diff -urN linux-2.4.21-bk-1.1141/include/linux/netfilter.h linux-2.4.21-bk1141-pom-20030429-pending/include/linux/netfilter.h --- linux-2.4.21-bk-1.1141/include/linux/netfilter.h Sun Apr 27 12:57:46 2003 +++ linux-2.4.21-bk1141-pom-20030429-pending/include/linux/netfilter.h Wed Apr 30 23:55:48 2003 @@ -19,9 +19,10 @@ #define NF_REPEAT 4 #define NF_MAX_VERDICT NF_REPEAT -/* Generic cache responses from hook functions. */ -#define NFC_ALTERED 0x8000 +/* Generic cache responses from hook functions. + <= 0x2000 is used for protocol-flags. */ #define NFC_UNKNOWN 0x4000 +#define NFC_ALTERED 0x8000 #ifdef __KERNEL__ #include diff -urN linux-2.4.21-bk-1.1141/include/linux/netfilter_ipv4/listhelp.h linux-2.4.21-bk1141-pom-20030429-pending/include/linux/netfilter_ipv4/listhelp.h --- linux-2.4.21-bk-1.1141/include/linux/netfilter_ipv4/listhelp.h Wed Apr 23 16:20:00 2003 +++ linux-2.4.21-bk1141-pom-20030429-pending/include/linux/netfilter_ipv4/listhelp.h Wed Apr 30 23:55:36 2003 @@ -39,6 +39,22 @@ (type)__i; \ }) +/* Just like LIST_FIND but we search backwards */ +#define LIST_FIND_B(head, cmpfn, type, args...) \ +({ \ + const struct list_head *__i = (head); \ + \ + ASSERT_READ_LOCK(head); \ + do { \ + __i = __i->prev; \ + if (__i == (head)) { \ + __i = NULL; \ + break; \ + } \ + } while (!cmpfn((const type)__i , ## args)); \ + (type)__i; \ +}) + static inline int __list_cmp_same(const void *p1, const void *p2) { return p1 == p2; } diff -urN linux-2.4.21-bk-1.1141/include/linux/netfilter_ipv4/lockhelp.h linux-2.4.21-bk1141-pom-20030429-pending/include/linux/netfilter_ipv4/lockhelp.h --- linux-2.4.21-bk-1.1141/include/linux/netfilter_ipv4/lockhelp.h Wed Apr 23 16:19:41 2003 +++ linux-2.4.21-bk1141-pom-20030429-pending/include/linux/netfilter_ipv4/lockhelp.h Wed Apr 30 23:55:45 2003 @@ -42,22 +42,22 @@ printk("ASSERT %s:%u %s locked\n", __FILE__, __LINE__, #l); \ } while(0) -/* Write locked OK as well. */ \ +/* Write locked OK as well. */ #define MUST_BE_READ_LOCKED(l) \ -do { if (!((l)->read_locked_map & (1 << smp_processor_id())) \ - && !((l)->write_locked_map & (1 << smp_processor_id()))) \ +do { if (!((l)->read_locked_map & (1UL << smp_processor_id())) \ + && !((l)->write_locked_map & (1UL << smp_processor_id()))) \ printk("ASSERT %s:%u %s not readlocked\n", __FILE__, __LINE__, #l); \ } while(0) #define MUST_BE_WRITE_LOCKED(l) \ -do { if (!((l)->write_locked_map & (1 << smp_processor_id()))) \ +do { if (!((l)->write_locked_map & (1UL << smp_processor_id()))) \ printk("ASSERT %s:%u %s not writelocked\n", __FILE__, __LINE__, #l); \ } while(0) #define MUST_BE_READ_WRITE_UNLOCKED(l) \ -do { if ((l)->read_locked_map & (1 << smp_processor_id())) \ +do { if ((l)->read_locked_map & (1UL << smp_processor_id())) \ printk("ASSERT %s:%u %s readlocked\n", __FILE__, __LINE__, #l); \ - else if ((l)->write_locked_map & (1 << smp_processor_id())) \ + else if ((l)->write_locked_map & (1UL << smp_processor_id())) \ printk("ASSERT %s:%u %s writelocked\n", __FILE__, __LINE__, #l); \ } while(0) @@ -91,7 +91,7 @@ #define READ_UNLOCK(lk) \ do { \ - if (!((lk)->read_locked_map & (1 << smp_processor_id()))) \ + if (!((lk)->read_locked_map & (1UL << smp_processor_id()))) \ printk("ASSERT: %s:%u %s not readlocked\n", \ __FILE__, __LINE__, #lk); \ clear_bit(smp_processor_id(), &(lk)->read_locked_map); \ diff -urN linux-2.4.21-bk-1.1141/net/ipv4/netfilter/ip_conntrack_core.c linux-2.4.21-bk1141-pom-20030429-pending/net/ipv4/netfilter/ip_conntrack_core.c --- linux-2.4.21-bk-1.1141/net/ipv4/netfilter/ip_conntrack_core.c Tue Apr 22 03:05:09 2003 +++ linux-2.4.21-bk1141-pom-20030429-pending/net/ipv4/netfilter/ip_conntrack_core.c Wed Apr 30 23:55:40 2003 @@ -595,7 +595,7 @@ int dropped = 0; READ_LOCK(&ip_conntrack_lock); - h = LIST_FIND(chain, unreplied, struct ip_conntrack_tuple_hash *); + h = LIST_FIND_B(chain, unreplied, struct ip_conntrack_tuple_hash *); if (h) atomic_inc(&h->ctrack->ct_general.use); READ_UNLOCK(&ip_conntrack_lock); @@ -1478,8 +1478,10 @@ ip_ct_attach = ip_conntrack_attach; return ret; +#ifdef CONFIG_SYSCTL err_free_ct_cachep: kmem_cache_destroy(ip_conntrack_cachep); +#endif /*CONFIG_SYSCTL*/ err_free_hash: vfree(ip_conntrack_hash); err_unreg_sockopt: diff -urN linux-2.4.21-bk-1.1141/net/ipv4/netfilter/ip_nat_core.c linux-2.4.21-bk1141-pom-20030429-pending/net/ipv4/netfilter/ip_nat_core.c --- linux-2.4.21-bk-1.1141/net/ipv4/netfilter/ip_nat_core.c Tue Apr 22 03:05:09 2003 +++ linux-2.4.21-bk1141-pom-20030429-pending/net/ipv4/netfilter/ip_nat_core.c Wed Apr 30 23:55:43 2003 @@ -756,6 +756,11 @@ enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); int is_tcp = (*pskb)->nh.iph->protocol == IPPROTO_TCP; + /* Skip everything and don't call helpers if there are no + * manips for this connection */ + if (info->num_manips == 0) + return NF_ACCEPT; + /* Need nat lock to protect against modification, but neither conntrack (referenced) and helper (deleted with synchronize_bh()) can vanish. */ @@ -796,6 +801,7 @@ struct ip_conntrack_expect *exp = NULL; struct list_head *cur_item; int ret = NF_ACCEPT; + int helper_called = 0; DEBUGP("do_bindings: helper existing for (%p)\n", ct); @@ -814,19 +820,22 @@ continue; if (exp_for_packet(exp, pskb)) { - /* FIXME: May be true multiple times in the case of UDP!! */ - DEBUGP("calling nat helper (exp=%p) for packet\n", - exp); + /* FIXME: May be true multiple times in the + * case of UDP!! */ + DEBUGP("calling nat helper (exp=%p) for + packet\n", exp); ret = helper->help(ct, exp, info, ctinfo, hooknum, pskb); if (ret != NF_ACCEPT) { READ_UNLOCK(&ip_conntrack_lock); return ret; } + helper_called = 1; } } - /* Helper might want to manip the packet even when there is no expectation */ - if (!exp && helper->flags & IP_NAT_HELPER_F_ALWAYS) { + /* Helper might want to manip the packet even when there is no + * matching expectation for this packet */ + if (!helper_called && helper->flags & IP_NAT_HELPER_F_ALWAYS) { DEBUGP("calling nat helper for packet without expectation\n"); ret = helper->help(ct, NULL, info, ctinfo, hooknum, pskb); diff -urN linux-2.4.21-bk-1.1141/net/ipv4/netfilter/ip_nat_helper.c linux-2.4.21-bk1141-pom-20030429-pending/net/ipv4/netfilter/ip_nat_helper.c --- linux-2.4.21-bk-1.1141/net/ipv4/netfilter/ip_nat_helper.c Tue Apr 22 03:05:09 2003 +++ linux-2.4.21-bk1141-pom-20030429-pending/net/ipv4/netfilter/ip_nat_helper.c Wed Apr 30 23:55:49 2003 @@ -84,7 +84,6 @@ iph = (*skb)->nh.iph; if (iph->protocol == IPPROTO_TCP) { struct tcphdr *tcph = (void *)iph + iph->ihl*4; - void *data = (void *)tcph + tcph->doff*4; DEBUGP("ip_nat_resize_packet: Seq_offset before: "); DUMP_OFFSET(this_way); diff -urN linux-2.4.21-bk-1.1141/net/ipv4/netfilter/ip_tables.c linux-2.4.21-bk1141-pom-20030429-pending/net/ipv4/netfilter/ip_tables.c --- linux-2.4.21-bk-1.1141/net/ipv4/netfilter/ip_tables.c Tue Apr 22 03:05:10 2003 +++ linux-2.4.21-bk1141-pom-20030429-pending/net/ipv4/netfilter/ip_tables.c Wed Apr 30 23:55:37 2003 @@ -1698,14 +1698,15 @@ = { { NULL, NULL }, "icmp", &icmp_match, &icmp_checkentry, NULL }; #ifdef CONFIG_PROC_FS -static inline int print_name(const struct ipt_table *t, +static inline int print_name(const char *i, off_t start_offset, char *buffer, int length, off_t *pos, unsigned int *count) { if ((*count)++ >= start_offset) { unsigned int namelen; - namelen = sprintf(buffer + *pos, "%s\n", t->name); + namelen = sprintf(buffer + *pos, "%s\n", + i + sizeof(struct list_head)); if (*pos + namelen > length) { /* Stop iterating */ return 1; @@ -1723,7 +1724,7 @@ if (down_interruptible(&ipt_mutex) != 0) return 0; - LIST_FIND(&ipt_tables, print_name, struct ipt_table *, + LIST_FIND(&ipt_tables, print_name, void *, offset, buffer, length, &pos, &count); up(&ipt_mutex); @@ -1732,6 +1733,46 @@ *start=(char *)((unsigned long)count-offset); return pos; } + +static int ipt_get_targets(char *buffer, char **start, off_t offset, int length) +{ + off_t pos = 0; + unsigned int count = 0; + + if (down_interruptible(&ipt_mutex) != 0) + return 0; + + LIST_FIND(&ipt_target, print_name, void *, + offset, buffer, length, &pos, &count); + + up(&ipt_mutex); + + *start = (char *)((unsigned long)count - offset); + return pos; +} + +static int ipt_get_matches(char *buffer, char **start, off_t offset, int length) +{ + off_t pos = 0; + unsigned int count = 0; + + if (down_interruptible(&ipt_mutex) != 0) + return 0; + + LIST_FIND(&ipt_match, print_name, void *, + offset, buffer, length, &pos, &count); + + up(&ipt_mutex); + + *start = (char *)((unsigned long)count - offset); + return pos; +} + +static struct { char *name; get_info_t *get_info; } ipt_proc_entry[] = +{ { "ip_tables_names", ipt_get_tables }, + { "ip_tables_targets", ipt_get_targets }, + { "ip_tables_matches", ipt_get_matches }, + { NULL, NULL} }; #endif /*CONFIG_PROC_FS*/ static int __init init(void) @@ -1757,13 +1798,19 @@ #ifdef CONFIG_PROC_FS { struct proc_dir_entry *proc; + int i; - proc = proc_net_create("ip_tables_names", 0, ipt_get_tables); - if (!proc) { - nf_unregister_sockopt(&ipt_sockopts); - return -ENOMEM; + for (i = 0; ipt_proc_entry[i].name; i++) { + proc = proc_net_create(ipt_proc_entry[i].name, 0, + ipt_proc_entry[i].get_info); + if (!proc) { + while (--i >= 0) + proc_net_remove(ipt_proc_entry[i].name); + nf_unregister_sockopt(&ipt_sockopts); + return -ENOMEM; + } + proc->owner = THIS_MODULE; } - proc->owner = THIS_MODULE; } #endif @@ -1775,7 +1822,11 @@ { nf_unregister_sockopt(&ipt_sockopts); #ifdef CONFIG_PROC_FS - proc_net_remove("ip_tables_names"); + { + int i; + for (i = 0; ipt_proc_entry[i].name; i++) + proc_net_remove(ipt_proc_entry[i].name); + } #endif }