}  if (np->rxopt.bits.rxtclass) { int tclass = (ntohl(*(u32 *)skb->nh.ipv6h) >> 20) & 0xff; put_cmsg(msg, SOL_IPV6, IPV6_TCLASS, sizeof(tclass), &tclass); 
int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb){	struct ipv6_pinfo *np = inet6_sk(sk);	struct inet6_skb_parm *opt = IP6CB(skb);	if (np->rxopt.bits.rxinfo) {		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_PKTINFO, sizeof(src_info), &src_info);	}	if (np->rxopt.bits.rxhlim) {		int hlim = skb->nh.ipv6h->hop_limit;		put_cmsg(msg, SOL_IPV6, IPV6_HOPLIMIT, sizeof(hlim), &hlim);	}	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 (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_2292DSTOPTS, (ptr[1]+1)<<3, ptr);	}	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_2292RTHDR, (rthdr->hdrlen+1) << 3, rthdr);	}	if (np->rxopt.bits.odstopts && opt->dst1) {		u8 *ptr = skb->nh.raw + opt->dst1;		put_cmsg(msg, SOL_IPV6, IPV6_2292DSTOPTS, (ptr[1]+1)<<3, ptr);	}	return 0;}
10457	/local/tlutelli/issta_data/temp/c/2005_temp/2005/10457/41a1f8ea4fbfcdc4232f023732584aae2220de31/datagram.c/clean/net/ipv6/datagram.c