0001
0002
0003
0004
0005
0006 #include <linux/init.h>
0007 #include <linux/module.h>
0008 #include <linux/kernel.h>
0009 #include <linux/rculist.h>
0010 #include <linux/rculist_nulls.h>
0011 #include <linux/types.h>
0012 #include <linux/timer.h>
0013 #include <linux/security.h>
0014 #include <linux/skbuff.h>
0015 #include <linux/errno.h>
0016 #include <linux/netlink.h>
0017 #include <linux/spinlock.h>
0018 #include <linux/interrupt.h>
0019 #include <linux/slab.h>
0020
0021 #include <linux/netfilter.h>
0022 #include <net/netlink.h>
0023 #include <net/netns/generic.h>
0024 #include <net/sock.h>
0025 #include <net/netfilter/nf_conntrack.h>
0026 #include <net/netfilter/nf_conntrack_core.h>
0027 #include <net/netfilter/nf_conntrack_l4proto.h>
0028 #include <net/netfilter/nf_conntrack_tuple.h>
0029 #include <net/netfilter/nf_conntrack_timeout.h>
0030
0031 #include <linux/netfilter/nfnetlink.h>
0032 #include <linux/netfilter/nfnetlink_cttimeout.h>
0033
0034 static unsigned int nfct_timeout_id __read_mostly;
0035
0036 struct ctnl_timeout {
0037 struct list_head head;
0038 struct list_head free_head;
0039 struct rcu_head rcu_head;
0040 refcount_t refcnt;
0041 char name[CTNL_TIMEOUT_NAME_MAX];
0042
0043
0044 struct nf_ct_timeout timeout;
0045 };
0046
0047 struct nfct_timeout_pernet {
0048 struct list_head nfct_timeout_list;
0049 struct list_head nfct_timeout_freelist;
0050 };
0051
0052 MODULE_LICENSE("GPL");
0053 MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
0054 MODULE_DESCRIPTION("cttimeout: Extended Netfilter Connection Tracking timeout tuning");
0055
0056 static const struct nla_policy cttimeout_nla_policy[CTA_TIMEOUT_MAX+1] = {
0057 [CTA_TIMEOUT_NAME] = { .type = NLA_NUL_STRING,
0058 .len = CTNL_TIMEOUT_NAME_MAX - 1},
0059 [CTA_TIMEOUT_L3PROTO] = { .type = NLA_U16 },
0060 [CTA_TIMEOUT_L4PROTO] = { .type = NLA_U8 },
0061 [CTA_TIMEOUT_DATA] = { .type = NLA_NESTED },
0062 };
0063
0064 static struct nfct_timeout_pernet *nfct_timeout_pernet(struct net *net)
0065 {
0066 return net_generic(net, nfct_timeout_id);
0067 }
0068
0069 static int
0070 ctnl_timeout_parse_policy(void *timeout,
0071 const struct nf_conntrack_l4proto *l4proto,
0072 struct net *net, const struct nlattr *attr)
0073 {
0074 struct nlattr **tb;
0075 int ret = 0;
0076
0077 tb = kcalloc(l4proto->ctnl_timeout.nlattr_max + 1, sizeof(*tb),
0078 GFP_KERNEL);
0079
0080 if (!tb)
0081 return -ENOMEM;
0082
0083 ret = nla_parse_nested_deprecated(tb,
0084 l4proto->ctnl_timeout.nlattr_max,
0085 attr,
0086 l4proto->ctnl_timeout.nla_policy,
0087 NULL);
0088 if (ret < 0)
0089 goto err;
0090
0091 ret = l4proto->ctnl_timeout.nlattr_to_obj(tb, net, timeout);
0092
0093 err:
0094 kfree(tb);
0095 return ret;
0096 }
0097
0098 static int cttimeout_new_timeout(struct sk_buff *skb,
0099 const struct nfnl_info *info,
0100 const struct nlattr * const cda[])
0101 {
0102 struct nfct_timeout_pernet *pernet = nfct_timeout_pernet(info->net);
0103 __u16 l3num;
0104 __u8 l4num;
0105 const struct nf_conntrack_l4proto *l4proto;
0106 struct ctnl_timeout *timeout, *matching = NULL;
0107 char *name;
0108 int ret;
0109
0110 if (!cda[CTA_TIMEOUT_NAME] ||
0111 !cda[CTA_TIMEOUT_L3PROTO] ||
0112 !cda[CTA_TIMEOUT_L4PROTO] ||
0113 !cda[CTA_TIMEOUT_DATA])
0114 return -EINVAL;
0115
0116 name = nla_data(cda[CTA_TIMEOUT_NAME]);
0117 l3num = ntohs(nla_get_be16(cda[CTA_TIMEOUT_L3PROTO]));
0118 l4num = nla_get_u8(cda[CTA_TIMEOUT_L4PROTO]);
0119
0120 list_for_each_entry(timeout, &pernet->nfct_timeout_list, head) {
0121 if (strncmp(timeout->name, name, CTNL_TIMEOUT_NAME_MAX) != 0)
0122 continue;
0123
0124 if (info->nlh->nlmsg_flags & NLM_F_EXCL)
0125 return -EEXIST;
0126
0127 matching = timeout;
0128 break;
0129 }
0130
0131 if (matching) {
0132 if (info->nlh->nlmsg_flags & NLM_F_REPLACE) {
0133
0134
0135
0136 if (matching->timeout.l3num != l3num ||
0137 matching->timeout.l4proto->l4proto != l4num)
0138 return -EINVAL;
0139
0140 return ctnl_timeout_parse_policy(&matching->timeout.data,
0141 matching->timeout.l4proto,
0142 info->net,
0143 cda[CTA_TIMEOUT_DATA]);
0144 }
0145
0146 return -EBUSY;
0147 }
0148
0149 l4proto = nf_ct_l4proto_find(l4num);
0150
0151
0152 if (l4proto->l4proto != l4num) {
0153 ret = -EOPNOTSUPP;
0154 goto err_proto_put;
0155 }
0156
0157 timeout = kzalloc(sizeof(struct ctnl_timeout) +
0158 l4proto->ctnl_timeout.obj_size, GFP_KERNEL);
0159 if (timeout == NULL) {
0160 ret = -ENOMEM;
0161 goto err_proto_put;
0162 }
0163
0164 ret = ctnl_timeout_parse_policy(&timeout->timeout.data, l4proto,
0165 info->net, cda[CTA_TIMEOUT_DATA]);
0166 if (ret < 0)
0167 goto err;
0168
0169 strcpy(timeout->name, nla_data(cda[CTA_TIMEOUT_NAME]));
0170 timeout->timeout.l3num = l3num;
0171 timeout->timeout.l4proto = l4proto;
0172 refcount_set(&timeout->refcnt, 1);
0173 __module_get(THIS_MODULE);
0174 list_add_tail_rcu(&timeout->head, &pernet->nfct_timeout_list);
0175
0176 return 0;
0177 err:
0178 kfree(timeout);
0179 err_proto_put:
0180 return ret;
0181 }
0182
0183 static int
0184 ctnl_timeout_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type,
0185 int event, struct ctnl_timeout *timeout)
0186 {
0187 struct nlmsghdr *nlh;
0188 unsigned int flags = portid ? NLM_F_MULTI : 0;
0189 const struct nf_conntrack_l4proto *l4proto = timeout->timeout.l4proto;
0190 struct nlattr *nest_parms;
0191 int ret;
0192
0193 event = nfnl_msg_type(NFNL_SUBSYS_CTNETLINK_TIMEOUT, event);
0194 nlh = nfnl_msg_put(skb, portid, seq, event, flags, AF_UNSPEC,
0195 NFNETLINK_V0, 0);
0196 if (!nlh)
0197 goto nlmsg_failure;
0198
0199 if (nla_put_string(skb, CTA_TIMEOUT_NAME, timeout->name) ||
0200 nla_put_be16(skb, CTA_TIMEOUT_L3PROTO,
0201 htons(timeout->timeout.l3num)) ||
0202 nla_put_u8(skb, CTA_TIMEOUT_L4PROTO, l4proto->l4proto) ||
0203 nla_put_be32(skb, CTA_TIMEOUT_USE,
0204 htonl(refcount_read(&timeout->refcnt))))
0205 goto nla_put_failure;
0206
0207 nest_parms = nla_nest_start(skb, CTA_TIMEOUT_DATA);
0208 if (!nest_parms)
0209 goto nla_put_failure;
0210
0211 ret = l4proto->ctnl_timeout.obj_to_nlattr(skb, &timeout->timeout.data);
0212 if (ret < 0)
0213 goto nla_put_failure;
0214
0215 nla_nest_end(skb, nest_parms);
0216
0217 nlmsg_end(skb, nlh);
0218 return skb->len;
0219
0220 nlmsg_failure:
0221 nla_put_failure:
0222 nlmsg_cancel(skb, nlh);
0223 return -1;
0224 }
0225
0226 static int
0227 ctnl_timeout_dump(struct sk_buff *skb, struct netlink_callback *cb)
0228 {
0229 struct nfct_timeout_pernet *pernet;
0230 struct net *net = sock_net(skb->sk);
0231 struct ctnl_timeout *cur, *last;
0232
0233 if (cb->args[2])
0234 return 0;
0235
0236 last = (struct ctnl_timeout *)cb->args[1];
0237 if (cb->args[1])
0238 cb->args[1] = 0;
0239
0240 rcu_read_lock();
0241 pernet = nfct_timeout_pernet(net);
0242 list_for_each_entry_rcu(cur, &pernet->nfct_timeout_list, head) {
0243 if (last) {
0244 if (cur != last)
0245 continue;
0246
0247 last = NULL;
0248 }
0249 if (ctnl_timeout_fill_info(skb, NETLINK_CB(cb->skb).portid,
0250 cb->nlh->nlmsg_seq,
0251 NFNL_MSG_TYPE(cb->nlh->nlmsg_type),
0252 IPCTNL_MSG_TIMEOUT_NEW, cur) < 0) {
0253 cb->args[1] = (unsigned long)cur;
0254 break;
0255 }
0256 }
0257 if (!cb->args[1])
0258 cb->args[2] = 1;
0259 rcu_read_unlock();
0260 return skb->len;
0261 }
0262
0263 static int cttimeout_get_timeout(struct sk_buff *skb,
0264 const struct nfnl_info *info,
0265 const struct nlattr * const cda[])
0266 {
0267 struct nfct_timeout_pernet *pernet = nfct_timeout_pernet(info->net);
0268 int ret = -ENOENT;
0269 char *name;
0270 struct ctnl_timeout *cur;
0271
0272 if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
0273 struct netlink_dump_control c = {
0274 .dump = ctnl_timeout_dump,
0275 };
0276 return netlink_dump_start(info->sk, skb, info->nlh, &c);
0277 }
0278
0279 if (!cda[CTA_TIMEOUT_NAME])
0280 return -EINVAL;
0281 name = nla_data(cda[CTA_TIMEOUT_NAME]);
0282
0283 list_for_each_entry(cur, &pernet->nfct_timeout_list, head) {
0284 struct sk_buff *skb2;
0285
0286 if (strncmp(cur->name, name, CTNL_TIMEOUT_NAME_MAX) != 0)
0287 continue;
0288
0289 skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
0290 if (skb2 == NULL) {
0291 ret = -ENOMEM;
0292 break;
0293 }
0294
0295 ret = ctnl_timeout_fill_info(skb2, NETLINK_CB(skb).portid,
0296 info->nlh->nlmsg_seq,
0297 NFNL_MSG_TYPE(info->nlh->nlmsg_type),
0298 IPCTNL_MSG_TIMEOUT_NEW, cur);
0299 if (ret <= 0) {
0300 kfree_skb(skb2);
0301 break;
0302 }
0303
0304 ret = nfnetlink_unicast(skb2, info->net, NETLINK_CB(skb).portid);
0305 break;
0306 }
0307
0308 return ret;
0309 }
0310
0311
0312 static int ctnl_timeout_try_del(struct net *net, struct ctnl_timeout *timeout)
0313 {
0314 int ret = 0;
0315
0316
0317
0318
0319 if (refcount_dec_if_one(&timeout->refcnt)) {
0320
0321 list_del_rcu(&timeout->head);
0322 nf_ct_untimeout(net, &timeout->timeout);
0323 kfree_rcu(timeout, rcu_head);
0324 } else {
0325 ret = -EBUSY;
0326 }
0327 return ret;
0328 }
0329
0330 static int cttimeout_del_timeout(struct sk_buff *skb,
0331 const struct nfnl_info *info,
0332 const struct nlattr * const cda[])
0333 {
0334 struct nfct_timeout_pernet *pernet = nfct_timeout_pernet(info->net);
0335 struct ctnl_timeout *cur, *tmp;
0336 int ret = -ENOENT;
0337 char *name;
0338
0339 if (!cda[CTA_TIMEOUT_NAME]) {
0340 list_for_each_entry_safe(cur, tmp, &pernet->nfct_timeout_list,
0341 head)
0342 ctnl_timeout_try_del(info->net, cur);
0343
0344 return 0;
0345 }
0346 name = nla_data(cda[CTA_TIMEOUT_NAME]);
0347
0348 list_for_each_entry(cur, &pernet->nfct_timeout_list, head) {
0349 if (strncmp(cur->name, name, CTNL_TIMEOUT_NAME_MAX) != 0)
0350 continue;
0351
0352 ret = ctnl_timeout_try_del(info->net, cur);
0353 if (ret < 0)
0354 return ret;
0355
0356 break;
0357 }
0358 return ret;
0359 }
0360
0361 static int cttimeout_default_set(struct sk_buff *skb,
0362 const struct nfnl_info *info,
0363 const struct nlattr * const cda[])
0364 {
0365 const struct nf_conntrack_l4proto *l4proto;
0366 __u8 l4num;
0367 int ret;
0368
0369 if (!cda[CTA_TIMEOUT_L3PROTO] ||
0370 !cda[CTA_TIMEOUT_L4PROTO] ||
0371 !cda[CTA_TIMEOUT_DATA])
0372 return -EINVAL;
0373
0374 l4num = nla_get_u8(cda[CTA_TIMEOUT_L4PROTO]);
0375 l4proto = nf_ct_l4proto_find(l4num);
0376
0377
0378 if (l4proto->l4proto != l4num) {
0379 ret = -EOPNOTSUPP;
0380 goto err;
0381 }
0382
0383 ret = ctnl_timeout_parse_policy(NULL, l4proto, info->net,
0384 cda[CTA_TIMEOUT_DATA]);
0385 if (ret < 0)
0386 goto err;
0387
0388 return 0;
0389 err:
0390 return ret;
0391 }
0392
0393 static int
0394 cttimeout_default_fill_info(struct net *net, struct sk_buff *skb, u32 portid,
0395 u32 seq, u32 type, int event, u16 l3num,
0396 const struct nf_conntrack_l4proto *l4proto,
0397 const unsigned int *timeouts)
0398 {
0399 struct nlmsghdr *nlh;
0400 unsigned int flags = portid ? NLM_F_MULTI : 0;
0401 struct nlattr *nest_parms;
0402 int ret;
0403
0404 event = nfnl_msg_type(NFNL_SUBSYS_CTNETLINK_TIMEOUT, event);
0405 nlh = nfnl_msg_put(skb, portid, seq, event, flags, AF_UNSPEC,
0406 NFNETLINK_V0, 0);
0407 if (!nlh)
0408 goto nlmsg_failure;
0409
0410 if (nla_put_be16(skb, CTA_TIMEOUT_L3PROTO, htons(l3num)) ||
0411 nla_put_u8(skb, CTA_TIMEOUT_L4PROTO, l4proto->l4proto))
0412 goto nla_put_failure;
0413
0414 nest_parms = nla_nest_start(skb, CTA_TIMEOUT_DATA);
0415 if (!nest_parms)
0416 goto nla_put_failure;
0417
0418 ret = l4proto->ctnl_timeout.obj_to_nlattr(skb, timeouts);
0419 if (ret < 0)
0420 goto nla_put_failure;
0421
0422 nla_nest_end(skb, nest_parms);
0423
0424 nlmsg_end(skb, nlh);
0425 return skb->len;
0426
0427 nlmsg_failure:
0428 nla_put_failure:
0429 nlmsg_cancel(skb, nlh);
0430 return -1;
0431 }
0432
0433 static int cttimeout_default_get(struct sk_buff *skb,
0434 const struct nfnl_info *info,
0435 const struct nlattr * const cda[])
0436 {
0437 const struct nf_conntrack_l4proto *l4proto;
0438 unsigned int *timeouts = NULL;
0439 struct sk_buff *skb2;
0440 __u16 l3num;
0441 __u8 l4num;
0442 int ret;
0443
0444 if (!cda[CTA_TIMEOUT_L3PROTO] || !cda[CTA_TIMEOUT_L4PROTO])
0445 return -EINVAL;
0446
0447 l3num = ntohs(nla_get_be16(cda[CTA_TIMEOUT_L3PROTO]));
0448 l4num = nla_get_u8(cda[CTA_TIMEOUT_L4PROTO]);
0449 l4proto = nf_ct_l4proto_find(l4num);
0450
0451 if (l4proto->l4proto != l4num)
0452 return -EOPNOTSUPP;
0453
0454 switch (l4proto->l4proto) {
0455 case IPPROTO_ICMP:
0456 timeouts = &nf_icmp_pernet(info->net)->timeout;
0457 break;
0458 case IPPROTO_TCP:
0459 timeouts = nf_tcp_pernet(info->net)->timeouts;
0460 break;
0461 case IPPROTO_UDP:
0462 case IPPROTO_UDPLITE:
0463 timeouts = nf_udp_pernet(info->net)->timeouts;
0464 break;
0465 case IPPROTO_DCCP:
0466 #ifdef CONFIG_NF_CT_PROTO_DCCP
0467 timeouts = nf_dccp_pernet(info->net)->dccp_timeout;
0468 #endif
0469 break;
0470 case IPPROTO_ICMPV6:
0471 timeouts = &nf_icmpv6_pernet(info->net)->timeout;
0472 break;
0473 case IPPROTO_SCTP:
0474 #ifdef CONFIG_NF_CT_PROTO_SCTP
0475 timeouts = nf_sctp_pernet(info->net)->timeouts;
0476 #endif
0477 break;
0478 case IPPROTO_GRE:
0479 #ifdef CONFIG_NF_CT_PROTO_GRE
0480 timeouts = nf_gre_pernet(info->net)->timeouts;
0481 #endif
0482 break;
0483 case 255:
0484 timeouts = &nf_generic_pernet(info->net)->timeout;
0485 break;
0486 default:
0487 WARN_ONCE(1, "Missing timeouts for proto %d", l4proto->l4proto);
0488 break;
0489 }
0490
0491 if (!timeouts)
0492 return -EOPNOTSUPP;
0493
0494 skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
0495 if (!skb2)
0496 return -ENOMEM;
0497
0498 ret = cttimeout_default_fill_info(info->net, skb2,
0499 NETLINK_CB(skb).portid,
0500 info->nlh->nlmsg_seq,
0501 NFNL_MSG_TYPE(info->nlh->nlmsg_type),
0502 IPCTNL_MSG_TIMEOUT_DEFAULT_SET,
0503 l3num, l4proto, timeouts);
0504 if (ret <= 0) {
0505 kfree_skb(skb2);
0506 return -ENOMEM;
0507 }
0508
0509 return nfnetlink_unicast(skb2, info->net, NETLINK_CB(skb).portid);
0510 }
0511
0512 static struct nf_ct_timeout *ctnl_timeout_find_get(struct net *net,
0513 const char *name)
0514 {
0515 struct nfct_timeout_pernet *pernet = nfct_timeout_pernet(net);
0516 struct ctnl_timeout *timeout, *matching = NULL;
0517
0518 list_for_each_entry_rcu(timeout, &pernet->nfct_timeout_list, head) {
0519 if (strncmp(timeout->name, name, CTNL_TIMEOUT_NAME_MAX) != 0)
0520 continue;
0521
0522 if (!refcount_inc_not_zero(&timeout->refcnt))
0523 goto err;
0524 matching = timeout;
0525 break;
0526 }
0527 err:
0528 return matching ? &matching->timeout : NULL;
0529 }
0530
0531 static void ctnl_timeout_put(struct nf_ct_timeout *t)
0532 {
0533 struct ctnl_timeout *timeout =
0534 container_of(t, struct ctnl_timeout, timeout);
0535
0536 if (refcount_dec_and_test(&timeout->refcnt)) {
0537 kfree_rcu(timeout, rcu_head);
0538 module_put(THIS_MODULE);
0539 }
0540 }
0541
0542 static const struct nfnl_callback cttimeout_cb[IPCTNL_MSG_TIMEOUT_MAX] = {
0543 [IPCTNL_MSG_TIMEOUT_NEW] = {
0544 .call = cttimeout_new_timeout,
0545 .type = NFNL_CB_MUTEX,
0546 .attr_count = CTA_TIMEOUT_MAX,
0547 .policy = cttimeout_nla_policy
0548 },
0549 [IPCTNL_MSG_TIMEOUT_GET] = {
0550 .call = cttimeout_get_timeout,
0551 .type = NFNL_CB_MUTEX,
0552 .attr_count = CTA_TIMEOUT_MAX,
0553 .policy = cttimeout_nla_policy
0554 },
0555 [IPCTNL_MSG_TIMEOUT_DELETE] = {
0556 .call = cttimeout_del_timeout,
0557 .type = NFNL_CB_MUTEX,
0558 .attr_count = CTA_TIMEOUT_MAX,
0559 .policy = cttimeout_nla_policy
0560 },
0561 [IPCTNL_MSG_TIMEOUT_DEFAULT_SET] = {
0562 .call = cttimeout_default_set,
0563 .type = NFNL_CB_MUTEX,
0564 .attr_count = CTA_TIMEOUT_MAX,
0565 .policy = cttimeout_nla_policy
0566 },
0567 [IPCTNL_MSG_TIMEOUT_DEFAULT_GET] = {
0568 .call = cttimeout_default_get,
0569 .type = NFNL_CB_MUTEX,
0570 .attr_count = CTA_TIMEOUT_MAX,
0571 .policy = cttimeout_nla_policy
0572 },
0573 };
0574
0575 static const struct nfnetlink_subsystem cttimeout_subsys = {
0576 .name = "conntrack_timeout",
0577 .subsys_id = NFNL_SUBSYS_CTNETLINK_TIMEOUT,
0578 .cb_count = IPCTNL_MSG_TIMEOUT_MAX,
0579 .cb = cttimeout_cb,
0580 };
0581
0582 MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK_TIMEOUT);
0583
0584 static int __net_init cttimeout_net_init(struct net *net)
0585 {
0586 struct nfct_timeout_pernet *pernet = nfct_timeout_pernet(net);
0587
0588 INIT_LIST_HEAD(&pernet->nfct_timeout_list);
0589 INIT_LIST_HEAD(&pernet->nfct_timeout_freelist);
0590
0591 return 0;
0592 }
0593
0594 static void __net_exit cttimeout_net_pre_exit(struct net *net)
0595 {
0596 struct nfct_timeout_pernet *pernet = nfct_timeout_pernet(net);
0597 struct ctnl_timeout *cur, *tmp;
0598
0599 list_for_each_entry_safe(cur, tmp, &pernet->nfct_timeout_list, head) {
0600 list_del_rcu(&cur->head);
0601 list_add(&cur->free_head, &pernet->nfct_timeout_freelist);
0602 }
0603
0604
0605 }
0606
0607 static void __net_exit cttimeout_net_exit(struct net *net)
0608 {
0609 struct nfct_timeout_pernet *pernet = nfct_timeout_pernet(net);
0610 struct ctnl_timeout *cur, *tmp;
0611
0612 if (list_empty(&pernet->nfct_timeout_freelist))
0613 return;
0614
0615 nf_ct_untimeout(net, NULL);
0616
0617 list_for_each_entry_safe(cur, tmp, &pernet->nfct_timeout_freelist, free_head) {
0618 list_del(&cur->free_head);
0619
0620 if (refcount_dec_and_test(&cur->refcnt))
0621 kfree_rcu(cur, rcu_head);
0622 }
0623 }
0624
0625 static struct pernet_operations cttimeout_ops = {
0626 .init = cttimeout_net_init,
0627 .pre_exit = cttimeout_net_pre_exit,
0628 .exit = cttimeout_net_exit,
0629 .id = &nfct_timeout_id,
0630 .size = sizeof(struct nfct_timeout_pernet),
0631 };
0632
0633 static const struct nf_ct_timeout_hooks hooks = {
0634 .timeout_find_get = ctnl_timeout_find_get,
0635 .timeout_put = ctnl_timeout_put,
0636 };
0637
0638 static int __init cttimeout_init(void)
0639 {
0640 int ret;
0641
0642 ret = register_pernet_subsys(&cttimeout_ops);
0643 if (ret < 0)
0644 return ret;
0645
0646 ret = nfnetlink_subsys_register(&cttimeout_subsys);
0647 if (ret < 0) {
0648 pr_err("cttimeout_init: cannot register cttimeout with "
0649 "nfnetlink.\n");
0650 goto err_out;
0651 }
0652 RCU_INIT_POINTER(nf_ct_timeout_hook, &hooks);
0653 return 0;
0654
0655 err_out:
0656 unregister_pernet_subsys(&cttimeout_ops);
0657 return ret;
0658 }
0659
0660 static int untimeout(struct nf_conn *ct, void *timeout)
0661 {
0662 struct nf_conn_timeout *timeout_ext = nf_ct_timeout_find(ct);
0663
0664 if (timeout_ext)
0665 RCU_INIT_POINTER(timeout_ext->timeout, NULL);
0666
0667 return 0;
0668 }
0669
0670 static void __exit cttimeout_exit(void)
0671 {
0672 nfnetlink_subsys_unregister(&cttimeout_subsys);
0673
0674 unregister_pernet_subsys(&cttimeout_ops);
0675 RCU_INIT_POINTER(nf_ct_timeout_hook, NULL);
0676
0677 nf_ct_iterate_destroy(untimeout, NULL);
0678 }
0679
0680 module_init(cttimeout_init);
0681 module_exit(cttimeout_exit);