Re: p2p interfaces and route to loopback
On 28/04/14(Mon) 22:57, Martin Pieuchot wrote: On 28/04/14(Mon) 21:51, Stuart Henderson wrote: On 2014/04/28 19:09, Martin Pieuchot wrote: On 28/04/14(Mon) 17:53, Stuart Henderson wrote: On 2014/04/28 18:39, Martin Pieuchot wrote: On 28/04/14(Mon) 17:32, Stuart Henderson wrote: On 2014/04/28 17:15, Stuart Henderson wrote: This breaks my setup, # /sbin/route add -inet6 default -ifp pppoe1 fe80:: route: writing to routing socket: Network is unreachable add net default: gateway fe80::: Network is unreachable hmmm... actually it seems something that was committed broke this; any suggestions of likely candidates? Concerning routing inet6 that might be the rt_ifa_add_loop() committed on the 3rd of April, but you tested and ok'd it or the rtinit() - rt_ifa_add() conversion committed the 10th of April. Window narrowed to between these: OpenBSD 5.5-current (GENERIC.MP) #61: Tue Apr 8 17:28:01 MDT 2014 OpenBSD 5.5-current (GENERIC.MP) #63: Thu Apr 10 20:45:05 MDT 2014 Could it be in6.c 1.135? (I need to stop breaking my net for a bit to get some other things done..) I doubt it will be this one since it's just removing a wrapper, but I don't see anything else in this timeframe. This is the one that breaks it, I can't just pull this diff out though, other things are stacked on top. Thanks for finding it, I'll cook a fix then. Here's a diff that fixes it in a way that allows me to remove the lladdr from the global lists. So the story behind this crap is horrible. Basically when you do: # route -ifp pppoe1 route(8) encodes the interface name into sdl_data using link_addr(3). This function is used only once and takes a crazy string argument like: em0:00.18.91.13.ed.30, really? But in your case, it only copy pppoe1. Then to really obfuscate the things, ifa_ifwithnet() was comparing this name like if it was an address... So makes thing obvious and call ifunit() directly if we didn't find an ifp with sdl_index. Ok? Index: net/route.c === RCS file: /home/ncvs/src/sys/net/route.c,v retrieving revision 1.164 diff -u -p -r1.164 route.c --- net/route.c 25 Apr 2014 10:41:09 - 1.164 +++ net/route.c 29 Apr 2014 08:55:15 - @@ -658,6 +658,8 @@ ifa_ifwithroute(int flags, struct sockad struct sockaddr_dl *sdl = (struct sockaddr_dl *)gateway; struct ifnet *ifp = if_get(sdl-sdl_index); + if (ifp == NULL) + ifp = ifunit(sdl-sdl_data); if (ifp != NULL) ifa = ifp-if_lladdr; } else { @@ -702,6 +704,8 @@ rt_getifa(struct rt_addrinfo *info, u_in sdl = (struct sockaddr_dl *)info-rti_info[RTAX_IFP]; ifp = if_get(sdl-sdl_index); + if (ifp == NULL) + ifp = ifunit(sdl-sdl_data); } if (info-rti_ifa == NULL info-rti_info[RTAX_IFA] != NULL)
Re: p2p interfaces and route to loopback
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%pppoe0link#12HL 00 - 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%pppoe0link#12HL 00 - 4 lo0 -2011:4b10:1003:ff::1 link#12HL 00 - 4 lo0 +fe80::300:245f:fedc:22f8%pppoe0::1H 00 - 4 lo0 +2011:4b10:1003:ff::1 ::1H 00 - 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 - 1.282 +++ net/if.c 9 Apr 2014 13:31:06 - @@ -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 - 1.64 +++ net/if_gif.c 9 Apr 2014 13:31:06 - @@ -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,
Re: p2p interfaces and route to loopback
This breaks my setup, # /sbin/route add -inet6 default -ifp pppoe1 fe80:: route: writing to routing socket: Network is unreachable add net default: gateway fe80::: Network is unreachable
Re: p2p interfaces and route to loopback
On 2014/04/28 17:15, Stuart Henderson wrote: This breaks my setup, # /sbin/route add -inet6 default -ifp pppoe1 fe80:: route: writing to routing socket: Network is unreachable add net default: gateway fe80::: Network is unreachable hmmm... actually it seems something that was committed broke this; any suggestions of likely candidates?
Re: p2p interfaces and route to loopback
On 28/04/14(Mon) 17:32, Stuart Henderson wrote: On 2014/04/28 17:15, Stuart Henderson wrote: This breaks my setup, # /sbin/route add -inet6 default -ifp pppoe1 fe80:: route: writing to routing socket: Network is unreachable add net default: gateway fe80::: Network is unreachable hmmm... actually it seems something that was committed broke this; any suggestions of likely candidates? Concerning routing inet6 that might be the rt_ifa_add_loop() committed on the 3rd of April, but you tested and ok'd it or the rtinit() - rt_ifa_add() conversion committed the 10th of April.
Re: p2p interfaces and route to loopback
On 2014/04/28 18:39, Martin Pieuchot wrote: On 28/04/14(Mon) 17:32, Stuart Henderson wrote: On 2014/04/28 17:15, Stuart Henderson wrote: This breaks my setup, # /sbin/route add -inet6 default -ifp pppoe1 fe80:: route: writing to routing socket: Network is unreachable add net default: gateway fe80::: Network is unreachable hmmm... actually it seems something that was committed broke this; any suggestions of likely candidates? Concerning routing inet6 that might be the rt_ifa_add_loop() committed on the 3rd of April, but you tested and ok'd it or the rtinit() - rt_ifa_add() conversion committed the 10th of April. Window narrowed to between these: OpenBSD 5.5-current (GENERIC.MP) #61: Tue Apr 8 17:28:01 MDT 2014 OpenBSD 5.5-current (GENERIC.MP) #63: Thu Apr 10 20:45:05 MDT 2014 Could it be in6.c 1.135? (I need to stop breaking my net for a bit to get some other things done..)
Re: p2p interfaces and route to loopback
On 28/04/14(Mon) 17:53, Stuart Henderson wrote: On 2014/04/28 18:39, Martin Pieuchot wrote: On 28/04/14(Mon) 17:32, Stuart Henderson wrote: On 2014/04/28 17:15, Stuart Henderson wrote: This breaks my setup, # /sbin/route add -inet6 default -ifp pppoe1 fe80:: route: writing to routing socket: Network is unreachable add net default: gateway fe80::: Network is unreachable hmmm... actually it seems something that was committed broke this; any suggestions of likely candidates? Concerning routing inet6 that might be the rt_ifa_add_loop() committed on the 3rd of April, but you tested and ok'd it or the rtinit() - rt_ifa_add() conversion committed the 10th of April. Window narrowed to between these: OpenBSD 5.5-current (GENERIC.MP) #61: Tue Apr 8 17:28:01 MDT 2014 OpenBSD 5.5-current (GENERIC.MP) #63: Thu Apr 10 20:45:05 MDT 2014 Could it be in6.c 1.135? (I need to stop breaking my net for a bit to get some other things done..) I doubt it will be this one since it's just removing a wrapper, but I don't see anything else in this timeframe.
Re: p2p interfaces and route to loopback
On 2014/04/28 19:09, Martin Pieuchot wrote: On 28/04/14(Mon) 17:53, Stuart Henderson wrote: On 2014/04/28 18:39, Martin Pieuchot wrote: On 28/04/14(Mon) 17:32, Stuart Henderson wrote: On 2014/04/28 17:15, Stuart Henderson wrote: This breaks my setup, # /sbin/route add -inet6 default -ifp pppoe1 fe80:: route: writing to routing socket: Network is unreachable add net default: gateway fe80::: Network is unreachable hmmm... actually it seems something that was committed broke this; any suggestions of likely candidates? Concerning routing inet6 that might be the rt_ifa_add_loop() committed on the 3rd of April, but you tested and ok'd it or the rtinit() - rt_ifa_add() conversion committed the 10th of April. Window narrowed to between these: OpenBSD 5.5-current (GENERIC.MP) #61: Tue Apr 8 17:28:01 MDT 2014 OpenBSD 5.5-current (GENERIC.MP) #63: Thu Apr 10 20:45:05 MDT 2014 Could it be in6.c 1.135? (I need to stop breaking my net for a bit to get some other things done..) I doubt it will be this one since it's just removing a wrapper, but I don't see anything else in this timeframe. This is the one that breaks it, I can't just pull this diff out though, other things are stacked on top. - PatchSet 3605 Date: 2014/04/10 14:55:55 Author: mpi Branch: HEAD Tag: (none) Log: Don't use ifa_ifwithnet() with obvious sockaddr_dl argument. This function should not deal with link-layer addresses and here there's no reason to do it. ok mikeb@ Members: route.c:1.159-1.160 Index: src/sys/net/route.c diff -u src/sys/net/route.c:1.159 src/sys/net/route.c:1.160 --- src/sys/net/route.c:1.159 Thu Apr 10 13:47:21 2014 +++ src/sys/net/route.c Thu Apr 10 13:55:55 2014 @@ -1,4 +1,4 @@ -/* $OpenBSD: route.c,v 1.159 2014/04/10 13:47:21 mpi Exp $ */ +/* $OpenBSD: route.c,v 1.160 2014/04/10 13:55:55 mpi Exp $ */ /* $NetBSD: route.c,v 1.14 1996/02/13 22:00:46 christos Exp $ */ /* @@ -683,11 +683,12 @@ * ifp may be specified by sockaddr_dl when protocol address * is ambiguous */ - if (info-rti_ifp == NULL info-rti_info[RTAX_IFP] != NULL -info-rti_info[RTAX_IFP]-sa_family == AF_LINK - (ifa = ifa_ifwithnet((struct sockaddr *)info-rti_info[RTAX_IFP], - rtid)) != NULL) - info-rti_ifp = ifa-ifa_ifp; + if (info-rti_ifp == NULL info-rti_info[RTAX_IFP] != NULL) { + struct sockaddr_dl *sdl; + + sdl = (struct sockaddr_dl *)info-rti_info[RTAX_IFP]; + info-rti_ifp = if_get(sdl-sdl_index); + } if (info-rti_ifa == NULL info-rti_info[RTAX_IFA] != NULL) info-rti_ifa = ifa_ifwithaddr(info-rti_info[RTAX_IFA], rtid);
Re: p2p interfaces and route to loopback
On 28/04/14(Mon) 21:51, Stuart Henderson wrote: On 2014/04/28 19:09, Martin Pieuchot wrote: On 28/04/14(Mon) 17:53, Stuart Henderson wrote: On 2014/04/28 18:39, Martin Pieuchot wrote: On 28/04/14(Mon) 17:32, Stuart Henderson wrote: On 2014/04/28 17:15, Stuart Henderson wrote: This breaks my setup, # /sbin/route add -inet6 default -ifp pppoe1 fe80:: route: writing to routing socket: Network is unreachable add net default: gateway fe80::: Network is unreachable hmmm... actually it seems something that was committed broke this; any suggestions of likely candidates? Concerning routing inet6 that might be the rt_ifa_add_loop() committed on the 3rd of April, but you tested and ok'd it or the rtinit() - rt_ifa_add() conversion committed the 10th of April. Window narrowed to between these: OpenBSD 5.5-current (GENERIC.MP) #61: Tue Apr 8 17:28:01 MDT 2014 OpenBSD 5.5-current (GENERIC.MP) #63: Thu Apr 10 20:45:05 MDT 2014 Could it be in6.c 1.135? (I need to stop breaking my net for a bit to get some other things done..) I doubt it will be this one since it's just removing a wrapper, but I don't see anything else in this timeframe. This is the one that breaks it, I can't just pull this diff out though, other things are stacked on top. Thanks for finding it, I'll cook a fix then. - PatchSet 3605 Date: 2014/04/10 14:55:55 Author: mpi Branch: HEAD Tag: (none) Log: Don't use ifa_ifwithnet() with obvious sockaddr_dl argument. This function should not deal with link-layer addresses and here there's no reason to do it. ok mikeb@ Members: route.c:1.159-1.160 Index: src/sys/net/route.c diff -u src/sys/net/route.c:1.159 src/sys/net/route.c:1.160 --- src/sys/net/route.c:1.159 Thu Apr 10 13:47:21 2014 +++ src/sys/net/route.c Thu Apr 10 13:55:55 2014 @@ -1,4 +1,4 @@ -/* $OpenBSD: route.c,v 1.159 2014/04/10 13:47:21 mpi Exp $ */ +/* $OpenBSD: route.c,v 1.160 2014/04/10 13:55:55 mpi Exp $ */ /* $NetBSD: route.c,v 1.14 1996/02/13 22:00:46 christos Exp $ */ /* @@ -683,11 +683,12 @@ * ifp may be specified by sockaddr_dl when protocol address * is ambiguous */ - if (info-rti_ifp == NULL info-rti_info[RTAX_IFP] != NULL - info-rti_info[RTAX_IFP]-sa_family == AF_LINK - (ifa = ifa_ifwithnet((struct sockaddr *)info-rti_info[RTAX_IFP], - rtid)) != NULL) - info-rti_ifp = ifa-ifa_ifp; + if (info-rti_ifp == NULL info-rti_info[RTAX_IFP] != NULL) { + struct sockaddr_dl *sdl; + + sdl = (struct sockaddr_dl *)info-rti_info[RTAX_IFP]; + info-rti_ifp = if_get(sdl-sdl_index); + } if (info-rti_ifa == NULL info-rti_info[RTAX_IFA] != NULL) info-rti_ifa = ifa_ifwithaddr(info-rti_info[RTAX_IFA], rtid);
Re: p2p interfaces and route to loopback
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%pppoe0link#12HL 00 - 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%pppoe0link#12HL 00 - 4 lo0 -2011:4b10:1003:ff::1 link#12HL 00 - 4 lo0 +fe80::300:245f:fedc:22f8%pppoe0::1H 00 - 4 lo0 +2011:4b10:1003:ff::1 ::1H 00 - 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(). Anyone? 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 - 1.282 +++ net/if.c 9 Apr 2014 13:31:06 - @@ -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 - 1.64 +++ net/if_gif.c 9 Apr 2014 13:31:06 - @@ -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: