summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorAlexey Kuznetsov <kuznet@ms2.inr.ac.ru>2003-07-18 09:44:04 -0700
committerDavid S. Miller <davem@nuts.ninka.net>2003-07-18 09:44:04 -0700
commit0cc526e0e801dd0a372641bfbefb20f74e881cb9 (patch)
tree007758e65478dd65b6ca8bd4943243f320fd6c2b /net
parent2135f3fb6233831584d450f6bdb792fa04f0d79f (diff)
[IPV6]: Fix anycast usage.
- Recognition of reserved anycasts is removed from ipv6_addr_type() Flag IPV6_ADDR_ANYCAST is removed as well. - Some meaningless noop code checking for anycast which are not going to happen is removed from ndisc.c - ipv6_unicast_destination() replaces suboptimal ipv6_chk_acast_addr() in data paths
Diffstat (limited to 'net')
-rw-r--r--net/ipv6/addrconf.c13
-rw-r--r--net/ipv6/anycast.c25
-rw-r--r--net/ipv6/icmp.c3
-rw-r--r--net/ipv6/ndisc.c6
-rw-r--r--net/ipv6/route.c4
-rw-r--r--net/ipv6/tcp_ipv6.c5
6 files changed, 25 insertions, 31 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index b0c186efccd3..649df9f76068 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -209,15 +209,8 @@ int ipv6_addr_type(const struct in6_addr *addr)
};
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 @@ static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
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 --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c
index 1dc5b9da2e2b..f36fee99a37c 100644
--- a/net/ipv6/anycast.c
+++ b/net/ipv6/anycast.c
@@ -96,7 +96,6 @@ ip6_onlink(struct in6_addr *addr, struct net_device *dev)
return onlink;
}
-
/*
* socket join an anycast group
*/
@@ -110,8 +109,12 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, struct in6_addr *addr)
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 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, struct in6_addr *addr)
* 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 @@ void ipv6_sock_ac_close(struct sock *sk)
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 @@ int inet6_ac_check(struct sock *sk, struct in6_addr *addr, int ifindex)
return found;
}
+#endif
+
static void aca_put(struct ifacaddr6 *ac)
{
if (atomic_dec_and_test(&ac->aca_refcnt)) {
@@ -347,7 +350,7 @@ int ipv6_dev_ac_inc(struct net_device *dev, struct in6_addr *addr)
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 --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 5cfc70535e35..727b681325aa 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -415,8 +415,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
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 --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 75a9eeaa05d0..95772c3e915a 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -785,8 +785,7 @@ static void ndisc_recv_ns(struct sk_buff *skb)
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 @@ static void ndisc_recv_ns(struct sk_buff *skb)
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 --git a/net/ipv6/route.c b/net/ipv6/route.c
index ac76e702faa2..69d7791712f8 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1261,7 +1261,7 @@ int ip6_pkt_discard(struct sk_buff *skb)
* 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();
@@ -1280,6 +1280,8 @@ int ip6_rt_addr_add(struct in6_addr *addr, struct net_device *dev)
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 --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 21b165ec5339..e5cd4c372577 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -971,7 +971,7 @@ static void tcp_v6_send_reset(struct sk_buff *skb)
if (th->rst)
return;
- if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr))
+ if (!ipv6_unicast_destination(skb))
return;
/*
@@ -1175,8 +1175,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
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;
/*