summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSoheil Hassas Yeganeh <soheil@google.com>2016-04-02 23:08:11 -0400
committerDavid S. Miller <davem@davemloft.net>2016-04-04 15:50:30 -0400
commitad1e46a837163a3e7160a1250825bcfafd2e714b (patch)
treef02d47ab7df711de7a6794fe54eae6768eb7b30f
parent24025c465f77c3585f73450bab19501b2edd6fba (diff)
ipv6: process socket-level control messages in IPv6
Process socket-level control messages by invoking __sock_cmsg_send in ip6_datagram_send_ctl for control messages on the SOL_SOCKET layer. This makes sure whenever ip6_datagram_send_ctl is called for udp and raw, we also process socket-level control messages. This is a bit uglier than IPv4, since IPv6 does not have something like ipcm_cookie. Perhaps we can later create a control message cookie for IPv6? Note that this commit interprets new control messages that were ignored before. As such, this commit does not change the behavior of IPv6 control messages. Signed-off-by: Soheil Hassas Yeganeh <soheil@google.com> Acked-by: Willem de Bruijn <willemb@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/transp_v6.h3
-rw-r--r--net/ipv6/datagram.c9
-rw-r--r--net/ipv6/ip6_flowlabel.c3
-rw-r--r--net/ipv6/ipv6_sockglue.c3
-rw-r--r--net/ipv6/raw.c6
-rw-r--r--net/ipv6/udp.c5
-rw-r--r--net/l2tp/l2tp_ip6.c8
7 files changed, 28 insertions, 9 deletions
diff --git a/include/net/transp_v6.h b/include/net/transp_v6.h
index b927413dde86..2b1c3450ab20 100644
--- a/include/net/transp_v6.h
+++ b/include/net/transp_v6.h
@@ -42,7 +42,8 @@ void ip6_datagram_recv_specific_ctl(struct sock *sk, struct msghdr *msg,
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 ipv6_txoptions *opt,
45 int *hlimit, int *tclass, int *dontfrag); 45 int *hlimit, int *tclass, int *dontfrag,
46 struct sockcm_cookie *sockc);
46 47
47void ip6_dgram_sock_seq_show(struct seq_file *seq, struct sock *sp, 48void ip6_dgram_sock_seq_show(struct seq_file *seq, struct sock *sp,
48 __u16 srcp, __u16 destp, int bucket); 49 __u16 srcp, __u16 destp, int bucket);
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index 428162155280..a73d70119fcd 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -685,7 +685,8 @@ EXPORT_SYMBOL_GPL(ip6_datagram_recv_ctl);
685int ip6_datagram_send_ctl(struct net *net, struct sock *sk, 685int ip6_datagram_send_ctl(struct net *net, struct sock *sk,
686 struct msghdr *msg, struct flowi6 *fl6, 686 struct msghdr *msg, struct flowi6 *fl6,
687 struct ipv6_txoptions *opt, 687 struct ipv6_txoptions *opt,
688 int *hlimit, int *tclass, int *dontfrag) 688 int *hlimit, int *tclass, int *dontfrag,
689 struct sockcm_cookie *sockc)
689{ 690{
690 struct in6_pktinfo *src_info; 691 struct in6_pktinfo *src_info;
691 struct cmsghdr *cmsg; 692 struct cmsghdr *cmsg;
@@ -702,6 +703,12 @@ int ip6_datagram_send_ctl(struct net *net, struct sock *sk,
702 goto exit_f; 703 goto exit_f;
703 } 704 }
704 705
706 if (cmsg->cmsg_level == SOL_SOCKET) {
707 if (__sock_cmsg_send(sk, msg, cmsg, sockc))
708 return -EINVAL;
709 continue;
710 }
711
705 if (cmsg->cmsg_level != SOL_IPV6) 712 if (cmsg->cmsg_level != SOL_IPV6)
706 continue; 713 continue;
707 714
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c
index dc2db4f7b182..35d3ddc328f8 100644
--- a/net/ipv6/ip6_flowlabel.c
+++ b/net/ipv6/ip6_flowlabel.c
@@ -372,6 +372,7 @@ fl_create(struct net *net, struct sock *sk, struct in6_flowlabel_req *freq,
372 if (olen > 0) { 372 if (olen > 0) {
373 struct msghdr msg; 373 struct msghdr msg;
374 struct flowi6 flowi6; 374 struct flowi6 flowi6;
375 struct sockcm_cookie sockc_junk;
375 int junk; 376 int junk;
376 377
377 err = -ENOMEM; 378 err = -ENOMEM;
@@ -390,7 +391,7 @@ fl_create(struct net *net, struct sock *sk, struct in6_flowlabel_req *freq,
390 memset(&flowi6, 0, sizeof(flowi6)); 391 memset(&flowi6, 0, sizeof(flowi6));
391 392
392 err = ip6_datagram_send_ctl(net, sk, &msg, &flowi6, fl->opt, 393 err = ip6_datagram_send_ctl(net, sk, &msg, &flowi6, fl->opt,
393 &junk, &junk, &junk); 394 &junk, &junk, &junk, &sockc_junk);
394 if (err) 395 if (err)
395 goto done; 396 goto done;
396 err = -EINVAL; 397 err = -EINVAL;
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index 4449ad1f8114..a5557d22f89e 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -471,6 +471,7 @@ sticky_done:
471 struct ipv6_txoptions *opt = NULL; 471 struct ipv6_txoptions *opt = NULL;
472 struct msghdr msg; 472 struct msghdr msg;
473 struct flowi6 fl6; 473 struct flowi6 fl6;
474 struct sockcm_cookie sockc_junk;
474 int junk; 475 int junk;
475 476
476 memset(&fl6, 0, sizeof(fl6)); 477 memset(&fl6, 0, sizeof(fl6));
@@ -503,7 +504,7 @@ sticky_done:
503 msg.msg_control = (void *)(opt+1); 504 msg.msg_control = (void *)(opt+1);
504 505
505 retv = ip6_datagram_send_ctl(net, sk, &msg, &fl6, opt, &junk, 506 retv = ip6_datagram_send_ctl(net, sk, &msg, &fl6, opt, &junk,
506 &junk, &junk); 507 &junk, &junk, &sockc_junk);
507 if (retv) 508 if (retv)
508 goto done; 509 goto done;
509update: 510update:
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index fa59dd7a427e..f175ec0a97ce 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -745,6 +745,7 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
745 struct dst_entry *dst = NULL; 745 struct dst_entry *dst = NULL;
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 int addr_len = msg->msg_namelen; 749 int addr_len = msg->msg_namelen;
749 int hlimit = -1; 750 int hlimit = -1;
750 int tclass = -1; 751 int tclass = -1;
@@ -821,13 +822,16 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
821 if (fl6.flowi6_oif == 0) 822 if (fl6.flowi6_oif == 0)
822 fl6.flowi6_oif = sk->sk_bound_dev_if; 823 fl6.flowi6_oif = sk->sk_bound_dev_if;
823 824
825 sockc.tsflags = 0;
826
824 if (msg->msg_controllen) { 827 if (msg->msg_controllen) {
825 opt = &opt_space; 828 opt = &opt_space;
826 memset(opt, 0, sizeof(struct ipv6_txoptions)); 829 memset(opt, 0, sizeof(struct ipv6_txoptions));
827 opt->tot_len = sizeof(struct ipv6_txoptions); 830 opt->tot_len = sizeof(struct ipv6_txoptions);
828 831
829 err = ip6_datagram_send_ctl(sock_net(sk), sk, msg, &fl6, opt, 832 err = ip6_datagram_send_ctl(sock_net(sk), sk, msg, &fl6, opt,
830 &hlimit, &tclass, &dontfrag); 833 &hlimit, &tclass, &dontfrag,
834 &sockc);
831 if (err < 0) { 835 if (err < 0) {
832 fl6_sock_release(flowlabel); 836 fl6_sock_release(flowlabel);
833 return err; 837 return err;
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 8125931106be..2a787af42163 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -1128,6 +1128,7 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
1128 int connected = 0; 1128 int connected = 0;
1129 int is_udplite = IS_UDPLITE(sk); 1129 int is_udplite = IS_UDPLITE(sk);
1130 int (*getfrag)(void *, char *, int, int, int, struct sk_buff *); 1130 int (*getfrag)(void *, char *, int, int, int, struct sk_buff *);
1131 struct sockcm_cookie sockc;
1131 1132
1132 /* destination address check */ 1133 /* destination address check */
1133 if (sin6) { 1134 if (sin6) {
@@ -1247,6 +1248,7 @@ do_udp_sendmsg:
1247 fl6.flowi6_oif = np->sticky_pktinfo.ipi6_ifindex; 1248 fl6.flowi6_oif = np->sticky_pktinfo.ipi6_ifindex;
1248 1249
1249 fl6.flowi6_mark = sk->sk_mark; 1250 fl6.flowi6_mark = sk->sk_mark;
1251 sockc.tsflags = 0;
1250 1252
1251 if (msg->msg_controllen) { 1253 if (msg->msg_controllen) {
1252 opt = &opt_space; 1254 opt = &opt_space;
@@ -1254,7 +1256,8 @@ do_udp_sendmsg:
1254 opt->tot_len = sizeof(*opt); 1256 opt->tot_len = sizeof(*opt);
1255 1257
1256 err = ip6_datagram_send_ctl(sock_net(sk), sk, msg, &fl6, opt, 1258 err = ip6_datagram_send_ctl(sock_net(sk), sk, msg, &fl6, opt,
1257 &hlimit, &tclass, &dontfrag); 1259 &hlimit, &tclass, &dontfrag,
1260 &sockc);
1258 if (err < 0) { 1261 if (err < 0) {
1259 fl6_sock_release(flowlabel); 1262 fl6_sock_release(flowlabel);
1260 return err; 1263 return err;
diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c
index 6b54ff3ff4cb..4f29a4a0f360 100644
--- a/net/l2tp/l2tp_ip6.c
+++ b/net/l2tp/l2tp_ip6.c
@@ -492,6 +492,7 @@ static int l2tp_ip6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
492 struct ip6_flowlabel *flowlabel = NULL; 492 struct ip6_flowlabel *flowlabel = NULL;
493 struct dst_entry *dst = NULL; 493 struct dst_entry *dst = NULL;
494 struct flowi6 fl6; 494 struct flowi6 fl6;
495 struct sockcm_cookie sockc_unused = {0};
495 int addr_len = msg->msg_namelen; 496 int addr_len = msg->msg_namelen;
496 int hlimit = -1; 497 int hlimit = -1;
497 int tclass = -1; 498 int tclass = -1;
@@ -562,9 +563,10 @@ static int l2tp_ip6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
562 memset(opt, 0, sizeof(struct ipv6_txoptions)); 563 memset(opt, 0, sizeof(struct ipv6_txoptions));
563 opt->tot_len = sizeof(struct ipv6_txoptions); 564 opt->tot_len = sizeof(struct ipv6_txoptions);
564 565
565 err = ip6_datagram_send_ctl(sock_net(sk), sk, msg, &fl6, opt, 566 err = ip6_datagram_send_ctl(sock_net(sk), sk, msg, &fl6, opt,
566 &hlimit, &tclass, &dontfrag); 567 &hlimit, &tclass, &dontfrag,
567 if (err < 0) { 568 &sockc_unused);
569 if (err < 0) {
568 fl6_sock_release(flowlabel); 570 fl6_sock_release(flowlabel);
569 return err; 571 return err;
570 } 572 }