neighbour.c (edfbeecd92b0c4a648ed96a7e255bfc9a1bc4642) | neighbour.c (dac9c9790e542777079999900594fd069ba10489) |
---|---|
1/* 2 * Generic address resolution entity 3 * 4 * Authors: 5 * Pedro Roque <roque@di.fc.ul.pt> 6 * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> 7 * 8 * This program is free software; you can redistribute it and/or --- 1266 unchanged lines hidden (view full) --- 1275 rcu_read_unlock(); 1276 1277 write_lock_bh(&neigh->lock); 1278 } 1279 __skb_queue_purge(&neigh->arp_queue); 1280 neigh->arp_queue_len_bytes = 0; 1281 } 1282out: | 1/* 2 * Generic address resolution entity 3 * 4 * Authors: 5 * Pedro Roque <roque@di.fc.ul.pt> 6 * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> 7 * 8 * This program is free software; you can redistribute it and/or --- 1266 unchanged lines hidden (view full) --- 1275 rcu_read_unlock(); 1276 1277 write_lock_bh(&neigh->lock); 1278 } 1279 __skb_queue_purge(&neigh->arp_queue); 1280 neigh->arp_queue_len_bytes = 0; 1281 } 1282out: |
1283 if (update_isrouter) { 1284 neigh->flags = (flags & NEIGH_UPDATE_F_ISROUTER) ? 1285 (neigh->flags | NTF_ROUTER) : 1286 (neigh->flags & ~NTF_ROUTER); 1287 } | 1283 if (update_isrouter) 1284 neigh_update_is_router(neigh, flags, ¬ify); |
1288 write_unlock_bh(&neigh->lock); 1289 1290 if (notify) 1291 neigh_update_notify(neigh, nlmsg_pid); 1292 1293 return err; 1294} 1295EXPORT_SYMBOL(neigh_update); --- 411 unchanged lines hidden (view full) --- 1707 1708out: 1709 return err; 1710} 1711 1712static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, 1713 struct netlink_ext_ack *extack) 1714{ | 1285 write_unlock_bh(&neigh->lock); 1286 1287 if (notify) 1288 neigh_update_notify(neigh, nlmsg_pid); 1289 1290 return err; 1291} 1292EXPORT_SYMBOL(neigh_update); --- 411 unchanged lines hidden (view full) --- 1704 1705out: 1706 return err; 1707} 1708 1709static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, 1710 struct netlink_ext_ack *extack) 1711{ |
1715 int flags = NEIGH_UPDATE_F_ADMIN | NEIGH_UPDATE_F_OVERRIDE; | 1712 int flags = NEIGH_UPDATE_F_ADMIN | NEIGH_UPDATE_F_OVERRIDE | 1713 NEIGH_UPDATE_F_OVERRIDE_ISROUTER; |
1716 struct net *net = sock_net(skb->sk); 1717 struct ndmsg *ndm; 1718 struct nlattr *tb[NDA_MAX+1]; 1719 struct neigh_table *tbl; 1720 struct net_device *dev = NULL; 1721 struct neighbour *neigh; 1722 void *dst, *lladdr; 1723 int err; --- 58 unchanged lines hidden (view full) --- 1782 } else { 1783 if (nlh->nlmsg_flags & NLM_F_EXCL) { 1784 err = -EEXIST; 1785 neigh_release(neigh); 1786 goto out; 1787 } 1788 1789 if (!(nlh->nlmsg_flags & NLM_F_REPLACE)) | 1714 struct net *net = sock_net(skb->sk); 1715 struct ndmsg *ndm; 1716 struct nlattr *tb[NDA_MAX+1]; 1717 struct neigh_table *tbl; 1718 struct net_device *dev = NULL; 1719 struct neighbour *neigh; 1720 void *dst, *lladdr; 1721 int err; --- 58 unchanged lines hidden (view full) --- 1780 } else { 1781 if (nlh->nlmsg_flags & NLM_F_EXCL) { 1782 err = -EEXIST; 1783 neigh_release(neigh); 1784 goto out; 1785 } 1786 1787 if (!(nlh->nlmsg_flags & NLM_F_REPLACE)) |
1790 flags &= ~NEIGH_UPDATE_F_OVERRIDE; | 1788 flags &= ~(NEIGH_UPDATE_F_OVERRIDE | 1789 NEIGH_UPDATE_F_OVERRIDE_ISROUTER); |
1791 } 1792 1793 if (ndm->ndm_flags & NTF_EXT_LEARNED) 1794 flags |= NEIGH_UPDATE_F_EXT_LEARNED; 1795 | 1790 } 1791 1792 if (ndm->ndm_flags & NTF_EXT_LEARNED) 1793 flags |= NEIGH_UPDATE_F_EXT_LEARNED; 1794 |
1795 if (ndm->ndm_flags & NTF_ROUTER) 1796 flags |= NEIGH_UPDATE_F_ISROUTER; 1797 |
|
1796 if (ndm->ndm_flags & NTF_USE) { 1797 neigh_event_send(neigh, NULL); 1798 err = 0; 1799 } else 1800 err = neigh_update(neigh, lladdr, ndm->ndm_state, flags, 1801 NETLINK_CB(skb).portid); 1802 neigh_release(neigh); 1803 --- 518 unchanged lines hidden (view full) --- 2322static bool neigh_ifindex_filtered(struct net_device *dev, int filter_idx) 2323{ 2324 if (filter_idx && dev->ifindex != filter_idx) 2325 return true; 2326 2327 return false; 2328} 2329 | 1798 if (ndm->ndm_flags & NTF_USE) { 1799 neigh_event_send(neigh, NULL); 1800 err = 0; 1801 } else 1802 err = neigh_update(neigh, lladdr, ndm->ndm_state, flags, 1803 NETLINK_CB(skb).portid); 1804 neigh_release(neigh); 1805 --- 518 unchanged lines hidden (view full) --- 2324static bool neigh_ifindex_filtered(struct net_device *dev, int filter_idx) 2325{ 2326 if (filter_idx && dev->ifindex != filter_idx) 2327 return true; 2328 2329 return false; 2330} 2331 |
2332struct neigh_dump_filter { 2333 int master_idx; 2334 int dev_idx; 2335}; 2336 |
|
2330static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb, | 2337static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb, |
2331 struct netlink_callback *cb) | 2338 struct netlink_callback *cb, 2339 struct neigh_dump_filter *filter) |
2332{ 2333 struct net *net = sock_net(skb->sk); | 2340{ 2341 struct net *net = sock_net(skb->sk); |
2334 const struct nlmsghdr *nlh = cb->nlh; 2335 struct nlattr *tb[NDA_MAX + 1]; | |
2336 struct neighbour *n; 2337 int rc, h, s_h = cb->args[1]; 2338 int idx, s_idx = idx = cb->args[2]; 2339 struct neigh_hash_table *nht; | 2342 struct neighbour *n; 2343 int rc, h, s_h = cb->args[1]; 2344 int idx, s_idx = idx = cb->args[2]; 2345 struct neigh_hash_table *nht; |
2340 int filter_master_idx = 0, filter_idx = 0; | |
2341 unsigned int flags = NLM_F_MULTI; | 2346 unsigned int flags = NLM_F_MULTI; |
2342 int err; | |
2343 | 2347 |
2344 err = nlmsg_parse(nlh, sizeof(struct ndmsg), tb, NDA_MAX, NULL, NULL); 2345 if (!err) { 2346 if (tb[NDA_IFINDEX]) { 2347 if (nla_len(tb[NDA_IFINDEX]) != sizeof(u32)) 2348 return -EINVAL; 2349 filter_idx = nla_get_u32(tb[NDA_IFINDEX]); 2350 } 2351 if (tb[NDA_MASTER]) { 2352 if (nla_len(tb[NDA_MASTER]) != sizeof(u32)) 2353 return -EINVAL; 2354 filter_master_idx = nla_get_u32(tb[NDA_MASTER]); 2355 } 2356 if (filter_idx || filter_master_idx) 2357 flags |= NLM_F_DUMP_FILTERED; 2358 } | 2348 if (filter->dev_idx || filter->master_idx) 2349 flags |= NLM_F_DUMP_FILTERED; |
2359 2360 rcu_read_lock_bh(); 2361 nht = rcu_dereference_bh(tbl->nht); 2362 2363 for (h = s_h; h < (1 << nht->hash_shift); h++) { 2364 if (h > s_h) 2365 s_idx = 0; 2366 for (n = rcu_dereference_bh(nht->hash_buckets[h]), idx = 0; 2367 n != NULL; 2368 n = rcu_dereference_bh(n->next)) { 2369 if (idx < s_idx || !net_eq(dev_net(n->dev), net)) 2370 goto next; | 2350 2351 rcu_read_lock_bh(); 2352 nht = rcu_dereference_bh(tbl->nht); 2353 2354 for (h = s_h; h < (1 << nht->hash_shift); h++) { 2355 if (h > s_h) 2356 s_idx = 0; 2357 for (n = rcu_dereference_bh(nht->hash_buckets[h]), idx = 0; 2358 n != NULL; 2359 n = rcu_dereference_bh(n->next)) { 2360 if (idx < s_idx || !net_eq(dev_net(n->dev), net)) 2361 goto next; |
2371 if (neigh_ifindex_filtered(n->dev, filter_idx) || 2372 neigh_master_filtered(n->dev, filter_master_idx)) | 2362 if (neigh_ifindex_filtered(n->dev, filter->dev_idx) || 2363 neigh_master_filtered(n->dev, filter->master_idx)) |
2373 goto next; 2374 if (neigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid, 2375 cb->nlh->nlmsg_seq, 2376 RTM_NEWNEIGH, 2377 flags) < 0) { 2378 rc = -1; 2379 goto out; 2380 } --- 5 unchanged lines hidden (view full) --- 2386out: 2387 rcu_read_unlock_bh(); 2388 cb->args[1] = h; 2389 cb->args[2] = idx; 2390 return rc; 2391} 2392 2393static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb, | 2364 goto next; 2365 if (neigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid, 2366 cb->nlh->nlmsg_seq, 2367 RTM_NEWNEIGH, 2368 flags) < 0) { 2369 rc = -1; 2370 goto out; 2371 } --- 5 unchanged lines hidden (view full) --- 2377out: 2378 rcu_read_unlock_bh(); 2379 cb->args[1] = h; 2380 cb->args[2] = idx; 2381 return rc; 2382} 2383 2384static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb, |
2394 struct netlink_callback *cb) | 2385 struct netlink_callback *cb, 2386 struct neigh_dump_filter *filter) |
2395{ 2396 struct pneigh_entry *n; 2397 struct net *net = sock_net(skb->sk); 2398 int rc, h, s_h = cb->args[3]; 2399 int idx, s_idx = idx = cb->args[4]; | 2387{ 2388 struct pneigh_entry *n; 2389 struct net *net = sock_net(skb->sk); 2390 int rc, h, s_h = cb->args[3]; 2391 int idx, s_idx = idx = cb->args[4]; |
2392 unsigned int flags = NLM_F_MULTI; |
|
2400 | 2393 |
2394 if (filter->dev_idx || filter->master_idx) 2395 flags |= NLM_F_DUMP_FILTERED; 2396 |
|
2401 read_lock_bh(&tbl->lock); 2402 2403 for (h = s_h; h <= PNEIGH_HASHMASK; h++) { 2404 if (h > s_h) 2405 s_idx = 0; 2406 for (n = tbl->phash_buckets[h], idx = 0; n; n = n->next) { 2407 if (idx < s_idx || pneigh_net(n) != net) 2408 goto next; | 2397 read_lock_bh(&tbl->lock); 2398 2399 for (h = s_h; h <= PNEIGH_HASHMASK; h++) { 2400 if (h > s_h) 2401 s_idx = 0; 2402 for (n = tbl->phash_buckets[h], idx = 0; n; n = n->next) { 2403 if (idx < s_idx || pneigh_net(n) != net) 2404 goto next; |
2405 if (neigh_ifindex_filtered(n->dev, filter->dev_idx) || 2406 neigh_master_filtered(n->dev, filter->master_idx)) 2407 goto next; |
|
2409 if (pneigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid, 2410 cb->nlh->nlmsg_seq, | 2408 if (pneigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid, 2409 cb->nlh->nlmsg_seq, |
2411 RTM_NEWNEIGH, 2412 NLM_F_MULTI, tbl) < 0) { | 2410 RTM_NEWNEIGH, flags, tbl) < 0) { |
2413 read_unlock_bh(&tbl->lock); 2414 rc = -1; 2415 goto out; 2416 } 2417 next: 2418 idx++; 2419 } 2420 } --- 4 unchanged lines hidden (view full) --- 2425 cb->args[3] = h; 2426 cb->args[4] = idx; 2427 return rc; 2428 2429} 2430 2431static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb) 2432{ | 2411 read_unlock_bh(&tbl->lock); 2412 rc = -1; 2413 goto out; 2414 } 2415 next: 2416 idx++; 2417 } 2418 } --- 4 unchanged lines hidden (view full) --- 2423 cb->args[3] = h; 2424 cb->args[4] = idx; 2425 return rc; 2426 2427} 2428 2429static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb) 2430{ |
2431 const struct nlmsghdr *nlh = cb->nlh; 2432 struct neigh_dump_filter filter = {}; 2433 struct nlattr *tb[NDA_MAX + 1]; |
|
2433 struct neigh_table *tbl; 2434 int t, family, s_t; 2435 int proxy = 0; 2436 int err; 2437 | 2434 struct neigh_table *tbl; 2435 int t, family, s_t; 2436 int proxy = 0; 2437 int err; 2438 |
2438 family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family; | 2439 family = ((struct rtgenmsg *)nlmsg_data(nlh))->rtgen_family; |
2439 2440 /* check for full ndmsg structure presence, family member is 2441 * the same for both structures 2442 */ | 2440 2441 /* check for full ndmsg structure presence, family member is 2442 * the same for both structures 2443 */ |
2443 if (nlmsg_len(cb->nlh) >= sizeof(struct ndmsg) && 2444 ((struct ndmsg *) nlmsg_data(cb->nlh))->ndm_flags == NTF_PROXY) | 2444 if (nlmsg_len(nlh) >= sizeof(struct ndmsg) && 2445 ((struct ndmsg *)nlmsg_data(nlh))->ndm_flags == NTF_PROXY) |
2445 proxy = 1; 2446 | 2446 proxy = 1; 2447 |
2448 err = nlmsg_parse(nlh, sizeof(struct ndmsg), tb, NDA_MAX, NULL, 2449 cb->extack); 2450 if (!err) { 2451 if (tb[NDA_IFINDEX]) { 2452 if (nla_len(tb[NDA_IFINDEX]) != sizeof(u32)) 2453 return -EINVAL; 2454 filter.dev_idx = nla_get_u32(tb[NDA_IFINDEX]); 2455 } 2456 if (tb[NDA_MASTER]) { 2457 if (nla_len(tb[NDA_MASTER]) != sizeof(u32)) 2458 return -EINVAL; 2459 filter.master_idx = nla_get_u32(tb[NDA_MASTER]); 2460 } 2461 } |
|
2447 s_t = cb->args[0]; 2448 2449 for (t = 0; t < NEIGH_NR_TABLES; t++) { 2450 tbl = neigh_tables[t]; 2451 2452 if (!tbl) 2453 continue; 2454 if (t < s_t || (family && tbl->family != family)) 2455 continue; 2456 if (t > s_t) 2457 memset(&cb->args[1], 0, sizeof(cb->args) - 2458 sizeof(cb->args[0])); 2459 if (proxy) | 2462 s_t = cb->args[0]; 2463 2464 for (t = 0; t < NEIGH_NR_TABLES; t++) { 2465 tbl = neigh_tables[t]; 2466 2467 if (!tbl) 2468 continue; 2469 if (t < s_t || (family && tbl->family != family)) 2470 continue; 2471 if (t > s_t) 2472 memset(&cb->args[1], 0, sizeof(cb->args) - 2473 sizeof(cb->args[0])); 2474 if (proxy) |
2460 err = pneigh_dump_table(tbl, skb, cb); | 2475 err = pneigh_dump_table(tbl, skb, cb, &filter); |
2461 else | 2476 else |
2462 err = neigh_dump_table(tbl, skb, cb); | 2477 err = neigh_dump_table(tbl, skb, cb, &filter); |
2463 if (err < 0) 2464 break; 2465 } 2466 2467 cb->args[0] = t; 2468 return skb->len; 2469} 2470 --- 809 unchanged lines hidden --- | 2478 if (err < 0) 2479 break; 2480 } 2481 2482 cb->args[0] = t; 2483 return skb->len; 2484} 2485 --- 809 unchanged lines hidden --- |