Messages in this thread Patch in this message |  | | Date | Sun, 15 Sep 96 17:06 BST | From | (Alan Cox) | Subject | Yet Another Networking Diff |
| |
* * Yet another block of diffs. * * o Documentation notes 3c59x problems a few people have and points * to new driver for 3c59x/3c9xx * o On a network where active hosts >> arp cache size we got noisy * and our cache tended to cycle * o Bridge had a memory leak * o bind() on a SOCK_PACKET with ETH_P_ALL behaves. * o Tom May's even faster checksum routines for ix86. Worth * another few K a second. Can anyone else do better ? * * [This one is an experiment, Linus don't apply the tcp changes to the * 2.0.xx kernel just yet ;)] * * o Diffs to tcp.c tcp.h tcp_input.c to include a simple SYN * attack filter for people not faking addresses, and some * limited protection for the generic case. This is mostly * there as a hook folks can add stuff onto. The simple case * it covers is useful as it will stop both a malfunctioning * host, and an attack via a provider with more than half a * brain. * People wanting to experiment further should look at * tcp_syn_filter() and add appropriately. * * diff --unified --new-file --recursive --exclude-from exclude linux.vanilla/Documentation/Configure.help linux/Documentation/Configure.help --- linux.vanilla/Documentation/Configure.help Sun Sep 15 16:07:07 1996 +++ linux/Documentation/Configure.help Sun Sep 15 14:45:17 1996 @@ -2148,10 +2148,14 @@ the Ethernet-HOWTO, available via ftp (user: anonymous) in sunsite.unc.edu:/pub/Linux/docs/HOWTO. More specific information is in Documentation/networking/vortex.txt and in the comments at the - beginning of drivers/net/3c59x.c. If you want to compile this - as a module ( = code which can be inserted in and removed from the - running kernel whenever you want), say M here and read - Documentation/modules.txt as well as + beginning of drivers/net/3c59x.c. + Some people have reported a few problems with the 3c590 card and this + driver. A newer EXPERIMENTAL driver for this card and the newest 3c9xx + series boards can be found at: + ftp://cesdis.gsfc.nasa.gov/pub/linux/drivers/v2.0/boomerang.c + If you want to compile this as a module ( = code which can be inserted + in and removed from the running kernel whenever you want), say M here + and read Documentation/modules.txt as well as Documentation/networking/net-modules.txt. If you plan to use more than one network card under linux, read the Multiple-Ethernet-mini-HOWTO, available from diff --unified --new-file --recursive --exclude-from exclude linux.vanilla/arch/i386/lib/checksum.c linux/arch/i386/lib/checksum.c --- linux.vanilla/arch/i386/lib/checksum.c Sun Jul 28 13:34:32 1996 +++ linux/arch/i386/lib/checksum.c Sun Sep 15 14:31:16 1996 @@ -70,8 +70,7 @@ 2: movl %%edx, %%ecx andl $0x1c, %%edx je 4f - shrl $2, %%edx - testl %%esi, %%esi + shrl $2, %%edx # This clears CF 3: adcl (%%esi), %%eax lea 4(%%esi), %%esi dec %%edx @@ -159,10 +158,9 @@ jne 1b adcl $0, %%eax 2: movl %%edx, %%ecx - andl $28, %%edx + andl $0x1c, %%edx je 4f - shrl $2, %%edx - testl %%esi, %%esi + shrl $2, %%edx # This clears CF 3: movl %%fs:(%%esi), %%ebx adcl %%ebx, %%eax movl %%ebx, (%%edi) @@ -212,52 +210,48 @@ addw %%bx, %%ax adcl $0, %%eax 2: - movl %%ecx, %%edx + pushl %%ecx shrl $5, %%ecx jz 2f testl %%esi, %%esi 1: movl (%%esi), %%ebx + movl 4(%%esi), %%edx adcl %%ebx, %%eax movl %%ebx, (%%edi) - - movl 4(%%esi), %%ebx - adcl %%ebx, %%eax - movl %%ebx, 4(%%edi) + adcl %%edx, %%eax + movl %%edx, 4(%%edi) movl 8(%%esi), %%ebx + movl 12(%%esi), %%edx adcl %%ebx, %%eax movl %%ebx, 8(%%edi) - - movl 12(%%esi), %%ebx - adcl %%ebx, %%eax - movl %%ebx, 12(%%edi) + adcl %%edx, %%eax + movl %%edx, 12(%%edi) movl 16(%%esi), %%ebx + movl 20(%%esi), %%edx adcl %%ebx, %%eax movl %%ebx, 16(%%edi) - - movl 20(%%esi), %%ebx - adcl %%ebx, %%eax - movl %%ebx, 20(%%edi) + adcl %%edx, %%eax + movl %%edx, 20(%%edi) movl 24(%%esi), %%ebx + movl 28(%%esi), %%edx adcl %%ebx, %%eax movl %%ebx, 24(%%edi) - - movl 28(%%esi), %%ebx - adcl %%ebx, %%eax - movl %%ebx, 28(%%edi) + adcl %%edx, %%eax + movl %%edx, 28(%%edi) lea 32(%%esi), %%esi lea 32(%%edi), %%edi dec %%ecx jne 1b adcl $0, %%eax -2: movl %%edx, %%ecx - andl $28, %%edx +2: popl %%edx + movl %%edx, %%ecx + andl $0x1c, %%edx je 4f - shrl $2, %%edx - testl %%esi, %%esi + shrl $2, %%edx # This clears CF 3: movl (%%esi), %%ebx adcl %%ebx, %%eax movl %%ebx, (%%edi) diff --unified --new-file --recursive --exclude-from exclude linux.vanilla/include/linux/if_arp.h linux/include/linux/if_arp.h --- linux.vanilla/include/linux/if_arp.h Sun Jul 28 13:32:54 1996 +++ linux/include/linux/if_arp.h Sun Sep 15 15:43:03 1996 @@ -52,6 +52,8 @@ #define ARPHRD_SKIP 771 /* SKIP vif */ #define ARPHRD_LOOPBACK 772 /* Loopback device */ #define ARPHRD_LOCALTLK 773 /* Localtalk device */ +#define ARPHRD_FDDI 774 /* FDDI interface (really uses 802 on wire) + */ /* ARP protocol opcodes. */ #define ARPOP_REQUEST 1 /* ARP request */ diff --unified --new-file --recursive --exclude-from exclude linux.vanilla/include/net/tcp.h linux/include/net/tcp.h --- linux.vanilla/include/net/tcp.h Tue Sep 3 22:07:30 1996 +++ linux/include/net/tcp.h Sun Sep 15 11:59:02 1996 @@ -70,7 +70,8 @@ #define TCP_PROBEWAIT_LEN (1*HZ)/* time to wait between probes when * I've got something to write and * there is no window */ - +#define TCP_CONNECT_TIMEOUT (75*HZ) /* 75 second default - more needed + for an amateur radio site! */ #define TCP_NO_CHECK 0 /* turn to one if you want the default * to be no checksum */ diff --unified --new-file --recursive --exclude-from exclude linux.vanilla/net/bridge/br.c linux/net/bridge/br.c --- linux.vanilla/net/bridge/br.c Sun Jul 28 13:33:23 1996 +++ linux/net/bridge/br.c Sun Sep 15 13:45:02 1996 @@ -19,6 +19,9 @@ * Put the path costs in the port info and devices. * Put the bridge port number in the device structure for speed. * Bridge SNMP stats. + * + * Fixes: + * Michael Leodolter : Bridge memory leak fix * */ @@ -1052,7 +1055,7 @@ int br_receive_frame(struct sk_buff *skb) /* 3.5 */ { int port; - int i; +/* int i;*/ if (br_stats.flags & BR_DEBUG) printk("br_receive_frame: "); @@ -1137,7 +1140,7 @@ /* happen in net_bh() in dev.c) */ } /* ok, forward this frame... */ - skb_device_lock(skb); + /*skb_device_lock(skb);*/ return(br_forward(skb, port)); default: printk(KERN_DEBUG "br_receive_frame: port [%i] unknown state [%i]\n", diff --unified --new-file --recursive --exclude-from exclude linux.vanilla/net/core/dev.c linux/net/core/dev.c --- linux.vanilla/net/core/dev.c Sat Aug 17 18:08:39 1996 +++ linux/net/core/dev.c Sun Sep 15 14:33:03 1996 @@ -654,13 +654,17 @@ pt_prev = NULL; for (ptype = ptype_all; ptype!=NULL; ptype=ptype->next) { - if(pt_prev) + /* Make sure we only pass on packets for the right device */ + if (!ptype->dev || ptype->dev==skb->dev) { - struct sk_buff *skb2=skb_clone(skb, GFP_ATOMIC); - if(skb2) - pt_prev->func(skb2,skb->dev, pt_prev); - } - pt_prev=ptype; + if(pt_prev) + { + struct sk_buff *skb2=skb_clone(skb, GFP_ATOMIC); + if(skb2) + pt_prev->func(skb2,skb->dev, pt_prev); + } + pt_prev=ptype; + } } for (ptype = ptype_base[ntohs(type)&15]; ptype != NULL; ptype = ptype->next) diff --unified --new-file --recursive --exclude-from exclude linux.vanilla/net/ipv4/arp.c linux/net/ipv4/arp.c --- linux.vanilla/net/ipv4/arp.c Sat Aug 17 18:08:39 1996 +++ linux/net/ipv4/arp.c Sun Sep 15 14:57:29 1996 @@ -60,6 +60,8 @@ * Mike Shaver : /proc/sys/net/ipv4/arp_* support * Stuart Cheshire : Metricom and grat arp fixes * *** FOR 2.1 clean this up *** + * Alan Cox : Cyclic ARP flushing bug fixed when + * run on big networks. */ /* RFC1122 Status: @@ -279,7 +281,7 @@ static void arp_run_bh(void); static void arp_check_expire (unsigned long); static int arp_update (u32 sip, char *sha, struct device * dev, - unsigned long updated, struct arp_table *ientry, int grat); + unsigned long updated, struct arp_table *ientry, int grat, int force); static struct timer_list arp_timer = { NULL, NULL, ARP_CHECK_INTERVAL, 0L, &arp_check_expire }; @@ -697,7 +699,7 @@ else { arp_fast_lock(); - arp_update(retreq->ip, retreq->ha, dev, retreq->updated, NULL, 0); + arp_update(retreq->ip, retreq->ha, dev, retreq->updated, NULL, 0, 1); arp_unlock(); } @@ -1024,13 +1026,17 @@ * arp_alloc_entry() should only be called with the cache locked too! */ -static struct arp_table * arp_alloc_entry(void) +static struct arp_table * arp_alloc_entry(int force) { struct arp_table * entry; if (arp_size >= ARP_MAXSIZE) + { + if(!force) + return NULL; arp_force_expire(); + } entry = (struct arp_table *) kmalloc(sizeof(struct arp_table),GFP_ATOMIC); @@ -1146,7 +1152,7 @@ static int arp_update (u32 sip, char *sha, struct device * dev, - unsigned long updated, struct arp_table *ientry, int grat) + unsigned long updated, struct arp_table *ientry, int grat, int force) { struct arp_table * entry; unsigned long hash; @@ -1211,7 +1217,7 @@ if (!entry) { - entry = arp_alloc_entry(); + entry = arp_alloc_entry(force); if (!entry) return 0; @@ -1323,7 +1329,7 @@ { struct arp_table *entry; - entry = arp_alloc_entry(); + entry = arp_alloc_entry(1); if (entry != NULL) { @@ -1567,7 +1573,7 @@ while ((entry = arp_dequeue(&arp_backlog)) != NULL) { restore_flags(flags); - if (arp_update(entry->ip, entry->ha, entry->dev, 0, entry, 0)) + if (arp_update(entry->ip, entry->ha, entry->dev, 0, entry, 0, 1)) arp_free_entry(entry); cli(); } @@ -1751,7 +1757,7 @@ unsigned char *arp_ptr= (unsigned char *)(arp+1); unsigned char *sha,*tha; u32 sip,tip; - + /* * The hardware length of the packet should match the hardware length * of the device. Similarly, the hardware types should match. The @@ -1937,7 +1943,17 @@ } arp_fast_lock(); - arp_update(sip, sha, dev, 0, NULL, ip_chk_addr(tip) != IS_MYADDR && dev->type != ARPHRD_METRICOM); + /* + * This is a bit subtle. We pass 0 for force, meaning an update + * here will not force an entry out of cache. This is correct + * because: + * An entry we here off the wire but don't need should + * not kick out an entry. + * An entry we are waiting to resolve or using exists + * and the force flag is not used. (Its used + * when we create the pending request). + */ + arp_update(sip, sha, dev, 0, NULL, ip_chk_addr(tip) != IS_MYADDR && dev->type != ARPHRD_METRICOM, 0); arp_unlock(); kfree_skb(skb, FREE_READ); return 0; @@ -2032,7 +2048,7 @@ entryp = &entry->next; } - entry = arp_alloc_entry(); + entry = arp_alloc_entry(1); if (entry == NULL) { arp_unlock(); diff --unified --new-file --recursive --exclude-from exclude linux.vanilla/net/ipv4/tcp.c linux/net/ipv4/tcp.c --- linux.vanilla/net/ipv4/tcp.c Sun Sep 8 14:15:30 1996 +++ linux/net/ipv4/tcp.c Sun Sep 15 13:43:15 1996 @@ -438,7 +438,7 @@ unsigned long seq_offset; struct tcp_mib tcp_statistics; -static void tcp_close(struct sock *sk, unsigned long timeout); +extern void tcp_close(struct sock *sk, unsigned long timeout); /* * Find someone to 'accept'. Must be called with @@ -1734,7 +1734,7 @@ } -static void tcp_close(struct sock *sk, unsigned long timeout) +void tcp_close(struct sock *sk, unsigned long timeout) { struct sk_buff *skb; diff --unified --new-file --recursive --exclude-from exclude linux.vanilla/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c --- linux.vanilla/net/ipv4/tcp_input.c Tue Sep 3 22:07:31 1996 +++ linux/net/ipv4/tcp_input.c Sun Sep 15 13:41:55 1996 @@ -341,6 +341,82 @@ #endif } +/* + * TCP filter for SYN frames. We disallow more than 30% queue + * occupancy by the same class C network range. This is designed + * to stop runaway hosts and attacks being made via a competent + * provider who has proper address filter rules. It doesn't stop + * spoofed source address attacks via a provider too stupid to + * have proper source address filters. For those cases you'll + * have to rely on dumps, provider co-operation and the law. + * + * Feel free to invent smarter filters and hook them here. + */ + +int tcp_syn_filter(struct sock *sk, struct sk_buff *skb, __u32 saddr) +{ + extern void tcp_close(struct sock *sk, unsigned long timeout); + + int ct=0; + struct sk_buff *tmp; + unsigned long flags; + /* If we have < 33% queue occupancy we don't care */ + if(3*sk->ack_backlog<=sk->max_ack_backlog) + return 0; + + /* + * We are potentially going to be losing things due to + * slow connects.. See if they've passed the trash timer + * as we do the count + */ + + /* Now count */ + saddr&=htonl(0xFFFFFF00); + + save_flags(flags); + cli(); + + tmp=skb_peek(&sk->receive_queue); + while(tmp && tmp!=(struct sk_buff *)&sk->receive_queue) + { + /* + * The next pointer could change if tcp_close does + * delete the socket. + */ + + struct sk_buff *tnext=tmp->next; + + /* + * Fits mask ? + */ + + if((tmp->sk->saddr&htonl(0xFFFFFF00))==saddr) + ct++; + + /* + * Timed out ? + */ + if(tmp->when - jiffies > TCP_CONNECT_TIMEOUT) + { + /* + * You can modify this to send a reset and + * go straight to closed. If you do then you + * in theory risk data errors (see RFC1337) + */ + tcp_close(tmp->sk,0); + } + tmp=tnext; + } + restore_flags(flags); + + /* + * Report whether to accept + */ + + if(3*ct>sk->max_ack_backlog) + return 1; + return 0; +} /* * This routine handles a connection request. @@ -382,13 +458,13 @@ * set backlog as a fudge factor. That's just too gross. */ - if (sk->ack_backlog >= sk->max_ack_backlog) + if (sk->ack_backlog >= sk->max_ack_backlog || tcp_syn_filter(sk,skb,saddr)) { tcp_statistics.TcpAttemptFails++; kfree_skb(skb, FREE_READ); return; } - + /* * We need to build a new sock struct. * It is sort of bad to have a socket without an inode attached @@ -428,6 +504,8 @@ return; } } + + skb->when = jiffies; /* For timeout */ skb_queue_head_init(&newsk->write_queue); skb_queue_head_init(&newsk->receive_queue); newsk->send_head = NULL;
|  |