* [PATCH 2/2] IPv6: strict address checks even on globals in ndisc
@ 2004-01-14 9:08 Ville Nuorvala
2004-01-22 6:34 ` David S. Miller
0 siblings, 1 reply; 2+ messages in thread
From: Ville Nuorvala @ 2004-01-14 9:08 UTC (permalink / raw)
To: davem; +Cc: netdev
[-- Attachment #1: Type: TEXT/PLAIN, Size: 923 bytes --]
Hi Dave,
the second part of my patchset contains fixes to the use of addresses in
neigbor discovery.
RFC 2461 requires that the source address of Neighbor Discovery messages
is an address assigned to the sending interface.
Duplicate Address Detection should also be interface specific. We don't,
for exaple, want a node to DoS itself just because it has two interfaces
on the same link and both happen to listen to the same multicast group. If
there is a true duplicate on the link, the interface doing DAD will notice
it anyway.
The attached patch adds a "strict" parameter to ip6_chk_addr() and
ip6_get_ifaddr() to allow link-local protocols like ND and DAD to do
strict address checks even on addresses with greater scope than
link-local.
Thanks,
Ville
--
Ville Nuorvala
Research Assistant, Institute of Digital Communications,
Helsinki University of Technology
email: vnuorval@tcs.hut.fi, phone: +358 (0)9 451 5257
[-- Attachment #2: Type: TEXT/PLAIN, Size: 7981 bytes --]
# 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.1514 -> 1.1515
# net/ipv6/anycast.c 1.9 -> 1.10
# net/ipv6/ip6_tunnel.c 1.15 -> 1.16
# net/ipv6/datagram.c 1.12 -> 1.13
# net/ipv6/icmp.c 1.45 -> 1.46
# net/ipv6/raw.c 1.46 -> 1.47
# net/ipv6/af_inet6.c 1.58 -> 1.59
# net/ipv6/ndisc.c 1.60 -> 1.61
# net/sctp/ipv6.c 1.49 -> 1.50
# include/net/addrconf.h 1.11 -> 1.12
# net/ipv6/addrconf.c 1.79 -> 1.80
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 04/01/13 vnuorval@amber.hut.mediapoli.com 1.1515
# Do strict (interface specific) address checks in ipv6_chk_addr() and ipv6_get_ifaddr() when
# doing Neighbor Discovery. This is required by the specification when selecting a source
# address for ND messages, and seems logical when doing DAD (for example on a multihomed node).
# --------------------------------------------
#
diff -Nru a/include/net/addrconf.h b/include/net/addrconf.h
--- a/include/net/addrconf.h Tue Jan 13 21:02:08 2004
+++ b/include/net/addrconf.h Tue Jan 13 21:02:08 2004
@@ -59,9 +59,11 @@
extern int addrconf_set_dstaddr(void *arg);
extern int ipv6_chk_addr(struct in6_addr *addr,
- struct net_device *dev);
+ struct net_device *dev,
+ int strict);
extern struct inet6_ifaddr * ipv6_get_ifaddr(struct in6_addr *addr,
- struct net_device *dev);
+ struct net_device *dev,
+ int strict);
extern int ipv6_get_saddr(struct dst_entry *dst,
struct in6_addr *daddr,
struct in6_addr *saddr);
diff -Nru a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
--- a/net/ipv6/addrconf.c Tue Jan 13 21:02:08 2004
+++ b/net/ipv6/addrconf.c Tue Jan 13 21:02:08 2004
@@ -904,7 +904,7 @@
return cnt;
}
-int ipv6_chk_addr(struct in6_addr *addr, struct net_device *dev)
+int ipv6_chk_addr(struct in6_addr *addr, struct net_device *dev, int strict)
{
struct inet6_ifaddr * ifp;
u8 hash = ipv6_addr_hash(addr);
@@ -914,7 +914,7 @@
if (ipv6_addr_cmp(&ifp->addr, addr) == 0 &&
!(ifp->flags&IFA_F_TENTATIVE)) {
if (dev == NULL || ifp->idev->dev == dev ||
- !(ifp->scope&(IFA_LINK|IFA_HOST)))
+ !(ifp->scope&(IFA_LINK|IFA_HOST) || strict))
break;
}
}
@@ -939,7 +939,7 @@
return ifp != NULL;
}
-struct inet6_ifaddr * ipv6_get_ifaddr(struct in6_addr *addr, struct net_device *dev)
+struct inet6_ifaddr * ipv6_get_ifaddr(struct in6_addr *addr, struct net_device *dev, int strict)
{
struct inet6_ifaddr * ifp;
u8 hash = ipv6_addr_hash(addr);
@@ -948,7 +948,7 @@
for(ifp = inet6_addr_lst[hash]; ifp; ifp=ifp->lst_next) {
if (ipv6_addr_cmp(&ifp->addr, addr) == 0) {
if (dev == NULL || ifp->idev->dev == dev ||
- !(ifp->scope&(IFA_LINK|IFA_HOST))) {
+ !(ifp->scope&(IFA_LINK|IFA_HOST) || strict)) {
in6_ifa_hold(ifp);
break;
}
@@ -1387,7 +1387,7 @@
ok:
- ifp = ipv6_get_ifaddr(&addr, dev);
+ ifp = ipv6_get_ifaddr(&addr, dev, 1);
if (ifp == NULL && valid_lft) {
/* Do not allow to create too much of autoconfigured
@@ -2830,7 +2830,7 @@
if (!ipv6_addr_any(&addr))
ipv6_dev_ac_dec(ifp->idev->dev, &addr);
}
- if (!ipv6_chk_addr(&ifp->addr, NULL))
+ if (!ipv6_chk_addr(&ifp->addr, ifp->idev->dev, 1))
ip6_rt_addr_del(&ifp->addr, ifp->idev->dev);
break;
}
diff -Nru a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
--- a/net/ipv6/af_inet6.c Tue Jan 13 21:02:08 2004
+++ b/net/ipv6/af_inet6.c Tue Jan 13 21:02:08 2004
@@ -355,7 +355,7 @@
*/
v4addr = LOOPBACK4_IPV6;
if (!(addr_type & IPV6_ADDR_MULTICAST)) {
- if (!ipv6_chk_addr(&addr->sin6_addr, dev)) {
+ if (!ipv6_chk_addr(&addr->sin6_addr, dev, 0)) {
if (dev)
dev_put(dev);
err = -EADDRNOTAVAIL;
diff -Nru a/net/ipv6/anycast.c b/net/ipv6/anycast.c
--- a/net/ipv6/anycast.c Tue Jan 13 21:02:08 2004
+++ b/net/ipv6/anycast.c Tue Jan 13 21:02:08 2004
@@ -113,7 +113,7 @@
return -EPERM;
if (ipv6_addr_type(addr) & IPV6_ADDR_MULTICAST)
return -EINVAL;
- if (ipv6_chk_addr(addr, NULL))
+ if (ipv6_chk_addr(addr, NULL, 0))
return -EINVAL;
pac = sock_kmalloc(sk, sizeof(struct ipv6_ac_socklist), GFP_KERNEL);
diff -Nru a/net/ipv6/datagram.c b/net/ipv6/datagram.c
--- a/net/ipv6/datagram.c Tue Jan 13 21:02:08 2004
+++ b/net/ipv6/datagram.c Tue Jan 13 21:02:08 2004
@@ -307,7 +307,7 @@
return -ENODEV;
}
}
- if (!ipv6_chk_addr(&src_info->ipi6_addr, dev)) {
+ if (!ipv6_chk_addr(&src_info->ipi6_addr, dev, 0)) {
if (dev)
dev_put(dev);
err = -EINVAL;
diff -Nru a/net/ipv6/icmp.c b/net/ipv6/icmp.c
--- a/net/ipv6/icmp.c Tue Jan 13 21:02:08 2004
+++ b/net/ipv6/icmp.c Tue Jan 13 21:02:08 2004
@@ -298,7 +298,7 @@
*/
addr_type = ipv6_addr_type(&hdr->daddr);
- if (ipv6_chk_addr(&hdr->daddr, skb->dev))
+ if (ipv6_chk_addr(&hdr->daddr, skb->dev, 0))
saddr = &hdr->daddr;
/*
diff -Nru a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
--- a/net/ipv6/ip6_tunnel.c Tue Jan 13 21:02:08 2004
+++ b/net/ipv6/ip6_tunnel.c Tue Jan 13 21:02:08 2004
@@ -777,10 +777,10 @@
if (p->link)
ldev = dev_get_by_index(p->link);
- if ((ltype&IPV6_ADDR_UNICAST) && !ipv6_chk_addr(laddr, ldev))
+ if (ltype&IPV6_ADDR_UNICAST && !ipv6_chk_addr(laddr, ldev, 0))
l_ok = 0;
- if ((rtype&IPV6_ADDR_UNICAST) && ipv6_chk_addr(raddr, NULL))
+ if (rtype&IPV6_ADDR_UNICAST && ipv6_chk_addr(raddr, NULL, 0))
r_ok = 0;
if (l_ok && r_ok) {
diff -Nru a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
--- a/net/ipv6/ndisc.c Tue Jan 13 21:02:08 2004
+++ b/net/ipv6/ndisc.c Tue Jan 13 21:02:08 2004
@@ -434,7 +434,7 @@
len = sizeof(struct icmp6hdr) + sizeof(struct in6_addr);
/* for anycast or proxy, solicited_addr != src_addr */
- ifp = ipv6_get_ifaddr(solicited_addr, dev);
+ ifp = ipv6_get_ifaddr(solicited_addr, dev, 1);
if (ifp) {
src_addr = solicited_addr;
in6_ifa_put(ifp);
@@ -680,7 +680,7 @@
struct in6_addr *target = (struct in6_addr *)&neigh->primary_key;
int probes = atomic_read(&neigh->probes);
- if (skb && ipv6_chk_addr(&skb->nh.ipv6h->saddr, dev))
+ if (skb && ipv6_chk_addr(&skb->nh.ipv6h->saddr, dev, 1))
saddr = &skb->nh.ipv6h->saddr;
if ((probes -= neigh->parms->ucast_probes) < 0) {
@@ -758,7 +758,7 @@
}
}
- if ((ifp = ipv6_get_ifaddr(&msg->target, dev)) != NULL) {
+ if ((ifp = ipv6_get_ifaddr(&msg->target, dev, 1)) != NULL) {
if (ifp->flags & IFA_F_TENTATIVE) {
/* Address is tentative. If the source
is unspecified address, it is someone
@@ -955,7 +955,7 @@
return;
}
}
- if ((ifp = ipv6_get_ifaddr(&msg->target, dev))) {
+ if ((ifp = ipv6_get_ifaddr(&msg->target, dev, 1))) {
if (ifp->flags & IFA_F_TENTATIVE) {
addrconf_dad_failure(ifp);
return;
diff -Nru a/net/ipv6/raw.c b/net/ipv6/raw.c
--- a/net/ipv6/raw.c Tue Jan 13 21:02:08 2004
+++ b/net/ipv6/raw.c Tue Jan 13 21:02:08 2004
@@ -227,7 +227,7 @@
v4addr = LOOPBACK4_IPV6;
if (!(addr_type & IPV6_ADDR_MULTICAST)) {
err = -EADDRNOTAVAIL;
- if (!ipv6_chk_addr(&addr->sin6_addr, dev)) {
+ if (!ipv6_chk_addr(&addr->sin6_addr, dev, 0)) {
if (dev)
dev_put(dev);
goto out;
diff -Nru a/net/sctp/ipv6.c b/net/sctp/ipv6.c
--- a/net/sctp/ipv6.c Tue Jan 13 21:02:08 2004
+++ b/net/sctp/ipv6.c Tue Jan 13 21:02:08 2004
@@ -510,7 +510,7 @@
if (!(type & IPV6_ADDR_UNICAST))
return 0;
- return ipv6_chk_addr(in6, NULL);
+ return ipv6_chk_addr(in6, NULL, 0);
}
/* This function checks if the address is a valid address to be used for
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH 2/2] IPv6: strict address checks even on globals in ndisc
2004-01-14 9:08 [PATCH 2/2] IPv6: strict address checks even on globals in ndisc Ville Nuorvala
@ 2004-01-22 6:34 ` David S. Miller
0 siblings, 0 replies; 2+ messages in thread
From: David S. Miller @ 2004-01-22 6:34 UTC (permalink / raw)
To: Ville Nuorvala; +Cc: netdev
On Wed, 14 Jan 2004 11:08:04 +0200 (EET)
Ville Nuorvala <vnuorval@tcs.hut.fi> wrote:
> The attached patch adds a "strict" parameter to ip6_chk_addr() and
> ip6_get_ifaddr() to allow link-local protocols like ND and DAD to do
> strict address checks even on addresses with greater scope than
> link-local.
Looks fine, applied.
Thanks Ville.
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2004-01-22 6:34 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-01-14 9:08 [PATCH 2/2] IPv6: strict address checks even on globals in ndisc Ville Nuorvala
2004-01-22 6:34 ` David S. Miller
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).