133965Sjdp// SPDX-License-Identifier: GPL-2.0-only 2218822Sdim/* (C) 1999-2001 Paul `Rusty' Russell 3218822Sdim * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org> 433965Sjdp */ 5130561Sobrien 633965Sjdp#include <linux/module.h> 7130561Sobrien#include <net/ip.h> 8130561Sobrien#include <net/tcp.h> 9130561Sobrien#include <net/route.h> 10130561Sobrien#include <net/dst.h> 1133965Sjdp#include <net/netfilter/ipv4/nf_reject.h> 12130561Sobrien#include <linux/netfilter_ipv4.h> 13130561Sobrien#include <linux/netfilter_bridge.h> 14130561Sobrien 15130561Sobrienstatic int nf_reject_iphdr_validate(struct sk_buff *skb) 1633965Sjdp{ 17130561Sobrien struct iphdr *iph; 18130561Sobrien u32 len; 19218822Sdim 2033965Sjdp if (!pskb_may_pull(skb, sizeof(struct iphdr))) 2138889Sjdp return 0; 22218822Sdim 2338889Sjdp iph = ip_hdr(skb); 2460484Sobrien if (iph->ihl < 5 || iph->version != 4) 2533965Sjdp return 0; 2660484Sobrien 2785815Sobrien len = ntohs(iph->tot_len); 2833965Sjdp if (skb->len < len) 29218822Sdim return 0; 30218822Sdim else if (len < (iph->ihl*4)) 31218822Sdim return 0; 32218822Sdim 33218822Sdim if (!pskb_may_pull(skb, iph->ihl*4)) 34218822Sdim return 0; 35218822Sdim 36218822Sdim return 1; 37218822Sdim} 38218822Sdim 39218822Sdimstruct sk_buff *nf_reject_skb_v4_tcp_reset(struct net *net, 40218822Sdim struct sk_buff *oldskb, 41218822Sdim const struct net_device *dev, 42218822Sdim int hook) 43218822Sdim{ 44218822Sdim const struct tcphdr *oth; 45218822Sdim struct sk_buff *nskb; 46218822Sdim struct iphdr *niph; 47218822Sdim struct tcphdr _oth; 48218822Sdim 49218822Sdim if (!nf_reject_iphdr_validate(oldskb)) 50130561Sobrien return NULL; 5189857Sobrien 5260484Sobrien oth = nf_reject_ip_tcphdr_get(oldskb, &_oth, hook); 5360484Sobrien if (!oth) 5460484Sobrien return NULL; 5560484Sobrien 5633965Sjdp nskb = alloc_skb(sizeof(struct iphdr) + sizeof(struct tcphdr) + 5733965Sjdp LL_MAX_HEADER, GFP_ATOMIC); 5833965Sjdp if (!nskb) 5933965Sjdp return NULL; 6033965Sjdp 6133965Sjdp nskb->dev = (struct net_device *)dev; 6285815Sobrien 6360484Sobrien skb_reserve(nskb, LL_MAX_HEADER); 6433965Sjdp niph = nf_reject_iphdr_put(nskb, oldskb, IPPROTO_TCP, 6533965Sjdp READ_ONCE(net->ipv4.sysctl_ip_default_ttl)); 6633965Sjdp nf_reject_ip_tcphdr_put(nskb, oldskb, oth); 6733965Sjdp niph->tot_len = htons(nskb->len); 6885815Sobrien ip_send_check(niph); 6933965Sjdp 7033965Sjdp return nskb; 7133965Sjdp} 7233965SjdpEXPORT_SYMBOL_GPL(nf_reject_skb_v4_tcp_reset); 7333965Sjdp 7433965Sjdpstruct sk_buff *nf_reject_skb_v4_unreach(struct net *net, 7533965Sjdp struct sk_buff *oldskb, 7633965Sjdp const struct net_device *dev, 7733965Sjdp int hook, u8 code) 7833965Sjdp{ 7933965Sjdp struct sk_buff *nskb; 8033965Sjdp struct iphdr *niph; 8133965Sjdp struct icmphdr *icmph; 82130561Sobrien unsigned int len; 83130561Sobrien int dataoff; 8460484Sobrien __wsum csum; 8560484Sobrien u8 proto; 8633965Sjdp 87218822Sdim if (!nf_reject_iphdr_validate(oldskb)) 88218822Sdim return NULL; 8933965Sjdp 9033965Sjdp /* IP header checks: fragment. */ 9185815Sobrien if (ip_hdr(oldskb)->frag_off & htons(IP_OFFSET)) 9260484Sobrien return NULL; 9333965Sjdp 9433965Sjdp /* RFC says return as much as we can without exceeding 576 bytes. */ 9533965Sjdp len = min_t(unsigned int, 536, oldskb->len); 9633965Sjdp 9733965Sjdp if (!pskb_may_pull(oldskb, len)) 9860484Sobrien return NULL; 9933965Sjdp 10033965Sjdp if (pskb_trim_rcsum(oldskb, ntohs(ip_hdr(oldskb)->tot_len))) 10133965Sjdp return NULL; 10233965Sjdp 10333965Sjdp dataoff = ip_hdrlen(oldskb); 10433965Sjdp proto = ip_hdr(oldskb)->protocol; 10538889Sjdp 10660484Sobrien if (!skb_csum_unnecessary(oldskb) && 10738889Sjdp nf_reject_verify_csum(oldskb, dataoff, proto) && 10885815Sobrien nf_ip_checksum(oldskb, hook, ip_hdrlen(oldskb), proto)) 10938889Sjdp return NULL; 11033965Sjdp 11133965Sjdp nskb = alloc_skb(sizeof(struct iphdr) + sizeof(struct icmphdr) + 11260484Sobrien LL_MAX_HEADER + len, GFP_ATOMIC); 11360484Sobrien if (!nskb) 11485815Sobrien return NULL; 11533965Sjdp 11638889Sjdp nskb->dev = (struct net_device *)dev; 11738889Sjdp 11833965Sjdp skb_reserve(nskb, LL_MAX_HEADER); 11933965Sjdp niph = nf_reject_iphdr_put(nskb, oldskb, IPPROTO_ICMP, 12089857Sobrien READ_ONCE(net->ipv4.sysctl_ip_default_ttl)); 12189857Sobrien 12289857Sobrien skb_reset_transport_header(nskb); 12389857Sobrien icmph = skb_put_zero(nskb, sizeof(struct icmphdr)); 12489857Sobrien icmph->type = ICMP_DEST_UNREACH; 12589857Sobrien icmph->code = code; 12689857Sobrien 12789857Sobrien skb_put_data(nskb, skb_network_header(oldskb), len); 12838889Sjdp 129104834Sobrien csum = csum_partial((void *)icmph, len + sizeof(struct icmphdr), 0); 130104834Sobrien icmph->checksum = csum_fold(csum); 13189857Sobrien 13260484Sobrien niph->tot_len = htons(nskb->len); 13389857Sobrien ip_send_check(niph); 13489857Sobrien 13589857Sobrien return nskb; 136130561Sobrien} 13789857SobrienEXPORT_SYMBOL_GPL(nf_reject_skb_v4_unreach); 13889857Sobrien 13989857Sobrienconst struct tcphdr *nf_reject_ip_tcphdr_get(struct sk_buff *oldskb, 14089857Sobrien struct tcphdr *_oth, int hook) 14189857Sobrien{ 14289857Sobrien const struct tcphdr *oth; 14389857Sobrien 14489857Sobrien /* IP header checks: fragment. */ 14589857Sobrien if (ip_hdr(oldskb)->frag_off & htons(IP_OFFSET)) 14689857Sobrien return NULL; 14789857Sobrien 14889857Sobrien if (ip_hdr(oldskb)->protocol != IPPROTO_TCP) 14989857Sobrien return NULL; 15089857Sobrien 15189857Sobrien oth = skb_header_pointer(oldskb, ip_hdrlen(oldskb), 15289857Sobrien sizeof(struct tcphdr), _oth); 15389857Sobrien if (oth == NULL) 154130561Sobrien return NULL; 155130561Sobrien 15689857Sobrien /* No RST for RST. */ 15789857Sobrien if (oth->rst) 15889857Sobrien return NULL; 15989857Sobrien 16089857Sobrien /* Check checksum */ 16189857Sobrien if (nf_ip_checksum(oldskb, hook, ip_hdrlen(oldskb), IPPROTO_TCP)) 16238889Sjdp return NULL; 16389857Sobrien 16438889Sjdp return oth; 16589857Sobrien} 16685815SobrienEXPORT_SYMBOL_GPL(nf_reject_ip_tcphdr_get); 16789857Sobrien 16889857Sobrienstruct iphdr *nf_reject_iphdr_put(struct sk_buff *nskb, 16989857Sobrien const struct sk_buff *oldskb, 17038889Sjdp __u8 protocol, int ttl) 17189857Sobrien{ 17289857Sobrien struct iphdr *niph, *oiph = ip_hdr(oldskb); 17389857Sobrien 17489857Sobrien skb_reset_network_header(nskb); 17589857Sobrien niph = skb_put(nskb, sizeof(struct iphdr)); 17689857Sobrien niph->version = 4; 17789857Sobrien niph->ihl = sizeof(struct iphdr) / 4; 17889857Sobrien niph->tos = 0; 17989857Sobrien niph->id = 0; 18089857Sobrien niph->frag_off = htons(IP_DF); 18189857Sobrien niph->protocol = protocol; 18289857Sobrien niph->check = 0; 18389857Sobrien niph->saddr = oiph->daddr; 18438889Sjdp niph->daddr = oiph->saddr; 18538889Sjdp niph->ttl = ttl; 18638889Sjdp 18738889Sjdp nskb->protocol = htons(ETH_P_IP); 18889857Sobrien 18989857Sobrien return niph; 19038889Sjdp} 19189857SobrienEXPORT_SYMBOL_GPL(nf_reject_iphdr_put); 19289857Sobrien 19389857Sobrienvoid nf_reject_ip_tcphdr_put(struct sk_buff *nskb, const struct sk_buff *oldskb, 19489857Sobrien const struct tcphdr *oth) 19589857Sobrien{ 19685815Sobrien struct iphdr *niph = ip_hdr(nskb); 19789857Sobrien struct tcphdr *tcph; 198104834Sobrien 19989857Sobrien skb_reset_transport_header(nskb); 20089857Sobrien tcph = skb_put_zero(nskb, sizeof(struct tcphdr)); 20138889Sjdp tcph->source = oth->dest; 20238889Sjdp tcph->dest = oth->source; 20338889Sjdp tcph->doff = sizeof(struct tcphdr) / 4; 20489857Sobrien 20589857Sobrien if (oth->ack) { 20638889Sjdp tcph->seq = oth->ack_seq; 20789857Sobrien } else { 20889857Sobrien tcph->ack_seq = htonl(ntohl(oth->seq) + oth->syn + oth->fin + 20989857Sobrien oldskb->len - ip_hdrlen(oldskb) - 21089857Sobrien (oth->doff << 2)); 21189857Sobrien tcph->ack = 1; 21238889Sjdp } 21338889Sjdp 21489857Sobrien tcph->rst = 1; 21589857Sobrien tcph->check = ~tcp_v4_check(sizeof(struct tcphdr), niph->saddr, 21689857Sobrien niph->daddr, 0); 21789857Sobrien nskb->ip_summed = CHECKSUM_PARTIAL; 21889857Sobrien nskb->csum_start = (unsigned char *)tcph - nskb->head; 21938889Sjdp nskb->csum_offset = offsetof(struct tcphdr, check); 22038889Sjdp} 22189857SobrienEXPORT_SYMBOL_GPL(nf_reject_ip_tcphdr_put); 22289857Sobrien 22389857Sobrienstatic int nf_reject_fill_skb_dst(struct sk_buff *skb_in) 22489857Sobrien{ 22589857Sobrien struct dst_entry *dst = NULL; 22638889Sjdp struct flowi fl; 22785815Sobrien 22860484Sobrien memset(&fl, 0, sizeof(struct flowi)); 22938889Sjdp fl.u.ip4.daddr = ip_hdr(skb_in)->saddr; 23089857Sobrien nf_ip_route(dev_net(skb_in->dev), &dst, &fl, false); 23189857Sobrien if (!dst) 23289857Sobrien return -1; 23338889Sjdp 23438889Sjdp skb_dst_set(skb_in, dst); 23538889Sjdp return 0; 23638889Sjdp} 23733965Sjdp 23833965Sjdp/* Send RST reply */ 23933965Sjdpvoid nf_send_reset(struct net *net, struct sock *sk, struct sk_buff *oldskb, 24033965Sjdp int hook) 24133965Sjdp{ 24233965Sjdp struct sk_buff *nskb; 24333965Sjdp struct iphdr *niph; 24433965Sjdp const struct tcphdr *oth; 24533965Sjdp struct tcphdr _oth; 24633965Sjdp 24733965Sjdp oth = nf_reject_ip_tcphdr_get(oldskb, &_oth, hook); 248218822Sdim if (!oth) 24933965Sjdp return; 25033965Sjdp 25160484Sobrien if ((hook == NF_INET_PRE_ROUTING || hook == NF_INET_INGRESS) && 25238889Sjdp nf_reject_fill_skb_dst(oldskb) < 0) 25338889Sjdp return; 25438889Sjdp 25538889Sjdp if (skb_rtable(oldskb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST)) 25638889Sjdp return; 25738889Sjdp 25838889Sjdp nskb = alloc_skb(sizeof(struct iphdr) + sizeof(struct tcphdr) + 25938889Sjdp LL_MAX_HEADER, GFP_ATOMIC); 26033965Sjdp if (!nskb) 26185815Sobrien return; 26233965Sjdp 26333965Sjdp /* ip_route_me_harder expects skb->dst to be set */ 26433965Sjdp skb_dst_set_noref(nskb, skb_dst(oldskb)); 26533965Sjdp 26660484Sobrien nskb->mark = IP4_REPLY_MARK(net, oldskb->mark); 26760484Sobrien 26860484Sobrien skb_reserve(nskb, LL_MAX_HEADER); 26960484Sobrien niph = nf_reject_iphdr_put(nskb, oldskb, IPPROTO_TCP, 27060484Sobrien ip4_dst_hoplimit(skb_dst(nskb))); 27160484Sobrien nf_reject_ip_tcphdr_put(nskb, oldskb, oth); 272218822Sdim if (ip_route_me_harder(net, sk, nskb, RTN_UNSPEC)) 273218822Sdim goto free_nskb; 27433965Sjdp 27533965Sjdp niph = ip_hdr(nskb); 27633965Sjdp 27733965Sjdp /* "Never happens" */ 27833965Sjdp if (nskb->len > dst_mtu(skb_dst(nskb))) 27933965Sjdp goto free_nskb; 28033965Sjdp 28133965Sjdp nf_ct_attach(nskb, oldskb); 28233965Sjdp nf_ct_set_closing(skb_nfct(oldskb)); 28333965Sjdp 28433965Sjdp#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) 28533965Sjdp /* If we use ip_local_out for bridged traffic, the MAC source on 28633965Sjdp * the RST will be ours, instead of the destination's. This confuses 28733965Sjdp * some routers/firewalls, and they drop the packet. So we need to 28833965Sjdp * build the eth header using the original destination's MAC as the 289218822Sdim * source, and send the RST packet directly. 29033965Sjdp */ 29133965Sjdp if (nf_bridge_info_exists(oldskb)) { 29260484Sobrien struct ethhdr *oeth = eth_hdr(oldskb); 29338889Sjdp struct net_device *br_indev; 29438889Sjdp 29538889Sjdp br_indev = nf_bridge_get_physindev(oldskb, net); 29638889Sjdp if (!br_indev) 29738889Sjdp goto free_nskb; 29838889Sjdp 29938889Sjdp nskb->dev = br_indev; 30033965Sjdp niph->tot_len = htons(nskb->len); 30185815Sobrien ip_send_check(niph); 30233965Sjdp if (dev_hard_header(nskb, nskb->dev, ntohs(nskb->protocol), 30333965Sjdp oeth->h_source, oeth->h_dest, nskb->len) < 0) 30433965Sjdp goto free_nskb; 30533965Sjdp dev_queue_xmit(nskb); 30660484Sobrien } else 30760484Sobrien#endif 30860484Sobrien ip_local_out(net, nskb->sk, nskb); 30960484Sobrien 31060484Sobrien return; 31160484Sobrien 312218822Sdim free_nskb: 313218822Sdim kfree_skb(nskb); 31433965Sjdp} 31533965SjdpEXPORT_SYMBOL_GPL(nf_send_reset); 31633965Sjdp 31733965Sjdpvoid nf_send_unreach(struct sk_buff *skb_in, int code, int hook) 318218822Sdim{ 319218822Sdim struct iphdr *iph = ip_hdr(skb_in); 320218822Sdim int dataoff = ip_hdrlen(skb_in); 321218822Sdim u8 proto = iph->protocol; 322218822Sdim 323218822Sdim if (iph->frag_off & htons(IP_OFFSET)) 324218822Sdim return; 325218822Sdim 326218822Sdim if ((hook == NF_INET_PRE_ROUTING || hook == NF_INET_INGRESS) && 327218822Sdim nf_reject_fill_skb_dst(skb_in) < 0) 328218822Sdim return; 329218822Sdim 330218822Sdim if (skb_csum_unnecessary(skb_in) || 331218822Sdim !nf_reject_verify_csum(skb_in, dataoff, proto)) { 33238889Sjdp icmp_send(skb_in, ICMP_DEST_UNREACH, code, 0); 33338889Sjdp return; 33485815Sobrien } 33538889Sjdp 33633965Sjdp if (nf_ip_checksum(skb_in, hook, dataoff, proto) == 0) 33733965Sjdp icmp_send(skb_in, ICMP_DEST_UNREACH, code, 0); 33833965Sjdp} 33933965SjdpEXPORT_SYMBOL_GPL(nf_send_unreach); 34033965Sjdp 34133965SjdpMODULE_LICENSE("GPL"); 34233965SjdpMODULE_DESCRIPTION("IPv4 packet rejection core"); 34333965Sjdp