linux/include/net/ieee802154_netdev.h
<<
>>
Prefs
   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
  25struct 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
  45struct 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
  72struct 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 */
  85int 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 */
  90int 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 */
  96int 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 */
 103int ieee802154_hdr_peek(const struct sk_buff *skb, struct ieee802154_hdr *hdr);
 104
 105int ieee802154_max_payload(const struct ieee802154_hdr *hdr);
 106
 107static inline int
 108ieee802154_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
 127static 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
 138static 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
 153static 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
 161static 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
 168static 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
 184static 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 */
 204struct 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
 216static inline struct ieee802154_mac_cb *mac_cb(struct sk_buff *skb)
 217{
 218        return (struct ieee802154_mac_cb *)skb->cb;
 219}
 220
 221static 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
 229enum {
 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
 242struct 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
 254struct wpan_phy;
 255
 256enum {
 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
 268struct 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 */
 308struct 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
 335static inline struct ieee802154_mlme_ops *
 336ieee802154_mlme_ops(const struct net_device *dev)
 337{
 338        return dev->ml_priv;
 339}
 340
 341#endif
 342