diff options
Diffstat (limited to 'net/ipv4/udp.c')
-rw-r--r-- | net/ipv4/udp.c | 42 |
1 files changed, 26 insertions, 16 deletions
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index c36522a0f113..baeec29fe0f1 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -233,7 +233,8 @@ int udp_lib_get_port(struct sock *sk, unsigned short snum, | |||
233 | */ | 233 | */ |
234 | do { | 234 | do { |
235 | if (low <= snum && snum <= high && | 235 | if (low <= snum && snum <= high && |
236 | !test_bit(snum >> udptable->log, bitmap)) | 236 | !test_bit(snum >> udptable->log, bitmap) && |
237 | !inet_is_reserved_local_port(snum)) | ||
237 | goto found; | 238 | goto found; |
238 | snum += rand; | 239 | snum += rand; |
239 | } while (snum != first); | 240 | } while (snum != first); |
@@ -307,13 +308,13 @@ static int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2) | |||
307 | static unsigned int udp4_portaddr_hash(struct net *net, __be32 saddr, | 308 | static unsigned int udp4_portaddr_hash(struct net *net, __be32 saddr, |
308 | unsigned int port) | 309 | unsigned int port) |
309 | { | 310 | { |
310 | return jhash_1word(saddr, net_hash_mix(net)) ^ port; | 311 | return jhash_1word((__force u32)saddr, net_hash_mix(net)) ^ port; |
311 | } | 312 | } |
312 | 313 | ||
313 | int udp_v4_get_port(struct sock *sk, unsigned short snum) | 314 | int udp_v4_get_port(struct sock *sk, unsigned short snum) |
314 | { | 315 | { |
315 | unsigned int hash2_nulladdr = | 316 | unsigned int hash2_nulladdr = |
316 | udp4_portaddr_hash(sock_net(sk), INADDR_ANY, snum); | 317 | udp4_portaddr_hash(sock_net(sk), htonl(INADDR_ANY), snum); |
317 | unsigned int hash2_partial = | 318 | unsigned int hash2_partial = |
318 | udp4_portaddr_hash(sock_net(sk), inet_sk(sk)->inet_rcv_saddr, 0); | 319 | udp4_portaddr_hash(sock_net(sk), inet_sk(sk)->inet_rcv_saddr, 0); |
319 | 320 | ||
@@ -466,14 +467,14 @@ static struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr, | |||
466 | daddr, hnum, dif, | 467 | daddr, hnum, dif, |
467 | hslot2, slot2); | 468 | hslot2, slot2); |
468 | if (!result) { | 469 | if (!result) { |
469 | hash2 = udp4_portaddr_hash(net, INADDR_ANY, hnum); | 470 | hash2 = udp4_portaddr_hash(net, htonl(INADDR_ANY), hnum); |
470 | slot2 = hash2 & udptable->mask; | 471 | slot2 = hash2 & udptable->mask; |
471 | hslot2 = &udptable->hash2[slot2]; | 472 | hslot2 = &udptable->hash2[slot2]; |
472 | if (hslot->count < hslot2->count) | 473 | if (hslot->count < hslot2->count) |
473 | goto begin; | 474 | goto begin; |
474 | 475 | ||
475 | result = udp4_lib_lookup2(net, saddr, sport, | 476 | result = udp4_lib_lookup2(net, saddr, sport, |
476 | INADDR_ANY, hnum, dif, | 477 | htonl(INADDR_ANY), hnum, dif, |
477 | hslot2, slot2); | 478 | hslot2, slot2); |
478 | } | 479 | } |
479 | rcu_read_unlock(); | 480 | rcu_read_unlock(); |
@@ -1062,10 +1063,10 @@ static unsigned int first_packet_length(struct sock *sk) | |||
1062 | spin_unlock_bh(&rcvq->lock); | 1063 | spin_unlock_bh(&rcvq->lock); |
1063 | 1064 | ||
1064 | if (!skb_queue_empty(&list_kill)) { | 1065 | if (!skb_queue_empty(&list_kill)) { |
1065 | lock_sock(sk); | 1066 | lock_sock_bh(sk); |
1066 | __skb_queue_purge(&list_kill); | 1067 | __skb_queue_purge(&list_kill); |
1067 | sk_mem_reclaim_partial(sk); | 1068 | sk_mem_reclaim_partial(sk); |
1068 | release_sock(sk); | 1069 | unlock_sock_bh(sk); |
1069 | } | 1070 | } |
1070 | return res; | 1071 | return res; |
1071 | } | 1072 | } |
@@ -1196,10 +1197,10 @@ out: | |||
1196 | return err; | 1197 | return err; |
1197 | 1198 | ||
1198 | csum_copy_err: | 1199 | csum_copy_err: |
1199 | lock_sock(sk); | 1200 | lock_sock_bh(sk); |
1200 | if (!skb_kill_datagram(sk, skb, flags)) | 1201 | if (!skb_kill_datagram(sk, skb, flags)) |
1201 | UDP_INC_STATS_USER(sock_net(sk), UDP_MIB_INERRORS, is_udplite); | 1202 | UDP_INC_STATS_USER(sock_net(sk), UDP_MIB_INERRORS, is_udplite); |
1202 | release_sock(sk); | 1203 | unlock_sock_bh(sk); |
1203 | 1204 | ||
1204 | if (noblock) | 1205 | if (noblock) |
1205 | return -EAGAIN; | 1206 | return -EAGAIN; |
@@ -1217,6 +1218,7 @@ int udp_disconnect(struct sock *sk, int flags) | |||
1217 | sk->sk_state = TCP_CLOSE; | 1218 | sk->sk_state = TCP_CLOSE; |
1218 | inet->inet_daddr = 0; | 1219 | inet->inet_daddr = 0; |
1219 | inet->inet_dport = 0; | 1220 | inet->inet_dport = 0; |
1221 | sock_rps_save_rxhash(sk, 0); | ||
1220 | sk->sk_bound_dev_if = 0; | 1222 | sk->sk_bound_dev_if = 0; |
1221 | if (!(sk->sk_userlocks & SOCK_BINDADDR_LOCK)) | 1223 | if (!(sk->sk_userlocks & SOCK_BINDADDR_LOCK)) |
1222 | inet_reset_saddr(sk); | 1224 | inet_reset_saddr(sk); |
@@ -1258,8 +1260,12 @@ EXPORT_SYMBOL(udp_lib_unhash); | |||
1258 | 1260 | ||
1259 | static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) | 1261 | static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) |
1260 | { | 1262 | { |
1261 | int rc = sock_queue_rcv_skb(sk, skb); | 1263 | int rc; |
1264 | |||
1265 | if (inet_sk(sk)->inet_daddr) | ||
1266 | sock_rps_save_rxhash(sk, skb->rxhash); | ||
1262 | 1267 | ||
1268 | rc = ip_queue_rcv_skb(sk, skb); | ||
1263 | if (rc < 0) { | 1269 | if (rc < 0) { |
1264 | int is_udplite = IS_UDPLITE(sk); | 1270 | int is_udplite = IS_UDPLITE(sk); |
1265 | 1271 | ||
@@ -1367,6 +1373,10 @@ int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
1367 | goto drop; | 1373 | goto drop; |
1368 | } | 1374 | } |
1369 | 1375 | ||
1376 | |||
1377 | if (sk_rcvqueues_full(sk, skb)) | ||
1378 | goto drop; | ||
1379 | |||
1370 | rc = 0; | 1380 | rc = 0; |
1371 | 1381 | ||
1372 | bh_lock_sock(sk); | 1382 | bh_lock_sock(sk); |
@@ -1615,9 +1625,9 @@ int udp_rcv(struct sk_buff *skb) | |||
1615 | 1625 | ||
1616 | void udp_destroy_sock(struct sock *sk) | 1626 | void udp_destroy_sock(struct sock *sk) |
1617 | { | 1627 | { |
1618 | lock_sock(sk); | 1628 | lock_sock_bh(sk); |
1619 | udp_flush_pending_frames(sk); | 1629 | udp_flush_pending_frames(sk); |
1620 | release_sock(sk); | 1630 | unlock_sock_bh(sk); |
1621 | } | 1631 | } |
1622 | 1632 | ||
1623 | /* | 1633 | /* |
@@ -1676,8 +1686,8 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname, | |||
1676 | return -ENOPROTOOPT; | 1686 | return -ENOPROTOOPT; |
1677 | if (val != 0 && val < 8) /* Illegal coverage: use default (8) */ | 1687 | if (val != 0 && val < 8) /* Illegal coverage: use default (8) */ |
1678 | val = 8; | 1688 | val = 8; |
1679 | else if (val > USHORT_MAX) | 1689 | else if (val > USHRT_MAX) |
1680 | val = USHORT_MAX; | 1690 | val = USHRT_MAX; |
1681 | up->pcslen = val; | 1691 | up->pcslen = val; |
1682 | up->pcflag |= UDPLITE_SEND_CC; | 1692 | up->pcflag |= UDPLITE_SEND_CC; |
1683 | break; | 1693 | break; |
@@ -1690,8 +1700,8 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname, | |||
1690 | return -ENOPROTOOPT; | 1700 | return -ENOPROTOOPT; |
1691 | if (val != 0 && val < 8) /* Avoid silly minimal values. */ | 1701 | if (val != 0 && val < 8) /* Avoid silly minimal values. */ |
1692 | val = 8; | 1702 | val = 8; |
1693 | else if (val > USHORT_MAX) | 1703 | else if (val > USHRT_MAX) |
1694 | val = USHORT_MAX; | 1704 | val = USHRT_MAX; |
1695 | up->pcrlen = val; | 1705 | up->pcrlen = val; |
1696 | up->pcflag |= UDPLITE_RECV_CC; | 1706 | up->pcflag |= UDPLITE_RECV_CC; |
1697 | break; | 1707 | break; |