]> git.neil.brown.name Git - history.git/commitdiff
Import 0.99.14o 0.99.14o
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:09:18 +0000 (15:09 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:09:18 +0000 (15:09 -0500)
48 files changed:
Makefile
drivers/net/Makefile
drivers/net/slip.c
fs/isofs/rock.c
include/linux/ip.h
include/linux/socket.h
include/linux/sockios.h
net/Makefile
net/Space.c
net/ddi.c
net/inet/Makefile
net/inet/README
net/inet/arp.c
net/inet/arp.h
net/inet/datagram.c [new file with mode: 0644]
net/inet/dev.c
net/inet/devinet.c [deleted file]
net/inet/devinet.h [deleted file]
net/inet/eth.c
net/inet/icmp.c
net/inet/ip.c
net/inet/ip.h
net/inet/loopback.c
net/inet/packet.c
net/inet/proc.c
net/inet/protocol.c
net/inet/raw.c
net/inet/route.c
net/inet/route.h
net/inet/skbuff.c [new file with mode: 0644]
net/inet/skbuff.h [new file with mode: 0644]
net/inet/sockinet.c [deleted file]
net/inet/sockinet.h [deleted file]
net/inet/tcp.c
net/inet/tcp.h
net/inet/timer.c
net/inet/udp.c
net/inet/utils.c
net/socket/Makefile [deleted file]
net/socket/datagram.c [deleted file]
net/socket/dev.c [deleted file]
net/socket/dev.h [deleted file]
net/socket/skbuff.c [deleted file]
net/socket/skbuff.h [deleted file]
net/socket/sock.c [deleted file]
net/socket/sock.h [deleted file]
net/unix/proc.c
net/unix/sock.c

index 3b14313ab9224a57f1469bb4acf6ec0e3640e9c8..bca493a2a7120749ebc2ee5e1d3ddd659f3dd889 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 0.99
 PATCHLEVEL = 14
-ALPHA = n
+ALPHA = o
 
 all:   Version zImage
 
@@ -50,7 +50,7 @@ SVGA_MODE=    -DSVGA_MODE=NORMAL_VGA
 # standard CFLAGS
 #
 
-CFLAGS = -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -pipe
+CFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe
 
 ifdef CONFIG_CPP
 CFLAGS := $(CFLAGS) -x c++
index e6d1140b1529ee38209b183c80fcf36022f482d3..51c1c8d9e7fd8c9de9ca652f7e7f946d5b2aa044 100644 (file)
@@ -8,8 +8,8 @@
 include CONFIG
 
 NETDRV_OBJS := net.a(Space.o) net.a(auto_irq.o) net.a(net_init.o)
-CFLAGS := $(CFLAGS) -I../../net/inet -I../../net/socket -I../../net
-CPP := $(CPP) -I../../net/inet -I../../net/socket -I../../net
+CFLAGS := $(CFLAGS) -I../../net/inet
+CPP := $(CPP) -I../../net/inet
 
 # The point of the makefile...
 all: net.a
index a3f2e1c82964d552a8a84ffa50c093341b52ff05..b72dbcae79c1aae4c8083b194a296ea2c919d17a 100644 (file)
@@ -40,9 +40,9 @@
 #include <linux/tty.h>
 #include <linux/in.h>
 #include "inet.h"
-#include "devinet.h"
+#include "dev.h"
 #ifdef CONFIG_AX25
-#include "ax25/ax25.h"
+#include "ax25.h"
 #endif
 #include "eth.h"
 #include "ip.h"
index 25b4214bb7fbb0e71da038080d2655ecc9b18204..ebbb449626543bc32407a291090088d6d46d94cd 100644 (file)
 #define MAYBE_CONTINUE(LABEL,DEV) \
   {if (buffer) kfree(buffer); \
   if (cont_extent){ \
-    int block, offset; \
+    int block, offset, offset1; \
     struct buffer_head * bh; \
     buffer = kmalloc(cont_size,GFP_KERNEL); \
     block = cont_extent; \
     offset = cont_offset; \
+    offset1 = 0; \
     if(ISOFS_BUFFER_SIZE(DEV) == 1024) {     \
       block <<= 1;    \
       if (offset >= 1024) block++; \
       offset &= 1023; \
+      if(offset + cont_size >= 1024) { \
+         bh = bread(DEV->i_dev, block++, ISOFS_BUFFER_SIZE(DEV)); \
+         memcpy(buffer, bh->b_data + offset, 1024 - offset); \
+          brelse(bh); \
+         offset1 = 1024 - offset; \
+         offset = 0; \
+      }  \
     };     \
     bh = bread(DEV->i_dev, block, ISOFS_BUFFER_SIZE(DEV)); \
     if(bh){       \
-      memcpy(buffer, bh->b_data, cont_size); \
+      memcpy(buffer + offset1, bh->b_data + offset, cont_size - offset1); \
       brelse(bh); \
       chr = (unsigned char *) buffer; \
       len = cont_size; \
@@ -291,10 +299,17 @@ int parse_rock_ridge_inode(struct iso_directory_record * de,
        };
        break;
       case SIG('T','F'):
+       /* Some RRIP writers incorrectly place ctime in the TF_CREATE field.
+          Try and handle this correctly for either case. */
        cnt = 0; /* Rock ridge never appears on a High Sierra disk */
-       if(rr->u.TF.flags & TF_CREATE) inode->i_ctime = iso_date(rr->u.TF.times[cnt++].time, 0);
-       if(rr->u.TF.flags & TF_MODIFY) inode->i_mtime = iso_date(rr->u.TF.times[cnt++].time, 0);
-       if(rr->u.TF.flags & TF_ACCESS) inode->i_atime = iso_date(rr->u.TF.times[cnt++].time, 0);
+       if(rr->u.TF.flags & TF_CREATE) 
+         inode->i_ctime = iso_date(rr->u.TF.times[cnt++].time, 0);
+       if(rr->u.TF.flags & TF_MODIFY) 
+         inode->i_mtime = iso_date(rr->u.TF.times[cnt++].time, 0);
+       if(rr->u.TF.flags & TF_ACCESS) 
+         inode->i_atime = iso_date(rr->u.TF.times[cnt++].time, 0);
+       if(rr->u.TF.flags & TF_ATTRIBUTES) 
+         inode->i_ctime = iso_date(rr->u.TF.times[cnt++].time, 0);
        break;
       case SIG('S','L'):
        {int slen;
index 887b2cb20cbd5ae08086b920dea7000a870f504c..26d4a5907576ef7d6e44f2a8ec121cb2ae2e5495 100644 (file)
@@ -59,8 +59,6 @@ struct options {
   unsigned short       handling;
   unsigned short       stream;
   unsigned             tcc;
-  int          option_length;
-  void *option_data;
 };
 
 
index e6a520bb8d7053dc8260f35d6b89697366177ed6..4e5fdbdf026ee451361080796db69cc786279300 100644 (file)
@@ -30,14 +30,10 @@ struct linger {
 #define AF_UNSPEC      0
 #define AF_UNIX                1
 #define AF_INET                2
-#define AF_AX25                3
-#define AF_IPX         4
 
 /* Protocol families, same as address families. */
 #define PF_UNIX                AF_UNIX
 #define PF_INET                AF_INET
-#define PF_AX25                AF_AX25
-#define PF_IPX         AF_IPX
 
 /* Flags we can use with send/ and recv. */
 #define MSG_OOB                1
@@ -45,10 +41,6 @@ struct linger {
 
 /* Setsockoptions(2) level. */
 #define SOL_SOCKET     1
-#define SOL_IP         2
-#define SOL_IPX                3
-#define SOL_AX25       4
-#define SOL_TCP                5
 
 /* For setsockoptions(2) */
 #define SO_DEBUG       1
@@ -64,19 +56,6 @@ struct linger {
 #define SO_NO_CHECK    11
 #define SO_PRIORITY    12
 #define SO_LINGER      13
-/* IP options */
-#define IP_TOS         1
-#define        IPTOS_LOWDELAY          0x10
-#define        IPTOS_THROUGHPUT        0x08
-#define        IPTOS_RELIABILITY       0x04
-#define IP_TTL         2
-/* IPX options */
-#define IPX_TYPE       1
-/* AX.25 options */
-#define AX25_WINDOW    1
-/* TCP options */
-#define TCP_MSS                1
-#define TCP_NODELAY    2
 
 /* The various priorities. */
 #define SOPRI_INTERACTIVE      0
index 4484b146cb926e17845fd70962eeebb92d050bb9..499b2190add5bc9557cf7158ca2fd5f2ff9f7713 100644 (file)
 #define IP_SET_DEV     0x2401
 
 struct ip_config {
-       char            name[MAX_IP_NAME];
-       unsigned long   paddr;
-       unsigned long   router;
-       unsigned long   net;
-       unsigned int    up:1,destroy:1;
+  char         name[MAX_IP_NAME];
+  unsigned long        paddr;
+  unsigned long        router;
+  unsigned long        net;
+  unsigned int up:1,destroy:1;
 };
 #endif /* FIXME: */
 
index 8299a0ebc8faa3684f43b70fad272ae95262c2d6..6478d1e335d4b7c20a7007a5782753be611887da 100644 (file)
@@ -7,17 +7,10 @@
 #
 # Note 2! The CFLAGS definition is now in the main makefile...
 
-SUBDIRS     := unix socket 
+# only these two lines should need to be changed to remove inet sockets.
+# (and the inet/tcpip.o in net.o)
 
-ifdef CONFIG_INET
-SUBDIRS            := $(SUBDIRS) inet
-endif
-ifdef CONFIG_IPX
-SUBDIRS            := $(SUBDIRS) ipx
-endif
-ifdef CONFIG_AX25
-SUBDIRS     := $(SUBDIRS) ax25
-endif
+SUBDIRS     := unix inet
 
 SUBOBJS     := $(foreach f,$(SUBDIRS),$f/$f.o)
 
index 5c90082fc6b2ccaf1ec29d0cda076178cadd2f24..b2cc011ad4769135901abbc96896356f4d178fb9 100644 (file)
 #  include "inet/inet.h"
 #endif
 #ifdef CONFIG_IPX
-#include "ipx/ipxcall.h"
+#include "inet/ipxcall.h"
 #endif
 #ifdef CONFIG_AX25
-#include "ax25/ax25call.h"
+#include "inet/ax25call.h"
 #endif
 
 struct ddi_proto protocols[] = {
@@ -53,3 +53,43 @@ struct ddi_proto protocols[] = {
 };
 
 
+/*
+ * Section B:  Device Driver Modules.
+ *             This section defines which network device drivers
+ *             get linked into the Linux kernel.  It is currently
+ *             only used by the INET protocol.  Any takers for the
+ *             other protocols like XNS or Novell?
+ *
+ * WARNING:    THIS SECTION IS NOT YET USED BY THE DRIVERS !!!!!
+ */
+/*#include "drv/we8003/we8003.h"       Western Digital WD-80[01]3      */
+/*#include "drv/dp8390/dp8390.h"       Donald Becker's DP8390 kit      */
+/*#inclde "drv/slip/slip.h"            Laurence Culhane's SLIP kit     */
+
+
+struct ddi_device devices[] = {
+#if CONF_WE8003
+  { "WD80x3[EBT]",
+       "",     0,      1,      we8003_init,    NULL,
+       19,     0,      DDI_FCHRDEV,
+    { 0x280,   0,      15,     0,      32768,  0xD0000         }       },
+#endif
+#if CONF_DP8390
+  { "DP8390/WD80x3",
+       "",     0,      1,      dpwd8003_init,  NULL,
+       20,     0,      DDI_FCHRDEV,
+    {  0,      0,      0,      0,      0,      0,              }       },
+  { "DP8390/NE-x000",
+       "",     0,      1,      dpne2000_init,  NULL,
+       20,     8,      DDI_FCHRDEV,
+    {  0,      0,      0,      0,      0,      0,              }       },
+  { "DP8390/3C50x",
+       "",     0,      1,      dpec503_init,   NULL,
+       20,     16,     DDI_FCHRDEV,
+    {  0,      0,      0,      0,      0,      0,              }       },
+#endif
+  { NULL,
+       "",     0,      0,      NULL,           NULL,
+       0,      0,      0,
+    {  0,      0,      0,      0,      0,      0               }       }
+};
index 79bcb00c247edd01331749c3cd9393f520869fef..7ebd3bf293b8a0fec15e2b9344b3fcbd8c1612ec 100644 (file)
--- a/net/ddi.c
+++ b/net/ddi.c
@@ -4,11 +4,9 @@
  *             but it eventually might move to an upper directory of
  *             the system.
  *
- * Version:    @(#)ddi.c       1.28    27/12/93
+ * Version:    @(#)ddi.c       1.0.5   04/22/93
  *
  * Author:     Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
- *
- *     Unused pieces nobbled.
  */
 #include <asm/segment.h>
 #include <asm/system.h>
@@ -20,9 +18,6 @@
 #include <linux/mm.h>
 #include <linux/socket.h>
 #include <linux/ddi.h>
-#include <linux/interrupt.h>
-
-#include "socket/dev.h"
 
 
 #undef DDI_DEBUG
 #endif
 
 
+extern struct ddi_device       devices[];      /* device driver map    */
 extern struct ddi_proto                protocols[];    /* network protocols    */
 
 
+/*
+ * This function gets called with an ASCII string representing the
+ * ID of some DDI driver.  We loop through the DDI Devices table
+ * and return the address of the control block that has a matching
+ * "name" field.  It is used by upper-level layers that want to
+ * dynamically bind some UNIX-domain "/dev/XXXX" file name to a
+ * DDI device driver.  The "iflink(8)" program is an example of
+ * this behaviour.
+ */
+struct ddi_device *
+ddi_map(const char *id)
+{
+  register struct ddi_device *dev;
+
+  PRINTK (("DDI: MAP: looking for \"%s\": ", id));
+  dev = devices;
+  while (dev->title != NULL) {
+       if (strncmp(dev->name, id, DDI_MAXNAME) == 0) {
+               PRINTK (("OK at 0x%X\n", dev));
+               return(dev);
+       }
+       dev++;
+  }
+  PRINTK (("NOT FOUND\n"));
+  return(NULL);
+}
+
+
 /*
  * This is the function that is called by a kernel routine during
  * system startup.  Its purpose is to walk trough the "devices"
  * table (defined above), and to call all moduled defined in it.
  */
-void ddi_init(void)
+void
+ddi_init(void)
 {
-       struct ddi_proto *pro;
+  struct ddi_proto *pro;
+  struct ddi_device *dev;
 
-       PRINTK (("DDI: Starting up!\n"));
+  PRINTK (("DDI: Starting up!\n"));
 
-       /* First off, kick all configured protocols. */
-       pro = protocols;
-       while (pro->name != NULL) 
-       {
-               (*pro->init)(pro);
-               pro++;
-       }
+  /* First off, kick all configured protocols. */
+  pro = protocols;
+  while (pro->name != NULL) {
+       (*pro->init)(pro);
+       pro++;
+  }
   
-       dev_init();
-       /* Initialize the "Buffer Head" pointers. */
-       bh_base[INET_BH].routine = inet_bh;
-  
-       /* We're all done... */
-}      
+  /* Done.  Now kick all configured device drivers. */
+  dev = devices;
+  while (dev->title != NULL) {
+       (*dev->init)(dev);
+       dev++;
+  }
+
+  /* We're all done... */
+}
index 4c1aa76471642b86ea786241e31deaf178d4dab8..a10caa33ed45741f74b487bec679f0316e729874 100644 (file)
@@ -7,9 +7,6 @@
 #
 # Note 2! The CFLAGS definition is now in the main makefile...
 
-CFLAGS := $(CFLAGS) -I../socket -I..
-CPP := $(CPP) -I../socket -I..
-
 .c.o:
        $(CC) $(CFLAGS) -c -o $*.o $<
 .s.o:
@@ -18,8 +15,10 @@ CPP := $(CPP) -I../socket -I..
        $(CC) $(CFLAGS) -S -o $*.s $<
 
 
-OBJS   = sockinet.o utils.o route.o proc.o timer.o protocol.o loopback.o \
-         eth.o packet.o arp.o devinet.o ip.o raw.o icmp.o tcp.o udp.o
+OBJS   = sock.o utils.o route.o proc.o timer.o protocol.o loopback.o \
+         eth.o packet.o arp.o dev.o ip.o raw.o icmp.o tcp.o udp.o \
+         datagram.o skbuff.o
+#        ipx.o ax25.o ax25_in.o ax25_out.o ax25_subr.o ax25_timer.o
 
 ifdef CONFIG_INET
 
index f216f16af5cd29d1d7c73c2e43f624cec79b9129..79f957ff26ef154a5ab59b22ace39fc02749b949 100644 (file)
@@ -1,8 +1,27 @@
 
-NET2Debugged 1.28 README
+NET2Debugged 1.24 README
 ------------------------
 
-
+Major Changes
+
+o      PLIP driver sort of works
+o      UDP and RAW have been partially rewritten for speed
+o      Internals heavily cleaned up, and memory monitoring of network
+       memory is now done. (On shift-scroll-lock)
+o      ARP should now not generate garbage
+o      Using MSG_PEEK can't cause race conditions and crashes
+o      Support for bootp clients.
+o      Supports RFC931 TAP authd
+o      NFS problems with certain types of network configuration are
+       fixed.
+o      Doesn't forward packets for other subnet (can cause packet storms)
+o      TCP won't ack rst frames causing packet storms (especially with
+       Lan workplace for DOS).
+o      Numerous fixes for solidity
+o      Verify_area used properly.
+o      MSG_PEEK is faster again
+o      Minor TCP fixes. Hopefully no more TCP lockups (ha!)
+o      Donald's promiscuous mode. Go forth and write protocol analysers...
 -------------------------------------------------------------------------
 NOTE:
        Drivers for this stack set must be using alloc_skb() not just
index c272817c284d233b485dc461ead283da41a3e43e..0b69e1f6f73ac86902a3e3a645a974777f0e1ae8 100644 (file)
@@ -13,7 +13,7 @@
  *             resolver, like it should be.  It will be put in a separate
  *             directory under 'net', being a protocol of its own. -FvK
  *
- * Version:    @(#)arp.c       1.28    20/12/93
+ * Version:    @(#)arp.c       1.0.15  05/25/93
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *             Alan Cox        :       skb->link3 maintained by letting the other xmit queue kill the packet.
  *             Alan Cox        :       Knows about type 3 devices (AX.25) using an AX.25 protocol ID not the ethernet
  *                                     one.
- *             Dominik Kubla   :       Better checking
- *             Tegge           :       Assorted corrections on cross port stuff
- *             Alan Cox        :       Heavily reformatted & recommented ready for the big day
- *             Alan Cox        :       ATF_PERM was backwards! - might be useful now (sigh)
- *
  *
  * To Fix:
  *                             :       arp response allocates an skbuff to send. However there is a perfectly
 #include <asm/segment.h>
 #include <stdarg.h>
 #include "inet.h"
-#include "devinet.h"
+#include "dev.h"
 #include "eth.h"
 #include "ip.h"
 #include "route.h"
 #include "protocol.h"
 #include "tcp.h"
 #include "skbuff.h"
-#include "sockinet.h"
+#include "sock.h"
 #include "arp.h"
 
-/*
- *     We will try an ARP the recommended three times before we abandon it. If we
- *     do abandon it all is not lost as the next frame will also try.
- */
 
 #define ARP_MAX_TRIES  3
 
-/*
- *     The ARP table itself
- */
+
+static char *unk_print(unsigned char *, int);
+static char *eth_aprint(unsigned char *, int);
+
+
+static char *arp_cmds[] = {
+  "0x%04X",
+  "REQUEST",
+  "REPLY",
+  "REVERSE REQUEST",
+  "REVERSE REPLY",
+  NULL
+};
+#define        ARP_MAX_CMDS    (sizeof(arp_cmds) / sizeof(arp_cmds[0]))
+
+static struct {
+  char *name;
+  char *(*print)(unsigned char *ptr, int len);
+} arp_types[] = {
+  { "0x%04X",                  unk_print       },
+  { "10 Mbps Ethernet",        eth_aprint      },
+  { "3 Mbps Ethernet",         eth_aprint      },
+  { "AX.25",                   unk_print       },
+  { "Pronet",                  unk_print       },
+  { "Chaos",                   unk_print       },
+  { "IEEE 802.2 Ethernet (?)", eth_aprint      },
+  { "Arcnet",                  unk_print       },
+  { "AppleTalk",               unk_print       },
+  { NULL,                      NULL            }
+};
+#define        ARP_MAX_TYPE    (sizeof(arp_types) / sizeof(arp_types[0]))
+
+
 struct arp_table *arp_tables[ARP_TABLE_SIZE] = {
   NULL,
 };
@@ -98,43 +118,103 @@ static int arp_proxies=0; /* So we can avoid the proxy arp
                                   overhead with the usual case of
                                   no proxy arps */
 
-/*
- *     Every packet awaiting an ARP resolution is stuffed on this
- *     queue until resolved or deleted. Note items in this queue
- *     may be on other (tcp retransmit) queues and we must not
- *     be the one to delete them.
- */
 struct sk_buff * volatile arp_q = NULL;
 
 static struct arp_table *arp_lookup(unsigned long addr);
 static struct arp_table *arp_lookup_proxy(unsigned long addr);
 
-/*
- *     We grab the arp queue, empty it and walk down it adding anything we can't
- *     resolve back onto the queue. We MUST do things this way as other entries
- *     may (will) get added as we walk the old list.
- */
+/* Dump the ADDRESS bytes of an unknown hardware type. */
+static char *
+unk_print(unsigned char *ptr, int len)
+{
+  static char buff[32];
+  char *bufp = buff;
+  int i;
+
+  for (i = 0; i < len; i++)
+       bufp += sprintf(bufp, "%02X ", (*ptr++ & 0377));
+  return(buff);
+}
+
 
-static void arp_send_q(void)
+/* Dump the ADDRESS bytes of an Ethernet hardware type. */
+static char *
+eth_aprint(unsigned char *ptr, int len)
 {
-       struct sk_buff *skb;
-       struct sk_buff *volatile work_q;
-       cli();
-       work_q = arp_q;
-       skb_new_list_head(&work_q);
-       arp_q = NULL;
-       sti();
-       while((skb=skb_dequeue(&work_q))!=NULL)
-       {
-               IS_SKB(skb);
-               skb->magic = 0;         /* So everyone knows this is _NOT_ on the arp queue */
+  if (len != ETH_ALEN) return("");
+  return(eth_print(ptr));
+}
 
-               /* Decrement the 'tries' counter. */
-               cli();
-               skb->tries--;
-               if (skb->tries == 0) 
-               {
+
+/* Dump an ARP packet. Not complete yet for non-Ethernet packets. */
+static void
+arp_print(struct arphdr *arp)
+{
+  int len, idx;
+  unsigned char *ptr;
+
+  if (inet_debug != DBG_ARP) return;
+
+  printk("ARP: ");
+  if (arp == NULL) {
+       printk("(null)\n");
+       return;
+  }
+
+  /* Print the opcode name. */
+  len = htons(arp->ar_op);
+  if (len < ARP_MAX_CMDS) idx = len;
+    else idx = 0;
+  printk("op ");
+  printk(arp_cmds[idx], len);
+
+  /* Print the ARP header. */
+  len = htons(arp->ar_hrd);
+  if (len < ARP_MAX_TYPE) idx = len;
+    else idx = 0;
+  printk("   hrd = "); printk(arp_types[idx].name, len);
+  printk("   pro = 0x%04X\n", htons(arp->ar_pro));
+  printk("   hlen = %d plen = %d\n", arp->ar_hln, arp->ar_pln);
+
+  /*
+   * Print the variable data.
+   * When ARP gets redone (after the formal introduction of NET-2),
+   * this part will be redone.  ARP will then be a multi-family address
+   * resolver, and the code below will be made more general. -FvK
+   */
+  ptr = ((unsigned char *) &arp->ar_op) + sizeof(u_short);
+  printk("   sender HA = %s ", arp_types[idx].print(ptr, arp->ar_hln));
+  ptr += arp->ar_hln;
+  printk("  PA = %s\n", in_ntoa(*(unsigned long *) ptr));
+  ptr += arp->ar_pln;
+  printk("   target HA = %s ", arp_types[idx].print(ptr, arp->ar_hln));
+  ptr += arp->ar_hln;
+  printk("  PA = %s\n", in_ntoa(*(unsigned long *) ptr));
+}
+
+
+/* This will try to retransmit everything on the queue. */
+static void
+arp_send_q(void)
+{
+  struct sk_buff *skb;
+  struct sk_buff *volatile work_q;
+  cli();
+  work_q = arp_q;
+  skb_new_list_head(&work_q);
+  arp_q = NULL;
+  sti();
+  while((skb=skb_dequeue(&work_q))!=NULL)
+  {
+       IS_SKB(skb);
+       skb->magic = 0;
+       skb->next = NULL;
+       skb->prev = NULL;
+
+       /* Decrement the 'tries' counter. */
+       cli();
+       skb->tries--;
+       if (skb->tries == 0) {
                /*
                 * Grmpf.
                 * We have tried ARP_MAX_TRIES to resolve the IP address
@@ -144,270 +224,231 @@ static void arp_send_q(void)
                 * In any case, trying further is useless.  So, we kill
                 * this packet from the queue.  (grinnik) -FvK
                 */
-                       skb->sk = NULL;
-                       if(skb->free)
-                               kfree_skb(skb, FREE_WRITE);
+               skb->sk = NULL;
+               if(skb->free)
+                       kfree_skb(skb, FREE_WRITE);
                        /* If free was 0, magic is now 0, next is 0 and 
                           the write queue will notice and kill */
-                       sti();
-                       continue;
-               }
-
-               /* Can we now complete this packet? */
                sti();
-               if (skb->arp || !skb->dev->rebuild_header(skb+1, skb->dev)) 
-               {
-                       skb->arp  = 1;
-                       skb->dev->queue_xmit(skb, skb->dev, 0);
-               } 
-               else 
-               {
-                       /* Alas.  Re-queue it... */
-                       skb->magic = ARP_QUEUE_MAGIC;      
-                       skb_queue_head(&arp_q,skb);
-               }
-       }
+               continue;
+       }
+
+       /* Can we now complete this packet? */
+       sti();
+       if (skb->arp || !skb->dev->rebuild_header(skb+1, skb->dev)) {
+               skb->arp  = 1;
+               skb->dev->queue_xmit(skb, skb->dev, 0);
+       } else {
+               /* Alas.  Re-queue it... */
+               skb->magic = ARP_QUEUE_MAGIC;      
+               skb_queue_head(&arp_q,skb);
+       }
+  }
 }
 
 
-/*
- *     Create and send our response to an ARP request. 
- */
-static int arp_response(struct arphdr *arp1, struct device *dev,  int addrtype)
+/* Create and send our response to an ARP request. */
+static int
+arp_response(struct arphdr *arp1, struct device *dev,  int addrtype)
 {
-       struct arphdr *arp2;
-       struct sk_buff *skb;
-       unsigned long src, dst;
-       unsigned char *ptr1, *ptr2;
-       int hlen;
-       struct arp_table *apt = NULL;/* =NULL otherwise the compiler gives warnings */
-
-       /* Decode the source (REQUEST) message. */
-       ptr1 = ((unsigned char *) &arp1->ar_op) + sizeof(u_short);
-       src = *((unsigned long *) (ptr1 + arp1->ar_hln));
-       dst = *((unsigned long *) (ptr1 + (arp1->ar_hln * 2) + arp1->ar_pln));
+  struct arphdr *arp2;
+  struct sk_buff *skb;
+  unsigned long src, dst;
+  unsigned char *ptr1, *ptr2;
+  int hlen;
+  struct arp_table *apt = NULL;/* =NULL otherwise the compiler gives warnings */
+
+  /* Decode the source (REQUEST) message. */
+  ptr1 = ((unsigned char *) &arp1->ar_op) + sizeof(u_short);
+  src = *((unsigned long *) (ptr1 + arp1->ar_hln));
+  dst = *((unsigned long *) (ptr1 + (arp1->ar_hln * 2) + arp1->ar_pln));
   
-       if(addrtype!=IS_MYADDR)
-       {
-               apt=arp_lookup_proxy(dst);
-               if(apt==NULL)
-                       return(1);
-       }
-
-       /* Get some mem and initialize it for the return trip. */
-       skb = alloc_skb(sizeof(struct sk_buff) +
+  if(addrtype!=IS_MYADDR)
+  {
+       apt=arp_lookup_proxy(dst);
+       if(apt==NULL)
+               return(1);
+  }
+
+  /* Get some mem and initialize it for the return trip. */
+  skb = alloc_skb(sizeof(struct sk_buff) +
                sizeof(struct arphdr) +
                (2 * arp1->ar_hln) + (2 * arp1->ar_pln) +
                dev->hard_header_len, GFP_ATOMIC);
-
-       if (skb == NULL) 
-       {
-               printk("ARP: no memory available for ARP REPLY!\n");
-               return(1);
-       }
-
-       skb->len      = sizeof(struct arphdr) + (2 * arp1->ar_hln) + 
-                         (2 * arp1->ar_pln) + dev->hard_header_len;
-       hlen = dev->hard_header((unsigned char *)(skb+1), dev,
+  if (skb == NULL) {
+       printk("ARP: no memory available for ARP REPLY!\n");
+       return(1);
+  }
+
+  skb->mem_addr = skb;
+  skb->len      = sizeof(struct arphdr) + (2 * arp1->ar_hln) + 
+                 (2 * arp1->ar_pln) + dev->hard_header_len;
+  skb->mem_len  = sizeof(struct sk_buff) + skb->len;
+  hlen = dev->hard_header((unsigned char *)(skb+1), dev,
                         ETH_P_ARP, src, dst, skb->len);
-       if (hlen < 0) 
-       {
-               printk("ARP: cannot create HW frame header for REPLY !\n");
-               kfree_skb(skb, FREE_WRITE);
-               return(1);
-       }
+  if (hlen < 0) {
+       printk("ARP: cannot create HW frame header for REPLY !\n");
+       kfree_skb(skb, FREE_WRITE);
+       return(1);
+  }
 
   /*
    * Fill in the ARP REPLY packet.
    * This looks ugly, but we have to deal with the variable-length
    * ARP packets and such.  It is not as bad as it looks- FvK
    */
-       arp2 = (struct arphdr *) ((unsigned char *) (skb+1) + hlen);
-       ptr2 = ((unsigned char *) &arp2->ar_op) + sizeof(u_short);
-       arp2->ar_hrd = arp1->ar_hrd;
-       arp2->ar_pro = arp1->ar_pro;
-       arp2->ar_hln = arp1->ar_hln;
-       arp2->ar_pln = arp1->ar_pln;
-       arp2->ar_op = htons(ARPOP_REPLY);
-
-       if(addrtype==IS_MYADDR)
-                 memcpy(ptr2, dev->dev_addr, arp2->ar_hln);
-         else          /* Proxy arp, so pull from the table */
-                 memcpy(ptr2, apt->ha, arp2->ar_hln);
-
-       ptr2 += arp2->ar_hln;
-       memcpy(ptr2, ptr1 + (arp1->ar_hln * 2) + arp1->ar_pln, arp2->ar_pln);
-       ptr2 += arp2->ar_pln;
-       memcpy(ptr2, ptr1, arp2->ar_hln);
-       ptr2 += arp2->ar_hln;
-       memcpy(ptr2, ptr1 + arp1->ar_hln, arp2->ar_pln);
-
-       skb->free = 1;
-       skb->arp = 1;
-       skb->sk = NULL;
-       skb->next = NULL;
-       
-       /* Queue the packet for transmission. */
-       dev->queue_xmit(skb, dev, 0);
-       return(0);
+  arp2 = (struct arphdr *) ((unsigned char *) (skb+1) + hlen);
+  ptr2 = ((unsigned char *) &arp2->ar_op) + sizeof(u_short);
+  arp2->ar_hrd = arp1->ar_hrd;
+  arp2->ar_pro = arp1->ar_pro;
+  arp2->ar_hln = arp1->ar_hln;
+  arp2->ar_pln = arp1->ar_pln;
+  arp2->ar_op = htons(ARPOP_REPLY);
+  if(addrtype==IS_MYADDR)
+         memcpy(ptr2, dev->dev_addr, arp2->ar_hln);
+  else         /* Proxy arp, so pull from the table */
+         memcpy(ptr2, apt->ha, arp2->ar_hln);
+  ptr2 += arp2->ar_hln;
+  memcpy(ptr2, ptr1 + (arp1->ar_hln * 2) + arp1->ar_pln, arp2->ar_pln);
+  ptr2 += arp2->ar_pln;
+  memcpy(ptr2, ptr1, arp2->ar_hln);
+  ptr2 += arp2->ar_hln;
+  memcpy(ptr2, ptr1 + arp1->ar_hln, arp2->ar_pln);
+
+  skb->free = 1;
+  skb->arp = 1;
+  skb->sk = NULL;
+  skb->next = NULL;
+
+  DPRINTF((DBG_ARP, ">>"));
+  arp_print(arp2);
+
+  /* Queue the packet for transmission. */
+  dev->queue_xmit(skb, dev, 0);
+  return(0);
 }
 
 
-/*
- * This will find an entry in the ARP table by looking at the IP address.
- */
-static struct arp_table *arp_lookup(unsigned long paddr)
+/* This will find an entry in the ARP table by looking at the IP address. */
+static struct arp_table *
+arp_lookup(unsigned long paddr)
 {
-       struct arp_table *apt;
-       unsigned long hash;
-
-       DPRINTF((DBG_ARP, "ARP: lookup(%s)\n", in_ntoa(paddr)));
-
-       /* We don't want to ARP ourselves. */
-       if (chk_addr(paddr) == IS_MYADDR) 
-       {
-               printk("ARP: ARPing my own IP address %s !\n", in_ntoa(paddr));
-               return(NULL);
-       }
-
-       /* Loop through the table for the desired address. */
-       hash = htonl(paddr) & (ARP_TABLE_SIZE - 1);
-       cli();
-       apt = arp_tables[hash];
-       while(apt != NULL) 
-       {
-               if (apt->ip == paddr) 
-               {
-                       sti();
-                       return(apt);
-               }
-               apt = apt->next;
-       }
-       sti();
-       return(NULL);
+  struct arp_table *apt;
+  unsigned long hash;
+
+  DPRINTF((DBG_ARP, "ARP: lookup(%s)\n", in_ntoa(paddr)));
+
+  /* We don't want to ARP ourselves. */
+  if (chk_addr(paddr) == IS_MYADDR) {
+       printk("ARP: ARPing my own IP address %s !\n", in_ntoa(paddr));
+       return(NULL);
+  }
+
+  /* Loop through the table for the desired address. */
+  hash = htonl(paddr) & (ARP_TABLE_SIZE - 1);
+  cli();
+  apt = arp_tables[hash];
+  while(apt != NULL) {
+       if (apt->ip == paddr) {
+               sti();
+               return(apt);
+       }
+       apt = apt->next;
+  }
+  sti();
+  return(NULL);
 }
 
 
-/*
- *     This will find a proxy in the ARP table by looking at the IP address.
- */
-
+/* This will find a proxy in the ARP table by looking at the IP address. */
 static struct arp_table *arp_lookup_proxy(unsigned long paddr)
 {
-       struct arp_table *apt;
-       unsigned long hash;
+  struct arp_table *apt;
+  unsigned long hash;
 
-       DPRINTF((DBG_ARP, "ARP: lookup proxy(%s)\n", in_ntoa(paddr)));
+  DPRINTF((DBG_ARP, "ARP: lookup proxy(%s)\n", in_ntoa(paddr)));
 
-       /* Loop through the table for the desired address. */
-       hash = htonl(paddr) & (ARP_TABLE_SIZE - 1);
-       cli();
-       apt = arp_tables[hash];
-       while(apt != NULL) 
-       {
-               if (apt->ip == paddr && (apt->flags & ATF_PUBL) ) 
-               {
-                       sti();
-                       return(apt);
-               }
-               apt = apt->next;
-       }       
-       sti();
-       return(NULL);
+  /* Loop through the table for the desired address. */
+  hash = htonl(paddr) & (ARP_TABLE_SIZE - 1);
+  cli();
+  apt = arp_tables[hash];
+  while(apt != NULL) {
+       if (apt->ip == paddr && (apt->flags & ATF_PUBL) ) {
+               sti();
+               return(apt);
+       }
+       apt = apt->next;
+  }
+  sti();
+  return(NULL);
 }
 
 
-/*
- *     Delete an ARP mapping entry in the cache.
- */
-static void arp_destructor(unsigned long paddr, int force)
+/* Delete an ARP mapping entry in the cache. */
+void
+arp_destroy(unsigned long paddr)
 {
-       struct arp_table *apt;
-       struct arp_table **lapt;
-       unsigned long hash;
+  struct arp_table *apt;
+  struct arp_table **lapt;
+  unsigned long hash;
 
-       DPRINTF((DBG_ARP, "ARP: destroy(%s)\n", in_ntoa(paddr)));
+  DPRINTF((DBG_ARP, "ARP: destroy(%s)\n", in_ntoa(paddr)));
 
-       /* We cannot destroy our own ARP entry. */
-       if (chk_addr(paddr) == IS_MYADDR) 
-       {
-               DPRINTF((DBG_ARP, "ARP: Destroying my own IP address %s !\n",
+  /* We cannot destroy our own ARP entry. */
+  if (chk_addr(paddr) == IS_MYADDR) {
+       DPRINTF((DBG_ARP, "ARP: Destroying my own IP address %s !\n",
                                                        in_ntoa(paddr)));
+       return;
+  }
+  hash = htonl(paddr) & (ARP_TABLE_SIZE - 1);
+
+  cli();
+  lapt = &arp_tables[hash];
+  while ((apt = *lapt) != NULL) {
+       if (apt->ip == paddr) {
+               *lapt = apt->next;
+               if(apt->flags&ATF_PUBL)
+                       arp_proxies--;                  
+               kfree_s(apt, sizeof(struct arp_table));
+               sti();
                return;
        }
-       hash = htonl(paddr) & (ARP_TABLE_SIZE - 1);
-
-       cli();
-       lapt = &arp_tables[hash];
-       while ((apt = *lapt) != NULL) 
-       {
-               if (apt->ip == paddr) 
-               {
-                       if((apt->flags&ATF_PERM) && !force)
-                               return;
-                       *lapt = apt->next;
-                       if(apt->flags&ATF_PUBL)
-                               arp_proxies--;                  
-                       kfree_s(apt, sizeof(struct arp_table));
-                       sti();
-                       return;
-               }
-               lapt = &apt->next;
-       }
-       sti();
+       lapt = &apt->next;
+  }
+  sti();
 }
 
-/*
- *     Kill an entry - eg for ioctl()
- */
 
-void arp_destroy(unsigned long paddr)
-{      
-       arp_destructor(paddr,1);
-}
-
-/*
- *     Delete a possibly invalid entry (see timer.c)
- */
-
-void arp_destroy_maybe(unsigned long paddr)
+/* Create an ARP entry.  The caller should check for duplicates! */
+static struct arp_table *
+arp_create(unsigned long paddr, unsigned char *addr, int hlen, int htype)
 {
-       arp_destructor(paddr,0);
-}
-
-/*
- *     Create an ARP entry.  The caller should check for duplicates!
- */
-static struct arp_table *arp_create(unsigned long paddr, unsigned char *addr, int hlen, int htype)
-{
-       struct arp_table *apt;
-       unsigned long hash;
-
-
-       apt = (struct arp_table *) kmalloc(sizeof(struct arp_table), GFP_ATOMIC);
-       if (apt == NULL) 
-       {
-               printk("ARP: no memory available for new ARP entry!\n");
-               return(NULL);
-       }
-
-       /* Fill in the allocated ARP cache entry. */
-       hash = htonl(paddr) & (ARP_TABLE_SIZE - 1);
-       apt->ip = paddr;
-       apt->hlen = hlen;
-       apt->htype = htype;
-       apt->flags = (ATF_INUSE | ATF_COM);             /* USED and COMPLETED entry */
-       memcpy(apt->ha, addr, hlen);
-       apt->last_used = jiffies;
-       cli();
-       apt->next = arp_tables[hash];
-       arp_tables[hash] = apt;
-       sti();
-       return(apt);
+  struct arp_table *apt;
+  unsigned long hash;
+
+  DPRINTF((DBG_ARP, "ARP: create(%s, ", in_ntoa(paddr)));
+  DPRINTF((DBG_ARP, "%s, ", eth_print(addr)));
+  DPRINTF((DBG_ARP, "%d, %d)\n", hlen, htype));
+
+  apt = (struct arp_table *) kmalloc(sizeof(struct arp_table), GFP_ATOMIC);
+  if (apt == NULL) {
+       printk("ARP: no memory available for new ARP entry!\n");
+       return(NULL);
+  }
+
+  /* Fill in the allocated ARP cache entry. */
+  hash = htonl(paddr) & (ARP_TABLE_SIZE - 1);
+  apt->ip = paddr;
+  apt->hlen = hlen;
+  apt->htype = htype;
+  apt->flags = (ATF_INUSE | ATF_COM);          /* USED and COMPLETED entry */
+  memcpy(apt->ha, addr, hlen);
+  apt->last_used = jiffies;
+  cli();
+  apt->next = arp_tables[hash];
+  arp_tables[hash] = apt;
+  sti();
+  return(apt);
 }
 
 
@@ -420,295 +461,281 @@ static struct arp_table *arp_create(unsigned long paddr, unsigned char *addr, in
  * one of our own IP addresses), we set up and send out an ARP REPLY
  * packet to the sender.
  */
-int arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
+int
+arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
 {
-       struct arphdr *arp;
-       struct arp_table *tbl;
-       unsigned long src, dst;
-       unsigned char *ptr;
-       int ret;
-       int addr_hint;
-       
-       arp = skb->h.arp;
-
-       /* If this test doesn't pass, its not IP. Might be DECNET or friends */
-       if (arp->ar_hln != dev->addr_len || dev->type != NET16(arp->ar_hrd)) 
-       {
-               DPRINTF((DBG_ARP,"ARP: Bad packet received on device \"%s\" !\n", dev->name));
-               kfree_skb(skb, FREE_READ);
-               return(0);
-       }
+  struct arphdr *arp;
+  struct arp_table *tbl;
+  unsigned long src, dst;
+  unsigned char *ptr;
+  int ret;
+  int addr_hint;
+
+  DPRINTF((DBG_ARP, "<<\n"));
+  arp = skb->h.arp;
+  arp_print(arp);
+
+  /* If this test doesn't pass, its not IP. Might be DECNET or friends */
+  if (arp->ar_hln != dev->addr_len || dev->type != NET16(arp->ar_hrd)) 
+  {
+       DPRINTF((DBG_ARP,"ARP: Bad packet received on device \"%s\" !\n", dev->name));
+       kfree_skb(skb, FREE_READ);
+       return(0);
+  }
+
+  /* For now we will only deal with IP addresses. */
+  if (((arp->ar_pro != NET16(0x00CC) && dev->type==3) || (arp->ar_pro != NET16(ETH_P_IP) && dev->type!=3) ) || arp->ar_pln != 4) 
+  {
+       if (arp->ar_op != NET16(ARPOP_REQUEST))
+               DPRINTF((DBG_ARP,"ARP: Non-IP request on device \"%s\" !\n", dev->name));
+       kfree_skb(skb, FREE_READ);
+       return(0);
+  }
 
-       /* For now we will only deal with IP addresses. */
-       if (((arp->ar_pro != NET16(0x00CC) && dev->type==3) || (arp->ar_pro != NET16(ETH_P_IP) && dev->type!=3) ) || arp->ar_pln != 4) 
-       {
-               if (arp->ar_op != NET16(ARPOP_REQUEST))
-                       DPRINTF((DBG_ARP,"ARP: Non-IP request on device \"%s\" !\n", dev->name));
+  /*
+   * As said before, we try to be smart by using the
+   * info already present in the packet: the sender's
+   * IP and hardware address.
+   */
+  ptr = ((unsigned char *) &arp->ar_op) + sizeof(u_short);
+  memcpy(&src, ptr + arp->ar_hln, arp->ar_pln);
+  tbl = arp_lookup(src);
+  if (tbl != NULL) {
+       DPRINTF((DBG_ARP, "ARP: udating entry for %s\n", in_ntoa(src)));
+       memcpy(tbl->ha, ptr, arp->ar_hln);
+       tbl->hlen = arp->ar_hln;
+       tbl->flags |= ATF_COM;
+       tbl->last_used = jiffies;
+  } else {
+       memcpy(&dst, ptr + (arp->ar_hln * 2) + arp->ar_pln, arp->ar_pln);
+       if (chk_addr(dst) != IS_MYADDR) {
                kfree_skb(skb, FREE_READ);
                return(0);
-       }
-
-       /*
-        * As said before, we try to be smart by using the
-        * info already present in the packet: the sender's
-        * IP and hardware address.
-        */
-       ptr = ((unsigned char *) &arp->ar_op) + sizeof(u_short);
-       memcpy(&src, ptr + arp->ar_hln, arp->ar_pln);
-       tbl = arp_lookup(src);
-       if (tbl != NULL) 
-       {
-               DPRINTF((DBG_ARP, "ARP: udating entry for %s\n", in_ntoa(src)));
-               memcpy(tbl->ha, ptr, arp->ar_hln);
-               tbl->hlen = arp->ar_hln;
-               tbl->flags |= ATF_COM;
-               tbl->last_used = jiffies;
-       } 
-       else
-       {
-               memcpy(&dst, ptr + (arp->ar_hln * 2) + arp->ar_pln, arp->ar_pln);
-               if (chk_addr(dst) != IS_MYADDR) 
-               {
+       } else {
+               tbl = arp_create(src, ptr, arp->ar_hln, arp->ar_hrd);
+               if (tbl == NULL) {
                        kfree_skb(skb, FREE_READ);
                        return(0);
-               } 
-               else 
-               {
-                       tbl = arp_create(src, ptr, arp->ar_hln, arp->ar_hrd);
-                       if (tbl == NULL) 
-                       {
-                               kfree_skb(skb, FREE_READ);
-                               return(0);
-                       }
                }
-       }
+       }
+  }
 
   /*
    * Since we updated the ARP cache, we might have enough
    * information to send out some previously queued IP
    * datagrams....
    */
-       arp_send_q();
+  arp_send_q();
 
   /*
    * OK, we used that part of the info.  Now check if the
    * request was an ARP REQUEST for one of our own addresses..
    */
-       if (arp->ar_op != NET16(ARPOP_REQUEST)) 
-       {
-               kfree_skb(skb, FREE_READ);
-               return(0);
-       }
+  if (arp->ar_op != NET16(ARPOP_REQUEST)) {
+       kfree_skb(skb, FREE_READ);
+       return(0);
+  }
 
   /*
    * A broadcast arp, ignore it
    */
 
-       if(chk_addr(dst)==IS_BROADCAST)
-       {
-               kfree_skb(skb, FREE_READ);
-               return 0;
-       }
+  if((dst&0xFF)==0xFF)
+  {
+       kfree_skb(skb, FREE_READ);
+       return 0;
+  }
 
-       memcpy(&dst, ptr + (arp->ar_hln * 2) + arp->ar_pln, arp->ar_pln);
-       if ((addr_hint=chk_addr(dst)) != IS_MYADDR && arp_proxies==0) 
-       {
-               DPRINTF((DBG_ARP, "ARP: request was not for me!\n"));
-               kfree_skb(skb, FREE_READ);
-               return(0);
-       }
-
-       /*
-        * Yes, it is for us.
-        * Allocate, fill in and send an ARP REPLY packet.
-        */
-       ret = arp_response(arp, dev, addr_hint);
-       kfree_skb(skb, FREE_READ);
-       return(ret);
+  memcpy(&dst, ptr + (arp->ar_hln * 2) + arp->ar_pln, arp->ar_pln);
+  if ((addr_hint=chk_addr(dst)) != IS_MYADDR && arp_proxies==0) {
+       DPRINTF((DBG_ARP, "ARP: request was not for me!\n"));
+       kfree_skb(skb, FREE_READ);
+       return(0);
+  }
+
+  /*
+   * Yes, it is for us.
+   * Allocate, fill in and send an ARP REPLY packet.
+   */
+  ret = arp_response(arp, dev, addr_hint);
+  kfree_skb(skb, FREE_READ);
+  return(ret);
 }
 
 
-/*
- *     Create and send an ARP REQUEST packet. 
- */
-void arp_send(unsigned long paddr, struct device *dev, unsigned long saddr)
+/* Create and send an ARP REQUEST packet. */
+void
+arp_send(unsigned long paddr, struct device *dev, unsigned long saddr)
 {
-       struct sk_buff *skb;
-       struct arphdr *arp;
-       unsigned char *ptr;
-       int tmp;
+  struct sk_buff *skb;
+  struct arphdr *arp;
+  unsigned char *ptr;
+  int tmp;
 
-       DPRINTF((DBG_ARP, "ARP: send(paddr=%s, ", in_ntoa(paddr)));
-       DPRINTF((DBG_ARP, "dev=%s, ", dev->name));
-       DPRINTF((DBG_ARP, "saddr=%s)\n", in_ntoa(saddr)));
+  DPRINTF((DBG_ARP, "ARP: send(paddr=%s, ", in_ntoa(paddr)));
+  DPRINTF((DBG_ARP, "dev=%s, ", dev->name));
+  DPRINTF((DBG_ARP, "saddr=%s)\n", in_ntoa(saddr)));
 
-       skb = alloc_skb(sizeof(struct sk_buff) +
+  skb = alloc_skb(sizeof(struct sk_buff) +
                sizeof(struct arphdr) + (2 * dev->addr_len) +
                dev->hard_header_len +
                (2 * 4 /* arp->plen */), GFP_ATOMIC);
-       if (skb == NULL) 
-       {
-               printk("ARP: No memory available for REQUEST %s\n", in_ntoa(paddr));
-               return;
-       }
+  if (skb == NULL) {
+       printk("ARP: No memory available for REQUEST %s\n", in_ntoa(paddr));
+       return;
+  }
   
-       /* Fill in the request. */
-       skb->sk = NULL;
-       skb->len = sizeof(struct arphdr) +
+  /* Fill in the request. */
+  skb->sk = NULL;
+  skb->mem_addr = skb;
+  skb->len = sizeof(struct arphdr) +
             dev->hard_header_len + (2 * dev->addr_len) + 8;
-       skb->arp = 1;
-       skb->dev = dev;
-       skb->next = NULL;
-       skb->free = 1;
-       tmp = dev->hard_header((unsigned char *)(skb+1), dev,
+  skb->mem_len = sizeof(struct sk_buff) + skb->len;
+  skb->arp = 1;
+  skb->dev = dev;
+  skb->next = NULL;
+  skb->free = 1;
+  tmp = dev->hard_header((unsigned char *)(skb+1), dev,
                          ETH_P_ARP, 0, saddr, skb->len);
-       if (tmp < 0) 
-       {
-               kfree_skb(skb,FREE_WRITE);
-               return;
-       }
-       arp = (struct arphdr *) ((unsigned char *) (skb+1) + tmp);
-       arp->ar_hrd = htons(dev->type);
-       if(dev->type!=3)        /* AX.25 */
-               arp->ar_pro = htons(ETH_P_IP);
-       else
-               arp->ar_pro = htons(0xCC);
-       arp->ar_hln = dev->addr_len;
-       arp->ar_pln = 4;
-       arp->ar_op = htons(ARPOP_REQUEST);
-
-       ptr = ((unsigned char *) &arp->ar_op) + sizeof(u_short);
-       memcpy(ptr, dev->dev_addr, arp->ar_hln);
-       ptr += arp->ar_hln;
-       memcpy(ptr, &saddr, arp->ar_pln);
-       ptr += arp->ar_pln;
-       /*memcpy(ptr, dev->broadcast, arp->ar_hln);*/
-       memset(ptr,0,arp->ar_hln);
-       ptr += arp->ar_hln;
-       memcpy(ptr, &paddr, arp->ar_pln);
-
-       dev->queue_xmit(skb, dev, 0);
+  if (tmp < 0) {
+       kfree_skb(skb,FREE_WRITE);
+       return;
+  }
+  arp = (struct arphdr *) ((unsigned char *) (skb+1) + tmp);
+  arp->ar_hrd = htons(dev->type);
+  if(dev->type!=3)     /* AX.25 */
+       arp->ar_pro = htons(ETH_P_IP);
+  else
+       arp->ar_pro = htons(0xCC);
+  arp->ar_hln = dev->addr_len;
+  arp->ar_pln = 4;
+  arp->ar_op = htons(ARPOP_REQUEST);
+
+  ptr = ((unsigned char *) &arp->ar_op) + sizeof(u_short);
+  memcpy(ptr, dev->dev_addr, arp->ar_hln);
+  ptr += arp->ar_hln;
+  memcpy(ptr, &saddr, arp->ar_pln);
+  ptr += arp->ar_pln;
+  /*memcpy(ptr, dev->broadcast, arp->ar_hln);*/
+  memset(ptr,0,arp->ar_hln);
+  ptr += arp->ar_hln;
+  memcpy(ptr, &paddr, arp->ar_pln);
+
+  DPRINTF((DBG_ARP, ">>\n"));
+  arp_print(arp);
+  dev->queue_xmit(skb, dev, 0);
 }
 
 
-/*
- *     Find an ARP mapping in the cache. If not found, post a REQUEST.
- */
-int arp_find(unsigned char *haddr, unsigned long paddr, struct device *dev,
-            unsigned long saddr)
+/* Find an ARP mapping in the cache. If not found, post a REQUEST. */
+int
+arp_find(unsigned char *haddr, unsigned long paddr, struct device *dev,
+          unsigned long saddr)
 {
-       struct arp_table *apt;
+  struct arp_table *apt;
 
-       switch(chk_addr(paddr)) 
-       {
-               case IS_MYADDR:
-                       memcpy(haddr, dev->dev_addr, dev->addr_len);
-                       return(0);
-               case IS_BROADCAST:
-                       memcpy(haddr, dev->broadcast, dev->addr_len);
-                       return(0);
-       }
+  DPRINTF((DBG_ARP, "ARP: find(haddr=%s, ", eth_print(haddr)));
+  DPRINTF((DBG_ARP, "paddr=%s, ", in_ntoa(paddr)));
+  DPRINTF((DBG_ARP, "dev=%s, saddr=%s)\n", dev->name, in_ntoa(saddr)));
+
+  switch(chk_addr(paddr)) {
+       case IS_MYADDR:
+               memcpy(haddr, dev->dev_addr, dev->addr_len);
+               return(0);
+       case IS_BROADCAST:
+               memcpy(haddr, dev->broadcast, dev->addr_len);
+               return(0);
+  }
                
-       apt = arp_lookup(paddr);
-       if (apt != NULL) 
-       {
+  apt = arp_lookup(paddr);
+  if (apt != NULL) {
        /*
         * Make sure it's not too old. If it is too old, we will
         * just pretend we did not find it, and then arp_send will
         * verify the address for us.
         */
-               if ((apt->flags & ATF_PERM) ||
-                   (apt->last_used < jiffies+ARP_TIMEOUT && apt->hlen != 0))
-               {
-                       apt->last_used = jiffies;
-                       memcpy(haddr, apt->ha, dev->addr_len);
-                       return(0);
-               } 
-               else 
-               {
-                       DPRINTF((DBG_ARP, "ARP: find: found expired entry for %s\n",
-                                                               in_ntoa(apt->ip)));
-               }
-       }
+        if ((!(apt->flags & ATF_PERM)) ||
+           (!before(apt->last_used, jiffies+ARP_TIMEOUT) && apt->hlen != 0)) {
+               apt->last_used = jiffies;
+               memcpy(haddr, apt->ha, dev->addr_len);
+               return(0);
+       } else {
+               DPRINTF((DBG_ARP, "ARP: find: found expired entry for %s\n",
+                                                       in_ntoa(apt->ip)));
+       }
+  }
 
   /*
    * This assume haddr are at least 4 bytes.
    * If this isn't true we can use a lookup table, one for every dev.
+   * NOTE: this bit of code still looks fishy to me- FvK
    */
-  
-       *(unsigned long *)haddr = paddr;
+  *(unsigned long *)haddr = paddr;
 
-       /* If we didn't find an entry, we will try to send an ARP packet. */
-       arp_send(paddr, dev, saddr);
+  /* If we didn't find an entry, we will try to send an ARP packet. */
+  arp_send(paddr, dev, saddr);
 
-       return(1);
+  return(1);
 }
 
 
-/* 
- *     Add an entry to the ARP cache.  Check for dupes!
- */
-void arp_add(unsigned long addr, unsigned char *haddr, struct device *dev)
+/* Add an entry to the ARP cache.  Check for dupes! */
+void
+arp_add(unsigned long addr, unsigned char *haddr, struct device *dev)
 {
-       struct arp_table *apt;
-
-         /* This is probably a good check... */
-       if (addr == 0) 
-       {
-               printk("ARP: add: will not add entry for 0.0.0.0 !\n");
-               return;
-       }
-
-       /* First see if the address is already in the table. */
-       apt = arp_lookup(addr);
-       if (apt != NULL) 
-       {
-               DPRINTF((DBG_ARP, "ARP: updating entry for %s\n", in_ntoa(addr)));
-               apt->last_used = jiffies;
-               memcpy(apt->ha, haddr , dev->addr_len);
-               return;
-       }
-       arp_create(addr, haddr, dev->addr_len, dev->type);
+  struct arp_table *apt;
+
+  DPRINTF((DBG_ARP, "ARP: add(%s, ", in_ntoa(addr)));
+  DPRINTF((DBG_ARP, "%s, ", eth_print(haddr)));
+  DPRINTF((DBG_ARP, "%d, %d)\n", dev->hard_header_len, dev->type));
+
+  /* This is probably a good check... */
+  if (addr == 0) {
+       printk("ARP: add: will not add entry for 0.0.0.0 !\n");
+       return;
+  }
+
+  /* First see if the address is already in the table. */
+  apt = arp_lookup(addr);
+  if (apt != NULL) {
+       DPRINTF((DBG_ARP, "ARP: updating entry for %s\n", in_ntoa(addr)));
+       apt->last_used = jiffies;
+       memcpy(apt->ha, haddr , dev->addr_len);
+       return;
+  }
+  arp_create(addr, haddr, dev->addr_len, dev->type);
 }
 
 
-/*
- *     Create an ARP entry for a device's broadcast address.
- */
-
-void arp_add_broad(unsigned long addr, struct device *dev)
+/* Create an ARP entry for a device's broadcast address. */
+void
+arp_add_broad(unsigned long addr, struct device *dev)
 {
-       struct arp_table *apt;
-
-       arp_add(addr, dev->broadcast, dev);
-       apt = arp_lookup(addr);
-       if (apt != NULL) 
-       {
-               apt->flags |= ATF_PERM;
-       }
+  struct arp_table *apt;
+
+  arp_add(addr, dev->broadcast, dev);
+  apt = arp_lookup(addr);
+  if (apt != NULL) {
+       apt->flags |= ATF_PERM;
+  }
 }
 
 
 /* Queue an IP packet, while waiting for the ARP reply packet. */
-void arp_queue(struct sk_buff *skb)
+void
+arp_queue(struct sk_buff *skb)
 {
-       unsigned long flags;
-       save_flags(flags);
-       cli();
-       skb->tries = ARP_MAX_TRIES;
+  cli();
+  skb->tries = ARP_MAX_TRIES;
 
-       if (skb->next != NULL) 
-       {
-               sti();
-               printk("ARP: arp_queue skb already on queue magic=%X.\n", skb->magic);
-               return;
-       }
-       skb_queue_tail(&arp_q,skb);
-       skb->magic = ARP_QUEUE_MAGIC;
-       restore_flags(flags);
+  if (skb->next != NULL) {
+       sti();
+       printk("ARP: arp_queue skb already on queue magic=%X.\n", skb->magic);
+       return;
+  }
+  skb_queue_tail(&arp_q,skb);
+  skb->magic = ARP_QUEUE_MAGIC;
+  sti();
 }
 
 
@@ -727,196 +754,172 @@ void arp_queue(struct sk_buff *skb)
  *
  * Perhaps we should redo PROCfs to handle larger buffers?  Michael?
  */
-
-int arp_get_info(char *buffer)
+int
+arp_get_info(char *buffer)
 {
-       struct arpreq *req;
-       struct arp_table *apt;
-       int i;
-       char *pos;
-
-       /* Loop over the ARP table and copy structures to the buffer. */
-       pos = buffer;
-       i = 0;
-       for (i = 0; i < ARP_TABLE_SIZE; i++) 
-       {
-               cli();
-               apt = arp_tables[i];
-               sti();
-               while (apt != NULL) 
-               {
-                       if (pos < (buffer + 4000)) 
-                       {
-                               req = (struct arpreq *) pos;
-                               memset((char *) req, 0, sizeof(struct arpreq));
-                               req->arp_pa.sa_family = AF_INET;
-                               memcpy((char *) req->arp_pa.sa_data, (char *) &apt->ip, 4);
+  struct arpreq *req;
+  struct arp_table *apt;
+  int i;
+  char *pos;
+
+  /* Loop over the ARP table and copy structures to the buffer. */
+  pos = buffer;
+  i = 0;
+  for (i = 0; i < ARP_TABLE_SIZE; i++) {
+       cli();
+       apt = arp_tables[i];
+       sti();
+       while (apt != NULL) {
+               if (pos < (buffer + 4000)) {
+                       req = (struct arpreq *) pos;
+                       memset((char *) req, 0, sizeof(struct arpreq));
+                       req->arp_pa.sa_family = AF_INET;
+                       memcpy((char *) req->arp_pa.sa_data, (char *) &apt->ip, 4);
                                req->arp_ha.sa_family = apt->htype;
-                               memcpy((char *) req->arp_ha.sa_data,
-                                       (char *) &apt->ha, apt->hlen);
-                       }
-                       pos += sizeof(struct arpreq);
-                       cli();
-                       apt = apt->next;
-                       sti();
+                       memcpy((char *) req->arp_ha.sa_data,
+                               (char *) &apt->ha, apt->hlen);
                }
-       }
-       return(pos - buffer);
+               pos += sizeof(struct arpreq);
+               cli();
+               apt = apt->next;
+               sti();
+       }
+  }
+  return(pos - buffer);
 }
 
 
-/*
- *     Set (create) an ARP cache entry. 
- */
-static int arp_req_set(struct arpreq *req)
+/* Set (create) an ARP cache entry. */
+static int
+arp_req_set(struct arpreq *req)
 {
-       struct arpreq r;
-       struct arp_table *apt;
-       struct sockaddr_in *si;
-       int htype, hlen;
-
-       /* We only understand about IP addresses... */
-       memcpy_fromfs(&r, req, sizeof(r));
-       if (r.arp_pa.sa_family != AF_INET) 
-               return(-EPFNOSUPPORT);
-
-       /*
-        * Find out about the hardware type.
-        * We have to be compatible with BSD UNIX, so we have to
-        * assume that a "not set" value (i.e. 0) means Ethernet.
-        */
-       si = (struct sockaddr_in *) &r.arp_pa;
-       switch(r.arp_ha.sa_family) 
-       {
-               case 0:
-               case ARPHRD_ETHER:
-                       htype = ARPHRD_ETHER;
-                       hlen = ETH_ALEN;
-                       break;
-               case ARPHRD_AX25:
-                       htype = ARPHRD_AX25;
-                       hlen = 7;
-                       break;
-                       
-               default:
-                       return(-EPFNOSUPPORT);
-       }       
-
-       /* Is there an existing entry for this address? */
-       if (si->sin_addr.s_addr == 0) 
-       {
-               printk("ARP: SETARP: requested PA is 0.0.0.0 !\n");
-               return(-EINVAL);
-       }
-       apt = arp_lookup(si->sin_addr.s_addr);
-       if (apt == NULL) 
-       {
-               apt = arp_create(si->sin_addr.s_addr,
-                       (unsigned char *) r.arp_ha.sa_data, hlen, htype);
-               if (apt == NULL) 
-                       return(-ENOMEM);
-       }
-
-       /* We now have a pointer to an ARP entry.  Update it! */
-       memcpy((char *) &apt->ha, (char *) &r.arp_ha.sa_data, hlen);
-       apt->last_used = jiffies;
-       apt->flags = r.arp_flags;
-       if(apt->flags&ATF_PUBL)
-               arp_proxies++;          /* Count proxy arps so we know if to use it */
-
-       return(0);
-}
+  struct arpreq r;
+  struct arp_table *apt;
+  struct sockaddr_in *si;
+  int htype, hlen;
 
+  /* We only understand about IP addresses... */
+  memcpy_fromfs(&r, req, sizeof(r));
+  if (r.arp_pa.sa_family != AF_INET) return(-EPFNOSUPPORT);
+
+  /*
+   * Find out about the hardware type.
+   * We have to be compatible with BSD UNIX, so we have to
+   * assume that a "not set" value (i.e. 0) means Ethernet.
+   */
+  si = (struct sockaddr_in *) &r.arp_pa;
+  switch(r.arp_ha.sa_family) {
+       case 0:
+       case ARPHRD_ETHER:
+               htype = ARPHRD_ETHER;
+               hlen = ETH_ALEN;
+               break;
+       default:
+               return(-EPFNOSUPPORT);
+  }
+
+  /* Is there an existing entry for this address? */
+  if (si->sin_addr.s_addr == 0) {
+       printk("ARP: SETARP: requested PA is 0.0.0.0 !\n");
+       return(-EINVAL);
+  }
+  apt = arp_lookup(si->sin_addr.s_addr);
+  if (apt == NULL) {
+       apt = arp_create(si->sin_addr.s_addr,
+               (unsigned char *) r.arp_ha.sa_data, hlen, htype);
+       if (apt == NULL) return(-ENOMEM);
+  }
+
+  /* We now have a pointer to an ARP entry.  Update it! */
+  memcpy((char *) &apt->ha, (char *) &r.arp_ha.sa_data, hlen);
+  apt->last_used = jiffies;
+  apt->flags = r.arp_flags;
+  if(apt->flags&ATF_PUBL)
+       arp_proxies++;          /* Count proxy arps so we know if to use it */
+
+  return(0);
+}
 
-/*
- *     Get an ARP cache entry.
- */
 
-static int arp_req_get(struct arpreq *req)
+/* Get an ARP cache entry. */
+static int
+arp_req_get(struct arpreq *req)
 {
-       struct arpreq r;
-       struct arp_table *apt;
-       struct sockaddr_in *si;
-
-       /* We only understand about IP addresses... */
-       memcpy_fromfs(&r, req, sizeof(r));
-       if (r.arp_pa.sa_family != AF_INET) 
-               return(-EPFNOSUPPORT);
-
-       /* Is there an existing entry for this address? */
-       si = (struct sockaddr_in *) &r.arp_pa;
-       apt = arp_lookup(si->sin_addr.s_addr);
-       if (apt == NULL) 
-               return(-ENXIO);
-
-       /* We found it; copy into structure. */
-       memcpy((char *) r.arp_ha.sa_data, (char *) &apt->ha, apt->hlen);
-       r.arp_ha.sa_family = apt->htype;
-       
-       /* Copy the information back */
-       memcpy_tofs(req, &r, sizeof(r));
-       return(0);
+  struct arpreq r;
+  struct arp_table *apt;
+  struct sockaddr_in *si;
+
+  /* We only understand about IP addresses... */
+  memcpy_fromfs(&r, req, sizeof(r));
+  if (r.arp_pa.sa_family != AF_INET) return(-EPFNOSUPPORT);
+
+  /* Is there an existing entry for this address? */
+  si = (struct sockaddr_in *) &r.arp_pa;
+  apt = arp_lookup(si->sin_addr.s_addr);
+  if (apt == NULL) return(-ENXIO);
+
+  /* We found it; copy into structure. */
+  memcpy((char *) r.arp_ha.sa_data, (char *) &apt->ha, apt->hlen);
+  r.arp_ha.sa_family = apt->htype;
+
+  /* Copy the information back */
+  memcpy_tofs(req, &r, sizeof(r));
+  return(0);
 }
 
 
-/*
- *     Delete an ARP cache entry.
- */
-static int arp_req_del(struct arpreq *req)
+/* Delete an ARP cache entry. */
+static int
+arp_req_del(struct arpreq *req)
 {
-       struct arpreq r;
-       struct sockaddr_in *si;
-       
-         /* We only understand about IP addresses... */
-         memcpy_fromfs(&r, req, sizeof(r));
-         if (r.arp_pa.sa_family != AF_INET) 
-               return(-EPFNOSUPPORT);  
-       si = (struct sockaddr_in *) &r.arp_pa;
+  struct arpreq r;
+  struct sockaddr_in *si;
+
+  /* We only understand about IP addresses... */
+  memcpy_fromfs(&r, req, sizeof(r));
+  if (r.arp_pa.sa_family != AF_INET) return(-EPFNOSUPPORT);
+
+  si = (struct sockaddr_in *) &r.arp_pa;
   
-       /* The system cope with this but splats up a nasty kernel message 
-          We trap it beforehand and tell the user off */
-       if(chk_addr(si->sin_addr.s_addr)==IS_MYADDR)
-               return -EINVAL;
+  /* The system cope with this but splats up a nasty kernel message 
+     We trap it beforehand and tell the user off */
+  if(chk_addr(si->sin_addr.s_addr)==IS_MYADDR)
+       return -EINVAL;
        
-       arp_destroy(si->sin_addr.s_addr);
-       
-       return(0);
+  arp_destroy(si->sin_addr.s_addr);
+
+  return(0);
 }
 
 
-/* 
- *     Handle an ARP layer I/O control request. 
- */
-int arp_ioctl(unsigned int cmd, void *arg)
+/* Handle an ARP layer I/O control request. */
+int
+arp_ioctl(unsigned int cmd, void *arg)
 {
-       int err;
-       switch(cmd) 
-       {
-               case DDIOCSDBG:
-                       return(dbg_ioctl(arg, DBG_ARP));
-               case SIOCDARP:
-                       if (!suser()) return(-EPERM);
-                       err=verify_area(VERIFY_READ,arg,sizeof(struct arpreq));
-                       if(err)
-                               return err;
-                       return(arp_req_del((struct arpreq *)arg));
-               case SIOCGARP:
-                       err=verify_area(VERIFY_WRITE,arg,sizeof(struct arpreq));
-                       if(err)
-                               return err;
-                       return(arp_req_get((struct arpreq *)arg));
-               case SIOCSARP:
-                       if (!suser()) return(-EPERM);
-                       err=verify_area(VERIFY_READ,arg,sizeof(struct arpreq));
-                       if(err)
-                               return err;
-                       return(arp_req_set((struct arpreq *)arg));
-               default:
-                       return(-EINVAL);
-       }
-       /*NOTREACHED*/
-       return(0);
+  int err;
+  switch(cmd) {
+       case DDIOCSDBG:
+               return(dbg_ioctl(arg, DBG_ARP));
+       case SIOCDARP:
+               if (!suser()) return(-EPERM);
+               err=verify_area(VERIFY_READ,arg,sizeof(struct arpreq));
+               if(err)
+                       return err;
+               return(arp_req_del((struct arpreq *)arg));
+       case SIOCGARP:
+               err=verify_area(VERIFY_WRITE,arg,sizeof(struct arpreq));
+               if(err)
+                       return err;
+               return(arp_req_get((struct arpreq *)arg));
+       case SIOCSARP:
+               if (!suser()) return(-EPERM);
+               err=verify_area(VERIFY_READ,arg,sizeof(struct arpreq));
+               if(err)
+                       return err;
+               return(arp_req_set((struct arpreq *)arg));
+       default:
+               return(-EINVAL);
+  }
+  /*NOTREACHED*/
+  return(0);
 }
index b18e0ae99ea82cec78339f4db2ccf023059c3a0d..c75c6cf182d178b42d2d202bb8c7a1c4b9992325 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             Definitions for the ARP protocol module.
  *
- * Version:    @(#)arp.h       1.28    24/12/93
+ * Version:    @(#)arp.h       1.0.6   05/21/93
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
 #define ARP_QUEUE_MAGIC        0x0432447A      /* magic # for queues           */
 
 
-/* 
- *     This structure defines the ARP mapping cache.
- */
-struct arp_table 
-{
-       struct arp_table                *next;
-       volatile unsigned long  last_used;
-       unsigned int                    flags;
-       unsigned long                   ip;
-       unsigned char                   ha[MAX_ADDR_LEN];
-       unsigned char                   hlen;
-       unsigned char                   htype;
+/* This structure defines the ARP mapping cache. */
+struct arp_table {
+  struct arp_table             *next;
+  volatile unsigned long       last_used;
+  unsigned int                 flags;
+#if 1
+  unsigned long                        ip;
+#else
+  unsigned char                        pa[MAX_ADDR_LEN];
+  unsigned char                        plen;
+  unsigned char                        ptype;
+#endif
+  unsigned char                        ha[MAX_ADDR_LEN];
+  unsigned char                        hlen;
+  unsigned char                        htype;
 };
 
 
-/*
- *     This is also used in "sock.c" and "tcp.c" - YUCK! - FvK 
- */
+/* This is also used in "sock.c" and "tcp.c" - YUCK! - FvK */
 extern struct sk_buff *arp_q;
 
 
 extern void    arp_destroy(unsigned long paddr);
-extern void    arp_destroy_maybe(unsigned long paddr);
 extern int     arp_rcv(struct sk_buff *skb, struct device *dev,
                        struct packet_type *pt);
 extern int     arp_find(unsigned char *haddr, unsigned long paddr,
diff --git a/net/inet/datagram.c b/net/inet/datagram.c
new file mode 100644 (file)
index 0000000..931d9f3
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+ *     SUCS    NET2 Debugged.
+ *
+ *     Generic datagram handling routines. These are generic for all protocols. Possibly a generic IP version on top
+ *     of these would make sense. Not tonight however 8-). 
+ *     This is used because UDP, RAW, PACKET and the to be released IPX layer all have identical select code and mostly
+ *     identical recvfrom() code. So we share it here. The select was shared before but buried in udp.c so I moved it.
+ *
+ *     Authors:        Alan Cox <iiitac@pyr.swan.ac.uk>. (datagram_select() from old udp.c code)
+ *
+ *     Fixes:
+ *             Alan Cox        :       NULL return from skb_peek_copy() understood
+ *             Alan Cox        :       Rewrote skb_read_datagram to avoid the skb_peek_copy stuff.
+ *             Alan Cox        :       Added support for SOCK_SEQPACKET. IPX can no longer use the SO_TYPE hack but
+ *                                     AX.25 now works right, and SPX is feasible.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <asm/segment.h>
+#include <asm/system.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/in.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include "inet.h"
+#include "dev.h"
+#include "ip.h"
+#include "protocol.h"
+#include "arp.h"
+#include "route.h"
+#include "tcp.h"
+#include "udp.h"
+#include "skbuff.h"
+#include "sock.h"
+
+/*
+ *     Get a datagram skbuff, understands the peeking, nonblocking wakeups and possible
+ *     races. This replaces identical code in packet,raw and udp, as well as the yet to
+ *     be released IPX support. It also finally fixes the long standing peek and read
+ *     race for datagram sockets. If you alter this routine remember it must be
+ *     re-entrant.
+ */
+
+struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags, int noblock, int *err)
+{  
+       struct sk_buff *skb;
+       
+       /* Socket is inuse - so the timer doesn't attack it */
+restart:
+       sk->inuse = 1;
+       while(sk->rqueue == NULL)       /* No data */
+       {
+               /* If we are shutdown then no more data is going to appear. We are done */
+               if (sk->shutdown & RCV_SHUTDOWN) 
+               {
+                       release_sock(sk);
+                       *err=0;
+                       return NULL;
+               }
+
+               if(sk->err)
+               {
+                       release_sock(sk);
+                       *err=-sk->err;
+                       sk->err=0;
+                       return NULL;
+               }
+               
+               /* Sequenced packets can come disconnected. If so we report the problem */
+               if(sk->type==SOCK_SEQPACKET && sk->state!=TCP_ESTABLISHED)
+               {
+                       release_sock(sk);
+                       *err=-ENOTCONN;
+                       return NULL;
+               }
+               
+               /* User doesn't want to wait */
+               if (noblock) 
+               {
+                       release_sock(sk);
+                       *err=-EAGAIN;
+                       return NULL;
+               }
+               release_sock(sk);
+               
+               /* Interrupts off so that no packet arrives before we begin sleeping. 
+                  Otherwise we might miss our wake up */
+               cli();
+               if (sk->rqueue == NULL) 
+               {
+                       interruptible_sleep_on(sk->sleep);
+                       /* Signals may need a restart of the syscall */
+                       if (current->signal & ~current->blocked) 
+                       {
+                               sti();
+                               *err=-ERESTARTSYS;
+                               return(NULL);
+                       }
+                       if(sk->err != 0)        /* Error while waiting for packet
+                                                  eg an icmp sent earlier by the
+                                                  peer has finaly turned up now */
+                       {
+                               *err = -sk->err;
+                               sti();
+                               sk->err=0;
+                               return NULL;
+                       }
+               }
+               sk->inuse = 1;
+               sti();
+         }
+         /* Again only user level code calls this function, so nothing interrupt level
+            will suddenely eat the rqueue */
+         if (!(flags & MSG_PEEK)) 
+         {
+               skb=skb_dequeue(&sk->rqueue);
+               if(skb!=NULL)
+                       skb->users++;
+               else
+                       goto restart;   /* Avoid race if someone beats us to the data */
+         }
+         else
+         {
+               cli();
+               skb=skb_peek(&sk->rqueue);
+               if(skb!=NULL)
+                       skb->users++;
+               sti();
+               if(skb==NULL)   /* shouldn't happen but .. */
+                       *err=-EAGAIN;
+         }
+         return skb;
+}      
+
+void skb_free_datagram(struct sk_buff *skb)
+{
+       unsigned long flags;
+
+       save_flags(flags);
+       cli();
+       skb->users--;
+       if(skb->users>0)
+       {
+               restore_flags(flags);
+               return;
+       }
+       /* See if it needs destroying */
+       if(skb->list == NULL)   /* Been dequeued by someone - ie its read */
+               kfree_skb(skb,FREE_READ);
+       restore_flags(flags);
+}
+
+void skb_copy_datagram(struct sk_buff *skb, int offset, char *to, int size)
+{
+       /* We will know all about the fraglist options to allow >4K receives 
+          but not this release */
+       memcpy_tofs(to,skb->h.raw+offset,size);
+}
+
+/*
+ *     Datagram select: Again totally generic. Moved from udp.c
+ *     Now does seqpacket.
+ */
+int datagram_select(struct sock *sk, int sel_type, select_table *wait)
+{
+       select_wait(sk->sleep, wait);
+       switch(sel_type) 
+       {
+               case SEL_IN:
+                       if (sk->type==SOCK_SEQPACKET && sk->state==TCP_CLOSE)
+                       {
+                               /* Connection closed: Wake up */
+                               return(1);
+                       }
+                       if (sk->rqueue != NULL || sk->err != 0) 
+                       {       /* This appears to be consistent
+                                  with other stacks */
+                               return(1);
+                       }
+                       return(0);
+
+               case SEL_OUT:
+                       if (sk->prot->wspace(sk) >= MIN_WRITE_SPACE) 
+                       {
+                               return(1);
+                       }
+                       return(0);
+       
+               case SEL_EX:
+                       if (sk->err)
+                               return(1); /* Socket has gone into error state (eg icmp error) */
+                       return(0);
+       }
+       return(0);
+}
index 05c2db461a1f1f1ad40ed6c876b44e5beabe86b9..e867ae38841efd3ed2899f04a826a2a1b19bdf5b 100644 (file)
@@ -790,6 +790,7 @@ static inline int bad_mask(unsigned long mask, unsigned long addr)
        return 0;
 }
 
+
 /* Perform the SIOCxIFxxx calls. */
 static int
 dev_ifsioc(void *arg, unsigned int getset)
diff --git a/net/inet/devinet.c b/net/inet/devinet.c
deleted file mode 100644 (file)
index 6b83134..0000000
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- * INET                An implementation of the TCP/IP protocol suite for the LINUX
- *             operating system.  INET is implemented using the  BSD Socket
- *             interface as the means of communication with the user level.
- *
- *             Interface (streams) handling functions.
- *
- * Version:    @(#)dev.c       1.28    20/12/93
- *
- * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
- *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- *             Mark Evans, <evansmp@uhura.aston.ac.uk>
- * 
- * Fixes:      
- *             Alan Cox:       check_addr returns a value for a wrong subnet
- *                             ie not us but don't forward this!
- *             Alan Cox:       block timer if the inet_bh handler is running
- *             Alan Cox:       generic queue code added. A lot neater now
- *             C.E.Hawkins:    SIOCGIFCONF only reports 'upped' interfaces
- *             C.E.Hawkins:    IFF_PROMISC support
- *             Alan Cox:       Supports Donald Beckers new hardware 
- *                             multicast layer, but not yet multicast lists.
- *             Alan Cox:       ip_addr_match problems with class A/B nets.
- *             C.E.Hawkins     IP 0.0.0.0 and also same net route fix. [FIXME: Ought to cause ICMP_REDIRECT]
- *             Alan Cox:       Removed bogus subnet check now the subnet code
- *                             a) actually works for all A/B nets
- *                             b) doesn't forward off the same interface.
- *             Alan Cox:       Multiple extra protocols
- *             Alan Cox:       A Couple more escaped verify_area calls die
- *             Alan Cox:       IP_SET_DEV is gone (forever) as per Fred's comment.
- *             Alan Cox:       Grand tidy up ready for the big day.
- *             Alan Cox:       Handles dev_open errors correctly.
- *             Alan Cox:       IP and generic parts split
- *
- *             This program is free software; you can redistribute it and/or
- *             modify it under the terms of the GNU General Public License
- *             as published by the Free Software Foundation; either version
- *             2 of the License, or (at your option) any later version.
- */
-
-#include <asm/segment.h>
-#include <asm/system.h>
-#include <asm/bitops.h>
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/if_ether.h>
-#include "inet.h"
-#include "devinet.h"
-#include "eth.h"
-#include "ip.h"
-#include "route.h"
-#include "protocol.h"
-#include "tcp.h"
-#include "skbuff.h"
-
-
-/* 
- *     Determine a default network mask, based on the IP address.
- */
-
-unsigned long ip_get_mask(unsigned long addr)
-{
-       unsigned long dst;
-
-       if (addr == 0L) 
-               return(0L);     /* special case */
-
-       dst = ntohl(addr);
-       if (IN_CLASSA(dst)) 
-               return(htonl(IN_CLASSA_NET));
-       if (IN_CLASSB(dst)) 
-               return(htonl(IN_CLASSB_NET));
-       if (IN_CLASSC(dst)) 
-               return(htonl(IN_CLASSC_NET));
-       
-       /* Something else, probably a subnet. */
-       return(0);
-}
-
-/*
- *     See if a pair of addresses match.
- */
-
-int ip_addr_match(unsigned long me, unsigned long him)
-{
-       int i;
-       unsigned long mask=0xFFFFFFFF;
-       DPRINTF((DBG_DEV, "ip_addr_match(%s, ", in_ntoa(me)));
-       DPRINTF((DBG_DEV, "%s)\n", in_ntoa(him)));
-
-       /* Fast path for 99.9% of cases */
-       if (me == him) 
-               return(1);
-               
-       for (i = 0; i < 4; i++, me >>= 8, him >>= 8, mask >>= 8) 
-       {
-               if ((me & 0xFF) != (him & 0xFF)) 
-               {
-                       /*
-                        * The only way this could be a match is for
-                        * the rest of addr1 to be 0 or 255.
-                        */
-                       if (me != 0 && me != mask) 
-                               return(0);
-                       return(1);
-               }
-       }
-       return(1);
-}
-
-
-/*
- *     Check the address for our address, broadcasts, etc. 
- *
- *     This routine is used a lot, and in many time critical
- *     places. It's already _TOO_ slow so be careful how you
- *     alter it.
- */
-int chk_addr(unsigned long addr)
-{
-       struct device *dev;
-       unsigned long dst;
-
-       DPRINTF((DBG_DEV, "chk_addr(%s) --> ", in_ntoa(addr)));
-       dst = ntohl(addr);
-
-       /*
-        * Accept both `all ones' and `all zeros' as BROADCAST. 
-        * All 0's is the old BSD broadcast.
-        */
-        
-       if (dst == INADDR_ANY || dst == INADDR_BROADCAST) 
-       {
-               DPRINTF((DBG_DEV, "BROADCAST\n"));
-               return(IS_BROADCAST);
-       }
-
-       /* Accept all of the `loopback' class A net. */
-       if ((dst & IN_CLASSA_NET) == 0x7F000000L) 
-       {
-               DPRINTF((DBG_DEV, "LOOPBACK\n"));
-
-               /*
-                * We force `loopback' to be equal to MY_ADDR.
-                */
-               return(IS_MYADDR);
-               /* return(IS_LOOPBACK); */
-       }
-
-       /* OK, now check the interface addresses. */
-       for (dev = dev_base; dev != NULL; dev = dev->next) 
-       {
-               if (!(dev->flags&IFF_UP))
-                       continue;
-               if ((dev->pa_addr == 0)/* || (dev->flags&IFF_PROMISC)*/)
-                       return(IS_MYADDR);
-               /* Is it the exact IP address? */
-               if (addr == dev->pa_addr) 
-               {
-                       DPRINTF((DBG_DEV, "MYADDR\n"));
-                       return(IS_MYADDR);
-               }
-
-               /* Nope. Check for a subnetwork broadcast. */
-               if ((addr & dev->pa_mask) == (dev->pa_addr & dev->pa_mask)) 
-               {
-                       if ((addr & ~dev->pa_mask) == 0) 
-                       {
-                               DPRINTF((DBG_DEV, "SUBBROADCAST-0\n"));
-                               return(IS_BROADCAST);
-                       }
-                       if (((addr & ~dev->pa_mask) | dev->pa_mask)
-                                               == INADDR_BROADCAST) 
-                       {
-                               DPRINTF((DBG_DEV, "SUBBROADCAST-1\n"));
-                               return(IS_BROADCAST);
-                       }
-               }
-
-               /* Nope. Check for Network broadcast. */
-               if(IN_CLASSA(dst)) 
-               {
-                       if( addr == (dev->pa_addr | 0xffffff00)) 
-                       {
-                               DPRINTF((DBG_DEV, "CLASS A BROADCAST-1\n"));
-                               return(IS_BROADCAST);
-                       }
-               }
-               else if(IN_CLASSB(dst)) 
-               {
-                       if( addr == (dev->pa_addr | 0xffff0000)) 
-                       {
-                               DPRINTF((DBG_DEV, "CLASS B BROADCAST-1\n"));
-                               return(IS_BROADCAST);
-                       }
-               }
-               else 
-               {   /* IN_CLASSC */
-                       if( addr == (dev->pa_addr | 0xff000000)) 
-                       {
-                               DPRINTF((DBG_DEV, "CLASS C BROADCAST-1\n"));
-                               return(IS_BROADCAST);
-                       }
-               }
-       }
-
-       DPRINTF((DBG_DEV, "NONE\n"));
-  
-       return(0);              /* no match at all */
-}
-
-
-/*
- * Retrieve our own address.
- * Because the loopback address (127.0.0.1) is already recognized
- * automatically, we can use the loopback interface's address as
- * our "primary" interface.  This is the addressed used by IP et
- * al when it doesn't know which address to use (i.e. it does not
- * yet know from or to which interface to go...).
- */
-
-unsigned long my_addr(void)
-{
-       struct device *dev;
-
-       for (dev = dev_base; dev != NULL; dev = dev->next) 
-       {
-               if (dev->flags & IFF_LOOPBACK) 
-                       return(dev->pa_addr);
-       }
-       return(0);
-}
-
-
-
-/*
- *     Find an interface that can handle addresses for a certain address. 
- */
-struct device *dev_check(unsigned long addr)
-{
-       struct device *dev;
-
-       for (dev = dev_base; dev; dev = dev->next)
-               if ((dev->flags & IFF_UP) && (dev->flags & IFF_POINTOPOINT) &&
-                       (addr == dev->pa_dstaddr))
-                       return dev;
-       for (dev = dev_base; dev; dev = dev->next)
-               if ((dev->flags & IFF_UP) && !(dev->flags & IFF_POINTOPOINT) &&
-                       (dev->flags & IFF_LOOPBACK ? (addr == dev->pa_addr) :
-                       (dev->pa_mask & addr) == (dev->pa_addr & dev->pa_mask)))
-                       break;
-  /* no need to check broadcast addresses */
-       return dev;
-}
-
diff --git a/net/inet/devinet.h b/net/inet/devinet.h
deleted file mode 100644 (file)
index c9fc5cc..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * INET                An implementation of the TCP/IP protocol suite for the LINUX
- *             operating system.  INET is implemented using the  BSD Socket
- *             interface as the means of communication with the user level.
- *
- *             Definitions for the INET bits of the interfaces handler.
- *
- */
-
-#ifndef _DEVINET_H
-#define _DEVINET_H
-
-#ifndef _DEV_H
-#include "dev.h"
-#endif
-
-extern int             ip_addr_match(unsigned long addr1, unsigned long addr2);
-extern int             chk_addr(unsigned long addr);
-extern struct device   *dev_check(unsigned long daddr);
-extern unsigned long   my_addr(void);
-
-#endif /* _DEVINET_H */
index 7bf2657a0e2d6fb3ab2fc34bd69a046bea0e7269..01e2f51ddef6c65ce3f9ea39eea2b6247a701a22 100644 (file)
@@ -5,27 +5,24 @@
  *
  *             Ethernet-type device handling.
  *
- * Version:    @(#)eth.c       1.28    20/12/93
+ * Version:    @(#)eth.c       1.0.7   05/25/93
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *             Mark Evans, <evansmp@uhura.aston.ac.uk>
  * 
  * Fixes:
- *             Mr Linux        : Arp problems.
- *             Alan Cox        : Generic queue tidyup (very tiny here).
- *             Alan Cox        : eth_header ntohs should be htons.
+ *             Mr Linux        : Arp problems
+ *             Alan Cox        : Generic queue tidyup (very tiny here)
+ *             Alan Cox        : eth_header ntohs should be htons
  *             Alan Cox        : eth_rebuild_header missing an htons and
  *                               minor other things.
- *             Tegge           : Arp bug fixes.
- *             Alan Cox        : Tidy up ready for the big day.
  *
  *             This program is free software; you can redistribute it and/or
  *             modify it under the terms of the GNU General Public License
  *             as published by the Free Software Foundation; either version
  *             2 of the License, or (at your option) any later version.
  */
-
 #include <asm/segment.h>
 #include <asm/system.h>
 #include <linux/types.h>
 #include <linux/socket.h>
 #include <linux/in.h>
 #include "inet.h"
-#include "devinet.h"
+#include "dev.h"
 #include "eth.h"
 #include "ip.h"
 #include "route.h"
 #include "protocol.h"
 #include "tcp.h"
 #include "skbuff.h"
-#include "sockinet.h"
+#include "sock.h"
 #include <linux/errno.h>
 #include "arp.h"
 
 
-#ifdef ETH_DEBUG
 /* Display an Ethernet address in readable format. */
 char *eth_print(unsigned char *ptr)
 {
@@ -61,16 +57,32 @@ char *eth_print(unsigned char *ptr)
   );
   return(buff);
 }
-#endif
-
-
-#ifdef ETH_DEBUG
 
-/*
- *     Display the contents of the Ethernet MAC header. 
- */
+void eth_setup(char *str, int *ints)
+{
+       struct device *d = dev_base;
+
+       if (!str || !*str)
+               return;
+       while (d) {
+               if (!strcmp(str,d->name)) {
+                       if (ints[0] > 0)
+                               d->irq=ints[1];
+                       if (ints[0] > 1)
+                               d->base_addr=ints[2];
+                       if (ints[0] > 2)
+                               d->mem_start=ints[3];
+                       if (ints[0] > 3)
+                               d->mem_end=ints[4];
+                       break;
+               }
+               d=d->next;
+       }
+}
 
-void eth_dump(struct ethhdr *eth)
+/* Display the contents of the Ethernet MAC header. */
+void
+eth_dump(struct ethhdr *eth)
 {
   if (inet_debug != DBG_ETH) return;
 
@@ -79,128 +91,96 @@ void eth_dump(struct ethhdr *eth)
   printk("TYPE = %04X\n", ntohs(eth->h_proto));
 }
 
-#endif
 
-
-/*
- *     Create the Ethernet MAC header. 
- *
- *     ARP might prevent this from working all in one go. See also
- *     the rebuild header function.
- */
-int eth_header(unsigned char *buff, struct device *dev, unsigned short type,
+/* Create the Ethernet MAC header. */
+int
+eth_header(unsigned char *buff, struct device *dev, unsigned short type,
           unsigned long daddr, unsigned long saddr, unsigned len)
 {
-       struct ethhdr *eth;
-
-       DPRINTF((DBG_DEV, "ETH: header(%s, ", in_ntoa(saddr)));
-       DPRINTF((DBG_DEV, "%s, 0x%X)\n", in_ntoa(daddr), type));
-
-       /* Fill in the basic Ethernet MAC header. */
-       eth = (struct ethhdr *) buff;
-       eth->h_proto = htons(type);
-
-       /* We don't ARP for the LOOPBACK device... */
-       if (dev->flags & IFF_LOOPBACK) 
-       {
-               DPRINTF((DBG_DEV, "ETH: No header for loopback\n"));
-               memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
-               memset(eth->h_dest, 0, dev->addr_len);
-               return(dev->hard_header_len);
-       }
-
-       /* Check if we can use the MAC BROADCAST address. */
-       if (chk_addr(daddr) == IS_BROADCAST) 
-       {
-               DPRINTF((DBG_DEV, "ETH: Using MAC Broadcast\n"));
-               memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
-               memcpy(eth->h_dest, dev->broadcast, dev->addr_len);
-               return(dev->hard_header_len);
-       }
-       /*
-        *      We disable interrupts here to avoid a race if the ARP
-        *      reply is too quick.
-        */
-       cli();
-       memcpy(eth->h_source, &saddr, 4);
-       /* No. Ask ARP to resolve the Ethernet address. */
-       if (arp_find(eth->h_dest, daddr, dev, dev->pa_addr/* saddr */)) 
-       {
-                       sti();
-               if(type!=ETH_P_IP)
-                       printk("Erk: protocol %X got into an arp request state!\n",type);
-               return(-dev->hard_header_len);
-       } 
-       else
-       {
-               memcpy(eth->h_source,dev->dev_addr,dev->addr_len);      /* This was missing causing chaos if the
-                                                                          header built correctly! */
-               sti();
-               return(dev->hard_header_len);
-       }
+  struct ethhdr *eth;
+
+  DPRINTF((DBG_DEV, "ETH: header(%s, ", in_ntoa(saddr)));
+  DPRINTF((DBG_DEV, "%s, 0x%X)\n", in_ntoa(daddr), type));
+
+  /* Fill in the basic Ethernet MAC header. */
+  eth = (struct ethhdr *) buff;
+  eth->h_proto = htons(type);
+
+  /* We don't ARP for the LOOPBACK device... */
+  if (dev->flags & IFF_LOOPBACK) {
+       DPRINTF((DBG_DEV, "ETH: No header for loopback\n"));
+       memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
+       memset(eth->h_dest, 0, dev->addr_len);
+       return(dev->hard_header_len);
+  }
+
+  /* Check if we can use the MAC BROADCAST address. */
+  if (chk_addr(daddr) == IS_BROADCAST) {
+       DPRINTF((DBG_DEV, "ETH: Using MAC Broadcast\n"));
+       memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
+       memcpy(eth->h_dest, dev->broadcast, dev->addr_len);
+       return(dev->hard_header_len);
+  }
+  cli();
+  memcpy(eth->h_source, &saddr, 4);
+  /* No. Ask ARP to resolve the Ethernet address. */
+  if (arp_find(eth->h_dest, daddr, dev, saddr)) 
+  {
+        sti();
+        if(type!=ETH_P_IP)
+               printk("Erk: protocol %X got into an arp request state!\n",type);
+       return(-dev->hard_header_len);
+  } 
+  else
+  {
+       memcpy(eth->h_source,dev->dev_addr,dev->addr_len);      /* This was missing causing chaos if the
+                                                                  header built correctly! */
+       sti();
+       return(dev->hard_header_len);
+  }
 }
 
 
-/*
- *     Rebuild the Ethernet MAC header.
- *
- *     We've got a 'stuck' packet that failed to go out before. See if
- *     the arp is resolved and we can finally shift it.
- */
-int eth_rebuild_header(void *buff, struct device *dev)
+/* Rebuild the Ethernet MAC header. */
+int
+eth_rebuild_header(void *buff, struct device *dev)
 {
-       struct ethhdr *eth;
-       unsigned long src, dst;
-
-       DPRINTF((DBG_DEV, "ETH: Using MAC Broadcast\n"));
-       eth = (struct ethhdr *) buff;
-       src = *(unsigned long *) eth->h_source;
-       dst = *(unsigned long *) eth->h_dest;
-       DPRINTF((DBG_DEV, "ETH: RebuildHeader: SRC=%s ", in_ntoa(src)));
-       DPRINTF((DBG_DEV, "DST=%s\n", in_ntoa(dst)));
-       if(eth->h_proto!=htons(ETH_P_ARP))      /* This ntohs kind of helps a bit! */
-               if (arp_find(eth->h_dest, dst, dev, dev->pa_addr /* src */)) 
-                       /* Still not known */
-                       return(1);
-       memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
-       return(0);
+  struct ethhdr *eth;
+  unsigned long src, dst;
+
+  DPRINTF((DBG_DEV, "ETH: Using MAC Broadcast\n"));
+  eth = (struct ethhdr *) buff;
+  src = *(unsigned long *) eth->h_source;
+  dst = *(unsigned long *) eth->h_dest;
+  DPRINTF((DBG_DEV, "ETH: RebuildHeader: SRC=%s ", in_ntoa(src)));
+  DPRINTF((DBG_DEV, "DST=%s\n", in_ntoa(dst)));
+  if(eth->h_proto!=htons(ETH_P_ARP))   /* This ntohs kind of helps a bit! */
+         if (arp_find(eth->h_dest, dst, dev, src)) return(1);
+  memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
+  return(0);
 }
 
 
-/* 
- *     Add an ARP entry for a host on this interface.
- */
-void eth_add_arp(unsigned long addr, struct sk_buff *skb, struct device *dev)
+/* Add an ARP entry for a host on this interface. */
+void
+eth_add_arp(unsigned long addr, struct sk_buff *skb, struct device *dev)
 {
-       struct ethhdr *eth;
+  struct ethhdr *eth;
 
-       eth = (struct ethhdr *) (skb + 1);
-       arp_add(addr, eth->h_source, dev);
+  eth = (struct ethhdr *) (skb + 1);
+  arp_add(addr, eth->h_source, dev);
 }
 
 
-/*
- *     Determine the packet's protocol ID. 
- *
- * Ethernet comes in two 'species' DIX (Digitial Intel Xerox) and IEE802.3
- * needless to say they are different. Fortunately there is a way of telling
- * them apart. All 'normal' modern DIX service ID's are >1536.
- * All IEE802.3 frames have a length at this position and that cannot be 
- * >=1536. Note IEE802.3 frames have a second 802.2 header normally. We don't
- * deal with this bit in the current kernel, but a user using SOCK_PACKET
- * for 802.3 frames can do so.
- */
-unsigned short eth_type_trans(struct sk_buff *skb, struct device *dev)
+/* Determine the packet's protocol ID. */
+unsigned short
+eth_type_trans(struct sk_buff *skb, struct device *dev)
 {
-       struct ethhdr *eth;
+  struct ethhdr *eth;
 
-       eth = (struct ethhdr *) (skb + 1);
+  eth = (struct ethhdr *) (skb + 1);
 
-       if(ntohs(eth->h_proto)<1536)
-               return(htons(ETH_P_802_3));
-       return(eth->h_proto);
+  if(ntohs(eth->h_proto)<1536)
+       return(htons(ETH_P_802_3));
+  return(eth->h_proto);
 }
index 467a1197bcde3d9ddb72333c220a83ae93ce4063..7b953d44504d33d13db5905ef26dd97e89ef9a26 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             Internet Control Message Protocol (ICMP)
  *
- * Version:    @(#)icmp.c      1.28    20/12/93
+ * Version:    @(#)icmp.c      1.0.11  06/02/93
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -14,7 +14,6 @@
  * Fixes:      
  *             Alan Cox        :       Generic queue usage.
  *             Gerhard Koerting:       ICMP addressing corrected
- *             Tegge           :       Subnet problems
  *
  *
  *             This program is free software; you can redistribute it and/or
@@ -22,7 +21,6 @@
  *             as published by the Free Software Foundation; either version
  *             2 of the License, or (at your option) any later version.
  */
 #include <linux/types.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/socket.h>
 #include <linux/in.h>
 #include "inet.h"
-#include "devinet.h"
+#include "dev.h"
 #include "ip.h"
 #include "route.h"
 #include "protocol.h"
 #include "icmp.h"
 #include "tcp.h"
 #include "skbuff.h"
-#include "sockinet.h"
+#include "sock.h"
 #include <linux/errno.h>
 #include <linux/timer.h>
 #include <asm/system.h>
@@ -65,413 +63,379 @@ struct icmp_err icmp_err_convert[] = {
 };
 
 
-#ifdef ICMP_DEBUG
-
 /* Display the contents of an ICMP header. */
 static void
 print_icmp(struct icmphdr *icmph)
 {
-       if (inet_debug != DBG_ICMP) 
-               return;
+  if (inet_debug != DBG_ICMP) return;
 
-       printk("ICMP: type = %d, code = %d, checksum = %X\n",
+  printk("ICMP: type = %d, code = %d, checksum = %X\n",
                        icmph->type, icmph->code, icmph->checksum);
-       printk("      gateway = %s\n", in_ntoa(icmph->un.gateway));
+  printk("      gateway = %s\n", in_ntoa(icmph->un.gateway));
 }
 
-#endif
-
-/* 
- *     Send an ICMP message. 
- *
- *     ICMP is the control message protocol for error reporting in IP.
- *     A good document to start with for this stuff is RFC 791.
- */
 
-void icmp_send(struct sk_buff *skb_in, int type, int code, struct device *dev)
+/* Send an ICMP message. */
+void
+icmp_send(struct sk_buff *skb_in, int type, int code, struct device *dev)
 {
-       struct sk_buff *skb;
-       struct iphdr *iph;
-       int offset;
-       struct icmphdr *icmph;
-       int len;
+  struct sk_buff *skb;
+  struct iphdr *iph;
+  int offset;
+  struct icmphdr *icmph;
+  int len;
 
-       DPRINTF((DBG_ICMP, "icmp_send(skb_in = %X, type = %d, code = %d, dev=%X)\n",
+  DPRINTF((DBG_ICMP, "icmp_send(skb_in = %X, type = %d, code = %d, dev=%X)\n",
                                                skb_in, type, code, dev));
 
-       /* Get some memory for the reply. */
-       len = sizeof(struct sk_buff) + dev->hard_header_len +
-               sizeof(struct iphdr) + sizeof(struct icmphdr) +
-               sizeof(struct iphdr) + 8;       /* amount of header to return */
+  /* Get some memory for the reply. */
+  len = sizeof(struct sk_buff) + dev->hard_header_len +
+       sizeof(struct iphdr) + sizeof(struct icmphdr) +
+       sizeof(struct iphdr) + 8;       /* amount of header to return */
           
-       skb = (struct sk_buff *) alloc_skb(len, GFP_ATOMIC);
-       /* We just forget about failed ICMP messages. ICMP is unreliable anyway and
-          things will sort out in time */
-          
-       if (skb == NULL) 
-               return;
-
-       skb->sk = NULL;
-       len -= sizeof(struct sk_buff);
-
-       /* Find the IP header. */
-       iph = (struct iphdr *) (skb_in + 1);
-       iph = (struct iphdr *) ((unsigned char *) iph + dev->hard_header_len);
-
-       /* Build Layer 2-3 headers for message back to source. */
-       offset = ip_build_header(skb, dev->pa_addr, iph->saddr,
-                          &dev, IPPROTO_ICMP, NULL, len, 25, IPTOS_RELIABILITY);
-       if (offset < 0) 
-       {
-               skb->sk = NULL;
-               kfree_skb(skb, FREE_READ);
-               return;
-       }
-
-       /* Re-adjust length according to actual IP header size. */
-       skb->len = offset + sizeof(struct icmphdr) + sizeof(struct iphdr) + 8;
-       icmph = (struct icmphdr *) ((unsigned char *) (skb + 1) + offset);
-       icmph->type = type;
-       icmph->code = code;
-       icmph->checksum = 0;
-       icmph->un.gateway = 0;
-       memcpy(icmph + 1, iph, sizeof(struct iphdr) + 8);
-
-       icmph->checksum = ip_compute_csum((unsigned char *)icmph,
-                              sizeof(struct icmphdr) + sizeof(struct iphdr) + 8);
-
-#ifdef ICMP_DEBUG
-       DPRINTF((DBG_ICMP, ">>\n"));
-       print_icmp(icmph);
-#endif
-       /* Send it and free it. */
-       ip_queue_xmit(NULL, dev, skb, 1);
+  skb = (struct sk_buff *) alloc_skb(len, GFP_ATOMIC);
+  if (skb == NULL) 
+       return;
+
+  skb->sk = NULL;
+  skb->mem_addr = skb;
+  skb->mem_len = len;
+  len -= sizeof(struct sk_buff);
+
+  /* Find the IP header. */
+  iph = (struct iphdr *) (skb_in + 1);
+  iph = (struct iphdr *) ((unsigned char *) iph + dev->hard_header_len);
+
+  /* Build Layer 2-3 headers for message back to source. */
+  offset = ip_build_header(skb, dev->pa_addr, iph->saddr,
+                          &dev, IPPROTO_ICMP, NULL, len);
+  if (offset < 0) {
+       skb->sk = NULL;
+       kfree_skb(skb, FREE_READ);
+       return;
+  }
+
+  /* Re-adjust length according to actual IP header size. */
+  skb->len = offset + sizeof(struct icmphdr) + sizeof(struct iphdr) + 8;
+  icmph = (struct icmphdr *) ((unsigned char *) (skb + 1) + offset);
+  icmph->type = type;
+  icmph->code = code;
+  icmph->checksum = 0;
+  icmph->un.gateway = 0;
+  memcpy(icmph + 1, iph, sizeof(struct iphdr) + 8);
+
+  icmph->checksum = ip_compute_csum((unsigned char *)icmph,
+                         sizeof(struct icmphdr) + sizeof(struct iphdr) + 8);
+
+  DPRINTF((DBG_ICMP, ">>\n"));
+  print_icmp(icmph);
+
+  /* Send it and free it. */
+  ip_queue_xmit(NULL, dev, skb, 1);
 }
 
 
-/*
- *     Handle ICMP_UNREACH and ICMP_QUENCH. 
- */
-
-static void icmp_unreach(struct icmphdr *icmph, struct sk_buff *skb)
+/* Handle ICMP_UNREACH and ICMP_QUENCH. */
+static void
+icmp_unreach(struct icmphdr *icmph, struct sk_buff *skb)
 {
-       struct inet_protocol *ipprot;
-       struct iphdr *iph;
-       unsigned char hash;
-       int err;
-       
-       err = (icmph->type << 8) | icmph->code;
-       iph = (struct iphdr *) (icmph + 1);
-       switch(icmph->code & 7) 
-       {
-               case ICMP_NET_UNREACH:
-                       DPRINTF((DBG_ICMP, "ICMP: %s: network unreachable.\n",
-                                                       in_ntoa(iph->daddr)));
-                       break;
-               case ICMP_HOST_UNREACH:
-                       DPRINTF((DBG_ICMP, "ICMP: %s: host unreachable.\n",
+  struct inet_protocol *ipprot;
+  struct iphdr *iph;
+  unsigned char hash;
+  int err;
+
+  err = (icmph->type << 8) | icmph->code;
+  iph = (struct iphdr *) (icmph + 1);
+  switch(icmph->code & 7) {
+       case ICMP_NET_UNREACH:
+               DPRINTF((DBG_ICMP, "ICMP: %s: network unreachable.\n",
                                                        in_ntoa(iph->daddr)));
-                       break;
-               case ICMP_PROT_UNREACH:
-                       printk("ICMP: %s:%d: protocol unreachable.\n",
-                               in_ntoa(iph->daddr), ntohs(iph->protocol));
-                       break;
-               case ICMP_PORT_UNREACH:
-                       DPRINTF((DBG_ICMP, "ICMP: %s:%d: port unreachable.\n",
-                               in_ntoa(iph->daddr), -1 /* FIXME: ntohs(iph->port) */));
-                       break;
-               case ICMP_FRAG_NEEDED:
-                       printk("ICMP: %s: fragmentation needed and DF set.\n",
-                                                               in_ntoa(iph->daddr));
-                       break;
-               case ICMP_SR_FAILED:
-                       printk("ICMP: %s: Source Route Failed.\n", in_ntoa(iph->daddr));
-                       break;
-               default:
-                       DPRINTF((DBG_ICMP, "ICMP: Unreachable: CODE=%d from %s\n",
-                                       (icmph->code & 7), in_ntoa(iph->daddr)));
-                       break;
-       }
-       
-       /* Get the protocol(s). */
-       hash = iph->protocol & (MAX_INET_PROTOS -1);
-
-       /* This can change while we are doing it. */
-       ipprot = (struct inet_protocol *) inet_protos[hash];
-       while(ipprot != NULL) 
-       {
-               struct inet_protocol *nextip;
-
-               nextip = (struct inet_protocol *) ipprot->next;
-
-               /* Pass it off to everyone who wants it. */
-               if (iph->protocol == ipprot->protocol && ipprot->err_handler) 
-               {
-                       ipprot->err_handler(err, (unsigned char *)(icmph + 1),
+               break;
+       case ICMP_HOST_UNREACH:
+               DPRINTF((DBG_ICMP, "ICMP: %s: host unreachable.\n",
+                                               in_ntoa(iph->daddr)));
+               break;
+       case ICMP_PROT_UNREACH:
+               printk("ICMP: %s:%d: protocol unreachable.\n",
+                       in_ntoa(iph->daddr), ntohs(iph->protocol));
+               break;
+       case ICMP_PORT_UNREACH:
+               DPRINTF((DBG_ICMP, "ICMP: %s:%d: port unreachable.\n",
+                       in_ntoa(iph->daddr), -1 /* FIXME: ntohs(iph->port) */));
+               break;
+       case ICMP_FRAG_NEEDED:
+               printk("ICMP: %s: fragmentation needed and DF set.\n",
+                                                       in_ntoa(iph->daddr));
+               break;
+       case ICMP_SR_FAILED:
+               printk("ICMP: %s: Source Route Failed.\n", in_ntoa(iph->daddr));
+               break;
+       default:
+               DPRINTF((DBG_ICMP, "ICMP: Unreachable: CODE=%d from %s\n",
+                               (icmph->code & 7), in_ntoa(iph->daddr)));
+               break;
+  }
+
+  /* Get the protocol(s). */
+  hash = iph->protocol & (MAX_INET_PROTOS -1);
+
+  /* This can change while we are doing it. */
+  ipprot = (struct inet_protocol *) inet_protos[hash];
+  while(ipprot != NULL) {
+       struct inet_protocol *nextip;
+
+       nextip = (struct inet_protocol *) ipprot->next;
+
+       /* Pass it off to everyone who wants it. */
+       if (iph->protocol == ipprot->protocol && ipprot->err_handler) {
+               ipprot->err_handler(err, (unsigned char *)(icmph + 1),
                                    iph->daddr, iph->saddr, ipprot);
-               }
+       }
 
-               ipprot = nextip;
-       }
-       skb->sk = NULL;
-       kfree_skb(skb, FREE_READ);
+       ipprot = nextip;
+  }
+  skb->sk = NULL;
+  kfree_skb(skb, FREE_READ);
 }
 
 
-/* 
- *     Handle ICMP_REDIRECT.
- */
-
-static void icmp_redirect(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev)
+/* Handle ICMP_REDIRECT. */
+static void
+icmp_redirect(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev)
 {
-       struct iphdr *iph;
-       unsigned long ip;
-
-       iph = (struct iphdr *) (icmph + 1);
-       ip = iph->daddr;
-       switch(icmph->code & 7) 
-       {
-               case ICMP_REDIR_NET:
-                       rt_add((RTF_DYNAMIC | RTF_MODIFIED | RTF_GATEWAY),
-                               ip, 0, icmph->un.gateway, dev);
-                       break;
-               case ICMP_REDIR_HOST:
-                       rt_add((RTF_DYNAMIC | RTF_MODIFIED | RTF_HOST | RTF_GATEWAY),
-                               ip, 0, icmph->un.gateway, dev);
-                       break;
-               case ICMP_REDIR_NETTOS:
-               case ICMP_REDIR_HOSTTOS:
-                       printk("ICMP: cannot handle TOS redirects yet!\n");
-                       break;
-               default:
-                       DPRINTF((DBG_ICMP, "ICMP: Unreach: CODE=%d\n",
-                                                       (icmph->code & 7)));
+  struct iphdr *iph;
+  unsigned long ip;
+
+  iph = (struct iphdr *) (icmph + 1);
+  ip = iph->daddr;
+  switch(icmph->code & 7) {
+       case ICMP_REDIR_NET:
+               rt_add((RTF_DYNAMIC | RTF_MODIFIED | RTF_GATEWAY),
+                       ip, 0, icmph->un.gateway, dev);
                break;
-       }
-       skb->sk = NULL;
-       kfree_skb(skb, FREE_READ);
+       case ICMP_REDIR_HOST:
+               rt_add((RTF_DYNAMIC | RTF_MODIFIED | RTF_HOST | RTF_GATEWAY),
+                       ip, 0, icmph->un.gateway, dev);
+               break;
+       case ICMP_REDIR_NETTOS:
+       case ICMP_REDIR_HOSTTOS:
+               printk("ICMP: cannot handle TOS redirects yet!\n");
+               break;
+       default:
+               DPRINTF((DBG_ICMP, "ICMP: Unreach: CODE=%d\n",
+                                               (icmph->code & 7)));
+               break;
+  }
+  skb->sk = NULL;
+  kfree_skb(skb, FREE_READ);
 }
 
 
 /* Handle ICMP_ECHO ("ping") requests. */
-static void icmp_echo(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev,
+static void
+icmp_echo(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev,
          unsigned long saddr, unsigned long daddr, int len,
          struct options *opt)
 {
-       struct icmphdr *icmphr;
-       struct sk_buff *skb2;
-       int size, offset;
-
-       size = sizeof(struct sk_buff) + dev->hard_header_len + 64 + len;
-       skb2 = alloc_skb(size, GFP_ATOMIC);
-       if (skb2 == NULL) 
-       {
-               skb->sk = NULL;
-               kfree_skb(skb, FREE_READ);
-               return;
-       }
-       skb2->sk = NULL;
-       skb2->free = 1;
-
-       /* Build Layer 2-3 headers for message back to source */
-       offset = ip_build_header(skb2, daddr, saddr, &dev,
-                               IPPROTO_ICMP, opt, len, 255, IPTOS_RELIABILITY);
-       if (offset < 0) 
-       {
-               printk("ICMP: Could not build IP Header for ICMP ECHO Response\n");
-               kfree_skb(skb2,FREE_WRITE);
-               skb->sk = NULL;
-               kfree_skb(skb, FREE_READ);
-               return;
-       }
-
-       /* Re-adjust length according to actual IP header size. */
-       skb2->len = offset + len;
-
-       /* Build ICMP_ECHO Response message. */
-       icmphr = (struct icmphdr *) ((char *) (skb2 + 1) + offset);
-       memcpy((char *) icmphr, (char *) icmph, len);
-       icmphr->type = ICMP_ECHOREPLY;
-       icmphr->code = 0;
-       icmphr->checksum = 0;
-       icmphr->checksum = ip_compute_csum((unsigned char *)icmphr, len);
-       
-       /* Ship it out - free it when done */
-       ip_queue_xmit((struct sock *)NULL, dev, skb2, 1);
-
-       skb->sk = NULL;
-       kfree_skb(skb, FREE_READ);
+  struct icmphdr *icmphr;
+  struct sk_buff *skb2;
+  int size, offset;
+
+  size = sizeof(struct sk_buff) + dev->hard_header_len + 64 + len;
+  skb2 = alloc_skb(size, GFP_ATOMIC);
+  if (skb2 == NULL) {
+       skb->sk = NULL;
+       kfree_skb(skb, FREE_READ);
+       return;
+  }
+  skb2->sk = NULL;
+  skb2->mem_addr = skb2;
+  skb2->mem_len = size;
+  skb2->free = 1;
+
+  /* Build Layer 2-3 headers for message back to source */
+  offset = ip_build_header(skb2, daddr, saddr, &dev,
+                               IPPROTO_ICMP, opt, len);
+  if (offset < 0) {
+       printk("ICMP: Could not build IP Header for ICMP ECHO Response\n");
+       kfree_skb(skb2,FREE_WRITE);
+       skb->sk = NULL;
+       kfree_skb(skb, FREE_READ);
+       return;
+  }
+
+  /* Re-adjust length according to actual IP header size. */
+  skb2->len = offset + len;
+
+  /* Build ICMP_ECHO Response message. */
+  icmphr = (struct icmphdr *) ((char *) (skb2 + 1) + offset);
+  memcpy((char *) icmphr, (char *) icmph, len);
+  icmphr->type = ICMP_ECHOREPLY;
+  icmphr->code = 0;
+  icmphr->checksum = 0;
+  icmphr->checksum = ip_compute_csum((unsigned char *)icmphr, len);
+
+  /* Ship it out - free it when done */
+  ip_queue_xmit((struct sock *)NULL, dev, skb2, 1);
+
+  skb->sk = NULL;
+  kfree_skb(skb, FREE_READ);
 }
 
 
-/* 
- *     Handle the ICMP INFORMATION REQUEST. 
- */
-
-static void icmp_info(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev,
+/* Handle the ICMP INFORMATION REQUEST. */
+static void
+icmp_info(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev,
          unsigned long saddr, unsigned long daddr, int len,
          struct options *opt)
 {
-       /* NOT YET */
-       skb->sk = NULL;
-       kfree_skb(skb, FREE_READ);
+  /* NOT YET */
+  skb->sk = NULL;
+  kfree_skb(skb, FREE_READ);
 }
 
 
-/* 
- *     Handle ICMP_ADRESS_MASK requests. 
- */
-
-static void icmp_address(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev,
+/* Handle ICMP_ADRESS_MASK requests. */
+static void
+icmp_address(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev,
          unsigned long saddr, unsigned long daddr, int len,
          struct options *opt)
 {
-       struct icmphdr *icmphr;
-       struct sk_buff *skb2;
-       int size, offset;
-
-       size = sizeof(struct sk_buff) + dev->hard_header_len + 64 + len;
-       skb2 = alloc_skb(size, GFP_ATOMIC);
-       if (skb2 == NULL) 
-       {
-               skb->sk = NULL;
-               kfree_skb(skb, FREE_READ);
-               return;
-       }
-       skb2->sk = NULL;
-       skb2->free = 1;
-
-       /* Build Layer 2-3 headers for message back to source */
-       offset = ip_build_header(skb2, daddr, saddr, &dev,
-                               IPPROTO_ICMP, opt, len, 255, IPTOS_RELIABILITY);
-       if (offset < 0) 
-       {
-               printk("ICMP: Could not build IP Header for ICMP ADDRESS Response\n");
-               kfree_skb(skb2,FREE_WRITE);
-               skb->sk = NULL;
-               kfree_skb(skb, FREE_READ);
-               return;
-       }
-
-       /* Re-adjust length according to actual IP header size. */
-       skb2->len = offset + len;
-       
-       /* Build ICMP ADDRESS MASK Response message. */
-       icmphr = (struct icmphdr *) ((char *) (skb2 + 1) + offset);
-       icmphr->type = ICMP_ADDRESSREPLY;
-       icmphr->code = 0;
-       icmphr->checksum = 0;
-       icmphr->un.echo.id = icmph->un.echo.id;
-       icmphr->un.echo.sequence = icmph->un.echo.sequence;
-       memcpy((char *) (icmphr + 1), (char *) &dev->pa_mask, sizeof(dev->pa_mask));
-       
-       icmphr->checksum = ip_compute_csum((unsigned char *)icmphr, len);
-
-       /* Ship it out - free it when done */
-       ip_queue_xmit((struct sock *)NULL, dev, skb2, 1);
-
-       skb->sk = NULL;
-       kfree_skb(skb, FREE_READ);
+  struct icmphdr *icmphr;
+  struct sk_buff *skb2;
+  int size, offset;
+
+  size = sizeof(struct sk_buff) + dev->hard_header_len + 64 + len;
+  skb2 = alloc_skb(size, GFP_ATOMIC);
+  if (skb2 == NULL) {
+       skb->sk = NULL;
+       kfree_skb(skb, FREE_READ);
+       return;
+  }
+  skb2->sk = NULL;
+  skb2->mem_addr = skb2;
+  skb2->mem_len = size;
+  skb2->free = 1;
+
+  /* Build Layer 2-3 headers for message back to source */
+  offset = ip_build_header(skb2, daddr, saddr, &dev,
+                               IPPROTO_ICMP, opt, len);
+  if (offset < 0) {
+       printk("ICMP: Could not build IP Header for ICMP ADDRESS Response\n");
+       kfree_skb(skb2,FREE_WRITE);
+       skb->sk = NULL;
+       kfree_skb(skb, FREE_READ);
+       return;
+  }
+
+  /* Re-adjust length according to actual IP header size. */
+  skb2->len = offset + len;
+
+  /* Build ICMP ADDRESS MASK Response message. */
+  icmphr = (struct icmphdr *) ((char *) (skb2 + 1) + offset);
+  icmphr->type = ICMP_ADDRESSREPLY;
+  icmphr->code = 0;
+  icmphr->checksum = 0;
+  icmphr->un.echo.id = icmph->un.echo.id;
+  icmphr->un.echo.sequence = icmph->un.echo.sequence;
+  memcpy((char *) (icmphr + 1), (char *) &dev->pa_mask, sizeof(dev->pa_mask));
+
+  icmphr->checksum = ip_compute_csum((unsigned char *)icmphr, len);
+
+  /* Ship it out - free it when done */
+  ip_queue_xmit((struct sock *)NULL, dev, skb2, 1);
+
+  skb->sk = NULL;
+  kfree_skb(skb, FREE_READ);
 }
 
 
-/*
- *     Deal with incoming ICMP packets. 
- */
-
-int icmp_rcv(struct sk_buff *skb1, struct device *dev, struct options *opt,
+/* Deal with incoming ICMP packets. */
+int
+icmp_rcv(struct sk_buff *skb1, struct device *dev, struct options *opt,
         unsigned long daddr, unsigned short len,
         unsigned long saddr, int redo, struct inet_protocol *protocol)
 {
-       struct icmphdr *icmph;
-       unsigned char *buff;
+  struct icmphdr *icmph;
+  unsigned char *buff;
 
-       /* Drop broadcast packets. */
-       if (chk_addr(daddr) == IS_BROADCAST) 
-       {
-               DPRINTF((DBG_ICMP, "ICMP: Discarded broadcast from %s\n",
+  /* Drop broadcast packets. */
+  if (chk_addr(daddr) == IS_BROADCAST) {
+       DPRINTF((DBG_ICMP, "ICMP: Discarded broadcast from %s\n",
                                                        in_ntoa(saddr)));
+       skb1->sk = NULL;
+       kfree_skb(skb1, FREE_READ);
+       return(0);
+  }
+
+  buff = skb1->h.raw;
+  icmph = (struct icmphdr *) buff;
+
+  /* Validate the packet first */
+  if (ip_compute_csum((unsigned char *) icmph, len)) {
+       /* Failed checksum! */
+       printk("ICMP: failed checksum from %s!\n", in_ntoa(saddr));
+       skb1->sk = NULL;
+       kfree_skb(skb1, FREE_READ);
+       return(0);
+  }
+  print_icmp(icmph);
+
+  /* Parse the ICMP message */
+  switch(icmph->type) {
+       case ICMP_TIME_EXCEEDED:
+       case ICMP_DEST_UNREACH:
+       case ICMP_SOURCE_QUENCH:
+               icmp_unreach(icmph, skb1);
+               return(0);
+       case ICMP_REDIRECT:
+               icmp_redirect(icmph, skb1, dev);
+               return(0);
+       case ICMP_ECHO: 
+               icmp_echo(icmph, skb1, dev, saddr, daddr, len, opt);
+               return 0;
+       case ICMP_ECHOREPLY:
                skb1->sk = NULL;
                kfree_skb(skb1, FREE_READ);
                return(0);
-       }
-
-       buff = skb1->h.raw;
-       icmph = (struct icmphdr *) buff;
-
-       /* Validate the packet first */
-       if (ip_compute_csum((unsigned char *) icmph, len)) 
-       {
-               /* Failed checksum! */
-               printk("ICMP: failed checksum from %s!\n", in_ntoa(saddr));
+       case ICMP_INFO_REQUEST:
+               icmp_info(icmph, skb1, dev, saddr, daddr, len, opt);
+               return 0;
+       case ICMP_INFO_REPLY:
                skb1->sk = NULL;
                kfree_skb(skb1, FREE_READ);
                return(0);
-       }
-#ifdef ICMP_DEBUG
-       print_icmp(icmph);
-#endif
-       /* Parse the ICMP message */
-       switch(icmph->type) 
-       {
-               case ICMP_TIME_EXCEEDED:
-               case ICMP_DEST_UNREACH:
-               case ICMP_SOURCE_QUENCH:
-                       icmp_unreach(icmph, skb1);
-                       return(0);
-               case ICMP_REDIRECT:
-                       icmp_redirect(icmph, skb1, dev);
-                       return(0);
-               case ICMP_ECHO: 
-                       icmp_echo(icmph, skb1, dev, saddr, daddr, len, opt);
-                       return 0;
-               case ICMP_ECHOREPLY:
-                       skb1->sk = NULL;
-                       kfree_skb(skb1, FREE_READ);
-                       return(0);
-               case ICMP_INFO_REQUEST:
-                       icmp_info(icmph, skb1, dev, saddr, daddr, len, opt);
-                       return 0;
-               case ICMP_INFO_REPLY:
-                       skb1->sk = NULL;
-                       kfree_skb(skb1, FREE_READ);
-                       return(0);
-               case ICMP_ADDRESS:
-                       icmp_address(icmph, skb1, dev, saddr, daddr, len, opt);
-                       return 0;
-               case ICMP_ADDRESSREPLY:
-                       skb1->sk = NULL;
-                       kfree_skb(skb1, FREE_READ);
-                       return(0);
-               default:
-                       DPRINTF((DBG_ICMP,
-                               "ICMP: Unsupported ICMP from %s, type = 0x%X\n",
-                                                       in_ntoa(saddr), icmph->type));
-                       skb1->sk = NULL;
-                       kfree_skb(skb1, FREE_READ);
-                       return(0);
-       }
-       /*NOTREACHED*/
-       skb1->sk = NULL;
-       kfree_skb(skb1, FREE_READ);
-       return(-1);
+       case ICMP_ADDRESS:
+               icmp_address(icmph, skb1, dev, saddr, daddr, len, opt);
+               return 0;
+       case ICMP_ADDRESSREPLY:
+               skb1->sk = NULL;
+               kfree_skb(skb1, FREE_READ);
+               return(0);
+       default:
+               DPRINTF((DBG_ICMP,
+                       "ICMP: Unsupported ICMP from %s, type = 0x%X\n",
+                                               in_ntoa(saddr), icmph->type));
+               skb1->sk = NULL;
+               kfree_skb(skb1, FREE_READ);
+               return(0);
+  }
+  /*NOTREACHED*/
+  skb1->sk = NULL;
+  kfree_skb(skb1, FREE_READ);
+  return(-1);
 }
 
 
-/* 
- *     Perform any ICMP-related I/O control requests. 
- *
- *     In the case of ICMP all the user can do is play with the debygging
- */
-int icmp_ioctl(struct sock *sk, int cmd, unsigned long arg)
+/* Perform any ICMP-related I/O control requests. */
+int
+icmp_ioctl(struct sock *sk, int cmd, unsigned long arg)
 {
-       switch(cmd) 
-       {
-               case DDIOCSDBG:
-                       return(dbg_ioctl((void *) arg, DBG_ICMP));
-               default:
-                       return(-EINVAL);
-       }
-       return(0);
+  switch(cmd) {
+       case DDIOCSDBG:
+               return(dbg_ioctl((void *) arg, DBG_ICMP));
+       default:
+               return(-EINVAL);
+  }
+  return(0);
 }
index a3cc4ec5114b16b531be66973e3865a3cb221a0b..4c9f924c3e7df4e6653458d3341ff2449888605f 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             The Internet Protocol (IP) module.
  *
- * Version:    @(#)ip.c        1.28    20/12/93
+ * Version:    @(#)ip.c        1.0.16b 9/1/93
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *             Gerhard Koerting:       IP interface addressing fix.
  *             Linus Torvalds  :       More robustness checks
  *             Alan Cox        :       Even more checks: Still not as robust as it ought to be
- *             Alan Cox        :       Reformatted for neatness and final release.
- *             Alan Cox        :       Tags ip header for RAW sockets, and for accept(). Old
- *                                     method wasn't suitable for AX.25
- *             Alan Cox        :       Most of the ip_options processing logic added.
  *
  * To Fix:
- *             RFC791 states that options are a 'required' feature of an
- *             IP implementation. We don't do options at all.
+ *             IP option processing is mostly not needed. ip_forward needs to know about routing rules
+ *             and time stamp but that's about all.
  *
  *             This program is free software; you can redistribute it and/or
  *             modify it under the terms of the GNU General Public License
 #include <linux/sockios.h>
 #include <linux/in.h>
 #include "inet.h"
-#include "devinet.h"
+#include "dev.h"
 #include "eth.h"
 #include "ip.h"
 #include "protocol.h"
 #include "route.h"
 #include "tcp.h"
 #include "skbuff.h"
-#include "sockinet.h"
+#include "sock.h"
 #include "arp.h"
 #include "icmp.h"
 
-/*
- *     These two can normally be left. In olden times the numerous bugs used to
- *     make forwarding go crazy on some nets and fragmentation fragment your
- *     computer 8-)
- */
-#define CONFIG_IP_FORWARD              /* Forwarding ? */
-#define CONFIG_IP_DEFRAG               /* Fragmentation ? */
-
+#define CONFIG_IP_FORWARD
+#define CONFIG_IP_DEFRAG
 
 extern int last_retran;
 extern void sort_send(struct sock *sk);
 
-#ifdef IP_DEBUG
-
-void ip_print(struct iphdr *ip)
+void
+ip_print(struct iphdr *ip)
 {
-       unsigned char buff[32];
-       unsigned char *ptr;
-       int addr, len, i;
-
-       if (inet_debug != DBG_IP) 
-               return;
-
-         /* Dump the IP header. */
-       printk("IP: ihl=%d, version=%d, tos=%d, tot_len=%d\n",
-               ip->ihl, ip->version, ip->tos, ntohs(ip->tot_len));
-       printk("    id=%X, ttl=%d, prot=%d, check=%X\n",
-               ip->id, ip->ttl, ip->protocol, ip->check);
-       printk("    frag_off=%d\n", ip->frag_off);
-       printk("    soucre=%s ", in_ntoa(ip->saddr));
-       printk("dest=%s\n", in_ntoa(ip->daddr));
-       printk("    ----\n");
-
-       /* Dump the data. */
-       ptr = (unsigned char *)(ip + 1);
-       addr = 0;
-       len = ntohs(ip->tot_len) - (4 * ip->ihl);
-       while (len > 0) 
-       {
-               printk("    %04X: ", addr);
-               for(i = 0; i < 16; i++) 
-               {
-                       if (len > 0) 
-                       {
-                               printk("%02X ", (*ptr & 0xFF));
-                               buff[i] = *ptr++;
-                               if (buff[i] < 32 || buff[i] > 126) buff[i] = '.';
-                       } 
-                       else 
-                       {
-                               printk("   ");
-                               buff[i] = ' ';
-                       }
-                       addr++;
-                       len--;
-               };
-               buff[i] = '\0';
-               printk("  \"%s\"\n", buff);
-       }
-       printk("    ----\n\n");
+  unsigned char buff[32];
+  unsigned char *ptr;
+  int addr, len, i;
+
+  if (inet_debug != DBG_IP) return;
+
+  /* Dump the IP header. */
+  printk("IP: ihl=%d, version=%d, tos=%d, tot_len=%d\n",
+          ip->ihl, ip->version, ip->tos, ntohs(ip->tot_len));
+  printk("    id=%X, ttl=%d, prot=%d, check=%X\n",
+          ip->id, ip->ttl, ip->protocol, ip->check);
+  printk("    frag_off=%d\n", ip->frag_off);
+  printk("    soucre=%s ", in_ntoa(ip->saddr));
+  printk("dest=%s\n", in_ntoa(ip->daddr));
+  printk("    ----\n");
+
+  /* Dump the data. */
+  ptr = (unsigned char *)(ip + 1);
+  addr = 0;
+  len = ntohs(ip->tot_len) - (4 * ip->ihl);
+  while (len > 0) {
+       printk("    %04X: ", addr);
+       for(i = 0; i < 16; i++) {
+               if (len > 0) {
+                       printk("%02X ", (*ptr & 0xFF));
+                       buff[i] = *ptr++;
+                       if (buff[i] < 32 || buff[i] > 126) buff[i] = '.';
+               } else {
+                       printk("   ");
+                       buff[i] = ' ';
+               }
+               addr++;
+               len--;
+       };
+       buff[i] = '\0';
+       printk("  \"%s\"\n", buff);
+  }
+  printk("    ----\n\n");
 }
 
-#endif
 
-/*
- *     Low level user requests to the IP device. NOT that same as IP layer
- *     socket requests (which also do nothing useful at the moment)
- */
-int ip_ioctl(struct sock *sk, int cmd, unsigned long arg)
+int
+ip_ioctl(struct sock *sk, int cmd, unsigned long arg)
 {
-       switch(cmd) 
-       {
-               case DDIOCSDBG:
-                       return(dbg_ioctl((void *) arg, DBG_IP));
-               default:
-                       return(-EINVAL);
-       }
+  switch(cmd) {
+       case DDIOCSDBG:
+               return(dbg_ioctl((void *) arg, DBG_IP));
+       default:
+               return(-EINVAL);
+  }
 }
 
 
-/*
- *     These two routines will do routing when we have ip options support 
- *     (RFC 791 page 18,19)
- */
-
-static void strict_route(struct iphdr *iph, struct options *opt)
+/* these two routines will do routining. */
+static void
+strict_route(struct iphdr *iph, struct options *opt)
 {
 }
 
 
-static void loose_route(struct iphdr *iph, struct options *opt)
+static void
+loose_route(struct iphdr *iph, struct options *opt)
 {
 }
 
 
-static void print_ipprot(struct inet_protocol *ipprot)
+static void
+print_ipprot(struct inet_protocol *ipprot)
 {
-       DPRINTF((DBG_IP, "handler = %X, protocol = %d, copy=%d \n",
-               ipprot->handler, ipprot->protocol, ipprot->copy));
+  DPRINTF((DBG_IP, "handler = %X, protocol = %d, copy=%d \n",
+          ipprot->handler, ipprot->protocol, ipprot->copy));
 }
 
 
-/*
- *     This routine will check to see if we have lost a gateway. 
- */
-void ip_route_check(unsigned long daddr)
+/* This routine will check to see if we have lost a gateway. */
+void
+ip_route_check(unsigned long daddr)
 {
 }
 
 
-/* 
- *     This routine puts the options at the end of an ip header. 
- */
-static int build_options(struct iphdr *iph, struct options *opt)
+#if 0
+/* this routine puts the options at the end of an ip header. */
+static int
+build_options(struct iphdr *iph, struct options *opt)
 {
-       unsigned char *ptr;
-       ptr = (unsigned char *)(iph+1);         
-       /* currently we don't support any options. */
-       if(opt==NULL)
-       {
-               *ptr = 0;
-               return (1);
-       }
-       else
-       {
-               memcpy(ptr,opt->option_data,opt->option_length);
-               return((opt->option_length+3)/4);
-       }
+  unsigned char *ptr;
+  /* currently we don't support any options. */
+  ptr = (unsigned char *)(iph+1);
+  *ptr = 0;
+  return (4);
 }
+#endif
 
 
-/*
- *     Take an skb, and fill in the MAC header. 
- */
-static int ip_send(struct sk_buff *skb, unsigned long daddr, int len, struct device *dev,
+/* Take an skb, and fill in the MAC header. */
+static int
+ip_send(struct sk_buff *skb, unsigned long daddr, int len, struct device *dev,
        unsigned long saddr)
 {
-       unsigned char *ptr;
-       int mac;
-
-       ptr = (unsigned char *)(skb + 1);
-       mac = 0;
-       skb->arp = 1;
-       if (dev->hard_header) 
-       {
-               mac = dev->hard_header(ptr, dev, ETH_P_IP, daddr, saddr, len);
-       }       
-       if (mac < 0) 
-       {
-               mac = -mac;
-               skb->arp = 0;
-       }
-       skb->dev = dev;
-       return(mac);
+  unsigned char *ptr;
+  int mac;
+
+  ptr = (unsigned char *)(skb + 1);
+  mac = 0;
+  skb->arp = 1;
+  if (dev->hard_header) {
+       mac = dev->hard_header(ptr, dev, ETH_P_IP, daddr, saddr, len);
+  }
+  if (mac < 0) {
+       mac = -mac;
+       skb->arp = 0;
+  }
+  skb->dev = dev;
+  return(mac);
 }
 
 
@@ -235,419 +196,333 @@ static int ip_send(struct sk_buff *skb, unsigned long daddr, int len, struct dev
  * protocol knows what it's doing, otherwise it uses the
  * routing/ARP tables to select a device struct.
  */
-int ip_build_header(struct sk_buff *skb, unsigned long saddr, unsigned long daddr,
-               struct device **dev, int type, struct options *opt, int len, int ttl,int tos)
+int
+ip_build_header(struct sk_buff *skb, unsigned long saddr, unsigned long daddr,
+               struct device **dev, int type, struct options *opt, int len)
 {
-       static struct options optmem;
-       struct iphdr *iph;
-       struct rtable *rt;
-       unsigned char *buff;
-       unsigned long raddr;
-       static int count = 0;
-       int tmp;
-       int optlen;
-       
-       if (saddr == 0) 
-               saddr = my_addr();
-       
-       DPRINTF((DBG_IP, "ip_build_header (skb=%X, saddr=%X, daddr=%X, *dev=%X,\n"
-               "                 type=%d, opt=%X, len = %d)\n",
-               skb, saddr, daddr, *dev, type, opt, len));
+  static struct options optmem;
+  struct iphdr *iph;
+  struct rtable *rt;
+  unsigned char *buff;
+  unsigned long raddr;
+  static int count = 0;
+  int tmp;
+
+  if (saddr == 0) 
+       saddr = my_addr();
+       
+  DPRINTF((DBG_IP, "ip_build_header (skb=%X, saddr=%X, daddr=%X, *dev=%X,\n"
+          "                 type=%d, opt=%X, len = %d)\n",
+          skb, saddr, daddr, *dev, type, opt, len));
           
-       buff = (unsigned char *)(skb + 1);
+  buff = (unsigned char *)(skb + 1);
 
-       /* See if we need to look up the device. */
-       if (*dev == NULL) 
-       {
-               rt = rt_route(daddr, &optmem);
-               if (rt == NULL) 
-                       return(-ENETUNREACH);
-
-               *dev = rt->rt_dev;
-               if (saddr == 0x0100007FL && daddr != 0x0100007FL) 
-                       saddr = rt->rt_dev->pa_addr;
-               raddr = rt->rt_gateway;
-
-               DPRINTF((DBG_IP, "ip_build_header: saddr set to %s\n", in_ntoa(saddr)));
-               opt = &optmem;
-       } 
-       else 
-       {
-               /* We still need the address of the first hop. */
-               rt = rt_route(daddr, &optmem);
-               raddr = (rt == NULL) ? 0 : rt->rt_gateway;
-       }
-       if (raddr == 0)
-               raddr = daddr;
+  /* See if we need to look up the device. */
+  if (*dev == NULL) {
+       rt = rt_route(daddr, &optmem);
+       if (rt == NULL) 
+               return(-ENETUNREACH);
 
-       /* Now build the MAC header. */
-       tmp = ip_send(skb, raddr, len, *dev, saddr);
-       buff += tmp;
-       len -= tmp;
-
-       skb->dev = *dev;
-       skb->saddr = saddr;
-       if (skb->sk) 
-               skb->sk->saddr = saddr;
-
-       /* Now build the IP header. */
-
-       /* If we are using IPPROTO_RAW, then we don't need an IP header, since
-          one is being supplied to us by the user */
-
-       if(type == IPPROTO_RAW) 
-               return (tmp);
-
-       iph = (struct iphdr *)buff;
-       iph->version  = 4;
-       iph->tos      = tos;
-       iph->frag_off = 0;
-       iph->ttl      = ttl;
-       iph->daddr    = daddr;
-       iph->saddr    = saddr;
-       iph->protocol = type;
-       iph->ihl      = 5;
-       iph->id       = htons(count++);
-       
-       /* Setup the IP options. Length is in longs.*/
+       *dev = rt->rt_dev;
+       if (saddr == 0x0100007FL && daddr != 0x0100007FL) 
+               saddr = rt->rt_dev->pa_addr;
+       raddr = rt->rt_gateway;
 
-       optlen=build_options(iph, opt);
-       iph->ihl+=optlen;
+       DPRINTF((DBG_IP, "ip_build_header: saddr set to %s\n", in_ntoa(saddr)));
+       opt = &optmem;
+  } else {
+       /* We still need the address of the first hop. */
+       rt = rt_route(daddr, &optmem);
+       raddr = (rt == NULL) ? 0 : rt->rt_gateway;
+  }
+  if (raddr == 0)
+       raddr = daddr;
+
+  /* Now build the MAC header. */
+  tmp = ip_send(skb, raddr, len, *dev, saddr);
+  buff += tmp;
+  len -= tmp;
+
+  skb->dev = *dev;
+  skb->saddr = saddr;
+  if (skb->sk) skb->sk->saddr = saddr;
+
+  /* Now build the IP header. */
+
+  /* If we are using IPPROTO_RAW, then we don't need an IP header, since
+     one is being supplied to us by the user */
+
+  if(type == IPPROTO_RAW) return (tmp);
+
+  iph = (struct iphdr *)buff;
+  iph->version  = 4;
+  iph->tos      = 0;
+  iph->frag_off = 0;
+  iph->ttl      = 32;
+  iph->daddr    = daddr;
+  iph->saddr    = saddr;
+  iph->protocol = type;
+  iph->ihl      = 5;
+  iph->id       = htons(count++);
+
+  /* Setup the IP options. */
+#ifdef Not_Yet_Avail
+  build_options(iph, opt);
+#endif
 
-       return(20 + tmp + 4*optlen);    /* IP header plus MAC header size */
+  return(20 + tmp);    /* IP header plus MAC header size */
 }
 
 
-/*
- *     Interpret the incoming options
- */
-
-static int do_options(struct iphdr *iph, struct options **opt_ptr, struct device *dev)
+static int
+do_options(struct iphdr *iph, struct options *opt)
 {
-       unsigned char *buff;
-       int done = 0;
-       int i, len = sizeof(struct iphdr);
-       unsigned char *outbuf;
-       struct options *opt;
-       int ol;
-       int optsiz;
-       
-       if(iph->ihl==5)
-       {
-               *opt_ptr=NULL;
-               return(0);
-       }
-
-       /* Allocate a buffer to stuff the options (decoded) and the raw option data into */
-       
-       ol=(iph->ihl*4)-sizeof(struct iphdr);
-       
-       opt=(struct options *)kmalloc(ol+sizeof(*opt),GFP_ATOMIC);
-       *opt_ptr=opt;
-       
-       if(opt==NULL)
-               return(1);
-
-       opt->option_length=ol;  
-       outbuf=(unsigned char *)(opt+1);
-       opt->option_data=outbuf;
-       
-       /* Zero out the options. */
-       opt->record_route.route_size = 0;
-       opt->loose_route.route_size  = 0;
-       opt->strict_route.route_size = 0;
-       opt->tstamp.ptr              = 0;
-       opt->security                = 0;
-       opt->compartment             = 0;
-       opt->handling                = 0;
-       opt->stream                  = 0;
-       opt->tcc                     = 0;
-       
-               
-       /* Advance the pointer to start at the options. */
-       buff = (unsigned char *)(iph + 1);
-       /* Copy the data */
-       memcpy(outbuf,buff,opt->option_length);
-       buff = outbuf;
-       
-       /* Now start the processing. */
-       while (!done && len < iph->ihl*4) switch(*buff) 
-       {
-               case IPOPT_END:
-                       done = 1;
-                       break;
-               case IPOPT_NOOP:
-                       buff++;
-                       len++;
-                       break;
-               case IPOPT_SEC:
-                       buff++;
-                       if (*buff != 11) 
-                               return(1);
-                       buff++;
-                       opt->security = ntohs(*(unsigned short *)buff);
-                       buff += 2;
-                       opt->compartment = ntohs(*(unsigned short *)buff);
-                       buff += 2;
-                       opt->handling = ntohs(*(unsigned short *)buff);
-                       buff += 2;
-                       opt->tcc = ((*buff) << 16) + ntohs(*(unsigned short *)(buff+1));
-                       buff += 3;
-                       len += 11;
-                       break;
-               case IPOPT_LSRR:
-                       buff++;
-                       if ((*buff - 3)% 4 != 0) 
-                               return(1);
-                       if(*buff<2)
-                               return(1);
-                       len += (optsiz= *buff);
-                       opt->loose_route.route_size = (*buff -3)/4;
-                       buff++;
-                       if (*buff % 4 != 0) 
-                               return(1);
-                       opt->loose_route.pointer = *buff/4 - 1;
-                       if(*buff<=optsiz)
-                               *buff+=4;       /* Move on a route */
-                       buff++;
-                       buff++;
-                       for (i = 0; i < opt->loose_route.route_size; i++) 
-                       {
-                               if(i>=MAX_ROUTE)
-                                       return(1);
-                               if(i==opt->strict_route.pointer)
-                                       *(unsigned long *)buff=dev->pa_addr;
-                               opt->loose_route.route[i] = *(unsigned long *)buff;
-                               buff += 4;
-                       }
-                       break;
-               case IPOPT_SSRR:
-                       buff++;
-                       if ((*buff - 3)% 4 != 0) 
+  unsigned char *buff;
+  int done = 0;
+  int i, len = sizeof(struct iphdr);
+
+  /* Zero out the options. */
+  opt->record_route.route_size = 0;
+  opt->loose_route.route_size  = 0;
+  opt->strict_route.route_size = 0;
+  opt->tstamp.ptr              = 0;
+  opt->security                = 0;
+  opt->compartment             = 0;
+  opt->handling                = 0;
+  opt->stream                  = 0;
+  opt->tcc                     = 0;
+  return(0);
+
+  /* Advance the pointer to start at the options. */
+  buff = (unsigned char *)(iph + 1);
+
+  /* Now start the processing. */
+  while (!done && len < iph->ihl*4) switch(*buff) {
+       case IPOPT_END:
+               done = 1;
+               break;
+       case IPOPT_NOOP:
+               buff++;
+               len++;
+               break;
+       case IPOPT_SEC:
+               buff++;
+               if (*buff != 11) return(1);
+               buff++;
+               opt->security = ntohs(*(unsigned short *)buff);
+               buff += 2;
+               opt->compartment = ntohs(*(unsigned short *)buff);
+               buff += 2;
+               opt->handling = ntohs(*(unsigned short *)buff);
+               buff += 2;
+               opt->tcc = ((*buff) << 16) + ntohs(*(unsigned short *)(buff+1));
+               buff += 3;
+               len += 11;
+               break;
+       case IPOPT_LSRR:
+               buff++;
+               if ((*buff - 3)% 4 != 0) return(1);
+               len += *buff;
+               opt->loose_route.route_size = (*buff -3)/4;
+               buff++;
+               if (*buff % 4 != 0) return(1);
+               opt->loose_route.pointer = *buff/4 - 1;
+               buff++;
+               buff++;
+               for (i = 0; i < opt->loose_route.route_size; i++) {
+                       if(i>=MAX_ROUTE)
                                return(1);
-                       if(*buff<2)
-                               return(1);
-                       len += (optsiz= *buff);
-                       opt->strict_route.route_size = (*buff -3)/4;
-                       buff++;
-                       if (*buff % 4 != 0) 
-                               return(1);
-                       opt->strict_route.pointer = *buff/4 - 1;
-                       if(*buff<=optsiz)
-                               *buff+=4;
-                       buff++;
-                       buff++;
-                       for (i = 0; i < opt->strict_route.route_size; i++) 
-                       {
-                               if(i>=MAX_ROUTE)
-                                       return(1);
-                               if(i==opt->strict_route.pointer)
-                                       *(unsigned long *)buff=dev->pa_addr;                                    
-                               opt->strict_route.route[i] = *(unsigned long *)buff;
-                               buff += 4;
-                       }       
-                       break;
-               case IPOPT_RR:
-                       buff++;
-                       if ((*buff - 3)% 4 != 0) 
-                               return(1);
-                       if(*buff<2)
-                               return(1);
-                       len += (optsiz= *buff);
-                       opt->record_route.route_size = (*buff -3)/4;
-                       buff++;
-                       if (*buff % 4 != 0)
+                       opt->loose_route.route[i] = *(unsigned long *)buff;
+                       buff += 4;
+               }
+               break;
+       case IPOPT_SSRR:
+               buff++;
+               if ((*buff - 3)% 4 != 0) return(1);
+               len += *buff;
+               opt->strict_route.route_size = (*buff -3)/4;
+               buff++;
+               if (*buff % 4 != 0) return(1);
+               opt->strict_route.pointer = *buff/4 - 1;
+               buff++;
+               buff++;
+               for (i = 0; i < opt->strict_route.route_size; i++) {
+                       if(i>=MAX_ROUTE)
                                return(1);
-                       opt->record_route.pointer = *buff/4 - 1;
-                       if(*buff+4<=optsiz)
-                               *buff+=4;
-                       buff++;
-                       buff++;
-                       for (i = 0; i < opt->record_route.route_size; i++) 
-                       {
-                               if(i>=MAX_ROUTE)
-                                       return 1;
-                               if(i==opt->record_route.pointer)
-                                       *(unsigned long *)buff=dev->pa_addr;
-                               opt->record_route.route[i] = *(unsigned long *)buff;
-                               buff += 4;
-                       }
-                       break;
-               case IPOPT_SID:
-                       len += 4;
-                       buff +=2;
-                       opt->stream = *(unsigned short *)buff;
-                       buff += 2;
-                       break;
-               case IPOPT_TIMESTAMP:
-                       /* FIXME: This one isn't altered correctly yet */
-                       buff++;
-                       if(*buff<2)
+                       opt->strict_route.route[i] = *(unsigned long *)buff;
+                       buff += 4;
+               }
+               break;
+       case IPOPT_RR:
+               buff++;
+               if ((*buff - 3)% 4 != 0) return(1);
+               len += *buff;
+               opt->record_route.route_size = (*buff -3)/4;
+               buff++;
+               if (*buff % 4 != 0) return(1);
+               opt->record_route.pointer = *buff/4 - 1;
+               buff++;
+               buff++;
+               for (i = 0; i < opt->record_route.route_size; i++) {
+                       if(i>=MAX_ROUTE)
                                return 1;
-                       len += *buff;
-                       if (*buff % 4 != 0) 
-                               return(1);
-                       opt->tstamp.len = *buff / 4 - 1;
-                       buff++;
-                       if ((*buff - 1) % 4 != 0) 
-                               return(1);
-                       opt->tstamp.ptr = (*buff-1)/4;
-                       buff++;
-                       opt->tstamp.x.full_char = *buff;
-                       buff++;
-                       for (i = 0; i < opt->tstamp.len; i++) 
-                       {
-                               opt->tstamp.data[i] = *(unsigned long *)buff;
-                               buff += 4;
-                       }
-                       break;
-               default:
-                       return(1);
-       }
+                       opt->record_route.route[i] = *(unsigned long *)buff;
+                       buff += 4;
+               }
+               break;
+       case IPOPT_SID:
+               len += 4;
+               buff +=2;
+               opt->stream = *(unsigned short *)buff;
+               buff += 2;
+               break;
+       case IPOPT_TIMESTAMP:
+               buff++;
+               len += *buff;
+               if (*buff % 4 != 0) return(1);
+               opt->tstamp.len = *buff / 4 - 1;
+               buff++;
+               if ((*buff - 1) % 4 != 0) return(1);
+               opt->tstamp.ptr = (*buff-1)/4;
+               buff++;
+               opt->tstamp.x.full_char = *buff;
+               buff++;
+               for (i = 0; i < opt->tstamp.len; i++) {
+                       opt->tstamp.data[i] = *(unsigned long *)buff;
+                       buff += 4;
+               }
+               break;
+       default:
+               return(1);
+  }
 
-       if (opt->record_route.route_size == 0) 
-       {
-               if (opt->strict_route.route_size != 0) 
-               {
-                       memcpy(&(opt->record_route), &(opt->strict_route),
+  if (opt->record_route.route_size == 0) {
+       if (opt->strict_route.route_size != 0) {
+               memcpy(&(opt->record_route), &(opt->strict_route),
                                             sizeof(opt->record_route));
-               } 
-               else if (opt->loose_route.route_size != 0) 
-               {
-                       memcpy(&(opt->record_route), &(opt->loose_route),
+       } else if (opt->loose_route.route_size != 0) {
+               memcpy(&(opt->record_route), &(opt->loose_route),
                                             sizeof(opt->record_route));
-               }
        }
+  }
 
-       if (opt->strict_route.route_size != 0 &&
-               opt->strict_route.route_size != opt->strict_route.pointer) 
-       {
-               strict_route(iph, opt);
-               return(0);
-       }
-
-       if (opt->loose_route.route_size != 0 &&
-           opt->loose_route.route_size != opt->loose_route.pointer) 
-       {
-               loose_route(iph, opt);
-               return(0);
-       }
+  if (opt->strict_route.route_size != 0 &&
+      opt->strict_route.route_size != opt->strict_route.pointer) {
+       strict_route(iph, opt);
+       return(0);
+  }
 
+  if (opt->loose_route.route_size != 0 &&
+      opt->loose_route.route_size != opt->loose_route.pointer) {
+       loose_route(iph, opt);
        return(0);
+  }
+
+  return(0);
 }
 
-/* 
- *     This is a version of ip_compute_csum() optimized for IP headers, which
- *     always checksum on 4 octet boundaries. 
- */
-static inline unsigned short ip_fast_csum(unsigned char * buff, int wlen)
+/* This is a version of ip_compute_csum() optimized for IP headers, which
+   always checksum on 4 octet boundaries. */
+static inline unsigned short
+ip_fast_csum(unsigned char * buff, int wlen)
 {
-       unsigned long sum = 0;
-
-       if (wlen) {
-               unsigned long bogus;
-                __asm__("clc\n"
-                       "1:\t"
-                       "lodsl\n\t"
-                       "adcl %3, %0\n\t"
-                       "decl %2\n\t"
-                       "jne 1b\n\t"
-                       "adcl $0, %0\n\t"
-                       "movl %0, %3\n\t"
-                       "shrl $16, %3\n\t"
-                       "addw %w3, %w0\n\t"
-                       "adcw $0, %w0"
-                       : "=r" (sum), "=S" (buff), "=r" (wlen), "=a" (bogus)
-                       : "0"  (sum),  "1" (buff),  "2" (wlen));
-       }
-       return (~sum) & 0xffff;
+    unsigned long sum = 0;
+
+    if (wlen) {
+       unsigned long bogus;
+        __asm__("clc\n"
+               "1:\t"
+               "lodsl\n\t"
+               "adcl %3, %0\n\t"
+               "decl %2\n\t"
+               "jne 1b\n\t"
+               "adcl $0, %0\n\t"
+               "movl %0, %3\n\t"
+               "shrl $16, %3\n\t"
+               "addw %w3, %w0\n\t"
+               "adcw $0, %w0"
+           : "=r" (sum), "=S" (buff), "=r" (wlen), "=a" (bogus)
+           : "0"  (sum),  "1" (buff),  "2" (wlen));
+    }
+    return (~sum) & 0xffff;
 }
 
 /*
  * This routine does all the checksum computations that don't
  * require anything special (like copying or special headers).
  */
-
-unsigned short ip_compute_csum(unsigned char * buff, int len)
+unsigned short
+ip_compute_csum(unsigned char * buff, int len)
 {
-       unsigned long sum = 0;
-
-       /* Do the first multiple of 4 bytes and convert to 16 bits. */
-       if (len > 3) {
-               __asm__("clc\n"
-                       "1:\t"
-                       "lodsl\n\t"
-                       "adcl %%eax, %%ebx\n\t"
-                       "loop 1b\n\t"
-                       "adcl $0, %%ebx\n\t"
-                       "movl %%ebx, %%eax\n\t"
-                       "shrl $16, %%eax\n\t"
-                       "addw %%ax, %%bx\n\t"
-                       "adcw $0, %%bx"
-                       : "=b" (sum) , "=S" (buff)
-                       : "0" (sum), "c" (len >> 2) ,"1" (buff)
-                       : "ax", "cx", "si", "bx" );
-       }
-       if (len & 2) {
-               __asm__("lodsw\n\t"
-                       "addw %%ax, %%bx\n\t"
-                       "adcw $0, %%bx"
-                       : "=b" (sum), "=S" (buff)
-                       : "0" (sum), "1" (buff)
-                       : "bx", "ax", "si");
-       }
-       if (len & 1) {
-               __asm__("lodsb\n\t"
-                       "movb $0, %%ah\n\t"
-                       "addw %%ax, %%bx\n\t"
-                       "adcw $0, %%bx"
-                       : "=b" (sum), "=S" (buff)
-                       : "0" (sum), "1" (buff)
-                       : "bx", "ax", "si");
-       }
-       sum =~sum;
-       return(sum & 0xffff);
+  unsigned long sum = 0;
+
+  /* Do the first multiple of 4 bytes and convert to 16 bits. */
+  if (len > 3) {
+       __asm__("clc\n"
+               "1:\t"
+               "lodsl\n\t"
+               "adcl %%eax, %%ebx\n\t"
+               "loop 1b\n\t"
+               "adcl $0, %%ebx\n\t"
+               "movl %%ebx, %%eax\n\t"
+               "shrl $16, %%eax\n\t"
+               "addw %%ax, %%bx\n\t"
+               "adcw $0, %%bx"
+               : "=b" (sum) , "=S" (buff)
+               : "0" (sum), "c" (len >> 2) ,"1" (buff)
+               : "ax", "cx", "si", "bx" );
+  }
+  if (len & 2) {
+       __asm__("lodsw\n\t"
+               "addw %%ax, %%bx\n\t"
+               "adcw $0, %%bx"
+               : "=b" (sum), "=S" (buff)
+               : "0" (sum), "1" (buff)
+               : "bx", "ax", "si");
+  }
+  if (len & 1) {
+       __asm__("lodsb\n\t"
+               "movb $0, %%ah\n\t"
+               "addw %%ax, %%bx\n\t"
+               "adcw $0, %%bx"
+               : "=b" (sum), "=S" (buff)
+               : "0" (sum), "1" (buff)
+               : "bx", "ax", "si");
+  }
+  sum =~sum;
+  return(sum & 0xffff);
 }
 
-/*
- *     Check the header of an incoming IP datagram.  This version is still used in slhc.c. 
- */
-
-int ip_csum(struct iphdr *iph)
+/* Check the header of an incoming IP datagram.  This version is still used in slhc.c. */
+int
+ip_csum(struct iphdr *iph)
 {
-       return ip_fast_csum((unsigned char *)iph, iph->ihl);
+  return ip_fast_csum((unsigned char *)iph, iph->ihl);
 }
 
-/* 
- *     Generate a checksym for an outgoing IP datagram.  (RFC791, Page 14)
- */
-
-static void ip_send_check(struct iphdr *iph)
+/* Generate a checksym for an outgoing IP datagram. */
+static void
+ip_send_check(struct iphdr *iph)
 {
-       iph->check = 0;
-       iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
+   iph->check = 0;
+   iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
 }
 
 /************************ Fragment Handlers From NET2E not yet with tweaks to beat 4K **********************************/
 
 static struct ipq *ipqueue = NULL;             /* IP fragment queue    */
-
-/* 
- *     Create a new fragment entry. 
- */
+ /* Create a new fragment entry. */
 static struct ipfrag *ip_frag_create(int offset, int end, struct sk_buff *skb, unsigned char *ptr)
 {
-       struct ipfrag *fp;
+       struct ipfrag *fp;
  
-       fp = (struct ipfrag *) kmalloc(sizeof(struct ipfrag), GFP_ATOMIC);
-       if (fp == NULL) 
-       {
+       fp = (struct ipfrag *) kmalloc(sizeof(struct ipfrag), GFP_ATOMIC);
+       if (fp == NULL) 
+       {
                printk("IP: frag_create: no memory left !\n");
                return(NULL);
-       }
-       memset(fp, 0, sizeof(struct ipfrag));
+       }
+       memset(fp, 0, sizeof(struct ipfrag));
 
         /* Fill in the structure. */
        fp->offset = offset;
@@ -664,7 +539,6 @@ static struct ipfrag *ip_frag_create(int offset, int end, struct sk_buff *skb, u
  * Find the correct entry in the "incomplete datagrams" queue for
  * this IP datagram, and return the queue entry address if found.
  */
-
 static struct ipq *ip_find(struct iphdr *iph)
 {
        struct ipq *qp;
@@ -674,14 +548,14 @@ static struct ipq *ip_find(struct iphdr *iph)
        qplast = NULL;
        for(qp = ipqueue; qp != NULL; qplast = qp, qp = qp->next) 
        {
-               if (iph->id== qp->iph->id && iph->saddr == qp->iph->saddr &&
+               if (iph->id== qp->iph->id && iph->saddr == qp->iph->saddr &&
                        iph->daddr == qp->iph->daddr && iph->protocol == qp->iph->protocol) 
                {
                        del_timer(&qp->timer);  /* So it doesnt vanish on us. The timer will be reset anyway */
-                       sti();
-                       return(qp);
-               }
-       }
+                       sti();
+                       return(qp);
+               }
+       }
        sti();
        return(NULL);
 }
@@ -709,62 +583,60 @@ static void ip_free(struct ipq *qp)
                ipqueue = qp->next;
                if (ipqueue != NULL) 
                        ipqueue->prev = NULL;
-       } 
-       else 
-       {
-               qp->prev->next = qp->next;
-               if (qp->next != NULL) 
-                       qp->next->prev = qp->prev;
-       }
-       /* Release all fragment data. */
+       } 
+       else 
+       {
+               qp->prev->next = qp->next;
+               if (qp->next != NULL) 
+                       qp->next->prev = qp->prev;
+       }
+       /* Release all fragment data. */
 /*     printk("ip_free: kill frag data\n");*/
-       fp = qp->fragments;
-       while (fp != NULL) 
-       {
-               xp = fp->next;
-               IS_SKB(fp->skb);
-               kfree_skb(fp->skb,FREE_READ);
-               kfree_s(fp, sizeof(struct ipfrag));
-               fp = xp;
-       }
-       
+       fp = qp->fragments;
+       while (fp != NULL) 
+       {
+               xp = fp->next;
+               IS_SKB(fp->skb);
+               kfree_skb(fp->skb,FREE_READ);
+               kfree_s(fp, sizeof(struct ipfrag));
+               fp = xp;
+       }
+       
 /*     printk("ip_free: cleanup\n");*/
  
-       /* Release the MAC header. */
-       kfree_s(qp->mac, qp->maclen);
+       /* Release the MAC header. */
+       kfree_s(qp->mac, qp->maclen);
  
-       /* Release the IP header. */
-       kfree_s(qp->iph, qp->ihlen + 8);
+       /* Release the IP header. */
+       kfree_s(qp->iph, qp->ihlen + 8);
  
-       /* Finally, release the queue descriptor itself. */
-       kfree_s(qp, sizeof(struct ipq));
+       /* Finally, release the queue descriptor itself. */
+       kfree_s(qp, sizeof(struct ipq));
 /*     printk("ip_free:done\n");*/
-       sti();
+       sti();
  }
  
  
-/*
- *     Oops- a fragment queue timed out.  Kill it and send an ICMP reply. 
- */
+ /* Oops- a fragment queue timed out.  Kill it and send an ICMP reply. */
  
 static void ip_expire(unsigned long arg)
 {
-       struct ipq *qp;
+       struct ipq *qp;
  
-       qp = (struct ipq *)arg;
-       DPRINTF((DBG_IP, "IP: queue_expire: fragment queue 0x%X timed out!\n", qp));
+       qp = (struct ipq *)arg;
+       DPRINTF((DBG_IP, "IP: queue_expire: fragment queue 0x%X timed out!\n", qp));
  
-       /* Send an ICMP "Fragment Reassembly Timeout" message. */
+       /* Send an ICMP "Fragment Reassembly Timeout" message. */
 #if 0          
-       icmp_send(qp->iph->ip_src.s_addr, ICMP_TIME_EXCEEDED,
-                   ICMP_EXC_FRAGTIME, qp->iph);
+       icmp_send(qp->iph->ip_src.s_addr, ICMP_TIME_EXCEEDED,
+                   ICMP_EXC_FRAGTIME, qp->iph);
 #endif                  
-       if(qp->fragments!=NULL)
-               icmp_send(qp->fragments->skb,ICMP_TIME_EXCEEDED,
-                               ICMP_EXC_FRAGTIME, qp->dev);
+       if(qp->fragments!=NULL)
+               icmp_send(qp->fragments->skb,ICMP_TIME_EXCEEDED,
+                               ICMP_EXC_FRAGTIME, qp->dev);
  
-       /* Nuke the fragment queue. */
+       /* Nuke the fragment queue. */
        ip_free(qp);
 }
  
@@ -778,168 +650,158 @@ static void ip_expire(unsigned long arg)
 
 static struct ipq *ip_create(struct sk_buff *skb, struct iphdr *iph, struct device *dev)
 {
-       struct ipq *qp;
-       int maclen;
-       int ihlen;
+       struct ipq *qp;
+       int maclen;
+       int ihlen;
 
-       qp = (struct ipq *) kmalloc(sizeof(struct ipq), GFP_ATOMIC);
-       if (qp == NULL) 
-       {
+       qp = (struct ipq *) kmalloc(sizeof(struct ipq), GFP_ATOMIC);
+       if (qp == NULL) 
+       {
                printk("IP: create: no memory left !\n");
                return(NULL);
-       }
-       memset(qp, 0, sizeof(struct ipq));
-
-       /* Allocate memory for the MAC header. */
-       maclen = ((unsigned long) iph) - ((unsigned long) (skb + 1));
-       qp->mac = (unsigned char *) kmalloc(maclen, GFP_ATOMIC);
-       if (qp->mac == NULL) 
-       {
+       }
+       memset(qp, 0, sizeof(struct ipq));
+
+       /* Allocate memory for the MAC header. */
+       maclen = ((unsigned long) iph) - ((unsigned long) (skb + 1));
+       qp->mac = (unsigned char *) kmalloc(maclen, GFP_ATOMIC);
+       if (qp->mac == NULL) 
+       {
                printk("IP: create: no memory left !\n");
                kfree_s(qp, sizeof(struct ipq));
                return(NULL);
-       }
+       }
 
-       /* Allocate memory for the IP header (plus 8 octects for ICMP). */
-       ihlen = (iph->ihl * sizeof(unsigned long));
-       qp->iph = (struct iphdr *) kmalloc(ihlen + 8, GFP_ATOMIC);
-       if (qp->iph == NULL) 
-       {
+       /* Allocate memory for the IP header (plus 8 octects for ICMP). */
+       ihlen = (iph->ihl * sizeof(unsigned long));
+       qp->iph = (struct iphdr *) kmalloc(ihlen + 8, GFP_ATOMIC);
+       if (qp->iph == NULL) 
+       {
                printk("IP: create: no memory left !\n");
                kfree_s(qp->mac, maclen);
                kfree_s(qp, sizeof(struct ipq));
                return(NULL);
-       }
-
-       /* Fill in the structure. */
-       memcpy(qp->mac, (skb + 1), maclen);
-       memcpy(qp->iph, iph, ihlen + 8);
-       qp->len = 0;
-       qp->ihlen = ihlen;
-       qp->maclen = maclen;
-       qp->fragments = NULL;
-       qp->dev = dev;
+       }
+
+       /* Fill in the structure. */
+       memcpy(qp->mac, (skb + 1), maclen);
+       memcpy(qp->iph, iph, ihlen + 8);
+       qp->len = 0;
+       qp->ihlen = ihlen;
+       qp->maclen = maclen;
+       qp->fragments = NULL;
+       qp->dev = dev;
 /*     printk("Protocol = %d\n",qp->iph->protocol);*/
        
-       /* Start a timer for this entry. */
-       qp->timer.expires = IP_FRAG_TIME;               /* about 30 seconds     */
-       qp->timer.data = (unsigned long) qp;            /* pointer to queue     */
-       qp->timer.function = ip_expire;                 /* expire function      */
-       add_timer(&qp->timer);
-
-       /* Add this entry to the queue. */
-       qp->prev = NULL;
-       cli();
-       qp->next = ipqueue;
-       if (qp->next != NULL) 
-               qp->next->prev = qp;
-       ipqueue = qp;
-       sti();
-       return(qp);
+       /* Start a timer for this entry. */
+       qp->timer.expires = IP_FRAG_TIME;               /* about 30 seconds     */
+       qp->timer.data = (unsigned long) qp;            /* pointer to queue     */
+       qp->timer.function = ip_expire;                 /* expire function      */
+       add_timer(&qp->timer);
+
+       /* Add this entry to the queue. */
+       qp->prev = NULL;
+       cli();
+       qp->next = ipqueue;
+       if (qp->next != NULL) 
+               qp->next->prev = qp;
+       ipqueue = qp;
+       sti();
+       return(qp);
 }
  
  
-/*
- *     See if a fragment queue is complete. 
- */
+ /* See if a fragment queue is complete. */
 static int ip_done(struct ipq *qp)
 {
        struct ipfrag *fp;
        int offset;
  
-       /* Only possible if we received the final fragment. */
-       if (qp->len == 0) 
-               return(0);
-       /* Check all fragment offsets to see if they connect. */
-       fp = qp->fragments;
-       offset = 0;
-       while (fp != NULL) 
-       {
-               if (fp->offset > offset) 
-                       return(0);      /* fragment(s) missing */
-               offset = fp->end;
-               fp = fp->next;
-       }
-       /* All fragments are present. */
-       return(1);
+       /* Only possible if we received the final fragment. */
+       if (qp->len == 0) 
+               return(0);
+       /* Check all fragment offsets to see if they connect. */
+       fp = qp->fragments;
+       offset = 0;
+       while (fp != NULL) 
+       {
+               if (fp->offset > offset) 
+                       return(0);      /* fragment(s) missing */
+               offset = fp->end;
+               fp = fp->next;
+       }
+       /* All fragments are present. */
+       return(1);
  }
  
  
-/*
- *     Build a new IP datagram from all its fragments. 
- */
+/* Build a new IP datagram from all its fragments. */
 static struct sk_buff *ip_glue(struct ipq *qp)
 {
        struct sk_buff *skb;
-       struct iphdr *iph;
-       struct ipfrag *fp;
-       unsigned char *ptr;
-       int count, len;
-       /* Allocate a new buffer for the datagram. */
-       len = sizeof(struct sk_buff)+qp->maclen + qp->ihlen + qp->len;
-       if ((skb = alloc_skb(len,GFP_ATOMIC)) == NULL) 
-       {
-               printk("IP: queue_glue: no memory for glueing queue 0x%X\n", (int) qp);
-               ip_free(qp);
-               return(NULL);
-       }
-       /* Fill in the basic details. */
-       skb->len = (len - qp->maclen);
-       skb->h.raw = (unsigned char *) (skb + 1);
-       skb->free = 1;
-       skb->lock = 1;
-       /* Copy the original MAC and IP headers into the new buffer. */
-       ptr = (unsigned char *) skb->h.raw;
-       memcpy(ptr, ((unsigned char *) qp->mac), qp->maclen);
+       struct iphdr *iph;
+       struct ipfrag *fp;
+       unsigned char *ptr;
+       int count, len;
+       /* Allocate a new buffer for the datagram. */
+       len = sizeof(struct sk_buff)+qp->maclen + qp->ihlen + qp->len;
+       if ((skb = alloc_skb(len,GFP_ATOMIC)) == NULL) 
+       {
+               printk("IP: queue_glue: no memory for glueing queue 0x%X\n", (int) qp);
+               ip_free(qp);
+               return(NULL);
+       }
+       /* Fill in the basic details. */
+       skb->len = (len - qp->maclen);
+       skb->h.raw = (unsigned char *) (skb + 1);
+       skb->free = 1;
+       skb->lock = 1;
+       /* Copy the original MAC and IP headers into the new buffer. */
+       ptr = (unsigned char *) skb->h.raw;
+       memcpy(ptr, ((unsigned char *) qp->mac), qp->maclen);
 /*     printk("Copied %d bytes of mac header.\n",qp->maclen);*/
-       ptr += qp->maclen;
-       memcpy(ptr, ((unsigned char *) qp->iph), qp->ihlen);
+       ptr += qp->maclen;
+       memcpy(ptr, ((unsigned char *) qp->iph), qp->ihlen);
 /*     printk("Copied %d byte of ip header.\n",qp->ihlen);*/
-       ptr += qp->ihlen;
-       skb->h.raw += qp->maclen;
-       
+       ptr += qp->ihlen;
+       skb->h.raw += qp->maclen;
+       
 /*     printk("Protocol = %d\n",skb->h.iph->protocol);*/
-       count = 0;
-       /* Copy the data portions of all fragments into the new buffer. */
-       fp = qp->fragments;
-       while(fp != NULL) 
-       {
-               if(count+fp->len>skb->len)
-               {
-                       /* In case some fool sends us a silly fragment. */
-                       printk("Invalid fragment list: Fragment over size.\n");
-                       kfree_skb(skb,FREE_WRITE);
-                       return NULL;
-               }
+       count = 0;
+       /* Copy the data portions of all fragments into the new buffer. */
+       fp = qp->fragments;
+       while(fp != NULL) 
+       {
+               if(count+fp->len>skb->len)
+               {
+                       printk("Invalid fragment list: Fragment over size.\n");
+                       kfree_skb(skb,FREE_WRITE);
+                       return NULL;
+               }
 /*             printk("Fragment %d size %d\n",fp->offset,fp->len);*/
-               memcpy((ptr + fp->offset), fp->ptr, fp->len);
-               count += fp->len;
-               fp = fp->next;
-       }
-       /* We glued together all fragments, so remove the queue entry. */
-       ip_free(qp);
-       /* Done with all fragments. Fixup the new IP header. */
-       iph = skb->h.iph;
-       iph->frag_off = 0;
-       iph->tot_len = htons((iph->ihl * sizeof(unsigned long)) + count);
-       return(skb);
+               memcpy((ptr + fp->offset), fp->ptr, fp->len);
+               count += fp->len;
+               fp = fp->next;
+       }
+       /* We glued together all fragments, so remove the queue entry. */
+       ip_free(qp);
+       /* Done with all fragments. Fixup the new IP header. */
+       iph = skb->h.iph;
+       iph->frag_off = 0;
+       iph->tot_len = htons((iph->ihl * sizeof(unsigned long)) + count);
+       return(skb);
 }
  
 
-/* 
- *     Process an incoming IP datagram fragment. 
- */
+/* Process an incoming IP datagram fragment. */
 static struct sk_buff *ip_defrag(struct iphdr *iph, struct sk_buff *skb, struct device *dev)
 {
        struct ipfrag *prev, *next;
@@ -951,135 +813,135 @@ static struct sk_buff *ip_defrag(struct iphdr *iph, struct sk_buff *skb, struct
        int i, ihl, end;
 
        /* Find the entry of this IP datagram in the "incomplete datagrams" queue. */
-       qp = ip_find(iph);
-       /* Is this a non-fragmented datagram? */
-       offset = ntohs(iph->frag_off);
-       flags = offset & ~IP_OFFSET;
-       offset &= IP_OFFSET;
-       if (((flags & IP_MF) == 0) && (offset == 0)) 
-       {
-               if (qp != NULL) 
-                       ip_free(qp);    /* Huh? How could this exist?? */
-               return(skb);
-       }
-       offset <<= 3;           /* offset is in 8-byte chunks */
-       /*
-        * If the queue already existed, keep restarting its timer as long
-        * as we still are receiving fragments.  Otherwise, create a fresh
-        * queue entry.
-        */
-       if (qp != NULL) 
-       {
-               del_timer(&qp->timer);
-               qp->timer.expires = IP_FRAG_TIME;       /* about 30 seconds     */
-               qp->timer.data = (unsigned long) qp;    /* pointer to queue     */
-               qp->timer.function = ip_expire;         /* expire function      */
-               add_timer(&qp->timer);
-       } 
-       else 
-       {
-               if ((qp = ip_create(skb, iph, dev)) == NULL) 
-                       return(NULL);
-       }
-       /* Determine the position of this fragment. */
-       ihl = (iph->ihl * sizeof(unsigned long));
-       end = offset + ntohs(iph->tot_len) - ihl;
-       /* Point into the IP datagram 'data' part. */
-       ptr = ((unsigned char *) (skb + 1)) + dev->hard_header_len + ihl;
-       /* Is this the final fragment? */
-       if ((flags & IP_MF) == 0) 
-               qp->len = end;
-       /*
-        * Find out which fragments are in front and at the back of us
-        * in the chain of fragments so far.  We must know where to put
-        * this fragment, right?
-        */
-       prev = NULL;
-       for(next = qp->fragments; next != NULL; next = next->next) 
-       {
-               if (next->offset > offset) 
-                       break;  /* bingo! */
-               prev = next;
-       }       
-       /*
-        * We found where to put this one.
-        * Check for overlap with preceeding fragment, and, if needed,
-        * align things so that any overlaps are eliminated.
-        */
-       if (prev != NULL && offset < prev->end) 
-       {
-               i = prev->end - offset;
-               offset += i;    /* ptr into datagram */
-               ptr += i;       /* ptr into fragment data */
-               DPRINTF((DBG_IP, "IP: defrag: fixed low overlap %d bytes\n", i));
-       }       
-       /*
-        * Look for overlap with succeeding segments.
-        * If we can merge fragments, do it.
+       qp = ip_find(iph);
+       /* Is this a non-fragmented datagram? */
+       offset = ntohs(iph->frag_off);
+       flags = offset & ~IP_OFFSET;
+       offset &= IP_OFFSET;
+       if (((flags & IP_MF) == 0) && (offset == 0)) 
+       {
+               if (qp != NULL) 
+                       ip_free(qp);    /* Huh? How could this exist?? */
+               return(skb);
+       }
+       offset <<= 3;           /* offset is in 8-byte chunks */
+       /*
+        * If the queue already existed, keep restarting its timer as long
+        * as we still are receiving fragments.  Otherwise, create a fresh
+        * queue entry.
+        */
+       if (qp != NULL) 
+       {
+               del_timer(&qp->timer);
+               qp->timer.expires = IP_FRAG_TIME;       /* about 30 seconds     */
+               qp->timer.data = (unsigned long) qp;    /* pointer to queue     */
+               qp->timer.function = ip_expire;         /* expire function      */
+               add_timer(&qp->timer);
+       } 
+       else 
+       {
+               if ((qp = ip_create(skb, iph, dev)) == NULL) 
+                       return(NULL);
+       }
+       /* Determine the position of this fragment. */
+       ihl = (iph->ihl * sizeof(unsigned long));
+       end = offset + ntohs(iph->tot_len) - ihl;
+       /* Point into the IP datagram 'data' part. */
+       ptr = ((unsigned char *) (skb + 1)) + dev->hard_header_len + ihl;
+       /* Is this the final fragment? */
+       if ((flags & IP_MF) == 0) 
+               qp->len = end;
+       /*
+        * Find out which fragments are in front and at the back of us
+        * in the chain of fragments so far.  We must know where to put
+        * this fragment, right?
+        */
+       prev = NULL;
+       for(next = qp->fragments; next != NULL; next = next->next) 
+       {
+               if (next->offset > offset) 
+                       break;  /* bingo! */
+               prev = next;
+       }       
+       /*
+        * We found where to put this one.
+        * Check for overlap with preceeding fragment, and, if needed,
+        * align things so that any overlaps are eliminated.
+        */
+       if (prev != NULL && offset < prev->end) 
+       {
+               i = prev->end - offset;
+               offset += i;    /* ptr into datagram */
+               ptr += i;       /* ptr into fragment data */
+               DPRINTF((DBG_IP, "IP: defrag: fixed low overlap %d bytes\n", i));
+       }       
+       /*
+        * Look for overlap with succeeding segments.
+        * If we can merge fragments, do it.
         */
    
-       for(; next != NULL; next = tfp) 
-       {
-               tfp = next->next;
-               if (next->offset >= end) 
-                       break;          /* no overlaps at all */
-               i = end - next->offset;                 /* overlap is 'i' bytes */
-               next->len -= i;                         /* so reduce size of    */
-               next->offset += i;                      /* next fragment        */
-               next->ptr += i;
-               
-               /* If we get a frag size of <= 0, remove it. */
-               if (next->len <= 0) 
-               {
-                       DPRINTF((DBG_IP, "IP: defrag: removing frag 0x%X (len %d)\n",
-                                                       next, next->len));
-                       if (next->prev != NULL) 
-                               next->prev->next = next->next;
-                       else 
-                               qp->fragments = next->next;
-               
-                       if (tfp->next != NULL) 
-                               next->next->prev = next->prev;
-                       
-                       kfree_s(next, sizeof(struct ipfrag));
-               }
-               DPRINTF((DBG_IP, "IP: defrag: fixed high overlap %d bytes\n", i));
-       }
-       /* Insert this fragment in the chain of fragments. */
-       tfp = NULL;
-       tfp = ip_frag_create(offset, end, skb, ptr);
-       tfp->prev = prev;
-       tfp->next = next;
-       if (prev != NULL) 
-               prev->next = tfp;
+       for(; next != NULL; next = tfp) 
+       {
+               tfp = next->next;
+               if (next->offset >= end) 
+                       break;          /* no overlaps at all */
+               i = end - next->offset;                 /* overlap is 'i' bytes */
+               next->len -= i;                         /* so reduce size of    */
+               next->offset += i;                      /* next fragment        */
+               next->ptr += i;
+               
+               /* If we get a frag size of <= 0, remove it. */
+               if (next->len <= 0) 
+               {
+                       DPRINTF((DBG_IP, "IP: defrag: removing frag 0x%X (len %d)\n",
+                                                       next, next->len));
+                       if (next->prev != NULL) 
+                               next->prev->next = next->next;
+                       else 
+                               qp->fragments = next->next;
+               
+                       if (tfp->next != NULL) 
+                               next->next->prev = next->prev;
+                       
+                       kfree_s(next, sizeof(struct ipfrag));
+               }
+               DPRINTF((DBG_IP, "IP: defrag: fixed high overlap %d bytes\n", i));
+       }
+       /* Insert this fragment in the chain of fragments. */
+       tfp = NULL;
+       tfp = ip_frag_create(offset, end, skb, ptr);
+       tfp->prev = prev;
+       tfp->next = next;
+       if (prev != NULL) 
+               prev->next = tfp;
        else 
                qp->fragments = tfp;
    
-       if (next != NULL) 
-               next->prev = tfp;
-       /*
-        * OK, so we inserted this new fragment into the chain.
-        * Check if we now have a full IP datagram which we can
-        * bump up to the IP layer...
-        */
+       if (next != NULL) 
+               next->prev = tfp;
+       /*
+        * OK, so we inserted this new fragment into the chain.
+        * Check if we now have a full IP datagram which we can
+        * bump up to the IP layer...
+        */
    
-       if (ip_done(qp)) 
-       {
-               skb2 = ip_glue(qp);             /* glue together the fragments */
-               return(skb2);
-       }
-       return(NULL);
+       if (ip_done(qp)) 
+       {
+               skb2 = ip_glue(qp);             /* glue together the fragments */
+               return(skb2);
+       }
+       return(NULL);
  }
  
  
@@ -1091,398 +953,363 @@ static struct sk_buff *ip_defrag(struct iphdr *iph, struct sk_buff *skb, struct
   * ip_queue_xmit().  Note that this is recursion, and bad things will happen
   * if this function causes a loop...
   */
  void ip_fragment(struct sock *sk, struct sk_buff *skb, struct device *dev, int is_frag)
  {
-       struct iphdr *iph;
-       unsigned char *raw;
-       unsigned char *ptr;
-       struct sk_buff *skb2;
-       int left, mtu, hlen, len;
-       int offset;
-       /* Point into the IP datagram header. */
-       raw = (unsigned char *) (skb + 1);
-       iph = (struct iphdr *) (raw + dev->hard_header_len);
-       
-       /* Setup starting values. */
-       hlen = (iph->ihl * sizeof(unsigned long));
-       left = ntohs(iph->tot_len) - hlen;
-       hlen += dev->hard_header_len;
-       mtu = (dev->mtu - hlen);
-       ptr = (raw + hlen);
-       
-       DPRINTF((DBG_IP, "IP: Fragmentation Desired\n"));
-       DPRINTF((DBG_IP, "    DEV=%s, MTU=%d, LEN=%d SRC=%s",
-               dev->name, dev->mtu, left, in_ntoa(iph->saddr)));
-       DPRINTF((DBG_IP, " DST=%s\n", in_ntoa(iph->daddr)));
-       /* Check for any "DF" flag. */
-       if (ntohs(iph->frag_off) & IP_DF) 
-       {
-               DPRINTF((DBG_IP, "IP: Fragmentation Desired, but DF set !\n"));
-               DPRINTF((DBG_IP, "    DEV=%s, MTU=%d, LEN=%d SRC=%s",
-                       dev->name, dev->mtu, left, in_ntoa(iph->saddr)));
-               DPRINTF((DBG_IP, " DST=%s\n", in_ntoa(iph->daddr)));
-               /*
-                * FIXME:
-                * We should send an ICMP warning message here!
-                */
-                
-               icmp_send(skb,ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, dev); 
-               return;
-       }
-       
-       /*
-        *      If it won't fit then error it. 
-        *      NOTE: We don't send a ICMP here. Suppose the ICMP didn't fit.... 
-        */
-          
-       if(mtu<8)
-       {
-               return;
-       }
-       /* Fragment the datagram. */
+       struct iphdr *iph;
+       unsigned char *raw;
+       unsigned char *ptr;
+       struct sk_buff *skb2;
+       int left, mtu, hlen, len;
+       int offset;
+       /* Point into the IP datagram header. */
+       raw = (unsigned char *) (skb + 1);
+       iph = (struct iphdr *) (raw + dev->hard_header_len);
+       
+       /* Setup starting values. */
+       hlen = (iph->ihl * sizeof(unsigned long));
+       left = ntohs(iph->tot_len) - hlen;
+       hlen += dev->hard_header_len;
+       mtu = (dev->mtu - hlen);
+       ptr = (raw + hlen);
+       
+       DPRINTF((DBG_IP, "IP: Fragmentation Desired\n"));
+       DPRINTF((DBG_IP, "    DEV=%s, MTU=%d, LEN=%d SRC=%s",
+               dev->name, dev->mtu, left, in_ntoa(iph->saddr)));
+       DPRINTF((DBG_IP, " DST=%s\n", in_ntoa(iph->daddr)));
+       /* Check for any "DF" flag. */
+       if (ntohs(iph->frag_off) & IP_DF) 
+       {
+               DPRINTF((DBG_IP, "IP: Fragmentation Desired, but DF set !\n"));
+               DPRINTF((DBG_IP, "    DEV=%s, MTU=%d, LEN=%d SRC=%s",
+                       dev->name, dev->mtu, left, in_ntoa(iph->saddr)));
+               DPRINTF((DBG_IP, " DST=%s\n", in_ntoa(iph->daddr)));
+               /*
+                * FIXME:
+                * We should send an ICMP warning message here!
+                */
+                
+               icmp_send(skb,ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, dev); 
+               return;
+       }
+       /* Fragment the datagram. */
        if (is_frag & 2)
          offset = (ntohs(iph->frag_off) & 0x1fff) << 3;
        else
-         offset = 0;
-       while(left > 0) 
-       {
-               len = left;
-               if (len+8 > mtu) 
-                       len = (dev->mtu - hlen - 8);
-               if ((left - len) >= 8) 
-               {
-                       len /= 8;
-                       len *= 8;
-               }
-               DPRINTF((DBG_IP,"IP: frag: creating fragment of %d bytes (%d total)\n",
-                                                       len, len + hlen));
-               /* Allocate buffer. */
-               if ((skb2 = alloc_skb(sizeof(struct sk_buff) + len + hlen,GFP_KERNEL)) == NULL) 
-               {
-                       printk("IP: frag: no memory for new fragment!\n");
-                       return;
-               }
-               skb2->arp = skb->arp;
-               skb2->free = skb->free;
-               skb2->len = len + hlen;
-               skb2->h.raw=(char *)(skb2+1);
-               if (sk) 
-                       sk->wmem_alloc += skb2->mem_len;
-               /* Copy the packet header into the new buffer. */
-               memcpy(skb2->h.raw, raw, hlen);
-               /* Copy a block of the IP datagram. */
-               memcpy(skb2->h.raw + hlen, ptr, len);
-               left -= len;
+         offset = 0;
+       while(left > 0) 
+       {
+               len = left;
+               if (len+8 > mtu) 
+                       len = (dev->mtu - hlen - 8);
+               if ((left - len) >= 8) 
+               {
+                       len /= 8;
+                       len *= 8;
+               }
+               DPRINTF((DBG_IP,"IP: frag: creating fragment of %d bytes (%d total)\n",
+                                                       len, len + hlen));
+               /* Allocate buffer. */
+               if ((skb2 = alloc_skb(sizeof(struct sk_buff) + len + hlen,GFP_KERNEL)) == NULL) 
+               {
+                       printk("IP: frag: no memory for new fragment!\n");
+                       return;
+               }
+               skb2->arp = skb->arp;
+               skb2->free = skb->free;
+               skb2->len = len + hlen;
+               skb2->h.raw=(char *)(skb2+1);
+               if (sk) 
+                       sk->wmem_alloc += skb2->mem_len;
+               /* Copy the packet header into the new buffer. */
+               memcpy(skb2->h.raw, raw, hlen);
+               /* Copy a block of the IP datagram. */
+               memcpy(skb2->h.raw + hlen, ptr, len);
+               left -= len;
 
                skb2->h.raw+=dev->hard_header_len; 
-               /* Fill in the new header fields. */
-               iph = (struct iphdr *)(skb2->h.raw/*+dev->hard_header_len*/);
-               iph->frag_off = htons((offset >> 3));
-               /* Added AC : If we are fragmenting a fragment thats not the
-                  last fragment then keep MF on each bit */
-               if (left > 0 || (is_frag & 1)) 
-                       iph->frag_off |= htons(IP_MF);
-               ptr += len;
-               offset += len;
+               /* Fill in the new header fields. */
+               iph = (struct iphdr *)(skb2->h.raw/*+dev->hard_header_len*/);
+               iph->frag_off = htons((offset >> 3));
+               /* Added AC : If we are fragmenting a fragment thats not the
+                  last fragment then keep MF on each bit */
+               if (left > 0 || (is_frag & 1)) 
+                       iph->frag_off |= htons(IP_MF);
+               ptr += len;
+               offset += len;
 /*             printk("Queue frag\n");*/
  
-               /* Put this fragment into the sending queue. */
-               ip_queue_xmit(sk, dev, skb2, 1);
+               /* Put this fragment into the sending queue. */
+               ip_queue_xmit(sk, dev, skb2, 1);
 /*             printk("Queued\n");*/
-       }
+       }
  }
  
 
 
 #ifdef CONFIG_IP_FORWARD
 
-/* 
- *     Forward an IP datagram to its next destination. 
- */
-static void ip_forward(struct sk_buff *skb, struct device *dev, int is_frag)
+/* Forward an IP datagram to its next destination. */
+static void
+ip_forward(struct sk_buff *skb, struct device *dev, int is_frag)
 {
-       struct device *dev2;
-       struct iphdr *iph;
-       struct sk_buff *skb2;
-       struct rtable *rt;
-       unsigned char *ptr;
-       unsigned long raddr;
+  struct device *dev2;
+  struct iphdr *iph;
+  struct sk_buff *skb2;
+  struct rtable *rt;
+  unsigned char *ptr;
+  unsigned long raddr;
 
-       /*
-        * Only forward packets that were fired at us when we are in promiscuous
-        * mode. In standard mode we rely on the driver to filter for us.
-        */
+  /*
+   * Only forward packets that were fired at us when we are in promiscuous
+   * mode. In standard mode we rely on the driver to filter for us.
+   */
    
-       if(dev->flags&IFF_PROMISC)
-       {
-               if(memcmp((char *)&skb[1],dev->dev_addr,dev->addr_len))
-                       return;
-       }
+  if(dev->flags&IFF_PROMISC)
+  {
+       if(memcmp((char *)&skb[1],dev->dev_addr,dev->addr_len))
+               return;
+  }
   
-       /*
-        * According to the RFC, we must first decrease the TTL field. If
-        * that reaches zero, we must reply an ICMP control message telling
-        * that the packet's lifetime expired. RFC791 page 30.
-        */
-       iph = skb->h.iph;
-       iph->ttl--;
-       if (iph->ttl <= 0) 
-       {
-               DPRINTF((DBG_IP, "\nIP: *** datagram expired: TTL=0 (ignored) ***\n"));
-               DPRINTF((DBG_IP, "    SRC = %s   ", in_ntoa(iph->saddr)));
-               DPRINTF((DBG_IP, "    DST = %s (ignored)\n", in_ntoa(iph->daddr)));
-       
-               /* Tell the sender its packet died... */
-               icmp_send(skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, dev);
-               return;
-       }
+  /*
+   * According to the RFC, we must first decrease the TTL field. If
+   * that reaches zero, we must reply an ICMP control message telling
+   * that the packet's lifetime expired.
+   */
+  iph = skb->h.iph;
+  iph->ttl--;
+  if (iph->ttl <= 0) {
+       DPRINTF((DBG_IP, "\nIP: *** datagram expired: TTL=0 (ignored) ***\n"));
+       DPRINTF((DBG_IP, "    SRC = %s   ", in_ntoa(iph->saddr)));
+       DPRINTF((DBG_IP, "    DST = %s (ignored)\n", in_ntoa(iph->daddr)));
 
-       /* Re-compute the IP header checksum. */
-       ip_send_check(iph);
+       /* Tell the sender its packet died... */
+       icmp_send(skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, dev);
+       return;
+  }
 
-       /*
-        * OK, the packet is still valid.  Fetch its destination address,
-        * and give it to the IP sender for further processing.
-        */
-       rt = rt_route(iph->daddr, NULL);
-       if (rt == NULL) 
-       {
-               DPRINTF((DBG_IP, "\nIP: *** routing (phase I) failed ***\n"));
+  /* Re-compute the IP header checksum. */
+  ip_send_check(iph);
 
-               /* Tell the sender its packet cannot be delivered... */
-               icmp_send(skb, ICMP_DEST_UNREACH, ICMP_NET_UNREACH, dev);
-               return;
-       }
+  /*
+   * OK, the packet is still valid.  Fetch its destination address,
+   * and give it to the IP sender for further processing.
+   */
+  rt = rt_route(iph->daddr, NULL);
+  if (rt == NULL) {
+       DPRINTF((DBG_IP, "\nIP: *** routing (phase I) failed ***\n"));
 
+       /* Tell the sender its packet cannot be delivered... */
+       icmp_send(skb, ICMP_DEST_UNREACH, ICMP_NET_UNREACH, dev);
+       return;
+  }
 
-       /*
-        * Gosh.  Not only is the packet valid; we even know how to
-        * forward it onto its final destination.  Can we say this
-        * is being plain lucky?
-        * If the router told us that there is no GW, use the dest.
-        * IP address itself- we seem to be connected directly...
-        */
-       raddr = rt->rt_gateway;
-       if (raddr != 0) 
-       {
-               rt = rt_route(raddr, NULL);
-               if (rt == NULL) 
-               {
-                       DPRINTF((DBG_IP, "\nIP: *** routing (phase II) failed ***\n"));
 
-                       /* Tell the sender its packet cannot be delivered... */
-                       icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, dev);
-                       return;
-               }
-               if (rt->rt_gateway != 0) 
-                       raddr = rt->rt_gateway;
-       } 
-       else 
-               raddr = iph->daddr;
-       dev2 = rt->rt_dev;
+  /*
+   * Gosh.  Not only is the packet valid; we even know how to
+   * forward it onto its final destination.  Can we say this
+   * is being plain lucky?
+   * If the router told us that there is no GW, use the dest.
+   * IP address itself- we seem to be connected directly...
+   */
+  raddr = rt->rt_gateway;
+  if (raddr != 0) {
+       rt = rt_route(raddr, NULL);
+       if (rt == NULL) {
+               DPRINTF((DBG_IP, "\nIP: *** routing (phase II) failed ***\n"));
 
-       /*
-        * Never forward out on the same interface, its not allowed, its often not pretty either (except for on
-        * source routing)
-        */
-       if (dev == dev2)
+               /* Tell the sender its packet cannot be delivered... */
+               icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, dev);
                return;
-       /*
-        * We now allocate a new buffer, and copy the datagram into it.
-        * If the indicated interface is up and running, kick it.
-        */
-       DPRINTF((DBG_IP, "\nIP: *** fwd %s -> ", in_ntoa(iph->saddr)));
-       DPRINTF((DBG_IP, "%s (via %s), LEN=%d\n",
+       }
+       if (rt->rt_gateway != 0) raddr = rt->rt_gateway;
+  } else raddr = iph->daddr;
+  dev2 = rt->rt_dev;
+
+
+  if (dev == dev2)
+       return;
+  /*
+   * We now allocate a new buffer, and copy the datagram into it.
+   * If the indicated interface is up and running, kick it.
+   */
+  DPRINTF((DBG_IP, "\nIP: *** fwd %s -> ", in_ntoa(iph->saddr)));
+  DPRINTF((DBG_IP, "%s (via %s), LEN=%d\n",
                        in_ntoa(raddr), dev2->name, skb->len));
 
-       if (dev2->flags & IFF_UP) 
-       {
-               skb2 = (struct sk_buff *) alloc_skb(sizeof(struct sk_buff) +
+  if (dev2->flags & IFF_UP) {
+       skb2 = (struct sk_buff *) alloc_skb(sizeof(struct sk_buff) +
                       dev2->hard_header_len + skb->len, GFP_ATOMIC);
-               if (skb2 == NULL) 
-               {
-                       printk("\nIP: No memory available for IP forward\n");
-                       return;
-               }
-               ptr = (unsigned char *)(skb2 + 1);
-               skb2->sk = NULL;
-               skb2->free = 1;
-               skb2->len = skb->len + dev2->hard_header_len;
-               skb2->next = NULL;
-               skb2->h.raw = ptr;
-
-               /* Copy the packet data into the new buffer. */
-               memcpy(ptr + dev2->hard_header_len, skb->h.raw, skb->len);
+       if (skb2 == NULL) {
+               printk("\nIP: No memory available for IP forward\n");
+               return;
+       }
+       ptr = (unsigned char *)(skb2 + 1);
+       skb2->sk = NULL;
+       skb2->free = 1;
+       skb2->len = skb->len + dev2->hard_header_len;
+       skb2->mem_addr = skb2;
+       skb2->mem_len = sizeof(struct sk_buff) + skb2->len;
+       skb2->next = NULL;
+       skb2->h.raw = ptr;
+
+       /* Copy the packet data into the new buffer. */
+       memcpy(ptr + dev2->hard_header_len, skb->h.raw, skb->len);
                
-               /* Now build the MAC header. */
-               (void) ip_send(skb2, raddr, skb->len, dev2, dev2->pa_addr);
+       /* Now build the MAC header. */
+       (void) ip_send(skb2, raddr, skb->len, dev2, dev2->pa_addr);
 
-               if(skb2->len > dev2->mtu)
-               {
-                       ip_fragment(NULL,skb2,dev2, is_frag);
-                       kfree_skb(skb2,FREE_WRITE);
-               }
-               else
-                       dev2->queue_xmit(skb2, dev2, SOPRI_NORMAL);
+       if(skb2->len > dev2->mtu)
+       {
+               ip_fragment(NULL,skb2,dev2, is_frag);
+               kfree_skb(skb2,FREE_WRITE);
        }
+       else
+               dev2->queue_xmit(skb2, dev2, SOPRI_NORMAL);
+  }
 }
 
 
 #endif
 
-
-/*
- *     This function receives all incoming IP datagrams. 
- */
-int ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
+/* This function receives all incoming IP datagrams. */
+int
+ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
 {
-       struct iphdr *iph = skb->h.iph;
-       unsigned char hash;
-       unsigned char flag = 0;
-       unsigned char opts_p = 0;       /* Set iff the packet has options. */
-       struct inet_protocol *ipprot;
-       struct options *opt=NULL;
-
-       int brd;
-       int is_frag=0;
-
-       DPRINTF((DBG_IP, "<<\n"));
-
-       /* Is the datagram acceptable? */
-       if (skb->len<sizeof(struct iphdr) || iph->ihl<5 || iph->version != 4 || ip_fast_csum((unsigned char *)iph, iph->ihl) !=0) 
-       {
-               DPRINTF((DBG_IP, "\nIP: *** datagram error ***\n"));
-               DPRINTF((DBG_IP, "    SRC = %s   ", in_ntoa(iph->saddr)));
-               DPRINTF((DBG_IP, "    DST = %s (ignored)\n", in_ntoa(iph->daddr)));
-               skb->sk = NULL;
-               kfree_skb(skb, FREE_WRITE);
-               return(0);
-       }
-
-       if (iph->ihl != 5) 
-       {       /* Fast path for the typical optionless IP packet. */
-#ifdef IP_DEBUG        
-               ip_print(iph);          /* Bogus, only for debugging. */
-#endif
-               if (do_options(iph, &opt,dev) != 0)
-               {
-                       if(opt)
-                               kfree(opt);
-                       return 0;
-               }
-/*             skb->ip_options=opt_ptr;*/
-               kfree(opt);
-               opt = NULL;
-               opts_p = 0/*1*/;
-       }
-
-       if (iph->frag_off & 0x0020)
-               is_frag|=1;
-       if (ntohs(iph->frag_off) & 0x1fff)
-               is_frag|=2;
-       
-       /* Do any IP forwarding required.  chk_addr() is expensive -- avoid it someday. */
-       if ((brd = chk_addr(iph->daddr)) == 0) 
-       {
+  struct iphdr *iph = skb->h.iph;
+  unsigned char hash;
+  unsigned char flag = 0;
+  unsigned char opts_p = 0;    /* Set iff the packet has options. */
+  struct inet_protocol *ipprot;
+  static struct options opt; /* since we don't use these yet, and they
+                               take up stack space. */
+  int brd;
+  int is_frag=0;
+
+  DPRINTF((DBG_IP, "<<\n"));
+
+  /* Is the datagram acceptable? */
+  if (skb->len<sizeof(struct iphdr) || iph->ihl<5 || iph->version != 4 || ip_fast_csum((unsigned char *)iph, iph->ihl) !=0) {
+       DPRINTF((DBG_IP, "\nIP: *** datagram error ***\n"));
+       DPRINTF((DBG_IP, "    SRC = %s   ", in_ntoa(iph->saddr)));
+       DPRINTF((DBG_IP, "    DST = %s (ignored)\n", in_ntoa(iph->daddr)));
+       skb->sk = NULL;
+       kfree_skb(skb, FREE_WRITE);
+       return(0);
+  }
+  
+  if (iph->ihl != 5) {         /* Fast path for the typical optionless IP packet. */
+      ip_print(iph);           /* Bogus, only for debugging. */
+      memset((char *) &opt, 0, sizeof(opt));
+      if (do_options(iph, &opt) != 0)
+         return 0;
+      opts_p = 1;
+  }
+
+  if (iph->frag_off & 0x0020)
+       is_frag|=1;
+  if (ntohs(iph->frag_off) & 0x1fff)
+       is_frag|=2;
+       
+  /* Do any IP forwarding required.  chk_addr() is expensive -- avoid it someday. */
+  if ((brd = chk_addr(iph->daddr)) == 0) {
 #ifdef CONFIG_IP_FORWARD
-               ip_forward(skb, dev, is_frag);
+       ip_forward(skb, dev, is_frag);
 #else
-               printk("Machine %x tried to use us as a forwarder to %x but we have forwarding disabled!\n",
+       printk("Machine %x tried to use us as a forwarder to %x but we have forwarding disabled!\n",
                        iph->saddr,iph->daddr);
 #endif                 
-               skb->sk = NULL;
-               kfree_skb(skb, FREE_WRITE);
-               return(0);
-       }
+       skb->sk = NULL;
+       kfree_skb(skb, FREE_WRITE);
+       return(0);
+  }
 
   /*
    * Reassemble IP fragments. 
    */
 
-       if(is_frag)
-       {
+  if(is_frag)
+  {
 #ifdef CONFIG_IP_DEFRAG
-               skb=ip_defrag(iph,skb,dev);
-               if(skb==NULL)
-               {
-                       return 0;
-               }
-               iph=skb->h.iph;
+        skb=ip_defrag(iph,skb,dev);
+        if(skb==NULL)
+        {
+               return 0;
+        }
+        iph=skb->h.iph;
 #else
-               printk("\nIP: *** datagram fragmentation not yet implemented ***\n");
-               printk("    SRC = %s   ", in_ntoa(iph->saddr));
-               printk("    DST = %s (ignored)\n", in_ntoa(iph->daddr));
-               icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, dev);
-               skb->sk = NULL;
-               kfree_skb(skb, FREE_WRITE);
-               return(0);
+       printk("\nIP: *** datagram fragmentation not yet implemented ***\n");
+       printk("    SRC = %s   ", in_ntoa(iph->saddr));
+       printk("    DST = %s (ignored)\n", in_ntoa(iph->daddr));
+       icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, dev);
+       skb->sk = NULL;
+       kfree_skb(skb, FREE_WRITE);
+       return(0);
 #endif
-       }
+  }
 
 
-       /* Point into the IP datagram, just past the header. */
-       skb->ip_hdr = iph;
-       skb->h.raw += iph->ihl*4;
-       hash = iph->protocol & (MAX_INET_PROTOS -1);
-       
-       /* Find someone to deliver it too */
-       
-       for (ipprot = (struct inet_protocol *)inet_protos[hash];
-                       ipprot != NULL;
-                       ipprot=(struct inet_protocol *)ipprot->next)
-       {
-               struct sk_buff *skb2;
 
-                       if (ipprot->protocol != iph->protocol) 
-                               continue;
-                       DPRINTF((DBG_IP, "Using protocol = %X:\n", ipprot));
-                       print_ipprot(ipprot);
+  if(brd==IS_INVBCAST)
+  {
+/*     printk("Invalid broadcast address from %x [target %x] (Probably they have a wrong netmask)\n",
+               iph->saddr,iph->daddr);*/
+       skb->sk=NULL;
+       kfree_skb(skb,FREE_WRITE);
+       return(0);
+  }
+  
+  /* Point into the IP datagram, just past the header. */
+  skb->h.raw += iph->ihl*4;
+  hash = iph->protocol & (MAX_INET_PROTOS -1);
+  for (ipprot = (struct inet_protocol *)inet_protos[hash];
+       ipprot != NULL;
+       ipprot=(struct inet_protocol *)ipprot->next)
+    {
+       struct sk_buff *skb2;
+
+       if (ipprot->protocol != iph->protocol) continue;
+       DPRINTF((DBG_IP, "Using protocol = %X:\n", ipprot));
+       print_ipprot(ipprot);
 
        /*
        * See if we need to make a copy of it.  This will
        * only be set if more than one protocol wants it. 
        * and then not for the last one.
        */
-               if (ipprot->copy) 
-               {
-                       skb2 = alloc_skb(skb->mem_len, GFP_ATOMIC);
-                       if (skb2 == NULL) 
-                               continue;
-                       memcpy(skb2, skb, skb->mem_len);
-                       skb2->mem_addr = skb2;
-                       skb2->h.raw = (unsigned char *)(
+       if (ipprot->copy) {
+               skb2 = alloc_skb(skb->mem_len, GFP_ATOMIC);
+               if (skb2 == NULL) 
+                       continue;
+               memcpy(skb2, skb, skb->mem_len);
+               skb2->mem_addr = skb2;
+               skb2->h.raw = (unsigned char *)(
                                (unsigned long)skb2 +
                                (unsigned long) skb->h.raw -
                                (unsigned long)skb);
-                       skb2->free=1;
-               } 
-               else 
-               {
-                       skb2 = skb;
-               }
-               flag = 1;
+               skb2->free=1;
+       } else {
+               skb2 = skb;
+       }
+       flag = 1;
 
-               /*
-        * Pass on the datagram to each protocol that wants it,
-        * based on the datagram protocol.  We should really
-        * check the protocol handler's return values here...
-        */
-               ipprot->handler(skb2, dev, opts_p ? opt : 0, iph->daddr,
+       /*
+       * Pass on the datagram to each protocol that wants it,
+       * based on the datagram protocol.  We should really
+       * check the protocol handler's return values here...
+       */
+       ipprot->handler(skb2, dev, opts_p ? &opt : 0, iph->daddr,
                        (ntohs(iph->tot_len) - (iph->ihl * 4)),
                        iph->saddr, 0, ipprot);
 
-       }
+  }
 
   /*
    * All protocols checked.
@@ -1490,15 +1317,14 @@ int ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
    * causes (proven, grin) ARP storms and a leakage of memory (i.e. all
    * ICMP reply messages get queued up for transmission...)
    */
-       if (!flag) 
-       {
-               if (brd != IS_BROADCAST)
-                       icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, dev);
-               skb->sk = NULL;
-               kfree_skb(skb, FREE_WRITE);
-       }
+  if (!flag) {
+       if (brd != IS_BROADCAST)
+               icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, dev);
+       skb->sk = NULL;
+       kfree_skb(skb, FREE_WRITE);
+  }
 
-       return(0);
+  return(0);
 }
 
 
@@ -1509,174 +1335,148 @@ int ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
  * This routine also needs to put in the total length, and
  * compute the checksum.
  */
-void ip_queue_xmit(struct sock *sk, struct device *dev, 
+void
+ip_queue_xmit(struct sock *sk, struct device *dev, 
              struct sk_buff *skb, int free)
 {
-       struct iphdr *iph;
-       unsigned char *ptr;
-
-       if (sk == NULL)
-               free = 1;
-       if (dev == NULL) 
-       {
-               printk("IP: ip_queue_xmit dev = NULL\n");
-               return;
-       }
-       IS_SKB(skb);
-       skb->free = free;
-       skb->dev = dev;
-       skb->when = jiffies;
+  struct iphdr *iph;
+  unsigned char *ptr;
+
+  if (sk == NULL) free = 1;
+  if (dev == NULL) {
+       printk("IP: ip_queue_xmit dev = NULL\n");
+       return;
+  }
+  IS_SKB(skb);
+  skb->free = free;
+  skb->dev = dev;
+  skb->when = jiffies;
   
-       DPRINTF((DBG_IP, ">>\n"));
-       ptr = (unsigned char *)(skb + 1);
-       ptr += dev->hard_header_len;
-       iph = (struct iphdr *)ptr;
-       iph->tot_len = ntohs(skb->len-dev->hard_header_len);
-       
-       if(skb->len > dev->mtu)
-       {
-/*             printk("Fragment!\n");*/
-               ip_fragment(sk,skb,dev,0);
-               IS_SKB(skb);
-               kfree_skb(skb,FREE_WRITE);
-               return;
-       }
+  DPRINTF((DBG_IP, ">>\n"));
+  ptr = (unsigned char *)(skb + 1);
+  ptr += dev->hard_header_len;
+  iph = (struct iphdr *)ptr;
+  iph->tot_len = ntohs(skb->len-dev->hard_header_len);
+
+  if(skb->len > dev->mtu)
+  {
+/*     printk("Fragment!\n");*/
+       ip_fragment(sk,skb,dev,0);
+       IS_SKB(skb);
+       kfree_skb(skb,FREE_WRITE);
+       return;
+  }
   
-       ip_send_check(iph);
-#ifdef IP_DEBUG
-       ip_print(iph);
-#endif
-       skb->next = NULL;
-
-       /* See if this is the one trashing our queue. Ross? */
-       skb->magic = 1;
-       if (!free) 
-       {
-               skb->link3 = NULL;
-               sk->packets_out++;
-               cli();
-               if (sk->send_head == NULL) 
-               {
+  ip_send_check(iph);
+  ip_print(iph);
+  skb->next = NULL;
+
+  /* See if this is the one trashing our queue. Ross? */
+  skb->magic = 1;
+  if (!free) {
+       skb->link3 = NULL;
+       sk->packets_out++;
+       cli();
+       if (sk->send_head == NULL) {
+               sk->send_tail = skb;
+               sk->send_head = skb;
+       } else {
+               /* See if we've got a problem. */
+               if (sk->send_tail == NULL) {
+                       printk("IP: ***bug sk->send_tail == NULL != sk->send_head\n");
+                       sort_send(sk);
+               } else {
+                       sk->send_tail->link3 = skb;
                        sk->send_tail = skb;
-                       sk->send_head = skb;
-               } 
-               else 
-               {
-                       /* See if we've got a problem. */
-                       if (sk->send_tail == NULL) 
-                       {
-                               printk("IP: ***bug sk->send_tail == NULL != sk->send_head\n");
-                               sort_send(sk);
-                       } 
-                       else 
-                       {
-                               sk->send_tail->link3 = skb;
-                               sk->send_tail = skb;
-                       }
                }
-               sti();
-               reset_timer(sk, TIME_WRITE,
-               backoff(sk->backoff) * (2 * sk->mdev + sk->rtt));
-       } 
-       else 
-       {
-               skb->sk = sk;
        }
-
-       /* If the indicated interface is up and running, kick it. */
-       if (dev->flags & IFF_UP) 
-       {
-               if (sk != NULL) 
-               {
-                       dev->queue_xmit(skb, dev, sk->priority);
-               } 
-               else 
-               {
-                       dev->queue_xmit(skb, dev, SOPRI_NORMAL);
-               }
+       sti();
+       reset_timer(sk, TIME_WRITE,
+               backoff(sk->backoff) * (2 * sk->mdev + sk->rtt));
+  } else {
+       skb->sk = sk;
+  }
+
+  /* If the indicated interface is up and running, kick it. */
+  if (dev->flags & IFF_UP) {
+       if (sk != NULL) {
+               dev->queue_xmit(skb, dev, sk->priority);
        } 
-       else 
-       {
-               if (free) kfree_skb(skb, FREE_WRITE);
+       else {
+               dev->queue_xmit(skb, dev, SOPRI_NORMAL);
        }
+  } else {
+       if (free) kfree_skb(skb, FREE_WRITE);
+  }
 }
 
 
-void ip_retransmit(struct sock *sk, int all)
+void
+ip_retransmit(struct sock *sk, int all)
 {
-       struct sk_buff * skb;
-       struct proto *prot;
-       struct device *dev;
-
-       prot = sk->prot;
-       skb = sk->send_head;
-       while (skb != NULL) 
+  struct sk_buff * skb;
+  struct proto *prot;
+  struct device *dev;
+
+  prot = sk->prot;
+  skb = sk->send_head;
+  while (skb != NULL) {
+       dev = skb->dev;
+       /* I know this can't happen but as it does.. */
+       if(dev==NULL)
        {
-               dev = skb->dev;
-               /* I know this can't happen but as it does.. */
-               if(dev==NULL)
-               {
-                       printk("ip_retransmit: NULL device bug!\n");
-                       goto oops;
-               }
-       
-               IS_SKB(skb);
-       
-               /*
-                * The rebuild_header function sees if the ARP is done.
-                * If not it sends a new ARP request, and if so it builds
-                * the header.
-                */
-               cli();  /* We might get interrupted by an arp reply here and fill
-                          the frame in twice. Because of the technique used this
-                          would be a little sad */
-               if (!skb->arp) 
-               {
-                       if (dev->rebuild_header(skb+1, dev)) 
-                       {
-                               sti();  /* Failed to rebuild - next */
-                               if (!all) 
-                                       break;
-                               skb = (struct sk_buff *)skb->link3;
-                               continue;
-                       }
-               }
-               skb->arp = 1;
-               sti();
-               skb->when = jiffies;
+               printk("ip_retransmit: NULL device bug!\n");
+               goto oops;
+       }
+
+       IS_SKB(skb);
        
-               /* If the interface is (still) up and running, kick it. */
-               if (dev->flags & IFF_UP) 
-               {
-                       if (sk) 
-                               dev->queue_xmit(skb, dev, sk->priority);
+       /*
+        * The rebuild_header function sees if the ARP is done.
+        * If not it sends a new ARP request, and if so it builds
+        * the header.
+        */
+        cli(); /* We might get interrupted by an arp reply here and fill
+                  the frame in twice. Because of the technique used this
+                  would be a little sad */
+       if (!skb->arp) {
+               if (dev->rebuild_header(skb+1, dev)) {
+                       sti();  /* Failed to rebuild - next */
+                       if (!all) break;
+                       skb = (struct sk_buff *)skb->link3;
+                       continue;
                }
+       }
+       skb->arp = 1;
+       sti();
+       skb->when = jiffies;
 
-oops:          sk->retransmits++;
-               sk->prot->retransmits ++;
-               if (!all) 
-                       break;
-
-               /* This should cut it off before we send too many packets. */
-               if (sk->retransmits > sk->cong_window) 
-                       break;
-               skb = (struct sk_buff *)skb->link3;
+       /* If the interface is (still) up and running, kick it. */
+       if (dev->flags & IFF_UP) {
+               if (sk) dev->queue_xmit(skb, dev, sk->priority);
+       /*        else dev->queue_xmit(skb, dev, SOPRI_NORMAL ); CANNOT HAVE SK=NULL HERE */
        }
 
+oops:  sk->retransmits++;
+       sk->prot->retransmits ++;
+       if (!all) break;
+
+       /* This should cut it off before we send too many packets. */
+       if (sk->retransmits > sk->cong_window) break;
+       skb = (struct sk_buff *)skb->link3;
+  }
+
   /*
    * Increase the RTT time every time we retransmit. 
    * This will cause exponential back off on how hard we try to
    * get through again.  Once we get through, the rtt will settle
    * back down reasonably quickly.
    */
-       sk->backoff++;
-       reset_timer(sk, TIME_WRITE, backoff(sk->backoff) * (2 * sk->mdev + sk->rtt));
-}      
-
-/*
- *     Backoff function - the subject of much research 
- */
+  sk->backoff++;
+  reset_timer(sk, TIME_WRITE, backoff(sk->backoff) * (2 * sk->mdev + sk->rtt));
+}
 
+/* Backoff function - the subject of much research */
 int backoff(int n)
 {
        /* Use binary exponential up to retry #4, and quadratic after that
@@ -1704,73 +1504,3 @@ int backoff(int n)
        }
 }
 
-
-/*
- *     Socket option code for IP. This is the end of the line after any TCP,UDP etc options on
- *     an IP socket.
- */
-int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int optlen)
-{
-       int val,err;
-       
-       if (optval == NULL) 
-               return(-EINVAL);
-
-       err=verify_area(VERIFY_READ, optval, sizeof(int));
-       if(err)
-               return err;
-       
-       val = get_fs_long((unsigned long *)optval);
-
-       if(level!=SOL_IP)
-               return -EOPNOTSUPP;
-
-       switch(optname)
-       {
-               case IP_TOS:
-                       if(val<0||val>255)
-                               return -EINVAL;
-                       sk->ip_tos=val;
-                       return 0;
-               case IP_TTL:
-                       if(val<1||val<255)
-                               return -EINVAL;
-                       sk->ip_ttl=val;
-                       return 0;
-               /* IP_OPTIONS and friends go here eventually */
-               default:
-                       return(-ENOPROTOOPT);
-       }
-}
-
-int ip_getsockopt(struct sock *sk, int level, int optname, char *optval, int *optlen)
-{
-       int val,err;
-       
-       if(level!=SOL_IP)
-               return -EOPNOTSUPP;
-               
-       switch(optname)
-       {
-               case IP_TOS:
-                       val=sk->ip_tos;
-                       break;
-               case IP_TTL:
-                       val=sk->ip_ttl;
-                       break;
-               default:
-                       return(-ENOPROTOOPT);
-       }
-       err=verify_area(VERIFY_WRITE, optlen, sizeof(int));
-       if(err)
-               return err;
-       put_fs_long(sizeof(int),(unsigned long *) optlen);
-
-       err=verify_area(VERIFY_WRITE, optval, sizeof(int));
-       if(err)
-               return err;
-       put_fs_long(val,(unsigned long *)optval);
-
-       return(0);
-}      
index 95daf2c74e937ff696b1afcfe8d75d7c3dbd9d6d..3c01cc8e716b598e0ab264cbd1020562752c7bd2 100644 (file)
@@ -21,8 +21,8 @@
 
 #include <linux/ip.h>
 
-#include "sockinet.h"
 
+#include "sock.h"      /* struct sock */
 
 /* IP flags. */
 #define IP_CE          0x8000          /* Flag: "Congestion"           */
@@ -69,8 +69,7 @@ extern int            ip_build_header(struct sk_buff *skb,
                                        unsigned long saddr,
                                        unsigned long daddr,
                                        struct device **dev, int type,
-                                       struct options *opt, int len,
-                                       int tos,int ttl);
+                                       struct options *opt, int len);
 extern unsigned short  ip_compute_csum(unsigned char * buff, int len);
 extern int             ip_rcv(struct sk_buff *skb, struct device *dev,
                               struct packet_type *pt);
@@ -78,6 +77,5 @@ extern void           ip_queue_xmit(struct sock *sk,
                                      struct device *dev, struct sk_buff *skb,
                                      int free);
 extern void            ip_retransmit(struct sock *sk, int all);
-extern int             ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int optlen);
-extern int             ip_getsockopt(struct sock *sk, int level, int optname, char *optval, int *optlen);
+
 #endif /* _IP_H */
index 949e41a08aee8c74c94e0e40089405123ad22f33..66203eb540f9edbdf474f47bd38ec30dc77863d1 100644 (file)
@@ -5,77 +5,71 @@
  *
  *             Pseudo-driver for the loopback interface.
  *
- * Version:    @(#)loopback.c  1.28    20/12/93
+ * Version:    @(#)loopback.c  1.0.4b  08/16/93
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *             Donald Becker, <becker@super.org>
  *
- *             This file should be in drivers/net, but our glorious leader
- *             has put it here, and who are we to argue with the Linus 8-)
- *
  *             This program is free software; you can redistribute it and/or
  *             modify it under the terms of the GNU General Public License
  *             as published by the Free Software Foundation; either version
  *             2 of the License, or (at your option) any later version.
  */
-#include <asm/system.h>
-#include <asm/segment.h>
-#include <asm/io.h>
 #include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/fs.h>
-#include <linux/tty.h>
 #include <linux/types.h>
-#include <linux/ptrace.h>
 #include <linux/string.h>
 #include <linux/socket.h>
 #include <linux/errno.h>
 #include <linux/fcntl.h>
 #include <linux/in.h>
 #include <linux/if_ether.h>    /* For the statistics structure. */
+
+#include <asm/system.h>
+#include <asm/segment.h>
+#include <asm/io.h>
+
 #include "inet.h"
-#include "devinet.h"
+#include "dev.h"
 #include "eth.h"
 #include "ip.h"
 #include "protocol.h"
 #include "tcp.h"
 #include "skbuff.h"
-#include "sockinet.h"
+#include "sock.h"
 #include "arp.h"
 
 
-static int loopback_xmit(struct sk_buff *skb, struct device *dev)
+static int
+loopback_xmit(struct sk_buff *skb, struct device *dev)
 {
-       struct enet_statistics *stats = (struct enet_statistics *)dev->priv;
-       int done;
+  struct enet_statistics *stats = (struct enet_statistics *)dev->priv;
+  int done;
 
-       DPRINTF((DBG_LOOPB, "loopback_xmit(dev=%X, skb=%X)\n", dev, skb));
-       if (skb == NULL || dev == NULL) 
-               return(0);
+  DPRINTF((DBG_LOOPB, "loopback_xmit(dev=%X, skb=%X)\n", dev, skb));
+  if (skb == NULL || dev == NULL) return(0);
 
-       cli();
-       if (dev->tbusy != 0) 
-       {
-               sti();
-               stats->tx_errors++;
-               return(1);
-       }
-       dev->tbusy = 1;
-       sti();
+  cli();
+  if (dev->tbusy != 0) {
+       sti();
+       stats->tx_errors++;
+       return(1);
+  }
+  dev->tbusy = 1;
+  sti();
 
-       done = dev_rint((unsigned char *)(skb+1), skb->len, 0, dev);
-       if (skb->free) 
-               kfree_skb(skb, FREE_WRITE);
+  done = dev_rint((unsigned char *)(skb+1), skb->len, 0, dev);
+  if (skb->free) kfree_skb(skb, FREE_WRITE);
 
-       while (done != 1) 
-       {
-               done = dev_rint(NULL, 0, 0, dev);
-       }
-       stats->tx_packets++;
+  while (done != 1) {
+       done = dev_rint(NULL, 0, 0, dev);
+  }
+  stats->tx_packets++;
 
-       dev->tbusy = 0;
+  dev->tbusy = 0;
 
 #if 1
        __asm__("cmpl $0,_intr_count\n\t"
@@ -92,50 +86,52 @@ static int loopback_xmit(struct sk_buff *skb, struct device *dev)
                : "ax", "dx", "cx");
 #endif
 
-       return(0);
+  return(0);
 }
 
-static struct enet_statistics *get_stats(struct device *dev)
+static struct enet_statistics *
+get_stats(struct device *dev)
 {
     return (struct enet_statistics *)dev->priv;
 }
 
 /* Initialize the rest of the LOOPBACK device. */
-int loopback_init(struct device *dev)
+int
+loopback_init(struct device *dev)
 {
-       dev->mtu                = 2000;                 /* MTU                  */
-       dev->tbusy              = 0;
-       dev->hard_start_xmit    = loopback_xmit;
-       dev->open               = NULL;
+  dev->mtu             = 2000;                 /* MTU                  */
+  dev->tbusy           = 0;
+  dev->hard_start_xmit = loopback_xmit;
+  dev->open            = NULL;
 #if 1
-       dev->hard_header        = eth_header;
-       dev->add_arp            = NULL;
-       dev->hard_header_len    = ETH_HLEN;             /* 14                   */
-       dev->addr_len           = ETH_ALEN;             /* 6                    */
-       dev->type               = ARPHRD_ETHER;         /* 0x0001               */
-       dev->type_trans = eth_type_trans;
-       dev->rebuild_header     = eth_rebuild_header;
+  dev->hard_header     = eth_header;
+  dev->add_arp         = NULL;
+  dev->hard_header_len = ETH_HLEN;             /* 14                   */
+  dev->addr_len                = ETH_ALEN;             /* 6                    */
+  dev->type            = ARPHRD_ETHER;         /* 0x0001               */
+  dev->type_trans      = eth_type_trans;
+  dev->rebuild_header  = eth_rebuild_header;
 #else
-       dev->hard_header_length = 0;
-       dev->add_arp            = NULL;
-       dev->addr_len           = 0;
-       dev->type               = 0;                    /* loopback_type (0)    */
-       dev->hard_header        = NULL;
-       dev->type_trans         = NULL;
-       dev->rebuild_header     = NULL;
+  dev->hard_header_length = 0;
+  dev->add_arp         = NULL;
+  dev->addr_len                = 0;
+  dev->type            = 0;                    /* loopback_type (0)    */
+  dev->hard_header     = NULL;
+  dev->type_trans      = NULL;
+  dev->rebuild_header  = NULL;
 #endif
-       dev->queue_xmit         = dev_queue_xmit;
+  dev->queue_xmit      = dev_queue_xmit;
 
   /* New-style flags. */
-       dev->flags              = IFF_LOOPBACK;
-       dev->family             = AF_INET;
-       dev->pa_addr            = in_aton("127.0.0.1");
-       dev->pa_brdaddr         = in_aton("127.255.255.255");
-       dev->pa_mask            = in_aton("255.0.0.0");
-       dev->pa_alen            = sizeof(unsigned long);
-       dev->priv               = kmalloc(sizeof(struct enet_statistics), GFP_KERNEL);
-       memset(dev->priv, 0, sizeof(struct enet_statistics));
-       dev->get_stats = get_stats;
+  dev->flags           = IFF_LOOPBACK;
+  dev->family          = AF_INET;
+  dev->pa_addr         = in_aton("127.0.0.1");
+  dev->pa_brdaddr      = in_aton("127.255.255.255");
+  dev->pa_mask         = in_aton("255.0.0.0");
+  dev->pa_alen         = sizeof(unsigned long);
+  dev->priv = kmalloc(sizeof(struct enet_statistics), GFP_KERNEL);
+  memset(dev->priv, 0, sizeof(struct enet_statistics));
+  dev->get_stats = get_stats;
   
-       return(0);
+  return(0);
 };
index 48b2184d9be087ce9fe6d758e7b77a3d1444a1d0..c0585a670b1cfd365b4287b4f9254d851a5d9929 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             PACKET - implements raw packet sockets.
  *
- * Version:    @(#)packet.c    1.28    20/12/93
+ * Version:    @(#)packet.c    1.0.6   05/25/93
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -18,7 +18,6 @@
  *                                     added. Also fixed the peek/read crash
  *                                     from all old Linux datagram code.
  *             Alan Cox        :       Uses the improved datagram code.
- *             Alan Cox        :       Clean up for final release.
  *
  *
  *             This program is free software; you can redistribute it and/or
 #include <linux/socket.h>
 #include <linux/in.h>
 #include "inet.h"
-#include "devinet.h"
+#include "dev.h"
 #include "ip.h"
 #include "protocol.h"
 #include "tcp.h"
 #include "skbuff.h"
-#include "sockinet.h"
+#include "sock.h"
 #include <linux/errno.h>
 #include <linux/timer.h>
 #include <asm/system.h>
 #include "udp.h"
 #include "raw.h"
 
-/*
- *     I'm sure there should be one of these, not one every file.
- */
 
-static unsigned long min(unsigned long a, unsigned long b)
+static unsigned long
+min(unsigned long a, unsigned long b)
 {
-       if (a < b) 
-               return(a);
-       return(b);
+  if (a < b) return(a);
+  return(b);
 }
 
 
-/* 
- *     This should be the easiest of all, all we do is copy it into a buffer. 
- */
-int packet_rcv(struct sk_buff *skb, struct device *dev,  struct packet_type *pt)
+/* This should be the easiest of all, all we do is copy it into a buffer. */
+int
+packet_rcv(struct sk_buff *skb, struct device *dev,  struct packet_type *pt)
 {
-       struct sock *sk;
-
-       sk = (struct sock *) pt->data;
-       skb->dev = dev;
-       skb->len += dev->hard_header_len;
-
-       skb->sk = sk;
-
-       /* Charge it too the socket. */
-       if (sk->rmem_alloc + skb->mem_len >= sk->rcvbuf) 
-       {
-               skb->sk = NULL;
-               kfree_skb(skb, FREE_READ);
-               return(0);
-       }
-       sk->rmem_alloc += skb->mem_len;
-       skb_queue_tail(&sk->rqueue,skb);
-       release_sock(sk);
-       sk->data_ready(sk,skb->len);    
-       return(0);
+  struct sock *sk;
+
+  sk = (struct sock *) pt->data;
+  skb->dev = dev;
+  skb->len += dev->hard_header_len;
+
+  skb->sk = sk;
+
+  /* Charge it too the socket. */
+  if (sk->rmem_alloc + skb->mem_len >= sk->rcvbuf) {
+       skb->sk = NULL;
+       kfree_skb(skb, FREE_READ);
+       return(0);
+  }
+  sk->rmem_alloc += skb->mem_len;
+  skb_queue_tail(&sk->rqueue,skb);
+  wake_up(sk->sleep);
+  release_sock(sk);
+  return(0);
 }
 
 
-/*
- *     This will do terrible things if len + ipheader + devheader > dev->mtu 
- *     Since only root can use these thats okish...
- */
-static int packet_sendto(struct sock *sk, unsigned char *from, int len,
+/* This will do terrible things if len + ipheader + devheader > dev->mtu */
+static int
+packet_sendto(struct sock *sk, unsigned char *from, int len,
              int noblock, unsigned flags, struct sockaddr_in *usin,
              int addr_len)
 {
-       struct sk_buff *skb;
-       struct device *dev;
-       struct sockaddr saddr;
-       int err;
-
-       /* Check the flags. */
-       if (flags) 
-               return(-EINVAL);
-       if (len < 0) 
-               return(-EINVAL);
-       
-       /* Get and verify the address. */
-       if (usin) 
-       {
-               if (addr_len < sizeof(saddr)) 
-                       return(-EINVAL);
-               err=verify_area(VERIFY_READ, usin, sizeof(saddr));
-               if(err)
-                       return err;
-               memcpy_fromfs(&saddr, usin, sizeof(saddr));
-       } 
-       else
-               return(-EINVAL);
+  struct sk_buff *skb;
+  struct device *dev;
+  struct sockaddr saddr;
+  int err;
+
+  /* Check the flags. */
+  if (flags) return(-EINVAL);
+  if (len < 0) return(-EINVAL);
+
+  /* Get and verify the address. */
+  if (usin) {
+       if (addr_len < sizeof(saddr)) return(-EINVAL);
+       err=verify_area(VERIFY_READ, usin, sizeof(saddr));
+       if(err)
+               return err;
+       memcpy_fromfs(&saddr, usin, sizeof(saddr));
+  } else
+       return(-EINVAL);
        
-       err=verify_area(VERIFY_READ,from,len);
-       if(err)
-               return(err);
-       /* Find the device first to size check it */
-
-       saddr.sa_data[13] = 0;
-       dev = dev_get(saddr.sa_data);
-       if (dev == NULL) 
-       {
-               return(-ENXIO);
-       }
-       if(len>dev->mtu)
-               return -EMSGSIZE;
-
-       /* Now allocate the buffer, knowing 4K pagelimits wont break this line */  
-       skb = (struct sk_buff *) sk->prot->wmalloc(sk, len+sizeof(*skb), 0, GFP_KERNEL);
-
-       /* This shouldn't happen, but it could. */
-       if (skb == NULL) 
-       {
-               DPRINTF((DBG_PKT, "packet_sendto: write buffer full?\n"));
-               return(-ENOMEM);
-       }
-       /* Fill it in */
-       skb->sk = sk;
-       skb->free = 1;
-       memcpy_fromfs (skb+1, from, len);
-       skb->len = len;
-       skb->next = NULL;
-       if (dev->flags & IFF_UP) 
-               dev->queue_xmit(skb, dev, sk->priority);
-       else 
-               kfree_skb(skb, FREE_WRITE);
-       return(len);
+  err=verify_area(VERIFY_READ,from,len);
+  if(err)
+       return(err);
+/* Find the device first to size check it */
+
+  saddr.sa_data[13] = 0;
+  dev = dev_get(saddr.sa_data);
+  if (dev == NULL) {
+       return(-ENXIO);
+  }
+  if(len>dev->mtu)
+       return -EMSGSIZE;
+
+/* Now allocate the buffer, knowing 4K pagelimits wont break this line */  
+  skb = (struct sk_buff *) sk->prot->wmalloc(sk, len+sizeof(*skb), 0, GFP_KERNEL);
+
+  /* This shouldn't happen, but it could. */
+  if (skb == NULL) {
+       DPRINTF((DBG_PKT, "packet_sendto: write buffer full?\n"));
+       return(-ENOMEM);
+  }
+  /* Fill it in */
+  skb->mem_addr = skb;
+  skb->mem_len = len + sizeof(*skb);
+  skb->sk = sk;
+  skb->free = 1;
+  memcpy_fromfs (skb+1, from, len);
+  skb->len = len;
+  skb->next = NULL;
+  if (dev->flags & IFF_UP) dev->queue_xmit(skb, dev, sk->priority);
+    else kfree_skb(skb, FREE_WRITE);
+  return(len);
 }
 
 
-static int packet_write(struct sock *sk, unsigned char *buff, 
+static int
+packet_write(struct sock *sk, unsigned char *buff, 
             int len, int noblock,  unsigned flags)
 {
-       return(packet_sendto(sk, buff, len, noblock, flags, NULL, 0));
+  return(packet_sendto(sk, buff, len, noblock, flags, NULL, 0));
 }
 
 
-static void packet_close(struct sock *sk, int timeout)
+static void
+packet_close(struct sock *sk, int timeout)
 {
-       sk->inuse = 1;
-       sk->state = TCP_CLOSE;
-       dev_remove_pack((struct packet_type *)sk->pair);
-       kfree_s((void *)sk->pair, sizeof(struct packet_type));
-       sk->pair = NULL;
-       release_sock(sk);
+  sk->inuse = 1;
+  sk->state = TCP_CLOSE;
+  dev_remove_pack((struct packet_type *)sk->pair);
+  kfree_s((void *)sk->pair, sizeof(struct packet_type));
+  sk->pair = NULL;
+  release_sock(sk);
 }
 
 
-static int packet_init(struct sock *sk)
+static int
+packet_init(struct sock *sk)
 {
-       struct packet_type *p;
+  struct packet_type *p;
 
-       p = (struct packet_type *) kmalloc(sizeof(*p), GFP_KERNEL);
-       if (p == NULL) 
-               return(-ENOMEM);
+  p = (struct packet_type *) kmalloc(sizeof(*p), GFP_KERNEL);
+  if (p == NULL) return(-ENOMEM);
 
-       p->func = packet_rcv;
-       p->type = sk->num;
-       p->data = (void *)sk;
-       dev_add_pack(p);
-        
-       /* We need to remember this somewhere. */
-       sk->pair = (struct sock *)p;
+  p->func = packet_rcv;
+  p->type = sk->num;
+  p->data = (void *)sk;
+  dev_add_pack(p);
+   
+  /* We need to remember this somewhere. */
+  sk->pair = (struct sock *)p;
 
-       return(0);
+  return(0);
 }
 
 
@@ -198,95 +183,89 @@ static int packet_init(struct sock *sk)
  * This should be easy, if there is something there
  * we return it, otherwise we block.
  */
-int packet_recvfrom(struct sock *sk, unsigned char *to, int len,
+int
+packet_recvfrom(struct sock *sk, unsigned char *to, int len,
                int noblock, unsigned flags, struct sockaddr_in *sin,
                int *addr_len)
 {
-       int copied=0;
-       struct sk_buff *skb;
-       struct sockaddr *saddr;
-       int err;
-       
-       saddr = (struct sockaddr *)sin;
-       if (len == 0) 
-               return(0);
-       if (len < 0) 
-               return(-EINVAL);
-
-       if (sk->shutdown & RCV_SHUTDOWN) 
-               return(0);
-       if (addr_len) 
-       {
-               err=verify_area(VERIFY_WRITE, addr_len, sizeof(*addr_len));
-               if(err)
-                       return err;
-               put_fs_long(sizeof(*saddr), addr_len);
-       }
+  int copied=0;
+  struct sk_buff *skb;
+  struct sockaddr *saddr;
+  int err;
+
+  saddr = (struct sockaddr *)sin;
+  if (len == 0) return(0);
+  if (len < 0) return(-EINVAL);
+
+  if (sk->shutdown & RCV_SHUTDOWN) return(0);
+  if (addr_len) {
+         err=verify_area(VERIFY_WRITE, addr_len, sizeof(*addr_len));
+         if(err)
+               return err;
+         put_fs_long(sizeof(*saddr), addr_len);
+  }
   
-       err=verify_area(VERIFY_WRITE,to,len);
-       if(err)
-               return err;
-       skb=skb_recv_datagram(sk,flags,noblock,&err);
-       if(skb==NULL)
-               return err;
-       copied = min(len, skb->len);
-
-       memcpy_tofs(to, skb+1, copied); /* Don't use skb_copy_datagram here: We can't get frag chains */
-
-       /* Copy the address. */
-       if (saddr) 
-       {
-               struct sockaddr addr;
-
-               addr.sa_family = skb->dev->type;
-               memcpy(addr.sa_data,skb->dev->name, 14);
-               verify_area(VERIFY_WRITE, saddr, sizeof(*saddr));
-               memcpy_tofs(saddr, &addr, sizeof(*saddr));
-       }
-
-       skb_free_datagram(skb);         /* Its either been used up, or its a peek_copy anyway */
-
-       release_sock(sk);
-       return(copied);
+  err=verify_area(VERIFY_WRITE,to,len);
+  if(err)
+       return err;
+  skb=skb_recv_datagram(sk,flags,noblock,&err);
+  if(skb==NULL)
+       return err;
+  copied = min(len, skb->len);
+
+  memcpy_tofs(to, skb+1, copied);      /* Don't use skb_copy_datagram here: We can't get frag chains */
+
+  /* Copy the address. */
+  if (saddr) {
+       struct sockaddr addr;
+
+       addr.sa_family = skb->dev->type;
+       memcpy(addr.sa_data,skb->dev->name, 14);
+       verify_area(VERIFY_WRITE, saddr, sizeof(*saddr));
+       memcpy_tofs(saddr, &addr, sizeof(*saddr));
+  }
+
+  skb_free_datagram(skb);              /* Its either been used up, or its a peek_copy anyway */
+
+  release_sock(sk);
+  return(copied);
 }
 
 
-int packet_read(struct sock *sk, unsigned char *buff,
+int
+packet_read(struct sock *sk, unsigned char *buff,
            int len, int noblock, unsigned flags)
 {
-       return(packet_recvfrom(sk, buff, len, noblock, flags, NULL, NULL));
+  return(packet_recvfrom(sk, buff, len, noblock, flags, NULL, NULL));
 }
 
 
-struct proto packet_prot = 
-{
-       sock_wmalloc,
-       sock_rmalloc,
-       sock_wfree,
-       sock_rfree,
-       sock_rspace,
-       sock_wspace,
-       packet_close,
-       packet_read,
-       packet_write,
-       packet_sendto,
-       packet_recvfrom,
-       ip_build_header,
-       udp_connect,
-       NULL,
-       ip_queue_xmit,
-       ip_retransmit,
-       NULL,
-       NULL,
-       NULL, 
-       datagram_select,
-       NULL,
-       packet_init,
-       NULL,
-       NULL,   /* No set/get socket options */
-       NULL,
-       128,
-       0,
-       {NULL,},
-       "PACKET"
+struct proto packet_prot = {
+  sock_wmalloc,
+  sock_rmalloc,
+  sock_wfree,
+  sock_rfree,
+  sock_rspace,
+  sock_wspace,
+  packet_close,
+  packet_read,
+  packet_write,
+  packet_sendto,
+  packet_recvfrom,
+  ip_build_header,
+  udp_connect,
+  NULL,
+  ip_queue_xmit,
+  ip_retransmit,
+  NULL,
+  NULL,
+  NULL, 
+  datagram_select,
+  NULL,
+  packet_init,
+  NULL,
+  128,
+  0,
+  {NULL,},
+  "PACKET"
 };
index 04ed9e8e90491e2eb3df26cccb958c41a9389509..d5bc16e913f67fc20e00729fe6a2d54f9adb7967 100644 (file)
@@ -7,7 +7,7 @@
  *             PROC file system.  It is mainly used for debugging and
  *             statistics.
  *
- * Version:    @(#)proc.c      1.28    20/12/93
+ * Version:    @(#)proc.c      1.0.5   05/27/93
  *
  * Authors:    Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *             Gerald J. Heim, <heim@peanuts.informatik.uni-tuebingen.de>
  *                                     using hint flag for the netinfo.
  *     Pauline Middelink       :       Pidentd support
  *             Alan Cox        :       Make /proc safer.
- *             Alan Cox        :       Final clean up.
+ *
+ * To Do:
+ *             Put the creating userid in the proc/net/... files. This will
+ *             allow us to write an RFC931 daemon for Linux
  *
  *             This program is free software; you can redistribute it and/or
  *             modify it under the terms of the GNU General Public License
 #include <linux/in.h>
 #include <linux/param.h>
 #include "inet.h"
-#include "devinet.h"
+#include "dev.h"
 #include "ip.h"
 #include "protocol.h"
 #include "tcp.h"
 #include "udp.h"
-#include "socket/skbuff.h"
-#include "sockinet.h"
+#include "skbuff.h"
+#include "sock.h"
 #include "raw.h"
 
 /*
  *  As in get_unix_netinfo, the buffer might be too small. If this
  *  happens, get__netinfo returns only part of the available infos.
  */
-static int get__netinfo(struct proto *pro, char *buffer, int format)
+static int
+get__netinfo(struct proto *pro, char *buffer, int format)
 {
-       struct sock **s_array;
-       struct sock *sp;
-       char *pos=buffer;
-       int i;
-       int timer_active;
-       unsigned long  dest, src;
-       unsigned short destp, srcp;
-       
-       s_array = pro->sock_array;
-       pos+=sprintf(pos, "sl  local_address rem_address   st tx_queue rx_queue tr tm->when uid\n");
+  struct sock **s_array;
+  struct sock *sp;
+  char *pos=buffer;
+  int i;
+  int timer_active;
+  unsigned long  dest, src;
+  unsigned short destp, srcp;
+
+  s_array = pro->sock_array;
+  pos+=sprintf(pos, "sl  local_address rem_address   st tx_queue rx_queue tr tm->when uid\n");
 /*
  *     This was very pretty but didn't work when a socket is destroyed at the wrong moment
  *     (eg a syn recv socket getting a reset), or a memory timer destroy. Instead of playing
  *     with timers we just concede defeat and cli().
  */
-       for(i = 0; i < SOCK_ARRAY_SIZE; i++) 
-       {
-               cli();
-               sp = s_array[i];
-               while(sp != NULL) 
-               {
-                       dest  = sp->daddr;
-                       src   = sp->saddr;
-                       destp = sp->dummy_th.dest;
-                       srcp  = sp->dummy_th.source;
+  for(i = 0; i < SOCK_ARRAY_SIZE; i++) {
+       cli();
+       sp = s_array[i];
+       while(sp != NULL) {
+               dest  = sp->daddr;
+               src   = sp->saddr;
+               destp = sp->dummy_th.dest;
+               srcp  = sp->dummy_th.source;
 
-                       /* Since we are Little Endian we need to swap the bytes :-( */
-                       destp = ntohs(destp);
-                       srcp  = ntohs(srcp);
-                       timer_active = del_timer(&sp->timer);
-                       if (!timer_active)
-                               sp->timer.expires = 0;
-                       pos+=sprintf(pos, "%2d: %08lX:%04X %08lX:%04X %02X %08lX:%08lX %02X:%08lX %08X %d\n",
-                               i, src, srcp, dest, destp, sp->state, 
-                               format==0?sp->send_seq-sp->rcv_ack_seq:sp->rmem_alloc, 
-                               format==0?sp->acked_seq-sp->copied_seq:sp->wmem_alloc,
-                               timer_active, sp->timer.expires, (unsigned) sp->retransmits,
-                               SOCK_INODE(sp->socket)->i_uid);
-                       if (timer_active)
-                               add_timer(&sp->timer);
-                       /* Is place in buffer too rare? then abort. */
-                       if (pos > buffer+PAGE_SIZE-80) 
-                       {
-                               printk("oops, too many %s sockets for netinfo.\n",
+               /* Since we are Little Endian we need to swap the bytes :-( */
+               destp = ntohs(destp);
+               srcp  = ntohs(srcp);
+               timer_active = del_timer(&sp->timer);
+               if (!timer_active)
+                       sp->timer.expires = 0;
+               pos+=sprintf(pos, "%2d: %08lX:%04X %08lX:%04X %02X %08lX:%08lX %02X:%08lX %08X %d\n",
+                       i, src, srcp, dest, destp, sp->state, 
+                       format==0?sp->send_seq-sp->rcv_ack_seq:sp->rmem_alloc, 
+                       format==0?sp->acked_seq-sp->copied_seq:sp->wmem_alloc,
+                       timer_active, sp->timer.expires, (unsigned) sp->retransmits,
+                       SOCK_INODE(sp->socket)->i_uid);
+               if (timer_active)
+                       add_timer(&sp->timer);
+               /* Is place in buffer too rare? then abort. */
+               if (pos > buffer+PAGE_SIZE-80) {
+                       printk("oops, too many %s sockets for netinfo.\n",
                                        pro->name);
-                               return(strlen(buffer));
-                       }
-
-                       /*
-                        * All sockets with (port mod SOCK_ARRAY_SIZE) = i
-                        * are kept in sock_array[i], so we must follow the
-                        * 'next' link to get them all.
-                        */
-                       sp = sp->next;
+                       return(strlen(buffer));
                }
-               sti();  /* We only turn interrupts back on for a moment, but because the interrupt queues anything built up
+
+               /*
+                * All sockets with (port mod SOCK_ARRAY_SIZE) = i
+                * are kept in sock_array[i], so we must follow the
+                * 'next' link to get them all.
+                */
+               sp = sp->next;
+       }
+       sti();  /* We only turn interrupts back on for a moment, but because the interrupt queues anything built up
                   before this will clear before we jump back and cli, so its not as bad as it looks */
-       }
-       return(strlen(buffer));
+  }
+  return(strlen(buffer));
 } 
 
 
 int tcp_get_info(char *buffer)
 {
-       return get__netinfo(&tcp_prot, buffer,0);
+  return get__netinfo(&tcp_prot, buffer,0);
 }
 
 
 int udp_get_info(char *buffer)
 {
-       return get__netinfo(&udp_prot, buffer,1);
+  return get__netinfo(&udp_prot, buffer,1);
 }
 
 
 int raw_get_info(char *buffer)
 {
-       return get__netinfo(&raw_prot, buffer,1);
+  return get__netinfo(&raw_prot, buffer,1);
 }
index b6390db9ca8b8f9b0fe7a18be87bac56ba38a6cf..5690267879797f92f5ad45993d6a19a5766f11d3 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             INET protocol dispatch tables.
  *
- * Version:    @(#)protocol.c  1.28    20/12/93
+ * Version:    @(#)protocol.c  1.0.5   05/25/93
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -14,8 +14,7 @@
  *             Alan Cox        : Ahah! udp icmp errors don't work because
  *                               udp_err is never called!
  *             Alan Cox        : Added new fields for init and ready for
- *                               proper fragmentation (_NO_ 4K limits!).
- *             Alan Cox        : Final clean up.
+ *                               proper fragmentation (_NO_ 4K limits!)
  *
  *             This program is free software; you can redistribute it and/or
  *             modify it under the terms of the GNU General Public License
 #include <linux/socket.h>
 #include <linux/in.h>
 #include "inet.h"
-#include "devinet.h"
+#include "dev.h"
 #include "ip.h"
 #include "protocol.h"
 #include "tcp.h"
-#include "socket/skbuff.h"
-#include "sockinet.h"
+#include "skbuff.h"
+#include "sock.h"
 #include "icmp.h"
 #include "udp.h"
 
 
-static struct inet_protocol tcp_protocol = 
-{
-       tcp_rcv,                /* TCP handler          */
-       NULL,                   /* No fragment handler (and won't be for a long time) */
-       tcp_err,                /* TCP error control    */
-       NULL,                   /* next                 */
-       IPPROTO_TCP,            /* protocol ID          */
-       0,                      /* copy                 */
-       NULL,                   /* data                 */
-       "TCP"                   /* name                 */
+static struct inet_protocol tcp_protocol = {
+  tcp_rcv,             /* TCP handler          */
+  NULL,                        /* No fragment handler (and won't be for a long time) */
+  tcp_err,             /* TCP error control    */
+  NULL,                        /* next                 */
+  IPPROTO_TCP,         /* protocol ID          */
+  0,                   /* copy                 */
+  NULL,                        /* data                 */
+  "TCP"                        /* name                 */
 };
 
 
-static struct inet_protocol udp_protocol = 
-{
-       udp_rcv,                /* UDP handler          */
-       NULL,                   /* Will be UDP fraglist handler */
-       udp_err,                /* UDP error control    */
-       &tcp_protocol,  /* next                 */
-       IPPROTO_UDP,            /* protocol ID          */
-       0,                      /* copy                 */
-       NULL,                   /* data                 */
-       "UDP"                   /* name                 */
+static struct inet_protocol udp_protocol = {
+  udp_rcv,             /* UDP handler          */
+  NULL,                        /* Will be UDP fraglist handler */
+  udp_err,             /* UDP error control    */
+  &tcp_protocol,       /* next                 */
+  IPPROTO_UDP,         /* protocol ID          */
+  0,                   /* copy                 */
+  NULL,                        /* data                 */
+  "UDP"                        /* name                 */
 };
 
 
-static struct inet_protocol icmp_protocol = 
-{
-       icmp_rcv,               /* ICMP handler         */
-       NULL,                   /* ICMP never fragments anyway */
-       NULL,                   /* ICMP error control   */
-       &udp_protocol,          /* next                 */
-       IPPROTO_ICMP,           /* protocol ID          */
-       0,                      /* copy                 */
-       NULL,                   /* data                 */
-       "ICMP"                  /* name                 */
+static struct inet_protocol icmp_protocol = {
+  icmp_rcv,            /* ICMP handler         */
+  NULL,                        /* ICMP never fragments anyway */
+  NULL,                        /* ICMP error control   */
+  &udp_protocol,       /* next                 */
+  IPPROTO_ICMP,                /* protocol ID          */
+  0,                   /* copy                 */
+  NULL,                        /* data                 */
+  "ICMP"               /* name                 */
 };
 
 
 struct inet_protocol *inet_protocol_base = &icmp_protocol;
-
-struct inet_protocol *inet_protos[MAX_INET_PROTOS] = 
-{
-       NULL
+struct inet_protocol *inet_protos[MAX_INET_PROTOS] = {
+  NULL
 };
 
 
-struct inet_protocol *inet_get_protocol(unsigned char prot)
+struct inet_protocol *
+inet_get_protocol(unsigned char prot)
 {
-       unsigned char hash;
-       struct inet_protocol *p;
-
-       DPRINTF((DBG_PROTO, "get_protocol (%d)\n ", prot));
-       hash = prot & (MAX_INET_PROTOS - 1);
-       for (p = inet_protos[hash] ; p != NULL; p=p->next) 
-       {
-               DPRINTF((DBG_PROTO, "trying protocol %d\n", p->protocol));
-               if (p->protocol == prot) 
-                       return((struct inet_protocol *) p);
-       }
-       return(NULL);
+  unsigned char hash;
+  struct inet_protocol *p;
+
+  DPRINTF((DBG_PROTO, "get_protocol (%d)\n ", prot));
+  hash = prot & (MAX_INET_PROTOS - 1);
+  for (p = inet_protos[hash] ; p != NULL; p=p->next) {
+       DPRINTF((DBG_PROTO, "trying protocol %d\n", p->protocol));
+       if (p->protocol == prot) return((struct inet_protocol *) p);
+  }
+  return(NULL);
 }
 
 
-void inet_add_protocol(struct inet_protocol *prot)
+void
+inet_add_protocol(struct inet_protocol *prot)
 {
-       unsigned char hash;
-       struct inet_protocol *p2;
-
-       hash = prot->protocol & (MAX_INET_PROTOS - 1);
-       prot ->next = inet_protos[hash];
-       inet_protos[hash] = prot;
-       prot->copy = 0;
-
-       /* Set the copy bit if we need to. */
-       p2 = (struct inet_protocol *) prot->next;
-       while(p2 != NULL) 
-       {
-               if (p2->protocol == prot->protocol) 
-               {
-                       prot->copy = 1;
-                       break;
-               }
-               p2 = (struct inet_protocol *) prot->next;
-       }
+  unsigned char hash;
+  struct inet_protocol *p2;
+
+  hash = prot->protocol & (MAX_INET_PROTOS - 1);
+  prot ->next = inet_protos[hash];
+  inet_protos[hash] = prot;
+  prot->copy = 0;
+
+  /* Set the copy bit if we need to. */
+  p2 = (struct inet_protocol *) prot->next;
+  while(p2 != NULL) {
+       if (p2->protocol == prot->protocol) {
+               prot->copy = 1;
+               break;
+       }
+       p2 = (struct inet_protocol *) prot->next;
+  }
 }
 
 
-int inet_del_protocol(struct inet_protocol *prot)
+int
+inet_del_protocol(struct inet_protocol *prot)
 {
-       struct inet_protocol *p;
-       struct inet_protocol *lp = NULL;
-       unsigned char hash;
-       
-       hash = prot->protocol & (MAX_INET_PROTOS - 1);
-       if (prot == inet_protos[hash]) 
-       {
-               inet_protos[hash] = (struct inet_protocol *) inet_protos[hash]->next;
-               return(0);
-       }
-
-       p = (struct inet_protocol *) inet_protos[hash];
-       while(p != NULL) 
-       {
+  struct inet_protocol *p;
+  struct inet_protocol *lp = NULL;
+  unsigned char hash;
+
+  hash = prot->protocol & (MAX_INET_PROTOS - 1);
+  if (prot == inet_protos[hash]) {
+       inet_protos[hash] = (struct inet_protocol *) inet_protos[hash]->next;
+       return(0);
+  }
+
+  p = (struct inet_protocol *) inet_protos[hash];
+  while(p != NULL) {
+       /*
+        * We have to worry if the protocol being deleted is
+        * the last one on the list, then we may need to reset
+        * someones copied bit.
+        */
+       if (p->next != NULL && p->next == prot) {
                /*
-                * We have to worry if the protocol being deleted is
-                * the last one on the list, then we may need to reset
-                * someones copied bit.
+                * if we are the last one with this protocol and
+                * there is a previous one, reset its copy bit.
                 */
-               if (p->next != NULL && p->next == prot) 
-               {
-                       /*
-                        * if we are the last one with this protocol and
-                        * there is a previous one, reset its copy bit.
-                        */
-                       if (p->copy == 0 && lp != NULL) 
-                               lp->copy = 0;
-                       p->next = prot->next;
-                       return(0);
-               }       
-
-               if (p->next != NULL && p->next->protocol == prot->protocol) 
-               {
-                       lp = p;
-               }
-
-               p = (struct inet_protocol *) p->next;
-       }
-       return(-1);
+            if (p->copy == 0 && lp != NULL) lp->copy = 0;
+            p->next = prot->next;
+            return(0);
+       }
+
+       if (p->next != NULL && p->next->protocol == prot->protocol) {
+               lp = p;
+       }
+
+       p = (struct inet_protocol *) p->next;
+  }
+  return(-1);
 }
index aa56a3c0cc267b5dc384d9e732157a98bdbceab3..75335322310074649b7b68ad4f9abf7877ab298a 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             RAW - implementation of IP "raw" sockets.
  *
- * Version:    @(#)raw.c       1.28    20/12/93
+ * Version:    @(#)raw.c       1.0.4   05/25/93
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *             Alan Cox        :       Checks sk->broadcast.
  *             Alan Cox        :       Uses skb_free_datagram/skb_copy_datagram
  *             Alan Cox        :       Raw passes ip options too
- *             Alan Cox        :       Cleaned up and reformatted for final release
- *             Alan Cox        :       Added socket option call to proto
- *             Alan Cox        :       Corrected broadcast check error to EACCES
  *
  *             This program is free software; you can redistribute it and/or
  *             modify it under the terms of the GNU General Public License
  *             as published by the Free Software Foundation; either version
  *             2 of the License, or (at your option) any later version.
  */
-
 #include <asm/system.h>
 #include <asm/segment.h>
 #include <linux/types.h>
 #include <linux/socket.h>
 #include <linux/in.h>
 #include "inet.h"
-#include "devinet.h"
+#include "dev.h"
 #include "ip.h"
 #include "protocol.h"
 #include "tcp.h"
 #include "skbuff.h"
-#include "sockinet.h"
+#include "sock.h"
 #include "icmp.h"
 #include "udp.h"
 
 
-static unsigned long min(unsigned long a, unsigned long b)
+static unsigned long
+min(unsigned long a, unsigned long b)
 {
-       if (a < b) 
-               return(a);
-       return(b);
+  if (a < b) return(a);
+  return(b);
 }
 
 
-/*
- *     raw_err gets called by the icmp module. 
- */
-void raw_err (int err, unsigned char *header, unsigned long daddr,
+/* raw_err gets called by the icmp module. */
+void
+raw_err (int err, unsigned char *header, unsigned long daddr,
         unsigned long saddr, struct inet_protocol *protocol)
 {
-       struct sock *sk;
+  struct sock *sk;
    
-       DPRINTF((DBG_RAW, "raw_err(err=%d, hdr=%X, daddr=%X, saddr=%X, protocl=%X)\n",
+  DPRINTF((DBG_RAW, "raw_err(err=%d, hdr=%X, daddr=%X, saddr=%X, protocl=%X)\n",
                err, header, daddr, saddr, protocol));
 
-       if (protocol == NULL) 
-               return;
-               
-       sk = (struct sock *) protocol->data;
-       if (sk == NULL) 
-               return;
+  if (protocol == NULL) return;
+  sk = (struct sock *) protocol->data;
+  if (sk == NULL) return;
 
-       /* This is meaningless in raw sockets. */
+  /* This is meaningless in raw sockets. */
+  if (err & 0xff00 == (ICMP_SOURCE_QUENCH << 8)) {
+       if (sk->cong_window > 1) sk->cong_window = sk->cong_window/2;
+       return;
+  }
 
-       if (err & 0xff00 == (ICMP_SOURCE_QUENCH << 8)) 
-       {
-               if (sk->cong_window > 1) 
-                       sk->cong_window = sk->cong_window/2;
-               return;
-       }
-
-       sk->err = icmp_err_convert[err & 0xff].errno;
-       sk->error_report(sk);
-       return;
+  sk->err = icmp_err_convert[err & 0xff].errno;
+  wake_up(sk->sleep);
+  
+  return;
 }
 
 
 /*
- *     This should be the easiest of all, all we do is\
- *     copy it into a buffer. We do have to diddle the pointer
- *     to get the ip header too.
+ * This should be the easiest of all, all we do is\
+ * copy it into a buffer.
  */
-int raw_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
+int
+raw_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
        unsigned long daddr, unsigned short len, unsigned long saddr,
        int redo, struct inet_protocol *protocol)
 {
-       struct sock *sk;
-
-       DPRINTF((DBG_RAW, "raw_rcv(skb=%X, dev=%X, opt=%X, daddr=%X,\n"
-               "         len=%d, saddr=%X, redo=%d, protocol=%X)\n",
-               skb, dev, opt, daddr, len, saddr, redo, protocol));
-
-       if (skb == NULL) 
-               return(0);
-
-       if (protocol == NULL) 
-       {
-               kfree_skb(skb, FREE_READ);
-               return(0);
-       }
-       sk = (struct sock *) protocol->data;
-       if (sk == NULL) 
-       {
-               kfree_skb(skb, FREE_READ);
-               return(0);
-       }
-
-       /* Now we need to copy this into memory. */
-       skb->sk = sk;
-       /* 
-        *      Adjust to get the header back
-        */
-       skb->len += skb->ip_hdr->ihl*sizeof(long);
-       skb->h.iph = skb->ip_hdr;
-       skb->dev = dev;
-       skb->saddr = daddr;
-       skb->daddr = saddr;
-
-       /* Charge it too the socket. */
-       if (sk->rmem_alloc + skb->mem_len >= sk->rcvbuf) 
-       {
-               skb->sk = NULL;
-               kfree_skb(skb, FREE_READ);
-               return(0);
-       }
-       sk->rmem_alloc += skb->mem_len;
-       skb_queue_tail(&sk->rqueue,skb);
-       release_sock(sk);
-       sk->data_ready(sk,skb->len);
-       return(0);
+  struct sock *sk;
+
+  DPRINTF((DBG_RAW, "raw_rcv(skb=%X, dev=%X, opt=%X, daddr=%X,\n"
+          "         len=%d, saddr=%X, redo=%d, protocol=%X)\n",
+          skb, dev, opt, daddr, len, saddr, redo, protocol));
+
+  if (skb == NULL) return(0);
+  if (protocol == NULL) {
+       kfree_skb(skb, FREE_READ);
+       return(0);
+  }
+  sk = (struct sock *) protocol->data;
+  if (sk == NULL) {
+       kfree_skb(skb, FREE_READ);
+       return(0);
+  }
+
+  /* Now we need to copy this into memory. */
+  skb->sk = sk;
+  skb->len = len;
+  skb->dev = dev;
+  skb->saddr = daddr;
+  skb->daddr = saddr;
+
+  /* Charge it too the socket. */
+  if (sk->rmem_alloc + skb->mem_len >= sk->rcvbuf) {
+       skb->sk = NULL;
+       kfree_skb(skb, FREE_READ);
+       return(0);
+  }
+  sk->rmem_alloc += skb->mem_len;
+  skb_queue_tail(&sk->rqueue,skb);
+  wake_up(sk->sleep);
+  release_sock(sk);
+  return(0);
 }
 
 
-/*
- *     Send a RAW IP packet (user level IP protocols). Root only
- *     caller provides IP header.
- */
-static int raw_sendto(struct sock *sk, unsigned char *from, int len,
+/* This will do terrible things if len + ipheader + devheader > dev->mtu */
+static int
+raw_sendto(struct sock *sk, unsigned char *from, int len,
           int noblock,
           unsigned flags, struct sockaddr_in *usin, int addr_len)
 {
-       struct sk_buff *skb;
-       struct device *dev=NULL;
-       struct sockaddr_in sin;
-       int tmp;
-       int err;
-
-       DPRINTF((DBG_RAW, "raw_sendto(sk=%X, from=%X, len=%d, noblock=%d, flags=%X,\n"
-               "            usin=%X, addr_len = %d)\n", sk, from, len, noblock,
-               flags, usin, addr_len));
-
-       /* Check the flags. */
-       if (flags) 
-               return(-EINVAL);
-       if (len < 0) 
-               return(-EINVAL);
-
-       err=verify_area(VERIFY_READ,from,len);
-       if(err)
-               return err;
-       /* Get and verify the address. */
-       if (usin) 
-       {
-               if (addr_len < sizeof(sin)) 
-                       return(-EINVAL);
-               err=verify_area (VERIFY_READ, usin, sizeof (sin));
-               if(err)
-                       return err;
-               memcpy_fromfs(&sin, usin, sizeof(sin));
-               if (sin.sin_family && sin.sin_family != AF_INET) 
-                       return(-EINVAL);
-       } 
-       else 
-       {
-               if (sk->state != TCP_ESTABLISHED) 
-                       return(-EINVAL);
-               sin.sin_family = AF_INET;
-               sin.sin_port = sk->protocol;
-               sin.sin_addr.s_addr = sk->daddr;
-       }       
-       if (sin.sin_port == 0) 
-               sin.sin_port = sk->protocol;
+  struct sk_buff *skb;
+  struct device *dev=NULL;
+  struct sockaddr_in sin;
+  int tmp;
+  int err;
+
+  DPRINTF((DBG_RAW, "raw_sendto(sk=%X, from=%X, len=%d, noblock=%d, flags=%X,\n"
+          "            usin=%X, addr_len = %d)\n", sk, from, len, noblock,
+          flags, usin, addr_len));
+
+  /* Check the flags. */
+  if (flags) return(-EINVAL);
+  if (len < 0) return(-EINVAL);
+
+  err=verify_area(VERIFY_READ,from,len);
+  if(err)
+       return err;
+  /* Get and verify the address. */
+  if (usin) {
+       if (addr_len < sizeof(sin)) return(-EINVAL);
+       err=verify_area (VERIFY_READ, usin, sizeof (sin));
+       if(err)
+               return err;
+       memcpy_fromfs(&sin, usin, sizeof(sin));
+       if (sin.sin_family && sin.sin_family != AF_INET) return(-EINVAL);
+  } else {
+       if (sk->state != TCP_ESTABLISHED) return(-EINVAL);
+       sin.sin_family = AF_INET;
+       sin.sin_port = sk->protocol;
+       sin.sin_addr.s_addr = sk->daddr;
+  }
+  if (sin.sin_port == 0) sin.sin_port = sk->protocol;
   
-       if (sk->broadcast == 0 && chk_addr(sin.sin_addr.s_addr)==IS_BROADCAST)
-               return -EACCES;
+  if (sk->broadcast == 0 && chk_addr(sin.sin_addr.s_addr)==IS_BROADCAST)
+       return -ENETUNREACH;
 
-       sk->inuse = 1;
-       skb = NULL;
-       while (skb == NULL) 
+  sk->inuse = 1;
+  skb = NULL;
+  while (skb == NULL) {
+       if(sk->err!=0)
        {
-               if(sk->err!=0)
-               {
-                       err= -sk->err;
-                       sk->err=0;
-                       release_sock(sk);
-                       return(err);
-               }
+               err= -sk->err;
+               sk->err=0;
+               release_sock(sk);
+               return(err);
+       }
        
-               skb = (struct sk_buff *) sk->prot->wmalloc(sk,
+       skb = (struct sk_buff *) sk->prot->wmalloc(sk,
                        len+sizeof(*skb) + sk->prot->max_header,
                        0, GFP_KERNEL);
-               if (skb == NULL) 
-               {
-                       int tmp;
-
-                       DPRINTF((DBG_RAW, "raw_sendto: write buffer full?\n"));
-                       if (noblock) 
-                               return(-EAGAIN);
-                       tmp = sk->wmem_alloc;
-                       release_sock(sk);
-                       cli();
-                       if (tmp <= sk->wmem_alloc) 
-                       {
-                               interruptible_sleep_on(sk->sleep);
-                               if (current->signal & ~current->blocked) 
-                               {
-                                       sti();
-                                       return(-ERESTARTSYS);
-                               }
+       if (skb == NULL) {
+               int tmp;
+
+               DPRINTF((DBG_RAW, "raw_sendto: write buffer full?\n"));
+               if (noblock) 
+                       return(-EAGAIN);
+               tmp = sk->wmem_alloc;
+               release_sock(sk);
+               cli();
+               if (tmp <= sk->wmem_alloc) {
+                       interruptible_sleep_on(sk->sleep);
+                       if (current->signal & ~current->blocked) {
+                               sti();
+                               return(-ERESTARTSYS);
                        }
-                       sk->inuse = 1;
-                       sti();
                }
-       }
-       skb->sk = sk;
-
-       skb->free = 1; /* these two should be unecessary. */
-       skb->arp = 0;
-
-       tmp = sk->prot->build_header(skb, sk->saddr, 
+               sk->inuse = 1;
+               sti();
+       }
+  }
+  skb->mem_addr = skb;
+  skb->mem_len = len + sizeof(*skb) +sk->prot->max_header;
+  skb->sk = sk;
+
+  skb->free = 1; /* these two should be unecessary. */
+  skb->arp = 0;
+
+  tmp = sk->prot->build_header(skb, sk->saddr, 
                               sin.sin_addr.s_addr, &dev,
-                              sk->protocol, sk->opt, skb->mem_len,
-                              sk->ip_ttl,sk->ip_tos);
-       if (tmp < 0) 
-       {
-               DPRINTF((DBG_RAW, "raw_sendto: error building ip header.\n"));
-               kfree_skb(skb,FREE_WRITE);
-               release_sock(sk);
-               return(tmp);
-       }
-
-       memcpy_fromfs ((unsigned char *)(skb+1)+tmp, from, len);
-
-       /* If we are using IPPROTO_RAW, we need to fill in the source address in
-          the IP header */
-
-       if(sk->protocol==IPPROTO_RAW) 
-       {
-               unsigned char *buff;
-               struct iphdr *iph;
-
-               buff = (unsigned char *)(skb + 1);
-               buff += tmp;
-               iph = (struct iphdr *)buff;
-               iph->saddr = sk->saddr;
-       }
-
-       skb->len = tmp + len;
-  
-       if(dev!=NULL && skb->len > 4095)
-       {
-               kfree_skb(skb, FREE_WRITE);
-               release_sock(sk);
-               return(-EMSGSIZE);
-       }
+                              sk->protocol, sk->opt, skb->mem_len);
+  if (tmp < 0) {
+       DPRINTF((DBG_RAW, "raw_sendto: error building ip header.\n"));
+       kfree_skb(skb,FREE_WRITE);
+       release_sock(sk);
+       return(tmp);
+  }
+
+  /* verify_area(VERIFY_WRITE, from, len);*/
+  memcpy_fromfs ((unsigned char *)(skb+1)+tmp, from, len);
+
+  /* If we are using IPPROTO_RAW, we need to fill in the source address in
+     the IP header */
+
+  if(sk->protocol==IPPROTO_RAW) {
+    unsigned char *buff;
+    struct iphdr *iph;
+
+    buff = (unsigned char *)(skb + 1);
+    buff += tmp;
+    iph = (struct iphdr *)buff;
+    iph->saddr = sk->saddr;
+  }
+
+  skb->len = tmp + len;
   
-       sk->prot->queue_xmit(sk, dev, skb, 1);
+  if(dev!=NULL && skb->len > 4095)
+  {
+       kfree_skb(skb, FREE_WRITE);
        release_sock(sk);
-       return(len);
+       return(-EMSGSIZE);
+  }
+  
+  sk->prot->queue_xmit(sk, dev, skb, 1);
+  release_sock(sk);
+  return(len);
 }
 
 
-static int raw_write(struct sock *sk, unsigned char *buff, int len, int noblock,
+static int
+raw_write(struct sock *sk, unsigned char *buff, int len, int noblock,
           unsigned flags)
 {
-       return(raw_sendto(sk, buff, len, noblock, flags, NULL, 0));
+  return(raw_sendto(sk, buff, len, noblock, flags, NULL, 0));
 }
 
 
-static void raw_close(struct sock *sk, int timeout)
+static void
+raw_close(struct sock *sk, int timeout)
 {
-       sk->inuse = 1;
-       sk->state = TCP_CLOSE;
+  sk->inuse = 1;
+  sk->state = TCP_CLOSE;
 
-       DPRINTF((DBG_RAW, "raw_close: deleting protocol %d\n",
-               ((struct inet_protocol *)sk->pair)->protocol));
+  DPRINTF((DBG_RAW, "raw_close: deleting protocol %d\n",
+          ((struct inet_protocol *)sk->pair)->protocol));
 
-       if (inet_del_protocol((struct inet_protocol *)sk->pair) < 0)
+  if (inet_del_protocol((struct inet_protocol *)sk->pair) < 0)
                DPRINTF((DBG_RAW, "raw_close: del_protocol failed.\n"));
-       kfree_s((void *)sk->pair, sizeof (struct inet_protocol));
-       sk->pair = NULL;
-       release_sock(sk);
+  kfree_s((void *)sk->pair, sizeof (struct inet_protocol));
+  sk->pair = NULL;
+  release_sock(sk);
 }
 
 
-static int raw_init(struct sock *sk)
+static int
+raw_init(struct sock *sk)
 {
-       struct inet_protocol *p;
-
-       p = (struct inet_protocol *) kmalloc(sizeof (*p), GFP_KERNEL);
-       if (p == NULL) 
-               return(-ENOMEM);
-
-       p->handler = raw_rcv;
-       p->protocol = sk->protocol;
-       p->data = (void *)sk;
-       p->err_handler = raw_err;
-       p->name="USER";
-       p->frag_handler = NULL; /* For now */
-       inet_add_protocol(p);
+  struct inet_protocol *p;
+
+  p = (struct inet_protocol *) kmalloc(sizeof (*p), GFP_KERNEL);
+  if (p == NULL) return(-ENOMEM);
+
+  p->handler = raw_rcv;
+  p->protocol = sk->protocol;
+  p->data = (void *)sk;
+  p->err_handler = raw_err;
+  p->name="USER";
+  p->frag_handler = NULL;      /* For now */
+  inet_add_protocol(p);
    
-       /* We need to remember this somewhere. */
-       sk->pair = (struct sock *)p;
+  /* We need to remember this somewhere. */
+  sk->pair = (struct sock *)p;
 
-       DPRINTF((DBG_RAW, "raw init added protocol %d\n", sk->protocol));
+  DPRINTF((DBG_RAW, "raw init added protocol %d\n", sk->protocol));
 
-       return(0);
+  return(0);
 }
 
 
@@ -343,98 +307,91 @@ static int raw_init(struct sock *sk)
  * This should be easy, if there is something there
  * we return it, otherwise we block.
  */
-
-int raw_recvfrom(struct sock *sk, unsigned char *to, int len,
+int
+raw_recvfrom(struct sock *sk, unsigned char *to, int len,
             int noblock, unsigned flags, struct sockaddr_in *sin,
             int *addr_len)
 {
-       int copied=0;
-       struct sk_buff *skb;
-       int err;
+  int copied=0;
+  struct sk_buff *skb;
+  int err;
 
-       DPRINTF((DBG_RAW, "raw_recvfrom (sk=%X, to=%X, len=%d, noblock=%d, flags=%X,\n"
-               "              sin=%X, addr_len=%X)\n",
+  DPRINTF((DBG_RAW, "raw_recvfrom (sk=%X, to=%X, len=%d, noblock=%d, flags=%X,\n"
+          "              sin=%X, addr_len=%X)\n",
                sk, to, len, noblock, flags, sin, addr_len));
 
-       if (len == 0) 
-               return(0);
-       if (len < 0) 
-               return(-EINVAL);
-
-       if (sk->shutdown & RCV_SHUTDOWN) 
-               return(0);
-       if (addr_len) 
-       {
-               err=verify_area(VERIFY_WRITE, addr_len, sizeof(*addr_len));
-               if(err)
-                       return err;
-               put_fs_long(sizeof(*sin), addr_len);
-       }
-       err=verify_area(VERIFY_WRITE,to,len);
-       if(err)
-               return err;
-
-       skb=skb_recv_datagram(sk,flags,noblock,&err);
-       if(skb==NULL)
-               return err;
-
-       copied = min(len, skb->len);
+  if (len == 0) return(0);
+  if (len < 0) return(-EINVAL);
+
+  if (sk->shutdown & RCV_SHUTDOWN) return(0);
+  if (addr_len) {
+       err=verify_area(VERIFY_WRITE, addr_len, sizeof(*addr_len));
+       if(err)
+               return err;
+       put_fs_long(sizeof(*sin), addr_len);
+  }
+  err=verify_area(VERIFY_WRITE,to,len);
+  if(err)
+       return err;
+
+  skb=skb_recv_datagram(sk,flags,noblock,&err);
+  if(skb==NULL)
+       return err;
+
+  copied = min(len, skb->len);
   
-       skb_copy_datagram(skb, 0, to, copied);
+  skb_copy_datagram(skb, 0, to, copied);
 
-       /* Copy the address. */
-       if (sin) 
-       {
-               struct sockaddr_in addr;
-       
-               addr.sin_family = AF_INET;
-               addr.sin_addr.s_addr = skb->daddr;
-               verify_area(VERIFY_WRITE, sin, sizeof(*sin));
-               memcpy_tofs(sin, &addr, sizeof(*sin));
-       }
+  /* Copy the address. */
+  if (sin) {
+       struct sockaddr_in addr;
 
-       skb_free_datagram(skb);
-       release_sock(sk);
-       return (copied);
+       addr.sin_family = AF_INET;
+       addr.sin_addr.s_addr = skb->daddr;
+       verify_area(VERIFY_WRITE, sin, sizeof(*sin));
+       memcpy_tofs(sin, &addr, sizeof(*sin));
+  }
+
+  skb_free_datagram(skb);
+  release_sock(sk);
+  return (copied);
 }
 
 
-int raw_read (struct sock *sk, unsigned char *buff, int len, int noblock,
+int
+raw_read (struct sock *sk, unsigned char *buff, int len, int noblock,
          unsigned flags)
 {
-       return(raw_recvfrom(sk, buff, len, noblock, flags, NULL, NULL));
+  return(raw_recvfrom(sk, buff, len, noblock, flags, NULL, NULL));
 }
 
 
-struct proto raw_prot = 
-{
-       sock_wmalloc,
-       sock_rmalloc,
-       sock_wfree,
-       sock_rfree,
-       sock_rspace,
-       sock_wspace,
-       raw_close,
-       raw_read,
-       raw_write,
-       raw_sendto,
-       raw_recvfrom,
-       ip_build_header,
-       udp_connect,
-       NULL,
-       ip_queue_xmit,
-       ip_retransmit,
-       NULL,
-       NULL,
-       raw_rcv,
-       datagram_select,
-       NULL,
-       raw_init,
-       NULL,
-       ip_setsockopt,
-       ip_getsockopt,
-       128,
-       0,
-       {NULL,},
-       "RAW"
+struct proto raw_prot = {
+  sock_wmalloc,
+  sock_rmalloc,
+  sock_wfree,
+  sock_rfree,
+  sock_rspace,
+  sock_wspace,
+  raw_close,
+  raw_read,
+  raw_write,
+  raw_sendto,
+  raw_recvfrom,
+  ip_build_header,
+  udp_connect,
+  NULL,
+  ip_queue_xmit,
+  ip_retransmit,
+  NULL,
+  NULL,
+  raw_rcv,
+  datagram_select,
+  NULL,
+  raw_init,
+  NULL,
+  128,
+  0,
+  {NULL,},
+  "RAW"
 };
index cd2e3551b8a8227d4f9b246e3b9952912b6b67f5..269c80d6a896770336e130724dd3a7ef260b192c 100644 (file)
@@ -47,18 +47,18 @@ static struct rtable *rt_base = NULL;
 static struct rtable *rt_loopback = NULL;
 
 /* Dump the contents of a routing table entry. */
-static void rt_print(struct rtable *rt)
+static void
+rt_print(struct rtable *rt)
 {
-       if (rt == NULL || inet_debug != DBG_RT)
-               return;
+  if (rt == NULL || inet_debug != DBG_RT) return;
 
-       printk("RT: %06lx NXT=%06lx FLAGS=0x%02x\n",
+  printk("RT: %06lx NXT=%06lx FLAGS=0x%02x\n",
                (long) rt, (long) rt->rt_next, rt->rt_flags);
-       printk("    TARGET=%s ", in_ntoa(rt->rt_dst));
-       printk("GW=%s ", in_ntoa(rt->rt_gateway));
-       printk("    DEV=%s USE=%ld REF=%d\n",
-               (rt->rt_dev == NULL) ? "NONE" : rt->rt_dev->name,
-               rt->rt_use, rt->rt_refcnt);
+  printk("    TARGET=%s ", in_ntoa(rt->rt_dst));
+  printk("GW=%s ", in_ntoa(rt->rt_gateway));
+  printk("    DEV=%s USE=%ld REF=%d\n",
+       (rt->rt_dev == NULL) ? "NONE" : rt->rt_dev->name,
+       rt->rt_use, rt->rt_refcnt);
 }
 
 
@@ -162,8 +162,8 @@ static inline struct device * get_gw_dev(unsigned long gw)
 /*
  * rewrote rt_add(), as the old one was weird. Linus
  */
-void rt_add(short flags, unsigned long dst, unsigned long mask,
-       unsigned long gw, struct device *dev)
+void
+rt_add(short flags, unsigned long dst, unsigned long mask, unsigned long gw, struct device *dev)
 {
        struct rtable *r, *rt;
        struct rtable **rp;
@@ -280,35 +280,38 @@ static int rt_new(struct rtentry *r)
 }
 
 
-static int rt_kill(struct rtentry *r)
+static int
+rt_kill(struct rtentry *r)
 {
-       struct sockaddr_in *trg;
+  struct sockaddr_in *trg;
 
-       trg = (struct sockaddr_in *) &r->rt_dst;
-       rt_del(trg->sin_addr.s_addr);
-       return 0;
+  trg = (struct sockaddr_in *) &r->rt_dst;
+  rt_del(trg->sin_addr.s_addr);
+
+  return(0);
 }
 
 
 /* Called from the PROCfs module. */
-int rt_get_info(char *buffer)
+int
+rt_get_info(char *buffer)
 {
-       struct rtable *r;
-       char *pos;
+  struct rtable *r;
+  char *pos;
 
-       pos = buffer;
+  pos = buffer;
 
-       pos += sprintf(pos,
-               "Iface\tDestination\tGateway \tFlags\tRefCnt\tUse\tMetric\tMask\n");
+  pos += sprintf(pos,
+                "Iface\tDestination\tGateway \tFlags\tRefCnt\tUse\tMetric\tMask\n");
   
-       /* This isn't quite right -- r->rt_dst is a struct! */
-       for (r = rt_base; r != NULL; r = r->rt_next) {
-               pos += sprintf(pos, "%s\t%08lX\t%08lX\t%02X\t%d\t%lu\t%d\t%08lX\n",
-                       r->rt_dev->name, r->rt_dst, r->rt_gateway,
-                       r->rt_flags, r->rt_refcnt, r->rt_use, r->rt_metric,
-                       r->rt_mask);
-       }
-       return pos - buffer;
+  /* This isn't quite right -- r->rt_dst is a struct! */
+  for (r = rt_base; r != NULL; r = r->rt_next) {
+        pos += sprintf(pos, "%s\t%08lX\t%08lX\t%02X\t%d\t%lu\t%d\t%08lX\n",
+               r->rt_dev->name, r->rt_dst, r->rt_gateway,
+               r->rt_flags, r->rt_refcnt, r->rt_use, r->rt_metric,
+               r->rt_mask);
+  }
+  return(pos - buffer);
 }
 
 /*
@@ -337,41 +340,39 @@ no_route:
 }
 
 
-int rt_ioctl(unsigned int cmd, void *arg)
+int
+rt_ioctl(unsigned int cmd, void *arg)
 {
-       struct device *dev;
-       struct rtentry rt;
-       char namebuf[32];
-       int ret;
-       int err;
+  struct device *dev;
+  struct rtentry rt;
+  char namebuf[32];
+  int ret;
+  int err;
 
-       switch(cmd) {
+  switch(cmd) {
        case DDIOCSDBG:
                ret = dbg_ioctl(arg, DBG_RT);
                break;
-
        case SIOCADDRT:
        case SIOCDELRT:
-               if (!suser())
-                       return -EPERM;
-               err = verify_area(VERIFY_READ, arg, sizeof(struct rtentry));
+               if (!suser()) return(-EPERM);
+               err=verify_area(VERIFY_READ, arg, sizeof(struct rtentry));
                if(err)
                        return err;
                memcpy_fromfs(&rt, arg, sizeof(struct rtentry));
                if (rt.rt_dev) {
-                       err = verify_area(VERIFY_READ, rt.rt_dev, sizeof namebuf);
-                       if(err)
-                               return err;
-                       memcpy_fromfs(&namebuf, rt.rt_dev, sizeof namebuf);
-                       dev = dev_get(namebuf);
-                       rt.rt_dev = dev;
+                   err=verify_area(VERIFY_READ, rt.rt_dev, sizeof namebuf);
+                   if(err)
+                       return err;
+                   memcpy_fromfs(&namebuf, rt.rt_dev, sizeof namebuf);
+                   dev = dev_get(namebuf);
+                   rt.rt_dev = dev;
                }
                ret = (cmd == SIOCDELRT) ? rt_kill(&rt) : rt_new(&rt);
                break;
-
        default:
                ret = -EINVAL;
-       }
+  }
 
-       return ret;
+  return(ret);
 }
index c5429c6150c341a9c42aee4703f39d59d7f2f2fd..bba3acf701c3d251dd9d6abea644895d8f174111 100644 (file)
 
 /* This is an entry in the IP routing table. */
 struct rtable {
-       struct rtable   *rt_next;
-       unsigned long   rt_dst;
-       unsigned long   rt_mask;
-       unsigned long   rt_gateway;
-       u_char          rt_flags;
-       u_char          rt_metric;
-       short           rt_refcnt;
-       u_long          rt_use;
-       struct device   *rt_dev;
+  struct rtable                *rt_next;
+  unsigned long                rt_dst;
+  unsigned long                rt_mask;
+  unsigned long                rt_gateway;
+  u_char               rt_flags;
+  u_char               rt_metric;
+  short                        rt_refcnt;
+  u_long               rt_use;
+  struct device                *rt_dev;
 };
 
 
diff --git a/net/inet/skbuff.c b/net/inet/skbuff.c
new file mode 100644 (file)
index 0000000..1f3299d
--- /dev/null
@@ -0,0 +1,454 @@
+/*
+ * INET                An implementation of the TCP/IP protocol suite for the LINUX
+ *             operating system.  INET is implemented using the  BSD Socket
+ *             interface as the means of communication with the user level.
+ *
+ *             A saner implementation of the skbuff stuff scattered everywhere
+ *             in the old NET2D code.
+ *
+ *     Authors:        Alan Cox <iiitac@pyr.swan.ac.uk>
+ *
+ *     Fixes:
+ *             Alan Cox        :       Tracks memory and number of buffers for kernel memory report
+ *                                     and memory leak hunting.
+ *             Alan Cox        :       More generic kfree handler
+ */
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <asm/segment.h>
+#include <asm/system.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/in.h>
+#include "inet.h"
+#include "dev.h"
+#include "ip.h"
+#include "protocol.h"
+#include "arp.h"
+#include "route.h"
+#include "tcp.h"
+#include "udp.h"
+#include "skbuff.h"
+#include "sock.h"
+
+
+/* Socket buffer operations. Ideally much of this list swap stuff ought to be using
+   exch instructions on the 386, and CAS/CAS2 on a 68K. This is the boring generic
+   slow C version. No doubt when Linus sees this comment he'll do horrible things
+   to this code 8-)
+*/
+
+/*
+ *     Resource tracking variables
+ */
+volatile unsigned long net_memory=0;
+volatile unsigned long net_skbcount=0;
+
+/*
+ *     Debugging paranoia. Can go later when this crud stack works
+ */ 
+
+
+void skb_check(struct sk_buff *skb, int line, char *file)
+{
+       if(skb->magic_debug_cookie==SK_FREED_SKB)
+       {
+               printk("File: %s Line %d, found a freed skb lurking in the undergrowth!\n",
+                       file,line);
+               printk("skb=%p, real size=%ld, claimed size=%ld, magic=%d, list=%p, free=%d\n",
+                       skb,skb->truesize,skb->mem_len,skb->magic,skb->list,skb->free);
+       }
+       if(skb->magic_debug_cookie!=SK_GOOD_SKB)
+       {
+               printk("File: %s Line %d, passed a non skb!\n", file,line);
+               printk("skb=%p, real size=%ld, claimed size=%ld, magic=%d, list=%p, free=%d\n",
+                       skb,skb->truesize,skb->mem_len,skb->magic,skb->list,skb->free);
+       }
+       if(skb->mem_len!=skb->truesize)
+       {
+               printk("File: %s Line %d, Dubious size setting!\n",file,line);
+               printk("skb=%p, real size=%ld, claimed size=%ld, magic=%d, list=%p\n",
+                       skb,skb->truesize,skb->mem_len,skb->magic,skb->list);
+       }
+       /* Guess it might be acceptable then */
+}
+
+/*
+ *     Insert an sk_buff at the start of a list.
+ */
+    
+void skb_queue_head(struct sk_buff *volatile* list,struct sk_buff *newsk)
+{
+       unsigned long flags;
+       
+       IS_SKB(newsk);  
+       if(newsk->list)
+               printk("Suspicious queue head: sk_buff on list!\n");
+       save_flags(flags);
+       cli();
+       newsk->list=list;
+       
+       newsk->next=*list;
+       
+       if(*list)
+               newsk->prev=(*list)->prev;
+       else
+               newsk->prev=newsk;
+       newsk->prev->next=newsk;
+       newsk->next->prev=newsk;
+       IS_SKB(newsk->prev);
+       IS_SKB(newsk->next);
+       *list=newsk;
+       restore_flags(flags);
+}
+
+/*
+ *     Insert an sk_buff at the end of a list.
+ */
+void skb_queue_tail(struct sk_buff *volatile* list, struct sk_buff *newsk)
+{
+       unsigned long flags;
+       
+       if(newsk->list)
+               printk("Suspicious queue tail: sk_buff on list!\n");
+       
+       IS_SKB(newsk);
+       save_flags(flags);
+       cli();
+
+       newsk->list=list;
+       if(*list)
+       {
+               (*list)->prev->next=newsk;
+               newsk->prev=(*list)->prev;
+               newsk->next=*list;
+               (*list)->prev=newsk;
+       }
+       else
+       {
+               newsk->next=newsk;
+               newsk->prev=newsk;
+               *list=newsk;
+       }
+       IS_SKB(newsk->prev);
+       IS_SKB(newsk->next);            
+       restore_flags(flags);
+
+}
+
+/*
+ *     Remove an sk_buff from a list. This routine is also interrupt safe
+ *     so you can grab read and free buffers as another process adds them.
+ */
+struct sk_buff *skb_dequeue(struct sk_buff *volatile* list)
+{
+       long flags;
+       struct sk_buff *result;
+       
+       save_flags(flags);
+       cli();
+       
+       if(*list==NULL)
+       {
+               restore_flags(flags);
+               return(NULL);
+       }
+       
+       result=*list;
+       if(result->next==result)
+               *list=NULL;
+       else
+       {
+               result->next->prev=result->prev;
+               result->prev->next=result->next;
+               *list=result->next;
+       }
+
+       IS_SKB(result);
+       restore_flags(flags);
+       
+       if(result->list!=list)
+               printk("Dequeued packet has invalid list pointer\n");
+
+       result->list=0;
+       result->next=0;
+       result->prev=0;
+       return(result);
+}
+
+/*
+ *     Insert a packet before another one in a list.
+ */
+void skb_insert(struct sk_buff *old, struct sk_buff *newsk)
+{
+       unsigned long flags;
+
+       IS_SKB(old);
+       IS_SKB(newsk);
+               
+       if(!old->list)
+               printk("insert before unlisted item!\n");
+       if(newsk->list)
+               printk("inserted item is already on a list.\n");
+               
+       save_flags(flags);
+       cli();
+       newsk->list=old->list;
+       newsk->next=old;
+       newsk->prev=old->prev;
+       newsk->next->prev=newsk;
+       newsk->prev->next=newsk;
+       
+       restore_flags(flags);
+}
+
+/*
+ *     Place a packet after a given packet in a list.
+ */
+void skb_append(struct sk_buff *old, struct sk_buff *newsk)
+{
+       unsigned long flags;
+       
+       IS_SKB(old);
+       IS_SKB(newsk);
+
+       if(!old->list)
+               printk("append before unlisted item!\n");
+       if(newsk->list)
+               printk("append item is already on a list.\n");
+               
+       save_flags(flags);
+       cli();
+       newsk->list=old->list;
+       newsk->prev=old;
+       newsk->next=old->next;
+       newsk->next->prev=newsk;
+       newsk->prev->next=newsk;
+       
+       restore_flags(flags);
+}
+
+/*
+ *     Remove an sk_buff from its list. Works even without knowing the list it
+ *     is sitting on, which can be handy at times. It also means that THE LIST
+ *     MUST EXIST when you unlink. Thus a list must have its contents unlinked
+ *     _FIRST_.
+ */
+void skb_unlink(struct sk_buff *skb)
+{
+       unsigned long flags;
+       save_flags(flags);
+       cli();
+
+       IS_SKB(skb);
+       
+       if(skb->list)
+       {
+               skb->next->prev=skb->prev;
+               skb->prev->next=skb->next;
+               if(*skb->list==skb)
+               {
+                       if(skb->next==skb)
+                               *skb->list=NULL;
+                       else
+                               *skb->list=skb->next;
+               }
+               skb->next=0;
+               skb->prev=0;
+               skb->list=0;
+       }
+       restore_flags(flags);
+}
+
+/*
+ *     An skbuff list has had its head reassigned. Move all the list
+ *     pointers. Must be called with ints off during the whole head
+ *     shifting
+ */
+
+void skb_new_list_head(struct sk_buff *volatile* list)
+{
+       struct sk_buff *skb=skb_peek(list);
+       if(skb!=NULL)
+       {
+               do
+               {
+                       IS_SKB(skb);
+                       skb->list=list;
+                       skb=skb->next;
+               }
+               while(skb!=*list);
+       }
+}
+                       
+/*
+ *     Peek an sk_buff. Unlike most other operations you _MUST_
+ *     be careful with this one. A peek leaves the buffer on the
+ *     list and someone else may run off with it. For an interrupt
+ *     type system cli() peek the buffer copy the data and sti();
+ */
+
+struct sk_buff *skb_peek(struct sk_buff *volatile* list)
+{
+       return *list;
+}
+
+/*
+ *     Get a clone of an sk_buff. This is the safe way to peek at
+ *     a socket queue without accidents. Its a bit long but most
+ *     of it acutally ends up as tiny bits of inline assembler
+ *     anyway. Only the memcpy of upto 4K with ints off is not
+ *     as nice as I'd like.
+ */
+struct sk_buff *skb_peek_copy(struct sk_buff *volatile* list)
+{
+       struct sk_buff *orig,*newsk;
+       unsigned long flags;
+       unsigned int len;
+       /* Now for some games to avoid races */
+       
+       do
+       {
+               save_flags(flags);
+               cli();
+               orig=skb_peek(list);
+               if(orig==NULL)
+               {
+                       restore_flags(flags);
+                       return NULL;
+               }
+               IS_SKB(orig);
+               len=orig->truesize;
+               restore_flags(flags);
+
+               newsk=alloc_skb(len,GFP_KERNEL);        /* May sleep */
+
+               if(newsk==NULL)         /* Oh dear... not to worry */
+                       return NULL;
+       
+               save_flags(flags);
+               cli();
+               if(skb_peek(list)!=orig)        /* List changed go around another time */
+               {
+                       restore_flags(flags);
+                       newsk->sk=NULL;
+                       newsk->free=1;
+                       newsk->mem_addr=newsk;
+                       newsk->mem_len=len;
+                       kfree_skb(newsk, FREE_WRITE);
+                       continue;
+               }
+               
+               IS_SKB(orig);
+               IS_SKB(newsk);
+               memcpy(newsk,orig,len);
+               newsk->list=NULL;
+               newsk->magic=0;
+               newsk->next=NULL;
+               newsk->prev=NULL;
+               newsk->mem_addr=newsk;
+               newsk->h.raw+=((char *)newsk-(char *)orig);
+               newsk->link3=NULL;
+               newsk->sk=NULL;
+               newsk->free=1;
+       }
+       while(0);
+       
+       restore_flags(flags);
+       return(newsk);
+}      
+       
+/*
+ *     Free an sk_buff. This still knows about things it should
+ *     not need to like protocols and sockets.
+ */
+
+void kfree_skb(struct sk_buff *skb, int rw)
+{
+  if (skb == NULL) {
+       printk("kfree_skb: skb = NULL\n");
+       return;
+  }
+  IS_SKB(skb);
+  if(skb->free == 2)
+       printk("Warning: kfree_skb passed an skb that nobody set the free flag on!\n");
+  if(skb->list)
+       printk("Warning: kfree_skb passed an skb still on a list.\n");
+  skb->magic = 0;
+  if (skb->sk) 
+  {
+        if(skb->sk->prot!=NULL)
+        {
+               if (rw)
+                       skb->sk->prot->rfree(skb->sk, skb->mem_addr, skb->mem_len);
+               else
+                       skb->sk->prot->wfree(skb->sk, skb->mem_addr, skb->mem_len);
+
+       }
+       else
+       {
+               /* Non INET - default wmalloc/rmalloc handler */
+               if (rw)
+                       skb->sk->rmem_alloc-=skb->mem_len;
+               else
+                       skb->sk->wmem_alloc-=skb->mem_len;
+               if(!skb->sk->dead)
+                       wake_up(skb->sk->sleep);
+               kfree_skbmem(skb->mem_addr,skb->mem_len);
+       }
+  } 
+  else 
+       kfree_skbmem(skb->mem_addr, skb->mem_len);
+}
+
+/*
+ *     Allocate a new skbuff. We do this ourselves so we can fill in a few 'private'
+ *     fields and also do memory statistics to find all the [BEEP] leaks.
+ */
+ struct sk_buff *alloc_skb(unsigned int size,int priority)
+ {
+       struct sk_buff *skb=(struct sk_buff *)kmalloc(size,priority);
+       if(skb==NULL)
+               return NULL;
+       skb->free= 2;   /* Invalid so we pick up forgetful users */
+       skb->list= 0;   /* Not on a list */
+       skb->truesize=size;
+       skb->mem_len=size;
+       skb->mem_addr=skb;
+       skb->fraglist=NULL;
+       net_memory+=size;
+       net_skbcount++;
+       skb->magic_debug_cookie=SK_GOOD_SKB;
+       skb->users=0;
+       return skb;
+ }
+
+/*
+ *     Free an skbuff by memory
+ */    
+
+void kfree_skbmem(void *mem,unsigned size)
+{
+       struct sk_buff *x=mem;
+       IS_SKB(x);
+       if(x->magic_debug_cookie==SK_GOOD_SKB)
+       {
+               x->magic_debug_cookie=SK_FREED_SKB;
+               kfree_s(mem,size);
+               net_skbcount--;
+               net_memory-=size;
+       }
+}
diff --git a/net/inet/skbuff.h b/net/inet/skbuff.h
new file mode 100644 (file)
index 0000000..6d5f879
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * INET                An implementation of the TCP/IP protocol suite for the LINUX
+ *             operating system.  INET is implemented using the  BSD Socket
+ *             interface as the means of communication with the user level.
+ *
+ *             Definitions for the 'struct sk_buff' memory handlers.
+ *
+ * Version:    @(#)skbuff.h    1.0.4   05/20/93
+ *
+ * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
+ *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *             Corey Minyard <wf-rch!minyard@relay.EU.net>
+ *
+ * Fixes:
+ *             Alan Cox                :       Volatiles (this makes me unhappy - we want proper asm linked list stuff)
+ *             Alan Cox                :       Declaration for new primitives
+ *             Alan Cox                :       Fraglist support (idea by Donald Becker)
+ *             Alan Cox                :       'users' counter. Combines with datagram changes to avoid skb_peek_copy
+ *                                             being used.
+ *
+ *             This program is free software; you can redistribute it and/or
+ *             modify it under the terms of the GNU General Public License
+ *             as published by the Free Software Foundation; either version
+ *             2 of the License, or (at your option) any later version.
+ */
+#ifndef _SKBUFF_H
+#define _SKBUFF_H
+#include <linux/malloc.h>
+
+#ifdef CONFIG_IPX
+#include "ipx.h"
+#endif
+
+#define HAVE_ALLOC_SKB         /* For the drivers to know */
+
+
+#define FREE_READ      1
+#define FREE_WRITE     0
+
+
+struct sk_buff {
+  unsigned long                        magic_debug_cookie;
+  struct sk_buff               *volatile next;
+  struct sk_buff               *volatile prev;
+  struct sk_buff               *volatile link3;
+  struct sk_buff               *volatile* list;
+  struct sock                  *sk;
+  volatile unsigned long       when;   /* used to compute rtt's        */
+  struct device                        *dev;
+  void                         *mem_addr;
+  union {
+       struct tcphdr   *th;
+       struct ethhdr   *eth;
+       struct iphdr    *iph;
+       struct udphdr   *uh;
+       struct arphdr   *arp;
+       unsigned char   *raw;
+       unsigned long   seq;
+#ifdef CONFIG_IPX      
+       ipx_packet      *ipx;
+#endif 
+  } h;
+  unsigned long                        mem_len;
+  unsigned long                len;
+  unsigned long                        fraglen;
+  struct sk_buff               *fraglist;      /* Fragment list */
+  unsigned long                        truesize;
+  unsigned long                saddr;
+  unsigned long                daddr;
+  int                          magic;
+  volatile char                acked,
+                               used,
+                               free,
+                               arp,
+                               urg_used;
+  unsigned char                        tries,lock;     /* Lock is now unused */
+  unsigned short               users;          /* User count - see datagram.c (and soon seqpacket.c/stream.c) */
+};
+
+#define SK_WMEM_MAX    8192
+#define SK_RMEM_MAX    32767
+
+#define SK_FREED_SKB   0x0DE2C0DE
+#define SK_GOOD_SKB    0xDEC0DED1
+
+extern void                    print_skb(struct sk_buff *);
+extern void                    kfree_skb(struct sk_buff *skb, int rw);
+extern void                    skb_queue_head(struct sk_buff * volatile *list,struct sk_buff *buf);
+extern void                    skb_queue_tail(struct sk_buff * volatile *list,struct sk_buff *buf);
+extern struct sk_buff *                skb_dequeue(struct sk_buff * volatile *list);
+extern void                    skb_insert(struct sk_buff *old,struct sk_buff *newsk);
+extern void                    skb_append(struct sk_buff *old,struct sk_buff *newsk);
+extern void                    skb_unlink(struct sk_buff *buf);
+extern void                    skb_new_list_head(struct sk_buff *volatile* list);
+extern struct sk_buff *                skb_peek(struct sk_buff * volatile *list);
+extern struct sk_buff *                skb_peek_copy(struct sk_buff * volatile *list);
+extern struct sk_buff *                alloc_skb(unsigned int size, int priority);
+extern void                    kfree_skbmem(void *mem, unsigned size);
+
+extern void                    skb_check(struct sk_buff *skb,int, char *);
+#define IS_SKB(skb)    skb_check((skb),__LINE__,__FILE__)
+
+extern struct sk_buff *                skb_recv_datagram(struct sock *sk,unsigned flags,int noblock, int *err);
+extern int                     datagram_select(struct sock *sk, int sel_type, select_table *wait);
+extern void                    skb_copy_datagram(struct sk_buff *from, int offset, char *to,int size);
+extern void                    skb_free_datagram(struct sk_buff *skb);
+#endif /* _SKBUFF_H */
diff --git a/net/inet/sockinet.c b/net/inet/sockinet.c
deleted file mode 100644 (file)
index 004d63c..0000000
+++ /dev/null
@@ -1,1636 +0,0 @@
-/*
- * INET                An implementation of the TCP/IP protocol suite for the LINUX
- *             operating system.  INET is implemented using the  BSD Socket
- *             interface as the means of communication with the user level.
- *
- *             SOCK - AF_INET protocol family socket handler.
- *
- * Version:    @(#)sock.c      1.28    24/12/93
- *
- * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
- *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- *             Florian La Roche, <flla@stud.uni-sb.de>
- *
- * Fixes:
- *             Alan Cox        :       Numerous verify_area() problems
- *             Alan Cox        :       Connecting on a connecting socket
- *                                     now returns an error for tcp.
- *             Alan Cox        :       sock->protocol is set correctly.
- *                                     and is not sometimes left as 0.
- *             Alan Cox        :       connect handles icmp errors on a
- *                                     connect properly. Unfortunately there
- *                                     is a restart syscall nasty there. I
- *                                     can't match BSD without hacking the C
- *                                     library. Ideas urgently sought!
- *             Alan Cox        :       Disallow bind() to addresses that are
- *                                     not ours - especially broadcast ones!!
- *             Alan Cox        :       Socket 1024 _IS_ ok for users. (fencepost)
- *             Alan Cox        :       sock_wfree/sock_rfree don't destroy sockets,
- *                                     instead they leave that for the DESTROY timer.
- *             Alan Cox        :       Clean up error flag in accept
- *             Alan Cox        :       TCP ack handling is buggy, the DESTROY timer
- *                                     was buggy. Put a remove_sock() in the handler
- *                                     for memory when we hit 0. Also altered the timer
- *                                     code. The ACK stuff can wait and needs major 
- *                                     TCP layer surgery.
- *             Alan Cox        :       Fixed TCP ack bug, removed remove sock
- *                                     and fixed timer/inet_bh race.
- *             Alan Cox        :       Added zapped flag for TCP
- *             Alan Cox        :       Move kfree_skb into skbuff.c and tidied up surplus code
- *             Alan Cox        :       for new sk_buff allocations wmalloc/rmalloc now call alloc_skb
- *             Alan Cox        :       kfree_s calls now are kfree_skbmem so we can track skb resources
- *             Alan Cox        :       Supports socket option broadcast now as does udp. Packet and raw need fixing.
- *             Alan Cox        :       Added RCVBUF,SNDBUF size setting. It suddenely occured to me how easy it was so...
- *             Rick Sladkey    :       Relaxed UDP rules for matching packets.
- *             C.E.Hawkins     :       IFF_PROMISC/SIOCGHWADDR support
- *     Pauline Middelink       :       Pidentd support
- *             Alan Cox        :       Fixed connect() taking signals I think.
- *             Alan Cox        :       SO_LINGER supported
- *             Alan Cox        :       Error reporting fixes
- *             Anonymous       :       inet_create tidied up (sk->reuse setting)
- *             Alan Cox        :       Tidy up for release.
- *             Alan Cox        :       Moved this to sockinet.c and removed generic code.
- *             Alan Cox        :       inet sockets don't set sk->type!
- *
- *
- * To Fix:
- *
- *
- *             This program is free software; you can redistribute it and/or
- *             modify it under the terms of the GNU General Public License
- *             as published by the Free Software Foundation; either version
- *             2 of the License, or (at your option) any later version.
- */
-
-#include <linux/config.h>
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/socket.h>
-#include <linux/in.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/string.h>
-#include <linux/sockios.h>
-#include <linux/net.h>
-#include <linux/fcntl.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-
-#include <asm/segment.h>
-#include <asm/system.h>
-
-#include "inet.h"
-#include "devinet.h"
-#include "ip.h"
-#include "protocol.h"
-#include "arp.h"
-#include "route.h"
-#include "tcp.h"
-#include "udp.h"
-#include "skbuff.h"
-#include "sockinet.h"
-#include "raw.h"
-#include "icmp.h"
-
-
-int inet_debug = DBG_OFF;              /* INET module debug flag       */
-
-
-#define min(a,b)       ((a)<(b)?(a):(b))
-
-extern struct proto packet_prot;
-
-
-
-static int sk_inuse(struct proto *prot, int num)
-{
-       struct sock *sk;
-
-       for(sk = prot->sock_array[num & (SOCK_ARRAY_SIZE -1 )];sk != NULL;sk=sk->next) 
-       {
-               if (sk->num == num) return(1);
-       }
-       return(0);
-}
-
-
-unsigned short get_new_socknum(struct proto *prot, unsigned short base)
-{
-       static int start=0;
-
-       /*
-        * Used to cycle through the port numbers so the
-        * chances of a confused connection drop.
-        */
-       int i, j;
-       int best = 0;
-       int size = 32767; /* a big num. */
-       struct sock *sk;
-
-       if (base == 0) 
-               base = PROT_SOCK+1+(start % 1024);
-       if (base <= PROT_SOCK) 
-       {
-               base += PROT_SOCK+(start % 1024);
-       }
-
-       /* Now look through the entire array and try to find an empty ptr. */
-       for(i=0; i < SOCK_ARRAY_SIZE; i++) 
-       {
-               j = 0;
-               sk = prot->sock_array[(i+base+1) &(SOCK_ARRAY_SIZE -1)];
-               while(sk != NULL) 
-               {
-                       sk = sk->next;
-                       j++;
-               }
-               if (j == 0) 
-               {
-                       start =(i+1+start )%1024;
-                       DPRINTF((DBG_INET, "get_new_socknum returning %d, start = %d\n",
-                                                       i + base + 1, start));
-                       return(i+base+1);
-               }
-               if (j < size) 
-               {
-                       best = i;
-                       size = j;
-               }
-       }
-
-       /* Now make sure the one we want is not in use. */
-       while(sk_inuse(prot, base +best+1)) 
-       {
-               best += SOCK_ARRAY_SIZE;
-       }
-       DPRINTF((DBG_INET, "get_new_socknum returning %d, start = %d\n",
-                                               best + base + 1, start));
-       return(best+base+1);
-}
-
-
-void put_sock(unsigned short num, struct sock *sk)
-{
-       struct sock *sk1;
-       struct sock *sk2;
-       int mask;
-
-       DPRINTF((DBG_INET, "put_sock(num = %d, sk = %X\n", num, sk));
-       sk->num = num;
-       sk->next = NULL;
-       num = num &(SOCK_ARRAY_SIZE -1);
-
-       /* We can't have an interupt re-enter here. */
-       cli();
-       if (sk->prot->sock_array[num] == NULL) 
-       {
-               sk->prot->sock_array[num] = sk;
-               sti();
-               return;
-       }
-       sti();
-       for(mask = 0xff000000; mask != 0xffffffff; mask = (mask >> 8) | mask) 
-       {
-               if ((mask & sk->saddr) &&
-                   (mask & sk->saddr) != (mask & 0xffffffff)) 
-               {
-                       mask = mask << 8;
-                       break;
-               }
-       }
-       DPRINTF((DBG_INET, "mask = %X\n", mask));
-
-       cli();
-       sk1 = sk->prot->sock_array[num];
-       for(sk2 = sk1; sk2 != NULL; sk2=sk2->next) 
-       {
-               if (!(sk2->saddr & mask)) 
-               {
-                       if (sk2 == sk1) 
-                       {
-                               sk->next = sk->prot->sock_array[num];
-                               sk->prot->sock_array[num] = sk;
-                               sti();
-                               return;
-                       }
-                       sk->next = sk2;
-                       sk1->next= sk;
-                       sti();
-                       return;
-               }
-               sk1 = sk2;
-       }
-
-       /* Goes at the end. */
-       sk->next = NULL;
-       sk1->next = sk;
-       sti();
-}
-
-
-static void remove_sock(struct sock *sk1)
-{
-       struct sock *sk2;
-
-       DPRINTF((DBG_INET, "remove_sock(sk1=%X)\n", sk1));
-       
-       if (!sk1) 
-       {
-               printk("sock.c: remove_sock: sk1 == NULL\n");
-               return;
-       }       
-
-       if (!sk1->prot) 
-       {
-               printk("sock.c: remove_sock: sk1->prot == NULL\n");
-               return;
-       }
-
-       /* We can't have this changing out from under us. */
-       cli();
-       sk2 = sk1->prot->sock_array[sk1->num &(SOCK_ARRAY_SIZE -1)];
-       if (sk2 == sk1) 
-       {
-               sk1->prot->sock_array[sk1->num &(SOCK_ARRAY_SIZE -1)] = sk1->next;
-               sti();
-               return;
-       }
-
-       while(sk2 && sk2->next != sk1) 
-       {
-               sk2 = sk2->next;
-       }
-
-       if (sk2) 
-       {
-               sk2->next = sk1->next;
-               sti();
-               return;
-       }
-  
-       sti();
-
-       if (sk1->num != 0) 
-               DPRINTF((DBG_INET, "remove_sock: sock not found.\n"));
-}
-
-
-void destroy_sock(struct sock *sk)
-{
-       struct sk_buff *skb;
-
-       DPRINTF((DBG_INET, "destroying socket %X\n", sk));
-       sk->inuse = 1;                  /* just to be safe. */
-
-       /* Incase it's sleeping somewhere. */
-       if (!sk->dead) 
-               wake_up(sk->sleep);
-
-       remove_sock(sk);
-  
-       /* Now we can no longer get new packets. */
-       delete_timer(sk);
-
-
-       if (sk->send_tmp != NULL) 
-       {
-               IS_SKB(sk->send_tmp);
-               kfree_skb(sk->send_tmp, FREE_WRITE);
-       }
-
-       /* Cleanup up the write buffer. */
-       for(skb = sk->wfront; skb != NULL; ) 
-       {
-               struct sk_buff *skb2;
-
-               skb2=(struct sk_buff *)skb->next;
-               if (skb->magic != TCP_WRITE_QUEUE_MAGIC) 
-               {
-                       printk("sock.c:destroy_sock write queue with bad magic(%X)\n",
-                                                               skb->magic);
-                       break;
-               }
-               IS_SKB(skb);
-               kfree_skb(skb, FREE_WRITE);
-               skb = skb2;
-       }
-
-       sk->wfront = NULL;
-       sk->wback = NULL;
-
-       if (sk->rqueue != NULL) 
-       {
-               while((skb=skb_dequeue(&sk->rqueue))!=NULL)
-               {
-               /*
-                * This will take care of closing sockets that were
-                * listening and didn't accept everything.
-                */
-                       if (skb->sk != NULL && skb->sk != sk) 
-                       {
-                               IS_SKB(skb);
-                               skb->sk->dead = 1;
-                               skb->sk->prot->close(skb->sk, 0);
-                       }
-                       IS_SKB(skb);
-                       kfree_skb(skb, FREE_READ);
-               }
-       }
-       sk->rqueue = NULL;
-
-  /* Now we need to clean up the send head. */
-       for(skb = sk->send_head; skb != NULL; ) 
-       {
-               struct sk_buff *skb2;
-
-               /*
-                * We need to remove skb from the transmit queue,
-                * or maybe the arp queue.
-                */
-               cli();
-
-               if (skb->next != NULL) 
-               {
-                       IS_SKB(skb);
-                       skb_unlink(skb);
-               }
-
-               skb->dev = NULL;
-               sti();
-               skb2 = (struct sk_buff *)skb->link3;
-               kfree_skb(skb, FREE_WRITE);
-               skb = skb2;
-       }       
-       sk->send_head = NULL;
-
-       /* And now the backlog. */
-       if (sk->back_log != NULL) 
-       {
-               /* this should never happen. */
-               printk("Socket Error: Socket destroyed with data backlog.\n");
-               cli();
-               skb = (struct sk_buff *)sk->back_log;
-               do 
-               {
-                       struct sk_buff *skb2;
-       
-                       skb2 = (struct sk_buff *)skb->next;
-                       kfree_skb(skb, FREE_READ);
-                       skb = skb2;
-               }
-               while(skb != sk->back_log);
-               sti();
-       }
-       sk->back_log = NULL;
-
-       /* Now if it has a half accepted/ closed socket. */
-       if (sk->pair) 
-       {
-               sk->pair->dead = 1;
-               sk->pair->prot->close(sk->pair, 0);
-               sk->pair = NULL;
-       }
-
-  /*
-   * Now if everything is gone we can free the socket
-   * structure, otherwise we need to keep it around until
-   * everything is gone.
-   */
-         if (sk->rmem_alloc == 0 && sk->wmem_alloc == 0) 
-         {
-               kfree_s((void *)sk,sizeof(*sk));
-         } 
-         else 
-         {
-               /* this should never happen. */
-               /* actually it can if an ack has just been sent. */
-               DPRINTF((DBG_INET, "possible memory leak in socket = %X\n", sk));
-               sk->destroy = 1;
-               sk->ack_backlog = 0;
-               sk->inuse = 0;
-               reset_timer(sk, TIME_DESTROY, SOCK_DESTROY_TIME);
-       }
-       DPRINTF((DBG_INET, "leaving destroy_sock\n"));
-}
-
-
-static int inet_fcntl(struct socket *sock, unsigned int cmd, unsigned long arg)
-{
-       struct sock *sk;
-
-       sk = (struct sock *) sock->data;
-       if (sk == NULL) 
-       {
-               printk("Warning: sock->data = NULL: %d\n" ,__LINE__);
-               return(0);
-       }
-
-       switch(cmd) 
-       {
-               case F_SETOWN:
-               /*
-                * This is a little restrictive, but it's the only
-                * way to make sure that you can't send a sigurg to
-                * another process.
-                */
-                       if (!suser() && current->pgrp != -arg && current->pid != arg) 
-                               return(-EPERM);
-                       sk->proc = arg;
-                       return(0);
-                       case F_GETOWN:
-                       return(sk->proc);
-               default:
-                       return(-EINVAL);
-       }
-}
-
-
-/*
- *     Set socket options on an inet socket.
- */
-static int inet_setsockopt(struct socket *sock, int level, int optname,
-                   char *optval, int optlen)
-{
-       struct sock *sk = (struct sock *) sock->data;  
-       if (level == SOL_SOCKET)
-               return sock_setsockopt(sk,level,optname,optval,optlen);
-       if (sk->prot->setsockopt==NULL)
-               return(-EOPNOTSUPP);
-       else
-               return sk->prot->setsockopt(sk,level,optname,optval,optlen);
-}
-
-
-
-
-static int inet_getsockopt(struct socket *sock, int level, int optname,
-                   char *optval, int *optlen)
-{
-       struct sock *sk = sock->data;   
-       if (level == SOL_SOCKET) 
-               return sock_getsockopt(sk,level,optname,optval,optlen);
-       if(sk->prot->getsockopt==NULL)          
-               return(-EOPNOTSUPP);
-       else
-               return sk->prot->getsockopt(sk,level,optname,optval,optlen);
-}
-
-
-
-static int inet_listen(struct socket *sock, int backlog)
-{
-       struct sock *sk;
-
-       sk = (struct sock *) sock->data;
-       if (sk == NULL) 
-       {
-               printk("Warning: sock->data = NULL: %d\n" ,__LINE__);
-               return(0);
-       }
-       
-       /* No listen() on a busy socket. */
-       
-       if(sk->state != TCP_CLOSE)
-               return -EINVAL;
-
-       /* We may need to bind the socket. */
-       if (sk->num == 0) 
-       {
-               sk->num = get_new_socknum(sk->prot, 0);
-               if (sk->num == 0)       
-                       return(-EAGAIN);
-               put_sock(sk->num, sk);
-               sk->dummy_th.source = ntohs(sk->num);
-       }
-       /* Some sanity checks here are a good idea */
-       if(backlog<0)
-               return -EINVAL;
-       /* Pick a number, any number 8-) */
-       if(backlog>5)
-               backlog=5;
-
-       /* We might as well re use these. */ 
-       sk->max_ack_backlog = backlog;
-       if (sk->state != TCP_LISTEN) 
-       {
-               sk->ack_backlog = 0;
-               sk->state = TCP_LISTEN;
-       }
-       return(0);
-}
-
-/*
- *     Default callbacks for user INET sockets. These just wake up
- *     the user owning the socket.
- */
-
-static void def_callback1(struct sock *sk)
-{
-       if(!sk->dead)
-               wake_up(sk->sleep);
-}
-
-static void def_callback2(struct sock *sk,int len)
-{
-       if(!sk->dead)
-               wake_up(sk->sleep);
-}
-
-
-/*
- *     Create an inet socket. Note that sock=NULL is now legal, and means a kernel
- *     created socket.
- */
-static int inet_create(struct socket *sock, int protocol)
-{
-       struct sock *sk;
-       struct proto *prot;
-       int err;
-
-       sk = (struct sock *) kmalloc(sizeof(*sk), GFP_KERNEL);
-       
-       if (sk == NULL) 
-               return(-ENOMEM);
-       sk->num = 0;
-       sk->reuse = 0;
-       switch(sock->type) 
-       {
-               case SOCK_STREAM:
-               case SOCK_SEQPACKET:
-                       if (protocol && protocol != IPPROTO_TCP) 
-                       {
-                               kfree_s((void *)sk, sizeof(*sk));
-                               return(-EPROTONOSUPPORT);
-                       }
-                       protocol = IPPROTO_TCP;
-                       sk->no_check = TCP_NO_CHECK;
-                       prot = &tcp_prot;
-                       break;
-
-               case SOCK_DGRAM:
-                       if (protocol && protocol != IPPROTO_UDP) 
-                       {
-                               kfree_s((void *)sk, sizeof(*sk));
-                               return(-EPROTONOSUPPORT);
-                       }
-                       protocol = IPPROTO_UDP;
-                       sk->no_check = UDP_NO_CHECK;
-                       prot=&udp_prot;
-                       break;
-      
-               case SOCK_RAW:
-                       if (!suser()) 
-                       {
-                               kfree_s((void *)sk, sizeof(*sk));
-                               return(-EPERM);
-                       }
-                       if (!protocol) 
-                       {
-                               kfree_s((void *)sk, sizeof(*sk));
-                               return(-EPROTONOSUPPORT);
-                       }
-                       prot = &raw_prot;
-                       sk->reuse = 1;
-                       sk->no_check = 0;       /*
-                                                * Doesn't matter no checksum is
-                                                * preformed anyway.
-                                                */
-                       sk->num = protocol;
-                       break;
-
-               case SOCK_PACKET:
-                       if (!suser()) 
-                       {
-                               kfree_s((void *)sk, sizeof(*sk));
-                               return(-EPERM);
-                       }
-                       if (!protocol) 
-                       {
-                               kfree_s((void *)sk, sizeof(*sk));
-                               return(-EPROTONOSUPPORT);
-                       }
-                       prot = &packet_prot;
-                       sk->reuse = 1;
-                       sk->no_check = 0;       /* Doesn't matter no checksum is
-                                                * preformed anyway.
-                                                */
-                       sk->num = protocol;
-                       break;
-
-               default:
-                       kfree_s((void *)sk, sizeof(*sk));
-                       return(-ESOCKTNOSUPPORT);
-       }
-       sk->socket = sock;
-       sk->type = sock->type;
-       sk->protocol = protocol;
-       sk->wmem_alloc = 0;
-       sk->rmem_alloc = 0;
-       sk->sndbuf = SK_WMEM_MAX;
-       sk->rcvbuf = SK_RMEM_MAX;
-       sk->pair = NULL;
-       sk->opt = NULL;
-       sk->send_seq = 0;
-       sk->acked_seq = 0;
-       sk->copied_seq = 0;
-       sk->fin_seq = 0;
-       sk->proc = 0;
-       sk->rtt = TCP_WRITE_TIME;
-       sk->mdev = 0;
-       sk->backoff = 0;
-       sk->packets_out = 0;
-       sk->cong_window = 1; /* start with only sending one packet at a time. */
-       sk->exp_growth = 1;  /* if set cong_window grow exponentially every time
-                                 we get an ack. */
-       sk->urginline = 0;
-       sk->intr = 0;
-       sk->linger = 0;
-       sk->destroy = 0;
-
-       sk->priority = 1;
-       sk->shutdown = 0;
-       sk->urg = 0;
-       sk->keepopen = 0;
-       sk->zapped = 0;
-       sk->done = 0;
-       sk->ack_backlog = 0;
-       sk->window = 0;
-       sk->bytes_rcv = 0;
-       sk->state = TCP_CLOSE;
-       sk->dead = 0;
-       sk->ack_timed = 0;
-       sk->send_tmp = NULL;
-       sk->mss = 0; /* we will try not to send any packets smaller than this. */
-       sk->debug = 0;
-       
-       /* this is how many unacked bytes we will accept for this socket.  */
-       sk->max_unacked = 2048;         /* needs to be at most 2 full packets. */
-
-       /* how many packets we should send before forcing an ack. 
-        * if this is set to zero it is the same as sk->delay_acks = 0 
-        */
-       sk->max_ack_backlog = 0;
-       sk->inuse = 0;
-       sk->delay_acks = 0;
-       sk->wback = NULL;
-       sk->wfront = NULL;
-       sk->rqueue = NULL;
-       sk->mtu = 576;  /* This is a reasonable typical choice. RFC791 guarantees this is acceptable */
-       sk->prot = prot;
-       sk->sleep = sock->wait;
-       sk->daddr = 0;
-       sk->saddr = my_addr();
-       sk->err = 0;
-       sk->next = NULL;
-       sk->pair = NULL;
-       sk->send_tail = NULL;
-       sk->send_head = NULL;
-       sk->timeout = 0;
-       sk->broadcast = 0;
-       sk->timer.data = (unsigned long)sk;
-       sk->timer.function = &net_timer;
-       sk->back_log = NULL;
-       sk->blog = 0;
-       sock->data =(void *) sk;
-       sk->dummy_th.doff = sizeof(sk->dummy_th)/4;
-       sk->dummy_th.res1=0;
-       sk->dummy_th.res2=0;
-       sk->dummy_th.urg_ptr = 0;
-       sk->dummy_th.fin = 0;
-       sk->dummy_th.syn = 0;
-       sk->dummy_th.rst = 0;
-       sk->dummy_th.psh = 0;
-       sk->dummy_th.ack = 0;
-       sk->dummy_th.urg = 0;
-       sk->dummy_th.dest = 0;
-       
-       sk->ip_tos=0;
-       sk->ip_ttl=64;
-       
-       sk->state_change = def_callback1;
-       sk->data_ready = def_callback2;
-       sk->write_space = def_callback1;
-       sk->error_report = def_callback1;
-
-       if (sk->num) 
-       {
-               /*
-                * It assumes that any protocol which allows
-                * the user to assign a number at socket
-                * creation time automatically
-                * shares.
-                */
-               put_sock(sk->num, sk);
-               sk->dummy_th.source = ntohs(sk->num);
-       }
-
-       if (sk->prot->init) 
-       {
-               err = sk->prot->init(sk);
-               if (err != 0) 
-               {
-                       destroy_sock(sk);
-                       return(err);
-               }
-       }
-       return(0);
-}
-
-
-static int inet_dup(struct socket *newsock, struct socket *oldsock)
-{
-       return(inet_create(newsock,((struct sock *)(oldsock->data))->protocol));
-}
-
-
-/* The peer socket should always be NULL. */
-static int inet_release(struct socket *sock, struct socket *peer)
-{
-       struct sock *sk;
-
-       sk = (struct sock *) sock->data;
-       if (sk == NULL) 
-               return(0);
-
-       DPRINTF((DBG_INET, "inet_release(sock = %X, peer = %X)\n", sock, peer));
-       wake_up(sk->sleep);
-
-       /* Start closing the connection.  This may take a while. */
-       /*
-        * If linger is set, we don't return until the close
-        * is complete.  Other wise we return immediately. The
-        * actually closing is done the same either way.
-        */
-       if (sk->linger == 0) 
-       {
-               sk->prot->close(sk,0);
-               sk->dead = 1;
-       } 
-       else 
-       {
-               DPRINTF((DBG_INET, "sk->linger set.\n"));
-               sk->prot->close(sk, 0);
-               cli();
-               if (sk->lingertime)
-                       current->timeout = jiffies + HZ*sk->lingertime;
-               while(sk->state != TCP_CLOSE && sk->state != TCP_FIN_WAIT2 && sk->state !=TCP_TIME_WAIT && current->timeout>0) 
-               {
-                       interruptible_sleep_on(sk->sleep);
-                       if (current->signal & ~current->blocked) 
-                       {
-                               sti();
-                               current->timeout=0;
-                               return(-ERESTARTSYS);
-                       }
-               }
-               current->timeout=0;
-               sti();
-               sk->dead = 1;
-       }
-       sk->inuse = 1;
-
-  /* This will destroy it. */
-       release_sock(sk);
-       sock->data = NULL;
-       DPRINTF((DBG_INET, "inet_release returning\n"));
-       return(0);
-}
-
-
-/* this needs to be changed to dissallow
-   the rebinding of sockets.   What error
-   should it return? */
-
-static int inet_bind(struct socket *sock, struct sockaddr *uaddr,
-              int addr_len)
-{
-       struct sockaddr_in addr;
-       struct sock *sk, *sk2;
-       unsigned short snum;
-       int err;
-
-       sk = (struct sock *) sock->data;
-       if (sk == NULL) 
-       {
-               printk("Warning: sock->data = NULL: %d\n" ,__LINE__);
-               return(0);
-       }
-
-       /* check this error. */
-       if (sk->state != TCP_CLOSE) 
-               return(-EIO);
-       if (sk->num != 0) 
-               return(-EINVAL);
-
-       err=verify_area(VERIFY_READ, uaddr, addr_len);
-       if(err)
-               return err;
-       memcpy_fromfs(&addr, uaddr, min(sizeof(addr), addr_len));
-
-       snum = ntohs(addr.sin_port);
-       DPRINTF((DBG_INET, "bind sk =%X to port = %d\n", sk, snum));
-       sk = (struct sock *) sock->data;
-       if (snum == 0) 
-       {
-               snum = get_new_socknum(sk->prot, 0);
-       }
-       if (snum < PROT_SOCK && !suser()) 
-               return(-EACCES);
-
-       if (addr.sin_addr.s_addr!=0 && chk_addr(addr.sin_addr.s_addr)!=IS_MYADDR)
-               return(-EADDRNOTAVAIL); /* Source address MUST be ours! */
-       
-       if (chk_addr(addr.sin_addr.s_addr) || addr.sin_addr.s_addr == 0)
-               sk->saddr = addr.sin_addr.s_addr;
-
-       DPRINTF((DBG_INET, "sock_array[%d] = %X:\n", snum &(SOCK_ARRAY_SIZE -1),
-               sk->prot->sock_array[snum &(SOCK_ARRAY_SIZE -1)]));
-
-       /* Make sure we are allowed to bind here. */
-       cli();
-outside_loop:
-       for(sk2 = sk->prot->sock_array[snum & (SOCK_ARRAY_SIZE -1)];sk2 != NULL; sk2 = sk2->next) 
-       {
-               if (sk2->num != snum) 
-                       continue;
-               if (sk2->saddr != sk->saddr) 
-                       continue;
-               if (sk2->dead && !sk2->inuse)   /* Added in use check AC 24/12/93 */
-               {
-                       destroy_sock(sk2);
-                       goto outside_loop;
-               }
-               if (!sk->reuse) 
-               {
-                       sti();
-                       return(-EADDRINUSE);
-               }
-               if (sk2->num != snum) 
-                       continue;               /* more than one */
-               if (sk2->saddr != sk->saddr) 
-                       continue;       /* socket per slot ! -FB */
-               if (!sk2->reuse) 
-               {
-                       sti();
-                       return(-EADDRINUSE);
-               }
-       }
-       sti();
-
-       remove_sock(sk);
-       put_sock(snum, sk);
-       sk->dummy_th.source = ntohs(sk->num);
-       sk->daddr = 0;
-       sk->dummy_th.dest = 0;
-       return(0);
-}
-
-
-static int inet_connect(struct socket *sock, struct sockaddr * uaddr,
-                 int addr_len, int flags)
-{
-       struct sock *sk;
-       int err;
-
-       sock->conn = NULL;
-       sk = (struct sock *) sock->data;
-       if (sk == NULL) 
-       {
-               printk("Warning: sock->data = NULL: %d\n" ,__LINE__);
-               return(0);
-       }
-
-       if (sock->state == SS_CONNECTING && sk->state == TCP_ESTABLISHED)
-       {
-               sock->state = SS_CONNECTED;
-         /* Connection completing after a connect/EINPROGRESS/select/connect */
-               return 0;       /* Rock and roll */
-       }
-
-       if (sock->state == SS_CONNECTING && sk->protocol == IPPROTO_TCP && (flags & O_NONBLOCK))
-               return -EALREADY;       /* Connecting is currently in progress */
-       
-       if (sock->state != SS_CONNECTING) 
-       {
-               /* We may need to bind the socket. */
-               if (sk->num == 0) 
-               {
-                       sk->num = get_new_socknum(sk->prot, 0);
-                       if (sk->num == 0) 
-                               return(-EAGAIN);
-                       put_sock(sk->num, sk);
-                       sk->dummy_th.source = htons(sk->num);
-               }
-
-               if (sk->prot->connect == NULL) 
-                       return(-EOPNOTSUPP);
-  
-               err = sk->prot->connect(sk, (struct sockaddr_in *)uaddr, addr_len);
-               if (err < 0)
-                       return(err);
-  
-               sock->state = SS_CONNECTING;
-       }
-
-       if (sk->state != TCP_ESTABLISHED &&(flags & O_NONBLOCK)) 
-               return(-EINPROGRESS);
-
-       cli(); /* avoid the race condition */
-       while(sk->state == TCP_SYN_SENT || sk->state == TCP_SYN_RECV) 
-       {
-               interruptible_sleep_on(sk->sleep);
-               if (current->signal & ~current->blocked) 
-               {
-                       sti();
-                       return(-ERESTARTSYS);
-               }
-               /* This fixes a nasty in the tcp/ip code. There is a hideous hassle with
-                  icmp error packets wanting to close a tcp or udp socket. */
-               if(sk->err && sk->protocol == IPPROTO_TCP)
-               {
-                       sti();
-                       sock->state = SS_UNCONNECTED;
-                       err = -sk->err;
-                       sk->err=0;
-                       return err; /* set by tcp_err() */
-               }
-       }
-       sti();
-       sock->state = SS_CONNECTED;
-
-       if (sk->state != TCP_ESTABLISHED && sk->err) 
-       {
-               sock->state = SS_UNCONNECTED;
-               err=sk->err;
-               sk->err=0;
-               return(err);
-       }
-       return(0);
-}
-
-
-static int inet_socketpair(struct socket *sock1, struct socket *sock2)
-{
-       return(-EOPNOTSUPP);
-}
-
-
-static int inet_accept(struct socket *sock, struct socket *newsock, int flags)
-{
-       struct sock *sk1, *sk2;
-       int err;
-
-       sk1 = (struct sock *) sock->data;
-       if (sk1 == NULL) 
-       {
-               printk("Warning: sock->data = NULL: %d\n" ,__LINE__);
-               return(0);
-       }
-
-       /*
-        * We've been passed an extra socket.
-        * We need to free it up because the tcp module creates
-        * it's own when it accepts one.
-        */
-       
-       if (newsock->data) 
-               kfree_s(newsock->data, sizeof(struct sock));
-       newsock->data = NULL;
-
-       if (sk1->prot->accept == NULL) 
-               return(-EOPNOTSUPP);
-
-       /* Restore the state if we have been interrupted, and then returned. */
-       if (sk1->pair != NULL ) 
-       {
-               sk2 = sk1->pair;
-               sk1->pair = NULL;
-       } 
-       else 
-       {
-               sk2 = sk1->prot->accept(sk1,flags);
-               if (sk2 == NULL) 
-               {
-                       if (sk1->err <= 0)
-                               printk("Warning sock.c:sk1->err <= 0.  Returning non-error.\n");
-                       err=sk1->err;
-                       sk1->err=0;
-                       return(-err);
-               }
-       }
-       newsock->data = (void *)sk2;
-       sk2->sleep = newsock->wait;
-       newsock->conn = NULL;
-       if (flags & O_NONBLOCK) 
-               return(0);
-
-       cli(); /* avoid the race. */
-
-       while(sk2->state == TCP_SYN_RECV) 
-       {
-               interruptible_sleep_on(sk2->sleep);
-               if (current->signal & ~current->blocked) 
-               {
-                       sti();
-                       sk1->pair = sk2;
-                       sk2->sleep = NULL;
-                       newsock->data = NULL;
-                       return(-ERESTARTSYS);
-               }
-       }
-       sti();
-
-       if (sk2->state != TCP_ESTABLISHED && sk2->err > 0) 
-       {
-
-               err = -sk2->err;
-               sk2->err=0;
-               destroy_sock(sk2);
-               newsock->data = NULL;
-               return(err);
-       }
-       newsock->state = SS_CONNECTED;
-       return(0);
-}
-
-
-static int inet_getname(struct socket *sock, struct sockaddr *uaddr,
-                int *uaddr_len, int peer)
-{
-       struct sockaddr_in sin;
-       struct sock *sk;
-       int len;
-       int err;
-  
-  
-       err = verify_area(VERIFY_WRITE,uaddr_len,sizeof(long));
-       if(err)
-               return err;
-       
-       len=get_fs_long(uaddr_len);
-       
-       err = verify_area(VERIFY_WRITE, uaddr, len);
-       if(err)
-               return err;
-       
-       /* Check this error. */
-       if (len < sizeof(sin))  
-               return(-EINVAL);
-
-       sin.sin_family = AF_INET;
-       sk = (struct sock *) sock->data;
-       if (sk == NULL) 
-       {
-               printk("Warning: sock->data = NULL: %d\n" ,__LINE__);
-               return(0);
-       }       
-       if (peer) 
-       {
-               if (!tcp_connected(sk->state)) 
-                       return(-ENOTCONN);
-               sin.sin_port = sk->dummy_th.dest;
-               sin.sin_addr.s_addr = sk->daddr;
-       } 
-       else 
-       {
-               sin.sin_port = sk->dummy_th.source;
-               if (sk->saddr == 0) 
-                       sin.sin_addr.s_addr = my_addr();
-               else 
-                       sin.sin_addr.s_addr = sk->saddr;
-       }
-       len = sizeof(sin);
-       memcpy_tofs(uaddr, &sin, sizeof(sin));
-       put_fs_long(len, uaddr_len);
-       return(0);
-}
-
-
-static int inet_read(struct socket *sock, char *ubuf, int size, int noblock)
-{
-       struct sock *sk;
-
-       sk = (struct sock *) sock->data;
-       if (sk == NULL) 
-       {
-               printk("Warning: sock->data = NULL: %d\n" ,__LINE__);
-               return(0);
-       }
-
-       /* We may need to bind the socket. */
-       if (sk->num == 0) 
-       {
-               sk->num = get_new_socknum(sk->prot, 0);
-               if (sk->num == 0) 
-                       return(-EAGAIN);
-               put_sock(sk->num, sk);
-               sk->dummy_th.source = ntohs(sk->num);
-       }
-       return(sk->prot->read(sk, (unsigned char *) ubuf, size, noblock,0));
-}
-
-
-static int inet_recv(struct socket *sock, void *ubuf, int size, int noblock, unsigned flags)
-{
-       struct sock *sk;
-
-       sk = (struct sock *) sock->data;
-       if (sk == NULL) 
-       {
-               printk("Warning: sock->data = NULL: %d\n" ,__LINE__);
-               return(0);
-       }
-
-       /* We may need to bind the socket. */
-       if (sk->num == 0) 
-       {
-               sk->num = get_new_socknum(sk->prot, 0);
-               if (sk->num == 0) 
-                       return(-EAGAIN);
-               put_sock(sk->num, sk);
-               sk->dummy_th.source = ntohs(sk->num);
-       }
-       return(sk->prot->read(sk, (unsigned char *) ubuf, size, noblock, flags));
-}
-
-
-static int inet_write(struct socket *sock, char *ubuf, int size, int noblock)
-{
-       struct sock *sk;
-
-       sk = (struct sock *) sock->data;
-       if (sk == NULL) 
-       {
-               printk("Warning: sock->data = NULL: %d\n" ,__LINE__);
-               return(0);
-       }
-       if (sk->shutdown & SEND_SHUTDOWN) 
-       {
-               send_sig(SIGPIPE, current, 1);
-               return(-EPIPE);
-       }
-
-       /* We may need to bind the socket. */
-       if (sk->num == 0) 
-       {
-               sk->num = get_new_socknum(sk->prot, 0);
-               if (sk->num == 0) 
-                       return(-EAGAIN);
-               put_sock(sk->num, sk);
-               sk->dummy_th.source = ntohs(sk->num);
-       }
-
-       return(sk->prot->write(sk, (unsigned char *) ubuf, size, noblock, 0));
-}
-
-
-static int inet_send(struct socket *sock, void *ubuf, int size, int noblock, 
-              unsigned flags)
-{
-       struct sock *sk;
-
-       sk = (struct sock *) sock->data;
-       if (sk == NULL) 
-       {
-               printk("Warning: sock->data = NULL: %d\n" ,__LINE__);
-               return(0);
-       }
-       if (sk->shutdown & SEND_SHUTDOWN) 
-       {
-               send_sig(SIGPIPE, current, 1);
-               return(-EPIPE);
-       }
-
-       /* We may need to bind the socket. */
-       if (sk->num == 0) 
-       {
-               sk->num = get_new_socknum(sk->prot, 0);
-               if (sk->num == 0) 
-                       return(-EAGAIN);
-               put_sock(sk->num, sk);
-               sk->dummy_th.source = ntohs(sk->num);
-       }
-
-       return(sk->prot->write(sk, (unsigned char *) ubuf, size, noblock, flags));
-}
-
-
-static int inet_sendto(struct socket *sock, void *ubuf, int size, int noblock, 
-           unsigned flags, struct sockaddr *sin, int addr_len)
-{
-       struct sock *sk;
-
-       sk = (struct sock *) sock->data;
-       if (sk == NULL) 
-       {
-               printk("Warning: sock->data = NULL: %d\n" ,__LINE__);
-               return(0);
-       }
-       if (sk->shutdown & SEND_SHUTDOWN) 
-       {
-               send_sig(SIGPIPE, current, 1);
-               return(-EPIPE);
-       }
-
-       if (sk->prot->sendto == NULL) 
-               return(-EOPNOTSUPP);
-
-       /* We may need to bind the socket. */
-       if (sk->num == 0) 
-       {
-               sk->num = get_new_socknum(sk->prot, 0);
-               if (sk->num == 0) 
-                       return(-EAGAIN);
-               put_sock(sk->num, sk);
-               sk->dummy_th.source = ntohs(sk->num);
-       }
-
-       return(sk->prot->sendto(sk, (unsigned char *) ubuf, size, noblock, flags, 
-                          (struct sockaddr_in *)sin, addr_len));
-}
-
-
-static int inet_recvfrom(struct socket *sock, void *ubuf, int size, int noblock, 
-                  unsigned flags, struct sockaddr *sin, int *addr_len )
-{
-       struct sock *sk;
-
-       sk = (struct sock *) sock->data;
-       if (sk == NULL) 
-       {
-               printk("Warning: sock->data = NULL: %d\n" ,__LINE__);
-               return(0);
-       }
-
-       if (sk->prot->recvfrom == NULL) 
-               return(-EOPNOTSUPP);
-
-       /* We may need to bind the socket. */
-       if (sk->num == 0) 
-       {
-               sk->num = get_new_socknum(sk->prot, 0);
-               if (sk->num == 0) 
-                       return(-EAGAIN);
-               put_sock(sk->num, sk);
-               sk->dummy_th.source = ntohs(sk->num);
-       }
-
-       return(sk->prot->recvfrom(sk, (unsigned char *) ubuf, size, noblock, flags,
-                            (struct sockaddr_in*)sin, addr_len));
-}
-
-
-static int inet_shutdown(struct socket *sock, int how)
-{
-       struct sock *sk;
-
-       /*
-        * This should really check to make sure
-        * the socket is a TCP socket.
-        */
-       how++; /* maps 0->1 has the advantage of making bit 1 rcvs and
-                      1->2 bit 2 snds.
-                      2->3 */
-       if (how & ~SHUTDOWN_MASK) 
-               return(-EINVAL);
-       sk = (struct sock *) sock->data;
-       if (sk == NULL) 
-       {
-               printk("Warning: sock->data = NULL: %d\n" ,__LINE__);
-               return(0);
-       }
-       if (sock->state == SS_CONNECTING && sk->state == TCP_ESTABLISHED)
-               sock->state = SS_CONNECTED;
-
-       if (!tcp_connected(sk->state)) 
-               return(-ENOTCONN);
-       sk->shutdown |= how;
-       if (sk->prot->shutdown) 
-               sk->prot->shutdown(sk, how);
-       return(0);
-}
-
-
-static int inet_select(struct socket *sock, int sel_type, select_table *wait )
-{
-       struct sock *sk;
-
-       sk = (struct sock *) sock->data;
-       if (sk == NULL) 
-       {
-               printk("Warning: sock->data = NULL: %d\n" ,__LINE__);
-               return(0);
-       }
-
-       if (sk->prot->select == NULL) 
-       {
-               DPRINTF((DBG_INET, "select on non-selectable socket.\n"));
-               return(0);
-       }
-       return(sk->prot->select(sk, sel_type, wait));
-}
-
-
-static int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
-{
-       struct sock *sk;
-       int err;
-
-       DPRINTF((DBG_INET, "INET: in inet_ioctl\n"));
-       sk = NULL;
-       if (sock && (sk = (struct sock *) sock->data) == NULL) 
-       {
-               printk("AF_INET: Warning: sock->data = NULL: %d\n" , __LINE__);
-               return(0);
-       }
-
-       switch(cmd) 
-       {
-               case FIOSETOWN:
-               case SIOCSPGRP:
-                       err=verify_area(VERIFY_READ,(int *)arg,sizeof(long));
-                       if(err)
-                               return err;
-                       if (sk)
-                               sk->proc = get_fs_long((int *) arg);
-                       return(0);
-               case FIOGETOWN:
-               case SIOCGPGRP:
-                       if (sk) 
-                       {
-                               err=verify_area(VERIFY_WRITE,(void *) arg, sizeof(long));
-                               if(err)
-                                       return err;
-                               put_fs_long(sk->proc,(int *)arg);
-                       }
-                       return(0);
-               case DDIOCSDBG:
-                       return(dbg_ioctl((void *) arg, DBG_INET));
-       
-               case SIOCADDRT:
-               case SIOCDELRT:
-                       return(rt_ioctl(cmd,(void *) arg));
-
-               case SIOCDARP:
-               case SIOCGARP:
-               case SIOCSARP:
-                       return(arp_ioctl(cmd,(void *) arg));
-
-               case IP_SET_DEV:
-               case SIOCGIFCONF:
-               case SIOCGIFFLAGS:
-               case SIOCSIFFLAGS:
-               case SIOCGIFADDR:
-               case SIOCSIFADDR:
-               case SIOCGIFDSTADDR:
-               case SIOCSIFDSTADDR:
-               case SIOCGIFBRDADDR:
-               case SIOCSIFBRDADDR:
-               case SIOCGIFNETMASK:
-               case SIOCSIFNETMASK:
-               case SIOCGIFMETRIC:
-               case SIOCSIFMETRIC:
-               case SIOCGIFMEM:
-               case SIOCSIFMEM:
-               case SIOCGIFMTU:
-               case SIOCSIFMTU:
-               case SIOCSIFLINK:
-               case SIOCGIFHWADDR:
-                       return(dev_ioctl(cmd,(void *) arg));
-       
-               default:
-                       if (!sk || !sk->prot->ioctl) 
-                               return(-EINVAL);
-                       return(sk->prot->ioctl(sk, cmd, arg));
-       }
-       /*NOTREACHED*/
-       return(0);
-}
-
-
-
-/*
- * This routine must find a socket given a TCP or UDP header.
- * Everyhting is assumed to be in net order.
- */
-struct sock *get_sock(struct proto *prot, unsigned short num,
-                               unsigned long raddr,
-                               unsigned short rnum, unsigned long laddr)
-{
-       struct sock *s;
-       unsigned short hnum;
-
-       hnum = ntohs(num);
-       DPRINTF((DBG_INET, "get_sock(prot=%X, num=%d, raddr=%X, rnum=%d, laddr=%X)\n",
-                 prot, num, raddr, rnum, laddr));
-
-  /*
-   * SOCK_ARRAY_SIZE must be a power of two.  This will work better
-   * than a prime unless 3 or more sockets end up using the same
-   * array entry.  This should not be a problem because most
-   * well known sockets don't overlap that much, and for
-   * the other ones, we can just be careful about picking our
-   * socket number when we choose an arbitrary one.
-   */
-       for(s = prot->sock_array[hnum & (SOCK_ARRAY_SIZE - 1)];s != NULL; s = s->next) 
-       {
-               if (s->num != hnum) 
-                       continue;
-               if(s->dead && (s->state == TCP_CLOSE))
-                       continue;
-               if(prot == &udp_prot)
-                       return s;
-               if(ip_addr_match(s->daddr,raddr)==0)
-                       continue;
-               if (s->dummy_th.dest != rnum && s->dummy_th.dest != 0) 
-                       continue;
-               if(ip_addr_match(s->saddr,laddr) == 0)
-                       continue;
-               return(s);
-       }
-       return(NULL);
-}
-
-
-void release_sock(struct sock *sk)
-{
-       if (!sk) 
-       {
-               printk("sock.c: release_sock sk == NULL\n");
-               return;
-       }
-       /* This one _IS_ legal */
-       if (!sk->prot) 
-       {
-               return;
-       }
-
-       if (sk->blog) 
-               return;
-
-       /* See if we have any packets built up. */
-       cli();
-       sk->inuse = 1;
-       while(sk->back_log != NULL) 
-       {
-               struct sk_buff *skb;
-
-               sk->blog = 1;
-               skb =(struct sk_buff *)sk->back_log;
-               DPRINTF((DBG_INET, "release_sock: skb = %X:\n", skb));
-               if (skb->next != skb) 
-               {
-                       sk->back_log = skb->next;
-                       skb->prev->next = skb->next;
-                       skb->next->prev = skb->prev;
-               } 
-               else 
-               {
-                       sk->back_log = NULL;
-               }
-               sti();
-               DPRINTF((DBG_INET, "sk->back_log = %X\n", sk->back_log));
-               if (sk->prot->rcv) 
-                       sk->prot->rcv(skb, skb->dev, sk->opt,
-                                        skb->saddr, skb->len, skb->daddr, 1,
-                                       /* Only used for/by raw sockets. */
-                                       (struct inet_protocol *)sk->pair); 
-               cli();
-       }
-       sk->blog = 0;
-       sk->inuse = 0;
-       sti();
-       if (sk->dead && sk->state == TCP_CLOSE) 
-       {
-               /* Should be about 2 rtt's */
-               reset_timer(sk, TIME_DONE, min(sk->rtt * 2, TCP_DONE_TIME));
-       }
-}
-
-
-static int inet_fioctl(struct inode *inode, struct file *file,
-        unsigned int cmd, unsigned long arg)
-{
-       int minor, ret;
-
-       /* Extract the minor number on which we work. */
-       minor = MINOR(inode->i_rdev);
-       if (minor != 0) 
-               return(-ENODEV);
-
-       /* Now dispatch on the minor device. */
-       switch(minor) 
-       {
-               case 0:         /* INET */
-                       ret = inet_ioctl(NULL, cmd, arg);
-                       break;
-               case 1:         /* IP */
-                       ret = ip_ioctl(NULL, cmd, arg);
-                       break;
-               case 2:         /* ICMP */
-                       ret = icmp_ioctl(NULL, cmd, arg);
-                       break;
-               case 3:         /* TCP */
-                       ret = tcp_ioctl(NULL, cmd, arg);
-                       break;
-               case 4:         /* UDP */
-                       ret = udp_ioctl(NULL, cmd, arg);
-                       break;
-               default:
-                       ret = -ENODEV;
-       }
-
-       return(ret);
-}
-
-
-static struct file_operations inet_fops = 
-{
-       NULL,           /* LSEEK        */
-       NULL,           /* READ         */
-       NULL,           /* WRITE        */
-       NULL,           /* READDIR      */
-       NULL,           /* SELECT       */
-       inet_fioctl,    /* IOCTL        */
-       NULL,           /* MMAP         */
-       NULL,           /* OPEN         */
-       NULL            /* CLOSE        */
-};     
-
-
-static struct proto_ops inet_proto_ops = 
-{
-       AF_INET,
-
-       inet_create,
-       inet_dup,
-       inet_release,
-       inet_bind,
-       inet_connect,
-       inet_socketpair,
-       inet_accept,
-       inet_getname, 
-       inet_read,
-       inet_write,
-       inet_select,
-       inet_ioctl,
-       inet_listen,
-       inet_send,
-       inet_recv,
-       inet_sendto,
-       inet_recvfrom,
-       inet_shutdown,
-       inet_setsockopt,
-       inet_getsockopt,
-       inet_fcntl,
-};
-
-extern unsigned long seq_offset;
-
-/* 
- *     Called by ddi.c on kernel startup.  
- */
-void inet_proto_init(struct ddi_proto *pro)
-{
-       struct inet_protocol *p;
-       int i;
-
-       printk("Swansea University Computer Society Net2Debugged [1.28]\n");
-       /* Set up our UNIX VFS major device. */
-       if (register_chrdev(AF_INET_MAJOR, "af_inet", &inet_fops) < 0) 
-       {
-               printk("%s: cannot register major device %d!\n",
-                                       pro->name, AF_INET_MAJOR);
-               return;
-       }
-
-       /* Tell SOCKET that we are alive... */
-       (void) sock_register(inet_proto_ops.family, &inet_proto_ops);
-
-       seq_offset = CURRENT_TIME*250;
-
-       /* Add all the protocols. */
-       for(i = 0; i < SOCK_ARRAY_SIZE; i++) 
-       {
-               tcp_prot.sock_array[i] = NULL;
-               udp_prot.sock_array[i] = NULL;
-               raw_prot.sock_array[i] = NULL;
-       }
-       printk("IP Protocols: ");
-       for(p = inet_protocol_base; p != NULL;) 
-       {
-               struct inet_protocol *tmp;
-       
-               tmp = (struct inet_protocol *) p->next;
-               inet_add_protocol(p);
-               printk("%s%s",p->name,tmp?", ":"\n");
-               p = tmp;
-       }
-
-}
diff --git a/net/inet/sockinet.h b/net/inet/sockinet.h
deleted file mode 100644 (file)
index 2e25e03..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- *             Definitions for the socket handler
- *
- * Version:    @(#)sock.h      1.28    26/12/93
- *
- * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
- *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- *             Corey Minyard <wf-rch!minyard@relay.EU.net>
- *             Florian La Roche <flla@stud.uni-sb.de>
- *
- * Fixes:
- *             Alan Cox        :       Volatiles in skbuff pointers. See
- *                                     skbuff comments. May be overdone,
- *                                     better to prove they can be removed
- *                                     than the reverse.
- *             Alan Cox        :       Added a zapped field for tcp to note
- *                                     a socket is reset and must stay shut up
- *             Alan Cox        :       New fields for options
- *     Pauline Middelink       :       identd support
- *             Alan Cox        :       Split into sock.h and sockinet.h
- *
- *             This program is free software; you can redistribute it and/or
- *             modify it under the terms of the GNU General Public License
- *             as published by the Free Software Foundation; either version
- *             2 of the License, or (at your option) any later version.
- */
-
-#ifndef _SOCKINET_H
-#define _SOCKINET_H
-
-#ifndef _SOCK_H
-#include "socket/sock.h"
-#endif
-
-#ifndef _PROTOCOL_H_
-#include "protocol.h"
-#endif
-
-struct proto {
-  void                 *(*wmalloc)(struct sock *sk,
-                                   unsigned long size, int force,
-                                   int priority);
-  void                 *(*rmalloc)(struct sock *sk,
-                                   unsigned long size, int force,
-                                   int priority);
-  void                 (*wfree)(struct sock *sk, void *mem,
-                                unsigned long size);
-  void                 (*rfree)(struct sock *sk, void *mem,
-                                unsigned long size);
-  unsigned long                (*rspace)(struct sock *sk);
-  unsigned long                (*wspace)(struct sock *sk);
-  void                 (*close)(struct sock *sk, int timeout);
-  int                  (*read)(struct sock *sk, unsigned char *to,
-                               int len, int nonblock, unsigned flags);
-  int                  (*write)(struct sock *sk, unsigned char *to,
-                                int len, int nonblock, unsigned flags);
-  int                  (*sendto)(struct sock *sk,
-                                 unsigned char *from, int len, int noblock,
-                                 unsigned flags, struct sockaddr_in *usin,
-                                 int addr_len);
-  int                  (*recvfrom)(struct sock *sk,
-                                   unsigned char *from, int len, int noblock,
-                                   unsigned flags, struct sockaddr_in *usin,
-                                   int *addr_len);
-  int                  (*build_header)(struct sk_buff *skb,
-                                       unsigned long saddr,
-                                       unsigned long daddr,
-                                       struct device **dev, int type,
-                                       struct options *opt, int len,
-                                       int ttl, int tos);
-  int                  (*connect)(struct sock *sk,
-                                 struct sockaddr_in *usin, int addr_len);
-  struct sock          *(*accept) (struct sock *sk, int flags);
-  void                 (*queue_xmit)(struct sock *sk,
-                                     struct device *dev, struct sk_buff *skb,
-                                     int free);
-  void                 (*retransmit)(struct sock *sk, int all);
-  void                 (*write_wakeup)(struct sock *sk);
-  void                 (*read_wakeup)(struct sock *sk);
-  int                  (*rcv)(struct sk_buff *buff, struct device *dev,
-                              struct options *opt, unsigned long daddr,
-                              unsigned short len, unsigned long saddr,
-                              int redo, struct inet_protocol *protocol);
-  int                  (*select)(struct sock *sk, int which,
-                                 select_table *wait);
-  int                  (*ioctl)(struct sock *sk, int cmd,
-                                unsigned long arg);
-  int                  (*init)(struct sock *sk);
-  void                 (*shutdown)(struct sock *sk, int how);
-  int                  (*setsockopt)(struct sock *sk, int level, int optname,
-                                char *optval, int optlen);
-  int                  (*getsockopt)(struct sock *sk, int level, int optname,
-                               char *optval, int *option);      
-  unsigned short       max_header;
-  unsigned long                retransmits;
-  struct sock          *sock_array[SOCK_ARRAY_SIZE];
-  char                 name[80];
-};
-
-extern void                    destroy_sock(struct sock *sk);
-extern unsigned short          get_new_socknum(struct proto *, unsigned short);
-extern void                    put_sock(unsigned short, struct sock *); 
-extern void                    release_sock(struct sock *sk);
-extern struct sock             *get_sock(struct proto *, unsigned short,
-                                         unsigned long, unsigned short,
-                                         unsigned long);
-
-
-/* declarations from timer.c */
-extern struct sock *timer_base;
-
-void delete_timer (struct sock *);
-void reset_timer (struct sock *, int, unsigned long);
-void net_timer (unsigned long);
-
-
-
-#endif
index 7239e098fa95ebab2c1030045a20249ded1b4b1b..83dfb4171ddc68d5e31ad29ee9f5752c14de4750 100644 (file)
@@ -4,9 +4,8 @@
  *             interface as the means of communication with the user level.
  *
  *             Implementation of the Transmission Control Protocol(TCP).
- *             This protocol is described in RFC793.
  *
- * Version:    @(#)tcp.c       1.28    25/12/93
+ * Version:    @(#)tcp.c       1.0.16  05/25/93
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -15,9 +14,9 @@
  *             Florian La Roche, <flla@stud.uni-sb.de>
  *
  * Fixes:      
- *             Alan Cox        :       Numerous verify_area() calls.
- *             Alan Cox        :       Set the ACK bit on a reset.
- *             Alan Cox        :       Stopped it crashing if it closed while sk->inuse=1.
+ *             Alan Cox        :       Numerous verify_area() calls
+ *             Alan Cox        :       Set the ACK bit on a reset
+ *             Alan Cox        :       Stopped it crashing if it closed while sk->inuse=1
  *                                     and was trying to connect (tcp_err()).
  *             Alan Cox        :       All icmp error handling was broken
  *                                     pointers passed where wrong and the
  *                                     tested any icmp error code obviously.
  *             Alan Cox        :       tcp_err() now handled properly. It wakes people
  *                                     on errors. select behaves and the icmp error race
- *                                     has gone by moving it into sock.c.
+ *                                     has gone by moving it into sock.c
  *             Alan Cox        :       tcp_reset() fixed to work for everything not just
  *                                     packets for unknown sockets.
  *             Alan Cox        :       tcp option processing.
- *             Alan Cox        :       Reset tweaked (still not 100%) [Had syn rule wrong].
- *             Herp Rosmanith  :       More reset fixes.
+ *             Alan Cox        :       Reset tweaked (still not 100%) [Had syn rule wrong]
+ *             Herp Rosmanith  :       More reset fixes
  *             Alan Cox        :       No longer acks invalid rst frames. Acking
  *                                     any kind of RST is right out.
  *             Alan Cox        :       Sets an ignore me flag on an rst receive
- *                                     otherwise odd bits of prattle escape still.
+ *                                     otherwise odd bits of prattle escape still
  *             Alan Cox        :       Fixed another acking RST frame bug. Should stop
  *                                     LAN workplace lockups.
- *             Alan Cox        :       Some tidyups using the new skb list facilities.
- *             Alan Cox        :       sk->keepopen now seems to work.
- *             Alan Cox        :       Pulls options out correctly on accepts.
- *             Alan Cox        :       Fixed assorted sk->rqueue->next errors.
+ *             Alan Cox        :       Some tidyups using the new skb list facilities
+ *             Alan Cox        :       sk->keepopen now seems to work
+ *             Alan Cox        :       Pulls options out correctly on accepts
+ *             Alan Cox        :       Fixed assorted sk->rqueue->next errors
  *             Alan Cox        :       PSH doesn't end a TCP read. Switched a bit to skb ops.
  *             Alan Cox        :       Tidied tcp_data to avoid a potential nasty.
- *             Alan Cox        :       Added some beter commenting, as the tcp is hard to follow.
- *             Alan Cox        :       Removed incorrect check for 20 * psh.
+ *             Alan Cox        :       Added some beter commenting, as the tcp is hard to follow
+ *             Alan Cox        :       Removed incorrect check for 20 * psh
  *     Michael O'Reilly        :       ack < copied bug fix.
  *     Johannes Stille         :       Misc tcp fixes (not all in yet).
- *             Alan Cox        :       FIN with no memory -> CRASH.
- *             Alan Cox        :       Tidied up ready for final release and merge of other fixes.
- *             Alan Cox        :       Missing logic on FIN events.
- *             Alan Cox        :       Missing SYN bit check added (was #defined out in error).
- *             Alan Cox        :       recvfrom() semantics corrected - short recv ok, return on PSH flag.
- *             Alan Cox        :       window no longer memory driven so doesn't shrink illegally.
- *             Alan Cox        :       Added socket option proto entries. Also added awareness of them to accept.
- *             Alan Cox        :       State machine error causing Linus the ACK explosion problem found
- *                                     Unsynchronized states now send RST to bad ack frames as per RFC793 page 34.
- *             Alan Cox        :       Added TCP options (SOL_TCP)
- *             Alan Cox        :       Switched wakeup calls to callbacks, so the kernel can layer network sockets.
+ *             Alan Cox        :       FIN with no memory -> CRASH
  *
  *
  * To Fix:
  *             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).
+ *                     Proper processing of piggybacked data on connect.
+ *                     Add VJ Fastrecovery algorithm ?
  *                     Protocol closedown badly messed up.
- *                     MSG_PEEK and read on same socket at once can cause crashes (in theory)
- *                     Should use the partial packet to piggy back acks.
+ *                     Incompatiblity with spider ports (tcp hangs on that 
+ *                     socket occasionally).
+ *             MSG_PEEK and read on same socket at once can cause crashes.
  *
  *             This program is free software; you can redistribute it and/or
  *             modify it under the terms of the GNU General Public License
 #include <linux/in.h>
 #include <linux/fcntl.h>
 #include "inet.h"
-#include "devinet.h"
+#include "dev.h"
 #include "ip.h"
 #include "protocol.h"
 #include "icmp.h"
 #include "tcp.h"
 #include "skbuff.h"
-#include "sockinet.h"
+#include "sock.h"
 #include "arp.h"
 #include <linux/errno.h>
 #include <linux/timer.h>
@@ -104,72 +96,67 @@ unsigned long seq_offset;
 static __inline__ int 
 min(unsigned int a, unsigned int b)
 {
-       if (a < b) 
-               return(a);
-       return(b);
+  if (a < b) return(a);
+  return(b);
 }
 
 
-void print_th(struct tcphdr *th)
+void
+print_th(struct tcphdr *th)
 {
-       unsigned char *ptr;
-
-       if (inet_debug != DBG_TCP) 
-               return;
-
-       printk("TCP header:\n");
-       ptr =(unsigned char *)(th + 1);
-       printk("    source=%d, dest=%d, seq =%ld, ack_seq = %ld\n",
-               ntohs(th->source), ntohs(th->dest),
-               ntohl(th->seq), ntohl(th->ack_seq));
-       printk("    fin=%d, syn=%d, rst=%d, psh=%d, ack=%d, urg=%d res1=%d res2=%d\n",
-               th->fin, th->syn, th->rst, th->psh, th->ack,
-               th->urg, th->res1, th->res2);
-       printk("    window = %d, check = %d urg_ptr = %d\n",
-               ntohs(th->window), ntohs(th->check), ntohs(th->urg_ptr));
-       printk("    doff = %d\n", th->doff);
-       printk("    options = %d %d %d %d\n", ptr[0], ptr[1], ptr[2], ptr[3]);
+  unsigned char *ptr;
+
+  if (inet_debug != DBG_TCP) return;
+
+  printk("TCP header:\n");
+  ptr =(unsigned char *)(th + 1);
+  printk("    source=%d, dest=%d, seq =%ld, ack_seq = %ld\n",
+       ntohs(th->source), ntohs(th->dest),
+       ntohl(th->seq), ntohl(th->ack_seq));
+  printk("    fin=%d, syn=%d, rst=%d, psh=%d, ack=%d, urg=%d res1=%d res2=%d\n",
+       th->fin, th->syn, th->rst, th->psh, th->ack,
+       th->urg, th->res1, th->res2);
+  printk("    window = %d, check = %d urg_ptr = %d\n",
+       ntohs(th->window), ntohs(th->check), ntohs(th->urg_ptr));
+  printk("    doff = %d\n", th->doff);
+  printk("    options = %d %d %d %d\n", ptr[0], ptr[1], ptr[2], ptr[3]);
  }
 
 
 
-/* 
- *     This routine grabs the first thing off of a rcv queue. 
- */
-static struct sk_buff *get_firstr(struct sock *sk)
+/* This routine grabs the first thing off of a rcv queue. */
+static struct sk_buff *
+get_firstr(struct sock *sk)
 {
-       return skb_dequeue(&sk->rqueue);
+  return skb_dequeue(&sk->rqueue);
 }
 
 /*
  *     Difference between two values in tcp ack terms.
  */
 
-static long diff(unsigned long seq1, unsigned long seq2)
+static long
+diff(unsigned long seq1, unsigned long seq2)
 {
-       long d;
+  long d;
 
-       d = seq1 - seq2;
-       if (d > 0)
-               return(d);
+  d = seq1 - seq2;
+  if (d > 0) return(d);
 
-       /* I hope this returns what I want. */
-       return(~d+1);
+  /* I hope this returns what I want. */
+  return(~d+1);
 }
 
 
-/*
- *     Enter the time wait state. 
- */
+/* Enter the time wait state. */
 
 static void tcp_time_wait(struct sock *sk)
 {
-       sk->state = TCP_TIME_WAIT;
-       sk->shutdown = SHUTDOWN_MASK;
-       if (!sk->dead)
-               sk->state_change(sk);
-       reset_timer(sk, TIME_CLOSE, TCP_TIMEWAIT_LEN);
+  sk->state = TCP_TIME_WAIT;
+  sk->shutdown = SHUTDOWN_MASK;
+  if (!sk->dead)
+       wake_up(sk->sleep);
+  reset_timer(sk, TIME_CLOSE, TCP_TIMEWAIT_LEN);
 }
 
 /*
@@ -179,20 +166,20 @@ static void tcp_time_wait(struct sock *sk)
  *     nothing clever here.
  */
 
-static void tcp_retransmit(struct sock *sk, int all)
+static void
+tcp_retransmit(struct sock *sk, int all)
 {
-       if (all) 
-       {
-               ip_retransmit(sk, all);
-               return;
-       }
+  if (all) {
+       ip_retransmit(sk, all);
+       return;
+  }
 
-       if (sk->cong_window > 4)
-                       sk->cong_window = sk->cong_window / 2;
-       sk->exp_growth = 0;
+  if (sk->cong_window > 4)
+       sk->cong_window = sk->cong_window / 2;
+  sk->exp_growth = 0;
 
-       /* Do the actuall retransmit. */
-       ip_retransmit(sk, all);
+  /* Do the actuall retransmit. */
+  ip_retransmit(sk, all);
 }
 
 
@@ -204,61 +191,56 @@ static void tcp_retransmit(struct sock *sk, int all)
  * header points to the first 8 bytes of the tcp header.  We need
  * to find the appropriate port.
  */
-void tcp_err(int err, unsigned char *header, unsigned long daddr,
+void
+tcp_err(int err, unsigned char *header, unsigned long daddr,
        unsigned long saddr, struct inet_protocol *protocol)
 {
-       struct tcphdr *th;
-       struct sock *sk;
-       struct iphdr *iph=(struct iphdr *)header;
+  struct tcphdr *th;
+  struct sock *sk;
+  struct iphdr *iph=(struct iphdr *)header;
   
-       header+=4*iph->ihl;
+  header+=4*iph->ihl;
    
-       DPRINTF((DBG_TCP, "TCP: tcp_err(%d, hdr=%X, daddr=%X saddr=%X, protocol=%X)\n",
+  DPRINTF((DBG_TCP, "TCP: tcp_err(%d, hdr=%X, daddr=%X saddr=%X, protocol=%X)\n",
                                        err, header, daddr, saddr, protocol));
 
-       th =(struct tcphdr *)header;
-       sk = get_sock(&tcp_prot, th->source/*dest*/, daddr, th->dest/*source*/, saddr);
-       print_th(th);
+  th =(struct tcphdr *)header;
+  sk = get_sock(&tcp_prot, th->source/*dest*/, daddr, th->dest/*source*/, saddr);
+  print_th(th);
 
-       if (sk == NULL) 
-               return;
+  if (sk == NULL) return;
   
-       if(err<0)
-       {
-               sk->err = -err;
-               sk->error_report(sk);
-               return;
-       }
-
-       if ((err & 0xff00) == (ICMP_SOURCE_QUENCH << 8)) 
-       {
-               /*
-                * FIXME:
-                * For now we will just trigger a linear backoff.
-                * The slow start code should cause a real backoff here.
-                */
-               if (sk->cong_window > 4) sk->cong_window--;
-               return;
-       }
+  if(err<0)
+  {
+       sk->err = -err;
+       wake_up(sk->sleep);
+       return;
+  }
 
-       DPRINTF((DBG_TCP, "TCP: icmp_err got error\n"));
-       sk->err = icmp_err_convert[err & 0xff].errno;
+  if ((err & 0xff00) == (ICMP_SOURCE_QUENCH << 8)) {
+       /*
+        * FIXME:
+        * For now we will just trigger a linear backoff.
+        * The slow start code should cause a real backoff here.
+        */
+       if (sk->cong_window > 4) sk->cong_window--;
+       return;
+  }
 
-       /*
-        * If we've already connected we will keep trying
-        * until we time out, or the user gives up.
-       */
+  DPRINTF((DBG_TCP, "TCP: icmp_err got error\n"));
+  sk->err = icmp_err_convert[err & 0xff].errno;
 
-       if (icmp_err_convert[err & 0xff].fatal) 
-       {
-               if (sk->state == TCP_SYN_SENT) 
-               {
-                       sk->state = TCP_CLOSE;
-                       sk->error_report(sk);           /* Wake people up to see the error (see connect in sock.c) */
-                       sk->state_change(sk);
-               }
-       }
-       return;
+  /*
+   * If we've already connected we will keep trying
+   * until we time out, or the user gives up.
+   */
+  if (icmp_err_convert[err & 0xff].fatal) {
+       if (sk->state == TCP_SYN_SENT) {
+               sk->state = TCP_CLOSE;
+               wake_up(sk->sleep);     /* Wake people up to see the error (see connect in sock.c) */
+       }
+  }
+  return;
 }
 
 
@@ -267,63 +249,66 @@ void tcp_err(int err, unsigned char *header, unsigned long daddr,
  *     in the received data queue (ie a frame missing that needs sending to us)
  */
 
-static int tcp_readable(struct sock *sk)
+static int
+tcp_readable(struct sock *sk)
 {
-       unsigned long counted;
-       unsigned long amount;
-       struct sk_buff *skb;
-       int count=0;
-       int sum;
-       unsigned long flags;
-
-       DPRINTF((DBG_TCP, "tcp_readable(sk=%X)\n", sk));
-       if(sk && sk->debug)
-               printk("tcp_readable: %p - ",sk);
-
-       if (sk == NULL || skb_peek(&sk->rqueue) == NULL)        /* Empty sockets are easy! */
-       {
-               if(sk && sk->debug) 
-                       printk("empty\n");
-               return(0);
-       }
+  unsigned long counted;
+  unsigned long amount;
+  struct sk_buff *skb;
+  int count=0;
+  int sum;
+  unsigned long flags;
+
+  DPRINTF((DBG_TCP, "tcp_readable(sk=%X)\n", sk));
+  if(sk && sk->debug)
+       printk("tcp_readable: %p - ",sk);
+
+  if (sk == NULL || skb_peek(&sk->rqueue) == NULL)     /* Empty sockets are easy! */
+  {
+       if(sk && sk->debug) 
+               printk("empty\n");
+       return(0);
+  }
   
-       counted = sk->copied_seq+1;     /* Where we are at the moment */
-       amount = 0;
+  counted = sk->copied_seq+1;  /* Where we are at the moment */
+  amount = 0;
   
-       save_flags(flags);              /* So nobody adds things at the wrong moment */
-       cli();
-       skb =(struct sk_buff *)sk->rqueue;
-
-       /* Do until a push or until we are out of data. */
-       do 
-       {
-               count++;
-               if (before(counted, skb->h.th->seq))    /* Found a hole so stops here */
-                       break;
-               sum = skb->len -(counted - skb->h.th->seq);     /* Length - header but start from where we are up to (avoid overlaps) */
-               if (skb->h.th->syn) 
-                       sum++;
-               if (skb->h.th->urg) 
-               {
-                       sum -= ntohs(skb->h.th->urg_ptr);       /* Dont count urg data */
-               }
-               if (sum >= 0) 
-               {                                       /* Add it up, move on */
-                       amount += sum;
-                       if (skb->h.th->syn) 
-                               amount--;
-                       counted += sum;
-               }
-/*             if (amount && skb->h.th->psh) 
-                       break;*/
-               skb =(struct sk_buff *)skb->next;               /* Move along */
-       } 
-       while(skb != sk->rqueue);
-       restore_flags(flags);
-       DPRINTF((DBG_TCP, "tcp readable returning %d bytes\n", amount));
-       if(sk->debug)
-               printk("got %lu bytes.\n",amount);
-       return(amount);
+  save_flags(flags);           /* So nobody adds things at the wrong moment */
+  cli();
+  skb =(struct sk_buff *)sk->rqueue;
+
+  /* Do until a push or until we are out of data. */
+  do {
+       count++;
+#ifdef OLD     
+       /* This is wrong: It breaks Chameleon amongst other stacks */
+       if (count > 20) {
+               restore_flags(flags);
+               DPRINTF((DBG_TCP, "tcp_readable, more than 20 packets without a psh\n"));
+               printk("tcp_read: possible read_queue corruption.\n");
+               return(amount);
+       }
+#endif 
+       if (before(counted, skb->h.th->seq))    /* Found a hole so stops here */
+               break;
+       sum = skb->len -(counted - skb->h.th->seq);     /* Length - header but start from where we are up to (avoid overlaps) */
+       if (skb->h.th->syn) sum++;
+       if (skb->h.th->urg) {
+               sum -= ntohs(skb->h.th->urg_ptr);       /* Dont count urg data */
+       }
+       if (sum >= 0) {                                 /* Add it up, move on */
+               amount += sum;
+               if (skb->h.th->syn) amount--;
+               counted += sum;
+       }
+/*     if (amount && skb->h.th->psh) break;*/
+       skb =(struct sk_buff *)skb->next;               /* Move along */
+  } while(skb != sk->rqueue);
+  restore_flags(flags);
+  DPRINTF((DBG_TCP, "tcp readable returning %d bytes\n", amount));
+  if(sk->debug)
+       printk("got %lu bytes.\n",amount);
+  return(amount);
 }
 
 
@@ -332,120 +317,112 @@ static int tcp_readable(struct sock *sk)
  *     listening socket has a receive queue of sockets to accept.
  */
 
-static int tcp_select(struct sock *sk, int sel_type, select_table *wait)
+static int
+tcp_select(struct sock *sk, int sel_type, select_table *wait)
 {
-       DPRINTF((DBG_TCP, "tcp_select(sk=%X, sel_type = %d, wait = %X)\n",
+  DPRINTF((DBG_TCP, "tcp_select(sk=%X, sel_type = %d, wait = %X)\n",
                                                sk, sel_type, wait));
 
-       sk->inuse = 1;
-       switch(sel_type) 
-       {
-               case SEL_IN:
-                       if(sk->debug)
-                               printk("select in");
-                       select_wait(sk->sleep, wait);
-                       if(sk->debug)
+  sk->inuse = 1;
+  switch(sel_type) {
+       case SEL_IN:
+               if(sk->debug)
+                       printk("select in");
+               select_wait(sk->sleep, wait);
+               if(sk->debug)
                        printk("-select out");
-                       if (skb_peek(&sk->rqueue) != NULL) 
-                       {
-                               if (sk->state == TCP_LISTEN || tcp_readable(sk)) 
-                               {
-                                       release_sock(sk);
-                                       if(sk->debug)
-                                               printk("-select ok data\n");
-                                       return(1);
-                               }
-                       }
-                       if (sk->err != 0)       /* Receiver error */
-                       {
-                               release_sock(sk);
-                               if(sk->debug)
-                                       printk("-select ok error");
-                               return(1);
-                       }
-                       if (sk->shutdown & RCV_SHUTDOWN) 
-                       {
+               if (skb_peek(&sk->rqueue) != NULL) {
+                       if (sk->state == TCP_LISTEN || tcp_readable(sk)) {
                                release_sock(sk);
                                if(sk->debug)
-                                       printk("-select ok down\n");
+                                       printk("-select ok data\n");
                                return(1);
-                       } 
-                       else 
-                       {
-                               release_sock(sk);
-                               if(sk->debug)
-                                       printk("-select fail\n");
-                               return(0);
-                       }
-               case SEL_OUT:
-                       select_wait(sk->sleep, wait);
-                       if (sk->shutdown & SEND_SHUTDOWN) 
-                       {
-                               DPRINTF((DBG_TCP,
-                                       "write select on shutdown socket.\n"));
-                               /* FIXME: should this return an error? */
-                               release_sock(sk);
-                               return(0);
                        }
+               }
+               if (sk->err != 0)       /* Receiver error */
+               {
+                       release_sock(sk);
+                       if(sk->debug)
+                               printk("-select ok error");
+                       return(1);
+               }
+               if (sk->shutdown & RCV_SHUTDOWN) {
+                       release_sock(sk);
+                       if(sk->debug)
+                               printk("-select ok down\n");
+                       return(1);
+               } else {
+                       release_sock(sk);
+                       if(sk->debug)
+                               printk("-select fail\n");
+                       return(0);
+               }
+       case SEL_OUT:
+               select_wait(sk->sleep, wait);
+               if (sk->shutdown & SEND_SHUTDOWN) {
+                       DPRINTF((DBG_TCP,
+                               "write select on shutdown socket.\n"));
+
+                       /* FIXME: should this return an error? */
+                       release_sock(sk);
+                       return(0);
+               }
+
                /*
                 * FIXME:
                 * Hack so it will probably be able to write
                 * something if it says it's ok to write.
                 */
-                       if (sk->prot->wspace(sk) >= sk->mtu) 
-                       {
-                               release_sock(sk);
-                               /* This should cause connect to work ok. */
-                               if (sk->state == TCP_SYN_RECV ||
-                                   sk->state == TCP_SYN_SENT) 
-                                       return(0);
-                               return(1);
-                       }
-                       DPRINTF((DBG_TCP,
-                               "tcp_select: sleeping on write sk->wmem_alloc = %d, "
-                               "sk->packets_out = %d\n"
-                               "sk->wback = %X, sk->wfront = %X\n"
-                               "sk->send_seq = %u, sk->window_seq=%u\n", 
-                                       sk->wmem_alloc, sk->packets_out,
-                                       sk->wback, sk->wfront,
-                                       sk->send_seq, sk->window_seq));
-       
+               if (sk->prot->wspace(sk) >= sk->mtu) {
                        release_sock(sk);
-                       return(0);
-               case SEL_EX:
-                       select_wait(sk->sleep,wait);
-                       if (sk->err) 
-                       {
-                               release_sock(sk);
-                               return(1);
-                       }
+                       /* This should cause connect to work ok. */
+                       if (sk->state == TCP_SYN_RECV ||
+                           sk->state == TCP_SYN_SENT) return(0);
+                       return(1);
+               }
+               DPRINTF((DBG_TCP,
+                       "tcp_select: sleeping on write sk->wmem_alloc = %d, "
+                       "sk->packets_out = %d\n"
+                       "sk->wback = %X, sk->wfront = %X\n"
+                       "sk->send_seq = %u, sk->window_seq=%u\n", 
+                               sk->wmem_alloc, sk->packets_out,
+                               sk->wback, sk->wfront,
+                               sk->send_seq, sk->window_seq));
+
+               release_sock(sk);
+               return(0);
+       case SEL_EX:
+               select_wait(sk->sleep,wait);
+               if (sk->err) {
                        release_sock(sk);
-                       return(0);
-       }
+                       return(1);
+               }
+               release_sock(sk);
+               return(0);
+  }
 
-       release_sock(sk);
-       return(0);
+  release_sock(sk);
+  return(0);
 }
 
 
-int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg)
+int
+tcp_ioctl(struct sock *sk, int cmd, unsigned long arg)
 {
-       int err;
-       DPRINTF((DBG_TCP, "tcp_ioctl(sk=%X, cmd = %d, arg=%X)\n", sk, cmd, arg));
-       switch(cmd) 
-       {
-               case DDIOCSDBG:
-                       return(dbg_ioctl((void *) arg, DBG_TCP));
+  int err;
+  DPRINTF((DBG_TCP, "tcp_ioctl(sk=%X, cmd = %d, arg=%X)\n", sk, cmd, arg));
+  switch(cmd) {
+       case DDIOCSDBG:
+               return(dbg_ioctl((void *) arg, DBG_TCP));
 
-               case TIOCINQ:
+       case TIOCINQ:
 #ifdef FIXME   /* FIXME: */
-               case FIONREAD:
+       case FIONREAD:
 #endif
                {
                        unsigned long amount;
 
-                       if (sk->state == TCP_LISTEN) 
-                               return(-EINVAL);
+                       if (sk->state == TCP_LISTEN) return(-EINVAL);
 
                        sk->inuse = 1;
                        amount = tcp_readable(sk);
@@ -458,7 +435,7 @@ int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg)
                        put_fs_long(amount,(unsigned long *)arg);
                        return(0);
                }
-               case SIOCATMARK:
+       case SIOCATMARK:
                {
                        struct sk_buff *skb;
                        int answ = 0;
@@ -471,7 +448,7 @@ int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg)
                        if ((skb=skb_peek(&sk->rqueue)) != NULL) 
                        {
                                if (sk->copied_seq+1 == skb->h.th->seq && skb->h.th->urg) 
-                                       answ = 1;
+                                               answ = 1;
                        }
                        release_sock(sk);
                        err=verify_area(VERIFY_WRITE,(void *) arg,
@@ -481,12 +458,11 @@ int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg)
                        put_fs_long(answ,(int *) arg);
                        return(0);
                }
-               case TIOCOUTQ:
+       case TIOCOUTQ:
                {
                        unsigned long amount;
 
-                       if (sk->state == TCP_LISTEN) 
-                               return(-EINVAL);
+                       if (sk->state == TCP_LISTEN) return(-EINVAL);
                        amount = sk->prot->wspace(sk);
                        err=verify_area(VERIFY_WRITE,(void *)arg,
                                                   sizeof(unsigned long));
@@ -495,1288 +471,986 @@ int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg)
                        put_fs_long(amount,(unsigned long *)arg);
                        return(0);
                }
-               default:
-                       return(-EINVAL);
-       }
+       default:
+               return(-EINVAL);
+  }
 }
 
 
-/* 
- *     This routine computes a TCP checksum. 
- */
-unsigned short tcp_check(struct tcphdr *th, int len,
+/* This routine computes a TCP checksum. */
+unsigned short
+tcp_check(struct tcphdr *th, int len,
          unsigned long saddr, unsigned long daddr)
 {     
-       unsigned long sum;
+  unsigned long sum;
    
-       if (saddr == 0)         
-               saddr = my_addr();
-       print_th(th);
-       __asm__("\t addl %%ecx,%%ebx\n"
-                 "\t adcl %%edx,%%ebx\n"
-                 "\t adcl $0, %%ebx\n"
-                 : "=b"(sum)
-                 : "0"(daddr), "c"(saddr), "d"((ntohs(len) << 16) + IPPROTO_TCP*256)
-                 : "cx","bx","dx" );
+  if (saddr == 0) saddr = my_addr();
+  print_th(th);
+  __asm__("\t addl %%ecx,%%ebx\n"
+         "\t adcl %%edx,%%ebx\n"
+         "\t adcl $0, %%ebx\n"
+         : "=b"(sum)
+         : "0"(daddr), "c"(saddr), "d"((ntohs(len) << 16) + IPPROTO_TCP*256)
+         : "cx","bx","dx" );
    
-       if (len > 3) 
-       {
-               __asm__("\tclc\n"
-                       "1:\n"
-                       "\t lodsl\n"
-                       "\t adcl %%eax, %%ebx\n"
-                       "\t loop 1b\n"
-                       "\t adcl $0, %%ebx\n"
-                       : "=b"(sum) , "=S"(th)
-                       : "0"(sum), "c"(len/4) ,"1"(th)
-                       : "ax", "cx", "bx", "si" );
-       }
+  if (len > 3) {
+       __asm__("\tclc\n"
+               "1:\n"
+               "\t lodsl\n"
+               "\t adcl %%eax, %%ebx\n"
+               "\t loop 1b\n"
+               "\t adcl $0, %%ebx\n"
+               : "=b"(sum) , "=S"(th)
+               : "0"(sum), "c"(len/4) ,"1"(th)
+               : "ax", "cx", "bx", "si" );
+  }
    
-       /* Convert from 32 bits to 16 bits. */
-       __asm__("\t movl %%ebx, %%ecx\n"
-                 "\t shrl $16,%%ecx\n"
-                 "\t addw %%cx, %%bx\n"
-                 "\t adcw $0, %%bx\n"
-                 : "=b"(sum)
-                 : "0"(sum)
-                 : "bx", "cx");
-          
-         /* Check for an extra word. */
-       if ((len & 2) != 0) 
-       {
-               __asm__("\t lodsw\n"
-                       "\t addw %%ax,%%bx\n"
-                       "\t adcw $0, %%bx\n"
-                       : "=b"(sum), "=S"(th)
-                       : "0"(sum) ,"1"(th)
-                       : "si", "ax", "bx");
-       }
+  /* Convert from 32 bits to 16 bits. */
+  __asm__("\t movl %%ebx, %%ecx\n"
+         "\t shrl $16,%%ecx\n"
+         "\t addw %%cx, %%bx\n"
+         "\t adcw $0, %%bx\n"
+         : "=b"(sum)
+         : "0"(sum)
+         : "bx", "cx");
    
-       /* Now check for the extra byte. */
-       if ((len & 1) != 0) 
-       {
-               __asm__("\t lodsb\n"
-                       "\t movb $0,%%ah\n"
-                       "\t addw %%ax,%%bx\n"
-                       "\t adcw $0, %%bx\n"
-                       : "=b"(sum)
-                       : "0"(sum) ,"S"(th)
-                       : "si", "ax", "bx");
-       }
+  /* Check for an extra word. */
+  if ((len & 2) != 0) {
+       __asm__("\t lodsw\n"
+               "\t addw %%ax,%%bx\n"
+               "\t adcw $0, %%bx\n"
+               : "=b"(sum), "=S"(th)
+               : "0"(sum) ,"1"(th)
+               : "si", "ax", "bx");
+  }
    
-       /* We only want the bottom 16 bits, but we never cleared the top 16. */
-       return((~sum) & 0xffff);
+  /* Now check for the extra byte. */
+  if ((len & 1) != 0) {
+       __asm__("\t lodsb\n"
+               "\t movb $0,%%ah\n"
+               "\t addw %%ax,%%bx\n"
+               "\t adcw $0, %%bx\n"
+               : "=b"(sum)
+               : "0"(sum) ,"S"(th)
+               : "si", "ax", "bx");
+  }
+   
+  /* We only want the bottom 16 bits, but we never cleared the top 16. */
+  return((~sum) & 0xffff);
 }
 
 
-void tcp_send_check(struct tcphdr *th, unsigned long saddr, 
+void
+tcp_send_check(struct tcphdr *th, unsigned long saddr, 
               unsigned long daddr, int len, struct sock *sk)
 {
-       th->check = 0;
-       th->check = tcp_check(th, len, saddr, daddr);
-       return;
+  th->check = 0;
+  th->check = tcp_check(th, len, saddr, daddr);
+  return;
 }
 
-/*
- *     Send current partially built frame
- */
 
-static void tcp_send_partial(struct sock *sk)
+static void
+tcp_send_partial(struct sock *sk)
 {
-       struct sk_buff *skb;
+  struct sk_buff *skb;
   
-       if (sk == NULL || sk->send_tmp == NULL) 
-               return;
+  if (sk == NULL || sk->send_tmp == NULL) return;
   
-       skb = sk->send_tmp;
+  skb = sk->send_tmp;
 
-       /* We need to complete and send the packet. */
-       
-       /*
-        *      Fill in the checksum
-        */
-        
-       tcp_send_check(skb->h.th, sk->saddr, sk->daddr,
+  /* We need to complete and send the packet. */
+  tcp_send_check(skb->h.th, sk->saddr, sk->daddr,
                 skb->len-(unsigned long)skb->h.th +
                (unsigned long)(skb+1), sk);
   
-       /*
-        *      Fill in the sequence number
-        */
-       skb->h.seq = sk->send_seq;
-       
-       /*      
-        *      Check the window and packet counts to
-        *      see where it goes 
-        */
-       if (after(sk->send_seq , sk->window_seq) ||
-               sk->packets_out >= sk->cong_window) 
-       {
-               DPRINTF((DBG_TCP, "sk->cong_window = %d, sk->packets_out = %d\n",
-                                               sk->cong_window, sk->packets_out));
-               DPRINTF((DBG_TCP, "sk->send_seq = %d, sk->window_seq = %d\n",
-                                               sk->send_seq, sk->window_seq));
-               skb->next = NULL;
-               skb->magic = TCP_WRITE_QUEUE_MAGIC;
-               if (sk->wback == NULL) 
-               {
-                       sk->wfront=skb;
-               } 
-               else 
-               {
-                       sk->wback->next = skb;
-               }
-               sk->wback = skb;
-       } 
-       else 
-       {
-               sk->prot->queue_xmit(sk, skb->dev, skb,0);
-       }
-       sk->send_tmp = NULL;
+  skb->h.seq = sk->send_seq;
+  if (after(sk->send_seq , sk->window_seq) ||
+      sk->packets_out >= sk->cong_window) {
+       DPRINTF((DBG_TCP, "sk->cong_window = %d, sk->packets_out = %d\n",
+                                       sk->cong_window, sk->packets_out));
+       DPRINTF((DBG_TCP, "sk->send_seq = %d, sk->window_seq = %d\n",
+                                       sk->send_seq, sk->window_seq));
+       skb->next = NULL;
+       skb->magic = TCP_WRITE_QUEUE_MAGIC;
+       if (sk->wback == NULL) {
+               sk->wfront=skb;
+       } else {
+               sk->wback->next = skb;
+       }
+       sk->wback = skb;
+  } else {
+       sk->prot->queue_xmit(sk, skb->dev, skb,0);
+  }
+  sk->send_tmp = NULL;
 }
 
 
-/*
- *     This routine sends an ack and also updates the window. 
- */
-static void tcp_send_ack(unsigned long sequence, unsigned long ack,
+/* This routine sends an ack and also updates the window. */
+static void
+tcp_send_ack(unsigned long sequence, unsigned long ack,
             struct sock *sk,
             struct tcphdr *th, unsigned long daddr)
 {
-       struct sk_buff *buff;
-       struct tcphdr *t1;
-       struct device *dev = NULL;
-       int tmp;
-
-       if(sk->zapped)
-               return;         /* We have been reset, we may not send again */
-       /*
-        * We need to grab some memory, and put together an ack,
-        * and then put it into the queue to be sent.
-        */
-       buff = (struct sk_buff *) sk->prot->wmalloc(sk, MAX_ACK_SIZE, 1, GFP_ATOMIC);
-       if (buff == NULL) 
-       {
-               /* Force it to send an ack. */
-               sk->ack_backlog++;
-               if (sk->timeout != TIME_WRITE && tcp_connected(sk->state)) 
-               {
-                       reset_timer(sk, TIME_WRITE, 10);
-               }
-               if (inet_debug == DBG_SLIP) 
-                       printk("\rtcp_ack: malloc failed\n");
-               return;
-       }
-       
-       buff->mem_addr = buff;
-       buff->mem_len = MAX_ACK_SIZE;
-       buff->len = sizeof(struct tcphdr);
-       buff->sk = sk;
-       t1 =(struct tcphdr *)(buff + 1);
-
-       /* Put in the IP header and routing stuff. */
-       tmp = sk->prot->build_header(buff, sk->saddr, daddr, &dev,IPPROTO_TCP, sk->opt, MAX_ACK_SIZE,
-                       sk->ip_ttl,sk->ip_tos);
-       if (tmp < 0) 
-       {
-               buff->free=1;
-               sk->prot->wfree(sk, buff->mem_addr, buff->mem_len);
-               if (inet_debug == DBG_SLIP) printk("\rtcp_ack: build_header failed\n");
-                       return;
-       }
-       buff->len += tmp;
-       t1 =(struct tcphdr *)((char *)t1 +tmp);
-
-       /* FIXME: */
-       memcpy(t1, th, sizeof(*t1)); /* this should probably be removed */
-
-       /* swap the send and the receive. */
-       t1->dest = th->source;
-       t1->source = th->dest;
-       t1->seq = ntohl(sequence);
-       t1->ack = 1;
-       sk->window = 4096/*sk->prot->rspace(sk)*/;
-       t1->window = ntohs(sk->window);
-       t1->res1 = 0;
-       t1->res2 = 0;
-       t1->rst = 0;
-       t1->urg = 0;
-       t1->syn = 0;
-       t1->psh = 0;
-       t1->fin = 0;
-       if (ack == sk->acked_seq) 
-       {
-               sk->ack_backlog = 0;
-               sk->bytes_rcv = 0;
-               sk->ack_timed = 0;
-               if (sk->send_head == NULL && sk->wfront == NULL) 
-               {
-/*                     delete_timer(sk);*/
-               }
-       }
-       t1->ack_seq = ntohl(ack);
-       t1->doff = sizeof(*t1)/4;
-       tcp_send_check(t1, sk->saddr, daddr, sizeof(*t1), sk);
-       if (sk->debug)
-               printk("\rtcp_ack: seq %lx ack %lx\n", sequence, ack);
-       sk->prot->queue_xmit(sk, dev, buff, 1);
+  struct sk_buff *buff;
+  struct tcphdr *t1;
+  struct device *dev = NULL;
+  int tmp;
+
+  if(sk->zapped)
+       return;         /* We have been reset, we may not send again */
+  /*
+   * We need to grab some memory, and put together an ack,
+   * and then put it into the queue to be sent.
+   */
+  buff = (struct sk_buff *) sk->prot->wmalloc(sk, MAX_ACK_SIZE, 1, GFP_ATOMIC);
+  if (buff == NULL) {
+       /* Force it to send an ack. */
+       sk->ack_backlog++;
+       if (sk->timeout != TIME_WRITE && tcp_connected(sk->state)) {
+               reset_timer(sk, TIME_WRITE, 10);
+       }
+if (inet_debug == DBG_SLIP) printk("\rtcp_ack: malloc failed\n");
+       return;
+  }
+
+  buff->mem_addr = buff;
+  buff->mem_len = MAX_ACK_SIZE;
+  buff->len = sizeof(struct tcphdr);
+  buff->sk = sk;
+  t1 =(struct tcphdr *)(buff + 1);
+
+  /* Put in the IP header and routing stuff. */
+  tmp = sk->prot->build_header(buff, sk->saddr, daddr, &dev,
+                               IPPROTO_TCP, sk->opt, MAX_ACK_SIZE);
+  if (tmp < 0) {
+       buff->free=1;
+       sk->prot->wfree(sk, buff->mem_addr, buff->mem_len);
+if (inet_debug == DBG_SLIP) printk("\rtcp_ack: build_header failed\n");
+       return;
+  }
+  buff->len += tmp;
+  t1 =(struct tcphdr *)((char *)t1 +tmp);
+
+  /* FIXME: */
+  memcpy(t1, th, sizeof(*t1)); /* this should probably be removed */
+
+  /* swap the send and the receive. */
+  t1->dest = th->source;
+  t1->source = th->dest;
+  t1->seq = ntohl(sequence);
+  t1->ack = 1;
+  sk->window = sk->prot->rspace(sk);
+  t1->window = ntohs(sk->window);
+  t1->res1 = 0;
+  t1->res2 = 0;
+  t1->rst = 0;
+  t1->urg = 0;
+  t1->syn = 0;
+  t1->psh = 0;
+  t1->fin = 0;
+  if (ack == sk->acked_seq) {
+       sk->ack_backlog = 0;
+       sk->bytes_rcv = 0;
+       sk->ack_timed = 0;
+       if (sk->send_head == NULL && sk->wfront == NULL) {
+/*             delete_timer(sk);*/
+       }
+  }
+  t1->ack_seq = ntohl(ack);
+  t1->doff = sizeof(*t1)/4;
+  tcp_send_check(t1, sk->saddr, daddr, sizeof(*t1), sk);
+  if (sk->debug)
+        printk("\rtcp_ack: seq %lx ack %lx\n", sequence, ack);
+  sk->prot->queue_xmit(sk, dev, buff, 1);
 }
 
 
-/*
- *     This routine builds a generic TCP header. 
- */
-static int tcp_build_header(struct tcphdr *th, struct sock *sk, int push)
+/* This routine builds a generic TCP header. */
+static int
+tcp_build_header(struct tcphdr *th, struct sock *sk, int push)
 {
 
-       /* FIXME: want to get rid of this. */
-       memcpy(th,(void *) &(sk->dummy_th), sizeof(*th));
-       th->seq = htonl(sk->send_seq);
-       th->psh =(push == 0) ? 1 : 0;
-       th->doff = sizeof(*th)/4;
-       th->ack = 1;
-       th->fin = 0;
-       sk->ack_backlog = 0;
-       sk->bytes_rcv = 0;
-       sk->ack_timed = 0;
-       th->ack_seq = htonl(sk->acked_seq);
-       sk->window = 4096-diff(sk->acked_seq,sk->copied_seq);           /* sk->prot->rspace(sk); */
-       th->window = htons(sk->window);
-
-       return(sizeof(*th));
+  /* FIXME: want to get rid of this. */
+  memcpy(th,(void *) &(sk->dummy_th), sizeof(*th));
+  th->seq = htonl(sk->send_seq);
+  th->psh =(push == 0) ? 1 : 0;
+  th->doff = sizeof(*th)/4;
+  th->ack = 1;
+  th->fin = 0;
+  sk->ack_backlog = 0;
+  sk->bytes_rcv = 0;
+  sk->ack_timed = 0;
+  th->ack_seq = htonl(sk->acked_seq);
+  sk->window = sk->prot->rspace(sk);
+  th->window = htons(sk->window);
+
+  return(sizeof(*th));
 }
 
 
 /*
- *     This routine copies from a user buffer into a socket,
- *     and starts the transmit system.
+ * This routine copies from a user buffer into a socket,
+ * and starts the transmit system.
  */
-static int tcp_write(struct sock *sk, unsigned char *from,
-               int len, int nonblock, unsigned flags)
+static int
+tcp_write(struct sock *sk, unsigned char *from,
+         int len, int nonblock, unsigned flags)
 {
-       int copied = 0;
-       int copy;
-       int tmp;
-       struct sk_buff *skb;
-       unsigned char *buff;
-       struct proto *prot;
-       struct device *dev = NULL;
-
-       DPRINTF((DBG_TCP, "tcp_write(sk=%X, from=%X, len=%d, nonblock=%d, flags=%X)\n",
+  int copied = 0;
+  int copy;
+  int tmp;
+  struct sk_buff *skb;
+  unsigned char *buff;
+  struct proto *prot;
+  struct device *dev = NULL;
+
+  DPRINTF((DBG_TCP, "tcp_write(sk=%X, from=%X, len=%d, nonblock=%d, flags=%X)\n",
                                        sk, from, len, nonblock, flags));
 
-       sk->inuse=1;
-       prot = sk->prot;
-       
-       while(len > 0) 
-       {
-               if (sk->err) 
-               {                       /* Stop on an error */
+  sk->inuse=1;
+  prot = sk->prot;
+  while(len > 0) {
+       if (sk->err) {                  /* Stop on an error */
+               release_sock(sk);
+               if (copied) return(copied);
+               tmp = -sk->err;
+               sk->err = 0;
+               return(tmp);
+       }
+
+       /* First thing we do is make sure that we are established. */    
+       if (sk->shutdown & SEND_SHUTDOWN) {
+               release_sock(sk);
+               sk->err = EPIPE;
+               if (copied) return(copied);
+               sk->err = 0;
+               return(-EPIPE);
+       }
+
+
+       /* Wait for a connection to finish. */
+       
+       while(sk->state != TCP_ESTABLISHED && sk->state != TCP_CLOSE_WAIT) {
+               if (sk->err) {
                        release_sock(sk);
-                       if (copied) 
-                               return(copied);
-                       /* FIXME: An error occuring between these two instructions _is_ remotely
-                          possible. This occurs throughout the old and new net code and needs
-                          fixing one day */
+                       if (copied) return(copied);
                        tmp = -sk->err;
                        sk->err = 0;
                        return(tmp);
                }
 
-               /* First thing we do is make sure that we are established. */    
-               if (sk->shutdown & SEND_SHUTDOWN) 
-               {
+               if (sk->state != TCP_SYN_SENT && sk->state != TCP_SYN_RECV) {
                        release_sock(sk);
-                       sk->err = EPIPE;
-                       if (copied)     
-                               return(copied);
-                       sk->err = 0;
-                       return(-EPIPE);
-               }
-
+                       DPRINTF((DBG_TCP, "tcp_write: return 1\n"));
+                       if (copied) return(copied);
 
-               /* Wait for a connection to finish. */
-       
-               while(sk->state != TCP_ESTABLISHED && sk->state != TCP_CLOSE_WAIT) 
-               {
-                       if (sk->err) 
-                       {
-                               release_sock(sk);
-                               if (copied) 
-                                       return(copied);
+                       if (sk->err) {
                                tmp = -sk->err;
                                sk->err = 0;
                                return(tmp);
                        }
 
-                       if (sk->state != TCP_SYN_SENT && sk->state != TCP_SYN_RECV) 
-                       {
-                               release_sock(sk);
-                               DPRINTF((DBG_TCP, "tcp_write: return 1\n"));
-                               if (copied) 
-                                       return(copied);
-
-                               if (sk->err) 
-                               {
-                                       tmp = -sk->err;
-                                       sk->err = 0;
-                                       return(tmp);
-                               }
-
-                               if (sk->keepopen) 
-                               {
-                                       send_sig(SIGPIPE, current, 0);
-                               }
-                               return(-EPIPE);
-                       }
-
-                       if (nonblock /*|| copied*/) 
-                       {
-                               release_sock(sk);
-                               DPRINTF((DBG_TCP, "tcp_write: return 2\n"));
-                               if (copied) 
-                                       return(copied);
-                               return(-EAGAIN);
+                       if (sk->keepopen) {
+                               send_sig(SIGPIPE, current, 0);
                        }
+                       return(-EPIPE);
+               }
 
+               if (nonblock || copied) {
                        release_sock(sk);
-                       cli();
-                       if (sk->state != TCP_ESTABLISHED &&
-                           sk->state != TCP_CLOSE_WAIT && sk->err == 0) 
-                       {
-                               interruptible_sleep_on(sk->sleep);
-                               if (current->signal & ~current->blocked) 
-                               {
-                                       sti();
-                                       DPRINTF((DBG_TCP, "tcp_write: return 3\n"));
-                                       if (copied) 
-                                               return(copied);
-                                       return(-ERESTARTSYS);
-                               }
+                       DPRINTF((DBG_TCP, "tcp_write: return 2\n"));
+                       if (copied) return(copied);
+                       return(-EAGAIN);
+               }
+
+               release_sock(sk);
+               cli();
+               if (sk->state != TCP_ESTABLISHED &&
+                   sk->state != TCP_CLOSE_WAIT && sk->err == 0) {
+                       interruptible_sleep_on(sk->sleep);
+                       if (current->signal & ~current->blocked) {
+                               sti();
+                               DPRINTF((DBG_TCP, "tcp_write: return 3\n"));
+                               if (copied) return(copied);
+                               return(-ERESTARTSYS);
                        }
-                       sk->inuse = 1;
-                       sti();
                }
-               /*
-                *      When we finally arrive at this point we can consider transmission
-                */
+               sk->inuse = 1;
+               sti();
+       }
 
-               /* 
-                *      Now we need to check if we have a half built packet. If so append to
-                *      it.
-                */
-                
-               if (sk->send_tmp != NULL) 
-               {
-                       copy=0;
-                       /* Add more stuff to the end of skb->len */
-                       skb = sk->send_tmp;
-                       if (!(flags & MSG_OOB)) 
-                       {
-                               copy = min(sk->mss - skb->len + 128 +
+       /* Now we need to check if we have a half built packet. */
+       if (sk->send_tmp != NULL) {
+               /* If sk->mss has been changed this could cause problems. */
+
+               /* Add more stuff to the end of skb->len */
+               skb = sk->send_tmp;
+               if (!(flags & MSG_OOB)) {
+                       copy = min(sk->mss - skb->len + 128 +
                                   prot->max_header, len);
              
-                               /* FIXME: this is really a bug. */
-                               if (copy <= 0) 
-                               {
-                                       printk("TCP: **bug**: \"copy\" <= 0!!\n");
-                                       copy = 0;
-                               }
-               
-                               /*
-                                *      Add data to the packet
-                                */
-                                        
-                               memcpy_fromfs((unsigned char *)(skb+1) + skb->len, from, copy);
-                               skb->len += copy;
-                               from += copy;
-                               copied += copy;
-                               len -= copy;
-                               sk->send_seq += copy;
-                       }
-
-                       /*
-                        *      Do we need to send it yet or can it wait for more data ?
-                        */
-                        
-                       if (skb->len -(unsigned long)skb->h.th + (unsigned long)(skb+1) >= sk->mss ||(flags & MSG_OOB) || copy==0) 
-                       {
-                               tcp_send_partial(sk);
-                       }
-                       continue;
-               }
-
-               /*
-                * We also need to worry about the window.
-                * The smallest we will send is about 200 bytes.
-                * This is a bit sad for TCP/AMPR people running
-                * 196 byte windows! - FIXME
-                */
-                
-               copy = min(sk->mtu, diff(sk->window_seq, sk->send_seq));
-
-               /* FIXME: redundant check here. */
-               if (copy < 200 || copy > sk->mtu) copy = sk->mtu;
-                       copy = min(copy, len);
-
-               /*
-                *      We should really check the window here also. 
-                *      [Why ?, Alan]
-                */
-                
-               if (sk->packets_out && copy < sk->mss && !(flags & MSG_OOB)) 
-               {
-                       /* We will release the socket in case we sleep here. */
-                       release_sock(sk);
-                       
-                       /*
-                        *      Grab a packet to suit the mss.
-                        */
-                        
-                       skb = (struct sk_buff *) prot->wmalloc(sk,
-                               sk->mss + 128 + prot->max_header +
-                               sizeof(*skb), 0, GFP_KERNEL);
-                       sk->inuse = 1;
-                       sk->send_tmp = skb;
-                       if (skb != NULL)
-                               skb->mem_len = sk->mss + 128 + prot->max_header + sizeof(*skb);
-               } 
-               else 
-               {
-                       /* We will release the socket in case we sleep here. */
-                       release_sock(sk);
-                       skb = (struct sk_buff *) prot->wmalloc(sk,
-                               copy + prot->max_header +
-                               sizeof(*skb), 0, GFP_KERNEL);
-                       sk->inuse = 1;
-                       if (skb != NULL)
-                               skb->mem_len = copy+prot->max_header + sizeof(*skb);
+               /* FIXME: this is really a bug. */
+               if (copy <= 0) {
+                       printk("TCP: **bug**: \"copy\" <= 0!!\n");
+                       copy = 0;
                }
+         
+               memcpy_fromfs((unsigned char *)(skb+1) + skb->len, from, copy);
+               skb->len += copy;
+               from += copy;
+               copied += copy;
+               len -= copy;
+               sk->send_seq += copy;
+       }
 
-               /* If we didn't get any memory, we need to sleep. */
-               if (skb == NULL) 
-               {
-                       if (nonblock /* || copied */) 
-                       {
-                               release_sock(sk);
-                               DPRINTF((DBG_TCP, "tcp_write: return 4\n"));
-                               if (copied) 
-                                       return(copied);
-                               return(-EAGAIN);
-                       }
-
-                       /* FIXME: here is another race condition. */
-                       tmp = sk->wmem_alloc;
-                       release_sock(sk);
-                       cli();
-                       /* Again we will try to avoid it. */
-                       if (tmp <= sk->wmem_alloc && (sk->state == TCP_ESTABLISHED||sk->state == TCP_CLOSE_WAIT) && sk->err == 0) 
-                       {
-                               interruptible_sleep_on(sk->sleep);
-                               if (current->signal & ~current->blocked) 
-                               {
-                                       sti();
-                                       DPRINTF((DBG_TCP, "tcp_write: return 5\n"));
-                                       if (copied) 
-                                               return(copied);
-                                       return(-ERESTARTSYS);
-                               }
-                       }
-                       sk->inuse = 1;
-                       sti();
-                       continue;
-               }
-       
-               skb->mem_addr = skb;
-               skb->len = 0;
-               skb->sk = sk;
-               skb->free = 0;
+       if (skb->len -(unsigned long)skb->h.th +
+          (unsigned long)(skb+1) >= sk->mss ||(flags & MSG_OOB)) {
+               tcp_send_partial(sk);
+       }
+       continue;
+  }
 
-               buff =(unsigned char *)(skb+1);
+  /*
+   * We also need to worry about the window.
+   * The smallest we will send is about 200 bytes.
+   * This is a bit sad for TCP/AMPR people running
+   * 196 byte windows! - FIXME
+   */
+  copy = min(sk->mtu, diff(sk->window_seq, sk->send_seq));
+
+  /* FIXME: redundent check here. */
+  if (copy < 200 || copy > sk->mtu) copy = sk->mtu;
+  copy = min(copy, len);
+
+  /* We should really check the window here also. */
+  if (sk->packets_out && copy < sk->mss && !(flags & MSG_OOB)) {
+       /* We will release the socket incase we sleep here. */
+       release_sock(sk);
+       skb = (struct sk_buff *) prot->wmalloc(sk,
+                       sk->mss + 128 + prot->max_header +
+                       sizeof(*skb), 0, GFP_KERNEL);
+       sk->inuse = 1;
+       sk->send_tmp = skb;
+       if (skb != NULL)
+               skb->mem_len = sk->mss + 128 + prot->max_header + sizeof(*skb);
+       } else {
+               /* We will release the socket incase we sleep here. */
+               release_sock(sk);
+               skb = (struct sk_buff *) prot->wmalloc(sk,
+                               copy + prot->max_header +
+                               sizeof(*skb), 0, GFP_KERNEL);
+               sk->inuse = 1;
+               if (skb != NULL)
+                       skb->mem_len = copy+prot->max_header + sizeof(*skb);
+       }
 
-               /*
-                * FIXME: we need to optimize this.
-                * Perhaps some hints here would be good.
-                */
-                
-               /*
-                *      Begin putting the headers on the packet
-                */
-                
-               tmp = prot->build_header(skb, sk->saddr, sk->daddr, &dev,
-                                IPPROTO_TCP, sk->opt, skb->mem_len, sk->ip_ttl,sk->ip_tos);
-               if (tmp < 0 ) 
-               {
-                       prot->wfree(sk, skb->mem_addr, skb->mem_len);
-                       release_sock(sk);
-                       DPRINTF((DBG_TCP, "tcp_write: return 6\n"));
-                       if (copied) 
-                               return(copied);
-                       return(tmp);
-               }
-               
-               skb->len += tmp;
-               skb->dev = dev;
-               buff += tmp;
-               skb->h.th =(struct tcphdr *) buff;
-               
-               /*
-                *      Put the TCP header in
-                */
-                
-               tmp = tcp_build_header((struct tcphdr *)buff, sk, len-copy);
-               if (tmp < 0) 
-               {
-                       prot->wfree(sk, skb->mem_addr, skb->mem_len);
+       /* If we didn't get any memory, we need to sleep. */
+       if (skb == NULL) {
+               if (nonblock /* || copied */) {
                        release_sock(sk);
-                       DPRINTF((DBG_TCP, "tcp_write: return 7\n"));
-                       if (copied) 
-                               return(copied);
-                       return(tmp);
+                       DPRINTF((DBG_TCP, "tcp_write: return 4\n"));
+                       if (copied) return(copied);
+                       return(-EAGAIN);
                }
 
-               /*
-                *      If this was OOB data it goes at the start of a packet
-                *      with the urg flag and urg ptr set. 
-                */
-                
-               if (flags & MSG_OOB) 
-               {
-                       ((struct tcphdr *)buff)->urg = 1;
-                       ((struct tcphdr *)buff)->urg_ptr = ntohs(copy);
+               /* FIXME: here is another race condition. */
+               tmp = sk->wmem_alloc;
+               release_sock(sk);
+               cli();
+               /* Again we will try to avoid it. */
+               if (tmp <= sk->wmem_alloc &&
+                 (sk->state == TCP_ESTABLISHED||sk->state == TCP_CLOSE_WAIT)
+                               && sk->err == 0) {
+                       interruptible_sleep_on(sk->sleep);
+                       if (current->signal & ~current->blocked) {
+                               sti();
+                               DPRINTF((DBG_TCP, "tcp_write: return 5\n"));
+                               if (copied) return(copied);
+                               return(-ERESTARTSYS);
+                       }
                }
-               
-               /*
-                *      Set the length
-                */
-                
-               skb->len += tmp;
-               
-               /*
-                *      Insert user data
-                */
-                
-               memcpy_fromfs(buff+tmp, from, copy);
+               sk->inuse = 1;
+               sti();
+               continue;
+       }
 
-               from += copy;
-               copied += copy;
-               len -= copy;
-               skb->len += copy;
-               skb->free = 0;
-               sk->send_seq += copy;
+       skb->mem_addr = skb;
+       skb->len = 0;
+       skb->sk = sk;
+       skb->free = 0;
 
-               if (sk->send_tmp != NULL)       
-                       continue;
-                       
-               /*
-                *      Checksum
-                */
+       buff =(unsigned char *)(skb+1);
 
-               tcp_send_check((struct tcphdr *)buff, sk->saddr, sk->daddr,
-                       copy + sizeof(struct tcphdr), sk);
+       /*
+        * FIXME: we need to optimize this.
+        * Perhaps some hints here would be good.
+        */
+       tmp = prot->build_header(skb, sk->saddr, sk->daddr, &dev,
+                                IPPROTO_TCP, sk->opt, skb->mem_len);
+       if (tmp < 0 ) {
+               prot->wfree(sk, skb->mem_addr, skb->mem_len);
+               release_sock(sk);
+               DPRINTF((DBG_TCP, "tcp_write: return 6\n"));
+               if (copied) return(copied);
+               return(tmp);
+       }
+       skb->len += tmp;
+       skb->dev = dev;
+       buff += tmp;
+       skb->h.th =(struct tcphdr *) buff;
+       tmp = tcp_build_header((struct tcphdr *)buff, sk, len-copy);
+       if (tmp < 0) {
+               prot->wfree(sk, skb->mem_addr, skb->mem_len);
+               release_sock(sk);
+               DPRINTF((DBG_TCP, "tcp_write: return 7\n"));
+               if (copied) return(copied);
+               return(tmp);
+       }
 
-               /*
-                *      Set the sequence number
-                */
+       if (flags & MSG_OOB) {
+               ((struct tcphdr *)buff)->urg = 1;
+               ((struct tcphdr *)buff)->urg_ptr = ntohs(copy);
+       }
+       skb->len += tmp;
+       memcpy_fromfs(buff+tmp, from, copy);
 
-               skb->h.seq = sk->send_seq;
-               
-               /*
-                *      Can we send (will it fit in the window and is our packet out count low
-                *      enough.
-                */
-                
-               if (after(sk->send_seq , sk->window_seq) || sk->packets_out >= sk->cong_window) 
-               {
-               
-                       /*
-                        *      Nope - add it to the write queue
-                        */
-                        
-                       DPRINTF((DBG_TCP, "sk->cong_window = %d, sk->packets_out = %d\n",
-                                               sk->cong_window, sk->packets_out));
-                       DPRINTF((DBG_TCP, "sk->send_seq = %d, sk->window_seq = %d\n",
-                                               sk->send_seq, sk->window_seq));
-                       skb->next = NULL;
-                       skb->magic = TCP_WRITE_QUEUE_MAGIC;
-                       if (sk->wback == NULL) 
-                       {
-                               sk->wfront = skb;
-                       }       
-                       else 
-                       {
-                               sk->wback->next = skb;
-                       }
-                       sk->wback = skb;
-               } 
-               else 
-               {
-                       /*
-                        *      Kick it our to IP for transmission (and maybe retransmission)
-                        */
-                        
-                       prot->queue_xmit(sk, dev, skb,0);
-               }
-       }
-       sk->err = 0;
+       from += copy;
+       copied += copy;
+       len -= copy;
+       skb->len += copy;
+       skb->free = 0;
+       sk->send_seq += copy;
+
+       if (sk->send_tmp != NULL) continue;
 
-       /* Avoid possible race on send_tmp - c/o Johannes Stille */
-       if(sk->send_tmp && sk->packets_out <sk->cong_window)
-               tcp_send_partial(sk);
-       /* -- */
+       tcp_send_check((struct tcphdr *)buff, sk->saddr, sk->daddr,
+                       copy + sizeof(struct tcphdr), sk);
 
-       release_sock(sk);
-       DPRINTF((DBG_TCP, "tcp_write: return 8\n"));
-       return(copied);
+       skb->h.seq = sk->send_seq;
+       if (after(sk->send_seq , sk->window_seq) ||
+                 sk->packets_out >= sk->cong_window) {
+               DPRINTF((DBG_TCP, "sk->cong_window = %d, sk->packets_out = %d\n",
+                                       sk->cong_window, sk->packets_out));
+               DPRINTF((DBG_TCP, "sk->send_seq = %d, sk->window_seq = %d\n",
+                                       sk->send_seq, sk->window_seq));
+               skb->next = NULL;
+               skb->magic = TCP_WRITE_QUEUE_MAGIC;
+               if (sk->wback == NULL) {
+                       sk->wfront = skb;
+               } else {
+                       sk->wback->next = skb;
+               }
+               sk->wback = skb;
+       } else {
+               prot->queue_xmit(sk, dev, skb,0);
+       }
+  }
+  sk->err = 0;
+  /* Avoid possible race on send_tmp - c/o Johannes Stille */
+  if(sk->send_tmp && !sk->packets_out)
+       tcp_send_partial(sk);
+  /* -- */
+  release_sock(sk);
+  DPRINTF((DBG_TCP, "tcp_write: return 8\n"));
+  return(copied);
 }
 
 
-static int tcp_sendto(struct sock *sk, unsigned char *from,
+static int
+tcp_sendto(struct sock *sk, unsigned char *from,
           int len, int nonblock, unsigned flags,
           struct sockaddr_in *addr, int addr_len)
 {
-       struct sockaddr_in sin;
-
-       if (addr_len < sizeof(sin)) 
-               return(-EINVAL);
-               
-       memcpy_fromfs(&sin, addr, sizeof(sin));
-       
-       if (sin.sin_family && sin.sin_family != AF_INET) 
-               return(-EINVAL);
-       if (sin.sin_port != sk->dummy_th.dest) 
-               return(-EINVAL);
-       if (sin.sin_addr.s_addr != sk->daddr) 
-               return(-EINVAL);
-       return(tcp_write(sk, from, len, nonblock, flags));
+  struct sockaddr_in sin;
+
+  if (addr_len < sizeof(sin)) return(-EINVAL);
+  memcpy_fromfs(&sin, addr, sizeof(sin));
+  if (sin.sin_family && sin.sin_family != AF_INET) return(-EINVAL);
+  if (sin.sin_port != sk->dummy_th.dest) return(-EINVAL);
+  if (sin.sin_addr.s_addr != sk->daddr) return(-EINVAL);
+  return(tcp_write(sk, from, len, nonblock, flags));
 }
 
 
 static void
 tcp_read_wakeup(struct sock *sk)
 {
-       int tmp;
-       struct device *dev = NULL;
-       struct tcphdr *t1;
-       struct sk_buff *buff;
-
-       DPRINTF((DBG_TCP, "in tcp read wakeup\n"));
-       if (!sk->ack_backlog) 
-               return;
-
-       /*
-        * FIXME: we need to put code here to prevent this routine from
-        * being called.  Being called once in a while is ok, so only check
-        * if this is the second time in a row.
-        */
-
-       /*
-        * We need to grab some memory, and put together an ack,
-        * and then put it into the queue to be sent.
-        * 
-        * The current code is rather keen to do this. It ought to first look
-        * for more optimal options like kicking out the pending partial packet.
-        */
-        
-       buff = (struct sk_buff *) sk->prot->wmalloc(sk,MAX_ACK_SIZE,1, GFP_ATOMIC);
-       if (buff == NULL) 
-       {
-               /* Try again real soon. */
-               reset_timer(sk, TIME_WRITE, 10);
-               return;
-       }
+  int tmp;
+  struct device *dev = NULL;
+  struct tcphdr *t1;
+  struct sk_buff *buff;
 
-       buff->mem_addr = buff;
-       buff->mem_len = MAX_ACK_SIZE;
-       buff->len = sizeof(struct tcphdr);
-       buff->sk = sk;
-       
-       /* Put in the IP header and routing stuff. */
-       tmp = sk->prot->build_header(buff, sk->saddr, sk->daddr, &dev,
-             IPPROTO_TCP, sk->opt, MAX_ACK_SIZE, sk->ip_ttl,sk->ip_tos);
-       if (tmp < 0) 
-       {
-               buff->free=1;
-               sk->prot->wfree(sk, buff->mem_addr, buff->mem_len);
-               return;
-       }
-       
-       buff->len += tmp;
-       t1 =(struct tcphdr *)((char *)(buff+1) +tmp);
+  DPRINTF((DBG_TCP, "in tcp read wakeup\n"));
+  if (!sk->ack_backlog) return;
 
-       /*
-        *      Fill in the header. 
-        */
-        
-       memcpy(t1,(void *) &sk->dummy_th, sizeof(*t1));
-       t1->seq = ntohl(sk->send_seq);
-       t1->ack = 1;
-       t1->res1 = 0;
-       t1->res2 = 0;
-       t1->rst = 0;
-       t1->urg = 0;
-       t1->syn = 0;
-       t1->psh = 0;
-       sk->ack_backlog = 0;
-       sk->bytes_rcv = 0;
-       sk->window = 4096/*sk->prot->rspace(sk)*/;
-       t1->window = ntohs(sk->window);
-       t1->ack_seq = ntohl(sk->acked_seq);
-       t1->doff = sizeof(*t1)/4;
-       tcp_send_check(t1, sk->saddr, sk->daddr, sizeof(*t1), sk);
-       
-       /*
-        *      These go straight out and don't retransmit
-        */
-        
-       sk->prot->queue_xmit(sk, dev, buff, 1);
+  /*
+   * FIXME: we need to put code here to prevent this routine from
+   * being called.  Being called once in a while is ok, so only check
+   * if this is the second time in a row.
+   */
+
+  /*
+   * We need to grab some memory, and put together an ack,
+   * and then put it into the queue to be sent.
+   */
+  buff = (struct sk_buff *) sk->prot->wmalloc(sk,MAX_ACK_SIZE,1, GFP_ATOMIC);
+  if (buff == NULL) {
+       /* Try again real soon. */
+       reset_timer(sk, TIME_WRITE, 10);
+       return;
+  }
+
+  buff->mem_addr = buff;
+  buff->mem_len = MAX_ACK_SIZE;
+  buff->len = sizeof(struct tcphdr);
+  buff->sk = sk;
+
+  /* Put in the IP header and routing stuff. */
+  tmp = sk->prot->build_header(buff, sk->saddr, sk->daddr, &dev,
+                              IPPROTO_TCP, sk->opt, MAX_ACK_SIZE);
+  if (tmp < 0) {
+       buff->free=1;
+       sk->prot->wfree(sk, buff->mem_addr, buff->mem_len);
+       return;
+  }
+
+  buff->len += tmp;
+  t1 =(struct tcphdr *)((char *)(buff+1) +tmp);
+
+  memcpy(t1,(void *) &sk->dummy_th, sizeof(*t1));
+  t1->seq = ntohl(sk->send_seq);
+  t1->ack = 1;
+  t1->res1 = 0;
+  t1->res2 = 0;
+  t1->rst = 0;
+  t1->urg = 0;
+  t1->syn = 0;
+  t1->psh = 0;
+  sk->ack_backlog = 0;
+  sk->bytes_rcv = 0;
+  sk->window = sk->prot->rspace(sk);
+  t1->window = ntohs(sk->window);
+  t1->ack_seq = ntohl(sk->acked_seq);
+  t1->doff = sizeof(*t1)/4;
+  tcp_send_check(t1, sk->saddr, sk->daddr, sizeof(*t1), sk);
+  sk->prot->queue_xmit(sk, dev, buff, 1);
 }
 
 
 /*
- *     FIXME:
- *     This routine frees used buffers.
- *     It should consider sending an ACK to let the
- *     other end know we now have a bigger window.
+ * FIXME:
+ * This routine frees used buffers.
+ * It should consider sending an ACK to let the
+ * other end know we now have a bigger window.
  */
-static void cleanup_rbuf(struct sock *sk)
+static void
+cleanup_rbuf(struct sock *sk)
 {
-       unsigned long flags;
-       int left;
-       struct sk_buff *skb;
+  unsigned long flags;
+  int left;
+  struct sk_buff *skb;
 
-       if(sk->debug)
-               printk("cleaning rbuf for sk=%p\n", sk);
+  if(sk->debug)
+       printk("cleaning rbuf for sk=%p\n", sk);
   
-       save_flags(flags);
-       cli();
+  save_flags(flags);
+  cli();
   
-       left = sk->prot->rspace(sk);
+  left = sk->prot->rspace(sk);
  
-       /*
-        * We have to loop through all the buffer headers,
-        * and try to free up all the space we can.
-        */
-
-       while((skb=skb_peek(&sk->rqueue)) != NULL ) 
-       {
-               if (!skb->used) 
-                       break;
-               skb_unlink(skb);
-               skb->sk = sk;
-               kfree_skb(skb, FREE_READ);
-       }
+  /*
+   * We have to loop through all the buffer headers,
+   * and try to free up all the space we can.
+   */
+  while((skb=skb_peek(&sk->rqueue)) != NULL ) 
+  {
+       if (!skb->used) 
+               break;
+       skb_unlink(skb);
+       skb->sk = sk;
+       kfree_skb(skb, FREE_READ);
+  }
 
-       restore_flags(flags);
+  restore_flags(flags);
 
-       /*
-        * FIXME:
-        * At this point we should send an ack if the difference
-        * in the window, and the amount of space is bigger than
-        * TCP_WINDOW_DIFF.
-        */
-       DPRINTF((DBG_TCP, "sk->window left = %d, sk->prot->rspace(sk)=%d\n",
+  /*
+   * FIXME:
+   * At this point we should send an ack if the difference
+   * in the window, and the amount of space is bigger than
+   * TCP_WINDOW_DIFF.
+   */
+  DPRINTF((DBG_TCP, "sk->window left = %d, sk->prot->rspace(sk)=%d\n",
                        sk->window - sk->bytes_rcv, sk->prot->rspace(sk)));
 
-       if(sk->debug)
-               printk("sk->rspace = %lu, was %d\n", sk->prot->rspace(sk),left);
-       if (sk->prot->rspace(sk) != left) 
-       {
-               /*
-                * This area has caused the most trouble.  The current strategy
-                * is to simply do nothing if the other end has room to send at
-                * least 3 full packets, because the ack from those will auto-
-                * matically update the window.  If the other end doesn't think
-                * we have much space left, but we have room for atleast 1 more
-                * complete packet than it thinks we do, we will send an ack
-                * immediatedly.  Otherwise we will wait up to .5 seconds in case
-                * the user reads some more.
-                *
-                * Changes this to reflect real windows - Alan
-                */
-               sk->ack_backlog++;
-               if (4096-diff(sk->acked_seq,sk->copied_seq) - sk->bytes_rcv < 3*sk->mtu)
-               {
-                       /* Send an ack right now. */
-                       tcp_read_wakeup(sk);
-               }
-               else 
-               {
-                       /* Force it to send an ack soon. */
-                       int was_active = del_timer(&sk->timer);
-                       if (!was_active || TCP_ACK_TIME < sk->timer.expires) 
-                       {
-                               reset_timer(sk, TIME_WRITE, TCP_ACK_TIME);
-                       } 
-                       else
-                               add_timer(&sk->timer);
-               }
-       }
+  if(sk->debug)
+       printk("sk->rspace = %lu, was %d\n", sk->prot->rspace(sk),
+                                           left);
+  if (sk->prot->rspace(sk) != left) 
+  {
+       /*
+        * This area has caused the most trouble.  The current strategy
+        * is to simply do nothing if the other end has room to send at
+        * least 3 full packets, because the ack from those will auto-
+        * matically update the window.  If the other end doesn't think
+        * we have much space left, but we have room for atleast 1 more
+        * complete packet than it thinks we do, we will send an ack
+        * immediatedly.  Otherwise we will wait up to .5 seconds in case
+        * the user reads some more.
+        */
+       sk->ack_backlog++;
+       if ((sk->prot->rspace(sk) > (sk->window - sk->bytes_rcv + sk->mtu))) {
+               /* Send an ack right now. */
+               tcp_read_wakeup(sk);
+       } else {
+               /* Force it to send an ack soon. */
+               int was_active = del_timer(&sk->timer);
+               if (!was_active || TCP_ACK_TIME < sk->timer.expires) {
+                       reset_timer(sk, TIME_WRITE, TCP_ACK_TIME);
+               } else
+                       add_timer(&sk->timer);
+       }
+  }
 } 
 
 
-/*
- *     Handle reading urgent data.
- */
-static int tcp_read_urg(struct sock * sk, int nonblock,
+/* Handle reading urgent data. */
+static int
+tcp_read_urg(struct sock * sk, int nonblock,
             unsigned char *to, int len, unsigned flags)
 {
-       int copied = 0;
-       struct sk_buff *skb;
-       int err;
+  int copied = 0;
+  struct sk_buff *skb;
 
-       DPRINTF((DBG_TCP, "tcp_read_urg(sk=%X, to=%X, len=%d, flags=%X)\n",
+  DPRINTF((DBG_TCP, "tcp_read_urg(sk=%X, to=%X, len=%d, flags=%X)\n",
                                        sk, to, len, flags));
 
-       err=verify_area(VERIFY_WRITE,to,len);
-       if(err)
-               return err;
-               
-       while(len > 0) 
-       {
-               sk->inuse = 1;
-               while(sk->urg==0 || skb_peek(&sk->rqueue) == NULL) 
-               {
-                       if (sk->err) 
-                       {
-                               int tmp;
+  while(len > 0) 
+  {
+       sk->inuse = 1;
+       while(sk->urg==0 || skb_peek(&sk->rqueue) == NULL) {
+               if (sk->err) {
+                       int tmp;
 
-                               release_sock(sk);
-                               if (copied)     
-                                       return(copied);
-                               tmp = -sk->err;
-                               sk->err = 0;
-                               return(tmp);
-                       }
+                       release_sock(sk);
+                       if (copied) return(copied);
+                       tmp = -sk->err;
+                       sk->err = 0;
+                       return(tmp);
+               }
 
-                       if (sk->state == TCP_CLOSE || sk->done) 
-                       {
-                               release_sock(sk);
-                               if (copied) 
-                                       return(copied);
-                               if (!sk->done) 
-                               {
-                                       sk->done = 1;
-                                       return(0);
-                               }
-                               return(-ENOTCONN);
+               if (sk->state == TCP_CLOSE || sk->done) {
+                       release_sock(sk);
+                       if (copied) return(copied);
+                       if (!sk->done) {
+                               sk->done = 1;
+                               return(0);
                        }
+                       return(-ENOTCONN);
+               }
                 
-                       if (sk->shutdown & RCV_SHUTDOWN) 
-                       {
-                               release_sock(sk);
-                               if (copied == 0) 
-                                       sk->done = 1;
-                               return(copied);
-                       }
-
-                       if (nonblock || copied) 
-                       {
-                               release_sock(sk);
-                               if (copied) 
-                                       return(copied);
-                               return(-EAGAIN);
-                       }
+               if (sk->shutdown & RCV_SHUTDOWN) {
+                       release_sock(sk);
+                       if (copied == 0) 
+                               sk->done = 1;
+                       return(copied);
+               }
 
-                       /* Now at this point, we may have gotten some data. */
+               if (nonblock || copied) {
                        release_sock(sk);
-                       cli();
-                       if ((sk->urg == 0 || skb_peek(&sk->rqueue) == NULL) &&
-                               sk->err == 0 && !(sk->shutdown & RCV_SHUTDOWN)) 
-                       {
-                               interruptible_sleep_on(sk->sleep);
-                               if (current->signal & ~current->blocked) 
-                               {
-                                       sti();
-                                       if (copied) 
-                                               return(copied);
-                                       return(-ERESTARTSYS);
-                               }
+                       if (copied) return(copied);
+                       return(-EAGAIN);
+               }
+
+               /* Now at this point, we may have gotten some data. */
+               release_sock(sk);
+               cli();
+               if ((sk->urg == 0 || skb_peek(&sk->rqueue) == NULL) &&
+                   sk->err == 0 && !(sk->shutdown & RCV_SHUTDOWN)) {
+                       interruptible_sleep_on(sk->sleep);
+                       if (current->signal & ~current->blocked) {
+                               sti();
+                               if (copied) return(copied);
+                               return(-ERESTARTSYS);
                        }
-                       sk->inuse = 1;
-                       sti();
                }
+               sk->inuse = 1;
+               sti();
+       }
 
-               skb = skb_peek(&sk->rqueue);
-               do 
-               {
-                       int amt;
+       skb = skb_peek(&sk->rqueue);
+       do {
+               int amt;
 
-                       if (skb->h.th->urg && !skb->urg_used) 
+               if (skb->h.th->urg && !skb->urg_used) {
+                       if (skb->h.th->urg_ptr == 0) {
+                               skb->h.th->urg_ptr = ntohs(skb->len);
+                       }
+                       amt = min(ntohs(skb->h.th->urg_ptr),len);
+                       if(amt)
                        {
-                               if (skb->h.th->urg_ptr == 0) 
-                               {
-                                       skb->h.th->urg_ptr = ntohs(skb->len);
-                               }
-                               amt = min(ntohs(skb->h.th->urg_ptr),len);
-                               if(amt)
-                               {
-                                       verify_area(VERIFY_WRITE, to, amt);
-                                       memcpy_tofs(to,(unsigned char *)(skb->h.th) +
-                                                               skb->h.th->doff*4, amt);
-                               }
+                               verify_area(VERIFY_WRITE, to, amt);
+                               memcpy_tofs(to,(unsigned char *)(skb->h.th) +
+                                                       skb->h.th->doff*4, amt);
+                       }
 
-                               if (!(flags & MSG_PEEK)) 
-                               {
-                                       skb->urg_used = 1;
-                                       sk->urg--;
-                               }
-                               release_sock(sk);
-                               copied += amt;
-                               return(copied);
+                       if (!(flags & MSG_PEEK)) {
+                               skb->urg_used = 1;
+                               sk->urg--;
                        }
-                       skb =(struct sk_buff *)skb->next;
-               } 
-               while(skb != sk->rqueue);
-       }
-       sk->urg = 0;
-       release_sock(sk);
-       return(0);
+                       release_sock(sk);
+                       copied += amt;
+                       return(copied);
+               }
+               skb =(struct sk_buff *)skb->next;
+       } while(skb != sk->rqueue);
+  }
+  sk->urg = 0;
+  release_sock(sk);
+  return(0);
 }
 
 
-/* 
- *     This routine copies from a sock struct into the user buffer. 
- */
-static int tcp_read_data(int type,struct sock *sk, unsigned char *to,
+/* This routine copies from a sock struct into the user buffer. */
+static int
+tcp_read(struct sock *sk, unsigned char *to,
         int len, int nonblock, unsigned flags)
 {
-       /* Type is 0 for read, 1 for recv()/recvfrom() */
-       
-       int copied=0; /* will be used to say how much has been copied. */
-       struct sk_buff *skb;
-       unsigned long offset;
-       unsigned long used;
-       int err;
-
-       if (len == 0) 
-               return(0);
-       if (len < 0) 
-       {
-               return(-EINVAL);
-       }
+  int copied=0; /* will be used to say how much has been copied. */
+  struct sk_buff *skb;
+  unsigned long offset;
+  unsigned long used;
+  int err;
+
+  if (len == 0) return(0);
+  if (len < 0) {
+       return(-EINVAL);
+  }
     
-       err=verify_area(VERIFY_WRITE,to,len);
-       if(err)
-               return err;
+  err=verify_area(VERIFY_WRITE,to,len);
+  if(err)
+       return err;
        
-       /* This error should be checked. */
-       if (sk->state == TCP_LISTEN) 
-               return(-ENOTCONN);
+  /* This error should be checked. */
+  if (sk->state == TCP_LISTEN) return(-ENOTCONN);
 
-       /* Urgent data needs to be handled specially. */
-       if ((flags & MSG_OOB)) 
-               return(tcp_read_urg(sk, nonblock, to, len, flags));
+  /* Urgent data needs to be handled specially. */
+  if ((flags & MSG_OOB)) 
+       return(tcp_read_urg(sk, nonblock, to, len, flags));
 
-       /* So no-one else will use this socket. */
-       sk->inuse = 1;
+  /* So no-one else will use this socket. */
+  sk->inuse = 1;
   
-       skb=skb_peek(&sk->rqueue);
-       
-       DPRINTF((DBG_TCP, "tcp_read(sk=%X, to=%X, len=%d, nonblock=%d, flags=%X)\n",
+  skb=skb_peek(&sk->rqueue);
+
+  DPRINTF((DBG_TCP, "tcp_read(sk=%X, to=%X, len=%d, nonblock=%d, flags=%X)\n",
                                                sk, to, len, nonblock, flags));
 
-       while(len > 0) 
-       {
-               /* skb->used just checks to see if we've gone all the way around. */
+  while(len > 0) {
+       /* skb->used just checks to see if we've gone all the way around. */
        
-               /* While no data, or first data indicates some is missing, or data is used */
-               while(skb == NULL || before(sk->copied_seq+1, skb->h.th->seq) || skb->used) 
+       /* While no data, or first data indicates some is missing, or data is used */
+       while(skb == NULL ||
+             before(sk->copied_seq+1, skb->h.th->seq) || skb->used) {
+               DPRINTF((DBG_TCP, "skb = %X:\n", skb));
+               cleanup_rbuf(sk);
+               if (sk->err) 
                {
-                       DPRINTF((DBG_TCP, "skb = %X:\n", skb));
-                       
-                       /*
-                        *      Clean up anything we can
-                        */
-                       cleanup_rbuf(sk);
-                       
-                       /*
-                        *      If an error has come in off the net report it
-                        */
-                       if (sk->err) 
+                       int tmp;
+
+                       release_sock(sk);
+                       if (copied) 
                        {
-                               int tmp;
-       
-                               release_sock(sk);
-                               if (copied) 
-                               {
-                                       DPRINTF((DBG_TCP, "tcp_read: returning %d\n",
-                                                                               copied));
-                                       return(copied);
-                               }
-                               tmp = -sk->err;
-                               sk->err = 0;
-                               return(tmp);
-                       }
-
-                       /*
-                        *      If we have become closed
-                        */     
-                       if (sk->state == TCP_CLOSE) 
-                       {
-                               release_sock(sk);
-                               if (copied) 
-                               {
-                                       DPRINTF((DBG_TCP, "tcp_read: returning %d\n",
+                               DPRINTF((DBG_TCP, "tcp_read: returning %d\n",
                                                                        copied));
-                                       return(copied);
-                               }
-                               if (!sk->done) 
-                               {
-                                       sk->done = 1;
-                                       return(0);
-                               }
-                               return(-ENOTCONN);
+                               return(copied);
                        }
+                       tmp = -sk->err;
+                       sk->err = 0;
+                       return(tmp);
+               }
 
-                       /*
-                        *      If we have been shutdown
-                        */
-                        
-                       if (sk->shutdown & RCV_SHUTDOWN) 
-                       {
-                               release_sock(sk);
-                               if (copied == 0) 
-                                       sk->done = 1;
-                               DPRINTF((DBG_TCP, "tcp_read: returning %d\n", copied));
+               if (sk->state == TCP_CLOSE) 
+               {
+                       release_sock(sk);
+                       if (copied) {
+                               DPRINTF((DBG_TCP, "tcp_read: returning %d\n",
+                                                               copied));
                                return(copied);
                        }
-                       
-                       /*
-                        *      If we don't want to wait.
-                        */
-                       
-                       if (nonblock || copied)                 /* Altered AC 24/12/93 */
-                       {
-                               release_sock(sk);
-                               if(sk->debug)
-                                       printk("read: EAGAIN\n");
-                               if (copied) 
-                               {
-                                       DPRINTF((DBG_TCP, "tcp_read: returning %d\n",
-                                                                       copied));
-                                       return(copied);
-                               }
-                               return(-EAGAIN);
+                       if (!sk->done) {
+                               sk->done = 1;
+                               return(0);
                        }
-                       
-                       /*
-                        *      Peeking doesn't wait around
-                        */
+                       return(-ENOTCONN);
+               }
 
-                       if ((flags & MSG_PEEK) && copied != 0) 
-                       {
-                               release_sock(sk);
-                               DPRINTF((DBG_TCP, "tcp_read: returning %d\n", copied));
-                               return(copied);
-                       }
-                        
-                       DPRINTF((DBG_TCP, "tcp_read about to sleep. state = %d\n",
-                                                                       sk->state));
+               if (sk->shutdown & RCV_SHUTDOWN) 
+               {
                        release_sock(sk);
-       
-                       /*
-                        * Now we may have some data waiting or we could
-                        * have changed state.
-                        */
-                       cli();
+                       if (copied == 0) sk->done = 1;
+                       DPRINTF((DBG_TCP, "tcp_read: returning %d\n", copied));
+                       return(copied);
+               }
                        
-                       /*
-                        *      We just missed an event. Go round and
-                        *      reprocess it. This happens normally because
-                        *      release_sock will catch up on the backlog
-                        *      queue.
-                        */
-                        
-                       if (sk->shutdown & RCV_SHUTDOWN || sk->err != 0) 
+               if (nonblock || copied) 
+               {
+                       release_sock(sk);
+                       if(sk->debug)
+                               printk("read: EAGAIN\n");
+                       if (copied) 
                        {
-                               sk->inuse = 1;
-                               sti();
-                               continue;
+                               DPRINTF((DBG_TCP, "tcp_read: returning %d\n",
+                                                               copied));
+                               return(copied);
                        }
-                       
-                       /*
-                        *      Anything present, if so make sure it fits at our current position
-                        */
+                       return(-EAGAIN);
+               }
 
-                       if (skb_peek(&sk->rqueue) == NULL || before(sk->copied_seq+1, sk->rqueue->h.th->seq)) 
-                       {
-                               if(sk->debug)
-                                       printk("Read wait sleep\n");
-                               interruptible_sleep_on(sk->sleep);
-                               if(sk->debug)
-                                       printk("Read wait wakes\n");
-                               if (current->signal & ~current->blocked) 
-                               {
-                                       sti();
-                                       if (copied) 
-                                       {
-                                               DPRINTF((DBG_TCP, "tcp_read: returning %d\n",
-                                                                       copied));
-                                               return(copied);
-                                       }
-                                       return(-ERESTARTSYS);
-                               }
-                       }
+               if ((flags & MSG_PEEK) && copied != 0) 
+               {
+                       release_sock(sk);
+                       DPRINTF((DBG_TCP, "tcp_read: returning %d\n", copied));
+                       return(copied);
+               }
+                
+               DPRINTF((DBG_TCP, "tcp_read about to sleep. state = %d\n",
+                                                               sk->state));
+               release_sock(sk);
+
+               /*
+                * Now we may have some data waiting or we could
+                * have changed state.
+                */
+               cli();
+               if (sk->shutdown & RCV_SHUTDOWN || sk->err != 0) {
                        sk->inuse = 1;
                        sti();
-                       DPRINTF((DBG_TCP, "tcp_read woke up. \n"));
-
+                       continue;
+               }
 
-                       /*
-                        *      Grab the first packet pointer
-                        */
+               if (skb_peek(&sk->rqueue) == NULL ||
+                   before(sk->copied_seq+1, sk->rqueue->h.th->seq)) {
+                       if(sk->debug)
+                               printk("Read wait sleep\n");
+                       interruptible_sleep_on(sk->sleep);
+                       if(sk->debug)
+                               printk("Read wait wakes\n");
+                       if (current->signal & ~current->blocked) {
+                               sti();
+                               if (copied) {
+                                       DPRINTF((DBG_TCP, "tcp_read: returning %d\n",
+                                                               copied));
+                                       return(copied);
+                               }
+                               return(-ERESTARTSYS);
+                       }
+               }
+               sk->inuse = 1;
+               sti();
+               DPRINTF((DBG_TCP, "tcp_read woke up. \n"));
 
-                       skb=skb_peek(&sk->rqueue);
 
-                       /*
-                        *      That may have been null if we were beaten, if so we loop again 
-                        */
-               }
+               skb=skb_peek(&sk->rqueue);
+               /* That may have been null if we were beaten, if so we loop again */
+       }
 
+       /*
+        * Copy anything from the current block that needs
+        * to go into the user buffer.
+        */
+        offset = sk->copied_seq+1 - skb->h.th->seq;
+  
+        if (skb->h.th->syn) offset--;
+        if (offset < skb->len) /* Some of the packet is useful */
+        {
                /*
-                *      Copy anything from the current block that needs
-                *      to go into the user buffer.
+                * If there is urgent data we must either
+                * return or skip over it.
                 */
-               
-               offset = sk->copied_seq+1 - skb->h.th->seq;
-  
-               if (skb->h.th->syn) 
-                       offset--;
-                       
-               if (offset < skb->len) /* Some of the packet is useful */
-               {
-                       /*
-                        * If there is urgent data we must either
-                        * return or skip over it.
-                        */
-                       if (skb->h.th->urg) 
+               if (skb->h.th->urg) 
+               {
+                       if (skb->urg_used) 
                        {
-                               if (skb->urg_used) 
+                               sk->copied_seq += ntohs(skb->h.th->urg_ptr);
+                               offset += ntohs(skb->h.th->urg_ptr);
+                               if (offset >= skb->len) 
                                {
-                                       sk->copied_seq += ntohs(skb->h.th->urg_ptr);
-                                       offset += ntohs(skb->h.th->urg_ptr);
-                                       if (offset >= skb->len) 
-                                       {
-                                               skb->used = 1;
-                                               skb =(struct sk_buff *)skb->next;
-                                               continue;
-                                       }
-                               } 
-                               else 
-                               {
-                                       release_sock(sk);
-                                       if (copied) 
-                                               return(copied);
-                                               
-                                       /*
-                                        *      This is technically wrong. What do we do if SIGURG is
-                                        *      being ignored. EINTR as a return is certainly wrong.
-                                        */
-                                        
-                                       send_sig(SIGURG, current, 0);
-                                       return(-EINTR);
+                                       skb->used = 1;
+                                       skb =(struct sk_buff *)skb->next;
+                                       continue;
                                }
-                       }
-                       
-                       /*
-                        *      Ok so how much can we use ? 
-                        */
-                       used = min(skb->len - offset, len);
-                       /*
-                        *      Copy it 
-                        */
-                       memcpy_tofs(to,((unsigned char *)skb->h.th) +
-                               skb->h.th->doff*4 + offset, used);
-                       copied += used;
-                       len -= used;
-                       to += used;
-               
-                       /*
-                        *      If we were reading the data is 'eaten' 
-                        */
-       
-                       if (!(flags & MSG_PEEK)) 
-                               sk->copied_seq += used;
-             
-                       /*
-                        * Mark this data used if we are really reading it,
-                        * and if it doesn't contain any urgent data. And we
-                        * have used all the data.
-                        */
-
-                       if (!(flags & MSG_PEEK) && (!skb->h.th->urg || skb->urg_used) && (used + offset >= skb->len)) 
-                               skb->used = 1;
-             
-                       /*
-                        * See if this is the end of a message or if the
-                        * remaining data is urgent.
-                        */
-
-                       if ((skb->h.th->psh && type) || skb->h.th->urg) 
+                       } 
+                       else 
                        {
-                               break;
+                               release_sock(sk);
+                               if (copied) 
+                                       return(copied);
+                               send_sig(SIGURG, current, 0);
+                               return(-EINTR);
                        }
-               } 
-               else 
-               {       /* 
-                        *      already used this data, must be a retransmit 
-                        */
-                       skb->used = 1;
                }
+               /* Ok so how much can we use ? */
+               used = min(skb->len - offset, len);
+               /* Copy it */
+               memcpy_tofs(to,((unsigned char *)skb->h.th) +
+                           skb->h.th->doff*4 + offset, used);
+               copied += used;
+               len -= used;
+               to += used;
                
-               /* 
-                *      Move along a packet. We might reach the end if so we will wait
-                *      for more.
+               /* If we were reading the data is 'eaten' */
+               if (!(flags & MSG_PEEK)) 
+                       sk->copied_seq += used;
+             
+               /*
+                * Mark this data used if we are really reading it,
+                * and if it doesn't contain any urgent data. And we
+                * have used all the data.
                 */
-                
-               skb =(struct sk_buff *)skb->next;
-       }
-       
-       
-       /* 
-        *      Clean up data we have read: This will do ACK frames 
-        */
-        
-       cleanup_rbuf(sk);
-       release_sock(sk);
-       DPRINTF((DBG_TCP, "tcp_read: returning %d\n", copied));
-       if (copied == 0 && nonblock) 
-               return(-EAGAIN);
-       return(copied);
+               if (!(flags & MSG_PEEK) &&
+                  (!skb->h.th->urg || skb->urg_used) &&
+                  (used + offset >= skb->len)) 
+                       skb->used = 1;
+             
+               /*
+                * See if this is the end of a message or if the
+                * remaining data is urgent.
+                */
+               if (/*skb->h.th->psh || */skb->h.th->urg) 
+               {
+                       break;
+               }
+       } 
+       else 
+       {       /* already used this data, must be a retransmit */
+               skb->used = 1;
+       }
+       /* Move along a packet */
+       skb =(struct sk_buff *)skb->next;
+  }
+  /* Clean up data we have read: This will do ACK frames */
+  cleanup_rbuf(sk);
+  release_sock(sk);
+  DPRINTF((DBG_TCP, "tcp_read: returning %d\n", copied));
+  if (copied == 0 && nonblock) 
+       return(-EAGAIN);
+  return(copied);
 }
 
-/*
- *     The read() user function. Read data, block and don't care
- *     about PSH and no partial reads
- */
-
-static int tcp_read(struct sock *sk, unsigned char *to,
-        int len, int nonblock, unsigned flags)
-{
-       return(tcp_read_data(1,sk,to,len,nonblock,flags));
-}
   
 /*
- *     Send a FIN without closing the connection.
- *     Not called at interrupt time.
+ * Send a FIN without closing the connection.
+ * Not called at interrupt time.
  */
-
-void tcp_shutdown(struct sock *sk, int how)
+void
+tcp_shutdown(struct sock *sk, int how)
 {
-       struct sk_buff *buff;
-       struct tcphdr *t1, *th;
-       struct proto *prot;
-       int tmp;
-       struct device *dev = NULL;
+  struct sk_buff *buff;
+  struct tcphdr *t1, *th;
+  struct proto *prot;
+  int tmp;
+  struct device *dev = NULL;
 
   /*
    * We need to grab some memory, and put together a FIN,
@@ -1786,204 +1460,179 @@ void tcp_shutdown(struct sock *sk, int how)
    *   Most of this is guesswork, so maybe it will work...
    */
   /* If we've already sent a FIN, return. */
-       if (sk->state == TCP_FIN_WAIT1 || sk->state == TCP_FIN_WAIT2) 
-               return;
-       if (!(how & SEND_SHUTDOWN)) 
-               return;
-       sk->inuse = 1;
+  if (sk->state == TCP_FIN_WAIT1 || sk->state == TCP_FIN_WAIT2) return;
+  if (!(how & SEND_SHUTDOWN)) return;
+  sk->inuse = 1;
+
+  /* Clear out any half completed packets. */
+  if (sk->send_tmp) tcp_send_partial(sk);
+
+  prot =(struct proto *)sk->prot;
+  th =(struct tcphdr *)&sk->dummy_th;
+  release_sock(sk); /* incase the malloc sleeps. */
+  buff = (struct sk_buff *) prot->wmalloc(sk, MAX_RESET_SIZE,1 , GFP_KERNEL);
+  if (buff == NULL) return;
+  sk->inuse = 1;
+
+  DPRINTF((DBG_TCP, "tcp_shutdown_send buff = %X\n", buff));
+  buff->mem_addr = buff;
+  buff->mem_len = MAX_RESET_SIZE;
+  buff->sk = sk;
+  buff->len = sizeof(*t1);
+  t1 =(struct tcphdr *)(buff + 1);
+
+  /* Put in the IP header and routing stuff. */
+  tmp = prot->build_header(buff,sk->saddr, sk->daddr, &dev,
+                          IPPROTO_TCP, sk->opt,
+                          sizeof(struct tcphdr));
+  if (tmp < 0) {
+       buff->free=1;
+       prot->wfree(sk,buff->mem_addr, buff->mem_len);
+       release_sock(sk);
+       DPRINTF((DBG_TCP, "Unable to build header for fin.\n"));
+       return;
+  }
+
+  t1 =(struct tcphdr *)((char *)t1 +tmp);
+  buff ->len += tmp;
+  buff->dev = dev;
+  memcpy(t1, th, sizeof(*t1));
+  t1->seq = ntohl(sk->send_seq);
+  sk->send_seq++;
+  buff->h.seq = sk->send_seq;
+  t1->ack = 1;
+  t1->ack_seq = ntohl(sk->acked_seq);
+  t1->window = ntohs(sk->prot->rspace(sk));
+  t1->fin = 1;
+  t1->rst = 0;
+  t1->doff = sizeof(*t1)/4;
+  tcp_send_check(t1, sk->saddr, sk->daddr, sizeof(*t1), sk);
 
-       /* Clear out any half completed packets. */
-       if (sk->send_tmp) 
-               tcp_send_partial(sk);
-
-       prot =(struct proto *)sk->prot;
-       th =(struct tcphdr *)&sk->dummy_th;
-       release_sock(sk); /* incase the malloc sleeps. */
-       buff = (struct sk_buff *) prot->wmalloc(sk, MAX_RESET_SIZE,1 , GFP_KERNEL);
-
-       if (buff == NULL) 
-               return;
-
-       sk->inuse = 1;
-
-       DPRINTF((DBG_TCP, "tcp_shutdown_send buff = %X\n", buff));
-       buff->mem_addr = buff;
-       buff->mem_len = MAX_RESET_SIZE;
-       buff->sk = sk;
-       buff->len = sizeof(*t1);
-       t1 =(struct tcphdr *)(buff + 1);
-
-       /* Put in the IP header and routing stuff. */
-       tmp = prot->build_header(buff,sk->saddr, sk->daddr, &dev,
-                                  IPPROTO_TCP, sk->opt,
-                                  sizeof(struct tcphdr),
-                                  sk->ip_ttl,sk->ip_tos
-                                  );
-       if (tmp < 0) 
-       {
-               buff->free=1;
-               prot->wfree(sk,buff->mem_addr, buff->mem_len);
-               release_sock(sk);
-               DPRINTF((DBG_TCP, "Unable to build header for fin.\n"));
-               return;
-       }
-
-       t1 =(struct tcphdr *)((char *)t1 +tmp);
-       buff ->len += tmp;
-       buff->dev = dev;
-       memcpy(t1, th, sizeof(*t1));
-       t1->seq = ntohl(sk->send_seq);
-       sk->send_seq++;
-       buff->h.seq = sk->send_seq;
-       t1->ack = 1;
-       t1->ack_seq = ntohl(sk->acked_seq);
-       t1->window = ntohs(sk->prot->rspace(sk));
-       t1->fin = 1;
-       t1->rst = 0;
-       t1->doff = sizeof(*t1)/4;
-       tcp_send_check(t1, sk->saddr, sk->daddr, sizeof(*t1), sk);
-
-       /*
-        * Can't just queue this up.
-        * It should go at the end of the write queue.
-        */
-       
-       if (sk->wback != NULL) 
-       {
-               buff->free=0;   
-               buff->next = NULL;
-               sk->wback->next = buff;
-               sk->wback = buff;
-               buff->magic = TCP_WRITE_QUEUE_MAGIC;
-       } 
-       else 
-       {
-               sk->prot->queue_xmit(sk, dev, buff, 0);
-       }
-
-       if (sk->state == TCP_ESTABLISHED) 
-               sk->state = TCP_FIN_WAIT1;
-       else 
-               sk->state = TCP_FIN_WAIT2;
-
-       release_sock(sk);
+  /*
+   * Can't just queue this up.
+   * It should go at the end of the write queue.
+   */
+  if (sk->wback != NULL) {
+       buff->free=0;   
+       buff->next = NULL;
+       sk->wback->next = buff;
+       sk->wback = buff;
+       buff->magic = TCP_WRITE_QUEUE_MAGIC;
+  } else {
+       sk->prot->queue_xmit(sk, dev, buff, 0);
+  }
+
+  if (sk->state == TCP_ESTABLISHED) sk->state = TCP_FIN_WAIT1;
+    else sk->state = TCP_FIN_WAIT2;
+
+  release_sock(sk);
 }
 
 
-static int tcp_recvfrom(struct sock *sk, unsigned char *to,
+static int
+tcp_recvfrom(struct sock *sk, unsigned char *to,
             int to_len, int nonblock, unsigned flags,
             struct sockaddr_in *addr, int *addr_len)
 {
-       struct sockaddr_in sin;
-       int len;
-       int err;
-       int result;
+  struct sockaddr_in sin;
+  int len;
+  int err;
+  int result;
   
- /*
-  *    Have to check these first unlike the old code. If 
-  *    we check them after we lose data on an error
-  *    which is wrong 
-  */
-     
-       err = verify_area(VERIFY_WRITE,addr_len,sizeof(long));
-       if(err)
-               return err;
-       len = get_fs_long(addr_len);
-       if(len > sizeof(sin))
-               len = sizeof(sin);
-       err=verify_area(VERIFY_WRITE, addr, len);  
-       if(err)
-               return err;
-               
-       result=tcp_read_data(1,sk, to, to_len, nonblock, flags);
-       
-       if (result < 0) 
-               return(result);
+  /* Have to check these first unlike the old code. If 
+     we check them after we lose data on an error
+     which is wrong */
+  err = verify_area(VERIFY_WRITE,addr_len,sizeof(long));
+  if(err)
+       return err;
+  len = get_fs_long(addr_len);
+  if(len > sizeof(sin))
+       len = sizeof(sin);
+  err=verify_area(VERIFY_WRITE, addr, len);  
+  if(err)
+       return err;
+       
+  result=tcp_read(sk, to, to_len, nonblock, flags);
+
+  if (result < 0) return(result);
   
-       sin.sin_family = AF_INET;
-       sin.sin_port = sk->dummy_th.dest;
-       sin.sin_addr.s_addr = sk->daddr;
+  sin.sin_family = AF_INET;
+  sin.sin_port = sk->dummy_th.dest;
+  sin.sin_addr.s_addr = sk->daddr;
 
-       memcpy_tofs(addr, &sin, len);
-       put_fs_long(len, addr_len);
-       return(result);
+  memcpy_tofs(addr, &sin, len);
+  put_fs_long(len, addr_len);
+  return(result);
 }
 
 
-/* 
- *     This routine will send an RST to the other tcp. 
- */
-static void tcp_reset(unsigned long saddr, unsigned long daddr, struct tcphdr *th,
+/* This routine will send an RST to the other tcp. */
+static void
+tcp_reset(unsigned long saddr, unsigned long daddr, struct tcphdr *th,
          struct proto *prot, struct options *opt, struct device *dev)
 {
-       struct sk_buff *buff;
-       struct tcphdr *t1;
-       int tmp;
+  struct sk_buff *buff;
+  struct tcphdr *t1;
+  int tmp;
 
   /*
    * We need to grab some memory, and put together an RST,
    * and then put it into the queue to be sent.
    */
-       buff = (struct sk_buff *) prot->wmalloc(NULL, MAX_RESET_SIZE, 1, GFP_ATOMIC);
-       if (buff == NULL) 
-               return;
-
-       DPRINTF((DBG_TCP, "tcp_reset buff = %X\n", buff));
-       buff->mem_addr = buff;
-       buff->mem_len = MAX_RESET_SIZE;
-       buff->len = sizeof(*t1);
-       buff->sk = NULL;
-       buff->dev = dev;
-
-       t1 =(struct tcphdr *)(buff + 1);
-
-       /* Put in the IP header and routing stuff. */
-       tmp = prot->build_header(buff, saddr, daddr, &dev, IPPROTO_TCP, opt,
-                          sizeof(struct tcphdr),255, IPTOS_RELIABILITY);
-       if (tmp < 0) 
-       {
-               buff->free = 1;
-               prot->wfree(NULL, buff->mem_addr, buff->mem_len);
-               return;
-       }
-       t1 =(struct tcphdr *)((char *)t1 +tmp);
-       buff->len += tmp;
-       memcpy(t1, th, sizeof(*t1));
-
-       /* Swap the send and the receive. */
-       t1->dest = th->source;
-       t1->source = th->dest;
-       t1->rst = 1;  
-       t1->window = 0;
+  buff = (struct sk_buff *) prot->wmalloc(NULL, MAX_RESET_SIZE, 1, GFP_ATOMIC);
+  if (buff == NULL) 
+       return;
+
+  DPRINTF((DBG_TCP, "tcp_reset buff = %X\n", buff));
+  buff->mem_addr = buff;
+  buff->mem_len = MAX_RESET_SIZE;
+  buff->len = sizeof(*t1);
+  buff->sk = NULL;
+  buff->dev = dev;
+
+  t1 =(struct tcphdr *)(buff + 1);
+
+  /* Put in the IP header and routing stuff. */
+  tmp = prot->build_header(buff, saddr, daddr, &dev, IPPROTO_TCP, opt,
+                          sizeof(struct tcphdr));
+  if (tmp < 0) {
+       buff->free = 1;
+       prot->wfree(NULL, buff->mem_addr, buff->mem_len);
+       return;
+  }
+  t1 =(struct tcphdr *)((char *)t1 +tmp);
+  buff->len += tmp;
+  memcpy(t1, th, sizeof(*t1));
+
+  /* Swap the send and the receive. */
+  t1->dest = th->source;
+  t1->source = th->dest;
+  t1->rst = 1;  
+  t1->window = 0;
   
-       /*
-        *      Fill in the ack field etc
-        */
-        
-       if(th->ack)
-       {
-               t1->ack=0;
-               t1->seq=th->ack_seq;
-               t1->ack_seq=0;
-       }
+  if(th->ack)
+  {
+       t1->ack=0;
+       t1->seq=th->ack_seq;
+       t1->ack_seq=0;
+  }
+  else
+  {
+       t1->ack=1;
+       if(!th->syn)
+               t1->ack_seq=htonl(th->seq);
        else
-       {
-               t1->ack=1;
-               if(!th->syn)
-                       t1->ack_seq=htonl(th->seq);
-               else
-                       t1->ack_seq=htonl(th->seq+1);
-               t1->seq=0;
-       }
-
-       t1->syn = 0;
-       t1->urg = 0;
-       t1->fin = 0;
-       t1->psh = 0;
-       t1->doff = sizeof(*t1)/4;
-       tcp_send_check(t1, saddr, daddr, sizeof(*t1), NULL);
-       prot->queue_xmit(NULL, dev, buff, 1);
+               t1->ack_seq=htonl(th->seq+1);
+       t1->seq=0;
+  }
+
+  t1->syn = 0;
+  t1->urg = 0;
+  t1->fin = 0;
+  t1->psh = 0;
+  t1->doff = sizeof(*t1)/4;
+  tcp_send_check(t1, saddr, daddr, sizeof(*t1), NULL);
+  prot->queue_xmit(NULL, dev, buff, 1);
 }
 
 
@@ -1991,102 +1640,96 @@ static void tcp_reset(unsigned long saddr, unsigned long daddr, struct tcphdr *t
  *     Look for tcp options. Parses everything but only knows about MSS
  */
  
-static void tcp_options(struct sock *sk, struct tcphdr *th)
+static void
+tcp_options(struct sock *sk, struct tcphdr *th)
 {
-       unsigned char *ptr;
-       int length=(th->doff*4)-sizeof(struct tcphdr);
-       int mtuset=0;
+  unsigned char *ptr;
+  int length=(th->doff*4)-sizeof(struct tcphdr);
+  int mtuset=0;
     
-       ptr = (unsigned char *)(th + 1);
+  ptr = (unsigned char *)(th + 1);
   
-       while(length>0)
-       {
-               int opcode=*ptr++;
-               int opsize=*ptr++;
-               switch(opcode)
-               {
-                       case TCPOPT_EOL:
-                               return;
-                       case TCPOPT_NOP:
-                               length-=2;
-                               continue;
+  while(length>0)
+  {
+       int opcode=*ptr++;
+       int opsize=*ptr++;
+       switch(opcode)
+       {
+               case TCPOPT_EOL:
+                       return;
+               case TCPOPT_NOP:
+                       length-=2;
+                       continue;
                
-                       default:
-                               if(opsize<=2)   /* Avoid silly options looping forever */
-                                       return;
-                               switch(opcode)
-                               {
-                                       case TCPOPT_MSS:
-                                               if(opsize==4)
-                                               {
-                                                       sk->mtu=min(sk->mtu,ntohs(*(unsigned short *)ptr));
-                                                       mtuset=1;
-                                               }
-                                               break;
-                                       /* 
-                                        *      Add other options here as people feel the urge to implement stuff like large windows 
-                                        */
-                               }
-                               ptr+=opsize-2;
-                               length-=opsize;
-               }
+               default:
+                       if(opsize<=2)   /* Avoid silly options looping forever */
+                               return;
+                       switch(opcode)
+                       {
+                               case TCPOPT_MSS:
+                                       if(opsize==4)
+                                       {
+                                               sk->mtu=min(sk->mtu,ntohs(*(unsigned short *)ptr));
+                                               mtuset=1;
+                                       }
+                                       break;
+                               /* Add other options here as people feel the urge to implement stuff like large windows */
+                       }
+                       ptr+=opsize-2;
+                       length-=opsize;
        }
+  }
                                        
-       if (!mtuset) 
-       {
-               sk->mtu = min(sk->mtu, 576 - HEADER_SIZE);
-               return;
-       }
+  if (!mtuset) 
+  {
+       sk->mtu = min(sk->mtu, 576 - HEADER_SIZE);
+       return;
+  }
 }
 
 /*
- *     This routine handles a connection request.
- *     It should make sure we haven't already responded.
- *     Because of the way BSD works, we have to send a syn/ack now.
- *     This also means it will be harder to close a socket which is
- *     listening.
+ * This routine handles a connection request.
+ * It should make sure we haven't already responded.
+ * Because of the way BSD works, we have to send a syn/ack now.
+ * This also means it will be harder to close a socket which is
+ * listening.
  */
-
-static void tcp_conn_request(struct sock *sk, struct sk_buff *skb,
+static void
+tcp_conn_request(struct sock *sk, struct sk_buff *skb,
                 unsigned long daddr, unsigned long saddr,
                 struct options *opt, struct device *dev)
 {
-       struct sk_buff *buff;
-       struct tcphdr *t1;
-       unsigned char *ptr;
-       struct sock *newsk;
-       struct tcphdr *th;
-       int tmp;
-
-       DPRINTF((DBG_TCP, "tcp_conn_request(sk = %X, skb = %X, daddr = %X, sadd4= %X, \n"
-               "                  opt = %X, dev = %X)\n",
-               sk, skb, daddr, saddr, opt, dev));
+  struct sk_buff *buff;
+  struct tcphdr *t1;
+  unsigned char *ptr;
+  struct sock *newsk;
+  struct tcphdr *th;
+  int tmp;
+
+  DPRINTF((DBG_TCP, "tcp_conn_request(sk = %X, skb = %X, daddr = %X, sadd4= %X, \n"
+         "                  opt = %X, dev = %X)\n",
+         sk, skb, daddr, saddr, opt, dev));
   
-       th = skb->h.th;
-
-       /* If the socket is dead, don't accept the connection. */
-       if (!sk->dead) 
-       {
-               sk->data_ready(sk,0);
-       } 
-       else 
-       {
-               DPRINTF((DBG_TCP, "tcp_conn_request on dead socket\n"));
-               tcp_reset(daddr, saddr, th, sk->prot, opt, dev);
-               kfree_skb(skb, FREE_READ);
-               return;
-       }
+  th = skb->h.th;
+
+  /* If the socket is dead, don't accept the connection. */
+  if (!sk->dead) {
+       wake_up(sk->sleep);
+  } else {
+       DPRINTF((DBG_TCP, "tcp_conn_request on dead socket\n"));
+       tcp_reset(daddr, saddr, th, sk->prot, opt, dev);
+       kfree_skb(skb, FREE_READ);
+       return;
+  }
 
   /*
    * Make sure we can accept more.  This will prevent a
    * flurry of syns from eating up all our memory.
    */
-       
-       if (sk->ack_backlog >= sk->max_ack_backlog) 
-       {
-               kfree_skb(skb, FREE_READ);
-               return;
-       }
+  if (sk->ack_backlog >= sk->max_ack_backlog) {
+       kfree_skb(skb, FREE_READ);
+       return;
+  }
 
   /*
    * We need to build a new sock struct.
@@ -2095,360 +1738,343 @@ static void tcp_conn_request(struct sock *sk, struct sk_buff *skb,
    * and if the listening socket is destroyed before this is taken
    * off of the queue, this will take care of it.
    */
-       newsk = (struct sock *) kmalloc(sizeof(struct sock), GFP_ATOMIC);
-       if (newsk == NULL) 
-       {
-               /* just ignore the syn.  It will get retransmitted. */
-               kfree_skb(skb, FREE_READ);
-               return;
-       }
-
-       DPRINTF((DBG_TCP, "newsk = %X\n", newsk));
-       memcpy((void *)newsk,(void *)sk, sizeof(*newsk));
-       newsk->wback = NULL;
-       newsk->wfront = NULL;
-       newsk->rqueue = NULL;
-       newsk->send_head = NULL;
-       newsk->send_tail = NULL;
-       newsk->back_log = NULL;
-       newsk->rtt = TCP_CONNECT_TIME;
-       newsk->mdev = 0;
-       newsk->backoff = 0;
-       newsk->blog = 0;
-       newsk->intr = 0;
-       newsk->proc = 0;
-       newsk->done = 0;
-       newsk->send_tmp = NULL;
-       newsk->pair = NULL;
-       newsk->wmem_alloc = 0;
-       newsk->rmem_alloc = 0;
-       
-       newsk->max_unacked = MAX_WINDOW - TCP_WINDOW_DIFF;
-       
-       newsk->err = 0;
-       newsk->shutdown = 0;
-       newsk->ack_backlog = 0;
-       newsk->acked_seq = skb->h.th->seq+1;
-       newsk->fin_seq = skb->h.th->seq;
-       newsk->copied_seq = skb->h.th->seq;
-       newsk->state = TCP_SYN_RECV;
-       newsk->timeout = 0;
-       newsk->send_seq = jiffies * SEQ_TICK - seq_offset;
-       newsk->rcv_ack_seq = newsk->send_seq;
-       newsk->urg =0;
-       newsk->retransmits = 0;
-       newsk->destroy = 0;
-       newsk->timer.data = (unsigned long)newsk;
-       newsk->timer.function = &net_timer;
-       newsk->dummy_th.source = skb->h.th->dest;
-       newsk->dummy_th.dest = skb->h.th->source;
-       
-       /* Swap these two, they are from our point of view. */
-       newsk->daddr = saddr;
-       newsk->saddr = daddr;
-       
-       put_sock(newsk->num,newsk);
-       newsk->dummy_th.res1 = 0;
-       newsk->dummy_th.doff = 6;
-       newsk->dummy_th.fin = 0;
-       newsk->dummy_th.syn = 0;
-       newsk->dummy_th.rst = 0;
-       newsk->dummy_th.psh = 0;
-       newsk->dummy_th.ack = 0;
-       newsk->dummy_th.urg = 0;
-       newsk->dummy_th.res2 = 0;
-       newsk->acked_seq = skb->h.th->seq + 1;
-       newsk->copied_seq = skb->h.th->seq;
-       
-       /* Grab the callers ttl and tos values and use them */
-       newsk->ip_ttl=skb->ip_hdr->ttl;
-       newsk->ip_tos=skb->ip_hdr->tos;
-       
-       tcp_options(newsk,skb->h.th);
-
-       buff = (struct sk_buff *) newsk->prot->wmalloc(newsk, MAX_SYN_SIZE, 1, GFP_ATOMIC);
-       if (buff == NULL) 
-       {
-               sk->err = -ENOMEM;
-               newsk->dead = 1;
-               release_sock(newsk);
-               kfree_skb(skb, FREE_READ);
-               return;
-       }
+  newsk = (struct sock *) kmalloc(sizeof(struct sock), GFP_ATOMIC);
+  if (newsk == NULL) {
+       /* just ignore the syn.  It will get retransmitted. */
+       kfree_skb(skb, FREE_READ);
+       return;
+  }
+
+  DPRINTF((DBG_TCP, "newsk = %X\n", newsk));
+  memcpy((void *)newsk,(void *)sk, sizeof(*newsk));
+  newsk->wback = NULL;
+  newsk->wfront = NULL;
+  newsk->rqueue = NULL;
+  newsk->send_head = NULL;
+  newsk->send_tail = NULL;
+  newsk->back_log = NULL;
+  newsk->rtt = TCP_CONNECT_TIME;
+  newsk->mdev = 0;
+  newsk->backoff = 0;
+  newsk->blog = 0;
+  newsk->intr = 0;
+  newsk->proc = 0;
+  newsk->done = 0;
+  newsk->send_tmp = NULL;
+  newsk->pair = NULL;
+  newsk->wmem_alloc = 0;
+  newsk->rmem_alloc = 0;
+
+  newsk->max_unacked = MAX_WINDOW - TCP_WINDOW_DIFF;
+
+  newsk->err = 0;
+  newsk->shutdown = 0;
+  newsk->ack_backlog = 0;
+  newsk->acked_seq = skb->h.th->seq+1;
+  newsk->fin_seq = skb->h.th->seq;
+  newsk->copied_seq = skb->h.th->seq;
+  newsk->state = TCP_SYN_RECV;
+  newsk->timeout = 0;
+  newsk->send_seq = jiffies * SEQ_TICK - seq_offset;
+  newsk->rcv_ack_seq = newsk->send_seq;
+  newsk->urg =0;
+  newsk->retransmits = 0;
+  newsk->destroy = 0;
+  newsk->timer.data = (unsigned long)newsk;
+  newsk->timer.function = &net_timer;
+  newsk->dummy_th.source = skb->h.th->dest;
+  newsk->dummy_th.dest = skb->h.th->source;
+
+  /* Swap these two, they are from our point of view. */
+  newsk->daddr = saddr;
+  newsk->saddr = daddr;
+
+  put_sock(newsk->num,newsk);
+  newsk->dummy_th.res1 = 0;
+  newsk->dummy_th.doff = 6;
+  newsk->dummy_th.fin = 0;
+  newsk->dummy_th.syn = 0;
+  newsk->dummy_th.rst = 0;
+  newsk->dummy_th.psh = 0;
+  newsk->dummy_th.ack = 0;
+  newsk->dummy_th.urg = 0;
+  newsk->dummy_th.res2 = 0;
+  newsk->acked_seq = skb->h.th->seq + 1;
+  newsk->copied_seq = skb->h.th->seq;
+
+#ifdef OLDWAY
+  if (skb->h.th->doff == 5) {
+       newsk->mtu = dev->mtu - HEADER_SIZE;
+  } else {
+       ptr =(unsigned char *)(skb->h.th + 1);
+       if (ptr[0] != 2 || ptr[1] != 4) {
+               newsk->mtu = dev->mtu - HEADER_SIZE;
+       } else {
+               newsk->mtu = min(ptr[2] * 256 + ptr[3] - HEADER_SIZE,
+                                dev->mtu - HEADER_SIZE);
+       }
+  }
+#else
+  tcp_options(newsk,skb->h.th);
+#endif
+  buff = (struct sk_buff *) newsk->prot->wmalloc(newsk, MAX_SYN_SIZE, 1, GFP_ATOMIC);
+  if (buff == NULL) {
+       sk->err = -ENOMEM;
+       newsk->dead = 1;
+       release_sock(newsk);
+       kfree_skb(skb, FREE_READ);
+       return;
+  }
   
-       buff->mem_addr = buff;
-       buff->mem_len = MAX_SYN_SIZE;
-       buff->len = sizeof(struct tcphdr)+4;
-       buff->sk = newsk;
+  buff->mem_addr = buff;
+  buff->mem_len = MAX_SYN_SIZE;
+  buff->len = sizeof(struct tcphdr)+4;
+  buff->sk = newsk;
   
-       t1 =(struct tcphdr *)(buff + 1);
-
-       /* Put in the IP header and routing stuff. */
-       tmp = sk->prot->build_header(buff, newsk->saddr, newsk->daddr, &dev,
-                              IPPROTO_TCP, NULL, MAX_SYN_SIZE,newsk->ip_ttl,newsk->ip_tos);
-
-       /* Something went wrong. */
-       if (tmp < 0) 
-       {
-               sk->err = tmp;
-               buff->free=1;
-               kfree_skb(buff,FREE_WRITE);
-               newsk->dead = 1;
-               release_sock(newsk);
-               skb->sk = sk;
-               kfree_skb(skb, FREE_READ);
-               return;
-       }
-       
-       /*
-        *      Assemble a syn|ack frame in reply
-        */
-
-       buff->len += tmp;
-       t1 =(struct tcphdr *)((char *)t1 +tmp);
+  t1 =(struct tcphdr *)(buff + 1);
+
+  /* Put in the IP header and routing stuff. */
+  tmp = sk->prot->build_header(buff, newsk->saddr, newsk->daddr, &dev,
+                              IPPROTO_TCP, NULL, MAX_SYN_SIZE);
+
+  /* Something went wrong. */
+  if (tmp < 0) {
+       sk->err = tmp;
+       buff->free=1;
+       kfree_skb(buff,FREE_WRITE);
+       newsk->dead = 1;
+       release_sock(newsk);
+       skb->sk = sk;
+       kfree_skb(skb, FREE_READ);
+       return;
+  }
+
+  buff->len += tmp;
+  t1 =(struct tcphdr *)((char *)t1 +tmp);
   
-       memcpy(t1, skb->h.th, sizeof(*t1));
-       buff->h.seq = newsk->send_seq;
-
-       /* Swap the send and the receive. */
-       t1->dest = skb->h.th->source;
-       t1->source = newsk->dummy_th.source;
-       t1->seq = ntohl(newsk->send_seq++);
-       t1->ack = 1;
-       newsk->window = 4096/*newsk->prot->rspace(newsk)*/;
-       t1->window = ntohs(newsk->window);
-       t1->res1 = 0;
-       t1->res2 = 0;
-       t1->rst = 0;
-       t1->urg = 0;
-       t1->psh = 0;
-       t1->syn = 1;
-       t1->ack_seq = ntohl(skb->h.th->seq+1);
-       t1->doff = sizeof(*t1)/4+1;
-
-       ptr =(unsigned char *)(t1+1);
-       ptr[0] = 2;
-       ptr[1] = 4;
-       ptr[2] =((dev->mtu - HEADER_SIZE) >> 8) & 0xff;
-       ptr[3] =(dev->mtu - HEADER_SIZE) & 0xff;
-       
-       tcp_send_check(t1, daddr, saddr, sizeof(*t1)+4, newsk);
-       newsk->prot->queue_xmit(newsk, dev, buff, 0);
-
-       reset_timer(newsk, TIME_WRITE /* -1 ? FIXME ??? */, TCP_CONNECT_TIME);
-       skb->sk = newsk;
-
-       /* Charge the sock_buff to newsk. */
-       sk->rmem_alloc -= skb->mem_len;
-       newsk->rmem_alloc += skb->mem_len;
-
-       skb_queue_tail(&sk->rqueue,skb);
-       sk->ack_backlog++;
-       release_sock(newsk);
+  memcpy(t1, skb->h.th, sizeof(*t1));
+  buff->h.seq = newsk->send_seq;
+
+  /* Swap the send and the receive. */
+  t1->dest = skb->h.th->source;
+  t1->source = newsk->dummy_th.source;
+  t1->seq = ntohl(newsk->send_seq++);
+  t1->ack = 1;
+  newsk->window = newsk->prot->rspace(newsk);
+  t1->window = ntohs(newsk->window);
+  t1->res1 = 0;
+  t1->res2 = 0;
+  t1->rst = 0;
+  t1->urg = 0;
+  t1->psh = 0;
+  t1->syn = 1;
+  t1->ack_seq = ntohl(skb->h.th->seq+1);
+  t1->doff = sizeof(*t1)/4+1;
+
+  ptr =(unsigned char *)(t1+1);
+  ptr[0] = 2;
+  ptr[1] = 4;
+  ptr[2] =((dev->mtu - HEADER_SIZE) >> 8) & 0xff;
+  ptr[3] =(dev->mtu - HEADER_SIZE) & 0xff;
+
+  tcp_send_check(t1, daddr, saddr, sizeof(*t1)+4, newsk);
+  newsk->prot->queue_xmit(newsk, dev, buff, 0);
+
+  reset_timer(newsk, TIME_WRITE /* -1 ? FIXME ??? */, TCP_CONNECT_TIME);
+  skb->sk = newsk;
+
+  /* Charge the sock_buff to newsk. */
+  sk->rmem_alloc -= skb->mem_len;
+  newsk->rmem_alloc += skb->mem_len;
+
+  skb_queue_tail(&sk->rqueue,skb);
+  sk->ack_backlog++;
+  release_sock(newsk);
 }
 
-/*
- *     Close a tcp connection
- */
 
-static void tcp_close(struct sock *sk, int timeout)
+static void
+tcp_close(struct sock *sk, int timeout)
 {
-       struct sk_buff *buff;
-       int need_reset = 0;
-       struct tcphdr *t1, *th;
-       struct proto *prot;
-       struct device *dev=NULL;
-       int tmp;
+  struct sk_buff *buff;
+  int need_reset = 0;
+  struct tcphdr *t1, *th;
+  struct proto *prot;
+  struct device *dev=NULL;
+  int tmp;
 
   /*
    * We need to grab some memory, and put together a FIN,
    * and then put it into the queue to be sent.
    */
-       DPRINTF((DBG_TCP, "tcp_close((struct sock *)%X, %d)\n",sk, timeout));
-       sk->inuse = 1;
-       sk->keepopen = 1;
-       sk->shutdown = SHUTDOWN_MASK;
-
-
-       /* We need to flush the recv. buffs. */
-       if (skb_peek(&sk->rqueue) != NULL) 
-       {
-               struct sk_buff *skb;
-               if(sk->debug)
-                       printk("Clean rcv queue\n");
-               while((skb=skb_dequeue(&sk->rqueue))!=NULL)
-               {
-                       if(skb->len > 0 && after(skb->h.th->seq + skb->len + 1 , sk->copied_seq))
-                                       need_reset = 1;
-                       kfree_skb(skb, FREE_READ);
-               }
-               if(sk->debug)
-                       printk("Cleaned.\n");
+  DPRINTF((DBG_TCP, "tcp_close((struct sock *)%X, %d)\n",sk, timeout));
+  sk->inuse = 1;
+  sk->keepopen = 1;
+  sk->shutdown = SHUTDOWN_MASK;
+
+  if (!sk->dead) wake_up(sk->sleep);
+
+  /* We need to flush the recv. buffs. */
+  if (skb_peek(&sk->rqueue) != NULL) 
+  {
+       struct sk_buff *skb;
+#ifdef OLD     
+       struct sk_buff *skb2;
+       skb = skb_peek(&sk->rqueue);
+       do {
+               skb2 =(struct sk_buff *)skb->next;
+               /* if there is some real unread data, send a reset. */
+               if (skb->len > 0 &&
+                   after(skb->h.th->seq + skb->len + 1, sk->copied_seq))
+                                                               need_reset = 1;
+               kfree_skb(skb, FREE_WRITE);
+               skb = skb2;
+       } while(skb != sk->rqueue);
+#else
+       if(sk->debug)
+               printk("Clean rcv queue\n");
+       while((skb=skb_dequeue(&sk->rqueue))!=NULL)
+       {
+               if(skb->len > 0 && after(skb->h.th->seq + skb->len + 1 , sk->copied_seq))
+                               need_reset = 1;
+               kfree_skb(skb, FREE_READ);
        }
-       sk->rqueue = NULL;
-
-       /* Get rid off any half-completed packets. */
-       if (sk->send_tmp) 
-       {
-               tcp_send_partial(sk);
-       }
-
-       switch(sk->state) 
-       {
-               case TCP_FIN_WAIT1:
-               case TCP_FIN_WAIT2:
-               case TCP_LAST_ACK:
-                       /* start a timer. */
-                       reset_timer(sk, TIME_CLOSE, 4 * sk->rtt);
-                       if (timeout) 
-                               tcp_time_wait(sk);
-                       release_sock(sk);
-                       if (!sk->dead) 
-                               sk->state_change(sk);
-                       return; /* break causes a double release - messy */
-               case TCP_TIME_WAIT:
-                       if (timeout) 
-                       {
-                               sk->state = TCP_CLOSE;
-                       }       
-                       release_sock(sk);
-                       if (!sk->dead) 
-                               sk->state_change(sk);
-                       return;
-               case TCP_LISTEN:
-                       sk->state = TCP_CLOSE;
+       if(sk->debug)
+               printk("Cleaned.\n");
+#endif
+  }
+  sk->rqueue = NULL;
+
+  /* Get rid off any half-completed packets. */
+  if (sk->send_tmp) {
+       tcp_send_partial(sk);
+  }
+
+  switch(sk->state) {
+       case TCP_FIN_WAIT1:
+       case TCP_FIN_WAIT2:
+       case TCP_LAST_ACK:
+               /* start a timer. */
+               reset_timer(sk, TIME_CLOSE, 4 * sk->rtt);
+               if (timeout) tcp_time_wait(sk);
+               release_sock(sk);
+               return; /* break causes a double release - messy */
+       case TCP_TIME_WAIT:
+               if (timeout) {
+                 sk->state = TCP_CLOSE;
+               }
+               release_sock(sk);
+               return;
+       case TCP_LISTEN:
+               sk->state = TCP_CLOSE;
+               release_sock(sk);
+               return;
+       case TCP_CLOSE:
+               release_sock(sk);
+               return;
+       case TCP_CLOSE_WAIT:
+       case TCP_ESTABLISHED:
+       case TCP_SYN_SENT:
+       case TCP_SYN_RECV:
+               prot =(struct proto *)sk->prot;
+               th =(struct tcphdr *)&sk->dummy_th;
+               buff = (struct sk_buff *) prot->wmalloc(sk, MAX_FIN_SIZE, 1, GFP_ATOMIC);
+               if (buff == NULL) {
+                       /* This will force it to try again later. */
+                       /* Or it would have if someone released the socket
+                          first. Anyway it might work now */
                        release_sock(sk);
-                       if (!sk->dead) 
-                               sk->state_change(sk);
+                       if (sk->state != TCP_CLOSE_WAIT)
+                                       sk->state = TCP_ESTABLISHED;
+                       reset_timer(sk, TIME_CLOSE, 100);
                        return;
-               case TCP_CLOSE:
+               }
+               buff->mem_addr = buff;
+               buff->mem_len = MAX_FIN_SIZE;
+               buff->sk = sk;
+               buff->free = 1;
+               buff->len = sizeof(*t1);
+               t1 =(struct tcphdr *)(buff + 1);
+
+               /* Put in the IP header and routing stuff. */
+               tmp = prot->build_header(buff,sk->saddr, sk->daddr, &dev,
+                                        IPPROTO_TCP, sk->opt,
+                                        sizeof(struct tcphdr));
+               if (tmp < 0) {
+                       kfree_skb(buff,FREE_WRITE);
+                       DPRINTF((DBG_TCP, "Unable to build header for fin.\n"));
                        release_sock(sk);
-                       if (!sk->dead) 
-                               sk->state_change(sk);
                        return;
-               case TCP_CLOSE_WAIT:
-               case TCP_ESTABLISHED:
-               case TCP_SYN_SENT:
-               case TCP_SYN_RECV:
-                       prot =(struct proto *)sk->prot;
-                       th =(struct tcphdr *)&sk->dummy_th;
-                       buff = (struct sk_buff *) prot->wmalloc(sk, MAX_FIN_SIZE, 1, GFP_ATOMIC);
-                       if (buff == NULL) 
-                       {
-                               /* This will force it to try again later. */
-                               /* Or it would have if someone released the socket
-                                  first. Anyway it might work now */
-                               release_sock(sk);
-                               if (sk->state != TCP_CLOSE_WAIT)
-                                       sk->state = TCP_ESTABLISHED;
-                               reset_timer(sk, TIME_CLOSE, 100);
-                               return;
-                       }
-                       buff->mem_addr = buff;
-                       buff->mem_len = MAX_FIN_SIZE;
-                       buff->sk = sk;
-                       buff->free = 1;
-                       buff->len = sizeof(*t1);
-                       t1 =(struct tcphdr *)(buff + 1);
-               
-                       /* Put in the IP header and routing stuff. */
-                       tmp = prot->build_header(buff,sk->saddr, sk->daddr, &dev,
-                                                IPPROTO_TCP, sk->opt,
-                                                sizeof(struct tcphdr),sk->ip_ttl,sk->ip_tos);
-       
-                       if (tmp < 0) 
-                       {
-                               kfree_skb(buff,FREE_WRITE);
-                               DPRINTF((DBG_TCP, "Unable to build header for fin.\n"));
-                               release_sock(sk);
-                               if (!sk->dead) 
-                                       sk->state_change(sk);
-                               return;
-                       }
-       
-                       t1 =(struct tcphdr *)((char *)t1 +tmp);
-                       buff ->len += tmp;
-                       buff->dev = dev;
-                       memcpy(t1, th, sizeof(*t1));
-                       t1->seq = ntohl(sk->send_seq);
-                       sk->send_seq++;
-                       buff->h.seq = sk->send_seq;
-                       t1->ack = 1;
-
-                       /* Ack everything immediately from now on. */
-                       sk->delay_acks = 0;
-                       t1->ack_seq = ntohl(sk->acked_seq);
-                       t1->window = ntohs(sk->prot->rspace(sk));
-                       t1->fin = 1;
-                       t1->rst = need_reset;
-                       t1->doff = sizeof(*t1)/4;
-                       tcp_send_check(t1, sk->saddr, sk->daddr, sizeof(*t1), sk);
-       
-                       if (sk->wfront == NULL) 
-                       {
-                               prot->queue_xmit(sk, dev, buff, 0);
-                       }
-                       else 
-                       {
-                               buff->free=0;
-                               reset_timer(sk, TIME_WRITE,backoff(sk->backoff) * (2 * sk->mdev + sk->rtt));
-                               buff->next = NULL;
-                               if (sk->wback == NULL) 
-                               {
-                                               sk->wfront=buff;
-                               } 
-                               else 
-                               {
-                                       sk->wback->next = buff;
-                               }
-                               sk->wback = buff;
-                               buff->magic = TCP_WRITE_QUEUE_MAGIC;
-                       }
+               }
 
-                       if (sk->state == TCP_CLOSE_WAIT) 
-                       {
-                               sk->state = TCP_FIN_WAIT2;
-                       } 
-                       else 
-                       {
-                               sk->state = TCP_FIN_WAIT1;
-                       }
-                       break;
-       }
-       if (!sk->dead) 
-               sk->state_change(sk);
-       release_sock(sk);
+               t1 =(struct tcphdr *)((char *)t1 +tmp);
+               buff ->len += tmp;
+               buff->dev = dev;
+               memcpy(t1, th, sizeof(*t1));
+               t1->seq = ntohl(sk->send_seq);
+               sk->send_seq++;
+               buff->h.seq = sk->send_seq;
+               t1->ack = 1;
+
+               /* Ack everything immediately from now on. */
+               sk->delay_acks = 0;
+               t1->ack_seq = ntohl(sk->acked_seq);
+               t1->window = ntohs(sk->prot->rspace(sk));
+               t1->fin = 1;
+               t1->rst = need_reset;
+               t1->doff = sizeof(*t1)/4;
+               tcp_send_check(t1, sk->saddr, sk->daddr, sizeof(*t1), sk);
+
+               if (sk->wfront == NULL) {
+                       prot->queue_xmit(sk, dev, buff, 0);
+               } else {
+                       reset_timer(sk, TIME_WRITE,
+                         backoff(sk->backoff) * (2 * sk->mdev + sk->rtt));
+                       buff->next = NULL;
+                       if (sk->wback == NULL) {
+                               sk->wfront=buff;
+                       } else {
+                               sk->wback->next = buff;
+                       }
+                       sk->wback = buff;
+                       buff->magic = TCP_WRITE_QUEUE_MAGIC;
+               }
+
+               if (sk->state == TCP_CLOSE_WAIT) {
+                       sk->state = TCP_FIN_WAIT2;
+               } else {
+                       sk->state = TCP_FIN_WAIT1;
+       }
+  }
+  release_sock(sk);
 }
 
 
 /*
- *     This routine takes stuff off of the write queue,
- *     and puts it in the xmit queue.
+ * This routine takes stuff off of the write queue,
+ * and puts it in the xmit queue.
  */
-
-static void tcp_write_xmit(struct sock *sk)
+static void
+tcp_write_xmit(struct sock *sk)
 {
-       struct sk_buff *skb;
+  struct sk_buff *skb;
 
-       DPRINTF((DBG_TCP, "tcp_write_xmit(sk=%X)\n", sk));
+  DPRINTF((DBG_TCP, "tcp_write_xmit(sk=%X)\n", sk));
 
-       /* The bytes will have to remain here. In time closedown will
-          empty the write queue and all will be happy */
-       if(sk->zapped)
-               return;
+  /* The bytes will have to remain here. In time closedown will
+     empty the write queue and all will be happy */
+  if(sk->zapped)
+       return;
 
-       while(sk->wfront != NULL &&
-               before(sk->wfront->h.seq, sk->window_seq) &&
-               sk->packets_out < sk->cong_window) 
-        {
+  while(sk->wfront != NULL &&
+        before(sk->wfront->h.seq, sk->window_seq) &&
+        sk->packets_out < sk->cong_window) {
                skb = sk->wfront;
                IS_SKB(skb);
                sk->wfront =(struct sk_buff *)skb->next;
-               if (sk->wfront == NULL) 
-                       sk->wback = NULL;
+               if (sk->wfront == NULL) sk->wback = NULL;
                skb->next = NULL;
-               if (skb->magic != TCP_WRITE_QUEUE_MAGIC) 
-               {
+               if (skb->magic != TCP_WRITE_QUEUE_MAGIC) {
                        printk("tcp.c skb with bad magic(%X) on write queue. Squashing "
                                "queue\n", skb->magic);
                        sk->wfront = NULL;
@@ -2459,15 +2085,11 @@ static void tcp_write_xmit(struct sock *sk)
                DPRINTF((DBG_TCP, "Sending a packet.\n"));
 
                /* See if we really need to send the packet. */
-               if (before(skb->h.seq, sk->rcv_ack_seq +1)) 
-               {
+               if (before(skb->h.seq, sk->rcv_ack_seq +1)) {
                        sk->retransmits = 0;
                        kfree_skb(skb, FREE_WRITE);
-                       if (!sk->dead)
-                               sk->write_space(sk);
-               } 
-               else 
-               {
+                       if (!sk->dead) wake_up(sk->sleep);
+               } else {
                        sk->prot->queue_xmit(sk, skb->dev, skb, skb->free);
                }
        }
@@ -2475,79 +2097,67 @@ static void tcp_write_xmit(struct sock *sk)
 
 
 /*
- *     This routine sorts the send list, and resets the
- *     sk->send_head and sk->send_tail pointers.
+ * This routine sorts the send list, and resets the
+ * sk->send_head and sk->send_tail pointers.
  */
-void sort_send(struct sock *sk)
+void
+sort_send(struct sock *sk)
 {
-       struct sk_buff *list = NULL;
-       struct sk_buff *skb,*skb2,*skb3;
-
-       for (skb = sk->send_head; skb != NULL; skb = skb2) 
-       {
-               skb2 = (struct sk_buff *)skb->link3;
-               if (list == NULL || before (skb2->h.seq, list->h.seq)) 
-               {
-                       skb->link3 = list;
-                       sk->send_tail = skb;
-                       list = skb;
-               } 
-               else 
-               {
-                       for (skb3 = list; ; skb3 = (struct sk_buff *)skb3->link3) 
-                       {
-                               if (skb3->link3 == NULL || before(skb->h.seq, skb3->link3->h.seq)) 
-                               {
-                                       skb->link3 = skb3->link3;
-                                       skb3->link3 = skb;
-                                       if (skb->link3 == NULL) 
-                                               sk->send_tail = skb;
-                                       break;
-                               }
+  struct sk_buff *list = NULL;
+  struct sk_buff *skb,*skb2,*skb3;
+
+  for (skb = sk->send_head; skb != NULL; skb = skb2) {
+       skb2 = (struct sk_buff *)skb->link3;
+       if (list == NULL || before (skb2->h.seq, list->h.seq)) {
+               skb->link3 = list;
+               sk->send_tail = skb;
+               list = skb;
+       } else {
+               for (skb3 = list; ; skb3 = (struct sk_buff *)skb3->link3) {
+                       if (skb3->link3 == NULL ||
+                           before(skb->h.seq, skb3->link3->h.seq)) {
+                               skb->link3 = skb3->link3;
+                               skb3->link3 = skb;
+                               if (skb->link3 == NULL) sk->send_tail = skb;
+                               break;
                        }
                }
-       }
-       sk->send_head = list;
+       }
+  }
+  sk->send_head = list;
 }
   
 
-/* 
- *     This routine deals with incoming acks, but not outgoing ones. 
- */
-static int tcp_ack(struct sock *sk, struct tcphdr *th, unsigned long saddr, int len)
+/* This routine deals with incoming acks, but not outgoing ones. */
+static int
+tcp_ack(struct sock *sk, struct tcphdr *th, unsigned long saddr, int len)
 {
-       unsigned long ack;
-       int flag = 0;
+  unsigned long ack;
+  int flag = 0;
 
-       if(sk->zapped)
-               return(1);      /* Dead, cant ack any more so why bother */
+  if(sk->zapped)
+       return(1);      /* Dead, cant ack any more so why bother */
 
-       ack = ntohl(th->ack_seq);
-       DPRINTF((DBG_TCP, "tcp_ack ack=%d, window=%d, "
-                 "sk->rcv_ack_seq=%d, sk->window_seq = %d\n",
-                 ack, ntohs(th->window), sk->rcv_ack_seq, sk->window_seq));
+  ack = ntohl(th->ack_seq);
+  DPRINTF((DBG_TCP, "tcp_ack ack=%d, window=%d, "
+         "sk->rcv_ack_seq=%d, sk->window_seq = %d\n",
+         ack, ntohs(th->window), sk->rcv_ack_seq, sk->window_seq));
 
-       if (after(ack, sk->send_seq+1) || before(ack, sk->rcv_ack_seq-1)) 
-       {
-               if (after(ack, sk->send_seq) || (sk->state != TCP_ESTABLISHED && sk->state != TCP_CLOSE_WAIT)) 
-               {
-                       return(0);
-               }
-               if (sk->keepopen) 
-               {
-                       reset_timer(sk, TIME_KEEPOPEN, TCP_TIMEOUT_LEN);
-               }
-               return(1);
-       }
+  if (after(ack, sk->send_seq+1) || before(ack, sk->rcv_ack_seq-1)) {
+       if (after(ack, sk->send_seq) ||
+          (sk->state != TCP_ESTABLISHED && sk->state != TCP_CLOSE_WAIT)) {
+               return(0);
+       }
+       if (sk->keepopen) {
+               reset_timer(sk, TIME_KEEPOPEN, TCP_TIMEOUT_LEN);
+       }
+       return(1);
+  }
 
-       if (len != th->doff*4) 
-               flag |= 1;
+  if (len != th->doff*4) flag |= 1;
 
-       /* See if our window has been shrunk. */
-       if (after(sk->window_seq, ack+ntohs(th->window))) 
-       {
+  /* See if our window has been shrunk. */
+  if (after(sk->window_seq, ack+ntohs(th->window))) {
        /*
         * We may need to move packets from the send queue
         * to the write queue, if the window has been shrunk on us.
@@ -2555,312 +2165,271 @@ static int tcp_ack(struct sock *sk, struct tcphdr *th, unsigned long saddr, int
         * like this, but if the other end does, you must be able
         * to deal with it.
         */
-               struct sk_buff *skb;
-               struct sk_buff *skb2;
-               struct sk_buff *wskb = NULL;
+       struct sk_buff *skb;
+       struct sk_buff *skb2;
+       struct sk_buff *wskb = NULL;
   
-               skb2 = sk->send_head;
-               sk->send_head = NULL;
-               sk->send_tail = NULL;
+       skb2 = sk->send_head;
+       sk->send_head = NULL;
+       sk->send_tail = NULL;
 
-               flag |= 4;
+       flag |= 4;
 
-               sk->window_seq = ack + ntohs(th->window);
-               cli();
-               while (skb2 != NULL) 
-               {
-                       skb = skb2;
-                       skb2 = (struct sk_buff *)skb->link3;
-                       skb->link3 = NULL;
-                       if (after(skb->h.seq, sk->window_seq)) 
-                       {
-                               if (sk->packets_out > 0) 
-                                       sk->packets_out--;
-                               /*
-                                *      We may need to remove this from the dev send list. 
-                                */
-                       
-                               if (skb->next != NULL) 
-                               {
-                                       skb_unlink(skb);                                
+       sk->window_seq = ack + ntohs(th->window);
+       cli();
+       while (skb2 != NULL) {
+               skb = skb2;
+               skb2 = (struct sk_buff *)skb->link3;
+               skb->link3 = NULL;
+               if (after(skb->h.seq, sk->window_seq)) {
+                       if (sk->packets_out > 0) sk->packets_out--;
+                       /* We may need to remove this from the dev send list. */
+                       if (skb->next != NULL) {
+#ifdef OLD_WAY                 
+                               int i;
+
+                               if (skb->next != skb) {
+                                       skb->next->prev = skb->prev;
+                                       skb->prev->next = skb->next;
                                }
-                               /* Now add it to the write_queue. */
-                               skb->magic = TCP_WRITE_QUEUE_MAGIC;
-                               if (wskb == NULL) 
-                               {
-                                       skb->next = sk->wfront;
-                                       sk->wfront = skb;
-                               } 
-                               else 
-                               {
-                                       skb->next = wskb->next;
-                                       wskb->next = skb;
+
+                               for(i = 0; i < DEV_NUMBUFFS; i++) {
+                                       if (skb->dev->buffs[i] == skb) {
+                                               if (skb->next == skb)
+                                                       skb->dev->buffs[i] = NULL;
+                                                 else
+                                                       skb->dev->buffs[i] = skb->next;
+                                               break;
+                                       }
                                }
-                               if (sk->wback == wskb) 
-                                       sk->wback = skb;
-                               wskb = skb;
-                       } 
-                       else 
-                       {
-                               if (sk->send_head == NULL) 
-                               {
-                                       sk->send_head = skb;
-                                       sk->send_tail = skb;
-                               } 
-                               else 
-                               {
-                                       sk->send_tail->link3 = skb;
-                                       sk->send_tail = skb;
+                               if (arp_q == skb) {
+                                       if (skb->next == skb) arp_q = NULL;
+                                         else arp_q = skb->next;
                                }
-                               skb->link3 = NULL;
+#else
+                               skb_unlink(skb);                                
+#endif                         
                        }
+                       /* Now add it to the write_queue. */
+                       skb->magic = TCP_WRITE_QUEUE_MAGIC;
+                       if (wskb == NULL) {
+                               skb->next = sk->wfront;
+                               sk->wfront = skb;
+                       } else {
+                               skb->next = wskb->next;
+                               wskb->next = skb;
+                       }
+                       if (sk->wback == wskb) sk->wback = skb;
+                       wskb = skb;
+               } else {
+                       if (sk->send_head == NULL) {
+                               sk->send_head = skb;
+                               sk->send_tail = skb;
+                       } else {
+                               sk->send_tail->link3 = skb;
+                               sk->send_tail = skb;
+                       }
+                       skb->link3 = NULL;
                }
-               sti();
-       }
-
-       if (sk->send_tail == NULL || sk->send_head == NULL) 
-       {
-               sk->send_head = NULL;
-               sk->send_tail = NULL;
-               sk->packets_out= 0;
-       }
-
-       sk->window_seq = ack + ntohs(th->window);
-
-       /* We don't want too many packets out there. */
-       if (sk->cong_window < 2048 && ack != sk->rcv_ack_seq) 
-       {
-               if (sk->exp_growth) 
-                       sk->cong_window *= 2;
-               else 
-                       sk->cong_window++;
-       }
-
-       DPRINTF((DBG_TCP, "tcp_ack: Updating rcv ack sequence.\n"));
-       sk->rcv_ack_seq = ack;
-
-       /* See if we can take anything off of the retransmit queue. */
-       while(sk->send_head != NULL) 
-       {
-               /* Check for a bug. */
-               if (sk->send_head->link3 && after(sk->send_head->h.seq, sk->send_head->link3->h.seq)) 
-               {
-                       printk("INET: tcp.c: *** bug send_list out of order.\n");
-                       sort_send(sk);
-               }
+       }
+       sti();
+  }
+
+  if (sk->send_tail == NULL || sk->send_head == NULL) {
+       sk->send_head = NULL;
+       sk->send_tail = NULL;
+       sk->packets_out= 0;
+  }
+
+  sk->window_seq = ack + ntohs(th->window);
+
+  /* We don't want too many packets out there. */
+  if (sk->cong_window < 2048 && ack != sk->rcv_ack_seq) {
+       if (sk->exp_growth) sk->cong_window *= 2;
+         else sk->cong_window++;
+  }
+
+  DPRINTF((DBG_TCP, "tcp_ack: Updating rcv ack sequence.\n"));
+  sk->rcv_ack_seq = ack;
+
+  /* See if we can take anything off of the retransmit queue. */
+  while(sk->send_head != NULL) {
+       /* Check for a bug. */
+       if (sk->send_head->link3 &&
+           after(sk->send_head->h.seq, sk->send_head->link3->h.seq)) {
+               printk("INET: tcp.c: *** bug send_list out of order.\n");
+               sort_send(sk);
+       }
 
-               if (before(sk->send_head->h.seq, ack+1)) 
-               {
-                       struct sk_buff *oskb;
+       if (before(sk->send_head->h.seq, ack+1)) {
+               struct sk_buff *oskb;
 
-                       sk->retransmits = 0;
+               sk->retransmits = 0;
 
-                       /* We have one less packet out there. */
-                       if (sk->packets_out > 0) 
-                               sk->packets_out --;
-                       DPRINTF((DBG_TCP, "skb=%X skb->h.seq = %d acked ack=%d\n",
+               /* We have one less packet out there. */
+               if (sk->packets_out > 0) sk->packets_out --;
+               DPRINTF((DBG_TCP, "skb=%X skb->h.seq = %d acked ack=%d\n",
                                sk->send_head, sk->send_head->h.seq, ack));
 
-                       /* Wake up the process, it can probably write more. */
-                       if (!sk->dead) 
-                               sk->write_space(sk);
+               /* Wake up the process, it can probably write more. */
+               if (!sk->dead) wake_up(sk->sleep);
 
-                       oskb = sk->send_head;
+               oskb = sk->send_head;
 
-                       /* Estimate the RTT. Ignore the ones right after a retransmit. */
-       
-                       if (sk->retransmits == 0 && !(flag&2)) 
-                       {
-                               long abserr, rtt = jiffies - oskb->when;
-
-                               if (sk->state == TCP_SYN_SENT || sk->state == TCP_SYN_RECV)
-                               /* first ack, so nothing else to average with */
-                                       sk->rtt = rtt;
-                               else 
-                               {
-                                       abserr = (rtt > sk->rtt) ? rtt - sk->rtt : sk->rtt - rtt;
-                                       sk->rtt = (7 * sk->rtt + rtt) >> 3;
-                                       sk->mdev = (3 * sk->mdev + abserr) >> 2;
-                               }
-                               sk->backoff = 0;
-                       }
-                       flag |= (2|4);
-                       /* no point retransmitting faster than .1 sec */
-                       /* 2 minutes is max legal rtt for Internet */
-                       
-                       if (sk->rtt < 10) 
-                               sk->rtt = 10;
-                               
-                       if (sk->rtt > 12000) 
-                               sk->rtt = 12000;
-
-                       cli();
-
-                       oskb = sk->send_head;
-                       IS_SKB(oskb);
-                       sk->send_head =(struct sk_buff *)oskb->link3;
-                       if (sk->send_head == NULL) 
-                       {
-                               sk->send_tail = NULL;
-                       }
+               /* Estimate the RTT. Ignore the ones right after a retransmit. */
+               if (sk->retransmits == 0 && !(flag&2)) {
+                 long abserr, rtt = jiffies - oskb->when;
 
-                       /* We may need to remove this from the dev send list. */                
-                       skb_unlink(oskb);       /* Much easier! */
-                       sti();
-                       oskb->magic = 0;
-                       kfree_skb(oskb, FREE_WRITE); /* write. */
-                       if (!sk->dead) 
-                               sk->write_space(sk);
-               } 
-               else 
-               {
-                       break;
+                 if (sk->state == TCP_SYN_SENT || sk->state == TCP_SYN_RECV)
+                   /* first ack, so nothing else to average with */
+                   sk->rtt = rtt;
+                 else {
+                   abserr = (rtt > sk->rtt) ? rtt - sk->rtt : sk->rtt - rtt;
+                   sk->rtt = (7 * sk->rtt + rtt) >> 3;
+                   sk->mdev = (3 * sk->mdev + abserr) >> 2;
+                 }
+                 sk->backoff = 0;
                }
-       }
+               flag |= (2|4);
+               /* no point retransmitting faster than .1 sec */
+               /* 2 minutes is max legal rtt for Internet */
+               if (sk->rtt < 10) sk->rtt = 10;
+               if (sk->rtt > 12000) sk->rtt = 12000;
 
-       /*
-        * Maybe we can take some stuff off of the write queue,
-        * and put it onto the xmit queue.
-        */
-       if (sk->wfront != NULL) 
-       {
-               if (after (sk->window_seq, sk->wfront->h.seq) && sk->packets_out < sk->cong_window) 
-               {
-                       flag |= 1;
-                       tcp_write_xmit(sk);
-               }
-       } 
-       else 
-       {
-               if (sk->send_head == NULL && sk->ack_backlog == 0 && sk->state != TCP_TIME_WAIT && !sk->keepopen) 
-               {
-                       DPRINTF((DBG_TCP, "Nothing to do, going to sleep.\n")); 
-                       if (!sk->dead) 
-                               sk->write_space(sk);
-
-                       if (sk->keepopen)
-                               reset_timer(sk, TIME_KEEPOPEN, TCP_TIMEOUT_LEN);
-                       else
-                               delete_timer(sk);
-               } 
-               else 
-               {
-                       if (sk->state != (unsigned char) sk->keepopen) 
-                       {
-                               reset_timer(sk, TIME_WRITE, backoff(sk->backoff) * (2 * sk->mdev + sk->rtt));
-                       }
-                       if (sk->state == TCP_TIME_WAIT) 
-                       {
-                               reset_timer(sk, TIME_CLOSE, TCP_TIMEWAIT_LEN);
-                       }
+               cli();
+
+               oskb = sk->send_head;
+               IS_SKB(oskb);
+               sk->send_head =(struct sk_buff *)oskb->link3;
+               if (sk->send_head == NULL) {
+                       sk->send_tail = NULL;
                }
-       }
 
-       /*
-        *      If we have nothing left to send then send the packet we are currently assembling
-        */
-        
-       if (sk->packets_out == 0 && sk->send_tmp != NULL && sk->wfront == NULL && sk->send_head == NULL) 
-       {
+               /* We may need to remove this from the dev send list. */                
+               skb_unlink(oskb);       /* Much easier! */
+               sti();
+               oskb->magic = 0;
+               kfree_skb(oskb, FREE_WRITE); /* write. */
+               if (!sk->dead) wake_up(sk->sleep);
+       } else {
+               break;
+       }
+  }
+
+  /*
+   * Maybe we can take some stuff off of the write queue,
+   * and put it onto the xmit queue.
+   */
+  if (sk->wfront != NULL) {
+       if (after (sk->window_seq, sk->wfront->h.seq) &&
+               sk->packets_out < sk->cong_window) {
                flag |= 1;
-               tcp_send_partial(sk);
-       }
+               tcp_write_xmit(sk);
+       }
+  } else {
+       if (sk->send_head == NULL && sk->ack_backlog == 0 &&
+           sk->state != TCP_TIME_WAIT && !sk->keepopen) {
+               DPRINTF((DBG_TCP, "Nothing to do, going to sleep.\n")); 
+               if (!sk->dead) wake_up(sk->sleep);
 
-       /* See if we are done. */
-       if (sk->state == TCP_TIME_WAIT) 
-       {
-                       
-               /*
-                *      Our FIN has been acknowledged
-                */
-                
-               if (sk->rcv_ack_seq == sk->send_seq && sk->acked_seq == sk->fin_seq) 
-               {
-                       flag |= 1;
-                       sk->state = TCP_CLOSE;
-                       sk->shutdown = SHUTDOWN_MASK;
-                       if (!sk->dead) 
-                               sk->state_change(sk);
+               if (sk->keepopen)
+                       reset_timer(sk, TIME_KEEPOPEN, TCP_TIMEOUT_LEN);
+               else
+                       delete_timer(sk);
+       } else {
+               if (sk->state != (unsigned char) sk->keepopen) {
+                       reset_timer(sk, TIME_WRITE,
+                         backoff(sk->backoff) * (2 * sk->mdev + sk->rtt));
                }
-       }
+               if (sk->state == TCP_TIME_WAIT) {
+                       reset_timer(sk, TIME_CLOSE, TCP_TIMEWAIT_LEN);
+               }
+       }
+  }
+
+  if (sk->packets_out == 0 && sk->send_tmp != NULL &&
+      sk->wfront == NULL && sk->send_head == NULL) {
+       flag |= 1;
+       tcp_send_partial(sk);
+  }
+
+  /* See if we are done. */
+  if (sk->state == TCP_TIME_WAIT) {
+       if (!sk->dead) wake_up(sk->sleep);
+       if (sk->rcv_ack_seq == sk->send_seq && sk->acked_seq == sk->fin_seq) {
+               flag |= 1;
+               sk->state = TCP_CLOSE;
+               sk->shutdown = SHUTDOWN_MASK;
+       }
+  }
 
-       if (sk->state == TCP_LAST_ACK || sk->state == TCP_FIN_WAIT2) 
-       {
-               if (sk->rcv_ack_seq == sk->send_seq) 
-               {
-                       flag |= 1;
-                       if (sk->acked_seq != sk->fin_seq) 
-                       {
-                               tcp_time_wait(sk);
-                       } 
-                       else 
-                       {
-                               DPRINTF((DBG_TCP, "tcp_ack closing socket - %X\n", sk));
-                               tcp_send_ack(sk->send_seq, sk->acked_seq, sk,
+  if (sk->state == TCP_LAST_ACK || sk->state == TCP_FIN_WAIT2) {
+       if (!sk->dead) wake_up(sk->sleep);
+       if (sk->rcv_ack_seq == sk->send_seq) {
+               flag |= 1;
+               if (sk->acked_seq != sk->fin_seq) {
+                       tcp_time_wait(sk);
+               } else {
+                       DPRINTF((DBG_TCP, "tcp_ack closing socket - %X\n", sk));
+                       tcp_send_ack(sk->send_seq, sk->acked_seq, sk,
                                     th, sk->daddr);
-                               sk->shutdown = SHUTDOWN_MASK;
-                               sk->state = TCP_CLOSE;
-                       }
+                       sk->shutdown = SHUTDOWN_MASK;
+                       sk->state = TCP_CLOSE;
                }
-               if (!sk->dead) 
-                       sk->state_change(sk);
-               
-       }
-
-       if (((!flag) || (flag&4)) && sk->send_head != NULL && (sk->send_head->when + backoff(sk->backoff) * (2 * sk->mdev + sk->rtt) < jiffies)) 
-       {
-               sk->exp_growth = 0;
-               ip_retransmit(sk, 0);
        }
+  }
 
-       DPRINTF((DBG_TCP, "leaving tcp_ack\n"));
-       return(1);
+  if (((!flag) || (flag&4)) && sk->send_head != NULL &&
+      (sk->send_head->when + backoff(sk->backoff) * (2 * sk->mdev + sk->rtt)
+       < jiffies)) {
+       sk->exp_growth = 0;
+       ip_retransmit(sk, 0);
+  }
+
+  DPRINTF((DBG_TCP, "leaving tcp_ack\n"));
+  return(1);
 }
 
 
 /*
- *     This routine handles the data.  If there is room in the buffer,
- *     it will be have already been moved into it.  If there is no
- *     room, then we will just have to discard the packet.
+ * This routine handles the data.  If there is room in the buffer,
+ * it will be have already been moved into it.  If there is no
+ * room, then we will just have to discard the packet.
  */
-static int tcp_data(struct sk_buff *skb, struct sock *sk, 
+static int
+tcp_data(struct sk_buff *skb, struct sock *sk, 
         unsigned long saddr, unsigned short len)
 {
-       struct sk_buff *skb1, *skb2;
-       struct tcphdr *th;
-       int dup_dumped=0;
-
-       th = skb->h.th;
-       print_th(th);
-  
-       skb->len = len -(th->doff*4);
-
-       DPRINTF((DBG_TCP, "tcp_data len = %d sk = %X:\n", skb->len, sk));
-
-       sk->bytes_rcv += skb->len;
-       if (skb->len == 0 && !th->fin && !th->urg && !th->psh) 
-       {
-               /* Don't want to keep passing ack's back and forth. */
-               if (!th->ack) 
-                       tcp_send_ack(sk->send_seq, sk->acked_seq,sk, th, saddr);
-               kfree_skb(skb, FREE_READ);
-               return(0);
-       }
-
-       if (sk->shutdown & RCV_SHUTDOWN) 
-       {
-               sk->acked_seq = th->seq + skb->len + th->syn + th->fin;
-               tcp_reset(sk->saddr, sk->daddr, skb->h.th, sk->prot, NULL, skb->dev);
-               sk->state = TCP_CLOSE;
-               sk->err = EPIPE;
-               sk->shutdown = SHUTDOWN_MASK;
-               DPRINTF((DBG_TCP, "tcp_data: closing socket - %X\n", sk));
-               kfree_skb(skb, FREE_READ);
-               if (!sk->dead) 
-                       sk->state_change(sk);
-               return(0);
-       }
+  struct sk_buff *skb1, *skb2;
+  struct tcphdr *th;
+  int dup_dumped=0;
+
+  th = skb->h.th;
+  print_th(th);
+  skb->len = len -(th->doff*4);
+
+  DPRINTF((DBG_TCP, "tcp_data len = %d sk = %X:\n", skb->len, sk));
+
+  sk->bytes_rcv += skb->len;
+  if (skb->len == 0 && !th->fin && !th->urg && !th->psh) {
+       /* Don't want to keep passing ack's back and forth. */
+       if (!th->ack) tcp_send_ack(sk->send_seq, sk->acked_seq,sk, th, saddr);
+       kfree_skb(skb, FREE_READ);
+       return(0);
+  }
+
+  if (sk->shutdown & RCV_SHUTDOWN) {
+       sk->acked_seq = th->seq + skb->len + th->syn + th->fin;
+       tcp_reset(sk->saddr, sk->daddr, skb->h.th,
+       sk->prot, NULL, skb->dev);
+       sk->state = TCP_CLOSE;
+       sk->err = EPIPE;
+       sk->shutdown = SHUTDOWN_MASK;
+       DPRINTF((DBG_TCP, "tcp_data: closing socket - %X\n", sk));
+       kfree_skb(skb, FREE_READ);
+       if (!sk->dead) wake_up(sk->sleep);
+       return(0);
+  }
 
   /*
    * Now we have to walk the chain, and figure out where this one
@@ -2870,482 +2439,430 @@ static int tcp_data(struct sk_buff *skb, struct sock *sk,
    * out of order we will be able to fit things in nicely.
    */
 
-       /* 
-        *      This should start at the last one, and then go around forwards. 
-        */
-        
-       if (sk->rqueue == NULL) 
-       {
-               DPRINTF((DBG_TCP, "tcp_data: skb = %X:\n", skb));
-               skb_queue_head(&sk->rqueue,skb);
-               skb1= NULL;
-       } 
-       else 
-       {
-               DPRINTF((DBG_TCP, "tcp_data adding to chain sk = %X:\n", sk));
-               for(skb1=sk->rqueue->prev; ; skb1 =(struct sk_buff *)skb1->prev) 
+  /* This should start at the last one, and then go around forwards. */
+  if (sk->rqueue == NULL) {
+       DPRINTF((DBG_TCP, "tcp_data: skb = %X:\n", skb));
+#ifdef OLDWAY
+       sk->rqueue = skb;
+       skb->next = skb;
+       skb->prev = skb;
+       skb->list = &sk->rqueue;
+#else
+       skb_queue_head(&sk->rqueue,skb);
+#endif         
+       skb1= NULL;
+  } else {
+       DPRINTF((DBG_TCP, "tcp_data adding to chain sk = %X:\n", sk));
+       for(skb1=sk->rqueue->prev; ; skb1 =(struct sk_buff *)skb1->prev) {
+               if(sk->debug)
                {
-                       if(sk->debug)
-                       {
-                               printk("skb1=%p :", skb1);
-                               printk("skb1->h.th->seq = %ld: ", skb1->h.th->seq);
-                               printk("skb->h.th->seq = %ld\n",skb->h.th->seq);
-                               printk("copied_seq = %ld acked_seq = %ld\n", sk->copied_seq,
-                                               sk->acked_seq);
-                       }
-                       if (th->seq==skb1->h.th->seq && skb->len>= skb1->len)
-                       {
-                               skb_append(skb1,skb);
-                               skb_unlink(skb1);
-                               kfree_skb(skb1,FREE_READ);
-                               dup_dumped=1;
-                               skb1=NULL;
-                               break;
-                       }
-                       if (after(th->seq+1, skb1->h.th->seq))
-                       {
-                               skb_append(skb1,skb);
-                               break;
-                       }
-                       if (skb1 == sk->rqueue)
-                       {
-                               skb_queue_head(&sk->rqueue, skb);               
-                               break;
-                       }
+                       printk("skb1=%p :", skb1);
+                       printk("skb1->h.th->seq = %ld: ", skb1->h.th->seq);
+                       printk("skb->h.th->seq = %ld\n",skb->h.th->seq);
+                       printk("copied_seq = %ld acked_seq = %ld\n", sk->copied_seq,
+                                       sk->acked_seq);
                }
-               DPRINTF((DBG_TCP, "skb = %X:\n", skb));
-       }
+#ifdef OLD             
+               if (after(th->seq+1, skb1->h.th->seq)) {
+                       skb->prev = skb1;
+                       skb->next = skb1->next;
+                       skb->next->prev = skb;
+                       skb1->next = skb;
+                       if (skb1 == sk->rqueue) sk->rqueue = skb;
+                       break;
+               }
+               if (skb1->prev == sk->rqueue) {
+                       skb->next= skb1;
+                       skb->prev = skb1->prev;
+                       skb->prev->next = skb;
+                       skb1->prev = skb;
+                       skb1 = NULL; /* so we know we might be able
+                                       to ack stuff. */
+                       break;
+               }
+#else
+               if (th->seq==skb1->h.th->seq && skb->len>= skb1->len)
+               {
+                       skb_append(skb1,skb);
+                       skb_unlink(skb1);
+                       kfree_skb(skb1,FREE_READ);
+                       dup_dumped=1;
+                       skb1=NULL;
+                       break;
+               }
+               if (after(th->seq+1, skb1->h.th->seq))
+               {
+                       skb_append(skb1,skb);
+                       break;
+               }
+               if (skb1 == sk->rqueue)
+               {
+                       skb_queue_head(&sk->rqueue, skb);               
+                       break;
+               }
+#endif         
+       }
+       DPRINTF((DBG_TCP, "skb = %X:\n", skb));
+  }
+
+  th->ack_seq = th->seq + skb->len;
+  if (th->syn) th->ack_seq++;
+  if (th->fin) th->ack_seq++;
+
+  if (before(sk->acked_seq, sk->copied_seq)) {
+       printk("*** tcp.c:tcp_data bug acked < copied\n");
+       sk->acked_seq = sk->copied_seq;
+  }
+
+  /* Now figure out if we can ack anything. */
+  if ((!dup_dumped && (skb1 == NULL || skb1->acked)) || before(th->seq, sk->acked_seq+1)) {
+      if (before(th->seq, sk->acked_seq+1)) {
+               if (after(th->ack_seq, sk->acked_seq))
+                                       sk->acked_seq = th->ack_seq;
+               skb->acked = 1;
+
+               /* When we ack the fin, we turn on the RCV_SHUTDOWN flag. */
+               if (skb->h.th->fin) {
+                       if (!sk->dead) wake_up(sk->sleep);
+                       sk->shutdown |= RCV_SHUTDOWN;
+               }
+         
+               for(skb2 = (struct sk_buff *)skb->next;
+                   skb2 !=(struct sk_buff *) sk->rqueue;
+                   skb2 = (struct sk_buff *)skb2->next) {
+                       if (before(skb2->h.th->seq, sk->acked_seq+1)) {
+                               if (after(skb2->h.th->ack_seq, sk->acked_seq))
+                                       sk->acked_seq = skb2->h.th->ack_seq;
+                               skb2->acked = 1;
 
-       th->ack_seq = th->seq + skb->len;
-       
-       if (th->syn) 
-               th->ack_seq++;
-  
-       if (th->fin) 
-               th->ack_seq++;
-
-       if (before(sk->acked_seq, sk->copied_seq)) 
-       {
-               printk("*** tcp.c:tcp_data bug acked < copied\n");
-               sk->acked_seq = sk->copied_seq;
-       }
-
-       /* Now figure out if we can ack anything. */
-  
-       if ((!dup_dumped && (skb1 == NULL || skb1->acked)) || before(th->seq, sk->acked_seq+1)) 
-       {
-               if (before(th->seq, sk->acked_seq+1)) 
-               {
-                       if (after(th->ack_seq, sk->acked_seq))
-                               sk->acked_seq = th->ack_seq;
-                       skb->acked = 1;
-
-                       /* When we ack the fin, we turn on the RCV_SHUTDOWN flag. */
-                       if (skb->h.th->fin) 
-                       {
-                               if (!sk->dead) 
-                                       sk->state_change(sk);
-                               sk->shutdown |= RCV_SHUTDOWN;
-                       }
-         
-                       for(skb2 = (struct sk_buff *)skb->next;
-                       skb2 !=(struct sk_buff *) sk->rqueue;
-                       skb2 = (struct sk_buff *)skb2->next) 
-                       {
-                               if (before(skb2->h.th->seq, sk->acked_seq+1)) 
-                               {
-                                       if (after(skb2->h.th->ack_seq, sk->acked_seq))
-                                               sk->acked_seq = skb2->h.th->ack_seq;
-                                       skb2->acked = 1;
-
-                                       /*
-                                        * When we ack the fin, we turn on
-                                        * the RCV_SHUTDOWN flag.
-                                        */
-                                       if (skb2->h.th->fin) 
-                                       {
-                                               sk->shutdown |= RCV_SHUTDOWN;
-                                               if (!sk->dead) 
-                                                       sk->state_change(sk);
-                                       }
-
-                                       /* Force an immediate ack. */
-                                       sk->ack_backlog = sk->max_ack_backlog;
-                               } 
-                               else 
-                               {
-                                       break;
+                               /*
+                                * When we ack the fin, we turn on
+                                * the RCV_SHUTDOWN flag.
+                                */
+                               if (skb2->h.th->fin) {
+                                       sk->shutdown |= RCV_SHUTDOWN;
+                                       if (!sk->dead) wake_up(sk->sleep);
                                }
-                       }
 
-                       /*
-                        * This also takes care of updating the window.
-                        * This if statement needs to be simplified.
-                        */
-                       if (!sk->delay_acks || sk->ack_backlog >= sk->max_ack_backlog || 
-                               sk->bytes_rcv > sk->max_unacked || th->fin) 
-                       {
-/*                             tcp_send_ack(sk->send_seq, sk->acked_seq,sk,th, saddr); */
-                       } 
-                       else 
-                       {
-                               sk->ack_backlog++;
-                               if(sk->debug)
-                                       printk("Ack queued.\n");
-                               reset_timer(sk, TIME_WRITE, TCP_ACK_TIME);
+                               /* Force an immediate ack. */
+                               sk->ack_backlog = sk->max_ack_backlog;
+                       } else {
+                               break;
                        }
                }
-       }
 
-       /*
-        * If we've missed a packet, send an ack.
-        * Also start a timer to send another.
-        */
-       if (!skb->acked) 
-       {
                /*
-                * This is important.  If we don't have much room left,
-                * we need to throw out a few packets so we have a good
-                * window.
+                * This also takes care of updating the window.
+                * This if statement needs to be simplified.
                 */
-               while (sk->prot->rspace(sk) < sk->mtu) 
-               {
-                       skb1 = skb_peek(&sk->rqueue);
-                       if (skb1 == NULL) 
-                       {
-                               printk("INET: tcp.c:tcp_data memory leak detected.\n");
-                               break;
-                       }
-
-                       /* Don't throw out something that has been acked. */
-                       if (skb1->acked) 
-                       {
-                               break;
-                       }
-               
-                       skb_unlink(skb1);
-                       kfree_skb(skb1, FREE_READ);
+               if (!sk->delay_acks ||
+                   sk->ack_backlog >= sk->max_ack_backlog || 
+                   sk->bytes_rcv > sk->max_unacked || th->fin) {
+/*                     tcp_send_ack(sk->send_seq, sk->acked_seq,sk,th, saddr); */
+               } else {
+                       sk->ack_backlog++;
+                       if(sk->debug)
+                               printk("Ack queued.\n");
+                       reset_timer(sk, TIME_WRITE, TCP_ACK_TIME);
                }
-               tcp_send_ack(sk->send_seq, sk->acked_seq, sk, th, saddr);
-               sk->ack_backlog++;
-               reset_timer(sk, TIME_WRITE, TCP_ACK_TIME);
-       } 
-       else 
-       {
-               /* We missed a packet.  Send an ack to try to resync things. */
-               tcp_send_ack(sk->send_seq, sk->acked_seq, sk, th, saddr);
-       }
-
-       /* Now tell the user we may have some data. */
-       if (!sk->dead) 
-       {
-               if(sk->debug)
-                       printk("Data wakeup.\n");
-               sk->data_ready(sk,0);
-       } 
-       else 
-       {
-               DPRINTF((DBG_TCP, "data received on dead socket.\n"));
-       }
+       }
+  }
 
-       if (sk->state == TCP_FIN_WAIT2 && sk->acked_seq == sk->fin_seq && sk->rcv_ack_seq == sk->send_seq) 
-       {
-               DPRINTF((DBG_TCP, "tcp_data: entering last_ack state sk = %X\n", sk));
+  /*
+   * If we've missed a packet, send an ack.
+   * Also start a timer to send another.
+   */
+  if (!skb->acked) {
+       /*
+        * This is important.  If we don't have much room left,
+        * we need to throw out a few packets so we have a good
+        * window.
+        */
+       while (sk->prot->rspace(sk) < sk->mtu) {
+               skb1 = skb_peek(&sk->rqueue);
+               if (skb1 == NULL) {
+                       printk("INET: tcp.c:tcp_data memory leak detected.\n");
+                       break;
+               }
 
-/*             tcp_send_ack(sk->send_seq, sk->acked_seq, sk, th, saddr); */
-               sk->shutdown = SHUTDOWN_MASK;
-               sk->state = TCP_LAST_ACK;
-               if (!sk->dead) 
-                       sk->state_change(sk);
+               /* Don't throw out something that has been acked. */
+               if (skb1->acked) {
+                       break;
+               }
+               
+               skb_unlink(skb1);
+#ifdef OLDWAY          
+               if (skb1->prev == skb1) {
+                       sk->rqueue = NULL;
+               } else {
+                       sk->rqueue = (struct sk_buff *)skb1->prev;
+                       skb1->next->prev = skb1->prev;
+                       skb1->prev->next = skb1->next;
+               }
+#endif         
+               kfree_skb(skb1, FREE_READ);
        }
+       tcp_send_ack(sk->send_seq, sk->acked_seq, sk, th, saddr);
+       sk->ack_backlog++;
+       reset_timer(sk, TIME_WRITE, TCP_ACK_TIME);
+  } else {
+       /* We missed a packet.  Send an ack to try to resync things. */
+       tcp_send_ack(sk->send_seq, sk->acked_seq, sk, th, saddr);
+  }
+
+  /* Now tell the user we may have some data. */
+  if (!sk->dead) {
+        if(sk->debug)
+               printk("Data wakeup.\n");
+       wake_up(sk->sleep);
+  } else {
+       DPRINTF((DBG_TCP, "data received on dead socket.\n"));
+  }
+
+  if (sk->state == TCP_FIN_WAIT2 &&
+      sk->acked_seq == sk->fin_seq && sk->rcv_ack_seq == sk->send_seq) {
+       DPRINTF((DBG_TCP, "tcp_data: entering last_ack state sk = %X\n", sk));
+
+/*     tcp_send_ack(sk->send_seq, sk->acked_seq, sk, th, saddr); */
+       sk->shutdown = SHUTDOWN_MASK;
+       sk->state = TCP_LAST_ACK;
+       if (!sk->dead) wake_up(sk->sleep);
+  }
 
-       return(0);
+  return(0);
 }
 
 
-static int tcp_urg(struct sock *sk, struct tcphdr *th, unsigned long saddr)
+static int
+tcp_urg(struct sock *sk, struct tcphdr *th, unsigned long saddr)
 {
-       extern int kill_pg(int pg, int sig, int priv);
-       extern int kill_proc(int pid, int sig, int priv);
+  extern int kill_pg(int pg, int sig, int priv);
+  extern int kill_proc(int pid, int sig, int priv);
     
-       if (!sk->dead) 
-               sk->data_ready(sk,0);
+  if (!sk->dead) wake_up(sk->sleep);
     
-       if (sk->urginline) 
-       {
-               th->urg = 0;
-               th->psh = 1;
-               return(0);
-       }
-
-       if (!sk->urg) 
-       {
-               /* So if we get more urgent data, we don't signal the user again. */
-               if (sk->proc != 0) 
-               {
-                       if (sk->proc > 0) 
-                       {
-                               kill_proc(sk->proc, SIGURG, 1);
-                       } 
-                       else 
-                       {
-                               kill_pg(-sk->proc, SIGURG, 1);
-                       }
+  if (sk->urginline) {
+       th->urg = 0;
+       th->psh = 1;
+       return(0);
+  }
+
+  if (!sk->urg) {
+       /* So if we get more urgent data, we don't signal the user again. */
+       if (sk->proc != 0) {
+               if (sk->proc > 0) {
+                       kill_proc(sk->proc, SIGURG, 1);
+               } else {
+                       kill_pg(-sk->proc, SIGURG, 1);
                }
-       }
-       sk->urg++;
-       return(0);
+       }
+  }
+  sk->urg++;
+  return(0);
 }
 
 
-/* 
- *     This deals with incoming fins.  [Page 75]
- */
-
-static int tcp_fin(struct sock *sk, struct tcphdr *th, 
+/* This deals with incoming fins. */
+static int
+tcp_fin(struct sock *sk, struct tcphdr *th, 
         unsigned long saddr, struct device *dev)
 {
-       DPRINTF((DBG_TCP, "tcp_fin(sk=%X, th=%X, saddr=%X, dev=%X)\n",
+  DPRINTF((DBG_TCP, "tcp_fin(sk=%X, th=%X, saddr=%X, dev=%X)\n",
                                                sk, th, saddr, dev));
   
+  if (!sk->dead) {
+       wake_up(sk->sleep);
+  }
+
+  switch(sk->state) {
+       case TCP_SYN_RECV:
+       case TCP_SYN_SENT:
+       case TCP_ESTABLISHED:
+               /* Contains the one that needs to be acked */
+               sk->fin_seq = th->seq+1;
+               sk->state = TCP_CLOSE_WAIT;
+               if (th->rst) sk->shutdown = SHUTDOWN_MASK;
+               break;
+
+       case TCP_CLOSE_WAIT:
+       case TCP_FIN_WAIT2:
+               break; /* we got a retransmit of the fin. */
+
+       case TCP_FIN_WAIT1:
+               /* Contains the one that needs to be acked */
+               sk->fin_seq = th->seq+1;
+               sk->state = TCP_FIN_WAIT2;
+               break;
+
+       default:
+       case TCP_TIME_WAIT:
+               sk->state = TCP_LAST_ACK;
 
-       switch(sk->state) 
-       {
-               case TCP_SYN_RECV:
-               case TCP_SYN_SENT:
-               case TCP_ESTABLISHED:
-                       /* Contains the one that needs to be acked */
-                       sk->fin_seq = th->seq+1;
-                       sk->state = TCP_CLOSE_WAIT;
-                       if (th->rst) 
-                               sk->shutdown = SHUTDOWN_MASK;
-                       break;
-
-               case TCP_CLOSE_WAIT:
-                       break;
-                       
-               case TCP_FIN_WAIT2:
-                       tcp_time_wait(sk);                      
-                       break; /* we got a retransmit of the fin. */
-
-               case TCP_FIN_WAIT1:
-                       /* Contains the one that needs to be acked */
-                       if(before(sk->send_seq,sk->rcv_ack_seq+1) && after(sk->send_seq,sk->rcv_ack_seq-1))
-                               tcp_time_wait(sk);
-                       else
-                       {
-                               sk->fin_seq = th->seq+1;
-                               sk->state = TCP_FIN_WAIT2;/* should be closing */
-                       }
-                       break;
-
-               default:
-               case TCP_TIME_WAIT:
-                       sk->state = TCP_LAST_ACK;
-
-                       /* Start the timers. */
-                       reset_timer(sk, TIME_CLOSE, TCP_TIMEWAIT_LEN);
-                       if (!sk->dead) 
-                       {
-                               sk->state_change(sk);
-                       }
-                       return(0);
-       }
-       sk->ack_backlog++;
-       if (!sk->dead) 
-       {
-               sk->state_change(sk);
-       }
+               /* Start the timers. */
+               reset_timer(sk, TIME_CLOSE, TCP_TIMEWAIT_LEN);
+               return(0);
+  }
+  sk->ack_backlog++;
 
-       return(0);
+  return(0);
 }
 
 
-/*
- *     This will accept the next outstanding connection. 
- */
-static struct sock *tcp_accept(struct sock *sk, int flags)
+/* This will accept the next outstanding connection. */
+static struct sock *
+tcp_accept(struct sock *sk, int flags)
 {
-       struct sock *newsk;
-       struct sk_buff *skb;
+  struct sock *newsk;
+  struct sk_buff *skb;
   
-       DPRINTF((DBG_TCP, "tcp_accept(sk=%X, flags=%X, addr=%s)\n",
+  DPRINTF((DBG_TCP, "tcp_accept(sk=%X, flags=%X, addr=%s)\n",
                                sk, flags, in_ntoa(sk->saddr)));
 
-       /*
-        * We need to make sure that this socket is listening,
-        * and that it has something pending.
-        */
-       
-       if (sk->state != TCP_LISTEN) 
-       {
-               sk->err = EINVAL;
-               return(NULL); 
-       }
-
-       /* avoid the race. */
-       
-       cli();
-       sk->inuse = 1;
-       while((skb = get_firstr(sk)) == NULL) 
-       {
-               /*
-                *      Nobody connecting
-                */
-               if (flags & O_NONBLOCK) 
-               {
-                       sti();
-                       release_sock(sk);
-                       sk->err = EAGAIN;
-                       return(NULL);
-               }
-
+  /*
+   * We need to make sure that this socket is listening,
+   * and that it has something pending.
+   */
+  if (sk->state != TCP_LISTEN) {
+       sk->err = EINVAL;
+       return(NULL); 
+  }
+
+  /* avoid the race. */
+  cli();
+  sk->inuse = 1;
+  while((skb = get_firstr(sk)) == NULL) {
+       if (flags & O_NONBLOCK) {
+               sti();
                release_sock(sk);
-               interruptible_sleep_on(sk->sleep);
-               if (current->signal & ~current->blocked) 
-               {
-                       sti();
-                       sk->err = ERESTARTSYS;
-                       return(NULL);
-               }
-               sk->inuse = 1;
-       }
-       sti();
+               sk->err = EAGAIN;
+               return(NULL);
+       }
+
+       release_sock(sk);
+       interruptible_sleep_on(sk->sleep);
+       if (current->signal & ~current->blocked) {
+               sti();
+               sk->err = ERESTARTSYS;
+               return(NULL);
+       }
+       sk->inuse = 1;
+  }
+  sti();
 
-       /* Now all we need to do is return skb->sk. */
-       newsk = skb->sk;
+  /* Now all we need to do is return skb->sk. */
+  newsk = skb->sk;
 
-       kfree_skb(skb, FREE_READ);
-       sk->ack_backlog--;
-       release_sock(sk);
-       return(newsk);
+  kfree_skb(skb, FREE_READ);
+  sk->ack_backlog--;
+  release_sock(sk);
+  return(newsk);
 }
 
 
-/* 
- *     This will initiate an outgoing connection. 
- */
-static int tcp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len)
+/* This will initiate an outgoing connection. */
+static int
+tcp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len)
 {
-       struct sk_buff *buff;
-       struct sockaddr_in sin;
-       struct device *dev=NULL;
-       unsigned char *ptr;
-       int tmp;
-       struct tcphdr *t1;
-       int err;
-
-       if (sk->state != TCP_CLOSE) 
-               return(-EISCONN);
-               
-       if (addr_len < 8) 
-               return(-EINVAL);
-
-       err=verify_area(VERIFY_READ, usin, addr_len);
-       if(err)
-               return err;
+  struct sk_buff *buff;
+  struct sockaddr_in sin;
+  struct device *dev=NULL;
+  unsigned char *ptr;
+  int tmp;
+  struct tcphdr *t1;
+  int err;
+
+  if (sk->state != TCP_CLOSE) return(-EISCONN);
+  if (addr_len < 8) return(-EINVAL);
+
+  err=verify_area(VERIFY_READ, usin, addr_len);
+  if(err)
+       return err;
        
-       memcpy_fromfs(&sin,usin, min(sizeof(sin), addr_len));
+  memcpy_fromfs(&sin,usin, min(sizeof(sin), addr_len));
 
-       if (sin.sin_family && sin.sin_family != AF_INET) 
-               return(-EAFNOSUPPORT);
+  if (sin.sin_family && sin.sin_family != AF_INET) return(-EAFNOSUPPORT);
 
-       DPRINTF((DBG_TCP, "TCP connect daddr=%s\n", in_ntoa(sin.sin_addr.s_addr)));
-  
-       /*
-        *      Don't want a TCP connection going to a broadcast address 
-        */
-
-       if (chk_addr(sin.sin_addr.s_addr) == IS_BROADCAST) 
-       { 
-               DPRINTF((DBG_TCP, "TCP connection to broadcast address not allowed\n"));
-               return(-ENETUNREACH);
-       }
+  DPRINTF((DBG_TCP, "TCP connect daddr=%s\n", in_ntoa(sin.sin_addr.s_addr)));
   
-       sk->inuse = 1;
-       sk->daddr = sin.sin_addr.s_addr;
-       sk->send_seq = jiffies * SEQ_TICK - seq_offset;
-       sk->rcv_ack_seq = sk->send_seq -1;
-       sk->err = 0;
-       sk->dummy_th.dest = sin.sin_port;
-       release_sock(sk);
-
-       buff = (struct sk_buff *) sk->prot->wmalloc(sk,MAX_SYN_SIZE,0, GFP_KERNEL);
-       if (buff == NULL) 
-       {
-               return(-ENOMEM);
-       }
+  /* Don't want a TCP connection going to a broadcast address */
+  if (chk_addr(sin.sin_addr.s_addr) == IS_BROADCAST) { 
+       DPRINTF((DBG_TCP, "TCP connection to broadcast address not allowed\n"));
+       return(-ENETUNREACH);
+  }
   
-       sk->inuse = 1;
-       buff->mem_addr = buff;
-       buff->mem_len = MAX_SYN_SIZE;
-       buff->len = 24;
-       buff->sk = sk;
-       buff->free = 1;
-       t1 = (struct tcphdr *)(buff + 1);
-
-       /* Put in the IP header and routing stuff. */
-       /* We need to build the routing stuff fromt the things saved in skb. */
-       tmp = sk->prot->build_header(buff, sk->saddr, sk->daddr, &dev,IPPROTO_TCP, NULL, MAX_SYN_SIZE,
-                       sk->ip_ttl,sk->ip_tos);
+  sk->inuse = 1;
+  sk->daddr = sin.sin_addr.s_addr;
+  sk->send_seq = jiffies * SEQ_TICK - seq_offset;
+  sk->rcv_ack_seq = sk->send_seq -1;
+  sk->err = 0;
+  sk->dummy_th.dest = sin.sin_port;
+  release_sock(sk);
+
+  buff = (struct sk_buff *) sk->prot->wmalloc(sk,MAX_SYN_SIZE,0, GFP_KERNEL);
+  if (buff == NULL) {
+       return(-ENOMEM);
+  }
+  sk->inuse = 1;
+  buff->mem_addr = buff;
+  buff->mem_len = MAX_SYN_SIZE;
+  buff->len = 24;
+  buff->sk = sk;
+  buff->free = 1;
+  t1 = (struct tcphdr *)(buff + 1);
+
+  /* Put in the IP header and routing stuff. */
+  /* We need to build the routing stuff fromt the things saved in skb. */
+  tmp = sk->prot->build_header(buff, sk->saddr, sk->daddr, &dev,
+                                       IPPROTO_TCP, NULL, MAX_SYN_SIZE);
+  if (tmp < 0) {
+       sk->prot->wfree(sk, buff->mem_addr, buff->mem_len);
+       release_sock(sk);
+       return(-ENETUNREACH);
+  }
+  buff->len += tmp;
+  t1 = (struct tcphdr *)((char *)t1 +tmp);
+
+  memcpy(t1,(void *)&(sk->dummy_th), sizeof(*t1));
+  t1->seq = ntohl(sk->send_seq++);
+  buff->h.seq = sk->send_seq;
+  t1->ack = 0;
+  t1->window = 2;
+  t1->res1=0;
+  t1->res2=0;
+  t1->rst = 0;
+  t1->urg = 0;
+  t1->psh = 0;
+  t1->syn = 1;
+  t1->urg_ptr = 0;
+  t1->doff = 6;
+
+  /* Put in the TCP options to say MTU. */
+  ptr = (unsigned char *)(t1+1);
+  ptr[0] = 2;
+  ptr[1] = 4;
+  ptr[2] = (dev->mtu- HEADER_SIZE) >> 8;
+  ptr[3] = (dev->mtu- HEADER_SIZE) & 0xff;
+  sk->mtu = dev->mtu - HEADER_SIZE;
+  tcp_send_check(t1, sk->saddr, sk->daddr,
+                 sizeof(struct tcphdr) + 4, sk);
+
+  /* This must go first otherwise a really quick response will get reset. */
+  sk->state = TCP_SYN_SENT;
+  sk->rtt = TCP_CONNECT_TIME;
+  reset_timer(sk, TIME_WRITE, TCP_CONNECT_TIME);       /* Timer for repeating the SYN until an answer */
+  sk->retransmits = TCP_RETR2 - TCP_SYN_RETRIES;
+
+  sk->prot->queue_xmit(sk, dev, buff, 0);  
   
-       if (tmp < 0) 
-       {
-               sk->prot->wfree(sk, buff->mem_addr, buff->mem_len);
-               release_sock(sk);
-               return(-ENETUNREACH);
-       }
-       buff->len += tmp;
-       t1 = (struct tcphdr *)((char *)t1 +tmp);
-
-       memcpy(t1,(void *)&(sk->dummy_th), sizeof(*t1));
-       t1->seq = ntohl(sk->send_seq++);
-       buff->h.seq = sk->send_seq;
-       t1->ack = 0;
-       t1->window = 2;
-       t1->res1=0;
-       t1->res2=0;
-       t1->rst = 0;
-       t1->urg = 0;
-       t1->psh = 0;
-       t1->syn = 1;
-       t1->urg_ptr = 0;
-       t1->doff = 6;
-
-       /* Put in the TCP options to say MTU. */
-       ptr = (unsigned char *)(t1+1);
-       ptr[0] = 2;
-       ptr[1] = 4;
-       ptr[2] = (dev->mtu- HEADER_SIZE) >> 8;
-       ptr[3] = (dev->mtu- HEADER_SIZE) & 0xff;
-       sk->mtu = dev->mtu - HEADER_SIZE;
-       tcp_send_check(t1, sk->saddr, sk->daddr,
-               sizeof(struct tcphdr) + 4, sk);
-
-       /* 
-        *      This must go first otherwise a really quick response will get reset. 
-        */
-
-       sk->state = TCP_SYN_SENT;
-       sk->rtt = TCP_CONNECT_TIME;
-       reset_timer(sk, TIME_WRITE, TCP_CONNECT_TIME);  /* Timer for repeating the SYN until an answer */
-       sk->retransmits = TCP_RETR2 - TCP_SYN_RETRIES;
-
-       sk->prot->queue_xmit(sk, dev, buff, 0);  
-       
-       release_sock(sk);
-       return(0);
+  release_sock(sk);
+  return(0);
 }
 
 
-/* 
- *     This functions checks to see if the tcp header is actually acceptible. 
- */
-
-static int tcp_sequence(struct sock *sk, struct tcphdr *th, short len,
-            struct options *opt, unsigned long saddr, struct device *dev)
+/* This functions checks to see if the tcp header is actually acceptible. */
+static int
+tcp_sequence(struct sock *sk, struct tcphdr *th, short len,
+            struct options *opt, unsigned long saddr)
 {
   /*
    * This isn't quite right.  sk->acked_seq could be more recent
@@ -3353,711 +2870,552 @@ static int tcp_sequence(struct sock *sk, struct tcphdr *th, short len,
    * slightly more packets than we should, but it should not cause
    * problems unless someone is trying to forge packets.
    */
-       DPRINTF((DBG_TCP, "tcp_sequence(sk=%X, th=%X, len = %d, opt=%d, saddr=%X)\n",
-               sk, th, len, opt, saddr));
-
-       /* Is it within the windows */
-       if (between(th->seq, sk->acked_seq, sk->acked_seq + sk->window)||
-               between(th->seq + len-(th->doff*4), sk->acked_seq + 1, sk->acked_seq + sk->window) ||
-               (before(th->seq, sk->acked_seq) &&
-                       after(th->seq + len -(th->doff*4), sk->acked_seq + sk->window))) 
-               {
-                       return(1);
-       }
-       DPRINTF((DBG_TCP, "tcp_sequence: rejecting packet.\n"));
-       
-       /*
-        *      Send a reset if we get something not ours and we are
-        *      unsynchronized. Note: We don't do anything to our end. We
-        *      are just killing the bogus remote connection then we will
-        *      connect again and it will work (with luck).
-        */
-        
-       if(sk->state==TCP_SYN_SENT||sk->state==TCP_SYN_RECV)
-       {
-               tcp_reset(sk->saddr,sk->daddr,th,sk->prot,NULL,dev);
-               return(1);
-       }
-
-       /*
-        * If it's too far ahead, send an ack to let the
-        * other end know what we expect.
-        */
-  
-       if (after(th->seq, sk->acked_seq + sk->window)) 
-       {
-               if(!th->rst)
-                       tcp_send_ack(sk->send_seq, sk->acked_seq, sk, th, saddr);
-               return(0);
-       }
+  DPRINTF((DBG_TCP, "tcp_sequence(sk=%X, th=%X, len = %d, opt=%d, saddr=%X)\n",
+         sk, th, len, opt, saddr));
+
+  if (between(th->seq, sk->acked_seq, sk->acked_seq + sk->window)||
+      between(th->seq + len-(th->doff*4), sk->acked_seq + 1,
+             sk->acked_seq + sk->window) ||
+     (before(th->seq, sk->acked_seq) &&
+       after(th->seq + len -(th->doff*4), sk->acked_seq + sk->window))) {
+       return(1);
+   }
+  DPRINTF((DBG_TCP, "tcp_sequence: rejecting packet.\n"));
 
-       /* 
-        *      In case it's just a late ack, let it through. 
-        */
-       
-       if (th->ack && len == (th->doff * 4) && after(th->seq, sk->acked_seq - 32767) && !th->fin && !th->syn) 
-               return(1);
-
-       if (!th->rst) 
-       {
-               /* Try to resync things. */
+  /*
+   * If it's too far ahead, send an ack to let the
+   * other end know what we expect.
+   */
+  if (after(th->seq, sk->acked_seq + sk->window)) {
+       if(!th->rst)
                tcp_send_ack(sk->send_seq, sk->acked_seq, sk, th, saddr);
-       }
-       return(0);
+       return(0);
+  }
+
+  /* In case it's just a late ack, let it through. */
+  if (th->ack && len == (th->doff * 4) &&
+      after(th->seq, sk->acked_seq - 32767) &&
+      !th->fin && !th->syn) return(1);
+
+  if (!th->rst) {
+       /* Try to resync things. */
+       tcp_send_ack(sk->send_seq, sk->acked_seq, sk, th, saddr);
+  }
+  return(0);
 }
 
 
 
-/*
- *     A TCP frame has been received by the IP layer and will now
- *     be thrown to us for processing. I've dropped page numbers
- *     into this. These are from the ASCII version of the RFC
- *     and should help anyone following it.
- */
 
-int tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
+
+int
+tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
        unsigned long daddr, unsigned short len,
        unsigned long saddr, int redo, struct inet_protocol * protocol)
 {
-       struct tcphdr *th;
-       struct sock *sk;
+  struct tcphdr *th;
+  struct sock *sk;
+
+  if (!skb) {
+       DPRINTF((DBG_TCP, "tcp.c: tcp_rcv skb = NULL\n"));
+       return(0);
+  }
+#if 0  /* FIXME: it's ok for protocol to be NULL */
+  if (!protocol) {
+       DPRINTF((DBG_TCP, "tcp.c: tcp_rcv protocol = NULL\n"));
+       return(0);
+  }
+
+  if (!opt) {  /* FIXME: it's ok for opt to be NULL */
+       DPRINTF((DBG_TCP, "tcp.c: tcp_rcv opt = NULL\n"));
+  }
+#endif
+  if (!dev) {
+       DPRINTF((DBG_TCP, "tcp.c: tcp_rcv dev = NULL\n"));
+       return(0);
+  }
+  th = skb->h.th;
+
+  /* Find the socket. */
+  sk = get_sock(&tcp_prot, th->dest, saddr, th->source, daddr);
+  DPRINTF((DBG_TCP, "<<\n"));
+  DPRINTF((DBG_TCP, "len = %d, redo = %d, skb=%X\n", len, redo, skb));
+  
+  /* If this socket has got a reset its to all intents and purposes 
+     really dead */
+  if (sk!=NULL && sk->zapped)
+       sk=NULL;
 
-       if (!skb) 
-       {
-               DPRINTF((DBG_TCP, "tcp.c: tcp_rcv skb = NULL\n"));
-               return(0);
-       }
+  if (sk) {
+        DPRINTF((DBG_TCP, "sk = %X:\n", sk));
+  }
 
-       if (!dev) 
-       {
-               DPRINTF((DBG_TCP, "tcp.c: tcp_rcv dev = NULL\n"));
+  if (!redo) {
+       if (tcp_check(th, len, saddr, daddr )) {
+               skb->sk = NULL;
+               DPRINTF((DBG_TCP, "packet dropped with bad checksum.\n"));
+if (inet_debug == DBG_SLIP) printk("\rtcp_rcv: bad checksum\n");
+               kfree_skb(skb,FREE_READ);
+               /*
+                * We don't release the socket because it was
+                * never marked in use.
+                */
                return(0);
-       }
-  
-       th = skb->h.th;
+       }
 
-       /* Find the socket. */
-       sk = get_sock(&tcp_prot, th->dest, saddr, th->source, daddr);
-       DPRINTF((DBG_TCP, "<<\n"));
-       DPRINTF((DBG_TCP, "len = %d, redo = %d, skb=%X\n", len, redo, skb));
-  
-       /* If this socket has got a reset its to all intents and purposes 
-          really dead */
-  
-       if (sk!=NULL && sk->zapped)
-               sk=NULL;
+       /* See if we know about the socket. */
+       if (sk == NULL) {
+               if (!th->rst) 
+               {       
+                       th->seq = ntohl(th->seq);
+                       /* So reset is always called with th->seq in host order */
+                       tcp_reset(daddr, saddr, th, &tcp_prot, opt,dev);
+               }
+               skb->sk = NULL;
+               kfree_skb(skb, FREE_READ);
+               return(0);
+       }
 
-       if (sk) 
-       {
-               DPRINTF((DBG_TCP, "sk = %X:\n", sk));
-       }
+       skb->len = len;
+       skb->sk = sk;
+       skb->acked = 0;
+       skb->used = 0;
+       skb->free = 0;
+       skb->urg_used = 0;
+       skb->saddr = daddr;
+       skb->daddr = saddr;
+
+       th->seq = ntohl(th->seq);
+
+       /* We may need to add it to the backlog here. */
+       cli();
+       if (sk->inuse) {
+               if (sk->back_log == NULL) {
+                       sk->back_log = skb;
+                       skb->next = skb;
+                       skb->prev = skb;
+               } else {
+                       skb->next = sk->back_log;
+                       skb->prev = sk->back_log->prev;
+                       skb->prev->next = skb;
+                       skb->next->prev = skb;
+               }
+               sti();
+               return(0);
+       }
+       sk->inuse = 1;
+       sti();
+  } else {
+       if (!sk) {
+               DPRINTF((DBG_TCP, "tcp.c: tcp_rcv bug sk=NULL redo = 1\n"));
+               return(0);
+       }
+  }
+
+  if (!sk->prot) {
+       DPRINTF((DBG_TCP, "tcp.c: tcp_rcv sk->prot = NULL \n"));
+       return(0);
+  }
+
+  /* Charge the memory to the socket. */
+  if (sk->rmem_alloc + skb->mem_len >= sk->rcvbuf) {
+       skb->sk = NULL;
+       DPRINTF((DBG_TCP, "dropping packet due to lack of buffer space.\n"));
+       kfree_skb(skb, FREE_READ);
+       release_sock(sk);
+       return(0);
+  }
+  sk->rmem_alloc += skb->mem_len;
+
+  DPRINTF((DBG_TCP, "About to do switch.\n"));
+
+  /* Now deal with it. */
+  switch(sk->state) {
+       /*
+        * This should close the system down if it's waiting
+        * for an ack that is never going to be sent.
+        */
+       case TCP_LAST_ACK:
+               if (th->rst) {
+                       sk->zapped=1;
+                       sk->err = ECONNRESET;
+                       sk->state = TCP_CLOSE;
+                       sk->shutdown = SHUTDOWN_MASK;
+                       if (!sk->dead) {
+                               wake_up(sk->sleep);
+                       }
+                       kfree_skb(skb, FREE_READ);
+                       release_sock(sk);
+                       return(0);
+               }
 
-       if (!redo) 
-       {
-               if (tcp_check(th, len, saddr, daddr )) 
-               {
-                       skb->sk = NULL;
-                       DPRINTF((DBG_TCP, "packet dropped with bad checksum.\n"));
-                       if (inet_debug == DBG_SLIP) 
-                               printk("\rtcp_rcv: bad checksum\n");
-                       kfree_skb(skb,FREE_READ);
-                       /*
-                        * We don't release the socket because it was
-                        * never marked in use.
-                        */
+       case TCP_ESTABLISHED:
+       case TCP_CLOSE_WAIT:
+       case TCP_FIN_WAIT1:
+       case TCP_FIN_WAIT2:
+       case TCP_TIME_WAIT:
+               if (!tcp_sequence(sk, th, len, opt, saddr)) {
+if (inet_debug == DBG_SLIP) printk("\rtcp_rcv: not in seq\n");
+                       if(!th->rst)
+                               tcp_send_ack(sk->send_seq, sk->acked_seq, 
+                                    sk, th, saddr);
+                       kfree_skb(skb, FREE_READ);
+                       release_sock(sk);
                        return(0);
                }
 
-               /* See if we know about the socket. */
-               if (sk == NULL) 
-               {
+               if (th->rst) {
+                       sk->zapped=1;
+                       /* This means the thing should really be closed. */
+                       sk->err = ECONNRESET;
+
+                       if (sk->state == TCP_CLOSE_WAIT) {
+                               sk->err = EPIPE;
+                       }
+
                        /*
-                        *      Segment to 'closed' socket [Page 65]
+                        * A reset with a fin just means that
+                        * the data was not all read.
                         */
-                       if (!th->rst) 
-                       {       
-                               th->seq = ntohl(th->seq);
-                               /* So reset is always called with th->seq in host order */
-                               tcp_reset(daddr, saddr, th, &tcp_prot, opt,dev);
+/* The comment above appears completely bogus --clh */
+/*                     if (!th->fin) { */
+                               sk->state = TCP_CLOSE;
+                               sk->shutdown = SHUTDOWN_MASK;
+                               if (!sk->dead) {
+                                       wake_up(sk->sleep);
+                               }
+                               kfree_skb(skb, FREE_READ);
+                               release_sock(sk);
+                               return(0);
+/*                     } */
+               }
+#if 0
+               if (opt && (opt->security != 0 ||
+                           opt->compartment != 0 || th->syn)) {
+                       sk->err = ECONNRESET;
+                       sk->state = TCP_CLOSE;
+                       sk->shutdown = SHUTDOWN_MASK;
+                       tcp_reset(daddr, saddr,  th, sk->prot, opt,dev);
+                       if (!sk->dead) {
+                               wake_up(sk->sleep);
                        }
-                       skb->sk = NULL;
                        kfree_skb(skb, FREE_READ);
+                       release_sock(sk);
                        return(0);
                }
-
-               skb->len = len;
-               skb->sk = sk;
-               skb->acked = 0;
-               skb->used = 0;
-               skb->free = 0;
-               skb->urg_used = 0;
-               skb->saddr = daddr;
-               skb->daddr = saddr;
-       
-               th->seq = ntohl(th->seq);
-
-              /* We may need to add it to the backlog here. */
-               cli();
-               if (sk->inuse) 
-               {
-                       if (sk->back_log == NULL) 
-                       {
-                               sk->back_log = skb;
-                               skb->next = skb;
-                               skb->prev = skb;
-                       } 
-                       else 
-                       {
-                               skb->next = sk->back_log;
-                               skb->prev = sk->back_log->prev;
-                               skb->prev->next = skb;
-                               skb->next->prev = skb;
+#endif
+               if (th->ack) {
+                       if (!tcp_ack(sk, th, saddr, len)) {
+                               kfree_skb(skb, FREE_READ);
+                               release_sock(sk);
+                               return(0);
                        }
-                       sti();
+               }
+               if (th->urg) {
+                       if (tcp_urg(sk, th, saddr)) {
+                               kfree_skb(skb, FREE_READ);
+                               release_sock(sk);
+                               return(0);
+                       }
+               }
+
+               if (th->fin && tcp_fin(sk, th, saddr, dev)) {
+                       kfree_skb(skb, FREE_READ);
+                       release_sock(sk);
                        return(0);
                }
-               sk->inuse = 1;
-               sti();
-       } 
-       else 
-       {
-               if (!sk) 
-               {
-                       DPRINTF((DBG_TCP, "tcp.c: tcp_rcv bug sk=NULL redo = 1\n"));
+
+               if (tcp_data(skb, sk, saddr, len)) {
+                       kfree_skb(skb, FREE_READ);
+                       release_sock(sk);
                        return(0);
                }
-       }
 
-  
-       if (!sk->prot) 
-       {
-               DPRINTF((DBG_TCP, "tcp.c: tcp_rcv sk->prot = NULL \n"));
+               release_sock(sk);
                return(0);
-       }
 
-       /* Charge the memory to the socket. */
-       if (sk->rmem_alloc + skb->mem_len >= sk->rcvbuf) 
-       {
-               skb->sk = NULL;
-               DPRINTF((DBG_TCP, "dropping packet due to lack of buffer space.\n"));
+       case TCP_CLOSE:
+               if (sk->dead || sk->daddr) {
+                       DPRINTF((DBG_TCP, "packet received for closed,dead socket\n"));
+                       kfree_skb(skb, FREE_READ);
+                       release_sock(sk);
+                       return(0);
+               }
+
+               if (!th->rst) {
+                       if (!th->ack)
+                               th->ack_seq = 0;
+                       tcp_reset(daddr, saddr, th, sk->prot, opt,dev);
+               }
                kfree_skb(skb, FREE_READ);
                release_sock(sk);
                return(0);
-       }
-  
-       sk->rmem_alloc += skb->mem_len;
 
-       DPRINTF((DBG_TCP, "About to do switch.\n"));
+       case TCP_LISTEN:
+               if (th->rst) {
+                       kfree_skb(skb, FREE_READ);
+                       release_sock(sk);
+                       return(0);
+               }
+               if (th->ack) {
+                       tcp_reset(daddr, saddr, th, sk->prot, opt,dev);
+                       kfree_skb(skb, FREE_READ);
+                       release_sock(sk);
+                       return(0);
+               }
 
-       /* Now deal with it. */
-  
-       switch(sk->state) 
-       {
-       /*
-        * This should close the system down if it's waiting
-        * for an ack that is never going to be sent.
-        *
-        *      [Page 68]
-        */
-               case TCP_LAST_ACK:
-                       if (th->rst) 
-                       {
-                               sk->zapped=1;
-                               sk->err = ECONNRESET;
-                               sk->state = TCP_CLOSE;
-                               sk->shutdown = SHUTDOWN_MASK;
-                               if (!sk->dead) 
-                               {
-                                       sk->state_change(sk);
-                               }
-                               kfree_skb(skb, FREE_READ);
+               if (th->syn) {
+#if 0
+                       if (opt->security != 0 || opt->compartment != 0) {
+                               tcp_reset(daddr, saddr, th, prot, opt,dev);
                                release_sock(sk);
                                return(0);
                        }
+#endif
 
-               case TCP_ESTABLISHED:
-               case TCP_CLOSE_WAIT:
-               case TCP_FIN_WAIT1:
-               case TCP_FIN_WAIT2:
-               case TCP_TIME_WAIT:
-                       if (!tcp_sequence(sk, th, len, opt, saddr,dev)) 
-                       {
-                               if (inet_debug == DBG_SLIP) 
-                                       printk("\rtcp_rcv: not in seq\n");
-                               if(!th->rst)
-                                       tcp_send_ack(sk->send_seq, sk->acked_seq, 
-                                            sk, th, saddr);
-                               kfree_skb(skb, FREE_READ);
-                               release_sock(sk);
-                               return(0);
-                       }
-       
-                       if (th->rst) 
-                       {
-                               sk->zapped=1;
-                               /* This means the thing should really be closed. [Page 70] */
-                               sk->err = ECONNRESET;
-       
-                               if (sk->state == TCP_CLOSE_WAIT) 
-                               {
-                                       sk->err = EPIPE;
-                               }
-       
-                               sk->state = TCP_CLOSE;
-                               sk->shutdown = SHUTDOWN_MASK;
-                               if (!sk->dead) 
-                               {
-                                       sk->state_change(sk);
-                               }
-                               kfree_skb(skb, FREE_READ);
-                               release_sock(sk);
-                               return(0);
-                       }
-                       /* [Page 71] - security options: We just say no thanks */
-                       if (opt && (opt->security != 0 || opt->compartment != 0)) 
-                       {
-                               sk->err = ECONNRESET;
-                               sk->state = TCP_CLOSE;
-                               sk->shutdown = SHUTDOWN_MASK;
-                               tcp_reset(daddr, saddr,  th, sk->prot, opt,dev);
-                               if (!sk->dead) 
-                               {
-                                       sk->state_change(sk);
-                               }
-                               kfree_skb(skb, FREE_READ);
-                               release_sock(sk);
-                               return(0);
-                       }
-                       if (th->syn)
-                       {
-                               sk->err = ECONNRESET;
-                               sk->state = TCP_CLOSE;
-                               sk->shutdown = SHUTDOWN_MASK;
-                               tcp_reset(daddr, saddr,  th, sk->prot, opt,dev);
-                               if (!sk->dead) 
-                               {
-                                       sk->state_change(sk);
-                               }
-                               kfree_skb(skb, FREE_READ);
-                               release_sock(sk);
-                               return(0);
-                       }
-                                                       
-                       if (th->ack) 
-                       {
-                               if (!tcp_ack(sk, th, saddr, len)) 
-                               {
-                                       kfree_skb(skb, FREE_READ);
-                                       release_sock(sk);
-                                       return(0);
-                               }
-                       }
-                       /* [Page 73] */
-                       if (th->urg &&(sk->state==TCP_ESTABLISHED||sk->state==TCP_FIN_WAIT1||sk->state==TCP_FIN_WAIT2)) 
-                       {
-                               if (tcp_urg(sk, th, saddr)) 
-                               {
-                                       kfree_skb(skb, FREE_READ);
-                                       release_sock(sk);
-                                       return(0);
-                               }
-                       }
-                       
-                       
-                       /* [Page 74] */
-                       if (tcp_data(skb, sk, saddr, len)) 
-                       {
-                               kfree_skb(skb, FREE_READ);
-                               release_sock(sk);
-                               return(0);
-                       }
-                       /* Move this below the data processing [Page 74/75] */
+                       /*
+                        * Now we just put the whole thing including
+                        * the header and saddr, and protocol pointer
+                        * into the buffer.  We can't respond until the
+                        * user tells us to accept the connection.
+                        */
+                       tcp_conn_request(sk, skb, daddr, saddr, opt, dev);
+                       release_sock(sk);
+                       return(0);
+               }
 
-                       if (th->fin && tcp_fin(sk, th, saddr, dev)) 
-                       {
-                               kfree_skb(skb, FREE_READ);
-                               release_sock(sk);
-                               return(0);
+               kfree_skb(skb, FREE_READ);
+               release_sock(sk);
+               return(0);
+
+       default:
+               if (!tcp_sequence(sk, th, len, opt, saddr)) {
+                       kfree_skb(skb, FREE_READ);
+                       release_sock(sk);
+                       return(0);
+               }
+
+       case TCP_SYN_SENT:
+               if (th->rst) {
+                       sk->err = ECONNREFUSED;
+                       sk->state = TCP_CLOSE;
+                       sk->shutdown = SHUTDOWN_MASK;
+                       sk->zapped = 1;
+                       if (!sk->dead) {
+                               wake_up(sk->sleep);
                        }
-       
+                       kfree_skb(skb, FREE_READ);
                        release_sock(sk);
                        return(0);
-       
-               case TCP_CLOSE:
-                       if (sk->dead || sk->daddr) 
-                       {
-                               DPRINTF((DBG_TCP, "packet received for closed,dead socket\n"));
-                               kfree_skb(skb, FREE_READ);
-                               release_sock(sk);
-                               return(0);
+               }
+#if 0
+               if (opt->security != 0 || opt->compartment != 0) {
+                       sk->err = ECONNRESET;
+                       sk->state = TCP_CLOSE;
+                       sk->shutdown = SHUTDOWN_MASK;
+                       tcp_reset(daddr, saddr,  th, sk->prot, opt, dev);
+                       if (!sk->dead) {
+                               wake_up(sk->sleep);
                        }
-       
-                       if (!th->rst) 
-                       {
-                               if (!th->ack)
-                                       th->ack_seq = 0;
-                               tcp_reset(daddr, saddr, th, sk->prot, opt,dev);
+                       kfree_skb(skb, FREE_READ);
+                       release_sock(sk);
+                       return(0);
+               }
+#endif
+               if (!th->ack) {
+                       if (th->syn) {
+                               sk->state = TCP_SYN_RECV;
                        }
+
                        kfree_skb(skb, FREE_READ);
                        release_sock(sk);
                        return(0);
+               }
 
-               case TCP_LISTEN:
-                       if (th->rst) 
-                       {
-                               kfree_skb(skb, FREE_READ);
-                               release_sock(sk);
-                               return(0);
-                       }
-                       if (th->ack) 
-                       {
-                               tcp_reset(daddr, saddr, th, sk->prot, opt,dev);
-                               kfree_skb(skb, FREE_READ);
-                               release_sock(sk);
-                               return(0);
-                       }
-       
-                       if (th->syn) 
-                       {
-                               if (opt && (opt->security != 0 || opt->compartment != 0))
-                               {
-                                       tcp_reset(daddr, saddr, th, sk->prot, opt,dev);
+               switch(sk->state) {
+                       case TCP_SYN_SENT:
+                               if (!tcp_ack(sk, th, saddr, len)) {
+                                       tcp_reset(daddr, saddr, th,
+                                                       sk->prot, opt,dev);
+                                       kfree_skb(skb, FREE_READ);
                                        release_sock(sk);
                                        return(0);
                                }
 
                                /*
-                                * Now we just put the whole thing including
-                                * the header and saddr, and protocol pointer
-                                * into the buffer.  We can't respond until the
-                                * user tells us to accept the connection.
+                                * If the syn bit is also set, switch to
+                                * tcp_syn_recv, and then to established.
                                 */
-                               tcp_conn_request(sk, skb, daddr, saddr, opt, dev);
-                               release_sock(sk);
-                               return(0);
-                       }
-
-                       kfree_skb(skb, FREE_READ);
-                       release_sock(sk);
-                       return(0);
+                               if (!th->syn) {
+                                       kfree_skb(skb, FREE_READ);
+                                       release_sock(sk);
+                                       return(0);
+                               }
 
-               default:
-                       if (!tcp_sequence(sk, th, len, opt, saddr,dev)) 
-                       {
-                               kfree_skb(skb, FREE_READ);
-                               release_sock(sk);
-                               return(0);
-                       }
+                               /* Ack the syn and fall through. */
+                               sk->acked_seq = th->seq+1;
+                               sk->fin_seq = th->seq;
+                               tcp_send_ack(sk->send_seq, th->seq+1,
+                                                       sk, th, sk->daddr);
        
-               case TCP_SYN_SENT:
-                       if (th->rst) 
-                       {
-                               sk->err = ECONNREFUSED;
-                               sk->state = TCP_CLOSE;
-                               sk->shutdown = SHUTDOWN_MASK;
-                               sk->zapped = 1;
-                               if (!sk->dead) 
-                               {
-                                       sk->state_change(sk);
-                               }
-                               kfree_skb(skb, FREE_READ);
-                               release_sock(sk);
-                               return(0);
-                       }
-                       if (opt && (opt->security != 0 || opt->compartment != 0))
-                       {
-                               sk->err = ECONNRESET;
-                               sk->state = TCP_CLOSE;
-                               sk->shutdown = SHUTDOWN_MASK;
-                               tcp_reset(daddr, saddr,  th, sk->prot, opt, dev);
-                               if (!sk->dead) 
-                               {
-                                       sk->state_change(sk);
+                       case TCP_SYN_RECV:
+                               if (!tcp_ack(sk, th, saddr, len)) {
+                                       tcp_reset(daddr, saddr, th,
+                                                       sk->prot, opt, dev);
+                                       kfree_skb(skb, FREE_READ);
+                                       release_sock(sk);
+                                       return(0);
                                }
-                               kfree_skb(skb, FREE_READ);
-                               release_sock(sk);
-                               return(0);
-                       }
-                       if (!th->ack) 
-                       {
-                               if (th->syn) 
-                               {
-                                       sk->state = TCP_SYN_RECV;
+                               sk->state = TCP_ESTABLISHED;
+
+                               /*
+                                * Now we need to finish filling out
+                                * some of the tcp header.
+                                */
+                               /* We need to check for mtu info. */
+                               tcp_options(sk, th);
+                               sk->dummy_th.dest = th->source;
+                               sk->copied_seq = sk->acked_seq-1;
+                               if (!sk->dead) {
+                                       wake_up(sk->sleep);
                                }
-       
-                               kfree_skb(skb, FREE_READ);
-                               release_sock(sk);
-                               return(0);
-                       }
 
-                       switch(sk->state) 
-                       {
-                               case TCP_SYN_SENT:
-                                       /* [Page 73] */
-                                       if (!tcp_ack(sk, th, saddr, len)) 
-                                       {
-                                               tcp_reset(daddr, saddr, th,
-                                                               sk->prot, opt,dev);
-                                               kfree_skb(skb, FREE_READ);
-                                               release_sock(sk);
-                                               return(0);
-                                       }
-       
-                                       /*
-                                        * If the syn bit is also set, switch to
-                                        * tcp_syn_recv, and then to established.
-                                        */
-                                       if (!th->syn) 
-                                       {
-                                               kfree_skb(skb, FREE_READ);
-                                               release_sock(sk);
-                                               return(0);
-                                       }
-       
-                                       /* Ack the syn and fall through. */
-                                       sk->acked_seq = th->seq+1;
-                                       sk->fin_seq = th->seq;
-                                       tcp_send_ack(sk->send_seq, th->seq+1, sk, th, sk->daddr);
-               
-                               case TCP_SYN_RECV:
-                                       if (!tcp_ack(sk, th, saddr, len)) 
-                                       {
-                                               tcp_reset(daddr, saddr, th, sk->prot, opt, dev);
+                               /*
+                                * Now process the rest like we were
+                                * already in the established state.
+                                */
+                               if (th->urg) {
+                                       if (tcp_urg(sk, th, saddr)) { 
                                                kfree_skb(skb, FREE_READ);
                                                release_sock(sk);
                                                return(0);
                                        }
-                                       sk->state = TCP_ESTABLISHED;
-       
-                                       /*
-                                        * Now we need to finish filling out
-                                        * some of the tcp header.
-                                        */
-                                       /* We need to check for mtu info. */
-                                       tcp_options(sk, th);
-                                       sk->dummy_th.dest = th->source;
-                                       sk->copied_seq = sk->acked_seq-1;
-                                       if (!sk->dead) 
-                                       {
-                                               sk->state_change(sk);
-                                       }
-       
-                                       /*
-                                        * Now process the rest like we were
-                                        * already in the established state.
-                                        */
-                                       
-                                       if (th->urg) 
-                                       {
-                                               if (tcp_urg(sk, th, saddr)) 
-                                               { 
-                                                       kfree_skb(skb, FREE_READ);
-                                                       release_sock(sk);
-                                                       return(0);
-                                               }
-                                       }
-                                       if (tcp_data(skb, sk, saddr, len))
-                                               kfree_skb(skb, FREE_READ);
-       
-                                       if (th->fin) 
-                                               tcp_fin(sk, th, saddr, dev);
-                                       release_sock(sk);
-                                       return(0);
                        }
-       
-                       if (th->urg) 
-                       {
-                               if (tcp_urg(sk, th, saddr)) 
-                               {
-                                       kfree_skb(skb, FREE_READ);
-                                       release_sock(sk);
-                                       return(0);
-                               }
-                       }
-       
-                       if (tcp_data(skb, sk, saddr, len)) 
-                       {
+                       if (tcp_data(skb, sk, saddr, len))
+                                               kfree_skb(skb, FREE_READ);
+
+                       if (th->fin) tcp_fin(sk, th, saddr, dev);
+                       release_sock(sk);
+                       return(0);
+               }
+
+               if (th->urg) {
+                       if (tcp_urg(sk, th, saddr)) {
                                kfree_skb(skb, FREE_READ);
                                release_sock(sk);
                                return(0);
                        }
+               }
 
-                       if (!th->fin) 
-                       {
-                               release_sock(sk);
-                               return(0);
-                       }
-                       tcp_fin(sk, th, saddr, dev);
+               if (tcp_data(skb, sk, saddr, len)) {
+                       kfree_skb(skb, FREE_READ);
+                       release_sock(sk);
+                       return(0);
+               }
+
+               if (!th->fin) {
                        release_sock(sk);
                        return(0);
+               }
+               tcp_fin(sk, th, saddr, dev);
+               release_sock(sk);
+               return(0);
        }
 }
 
 
- /*
-  *    This routine sends a packet with an out of date sequence
-  *    number. It assumes the other end will try to ack it.
+/*
+  * This routine sends a packet with an out of date sequence
+  * number. It assumes the other end will try to ack it.
   */
-  
-static void tcp_write_wakeup(struct sock *sk)
+static void
+tcp_write_wakeup(struct sock *sk)
 {
-       struct sk_buff *buff;
-       struct tcphdr *t1;
-       struct device *dev=NULL;
-       int tmp;
+  struct sk_buff *buff;
+  struct tcphdr *t1;
+  struct device *dev=NULL;
+  int tmp;
 
-       if (sk->zapped)
-               return; /* Afer a valid reset we can send no more */
+  if (sk->zapped)
+       return; /* Afer a valid reset we can send no more */
 
-       if (sk -> state != TCP_ESTABLISHED && sk->state != TCP_CLOSE_WAIT)      
-               return;
-
-       buff = (struct sk_buff *) sk->prot->wmalloc(sk,MAX_ACK_SIZE,1, GFP_ATOMIC);
-       
-       if (buff == NULL)       
-               return;
+  if (sk -> state != TCP_ESTABLISHED && sk->state != TCP_CLOSE_WAIT) return;
 
-       buff->mem_addr = buff;
-       buff->mem_len = MAX_ACK_SIZE;
-       buff->len = sizeof(struct tcphdr);
-       buff->free = 1;
-       buff->sk = sk;
-       DPRINTF((DBG_TCP, "in tcp_write_wakeup\n"));
-       t1 = (struct tcphdr *)(buff + 1);
-
-       /* Put in the IP header and routing stuff. */
-       tmp = sk->prot->build_header(buff, sk->saddr, sk->daddr, &dev,
-               IPPROTO_TCP, sk->opt, MAX_ACK_SIZE, sk->ip_ttl,sk->ip_tos);
-       if (tmp < 0) 
-       {
-               sk->prot->wfree(sk, buff->mem_addr, buff->mem_len);
-               return;
-       }
+  buff = (struct sk_buff *) sk->prot->wmalloc(sk,MAX_ACK_SIZE,1, GFP_ATOMIC);
+  if (buff == NULL) return;
 
-       buff->len += tmp;
-       t1 = (struct tcphdr *)((char *)t1 +tmp);
-       
-       memcpy(t1,(void *) &sk->dummy_th, sizeof(*t1));
-
-       /*
-        * Use a previous sequence.
-        * This should cause the other end to send an ack.
-        */
-       t1->seq = ntohl(sk->send_seq-1);
-       t1->ack = 1; 
-       t1->res1= 0;
-       t1->res2= 0;
-       t1->rst = 0;
-       t1->urg = 0;
-       t1->psh = 0;
-       t1->fin = 0;
-       t1->syn = 0;
-       t1->ack_seq = ntohl(sk->acked_seq);
-       t1->window = ntohs(sk->prot->rspace(sk));
-       t1->doff = sizeof(*t1)/4;
-       tcp_send_check(t1, sk->saddr, sk->daddr, sizeof(*t1), sk);
-       
-       /*      Send it and free it.
-        *      This will prevent the timer from automatically being restarted.
-        */
-       sk->prot->queue_xmit(sk, dev, buff, 1);
-}
-
-/*
- *     Socket option code for TCP. 
- */
-  
-int tcp_setsockopt(struct sock *sk, int level, int optname, char *optval, int optlen)
-{
-       int val,err;
+  buff->mem_addr = buff;
+  buff->mem_len = MAX_ACK_SIZE;
+  buff->len = sizeof(struct tcphdr);
+  buff->free = 1;
+  buff->sk = sk;
+  DPRINTF((DBG_TCP, "in tcp_write_wakeup\n"));
+  t1 = (struct tcphdr *)(buff + 1);
 
-       if(level!=SOL_TCP)
-               return ip_setsockopt(sk,level,optname,optval,optlen);
+  /* Put in the IP header and routing stuff. */
+  tmp = sk->prot->build_header(buff, sk->saddr, sk->daddr, &dev,
+                               IPPROTO_TCP, sk->opt, MAX_ACK_SIZE);
+  if (tmp < 0) {
+       sk->prot->wfree(sk, buff->mem_addr, buff->mem_len);
+       return;
+  }
 
-       if (optval == NULL) 
-               return(-EINVAL);
+  buff->len += tmp;
+  t1 = (struct tcphdr *)((char *)t1 +tmp);
 
-       err=verify_area(VERIFY_READ, optval, sizeof(int));
-       if(err)
-               return err;
-       
-       val = get_fs_long((unsigned long *)optval);
+  memcpy(t1,(void *) &sk->dummy_th, sizeof(*t1));
 
-       switch(optname)
-       {
-               case TCP_MSS:
-                       if(val<200||val>2048)
-                               return -EINVAL;
-                       sk->mss=val;
-                       return 0;
-               case TCP_NODELAY:
-                       /* Ready for Johannes delayed ACK code */
-                       return 0;
-               default:
-                       return(-ENOPROTOOPT);
-       }
+  /*
+   * Use a previous sequence.
+   * This should cause the other end to send an ack.
+   */
+  t1->seq = ntohl(sk->send_seq-1);
+  t1->ack = 1; 
+  t1->res1= 0;
+  t1->res2= 0;
+  t1->rst = 0;
+  t1->urg = 0;
+  t1->psh = 0;
+  t1->fin = 0;
+  t1->syn = 0;
+  t1->ack_seq = ntohl(sk->acked_seq);
+  t1->window = ntohs(sk->prot->rspace(sk));
+  t1->doff = sizeof(*t1)/4;
+  tcp_send_check(t1, sk->saddr, sk->daddr, sizeof(*t1), sk);
+
+  /* Send it and free it.
+   * This will prevent the timer from automatically being restarted.
+  */
+  sk->prot->queue_xmit(sk, dev, buff, 1);
 }
 
-int tcp_getsockopt(struct sock *sk, int level, int optname, char *optval, int *optlen)
-{
-       int val,err;
 
-       if(level!=SOL_TCP)
-               return ip_getsockopt(sk,level,optname,optval,optlen);
-                       
-       switch(optname)
-       {
-               case TCP_MSS:
-                       val=sk->mss;
-                       break;
-               case TCP_NODELAY:
-                       val=1;  /* Until Johannes stuff is in */
-                       break;
-               default:
-                       return(-ENOPROTOOPT);
-       }
-       err=verify_area(VERIFY_WRITE, optlen, sizeof(int));
-       if(err)
-               return err;
-       put_fs_long(sizeof(int),(unsigned long *) optlen);
-
-       err=verify_area(VERIFY_WRITE, optval, sizeof(int));
-       if(err)
-               return err;
-       put_fs_long(val,(unsigned long *)optval);
-
-       return(0);
-}      
-
-struct proto tcp_prot = 
-{
-       sock_wmalloc,
-       sock_rmalloc,
-       sock_wfree,
-       sock_rfree,
-       sock_rspace,
-       sock_wspace,
-       tcp_close,
-       tcp_read,
-       tcp_write,
-       tcp_sendto,
-       tcp_recvfrom,
-       ip_build_header,
-       tcp_connect,
-       tcp_accept,
-       ip_queue_xmit,
-       tcp_retransmit,
-       tcp_write_wakeup,
-       tcp_read_wakeup,
-       tcp_rcv,
-       tcp_select,
-       tcp_ioctl,
-       NULL,
-       tcp_shutdown,
-       tcp_setsockopt,
-       tcp_getsockopt,
-       128,
-       0,
-       {NULL,},
-       "TCP"
+struct proto tcp_prot = {
+  sock_wmalloc,
+  sock_rmalloc,
+  sock_wfree,
+  sock_rfree,
+  sock_rspace,
+  sock_wspace,
+  tcp_close,
+  tcp_read,
+  tcp_write,
+  tcp_sendto,
+  tcp_recvfrom,
+  ip_build_header,
+  tcp_connect,
+  tcp_accept,
+  ip_queue_xmit,
+  tcp_retransmit,
+  tcp_write_wakeup,
+  tcp_read_wakeup,
+  tcp_rcv,
+  tcp_select,
+  tcp_ioctl,
+  NULL,
+  tcp_shutdown,
+  128,
+  0,
+  {NULL,},
+  "TCP"
 };
index 9077dbf0f53b154bb2581ab32290fb71ad2d41b0..cb051e48d359c63ce1db3c9ef5cd222ba43fedc2 100644 (file)
  * normal compare so long as neither of the numbers is within
  * 4K of wrapping.  Otherwise we must check for the wrap.
  */
-static inline int before (unsigned long seq1, unsigned long seq2)
+static inline int
+before (unsigned long seq1, unsigned long seq2)
 {
-       /* this inequality is strict. */
-       if (seq1 == seq2)       
-               return(0);
-
-       if (seq1 < seq2) 
-       {
-               if ((unsigned long)seq2-(unsigned long)seq1 < 65536UL) 
-               {
-                       return(1);
-               } 
-               else 
-               {
-                       return(0);
-               }
-       }
-
-       /*
-        * Now we know seq1 > seq2.  So all we need to do is check
-        * to see if seq1 has wrapped.
-        */
-       if (seq2 < 8192UL && seq1 > (0xffffffffUL - 8192UL)) 
-       {
+  /* this inequality is strict. */
+  if (seq1 == seq2) return(0);
+
+  if (seq1 < seq2) {
+       if ((unsigned long)seq2-(unsigned long)seq1 < 65536UL) {
                return(1);
-       }
-       return(0);
+       } else {
+               return(0);
+       }
+  }
+
+  /*
+   * Now we know seq1 > seq2.  So all we need to do is check
+   * to see if seq1 has wrapped.
+   */
+  if (seq2 < 8192UL && seq1 > (0xffffffffUL - 8192UL)) {
+       return(1);
+  }
+  return(0);
 }
 
 
-static inline int after(unsigned long seq1, unsigned long seq2)
+static inline int
+after(unsigned long seq1, unsigned long seq2)
 {
-       return(before(seq2, seq1));
+  return(before(seq2, seq1));
 }
 
 
 /* is s2<=s1<=s3 ? */
-static inline int between(unsigned long seq1, unsigned long seq2, unsigned long seq3)
+static inline int
+between(unsigned long seq1, unsigned long seq2, unsigned long seq3)
 {
-       return(after(seq1+1, seq2) && before(seq1, seq3+1));
+  return(after(seq1+1, seq2) && before(seq1, seq3+1));
 }
 
 
@@ -124,11 +121,12 @@ static inline int between(unsigned long seq1, unsigned long seq2, unsigned long
  * convinced that this is the solution for the 'getpeername(2)'
  * problem. Thanks to Stephen A. Wood <saw@cebaf.gov>  -FvK
  */
-static inline const int tcp_connected(const int state)
+static inline const int
+tcp_connected(const int state)
 {
-       return(state == TCP_ESTABLISHED || state == TCP_CLOSE_WAIT ||
-                state == TCP_FIN_WAIT1   || state == TCP_FIN_WAIT2 ||
-                state == TCP_SYN_RECV);
+  return(state == TCP_ESTABLISHED || state == TCP_CLOSE_WAIT ||
+        state == TCP_FIN_WAIT1   || state == TCP_FIN_WAIT2 ||
+        state == TCP_SYN_RECV);
 }
 
 
index 7cd66b5d43efde8d2066aa251802da9eb5802da3..f6540a18cf19246f355042a3baaa43ebea06165c 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             TIMER - implementation of software timers.
  *
- * Version:    @(#)timer.c     1.28    22/12/93
+ * Version:    @(#)timer.c     1.0.7   05/25/93
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -24,8 +24,6 @@
  *                                     of inet_bh() with this socket being handled it goes
  *                                     BOOM! Have to stop timer going off if inet_bh is
  *                                     active or the destroy causes crashes.
- *             Alan Cox        :       Clean up for final release
- *             Alan Cox        :       Oops - timeouts destroyed permanent arp entries!
  *
  *             This program is free software; you can redistribute it and/or
  *             modify it under the terms of the GNU General Public License
 #include <asm/system.h>
 #include <linux/interrupt.h>
 #include "inet.h"
-#include "devinet.h"
+#include "dev.h"
 #include "ip.h"
 #include "protocol.h"
 #include "tcp.h"
 #include "skbuff.h"
-#include "sockinet.h"
+#include "sock.h"
 #include "arp.h"
 
-void delete_timer (struct sock *t)
+void
+delete_timer (struct sock *t)
 {
-       unsigned long flags;
+  unsigned long flags;
 
-       save_flags (flags);
-       cli();
+  save_flags (flags);
+  cli();
 
-       t->timeout = 0;
-       del_timer (&t->timer);
+  t->timeout = 0;
+  del_timer (&t->timer);
 
-       restore_flags (flags);
+  restore_flags (flags);
 }
 
-void reset_timer (struct sock *t, int timeout, unsigned long len)
+void
+reset_timer (struct sock *t, int timeout, unsigned long len)
 {
-       delete_timer (t);
+  delete_timer (t);
+
+  if (timeout != -1)
+    t->timeout = timeout;
 
-       if (timeout != -1)
-               t->timeout = timeout;
 #if 1
-       /* FIXME: ??? */
-       if ((int) len < 0)      /* prevent close to infinite timers. THEY _DO_ */
-               len = 3;        /* happen (negative values ?) - don't ask me why ! -FB */
+  /* FIXME: ??? */
+  if ((int) len < 0)   /* prevent close to infinite timers. THEY _DO_ */
+       len = 3;        /* happen (negative values ?) - don't ask me why ! -FB */
 #endif
-       t->timer.expires = len;
-       add_timer (&t->timer);
+  t->timer.expires = len;
+  add_timer (&t->timer);
 }
 
 
 /*
- *     Now we will only be called whenever we need to do
- *     something, but we must be sure to process all of the
- *     sockets that need it.
+ * Now we will only be called whenever we need to do
+ * something, but we must be sure to process all of the
+ * sockets that need it.
  */
-void net_timer (unsigned long data)
+void
+net_timer (unsigned long data)
 {
-       struct sock *sk = (struct sock*)data;
-       int why = sk->timeout;
-       /* timeout is overwritten by 'delete_timer' and 'reset_timer' */
-
-       if (sk->inuse || in_inet_bh()) 
-       {
-               sk->timer.expires = 10;
-               add_timer(&sk->timer);
-               return;
-       }
-       sk->inuse = 1;
-
-       DPRINTF ((DBG_TMR, "net_timer: found sk=%X why = %d\n", sk, why));
-       if (sk->keepopen)
-               reset_timer (sk, TIME_KEEPOPEN, TCP_TIMEOUT_LEN);
-
-       /* Always see if we need to send an ack. */
-       if (sk->ack_backlog) 
-       {
-               sk->prot->read_wakeup (sk);
-               if (! sk->dead)
-                       wake_up (sk->sleep);
-       }
-
-       /* Now we need to figure out why the socket was on the timer. */
-       switch (why) 
-       {
-               case TIME_DONE:
-                       if (! sk->dead || sk->state != TCP_CLOSE) 
-                       {
-                               printk ("non dead socket in time_done\n");
-                               release_sock (sk);
-                               break;
-                       }
-                       destroy_sock (sk);
-                       break;
-               case TIME_DESTROY:
-                       /* We've waited for a while for all the memory associated with
-                        * the socket to be freed.  We need to print an error message.
-                        */
-                       if(sk->wmem_alloc!=0 || sk->rmem_alloc!=0)
-                       {
-                               DPRINTF ((DBG_TMR, "possible memory leak.  sk = %X\n", sk));
-                               sk->wmem_alloc++;       /* So it DOESNT go away */
-                               destroy_sock (sk);
-                               sk->wmem_alloc--;       /* Might now have hit 0 - fall through and do it again if so */
-                               sk->inuse = 0;  /* This will be ok, the destroy won't totally work */
-                       }
-                       if(sk->wmem_alloc==0 && sk->rmem_alloc==0)
-                               destroy_sock(sk);       /* Socket gone, DONT update sk->inuse! */
-                       break;
-               case TIME_CLOSE:
-                       /* We've waited long enough, close the socket. */
-                       sk->state = TCP_CLOSE;
-                       delete_timer (sk);
-                       /* Kill the ARP entry in case the hardware has changed. */
-                       arp_destroy_maybe (sk->daddr);
-                       if (!sk->dead)
-                               wake_up (sk->sleep);
-                       sk->shutdown = SHUTDOWN_MASK;
-                       reset_timer (sk, TIME_DESTROY, TCP_DONE_TIME);
-                       release_sock (sk);
-                       break;
-               case TIME_WRITE:        /* try to retransmit. */
-                       /* It could be we got here because we needed to send an ack.
-                        * So we need to check for that.
-                        */
-                       if (sk->send_head) 
-                       {
-                               if (jiffies < (sk->send_head->when + backoff (sk->backoff)
-                                       * (2 * sk->mdev + sk->rtt))) 
-                               {
-                                       reset_timer (sk, TIME_WRITE, (sk->send_head->when
-                                               + backoff (sk->backoff) * (2 * sk->mdev + sk->rtt)) - jiffies);
-                                       release_sock (sk);
-                                       break;
-                               }
-                               /* printk("timer: seq %d retrans %d out %d cong %d\n", sk->send_head->h.seq,
-                                       sk->retransmits, sk->packets_out, sk->cong_window); */
-                               DPRINTF ((DBG_TMR, "retransmitting.\n"));
-                               sk->prot->retransmit (sk, 0);
-                               if ((sk->state == TCP_ESTABLISHED && sk->retransmits && !(sk->retransmits & 7))
-                                       || (sk->state != TCP_ESTABLISHED && sk->retransmits > TCP_RETR1)) 
-                               {
-                                       DPRINTF ((DBG_TMR, "timer.c TIME_WRITE time-out 1\n"));
-                                       arp_destroy_maybe (sk->daddr);
-                                       ip_route_check (sk->daddr);
-                               }
-                               if (sk->state != TCP_ESTABLISHED && sk->retransmits > TCP_RETR2) 
-                               {
-                                       DPRINTF ((DBG_TMR, "timer.c TIME_WRITE time-out 2\n"));
-                                       sk->err = ETIMEDOUT;
-                                       if (sk->state == TCP_FIN_WAIT1 || sk->state == TCP_FIN_WAIT2
-                                               || sk->state == TCP_LAST_ACK) 
-                                       {
-                                               sk->state = TCP_TIME_WAIT;
-                                               reset_timer (sk, TIME_CLOSE, TCP_TIMEWAIT_LEN);
-                                       } 
-                                       else 
-                                       {
-                                               sk->prot->close (sk, 1);
-                                               break;
-                                       }
-                               }
-                       }
-                       release_sock (sk);
-                       break;
-               case TIME_KEEPOPEN:
-                       /* Send something to keep the connection open. */
-                       if (sk->prot->write_wakeup)
-                               sk->prot->write_wakeup (sk);
-                       sk->retransmits++;
-                       if (sk->shutdown == SHUTDOWN_MASK) 
-                       {
-                               sk->prot->close (sk, 1);
-                               sk->state = TCP_CLOSE;
-                       }
-
-                       if ((sk->state == TCP_ESTABLISHED && sk->retransmits && !(sk->retransmits & 7))
-                               || (sk->state != TCP_ESTABLISHED && sk->retransmits > TCP_RETR1)) 
-                       {
-                               DPRINTF ((DBG_TMR, "timer.c TIME_KEEPOPEN time-out 1\n"));
-                               arp_destroy_maybe (sk->daddr);
-                               ip_route_check (sk->daddr);
-                               release_sock (sk);
-                               break;
-                       }
-                       if (sk->state != TCP_ESTABLISHED && sk->retransmits > TCP_RETR2) 
-                       {
-                               DPRINTF ((DBG_TMR, "timer.c TIME_KEEPOPEN time-out 2\n"));
-                               arp_destroy_maybe (sk->daddr);
-                               sk->err = ETIMEDOUT;
-                               if (sk->state == TCP_FIN_WAIT1 || sk->state == TCP_FIN_WAIT2) 
-                               {
-                                       sk->state = TCP_TIME_WAIT;
-                                       if (!sk->dead)
-                                               wake_up (sk->sleep);
-                                       release_sock (sk);
-                               } 
-                               else 
-                               {
-                                       sk->prot->close (sk, 1);
-                               }
-                               break;
-                       }
-                       release_sock (sk);
-                       break;
-               default:
-                       printk ("net timer expired - reason unknown, sk=%08X\n", (int)sk);
-                       release_sock (sk);
-                       break;
-       }
+  struct sock *sk = (struct sock*)data;
+  int why = sk->timeout;
+  /* timeout is overwritten by 'delete_timer' and 'reset_timer' */
+
+  if (sk->inuse || in_inet_bh()) {
+    sk->timer.expires = 10;
+    add_timer(&sk->timer);
+    return;
+  }
+  sk->inuse = 1;
+
+  DPRINTF ((DBG_TMR, "net_timer: found sk=%X why = %d\n", sk, why));
+  if (sk->keepopen)
+    reset_timer (sk, TIME_KEEPOPEN, TCP_TIMEOUT_LEN);
+
+  /* Always see if we need to send an ack. */
+  if (sk->ack_backlog) {
+    sk->prot->read_wakeup (sk);
+    if (! sk->dead)
+      wake_up (sk->sleep);
+  }
+
+  /* Now we need to figure out why the socket was on the timer. */
+  switch (why) {
+    case TIME_DONE:
+       if (! sk->dead || sk->state != TCP_CLOSE) {
+         printk ("non dead socket in time_done\n");
+         release_sock (sk);
+         break;
+       }
+       destroy_sock (sk);
+       break;
+    case TIME_DESTROY:
+       /* We've waited for a while for all the memory associated with
+        * the socket to be freed.  We need to print an error message.
+        */
+       if(sk->wmem_alloc!=0 || sk->rmem_alloc!=0)
+       {
+               DPRINTF ((DBG_TMR, "possible memory leak.  sk = %X\n", sk));
+               sk->wmem_alloc++;       /* So it DOESNT go away */
+               destroy_sock (sk);
+               sk->wmem_alloc--;       /* Might now have hit 0 - fall through and do it again if so */
+               sk->inuse = 0;  /* This will be ok, the destroy won't totally work */
+       }
+       if(sk->wmem_alloc==0 && sk->rmem_alloc==0)
+               destroy_sock(sk);       /* Socket gone, DONT update sk->inuse! */
+       break;
+    case TIME_CLOSE:
+       /* We've waited long enough, close the socket. */
+       sk->state = TCP_CLOSE;
+       delete_timer (sk);
+       /* Kill the ARP entry in case the hardware has changed. */
+       arp_destroy (sk->daddr);
+       if (!sk->dead)
+         wake_up (sk->sleep);
+       sk->shutdown = SHUTDOWN_MASK;
+       reset_timer (sk, TIME_DESTROY, TCP_DONE_TIME);
+       release_sock (sk);
+       break;
+    case TIME_WRITE:   /* try to retransmit. */
+       /* It could be we got here because we needed to send an ack.
+        * So we need to check for that.
+        */
+       if (sk->send_head) {
+         if (jiffies < (sk->send_head->when + backoff (sk->backoff)
+           * (2 * sk->mdev + sk->rtt))) {
+           reset_timer (sk, TIME_WRITE, (sk->send_head->when
+               + backoff (sk->backoff) * (2 * sk->mdev + sk->rtt)) - jiffies);
+           release_sock (sk);
+           break;
+         }
+         /* printk("timer: seq %d retrans %d out %d cong %d\n", sk->send_head->h.seq,
+            sk->retransmits, sk->packets_out, sk->cong_window); */
+         DPRINTF ((DBG_TMR, "retransmitting.\n"));
+         sk->prot->retransmit (sk, 0);
+         if ((sk->state == TCP_ESTABLISHED && sk->retransmits && !(sk->retransmits & 7))
+           || (sk->state != TCP_ESTABLISHED && sk->retransmits > TCP_RETR1)) {
+           DPRINTF ((DBG_TMR, "timer.c TIME_WRITE time-out 1\n"));
+           arp_destroy (sk->daddr);
+           ip_route_check (sk->daddr);
+         }
+         if (sk->state != TCP_ESTABLISHED && sk->retransmits > TCP_RETR2) {
+           DPRINTF ((DBG_TMR, "timer.c TIME_WRITE time-out 2\n"));
+           sk->err = ETIMEDOUT;
+           if (sk->state == TCP_FIN_WAIT1 || sk->state == TCP_FIN_WAIT2
+             || sk->state == TCP_LAST_ACK) {
+             sk->state = TCP_TIME_WAIT;
+             reset_timer (sk, TIME_CLOSE, TCP_TIMEWAIT_LEN);
+           } else {
+             sk->prot->close (sk, 1);
+             break;
+           }
+         }
+       }
+       release_sock (sk);
+       break;
+    case TIME_KEEPOPEN:
+       /* Send something to keep the connection open. */
+       if (sk->prot->write_wakeup)
+         sk->prot->write_wakeup (sk);
+       sk->retransmits++;
+       if (sk->shutdown == SHUTDOWN_MASK) {
+         sk->prot->close (sk, 1);
+         sk->state = TCP_CLOSE;
+       }
+
+       if ((sk->state == TCP_ESTABLISHED && sk->retransmits && !(sk->retransmits & 7))
+         || (sk->state != TCP_ESTABLISHED && sk->retransmits > TCP_RETR1)) {
+         DPRINTF ((DBG_TMR, "timer.c TIME_KEEPOPEN time-out 1\n"));
+         arp_destroy (sk->daddr);
+         ip_route_check (sk->daddr);
+         release_sock (sk);
+         break;
+       }
+       if (sk->state != TCP_ESTABLISHED && sk->retransmits > TCP_RETR2) {
+         DPRINTF ((DBG_TMR, "timer.c TIME_KEEPOPEN time-out 2\n"));
+         arp_destroy (sk->daddr);
+         sk->err = ETIMEDOUT;
+         if (sk->state == TCP_FIN_WAIT1 || sk->state == TCP_FIN_WAIT2) {
+           sk->state = TCP_TIME_WAIT;
+           if (!sk->dead)
+             wake_up (sk->sleep);
+           release_sock (sk);
+         } else {
+           sk->prot->close (sk, 1);
+         }
+         break;
+       }
+       release_sock (sk);
+       break;
+    default:
+       printk ("net timer expired - reason unknown, sk=%08X\n", (int)sk);
+       release_sock (sk);
+       break;
+  }
 }
 
index 33d2b386a3d0673c3e38c37fc35bc7b5115753b9..78066c3f629686d75fd2b5db8194477aa79f58ea 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             The User Datagram Protocol (UDP).
  *
- * Version:    @(#)udp.c       1.28    22/12/93
+ * Version:    @(#)udp.c       1.0.13  06/02/93
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *                                     bug no longer crashes it.
  *             Fred Van Kempen :       Net2e support for sk->broadcast.
  *             Alan Cox        :       Uses skb_free_datagram
- *             Alan Cox        :       Tidy up ready for the 'real' thing.
- *             Alan Cox        :       Added get/set sockopt support.
- *             Alan Cox        :       Broadcasting without option set returns EACCES.
- *             Alan Cox        :       No wakeup calls. Instead we now use the callbacks.
  *
+ * To Do:
+ *             Verify all the error codes from UDP operations match the
+ *             BSD behaviour, since thats effectively the formal spec.
  *
  *             This program is free software; you can redistribute it and/or
  *             modify it under the terms of the GNU General Public License
 #include <linux/termios.h>
 #include <linux/mm.h>
 #include "inet.h"
-#include "devinet.h"
+#include "dev.h"
 #include "ip.h"
 #include "protocol.h"
 #include "tcp.h"
 #include "skbuff.h"
-#include "sockinet.h"
+#include "sock.h"
 #include "udp.h"
 #include "icmp.h"
 
 #define min(a,b)       ((a)<(b)?(a):(b))
 
 
-static void print_udp(struct udphdr *uh)
+static void
+print_udp(struct udphdr *uh)
 {
-       if (inet_debug != DBG_UDP) 
-               return;
-
-       if (uh == NULL) 
-       {
-               printk("(NULL)\n");
-               return;
-       }
-       printk("UDP: source = %d, dest = %d\n", ntohs(uh->source), ntohs(uh->dest));
-       printk("     len = %d, check = %d\n", ntohs(uh->len), ntohs(uh->check));
+  if (inet_debug != DBG_UDP) return;
+
+  if (uh == NULL) {
+       printk("(NULL)\n");
+       return;
+  }
+  printk("UDP: source = %d, dest = %d\n", ntohs(uh->source), ntohs(uh->dest));
+  printk("     len = %d, check = %d\n", ntohs(uh->len), ntohs(uh->check));
 }
 
 
@@ -93,289 +91,285 @@ static void print_udp(struct udphdr *uh)
  * header points to the first 8 bytes of the udp header.  We need
  * to find the appropriate port.
  */
-
-void udp_err(int err, unsigned char *header, unsigned long daddr,
+void
+udp_err(int err, unsigned char *header, unsigned long daddr,
        unsigned long saddr, struct inet_protocol *protocol)
 {
-       struct udphdr *th;
-       struct sock *sk;
-       struct iphdr *ip=(struct iphdr *)header;
-
-       header += 4*ip->ihl;
-
-       th = (struct udphdr *)header;  
-       DPRINTF((DBG_UDP,"UDP: err(err=%d, header=%X, daddr=%X, saddr=%X, protocl=%X)\n\
-       sport=%d,dport=%d", err, header, daddr, saddr, protocol, (int)th->source,(int)th->dest));
+  struct udphdr *th;
+  struct sock *sk;
+  struct iphdr *ip=(struct iphdr *)header;
+  
+  header += 4*ip->ihl;
+  
+  th = (struct udphdr *)header;  
+   
+  DPRINTF((DBG_UDP,"UDP: err(err=%d, header=%X, daddr=%X, saddr=%X, protocl=%X)\n\
+sport=%d,dport=%d", err, header, daddr, saddr, protocol, (int)th->source,(int)th->dest));
 
-       sk = get_sock(&udp_prot, th->source, daddr, th->dest, saddr);
+  sk = get_sock(&udp_prot, th->source, daddr, th->dest, saddr);
 
-       if (sk == NULL) 
-               return; /* No socket for error */
+  if (sk == NULL) 
+       return; /* No socket for error */
        
-       if (err < 0)            /* As per the calling spec */
-       {
-               sk->err = -err;
-               sk->error_report(sk);           /* User process wakes to see error */
-               return;
-       }
+  if (err < 0)         /* As per the calling spec */
+  {
+       sk->err = -err;
+       wake_up(sk->sleep);     /* User process wakes to see error */
+       return;
+  }
   
-       if (err & 0xff00 ==(ICMP_SOURCE_QUENCH << 8)) 
-       {               /* Slow down! */
-               if (sk->cong_window > 1) 
-                       sk->cong_window = sk->cong_window/2;
-               return;
-       }
-
-       sk->err = icmp_err_convert[err & 0xff].errno;
-
-       /* It's only fatal if we have connected to them. */
-       if (icmp_err_convert[err & 0xff].fatal && sk->state == TCP_ESTABLISHED) 
-       {
-               sk->err=ECONNREFUSED;
-       }
-       sk->error_report(sk);
+  if (err & 0xff00 ==(ICMP_SOURCE_QUENCH << 8)) {      /* Slow down! */
+       if (sk->cong_window > 1) 
+               sk->cong_window = sk->cong_window/2;
+       return;
+  }
+
+  sk->err = icmp_err_convert[err & 0xff].errno;
+
+  /* It's only fatal if we have connected to them. */
+  if (icmp_err_convert[err & 0xff].fatal && sk->state == TCP_ESTABLISHED) {
+       sk->err=ECONNREFUSED;
+  }
+  wake_up(sk->sleep);
 }
 
 
-static unsigned short udp_check(struct udphdr *uh, int len,
+static unsigned short
+udp_check(struct udphdr *uh, int len,
          unsigned long saddr, unsigned long daddr)
 {
-       unsigned long sum;
+  unsigned long sum;
 
-       DPRINTF((DBG_UDP, "UDP: check(uh=%X, len = %d, saddr = %X, daddr = %X)\n",
+  DPRINTF((DBG_UDP, "UDP: check(uh=%X, len = %d, saddr = %X, daddr = %X)\n",
                                                        uh, len, saddr, daddr));
 
-       print_udp(uh);
-
-       __asm__("\t addl %%ecx,%%ebx\n"
-               "\t adcl %%edx,%%ebx\n"
-               "\t adcl $0, %%ebx\n"
-               : "=b"(sum)
-               : "0"(daddr), "c"(saddr), "d"((ntohs(len) << 16) + IPPROTO_UDP*256)
-               : "cx","bx","dx" );
-
-       if (len > 3) 
-       {
-               __asm__("\tclc\n"
-                       "1:\n"
-                       "\t lodsl\n"
-                       "\t adcl %%eax, %%ebx\n"
-                       "\t loop 1b\n"
-                       "\t adcl $0, %%ebx\n"
-                       : "=b"(sum) , "=S"(uh)
-                       : "0"(sum), "c"(len/4) ,"1"(uh)
-                       : "ax", "cx", "bx", "si" );
-       }       
-
-       /* Convert from 32 bits to 16 bits. */
-       __asm__("\t movl %%ebx, %%ecx\n"
-               "\t shrl $16,%%ecx\n"
-               "\t addw %%cx, %%bx\n"
-               "\t adcw $0, %%bx\n"
-               : "=b"(sum)
-               : "0"(sum)
-               : "bx", "cx");
-
-       /* Check for an extra word. */
-       if ((len & 2) != 0) 
-       {
-               __asm__("\t lodsw\n"
-                       "\t addw %%ax,%%bx\n"
-                       "\t adcw $0, %%bx\n"
-                       : "=b"(sum), "=S"(uh)
-                       : "0"(sum) ,"1"(uh)
-                       : "si", "ax", "bx");
-       }
-
-       /* Now check for the extra byte. */
-       if ((len & 1) != 0) 
-       {
-               __asm__("\t lodsb\n"
-                       "\t movb $0,%%ah\n"
-                       "\t addw %%ax,%%bx\n"
-                       "\t adcw $0, %%bx\n"
-                       : "=b"(sum)
-                       : "0"(sum) ,"S"(uh)
-                       : "si", "ax", "bx");
-       }
-
-       /* We only want the bottom 16 bits, but we never cleared the top 16. */
-       return((~sum) & 0xffff);
+  print_udp(uh);
+
+  __asm__("\t addl %%ecx,%%ebx\n"
+         "\t adcl %%edx,%%ebx\n"
+         "\t adcl $0, %%ebx\n"
+         : "=b"(sum)
+         : "0"(daddr), "c"(saddr), "d"((ntohs(len) << 16) + IPPROTO_UDP*256)
+         : "cx","bx","dx" );
+
+  if (len > 3) {
+       __asm__("\tclc\n"
+               "1:\n"
+               "\t lodsl\n"
+               "\t adcl %%eax, %%ebx\n"
+               "\t loop 1b\n"
+               "\t adcl $0, %%ebx\n"
+               : "=b"(sum) , "=S"(uh)
+               : "0"(sum), "c"(len/4) ,"1"(uh)
+               : "ax", "cx", "bx", "si" );
+  }
+
+  /* Convert from 32 bits to 16 bits. */
+  __asm__("\t movl %%ebx, %%ecx\n"
+         "\t shrl $16,%%ecx\n"
+         "\t addw %%cx, %%bx\n"
+         "\t adcw $0, %%bx\n"
+         : "=b"(sum)
+         : "0"(sum)
+         : "bx", "cx");
+
+  /* Check for an extra word. */
+  if ((len & 2) != 0) {
+       __asm__("\t lodsw\n"
+               "\t addw %%ax,%%bx\n"
+               "\t adcw $0, %%bx\n"
+               : "=b"(sum), "=S"(uh)
+               : "0"(sum) ,"1"(uh)
+               : "si", "ax", "bx");
+  }
+
+  /* Now check for the extra byte. */
+  if ((len & 1) != 0) {
+       __asm__("\t lodsb\n"
+               "\t movb $0,%%ah\n"
+               "\t addw %%ax,%%bx\n"
+               "\t adcw $0, %%bx\n"
+               : "=b"(sum)
+               : "0"(sum) ,"S"(uh)
+               : "si", "ax", "bx");
+  }
+
+  /* We only want the bottom 16 bits, but we never cleared the top 16. */
+  return((~sum) & 0xffff);
 }
 
-/*
- *     Calculate the UDP checksum. Note 0 becomes FFFF because 0 means
- *     'no checksum'.
- */
 
-static void udp_send_check(struct udphdr *uh, unsigned long saddr, 
+static void
+udp_send_check(struct udphdr *uh, unsigned long saddr, 
               unsigned long daddr, int len, struct sock *sk)
 {
-       uh->check = 0;
-       if (sk && sk->no_check) 
-               return;
-       uh->check = udp_check(uh, len, saddr, daddr);
-       if (uh->check == 0) 
-               uh->check = 0xffff;
+  uh->check = 0;
+  if (sk && sk->no_check) 
+       return;
+  uh->check = udp_check(uh, len, saddr, daddr);
+  if (uh->check == 0) uh->check = 0xffff;
 }
 
 
-static int udp_send(struct sock *sk, struct sockaddr_in *sin,
+static int
+udp_send(struct sock *sk, struct sockaddr_in *sin,
         unsigned char *from, int len)
 {
-       struct sk_buff *skb;
-       struct device *dev;
-       struct udphdr *uh;
-       unsigned char *buff;
-       unsigned long saddr;
-       int size, tmp;
-       int err;
+  struct sk_buff *skb;
+  struct device *dev;
+  struct udphdr *uh;
+  unsigned char *buff;
+  unsigned long saddr;
+  int size, tmp;
+  int err;
   
-       DPRINTF((DBG_UDP, "UDP: send(dst=%s:%d buff=%X len=%d)\n",
+  DPRINTF((DBG_UDP, "UDP: send(dst=%s:%d buff=%X len=%d)\n",
                in_ntoa(sin->sin_addr.s_addr), ntohs(sin->sin_port),
                from, len));
 
-       err=verify_area(VERIFY_READ, from, len);
-       if(err)
-               return(err);
-
-       /* Allocate a copy of the packet. */
-       size = sizeof(struct sk_buff) + sk->prot->max_header + len;
-       skb = (struct sk_buff *) sk->prot->wmalloc(sk, size, 0, GFP_KERNEL);
-       if (skb == NULL) 
-               return(-ENOMEM);
-
-       skb->sk       = NULL;   /* to avoid changing sk->saddr */
-       skb->free     = 1;
-       skb->arp      = 0;
-
-       /* Now build the IP and MAC header. */
-       buff = (unsigned char *) (skb+1);
-       saddr = 0;
-       dev = NULL;
-       DPRINTF((DBG_UDP, "UDP: >> IP_Header: %X -> %X dev=%X prot=%X len=%d\n",
+  err=verify_area(VERIFY_READ, from, len);
+  if(err)
+       return(err);
+
+  /* Allocate a copy of the packet. */
+  size = sizeof(struct sk_buff) + sk->prot->max_header + len;
+  skb = (struct sk_buff *) sk->prot->wmalloc(sk, size, 0, GFP_KERNEL);
+  if (skb == NULL) return(-ENOMEM);
+
+  skb->mem_addr = skb;
+  skb->mem_len  = size;
+  skb->sk       = NULL;        /* to avoid changing sk->saddr */
+  skb->free     = 1;
+  skb->arp      = 0;
+
+  /* Now build the IP and MAC header. */
+  buff = (unsigned char *) (skb+1);
+  saddr = 0;
+  dev = NULL;
+  DPRINTF((DBG_UDP, "UDP: >> IP_Header: %X -> %X dev=%X prot=%X len=%d\n",
                        saddr, sin->sin_addr.s_addr, dev, IPPROTO_UDP, skb->mem_len));
-       tmp = sk->prot->build_header(skb, saddr, sin->sin_addr.s_addr,
-                              &dev, IPPROTO_UDP, sk->opt, skb->mem_len, 
-                              sk->ip_ttl,sk->ip_tos);
-       skb->sk=sk;     /* So memory is freed correctly */
+  tmp = sk->prot->build_header(skb, saddr, sin->sin_addr.s_addr,
+                              &dev, IPPROTO_UDP, sk->opt, skb->mem_len);
+  skb->sk=sk;  /* So memory is freed correctly */
                            
-       if (tmp < 0 ) 
-       {
-               sk->prot->wfree(sk, skb->mem_addr, skb->mem_len);
-               return(tmp);
-       }
-       buff += tmp;
-       saddr = dev->pa_addr;
-       DPRINTF((DBG_UDP, "UDP: >> MAC+IP len=%d\n", tmp));
-
-       skb->len = tmp + sizeof(struct udphdr) + len;   /* len + UDP + IP + MAC */
-       skb->dev = dev;
-       if (skb->len > 4095)
-       {
-               printk("UDP: send: length %d > mtu %d (ignored)\n", len, 4095);
-               sk->prot->wfree(sk, skb->mem_addr, skb->mem_len);
-               return(-EMSGSIZE);
-       }
-       
-       /* Fill in the UDP header. */
-       uh = (struct udphdr *) buff;
-       uh->len = htons(len + sizeof(struct udphdr));
-       uh->source = sk->dummy_th.source;
-       uh->dest = sin->sin_port;
-       buff = (unsigned char *) (uh + 1);
-
-       /* Copy the user data. */
-       memcpy_fromfs(buff, from, len);
-
-       /* Set up the UDP checksum. */
-       udp_send_check(uh, saddr, sin->sin_addr.s_addr, skb->len - tmp, sk);
-
-       /* Send the datagram to the interface. */
-       sk->prot->queue_xmit(sk, dev, skb, 1);
-
-       return(len);
+  if (tmp < 0 ) {
+       sk->prot->wfree(sk, skb->mem_addr, skb->mem_len);
+       return(tmp);
+  }
+  buff += tmp;
+  saddr = dev->pa_addr;
+  DPRINTF((DBG_UDP, "UDP: >> MAC+IP len=%d\n", tmp));
+
+  skb->len = tmp + sizeof(struct udphdr) + len;        /* len + UDP + IP + MAC */
+  skb->dev = dev;
+#ifdef OLD
+  /*
+   * This code used to hack in some form of fragmentation.
+   * I removed that, since it didn't work anyway, and it made the
+   * code a bad thing to read and understand. -FvK
+   */
+  if (len > dev->mtu) {
+#else
+  if (skb->len > 4095)
+  {
+#endif    
+       printk("UDP: send: length %d > mtu %d (ignored)\n", len, dev->mtu);
+       sk->prot->wfree(sk, skb->mem_addr, skb->mem_len);
+       return(-EMSGSIZE);
+  }
+
+  /* Fill in the UDP header. */
+  uh = (struct udphdr *) buff;
+  uh->len = htons(len + sizeof(struct udphdr));
+  uh->source = sk->dummy_th.source;
+  uh->dest = sin->sin_port;
+  buff = (unsigned char *) (uh + 1);
+
+  /* Copy the user data. */
+  memcpy_fromfs(buff, from, len);
+
+  /* Set up the UDP checksum. */
+  udp_send_check(uh, saddr, sin->sin_addr.s_addr, skb->len - tmp, sk);
+
+  /* Send the datagram to the interface. */
+  sk->prot->queue_xmit(sk, dev, skb, 1);
+
+  return(len);
 }
 
 
-static int udp_sendto(struct sock *sk, unsigned char *from, int len, int noblock,
+static int
+udp_sendto(struct sock *sk, unsigned char *from, int len, int noblock,
           unsigned flags, struct sockaddr_in *usin, int addr_len)
 {
-       struct sockaddr_in sin;
-       int tmp;
-       int err;
-
-       DPRINTF((DBG_UDP, "UDP: sendto(len=%d, flags=%X)\n", len, flags));
-
-       /* Check the flags. */
-       if (flags) 
-               return(-EINVAL);
-       if (len < 0) 
-               return(-EINVAL);
-       if (len == 0) 
-               return(0);
-
-       /* Get and verify the address. */
-       if (usin) 
-       {
-               if (addr_len < sizeof(sin)) 
-                       return(-EINVAL);
-               err=verify_area(VERIFY_READ, usin, sizeof(sin));
-               if(err)
-                       return err;
-               memcpy_fromfs(&sin, usin, sizeof(sin));
-               if (sin.sin_family && sin.sin_family != AF_INET) 
-                       return(-EINVAL);
-               if (sin.sin_port == 0) 
-                       return(-EINVAL);
-       } 
-       else 
-       {
-               if (sk->state != TCP_ESTABLISHED) 
-                       return(-EINVAL);
-               sin.sin_family = AF_INET;
-               sin.sin_port = sk->dummy_th.dest;
-               sin.sin_addr.s_addr = sk->daddr;
-       }
+  struct sockaddr_in sin;
+  int tmp;
+  int err;
+
+  DPRINTF((DBG_UDP, "UDP: sendto(len=%d, flags=%X)\n", len, flags));
+
+  /* Check the flags. */
+  if (flags) 
+       return(-EINVAL);
+  if (len < 0) 
+       return(-EINVAL);
+  if (len == 0) 
+       return(0);
+
+  /* Get and verify the address. */
+  if (usin) {
+       if (addr_len < sizeof(sin)) return(-EINVAL);
+       err=verify_area(VERIFY_READ, usin, sizeof(sin));
+       if(err)
+               return err;
+       memcpy_fromfs(&sin, usin, sizeof(sin));
+       if (sin.sin_family && sin.sin_family != AF_INET) 
+               return(-EINVAL);
+       if (sin.sin_port == 0) 
+               return(-EINVAL);
+  } else {
+       if (sk->state != TCP_ESTABLISHED) return(-EINVAL);
+       sin.sin_family = AF_INET;
+       sin.sin_port = sk->dummy_th.dest;
+       sin.sin_addr.s_addr = sk->daddr;
+  }
   
-       if(!sk->broadcast && chk_addr(sin.sin_addr.s_addr)==IS_BROADCAST)
-               return -EACCES;                 /* Must turn broadcast on first */
-       sk->inuse = 1;
+  if(!sk->broadcast && chk_addr(sin.sin_addr.s_addr)==IS_BROADCAST)
+       return -ENETUNREACH;            /* Must turn broadcast on first */
+  sk->inuse = 1;
 
-       /* Send the packet. */
-       tmp = udp_send(sk, &sin, from, len);
+  /* Send the packet. */
+  tmp = udp_send(sk, &sin, from, len);
 
-       /* The datagram has been sent off.  Release the socket. */
-       release_sock(sk);
-       return(tmp);
+  /* The datagram has been sent off.  Release the socket. */
+  release_sock(sk);
+  return(tmp);
 }
 
 
-static int udp_write(struct sock *sk, unsigned char *buff, int len, int noblock,
+static int
+udp_write(struct sock *sk, unsigned char *buff, int len, int noblock,
          unsigned flags)
 {
-       return(udp_sendto(sk, buff, len, noblock, flags, NULL, 0));
+  return(udp_sendto(sk, buff, len, noblock, flags, NULL, 0));
 }
 
 
-int udp_ioctl(struct sock *sk, int cmd, unsigned long arg)
+int
+udp_ioctl(struct sock *sk, int cmd, unsigned long arg)
 {
-       int err;
-       switch(cmd) 
-       {
-               case DDIOCSDBG:
+  int err;
+  switch(cmd) {
+       case DDIOCSDBG:
                {
                        int val;
 
-                       if (!suser()) 
-                               return(-EPERM);
+                       if (!suser()) return(-EPERM);
                        err=verify_area(VERIFY_READ, (void *)arg, sizeof(int));
                        if(err)
                                return err;
                        val = get_fs_long((int *)arg);
-                       switch(val) 
-                       {
+                       switch(val) {
                                case 0:
                                        inet_debug = 0;
                                        break;
@@ -387,14 +381,12 @@ int udp_ioctl(struct sock *sk, int cmd, unsigned long arg)
                        }
                }
                break;
-               
-               case TIOCOUTQ:
+       case TIOCOUTQ:
                {
                        unsigned long amount;
 
-                       if (sk->state == TCP_LISTEN) 
-                               return(-EINVAL);
-                       amount = sk->prot->wspace(sk);
+                       if (sk->state == TCP_LISTEN) return(-EINVAL);
+                       amount = sk->prot->wspace(sk)/*/2*/;
                        err=verify_area(VERIFY_WRITE,(void *)arg,
                                        sizeof(unsigned long));
                        if(err)
@@ -403,17 +395,15 @@ int udp_ioctl(struct sock *sk, int cmd, unsigned long arg)
                        return(0);
                }
 
-               case TIOCINQ:
+       case TIOCINQ:
                {
                        struct sk_buff *skb;
                        unsigned long amount;
 
-                       if (sk->state == TCP_LISTEN) 
-                               return(-EINVAL);
+                       if (sk->state == TCP_LISTEN) return(-EINVAL);
                        amount = 0;
                        skb = sk->rqueue;
-                       if (skb != NULL) 
-                       {
+                       if (skb != NULL) {
                                /*
                                 * We will only return the amount
                                 * of this packet since that is all
@@ -429,233 +419,224 @@ int udp_ioctl(struct sock *sk, int cmd, unsigned long arg)
                        return(0);
                }
 
-               default:
-                       return(-EINVAL);
-       }
-       return(0);
+       default:
+               return(-EINVAL);
+  }
+  return(0);
 }
 
 
 /*
- * This should be easy, if there is something there we
+ * This should be easy, if there is something there we\
  * return it, otherwise we block.
  */
-int udp_recvfrom(struct sock *sk, unsigned char *to, int len,
+int
+udp_recvfrom(struct sock *sk, unsigned char *to, int len,
             int noblock, unsigned flags, struct sockaddr_in *sin,
             int *addr_len)
 {
-       int copied = 0;
-       struct sk_buff *skb;
-       int er;
-
-
-       /*
-        * This will pick up errors that occured while the program
-        * was doing something else.
-        */
-       if (sk->err) 
-       {
-               int err;
-       
-               err = -sk->err;
-               sk->err = 0;
-               return(err);
-       }
+  int copied = 0;
+  struct sk_buff *skb;
+  int er;
+
 
-       if (len == 0) 
-               return(0);
-       if (len < 0) 
-               return(-EINVAL);
-
-       if (addr_len) 
-       {
-               er=verify_area(VERIFY_WRITE, addr_len, sizeof(*addr_len));
-               if(er)
-                       return(er);
-               put_fs_long(sizeof(*sin), addr_len);
-       }
-       if(sin)
-       {
-               er=verify_area(VERIFY_WRITE, sin, sizeof(*sin));
-               if(er)
-                       return(er);
-       }
-       er=verify_area(VERIFY_WRITE,to,len);
+  /*
+   * This will pick up errors that occured while the program
+   * was doing something else.
+   */
+  if (sk->err) {
+       int err;
+
+       err = -sk->err;
+       sk->err = 0;
+       return(err);
+  }
+
+  if (len == 0) 
+       return(0);
+  if (len < 0) 
+       return(-EINVAL);
+
+  if (addr_len) {
+       er=verify_area(VERIFY_WRITE, addr_len, sizeof(*addr_len));
+       if(er)
+               return(er);
+       put_fs_long(sizeof(*sin), addr_len);
+  }
+  if(sin)
+  {
+       er=verify_area(VERIFY_WRITE, sin, sizeof(*sin));
        if(er)
-               return er;
-       skb=skb_recv_datagram(sk,flags,noblock,&er);
-       if(skb==NULL)
-               return er;
-       copied = min(len, skb->len);
-       
+               return(er);
+  }
+  er=verify_area(VERIFY_WRITE,to,len);
+  if(er)
+       return er;
+  skb=skb_recv_datagram(sk,flags,noblock,&er);
+  if(skb==NULL)
+       return er;
+  copied = min(len, skb->len);
+
   /* FIXME : should use udp header size info value */
-       skb_copy_datagram(skb,sizeof(struct udphdr),to,copied);
+  skb_copy_datagram(skb,sizeof(struct udphdr),to,copied);
 
   /* Copy the address. */
-       if (sin) 
-       {
-               struct sockaddr_in addr;
-       
-               addr.sin_family = AF_INET;
-               addr.sin_port = skb->h.uh->source;
-               addr.sin_addr.s_addr = skb->daddr;
-               memcpy_tofs(sin, &addr, sizeof(*sin));
-       }
+  if (sin) {
+       struct sockaddr_in addr;
+
+       addr.sin_family = AF_INET;
+       addr.sin_port = skb->h.uh->source;
+       addr.sin_addr.s_addr = skb->daddr;
+       memcpy_tofs(sin, &addr, sizeof(*sin));
+  }
   
-       skb_free_datagram(skb);
-       release_sock(sk);
-       return(copied);
+  skb_free_datagram(skb);
+  release_sock(sk);
+  return(copied);
 }
 
 
-int udp_read(struct sock *sk, unsigned char *buff, int len, int noblock,
+int
+udp_read(struct sock *sk, unsigned char *buff, int len, int noblock,
         unsigned flags)
 {
-       return(udp_recvfrom(sk, buff, len, noblock, flags, NULL, NULL));
+  return(udp_recvfrom(sk, buff, len, noblock, flags, NULL, NULL));
 }
 
 
-int udp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len)
+int
+udp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len)
 {
-       struct sockaddr_in sin;
-       int er;
+  struct sockaddr_in sin;
+  int er;
   
-       if (addr_len < sizeof(sin)) 
-               return(-EINVAL);
+  if (addr_len < sizeof(sin)) 
+       return(-EINVAL);
 
-       er=verify_area(VERIFY_READ, usin, sizeof(sin));
-       if(er)
-               return er;
+  er=verify_area(VERIFY_READ, usin, sizeof(sin));
+  if(er)
+       return er;
 
-       memcpy_fromfs(&sin, usin, sizeof(sin));
-       if (sin.sin_family && sin.sin_family != AF_INET) 
-               return(-EAFNOSUPPORT);
+  memcpy_fromfs(&sin, usin, sizeof(sin));
+  if (sin.sin_family && sin.sin_family != AF_INET) 
+       return(-EAFNOSUPPORT);
 
-       if(!sk->broadcast && chk_addr(sin.sin_addr.s_addr)==IS_BROADCAST)
-               return -EACCES;                 /* Must turn broadcast on first */
+  if(!sk->broadcast && chk_addr(sin.sin_addr.s_addr)==IS_BROADCAST)
+       return -ENETUNREACH;            /* Must turn broadcast on first */
        
-       sk->daddr = sin.sin_addr.s_addr;
-       sk->dummy_th.dest = sin.sin_port;
-       sk->state = TCP_ESTABLISHED;
-       return(0);
+  sk->daddr = sin.sin_addr.s_addr;
+  sk->dummy_th.dest = sin.sin_port;
+  sk->state = TCP_ESTABLISHED;
+  return(0);
 }
 
 
-static void udp_close(struct sock *sk, int timeout)
+static void
+udp_close(struct sock *sk, int timeout)
 {
-       sk->inuse = 1;
-       sk->state = TCP_CLOSE;
-       if (sk->dead) 
-               destroy_sock(sk);
-       else 
-               release_sock(sk);
+  sk->inuse = 1;
+  sk->state = TCP_CLOSE;
+  if (sk->dead) destroy_sock(sk);
+    else release_sock(sk);
 }
 
 
-/*
- *     All we need to do is get the socket, and then do a checksum. 
- */
-int udp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
+/* All we need to do is get the socket, and then do a checksum. */
+int
+udp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
        unsigned long daddr, unsigned short len,
        unsigned long saddr, int redo, struct inet_protocol *protocol)
 {
-       struct sock *sk;
-       struct udphdr *uh;
-
-       uh = (struct udphdr *) skb->h.uh;
-       sk = get_sock(&udp_prot, uh->dest, saddr, uh->source, daddr);
-       if (sk == NULL) 
-       {
-               if (chk_addr(daddr) == IS_MYADDR) 
-               {
-                       icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, dev);
-               }
-               /*
-                * Hmm.  We got an UDP broadcast to a port to which we
-                * don't wanna listen.  The only thing we can do now is
-                * to ignore the packet... -FvK
-                */
-               skb->sk = NULL;
-               kfree_skb(skb, FREE_WRITE);
-               return(0);
-       }
-
-       if (uh->check && udp_check(uh, len, saddr, daddr)) 
-       {
-               DPRINTF((DBG_UDP, "UDP: bad checksum\n"));
-               skb->sk = NULL;
-               kfree_skb(skb, FREE_WRITE);
-               return(0);
-       }
-
-       skb->sk = sk;
-       skb->dev = dev;
-       skb->len = len;
-
-       /* These are supposed to be switched. */
-       skb->daddr = saddr;
-       skb->saddr = daddr;
-
-
-       /* Charge it to the socket. */
-       if (sk->rmem_alloc + skb->mem_len >= sk->rcvbuf) 
-       {
-               skb->sk = NULL;
-               kfree_skb(skb, FREE_WRITE);
-               release_sock(sk);
-               return(0);
+  struct sock *sk;
+  struct udphdr *uh;
+
+  uh = (struct udphdr *) skb->h.uh;
+  sk = get_sock(&udp_prot, uh->dest, saddr, uh->source, daddr);
+  if (sk == NULL) 
+  {
+       if (chk_addr(daddr) == IS_MYADDR) 
+       {
+               icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, dev);
        }
-       sk->rmem_alloc += skb->mem_len;
+       /*
+        * Hmm.  We got an UDP broadcast to a port to which we
+        * don't wanna listen.  The only thing we can do now is
+        * to ignore the packet... -FvK
+        */
+       skb->sk = NULL;
+       kfree_skb(skb, FREE_WRITE);
+       return(0);
+  }
+
+  if (uh->check && udp_check(uh, len, saddr, daddr)) {
+       DPRINTF((DBG_UDP, "UDP: bad checksum\n"));
+       skb->sk = NULL;
+       kfree_skb(skb, FREE_WRITE);
+       return(0);
+  }
+
+  skb->sk = sk;
+  skb->dev = dev;
+  skb->len = len;
+
+/* These are supposed to be switched. */
+  skb->daddr = saddr;
+  skb->saddr = daddr;
+
+
+  /* Charge it to the socket. */
+  if (sk->rmem_alloc + skb->mem_len >= sk->rcvbuf) 
+  {
+       skb->sk = NULL;
+       kfree_skb(skb, FREE_WRITE);
+       release_sock(sk);
+       return(0);
+  }
+  sk->rmem_alloc += skb->mem_len;
 
-       /* At this point we should print the thing out. */
-       DPRINTF((DBG_UDP, "<< \n"));
-       print_udp(uh);
+  /* At this point we should print the thing out. */
+  DPRINTF((DBG_UDP, "<< \n"));
+  print_udp(uh);
 
-       /* Now add it to the data chain and wake things up. */
+  /* Now add it to the data chain and wake things up. */
   
-       skb_queue_tail(&sk->rqueue,skb);
+  skb_queue_tail(&sk->rqueue,skb);
 
-       skb->len = len - sizeof(*uh);
+  skb->len = len - sizeof(*uh);
 
-       release_sock(sk);
+  if (!sk->dead) wake_up(sk->sleep);
 
-       if (!sk->dead) 
-               sk->data_ready(sk,skb->len);
-
-       return(0);
+  release_sock(sk);
+  return(0);
 }
 
 
-struct proto udp_prot = 
-{
-       sock_wmalloc,
-       sock_rmalloc,
-       sock_wfree,
-       sock_rfree,
-       sock_rspace,
-       sock_wspace,
-       udp_close,
-       udp_read,
-       udp_write,
-       udp_sendto,
-       udp_recvfrom,
-       ip_build_header,
-       udp_connect,
-       NULL,
-       ip_queue_xmit,
-       ip_retransmit,
-       NULL,
-       NULL,
-       udp_rcv,
-       datagram_select,
-       udp_ioctl,
-       NULL,
-       NULL,
-       ip_setsockopt,
-       ip_getsockopt,
-       128,
-       0,
-       {NULL,},
-       "UDP"
+struct proto udp_prot = {
+  sock_wmalloc,
+  sock_rmalloc,
+  sock_wfree,
+  sock_rfree,
+  sock_rspace,
+  sock_wspace,
+  udp_close,
+  udp_read,
+  udp_write,
+  udp_sendto,
+  udp_recvfrom,
+  ip_build_header,
+  udp_connect,
+  NULL,
+  ip_queue_xmit,
+  ip_retransmit,
+  NULL,
+  NULL,
+  udp_rcv,
+  datagram_select,
+  udp_ioctl,
+  NULL,
+  NULL,
+  128,
+  0,
+  {NULL,},
+  "UDP"
 };
index 821fbe83823ccc4eab45c86bc02dd69906ee4424..f9e81e3dc73906153408eb2008a435268cc9bdf7 100644 (file)
@@ -6,13 +6,12 @@
  *             Various kernel-resident INET utility functions; mainly
  *             for format conversion and debugging output.
  *
- * Version:    @(#)utils.c     1.28    20/12/93
+ * Version:    @(#)utils.c     1.0.7   05/18/93
  *
  * Author:     Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *
  * Fixes:
  *             Alan Cox        :       verify_area check.
- *             Alan Cox        :       Clean up to match code style
  *
  *
  *             This program is free software; you can redistribute it and/or
@@ -33,7 +32,7 @@
 #include <linux/stat.h>
 #include <stdarg.h>
 #include "inet.h"
-#include "devinet.h"
+#include "dev.h"
 #include "eth.h"
 #include "ip.h"
 #include "protocol.h"
 #include "arp.h"
 
 
-/*
- *     Display an IP address in readable format. 
- */
+/* Display an IP address in readable format. */
 char *in_ntoa(unsigned long in)
 {
-       static char buff[18];
-       register char *p;
+  static char buff[18];
+  register char *p;
 
-       p = (char *) &in;
-       sprintf(buff, "%d.%d.%d.%d",
-               (p[0] & 255), (p[1] & 255), (p[2] & 255), (p[3] & 255));
-       return(buff);
+  p = (char *) &in;
+  sprintf(buff, "%d.%d.%d.%d",
+       (p[0] & 255), (p[1] & 255), (p[2] & 255), (p[3] & 255));
+  return(buff);
 }
 
 
-/*
- *     Convert an ASCII string to binary IP. 
- */
-unsigned long in_aton(char *str)
+/* Convert an ASCII string to binary IP. */
+unsigned long
+in_aton(char *str)
 {
-       unsigned long l;
-       unsigned int val;
-       int i;
-
-       l = 0;
-       for (i = 0; i < 4; i++) 
-       {
-               l <<= 8;
-               if (*str != '\0') 
-               {
-                       val = 0;
-                       while (*str != '\0' && *str != '.') 
-                       {
-                               val *= 10;
-                               val += *str - '0';
-                               str++;
-                       }
-                       l |= val;
-                       if (*str != '\0') 
-                               str++;
+  unsigned long l;
+  unsigned int val;
+  int i;
+
+  l = 0;
+  for (i = 0; i < 4; i++) {
+       l <<= 8;
+       if (*str != '\0') {
+               val = 0;
+               while (*str != '\0' && *str != '.') {
+                       val *= 10;
+                       val += *str - '0';
+                       str++;
                }
-       }
-       return(htonl(l));
+               l |= val;
+               if (*str != '\0') str++;
+       }
+  }
+  return(htonl(l));
 }
 
 
-void dprintf(int level, char *fmt, ...)
+void
+dprintf(int level, char *fmt, ...)
 {
-       va_list args;
-       char *buff;
-       extern int vsprintf(char * buf, const char * fmt, va_list args);
-
-       if (level != inet_debug) 
-               return;
-
-       buff = (char *) kmalloc(256, GFP_ATOMIC);
-       if (buff != NULL) 
-       {
-               va_start(args, fmt);
-               vsprintf(buff, fmt, args);
-               va_end(args);
-               printk(buff);
-               kfree(buff);
-       }
+  va_list args;
+  char *buff;
+  extern int vsprintf(char * buf, const char * fmt, va_list args);
+
+  if (level != inet_debug) return;
+
+  buff = (char *) kmalloc(256, GFP_ATOMIC);
+  if (buff != NULL) {
+       va_start(args, fmt);
+       vsprintf(buff, fmt, args);
+       va_end(args);
+       printk(buff);
+       kfree(buff);
+  }
 }
 
 
-int dbg_ioctl(void *arg, int level)
+int
+dbg_ioctl(void *arg, int level)
 {
-       int val;
-       int err;
+  int val;
+  int err;
   
-       if (!suser()) 
-               return(-EPERM);
-       err=verify_area(VERIFY_READ, (void *)arg, sizeof(int));
-       if(err)
-               return err;
-       val = get_fs_long((int *)arg);
-       switch(val) 
-       {
-               case 0: /* OFF */
-                       inet_debug = DBG_OFF;
-                       break;
-               case 1: /* ON, INET */
-                       inet_debug = level;
-                       break;
-
-               case DBG_RT:            /* modules */
-               case DBG_DEV:
-               case DBG_ETH:
-               case DBG_PROTO:
-               case DBG_TMR:
-               case DBG_PKT:
-               case DBG_RAW:
-       
-               case DBG_LOOPB:         /* drivers */
-               case DBG_SLIP:
-       
-               case DBG_ARP:           /* protocols */
-               case DBG_IP:
-               case DBG_ICMP:
-               case DBG_TCP:
-               case DBG_UDP:
-       
-                       inet_debug = val;
-                       break;
-       
-               default:
-                       return(-EINVAL);
-         }
-       
-         return(0);
+  if (!suser()) return(-EPERM);
+  err=verify_area(VERIFY_READ, (void *)arg, sizeof(int));
+  if(err)
+       return err;
+  val = get_fs_long((int *)arg);
+  switch(val) {
+       case 0: /* OFF */
+               inet_debug = DBG_OFF;
+               break;
+       case 1: /* ON, INET */
+               inet_debug = level;
+               break;
+
+       case DBG_RT:            /* modules */
+       case DBG_DEV:
+       case DBG_ETH:
+       case DBG_PROTO:
+       case DBG_TMR:
+       case DBG_PKT:
+       case DBG_RAW:
+
+       case DBG_LOOPB:         /* drivers */
+       case DBG_SLIP:
+
+       case DBG_ARP:           /* protocols */
+       case DBG_IP:
+       case DBG_ICMP:
+       case DBG_TCP:
+       case DBG_UDP:
+
+               inet_debug = val;
+               break;
+
+       default:
+               return(-EINVAL);
+  }
+
+  return(0);
 }
diff --git a/net/socket/Makefile b/net/socket/Makefile
deleted file mode 100644 (file)
index b3d5b42..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-#
-# Makefile for the Linux socket support layer.
-#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
-# Note 2! The CFLAGS definition is now in the main makefile...
-
-CFLAGS := $(CFLAGS) -I../inet -I..
-CPP := $(CPP) -I../inet -I..
-
-.c.o:
-       $(CC) $(CFLAGS) -c -o $*.o $<
-.s.o:
-       $(AS) -o $*.o $<
-.c.s:
-       $(CC) $(CFLAGS) -S -o $*.s $<
-
-
-OBJS   = datagram.o dev.o skbuff.o sock.o
-
-socket.o:      $(OBJS)
-               $(LD) -r -o socket.o $(OBJS)
-
-dep:
-               $(CPP) -M *.c > .depend
-
-tar:
-               tar -cvf /dev/f1 .
-
-#
-# include a dependency file if one exists
-#
-ifeq (.depend,$(wildcard .depend))
-include .depend
-endif
diff --git a/net/socket/datagram.c b/net/socket/datagram.c
deleted file mode 100644 (file)
index b7ebe91..0000000
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- *     SUCS    NET2 Debugged.
- *
- *     Generic datagram handling routines. These are generic for all protocols. Possibly a generic IP version on top
- *     of these would make sense. Not tonight however 8-). 
- *     This is used because UDP, RAW, PACKET and the to be released IPX layer all have identical select code and mostly
- *     identical recvfrom() code. So we share it here. The select was shared before but buried in udp.c so I moved it.
- *
- *     Authors:        Alan Cox <iiitac@pyr.swan.ac.uk>. (datagram_select() from old udp.c code)
- *
- *     Fixes:
- *             Alan Cox        :       NULL return from skb_peek_copy() understood
- *             Alan Cox        :       Rewrote skb_read_datagram to avoid the skb_peek_copy stuff.
- *             Alan Cox        :       Added support for SOCK_SEQPACKET. IPX can no longer use the SO_TYPE hack but
- *                                     AX.25 now works right, and SPX is feasible.
- *             Alan Cox        :       Tidied up ready for the big day.
- *             Alan Cox        :       Fixed write select of no IP protocol crash.
- */
-
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <asm/segment.h>
-#include <asm/system.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/in.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include "inet.h"
-#include "dev.h"
-#include "ip.h"
-#include "protocol.h"
-#include "arp.h"
-#include "route.h"
-#include "tcp.h"
-#include "udp.h"
-#include "skbuff.h"
-#include "sock.h"
-
-/*
- *     Get a datagram skbuff, understands the peeking, nonblocking wakeups and possible
- *     races. This replaces identical code in packet,raw and udp, as well as the yet to
- *     be released IPX support. It also finally fixes the long standing peek and read
- *     race for datagram sockets. If you alter this routine remember it must be
- *     re-entrant.
- */
-
-struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags, int noblock, int *err)
-{  
-       struct sk_buff *skb;
-       
-       /* Socket is inuse - so the timer doesn't attack it */
-restart:
-       sk->inuse = 1;
-       while(sk->rqueue == NULL)       /* No data */
-       {
-               /* If we are shutdown then no more data is going to appear. We are done */
-               if (sk->shutdown & RCV_SHUTDOWN) 
-               {
-                       release_sock(sk);
-                       *err=0;
-                       return NULL;
-               }
-
-               if(sk->err)
-               {
-                       release_sock(sk);
-                       *err=-sk->err;
-                       sk->err=0;
-                       return NULL;
-               }
-               
-               /* Sequenced packets can come disconnected. If so we report the problem */
-               if(sk->type==SOCK_SEQPACKET && sk->state!=TCP_ESTABLISHED)
-               {
-                       release_sock(sk);
-                       *err=-ENOTCONN;
-                       return NULL;
-               }
-               
-               /* User doesn't want to wait */
-               if (noblock) 
-               {
-                       release_sock(sk);
-                       *err=-EAGAIN;
-                       return NULL;
-               }
-               release_sock(sk);
-               
-               /* Interrupts off so that no packet arrives before we begin sleeping. 
-                  Otherwise we might miss our wake up */
-               cli();
-               if (sk->rqueue == NULL) 
-               {
-                       interruptible_sleep_on(sk->sleep);
-                       /* Signals may need a restart of the syscall */
-                       if (current->signal & ~current->blocked) 
-                       {
-                               sti();
-                               *err=-ERESTARTSYS;
-                               return(NULL);
-                       }
-                       if(sk->err != 0)        /* Error while waiting for packet
-                                                  eg an icmp sent earlier by the
-                                                  peer has finaly turned up now */
-                       {
-                               *err = -sk->err;
-                               sti();
-                               sk->err=0;
-                               return NULL;
-                       }
-               }
-               sk->inuse = 1;
-               sti();
-         }
-         /* Again only user level code calls this function, so nothing interrupt level
-            will suddenely eat the rqueue */
-         if (!(flags & MSG_PEEK)) 
-         {
-               skb=skb_dequeue(&sk->rqueue);
-               if(skb!=NULL)
-                       skb->users++;
-               else
-                       goto restart;   /* Avoid race if someone beats us to the data */
-         }
-         else
-         {
-               cli();
-               skb=skb_peek(&sk->rqueue);
-               if(skb!=NULL)
-                       skb->users++;
-               sti();
-               if(skb==NULL)   /* shouldn't happen but .. */
-                       *err=-EAGAIN;
-         }
-         return skb;
-}      
-
-/*
- *     Free a datagram buffer. This has some conditions to watch. We keep
- *     a user count so the last user may free the buffer. If however the
- *     buffer has a valid next pointer it was never removed and all the
- *     users PEEKed at it - so don't free it yet.
- */
-void skb_free_datagram(struct sk_buff *skb)
-{
-       unsigned long flags;
-
-       save_flags(flags);
-       cli();
-       skb->users--;
-       if(skb->users>0)
-       {
-               restore_flags(flags);
-               return;
-       }
-       /* See if it needs destroying */
-       if(skb->list == NULL)   /* Been dequeued by someone - ie its read */
-               kfree_skb(skb,FREE_READ);
-       restore_flags(flags);
-}
-
-void skb_copy_datagram(struct sk_buff *skb, int offset, char *to, int size)
-{
-       /* We will know all about the fraglist options to allow >4K receives 
-          but not this release */
-       memcpy_tofs(to,skb->h.raw+offset,size);
-}
-
-/*
- *     Datagram select: Again totally generic. Moved from udp.c
- *     Now does seqpacket.
- */
-int datagram_select(struct sock *sk, int sel_type, select_table *wait)
-{
-       select_wait(sk->sleep, wait);
-       switch(sel_type) 
-       {
-               case SEL_IN:
-                       if (sk->type==SOCK_SEQPACKET && sk->state==TCP_CLOSE)
-                       {
-                               /* Connection closed: Wake up */
-                               return(1);
-                       }
-                       if (sk->rqueue != NULL || sk->err != 0) 
-                       {       /* This appears to be consistent
-                                  with other stacks */
-                               return(1);
-                       }
-                       return(0);
-
-               case SEL_OUT:
-                       if(sk->prot && sk->prot->wspace(sk) >= MIN_WRITE_SPACE) 
-                       {
-                               return(1);
-                       }
-                       if(sk->prot==NULL && sk->sndbuf-sk->wmem_alloc >= MIN_WRITE_SPACE)
-                       {
-                               return(1);
-                       }
-                       return(0);
-       
-               case SEL_EX:
-                       if (sk->err)
-                               return(1); /* Socket has gone into error state (eg icmp error) */
-                       return(0);
-       }
-       return(0);
-}
diff --git a/net/socket/dev.c b/net/socket/dev.c
deleted file mode 100644 (file)
index 20ce0f6..0000000
+++ /dev/null
@@ -1,980 +0,0 @@
-/*
- * INET                An implementation of the TCP/IP protocol suite for the LINUX
- *             operating system.  INET is implemented using the  BSD Socket
- *             interface as the means of communication with the user level.
- *
- *             Interface (streams) handling functions.
- *
- * Version:    @(#)dev.c       1.28    20/12/93
- *
- * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
- *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- *             Mark Evans, <evansmp@uhura.aston.ac.uk>
- * 
- * Fixes:      
- *             Alan Cox:       check_addr returns a value for a wrong subnet
- *                             ie not us but don't forward this!
- *             Alan Cox:       block timer if the inet_bh handler is running
- *             Alan Cox:       generic queue code added. A lot neater now
- *             C.E.Hawkins:    SIOCGIFCONF only reports 'upped' interfaces
- *             C.E.Hawkins:    IFF_PROMISC support
- *             Alan Cox:       Supports Donald Beckers new hardware 
- *                             multicast layer, but not yet multicast lists.
- *             Alan Cox:       ip_addr_match problems with class A/B nets.
- *             C.E.Hawkins     IP 0.0.0.0 and also same net route fix. [FIXME: Ought to cause ICMP_REDIRECT]
- *             Alan Cox:       Removed bogus subnet check now the subnet code
- *                             a) actually works for all A/B nets
- *                             b) doesn't forward off the same interface.
- *             Alan Cox:       Multiple extra protocols
- *             Alan Cox:       A Couple more escaped verify_area calls die
- *             Alan Cox:       IP_SET_DEV is gone (forever) as per Fred's comment.
- *             Alan Cox:       Grand tidy up ready for the big day.
- *             Alan Cox:       Handles dev_open errors correctly.
- *             Alan Cox:       IP part split from main section
- *
- *             This program is free software; you can redistribute it and/or
- *             modify it under the terms of the GNU General Public License
- *             as published by the Free Software Foundation; either version
- *             2 of the License, or (at your option) any later version.
- */
-
-#include <asm/segment.h>
-#include <asm/system.h>
-#include <asm/bitops.h>
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/if_ether.h>
-#include "inet.h"
-#include "dev.h"
-#include "eth.h"
-#include "ip.h"
-#include "route.h"
-#include "protocol.h"
-#include "tcp.h"
-#include "skbuff.h"
-#include "sock.h"
-#include "arp.h"
-#ifdef CONFIG_AX25
-#include "ax25/ax25.h"
-#endif
-#ifdef CONFIG_IPX
-#include "ipx/ipx.h"
-#endif
-
-
-#ifdef CONFIG_IPX
-
-/*
- *     These describe how each lowest level protocol is processed.
- */
-static struct packet_type ipx_8023_type = 
-{
-       NET16(ETH_P_802_3),
-       0,
-       ipx_rcv,
-       NULL,
-       NULL
-};
-
-static struct packet_type ipx_packet_type = 
-{
-       NET16(ETH_P_IPX),       /* IPX over DIX - eg PDIPX */
-       0,
-       ipx_rcv,
-       NULL,
-       &ipx_8023_type
-};
-
-#endif
-
-#ifdef CONFIG_AX25
-
-static struct packet_type ax25_packet_type = 
-{
-       NET16(ETH_P_AX25),
-       0,
-       ax25_rcv,
-       NULL,
-#ifdef CONFIG_IPX
-       &ipx_packet_type
-#else
-       NULL
-#endif
-};
-#endif
-
-
-static struct packet_type arp_packet_type = 
-{
-       NET16(ETH_P_ARP),
-       0,              /* copy */
-       arp_rcv,
-       NULL,
-#ifdef CONFIG_IPX
-#ifndef CONFIG_AX25
-       &ipx_packet_type
-#else
-       &ax25_packet_type
-#endif
-#else
-       NULL            /* next */
-#endif
-};
-
-
-static struct packet_type ip_packet_type = 
-{
-       NET16(ETH_P_IP),
-       0,              /* copy */
-       ip_rcv,
-       NULL,
-       &arp_packet_type
-};
-
-/*
- *     The list of known protocols. Note that
- *     SOCK_PACKET sockets dynamically alter this.
- */   
-
-#ifdef CONFIG_INET
-struct packet_type *ptype_base = &ip_packet_type;
-#else
-#ifdef CONFIG_AX25
-struct packet_type *ptype_base = &ax25_packet_type;
-#else
-struct packet_type *ptype_base = &ipx_packet_type;
-#endif
-#endif
-
-/* A queue of all the packets we have to deal with */
-static struct sk_buff *volatile backlog = NULL;
-
-
-
-/* 
- *     Return the lesser of the two values. 
- */
-
-static unsigned long
-min(unsigned long a, unsigned long b)
-{
-       if (a < b) 
-               return(a);
-       return(b);
-}
-
-
-
-
-/*
- *     Add a protocol ID to the list of known protocols
- *     (see SOCK_PACKET code)
- */
-void dev_add_pack(struct packet_type *pt)
-{
-       struct packet_type *p1;
-
-       pt->next = ptype_base;
-
-       /* See if we need to copy it. */
-       for (p1 = ptype_base; p1 != NULL; p1 = p1->next) 
-       {
-               if (p1->type == pt->type) 
-               {
-                       pt->copy = 1;
-                       break;
-               }
-       }
-       ptype_base = pt;
-}
-
-
-/*     
- *     Remove a protocol ID from the list. Also used
- *     for SOCK_PACKET. Maybe one day we will do loadable
- *     protocol layers too.
- */
-void dev_remove_pack(struct packet_type *pt)
-{
-       struct packet_type *lpt, *pt1;
-
-       if (pt == ptype_base) 
-       {
-               ptype_base = pt->next;
-               return;
-       }
-
-       lpt = NULL;
-       for (pt1 = ptype_base; pt1->next != NULL; pt1 = pt1->next) 
-       {
-               if (pt1->next == pt ) 
-               {
-                       cli();
-                       if (!pt->copy && lpt) 
-                               lpt->copy = 0;
-                       pt1->next = pt->next;
-                       sti();
-                       return;
-               }
-
-               if (pt1->next -> type == pt ->type) 
-               {
-                       lpt = pt1->next;
-               }
-       }
-}
-
-
-/*
- *     Find an interface in the list.
- */
-
-struct device *dev_get(char *name)
-{
-       struct device *dev;
-
-       for (dev = dev_base; dev != NULL; dev = dev->next) 
-       {
-               if (strcmp(dev->name, name) == 0) 
-               return(dev);
-       }
-       return(NULL);
-}
-
-
-/*
- *     Prepare an interface for use. 
- */
-
-int dev_open(struct device *dev)
-{
-       int ret = 0;
-
-       if (dev->open) 
-               ret = dev->open(dev);
-       if (ret == 0) 
-               dev->flags |= (IFF_UP | IFF_RUNNING);
-
-       return(ret);
-}
-
-
-/*
- *     Completely shutdown an interface. 
- */
-int dev_close(struct device *dev)
-{
-       if (dev->flags != 0) 
-       {
-               int ct=0;
-               dev->flags = 0;
-               if (dev->stop) 
-                       dev->stop(dev);
-               rt_flush(dev);
-               dev->pa_addr = 0;
-               dev->pa_dstaddr = 0;
-               dev->pa_brdaddr = 0;
-               dev->pa_mask = 0;
-               /* Purge any queued packets when we down the link */
-               while(ct<DEV_NUMBUFFS)
-               {
-                       struct sk_buff *skb;
-                       while((skb=skb_dequeue(&dev->buffs[ct]))!=NULL)
-                               if(skb->free)
-                                       kfree_skb(skb,FREE_WRITE);
-                       ct++;
-               }
-       }
-
-       return(0);
-}
-
-
-/*
- *     Send (or queue for sending) a packet.
- */
-void dev_queue_xmit(struct sk_buff *skb, struct device *dev, int pri)
-{
-       int where = 0;          /* used to say if the packet should go  */
-                               /* at the front or the back of the      */
-                               /* queue.                               */
-
-       DPRINTF((DBG_DEV, "dev_queue_xmit(skb=%X, dev=%X, pri = %d)\n",
-                                                       skb, dev, pri));
-
-       if (dev == NULL) 
-       {
-               printk("dev.c: dev_queue_xmit: dev = NULL\n");
-               return;
-       }
-       IS_SKB(skb);
-    
-       skb->dev = dev;
-       if (skb->next != NULL) 
-       {
-               /* Make sure we haven't missed an interrupt. */
-               dev->hard_start_xmit(NULL, dev);
-               return;
-       }
-
-       if (pri < 0) 
-       {
-               pri = -pri-1;
-               where = 1;
-       }
-
-       if (pri >= DEV_NUMBUFFS) 
-       {
-               printk("bad priority in dev_queue_xmit.\n");
-               pri = 1;
-       }
-
-       if (dev->hard_start_xmit(skb, dev) == 0) 
-       {
-               /* It went out without fuss */
-               return;
-       }
-
-       /* The driver was busy.. */
-       /* Put skb into a bidirectional circular linked list. */
-       DPRINTF((DBG_DEV, "dev_queue_xmit dev->buffs[%d]=%X\n",
-                                       pri, dev->buffs[pri]));
-
-       /* Interrupts should already be cleared by hard_start_xmit. */
-       cli();
-       skb->magic = DEV_QUEUE_MAGIC;
-       if(where)
-               skb_queue_head(&dev->buffs[pri],skb);
-       else
-               skb_queue_tail(&dev->buffs[pri],skb);
-       skb->magic = DEV_QUEUE_MAGIC;
-       sti();
-}
-
-/*
- *     Receive a packet from a device driver and queue it for the upper
- *     (protocol) levels.  It always succeeds.
- */
-
-void netif_rx(struct sk_buff *skb)
-{
-       /* Set any necessary flags. */
-       skb->sk = NULL;
-       skb->free = 1;
-  
-       /* and add it to the "backlog" queue. */
-       IS_SKB(skb);
-       skb_queue_tail(&backlog,skb);
-   
-       /* If any packet arrived, mark it for processing. */
-       if (backlog != NULL)
-               mark_bh(INET_BH);
-
-       return;
-}
-
-
-/*
- *     The old interface to fetch a packet from a device driver.
- *     This function is the base level entry point for all drivers that
- *     want to send a packet to the upper (protocol) levels.  It takes
- *     care of de-multiplexing the packet to the various modules based
- *     on their protocol ID.
- *
- *      Return values:         1 <- exit I can't do any more
- *                             0 <- feed me more (i.e. "done", "OK"). 
- *
- *     THIS FUNCTION IS OBSOLETE: DO NOT USE IT ANY MORE!!!!
- */
-int dev_rint(unsigned char *buff, long len, int flags, struct device *dev)
-{
-       static int dropping = 0;
-       struct sk_buff *skb = NULL;
-       unsigned char *to;
-       int amount, left;
-       int len2;
-
-       if (dev == NULL || buff == NULL || len <= 0)    
-               return(1);
-       if (flags & IN_SKBUFF) 
-       {
-               skb = (struct sk_buff *) buff;
-       } 
-       else 
-       {
-               if (dropping) 
-               {
-                       if (backlog != NULL)
-                               return(1);
-                       printk("INET: dev_rint: no longer dropping packets.\n");
-                       dropping = 0;
-               }
-
-               skb = alloc_skb(sizeof(*skb) + len, GFP_ATOMIC);
-               if (skb == NULL) 
-               {
-                       printk("dev_rint: packet dropped on %s (no memory) !\n",
-                              dev->name);
-                       dropping = 1;
-                       return(1);
-               }
-
-               /* First we copy the packet into a buffer, and save it for later. */
-               to = (unsigned char *) (skb + 1);
-               left = len;
-               len2 = len;
-               while (len2 > 0) 
-               {
-                       amount = min(len2, (unsigned long) dev->rmem_end -
-                                               (unsigned long) buff);
-                       memcpy(to, buff, amount);
-                       len2 -= amount;
-                       left -= amount;
-                       buff += amount;
-                       to += amount;
-                       if ((unsigned long) buff == dev->rmem_end)
-                               buff = (unsigned char *) dev->rmem_start;
-               }
-       }
-       skb->len = len;
-       skb->dev = dev;
-       skb->free = 1;
-
-       netif_rx(skb);
-       /* OK, all done. */
-       return(0);
-}
-
-
-/* 
- *     This routine causes all interfaces to try to send some data. 
- */
-
-void dev_transmit(void)
-{
-       struct device *dev;
-
-       for (dev = dev_base; dev != NULL; dev = dev->next) 
-       {
-               if (!dev->tbusy) 
-               {
-                       dev_tint(dev);
-               }
-       }
-}
-
-
-/* We need to know if we are re-entering the bottom level handler
-   for the network */
-   
-static volatile char in_bh = 0;
-
-int in_inet_bh()       /* Used by timer.c */
-{
-       return(in_bh==0?0:1);
-}
-
-/*
- * This function gets called periodically, to see if we can
- * process any data that came in from some interface.
- *
- */
-void inet_bh(void *tmp)
-{
-       struct sk_buff *skb;
-       struct packet_type *ptype;
-       unsigned short type;
-       unsigned char flag = 0;
-
-
-       /* Atomically check and mark our BUSY state. */
-       if (set_bit(1, (void*)&in_bh))
-               return;
-
-       /* Can we send anything now? */
-       dev_transmit();
-  
-       /* Any data left to process? */
-       while((skb=skb_dequeue(&backlog))!=NULL)
-       {
-               flag=0;
-               sti();
-                       /*
-                * Bump the pointer to the next structure.
-                * This assumes that the basic 'skb' pointer points to
-                * the MAC header, if any (as indicated by its "length"
-                * field).  Take care now!
-                */
-                       skb->h.raw = (unsigned char *) (skb + 1) + skb->dev->hard_header_len;
-                       skb->len -= skb->dev->hard_header_len;
-
-                       /*
-                * Fetch the packet protocol ID.  This is also quite ugly, as
-                * it depends on the protocol driver (the interface itself) to
-                * know what the type is, or where to get it from.  The Ethernet
-                * interfaces fetch the ID from the two bytes in the Ethernet MAC
-                * header (the h_proto field in struct ethhdr), but drivers like
-                * SLIP and PLIP have no alternative but to force the type to be
-                * IP or something like that.  Sigh- FvK
-                */
-               type = skb->dev->type_trans(skb, skb->dev);
-
-               /*
-                * We got a packet ID.  Now loop over the "known protocols"
-                * table (which is actually a linked list, but this will
-                * change soon if I get my way- FvK), and forward the packet
-                * to anyone who wants it.
-                */
-               for (ptype = ptype_base; ptype != NULL; ptype = ptype->next) 
-               {
-                       if (ptype->type == type) 
-                       {
-                               struct sk_buff *skb2;
-       
-                               if (ptype->copy) 
-                               {       /* copy if we need to   */
-                                       skb2 = alloc_skb(skb->mem_len, GFP_ATOMIC);
-                                       if (skb2 == NULL) 
-                                               continue;
-                                       memcpy(skb2, (const void *) skb, skb->mem_len);
-                                       skb2->mem_addr=skb2;
-                                       skb2->h.raw = (unsigned char *)
-                                       (
-                                           (unsigned long) skb2 +
-                                           (unsigned long) skb->h.raw -
-                                           (unsigned long) skb
-                                       );
-                                       skb2->free = 1;
-                               } 
-                               else 
-                               {
-                                       skb2 = skb;
-                               }
-
-                               /* This used to be in the 'else' part, but then
-                                * we don't have this flag set when we get a
-                                * protocol that *does* require copying... -FvK
-                                */
-                               flag = 1;
-
-                               /* Kick the protocol handler. */
-                               ptype->func(skb2, skb->dev, ptype);
-                       }
-               }
-
-               /*
-                * That's odd.  We got an unknown packet.  Who's using
-                * stuff like Novell or Amoeba on this network??
-                */
-               if (!flag) 
-               {
-                       DPRINTF((DBG_DEV,
-                               "INET: unknown packet type 0x%04X (ignored)\n", type));
-                       skb->sk = NULL;
-                       kfree_skb(skb, FREE_WRITE);
-               }
-
-               /* Again, see if we can transmit anything now. */
-               dev_transmit();
-               cli();
-       }
-       in_bh = 0;
-       sti();
-       dev_transmit(); /* Try and kick anything this processing produced */
-}
-
-
-/*
- *     This routine is called when an device driver (i.e. an
- *     interface) is * ready to transmit a packet.
- */
-void dev_tint(struct device *dev)
-{
-       int i;
-       struct sk_buff *skb;
-       
-       for(i = 0;i < DEV_NUMBUFFS; i++) 
-       {
-               while((skb=skb_dequeue(&dev->buffs[i]))!=NULL)
-               {
-                       skb->magic = 0;
-                       dev->queue_xmit(skb,dev,-i - 1);
-                       if (dev->tbusy)
-                               return;
-               }
-       }
-}
-
-
-/* 
- *     Perform a SIOCGIFCONF call. 
- */
-
-static int dev_ifconf(char *arg)
-{
-       struct ifconf ifc;
-       struct ifreq ifr;
-       struct device *dev;
-       char *pos;
-       int len;
-       int err;
-
-       /* Fetch the caller's info block. */
-       err=verify_area(VERIFY_WRITE, arg, sizeof(struct ifconf));
-       if(err)
-               return -err;
-       memcpy_fromfs(&ifc, arg, sizeof(struct ifconf));
-       len = ifc.ifc_len;
-       pos = ifc.ifc_buf;
-
-       /* Loop over the interfaces, and write an info block for each. */
-       for (dev = dev_base; dev != NULL; dev = dev->next) 
-       {
-               if(!(dev->flags & IFF_UP))
-                       continue;
-               memset(&ifr, 0, sizeof(struct ifreq));
-               strcpy(ifr.ifr_name, dev->name);
-               (*(struct sockaddr_in *) &ifr.ifr_addr).sin_family = dev->family;
-               (*(struct sockaddr_in *) &ifr.ifr_addr).sin_addr.s_addr = dev->pa_addr;
-       
-               /* Write this block to the caller's space. */
-               memcpy_tofs(pos, &ifr, sizeof(struct ifreq));
-               pos += sizeof(struct ifreq);
-               len -= sizeof(struct ifreq);
-               if (len < sizeof(struct ifreq)) break;
-       }
-
-       /* All done.  Write the updated control block back to the caller. */
-       ifc.ifc_len = (pos - ifc.ifc_buf);
-       ifc.ifc_req = (struct ifreq *) ifc.ifc_buf;
-       memcpy_tofs(arg, &ifc, sizeof(struct ifconf));
-       return(pos - arg);
-}
-
-/* 
- *     Print device statistics. 
- */
-char *sprintf_stats(char *buffer, struct device *dev)
-{
-       char *pos = buffer;
-       struct enet_statistics *stats = (dev->get_stats ? dev->get_stats(dev): NULL);
-
-       if (stats)
-               pos += sprintf(pos, "%6s:%7d %4d %4d %4d %4d %8d %4d %4d %4d %5d %4d\n",
-                  dev->name,
-                  stats->rx_packets, stats->rx_errors,
-                  stats->rx_dropped + stats->rx_missed_errors,
-                  stats->rx_fifo_errors,
-                  stats->rx_length_errors + stats->rx_over_errors
-                  + stats->rx_crc_errors + stats->rx_frame_errors,
-                  stats->tx_packets, stats->tx_errors, stats->tx_dropped,
-                  stats->tx_fifo_errors, stats->collisions,
-                  stats->tx_carrier_errors + stats->tx_aborted_errors
-                  + stats->tx_window_errors + stats->tx_heartbeat_errors);
-       else
-               pos += sprintf(pos, "%6s: No statistics available.\n", dev->name);
-
-       return pos;
-}
-
-/*
- *     Called from the PROCfs module (/proc/net/dev).
- */
-int dev_get_info(char *buffer)
-{
-       char *pos = buffer;
-       struct device *dev;
-
-       pos +=
-       sprintf(pos,
-             "Inter-|   Receive                  |  Transmit\n"
-             " face |packets errs drop fifo frame|packets errs drop fifo colls carrier\n");
-       for (dev = dev_base; dev != NULL; dev = dev->next) 
-       {
-               pos = sprintf_stats(pos, dev);
-       }
-       return pos - buffer;
-}
-
-/*
- *     Perform the SIOCxIFxxx calls. 
- */
-static int dev_ifsioc(void *arg, unsigned int getset)
-{
-       struct ifreq ifr;
-       struct device *dev;
-       int ret;
-       int err;
-
-       /* Fetch the caller's info block. */
-       err=verify_area(VERIFY_WRITE, arg, sizeof(struct ifreq));
-       if(err)
-               return -err;
-       memcpy_fromfs(&ifr, arg, sizeof(struct ifreq));
-
-       /* See which interface the caller is talking about. */
-       if ((dev = dev_get(ifr.ifr_name)) == NULL) 
-               return(-EINVAL);
-
-       switch(getset) 
-       {
-               case SIOCGIFFLAGS:
-                       ifr.ifr_flags = dev->flags;
-                       memcpy_tofs(arg, &ifr, sizeof(struct ifreq));
-                       ret = 0;
-                       break;
-               case SIOCSIFFLAGS:
-                       {
-                               int old_flags = dev->flags;
-                               dev->flags = ifr.ifr_flags & (
-                                       IFF_UP | IFF_BROADCAST | IFF_DEBUG | IFF_LOOPBACK |
-                                       IFF_POINTOPOINT | IFF_NOTRAILERS | IFF_RUNNING |
-                                       IFF_NOARP | IFF_PROMISC | IFF_ALLMULTI);
-                               
-                               if ( (old_flags & IFF_PROMISC) && ((dev->flags & IFF_PROMISC) == 0))
-                                       dev->set_multicast_list(dev,0,NULL);
-                               if ( (dev->flags & IFF_PROMISC) && ((old_flags & IFF_PROMISC) == 0))
-                                       dev->set_multicast_list(dev,-1,NULL);
-                               if ((old_flags & IFF_UP) && ((dev->flags & IFF_UP) == 0)) 
-                               {
-                                       ret = dev_close(dev);
-                               } 
-                               else
-                               {
-                                       ret = (! (old_flags & IFF_UP) && (dev->flags & IFF_UP))
-                                               ? dev_open(dev) : 0;
-                                       if(ret!=0)
-                                               dev->flags&=~IFF_UP;    /* Failed to come up so go down again */
-                               }
-                       }
-                       break;
-               case SIOCGIFADDR:
-                       (*(struct sockaddr_in *)
-                         &ifr.ifr_addr).sin_addr.s_addr = dev->pa_addr;
-                       (*(struct sockaddr_in *)
-                         &ifr.ifr_addr).sin_family = dev->family;
-                       (*(struct sockaddr_in *)
-                         &ifr.ifr_addr).sin_port = 0;
-                       memcpy_tofs(arg, &ifr, sizeof(struct ifreq));
-                       ret = 0;
-                       break;
-               case SIOCSIFADDR:
-                       dev->pa_addr = (*(struct sockaddr_in *)
-                                        &ifr.ifr_addr).sin_addr.s_addr;
-                       dev->family = ifr.ifr_addr.sa_family;
-                       dev->pa_mask = ip_get_mask(dev->pa_addr);
-                       dev->pa_brdaddr = dev->pa_addr | ~dev->pa_mask;
-                       ret = 0;
-                       break;
-               case SIOCGIFBRDADDR:
-                       (*(struct sockaddr_in *)
-                         &ifr.ifr_broadaddr).sin_addr.s_addr = dev->pa_brdaddr;
-                       (*(struct sockaddr_in *)
-                         &ifr.ifr_broadaddr).sin_family = dev->family;
-                       (*(struct sockaddr_in *)
-                         &ifr.ifr_broadaddr).sin_port = 0;
-                       memcpy_tofs(arg, &ifr, sizeof(struct ifreq));
-                       ret = 0;
-                       break;
-               case SIOCSIFBRDADDR:
-                       dev->pa_brdaddr = (*(struct sockaddr_in *)
-                                           &ifr.ifr_broadaddr).sin_addr.s_addr;
-                       ret = 0;
-                       break;
-               case SIOCGIFDSTADDR:
-                       (*(struct sockaddr_in *)
-                         &ifr.ifr_dstaddr).sin_addr.s_addr = dev->pa_dstaddr;
-                       (*(struct sockaddr_in *)
-                                 &ifr.ifr_broadaddr).sin_family = dev->family;
-                       (*(struct sockaddr_in *)
-                                 &ifr.ifr_broadaddr).sin_port = 0;
-                       memcpy_tofs(arg, &ifr, sizeof(struct ifreq));
-                       ret = 0;
-                       break;
-               case SIOCSIFDSTADDR:
-                       dev->pa_dstaddr = (*(struct sockaddr_in *)
-                                           &ifr.ifr_dstaddr).sin_addr.s_addr;
-                       ret = 0;
-                       break;
-               case SIOCGIFNETMASK:
-                       (*(struct sockaddr_in *)
-                         &ifr.ifr_netmask).sin_addr.s_addr = dev->pa_mask;
-                       (*(struct sockaddr_in *)
-                         &ifr.ifr_netmask).sin_family = dev->family;
-                       (*(struct sockaddr_in *)
-                         &ifr.ifr_netmask).sin_port = 0;
-                       memcpy_tofs(arg, &ifr, sizeof(struct ifreq));
-                       ret = 0;
-                       break;
-               case SIOCSIFNETMASK:
-                       dev->pa_mask = (*(struct sockaddr_in *)
-                                &ifr.ifr_netmask).sin_addr.s_addr;
-                       ret = 0;
-                       break;
-               case SIOCGIFMETRIC:
-                       ifr.ifr_metric = dev->metric;
-                       memcpy_tofs(arg, &ifr, sizeof(struct ifreq));
-                       ret = 0;
-                       break;
-               case SIOCSIFMETRIC:
-                       dev->metric = ifr.ifr_metric;
-                       ret = 0;
-                       break;
-               case SIOCGIFMTU:
-                       ifr.ifr_mtu = dev->mtu;
-                       memcpy_tofs(arg, &ifr, sizeof(struct ifreq));
-                       ret = 0;
-                       break;
-               case SIOCSIFMTU:
-                       dev->mtu = ifr.ifr_mtu;
-                       ret = 0;
-                       break;
-               case SIOCGIFMEM:
-                       printk("NET: ioctl(SIOCGIFMEM, 0x%08X)\n", (int)arg);
-                       ret = -EINVAL;
-                       break;
-               case SIOCSIFMEM:
-                       printk("NET: ioctl(SIOCSIFMEM, 0x%08X)\n", (int)arg);
-                       ret = -EINVAL;
-                       break;
-               case SIOCGIFHWADDR:
-                       memcpy(ifr.ifr_hwaddr,dev->dev_addr, MAX_ADDR_LEN);
-                       memcpy_tofs(arg,&ifr,sizeof(struct ifreq));
-                       ret=0;
-                       break;
-               default:
-                       ret = -EINVAL;
-       }       
-       return(ret);
-}
-
-
-/*
- *     This function handles all "interface"-type I/O control requests. 
- */
-int dev_ioctl(unsigned int cmd, void *arg)
-{
-       int ret;
-
-       switch(cmd) 
-       {
-               case IP_SET_DEV:
-                       printk("IP_SET_DEV is obsolete. You need newer network tools.\n");
-                       ret= -EINVAL;
-               case SIOCGIFCONF:
-                       (void) dev_ifconf((char *) arg);
-                       ret = 0;
-                       break;
-               case SIOCGIFFLAGS:
-               case SIOCSIFFLAGS:
-               case SIOCGIFADDR:
-               case SIOCSIFADDR:
-               case SIOCGIFDSTADDR:
-               case SIOCSIFDSTADDR:
-               case SIOCGIFBRDADDR:
-               case SIOCSIFBRDADDR:
-               case SIOCGIFNETMASK:
-               case SIOCSIFNETMASK:
-               case SIOCGIFMETRIC:
-               case SIOCSIFMETRIC:
-               case SIOCGIFMTU:
-               case SIOCSIFMTU:
-               case SIOCGIFMEM:
-               case SIOCSIFMEM:
-               case SIOCGIFHWADDR:
-                       if (!suser()) 
-                               return(-EPERM);
-                       ret = dev_ifsioc(arg, cmd);
-                       break;
-               case SIOCSIFLINK:
-                       if (!suser()) 
-                               return(-EPERM);
-               default:
-                       ret = -EINVAL;
-        }
-
-       return(ret);
-}
-
-/*
- *     Setup an ethernet type interface
- */
-void eth_setup(char *str, int *ints)
-{
-       struct device *d = dev_base;
-
-       if (!str || !*str)
-               return;
-               
-       /* Walk the device list */
-       while (d) 
-       {
-               if (!strcmp(str,d->name)) 
-               {
-                       if (ints[0] > 0)
-                               d->irq=ints[1];
-                       if (ints[0] > 1)
-                               d->base_addr=ints[2];
-                       if (ints[0] > 2)
-                               d->mem_start=ints[3];
-                       if (ints[0] > 3)
-                               d->mem_end=ints[4];
-                       break;
-               }
-               d=d->next;
-       }
-}
-
-
-/* 
- *     Initialize the DEV module. 
- */
-void dev_init(void)
-{
-       struct device *dev, *dev2;
-
-       /* Add the devices.
-        * If the call to dev->init fails, the dev is removed
-        * from the chain disconnecting the device until the
-        * next reboot.
-        */
-       dev2 = NULL;
-       for (dev = dev_base; dev != NULL; dev=dev->next) 
-       {
-               if (dev->init && dev->init(dev)) 
-               {
-                       if (dev2 == NULL) 
-                               dev_base = dev->next;
-                       else 
-                               dev2->next = dev->next;
-               } 
-               else 
-               {
-                       dev2 = dev;
-               }
-       }
-
-}
-
diff --git a/net/socket/dev.h b/net/socket/dev.h
deleted file mode 100644 (file)
index 4cb829b..0000000
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * INET                An implementation of the TCP/IP protocol suite for the LINUX
- *             operating system.  INET is implemented using the  BSD Socket
- *             interface as the means of communication with the user level.
- *
- *             Definitions for the Interfaces handler.
- *
- * Version:    @(#)dev.h       1.0.10  08/12/93
- *
- * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
- *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- *             Corey Minyard <wf-rch!minyard@relay.EU.net>
- *             Donald J. Becker, <becker@super.org>
- *
- *             This program is free software; you can redistribute it and/or
- *             modify it under the terms of the GNU General Public License
- *             as published by the Free Software Foundation; either version
- *             2 of the License, or (at your option) any later version.
- */
-#ifndef _DEV_H
-#define _DEV_H
-
-#include <linux/if.h>
-#include <linux/if_ether.h>
-
-
-/* for future expansion when we will have different priorities. */
-#define DEV_NUMBUFFS   3
-#define MAX_ADDR_LEN   7
-#define MAX_HEADER     18
-
-#define IS_MYADDR      1               /* address is (one of) our own  */
-#define IS_LOOPBACK    2               /* address is for LOOPBACK      */
-#define IS_BROADCAST   3               /* address is a valid broadcast */
-#define IS_INVBCAST    4               /* Wrong netmask bcast not for us */
-
-/*
- * The DEVICE structure.
- * Actually, this whole structure is a big mistake.  It mixes I/O
- * data with strictly "high-level" data, and it has to know about
- * almost every data structure used in the INET module.  We will
- * gradually phase out this structure, and replace it with the
- * more general (but stolen :-) BSD "ifnet" structure. -FvK
- */
-struct device {
-
-  /*
-   * This is the first field of the "visible" part of this structure
-   * (i.e. as seen by users in the "Space.c" file).  It is the name
-   * the interface.
-   */
-  char                   *name;
-
-  /* I/O specific fields.  These will be moved to DDI soon. */
-  unsigned long                  rmem_end;             /* shmem "recv" end     */
-  unsigned long                  rmem_start;           /* shmem "recv" start   */
-  unsigned long                  mem_end;              /* sahared mem end      */
-  unsigned long                  mem_start;            /* shared mem start     */
-  unsigned short         base_addr;            /* device I/O address   */
-  unsigned char                  irq;                  /* device IRQ number    */
-
-  /* Low-level status flags. */
-  volatile unsigned char  start,               /* start an operation   */
-                          tbusy,               /* transmitter busy     */
-                          interrupt;           /* interrupt arrived    */
-
-  /*
-   * Another mistake.
-   * This points to the next device in the "dev" chain. It will
-   * be moved to the "invisible" part of the structure as soon as
-   * it has been cleaned up. -FvK
-   */
-  struct device                  *next;
-
-  /* The device initialization function. Called only once. */
-  int                    (*init)(struct device *dev);
-
-  /* Some hardware also needs these fields, but they are not part of the
-     usual set specified in Space.c. */
-  unsigned char                  if_port;              /* Selectable AUI, TP,..*/
-  unsigned char                  dma;                  /* DMA channel          */
-
-  struct enet_statistics* (*get_stats)(struct device *dev);
-
-  /*
-   * This marks the end of the "visible" part of the structure. All
-   * fields hereafter are internal to the system, and may change at
-   * will (read: may be cleaned up at will).
-   */
-
-  /* These may be needed for future network-power-down code. */
-  unsigned long                  trans_start;  /* Time (in jiffies) of last Tx */
-  unsigned long                  last_rx;      /* Time of last Rx              */
-
-  unsigned short         flags;        /* interface flags (a la BSD)   */
-  unsigned short         family;       /* address family ID (AF_INET)  */
-  unsigned short         metric;       /* routing metric (not used)    */
-  unsigned short         mtu;          /* interface MTU value          */
-  unsigned short         type;         /* interface hardware type      */
-  unsigned short         hard_header_len;      /* hardware hdr length  */
-  void                   *priv;        /* pointer to private data      */
-
-  /* Interface address info. */
-  unsigned char                  broadcast[MAX_ADDR_LEN];      /* hw bcast add */
-  unsigned char                  dev_addr[MAX_ADDR_LEN];       /* hw address   */
-  unsigned char                  addr_len;     /* harfware address length      */
-  unsigned long                  pa_addr;      /* protocol address             */
-  unsigned long                  pa_brdaddr;   /* protocol broadcast addr      */
-  unsigned long                  pa_dstaddr;   /* protocol P-P other side addr */
-  unsigned long                  pa_mask;      /* protocol netmask             */
-  unsigned short         pa_alen;      /* protocol address length      */
-
-  /* Pointer to the interface buffers. */
-  struct sk_buff         *volatile buffs[DEV_NUMBUFFS];
-
-  /* Pointers to interface service routines. */
-  int                    (*open)(struct device *dev);
-  int                    (*stop)(struct device *dev);
-  int                    (*hard_start_xmit) (struct sk_buff *skb,
-                                             struct device *dev);
-  int                    (*hard_header) (unsigned char *buff,
-                                         struct device *dev,
-                                         unsigned short type,
-                                         unsigned long daddr,
-                                         unsigned long saddr,
-                                         unsigned len);
-  void                   (*add_arp) (unsigned long addr,
-                                     struct sk_buff *skb,
-                                     struct device *dev);
-  void                   (*queue_xmit)(struct sk_buff *skb,
-                                       struct device *dev, int pri);
-  int                    (*rebuild_header)(void *eth, struct device *dev);
-  unsigned short         (*type_trans) (struct sk_buff *skb,
-                                        struct device *dev);
-#define HAVE_MULTICAST                  
-  void                   (*set_multicast_list)(struct device *dev,
-                                        int num_addrs, void *addrs);
-#define HAVE_SET_MAC_ADDR               
-  int                    (*set_mac_address)(struct device *dev, void *addr);
-};
-
-
-struct packet_type {
-  unsigned short       type;   /* This is really NET16(ether_type) other
-                                * devices will have to translate
-                                * appropriately.
-                                */
-  unsigned short       copy:1;
-  int                  (*func) (struct sk_buff *, struct device *,
-                                struct packet_type *);
-  void                 *data;
-  struct packet_type   *next;
-};
-
-
-/* Used by dev_rint */
-#define IN_SKBUFF      1
-#define DEV_QUEUE_MAGIC        0x17432895
-
-
-extern struct device   *dev_base;
-extern struct packet_type *ptype_base;
-
-
-extern unsigned long   ip_get_mask(unsigned long);
-extern void            dev_add_pack(struct packet_type *pt);
-extern void            dev_remove_pack(struct packet_type *pt);
-extern struct device   *dev_get(char *name);
-extern int             dev_open(struct device *dev);
-extern int             dev_close(struct device *dev);
-extern void            dev_queue_xmit(struct sk_buff *skb, struct device *dev,
-                                      int pri);
-#define HAVE_NETIF_RX 1
-extern void            netif_rx(struct sk_buff *skb);
-/* The old interface to netif_rx(). */
-extern int             dev_rint(unsigned char *buff, long len, int flags,
-                                struct device * dev);
-extern void            dev_transmit(void);
-extern int             in_inet_bh(void);
-extern void            inet_bh(void *tmp);
-extern void            dev_tint(struct device *dev);
-extern int             dev_get_info(char *buffer);
-extern int             dev_ioctl(unsigned int cmd, void *);
-
-extern void            dev_init(void);
-
-#endif /* _DEV_H */
diff --git a/net/socket/skbuff.c b/net/socket/skbuff.c
deleted file mode 100644 (file)
index 1b9ab93..0000000
+++ /dev/null
@@ -1,461 +0,0 @@
-/*
- * INET                An implementation of the TCP/IP protocol suite for the LINUX
- *             operating system.  INET is implemented using the  BSD Socket
- *             interface as the means of communication with the user level.
- *
- *             A saner implementation of the skbuff stuff scattered everywhere
- *             in the old NET2D code.
- *
- *     Authors:        Alan Cox <iiitac@pyr.swan.ac.uk>
- *
- *     Fixes:
- *             Alan Cox        :       Tracks memory and number of buffers for kernel memory report
- *                                     and memory leak hunting.
- *             Alan Cox        :       More generic kfree handler
- */
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <asm/segment.h>
-#include <asm/system.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/in.h>
-#include "inet.h"
-#include "dev.h"
-#include "ip.h"
-#include "protocol.h"
-#include "arp.h"
-#include "route.h"
-#include "tcp.h"
-#include "udp.h"
-#include "skbuff.h"
-#include "sock.h"
-
-
-/* Socket buffer operations. Ideally much of this list swap stuff ought to be using
-   exch instructions on the 386, and CAS/CAS2 on a 68K. This is the boring generic
-   slow C version. No doubt when Linus sees this comment he'll do horrible things
-   to this code 8-)
-*/
-
-/*
- *     Resource tracking variables
- */
-volatile unsigned long net_memory=0;
-volatile unsigned long net_skbcount=0;
-
-/*
- *     Debugging paranoia. Can go later when this crud stack works
- */ 
-
-
-void skb_check(struct sk_buff *skb, int line, char *file)
-{
-       if(skb->magic_debug_cookie==SK_FREED_SKB)
-       {
-               printk("File: %s Line %d, found a freed skb lurking in the undergrowth!\n",
-                       file,line);
-               printk("skb=%p, real size=%ld, claimed size=%ld, magic=%d, list=%p, free=%d\n",
-                       skb,skb->truesize,skb->mem_len,skb->magic,skb->list,skb->free);
-       }
-       if(skb->magic_debug_cookie!=SK_GOOD_SKB)
-       {
-               printk("File: %s Line %d, passed a non skb!\n", file,line);
-               printk("skb=%p, real size=%ld, claimed size=%ld, magic=%d, list=%p, free=%d\n",
-                       skb,skb->truesize,skb->mem_len,skb->magic,skb->list,skb->free);
-       }
-       if(skb->mem_len!=skb->truesize)
-       {
-               printk("File: %s Line %d, Dubious size setting!\n",file,line);
-               printk("skb=%p, real size=%ld, claimed size=%ld, magic=%d, list=%p\n",
-                       skb,skb->truesize,skb->mem_len,skb->magic,skb->list);
-       }
-       /* Guess it might be acceptable then */
-}
-
-/*
- *     Insert an sk_buff at the start of a list.
- */
-    
-void skb_queue_head(struct sk_buff *volatile* list,struct sk_buff *newsk)
-{
-       unsigned long flags;
-       
-       IS_SKB(newsk);  
-       if(newsk->list)
-               printk("Suspicious queue head: sk_buff on list!\n");
-       save_flags(flags);
-       cli();
-       newsk->list=list;
-       
-       newsk->next=*list;
-       
-       if(*list)
-               newsk->prev=(*list)->prev;
-       else
-               newsk->prev=newsk;
-       newsk->prev->next=newsk;
-       newsk->next->prev=newsk;
-       IS_SKB(newsk->prev);
-       IS_SKB(newsk->next);
-       *list=newsk;
-       restore_flags(flags);
-}
-
-/*
- *     Insert an sk_buff at the end of a list.
- */
-void skb_queue_tail(struct sk_buff *volatile* list, struct sk_buff *newsk)
-{
-       unsigned long flags;
-       
-       if(newsk->list)
-               printk("Suspicious queue tail: sk_buff on list!\n");
-       
-       IS_SKB(newsk);
-       save_flags(flags);
-       cli();
-
-       newsk->list=list;
-       if(*list)
-       {
-               (*list)->prev->next=newsk;
-               newsk->prev=(*list)->prev;
-               newsk->next=*list;
-               (*list)->prev=newsk;
-       }
-       else
-       {
-               newsk->next=newsk;
-               newsk->prev=newsk;
-               *list=newsk;
-       }
-       IS_SKB(newsk->prev);
-       IS_SKB(newsk->next);            
-       restore_flags(flags);
-
-}
-
-/*
- *     Remove an sk_buff from a list. This routine is also interrupt safe
- *     so you can grab read and free buffers as another process adds them.
- */
-struct sk_buff *skb_dequeue(struct sk_buff *volatile* list)
-{
-       long flags;
-       struct sk_buff *result;
-       
-       save_flags(flags);
-       cli();
-       
-       if(*list==NULL)
-       {
-               restore_flags(flags);
-               return(NULL);
-       }
-       
-       result=*list;
-       if(result->next==result)
-               *list=NULL;
-       else
-       {
-               result->next->prev=result->prev;
-               result->prev->next=result->next;
-               *list=result->next;
-       }
-
-       IS_SKB(result);
-       restore_flags(flags);
-       
-       if(result->list!=list)
-               printk("Dequeued packet has invalid list pointer\n");
-
-       result->list=0;
-       result->next=0;
-       result->prev=0;
-       return(result);
-}
-
-/*
- *     Insert a packet before another one in a list.
- */
-void skb_insert(struct sk_buff *old, struct sk_buff *newsk)
-{
-       unsigned long flags;
-
-       IS_SKB(old);
-       IS_SKB(newsk);
-               
-       if(!old->list)
-               printk("insert before unlisted item!\n");
-       if(newsk->list)
-               printk("inserted item is already on a list.\n");
-               
-       save_flags(flags);
-       cli();
-       newsk->list=old->list;
-       newsk->next=old;
-       newsk->prev=old->prev;
-       newsk->next->prev=newsk;
-       newsk->prev->next=newsk;
-       
-       restore_flags(flags);
-}
-
-/*
- *     Place a packet after a given packet in a list.
- */
-void skb_append(struct sk_buff *old, struct sk_buff *newsk)
-{
-       unsigned long flags;
-       
-       IS_SKB(old);
-       IS_SKB(newsk);
-
-       if(!old->list)
-               printk("append before unlisted item!\n");
-       if(newsk->list)
-               printk("append item is already on a list.\n");
-               
-       save_flags(flags);
-       cli();
-       newsk->list=old->list;
-       newsk->prev=old;
-       newsk->next=old->next;
-       newsk->next->prev=newsk;
-       newsk->prev->next=newsk;
-       
-       restore_flags(flags);
-}
-
-/*
- *     Remove an sk_buff from its list. Works even without knowing the list it
- *     is sitting on, which can be handy at times. It also means that THE LIST
- *     MUST EXIST when you unlink. Thus a list must have its contents unlinked
- *     _FIRST_.
- */
-void skb_unlink(struct sk_buff *skb)
-{
-       unsigned long flags;
-       save_flags(flags);
-       cli();
-
-       IS_SKB(skb);
-       
-       if(skb->list)
-       {
-               skb->next->prev=skb->prev;
-               skb->prev->next=skb->next;
-               if(*skb->list==skb)
-               {
-                       if(skb->next==skb)
-                               *skb->list=NULL;
-                       else
-                               *skb->list=skb->next;
-               }
-               skb->next=0;
-               skb->prev=0;
-               skb->list=0;
-       }
-       restore_flags(flags);
-}
-
-/*
- *     An skbuff list has had its head reassigned. Move all the list
- *     pointers. Must be called with ints off during the whole head
- *     shifting
- */
-
-void skb_new_list_head(struct sk_buff *volatile* list)
-{
-       struct sk_buff *skb=skb_peek(list);
-       if(skb!=NULL)
-       {
-               do
-               {
-                       IS_SKB(skb);
-                       skb->list=list;
-                       skb=skb->next;
-               }
-               while(skb!=*list);
-       }
-}
-                       
-/*
- *     Peek an sk_buff. Unlike most other operations you _MUST_
- *     be careful with this one. A peek leaves the buffer on the
- *     list and someone else may run off with it. For an interrupt
- *     type system cli() peek the buffer copy the data and sti();
- */
-
-struct sk_buff *skb_peek(struct sk_buff *volatile* list)
-{
-       return *list;
-}
-
-
-#ifdef UNUSED_NOW
-
-/*
- *     Get a clone of an sk_buff. This is the safe way to peek at
- *     a socket queue without accidents. Its a bit long but most
- *     of it acutally ends up as tiny bits of inline assembler
- *     anyway. Only the memcpy of upto 4K with ints off is not
- *     as nice as I'd like.
- */
-struct sk_buff *skb_peek_copy(struct sk_buff *volatile* list)
-{
-       struct sk_buff *orig,*newsk;
-       unsigned long flags;
-       unsigned int len;
-       /* Now for some games to avoid races */
-       
-       do
-       {
-               save_flags(flags);
-               cli();
-               orig=skb_peek(list);
-               if(orig==NULL)
-               {
-                       restore_flags(flags);
-                       return NULL;
-               }
-               IS_SKB(orig);
-               len=orig->truesize;
-               restore_flags(flags);
-
-               newsk=alloc_skb(len,GFP_KERNEL);        /* May sleep */
-
-               if(newsk==NULL)         /* Oh dear... not to worry */
-                       return NULL;
-       
-               save_flags(flags);
-               cli();
-               if(skb_peek(list)!=orig)        /* List changed go around another time */
-               {
-                       restore_flags(flags);
-                       newsk->sk=NULL;
-                       newsk->free=1;
-                       newsk->mem_addr=newsk;
-                       newsk->mem_len=len;
-                       kfree_skb(newsk, FREE_WRITE);
-                       continue;
-               }
-               
-               IS_SKB(orig);
-               IS_SKB(newsk);
-               memcpy(newsk,orig,len);
-               newsk->list=NULL;
-               newsk->magic=0;
-               newsk->next=NULL;
-               newsk->prev=NULL;
-               newsk->mem_addr=newsk;
-               newsk->h.raw+=((char *)newsk-(char *)orig);
-               newsk->link3=NULL;
-               newsk->sk=NULL;
-               newsk->free=1;
-       }
-       while(0);
-       
-       restore_flags(flags);
-       return(newsk);
-}      
-
-#endif
-       
-/*
- *     Free an sk_buff. This still knows about things it should
- *     not need to like protocols and sockets.
- */
-
-void kfree_skb(struct sk_buff *skb, int rw)
-{
-       if (skb == NULL) {
-               printk("kfree_skb: skb = NULL\n");
-               return;
-       }
-       IS_SKB(skb);
-       if(skb->free == 2)
-               printk("Warning: kfree_skb passed an skb that nobody set the free flag on!\n");
-       if(skb->list)
-               printk("Warning: kfree_skb passed an skb still on a list.\n");
-       skb->magic = 0;
-       if (skb->sk) 
-       {
-             if(skb->sk->prot!=NULL)
-             {
-                       if (rw)
-                               skb->sk->prot->rfree(skb->sk, skb->mem_addr, skb->mem_len);
-                       else
-                               skb->sk->prot->wfree(skb->sk, skb->mem_addr, skb->mem_len);
-       
-               }
-               else
-               {
-                       /* Non INET - default wmalloc/rmalloc handler */
-                               if (rw)
-                                       skb->sk->rmem_alloc-=skb->mem_len;
-                               else
-                                       skb->sk->wmem_alloc-=skb->mem_len;
-                               if(!skb->sk->dead)
-                                       skb->sk->write_space(skb->sk);
-                               kfree_skbmem(skb->mem_addr,skb->mem_len);
-               }
-       } 
-       else 
-       {
-               kfree_skbmem(skb->mem_addr, skb->mem_len);
-       }
-}
-
-/*
- *     Allocate a new skbuff. We do this ourselves so we can fill in a few 'private'
- *     fields and also do memory statistics to find all the [BEEP] leaks.
- */
- struct sk_buff *alloc_skb(unsigned int size,int priority)
- {
-       struct sk_buff *skb=(struct sk_buff *)kmalloc(size,priority);
-       if(skb==NULL)
-               return NULL;
-       skb->free= 2;   /* Invalid so we pick up forgetful users */
-       skb->list= 0;   /* Not on a list */
-       skb->truesize=size;
-       skb->mem_len=size;
-       skb->mem_addr=skb;
-       skb->fraglist=NULL;
-       net_memory+=size;
-       net_skbcount++;
-       skb->magic_debug_cookie=SK_GOOD_SKB;
-       skb->users=0;
-       return skb;
- }
-
-/*
- *     Free an skbuff by memory
- */    
-
-void kfree_skbmem(void *mem,unsigned size)
-{
-       struct sk_buff *x=mem;
-       IS_SKB(x);
-       if(x->magic_debug_cookie==SK_GOOD_SKB)
-       {
-               x->magic_debug_cookie=SK_FREED_SKB;
-               kfree_s(mem,size);
-               net_skbcount--;
-               net_memory-=size;
-       }
-}
diff --git a/net/socket/skbuff.h b/net/socket/skbuff.h
deleted file mode 100644 (file)
index ef04197..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * INET                An implementation of the TCP/IP protocol suite for the LINUX
- *             operating system.  INET is implemented using the  BSD Socket
- *             interface as the means of communication with the user level.
- *
- *             Definitions for the 'struct sk_buff' memory handlers.
- *
- * Version:    @(#)skbuff.h    1.0.4   05/20/93
- *
- * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
- *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- *             Corey Minyard <wf-rch!minyard@relay.EU.net>
- *
- * Fixes:
- *             Alan Cox                :       Volatiles (this makes me unhappy - we want proper asm linked list stuff)
- *             Alan Cox                :       Declaration for new primitives
- *             Alan Cox                :       Fraglist support (idea by Donald Becker)
- *             Alan Cox                :       'users' counter. Combines with datagram changes to avoid skb_peek_copy
- *                                             being used.
- *             Alan Cox                :       Extra fields for RAW fixes
- *
- *             This program is free software; you can redistribute it and/or
- *             modify it under the terms of the GNU General Public License
- *             as published by the Free Software Foundation; either version
- *             2 of the License, or (at your option) any later version.
- */
-#ifndef _SKBUFF_H
-#define _SKBUFF_H
-#include <linux/malloc.h>
-
-#ifdef CONFIG_IPX
-#include "ipx/ipx.h"
-#endif
-
-#define HAVE_ALLOC_SKB         /* For the drivers to know */
-
-
-#define FREE_READ      1
-#define FREE_WRITE     0
-
-
-struct sk_buff 
-{
-       unsigned long           magic_debug_cookie;
-       struct sk_buff          *volatile next;
-       struct sk_buff          *volatile prev;
-       struct sk_buff          *volatile link3;
-       struct sk_buff          *volatile* list;
-       struct sock             *sk;
-       volatile unsigned long  when;   /* used to compute rtt's        */
-       struct device           *dev;
-       void                    *mem_addr;
-       union 
-       {
-               struct tcphdr   *th;
-               struct ethhdr   *eth;
-               struct iphdr    *iph;
-               struct udphdr   *uh;
-               struct arphdr   *arp;
-               unsigned char   *raw;
-               unsigned long   seq;
-#ifdef CONFIG_IPX      
-               ipx_packet      *ipx;
-#endif 
-       } h;
-       struct iphdr *          ip_hdr;
-       unsigned long           mem_len;
-       unsigned long           len;
-       unsigned long           fraglen;
-       struct sk_buff          *fraglist;      /* Fragment list */
-       unsigned long           truesize;
-       unsigned long           saddr;
-       unsigned long           daddr;
-       int                     magic;
-       volatile char           acked,
-                               used,
-                               free,
-                               arp,
-                               urg_used;
-       unsigned char                   tries,lock;     /* Lock is now unused */
-       unsigned short          users;          /* User count - see datagram.c (and soon seqpacket.c/stream.c) */
-};
-
-#define SK_WMEM_MAX    8192
-#define SK_RMEM_MAX    32767
-
-#define SK_FREED_SKB   0x0DE2C0DE
-#define SK_GOOD_SKB    0xDEC0DED1
-
-extern void                    print_skb(struct sk_buff *);
-extern void                    kfree_skb(struct sk_buff *skb, int rw);
-extern void                    skb_queue_head(struct sk_buff * volatile *list,struct sk_buff *buf);
-extern void                    skb_queue_tail(struct sk_buff * volatile *list,struct sk_buff *buf);
-extern struct sk_buff *                skb_dequeue(struct sk_buff * volatile *list);
-extern void                    skb_insert(struct sk_buff *old,struct sk_buff *newsk);
-extern void                    skb_append(struct sk_buff *old,struct sk_buff *newsk);
-extern void                    skb_unlink(struct sk_buff *buf);
-extern void                    skb_new_list_head(struct sk_buff *volatile* list);
-extern struct sk_buff *                skb_peek(struct sk_buff * volatile *list);
-extern struct sk_buff *                skb_peek_copy(struct sk_buff * volatile *list);
-extern struct sk_buff *                alloc_skb(unsigned int size, int priority);
-extern void                    kfree_skbmem(void *mem, unsigned size);
-
-extern void                    skb_check(struct sk_buff *skb,int, char *);
-#define IS_SKB(skb)    skb_check((skb),__LINE__,__FILE__)
-
-extern struct sk_buff *                skb_recv_datagram(struct sock *sk,unsigned flags,int noblock, int *err);
-extern int                     datagram_select(struct sock *sk, int sel_type, select_table *wait);
-extern void                    skb_copy_datagram(struct sk_buff *from, int offset, char *to,int size);
-extern void                    skb_free_datagram(struct sk_buff *skb);
-#endif /* _SKBUFF_H */
diff --git a/net/socket/sock.c b/net/socket/sock.c
deleted file mode 100644 (file)
index 1316be3..0000000
+++ /dev/null
@@ -1,418 +0,0 @@
-/*
- *     NET2Debugged, generic socket properties.
- *
- *     This module provides the generic option control and memory handling
- *     for a socket of any kind.
- *
- * Version:    @(#)sock.c      1.28    26/12/93
- *
- * Authors:    Alan Cox <iiitac@pyr.swan.ac.uk>
- *
- */
-#include <linux/config.h>
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/socket.h>
-#include <linux/in.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/string.h>
-#include <linux/sockios.h>
-#include <linux/net.h>
-#include <linux/fcntl.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-
-#include <asm/segment.h>
-#include <asm/system.h>
-
-#include "inet.h"
-#include "dev.h"
-#include "ip.h"
-#include "protocol.h"
-#include "arp.h"
-#include "route.h"
-#include "tcp.h"
-#include "udp.h"
-#include "skbuff.h"
-#include "sock.h"
-#include "raw.h"
-#include "icmp.h"
-
-static __inline__ int 
-min(unsigned int a, unsigned int b)
-{
-       if (a < b) 
-               return(a);
-       return(b);
-}
-
-#ifdef SOCK_DEBUG
-
-void print_sk(struct sock *sk)
-{
-       if (!sk) 
-       {
-               printk("  print_sk(NULL)\n");
-               return;
-       }
-       printk("  wmem_alloc = %lu\n", sk->wmem_alloc);
-       printk("  rmem_alloc = %lu\n", sk->rmem_alloc);
-       printk("  send_head = %p\n", sk->send_head);
-       printk("  state = %d\n",sk->state);
-       printk("  wback = %p, rqueue = %p\n", sk->wback, sk->rqueue);
-       printk("  wfront = %p\n", sk->wfront);
-       printk("  daddr = %lX, saddr = %lX\n", sk->daddr,sk->saddr);
-       printk("  num = %d", sk->num);
-       printk(" next = %p\n", sk->next);
-       printk("  send_seq = %ld, acked_seq = %ld, copied_seq = %ld\n",
-                 sk->send_seq, sk->acked_seq, sk->copied_seq);
-       printk("  rcv_ack_seq = %ld, window_seq = %ld, fin_seq = %ld\n",
-                 sk->rcv_ack_seq, sk->window_seq, sk->fin_seq);
-       printk("  prot = %p\n", sk->prot);
-       printk("  pair = %p, back_log = %p\n", sk->pair,sk->back_log);
-       printk("  inuse = %d , blog = %d\n", sk->inuse, sk->blog);
-       printk("  dead = %d delay_acks=%d\n", sk->dead, sk->delay_acks);
-       printk("  retransmits = %ld, timeout = %d\n", sk->retransmits, sk->timeout);
-       printk("  cong_window = %d, packets_out = %d\n", sk->cong_window,
-                 sk->packets_out);
-       printk("  urg = %d shutdown=%d\n", sk->urg, sk->shutdown);
-}
-
-
-void print_skb(struct sk_buff *skb)
-{
-       if (!skb) 
-       {
-               printk("  print_skb(NULL)\n");
-               return;
-       }
-       printk("  prev = %p, next = %p\n", skb->prev, skb->next);
-       printk("  sk = %p link3 = %p\n", skb->sk, skb->link3);
-       printk("  mem_addr = %p, mem_len = %lu\n", skb->mem_addr, skb->mem_len);
-       printk("  used = %d free = %d\n", skb->used,skb->free);
-}
-
-
-#endif
-
-/*
- *     This is meant for all protocols to use and covers goings on
- *     at the socket level. Everything here is generic.
- */
-
-int sock_setsockopt(struct sock *sk, int level, int optname,
-               char *optval, int optlen)
-{
-       int val;
-       int err;
-       struct linger ling;
-
-       if (optval == NULL) 
-               return(-EINVAL);
-
-       err=verify_area(VERIFY_READ, optval, sizeof(int));
-       if(err)
-               return err;
-       
-       val = get_fs_long((unsigned long *)optval);
-       switch(optname) 
-       {
-               case SO_TYPE:
-               case SO_ERROR:
-                       return(-ENOPROTOOPT);
-
-               case SO_DEBUG:  
-                       sk->debug=val?1:0;
-               case SO_DONTROUTE:      /* Still to be implemented */
-                       return(0);
-               case SO_BROADCAST:
-                       sk->broadcast=val?1:0;
-                       return 0;
-               case SO_SNDBUF:
-                       if(val>32767)
-                               val=32767;
-                       if(val<256)
-                               val=256;
-                       sk->sndbuf=val;
-                       return 0;
-               case SO_LINGER:
-                       err=verify_area(VERIFY_READ,optval,sizeof(ling));
-                       if(err)
-                               return err;
-                       memcpy_fromfs(&ling,optval,sizeof(ling));
-                       if(ling.l_onoff==0)
-                               sk->linger=0;
-                       else
-                       {
-                               sk->lingertime=ling.l_linger;
-                               sk->linger=1;
-                       }
-                       return 0;
-               case SO_RCVBUF:
-                       if(val>32767)
-                               val=32767;
-                       if(val<256)
-                               val=256;
-                       sk->rcvbuf=val;
-                       return(0);
-
-               case SO_REUSEADDR:
-                       if (val) 
-                               sk->reuse = 1;
-                       else 
-                               sk->reuse = 0;
-                       return(0);
-
-               case SO_KEEPALIVE:
-                       if (val)
-                               sk->keepopen = 1;
-                       else 
-                               sk->keepopen = 0;
-                       return(0);
-
-               case SO_OOBINLINE:
-                       if (val) 
-                               sk->urginline = 1;
-                       else 
-                               sk->urginline = 0;
-                       return(0);
-
-               case SO_NO_CHECK:
-                       if (val) 
-                               sk->no_check = 1;
-                       else 
-                               sk->no_check = 0;
-                       return(0);
-
-                case SO_PRIORITY:
-                       if (val >= 0 && val < DEV_NUMBUFFS) 
-                       {
-                               sk->priority = val;
-                       } 
-                       else 
-                       {
-                               return(-EINVAL);
-                       }
-                       return(0);
-
-               default:
-                       return(-ENOPROTOOPT);
-       }
-}
-
-
-int sock_getsockopt(struct sock *sk, int level, int optname,
-                  char *optval, int *optlen)
-{              
-       int val;
-       int err;
-       struct linger ling;
-
-       switch(optname) 
-       {
-               case SO_DEBUG:          
-                       val = sk->debug;
-                       break;
-               
-               case SO_DONTROUTE:      /* One last option to implement */
-                       val = 0;
-                       break;
-               
-               case SO_BROADCAST:
-                       val= sk->broadcast;
-                       break;
-               
-               case SO_LINGER: 
-                       err=verify_area(VERIFY_WRITE,optval,sizeof(ling));
-                       if(err)
-                               return err;
-                       err=verify_area(VERIFY_WRITE,optlen,sizeof(int));
-                       if(err)
-                               return err;
-                       put_fs_long(sizeof(ling),(unsigned long *)optlen);
-                       ling.l_onoff=sk->linger;
-                       ling.l_linger=sk->lingertime;
-                       memcpy_tofs(optval,&ling,sizeof(ling));
-                       return 0;
-               
-               case SO_SNDBUF:
-                       val=sk->sndbuf;
-                       break;
-               
-               case SO_RCVBUF:
-                       val =sk->rcvbuf;
-                       break;
-
-               case SO_REUSEADDR:
-                       val = sk->reuse;
-                       break;
-
-               case SO_KEEPALIVE:
-                       val = sk->keepopen;
-                       break;
-
-               case SO_TYPE:
-                       if (sk->prot == &tcp_prot) 
-                               val = SOCK_STREAM;
-                       else 
-                               val = SOCK_DGRAM;
-                       break;
-
-               case SO_ERROR:
-                       val = sk->err;
-                       sk->err = 0;
-                       break;
-
-               case SO_OOBINLINE:
-                       val = sk->urginline;
-                       break;
-       
-               case SO_NO_CHECK:
-                       val = sk->no_check;
-                       break;
-
-               case SO_PRIORITY:
-                       val = sk->priority;
-                       break;
-
-               default:
-                       return(-ENOPROTOOPT);
-       }
-       err=verify_area(VERIFY_WRITE, optlen, sizeof(int));
-       if(err)
-               return err;
-       put_fs_long(sizeof(int),(unsigned long *) optlen);
-
-       err=verify_area(VERIFY_WRITE, optval, sizeof(int));
-       if(err)
-               return err;
-       put_fs_long(val,(unsigned long *)optval);
-
-       return(0);
-}
-
-
-void *sock_wmalloc(struct sock *sk, unsigned long size, int force,
-            int priority)
-{
-       if (sk) 
-       {
-               if (sk->wmem_alloc + size < sk->sndbuf || force) 
-               {
-                       cli();
-                       sk->wmem_alloc+= size;
-                       sti();
-                       return(alloc_skb(size, priority));
-               }
-               DPRINTF((DBG_INET, "sock_wmalloc(%X,%d,%d,%d) returning NULL\n",
-                                               sk, size, force, priority));
-               return(NULL);
-       }
-       return(alloc_skb(size, priority));
-}
-
-
-void *sock_rmalloc(struct sock *sk, unsigned long size, int force, int priority)
-{
-       if (sk) 
-       {
-               if (sk->rmem_alloc + size < sk->rcvbuf || force) 
-               {
-                       void *c = alloc_skb(size, priority);
-                       cli();
-                       if (c) 
-                               sk->rmem_alloc += size;
-                       sti();
-                       return(c);
-               }
-               DPRINTF((DBG_INET, "sock_rmalloc(%X,%d,%d,%d) returning NULL\n",
-                                               sk,size,force, priority));
-               return(NULL);
-         }
-         return(alloc_skb(size, priority));
-}
-
-
-unsigned long sock_rspace(struct sock *sk)
-{
-       int amt;
-
-       if (sk != NULL) 
-       {
-               if (sk->rmem_alloc >= sk->rcvbuf-2*MIN_WINDOW) 
-                       return(0);
-               amt = min((sk->rcvbuf-sk->rmem_alloc)/2-MIN_WINDOW, MAX_WINDOW);
-               if (amt < 0) 
-                       return(0);
-               return(amt);
-       }
-       return(0);
-}
-
-
-unsigned long sock_wspace(struct sock *sk)
-{
-       if (sk != NULL) 
-       {
-               if (sk->shutdown & SEND_SHUTDOWN) 
-                       return(0);
-               if (sk->wmem_alloc >= sk->sndbuf)
-                       return(0);
-               return(sk->sndbuf-sk->wmem_alloc );
-       }
-       return(0);
-}
-
-
-void sock_wfree(struct sock *sk, void *mem, unsigned long size)
-{
-       struct sk_buff *skb;
-       DPRINTF((DBG_INET, "sock_wfree(sk=%X, mem=%X, size=%d)\n", sk, mem, size));
-
-       IS_SKB(mem);
-       
-       skb=mem;
-       
-       kfree_skbmem(mem, size);
-       if (sk) 
-       {
-               sk->wmem_alloc -= size;
-
-               /* In case it might be waiting for more memory. */
-               if (!sk->dead) 
-                       sk->write_space(sk);
-               if (sk->destroy && sk->wmem_alloc == 0 && sk->rmem_alloc == 0) 
-               {
-                       DPRINTF((DBG_INET,
-                               "recovered lost memory, sock = %X\n", sk));
-               }
-               return;
-       }
-}
-
-
-void sock_rfree(struct sock *sk, void *mem, unsigned long size)
-{
-       struct sk_buff *skb;
-       
-       DPRINTF((DBG_INET, "sock_rfree(sk=%X, mem=%X, size=%d)\n", sk, mem, size));
-
-       IS_SKB(mem);
-       skb=mem;
-       
-       kfree_skbmem(mem, size);
-       
-       if (sk) 
-       {
-               sk->rmem_alloc -= size;
-               if (sk->destroy && sk->wmem_alloc == 0 && sk->rmem_alloc == 0) 
-               {
-                       DPRINTF((DBG_INET,"recovered lot memory, sock = %X\n", sk));
-               }
-       }
-}
-
diff --git a/net/socket/sock.h b/net/socket/sock.h
deleted file mode 100644 (file)
index 6f0b1d8..0000000
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- *             Definitions for the socket handler
- *
- * Version:    @(#)sock.h      1.28    26/12/93
- *
- * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
- *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- *             Corey Minyard <wf-rch!minyard@relay.EU.net>
- *             Florian La Roche <flla@stud.uni-sb.de>
- *
- * Fixes:
- *             Alan Cox        :       Volatiles in skbuff pointers. See
- *                                     skbuff comments. May be overdone,
- *                                     better to prove they can be removed
- *                                     than the reverse.
- *             Alan Cox        :       Added a zapped field for tcp to note
- *                                     a socket is reset and must stay shut up
- *             Alan Cox        :       New fields for options
- *     Pauline Middelink       :       identd support
- *             Alan Cox        :       Split into sock.h and sockinet.h
- *
- *             This program is free software; you can redistribute it and/or
- *             modify it under the terms of the GNU General Public License
- *             as published by the Free Software Foundation; either version
- *             2 of the License, or (at your option) any later version.
- */
-#ifndef _SOCK_H
-#define _SOCK_H
-
-#include <linux/timer.h>
-#include <linux/ip.h>          /* struct options */
-#include <linux/tcp.h>         /* struct tcphdr */
-
-#include "skbuff.h"            /* struct sk_buff */
-#ifdef CONFIG_AX25
-#include "ax25/ax25.h"
-#endif
-#ifdef CONFIG_IPX
-#include "ipx/ipx.h"
-#endif
-
-#define SOCK_ARRAY_SIZE        64
-
-
-/*
- * This structure really needs to be cleaned up.
- * Most of it is for TCP, and not used by any of
- * the other protocols.
- */
-struct sock {
-  struct options               *opt;
-  struct options               *rcv_opt;
-  volatile unsigned long       wmem_alloc;
-  volatile unsigned long       rmem_alloc;
-  unsigned long                        send_seq;
-  unsigned long                        acked_seq;
-  unsigned long                        copied_seq;
-  unsigned long                        rcv_ack_seq;
-  unsigned long                        window_seq;
-  unsigned long                        fin_seq;
-
-  /*
-   * Not all are volatile, but some are, so we
-   * might as well say they all are.
-   */
-  volatile char                 inuse,
-                               dead,
-                               urginline,
-                               intr,
-                               blog,
-                               done,
-                               reuse,
-                               keepopen,
-                               linger,
-                               delay_acks,
-                               destroy,
-                               ack_timed,
-                               no_check,
-                               exp_growth,
-                               zapped, /* In ax25 & ipx means not linked */
-                               broadcast;
-  unsigned long                        lingertime;
-  int                          proc;
-  struct sock                  *next;
-  struct sock                  *pair;
-  struct sk_buff               *volatile send_tail;
-  struct sk_buff               *volatile send_head;
-  struct sk_buff               *volatile back_log;
-  struct sk_buff               *send_tmp;
-  long                         retransmits;
-  struct sk_buff               *volatile wback,
-                               *volatile wfront,
-                               *volatile rqueue;
-  struct proto                 *prot;
-  struct wait_queue            **sleep;
-  unsigned long                        daddr;
-  unsigned long                        saddr;
-  unsigned short               max_unacked;
-  unsigned short               window;
-  unsigned short               bytes_rcv;
-  unsigned short               mtu;
-  unsigned short               num;
-  volatile unsigned short      cong_window;
-  volatile unsigned short      packets_out;
-  volatile unsigned short      urg;
-  volatile unsigned short      shutdown;
-  unsigned short               mss;
-  volatile unsigned long       rtt;
-  volatile unsigned long       mdev;
-  volatile unsigned short      backoff;
-  volatile short               err;
-  unsigned char                        protocol;
-  volatile unsigned char       state;
-  volatile unsigned char       ack_backlog;
-  unsigned char                        max_ack_backlog;
-  unsigned char                        priority;
-  unsigned char                        debug;
-  unsigned short               rcvbuf;
-  unsigned short               sndbuf;
-  unsigned short               type;
-#ifdef CONFIG_IPX
-  ipx_address                  ipx_source_addr,ipx_dest_addr;
-  unsigned short               ipx_type;
-#endif
-#ifdef CONFIG_AX25
-/* Really we want to add a per protocol private area */
-  ax25_address                 ax25_source_addr,ax25_dest_addr;
-  struct sk_buff *volatile     ax25_retxq[8];
-  char                         ax25_state,ax25_vs,ax25_vr,ax25_lastrxnr,ax25_lasttxnr;
-  char                         ax25_condition;
-  char                         ax25_retxcnt;
-  char                         ax25_xx;
-  char                         ax25_retxqi;
-  char                         ax25_rrtimer;
-  char                         ax25_timer;
-#endif  
-/* IP 'private area' or will be eventually */
-  int                          ip_ttl;         /* TTL setting */
-  int                          ip_tos;         /* TOS */
-  
-  struct tcphdr                        dummy_th;
-
-  /* This part is used for the timeout functions (timer.c). */
-  int                          timeout;        /* What are we waiting for? */
-  struct timer_list            timer;
-
-  /* identd */
-  struct socket                        *socket;
-  
-  /* Event callbacks */
-  
-  void                         (*state_change)(struct sock *sk);
-  void                         (*data_ready)(struct sock *sk,int bytes);
-  void                         (*write_space)(struct sock *sk);
-  void                         (*error_report)(struct sock *sk);
-};
-
-
-#define TIME_WRITE     1
-#define TIME_CLOSE     2
-#define TIME_KEEPOPEN  3
-#define TIME_DESTROY   4
-#define TIME_DONE      5       /* used to absorb those last few packets */
-#define SOCK_DESTROY_TIME 1000 /* about 10 seconds                     */
-
-#define PROT_SOCK      1024    /* Sockets 0-1023 can't be bound too unless you are superuser */
-
-#define SHUTDOWN_MASK  3
-#define RCV_SHUTDOWN   1
-#define SEND_SHUTDOWN  2
-
-extern void                    print_sk(struct sock *);
-extern void                    *sock_wmalloc(struct sock *sk,
-                                             unsigned long size, int force,
-                                             int priority);
-extern void                    *sock_rmalloc(struct sock *sk,
-                                             unsigned long size, int force,
-                                             int priority);
-extern void                    sock_wfree(struct sock *sk, void *mem,
-                                          unsigned long size);
-extern void                    sock_rfree(struct sock *sk, void *mem,
-                                          unsigned long size);
-extern unsigned long           sock_rspace(struct sock *sk);
-extern unsigned long           sock_wspace(struct sock *sk);
-
-extern int                     sock_setsockopt(struct sock *sk, int level, int optname, char *optval,
-                                               int optlen);
-extern int                     sock_getsockopt(struct sock *sk, int level, int optname, char *optval,
-                                               int *optlen);                                           
-
-#endif /* _SOCK_H */
index 4e23976f57eafa446a1c34b389b115651ccab844..8a80ad55b0bacf5eb341f59b239c07514b6e0b11 100644 (file)
@@ -8,7 +8,7 @@
  *             the PROC file system and the "unix" family of networking
  *             protocols. It is mainly used for debugging and statistics.
  *
- * Version:    @(#)proc.c      1.28            25/12/93
+ * Version:    @(#)proc.c      1.0.4   05/23/93
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *             Fred Baumgarten, <dc6iq@insu1.etec.uni-kalrsruhe.de>
  *
  * Fixes:
- *             Anonymous               :       Comment errors
  *
  *             This program is free software; you can redistribute it and/or
  *             modify it under the terms of the GNU General Public License
  *             as published by the Free Software Foundation; either version
  *             2 of the License, or (at your option) any later version.
  */
-
 #include <linux/autoconf.h>
 #include <linux/sched.h>
 #include <linux/string.h>
 #include "unix.h"
 
 
-/*
- *     Called from PROCfs.
- */
+/* Called from PROCfs. */
 int unix_get_info(char *buffer)
 {
-       char *pos;
-       int i;
+  char *pos;
+  int i;
 
-       pos = buffer;
-       pos += sprintf(pos, "Num RefCount Protocol Flags    Type St Path\n");
+  pos = buffer;
+  pos += sprintf(pos, "Num RefCount Protocol Flags    Type St Path\n");
 
-       for(i = 0; i < NSOCKETS; i++) 
-       {
-               if (unix_datas[i].refcnt) 
-               {
-                       pos += sprintf(pos, "%2d: %08X %08X %08lX %04X %02X", i,
-                               unix_datas[i].refcnt,
-                               unix_datas[i].protocol,
-                               unix_datas[i].socket->flags,
-                               unix_datas[i].socket->type,
-                               unix_datas[i].socket->state
-                       );
-       
-                       /* If socket is bound to a filename, we'll print it. */
-                       if(unix_datas[i].sockaddr_len>0) 
-                       {
-                               pos += sprintf(pos, " %s\n",
-                                       unix_datas[i].sockaddr_un.sun_path);
-                       } 
-                       else 
-                       { /* just add a newline */
-                               *pos='\n';
-                               pos++;
-                               *pos='\0';
-                       }
+  for(i = 0; i < NSOCKETS; i++) {
+       if (unix_datas[i].refcnt) {
+               pos += sprintf(pos, "%2d: %08X %08X %08lX %04X %02X", i,
+                       unix_datas[i].refcnt,
+                       unix_datas[i].protocol,
+                       unix_datas[i].socket->flags,
+                       unix_datas[i].socket->type,
+                       unix_datas[i].socket->state
+               );
+
+               /* If socket is bound to a filename, we'll print it. */
+               if(unix_datas[i].sockaddr_len>0) {
+                       pos += sprintf(pos, " %s\n",
+                               unix_datas[i].sockaddr_un.sun_path);
+               } else { /* just add a newline */
+                       *pos='\n';
+                       pos++;
+                       *pos='\0';
+               }
 
-                       /*
-                        * Check whether buffer _may_ overflow in the next loop.
-                        * Since sockets may have very very long paths, we make
-                        * PATH_MAX+80 the minimum space left for a new line.
-                        */
-               
-                       if (pos > buffer+PAGE_SIZE-80-PATH_MAX) 
-                       {
-                               printk("UNIX: netinfo: oops, too many sockets.\n");
-                               return(pos - buffer);
-                       }
+               /*
+                * Check whether buffer _may_ overflow in the next loop.
+                * Since sockets may have very very long paths, we make
+                * PATH_MAX+80 the minimum space left for a new line.
+                */
+               if (pos > buffer+PAGE_SIZE-80-PATH_MAX) {
+                       printk("UNIX: netinfo: oops, too many sockets.\n");
+                       return(pos - buffer);
                }
-       }
-       return(pos - buffer);
+       }
+  }
+  return(pos - buffer);
 }
index 7e68b240592ce284aff049d23183e902626b783c..f4de8a89c14d0c4f2d295bbf4d6574daef8775ea 100644 (file)
@@ -4,7 +4,7 @@
  *             BSD Socket interface as the means of communication with
  *             the user level.
  *
- * Version:    @(#)sock.c      1.28    25/12/93
+ * Version:    @(#)sock.c      1.0.5   05/25/93
  *
  * Authors:    Orest Zborowski, <obz@Kodak.COM>
  *             Ross Biro, <bir7@leland.Stanford.Edu>
@@ -12,7 +12,6 @@
  *
  * Fixes:
  *             Alan Cox        :       Verify Area
- *             Alan Cox        :       Tidy up ready for release
  *
  * BUGS
  *     Page faults on read while another process reads could lose data.
@@ -94,268 +93,252 @@ static int unix_proto_getsockopt(struct socket *sock, int level, int optname,
                                  char *optval, int *optlen);
 
 
-static void dprintf(int level, char *fmt, ...)
+static void
+dprintf(int level, char *fmt, ...)
 {
-       va_list args;
-       char *buff;
-       extern int vsprintf(char * buf, const char * fmt, va_list args);
-
-       if (level != unix_debug) 
-               return;
-
-       buff = (char *) kmalloc(256, GFP_KERNEL);
-       if (buff != NULL) 
-       {
-               va_start(args, fmt);
-               vsprintf(buff, fmt, args);
-               va_end(args);
-               printk(buff);
-               kfree(buff);
-       }
+  va_list args;
+  char *buff;
+  extern int vsprintf(char * buf, const char * fmt, va_list args);
+
+  if (level != unix_debug) return;
+
+  buff = (char *) kmalloc(256, GFP_KERNEL);
+  if (buff != NULL) {
+       va_start(args, fmt);
+       vsprintf(buff, fmt, args);
+       va_end(args);
+       printk(buff);
+       kfree(buff);
+  }
 }
 
 
-static inline int min(int a, int b)
+static inline int
+min(int a, int b)
 {
-       if (a < b) 
-               return(a);
-       return(b);
+  if (a < b) return(a);
+  return(b);
 }
 
 
-void sockaddr_un_printk(struct sockaddr_un *sockun, int sockaddr_len)
+void
+sockaddr_un_printk(struct sockaddr_un *sockun, int sockaddr_len)
 {
-       char buf[sizeof(sockun->sun_path) + 1];
-
-       if (unix_debug == 0) 
-               return;
-
-       sockaddr_len -= UN_PATH_OFFSET;
-       if (sockun->sun_family != AF_UNIX)
-               printk("UNIX: Badd addr family %d>\n", sockun->sun_family);
-       else if (sockaddr_len <= 0 || sockaddr_len >= sizeof(buf))
-               printk("UNIX: Bad addr len %d>\n", sockaddr_len);
-       else 
-       {
-               memcpy(buf, sockun->sun_path, sockaddr_len);
-               buf[sockaddr_len] = '\0';
-               printk("\"%s\"[%lu]\n", buf, sockaddr_len + UN_PATH_OFFSET);
-       }
+  char buf[sizeof(sockun->sun_path) + 1];
+
+  if (unix_debug == 0) return;
+
+  sockaddr_len -= UN_PATH_OFFSET;
+  if (sockun->sun_family != AF_UNIX)
+       printk("UNIX: Badd addr family %d>\n", sockun->sun_family);
+    else if (sockaddr_len <= 0 || sockaddr_len >= sizeof(buf))
+       printk("UNIX: Bad addr len %d>\n", sockaddr_len);
+    else {
+       memcpy(buf, sockun->sun_path, sockaddr_len);
+       buf[sockaddr_len] = '\0';
+       printk("\"%s\"[%lu]\n", buf, sockaddr_len + UN_PATH_OFFSET);
+  }
 }
   
 
-/*
- *     Don't have to do anything. 
- */
-static int unix_proto_listen(struct socket *sock, int backlog)
+/* don't have to do anything. */
+static int
+unix_proto_listen(struct socket *sock, int backlog)
 {
-       return(0);
+  return(0);
 }
 
 
-static int unix_proto_setsockopt(struct socket *sock, int level, int optname,
+static int
+unix_proto_setsockopt(struct socket *sock, int level, int optname,
                      char *optval, int optlen)
 {
-       return(-EOPNOTSUPP);
+  return(-EOPNOTSUPP);
 }
 
 
-static int unix_proto_getsockopt(struct socket *sock, int level, int optname,
+static int
+unix_proto_getsockopt(struct socket *sock, int level, int optname,
                      char *optval, int *optlen)
 {
-       return(-EOPNOTSUPP);
+  return(-EOPNOTSUPP);
 }
 
-static int unix_proto_sendto(struct socket *sock, void *buff, int len, int nonblock, 
+static int
+unix_proto_sendto(struct socket *sock, void *buff, int len, int nonblock, 
                  unsigned flags,  struct sockaddr *addr, int addr_len)
 {
-       return(-EOPNOTSUPP);
+  return(-EOPNOTSUPP);
 }     
 
-static int unix_proto_recvfrom(struct socket *sock, void *buff, int len, int nonblock, 
+static int
+unix_proto_recvfrom(struct socket *sock, void *buff, int len, int nonblock, 
                    unsigned flags, struct sockaddr *addr, int *addr_len)
 {
-       return(-EOPNOTSUPP);
+  return(-EOPNOTSUPP);
 }     
 
 
-static int unix_proto_shutdown(struct socket *sock, int how)
+static int
+unix_proto_shutdown(struct socket *sock, int how)
 {
-       return(-EOPNOTSUPP);
+  return(-EOPNOTSUPP);
 }
 
 
-/*
- *     This error needs to be checked. 
- */
-
-static int unix_proto_send(struct socket *sock, void *buff, int len, int nonblock,
+/* This error needs to be checked. */
+static int
+unix_proto_send(struct socket *sock, void *buff, int len, int nonblock,
                unsigned flags)
 {
-       if (flags != 0) 
-               return(-EINVAL);
-       return(unix_proto_write(sock, (char *) buff, len, nonblock));
+  if (flags != 0) return(-EINVAL);
+  return(unix_proto_write(sock, (char *) buff, len, nonblock));
 }
 
 
-/*
- *     This error needs to be checked. 
- */
-static int unix_proto_recv(struct socket *sock, void *buff, int len, int nonblock,
+/* This error needs to be checked. */
+static int
+unix_proto_recv(struct socket *sock, void *buff, int len, int nonblock,
                unsigned flags)
 {
-       if (flags != 0) 
-               return(-EINVAL);
-       return(unix_proto_read(sock, (char *) buff, len, nonblock));
+  if (flags != 0) return(-EINVAL);
+  return(unix_proto_read(sock, (char *) buff, len, nonblock));
 }
 
 
-static struct unix_proto_data * unix_data_lookup(struct sockaddr_un *sockun, int sockaddr_len,
+static struct unix_proto_data *
+unix_data_lookup(struct sockaddr_un *sockun, int sockaddr_len,
                 struct inode *inode)
 {
-       struct unix_proto_data *upd;
-
-       for(upd = unix_datas; upd <= last_unix_data; ++upd) 
-       {
-               if (upd->refcnt && upd->socket &&
-                       upd->socket->state == SS_UNCONNECTED &&
-                       upd->sockaddr_un.sun_family == sockun->sun_family &&
-                       upd->inode == inode) 
-               {
-                       return(upd);
-               }
-       }
-       return(NULL);
+  struct unix_proto_data *upd;
+
+  for(upd = unix_datas; upd <= last_unix_data; ++upd) {
+       if (upd->refcnt && upd->socket &&
+           upd->socket->state == SS_UNCONNECTED &&
+           upd->sockaddr_un.sun_family == sockun->sun_family &&
+           upd->inode == inode) return(upd);
+  }
+  return(NULL);
 }
 
 
-static struct unix_proto_data *unix_data_alloc(void)
+static struct unix_proto_data *
+unix_data_alloc(void)
 {
-       struct unix_proto_data *upd;
-
-       cli();
-       for(upd = unix_datas; upd <= last_unix_data; ++upd) 
-       {
-               if (!upd->refcnt) 
-               {
-                       upd->refcnt = 1;
-                       sti();
-                       upd->socket = NULL;
-                       upd->sockaddr_len = 0;
-                       upd->sockaddr_un.sun_family = 0;
-                       upd->buf = NULL;
-                       upd->bp_head = upd->bp_tail = 0;
-                       upd->inode = NULL;
-                       upd->peerupd = NULL;
-                       return(upd);
-               }
-       }
-       sti();
-       return(NULL);
+  struct unix_proto_data *upd;
+
+  cli();
+  for(upd = unix_datas; upd <= last_unix_data; ++upd) {
+       if (!upd->refcnt) {
+               upd->refcnt = 1;
+               sti();
+               upd->socket = NULL;
+               upd->sockaddr_len = 0;
+               upd->sockaddr_un.sun_family = 0;
+               upd->buf = NULL;
+               upd->bp_head = upd->bp_tail = 0;
+               upd->inode = NULL;
+               upd->peerupd = NULL;
+               return(upd);
+       }
+  }
+  sti();
+  return(NULL);
 }
 
 
-static inline void unix_data_ref(struct unix_proto_data *upd)
+static inline void
+unix_data_ref(struct unix_proto_data *upd)
 {
-       if (!upd) 
-       {
-               dprintf(1, "UNIX: data_ref: upd = NULL\n");
-               return;
-       }
-       ++upd->refcnt;
-       dprintf(1, "UNIX: data_ref: refing data 0x%x(%d)\n", upd, upd->refcnt);
+  if (!upd) {
+    dprintf(1, "UNIX: data_ref: upd = NULL\n");
+    return;
+  }
+  ++upd->refcnt;
+  dprintf(1, "UNIX: data_ref: refing data 0x%x(%d)\n", upd, upd->refcnt);
 }
 
 
-static void unix_data_deref(struct unix_proto_data *upd)
+static void
+unix_data_deref(struct unix_proto_data *upd)
 {
-       if (!upd) 
-       {
-               dprintf(1, "UNIX: data_deref: upd = NULL\n");
-               return;
-       }
-       if (upd->refcnt == 1) 
-       {
-               dprintf(1, "UNIX: data_deref: releasing data 0x%x\n", upd);
-               if (upd->buf) 
-               {
-                       free_page((unsigned long)upd->buf);
-                       upd->buf = NULL;
-                       upd->bp_head = upd->bp_tail = 0;
-               }
-       }
-       --upd->refcnt;
+  if (!upd) {
+    dprintf(1, "UNIX: data_deref: upd = NULL\n");
+    return;
+  }
+  if (upd->refcnt == 1) {
+       dprintf(1, "UNIX: data_deref: releasing data 0x%x\n", upd);
+       if (upd->buf) {
+               free_page((unsigned long)upd->buf);
+               upd->buf = NULL;
+               upd->bp_head = upd->bp_tail = 0;
+       }
+  }
+  --upd->refcnt;
 }
 
 
 /*
- *     Upon a create, we allocate an empty protocol data,
- *     and grab a page to buffer writes.
+ * Upon a create, we allocate an empty protocol data,
+ * and grab a page to buffer writes.
  */
-
-static int unix_proto_create(struct socket *sock, int protocol)
-{
-       struct unix_proto_data *upd;
-
-       dprintf(1, "UNIX: create: socket 0x%x, proto %d\n", sock, protocol);
-       if (protocol != 0) 
-       {
-               dprintf(1, "UNIX: create: protocol != 0\n");
-               return(-EINVAL);
-       }
-       if (!(upd = unix_data_alloc())) 
-       {
-               printk("UNIX: create: can't allocate buffer\n");
-               return(-ENOMEM);
-       }
-       if (!(upd->buf = (char*) get_free_page(GFP_USER))) 
-       {
-               printk("UNIX: create: can't get page!\n");
-               unix_data_deref(upd);
-               return(-ENOMEM);
-       }
-       upd->protocol = protocol;
-       upd->socket = sock;
-       UN_DATA(sock) = upd;
-       dprintf(1, "UNIX: create: allocated data 0x%x\n", upd);
-       return(0);
+static int
+unix_proto_create(struct socket *sock, int protocol)
+{
+  struct unix_proto_data *upd;
+
+  dprintf(1, "UNIX: create: socket 0x%x, proto %d\n", sock, protocol);
+  if (protocol != 0) {
+       dprintf(1, "UNIX: create: protocol != 0\n");
+       return(-EINVAL);
+  }
+  if (!(upd = unix_data_alloc())) {
+       printk("UNIX: create: can't allocate buffer\n");
+       return(-ENOMEM);
+  }
+  if (!(upd->buf = (char*) get_free_page(GFP_USER))) {
+       printk("UNIX: create: can't get page!\n");
+       unix_data_deref(upd);
+       return(-ENOMEM);
+  }
+  upd->protocol = protocol;
+  upd->socket = sock;
+  UN_DATA(sock) = upd;
+  dprintf(1, "UNIX: create: allocated data 0x%x\n", upd);
+  return(0);
 }
 
 
-static int unix_proto_dup(struct socket *newsock, struct socket *oldsock)
+static int
+unix_proto_dup(struct socket *newsock, struct socket *oldsock)
 {
-       struct unix_proto_data *upd = UN_DATA(oldsock);
+  struct unix_proto_data *upd = UN_DATA(oldsock);
 
-       return(unix_proto_create(newsock, upd->protocol));
+  return(unix_proto_create(newsock, upd->protocol));
 }
 
 
-static int unix_proto_release(struct socket *sock, struct socket *peer)
-{
-       struct unix_proto_data *upd = UN_DATA(sock);
-
-       dprintf(1, "UNIX: release: socket 0x%x, unix_data 0x%x\n", sock, upd);
-       if (!upd) 
-               return(0);
-       if (upd->socket != sock) 
-       {
-               printk("UNIX: release: socket link mismatch!\n");
-               return(-EINVAL);
-       }
-       if (upd->inode) 
-       {
-               dprintf(1, "UNIX: release: releasing inode 0x%x\n", upd->inode);
-               iput(upd->inode);
-               upd->inode = NULL;
-       }
-       UN_DATA(sock) = NULL;
-       upd->socket = NULL;
-       if (upd->peerupd) 
-               unix_data_deref(upd->peerupd);
-       unix_data_deref(upd);
-       return(0);
+static int
+unix_proto_release(struct socket *sock, struct socket *peer)
+{
+  struct unix_proto_data *upd = UN_DATA(sock);
+
+  dprintf(1, "UNIX: release: socket 0x%x, unix_data 0x%x\n", sock, upd);
+  if (!upd) return(0);
+  if (upd->socket != sock) {
+       printk("UNIX: release: socket link mismatch!\n");
+       return(-EINVAL);
+  }
+  if (upd->inode) {
+       dprintf(1, "UNIX: release: releasing inode 0x%x\n", upd->inode);
+       iput(upd->inode);
+       upd->inode = NULL;
+  }
+  UN_DATA(sock) = NULL;
+  upd->socket = NULL;
+  if (upd->peerupd) unix_data_deref(upd->peerupd);
+  unix_data_deref(upd);
+  return(0);
 }
 
 
@@ -368,57 +351,54 @@ static int unix_proto_release(struct socket *sock, struct socket *peer)
  *       Here we return EINVAL, but it may be necessary to re-bind.
  *       I think thats what BSD does in the case of datagram sockets...
  */
-static int unix_proto_bind(struct socket *sock, struct sockaddr *umyaddr,
+static int
+unix_proto_bind(struct socket *sock, struct sockaddr *umyaddr,
                int sockaddr_len)
 {
-       char fname[sizeof(((struct sockaddr_un *)0)->sun_path) + 1];
-       struct unix_proto_data *upd = UN_DATA(sock);
-       unsigned long old_fs;
-       int i;
-       int er;
-
-       dprintf(1, "UNIX: bind: socket 0x%x, len=%d\n", sock, sockaddr_len);
-       if (sockaddr_len <= UN_PATH_OFFSET || sockaddr_len > sizeof(struct sockaddr_un)) 
-       {
-               dprintf(1, "UNIX: bind: bad length %d\n", sockaddr_len);
-               return(-EINVAL);
-       }
-       if (upd->sockaddr_len || upd->inode) 
-       {
-               printk("UNIX: bind: already bound!\n");
-               return(-EINVAL);
-       }
-       er=verify_area(VERIFY_WRITE, umyaddr, sockaddr_len);
-       if(er)
-               return er;
-       memcpy_fromfs(&upd->sockaddr_un, umyaddr, sockaddr_len);
-       upd->sockaddr_un.sun_path[sockaddr_len-UN_PATH_OFFSET] = '\0';
-       if (upd->sockaddr_un.sun_family != AF_UNIX) 
-       {
-               dprintf(1, "UNIX: bind: family is %d, not AF_UNIX(%d)\n",
-                       upd->sockaddr_un.sun_family, AF_UNIX);
-               return(-EINVAL);
-       }
-
-       memcpy(fname, upd->sockaddr_un.sun_path, sockaddr_len-UN_PATH_OFFSET);
-       fname[sockaddr_len-UN_PATH_OFFSET] = '\0';
-       old_fs = get_fs();
-       set_fs(get_ds());
-       i = do_mknod(fname, S_IFSOCK | S_IRWXUGO, 0);
-       if (i == 0) 
-               i = open_namei(fname, 0, S_IFSOCK, &upd->inode, NULL);
-       set_fs(old_fs);
-       if (i < 0) 
-       {
-               printk("UNIX: bind: can't open socket %s\n", fname);
-               return(i);
-       }
-       upd->sockaddr_len = sockaddr_len;       /* now its legal */
-
-       dprintf(1, "UNIX: bind: bound socket address: ");
-       sockaddr_un_printk(&upd->sockaddr_un, upd->sockaddr_len);
-       dprintf(1, "to inode 0x%x\n", upd->inode);
-       return(0);
+  char fname[sizeof(((struct sockaddr_un *)0)->sun_path) + 1];
+  struct unix_proto_data *upd = UN_DATA(sock);
+  unsigned long old_fs;
+  int i;
+  int er;
+
+  dprintf(1, "UNIX: bind: socket 0x%x, len=%d\n", sock, sockaddr_len);
+  if (sockaddr_len <= UN_PATH_OFFSET ||
+      sockaddr_len > sizeof(struct sockaddr_un)) {
+       dprintf(1, "UNIX: bind: bad length %d\n", sockaddr_len);
+       return(-EINVAL);
+  }
+  if (upd->sockaddr_len || upd->inode) {
+       printk("UNIX: bind: already bound!\n");
+       return(-EINVAL);
+  }
+  er=verify_area(VERIFY_WRITE, umyaddr, sockaddr_len);
+  if(er)
+       return er;
+  memcpy_fromfs(&upd->sockaddr_un, umyaddr, sockaddr_len);
+  upd->sockaddr_un.sun_path[sockaddr_len-UN_PATH_OFFSET] = '\0';
+  if (upd->sockaddr_un.sun_family != AF_UNIX) {
+       dprintf(1, "UNIX: bind: family is %d, not AF_UNIX(%d)\n",
+                               upd->sockaddr_un.sun_family, AF_UNIX);
+       return(-EINVAL);
+  }
+
+  memcpy(fname, upd->sockaddr_un.sun_path, sockaddr_len-UN_PATH_OFFSET);
+  fname[sockaddr_len-UN_PATH_OFFSET] = '\0';
+  old_fs = get_fs();
+  set_fs(get_ds());
+  i = do_mknod(fname, S_IFSOCK | S_IRWXUGO, 0);
+  if (i == 0) i = open_namei(fname, 0, S_IFSOCK, &upd->inode, NULL);
+  set_fs(old_fs);
+  if (i < 0) {
+       printk("UNIX: bind: can't open socket %s\n", fname);
+       return(i);
+  }
+  upd->sockaddr_len = sockaddr_len;    /* now its legal */
+
+  dprintf(1, "UNIX: bind: bound socket address: ");
+  sockaddr_un_printk(&upd->sockaddr_un, upd->sockaddr_len);
+  dprintf(1, "to inode 0x%x\n", upd->inode);
+  return(0);
 }
 
 
@@ -427,79 +407,71 @@ static int unix_proto_bind(struct socket *sock, struct sockaddr *umyaddr,
  * (I can't for the life of me find an application where that
  * wouldn't be the case!)
  */
-
-static int unix_proto_connect(struct socket *sock, struct sockaddr *uservaddr,
-       int sockaddr_len, int flags)
-{
-       char fname[sizeof(((struct sockaddr_un *)0)->sun_path) + 1];
-       struct sockaddr_un sockun;
-       struct unix_proto_data *serv_upd;
-       struct inode *inode;
-       unsigned long old_fs;
-       int i;
-       int er;
-       
-       dprintf(1, "UNIX: connect: socket 0x%x, servlen=%d\n", sock, sockaddr_len);
-       
-       if (sockaddr_len <= UN_PATH_OFFSET || sockaddr_len > sizeof(struct sockaddr_un)) 
-       {
-               dprintf(1, "UNIX: connect: bad length %d\n", sockaddr_len);
-               return(-EINVAL);
-       }
-       if (sock->state == SS_CONNECTING) 
-               return(-EINPROGRESS);
-       if (sock->state == SS_CONNECTED)
-               return(-EISCONN);
-
-       er=verify_area(VERIFY_READ, uservaddr, sockaddr_len);
-       if(er)
-               return er;
-       memcpy_fromfs(&sockun, uservaddr, sockaddr_len);
-       sockun.sun_path[sockaddr_len-UN_PATH_OFFSET] = '\0';
-       if (sockun.sun_family != AF_UNIX) 
-       {
-               dprintf(1, "UNIX: connect: family is %d, not AF_UNIX(%d)\n",
-                       sockun.sun_family, AF_UNIX);
-               return(-EINVAL);
-       }
-
-       /*
-        * Try to open the name in the filesystem - this is how we
-        * identify ourselves and our server. Note that we don't
-        * hold onto the inode that long, just enough to find our
-        * server. When we're connected, we mooch off the server.
-        */
-
-       memcpy(fname, sockun.sun_path, sockaddr_len-UN_PATH_OFFSET);
-       fname[sockaddr_len-UN_PATH_OFFSET] = '\0';
-       old_fs = get_fs();
-       set_fs(get_ds());
-       i = open_namei(fname, 0, S_IFSOCK, &inode, NULL);
-       set_fs(old_fs);
-       if (i < 0) 
-       {
-               dprintf(1, "UNIX: connect: can't open socket %s\n", fname);
-               return(i);
-       }
-       serv_upd = unix_data_lookup(&sockun, sockaddr_len, inode);
-       iput(inode);
-       if (!serv_upd) 
-       {
-               dprintf(1, "UNIX: connect: can't locate peer %s at inode 0x%x\n",
-                       fname, inode);
-               return(-EINVAL);
-       }
-       if ((i = sock_awaitconn(sock, serv_upd->socket)) < 0) 
-       {
-               dprintf(1, "UNIX: connect: can't await connection\n");
-               return(i);
-       }
-       if (sock->conn) 
-       {
-               unix_data_ref(UN_DATA(sock->conn));
-               UN_DATA(sock)->peerupd = UN_DATA(sock->conn); /* ref server */
-       }
-       return(0);
+static int
+unix_proto_connect(struct socket *sock, struct sockaddr *uservaddr,
+                  int sockaddr_len, int flags)
+{
+  char fname[sizeof(((struct sockaddr_un *)0)->sun_path) + 1];
+  struct sockaddr_un sockun;
+  struct unix_proto_data *serv_upd;
+  struct inode *inode;
+  unsigned long old_fs;
+  int i;
+  int er;
+
+  dprintf(1, "UNIX: connect: socket 0x%x, servlen=%d\n", sock, sockaddr_len);
+
+  if (sockaddr_len <= UN_PATH_OFFSET ||
+      sockaddr_len > sizeof(struct sockaddr_un)) {
+       dprintf(1, "UNIX: connect: bad length %d\n", sockaddr_len);
+       return(-EINVAL);
+  }
+  if (sock->state == SS_CONNECTING) return(-EINPROGRESS);
+  if (sock->state == SS_CONNECTED) return(-EISCONN);
+
+  er=verify_area(VERIFY_READ, uservaddr, sockaddr_len);
+  if(er)
+       return er;
+  memcpy_fromfs(&sockun, uservaddr, sockaddr_len);
+  sockun.sun_path[sockaddr_len-UN_PATH_OFFSET] = '\0';
+  if (sockun.sun_family != AF_UNIX) {
+       dprintf(1, "UNIX: connect: family is %d, not AF_UNIX(%d)\n",
+                                               sockun.sun_family, AF_UNIX);
+       return(-EINVAL);
+  }
+
+  /*
+   * Try to open the name in the filesystem - this is how we
+   * identify ourselves and our server. Note that we don't
+   * hold onto the inode that long, just enough to find our
+   * server. When we're connected, we mooch off the server.
+   */
+  memcpy(fname, sockun.sun_path, sockaddr_len-UN_PATH_OFFSET);
+  fname[sockaddr_len-UN_PATH_OFFSET] = '\0';
+  old_fs = get_fs();
+  set_fs(get_ds());
+  i = open_namei(fname, 0, S_IFSOCK, &inode, NULL);
+  set_fs(old_fs);
+  if (i < 0) {
+       dprintf(1, "UNIX: connect: can't open socket %s\n", fname);
+       return(i);
+  }
+  serv_upd = unix_data_lookup(&sockun, sockaddr_len, inode);
+  iput(inode);
+  if (!serv_upd) {
+       dprintf(1, "UNIX: connect: can't locate peer %s at inode 0x%x\n",
+                                                               fname, inode);
+       return(-EINVAL);
+  }
+  if ((i = sock_awaitconn(sock, serv_upd->socket)) < 0) {
+       dprintf(1, "UNIX: connect: can't await connection\n");
+       return(i);
+  }
+  if (sock->conn) {
+       unix_data_ref(UN_DATA(sock->conn));
+       UN_DATA(sock)->peerupd = UN_DATA(sock->conn); /* ref server */
+  }
+  return(0);
 }
 
 
@@ -509,173 +481,146 @@ static int unix_proto_connect(struct socket *sock, struct sockaddr *uservaddr,
  * for a wait area, and deadlock prevention in the case of a process
  * writing to itself is, ignored, in true unix fashion!
  */
-
-static int unix_proto_socketpair(struct socket *sock1, struct socket *sock2)
+static int
+unix_proto_socketpair(struct socket *sock1, struct socket *sock2)
 {
-       struct unix_proto_data *upd1 = UN_DATA(sock1), *upd2 = UN_DATA(sock2);
+  struct unix_proto_data *upd1 = UN_DATA(sock1), *upd2 = UN_DATA(sock2);
 
-       unix_data_ref(upd1);
-       unix_data_ref(upd2);
-       upd1->peerupd = upd2;
-       upd2->peerupd = upd1;
-       return(0);
+  unix_data_ref(upd1);
+  unix_data_ref(upd2);
+  upd1->peerupd = upd2;
+  upd2->peerupd = upd1;
+  return(0);
 }
 
 
 /* On accept, we ref the peer's data for safe writes. */
-
-static int unix_proto_accept(struct socket *sock, struct socket *newsock, int flags)
-{
-       struct socket *clientsock;
-
-       dprintf(1, "UNIX: accept: socket 0x%x accepted via socket 0x%x\n",
-               sock, newsock);
-
-       /*
-        * If there aren't any sockets awaiting connection,
-        * then wait for one, unless nonblocking.
-        */
-       while(!(clientsock = sock->iconn)) 
-       {
-               if (flags & O_NONBLOCK) 
-                       return(-EAGAIN);
-               interruptible_sleep_on(sock->wait);
-               if (current->signal & ~current->blocked) 
-               {
-                       dprintf(1, "UNIX: accept: sleep was interrupted\n");
-                       return(-ERESTARTSYS);
-               }
-       }
-
-       /*
-        * Great. Finish the connection relative to server and client,
-        * wake up the client and return the new fd to the server.
-        */
-       sock->iconn = clientsock->next;
-       clientsock->next = NULL;
-       newsock->conn = clientsock;
-       clientsock->conn = newsock;
-       clientsock->state = SS_CONNECTED;
-       newsock->state = SS_CONNECTED;
-       unix_data_ref(UN_DATA(clientsock));
-       UN_DATA(newsock)->peerupd              = UN_DATA(clientsock);
-       UN_DATA(newsock)->sockaddr_un        = UN_DATA(sock)->sockaddr_un;
-       UN_DATA(newsock)->sockaddr_len       = UN_DATA(sock)->sockaddr_len;
-       wake_up(clientsock->wait);
-       return(0);
+static int
+unix_proto_accept(struct socket *sock, struct socket *newsock, int flags)
+{
+  struct socket *clientsock;
+
+  dprintf(1, "UNIX: accept: socket 0x%x accepted via socket 0x%x\n",
+                                                       sock, newsock);
+
+  /*
+   * If there aren't any sockets awaiting connection,
+   * then wait for one, unless nonblocking.
+   */
+  while(!(clientsock = sock->iconn)) {
+       if (flags & O_NONBLOCK) return(-EAGAIN);
+       interruptible_sleep_on(sock->wait);
+       if (current->signal & ~current->blocked) {
+               dprintf(1, "UNIX: accept: sleep was interrupted\n");
+               return(-ERESTARTSYS);
+       }
+  }
+
+  /*
+   * Great. Finish the connection relative to server and client,
+   * wake up the client and return the new fd to the server.
+   */
+  sock->iconn = clientsock->next;
+  clientsock->next = NULL;
+  newsock->conn = clientsock;
+  clientsock->conn = newsock;
+  clientsock->state = SS_CONNECTED;
+  newsock->state = SS_CONNECTED;
+  unix_data_ref(UN_DATA(clientsock));
+  UN_DATA(newsock)->peerupd           = UN_DATA(clientsock);
+  UN_DATA(newsock)->sockaddr_un        = UN_DATA(sock)->sockaddr_un;
+  UN_DATA(newsock)->sockaddr_len       = UN_DATA(sock)->sockaddr_len;
+  wake_up(clientsock->wait);
+  return(0);
 }
 
 
-/*
- *     Gets the current name or the name of the connected socket. 
- */
-static int unix_proto_getname(struct socket *sock, struct sockaddr *usockaddr,
-       int *usockaddr_len, int peer)
+/* Gets the current name or the name of the connected socket. */
+static int
+unix_proto_getname(struct socket *sock, struct sockaddr *usockaddr,
+                  int *usockaddr_len, int peer)
 {
-       struct unix_proto_data *upd;
-       int len;
-       int er;
-
-       dprintf(1, "UNIX: getname: socket 0x%x for %s\n", sock, peer?"peer":"self");
-       if (peer) 
-       {
-               if (sock->state != SS_CONNECTED) 
-               {
-                       dprintf(1, "UNIX: getname: socket not connected\n");
-                       return(-EINVAL);
-               }
-               upd = UN_DATA(sock->conn);
-       } 
-       else
-               upd = UN_DATA(sock);
-
-       er=verify_area(VERIFY_WRITE, usockaddr_len, sizeof(*usockaddr_len));
-       if(er)
-               return er;
-       if ((len = get_fs_long(usockaddr_len)) <= 0) 
-               return(-EINVAL);
-       if (len > upd->sockaddr_len) 
-               len = upd->sockaddr_len;
-       if (len) 
-       {
-               er=verify_area(VERIFY_WRITE, usockaddr, len);
-               if(er)
-                       return er;
-               memcpy_tofs(usockaddr, &upd->sockaddr_un, len);
-       }
-       put_fs_long(len, usockaddr_len);
-       return(0);
+  struct unix_proto_data *upd;
+  int len;
+  int er;
+
+  dprintf(1, "UNIX: getname: socket 0x%x for %s\n", sock, peer?"peer":"self");
+  if (peer) {
+       if (sock->state != SS_CONNECTED) {
+               dprintf(1, "UNIX: getname: socket not connected\n");
+               return(-EINVAL);
+       }
+       upd = UN_DATA(sock->conn);
+  } else
+       upd = UN_DATA(sock);
+
+  er=verify_area(VERIFY_WRITE, usockaddr_len, sizeof(*usockaddr_len));
+  if(er)
+       return er;
+  if ((len = get_fs_long(usockaddr_len)) <= 0) return(-EINVAL);
+  if (len > upd->sockaddr_len) len = upd->sockaddr_len;
+  if (len) {
+       er=verify_area(VERIFY_WRITE, usockaddr, len);
+       if(er)
+               return er;
+       memcpy_tofs(usockaddr, &upd->sockaddr_un, len);
+  }
+  put_fs_long(len, usockaddr_len);
+  return(0);
 }
 
 
 /* We read from our own buf. */
+static int
+unix_proto_read(struct socket *sock, char *ubuf, int size, int nonblock)
+{
+  struct unix_proto_data *upd;
+  int todo, avail;
+  int er;
+
+  if ((todo = size) <= 0) return(0);
+  upd = UN_DATA(sock);
+  while(!(avail = UN_BUF_AVAIL(upd))) {
+       if (sock->state != SS_CONNECTED) {
+               dprintf(1, "UNIX: read: socket not connected\n");
+               return((sock->state == SS_DISCONNECTING) ? 0 : -EINVAL);
+       }
+       dprintf(1, "UNIX: read: no data available...\n");
+       if (nonblock) return(-EAGAIN);
+       interruptible_sleep_on(sock->wait);
+       if (current->signal & ~current->blocked) {
+               dprintf(1, "UNIX: read: interrupted\n");
+               return(-ERESTARTSYS);
+       }
+  }
+
+  /*
+   * Copy from the read buffer into the user's buffer,
+   * watching for wraparound. Then we wake up the writer.
+   */
+  do {
+       int part, cando;
+
+       if (avail <= 0) {
+               printk("UNIX: read: AVAIL IS NEGATIVE!!!\n");
+               send_sig(SIGKILL, current, 1);
+               return(-EPIPE);
+       }
 
-static int unix_proto_read(struct socket *sock, char *ubuf, int size, int nonblock)
-{
-       struct unix_proto_data *upd;
-       int todo, avail;
-       int er;
-
-       if ((todo = size) <= 0) 
-               return(0);
-       upd = UN_DATA(sock);
-       while(!(avail = UN_BUF_AVAIL(upd))) 
-       {
-               if (sock->state != SS_CONNECTED) 
-               {
-                       dprintf(1, "UNIX: read: socket not connected\n");
-                       return((sock->state == SS_DISCONNECTING) ? 0 : -EINVAL);
-               }
-               dprintf(1, "UNIX: read: no data available...\n");
-               if (nonblock) 
-                       return(-EAGAIN);
-               interruptible_sleep_on(sock->wait);
-               if (current->signal & ~current->blocked) 
-               {
-                       dprintf(1, "UNIX: read: interrupted\n");
-                       return(-ERESTARTSYS);
-               }
-       }
-
-       /*
-        * Copy from the read buffer into the user's buffer,
-        * watching for wraparound. Then we wake up the writer.
-        */
-
-       do 
-       {
-               int part, cando;
-       
-               if (avail <= 0) 
-               {
-                       printk("UNIX: read: AVAIL IS NEGATIVE!!!\n");
-                       send_sig(SIGKILL, current, 1);
-                       return(-EPIPE);
-               }
-
-               if ((cando = todo) > avail) 
-                       cando = avail;
-               if (cando >(part = BUF_SIZE - upd->bp_tail)) 
-                       cando = part;
-       
-               dprintf(1, "UNIX: read: avail=%d, todo=%d, cando=%d\n",
-                       avail, todo, cando);
-               
-               if((er=verify_area(VERIFY_WRITE,ubuf,cando))<0)
-                       return er;
-       
-               memcpy_tofs(ubuf, upd->buf + upd->bp_tail, cando);
-               upd->bp_tail =(upd->bp_tail + cando) &(BUF_SIZE-1);
-               ubuf += cando;
-               todo -= cando;
-       
-               if (sock->state == SS_CONNECTED) 
-                       wake_up(sock->conn->wait);
-               avail = UN_BUF_AVAIL(upd);
-       } 
-       while(todo && avail);
-       return(size - todo);
+       if ((cando = todo) > avail) cando = avail;
+       if (cando >(part = BUF_SIZE - upd->bp_tail)) cando = part;
+       dprintf(1, "UNIX: read: avail=%d, todo=%d, cando=%d\n",
+                                               avail, todo, cando);
+       if((er=verify_area(VERIFY_WRITE,ubuf,cando))<0)
+               return er;
+       memcpy_tofs(ubuf, upd->buf + upd->bp_tail, cando);
+       upd->bp_tail =(upd->bp_tail + cando) &(BUF_SIZE-1);
+       ubuf += cando;
+       todo -= cando;
+       if (sock->state == SS_CONNECTED) wake_up(sock->conn->wait);
+       avail = UN_BUF_AVAIL(upd);
+  } while(todo && avail);
+  return(size - todo);
 }
 
 
@@ -684,308 +629,274 @@ static int unix_proto_read(struct socket *sock, char *ubuf, int size, int nonblo
  * peer so we are safe that the buffer remains, even after the
  * peer has disconnected, which we check other ways.
  */
-static int unix_proto_write(struct socket *sock, char *ubuf, int size, int nonblock)
-{
-       struct unix_proto_data *pupd;
-       int todo, space;
-       int er;
-
-       if ((todo = size) <= 0)
-               return(0);
-       if (sock->state != SS_CONNECTED) 
-       {
-               dprintf(1, "UNIX: write: socket not connected\n");
-               if (sock->state == SS_DISCONNECTING) 
-               {
-                       send_sig(SIGPIPE, current, 1);
-                       return(-EPIPE);
-               }
-               return(-EINVAL);
-       }
-       pupd = UN_DATA(sock)->peerupd;  /* safer than sock->conn */
-
-       while(!(space = UN_BUF_SPACE(pupd))) 
-       {
-               dprintf(1, "UNIX: write: no space left...\n");
-               if (nonblock)
-                       return(-EAGAIN);
-               interruptible_sleep_on(sock->wait);
-               if (current->signal & ~current->blocked) 
-               {
-                       dprintf(1, "UNIX: write: interrupted\n");
-                       return(-ERESTARTSYS);
-               }
-               if (sock->state == SS_DISCONNECTING) 
-               {
-                       dprintf(1, "UNIX: write: disconnected(SIGPIPE)\n");
-                       send_sig(SIGPIPE, current, 1);
-                       return(-EPIPE);
-               }
-       }
-
-       /*
-        * Copy from the user's buffer to the write buffer,
-        * watching for wraparound. Then we wake up the reader.
-        */
-  
-       do 
-       {
-               int part, cando;
-
-               if (space <= 0) 
-               {
-                       printk("UNIX: write: SPACE IS NEGATIVE!!!\n");
-                       send_sig(SIGKILL, current, 1);
-                       return(-EPIPE);
-               }
+static int
+unix_proto_write(struct socket *sock, char *ubuf, int size, int nonblock)
+{
+  struct unix_proto_data *pupd;
+  int todo, space;
+  int er;
+
+  if ((todo = size) <= 0) return(0);
+  if (sock->state != SS_CONNECTED) {
+       dprintf(1, "UNIX: write: socket not connected\n");
+       if (sock->state == SS_DISCONNECTING) {
+               send_sig(SIGPIPE, current, 1);
+               return(-EPIPE);
+       }
+       return(-EINVAL);
+  }
+  pupd = UN_DATA(sock)->peerupd;       /* safer than sock->conn */
+
+  while(!(space = UN_BUF_SPACE(pupd))) {
+       dprintf(1, "UNIX: write: no space left...\n");
+       if (nonblock) return(-EAGAIN);
+       interruptible_sleep_on(sock->wait);
+       if (current->signal & ~current->blocked) {
+               dprintf(1, "UNIX: write: interrupted\n");
+               return(-ERESTARTSYS);
+       }
+       if (sock->state == SS_DISCONNECTING) {
+               dprintf(1, "UNIX: write: disconnected(SIGPIPE)\n");
+               send_sig(SIGPIPE, current, 1);
+               return(-EPIPE);
+       }
+  }
+
+  /*
+   * Copy from the user's buffer to the write buffer,
+   * watching for wraparound. Then we wake up the reader.
+   */
+  do {
+       int part, cando;
+
+       if (space <= 0) {
+               printk("UNIX: write: SPACE IS NEGATIVE!!!\n");
+               send_sig(SIGKILL, current, 1);
+               return(-EPIPE);
+       }
 
-               /*
-                * We may become disconnected inside this loop, so watch
-                * for it (peerupd is safe until we close).
-                */
-       
-               if (sock->state == SS_DISCONNECTING) 
-               {
-                       send_sig(SIGPIPE, current, 1);
-                       return(-EPIPE);
-               }
-               if ((cando = todo) > space) 
-                       cando = space;
-       
-               if (cando >(part = BUF_SIZE - pupd->bp_head)) 
-                       cando = part;
-
-               dprintf(1, "UNIX: write: space=%d, todo=%d, cando=%d\n",
-                       space, todo, cando);
-       
-               er=verify_area(VERIFY_READ, ubuf, cando);
-               if(er)
-                       return er;
-               memcpy_fromfs(pupd->buf + pupd->bp_head, ubuf, cando);
-               pupd->bp_head =(pupd->bp_head + cando) &(BUF_SIZE-1);
-               
-               ubuf += cando;
-               todo -= cando;
-               
-               if (sock->state == SS_CONNECTED) 
-                       wake_up(sock->conn->wait);
-               space = UN_BUF_SPACE(pupd);
-       } 
-       while(todo && space);
-       return(size - todo);
+       /*
+        * We may become disconnected inside this loop, so watch
+        * for it (peerupd is safe until we close).
+        */
+       if (sock->state == SS_DISCONNECTING) {
+               send_sig(SIGPIPE, current, 1);
+               return(-EPIPE);
+       }
+       if ((cando = todo) > space) cando = space;
+       if (cando >(part = BUF_SIZE - pupd->bp_head)) cando = part;
+       dprintf(1, "UNIX: write: space=%d, todo=%d, cando=%d\n",
+                                               space, todo, cando);
+       er=verify_area(VERIFY_READ, ubuf, cando);
+       if(er)
+               return er;
+       memcpy_fromfs(pupd->buf + pupd->bp_head, ubuf, cando);
+       pupd->bp_head =(pupd->bp_head + cando) &(BUF_SIZE-1);
+       ubuf += cando;
+       todo -= cando;
+       if (sock->state == SS_CONNECTED) wake_up(sock->conn->wait);
+       space = UN_BUF_SPACE(pupd);
+  } while(todo && space);
+  return(size - todo);
 }
 
 
-static int unix_proto_select(struct socket *sock, int sel_type, select_table * wait)
+static int
+unix_proto_select(struct socket *sock, int sel_type, select_table * wait)
 {
-       struct unix_proto_data *upd, *peerupd;
-
-       /* Handle server sockets specially. */
-       if (sock->flags & SO_ACCEPTCON) 
-       {
-               if (sel_type == SEL_IN) 
-               {
-                       dprintf(1, "UNIX: select: %sconnections pending\n",
-                               sock->iconn ? "" : "no ");
-                       if (sock->iconn) 
-                               return(1);
-                       select_wait(sock->wait, wait);
-                       return(sock->iconn ? 1 : 0);
-               }
-               dprintf(1, "UNIX: select: nothing else for server socket\n");
+  struct unix_proto_data *upd, *peerupd;
+
+  /* Handle server sockets specially. */
+  if (sock->flags & SO_ACCEPTCON) {
+       if (sel_type == SEL_IN) {
+               dprintf(1, "UNIX: select: %sconnections pending\n",
+                                               sock->iconn ? "" : "no ");
+               if (sock->iconn) return(1);
                select_wait(sock->wait, wait);
-               return(0);
-       }
-
-       if (sel_type == SEL_IN) 
-       {
-               upd = UN_DATA(sock);
-               dprintf(1, "UNIX: select: there is%s data available\n",
-                       UN_BUF_AVAIL(upd) ? "" : " no");
-               if (UN_BUF_AVAIL(upd))  /* even if disconnected */
-                       return(1);
-               else if (sock->state != SS_CONNECTED) 
-               {
-                       dprintf(1, "UNIX: select: socket not connected(read EOF)\n");
-                       return(1);
-               }
-               select_wait(sock->wait,wait);
-               return(0);
-       }
-       if (sel_type == SEL_OUT) 
-       {
-               if (sock->state != SS_CONNECTED) 
-               {
-                       dprintf(1, "UNIX: select: socket not connected(write EOF)\n");
-                       return(1);
-               }
-               peerupd = UN_DATA(sock->conn);
-               dprintf(1, "UNIX: select: there is%s space available\n",
-                       UN_BUF_SPACE(peerupd) ? "" : " no");
-               if (UN_BUF_SPACE(peerupd) > 0) 
+               return(sock->iconn ? 1 : 0);
+       }
+       dprintf(1, "UNIX: select: nothing else for server socket\n");
+       select_wait(sock->wait, wait);
+       return(0);
+  }
+
+  if (sel_type == SEL_IN) {
+       upd = UN_DATA(sock);
+       dprintf(1, "UNIX: select: there is%s data available\n",
+                                               UN_BUF_AVAIL(upd) ? "" : " no");
+       if (UN_BUF_AVAIL(upd))  /* even if disconnected */
                        return(1);
-               select_wait(sock->wait,wait);
-               return(0);
-       }
-
-       /* SEL_EX */
-       dprintf(1, "UNIX: select: there are no exceptions here?!\n");
-       return(0);
+       else if (sock->state != SS_CONNECTED) {
+               dprintf(1, "UNIX: select: socket not connected(read EOF)\n");
+               return(1);
+       }
+       select_wait(sock->wait,wait);
+       return(0);
+  }
+  if (sel_type == SEL_OUT) {
+       if (sock->state != SS_CONNECTED) {
+               dprintf(1, "UNIX: select: socket not connected(write EOF)\n");
+               return(1);
+       }
+       peerupd = UN_DATA(sock->conn);
+       dprintf(1, "UNIX: select: there is%s space available\n",
+                                       UN_BUF_SPACE(peerupd) ? "" : " no");
+       if (UN_BUF_SPACE(peerupd) > 0) return(1);
+       select_wait(sock->wait,wait);
+       return(0);
+  }
+
+  /* SEL_EX */
+  dprintf(1, "UNIX: select: there are no exceptions here?!\n");
+  return(0);
 }
 
 
-static int unix_proto_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+static int
+unix_proto_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 {
-       struct unix_proto_data *upd, *peerupd;
-       int er;
-
-       upd = UN_DATA(sock);
-       peerupd = (sock->state == SS_CONNECTED) ? UN_DATA(sock->conn) : NULL;
-
-       switch(cmd) 
-       {
-               case TIOCINQ:
-                       if (sock->flags & SO_ACCEPTCON) 
-                               return(-EINVAL);
-                       er=verify_area(VERIFY_WRITE,(void *)arg, sizeof(unsigned long));
-                       if(er)
-                               return er;
-                       if (UN_BUF_AVAIL(upd) || peerupd)
-                               put_fs_long(UN_BUF_AVAIL(upd),(unsigned long *)arg);
-                       else
-                               put_fs_long(0,(unsigned long *)arg);
-                       break;
-               case TIOCOUTQ:
-                       if (sock->flags & SO_ACCEPTCON) 
-                               return(-EINVAL);
-                       er=verify_area(VERIFY_WRITE,(void *)arg, sizeof(unsigned long));
-                       if(er)
-                               return er;
-                       if (peerupd) 
-                               put_fs_long(UN_BUF_SPACE(peerupd), (unsigned long *)arg);
-                       else
-                               put_fs_long(0,(unsigned long *)arg);
-                       break;
-               default:
-                       return(-EINVAL);
-       }
-       return(0);
+  struct unix_proto_data *upd, *peerupd;
+  int er;
+
+  upd = UN_DATA(sock);
+  peerupd = (sock->state == SS_CONNECTED) ? UN_DATA(sock->conn) : NULL;
+
+  switch(cmd) {
+       case TIOCINQ:
+               if (sock->flags & SO_ACCEPTCON) return(-EINVAL);
+               er=verify_area(VERIFY_WRITE,(void *)arg, sizeof(unsigned long));
+               if(er)
+                       return er;
+               if (UN_BUF_AVAIL(upd) || peerupd)
+                       put_fs_long(UN_BUF_AVAIL(upd),(unsigned long *)arg);
+                 else
+                       put_fs_long(0,(unsigned long *)arg);
+               break;
+       case TIOCOUTQ:
+               if (sock->flags & SO_ACCEPTCON) return(-EINVAL);
+               er=verify_area(VERIFY_WRITE,(void *)arg, sizeof(unsigned long));
+               if(er)
+                       return er;
+               if (peerupd) put_fs_long(UN_BUF_SPACE(peerupd),
+                                               (unsigned long *)arg);
+                 else
+                       put_fs_long(0,(unsigned long *)arg);
+               break;
+       default:
+               return(-EINVAL);
+  }
+  return(0);
 }
 
 
-static int unix_open(struct inode * inode, struct file * file)
+static int
+unix_open(struct inode * inode, struct file * file)
 {
-       int minor;
+  int minor;
 
-       dprintf(1, "UNIX: open\n");
-       minor = MINOR(inode->i_rdev);
-       
-       if (minor != 0) 
-               return(-ENODEV);
+  dprintf(1, "UNIX: open\n");
+  minor = MINOR(inode->i_rdev);
+  if (minor != 0) return(-ENODEV);
 
-       return(0);
+  return(0);
 }
 
 
-static void unix_close(struct inode * inode, struct file * file)
+static void
+unix_close(struct inode * inode, struct file * file)
 {
-       dprintf(1, "UNIX: close\n");
+  dprintf(1, "UNIX: close\n");
 }
 
 
-static int unix_ioctl(struct inode *inode, struct file *file,
-       unsigned int cmd, unsigned long arg)
+static int
+unix_ioctl(struct inode *inode, struct file *file,
+        unsigned int cmd, unsigned long arg)
 {
-       int minor, ret;
-       int er;
-
-       dprintf(1, "UNIX: ioctl(0x%X, 0x%X)\n", cmd, arg);
-       minor = MINOR(inode->i_rdev);
-
-       if (minor != 0) 
-               return(-ENODEV);
-
-       ret = -EINVAL;
-       switch(cmd) 
-       {
-               case DDIOCSDBG:
-                       er=verify_area(VERIFY_READ,(void *)arg, sizeof(int));
-                       if(er)
-                               return er;
-                       unix_debug = get_fs_long((int *)arg);
-                       if (unix_debug != 0 && unix_debug != 1) 
-                       {
-                               unix_debug = 0;
-                               return(-EINVAL);
-                       }
-                       return(0);
-               case SIOCSIFLINK:
-                       printk("UNIX: cannot link streams!\n");
-                       break;
-               default:
-                       break;
-       }
-       return(ret);
+  int minor, ret;
+  int er;
+
+  dprintf(1, "UNIX: ioctl(0x%X, 0x%X)\n", cmd, arg);
+  minor = MINOR(inode->i_rdev);
+  if (minor != 0) return(-ENODEV);
+
+  ret = -EINVAL;
+  switch(cmd) {
+       case DDIOCSDBG:
+               er=verify_area(VERIFY_READ,(void *)arg, sizeof(int));
+               if(er)
+                       return er;
+               unix_debug = get_fs_long((int *)arg);
+               if (unix_debug != 0 && unix_debug != 1) {
+                       unix_debug = 0;
+                       return(-EINVAL);
+               }
+               return(0);
+       case SIOCSIFLINK:
+               printk("UNIX: cannot link streams!\n");
+               break;
+       default:
+               break;
+  }
+  return(ret);
 }
 
 
-static struct file_operations unix_fops = 
-{
-       NULL,           /* LSEEK        */
-       NULL,           /* READ         */
-       NULL,           /* WRITE        */
-       NULL,           /* READDIR      */
-       NULL,           /* SELECT       */
-       unix_ioctl,     /* IOCTL        */
-       NULL,           /* MMAP         */
-       unix_open,      /* OPEN         */
-       unix_close      /* CLOSE        */
+static struct file_operations unix_fops = {
+  NULL,                /* LSEEK        */
+  NULL,                /* READ         */
+  NULL,                /* WRITE        */
+  NULL,                /* READDIR      */
+  NULL,                /* SELECT       */
+  unix_ioctl,  /* IOCTL        */
+  NULL,                /* MMAP         */
+  unix_open,   /* OPEN         */
+  unix_close   /* CLOSE        */
 };
 
 
 static struct proto_ops unix_proto_ops = {
-       AF_UNIX,
-       unix_proto_create,
-       unix_proto_dup,
-       unix_proto_release,
-       unix_proto_bind,
-       unix_proto_connect,
-       unix_proto_socketpair,
-       unix_proto_accept,
-       unix_proto_getname,
-       unix_proto_read,
-       unix_proto_write,
-       unix_proto_select,
-       unix_proto_ioctl,
-       unix_proto_listen,
-       unix_proto_send,
-       unix_proto_recv,
-       unix_proto_sendto,
-       unix_proto_recvfrom,
-       unix_proto_shutdown,
-       unix_proto_setsockopt,
-       unix_proto_getsockopt,
-       NULL                            /* unix_proto_fcntl     */
+  AF_UNIX,
+  unix_proto_create,
+  unix_proto_dup,
+  unix_proto_release,
+  unix_proto_bind,
+  unix_proto_connect,
+  unix_proto_socketpair,
+  unix_proto_accept,
+  unix_proto_getname,
+  unix_proto_read,
+  unix_proto_write,
+  unix_proto_select,
+  unix_proto_ioctl,
+  unix_proto_listen,
+  unix_proto_send,
+  unix_proto_recv,
+  unix_proto_sendto,
+  unix_proto_recvfrom,
+  unix_proto_shutdown,
+  unix_proto_setsockopt,
+  unix_proto_getsockopt,
+  NULL                         /* unix_proto_fcntl     */
 };
 
 
-void unix_proto_init(struct ddi_proto *pro)
+void
+unix_proto_init(struct ddi_proto *pro)
 {
-       struct unix_proto_data *upd;
-
-       dprintf(1, "%s: init: initializing...\n", pro->name);
-       if (register_chrdev(AF_UNIX_MAJOR, "af_unix", &unix_fops) < 0) 
-       {
-               printk("%s: cannot register major device %d!\n",
-                       pro->name, AF_UNIX_MAJOR);
-               return;
-       }
-
-       /* Tell SOCKET that we are alive... */
-       (void) sock_register(unix_proto_ops.family, &unix_proto_ops);
-
-       for(upd = unix_datas; upd <= last_unix_data; ++upd) 
-       {
-               upd->refcnt = 0;
-       }
+  struct unix_proto_data *upd;
+
+  dprintf(1, "%s: init: initializing...\n", pro->name);
+  if (register_chrdev(AF_UNIX_MAJOR, "af_unix", &unix_fops) < 0) {
+       printk("%s: cannot register major device %d!\n",
+                                               pro->name, AF_UNIX_MAJOR);
+       return;
+  }
+
+  /* Tell SOCKET that we are alive... */
+  (void) sock_register(unix_proto_ops.family, &unix_proto_ops);
+
+  for(upd = unix_datas; upd <= last_unix_data; ++upd) {
+       upd->refcnt = 0;
+  }
 }