Example #1
0
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;
}
Example #2
0
static int lowpan_ndisc_opt_addr_space(const struct net_device *dev,
                                       u8 icmp6_type, struct neighbour *neigh,
                                       u8 *ha_buf, u8 **ha)
{
    struct lowpan_802154_neigh *n;
    struct wpan_dev *wpan_dev;
    int addr_space = 0;

    if (!lowpan_is_ll(dev, LOWPAN_LLTYPE_IEEE802154))
        return 0;

    switch (icmp6_type) {
    case NDISC_REDIRECT:
        n = lowpan_802154_neigh(neighbour_priv(neigh));

        read_lock_bh(&neigh->lock);
        if (lowpan_802154_is_valid_src_short_addr(n->short_addr)) {
            memcpy(ha_buf, &n->short_addr,
                   IEEE802154_SHORT_ADDR_LEN);
            read_unlock_bh(&neigh->lock);
            addr_space += __ndisc_opt_addr_space(IEEE802154_SHORT_ADDR_LEN, 0);
            *ha = ha_buf;
        } else {
            read_unlock_bh(&neigh->lock);
        }
        break;
    case NDISC_NEIGHBOUR_ADVERTISEMENT:
    case NDISC_NEIGHBOUR_SOLICITATION:
    case NDISC_ROUTER_SOLICITATION:
        wpan_dev = lowpan_802154_dev(dev)->wdev->ieee802154_ptr;

        if (lowpan_802154_is_valid_src_short_addr(wpan_dev->short_addr))
            addr_space = __ndisc_opt_addr_space(IEEE802154_SHORT_ADDR_LEN, 0);
        break;
    default:
        break;
    }

    return addr_space;
}
Example #3
0
static void lowpan_ndisc_802154_update(struct neighbour *n, u32 flags,
                                       u8 icmp6_type,
                                       const struct ndisc_options *ndopts)
{
    struct lowpan_802154_neigh *neigh = lowpan_802154_neigh(neighbour_priv(n));
    u8 *lladdr_short = NULL;

    switch (icmp6_type) {
    case NDISC_ROUTER_SOLICITATION:
    case NDISC_ROUTER_ADVERTISEMENT:
    case NDISC_NEIGHBOUR_SOLICITATION:
        if (ndopts->nd_802154_opts_src_lladdr) {
            lladdr_short = __ndisc_opt_addr_data(ndopts->nd_802154_opts_src_lladdr,
                                                 IEEE802154_SHORT_ADDR_LEN, 0);
            if (!lladdr_short) {
                ND_PRINTK(2, warn,
                          "NA: invalid short link-layer address length\n");
                return;
            }
        }
        break;
    case NDISC_REDIRECT:
    case NDISC_NEIGHBOUR_ADVERTISEMENT:
        if (ndopts->nd_802154_opts_tgt_lladdr) {
            lladdr_short = __ndisc_opt_addr_data(ndopts->nd_802154_opts_tgt_lladdr,
                                                 IEEE802154_SHORT_ADDR_LEN, 0);
            if (!lladdr_short) {
                ND_PRINTK(2, warn,
                          "NA: invalid short link-layer address length\n");
                return;
            }
        }
        break;
    default:
        break;
    }

    write_lock_bh(&n->lock);
    if (lladdr_short) {
        ieee802154_be16_to_le16(&neigh->short_addr, lladdr_short);
        if (!lowpan_802154_is_valid_src_short_addr(neigh->short_addr))
            neigh->short_addr = cpu_to_le16(IEEE802154_ADDR_SHORT_UNSPEC);
    } else {
        neigh->short_addr = cpu_to_le16(IEEE802154_ADDR_SHORT_UNSPEC);
    }
    write_unlock_bh(&n->lock);
}
Example #4
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);
    }
}