diff options
Diffstat (limited to 'net/ipv6/udp.c')
-rw-r--r-- | net/ipv6/udp.c | 41 |
1 files changed, 31 insertions, 10 deletions
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 90824852f59..3d7a2c0b836 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -91,9 +91,9 @@ static unsigned int udp6_portaddr_hash(struct net *net, | |||
91 | if (ipv6_addr_any(addr6)) | 91 | if (ipv6_addr_any(addr6)) |
92 | hash = jhash_1word(0, mix); | 92 | hash = jhash_1word(0, mix); |
93 | else if (ipv6_addr_v4mapped(addr6)) | 93 | else if (ipv6_addr_v4mapped(addr6)) |
94 | hash = jhash_1word(addr6->s6_addr32[3], mix); | 94 | hash = jhash_1word((__force u32)addr6->s6_addr32[3], mix); |
95 | else | 95 | else |
96 | hash = jhash2(addr6->s6_addr32, 4, mix); | 96 | hash = jhash2((__force u32 *)addr6->s6_addr32, 4, mix); |
97 | 97 | ||
98 | return hash ^ port; | 98 | return hash ^ port; |
99 | } | 99 | } |
@@ -335,6 +335,9 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk, | |||
335 | if (flags & MSG_ERRQUEUE) | 335 | if (flags & MSG_ERRQUEUE) |
336 | return ipv6_recv_error(sk, msg, len); | 336 | return ipv6_recv_error(sk, msg, len); |
337 | 337 | ||
338 | if (np->rxpmtu && np->rxopt.bits.rxpmtu) | ||
339 | return ipv6_recv_rxpmtu(sk, msg, len); | ||
340 | |||
338 | try_again: | 341 | try_again: |
339 | skb = __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0), | 342 | skb = __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0), |
340 | &peeked, &err); | 343 | &peeked, &err); |
@@ -421,7 +424,7 @@ out: | |||
421 | return err; | 424 | return err; |
422 | 425 | ||
423 | csum_copy_err: | 426 | csum_copy_err: |
424 | lock_sock(sk); | 427 | lock_sock_bh(sk); |
425 | if (!skb_kill_datagram(sk, skb, flags)) { | 428 | if (!skb_kill_datagram(sk, skb, flags)) { |
426 | if (is_udp4) | 429 | if (is_udp4) |
427 | UDP_INC_STATS_USER(sock_net(sk), | 430 | UDP_INC_STATS_USER(sock_net(sk), |
@@ -430,7 +433,7 @@ csum_copy_err: | |||
430 | UDP6_INC_STATS_USER(sock_net(sk), | 433 | UDP6_INC_STATS_USER(sock_net(sk), |
431 | UDP_MIB_INERRORS, is_udplite); | 434 | UDP_MIB_INERRORS, is_udplite); |
432 | } | 435 | } |
433 | release_sock(sk); | 436 | unlock_sock_bh(sk); |
434 | 437 | ||
435 | if (flags & MSG_DONTWAIT) | 438 | if (flags & MSG_DONTWAIT) |
436 | return -EAGAIN; | 439 | return -EAGAIN; |
@@ -511,7 +514,7 @@ int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) | |||
511 | goto drop; | 514 | goto drop; |
512 | } | 515 | } |
513 | 516 | ||
514 | if ((rc = sock_queue_rcv_skb(sk, skb)) < 0) { | 517 | if ((rc = ip_queue_rcv_skb(sk, skb)) < 0) { |
515 | /* Note that an ENOMEM error is charged twice */ | 518 | /* Note that an ENOMEM error is charged twice */ |
516 | if (rc == -ENOMEM) | 519 | if (rc == -ENOMEM) |
517 | UDP6_INC_STATS_BH(sock_net(sk), | 520 | UDP6_INC_STATS_BH(sock_net(sk), |
@@ -581,6 +584,10 @@ static void flush_stack(struct sock **stack, unsigned int count, | |||
581 | 584 | ||
582 | sk = stack[i]; | 585 | sk = stack[i]; |
583 | if (skb1) { | 586 | if (skb1) { |
587 | if (sk_rcvqueues_full(sk, skb)) { | ||
588 | kfree_skb(skb1); | ||
589 | goto drop; | ||
590 | } | ||
584 | bh_lock_sock(sk); | 591 | bh_lock_sock(sk); |
585 | if (!sock_owned_by_user(sk)) | 592 | if (!sock_owned_by_user(sk)) |
586 | udpv6_queue_rcv_skb(sk, skb1); | 593 | udpv6_queue_rcv_skb(sk, skb1); |
@@ -692,7 +699,7 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, | |||
692 | u32 ulen = 0; | 699 | u32 ulen = 0; |
693 | 700 | ||
694 | if (!pskb_may_pull(skb, sizeof(struct udphdr))) | 701 | if (!pskb_may_pull(skb, sizeof(struct udphdr))) |
695 | goto short_packet; | 702 | goto discard; |
696 | 703 | ||
697 | saddr = &ipv6_hdr(skb)->saddr; | 704 | saddr = &ipv6_hdr(skb)->saddr; |
698 | daddr = &ipv6_hdr(skb)->daddr; | 705 | daddr = &ipv6_hdr(skb)->daddr; |
@@ -756,6 +763,10 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, | |||
756 | 763 | ||
757 | /* deliver */ | 764 | /* deliver */ |
758 | 765 | ||
766 | if (sk_rcvqueues_full(sk, skb)) { | ||
767 | sock_put(sk); | ||
768 | goto discard; | ||
769 | } | ||
759 | bh_lock_sock(sk); | 770 | bh_lock_sock(sk); |
760 | if (!sock_owned_by_user(sk)) | 771 | if (!sock_owned_by_user(sk)) |
761 | udpv6_queue_rcv_skb(sk, skb); | 772 | udpv6_queue_rcv_skb(sk, skb); |
@@ -770,9 +781,14 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, | |||
770 | return 0; | 781 | return 0; |
771 | 782 | ||
772 | short_packet: | 783 | short_packet: |
773 | LIMIT_NETDEBUG(KERN_DEBUG "UDP%sv6: short packet: %d/%u\n", | 784 | LIMIT_NETDEBUG(KERN_DEBUG "UDP%sv6: short packet: From [%pI6c]:%u %d/%d to [%pI6c]:%u\n", |
774 | proto == IPPROTO_UDPLITE ? "-Lite" : "", | 785 | proto == IPPROTO_UDPLITE ? "-Lite" : "", |
775 | ulen, skb->len); | 786 | saddr, |
787 | ntohs(uh->source), | ||
788 | ulen, | ||
789 | skb->len, | ||
790 | daddr, | ||
791 | ntohs(uh->dest)); | ||
776 | 792 | ||
777 | discard: | 793 | discard: |
778 | UDP6_INC_STATS_BH(net, UDP_MIB_INERRORS, proto == IPPROTO_UDPLITE); | 794 | UDP6_INC_STATS_BH(net, UDP_MIB_INERRORS, proto == IPPROTO_UDPLITE); |
@@ -919,6 +935,7 @@ int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
919 | int ulen = len; | 935 | int ulen = len; |
920 | int hlimit = -1; | 936 | int hlimit = -1; |
921 | int tclass = -1; | 937 | int tclass = -1; |
938 | int dontfrag = -1; | ||
922 | int corkreq = up->corkflag || msg->msg_flags&MSG_MORE; | 939 | int corkreq = up->corkflag || msg->msg_flags&MSG_MORE; |
923 | int err; | 940 | int err; |
924 | int connected = 0; | 941 | int connected = 0; |
@@ -1049,7 +1066,8 @@ do_udp_sendmsg: | |||
1049 | memset(opt, 0, sizeof(struct ipv6_txoptions)); | 1066 | memset(opt, 0, sizeof(struct ipv6_txoptions)); |
1050 | opt->tot_len = sizeof(*opt); | 1067 | opt->tot_len = sizeof(*opt); |
1051 | 1068 | ||
1052 | err = datagram_send_ctl(sock_net(sk), msg, &fl, opt, &hlimit, &tclass); | 1069 | err = datagram_send_ctl(sock_net(sk), msg, &fl, opt, &hlimit, |
1070 | &tclass, &dontfrag); | ||
1053 | if (err < 0) { | 1071 | if (err < 0) { |
1054 | fl6_sock_release(flowlabel); | 1072 | fl6_sock_release(flowlabel); |
1055 | return err; | 1073 | return err; |
@@ -1120,6 +1138,9 @@ do_udp_sendmsg: | |||
1120 | if (tclass < 0) | 1138 | if (tclass < 0) |
1121 | tclass = np->tclass; | 1139 | tclass = np->tclass; |
1122 | 1140 | ||
1141 | if (dontfrag < 0) | ||
1142 | dontfrag = np->dontfrag; | ||
1143 | |||
1123 | if (msg->msg_flags&MSG_CONFIRM) | 1144 | if (msg->msg_flags&MSG_CONFIRM) |
1124 | goto do_confirm; | 1145 | goto do_confirm; |
1125 | back_from_confirm: | 1146 | back_from_confirm: |
@@ -1143,7 +1164,7 @@ do_append_data: | |||
1143 | err = ip6_append_data(sk, getfrag, msg->msg_iov, ulen, | 1164 | err = ip6_append_data(sk, getfrag, msg->msg_iov, ulen, |
1144 | sizeof(struct udphdr), hlimit, tclass, opt, &fl, | 1165 | sizeof(struct udphdr), hlimit, tclass, opt, &fl, |
1145 | (struct rt6_info*)dst, | 1166 | (struct rt6_info*)dst, |
1146 | corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags); | 1167 | corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags, dontfrag); |
1147 | if (err) | 1168 | if (err) |
1148 | udp_v6_flush_pending_frames(sk); | 1169 | udp_v6_flush_pending_frames(sk); |
1149 | else if (!corkreq) | 1170 | else if (!corkreq) |