Loading include/linux/in6.h +30 −6 Original line number Diff line number Diff line Loading @@ -148,13 +148,13 @@ struct in6_flowlabel_req */ #define IPV6_ADDRFORM 1 #define IPV6_PKTINFO 2 #define IPV6_HOPOPTS 3 #define IPV6_DSTOPTS 4 #define IPV6_RTHDR 5 #define IPV6_PKTOPTIONS 6 #define IPV6_2292PKTINFO 2 #define IPV6_2292HOPOPTS 3 #define IPV6_2292DSTOPTS 4 #define IPV6_2292RTHDR 5 #define IPV6_2292PKTOPTIONS 6 #define IPV6_CHECKSUM 7 #define IPV6_HOPLIMIT 8 #define IPV6_2292HOPLIMIT 8 #define IPV6_NEXTHOP 9 #define IPV6_AUTHHDR 10 /* obsolete */ #define IPV6_FLOWINFO 11 Loading Loading @@ -198,4 +198,28 @@ struct in6_flowlabel_req * MCAST_MSFILTER 48 */ /* RFC3542 advanced socket options (50-67) */ #define IPV6_RECVPKTINFO 50 #define IPV6_PKTINFO 51 #if 0 #define IPV6_RECVPATHMTU 52 #define IPV6_PATHMTU 53 #define IPV6_DONTFRAG 54 #define IPV6_USE_MIN_MTU 55 #endif #define IPV6_RECVHOPOPTS 56 #define IPV6_HOPOPTS 57 #if 0 #define IPV6_RECVRTHDRDSTOPTS 58 /* Unused, see net/ipv6/datagram.c */ #endif #define IPV6_RTHDRDSTOPTS 59 #define IPV6_RECVRTHDR 60 #define IPV6_RTHDR 61 #define IPV6_RECVDSTOPTS 62 #define IPV6_DSTOPTS 63 #define IPV6_RECVHOPLIMIT 64 #define IPV6_HOPLIMIT 65 #define IPV6_RECVTCLASS 66 #define IPV6_TCLASS 67 #endif include/linux/ipv6.h +12 −3 Original line number Diff line number Diff line Loading @@ -189,6 +189,7 @@ struct inet6_skb_parm { __u16 dst0; __u16 srcrt; __u16 dst1; __u16 lastopt; }; #define IP6CB(skb) ((struct inet6_skb_parm*)((skb)->cb)) Loading Loading @@ -234,14 +235,20 @@ struct ipv6_pinfo { /* pktoption flags */ union { struct { __u8 srcrt:2, __u16 srcrt:2, osrcrt:2, rxinfo:1, rxoinfo:1, rxhlim:1, rxohlim:1, hopopts:1, ohopopts:1, dstopts:1, rxflow:1; odstopts:1, rxflow:1, rxtclass:1; } bits; __u8 all; __u16 all; } rxopt; /* sockopt flags */ Loading @@ -250,6 +257,7 @@ struct ipv6_pinfo { sndflow:1, pmtudisc:2, ipv6only:1; __u8 tclass; __u32 dst_cookie; Loading @@ -263,6 +271,7 @@ struct ipv6_pinfo { struct ipv6_txoptions *opt; struct rt6_info *rt; int hop_limit; int tclass; } cork; }; Loading include/net/ipv6.h +5 −0 Original line number Diff line number Diff line Loading @@ -233,6 +233,10 @@ extern int ip6_ra_control(struct sock *sk, int sel, extern int ipv6_parse_hopopts(struct sk_buff *skb, int); extern struct ipv6_txoptions * ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt); extern struct ipv6_txoptions * ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt, int newtype, struct ipv6_opt_hdr __user *newopt, int newoptlen); extern int ip6_frag_nqueues; extern atomic_t ip6_frag_mem; Loading Loading @@ -373,6 +377,7 @@ extern int ip6_append_data(struct sock *sk, int length, int transhdrlen, int hlimit, int tclass, struct ipv6_txoptions *opt, struct flowi *fl, struct rt6_info *rt, Loading include/net/transp_v6.h +1 −1 Original line number Diff line number Diff line Loading @@ -37,7 +37,7 @@ extern int datagram_recv_ctl(struct sock *sk, extern int datagram_send_ctl(struct msghdr *msg, struct flowi *fl, struct ipv6_txoptions *opt, int *hlimit); int *hlimit, int *tclass); #define LOOPBACK4_IPV6 __constant_htonl(0x7f000006) Loading net/ipv6/datagram.c +126 −9 Original line number Diff line number Diff line Loading @@ -390,32 +390,101 @@ 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); } /* HbH is allowed only once */ if (np->rxopt.bits.hopopts && opt->hop) { u8 *ptr = skb->nh.raw + opt->hop; put_cmsg(msg, SOL_IPV6, IPV6_HOPOPTS, (ptr[1]+1)<<3, ptr); } if (np->rxopt.bits.dstopts && opt->dst0) { if (opt->lastopt && (np->rxopt.bits.dstopts || np->rxopt.bits.srcrt)) { /* * Silly enough, but we need to reparse in order to * report extension headers (except for HbH) * in order. * * Also note that IPV6_RECVRTHDRDSTOPTS is NOT * (and WILL NOT be) defined because * IPV6_RECVDSTOPTS is more generic. --yoshfuji */ unsigned int off = sizeof(struct ipv6hdr); u8 nexthdr = skb->nh.ipv6h->nexthdr; while (off <= opt->lastopt) { unsigned len; u8 *ptr = skb->nh.raw + off; switch(nexthdr) { case IPPROTO_DSTOPTS: nexthdr = ptr[0]; len = (ptr[1] + 1) << 3; if (np->rxopt.bits.dstopts) put_cmsg(msg, SOL_IPV6, IPV6_DSTOPTS, len, ptr); break; case IPPROTO_ROUTING: nexthdr = ptr[0]; len = (ptr[1] + 1) << 3; if (np->rxopt.bits.srcrt) put_cmsg(msg, SOL_IPV6, IPV6_RTHDR, len, ptr); break; case IPPROTO_AH: nexthdr = ptr[0]; len = (ptr[1] + 1) << 2; break; default: nexthdr = ptr[0]; len = (ptr[1] + 1) << 3; break; } off += len; } } /* socket options in old style */ if (np->rxopt.bits.rxoinfo) { struct in6_pktinfo src_info; src_info.ipi6_ifindex = opt->iif; ipv6_addr_copy(&src_info.ipi6_addr, &skb->nh.ipv6h->daddr); put_cmsg(msg, SOL_IPV6, IPV6_2292PKTINFO, sizeof(src_info), &src_info); } if (np->rxopt.bits.rxohlim) { int hlim = skb->nh.ipv6h->hop_limit; put_cmsg(msg, SOL_IPV6, IPV6_2292HOPLIMIT, sizeof(hlim), &hlim); } if (np->rxopt.bits.ohopopts && opt->hop) { u8 *ptr = skb->nh.raw + opt->hop; put_cmsg(msg, SOL_IPV6, IPV6_2292HOPOPTS, (ptr[1]+1)<<3, ptr); } if (np->rxopt.bits.odstopts && opt->dst0) { u8 *ptr = skb->nh.raw + opt->dst0; put_cmsg(msg, SOL_IPV6, IPV6_DSTOPTS, (ptr[1]+1)<<3, ptr); put_cmsg(msg, SOL_IPV6, IPV6_2292DSTOPTS, (ptr[1]+1)<<3, ptr); } if (np->rxopt.bits.srcrt && opt->srcrt) { if (np->rxopt.bits.osrcrt && opt->srcrt) { struct ipv6_rt_hdr *rthdr = (struct ipv6_rt_hdr *)(skb->nh.raw + opt->srcrt); put_cmsg(msg, SOL_IPV6, IPV6_RTHDR, (rthdr->hdrlen+1) << 3, rthdr); put_cmsg(msg, SOL_IPV6, IPV6_2292RTHDR, (rthdr->hdrlen+1) << 3, rthdr); } if (np->rxopt.bits.dstopts && opt->dst1) { if (np->rxopt.bits.odstopts && opt->dst1) { u8 *ptr = skb->nh.raw + opt->dst1; put_cmsg(msg, SOL_IPV6, IPV6_DSTOPTS, (ptr[1]+1)<<3, ptr); put_cmsg(msg, SOL_IPV6, IPV6_2292DSTOPTS, (ptr[1]+1)<<3, ptr); } return 0; } 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; Loading @@ -438,6 +507,7 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl, switch (cmsg->cmsg_type) { case IPV6_PKTINFO: case IPV6_2292PKTINFO: if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct in6_pktinfo))) { err = -EINVAL; goto exit_f; Loading Loading @@ -492,6 +562,7 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl, fl->fl6_flowlabel = IPV6_FLOWINFO_MASK & *(u32 *)CMSG_DATA(cmsg); break; case IPV6_2292HOPOPTS: case IPV6_HOPOPTS: if (opt->hopopt || cmsg->cmsg_len < CMSG_LEN(sizeof(struct ipv6_opt_hdr))) { err = -EINVAL; Loading @@ -512,7 +583,7 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl, opt->hopopt = hdr; break; case IPV6_DSTOPTS: case IPV6_2292DSTOPTS: if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct ipv6_opt_hdr))) { err = -EINVAL; goto exit_f; Loading @@ -536,6 +607,33 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl, opt->dst1opt = hdr; break; case IPV6_DSTOPTS: case IPV6_RTHDRDSTOPTS: if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct ipv6_opt_hdr))) { err = -EINVAL; goto exit_f; } hdr = (struct ipv6_opt_hdr *)CMSG_DATA(cmsg); len = ((hdr->hdrlen + 1) << 3); if (cmsg->cmsg_len < CMSG_LEN(len)) { err = -EINVAL; goto exit_f; } if (!capable(CAP_NET_RAW)) { err = -EPERM; goto exit_f; } if (cmsg->cmsg_type == IPV6_DSTOPTS) { opt->opt_flen += len; opt->dst1opt = hdr; } else { opt->opt_nflen += len; opt->dst0opt = hdr; } break; case IPV6_2292RTHDR: case IPV6_RTHDR: if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct ipv6_rt_hdr))) { err = -EINVAL; Loading Loading @@ -568,7 +666,7 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl, opt->opt_nflen += len; opt->srcrt = rthdr; if (opt->dst1opt) { if (cmsg->cmsg_type == IPV6_2292RTHDR && opt->dst1opt) { int dsthdrlen = ((opt->dst1opt->hdrlen+1)<<3); opt->opt_nflen += dsthdrlen; Loading @@ -579,6 +677,7 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl, break; case IPV6_2292HOPLIMIT: case IPV6_HOPLIMIT: if (cmsg->cmsg_len != CMSG_LEN(sizeof(int))) { err = -EINVAL; Loading @@ -588,6 +687,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); Loading Loading
include/linux/in6.h +30 −6 Original line number Diff line number Diff line Loading @@ -148,13 +148,13 @@ struct in6_flowlabel_req */ #define IPV6_ADDRFORM 1 #define IPV6_PKTINFO 2 #define IPV6_HOPOPTS 3 #define IPV6_DSTOPTS 4 #define IPV6_RTHDR 5 #define IPV6_PKTOPTIONS 6 #define IPV6_2292PKTINFO 2 #define IPV6_2292HOPOPTS 3 #define IPV6_2292DSTOPTS 4 #define IPV6_2292RTHDR 5 #define IPV6_2292PKTOPTIONS 6 #define IPV6_CHECKSUM 7 #define IPV6_HOPLIMIT 8 #define IPV6_2292HOPLIMIT 8 #define IPV6_NEXTHOP 9 #define IPV6_AUTHHDR 10 /* obsolete */ #define IPV6_FLOWINFO 11 Loading Loading @@ -198,4 +198,28 @@ struct in6_flowlabel_req * MCAST_MSFILTER 48 */ /* RFC3542 advanced socket options (50-67) */ #define IPV6_RECVPKTINFO 50 #define IPV6_PKTINFO 51 #if 0 #define IPV6_RECVPATHMTU 52 #define IPV6_PATHMTU 53 #define IPV6_DONTFRAG 54 #define IPV6_USE_MIN_MTU 55 #endif #define IPV6_RECVHOPOPTS 56 #define IPV6_HOPOPTS 57 #if 0 #define IPV6_RECVRTHDRDSTOPTS 58 /* Unused, see net/ipv6/datagram.c */ #endif #define IPV6_RTHDRDSTOPTS 59 #define IPV6_RECVRTHDR 60 #define IPV6_RTHDR 61 #define IPV6_RECVDSTOPTS 62 #define IPV6_DSTOPTS 63 #define IPV6_RECVHOPLIMIT 64 #define IPV6_HOPLIMIT 65 #define IPV6_RECVTCLASS 66 #define IPV6_TCLASS 67 #endif
include/linux/ipv6.h +12 −3 Original line number Diff line number Diff line Loading @@ -189,6 +189,7 @@ struct inet6_skb_parm { __u16 dst0; __u16 srcrt; __u16 dst1; __u16 lastopt; }; #define IP6CB(skb) ((struct inet6_skb_parm*)((skb)->cb)) Loading Loading @@ -234,14 +235,20 @@ struct ipv6_pinfo { /* pktoption flags */ union { struct { __u8 srcrt:2, __u16 srcrt:2, osrcrt:2, rxinfo:1, rxoinfo:1, rxhlim:1, rxohlim:1, hopopts:1, ohopopts:1, dstopts:1, rxflow:1; odstopts:1, rxflow:1, rxtclass:1; } bits; __u8 all; __u16 all; } rxopt; /* sockopt flags */ Loading @@ -250,6 +257,7 @@ struct ipv6_pinfo { sndflow:1, pmtudisc:2, ipv6only:1; __u8 tclass; __u32 dst_cookie; Loading @@ -263,6 +271,7 @@ struct ipv6_pinfo { struct ipv6_txoptions *opt; struct rt6_info *rt; int hop_limit; int tclass; } cork; }; Loading
include/net/ipv6.h +5 −0 Original line number Diff line number Diff line Loading @@ -233,6 +233,10 @@ extern int ip6_ra_control(struct sock *sk, int sel, extern int ipv6_parse_hopopts(struct sk_buff *skb, int); extern struct ipv6_txoptions * ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt); extern struct ipv6_txoptions * ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt, int newtype, struct ipv6_opt_hdr __user *newopt, int newoptlen); extern int ip6_frag_nqueues; extern atomic_t ip6_frag_mem; Loading Loading @@ -373,6 +377,7 @@ extern int ip6_append_data(struct sock *sk, int length, int transhdrlen, int hlimit, int tclass, struct ipv6_txoptions *opt, struct flowi *fl, struct rt6_info *rt, Loading
include/net/transp_v6.h +1 −1 Original line number Diff line number Diff line Loading @@ -37,7 +37,7 @@ extern int datagram_recv_ctl(struct sock *sk, extern int datagram_send_ctl(struct msghdr *msg, struct flowi *fl, struct ipv6_txoptions *opt, int *hlimit); int *hlimit, int *tclass); #define LOOPBACK4_IPV6 __constant_htonl(0x7f000006) Loading
net/ipv6/datagram.c +126 −9 Original line number Diff line number Diff line Loading @@ -390,32 +390,101 @@ 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); } /* HbH is allowed only once */ if (np->rxopt.bits.hopopts && opt->hop) { u8 *ptr = skb->nh.raw + opt->hop; put_cmsg(msg, SOL_IPV6, IPV6_HOPOPTS, (ptr[1]+1)<<3, ptr); } if (np->rxopt.bits.dstopts && opt->dst0) { if (opt->lastopt && (np->rxopt.bits.dstopts || np->rxopt.bits.srcrt)) { /* * Silly enough, but we need to reparse in order to * report extension headers (except for HbH) * in order. * * Also note that IPV6_RECVRTHDRDSTOPTS is NOT * (and WILL NOT be) defined because * IPV6_RECVDSTOPTS is more generic. --yoshfuji */ unsigned int off = sizeof(struct ipv6hdr); u8 nexthdr = skb->nh.ipv6h->nexthdr; while (off <= opt->lastopt) { unsigned len; u8 *ptr = skb->nh.raw + off; switch(nexthdr) { case IPPROTO_DSTOPTS: nexthdr = ptr[0]; len = (ptr[1] + 1) << 3; if (np->rxopt.bits.dstopts) put_cmsg(msg, SOL_IPV6, IPV6_DSTOPTS, len, ptr); break; case IPPROTO_ROUTING: nexthdr = ptr[0]; len = (ptr[1] + 1) << 3; if (np->rxopt.bits.srcrt) put_cmsg(msg, SOL_IPV6, IPV6_RTHDR, len, ptr); break; case IPPROTO_AH: nexthdr = ptr[0]; len = (ptr[1] + 1) << 2; break; default: nexthdr = ptr[0]; len = (ptr[1] + 1) << 3; break; } off += len; } } /* socket options in old style */ if (np->rxopt.bits.rxoinfo) { struct in6_pktinfo src_info; src_info.ipi6_ifindex = opt->iif; ipv6_addr_copy(&src_info.ipi6_addr, &skb->nh.ipv6h->daddr); put_cmsg(msg, SOL_IPV6, IPV6_2292PKTINFO, sizeof(src_info), &src_info); } if (np->rxopt.bits.rxohlim) { int hlim = skb->nh.ipv6h->hop_limit; put_cmsg(msg, SOL_IPV6, IPV6_2292HOPLIMIT, sizeof(hlim), &hlim); } if (np->rxopt.bits.ohopopts && opt->hop) { u8 *ptr = skb->nh.raw + opt->hop; put_cmsg(msg, SOL_IPV6, IPV6_2292HOPOPTS, (ptr[1]+1)<<3, ptr); } if (np->rxopt.bits.odstopts && opt->dst0) { u8 *ptr = skb->nh.raw + opt->dst0; put_cmsg(msg, SOL_IPV6, IPV6_DSTOPTS, (ptr[1]+1)<<3, ptr); put_cmsg(msg, SOL_IPV6, IPV6_2292DSTOPTS, (ptr[1]+1)<<3, ptr); } if (np->rxopt.bits.srcrt && opt->srcrt) { if (np->rxopt.bits.osrcrt && opt->srcrt) { struct ipv6_rt_hdr *rthdr = (struct ipv6_rt_hdr *)(skb->nh.raw + opt->srcrt); put_cmsg(msg, SOL_IPV6, IPV6_RTHDR, (rthdr->hdrlen+1) << 3, rthdr); put_cmsg(msg, SOL_IPV6, IPV6_2292RTHDR, (rthdr->hdrlen+1) << 3, rthdr); } if (np->rxopt.bits.dstopts && opt->dst1) { if (np->rxopt.bits.odstopts && opt->dst1) { u8 *ptr = skb->nh.raw + opt->dst1; put_cmsg(msg, SOL_IPV6, IPV6_DSTOPTS, (ptr[1]+1)<<3, ptr); put_cmsg(msg, SOL_IPV6, IPV6_2292DSTOPTS, (ptr[1]+1)<<3, ptr); } return 0; } 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; Loading @@ -438,6 +507,7 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl, switch (cmsg->cmsg_type) { case IPV6_PKTINFO: case IPV6_2292PKTINFO: if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct in6_pktinfo))) { err = -EINVAL; goto exit_f; Loading Loading @@ -492,6 +562,7 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl, fl->fl6_flowlabel = IPV6_FLOWINFO_MASK & *(u32 *)CMSG_DATA(cmsg); break; case IPV6_2292HOPOPTS: case IPV6_HOPOPTS: if (opt->hopopt || cmsg->cmsg_len < CMSG_LEN(sizeof(struct ipv6_opt_hdr))) { err = -EINVAL; Loading @@ -512,7 +583,7 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl, opt->hopopt = hdr; break; case IPV6_DSTOPTS: case IPV6_2292DSTOPTS: if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct ipv6_opt_hdr))) { err = -EINVAL; goto exit_f; Loading @@ -536,6 +607,33 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl, opt->dst1opt = hdr; break; case IPV6_DSTOPTS: case IPV6_RTHDRDSTOPTS: if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct ipv6_opt_hdr))) { err = -EINVAL; goto exit_f; } hdr = (struct ipv6_opt_hdr *)CMSG_DATA(cmsg); len = ((hdr->hdrlen + 1) << 3); if (cmsg->cmsg_len < CMSG_LEN(len)) { err = -EINVAL; goto exit_f; } if (!capable(CAP_NET_RAW)) { err = -EPERM; goto exit_f; } if (cmsg->cmsg_type == IPV6_DSTOPTS) { opt->opt_flen += len; opt->dst1opt = hdr; } else { opt->opt_nflen += len; opt->dst0opt = hdr; } break; case IPV6_2292RTHDR: case IPV6_RTHDR: if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct ipv6_rt_hdr))) { err = -EINVAL; Loading Loading @@ -568,7 +666,7 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl, opt->opt_nflen += len; opt->srcrt = rthdr; if (opt->dst1opt) { if (cmsg->cmsg_type == IPV6_2292RTHDR && opt->dst1opt) { int dsthdrlen = ((opt->dst1opt->hdrlen+1)<<3); opt->opt_nflen += dsthdrlen; Loading @@ -579,6 +677,7 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl, break; case IPV6_2292HOPLIMIT: case IPV6_HOPLIMIT: if (cmsg->cmsg_len != CMSG_LEN(sizeof(int))) { err = -EINVAL; Loading @@ -588,6 +687,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); Loading