Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.19-rc3 447 lines 11 kB view raw
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 31struct ieee802154_sechdr { 32#if defined(__LITTLE_ENDIAN_BITFIELD) 33 u8 level:3, 34 key_id_mode:2, 35 reserved:3; 36#elif defined(__BIG_ENDIAN_BITFIELD) 37 u8 reserved:3, 38 key_id_mode:2, 39 level:3; 40#else 41#error "Please fix <asm/byteorder.h>" 42#endif 43 u8 key_id; 44 __le32 frame_counter; 45 union { 46 __le32 short_src; 47 __le64 extended_src; 48 }; 49}; 50 51struct ieee802154_addr { 52 u8 mode; 53 __le16 pan_id; 54 union { 55 __le16 short_addr; 56 __le64 extended_addr; 57 }; 58}; 59 60struct ieee802154_hdr_fc { 61#if defined(__LITTLE_ENDIAN_BITFIELD) 62 u16 type:3, 63 security_enabled:1, 64 frame_pending:1, 65 ack_request:1, 66 intra_pan:1, 67 reserved:3, 68 dest_addr_mode:2, 69 version:2, 70 source_addr_mode:2; 71#elif defined(__BIG_ENDIAN_BITFIELD) 72 u16 reserved:1, 73 intra_pan:1, 74 ack_request:1, 75 frame_pending:1, 76 security_enabled:1, 77 type:3, 78 source_addr_mode:2, 79 version:2, 80 dest_addr_mode:2, 81 reserved2:2; 82#else 83#error "Please fix <asm/byteorder.h>" 84#endif 85}; 86 87struct ieee802154_hdr { 88 struct ieee802154_hdr_fc fc; 89 u8 seq; 90 struct ieee802154_addr source; 91 struct ieee802154_addr dest; 92 struct ieee802154_sechdr sec; 93}; 94 95/* pushes hdr onto the skb. fields of hdr->fc that can be calculated from 96 * the contents of hdr will be, and the actual value of those bits in 97 * hdr->fc will be ignored. this includes the INTRA_PAN bit and the frame 98 * version, if SECEN is set. 99 */ 100int ieee802154_hdr_push(struct sk_buff *skb, const struct ieee802154_hdr *hdr); 101 102/* pulls the entire 802.15.4 header off of the skb, including the security 103 * header, and performs pan id decompression 104 */ 105int ieee802154_hdr_pull(struct sk_buff *skb, struct ieee802154_hdr *hdr); 106 107/* parses the frame control, sequence number of address fields in a given skb 108 * and stores them into hdr, performing pan id decompression and length checks 109 * to be suitable for use in header_ops.parse 110 */ 111int ieee802154_hdr_peek_addrs(const struct sk_buff *skb, 112 struct ieee802154_hdr *hdr); 113 114/* parses the full 802.15.4 header a given skb and stores them into hdr, 115 * performing pan id decompression and length checks to be suitable for use in 116 * header_ops.parse 117 */ 118int ieee802154_hdr_peek(const struct sk_buff *skb, struct ieee802154_hdr *hdr); 119 120int ieee802154_max_payload(const struct ieee802154_hdr *hdr); 121 122static inline int 123ieee802154_sechdr_authtag_len(const struct ieee802154_sechdr *sec) 124{ 125 switch (sec->level) { 126 case IEEE802154_SCF_SECLEVEL_MIC32: 127 case IEEE802154_SCF_SECLEVEL_ENC_MIC32: 128 return 4; 129 case IEEE802154_SCF_SECLEVEL_MIC64: 130 case IEEE802154_SCF_SECLEVEL_ENC_MIC64: 131 return 8; 132 case IEEE802154_SCF_SECLEVEL_MIC128: 133 case IEEE802154_SCF_SECLEVEL_ENC_MIC128: 134 return 16; 135 case IEEE802154_SCF_SECLEVEL_NONE: 136 case IEEE802154_SCF_SECLEVEL_ENC: 137 default: 138 return 0; 139 } 140} 141 142static inline int ieee802154_hdr_length(struct sk_buff *skb) 143{ 144 struct ieee802154_hdr hdr; 145 int len = ieee802154_hdr_pull(skb, &hdr); 146 147 if (len > 0) 148 skb_push(skb, len); 149 150 return len; 151} 152 153static inline bool ieee802154_addr_equal(const struct ieee802154_addr *a1, 154 const struct ieee802154_addr *a2) 155{ 156 if (a1->pan_id != a2->pan_id || a1->mode != a2->mode) 157 return false; 158 159 if ((a1->mode == IEEE802154_ADDR_LONG && 160 a1->extended_addr != a2->extended_addr) || 161 (a1->mode == IEEE802154_ADDR_SHORT && 162 a1->short_addr != a2->short_addr)) 163 return false; 164 165 return true; 166} 167 168static inline __le64 ieee802154_devaddr_from_raw(const void *raw) 169{ 170 u64 temp; 171 172 memcpy(&temp, raw, IEEE802154_ADDR_LEN); 173 return (__force __le64)swab64(temp); 174} 175 176static inline void ieee802154_devaddr_to_raw(void *raw, __le64 addr) 177{ 178 u64 temp = swab64((__force u64)addr); 179 180 memcpy(raw, &temp, IEEE802154_ADDR_LEN); 181} 182 183static inline void ieee802154_addr_from_sa(struct ieee802154_addr *a, 184 const struct ieee802154_addr_sa *sa) 185{ 186 a->mode = sa->addr_type; 187 a->pan_id = cpu_to_le16(sa->pan_id); 188 189 switch (a->mode) { 190 case IEEE802154_ADDR_SHORT: 191 a->short_addr = cpu_to_le16(sa->short_addr); 192 break; 193 case IEEE802154_ADDR_LONG: 194 a->extended_addr = ieee802154_devaddr_from_raw(sa->hwaddr); 195 break; 196 } 197} 198 199static inline void ieee802154_addr_to_sa(struct ieee802154_addr_sa *sa, 200 const struct ieee802154_addr *a) 201{ 202 sa->addr_type = a->mode; 203 sa->pan_id = le16_to_cpu(a->pan_id); 204 205 switch (a->mode) { 206 case IEEE802154_ADDR_SHORT: 207 sa->short_addr = le16_to_cpu(a->short_addr); 208 break; 209 case IEEE802154_ADDR_LONG: 210 ieee802154_devaddr_to_raw(sa->hwaddr, a->extended_addr); 211 break; 212 } 213} 214 215/* 216 * A control block of skb passed between the ARPHRD_IEEE802154 device 217 * and other stack parts. 218 */ 219struct ieee802154_mac_cb { 220 u8 lqi; 221 u8 type; 222 bool ackreq; 223 bool secen; 224 bool secen_override; 225 u8 seclevel; 226 bool seclevel_override; 227 struct ieee802154_addr source; 228 struct ieee802154_addr dest; 229}; 230 231static inline struct ieee802154_mac_cb *mac_cb(struct sk_buff *skb) 232{ 233 return (struct ieee802154_mac_cb *)skb->cb; 234} 235 236static inline struct ieee802154_mac_cb *mac_cb_init(struct sk_buff *skb) 237{ 238 BUILD_BUG_ON(sizeof(struct ieee802154_mac_cb) > sizeof(skb->cb)); 239 240 memset(skb->cb, 0, sizeof(struct ieee802154_mac_cb)); 241 return mac_cb(skb); 242} 243 244#define IEEE802154_LLSEC_KEY_SIZE 16 245 246struct ieee802154_llsec_key_id { 247 u8 mode; 248 u8 id; 249 union { 250 struct ieee802154_addr device_addr; 251 __le32 short_source; 252 __le64 extended_source; 253 }; 254}; 255 256struct ieee802154_llsec_key { 257 u8 frame_types; 258 u32 cmd_frame_ids; 259 u8 key[IEEE802154_LLSEC_KEY_SIZE]; 260}; 261 262struct ieee802154_llsec_key_entry { 263 struct list_head list; 264 265 struct ieee802154_llsec_key_id id; 266 struct ieee802154_llsec_key *key; 267}; 268 269struct ieee802154_llsec_device_key { 270 struct list_head list; 271 272 struct ieee802154_llsec_key_id key_id; 273 u32 frame_counter; 274}; 275 276enum { 277 IEEE802154_LLSEC_DEVKEY_IGNORE, 278 IEEE802154_LLSEC_DEVKEY_RESTRICT, 279 IEEE802154_LLSEC_DEVKEY_RECORD, 280 281 __IEEE802154_LLSEC_DEVKEY_MAX, 282}; 283 284struct ieee802154_llsec_device { 285 struct list_head list; 286 287 __le16 pan_id; 288 __le16 short_addr; 289 __le64 hwaddr; 290 u32 frame_counter; 291 bool seclevel_exempt; 292 293 u8 key_mode; 294 struct list_head keys; 295}; 296 297struct ieee802154_llsec_seclevel { 298 struct list_head list; 299 300 u8 frame_type; 301 u8 cmd_frame_id; 302 bool device_override; 303 u32 sec_levels; 304}; 305 306struct ieee802154_llsec_params { 307 bool enabled; 308 309 __be32 frame_counter; 310 u8 out_level; 311 struct ieee802154_llsec_key_id out_key; 312 313 __le64 default_key_source; 314 315 __le16 pan_id; 316 __le64 hwaddr; 317 __le64 coord_hwaddr; 318 __le16 coord_shortaddr; 319}; 320 321struct ieee802154_llsec_table { 322 struct list_head keys; 323 struct list_head devices; 324 struct list_head security_levels; 325}; 326 327#define IEEE802154_MAC_SCAN_ED 0 328#define IEEE802154_MAC_SCAN_ACTIVE 1 329#define IEEE802154_MAC_SCAN_PASSIVE 2 330#define IEEE802154_MAC_SCAN_ORPHAN 3 331 332struct ieee802154_mac_params { 333 s8 transmit_power; 334 u8 min_be; 335 u8 max_be; 336 u8 csma_retries; 337 s8 frame_retries; 338 339 bool lbt; 340 u8 cca_mode; 341 s32 cca_ed_level; 342}; 343 344struct wpan_phy; 345 346enum { 347 IEEE802154_LLSEC_PARAM_ENABLED = 1 << 0, 348 IEEE802154_LLSEC_PARAM_FRAME_COUNTER = 1 << 1, 349 IEEE802154_LLSEC_PARAM_OUT_LEVEL = 1 << 2, 350 IEEE802154_LLSEC_PARAM_OUT_KEY = 1 << 3, 351 IEEE802154_LLSEC_PARAM_KEY_SOURCE = 1 << 4, 352 IEEE802154_LLSEC_PARAM_PAN_ID = 1 << 5, 353 IEEE802154_LLSEC_PARAM_HWADDR = 1 << 6, 354 IEEE802154_LLSEC_PARAM_COORD_HWADDR = 1 << 7, 355 IEEE802154_LLSEC_PARAM_COORD_SHORTADDR = 1 << 8, 356}; 357 358struct ieee802154_llsec_ops { 359 int (*get_params)(struct net_device *dev, 360 struct ieee802154_llsec_params *params); 361 int (*set_params)(struct net_device *dev, 362 const struct ieee802154_llsec_params *params, 363 int changed); 364 365 int (*add_key)(struct net_device *dev, 366 const struct ieee802154_llsec_key_id *id, 367 const struct ieee802154_llsec_key *key); 368 int (*del_key)(struct net_device *dev, 369 const struct ieee802154_llsec_key_id *id); 370 371 int (*add_dev)(struct net_device *dev, 372 const struct ieee802154_llsec_device *llsec_dev); 373 int (*del_dev)(struct net_device *dev, __le64 dev_addr); 374 375 int (*add_devkey)(struct net_device *dev, 376 __le64 device_addr, 377 const struct ieee802154_llsec_device_key *key); 378 int (*del_devkey)(struct net_device *dev, 379 __le64 device_addr, 380 const struct ieee802154_llsec_device_key *key); 381 382 int (*add_seclevel)(struct net_device *dev, 383 const struct ieee802154_llsec_seclevel *sl); 384 int (*del_seclevel)(struct net_device *dev, 385 const struct ieee802154_llsec_seclevel *sl); 386 387 void (*lock_table)(struct net_device *dev); 388 void (*get_table)(struct net_device *dev, 389 struct ieee802154_llsec_table **t); 390 void (*unlock_table)(struct net_device *dev); 391}; 392/* 393 * This should be located at net_device->ml_priv 394 * 395 * get_phy should increment the reference counting on returned phy. 396 * Use wpan_wpy_put to put that reference. 397 */ 398struct ieee802154_mlme_ops { 399 /* The following fields are optional (can be NULL). */ 400 401 int (*assoc_req)(struct net_device *dev, 402 struct ieee802154_addr *addr, 403 u8 channel, u8 page, u8 cap); 404 int (*assoc_resp)(struct net_device *dev, 405 struct ieee802154_addr *addr, 406 __le16 short_addr, u8 status); 407 int (*disassoc_req)(struct net_device *dev, 408 struct ieee802154_addr *addr, 409 u8 reason); 410 int (*start_req)(struct net_device *dev, 411 struct ieee802154_addr *addr, 412 u8 channel, u8 page, u8 bcn_ord, u8 sf_ord, 413 u8 pan_coord, u8 blx, u8 coord_realign); 414 int (*scan_req)(struct net_device *dev, 415 u8 type, u32 channels, u8 page, u8 duration); 416 417 int (*set_mac_params)(struct net_device *dev, 418 const struct ieee802154_mac_params *params); 419 void (*get_mac_params)(struct net_device *dev, 420 struct ieee802154_mac_params *params); 421 422 struct ieee802154_llsec_ops *llsec; 423 424 /* The fields below are required. */ 425 426 /* 427 * FIXME: these should become the part of PIB/MIB interface. 428 * However we still don't have IB interface of any kind 429 */ 430 __le16 (*get_pan_id)(const struct net_device *dev); 431 __le16 (*get_short_addr)(const struct net_device *dev); 432 u8 (*get_dsn)(const struct net_device *dev); 433}; 434 435static inline struct ieee802154_mlme_ops * 436ieee802154_mlme_ops(const struct net_device *dev) 437{ 438 return dev->ml_priv; 439} 440 441static inline struct ieee802154_reduced_mlme_ops * 442ieee802154_reduced_mlme_ops(const struct net_device *dev) 443{ 444 return dev->ml_priv; 445} 446 447#endif