Here is a diff to allow deletion of lo(4) created by rdomain.

Of course, lo(4) cannot be deleted while the rdomain is used on another
interface. rtable is still available after all the interfaces are out of the
rdomain though.

[denis@visigoth:~] doas ifconfig em0 rdomain 3
[denis@visigoth:~] ifconfig 
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 32768
        index 4 priority 0 llprio 3
        groups: lo
        inet6 ::1 prefixlen 128
        inet6 fe80::1%lo0 prefixlen 64 scopeid 0x4
        inet 127.0.0.1 netmask 0xff000000
em0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> rdomain 3 mtu 1500
        lladdr 8c:16:45:57:e4:91
        index 2 priority 0 llprio 3
        media: Ethernet autoselect (none)
        status: no carrier
lo3: flags=8008<LOOPBACK,MULTICAST> rdomain 3 mtu 32768
        index 7 priority 0 llprio 3
        groups: lo
[denis@visigoth:~] doas ifconfig lo3 -rdomain
ifconfig: SIOCSIFRDOMAIN: Operation not permitted
[denis@visigoth:~] doas ifconfig em0 -rdomain
[denis@visigoth:~] doas ifconfig lo3 -rdomain
[denis@visigoth:~] ifconfig 
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 32768
        index 4 priority 0 llprio 3
        groups: lo
        inet6 ::1 prefixlen 128
        inet6 fe80::1%lo0 prefixlen 64 scopeid 0x4
        inet 127.0.0.1 netmask 0xff000000
em0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
        lladdr 8c:16:45:57:e4:91
        index 2 priority 0 llprio 3
        media: Ethernet autoselect (none)
        status: no carrier
lo3: flags=8008<LOOPBACK,MULTICAST> mtu 32768
        index 7 priority 0 llprio 3
        groups: lo
[denis@visigoth:~] doas ifconfig lo3 destroy
[denis@visigoth:~] ifconfig
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 32768
        index 4 priority 0 llprio 3
        groups: lo
        inet6 ::1 prefixlen 128
        inet6 fe80::1%lo0 prefixlen 64 scopeid 0x4
        inet 127.0.0.1 netmask 0xff000000
em0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
        lladdr 8c:16:45:57:e4:91
        index 2 priority 0 llprio 3
        media: Ethernet autoselect (none)
        status: no carrier

Because the kernel panics when manipulating rdomain on enc(4), I added a check
to disallow that (the kernel panic is not linked to this change, it
preexisted).


Index: if.c
===================================================================
RCS file: /cvs/src/sys/net/if.c,v
retrieving revision 1.556
diff -u -p -r1.556 if.c
--- if.c        21 Jun 2018 07:40:43 -0000      1.556
+++ if.c        23 Jun 2018 19:41:05 -0000
@@ -1729,43 +1729,53 @@ if_setlladdr(struct ifnet *ifp, const ui
        return (0);
 }
 
+struct ifnet *
+rdomain_isused(struct ifnet *ifp, int rdomain)
+{
+       struct ifnet *ifp_;
+
+       TAILQ_FOREACH(ifp_, &ifnet, if_list) {
+               if (ifp_ == ifp)
+                       continue;
+               if (ifp_->if_rdomain == rdomain)
+                       return (ifp_);
+       }
+       return (NULL);
+}
+
 int
 if_setrdomain(struct ifnet *ifp, int rdomain)
 {
        struct ifreq ifr;
        int error, up = 0, s;
+       struct ifnet *loifp;
+       char loifname[IFNAMSIZ];
+       unsigned int unit = rdomain;
 
        if (rdomain < 0 || rdomain > RT_TABLEID_MAX)
                return (EINVAL);
 
+       if (strncmp(ifp->if_xname, "enc", 3) == 0)
+               return (EPERM);
+
        /*
         * Create the routing table if it does not exist, including its
         * loopback interface with unit == rdomain.
         */
-       if (!rtable_exists(rdomain)) {
-               struct ifnet *loifp;
-               char loifname[IFNAMSIZ];
-               unsigned int unit = rdomain;
-
-               snprintf(loifname, sizeof(loifname), "lo%u", unit);
-               error = if_clone_create(loifname, 0);
-
-               if ((loifp = ifunit(loifname)) == NULL)
-                       return (ENXIO);
-
-               /* Do not error out if creating the default lo(4) interface */
-               if (error && (ifp != loifp || error != EEXIST))
+       if (!rtable_exists(rdomain))
+               if ((error = rtable_add(rdomain)))
                        return (error);
 
-               if ((error = rtable_add(rdomain)) == 0)
-                       rtable_l2set(rdomain, rdomain, loifp->if_index);
-               if (error) {
-                       if_clone_destroy(loifname);
-                       return (error);
-               }
+       snprintf(loifname, sizeof(loifname), "lo%u", unit);
+       error = if_clone_create(loifname, 0);
+       if (error && error != EEXIST)
+               return (error);
 
-               loifp->if_rdomain = rdomain;
-       }
+       if ((loifp = ifunit(loifname)) == NULL)
+               return (ENXIO);
+
+       rtable_l2set(rdomain, rdomain, loifp->if_index);
+       loifp->if_rdomain = rdomain;
 
        /* make sure that the routing table is a real rdomain */
        if (rdomain != rtable_l2(rdomain))
@@ -1773,7 +1783,8 @@ if_setrdomain(struct ifnet *ifp, int rdo
 
        if (rdomain != ifp->if_rdomain) {
                if ((ifp->if_flags & IFF_LOOPBACK) &&
-                   (ifp->if_index == rtable_loindex(ifp->if_rdomain)))
+                   (ifp->if_index == rtable_loindex(ifp->if_rdomain)) &&
+                   (rdomain_isused(ifp, ifp->if_rdomain)))
                        return (EPERM);
 
                s = splnet();

Reply via email to