goto errout;
}
+ if (ops->dumpit)
+ ops->flags |= GENL_CMD_CAP_DUMP;
+ if (ops->doit)
+ ops->flags |= GENL_CMD_CAP_DO;
+ if (ops->policy)
+ ops->flags |= GENL_CMD_CAP_HASPOL;
+
genl_lock();
list_add_tail(&ops->ops_list, &family->ops_list);
genl_unlock();
return -ENOENT;
}
-static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
- int *errp)
+static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
{
struct genl_ops *ops;
struct genl_family *family;
struct genl_info info;
struct genlmsghdr *hdr = nlmsg_data(nlh);
- int hdrlen, err = -EINVAL;
-
- if (!(nlh->nlmsg_flags & NLM_F_REQUEST))
- goto ignore;
-
- if (nlh->nlmsg_type < NLMSG_MIN_TYPE)
- goto ignore;
+ int hdrlen, err;
- family = genl_family_find_byid(nlh->nlmsg_type);
- if (family == NULL) {
- err = -ENOENT;
- goto errout;
- }
+ family = genl_family_find_byid(nlh->nlmsg_type);
+ if (family == NULL)
+ return -ENOENT;
hdrlen = GENL_HDRLEN + family->hdrsize;
if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen))
- goto errout;
+ return -EINVAL;
ops = genl_get_cmd(hdr->cmd, family);
- if (ops == NULL) {
- err = -EOPNOTSUPP;
- goto errout;
- }
+ if (ops == NULL)
+ return -EOPNOTSUPP;
- if ((ops->flags & GENL_ADMIN_PERM) && security_netlink_recv(skb, CAP_NET_ADMIN)) {
- err = -EPERM;
- goto errout;
- }
+ if ((ops->flags & GENL_ADMIN_PERM) &&
+ security_netlink_recv(skb, CAP_NET_ADMIN))
+ return -EPERM;
if (nlh->nlmsg_flags & NLM_F_DUMP) {
- if (ops->dumpit == NULL) {
- err = -EOPNOTSUPP;
- goto errout;
- }
+ if (ops->dumpit == NULL)
+ return -EOPNOTSUPP;
- *errp = err = netlink_dump_start(genl_sock, skb, nlh,
- ops->dumpit, NULL);
- if (err == 0)
- skb_pull(skb, min(NLMSG_ALIGN(nlh->nlmsg_len),
- skb->len));
- return -1;
+ return netlink_dump_start(genl_sock, skb, nlh,
+ ops->dumpit, ops->done);
}
- if (ops->doit == NULL) {
- err = -EOPNOTSUPP;
- goto errout;
- }
+ if (ops->doit == NULL)
+ return -EOPNOTSUPP;
if (family->attrbuf) {
err = nlmsg_parse(nlh, hdrlen, family->attrbuf, family->maxattr,
ops->policy);
if (err < 0)
- goto errout;
+ return err;
}
info.snd_seq = nlh->nlmsg_seq;
info.userhdr = nlmsg_data(nlh) + GENL_HDRLEN;
info.attrs = family->attrbuf;
- *errp = err = ops->doit(skb, &info);
- return err;
-
-ignore:
- return 0;
-
-errout:
- *errp = err;
- return -1;
+ return ops->doit(skb, &info);
}
static void genl_rcv(struct sock *sk, int len)
static struct genl_family genl_ctrl = {
.id = GENL_ID_CTRL,
.name = "nlctrl",
- .version = 0x1,
+ .version = 0x2,
.maxattr = CTRL_ATTR_MAX,
};
static int ctrl_fill_info(struct genl_family *family, u32 pid, u32 seq,
u32 flags, struct sk_buff *skb, u8 cmd)
{
- struct nlattr *nla_ops;
- struct genl_ops *ops;
void *hdr;
- int idx = 1;
hdr = genlmsg_put(skb, pid, seq, &genl_ctrl, flags, cmd);
if (hdr == NULL)
NLA_PUT_U32(skb, CTRL_ATTR_HDRSIZE, family->hdrsize);
NLA_PUT_U32(skb, CTRL_ATTR_MAXATTR, family->maxattr);
- nla_ops = nla_nest_start(skb, CTRL_ATTR_OPS);
- if (nla_ops == NULL)
- goto nla_put_failure;
+ if (!list_empty(&family->ops_list)) {
+ struct nlattr *nla_ops;
+ struct genl_ops *ops;
+ int idx = 1;
- list_for_each_entry(ops, &family->ops_list, ops_list) {
- struct nlattr *nest;
-
- nest = nla_nest_start(skb, idx++);
- if (nest == NULL)
+ nla_ops = nla_nest_start(skb, CTRL_ATTR_OPS);
+ if (nla_ops == NULL)
goto nla_put_failure;
- NLA_PUT_U32(skb, CTRL_ATTR_OP_ID, ops->cmd);
- NLA_PUT_U32(skb, CTRL_ATTR_OP_FLAGS, ops->flags);
+ list_for_each_entry(ops, &family->ops_list, ops_list) {
+ struct nlattr *nest;
- if (ops->policy)
- NLA_PUT_FLAG(skb, CTRL_ATTR_OP_POLICY);
+ nest = nla_nest_start(skb, idx++);
+ if (nest == NULL)
+ goto nla_put_failure;
- if (ops->doit)
- NLA_PUT_FLAG(skb, CTRL_ATTR_OP_DOIT);
+ NLA_PUT_U32(skb, CTRL_ATTR_OP_ID, ops->cmd);
+ NLA_PUT_U32(skb, CTRL_ATTR_OP_FLAGS, ops->flags);
- if (ops->dumpit)
- NLA_PUT_FLAG(skb, CTRL_ATTR_OP_DUMPIT);
+ nla_nest_end(skb, nest);
+ }
- nla_nest_end(skb, nest);
+ nla_nest_end(skb, nla_ops);
}
- nla_nest_end(skb, nla_ops);
-
return genlmsg_end(skb, hdr);
nla_put_failure:
netlink_set_nonroot(NETLINK_GENERIC, NL_NONROOT_RECV);
genl_sock = netlink_kernel_create(NETLINK_GENERIC, GENL_MAX_ID,
- genl_rcv, THIS_MODULE);
+ genl_rcv, NULL, THIS_MODULE);
if (genl_sock == NULL)
panic("GENL: Cannot initialize generic netlink\n");