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