netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Remi Denis-Courmont <rdenis@simphalempin.com>
To: David Miller <davem@davemloft.net>, yoshfuji@linux-ipv6.org
Cc: netdev@vger.kernel.org
Subject: [PATCH] IPv6: optionaly validate RAs on raw sockets
Date: Tue, 10 Jul 2007 21:11:17 +0300	[thread overview]
Message-ID: <200707102111.18824@auguste.remlab.net> (raw)

ICMPv6 Router Advertisements may now contain informations that is
mostly of interest to userland. This currently mostly consists of
recursive DNS server addresses (though one should expect other
stuff to come).

This patch adds a setsockopt to ICMPv6 sockets to only deliver Router
Advertisements if they pass the same set of checks as the kernel
IPv6 autoconfiguration does, so that userland can parse attributes it
is interested safely (otherwise, it would get and parse advertisements
that the kernel rejected).

N.B.: not too sure about the option name though...

Signed-off-by: Remi Denis-Courmont <rdenis@simphalempin.com>

diff --git a/include/linux/icmpv6.h b/include/linux/icmpv6.h
index 7c5e981..8c96822 100644
--- a/include/linux/icmpv6.h
+++ b/include/linux/icmpv6.h
@@ -139,6 +139,7 @@ static inline struct icmp6hdr *icmp6_hdr(const struct sk_buff *skb)
  */
 
 #define ICMPV6_FILTER			1
+#define ICMPV6_VALID_ADVERT		2
 
 /*
  *	ICMPV6 filter
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index 648bd1f..af72f02 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -343,7 +343,9 @@ struct ipv6_pinfo {
 struct raw6_sock {
 	/* inet_sock has to be the first member of raw6_sock */
 	struct inet_sock	inet;
-	__u32			checksum;	/* perform checksum */
+	__u16			unused;
+	__u8			valid_advert;	/* deliver valid RAs only */
+	__u8			checksum;	/* perform checksum */
 	__u32			offset;		/* checksum offset  */
 	struct icmp6_filter	filter;
 	/* ipv6_pinfo has to be the last member of raw6_sock, see inet6_sk_generic */
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index a58459a..da6cb50 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -127,12 +127,35 @@ static __inline__ int icmpv6_filter(struct sock *sk, struct sk_buff *skb)
 
 	if (pskb_may_pull(skb, sizeof(struct icmp6hdr))) {
 		__u32 *data = &rp->filter.data[0];
-		int bit_nr;
+		int type;
 
 		icmph = (struct icmp6hdr *) skb->data;
-		bit_nr = icmph->icmp6_type;
+		type = icmph->icmp6_type;
 
-		return (data[bit_nr >> 5] & (1 << (bit_nr & 31))) != 0;
+		if (data[type >> 5] & (1 << (type & 31)))
+			return 1;
+
+		/* Userland only wants valid router advertisements? */
+		if (type == NDISC_ROUTER_ADVERTISEMENT &&
+		    rp->valid_advert) {
+			struct inet6_dev *idev;
+
+			if (!pskb_may_pull(skb, sizeof(struct ra_msg)) ||
+			    !(ipv6_addr_type(&ipv6_hdr(skb)->saddr) &
+			      IPV6_ADDR_LINKLOCAL))
+				return 1;
+
+		        idev = in6_dev_get(skb->dev);
+		        if (!idev)
+		                return 1;
+
+			/* Ignore RA when routing */
+			if (idev->cnf.forwarding || !idev->cnf.accept_ra) {
+				in6_dev_put(idev);
+				return 1;
+			}
+			in6_dev_put(idev);
+		}
 	}
 	return 0;
 }
@@ -877,13 +900,26 @@ do_confirm:
 static int rawv6_seticmpfilter(struct sock *sk, int level, int optname,
 			       char __user *optval, int optlen)
 {
+	struct raw6_sock *rp = raw6_sk(sk);
+
 	switch (optname) {
 	case ICMPV6_FILTER:
 		if (optlen > sizeof(struct icmp6_filter))
 			optlen = sizeof(struct icmp6_filter);
-		if (copy_from_user(&raw6_sk(sk)->filter, optval, optlen))
+		if (copy_from_user(&rp->filter, optval, optlen))
 			return -EFAULT;
 		return 0;
+	case ICMPV6_VALID_ADVERT: {
+		int val;
+
+		if (optlen != sizeof(int))
+			return -EINVAL;
+		if (copy_from_user(&val, optval, sizeof(int)))
+			return -EFAULT;
+		/* -1 resets to default, which is actually 0 */
+		rp->valid_advert = (val > 0);
+		return 0;
+	}
 	default:
 		return -ENOPROTOOPT;
 	}
@@ -894,25 +930,38 @@ static int rawv6_seticmpfilter(struct sock *sk, int level, int optname,
 static int rawv6_geticmpfilter(struct sock *sk, int level, int optname,
 			       char __user *optval, int __user *optlen)
 {
+	struct raw6_sock *rp = raw6_sk(sk);
 	int len;
 
+	if (get_user(len, optlen))
+		return -EFAULT;
+	if (len < 0)
+		return -EINVAL;
+
 	switch (optname) {
 	case ICMPV6_FILTER:
-		if (get_user(len, optlen))
-			return -EFAULT;
-		if (len < 0)
-			return -EINVAL;
 		if (len > sizeof(struct icmp6_filter))
 			len = sizeof(struct icmp6_filter);
-		if (put_user(len, optlen))
+		if (copy_to_user(optval, &rp->filter, len))
 			return -EFAULT;
-		if (copy_to_user(optval, &raw6_sk(sk)->filter, len))
+		break;
+	case ICMPV6_VALID_ADVERT: {
+		int val;
+
+		if (len < sizeof(int))
+			return -EINVAL;
+		val = rp->valid_advert;
+		len = sizeof(int);
+		if (copy_to_user(optval, &val, sizeof(int)))
 			return -EFAULT;
-		return 0;
+		break;
+	}
 	default:
 		return -ENOPROTOOPT;
 	}
 
+	if (put_user(len, optlen))
+		return -EFAULT;
 	return 0;
 }
 

-- 
Rémi Denis-Courmont
http://www.remlab.net/

             reply	other threads:[~2007-07-10 18:11 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-07-10 18:11 Remi Denis-Courmont [this message]
2007-07-11 12:29 ` [PATCH] IPv6: optionaly validate RAs on raw sockets YOSHIFUJI Hideaki / 吉藤英明
2007-07-11 12:44   ` Rémi Denis-Courmont
2007-07-11 13:20     ` David Stevens
2007-07-11 14:10     ` Vlad Yasevich
2007-07-11 16:10       ` David Stevens
2007-07-11 16:19         ` Rémi Denis-Courmont
2007-07-11 16:50           ` Vlad Yasevich
2007-07-11 20:56           ` David Miller
2007-07-11 21:17             ` James Morris

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=200707102111.18824@auguste.remlab.net \
    --to=rdenis@simphalempin.com \
    --cc=davem@davemloft.net \
    --cc=netdev@vger.kernel.org \
    --cc=yoshfuji@linux-ipv6.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).