From 3f6d08cf2019f2380a0eaf714a5e4a83aeaf953a Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Fri, 14 Jul 2000 07:45:08 +0000 Subject: Patches and isapplied script for reducing bug reports. --- patch-test3-pre2-sparc-ppc-align | 48 ++++++ patch-test3-pre6-reject-enhancements | 305 +++++++++++++++++++++++++++++++++++ 2 files changed, 353 insertions(+) create mode 100644 patch-test3-pre2-sparc-ppc-align create mode 100644 patch-test3-pre6-reject-enhancements diff --git a/patch-test3-pre2-sparc-ppc-align b/patch-test3-pre2-sparc-ppc-align new file mode 100644 index 00000000..83a1b220 --- /dev/null +++ b/patch-test3-pre2-sparc-ppc-align @@ -0,0 +1,48 @@ +diff -urN -X /tmp/file5l4Euc --minimal linux-2.4.0-test3-2/include/linux/netfilter_ipv4/ip_tables.h working-2.4.0-test3-2/include/linux/netfilter_ipv4/ip_tables.h +--- linux-2.4.0-test3-2/include/linux/netfilter_ipv4/ip_tables.h Thu Jul 6 13:26:32 2000 ++++ working-2.4.0-test3-2/include/linux/netfilter_ipv4/ip_tables.h Fri Jul 7 18:42:41 2000 +@@ -280,7 +280,7 @@ + unsigned int size; + + /* The entries. */ +- unsigned char entries[0]; ++ struct ipt_entry entrytable[0]; + }; + + /* Standard return verdict, or do jump. */ +diff -urN -X /tmp/file5l4Euc --minimal linux-2.4.0-test3-2/include/linux/netfilter_ipv6/ip6_tables.h working-2.4.0-test3-2/include/linux/netfilter_ipv6/ip6_tables.h +--- linux-2.4.0-test3-2/include/linux/netfilter_ipv6/ip6_tables.h Thu May 25 12:41:49 2000 ++++ working-2.4.0-test3-2/include/linux/netfilter_ipv6/ip6_tables.h Fri Jul 7 19:08:16 2000 +@@ -286,7 +286,7 @@ + unsigned int size; + + /* The entries. */ +- unsigned char entries[0]; ++ struct ip6t_entry entrytable[0]; + }; + + /* Standard return verdict, or do jump. */ +diff -urN -X /tmp/file5l4Euc --minimal linux-2.4.0-test3-2/net/ipv4/netfilter/ip_tables.c working-2.4.0-test3-2/net/ipv4/netfilter/ip_tables.c +--- linux-2.4.0-test3-2/net/ipv4/netfilter/ip_tables.c Thu Jun 29 01:26:09 2000 ++++ working-2.4.0-test3-2/net/ipv4/netfilter/ip_tables.c Fri Jul 7 18:43:40 2000 +@@ -1029,7 +1029,7 @@ + t->private->number); + if (entries->size == t->private->size) + ret = copy_entries_to_user(t->private->size, +- t, uptr->entries); ++ t, uptr->entrytable); + else { + duprintf("get_entries: I've got %u not %u!\n", + t->private->size, +diff -urN -X /tmp/file5l4Euc --minimal linux-2.4.0-test3-2/net/ipv6/netfilter/ip6_tables.c working-2.4.0-test3-2/net/ipv6/netfilter/ip6_tables.c +--- linux-2.4.0-test3-2/net/ipv6/netfilter/ip6_tables.c Thu Jun 29 01:26:11 2000 ++++ working-2.4.0-test3-2/net/ipv6/netfilter/ip6_tables.c Fri Jul 7 19:15:15 2000 +@@ -1075,7 +1075,7 @@ + t->private->number); + if (entries->size == t->private->size) + ret = copy_entries_to_user(t->private->size, +- t, uptr->entries); ++ t, uptr->entrytable); + else { + duprintf("get_entries: I've got %u not %u!\n", + t->private->size, diff --git a/patch-test3-pre6-reject-enhancements b/patch-test3-pre6-reject-enhancements new file mode 100644 index 00000000..a2c679ee --- /dev/null +++ b/patch-test3-pre6-reject-enhancements @@ -0,0 +1,305 @@ +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 +--- tmp/include/linux/netfilter_ipv4/ipt_REJECT.h Tue Mar 28 04:35:56 2000 ++++ working-2.4.0-test3-9/include/linux/netfilter_ipv4/ipt_REJECT.h Tue Jul 11 17:36:54 2000 +@@ -6,7 +6,10 @@ + IPT_ICMP_HOST_UNREACHABLE, + IPT_ICMP_PROT_UNREACHABLE, + IPT_ICMP_PORT_UNREACHABLE, +- IPT_ICMP_ECHOREPLY ++ IPT_ICMP_ECHOREPLY, ++ IPT_ICMP_NET_PROHIBITED, ++ IPT_ICMP_HOST_PROHIBITED, ++ IPT_TCP_RESET + }; + + struct ipt_reject_info { +diff -urN -X /tmp/fileVB9oIz --minimal tmp/net/core/netfilter.c working-2.4.0-test3-9/net/core/netfilter.c +--- tmp/net/core/netfilter.c Fri Apr 14 10:19:57 2000 ++++ working-2.4.0-test3-9/net/core/netfilter.c Wed Jul 12 12:18:42 2000 +@@ -261,11 +261,11 @@ + if (skb->nf_debug != ((1 << NF_IP_PRE_ROUTING) + | (1 << NF_IP_FORWARD) + | (1 << NF_IP_POST_ROUTING))) { +- /* Fragments will have no owners, but still +- may be local */ +- if (!(skb->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) +- || skb->nf_debug != ((1 << NF_IP_LOCAL_OUT) +- | (1 << NF_IP_POST_ROUTING))){ ++ /* Fragments, entunnelled packets, TCP RSTs ++ generated by ipt_REJECT will have no ++ owners, but still may be local */ ++ if (skb->nf_debug != ((1 << NF_IP_LOCAL_OUT) ++ | (1 << NF_IP_POST_ROUTING))){ + printk("ip_finish_output:" + " bad unowned skb = %p: ",skb); + debug_print_hooks_ip(skb->nf_debug); +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 +--- tmp/net/ipv4/netfilter/ip_conntrack_core.c Tue Jul 11 12:08:17 2000 ++++ working-2.4.0-test3-9/net/ipv4/netfilter/ip_conntrack_core.c Tue Jul 11 17:12:08 2000 +@@ -551,6 +551,7 @@ + resolve_normal_ct(struct sk_buff *skb, + struct ip_conntrack_protocol *proto, + int *set_reply, ++ unsigned int hooknum, + enum ip_conntrack_info *ctinfo) + { + struct ip_conntrack_tuple tuple; +@@ -573,6 +574,21 @@ + if (DIRECTION(h) == IP_CT_DIR_REPLY) { + /* Reply on unconfirmed connection => unclassifiable */ + if (!(h->ctrack->status & IPS_CONFIRMED)) { ++ /* Exception: local TCP RSTs (generated by ++ REJECT target). */ ++ if (hooknum == NF_IP_LOCAL_OUT ++ && h->tuple.dst.protonum == IPPROTO_TCP) { ++ const struct tcphdr *tcph ++ = (const struct tcphdr *) ++ ((u_int32_t *)skb->nh.iph ++ + skb->nh.iph->ihl); ++ if (tcph->rst) { ++ *ctinfo = IP_CT_ESTABLISHED ++ + IP_CT_IS_REPLY; ++ *set_reply = 0; ++ goto set_skb; ++ } ++ } + DEBUGP("Reply on unconfirmed connection\n"); + ip_conntrack_put(h->ctrack); + return NULL; +@@ -598,6 +614,7 @@ + } + *set_reply = 0; + } ++ set_skb: + skb->nfct = &h->ctrack->infos[*ctinfo]; + return h->ctrack; + } +@@ -669,7 +686,7 @@ + && icmp_error_track(*pskb, &ctinfo, hooknum)) + return NF_ACCEPT; + +- if (!(ct = resolve_normal_ct(*pskb, proto, &set_reply, &ctinfo))) ++ if (!(ct = resolve_normal_ct(*pskb, proto,&set_reply,hooknum,&ctinfo))) + /* Not valid part of a connection */ + return NF_ACCEPT; + +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 +--- tmp/net/ipv4/netfilter/ip_conntrack_standalone.c Fri Apr 28 08:43:15 2000 ++++ working-2.4.0-test3-9/net/ipv4/netfilter/ip_conntrack_standalone.c Tue Jul 11 17:12:08 2000 +@@ -169,11 +169,15 @@ + const struct net_device *out, + int (*okfn)(struct sk_buff *)) + { +- /* We've seen it coming out the other side: confirm */ ++ /* We've seen it coming out the other side: confirm (only if ++ new packet: REJECT can generate TCP RESET response, or ICMP ++ errors) */ + if ((*pskb)->nfct) { + struct ip_conntrack *ct + = (struct ip_conntrack *)(*pskb)->nfct->master; +- if (!(ct->status & IPS_CONFIRMED)) ++ /* ctinfo is the index of the nfct inside the conntrack */ ++ if ((*pskb)->nfct - ct->infos == IP_CT_NEW ++ && !(ct->status & IPS_CONFIRMED)) + ip_conntrack_confirm(ct); + } + return NF_ACCEPT; +@@ -191,7 +195,8 @@ + if ((*pskb)->nfct) { + struct ip_conntrack *ct + = (struct ip_conntrack *)(*pskb)->nfct->master; +- if (!(ct->status & IPS_CONFIRMED)) ++ if ((*pskb)->nfct - ct->infos == IP_CT_NEW ++ && !(ct->status & IPS_CONFIRMED)) + ip_conntrack_confirm(ct); + } + +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 +--- tmp/net/ipv4/netfilter/ip_fw_compat.c Tue Jul 11 12:08:17 2000 ++++ working-2.4.0-test3-9/net/ipv4/netfilter/ip_fw_compat.c Tue Jul 11 17:12:08 2000 +@@ -71,7 +71,8 @@ + struct ip_conntrack *ct + = (struct ip_conntrack *)skb->nfct->master; + +- if (!(ct->status & IPS_CONFIRMED)) ++ if (skb->nfct - ct->infos == IP_CT_NEW ++ && !(ct->status & IPS_CONFIRMED)) + ip_conntrack_confirm(ct); + } + } +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 +--- tmp/net/ipv4/netfilter/ipt_REJECT.c Tue Jun 27 14:52:47 2000 ++++ working-2.4.0-test3-9/net/ipv4/netfilter/ipt_REJECT.c Wed Jul 12 17:46:26 2000 +@@ -7,6 +7,7 @@ + #include + #include + #include ++#include + struct in_device; + #include + #include +@@ -18,6 +19,113 @@ + #define DEBUGP(format, args...) + #endif + ++/* Send RST reply */ ++static void send_reset(struct sk_buff *oldskb) ++{ ++ struct sk_buff *nskb; ++ struct tcphdr *tcph; ++ struct rtable *rt; ++ unsigned int tcplen; ++ int needs_ack; ++ ++ /* Clone skb (skb is about to be dropped, so we don't care) */ ++ nskb = skb_clone(oldskb, GFP_ATOMIC); ++ if (!nskb) ++ return; ++ ++ /* This packet will not be the same as the other: clear nf fields */ ++ nf_conntrack_put(nskb->nfct); ++ nskb->nfct = NULL; ++ nskb->nfcache = 0; ++#ifdef CONFIG_NETFILTER_DEBUG ++ nskb->nf_debug = 0; ++#endif ++ ++ /* IP header checks: fragment, too short. */ ++ if (nskb->nh.iph->frag_off & htons(IP_OFFSET) ++ || nskb->len < (nskb->nh.iph->ihl<<2) + sizeof(struct tcphdr)) ++ goto free_nskb; ++ ++ tcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl); ++ tcplen = nskb->len - nskb->nh.iph->ihl*4; ++ ++ /* Check checksum. */ ++ if (tcp_v4_check(tcph, tcplen, nskb->nh.iph->saddr, ++ nskb->nh.iph->daddr, ++ csum_partial((char *)tcph, tcplen, 0)) != 0) ++ goto free_nskb; ++ ++ /* No RST for RST. */ ++ if (tcph->rst) ++ goto free_nskb; ++ ++ nskb->nh.iph->daddr = xchg(&nskb->nh.iph->saddr, nskb->nh.iph->daddr); ++ tcph->source = xchg(&tcph->dest, tcph->source); ++ ++ /* Truncate to length (no data) */ ++ tcph->doff = sizeof(struct tcphdr)/4; ++ skb_trim(nskb, nskb->nh.iph->ihl*4 + sizeof(struct tcphdr)); ++ ++ if (tcph->ack) { ++ needs_ack = 0; ++ tcph->seq = tcph->ack_seq; ++ tcph->ack_seq = 0; ++ } else { ++ needs_ack = 1; ++ tcph->seq = 0; ++ tcph->ack_seq = htonl(ntohl(tcph->seq) + tcph->syn + tcph->fin ++ + tcplen - (tcph->doff<<2)); ++ } ++ ++ /* Reset flags */ ++ ((u_int8_t *)tcph)[13] = 0; ++ tcph->rst = 1; ++ if (needs_ack) ++ tcph->ack = 1; ++ ++ tcph->window = 0; ++ tcph->urg_ptr = 0; ++ ++ /* Adjust TCP checksum */ ++ tcph->check = 0; ++ tcph->check = tcp_v4_check(tcph, sizeof(struct tcphdr), ++ nskb->nh.iph->saddr, ++ nskb->nh.iph->daddr, ++ csum_partial((char *)tcph, ++ sizeof(struct tcphdr), 0)); ++ ++ /* Adjust IP TTL, DF */ ++ nskb->nh.iph->ttl = MAXTTL; ++ /* Set DF, id = 0 */ ++ nskb->nh.iph->frag_off = htons(IP_DF); ++ nskb->nh.iph->id = 0; ++ ++ /* Adjust IP checksum */ ++ nskb->nh.iph->check = 0; ++ nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph, ++ nskb->nh.iph->ihl); ++ ++ /* Routing */ ++ if (ip_route_output(&rt, nskb->nh.iph->daddr, nskb->nh.iph->saddr, ++ RT_TOS(nskb->nh.iph->tos) | RTO_CONN, ++ 0) != 0) ++ goto free_nskb; ++ ++ dst_release(nskb->dst); ++ nskb->dst = &rt->u.dst; ++ ++ /* "Never happens" */ ++ if (nskb->len > nskb->dst->pmtu) ++ goto free_nskb; ++ ++ NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev, ++ ip_finish_output); ++ return; ++ ++ free_nskb: ++ kfree_skb(nskb); ++} ++ + static unsigned int reject(struct sk_buff **pskb, + unsigned int hooknum, + const struct net_device *in, +@@ -43,6 +151,12 @@ + case IPT_ICMP_PORT_UNREACHABLE: + icmp_send(*pskb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); + break; ++ case IPT_ICMP_NET_PROHIBITED: ++ icmp_send(*pskb, ICMP_DEST_UNREACH, ICMP_NET_ANO, 0); ++ break; ++ case IPT_ICMP_HOST_PROHIBITED: ++ icmp_send(*pskb, ICMP_DEST_UNREACH, ICMP_HOST_ANO, 0); ++ break; + case IPT_ICMP_ECHOREPLY: { + struct icmphdr *icmph = (struct icmphdr *) + ((u_int32_t *)(*pskb)->nh.iph + (*pskb)->nh.iph->ihl); +@@ -64,6 +178,9 @@ + } + } + break; ++ case IPT_TCP_RESET: ++ send_reset(*pskb); ++ break; + } + + return NF_DROP; +@@ -96,7 +213,7 @@ + + /* Only allow these for packet filtering. */ + if (strcmp(tablename, "filter") != 0) { +- DEBUGP("REJECT: bad table `%s'.\n", table); ++ DEBUGP("REJECT: bad table `%s'.\n", tablename); + return 0; + } + if ((hook_mask & ~((1 << NF_IP_LOCAL_IN) +@@ -116,6 +233,18 @@ + /* Must contain ICMP match. */ + if (IPT_MATCH_ITERATE(e, find_ping_match) == 0) { + DEBUGP("REJECT: ECHOREPLY illegal for non-ping\n"); ++ return 0; ++ } ++ } else if (rejinfo->with == IPT_TCP_RESET) { ++ /* Must specify that it's a TCP packet */ ++ if (e->ip.proto != IPPROTO_TCP ++ || (e->ip.invflags & IPT_INV_PROTO)) { ++ DEBUGP("REJECT: TCP_RESET illegal for non-tcp\n"); ++ return 0; ++ } ++ /* Only for local input. Rest is too dangerous. */ ++ if ((hook_mask & ~(1 << NF_IP_LOCAL_IN)) != 0) { ++ DEBUGP("REJECT: TCP_RESET only from INPUT\n"); + return 0; + } + } -- cgit v1.2.3