1a0ae2562SFlorian Westphal // SPDX-License-Identifier: GPL-2.0 28f03dea5SMartin Josefsson 38f03dea5SMartin Josefsson #include <linux/types.h> 48f03dea5SMartin Josefsson #include <linux/netfilter.h> 58f03dea5SMartin Josefsson #include <linux/module.h> 65a0e3ad6STejun Heo #include <linux/slab.h> 7d62f9ed4SPatrick McHardy #include <linux/mutex.h> 88f03dea5SMartin Josefsson #include <linux/vmalloc.h> 98f03dea5SMartin Josefsson #include <linux/stddef.h> 108f03dea5SMartin Josefsson #include <linux/err.h> 118f03dea5SMartin Josefsson #include <linux/percpu.h> 128f03dea5SMartin Josefsson #include <linux/notifier.h> 138f03dea5SMartin Josefsson #include <linux/kernel.h> 148f03dea5SMartin Josefsson #include <linux/netdevice.h> 158f03dea5SMartin Josefsson 168f03dea5SMartin Josefsson #include <net/netfilter/nf_conntrack.h> 17605dcad6SMartin Josefsson #include <net/netfilter/nf_conntrack_l4proto.h> 188f03dea5SMartin Josefsson #include <net/netfilter/nf_conntrack_core.h> 19d035f19fSPablo Neira Ayuso #include <net/netfilter/nf_conntrack_bridge.h> 20c4f3db15SFlorian Westphal #include <net/netfilter/nf_log.h> 218f03dea5SMartin Josefsson 22a0ae2562SFlorian Westphal #include <linux/ip.h> 23a0ae2562SFlorian Westphal #include <linux/icmp.h> 24a0ae2562SFlorian Westphal #include <linux/sysctl.h> 25a0ae2562SFlorian Westphal #include <net/route.h> 26a0ae2562SFlorian Westphal #include <net/ip.h> 27a0ae2562SFlorian Westphal 28a0ae2562SFlorian Westphal #include <linux/netfilter_ipv4.h> 29a0ae2562SFlorian Westphal #include <linux/netfilter_ipv6.h> 30a0ae2562SFlorian Westphal #include <linux/netfilter_ipv6/ip6_tables.h> 31a0ae2562SFlorian Westphal #include <net/netfilter/nf_conntrack_helper.h> 32a0ae2562SFlorian Westphal #include <net/netfilter/nf_conntrack_zones.h> 33a0ae2562SFlorian Westphal #include <net/netfilter/nf_conntrack_seqadj.h> 34a0ae2562SFlorian Westphal #include <net/netfilter/ipv4/nf_conntrack_ipv4.h> 35a0ae2562SFlorian Westphal #include <net/netfilter/ipv6/nf_conntrack_ipv6.h> 36a0ae2562SFlorian Westphal #include <net/netfilter/nf_nat_helper.h> 37a0ae2562SFlorian Westphal #include <net/netfilter/ipv4/nf_defrag_ipv4.h> 38a0ae2562SFlorian Westphal #include <net/netfilter/ipv6/nf_defrag_ipv6.h> 39a0ae2562SFlorian Westphal 40a0ae2562SFlorian Westphal #include <linux/ipv6.h> 41a0ae2562SFlorian Westphal #include <linux/in6.h> 42a0ae2562SFlorian Westphal #include <net/ipv6.h> 43a0ae2562SFlorian Westphal #include <net/inet_frag.h> 44a0ae2562SFlorian Westphal 45a0ae2562SFlorian Westphal extern unsigned int nf_conntrack_net_id; 46a0ae2562SFlorian Westphal 47b19caa0cSPatrick McHardy static DEFINE_MUTEX(nf_ct_proto_mutex); 48d62f9ed4SPatrick McHardy 49b19caa0cSPatrick McHardy #ifdef CONFIG_SYSCTL 50c4f3db15SFlorian Westphal __printf(5, 6) 51c4f3db15SFlorian Westphal void nf_l4proto_log_invalid(const struct sk_buff *skb, 52c4f3db15SFlorian Westphal struct net *net, 53c4f3db15SFlorian Westphal u16 pf, u8 protonum, 54c4f3db15SFlorian Westphal const char *fmt, ...) 55c4f3db15SFlorian Westphal { 56c4f3db15SFlorian Westphal struct va_format vaf; 57c4f3db15SFlorian Westphal va_list args; 58c4f3db15SFlorian Westphal 59d4866805SAndrei Vagin if (net->ct.sysctl_log_invalid != protonum && 60c4f3db15SFlorian Westphal net->ct.sysctl_log_invalid != IPPROTO_RAW) 61c4f3db15SFlorian Westphal return; 62c4f3db15SFlorian Westphal 63c4f3db15SFlorian Westphal va_start(args, fmt); 64c4f3db15SFlorian Westphal vaf.fmt = fmt; 65c4f3db15SFlorian Westphal vaf.va = &args; 66c4f3db15SFlorian Westphal 67c4f3db15SFlorian Westphal nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, 68c4f3db15SFlorian Westphal "nf_ct_proto_%d: %pV ", protonum, &vaf); 69c4f3db15SFlorian Westphal va_end(args); 70c4f3db15SFlorian Westphal } 71c4f3db15SFlorian Westphal EXPORT_SYMBOL_GPL(nf_l4proto_log_invalid); 723d0b527bSFlorian Westphal 733d0b527bSFlorian Westphal __printf(3, 4) 743d0b527bSFlorian Westphal void nf_ct_l4proto_log_invalid(const struct sk_buff *skb, 753d0b527bSFlorian Westphal const struct nf_conn *ct, 763d0b527bSFlorian Westphal const char *fmt, ...) 773d0b527bSFlorian Westphal { 783d0b527bSFlorian Westphal struct va_format vaf; 793d0b527bSFlorian Westphal struct net *net; 803d0b527bSFlorian Westphal va_list args; 813d0b527bSFlorian Westphal 823d0b527bSFlorian Westphal net = nf_ct_net(ct); 833d0b527bSFlorian Westphal if (likely(net->ct.sysctl_log_invalid == 0)) 843d0b527bSFlorian Westphal return; 853d0b527bSFlorian Westphal 863d0b527bSFlorian Westphal va_start(args, fmt); 873d0b527bSFlorian Westphal vaf.fmt = fmt; 883d0b527bSFlorian Westphal vaf.va = &args; 893d0b527bSFlorian Westphal 903d0b527bSFlorian Westphal nf_l4proto_log_invalid(skb, net, nf_ct_l3num(ct), 913d0b527bSFlorian Westphal nf_ct_protonum(ct), "%pV", &vaf); 923d0b527bSFlorian Westphal va_end(args); 933d0b527bSFlorian Westphal } 943d0b527bSFlorian Westphal EXPORT_SYMBOL_GPL(nf_ct_l4proto_log_invalid); 95d62f9ed4SPatrick McHardy #endif 96d62f9ed4SPatrick McHardy 974a60dc74SFlorian Westphal const struct nf_conntrack_l4proto *nf_ct_l4proto_find(u8 l4proto) 988f03dea5SMartin Josefsson { 994a60dc74SFlorian Westphal switch (l4proto) { 1004a60dc74SFlorian Westphal case IPPROTO_UDP: return &nf_conntrack_l4proto_udp; 1014a60dc74SFlorian Westphal case IPPROTO_TCP: return &nf_conntrack_l4proto_tcp; 1024a60dc74SFlorian Westphal case IPPROTO_ICMP: return &nf_conntrack_l4proto_icmp; 1034a60dc74SFlorian Westphal #ifdef CONFIG_NF_CT_PROTO_DCCP 1044a60dc74SFlorian Westphal case IPPROTO_DCCP: return &nf_conntrack_l4proto_dccp; 1054a60dc74SFlorian Westphal #endif 1064a60dc74SFlorian Westphal #ifdef CONFIG_NF_CT_PROTO_SCTP 1074a60dc74SFlorian Westphal case IPPROTO_SCTP: return &nf_conntrack_l4proto_sctp; 1084a60dc74SFlorian Westphal #endif 1094a60dc74SFlorian Westphal #ifdef CONFIG_NF_CT_PROTO_UDPLITE 1104a60dc74SFlorian Westphal case IPPROTO_UDPLITE: return &nf_conntrack_l4proto_udplite; 1114a60dc74SFlorian Westphal #endif 1124a60dc74SFlorian Westphal #ifdef CONFIG_NF_CT_PROTO_GRE 1134a60dc74SFlorian Westphal case IPPROTO_GRE: return &nf_conntrack_l4proto_gre; 1144a60dc74SFlorian Westphal #endif 1154a60dc74SFlorian Westphal #if IS_ENABLED(CONFIG_IPV6) 1164a60dc74SFlorian Westphal case IPPROTO_ICMPV6: return &nf_conntrack_l4proto_icmpv6; 1174a60dc74SFlorian Westphal #endif /* CONFIG_IPV6 */ 1184a60dc74SFlorian Westphal } 1194a60dc74SFlorian Westphal 120605dcad6SMartin Josefsson return &nf_conntrack_l4proto_generic; 1214a60dc74SFlorian Westphal }; 1224a60dc74SFlorian Westphal EXPORT_SYMBOL_GPL(nf_ct_l4proto_find); 1230e54d217SDavide Caratti 1243c171f49SPablo Neira Ayuso unsigned int nf_confirm(struct sk_buff *skb, unsigned int protoff, 1253c171f49SPablo Neira Ayuso struct nf_conn *ct, enum ip_conntrack_info ctinfo) 126a0ae2562SFlorian Westphal { 127a0ae2562SFlorian Westphal const struct nf_conn_help *help; 128a0ae2562SFlorian Westphal 129a0ae2562SFlorian Westphal help = nfct_help(ct); 130827318feSFlorian Westphal if (help) { 131827318feSFlorian Westphal const struct nf_conntrack_helper *helper; 132827318feSFlorian Westphal int ret; 133a0ae2562SFlorian Westphal 134a0ae2562SFlorian Westphal /* rcu_read_lock()ed by nf_hook_thresh */ 135a0ae2562SFlorian Westphal helper = rcu_dereference(help->helper); 136827318feSFlorian Westphal if (helper) { 137827318feSFlorian Westphal ret = helper->help(skb, 138827318feSFlorian Westphal protoff, 139a0ae2562SFlorian Westphal ct, ctinfo); 140827318feSFlorian Westphal if (ret != NF_ACCEPT) 141827318feSFlorian Westphal return ret; 142827318feSFlorian Westphal } 143827318feSFlorian Westphal } 144827318feSFlorian Westphal 145827318feSFlorian Westphal if (test_bit(IPS_SEQ_ADJUST_BIT, &ct->status) && 146827318feSFlorian Westphal !nf_is_loopback_packet(skb)) { 147827318feSFlorian Westphal if (!nf_ct_seq_adjust(skb, ct, ctinfo, protoff)) { 148827318feSFlorian Westphal NF_CT_STAT_INC_ATOMIC(nf_ct_net(ct), drop); 149827318feSFlorian Westphal return NF_DROP; 150827318feSFlorian Westphal } 151827318feSFlorian Westphal } 152827318feSFlorian Westphal 153827318feSFlorian Westphal /* We've seen it coming out the other side: confirm it */ 154827318feSFlorian Westphal return nf_conntrack_confirm(skb); 155a0ae2562SFlorian Westphal } 1563c171f49SPablo Neira Ayuso EXPORT_SYMBOL_GPL(nf_confirm); 157a0ae2562SFlorian Westphal 158a0ae2562SFlorian Westphal static unsigned int ipv4_confirm(void *priv, 159a0ae2562SFlorian Westphal struct sk_buff *skb, 160a0ae2562SFlorian Westphal const struct nf_hook_state *state) 161a0ae2562SFlorian Westphal { 162a0ae2562SFlorian Westphal enum ip_conntrack_info ctinfo; 163827318feSFlorian Westphal struct nf_conn *ct; 164a0ae2562SFlorian Westphal 165a0ae2562SFlorian Westphal ct = nf_ct_get(skb, &ctinfo); 166a0ae2562SFlorian Westphal if (!ct || ctinfo == IP_CT_RELATED_REPLY) 167a0ae2562SFlorian Westphal return nf_conntrack_confirm(skb); 168827318feSFlorian Westphal 169827318feSFlorian Westphal return nf_confirm(skb, 170827318feSFlorian Westphal skb_network_offset(skb) + ip_hdrlen(skb), 171827318feSFlorian Westphal ct, ctinfo); 172a0ae2562SFlorian Westphal } 173a0ae2562SFlorian Westphal 174a0ae2562SFlorian Westphal static unsigned int ipv4_conntrack_in(void *priv, 175a0ae2562SFlorian Westphal struct sk_buff *skb, 176a0ae2562SFlorian Westphal const struct nf_hook_state *state) 177a0ae2562SFlorian Westphal { 17893e66024SFlorian Westphal return nf_conntrack_in(skb, state); 179a0ae2562SFlorian Westphal } 180a0ae2562SFlorian Westphal 181a0ae2562SFlorian Westphal static unsigned int ipv4_conntrack_local(void *priv, 182a0ae2562SFlorian Westphal struct sk_buff *skb, 183a0ae2562SFlorian Westphal const struct nf_hook_state *state) 184a0ae2562SFlorian Westphal { 185a0ae2562SFlorian Westphal if (ip_is_fragment(ip_hdr(skb))) { /* IP_NODEFRAG setsockopt set */ 186a0ae2562SFlorian Westphal enum ip_conntrack_info ctinfo; 187a0ae2562SFlorian Westphal struct nf_conn *tmpl; 188a0ae2562SFlorian Westphal 189a0ae2562SFlorian Westphal tmpl = nf_ct_get(skb, &ctinfo); 190a0ae2562SFlorian Westphal if (tmpl && nf_ct_is_template(tmpl)) { 191a0ae2562SFlorian Westphal /* when skipping ct, clear templates to avoid fooling 192a0ae2562SFlorian Westphal * later targets/matches 193a0ae2562SFlorian Westphal */ 194a0ae2562SFlorian Westphal skb->_nfct = 0; 195a0ae2562SFlorian Westphal nf_ct_put(tmpl); 196a0ae2562SFlorian Westphal } 197a0ae2562SFlorian Westphal return NF_ACCEPT; 198a0ae2562SFlorian Westphal } 199a0ae2562SFlorian Westphal 20093e66024SFlorian Westphal return nf_conntrack_in(skb, state); 201a0ae2562SFlorian Westphal } 202a0ae2562SFlorian Westphal 203a0ae2562SFlorian Westphal /* Connection tracking may drop packets, but never alters them, so 204a0ae2562SFlorian Westphal * make it the first hook. 205a0ae2562SFlorian Westphal */ 206a0ae2562SFlorian Westphal static const struct nf_hook_ops ipv4_conntrack_ops[] = { 207a0ae2562SFlorian Westphal { 208a0ae2562SFlorian Westphal .hook = ipv4_conntrack_in, 209a0ae2562SFlorian Westphal .pf = NFPROTO_IPV4, 210a0ae2562SFlorian Westphal .hooknum = NF_INET_PRE_ROUTING, 211a0ae2562SFlorian Westphal .priority = NF_IP_PRI_CONNTRACK, 212a0ae2562SFlorian Westphal }, 213a0ae2562SFlorian Westphal { 214a0ae2562SFlorian Westphal .hook = ipv4_conntrack_local, 215a0ae2562SFlorian Westphal .pf = NFPROTO_IPV4, 216a0ae2562SFlorian Westphal .hooknum = NF_INET_LOCAL_OUT, 217a0ae2562SFlorian Westphal .priority = NF_IP_PRI_CONNTRACK, 218a0ae2562SFlorian Westphal }, 219a0ae2562SFlorian Westphal { 220a0ae2562SFlorian Westphal .hook = ipv4_confirm, 221a0ae2562SFlorian Westphal .pf = NFPROTO_IPV4, 222a0ae2562SFlorian Westphal .hooknum = NF_INET_POST_ROUTING, 223a0ae2562SFlorian Westphal .priority = NF_IP_PRI_CONNTRACK_CONFIRM, 224a0ae2562SFlorian Westphal }, 225a0ae2562SFlorian Westphal { 226a0ae2562SFlorian Westphal .hook = ipv4_confirm, 227a0ae2562SFlorian Westphal .pf = NFPROTO_IPV4, 228a0ae2562SFlorian Westphal .hooknum = NF_INET_LOCAL_IN, 229a0ae2562SFlorian Westphal .priority = NF_IP_PRI_CONNTRACK_CONFIRM, 230a0ae2562SFlorian Westphal }, 231a0ae2562SFlorian Westphal }; 232a0ae2562SFlorian Westphal 233a0ae2562SFlorian Westphal /* Fast function for those who don't want to parse /proc (and I don't 234a0ae2562SFlorian Westphal * blame them). 235a0ae2562SFlorian Westphal * Reversing the socket's dst/src point of view gives us the reply 236a0ae2562SFlorian Westphal * mapping. 237a0ae2562SFlorian Westphal */ 238a0ae2562SFlorian Westphal static int 239a0ae2562SFlorian Westphal getorigdst(struct sock *sk, int optval, void __user *user, int *len) 240a0ae2562SFlorian Westphal { 241a0ae2562SFlorian Westphal const struct inet_sock *inet = inet_sk(sk); 242a0ae2562SFlorian Westphal const struct nf_conntrack_tuple_hash *h; 243a0ae2562SFlorian Westphal struct nf_conntrack_tuple tuple; 244a0ae2562SFlorian Westphal 245a0ae2562SFlorian Westphal memset(&tuple, 0, sizeof(tuple)); 246a0ae2562SFlorian Westphal 247a0ae2562SFlorian Westphal lock_sock(sk); 248a0ae2562SFlorian Westphal tuple.src.u3.ip = inet->inet_rcv_saddr; 249a0ae2562SFlorian Westphal tuple.src.u.tcp.port = inet->inet_sport; 250a0ae2562SFlorian Westphal tuple.dst.u3.ip = inet->inet_daddr; 251a0ae2562SFlorian Westphal tuple.dst.u.tcp.port = inet->inet_dport; 252a0ae2562SFlorian Westphal tuple.src.l3num = PF_INET; 253a0ae2562SFlorian Westphal tuple.dst.protonum = sk->sk_protocol; 254a0ae2562SFlorian Westphal release_sock(sk); 255a0ae2562SFlorian Westphal 256a0ae2562SFlorian Westphal /* We only do TCP and SCTP at the moment: is there a better way? */ 257a0ae2562SFlorian Westphal if (tuple.dst.protonum != IPPROTO_TCP && 258a0ae2562SFlorian Westphal tuple.dst.protonum != IPPROTO_SCTP) { 259a0ae2562SFlorian Westphal pr_debug("SO_ORIGINAL_DST: Not a TCP/SCTP socket\n"); 260a0ae2562SFlorian Westphal return -ENOPROTOOPT; 261a0ae2562SFlorian Westphal } 262a0ae2562SFlorian Westphal 263a0ae2562SFlorian Westphal if ((unsigned int)*len < sizeof(struct sockaddr_in)) { 264a0ae2562SFlorian Westphal pr_debug("SO_ORIGINAL_DST: len %d not %zu\n", 265a0ae2562SFlorian Westphal *len, sizeof(struct sockaddr_in)); 266a0ae2562SFlorian Westphal return -EINVAL; 267a0ae2562SFlorian Westphal } 268a0ae2562SFlorian Westphal 269a0ae2562SFlorian Westphal h = nf_conntrack_find_get(sock_net(sk), &nf_ct_zone_dflt, &tuple); 270a0ae2562SFlorian Westphal if (h) { 271a0ae2562SFlorian Westphal struct sockaddr_in sin; 272a0ae2562SFlorian Westphal struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h); 273a0ae2562SFlorian Westphal 274a0ae2562SFlorian Westphal sin.sin_family = AF_INET; 275a0ae2562SFlorian Westphal sin.sin_port = ct->tuplehash[IP_CT_DIR_ORIGINAL] 276a0ae2562SFlorian Westphal .tuple.dst.u.tcp.port; 277a0ae2562SFlorian Westphal sin.sin_addr.s_addr = ct->tuplehash[IP_CT_DIR_ORIGINAL] 278a0ae2562SFlorian Westphal .tuple.dst.u3.ip; 279a0ae2562SFlorian Westphal memset(sin.sin_zero, 0, sizeof(sin.sin_zero)); 280a0ae2562SFlorian Westphal 281a0ae2562SFlorian Westphal pr_debug("SO_ORIGINAL_DST: %pI4 %u\n", 282a0ae2562SFlorian Westphal &sin.sin_addr.s_addr, ntohs(sin.sin_port)); 283a0ae2562SFlorian Westphal nf_ct_put(ct); 284a0ae2562SFlorian Westphal if (copy_to_user(user, &sin, sizeof(sin)) != 0) 285a0ae2562SFlorian Westphal return -EFAULT; 286a0ae2562SFlorian Westphal else 287a0ae2562SFlorian Westphal return 0; 288a0ae2562SFlorian Westphal } 289a0ae2562SFlorian Westphal pr_debug("SO_ORIGINAL_DST: Can't find %pI4/%u-%pI4/%u.\n", 290a0ae2562SFlorian Westphal &tuple.src.u3.ip, ntohs(tuple.src.u.tcp.port), 291a0ae2562SFlorian Westphal &tuple.dst.u3.ip, ntohs(tuple.dst.u.tcp.port)); 292a0ae2562SFlorian Westphal return -ENOENT; 293a0ae2562SFlorian Westphal } 294a0ae2562SFlorian Westphal 295a0ae2562SFlorian Westphal static struct nf_sockopt_ops so_getorigdst = { 296a0ae2562SFlorian Westphal .pf = PF_INET, 297a0ae2562SFlorian Westphal .get_optmin = SO_ORIGINAL_DST, 298a0ae2562SFlorian Westphal .get_optmax = SO_ORIGINAL_DST + 1, 299a0ae2562SFlorian Westphal .get = getorigdst, 300a0ae2562SFlorian Westphal .owner = THIS_MODULE, 301a0ae2562SFlorian Westphal }; 302a0ae2562SFlorian Westphal 303a0ae2562SFlorian Westphal #if IS_ENABLED(CONFIG_IPV6) 304a0ae2562SFlorian Westphal static int 305a0ae2562SFlorian Westphal ipv6_getorigdst(struct sock *sk, int optval, void __user *user, int *len) 306a0ae2562SFlorian Westphal { 307a0ae2562SFlorian Westphal struct nf_conntrack_tuple tuple = { .src.l3num = NFPROTO_IPV6 }; 308a0ae2562SFlorian Westphal const struct ipv6_pinfo *inet6 = inet6_sk(sk); 309a0ae2562SFlorian Westphal const struct inet_sock *inet = inet_sk(sk); 310a0ae2562SFlorian Westphal const struct nf_conntrack_tuple_hash *h; 311a0ae2562SFlorian Westphal struct sockaddr_in6 sin6; 312a0ae2562SFlorian Westphal struct nf_conn *ct; 313a0ae2562SFlorian Westphal __be32 flow_label; 314a0ae2562SFlorian Westphal int bound_dev_if; 315a0ae2562SFlorian Westphal 316a0ae2562SFlorian Westphal lock_sock(sk); 317a0ae2562SFlorian Westphal tuple.src.u3.in6 = sk->sk_v6_rcv_saddr; 318a0ae2562SFlorian Westphal tuple.src.u.tcp.port = inet->inet_sport; 319a0ae2562SFlorian Westphal tuple.dst.u3.in6 = sk->sk_v6_daddr; 320a0ae2562SFlorian Westphal tuple.dst.u.tcp.port = inet->inet_dport; 321a0ae2562SFlorian Westphal tuple.dst.protonum = sk->sk_protocol; 322a0ae2562SFlorian Westphal bound_dev_if = sk->sk_bound_dev_if; 323a0ae2562SFlorian Westphal flow_label = inet6->flow_label; 324a0ae2562SFlorian Westphal release_sock(sk); 325a0ae2562SFlorian Westphal 326a0ae2562SFlorian Westphal if (tuple.dst.protonum != IPPROTO_TCP && 327a0ae2562SFlorian Westphal tuple.dst.protonum != IPPROTO_SCTP) 328a0ae2562SFlorian Westphal return -ENOPROTOOPT; 329a0ae2562SFlorian Westphal 330a0ae2562SFlorian Westphal if (*len < 0 || (unsigned int)*len < sizeof(sin6)) 331a0ae2562SFlorian Westphal return -EINVAL; 332a0ae2562SFlorian Westphal 333a0ae2562SFlorian Westphal h = nf_conntrack_find_get(sock_net(sk), &nf_ct_zone_dflt, &tuple); 334a0ae2562SFlorian Westphal if (!h) { 335a0ae2562SFlorian Westphal pr_debug("IP6T_SO_ORIGINAL_DST: Can't find %pI6c/%u-%pI6c/%u.\n", 336a0ae2562SFlorian Westphal &tuple.src.u3.ip6, ntohs(tuple.src.u.tcp.port), 337a0ae2562SFlorian Westphal &tuple.dst.u3.ip6, ntohs(tuple.dst.u.tcp.port)); 338a0ae2562SFlorian Westphal return -ENOENT; 339a0ae2562SFlorian Westphal } 340a0ae2562SFlorian Westphal 341a0ae2562SFlorian Westphal ct = nf_ct_tuplehash_to_ctrack(h); 342a0ae2562SFlorian Westphal 343a0ae2562SFlorian Westphal sin6.sin6_family = AF_INET6; 344a0ae2562SFlorian Westphal sin6.sin6_port = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.tcp.port; 345a0ae2562SFlorian Westphal sin6.sin6_flowinfo = flow_label & IPV6_FLOWINFO_MASK; 346a0ae2562SFlorian Westphal memcpy(&sin6.sin6_addr, 347a0ae2562SFlorian Westphal &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.in6, 348a0ae2562SFlorian Westphal sizeof(sin6.sin6_addr)); 349a0ae2562SFlorian Westphal 350a0ae2562SFlorian Westphal nf_ct_put(ct); 351a0ae2562SFlorian Westphal sin6.sin6_scope_id = ipv6_iface_scope_id(&sin6.sin6_addr, bound_dev_if); 352a0ae2562SFlorian Westphal return copy_to_user(user, &sin6, sizeof(sin6)) ? -EFAULT : 0; 353a0ae2562SFlorian Westphal } 354a0ae2562SFlorian Westphal 355a0ae2562SFlorian Westphal static struct nf_sockopt_ops so_getorigdst6 = { 356a0ae2562SFlorian Westphal .pf = NFPROTO_IPV6, 357a0ae2562SFlorian Westphal .get_optmin = IP6T_SO_ORIGINAL_DST, 358a0ae2562SFlorian Westphal .get_optmax = IP6T_SO_ORIGINAL_DST + 1, 359a0ae2562SFlorian Westphal .get = ipv6_getorigdst, 360a0ae2562SFlorian Westphal .owner = THIS_MODULE, 361a0ae2562SFlorian Westphal }; 362a0ae2562SFlorian Westphal 363a0ae2562SFlorian Westphal static unsigned int ipv6_confirm(void *priv, 364a0ae2562SFlorian Westphal struct sk_buff *skb, 365a0ae2562SFlorian Westphal const struct nf_hook_state *state) 366a0ae2562SFlorian Westphal { 367a0ae2562SFlorian Westphal struct nf_conn *ct; 368a0ae2562SFlorian Westphal enum ip_conntrack_info ctinfo; 369a0ae2562SFlorian Westphal unsigned char pnum = ipv6_hdr(skb)->nexthdr; 370a0ae2562SFlorian Westphal __be16 frag_off; 371827318feSFlorian Westphal int protoff; 372a0ae2562SFlorian Westphal 373a0ae2562SFlorian Westphal ct = nf_ct_get(skb, &ctinfo); 374a0ae2562SFlorian Westphal if (!ct || ctinfo == IP_CT_RELATED_REPLY) 375827318feSFlorian Westphal return nf_conntrack_confirm(skb); 376a0ae2562SFlorian Westphal 377a0ae2562SFlorian Westphal protoff = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &pnum, 378a0ae2562SFlorian Westphal &frag_off); 379a0ae2562SFlorian Westphal if (protoff < 0 || (frag_off & htons(~0x7)) != 0) { 380a0ae2562SFlorian Westphal pr_debug("proto header not found\n"); 381827318feSFlorian Westphal return nf_conntrack_confirm(skb); 382a0ae2562SFlorian Westphal } 383a0ae2562SFlorian Westphal 384827318feSFlorian Westphal return nf_confirm(skb, protoff, ct, ctinfo); 385a0ae2562SFlorian Westphal } 386a0ae2562SFlorian Westphal 387a0ae2562SFlorian Westphal static unsigned int ipv6_conntrack_in(void *priv, 388a0ae2562SFlorian Westphal struct sk_buff *skb, 389a0ae2562SFlorian Westphal const struct nf_hook_state *state) 390a0ae2562SFlorian Westphal { 39193e66024SFlorian Westphal return nf_conntrack_in(skb, state); 392a0ae2562SFlorian Westphal } 393a0ae2562SFlorian Westphal 394a0ae2562SFlorian Westphal static unsigned int ipv6_conntrack_local(void *priv, 395a0ae2562SFlorian Westphal struct sk_buff *skb, 396a0ae2562SFlorian Westphal const struct nf_hook_state *state) 397a0ae2562SFlorian Westphal { 39893e66024SFlorian Westphal return nf_conntrack_in(skb, state); 399a0ae2562SFlorian Westphal } 400a0ae2562SFlorian Westphal 401a0ae2562SFlorian Westphal static const struct nf_hook_ops ipv6_conntrack_ops[] = { 402a0ae2562SFlorian Westphal { 403a0ae2562SFlorian Westphal .hook = ipv6_conntrack_in, 404a0ae2562SFlorian Westphal .pf = NFPROTO_IPV6, 405a0ae2562SFlorian Westphal .hooknum = NF_INET_PRE_ROUTING, 406a0ae2562SFlorian Westphal .priority = NF_IP6_PRI_CONNTRACK, 407a0ae2562SFlorian Westphal }, 408a0ae2562SFlorian Westphal { 409a0ae2562SFlorian Westphal .hook = ipv6_conntrack_local, 410a0ae2562SFlorian Westphal .pf = NFPROTO_IPV6, 411a0ae2562SFlorian Westphal .hooknum = NF_INET_LOCAL_OUT, 412a0ae2562SFlorian Westphal .priority = NF_IP6_PRI_CONNTRACK, 413a0ae2562SFlorian Westphal }, 414a0ae2562SFlorian Westphal { 415a0ae2562SFlorian Westphal .hook = ipv6_confirm, 416a0ae2562SFlorian Westphal .pf = NFPROTO_IPV6, 417a0ae2562SFlorian Westphal .hooknum = NF_INET_POST_ROUTING, 418a0ae2562SFlorian Westphal .priority = NF_IP6_PRI_LAST, 419a0ae2562SFlorian Westphal }, 420a0ae2562SFlorian Westphal { 421a0ae2562SFlorian Westphal .hook = ipv6_confirm, 422a0ae2562SFlorian Westphal .pf = NFPROTO_IPV6, 423a0ae2562SFlorian Westphal .hooknum = NF_INET_LOCAL_IN, 424a0ae2562SFlorian Westphal .priority = NF_IP6_PRI_LAST - 1, 425a0ae2562SFlorian Westphal }, 426a0ae2562SFlorian Westphal }; 427a0ae2562SFlorian Westphal #endif 428a0ae2562SFlorian Westphal 429f94e6380SFlorian Westphal static int nf_ct_tcp_fixup(struct nf_conn *ct, void *_nfproto) 430f94e6380SFlorian Westphal { 431f94e6380SFlorian Westphal u8 nfproto = (unsigned long)_nfproto; 432f94e6380SFlorian Westphal 433f94e6380SFlorian Westphal if (nf_ct_l3num(ct) != nfproto) 434f94e6380SFlorian Westphal return 0; 435f94e6380SFlorian Westphal 436f94e6380SFlorian Westphal if (nf_ct_protonum(ct) == IPPROTO_TCP && 437f94e6380SFlorian Westphal ct->proto.tcp.state == TCP_CONNTRACK_ESTABLISHED) { 438f94e6380SFlorian Westphal ct->proto.tcp.seen[0].td_maxwin = 0; 439f94e6380SFlorian Westphal ct->proto.tcp.seen[1].td_maxwin = 0; 440f94e6380SFlorian Westphal } 441f94e6380SFlorian Westphal 442f94e6380SFlorian Westphal return 0; 443f94e6380SFlorian Westphal } 444f94e6380SFlorian Westphal 445d035f19fSPablo Neira Ayuso static struct nf_ct_bridge_info *nf_ct_bridge_info; 446d035f19fSPablo Neira Ayuso 447a0ae2562SFlorian Westphal static int nf_ct_netns_do_get(struct net *net, u8 nfproto) 448a0ae2562SFlorian Westphal { 449a0ae2562SFlorian Westphal struct nf_conntrack_net *cnet = net_generic(net, nf_conntrack_net_id); 450d035f19fSPablo Neira Ayuso bool fixup_needed = false, retry = true; 451a0ae2562SFlorian Westphal int err = 0; 452d035f19fSPablo Neira Ayuso retry: 453a0ae2562SFlorian Westphal mutex_lock(&nf_ct_proto_mutex); 454a0ae2562SFlorian Westphal 455a0ae2562SFlorian Westphal switch (nfproto) { 456a0ae2562SFlorian Westphal case NFPROTO_IPV4: 457a0ae2562SFlorian Westphal cnet->users4++; 458a0ae2562SFlorian Westphal if (cnet->users4 > 1) 459a0ae2562SFlorian Westphal goto out_unlock; 460a0ae2562SFlorian Westphal err = nf_defrag_ipv4_enable(net); 461a0ae2562SFlorian Westphal if (err) { 462a0ae2562SFlorian Westphal cnet->users4 = 0; 463a0ae2562SFlorian Westphal goto out_unlock; 464a0ae2562SFlorian Westphal } 465a0ae2562SFlorian Westphal 466a0ae2562SFlorian Westphal err = nf_register_net_hooks(net, ipv4_conntrack_ops, 467a0ae2562SFlorian Westphal ARRAY_SIZE(ipv4_conntrack_ops)); 468a0ae2562SFlorian Westphal if (err) 469a0ae2562SFlorian Westphal cnet->users4 = 0; 470f94e6380SFlorian Westphal else 471f94e6380SFlorian Westphal fixup_needed = true; 472a0ae2562SFlorian Westphal break; 473a0ae2562SFlorian Westphal #if IS_ENABLED(CONFIG_IPV6) 474a0ae2562SFlorian Westphal case NFPROTO_IPV6: 475a0ae2562SFlorian Westphal cnet->users6++; 476a0ae2562SFlorian Westphal if (cnet->users6 > 1) 477a0ae2562SFlorian Westphal goto out_unlock; 478a0ae2562SFlorian Westphal err = nf_defrag_ipv6_enable(net); 479a0ae2562SFlorian Westphal if (err < 0) { 480a0ae2562SFlorian Westphal cnet->users6 = 0; 481a0ae2562SFlorian Westphal goto out_unlock; 482a0ae2562SFlorian Westphal } 483a0ae2562SFlorian Westphal 484a0ae2562SFlorian Westphal err = nf_register_net_hooks(net, ipv6_conntrack_ops, 485a0ae2562SFlorian Westphal ARRAY_SIZE(ipv6_conntrack_ops)); 486a0ae2562SFlorian Westphal if (err) 487a0ae2562SFlorian Westphal cnet->users6 = 0; 488f94e6380SFlorian Westphal else 489f94e6380SFlorian Westphal fixup_needed = true; 490a0ae2562SFlorian Westphal break; 491a0ae2562SFlorian Westphal #endif 492d035f19fSPablo Neira Ayuso case NFPROTO_BRIDGE: 493d035f19fSPablo Neira Ayuso if (!nf_ct_bridge_info) { 494d035f19fSPablo Neira Ayuso if (!retry) { 495d035f19fSPablo Neira Ayuso err = -EPROTO; 496d035f19fSPablo Neira Ayuso goto out_unlock; 497d035f19fSPablo Neira Ayuso } 498d035f19fSPablo Neira Ayuso mutex_unlock(&nf_ct_proto_mutex); 499d035f19fSPablo Neira Ayuso request_module("nf_conntrack_bridge"); 500d035f19fSPablo Neira Ayuso retry = false; 501d035f19fSPablo Neira Ayuso goto retry; 502d035f19fSPablo Neira Ayuso } 503d035f19fSPablo Neira Ayuso if (!try_module_get(nf_ct_bridge_info->me)) { 504d035f19fSPablo Neira Ayuso err = -EPROTO; 505d035f19fSPablo Neira Ayuso goto out_unlock; 506d035f19fSPablo Neira Ayuso } 507d035f19fSPablo Neira Ayuso cnet->users_bridge++; 508d035f19fSPablo Neira Ayuso if (cnet->users_bridge > 1) 509d035f19fSPablo Neira Ayuso goto out_unlock; 510d035f19fSPablo Neira Ayuso 511d035f19fSPablo Neira Ayuso err = nf_register_net_hooks(net, nf_ct_bridge_info->ops, 512d035f19fSPablo Neira Ayuso nf_ct_bridge_info->ops_size); 513d035f19fSPablo Neira Ayuso if (err) 514d035f19fSPablo Neira Ayuso cnet->users_bridge = 0; 515d035f19fSPablo Neira Ayuso else 516d035f19fSPablo Neira Ayuso fixup_needed = true; 517d035f19fSPablo Neira Ayuso break; 518a0ae2562SFlorian Westphal default: 519a0ae2562SFlorian Westphal err = -EPROTO; 520a0ae2562SFlorian Westphal break; 521a0ae2562SFlorian Westphal } 522a0ae2562SFlorian Westphal out_unlock: 523a0ae2562SFlorian Westphal mutex_unlock(&nf_ct_proto_mutex); 524f94e6380SFlorian Westphal 525f94e6380SFlorian Westphal if (fixup_needed) 526f94e6380SFlorian Westphal nf_ct_iterate_cleanup_net(net, nf_ct_tcp_fixup, 527f94e6380SFlorian Westphal (void *)(unsigned long)nfproto, 0, 0); 528f94e6380SFlorian Westphal 529a0ae2562SFlorian Westphal return err; 530a0ae2562SFlorian Westphal } 531a0ae2562SFlorian Westphal 532a0ae2562SFlorian Westphal static void nf_ct_netns_do_put(struct net *net, u8 nfproto) 533a0ae2562SFlorian Westphal { 534a0ae2562SFlorian Westphal struct nf_conntrack_net *cnet = net_generic(net, nf_conntrack_net_id); 535a0ae2562SFlorian Westphal 536a0ae2562SFlorian Westphal mutex_lock(&nf_ct_proto_mutex); 537a0ae2562SFlorian Westphal switch (nfproto) { 538a0ae2562SFlorian Westphal case NFPROTO_IPV4: 539a0ae2562SFlorian Westphal if (cnet->users4 && (--cnet->users4 == 0)) 540a0ae2562SFlorian Westphal nf_unregister_net_hooks(net, ipv4_conntrack_ops, 541a0ae2562SFlorian Westphal ARRAY_SIZE(ipv4_conntrack_ops)); 542a0ae2562SFlorian Westphal break; 543a0ae2562SFlorian Westphal #if IS_ENABLED(CONFIG_IPV6) 544a0ae2562SFlorian Westphal case NFPROTO_IPV6: 545a0ae2562SFlorian Westphal if (cnet->users6 && (--cnet->users6 == 0)) 546a0ae2562SFlorian Westphal nf_unregister_net_hooks(net, ipv6_conntrack_ops, 547a0ae2562SFlorian Westphal ARRAY_SIZE(ipv6_conntrack_ops)); 548a0ae2562SFlorian Westphal break; 549a0ae2562SFlorian Westphal #endif 550d035f19fSPablo Neira Ayuso case NFPROTO_BRIDGE: 551d035f19fSPablo Neira Ayuso if (!nf_ct_bridge_info) 552d035f19fSPablo Neira Ayuso break; 553d035f19fSPablo Neira Ayuso if (cnet->users_bridge && (--cnet->users_bridge == 0)) 554d035f19fSPablo Neira Ayuso nf_unregister_net_hooks(net, nf_ct_bridge_info->ops, 555d035f19fSPablo Neira Ayuso nf_ct_bridge_info->ops_size); 556a0ae2562SFlorian Westphal 557d035f19fSPablo Neira Ayuso module_put(nf_ct_bridge_info->me); 558d035f19fSPablo Neira Ayuso break; 559d035f19fSPablo Neira Ayuso } 560a0ae2562SFlorian Westphal mutex_unlock(&nf_ct_proto_mutex); 561a0ae2562SFlorian Westphal } 562a0ae2562SFlorian Westphal 563a0ae2562SFlorian Westphal int nf_ct_netns_get(struct net *net, u8 nfproto) 564a0ae2562SFlorian Westphal { 565a0ae2562SFlorian Westphal int err; 566a0ae2562SFlorian Westphal 567a0ae2562SFlorian Westphal if (nfproto == NFPROTO_INET) { 568a0ae2562SFlorian Westphal err = nf_ct_netns_do_get(net, NFPROTO_IPV4); 569a0ae2562SFlorian Westphal if (err < 0) 570a0ae2562SFlorian Westphal goto err1; 571a0ae2562SFlorian Westphal err = nf_ct_netns_do_get(net, NFPROTO_IPV6); 572a0ae2562SFlorian Westphal if (err < 0) 573a0ae2562SFlorian Westphal goto err2; 574a0ae2562SFlorian Westphal } else { 575a0ae2562SFlorian Westphal err = nf_ct_netns_do_get(net, nfproto); 576a0ae2562SFlorian Westphal if (err < 0) 577a0ae2562SFlorian Westphal goto err1; 578a0ae2562SFlorian Westphal } 579a0ae2562SFlorian Westphal return 0; 580a0ae2562SFlorian Westphal 581a0ae2562SFlorian Westphal err2: 582a0ae2562SFlorian Westphal nf_ct_netns_put(net, NFPROTO_IPV4); 583a0ae2562SFlorian Westphal err1: 584a0ae2562SFlorian Westphal return err; 585a0ae2562SFlorian Westphal } 586a0ae2562SFlorian Westphal EXPORT_SYMBOL_GPL(nf_ct_netns_get); 587a0ae2562SFlorian Westphal 588a0ae2562SFlorian Westphal void nf_ct_netns_put(struct net *net, uint8_t nfproto) 589a0ae2562SFlorian Westphal { 590a0ae2562SFlorian Westphal if (nfproto == NFPROTO_INET) { 591a0ae2562SFlorian Westphal nf_ct_netns_do_put(net, NFPROTO_IPV4); 592a0ae2562SFlorian Westphal nf_ct_netns_do_put(net, NFPROTO_IPV6); 593a0ae2562SFlorian Westphal } else { 594a0ae2562SFlorian Westphal nf_ct_netns_do_put(net, nfproto); 595a0ae2562SFlorian Westphal } 596a0ae2562SFlorian Westphal } 597a0ae2562SFlorian Westphal EXPORT_SYMBOL_GPL(nf_ct_netns_put); 598a0ae2562SFlorian Westphal 599d035f19fSPablo Neira Ayuso void nf_ct_bridge_register(struct nf_ct_bridge_info *info) 600d035f19fSPablo Neira Ayuso { 601d035f19fSPablo Neira Ayuso WARN_ON(nf_ct_bridge_info); 602d035f19fSPablo Neira Ayuso mutex_lock(&nf_ct_proto_mutex); 603d035f19fSPablo Neira Ayuso nf_ct_bridge_info = info; 604d035f19fSPablo Neira Ayuso mutex_unlock(&nf_ct_proto_mutex); 605d035f19fSPablo Neira Ayuso } 606d035f19fSPablo Neira Ayuso EXPORT_SYMBOL_GPL(nf_ct_bridge_register); 607d035f19fSPablo Neira Ayuso 608d035f19fSPablo Neira Ayuso void nf_ct_bridge_unregister(struct nf_ct_bridge_info *info) 609d035f19fSPablo Neira Ayuso { 610d035f19fSPablo Neira Ayuso WARN_ON(!nf_ct_bridge_info); 611d035f19fSPablo Neira Ayuso mutex_lock(&nf_ct_proto_mutex); 612d035f19fSPablo Neira Ayuso nf_ct_bridge_info = NULL; 613d035f19fSPablo Neira Ayuso mutex_unlock(&nf_ct_proto_mutex); 614d035f19fSPablo Neira Ayuso } 615d035f19fSPablo Neira Ayuso EXPORT_SYMBOL_GPL(nf_ct_bridge_unregister); 616d035f19fSPablo Neira Ayuso 617a0ae2562SFlorian Westphal int nf_conntrack_proto_init(void) 618a0ae2562SFlorian Westphal { 6194a60dc74SFlorian Westphal int ret; 620a0ae2562SFlorian Westphal 621a0ae2562SFlorian Westphal ret = nf_register_sockopt(&so_getorigdst); 622a0ae2562SFlorian Westphal if (ret < 0) 623a0ae2562SFlorian Westphal return ret; 624a0ae2562SFlorian Westphal 625a0ae2562SFlorian Westphal #if IS_ENABLED(CONFIG_IPV6) 626a0ae2562SFlorian Westphal ret = nf_register_sockopt(&so_getorigdst6); 627a0ae2562SFlorian Westphal if (ret < 0) 628a0ae2562SFlorian Westphal goto cleanup_sockopt; 629a0ae2562SFlorian Westphal #endif 630dd2934a9SFlorian Westphal 631a0ae2562SFlorian Westphal return ret; 6324a60dc74SFlorian Westphal 633a0ae2562SFlorian Westphal #if IS_ENABLED(CONFIG_IPV6) 634a0ae2562SFlorian Westphal cleanup_sockopt: 635a0ae2562SFlorian Westphal nf_unregister_sockopt(&so_getorigdst6); 636a0ae2562SFlorian Westphal #endif 637a0ae2562SFlorian Westphal return ret; 638a0ae2562SFlorian Westphal } 639a0ae2562SFlorian Westphal 640a0ae2562SFlorian Westphal void nf_conntrack_proto_fini(void) 641a0ae2562SFlorian Westphal { 642a0ae2562SFlorian Westphal nf_unregister_sockopt(&so_getorigdst); 643a0ae2562SFlorian Westphal #if IS_ENABLED(CONFIG_IPV6) 644a0ae2562SFlorian Westphal nf_unregister_sockopt(&so_getorigdst6); 645a0ae2562SFlorian Westphal #endif 646a0ae2562SFlorian Westphal } 647a0ae2562SFlorian Westphal 6484a60dc74SFlorian Westphal void nf_conntrack_proto_pernet_init(struct net *net) 649ac5357ebSPatrick McHardy { 6502a389de8SFlorian Westphal nf_conntrack_generic_init_net(net); 6512a389de8SFlorian Westphal nf_conntrack_udp_init_net(net); 6522a389de8SFlorian Westphal nf_conntrack_tcp_init_net(net); 6532a389de8SFlorian Westphal nf_conntrack_icmp_init_net(net); 65481e01647SFlorian Westphal #if IS_ENABLED(CONFIG_IPV6) 6552a389de8SFlorian Westphal nf_conntrack_icmpv6_init_net(net); 65681e01647SFlorian Westphal #endif 6572a389de8SFlorian Westphal #ifdef CONFIG_NF_CT_PROTO_DCCP 6582a389de8SFlorian Westphal nf_conntrack_dccp_init_net(net); 6592a389de8SFlorian Westphal #endif 6602a389de8SFlorian Westphal #ifdef CONFIG_NF_CT_PROTO_SCTP 6612a389de8SFlorian Westphal nf_conntrack_sctp_init_net(net); 6622a389de8SFlorian Westphal #endif 6632a389de8SFlorian Westphal #ifdef CONFIG_NF_CT_PROTO_GRE 6642a389de8SFlorian Westphal nf_conntrack_gre_init_net(net); 6652a389de8SFlorian Westphal #endif 666ac5357ebSPatrick McHardy } 667ac5357ebSPatrick McHardy 66804d87001SGao feng void nf_conntrack_proto_pernet_fini(struct net *net) 669ac5357ebSPatrick McHardy { 67022fc4c4cSFlorian Westphal #ifdef CONFIG_NF_CT_PROTO_GRE 67122fc4c4cSFlorian Westphal nf_ct_gre_keymap_flush(net); 67222fc4c4cSFlorian Westphal #endif 67304d87001SGao feng } 67404d87001SGao feng 675a0ae2562SFlorian Westphal module_param_call(hashsize, nf_conntrack_set_hashsize, param_get_uint, 676a0ae2562SFlorian Westphal &nf_conntrack_htable_size, 0600); 677a0ae2562SFlorian Westphal 678a0ae2562SFlorian Westphal MODULE_ALIAS("ip_conntrack"); 679a0ae2562SFlorian Westphal MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET)); 680a0ae2562SFlorian Westphal MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET6)); 681a0ae2562SFlorian Westphal MODULE_LICENSE("GPL"); 682