0001
0002
0003 #include <linux/types.h>
0004 #include <linux/netfilter.h>
0005 #include <linux/module.h>
0006 #include <linux/slab.h>
0007 #include <linux/mutex.h>
0008 #include <linux/vmalloc.h>
0009 #include <linux/stddef.h>
0010 #include <linux/err.h>
0011 #include <linux/percpu.h>
0012 #include <linux/notifier.h>
0013 #include <linux/kernel.h>
0014 #include <linux/netdevice.h>
0015
0016 #include <net/netfilter/nf_conntrack.h>
0017 #include <net/netfilter/nf_conntrack_l4proto.h>
0018 #include <net/netfilter/nf_conntrack_core.h>
0019 #include <net/netfilter/nf_conntrack_bridge.h>
0020 #include <net/netfilter/nf_log.h>
0021
0022 #include <linux/ip.h>
0023 #include <linux/icmp.h>
0024 #include <linux/sysctl.h>
0025 #include <net/route.h>
0026 #include <net/ip.h>
0027
0028 #include <linux/netfilter_ipv4.h>
0029 #include <linux/netfilter_ipv6.h>
0030 #include <linux/netfilter_ipv6/ip6_tables.h>
0031 #include <net/netfilter/nf_conntrack_helper.h>
0032 #include <net/netfilter/nf_conntrack_zones.h>
0033 #include <net/netfilter/nf_conntrack_seqadj.h>
0034 #include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
0035 #include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
0036 #include <net/netfilter/nf_nat_helper.h>
0037 #include <net/netfilter/ipv4/nf_defrag_ipv4.h>
0038 #include <net/netfilter/ipv6/nf_defrag_ipv6.h>
0039
0040 #include <linux/ipv6.h>
0041 #include <linux/in6.h>
0042 #include <net/ipv6.h>
0043 #include <net/inet_frag.h>
0044
0045 static DEFINE_MUTEX(nf_ct_proto_mutex);
0046
0047 #ifdef CONFIG_SYSCTL
0048 __printf(4, 5)
0049 void nf_l4proto_log_invalid(const struct sk_buff *skb,
0050 const struct nf_hook_state *state,
0051 u8 protonum,
0052 const char *fmt, ...)
0053 {
0054 struct net *net = state->net;
0055 struct va_format vaf;
0056 va_list args;
0057
0058 if (net->ct.sysctl_log_invalid != protonum &&
0059 net->ct.sysctl_log_invalid != IPPROTO_RAW)
0060 return;
0061
0062 va_start(args, fmt);
0063 vaf.fmt = fmt;
0064 vaf.va = &args;
0065
0066 nf_log_packet(net, state->pf, 0, skb, state->in, state->out,
0067 NULL, "nf_ct_proto_%d: %pV ", protonum, &vaf);
0068 va_end(args);
0069 }
0070 EXPORT_SYMBOL_GPL(nf_l4proto_log_invalid);
0071
0072 __printf(4, 5)
0073 void nf_ct_l4proto_log_invalid(const struct sk_buff *skb,
0074 const struct nf_conn *ct,
0075 const struct nf_hook_state *state,
0076 const char *fmt, ...)
0077 {
0078 struct va_format vaf;
0079 struct net *net;
0080 va_list args;
0081
0082 net = nf_ct_net(ct);
0083 if (likely(net->ct.sysctl_log_invalid == 0))
0084 return;
0085
0086 va_start(args, fmt);
0087 vaf.fmt = fmt;
0088 vaf.va = &args;
0089
0090 nf_l4proto_log_invalid(skb, state,
0091 nf_ct_protonum(ct), "%pV", &vaf);
0092 va_end(args);
0093 }
0094 EXPORT_SYMBOL_GPL(nf_ct_l4proto_log_invalid);
0095 #endif
0096
0097 const struct nf_conntrack_l4proto *nf_ct_l4proto_find(u8 l4proto)
0098 {
0099 switch (l4proto) {
0100 case IPPROTO_UDP: return &nf_conntrack_l4proto_udp;
0101 case IPPROTO_TCP: return &nf_conntrack_l4proto_tcp;
0102 case IPPROTO_ICMP: return &nf_conntrack_l4proto_icmp;
0103 #ifdef CONFIG_NF_CT_PROTO_DCCP
0104 case IPPROTO_DCCP: return &nf_conntrack_l4proto_dccp;
0105 #endif
0106 #ifdef CONFIG_NF_CT_PROTO_SCTP
0107 case IPPROTO_SCTP: return &nf_conntrack_l4proto_sctp;
0108 #endif
0109 #ifdef CONFIG_NF_CT_PROTO_UDPLITE
0110 case IPPROTO_UDPLITE: return &nf_conntrack_l4proto_udplite;
0111 #endif
0112 #ifdef CONFIG_NF_CT_PROTO_GRE
0113 case IPPROTO_GRE: return &nf_conntrack_l4proto_gre;
0114 #endif
0115 #if IS_ENABLED(CONFIG_IPV6)
0116 case IPPROTO_ICMPV6: return &nf_conntrack_l4proto_icmpv6;
0117 #endif
0118 }
0119
0120 return &nf_conntrack_l4proto_generic;
0121 };
0122 EXPORT_SYMBOL_GPL(nf_ct_l4proto_find);
0123
0124 unsigned int nf_confirm(struct sk_buff *skb, unsigned int protoff,
0125 struct nf_conn *ct, enum ip_conntrack_info ctinfo)
0126 {
0127 const struct nf_conn_help *help;
0128
0129 help = nfct_help(ct);
0130 if (help) {
0131 const struct nf_conntrack_helper *helper;
0132 int ret;
0133
0134
0135 helper = rcu_dereference(help->helper);
0136 if (helper) {
0137 ret = helper->help(skb,
0138 protoff,
0139 ct, ctinfo);
0140 if (ret != NF_ACCEPT)
0141 return ret;
0142 }
0143 }
0144
0145 if (test_bit(IPS_SEQ_ADJUST_BIT, &ct->status) &&
0146 !nf_is_loopback_packet(skb)) {
0147 if (!nf_ct_seq_adjust(skb, ct, ctinfo, protoff)) {
0148 NF_CT_STAT_INC_ATOMIC(nf_ct_net(ct), drop);
0149 return NF_DROP;
0150 }
0151 }
0152
0153
0154 return nf_conntrack_confirm(skb);
0155 }
0156 EXPORT_SYMBOL_GPL(nf_confirm);
0157
0158 static bool in_vrf_postrouting(const struct nf_hook_state *state)
0159 {
0160 #if IS_ENABLED(CONFIG_NET_L3_MASTER_DEV)
0161 if (state->hook == NF_INET_POST_ROUTING &&
0162 netif_is_l3_master(state->out))
0163 return true;
0164 #endif
0165 return false;
0166 }
0167
0168 static unsigned int ipv4_confirm(void *priv,
0169 struct sk_buff *skb,
0170 const struct nf_hook_state *state)
0171 {
0172 enum ip_conntrack_info ctinfo;
0173 struct nf_conn *ct;
0174
0175 ct = nf_ct_get(skb, &ctinfo);
0176 if (!ct || ctinfo == IP_CT_RELATED_REPLY)
0177 return nf_conntrack_confirm(skb);
0178
0179 if (in_vrf_postrouting(state))
0180 return NF_ACCEPT;
0181
0182 return nf_confirm(skb,
0183 skb_network_offset(skb) + ip_hdrlen(skb),
0184 ct, ctinfo);
0185 }
0186
0187 static unsigned int ipv4_conntrack_in(void *priv,
0188 struct sk_buff *skb,
0189 const struct nf_hook_state *state)
0190 {
0191 return nf_conntrack_in(skb, state);
0192 }
0193
0194 static unsigned int ipv4_conntrack_local(void *priv,
0195 struct sk_buff *skb,
0196 const struct nf_hook_state *state)
0197 {
0198 if (ip_is_fragment(ip_hdr(skb))) {
0199 enum ip_conntrack_info ctinfo;
0200 struct nf_conn *tmpl;
0201
0202 tmpl = nf_ct_get(skb, &ctinfo);
0203 if (tmpl && nf_ct_is_template(tmpl)) {
0204
0205
0206
0207 skb->_nfct = 0;
0208 nf_ct_put(tmpl);
0209 }
0210 return NF_ACCEPT;
0211 }
0212
0213 return nf_conntrack_in(skb, state);
0214 }
0215
0216
0217
0218
0219 static const struct nf_hook_ops ipv4_conntrack_ops[] = {
0220 {
0221 .hook = ipv4_conntrack_in,
0222 .pf = NFPROTO_IPV4,
0223 .hooknum = NF_INET_PRE_ROUTING,
0224 .priority = NF_IP_PRI_CONNTRACK,
0225 },
0226 {
0227 .hook = ipv4_conntrack_local,
0228 .pf = NFPROTO_IPV4,
0229 .hooknum = NF_INET_LOCAL_OUT,
0230 .priority = NF_IP_PRI_CONNTRACK,
0231 },
0232 {
0233 .hook = ipv4_confirm,
0234 .pf = NFPROTO_IPV4,
0235 .hooknum = NF_INET_POST_ROUTING,
0236 .priority = NF_IP_PRI_CONNTRACK_CONFIRM,
0237 },
0238 {
0239 .hook = ipv4_confirm,
0240 .pf = NFPROTO_IPV4,
0241 .hooknum = NF_INET_LOCAL_IN,
0242 .priority = NF_IP_PRI_CONNTRACK_CONFIRM,
0243 },
0244 };
0245
0246
0247
0248
0249
0250
0251 static int
0252 getorigdst(struct sock *sk, int optval, void __user *user, int *len)
0253 {
0254 const struct inet_sock *inet = inet_sk(sk);
0255 const struct nf_conntrack_tuple_hash *h;
0256 struct nf_conntrack_tuple tuple;
0257
0258 memset(&tuple, 0, sizeof(tuple));
0259
0260 lock_sock(sk);
0261 tuple.src.u3.ip = inet->inet_rcv_saddr;
0262 tuple.src.u.tcp.port = inet->inet_sport;
0263 tuple.dst.u3.ip = inet->inet_daddr;
0264 tuple.dst.u.tcp.port = inet->inet_dport;
0265 tuple.src.l3num = PF_INET;
0266 tuple.dst.protonum = sk->sk_protocol;
0267 release_sock(sk);
0268
0269
0270 if (tuple.dst.protonum != IPPROTO_TCP &&
0271 tuple.dst.protonum != IPPROTO_SCTP) {
0272 pr_debug("SO_ORIGINAL_DST: Not a TCP/SCTP socket\n");
0273 return -ENOPROTOOPT;
0274 }
0275
0276 if ((unsigned int)*len < sizeof(struct sockaddr_in)) {
0277 pr_debug("SO_ORIGINAL_DST: len %d not %zu\n",
0278 *len, sizeof(struct sockaddr_in));
0279 return -EINVAL;
0280 }
0281
0282 h = nf_conntrack_find_get(sock_net(sk), &nf_ct_zone_dflt, &tuple);
0283 if (h) {
0284 struct sockaddr_in sin;
0285 struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h);
0286
0287 sin.sin_family = AF_INET;
0288 sin.sin_port = ct->tuplehash[IP_CT_DIR_ORIGINAL]
0289 .tuple.dst.u.tcp.port;
0290 sin.sin_addr.s_addr = ct->tuplehash[IP_CT_DIR_ORIGINAL]
0291 .tuple.dst.u3.ip;
0292 memset(sin.sin_zero, 0, sizeof(sin.sin_zero));
0293
0294 pr_debug("SO_ORIGINAL_DST: %pI4 %u\n",
0295 &sin.sin_addr.s_addr, ntohs(sin.sin_port));
0296 nf_ct_put(ct);
0297 if (copy_to_user(user, &sin, sizeof(sin)) != 0)
0298 return -EFAULT;
0299 else
0300 return 0;
0301 }
0302 pr_debug("SO_ORIGINAL_DST: Can't find %pI4/%u-%pI4/%u.\n",
0303 &tuple.src.u3.ip, ntohs(tuple.src.u.tcp.port),
0304 &tuple.dst.u3.ip, ntohs(tuple.dst.u.tcp.port));
0305 return -ENOENT;
0306 }
0307
0308 static struct nf_sockopt_ops so_getorigdst = {
0309 .pf = PF_INET,
0310 .get_optmin = SO_ORIGINAL_DST,
0311 .get_optmax = SO_ORIGINAL_DST + 1,
0312 .get = getorigdst,
0313 .owner = THIS_MODULE,
0314 };
0315
0316 #if IS_ENABLED(CONFIG_IPV6)
0317 static int
0318 ipv6_getorigdst(struct sock *sk, int optval, void __user *user, int *len)
0319 {
0320 struct nf_conntrack_tuple tuple = { .src.l3num = NFPROTO_IPV6 };
0321 const struct ipv6_pinfo *inet6 = inet6_sk(sk);
0322 const struct inet_sock *inet = inet_sk(sk);
0323 const struct nf_conntrack_tuple_hash *h;
0324 struct sockaddr_in6 sin6;
0325 struct nf_conn *ct;
0326 __be32 flow_label;
0327 int bound_dev_if;
0328
0329 lock_sock(sk);
0330 tuple.src.u3.in6 = sk->sk_v6_rcv_saddr;
0331 tuple.src.u.tcp.port = inet->inet_sport;
0332 tuple.dst.u3.in6 = sk->sk_v6_daddr;
0333 tuple.dst.u.tcp.port = inet->inet_dport;
0334 tuple.dst.protonum = sk->sk_protocol;
0335 bound_dev_if = sk->sk_bound_dev_if;
0336 flow_label = inet6->flow_label;
0337 release_sock(sk);
0338
0339 if (tuple.dst.protonum != IPPROTO_TCP &&
0340 tuple.dst.protonum != IPPROTO_SCTP)
0341 return -ENOPROTOOPT;
0342
0343 if (*len < 0 || (unsigned int)*len < sizeof(sin6))
0344 return -EINVAL;
0345
0346 h = nf_conntrack_find_get(sock_net(sk), &nf_ct_zone_dflt, &tuple);
0347 if (!h) {
0348 pr_debug("IP6T_SO_ORIGINAL_DST: Can't find %pI6c/%u-%pI6c/%u.\n",
0349 &tuple.src.u3.ip6, ntohs(tuple.src.u.tcp.port),
0350 &tuple.dst.u3.ip6, ntohs(tuple.dst.u.tcp.port));
0351 return -ENOENT;
0352 }
0353
0354 ct = nf_ct_tuplehash_to_ctrack(h);
0355
0356 sin6.sin6_family = AF_INET6;
0357 sin6.sin6_port = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.tcp.port;
0358 sin6.sin6_flowinfo = flow_label & IPV6_FLOWINFO_MASK;
0359 memcpy(&sin6.sin6_addr,
0360 &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.in6,
0361 sizeof(sin6.sin6_addr));
0362
0363 nf_ct_put(ct);
0364 sin6.sin6_scope_id = ipv6_iface_scope_id(&sin6.sin6_addr, bound_dev_if);
0365 return copy_to_user(user, &sin6, sizeof(sin6)) ? -EFAULT : 0;
0366 }
0367
0368 static struct nf_sockopt_ops so_getorigdst6 = {
0369 .pf = NFPROTO_IPV6,
0370 .get_optmin = IP6T_SO_ORIGINAL_DST,
0371 .get_optmax = IP6T_SO_ORIGINAL_DST + 1,
0372 .get = ipv6_getorigdst,
0373 .owner = THIS_MODULE,
0374 };
0375
0376 static unsigned int ipv6_confirm(void *priv,
0377 struct sk_buff *skb,
0378 const struct nf_hook_state *state)
0379 {
0380 struct nf_conn *ct;
0381 enum ip_conntrack_info ctinfo;
0382 unsigned char pnum = ipv6_hdr(skb)->nexthdr;
0383 __be16 frag_off;
0384 int protoff;
0385
0386 ct = nf_ct_get(skb, &ctinfo);
0387 if (!ct || ctinfo == IP_CT_RELATED_REPLY)
0388 return nf_conntrack_confirm(skb);
0389
0390 if (in_vrf_postrouting(state))
0391 return NF_ACCEPT;
0392
0393 protoff = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &pnum,
0394 &frag_off);
0395 if (protoff < 0 || (frag_off & htons(~0x7)) != 0) {
0396 pr_debug("proto header not found\n");
0397 return nf_conntrack_confirm(skb);
0398 }
0399
0400 return nf_confirm(skb, protoff, ct, ctinfo);
0401 }
0402
0403 static unsigned int ipv6_conntrack_in(void *priv,
0404 struct sk_buff *skb,
0405 const struct nf_hook_state *state)
0406 {
0407 return nf_conntrack_in(skb, state);
0408 }
0409
0410 static unsigned int ipv6_conntrack_local(void *priv,
0411 struct sk_buff *skb,
0412 const struct nf_hook_state *state)
0413 {
0414 return nf_conntrack_in(skb, state);
0415 }
0416
0417 static const struct nf_hook_ops ipv6_conntrack_ops[] = {
0418 {
0419 .hook = ipv6_conntrack_in,
0420 .pf = NFPROTO_IPV6,
0421 .hooknum = NF_INET_PRE_ROUTING,
0422 .priority = NF_IP6_PRI_CONNTRACK,
0423 },
0424 {
0425 .hook = ipv6_conntrack_local,
0426 .pf = NFPROTO_IPV6,
0427 .hooknum = NF_INET_LOCAL_OUT,
0428 .priority = NF_IP6_PRI_CONNTRACK,
0429 },
0430 {
0431 .hook = ipv6_confirm,
0432 .pf = NFPROTO_IPV6,
0433 .hooknum = NF_INET_POST_ROUTING,
0434 .priority = NF_IP6_PRI_LAST,
0435 },
0436 {
0437 .hook = ipv6_confirm,
0438 .pf = NFPROTO_IPV6,
0439 .hooknum = NF_INET_LOCAL_IN,
0440 .priority = NF_IP6_PRI_LAST - 1,
0441 },
0442 };
0443 #endif
0444
0445 static int nf_ct_tcp_fixup(struct nf_conn *ct, void *_nfproto)
0446 {
0447 u8 nfproto = (unsigned long)_nfproto;
0448
0449 if (nf_ct_l3num(ct) != nfproto)
0450 return 0;
0451
0452 if (nf_ct_protonum(ct) == IPPROTO_TCP &&
0453 ct->proto.tcp.state == TCP_CONNTRACK_ESTABLISHED) {
0454 ct->proto.tcp.seen[0].td_maxwin = 0;
0455 ct->proto.tcp.seen[1].td_maxwin = 0;
0456 }
0457
0458 return 0;
0459 }
0460
0461 static struct nf_ct_bridge_info *nf_ct_bridge_info;
0462
0463 static int nf_ct_netns_do_get(struct net *net, u8 nfproto)
0464 {
0465 struct nf_conntrack_net *cnet = nf_ct_pernet(net);
0466 bool fixup_needed = false, retry = true;
0467 int err = 0;
0468 retry:
0469 mutex_lock(&nf_ct_proto_mutex);
0470
0471 switch (nfproto) {
0472 case NFPROTO_IPV4:
0473 cnet->users4++;
0474 if (cnet->users4 > 1)
0475 goto out_unlock;
0476 err = nf_defrag_ipv4_enable(net);
0477 if (err) {
0478 cnet->users4 = 0;
0479 goto out_unlock;
0480 }
0481
0482 err = nf_register_net_hooks(net, ipv4_conntrack_ops,
0483 ARRAY_SIZE(ipv4_conntrack_ops));
0484 if (err)
0485 cnet->users4 = 0;
0486 else
0487 fixup_needed = true;
0488 break;
0489 #if IS_ENABLED(CONFIG_IPV6)
0490 case NFPROTO_IPV6:
0491 cnet->users6++;
0492 if (cnet->users6 > 1)
0493 goto out_unlock;
0494 err = nf_defrag_ipv6_enable(net);
0495 if (err < 0) {
0496 cnet->users6 = 0;
0497 goto out_unlock;
0498 }
0499
0500 err = nf_register_net_hooks(net, ipv6_conntrack_ops,
0501 ARRAY_SIZE(ipv6_conntrack_ops));
0502 if (err)
0503 cnet->users6 = 0;
0504 else
0505 fixup_needed = true;
0506 break;
0507 #endif
0508 case NFPROTO_BRIDGE:
0509 if (!nf_ct_bridge_info) {
0510 if (!retry) {
0511 err = -EPROTO;
0512 goto out_unlock;
0513 }
0514 mutex_unlock(&nf_ct_proto_mutex);
0515 request_module("nf_conntrack_bridge");
0516 retry = false;
0517 goto retry;
0518 }
0519 if (!try_module_get(nf_ct_bridge_info->me)) {
0520 err = -EPROTO;
0521 goto out_unlock;
0522 }
0523 cnet->users_bridge++;
0524 if (cnet->users_bridge > 1)
0525 goto out_unlock;
0526
0527 err = nf_register_net_hooks(net, nf_ct_bridge_info->ops,
0528 nf_ct_bridge_info->ops_size);
0529 if (err)
0530 cnet->users_bridge = 0;
0531 else
0532 fixup_needed = true;
0533 break;
0534 default:
0535 err = -EPROTO;
0536 break;
0537 }
0538 out_unlock:
0539 mutex_unlock(&nf_ct_proto_mutex);
0540
0541 if (fixup_needed) {
0542 struct nf_ct_iter_data iter_data = {
0543 .net = net,
0544 .data = (void *)(unsigned long)nfproto,
0545 };
0546 nf_ct_iterate_cleanup_net(nf_ct_tcp_fixup, &iter_data);
0547 }
0548
0549 return err;
0550 }
0551
0552 static void nf_ct_netns_do_put(struct net *net, u8 nfproto)
0553 {
0554 struct nf_conntrack_net *cnet = nf_ct_pernet(net);
0555
0556 mutex_lock(&nf_ct_proto_mutex);
0557 switch (nfproto) {
0558 case NFPROTO_IPV4:
0559 if (cnet->users4 && (--cnet->users4 == 0)) {
0560 nf_unregister_net_hooks(net, ipv4_conntrack_ops,
0561 ARRAY_SIZE(ipv4_conntrack_ops));
0562 nf_defrag_ipv4_disable(net);
0563 }
0564 break;
0565 #if IS_ENABLED(CONFIG_IPV6)
0566 case NFPROTO_IPV6:
0567 if (cnet->users6 && (--cnet->users6 == 0)) {
0568 nf_unregister_net_hooks(net, ipv6_conntrack_ops,
0569 ARRAY_SIZE(ipv6_conntrack_ops));
0570 nf_defrag_ipv6_disable(net);
0571 }
0572 break;
0573 #endif
0574 case NFPROTO_BRIDGE:
0575 if (!nf_ct_bridge_info)
0576 break;
0577 if (cnet->users_bridge && (--cnet->users_bridge == 0))
0578 nf_unregister_net_hooks(net, nf_ct_bridge_info->ops,
0579 nf_ct_bridge_info->ops_size);
0580
0581 module_put(nf_ct_bridge_info->me);
0582 break;
0583 }
0584 mutex_unlock(&nf_ct_proto_mutex);
0585 }
0586
0587 static int nf_ct_netns_inet_get(struct net *net)
0588 {
0589 int err;
0590
0591 err = nf_ct_netns_do_get(net, NFPROTO_IPV4);
0592 #if IS_ENABLED(CONFIG_IPV6)
0593 if (err < 0)
0594 goto err1;
0595 err = nf_ct_netns_do_get(net, NFPROTO_IPV6);
0596 if (err < 0)
0597 goto err2;
0598
0599 return err;
0600 err2:
0601 nf_ct_netns_put(net, NFPROTO_IPV4);
0602 err1:
0603 #endif
0604 return err;
0605 }
0606
0607 int nf_ct_netns_get(struct net *net, u8 nfproto)
0608 {
0609 int err;
0610
0611 switch (nfproto) {
0612 case NFPROTO_INET:
0613 err = nf_ct_netns_inet_get(net);
0614 break;
0615 case NFPROTO_BRIDGE:
0616 err = nf_ct_netns_do_get(net, NFPROTO_BRIDGE);
0617 if (err < 0)
0618 return err;
0619
0620 err = nf_ct_netns_inet_get(net);
0621 if (err < 0) {
0622 nf_ct_netns_put(net, NFPROTO_BRIDGE);
0623 return err;
0624 }
0625 break;
0626 default:
0627 err = nf_ct_netns_do_get(net, nfproto);
0628 break;
0629 }
0630 return err;
0631 }
0632 EXPORT_SYMBOL_GPL(nf_ct_netns_get);
0633
0634 void nf_ct_netns_put(struct net *net, uint8_t nfproto)
0635 {
0636 switch (nfproto) {
0637 case NFPROTO_BRIDGE:
0638 nf_ct_netns_do_put(net, NFPROTO_BRIDGE);
0639 fallthrough;
0640 case NFPROTO_INET:
0641 nf_ct_netns_do_put(net, NFPROTO_IPV4);
0642 nf_ct_netns_do_put(net, NFPROTO_IPV6);
0643 break;
0644 default:
0645 nf_ct_netns_do_put(net, nfproto);
0646 break;
0647 }
0648 }
0649 EXPORT_SYMBOL_GPL(nf_ct_netns_put);
0650
0651 void nf_ct_bridge_register(struct nf_ct_bridge_info *info)
0652 {
0653 WARN_ON(nf_ct_bridge_info);
0654 mutex_lock(&nf_ct_proto_mutex);
0655 nf_ct_bridge_info = info;
0656 mutex_unlock(&nf_ct_proto_mutex);
0657 }
0658 EXPORT_SYMBOL_GPL(nf_ct_bridge_register);
0659
0660 void nf_ct_bridge_unregister(struct nf_ct_bridge_info *info)
0661 {
0662 WARN_ON(!nf_ct_bridge_info);
0663 mutex_lock(&nf_ct_proto_mutex);
0664 nf_ct_bridge_info = NULL;
0665 mutex_unlock(&nf_ct_proto_mutex);
0666 }
0667 EXPORT_SYMBOL_GPL(nf_ct_bridge_unregister);
0668
0669 int nf_conntrack_proto_init(void)
0670 {
0671 int ret;
0672
0673 ret = nf_register_sockopt(&so_getorigdst);
0674 if (ret < 0)
0675 return ret;
0676
0677 #if IS_ENABLED(CONFIG_IPV6)
0678 ret = nf_register_sockopt(&so_getorigdst6);
0679 if (ret < 0)
0680 goto cleanup_sockopt;
0681 #endif
0682
0683 return ret;
0684
0685 #if IS_ENABLED(CONFIG_IPV6)
0686 cleanup_sockopt:
0687 nf_unregister_sockopt(&so_getorigdst);
0688 #endif
0689 return ret;
0690 }
0691
0692 void nf_conntrack_proto_fini(void)
0693 {
0694 nf_unregister_sockopt(&so_getorigdst);
0695 #if IS_ENABLED(CONFIG_IPV6)
0696 nf_unregister_sockopt(&so_getorigdst6);
0697 #endif
0698 }
0699
0700 void nf_conntrack_proto_pernet_init(struct net *net)
0701 {
0702 nf_conntrack_generic_init_net(net);
0703 nf_conntrack_udp_init_net(net);
0704 nf_conntrack_tcp_init_net(net);
0705 nf_conntrack_icmp_init_net(net);
0706 #if IS_ENABLED(CONFIG_IPV6)
0707 nf_conntrack_icmpv6_init_net(net);
0708 #endif
0709 #ifdef CONFIG_NF_CT_PROTO_DCCP
0710 nf_conntrack_dccp_init_net(net);
0711 #endif
0712 #ifdef CONFIG_NF_CT_PROTO_SCTP
0713 nf_conntrack_sctp_init_net(net);
0714 #endif
0715 #ifdef CONFIG_NF_CT_PROTO_GRE
0716 nf_conntrack_gre_init_net(net);
0717 #endif
0718 }
0719
0720 module_param_call(hashsize, nf_conntrack_set_hashsize, param_get_uint,
0721 &nf_conntrack_htable_size, 0600);
0722
0723 MODULE_ALIAS("ip_conntrack");
0724 MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET));
0725 MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET6));
0726 MODULE_LICENSE("GPL");