Re: Anycast usage, final diagnosis? (was: IPv6: Fix broken anycast
From: Pekka Savola <hidden>
Date: 2003-07-18 06:44:46
On Fri, 18 Jul 2003 kuznet@ms2.inr.ac.ru wrote:
quoted
No user should be able to join anycast group, IMHO.OK. Done, the patch enclosed.
Based on a quick glance, looks OK. Better than the code we have now..
Another rfc question: is random delay answering solicitations for anycast not required already?
I'm not sure whether this is what you're asking but..: When responding to an NS with an NA w/ anycast address, the response SHOULD be delayed by a random 0..MAX_ANYCAST_DELAY_TIME (1 by default) seconds. (Override bit also SHOULD be set to 0.)
quoted hunk
# This is a BitKeeper generated patch for the following project: # Project Name: Linux kernel tree # This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas: # ChangeSet 1.1469 -> 1.1470 # net/ipv6/anycast.c 1.5 -> 1.6 # include/net/ip6_route.h 1.10 -> 1.11 # net/ipv6/icmp.c 1.36 -> 1.37 # net/ipv6/tcp_ipv6.c 1.64 -> 1.65 # net/ipv6/ndisc.c 1.52 -> 1.53 # net/ipv6/route.c 1.50 -> 1.51 # include/net/ipv6.h 1.22 -> 1.23 # net/ipv6/addrconf.c 1.58 -> 1.59 # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 03/07/18 kuznet@oops.inr.ac.ru 1.1470 # IPv6: sanitize anycast address support # -------------------------------------------- # diff -Nru a/include/net/ip6_route.h b/include/net/ip6_route.h--- a/include/net/ip6_route.h Fri Jul 18 00:49:43 2003 +++ b/include/net/ip6_route.h Fri Jul 18 00:49:43 2003@@ -45,7 +45,8 @@ void *rtattr); extern int ip6_rt_addr_add(struct in6_addr *addr, - struct net_device *dev); + struct net_device *dev, + int anycast); extern int ip6_rt_addr_del(struct in6_addr *addr, struct net_device *dev);@@ -116,6 +117,13 @@ np->daddr_cache = daddr; np->dst_cookie = rt->rt6i_node ? rt->rt6i_node->fn_sernum : 0; write_unlock(&sk->sk_dst_lock); +} + +static inline int ipv6_unicast_destination(struct sk_buff *skb) +{ + struct rt6_info *rt = (struct rt6_info *) skb->dst; + + return rt->rt6i_flags & RTF_LOCAL; } #endifdiff -Nru a/include/net/ipv6.h b/include/net/ipv6.h--- a/include/net/ipv6.h Fri Jul 18 00:49:43 2003 +++ b/include/net/ipv6.h Fri Jul 18 00:49:43 2003@@ -51,7 +51,7 @@ /* * Addr type * - * type - unicast | multicast | anycast + * type - unicast | multicast * scope - local | site | global * v4 - compat * v4mapped@@ -63,7 +63,6 @@ #define IPV6_ADDR_UNICAST 0x0001U #define IPV6_ADDR_MULTICAST 0x0002U -#define IPV6_ADDR_ANYCAST 0x0004U #define IPV6_ADDR_LOOPBACK 0x0010U #define IPV6_ADDR_LINKLOCAL 0x0020Udiff -Nru a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c--- a/net/ipv6/addrconf.c Fri Jul 18 00:49:43 2003 +++ b/net/ipv6/addrconf.c Fri Jul 18 00:49:43 2003@@ -209,15 +209,8 @@ }; return type; } - /* check for reserved anycast addresses */ - - if ((st & htonl(0xE0000000)) && - ((addr->s6_addr32[2] == htonl(0xFDFFFFFF) && - (addr->s6_addr32[3] | htonl(0x7F)) == (u32)~0) || - (addr->s6_addr32[2] == 0 && addr->s6_addr32[3] == 0))) - type = IPV6_ADDR_ANYCAST; - else - type = IPV6_ADDR_UNICAST; + + type = IPV6_ADDR_UNICAST; /* Consider all addresses with the first three bits different of 000 and 111 as finished.@@ -2552,7 +2545,7 @@ switch (event) { case RTM_NEWADDR: - ip6_rt_addr_add(&ifp->addr, ifp->idev->dev); + ip6_rt_addr_add(&ifp->addr, ifp->idev->dev, 0); break; case RTM_DELADDR: addrconf_leave_solict(ifp->idev->dev, &ifp->addr);diff -Nru a/net/ipv6/anycast.c b/net/ipv6/anycast.c--- a/net/ipv6/anycast.c Fri Jul 18 00:49:43 2003 +++ b/net/ipv6/anycast.c Fri Jul 18 00:49:43 2003@@ -96,7 +96,6 @@ return onlink; } - /* * socket join an anycast group */@@ -110,8 +109,12 @@ int ishost = !ipv6_devconf.forwarding; int err = 0; + if (!capable(CAP_NET_ADMIN)) + return -EPERM; if (ipv6_addr_type(addr) & IPV6_ADDR_MULTICAST) return -EINVAL; + if (ipv6_chk_addr(addr, NULL)) + return -EINVAL; pac = sock_kmalloc(sk, sizeof(struct ipv6_ac_socklist), GFP_KERNEL); if (pac == NULL)@@ -161,21 +164,12 @@ * For hosts, allow link-local or matching prefix anycasts. * This obviates the need for propagating anycast routes while * still allowing some non-router anycast participation. - * - * allow anyone to join anycasts that don't require a special route - * and can't be spoofs of unicast addresses (reserved anycast only) */ if (!ip6_onlink(addr, dev)) { if (ishost) err = -EADDRNOTAVAIL; - else if (!capable(CAP_NET_ADMIN)) - err = -EPERM; if (err) goto out_dev_put; - } else if (!(ipv6_addr_type(addr) & IPV6_ADDR_ANYCAST) && - !capable(CAP_NET_ADMIN)) { - err = -EPERM; - goto out_dev_put; } err = ipv6_dev_ac_inc(dev, addr);@@ -266,6 +260,13 @@ dev_put(dev); } +#if 0 +/* The function is not used, which is funny. Apparently, author + * supposed to use it to filter out datagrams inside udp/raw but forgot. + * + * It is OK, anycasts are not special comparing to delivery to unicasts. + */ + int inet6_ac_check(struct sock *sk, struct in6_addr *addr, int ifindex) { struct ipv6_ac_socklist *pac;@@ -286,6 +287,8 @@ return found; } +#endif + static void aca_put(struct ifacaddr6 *ac) { if (atomic_dec_and_test(&ac->aca_refcnt)) {@@ -347,7 +350,7 @@ idev->ac_list = aca; write_unlock_bh(&idev->lock); - ip6_rt_addr_add(&aca->aca_addr, dev); + ip6_rt_addr_add(&aca->aca_addr, dev, 1); addrconf_join_solict(dev, &aca->aca_addr);diff -Nru a/net/ipv6/icmp.c b/net/ipv6/icmp.c--- a/net/ipv6/icmp.c Fri Jul 18 00:49:43 2003 +++ b/net/ipv6/icmp.c Fri Jul 18 00:49:43 2003@@ -415,8 +415,7 @@ saddr = &skb->nh.ipv6h->daddr; - if (ipv6_addr_type(saddr) & IPV6_ADDR_MULTICAST || - ipv6_chk_acast_addr(0, saddr)) + if (!ipv6_unicast_destination(skb)) saddr = NULL; memcpy(&tmp_hdr, icmph, sizeof(tmp_hdr));diff -Nru a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c--- a/net/ipv6/ndisc.c Fri Jul 18 00:49:43 2003 +++ b/net/ipv6/ndisc.c Fri Jul 18 00:49:43 2003@@ -785,8 +785,7 @@ ipv6_addr_all_nodes(&maddr); ndisc_send_na(dev, NULL, &maddr, &ifp->addr, ifp->idev->cnf.forwarding, 0, - ipv6_addr_type(&ifp->addr)&IPV6_ADDR_ANYCAST ? 0 : 1, - 1); + 1, 1); in6_ifa_put(ifp); return; }@@ -809,8 +808,7 @@ if (neigh || !dev->hard_header) { ndisc_send_na(dev, neigh, saddr, &ifp->addr, ifp->idev->cnf.forwarding, 1, - ipv6_addr_type(&ifp->addr)&IPV6_ADDR_ANYCAST ? 0 : 1, - 1); + 1, 1); if (neigh) neigh_release(neigh); }diff -Nru a/net/ipv6/route.c b/net/ipv6/route.c--- a/net/ipv6/route.c Fri Jul 18 00:49:43 2003 +++ b/net/ipv6/route.c Fri Jul 18 00:49:43 2003@@ -1256,7 +1256,7 @@ * Add address */ -int ip6_rt_addr_add(struct in6_addr *addr, struct net_device *dev) +int ip6_rt_addr_add(struct in6_addr *addr, struct net_device *dev, int anycast) { struct rt6_info *rt = ip6_dst_alloc();@@ -1275,6 +1275,8 @@ rt->u.dst.obsolete = -1; rt->rt6i_flags = RTF_UP | RTF_NONEXTHOP; + if (!anycast) + rt->rt6i_flags |= RTF_LOCAL; rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_gateway); if (rt->rt6i_nexthop == NULL) { dst_free((struct dst_entry *) rt);diff -Nru a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c--- a/net/ipv6/tcp_ipv6.c Fri Jul 18 00:49:43 2003 +++ b/net/ipv6/tcp_ipv6.c Fri Jul 18 00:49:43 2003@@ -971,7 +971,7 @@ if (th->rst) return; - if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr)) + if (!ipv6_unicast_destination(skb)) return; /*@@ -1175,8 +1175,7 @@ if (skb->protocol == htons(ETH_P_IP)) return tcp_v4_conn_request(sk, skb); - /* FIXME: do the same check for anycast */ - if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr)) + if (!ipv6_unicast_destination(skb)) goto drop; /*
-- Pekka Savola "You each name yourselves king, yet the Netcore Oy kingdom bleeds." Systems. Networks. Security. -- George R.R. Martin: A Clash of Kings