* Johannes Berg <[EMAIL PROTECTED]> 2006-08-22 15:52
> +static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
> + [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 },
> + [NL80211_ATTR_WIPHY] = { .type = NLA_U32 },
> + [NL80211_ATTR_FLAGS] = { .type = NLA_U32 },
> + [NL80211_ATTR_QUEUE] = { .type = NLA_U32 },
> + [NL80211_ATTR_FRAME] = { .type = NLA_STRING, .len = 2500 },
Might want to put this in a header so userspace can see the limit.
> + [NL80211_ATTR_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ-1 },
> +};
> +
> +static int nl80211_get_commands(struct sk_buff *skb, struct genl_info *info)
> +{
> + struct nl80211_registered_driver *drv;
> + struct sk_buff *msg;
> + void *hdr;
> + int err;
> + struct nlattr *start;
> + u8 *data;
> +
> + drv = nl80211_drv_from_info_with_locking(info);
> + if (IS_ERR(drv))
> + return PTR_ERR(drv);
> +
> + hdr = nl80211msg_new(&msg, info->snd_pid, info->snd_seq, 0,
> + NL80211_CMD_GET_COMMANDS);
This isn't wrong in particular but usually we reverse the
meaning of the command when sending back answers, i.e. in
your case you'd define CMD_GET_COMMAND and CMD_NEW_COMMAND
with the following behaviour:
CMD_GET_COMMAND
Search for command specified by the attributes and send
back a CMD_NEW_COMMAND message.
CMD_GET_COMMAND with NLM_F_DUMP
Iterate over all commands and send back a CMD_NEW_COMMAND
message for each command.
In your case I'd call it GET_CMDLIST and NEW_CMDLIST which
means you request a command list with GET_CMDLIST and
receive the answer with a CMD_NEWLIST message.
> + start = nla_nest_start(msg, NL80211_ATTR_CMDS);
> + if (!start)
> + goto nla_nest_failure;
> + data = nla_data(start);
> +
> + /* unconditionally allow some common commands we handle centrally */
> + skb_put(msg, 1);
> + *data++ = NL80211_CMD_GET_COMMANDS;
> + skb_put(msg, 1);
> + *data++ = NL80211_CMD_GET_WIPHYS;
> + skb_put(msg, 1);
> + *data++ = NL80211_CMD_GET_INTERFACES;
> +
> + CHECK_CMD(inject_packet, INJECT);
> + CHECK_CMD(add_virtual_intf, ADD_VIRTUAL_INTERFACE);
> + CHECK_CMD(del_virtual_intf, DEL_VIRTUAL_INTERFACE);
> +
> + nla_nest_end(msg, start);
I'd just use the command id as attribute type:
NLA_PUT_FLAG(msg, NL80211_CMD_GET_COMMANDS);
NLA_PUT_FLAG(msg, NL80211_CMD_GET_WIPHYS);
....
This makes checking avaibility of a command as easy as
accessing an array for userspace.
> + err = genlmsg_end(msg, hdr);
> + if (err)
> + goto msg_free;
genlmsg_end() can't fail, it just returns skb->len which
is only of importance while dumping to see if there is
still more to dump or not.
> +void *nl80211msg_new(struct sk_buff **skb, u32 pid, u32 seq, int flags, u8
> cmd)
> +{
> + void *hdr;
> +
> + *skb = nlmsg_new(NLMSG_GOODSIZE);
> + if (!*skb)
> + return ERR_PTR(-ENOBUFS);
> +
> + hdr = nl80211hdr_put(*skb, pid, seq, flags, cmd);
> + if (!hdr) {
> + nlmsg_free(*skb);
> + /* what would be a good error here? */
> + return ERR_PTR(-EINVAL);
> + }
ENOBUFS
You might want to send out notifications for various events such as the
additiona and deletion of virtual interfaces etc.
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html