]> git.neil.brown.name Git - history.git/commitdiff
Import 1.1.17 1.1.17
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:09:31 +0000 (15:09 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:09:31 +0000 (15:09 -0500)
Makefile
config.in
drivers/net/Makefile
drivers/net/dummy.c [new file with mode: 0644]
drivers/net/net_init.c
drivers/net/plip.c
net/inet/README
net/inet/arp.c
net/inet/ip.c
net/inet/tcp.c
net/inet/udp.c

index 0a139d6aceb232e6db6167f58ce2449b583c109c..094edc39cadbc9f5a182438c58d894d3d70758f6 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 1
-SUBLEVEL = 16
+SUBLEVEL = 17
 
 all:   Version zImage
 
index 80b1c57af5749919547f56df5ff62ff25cece322..a5dc5d428e984fb7321f04059ed027d3c89a4a39 100644 (file)
--- a/config.in
+++ b/config.in
@@ -73,6 +73,7 @@ if [ "$CONFIG_NETDEVICES" = "n" ]; then
 comment 'Skipping ethercard configuration options...'
 
 else
+bool 'Dummy net driver support' CONFIG_DUMMY y
 bool 'SLIP (serial line) support' CONFIG_SLIP n
 if [ "$CONFIG_SLIP" = "y" ]; then
   bool ' CSLIP compressed headers' SL_COMPRESSED y
@@ -98,7 +99,7 @@ bool 'DEPCA support' CONFIG_DEPCA n
 #bool 'NI52EE support' CONFIG_NI52 n
 #bool 'NI65EE support' CONFIG_NI65 n
 #bool 'Ansel Communications EISA 3200 support' CONFIG_AC3200 n
-#bool 'Cabletron E21xx support (not recommended)' CONFIG_E21 n
+#bool 'Cabletron E21xx support (not recommended)' CONFIG_E2100 n
 bool 'D-Link DE600 pocket adaptor support' CONFIG_DE600 n
 bool 'AT-LAN-TEC/RealTek pocket adaptor support' CONFIG_ATP n
 fi
index 44bb05180f9747fb8e60624cbf1022ee18cfdf65..442336e2b96e10aa44d52792206805dec9b00ba8 100644 (file)
@@ -82,6 +82,12 @@ ifdef CONFIG_3C589
 NETDRV_OBJS := $(NETDRV_OBJS) net.a(3c589.o)
 endif
 
+ifdef CONFIG_DUMMY
+NETDRV_OBJS := $(NETDRV_OBJS) net.a(dummy.o)
+dummy.o: dummy.c CONFIG
+       $(CC) $(CPPFLAGS) $(CFLAGS) -c $<
+endif
+
 ifdef CONFIG_DE600
 NETDRV_OBJS := $(NETDRV_OBJS) net.a(de600.o)
 endif
diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c
new file mode 100644 (file)
index 0000000..2b19f8a
--- /dev/null
@@ -0,0 +1,110 @@
+/* dummy.c: a dummy net driver
+
+       The purpose of this driver is to provide a device to point a
+       route through, but not to actually transmit packets.
+
+       Why?  If you have a machine whose only connection is an occasional
+       PPP/SLIP/PLIP link, you can only connect to your own hostname
+       when the link is up.  Otherwise you have to use localhost.
+       This isn't very consistent.
+
+       One solution is to set up a dummy link using PPP/SLIP/PLIP,
+       but this seems (to me) too much overhead for too little gain.
+       This driver provides a small alternative. Thus you can do
+       
+       [when not running slip]
+               ifconfig dummy slip.addr.ess.here up
+       [to go to slip]
+               ifconfig dummy down
+               dip whatever
+
+       This was written by looking at Donald Becker's skeleton driver
+       and the loopback driver.  I then threw away anything that didn't
+       apply!  Thanks to Alan Cox for the key clue on what to do with
+       misguided packets.
+
+                       Nick Holloway, 27th May 1994
+       [I tweaked this explanation a little but thats all]
+                       Alan Cox, 30th May 1994
+*/
+
+/* To have statistics (just packets sent) define this */
+#undef DUMMY_STATS
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/interrupt.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/in.h>
+#include <linux/malloc.h>
+#include <linux/string.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <errno.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+
+static int dummy_xmit(struct sk_buff *skb, struct device *dev);
+#ifdef DUMMY_STATS
+static struct enet_statistics *dummy_get_stats(struct device *dev);
+#endif
+
+int
+dummy_init(struct device *dev)
+{
+/* I commented this out as bootup is noisy enough anyway and this driver
+   seems pretty reliable 8) 8) 8) */
+/*     printk ( KERN_INFO "Dummy net driver (94/05/27 v1.0)\n" ); */
+
+       /* Initialize the device structure. */
+       dev->hard_start_xmit    = dummy_xmit;
+
+#if DUMMY_STATS
+       dev->priv = kmalloc(sizeof(struct enet_statistics), GFP_KERNEL);
+       memset(dev->priv, 0, sizeof(struct enet_statistics));
+       dev->get_stats          = dummy_get_stats;
+#endif
+
+       /* Fill in the fields of the device structure with ethernet-generic values. */
+       ether_setup(dev);
+
+       return 0;
+}
+
+static int
+dummy_xmit(struct sk_buff *skb, struct device *dev)
+{
+#if DUMMY_STATS
+       struct enet_statistics *stats;
+#endif
+
+       if (skb == NULL || dev == NULL)
+               return 0;
+
+       if (skb->free)
+               kfree_skb(skb, FREE_WRITE);
+
+#if DUMMY_STATS
+       stats = (struct enet_statistics *)dev->priv;
+       stats->tx_packets++;
+#endif
+
+       return 0;
+}
+
+#if DUMMY_STATS
+static struct enet_statistics *
+dummy_get_stats(struct device *dev)
+{
+       struct enet_statistics *stats = (struct enet_statistics*) dev->priv;
+       return stats;
+}
+#endif
index 295ef7c027a7d12887f65f66aea8d3159d46425b..9b2b2a8c983012b018a2c46d0db4113d242aca22 100644 (file)
@@ -15,7 +15,9 @@
        A secondary advantage is that the dangerous NE*000 netcards can reserve
        their I/O port region before the SCSI probes start.
 
-       register_netdev()/unregister_netdev() by Bjorn Ekwall <bj0rn@blox.se>
+       Modifications/additions by Bjorn Ekwall <bj0rn@blox.se>:
+               ethdev_index[MAX_ETH_CARDS]
+               register_netdev() / unregister_netdev()
 */
 
 #include <linux/config.h>
@@ -45,8 +47,9 @@
     by magic we get them, but otherwise they are un-needed and a space waste]
 */
 
-/* The next device number/name to assign: "eth0", "eth1", etc. */
-static int next_ethdev_number = 0;
+/* The list of used and available "eth" slots (for "eth0", "eth1", etc.) */
+#define MAX_ETH_CARDS 16 /* same as the number if irq's in irq2dev[] */
+static struct device *ethdev_index[MAX_ETH_CARDS];
 
 unsigned long lance_init(unsigned long mem_start, unsigned long mem_end);
 
@@ -78,11 +81,11 @@ unsigned long net_dev_init (unsigned long mem_start, unsigned long mem_end)
    long.
  */
 
-struct device *init_etherdev(struct device *dev, int sizeof_private,
-                                                        unsigned long *mem_startp)
+struct device *
+init_etherdev(struct device *dev, int sizeof_private, unsigned long *mem_startp)
 {
-       int i;
        int new_device = 0;
+       int i;
 
        if (dev == NULL) {
                int alloc_size = sizeof(struct device) + sizeof("eth%d ")
@@ -99,31 +102,17 @@ struct device *init_etherdev(struct device *dev, int sizeof_private,
                new_device = 1;
        }
 
-       if (dev->name  &&  dev->name[0] == '\0')
-               sprintf(dev->name, "eth%d", next_ethdev_number++);
-
-       for (i = 0; i < DEV_NUMBUFFS; i++)
-               skb_queue_head_init(&dev->buffs[i]);
-       
-       dev->hard_header        = eth_header;
-       dev->rebuild_header     = eth_rebuild_header;
-       dev->type_trans         = eth_type_trans;
-       
-       dev->type                       = ARPHRD_ETHER;
-       dev->hard_header_len = ETH_HLEN;
-       dev->mtu                        = 1500; /* eth_mtu */
-       dev->addr_len           = ETH_ALEN;
-       for (i = 0; i < ETH_ALEN; i++) {
-               dev->broadcast[i]=0xff;
+       if (dev->name &&
+               ((dev->name[0] == '\0') || (dev->name[0] == ' '))) {
+               for (i = 0; i < MAX_ETH_CARDS; ++i)
+                       if (ethdev_index[i] == NULL) {
+                               sprintf(dev->name, "eth%d", i);
+                               ethdev_index[i] = dev;
+                               break;
+                       }
        }
-       
-       /* New-style flags. */
-       dev->flags                      = IFF_BROADCAST;
-       dev->family                     = AF_INET;
-       dev->pa_addr            = 0;
-       dev->pa_brdaddr         = 0;
-       dev->pa_mask            = 0;
-       dev->pa_alen            = sizeof(unsigned long);
+
+       ether_setup(dev); /* should this be called here? */
        
        if (new_device) {
                /* Append the device to the device queue. */
@@ -144,6 +133,19 @@ void ether_setup(struct device *dev)
        for (i = 0; i < DEV_NUMBUFFS; i++)
                skb_queue_head_init(&dev->buffs[i]);
 
+       /* register boot-defined "eth" devices */
+       if (dev->name && (strncmp(dev->name, "eth", 3) == 0)) {
+               i = simple_strtoul(dev->name + 3, NULL, 0);
+               if (ethdev_index[i] == NULL) {
+                       ethdev_index[i] = dev;
+               }
+               else if (dev != ethdev_index[i]) {
+                       /* Really shouldn't happen! */
+                       printk("ether_setup: Ouch! Someone else took %s\n",
+                               dev->name);
+               }
+       }
+
        dev->hard_header        = eth_header;
        dev->rebuild_header = eth_rebuild_header;
        dev->type_trans = eth_type_trans;
@@ -186,24 +188,30 @@ int register_netdev(struct device *dev)
 {
        struct device *d = dev_base;
        unsigned long flags;
-       
+       int i;
+
        save_flags(flags);
        cli();
 
-       if (dev && dev->init) 
-       {
-               if (dev->init(dev) != 0)
-               {
+       if (dev && dev->init) {
+               if (dev->init(dev) != 0) {
                        restore_flags(flags);
                        return -EIO;
                }
-               
-               if (dev->name  &&  dev->name[0] == '\0')
-                       sprintf(dev->name, "eth%d", next_ethdev_number++);
+
+               if (dev->name &&
+                       ((dev->name[0] == '\0') || (dev->name[0] == ' '))) {
+                       for (i = 0; i < MAX_ETH_CARDS; ++i)
+                               if (ethdev_index[i] == NULL) {
+                                       sprintf(dev->name, "eth%d", i);
+                                       printk("device '%s' loaded\n", dev->name);
+                                       ethdev_index[i] = dev;
+                                       break;
+                               }
+               }
 
                /* Add device to end of chain */
-               if (dev_base) 
-               {
+               if (dev_base) {
                        while (d->next)
                                d = d->next;
                        d->next = dev;
@@ -220,36 +228,49 @@ void unregister_netdev(struct device *dev)
 {
        struct device *d = dev_base;
        unsigned long flags;
-       
+       int i;
+
        save_flags(flags);
        cli();
 
        printk("unregister_netdev: device ");
-       if (dev) {
-               if (dev->start)
-                       printk("'%s' busy", dev->name);
+
+       if (dev == NULL) {
+               printk("was NULL\n");
+               restore_flags(flags);
+               return;
+       }
+       /* else */
+       if (dev->start)
+               printk("'%s' busy\n", dev->name);
+       else {
+               if (dev_base == dev)
+                       dev_base = dev->next;
                else {
-                       if (dev_base == dev)
-                               dev_base = dev->next;
-                       else {
-                               while (d && (d->next != dev))
-                                       d = d->next;
+                       while (d && (d->next != dev))
+                               d = d->next;
 
-                               if (d && (d->next == dev)) {
-                                       d->next = dev->next;
-                                       printk("'%s' unlinked", dev->name);
-                               }
-                               else
-                                       printk("'%s' not found", dev->name);
+                       if (d && (d->next == dev)) {
+                               d->next = dev->next;
+                               printk("'%s' unlinked\n", dev->name);
+                       }
+                       else {
+                               printk("'%s' not found\n", dev->name);
+                               restore_flags(flags);
+                               return;
+                       }
+               }
+               for (i = 0; i < MAX_ETH_CARDS; ++i) {
+                       if (ethdev_index[i] == dev) {
+                               ethdev_index[i] = NULL;
+                               break;
                        }
                }
        }
-       else
-               printk("was NULL");
-       printk("\n");
        restore_flags(flags);
 }
 
+
 \f
 /*
  * Local variables:
index b89a8a1b8c11b6a3d154bdbca91175bd3bdcafce..ba0f79eacf003df278520a0f69aad3f344534948 100644 (file)
  *
  ***** So we can all compare loads of different PLIP drivers for a bit I've modularised this beastie too.
  ***** In addition a seperate bidirectional plip module can be done.
+ *
+ *     WARNING: The PRE 1.1.16 plip will NOT work with this PLIP driver. We
+ *     can't avoid this due to an error in the old plip module. If you must
+ *     mix PLIP's you'll need to fix the _OLD_ one to use 0xFC 0xFC as its
+ *     MAC header not 0xFD.
+ *
  */
 
 static char *version =
@@ -703,7 +709,7 @@ plip_set_physicaladdr(struct device *dev, unsigned long ipaddr)
 {
     /*
      * set physical address to
-     *  0xfd.0xfd.ipaddr
+     *  0xfc.0xfc.ipaddr
      */
 
     unsigned char *addr = dev->dev_addr;
index 67f6d732312fc92ae52bd7d82479baa937296f12..06cc8ffcc33c4772e4818122f6833b4280128494 100644 (file)
@@ -1,5 +1,18 @@
 This is snapshot 014
 
+Fixes added for 1.1.17
+
+o      Charles Hedrick's fixes broken fragmentation totally. Mended.
+o      Contributed 'dummy' device added. Apparently some slip people want it.
+o      Tried to kill the memory problems with fragments by setting things
+       up more carefully and guarding them.
+o      Module fixes by Bj0rn.
+o      PLIP fix by Tanabe.
+
+Fixes added for 1.1.16
+o      Charles Hedricks fixes to TCP.
+o      Small fixes all over the place.
+
 Fixes added for 1.1.15
 o      Modular PLIP and 3c501 drivers. Now you -can- have multiple 3c501's
        (sort of).
index bd904cd53f56959f03acf6e13f98feb992508b2b..d0b6fc638113489882da1b5fe9c5cd7e6a1bfcae 100644 (file)
@@ -722,17 +722,6 @@ int arp_find(unsigned char *haddr, unsigned long paddr, struct device *dev,
 {
        struct arp_table *entry;
        unsigned long hash;
-/* SHOULD BE FIXED NOW */      
-       if(paddr==0)
-       {
-               printk("ADDRESS BOTCH 0\n");
-               if(skb)
-               {
-                       printk("skb(saddr=%lx, daddr=%lx, raddr=%lx)\n",
-                               skb->saddr,skb->daddr,skb->raddr);
-               }
-       }       
-/* ------------- */
        switch (ip_chk_addr(paddr))
        {
                case IS_MYADDR:
index 2743352df9ffe4fd8793f2f1ec88634f393c7de2..41bf38049bc6aa7683094b00c89bfdfd3fe2b274 100644 (file)
@@ -171,7 +171,7 @@ static int ip_send(struct sk_buff *skb, unsigned long daddr, int len, struct dev
                {
                        mac = -mac;
                        skb->arp = 0;
-                       skb->raddr = daddr;     /* next routing address */
+                       skb->raddr = daddr;     /* next routing address */                      
                }       
        }
        return mac;
@@ -226,7 +226,7 @@ int ip_build_header(struct sk_buff *skb, unsigned long saddr, unsigned long dadd
                 *      If the frame is from us and going off machine it MUST MUST MUST
                 *      have the output device ip address and never the loopback
                 */
-               if (saddr == 0x0100007FL && daddr != 0x0100007FL) 
+               if (saddr == htonl(0x7F000001L) && daddr != htonl(0x7F000001L))
                        saddr = src;/*rt->rt_dev->pa_addr;*/
                raddr = rt->rt_gateway;
 
@@ -665,7 +665,6 @@ static void ip_free(struct ipq *qp)
  
        /* Finally, release the queue descriptor itself. */
        kfree_s(qp, sizeof(struct ipq));
-/*     printk("ip_free:done\n");*/
        sti();
  }
  
@@ -716,7 +715,7 @@ static struct ipq *ip_create(struct sk_buff *skb, struct iphdr *iph, struct devi
        {
                printk("IP: create: no memory left !\n");
                return(NULL);
-       skb->dev = qp->dev;
+               skb->dev = qp->dev;
        }
        memset(qp, 0, sizeof(struct ipq));
 
@@ -949,7 +948,7 @@ static struct sk_buff *ip_defrag(struct iphdr *iph, struct sk_buff *skb, struct
         
        ihl = (iph->ihl * sizeof(unsigned long));
        end = offset + ntohs(iph->tot_len) - ihl;
+
        /*
         *      Point into the IP datagram 'data' part. 
         */
@@ -1088,6 +1087,7 @@ static struct sk_buff *ip_defrag(struct iphdr *iph, struct sk_buff *skb, struct
        struct sk_buff *skb2;
        int left, mtu, hlen, len;
        int offset;
+       unsigned long flags;
  
        /* 
         *      Point into the IP datagram header. 
@@ -1180,19 +1180,27 @@ static struct sk_buff *ip_defrag(struct iphdr *iph, struct sk_buff *skb, struct
                 *      Set up data on packet
                 */
 
-               skb2->arp = 0;/*skb->arp;*/
-               skb2->free = skb->free;
+               skb2->arp = skb->arp;
+               if(skb->free==0)
+                       printk("IP fragmenter: BUG free!=1 in fragmenter\n");
+               skb2->free = 1;
                skb2->len = len + hlen;
                skb2->h.raw=(char *) skb2->data;
-               skb2->raddr = skb->raddr;       /* For rebuild_header */
                /*
                 *      Charge the memory for the fragment to any owner
                 *      it might posess
                 */
                 
+               save_flags(flags);
                if (sk) 
+               {
+                       cli();
                        sk->wmem_alloc += skb2->mem_len;
+                       skb2->sk=sk;
+               }
+               restore_flags(flags);
+               skb2->raddr = skb->raddr;       /* For rebuild_header - must be here */ 
+
                /* 
                 *      Copy the packet header into the new buffer. 
                 */
@@ -1227,7 +1235,7 @@ static struct sk_buff *ip_defrag(struct iphdr *iph, struct sk_buff *skb, struct
                 
                ip_statistics.IpFragCreates++;
                
-               ip_queue_xmit(sk, dev, skb2, 1);
+               ip_queue_xmit(sk, dev, skb2, 2);
        }
        ip_statistics.IpFragOKs++;
 }
@@ -1236,7 +1244,7 @@ static struct sk_buff *ip_defrag(struct iphdr *iph, struct sk_buff *skb, struct
 
 #ifdef CONFIG_IP_FORWARD
 
-/* 
+/*     
  *     Forward an IP datagram to its next destination. 
  */
 
@@ -1627,7 +1635,8 @@ int ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
 /*
  * Queues a packet to be sent, and starts the transmitter
  * if necessary.  if free = 1 then we free the block after
- * transmit, otherwise we don't.
+ * transmit, otherwise we don't. If free==2 we not only
+ * free the block but also dont assign a new ip seq number.
  * This routine also needs to put in the total length,
  * and compute the checksum
  */
@@ -1655,7 +1664,7 @@ void ip_queue_xmit(struct sock *sk, struct device *dev,
         *      Do some book-keeping in the packet for later
         */
 
-       skb->free = free;
+
        skb->dev = dev;
        skb->when = jiffies;
   
@@ -1672,7 +1681,17 @@ void ip_queue_xmit(struct sock *sk, struct device *dev,
        iph = (struct iphdr *)ptr;
        skb->ip_hdr = iph;
        iph->tot_len = ntohs(skb->len-dev->hard_header_len);
-       iph->id      = htons(ip_id_count++);
+
+       /*
+        *      No reassigning numbers to fragments...
+        */
+        
+       if(free!=2)
+               iph->id      = htons(ip_id_count++);
+       else
+               free=1;
+               
+       skb->free = free;               
 
        /*
         *      Do we need to fragment. Again this is inefficient. 
index db1e3ba29d6f68a2cb8e4baae627ded2142f5519..f111fcfe2134d67286315fd3caa2563bdacb0109 100644 (file)
@@ -71,6 +71,7 @@
  *             Matthew Dillon  :       Reworked TCP machine states as per RFC
  *             Gerhard Koerting:       PC/TCP workarounds
  *             Adam Caldwell   :       Assorted timer/timing errors
+ *             Matthew Dillon  :       Fixed another RST bug
  *
  *
  * To Fix:
@@ -78,7 +79,6 @@
  *             it causes a select. Linux can - given the official select semantics I
  *             feel that _really_ its the BSD network programs that are bust (notably
  *             inetd, which hangs occasionally because of this).
- *                     Protocol closedown badly messed up.
  *
  *             This program is free software; you can redistribute it and/or
  *             modify it under the terms of the GNU General Public License
@@ -2044,7 +2044,9 @@ static void tcp_close(struct sock *sk, int timeout)
                        printk("Clean rcv queue\n");
                while((skb=skb_dequeue(&sk->receive_queue))!=NULL)
                {
-                       if(skb->len > 0 && after(skb->h.th->seq + skb->len + 1 , sk->copied_seq))
+                       /* The +1 is not needed because the FIN takes up sequence space and
+                          is not read!!! */
+                       if(skb->len > 0 && after(skb->h.th->seq + skb->len/* + 1 */ , sk->copied_seq))
                                need_reset = 1;
                        kfree_skb(skb, FREE_READ);
                }
index 23a12b0ba23f5a7d13c0d1fb1d0a2b0766e11777..aa55f1f81c5c3e09f17a9abdcf8c27eb0a813533 100644 (file)
@@ -118,6 +118,15 @@ void udp_err(int err, unsigned char *header, unsigned long daddr,
                return;
        }
 
+       /*
+        *      Various people wanted BSD UDP semantics. Well they've come 
+        *      back out because they slow down response to stuff like dead
+        *      or unreachable name servers and they screw term users something
+        *      chronic. Oh and it violates RFC1122. So basically fix your 
+        *      client code people.
+        */
+        
+#ifdef CONFIG_I_AM_A_BROKEN_BSD_WEENIE
        /*
         *      It's only fatal if we have connected to them. I'm not happy
         *      with this code. Some BSD comparisons need doing.
@@ -126,10 +135,15 @@ void udp_err(int err, unsigned char *header, unsigned long daddr,
        if (icmp_err_convert[err & 0xff].fatal && sk->state == TCP_ESTABLISHED) 
        {
                sk->err = icmp_err_convert[err & 0xff].errno;
-/*             sk->err=ECONNREFUSED;*/
+               sk->error_report(sk);
        }
-       
-       sk->error_report(sk);
+#else
+       if (icmp_err_convert[err & 0xff].fatal)
+       {
+               sk->err = icmp_err_convert[err & 0xff].errno;
+               sk->error_report(sk);
+       }
+#endif
 }