int addrconf_ifid_802154_6lowpan(u8 *eui, struct net_device *dev) { struct wpan_dev *wpan_dev = lowpan_802154_dev(dev)->wdev->ieee802154_ptr; /* Set short_addr autoconfiguration if short_addr is present only */ if (!lowpan_802154_is_valid_src_short_addr(wpan_dev->short_addr)) return -1; /* For either address format, all zero addresses MUST NOT be used */ if (wpan_dev->pan_id == cpu_to_le16(0x0000) && wpan_dev->short_addr == cpu_to_le16(0x0000)) return -1; /* Alternatively, if no PAN ID is known, 16 zero bits may be used */ if (wpan_dev->pan_id == cpu_to_le16(IEEE802154_PAN_ID_BROADCAST)) memset(eui, 0, 2); else ieee802154_le16_to_be16(eui, &wpan_dev->pan_id); /* The "Universal/Local" (U/L) bit shall be set to zero */ eui[0] &= ~2; eui[2] = 0; eui[3] = 0xFF; eui[4] = 0xFE; eui[5] = 0; ieee802154_le16_to_be16(&eui[6], &wpan_dev->short_addr); return 0; }
static void lowpan_ndisc_fill_addr_option(const struct net_device *dev, struct sk_buff *skb, u8 icmp6_type, const u8 *ha) { struct wpan_dev *wpan_dev; __be16 short_addr; u8 opt_type; if (!lowpan_is_ll(dev, LOWPAN_LLTYPE_IEEE802154)) return; switch (icmp6_type) { case NDISC_REDIRECT: if (ha) { ieee802154_le16_to_be16(&short_addr, ha); __ndisc_fill_addr_option(skb, ND_OPT_TARGET_LL_ADDR, &short_addr, IEEE802154_SHORT_ADDR_LEN, 0); } return; case NDISC_NEIGHBOUR_ADVERTISEMENT: opt_type = ND_OPT_TARGET_LL_ADDR; break; case NDISC_ROUTER_SOLICITATION: case NDISC_NEIGHBOUR_SOLICITATION: opt_type = ND_OPT_SOURCE_LL_ADDR; break; default: return; } wpan_dev = lowpan_802154_dev(dev)->wdev->ieee802154_ptr; if (lowpan_802154_is_valid_src_short_addr(wpan_dev->short_addr)) { ieee802154_le16_to_be16(&short_addr, &wpan_dev->short_addr); __ndisc_fill_addr_option(skb, opt_type, &short_addr, IEEE802154_SHORT_ADDR_LEN, 0); } }