diff options
Diffstat (limited to 'net/ipv4/udp.c')
| -rw-r--r-- | net/ipv4/udp.c | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 32e0bef60d0a..fb23c2e63b52 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
| @@ -1260,6 +1260,49 @@ void udp_lib_unhash(struct sock *sk) | |||
| 1260 | } | 1260 | } |
| 1261 | EXPORT_SYMBOL(udp_lib_unhash); | 1261 | EXPORT_SYMBOL(udp_lib_unhash); |
| 1262 | 1262 | ||
| 1263 | /* | ||
| 1264 | * inet_rcv_saddr was changed, we must rehash secondary hash | ||
| 1265 | */ | ||
| 1266 | void udp_lib_rehash(struct sock *sk, u16 newhash) | ||
| 1267 | { | ||
| 1268 | if (sk_hashed(sk)) { | ||
| 1269 | struct udp_table *udptable = sk->sk_prot->h.udp_table; | ||
| 1270 | struct udp_hslot *hslot, *hslot2, *nhslot2; | ||
| 1271 | |||
| 1272 | hslot2 = udp_hashslot2(udptable, udp_sk(sk)->udp_portaddr_hash); | ||
| 1273 | nhslot2 = udp_hashslot2(udptable, newhash); | ||
| 1274 | udp_sk(sk)->udp_portaddr_hash = newhash; | ||
| 1275 | if (hslot2 != nhslot2) { | ||
| 1276 | hslot = udp_hashslot(udptable, sock_net(sk), | ||
| 1277 | udp_sk(sk)->udp_port_hash); | ||
| 1278 | /* we must lock primary chain too */ | ||
| 1279 | spin_lock_bh(&hslot->lock); | ||
| 1280 | |||
| 1281 | spin_lock(&hslot2->lock); | ||
| 1282 | hlist_nulls_del_init_rcu(&udp_sk(sk)->udp_portaddr_node); | ||
| 1283 | hslot2->count--; | ||
| 1284 | spin_unlock(&hslot2->lock); | ||
| 1285 | |||
| 1286 | spin_lock(&nhslot2->lock); | ||
| 1287 | hlist_nulls_add_head_rcu(&udp_sk(sk)->udp_portaddr_node, | ||
| 1288 | &nhslot2->head); | ||
| 1289 | nhslot2->count++; | ||
| 1290 | spin_unlock(&nhslot2->lock); | ||
| 1291 | |||
| 1292 | spin_unlock_bh(&hslot->lock); | ||
| 1293 | } | ||
| 1294 | } | ||
| 1295 | } | ||
| 1296 | EXPORT_SYMBOL(udp_lib_rehash); | ||
| 1297 | |||
| 1298 | static void udp_v4_rehash(struct sock *sk) | ||
| 1299 | { | ||
| 1300 | u16 new_hash = udp4_portaddr_hash(sock_net(sk), | ||
| 1301 | inet_sk(sk)->inet_rcv_saddr, | ||
| 1302 | inet_sk(sk)->inet_num); | ||
| 1303 | udp_lib_rehash(sk, new_hash); | ||
| 1304 | } | ||
| 1305 | |||
| 1263 | static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) | 1306 | static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) |
| 1264 | { | 1307 | { |
| 1265 | int rc; | 1308 | int rc; |
| @@ -1843,6 +1886,7 @@ struct proto udp_prot = { | |||
| 1843 | .backlog_rcv = __udp_queue_rcv_skb, | 1886 | .backlog_rcv = __udp_queue_rcv_skb, |
| 1844 | .hash = udp_lib_hash, | 1887 | .hash = udp_lib_hash, |
| 1845 | .unhash = udp_lib_unhash, | 1888 | .unhash = udp_lib_unhash, |
| 1889 | .rehash = udp_v4_rehash, | ||
| 1846 | .get_port = udp_v4_get_port, | 1890 | .get_port = udp_v4_get_port, |
| 1847 | .memory_allocated = &udp_memory_allocated, | 1891 | .memory_allocated = &udp_memory_allocated, |
| 1848 | .sysctl_mem = sysctl_udp_mem, | 1892 | .sysctl_mem = sysctl_udp_mem, |
