aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2014-03-14 22:15:35 -0400
committerDavid S. Miller <davem@davemloft.net>2014-03-14 22:15:35 -0400
commit983f59617aabbbfadbc73b897b9a78e6ffd92841 (patch)
tree9e132ac257c7f520382d7082e34ab3f5f1cc9452
parent177943260a6088bec51fc6c04643d84e43bef423 (diff)
parentd1d7358e9f032a43bd48d56a623943b7bee7dce0 (diff)
Merge branch 'ieee802154-next'
Phoebe Buckheister says: ==================== ieee802154: fix endianness and header handling This patch set enforces network byte order on all internal operations and fields of the 802.15.4 stack and adds a general representation of 802.15.4 headers with operations to create and parse those headers. This reduces code duplication in the current stack and also allows for upper layers to read headers of packets they have just received; it is also necessary for 802.15.4 link layer security, which requires header mangling. Changes since v1: * fixed lowpan packet rx after reassembly. Control blocks were used to retrieve source/dest addresses, but the CB is clobbered by reassembly. Instead, parse the header anew in lowpan. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ieee802154/at86rf230.c25
-rw-r--r--drivers/net/ieee802154/fakehard.c22
-rw-r--r--drivers/net/ieee802154/mrf24j40.c17
-rw-r--r--include/net/af_ieee802154.h4
-rw-r--r--include/net/ieee802154.h28
-rw-r--r--include/net/ieee802154_netdev.h181
-rw-r--r--include/net/mac802154.h6
-rw-r--r--include/net/nl802154.h6
-rw-r--r--net/ieee802154/6lowpan_rtnl.c58
-rw-r--r--net/ieee802154/Makefile5
-rw-r--r--net/ieee802154/af802154.h5
-rw-r--r--net/ieee802154/af_ieee802154.c20
-rw-r--r--net/ieee802154/dgram.c56
-rw-r--r--net/ieee802154/header_ops.c287
-rw-r--r--net/ieee802154/nl-mac.c102
-rw-r--r--net/ieee802154/raw.c14
-rw-r--r--net/ieee802154/reassembly.c40
-rw-r--r--net/ieee802154/reassembly.h31
-rw-r--r--net/mac802154/Makefile2
-rw-r--r--net/mac802154/ieee802154_dev.c5
-rw-r--r--net/mac802154/mac802154.h9
-rw-r--r--net/mac802154/mac_cmd.c2
-rw-r--r--net/mac802154/mib.c22
-rw-r--r--net/mac802154/wpan.c376
24 files changed, 841 insertions, 482 deletions
diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c
index b8e732121a85..934a12c03552 100644
--- a/drivers/net/ieee802154/at86rf230.c
+++ b/drivers/net/ieee802154/at86rf230.c
@@ -745,30 +745,31 @@ at86rf230_set_hw_addr_filt(struct ieee802154_dev *dev,
745 struct at86rf230_local *lp = dev->priv; 745 struct at86rf230_local *lp = dev->priv;
746 746
747 if (changed & IEEE802515_AFILT_SADDR_CHANGED) { 747 if (changed & IEEE802515_AFILT_SADDR_CHANGED) {
748 u16 addr = le16_to_cpu(filt->short_addr);
749
748 dev_vdbg(&lp->spi->dev, 750 dev_vdbg(&lp->spi->dev,
749 "at86rf230_set_hw_addr_filt called for saddr\n"); 751 "at86rf230_set_hw_addr_filt called for saddr\n");
750 __at86rf230_write(lp, RG_SHORT_ADDR_0, filt->short_addr); 752 __at86rf230_write(lp, RG_SHORT_ADDR_0, addr);
751 __at86rf230_write(lp, RG_SHORT_ADDR_1, filt->short_addr >> 8); 753 __at86rf230_write(lp, RG_SHORT_ADDR_1, addr >> 8);
752 } 754 }
753 755
754 if (changed & IEEE802515_AFILT_PANID_CHANGED) { 756 if (changed & IEEE802515_AFILT_PANID_CHANGED) {
757 u16 pan = le16_to_cpu(filt->pan_id);
758
755 dev_vdbg(&lp->spi->dev, 759 dev_vdbg(&lp->spi->dev,
756 "at86rf230_set_hw_addr_filt called for pan id\n"); 760 "at86rf230_set_hw_addr_filt called for pan id\n");
757 __at86rf230_write(lp, RG_PAN_ID_0, filt->pan_id); 761 __at86rf230_write(lp, RG_PAN_ID_0, pan);
758 __at86rf230_write(lp, RG_PAN_ID_1, filt->pan_id >> 8); 762 __at86rf230_write(lp, RG_PAN_ID_1, pan >> 8);
759 } 763 }
760 764
761 if (changed & IEEE802515_AFILT_IEEEADDR_CHANGED) { 765 if (changed & IEEE802515_AFILT_IEEEADDR_CHANGED) {
766 u8 i, addr[8];
767
768 memcpy(addr, &filt->ieee_addr, 8);
762 dev_vdbg(&lp->spi->dev, 769 dev_vdbg(&lp->spi->dev,
763 "at86rf230_set_hw_addr_filt called for IEEE addr\n"); 770 "at86rf230_set_hw_addr_filt called for IEEE addr\n");
764 at86rf230_write_subreg(lp, SR_IEEE_ADDR_0, filt->ieee_addr[7]); 771 for (i = 0; i < 8; i++)
765 at86rf230_write_subreg(lp, SR_IEEE_ADDR_1, filt->ieee_addr[6]); 772 __at86rf230_write(lp, RG_IEEE_ADDR_0 + i, addr[i]);
766 at86rf230_write_subreg(lp, SR_IEEE_ADDR_2, filt->ieee_addr[5]);
767 at86rf230_write_subreg(lp, SR_IEEE_ADDR_3, filt->ieee_addr[4]);
768 at86rf230_write_subreg(lp, SR_IEEE_ADDR_4, filt->ieee_addr[3]);
769 at86rf230_write_subreg(lp, SR_IEEE_ADDR_5, filt->ieee_addr[2]);
770 at86rf230_write_subreg(lp, SR_IEEE_ADDR_6, filt->ieee_addr[1]);
771 at86rf230_write_subreg(lp, SR_IEEE_ADDR_7, filt->ieee_addr[0]);
772 } 773 }
773 774
774 if (changed & IEEE802515_AFILT_PANC_CHANGED) { 775 if (changed & IEEE802515_AFILT_PANC_CHANGED) {
diff --git a/drivers/net/ieee802154/fakehard.c b/drivers/net/ieee802154/fakehard.c
index bf0d55e2dd63..78f18be3bbf2 100644
--- a/drivers/net/ieee802154/fakehard.c
+++ b/drivers/net/ieee802154/fakehard.c
@@ -63,11 +63,11 @@ static struct wpan_phy *fake_get_phy(const struct net_device *dev)
63 * 63 *
64 * Return the ID of the PAN from the PIB. 64 * Return the ID of the PAN from the PIB.
65 */ 65 */
66static u16 fake_get_pan_id(const struct net_device *dev) 66static __le16 fake_get_pan_id(const struct net_device *dev)
67{ 67{
68 BUG_ON(dev->type != ARPHRD_IEEE802154); 68 BUG_ON(dev->type != ARPHRD_IEEE802154);
69 69
70 return 0xeba1; 70 return cpu_to_le16(0xeba1);
71} 71}
72 72
73/** 73/**
@@ -78,11 +78,11 @@ static u16 fake_get_pan_id(const struct net_device *dev)
78 * device. If the device has not yet had a short address assigned 78 * device. If the device has not yet had a short address assigned
79 * then this should return 0xFFFF to indicate a lack of association. 79 * then this should return 0xFFFF to indicate a lack of association.
80 */ 80 */
81static u16 fake_get_short_addr(const struct net_device *dev) 81static __le16 fake_get_short_addr(const struct net_device *dev)
82{ 82{
83 BUG_ON(dev->type != ARPHRD_IEEE802154); 83 BUG_ON(dev->type != ARPHRD_IEEE802154);
84 84
85 return 0x1; 85 return cpu_to_le16(0x1);
86} 86}
87 87
88/** 88/**
@@ -149,7 +149,7 @@ static int fake_assoc_req(struct net_device *dev,
149 * 802.15.4-2006 document. 149 * 802.15.4-2006 document.
150 */ 150 */
151static int fake_assoc_resp(struct net_device *dev, 151static int fake_assoc_resp(struct net_device *dev,
152 struct ieee802154_addr *addr, u16 short_addr, u8 status) 152 struct ieee802154_addr *addr, __le16 short_addr, u8 status)
153{ 153{
154 return 0; 154 return 0;
155} 155}
@@ -191,10 +191,10 @@ static int fake_disassoc_req(struct net_device *dev,
191 * Note: This is in section 7.5.2.3 of the IEEE 802.15.4-2006 191 * Note: This is in section 7.5.2.3 of the IEEE 802.15.4-2006
192 * document, with 7.3.8 describing coordinator realignment. 192 * document, with 7.3.8 describing coordinator realignment.
193 */ 193 */
194static int fake_start_req(struct net_device *dev, struct ieee802154_addr *addr, 194static int fake_start_req(struct net_device *dev,
195 u8 channel, u8 page, 195 struct ieee802154_addr *addr, u8 channel, u8 page,
196 u8 bcn_ord, u8 sf_ord, u8 pan_coord, u8 blx, 196 u8 bcn_ord, u8 sf_ord, u8 pan_coord, u8 blx,
197 u8 coord_realign) 197 u8 coord_realign)
198{ 198{
199 struct wpan_phy *phy = fake_to_phy(dev); 199 struct wpan_phy *phy = fake_to_phy(dev);
200 200
@@ -281,8 +281,8 @@ static int ieee802154_fake_ioctl(struct net_device *dev, struct ifreq *ifr,
281 switch (cmd) { 281 switch (cmd) {
282 case SIOCGIFADDR: 282 case SIOCGIFADDR:
283 /* FIXME: fixed here, get from device IRL */ 283 /* FIXME: fixed here, get from device IRL */
284 pan_id = fake_get_pan_id(dev); 284 pan_id = le16_to_cpu(fake_get_pan_id(dev));
285 short_addr = fake_get_short_addr(dev); 285 short_addr = le16_to_cpu(fake_get_short_addr(dev));
286 if (pan_id == IEEE802154_PANID_BROADCAST || 286 if (pan_id == IEEE802154_PANID_BROADCAST ||
287 short_addr == IEEE802154_ADDR_BROADCAST) 287 short_addr == IEEE802154_ADDR_BROADCAST)
288 return -EADDRNOTAVAIL; 288 return -EADDRNOTAVAIL;
diff --git a/drivers/net/ieee802154/mrf24j40.c b/drivers/net/ieee802154/mrf24j40.c
index 246befa4ba05..78a6552ed707 100644
--- a/drivers/net/ieee802154/mrf24j40.c
+++ b/drivers/net/ieee802154/mrf24j40.c
@@ -465,8 +465,8 @@ static int mrf24j40_filter(struct ieee802154_dev *dev,
465 if (changed & IEEE802515_AFILT_SADDR_CHANGED) { 465 if (changed & IEEE802515_AFILT_SADDR_CHANGED) {
466 /* Short Addr */ 466 /* Short Addr */
467 u8 addrh, addrl; 467 u8 addrh, addrl;
468 addrh = filt->short_addr >> 8 & 0xff; 468 addrh = le16_to_cpu(filt->short_addr) >> 8 & 0xff;
469 addrl = filt->short_addr & 0xff; 469 addrl = le16_to_cpu(filt->short_addr) & 0xff;
470 470
471 write_short_reg(devrec, REG_SADRH, addrh); 471 write_short_reg(devrec, REG_SADRH, addrh);
472 write_short_reg(devrec, REG_SADRL, addrl); 472 write_short_reg(devrec, REG_SADRL, addrl);
@@ -476,15 +476,16 @@ static int mrf24j40_filter(struct ieee802154_dev *dev,
476 476
477 if (changed & IEEE802515_AFILT_IEEEADDR_CHANGED) { 477 if (changed & IEEE802515_AFILT_IEEEADDR_CHANGED) {
478 /* Device Address */ 478 /* Device Address */
479 int i; 479 u8 i, addr[8];
480
481 memcpy(addr, &filt->ieee_addr, 8);
480 for (i = 0; i < 8; i++) 482 for (i = 0; i < 8; i++)
481 write_short_reg(devrec, REG_EADR0+i, 483 write_short_reg(devrec, REG_EADR0 + i, addr[i]);
482 filt->ieee_addr[7-i]);
483 484
484#ifdef DEBUG 485#ifdef DEBUG
485 printk(KERN_DEBUG "Set long addr to: "); 486 printk(KERN_DEBUG "Set long addr to: ");
486 for (i = 0; i < 8; i++) 487 for (i = 0; i < 8; i++)
487 printk("%02hhx ", filt->ieee_addr[i]); 488 printk("%02hhx ", addr[7 - i]);
488 printk(KERN_DEBUG "\n"); 489 printk(KERN_DEBUG "\n");
489#endif 490#endif
490 } 491 }
@@ -492,8 +493,8 @@ static int mrf24j40_filter(struct ieee802154_dev *dev,
492 if (changed & IEEE802515_AFILT_PANID_CHANGED) { 493 if (changed & IEEE802515_AFILT_PANID_CHANGED) {
493 /* PAN ID */ 494 /* PAN ID */
494 u8 panidl, panidh; 495 u8 panidl, panidh;
495 panidh = filt->pan_id >> 8 & 0xff; 496 panidh = le16_to_cpu(filt->pan_id) >> 8 & 0xff;
496 panidl = filt->pan_id & 0xff; 497 panidl = le16_to_cpu(filt->pan_id) & 0xff;
497 write_short_reg(devrec, REG_PANIDH, panidh); 498 write_short_reg(devrec, REG_PANIDH, panidh);
498 write_short_reg(devrec, REG_PANIDL, panidl); 499 write_short_reg(devrec, REG_PANIDL, panidl);
499 500
diff --git a/include/net/af_ieee802154.h b/include/net/af_ieee802154.h
index 75e64c7a2960..f79ae2aa76d6 100644
--- a/include/net/af_ieee802154.h
+++ b/include/net/af_ieee802154.h
@@ -36,7 +36,7 @@ enum {
36/* address length, octets */ 36/* address length, octets */
37#define IEEE802154_ADDR_LEN 8 37#define IEEE802154_ADDR_LEN 8
38 38
39struct ieee802154_addr { 39struct ieee802154_addr_sa {
40 int addr_type; 40 int addr_type;
41 u16 pan_id; 41 u16 pan_id;
42 union { 42 union {
@@ -51,7 +51,7 @@ struct ieee802154_addr {
51 51
52struct sockaddr_ieee802154 { 52struct sockaddr_ieee802154 {
53 sa_family_t family; /* AF_IEEE802154 */ 53 sa_family_t family; /* AF_IEEE802154 */
54 struct ieee802154_addr addr; 54 struct ieee802154_addr_sa addr;
55}; 55};
56 56
57/* get/setsockopt */ 57/* get/setsockopt */
diff --git a/include/net/ieee802154.h b/include/net/ieee802154.h
index ee59f8b188dd..c7ae0ac528dc 100644
--- a/include/net/ieee802154.h
+++ b/include/net/ieee802154.h
@@ -42,22 +42,42 @@
42 (((x) << IEEE802154_FC_TYPE_SHIFT) & IEEE802154_FC_TYPE_MASK)); \ 42 (((x) << IEEE802154_FC_TYPE_SHIFT) & IEEE802154_FC_TYPE_MASK)); \
43 } while (0) 43 } while (0)
44 44
45#define IEEE802154_FC_SECEN (1 << 3) 45#define IEEE802154_FC_SECEN_SHIFT 3
46#define IEEE802154_FC_FRPEND (1 << 4) 46#define IEEE802154_FC_SECEN (1 << IEEE802154_FC_SECEN_SHIFT)
47#define IEEE802154_FC_ACK_REQ (1 << 5) 47#define IEEE802154_FC_FRPEND_SHIFT 4
48#define IEEE802154_FC_INTRA_PAN (1 << 6) 48#define IEEE802154_FC_FRPEND (1 << IEEE802154_FC_FRPEND_SHIFT)
49#define IEEE802154_FC_ACK_REQ_SHIFT 5
50#define IEEE802154_FC_ACK_REQ (1 << IEEE802154_FC_ACK_REQ_SHIFT)
51#define IEEE802154_FC_INTRA_PAN_SHIFT 6
52#define IEEE802154_FC_INTRA_PAN (1 << IEEE802154_FC_INTRA_PAN_SHIFT)
49 53
50#define IEEE802154_FC_SAMODE_SHIFT 14 54#define IEEE802154_FC_SAMODE_SHIFT 14
51#define IEEE802154_FC_SAMODE_MASK (3 << IEEE802154_FC_SAMODE_SHIFT) 55#define IEEE802154_FC_SAMODE_MASK (3 << IEEE802154_FC_SAMODE_SHIFT)
52#define IEEE802154_FC_DAMODE_SHIFT 10 56#define IEEE802154_FC_DAMODE_SHIFT 10
53#define IEEE802154_FC_DAMODE_MASK (3 << IEEE802154_FC_DAMODE_SHIFT) 57#define IEEE802154_FC_DAMODE_MASK (3 << IEEE802154_FC_DAMODE_SHIFT)
54 58
59#define IEEE802154_FC_VERSION_SHIFT 12
60#define IEEE802154_FC_VERSION_MASK (3 << IEEE802154_FC_VERSION_SHIFT)
61#define IEEE802154_FC_VERSION(x) ((x & IEEE802154_FC_VERSION_MASK) >> IEEE802154_FC_VERSION_SHIFT)
62
55#define IEEE802154_FC_SAMODE(x) \ 63#define IEEE802154_FC_SAMODE(x) \
56 (((x) & IEEE802154_FC_SAMODE_MASK) >> IEEE802154_FC_SAMODE_SHIFT) 64 (((x) & IEEE802154_FC_SAMODE_MASK) >> IEEE802154_FC_SAMODE_SHIFT)
57 65
58#define IEEE802154_FC_DAMODE(x) \ 66#define IEEE802154_FC_DAMODE(x) \
59 (((x) & IEEE802154_FC_DAMODE_MASK) >> IEEE802154_FC_DAMODE_SHIFT) 67 (((x) & IEEE802154_FC_DAMODE_MASK) >> IEEE802154_FC_DAMODE_SHIFT)
60 68
69#define IEEE802154_SCF_SECLEVEL_MASK 7
70#define IEEE802154_SCF_SECLEVEL_SHIFT 0
71#define IEEE802154_SCF_SECLEVEL(x) (x & IEEE802154_SCF_SECLEVEL_MASK)
72#define IEEE802154_SCF_KEY_ID_MODE_SHIFT 3
73#define IEEE802154_SCF_KEY_ID_MODE_MASK (3 << IEEE802154_SCF_KEY_ID_MODE_SHIFT)
74#define IEEE802154_SCF_KEY_ID_MODE(x) \
75 ((x & IEEE802154_SCF_KEY_ID_MODE_MASK) >> IEEE802154_SCF_KEY_ID_MODE_SHIFT)
76
77#define IEEE802154_SCF_KEY_IMPLICIT 0
78#define IEEE802154_SCF_KEY_INDEX 1
79#define IEEE802154_SCF_KEY_SHORT_INDEX 2
80#define IEEE802154_SCF_KEY_HW_INDEX 3
61 81
62/* MAC footer size */ 82/* MAC footer size */
63#define IEEE802154_MFR_SIZE 2 /* 2 octets */ 83#define IEEE802154_MFR_SIZE 2 /* 2 octets */
diff --git a/include/net/ieee802154_netdev.h b/include/net/ieee802154_netdev.h
index 97b2e34d87f7..e1717cbf609b 100644
--- a/include/net/ieee802154_netdev.h
+++ b/include/net/ieee802154_netdev.h
@@ -28,24 +28,175 @@
28#define IEEE802154_NETDEVICE_H 28#define IEEE802154_NETDEVICE_H
29 29
30#include <net/af_ieee802154.h> 30#include <net/af_ieee802154.h>
31#include <linux/netdevice.h>
32#include <linux/skbuff.h>
31 33
32struct ieee802154_frag_info { 34struct ieee802154_sechdr {
33 __be16 d_tag; 35#if defined(__LITTLE_ENDIAN_BITFIELD)
34 u16 d_size; 36 u8 level:3,
35 u8 d_offset; 37 key_id_mode:2,
38 reserved:3;
39#elif defined(__BIG_ENDIAN_BITFIELD)
40 u8 reserved:3,
41 key_id_mode:2,
42 level:3;
43#else
44#error "Please fix <asm/byteorder.h>"
45#endif
46 u8 key_id;
47 __le32 frame_counter;
48 union {
49 __le32 short_src;
50 __le64 extended_src;
51 };
52};
53
54struct ieee802154_addr {
55 u8 mode;
56 __le16 pan_id;
57 union {
58 __le16 short_addr;
59 __le64 extended_addr;
60 };
61};
62
63struct ieee802154_hdr_fc {
64#if defined(__LITTLE_ENDIAN_BITFIELD)
65 u16 type:3,
66 security_enabled:1,
67 frame_pending:1,
68 ack_request:1,
69 intra_pan:1,
70 reserved:3,
71 dest_addr_mode:2,
72 version:2,
73 source_addr_mode:2;
74#elif defined(__BIG_ENDIAN_BITFIELD)
75 u16 reserved:1,
76 intra_pan:1,
77 ack_request:1,
78 frame_pending:1,
79 security_enabled:1,
80 type:3,
81 source_addr_mode:2,
82 version:2,
83 dest_addr_mode:2,
84 reserved2:2;
85#else
86#error "Please fix <asm/byteorder.h>"
87#endif
36}; 88};
37 89
90struct ieee802154_hdr {
91 struct ieee802154_hdr_fc fc;
92 u8 seq;
93 struct ieee802154_addr source;
94 struct ieee802154_addr dest;
95 struct ieee802154_sechdr sec;
96};
97
98/* pushes hdr onto the skb. fields of hdr->fc that can be calculated from
99 * the contents of hdr will be, and the actual value of those bits in
100 * hdr->fc will be ignored. this includes the INTRA_PAN bit and the frame
101 * version, if SECEN is set.
102 */
103int ieee802154_hdr_push(struct sk_buff *skb, const struct ieee802154_hdr *hdr);
104
105/* pulls the entire 802.15.4 header off of the skb, including the security
106 * header, and performs pan id decompression
107 */
108int ieee802154_hdr_pull(struct sk_buff *skb, struct ieee802154_hdr *hdr);
109
110/* parses the frame control, sequence number of address fields in a given skb
111 * and stores them into hdr, performing pan id decompression and length checks
112 * to be suitable for use in header_ops.parse
113 */
114int ieee802154_hdr_peek_addrs(const struct sk_buff *skb,
115 struct ieee802154_hdr *hdr);
116
117static inline int ieee802154_hdr_length(struct sk_buff *skb)
118{
119 struct ieee802154_hdr hdr;
120 int len = ieee802154_hdr_pull(skb, &hdr);
121
122 if (len > 0)
123 skb_push(skb, len);
124
125 return len;
126}
127
128static inline bool ieee802154_addr_equal(const struct ieee802154_addr *a1,
129 const struct ieee802154_addr *a2)
130{
131 if (a1->pan_id != a2->pan_id || a1->mode != a2->mode)
132 return false;
133
134 if ((a1->mode == IEEE802154_ADDR_LONG &&
135 a1->extended_addr != a2->extended_addr) ||
136 (a1->mode == IEEE802154_ADDR_SHORT &&
137 a1->short_addr != a2->short_addr))
138 return false;
139
140 return true;
141}
142
143static inline __le64 ieee802154_devaddr_from_raw(const void *raw)
144{
145 u64 temp;
146
147 memcpy(&temp, raw, IEEE802154_ADDR_LEN);
148 return (__force __le64)swab64(temp);
149}
150
151static inline void ieee802154_devaddr_to_raw(void *raw, __le64 addr)
152{
153 u64 temp = swab64((__force u64)addr);
154
155 memcpy(raw, &temp, IEEE802154_ADDR_LEN);
156}
157
158static inline void ieee802154_addr_from_sa(struct ieee802154_addr *a,
159 const struct ieee802154_addr_sa *sa)
160{
161 a->mode = sa->addr_type;
162 a->pan_id = cpu_to_le16(sa->pan_id);
163
164 switch (a->mode) {
165 case IEEE802154_ADDR_SHORT:
166 a->short_addr = cpu_to_le16(sa->short_addr);
167 break;
168 case IEEE802154_ADDR_LONG:
169 a->extended_addr = ieee802154_devaddr_from_raw(sa->hwaddr);
170 break;
171 }
172}
173
174static inline void ieee802154_addr_to_sa(struct ieee802154_addr_sa *sa,
175 const struct ieee802154_addr *a)
176{
177 sa->addr_type = a->mode;
178 sa->pan_id = le16_to_cpu(a->pan_id);
179
180 switch (a->mode) {
181 case IEEE802154_ADDR_SHORT:
182 sa->short_addr = le16_to_cpu(a->short_addr);
183 break;
184 case IEEE802154_ADDR_LONG:
185 ieee802154_devaddr_to_raw(sa->hwaddr, a->extended_addr);
186 break;
187 }
188}
189
38/* 190/*
39 * A control block of skb passed between the ARPHRD_IEEE802154 device 191 * A control block of skb passed between the ARPHRD_IEEE802154 device
40 * and other stack parts. 192 * and other stack parts.
41 */ 193 */
42struct ieee802154_mac_cb { 194struct ieee802154_mac_cb {
43 u8 lqi; 195 u8 lqi;
44 struct ieee802154_addr sa;
45 struct ieee802154_addr da;
46 u8 flags; 196 u8 flags;
47 u8 seq; 197 u8 seq;
48 struct ieee802154_frag_info frag_info; 198 struct ieee802154_addr source;
199 struct ieee802154_addr dest;
49}; 200};
50 201
51static inline struct ieee802154_mac_cb *mac_cb(struct sk_buff *skb) 202static inline struct ieee802154_mac_cb *mac_cb(struct sk_buff *skb)
@@ -57,23 +208,17 @@ static inline struct ieee802154_mac_cb *mac_cb(struct sk_buff *skb)
57 208
58#define MAC_CB_FLAG_ACKREQ (1 << 3) 209#define MAC_CB_FLAG_ACKREQ (1 << 3)
59#define MAC_CB_FLAG_SECEN (1 << 4) 210#define MAC_CB_FLAG_SECEN (1 << 4)
60#define MAC_CB_FLAG_INTRAPAN (1 << 5)
61 211
62static inline int mac_cb_is_ackreq(struct sk_buff *skb) 212static inline bool mac_cb_is_ackreq(struct sk_buff *skb)
63{ 213{
64 return mac_cb(skb)->flags & MAC_CB_FLAG_ACKREQ; 214 return mac_cb(skb)->flags & MAC_CB_FLAG_ACKREQ;
65} 215}
66 216
67static inline int mac_cb_is_secen(struct sk_buff *skb) 217static inline bool mac_cb_is_secen(struct sk_buff *skb)
68{ 218{
69 return mac_cb(skb)->flags & MAC_CB_FLAG_SECEN; 219 return mac_cb(skb)->flags & MAC_CB_FLAG_SECEN;
70} 220}
71 221
72static inline int mac_cb_is_intrapan(struct sk_buff *skb)
73{
74 return mac_cb(skb)->flags & MAC_CB_FLAG_INTRAPAN;
75}
76
77static inline int mac_cb_type(struct sk_buff *skb) 222static inline int mac_cb_type(struct sk_buff *skb)
78{ 223{
79 return mac_cb(skb)->flags & MAC_CB_FLAG_TYPEMASK; 224 return mac_cb(skb)->flags & MAC_CB_FLAG_TYPEMASK;
@@ -99,7 +244,7 @@ struct ieee802154_mlme_ops {
99 u8 channel, u8 page, u8 cap); 244 u8 channel, u8 page, u8 cap);
100 int (*assoc_resp)(struct net_device *dev, 245 int (*assoc_resp)(struct net_device *dev,
101 struct ieee802154_addr *addr, 246 struct ieee802154_addr *addr,
102 u16 short_addr, u8 status); 247 __le16 short_addr, u8 status);
103 int (*disassoc_req)(struct net_device *dev, 248 int (*disassoc_req)(struct net_device *dev,
104 struct ieee802154_addr *addr, 249 struct ieee802154_addr *addr,
105 u8 reason); 250 u8 reason);
@@ -118,8 +263,8 @@ struct ieee802154_mlme_ops {
118 * FIXME: these should become the part of PIB/MIB interface. 263 * FIXME: these should become the part of PIB/MIB interface.
119 * However we still don't have IB interface of any kind 264 * However we still don't have IB interface of any kind
120 */ 265 */
121 u16 (*get_pan_id)(const struct net_device *dev); 266 __le16 (*get_pan_id)(const struct net_device *dev);
122 u16 (*get_short_addr)(const struct net_device *dev); 267 __le16 (*get_short_addr)(const struct net_device *dev);
123 u8 (*get_dsn)(const struct net_device *dev); 268 u8 (*get_dsn)(const struct net_device *dev);
124}; 269};
125 270
diff --git a/include/net/mac802154.h b/include/net/mac802154.h
index 8ca3d04e7558..a591053cae63 100644
--- a/include/net/mac802154.h
+++ b/include/net/mac802154.h
@@ -20,6 +20,7 @@
20#define NET_MAC802154_H 20#define NET_MAC802154_H
21 21
22#include <net/af_ieee802154.h> 22#include <net/af_ieee802154.h>
23#include <linux/skbuff.h>
23 24
24/* General MAC frame format: 25/* General MAC frame format:
25 * 2 bytes: Frame Control 26 * 2 bytes: Frame Control
@@ -50,7 +51,7 @@ struct ieee802154_hw_addr_filt {
50 * devices across independent networks. 51 * devices across independent networks.
51 */ 52 */
52 __le16 short_addr; 53 __le16 short_addr;
53 u8 ieee_addr[IEEE802154_ADDR_LEN]; 54 __le64 ieee_addr;
54 u8 pan_coord; 55 u8 pan_coord;
55}; 56};
56 57
@@ -153,8 +154,7 @@ struct ieee802154_ops {
153 int (*set_hw_addr_filt)(struct ieee802154_dev *dev, 154 int (*set_hw_addr_filt)(struct ieee802154_dev *dev,
154 struct ieee802154_hw_addr_filt *filt, 155 struct ieee802154_hw_addr_filt *filt,
155 unsigned long changed); 156 unsigned long changed);
156 int (*ieee_addr)(struct ieee802154_dev *dev, 157 int (*ieee_addr)(struct ieee802154_dev *dev, __le64 addr);
157 u8 addr[IEEE802154_ADDR_LEN]);
158 int (*set_txpower)(struct ieee802154_dev *dev, int db); 158 int (*set_txpower)(struct ieee802154_dev *dev, int db);
159 int (*set_lbt)(struct ieee802154_dev *dev, bool on); 159 int (*set_lbt)(struct ieee802154_dev *dev, bool on);
160 int (*set_cca_mode)(struct ieee802154_dev *dev, u8 mode); 160 int (*set_cca_mode)(struct ieee802154_dev *dev, u8 mode);
diff --git a/include/net/nl802154.h b/include/net/nl802154.h
index 99d2ba1c7e03..b23548e04098 100644
--- a/include/net/nl802154.h
+++ b/include/net/nl802154.h
@@ -52,7 +52,7 @@ int ieee802154_nl_assoc_indic(struct net_device *dev,
52 * Note: This is in section 7.3.2 of the IEEE 802.15.4 document. 52 * Note: This is in section 7.3.2 of the IEEE 802.15.4 document.
53 */ 53 */
54int ieee802154_nl_assoc_confirm(struct net_device *dev, 54int ieee802154_nl_assoc_confirm(struct net_device *dev,
55 u16 short_addr, u8 status); 55 __le16 short_addr, u8 status);
56 56
57/** 57/**
58 * ieee802154_nl_disassoc_indic - Notify userland of disassociation. 58 * ieee802154_nl_disassoc_indic - Notify userland of disassociation.
@@ -111,8 +111,8 @@ int ieee802154_nl_scan_confirm(struct net_device *dev,
111 * Note: This API cannot indicate a beacon frame for a coordinator 111 * Note: This API cannot indicate a beacon frame for a coordinator
112 * operating in long addressing mode. 112 * operating in long addressing mode.
113 */ 113 */
114int ieee802154_nl_beacon_indic(struct net_device *dev, u16 panid, 114int ieee802154_nl_beacon_indic(struct net_device *dev, __le16 panid,
115 u16 coord_addr); 115 __le16 coord_addr);
116 116
117/** 117/**
118 * ieee802154_nl_start_confirm - Notify userland of completion of start. 118 * ieee802154_nl_start_confirm - Notify userland of completion of start.
diff --git a/net/ieee802154/6lowpan_rtnl.c b/net/ieee802154/6lowpan_rtnl.c
index 48a8f52b5991..606039442a59 100644
--- a/net/ieee802154/6lowpan_rtnl.c
+++ b/net/ieee802154/6lowpan_rtnl.c
@@ -119,29 +119,29 @@ static int lowpan_header_create(struct sk_buff *skb,
119 mac_cb(skb)->seq = ieee802154_mlme_ops(dev)->get_dsn(dev); 119 mac_cb(skb)->seq = ieee802154_mlme_ops(dev)->get_dsn(dev);
120 120
121 /* prepare wpan address data */ 121 /* prepare wpan address data */
122 sa.addr_type = IEEE802154_ADDR_LONG; 122 sa.mode = IEEE802154_ADDR_LONG;
123 sa.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev); 123 sa.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev);
124 sa.extended_addr = ieee802154_devaddr_from_raw(saddr);
124 125
125 memcpy(&(sa.hwaddr), saddr, 8);
126 /* intra-PAN communications */ 126 /* intra-PAN communications */
127 da.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev); 127 da.pan_id = sa.pan_id;
128 128
129 /* if the destination address is the broadcast address, use the 129 /* if the destination address is the broadcast address, use the
130 * corresponding short address 130 * corresponding short address
131 */ 131 */
132 if (lowpan_is_addr_broadcast(daddr)) { 132 if (lowpan_is_addr_broadcast(daddr)) {
133 da.addr_type = IEEE802154_ADDR_SHORT; 133 da.mode = IEEE802154_ADDR_SHORT;
134 da.short_addr = IEEE802154_ADDR_BROADCAST; 134 da.short_addr = cpu_to_le16(IEEE802154_ADDR_BROADCAST);
135 } else { 135 } else {
136 da.addr_type = IEEE802154_ADDR_LONG; 136 da.mode = IEEE802154_ADDR_LONG;
137 memcpy(&(da.hwaddr), daddr, IEEE802154_ADDR_LEN); 137 da.extended_addr = ieee802154_devaddr_from_raw(daddr);
138 138
139 /* request acknowledgment */ 139 /* request acknowledgment */
140 mac_cb(skb)->flags |= MAC_CB_FLAG_ACKREQ; 140 mac_cb(skb)->flags |= MAC_CB_FLAG_ACKREQ;
141 } 141 }
142 142
143 return dev_hard_header(skb, lowpan_dev_info(dev)->real_dev, 143 return dev_hard_header(skb, lowpan_dev_info(dev)->real_dev,
144 type, (void *)&da, (void *)&sa, skb->len); 144 type, (void *)&da, (void *)&sa, 0);
145} 145}
146 146
147static int lowpan_give_skb_to_devices(struct sk_buff *skb, 147static int lowpan_give_skb_to_devices(struct sk_buff *skb,
@@ -168,10 +168,11 @@ static int lowpan_give_skb_to_devices(struct sk_buff *skb,
168 return stat; 168 return stat;
169} 169}
170 170
171static int process_data(struct sk_buff *skb) 171static int process_data(struct sk_buff *skb, const struct ieee802154_hdr *hdr)
172{ 172{
173 u8 iphc0, iphc1; 173 u8 iphc0, iphc1;
174 const struct ieee802154_addr *_saddr, *_daddr; 174 struct ieee802154_addr_sa sa, da;
175 void *sap, *dap;
175 176
176 raw_dump_table(__func__, "raw skb data dump", skb->data, skb->len); 177 raw_dump_table(__func__, "raw skb data dump", skb->data, skb->len);
177 /* at least two bytes will be used for the encoding */ 178 /* at least two bytes will be used for the encoding */
@@ -184,14 +185,23 @@ static int process_data(struct sk_buff *skb)
184 if (lowpan_fetch_skb_u8(skb, &iphc1)) 185 if (lowpan_fetch_skb_u8(skb, &iphc1))
185 goto drop; 186 goto drop;
186 187
187 _saddr = &mac_cb(skb)->sa; 188 ieee802154_addr_to_sa(&sa, &hdr->source);
188 _daddr = &mac_cb(skb)->da; 189 ieee802154_addr_to_sa(&da, &hdr->dest);
189 190
190 return lowpan_process_data(skb, skb->dev, (u8 *)_saddr->hwaddr, 191 if (sa.addr_type == IEEE802154_ADDR_SHORT)
191 _saddr->addr_type, IEEE802154_ADDR_LEN, 192 sap = &sa.short_addr;
192 (u8 *)_daddr->hwaddr, _daddr->addr_type, 193 else
193 IEEE802154_ADDR_LEN, iphc0, iphc1, 194 sap = &sa.hwaddr;
194 lowpan_give_skb_to_devices); 195
196 if (da.addr_type == IEEE802154_ADDR_SHORT)
197 dap = &da.short_addr;
198 else
199 dap = &da.hwaddr;
200
201 return lowpan_process_data(skb, skb->dev, sap, sa.addr_type,
202 IEEE802154_ADDR_LEN, dap, da.addr_type,
203 IEEE802154_ADDR_LEN, iphc0, iphc1,
204 lowpan_give_skb_to_devices);
195 205
196drop: 206drop:
197 kfree_skb(skb); 207 kfree_skb(skb);
@@ -352,13 +362,13 @@ static struct wpan_phy *lowpan_get_phy(const struct net_device *dev)
352 return ieee802154_mlme_ops(real_dev)->get_phy(real_dev); 362 return ieee802154_mlme_ops(real_dev)->get_phy(real_dev);
353} 363}
354 364
355static u16 lowpan_get_pan_id(const struct net_device *dev) 365static __le16 lowpan_get_pan_id(const struct net_device *dev)
356{ 366{
357 struct net_device *real_dev = lowpan_dev_info(dev)->real_dev; 367 struct net_device *real_dev = lowpan_dev_info(dev)->real_dev;
358 return ieee802154_mlme_ops(real_dev)->get_pan_id(real_dev); 368 return ieee802154_mlme_ops(real_dev)->get_pan_id(real_dev);
359} 369}
360 370
361static u16 lowpan_get_short_addr(const struct net_device *dev) 371static __le16 lowpan_get_short_addr(const struct net_device *dev)
362{ 372{
363 struct net_device *real_dev = lowpan_dev_info(dev)->real_dev; 373 struct net_device *real_dev = lowpan_dev_info(dev)->real_dev;
364 return ieee802154_mlme_ops(real_dev)->get_short_addr(real_dev); 374 return ieee802154_mlme_ops(real_dev)->get_short_addr(real_dev);
@@ -438,6 +448,7 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev,
438 struct packet_type *pt, struct net_device *orig_dev) 448 struct packet_type *pt, struct net_device *orig_dev)
439{ 449{
440 struct sk_buff *local_skb; 450 struct sk_buff *local_skb;
451 struct ieee802154_hdr hdr;
441 int ret; 452 int ret;
442 453
443 if (!netif_running(dev)) 454 if (!netif_running(dev))
@@ -446,6 +457,9 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev,
446 if (dev->type != ARPHRD_IEEE802154) 457 if (dev->type != ARPHRD_IEEE802154)
447 goto drop_skb; 458 goto drop_skb;
448 459
460 if (ieee802154_hdr_peek_addrs(skb, &hdr) < 0)
461 goto drop_skb;
462
449 local_skb = skb_clone(skb, GFP_ATOMIC); 463 local_skb = skb_clone(skb, GFP_ATOMIC);
450 if (!local_skb) 464 if (!local_skb)
451 goto drop_skb; 465 goto drop_skb;
@@ -466,14 +480,14 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev,
466 } else { 480 } else {
467 switch (skb->data[0] & 0xe0) { 481 switch (skb->data[0] & 0xe0) {
468 case LOWPAN_DISPATCH_IPHC: /* ipv6 datagram */ 482 case LOWPAN_DISPATCH_IPHC: /* ipv6 datagram */
469 ret = process_data(local_skb); 483 ret = process_data(local_skb, &hdr);
470 if (ret == NET_RX_DROP) 484 if (ret == NET_RX_DROP)
471 goto drop; 485 goto drop;
472 break; 486 break;
473 case LOWPAN_DISPATCH_FRAG1: /* first fragment header */ 487 case LOWPAN_DISPATCH_FRAG1: /* first fragment header */
474 ret = lowpan_frag_rcv(local_skb, LOWPAN_DISPATCH_FRAG1); 488 ret = lowpan_frag_rcv(local_skb, LOWPAN_DISPATCH_FRAG1);
475 if (ret == 1) { 489 if (ret == 1) {
476 ret = process_data(local_skb); 490 ret = process_data(local_skb, &hdr);
477 if (ret == NET_RX_DROP) 491 if (ret == NET_RX_DROP)
478 goto drop; 492 goto drop;
479 } 493 }
@@ -481,7 +495,7 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev,
481 case LOWPAN_DISPATCH_FRAGN: /* next fragments headers */ 495 case LOWPAN_DISPATCH_FRAGN: /* next fragments headers */
482 ret = lowpan_frag_rcv(local_skb, LOWPAN_DISPATCH_FRAGN); 496 ret = lowpan_frag_rcv(local_skb, LOWPAN_DISPATCH_FRAGN);
483 if (ret == 1) { 497 if (ret == 1) {
484 ret = process_data(local_skb); 498 ret = process_data(local_skb, &hdr);
485 if (ret == NET_RX_DROP) 499 if (ret == NET_RX_DROP)
486 goto drop; 500 goto drop;
487 } 501 }
diff --git a/net/ieee802154/Makefile b/net/ieee802154/Makefile
index b113fc4be3e0..bf1b51497a41 100644
--- a/net/ieee802154/Makefile
+++ b/net/ieee802154/Makefile
@@ -3,5 +3,8 @@ obj-$(CONFIG_IEEE802154_6LOWPAN) += 6lowpan.o
3obj-$(CONFIG_6LOWPAN_IPHC) += 6lowpan_iphc.o 3obj-$(CONFIG_6LOWPAN_IPHC) += 6lowpan_iphc.o
4 4
56lowpan-y := 6lowpan_rtnl.o reassembly.o 56lowpan-y := 6lowpan_rtnl.o reassembly.o
6ieee802154-y := netlink.o nl-mac.o nl-phy.o nl_policy.o wpan-class.o 6ieee802154-y := netlink.o nl-mac.o nl-phy.o nl_policy.o wpan-class.o \
7 header_ops.o
7af_802154-y := af_ieee802154.o raw.o dgram.o 8af_802154-y := af_ieee802154.o raw.o dgram.o
9
10ccflags-y += -D__CHECK_ENDIAN__
diff --git a/net/ieee802154/af802154.h b/net/ieee802154/af802154.h
index b1ec52537522..8330a09bfc95 100644
--- a/net/ieee802154/af802154.h
+++ b/net/ieee802154/af802154.h
@@ -25,12 +25,13 @@
25#define AF802154_H 25#define AF802154_H
26 26
27struct sk_buff; 27struct sk_buff;
28struct net_devce; 28struct net_device;
29struct ieee802154_addr;
29extern struct proto ieee802154_raw_prot; 30extern struct proto ieee802154_raw_prot;
30extern struct proto ieee802154_dgram_prot; 31extern struct proto ieee802154_dgram_prot;
31void ieee802154_raw_deliver(struct net_device *dev, struct sk_buff *skb); 32void ieee802154_raw_deliver(struct net_device *dev, struct sk_buff *skb);
32int ieee802154_dgram_deliver(struct net_device *dev, struct sk_buff *skb); 33int ieee802154_dgram_deliver(struct net_device *dev, struct sk_buff *skb);
33struct net_device *ieee802154_get_dev(struct net *net, 34struct net_device *ieee802154_get_dev(struct net *net,
34 struct ieee802154_addr *addr); 35 const struct ieee802154_addr *addr);
35 36
36#endif 37#endif
diff --git a/net/ieee802154/af_ieee802154.c b/net/ieee802154/af_ieee802154.c
index a56ab9c47278..be44a86751aa 100644
--- a/net/ieee802154/af_ieee802154.c
+++ b/net/ieee802154/af_ieee802154.c
@@ -43,25 +43,27 @@
43/* 43/*
44 * Utility function for families 44 * Utility function for families
45 */ 45 */
46struct net_device *ieee802154_get_dev(struct net *net, 46struct net_device*
47 struct ieee802154_addr *addr) 47ieee802154_get_dev(struct net *net, const struct ieee802154_addr *addr)
48{ 48{
49 struct net_device *dev = NULL; 49 struct net_device *dev = NULL;
50 struct net_device *tmp; 50 struct net_device *tmp;
51 u16 pan_id, short_addr; 51 __le16 pan_id, short_addr;
52 u8 hwaddr[IEEE802154_ADDR_LEN];
52 53
53 switch (addr->addr_type) { 54 switch (addr->mode) {
54 case IEEE802154_ADDR_LONG: 55 case IEEE802154_ADDR_LONG:
56 ieee802154_devaddr_to_raw(hwaddr, addr->extended_addr);
55 rcu_read_lock(); 57 rcu_read_lock();
56 dev = dev_getbyhwaddr_rcu(net, ARPHRD_IEEE802154, addr->hwaddr); 58 dev = dev_getbyhwaddr_rcu(net, ARPHRD_IEEE802154, hwaddr);
57 if (dev) 59 if (dev)
58 dev_hold(dev); 60 dev_hold(dev);
59 rcu_read_unlock(); 61 rcu_read_unlock();
60 break; 62 break;
61 case IEEE802154_ADDR_SHORT: 63 case IEEE802154_ADDR_SHORT:
62 if (addr->pan_id == 0xffff || 64 if (addr->pan_id == cpu_to_le16(IEEE802154_PANID_BROADCAST) ||
63 addr->short_addr == IEEE802154_ADDR_UNDEF || 65 addr->short_addr == cpu_to_le16(IEEE802154_ADDR_UNDEF) ||
64 addr->short_addr == 0xffff) 66 addr->short_addr == cpu_to_le16(IEEE802154_ADDR_UNDEF))
65 break; 67 break;
66 68
67 rtnl_lock(); 69 rtnl_lock();
@@ -86,7 +88,7 @@ struct net_device *ieee802154_get_dev(struct net *net,
86 break; 88 break;
87 default: 89 default:
88 pr_warning("Unsupported ieee802154 address type: %d\n", 90 pr_warning("Unsupported ieee802154 address type: %d\n",
89 addr->addr_type); 91 addr->mode);
90 break; 92 break;
91 } 93 }
92 94
diff --git a/net/ieee802154/dgram.c b/net/ieee802154/dgram.c
index 1846c1fe0d06..4c47154041b0 100644
--- a/net/ieee802154/dgram.c
+++ b/net/ieee802154/dgram.c
@@ -73,10 +73,10 @@ static int dgram_init(struct sock *sk)
73{ 73{
74 struct dgram_sock *ro = dgram_sk(sk); 74 struct dgram_sock *ro = dgram_sk(sk);
75 75
76 ro->dst_addr.addr_type = IEEE802154_ADDR_LONG; 76 ro->dst_addr.mode = IEEE802154_ADDR_LONG;
77 ro->dst_addr.pan_id = 0xffff; 77 ro->dst_addr.pan_id = cpu_to_le16(IEEE802154_ADDR_BROADCAST);
78 ro->want_ack = 1; 78 ro->want_ack = 1;
79 memset(&ro->dst_addr.hwaddr, 0xff, sizeof(ro->dst_addr.hwaddr)); 79 memset(&ro->dst_addr.extended_addr, 0xff, IEEE802154_ADDR_LEN);
80 return 0; 80 return 0;
81} 81}
82 82
@@ -88,6 +88,7 @@ static void dgram_close(struct sock *sk, long timeout)
88static int dgram_bind(struct sock *sk, struct sockaddr *uaddr, int len) 88static int dgram_bind(struct sock *sk, struct sockaddr *uaddr, int len)
89{ 89{
90 struct sockaddr_ieee802154 *addr = (struct sockaddr_ieee802154 *)uaddr; 90 struct sockaddr_ieee802154 *addr = (struct sockaddr_ieee802154 *)uaddr;
91 struct ieee802154_addr haddr;
91 struct dgram_sock *ro = dgram_sk(sk); 92 struct dgram_sock *ro = dgram_sk(sk);
92 int err = -EINVAL; 93 int err = -EINVAL;
93 struct net_device *dev; 94 struct net_device *dev;
@@ -102,7 +103,8 @@ static int dgram_bind(struct sock *sk, struct sockaddr *uaddr, int len)
102 if (addr->family != AF_IEEE802154) 103 if (addr->family != AF_IEEE802154)
103 goto out; 104 goto out;
104 105
105 dev = ieee802154_get_dev(sock_net(sk), &addr->addr); 106 ieee802154_addr_from_sa(&haddr, &addr->addr);
107 dev = ieee802154_get_dev(sock_net(sk), &haddr);
106 if (!dev) { 108 if (!dev) {
107 err = -ENODEV; 109 err = -ENODEV;
108 goto out; 110 goto out;
@@ -113,7 +115,7 @@ static int dgram_bind(struct sock *sk, struct sockaddr *uaddr, int len)
113 goto out_put; 115 goto out_put;
114 } 116 }
115 117
116 memcpy(&ro->src_addr, &addr->addr, sizeof(struct ieee802154_addr)); 118 ro->src_addr = haddr;
117 119
118 ro->bound = 1; 120 ro->bound = 1;
119 err = 0; 121 err = 0;
@@ -149,8 +151,7 @@ static int dgram_ioctl(struct sock *sk, int cmd, unsigned long arg)
149 * of this packet since that is all 151 * of this packet since that is all
150 * that will be read. 152 * that will be read.
151 */ 153 */
152 /* FIXME: parse the header for more correct value */ 154 amount = skb->len - ieee802154_hdr_length(skb);
153 amount = skb->len - (3+8+8);
154 } 155 }
155 spin_unlock_bh(&sk->sk_receive_queue.lock); 156 spin_unlock_bh(&sk->sk_receive_queue.lock);
156 return put_user(amount, (int __user *)arg); 157 return put_user(amount, (int __user *)arg);
@@ -181,7 +182,7 @@ static int dgram_connect(struct sock *sk, struct sockaddr *uaddr,
181 goto out; 182 goto out;
182 } 183 }
183 184
184 memcpy(&ro->dst_addr, &addr->addr, sizeof(struct ieee802154_addr)); 185 ieee802154_addr_from_sa(&ro->dst_addr, &addr->addr);
185 186
186out: 187out:
187 release_sock(sk); 188 release_sock(sk);
@@ -194,8 +195,8 @@ static int dgram_disconnect(struct sock *sk, int flags)
194 195
195 lock_sock(sk); 196 lock_sock(sk);
196 197
197 ro->dst_addr.addr_type = IEEE802154_ADDR_LONG; 198 ro->dst_addr.mode = IEEE802154_ADDR_LONG;
198 memset(&ro->dst_addr.hwaddr, 0xff, sizeof(ro->dst_addr.hwaddr)); 199 memset(&ro->dst_addr.extended_addr, 0xff, IEEE802154_ADDR_LEN);
199 200
200 release_sock(sk); 201 release_sock(sk);
201 202
@@ -232,7 +233,7 @@ static int dgram_sendmsg(struct kiocb *iocb, struct sock *sk,
232 233
233 if (size > mtu) { 234 if (size > mtu) {
234 pr_debug("size = %Zu, mtu = %u\n", size, mtu); 235 pr_debug("size = %Zu, mtu = %u\n", size, mtu);
235 err = -EINVAL; 236 err = -EMSGSIZE;
236 goto out_dev; 237 goto out_dev;
237 } 238 }
238 239
@@ -312,7 +313,7 @@ static int dgram_recvmsg(struct kiocb *iocb, struct sock *sk,
312 313
313 if (saddr) { 314 if (saddr) {
314 saddr->family = AF_IEEE802154; 315 saddr->family = AF_IEEE802154;
315 saddr->addr = mac_cb(skb)->sa; 316 ieee802154_addr_to_sa(&saddr->addr, &mac_cb(skb)->source);
316 *addr_len = sizeof(*saddr); 317 *addr_len = sizeof(*saddr);
317 } 318 }
318 319
@@ -336,40 +337,43 @@ static int dgram_rcv_skb(struct sock *sk, struct sk_buff *skb)
336 return NET_RX_SUCCESS; 337 return NET_RX_SUCCESS;
337} 338}
338 339
339static inline int ieee802154_match_sock(u8 *hw_addr, u16 pan_id, 340static inline bool
340 u16 short_addr, struct dgram_sock *ro) 341ieee802154_match_sock(__le64 hw_addr, __le16 pan_id, __le16 short_addr,
342 struct dgram_sock *ro)
341{ 343{
342 if (!ro->bound) 344 if (!ro->bound)
343 return 1; 345 return true;
344 346
345 if (ro->src_addr.addr_type == IEEE802154_ADDR_LONG && 347 if (ro->src_addr.mode == IEEE802154_ADDR_LONG &&
346 !memcmp(ro->src_addr.hwaddr, hw_addr, IEEE802154_ADDR_LEN)) 348 hw_addr == ro->src_addr.extended_addr)
347 return 1; 349 return true;
348 350
349 if (ro->src_addr.addr_type == IEEE802154_ADDR_SHORT && 351 if (ro->src_addr.mode == IEEE802154_ADDR_SHORT &&
350 pan_id == ro->src_addr.pan_id && 352 pan_id == ro->src_addr.pan_id &&
351 short_addr == ro->src_addr.short_addr) 353 short_addr == ro->src_addr.short_addr)
352 return 1; 354 return true;
353 355
354 return 0; 356 return false;
355} 357}
356 358
357int ieee802154_dgram_deliver(struct net_device *dev, struct sk_buff *skb) 359int ieee802154_dgram_deliver(struct net_device *dev, struct sk_buff *skb)
358{ 360{
359 struct sock *sk, *prev = NULL; 361 struct sock *sk, *prev = NULL;
360 int ret = NET_RX_SUCCESS; 362 int ret = NET_RX_SUCCESS;
361 u16 pan_id, short_addr; 363 __le16 pan_id, short_addr;
364 __le64 hw_addr;
362 365
363 /* Data frame processing */ 366 /* Data frame processing */
364 BUG_ON(dev->type != ARPHRD_IEEE802154); 367 BUG_ON(dev->type != ARPHRD_IEEE802154);
365 368
366 pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev); 369 pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev);
367 short_addr = ieee802154_mlme_ops(dev)->get_short_addr(dev); 370 short_addr = ieee802154_mlme_ops(dev)->get_short_addr(dev);
371 hw_addr = ieee802154_devaddr_from_raw(dev->dev_addr);
368 372
369 read_lock(&dgram_lock); 373 read_lock(&dgram_lock);
370 sk_for_each(sk, &dgram_head) { 374 sk_for_each(sk, &dgram_head) {
371 if (ieee802154_match_sock(dev->dev_addr, pan_id, short_addr, 375 if (ieee802154_match_sock(hw_addr, pan_id, short_addr,
372 dgram_sk(sk))) { 376 dgram_sk(sk))) {
373 if (prev) { 377 if (prev) {
374 struct sk_buff *clone; 378 struct sk_buff *clone;
375 clone = skb_clone(skb, GFP_ATOMIC); 379 clone = skb_clone(skb, GFP_ATOMIC);
diff --git a/net/ieee802154/header_ops.c b/net/ieee802154/header_ops.c
new file mode 100644
index 000000000000..bed42a48408c
--- /dev/null
+++ b/net/ieee802154/header_ops.c
@@ -0,0 +1,287 @@
1/*
2 * Copyright (C) 2014 Fraunhofer ITWM
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * Written by:
14 * Phoebe Buckheister <phoebe.buckheister@itwm.fraunhofer.de>
15 */
16
17#include <net/mac802154.h>
18#include <net/ieee802154.h>
19#include <net/ieee802154_netdev.h>
20
21static int
22ieee802154_hdr_push_addr(u8 *buf, const struct ieee802154_addr *addr,
23 bool omit_pan)
24{
25 int pos = 0;
26
27 if (addr->mode == IEEE802154_ADDR_NONE)
28 return 0;
29
30 if (!omit_pan) {
31 memcpy(buf + pos, &addr->pan_id, 2);
32 pos += 2;
33 }
34
35 switch (addr->mode) {
36 case IEEE802154_ADDR_SHORT:
37 memcpy(buf + pos, &addr->short_addr, 2);
38 pos += 2;
39 break;
40
41 case IEEE802154_ADDR_LONG:
42 memcpy(buf + pos, &addr->extended_addr, IEEE802154_ADDR_LEN);
43 pos += IEEE802154_ADDR_LEN;
44 break;
45
46 default:
47 return -EINVAL;
48 }
49
50 return pos;
51}
52
53static int
54ieee802154_hdr_push_sechdr(u8 *buf, const struct ieee802154_sechdr *hdr)
55{
56 int pos = 5;
57
58 memcpy(buf, hdr, 1);
59 memcpy(buf + 1, &hdr->frame_counter, 4);
60
61 switch (hdr->key_id_mode) {
62 case IEEE802154_SCF_KEY_IMPLICIT:
63 return pos;
64
65 case IEEE802154_SCF_KEY_INDEX:
66 break;
67
68 case IEEE802154_SCF_KEY_SHORT_INDEX:
69 memcpy(buf + pos, &hdr->short_src, 4);
70 pos += 4;
71 break;
72
73 case IEEE802154_SCF_KEY_HW_INDEX:
74 memcpy(buf + pos, &hdr->extended_src, IEEE802154_ADDR_LEN);
75 pos += IEEE802154_ADDR_LEN;
76 break;
77 }
78
79 buf[pos++] = hdr->key_id;
80
81 return pos;
82}
83
84int
85ieee802154_hdr_push(struct sk_buff *skb, const struct ieee802154_hdr *hdr)
86{
87 u8 buf[MAC802154_FRAME_HARD_HEADER_LEN];
88 int pos = 2;
89 int rc;
90 struct ieee802154_hdr_fc fc = hdr->fc;
91
92 buf[pos++] = hdr->seq;
93
94 fc.dest_addr_mode = hdr->dest.mode;
95
96 rc = ieee802154_hdr_push_addr(buf + pos, &hdr->dest, false);
97 if (rc < 0)
98 return -EINVAL;
99 pos += rc;
100
101 fc.source_addr_mode = hdr->source.mode;
102
103 if (hdr->source.pan_id == hdr->dest.pan_id &&
104 hdr->dest.mode != IEEE802154_ADDR_NONE)
105 fc.intra_pan = true;
106
107 rc = ieee802154_hdr_push_addr(buf + pos, &hdr->source, fc.intra_pan);
108 if (rc < 0)
109 return -EINVAL;
110 pos += rc;
111
112 if (fc.security_enabled) {
113 fc.version = 1;
114
115 rc = ieee802154_hdr_push_sechdr(buf + pos, &hdr->sec);
116 if (rc < 0)
117 return -EINVAL;
118
119 pos += rc;
120 }
121
122 memcpy(buf, &fc, 2);
123
124 memcpy(skb_push(skb, pos), buf, pos);
125
126 return pos;
127}
128EXPORT_SYMBOL_GPL(ieee802154_hdr_push);
129
130static int
131ieee802154_hdr_get_addr(const u8 *buf, int mode, bool omit_pan,
132 struct ieee802154_addr *addr)
133{
134 int pos = 0;
135
136 addr->mode = mode;
137
138 if (mode == IEEE802154_ADDR_NONE)
139 return 0;
140
141 if (!omit_pan) {
142 memcpy(&addr->pan_id, buf + pos, 2);
143 pos += 2;
144 }
145
146 if (mode == IEEE802154_ADDR_SHORT) {
147 memcpy(&addr->short_addr, buf + pos, 2);
148 return pos + 2;
149 } else {
150 memcpy(&addr->extended_addr, buf + pos, IEEE802154_ADDR_LEN);
151 return pos + IEEE802154_ADDR_LEN;
152 }
153}
154
155static int ieee802154_hdr_addr_len(int mode, bool omit_pan)
156{
157 int pan_len = omit_pan ? 0 : 2;
158
159 switch (mode) {
160 case IEEE802154_ADDR_NONE: return 0;
161 case IEEE802154_ADDR_SHORT: return 2 + pan_len;
162 case IEEE802154_ADDR_LONG: return IEEE802154_ADDR_LEN + pan_len;
163 default: return -EINVAL;
164 }
165}
166
167static int
168ieee802154_hdr_get_sechdr(const u8 *buf, struct ieee802154_sechdr *hdr)
169{
170 int pos = 5;
171
172 memcpy(hdr, buf, 1);
173 memcpy(&hdr->frame_counter, buf + 1, 4);
174
175 switch (hdr->key_id_mode) {
176 case IEEE802154_SCF_KEY_IMPLICIT:
177 return pos;
178
179 case IEEE802154_SCF_KEY_INDEX:
180 break;
181
182 case IEEE802154_SCF_KEY_SHORT_INDEX:
183 memcpy(&hdr->short_src, buf + pos, 4);
184 pos += 4;
185 break;
186
187 case IEEE802154_SCF_KEY_HW_INDEX:
188 memcpy(&hdr->extended_src, buf + pos, IEEE802154_ADDR_LEN);
189 pos += IEEE802154_ADDR_LEN;
190 break;
191 }
192
193 hdr->key_id = buf[pos++];
194
195 return pos;
196}
197
198static int ieee802154_hdr_sechdr_len(u8 sc)
199{
200 switch (IEEE802154_SCF_KEY_ID_MODE(sc)) {
201 case IEEE802154_SCF_KEY_IMPLICIT: return 5;
202 case IEEE802154_SCF_KEY_INDEX: return 6;
203 case IEEE802154_SCF_KEY_SHORT_INDEX: return 10;
204 case IEEE802154_SCF_KEY_HW_INDEX: return 14;
205 default: return -EINVAL;
206 }
207}
208
209static int ieee802154_hdr_minlen(const struct ieee802154_hdr *hdr)
210{
211 int dlen, slen;
212
213 dlen = ieee802154_hdr_addr_len(hdr->fc.dest_addr_mode, false);
214 slen = ieee802154_hdr_addr_len(hdr->fc.source_addr_mode,
215 hdr->fc.intra_pan);
216
217 if (slen < 0 || dlen < 0)
218 return -EINVAL;
219
220 return 3 + dlen + slen + hdr->fc.security_enabled;
221}
222
223static int
224ieee802154_hdr_get_addrs(const u8 *buf, struct ieee802154_hdr *hdr)
225{
226 int pos = 0;
227
228 pos += ieee802154_hdr_get_addr(buf + pos, hdr->fc.dest_addr_mode,
229 false, &hdr->dest);
230 pos += ieee802154_hdr_get_addr(buf + pos, hdr->fc.source_addr_mode,
231 hdr->fc.intra_pan, &hdr->source);
232
233 if (hdr->fc.intra_pan)
234 hdr->source.pan_id = hdr->dest.pan_id;
235
236 return pos;
237}
238
239int
240ieee802154_hdr_pull(struct sk_buff *skb, struct ieee802154_hdr *hdr)
241{
242 int pos = 3, rc;
243
244 if (!pskb_may_pull(skb, 3))
245 return -EINVAL;
246
247 memcpy(hdr, skb->data, 3);
248
249 rc = ieee802154_hdr_minlen(hdr);
250 if (rc < 0 || !pskb_may_pull(skb, rc))
251 return -EINVAL;
252
253 pos += ieee802154_hdr_get_addrs(skb->data + pos, hdr);
254
255 if (hdr->fc.security_enabled) {
256 int want = pos + ieee802154_hdr_sechdr_len(skb->data[pos]);
257
258 if (!pskb_may_pull(skb, want))
259 return -EINVAL;
260
261 pos += ieee802154_hdr_get_sechdr(skb->data + pos, &hdr->sec);
262 }
263
264 skb_pull(skb, pos);
265 return pos;
266}
267EXPORT_SYMBOL_GPL(ieee802154_hdr_pull);
268
269int
270ieee802154_hdr_peek_addrs(const struct sk_buff *skb, struct ieee802154_hdr *hdr)
271{
272 const u8 *buf = skb_mac_header(skb);
273 int pos = 3, rc;
274
275 if (buf + 3 > skb_tail_pointer(skb))
276 return -EINVAL;
277
278 memcpy(hdr, buf, 3);
279
280 rc = ieee802154_hdr_minlen(hdr);
281 if (rc < 0 || buf + rc > skb_tail_pointer(skb))
282 return -EINVAL;
283
284 pos += ieee802154_hdr_get_addrs(buf + pos, hdr);
285 return pos;
286}
287EXPORT_SYMBOL_GPL(ieee802154_hdr_peek_addrs);
diff --git a/net/ieee802154/nl-mac.c b/net/ieee802154/nl-mac.c
index ba5c1e002f37..bda8dba4f993 100644
--- a/net/ieee802154/nl-mac.c
+++ b/net/ieee802154/nl-mac.c
@@ -39,6 +39,26 @@
39 39
40#include "ieee802154.h" 40#include "ieee802154.h"
41 41
42static int nla_put_hwaddr(struct sk_buff *msg, int type, __le64 hwaddr)
43{
44 return nla_put_u64(msg, type, swab64((__force u64)hwaddr));
45}
46
47static __le64 nla_get_hwaddr(const struct nlattr *nla)
48{
49 return ieee802154_devaddr_from_raw(nla_data(nla));
50}
51
52static int nla_put_shortaddr(struct sk_buff *msg, int type, __le16 addr)
53{
54 return nla_put_u16(msg, type, le16_to_cpu(addr));
55}
56
57static __le16 nla_get_shortaddr(const struct nlattr *nla)
58{
59 return cpu_to_le16(nla_get_u16(nla));
60}
61
42int ieee802154_nl_assoc_indic(struct net_device *dev, 62int ieee802154_nl_assoc_indic(struct net_device *dev,
43 struct ieee802154_addr *addr, u8 cap) 63 struct ieee802154_addr *addr, u8 cap)
44{ 64{
@@ -46,7 +66,7 @@ int ieee802154_nl_assoc_indic(struct net_device *dev,
46 66
47 pr_debug("%s\n", __func__); 67 pr_debug("%s\n", __func__);
48 68
49 if (addr->addr_type != IEEE802154_ADDR_LONG) { 69 if (addr->mode != IEEE802154_ADDR_LONG) {
50 pr_err("%s: received non-long source address!\n", __func__); 70 pr_err("%s: received non-long source address!\n", __func__);
51 return -EINVAL; 71 return -EINVAL;
52 } 72 }
@@ -59,8 +79,8 @@ int ieee802154_nl_assoc_indic(struct net_device *dev,
59 nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) || 79 nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
60 nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, 80 nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN,
61 dev->dev_addr) || 81 dev->dev_addr) ||
62 nla_put(msg, IEEE802154_ATTR_SRC_HW_ADDR, IEEE802154_ADDR_LEN, 82 nla_put_hwaddr(msg, IEEE802154_ATTR_SRC_HW_ADDR,
63 addr->hwaddr) || 83 addr->extended_addr) ||
64 nla_put_u8(msg, IEEE802154_ATTR_CAPABILITY, cap)) 84 nla_put_u8(msg, IEEE802154_ATTR_CAPABILITY, cap))
65 goto nla_put_failure; 85 goto nla_put_failure;
66 86
@@ -72,7 +92,7 @@ nla_put_failure:
72} 92}
73EXPORT_SYMBOL(ieee802154_nl_assoc_indic); 93EXPORT_SYMBOL(ieee802154_nl_assoc_indic);
74 94
75int ieee802154_nl_assoc_confirm(struct net_device *dev, u16 short_addr, 95int ieee802154_nl_assoc_confirm(struct net_device *dev, __le16 short_addr,
76 u8 status) 96 u8 status)
77{ 97{
78 struct sk_buff *msg; 98 struct sk_buff *msg;
@@ -87,7 +107,7 @@ int ieee802154_nl_assoc_confirm(struct net_device *dev, u16 short_addr,
87 nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) || 107 nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
88 nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, 108 nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN,
89 dev->dev_addr) || 109 dev->dev_addr) ||
90 nla_put_u16(msg, IEEE802154_ATTR_SHORT_ADDR, short_addr) || 110 nla_put_shortaddr(msg, IEEE802154_ATTR_SHORT_ADDR, short_addr) ||
91 nla_put_u8(msg, IEEE802154_ATTR_STATUS, status)) 111 nla_put_u8(msg, IEEE802154_ATTR_STATUS, status))
92 goto nla_put_failure; 112 goto nla_put_failure;
93 return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP); 113 return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP);
@@ -114,13 +134,13 @@ int ieee802154_nl_disassoc_indic(struct net_device *dev,
114 nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, 134 nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN,
115 dev->dev_addr)) 135 dev->dev_addr))
116 goto nla_put_failure; 136 goto nla_put_failure;
117 if (addr->addr_type == IEEE802154_ADDR_LONG) { 137 if (addr->mode == IEEE802154_ADDR_LONG) {
118 if (nla_put(msg, IEEE802154_ATTR_SRC_HW_ADDR, IEEE802154_ADDR_LEN, 138 if (nla_put_hwaddr(msg, IEEE802154_ATTR_SRC_HW_ADDR,
119 addr->hwaddr)) 139 addr->extended_addr))
120 goto nla_put_failure; 140 goto nla_put_failure;
121 } else { 141 } else {
122 if (nla_put_u16(msg, IEEE802154_ATTR_SRC_SHORT_ADDR, 142 if (nla_put_shortaddr(msg, IEEE802154_ATTR_SRC_SHORT_ADDR,
123 addr->short_addr)) 143 addr->short_addr))
124 goto nla_put_failure; 144 goto nla_put_failure;
125 } 145 }
126 if (nla_put_u8(msg, IEEE802154_ATTR_REASON, reason)) 146 if (nla_put_u8(msg, IEEE802154_ATTR_REASON, reason))
@@ -157,8 +177,8 @@ nla_put_failure:
157} 177}
158EXPORT_SYMBOL(ieee802154_nl_disassoc_confirm); 178EXPORT_SYMBOL(ieee802154_nl_disassoc_confirm);
159 179
160int ieee802154_nl_beacon_indic(struct net_device *dev, 180int ieee802154_nl_beacon_indic(struct net_device *dev, __le16 panid,
161 u16 panid, u16 coord_addr) 181 __le16 coord_addr)
162{ 182{
163 struct sk_buff *msg; 183 struct sk_buff *msg;
164 184
@@ -172,8 +192,9 @@ int ieee802154_nl_beacon_indic(struct net_device *dev,
172 nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) || 192 nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
173 nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, 193 nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN,
174 dev->dev_addr) || 194 dev->dev_addr) ||
175 nla_put_u16(msg, IEEE802154_ATTR_COORD_SHORT_ADDR, coord_addr) || 195 nla_put_shortaddr(msg, IEEE802154_ATTR_COORD_SHORT_ADDR,
176 nla_put_u16(msg, IEEE802154_ATTR_COORD_PAN_ID, panid)) 196 coord_addr) ||
197 nla_put_shortaddr(msg, IEEE802154_ATTR_COORD_PAN_ID, panid))
177 goto nla_put_failure; 198 goto nla_put_failure;
178 return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP); 199 return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP);
179 200
@@ -243,6 +264,7 @@ static int ieee802154_nl_fill_iface(struct sk_buff *msg, u32 portid,
243{ 264{
244 void *hdr; 265 void *hdr;
245 struct wpan_phy *phy; 266 struct wpan_phy *phy;
267 __le16 short_addr, pan_id;
246 268
247 pr_debug("%s\n", __func__); 269 pr_debug("%s\n", __func__);
248 270
@@ -254,15 +276,16 @@ static int ieee802154_nl_fill_iface(struct sk_buff *msg, u32 portid,
254 phy = ieee802154_mlme_ops(dev)->get_phy(dev); 276 phy = ieee802154_mlme_ops(dev)->get_phy(dev);
255 BUG_ON(!phy); 277 BUG_ON(!phy);
256 278
279 short_addr = ieee802154_mlme_ops(dev)->get_short_addr(dev);
280 pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev);
281
257 if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) || 282 if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
258 nla_put_string(msg, IEEE802154_ATTR_PHY_NAME, wpan_phy_name(phy)) || 283 nla_put_string(msg, IEEE802154_ATTR_PHY_NAME, wpan_phy_name(phy)) ||
259 nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) || 284 nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
260 nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, 285 nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN,
261 dev->dev_addr) || 286 dev->dev_addr) ||
262 nla_put_u16(msg, IEEE802154_ATTR_SHORT_ADDR, 287 nla_put_shortaddr(msg, IEEE802154_ATTR_SHORT_ADDR, short_addr) ||
263 ieee802154_mlme_ops(dev)->get_short_addr(dev)) || 288 nla_put_shortaddr(msg, IEEE802154_ATTR_PAN_ID, pan_id))
264 nla_put_u16(msg, IEEE802154_ATTR_PAN_ID,
265 ieee802154_mlme_ops(dev)->get_pan_id(dev)))
266 goto nla_put_failure; 289 goto nla_put_failure;
267 wpan_phy_put(phy); 290 wpan_phy_put(phy);
268 return genlmsg_end(msg, hdr); 291 return genlmsg_end(msg, hdr);
@@ -322,16 +345,16 @@ int ieee802154_associate_req(struct sk_buff *skb, struct genl_info *info)
322 goto out; 345 goto out;
323 346
324 if (info->attrs[IEEE802154_ATTR_COORD_HW_ADDR]) { 347 if (info->attrs[IEEE802154_ATTR_COORD_HW_ADDR]) {
325 addr.addr_type = IEEE802154_ADDR_LONG; 348 addr.mode = IEEE802154_ADDR_LONG;
326 nla_memcpy(addr.hwaddr, 349 addr.extended_addr = nla_get_hwaddr(
327 info->attrs[IEEE802154_ATTR_COORD_HW_ADDR], 350 info->attrs[IEEE802154_ATTR_COORD_HW_ADDR]);
328 IEEE802154_ADDR_LEN);
329 } else { 351 } else {
330 addr.addr_type = IEEE802154_ADDR_SHORT; 352 addr.mode = IEEE802154_ADDR_SHORT;
331 addr.short_addr = nla_get_u16( 353 addr.short_addr = nla_get_shortaddr(
332 info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR]); 354 info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR]);
333 } 355 }
334 addr.pan_id = nla_get_u16(info->attrs[IEEE802154_ATTR_COORD_PAN_ID]); 356 addr.pan_id = nla_get_shortaddr(
357 info->attrs[IEEE802154_ATTR_COORD_PAN_ID]);
335 358
336 if (info->attrs[IEEE802154_ATTR_PAGE]) 359 if (info->attrs[IEEE802154_ATTR_PAGE])
337 page = nla_get_u8(info->attrs[IEEE802154_ATTR_PAGE]); 360 page = nla_get_u8(info->attrs[IEEE802154_ATTR_PAGE]);
@@ -365,14 +388,13 @@ int ieee802154_associate_resp(struct sk_buff *skb, struct genl_info *info)
365 if (!ieee802154_mlme_ops(dev)->assoc_resp) 388 if (!ieee802154_mlme_ops(dev)->assoc_resp)
366 goto out; 389 goto out;
367 390
368 addr.addr_type = IEEE802154_ADDR_LONG; 391 addr.mode = IEEE802154_ADDR_LONG;
369 nla_memcpy(addr.hwaddr, info->attrs[IEEE802154_ATTR_DEST_HW_ADDR], 392 addr.extended_addr = nla_get_hwaddr(
370 IEEE802154_ADDR_LEN); 393 info->attrs[IEEE802154_ATTR_DEST_HW_ADDR]);
371 addr.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev); 394 addr.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev);
372 395
373
374 ret = ieee802154_mlme_ops(dev)->assoc_resp(dev, &addr, 396 ret = ieee802154_mlme_ops(dev)->assoc_resp(dev, &addr,
375 nla_get_u16(info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR]), 397 nla_get_shortaddr(info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR]),
376 nla_get_u8(info->attrs[IEEE802154_ATTR_STATUS])); 398 nla_get_u8(info->attrs[IEEE802154_ATTR_STATUS]));
377 399
378out: 400out:
@@ -398,13 +420,12 @@ int ieee802154_disassociate_req(struct sk_buff *skb, struct genl_info *info)
398 goto out; 420 goto out;
399 421
400 if (info->attrs[IEEE802154_ATTR_DEST_HW_ADDR]) { 422 if (info->attrs[IEEE802154_ATTR_DEST_HW_ADDR]) {
401 addr.addr_type = IEEE802154_ADDR_LONG; 423 addr.mode = IEEE802154_ADDR_LONG;
402 nla_memcpy(addr.hwaddr, 424 addr.extended_addr = nla_get_hwaddr(
403 info->attrs[IEEE802154_ATTR_DEST_HW_ADDR], 425 info->attrs[IEEE802154_ATTR_DEST_HW_ADDR]);
404 IEEE802154_ADDR_LEN);
405 } else { 426 } else {
406 addr.addr_type = IEEE802154_ADDR_SHORT; 427 addr.mode = IEEE802154_ADDR_SHORT;
407 addr.short_addr = nla_get_u16( 428 addr.short_addr = nla_get_shortaddr(
408 info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR]); 429 info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR]);
409 } 430 }
410 addr.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev); 431 addr.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev);
@@ -449,10 +470,11 @@ int ieee802154_start_req(struct sk_buff *skb, struct genl_info *info)
449 if (!ieee802154_mlme_ops(dev)->start_req) 470 if (!ieee802154_mlme_ops(dev)->start_req)
450 goto out; 471 goto out;
451 472
452 addr.addr_type = IEEE802154_ADDR_SHORT; 473 addr.mode = IEEE802154_ADDR_SHORT;
453 addr.short_addr = nla_get_u16( 474 addr.short_addr = nla_get_shortaddr(
454 info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR]); 475 info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR]);
455 addr.pan_id = nla_get_u16(info->attrs[IEEE802154_ATTR_COORD_PAN_ID]); 476 addr.pan_id = nla_get_shortaddr(
477 info->attrs[IEEE802154_ATTR_COORD_PAN_ID]);
456 478
457 channel = nla_get_u8(info->attrs[IEEE802154_ATTR_CHANNEL]); 479 channel = nla_get_u8(info->attrs[IEEE802154_ATTR_CHANNEL]);
458 bcn_ord = nla_get_u8(info->attrs[IEEE802154_ATTR_BCN_ORD]); 480 bcn_ord = nla_get_u8(info->attrs[IEEE802154_ATTR_BCN_ORD]);
@@ -467,7 +489,7 @@ int ieee802154_start_req(struct sk_buff *skb, struct genl_info *info)
467 page = 0; 489 page = 0;
468 490
469 491
470 if (addr.short_addr == IEEE802154_ADDR_BROADCAST) { 492 if (addr.short_addr == cpu_to_le16(IEEE802154_ADDR_BROADCAST)) {
471 ieee802154_nl_start_confirm(dev, IEEE802154_NO_SHORT_ADDRESS); 493 ieee802154_nl_start_confirm(dev, IEEE802154_NO_SHORT_ADDRESS);
472 dev_put(dev); 494 dev_put(dev);
473 return -EINVAL; 495 return -EINVAL;
diff --git a/net/ieee802154/raw.c b/net/ieee802154/raw.c
index 41f538b8e59c..e5258cf6773b 100644
--- a/net/ieee802154/raw.c
+++ b/net/ieee802154/raw.c
@@ -28,6 +28,7 @@
28#include <linux/slab.h> 28#include <linux/slab.h>
29#include <net/sock.h> 29#include <net/sock.h>
30#include <net/af_ieee802154.h> 30#include <net/af_ieee802154.h>
31#include <net/ieee802154_netdev.h>
31 32
32#include "af802154.h" 33#include "af802154.h"
33 34
@@ -55,21 +56,24 @@ static void raw_close(struct sock *sk, long timeout)
55 sk_common_release(sk); 56 sk_common_release(sk);
56} 57}
57 58
58static int raw_bind(struct sock *sk, struct sockaddr *uaddr, int len) 59static int raw_bind(struct sock *sk, struct sockaddr *_uaddr, int len)
59{ 60{
60 struct sockaddr_ieee802154 *addr = (struct sockaddr_ieee802154 *)uaddr; 61 struct ieee802154_addr addr;
62 struct sockaddr_ieee802154 *uaddr = (struct sockaddr_ieee802154 *)_uaddr;
61 int err = 0; 63 int err = 0;
62 struct net_device *dev = NULL; 64 struct net_device *dev = NULL;
63 65
64 if (len < sizeof(*addr)) 66 if (len < sizeof(*uaddr))
65 return -EINVAL; 67 return -EINVAL;
66 68
67 if (addr->family != AF_IEEE802154) 69 uaddr = (struct sockaddr_ieee802154 *)_uaddr;
70 if (uaddr->family != AF_IEEE802154)
68 return -EINVAL; 71 return -EINVAL;
69 72
70 lock_sock(sk); 73 lock_sock(sk);
71 74
72 dev = ieee802154_get_dev(sock_net(sk), &addr->addr); 75 ieee802154_addr_from_sa(&addr, &uaddr->addr);
76 dev = ieee802154_get_dev(sock_net(sk), &addr);
73 if (!dev) { 77 if (!dev) {
74 err = -ENODEV; 78 err = -ENODEV;
75 goto out; 79 goto out;
diff --git a/net/ieee802154/reassembly.c b/net/ieee802154/reassembly.c
index 1dae1991883d..ef2d54372b13 100644
--- a/net/ieee802154/reassembly.c
+++ b/net/ieee802154/reassembly.c
@@ -30,6 +30,17 @@
30 30
31#include "reassembly.h" 31#include "reassembly.h"
32 32
33struct lowpan_frag_info {
34 __be16 d_tag;
35 u16 d_size;
36 u8 d_offset;
37};
38
39struct lowpan_frag_info *lowpan_cb(struct sk_buff *skb)
40{
41 return (struct lowpan_frag_info *)skb->cb;
42}
43
33static struct inet_frags lowpan_frags; 44static struct inet_frags lowpan_frags;
34 45
35static int lowpan_frag_reasm(struct lowpan_frag_queue *fq, 46static int lowpan_frag_reasm(struct lowpan_frag_queue *fq,
@@ -65,8 +76,8 @@ static bool lowpan_frag_match(struct inet_frag_queue *q, void *a)
65 76
66 fq = container_of(q, struct lowpan_frag_queue, q); 77 fq = container_of(q, struct lowpan_frag_queue, q);
67 return fq->tag == arg->tag && fq->d_size == arg->d_size && 78 return fq->tag == arg->tag && fq->d_size == arg->d_size &&
68 ieee802154_addr_addr_equal(&fq->saddr, arg->src) && 79 ieee802154_addr_equal(&fq->saddr, arg->src) &&
69 ieee802154_addr_addr_equal(&fq->daddr, arg->dst); 80 ieee802154_addr_equal(&fq->daddr, arg->dst);
70} 81}
71 82
72static void lowpan_frag_init(struct inet_frag_queue *q, void *a) 83static void lowpan_frag_init(struct inet_frag_queue *q, void *a)
@@ -102,8 +113,9 @@ out:
102} 113}
103 114
104static inline struct lowpan_frag_queue * 115static inline struct lowpan_frag_queue *
105fq_find(struct net *net, const struct ieee802154_frag_info *frag_info, 116fq_find(struct net *net, const struct lowpan_frag_info *frag_info,
106 const struct ieee802154_addr *src, const struct ieee802154_addr *dst) 117 const struct ieee802154_addr *src,
118 const struct ieee802154_addr *dst)
107{ 119{
108 struct inet_frag_queue *q; 120 struct inet_frag_queue *q;
109 struct lowpan_create_arg arg; 121 struct lowpan_create_arg arg;
@@ -136,8 +148,8 @@ static int lowpan_frag_queue(struct lowpan_frag_queue *fq,
136 if (fq->q.last_in & INET_FRAG_COMPLETE) 148 if (fq->q.last_in & INET_FRAG_COMPLETE)
137 goto err; 149 goto err;
138 150
139 offset = mac_cb(skb)->frag_info.d_offset << 3; 151 offset = lowpan_cb(skb)->d_offset << 3;
140 end = mac_cb(skb)->frag_info.d_size; 152 end = lowpan_cb(skb)->d_size;
141 153
142 /* Is this the final fragment? */ 154 /* Is this the final fragment? */
143 if (offset + skb->len == end) { 155 if (offset + skb->len == end) {
@@ -163,15 +175,13 @@ static int lowpan_frag_queue(struct lowpan_frag_queue *fq,
163 * this fragment, right? 175 * this fragment, right?
164 */ 176 */
165 prev = fq->q.fragments_tail; 177 prev = fq->q.fragments_tail;
166 if (!prev || mac_cb(prev)->frag_info.d_offset < 178 if (!prev || lowpan_cb(prev)->d_offset < lowpan_cb(skb)->d_offset) {
167 mac_cb(skb)->frag_info.d_offset) {
168 next = NULL; 179 next = NULL;
169 goto found; 180 goto found;
170 } 181 }
171 prev = NULL; 182 prev = NULL;
172 for (next = fq->q.fragments; next != NULL; next = next->next) { 183 for (next = fq->q.fragments; next != NULL; next = next->next) {
173 if (mac_cb(next)->frag_info.d_offset >= 184 if (lowpan_cb(next)->d_offset >= lowpan_cb(skb)->d_offset)
174 mac_cb(skb)->frag_info.d_offset)
175 break; /* bingo! */ 185 break; /* bingo! */
176 prev = next; 186 prev = next;
177 } 187 }
@@ -318,7 +328,7 @@ out_oom:
318} 328}
319 329
320static int lowpan_get_frag_info(struct sk_buff *skb, const u8 frag_type, 330static int lowpan_get_frag_info(struct sk_buff *skb, const u8 frag_type,
321 struct ieee802154_frag_info *frag_info) 331 struct lowpan_frag_info *frag_info)
322{ 332{
323 bool fail; 333 bool fail;
324 u8 pattern = 0, low = 0; 334 u8 pattern = 0, low = 0;
@@ -345,9 +355,13 @@ int lowpan_frag_rcv(struct sk_buff *skb, const u8 frag_type)
345{ 355{
346 struct lowpan_frag_queue *fq; 356 struct lowpan_frag_queue *fq;
347 struct net *net = dev_net(skb->dev); 357 struct net *net = dev_net(skb->dev);
348 struct ieee802154_frag_info *frag_info = &mac_cb(skb)->frag_info; 358 struct lowpan_frag_info *frag_info = lowpan_cb(skb);
359 struct ieee802154_addr source, dest;
349 int err; 360 int err;
350 361
362 source = mac_cb(skb)->source;
363 dest = mac_cb(skb)->dest;
364
351 err = lowpan_get_frag_info(skb, frag_type, frag_info); 365 err = lowpan_get_frag_info(skb, frag_type, frag_info);
352 if (err < 0) 366 if (err < 0)
353 goto err; 367 goto err;
@@ -357,7 +371,7 @@ int lowpan_frag_rcv(struct sk_buff *skb, const u8 frag_type)
357 371
358 inet_frag_evictor(&net->ieee802154_lowpan.frags, &lowpan_frags, false); 372 inet_frag_evictor(&net->ieee802154_lowpan.frags, &lowpan_frags, false);
359 373
360 fq = fq_find(net, frag_info, &mac_cb(skb)->sa, &mac_cb(skb)->da); 374 fq = fq_find(net, frag_info, &source, &dest);
361 if (fq != NULL) { 375 if (fq != NULL) {
362 int ret; 376 int ret;
363 spin_lock(&fq->q.lock); 377 spin_lock(&fq->q.lock);
diff --git a/net/ieee802154/reassembly.h b/net/ieee802154/reassembly.h
index 055518b9da2d..74e4a7c98191 100644
--- a/net/ieee802154/reassembly.h
+++ b/net/ieee802154/reassembly.h
@@ -23,10 +23,10 @@ struct lowpan_frag_queue {
23 23
24static inline u32 ieee802154_addr_hash(const struct ieee802154_addr *a) 24static inline u32 ieee802154_addr_hash(const struct ieee802154_addr *a)
25{ 25{
26 switch (a->addr_type) { 26 switch (a->mode) {
27 case IEEE802154_ADDR_LONG: 27 case IEEE802154_ADDR_LONG:
28 return (__force u32)((((u32 *)a->hwaddr))[0] ^ 28 return (((__force u64)a->extended_addr) >> 32) ^
29 ((u32 *)(a->hwaddr))[1]); 29 (((__force u64)a->extended_addr) & 0xffffffff);
30 case IEEE802154_ADDR_SHORT: 30 case IEEE802154_ADDR_SHORT:
31 return (__force u32)(a->short_addr); 31 return (__force u32)(a->short_addr);
32 default: 32 default:
@@ -34,31 +34,6 @@ static inline u32 ieee802154_addr_hash(const struct ieee802154_addr *a)
34 } 34 }
35} 35}
36 36
37static inline bool ieee802154_addr_addr_equal(const struct ieee802154_addr *a1,
38 const struct ieee802154_addr *a2)
39{
40 if (a1->pan_id != a2->pan_id)
41 return false;
42
43 if (a1->addr_type != a2->addr_type)
44 return false;
45
46 switch (a1->addr_type) {
47 case IEEE802154_ADDR_LONG:
48 if (memcmp(a1->hwaddr, a2->hwaddr, IEEE802154_ADDR_LEN))
49 return false;
50 break;
51 case IEEE802154_ADDR_SHORT:
52 if (a1->short_addr != a2->short_addr)
53 return false;
54 break;
55 default:
56 return false;
57 }
58
59 return true;
60}
61
62int lowpan_frag_rcv(struct sk_buff *skb, const u8 frag_type); 37int lowpan_frag_rcv(struct sk_buff *skb, const u8 frag_type);
63void lowpan_net_frag_exit(void); 38void lowpan_net_frag_exit(void);
64int lowpan_net_frag_init(void); 39int lowpan_net_frag_init(void);
diff --git a/net/mac802154/Makefile b/net/mac802154/Makefile
index 57cf5d1a2e4a..15d62df52182 100644
--- a/net/mac802154/Makefile
+++ b/net/mac802154/Makefile
@@ -1,2 +1,4 @@
1obj-$(CONFIG_MAC802154) += mac802154.o 1obj-$(CONFIG_MAC802154) += mac802154.o
2mac802154-objs := ieee802154_dev.o rx.o tx.o mac_cmd.o mib.o monitor.o wpan.o 2mac802154-objs := ieee802154_dev.o rx.o tx.o mac_cmd.o mib.o monitor.o wpan.o
3
4ccflags-y += -D__CHECK_ENDIAN__
diff --git a/net/mac802154/ieee802154_dev.c b/net/mac802154/ieee802154_dev.c
index b75bb01e5c6b..10cdb091b775 100644
--- a/net/mac802154/ieee802154_dev.c
+++ b/net/mac802154/ieee802154_dev.c
@@ -27,6 +27,7 @@
27#include <net/netlink.h> 27#include <net/netlink.h>
28#include <linux/nl802154.h> 28#include <linux/nl802154.h>
29#include <net/mac802154.h> 29#include <net/mac802154.h>
30#include <net/ieee802154_netdev.h>
30#include <net/route.h> 31#include <net/route.h>
31#include <net/wpan-phy.h> 32#include <net/wpan-phy.h>
32 33
@@ -46,7 +47,9 @@ int mac802154_slave_open(struct net_device *dev)
46 } 47 }
47 48
48 if (ipriv->ops->ieee_addr) { 49 if (ipriv->ops->ieee_addr) {
49 res = ipriv->ops->ieee_addr(&ipriv->hw, dev->dev_addr); 50 __le64 addr = ieee802154_devaddr_from_raw(dev->dev_addr);
51
52 res = ipriv->ops->ieee_addr(&ipriv->hw, addr);
50 WARN_ON(res); 53 WARN_ON(res);
51 if (res) 54 if (res)
52 goto err; 55 goto err;
diff --git a/net/mac802154/mac802154.h b/net/mac802154/mac802154.h
index d48422e27110..4619486f1da2 100644
--- a/net/mac802154/mac802154.h
+++ b/net/mac802154/mac802154.h
@@ -76,6 +76,7 @@ struct mac802154_sub_if_data {
76 76
77 __le16 pan_id; 77 __le16 pan_id;
78 __le16 short_addr; 78 __le16 short_addr;
79 __le64 extended_addr;
79 80
80 u8 chan; 81 u8 chan;
81 u8 page; 82 u8 page;
@@ -106,11 +107,11 @@ netdev_tx_t mac802154_tx(struct mac802154_priv *priv, struct sk_buff *skb,
106 u8 page, u8 chan); 107 u8 page, u8 chan);
107 108
108/* MIB callbacks */ 109/* MIB callbacks */
109void mac802154_dev_set_short_addr(struct net_device *dev, u16 val); 110void mac802154_dev_set_short_addr(struct net_device *dev, __le16 val);
110u16 mac802154_dev_get_short_addr(const struct net_device *dev); 111__le16 mac802154_dev_get_short_addr(const struct net_device *dev);
111void mac802154_dev_set_ieee_addr(struct net_device *dev); 112void mac802154_dev_set_ieee_addr(struct net_device *dev);
112u16 mac802154_dev_get_pan_id(const struct net_device *dev); 113__le16 mac802154_dev_get_pan_id(const struct net_device *dev);
113void mac802154_dev_set_pan_id(struct net_device *dev, u16 val); 114void mac802154_dev_set_pan_id(struct net_device *dev, __le16 val);
114void mac802154_dev_set_page_channel(struct net_device *dev, u8 page, u8 chan); 115void mac802154_dev_set_page_channel(struct net_device *dev, u8 page, u8 chan);
115u8 mac802154_dev_get_dsn(const struct net_device *dev); 116u8 mac802154_dev_get_dsn(const struct net_device *dev);
116 117
diff --git a/net/mac802154/mac_cmd.c b/net/mac802154/mac_cmd.c
index a99910d4d52f..15bac3358889 100644
--- a/net/mac802154/mac_cmd.c
+++ b/net/mac802154/mac_cmd.c
@@ -40,7 +40,7 @@ static int mac802154_mlme_start_req(struct net_device *dev,
40 u8 pan_coord, u8 blx, 40 u8 pan_coord, u8 blx,
41 u8 coord_realign) 41 u8 coord_realign)
42{ 42{
43 BUG_ON(addr->addr_type != IEEE802154_ADDR_SHORT); 43 BUG_ON(addr->mode != IEEE802154_ADDR_SHORT);
44 44
45 mac802154_dev_set_pan_id(dev, addr->pan_id); 45 mac802154_dev_set_pan_id(dev, addr->pan_id);
46 mac802154_dev_set_short_addr(dev, addr->short_addr); 46 mac802154_dev_set_short_addr(dev, addr->short_addr);
diff --git a/net/mac802154/mib.c b/net/mac802154/mib.c
index f48f40c1da1a..153bd1ddbfbb 100644
--- a/net/mac802154/mib.c
+++ b/net/mac802154/mib.c
@@ -24,7 +24,9 @@
24#include <linux/if_arp.h> 24#include <linux/if_arp.h>
25 25
26#include <net/mac802154.h> 26#include <net/mac802154.h>
27#include <net/ieee802154_netdev.h>
27#include <net/wpan-phy.h> 28#include <net/wpan-phy.h>
29#include <net/ieee802154_netdev.h>
28 30
29#include "mac802154.h" 31#include "mac802154.h"
30 32
@@ -79,7 +81,7 @@ static void set_hw_addr_filt(struct net_device *dev, unsigned long changed)
79 queue_work(priv->hw->dev_workqueue, &work->work); 81 queue_work(priv->hw->dev_workqueue, &work->work);
80} 82}
81 83
82void mac802154_dev_set_short_addr(struct net_device *dev, u16 val) 84void mac802154_dev_set_short_addr(struct net_device *dev, __le16 val)
83{ 85{
84 struct mac802154_sub_if_data *priv = netdev_priv(dev); 86 struct mac802154_sub_if_data *priv = netdev_priv(dev);
85 87
@@ -96,10 +98,10 @@ void mac802154_dev_set_short_addr(struct net_device *dev, u16 val)
96 } 98 }
97} 99}
98 100
99u16 mac802154_dev_get_short_addr(const struct net_device *dev) 101__le16 mac802154_dev_get_short_addr(const struct net_device *dev)
100{ 102{
101 struct mac802154_sub_if_data *priv = netdev_priv(dev); 103 struct mac802154_sub_if_data *priv = netdev_priv(dev);
102 u16 ret; 104 __le16 ret;
103 105
104 BUG_ON(dev->type != ARPHRD_IEEE802154); 106 BUG_ON(dev->type != ARPHRD_IEEE802154);
105 107
@@ -115,19 +117,19 @@ void mac802154_dev_set_ieee_addr(struct net_device *dev)
115 struct mac802154_sub_if_data *priv = netdev_priv(dev); 117 struct mac802154_sub_if_data *priv = netdev_priv(dev);
116 struct mac802154_priv *mac = priv->hw; 118 struct mac802154_priv *mac = priv->hw;
117 119
120 priv->extended_addr = ieee802154_devaddr_from_raw(dev->dev_addr);
121
118 if (mac->ops->set_hw_addr_filt && 122 if (mac->ops->set_hw_addr_filt &&
119 memcmp(mac->hw.hw_filt.ieee_addr, 123 mac->hw.hw_filt.ieee_addr != priv->extended_addr) {
120 dev->dev_addr, IEEE802154_ADDR_LEN)) { 124 mac->hw.hw_filt.ieee_addr = priv->extended_addr;
121 memcpy(mac->hw.hw_filt.ieee_addr,
122 dev->dev_addr, IEEE802154_ADDR_LEN);
123 set_hw_addr_filt(dev, IEEE802515_AFILT_IEEEADDR_CHANGED); 125 set_hw_addr_filt(dev, IEEE802515_AFILT_IEEEADDR_CHANGED);
124 } 126 }
125} 127}
126 128
127u16 mac802154_dev_get_pan_id(const struct net_device *dev) 129__le16 mac802154_dev_get_pan_id(const struct net_device *dev)
128{ 130{
129 struct mac802154_sub_if_data *priv = netdev_priv(dev); 131 struct mac802154_sub_if_data *priv = netdev_priv(dev);
130 u16 ret; 132 __le16 ret;
131 133
132 BUG_ON(dev->type != ARPHRD_IEEE802154); 134 BUG_ON(dev->type != ARPHRD_IEEE802154);
133 135
@@ -138,7 +140,7 @@ u16 mac802154_dev_get_pan_id(const struct net_device *dev)
138 return ret; 140 return ret;
139} 141}
140 142
141void mac802154_dev_set_pan_id(struct net_device *dev, u16 val) 143void mac802154_dev_set_pan_id(struct net_device *dev, __le16 val)
142{ 144{
143 struct mac802154_sub_if_data *priv = netdev_priv(dev); 145 struct mac802154_sub_if_data *priv = netdev_priv(dev);
144 146
diff --git a/net/mac802154/wpan.c b/net/mac802154/wpan.c
index 372d8a222b91..80cbee1a2f56 100644
--- a/net/mac802154/wpan.c
+++ b/net/mac802154/wpan.c
@@ -35,35 +35,6 @@
35 35
36#include "mac802154.h" 36#include "mac802154.h"
37 37
38static inline int mac802154_fetch_skb_u8(struct sk_buff *skb, u8 *val)
39{
40 if (unlikely(!pskb_may_pull(skb, 1)))
41 return -EINVAL;
42
43 *val = skb->data[0];
44 skb_pull(skb, 1);
45
46 return 0;
47}
48
49static inline int mac802154_fetch_skb_u16(struct sk_buff *skb, u16 *val)
50{
51 if (unlikely(!pskb_may_pull(skb, 2)))
52 return -EINVAL;
53
54 *val = skb->data[0] | (skb->data[1] << 8);
55 skb_pull(skb, 2);
56
57 return 0;
58}
59
60static inline void mac802154_haddr_copy_swap(u8 *dest, const u8 *src)
61{
62 int i;
63 for (i = 0; i < IEEE802154_ADDR_LEN; i++)
64 dest[IEEE802154_ADDR_LEN - i - 1] = src[i];
65}
66
67static int 38static int
68mac802154_wpan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) 39mac802154_wpan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
69{ 40{
@@ -76,19 +47,25 @@ mac802154_wpan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
76 47
77 switch (cmd) { 48 switch (cmd) {
78 case SIOCGIFADDR: 49 case SIOCGIFADDR:
79 if (priv->pan_id == IEEE802154_PANID_BROADCAST || 50 {
80 priv->short_addr == IEEE802154_ADDR_BROADCAST) { 51 u16 pan_id, short_addr;
52
53 pan_id = le16_to_cpu(priv->pan_id);
54 short_addr = le16_to_cpu(priv->short_addr);
55 if (pan_id == IEEE802154_PANID_BROADCAST ||
56 short_addr == IEEE802154_ADDR_BROADCAST) {
81 err = -EADDRNOTAVAIL; 57 err = -EADDRNOTAVAIL;
82 break; 58 break;
83 } 59 }
84 60
85 sa->family = AF_IEEE802154; 61 sa->family = AF_IEEE802154;
86 sa->addr.addr_type = IEEE802154_ADDR_SHORT; 62 sa->addr.addr_type = IEEE802154_ADDR_SHORT;
87 sa->addr.pan_id = priv->pan_id; 63 sa->addr.pan_id = pan_id;
88 sa->addr.short_addr = priv->short_addr; 64 sa->addr.short_addr = short_addr;
89 65
90 err = 0; 66 err = 0;
91 break; 67 break;
68 }
92 case SIOCSIFADDR: 69 case SIOCSIFADDR:
93 dev_warn(&dev->dev, 70 dev_warn(&dev->dev,
94 "Using DEBUGing ioctl SIOCSIFADDR isn't recommened!\n"); 71 "Using DEBUGing ioctl SIOCSIFADDR isn't recommened!\n");
@@ -101,8 +78,8 @@ mac802154_wpan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
101 break; 78 break;
102 } 79 }
103 80
104 priv->pan_id = sa->addr.pan_id; 81 priv->pan_id = cpu_to_le16(sa->addr.pan_id);
105 priv->short_addr = sa->addr.short_addr; 82 priv->short_addr = cpu_to_le16(sa->addr.short_addr);
106 83
107 err = 0; 84 err = 0;
108 break; 85 break;
@@ -128,187 +105,70 @@ static int mac802154_wpan_mac_addr(struct net_device *dev, void *p)
128static int mac802154_header_create(struct sk_buff *skb, 105static int mac802154_header_create(struct sk_buff *skb,
129 struct net_device *dev, 106 struct net_device *dev,
130 unsigned short type, 107 unsigned short type,
131 const void *_daddr, 108 const void *daddr,
132 const void *_saddr, 109 const void *saddr,
133 unsigned len) 110 unsigned len)
134{ 111{
135 const struct ieee802154_addr *saddr = _saddr; 112 struct ieee802154_hdr hdr;
136 const struct ieee802154_addr *daddr = _daddr;
137 struct ieee802154_addr dev_addr;
138 struct mac802154_sub_if_data *priv = netdev_priv(dev); 113 struct mac802154_sub_if_data *priv = netdev_priv(dev);
139 int pos = 2; 114 int hlen;
140 u8 head[MAC802154_FRAME_HARD_HEADER_LEN];
141 u16 fc;
142 115
143 if (!daddr) 116 if (!daddr)
144 return -EINVAL; 117 return -EINVAL;
145 118
146 head[pos++] = mac_cb(skb)->seq; /* DSN/BSN */ 119 memset(&hdr.fc, 0, sizeof(hdr.fc));
147 fc = mac_cb_type(skb); 120 hdr.fc.type = mac_cb_type(skb);
148 if (mac_cb_is_ackreq(skb)) 121 hdr.fc.security_enabled = mac_cb_is_secen(skb);
149 fc |= IEEE802154_FC_ACK_REQ; 122 hdr.fc.ack_request = mac_cb_is_ackreq(skb);
150 123
151 if (!saddr) { 124 if (!saddr) {
152 spin_lock_bh(&priv->mib_lock); 125 spin_lock_bh(&priv->mib_lock);
153 126
154 if (priv->short_addr == IEEE802154_ADDR_BROADCAST || 127 if (priv->short_addr == cpu_to_le16(IEEE802154_ADDR_BROADCAST) ||
155 priv->short_addr == IEEE802154_ADDR_UNDEF || 128 priv->short_addr == cpu_to_le16(IEEE802154_ADDR_UNDEF) ||
156 priv->pan_id == IEEE802154_PANID_BROADCAST) { 129 priv->pan_id == cpu_to_le16(IEEE802154_PANID_BROADCAST)) {
157 dev_addr.addr_type = IEEE802154_ADDR_LONG; 130 hdr.source.mode = IEEE802154_ADDR_LONG;
158 memcpy(dev_addr.hwaddr, dev->dev_addr, 131 hdr.source.extended_addr = priv->extended_addr;
159 IEEE802154_ADDR_LEN);
160 } else { 132 } else {
161 dev_addr.addr_type = IEEE802154_ADDR_SHORT; 133 hdr.source.mode = IEEE802154_ADDR_SHORT;
162 dev_addr.short_addr = priv->short_addr; 134 hdr.source.short_addr = priv->short_addr;
163 } 135 }
164 136
165 dev_addr.pan_id = priv->pan_id; 137 hdr.source.pan_id = priv->pan_id;
166 saddr = &dev_addr;
167 138
168 spin_unlock_bh(&priv->mib_lock); 139 spin_unlock_bh(&priv->mib_lock);
140 } else {
141 hdr.source = *(const struct ieee802154_addr *)saddr;
169 } 142 }
170 143
171 if (daddr->addr_type != IEEE802154_ADDR_NONE) { 144 hdr.dest = *(const struct ieee802154_addr *)daddr;
172 fc |= (daddr->addr_type << IEEE802154_FC_DAMODE_SHIFT);
173
174 head[pos++] = daddr->pan_id & 0xff;
175 head[pos++] = daddr->pan_id >> 8;
176
177 if (daddr->addr_type == IEEE802154_ADDR_SHORT) {
178 head[pos++] = daddr->short_addr & 0xff;
179 head[pos++] = daddr->short_addr >> 8;
180 } else {
181 mac802154_haddr_copy_swap(head + pos, daddr->hwaddr);
182 pos += IEEE802154_ADDR_LEN;
183 }
184 }
185
186 if (saddr->addr_type != IEEE802154_ADDR_NONE) {
187 fc |= (saddr->addr_type << IEEE802154_FC_SAMODE_SHIFT);
188
189 if ((saddr->pan_id == daddr->pan_id) &&
190 (saddr->pan_id != IEEE802154_PANID_BROADCAST)) {
191 /* PANID compression/intra PAN */
192 fc |= IEEE802154_FC_INTRA_PAN;
193 } else {
194 head[pos++] = saddr->pan_id & 0xff;
195 head[pos++] = saddr->pan_id >> 8;
196 }
197
198 if (saddr->addr_type == IEEE802154_ADDR_SHORT) {
199 head[pos++] = saddr->short_addr & 0xff;
200 head[pos++] = saddr->short_addr >> 8;
201 } else {
202 mac802154_haddr_copy_swap(head + pos, saddr->hwaddr);
203 pos += IEEE802154_ADDR_LEN;
204 }
205 }
206 145
207 head[0] = fc; 146 hlen = ieee802154_hdr_push(skb, &hdr);
208 head[1] = fc >> 8; 147 if (hlen < 0)
148 return -EINVAL;
209 149
210 memcpy(skb_push(skb, pos), head, pos);
211 skb_reset_mac_header(skb); 150 skb_reset_mac_header(skb);
212 skb->mac_len = pos; 151 skb->mac_len = hlen;
152
153 if (hlen + len + 2 > dev->mtu)
154 return -EMSGSIZE;
213 155
214 return pos; 156 return hlen;
215} 157}
216 158
217static int 159static int
218mac802154_header_parse(const struct sk_buff *skb, unsigned char *haddr) 160mac802154_header_parse(const struct sk_buff *skb, unsigned char *haddr)
219{ 161{
220 const u8 *hdr = skb_mac_header(skb); 162 struct ieee802154_hdr hdr;
221 const u8 *tail = skb_tail_pointer(skb);
222 struct ieee802154_addr *addr = (struct ieee802154_addr *)haddr; 163 struct ieee802154_addr *addr = (struct ieee802154_addr *)haddr;
223 u16 fc;
224 int da_type;
225
226 if (hdr + 3 > tail)
227 goto malformed;
228
229 fc = hdr[0] | (hdr[1] << 8);
230
231 hdr += 3;
232
233 da_type = IEEE802154_FC_DAMODE(fc);
234 addr->addr_type = IEEE802154_FC_SAMODE(fc);
235
236 switch (da_type) {
237 case IEEE802154_ADDR_NONE:
238 if (fc & IEEE802154_FC_INTRA_PAN)
239 goto malformed;
240 break;
241 case IEEE802154_ADDR_LONG:
242 if (fc & IEEE802154_FC_INTRA_PAN) {
243 if (hdr + 2 > tail)
244 goto malformed;
245 addr->pan_id = hdr[0] | (hdr[1] << 8);
246 hdr += 2;
247 }
248
249 if (hdr + IEEE802154_ADDR_LEN > tail)
250 goto malformed;
251
252 hdr += IEEE802154_ADDR_LEN;
253 break;
254 case IEEE802154_ADDR_SHORT:
255 if (fc & IEEE802154_FC_INTRA_PAN) {
256 if (hdr + 2 > tail)
257 goto malformed;
258 addr->pan_id = hdr[0] | (hdr[1] << 8);
259 hdr += 2;
260 }
261
262 if (hdr + 2 > tail)
263 goto malformed;
264
265 hdr += 2;
266 break;
267 default:
268 goto malformed;
269 164
165 if (ieee802154_hdr_peek_addrs(skb, &hdr) < 0) {
166 pr_debug("malformed packet\n");
167 return 0;
270 } 168 }
271 169
272 switch (addr->addr_type) { 170 *addr = hdr.source;
273 case IEEE802154_ADDR_NONE: 171 return sizeof(*addr);
274 break;
275 case IEEE802154_ADDR_LONG:
276 if (!(fc & IEEE802154_FC_INTRA_PAN)) {
277 if (hdr + 2 > tail)
278 goto malformed;
279 addr->pan_id = hdr[0] | (hdr[1] << 8);
280 hdr += 2;
281 }
282
283 if (hdr + IEEE802154_ADDR_LEN > tail)
284 goto malformed;
285
286 mac802154_haddr_copy_swap(addr->hwaddr, hdr);
287 hdr += IEEE802154_ADDR_LEN;
288 break;
289 case IEEE802154_ADDR_SHORT:
290 if (!(fc & IEEE802154_FC_INTRA_PAN)) {
291 if (hdr + 2 > tail)
292 goto malformed;
293 addr->pan_id = hdr[0] | (hdr[1] << 8);
294 hdr += 2;
295 }
296
297 if (hdr + 2 > tail)
298 goto malformed;
299
300 addr->short_addr = hdr[0] | (hdr[1] << 8);
301 hdr += 2;
302 break;
303 default:
304 goto malformed;
305 }
306
307 return sizeof(struct ieee802154_addr);
308
309malformed:
310 pr_debug("malformed packet\n");
311 return 0;
312} 172}
313 173
314static netdev_tx_t 174static netdev_tx_t
@@ -382,8 +242,8 @@ void mac802154_wpan_setup(struct net_device *dev)
382 get_random_bytes(&priv->bsn, 1); 242 get_random_bytes(&priv->bsn, 1);
383 get_random_bytes(&priv->dsn, 1); 243 get_random_bytes(&priv->dsn, 1);
384 244
385 priv->pan_id = IEEE802154_PANID_BROADCAST; 245 priv->pan_id = cpu_to_le16(IEEE802154_PANID_BROADCAST);
386 priv->short_addr = IEEE802154_ADDR_BROADCAST; 246 priv->short_addr = cpu_to_le16(IEEE802154_ADDR_BROADCAST);
387} 247}
388 248
389static int mac802154_process_data(struct net_device *dev, struct sk_buff *skb) 249static int mac802154_process_data(struct net_device *dev, struct sk_buff *skb)
@@ -394,13 +254,18 @@ static int mac802154_process_data(struct net_device *dev, struct sk_buff *skb)
394static int 254static int
395mac802154_subif_frame(struct mac802154_sub_if_data *sdata, struct sk_buff *skb) 255mac802154_subif_frame(struct mac802154_sub_if_data *sdata, struct sk_buff *skb)
396{ 256{
257 __le16 span, sshort;
258
397 pr_debug("getting packet via slave interface %s\n", sdata->dev->name); 259 pr_debug("getting packet via slave interface %s\n", sdata->dev->name);
398 260
399 spin_lock_bh(&sdata->mib_lock); 261 spin_lock_bh(&sdata->mib_lock);
400 262
401 switch (mac_cb(skb)->da.addr_type) { 263 span = sdata->pan_id;
264 sshort = sdata->short_addr;
265
266 switch (mac_cb(skb)->dest.mode) {
402 case IEEE802154_ADDR_NONE: 267 case IEEE802154_ADDR_NONE:
403 if (mac_cb(skb)->sa.addr_type != IEEE802154_ADDR_NONE) 268 if (mac_cb(skb)->dest.mode != IEEE802154_ADDR_NONE)
404 /* FIXME: check if we are PAN coordinator */ 269 /* FIXME: check if we are PAN coordinator */
405 skb->pkt_type = PACKET_OTHERHOST; 270 skb->pkt_type = PACKET_OTHERHOST;
406 else 271 else
@@ -408,23 +273,22 @@ mac802154_subif_frame(struct mac802154_sub_if_data *sdata, struct sk_buff *skb)
408 skb->pkt_type = PACKET_HOST; 273 skb->pkt_type = PACKET_HOST;
409 break; 274 break;
410 case IEEE802154_ADDR_LONG: 275 case IEEE802154_ADDR_LONG:
411 if (mac_cb(skb)->da.pan_id != sdata->pan_id && 276 if (mac_cb(skb)->dest.pan_id != span &&
412 mac_cb(skb)->da.pan_id != IEEE802154_PANID_BROADCAST) 277 mac_cb(skb)->dest.pan_id != cpu_to_le16(IEEE802154_PANID_BROADCAST))
413 skb->pkt_type = PACKET_OTHERHOST; 278 skb->pkt_type = PACKET_OTHERHOST;
414 else if (!memcmp(mac_cb(skb)->da.hwaddr, sdata->dev->dev_addr, 279 else if (mac_cb(skb)->dest.extended_addr == sdata->extended_addr)
415 IEEE802154_ADDR_LEN))
416 skb->pkt_type = PACKET_HOST; 280 skb->pkt_type = PACKET_HOST;
417 else 281 else
418 skb->pkt_type = PACKET_OTHERHOST; 282 skb->pkt_type = PACKET_OTHERHOST;
419 break; 283 break;
420 case IEEE802154_ADDR_SHORT: 284 case IEEE802154_ADDR_SHORT:
421 if (mac_cb(skb)->da.pan_id != sdata->pan_id && 285 if (mac_cb(skb)->dest.pan_id != span &&
422 mac_cb(skb)->da.pan_id != IEEE802154_PANID_BROADCAST) 286 mac_cb(skb)->dest.pan_id != cpu_to_le16(IEEE802154_PANID_BROADCAST))
423 skb->pkt_type = PACKET_OTHERHOST; 287 skb->pkt_type = PACKET_OTHERHOST;
424 else if (mac_cb(skb)->da.short_addr == sdata->short_addr) 288 else if (mac_cb(skb)->dest.short_addr == sshort)
425 skb->pkt_type = PACKET_HOST; 289 skb->pkt_type = PACKET_HOST;
426 else if (mac_cb(skb)->da.short_addr == 290 else if (mac_cb(skb)->dest.short_addr ==
427 IEEE802154_ADDR_BROADCAST) 291 cpu_to_le16(IEEE802154_ADDR_BROADCAST))
428 skb->pkt_type = PACKET_BROADCAST; 292 skb->pkt_type = PACKET_BROADCAST;
429 else 293 else
430 skb->pkt_type = PACKET_OTHERHOST; 294 skb->pkt_type = PACKET_OTHERHOST;
@@ -451,88 +315,82 @@ mac802154_subif_frame(struct mac802154_sub_if_data *sdata, struct sk_buff *skb)
451 } 315 }
452} 316}
453 317
454static int mac802154_parse_frame_start(struct sk_buff *skb) 318static void mac802154_print_addr(const char *name,
319 const struct ieee802154_addr *addr)
455{ 320{
456 u8 *head = skb->data; 321 if (addr->mode == IEEE802154_ADDR_NONE)
457 u16 fc; 322 pr_debug("%s not present\n", name);
458 323
459 if (mac802154_fetch_skb_u16(skb, &fc) || 324 pr_debug("%s PAN ID: %04x\n", name, le16_to_cpu(addr->pan_id));
460 mac802154_fetch_skb_u8(skb, &(mac_cb(skb)->seq))) 325 if (addr->mode == IEEE802154_ADDR_SHORT) {
461 goto err; 326 pr_debug("%s is short: %04x\n", name,
327 le16_to_cpu(addr->short_addr));
328 } else {
329 u64 hw = swab64((__force u64) addr->extended_addr);
462 330
463 pr_debug("fc: %04x dsn: %02x\n", fc, head[2]); 331 pr_debug("%s is hardware: %8phC\n", name, &hw);
464 332 }
465 mac_cb(skb)->flags = IEEE802154_FC_TYPE(fc); 333}
466 mac_cb(skb)->sa.addr_type = IEEE802154_FC_SAMODE(fc);
467 mac_cb(skb)->da.addr_type = IEEE802154_FC_DAMODE(fc);
468 334
469 if (fc & IEEE802154_FC_INTRA_PAN) 335static int mac802154_parse_frame_start(struct sk_buff *skb)
470 mac_cb(skb)->flags |= MAC_CB_FLAG_INTRAPAN; 336{
337 int hlen;
338 struct ieee802154_hdr hdr;
471 339
472 if (mac_cb(skb)->da.addr_type != IEEE802154_ADDR_NONE) { 340 hlen = ieee802154_hdr_pull(skb, &hdr);
473 if (mac802154_fetch_skb_u16(skb, &(mac_cb(skb)->da.pan_id))) 341 if (hlen < 0)
474 goto err; 342 return -EINVAL;
475 343
476 /* source PAN id compression */ 344 skb->mac_len = hlen;
477 if (mac_cb_is_intrapan(skb))
478 mac_cb(skb)->sa.pan_id = mac_cb(skb)->da.pan_id;
479 345
480 pr_debug("dest PAN addr: %04x\n", mac_cb(skb)->da.pan_id); 346 pr_debug("fc: %04x dsn: %02x\n", le16_to_cpup((__le16 *)&hdr.fc),
347 hdr.seq);
481 348
482 if (mac_cb(skb)->da.addr_type == IEEE802154_ADDR_SHORT) { 349 mac_cb(skb)->flags = hdr.fc.type;
483 u16 *da = &(mac_cb(skb)->da.short_addr);
484 350
485 if (mac802154_fetch_skb_u16(skb, da)) 351 if (hdr.fc.ack_request)
486 goto err; 352 mac_cb(skb)->flags |= MAC_CB_FLAG_ACKREQ;
353 if (hdr.fc.security_enabled)
354 mac_cb(skb)->flags |= MAC_CB_FLAG_SECEN;
487 355
488 pr_debug("destination address is short: %04x\n", 356 mac802154_print_addr("destination", &hdr.dest);
489 mac_cb(skb)->da.short_addr); 357 mac802154_print_addr("source", &hdr.source);
490 } else {
491 if (!pskb_may_pull(skb, IEEE802154_ADDR_LEN))
492 goto err;
493 358
494 mac802154_haddr_copy_swap(mac_cb(skb)->da.hwaddr, 359 mac_cb(skb)->source = hdr.source;
495 skb->data); 360 mac_cb(skb)->dest = hdr.dest;
496 skb_pull(skb, IEEE802154_ADDR_LEN);
497 361
498 pr_debug("destination address is hardware\n"); 362 if (hdr.fc.security_enabled) {
499 } 363 u64 key;
500 }
501 364
502 if (mac_cb(skb)->sa.addr_type != IEEE802154_ADDR_NONE) { 365 pr_debug("seclevel %i\n", hdr.sec.level);
503 /* non PAN-compression, fetch source address id */
504 if (!(mac_cb_is_intrapan(skb))) {
505 u16 *sa_pan = &(mac_cb(skb)->sa.pan_id);
506 366
507 if (mac802154_fetch_skb_u16(skb, sa_pan)) 367 switch (hdr.sec.key_id_mode) {
508 goto err; 368 case IEEE802154_SCF_KEY_IMPLICIT:
509 } 369 pr_debug("implicit key\n");
510 370 break;
511 pr_debug("source PAN addr: %04x\n", mac_cb(skb)->da.pan_id);
512
513 if (mac_cb(skb)->sa.addr_type == IEEE802154_ADDR_SHORT) {
514 u16 *sa = &(mac_cb(skb)->sa.short_addr);
515
516 if (mac802154_fetch_skb_u16(skb, sa))
517 goto err;
518 371
519 pr_debug("source address is short: %04x\n", 372 case IEEE802154_SCF_KEY_INDEX:
520 mac_cb(skb)->sa.short_addr); 373 pr_debug("key %02x\n", hdr.sec.key_id);
521 } else { 374 break;
522 if (!pskb_may_pull(skb, IEEE802154_ADDR_LEN))
523 goto err;
524 375
525 mac802154_haddr_copy_swap(mac_cb(skb)->sa.hwaddr, 376 case IEEE802154_SCF_KEY_SHORT_INDEX:
526 skb->data); 377 pr_debug("key %04x:%04x %02x\n",
527 skb_pull(skb, IEEE802154_ADDR_LEN); 378 le32_to_cpu(hdr.sec.short_src) >> 16,
379 le32_to_cpu(hdr.sec.short_src) & 0xffff,
380 hdr.sec.key_id);
381 break;
528 382
529 pr_debug("source address is hardware\n"); 383 case IEEE802154_SCF_KEY_HW_INDEX:
384 key = swab64((__force u64) hdr.sec.extended_src);
385 pr_debug("key source %8phC %02x\n", &key,
386 hdr.sec.key_id);
387 break;
530 } 388 }
389
390 return -EINVAL;
531 } 391 }
532 392
533 return 0; 393 return 0;
534err:
535 return -EINVAL;
536} 394}
537 395
538void mac802154_wpans_rx(struct mac802154_priv *priv, struct sk_buff *skb) 396void mac802154_wpans_rx(struct mac802154_priv *priv, struct sk_buff *skb)