diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv6/datagram.c | 21 | ||||
-rw-r--r-- | net/ipv6/icmp.c | 5 | ||||
-rw-r--r-- | net/ipv6/ip6_flowlabel.c | 3 | ||||
-rw-r--r-- | net/ipv6/ip6_output.c | 2 | ||||
-rw-r--r-- | net/ipv6/ipv6_sockglue.c | 3 | ||||
-rw-r--r-- | net/ipv6/raw.c | 9 | ||||
-rw-r--r-- | net/ipv6/udp.c | 9 |
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) | |||
497 | int datagram_send_ctl(struct net *net, | 497 | int 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; |
464 | update: | 465 | update: |
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; |
1125 | back_from_confirm: | 1130 | back_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) |