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.
>