/* * Exporting to user space over generic netlink * * Parse the reset command from user space, return error code. * * No attributes. */ static int wimax_gnl_doit_reset(struct sk_buff *skb, struct genl_info *info) { int result, ifindex; struct wimax_dev *wimax_dev; struct device *dev; d_fnstart(3, NULL, "(skb %p info %p)\n", skb, info); result = -ENODEV; if (info->attrs[WIMAX_GNL_RESET_IFIDX] == NULL) { printk(KERN_ERR "WIMAX_GNL_OP_RFKILL: can't find IFIDX " "attribute\n"); goto error_no_wimax_dev; } ifindex = nla_get_u32(info->attrs[WIMAX_GNL_RESET_IFIDX]); wimax_dev = wimax_dev_get_by_genl_info(info, ifindex); if (wimax_dev == NULL) goto error_no_wimax_dev; dev = wimax_dev_to_dev(wimax_dev); /* Execute the operation and send the result back to user space */ result = wimax_reset(wimax_dev); dev_put(wimax_dev->net_dev); error_no_wimax_dev: d_fnend(3, NULL, "(skb %p info %p) = %d\n", skb, info, result); return result; }
static int wimax_gnl_doit_state_get(struct sk_buff *skb, struct genl_info *info) { int result, ifindex; struct wimax_dev *wimax_dev; struct device *dev; d_fnstart(3, NULL, "(skb %p info %p)\n", skb, info); result = -ENODEV; if (info->attrs[WIMAX_GNL_STGET_IFIDX] == NULL) { printk(KERN_ERR "WIMAX_GNL_OP_STATE_GET: can't find IFIDX " "attribute\n"); goto error_no_wimax_dev; } ifindex = nla_get_u32(info->attrs[WIMAX_GNL_STGET_IFIDX]); wimax_dev = wimax_dev_get_by_genl_info(info, ifindex); if (wimax_dev == NULL) goto error_no_wimax_dev; dev = wimax_dev_to_dev(wimax_dev); result = wimax_state_get(wimax_dev); dev_put(wimax_dev->net_dev); error_no_wimax_dev: d_fnend(3, NULL, "(skb %p info %p) = %d\n", skb, info, result); return result; }
static int wimax_gnl_doit_rfkill(struct sk_buff *skb, struct genl_info *info) { int result, ifindex; struct wimax_dev *wimax_dev; struct device *dev; enum wimax_rf_state new_state; d_fnstart(3, NULL, "(skb %p info %p)\n", skb, info); result = -ENODEV; if (info->attrs[WIMAX_GNL_RFKILL_IFIDX] == NULL) { printk(KERN_ERR "WIMAX_GNL_OP_RFKILL: can't find IFIDX " "attribute\n"); goto error_no_wimax_dev; } ifindex = nla_get_u32(info->attrs[WIMAX_GNL_RFKILL_IFIDX]); wimax_dev = wimax_dev_get_by_genl_info(info, ifindex); if (wimax_dev == NULL) goto error_no_wimax_dev; dev = wimax_dev_to_dev(wimax_dev); result = -EINVAL; if (info->attrs[WIMAX_GNL_RFKILL_STATE] == NULL) { dev_err(dev, "WIMAX_GNL_RFKILL: can't find RFKILL_STATE " "attribute\n"); goto error_no_pid; } new_state = nla_get_u32(info->attrs[WIMAX_GNL_RFKILL_STATE]); /* */ result = wimax_rfkill(wimax_dev, new_state); error_no_pid: dev_put(wimax_dev->net_dev); error_no_wimax_dev: d_fnend(3, NULL, "(skb %p info %p) = %d\n", skb, info, result); return result; }
static int wimax_gnl_doit_msg_from_user(struct sk_buff *skb, struct genl_info *info) { int result, ifindex; struct wimax_dev *wimax_dev; struct device *dev; struct nlmsghdr *nlh = info->nlhdr; char *pipe_name; void *msg_buf; size_t msg_len; might_sleep(); d_fnstart(3, NULL, "(skb %p info %p)\n", skb, info); result = -ENODEV; if (info->attrs[WIMAX_GNL_MSG_IFIDX] == NULL) { printk(KERN_ERR "WIMAX_GNL_MSG_FROM_USER: can't find IFIDX " "attribute\n"); goto error_no_wimax_dev; } ifindex = nla_get_u32(info->attrs[WIMAX_GNL_MSG_IFIDX]); wimax_dev = wimax_dev_get_by_genl_info(info, ifindex); if (wimax_dev == NULL) goto error_no_wimax_dev; dev = wimax_dev_to_dev(wimax_dev); /* */ result = -EINVAL; if (info->attrs[WIMAX_GNL_MSG_DATA] == NULL) { dev_err(dev, "WIMAX_GNL_MSG_FROM_USER: can't find MSG_DATA " "attribute\n"); goto error_no_data; } msg_buf = nla_data(info->attrs[WIMAX_GNL_MSG_DATA]); msg_len = nla_len(info->attrs[WIMAX_GNL_MSG_DATA]); if (info->attrs[WIMAX_GNL_MSG_PIPE_NAME] == NULL) pipe_name = NULL; else { struct nlattr *attr = info->attrs[WIMAX_GNL_MSG_PIPE_NAME]; size_t attr_len = nla_len(attr); /* */ result = -ENOMEM; pipe_name = kstrndup(nla_data(attr), attr_len + 1, GFP_KERNEL); if (pipe_name == NULL) goto error_alloc; pipe_name[attr_len] = 0; } mutex_lock(&wimax_dev->mutex); result = wimax_dev_is_ready(wimax_dev); if (result == -ENOMEDIUM) result = 0; if (result < 0) goto error_not_ready; result = -ENOSYS; if (wimax_dev->op_msg_from_user == NULL) goto error_noop; d_printf(1, dev, "CRX: nlmsghdr len %u type %u flags 0x%04x seq 0x%x pid %u\n", nlh->nlmsg_len, nlh->nlmsg_type, nlh->nlmsg_flags, nlh->nlmsg_seq, nlh->nlmsg_pid); d_printf(1, dev, "CRX: wimax message %zu bytes\n", msg_len); d_dump(2, dev, msg_buf, msg_len); result = wimax_dev->op_msg_from_user(wimax_dev, pipe_name, msg_buf, msg_len, info); error_noop: error_not_ready: mutex_unlock(&wimax_dev->mutex); error_alloc: kfree(pipe_name); error_no_data: dev_put(wimax_dev->net_dev); error_no_wimax_dev: d_fnend(3, NULL, "(skb %p info %p) = %d\n", skb, info, result); return result; }