static int brc_genl_query(struct sk_buff *skb, struct genl_info *info) { int err = -EINVAL; struct sk_buff *ans_skb; void *data; ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!ans_skb) return -ENOMEM; data = genlmsg_put_reply(ans_skb, info, &brc_genl_family, 0, BRC_GENL_C_QUERY_MC); if (data == NULL) { err = -ENOMEM; goto err; } NLA_PUT_U32(ans_skb, BRC_GENL_A_MC_GROUP, brc_mc_group.id); genlmsg_end(ans_skb, data); return genlmsg_reply(ans_skb, info); err: nla_put_failure: kfree_skb(ans_skb); return err; }
static int ieee802154_list_iface(struct sk_buff *skb, struct genl_info *info) { /* */ 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_reply(msg, info); out_free: nlmsg_free(msg); out_dev: dev_put(dev); return rc; }
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_DEFAULT_SIZE, GFP_KERNEL); if (!msg) goto out_dev; rc = ieee802154_nl_fill_iface(msg, genl_info_snd_portid(info), info->snd_seq, 0, dev); if (rc < 0) goto out_free; dev_put(dev); return genlmsg_reply(msg, info); out_free: nlmsg_free(msg); out_dev: dev_put(dev); return rc; }
static int ixgbe_nl_reply(u8 value, u8 cmd, u8 attr, struct genl_info *info) { struct sk_buff *dcb_skb = NULL; void *data; int ret; dcb_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!dcb_skb) return -EINVAL; data = genlmsg_put_reply(dcb_skb, info, &dcb_family, 0, cmd); if (!data) goto err; ret = nla_put_u8(dcb_skb, attr, value); if (ret) goto err; /* end the message, assign the nlmsg_len. */ genlmsg_end(dcb_skb, data); ret = genlmsg_reply(dcb_skb, info); if (ret) goto err; return 0; err: kfree(dcb_skb); return -EINVAL; }
/** * netlbl_unlabel_list - Handle a LIST message * @skb: the NETLINK buffer * @info: the Generic NETLINK info block * * Description: * Process a user generated LIST message and respond with the current status. * Returns zero on success, negative values on failure. * */ static int netlbl_unlabel_list(struct sk_buff *skb, struct genl_info *info) { int ret_val = -EINVAL; struct sk_buff *ans_skb; void *data; ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (ans_skb == NULL) goto list_failure; data = genlmsg_put_reply(ans_skb, info, &netlbl_unlabel_gnl_family, 0, NLBL_UNLABEL_C_LIST); if (data == NULL) { ret_val = -ENOMEM; goto list_failure; } rcu_read_lock(); ret_val = nla_put_u8(ans_skb, NLBL_UNLABEL_A_ACPTFLG, netlabel_unlabel_acceptflg); rcu_read_unlock(); if (ret_val != 0) goto list_failure; genlmsg_end(ans_skb, data); ret_val = genlmsg_reply(ans_skb, info); if (ret_val != 0) goto list_failure; return 0; list_failure: kfree(ans_skb); return ret_val; }
static int wl1251_nl_reg_read(struct sk_buff *skb, struct genl_info *info) { struct wl1251 *wl; u32 addr, val; int ret = 0; struct sk_buff *msg; void *hdr; if (!info->attrs[WL1251_NL_ATTR_REG_ADDR]) return -EINVAL; msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); if (!msg) return -ENOMEM; wl = ifname_to_wl1251(&init_net, info); if (wl == NULL) { wl1251_error("wl1251 not found"); return -EINVAL; } addr = nla_get_u32(info->attrs[WL1251_NL_ATTR_REG_ADDR]); mutex_lock(&wl->mutex); val = wl1251_reg_read32(wl, addr); mutex_unlock(&wl->mutex); hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq, &wl1251_nl_family, 0, WL1251_NL_CMD_PHY_REG_READ); if (IS_ERR(hdr)) { ret = PTR_ERR(hdr); goto nla_put_failure; } NLA_PUT_STRING(msg, WL1251_NL_ATTR_IFNAME, nla_data(info->attrs[WL1251_NL_ATTR_IFNAME])); NLA_PUT_U32(msg, WL1251_NL_ATTR_REG_VAL, val); ret = genlmsg_end(msg, hdr); if (ret < 0) { wl1251_error("%s() failed", __func__); goto nla_put_failure; } return genlmsg_reply(msg, info); nla_put_failure: nlmsg_free(msg); return ret; }
int ieee802154_nl_reply(struct sk_buff *msg, struct genl_info *info) { /* XXX: nlh is right at the start of msg */ void *hdr = genlmsg_data(NLMSG_DATA(msg->data)); if (genlmsg_end(msg, hdr) < 0) goto out; return genlmsg_reply(msg, info); out: nlmsg_free(msg); return -ENOBUFS; }
int ieee802154_nl_reply(struct sk_buff *msg, struct genl_info *info) { struct nlmsghdr *nlh = nlmsg_hdr(msg); void *hdr = genlmsg_data(nlmsg_data(nlh)); if (genlmsg_end(msg, hdr) < 0) goto out; return genlmsg_reply(msg, info); out: nlmsg_free(msg); return -ENOBUFS; }
int tipc_nl_bearer_get(struct sk_buff *skb, struct genl_info *info) { int err; char *name; struct sk_buff *rep; struct tipc_bearer *bearer; struct tipc_nl_msg msg; struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1]; struct net *net = genl_info_net(info); if (!info->attrs[TIPC_NLA_BEARER]) return -EINVAL; err = nla_parse_nested(attrs, TIPC_NLA_BEARER_MAX, info->attrs[TIPC_NLA_BEARER], tipc_nl_bearer_policy); if (err) return err; if (!attrs[TIPC_NLA_BEARER_NAME]) return -EINVAL; name = nla_data(attrs[TIPC_NLA_BEARER_NAME]); rep = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); if (!rep) return -ENOMEM; msg.skb = rep; msg.portid = info->snd_portid; msg.seq = info->snd_seq; rtnl_lock(); bearer = tipc_bearer_find(net, name); if (!bearer) { err = -EINVAL; goto err_out; } err = __tipc_nl_add_bearer(&msg, bearer); if (err) goto err_out; rtnl_unlock(); return genlmsg_reply(rep, info); err_out: rtnl_unlock(); nlmsg_free(rep); return err; }
int tipc_nl_media_get(struct sk_buff *skb, struct genl_info *info) { int err; char *name; struct tipc_nl_msg msg; struct tipc_media *media; struct sk_buff *rep; struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1]; if (!info->attrs[TIPC_NLA_MEDIA]) return -EINVAL; err = nla_parse_nested(attrs, TIPC_NLA_MEDIA_MAX, info->attrs[TIPC_NLA_MEDIA], tipc_nl_media_policy); if (err) return err; if (!attrs[TIPC_NLA_MEDIA_NAME]) return -EINVAL; name = nla_data(attrs[TIPC_NLA_MEDIA_NAME]); rep = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); if (!rep) return -ENOMEM; msg.skb = rep; msg.portid = info->snd_portid; msg.seq = info->snd_seq; rtnl_lock(); media = tipc_media_find(name); if (!media) { err = -EINVAL; goto err_out; } err = __tipc_nl_add_media(&msg, media); if (err) goto err_out; rtnl_unlock(); return genlmsg_reply(rep, info); err_out: rtnl_unlock(); nlmsg_free(rep); return err; }
static int irda_nl_get_mode(struct sk_buff *skb, struct genl_info *info) { struct net_device * dev; struct irlap_cb * irlap; struct sk_buff *msg; void *hdr; int ret = -ENOBUFS; dev = ifname_to_netdev(&init_net, info); if (!dev) return -ENODEV; msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!msg) { dev_put(dev); return -ENOMEM; } irlap = (struct irlap_cb *)dev->atalk_ptr; if (!irlap) { ret = -ENODEV; goto err_out; } hdr = genlmsg_put(msg, info->snd_portid, info->snd_seq, &irda_nl_family, 0, IRDA_NL_CMD_GET_MODE); if (hdr == NULL) { ret = -EMSGSIZE; goto err_out; } if(nla_put_string(msg, IRDA_NL_ATTR_IFNAME, dev->name)) goto err_out; if(nla_put_u32(msg, IRDA_NL_ATTR_MODE, irlap->mode)) goto err_out; genlmsg_end(msg, hdr); return genlmsg_reply(msg, info); err_out: nlmsg_free(msg); dev_put(dev); return ret; }
static int kg2_genl_get_daemon_pid(struct sk_buff * skb, struct genl_info * info) { int ret = 0; void * hdr; struct sk_buff * msg; printk(KERN_INFO "kg2: Send daemon PID to user: %u\n", info->snd_pid); if (g_daemon_pid == 0) return -EINVAL; // Allocate message msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); if (msg == NULL) return -ENOMEM; // Set message header hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq, &kg2_genl_family, 0, KG2_GENL_CMD_SET_DAEMON_PID); if (hdr == NULL) { ret = -EMSGSIZE; goto err; } // Set message payload ret = nla_put_u32(msg, KG2_GENL_ATTR_PID, g_daemon_pid); if (ret) { ret = -ENOBUFS; goto err; } // Finalize message genlmsg_end(msg, hdr); // Reply message return genlmsg_reply(msg, info); err: nlmsg_free(msg); return ret; }
static int ipctl_reply(struct sk_buff *skb, struct genl_info *info, int property, int ifIndex, int value) { struct sk_buff *skb_reply; void *msg_head; int rc = 0; pr_debug("ipctl: reply start\n"); skb_reply = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); if (skb_reply == NULL) goto out; msg_head = genlmsg_put(skb_reply, 0, info->snd_seq, &ipctl_gnl_family, 0, IPCTL_CMD_GET); if (msg_head == NULL) { rc = -ENOMEM; goto out; } rc = nla_put_u32(skb_reply, IPCTL_ATTR_PROPERTY, property); if (rc != 0) goto out; rc = nla_put_u32(skb_reply, IPCTL_ATTR_IFINDEX, ifIndex); if (rc != 0) goto out; rc = nla_put_u8(skb_reply, IPCTL_ATTR_VALUE, value); if (rc != 0) goto out; /* finalize the message */ genlmsg_end(skb_reply, msg_head); rc = genlmsg_reply(skb_reply , info); if (rc != 0) goto out; return 0; out: pr_warning("ipctl: Error occured in reply: %d\n", rc); return rc; }
static int ieee802154_list_phy(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 wpan_phy *phy; const char *name; int rc = -ENOBUFS; pr_debug("%s\n", __func__); if (!info->attrs[IEEE802154_ATTR_PHY_NAME]) return -EINVAL; name = nla_data(info->attrs[IEEE802154_ATTR_PHY_NAME]); if (name[nla_len(info->attrs[IEEE802154_ATTR_PHY_NAME]) - 1] != '\0') return -EINVAL; /* phy name should be null-terminated */ phy = wpan_phy_find(name); if (!phy) return -ENODEV; msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); if (!msg) goto out_dev; rc = ieee802154_nl_fill_phy(msg, info->snd_pid, info->snd_seq, 0, phy); if (rc < 0) goto out_free; wpan_phy_put(phy); return genlmsg_reply(msg, info); out_free: nlmsg_free(msg); out_dev: wpan_phy_put(phy); return rc; }
/* hello world from the inner space */ int hello_world(struct sk_buff *request, struct genl_info *info) { struct sk_buff *reply; int rc; void *msg_head; if (info == NULL) goto out; /* send a message back*/ /* allocate some memory, since the size is not yet known use NLMSG_GOODSIZE*/ reply = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); if (reply == NULL) goto out; msg_head = genlmsg_put_reply(reply, info, &exmpl_gnl_family, 0, info->genlhdr->cmd); if (msg_head == NULL) { rc = -ENOMEM; goto out; } /* add a EXMPL_MSG attribute (actual value to be sent) */ rc = nla_put_string(reply, EXMPL_MSG, "hello world from kernel space"); if (rc != 0) goto out; /* finalize the message */ genlmsg_end(reply, msg_head); /* send the message back */ rc = genlmsg_reply(reply, info); if (rc != 0) goto out; return 0; out: printk("an error occured in hello_world:\n"); return 0; }
static int nfc_genl_get_device(struct sk_buff *skb, struct genl_info *info) { struct sk_buff *msg; struct nfc_dev *dev; u32 idx; int rc = -ENOBUFS; if (!info->attrs[NFC_ATTR_DEVICE_INDEX]) return -EINVAL; idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]); dev = nfc_get_device(idx); if (!dev) return -ENODEV; msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); if (!msg) { rc = -ENOMEM; goto out_putdev; } rc = nfc_genl_send_device(msg, dev, info->snd_pid, info->snd_seq, NULL, 0); if (rc < 0) goto out_free; nfc_put_device(dev); return genlmsg_reply(msg, info); out_free: nlmsg_free(msg); out_putdev: nfc_put_device(dev); return rc; }
static int seg6_genl_get_tunsrc(struct sk_buff *skb, struct genl_info *info) { struct net *net = genl_info_net(info); struct in6_addr *tun_src; struct sk_buff *msg; void *hdr; msg = genlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!msg) return -ENOMEM; hdr = genlmsg_put(msg, info->snd_portid, info->snd_seq, &seg6_genl_family, 0, SEG6_CMD_GET_TUNSRC); if (!hdr) goto free_msg; rcu_read_lock(); tun_src = rcu_dereference(seg6_pernet(net)->tun_src); if (nla_put(msg, SEG6_ATTR_DST, sizeof(struct in6_addr), tun_src)) goto nla_put_failure; rcu_read_unlock(); genlmsg_end(msg, hdr); genlmsg_reply(msg, info); return 0; nla_put_failure: rcu_read_unlock(); genlmsg_cancel(msg, hdr); free_msg: nlmsg_free(msg); return -ENOMEM; }
static int ixgbe_dcb_pg_gcfg(struct sk_buff *skb, struct genl_info *info, int dir) { void *data; struct sk_buff *dcb_skb = NULL; struct nlattr *pg_nest, *param_nest, *tb; struct nlattr *pg_tb[IXGBE_DCB_PG_A_MAX + 1]; struct nlattr *param_tb[IXGBE_DCB_TC_A_PARAM_MAX + 1]; struct net_device *netdev = NULL; struct ixgbe_adapter *adapter = NULL; struct tc_configuration *tc_config = NULL; struct tc_bw_alloc *tc = NULL; int ret = -ENOMEM; int i, tc_max; if (!info->attrs[DCB_A_IFNAME] || !info->attrs[DCB_A_PG_CFG]) return -EINVAL; netdev = dev_get_by_name(&init_net, nla_data(info->attrs[DCB_A_IFNAME])); if (!netdev) return -EINVAL; ret = ixgbe_dcb_check_adapter(netdev); if (ret) goto err_out; else adapter = netdev_priv(netdev); ret = nla_parse_nested(pg_tb, IXGBE_DCB_PG_A_MAX, info->attrs[DCB_A_PG_CFG], dcb_pg_nest); if (ret) goto err; dcb_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!dcb_skb) goto err; data = genlmsg_put_reply(dcb_skb, info, &dcb_family, 0, (dir) ? DCB_C_PGRX_GCFG : DCB_C_PGTX_GCFG); if (!data) goto err; pg_nest = nla_nest_start(dcb_skb, DCB_A_PG_CFG); if (!pg_nest) goto err; tc_max = adapter->ring_feature[RING_F_DCB].indices; for (i = PG_A_TC_0; i < tc_max + PG_A_TC_0; i++) { if (!pg_tb[i] && !pg_tb[PG_A_TC_ALL]) continue; if (pg_tb[PG_A_TC_ALL]) tb = pg_tb[PG_A_TC_ALL]; else tb = pg_tb[i]; ret = nla_parse_nested(param_tb, IXGBE_DCB_TC_A_PARAM_MAX, tb, dcb_tc_param_nest); if (ret) goto err_pg; param_nest = nla_nest_start(dcb_skb, i); if (!param_nest) goto err_pg; tc_config = &adapter->dcb_cfg.tc_config[i - PG_A_TC_0]; tc = &adapter->dcb_cfg.tc_config[i - PG_A_TC_0].path[dir]; if (param_tb[TC_A_PARAM_STRICT_PRIO] || param_tb[TC_A_PARAM_ALL]) { ret = nla_put_u8(dcb_skb, TC_A_PARAM_STRICT_PRIO, tc->prio_type); if (ret) goto err_param; } if (param_tb[TC_A_PARAM_BW_GROUP_ID] || param_tb[TC_A_PARAM_ALL]) { ret = nla_put_u8(dcb_skb, TC_A_PARAM_BW_GROUP_ID, tc->bwg_id); if (ret) goto err_param; } if (param_tb[TC_A_PARAM_BW_PCT_IN_GROUP] || param_tb[TC_A_PARAM_ALL]) { ret = nla_put_u8(dcb_skb, TC_A_PARAM_BW_PCT_IN_GROUP, tc->bwg_percent); if (ret) goto err_param; } if (param_tb[TC_A_PARAM_UP_MAPPING] || param_tb[TC_A_PARAM_ALL]) { ret = nla_put_u8(dcb_skb, TC_A_PARAM_UP_MAPPING, tc->up_to_tc_bitmap); if (ret) goto err_param; } nla_nest_end(dcb_skb, param_nest); } for (i = PG_A_BWG_0; i < PG_A_BWG_MAX; i++) { if (!pg_tb[i] && !pg_tb[PG_A_BWG_ALL]) continue; ret = nla_put_u8(dcb_skb, i, adapter->dcb_cfg.bw_percentage[dir][i-PG_A_BWG_0]); if (ret) goto err_pg; } nla_nest_end(dcb_skb, pg_nest); genlmsg_end(dcb_skb, data); ret = genlmsg_reply(dcb_skb, info); if (ret) goto err; dev_put(netdev); return 0; err_param: DPRINTK(DRV, ERR, "Error in get pg %s.\n", dir?"rx":"tx"); nla_nest_cancel(dcb_skb, param_nest); err_pg: nla_nest_cancel(dcb_skb, pg_nest); err: kfree(dcb_skb); err_out: dev_put(netdev); return ret; }
static int ixgbe_dcb_gperm_hwaddr(struct sk_buff *skb, struct genl_info *info) { void *data; struct sk_buff *dcb_skb = NULL; struct nlattr *tb[IXGBE_DCB_PERM_HW_A_MAX + 1], *nest; struct net_device *netdev = NULL; struct ixgbe_adapter *adapter = NULL; struct ixgbe_hw *hw = NULL; int ret = -ENOMEM; int i; if (!info->attrs[DCB_A_IFNAME] || !info->attrs[DCB_A_PERM_HWADDR]) return -EINVAL; netdev = dev_get_by_name(&init_net, nla_data(info->attrs[DCB_A_IFNAME])); if (!netdev) return -EINVAL; ret = ixgbe_dcb_check_adapter(netdev); if (ret) goto err_out; else adapter = netdev_priv(netdev); hw = &adapter->hw; ret = nla_parse_nested(tb, IXGBE_DCB_PERM_HW_A_MAX, info->attrs[DCB_A_PERM_HWADDR], dcb_perm_hwaddr_nest); if (ret) goto err; dcb_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!dcb_skb) goto err; data = genlmsg_put_reply(dcb_skb, info, &dcb_family, 0, DCB_C_GPERM_HWADDR); if (!data) goto err; nest = nla_nest_start(dcb_skb, DCB_A_PERM_HWADDR); if (!nest) goto err; for (i = 0; i < netdev->addr_len; i++) { if (!tb[i+PERM_HW_A_0] && !tb[PERM_HW_A_ALL]) goto err; ret = nla_put_u8(dcb_skb, DCB_A_PERM_HWADDR, hw->mac.perm_addr[i]); if (ret) { nla_nest_cancel(dcb_skb, nest); goto err; } } nla_nest_end(dcb_skb, nest); genlmsg_end(dcb_skb, data); ret = genlmsg_reply(dcb_skb, info); if (ret) goto err; dev_put(netdev); return 0; err: DPRINTK(DRV, ERR, "Error in get permanent hwaddr.\n"); kfree(dcb_skb); err_out: dev_put(netdev); return ret; }
static int kfm_genl_get_cmd(struct sk_buff *skb, struct genl_info *info) { struct sk_buff *msg; void *reply; int ret, cmd, reply_cmd; cmd = info->genlhdr->cmd; switch (cmd) { case KFM_CMD_GET_INFO: reply_cmd = KFM_CMD_GET_INFO_REPLY; break; case KFM_CMD_GET_CACHE_INFO: reply_cmd = KFM_CMD_GET_CACHE_INFO_REPLY; break; case KFM_CMD_GET_MEMPAGE_INFO: reply_cmd = KFM_CMD_GET_MEMPAGE_INFO_REPLY; break; default: KFM_ERR("unknown Generic Netlink command\n"); return -EINVAL; } msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!msg) return -ENOMEM; mutex_lock(&__kfm_mutex); // need lock?? reply = genlmsg_put_reply(msg, info, &kfm_genl_family, 0, reply_cmd); if (reply == NULL) goto nla_put_failure; switch (cmd) { case KFM_CMD_GET_INFO: if (nla_put_u32(msg, KFM_INFO_ATTR_VERSION, KFM_VERSION_CODE)) goto nla_put_failure; break; case KFM_CMD_GET_CACHE_INFO: { struct kfm_cache_u ucache; ret = kfm_genl_parse_cache(&ucache, info->attrs); if (ret) goto out_err; if((ret = kfm_cache_status_on_cpu(ucache.cpu)) < 0) goto out_err; ucache.status = ret; ret = kfm_genl_fill_cache(msg, &ucache); if (ret) goto nla_put_failure; break; } case KFM_CMD_GET_MEMPAGE_INFO: { struct kfm_mempage_u umempage; ret = kfm_genl_parse_mempage(&umempage, info->attrs); if (ret) goto out_err; if(kfm_get_mempage_info(umempage.addr, &umempage)) goto out_err; ret = kfm_genl_fill_mempage(msg, &umempage); if (ret) goto nla_put_failure; break; } /* for other get cmd */ } genlmsg_end(msg, reply); ret = genlmsg_reply(msg, info); goto out; nla_put_failure: pr_err("not enough space in Netlink message\n"); ret = -EMSGSIZE; out_err: nlmsg_free(msg); out: mutex_unlock(&__kfm_mutex); return ret; }
static int wl1251_nl_test_cmd(struct sk_buff *skb, struct genl_info *info) { struct wl1251 *wl; struct wl1251_command *cmd; char *buf; int buf_len, ret, cmd_len; u8 answer; if (!info->attrs[WL1251_NL_ATTR_CMD_TEST_PARAM]) return -EINVAL; wl = ifname_to_wl1251(&init_net, info); if (wl == NULL) { wl1251_error("wl1251 not found"); return -EINVAL; } cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (!cmd) return -ENOMEM; buf = nla_data(info->attrs[WL1251_NL_ATTR_CMD_TEST_PARAM]); buf_len = nla_len(info->attrs[WL1251_NL_ATTR_CMD_TEST_PARAM]); answer = nla_get_u8(info->attrs[WL1251_NL_ATTR_CMD_TEST_ANSWER]); cmd->header.id = CMD_TEST; memcpy(cmd->parameters, buf, buf_len); cmd_len = sizeof(struct wl1251_cmd_header) + buf_len; mutex_lock(&wl->mutex); ret = wl1251_cmd_test(wl, cmd, cmd_len, answer); mutex_unlock(&wl->mutex); if (ret < 0) { wl1251_error("%s() failed", __func__); goto out; } if (answer) { struct sk_buff *msg; void *hdr; msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); if (!msg) { ret = -ENOMEM; goto out; } hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq, &wl1251_nl_family, 0, WL1251_NL_CMD_TEST); if (IS_ERR(hdr)) { ret = PTR_ERR(hdr); goto nla_put_failure; } NLA_PUT_STRING(msg, WL1251_NL_ATTR_IFNAME, nla_data(info->attrs[WL1251_NL_ATTR_IFNAME])); NLA_PUT(msg, WL1251_NL_ATTR_CMD_TEST_ANSWER, sizeof(*cmd), cmd); ret = genlmsg_end(msg, hdr); if (ret < 0) { wl1251_error("%s() failed", __func__); goto nla_put_failure; } wl1251_debug(DEBUG_NETLINK, "TEST cmd sent, answer"); ret = genlmsg_reply(msg, info); goto out; nla_put_failure: nlmsg_free(msg); } else wl1251_debug(DEBUG_NETLINK, "TEST cmd sent"); out: kfree(cmd); return ret; }
static int wl1251_nl_interrogate(struct sk_buff *skb, struct genl_info *info) { struct wl1251 *wl; struct sk_buff *msg; int ret = -ENOBUFS, cmd_ie, cmd_ie_len; struct wl1251_command *cmd; void *hdr; if (!info->attrs[WL1251_NL_ATTR_CMD_IE]) return -EINVAL; if (!info->attrs[WL1251_NL_ATTR_CMD_IE_LEN]) return -EINVAL; cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (!cmd) return -ENOMEM; msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); if (!msg) return -ENOMEM; wl = ifname_to_wl1251(&init_net, info); if (wl == NULL) { wl1251_error("wl1251 not found"); ret = -EINVAL; goto nla_put_failure; } /* acx id */ cmd_ie = nla_get_u32(info->attrs[WL1251_NL_ATTR_CMD_IE]); /* maximum length of acx, including all headers */ cmd_ie_len = nla_get_u32(info->attrs[WL1251_NL_ATTR_CMD_IE_LEN]); wl1251_debug(DEBUG_NETLINK, "Getting IE 0x%x (len %d)", cmd_ie, cmd_ie_len); mutex_lock(&wl->mutex); ret = wl1251_cmd_interrogate(wl, cmd_ie, cmd, cmd_ie_len); mutex_unlock(&wl->mutex); if (ret < 0) { wl1251_error("%s() failed", __func__); goto nla_put_failure; } hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq, &wl1251_nl_family, 0, WL1251_NL_CMD_INTERROGATE); if (IS_ERR(hdr)) { ret = PTR_ERR(hdr); goto nla_put_failure; } NLA_PUT_STRING(msg, WL1251_NL_ATTR_IFNAME, nla_data(info->attrs[WL1251_NL_ATTR_IFNAME])); NLA_PUT(msg, WL1251_NL_ATTR_CMD_IE_ANSWER, cmd_ie_len, cmd); ret = genlmsg_end(msg, hdr); if (ret < 0) { wl1251_error("%s() failed", __func__); goto nla_put_failure; } kfree(cmd); return genlmsg_reply(msg, info); nla_put_failure: kfree(cmd); nlmsg_free(msg); return ret; }
static int wl1251_nl_phy_reg_read(struct sk_buff *skb, struct genl_info *info) { struct wl1251 *wl; struct sk_buff *msg; u32 reg_addr, *reg_value = NULL; int ret = 0; void *hdr; if (!info->attrs[WL1251_NL_ATTR_REG_ADDR]) return -EINVAL; msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); if (!msg) return -ENOMEM; wl = ifname_to_wl1251(&init_net, info); if (wl == NULL) { wl1251_error("wl1251 not found"); ret = -EINVAL; goto nla_put_failure; } reg_value = kmalloc(sizeof(*reg_value), GFP_KERNEL); if (!reg_value) { ret = -ENOMEM; goto nla_put_failure; } reg_addr = nla_get_u32(info->attrs[WL1251_NL_ATTR_REG_ADDR]); wl1251_debug(DEBUG_NETLINK, "Reading PHY reg 0x%x", reg_addr); mutex_lock(&wl->mutex); ret = wl1251_cmd_read_memory(wl, reg_addr, reg_value, sizeof(*reg_value)); mutex_unlock(&wl->mutex); if (ret < 0) { wl1251_error("%s() failed", __func__); goto nla_put_failure; } hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq, &wl1251_nl_family, 0, WL1251_NL_CMD_PHY_REG_READ); if (IS_ERR(hdr)) { ret = PTR_ERR(hdr); goto nla_put_failure; } NLA_PUT_STRING(msg, WL1251_NL_ATTR_IFNAME, nla_data(info->attrs[WL1251_NL_ATTR_IFNAME])); NLA_PUT_U32(msg, WL1251_NL_ATTR_REG_VAL, *reg_value); ret = genlmsg_end(msg, hdr); if (ret < 0) { wl1251_error("%s() failed", __func__); goto nla_put_failure; } kfree(reg_value); return genlmsg_reply(msg, info); nla_put_failure: nlmsg_free(msg); kfree(reg_value); return ret; }
static int ixgbe_dcb_gpfccfg(struct sk_buff *skb, struct genl_info *info) { void *data; struct sk_buff *dcb_skb = NULL; struct nlattr *tb[IXGBE_DCB_PFC_A_UP_MAX + 1], *nest; struct net_device *netdev = NULL; struct ixgbe_adapter *adapter = NULL; int ret = -ENOMEM; int i; if (!info->attrs[DCB_A_IFNAME] || !info->attrs[DCB_A_PFC_CFG]) return -EINVAL; netdev = dev_get_by_name(&init_net, nla_data(info->attrs[DCB_A_IFNAME])); if (!netdev) return -EINVAL; ret = ixgbe_dcb_check_adapter(netdev); if (ret) goto err_out; else adapter = netdev_priv(netdev); ret = nla_parse_nested(tb, IXGBE_DCB_PFC_A_UP_MAX, info->attrs[DCB_A_PFC_CFG], dcb_pfc_up_nest); if (ret) goto err; dcb_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!dcb_skb) goto err; data = genlmsg_put_reply(dcb_skb, info, &dcb_family, 0, DCB_C_PFC_GCFG); if (!data) goto err; nest = nla_nest_start(dcb_skb, DCB_A_PFC_CFG); if (!nest) goto err; for (i = PFC_A_UP_0; i < PFC_A_UP_MAX; i++) { if (!tb[i] && !tb[PFC_A_UP_ALL]) continue; ret = nla_put_u8(dcb_skb, i, adapter->dcb_cfg.tc_config[i-PFC_A_UP_0].dcb_pfc); if (ret) { nla_nest_cancel(dcb_skb, nest); goto err; } } nla_nest_end(dcb_skb, nest); genlmsg_end(dcb_skb, data); ret = genlmsg_reply(dcb_skb, info); if (ret) goto err; dev_put(netdev); return 0; err: DPRINTK(DRV, ERR, "Error in get pfc stats.\n"); kfree(dcb_skb); err_out: dev_put(netdev); return ret; }