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 */
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);
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;
*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);