diff options
Diffstat (limited to 'net/ipv4/udp.c')
| -rw-r--r-- | net/ipv4/udp.c | 30 |
1 files changed, 16 insertions, 14 deletions
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index f0126fdd7e04..8fef859db35d 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
| @@ -95,6 +95,7 @@ | |||
| 95 | #include <linux/mm.h> | 95 | #include <linux/mm.h> |
| 96 | #include <linux/inet.h> | 96 | #include <linux/inet.h> |
| 97 | #include <linux/netdevice.h> | 97 | #include <linux/netdevice.h> |
| 98 | #include <linux/slab.h> | ||
| 98 | #include <net/tcp_states.h> | 99 | #include <net/tcp_states.h> |
| 99 | #include <linux/skbuff.h> | 100 | #include <linux/skbuff.h> |
| 100 | #include <linux/proc_fs.h> | 101 | #include <linux/proc_fs.h> |
| @@ -471,8 +472,8 @@ static struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr, | |||
| 471 | if (hslot->count < hslot2->count) | 472 | if (hslot->count < hslot2->count) |
| 472 | goto begin; | 473 | goto begin; |
| 473 | 474 | ||
| 474 | result = udp4_lib_lookup2(net, INADDR_ANY, sport, | 475 | result = udp4_lib_lookup2(net, saddr, sport, |
| 475 | daddr, hnum, dif, | 476 | INADDR_ANY, hnum, dif, |
| 476 | hslot2, slot2); | 477 | hslot2, slot2); |
| 477 | } | 478 | } |
| 478 | rcu_read_unlock(); | 479 | rcu_read_unlock(); |
| @@ -1117,7 +1118,7 @@ int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
| 1117 | struct inet_sock *inet = inet_sk(sk); | 1118 | struct inet_sock *inet = inet_sk(sk); |
| 1118 | struct sockaddr_in *sin = (struct sockaddr_in *)msg->msg_name; | 1119 | struct sockaddr_in *sin = (struct sockaddr_in *)msg->msg_name; |
| 1119 | struct sk_buff *skb; | 1120 | struct sk_buff *skb; |
| 1120 | unsigned int ulen, copied; | 1121 | unsigned int ulen; |
| 1121 | int peeked; | 1122 | int peeked; |
| 1122 | int err; | 1123 | int err; |
| 1123 | int is_udplite = IS_UDPLITE(sk); | 1124 | int is_udplite = IS_UDPLITE(sk); |
| @@ -1138,10 +1139,9 @@ try_again: | |||
| 1138 | goto out; | 1139 | goto out; |
| 1139 | 1140 | ||
| 1140 | ulen = skb->len - sizeof(struct udphdr); | 1141 | ulen = skb->len - sizeof(struct udphdr); |
| 1141 | copied = len; | 1142 | if (len > ulen) |
| 1142 | if (copied > ulen) | 1143 | len = ulen; |
| 1143 | copied = ulen; | 1144 | else if (len < ulen) |
| 1144 | else if (copied < ulen) | ||
| 1145 | msg->msg_flags |= MSG_TRUNC; | 1145 | msg->msg_flags |= MSG_TRUNC; |
| 1146 | 1146 | ||
| 1147 | /* | 1147 | /* |
| @@ -1150,14 +1150,14 @@ try_again: | |||
| 1150 | * coverage checksum (UDP-Lite), do it before the copy. | 1150 | * coverage checksum (UDP-Lite), do it before the copy. |
| 1151 | */ | 1151 | */ |
| 1152 | 1152 | ||
| 1153 | if (copied < ulen || UDP_SKB_CB(skb)->partial_cov) { | 1153 | if (len < ulen || UDP_SKB_CB(skb)->partial_cov) { |
| 1154 | if (udp_lib_checksum_complete(skb)) | 1154 | if (udp_lib_checksum_complete(skb)) |
| 1155 | goto csum_copy_err; | 1155 | goto csum_copy_err; |
| 1156 | } | 1156 | } |
| 1157 | 1157 | ||
| 1158 | if (skb_csum_unnecessary(skb)) | 1158 | if (skb_csum_unnecessary(skb)) |
| 1159 | err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), | 1159 | err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), |
| 1160 | msg->msg_iov, copied); | 1160 | msg->msg_iov, len); |
| 1161 | else { | 1161 | else { |
| 1162 | err = skb_copy_and_csum_datagram_iovec(skb, | 1162 | err = skb_copy_and_csum_datagram_iovec(skb, |
| 1163 | sizeof(struct udphdr), | 1163 | sizeof(struct udphdr), |
| @@ -1186,7 +1186,7 @@ try_again: | |||
| 1186 | if (inet->cmsg_flags) | 1186 | if (inet->cmsg_flags) |
| 1187 | ip_cmsg_recv(msg, skb); | 1187 | ip_cmsg_recv(msg, skb); |
| 1188 | 1188 | ||
| 1189 | err = copied; | 1189 | err = len; |
| 1190 | if (flags & MSG_TRUNC) | 1190 | if (flags & MSG_TRUNC) |
| 1191 | err = ulen; | 1191 | err = ulen; |
| 1192 | 1192 | ||
| @@ -1372,8 +1372,10 @@ int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
| 1372 | bh_lock_sock(sk); | 1372 | bh_lock_sock(sk); |
| 1373 | if (!sock_owned_by_user(sk)) | 1373 | if (!sock_owned_by_user(sk)) |
| 1374 | rc = __udp_queue_rcv_skb(sk, skb); | 1374 | rc = __udp_queue_rcv_skb(sk, skb); |
| 1375 | else | 1375 | else if (sk_add_backlog(sk, skb)) { |
| 1376 | sk_add_backlog(sk, skb); | 1376 | bh_unlock_sock(sk); |
| 1377 | goto drop; | ||
| 1378 | } | ||
| 1377 | bh_unlock_sock(sk); | 1379 | bh_unlock_sock(sk); |
| 1378 | 1380 | ||
| 1379 | return rc; | 1381 | return rc; |
| @@ -2027,12 +2029,12 @@ static struct udp_seq_afinfo udp4_seq_afinfo = { | |||
| 2027 | }, | 2029 | }, |
| 2028 | }; | 2030 | }; |
| 2029 | 2031 | ||
| 2030 | static int udp4_proc_init_net(struct net *net) | 2032 | static int __net_init udp4_proc_init_net(struct net *net) |
| 2031 | { | 2033 | { |
| 2032 | return udp_proc_register(net, &udp4_seq_afinfo); | 2034 | return udp_proc_register(net, &udp4_seq_afinfo); |
| 2033 | } | 2035 | } |
| 2034 | 2036 | ||
| 2035 | static void udp4_proc_exit_net(struct net *net) | 2037 | static void __net_exit udp4_proc_exit_net(struct net *net) |
| 2036 | { | 2038 | { |
| 2037 | udp_proc_unregister(net, &udp4_seq_afinfo); | 2039 | udp_proc_unregister(net, &udp4_seq_afinfo); |
| 2038 | } | 2040 | } |
