]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - net/ipv6/raw.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/penberg...
[mv-sheeva.git] / net / ipv6 / raw.c
index 059298baa1dd696ad491b1d01deeda3759ba0e88..396f0ea11090a98d6a07898d0e79d58fb7652313 100644 (file)
@@ -357,8 +357,10 @@ void raw6_icmp_error(struct sk_buff *skb, int nexthdr,
        read_lock(&raw_v6_hashinfo.lock);
        sk = sk_head(&raw_v6_hashinfo.ht[hash]);
        if (sk != NULL) {
-               saddr = &ipv6_hdr(skb)->saddr;
-               daddr = &ipv6_hdr(skb)->daddr;
+               /* Note: ipv6_hdr(skb) != skb->data */
+               struct ipv6hdr *ip6h = (struct ipv6hdr *)skb->data;
+               saddr = &ip6h->saddr;
+               daddr = &ip6h->daddr;
                net = dev_net(skb->dev);
 
                while ((sk = __raw_v6_lookup(net, sk, nexthdr, saddr, daddr,
@@ -969,6 +971,19 @@ static int do_rawv6_setsockopt(struct sock *sk, int level, int optname,
 
        switch (optname) {
                case IPV6_CHECKSUM:
+                       if (inet_sk(sk)->num == IPPROTO_ICMPV6 &&
+                           level == IPPROTO_IPV6) {
+                               /*
+                                * RFC3542 tells that IPV6_CHECKSUM socket
+                                * option in the IPPROTO_IPV6 level is not
+                                * allowed on ICMPv6 sockets.
+                                * If you want to set it, use IPPROTO_RAW
+                                * level IPV6_CHECKSUM socket option
+                                * (Linux extension).
+                                */
+                               return -EINVAL;
+                       }
+
                        /* You may get strange result with a positive odd offset;
                           RFC2292bis agrees with me. */
                        if (val > 0 && (val&1))
@@ -1044,6 +1059,11 @@ static int do_rawv6_getsockopt(struct sock *sk, int level, int optname,
 
        switch (optname) {
        case IPV6_CHECKSUM:
+               /*
+                * We allow getsockopt() for IPPROTO_IPV6-level
+                * IPV6_CHECKSUM socket option on ICMPv6 sockets
+                * since RFC3542 is silent about it.
+                */
                if (rp->checksum == 0)
                        val = -1;
                else