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, &notify);
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 ---