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