/* * Utility function for families */ struct net_device *ieee802154_get_dev(struct net *net, struct ieee802154_addr *addr) { struct net_device *dev = NULL; struct net_device *tmp; u16 pan_id, short_addr; switch (addr->addr_type) { case IEEE802154_ADDR_LONG: rcu_read_lock(); dev = dev_getbyhwaddr_rcu(net, ARPHRD_IEEE802154, addr->hwaddr); if (dev) dev_hold(dev); rcu_read_unlock(); break; case IEEE802154_ADDR_SHORT: if (addr->pan_id == 0xffff || addr->short_addr == IEEE802154_ADDR_UNDEF || addr->short_addr == 0xffff) break; rtnl_lock(); for_each_netdev(net, tmp) { if (tmp->type != ARPHRD_IEEE802154) continue; pan_id = ieee802154_mlme_ops(tmp)->get_pan_id(tmp); short_addr = ieee802154_mlme_ops(tmp)->get_short_addr(tmp); if (pan_id == addr->pan_id && short_addr == addr->short_addr) { dev = tmp; dev_hold(dev); break; } } rtnl_unlock(); break; default: pr_warning("Unsupported ieee802154 address type: %d\n", addr->addr_type); break; } return dev; }
static int arp_req_set_public(struct net *net, struct arpreq *r, struct net_device *dev) { __be32 ip = ((struct sockaddr_in *)&r->arp_pa)->sin_addr.s_addr; __be32 mask = ((struct sockaddr_in *)&r->arp_netmask)->sin_addr.s_addr; if (mask && mask != htonl(0xFFFFFFFF)) return -EINVAL; if (!dev && (r->arp_flags & ATF_COM)) { dev = dev_getbyhwaddr_rcu(net, r->arp_ha.sa_family, r->arp_ha.sa_data); if (!dev) return -ENODEV; } if (mask) { if (pneigh_lookup(&arp_tbl, net, &ip, dev, 1) == NULL) return -ENOBUFS; return 0; } return arp_req_set_proxy(net, dev, 1); }