lkml.org 
[lkml]   [2003]   [Jan]   [24]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patches in this message
/
Date
From
Subject[PATCH] IPv6: fixes to proxy Neighbor discovery
Hello!

This patch contains some fixes to proxy Neighbor Discovery.

1) Source address fixed in neigbor advertisements:

RFC 2461
4.4. Neighbor Advertisement Message Format
" Source Address
An address assigned to the interface from which the
advertisement is sent."

This also applies to proxy Neighbor Adverisements.

2) Proxy protects against Duplicate Address Detection:

RFC 2461
7.2.3. Receipt of Neighbor Solicitations
" A valid Neighbor Solicitation that does not meet any the following
requirements MUST be silently discarded:

- The Target Address is a "valid" unicast or anycast address
assigned to the receiving interface [ADDRCONF],

- The Target Address is a unicast address for which the node is
offering proxy service, or

- The Target Address is a "tentative" address on which Duplicate
Address Detection is being performed [ADDRCONF].

If the Target Address is tentative, the Neighbor Solicitation should
be processed as described in [ADDRCONF]. Otherwise, the following
description applies. If the Source Address is not the unspecified
address and, on link layers that have addresses, the solicitation
includes a Source Link-Layer Address option, then the recipient
SHOULD create or update the Neighbor Cache entry for the IP Source
Address of the solicitation."
....
" If the Source Address is the unspecified address the node MUST NOT
create or update the Neighbor Cache entry.

After any updates to the Neighbor Cache, the node sends a Neighbor
Advertisement response as described in the next section."

This clearly means the proxy should protect the address against DAD.

Below are patches against both the 2.4 and 2.5 bk trees.

Thanks,
Ville

===== net/ipv6/ndisc.c 1.16 vs edited =====
--- 1.16/net/ipv6/ndisc.c Sat Dec 21 09:43:20 2002
+++ edited/net/ipv6/ndisc.c Fri Jan 24 10:14:33 2003
@@ -23,6 +23,7 @@
* and moved to net/core.
* Pekka Savola : RFC2461 validation
* YOSHIFUJI Hideaki @USAGI : Verify ND options properly
+ * Ville Nuorvala : RFC2461 fixes to proxy ND
*/

/* Set to 3 to get tracing... */
@@ -370,8 +371,9 @@
*/

void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
- struct in6_addr *daddr, struct in6_addr *solicited_addr,
- int router, int solicited, int override, int inc_opt)
+ struct in6_addr *daddr, struct in6_addr *saddr,
+ struct in6_addr *solicited_addr, int router,
+ int solicited, int override, int inc_opt)
{
struct sock *sk = ndisc_socket->sk;
struct nd_msg *msg;
@@ -401,7 +403,7 @@
return;
}

- ip6_nd_hdr(sk, skb, dev, solicited_addr, daddr, IPPROTO_ICMPV6, len);
+ ip6_nd_hdr(sk, skb, dev, saddr, daddr, IPPROTO_ICMPV6, len);

msg = (struct nd_msg *) skb_put(skb, len);

@@ -421,7 +423,7 @@
ndisc_fill_option(msg->opt, ND_OPT_TARGET_LL_ADDR, dev->dev_addr, dev->addr_len);

/* checksum */
- msg->icmph.icmp6_cksum = csum_ipv6_magic(solicited_addr, daddr, len,
+ msg->icmph.icmp6_cksum = csum_ipv6_magic(saddr, daddr, len,
IPPROTO_ICMPV6,
csum_partial((__u8 *) msg,
len, 0));
@@ -669,8 +671,8 @@
struct in6_addr maddr;

ipv6_addr_all_nodes(&maddr);
- ndisc_send_na(dev, NULL, &maddr, &ifp->addr,
- ifp->idev->cnf.forwarding, 0,
+ ndisc_send_na(dev, NULL, &maddr, &ifp->addr,
+ &ifp->addr, ifp->idev->cnf.forwarding, 0,
ipv6_addr_type(&ifp->addr)&IPV6_ADDR_ANYCAST ? 0 : 1,
1);
in6_ifa_put(ifp);
@@ -693,7 +695,8 @@
neigh = neigh_event_ns(&nd_tbl, lladdr, saddr, dev);

if (neigh || !dev->hard_header) {
- ndisc_send_na(dev, neigh, saddr, &ifp->addr,
+ ndisc_send_na(dev, neigh, saddr,
+ &ifp->addr, &ifp->addr,
ifp->idev->cnf.forwarding, 1,
ipv6_addr_type(&ifp->addr)&IPV6_ADDR_ANYCAST ? 0 : 1,
1);
@@ -707,7 +710,8 @@
int addr_type = ipv6_addr_type(saddr);

if (in6_dev && in6_dev->cnf.forwarding &&
- (addr_type & IPV6_ADDR_UNICAST) &&
+ (addr_type & IPV6_ADDR_UNICAST ||
+ addr_type == IPV6_ADDR_ANY) &&
pneigh_lookup(&nd_tbl, &msg->target, dev, 0)) {
int inc = ipv6_addr_type(daddr)&IPV6_ADDR_MULTICAST;

@@ -715,17 +719,38 @@
skb->pkt_type == PACKET_HOST ||
inc == 0 ||
in6_dev->nd_parms->proxy_delay == 0) {
+ struct in6_addr na_saddr;
+
if (inc)
nd_tbl.stats.rcv_probes_mcast++;
else
nd_tbl.stats.rcv_probes_ucast++;
-
- neigh = neigh_event_ns(&nd_tbl, lladdr, saddr, dev);

- if (neigh) {
- ndisc_send_na(dev, neigh, saddr, &msg->target,
- 0, 1, 0, 1);
- neigh_release(neigh);
+ /*
+ * RFC2461 4.4:
+ * The souce address is always an address assigned to the interface,
+ * this also applies to proxies
+ */
+ if (ipv6_get_lladdr(dev, &na_saddr)) {
+ in6_dev_put(in6_dev);
+ return;
+ }
+ if (addr_type & IPV6_ADDR_UNICAST) {
+ neigh = neigh_event_ns(&nd_tbl, lladdr, saddr, dev);
+
+ if (neigh) {
+ ndisc_send_na(dev, neigh, saddr,
+ &na_saddr, &msg->target,
+ 0, 1, 0, 1);
+ neigh_release(neigh);
+ }
+ } else {
+ /* the proxy should also protect against DAD */
+ struct in6_addr maddr;
+ ipv6_addr_all_nodes(&maddr);
+ ndisc_send_na(dev, NULL, &maddr,
+ &na_saddr, &msg->target,
+ 0, 0, 0, 1);
}
} else {
struct sk_buff *n = skb_clone(skb, GFP_ATOMIC);
===== net/ipv6/ndisc.c 1.21 vs edited =====
--- 1.21/net/ipv6/ndisc.c Sat Dec 21 09:14:32 2002
+++ edited/net/ipv6/ndisc.c Fri Jan 24 10:17:18 2003
@@ -23,6 +23,7 @@
* and moved to net/core.
* Pekka Savola : RFC2461 validation
* YOSHIFUJI Hideaki @USAGI : Verify ND options properly
+ * Ville Nuorvala : RFC2461 fixes to proxy ND
*/

/* Set to 3 to get tracing... */
@@ -375,8 +376,9 @@
*/

static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
- struct in6_addr *daddr, struct in6_addr *solicited_addr,
- int router, int solicited, int override, int inc_opt)
+ struct in6_addr *daddr, struct in6_addr *saddr,
+ struct in6_addr *solicited_addr, int router,
+ int solicited, int override, int inc_opt)
{
struct sock *sk = ndisc_socket->sk;
struct nd_msg *msg;
@@ -406,7 +408,7 @@
return;
}

- ip6_nd_hdr(sk, skb, dev, solicited_addr, daddr, IPPROTO_ICMPV6, len);
+ ip6_nd_hdr(sk, skb, dev, saddr, daddr, IPPROTO_ICMPV6, len);

msg = (struct nd_msg *) skb_put(skb, len);

@@ -426,7 +428,7 @@
ndisc_fill_option(msg->opt, ND_OPT_TARGET_LL_ADDR, dev->dev_addr, dev->addr_len);

/* checksum */
- msg->icmph.icmp6_cksum = csum_ipv6_magic(solicited_addr, daddr, len,
+ msg->icmph.icmp6_cksum = csum_ipv6_magic(saddr, daddr, len,
IPPROTO_ICMPV6,
csum_partial((__u8 *) msg,
len, 0));
@@ -674,8 +676,8 @@
struct in6_addr maddr;

ipv6_addr_all_nodes(&maddr);
- ndisc_send_na(dev, NULL, &maddr, &ifp->addr,
- ifp->idev->cnf.forwarding, 0,
+ ndisc_send_na(dev, NULL, &maddr, &ifp->addr,
+ &ifp->addr, ifp->idev->cnf.forwarding, 0,
ipv6_addr_type(&ifp->addr)&IPV6_ADDR_ANYCAST ? 0 : 1,
1);
in6_ifa_put(ifp);
@@ -698,7 +700,8 @@
neigh = neigh_event_ns(&nd_tbl, lladdr, saddr, dev);

if (neigh || !dev->hard_header) {
- ndisc_send_na(dev, neigh, saddr, &ifp->addr,
+ ndisc_send_na(dev, neigh, saddr,
+ &ifp->addr, &ifp->addr,
ifp->idev->cnf.forwarding, 1,
ipv6_addr_type(&ifp->addr)&IPV6_ADDR_ANYCAST ? 0 : 1,
1);
@@ -712,7 +715,8 @@
int addr_type = ipv6_addr_type(saddr);

if (in6_dev && in6_dev->cnf.forwarding &&
- (addr_type & IPV6_ADDR_UNICAST) &&
+ (addr_type & IPV6_ADDR_UNICAST ||
+ addr_type == IPV6_ADDR_ANY) &&
pneigh_lookup(&nd_tbl, &msg->target, dev, 0)) {
int inc = ipv6_addr_type(daddr)&IPV6_ADDR_MULTICAST;

@@ -720,17 +724,38 @@
skb->pkt_type == PACKET_HOST ||
inc == 0 ||
in6_dev->nd_parms->proxy_delay == 0) {
+ struct in6_addr na_saddr;
+
if (inc)
nd_tbl.stats.rcv_probes_mcast++;
else
nd_tbl.stats.rcv_probes_ucast++;
-
- neigh = neigh_event_ns(&nd_tbl, lladdr, saddr, dev);

- if (neigh) {
- ndisc_send_na(dev, neigh, saddr, &msg->target,
- 0, 1, 0, 1);
- neigh_release(neigh);
+ /*
+ * RFC2461 4.4:
+ * The souce address is always an address assigned to the interface,
+ * this also applies to proxies
+ */
+ if (ipv6_get_lladdr(dev, &na_saddr)) {
+ in6_dev_put(in6_dev);
+ return;
+ }
+ if (addr_type & IPV6_ADDR_UNICAST) {
+ neigh = neigh_event_ns(&nd_tbl, lladdr, saddr, dev);
+
+ if (neigh) {
+ ndisc_send_na(dev, neigh, saddr,
+ &na_saddr, &msg->target,
+ 0, 1, 0, 1);
+ neigh_release(neigh);
+ }
+ } else {
+ /* the proxy should also protect against DAD */
+ struct in6_addr maddr;
+ ipv6_addr_all_nodes(&maddr);
+ ndisc_send_na(dev, NULL, &maddr,
+ &na_saddr, &msg->target,
+ 0, 0, 0, 1);
}
} else {
struct sk_buff *n = skb_clone(skb, GFP_ATOMIC);
--
Ville Nuorvala
Research Assistant, Institute of Digital Communications,
Helsinki University of Technology
email: vnuorval@tml.hut.fi, phone: +358 (0)9 451 5257










-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

\
 
 \ /
  Last update: 2005-03-22 13:32    [W:0.213 / U:0.112 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site