On 09/04/14(Wed) 15:36, Martin Pieuchot wrote:
> On 09/04/14(Wed) 11:22, Martin Pieuchot wrote:
> > When an IPv6 address is configured on a point-to-point interface, it
> > is associated to nd6_rtrequest().  This is because nd6_request()
> > contains a hack to automatically create a route to loopback for p2p
> > interfaces.
> > 
> > The resulting route looks like this:
> > 
> > fe80::300:245f:fedc:22f8%pppoe0    link#12                        HL        
> >  0        0     -     4 lo0  
> > 
> > 
> > I'd like to stop abusing nd6_rtrequest() for point-to-point interfaces
> > because I want to introduce a similar behavior for IPv4.  So the diff
> > below adds a sppp_rtrequest() function that works for both IPv4 and
> > IPv6 and creates a local route if the loopback interface has an address
> > of the same family.  This diff introduce a difference in the routing
> > table, see below, but it shouldn't matter.  The RTF_LLINFO flags is
> > necessary for ND6 or ARP, not for p2p interfaces.
> > 
> > 
> > -fe80::300:245f:fedc:22f8%pppoe0    link#12                        HL       
> >   0        0     -     4 lo0  
> > -2011:4b10:1003:ff::1               link#12                        HL       
> >   0        0     -     4 lo0  
> > +fe80::300:245f:fedc:22f8%pppoe0    ::1                            H        
> >   0        0     -     4 lo0  
> > +2011:4b10:1003:ff::1               ::1                            H        
> >   0        0     -     4 lo0  
> 
> Here's an updated diff that addresses some points raised by claudio@:
>   - Support all the p2p interfaces but mpe(4) (should I include it?)
>   - Add comment about lo0 vs rdomain in {p2p,arp,nd6}_rtrequest().

Whoo!  So this diff removes a hack, document another one, will let
me share some code between IPv6 and IPv4 and I didn't hear anybody
complaining about a regression.

Can I have Oks?

> 
> Index: net/if.c
> ===================================================================
> RCS file: /home/ncvs/src/sys/net/if.c,v
> retrieving revision 1.282
> diff -u -p -r1.282 if.c
> --- net/if.c  20 Mar 2014 13:19:06 -0000      1.282
> +++ net/if.c  9 Apr 2014 13:31:06 -0000
> @@ -1009,6 +1009,71 @@ link_rtrequest(int cmd, struct rtentry *
>  }
>  
>  /*
> + * Default action when installing a local route on a point-to-point
> + * interface.
> + */
> +void
> +p2p_rtrequest(int req, struct rtentry *rt)
> +{
> +     struct ifnet *ifp = rt->rt_ifp;
> +     struct ifaddr *ifa, *lo0ifa;
> +
> +     switch (req) {
> +     case RTM_ADD:
> +             /*
> +              * XXX Here we abuse RTF_LLINFO to add a route to
> +              * loopback.  We do that to always have a route
> +              * pointing to our address.
> +              */
> +             if ((rt->rt_flags & RTF_LLINFO) == 0)
> +                     break;
> +
> +             TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
> +                     if (memcmp(rt_key(rt), ifa->ifa_addr,
> +                         rt_key(rt)->sa_len) == 0)
> +                             break;
> +             }
> +
> +             if (ifa == NULL)
> +                     break;
> +
> +             /*
> +              * XXX Since lo0 is in the default rdomain we should not
> +              * (ab)use it for any route related to an interface of a
> +              * different rdomain.
> +              */
> +             TAILQ_FOREACH(lo0ifa, &lo0ifp->if_addrlist, ifa_list)
> +                     if (lo0ifa->ifa_addr->sa_family ==
> +                         ifa->ifa_addr->sa_family)
> +                             break;
> +
> +             if (lo0ifa == NULL)
> +                     break;
> +
> +             rt_setgate(rt, rt_key(rt), lo0ifa->ifa_addr, ifp->if_rdomain);
> +             rt->rt_ifp = lo0ifp;
> +             rt->rt_flags &= ~RTF_LLINFO;
> +
> +             /*
> +              * make sure to set rt->rt_ifa to the interface
> +              * address we are using, otherwise we will have trouble
> +              * with source address selection.
> +              */
> +             if (ifa != rt->rt_ifa) {
> +                     ifafree(rt->rt_ifa);
> +                     ifa->ifa_refcnt++;
> +                     rt->rt_ifa = ifa;
> +             }
> +             break;
> +     case RTM_DELETE:
> +     case RTM_RESOLVE:
> +     default:
> +             break;
> +     }
> +}
> +
> +
> +/*
>   * Bring down all interfaces
>   */
>  void
> Index: net/if_gif.c
> ===================================================================
> RCS file: /home/ncvs/src/sys/net/if_gif.c,v
> retrieving revision 1.64
> diff -u -p -r1.64 if_gif.c
> --- net/if_gif.c      19 Oct 2013 14:46:30 -0000      1.64
> +++ net/if_gif.c      9 Apr 2014 13:31:06 -0000
> @@ -356,7 +356,8 @@ int
>  gif_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
>  {
>       struct gif_softc *sc  = (struct gif_softc*)ifp;
> -     struct ifreq     *ifr = (struct ifreq*)data;
> +     struct ifreq     *ifr = (struct ifreq *)data;
> +     struct ifaddr    *ifa = (struct ifaddr *)data;
>       int error = 0, size;
>       struct sockaddr *dst, *src;
>       struct sockaddr *sa;
> @@ -365,6 +366,7 @@ gif_ioctl(struct ifnet *ifp, u_long cmd,
>  
>       switch (cmd) {
>       case SIOCSIFADDR:
> +             ifa->ifa_rtrequest = p2p_rtrequest;
>               break;
>  
>       case SIOCSIFDSTADDR:
> Index: net/if_gre.c
> ===================================================================
> RCS file: /home/ncvs/src/sys/net/if_gre.c,v
> retrieving revision 1.64
> diff -u -p -r1.64 if_gre.c
> --- net/if_gre.c      19 Oct 2013 14:46:30 -0000      1.64
> +++ net/if_gre.c      9 Apr 2014 13:31:06 -0000
> @@ -441,7 +441,8 @@ int
>  gre_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
>  {
>  
> -     struct ifreq *ifr = (struct ifreq *) data;
> +     struct ifreq *ifr = (struct ifreq *)data;
> +     struct ifaddr *ifa = (struct ifaddr *)data;
>       struct if_laddrreq *lifr = (struct if_laddrreq *)data;
>       struct ifkalivereq *ikar = (struct ifkalivereq *)data;
>       struct gre_softc *sc = ifp->if_softc;
> @@ -455,6 +456,7 @@ gre_ioctl(struct ifnet *ifp, u_long cmd,
>       switch(cmd) {
>       case SIOCSIFADDR:
>               ifp->if_flags |= IFF_UP;
> +             ifa->ifa_rtrequest = p2p_rtrequest;
>               break;
>       case SIOCSIFDSTADDR:
>               break;
> Index: net/if_ppp.c
> ===================================================================
> RCS file: /home/ncvs/src/sys/net/if_ppp.c,v
> retrieving revision 1.71
> diff -u -p -r1.71 if_ppp.c
> --- net/if_ppp.c      23 Oct 2013 15:12:42 -0000      1.71
> +++ net/if_ppp.c      9 Apr 2014 13:31:06 -0000
> @@ -619,6 +619,7 @@ pppsioctl(struct ifnet *ifp, u_long cmd,
>      case SIOCSIFADDR:
>       if (ifa->ifa_addr->sa_family != AF_INET)
>           error = EAFNOSUPPORT;
> +     ifa->ifa_rtrequest = p2p_rtrequest;
>       break;
>  
>      case SIOCSIFDSTADDR:
> Index: net/if_pppx.c
> ===================================================================
> RCS file: /home/ncvs/src/sys/net/if_pppx.c,v
> retrieving revision 1.29
> diff -u -p -r1.29 if_pppx.c
> --- net/if_pppx.c     8 Apr 2014 04:26:53 -0000       1.29
> +++ net/if_pppx.c     9 Apr 2014 13:31:06 -0000
> @@ -1094,10 +1094,14 @@ pppx_if_ioctl(struct ifnet *ifp, u_long 
>  {
>       struct pppx_if *pxi = (struct pppx_if *)ifp->if_softc;
>       struct ifreq *ifr = (struct ifreq *)addr;
> +     struct ifaddr *ifa = (struct ifaddr *)addr;
>       int error = 0;
>  
>       switch (cmd) {
>       case SIOCSIFADDR:
> +             ifa->ifa_rtrequest = p2p_rtrequest;
> +             break;
> +
>       case SIOCSIFFLAGS:
>               break;
>  
> Index: net/if_spppsubr.c
> ===================================================================
> RCS file: /home/ncvs/src/sys/net/if_spppsubr.c,v
> retrieving revision 1.119
> diff -u -p -r1.119 if_spppsubr.c
> --- net/if_spppsubr.c 3 Apr 2014 06:06:56 -0000       1.119
> +++ net/if_spppsubr.c 9 Apr 2014 13:31:06 -0000
> @@ -1010,7 +1010,8 @@ sppp_pick(struct ifnet *ifp)
>  int
>  sppp_ioctl(struct ifnet *ifp, u_long cmd, void *data)
>  {
> -     struct ifreq *ifr = (struct ifreq*) data;
> +     struct ifreq *ifr = data;
> +     struct ifaddr *ifa = data;
>       struct sppp *sp = (struct sppp*) ifp;
>       int s, rv, going_up, going_down, newmode;
>  
> @@ -1023,6 +1024,7 @@ sppp_ioctl(struct ifnet *ifp, u_long cmd
>  
>       case SIOCSIFADDR:
>               if_up(ifp);
> +             ifa->ifa_rtrequest = p2p_rtrequest;
>               /* FALLTHROUGH */
>  
>       case SIOCSIFFLAGS:
> Index: net/if_tun.c
> ===================================================================
> RCS file: /home/ncvs/src/sys/net/if_tun.c,v
> retrieving revision 1.121
> diff -u -p -r1.121 if_tun.c
> --- net/if_tun.c      30 Mar 2014 21:54:48 -0000      1.121
> +++ net/if_tun.c      9 Apr 2014 13:31:06 -0000
> @@ -469,6 +469,7 @@ tun_ioctl(struct ifnet *ifp, u_long cmd,
>  {
>       struct tun_softc        *tp = (struct tun_softc *)(ifp->if_softc);
>       struct ifreq            *ifr = (struct ifreq *)data;
> +     struct ifaddr           *ifa = (struct ifaddr *)data;
>       int                      error = 0, s;
>  
>       s = splnet();
> @@ -477,16 +478,19 @@ tun_ioctl(struct ifnet *ifp, u_long cmd,
>       case SIOCSIFADDR:
>               tuninit(tp);
>               TUNDEBUG(("%s: address set\n", ifp->if_xname));
> -             if (tp->tun_flags & TUN_LAYER2)
> -                     switch (((struct ifaddr *)data)->ifa_addr->sa_family) {
> +             if (tp->tun_flags & TUN_LAYER2) {
> +                     switch (ifa->ifa_addr->sa_family) {
>  #ifdef INET
>                       case AF_INET:
> -                             arp_ifinit(&tp->arpcom, (struct ifaddr *)data);
> +                             arp_ifinit(&tp->arpcom, ifa);
>                               break;
>  #endif
>                       default:
>                               break;
>                       }
> +             } else {
> +                     ifa->ifa_rtrequest = p2p_rtrequest;
> +             }
>               break;
>       case SIOCSIFDSTADDR:
>               tuninit(tp);
> Index: net/if_var.h
> ===================================================================
> RCS file: /home/ncvs/src/sys/net/if_var.h,v
> retrieving revision 1.6
> diff -u -p -r1.6 if_var.h
> --- net/if_var.h      27 Mar 2014 10:39:23 -0000      1.6
> +++ net/if_var.h      9 Apr 2014 13:31:06 -0000
> @@ -501,6 +501,7 @@ struct    ifaddr *ifa_ifwithroute(int, stru
>  struct       ifaddr *ifaof_ifpforaddr(struct sockaddr *, struct ifnet *);
>  void ifafree(struct ifaddr *);
>  void link_rtrequest(int, struct rtentry *);
> +void p2p_rtrequest(int, struct rtentry *);
>  
>  void if_clone_attach(struct if_clone *);
>  void if_clone_detach(struct if_clone *);
> Index: netinet/if_ether.c
> ===================================================================
> RCS file: /home/ncvs/src/sys/netinet/if_ether.c,v
> retrieving revision 1.123
> diff -u -p -r1.123 if_ether.c
> --- netinet/if_ether.c        27 Mar 2014 10:39:23 -0000      1.123
> +++ netinet/if_ether.c        9 Apr 2014 13:31:06 -0000
> @@ -254,6 +254,12 @@ arp_rtrequest(int req, struct rtentry *r
>                       SDL(gate)->sdl_alen = ETHER_ADDR_LEN;
>                       memcpy(LLADDR(SDL(gate)),
>                           ((struct arpcom *)ifp)->ac_enaddr, ETHER_ADDR_LEN);
> +
> +                     /*
> +                      * XXX Since lo0 is in the default rdomain we
> +                      * should not (ab)use it for any route related
> +                      * to an interface of a different rdomain.
> +                      */
>                       if (useloopback)
>                               rt->rt_ifp = lo0ifp;
>                       /*
> Index: netinet6/in6.c
> ===================================================================
> RCS file: /home/ncvs/src/sys/netinet6/in6.c,v
> retrieving revision 1.134
> diff -u -p -r1.134 in6.c
> --- netinet6/in6.c    3 Apr 2014 08:22:10 -0000       1.134
> +++ netinet6/in6.c    9 Apr 2014 13:31:06 -0000
> @@ -1369,7 +1369,8 @@ in6_ifinit(struct ifnet *ifp, struct in6
>               ifacount++;
>       }
>  
> -     if ((ifacount <= 1 || ifp->if_type == IFT_CARP) && ifp->if_ioctl &&
> +     if ((ifacount <= 1 || ifp->if_type == IFT_CARP ||
> +         (ifp->if_flags & IFF_POINTOPOINT)) && ifp->if_ioctl &&
>           (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia6))) {
>               splx(s);
>               return (error);
> @@ -1396,7 +1397,9 @@ in6_ifinit(struct ifnet *ifp, struct in6
>       /* Add ownaddr as loopback rtentry, if necessary (ex. on p2p link). */
>       if (newhost) {
>               /* set the rtrequest function to create llinfo */
> -             ia6->ia_ifa.ifa_rtrequest = nd6_rtrequest;
> +             if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
> +                     ia6->ia_ifa.ifa_rtrequest = nd6_rtrequest;
> +
>               rt_ifa_addloop(&(ia6->ia_ifa));
>       }
>  
> Index: netinet6/nd6.c
> ===================================================================
> RCS file: /home/ncvs/src/sys/netinet6/nd6.c,v
> retrieving revision 1.113
> diff -u -p -r1.113 nd6.c
> --- netinet6/nd6.c    27 Mar 2014 10:39:23 -0000      1.113
> +++ netinet6/nd6.c    9 Apr 2014 13:31:06 -0000
> @@ -1157,8 +1157,14 @@ nd6_rtrequest(int req, struct rtentry *r
>                               memcpy(LLADDR(SDL(gate)), macp, 
> ifp->if_addrlen);
>                               SDL(gate)->sdl_alen = ifp->if_addrlen;
>                       }
> +
> +                     /*
> +                      * XXX Since lo0 is in the default rdomain we
> +                      * should not (ab)use it for any route related
> +                      * to an interface of a different rdomain.
> +                      */
>                       if (nd6_useloopback) {
> -                             rt->rt_ifp = lo0ifp;    /*XXX*/
> +                             rt->rt_ifp = lo0ifp;
>                               /*
>                                * Make sure rt_ifa be equal to the ifaddr
>                                * corresponding to the address.
> 

Reply via email to