Loading include/linux/nl802154.h +2 −0 Original line number Diff line number Diff line Loading @@ -111,6 +111,8 @@ enum { IEEE802154_RX_ENABLE_REQ, /* Not supported yet */ IEEE802154_RX_ENABLE_CONF, /* Not supported yet */ IEEE802154_LIST_IFACE, __IEEE802154_CMD_MAX, }; Loading net/ieee802154/netlink.c +104 −2 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ * Written by: * Sergey Lapin <slapin@ossfans.org> * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> * Maxim Osipov <maxim.osipov@siemens.com> */ #include <linux/kernel.h> Loading @@ -26,6 +27,7 @@ #include <linux/netdevice.h> #include <net/netlink.h> #include <net/genetlink.h> #include <net/sock.h> #include <linux/nl802154.h> #include <net/af_ieee802154.h> #include <net/nl802154.h> Loading Loading @@ -73,7 +75,7 @@ static int ieee802154_nl_finish(struct sk_buff *msg) /* XXX: nlh is right at the start of msg */ void *hdr = genlmsg_data(NLMSG_DATA(msg->data)); if (!genlmsg_end(msg, hdr)) if (genlmsg_end(msg, hdr) < 0) goto out; return genlmsg_multicast(msg, 0, ieee802154_coord_mcgrp.id, Loading Loading @@ -260,6 +262,35 @@ int ieee802154_nl_scan_confirm(struct net_device *dev, } EXPORT_SYMBOL(ieee802154_nl_scan_confirm); static int ieee802154_nl_fill_iface(struct sk_buff *msg, u32 pid, u32 seq, int flags, struct net_device *dev) { void *hdr; pr_debug("%s\n", __func__); hdr = genlmsg_put(msg, 0, seq, &ieee802154_coordinator_family, flags, IEEE802154_LIST_IFACE); if (!hdr) goto out; NLA_PUT_STRING(msg, IEEE802154_ATTR_DEV_NAME, dev->name); NLA_PUT_U32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex); NLA_PUT(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, dev->dev_addr); NLA_PUT_U16(msg, IEEE802154_ATTR_SHORT_ADDR, ieee802154_mlme_ops(dev)->get_short_addr(dev)); NLA_PUT_U16(msg, IEEE802154_ATTR_PAN_ID, ieee802154_mlme_ops(dev)->get_pan_id(dev)); return genlmsg_end(msg, hdr); nla_put_failure: genlmsg_cancel(msg, hdr); out: return -EMSGSIZE; } /* Requests from userspace */ static struct net_device *ieee802154_nl_get_dev(struct genl_info *info) { Loading Loading @@ -466,6 +497,67 @@ static int ieee802154_scan_req(struct sk_buff *skb, struct genl_info *info) return ret; } static int ieee802154_list_iface(struct sk_buff *skb, struct genl_info *info) { /* Request for interface name, index, type, IEEE address, PAN Id, short address */ struct sk_buff *msg; struct net_device *dev = NULL; int rc = -ENOBUFS; pr_debug("%s\n", __func__); dev = ieee802154_nl_get_dev(info); if (!dev) return -ENODEV; msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); if (!msg) goto out_dev; rc = ieee802154_nl_fill_iface(msg, info->snd_pid, info->snd_seq, 0, dev); if (rc < 0) goto out_free; dev_put(dev); return genlmsg_unicast(&init_net, msg, info->snd_pid); out_free: nlmsg_free(msg); out_dev: dev_put(dev); return rc; } static int ieee802154_dump_iface(struct sk_buff *skb, struct netlink_callback *cb) { struct net *net = sock_net(skb->sk); struct net_device *dev; int idx; int s_idx = cb->args[0]; pr_debug("%s\n", __func__); idx = 0; for_each_netdev(net, dev) { if (idx < s_idx || (dev->type != ARPHRD_IEEE802154)) goto cont; if (ieee802154_nl_fill_iface(skb, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, NLM_F_MULTI, dev) < 0) break; cont: idx++; } cb->args[0] = idx; return skb->len; } #define IEEE802154_OP(_cmd, _func) \ { \ .cmd = _cmd, \ Loading @@ -475,12 +567,22 @@ static int ieee802154_scan_req(struct sk_buff *skb, struct genl_info *info) .flags = GENL_ADMIN_PERM, \ } #define IEEE802154_DUMP(_cmd, _func, _dump) \ { \ .cmd = _cmd, \ .policy = ieee802154_policy, \ .doit = _func, \ .dumpit = _dump, \ } static struct genl_ops ieee802154_coordinator_ops[] = { IEEE802154_OP(IEEE802154_ASSOCIATE_REQ, ieee802154_associate_req), IEEE802154_OP(IEEE802154_ASSOCIATE_RESP, ieee802154_associate_resp), IEEE802154_OP(IEEE802154_DISASSOCIATE_REQ, ieee802154_disassociate_req), IEEE802154_OP(IEEE802154_SCAN_REQ, ieee802154_scan_req), IEEE802154_OP(IEEE802154_START_REQ, ieee802154_start_req), IEEE802154_DUMP(IEEE802154_LIST_IFACE, ieee802154_list_iface, ieee802154_dump_iface), }; static int __init ieee802154_nl_init(void) Loading Loading
include/linux/nl802154.h +2 −0 Original line number Diff line number Diff line Loading @@ -111,6 +111,8 @@ enum { IEEE802154_RX_ENABLE_REQ, /* Not supported yet */ IEEE802154_RX_ENABLE_CONF, /* Not supported yet */ IEEE802154_LIST_IFACE, __IEEE802154_CMD_MAX, }; Loading
net/ieee802154/netlink.c +104 −2 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ * Written by: * Sergey Lapin <slapin@ossfans.org> * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> * Maxim Osipov <maxim.osipov@siemens.com> */ #include <linux/kernel.h> Loading @@ -26,6 +27,7 @@ #include <linux/netdevice.h> #include <net/netlink.h> #include <net/genetlink.h> #include <net/sock.h> #include <linux/nl802154.h> #include <net/af_ieee802154.h> #include <net/nl802154.h> Loading Loading @@ -73,7 +75,7 @@ static int ieee802154_nl_finish(struct sk_buff *msg) /* XXX: nlh is right at the start of msg */ void *hdr = genlmsg_data(NLMSG_DATA(msg->data)); if (!genlmsg_end(msg, hdr)) if (genlmsg_end(msg, hdr) < 0) goto out; return genlmsg_multicast(msg, 0, ieee802154_coord_mcgrp.id, Loading Loading @@ -260,6 +262,35 @@ int ieee802154_nl_scan_confirm(struct net_device *dev, } EXPORT_SYMBOL(ieee802154_nl_scan_confirm); static int ieee802154_nl_fill_iface(struct sk_buff *msg, u32 pid, u32 seq, int flags, struct net_device *dev) { void *hdr; pr_debug("%s\n", __func__); hdr = genlmsg_put(msg, 0, seq, &ieee802154_coordinator_family, flags, IEEE802154_LIST_IFACE); if (!hdr) goto out; NLA_PUT_STRING(msg, IEEE802154_ATTR_DEV_NAME, dev->name); NLA_PUT_U32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex); NLA_PUT(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, dev->dev_addr); NLA_PUT_U16(msg, IEEE802154_ATTR_SHORT_ADDR, ieee802154_mlme_ops(dev)->get_short_addr(dev)); NLA_PUT_U16(msg, IEEE802154_ATTR_PAN_ID, ieee802154_mlme_ops(dev)->get_pan_id(dev)); return genlmsg_end(msg, hdr); nla_put_failure: genlmsg_cancel(msg, hdr); out: return -EMSGSIZE; } /* Requests from userspace */ static struct net_device *ieee802154_nl_get_dev(struct genl_info *info) { Loading Loading @@ -466,6 +497,67 @@ static int ieee802154_scan_req(struct sk_buff *skb, struct genl_info *info) return ret; } static int ieee802154_list_iface(struct sk_buff *skb, struct genl_info *info) { /* Request for interface name, index, type, IEEE address, PAN Id, short address */ struct sk_buff *msg; struct net_device *dev = NULL; int rc = -ENOBUFS; pr_debug("%s\n", __func__); dev = ieee802154_nl_get_dev(info); if (!dev) return -ENODEV; msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); if (!msg) goto out_dev; rc = ieee802154_nl_fill_iface(msg, info->snd_pid, info->snd_seq, 0, dev); if (rc < 0) goto out_free; dev_put(dev); return genlmsg_unicast(&init_net, msg, info->snd_pid); out_free: nlmsg_free(msg); out_dev: dev_put(dev); return rc; } static int ieee802154_dump_iface(struct sk_buff *skb, struct netlink_callback *cb) { struct net *net = sock_net(skb->sk); struct net_device *dev; int idx; int s_idx = cb->args[0]; pr_debug("%s\n", __func__); idx = 0; for_each_netdev(net, dev) { if (idx < s_idx || (dev->type != ARPHRD_IEEE802154)) goto cont; if (ieee802154_nl_fill_iface(skb, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, NLM_F_MULTI, dev) < 0) break; cont: idx++; } cb->args[0] = idx; return skb->len; } #define IEEE802154_OP(_cmd, _func) \ { \ .cmd = _cmd, \ Loading @@ -475,12 +567,22 @@ static int ieee802154_scan_req(struct sk_buff *skb, struct genl_info *info) .flags = GENL_ADMIN_PERM, \ } #define IEEE802154_DUMP(_cmd, _func, _dump) \ { \ .cmd = _cmd, \ .policy = ieee802154_policy, \ .doit = _func, \ .dumpit = _dump, \ } static struct genl_ops ieee802154_coordinator_ops[] = { IEEE802154_OP(IEEE802154_ASSOCIATE_REQ, ieee802154_associate_req), IEEE802154_OP(IEEE802154_ASSOCIATE_RESP, ieee802154_associate_resp), IEEE802154_OP(IEEE802154_DISASSOCIATE_REQ, ieee802154_disassociate_req), IEEE802154_OP(IEEE802154_SCAN_REQ, ieee802154_scan_req), IEEE802154_OP(IEEE802154_START_REQ, ieee802154_start_req), IEEE802154_DUMP(IEEE802154_LIST_IFACE, ieee802154_list_iface, ieee802154_dump_iface), }; static int __init ieee802154_nl_init(void) Loading