ip6 source address selection and down interfaces

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

ip6 source address selection and down interfaces

Stuart Henderson
Someone trying to replace some latvian boxes with bgpd/npppd mentioned
a problem with v6 on carp interfaces in 'backup' state where their
address was used as source address, despite there being an address
on the carpdev which was up.

I don't have a proper v6 carp setup handy to test but got a test
machine into a state with 'ifconfig carp0 down' (which seems should be
a close enough equivalent to 'carp backup' for tests) which did
indeed consider the 'down' carp interface as a source address.

It can be bodged around with pltime 0 of course, but from looking at
in6_selectsrc() I don't see why it wouldn't just pick the address
from the interface associated with the route i.e. the one on em0..
but then I must be missing something as I don't see where pltime 0
is handled either... does anyone have clues?

# ifconfig em0
em0: flags=48b43<UP,BROADCAST,RUNNING,PROMISC,ALLMULTI,SIMPLEX,MULTICAST,INET6_NOPRIVACY> mtu 1500
        lladdr f0:de:f1:f9:a7:52
        priority: 0
        groups: egress
        media: Ethernet autoselect (1000baseT full-duplex)
        status: active
        inet6 fe80::f2de:f1ff:fef9:a752%em0 prefixlen 64 scopeid 0x1
        inet6 2001:8b0:648e:cc01:f2de:f1ff:fef9:a752 prefixlen 64 autoconf pltime 604697 vltime 2591897
        inet 85.158.44.149 netmask 0xfffffff0 broadcast 85.158.44.159
# ifconfig carp0
carp0: flags=8802<BROADCAST,SIMPLEX,MULTICAST> mtu 1500
        lladdr 00:00:5e:00:01:01
        priority: 0
        carp: INIT carpdev em0 vhid 1 advbase 1 advskew 0
        groups: carp
        status: invalid
        inet6 fe80::200:5eff:fe00:101%carp0 prefixlen 64 scopeid 0xa
        inet6 2001:8b0:648e:cc01:200:5eff:fe00:101 prefixlen 64 detached autoconf pltime 604690 vltime 2591890
        inet6 2001:8b0:648e:cc01:5c46:9730:9899:1008 prefixlen 64 detached autoconf autoconfprivacy pltime 81660 vltime 600216
        inet6 2001:8b0:648e:cc01::ca1f prefixlen 64
# $ route -n get -inet6 2001:8b0:648e:cc01:20d:b9ff:fe04:a330
   route to: 2001:8b0:648e:cc01:20d:b9ff:fe04:a330
destination: 2001:8b0:648e:cc01::
       mask: ffff:ffff:ffff:ffff::
  interface: em0
 if address: fe80::f2de:f1ff:fef9:a752%em0
   priority: 4 (connected)
      flags: <UP,DONE,CLONING>
     use       mtu    expire
       0         0         0
# ping6 jodrell
PING6(56=40+8+8 bytes) 2001:8b0:648e:cc01::ca1f --> 2001:8b0:648e:cc01:20d:b9ff:fe04:a330
^C
--- jodrell.spacehopper.org ping6 statistics ---
3 packets transmitted, 0 packets received, 100.0% packet loss


# netstat -rnfinet6|grep -e 2001:8b0:648e:cc01 -e carp0
2001:8b0:648e:cc01::/64            link#1                         UC         7        0     -     4 em0  
2001:8b0:648e:cc01::1              00:0d:b9:17:0c:c4              UHLc       0        5     -     4 em0  
2001:8b0:648e:cc01::ca1f           link#1                         UHLc       1        0     -     4 em0  
2001:8b0:648e:cc01:200:5eff:fe00:101 00:00:5e:00:01:01              UHL        0        0     -     4 lo0  
2001:8b0:648e:cc01:20d:93ff:fe63:da5a 00:0d:93:63:da:5a              UHLc       1        8     -     4 em0  
2001:8b0:648e:cc01:20d:b9ff:fe04:a330 00:0d:b9:17:0c:c4              UHLc       0        3     -     4 em0  
2001:8b0:648e:cc01:5c46:9730:9899:1008 00:00:5e:00:01:01              UHL        0        0     -     4 lo0  
2001:8b0:648e:cc01:f2de:f1ff:fef9:a752 f0:de:f1:f9:a7:52              UHLc       0        0     -     4 lo0  
fe80::%carp0/64                    link#10                        UC        12        0     -     4 carp0
fe80::200:5eff:fe00:101%carp0      00:00:5e:00:01:01              UHL        0        0     -     4 lo0  
fe80::20d:93ff:fe63:da5a%carp0     00:0d:93:63:da:5a              UHLc       0        2     -     4 carp0
fe80::20d:b9ff:fe17:cc4%carp0      00:0d:b9:17:0c:c4              UHLc       0        0     -     4 carp0
ff01::%carp0/32                    link#10                        UC         0        0     -     4 carp0
ff02::%carp0/32                    link#10                        UC         2        0     -     4 carp0
ff02::1:ff04:a330%carp0            link#10                        UHLc       0        0     -     4 carp0
ff02::1:ff63:da5a%carp0            link#10                        UHLc       0        0     -     4 carp0

Reply | Threaded
Open this post in threaded view
|

Re: ip6 source address selection and down interfaces

Todd T. Fries-2
The source address selection mechanism in IPv4 is to my understanding:

 the first address on the interface associated with the route
 to the remote host

The source address selection mechanism in IPv6 is to my understanding:

 for each of the global addresses on a system, turn it into an integer
 and subtract it from the destination address.  The difference closest
 to zero decides what address will be selected because it is 'closest'.

Personally I'd be happy if IPv6 mimicked IPv4 in this regard.  Other OS's
permit configurable address selection criteria in the kernel, but I'll be
the first to suggest this is not the OpenBSD way.  The default should be
good enough and .. this is not good enough for me in every scenario I've
encountered it.

Naddy may pipe up as well, he's quite familiar with this scenario.

Thanks,

Penned by Stuart Henderson on 20130219 19:11.10, we have:
| Someone trying to replace some latvian boxes with bgpd/npppd mentioned
| a problem with v6 on carp interfaces in 'backup' state where their
| address was used as source address, despite there being an address
| on the carpdev which was up.
|
| I don't have a proper v6 carp setup handy to test but got a test
| machine into a state with 'ifconfig carp0 down' (which seems should be
| a close enough equivalent to 'carp backup' for tests) which did
| indeed consider the 'down' carp interface as a source address.
|
| It can be bodged around with pltime 0 of course, but from looking at
| in6_selectsrc() I don't see why it wouldn't just pick the address
| from the interface associated with the route i.e. the one on em0..
| but then I must be missing something as I don't see where pltime 0
| is handled either... does anyone have clues?
|
| # ifconfig em0
| em0: flags=48b43<UP,BROADCAST,RUNNING,PROMISC,ALLMULTI,SIMPLEX,MULTICAST,INET6_NOPRIVACY> mtu 1500
| lladdr f0:de:f1:f9:a7:52
| priority: 0
| groups: egress
| media: Ethernet autoselect (1000baseT full-duplex)
| status: active
| inet6 fe80::f2de:f1ff:fef9:a752%em0 prefixlen 64 scopeid 0x1
| inet6 2001:8b0:648e:cc01:f2de:f1ff:fef9:a752 prefixlen 64 autoconf pltime 604697 vltime 2591897
| inet 85.158.44.149 netmask 0xfffffff0 broadcast 85.158.44.159
| # ifconfig carp0
| carp0: flags=8802<BROADCAST,SIMPLEX,MULTICAST> mtu 1500
| lladdr 00:00:5e:00:01:01
| priority: 0
| carp: INIT carpdev em0 vhid 1 advbase 1 advskew 0
| groups: carp
| status: invalid
| inet6 fe80::200:5eff:fe00:101%carp0 prefixlen 64 scopeid 0xa
| inet6 2001:8b0:648e:cc01:200:5eff:fe00:101 prefixlen 64 detached autoconf pltime 604690 vltime 2591890
| inet6 2001:8b0:648e:cc01:5c46:9730:9899:1008 prefixlen 64 detached autoconf autoconfprivacy pltime 81660 vltime 600216
| inet6 2001:8b0:648e:cc01::ca1f prefixlen 64
| # $ route -n get -inet6 2001:8b0:648e:cc01:20d:b9ff:fe04:a330
|    route to: 2001:8b0:648e:cc01:20d:b9ff:fe04:a330
| destination: 2001:8b0:648e:cc01::
|        mask: ffff:ffff:ffff:ffff::
|   interface: em0
|  if address: fe80::f2de:f1ff:fef9:a752%em0
|    priority: 4 (connected)
|       flags: <UP,DONE,CLONING>
|      use       mtu    expire
|        0         0         0
| # ping6 jodrell
| PING6(56=40+8+8 bytes) 2001:8b0:648e:cc01::ca1f --> 2001:8b0:648e:cc01:20d:b9ff:fe04:a330
| ^C
| --- jodrell.spacehopper.org ping6 statistics ---
| 3 packets transmitted, 0 packets received, 100.0% packet loss
|
|
| # netstat -rnfinet6|grep -e 2001:8b0:648e:cc01 -e carp0
| 2001:8b0:648e:cc01::/64            link#1                         UC         7        0     -     4 em0  
| 2001:8b0:648e:cc01::1              00:0d:b9:17:0c:c4              UHLc       0        5     -     4 em0  
| 2001:8b0:648e:cc01::ca1f           link#1                         UHLc       1        0     -     4 em0  
| 2001:8b0:648e:cc01:200:5eff:fe00:101 00:00:5e:00:01:01              UHL        0        0     -     4 lo0  
| 2001:8b0:648e:cc01:20d:93ff:fe63:da5a 00:0d:93:63:da:5a              UHLc       1        8     -     4 em0  
| 2001:8b0:648e:cc01:20d:b9ff:fe04:a330 00:0d:b9:17:0c:c4              UHLc       0        3     -     4 em0  
| 2001:8b0:648e:cc01:5c46:9730:9899:1008 00:00:5e:00:01:01              UHL        0        0     -     4 lo0  
| 2001:8b0:648e:cc01:f2de:f1ff:fef9:a752 f0:de:f1:f9:a7:52              UHLc       0        0     -     4 lo0  
| fe80::%carp0/64                    link#10                        UC        12        0     -     4 carp0
| fe80::200:5eff:fe00:101%carp0      00:00:5e:00:01:01              UHL        0        0     -     4 lo0  
| fe80::20d:93ff:fe63:da5a%carp0     00:0d:93:63:da:5a              UHLc       0        2     -     4 carp0
| fe80::20d:b9ff:fe17:cc4%carp0      00:0d:b9:17:0c:c4              UHLc       0        0     -     4 carp0
| ff01::%carp0/32                    link#10                        UC         0        0     -     4 carp0
| ff02::%carp0/32                    link#10                        UC         2        0     -     4 carp0
| ff02::1:ff04:a330%carp0            link#10                        UHLc       0        0     -     4 carp0
| ff02::1:ff63:da5a%carp0            link#10                        UHLc       0        0     -     4 carp0

--
Todd Fries .. [hidden email]

 ____________________________________________
|                                            \  1.636.410.0632 (voice)
| Free Daemon Consulting, LLC                \  1.405.227.9094 (voice)
| http://FreeDaemonConsulting.com            \  1.866.792.3418 (FAX)
| PO Box 16169, Oklahoma City, OK 73113      \  sip:[hidden email]
| "..in support of free software solutions." \  sip:[hidden email]
 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
                                                 
              37E7 D3EB 74D0 8D66 A68D  B866 0326 204E 3F42 004A
                        http://todd.fries.net/pgp.txt

Reply | Threaded
Open this post in threaded view
|

Re: ip6 source address selection and down interfaces

Todd T. Fries-2
In reply to this post by Stuart Henderson
see in6.c:in6_ifawithscope()

probably ought to add a case int he TAILQ_FOREACH(ifp, ...) loop
to 'continue;' if the interface is down...?

Penned by Stuart Henderson on 20130219 19:11.10, we have:
| Someone trying to replace some latvian boxes with bgpd/npppd mentioned
| a problem with v6 on carp interfaces in 'backup' state where their
| address was used as source address, despite there being an address
| on the carpdev which was up.
|
| I don't have a proper v6 carp setup handy to test but got a test
| machine into a state with 'ifconfig carp0 down' (which seems should be
| a close enough equivalent to 'carp backup' for tests) which did
| indeed consider the 'down' carp interface as a source address.
|
| It can be bodged around with pltime 0 of course, but from looking at
| in6_selectsrc() I don't see why it wouldn't just pick the address
| from the interface associated with the route i.e. the one on em0..
| but then I must be missing something as I don't see where pltime 0
| is handled either... does anyone have clues?
|
| # ifconfig em0
| em0: flags=48b43<UP,BROADCAST,RUNNING,PROMISC,ALLMULTI,SIMPLEX,MULTICAST,INET6_NOPRIVACY> mtu 1500
| lladdr f0:de:f1:f9:a7:52
| priority: 0
| groups: egress
| media: Ethernet autoselect (1000baseT full-duplex)
| status: active
| inet6 fe80::f2de:f1ff:fef9:a752%em0 prefixlen 64 scopeid 0x1
| inet6 2001:8b0:648e:cc01:f2de:f1ff:fef9:a752 prefixlen 64 autoconf pltime 604697 vltime 2591897
| inet 85.158.44.149 netmask 0xfffffff0 broadcast 85.158.44.159
| # ifconfig carp0
| carp0: flags=8802<BROADCAST,SIMPLEX,MULTICAST> mtu 1500
| lladdr 00:00:5e:00:01:01
| priority: 0
| carp: INIT carpdev em0 vhid 1 advbase 1 advskew 0
| groups: carp
| status: invalid
| inet6 fe80::200:5eff:fe00:101%carp0 prefixlen 64 scopeid 0xa
| inet6 2001:8b0:648e:cc01:200:5eff:fe00:101 prefixlen 64 detached autoconf pltime 604690 vltime 2591890
| inet6 2001:8b0:648e:cc01:5c46:9730:9899:1008 prefixlen 64 detached autoconf autoconfprivacy pltime 81660 vltime 600216
| inet6 2001:8b0:648e:cc01::ca1f prefixlen 64
| # $ route -n get -inet6 2001:8b0:648e:cc01:20d:b9ff:fe04:a330
|    route to: 2001:8b0:648e:cc01:20d:b9ff:fe04:a330
| destination: 2001:8b0:648e:cc01::
|        mask: ffff:ffff:ffff:ffff::
|   interface: em0
|  if address: fe80::f2de:f1ff:fef9:a752%em0
|    priority: 4 (connected)
|       flags: <UP,DONE,CLONING>
|      use       mtu    expire
|        0         0         0
| # ping6 jodrell
| PING6(56=40+8+8 bytes) 2001:8b0:648e:cc01::ca1f --> 2001:8b0:648e:cc01:20d:b9ff:fe04:a330
| ^C
| --- jodrell.spacehopper.org ping6 statistics ---
| 3 packets transmitted, 0 packets received, 100.0% packet loss
|
|
| # netstat -rnfinet6|grep -e 2001:8b0:648e:cc01 -e carp0
| 2001:8b0:648e:cc01::/64            link#1                         UC         7        0     -     4 em0  
| 2001:8b0:648e:cc01::1              00:0d:b9:17:0c:c4              UHLc       0        5     -     4 em0  
| 2001:8b0:648e:cc01::ca1f           link#1                         UHLc       1        0     -     4 em0  
| 2001:8b0:648e:cc01:200:5eff:fe00:101 00:00:5e:00:01:01              UHL        0        0     -     4 lo0  
| 2001:8b0:648e:cc01:20d:93ff:fe63:da5a 00:0d:93:63:da:5a              UHLc       1        8     -     4 em0  
| 2001:8b0:648e:cc01:20d:b9ff:fe04:a330 00:0d:b9:17:0c:c4              UHLc       0        3     -     4 em0  
| 2001:8b0:648e:cc01:5c46:9730:9899:1008 00:00:5e:00:01:01              UHL        0        0     -     4 lo0  
| 2001:8b0:648e:cc01:f2de:f1ff:fef9:a752 f0:de:f1:f9:a7:52              UHLc       0        0     -     4 lo0  
| fe80::%carp0/64                    link#10                        UC        12        0     -     4 carp0
| fe80::200:5eff:fe00:101%carp0      00:00:5e:00:01:01              UHL        0        0     -     4 lo0  
| fe80::20d:93ff:fe63:da5a%carp0     00:0d:93:63:da:5a              UHLc       0        2     -     4 carp0
| fe80::20d:b9ff:fe17:cc4%carp0      00:0d:b9:17:0c:c4              UHLc       0        0     -     4 carp0
| ff01::%carp0/32                    link#10                        UC         0        0     -     4 carp0
| ff02::%carp0/32                    link#10                        UC         2        0     -     4 carp0
| ff02::1:ff04:a330%carp0            link#10                        UHLc       0        0     -     4 carp0
| ff02::1:ff63:da5a%carp0            link#10                        UHLc       0        0     -     4 carp0

--
Todd Fries .. [hidden email]

 ____________________________________________
|                                            \  1.636.410.0632 (voice)
| Free Daemon Consulting, LLC                \  1.405.227.9094 (voice)
| http://FreeDaemonConsulting.com            \  1.866.792.3418 (FAX)
| PO Box 16169, Oklahoma City, OK 73113      \  sip:[hidden email]
| "..in support of free software solutions." \  sip:[hidden email]
 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
                                                 
              37E7 D3EB 74D0 8D66 A68D  B866 0326 204E 3F42 004A
                        http://todd.fries.net/pgp.txt

Reply | Threaded
Open this post in threaded view
|

Re: ip6 source address selection and down interfaces

Alexander Bluhm
In reply to this post by Stuart Henderson
On Wed, Feb 20, 2013 at 01:11:10AM +0000, Stuart Henderson wrote:
> Someone trying to replace some latvian boxes with bgpd/npppd mentioned
> a problem with v6 on carp interfaces in 'backup' state where their
> address was used as source address, despite there being an address
> on the carpdev which was up.

For CARP and IPv6 you should try this diff.  I have sent this around
a while ago.

Test reports? OKs?

bluhm

Index: netinet6/in6.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/in6.c,v
retrieving revision 1.101
diff -u -p -r1.101 in6.c
--- netinet6/in6.c 30 Nov 2012 13:48:12 -0000 1.101
+++ netinet6/in6.c 30 Dec 2012 16:30:47 -0000
@@ -97,6 +97,9 @@
 #include <netinet6/ip6_mroute.h>
 #endif
 #include <netinet6/in6_ifattach.h>
+#if NCARP > 0
+#include <netinet/ip_carp.h>
+#endif
 
 /* backward compatibility for a while... */
 #define COMPAT_IN6IFIOCTL
@@ -2145,6 +2148,9 @@ in6_ifawithscope(struct ifnet *oifp, str
  struct ifaddr *ifa;
  struct ifnet *ifp;
  struct in6_ifaddr *ifa_best = NULL;
+#if NCARP > 0
+ struct sockaddr_dl *proxydl = NULL;
+#endif
 
  if (oifp == NULL) {
  printf("in6_ifawithscope: output interface is not specified\n");
@@ -2159,6 +2165,14 @@ in6_ifawithscope(struct ifnet *oifp, str
  TAILQ_FOREACH(ifp, &ifnet, if_list) {
  if (ifp->if_rdomain != rdomain)
  continue;
+#if NCARP > 0
+ /* Never use a carp address of an interface which is not
+ * the master.
+ */
+ if (ifp->if_type == IFT_CARP &&
+    !carp_iamatch6(ifp, NULL, &proxydl))
+ continue;
+#endif
 
  /*
  * We can never take an address that breaks the scope zone
@@ -2435,6 +2449,14 @@ in6if_do_dad(struct ifnet *ifp)
  * NS would confuse the DAD procedure.
  */
  return (0);
+#if NCARP > 0
+ case IFT_CARP:
+ /*
+ * XXX: DAD does not work currently on carp(4)
+ * so disable it for now.
+ */
+ return (0);
+#endif
  default:
  /*
  * Our DAD routine requires the interface up and running.
Index: netinet6/nd6_nbr.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/nd6_nbr.c,v
retrieving revision 1.63
diff -u -p -r1.63 nd6_nbr.c
--- netinet6/nd6_nbr.c 16 May 2012 09:48:38 -0000 1.63
+++ netinet6/nd6_nbr.c 30 Dec 2012 16:22:54 -0000
@@ -561,6 +561,9 @@ nd6_na_input(struct mbuf *m, int off, in
  struct rtentry *rt;
  struct sockaddr_dl *sdl;
  union nd_opts ndopts;
+#if NCARP > 0
+ struct sockaddr_dl *proxydl = NULL;
+#endif
 
  if (ip6->ip6_hlim != 255) {
  nd6log((LOG_ERR,
@@ -617,6 +620,11 @@ nd6_na_input(struct mbuf *m, int off, in
  }
 
  ifa = &in6ifa_ifpwithaddr(ifp, &taddr6)->ia_ifa;
+#if NCARP > 0
+ if (ifp->if_type == IFT_CARP && ifa &&
+    !carp_iamatch6(ifp, lladdr, &proxydl))
+ ifa = NULL;
+#endif
 
  /*
  * Target address matches one of my interface address.

Reply | Threaded
Open this post in threaded view
|

Re: ip6 source address selection and down interfaces

Alexander Bluhm
In reply to this post by Todd T. Fries-2
On Wed, Feb 20, 2013 at 12:36:13AM -0600, Todd T. Fries wrote:

> The source address selection mechanism in IPv4 is to my understanding:
>
>  the first address on the interface associated with the route
>  to the remote host
>
> The source address selection mechanism in IPv6 is to my understanding:
>
>  for each of the global addresses on a system, turn it into an integer
>  and subtract it from the destination address.  The difference closest
>  to zero decides what address will be selected because it is 'closest'.
>
> Personally I'd be happy if IPv6 mimicked IPv4 in this regard.  Other OS's
> permit configurable address selection criteria in the kernel, but I'll be
> the first to suggest this is not the OpenBSD way.  The default should be
> good enough and .. this is not good enough for me in every scenario I've
> encountered it.

I am running with this diff for a while now.  It gives the outgoing
interface a higher priority when selecting an IPv6 source addresse.

More and more RFCs on that topic get published, making things more
complicated.  I am not convinced that this diff is good solution
in general.

bluhm

Index: netinet6/in6.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/in6.c,v
retrieving revision 1.101
diff -u -p -r1.101 in6.c
--- netinet6/in6.c 30 Nov 2012 13:48:12 -0000 1.101
+++ netinet6/in6.c 3 Feb 2013 12:09:31 -0000
@@ -2263,6 +2263,12 @@ in6_ifawithscope(struct ifnet *oifp, str
      IN6_IFF_DEPRECATED) == 0)
  goto replace;
 
+ /* RFC 3484 5. Rule 5: Prefer outgoing interface */
+ if (ifa_best->ia_ifp == oifp && ifp != oifp)
+ continue;
+ if (ifa_best->ia_ifp != oifp && ifp == oifp)
+ goto replace;
+
  /*
  * At this point, we have two cases:
  * 1. we are looking at a non-deprecated address,