diff options
Diffstat (limited to 'net/ieee802154')
-rw-r--r-- | net/ieee802154/6lowpan_rtnl.c | 38 | ||||
-rw-r--r-- | net/ieee802154/dgram.c | 2 | ||||
-rw-r--r-- | net/ieee802154/nl-mac.c | 114 | ||||
-rw-r--r-- | net/ieee802154/reassembly.c | 17 | ||||
-rw-r--r-- | net/ieee802154/reassembly.h | 42 |
5 files changed, 112 insertions, 101 deletions
diff --git a/net/ieee802154/6lowpan_rtnl.c b/net/ieee802154/6lowpan_rtnl.c index 678564c7718..d4edd20dab5 100644 --- a/net/ieee802154/6lowpan_rtnl.c +++ b/net/ieee802154/6lowpan_rtnl.c @@ -168,10 +168,11 @@ static int lowpan_give_skb_to_devices(struct sk_buff *skb, return stat; } -static int process_data(struct sk_buff *skb) +static int process_data(struct sk_buff *skb, const struct ieee802154_hdr *hdr) { u8 iphc0, iphc1; - const struct ieee802154_addr_sa *_saddr, *_daddr; + struct ieee802154_addr_sa sa, da; + void *sap, *dap; raw_dump_table(__func__, "raw skb data dump", skb->data, skb->len); /* at least two bytes will be used for the encoding */ @@ -184,14 +185,23 @@ static int process_data(struct sk_buff *skb) if (lowpan_fetch_skb_u8(skb, &iphc1)) goto drop; - _saddr = &mac_cb(skb)->sa; - _daddr = &mac_cb(skb)->da; + ieee802154_addr_to_sa(&sa, &hdr->source); + ieee802154_addr_to_sa(&da, &hdr->dest); - return lowpan_process_data(skb, skb->dev, (u8 *)_saddr->hwaddr, - _saddr->addr_type, IEEE802154_ADDR_LEN, - (u8 *)_daddr->hwaddr, _daddr->addr_type, - IEEE802154_ADDR_LEN, iphc0, iphc1, - lowpan_give_skb_to_devices); + if (sa.addr_type == IEEE802154_ADDR_SHORT) + sap = &sa.short_addr; + else + sap = &sa.hwaddr; + + if (da.addr_type == IEEE802154_ADDR_SHORT) + dap = &da.short_addr; + else + dap = &da.hwaddr; + + return lowpan_process_data(skb, skb->dev, sap, sa.addr_type, + IEEE802154_ADDR_LEN, dap, da.addr_type, + IEEE802154_ADDR_LEN, iphc0, iphc1, + lowpan_give_skb_to_devices); drop: kfree_skb(skb); @@ -438,6 +448,7 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev) { struct sk_buff *local_skb; + struct ieee802154_hdr hdr; int ret; if (!netif_running(dev)) @@ -446,6 +457,9 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev, if (dev->type != ARPHRD_IEEE802154) goto drop_skb; + if (ieee802154_hdr_peek_addrs(skb, &hdr) < 0) + goto drop_skb; + local_skb = skb_clone(skb, GFP_ATOMIC); if (!local_skb) goto drop_skb; @@ -466,14 +480,14 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev, } else { switch (skb->data[0] & 0xe0) { case LOWPAN_DISPATCH_IPHC: /* ipv6 datagram */ - ret = process_data(local_skb); + ret = process_data(local_skb, &hdr); if (ret == NET_RX_DROP) goto drop; break; case LOWPAN_DISPATCH_FRAG1: /* first fragment header */ ret = lowpan_frag_rcv(local_skb, LOWPAN_DISPATCH_FRAG1); if (ret == 1) { - ret = process_data(local_skb); + ret = process_data(local_skb, &hdr); if (ret == NET_RX_DROP) goto drop; } @@ -481,7 +495,7 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev, case LOWPAN_DISPATCH_FRAGN: /* next fragments headers */ ret = lowpan_frag_rcv(local_skb, LOWPAN_DISPATCH_FRAGN); if (ret == 1) { - ret = process_data(local_skb); + ret = process_data(local_skb, &hdr); if (ret == NET_RX_DROP) goto drop; } diff --git a/net/ieee802154/dgram.c b/net/ieee802154/dgram.c index 0a926c6bc8c..55f2dc45a7d 100644 --- a/net/ieee802154/dgram.c +++ b/net/ieee802154/dgram.c @@ -313,7 +313,7 @@ static int dgram_recvmsg(struct kiocb *iocb, struct sock *sk, if (saddr) { saddr->family = AF_IEEE802154; - saddr->addr = mac_cb(skb)->sa; + ieee802154_addr_to_sa(&saddr->addr, &mac_cb(skb)->source); *addr_len = sizeof(*saddr); } diff --git a/net/ieee802154/nl-mac.c b/net/ieee802154/nl-mac.c index 58fa523fb53..bda8dba4f99 100644 --- a/net/ieee802154/nl-mac.c +++ b/net/ieee802154/nl-mac.c @@ -39,14 +39,34 @@ #include "ieee802154.h" +static int nla_put_hwaddr(struct sk_buff *msg, int type, __le64 hwaddr) +{ + return nla_put_u64(msg, type, swab64((__force u64)hwaddr)); +} + +static __le64 nla_get_hwaddr(const struct nlattr *nla) +{ + return ieee802154_devaddr_from_raw(nla_data(nla)); +} + +static int nla_put_shortaddr(struct sk_buff *msg, int type, __le16 addr) +{ + return nla_put_u16(msg, type, le16_to_cpu(addr)); +} + +static __le16 nla_get_shortaddr(const struct nlattr *nla) +{ + return cpu_to_le16(nla_get_u16(nla)); +} + int ieee802154_nl_assoc_indic(struct net_device *dev, - struct ieee802154_addr_sa *addr, u8 cap) + struct ieee802154_addr *addr, u8 cap) { struct sk_buff *msg; pr_debug("%s\n", __func__); - if (addr->addr_type != IEEE802154_ADDR_LONG) { + if (addr->mode != IEEE802154_ADDR_LONG) { pr_err("%s: received non-long source address!\n", __func__); return -EINVAL; } @@ -59,8 +79,8 @@ int ieee802154_nl_assoc_indic(struct net_device *dev, nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) || nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, dev->dev_addr) || - nla_put(msg, IEEE802154_ATTR_SRC_HW_ADDR, IEEE802154_ADDR_LEN, - addr->hwaddr) || + nla_put_hwaddr(msg, IEEE802154_ATTR_SRC_HW_ADDR, + addr->extended_addr) || nla_put_u8(msg, IEEE802154_ATTR_CAPABILITY, cap)) goto nla_put_failure; @@ -87,8 +107,7 @@ int ieee802154_nl_assoc_confirm(struct net_device *dev, __le16 short_addr, nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) || nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, dev->dev_addr) || - nla_put_u16(msg, IEEE802154_ATTR_SHORT_ADDR, - le16_to_cpu(short_addr)) || + nla_put_shortaddr(msg, IEEE802154_ATTR_SHORT_ADDR, short_addr) || nla_put_u8(msg, IEEE802154_ATTR_STATUS, status)) goto nla_put_failure; return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP); @@ -100,7 +119,7 @@ nla_put_failure: EXPORT_SYMBOL(ieee802154_nl_assoc_confirm); int ieee802154_nl_disassoc_indic(struct net_device *dev, - struct ieee802154_addr_sa *addr, u8 reason) + struct ieee802154_addr *addr, u8 reason) { struct sk_buff *msg; @@ -115,13 +134,13 @@ int ieee802154_nl_disassoc_indic(struct net_device *dev, nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, dev->dev_addr)) goto nla_put_failure; - if (addr->addr_type == IEEE802154_ADDR_LONG) { - if (nla_put(msg, IEEE802154_ATTR_SRC_HW_ADDR, IEEE802154_ADDR_LEN, - addr->hwaddr)) + if (addr->mode == IEEE802154_ADDR_LONG) { + if (nla_put_hwaddr(msg, IEEE802154_ATTR_SRC_HW_ADDR, + addr->extended_addr)) goto nla_put_failure; } else { - if (nla_put_u16(msg, IEEE802154_ATTR_SRC_SHORT_ADDR, - addr->short_addr)) + if (nla_put_shortaddr(msg, IEEE802154_ATTR_SRC_SHORT_ADDR, + addr->short_addr)) goto nla_put_failure; } if (nla_put_u8(msg, IEEE802154_ATTR_REASON, reason)) @@ -173,10 +192,9 @@ int ieee802154_nl_beacon_indic(struct net_device *dev, __le16 panid, nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) || nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, dev->dev_addr) || - nla_put_u16(msg, IEEE802154_ATTR_COORD_SHORT_ADDR, - le16_to_cpu(coord_addr)) || - nla_put_u16(msg, IEEE802154_ATTR_COORD_PAN_ID, - le16_to_cpu(panid))) + nla_put_shortaddr(msg, IEEE802154_ATTR_COORD_SHORT_ADDR, + coord_addr) || + nla_put_shortaddr(msg, IEEE802154_ATTR_COORD_PAN_ID, panid)) goto nla_put_failure; return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP); @@ -246,7 +264,7 @@ static int ieee802154_nl_fill_iface(struct sk_buff *msg, u32 portid, { void *hdr; struct wpan_phy *phy; - u16 short_addr, pan_id; + __le16 short_addr, pan_id; pr_debug("%s\n", __func__); @@ -258,16 +276,16 @@ static int ieee802154_nl_fill_iface(struct sk_buff *msg, u32 portid, phy = ieee802154_mlme_ops(dev)->get_phy(dev); BUG_ON(!phy); - short_addr = le16_to_cpu(ieee802154_mlme_ops(dev)->get_short_addr(dev)); - pan_id = le16_to_cpu(ieee802154_mlme_ops(dev)->get_pan_id(dev)); + short_addr = ieee802154_mlme_ops(dev)->get_short_addr(dev); + pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev); if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) || nla_put_string(msg, IEEE802154_ATTR_PHY_NAME, wpan_phy_name(phy)) || nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) || nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, dev->dev_addr) || - nla_put_u16(msg, IEEE802154_ATTR_SHORT_ADDR, short_addr) || - nla_put_u16(msg, IEEE802154_ATTR_PAN_ID, pan_id)) + nla_put_shortaddr(msg, IEEE802154_ATTR_SHORT_ADDR, short_addr) || + nla_put_shortaddr(msg, IEEE802154_ATTR_PAN_ID, pan_id)) goto nla_put_failure; wpan_phy_put(phy); return genlmsg_end(msg, hdr); @@ -309,7 +327,7 @@ static struct net_device *ieee802154_nl_get_dev(struct genl_info *info) int ieee802154_associate_req(struct sk_buff *skb, struct genl_info *info) { struct net_device *dev; - struct ieee802154_addr_sa addr; + struct ieee802154_addr addr; u8 page; int ret = -EOPNOTSUPP; @@ -327,16 +345,16 @@ int ieee802154_associate_req(struct sk_buff *skb, struct genl_info *info) goto out; if (info->attrs[IEEE802154_ATTR_COORD_HW_ADDR]) { - addr.addr_type = IEEE802154_ADDR_LONG; - nla_memcpy(addr.hwaddr, - info->attrs[IEEE802154_ATTR_COORD_HW_ADDR], - IEEE802154_ADDR_LEN); + addr.mode = IEEE802154_ADDR_LONG; + addr.extended_addr = nla_get_hwaddr( + info->attrs[IEEE802154_ATTR_COORD_HW_ADDR]); } else { - addr.addr_type = IEEE802154_ADDR_SHORT; - addr.short_addr = nla_get_u16( + addr.mode = IEEE802154_ADDR_SHORT; + addr.short_addr = nla_get_shortaddr( info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR]); } - addr.pan_id = nla_get_u16(info->attrs[IEEE802154_ATTR_COORD_PAN_ID]); + addr.pan_id = nla_get_shortaddr( + info->attrs[IEEE802154_ATTR_COORD_PAN_ID]); if (info->attrs[IEEE802154_ATTR_PAGE]) page = nla_get_u8(info->attrs[IEEE802154_ATTR_PAGE]); @@ -356,7 +374,7 @@ out: int ieee802154_associate_resp(struct sk_buff *skb, struct genl_info *info) { struct net_device *dev; - struct ieee802154_addr_sa addr; + struct ieee802154_addr addr; int ret = -EOPNOTSUPP; if (!info->attrs[IEEE802154_ATTR_STATUS] || @@ -370,13 +388,13 @@ int ieee802154_associate_resp(struct sk_buff *skb, struct genl_info *info) if (!ieee802154_mlme_ops(dev)->assoc_resp) goto out; - addr.addr_type = IEEE802154_ADDR_LONG; - nla_memcpy(addr.hwaddr, info->attrs[IEEE802154_ATTR_DEST_HW_ADDR], - IEEE802154_ADDR_LEN); - addr.pan_id = le16_to_cpu(ieee802154_mlme_ops(dev)->get_pan_id(dev)); + addr.mode = IEEE802154_ADDR_LONG; + addr.extended_addr = nla_get_hwaddr( + info->attrs[IEEE802154_ATTR_DEST_HW_ADDR]); + addr.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev); ret = ieee802154_mlme_ops(dev)->assoc_resp(dev, &addr, - cpu_to_le16(nla_get_u16(info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR])), + nla_get_shortaddr(info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR]), nla_get_u8(info->attrs[IEEE802154_ATTR_STATUS])); out: @@ -387,7 +405,7 @@ out: int ieee802154_disassociate_req(struct sk_buff *skb, struct genl_info *info) { struct net_device *dev; - struct ieee802154_addr_sa addr; + struct ieee802154_addr addr; int ret = -EOPNOTSUPP; if ((!info->attrs[IEEE802154_ATTR_DEST_HW_ADDR] && @@ -402,16 +420,15 @@ int ieee802154_disassociate_req(struct sk_buff *skb, struct genl_info *info) goto out; if (info->attrs[IEEE802154_ATTR_DEST_HW_ADDR]) { - addr.addr_type = IEEE802154_ADDR_LONG; - nla_memcpy(addr.hwaddr, - info->attrs[IEEE802154_ATTR_DEST_HW_ADDR], - IEEE802154_ADDR_LEN); + addr.mode = IEEE802154_ADDR_LONG; + addr.extended_addr = nla_get_hwaddr( + info->attrs[IEEE802154_ATTR_DEST_HW_ADDR]); } else { - addr.addr_type = IEEE802154_ADDR_SHORT; - addr.short_addr = nla_get_u16( + addr.mode = IEEE802154_ADDR_SHORT; + addr.short_addr = nla_get_shortaddr( info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR]); } - addr.pan_id = le16_to_cpu(ieee802154_mlme_ops(dev)->get_pan_id(dev)); + addr.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev); ret = ieee802154_mlme_ops(dev)->disassoc_req(dev, &addr, nla_get_u8(info->attrs[IEEE802154_ATTR_REASON])); @@ -429,7 +446,7 @@ out: int ieee802154_start_req(struct sk_buff *skb, struct genl_info *info) { struct net_device *dev; - struct ieee802154_addr_sa addr; + struct ieee802154_addr addr; u8 channel, bcn_ord, sf_ord; u8 page; @@ -453,10 +470,11 @@ int ieee802154_start_req(struct sk_buff *skb, struct genl_info *info) if (!ieee802154_mlme_ops(dev)->start_req) goto out; - addr.addr_type = IEEE802154_ADDR_SHORT; - addr.short_addr = nla_get_u16( + addr.mode = IEEE802154_ADDR_SHORT; + addr.short_addr = nla_get_shortaddr( info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR]); - addr.pan_id = nla_get_u16(info->attrs[IEEE802154_ATTR_COORD_PAN_ID]); + addr.pan_id = nla_get_shortaddr( + info->attrs[IEEE802154_ATTR_COORD_PAN_ID]); channel = nla_get_u8(info->attrs[IEEE802154_ATTR_CHANNEL]); bcn_ord = nla_get_u8(info->attrs[IEEE802154_ATTR_BCN_ORD]); @@ -471,7 +489,7 @@ int ieee802154_start_req(struct sk_buff *skb, struct genl_info *info) page = 0; - if (addr.short_addr == IEEE802154_ADDR_BROADCAST) { + if (addr.short_addr == cpu_to_le16(IEEE802154_ADDR_BROADCAST)) { ieee802154_nl_start_confirm(dev, IEEE802154_NO_SHORT_ADDRESS); dev_put(dev); return -EINVAL; diff --git a/net/ieee802154/reassembly.c b/net/ieee802154/reassembly.c index f08b37a24b1..a2b9e4e533f 100644 --- a/net/ieee802154/reassembly.c +++ b/net/ieee802154/reassembly.c @@ -36,8 +36,8 @@ static int lowpan_frag_reasm(struct lowpan_frag_queue *fq, struct sk_buff *prev, struct net_device *dev); static unsigned int lowpan_hash_frag(__be16 tag, u16 d_size, - const struct ieee802154_addr_sa *saddr, - const struct ieee802154_addr_sa *daddr) + const struct ieee802154_addr *saddr, + const struct ieee802154_addr *daddr) { u32 c; @@ -65,8 +65,8 @@ static bool lowpan_frag_match(struct inet_frag_queue *q, void *a) fq = container_of(q, struct lowpan_frag_queue, q); return fq->tag == arg->tag && fq->d_size == arg->d_size && - ieee802154_addr_addr_equal(&fq->saddr, arg->src) && - ieee802154_addr_addr_equal(&fq->daddr, arg->dst); + ieee802154_addr_equal(&fq->saddr, arg->src) && + ieee802154_addr_equal(&fq->daddr, arg->dst); } static void lowpan_frag_init(struct inet_frag_queue *q, void *a) @@ -103,7 +103,8 @@ out: static inline struct lowpan_frag_queue * fq_find(struct net *net, const struct ieee802154_frag_info *frag_info, - const struct ieee802154_addr_sa *src, const struct ieee802154_addr_sa *dst) + const struct ieee802154_addr *src, + const struct ieee802154_addr *dst) { struct inet_frag_queue *q; struct lowpan_create_arg arg; @@ -346,8 +347,12 @@ int lowpan_frag_rcv(struct sk_buff *skb, const u8 frag_type) struct lowpan_frag_queue *fq; struct net *net = dev_net(skb->dev); struct ieee802154_frag_info *frag_info = &mac_cb(skb)->frag_info; + struct ieee802154_addr source, dest; int err; + source = mac_cb(skb)->source; + dest = mac_cb(skb)->dest; + err = lowpan_get_frag_info(skb, frag_type, frag_info); if (err < 0) goto err; @@ -357,7 +362,7 @@ int lowpan_frag_rcv(struct sk_buff *skb, const u8 frag_type) inet_frag_evictor(&net->ieee802154_lowpan.frags, &lowpan_frags, false); - fq = fq_find(net, frag_info, &mac_cb(skb)->sa, &mac_cb(skb)->da); + fq = fq_find(net, frag_info, &source, &dest); if (fq != NULL) { int ret; spin_lock(&fq->q.lock); diff --git a/net/ieee802154/reassembly.h b/net/ieee802154/reassembly.h index 895721ae71e..74e4a7c9819 100644 --- a/net/ieee802154/reassembly.h +++ b/net/ieee802154/reassembly.h @@ -6,8 +6,8 @@ struct lowpan_create_arg { __be16 tag; u16 d_size; - const struct ieee802154_addr_sa *src; - const struct ieee802154_addr_sa *dst; + const struct ieee802154_addr *src; + const struct ieee802154_addr *dst; }; /* Equivalent of ipv4 struct ip @@ -17,16 +17,16 @@ struct lowpan_frag_queue { __be16 tag; u16 d_size; - struct ieee802154_addr_sa saddr; - struct ieee802154_addr_sa daddr; + struct ieee802154_addr saddr; + struct ieee802154_addr daddr; }; -static inline u32 ieee802154_addr_hash(const struct ieee802154_addr_sa *a) +static inline u32 ieee802154_addr_hash(const struct ieee802154_addr *a) { - switch (a->addr_type) { + switch (a->mode) { case IEEE802154_ADDR_LONG: - return (__force u32)((((u32 *)a->hwaddr))[0] ^ - ((u32 *)(a->hwaddr))[1]); + return (((__force u64)a->extended_addr) >> 32) ^ + (((__force u64)a->extended_addr) & 0xffffffff); case IEEE802154_ADDR_SHORT: return (__force u32)(a->short_addr); default: @@ -34,32 +34,6 @@ static inline u32 ieee802154_addr_hash(const struct ieee802154_addr_sa *a) } } -static inline bool -ieee802154_addr_addr_equal(const struct ieee802154_addr_sa *a1, - const struct ieee802154_addr_sa *a2) -{ - if (a1->pan_id != a2->pan_id) - return false; - - if (a1->addr_type != a2->addr_type) - return false; - - switch (a1->addr_type) { - case IEEE802154_ADDR_LONG: - if (memcmp(a1->hwaddr, a2->hwaddr, IEEE802154_ADDR_LEN)) - return false; - break; - case IEEE802154_ADDR_SHORT: - if (a1->short_addr != a2->short_addr) - return false; - break; - default: - return false; - } - - return true; -} - int lowpan_frag_rcv(struct sk_buff *skb, const u8 frag_type); void lowpan_net_frag_exit(void); int lowpan_net_frag_init(void); |