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