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 \
    /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
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.