Rusty Russell | 3f6d08c | 2000-07-14 07:45:08 +0000 | [diff] [blame] | 1 | diff -urN -X /tmp/fileVB9oIz --minimal tmp/include/linux/netfilter_ipv4/ipt_REJECT.h working-2.4.0-test3-9/include/linux/netfilter_ipv4/ipt_REJECT.h |
| 2 | --- tmp/include/linux/netfilter_ipv4/ipt_REJECT.h Tue Mar 28 04:35:56 2000 |
| 3 | +++ working-2.4.0-test3-9/include/linux/netfilter_ipv4/ipt_REJECT.h Tue Jul 11 17:36:54 2000 |
| 4 | @@ -6,7 +6,10 @@ |
| 5 | IPT_ICMP_HOST_UNREACHABLE, |
| 6 | IPT_ICMP_PROT_UNREACHABLE, |
| 7 | IPT_ICMP_PORT_UNREACHABLE, |
| 8 | - IPT_ICMP_ECHOREPLY |
| 9 | + IPT_ICMP_ECHOREPLY, |
| 10 | + IPT_ICMP_NET_PROHIBITED, |
| 11 | + IPT_ICMP_HOST_PROHIBITED, |
| 12 | + IPT_TCP_RESET |
| 13 | }; |
| 14 | |
| 15 | struct ipt_reject_info { |
| 16 | diff -urN -X /tmp/fileVB9oIz --minimal tmp/net/core/netfilter.c working-2.4.0-test3-9/net/core/netfilter.c |
| 17 | --- tmp/net/core/netfilter.c Fri Apr 14 10:19:57 2000 |
| 18 | +++ working-2.4.0-test3-9/net/core/netfilter.c Wed Jul 12 12:18:42 2000 |
| 19 | @@ -261,11 +261,11 @@ |
| 20 | if (skb->nf_debug != ((1 << NF_IP_PRE_ROUTING) |
| 21 | | (1 << NF_IP_FORWARD) |
| 22 | | (1 << NF_IP_POST_ROUTING))) { |
| 23 | - /* Fragments will have no owners, but still |
| 24 | - may be local */ |
| 25 | - if (!(skb->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) |
| 26 | - || skb->nf_debug != ((1 << NF_IP_LOCAL_OUT) |
| 27 | - | (1 << NF_IP_POST_ROUTING))){ |
| 28 | + /* Fragments, entunnelled packets, TCP RSTs |
| 29 | + generated by ipt_REJECT will have no |
| 30 | + owners, but still may be local */ |
| 31 | + if (skb->nf_debug != ((1 << NF_IP_LOCAL_OUT) |
| 32 | + | (1 << NF_IP_POST_ROUTING))){ |
| 33 | printk("ip_finish_output:" |
| 34 | " bad unowned skb = %p: ",skb); |
| 35 | debug_print_hooks_ip(skb->nf_debug); |
| 36 | diff -urN -X /tmp/fileVB9oIz --minimal tmp/net/ipv4/netfilter/ip_conntrack_core.c working-2.4.0-test3-9/net/ipv4/netfilter/ip_conntrack_core.c |
| 37 | --- tmp/net/ipv4/netfilter/ip_conntrack_core.c Tue Jul 11 12:08:17 2000 |
| 38 | +++ working-2.4.0-test3-9/net/ipv4/netfilter/ip_conntrack_core.c Tue Jul 11 17:12:08 2000 |
| 39 | @@ -551,6 +551,7 @@ |
| 40 | resolve_normal_ct(struct sk_buff *skb, |
| 41 | struct ip_conntrack_protocol *proto, |
| 42 | int *set_reply, |
| 43 | + unsigned int hooknum, |
| 44 | enum ip_conntrack_info *ctinfo) |
| 45 | { |
| 46 | struct ip_conntrack_tuple tuple; |
| 47 | @@ -573,6 +574,21 @@ |
| 48 | if (DIRECTION(h) == IP_CT_DIR_REPLY) { |
| 49 | /* Reply on unconfirmed connection => unclassifiable */ |
| 50 | if (!(h->ctrack->status & IPS_CONFIRMED)) { |
| 51 | + /* Exception: local TCP RSTs (generated by |
| 52 | + REJECT target). */ |
| 53 | + if (hooknum == NF_IP_LOCAL_OUT |
| 54 | + && h->tuple.dst.protonum == IPPROTO_TCP) { |
| 55 | + const struct tcphdr *tcph |
| 56 | + = (const struct tcphdr *) |
| 57 | + ((u_int32_t *)skb->nh.iph |
| 58 | + + skb->nh.iph->ihl); |
| 59 | + if (tcph->rst) { |
| 60 | + *ctinfo = IP_CT_ESTABLISHED |
| 61 | + + IP_CT_IS_REPLY; |
| 62 | + *set_reply = 0; |
| 63 | + goto set_skb; |
| 64 | + } |
| 65 | + } |
| 66 | DEBUGP("Reply on unconfirmed connection\n"); |
| 67 | ip_conntrack_put(h->ctrack); |
| 68 | return NULL; |
| 69 | @@ -598,6 +614,7 @@ |
| 70 | } |
| 71 | *set_reply = 0; |
| 72 | } |
| 73 | + set_skb: |
| 74 | skb->nfct = &h->ctrack->infos[*ctinfo]; |
| 75 | return h->ctrack; |
| 76 | } |
| 77 | @@ -669,7 +686,7 @@ |
| 78 | && icmp_error_track(*pskb, &ctinfo, hooknum)) |
| 79 | return NF_ACCEPT; |
| 80 | |
| 81 | - if (!(ct = resolve_normal_ct(*pskb, proto, &set_reply, &ctinfo))) |
| 82 | + if (!(ct = resolve_normal_ct(*pskb, proto,&set_reply,hooknum,&ctinfo))) |
| 83 | /* Not valid part of a connection */ |
| 84 | return NF_ACCEPT; |
| 85 | |
| 86 | diff -urN -X /tmp/fileVB9oIz --minimal tmp/net/ipv4/netfilter/ip_conntrack_standalone.c working-2.4.0-test3-9/net/ipv4/netfilter/ip_conntrack_standalone.c |
| 87 | --- tmp/net/ipv4/netfilter/ip_conntrack_standalone.c Fri Apr 28 08:43:15 2000 |
| 88 | +++ working-2.4.0-test3-9/net/ipv4/netfilter/ip_conntrack_standalone.c Tue Jul 11 17:12:08 2000 |
| 89 | @@ -169,11 +169,15 @@ |
| 90 | const struct net_device *out, |
| 91 | int (*okfn)(struct sk_buff *)) |
| 92 | { |
| 93 | - /* We've seen it coming out the other side: confirm */ |
| 94 | + /* We've seen it coming out the other side: confirm (only if |
| 95 | + new packet: REJECT can generate TCP RESET response, or ICMP |
| 96 | + errors) */ |
| 97 | if ((*pskb)->nfct) { |
| 98 | struct ip_conntrack *ct |
| 99 | = (struct ip_conntrack *)(*pskb)->nfct->master; |
| 100 | - if (!(ct->status & IPS_CONFIRMED)) |
| 101 | + /* ctinfo is the index of the nfct inside the conntrack */ |
| 102 | + if ((*pskb)->nfct - ct->infos == IP_CT_NEW |
| 103 | + && !(ct->status & IPS_CONFIRMED)) |
| 104 | ip_conntrack_confirm(ct); |
| 105 | } |
| 106 | return NF_ACCEPT; |
| 107 | @@ -191,7 +195,8 @@ |
| 108 | if ((*pskb)->nfct) { |
| 109 | struct ip_conntrack *ct |
| 110 | = (struct ip_conntrack *)(*pskb)->nfct->master; |
| 111 | - if (!(ct->status & IPS_CONFIRMED)) |
| 112 | + if ((*pskb)->nfct - ct->infos == IP_CT_NEW |
| 113 | + && !(ct->status & IPS_CONFIRMED)) |
| 114 | ip_conntrack_confirm(ct); |
| 115 | } |
| 116 | |
| 117 | diff -urN -X /tmp/fileVB9oIz --minimal tmp/net/ipv4/netfilter/ip_fw_compat.c working-2.4.0-test3-9/net/ipv4/netfilter/ip_fw_compat.c |
| 118 | --- tmp/net/ipv4/netfilter/ip_fw_compat.c Tue Jul 11 12:08:17 2000 |
| 119 | +++ working-2.4.0-test3-9/net/ipv4/netfilter/ip_fw_compat.c Tue Jul 11 17:12:08 2000 |
| 120 | @@ -71,7 +71,8 @@ |
| 121 | struct ip_conntrack *ct |
| 122 | = (struct ip_conntrack *)skb->nfct->master; |
| 123 | |
| 124 | - if (!(ct->status & IPS_CONFIRMED)) |
| 125 | + if (skb->nfct - ct->infos == IP_CT_NEW |
| 126 | + && !(ct->status & IPS_CONFIRMED)) |
| 127 | ip_conntrack_confirm(ct); |
| 128 | } |
| 129 | } |
| 130 | diff -urN -X /tmp/fileVB9oIz --minimal tmp/net/ipv4/netfilter/ipt_REJECT.c working-2.4.0-test3-9/net/ipv4/netfilter/ipt_REJECT.c |
| 131 | --- tmp/net/ipv4/netfilter/ipt_REJECT.c Tue Jun 27 14:52:47 2000 |
| 132 | +++ working-2.4.0-test3-9/net/ipv4/netfilter/ipt_REJECT.c Wed Jul 12 17:46:26 2000 |
| 133 | @@ -7,6 +7,7 @@ |
| 134 | #include <linux/ip.h> |
| 135 | #include <net/icmp.h> |
| 136 | #include <net/ip.h> |
| 137 | +#include <net/tcp.h> |
| 138 | struct in_device; |
| 139 | #include <net/route.h> |
| 140 | #include <linux/netfilter_ipv4/ip_tables.h> |
| 141 | @@ -18,6 +19,113 @@ |
| 142 | #define DEBUGP(format, args...) |
| 143 | #endif |
| 144 | |
| 145 | +/* Send RST reply */ |
| 146 | +static void send_reset(struct sk_buff *oldskb) |
| 147 | +{ |
| 148 | + struct sk_buff *nskb; |
| 149 | + struct tcphdr *tcph; |
| 150 | + struct rtable *rt; |
| 151 | + unsigned int tcplen; |
| 152 | + int needs_ack; |
| 153 | + |
| 154 | + /* Clone skb (skb is about to be dropped, so we don't care) */ |
| 155 | + nskb = skb_clone(oldskb, GFP_ATOMIC); |
| 156 | + if (!nskb) |
| 157 | + return; |
| 158 | + |
| 159 | + /* This packet will not be the same as the other: clear nf fields */ |
| 160 | + nf_conntrack_put(nskb->nfct); |
| 161 | + nskb->nfct = NULL; |
| 162 | + nskb->nfcache = 0; |
| 163 | +#ifdef CONFIG_NETFILTER_DEBUG |
| 164 | + nskb->nf_debug = 0; |
| 165 | +#endif |
| 166 | + |
| 167 | + /* IP header checks: fragment, too short. */ |
| 168 | + if (nskb->nh.iph->frag_off & htons(IP_OFFSET) |
| 169 | + || nskb->len < (nskb->nh.iph->ihl<<2) + sizeof(struct tcphdr)) |
| 170 | + goto free_nskb; |
| 171 | + |
| 172 | + tcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl); |
| 173 | + tcplen = nskb->len - nskb->nh.iph->ihl*4; |
| 174 | + |
| 175 | + /* Check checksum. */ |
| 176 | + if (tcp_v4_check(tcph, tcplen, nskb->nh.iph->saddr, |
| 177 | + nskb->nh.iph->daddr, |
| 178 | + csum_partial((char *)tcph, tcplen, 0)) != 0) |
| 179 | + goto free_nskb; |
| 180 | + |
| 181 | + /* No RST for RST. */ |
| 182 | + if (tcph->rst) |
| 183 | + goto free_nskb; |
| 184 | + |
| 185 | + nskb->nh.iph->daddr = xchg(&nskb->nh.iph->saddr, nskb->nh.iph->daddr); |
| 186 | + tcph->source = xchg(&tcph->dest, tcph->source); |
| 187 | + |
| 188 | + /* Truncate to length (no data) */ |
| 189 | + tcph->doff = sizeof(struct tcphdr)/4; |
| 190 | + skb_trim(nskb, nskb->nh.iph->ihl*4 + sizeof(struct tcphdr)); |
| 191 | + |
| 192 | + if (tcph->ack) { |
| 193 | + needs_ack = 0; |
| 194 | + tcph->seq = tcph->ack_seq; |
| 195 | + tcph->ack_seq = 0; |
| 196 | + } else { |
| 197 | + needs_ack = 1; |
| 198 | + tcph->seq = 0; |
| 199 | + tcph->ack_seq = htonl(ntohl(tcph->seq) + tcph->syn + tcph->fin |
| 200 | + + tcplen - (tcph->doff<<2)); |
| 201 | + } |
| 202 | + |
| 203 | + /* Reset flags */ |
| 204 | + ((u_int8_t *)tcph)[13] = 0; |
| 205 | + tcph->rst = 1; |
| 206 | + if (needs_ack) |
| 207 | + tcph->ack = 1; |
| 208 | + |
| 209 | + tcph->window = 0; |
| 210 | + tcph->urg_ptr = 0; |
| 211 | + |
| 212 | + /* Adjust TCP checksum */ |
| 213 | + tcph->check = 0; |
| 214 | + tcph->check = tcp_v4_check(tcph, sizeof(struct tcphdr), |
| 215 | + nskb->nh.iph->saddr, |
| 216 | + nskb->nh.iph->daddr, |
| 217 | + csum_partial((char *)tcph, |
| 218 | + sizeof(struct tcphdr), 0)); |
| 219 | + |
| 220 | + /* Adjust IP TTL, DF */ |
| 221 | + nskb->nh.iph->ttl = MAXTTL; |
| 222 | + /* Set DF, id = 0 */ |
| 223 | + nskb->nh.iph->frag_off = htons(IP_DF); |
| 224 | + nskb->nh.iph->id = 0; |
| 225 | + |
| 226 | + /* Adjust IP checksum */ |
| 227 | + nskb->nh.iph->check = 0; |
| 228 | + nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph, |
| 229 | + nskb->nh.iph->ihl); |
| 230 | + |
| 231 | + /* Routing */ |
| 232 | + if (ip_route_output(&rt, nskb->nh.iph->daddr, nskb->nh.iph->saddr, |
| 233 | + RT_TOS(nskb->nh.iph->tos) | RTO_CONN, |
| 234 | + 0) != 0) |
| 235 | + goto free_nskb; |
| 236 | + |
| 237 | + dst_release(nskb->dst); |
| 238 | + nskb->dst = &rt->u.dst; |
| 239 | + |
| 240 | + /* "Never happens" */ |
| 241 | + if (nskb->len > nskb->dst->pmtu) |
| 242 | + goto free_nskb; |
| 243 | + |
| 244 | + NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev, |
| 245 | + ip_finish_output); |
| 246 | + return; |
| 247 | + |
| 248 | + free_nskb: |
| 249 | + kfree_skb(nskb); |
| 250 | +} |
| 251 | + |
| 252 | static unsigned int reject(struct sk_buff **pskb, |
| 253 | unsigned int hooknum, |
| 254 | const struct net_device *in, |
| 255 | @@ -43,6 +151,12 @@ |
| 256 | case IPT_ICMP_PORT_UNREACHABLE: |
| 257 | icmp_send(*pskb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); |
| 258 | break; |
| 259 | + case IPT_ICMP_NET_PROHIBITED: |
| 260 | + icmp_send(*pskb, ICMP_DEST_UNREACH, ICMP_NET_ANO, 0); |
| 261 | + break; |
| 262 | + case IPT_ICMP_HOST_PROHIBITED: |
| 263 | + icmp_send(*pskb, ICMP_DEST_UNREACH, ICMP_HOST_ANO, 0); |
| 264 | + break; |
| 265 | case IPT_ICMP_ECHOREPLY: { |
| 266 | struct icmphdr *icmph = (struct icmphdr *) |
| 267 | ((u_int32_t *)(*pskb)->nh.iph + (*pskb)->nh.iph->ihl); |
| 268 | @@ -64,6 +178,9 @@ |
| 269 | } |
| 270 | } |
| 271 | break; |
| 272 | + case IPT_TCP_RESET: |
| 273 | + send_reset(*pskb); |
| 274 | + break; |
| 275 | } |
| 276 | |
| 277 | return NF_DROP; |
| 278 | @@ -96,7 +213,7 @@ |
| 279 | |
| 280 | /* Only allow these for packet filtering. */ |
| 281 | if (strcmp(tablename, "filter") != 0) { |
| 282 | - DEBUGP("REJECT: bad table `%s'.\n", table); |
| 283 | + DEBUGP("REJECT: bad table `%s'.\n", tablename); |
| 284 | return 0; |
| 285 | } |
| 286 | if ((hook_mask & ~((1 << NF_IP_LOCAL_IN) |
| 287 | @@ -116,6 +233,18 @@ |
| 288 | /* Must contain ICMP match. */ |
| 289 | if (IPT_MATCH_ITERATE(e, find_ping_match) == 0) { |
| 290 | DEBUGP("REJECT: ECHOREPLY illegal for non-ping\n"); |
| 291 | + return 0; |
| 292 | + } |
| 293 | + } else if (rejinfo->with == IPT_TCP_RESET) { |
| 294 | + /* Must specify that it's a TCP packet */ |
| 295 | + if (e->ip.proto != IPPROTO_TCP |
| 296 | + || (e->ip.invflags & IPT_INV_PROTO)) { |
| 297 | + DEBUGP("REJECT: TCP_RESET illegal for non-tcp\n"); |
| 298 | + return 0; |
| 299 | + } |
| 300 | + /* Only for local input. Rest is too dangerous. */ |
| 301 | + if ((hook_mask & ~(1 << NF_IP_LOCAL_IN)) != 0) { |
| 302 | + DEBUGP("REJECT: TCP_RESET only from INPUT\n"); |
| 303 | return 0; |
| 304 | } |
| 305 | } |