All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alexander Aring <aar@pengutronix.de>
To: linux-wpan@vger.kernel.org
Cc: kernel@pengutronix.de, jukka.rissanen@linux.intel.com,
	hannes@stressinduktion.org, stefan@osg.samsung.com,
	mcr@sandelman.ca, werner@almesberger.net,
	Alexander Aring <aar@pengutronix.de>
Subject: [RFC bluetooth-next 18/19] ndisc: add support for short address option
Date: Tue, 22 Mar 2016 14:15:14 +0100	[thread overview]
Message-ID: <1458652515-7862-19-git-send-email-aar@pengutronix.de> (raw)
In-Reply-To: <1458652515-7862-1-git-send-email-aar@pengutronix.de>

This patch will add 802.15.4 6lowpan handling when parsing NS and NA
messages. The 802.15.4 6lowpan neighbour has a parivate data room for
storing an optional address which is available via link layer address
option fields.

This option field will currently always be written if a neighbour was
returned by neighbour lookup functionality.

Signed-off-by: Alexander Aring <aar@pengutronix.de>
---
 net/ipv6/ndisc.c | 126 ++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 121 insertions(+), 5 deletions(-)

diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 5c96ec6..6d9768e 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -235,6 +235,52 @@ static void ndisc_802154_parse_addr_options(struct ndisc_options *ndopts,
 		break;
 	}
 }
+
+static void ndisc_802154_neigh_update(struct neighbour *n, void *priv)
+{
+	struct lowpan_802154_neigh *neigh = lowpan_802154_neigh(neighbour_priv(n));
+
+	write_lock_bh(&n->lock);
+	if (priv)
+		ieee802154_be16_to_le16(&neigh->short_addr, priv);
+	else
+		neigh->short_addr = cpu_to_le16(IEEE802154_ADDR_SHORT_UNSPEC);
+	write_unlock_bh(&n->lock);
+}
+
+static inline int ndisc_802154_short_addr_space(struct net_device *dev)
+{
+	struct wpan_dev *wpan_dev;
+	int addr_space = 0;
+
+	if (lowpan_is_ll(dev, LOWPAN_LLTYPE_IEEE802154)) {
+		wpan_dev = lowpan_802154_dev(dev)->wdev->ieee802154_ptr;
+
+		if (ieee802154_is_valid_src_short_addr(wpan_dev->short_addr))
+			addr_space = ndisc_opt_addr_space(dev, IEEE802154_SHORT_ADDR_LEN);
+	}
+
+	return addr_space;
+}
+
+static inline void ndisc_802154_short_addr_option(struct net_device *dev,
+						  struct sk_buff *skb,
+						  int type)
+{
+	struct wpan_dev *wpan_dev;
+	__be16 short_addr;
+
+	if (lowpan_is_ll(dev, LOWPAN_LLTYPE_IEEE802154)) {
+		wpan_dev = lowpan_802154_dev(dev)->wdev->ieee802154_ptr;
+
+		if (ieee802154_is_valid_src_short_addr(wpan_dev->short_addr)) {
+			ieee802154_le16_to_be16(&short_addr,
+						&wpan_dev->short_addr);
+			ndisc_fill_addr_option(skb, type, &short_addr,
+					       IEEE802154_SHORT_ADDR_LEN);
+		}
+	}
+}
 #endif
 
 struct ndisc_options *ndisc_parse_options(const struct net_device *dev,
@@ -550,8 +596,12 @@ void ndisc_send_na(struct net_device *dev, const struct in6_addr *daddr,
 
 	if (!dev->addr_len)
 		inc_opt = 0;
-	if (inc_opt)
+	if (inc_opt) {
 		optlen += ndisc_opt_addr_space(dev, dev->addr_len);
+#ifdef CONFIG_IEEE802154_6LOWPAN
+		optlen += ndisc_802154_short_addr_space(dev);
+#endif
+	}
 
 	skb = ndisc_alloc_skb(dev, sizeof(*msg) + optlen);
 	if (!skb)
@@ -568,9 +618,14 @@ void ndisc_send_na(struct net_device *dev, const struct in6_addr *daddr,
 		.target = *solicited_addr,
 	};
 
-	if (inc_opt)
+	if (inc_opt) {
 		ndisc_fill_addr_option(skb, ND_OPT_TARGET_LL_ADDR,
 				       dev->dev_addr, dev->addr_len);
+#ifdef CONFIG_IEEE802154_6LOWPAN
+		ndisc_802154_short_addr_option(dev, skb,
+					       ND_OPT_TARGET_LL_ADDR);
+#endif
+	}
 
 
 	ndisc_send_skb(skb, daddr, src_addr);
@@ -615,8 +670,12 @@ void ndisc_send_ns(struct net_device *dev, const struct in6_addr *solicit,
 
 	if (ipv6_addr_any(saddr))
 		inc_opt = false;
-	if (inc_opt)
+	if (inc_opt) {
 		optlen += ndisc_opt_addr_space(dev, dev->addr_len);
+#ifdef CONFIG_IEEE802154_6LOWPAN
+		optlen += ndisc_802154_short_addr_space(dev);
+#endif
+	}
 
 	skb = ndisc_alloc_skb(dev, sizeof(*msg) + optlen);
 	if (!skb)
@@ -630,9 +689,14 @@ void ndisc_send_ns(struct net_device *dev, const struct in6_addr *solicit,
 		.target = *solicit,
 	};
 
-	if (inc_opt)
+	if (inc_opt) {
 		ndisc_fill_addr_option(skb, ND_OPT_SOURCE_LL_ADDR,
 				       dev->dev_addr, dev->addr_len);
+#ifdef CONFIG_IEEE802154_6LOWPAN
+		ndisc_802154_short_addr_option(dev, skb,
+					       ND_OPT_SOURCE_LL_ADDR);
+#endif
+	}
 
 	ndisc_send_skb(skb, daddr, saddr);
 }
@@ -760,6 +824,9 @@ static void ndisc_recv_ns(struct sk_buff *skb)
 	int dad = ipv6_addr_any(saddr);
 	bool inc;
 	int is_router = -1;
+#ifdef CONFIG_IEEE802154_6LOWPAN
+	u8 *lladdr_short = NULL;
+#endif
 
 	if (skb->len < sizeof(struct nd_msg)) {
 		ND_PRINTK(2, warn, "NS: packet too short\n");
@@ -806,6 +873,30 @@ static void ndisc_recv_ns(struct sk_buff *skb)
 		}
 	}
 
+#ifdef CONFIG_IEEE802154_6LOWPAN
+	if (lowpan_is_ll(dev, LOWPAN_LLTYPE_IEEE802154) &&
+	    ndopts.nd_802154_opts_src_lladdr) {
+		lladdr_short = ndisc_opt_addr_data(ndopts.nd_802154_opts_src_lladdr,
+						   dev, IEEE802154_SHORT_ADDR_LEN);
+		if (!lladdr_short) {
+			ND_PRINTK(2, warn,
+				  "NS: invalid short link-layer address length\n");
+			return;
+		}
+
+		/* RFC2461 7.1.1:
+		 *	If the IP source address is the unspecified address,
+		 *	there MUST NOT be source link-layer address option
+		 *	in the message.
+		 */
+		if (dad) {
+			ND_PRINTK(2, warn,
+				  "NS: bad DAD packet (short link-layer address option)\n");
+			return;
+		}
+	}
+#endif
+
 	inc = ipv6_addr_is_multicast(daddr);
 
 	ifp = ipv6_get_ifaddr(dev_net(dev), &msg->target, dev, 1);
@@ -898,10 +989,15 @@ have_ifp:
 	 */
 	neigh = __neigh_lookup(&nd_tbl, saddr, dev,
 			       !inc || lladdr || !dev->addr_len);
-	if (neigh)
+	if (neigh) {
 		neigh_update(neigh, lladdr, NUD_STALE,
 			     NEIGH_UPDATE_F_WEAK_OVERRIDE|
 			     NEIGH_UPDATE_F_OVERRIDE);
+#ifdef CONFIG_IEEE802154_6LOWPAN
+		if (lowpan_is_ll(dev, LOWPAN_LLTYPE_IEEE802154))
+			ndisc_802154_neigh_update(neigh, lladdr_short);
+#endif
+	}
 	if (neigh || !dev->header_ops) {
 		ndisc_send_na(dev, saddr, &msg->target, !!is_router,
 			      true, (ifp != NULL && inc), inc);
@@ -929,6 +1025,9 @@ static void ndisc_recv_na(struct sk_buff *skb)
 	struct inet6_dev *idev = __in6_dev_get(dev);
 	struct inet6_ifaddr *ifp;
 	struct neighbour *neigh;
+#ifdef CONFIG_IEEE802154_6LOWPAN
+	u8 *lladdr_short = NULL;
+#endif
 
 	if (skb->len < sizeof(struct nd_msg)) {
 		ND_PRINTK(2, warn, "NA: packet too short\n");
@@ -967,6 +1066,18 @@ static void ndisc_recv_na(struct sk_buff *skb)
 			return;
 		}
 	}
+#ifdef CONFIG_IEEE802154_6LOWPAN
+	if (lowpan_is_ll(dev, LOWPAN_LLTYPE_IEEE802154) &&
+	    ndopts.nd_802154_opts_tgt_lladdr) {
+		lladdr_short = ndisc_opt_addr_data(ndopts.nd_802154_opts_tgt_lladdr,
+						   dev, IEEE802154_SHORT_ADDR_LEN);
+		if (!lladdr_short) {
+			ND_PRINTK(2, warn,
+				  "NA: invalid short link-layer address length\n");
+			return;
+		}
+	}
+#endif
 	ifp = ipv6_get_ifaddr(dev_net(dev), &msg->target, dev, 1);
 	if (ifp) {
 		if (skb->pkt_type != PACKET_LOOPBACK
@@ -1018,6 +1129,11 @@ static void ndisc_recv_na(struct sk_buff *skb)
 			     NEIGH_UPDATE_F_OVERRIDE_ISROUTER|
 			     (msg->icmph.icmp6_router ? NEIGH_UPDATE_F_ISROUTER : 0));
 
+#ifdef CONFIG_IEEE802154_6LOWPAN
+		if (lowpan_is_ll(dev, LOWPAN_LLTYPE_IEEE802154))
+			ndisc_802154_neigh_update(neigh, lladdr_short);
+#endif
+
 		if ((old_flags & ~neigh->flags) & NTF_ROUTER) {
 			/*
 			 * Change: router to host
-- 
2.7.4


  parent reply	other threads:[~2016-03-22 13:15 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-03-22 13:14 [RFC bluetooth-next 00/19] 6lowpan: l2 neighbour data and short address Alexander Aring
2016-03-22 13:14 ` [RFC bluetooth-next 01/19] ieee802154: cleanups for ieee802154.h Alexander Aring
2016-03-23  9:59   ` Stefan Schmidt
2016-03-22 13:14 ` [RFC bluetooth-next 02/19] ieee802154: add short address helpers Alexander Aring
2016-03-23  9:59   ` Stefan Schmidt
2016-03-22 13:14 ` [RFC bluetooth-next 03/19] nl802154: avoid address change while running lowpan Alexander Aring
2016-03-23  9:59   ` Stefan Schmidt
2016-03-22 13:15 ` [RFC bluetooth-next 04/19] ieee802154: 6lowpan: fix short addr hash Alexander Aring
2016-03-23  9:58   ` Stefan Schmidt
2016-03-22 13:15 ` [RFC bluetooth-next 05/19] 6lowpan: change naming for lowpan private data Alexander Aring
2016-03-22 13:15 ` [RFC bluetooth-next 06/19] 6lowpan: move lowpan_802154_dev to 6lowpan Alexander Aring
2016-03-23 10:08   ` Stefan Schmidt
2016-03-22 13:15 ` [RFC bluetooth-next 07/19] 6lowpan: iphc: rename add lowpan prefix Alexander Aring
2016-03-23 10:09   ` Stefan Schmidt
2016-04-08 17:36     ` Marcel Holtmann
2016-04-11 17:00       ` Stefan Schmidt
2016-03-22 13:15 ` [RFC bluetooth-next 08/19] 6lowpan: iphc: remove unnecessary zero data Alexander Aring
2016-03-22 13:15 ` [RFC bluetooth-next 09/19] 6lowpan: move eui64 uncompress function Alexander Aring
2016-03-22 13:15 ` [RFC bluetooth-next 10/19] 6lowpan: add lowpan_is_ll function Alexander Aring
2016-03-22 13:15 ` [RFC bluetooth-next 11/19] 6lowpan: move mac802154 header Alexander Aring
2016-03-22 13:15 ` [RFC bluetooth-next 12/19] 6lowpan: add private neighbour data Alexander Aring
2016-03-22 13:15 ` [RFC bluetooth-next 13/19] addrconf: add 802.15.4 short addr slaac Alexander Aring
2016-03-23 10:50   ` Hannes Frederic Sowa
2016-04-05  8:20     ` Alexander Aring
2016-03-22 13:15 ` [RFC bluetooth-next 14/19] ndisc: add addr_len parameter to ndisc_opt_addr_space Alexander Aring
2016-03-22 13:15 ` [RFC bluetooth-next 15/19] ndisc: add addr_len parameter to ndisc_opt_addr_data Alexander Aring
2016-03-22 13:15 ` [RFC bluetooth-next 16/19] ndisc: add addr_len parameter to ndisc_fill_addr_option Alexander Aring
2016-03-22 13:15 ` [RFC bluetooth-next 17/19] ndisc: add short address to ndisc opts parsing Alexander Aring
2016-03-22 13:15 ` Alexander Aring [this message]
2016-03-22 13:15 ` [RFC bluetooth-next 19/19] 6lowpan: add support for 802.15.4 short addr handling Alexander Aring

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1458652515-7862-19-git-send-email-aar@pengutronix.de \
    --to=aar@pengutronix.de \
    --cc=hannes@stressinduktion.org \
    --cc=jukka.rissanen@linux.intel.com \
    --cc=kernel@pengutronix.de \
    --cc=linux-wpan@vger.kernel.org \
    --cc=mcr@sandelman.ca \
    --cc=stefan@osg.samsung.com \
    --cc=werner@almesberger.net \
    --subject='Re: [RFC bluetooth-next 18/19] ndisc: add support for short address option' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.