11 #include <linux/module.h>
12 #include <linux/kernel.h>
14 #include <linux/netlink.h>
16 #include <linux/slab.h>
17 #include <linux/types.h>
18 #include <linux/list.h>
19 #include <linux/errno.h>
27 #include <linux/netfilter/nfnetlink.h>
36 nfnl_userspace_cthelper(
struct sk_buff *
skb,
unsigned int protoff,
78 tuple->
dst.protonum = nla_get_u8(tb[NFCTH_TUPLE_L4PROTONUM]);
84 nfnl_cthelper_from_nlattr(
struct nlattr *attr,
struct nf_conn *ct)
91 if (help->
helper->data_len == 0)
99 nfnl_cthelper_to_nlattr(
struct sk_buff *skb,
const struct nf_conn *ct)
103 if (help->
helper->data_len &&
105 goto nla_put_failure;
122 const struct nlattr *attr)
138 ntohl(nla_get_be32(tb[NFCTH_POLICY_EXPECT_TIMEOUT]));
150 const struct nlattr *attr)
157 nfnl_cthelper_expect_policy_set);
163 ntohl(nla_get_be32(tb[NFCTH_POLICY_SET_NUM]));
171 if (expect_policy ==
NULL)
178 ret = nfnl_cthelper_expect_policy(&expect_policy[i],
186 kfree(expect_policy);
191 nfnl_cthelper_create(
const struct nlattr *
const tb[],
204 ret = nfnl_cthelper_parse_expect_policy(helper, tb[
NFCTH_POLICY]);
209 helper->
data_len =
ntohl(nla_get_be32(tb[NFCTH_PRIV_DATA_LEN]));
214 helper->
help = nfnl_userspace_cthelper;
216 helper->
to_nlattr = nfnl_cthelper_to_nlattr;
223 int status =
ntohl(nla_get_be32(tb[NFCTH_STATUS]));
246 nfnl_cthelper_update(
const struct nlattr *
const tb[],
251 if (tb[NFCTH_PRIV_DATA_LEN])
255 ret = nfnl_cthelper_parse_expect_policy(helper,
260 if (tb[NFCTH_QUEUE_NUM])
263 if (tb[NFCTH_STATUS]) {
264 int status =
ntohl(nla_get_be32(tb[NFCTH_STATUS]));
279 nfnl_cthelper_new(
struct sock *nfnl,
struct sk_buff *skb,
282 const char *helper_name;
293 ret = nfnl_cthelper_parse_tuple(&tuple, tb[NFCTH_TUPLE]);
299 hlist_for_each_entry_rcu(cur, n, &nf_ct_helper_hash[i], hnode) {
309 if ((tuple.
src.l3num != cur->
tuple.src.l3num ||
310 tuple.
dst.protonum != cur->
tuple.dst.protonum))
324 ret = nfnl_cthelper_create(tb, &tuple);
326 ret = nfnl_cthelper_update(tb, helper);
335 nfnl_cthelper_dump_tuple(
struct sk_buff *skb,
338 struct nlattr *nest_parms;
340 nest_parms = nla_nest_start(skb, NFCTH_TUPLE |
NLA_F_NESTED);
341 if (nest_parms ==
NULL)
342 goto nla_put_failure;
346 goto nla_put_failure;
348 if (nla_put_u8(skb, NFCTH_TUPLE_L4PROTONUM, helper->
tuple.dst.protonum))
349 goto nla_put_failure;
351 nla_nest_end(skb, nest_parms);
359 nfnl_cthelper_dump_policy(
struct sk_buff *skb,
363 struct nlattr *nest_parms1, *nest_parms2;
365 nest_parms1 = nla_nest_start(skb, NFCTH_POLICY |
NLA_F_NESTED);
366 if (nest_parms1 ==
NULL)
367 goto nla_put_failure;
369 if (nla_put_be32(skb, NFCTH_POLICY_SET_NUM,
371 goto nla_put_failure;
374 nest_parms2 = nla_nest_start(skb,
376 if (nest_parms2 ==
NULL)
377 goto nla_put_failure;
381 goto nla_put_failure;
385 goto nla_put_failure;
387 if (nla_put_be32(skb, NFCTH_POLICY_EXPECT_TIMEOUT,
389 goto nla_put_failure;
391 nla_nest_end(skb, nest_parms2);
393 nla_nest_end(skb, nest_parms1);
410 nlh = nlmsg_put(skb, portid, seq, event,
sizeof(*nfmsg), flags);
414 nfmsg = nlmsg_data(nlh);
420 goto nla_put_failure;
423 goto nla_put_failure;
425 if (nfnl_cthelper_dump_tuple(skb, helper) < 0)
426 goto nla_put_failure;
428 if (nfnl_cthelper_dump_policy(skb, helper) < 0)
429 goto nla_put_failure;
431 if (nla_put_be32(skb, NFCTH_PRIV_DATA_LEN,
htonl(helper->
data_len)))
432 goto nla_put_failure;
439 if (nla_put_be32(skb, NFCTH_STATUS,
htonl(status)))
440 goto nla_put_failure;
447 nlmsg_cancel(skb, nlh);
461 hlist_for_each_entry_rcu(cur, n,
462 &nf_ct_helper_hash[cb->
args[0]],
hnode) {
473 if (nfnl_cthelper_fill_info(skb,
493 nfnl_cthelper_get(
struct sock *nfnl,
struct sk_buff *skb,
500 char *helper_name =
NULL;
502 bool tuple_set =
false;
506 .dump = nfnl_cthelper_dump_table,
508 return netlink_dump_start(nfnl, skb, nlh, &c);
512 helper_name = nla_data(tb[NFCTH_NAME]);
514 if (tb[NFCTH_TUPLE]) {
515 ret = nfnl_cthelper_parse_tuple(&tuple, tb[NFCTH_TUPLE]);
523 hlist_for_each_entry_rcu(cur, n, &nf_ct_helper_hash[i], hnode) {
534 (tuple.
src.l3num != cur->
tuple.src.l3num ||
535 tuple.
dst.protonum != cur->
tuple.dst.protonum))
544 ret = nfnl_cthelper_fill_info(skb2,
NETLINK_CB(skb).portid,
566 nfnl_cthelper_del(
struct sock *nfnl,
struct sk_buff *skb,
569 char *helper_name =
NULL;
573 bool tuple_set =
false, found =
false;
577 helper_name = nla_data(tb[NFCTH_NAME]);
579 if (tb[NFCTH_TUPLE]) {
580 ret = nfnl_cthelper_parse_tuple(&tuple, tb[NFCTH_TUPLE]);
587 for (i = 0; i < nf_ct_helper_hsize; i++) {
601 (tuple.
src.l3num != cur->
tuple.src.l3num ||
602 tuple.
dst.protonum != cur->
tuple.dst.protonum))
610 return (found || j == 0) ? 0 : -
ENOENT;
622 .policy = nfnl_cthelper_policy },
625 .policy = nfnl_cthelper_policy },
628 .policy = nfnl_cthelper_policy },
635 .cb = nfnl_cthelper_cb,
640 static int __init nfnl_cthelper_init(
void)
646 pr_err(
"nfnl_cthelper: cannot register with nfnetlink.\n");
654 static void __exit nfnl_cthelper_exit(
void)
662 for (i=0; i<nf_ct_helper_hsize; i++) {