Below is a patch that adds a warning message for rfc2292-style
use of socket options, and uses a different numeric value for
options that have a different meaning in the rfc3542 API.
It also, of course, adds support for sending and receiving
traffic class, and the new IPV6_RECVx socket options from
rfc3542.
+-DLS
Signed-off-by: David L Stevens <dlstevens@xxxxxxxxxx>
diff -ruNp linux-2.6.11.10/include/linux/in6.h
linux-2.6.11.10T3/include/linux/in6.h
--- linux-2.6.11.10/include/linux/in6.h 2005-05-16 10:51:43.000000000
-0700
+++ linux-2.6.11.10T3/include/linux/in6.h 2005-06-08
10:45:25.000000000 -0700
@@ -148,10 +148,10 @@ 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_2292PKTINFO 2
+#define IPV6_2292HOPOPTS 3
+#define IPV6_2292DSTOPTS 4
+#define IPV6_2292RTHDR 5
#define IPV6_PKTOPTIONS 6
#define IPV6_CHECKSUM 7
#define IPV6_HOPLIMIT 8
@@ -184,6 +184,12 @@ struct in6_flowlabel_req
#define IPV6_IPSEC_POLICY 34
#define IPV6_XFRM_POLICY 35
+#define IPV6_RECVPKTINFO 36
+#define IPV6_RECVHOPLIMIT 37
+#define IPV6_RECVRTHDR 38
+#define IPV6_RECVHOPOPTS 39
+#define IPV6_RECVDSTOPTS 40
+#define IPV6_RECVTCLASS 41
/*
* Multicast:
@@ -198,4 +204,11 @@ struct in6_flowlabel_req
* MCAST_MSFILTER 48
*/
+#define IPV6_PKTINFO 49
+#define IPV6_RTHDR 50
+#define IPV6_HOPOPTS 51
+#define IPV6_DSTOPTS 52
+#define IPV6_TCLASS 53
+#define IPV6_RTHDRDSTOPTS 54
+
#endif
diff -ruNp linux-2.6.11.10/include/linux/ipv6.h
linux-2.6.11.10T3/include/linux/ipv6.h
--- linux-2.6.11.10/include/linux/ipv6.h 2005-05-16
10:51:43.000000000 -0700
+++ linux-2.6.11.10T3/include/linux/ipv6.h 2005-06-07
15:10:28.000000000 -0700
@@ -221,7 +221,8 @@ struct ipv6_pinfo {
rxhlim:1,
hopopts:1,
dstopts:1,
- rxflow:1;
+ rxflow:1,
+ rxtclass:1;
} bits;
__u8 all;
} rxopt;
@@ -231,7 +232,8 @@ struct ipv6_pinfo {
recverr:1,
sndflow:1,
pmtudisc:2,
- ipv6only:1;
+ ipv6only:1,
+ rfc2292:1;
struct ipv6_mc_socklist *ipv6_mc_list;
struct ipv6_ac_socklist *ipv6_ac_list;
@@ -244,6 +246,7 @@ struct ipv6_pinfo {
struct ipv6_txoptions *opt;
struct rt6_info *rt;
int hop_limit;
+ int tclass;
} cork;
};
diff -ruNp linux-2.6.11.10/include/net/ipv6.h
linux-2.6.11.10T3/include/net/ipv6.h
--- linux-2.6.11.10/include/net/ipv6.h 2005-05-16 10:51:49.000000000
-0700
+++ linux-2.6.11.10T3/include/net/ipv6.h 2005-05-24
14:57:23.000000000 -0700
@@ -347,6 +347,7 @@ extern int ip6_append_data(struct
sock
int length,
int transhdrlen,
int hlimit,
+ int tclass,
struct ipv6_txoptions
*opt,
struct flowi *fl,
struct rt6_info *rt,
diff -ruNp linux-2.6.11.10/include/net/transp_v6.h
linux-2.6.11.10T3/include/net/transp_v6.h
--- linux-2.6.11.10/include/net/transp_v6.h 2005-05-16
10:51:51.000000000 -0700
+++ linux-2.6.11.10T3/include/net/transp_v6.h 2005-05-24
14:04:11.000000000 -0700
@@ -37,7 +37,7 @@ extern int datagram_recv_ctl(struct
so
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)
diff -ruNp linux-2.6.11.10/net/ipv6/datagram.c
linux-2.6.11.10T3/net/ipv6/datagram.c
--- linux-2.6.11.10/net/ipv6/datagram.c 2005-05-16 10:52:00.000000000
-0700
+++ linux-2.6.11.10T3/net/ipv6/datagram.c 2005-06-08
11:29:31.000000000 -0700
@@ -381,13 +381,19 @@ int datagram_recv_ctl(struct sock *sk, s
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);
+ put_cmsg(msg, SOL_IPV6, np->rfc2292 ? IPV6_2292PKTINFO :
+ 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.rxtclass) {
+ u8 tclass = (skb->nh.ipv6h->priority << 4) |
+ ((skb->nh.ipv6h->flow_lbl[0]>>4) & 0xf);
+ 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;
@@ -395,26 +401,30 @@ int datagram_recv_ctl(struct sock *sk, s
}
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);
+ put_cmsg(msg, SOL_IPV6, np->rfc2292 ? IPV6_2292HOPOPTS :
+ IPV6_HOPOPTS, (ptr[1]+1)<<3, ptr);
}
if (np->rxopt.bits.dstopts && 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, np->rfc2292 ? IPV6_2292DSTOPTS :
+ IPV6_DSTOPTS, (ptr[1]+1)<<3, ptr);
}
if (np->rxopt.bits.srcrt && 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, np->rfc2292 ? IPV6_2292RTHDR :
+ IPV6_RTHDR, (rthdr->hdrlen+1) << 3, rthdr);
}
if (np->rxopt.bits.dstopts && 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, np->rfc2292 ? IPV6_2292DSTOPTS :
+ IPV6_DSTOPTS, (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;
@@ -436,6 +446,7 @@ int datagram_send_ctl(struct msghdr *msg
continue;
switch (cmsg->cmsg_type) {
+ case IPV6_2292PKTINFO:
case IPV6_PKTINFO:
if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct
in6_pktinfo))) {
err = -EINVAL;
@@ -491,6 +502,7 @@ int datagram_send_ctl(struct msghdr *msg
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;
@@ -511,6 +523,7 @@ int datagram_send_ctl(struct msghdr *msg
opt->hopopt = hdr;
break;
+ case IPV6_2292DSTOPTS:
case IPV6_DSTOPTS:
if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct
ipv6_opt_hdr))) {
err = -EINVAL;
@@ -535,6 +548,7 @@ int datagram_send_ctl(struct msghdr *msg
opt->dst1opt = hdr;
break;
+ case IPV6_2292RTHDR:
case IPV6_RTHDR:
if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct
ipv6_rt_hdr))) {
err = -EINVAL;
@@ -587,6 +601,15 @@ int datagram_send_ctl(struct msghdr *msg
*hlimit = *(int *)CMSG_DATA(cmsg);
break;
+ case IPV6_TCLASS:
+ if (cmsg->cmsg_len != CMSG_LEN(sizeof(int))) {
+ err = -EINVAL;
+ goto exit_f;
+ }
+
+ *tclass = *(int *)CMSG_DATA(cmsg);
+ break;
+
default:
LIMIT_NETDEBUG(
printk(KERN_DEBUG "invalid cmsg type:
%d\n", cmsg->cmsg_type));
diff -ruNp linux-2.6.11.10/net/ipv6/icmp.c
linux-2.6.11.10T3/net/ipv6/icmp.c
--- linux-2.6.11.10/net/ipv6/icmp.c 2005-05-16 10:52:00.000000000
-0700
+++ linux-2.6.11.10T3/net/ipv6/icmp.c 2005-05-24 15:05:14.000000000
-0700
@@ -287,7 +287,7 @@ void icmpv6_send(struct sk_buff *skb, in
int iif = 0;
int addr_type = 0;
int len;
- int hlimit;
+ int hlimit, tclass;
int err = 0;
if ((u8*)hdr < skb->head || (u8*)(hdr+1) > skb->tail)
@@ -381,6 +381,9 @@ void icmpv6_send(struct sk_buff *skb, in
hlimit = np->hop_limit;
if (hlimit < 0)
hlimit = dst_metric(dst, RTAX_HOPLIMIT);
+ tclass = np->cork.tclass;
+ if (tclass < 0)
+ tclass = 0;
msg.skb = skb;
msg.offset = skb->nh.raw - skb->data;
@@ -398,7 +401,7 @@ void icmpv6_send(struct sk_buff *skb, in
err = ip6_append_data(sk, icmpv6_getfrag, &msg,
len + sizeof(struct icmp6hdr),
sizeof(struct icmp6hdr),
- hlimit, NULL, &fl, (struct rt6_info*)dst,
+ hlimit, tclass, NULL, &fl, (struct
rt6_info*)dst,
MSG_DONTWAIT);
if (err) {
ip6_flush_pending_frames(sk);
@@ -432,6 +435,7 @@ static void icmpv6_echo_reply(struct sk_
struct dst_entry *dst;
int err = 0;
int hlimit;
+ int tclass;
saddr = &skb->nh.ipv6h->daddr;
@@ -467,15 +471,18 @@ static void icmpv6_echo_reply(struct sk_
hlimit = np->hop_limit;
if (hlimit < 0)
hlimit = dst_metric(dst, RTAX_HOPLIMIT);
+ tclass = np->cork.tclass;
+ if (tclass < 0)
+ tclass = 0;
idev = in6_dev_get(skb->dev);
msg.skb = skb;
msg.offset = 0;
- err = ip6_append_data(sk, icmpv6_getfrag, &msg, skb->len +
sizeof(struct icmp6hdr),
- sizeof(struct icmp6hdr), hlimit, NULL,
&fl,
- (struct rt6_info*)dst, MSG_DONTWAIT);
+ err = ip6_append_data(sk, icmpv6_getfrag, &msg, skb->len +
+ sizeof(struct icmp6hdr), sizeof(struct icmp6hdr), hlimit,
+ tclass, NULL, &fl, (struct rt6_info*)dst, MSG_DONTWAIT);
if (err) {
ip6_flush_pending_frames(sk);
diff -ruNp linux-2.6.11.10/net/ipv6/ip6_flowlabel.c
linux-2.6.11.10T3/net/ipv6/ip6_flowlabel.c
--- linux-2.6.11.10/net/ipv6/ip6_flowlabel.c 2005-05-16
10:52:00.000000000 -0700
+++ linux-2.6.11.10T3/net/ipv6/ip6_flowlabel.c 2005-05-24
14:04:28.000000000 -0700
@@ -311,7 +311,7 @@ fl_create(struct in6_flowlabel_req *freq
msg.msg_control = (void*)(fl->opt+1);
flowi.oif = 0;
- err = datagram_send_ctl(&msg, &flowi, fl->opt, &junk);
+ err = datagram_send_ctl(&msg, &flowi, fl->opt, &junk,
&junk);
if (err)
goto done;
err = -EINVAL;
diff -ruNp linux-2.6.11.10/net/ipv6/ip6_output.c
linux-2.6.11.10T3/net/ipv6/ip6_output.c
--- linux-2.6.11.10/net/ipv6/ip6_output.c 2005-05-16
10:52:00.000000000 -0700
+++ linux-2.6.11.10T3/net/ipv6/ip6_output.c 2005-05-24
14:58:51.000000000 -0700
@@ -211,7 +211,7 @@ int ip6_xmit(struct sock *sk, struct sk_
struct ipv6hdr *hdr;
u8 proto = fl->proto;
int seg_len = skb->len;
- int hlimit;
+ int hlimit, tclass;
u32 mtu;
if (opt) {
@@ -253,6 +253,13 @@ int ip6_xmit(struct sock *sk, struct sk_
hlimit = np->hop_limit;
if (hlimit < 0)
hlimit = dst_metric(dst, RTAX_HOPLIMIT);
+ tclass = -1;
+ if (np)
+ tclass = np->cork.tclass;
+ if (tclass < 0)
+ tclass = 0;
+ hdr->priority = (np->cork.tclass>>4) &0xf;
+ hdr->flow_lbl[0] |= (np->cork.tclass & 0xf)<<4;
hdr->payload_len = htons(seg_len);
hdr->nexthdr = proto;
@@ -806,10 +813,11 @@ out_err_release:
return err;
}
-int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
int offset, int len, int odd, struct sk_buff *skb),
- void *from, int length, int transhdrlen,
- int hlimit, struct ipv6_txoptions *opt, struct flowi
*fl, struct rt6_info *rt,
- unsigned int flags)
+int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
+ int offset, int len, int odd, struct sk_buff *skb),
+ void *from, int length, int transhdrlen,
+ int hlimit, int tclass, struct ipv6_txoptions *opt, struct flowi
*fl,
+ struct rt6_info *rt, unsigned int flags)
{
struct inet_sock *inet = inet_sk(sk);
struct ipv6_pinfo *np = inet6_sk(sk);
@@ -847,6 +855,7 @@ int ip6_append_data(struct sock *sk, int
np->cork.rt = rt;
inet->cork.fl = *fl;
np->cork.hop_limit = hlimit;
+ np->cork.tclass = tclass;
inet->cork.fragsize = mtu = dst_pmtu(&rt->u.dst);
inet->cork.length = 0;
sk->sk_sndmsg_page = NULL;
@@ -1130,6 +1139,10 @@ int ip6_push_pending_frames(struct sock
*(u32*)hdr = fl->fl6_flowlabel | htonl(0x60000000);
+ /* traffic class */
+ hdr->priority = (np->cork.tclass>>4) & 0xf;
+ hdr->flow_lbl[0] |= (np->cork.tclass & 0xf)<<4;
+
if (skb->len <= sizeof(struct ipv6hdr) + IPV6_MAXPLEN)
hdr->payload_len = htons(skb->len - sizeof(struct
ipv6hdr));
else
diff -ruNp linux-2.6.11.10/net/ipv6/ipv6_sockglue.c
linux-2.6.11.10T3/net/ipv6/ipv6_sockglue.c
--- linux-2.6.11.10/net/ipv6/ipv6_sockglue.c 2005-05-16
10:52:00.000000000 -0700
+++ linux-2.6.11.10T3/net/ipv6/ipv6_sockglue.c 2005-06-08
11:06:47.000000000 -0700
@@ -115,6 +115,15 @@ extern int ip6_mc_msfilter(struct sock *
extern int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf,
struct group_filter __user *optval, int __user *optlen);
+/*
+ * warn of obsolete RFC 2292 socket API use
+ */
+static void warn2292(char *optname)
+{
+ printk(KERN_WARNING "process '%s' is using obsolete %s socket
option\n",
+ current->comm, optname);
+}
+
int ipv6_setsockopt(struct sock *sk, int level, int optname,
char __user *optval, int optlen)
@@ -208,33 +217,53 @@ int ipv6_setsockopt(struct sock *sk, int
retv = 0;
break;
- case IPV6_PKTINFO:
+ case IPV6_2292PKTINFO:
+ warn2292("IPV6_PKTINFO");
+ case IPV6_RECVPKTINFO:
+ np->rfc2292 = optname == IPV6_2292PKTINFO;
np->rxopt.bits.rxinfo = valbool;
retv = 0;
break;
case IPV6_HOPLIMIT:
+ warn2292("IPV6_HOPLIMIT");
+ case IPV6_RECVHOPLIMIT:
+ np->rfc2292 = optname == IPV6_HOPLIMIT;
np->rxopt.bits.rxhlim = valbool;
retv = 0;
break;
- case IPV6_RTHDR:
+ case IPV6_2292RTHDR:
+ warn2292("IPV6_RTHDR");
+ case IPV6_RECVRTHDR:
if (val < 0 || val > 2)
goto e_inval;
+ np->rfc2292 = optname == IPV6_2292RTHDR;
np->rxopt.bits.srcrt = val;
retv = 0;
break;
- case IPV6_HOPOPTS:
+ case IPV6_2292HOPOPTS:
+ warn2292("IPV6_HOPOPTS");
+ case IPV6_RECVHOPOPTS:
+ np->rfc2292 = optname == IPV6_2292HOPOPTS;
np->rxopt.bits.hopopts = valbool;
retv = 0;
break;
- case IPV6_DSTOPTS:
+ case IPV6_2292DSTOPTS:
+ warn2292("IPV6_DSTOPTS");
+ case IPV6_RECVDSTOPTS:
+ np->rfc2292 = optname == IPV6_2292DSTOPTS;
np->rxopt.bits.dstopts = valbool;
retv = 0;
break;
+ case IPV6_RECVTCLASS:
+ np->rxopt.bits.rxtclass = valbool;
+ retv = 0;
+ break;
+
case IPV6_FLOWINFO:
np->rxopt.bits.rxflow = valbool;
retv = 0;
@@ -274,7 +303,7 @@ int ipv6_setsockopt(struct sock *sk, int
msg.msg_controllen = optlen;
msg.msg_control = (void*)(opt+1);
- retv = datagram_send_ctl(&msg, &fl, opt, &junk);
+ retv = datagram_send_ctl(&msg, &fl, opt, &junk, &junk);
if (retv)
goto done;
update:
@@ -620,26 +649,45 @@ int ipv6_getsockopt(struct sock *sk, int
val = np->ipv6only;
break;
- case IPV6_PKTINFO:
+ case IPV6_2292PKTINFO:
+ warn2292("IPV6_PKTINFO");
+ case IPV6_RECVPKTINFO:
+ np->rfc2292 = optname == IPV6_2292PKTINFO;
val = np->rxopt.bits.rxinfo;
break;
case IPV6_HOPLIMIT:
+ warn2292("IPV6_HOPLIMIT");
+ case IPV6_RECVHOPLIMIT:
+ np->rfc2292 = optname == IPV6_HOPLIMIT;
val = np->rxopt.bits.rxhlim;
break;
- case IPV6_RTHDR:
+ case IPV6_2292RTHDR:
+ warn2292("IPV6_RTHDR");
+ case IPV6_RECVRTHDR:
+ np->rfc2292 = optname == IPV6_2292RTHDR;
val = np->rxopt.bits.srcrt;
break;
- case IPV6_HOPOPTS:
+ case IPV6_2292HOPOPTS:
+ warn2292("IPV6_HOPOPTS");
+ case IPV6_RECVHOPOPTS:
+ np->rfc2292 = optname == IPV6_2292HOPOPTS;
val = np->rxopt.bits.hopopts;
break;
- case IPV6_DSTOPTS:
+ case IPV6_2292DSTOPTS:
+ warn2292("IPV6_DSTOPTS");
+ case IPV6_RECVDSTOPTS:
+ np->rfc2292 = optname == IPV6_2292DSTOPTS;
val = np->rxopt.bits.dstopts;
break;
+ case IPV6_RECVTCLASS:
+ val = np->rxopt.bits.rxtclass;
+ break;
+
case IPV6_FLOWINFO:
val = np->rxopt.bits.rxflow;
break;
diff -ruNp linux-2.6.11.10/net/ipv6/raw.c linux-2.6.11.10T3/net/ipv6/raw.c
--- linux-2.6.11.10/net/ipv6/raw.c 2005-05-16 10:52:00.000000000
-0700
+++ linux-2.6.11.10T3/net/ipv6/raw.c 2005-05-24 15:09:42.000000000
-0700
@@ -617,6 +617,7 @@ static int rawv6_sendmsg(struct kiocb *i
struct flowi fl;
int addr_len = msg->msg_namelen;
int hlimit = -1;
+ int tclass = -1;
u16 proto;
int err;
@@ -702,7 +703,7 @@ static int rawv6_sendmsg(struct kiocb *i
memset(opt, 0, sizeof(struct ipv6_txoptions));
opt->tot_len = sizeof(struct ipv6_txoptions);
- err = datagram_send_ctl(msg, &fl, opt, &hlimit);
+ err = datagram_send_ctl(msg, &fl, opt, &hlimit, &tclass);
if (err < 0) {
fl6_sock_release(flowlabel);
return err;
@@ -758,6 +759,12 @@ static int rawv6_sendmsg(struct kiocb *i
hlimit = dst_metric(dst, RTAX_HOPLIMIT);
}
+ if (tclass < 0) {
+ tclass = np->cork.tclass;
+ if (tclass < 0)
+ tclass = 0;
+ }
+
if (msg->msg_flags&MSG_CONFIRM)
goto do_confirm;
@@ -766,8 +773,9 @@ back_from_confirm:
err = rawv6_send_hdrinc(sk, msg->msg_iov, len, &fl,
(struct rt6_info*)dst, msg->msg_flags);
} else {
lock_sock(sk);
- err = ip6_append_data(sk, ip_generic_getfrag,
msg->msg_iov, len, 0,
- hlimit, opt, &fl, (struct
rt6_info*)dst, msg->msg_flags);
+ err = ip6_append_data(sk, ip_generic_getfrag,
msg->msg_iov,
+ len, 0, hlimit, tclass, opt, &fl, (struct
rt6_info*)dst,
+ msg->msg_flags);
if (err)
ip6_flush_pending_frames(sk);
diff -ruNp linux-2.6.11.10/net/ipv6/udp.c linux-2.6.11.10T3/net/ipv6/udp.c
--- linux-2.6.11.10/net/ipv6/udp.c 2005-05-16 10:52:00.000000000
-0700
+++ linux-2.6.11.10T3/net/ipv6/udp.c 2005-05-24 15:11:58.000000000
-0700
@@ -637,6 +637,7 @@ static int udpv6_sendmsg(struct kiocb *i
int addr_len = msg->msg_namelen;
int ulen = len;
int hlimit = -1;
+ int tclass = -1;
int corkreq = up->corkflag || msg->msg_flags&MSG_MORE;
int err;
@@ -758,7 +759,7 @@ do_udp_sendmsg:
memset(opt, 0, sizeof(struct ipv6_txoptions));
opt->tot_len = sizeof(*opt);
- err = datagram_send_ctl(msg, fl, opt, &hlimit);
+ err = datagram_send_ctl(msg, fl, opt, &hlimit, &tclass);
if (err < 0) {
fl6_sock_release(flowlabel);
return err;
@@ -812,6 +813,11 @@ do_udp_sendmsg:
if (hlimit < 0)
hlimit = dst_metric(dst, RTAX_HOPLIMIT);
}
+ if (tclass < 0) {
+ tclass = np->cork.tclass;
+ if (tclass < 0)
+ tclass = 0;
+ }
if (msg->msg_flags&MSG_CONFIRM)
goto do_confirm;
@@ -832,9 +838,10 @@ back_from_confirm:
do_append_data:
up->len += ulen;
- err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov, ulen,
sizeof(struct udphdr),
- hlimit, opt, fl, (struct rt6_info*)dst,
- corkreq ? msg->msg_flags|MSG_MORE :
msg->msg_flags);
+ err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov, ulen,
+ sizeof(struct udphdr), hlimit, tclass, opt, fl,
+ (struct rt6_info*)dst,
+ corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags);
if (err)
udp_v6_flush_pending_frames(sk);
else if (!corkreq)
rfc3542-2.patch
Description: Binary data
|