[NETFILTER] attribute count is an anttribute of message type, not subsytem

Prior to this patch, every nfnetlink subsystem had to specify it's
attribute count.  However, in reality the attribute count depends on the
message type within the subsystem, not the subsystem itself.  This patch
moves 'attr_count' from 'struct nfnetlink_subsys' into nfnl_callback to
fix this.

Signed-off-by: Harald Welte <[EMAIL PROTECTED]>

---
commit 9ae30513b70ed5325f66adc02788a7d6ef69cb1e
tree 993ba601e02c1be1e23896d4b62ac45de0bb7064
parent 5d03469be285d9bc2b82861d87c667cf5614132d
author Harald Welte <[EMAIL PROTECTED]> Di, 02 Aug 2005 12:17:57 +0200
committer Harald Welte <[EMAIL PROTECTED]> Di, 02 Aug 2005 12:17:57 +0200

 include/linux/netfilter/nfnetlink.h       |    4 ++--
 net/ipv4/netfilter/ip_conntrack_netlink.c |    9 +++++++--
 net/netfilter/nfnetlink.c                 |   20 ++++++++++++++++----
 net/netfilter/nfnetlink_log.c             |    5 +++--
 net/netfilter/nfnetlink_queue.c           |    4 +++-
 5 files changed, 31 insertions(+), 11 deletions(-)

diff --git a/include/linux/netfilter/nfnetlink.h 
b/include/linux/netfilter/nfnetlink.h
--- a/include/linux/netfilter/nfnetlink.h
+++ b/include/linux/netfilter/nfnetlink.h
@@ -85,9 +85,10 @@ struct nfgenmsg {
 
 struct nfnl_callback
 {
-       kernel_cap_t cap_required; /* capabilities required for this msg */
        int (*call)(struct sock *nl, struct sk_buff *skb, 
                struct nlmsghdr *nlh, struct nfattr *cda[], int *errp);
+       kernel_cap_t cap_required; /* capabilities required for this msg */
+       u_int16_t attr_count;   /* number of nfattr's */
 };
 
 struct nfnetlink_subsystem
@@ -95,7 +96,6 @@ struct nfnetlink_subsystem
        const char *name;
        __u8 subsys_id;         /* nfnetlink subsystem ID */
        __u8 cb_count;          /* number of callbacks */
-       u_int32_t attr_count;   /* number of nfattr's */
        struct nfnl_callback *cb; /* callback for individual types */
 };
 
diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c 
b/net/ipv4/netfilter/ip_conntrack_netlink.c
--- a/net/ipv4/netfilter/ip_conntrack_netlink.c
+++ b/net/ipv4/netfilter/ip_conntrack_netlink.c
@@ -1484,21 +1484,28 @@ static struct notifier_block ctnl_notifi
 
 static struct nfnl_callback ctnl_cb[IPCTNL_MSG_MAX] = {
        [IPCTNL_MSG_CT_NEW]             = { .call = ctnetlink_new_conntrack,
+                                           .attr_count = CTA_MAX,
                                            .cap_required = CAP_NET_ADMIN },
        [IPCTNL_MSG_CT_GET]             = { .call = ctnetlink_get_conntrack,
+                                           .attr_count = CTA_MAX,
                                            .cap_required = CAP_NET_ADMIN },
        [IPCTNL_MSG_CT_DELETE]          = { .call = ctnetlink_del_conntrack,
+                                           .attr_count = CTA_MAX,
                                            .cap_required = CAP_NET_ADMIN },
        [IPCTNL_MSG_CT_GET_CTRZERO]     = { .call = ctnetlink_get_conntrack,
+                                           .attr_count = CTA_MAX,
                                            .cap_required = CAP_NET_ADMIN },
 };
 
 static struct nfnl_callback ctnl_exp_cb[IPCTNL_MSG_MAX] = {
        [IPCTNL_MSG_EXP_GET]            = { .call = ctnetlink_get_expect,
+                                           .attr_count = CTA_EXPECT_MAX,
                                            .cap_required = CAP_NET_ADMIN },
        [IPCTNL_MSG_EXP_NEW]            = { .call = ctnetlink_new_expect,
+                                           .attr_count = CTA_EXPECT_MAX,
                                            .cap_required = CAP_NET_ADMIN },
        [IPCTNL_MSG_EXP_DELETE]         = { .call = ctnetlink_del_expect,
+                                           .attr_count = CTA_EXPECT_MAX,
                                            .cap_required = CAP_NET_ADMIN },
 };
 
@@ -1506,7 +1513,6 @@ static struct nfnetlink_subsystem ctnl_s
        .name                           = "conntrack",
        .subsys_id                      = NFNL_SUBSYS_CTNETLINK,
        .cb_count                       = IPCTNL_MSG_MAX,
-       .attr_count                     = CTA_MAX,
        .cb                             = ctnl_cb,
 };
 
@@ -1514,7 +1520,6 @@ static struct nfnetlink_subsystem ctnl_e
        .name                           = "conntrack_expect",
        .subsys_id                      = NFNL_SUBSYS_CTNETLINK_EXP,
        .cb_count                       = IPCTNL_MSG_EXP_MAX,
-       .attr_count                     = CTA_MAX,
        .cb                             = ctnl_exp_cb,
 };
 
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c
--- a/net/netfilter/nfnetlink.c
+++ b/net/netfilter/nfnetlink.c
@@ -155,8 +155,18 @@ nfnetlink_check_attributes(struct nfnetl
                           struct nlmsghdr *nlh, struct nfattr *cda[])
 {
        int min_len;
+       u_int16_t attr_count;
+       u_int8_t cb_id = NFNL_MSG_TYPE(nlh->nlmsg_type);
 
-       memset(cda, 0, sizeof(struct nfattr *) * subsys->attr_count);
+       if (unlikely(cb_id >= subsys->cb_count)) {
+               DEBUGP("msgtype %u >= %u, returning\n",
+                       cb_id, subsys->cb_count);
+               return -EINVAL;
+       }
+       
+       attr_count = subsys->cb[cb_id].attr_count;
+
+       memset(cda, 0, sizeof(struct nfattr *) * attr_count);
 
        /* check attribute lengths. */
        min_len = NLMSG_ALIGN(sizeof(struct nfgenmsg));
@@ -170,7 +180,7 @@ nfnetlink_check_attributes(struct nfnetl
                while (NFA_OK(attr, attrlen)) {
                        unsigned flavor = attr->nfa_type;
                        if (flavor) {
-                               if (flavor > subsys->attr_count)
+                               if (flavor > attr_count)
                                        return -EINVAL;
                                cda[flavor - 1] = attr;
                        }
@@ -256,9 +266,11 @@ static inline int nfnetlink_rcv_msg(stru
        }
 
        {
-               struct nfattr *cda[ss->attr_count];
+               u_int16_t attr_count = 
+                       ss->cb[NFNL_MSG_TYPE(nlh->nlmsg_type)].attr_count;
+               struct nfattr *cda[attr_count];
 
-               memset(cda, 0, ss->attr_count*sizeof(struct nfattr *));
+               memset(cda, 0, sizeof(struct nfattr *) * attr_count);
                
                err = nfnetlink_check_attributes(ss, nlh, cda);
                if (err < 0)
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -803,8 +803,10 @@ out_put:
 
 static struct nfnl_callback nfulnl_cb[NFULNL_MSG_MAX] = {
        [NFULNL_MSG_PACKET]     = { .call = nfulnl_recv_unsupp,
-                                   .cap_required = CAP_NET_ADMIN },
+                                   .attr_count = NFULA_MAX,
+                                   .cap_required = CAP_NET_ADMIN, },
        [NFULNL_MSG_CONFIG]     = { .call = nfulnl_recv_config,
+                                   .attr_count = NFULA_CFG_MAX,
                                    .cap_required = CAP_NET_ADMIN },
 };
 
@@ -812,7 +814,6 @@ static struct nfnetlink_subsystem nfulnl
        .name           = "log",
        .subsys_id      = NFNL_SUBSYS_ULOG,
        .cb_count       = NFULNL_MSG_MAX,
-       .attr_count     = NFULA_MAX,
        .cb             = nfulnl_cb,
 };
 
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -877,10 +877,13 @@ out_put:
 
 static struct nfnl_callback nfqnl_cb[NFQNL_MSG_MAX] = {
        [NFQNL_MSG_PACKET]      = { .call = nfqnl_recv_unsupp,
+                                   .attr_count = NFQA_MAX,
                                    .cap_required = CAP_NET_ADMIN },
        [NFQNL_MSG_VERDICT]     = { .call = nfqnl_recv_verdict,
+                                   .attr_count = NFQA_MAX,
                                    .cap_required = CAP_NET_ADMIN },
        [NFQNL_MSG_CONFIG]      = { .call = nfqnl_recv_config,
+                                   .attr_count = NFQA_CFG_MAX,
                                    .cap_required = CAP_NET_ADMIN },
 };
 
@@ -888,7 +891,6 @@ static struct nfnetlink_subsystem nfqnl_
        .name           = "nf_queue",
        .subsys_id      = NFNL_SUBSYS_QUEUE,
        .cb_count       = NFQNL_MSG_MAX,
-       .attr_count     = NFQA_MAX,
        .cb             = nfqnl_cb,
 };
 
-- 
- Harald Welte <[EMAIL PROTECTED]>                 http://netfilter.org/
============================================================================
  "Fragmentation is like classful addressing -- an interesting early
   architectural error that shows how much experimentation was going
   on while IP was being designed."                    -- Paul Vixie

Attachment: pgprQ7MADGN2t.pgp
Description: PGP signature

Reply via email to