aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/ipv6/datagram.c21
-rw-r--r--net/ipv6/icmp.c5
-rw-r--r--net/ipv6/ip6_flowlabel.c3
-rw-r--r--net/ipv6/ip6_output.c2
-rw-r--r--net/ipv6/ipv6_sockglue.c3
-rw-r--r--net/ipv6/raw.c9
-rw-r--r--net/ipv6/udp.c9
7 files changed, 42 insertions, 10 deletions
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index 622dc7939a1b..f5076d349b18 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -497,7 +497,7 @@ int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb)
497int datagram_send_ctl(struct net *net, 497int datagram_send_ctl(struct net *net,
498 struct msghdr *msg, struct flowi *fl, 498 struct msghdr *msg, struct flowi *fl,
499 struct ipv6_txoptions *opt, 499 struct ipv6_txoptions *opt,
500 int *hlimit, int *tclass) 500 int *hlimit, int *tclass, int *dontfrag)
501{ 501{
502 struct in6_pktinfo *src_info; 502 struct in6_pktinfo *src_info;
503 struct cmsghdr *cmsg; 503 struct cmsghdr *cmsg;
@@ -737,6 +737,25 @@ int datagram_send_ctl(struct net *net,
737 737
738 break; 738 break;
739 } 739 }
740
741 case IPV6_DONTFRAG:
742 {
743 int df;
744
745 err = -EINVAL;
746 if (cmsg->cmsg_len != CMSG_LEN(sizeof(int))) {
747 goto exit_f;
748 }
749
750 df = *(int *)CMSG_DATA(cmsg);
751 if (df < 0 || df > 1)
752 goto exit_f;
753
754 err = 0;
755 *dontfrag = df;
756
757 break;
758 }
740 default: 759 default:
741 LIMIT_NETDEBUG(KERN_DEBUG "invalid cmsg type: %d\n", 760 LIMIT_NETDEBUG(KERN_DEBUG "invalid cmsg type: %d\n",
742 cmsg->cmsg_type); 761 cmsg->cmsg_type);
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 12d2fa42657d..ce7992982557 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -481,7 +481,7 @@ route_done:
481 len + sizeof(struct icmp6hdr), 481 len + sizeof(struct icmp6hdr),
482 sizeof(struct icmp6hdr), hlimit, 482 sizeof(struct icmp6hdr), hlimit,
483 np->tclass, NULL, &fl, (struct rt6_info*)dst, 483 np->tclass, NULL, &fl, (struct rt6_info*)dst,
484 MSG_DONTWAIT); 484 MSG_DONTWAIT, np->dontfrag);
485 if (err) { 485 if (err) {
486 ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTMSGS); 486 ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTMSGS);
487 ip6_flush_pending_frames(sk); 487 ip6_flush_pending_frames(sk);
@@ -561,7 +561,8 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
561 561
562 err = ip6_append_data(sk, icmpv6_getfrag, &msg, skb->len + sizeof(struct icmp6hdr), 562 err = ip6_append_data(sk, icmpv6_getfrag, &msg, skb->len + sizeof(struct icmp6hdr),
563 sizeof(struct icmp6hdr), hlimit, np->tclass, NULL, &fl, 563 sizeof(struct icmp6hdr), hlimit, np->tclass, NULL, &fl,
564 (struct rt6_info*)dst, MSG_DONTWAIT); 564 (struct rt6_info*)dst, MSG_DONTWAIT,
565 np->dontfrag);
565 566
566 if (err) { 567 if (err) {
567 ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTMSGS); 568 ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTMSGS);
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c
index 14e23216eb28..13654686aeab 100644
--- a/net/ipv6/ip6_flowlabel.c
+++ b/net/ipv6/ip6_flowlabel.c
@@ -360,7 +360,8 @@ fl_create(struct net *net, struct in6_flowlabel_req *freq, char __user *optval,
360 msg.msg_control = (void*)(fl->opt+1); 360 msg.msg_control = (void*)(fl->opt+1);
361 flowi.oif = 0; 361 flowi.oif = 0;
362 362
363 err = datagram_send_ctl(net, &msg, &flowi, fl->opt, &junk, &junk); 363 err = datagram_send_ctl(net, &msg, &flowi, fl->opt, &junk,
364 &junk, &junk);
364 if (err) 365 if (err)
365 goto done; 366 goto done;
366 err = -EINVAL; 367 err = -EINVAL;
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 263d4cf5a8de..54d43dd1f085 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -1105,7 +1105,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
1105 int offset, int len, int odd, struct sk_buff *skb), 1105 int offset, int len, int odd, struct sk_buff *skb),
1106 void *from, int length, int transhdrlen, 1106 void *from, int length, int transhdrlen,
1107 int hlimit, int tclass, struct ipv6_txoptions *opt, struct flowi *fl, 1107 int hlimit, int tclass, struct ipv6_txoptions *opt, struct flowi *fl,
1108 struct rt6_info *rt, unsigned int flags) 1108 struct rt6_info *rt, unsigned int flags, int dontfrag)
1109{ 1109{
1110 struct inet_sock *inet = inet_sk(sk); 1110 struct inet_sock *inet = inet_sk(sk);
1111 struct ipv6_pinfo *np = inet6_sk(sk); 1111 struct ipv6_pinfo *np = inet6_sk(sk);
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index 2bf9eda72788..bd43f0152c21 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -458,7 +458,8 @@ sticky_done:
458 msg.msg_controllen = optlen; 458 msg.msg_controllen = optlen;
459 msg.msg_control = (void*)(opt+1); 459 msg.msg_control = (void*)(opt+1);
460 460
461 retv = datagram_send_ctl(net, &msg, &fl, opt, &junk, &junk); 461 retv = datagram_send_ctl(net, &msg, &fl, opt, &junk, &junk,
462 &junk);
462 if (retv) 463 if (retv)
463 goto done; 464 goto done;
464update: 465update:
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 8763b1a0814a..44a84ea9b3e8 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -733,6 +733,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
733 int addr_len = msg->msg_namelen; 733 int addr_len = msg->msg_namelen;
734 int hlimit = -1; 734 int hlimit = -1;
735 int tclass = -1; 735 int tclass = -1;
736 int dontfrag = -1;
736 u16 proto; 737 u16 proto;
737 int err; 738 int err;
738 739
@@ -811,7 +812,8 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
811 memset(opt, 0, sizeof(struct ipv6_txoptions)); 812 memset(opt, 0, sizeof(struct ipv6_txoptions));
812 opt->tot_len = sizeof(struct ipv6_txoptions); 813 opt->tot_len = sizeof(struct ipv6_txoptions);
813 814
814 err = datagram_send_ctl(sock_net(sk), msg, &fl, opt, &hlimit, &tclass); 815 err = datagram_send_ctl(sock_net(sk), msg, &fl, opt, &hlimit,
816 &tclass, &dontfrag);
815 if (err < 0) { 817 if (err < 0) {
816 fl6_sock_release(flowlabel); 818 fl6_sock_release(flowlabel);
817 return err; 819 return err;
@@ -880,6 +882,9 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
880 if (tclass < 0) 882 if (tclass < 0)
881 tclass = np->tclass; 883 tclass = np->tclass;
882 884
885 if (dontfrag < 0)
886 dontfrag = np->dontfrag;
887
883 if (msg->msg_flags&MSG_CONFIRM) 888 if (msg->msg_flags&MSG_CONFIRM)
884 goto do_confirm; 889 goto do_confirm;
885 890
@@ -890,7 +895,7 @@ back_from_confirm:
890 lock_sock(sk); 895 lock_sock(sk);
891 err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov, 896 err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov,
892 len, 0, hlimit, tclass, opt, &fl, (struct rt6_info*)dst, 897 len, 0, hlimit, tclass, opt, &fl, (struct rt6_info*)dst,
893 msg->msg_flags); 898 msg->msg_flags, dontfrag);
894 899
895 if (err) 900 if (err)
896 ip6_flush_pending_frames(sk); 901 ip6_flush_pending_frames(sk);
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 92bf9033e245..39e3665d9460 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -919,6 +919,7 @@ int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk,
919 int ulen = len; 919 int ulen = len;
920 int hlimit = -1; 920 int hlimit = -1;
921 int tclass = -1; 921 int tclass = -1;
922 int dontfrag = -1;
922 int corkreq = up->corkflag || msg->msg_flags&MSG_MORE; 923 int corkreq = up->corkflag || msg->msg_flags&MSG_MORE;
923 int err; 924 int err;
924 int connected = 0; 925 int connected = 0;
@@ -1049,7 +1050,8 @@ do_udp_sendmsg:
1049 memset(opt, 0, sizeof(struct ipv6_txoptions)); 1050 memset(opt, 0, sizeof(struct ipv6_txoptions));
1050 opt->tot_len = sizeof(*opt); 1051 opt->tot_len = sizeof(*opt);
1051 1052
1052 err = datagram_send_ctl(sock_net(sk), msg, &fl, opt, &hlimit, &tclass); 1053 err = datagram_send_ctl(sock_net(sk), msg, &fl, opt, &hlimit,
1054 &tclass, &dontfrag);
1053 if (err < 0) { 1055 if (err < 0) {
1054 fl6_sock_release(flowlabel); 1056 fl6_sock_release(flowlabel);
1055 return err; 1057 return err;
@@ -1120,6 +1122,9 @@ do_udp_sendmsg:
1120 if (tclass < 0) 1122 if (tclass < 0)
1121 tclass = np->tclass; 1123 tclass = np->tclass;
1122 1124
1125 if (dontfrag < 0)
1126 dontfrag = np->dontfrag;
1127
1123 if (msg->msg_flags&MSG_CONFIRM) 1128 if (msg->msg_flags&MSG_CONFIRM)
1124 goto do_confirm; 1129 goto do_confirm;
1125back_from_confirm: 1130back_from_confirm:
@@ -1143,7 +1148,7 @@ do_append_data:
1143 err = ip6_append_data(sk, getfrag, msg->msg_iov, ulen, 1148 err = ip6_append_data(sk, getfrag, msg->msg_iov, ulen,
1144 sizeof(struct udphdr), hlimit, tclass, opt, &fl, 1149 sizeof(struct udphdr), hlimit, tclass, opt, &fl,
1145 (struct rt6_info*)dst, 1150 (struct rt6_info*)dst,
1146 corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags); 1151 corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags, dontfrag);
1147 if (err) 1152 if (err)
1148 udp_v6_flush_pending_frames(sk); 1153 udp_v6_flush_pending_frames(sk);
1149 else if (!corkreq) 1154 else if (!corkreq)