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 124827318feSFlorian Westphal static unsigned int nf_confirm(struct sk_buff *skb, 125827318feSFlorian Westphal unsigned int protoff, 126827318feSFlorian Westphal struct nf_conn *ct, 127827318feSFlorian Westphal enum ip_conntrack_info ctinfo) 128a0ae2562SFlorian Westphal { 129a0ae2562SFlorian Westphal const struct nf_conn_help *help; 130a0ae2562SFlorian Westphal 131a0ae2562SFlorian Westphal help = nfct_help(ct); 132827318feSFlorian Westphal if (help) { 133827318feSFlorian Westphal const struct nf_conntrack_helper *helper; 134827318feSFlorian Westphal int ret; 135a0ae2562SFlorian Westphal 136a0ae2562SFlorian Westphal /* rcu_read_lock()ed by nf_hook_thresh */ 137a0ae2562SFlorian Westphal helper = rcu_dereference(help->helper); 138827318feSFlorian Westphal if (helper) { 139827318feSFlorian Westphal ret = helper->help(skb, 140827318feSFlorian Westphal protoff, 141a0ae2562SFlorian Westphal ct, ctinfo); 142827318feSFlorian Westphal if (ret != NF_ACCEPT) 143827318feSFlorian Westphal return ret; 144827318feSFlorian Westphal } 145827318feSFlorian Westphal } 146827318feSFlorian Westphal 147827318feSFlorian Westphal if (test_bit(IPS_SEQ_ADJUST_BIT, &ct->status) && 148827318feSFlorian Westphal !nf_is_loopback_packet(skb)) { 149827318feSFlorian Westphal if (!nf_ct_seq_adjust(skb, ct, ctinfo, protoff)) { 150827318feSFlorian Westphal NF_CT_STAT_INC_ATOMIC(nf_ct_net(ct), drop); 151827318feSFlorian Westphal return NF_DROP; 152827318feSFlorian Westphal } 153827318feSFlorian Westphal } 154827318feSFlorian Westphal 155827318feSFlorian Westphal /* We've seen it coming out the other side: confirm it */ 156827318feSFlorian Westphal return nf_conntrack_confirm(skb); 157a0ae2562SFlorian Westphal } 158a0ae2562SFlorian Westphal 159a0ae2562SFlorian Westphal static unsigned int ipv4_confirm(void *priv, 160a0ae2562SFlorian Westphal struct sk_buff *skb, 161a0ae2562SFlorian Westphal const struct nf_hook_state *state) 162a0ae2562SFlorian Westphal { 163a0ae2562SFlorian Westphal enum ip_conntrack_info ctinfo; 164827318feSFlorian Westphal struct nf_conn *ct; 165a0ae2562SFlorian Westphal 166a0ae2562SFlorian Westphal ct = nf_ct_get(skb, &ctinfo); 167a0ae2562SFlorian Westphal if (!ct || ctinfo == IP_CT_RELATED_REPLY) 168a0ae2562SFlorian Westphal return nf_conntrack_confirm(skb); 169827318feSFlorian Westphal 170827318feSFlorian Westphal return nf_confirm(skb, 171827318feSFlorian Westphal skb_network_offset(skb) + ip_hdrlen(skb), 172827318feSFlorian Westphal ct, ctinfo); 173a0ae2562SFlorian Westphal } 174a0ae2562SFlorian Westphal 175a0ae2562SFlorian Westphal static unsigned int ipv4_conntrack_in(void *priv, 176a0ae2562SFlorian Westphal struct sk_buff *skb, 177a0ae2562SFlorian Westphal const struct nf_hook_state *state) 178a0ae2562SFlorian Westphal { 17993e66024SFlorian Westphal return nf_conntrack_in(skb, state); 180a0ae2562SFlorian Westphal } 181a0ae2562SFlorian Westphal 182a0ae2562SFlorian Westphal static unsigned int ipv4_conntrack_local(void *priv, 183a0ae2562SFlorian Westphal struct sk_buff *skb, 184a0ae2562SFlorian Westphal const struct nf_hook_state *state) 185a0ae2562SFlorian Westphal { 186a0ae2562SFlorian Westphal if (ip_is_fragment(ip_hdr(skb))) { /* IP_NODEFRAG setsockopt set */ 187a0ae2562SFlorian Westphal enum ip_conntrack_info ctinfo; 188a0ae2562SFlorian Westphal struct nf_conn *tmpl; 189a0ae2562SFlorian Westphal 190a0ae2562SFlorian Westphal tmpl = nf_ct_get(skb, &ctinfo); 191a0ae2562SFlorian Westphal if (tmpl && nf_ct_is_template(tmpl)) { 192a0ae2562SFlorian Westphal /* when skipping ct, clear templates to avoid fooling 193a0ae2562SFlorian Westphal * later targets/matches 194a0ae2562SFlorian Westphal */ 195a0ae2562SFlorian Westphal skb->_nfct = 0; 196a0ae2562SFlorian Westphal nf_ct_put(tmpl); 197a0ae2562SFlorian Westphal } 198a0ae2562SFlorian Westphal return NF_ACCEPT; 199a0ae2562SFlorian Westphal } 200a0ae2562SFlorian Westphal 20193e66024SFlorian Westphal return nf_conntrack_in(skb, state); 202a0ae2562SFlorian Westphal } 203a0ae2562SFlorian Westphal 204a0ae2562SFlorian Westphal /* Connection tracking may drop packets, but never alters them, so 205a0ae2562SFlorian Westphal * make it the first hook. 206a0ae2562SFlorian Westphal */ 207a0ae2562SFlorian Westphal static const struct nf_hook_ops ipv4_conntrack_ops[] = { 208a0ae2562SFlorian Westphal { 209a0ae2562SFlorian Westphal .hook = ipv4_conntrack_in, 210a0ae2562SFlorian Westphal .pf = NFPROTO_IPV4, 211a0ae2562SFlorian Westphal .hooknum = NF_INET_PRE_ROUTING, 212a0ae2562SFlorian Westphal .priority = NF_IP_PRI_CONNTRACK, 213a0ae2562SFlorian Westphal }, 214a0ae2562SFlorian Westphal { 215a0ae2562SFlorian Westphal .hook = ipv4_conntrack_local, 216a0ae2562SFlorian Westphal .pf = NFPROTO_IPV4, 217a0ae2562SFlorian Westphal .hooknum = NF_INET_LOCAL_OUT, 218a0ae2562SFlorian Westphal .priority = NF_IP_PRI_CONNTRACK, 219a0ae2562SFlorian Westphal }, 220a0ae2562SFlorian Westphal { 221a0ae2562SFlorian Westphal .hook = ipv4_confirm, 222a0ae2562SFlorian Westphal .pf = NFPROTO_IPV4, 223a0ae2562SFlorian Westphal .hooknum = NF_INET_POST_ROUTING, 224a0ae2562SFlorian Westphal .priority = NF_IP_PRI_CONNTRACK_CONFIRM, 225a0ae2562SFlorian Westphal }, 226a0ae2562SFlorian Westphal { 227a0ae2562SFlorian Westphal .hook = ipv4_confirm, 228a0ae2562SFlorian Westphal .pf = NFPROTO_IPV4, 229a0ae2562SFlorian Westphal .hooknum = NF_INET_LOCAL_IN, 230a0ae2562SFlorian Westphal .priority = NF_IP_PRI_CONNTRACK_CONFIRM, 231a0ae2562SFlorian Westphal }, 232a0ae2562SFlorian Westphal }; 233a0ae2562SFlorian Westphal 234a0ae2562SFlorian Westphal /* Fast function for those who don't want to parse /proc (and I don't 235a0ae2562SFlorian Westphal * blame them). 236a0ae2562SFlorian Westphal * Reversing the socket's dst/src point of view gives us the reply 237a0ae2562SFlorian Westphal * mapping. 238a0ae2562SFlorian Westphal */ 239a0ae2562SFlorian Westphal static int 240a0ae2562SFlorian Westphal getorigdst(struct sock *sk, int optval, void __user *user, int *len) 241a0ae2562SFlorian Westphal { 242a0ae2562SFlorian Westphal const struct inet_sock *inet = inet_sk(sk); 243a0ae2562SFlorian Westphal const struct nf_conntrack_tuple_hash *h; 244a0ae2562SFlorian Westphal struct nf_conntrack_tuple tuple; 245a0ae2562SFlorian Westphal 246a0ae2562SFlorian Westphal memset(&tuple, 0, sizeof(tuple)); 247a0ae2562SFlorian Westphal 248a0ae2562SFlorian Westphal lock_sock(sk); 249a0ae2562SFlorian Westphal tuple.src.u3.ip = inet->inet_rcv_saddr; 250a0ae2562SFlorian Westphal tuple.src.u.tcp.port = inet->inet_sport; 251a0ae2562SFlorian Westphal tuple.dst.u3.ip = inet->inet_daddr; 252a0ae2562SFlorian Westphal tuple.dst.u.tcp.port = inet->inet_dport; 253a0ae2562SFlorian Westphal tuple.src.l3num = PF_INET; 254a0ae2562SFlorian Westphal tuple.dst.protonum = sk->sk_protocol; 255a0ae2562SFlorian Westphal release_sock(sk); 256a0ae2562SFlorian Westphal 257a0ae2562SFlorian Westphal /* We only do TCP and SCTP at the moment: is there a better way? */ 258a0ae2562SFlorian Westphal if (tuple.dst.protonum != IPPROTO_TCP && 259a0ae2562SFlorian Westphal tuple.dst.protonum != IPPROTO_SCTP) { 260a0ae2562SFlorian Westphal pr_debug("SO_ORIGINAL_DST: Not a TCP/SCTP socket\n"); 261a0ae2562SFlorian Westphal return -ENOPROTOOPT; 262a0ae2562SFlorian Westphal } 263a0ae2562SFlorian Westphal 264a0ae2562SFlorian Westphal if ((unsigned int)*len < sizeof(struct sockaddr_in)) { 265a0ae2562SFlorian Westphal pr_debug("SO_ORIGINAL_DST: len %d not %zu\n", 266a0ae2562SFlorian Westphal *len, sizeof(struct sockaddr_in)); 267a0ae2562SFlorian Westphal return -EINVAL; 268a0ae2562SFlorian Westphal } 269a0ae2562SFlorian Westphal 270a0ae2562SFlorian Westphal h = nf_conntrack_find_get(sock_net(sk), &nf_ct_zone_dflt, &tuple); 271a0ae2562SFlorian Westphal if (h) { 272a0ae2562SFlorian Westphal struct sockaddr_in sin; 273a0ae2562SFlorian Westphal struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h); 274a0ae2562SFlorian Westphal 275a0ae2562SFlorian Westphal sin.sin_family = AF_INET; 276a0ae2562SFlorian Westphal sin.sin_port = ct->tuplehash[IP_CT_DIR_ORIGINAL] 277a0ae2562SFlorian Westphal .tuple.dst.u.tcp.port; 278a0ae2562SFlorian Westphal sin.sin_addr.s_addr = ct->tuplehash[IP_CT_DIR_ORIGINAL] 279a0ae2562SFlorian Westphal .tuple.dst.u3.ip; 280a0ae2562SFlorian Westphal memset(sin.sin_zero, 0, sizeof(sin.sin_zero)); 281a0ae2562SFlorian Westphal 282a0ae2562SFlorian Westphal pr_debug("SO_ORIGINAL_DST: %pI4 %u\n", 283a0ae2562SFlorian Westphal &sin.sin_addr.s_addr, ntohs(sin.sin_port)); 284a0ae2562SFlorian Westphal nf_ct_put(ct); 285a0ae2562SFlorian Westphal if (copy_to_user(user, &sin, sizeof(sin)) != 0) 286a0ae2562SFlorian Westphal return -EFAULT; 287a0ae2562SFlorian Westphal else 288a0ae2562SFlorian Westphal return 0; 289a0ae2562SFlorian Westphal } 290a0ae2562SFlorian Westphal pr_debug("SO_ORIGINAL_DST: Can't find %pI4/%u-%pI4/%u.\n", 291a0ae2562SFlorian Westphal &tuple.src.u3.ip, ntohs(tuple.src.u.tcp.port), 292a0ae2562SFlorian Westphal &tuple.dst.u3.ip, ntohs(tuple.dst.u.tcp.port)); 293a0ae2562SFlorian Westphal return -ENOENT; 294a0ae2562SFlorian Westphal } 295a0ae2562SFlorian Westphal 296a0ae2562SFlorian Westphal static struct nf_sockopt_ops so_getorigdst = { 297a0ae2562SFlorian Westphal .pf = PF_INET, 298a0ae2562SFlorian Westphal .get_optmin = SO_ORIGINAL_DST, 299a0ae2562SFlorian Westphal .get_optmax = SO_ORIGINAL_DST + 1, 300a0ae2562SFlorian Westphal .get = getorigdst, 301a0ae2562SFlorian Westphal .owner = THIS_MODULE, 302a0ae2562SFlorian Westphal }; 303a0ae2562SFlorian Westphal 304a0ae2562SFlorian Westphal #if IS_ENABLED(CONFIG_IPV6) 305a0ae2562SFlorian Westphal static int 306a0ae2562SFlorian Westphal ipv6_getorigdst(struct sock *sk, int optval, void __user *user, int *len) 307a0ae2562SFlorian Westphal { 308a0ae2562SFlorian Westphal struct nf_conntrack_tuple tuple = { .src.l3num = NFPROTO_IPV6 }; 309a0ae2562SFlorian Westphal const struct ipv6_pinfo *inet6 = inet6_sk(sk); 310a0ae2562SFlorian Westphal const struct inet_sock *inet = inet_sk(sk); 311a0ae2562SFlorian Westphal const struct nf_conntrack_tuple_hash *h; 312a0ae2562SFlorian Westphal struct sockaddr_in6 sin6; 313a0ae2562SFlorian Westphal struct nf_conn *ct; 314a0ae2562SFlorian Westphal __be32 flow_label; 315a0ae2562SFlorian Westphal int bound_dev_if; 316a0ae2562SFlorian Westphal 317a0ae2562SFlorian Westphal lock_sock(sk); 318a0ae2562SFlorian Westphal tuple.src.u3.in6 = sk->sk_v6_rcv_saddr; 319a0ae2562SFlorian Westphal tuple.src.u.tcp.port = inet->inet_sport; 320a0ae2562SFlorian Westphal tuple.dst.u3.in6 = sk->sk_v6_daddr; 321a0ae2562SFlorian Westphal tuple.dst.u.tcp.port = inet->inet_dport; 322a0ae2562SFlorian Westphal tuple.dst.protonum = sk->sk_protocol; 323a0ae2562SFlorian Westphal bound_dev_if = sk->sk_bound_dev_if; 324a0ae2562SFlorian Westphal flow_label = inet6->flow_label; 325a0ae2562SFlorian Westphal release_sock(sk); 326a0ae2562SFlorian Westphal 327a0ae2562SFlorian Westphal if (tuple.dst.protonum != IPPROTO_TCP && 328a0ae2562SFlorian Westphal tuple.dst.protonum != IPPROTO_SCTP) 329a0ae2562SFlorian Westphal return -ENOPROTOOPT; 330a0ae2562SFlorian Westphal 331a0ae2562SFlorian Westphal if (*len < 0 || (unsigned int)*len < sizeof(sin6)) 332a0ae2562SFlorian Westphal return -EINVAL; 333a0ae2562SFlorian Westphal 334a0ae2562SFlorian Westphal h = nf_conntrack_find_get(sock_net(sk), &nf_ct_zone_dflt, &tuple); 335a0ae2562SFlorian Westphal if (!h) { 336a0ae2562SFlorian Westphal pr_debug("IP6T_SO_ORIGINAL_DST: Can't find %pI6c/%u-%pI6c/%u.\n", 337a0ae2562SFlorian Westphal &tuple.src.u3.ip6, ntohs(tuple.src.u.tcp.port), 338a0ae2562SFlorian Westphal &tuple.dst.u3.ip6, ntohs(tuple.dst.u.tcp.port)); 339a0ae2562SFlorian Westphal return -ENOENT; 340a0ae2562SFlorian Westphal } 341a0ae2562SFlorian Westphal 342a0ae2562SFlorian Westphal ct = nf_ct_tuplehash_to_ctrack(h); 343a0ae2562SFlorian Westphal 344a0ae2562SFlorian Westphal sin6.sin6_family = AF_INET6; 345a0ae2562SFlorian Westphal sin6.sin6_port = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.tcp.port; 346a0ae2562SFlorian Westphal sin6.sin6_flowinfo = flow_label & IPV6_FLOWINFO_MASK; 347a0ae2562SFlorian Westphal memcpy(&sin6.sin6_addr, 348a0ae2562SFlorian Westphal &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.in6, 349a0ae2562SFlorian Westphal sizeof(sin6.sin6_addr)); 350a0ae2562SFlorian Westphal 351a0ae2562SFlorian Westphal nf_ct_put(ct); 352a0ae2562SFlorian Westphal sin6.sin6_scope_id = ipv6_iface_scope_id(&sin6.sin6_addr, bound_dev_if); 353a0ae2562SFlorian Westphal return copy_to_user(user, &sin6, sizeof(sin6)) ? -EFAULT : 0; 354a0ae2562SFlorian Westphal } 355a0ae2562SFlorian Westphal 356a0ae2562SFlorian Westphal static struct nf_sockopt_ops so_getorigdst6 = { 357a0ae2562SFlorian Westphal .pf = NFPROTO_IPV6, 358a0ae2562SFlorian Westphal .get_optmin = IP6T_SO_ORIGINAL_DST, 359a0ae2562SFlorian Westphal .get_optmax = IP6T_SO_ORIGINAL_DST + 1, 360a0ae2562SFlorian Westphal .get = ipv6_getorigdst, 361a0ae2562SFlorian Westphal .owner = THIS_MODULE, 362a0ae2562SFlorian Westphal }; 363a0ae2562SFlorian Westphal 364a0ae2562SFlorian Westphal static unsigned int ipv6_confirm(void *priv, 365a0ae2562SFlorian Westphal struct sk_buff *skb, 366a0ae2562SFlorian Westphal const struct nf_hook_state *state) 367a0ae2562SFlorian Westphal { 368a0ae2562SFlorian Westphal struct nf_conn *ct; 369a0ae2562SFlorian Westphal enum ip_conntrack_info ctinfo; 370a0ae2562SFlorian Westphal unsigned char pnum = ipv6_hdr(skb)->nexthdr; 371a0ae2562SFlorian Westphal __be16 frag_off; 372827318feSFlorian Westphal int protoff; 373a0ae2562SFlorian Westphal 374a0ae2562SFlorian Westphal ct = nf_ct_get(skb, &ctinfo); 375a0ae2562SFlorian Westphal if (!ct || ctinfo == IP_CT_RELATED_REPLY) 376827318feSFlorian Westphal return nf_conntrack_confirm(skb); 377a0ae2562SFlorian Westphal 378a0ae2562SFlorian Westphal protoff = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &pnum, 379a0ae2562SFlorian Westphal &frag_off); 380a0ae2562SFlorian Westphal if (protoff < 0 || (frag_off & htons(~0x7)) != 0) { 381a0ae2562SFlorian Westphal pr_debug("proto header not found\n"); 382827318feSFlorian Westphal return nf_conntrack_confirm(skb); 383a0ae2562SFlorian Westphal } 384a0ae2562SFlorian Westphal 385827318feSFlorian Westphal return nf_confirm(skb, protoff, ct, ctinfo); 386a0ae2562SFlorian Westphal } 387a0ae2562SFlorian Westphal 388a0ae2562SFlorian Westphal static unsigned int ipv6_conntrack_in(void *priv, 389a0ae2562SFlorian Westphal struct sk_buff *skb, 390a0ae2562SFlorian Westphal const struct nf_hook_state *state) 391a0ae2562SFlorian Westphal { 39293e66024SFlorian Westphal return nf_conntrack_in(skb, state); 393a0ae2562SFlorian Westphal } 394a0ae2562SFlorian Westphal 395a0ae2562SFlorian Westphal static unsigned int ipv6_conntrack_local(void *priv, 396a0ae2562SFlorian Westphal struct sk_buff *skb, 397a0ae2562SFlorian Westphal const struct nf_hook_state *state) 398a0ae2562SFlorian Westphal { 39993e66024SFlorian Westphal return nf_conntrack_in(skb, state); 400a0ae2562SFlorian Westphal } 401a0ae2562SFlorian Westphal 402a0ae2562SFlorian Westphal static const struct nf_hook_ops ipv6_conntrack_ops[] = { 403a0ae2562SFlorian Westphal { 404a0ae2562SFlorian Westphal .hook = ipv6_conntrack_in, 405a0ae2562SFlorian Westphal .pf = NFPROTO_IPV6, 406a0ae2562SFlorian Westphal .hooknum = NF_INET_PRE_ROUTING, 407a0ae2562SFlorian Westphal .priority = NF_IP6_PRI_CONNTRACK, 408a0ae2562SFlorian Westphal }, 409a0ae2562SFlorian Westphal { 410a0ae2562SFlorian Westphal .hook = ipv6_conntrack_local, 411a0ae2562SFlorian Westphal .pf = NFPROTO_IPV6, 412a0ae2562SFlorian Westphal .hooknum = NF_INET_LOCAL_OUT, 413a0ae2562SFlorian Westphal .priority = NF_IP6_PRI_CONNTRACK, 414a0ae2562SFlorian Westphal }, 415a0ae2562SFlorian Westphal { 416a0ae2562SFlorian Westphal .hook = ipv6_confirm, 417a0ae2562SFlorian Westphal .pf = NFPROTO_IPV6, 418a0ae2562SFlorian Westphal .hooknum = NF_INET_POST_ROUTING, 419a0ae2562SFlorian Westphal .priority = NF_IP6_PRI_LAST, 420a0ae2562SFlorian Westphal }, 421a0ae2562SFlorian Westphal { 422a0ae2562SFlorian Westphal .hook = ipv6_confirm, 423a0ae2562SFlorian Westphal .pf = NFPROTO_IPV6, 424a0ae2562SFlorian Westphal .hooknum = NF_INET_LOCAL_IN, 425a0ae2562SFlorian Westphal .priority = NF_IP6_PRI_LAST - 1, 426a0ae2562SFlorian Westphal }, 427a0ae2562SFlorian Westphal }; 428a0ae2562SFlorian Westphal #endif 429a0ae2562SFlorian Westphal 430f94e6380SFlorian Westphal static int nf_ct_tcp_fixup(struct nf_conn *ct, void *_nfproto) 431f94e6380SFlorian Westphal { 432f94e6380SFlorian Westphal u8 nfproto = (unsigned long)_nfproto; 433f94e6380SFlorian Westphal 434f94e6380SFlorian Westphal if (nf_ct_l3num(ct) != nfproto) 435f94e6380SFlorian Westphal return 0; 436f94e6380SFlorian Westphal 437f94e6380SFlorian Westphal if (nf_ct_protonum(ct) == IPPROTO_TCP && 438f94e6380SFlorian Westphal ct->proto.tcp.state == TCP_CONNTRACK_ESTABLISHED) { 439f94e6380SFlorian Westphal ct->proto.tcp.seen[0].td_maxwin = 0; 440f94e6380SFlorian Westphal ct->proto.tcp.seen[1].td_maxwin = 0; 441f94e6380SFlorian Westphal } 442f94e6380SFlorian Westphal 443f94e6380SFlorian Westphal return 0; 444f94e6380SFlorian Westphal } 445f94e6380SFlorian Westphal 446d035f19fSPablo Neira Ayuso static struct nf_ct_bridge_info *nf_ct_bridge_info; 447d035f19fSPablo Neira Ayuso 448a0ae2562SFlorian Westphal static int nf_ct_netns_do_get(struct net *net, u8 nfproto) 449a0ae2562SFlorian Westphal { 450a0ae2562SFlorian Westphal struct nf_conntrack_net *cnet = net_generic(net, nf_conntrack_net_id); 451d035f19fSPablo Neira Ayuso bool fixup_needed = false, retry = true; 452a0ae2562SFlorian Westphal int err = 0; 453d035f19fSPablo Neira Ayuso retry: 454a0ae2562SFlorian Westphal mutex_lock(&nf_ct_proto_mutex); 455a0ae2562SFlorian Westphal 456a0ae2562SFlorian Westphal switch (nfproto) { 457a0ae2562SFlorian Westphal case NFPROTO_IPV4: 458a0ae2562SFlorian Westphal cnet->users4++; 459a0ae2562SFlorian Westphal if (cnet->users4 > 1) 460a0ae2562SFlorian Westphal goto out_unlock; 461a0ae2562SFlorian Westphal err = nf_defrag_ipv4_enable(net); 462a0ae2562SFlorian Westphal if (err) { 463a0ae2562SFlorian Westphal cnet->users4 = 0; 464a0ae2562SFlorian Westphal goto out_unlock; 465a0ae2562SFlorian Westphal } 466a0ae2562SFlorian Westphal 467a0ae2562SFlorian Westphal err = nf_register_net_hooks(net, ipv4_conntrack_ops, 468a0ae2562SFlorian Westphal ARRAY_SIZE(ipv4_conntrack_ops)); 469a0ae2562SFlorian Westphal if (err) 470a0ae2562SFlorian Westphal cnet->users4 = 0; 471f94e6380SFlorian Westphal else 472f94e6380SFlorian Westphal fixup_needed = true; 473a0ae2562SFlorian Westphal break; 474a0ae2562SFlorian Westphal #if IS_ENABLED(CONFIG_IPV6) 475a0ae2562SFlorian Westphal case NFPROTO_IPV6: 476a0ae2562SFlorian Westphal cnet->users6++; 477a0ae2562SFlorian Westphal if (cnet->users6 > 1) 478a0ae2562SFlorian Westphal goto out_unlock; 479a0ae2562SFlorian Westphal err = nf_defrag_ipv6_enable(net); 480a0ae2562SFlorian Westphal if (err < 0) { 481a0ae2562SFlorian Westphal cnet->users6 = 0; 482a0ae2562SFlorian Westphal goto out_unlock; 483a0ae2562SFlorian Westphal } 484a0ae2562SFlorian Westphal 485a0ae2562SFlorian Westphal err = nf_register_net_hooks(net, ipv6_conntrack_ops, 486a0ae2562SFlorian Westphal ARRAY_SIZE(ipv6_conntrack_ops)); 487a0ae2562SFlorian Westphal if (err) 488a0ae2562SFlorian Westphal cnet->users6 = 0; 489f94e6380SFlorian Westphal else 490f94e6380SFlorian Westphal fixup_needed = true; 491a0ae2562SFlorian Westphal break; 492a0ae2562SFlorian Westphal #endif 493d035f19fSPablo Neira Ayuso case NFPROTO_BRIDGE: 494d035f19fSPablo Neira Ayuso if (!nf_ct_bridge_info) { 495d035f19fSPablo Neira Ayuso if (!retry) { 496d035f19fSPablo Neira Ayuso err = -EPROTO; 497d035f19fSPablo Neira Ayuso goto out_unlock; 498d035f19fSPablo Neira Ayuso } 499d035f19fSPablo Neira Ayuso mutex_unlock(&nf_ct_proto_mutex); 500d035f19fSPablo Neira Ayuso request_module("nf_conntrack_bridge"); 501d035f19fSPablo Neira Ayuso retry = false; 502d035f19fSPablo Neira Ayuso goto retry; 503d035f19fSPablo Neira Ayuso } 504d035f19fSPablo Neira Ayuso if (!try_module_get(nf_ct_bridge_info->me)) { 505d035f19fSPablo Neira Ayuso err = -EPROTO; 506d035f19fSPablo Neira Ayuso goto out_unlock; 507d035f19fSPablo Neira Ayuso } 508d035f19fSPablo Neira Ayuso cnet->users_bridge++; 509d035f19fSPablo Neira Ayuso if (cnet->users_bridge > 1) 510d035f19fSPablo Neira Ayuso goto out_unlock; 511d035f19fSPablo Neira Ayuso 512d035f19fSPablo Neira Ayuso err = nf_register_net_hooks(net, nf_ct_bridge_info->ops, 513d035f19fSPablo Neira Ayuso nf_ct_bridge_info->ops_size); 514d035f19fSPablo Neira Ayuso if (err) 515d035f19fSPablo Neira Ayuso cnet->users_bridge = 0; 516d035f19fSPablo Neira Ayuso else 517d035f19fSPablo Neira Ayuso fixup_needed = true; 518d035f19fSPablo Neira Ayuso break; 519a0ae2562SFlorian Westphal default: 520a0ae2562SFlorian Westphal err = -EPROTO; 521a0ae2562SFlorian Westphal break; 522a0ae2562SFlorian Westphal } 523a0ae2562SFlorian Westphal out_unlock: 524a0ae2562SFlorian Westphal mutex_unlock(&nf_ct_proto_mutex); 525f94e6380SFlorian Westphal 526f94e6380SFlorian Westphal if (fixup_needed) 527f94e6380SFlorian Westphal nf_ct_iterate_cleanup_net(net, nf_ct_tcp_fixup, 528f94e6380SFlorian Westphal (void *)(unsigned long)nfproto, 0, 0); 529f94e6380SFlorian Westphal 530a0ae2562SFlorian Westphal return err; 531a0ae2562SFlorian Westphal } 532a0ae2562SFlorian Westphal 533a0ae2562SFlorian Westphal static void nf_ct_netns_do_put(struct net *net, u8 nfproto) 534a0ae2562SFlorian Westphal { 535a0ae2562SFlorian Westphal struct nf_conntrack_net *cnet = net_generic(net, nf_conntrack_net_id); 536a0ae2562SFlorian Westphal 537a0ae2562SFlorian Westphal mutex_lock(&nf_ct_proto_mutex); 538a0ae2562SFlorian Westphal switch (nfproto) { 539a0ae2562SFlorian Westphal case NFPROTO_IPV4: 540a0ae2562SFlorian Westphal if (cnet->users4 && (--cnet->users4 == 0)) 541a0ae2562SFlorian Westphal nf_unregister_net_hooks(net, ipv4_conntrack_ops, 542a0ae2562SFlorian Westphal ARRAY_SIZE(ipv4_conntrack_ops)); 543a0ae2562SFlorian Westphal break; 544a0ae2562SFlorian Westphal #if IS_ENABLED(CONFIG_IPV6) 545a0ae2562SFlorian Westphal case NFPROTO_IPV6: 546a0ae2562SFlorian Westphal if (cnet->users6 && (--cnet->users6 == 0)) 547a0ae2562SFlorian Westphal nf_unregister_net_hooks(net, ipv6_conntrack_ops, 548a0ae2562SFlorian Westphal ARRAY_SIZE(ipv6_conntrack_ops)); 549a0ae2562SFlorian Westphal break; 550a0ae2562SFlorian Westphal #endif 551d035f19fSPablo Neira Ayuso case NFPROTO_BRIDGE: 552d035f19fSPablo Neira Ayuso if (!nf_ct_bridge_info) 553d035f19fSPablo Neira Ayuso break; 554d035f19fSPablo Neira Ayuso if (cnet->users_bridge && (--cnet->users_bridge == 0)) 555d035f19fSPablo Neira Ayuso nf_unregister_net_hooks(net, nf_ct_bridge_info->ops, 556d035f19fSPablo Neira Ayuso nf_ct_bridge_info->ops_size); 557a0ae2562SFlorian Westphal 558d035f19fSPablo Neira Ayuso module_put(nf_ct_bridge_info->me); 559d035f19fSPablo Neira Ayuso break; 560d035f19fSPablo Neira Ayuso } 561a0ae2562SFlorian Westphal mutex_unlock(&nf_ct_proto_mutex); 562a0ae2562SFlorian Westphal } 563a0ae2562SFlorian Westphal 564a0ae2562SFlorian Westphal int nf_ct_netns_get(struct net *net, u8 nfproto) 565a0ae2562SFlorian Westphal { 566a0ae2562SFlorian Westphal int err; 567a0ae2562SFlorian Westphal 568a0ae2562SFlorian Westphal if (nfproto == NFPROTO_INET) { 569a0ae2562SFlorian Westphal err = nf_ct_netns_do_get(net, NFPROTO_IPV4); 570a0ae2562SFlorian Westphal if (err < 0) 571a0ae2562SFlorian Westphal goto err1; 572a0ae2562SFlorian Westphal err = nf_ct_netns_do_get(net, NFPROTO_IPV6); 573a0ae2562SFlorian Westphal if (err < 0) 574a0ae2562SFlorian Westphal goto err2; 575a0ae2562SFlorian Westphal } else { 576a0ae2562SFlorian Westphal err = nf_ct_netns_do_get(net, nfproto); 577a0ae2562SFlorian Westphal if (err < 0) 578a0ae2562SFlorian Westphal goto err1; 579a0ae2562SFlorian Westphal } 580a0ae2562SFlorian Westphal return 0; 581a0ae2562SFlorian Westphal 582a0ae2562SFlorian Westphal err2: 583a0ae2562SFlorian Westphal nf_ct_netns_put(net, NFPROTO_IPV4); 584a0ae2562SFlorian Westphal err1: 585a0ae2562SFlorian Westphal return err; 586a0ae2562SFlorian Westphal } 587a0ae2562SFlorian Westphal EXPORT_SYMBOL_GPL(nf_ct_netns_get); 588a0ae2562SFlorian Westphal 589a0ae2562SFlorian Westphal void nf_ct_netns_put(struct net *net, uint8_t nfproto) 590a0ae2562SFlorian Westphal { 591a0ae2562SFlorian Westphal if (nfproto == NFPROTO_INET) { 592a0ae2562SFlorian Westphal nf_ct_netns_do_put(net, NFPROTO_IPV4); 593a0ae2562SFlorian Westphal nf_ct_netns_do_put(net, NFPROTO_IPV6); 594a0ae2562SFlorian Westphal } else { 595a0ae2562SFlorian Westphal nf_ct_netns_do_put(net, nfproto); 596a0ae2562SFlorian Westphal } 597a0ae2562SFlorian Westphal } 598a0ae2562SFlorian Westphal EXPORT_SYMBOL_GPL(nf_ct_netns_put); 599a0ae2562SFlorian Westphal 600d035f19fSPablo Neira Ayuso void nf_ct_bridge_register(struct nf_ct_bridge_info *info) 601d035f19fSPablo Neira Ayuso { 602d035f19fSPablo Neira Ayuso WARN_ON(nf_ct_bridge_info); 603d035f19fSPablo Neira Ayuso mutex_lock(&nf_ct_proto_mutex); 604d035f19fSPablo Neira Ayuso nf_ct_bridge_info = info; 605d035f19fSPablo Neira Ayuso mutex_unlock(&nf_ct_proto_mutex); 606d035f19fSPablo Neira Ayuso } 607d035f19fSPablo Neira Ayuso EXPORT_SYMBOL_GPL(nf_ct_bridge_register); 608d035f19fSPablo Neira Ayuso 609d035f19fSPablo Neira Ayuso void nf_ct_bridge_unregister(struct nf_ct_bridge_info *info) 610d035f19fSPablo Neira Ayuso { 611d035f19fSPablo Neira Ayuso WARN_ON(!nf_ct_bridge_info); 612d035f19fSPablo Neira Ayuso mutex_lock(&nf_ct_proto_mutex); 613d035f19fSPablo Neira Ayuso nf_ct_bridge_info = NULL; 614d035f19fSPablo Neira Ayuso mutex_unlock(&nf_ct_proto_mutex); 615d035f19fSPablo Neira Ayuso } 616d035f19fSPablo Neira Ayuso EXPORT_SYMBOL_GPL(nf_ct_bridge_unregister); 617d035f19fSPablo Neira Ayuso 618a0ae2562SFlorian Westphal int nf_conntrack_proto_init(void) 619a0ae2562SFlorian Westphal { 6204a60dc74SFlorian Westphal int ret; 621a0ae2562SFlorian Westphal 622a0ae2562SFlorian Westphal ret = nf_register_sockopt(&so_getorigdst); 623a0ae2562SFlorian Westphal if (ret < 0) 624a0ae2562SFlorian Westphal return ret; 625a0ae2562SFlorian Westphal 626a0ae2562SFlorian Westphal #if IS_ENABLED(CONFIG_IPV6) 627a0ae2562SFlorian Westphal ret = nf_register_sockopt(&so_getorigdst6); 628a0ae2562SFlorian Westphal if (ret < 0) 629a0ae2562SFlorian Westphal goto cleanup_sockopt; 630a0ae2562SFlorian Westphal #endif 631dd2934a9SFlorian Westphal 632a0ae2562SFlorian Westphal return ret; 6334a60dc74SFlorian Westphal 634a0ae2562SFlorian Westphal #if IS_ENABLED(CONFIG_IPV6) 635a0ae2562SFlorian Westphal cleanup_sockopt: 636a0ae2562SFlorian Westphal nf_unregister_sockopt(&so_getorigdst6); 637a0ae2562SFlorian Westphal #endif 638a0ae2562SFlorian Westphal return ret; 639a0ae2562SFlorian Westphal } 640a0ae2562SFlorian Westphal 641a0ae2562SFlorian Westphal void nf_conntrack_proto_fini(void) 642a0ae2562SFlorian Westphal { 643a0ae2562SFlorian Westphal nf_unregister_sockopt(&so_getorigdst); 644a0ae2562SFlorian Westphal #if IS_ENABLED(CONFIG_IPV6) 645a0ae2562SFlorian Westphal nf_unregister_sockopt(&so_getorigdst6); 646a0ae2562SFlorian Westphal #endif 647a0ae2562SFlorian Westphal } 648a0ae2562SFlorian Westphal 6494a60dc74SFlorian Westphal void nf_conntrack_proto_pernet_init(struct net *net) 650ac5357ebSPatrick McHardy { 6512a389de8SFlorian Westphal nf_conntrack_generic_init_net(net); 6522a389de8SFlorian Westphal nf_conntrack_udp_init_net(net); 6532a389de8SFlorian Westphal nf_conntrack_tcp_init_net(net); 6542a389de8SFlorian Westphal nf_conntrack_icmp_init_net(net); 65581e01647SFlorian Westphal #if IS_ENABLED(CONFIG_IPV6) 6562a389de8SFlorian Westphal nf_conntrack_icmpv6_init_net(net); 65781e01647SFlorian Westphal #endif 6582a389de8SFlorian Westphal #ifdef CONFIG_NF_CT_PROTO_DCCP 6592a389de8SFlorian Westphal nf_conntrack_dccp_init_net(net); 6602a389de8SFlorian Westphal #endif 6612a389de8SFlorian Westphal #ifdef CONFIG_NF_CT_PROTO_SCTP 6622a389de8SFlorian Westphal nf_conntrack_sctp_init_net(net); 6632a389de8SFlorian Westphal #endif 6642a389de8SFlorian Westphal #ifdef CONFIG_NF_CT_PROTO_GRE 6652a389de8SFlorian Westphal nf_conntrack_gre_init_net(net); 6662a389de8SFlorian Westphal #endif 667ac5357ebSPatrick McHardy } 668ac5357ebSPatrick McHardy 66904d87001SGao feng void nf_conntrack_proto_pernet_fini(struct net *net) 670ac5357ebSPatrick McHardy { 67122fc4c4cSFlorian Westphal #ifdef CONFIG_NF_CT_PROTO_GRE 67222fc4c4cSFlorian Westphal nf_ct_gre_keymap_flush(net); 67322fc4c4cSFlorian Westphal #endif 67404d87001SGao feng } 67504d87001SGao feng 676a0ae2562SFlorian Westphal module_param_call(hashsize, nf_conntrack_set_hashsize, param_get_uint, 677a0ae2562SFlorian Westphal &nf_conntrack_htable_size, 0600); 678a0ae2562SFlorian Westphal 679a0ae2562SFlorian Westphal MODULE_ALIAS("ip_conntrack"); 680a0ae2562SFlorian Westphal MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET)); 681a0ae2562SFlorian Westphal MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET6)); 682a0ae2562SFlorian Westphal MODULE_LICENSE("GPL"); 683