]> err.no Git - linux-2.6/blobdiff - net/ipv6/datagram.c
Merge branch 'for-linus' from kernel.org:/.../shaggy/jfs-2.6 manually
[linux-2.6] / net / ipv6 / datagram.c
index 832476bbc5cb9cee47c118bfa7d9224a4d17e693..cc518405b3e1efc29b87aea3cadb4e0c6d60068f 100644 (file)
@@ -175,10 +175,8 @@ ipv4_connected:
        if (final_p)
                ipv6_addr_copy(&fl.fl6_dst, final_p);
 
-       if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
-               dst_release(dst);
+       if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0)
                goto out;
-       }
 
        /* source address lookup done in ip6_dst_lookup */
 
@@ -390,6 +388,11 @@ int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb)
                put_cmsg(msg, SOL_IPV6, IPV6_HOPLIMIT, sizeof(hlim), &hlim);
        }
 
+       if (np->rxopt.bits.rxtclass) {
+               int tclass = (ntohl(*(u32 *)skb->nh.ipv6h) >> 20) & 0xff;
+               put_cmsg(msg, SOL_IPV6, IPV6_TCLASS, sizeof(tclass), &tclass);
+       }
+
        if (np->rxopt.bits.rxflow && (*(u32*)skb->nh.raw & IPV6_FLOWINFO_MASK)) {
                u32 flowinfo = *(u32*)skb->nh.raw & IPV6_FLOWINFO_MASK;
                put_cmsg(msg, SOL_IPV6, IPV6_FLOWINFO, sizeof(flowinfo), &flowinfo);
@@ -479,7 +482,7 @@ int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb)
 
 int datagram_send_ctl(struct msghdr *msg, struct flowi *fl,
                      struct ipv6_txoptions *opt,
-                     int *hlimit)
+                     int *hlimit, int *tclass)
 {
        struct in6_pktinfo *src_info;
        struct cmsghdr *cmsg;
@@ -682,6 +685,24 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl,
                        *hlimit = *(int *)CMSG_DATA(cmsg);
                        break;
 
+               case IPV6_TCLASS:
+                   {
+                       int tc;
+
+                       err = -EINVAL;
+                       if (cmsg->cmsg_len != CMSG_LEN(sizeof(int))) {
+                               goto exit_f;
+                       }
+
+                       tc = *(int *)CMSG_DATA(cmsg);
+                       if (tc < 0 || tc > 0xff)
+                               goto exit_f;
+
+                       err = 0;
+                       *tclass = tc;
+
+                       break;
+                   }
                default:
                        LIMIT_NETDEBUG(KERN_DEBUG "invalid cmsg type: %d\n",
                                       cmsg->cmsg_type);