1diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.18-plain/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.4.19-plain/include/linux/netfilter_ipv4/ip_conntrack.h 2--- linux-2.4.18-plain/include/linux/netfilter_ipv4/ip_conntrack.h Mon Feb 25 20:38:13 2002 3+++ linux-2.4.19-plain/include/linux/netfilter_ipv4/ip_conntrack.h Sat Aug 3 02:39:45 2002 4@@ -82,10 +82,7 @@ 5 #endif 6 7 #include <linux/netfilter_ipv4/ip_conntrack_ftp.h> 8- 9-#if defined(CONFIG_IP_NF_IRC) || defined(CONFIG_IP_NF_IRC_MODULE) 10 #include <linux/netfilter_ipv4/ip_conntrack_irc.h> 11-#endif 12 13 struct ip_conntrack 14 { 15@@ -125,9 +122,7 @@ 16 17 union { 18 struct ip_ct_ftp ct_ftp_info; 19-#if defined(CONFIG_IP_NF_IRC) || defined(CONFIG_IP_NF_IRC_MODULE) 20 struct ip_ct_irc ct_irc_info; 21-#endif 22 } help; 23 24 #ifdef CONFIG_IP_NF_NAT_NEEDED 25diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.18-plain/include/linux/netfilter_ipv4/ip_conntrack_protocol.h linux-2.4.19-plain/include/linux/netfilter_ipv4/ip_conntrack_protocol.h 26--- linux-2.4.18-plain/include/linux/netfilter_ipv4/ip_conntrack_protocol.h Fri Apr 27 23:15:01 2001 27+++ linux-2.4.19-plain/include/linux/netfilter_ipv4/ip_conntrack_protocol.h Sat Aug 3 02:39:45 2002 28@@ -42,6 +42,9 @@ 29 int (*new)(struct ip_conntrack *conntrack, struct iphdr *iph, 30 size_t len); 31 32+ /* Called when a conntrack entry is destroyed */ 33+ void (*destroy)(struct ip_conntrack *conntrack); 34+ 35 /* Module (if any) which this is connected to. */ 36 struct module *me; 37 }; 38diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.18-plain/include/linux/netfilter_ipv4/ip_nat.h linux-2.4.19-plain/include/linux/netfilter_ipv4/ip_nat.h 39--- linux-2.4.18-plain/include/linux/netfilter_ipv4/ip_nat.h Thu Apr 26 00:00:28 2001 40+++ linux-2.4.19-plain/include/linux/netfilter_ipv4/ip_nat.h Sat Aug 3 02:39:45 2002 41@@ -11,8 +11,13 @@ 42 IP_NAT_MANIP_DST 43 }; 44 45+#ifndef CONFIG_IP_NF_NAT_LOCAL 46 /* SRC manip occurs only on POST_ROUTING */ 47 #define HOOK2MANIP(hooknum) ((hooknum) != NF_IP_POST_ROUTING) 48+#else 49+/* SRC manip occurs POST_ROUTING or LOCAL_IN */ 50+#define HOOK2MANIP(hooknum) ((hooknum) != NF_IP_POST_ROUTING && (hooknum) != NF_IP_LOCAL_IN) 51+#endif 52 53 /* 2.3.19 (I hope) will define this in linux/netfilter_ipv4.h. */ 54 #ifndef SO_ORIGINAL_DST 55diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.18-plain/net/ipv4/netfilter/Config.in linux-2.4.19-plain/net/ipv4/netfilter/Config.in 56--- linux-2.4.18-plain/net/ipv4/netfilter/Config.in Mon Feb 25 20:38:14 2002 57+++ linux-2.4.19-plain/net/ipv4/netfilter/Config.in Sat Aug 3 02:39:46 2002 58@@ -47,6 +47,7 @@ 59 define_bool CONFIG_IP_NF_NAT_NEEDED y 60 dep_tristate ' MASQUERADE target support' CONFIG_IP_NF_TARGET_MASQUERADE $CONFIG_IP_NF_NAT 61 dep_tristate ' REDIRECT target support' CONFIG_IP_NF_TARGET_REDIRECT $CONFIG_IP_NF_NAT 62+ bool ' NAT of local connections (READ HELP)' CONFIG_IP_NF_NAT_LOCAL 63 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then 64 dep_tristate ' Basic SNMP-ALG support (EXPERIMENTAL)' CONFIG_IP_NF_NAT_SNMP_BASIC $CONFIG_IP_NF_NAT 65 fi 66@@ -75,10 +76,13 @@ 67 dep_tristate ' MARK target support' CONFIG_IP_NF_TARGET_MARK $CONFIG_IP_NF_MANGLE 68 fi 69 dep_tristate ' LOG target support' CONFIG_IP_NF_TARGET_LOG $CONFIG_IP_NF_IPTABLES 70- if [ "$CONFIG_NETLINK" != "n" ]; then 71- dep_tristate ' ULOG target support' CONFIG_IP_NF_TARGET_ULOG $CONFIG_NETLINK $CONFIG_IP_NF_IPTABLES 72- fi 73+ dep_tristate ' ULOG target support' CONFIG_IP_NF_TARGET_ULOG $CONFIG_IP_NF_IPTABLES 74 dep_tristate ' TCPMSS target support' CONFIG_IP_NF_TARGET_TCPMSS $CONFIG_IP_NF_IPTABLES 75+fi 76+ 77+tristate 'ARP tables support' CONFIG_IP_NF_ARPTABLES 78+if [ "$CONFIG_IP_NF_ARPTABLES" != "n" ]; then 79+ dep_tristate ' ARP packet filtering' CONFIG_IP_NF_ARPFILTER $CONFIG_IP_NF_ARPTABLES 80 fi 81 82 # Backwards compatibility modules: only if you don't build in the others. 83diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.18-plain/net/ipv4/netfilter/Makefile linux-2.4.19-plain/net/ipv4/netfilter/Makefile 84--- linux-2.4.18-plain/net/ipv4/netfilter/Makefile Mon Feb 25 20:38:14 2002 85+++ linux-2.4.19-plain/net/ipv4/netfilter/Makefile Sat Aug 3 02:39:46 2002 86@@ -9,7 +9,7 @@ 87 88 O_TARGET := netfilter.o 89 90-export-objs = ip_conntrack_standalone.o ip_conntrack_ftp.o ip_fw_compat.o ip_nat_standalone.o ip_tables.o 91+export-objs = ip_conntrack_standalone.o ip_conntrack_ftp.o ip_fw_compat.o ip_nat_standalone.o ip_tables.o arp_tables.o 92 93 # Multipart objects. 94 list-multi := ip_conntrack.o iptable_nat.o ipfwadm.o ipchains.o 95@@ -31,15 +31,13 @@ 96 # connection tracking 97 obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o 98 99-# IRC support 100-obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o 101-obj-$(CONFIG_IP_NF_NAT_IRC) += ip_nat_irc.o 102- 103 # connection tracking helpers 104 obj-$(CONFIG_IP_NF_FTP) += ip_conntrack_ftp.o 105+obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o 106 107 # NAT helpers 108 obj-$(CONFIG_IP_NF_NAT_FTP) += ip_nat_ftp.o 109+obj-$(CONFIG_IP_NF_NAT_IRC) += ip_nat_irc.o 110 111 # generic IP tables 112 obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o 113@@ -76,6 +74,12 @@ 114 obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o 115 obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o 116 obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o 117+ 118+# generic ARP tables 119+obj-$(CONFIG_IP_NF_ARPTABLES) += arp_tables.o 120+ 121+# just filtering instance of ARP tables for now 122+obj-$(CONFIG_IP_NF_ARPFILTER) += arptable_filter.o 123 124 # backwards compatibility 125 obj-$(CONFIG_IP_NF_COMPAT_IPCHAINS) += ipchains.o 126diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.18-plain/net/ipv4/netfilter/arp_tables.c linux-2.4.19-plain/net/ipv4/netfilter/arp_tables.c 127--- linux-2.4.18-plain/net/ipv4/netfilter/arp_tables.c Thu Jan 1 01:00:00 1970 128+++ linux-2.4.19-plain/net/ipv4/netfilter/arp_tables.c Sat Aug 3 02:39:46 2002 129@@ -0,0 +1,1313 @@ 130+/* 131+ * Packet matching code for ARP packets. 132+ * 133+ * Based heavily, if not almost entirely, upon ip_tables.c framework. 134+ * 135+ * Some ARP specific bits are: 136+ * 137+ * Copyright (C) 2002 David S. Miller (davem@redhat.com) 138+ * 139+ */ 140+ 141+#include <linux/config.h> 142+#include <linux/kernel.h> 143+#include <linux/skbuff.h> 144+#include <linux/netdevice.h> 145+#include <linux/if_arp.h> 146+#include <linux/kmod.h> 147+#include <linux/vmalloc.h> 148+#include <linux/proc_fs.h> 149+#include <linux/module.h> 150+#include <linux/init.h> 151+ 152+#include <asm/uaccess.h> 153+#include <asm/semaphore.h> 154+ 155+#include <linux/netfilter_arp/arp_tables.h> 156+ 157+/*#define DEBUG_ARP_TABLES*/ 158+/*#define DEBUG_ARP_TABLES_USER*/ 159+ 160+#ifdef DEBUG_ARP_TABLES 161+#define dprintf(format, args...) printk(format , ## args) 162+#else 163+#define dprintf(format, args...) 164+#endif 165+ 166+#ifdef DEBUG_ARP_TABLES_USER 167+#define duprintf(format, args...) printk(format , ## args) 168+#else 169+#define duprintf(format, args...) 170+#endif 171+ 172+#ifdef CONFIG_NETFILTER_DEBUG 173+#define ARP_NF_ASSERT(x) \ 174+do { \ 175+ if (!(x)) \ 176+ printk("ARP_NF_ASSERT: %s:%s:%u\n", \ 177+ __FUNCTION__, __FILE__, __LINE__); \ 178+} while(0) 179+#else 180+#define ARP_NF_ASSERT(x) 181+#endif 182+#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1)) 183+ 184+static DECLARE_MUTEX(arpt_mutex); 185+ 186+#define ASSERT_READ_LOCK(x) ARP_NF_ASSERT(down_trylock(&arpt_mutex) != 0) 187+#define ASSERT_WRITE_LOCK(x) ARP_NF_ASSERT(down_trylock(&arpt_mutex) != 0) 188+#include <linux/netfilter_ipv4/lockhelp.h> 189+#include <linux/netfilter_ipv4/listhelp.h> 190+ 191+struct arpt_table_info { 192+ unsigned int size; 193+ unsigned int number; 194+ unsigned int initial_entries; 195+ unsigned int hook_entry[NF_ARP_NUMHOOKS]; 196+ unsigned int underflow[NF_ARP_NUMHOOKS]; 197+ char entries[0] __attribute__((aligned(SMP_CACHE_BYTES))); 198+}; 199+ 200+static LIST_HEAD(arpt_target); 201+static LIST_HEAD(arpt_tables); 202+#define ADD_COUNTER(c,b,p) do { (c).bcnt += (b); (c).pcnt += (p); } while(0) 203+ 204+#ifdef CONFIG_SMP 205+#define TABLE_OFFSET(t,p) (SMP_ALIGN((t)->size)*(p)) 206+#else 207+#define TABLE_OFFSET(t,p) 0 208+#endif 209+ 210+static inline int arp_devaddr_compare(const struct arpt_devaddr_info *ap, 211+ char *hdr_addr, int len) 212+{ 213+ int i, ret; 214+ 215+ if (len > ARPT_DEV_ADDR_LEN_MAX) 216+ len = ARPT_DEV_ADDR_LEN_MAX; 217+ 218+ ret = 0; 219+ for (i = 0; i < len; i++) 220+ ret |= (hdr_addr[i] ^ ap->addr[i]) & ap->mask[i]; 221+ 222+ return (ret != 0); 223+} 224+ 225+/* Returns whether packet matches rule or not. */ 226+static inline int arp_packet_match(const struct arphdr *arphdr, 227+ struct net_device *dev, 228+ const char *indev, 229+ const char *outdev, 230+ const struct arpt_arp *arpinfo) 231+{ 232+ char *arpptr = (char *)(arphdr + 1); 233+ char *src_devaddr, *tgt_devaddr; 234+ u32 *src_ipaddr, *tgt_ipaddr; 235+ int i, ret; 236+ 237+#define FWINV(bool,invflg) ((bool) ^ !!(arpinfo->invflags & invflg)) 238+ 239+ if (FWINV((arphdr->ar_op & arpinfo->arpop_mask) != arpinfo->arpop, 240+ ARPT_INV_ARPOP)) { 241+ dprintf("ARP operation field mismatch.\n"); 242+ dprintf("ar_op: %04x info->arpop: %04x info->arpop_mask: %04x\n", 243+ arphdr->ar_op, arpinfo->arpop, arpinfo->arpop_mask); 244+ return 0; 245+ } 246+ 247+ if (FWINV((arphdr->ar_hrd & arpinfo->arhrd_mask) != arpinfo->arhrd, 248+ ARPT_INV_ARPHRD)) { 249+ dprintf("ARP hardware address format mismatch.\n"); 250+ dprintf("ar_hrd: %04x info->arhrd: %04x info->arhrd_mask: %04x\n", 251+ arphdr->ar_hrd, arpinfo->arhrd, arpinfo->arhrd_mask); 252+ return 0; 253+ } 254+ 255+ if (FWINV((arphdr->ar_pro & arpinfo->arpro_mask) != arpinfo->arpro, 256+ ARPT_INV_ARPPRO)) { 257+ dprintf("ARP protocol address format mismatch.\n"); 258+ dprintf("ar_pro: %04x info->arpro: %04x info->arpro_mask: %04x\n", 259+ arphdr->ar_pro, arpinfo->arpro, arpinfo->arpro_mask); 260+ return 0; 261+ } 262+ 263+ if (FWINV((arphdr->ar_hln & arpinfo->arhln_mask) != arpinfo->arhln, 264+ ARPT_INV_ARPHLN)) { 265+ dprintf("ARP hardware address length mismatch.\n"); 266+ dprintf("ar_hln: %02x info->arhln: %02x info->arhln_mask: %02x\n", 267+ arphdr->ar_hln, arpinfo->arhln, arpinfo->arhln_mask); 268+ } 269+ 270+ src_devaddr = arpptr; 271+ arpptr += dev->addr_len; 272+ src_ipaddr = (u32 *) arpptr; 273+ arpptr += sizeof(u32); 274+ tgt_devaddr = arpptr; 275+ arpptr += dev->addr_len; 276+ tgt_ipaddr = (u32 *) arpptr; 277+ 278+ if (FWINV(arp_devaddr_compare(&arpinfo->src_devaddr, src_devaddr, dev->addr_len), 279+ ARPT_INV_SRCDEVADDR) || 280+ FWINV(arp_devaddr_compare(&arpinfo->tgt_devaddr, tgt_devaddr, dev->addr_len), 281+ ARPT_INV_TGTDEVADDR)) { 282+ dprintf("Source or target device address mismatch.\n"); 283+ 284+ return 0; 285+ } 286+ 287+ if (FWINV(((*src_ipaddr) & arpinfo->smsk.s_addr) != arpinfo->src.s_addr, 288+ ARPT_INV_SRCIP) || 289+ FWINV((((*tgt_ipaddr) & arpinfo->tmsk.s_addr) != arpinfo->tgt.s_addr), 290+ ARPT_INV_TGTIP)) { 291+ dprintf("Source or target IP address mismatch.\n"); 292+ 293+ dprintf("SRC: %u.%u.%u.%u. Mask: %u.%u.%u.%u. Target: %u.%u.%u.%u.%s\n", 294+ NIPQUAD(*src_ipaddr), 295+ NIPQUAD(arpinfo->smsk.s_addr), 296+ NIPQUAD(arpinfo->src.s_addr), 297+ arpinfo->invflags & ARPT_INV_SRCIP ? " (INV)" : ""); 298+ dprintf("TGT: %u.%u.%u.%u Mask: %u.%u.%u.%u Target: %u.%u.%u.%u.%s\n", 299+ NIPQUAD(*tgt_ipaddr), 300+ NIPQUAD(arpinfo->tmsk.s_addr), 301+ NIPQUAD(arpinfo->tgt.s_addr), 302+ arpinfo->invflags & ARPT_INV_TGTIP ? " (INV)" : ""); 303+ return 0; 304+ } 305+ 306+ /* Look for ifname matches; this should unroll nicely. */ 307+ for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) { 308+ ret |= (((const unsigned long *)indev)[i] 309+ ^ ((const unsigned long *)arpinfo->iniface)[i]) 310+ & ((const unsigned long *)arpinfo->iniface_mask)[i]; 311+ } 312+ 313+ if (FWINV(ret != 0, ARPT_INV_VIA_IN)) { 314+ dprintf("VIA in mismatch (%s vs %s).%s\n", 315+ indev, arpinfo->iniface, 316+ arpinfo->invflags&ARPT_INV_VIA_IN ?" (INV)":""); 317+ return 0; 318+ } 319+ 320+ for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) { 321+ ret |= (((const unsigned long *)outdev)[i] 322+ ^ ((const unsigned long *)arpinfo->outiface)[i]) 323+ & ((const unsigned long *)arpinfo->outiface_mask)[i]; 324+ } 325+ 326+ if (FWINV(ret != 0, ARPT_INV_VIA_OUT)) { 327+ dprintf("VIA out mismatch (%s vs %s).%s\n", 328+ outdev, arpinfo->outiface, 329+ arpinfo->invflags&ARPT_INV_VIA_OUT ?" (INV)":""); 330+ return 0; 331+ } 332+ 333+ return 1; 334+} 335+ 336+static inline int arp_checkentry(const struct arpt_arp *arp) 337+{ 338+ if (arp->flags & ~ARPT_F_MASK) { 339+ duprintf("Unknown flag bits set: %08X\n", 340+ arp->flags & ~ARPT_F_MASK); 341+ return 0; 342+ } 343+ if (arp->invflags & ~ARPT_INV_MASK) { 344+ duprintf("Unknown invflag bits set: %08X\n", 345+ arp->invflags & ~ARPT_INV_MASK); 346+ return 0; 347+ } 348+ 349+ return 1; 350+} 351+ 352+static unsigned int arpt_error(struct sk_buff **pskb, 353+ unsigned int hooknum, 354+ const struct net_device *in, 355+ const struct net_device *out, 356+ const void *targinfo, 357+ void *userinfo) 358+{ 359+ if (net_ratelimit()) 360+ printk("arp_tables: error: '%s'\n", (char *)targinfo); 361+ 362+ return NF_DROP; 363+} 364+ 365+static inline struct arpt_entry *get_entry(void *base, unsigned int offset) 366+{ 367+ return (struct arpt_entry *)(base + offset); 368+} 369+ 370+unsigned int arpt_do_table(struct sk_buff **pskb, 371+ unsigned int hook, 372+ const struct net_device *in, 373+ const struct net_device *out, 374+ struct arpt_table *table, 375+ void *userdata) 376+{ 377+ static const char nulldevname[IFNAMSIZ] = { 0 }; 378+ unsigned int verdict = NF_DROP; 379+ struct arphdr *arp = (*pskb)->nh.arph; 380+ int hotdrop = 0; 381+ struct arpt_entry *e, *back; 382+ const char *indev, *outdev; 383+ void *table_base; 384+ 385+ indev = in ? in->name : nulldevname; 386+ outdev = out ? out->name : nulldevname; 387+ 388+ read_lock_bh(&table->lock); 389+ table_base = (void *)table->private->entries 390+ + TABLE_OFFSET(table->private, 391+ cpu_number_map(smp_processor_id())); 392+ e = get_entry(table_base, table->private->hook_entry[hook]); 393+ back = get_entry(table_base, table->private->underflow[hook]); 394+ 395+ do { 396+ if (arp_packet_match(arp, (*pskb)->dev, indev, outdev, &e->arp)) { 397+ struct arpt_entry_target *t; 398+ int hdr_len; 399+ 400+ hdr_len = sizeof(*arp) + (2 * sizeof(struct in_addr)) + 401+ (2 * (*pskb)->dev->addr_len); 402+ ADD_COUNTER(e->counters, hdr_len, 1); 403+ 404+ t = arpt_get_target(e); 405+ 406+ /* Standard target? */ 407+ if (!t->u.kernel.target->target) { 408+ int v; 409+ 410+ v = ((struct arpt_standard_target *)t)->verdict; 411+ if (v < 0) { 412+ /* Pop from stack? */ 413+ if (v != ARPT_RETURN) { 414+ verdict = (unsigned)(-v) - 1; 415+ break; 416+ } 417+ e = back; 418+ back = get_entry(table_base, 419+ back->comefrom); 420+ continue; 421+ } 422+ if (table_base + v 423+ != (void *)e + e->next_offset) { 424+ /* Save old back ptr in next entry */ 425+ struct arpt_entry *next 426+ = (void *)e + e->next_offset; 427+ next->comefrom = 428+ (void *)back - table_base; 429+ 430+ /* set back pointer to next entry */ 431+ back = next; 432+ } 433+ 434+ e = get_entry(table_base, v); 435+ } else { 436+ /* Targets which reenter must return 437+ * abs. verdicts 438+ */ 439+ verdict = t->u.kernel.target->target(pskb, 440+ hook, 441+ in, out, 442+ t->data, 443+ userdata); 444+ 445+ /* Target might have changed stuff. */ 446+ arp = (*pskb)->nh.arph; 447+ 448+ if (verdict == ARPT_CONTINUE) 449+ e = (void *)e + e->next_offset; 450+ else 451+ /* Verdict */ 452+ break; 453+ } 454+ } else { 455+ e = (void *)e + e->next_offset; 456+ } 457+ } while (!hotdrop); 458+ read_unlock_bh(&table->lock); 459+ 460+ if (hotdrop) 461+ return NF_DROP; 462+ else 463+ return verdict; 464+} 465+ 466+static inline void *find_inlist_lock_noload(struct list_head *head, 467+ const char *name, 468+ int *error, 469+ struct semaphore *mutex) 470+{ 471+ void *ret; 472+ 473+ *error = down_interruptible(mutex); 474+ if (*error != 0) 475+ return NULL; 476+ 477+ ret = list_named_find(head, name); 478+ if (!ret) { 479+ *error = -ENOENT; 480+ up(mutex); 481+ } 482+ return ret; 483+} 484+ 485+#ifndef CONFIG_KMOD 486+#define find_inlist_lock(h,n,p,e,m) find_inlist_lock_noload((h),(n),(e),(m)) 487+#else 488+static void * 489+find_inlist_lock(struct list_head *head, 490+ const char *name, 491+ const char *prefix, 492+ int *error, 493+ struct semaphore *mutex) 494+{ 495+ void *ret; 496+ 497+ ret = find_inlist_lock_noload(head, name, error, mutex); 498+ if (!ret) { 499+ char modulename[ARPT_FUNCTION_MAXNAMELEN + strlen(prefix) + 1]; 500+ strcpy(modulename, prefix); 501+ strcat(modulename, name); 502+ duprintf("find_inlist: loading `%s'.\n", modulename); 503+ request_module(modulename); 504+ ret = find_inlist_lock_noload(head, name, error, mutex); 505+ } 506+ 507+ return ret; 508+} 509+#endif 510+ 511+static inline struct arpt_table *find_table_lock(const char *name, int *error, struct semaphore *mutex) 512+{ 513+ return find_inlist_lock(&arpt_tables, name, "arptable_", error, mutex); 514+} 515+ 516+static inline struct arpt_target *find_target_lock(const char *name, int *error, struct semaphore *mutex) 517+{ 518+ return find_inlist_lock(&arpt_target, name, "arpt_", error, mutex); 519+} 520+ 521+/* All zeroes == unconditional rule. */ 522+static inline int unconditional(const struct arpt_arp *arp) 523+{ 524+ unsigned int i; 525+ 526+ for (i = 0; i < sizeof(*arp)/sizeof(__u32); i++) 527+ if (((__u32 *)arp)[i]) 528+ return 0; 529+ 530+ return 1; 531+} 532+ 533+/* Figures out from what hook each rule can be called: returns 0 if 534+ * there are loops. Puts hook bitmask in comefrom. 535+ */ 536+static int mark_source_chains(struct arpt_table_info *newinfo, unsigned int valid_hooks) 537+{ 538+ unsigned int hook; 539+ 540+ /* No recursion; use packet counter to save back ptrs (reset 541+ * to 0 as we leave), and comefrom to save source hook bitmask. 542+ */ 543+ for (hook = 0; hook < NF_ARP_NUMHOOKS; hook++) { 544+ unsigned int pos = newinfo->hook_entry[hook]; 545+ struct arpt_entry *e 546+ = (struct arpt_entry *)(newinfo->entries + pos); 547+ 548+ if (!(valid_hooks & (1 << hook))) 549+ continue; 550+ 551+ /* Set initial back pointer. */ 552+ e->counters.pcnt = pos; 553+ 554+ for (;;) { 555+ struct arpt_standard_target *t 556+ = (void *)arpt_get_target(e); 557+ 558+ if (e->comefrom & (1 << NF_ARP_NUMHOOKS)) { 559+ printk("arptables: loop hook %u pos %u %08X.\n", 560+ hook, pos, e->comefrom); 561+ return 0; 562+ } 563+ e->comefrom 564+ |= ((1 << hook) | (1 << NF_ARP_NUMHOOKS)); 565+ 566+ /* Unconditional return/END. */ 567+ if (e->target_offset == sizeof(struct arpt_entry) 568+ && (strcmp(t->target.u.user.name, 569+ ARPT_STANDARD_TARGET) == 0) 570+ && t->verdict < 0 571+ && unconditional(&e->arp)) { 572+ unsigned int oldpos, size; 573+ 574+ /* Return: backtrack through the last 575+ * big jump. 576+ */ 577+ do { 578+ e->comefrom ^= (1<<NF_ARP_NUMHOOKS); 579+ oldpos = pos; 580+ pos = e->counters.pcnt; 581+ e->counters.pcnt = 0; 582+ 583+ /* We're at the start. */ 584+ if (pos == oldpos) 585+ goto next; 586+ 587+ e = (struct arpt_entry *) 588+ (newinfo->entries + pos); 589+ } while (oldpos == pos + e->next_offset); 590+ 591+ /* Move along one */ 592+ size = e->next_offset; 593+ e = (struct arpt_entry *) 594+ (newinfo->entries + pos + size); 595+ e->counters.pcnt = pos; 596+ pos += size; 597+ } else { 598+ int newpos = t->verdict; 599+ 600+ if (strcmp(t->target.u.user.name, 601+ ARPT_STANDARD_TARGET) == 0 602+ && newpos >= 0) { 603+ /* This a jump; chase it. */ 604+ duprintf("Jump rule %u -> %u\n", 605+ pos, newpos); 606+ } else { 607+ /* ... this is a fallthru */ 608+ newpos = pos + e->next_offset; 609+ } 610+ e = (struct arpt_entry *) 611+ (newinfo->entries + newpos); 612+ e->counters.pcnt = pos; 613+ pos = newpos; 614+ } 615+ } 616+ next: 617+ duprintf("Finished chain %u\n", hook); 618+ } 619+ return 1; 620+} 621+ 622+static inline int standard_check(const struct arpt_entry_target *t, 623+ unsigned int max_offset) 624+{ 625+ struct arpt_standard_target *targ = (void *)t; 626+ 627+ /* Check standard info. */ 628+ if (t->u.target_size 629+ != ARPT_ALIGN(sizeof(struct arpt_standard_target))) { 630+ duprintf("arpt_standard_check: target size %u != %Zu\n", 631+ t->u.target_size, 632+ ARPT_ALIGN(sizeof(struct arpt_standard_target))); 633+ return 0; 634+ } 635+ 636+ if (targ->verdict >= 0 637+ && targ->verdict > max_offset - sizeof(struct arpt_entry)) { 638+ duprintf("arpt_standard_check: bad verdict (%i)\n", 639+ targ->verdict); 640+ return 0; 641+ } 642+ 643+ if (targ->verdict < -NF_MAX_VERDICT - 1) { 644+ duprintf("arpt_standard_check: bad negative verdict (%i)\n", 645+ targ->verdict); 646+ return 0; 647+ } 648+ return 1; 649+} 650+ 651+static struct arpt_target arpt_standard_target; 652+ 653+static inline int check_entry(struct arpt_entry *e, const char *name, unsigned int size, 654+ unsigned int *i) 655+{ 656+ struct arpt_entry_target *t; 657+ struct arpt_target *target; 658+ int ret; 659+ 660+ if (!arp_checkentry(&e->arp)) { 661+ duprintf("arp_tables: arp check failed %p %s.\n", e, name); 662+ return -EINVAL; 663+ } 664+ 665+ t = arpt_get_target(e); 666+ target = find_target_lock(t->u.user.name, &ret, &arpt_mutex); 667+ if (!target) { 668+ duprintf("check_entry: `%s' not found\n", t->u.user.name); 669+ goto out; 670+ } 671+ if (target->me) 672+ __MOD_INC_USE_COUNT(target->me); 673+ t->u.kernel.target = target; 674+ up(&arpt_mutex); 675+ 676+ if (t->u.kernel.target == &arpt_standard_target) { 677+ if (!standard_check(t, size)) { 678+ ret = -EINVAL; 679+ goto out; 680+ } 681+ } else if (t->u.kernel.target->checkentry 682+ && !t->u.kernel.target->checkentry(name, e, t->data, 683+ t->u.target_size 684+ - sizeof(*t), 685+ e->comefrom)) { 686+ if (t->u.kernel.target->me) 687+ __MOD_DEC_USE_COUNT(t->u.kernel.target->me); 688+ duprintf("arp_tables: check failed for `%s'.\n", 689+ t->u.kernel.target->name); 690+ ret = -EINVAL; 691+ goto out; 692+ } 693+ 694+ (*i)++; 695+ return 0; 696+ 697+out: 698+ return ret; 699+} 700+ 701+static inline int check_entry_size_and_hooks(struct arpt_entry *e, 702+ struct arpt_table_info *newinfo, 703+ unsigned char *base, 704+ unsigned char *limit, 705+ const unsigned int *hook_entries, 706+ const unsigned int *underflows, 707+ unsigned int *i) 708+{ 709+ unsigned int h; 710+ 711+ if ((unsigned long)e % __alignof__(struct arpt_entry) != 0 712+ || (unsigned char *)e + sizeof(struct arpt_entry) >= limit) { 713+ duprintf("Bad offset %p\n", e); 714+ return -EINVAL; 715+ } 716+ 717+ if (e->next_offset 718+ < sizeof(struct arpt_entry) + sizeof(struct arpt_entry_target)) { 719+ duprintf("checking: element %p size %u\n", 720+ e, e->next_offset); 721+ return -EINVAL; 722+ } 723+ 724+ /* Check hooks & underflows */ 725+ for (h = 0; h < NF_ARP_NUMHOOKS; h++) { 726+ if ((unsigned char *)e - base == hook_entries[h]) 727+ newinfo->hook_entry[h] = hook_entries[h]; 728+ if ((unsigned char *)e - base == underflows[h]) 729+ newinfo->underflow[h] = underflows[h]; 730+ } 731+ 732+ 733+ 734+ /* Clear counters and comefrom */ 735+ e->counters = ((struct arpt_counters) { 0, 0 }); 736+ e->comefrom = 0; 737+ 738+ (*i)++; 739+ return 0; 740+} 741+ 742+static inline int cleanup_entry(struct arpt_entry *e, unsigned int *i) 743+{ 744+ struct arpt_entry_target *t; 745+ 746+ if (i && (*i)-- == 0) 747+ return 1; 748+ 749+ t = arpt_get_target(e); 750+ if (t->u.kernel.target->destroy) 751+ t->u.kernel.target->destroy(t->data, 752+ t->u.target_size - sizeof(*t)); 753+ if (t->u.kernel.target->me) 754+ __MOD_DEC_USE_COUNT(t->u.kernel.target->me); 755+ 756+ return 0; 757+} 758+ 759+/* Checks and translates the user-supplied table segment (held in 760+ * newinfo). 761+ */ 762+static int translate_table(const char *name, 763+ unsigned int valid_hooks, 764+ struct arpt_table_info *newinfo, 765+ unsigned int size, 766+ unsigned int number, 767+ const unsigned int *hook_entries, 768+ const unsigned int *underflows) 769+{ 770+ unsigned int i; 771+ int ret; 772+ 773+ newinfo->size = size; 774+ newinfo->number = number; 775+ 776+ /* Init all hooks to impossible value. */ 777+ for (i = 0; i < NF_ARP_NUMHOOKS; i++) { 778+ newinfo->hook_entry[i] = 0xFFFFFFFF; 779+ newinfo->underflow[i] = 0xFFFFFFFF; 780+ } 781+ 782+ duprintf("translate_table: size %u\n", newinfo->size); 783+ i = 0; 784+ 785+ /* Walk through entries, checking offsets. */ 786+ ret = ARPT_ENTRY_ITERATE(newinfo->entries, newinfo->size, 787+ check_entry_size_and_hooks, 788+ newinfo, 789+ newinfo->entries, 790+ newinfo->entries + size, 791+ hook_entries, underflows, &i); 792+ duprintf("translate_table: ARPT_ENTRY_ITERATE gives %d\n", ret); 793+ if (ret != 0) 794+ return ret; 795+ 796+ if (i != number) { 797+ duprintf("translate_table: %u not %u entries\n", 798+ i, number); 799+ return -EINVAL; 800+ } 801+ 802+ /* Check hooks all assigned */ 803+ for (i = 0; i < NF_ARP_NUMHOOKS; i++) { 804+ /* Only hooks which are valid */ 805+ if (!(valid_hooks & (1 << i))) 806+ continue; 807+ if (newinfo->hook_entry[i] == 0xFFFFFFFF) { 808+ duprintf("Invalid hook entry %u %u\n", 809+ i, hook_entries[i]); 810+ return -EINVAL; 811+ } 812+ if (newinfo->underflow[i] == 0xFFFFFFFF) { 813+ duprintf("Invalid underflow %u %u\n", 814+ i, underflows[i]); 815+ return -EINVAL; 816+ } 817+ } 818+ 819+ if (!mark_source_chains(newinfo, valid_hooks)) { 820+ duprintf("Looping hook\n"); 821+ return -ELOOP; 822+ } 823+ 824+ /* Finally, each sanity check must pass */ 825+ i = 0; 826+ ret = ARPT_ENTRY_ITERATE(newinfo->entries, newinfo->size, 827+ check_entry, name, size, &i); 828+ 829+ if (ret != 0) { 830+ ARPT_ENTRY_ITERATE(newinfo->entries, newinfo->size, 831+ cleanup_entry, &i); 832+ return ret; 833+ } 834+ 835+ /* And one copy for every other CPU */ 836+ for (i = 1; i < smp_num_cpus; i++) { 837+ memcpy(newinfo->entries + SMP_ALIGN(newinfo->size)*i, 838+ newinfo->entries, 839+ SMP_ALIGN(newinfo->size)); 840+ } 841+ 842+ return ret; 843+} 844+ 845+static struct arpt_table_info *replace_table(struct arpt_table *table, 846+ unsigned int num_counters, 847+ struct arpt_table_info *newinfo, 848+ int *error) 849+{ 850+ struct arpt_table_info *oldinfo; 851+ 852+ /* Do the substitution. */ 853+ write_lock_bh(&table->lock); 854+ /* Check inside lock: is the old number correct? */ 855+ if (num_counters != table->private->number) { 856+ duprintf("num_counters != table->private->number (%u/%u)\n", 857+ num_counters, table->private->number); 858+ write_unlock_bh(&table->lock); 859+ *error = -EAGAIN; 860+ return NULL; 861+ } 862+ oldinfo = table->private; 863+ table->private = newinfo; 864+ newinfo->initial_entries = oldinfo->initial_entries; 865+ write_unlock_bh(&table->lock); 866+ 867+ return oldinfo; 868+} 869+ 870+/* Gets counters. */ 871+static inline int add_entry_to_counter(const struct arpt_entry *e, 872+ struct arpt_counters total[], 873+ unsigned int *i) 874+{ 875+ ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt); 876+ 877+ (*i)++; 878+ return 0; 879+} 880+ 881+static void get_counters(const struct arpt_table_info *t, 882+ struct arpt_counters counters[]) 883+{ 884+ unsigned int cpu; 885+ unsigned int i; 886+ 887+ for (cpu = 0; cpu < smp_num_cpus; cpu++) { 888+ i = 0; 889+ ARPT_ENTRY_ITERATE(t->entries + TABLE_OFFSET(t, cpu), 890+ t->size, 891+ add_entry_to_counter, 892+ counters, 893+ &i); 894+ } 895+} 896+ 897+static int copy_entries_to_user(unsigned int total_size, 898+ struct arpt_table *table, 899+ void *userptr) 900+{ 901+ unsigned int off, num, countersize; 902+ struct arpt_entry *e; 903+ struct arpt_counters *counters; 904+ int ret = 0; 905+ 906+ /* We need atomic snapshot of counters: rest doesn't change 907+ * (other than comefrom, which userspace doesn't care 908+ * about). 909+ */ 910+ countersize = sizeof(struct arpt_counters) * table->private->number; 911+ counters = vmalloc(countersize); 912+ 913+ if (counters == NULL) 914+ return -ENOMEM; 915+ 916+ /* First, sum counters... */ 917+ memset(counters, 0, countersize); 918+ write_lock_bh(&table->lock); 919+ get_counters(table->private, counters); 920+ write_unlock_bh(&table->lock); 921+ 922+ /* ... then copy entire thing from CPU 0... */ 923+ if (copy_to_user(userptr, table->private->entries, total_size) != 0) { 924+ ret = -EFAULT; 925+ goto free_counters; 926+ } 927+ 928+ 929+ /* ... then go back and fix counters and names */ 930+ for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){ 931+ struct arpt_entry_target *t; 932+ 933+ e = (struct arpt_entry *)(table->private->entries + off); 934+ if (copy_to_user(userptr + off 935+ + offsetof(struct arpt_entry, counters), 936+ &counters[num], 937+ sizeof(counters[num])) != 0) { 938+ ret = -EFAULT; 939+ goto free_counters; 940+ } 941+ 942+ t = arpt_get_target(e); 943+ if (copy_to_user(userptr + off + e->target_offset 944+ + offsetof(struct arpt_entry_target, 945+ u.user.name), 946+ t->u.kernel.target->name, 947+ strlen(t->u.kernel.target->name)+1) != 0) { 948+ ret = -EFAULT; 949+ goto free_counters; 950+ } 951+ } 952+ 953+ free_counters: 954+ vfree(counters); 955+ return ret; 956+} 957+ 958+static int get_entries(const struct arpt_get_entries *entries, 959+ struct arpt_get_entries *uptr) 960+{ 961+ int ret; 962+ struct arpt_table *t; 963+ 964+ t = find_table_lock(entries->name, &ret, &arpt_mutex); 965+ if (t) { 966+ duprintf("t->private->number = %u\n", 967+ t->private->number); 968+ if (entries->size == t->private->size) 969+ ret = copy_entries_to_user(t->private->size, 970+ t, uptr->entrytable); 971+ else { 972+ duprintf("get_entries: I've got %u not %u!\n", 973+ t->private->size, 974+ entries->size); 975+ ret = -EINVAL; 976+ } 977+ up(&arpt_mutex); 978+ } else 979+ duprintf("get_entries: Can't find %s!\n", 980+ entries->name); 981+ 982+ return ret; 983+} 984+ 985+static int do_replace(void *user, unsigned int len) 986+{ 987+ int ret; 988+ struct arpt_replace tmp; 989+ struct arpt_table *t; 990+ struct arpt_table_info *newinfo, *oldinfo; 991+ struct arpt_counters *counters; 992+ 993+ if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) 994+ return -EFAULT; 995+ 996+ /* Hack: Causes ipchains to give correct error msg --RR */ 997+ if (len != sizeof(tmp) + tmp.size) 998+ return -ENOPROTOOPT; 999+ 1000+ /* Pedantry: prevent them from hitting BUG() in vmalloc.c --RR */ 1001+ if ((SMP_ALIGN(tmp.size) >> PAGE_SHIFT) + 2 > num_physpages) 1002+ return -ENOMEM; 1003+ 1004+ newinfo = vmalloc(sizeof(struct arpt_table_info) 1005+ + SMP_ALIGN(tmp.size) * smp_num_cpus); 1006+ if (!newinfo) 1007+ return -ENOMEM; 1008+ 1009+ if (copy_from_user(newinfo->entries, user + sizeof(tmp), 1010+ tmp.size) != 0) { 1011+ ret = -EFAULT; 1012+ goto free_newinfo; 1013+ } 1014+ 1015+ counters = vmalloc(tmp.num_counters * sizeof(struct arpt_counters)); 1016+ if (!counters) { 1017+ ret = -ENOMEM; 1018+ goto free_newinfo; 1019+ } 1020+ memset(counters, 0, tmp.num_counters * sizeof(struct arpt_counters)); 1021+ 1022+ ret = translate_table(tmp.name, tmp.valid_hooks, 1023+ newinfo, tmp.size, tmp.num_entries, 1024+ tmp.hook_entry, tmp.underflow); 1025+ if (ret != 0) 1026+ goto free_newinfo_counters; 1027+ 1028+ duprintf("arp_tables: Translated table\n"); 1029+ 1030+ t = find_table_lock(tmp.name, &ret, &arpt_mutex); 1031+ if (!t) 1032+ goto free_newinfo_counters_untrans; 1033+ 1034+ /* You lied! */ 1035+ if (tmp.valid_hooks != t->valid_hooks) { 1036+ duprintf("Valid hook crap: %08X vs %08X\n", 1037+ tmp.valid_hooks, t->valid_hooks); 1038+ ret = -EINVAL; 1039+ goto free_newinfo_counters_untrans_unlock; 1040+ } 1041+ 1042+ oldinfo = replace_table(t, tmp.num_counters, newinfo, &ret); 1043+ if (!oldinfo) 1044+ goto free_newinfo_counters_untrans_unlock; 1045+ 1046+ /* Update module usage count based on number of rules */ 1047+ duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%u\n", 1048+ oldinfo->number, oldinfo->initial_entries, newinfo->number); 1049+ if (t->me && (oldinfo->number <= oldinfo->initial_entries) && 1050+ (newinfo->number > oldinfo->initial_entries)) 1051+ __MOD_INC_USE_COUNT(t->me); 1052+ else if (t->me && (oldinfo->number > oldinfo->initial_entries) && 1053+ (newinfo->number <= oldinfo->initial_entries)) 1054+ __MOD_DEC_USE_COUNT(t->me); 1055+ 1056+ /* Get the old counters. */ 1057+ get_counters(oldinfo, counters); 1058+ /* Decrease module usage counts and free resource */ 1059+ ARPT_ENTRY_ITERATE(oldinfo->entries, oldinfo->size, cleanup_entry,NULL); 1060+ vfree(oldinfo); 1061+ /* Silent error: too late now. */ 1062+ copy_to_user(tmp.counters, counters, 1063+ sizeof(struct arpt_counters) * tmp.num_counters); 1064+ vfree(counters); 1065+ up(&arpt_mutex); 1066+ return 0; 1067+ 1068+ free_newinfo_counters_untrans_unlock: 1069+ up(&arpt_mutex); 1070+ free_newinfo_counters_untrans: 1071+ ARPT_ENTRY_ITERATE(newinfo->entries, newinfo->size, cleanup_entry, NULL); 1072+ free_newinfo_counters: 1073+ vfree(counters); 1074+ free_newinfo: 1075+ vfree(newinfo); 1076+ return ret; 1077+} 1078+ 1079+/* We're lazy, and add to the first CPU; overflow works its fey magic 1080+ * and everything is OK. 1081+ */ 1082+static inline int add_counter_to_entry(struct arpt_entry *e, 1083+ const struct arpt_counters addme[], 1084+ unsigned int *i) 1085+{ 1086+ 1087+ ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt); 1088+ 1089+ (*i)++; 1090+ return 0; 1091+} 1092+ 1093+static int do_add_counters(void *user, unsigned int len) 1094+{ 1095+ unsigned int i; 1096+ struct arpt_counters_info tmp, *paddc; 1097+ struct arpt_table *t; 1098+ int ret; 1099+ 1100+ if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) 1101+ return -EFAULT; 1102+ 1103+ if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct arpt_counters)) 1104+ return -EINVAL; 1105+ 1106+ paddc = vmalloc(len); 1107+ if (!paddc) 1108+ return -ENOMEM; 1109+ 1110+ if (copy_from_user(paddc, user, len) != 0) { 1111+ ret = -EFAULT; 1112+ goto free; 1113+ } 1114+ 1115+ t = find_table_lock(tmp.name, &ret, &arpt_mutex); 1116+ if (!t) 1117+ goto free; 1118+ 1119+ write_lock_bh(&t->lock); 1120+ if (t->private->number != paddc->num_counters) { 1121+ ret = -EINVAL; 1122+ goto unlock_up_free; 1123+ } 1124+ 1125+ i = 0; 1126+ ARPT_ENTRY_ITERATE(t->private->entries, 1127+ t->private->size, 1128+ add_counter_to_entry, 1129+ paddc->counters, 1130+ &i); 1131+ unlock_up_free: 1132+ write_unlock_bh(&t->lock); 1133+ up(&arpt_mutex); 1134+ free: 1135+ vfree(paddc); 1136+ 1137+ return ret; 1138+} 1139+ 1140+static int do_arpt_set_ctl(struct sock *sk, int cmd, void *user, unsigned int len) 1141+{ 1142+ int ret; 1143+ 1144+ if (!capable(CAP_NET_ADMIN)) 1145+ return -EPERM; 1146+ 1147+ switch (cmd) { 1148+ case ARPT_SO_SET_REPLACE: 1149+ ret = do_replace(user, len); 1150+ break; 1151+ 1152+ case ARPT_SO_SET_ADD_COUNTERS: 1153+ ret = do_add_counters(user, len); 1154+ break; 1155+ 1156+ default: 1157+ duprintf("do_arpt_set_ctl: unknown request %i\n", cmd); 1158+ ret = -EINVAL; 1159+ } 1160+ 1161+ return ret; 1162+} 1163+ 1164+static int do_arpt_get_ctl(struct sock *sk, int cmd, void *user, int *len) 1165+{ 1166+ int ret; 1167+ 1168+ if (!capable(CAP_NET_ADMIN)) 1169+ return -EPERM; 1170+ 1171+ switch (cmd) { 1172+ case ARPT_SO_GET_INFO: { 1173+ char name[ARPT_TABLE_MAXNAMELEN]; 1174+ struct arpt_table *t; 1175+ 1176+ if (*len != sizeof(struct arpt_getinfo)) { 1177+ duprintf("length %u != %Zu\n", *len, 1178+ sizeof(struct arpt_getinfo)); 1179+ ret = -EINVAL; 1180+ break; 1181+ } 1182+ 1183+ if (copy_from_user(name, user, sizeof(name)) != 0) { 1184+ ret = -EFAULT; 1185+ break; 1186+ } 1187+ name[ARPT_TABLE_MAXNAMELEN-1] = '\0'; 1188+ t = find_table_lock(name, &ret, &arpt_mutex); 1189+ if (t) { 1190+ struct arpt_getinfo info; 1191+ 1192+ info.valid_hooks = t->valid_hooks; 1193+ memcpy(info.hook_entry, t->private->hook_entry, 1194+ sizeof(info.hook_entry)); 1195+ memcpy(info.underflow, t->private->underflow, 1196+ sizeof(info.underflow)); 1197+ info.num_entries = t->private->number; 1198+ info.size = t->private->size; 1199+ strcpy(info.name, name); 1200+ 1201+ if (copy_to_user(user, &info, *len) != 0) 1202+ ret = -EFAULT; 1203+ else 1204+ ret = 0; 1205+ 1206+ up(&arpt_mutex); 1207+ } 1208+ } 1209+ break; 1210+ 1211+ case ARPT_SO_GET_ENTRIES: { 1212+ struct arpt_get_entries get; 1213+ 1214+ if (*len < sizeof(get)) { 1215+ duprintf("get_entries: %u < %Zu\n", *len, sizeof(get)); 1216+ ret = -EINVAL; 1217+ } else if (copy_from_user(&get, user, sizeof(get)) != 0) { 1218+ ret = -EFAULT; 1219+ } else if (*len != sizeof(struct arpt_get_entries) + get.size) { 1220+ duprintf("get_entries: %u != %Zu\n", *len, 1221+ sizeof(struct arpt_get_entries) + get.size); 1222+ ret = -EINVAL; 1223+ } else 1224+ ret = get_entries(&get, user); 1225+ break; 1226+ } 1227+ 1228+ default: 1229+ duprintf("do_arpt_get_ctl: unknown request %i\n", cmd); 1230+ ret = -EINVAL; 1231+ } 1232+ 1233+ return ret; 1234+} 1235+ 1236+/* Registration hooks for targets. */ 1237+int arpt_register_target(struct arpt_target *target) 1238+{ 1239+ int ret; 1240+ 1241+ MOD_INC_USE_COUNT; 1242+ ret = down_interruptible(&arpt_mutex); 1243+ if (ret != 0) { 1244+ MOD_DEC_USE_COUNT; 1245+ return ret; 1246+ } 1247+ if (!list_named_insert(&arpt_target, target)) { 1248+ duprintf("arpt_register_target: `%s' already in list!\n", 1249+ target->name); 1250+ ret = -EINVAL; 1251+ MOD_DEC_USE_COUNT; 1252+ } 1253+ up(&arpt_mutex); 1254+ return ret; 1255+} 1256+ 1257+void arpt_unregister_target(struct arpt_target *target) 1258+{ 1259+ down(&arpt_mutex); 1260+ LIST_DELETE(&arpt_target, target); 1261+ up(&arpt_mutex); 1262+ MOD_DEC_USE_COUNT; 1263+} 1264+ 1265+int arpt_register_table(struct arpt_table *table) 1266+{ 1267+ int ret; 1268+ struct arpt_table_info *newinfo; 1269+ static struct arpt_table_info bootstrap 1270+ = { 0, 0, 0, { 0 }, { 0 }, { } }; 1271+ 1272+ MOD_INC_USE_COUNT; 1273+ newinfo = vmalloc(sizeof(struct arpt_table_info) 1274+ + SMP_ALIGN(table->table->size) * smp_num_cpus); 1275+ if (!newinfo) { 1276+ ret = -ENOMEM; 1277+ MOD_DEC_USE_COUNT; 1278+ return ret; 1279+ } 1280+ memcpy(newinfo->entries, table->table->entries, table->table->size); 1281+ 1282+ ret = translate_table(table->name, table->valid_hooks, 1283+ newinfo, table->table->size, 1284+ table->table->num_entries, 1285+ table->table->hook_entry, 1286+ table->table->underflow); 1287+ duprintf("arpt_register_table: translate table gives %d\n", ret); 1288+ if (ret != 0) { 1289+ vfree(newinfo); 1290+ MOD_DEC_USE_COUNT; 1291+ return ret; 1292+ } 1293+ 1294+ ret = down_interruptible(&arpt_mutex); 1295+ if (ret != 0) { 1296+ vfree(newinfo); 1297+ MOD_DEC_USE_COUNT; 1298+ return ret; 1299+ } 1300+ 1301+ /* Don't autoload: we'd eat our tail... */ 1302+ if (list_named_find(&arpt_tables, table->name)) { 1303+ ret = -EEXIST; 1304+ goto free_unlock; 1305+ } 1306+ 1307+ /* Simplifies replace_table code. */ 1308+ table->private = &bootstrap; 1309+ if (!replace_table(table, 0, newinfo, &ret)) 1310+ goto free_unlock; 1311+ 1312+ duprintf("table->private->number = %u\n", 1313+ table->private->number); 1314+ 1315+ /* save number of initial entries */ 1316+ table->private->initial_entries = table->private->number; 1317+ 1318+ table->lock = RW_LOCK_UNLOCKED; 1319+ list_prepend(&arpt_tables, table); 1320+ 1321+ unlock: 1322+ up(&arpt_mutex); 1323+ return ret; 1324+ 1325+ free_unlock: 1326+ vfree(newinfo); 1327+ MOD_DEC_USE_COUNT; 1328+ goto unlock; 1329+} 1330+ 1331+void arpt_unregister_table(struct arpt_table *table) 1332+{ 1333+ down(&arpt_mutex); 1334+ LIST_DELETE(&arpt_tables, table); 1335+ up(&arpt_mutex); 1336+ 1337+ /* Decrease module usage counts and free resources */ 1338+ ARPT_ENTRY_ITERATE(table->private->entries, table->private->size, 1339+ cleanup_entry, NULL); 1340+ vfree(table->private); 1341+ MOD_DEC_USE_COUNT; 1342+} 1343+ 1344+/* The built-in targets: standard (NULL) and error. */ 1345+static struct arpt_target arpt_standard_target 1346+= { { NULL, NULL }, ARPT_STANDARD_TARGET, NULL, NULL, NULL }; 1347+static struct arpt_target arpt_error_target 1348+= { { NULL, NULL }, ARPT_ERROR_TARGET, arpt_error, NULL, NULL }; 1349+ 1350+static struct nf_sockopt_ops arpt_sockopts 1351+= { { NULL, NULL }, PF_INET, ARPT_BASE_CTL, ARPT_SO_SET_MAX+1, do_arpt_set_ctl, 1352+ ARPT_BASE_CTL, ARPT_SO_GET_MAX+1, do_arpt_get_ctl, 0, NULL }; 1353+ 1354+#ifdef CONFIG_PROC_FS 1355+static inline int print_name(const struct arpt_table *t, 1356+ off_t start_offset, char *buffer, int length, 1357+ off_t *pos, unsigned int *count) 1358+{ 1359+ if ((*count)++ >= start_offset) { 1360+ unsigned int namelen; 1361+ 1362+ namelen = sprintf(buffer + *pos, "%s\n", t->name); 1363+ if (*pos + namelen > length) { 1364+ /* Stop iterating */ 1365+ return 1; 1366+ } 1367+ *pos += namelen; 1368+ } 1369+ return 0; 1370+} 1371+ 1372+static int arpt_get_tables(char *buffer, char **start, off_t offset, int length) 1373+{ 1374+ off_t pos = 0; 1375+ unsigned int count = 0; 1376+ 1377+ if (down_interruptible(&arpt_mutex) != 0) 1378+ return 0; 1379+ 1380+ LIST_FIND(&arpt_tables, print_name, struct arpt_table *, 1381+ offset, buffer, length, &pos, &count); 1382+ 1383+ up(&arpt_mutex); 1384+ 1385+ /* `start' hack - see fs/proc/generic.c line ~105 */ 1386+ *start=(char *)((unsigned long)count-offset); 1387+ return pos; 1388+} 1389+#endif /*CONFIG_PROC_FS*/ 1390+ 1391+static int __init init(void) 1392+{ 1393+ int ret; 1394+ 1395+ /* Noone else will be downing sem now, so we won't sleep */ 1396+ down(&arpt_mutex); 1397+ list_append(&arpt_target, &arpt_standard_target); 1398+ list_append(&arpt_target, &arpt_error_target); 1399+ up(&arpt_mutex); 1400+ 1401+ /* Register setsockopt */ 1402+ ret = nf_register_sockopt(&arpt_sockopts); 1403+ if (ret < 0) { 1404+ duprintf("Unable to register sockopts.\n"); 1405+ return ret; 1406+ } 1407+ 1408+#ifdef CONFIG_PROC_FS 1409+ { 1410+ struct proc_dir_entry *proc; 1411+ 1412+ proc = proc_net_create("arp_tables_names", 0, arpt_get_tables); 1413+ if (!proc) { 1414+ nf_unregister_sockopt(&arpt_sockopts); 1415+ return -ENOMEM; 1416+ } 1417+ proc->owner = THIS_MODULE; 1418+ } 1419+#endif 1420+ 1421+ printk("arp_tables: (C) 2002 David S. Miller\n"); 1422+ return 0; 1423+} 1424+ 1425+static void __exit fini(void) 1426+{ 1427+ nf_unregister_sockopt(&arpt_sockopts); 1428+#ifdef CONFIG_PROC_FS 1429+ proc_net_remove("arp_tables_names"); 1430+#endif 1431+} 1432+ 1433+EXPORT_SYMBOL(arpt_register_table); 1434+EXPORT_SYMBOL(arpt_unregister_table); 1435+EXPORT_SYMBOL(arpt_do_table); 1436+EXPORT_SYMBOL(arpt_register_target); 1437+EXPORT_SYMBOL(arpt_unregister_target); 1438+ 1439+module_init(init); 1440+module_exit(fini); 1441+MODULE_LICENSE("GPL"); 1442diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.18-plain/net/ipv4/netfilter/arptable_filter.c linux-2.4.19-plain/net/ipv4/netfilter/arptable_filter.c 1443--- linux-2.4.18-plain/net/ipv4/netfilter/arptable_filter.c Thu Jan 1 01:00:00 1970 1444+++ linux-2.4.19-plain/net/ipv4/netfilter/arptable_filter.c Sat Aug 3 02:39:46 2002 1445@@ -0,0 +1,174 @@ 1446+/* 1447+ * Filtering ARP tables module. 1448+ * 1449+ * Copyright (C) 2002 David S. Miller (davem@redhat.com) 1450+ * 1451+ */ 1452+ 1453+#include <linux/module.h> 1454+#include <linux/netfilter_arp/arp_tables.h> 1455+ 1456+#define FILTER_VALID_HOOKS ((1 << NF_ARP_IN) | (1 << NF_ARP_OUT)) 1457+ 1458+/* Standard entry. */ 1459+struct arpt_standard 1460+{ 1461+ struct arpt_entry entry; 1462+ struct arpt_standard_target target; 1463+}; 1464+ 1465+struct arpt_error_target 1466+{ 1467+ struct arpt_entry_target target; 1468+ char errorname[ARPT_FUNCTION_MAXNAMELEN]; 1469+}; 1470+ 1471+struct arpt_error 1472+{ 1473+ struct arpt_entry entry; 1474+ struct arpt_error_target target; 1475+}; 1476+ 1477+static struct 1478+{ 1479+ struct arpt_replace repl; 1480+ struct arpt_standard entries[2]; 1481+ struct arpt_error term; 1482+} initial_table __initdata 1483+= { { "filter", FILTER_VALID_HOOKS, 3, 1484+ sizeof(struct arpt_standard) * 2 + sizeof(struct arpt_error), 1485+ { [NF_ARP_IN] 0, 1486+ [NF_ARP_OUT] sizeof(struct arpt_standard) }, 1487+ { [NF_ARP_IN] 0, 1488+ [NF_ARP_OUT] sizeof(struct arpt_standard), }, 1489+ 0, NULL, { } }, 1490+ { 1491+ /* ARP_IN */ 1492+ { 1493+ { 1494+ { 1495+ { 0 }, { 0 }, { 0 }, { 0 }, 1496+ 0, 0, 1497+ { { 0, }, { 0, } }, 1498+ { { 0, }, { 0, } }, 1499+ 0, 0, 1500+ 0, 0, 1501+ 0, 0, 1502+ "", "", { 0 }, { 0 }, 1503+ 0, 0 1504+ }, 1505+ sizeof(struct arpt_entry), 1506+ sizeof(struct arpt_standard), 1507+ 0, 1508+ { 0, 0 }, { } }, 1509+ { { { { ARPT_ALIGN(sizeof(struct arpt_standard_target)), "" } }, { } }, 1510+ -NF_ACCEPT - 1 } 1511+ }, 1512+ /* ARP_OUT */ 1513+ { 1514+ { 1515+ { 1516+ { 0 }, { 0 }, { 0 }, { 0 }, 1517+ 0, 0, 1518+ { { 0, }, { 0, } }, 1519+ { { 0, }, { 0, } }, 1520+ 0, 0, 1521+ 0, 0, 1522+ 0, 0, 1523+ "", "", { 0 }, { 0 }, 1524+ 0, 0 1525+ }, 1526+ sizeof(struct arpt_entry), 1527+ sizeof(struct arpt_standard), 1528+ 0, 1529+ { 0, 0 }, { } }, 1530+ { { { { ARPT_ALIGN(sizeof(struct arpt_standard_target)), "" } }, { } }, 1531+ -NF_ACCEPT - 1 } 1532+ } 1533+ }, 1534+ /* ERROR */ 1535+ { 1536+ { 1537+ { 1538+ { 0 }, { 0 }, { 0 }, { 0 }, 1539+ 0, 0, 1540+ { { 0, }, { 0, } }, 1541+ { { 0, }, { 0, } }, 1542+ 0, 0, 1543+ 0, 0, 1544+ 0, 0, 1545+ "", "", { 0 }, { 0 }, 1546+ 0, 0 1547+ }, 1548+ sizeof(struct arpt_entry), 1549+ sizeof(struct arpt_error), 1550+ 0, 1551+ { 0, 0 }, { } }, 1552+ { { { { ARPT_ALIGN(sizeof(struct arpt_error_target)), ARPT_ERROR_TARGET } }, 1553+ { } }, 1554+ "ERROR" 1555+ } 1556+ } 1557+}; 1558+ 1559+static struct arpt_table packet_filter 1560+= { { NULL, NULL }, "filter", &initial_table.repl, 1561+ FILTER_VALID_HOOKS, RW_LOCK_UNLOCKED, NULL, THIS_MODULE }; 1562+ 1563+/* The work comes in here from netfilter.c */ 1564+static unsigned int arpt_hook(unsigned int hook, 1565+ struct sk_buff **pskb, 1566+ const struct net_device *in, 1567+ const struct net_device *out, 1568+ int (*okfn)(struct sk_buff *)) 1569+{ 1570+ return arpt_do_table(pskb, hook, in, out, &packet_filter, NULL); 1571+} 1572+ 1573+static struct nf_hook_ops arpt_ops[] 1574+= { { { NULL, NULL }, arpt_hook, NF_ARP, NF_ARP_IN, 0 }, 1575+ { { NULL, NULL }, arpt_hook, NF_ARP, NF_ARP_OUT, 0 } 1576+}; 1577+ 1578+static int __init init(void) 1579+{ 1580+ int ret; 1581+ 1582+ /* Register table */ 1583+ ret = arpt_register_table(&packet_filter); 1584+ if (ret < 0) 1585+ return ret; 1586+ 1587+ /* Register hooks */ 1588+ ret = nf_register_hook(&arpt_ops[0]); 1589+ if (ret < 0) 1590+ goto cleanup_table; 1591+ 1592+ ret = nf_register_hook(&arpt_ops[1]); 1593+ if (ret < 0) 1594+ goto cleanup_hook0; 1595+ 1596+ return ret; 1597+ 1598+cleanup_hook0: 1599+ nf_unregister_hook(&arpt_ops[0]); 1600+ 1601+cleanup_table: 1602+ arpt_unregister_table(&packet_filter); 1603+ 1604+ return ret; 1605+} 1606+ 1607+static void __exit fini(void) 1608+{ 1609+ unsigned int i; 1610+ 1611+ for (i = 0; i < sizeof(arpt_ops)/sizeof(struct nf_hook_ops); i++) 1612+ nf_unregister_hook(&arpt_ops[i]); 1613+ 1614+ arpt_unregister_table(&packet_filter); 1615+} 1616+ 1617+module_init(init); 1618+module_exit(fini); 1619+MODULE_LICENSE("GPL"); 1620diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.18-plain/net/ipv4/netfilter/ip_conntrack_core.c linux-2.4.19-plain/net/ipv4/netfilter/ip_conntrack_core.c 1621--- linux-2.4.18-plain/net/ipv4/netfilter/ip_conntrack_core.c Tue Aug 7 17:30:50 2001 1622+++ linux-2.4.19-plain/net/ipv4/netfilter/ip_conntrack_core.c Sat Aug 3 02:39:46 2002 1623@@ -175,6 +175,7 @@ 1624 destroy_conntrack(struct nf_conntrack *nfct) 1625 { 1626 struct ip_conntrack *ct = (struct ip_conntrack *)nfct; 1627+ struct ip_conntrack_protocol *proto; 1628 1629 IP_NF_ASSERT(atomic_read(&nfct->use) == 0); 1630 IP_NF_ASSERT(!timer_pending(&ct->timeout)); 1631@@ -182,6 +183,13 @@ 1632 if (ct->master.master) 1633 nf_conntrack_put(&ct->master); 1634 1635+ /* To make sure we don't get any weird locking issues here: 1636+ * destroy_conntrack() MUST NOT be called with a write lock 1637+ * to ip_conntrack_lock!!! -HW */ 1638+ proto = find_proto(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.protonum); 1639+ if (proto && proto->destroy) 1640+ proto->destroy(ct); 1641+ 1642 if (ip_conntrack_destroyed) 1643 ip_conntrack_destroyed(ct); 1644 kmem_cache_free(ip_conntrack_cachep, ct); 1645@@ -489,9 +497,9 @@ 1646 /* Try dropping from random chain, or else from the 1647 chain about to put into (in case they're trying to 1648 bomb one hash chain). */ 1649- if (drop_next >= ip_conntrack_htable_size) 1650- drop_next = 0; 1651- if (!early_drop(&ip_conntrack_hash[drop_next++]) 1652+ unsigned int next = (drop_next++)%ip_conntrack_htable_size; 1653+ 1654+ if (!early_drop(&ip_conntrack_hash[next]) 1655 && !early_drop(&ip_conntrack_hash[hash])) { 1656 if (net_ratelimit()) 1657 printk(KERN_WARNING 1658diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.18-plain/net/ipv4/netfilter/ip_conntrack_proto_generic.c linux-2.4.19-plain/net/ipv4/netfilter/ip_conntrack_proto_generic.c 1659--- linux-2.4.18-plain/net/ipv4/netfilter/ip_conntrack_proto_generic.c Fri Apr 27 23:15:01 2001 1660+++ linux-2.4.19-plain/net/ipv4/netfilter/ip_conntrack_proto_generic.c Sat Aug 3 02:39:46 2002 1661@@ -57,5 +57,5 @@ 1662 struct ip_conntrack_protocol ip_conntrack_generic_protocol 1663 = { { NULL, NULL }, 0, "unknown", 1664 generic_pkt_to_tuple, generic_invert_tuple, generic_print_tuple, 1665- generic_print_conntrack, established, new, NULL }; 1666+ generic_print_conntrack, established, new, NULL, NULL }; 1667 1668diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.18-plain/net/ipv4/netfilter/ip_conntrack_proto_icmp.c linux-2.4.19-plain/net/ipv4/netfilter/ip_conntrack_proto_icmp.c 1669--- linux-2.4.18-plain/net/ipv4/netfilter/ip_conntrack_proto_icmp.c Fri Apr 27 23:15:01 2001 1670+++ linux-2.4.19-plain/net/ipv4/netfilter/ip_conntrack_proto_icmp.c Sat Aug 3 02:39:46 2002 1671@@ -113,4 +113,4 @@ 1672 struct ip_conntrack_protocol ip_conntrack_protocol_icmp 1673 = { { NULL, NULL }, IPPROTO_ICMP, "icmp", 1674 icmp_pkt_to_tuple, icmp_invert_tuple, icmp_print_tuple, 1675- icmp_print_conntrack, icmp_packet, icmp_new, NULL }; 1676+ icmp_print_conntrack, icmp_packet, icmp_new, NULL, NULL }; 1677diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.18-plain/net/ipv4/netfilter/ip_conntrack_proto_tcp.c linux-2.4.19-plain/net/ipv4/netfilter/ip_conntrack_proto_tcp.c 1678--- linux-2.4.18-plain/net/ipv4/netfilter/ip_conntrack_proto_tcp.c Fri Apr 27 23:15:01 2001 1679+++ linux-2.4.19-plain/net/ipv4/netfilter/ip_conntrack_proto_tcp.c Sat Aug 3 02:39:46 2002 1680@@ -230,4 +230,4 @@ 1681 struct ip_conntrack_protocol ip_conntrack_protocol_tcp 1682 = { { NULL, NULL }, IPPROTO_TCP, "tcp", 1683 tcp_pkt_to_tuple, tcp_invert_tuple, tcp_print_tuple, tcp_print_conntrack, 1684- tcp_packet, tcp_new, NULL }; 1685+ tcp_packet, tcp_new, NULL, NULL }; 1686diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.18-plain/net/ipv4/netfilter/ip_conntrack_proto_udp.c linux-2.4.19-plain/net/ipv4/netfilter/ip_conntrack_proto_udp.c 1687--- linux-2.4.18-plain/net/ipv4/netfilter/ip_conntrack_proto_udp.c Fri Apr 27 23:15:01 2001 1688+++ linux-2.4.19-plain/net/ipv4/netfilter/ip_conntrack_proto_udp.c Sat Aug 3 02:39:46 2002 1689@@ -71,4 +71,4 @@ 1690 struct ip_conntrack_protocol ip_conntrack_protocol_udp 1691 = { { NULL, NULL }, IPPROTO_UDP, "udp", 1692 udp_pkt_to_tuple, udp_invert_tuple, udp_print_tuple, udp_print_conntrack, 1693- udp_packet, udp_new, NULL }; 1694+ udp_packet, udp_new, NULL, NULL }; 1695diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.18-plain/net/ipv4/netfilter/ip_conntrack_standalone.c linux-2.4.19-plain/net/ipv4/netfilter/ip_conntrack_standalone.c 1696--- linux-2.4.18-plain/net/ipv4/netfilter/ip_conntrack_standalone.c Mon Feb 25 20:38:14 2002 1697+++ linux-2.4.19-plain/net/ipv4/netfilter/ip_conntrack_standalone.c Sat Aug 3 02:39:46 2002 1698@@ -15,6 +15,7 @@ 1699 #include <linux/skbuff.h> 1700 #include <linux/proc_fs.h> 1701 #include <linux/version.h> 1702+#include <linux/brlock.h> 1703 #include <net/checksum.h> 1704 1705 #define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_conntrack_lock) 1706@@ -35,6 +36,11 @@ 1707 struct module *ip_conntrack_module = THIS_MODULE; 1708 MODULE_LICENSE("GPL"); 1709 1710+static int kill_proto(const struct ip_conntrack *i, void *data) 1711+{ 1712+ return (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == 1713+ *((u_int8_t *) data)); 1714+} 1715 1716 static unsigned int 1717 print_tuple(char *buffer, const struct ip_conntrack_tuple *tuple, 1718@@ -304,12 +310,24 @@ 1719 return ret; 1720 } 1721 1722- 1723-#if 0 1724 void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto) 1725 { 1726+ WRITE_LOCK(&ip_conntrack_lock); 1727+ 1728+ /* find_proto() returns proto_generic in case there is no protocol 1729+ * helper. So this should be enough - HW */ 1730+ LIST_DELETE(&protocol_list, proto); 1731+ WRITE_UNLOCK(&ip_conntrack_lock); 1732+ 1733+ /* Somebody could be still looking at the proto in bh. */ 1734+ br_write_lock_bh(BR_NETPROTO_LOCK); 1735+ br_write_unlock_bh(BR_NETPROTO_LOCK); 1736+ 1737+ /* Remove all contrack entries for this protocol */ 1738+ ip_ct_selective_cleanup(kill_proto, &proto->proto); 1739+ 1740+ MOD_DEC_USE_COUNT; 1741 } 1742-#endif 1743 1744 static int __init init(void) 1745 { 1746@@ -325,6 +343,7 @@ 1747 module_exit(fini); 1748 1749 EXPORT_SYMBOL(ip_conntrack_protocol_register); 1750+EXPORT_SYMBOL(ip_conntrack_protocol_unregister); 1751 EXPORT_SYMBOL(invert_tuplepr); 1752 EXPORT_SYMBOL(ip_conntrack_alter_reply); 1753 EXPORT_SYMBOL(ip_conntrack_destroyed); 1754@@ -335,6 +354,7 @@ 1755 EXPORT_SYMBOL(ip_ct_selective_cleanup); 1756 EXPORT_SYMBOL(ip_ct_refresh); 1757 EXPORT_SYMBOL(ip_conntrack_expect_related); 1758+EXPORT_SYMBOL(ip_conntrack_unexpect_related); 1759 EXPORT_SYMBOL(ip_conntrack_tuple_taken); 1760 EXPORT_SYMBOL(ip_ct_gather_frags); 1761 EXPORT_SYMBOL(ip_conntrack_htable_size); 1762diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.18-plain/net/ipv4/netfilter/ip_fw_compat_redir.c linux-2.4.19-plain/net/ipv4/netfilter/ip_fw_compat_redir.c 1763--- linux-2.4.18-plain/net/ipv4/netfilter/ip_fw_compat_redir.c Mon Feb 25 20:38:14 2002 1764+++ linux-2.4.19-plain/net/ipv4/netfilter/ip_fw_compat_redir.c Sat Aug 3 02:39:46 2002 1765@@ -43,7 +43,7 @@ 1766 netplay... */ \ 1767 printk("ASSERT: %s:%i(%s)\n", \ 1768 __FILE__, __LINE__, __FUNCTION__); \ 1769-} while(0); 1770+} while(0) 1771 #else 1772 #define IP_NF_ASSERT(x) 1773 #endif 1774diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.18-plain/net/ipv4/netfilter/ip_nat_core.c linux-2.4.19-plain/net/ipv4/netfilter/ip_nat_core.c 1775--- linux-2.4.18-plain/net/ipv4/netfilter/ip_nat_core.c Fri Dec 21 18:42:05 2001 1776+++ linux-2.4.19-plain/net/ipv4/netfilter/ip_nat_core.c Sat Aug 3 02:39:46 2002 1777@@ -314,6 +314,7 @@ 1778 * do_extra_mangle last time. */ 1779 *other_ipp = saved_ip; 1780 1781+#ifdef CONFIG_IP_NF_NAT_LOCAL 1782 if (hooknum == NF_IP_LOCAL_OUT 1783 && *var_ipp != orig_dstip 1784 && !do_extra_mangle(*var_ipp, other_ipp)) { 1785@@ -324,6 +325,7 @@ 1786 * anyway. */ 1787 continue; 1788 } 1789+#endif 1790 1791 /* Count how many others map onto this. */ 1792 score = count_maps(tuple->src.ip, tuple->dst.ip, 1793@@ -367,11 +369,13 @@ 1794 else { 1795 /* Only do extra mangle when required (breaks 1796 socket binding) */ 1797+#ifdef CONFIG_IP_NF_NAT_LOCAL 1798 if (tuple->dst.ip != mr->range[0].min_ip 1799 && hooknum == NF_IP_LOCAL_OUT 1800 && !do_extra_mangle(mr->range[0].min_ip, 1801 &tuple->src.ip)) 1802 return NULL; 1803+#endif 1804 tuple->dst.ip = mr->range[0].min_ip; 1805 } 1806 } 1807@@ -494,7 +498,10 @@ 1808 static unsigned int opposite_hook[NF_IP_NUMHOOKS] 1809 = { [NF_IP_PRE_ROUTING] = NF_IP_POST_ROUTING, 1810 [NF_IP_POST_ROUTING] = NF_IP_PRE_ROUTING, 1811- [NF_IP_LOCAL_OUT] = NF_IP_POST_ROUTING 1812+#ifdef CONFIG_IP_NF_NAT_LOCAL 1813+ [NF_IP_LOCAL_OUT] = NF_IP_LOCAL_IN, 1814+ [NF_IP_LOCAL_IN] = NF_IP_LOCAL_OUT, 1815+#endif 1816 }; 1817 1818 unsigned int 1819diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.18-plain/net/ipv4/netfilter/ip_nat_rule.c linux-2.4.19-plain/net/ipv4/netfilter/ip_nat_rule.c 1820--- linux-2.4.18-plain/net/ipv4/netfilter/ip_nat_rule.c Mon Feb 25 20:38:14 2002 1821+++ linux-2.4.19-plain/net/ipv4/netfilter/ip_nat_rule.c Sat Aug 3 02:39:46 2002 1822@@ -140,8 +140,12 @@ 1823 struct ip_conntrack *ct; 1824 enum ip_conntrack_info ctinfo; 1825 1826+#ifdef CONFIG_IP_NF_NAT_LOCAL 1827 IP_NF_ASSERT(hooknum == NF_IP_PRE_ROUTING 1828 || hooknum == NF_IP_LOCAL_OUT); 1829+#else 1830+ IP_NF_ASSERT(hooknum == NF_IP_PRE_ROUTING); 1831+#endif 1832 1833 ct = ip_conntrack_get(*pskb, &ctinfo); 1834 1835@@ -210,7 +214,7 @@ 1836 1837 /* Only allow these for NAT. */ 1838 if (strcmp(tablename, "nat") != 0) { 1839- DEBUGP("SNAT: wrong table %s\n", tablename); 1840+ DEBUGP("DNAT: wrong table %s\n", tablename); 1841 return 0; 1842 } 1843 1844@@ -218,6 +222,14 @@ 1845 DEBUGP("DNAT: hook mask 0x%x bad\n", hook_mask); 1846 return 0; 1847 } 1848+ 1849+#ifndef CONFIG_IP_NF_NAT_LOCAL 1850+ if (hook_mask & (1 << NF_IP_LOCAL_OUT)) { 1851+ DEBUGP("DNAT: CONFIG_IP_NF_NAT_LOCAL not enabled\n"); 1852+ return 0; 1853+ } 1854+#endif 1855+ 1856 return 1; 1857 } 1858 1859diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.18-plain/net/ipv4/netfilter/ip_nat_standalone.c linux-2.4.19-plain/net/ipv4/netfilter/ip_nat_standalone.c 1860--- linux-2.4.18-plain/net/ipv4/netfilter/ip_nat_standalone.c Mon Feb 25 20:38:14 2002 1861+++ linux-2.4.19-plain/net/ipv4/netfilter/ip_nat_standalone.c Sat Aug 3 02:39:46 2002 1862@@ -41,7 +41,8 @@ 1863 #define HOOKNAME(hooknum) ((hooknum) == NF_IP_POST_ROUTING ? "POST_ROUTING" \ 1864 : ((hooknum) == NF_IP_PRE_ROUTING ? "PRE_ROUTING" \ 1865 : ((hooknum) == NF_IP_LOCAL_OUT ? "LOCAL_OUT" \ 1866- : "*ERROR*"))) 1867+ : ((hooknum) == NF_IP_LOCAL_IN ? "LOCAL_IN" \ 1868+ : "*ERROR*"))) 1869 1870 static unsigned int 1871 ip_nat_fn(unsigned int hooknum, 1872@@ -94,6 +95,12 @@ 1873 } 1874 /* Fall thru... (Only ICMPs can be IP_CT_IS_REPLY) */ 1875 case IP_CT_NEW: 1876+#ifdef CONFIG_IP_NF_NAT_LOCAL 1877+ /* LOCAL_IN hook doesn't have a chain and thus doesn't care 1878+ * about new packets -HW */ 1879+ if (hooknum == NF_IP_LOCAL_IN) 1880+ return NF_ACCEPT; 1881+#endif 1882 info = &ct->nat.info; 1883 1884 WRITE_LOCK(&ip_nat_lock); 1885@@ -204,6 +211,11 @@ 1886 static struct nf_hook_ops ip_nat_local_out_ops 1887 = { { NULL, NULL }, ip_nat_local_fn, PF_INET, NF_IP_LOCAL_OUT, NF_IP_PRI_NAT_DST }; 1888 1889+#ifdef CONFIG_IP_NF_NAT_LOCAL 1890+static struct nf_hook_ops ip_nat_local_in_ops 1891+= { { NULL, NULL }, ip_nat_fn, PF_INET, NF_IP_LOCAL_IN, NF_IP_PRI_NAT_SRC }; 1892+#endif 1893+ 1894 /* Protocol registration. */ 1895 int ip_nat_protocol_register(struct ip_nat_protocol *proto) 1896 { 1897@@ -272,6 +284,13 @@ 1898 printk("ip_nat_init: can't register local out hook.\n"); 1899 goto cleanup_outops; 1900 } 1901+#ifdef CONFIG_IP_NF_NAT_LOCAL 1902+ ret = nf_register_hook(&ip_nat_local_in_ops); 1903+ if (ret < 0) { 1904+ printk("ip_nat_init: can't register local in hook.\n"); 1905+ goto cleanup_localoutops; 1906+ } 1907+#endif 1908 if (ip_conntrack_module) 1909 __MOD_INC_USE_COUNT(ip_conntrack_module); 1910 return ret; 1911@@ -279,6 +298,10 @@ 1912 cleanup: 1913 if (ip_conntrack_module) 1914 __MOD_DEC_USE_COUNT(ip_conntrack_module); 1915+#ifdef CONFIG_IP_NF_NAT_LOCAL 1916+ nf_unregister_hook(&ip_nat_local_in_ops); 1917+ cleanup_localoutops: 1918+#endif 1919 nf_unregister_hook(&ip_nat_local_out_ops); 1920 cleanup_outops: 1921 nf_unregister_hook(&ip_nat_out_ops); 1922@@ -307,6 +330,8 @@ 1923 module_exit(fini); 1924 1925 EXPORT_SYMBOL(ip_nat_setup_info); 1926+EXPORT_SYMBOL(ip_nat_protocol_register); 1927+EXPORT_SYMBOL(ip_nat_protocol_unregister); 1928 EXPORT_SYMBOL(ip_nat_helper_register); 1929 EXPORT_SYMBOL(ip_nat_helper_unregister); 1930 EXPORT_SYMBOL(ip_nat_expect_register); 1931@@ -315,4 +340,5 @@ 1932 EXPORT_SYMBOL(ip_nat_mangle_tcp_packet); 1933 EXPORT_SYMBOL(ip_nat_seq_adjust); 1934 EXPORT_SYMBOL(ip_nat_delete_sack); 1935+EXPORT_SYMBOL(ip_nat_used_tuple); 1936 MODULE_LICENSE("GPL"); 1937diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.18-plain/net/ipv4/netfilter/ip_queue.c linux-2.4.19-plain/net/ipv4/netfilter/ip_queue.c 1938--- linux-2.4.18-plain/net/ipv4/netfilter/ip_queue.c Mon Feb 25 20:38:14 2002 1939+++ linux-2.4.19-plain/net/ipv4/netfilter/ip_queue.c Sat Aug 3 02:39:46 2002 1940@@ -464,7 +464,7 @@ 1941 return netlink_unicast(nfnl, skb, nlq->peer.pid, MSG_DONTWAIT); 1942 } 1943 1944-#define RCV_SKB_FAIL(err) do { netlink_ack(skb, nlh, (err)); return; } while (0); 1945+#define RCV_SKB_FAIL(err) do { netlink_ack(skb, nlh, (err)); return; } while (0) 1946 1947 static __inline__ void netlink_receive_user_skb(struct sk_buff *skb) 1948 { 1949diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.18-plain/net/ipv4/netfilter/ipchains_core.c linux-2.4.19-plain/net/ipv4/netfilter/ipchains_core.c 1950--- linux-2.4.18-plain/net/ipv4/netfilter/ipchains_core.c Mon Feb 25 20:38:14 2002 1951+++ linux-2.4.19-plain/net/ipv4/netfilter/ipchains_core.c Sat Aug 3 02:39:46 2002 1952@@ -549,7 +549,7 @@ 1953 strcpy(outskb->data+sizeof(__u32)*2, rif); 1954 memcpy(outskb->data+sizeof(__u32)*2+IFNAMSIZ, ip, 1955 len-(sizeof(__u32)*2+IFNAMSIZ)); 1956- netlink_broadcast(ipfwsk, outskb, 0, ~0, GFP_KERNEL); 1957+ netlink_broadcast(ipfwsk, outskb, 0, ~0, GFP_ATOMIC); 1958 } 1959 else { 1960 #endif 1961@@ -723,6 +723,7 @@ 1962 src_port, dst_port, 1963 count, tcpsyn)) { 1964 ret = FW_BLOCK; 1965+ cleanup(chain, 0, slot); 1966 goto out; 1967 } 1968 break; 1969diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.18-plain/net/ipv4/netfilter/ipt_REJECT.c linux-2.4.19-plain/net/ipv4/netfilter/ipt_REJECT.c 1970--- linux-2.4.18-plain/net/ipv4/netfilter/ipt_REJECT.c Sat Oct 6 17:50:28 2001 1971+++ linux-2.4.19-plain/net/ipv4/netfilter/ipt_REJECT.c Sat Aug 3 02:39:46 2002 1972@@ -39,7 +39,8 @@ 1973 struct tcphdr *otcph, *tcph; 1974 struct rtable *rt; 1975 unsigned int otcplen; 1976- u_int16_t tmp; 1977+ u_int16_t tmp_port; 1978+ u_int32_t tmp_addr; 1979 int needs_ack; 1980 1981 /* IP header checks: fragment, too short. */ 1982@@ -78,10 +79,12 @@ 1983 tcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl); 1984 1985 /* Swap source and dest */ 1986- nskb->nh.iph->daddr = xchg(&nskb->nh.iph->saddr, nskb->nh.iph->daddr); 1987- tmp = tcph->source; 1988+ tmp_addr = nskb->nh.iph->saddr; 1989+ nskb->nh.iph->saddr = nskb->nh.iph->daddr; 1990+ nskb->nh.iph->daddr = tmp_addr; 1991+ tmp_port = tcph->source; 1992 tcph->source = tcph->dest; 1993- tcph->dest = tmp; 1994+ tcph->dest = tmp_port; 1995 1996 /* Truncate to length (no data) */ 1997 tcph->doff = sizeof(struct tcphdr)/4; 1998@@ -234,11 +237,8 @@ 1999 iph->tos=tos; 2000 iph->tot_len = htons(length); 2001 2002- /* This abbreviates icmp->send->ip_build_xmit->ip_dont_fragment */ 2003- if (!ipv4_config.no_pmtu_disc 2004- && !(rt->u.dst.mxlock&(1<<RTAX_MTU))) 2005- iph->frag_off = htons(IP_DF); 2006- else iph->frag_off = 0; 2007+ /* PMTU discovery never applies to ICMP packets. */ 2008+ iph->frag_off = 0; 2009 2010 iph->ttl = MAXTTL; 2011 ip_select_ident(iph, &rt->u.dst, NULL); 2012diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.18-plain/net/ipv4/netfilter/ipt_ULOG.c linux-2.4.19-plain/net/ipv4/netfilter/ipt_ULOG.c 2013--- linux-2.4.18-plain/net/ipv4/netfilter/ipt_ULOG.c Mon Feb 25 20:38:14 2002 2014+++ linux-2.4.19-plain/net/ipv4/netfilter/ipt_ULOG.c Sat Aug 3 02:39:46 2002 2015@@ -29,7 +29,7 @@ 2016 * Specify, after how many clock ticks (intel: 100 per second) the queue 2017 * should be flushed even if it is not full yet. 2018 * 2019- * ipt_ULOG.c,v 1.15 2002/01/18 21:33:19 laforge Exp 2020+ * ipt_ULOG.c,v 1.18 2002/04/16 07:33:00 laforge Exp 2021 */ 2022 2023 #include <linux/module.h> 2024@@ -61,7 +61,7 @@ 2025 #define DEBUGP(format, args...) 2026 #endif 2027 2028-#define PRINTR(format, args...) do { if (net_ratelimit()) printk(format, ## args); } while (0); 2029+#define PRINTR(format, args...) do { if (net_ratelimit()) printk(format, ## args); } while (0) 2030 2031 MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>"); 2032 MODULE_DESCRIPTION("IP tables userspace logging module"); 2033@@ -339,10 +339,28 @@ 2034 2035 static void __exit fini(void) 2036 { 2037+ ulog_buff_t *ub; 2038+ int i; 2039+ 2040 DEBUGP("ipt_ULOG: cleanup_module\n"); 2041 2042 ipt_unregister_target(&ipt_ulog_reg); 2043 sock_release(nflognl->socket); 2044+ 2045+ /* remove pending timers and free allocated skb's */ 2046+ for (i = 0; i < ULOG_MAXNLGROUPS; i++) { 2047+ ub = &ulog_buffers[i]; 2048+ if (timer_pending(&ub->timer)) { 2049+ DEBUGP("timer was pending, deleting\n"); 2050+ del_timer(&ub->timer); 2051+ } 2052+ 2053+ if (ub->skb) { 2054+ kfree_skb(ub->skb); 2055+ ub->skb = NULL; 2056+ } 2057+ } 2058+ 2059 } 2060 2061 module_init(init); 2062diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.18-plain/net/ipv6/netfilter/ip6_queue.c linux-2.4.19-plain/net/ipv6/netfilter/ip6_queue.c 2063--- linux-2.4.18-plain/net/ipv6/netfilter/ip6_queue.c Mon Feb 25 20:38:14 2002 2064+++ linux-2.4.19-plain/net/ipv6/netfilter/ip6_queue.c Sat Aug 3 02:39:46 2002 2065@@ -518,7 +518,7 @@ 2066 return netlink_unicast(nfnl, skb, nlq6->peer.pid, MSG_DONTWAIT); 2067 } 2068 2069-#define RCV_SKB_FAIL(err) do { netlink_ack(skb, nlh, (err)); return; } while (0); 2070+#define RCV_SKB_FAIL(err) do { netlink_ack(skb, nlh, (err)); return; } while (0) 2071 2072 static __inline__ void netlink_receive_user_skb(struct sk_buff *skb) 2073 { 2074diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.18-plain/net/ipv6/netfilter/ip6_tables.c linux-2.4.19-plain/net/ipv6/netfilter/ip6_tables.c 2075--- linux-2.4.18-plain/net/ipv6/netfilter/ip6_tables.c Mon Feb 25 20:38:14 2002 2076+++ linux-2.4.19-plain/net/ipv6/netfilter/ip6_tables.c Sat Aug 3 02:39:46 2002 2077@@ -110,7 +110,7 @@ 2078 #define ADD_COUNTER(c,b,p) do { (c).bcnt += (b); (c).pcnt += (p); } while(0) 2079 2080 #ifdef CONFIG_SMP 2081-#define TABLE_OFFSET(t,p) (SMP_ALIGN((t)->size)*cpu_number_map(p)) 2082+#define TABLE_OFFSET(t,p) (SMP_ALIGN((t)->size)*(p)) 2083 #else 2084 #define TABLE_OFFSET(t,p) 0 2085 #endif 2086@@ -336,7 +336,8 @@ 2087 read_lock_bh(&table->lock); 2088 IP_NF_ASSERT(table->valid_hooks & (1 << hook)); 2089 table_base = (void *)table->private->entries 2090- + TABLE_OFFSET(table->private, smp_processor_id()); 2091+ + TABLE_OFFSET(table->private, 2092+ cpu_number_map(smp_processor_id())); 2093 e = get_entry(table_base, table->private->hook_entry[hook]); 2094 2095 #ifdef CONFIG_NETFILTER_DEBUG 2096@@ -426,7 +427,7 @@ 2097 #endif 2098 /* Target might have changed stuff. */ 2099 ipv6 = (*pskb)->nh.ipv6h; 2100- protohdr = (u_int32_t *)ipv6 + IPV6_HDR_LEN; 2101+ protohdr = (u_int32_t *)((void *)ipv6 + IPV6_HDR_LEN); 2102 datalen = (*pskb)->len - IPV6_HDR_LEN; 2103 2104 if (verdict == IP6T_CONTINUE) 2105@@ -913,7 +914,7 @@ 2106 2107 /* And one copy for every other CPU */ 2108 for (i = 1; i < smp_num_cpus; i++) { 2109- memcpy(newinfo->entries + SMP_ALIGN(newinfo->size*i), 2110+ memcpy(newinfo->entries + SMP_ALIGN(newinfo->size)*i, 2111 newinfo->entries, 2112 SMP_ALIGN(newinfo->size)); 2113 } 2114@@ -1795,9 +1796,15 @@ 2115 } 2116 2117 #ifdef CONFIG_PROC_FS 2118- if (!proc_net_create("ip6_tables_names", 0, ip6t_get_tables)) { 2119- nf_unregister_sockopt(&ip6t_sockopts); 2120- return -ENOMEM; 2121+ { 2122+ struct proc_dir_entry *proc; 2123+ proc = proc_net_create("ip6_tables_names", 0, 2124+ ip6t_get_tables); 2125+ if (!proc) { 2126+ nf_unregister_sockopt(&ip6t_sockopts); 2127+ return -ENOMEM; 2128+ } 2129+ proc->owner = THIS_MODULE; 2130 } 2131 #endif 2132 2133diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.18-plain/net/ipv6/netfilter/ip6t_mac.c linux-2.4.19-plain/net/ipv6/netfilter/ip6t_mac.c 2134--- linux-2.4.18-plain/net/ipv6/netfilter/ip6t_mac.c Wed Oct 31 00:08:12 2001 2135+++ linux-2.4.19-plain/net/ipv6/netfilter/ip6t_mac.c Sat Aug 3 02:39:46 2002 2136@@ -34,8 +34,10 @@ 2137 unsigned int hook_mask) 2138 { 2139 if (hook_mask 2140- & ~((1 << NF_IP6_PRE_ROUTING) | (1 << NF_IP6_LOCAL_IN))) { 2141- printk("ip6t_mac: only valid for PRE_ROUTING or LOCAL_IN.\n"); 2142+ & ~((1 << NF_IP6_PRE_ROUTING) | (1 << NF_IP6_LOCAL_IN) 2143+ | (1 << NF_IP6_FORWARD))) { 2144+ printk("ip6t_mac: only valid for PRE_ROUTING, LOCAL_IN or" 2145+ " FORWARD\n"); 2146 return 0; 2147 } 2148 2149@@ -60,3 +62,5 @@ 2150 2151 module_init(init); 2152 module_exit(fini); 2153+MODULE_LICENSE("GPL"); 2154+MODULE_DESCRIPTION("MAC address matching module for IPv6"); 2155--- linux-2.4.18-plain/net/core/netfilter.c Mon Feb 25 20:38:14 2002 2156+++ linux-2.4.19-plain/net/core/netfilter.c Sat Aug 3 02:39:46 2002 2157@@ -83,8 +83,7 @@ 2158 /* Do exclusive ranges overlap? */ 2159 static inline int overlap(int min1, int max1, int min2, int max2) 2160 { 2161- return (min1 >= min2 && min1 < max2) 2162- || (max1 > min2 && max1 <= max2); 2163+ return max1 > min2 && min1 < max2; 2164 } 2165 2166 /* Functions to register sockopt ranges (exclusive). */ 2167