Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netfilter: kill nf_send_reset6() from include/net/netfilter/ipv6/nf_reject.h

nf_send_reset6() now resides in net/ipv6/netfilter/nf_reject_ipv6.c

Fixes: c8d7b98 ("netfilter: move nf_send_resetX() code to nf_reject_ipvX modules")
Reported-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Acked-by: Eric Dumazet <edumazet@google.com>

+2 -155
+2 -155
include/net/netfilter/ipv6/nf_reject.h
··· 1 1 #ifndef _IPV6_NF_REJECT_H 2 2 #define _IPV6_NF_REJECT_H 3 3 4 - #include <net/ipv6.h> 5 - #include <net/ip6_route.h> 6 - #include <net/ip6_fib.h> 7 - #include <net/ip6_checksum.h> 8 - #include <linux/netfilter_ipv6.h> 4 + #include <linux/icmpv6.h> 9 5 10 6 static inline void 11 7 nf_send_unreach6(struct net *net, struct sk_buff *skb_in, unsigned char code, ··· 13 17 icmpv6_send(skb_in, ICMPV6_DEST_UNREACH, code, 0); 14 18 } 15 19 16 - /* Send RST reply */ 17 - static void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook) 18 - { 19 - struct sk_buff *nskb; 20 - struct tcphdr otcph, *tcph; 21 - unsigned int otcplen, hh_len; 22 - int tcphoff, needs_ack; 23 - const struct ipv6hdr *oip6h = ipv6_hdr(oldskb); 24 - struct ipv6hdr *ip6h; 25 - #define DEFAULT_TOS_VALUE 0x0U 26 - const __u8 tclass = DEFAULT_TOS_VALUE; 27 - struct dst_entry *dst = NULL; 28 - u8 proto; 29 - __be16 frag_off; 30 - struct flowi6 fl6; 31 - 32 - if ((!(ipv6_addr_type(&oip6h->saddr) & IPV6_ADDR_UNICAST)) || 33 - (!(ipv6_addr_type(&oip6h->daddr) & IPV6_ADDR_UNICAST))) { 34 - pr_debug("addr is not unicast.\n"); 35 - return; 36 - } 37 - 38 - proto = oip6h->nexthdr; 39 - tcphoff = ipv6_skip_exthdr(oldskb, ((u8*)(oip6h+1) - oldskb->data), &proto, &frag_off); 40 - 41 - if ((tcphoff < 0) || (tcphoff > oldskb->len)) { 42 - pr_debug("Cannot get TCP header.\n"); 43 - return; 44 - } 45 - 46 - otcplen = oldskb->len - tcphoff; 47 - 48 - /* IP header checks: fragment, too short. */ 49 - if (proto != IPPROTO_TCP || otcplen < sizeof(struct tcphdr)) { 50 - pr_debug("proto(%d) != IPPROTO_TCP, " 51 - "or too short. otcplen = %d\n", 52 - proto, otcplen); 53 - return; 54 - } 55 - 56 - if (skb_copy_bits(oldskb, tcphoff, &otcph, sizeof(struct tcphdr))) 57 - BUG(); 58 - 59 - /* No RST for RST. */ 60 - if (otcph.rst) { 61 - pr_debug("RST is set\n"); 62 - return; 63 - } 64 - 65 - /* Check checksum. */ 66 - if (nf_ip6_checksum(oldskb, hook, tcphoff, IPPROTO_TCP)) { 67 - pr_debug("TCP checksum is invalid\n"); 68 - return; 69 - } 70 - 71 - memset(&fl6, 0, sizeof(fl6)); 72 - fl6.flowi6_proto = IPPROTO_TCP; 73 - fl6.saddr = oip6h->daddr; 74 - fl6.daddr = oip6h->saddr; 75 - fl6.fl6_sport = otcph.dest; 76 - fl6.fl6_dport = otcph.source; 77 - security_skb_classify_flow(oldskb, flowi6_to_flowi(&fl6)); 78 - dst = ip6_route_output(net, NULL, &fl6); 79 - if (dst == NULL || dst->error) { 80 - dst_release(dst); 81 - return; 82 - } 83 - dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), NULL, 0); 84 - if (IS_ERR(dst)) 85 - return; 86 - 87 - hh_len = (dst->dev->hard_header_len + 15)&~15; 88 - nskb = alloc_skb(hh_len + 15 + dst->header_len + sizeof(struct ipv6hdr) 89 - + sizeof(struct tcphdr) + dst->trailer_len, 90 - GFP_ATOMIC); 91 - 92 - if (!nskb) { 93 - net_dbg_ratelimited("cannot alloc skb\n"); 94 - dst_release(dst); 95 - return; 96 - } 97 - 98 - skb_dst_set(nskb, dst); 99 - 100 - skb_reserve(nskb, hh_len + dst->header_len); 101 - 102 - skb_put(nskb, sizeof(struct ipv6hdr)); 103 - skb_reset_network_header(nskb); 104 - ip6h = ipv6_hdr(nskb); 105 - ip6_flow_hdr(ip6h, tclass, 0); 106 - ip6h->hop_limit = ip6_dst_hoplimit(dst); 107 - ip6h->nexthdr = IPPROTO_TCP; 108 - ip6h->saddr = oip6h->daddr; 109 - ip6h->daddr = oip6h->saddr; 110 - 111 - skb_reset_transport_header(nskb); 112 - tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr)); 113 - /* Truncate to length (no data) */ 114 - tcph->doff = sizeof(struct tcphdr)/4; 115 - tcph->source = otcph.dest; 116 - tcph->dest = otcph.source; 117 - 118 - if (otcph.ack) { 119 - needs_ack = 0; 120 - tcph->seq = otcph.ack_seq; 121 - tcph->ack_seq = 0; 122 - } else { 123 - needs_ack = 1; 124 - tcph->ack_seq = htonl(ntohl(otcph.seq) + otcph.syn + otcph.fin 125 - + otcplen - (otcph.doff<<2)); 126 - tcph->seq = 0; 127 - } 128 - 129 - /* Reset flags */ 130 - ((u_int8_t *)tcph)[13] = 0; 131 - tcph->rst = 1; 132 - tcph->ack = needs_ack; 133 - tcph->window = 0; 134 - tcph->urg_ptr = 0; 135 - tcph->check = 0; 136 - 137 - /* Adjust TCP checksum */ 138 - tcph->check = csum_ipv6_magic(&ipv6_hdr(nskb)->saddr, 139 - &ipv6_hdr(nskb)->daddr, 140 - sizeof(struct tcphdr), IPPROTO_TCP, 141 - csum_partial(tcph, 142 - sizeof(struct tcphdr), 0)); 143 - 144 - nf_ct_attach(nskb, oldskb); 145 - 146 - #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) 147 - /* If we use ip6_local_out for bridged traffic, the MAC source on 148 - * the RST will be ours, instead of the destination's. This confuses 149 - * some routers/firewalls, and they drop the packet. So we need to 150 - * build the eth header using the original destination's MAC as the 151 - * source, and send the RST packet directly. 152 - */ 153 - if (oldskb->nf_bridge) { 154 - struct ethhdr *oeth = eth_hdr(oldskb); 155 - nskb->dev = oldskb->nf_bridge->physindev; 156 - nskb->protocol = htons(ETH_P_IPV6); 157 - ip6h->payload_len = htons(sizeof(struct tcphdr)); 158 - if (dev_hard_header(nskb, nskb->dev, ntohs(nskb->protocol), 159 - oeth->h_source, oeth->h_dest, nskb->len) < 0) 160 - return; 161 - dev_queue_xmit(nskb); 162 - } else 163 - #endif 164 - ip6_local_out(nskb); 165 - } 20 + void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook); 166 21 167 22 #endif /* _IPV6_NF_REJECT_H */