This field is really only used by enc(4) in order to have an ifa to
attach the encap routes to.  Diff below adds an "struct ifaddr" to
this driver and kill if_lladdr.

There's one place where if_lladdr was temporarily used, in 
ifa_ifwithroute().  But the destination of a route is cannot be
of type AF_LINK, so we would find another ifa right after.

I've checked that changing the lladdr of an interface works fine, that I
can still use "route -ifp" and tested IPSEC.

Ok?


Index: net/if.c
===================================================================
RCS file: /home/ncvs/src/sys/net/if.c,v
retrieving revision 1.304
diff -u -p -r1.304 if.c
--- net/if.c    23 Nov 2014 07:39:02 -0000      1.304
+++ net/if.c    24 Nov 2014 14:12:30 -0000
@@ -285,10 +285,9 @@ if_attachsetup(struct ifnet *ifp)
 void
 if_alloc_sadl(struct ifnet *ifp)
 {
-       unsigned int socksize, ifasize;
+       unsigned int socksize;
        int namelen, masklen;
        struct sockaddr_dl *sdl;
-       struct ifaddr *ifa;
 
        /*
         * If the interface already has a link name, release it
@@ -305,9 +304,7 @@ if_alloc_sadl(struct ifnet *ifp)
        if (socksize < sizeof(*sdl))
                socksize = sizeof(*sdl);
        socksize = ROUNDUP(socksize);
-       ifasize = sizeof(*ifa) + socksize;
-       ifa = malloc(ifasize, M_IFADDR, M_WAITOK|M_ZERO);
-       sdl = (struct sockaddr_dl *)(ifa + 1);
+       sdl = malloc(socksize, M_IFADDR, M_WAITOK|M_ZERO);
        sdl->sdl_len = socksize;
        sdl->sdl_family = AF_LINK;
        bcopy(ifp->if_xname, sdl->sdl_data, namelen);
@@ -315,12 +312,7 @@ if_alloc_sadl(struct ifnet *ifp)
        sdl->sdl_alen = ifp->if_addrlen;
        sdl->sdl_index = ifp->if_index;
        sdl->sdl_type = ifp->if_type;
-       ifp->if_lladdr = ifa;
-       ifa->ifa_ifp = ifp;
-       ifa->ifa_rtrequest = link_rtrequest;
-       ifa->ifa_addr = (struct sockaddr *)sdl;
        ifp->if_sadl = sdl;
-       ifa->ifa_netmask = NULL;
 }
 
 /*
@@ -331,19 +323,8 @@ if_alloc_sadl(struct ifnet *ifp)
 void
 if_free_sadl(struct ifnet *ifp)
 {
-       struct ifaddr *ifa;
-       int s;
-
-       ifa = ifp->if_lladdr;
-       if (ifa == NULL)
-               return;
-
-       s = splnet();
-       rt_ifa_del(ifa, 0, ifa->ifa_addr);
-       ifafree(ifp->if_lladdr);
-       ifp->if_lladdr = NULL;
+       free(ifp->if_sadl, M_IFADDR, 0);
        ifp->if_sadl = NULL;
-       splx(s);
 }
 
 void
@@ -1220,7 +1201,6 @@ ifioctl(struct socket *so, u_long cmd, c
 {
        struct ifnet *ifp;
        struct ifreq *ifr;
-       struct ifaddr *ifa;
        struct sockaddr_dl *sdl;
        struct ifgroupreq *ifgr;
        char ifdescrbuf[IFDESCRSIZE];
@@ -1593,10 +1573,7 @@ ifioctl(struct socket *so, u_long cmd, c
        case SIOCSIFLLADDR:
                if ((error = suser(p, 0)))
                        return (error);
-               ifa = ifp->if_lladdr;
-               if (ifa == NULL)
-                       return (EINVAL);
-               sdl = (struct sockaddr_dl *)ifa->ifa_addr;
+               sdl = (struct sockaddr_dl *)ifp->if_sadl;
                if (sdl == NULL)
                        return (EINVAL);
                if (ifr->ifr_addr.sa_len != ETHER_ADDR_LEN)
Index: net/if_enc.c
===================================================================
RCS file: /home/ncvs/src/sys/net/if_enc.c,v
retrieving revision 1.56
diff -u -p -r1.56 if_enc.c
--- net/if_enc.c        8 Sep 2014 06:24:13 -0000       1.56
+++ net/if_enc.c        24 Nov 2014 14:12:30 -0000
@@ -98,10 +98,14 @@ enc_clone_create(struct if_clone *ifc, i
                if_addgroup(ifp, ifc->ifc_name);
        /*
         * enc(4) does not have a link-layer address but rtrequest1()
-        * wants an ifa for every route entry.  So let's allocate
-        * a fake and empty ifa of type AF_LINK for this purpose.
+        * wants an ifa for every route entry.  So let's setup a fake
+        * and empty ifa of type AF_LINK for this purpose.
         */
        if_alloc_sadl(ifp);
+       sc->sc_fakeifa.ifa_ifp = ifp;
+       sc->sc_fakeifa.ifa_rtrequest = link_rtrequest;
+       sc->sc_fakeifa.ifa_addr = (struct sockaddr *)ifp->if_sadl;
+       sc->sc_fakeifa.ifa_netmask = NULL;
 
 #if NBPFILTER > 0
        bpfattach(&ifp->if_bpf, ifp, DLT_ENC, ENC_HDRLEN);
@@ -225,6 +229,19 @@ enc_getif(u_int id, u_int unit)
        return (enc_ifps[id]);
 }
 
+struct ifaddr
+*enc_getifa(u_int id, u_int unit)
+{
+       struct ifnet            *ifp;
+       struct enc_softc        *sc;
+
+       ifp = enc_getif(id, unit);
+       if (ifp == NULL)
+               return (NULL);
+
+       sc = ifp->if_softc;
+       return (&sc->sc_fakeifa);
+}
 int
 enc_setif(struct ifnet *ifp, u_int id)
 {
Index: net/if_enc.h
===================================================================
RCS file: /home/ncvs/src/sys/net/if_enc.h,v
retrieving revision 1.11
diff -u -p -r1.11 if_enc.h
--- net/if_enc.h        25 Jun 2013 09:16:34 -0000      1.11
+++ net/if_enc.h        24 Nov 2014 14:12:30 -0000
@@ -32,9 +32,11 @@ struct enchdr {
 struct enc_softc {
        struct ifnet             sc_if;         /* virtual interface */
        u_int                    sc_unit;
+       struct ifaddr            sc_fakeifa;    /* needed to attach rtentry */
 };
 
 struct ifnet   *enc_getif(u_int, u_int);
+struct ifaddr  *enc_getifa(u_int, u_int);
 #endif /* _KERNEL */
 
 #endif /* _NET_ENC_H */
Index: net/if_ethersubr.c
===================================================================
RCS file: /home/ncvs/src/sys/net/if_ethersubr.c,v
retrieving revision 1.179
diff -u -p -r1.179 if_ethersubr.c
--- net/if_ethersubr.c  20 Nov 2014 14:51:42 -0000      1.179
+++ net/if_ethersubr.c  24 Nov 2014 14:12:30 -0000
@@ -807,11 +807,6 @@ ether_ifdetach(struct ifnet *ifp)
                LIST_REMOVE(enm, enm_list);
                free(enm, M_IFMADDR, 0);
        }
-
-#if 0
-       /* moved to if_detach() */
-       if_free_sadl(ifp);
-#endif
 }
 
 #if 0
Index: net/if_var.h
===================================================================
RCS file: /home/ncvs/src/sys/net/if_var.h,v
retrieving revision 1.12
diff -u -p -r1.12 if_var.h
--- net/if_var.h        8 Jul 2014 04:02:14 -0000       1.12
+++ net/if_var.h        24 Nov 2014 14:12:30 -0000
@@ -165,7 +165,6 @@ struct ifnet {                              /* and the 
entries */
                                        /* timer routine */
        void    (*if_watchdog)(struct ifnet *);
        int     (*if_wol)(struct ifnet *, int);
-       struct  ifaddr *if_lladdr;      /* pointer to link-level address */
        struct  ifqueue if_snd;         /* output queue */
        struct sockaddr_dl *if_sadl;    /* pointer to our sockaddr_dl */
 
Index: net/route.c
===================================================================
RCS file: /home/ncvs/src/sys/net/route.c,v
retrieving revision 1.191
diff -u -p -r1.191 route.c
--- net/route.c 24 Nov 2014 12:43:54 -0000      1.191
+++ net/route.c 24 Nov 2014 14:12:30 -0000
@@ -127,8 +127,6 @@
 #ifdef IPSEC
 #include <netinet/ip_ipsp.h>
 #include <net/if_enc.h>
-
-struct ifaddr  *encap_findgwifa(struct sockaddr *, u_int);
 #endif
 
 struct rtstat             rtstat;
@@ -163,26 +161,6 @@ struct rt_label {
 
 TAILQ_HEAD(rt_labels, rt_label)        rt_labels = 
TAILQ_HEAD_INITIALIZER(rt_labels);
 
-#ifdef IPSEC
-struct ifaddr *
-encap_findgwifa(struct sockaddr *gw, u_int rdomain)
-{
-       struct ifnet    *encif;
-
-       if ((encif = enc_getif(rdomain, 0)) == NULL)
-               return (NULL);
-
-       /*
-        * This is not a real link-layer address, it is an empty ifa of
-        * type AF_LINK.
-        * It is used when adding an encap route entry because RTM_ADD
-        * and rt_getifa() want an ifa to find an ifp to associate it to
-        * the route.
-        */
-       return (encif->if_lladdr);
-}
-#endif
-
 int
 rtable_init(struct radix_node_head ***table, u_int id)
 {
@@ -604,17 +582,6 @@ ifa_ifwithroute(int flags, struct sockad
 {
        struct ifaddr   *ifa;
 
-#ifdef IPSEC
-       /*
-        * If the destination is a PF_KEY address, we'll look
-        * for the existence of a encap interface number or address
-        * in the options list of the gateway. By default, we'll return
-        * enc0.
-        */
-       if (dst && (dst->sa_family == PF_KEY))
-               return (encap_findgwifa(gateway, rtableid));
-#endif
-
        if ((flags & RTF_GATEWAY) == 0) {
                /*
                 * If we are adding a route to an interface,
@@ -644,7 +611,7 @@ ifa_ifwithroute(int flags, struct sockad
                        if (ifp == NULL)
                                ifp = ifunit(sdl->sdl_data);
                        if (ifp != NULL)
-                               ifa = ifp->if_lladdr;
+                               ifa = ifaof_ifpforaddr(dst, ifp);
                } else {
                        ifa = ifa_ifwithnet(gateway, rtableid);
                }
@@ -691,6 +658,18 @@ rt_getifa(struct rt_addrinfo *info, u_in
                if (ifp == NULL)
                        ifp = ifunit(sdl->sdl_data);
        }
+
+#ifdef IPSEC
+       /*
+        * If the destination is a PF_KEY address, we'll look
+        * for the existence of a encap interface number or address
+        * in the options list of the gateway. By default, we'll return
+        * enc0.
+        */
+       if (info->rti_info[RTAX_DST] &&
+           info->rti_info[RTAX_DST]->sa_family == PF_KEY)
+               info->rti_ifa = enc_getifa(rtid, 0);
+#endif
 
        if (info->rti_ifa == NULL && info->rti_info[RTAX_IFA] != NULL)
                info->rti_ifa = ifa_ifwithaddr(info->rti_info[RTAX_IFA], rtid);

Reply via email to