net/6lowpan/ndisc.c

Source file repositories/reference/linux-study-clean/net/6lowpan/ndisc.c

File Facts

System
Linux kernel
Corpus path
net/6lowpan/ndisc.c
Extension
.c
Size
6292 bytes
Lines
224
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: implementation source
Status
source implementation candidate

Why This File Exists

Networking stack implementation surface: socket APIs, protocol dispatch, packet flow, routing, filtering, and network namespaces.

Dependency Surface

Detected Declarations

Annotated Snippet

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) {
				net_dbg_ratelimited("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) {
				net_dbg_ratelimited("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);
	}
	write_unlock_bh(&n->lock);
}

static void lowpan_ndisc_update(const struct net_device *dev,
				struct neighbour *n, u32 flags, u8 icmp6_type,
				const struct ndisc_options *ndopts)
{
	if (!lowpan_is_ll(dev, LOWPAN_LLTYPE_IEEE802154))
		return;

	/* react on overrides only. TODO check if this is really right. */
	if (flags & NEIGH_UPDATE_F_OVERRIDE)
		lowpan_ndisc_802154_update(n, flags, icmp6_type, ndopts);
}

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;
}

static void lowpan_ndisc_fill_addr_option(const struct net_device *dev,
					  struct sk_buff *skb, u8 icmp6_type,
					  const u8 *ha)
{

Annotation

Implementation Notes