summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWei Wang <weiwan@google.com>2016-05-03 00:40:07 -0400
committerDavid S. Miller <davem@davemloft.net>2016-05-03 16:08:14 -0400
commit26879da58711aa604a1b866cbeedd7e0f78f90ad (patch)
tree579b56b3b42598c5db664ef276979ce37b7c6416
parent1d2077ac0165c0d173a2255e37cf4dc5033d92c7 (diff)
ipv6: add new struct ipcm6_cookie
In the sendmsg function of UDP, raw, ICMP and l2tp sockets, we use local variables like hlimits, tclass, opt and dontfrag and pass them to corresponding functions like ip6_make_skb, ip6_append_data and xxx_push_pending_frames. This is not a good practice and makes it hard to add new parameters. This fix introduces a new struct ipcm6_cookie similar to ipcm_cookie in ipv4 and include the above mentioned variables. And we only pass the pointer to this structure to corresponding functions. This makes it easier to add new parameters in the future and makes the function cleaner. Signed-off-by: Wei Wang <weiwan@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/ipv6.h18
-rw-r--r--include/net/transp_v6.h3
-rw-r--r--net/ipv6/datagram.c13
-rw-r--r--net/ipv6/icmp.c28
-rw-r--r--net/ipv6/ip6_flowlabel.c6
-rw-r--r--net/ipv6/ip6_output.c42
-rw-r--r--net/ipv6/ipv6_sockglue.c6
-rw-r--r--net/ipv6/ping.c12
-rw-r--r--net/ipv6/raw.c33
-rw-r--r--net/ipv6/udp.c38
-rw-r--r--net/l2tp/l2tp_ip6.c33
11 files changed, 123 insertions, 109 deletions
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 415213da5be3..11a045281948 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -251,6 +251,13 @@ struct ipv6_fl_socklist {
251 struct rcu_head rcu; 251 struct rcu_head rcu;
252}; 252};
253 253
254struct ipcm6_cookie {
255 __s16 hlimit;
256 __s16 tclass;
257 __s8 dontfrag;
258 struct ipv6_txoptions *opt;
259};
260
254static inline struct ipv6_txoptions *txopt_get(const struct ipv6_pinfo *np) 261static inline struct ipv6_txoptions *txopt_get(const struct ipv6_pinfo *np)
255{ 262{
256 struct ipv6_txoptions *opt; 263 struct ipv6_txoptions *opt;
@@ -863,9 +870,9 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr);
863int ip6_append_data(struct sock *sk, 870int ip6_append_data(struct sock *sk,
864 int getfrag(void *from, char *to, int offset, int len, 871 int getfrag(void *from, char *to, int offset, int len,
865 int odd, struct sk_buff *skb), 872 int odd, struct sk_buff *skb),
866 void *from, int length, int transhdrlen, int hlimit, 873 void *from, int length, int transhdrlen,
867 int tclass, struct ipv6_txoptions *opt, struct flowi6 *fl6, 874 struct ipcm6_cookie *ipc6, struct flowi6 *fl6,
868 struct rt6_info *rt, unsigned int flags, int dontfrag, 875 struct rt6_info *rt, unsigned int flags,
869 const struct sockcm_cookie *sockc); 876 const struct sockcm_cookie *sockc);
870 877
871int ip6_push_pending_frames(struct sock *sk); 878int ip6_push_pending_frames(struct sock *sk);
@@ -881,9 +888,8 @@ struct sk_buff *ip6_make_skb(struct sock *sk,
881 int getfrag(void *from, char *to, int offset, 888 int getfrag(void *from, char *to, int offset,
882 int len, int odd, struct sk_buff *skb), 889 int len, int odd, struct sk_buff *skb),
883 void *from, int length, int transhdrlen, 890 void *from, int length, int transhdrlen,
884 int hlimit, int tclass, struct ipv6_txoptions *opt, 891 struct ipcm6_cookie *ipc6, struct flowi6 *fl6,
885 struct flowi6 *fl6, struct rt6_info *rt, 892 struct rt6_info *rt, unsigned int flags,
886 unsigned int flags, int dontfrag,
887 const struct sockcm_cookie *sockc); 893 const struct sockcm_cookie *sockc);
888 894
889static inline struct sk_buff *ip6_finish_skb(struct sock *sk) 895static inline struct sk_buff *ip6_finish_skb(struct sock *sk)
diff --git a/include/net/transp_v6.h b/include/net/transp_v6.h
index 2b1c3450ab20..276f9760ab56 100644
--- a/include/net/transp_v6.h
+++ b/include/net/transp_v6.h
@@ -41,8 +41,7 @@ void ip6_datagram_recv_specific_ctl(struct sock *sk, struct msghdr *msg,
41 struct sk_buff *skb); 41 struct sk_buff *skb);
42 42
43int ip6_datagram_send_ctl(struct net *net, struct sock *sk, struct msghdr *msg, 43int ip6_datagram_send_ctl(struct net *net, struct sock *sk, struct msghdr *msg,
44 struct flowi6 *fl6, struct ipv6_txoptions *opt, 44 struct flowi6 *fl6, struct ipcm6_cookie *ipc6,
45 int *hlimit, int *tclass, int *dontfrag,
46 struct sockcm_cookie *sockc); 45 struct sockcm_cookie *sockc);
47 46
48void ip6_dgram_sock_seq_show(struct seq_file *seq, struct sock *sp, 47void ip6_dgram_sock_seq_show(struct seq_file *seq, struct sock *sp,
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index ea9ee5cce5cf..00d0c2903173 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -727,14 +727,13 @@ EXPORT_SYMBOL_GPL(ip6_datagram_recv_ctl);
727 727
728int ip6_datagram_send_ctl(struct net *net, struct sock *sk, 728int ip6_datagram_send_ctl(struct net *net, struct sock *sk,
729 struct msghdr *msg, struct flowi6 *fl6, 729 struct msghdr *msg, struct flowi6 *fl6,
730 struct ipv6_txoptions *opt, 730 struct ipcm6_cookie *ipc6, struct sockcm_cookie *sockc)
731 int *hlimit, int *tclass, int *dontfrag,
732 struct sockcm_cookie *sockc)
733{ 731{
734 struct in6_pktinfo *src_info; 732 struct in6_pktinfo *src_info;
735 struct cmsghdr *cmsg; 733 struct cmsghdr *cmsg;
736 struct ipv6_rt_hdr *rthdr; 734 struct ipv6_rt_hdr *rthdr;
737 struct ipv6_opt_hdr *hdr; 735 struct ipv6_opt_hdr *hdr;
736 struct ipv6_txoptions *opt = ipc6->opt;
738 int len; 737 int len;
739 int err = 0; 738 int err = 0;
740 739
@@ -953,8 +952,8 @@ int ip6_datagram_send_ctl(struct net *net, struct sock *sk,
953 goto exit_f; 952 goto exit_f;
954 } 953 }
955 954
956 *hlimit = *(int *)CMSG_DATA(cmsg); 955 ipc6->hlimit = *(int *)CMSG_DATA(cmsg);
957 if (*hlimit < -1 || *hlimit > 0xff) { 956 if (ipc6->hlimit < -1 || ipc6->hlimit > 0xff) {
958 err = -EINVAL; 957 err = -EINVAL;
959 goto exit_f; 958 goto exit_f;
960 } 959 }
@@ -974,7 +973,7 @@ int ip6_datagram_send_ctl(struct net *net, struct sock *sk,
974 goto exit_f; 973 goto exit_f;
975 974
976 err = 0; 975 err = 0;
977 *tclass = tc; 976 ipc6->tclass = tc;
978 977
979 break; 978 break;
980 } 979 }
@@ -992,7 +991,7 @@ int ip6_datagram_send_ctl(struct net *net, struct sock *sk,
992 goto exit_f; 991 goto exit_f;
993 992
994 err = 0; 993 err = 0;
995 *dontfrag = df; 994 ipc6->dontfrag = df;
996 995
997 break; 996 break;
998 } 997 }
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 23b9a4cc418e..9554b99a8508 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -401,10 +401,10 @@ static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info)
401 struct flowi6 fl6; 401 struct flowi6 fl6;
402 struct icmpv6_msg msg; 402 struct icmpv6_msg msg;
403 struct sockcm_cookie sockc_unused = {0}; 403 struct sockcm_cookie sockc_unused = {0};
404 struct ipcm6_cookie ipc6;
404 int iif = 0; 405 int iif = 0;
405 int addr_type = 0; 406 int addr_type = 0;
406 int len; 407 int len;
407 int hlimit;
408 int err = 0; 408 int err = 0;
409 u32 mark = IP6_REPLY_MARK(net, skb->mark); 409 u32 mark = IP6_REPLY_MARK(net, skb->mark);
410 410
@@ -507,7 +507,10 @@ static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info)
507 if (IS_ERR(dst)) 507 if (IS_ERR(dst))
508 goto out; 508 goto out;
509 509
510 hlimit = ip6_sk_dst_hoplimit(np, &fl6, dst); 510 ipc6.hlimit = ip6_sk_dst_hoplimit(np, &fl6, dst);
511 ipc6.tclass = np->tclass;
512 ipc6.dontfrag = np->dontfrag;
513 ipc6.opt = NULL;
511 514
512 msg.skb = skb; 515 msg.skb = skb;
513 msg.offset = skb_network_offset(skb); 516 msg.offset = skb_network_offset(skb);
@@ -526,9 +529,9 @@ static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info)
526 529
527 err = ip6_append_data(sk, icmpv6_getfrag, &msg, 530 err = ip6_append_data(sk, icmpv6_getfrag, &msg,
528 len + sizeof(struct icmp6hdr), 531 len + sizeof(struct icmp6hdr),
529 sizeof(struct icmp6hdr), hlimit, 532 sizeof(struct icmp6hdr),
530 np->tclass, NULL, &fl6, (struct rt6_info *)dst, 533 &ipc6, &fl6, (struct rt6_info *)dst,
531 MSG_DONTWAIT, np->dontfrag, &sockc_unused); 534 MSG_DONTWAIT, &sockc_unused);
532 if (err) { 535 if (err) {
533 ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTERRORS); 536 ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTERRORS);
534 ip6_flush_pending_frames(sk); 537 ip6_flush_pending_frames(sk);
@@ -563,9 +566,8 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
563 struct flowi6 fl6; 566 struct flowi6 fl6;
564 struct icmpv6_msg msg; 567 struct icmpv6_msg msg;
565 struct dst_entry *dst; 568 struct dst_entry *dst;
569 struct ipcm6_cookie ipc6;
566 int err = 0; 570 int err = 0;
567 int hlimit;
568 u8 tclass;
569 u32 mark = IP6_REPLY_MARK(net, skb->mark); 571 u32 mark = IP6_REPLY_MARK(net, skb->mark);
570 struct sockcm_cookie sockc_unused = {0}; 572 struct sockcm_cookie sockc_unused = {0};
571 573
@@ -607,19 +609,21 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
607 if (IS_ERR(dst)) 609 if (IS_ERR(dst))
608 goto out; 610 goto out;
609 611
610 hlimit = ip6_sk_dst_hoplimit(np, &fl6, dst);
611
612 idev = __in6_dev_get(skb->dev); 612 idev = __in6_dev_get(skb->dev);
613 613
614 msg.skb = skb; 614 msg.skb = skb;
615 msg.offset = 0; 615 msg.offset = 0;
616 msg.type = ICMPV6_ECHO_REPLY; 616 msg.type = ICMPV6_ECHO_REPLY;
617 617
618 tclass = ipv6_get_dsfield(ipv6_hdr(skb)); 618 ipc6.hlimit = ip6_sk_dst_hoplimit(np, &fl6, dst);
619 ipc6.tclass = ipv6_get_dsfield(ipv6_hdr(skb));
620 ipc6.dontfrag = np->dontfrag;
621 ipc6.opt = NULL;
622
619 err = ip6_append_data(sk, icmpv6_getfrag, &msg, skb->len + sizeof(struct icmp6hdr), 623 err = ip6_append_data(sk, icmpv6_getfrag, &msg, skb->len + sizeof(struct icmp6hdr),
620 sizeof(struct icmp6hdr), hlimit, tclass, NULL, &fl6, 624 sizeof(struct icmp6hdr), &ipc6, &fl6,
621 (struct rt6_info *)dst, MSG_DONTWAIT, 625 (struct rt6_info *)dst, MSG_DONTWAIT,
622 np->dontfrag, &sockc_unused); 626 &sockc_unused);
623 627
624 if (err) { 628 if (err) {
625 __ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTERRORS); 629 __ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTERRORS);
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c
index 35d3ddc328f8..b912f0dbaf72 100644
--- a/net/ipv6/ip6_flowlabel.c
+++ b/net/ipv6/ip6_flowlabel.c
@@ -373,7 +373,7 @@ fl_create(struct net *net, struct sock *sk, struct in6_flowlabel_req *freq,
373 struct msghdr msg; 373 struct msghdr msg;
374 struct flowi6 flowi6; 374 struct flowi6 flowi6;
375 struct sockcm_cookie sockc_junk; 375 struct sockcm_cookie sockc_junk;
376 int junk; 376 struct ipcm6_cookie ipc6;
377 377
378 err = -ENOMEM; 378 err = -ENOMEM;
379 fl->opt = kmalloc(sizeof(*fl->opt) + olen, GFP_KERNEL); 379 fl->opt = kmalloc(sizeof(*fl->opt) + olen, GFP_KERNEL);
@@ -390,8 +390,8 @@ fl_create(struct net *net, struct sock *sk, struct in6_flowlabel_req *freq,
390 msg.msg_control = (void *)(fl->opt+1); 390 msg.msg_control = (void *)(fl->opt+1);
391 memset(&flowi6, 0, sizeof(flowi6)); 391 memset(&flowi6, 0, sizeof(flowi6));
392 392
393 err = ip6_datagram_send_ctl(net, sk, &msg, &flowi6, fl->opt, 393 ipc6.opt = fl->opt;
394 &junk, &junk, &junk, &sockc_junk); 394 err = ip6_datagram_send_ctl(net, sk, &msg, &flowi6, &ipc6, &sockc_junk);
395 if (err) 395 if (err)
396 goto done; 396 goto done;
397 err = -EINVAL; 397 err = -EINVAL;
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 2b3ffc582d16..cbf127ae7c67 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -1182,12 +1182,12 @@ static void ip6_append_data_mtu(unsigned int *mtu,
1182} 1182}
1183 1183
1184static int ip6_setup_cork(struct sock *sk, struct inet_cork_full *cork, 1184static int ip6_setup_cork(struct sock *sk, struct inet_cork_full *cork,
1185 struct inet6_cork *v6_cork, 1185 struct inet6_cork *v6_cork, struct ipcm6_cookie *ipc6,
1186 int hlimit, int tclass, struct ipv6_txoptions *opt,
1187 struct rt6_info *rt, struct flowi6 *fl6) 1186 struct rt6_info *rt, struct flowi6 *fl6)
1188{ 1187{
1189 struct ipv6_pinfo *np = inet6_sk(sk); 1188 struct ipv6_pinfo *np = inet6_sk(sk);
1190 unsigned int mtu; 1189 unsigned int mtu;
1190 struct ipv6_txoptions *opt = ipc6->opt;
1191 1191
1192 /* 1192 /*
1193 * setup for corking 1193 * setup for corking
@@ -1229,8 +1229,8 @@ static int ip6_setup_cork(struct sock *sk, struct inet_cork_full *cork,
1229 dst_hold(&rt->dst); 1229 dst_hold(&rt->dst);
1230 cork->base.dst = &rt->dst; 1230 cork->base.dst = &rt->dst;
1231 cork->fl.u.ip6 = *fl6; 1231 cork->fl.u.ip6 = *fl6;
1232 v6_cork->hop_limit = hlimit; 1232 v6_cork->hop_limit = ipc6->hlimit;
1233 v6_cork->tclass = tclass; 1233 v6_cork->tclass = ipc6->tclass;
1234 if (rt->dst.flags & DST_XFRM_TUNNEL) 1234 if (rt->dst.flags & DST_XFRM_TUNNEL)
1235 mtu = np->pmtudisc >= IPV6_PMTUDISC_PROBE ? 1235 mtu = np->pmtudisc >= IPV6_PMTUDISC_PROBE ?
1236 rt->dst.dev->mtu : dst_mtu(&rt->dst); 1236 rt->dst.dev->mtu : dst_mtu(&rt->dst);
@@ -1258,7 +1258,7 @@ static int __ip6_append_data(struct sock *sk,
1258 int getfrag(void *from, char *to, int offset, 1258 int getfrag(void *from, char *to, int offset,
1259 int len, int odd, struct sk_buff *skb), 1259 int len, int odd, struct sk_buff *skb),
1260 void *from, int length, int transhdrlen, 1260 void *from, int length, int transhdrlen,
1261 unsigned int flags, int dontfrag, 1261 unsigned int flags, struct ipcm6_cookie *ipc6,
1262 const struct sockcm_cookie *sockc) 1262 const struct sockcm_cookie *sockc)
1263{ 1263{
1264 struct sk_buff *skb, *skb_prev = NULL; 1264 struct sk_buff *skb, *skb_prev = NULL;
@@ -1298,7 +1298,7 @@ static int __ip6_append_data(struct sock *sk,
1298 sizeof(struct frag_hdr) : 0) + 1298 sizeof(struct frag_hdr) : 0) +
1299 rt->rt6i_nfheader_len; 1299 rt->rt6i_nfheader_len;
1300 1300
1301 if (cork->length + length > mtu - headersize && dontfrag && 1301 if (cork->length + length > mtu - headersize && ipc6->dontfrag &&
1302 (sk->sk_protocol == IPPROTO_UDP || 1302 (sk->sk_protocol == IPPROTO_UDP ||
1303 sk->sk_protocol == IPPROTO_RAW)) { 1303 sk->sk_protocol == IPPROTO_RAW)) {
1304 ipv6_local_rxpmtu(sk, fl6, mtu - headersize + 1304 ipv6_local_rxpmtu(sk, fl6, mtu - headersize +
@@ -1564,9 +1564,9 @@ error:
1564int ip6_append_data(struct sock *sk, 1564int ip6_append_data(struct sock *sk,
1565 int getfrag(void *from, char *to, int offset, int len, 1565 int getfrag(void *from, char *to, int offset, int len,
1566 int odd, struct sk_buff *skb), 1566 int odd, struct sk_buff *skb),
1567 void *from, int length, int transhdrlen, int hlimit, 1567 void *from, int length, int transhdrlen,
1568 int tclass, struct ipv6_txoptions *opt, struct flowi6 *fl6, 1568 struct ipcm6_cookie *ipc6, struct flowi6 *fl6,
1569 struct rt6_info *rt, unsigned int flags, int dontfrag, 1569 struct rt6_info *rt, unsigned int flags,
1570 const struct sockcm_cookie *sockc) 1570 const struct sockcm_cookie *sockc)
1571{ 1571{
1572 struct inet_sock *inet = inet_sk(sk); 1572 struct inet_sock *inet = inet_sk(sk);
@@ -1580,12 +1580,12 @@ int ip6_append_data(struct sock *sk,
1580 /* 1580 /*
1581 * setup for corking 1581 * setup for corking
1582 */ 1582 */
1583 err = ip6_setup_cork(sk, &inet->cork, &np->cork, hlimit, 1583 err = ip6_setup_cork(sk, &inet->cork, &np->cork,
1584 tclass, opt, rt, fl6); 1584 ipc6, rt, fl6);
1585 if (err) 1585 if (err)
1586 return err; 1586 return err;
1587 1587
1588 exthdrlen = (opt ? opt->opt_flen : 0); 1588 exthdrlen = (ipc6->opt ? ipc6->opt->opt_flen : 0);
1589 length += exthdrlen; 1589 length += exthdrlen;
1590 transhdrlen += exthdrlen; 1590 transhdrlen += exthdrlen;
1591 } else { 1591 } else {
@@ -1595,8 +1595,7 @@ int ip6_append_data(struct sock *sk,
1595 1595
1596 return __ip6_append_data(sk, fl6, &sk->sk_write_queue, &inet->cork.base, 1596 return __ip6_append_data(sk, fl6, &sk->sk_write_queue, &inet->cork.base,
1597 &np->cork, sk_page_frag(sk), getfrag, 1597 &np->cork, sk_page_frag(sk), getfrag,
1598 from, length, transhdrlen, flags, dontfrag, 1598 from, length, transhdrlen, flags, ipc6, sockc);
1599 sockc);
1600} 1599}
1601EXPORT_SYMBOL_GPL(ip6_append_data); 1600EXPORT_SYMBOL_GPL(ip6_append_data);
1602 1601
@@ -1752,15 +1751,14 @@ struct sk_buff *ip6_make_skb(struct sock *sk,
1752 int getfrag(void *from, char *to, int offset, 1751 int getfrag(void *from, char *to, int offset,
1753 int len, int odd, struct sk_buff *skb), 1752 int len, int odd, struct sk_buff *skb),
1754 void *from, int length, int transhdrlen, 1753 void *from, int length, int transhdrlen,
1755 int hlimit, int tclass, 1754 struct ipcm6_cookie *ipc6, struct flowi6 *fl6,
1756 struct ipv6_txoptions *opt, struct flowi6 *fl6,
1757 struct rt6_info *rt, unsigned int flags, 1755 struct rt6_info *rt, unsigned int flags,
1758 int dontfrag, const struct sockcm_cookie *sockc) 1756 const struct sockcm_cookie *sockc)
1759{ 1757{
1760 struct inet_cork_full cork; 1758 struct inet_cork_full cork;
1761 struct inet6_cork v6_cork; 1759 struct inet6_cork v6_cork;
1762 struct sk_buff_head queue; 1760 struct sk_buff_head queue;
1763 int exthdrlen = (opt ? opt->opt_flen : 0); 1761 int exthdrlen = (ipc6->opt ? ipc6->opt->opt_flen : 0);
1764 int err; 1762 int err;
1765 1763
1766 if (flags & MSG_PROBE) 1764 if (flags & MSG_PROBE)
@@ -1772,17 +1770,17 @@ struct sk_buff *ip6_make_skb(struct sock *sk,
1772 cork.base.addr = 0; 1770 cork.base.addr = 0;
1773 cork.base.opt = NULL; 1771 cork.base.opt = NULL;
1774 v6_cork.opt = NULL; 1772 v6_cork.opt = NULL;
1775 err = ip6_setup_cork(sk, &cork, &v6_cork, hlimit, tclass, opt, rt, fl6); 1773 err = ip6_setup_cork(sk, &cork, &v6_cork, ipc6, rt, fl6);
1776 if (err) 1774 if (err)
1777 return ERR_PTR(err); 1775 return ERR_PTR(err);
1778 1776
1779 if (dontfrag < 0) 1777 if (ipc6->dontfrag < 0)
1780 dontfrag = inet6_sk(sk)->dontfrag; 1778 ipc6->dontfrag = inet6_sk(sk)->dontfrag;
1781 1779
1782 err = __ip6_append_data(sk, fl6, &queue, &cork.base, &v6_cork, 1780 err = __ip6_append_data(sk, fl6, &queue, &cork.base, &v6_cork,
1783 &current->task_frag, getfrag, from, 1781 &current->task_frag, getfrag, from,
1784 length + exthdrlen, transhdrlen + exthdrlen, 1782 length + exthdrlen, transhdrlen + exthdrlen,
1785 flags, dontfrag, sockc); 1783 flags, ipc6, sockc);
1786 if (err) { 1784 if (err) {
1787 __ip6_flush_pending_frames(sk, &queue, &cork, &v6_cork); 1785 __ip6_flush_pending_frames(sk, &queue, &cork, &v6_cork);
1788 return ERR_PTR(err); 1786 return ERR_PTR(err);
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index 4ff4b29894eb..a9895e15ee9c 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -473,7 +473,7 @@ sticky_done:
473 struct msghdr msg; 473 struct msghdr msg;
474 struct flowi6 fl6; 474 struct flowi6 fl6;
475 struct sockcm_cookie sockc_junk; 475 struct sockcm_cookie sockc_junk;
476 int junk; 476 struct ipcm6_cookie ipc6;
477 477
478 memset(&fl6, 0, sizeof(fl6)); 478 memset(&fl6, 0, sizeof(fl6));
479 fl6.flowi6_oif = sk->sk_bound_dev_if; 479 fl6.flowi6_oif = sk->sk_bound_dev_if;
@@ -503,9 +503,9 @@ sticky_done:
503 503
504 msg.msg_controllen = optlen; 504 msg.msg_controllen = optlen;
505 msg.msg_control = (void *)(opt+1); 505 msg.msg_control = (void *)(opt+1);
506 ipc6.opt = opt;
506 507
507 retv = ip6_datagram_send_ctl(net, sk, &msg, &fl6, opt, &junk, 508 retv = ip6_datagram_send_ctl(net, sk, &msg, &fl6, &ipc6, &sockc_junk);
508 &junk, &junk, &sockc_junk);
509 if (retv) 509 if (retv)
510 goto done; 510 goto done;
511update: 511update:
diff --git a/net/ipv6/ping.c b/net/ipv6/ping.c
index da1cff79e447..3ee3e444a66b 100644
--- a/net/ipv6/ping.c
+++ b/net/ipv6/ping.c
@@ -58,11 +58,11 @@ static int ping_v6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
58 int iif = 0; 58 int iif = 0;
59 struct flowi6 fl6; 59 struct flowi6 fl6;
60 int err; 60 int err;
61 int hlimit;
62 struct dst_entry *dst; 61 struct dst_entry *dst;
63 struct rt6_info *rt; 62 struct rt6_info *rt;
64 struct pingfakehdr pfh; 63 struct pingfakehdr pfh;
65 struct sockcm_cookie junk = {0}; 64 struct sockcm_cookie junk = {0};
65 struct ipcm6_cookie ipc6;
66 66
67 pr_debug("ping_v6_sendmsg(sk=%p,sk->num=%u)\n", inet, inet->inet_num); 67 pr_debug("ping_v6_sendmsg(sk=%p,sk->num=%u)\n", inet, inet->inet_num);
68 68
@@ -139,13 +139,15 @@ static int ping_v6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
139 pfh.wcheck = 0; 139 pfh.wcheck = 0;
140 pfh.family = AF_INET6; 140 pfh.family = AF_INET6;
141 141
142 hlimit = ip6_sk_dst_hoplimit(np, &fl6, dst); 142 ipc6.hlimit = ip6_sk_dst_hoplimit(np, &fl6, dst);
143 ipc6.tclass = np->tclass;
144 ipc6.dontfrag = np->dontfrag;
145 ipc6.opt = NULL;
143 146
144 lock_sock(sk); 147 lock_sock(sk);
145 err = ip6_append_data(sk, ping_getfrag, &pfh, len, 148 err = ip6_append_data(sk, ping_getfrag, &pfh, len,
146 0, hlimit, 149 0, &ipc6, &fl6, rt,
147 np->tclass, NULL, &fl6, rt, 150 MSG_DONTWAIT, &junk);
148 MSG_DONTWAIT, np->dontfrag, &junk);
149 151
150 if (err) { 152 if (err) {
151 ICMP6_INC_STATS(sock_net(sk), rt->rt6i_idev, 153 ICMP6_INC_STATS(sock_net(sk), rt->rt6i_idev,
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index b07ce21983aa..896350df6423 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -746,10 +746,8 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
746 struct raw6_frag_vec rfv; 746 struct raw6_frag_vec rfv;
747 struct flowi6 fl6; 747 struct flowi6 fl6;
748 struct sockcm_cookie sockc; 748 struct sockcm_cookie sockc;
749 struct ipcm6_cookie ipc6;
749 int addr_len = msg->msg_namelen; 750 int addr_len = msg->msg_namelen;
750 int hlimit = -1;
751 int tclass = -1;
752 int dontfrag = -1;
753 u16 proto; 751 u16 proto;
754 int err; 752 int err;
755 753
@@ -770,6 +768,11 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
770 768
771 fl6.flowi6_mark = sk->sk_mark; 769 fl6.flowi6_mark = sk->sk_mark;
772 770
771 ipc6.hlimit = -1;
772 ipc6.tclass = -1;
773 ipc6.dontfrag = -1;
774 ipc6.opt = NULL;
775
773 if (sin6) { 776 if (sin6) {
774 if (addr_len < SIN6_LEN_RFC2133) 777 if (addr_len < SIN6_LEN_RFC2133)
775 return -EINVAL; 778 return -EINVAL;
@@ -827,10 +830,9 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
827 opt = &opt_space; 830 opt = &opt_space;
828 memset(opt, 0, sizeof(struct ipv6_txoptions)); 831 memset(opt, 0, sizeof(struct ipv6_txoptions));
829 opt->tot_len = sizeof(struct ipv6_txoptions); 832 opt->tot_len = sizeof(struct ipv6_txoptions);
833 ipc6.opt = opt;
830 834
831 err = ip6_datagram_send_ctl(sock_net(sk), sk, msg, &fl6, opt, 835 err = ip6_datagram_send_ctl(sock_net(sk), sk, msg, &fl6, &ipc6, &sockc);
832 &hlimit, &tclass, &dontfrag,
833 &sockc);
834 if (err < 0) { 836 if (err < 0) {
835 fl6_sock_release(flowlabel); 837 fl6_sock_release(flowlabel);
836 return err; 838 return err;
@@ -846,7 +848,7 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
846 if (!opt) { 848 if (!opt) {
847 opt = txopt_get(np); 849 opt = txopt_get(np);
848 opt_to_free = opt; 850 opt_to_free = opt;
849 } 851 }
850 if (flowlabel) 852 if (flowlabel)
851 opt = fl6_merge_options(&opt_space, flowlabel, opt); 853 opt = fl6_merge_options(&opt_space, flowlabel, opt);
852 opt = ipv6_fixup_options(&opt_space, opt); 854 opt = ipv6_fixup_options(&opt_space, opt);
@@ -881,14 +883,14 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
881 err = PTR_ERR(dst); 883 err = PTR_ERR(dst);
882 goto out; 884 goto out;
883 } 885 }
884 if (hlimit < 0) 886 if (ipc6.hlimit < 0)
885 hlimit = ip6_sk_dst_hoplimit(np, &fl6, dst); 887 ipc6.hlimit = ip6_sk_dst_hoplimit(np, &fl6, dst);
886 888
887 if (tclass < 0) 889 if (ipc6.tclass < 0)
888 tclass = np->tclass; 890 ipc6.tclass = np->tclass;
889 891
890 if (dontfrag < 0) 892 if (ipc6.dontfrag < 0)
891 dontfrag = np->dontfrag; 893 ipc6.dontfrag = np->dontfrag;
892 894
893 if (msg->msg_flags&MSG_CONFIRM) 895 if (msg->msg_flags&MSG_CONFIRM)
894 goto do_confirm; 896 goto do_confirm;
@@ -897,10 +899,11 @@ back_from_confirm:
897 if (inet->hdrincl) 899 if (inet->hdrincl)
898 err = rawv6_send_hdrinc(sk, msg, len, &fl6, &dst, msg->msg_flags); 900 err = rawv6_send_hdrinc(sk, msg, len, &fl6, &dst, msg->msg_flags);
899 else { 901 else {
902 ipc6.opt = opt;
900 lock_sock(sk); 903 lock_sock(sk);
901 err = ip6_append_data(sk, raw6_getfrag, &rfv, 904 err = ip6_append_data(sk, raw6_getfrag, &rfv,
902 len, 0, hlimit, tclass, opt, &fl6, (struct rt6_info *)dst, 905 len, 0, &ipc6, &fl6, (struct rt6_info *)dst,
903 msg->msg_flags, dontfrag, &sockc); 906 msg->msg_flags, &sockc);
904 907
905 if (err) 908 if (err)
906 ip6_flush_pending_frames(sk); 909 ip6_flush_pending_frames(sk);
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index f911c63f79e6..aca06094110f 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -1064,11 +1064,9 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
1064 struct ip6_flowlabel *flowlabel = NULL; 1064 struct ip6_flowlabel *flowlabel = NULL;
1065 struct flowi6 fl6; 1065 struct flowi6 fl6;
1066 struct dst_entry *dst; 1066 struct dst_entry *dst;
1067 struct ipcm6_cookie ipc6;
1067 int addr_len = msg->msg_namelen; 1068 int addr_len = msg->msg_namelen;
1068 int ulen = len; 1069 int ulen = len;
1069 int hlimit = -1;
1070 int tclass = -1;
1071 int dontfrag = -1;
1072 int corkreq = up->corkflag || msg->msg_flags&MSG_MORE; 1070 int corkreq = up->corkflag || msg->msg_flags&MSG_MORE;
1073 int err; 1071 int err;
1074 int connected = 0; 1072 int connected = 0;
@@ -1076,6 +1074,10 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
1076 int (*getfrag)(void *, char *, int, int, int, struct sk_buff *); 1074 int (*getfrag)(void *, char *, int, int, int, struct sk_buff *);
1077 struct sockcm_cookie sockc; 1075 struct sockcm_cookie sockc;
1078 1076
1077 ipc6.hlimit = -1;
1078 ipc6.tclass = -1;
1079 ipc6.dontfrag = -1;
1080
1079 /* destination address check */ 1081 /* destination address check */
1080 if (sin6) { 1082 if (sin6) {
1081 if (addr_len < offsetof(struct sockaddr, sa_data)) 1083 if (addr_len < offsetof(struct sockaddr, sa_data))
@@ -1200,10 +1202,9 @@ do_udp_sendmsg:
1200 opt = &opt_space; 1202 opt = &opt_space;
1201 memset(opt, 0, sizeof(struct ipv6_txoptions)); 1203 memset(opt, 0, sizeof(struct ipv6_txoptions));
1202 opt->tot_len = sizeof(*opt); 1204 opt->tot_len = sizeof(*opt);
1205 ipc6.opt = opt;
1203 1206
1204 err = ip6_datagram_send_ctl(sock_net(sk), sk, msg, &fl6, opt, 1207 err = ip6_datagram_send_ctl(sock_net(sk), sk, msg, &fl6, &ipc6, &sockc);
1205 &hlimit, &tclass, &dontfrag,
1206 &sockc);
1207 if (err < 0) { 1208 if (err < 0) {
1208 fl6_sock_release(flowlabel); 1209 fl6_sock_release(flowlabel);
1209 return err; 1210 return err;
@@ -1224,6 +1225,7 @@ do_udp_sendmsg:
1224 if (flowlabel) 1225 if (flowlabel)
1225 opt = fl6_merge_options(&opt_space, flowlabel, opt); 1226 opt = fl6_merge_options(&opt_space, flowlabel, opt);
1226 opt = ipv6_fixup_options(&opt_space, opt); 1227 opt = ipv6_fixup_options(&opt_space, opt);
1228 ipc6.opt = opt;
1227 1229
1228 fl6.flowi6_proto = sk->sk_protocol; 1230 fl6.flowi6_proto = sk->sk_protocol;
1229 if (!ipv6_addr_any(daddr)) 1231 if (!ipv6_addr_any(daddr))
@@ -1253,11 +1255,11 @@ do_udp_sendmsg:
1253 goto out; 1255 goto out;
1254 } 1256 }
1255 1257
1256 if (hlimit < 0) 1258 if (ipc6.hlimit < 0)
1257 hlimit = ip6_sk_dst_hoplimit(np, &fl6, dst); 1259 ipc6.hlimit = ip6_sk_dst_hoplimit(np, &fl6, dst);
1258 1260
1259 if (tclass < 0) 1261 if (ipc6.tclass < 0)
1260 tclass = np->tclass; 1262 ipc6.tclass = np->tclass;
1261 1263
1262 if (msg->msg_flags&MSG_CONFIRM) 1264 if (msg->msg_flags&MSG_CONFIRM)
1263 goto do_confirm; 1265 goto do_confirm;
@@ -1268,9 +1270,9 @@ back_from_confirm:
1268 struct sk_buff *skb; 1270 struct sk_buff *skb;
1269 1271
1270 skb = ip6_make_skb(sk, getfrag, msg, ulen, 1272 skb = ip6_make_skb(sk, getfrag, msg, ulen,
1271 sizeof(struct udphdr), hlimit, tclass, opt, 1273 sizeof(struct udphdr), &ipc6,
1272 &fl6, (struct rt6_info *)dst, 1274 &fl6, (struct rt6_info *)dst,
1273 msg->msg_flags, dontfrag, &sockc); 1275 msg->msg_flags, &sockc);
1274 err = PTR_ERR(skb); 1276 err = PTR_ERR(skb);
1275 if (!IS_ERR_OR_NULL(skb)) 1277 if (!IS_ERR_OR_NULL(skb))
1276 err = udp_v6_send_skb(skb, &fl6); 1278 err = udp_v6_send_skb(skb, &fl6);
@@ -1291,14 +1293,12 @@ back_from_confirm:
1291 up->pending = AF_INET6; 1293 up->pending = AF_INET6;
1292 1294
1293do_append_data: 1295do_append_data:
1294 if (dontfrag < 0) 1296 if (ipc6.dontfrag < 0)
1295 dontfrag = np->dontfrag; 1297 ipc6.dontfrag = np->dontfrag;
1296 up->len += ulen; 1298 up->len += ulen;
1297 err = ip6_append_data(sk, getfrag, msg, ulen, 1299 err = ip6_append_data(sk, getfrag, msg, ulen, sizeof(struct udphdr),
1298 sizeof(struct udphdr), hlimit, tclass, opt, &fl6, 1300 &ipc6, &fl6, (struct rt6_info *)dst,
1299 (struct rt6_info *)dst, 1301 corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags, &sockc);
1300 corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags, dontfrag,
1301 &sockc);
1302 if (err) 1302 if (err)
1303 udp_v6_flush_pending_frames(sk); 1303 udp_v6_flush_pending_frames(sk);
1304 else if (!corkreq) 1304 else if (!corkreq)
diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c
index 46e07267e503..c6f5df1bed12 100644
--- a/net/l2tp/l2tp_ip6.c
+++ b/net/l2tp/l2tp_ip6.c
@@ -495,10 +495,8 @@ static int l2tp_ip6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
495 struct dst_entry *dst = NULL; 495 struct dst_entry *dst = NULL;
496 struct flowi6 fl6; 496 struct flowi6 fl6;
497 struct sockcm_cookie sockc_unused = {0}; 497 struct sockcm_cookie sockc_unused = {0};
498 struct ipcm6_cookie ipc6;
498 int addr_len = msg->msg_namelen; 499 int addr_len = msg->msg_namelen;
499 int hlimit = -1;
500 int tclass = -1;
501 int dontfrag = -1;
502 int transhdrlen = 4; /* zero session-id */ 500 int transhdrlen = 4; /* zero session-id */
503 int ulen = len + transhdrlen; 501 int ulen = len + transhdrlen;
504 int err; 502 int err;
@@ -520,6 +518,10 @@ static int l2tp_ip6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
520 518
521 fl6.flowi6_mark = sk->sk_mark; 519 fl6.flowi6_mark = sk->sk_mark;
522 520
521 ipc6.hlimit = -1;
522 ipc6.tclass = -1;
523 ipc6.dontfrag = -1;
524
523 if (lsa) { 525 if (lsa) {
524 if (addr_len < SIN6_LEN_RFC2133) 526 if (addr_len < SIN6_LEN_RFC2133)
525 return -EINVAL; 527 return -EINVAL;
@@ -564,11 +566,11 @@ static int l2tp_ip6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
564 opt = &opt_space; 566 opt = &opt_space;
565 memset(opt, 0, sizeof(struct ipv6_txoptions)); 567 memset(opt, 0, sizeof(struct ipv6_txoptions));
566 opt->tot_len = sizeof(struct ipv6_txoptions); 568 opt->tot_len = sizeof(struct ipv6_txoptions);
569 ipc6.opt = opt;
567 570
568 err = ip6_datagram_send_ctl(sock_net(sk), sk, msg, &fl6, opt, 571 err = ip6_datagram_send_ctl(sock_net(sk), sk, msg, &fl6, &ipc6,
569 &hlimit, &tclass, &dontfrag, 572 &sockc_unused);
570 &sockc_unused); 573 if (err < 0) {
571 if (err < 0) {
572 fl6_sock_release(flowlabel); 574 fl6_sock_release(flowlabel);
573 return err; 575 return err;
574 } 576 }
@@ -588,6 +590,7 @@ static int l2tp_ip6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
588 if (flowlabel) 590 if (flowlabel)
589 opt = fl6_merge_options(&opt_space, flowlabel, opt); 591 opt = fl6_merge_options(&opt_space, flowlabel, opt);
590 opt = ipv6_fixup_options(&opt_space, opt); 592 opt = ipv6_fixup_options(&opt_space, opt);
593 ipc6.opt = opt;
591 594
592 fl6.flowi6_proto = sk->sk_protocol; 595 fl6.flowi6_proto = sk->sk_protocol;
593 if (!ipv6_addr_any(daddr)) 596 if (!ipv6_addr_any(daddr))
@@ -612,14 +615,14 @@ static int l2tp_ip6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
612 goto out; 615 goto out;
613 } 616 }
614 617
615 if (hlimit < 0) 618 if (ipc6.hlimit < 0)
616 hlimit = ip6_sk_dst_hoplimit(np, &fl6, dst); 619 ipc6.hlimit = ip6_sk_dst_hoplimit(np, &fl6, dst);
617 620
618 if (tclass < 0) 621 if (ipc6.tclass < 0)
619 tclass = np->tclass; 622 ipc6.tclass = np->tclass;
620 623
621 if (dontfrag < 0) 624 if (ipc6.dontfrag < 0)
622 dontfrag = np->dontfrag; 625 ipc6.dontfrag = np->dontfrag;
623 626
624 if (msg->msg_flags & MSG_CONFIRM) 627 if (msg->msg_flags & MSG_CONFIRM)
625 goto do_confirm; 628 goto do_confirm;
@@ -627,9 +630,9 @@ static int l2tp_ip6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
627back_from_confirm: 630back_from_confirm:
628 lock_sock(sk); 631 lock_sock(sk);
629 err = ip6_append_data(sk, ip_generic_getfrag, msg, 632 err = ip6_append_data(sk, ip_generic_getfrag, msg,
630 ulen, transhdrlen, hlimit, tclass, opt, 633 ulen, transhdrlen, &ipc6,
631 &fl6, (struct rt6_info *)dst, 634 &fl6, (struct rt6_info *)dst,
632 msg->msg_flags, dontfrag, &sockc_unused); 635 msg->msg_flags, &sockc_unused);
633 if (err) 636 if (err)
634 ip6_flush_pending_frames(sk); 637 ip6_flush_pending_frames(sk);
635 else if (!(msg->msg_flags & MSG_MORE)) 638 else if (!(msg->msg_flags & MSG_MORE))