-/* $OpenBSD: if.c,v 1.561 2018/09/09 10:09:06 henning Exp $ */
+/* $OpenBSD: if.c,v 1.562 2018/09/10 16:07:20 henning Exp $ */
/* $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $ */
/*
void if_attachsetup(struct ifnet *);
void if_attachdomain(struct ifnet *);
void if_attach_common(struct ifnet *);
+int if_createrdomain(int, struct ifnet *);
int if_setrdomain(struct ifnet *, int);
void if_slowtimo(void *);
return (0);
}
+int
+if_createrdomain(int rdomain, struct ifnet *ifp)
+{
+ int error;
+ struct ifnet *loifp;
+ char loifname[IFNAMSIZ];
+ unsigned int unit = rdomain;
+
+ if (!rtable_exists(rdomain) && (error = rtable_add(rdomain)) != 0)
+ return (error);
+ if (!rtable_empty(rdomain))
+ return (EEXIST);
+
+ /* Create rdomain including its loopback if with unit == rdomain */
+ snprintf(loifname, sizeof(loifname), "lo%u", unit);
+ error = if_clone_create(loifname, 0);
+ if ((loifp = ifunit(loifname)) == NULL)
+ return (ENXIO);
+ if (error && (ifp != loifp || error != EEXIST))
+ return (error);
+
+ rtable_l2set(rdomain, rdomain, loifp->if_index);
+ loifp->if_rdomain = rdomain;
+
+ return (0);
+}
+
int
if_setrdomain(struct ifnet *ifp, int rdomain)
{
struct ifreq ifr;
- int error, createerr, up = 0, s;
+ int error, up = 0, s;
if (rdomain < 0 || rdomain > RT_TABLEID_MAX)
return (EINVAL);
(ifp->if_index == rtable_loindex(ifp->if_rdomain)))
return (EPERM);
- /*
- * Create the routing table if it does not exist, including its
- * loopback interface with unit == rdomain.
- */
- if (!rtable_exists(rdomain) || rtable_empty(rdomain)) {
- struct ifnet *loifp;
- char loifname[IFNAMSIZ];
- unsigned int unit = rdomain;
-
- snprintf(loifname, sizeof(loifname), "lo%u", unit);
- createerr = if_clone_create(loifname, 0);
- if (createerr && createerr != EEXIST)
- return (createerr);
-
- if ((loifp = ifunit(loifname)) == NULL)
- return (ENXIO);
-
- if (!rtable_exists(rdomain)) {
- error = rtable_add(rdomain);
- if (error) {
- if (createerr != EEXIST)
- if_clone_destroy(loifname);
- return (error);
- }
- }
-
- rtable_l2set(rdomain, rdomain, loifp->if_index);
- loifp->if_rdomain = rdomain;
- }
+ if (!rtable_exists(rdomain))
+ return (ESRCH);
/* make sure that the routing table is a real rdomain */
if (rdomain != rtable_l2(rdomain))
if ((error = suser(p)) != 0)
break;
NET_LOCK();
- error = if_setrdomain(ifp, ifr->ifr_rdomainid);
+ error = if_createrdomain(ifr->ifr_rdomainid, ifp);
+ if (!error || error == EEXIST)
+ error = if_setrdomain(ifp, ifr->ifr_rdomainid);
NET_UNLOCK();
break;