| 1 | |
| 2 | |
| 3 | * Netlink interface for IEEE 802.15.4 stack
|
| 4 | *
|
| 5 | * Copyright 2007, 2008 Siemens AG
|
| 6 | *
|
| 7 | * Written by:
|
| 8 | * Sergey Lapin <[email protected]>
|
| 9 | * Dmitry Eremin-Solenikov <[email protected]>
|
| 10 | * Maxim Osipov <[email protected]>
|
| 11 |
|
| 12 |
|
| 13 | #include <linux/kernel.h>
|
| 14 | #include <linux/gfp.h>
|
| 15 | #include <net/genetlink.h>
|
| 16 | #include <linux/nl802154.h>
|
| 17 |
|
| 18 | #include "ieee802154.h"
|
| 19 |
|
| 20 | static unsigned int ieee802154_seq_num;
|
| 21 | static DEFINE_SPINLOCK(ieee802154_seq_lock);
|
| 22 |
|
| 23 |
|
| 24 | struct sk_buff *ieee802154_nl_create(int flags, u8 req)
|
| 25 | {
|
| 26 | void *hdr;
|
| 27 | struct sk_buff *msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
|
| 28 | unsigned long f;
|
| 29 |
|
| 30 | if (!msg)
|
| 31 | return NULL;
|
| 32 |
|
| 33 | spin_lock_irqsave(&ieee802154_seq_lock, f);
|
| 34 | hdr = genlmsg_put(msg, 0, ieee802154_seq_num++,
|
| 35 | &nl802154_family, flags, req);
|
| 36 | spin_unlock_irqrestore(&ieee802154_seq_lock, f);
|
| 37 | if (!hdr) {
|
| 38 | nlmsg_free(msg);
|
| 39 | return NULL;
|
| 40 | }
|
| 41 |
|
| 42 | return msg;
|
| 43 | }
|
| 44 |
|
| 45 | int ieee802154_nl_mcast(struct sk_buff *msg, unsigned int group)
|
| 46 | {
|
| 47 | struct nlmsghdr *nlh = nlmsg_hdr(msg);
|
| 48 | void *hdr = genlmsg_data(nlmsg_data(nlh));
|
| 49 |
|
| 50 | genlmsg_end(msg, hdr);
|
| 51 |
|
| 52 | return genlmsg_multicast(&nl802154_family, msg, 0, group, GFP_ATOMIC);
|
| 53 | }
|
| 54 |
|
| 55 | struct sk_buff *ieee802154_nl_new_reply(struct genl_info *info,
|
| 56 | int flags, u8 req)
|
| 57 | {
|
| 58 | void *hdr;
|
| 59 | struct sk_buff *msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
|
| 60 |
|
| 61 | if (!msg)
|
| 62 | return NULL;
|
| 63 |
|
| 64 | hdr = genlmsg_put_reply(msg, info,
|
| 65 | &nl802154_family, flags, req);
|
| 66 | if (!hdr) {
|
| 67 | nlmsg_free(msg);
|
| 68 | return NULL;
|
| 69 | }
|
| 70 |
|
| 71 | return msg;
|
| 72 | }
|
| 73 |
|
| 74 | int ieee802154_nl_reply(struct sk_buff *msg, struct genl_info *info)
|
| 75 | {
|
| 76 | struct nlmsghdr *nlh = nlmsg_hdr(msg);
|
| 77 | void *hdr = genlmsg_data(nlmsg_data(nlh));
|
| 78 |
|
| 79 | genlmsg_end(msg, hdr);
|
| 80 |
|
| 81 | return genlmsg_reply(msg, info);
|
| 82 | }
|
| 83 |
|
| 84 | static const struct genl_small_ops ieee802154_ops[] = {
|
| 85 |
|
| 86 | IEEE802154_DUMP(IEEE802154_LIST_PHY, ieee802154_list_phy,
|
| 87 | ieee802154_dump_phy),
|
| 88 | IEEE802154_OP(IEEE802154_ADD_IFACE, ieee802154_add_iface),
|
| 89 | IEEE802154_OP(IEEE802154_DEL_IFACE, ieee802154_del_iface),
|
| 90 |
|
| 91 | IEEE802154_OP(IEEE802154_ASSOCIATE_REQ, ieee802154_associate_req),
|
| 92 | IEEE802154_OP(IEEE802154_ASSOCIATE_RESP, ieee802154_associate_resp),
|
| 93 | IEEE802154_OP(IEEE802154_DISASSOCIATE_REQ, ieee802154_disassociate_req),
|
| 94 | IEEE802154_OP(IEEE802154_SCAN_REQ, ieee802154_scan_req),
|
| 95 | IEEE802154_OP(IEEE802154_START_REQ, ieee802154_start_req),
|
| 96 | IEEE802154_DUMP(IEEE802154_LIST_IFACE, ieee802154_list_iface,
|
| 97 | ieee802154_dump_iface),
|
| 98 | IEEE802154_OP(IEEE802154_SET_MACPARAMS, ieee802154_set_macparams),
|
| 99 | IEEE802154_OP(IEEE802154_LLSEC_GETPARAMS, ieee802154_llsec_getparams),
|
| 100 | IEEE802154_OP(IEEE802154_LLSEC_SETPARAMS, ieee802154_llsec_setparams),
|
| 101 | IEEE802154_DUMP_PRIV(IEEE802154_LLSEC_LIST_KEY, NULL,
|
| 102 | ieee802154_llsec_dump_keys),
|
| 103 | IEEE802154_OP_RELAXED(IEEE802154_LLSEC_ADD_KEY, ieee802154_llsec_add_key),
|
| 104 | IEEE802154_OP_RELAXED(IEEE802154_LLSEC_DEL_KEY, ieee802154_llsec_del_key),
|
| 105 | IEEE802154_DUMP_PRIV(IEEE802154_LLSEC_LIST_DEV, NULL,
|
| 106 | ieee802154_llsec_dump_devs),
|
| 107 | IEEE802154_OP_RELAXED(IEEE802154_LLSEC_ADD_DEV, ieee802154_llsec_add_dev),
|
| 108 | IEEE802154_OP_RELAXED(IEEE802154_LLSEC_DEL_DEV, ieee802154_llsec_del_dev),
|
| 109 | IEEE802154_DUMP_PRIV(IEEE802154_LLSEC_LIST_DEVKEY, NULL,
|
| 110 | ieee802154_llsec_dump_devkeys),
|
| 111 | IEEE802154_OP_RELAXED(IEEE802154_LLSEC_ADD_DEVKEY, ieee802154_llsec_add_devkey),
|
| 112 | IEEE802154_OP_RELAXED(IEEE802154_LLSEC_DEL_DEVKEY, ieee802154_llsec_del_devkey),
|
| 113 | IEEE802154_DUMP_PRIV(IEEE802154_LLSEC_LIST_SECLEVEL, NULL,
|
| 114 | ieee802154_llsec_dump_seclevels),
|
| 115 | IEEE802154_OP_RELAXED(IEEE802154_LLSEC_ADD_SECLEVEL,
|
| 116 | ieee802154_llsec_add_seclevel),
|
| 117 | IEEE802154_OP_RELAXED(IEEE802154_LLSEC_DEL_SECLEVEL,
|
| 118 | ieee802154_llsec_del_seclevel),
|
| 119 | };
|
| 120 |
|
| 121 | static const struct genl_multicast_group ieee802154_mcgrps[] = {
|
| 122 | [IEEE802154_COORD_MCGRP] = { .name = IEEE802154_MCAST_COORD_NAME, },
|
| 123 | [IEEE802154_BEACON_MCGRP] = { .name = IEEE802154_MCAST_BEACON_NAME, },
|
| 124 | };
|
| 125 |
|
| 126 | struct genl_family nl802154_family __ro_after_init = {
|
| 127 | .hdrsize = 0,
|
| 128 | .name = IEEE802154_NL_NAME,
|
| 129 | .version = 1,
|
| 130 | .maxattr = IEEE802154_ATTR_MAX,
|
| 131 | .policy = ieee802154_policy,
|
| 132 | .module = THIS_MODULE,
|
| 133 | .small_ops = ieee802154_ops,
|
| 134 | .n_small_ops = ARRAY_SIZE(ieee802154_ops),
|
| 135 | .resv_start_op = IEEE802154_LLSEC_DEL_SECLEVEL + 1,
|
| 136 | .mcgrps = ieee802154_mcgrps,
|
| 137 | .n_mcgrps = ARRAY_SIZE(ieee802154_mcgrps),
|
| 138 | };
|
| 139 |
|
| 140 | int __init ieee802154_nl_init(void)
|
| 141 | {
|
| 142 | return genl_register_family(&nl802154_family);
|
| 143 | }
|
| 144 |
|
| 145 | void ieee802154_nl_exit(void)
|
| 146 | {
|
| 147 | genl_unregister_family(&nl802154_family);
|
| 148 | }
|