xref: /linux/include/net/ieee802154_netdev.h (revision 44f57d78)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * An interface between IEEE802.15.4 device and rest of the kernel.
4  *
5  * Copyright (C) 2007-2012 Siemens AG
6  *
7  * Written by:
8  * Pavel Smolenskiy <pavel.smolenskiy@gmail.com>
9  * Maxim Gorbachyov <maxim.gorbachev@siemens.com>
10  * Maxim Osipov <maxim.osipov@siemens.com>
11  * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
12  * Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
13  */
14 
15 #ifndef IEEE802154_NETDEVICE_H
16 #define IEEE802154_NETDEVICE_H
17 
18 #include <net/af_ieee802154.h>
19 #include <linux/netdevice.h>
20 #include <linux/skbuff.h>
21 #include <linux/ieee802154.h>
22 
23 #include <net/cfg802154.h>
24 
25 struct ieee802154_sechdr {
26 #if defined(__LITTLE_ENDIAN_BITFIELD)
27 	u8 level:3,
28 	   key_id_mode:2,
29 	   reserved:3;
30 #elif defined(__BIG_ENDIAN_BITFIELD)
31 	u8 reserved:3,
32 	   key_id_mode:2,
33 	   level:3;
34 #else
35 #error	"Please fix <asm/byteorder.h>"
36 #endif
37 	u8 key_id;
38 	__le32 frame_counter;
39 	union {
40 		__le32 short_src;
41 		__le64 extended_src;
42 	};
43 };
44 
45 struct ieee802154_hdr_fc {
46 #if defined(__LITTLE_ENDIAN_BITFIELD)
47 	u16 type:3,
48 	    security_enabled:1,
49 	    frame_pending:1,
50 	    ack_request:1,
51 	    intra_pan:1,
52 	    reserved:3,
53 	    dest_addr_mode:2,
54 	    version:2,
55 	    source_addr_mode:2;
56 #elif defined(__BIG_ENDIAN_BITFIELD)
57 	u16 reserved:1,
58 	    intra_pan:1,
59 	    ack_request:1,
60 	    frame_pending:1,
61 	    security_enabled:1,
62 	    type:3,
63 	    source_addr_mode:2,
64 	    version:2,
65 	    dest_addr_mode:2,
66 	    reserved2:2;
67 #else
68 #error	"Please fix <asm/byteorder.h>"
69 #endif
70 };
71 
72 struct ieee802154_hdr {
73 	struct ieee802154_hdr_fc fc;
74 	u8 seq;
75 	struct ieee802154_addr source;
76 	struct ieee802154_addr dest;
77 	struct ieee802154_sechdr sec;
78 };
79 
80 /* pushes hdr onto the skb. fields of hdr->fc that can be calculated from
81  * the contents of hdr will be, and the actual value of those bits in
82  * hdr->fc will be ignored. this includes the INTRA_PAN bit and the frame
83  * version, if SECEN is set.
84  */
85 int ieee802154_hdr_push(struct sk_buff *skb, struct ieee802154_hdr *hdr);
86 
87 /* pulls the entire 802.15.4 header off of the skb, including the security
88  * header, and performs pan id decompression
89  */
90 int ieee802154_hdr_pull(struct sk_buff *skb, struct ieee802154_hdr *hdr);
91 
92 /* parses the frame control, sequence number of address fields in a given skb
93  * and stores them into hdr, performing pan id decompression and length checks
94  * to be suitable for use in header_ops.parse
95  */
96 int ieee802154_hdr_peek_addrs(const struct sk_buff *skb,
97 			      struct ieee802154_hdr *hdr);
98 
99 /* parses the full 802.15.4 header a given skb and stores them into hdr,
100  * performing pan id decompression and length checks to be suitable for use in
101  * header_ops.parse
102  */
103 int ieee802154_hdr_peek(const struct sk_buff *skb, struct ieee802154_hdr *hdr);
104 
105 int ieee802154_max_payload(const struct ieee802154_hdr *hdr);
106 
107 static inline int
108 ieee802154_sechdr_authtag_len(const struct ieee802154_sechdr *sec)
109 {
110 	switch (sec->level) {
111 	case IEEE802154_SCF_SECLEVEL_MIC32:
112 	case IEEE802154_SCF_SECLEVEL_ENC_MIC32:
113 		return 4;
114 	case IEEE802154_SCF_SECLEVEL_MIC64:
115 	case IEEE802154_SCF_SECLEVEL_ENC_MIC64:
116 		return 8;
117 	case IEEE802154_SCF_SECLEVEL_MIC128:
118 	case IEEE802154_SCF_SECLEVEL_ENC_MIC128:
119 		return 16;
120 	case IEEE802154_SCF_SECLEVEL_NONE:
121 	case IEEE802154_SCF_SECLEVEL_ENC:
122 	default:
123 		return 0;
124 	}
125 }
126 
127 static inline int ieee802154_hdr_length(struct sk_buff *skb)
128 {
129 	struct ieee802154_hdr hdr;
130 	int len = ieee802154_hdr_pull(skb, &hdr);
131 
132 	if (len > 0)
133 		skb_push(skb, len);
134 
135 	return len;
136 }
137 
138 static inline bool ieee802154_addr_equal(const struct ieee802154_addr *a1,
139 					 const struct ieee802154_addr *a2)
140 {
141 	if (a1->pan_id != a2->pan_id || a1->mode != a2->mode)
142 		return false;
143 
144 	if ((a1->mode == IEEE802154_ADDR_LONG &&
145 	     a1->extended_addr != a2->extended_addr) ||
146 	    (a1->mode == IEEE802154_ADDR_SHORT &&
147 	     a1->short_addr != a2->short_addr))
148 		return false;
149 
150 	return true;
151 }
152 
153 static inline __le64 ieee802154_devaddr_from_raw(const void *raw)
154 {
155 	u64 temp;
156 
157 	memcpy(&temp, raw, IEEE802154_ADDR_LEN);
158 	return (__force __le64)swab64(temp);
159 }
160 
161 static inline void ieee802154_devaddr_to_raw(void *raw, __le64 addr)
162 {
163 	u64 temp = swab64((__force u64)addr);
164 
165 	memcpy(raw, &temp, IEEE802154_ADDR_LEN);
166 }
167 
168 static inline void ieee802154_addr_from_sa(struct ieee802154_addr *a,
169 					   const struct ieee802154_addr_sa *sa)
170 {
171 	a->mode = sa->addr_type;
172 	a->pan_id = cpu_to_le16(sa->pan_id);
173 
174 	switch (a->mode) {
175 	case IEEE802154_ADDR_SHORT:
176 		a->short_addr = cpu_to_le16(sa->short_addr);
177 		break;
178 	case IEEE802154_ADDR_LONG:
179 		a->extended_addr = ieee802154_devaddr_from_raw(sa->hwaddr);
180 		break;
181 	}
182 }
183 
184 static inline void ieee802154_addr_to_sa(struct ieee802154_addr_sa *sa,
185 					 const struct ieee802154_addr *a)
186 {
187 	sa->addr_type = a->mode;
188 	sa->pan_id = le16_to_cpu(a->pan_id);
189 
190 	switch (a->mode) {
191 	case IEEE802154_ADDR_SHORT:
192 		sa->short_addr = le16_to_cpu(a->short_addr);
193 		break;
194 	case IEEE802154_ADDR_LONG:
195 		ieee802154_devaddr_to_raw(sa->hwaddr, a->extended_addr);
196 		break;
197 	}
198 }
199 
200 /*
201  * A control block of skb passed between the ARPHRD_IEEE802154 device
202  * and other stack parts.
203  */
204 struct ieee802154_mac_cb {
205 	u8 lqi;
206 	u8 type;
207 	bool ackreq;
208 	bool secen;
209 	bool secen_override;
210 	u8 seclevel;
211 	bool seclevel_override;
212 	struct ieee802154_addr source;
213 	struct ieee802154_addr dest;
214 };
215 
216 static inline struct ieee802154_mac_cb *mac_cb(struct sk_buff *skb)
217 {
218 	return (struct ieee802154_mac_cb *)skb->cb;
219 }
220 
221 static inline struct ieee802154_mac_cb *mac_cb_init(struct sk_buff *skb)
222 {
223 	BUILD_BUG_ON(sizeof(struct ieee802154_mac_cb) > sizeof(skb->cb));
224 
225 	memset(skb->cb, 0, sizeof(struct ieee802154_mac_cb));
226 	return mac_cb(skb);
227 }
228 
229 enum {
230 	IEEE802154_LLSEC_DEVKEY_IGNORE,
231 	IEEE802154_LLSEC_DEVKEY_RESTRICT,
232 	IEEE802154_LLSEC_DEVKEY_RECORD,
233 
234 	__IEEE802154_LLSEC_DEVKEY_MAX,
235 };
236 
237 #define IEEE802154_MAC_SCAN_ED		0
238 #define IEEE802154_MAC_SCAN_ACTIVE	1
239 #define IEEE802154_MAC_SCAN_PASSIVE	2
240 #define IEEE802154_MAC_SCAN_ORPHAN	3
241 
242 struct ieee802154_mac_params {
243 	s8 transmit_power;
244 	u8 min_be;
245 	u8 max_be;
246 	u8 csma_retries;
247 	s8 frame_retries;
248 
249 	bool lbt;
250 	struct wpan_phy_cca cca;
251 	s32 cca_ed_level;
252 };
253 
254 struct wpan_phy;
255 
256 enum {
257 	IEEE802154_LLSEC_PARAM_ENABLED		= BIT(0),
258 	IEEE802154_LLSEC_PARAM_FRAME_COUNTER	= BIT(1),
259 	IEEE802154_LLSEC_PARAM_OUT_LEVEL	= BIT(2),
260 	IEEE802154_LLSEC_PARAM_OUT_KEY		= BIT(3),
261 	IEEE802154_LLSEC_PARAM_KEY_SOURCE	= BIT(4),
262 	IEEE802154_LLSEC_PARAM_PAN_ID		= BIT(5),
263 	IEEE802154_LLSEC_PARAM_HWADDR		= BIT(6),
264 	IEEE802154_LLSEC_PARAM_COORD_HWADDR	= BIT(7),
265 	IEEE802154_LLSEC_PARAM_COORD_SHORTADDR	= BIT(8),
266 };
267 
268 struct ieee802154_llsec_ops {
269 	int (*get_params)(struct net_device *dev,
270 			  struct ieee802154_llsec_params *params);
271 	int (*set_params)(struct net_device *dev,
272 			  const struct ieee802154_llsec_params *params,
273 			  int changed);
274 
275 	int (*add_key)(struct net_device *dev,
276 		       const struct ieee802154_llsec_key_id *id,
277 		       const struct ieee802154_llsec_key *key);
278 	int (*del_key)(struct net_device *dev,
279 		       const struct ieee802154_llsec_key_id *id);
280 
281 	int (*add_dev)(struct net_device *dev,
282 		       const struct ieee802154_llsec_device *llsec_dev);
283 	int (*del_dev)(struct net_device *dev, __le64 dev_addr);
284 
285 	int (*add_devkey)(struct net_device *dev,
286 			  __le64 device_addr,
287 			  const struct ieee802154_llsec_device_key *key);
288 	int (*del_devkey)(struct net_device *dev,
289 			  __le64 device_addr,
290 			  const struct ieee802154_llsec_device_key *key);
291 
292 	int (*add_seclevel)(struct net_device *dev,
293 			    const struct ieee802154_llsec_seclevel *sl);
294 	int (*del_seclevel)(struct net_device *dev,
295 			    const struct ieee802154_llsec_seclevel *sl);
296 
297 	void (*lock_table)(struct net_device *dev);
298 	void (*get_table)(struct net_device *dev,
299 			  struct ieee802154_llsec_table **t);
300 	void (*unlock_table)(struct net_device *dev);
301 };
302 /*
303  * This should be located at net_device->ml_priv
304  *
305  * get_phy should increment the reference counting on returned phy.
306  * Use wpan_wpy_put to put that reference.
307  */
308 struct ieee802154_mlme_ops {
309 	/* The following fields are optional (can be NULL). */
310 
311 	int (*assoc_req)(struct net_device *dev,
312 			struct ieee802154_addr *addr,
313 			u8 channel, u8 page, u8 cap);
314 	int (*assoc_resp)(struct net_device *dev,
315 			struct ieee802154_addr *addr,
316 			__le16 short_addr, u8 status);
317 	int (*disassoc_req)(struct net_device *dev,
318 			struct ieee802154_addr *addr,
319 			u8 reason);
320 	int (*start_req)(struct net_device *dev,
321 			struct ieee802154_addr *addr,
322 			u8 channel, u8 page, u8 bcn_ord, u8 sf_ord,
323 			u8 pan_coord, u8 blx, u8 coord_realign);
324 	int (*scan_req)(struct net_device *dev,
325 			u8 type, u32 channels, u8 page, u8 duration);
326 
327 	int (*set_mac_params)(struct net_device *dev,
328 			      const struct ieee802154_mac_params *params);
329 	void (*get_mac_params)(struct net_device *dev,
330 			       struct ieee802154_mac_params *params);
331 
332 	const struct ieee802154_llsec_ops *llsec;
333 };
334 
335 static inline struct ieee802154_mlme_ops *
336 ieee802154_mlme_ops(const struct net_device *dev)
337 {
338 	return dev->ml_priv;
339 }
340 
341 #endif
342