nf_conntrack_proto.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include <linux/types.h>
  3. #include <linux/netfilter.h>
  4. #include <linux/module.h>
  5. #include <linux/slab.h>
  6. #include <linux/mutex.h>
  7. #include <linux/vmalloc.h>
  8. #include <linux/stddef.h>
  9. #include <linux/err.h>
  10. #include <linux/percpu.h>
  11. #include <linux/notifier.h>
  12. #include <linux/kernel.h>
  13. #include <linux/netdevice.h>
  14. #include <net/netfilter/nf_conntrack.h>
  15. #include <net/netfilter/nf_conntrack_l4proto.h>
  16. #include <net/netfilter/nf_conntrack_core.h>
  17. #include <net/netfilter/nf_conntrack_bridge.h>
  18. #include <net/netfilter/nf_log.h>
  19. #include <linux/ip.h>
  20. #include <linux/icmp.h>
  21. #include <linux/sysctl.h>
  22. #include <net/route.h>
  23. #include <net/ip.h>
  24. #include <linux/netfilter_ipv4.h>
  25. #include <linux/netfilter_ipv6.h>
  26. #include <linux/netfilter_ipv6/ip6_tables.h>
  27. #include <net/netfilter/nf_conntrack_helper.h>
  28. #include <net/netfilter/nf_conntrack_zones.h>
  29. #include <net/netfilter/nf_conntrack_seqadj.h>
  30. #include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
  31. #include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
  32. #include <net/netfilter/nf_nat_helper.h>
  33. #include <net/netfilter/ipv4/nf_defrag_ipv4.h>
  34. #include <net/netfilter/ipv6/nf_defrag_ipv6.h>
  35. #include <linux/ipv6.h>
  36. #include <linux/in6.h>
  37. #include <net/ipv6.h>
  38. #include <net/inet_frag.h>
  39. extern unsigned int nf_conntrack_net_id;
  40. static DEFINE_MUTEX(nf_ct_proto_mutex);
  41. #ifdef CONFIG_SYSCTL
  42. __printf(5, 6)
  43. void nf_l4proto_log_invalid(const struct sk_buff *skb,
  44. struct net *net,
  45. u16 pf, u8 protonum,
  46. const char *fmt, ...)
  47. {
  48. struct va_format vaf;
  49. va_list args;
  50. if (net->ct.sysctl_log_invalid != protonum &&
  51. net->ct.sysctl_log_invalid != IPPROTO_RAW)
  52. return;
  53. va_start(args, fmt);
  54. vaf.fmt = fmt;
  55. vaf.va = &args;
  56. nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
  57. "nf_ct_proto_%d: %pV ", protonum, &vaf);
  58. va_end(args);
  59. }
  60. EXPORT_SYMBOL_GPL(nf_l4proto_log_invalid);
  61. __printf(3, 4)
  62. void nf_ct_l4proto_log_invalid(const struct sk_buff *skb,
  63. const struct nf_conn *ct,
  64. const char *fmt, ...)
  65. {
  66. struct va_format vaf;
  67. struct net *net;
  68. va_list args;
  69. net = nf_ct_net(ct);
  70. if (likely(net->ct.sysctl_log_invalid == 0))
  71. return;
  72. va_start(args, fmt);
  73. vaf.fmt = fmt;
  74. vaf.va = &args;
  75. nf_l4proto_log_invalid(skb, net, nf_ct_l3num(ct),
  76. nf_ct_protonum(ct), "%pV", &vaf);
  77. va_end(args);
  78. }
  79. EXPORT_SYMBOL_GPL(nf_ct_l4proto_log_invalid);
  80. #endif
  81. const struct nf_conntrack_l4proto *nf_ct_l4proto_find(u8 l4proto)
  82. {
  83. switch (l4proto) {
  84. case IPPROTO_UDP: return &nf_conntrack_l4proto_udp;
  85. case IPPROTO_TCP: return &nf_conntrack_l4proto_tcp;
  86. case IPPROTO_ICMP: return &nf_conntrack_l4proto_icmp;
  87. #ifdef CONFIG_NF_CT_PROTO_DCCP
  88. case IPPROTO_DCCP: return &nf_conntrack_l4proto_dccp;
  89. #endif
  90. #ifdef CONFIG_NF_CT_PROTO_SCTP
  91. case IPPROTO_SCTP: return &nf_conntrack_l4proto_sctp;
  92. #endif
  93. #ifdef CONFIG_NF_CT_PROTO_UDPLITE
  94. case IPPROTO_UDPLITE: return &nf_conntrack_l4proto_udplite;
  95. #endif
  96. #ifdef CONFIG_NF_CT_PROTO_GRE
  97. case IPPROTO_GRE: return &nf_conntrack_l4proto_gre;
  98. #endif
  99. #if IS_ENABLED(CONFIG_IPV6)
  100. case IPPROTO_ICMPV6: return &nf_conntrack_l4proto_icmpv6;
  101. #endif /* CONFIG_IPV6 */
  102. }
  103. return &nf_conntrack_l4proto_generic;
  104. };
  105. EXPORT_SYMBOL_GPL(nf_ct_l4proto_find);
  106. unsigned int nf_confirm(struct sk_buff *skb, unsigned int protoff,
  107. struct nf_conn *ct, enum ip_conntrack_info ctinfo)
  108. {
  109. const struct nf_conn_help *help;
  110. help = nfct_help(ct);
  111. if (help) {
  112. const struct nf_conntrack_helper *helper;
  113. int ret;
  114. /* rcu_read_lock()ed by nf_hook_thresh */
  115. helper = rcu_dereference(help->helper);
  116. if (helper) {
  117. ret = helper->help(skb,
  118. protoff,
  119. ct, ctinfo);
  120. if (ret != NF_ACCEPT)
  121. return ret;
  122. }
  123. }
  124. if (test_bit(IPS_SEQ_ADJUST_BIT, &ct->status) &&
  125. !nf_is_loopback_packet(skb)) {
  126. if (!nf_ct_seq_adjust(skb, ct, ctinfo, protoff)) {
  127. NF_CT_STAT_INC_ATOMIC(nf_ct_net(ct), drop);
  128. return NF_DROP;
  129. }
  130. }
  131. /* We've seen it coming out the other side: confirm it */
  132. return nf_conntrack_confirm(skb);
  133. }
  134. EXPORT_SYMBOL_GPL(nf_confirm);
  135. static unsigned int ipv4_confirm(void *priv,
  136. struct sk_buff *skb,
  137. const struct nf_hook_state *state)
  138. {
  139. enum ip_conntrack_info ctinfo;
  140. struct nf_conn *ct;
  141. ct = nf_ct_get(skb, &ctinfo);
  142. if (!ct || ctinfo == IP_CT_RELATED_REPLY)
  143. return nf_conntrack_confirm(skb);
  144. return nf_confirm(skb,
  145. skb_network_offset(skb) + ip_hdrlen(skb),
  146. ct, ctinfo);
  147. }
  148. static unsigned int ipv4_conntrack_in(void *priv,
  149. struct sk_buff *skb,
  150. const struct nf_hook_state *state)
  151. {
  152. return nf_conntrack_in(skb, state);
  153. }
  154. static unsigned int ipv4_conntrack_local(void *priv,
  155. struct sk_buff *skb,
  156. const struct nf_hook_state *state)
  157. {
  158. if (ip_is_fragment(ip_hdr(skb))) { /* IP_NODEFRAG setsockopt set */
  159. enum ip_conntrack_info ctinfo;
  160. struct nf_conn *tmpl;
  161. tmpl = nf_ct_get(skb, &ctinfo);
  162. if (tmpl && nf_ct_is_template(tmpl)) {
  163. /* when skipping ct, clear templates to avoid fooling
  164. * later targets/matches
  165. */
  166. skb->_nfct = 0;
  167. nf_ct_put(tmpl);
  168. }
  169. return NF_ACCEPT;
  170. }
  171. return nf_conntrack_in(skb, state);
  172. }
  173. /* Connection tracking may drop packets, but never alters them, so
  174. * make it the first hook.
  175. */
  176. static const struct nf_hook_ops ipv4_conntrack_ops[] = {
  177. {
  178. .hook = ipv4_conntrack_in,
  179. .pf = NFPROTO_IPV4,
  180. .hooknum = NF_INET_PRE_ROUTING,
  181. .priority = NF_IP_PRI_CONNTRACK,
  182. },
  183. {
  184. .hook = ipv4_conntrack_local,
  185. .pf = NFPROTO_IPV4,
  186. .hooknum = NF_INET_LOCAL_OUT,
  187. .priority = NF_IP_PRI_CONNTRACK,
  188. },
  189. {
  190. .hook = ipv4_confirm,
  191. .pf = NFPROTO_IPV4,
  192. .hooknum = NF_INET_POST_ROUTING,
  193. .priority = NF_IP_PRI_CONNTRACK_CONFIRM,
  194. },
  195. {
  196. .hook = ipv4_confirm,
  197. .pf = NFPROTO_IPV4,
  198. .hooknum = NF_INET_LOCAL_IN,
  199. .priority = NF_IP_PRI_CONNTRACK_CONFIRM,
  200. },
  201. };
  202. /* Fast function for those who don't want to parse /proc (and I don't
  203. * blame them).
  204. * Reversing the socket's dst/src point of view gives us the reply
  205. * mapping.
  206. */
  207. static int
  208. getorigdst(struct sock *sk, int optval, void __user *user, int *len)
  209. {
  210. const struct inet_sock *inet = inet_sk(sk);
  211. const struct nf_conntrack_tuple_hash *h;
  212. struct nf_conntrack_tuple tuple;
  213. memset(&tuple, 0, sizeof(tuple));
  214. lock_sock(sk);
  215. tuple.src.u3.ip = inet->inet_rcv_saddr;
  216. tuple.src.u.tcp.port = inet->inet_sport;
  217. tuple.dst.u3.ip = inet->inet_daddr;
  218. tuple.dst.u.tcp.port = inet->inet_dport;
  219. tuple.src.l3num = PF_INET;
  220. tuple.dst.protonum = sk->sk_protocol;
  221. release_sock(sk);
  222. /* We only do TCP and SCTP at the moment: is there a better way? */
  223. if (tuple.dst.protonum != IPPROTO_TCP &&
  224. tuple.dst.protonum != IPPROTO_SCTP) {
  225. pr_debug("SO_ORIGINAL_DST: Not a TCP/SCTP socket\n");
  226. return -ENOPROTOOPT;
  227. }
  228. if ((unsigned int)*len < sizeof(struct sockaddr_in)) {
  229. pr_debug("SO_ORIGINAL_DST: len %d not %zu\n",
  230. *len, sizeof(struct sockaddr_in));
  231. return -EINVAL;
  232. }
  233. h = nf_conntrack_find_get(sock_net(sk), &nf_ct_zone_dflt, &tuple);
  234. if (h) {
  235. struct sockaddr_in sin;
  236. struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h);
  237. sin.sin_family = AF_INET;
  238. sin.sin_port = ct->tuplehash[IP_CT_DIR_ORIGINAL]
  239. .tuple.dst.u.tcp.port;
  240. sin.sin_addr.s_addr = ct->tuplehash[IP_CT_DIR_ORIGINAL]
  241. .tuple.dst.u3.ip;
  242. memset(sin.sin_zero, 0, sizeof(sin.sin_zero));
  243. pr_debug("SO_ORIGINAL_DST: %pI4 %u\n",
  244. &sin.sin_addr.s_addr, ntohs(sin.sin_port));
  245. nf_ct_put(ct);
  246. if (copy_to_user(user, &sin, sizeof(sin)) != 0)
  247. return -EFAULT;
  248. else
  249. return 0;
  250. }
  251. pr_debug("SO_ORIGINAL_DST: Can't find %pI4/%u-%pI4/%u.\n",
  252. &tuple.src.u3.ip, ntohs(tuple.src.u.tcp.port),
  253. &tuple.dst.u3.ip, ntohs(tuple.dst.u.tcp.port));
  254. return -ENOENT;
  255. }
  256. static struct nf_sockopt_ops so_getorigdst = {
  257. .pf = PF_INET,
  258. .get_optmin = SO_ORIGINAL_DST,
  259. .get_optmax = SO_ORIGINAL_DST + 1,
  260. .get = getorigdst,
  261. .owner = THIS_MODULE,
  262. };
  263. #if IS_ENABLED(CONFIG_IPV6)
  264. static int
  265. ipv6_getorigdst(struct sock *sk, int optval, void __user *user, int *len)
  266. {
  267. struct nf_conntrack_tuple tuple = { .src.l3num = NFPROTO_IPV6 };
  268. const struct ipv6_pinfo *inet6 = inet6_sk(sk);
  269. const struct inet_sock *inet = inet_sk(sk);
  270. const struct nf_conntrack_tuple_hash *h;
  271. struct sockaddr_in6 sin6;
  272. struct nf_conn *ct;
  273. __be32 flow_label;
  274. int bound_dev_if;
  275. lock_sock(sk);
  276. tuple.src.u3.in6 = sk->sk_v6_rcv_saddr;
  277. tuple.src.u.tcp.port = inet->inet_sport;
  278. tuple.dst.u3.in6 = sk->sk_v6_daddr;
  279. tuple.dst.u.tcp.port = inet->inet_dport;
  280. tuple.dst.protonum = sk->sk_protocol;
  281. bound_dev_if = sk->sk_bound_dev_if;
  282. flow_label = inet6->flow_label;
  283. release_sock(sk);
  284. if (tuple.dst.protonum != IPPROTO_TCP &&
  285. tuple.dst.protonum != IPPROTO_SCTP)
  286. return -ENOPROTOOPT;
  287. if (*len < 0 || (unsigned int)*len < sizeof(sin6))
  288. return -EINVAL;
  289. h = nf_conntrack_find_get(sock_net(sk), &nf_ct_zone_dflt, &tuple);
  290. if (!h) {
  291. pr_debug("IP6T_SO_ORIGINAL_DST: Can't find %pI6c/%u-%pI6c/%u.\n",
  292. &tuple.src.u3.ip6, ntohs(tuple.src.u.tcp.port),
  293. &tuple.dst.u3.ip6, ntohs(tuple.dst.u.tcp.port));
  294. return -ENOENT;
  295. }
  296. ct = nf_ct_tuplehash_to_ctrack(h);
  297. sin6.sin6_family = AF_INET6;
  298. sin6.sin6_port = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.tcp.port;
  299. sin6.sin6_flowinfo = flow_label & IPV6_FLOWINFO_MASK;
  300. memcpy(&sin6.sin6_addr,
  301. &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.in6,
  302. sizeof(sin6.sin6_addr));
  303. nf_ct_put(ct);
  304. sin6.sin6_scope_id = ipv6_iface_scope_id(&sin6.sin6_addr, bound_dev_if);
  305. return copy_to_user(user, &sin6, sizeof(sin6)) ? -EFAULT : 0;
  306. }
  307. static struct nf_sockopt_ops so_getorigdst6 = {
  308. .pf = NFPROTO_IPV6,
  309. .get_optmin = IP6T_SO_ORIGINAL_DST,
  310. .get_optmax = IP6T_SO_ORIGINAL_DST + 1,
  311. .get = ipv6_getorigdst,
  312. .owner = THIS_MODULE,
  313. };
  314. static unsigned int ipv6_confirm(void *priv,
  315. struct sk_buff *skb,
  316. const struct nf_hook_state *state)
  317. {
  318. struct nf_conn *ct;
  319. enum ip_conntrack_info ctinfo;
  320. unsigned char pnum = ipv6_hdr(skb)->nexthdr;
  321. __be16 frag_off;
  322. int protoff;
  323. ct = nf_ct_get(skb, &ctinfo);
  324. if (!ct || ctinfo == IP_CT_RELATED_REPLY)
  325. return nf_conntrack_confirm(skb);
  326. protoff = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &pnum,
  327. &frag_off);
  328. if (protoff < 0 || (frag_off & htons(~0x7)) != 0) {
  329. pr_debug("proto header not found\n");
  330. return nf_conntrack_confirm(skb);
  331. }
  332. return nf_confirm(skb, protoff, ct, ctinfo);
  333. }
  334. static unsigned int ipv6_conntrack_in(void *priv,
  335. struct sk_buff *skb,
  336. const struct nf_hook_state *state)
  337. {
  338. return nf_conntrack_in(skb, state);
  339. }
  340. static unsigned int ipv6_conntrack_local(void *priv,
  341. struct sk_buff *skb,
  342. const struct nf_hook_state *state)
  343. {
  344. return nf_conntrack_in(skb, state);
  345. }
  346. static const struct nf_hook_ops ipv6_conntrack_ops[] = {
  347. {
  348. .hook = ipv6_conntrack_in,
  349. .pf = NFPROTO_IPV6,
  350. .hooknum = NF_INET_PRE_ROUTING,
  351. .priority = NF_IP6_PRI_CONNTRACK,
  352. },
  353. {
  354. .hook = ipv6_conntrack_local,
  355. .pf = NFPROTO_IPV6,
  356. .hooknum = NF_INET_LOCAL_OUT,
  357. .priority = NF_IP6_PRI_CONNTRACK,
  358. },
  359. {
  360. .hook = ipv6_confirm,
  361. .pf = NFPROTO_IPV6,
  362. .hooknum = NF_INET_POST_ROUTING,
  363. .priority = NF_IP6_PRI_LAST,
  364. },
  365. {
  366. .hook = ipv6_confirm,
  367. .pf = NFPROTO_IPV6,
  368. .hooknum = NF_INET_LOCAL_IN,
  369. .priority = NF_IP6_PRI_LAST - 1,
  370. },
  371. };
  372. #endif
  373. static int nf_ct_tcp_fixup(struct nf_conn *ct, void *_nfproto)
  374. {
  375. u8 nfproto = (unsigned long)_nfproto;
  376. if (nf_ct_l3num(ct) != nfproto)
  377. return 0;
  378. if (nf_ct_protonum(ct) == IPPROTO_TCP &&
  379. ct->proto.tcp.state == TCP_CONNTRACK_ESTABLISHED) {
  380. ct->proto.tcp.seen[0].td_maxwin = 0;
  381. ct->proto.tcp.seen[1].td_maxwin = 0;
  382. }
  383. return 0;
  384. }
  385. static struct nf_ct_bridge_info *nf_ct_bridge_info;
  386. static int nf_ct_netns_do_get(struct net *net, u8 nfproto)
  387. {
  388. struct nf_conntrack_net *cnet = net_generic(net, nf_conntrack_net_id);
  389. bool fixup_needed = false, retry = true;
  390. int err = 0;
  391. retry:
  392. mutex_lock(&nf_ct_proto_mutex);
  393. switch (nfproto) {
  394. case NFPROTO_IPV4:
  395. cnet->users4++;
  396. if (cnet->users4 > 1)
  397. goto out_unlock;
  398. err = nf_defrag_ipv4_enable(net);
  399. if (err) {
  400. cnet->users4 = 0;
  401. goto out_unlock;
  402. }
  403. err = nf_register_net_hooks(net, ipv4_conntrack_ops,
  404. ARRAY_SIZE(ipv4_conntrack_ops));
  405. if (err)
  406. cnet->users4 = 0;
  407. else
  408. fixup_needed = true;
  409. break;
  410. #if IS_ENABLED(CONFIG_IPV6)
  411. case NFPROTO_IPV6:
  412. cnet->users6++;
  413. if (cnet->users6 > 1)
  414. goto out_unlock;
  415. err = nf_defrag_ipv6_enable(net);
  416. if (err < 0) {
  417. cnet->users6 = 0;
  418. goto out_unlock;
  419. }
  420. err = nf_register_net_hooks(net, ipv6_conntrack_ops,
  421. ARRAY_SIZE(ipv6_conntrack_ops));
  422. if (err)
  423. cnet->users6 = 0;
  424. else
  425. fixup_needed = true;
  426. break;
  427. #endif
  428. case NFPROTO_BRIDGE:
  429. if (!nf_ct_bridge_info) {
  430. if (!retry) {
  431. err = -EPROTO;
  432. goto out_unlock;
  433. }
  434. mutex_unlock(&nf_ct_proto_mutex);
  435. request_module("nf_conntrack_bridge");
  436. retry = false;
  437. goto retry;
  438. }
  439. if (!try_module_get(nf_ct_bridge_info->me)) {
  440. err = -EPROTO;
  441. goto out_unlock;
  442. }
  443. cnet->users_bridge++;
  444. if (cnet->users_bridge > 1)
  445. goto out_unlock;
  446. err = nf_register_net_hooks(net, nf_ct_bridge_info->ops,
  447. nf_ct_bridge_info->ops_size);
  448. if (err)
  449. cnet->users_bridge = 0;
  450. else
  451. fixup_needed = true;
  452. break;
  453. default:
  454. err = -EPROTO;
  455. break;
  456. }
  457. out_unlock:
  458. mutex_unlock(&nf_ct_proto_mutex);
  459. if (fixup_needed)
  460. nf_ct_iterate_cleanup_net(net, nf_ct_tcp_fixup,
  461. (void *)(unsigned long)nfproto, 0, 0);
  462. return err;
  463. }
  464. static void nf_ct_netns_do_put(struct net *net, u8 nfproto)
  465. {
  466. struct nf_conntrack_net *cnet = net_generic(net, nf_conntrack_net_id);
  467. mutex_lock(&nf_ct_proto_mutex);
  468. switch (nfproto) {
  469. case NFPROTO_IPV4:
  470. if (cnet->users4 && (--cnet->users4 == 0))
  471. nf_unregister_net_hooks(net, ipv4_conntrack_ops,
  472. ARRAY_SIZE(ipv4_conntrack_ops));
  473. break;
  474. #if IS_ENABLED(CONFIG_IPV6)
  475. case NFPROTO_IPV6:
  476. if (cnet->users6 && (--cnet->users6 == 0))
  477. nf_unregister_net_hooks(net, ipv6_conntrack_ops,
  478. ARRAY_SIZE(ipv6_conntrack_ops));
  479. break;
  480. #endif
  481. case NFPROTO_BRIDGE:
  482. if (!nf_ct_bridge_info)
  483. break;
  484. if (cnet->users_bridge && (--cnet->users_bridge == 0))
  485. nf_unregister_net_hooks(net, nf_ct_bridge_info->ops,
  486. nf_ct_bridge_info->ops_size);
  487. module_put(nf_ct_bridge_info->me);
  488. break;
  489. }
  490. mutex_unlock(&nf_ct_proto_mutex);
  491. }
  492. static int nf_ct_netns_inet_get(struct net *net)
  493. {
  494. int err;
  495. err = nf_ct_netns_do_get(net, NFPROTO_IPV4);
  496. #if IS_ENABLED(CONFIG_IPV6)
  497. if (err < 0)
  498. goto err1;
  499. err = nf_ct_netns_do_get(net, NFPROTO_IPV6);
  500. if (err < 0)
  501. goto err2;
  502. return err;
  503. err2:
  504. nf_ct_netns_put(net, NFPROTO_IPV4);
  505. err1:
  506. #endif
  507. return err;
  508. }
  509. int nf_ct_netns_get(struct net *net, u8 nfproto)
  510. {
  511. int err;
  512. switch (nfproto) {
  513. case NFPROTO_INET:
  514. err = nf_ct_netns_inet_get(net);
  515. break;
  516. case NFPROTO_BRIDGE:
  517. err = nf_ct_netns_do_get(net, NFPROTO_BRIDGE);
  518. if (err < 0)
  519. return err;
  520. err = nf_ct_netns_inet_get(net);
  521. if (err < 0) {
  522. nf_ct_netns_put(net, NFPROTO_BRIDGE);
  523. return err;
  524. }
  525. break;
  526. default:
  527. err = nf_ct_netns_do_get(net, nfproto);
  528. break;
  529. }
  530. return err;
  531. }
  532. EXPORT_SYMBOL_GPL(nf_ct_netns_get);
  533. void nf_ct_netns_put(struct net *net, uint8_t nfproto)
  534. {
  535. switch (nfproto) {
  536. case NFPROTO_BRIDGE:
  537. nf_ct_netns_do_put(net, NFPROTO_BRIDGE);
  538. fallthrough;
  539. case NFPROTO_INET:
  540. nf_ct_netns_do_put(net, NFPROTO_IPV4);
  541. nf_ct_netns_do_put(net, NFPROTO_IPV6);
  542. break;
  543. default:
  544. nf_ct_netns_do_put(net, nfproto);
  545. break;
  546. }
  547. }
  548. EXPORT_SYMBOL_GPL(nf_ct_netns_put);
  549. void nf_ct_bridge_register(struct nf_ct_bridge_info *info)
  550. {
  551. WARN_ON(nf_ct_bridge_info);
  552. mutex_lock(&nf_ct_proto_mutex);
  553. nf_ct_bridge_info = info;
  554. mutex_unlock(&nf_ct_proto_mutex);
  555. }
  556. EXPORT_SYMBOL_GPL(nf_ct_bridge_register);
  557. void nf_ct_bridge_unregister(struct nf_ct_bridge_info *info)
  558. {
  559. WARN_ON(!nf_ct_bridge_info);
  560. mutex_lock(&nf_ct_proto_mutex);
  561. nf_ct_bridge_info = NULL;
  562. mutex_unlock(&nf_ct_proto_mutex);
  563. }
  564. EXPORT_SYMBOL_GPL(nf_ct_bridge_unregister);
  565. int nf_conntrack_proto_init(void)
  566. {
  567. int ret;
  568. ret = nf_register_sockopt(&so_getorigdst);
  569. if (ret < 0)
  570. return ret;
  571. #if IS_ENABLED(CONFIG_IPV6)
  572. ret = nf_register_sockopt(&so_getorigdst6);
  573. if (ret < 0)
  574. goto cleanup_sockopt;
  575. #endif
  576. return ret;
  577. #if IS_ENABLED(CONFIG_IPV6)
  578. cleanup_sockopt:
  579. nf_unregister_sockopt(&so_getorigdst);
  580. #endif
  581. return ret;
  582. }
  583. void nf_conntrack_proto_fini(void)
  584. {
  585. nf_unregister_sockopt(&so_getorigdst);
  586. #if IS_ENABLED(CONFIG_IPV6)
  587. nf_unregister_sockopt(&so_getorigdst6);
  588. #endif
  589. }
  590. void nf_conntrack_proto_pernet_init(struct net *net)
  591. {
  592. nf_conntrack_generic_init_net(net);
  593. nf_conntrack_udp_init_net(net);
  594. nf_conntrack_tcp_init_net(net);
  595. nf_conntrack_icmp_init_net(net);
  596. #if IS_ENABLED(CONFIG_IPV6)
  597. nf_conntrack_icmpv6_init_net(net);
  598. #endif
  599. #ifdef CONFIG_NF_CT_PROTO_DCCP
  600. nf_conntrack_dccp_init_net(net);
  601. #endif
  602. #ifdef CONFIG_NF_CT_PROTO_SCTP
  603. nf_conntrack_sctp_init_net(net);
  604. #endif
  605. #ifdef CONFIG_NF_CT_PROTO_GRE
  606. nf_conntrack_gre_init_net(net);
  607. #endif
  608. }
  609. void nf_conntrack_proto_pernet_fini(struct net *net)
  610. {
  611. #ifdef CONFIG_NF_CT_PROTO_GRE
  612. nf_ct_gre_keymap_flush(net);
  613. #endif
  614. }
  615. module_param_call(hashsize, nf_conntrack_set_hashsize, param_get_uint,
  616. &nf_conntrack_htable_size, 0600);
  617. MODULE_ALIAS("ip_conntrack");
  618. MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET));
  619. MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET6));
  620. MODULE_LICENSE("GPL");