// SPDX-License-Identifier: GPL-2.0-only
/*
 *
 * Authors:
 * (C) 2016 Pengutronix, Alexander Aring <aar@pengutronix.de>
 */

#include <net/6lowpan.h>
#include <net/addrconf.h>
#include <net/ndisc.h>

#include "6lowpan_i.h"

#if IS_ENABLED(CONFIG_IEEE802154_6LOWPAN)
#define NDISC_802154_SHORT_ADDR_LENGTH	1
static int lowpan_ndisc_parse_802154_options(const struct net_device *dev,
					     struct nd_opt_hdr *nd_opt,
					     struct ndisc_options *ndopts)
{
	switch (nd_opt->nd_opt_len) {
	case NDISC_802154_SHORT_ADDR_LENGTH:
		if (ndopts->nd_802154_opt_array[nd_opt->nd_opt_type])
			ND_PRINTK(2, warn,
				  "%s: duplicated short addr ND6 option found: type=%d\n",
				  __func__, nd_opt->nd_opt_type);
		else
			ndopts->nd_802154_opt_array[nd_opt->nd_opt_type] = nd_opt;
		return 1;
	default:
		/* all others will be handled by ndisc IPv6 option parsing */
		return 0;
	}
}

static int lowpan_ndisc_parse_options(const struct net_device *dev,
				      struct nd_opt_hdr *nd_opt,
				      struct ndisc_options *ndopts)
{
	if (!lowpan_is_ll(dev, LOWPAN_LLTYPE_IEEE802154))
		return 0;

	switch (nd_opt->nd_opt_type) {
	case ND_OPT_SOURCE_LL_ADDR:
	case ND_OPT_TARGET_LL_ADDR:
		return lowpan_ndisc_parse_802154_options(dev, nd_opt, ndopts);
	default:
		return 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);
	}
	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)
{
	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);
	}
}

static void lowpan_ndisc_prefix_rcv_add_addr(struct net *net,
					     struct net_device *dev,
					     const struct prefix_info *pinfo,
					     struct inet6_dev *in6_dev,
					     struct in6_addr *addr,
					     int addr_type, u32 addr_flags,
					     bool sllao, bool tokenized,
					     __u32 valid_lft,
					     u32 prefered_lft,
					     bool dev_addr_generated)
{
	int err;

	/* generates short based address for RA PIO's */
	if (lowpan_is_ll(dev, LOWPAN_LLTYPE_IEEE802154) && dev_addr_generated &&
	    !addrconf_ifid_802154_6lowpan(addr->s6_addr + 8, dev)) {
		err = addrconf_prefix_rcv_add_addr(net, dev, pinfo, in6_dev,
						   addr, addr_type, addr_flags,
						   sllao, tokenized, valid_lft,
						   prefered_lft);
		if (err)
			ND_PRINTK(2, warn,
				  "RA: could not add a short address based address for prefix: %pI6c\n",
				  &pinfo->prefix);
	}
}
#endif

const struct ndisc_ops lowpan_ndisc_ops = {
#if IS_ENABLED(CONFIG_IEEE802154_6LOWPAN)
	.parse_options		= lowpan_ndisc_parse_options,
	.update			= lowpan_ndisc_update,
	.opt_addr_space		= lowpan_ndisc_opt_addr_space,
	.fill_addr_option	= lowpan_ndisc_fill_addr_option,
	.prefix_rcv_add_addr	= lowpan_ndisc_prefix_rcv_add_addr,
#endif
};
