diff options
author | Patrick McHardy <kaber@trash.net> | 2007-09-28 17:38:52 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-10-10 19:53:33 -0400 |
commit | e3730578285fcf0c628f08b0dc89425cfeafd4ba (patch) | |
tree | 7ba377a0c5ac7070f3293f2297f2e9ab910d6865 | |
parent | dd82185f2c55e9dc2247c83d78517ef14e71d30e (diff) |
[NETFILTER]: nfnetlink: support attribute policies
Add support for automatic checking of per-callback attribute policies.
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/linux/netfilter/nfnetlink.h | 3 | ||||
-rw-r--r-- | net/netfilter/nfnetlink.c | 48 |
2 files changed, 15 insertions, 36 deletions
diff --git a/include/linux/netfilter/nfnetlink.h b/include/linux/netfilter/nfnetlink.h index e61a8a5fcaff..cd8fded36550 100644 --- a/include/linux/netfilter/nfnetlink.h +++ b/include/linux/netfilter/nfnetlink.h | |||
@@ -58,7 +58,8 @@ struct nfnl_callback | |||
58 | { | 58 | { |
59 | int (*call)(struct sock *nl, struct sk_buff *skb, | 59 | int (*call)(struct sock *nl, struct sk_buff *skb, |
60 | struct nlmsghdr *nlh, struct nlattr *cda[]); | 60 | struct nlmsghdr *nlh, struct nlattr *cda[]); |
61 | u_int16_t attr_count; /* number of nlattr's */ | 61 | const struct nla_policy *policy; /* netlink attribute policy */ |
62 | const u_int16_t attr_count; /* number of nlattr's */ | ||
62 | }; | 63 | }; |
63 | 64 | ||
64 | struct nfnetlink_subsystem | 65 | struct nfnetlink_subsystem |
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c index e212102b0e4a..cb41990f92e0 100644 --- a/net/netfilter/nfnetlink.c +++ b/net/netfilter/nfnetlink.c | |||
@@ -111,35 +111,6 @@ nfnetlink_find_client(u_int16_t type, const struct nfnetlink_subsystem *ss) | |||
111 | return &ss->cb[cb_id]; | 111 | return &ss->cb[cb_id]; |
112 | } | 112 | } |
113 | 113 | ||
114 | /** | ||
115 | * nfnetlink_check_attributes - check and parse nfnetlink attributes | ||
116 | * | ||
117 | * subsys: nfnl subsystem for which this message is to be parsed | ||
118 | * nlmsghdr: netlink message to be checked/parsed | ||
119 | * cda: array of pointers, needs to be at least subsys->attr_count+1 big | ||
120 | * | ||
121 | */ | ||
122 | static int | ||
123 | nfnetlink_check_attributes(const struct nfnetlink_subsystem *subsys, | ||
124 | struct nlmsghdr *nlh, struct nlattr *cda[]) | ||
125 | { | ||
126 | int min_len = NLMSG_SPACE(sizeof(struct nfgenmsg)); | ||
127 | u_int8_t cb_id = NFNL_MSG_TYPE(nlh->nlmsg_type); | ||
128 | u_int16_t attr_count = subsys->cb[cb_id].attr_count; | ||
129 | |||
130 | /* check attribute lengths. */ | ||
131 | if (likely(nlh->nlmsg_len > min_len)) { | ||
132 | struct nlattr *attr = (void *)nlh + NLMSG_ALIGN(min_len); | ||
133 | int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(min_len); | ||
134 | nla_parse(cda, attr_count, attr, attrlen, NULL); | ||
135 | } | ||
136 | |||
137 | /* implicit: if nlmsg_len == min_len, we return 0, and an empty | ||
138 | * (zeroed) cda[] array. The message is valid, but empty. */ | ||
139 | |||
140 | return 0; | ||
141 | } | ||
142 | |||
143 | int nfnetlink_has_listeners(unsigned int group) | 114 | int nfnetlink_has_listeners(unsigned int group) |
144 | { | 115 | { |
145 | return netlink_has_listeners(nfnl, group); | 116 | return netlink_has_listeners(nfnl, group); |
@@ -192,15 +163,22 @@ static int nfnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
192 | return -EINVAL; | 163 | return -EINVAL; |
193 | 164 | ||
194 | { | 165 | { |
195 | u_int16_t attr_count = | 166 | int min_len = NLMSG_SPACE(sizeof(struct nfgenmsg)); |
196 | ss->cb[NFNL_MSG_TYPE(nlh->nlmsg_type)].attr_count; | 167 | u_int8_t cb_id = NFNL_MSG_TYPE(nlh->nlmsg_type); |
168 | u_int16_t attr_count = ss->cb[cb_id].attr_count; | ||
197 | struct nlattr *cda[attr_count+1]; | 169 | struct nlattr *cda[attr_count+1]; |
198 | 170 | ||
199 | memset(cda, 0, sizeof(struct nlattr *) * attr_count); | 171 | if (likely(nlh->nlmsg_len >= min_len)) { |
172 | struct nlattr *attr = (void *)nlh + NLMSG_ALIGN(min_len); | ||
173 | int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(min_len); | ||
174 | |||
175 | err = nla_parse(cda, attr_count, attr, attrlen, | ||
176 | ss->cb[cb_id].policy); | ||
177 | if (err < 0) | ||
178 | return err; | ||
179 | } else | ||
180 | return -EINVAL; | ||
200 | 181 | ||
201 | err = nfnetlink_check_attributes(ss, nlh, cda); | ||
202 | if (err < 0) | ||
203 | return err; | ||
204 | return nc->call(nfnl, skb, nlh, cda); | 182 | return nc->call(nfnl, skb, nlh, cda); |
205 | } | 183 | } |
206 | } | 184 | } |