nfnetlink_cttimeout.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655
  1. /*
  2. * (C) 2012 by Pablo Neira Ayuso <pablo@netfilter.org>
  3. * (C) 2012 by Vyatta Inc. <http://www.vyatta.com>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation (or any later at your option).
  8. */
  9. #include <linux/init.h>
  10. #include <linux/module.h>
  11. #include <linux/kernel.h>
  12. #include <linux/rculist.h>
  13. #include <linux/rculist_nulls.h>
  14. #include <linux/types.h>
  15. #include <linux/timer.h>
  16. #include <linux/security.h>
  17. #include <linux/skbuff.h>
  18. #include <linux/errno.h>
  19. #include <linux/netlink.h>
  20. #include <linux/spinlock.h>
  21. #include <linux/interrupt.h>
  22. #include <linux/slab.h>
  23. #include <linux/netfilter.h>
  24. #include <net/netlink.h>
  25. #include <net/sock.h>
  26. #include <net/netfilter/nf_conntrack.h>
  27. #include <net/netfilter/nf_conntrack_core.h>
  28. #include <net/netfilter/nf_conntrack_l3proto.h>
  29. #include <net/netfilter/nf_conntrack_l4proto.h>
  30. #include <net/netfilter/nf_conntrack_tuple.h>
  31. #include <net/netfilter/nf_conntrack_timeout.h>
  32. #include <linux/netfilter/nfnetlink.h>
  33. #include <linux/netfilter/nfnetlink_cttimeout.h>
  34. MODULE_LICENSE("GPL");
  35. MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
  36. MODULE_DESCRIPTION("cttimeout: Extended Netfilter Connection Tracking timeout tuning");
  37. static const struct nla_policy cttimeout_nla_policy[CTA_TIMEOUT_MAX+1] = {
  38. [CTA_TIMEOUT_NAME] = { .type = NLA_NUL_STRING,
  39. .len = CTNL_TIMEOUT_NAME_MAX - 1},
  40. [CTA_TIMEOUT_L3PROTO] = { .type = NLA_U16 },
  41. [CTA_TIMEOUT_L4PROTO] = { .type = NLA_U8 },
  42. [CTA_TIMEOUT_DATA] = { .type = NLA_NESTED },
  43. };
  44. static int
  45. ctnl_timeout_parse_policy(void *timeouts, struct nf_conntrack_l4proto *l4proto,
  46. struct net *net, const struct nlattr *attr)
  47. {
  48. int ret = 0;
  49. if (likely(l4proto->ctnl_timeout.nlattr_to_obj)) {
  50. struct nlattr *tb[l4proto->ctnl_timeout.nlattr_max+1];
  51. ret = nla_parse_nested(tb, l4proto->ctnl_timeout.nlattr_max,
  52. attr, l4proto->ctnl_timeout.nla_policy);
  53. if (ret < 0)
  54. return ret;
  55. ret = l4proto->ctnl_timeout.nlattr_to_obj(tb, net, timeouts);
  56. }
  57. return ret;
  58. }
  59. static int cttimeout_new_timeout(struct net *net, struct sock *ctnl,
  60. struct sk_buff *skb,
  61. const struct nlmsghdr *nlh,
  62. const struct nlattr * const cda[])
  63. {
  64. __u16 l3num;
  65. __u8 l4num;
  66. struct nf_conntrack_l4proto *l4proto;
  67. struct ctnl_timeout *timeout, *matching = NULL;
  68. char *name;
  69. int ret;
  70. if (!cda[CTA_TIMEOUT_NAME] ||
  71. !cda[CTA_TIMEOUT_L3PROTO] ||
  72. !cda[CTA_TIMEOUT_L4PROTO] ||
  73. !cda[CTA_TIMEOUT_DATA])
  74. return -EINVAL;
  75. name = nla_data(cda[CTA_TIMEOUT_NAME]);
  76. l3num = ntohs(nla_get_be16(cda[CTA_TIMEOUT_L3PROTO]));
  77. l4num = nla_get_u8(cda[CTA_TIMEOUT_L4PROTO]);
  78. list_for_each_entry(timeout, &net->nfct_timeout_list, head) {
  79. if (strncmp(timeout->name, name, CTNL_TIMEOUT_NAME_MAX) != 0)
  80. continue;
  81. if (nlh->nlmsg_flags & NLM_F_EXCL)
  82. return -EEXIST;
  83. matching = timeout;
  84. break;
  85. }
  86. if (matching) {
  87. if (nlh->nlmsg_flags & NLM_F_REPLACE) {
  88. /* You cannot replace one timeout policy by another of
  89. * different kind, sorry.
  90. */
  91. if (matching->l3num != l3num ||
  92. matching->l4proto->l4proto != l4num)
  93. return -EINVAL;
  94. return ctnl_timeout_parse_policy(&matching->data,
  95. matching->l4proto, net,
  96. cda[CTA_TIMEOUT_DATA]);
  97. }
  98. return -EBUSY;
  99. }
  100. l4proto = nf_ct_l4proto_find_get(l3num, l4num);
  101. /* This protocol is not supportted, skip. */
  102. if (l4proto->l4proto != l4num) {
  103. ret = -EOPNOTSUPP;
  104. goto err_proto_put;
  105. }
  106. timeout = kzalloc(sizeof(struct ctnl_timeout) +
  107. l4proto->ctnl_timeout.obj_size, GFP_KERNEL);
  108. if (timeout == NULL) {
  109. ret = -ENOMEM;
  110. goto err_proto_put;
  111. }
  112. ret = ctnl_timeout_parse_policy(&timeout->data, l4proto, net,
  113. cda[CTA_TIMEOUT_DATA]);
  114. if (ret < 0)
  115. goto err;
  116. strcpy(timeout->name, nla_data(cda[CTA_TIMEOUT_NAME]));
  117. timeout->l3num = l3num;
  118. timeout->l4proto = l4proto;
  119. atomic_set(&timeout->refcnt, 1);
  120. list_add_tail_rcu(&timeout->head, &net->nfct_timeout_list);
  121. return 0;
  122. err:
  123. kfree(timeout);
  124. err_proto_put:
  125. nf_ct_l4proto_put(l4proto);
  126. return ret;
  127. }
  128. static int
  129. ctnl_timeout_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type,
  130. int event, struct ctnl_timeout *timeout)
  131. {
  132. struct nlmsghdr *nlh;
  133. struct nfgenmsg *nfmsg;
  134. unsigned int flags = portid ? NLM_F_MULTI : 0;
  135. struct nf_conntrack_l4proto *l4proto = timeout->l4proto;
  136. event |= NFNL_SUBSYS_CTNETLINK_TIMEOUT << 8;
  137. nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags);
  138. if (nlh == NULL)
  139. goto nlmsg_failure;
  140. nfmsg = nlmsg_data(nlh);
  141. nfmsg->nfgen_family = AF_UNSPEC;
  142. nfmsg->version = NFNETLINK_V0;
  143. nfmsg->res_id = 0;
  144. if (nla_put_string(skb, CTA_TIMEOUT_NAME, timeout->name) ||
  145. nla_put_be16(skb, CTA_TIMEOUT_L3PROTO, htons(timeout->l3num)) ||
  146. nla_put_u8(skb, CTA_TIMEOUT_L4PROTO, timeout->l4proto->l4proto) ||
  147. nla_put_be32(skb, CTA_TIMEOUT_USE,
  148. htonl(atomic_read(&timeout->refcnt))))
  149. goto nla_put_failure;
  150. if (likely(l4proto->ctnl_timeout.obj_to_nlattr)) {
  151. struct nlattr *nest_parms;
  152. int ret;
  153. nest_parms = nla_nest_start(skb,
  154. CTA_TIMEOUT_DATA | NLA_F_NESTED);
  155. if (!nest_parms)
  156. goto nla_put_failure;
  157. ret = l4proto->ctnl_timeout.obj_to_nlattr(skb, &timeout->data);
  158. if (ret < 0)
  159. goto nla_put_failure;
  160. nla_nest_end(skb, nest_parms);
  161. }
  162. nlmsg_end(skb, nlh);
  163. return skb->len;
  164. nlmsg_failure:
  165. nla_put_failure:
  166. nlmsg_cancel(skb, nlh);
  167. return -1;
  168. }
  169. static int
  170. ctnl_timeout_dump(struct sk_buff *skb, struct netlink_callback *cb)
  171. {
  172. struct net *net = sock_net(skb->sk);
  173. struct ctnl_timeout *cur, *last;
  174. if (cb->args[2])
  175. return 0;
  176. last = (struct ctnl_timeout *)cb->args[1];
  177. if (cb->args[1])
  178. cb->args[1] = 0;
  179. rcu_read_lock();
  180. list_for_each_entry_rcu(cur, &net->nfct_timeout_list, head) {
  181. if (last) {
  182. if (cur != last)
  183. continue;
  184. last = NULL;
  185. }
  186. if (ctnl_timeout_fill_info(skb, NETLINK_CB(cb->skb).portid,
  187. cb->nlh->nlmsg_seq,
  188. NFNL_MSG_TYPE(cb->nlh->nlmsg_type),
  189. IPCTNL_MSG_TIMEOUT_NEW, cur) < 0) {
  190. cb->args[1] = (unsigned long)cur;
  191. break;
  192. }
  193. }
  194. if (!cb->args[1])
  195. cb->args[2] = 1;
  196. rcu_read_unlock();
  197. return skb->len;
  198. }
  199. static int cttimeout_get_timeout(struct net *net, struct sock *ctnl,
  200. struct sk_buff *skb,
  201. const struct nlmsghdr *nlh,
  202. const struct nlattr * const cda[])
  203. {
  204. int ret = -ENOENT;
  205. char *name;
  206. struct ctnl_timeout *cur;
  207. if (nlh->nlmsg_flags & NLM_F_DUMP) {
  208. struct netlink_dump_control c = {
  209. .dump = ctnl_timeout_dump,
  210. };
  211. return netlink_dump_start(ctnl, skb, nlh, &c);
  212. }
  213. if (!cda[CTA_TIMEOUT_NAME])
  214. return -EINVAL;
  215. name = nla_data(cda[CTA_TIMEOUT_NAME]);
  216. list_for_each_entry(cur, &net->nfct_timeout_list, head) {
  217. struct sk_buff *skb2;
  218. if (strncmp(cur->name, name, CTNL_TIMEOUT_NAME_MAX) != 0)
  219. continue;
  220. skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
  221. if (skb2 == NULL) {
  222. ret = -ENOMEM;
  223. break;
  224. }
  225. ret = ctnl_timeout_fill_info(skb2, NETLINK_CB(skb).portid,
  226. nlh->nlmsg_seq,
  227. NFNL_MSG_TYPE(nlh->nlmsg_type),
  228. IPCTNL_MSG_TIMEOUT_NEW, cur);
  229. if (ret <= 0) {
  230. kfree_skb(skb2);
  231. break;
  232. }
  233. ret = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).portid,
  234. MSG_DONTWAIT);
  235. if (ret > 0)
  236. ret = 0;
  237. /* this avoids a loop in nfnetlink. */
  238. return ret == -EAGAIN ? -ENOBUFS : ret;
  239. }
  240. return ret;
  241. }
  242. static void untimeout(struct nf_conntrack_tuple_hash *i,
  243. struct ctnl_timeout *timeout)
  244. {
  245. struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(i);
  246. struct nf_conn_timeout *timeout_ext = nf_ct_timeout_find(ct);
  247. if (timeout_ext && (!timeout || timeout_ext->timeout == timeout))
  248. RCU_INIT_POINTER(timeout_ext->timeout, NULL);
  249. }
  250. static void ctnl_untimeout(struct net *net, struct ctnl_timeout *timeout)
  251. {
  252. struct nf_conntrack_tuple_hash *h;
  253. const struct hlist_nulls_node *nn;
  254. unsigned int last_hsize;
  255. spinlock_t *lock;
  256. int i, cpu;
  257. for_each_possible_cpu(cpu) {
  258. struct ct_pcpu *pcpu = per_cpu_ptr(net->ct.pcpu_lists, cpu);
  259. spin_lock_bh(&pcpu->lock);
  260. hlist_nulls_for_each_entry(h, nn, &pcpu->unconfirmed, hnnode)
  261. untimeout(h, timeout);
  262. spin_unlock_bh(&pcpu->lock);
  263. }
  264. local_bh_disable();
  265. restart:
  266. last_hsize = nf_conntrack_htable_size;
  267. for (i = 0; i < last_hsize; i++) {
  268. lock = &nf_conntrack_locks[i % CONNTRACK_LOCKS];
  269. nf_conntrack_lock(lock);
  270. if (last_hsize != nf_conntrack_htable_size) {
  271. spin_unlock(lock);
  272. goto restart;
  273. }
  274. hlist_nulls_for_each_entry(h, nn, &nf_conntrack_hash[i], hnnode)
  275. untimeout(h, timeout);
  276. spin_unlock(lock);
  277. }
  278. local_bh_enable();
  279. }
  280. /* try to delete object, fail if it is still in use. */
  281. static int ctnl_timeout_try_del(struct net *net, struct ctnl_timeout *timeout)
  282. {
  283. int ret = 0;
  284. /* We want to avoid races with ctnl_timeout_put. So only when the
  285. * current refcnt is 1, we decrease it to 0.
  286. */
  287. if (atomic_cmpxchg(&timeout->refcnt, 1, 0) == 1) {
  288. /* We are protected by nfnl mutex. */
  289. list_del_rcu(&timeout->head);
  290. nf_ct_l4proto_put(timeout->l4proto);
  291. ctnl_untimeout(net, timeout);
  292. kfree_rcu(timeout, rcu_head);
  293. } else {
  294. ret = -EBUSY;
  295. }
  296. return ret;
  297. }
  298. static int cttimeout_del_timeout(struct net *net, struct sock *ctnl,
  299. struct sk_buff *skb,
  300. const struct nlmsghdr *nlh,
  301. const struct nlattr * const cda[])
  302. {
  303. struct ctnl_timeout *cur, *tmp;
  304. int ret = -ENOENT;
  305. char *name;
  306. if (!cda[CTA_TIMEOUT_NAME]) {
  307. list_for_each_entry_safe(cur, tmp, &net->nfct_timeout_list,
  308. head)
  309. ctnl_timeout_try_del(net, cur);
  310. return 0;
  311. }
  312. name = nla_data(cda[CTA_TIMEOUT_NAME]);
  313. list_for_each_entry(cur, &net->nfct_timeout_list, head) {
  314. if (strncmp(cur->name, name, CTNL_TIMEOUT_NAME_MAX) != 0)
  315. continue;
  316. ret = ctnl_timeout_try_del(net, cur);
  317. if (ret < 0)
  318. return ret;
  319. break;
  320. }
  321. return ret;
  322. }
  323. static int cttimeout_default_set(struct net *net, struct sock *ctnl,
  324. struct sk_buff *skb,
  325. const struct nlmsghdr *nlh,
  326. const struct nlattr * const cda[])
  327. {
  328. __u16 l3num;
  329. __u8 l4num;
  330. struct nf_conntrack_l4proto *l4proto;
  331. unsigned int *timeouts;
  332. int ret;
  333. if (!cda[CTA_TIMEOUT_L3PROTO] ||
  334. !cda[CTA_TIMEOUT_L4PROTO] ||
  335. !cda[CTA_TIMEOUT_DATA])
  336. return -EINVAL;
  337. l3num = ntohs(nla_get_be16(cda[CTA_TIMEOUT_L3PROTO]));
  338. l4num = nla_get_u8(cda[CTA_TIMEOUT_L4PROTO]);
  339. l4proto = nf_ct_l4proto_find_get(l3num, l4num);
  340. /* This protocol is not supported, skip. */
  341. if (l4proto->l4proto != l4num) {
  342. ret = -EOPNOTSUPP;
  343. goto err;
  344. }
  345. timeouts = l4proto->get_timeouts(net);
  346. ret = ctnl_timeout_parse_policy(timeouts, l4proto, net,
  347. cda[CTA_TIMEOUT_DATA]);
  348. if (ret < 0)
  349. goto err;
  350. nf_ct_l4proto_put(l4proto);
  351. return 0;
  352. err:
  353. nf_ct_l4proto_put(l4proto);
  354. return ret;
  355. }
  356. static int
  357. cttimeout_default_fill_info(struct net *net, struct sk_buff *skb, u32 portid,
  358. u32 seq, u32 type, int event,
  359. struct nf_conntrack_l4proto *l4proto)
  360. {
  361. struct nlmsghdr *nlh;
  362. struct nfgenmsg *nfmsg;
  363. unsigned int flags = portid ? NLM_F_MULTI : 0;
  364. event |= NFNL_SUBSYS_CTNETLINK_TIMEOUT << 8;
  365. nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags);
  366. if (nlh == NULL)
  367. goto nlmsg_failure;
  368. nfmsg = nlmsg_data(nlh);
  369. nfmsg->nfgen_family = AF_UNSPEC;
  370. nfmsg->version = NFNETLINK_V0;
  371. nfmsg->res_id = 0;
  372. if (nla_put_be16(skb, CTA_TIMEOUT_L3PROTO, htons(l4proto->l3proto)) ||
  373. nla_put_u8(skb, CTA_TIMEOUT_L4PROTO, l4proto->l4proto))
  374. goto nla_put_failure;
  375. if (likely(l4proto->ctnl_timeout.obj_to_nlattr)) {
  376. struct nlattr *nest_parms;
  377. unsigned int *timeouts = l4proto->get_timeouts(net);
  378. int ret;
  379. nest_parms = nla_nest_start(skb,
  380. CTA_TIMEOUT_DATA | NLA_F_NESTED);
  381. if (!nest_parms)
  382. goto nla_put_failure;
  383. ret = l4proto->ctnl_timeout.obj_to_nlattr(skb, timeouts);
  384. if (ret < 0)
  385. goto nla_put_failure;
  386. nla_nest_end(skb, nest_parms);
  387. }
  388. nlmsg_end(skb, nlh);
  389. return skb->len;
  390. nlmsg_failure:
  391. nla_put_failure:
  392. nlmsg_cancel(skb, nlh);
  393. return -1;
  394. }
  395. static int cttimeout_default_get(struct net *net, struct sock *ctnl,
  396. struct sk_buff *skb,
  397. const struct nlmsghdr *nlh,
  398. const struct nlattr * const cda[])
  399. {
  400. __u16 l3num;
  401. __u8 l4num;
  402. struct nf_conntrack_l4proto *l4proto;
  403. struct sk_buff *skb2;
  404. int ret, err;
  405. if (!cda[CTA_TIMEOUT_L3PROTO] || !cda[CTA_TIMEOUT_L4PROTO])
  406. return -EINVAL;
  407. l3num = ntohs(nla_get_be16(cda[CTA_TIMEOUT_L3PROTO]));
  408. l4num = nla_get_u8(cda[CTA_TIMEOUT_L4PROTO]);
  409. l4proto = nf_ct_l4proto_find_get(l3num, l4num);
  410. /* This protocol is not supported, skip. */
  411. if (l4proto->l4proto != l4num) {
  412. err = -EOPNOTSUPP;
  413. goto err;
  414. }
  415. skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
  416. if (skb2 == NULL) {
  417. err = -ENOMEM;
  418. goto err;
  419. }
  420. ret = cttimeout_default_fill_info(net, skb2, NETLINK_CB(skb).portid,
  421. nlh->nlmsg_seq,
  422. NFNL_MSG_TYPE(nlh->nlmsg_type),
  423. IPCTNL_MSG_TIMEOUT_DEFAULT_SET,
  424. l4proto);
  425. if (ret <= 0) {
  426. kfree_skb(skb2);
  427. err = -ENOMEM;
  428. goto err;
  429. }
  430. ret = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).portid, MSG_DONTWAIT);
  431. if (ret > 0)
  432. ret = 0;
  433. /* this avoids a loop in nfnetlink. */
  434. return ret == -EAGAIN ? -ENOBUFS : ret;
  435. err:
  436. nf_ct_l4proto_put(l4proto);
  437. return err;
  438. }
  439. #ifdef CONFIG_NF_CONNTRACK_TIMEOUT
  440. static struct ctnl_timeout *
  441. ctnl_timeout_find_get(struct net *net, const char *name)
  442. {
  443. struct ctnl_timeout *timeout, *matching = NULL;
  444. rcu_read_lock();
  445. list_for_each_entry_rcu(timeout, &net->nfct_timeout_list, head) {
  446. if (strncmp(timeout->name, name, CTNL_TIMEOUT_NAME_MAX) != 0)
  447. continue;
  448. if (!try_module_get(THIS_MODULE))
  449. goto err;
  450. if (!atomic_inc_not_zero(&timeout->refcnt)) {
  451. module_put(THIS_MODULE);
  452. goto err;
  453. }
  454. matching = timeout;
  455. break;
  456. }
  457. err:
  458. rcu_read_unlock();
  459. return matching;
  460. }
  461. static void ctnl_timeout_put(struct ctnl_timeout *timeout)
  462. {
  463. if (atomic_dec_and_test(&timeout->refcnt))
  464. kfree_rcu(timeout, rcu_head);
  465. module_put(THIS_MODULE);
  466. }
  467. #endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
  468. static const struct nfnl_callback cttimeout_cb[IPCTNL_MSG_TIMEOUT_MAX] = {
  469. [IPCTNL_MSG_TIMEOUT_NEW] = { .call = cttimeout_new_timeout,
  470. .attr_count = CTA_TIMEOUT_MAX,
  471. .policy = cttimeout_nla_policy },
  472. [IPCTNL_MSG_TIMEOUT_GET] = { .call = cttimeout_get_timeout,
  473. .attr_count = CTA_TIMEOUT_MAX,
  474. .policy = cttimeout_nla_policy },
  475. [IPCTNL_MSG_TIMEOUT_DELETE] = { .call = cttimeout_del_timeout,
  476. .attr_count = CTA_TIMEOUT_MAX,
  477. .policy = cttimeout_nla_policy },
  478. [IPCTNL_MSG_TIMEOUT_DEFAULT_SET]= { .call = cttimeout_default_set,
  479. .attr_count = CTA_TIMEOUT_MAX,
  480. .policy = cttimeout_nla_policy },
  481. [IPCTNL_MSG_TIMEOUT_DEFAULT_GET]= { .call = cttimeout_default_get,
  482. .attr_count = CTA_TIMEOUT_MAX,
  483. .policy = cttimeout_nla_policy },
  484. };
  485. static const struct nfnetlink_subsystem cttimeout_subsys = {
  486. .name = "conntrack_timeout",
  487. .subsys_id = NFNL_SUBSYS_CTNETLINK_TIMEOUT,
  488. .cb_count = IPCTNL_MSG_TIMEOUT_MAX,
  489. .cb = cttimeout_cb,
  490. };
  491. MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK_TIMEOUT);
  492. static int __net_init cttimeout_net_init(struct net *net)
  493. {
  494. INIT_LIST_HEAD(&net->nfct_timeout_list);
  495. return 0;
  496. }
  497. static void __net_exit cttimeout_net_exit(struct net *net)
  498. {
  499. struct ctnl_timeout *cur, *tmp;
  500. ctnl_untimeout(net, NULL);
  501. list_for_each_entry_safe(cur, tmp, &net->nfct_timeout_list, head) {
  502. list_del_rcu(&cur->head);
  503. nf_ct_l4proto_put(cur->l4proto);
  504. if (atomic_dec_and_test(&cur->refcnt))
  505. kfree_rcu(cur, rcu_head);
  506. }
  507. }
  508. static struct pernet_operations cttimeout_ops = {
  509. .init = cttimeout_net_init,
  510. .exit = cttimeout_net_exit,
  511. };
  512. static int __init cttimeout_init(void)
  513. {
  514. int ret;
  515. ret = register_pernet_subsys(&cttimeout_ops);
  516. if (ret < 0)
  517. return ret;
  518. ret = nfnetlink_subsys_register(&cttimeout_subsys);
  519. if (ret < 0) {
  520. pr_err("cttimeout_init: cannot register cttimeout with "
  521. "nfnetlink.\n");
  522. goto err_out;
  523. }
  524. #ifdef CONFIG_NF_CONNTRACK_TIMEOUT
  525. RCU_INIT_POINTER(nf_ct_timeout_find_get_hook, ctnl_timeout_find_get);
  526. RCU_INIT_POINTER(nf_ct_timeout_put_hook, ctnl_timeout_put);
  527. #endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
  528. return 0;
  529. err_out:
  530. unregister_pernet_subsys(&cttimeout_ops);
  531. return ret;
  532. }
  533. static void __exit cttimeout_exit(void)
  534. {
  535. pr_info("cttimeout: unregistering from nfnetlink.\n");
  536. nfnetlink_subsys_unregister(&cttimeout_subsys);
  537. unregister_pernet_subsys(&cttimeout_ops);
  538. #ifdef CONFIG_NF_CONNTRACK_TIMEOUT
  539. RCU_INIT_POINTER(nf_ct_timeout_find_get_hook, NULL);
  540. RCU_INIT_POINTER(nf_ct_timeout_put_hook, NULL);
  541. synchronize_rcu();
  542. #endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
  543. }
  544. module_init(cttimeout_init);
  545. module_exit(cttimeout_exit);