]> git.neil.brown.name Git - history.git/commitdiff
Linux 2.1.100pre1 2.1.100pre1
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:15:22 +0000 (15:15 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:15:22 +0000 (15:15 -0500)
pre-100 (on ftp.kernel.org now), moves the dcache shrinking into the regular
memory de-allocation loop, and while the exact shrinking speed is probably
completely off, it should be able to react much better to small-memory machines
than the hardcoded shrink did..

Also, for those that appear to still have SMP interrupt stability
problems, Ingo pointed out that we may have problems with PCI
level-triggered interrupts. Could those people please test an additional
small patch that involves moving the "ack_APIC_irq();" inside
arch/i386/kernel/irq.c: do_ioapic_IRQ() from the top of the function to
the very bottom of that function (that will move it to outside the irq
controller lock, but it should actually be perfectly ok in this case).

                Linus

32 files changed:
Documentation/filesystems/vfs.txt
Makefile
drivers/net/sdla_fr.c
drivers/net/sdla_x25.c
drivers/net/sdlamain.c
drivers/net/smc-mca.c
drivers/scsi/scsi_ioctl.c
drivers/scsi/sd.c
fs/dcache.c
fs/namei.c
include/linux/icmpv6.h
include/linux/ipv6.h
include/net/ipv6.h
include/net/ndisc.h
include/net/tcp.h
include/scsi/scsi_ioctl.h
mm/vmscan.c
net/core/dev.c
net/ethernet/pe2.c
net/ipv4/ip_fw.c
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_timer.c
net/ipv6/exthdrs.c
net/ipv6/icmp.c
net/ipv6/ip6_input.c
net/ipv6/ipv6_sockglue.c
net/ipv6/mcast.c
net/ipv6/ndisc.c
net/ipv6/reassembly.c
net/ipv6/tcp_ipv6.c
net/netsyms.c

index 7f75f4770de187c49ade9758697c0162982cf310..9dfe8dc27c31261b65033267393abf1de1e8ac36 100644 (file)
@@ -10,7 +10,6 @@ pages of code to determine what is expected when writing a filesystem.
 Hopefully this helps anyone attempting such a feat, as well as clearing up
 a few important points/dependencies.
 
-
 register_filesystem (struct file_system_type *fstype)
 =====================================================
 
@@ -133,10 +132,12 @@ struct inode_operations
 
        int (*follow_link) (struct inode *,struct inode *,int,int,struct inode **);
        [optional]
-               The follow_link function is only necessary if a filesystem uses a really
-               twisted form of symbolic links - namely if the symbolic link comes from a
-               foreign filesystem that makes no sense....
-               I threw this one out - too much redundant code!
+               follow_link must be implemented if readlink is implemented.
+               Note that follow_link can return a different inode than a
+               lookup_dentry() on the result of readlink() would return.
+               The proc filesystem, in particular, uses this feature heavily.
+               For most user filesystems, however, follow_link() and readlink()
+               should return consistent results.
 
        int (*readpage) (struct inode *, struct page *);        [optional]
        int (*writepage) (struct inode *, struct page *);       [mandatory with readpage]
index 1586e862d0f092411049b860ca9c3c8fcb396efa..ebbc501a129d4790771a5adcf41f9f4bb60a3791 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 1
-SUBLEVEL = 99
+SUBLEVEL = 100
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/)
 
index 79bd5d4ca0a2446fd941633f58e36f9b89f82ae2..36b74b90e3ca032887fce582e969f7eacbabfb04 100644 (file)
@@ -831,7 +831,7 @@ static int if_header(struct sk_buff *skb, struct device *dev,
 {
        int hdr_len = 0;
        skb->protocol = type;
-       hdr_len = wan_encapsulate(skb, dev);
+       hdr_len = wanrouter_encapsulate(skb, dev);
        if (hdr_len < 0) 
        {
                hdr_len = 0;
@@ -1486,7 +1486,7 @@ static void fr502_rx_intr(sdla_t * card)
                /* Decapsulate packet and pass it up the protocol stack */
                skb->dev = dev;
                buf = skb_pull(skb, 1);         /* remove hardware header */
-               if (!wan_type_trans(skb, dev)) 
+               if (!wanrouter_type_trans(skb, dev)) 
                {
                        /* can't decapsulate packet */
                        dev_kfree_skb(skb);
@@ -1601,7 +1601,7 @@ static void fr508_rx_intr(sdla_t * card)
                                        skb->dev = dev;
                                        /* remove hardware header */
                                        buf = skb_pull(skb, 1);
-                                       if (!wan_type_trans(skb, dev)) 
+                                       if (!wanrouter_type_trans(skb, dev)) 
                                        {
                                                /* can't decapsulate packet */
                                                dev_kfree_skb(skb);
@@ -2746,7 +2746,7 @@ static int process_udp_mgmt_pkt(char udp_pkt_src, sdla_t * card, struct sk_buff
                           stack */
                        new_skb->dev = dev;
                        buf = skb_pull(new_skb, 1);     /* remove hardware header */
-                       if (!wan_type_trans(new_skb, dev)) 
+                       if (!wanrouter_type_trans(new_skb, dev)) 
                        {
                                ++chan->UDP_FPIPE_mgmt_not_passed_to_stack;
                                /* can't decapsulate packet */
@@ -2944,7 +2944,7 @@ static int process_udp_driver_call(char udp_pkt_src, sdla_t * card, struct sk_bu
                        new_skb->dev = dev;
                        /* remove hardware header */
                        buf = skb_pull(new_skb, 1);
-                       if (!wan_type_trans(new_skb, dev)) 
+                       if (!wanrouter_type_trans(new_skb, dev)) 
                        {
                                /* can't decapsulate packet */
                                ++chan->UDP_DRVSTATS_mgmt_not_passed_to_stack;
index 6a1759040bc3c8ae675680eda2243929bd12f31d..af7d318443bfbe7b79ee1a38bdb76a53912c5a0c 100644 (file)
@@ -649,7 +649,7 @@ static int if_header (struct sk_buff* skb, struct device* dev,
        skb->protocol = type;
        if (!chan->protocol)
        {
-               hdr_len = wan_encapsulate(skb, dev);
+               hdr_len = wanrouter_encapsulate(skb, dev);
                if (hdr_len < 0)
                {
                        hdr_len = 0;
@@ -999,7 +999,7 @@ static void rx_intr (sdla_t* card)
        chan->rx_skb = NULL;            /* dequeue packet */
 
        /* Decapsulate packet, if necessary */
-       if (!skb->protocol && !wan_type_trans(skb, dev))
+       if (!skb->protocol && !wanrouter_type_trans(skb, dev))
        {
                /* can't decapsulate packet */
                dev_kfree_skb(skb);
index eed8c9f366c6137552529e5e80edf6f645eae0b7..44fabaecb2cf5db27b9f329e1a495ed2ba2ceb62 100644 (file)
@@ -152,7 +152,7 @@ int init_module (void)
                wandev->setup    = &setup;
                wandev->shutdown = &shutdown;
                wandev->ioctl    = &ioctl;
-               err = register_wandev(wandev);
+               err = register_wan_device(wandev);
                if (err)
                {
                        printk(KERN_ERR
@@ -179,7 +179,7 @@ void cleanup_module (void)
        for (i = 0; i < ncards; ++i)
        {
                sdla_t* card = &card_array[i];
-               unregister_wandev(card->devname);
+               unregister_wan_device(card->devname);
        }
        kfree(card_array);
 }
index 79d6d8076853ab04e516792eb75beb71afa43908..152beacbc930b36ed5edb39da35673d448c487c0 100644 (file)
@@ -337,7 +337,7 @@ int init_module(void)
                dev->name = namelist+(NAMELEN*this_dev);
                dev->irq = irq[this_dev];
                dev->base_addr = io[this_dev];
-               dev->init = ultra_probe;
+               dev->init = ultramca_probe;
                if (io[this_dev] == 0)
                {
                        if (this_dev != 0)
index a052caadfe9b849feb3101592d5f25b7fbce4689..e2f933fb3c5d087851e9d4b9d578a29d482e6a59 100644 (file)
 #include "hosts.h"
 #include <scsi/scsi_ioctl.h>
 
-#define MAX_RETRIES 5   
-#define MAX_TIMEOUT (9 * HZ)
+#define NORMAL_RETRIES 5   
+#define NORMAL_TIMEOUT (10 * HZ)
+#define FORMAT_UNIT_TIMEOUT (2 * 60 * 60 * HZ)
+#define START_STOP_TIMEOUT (60 * HZ)
+#define MOVE_MEDIUM_TIMEOUT (5 * 60 * HZ)
+#define READ_ELEMENT_STATUS_TIMEOUT (5 * 60 * HZ)
+
 #define MAX_BUF PAGE_SIZE
 
 #define max(a,b) (((a) > (b)) ? (a) : (b))
@@ -61,7 +66,7 @@ static int ioctl_probe(struct Scsi_Host * host, void *buffer)
 /*
  * 
  * The SCSI_IOCTL_SEND_COMMAND ioctl sends a command out to the SCSI host.
- * The MAX_TIMEOUT and MAX_RETRIES  variables are used.  
+ * The NORMAL_TIMEOUT and NORMAL_RETRIES  variables are used.  
  * 
  * dev is the SCSI device struct ptr, *(int *) arg is the length of the
  * input data, if any, not including the command string & counts, 
@@ -94,7 +99,8 @@ static void scsi_ioctl_done (Scsi_Cmnd * SCpnt)
     }
 }   
 
-static int ioctl_internal_command(Scsi_Device *dev, char * cmd)
+static int ioctl_internal_command(Scsi_Device *dev, char * cmd,
+                                 int timeout, int retries)
 {
     unsigned long flags;
     int result;
@@ -107,9 +113,7 @@ static int ioctl_internal_command(Scsi_Device *dev, char * cmd)
        struct semaphore sem = MUTEX_LOCKED;
        SCpnt->request.sem = &sem;
        spin_lock_irqsave(&io_request_lock, flags);
-       scsi_do_cmd(SCpnt,  cmd, NULL,  0,
-                   scsi_ioctl_done,  MAX_TIMEOUT,
-                   MAX_RETRIES);
+       scsi_do_cmd(SCpnt,  cmd, NULL,  0, scsi_ioctl_done,  timeout, retries);
        spin_unlock_irqrestore(&io_request_lock, flags);
        down(&sem);
         SCpnt->request.sem = NULL;
@@ -250,21 +254,24 @@ int scsi_ioctl_send_command(Scsi_Device *dev, Scsi_Ioctl_Command *sic)
     switch (opcode)
       {
       case FORMAT_UNIT:
-       timeout =  2 * 60 * 60 * HZ; /* 2 Hours */
+       timeout = FORMAT_UNIT_TIMEOUT;
        retries = 1;
        break;
       case START_STOP:
-       timeout =  2 * 60 * HZ; /* 2 minutes */
-       retries = 1;
+       timeout = START_STOP_TIMEOUT;
+       retries = NORMAL_RETRIES;
        break;
       case MOVE_MEDIUM:
+       timeout = MOVE_MEDIUM_TIMEOUT;
+       retries = NORMAL_RETRIES;
+       break;
       case READ_ELEMENT_STATUS:
-       timeout =  5 * 60 * HZ; /* 5 minutes */
-       retries = 1;
+       timeout = READ_ELEMENT_STATUS_TIMEOUT;
+       retries = NORMAL_RETRIES;
        break;
       default:
-       timeout = MAX_TIMEOUT;
-       retries = MAX_RETRIES;
+       timeout = NORMAL_TIMEOUT;
+       retries = NORMAL_RETRIES;
        break;
       }
 
@@ -395,7 +402,8 @@ int scsi_ioctl (Scsi_Device *dev, int cmd, void *arg)
        scsi_cmd[1] = dev->lun << 5;
        scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
        scsi_cmd[4] = SCSI_REMOVAL_PREVENT;
-       return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd);
+       return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd,
+                                     NORMAL_TIMEOUT, NORMAL_RETRIES);
        break;
     case SCSI_IOCTL_DOORUNLOCK:
        if (!dev->removable || !dev->lockable) return 0;
@@ -403,13 +411,31 @@ int scsi_ioctl (Scsi_Device *dev, int cmd, void *arg)
        scsi_cmd[1] = dev->lun << 5;
        scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
        scsi_cmd[4] = SCSI_REMOVAL_ALLOW;
-       return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd);
+       return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd,
+                                     NORMAL_TIMEOUT, NORMAL_RETRIES);
     case SCSI_IOCTL_TEST_UNIT_READY:
        scsi_cmd[0] = TEST_UNIT_READY;
        scsi_cmd[1] = dev->lun << 5;
        scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
        scsi_cmd[4] = 0;
-       return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd);
+       return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd,
+                                     NORMAL_TIMEOUT, NORMAL_RETRIES);
+       break;
+    case SCSI_IOCTL_START_UNIT:
+       scsi_cmd[0] = START_STOP;
+       scsi_cmd[1] = dev->lun << 5;
+       scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
+       scsi_cmd[4] = 1;
+       return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd,
+                                     START_STOP_TIMEOUT, NORMAL_RETRIES);
+       break;
+    case SCSI_IOCTL_STOP_UNIT:
+       scsi_cmd[0] = START_STOP;
+       scsi_cmd[1] = dev->lun << 5;
+       scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
+       scsi_cmd[4] = 0;
+       return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd,
+                                     START_STOP_TIMEOUT, NORMAL_RETRIES);
        break;
     default :           
        if (dev->host->hostt->ioctl)
index e7da5c95414a456c80b98f7b08dfa017f19169b7..ac752b2e5799b575b4a29d9c237b283a93ea04e1 100644 (file)
@@ -1060,8 +1060,15 @@ static int check_scsidisk_media_change(kdev_t full_dev){
     }
 
     inode.i_rdev = full_dev;  /* This is all we really need here */
-    retval = sd_ioctl(&inode, NULL, SCSI_IOCTL_TEST_UNIT_READY, 0);
 
+    /* Using Start/Stop enables differentiation between drive with
+     * no cartridge loaded - NOT READY, drive with changed cartridge -
+     * UNIT ATTENTION, or with same cartridge - GOOD STATUS.
+     * This also handles drives that auto spin down. eg iomega jaz 1GB
+     * as this will spin up the drive.
+     */
+    retval = sd_ioctl(&inode, NULL, SCSI_IOCTL_START_UNIT, 0);
+    
     if(retval){ /* Unable to test, unit probably not ready.  This usually
                 * means there is no disc in the drive.  Mark as changed,
                 * and we will figure it out later once the drive is
index 58c6479c91b0b050cd3558ea75dbe2f84992790a..0ef962687b27d0f41d45ea1f0863725cad4a34ba 100644 (file)
@@ -430,12 +430,17 @@ void shrink_dcache_parent(struct dentry * parent)
  * more memory, but aren't really sure how much. So we
  * carefully try to free a _bit_ of our dcache, but not
  * too much.
+ *
+ * Priority:
+ *   0 - very urgent: schrink everything
+ *  ...
+ *   6 - base-level: try to shrink a bit.
  */
-void shrink_dcache_memory(void)
+void shrink_dcache_memory(int priority, unsigned int gfp_mask)
 {
        int count = select_dcache(32, 8);
        if (count)
-               prune_dcache(count);
+               prune_dcache((count << 6) >> priority);
 }
 
 #define NAME_ALLOC_LEN(len)    ((len+16) & ~15)
index a6de99eadfa3074349b2aa71013d3f1df006f911..06257ab99c63b7f2be27e6c37b1bb970cd4c1872 100644 (file)
  *
  * The new code replaces the old recursive symlink resolution with
  * an iterative one (in case of non-nested symlink chains).  It does
- * this by looking up the symlink name from the particular filesystem,
- * and then follows this name as if it were a user-supplied one.  This
- * is done solely in the VFS level, such that <fs>_follow_link() is not
- * used any more and could be removed in future.  As a side effect,
- * dir_namei(), _namei() and follow_link() are now replaced with a single
- * function lookup_dentry() that can handle all the special cases of the former
- * code.
+ * this with calls to <fs>_follow_link().
+ * As a side effect, dir_namei(), _namei() and follow_link() are now 
+ * replaced with a single function lookup_dentry() that can handle all 
+ * the special cases of the former code.
  *
  * With the new dcache, the pathname is stored at each inode, at least as
  * long as the refcount of the inode is positive.  As a side effect, the
  * size of the dcache depends on the inode cache and thus is dynamic.
+ *
+ * [29-Apr-1998 C. Scott Ananian] Updated above description of symlink
+ * resolution to correspond with current state of the code.
+ *
+ * Note that the symlink resolution is not *completely* iterative.
+ * There is still a significant amount of tail- and mid- recursion in
+ * the algorithm.  Also, note that <fs>_readlink() is not used in
+ * lookup_dentry(): lookup_dentry() on the result of <fs>_readlink()
+ * may return different results than <fs>_follow_link().  Many virtual
+ * filesystems (including /proc) exhibit this behavior.
  */
 
 /* [24-Feb-97 T. Schoebel-Theuer] Side effects caused by new implementation:
index a582e37b58bfed99d5b165bf15746aa40275f480..fcd6fce28b89489dc7b0fd0ee8ee28709c1bde8c 100644 (file)
@@ -138,9 +138,12 @@ extern void                                icmpv6_send(struct sk_buff *skb,
                                                    __u32 info, 
                                                    struct device *dev);
 
-extern void                            icmpv6_init(struct net_proto_family *ops);
+extern int                             icmpv6_init(struct net_proto_family *ops);
 extern int                             icmpv6_err_convert(int type, int code,
                                                           int *err);
+extern void                            icmpv6_cleanup(void);
+extern void                            icmpv6_param_prob(struct sk_buff *skb,
+                                                         int code, void *pos);
 #endif
 
 #endif
index 478c8503c83a4452a31f2a7da39ee27a65bfe759..3913524180d1f658e3ce79602e539b9ecbae0f4e 100644 (file)
@@ -42,6 +42,24 @@ struct ipv6_rt_hdr {
         */
 };
 
+
+struct ipv6_opt_hdr {
+       __u8            nexthdr;
+       __u8            hdrlen;
+       /* 
+        * TLV encoded option data follows.
+        */
+};
+
+#define ipv6_destopt_hdr ipv6_opt_hdr
+#define ipv6_hopopt_hdr  ipv6_opt_hdr
+
+#ifdef __KERNEL__
+#define ipv6_optlen(p)  (((p)->hdrlen+1) << 3)
+#endif
+
+
+
 /*
  *     routing header type 0 (used in cmsghdr struct)
  */
@@ -95,13 +113,13 @@ struct ipv6_options
 
        /* 
         * protocol options 
-        * usualy carried in IPv6 extension headers
+        * usually carried in IPv6 extension headers
         */
 
        struct ipv6_rt_hdr              *srcrt; /* Routing Header */
-
 };
 
+
 #endif
 
 #endif
index 1a322a49813f9ae66252e270b2b756ef18833623..c3d2d58954ad71a3ef69854188ad0156181db33f 100644 (file)
@@ -4,7 +4,7 @@
  *     Authors:
  *     Pedro Roque             <roque@di.fc.ul.pt>
  *
- *     $Id: ipv6.h,v 1.9 1998/03/08 05:55:20 davem Exp $
+ *     $Id: ipv6.h,v 1.10 1998/04/30 16:24:14 freitag Exp $
  *
  *     This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -108,6 +108,8 @@ struct frag_queue {
        struct frag_queue       *prev;
 
        __u32                   id;             /* fragment id          */
+       struct in6_addr         saddr;
+       struct in6_addr         daddr;
        struct timer_list       timer;          /* expire timer         */
        struct ipv6_frag        *fragments;
        struct device           *dev;
@@ -248,6 +250,10 @@ extern int                 ipv6opt_srt_tosin(struct ipv6_options *opt,
 
 extern void                    ipv6opt_free(struct ipv6_options *opt);
 
+extern struct ipv6_opt_hdr *   ipv6_skip_exthdr(struct ipv6_opt_hdr *hdr, 
+                                                u8 *nexthdrp, int len);
+
+
 
 /*
  *     socket options (ipv6_sockglue.c)
index 754253811e083e5111529f5b1c94588b6be64023..adaf76ef3266b209621178de32c16042342daaef 100644 (file)
@@ -101,6 +101,8 @@ extern int                  igmp6_event_report(struct sk_buff *skb,
                                                   struct icmp6hdr *hdr,
                                                   int len);
 
+extern void                    igmp6_cleanup(void);
+
 extern __inline__ struct neighbour * ndisc_get_neigh(struct device *dev, struct in6_addr *addr)
 {
 
index 52853f44a5c107720755ca02f6ad01d74f9f2c23..ca1240b8acafa2f0347bdf0324105a705b03338f 100644 (file)
@@ -642,7 +642,7 @@ static __inline__ unsigned int tcp_current_mss(struct sock *sk)
 
                /* PMTU discovery event has occurred. */
                sk->mtu = dst->pmtu;
-               sk->mss = sk->mtu - mss_distance;
+               mss_now = sk->mss = sk->mtu - mss_distance;
        }
 
        if(tp->sack_ok && tp->num_sacks)
index 97e20a98a5ed5a5d249090fb98a5fd56dcf80cc8..6ba0dd542f936b37c36c07b2a3d46eed89a3b041 100644 (file)
@@ -5,6 +5,8 @@
 #define SCSI_IOCTL_TEST_UNIT_READY 2
 #define SCSI_IOCTL_BENCHMARK_COMMAND 3
 #define SCSI_IOCTL_SYNC 4                      /* Request synchronous parameters */
+#define SCSI_IOCTL_START_UNIT 5
+#define SCSI_IOCTL_STOP_UNIT 6
 /* The door lock/unlock constants are compatible with Sun constants for
    the cdrom */
 #define SCSI_IOCTL_DOORLOCK 0x5380             /* lock the eject mechanism */
index 8eaeb23d59e5b430d37db8a0369f7234e8374f4f..9644f6d8c39cbf314a80b635654c01112dccb656 100644 (file)
@@ -455,17 +455,20 @@ static inline int do_try_to_free_page(int gfp_mask)
        switch (state) {
                do {
                case 0:
-                       state = 1;
                        if (shrink_mmap(i, gfp_mask))
                                return 1;
+                       state = 1;
                case 1:
-                       state = 2;
                        if ((gfp_mask & __GFP_IO) && shm_swap(i, gfp_mask))
                                return 1;
-               default:
-                       state = 0;
+                       state = 2;
+               case 2:
                        if (swap_out(i, gfp_mask))
                                return 1;
+                       state = 3;
+               case 3:
+                       shrink_dcache_memory(i, gfp_mask);
+                       state = 0;
                i--;
                } while ((i - stop) >= 0);
        }
@@ -545,9 +548,6 @@ int kswapd(void *unused)
                schedule();
                swapstats.wakeups++;
 
-               /* This will gently shrink the dcache.. */
-               shrink_dcache_memory();
-       
                /*
                 * Do the background pageout: be
                 * more aggressive if we're really
index 85312b12c0e63693c640f1391f45c8065df611b5..1bb5dede15e2dd1b4af41a5ea8228e5623adff2c 100644 (file)
@@ -1764,6 +1764,9 @@ extern int baycom_init(void);
 extern int lapbeth_init(void);
 extern void arcnet_init(void);
 extern void ip_auto_config(void);
+#ifdef CONFIG_8xx
+extern int cpm_enet_init(void);
+#endif /* CONFIG_8xx */
 
 #ifdef CONFIG_PROC_FS
 static struct proc_dir_entry proc_net_dev = {
@@ -1845,6 +1848,9 @@ __initfunc(int net_dev_init(void))
 #endif
 #if defined(CONFIG_ARCNET)
        arcnet_init();
+#endif
+#if defined(CONFIG_8xx)
+        cpm_enet_init();
 #endif
        /*
         *      SLHC if present needs attaching so other people see it
index 812d3586439965cda3a68f0886a796ca1659668f..4915f07072e109d4ee08ece5515b7a0a79d5ebf4 100644 (file)
@@ -11,7 +11,8 @@ pEII_datalink_header(struct datalink_proto *dl,
        struct device   *dev = skb->dev;
 
        skb->protocol = htons (ETH_P_IPX);
-       dev->hard_header(skb, dev, ETH_P_IPX, dest_node, NULL, skb->len);
+       if(dev->hard_header)
+               dev->hard_header(skb, dev, ETH_P_IPX, dest_node, NULL, skb->len);
 }
 
 struct datalink_proto *
index 28ad5bc334bc8f72c572e6fb73a185b4368fc100..745d07cb4c7ba38962c2545676667ac177333b43 100644 (file)
@@ -6,7 +6,7 @@
  *     license in recognition of the original copyright. 
  *                             -- Alan Cox.
  *
- *     $Id: ip_fw.c,v 1.34 1998/03/20 09:12:06 davem Exp $
+ *     $Id: ip_fw.c,v 1.35 1998/04/30 16:29:51 freitag Exp $
  *
  *     Ported from BSD to Linux,
  *             Alan Cox 22/Nov/1994.
@@ -62,6 +62,7 @@
  *     Wouter Gadeyne          :       Fixed masquerading support of ftp PORT commands
  *
  *     Juan Jose Ciarlante     :       Masquerading code moved to ip_masq.c
+ *     Andi Kleen :            Print frag_offsets and the ip flags properly.
  *
  *     All the real work was done by .....
  *
@@ -202,6 +203,90 @@ extern inline int port_match(unsigned short *portptr,int nports,unsigned short p
 
 #if defined(CONFIG_IP_ACCT) || defined(CONFIG_IP_FIREWALL)
 
+#ifdef CONFIG_IP_FIREWALL_VERBOSE
+
+/* 
+ *     VERY ugly piece of code which actually makes kernel printf for
+ *     matching packets. 
+ */
+
+static char *chain_name(struct ip_fw *chain, int mode)
+{
+       switch (mode) { 
+       case IP_FW_MODE_ACCT_IN: return "acct in";
+       case IP_FW_MODE_ACCT_OUT: return "acct out";
+       default:
+               if (chain == ip_fw_fwd_chain) 
+                       return "fw-fwd";
+               else if (chain == ip_fw_in_chain)
+                       return "fw-in";
+               else
+                       return "fw-out"; 
+       }
+}
+
+static char *rule_name(struct ip_fw *f, int mode, char *buf)
+{
+       if (mode == IP_FW_MODE_ACCT_IN || mode == IP_FW_MODE_ACCT_OUT)
+               return "";
+
+       if(f->fw_flg&IP_FW_F_ACCEPT) {
+               if(f->fw_flg&IP_FW_F_REDIR) {
+                       sprintf(buf, "acc/r%d ", f->fw_pts[f->fw_nsp+f->fw_ndp]);
+                       return buf;
+               } else if(f->fw_flg&IP_FW_F_MASQ)
+                       return "acc/masq ";
+               else
+                       return "acc ";
+       } else if(f->fw_flg&IP_FW_F_ICMPRPL) {
+               return "rej ";
+       } else {
+               return "deny ";
+       }
+}
+
+static void print_packet(struct iphdr *ip, 
+                        u16 src_port, u16 dst_port, u16 icmp_type,
+                        char *chain, char *rule, char *devname)
+{
+       __u32 *opt = (__u32 *) (ip + 1);
+       int opti;
+       __u16 foff = ntohs(ip->frag_off); 
+
+       printk(KERN_INFO "IP %s %s%s", chain, rule, devname); 
+
+       switch(ip->protocol)
+       {
+       case IPPROTO_TCP:
+               printk(" TCP ");
+               break;
+       case IPPROTO_UDP:
+               printk(" UDP ");
+               break;
+       case IPPROTO_ICMP:
+               printk(" ICMP/%d ", icmp_type);
+               break;
+       default:
+               printk(" PROTO=%d ", ip->protocol);
+               break;
+       }
+       print_ip(ip->saddr);
+       if(ip->protocol == IPPROTO_TCP || ip->protocol == IPPROTO_UDP)
+               printk(":%hu", src_port);
+       printk(" ");
+       print_ip(ip->daddr);
+       if(ip->protocol == IPPROTO_TCP || ip->protocol == IPPROTO_UDP)
+               printk(":%hu", dst_port);
+       printk(" L=%hu S=0x%2.2hX I=%hu FO=0x%4.4hX T=%hu",
+              ntohs(ip->tot_len), ip->tos, ntohs(ip->id),
+              foff & IP_OFFSET, ip->ttl); 
+       if (foff & IP_DF) printk(" DF=1");
+       if (foff & IP_MF) printk(" MF=1"); 
+       for (opti = 0; opti < (ip->ihl - sizeof(struct iphdr) / 4); opti++)
+               printk(" O=0x%8.8X", *opt++);
+       printk("\n");   
+}
+#endif
 
 /*
  *     Returns one of the generic firewall policies, like FW_ACCEPT.
@@ -483,68 +568,14 @@ int ip_fw_chk(struct iphdr *ip, struct device *rif, __u16 *redirport, struct ip_
                }
 
 #ifdef CONFIG_IP_FIREWALL_VERBOSE
-               /*
-                * VERY ugly piece of code which actually
-                * makes kernel printf for matching packets...
-                */
-
                if (f->fw_flg & IP_FW_F_PRN)
                {
-                       __u32 *opt = (__u32 *) (ip + 1);
-                       int opti;
-
-                       if(mode == IP_FW_MODE_ACCT_IN)
-                               printk(KERN_INFO "IP acct in ");
-                       else if(mode == IP_FW_MODE_ACCT_OUT)
-                               printk(KERN_INFO "IP acct out ");
-                       else {
-                               if(chain == ip_fw_fwd_chain)
-                                       printk(KERN_INFO "IP fw-fwd ");
-                               else if(chain == ip_fw_in_chain)
-                                       printk(KERN_INFO "IP fw-in ");
-                               else
-                                       printk(KERN_INFO "IP fw-out ");
-                               if(f->fw_flg&IP_FW_F_ACCEPT) {
-                                       if(f->fw_flg&IP_FW_F_REDIR)
-                                               printk("acc/r%d ", f->fw_pts[f->fw_nsp+f->fw_ndp]);
-                                       else if(f->fw_flg&IP_FW_F_MASQ)
-                                               printk("acc/masq ");
-                                       else
-                                               printk("acc ");
-                               } else if(f->fw_flg&IP_FW_F_ICMPRPL)
-                                       printk("rej ");
-                               else
-                                       printk("deny ");
-                       }
-                       printk(rif ? rif->name : "-");
-                       switch(ip->protocol)
-                       {
-                               case IPPROTO_TCP:
-                                       printk(" TCP ");
-                                       break;
-                               case IPPROTO_UDP:
-                                       printk(" UDP ");
-                                       break;
-                               case IPPROTO_ICMP:
-                                       printk(" ICMP/%d ", icmp_type);
-                                       break;
-                               default:
-                                       printk(" PROTO=%d ", ip->protocol);
-                                       break;
-                       }
-                       print_ip(ip->saddr);
-                       if(ip->protocol == IPPROTO_TCP || ip->protocol == IPPROTO_UDP)
-                               printk(":%hu", src_port);
-                       printk(" ");
-                       print_ip(ip->daddr);
-                       if(ip->protocol == IPPROTO_TCP || ip->protocol == IPPROTO_UDP)
-                               printk(":%hu", dst_port);
-                       printk(" L=%hu S=0x%2.2hX I=%hu F=0x%4.4hX T=%hu",
-                               ntohs(ip->tot_len), ip->tos, ntohs(ip->id),
-                               ip->frag_off, ip->ttl);
-                       for (opti = 0; opti < (ip->ihl - sizeof(struct iphdr) / 4); opti++)
-                               printk(" O=0x%8.8X", *opt++);
-                       printk("\n");
+                       char buf[16]; 
+
+                       print_packet(ip, src_port, dst_port, icmp_type,
+                                    chain_name(chain, mode), 
+                                    rule_name(f, mode, buf), 
+                                    rif ? rif->name : "-");
                }
 #endif         
                if (mode != IP_FW_MODE_CHK) {
index d5b0b15c60aed3185266acd10537ed91a163b9dd..7a0a40aeb57f757902df68c205745a2be1ae2309 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:    $Id: tcp_input.c,v 1.114 1998/04/28 06:42:22 davem Exp $
+ * Version:    $Id: tcp_input.c,v 1.116 1998/05/02 14:50:11 davem Exp $
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -421,33 +421,6 @@ static __inline__ int tcp_fast_parse_options(struct sock *sk, struct tcphdr *th,
        return 1;
 }
 
-#if 0 /* Not working yet... -DaveM */
-static void tcp_compute_tsack(struct sock *sk, struct tcp_opt *tp)
-{
-       struct sk_buff *skb = skb_peek(&sk->write_queue);
-       __u32 tstamp = tp->rcv_tsecr;
-       int fack_count = 0;
-
-       while((skb != NULL) &&
-             (skb != tp->send_head) &&
-             (skb != (struct sk_buff *)&sk->write_queue)) {
-               if(TCP_SKB_CB(skb)->when == tstamp) {
-                       __u8 sacked = TCP_SKB_CB(skb)->sacked;
-
-                       sacked |= TCPCB_SACKED_ACKED;
-                       if(sacked & TCPCB_SACKED_RETRANS)
-                               tp->retrans_out--;
-                       TCP_SKB_CB(skb)->sacked = sacked;
-               }
-               if(!before(TCP_SKB_CB(skb)->when, tstamp))
-                       fack_count++;
-               skb = skb->next;
-       }
-       if(fack_count > tp->fackets_out)
-               tp->fackets_out = fack_count;
-}
-#endif
-
 #define FLAG_DATA              0x01 /* Incoming frame contained data.          */
 #define FLAG_WIN_UPDATE                0x02 /* Incoming ACK was a window update.       */
 #define FLAG_DATA_ACKED                0x04 /* This ACK acknowledged new data.         */
@@ -481,13 +454,6 @@ static void tcp_fast_retrans(struct sock *sk, u32 ack, int not_dup)
        if (ack == tp->snd_una && tp->packets_out && (not_dup == 0)) {
                /* This is the standard reno style fast retransmit branch. */
 
-#if 0  /* Not working yet... -DaveM */
-               /* If not doing SACK, but doing timestamps, compute timestamp
-                * based pseudo-SACKs when we see duplicate ACKs.
-                */
-               if(!tp->sack_ok && tp->saw_tstamp)
-                       tcp_compute_tsack(sk, tp);
-#endif
                 /* 1. When the third duplicate ack is received, set ssthresh 
                  * to one half the current congestion window, but no less 
                  * than two segments. Retransmit the missing segment.
@@ -611,6 +577,7 @@ static int tcp_clean_rtx_queue(struct sock *sk, __u32 ack,
 
        while((skb=skb_peek(&sk->write_queue)) && (skb != tp->send_head)) {
                struct tcp_skb_cb *scb = TCP_SKB_CB(skb); 
+               __u8 sacked = scb->sacked;
                
                /* If our packet is before the ack sequence we can
                 * discard it as it's confirmed to have arrived at
@@ -626,22 +593,12 @@ static int tcp_clean_rtx_queue(struct sock *sk, __u32 ack,
                 * connection startup slow start one packet too
                 * quickly.  This is severely frowned upon behavior.
                 */
+               if(sacked & TCPCB_SACKED_RETRANS && tp->retrans_out)
+                       tp->retrans_out--;
                if(!(scb->flags & TCPCB_FLAG_SYN)) {
-                       __u8 sacked = scb->sacked;
-
                        acked |= FLAG_DATA_ACKED;
-                       if(sacked & TCPCB_SACKED_RETRANS) {
+                       if(sacked & TCPCB_SACKED_RETRANS)
                                acked |= FLAG_RETRANS_DATA_ACKED;
-
-                               /* XXX The race is, fast retrans frame -->
-                                * XXX retrans timeout sends older frame -->
-                                * XXX ACK arrives for fast retrans frame -->
-                                * XXX retrans_out goes negative --> splat.
-                                * XXX Please help me find a better way -DaveM
-                                */
-                               if(tp->retrans_out)
-                                       tp->retrans_out--;
-                       }
                        if(tp->fackets_out)
                                tp->fackets_out--;
                } else {
index 08ca40a4bea53a28598840731a1a5bf8ea42c8a2..328cc9389cf4f3395ec39db121b1ae6cc7df2b0b 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:    $Id: tcp_ipv4.c,v 1.142 1998/04/30 12:00:45 davem Exp $
+ * Version:    $Id: tcp_ipv4.c,v 1.145 1998/05/02 12:47:13 davem Exp $
  *
  *             IPv4 specific functions
  *
@@ -48,7 +48,6 @@
 
 #include <linux/config.h>
 #include <linux/types.h>
-#include <linux/stddef.h>
 #include <linux/fcntl.h>
 #include <linux/random.h>
 #include <linux/init.h>
 #include <asm/segment.h>
 
 #include <linux/inet.h>
+#include <linux/stddef.h>
 
 extern int sysctl_tcp_timestamps;
 extern int sysctl_tcp_window_scaling;
 extern int sysctl_tcp_sack;
 extern int sysctl_tcp_syncookies;
 extern int sysctl_ip_dynaddr;
+extern __u32 sysctl_wmem_max;
+extern __u32 sysctl_rmem_max;
 
 /* Check TCP sequence numbers in ICMP packets. */
 #define ICMP_MIN_LENGTH 8
@@ -166,17 +168,21 @@ struct tcp_bind_bucket *tcp_bucket_create(unsigned short snum)
        return tb;
 }
 
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
 /* Ensure that the bound bucket for the port exists.
  * Return 0 on success.
  */
 static __inline__ int tcp_bucket_check(unsigned short snum)
 {
-       if (tcp_bound_hash[tcp_bhashfn(snum)] == NULL &&
-                       tcp_bucket_create(snum) == NULL)
+       struct tcp_bind_bucket *tb = tcp_bound_hash[tcp_bhashfn(snum)];
+       for( ; (tb && (tb->port != snum)); tb = tb->next)
+               ;
+       if(tb == NULL && tcp_bucket_create(snum) == NULL)
                return 1;
        else
                return 0;
 }
+#endif
 
 static int tcp_v4_verify_bind(struct sock *sk, unsigned short snum)
 {
@@ -215,10 +221,21 @@ static int tcp_v4_verify_bind(struct sock *sk, unsigned short snum)
                                result = 1;
                }
        }
-       if((result == 0) &&
-          (tb == NULL) &&
-          (tcp_bucket_create(snum) == NULL))
-               result = 1;
+       if(result == 0) {
+               if(tb == NULL) {
+                       if(tcp_bucket_create(snum) == NULL)
+                               result = 1;
+               } else {
+                       /* It could be pending garbage collection, this
+                        * kills the race and prevents it from disappearing
+                        * out from under us by the time we use it.  -DaveM
+                        */
+                       if(tb->owners == NULL && !(tb->flags & TCPB_FLAG_LOCKED)) {
+                               tb->flags = TCPB_FLAG_LOCKED;
+                               tcp_dec_slow_timer(TCP_SLT_BUCKETGC);
+                       }
+               }
+       }
 go_like_smoke:
        SOCKHASH_UNLOCK();
        return result;
@@ -1308,6 +1325,11 @@ struct sock * tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
        if (!newsk) 
                goto exit;
 
+       if (newsk->rcvbuf < (3 * newsk->mtu))
+               newsk->rcvbuf = min ((3 * newsk->mtu), sysctl_rmem_max);
+       if (newsk->sndbuf < (3 * newsk->mtu))
+               newsk->sndbuf = min ((3 * newsk->mtu), sysctl_wmem_max);
        sk->tp_pinfo.af_tcp.syn_backlog--;
        sk->ack_backlog++;
 
index 9a0f9dfbb336b91363d2e4195f5fd31aedf20345..665a448bb50c75865201ce1ef9f5df3172fe593e 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:    $Id: tcp_timer.c,v 1.50 1998/04/14 09:08:59 davem Exp $
+ * Version:    $Id: tcp_timer.c,v 1.51 1998/05/02 15:19:26 davem Exp $
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -448,26 +448,24 @@ void tcp_retransmit_timer(unsigned long data)
         */
        if(tp->sack_ok) {
                struct sk_buff *skb = skb_peek(&sk->write_queue);
-               __u8 toclear = TCPCB_SACKED_ACKED;
 
-               if(tp->retransmits == 0)
-                       toclear |= TCPCB_SACKED_RETRANS;
                while((skb != NULL) &&
                      (skb != tp->send_head) &&
                      (skb != (struct sk_buff *)&sk->write_queue)) {
-                       TCP_SKB_CB(skb)->sacked &= ~(toclear);
+                       TCP_SKB_CB(skb)->sacked &=
+                               ~(TCPCB_SACKED_ACKED | TCPCB_SACKED_RETRANS);
                        skb = skb->next;
                }
-               tp->fackets_out = 0;
        }
 
        /* Retransmission. */
        tp->retrans_head = NULL;
+       tp->fackets_out = 0;
+       tp->retrans_out = 0;
        if (tp->retransmits == 0) {
                /* remember window where we lost
                 * "one half of the current window but at least 2 segments"
                 */
-               tp->retrans_out = 0;
                tp->snd_ssthresh = max(tp->snd_cwnd >> (1 + TCP_CWND_SHIFT), 2);
                tp->snd_cwnd = (1 << TCP_CWND_SHIFT);
        }
index af29057ecb6fc20d8f338220690f52b5f36f605c..0b826870f1248b1a50ed9cc4d1ef764f69bb859e 100644 (file)
@@ -4,8 +4,9 @@
  *
  *     Authors:
  *     Pedro Roque             <roque@di.fc.ul.pt>
+ *     Andi Kleen              <ak@muc.de>
  *
- *     $Id: exthdrs.c,v 1.5 1998/02/12 07:43:39 davem Exp $
+ *     $Id: exthdrs.c,v 1.6 1998/04/30 16:24:20 freitag Exp $
  *
  *     This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
 #include <net/ip6_route.h>
 #include <net/addrconf.h>
 
+#include <asm/uaccess.h>
+
+#define swap(a,b) do { typeof (a) tmp; tmp = (a); (a) = (b); (b) = (tmp); } while(0)
+
 /*
  *     inbound
  */
@@ -135,7 +140,7 @@ int ipv6_routing_header(struct sk_buff **skb_ptr, struct device *dev,
  */
 
 int ipv6opt_bld_rthdr(struct sk_buff *skb, struct ipv6_options *opt,
-                     struct in6_addr *addr, int proto)               
+                     struct in6_addr *addr)                  
 {
        struct rt0_hdr *phdr, *ihdr;
        int hops;
@@ -153,8 +158,76 @@ int ipv6opt_bld_rthdr(struct sk_buff *skb, struct ipv6_options *opt,
 
        ipv6_addr_copy(phdr->addr + (hops - 1), addr);
        
-       phdr->rt_hdr.nexthdr = proto;
-
+       phdr->rt_hdr.nexthdr = proto; 
        return NEXTHDR_ROUTING;
 }
 #endif
+
+/* 
+ * find out if nexthdr is an extension header or a protocol
+ */
+
+static __inline__ int ipv6_ext_hdr(u8 nexthdr)
+{
+       /* 
+        * find out if nexthdr is an extension header or a protocol
+        */
+       return ( (nexthdr == NEXTHDR_HOP)       ||
+                (nexthdr == NEXTHDR_ROUTING)   ||
+                (nexthdr == NEXTHDR_FRAGMENT)  ||
+                (nexthdr == NEXTHDR_ESP)       ||
+                (nexthdr == NEXTHDR_AUTH)      ||
+                (nexthdr == NEXTHDR_NONE)      ||
+                (nexthdr == NEXTHDR_DEST) );
+                
+}
+
+/*
+ * Skip any extension headers. This is used by the ICMP module.
+ *
+ * Note that strictly speaking this conflicts with RFC1883 4.0:
+ * ...The contents and semantics of each extension header determine whether 
+ * or not to proceed to the next header.  Therefore, extension headers must
+ * be processed strictly in the order they appear in the packet; a
+ * receiver must not, for example, scan through a packet looking for a
+ * particular kind of extension header and process that header prior to
+ * processing all preceding ones.
+ * 
+ * We do exactly this. This is a protocol bug. We can't decide after a
+ * seeing an unknown discard-with-error flavour TLV option if it's a 
+ * ICMP error message or not (errors should never be send in reply to
+ * ICMP error messages).
+ * 
+ * But I see no other way to do this. This might need to be reexamined
+ * when Linux implements ESP (and maybe AUTH) headers.
+ */
+struct ipv6_opt_hdr *ipv6_skip_exthdr(struct ipv6_opt_hdr *hdr, 
+                                     u8 *nexthdrp, int len)
+{
+       u8 nexthdr = *nexthdrp;
+
+       while (ipv6_ext_hdr(nexthdr)) {
+               int hdrlen; 
+               
+               if (nexthdr == NEXTHDR_NONE)
+                       return NULL;
+               if (len < sizeof(struct ipv6_opt_hdr)) /* be anal today */
+                       return NULL;
+
+               hdrlen = ipv6_optlen(hdr); 
+               if (len < hdrlen)
+                       return NULL; 
+
+               nexthdr = hdr->nexthdr;
+               hdr = (struct ipv6_opt_hdr *) ((u8*)hdr + hdrlen);
+               len -= hdrlen;
+       }
+
+       /* Hack.. Do the same for AUTH headers? */
+       if (nexthdr == NEXTHDR_ESP) 
+               return NULL; 
+
+       *nexthdrp = nexthdr;
+       return hdr;
+}
+
index f181aec52d670ac8826746e6d451d7dffdedea1c..1048959362203ed5b68b2a6ea635604968a130c6 100644 (file)
@@ -5,7 +5,7 @@
  *     Authors:
  *     Pedro Roque             <roque@di.fc.ul.pt>
  *
- *     $Id: icmp.c,v 1.15 1998/03/21 07:28:03 davem Exp $
+ *     $Id: icmp.c,v 1.17 1998/05/01 10:31:41 davem Exp $
  *
  *     Based on net/ipv4/icmp.c
  *
@@ -21,6 +21,8 @@
  *     Changes:
  *
  *     Andi Kleen              :       exception handling
+ *     Andi Kleen                      add rate limits. never reply to a icmp.
+ *                                     add more length checks and other fixes.
  */
 
 #define __NO_VERSION__
@@ -51,6 +53,7 @@
 #include <net/transp_v6.h>
 #include <net/ip6_route.h>
 #include <net/addrconf.h>
+#include <net/icmp.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -129,6 +132,62 @@ static int icmpv6_getfrag(const void *data, struct in6_addr *saddr,
        return 0; 
 }
 
+
+/* 
+ * Slightly more convenient version of icmpv6_send.
+ */
+void icmpv6_param_prob(struct sk_buff *skb, int code, void *pos)
+{
+       int offset = (u8*)pos - (u8*)skb->nh.ipv6h; 
+       
+       icmpv6_send(skb, ICMPV6_PARAMPROB, code, offset, skb->dev);
+       kfree_skb(skb);
+}
+
+static inline int is_icmp(struct ipv6hdr *hdr, int len)
+{
+       __u8 nexthdr = hdr->nexthdr; 
+
+       if (!ipv6_skip_exthdr((struct ipv6_opt_hdr *)(hdr+1), &nexthdr, len))
+               return 0; 
+       return nexthdr == IPPROTO_ICMP; 
+}
+
+int sysctl_icmpv6_time = 1*HZ; 
+
+/* 
+ * Check the ICMP output rate limit 
+ */
+static inline int icmpv6_xrlim_allow(struct sock *sk, int type,
+                                    struct flowi *fl)
+{
+#if 0
+       struct dst_entry *dst; 
+       int allow = 0;
+#endif
+       /* Informational messages are not limited. */
+       if (type & 0x80)
+               return 1; 
+
+#if 0 /* not yet, first fix routing COW */
+
+       /* 
+        * Look up the output route.
+        * XXX: perhaps the expire for routing entries cloned by
+        * this lookup should be more aggressive (not longer than timeout).
+        */
+       dst = ip6_route_output(sk, fl, 1);
+       if (dst->error) 
+               ipv6_statistics.Ip6OutNoRoutes++;
+       else 
+               allow = xrlim_allow(dst, sysctl_icmpv6_time);
+       dst_release(dst);
+       return allow;
+#else
+       return 1;
+#endif
+}
+
 /*
  *     an inline helper for the "simple" if statement below
  *     checks if parameter problem report is caused by an
@@ -214,6 +273,24 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
                return;
        }
 
+       /* 
+        *      Never answer to a ICMP packet.
+        */
+       if (is_icmp(hdr, (u8*)skb->tail - (u8*)hdr)) {
+               printk(KERN_DEBUG "icmpv6_send: no reply to icmp\n"); 
+               return;
+       }
+
+       fl.proto = IPPROTO_ICMPV6;
+       fl.nl_u.ip6_u.daddr = &hdr->saddr;
+       fl.nl_u.ip6_u.saddr = saddr;
+       fl.oif = iif;
+       fl.uli_u.icmpt.type = type;
+       fl.uli_u.icmpt.code = code;
+
+       if (!icmpv6_xrlim_allow(sk, type, &fl)) 
+               return; 
+
        /*
         *      ok. kick it. checksum will be provided by the 
         *      getfrag_t callback.
@@ -248,13 +325,6 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
 
        msg.len = len;
 
-       fl.proto = IPPROTO_ICMPV6;
-       fl.nl_u.ip6_u.daddr = &hdr->saddr;
-       fl.nl_u.ip6_u.saddr = saddr;
-       fl.oif = iif;
-       fl.uli_u.icmpt.type = type;
-       fl.uli_u.icmpt.code = code;
-
        ip6_build_xmit(sk, icmpv6_getfrag, &msg, &fl, len, NULL, -1,
                       MSG_DONTWAIT);
 
@@ -312,21 +382,6 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
        dst_release(xchg(&sk->dst_cache, NULL));
 }
 
-static __inline__ int ipv6_ext_hdr(u8 nexthdr)
-{
-       /* 
-        * find out if nexthdr is an extension header or a protocol
-        */
-       return ( (nexthdr == NEXTHDR_HOP)       ||
-                (nexthdr == NEXTHDR_ROUTING)   ||
-                (nexthdr == NEXTHDR_FRAGMENT)  ||
-                (nexthdr == NEXTHDR_ESP)       ||
-                (nexthdr == NEXTHDR_AUTH)      ||
-                (nexthdr == NEXTHDR_NONE)      ||
-                (nexthdr == NEXTHDR_DEST) );
-                
-}
-
 static void icmpv6_notify(struct sk_buff *skb,
                          int type, int code, unsigned char *buff, int len,
                          struct in6_addr *saddr, struct in6_addr *daddr, 
@@ -335,39 +390,22 @@ static void icmpv6_notify(struct sk_buff *skb,
        struct ipv6hdr *hdr = (struct ipv6hdr *) buff;
        struct inet6_protocol *ipprot;
        struct sock *sk;
-       char * pbuff;
+       struct ipv6_opt_hdr *pb;
        __u32 info = 0;
        int hash;
        u8 nexthdr;
 
-       /* now skip over extension headers */
-
        nexthdr = hdr->nexthdr;
 
-       pbuff = (char *) (hdr + 1);
+       pb = (struct ipv6_opt_hdr *) (hdr + 1);
        len -= sizeof(struct ipv6hdr);
+       if (len < 0)
+               return;
 
-       while (ipv6_ext_hdr(nexthdr)) {
-               int hdrlen;
-
-               if (nexthdr == NEXTHDR_NONE)
-                       return;
-
-               nexthdr = *pbuff;
-
-               /* Header length is size in 8-octet units, not
-                * including the first 8 octets.
-                */
-               hdrlen = *(pbuff+1);
-               hdrlen = (hdrlen + 1) << 3;
-
-               if (hdrlen > len)
-                       return;
-               
-               /* Now this is right. */
-               pbuff += hdrlen;
-               len -= hdrlen;
-       }
+       /* now skip over extension headers */
+       pb = ipv6_skip_exthdr(pb, &nexthdr, len);
+       if (!pb)
+               return;
 
        hash = nexthdr & (MAX_INET_PROTOS - 1);
 
@@ -378,7 +416,7 @@ static void icmpv6_notify(struct sk_buff *skb,
                        continue;
 
                if (ipprot->err_handler) 
-                       ipprot->err_handler(skb, type, code, pbuff, info,
+                       ipprot->err_handler(skb, type, code, (u8*)pb, info,
                                            saddr, daddr, ipprot);
                return;
        }
@@ -391,7 +429,7 @@ static void icmpv6_notify(struct sk_buff *skb,
                return;
 
        while((sk = raw_v6_lookup(sk, nexthdr, daddr, saddr))) {
-               rawv6_err(sk, type, code, pbuff, saddr, daddr);
+               rawv6_err(sk, type, code, (char*)pb, saddr, daddr);
                sk = sk->next;
        }
 }
@@ -514,7 +552,7 @@ discard_it:
        return 0;
 }
 
-__initfunc(void icmpv6_init(struct net_proto_family *ops))
+__initfunc(int icmpv6_init(struct net_proto_family *ops))
 {
        struct sock *sk;
        int err;
@@ -528,11 +566,11 @@ __initfunc(void icmpv6_init(struct net_proto_family *ops))
        icmpv6_socket->state = SS_UNCONNECTED;
        icmpv6_socket->type=SOCK_RAW;
 
-       if((err=ops->create(icmpv6_socket, IPPROTO_ICMPV6))<0)
+       if((err=ops->create(icmpv6_socket, IPPROTO_ICMPV6))<0) {
                printk(KERN_DEBUG 
                       "Failed to create the ICMP6 control socket.\n");
-
-       MOD_DEC_USE_COUNT;
+               return 1;
+       }
 
        sk = icmpv6_socket->sk;
        sk->allocation = GFP_ATOMIC;
@@ -542,6 +580,16 @@ __initfunc(void icmpv6_init(struct net_proto_family *ops))
 
        ndisc_init(ops);
        igmp6_init(ops);
+       return 0; 
+}
+
+void icmpv6_cleanup(void)
+{
+       inet6_del_protocol(&icmpv6_protocol);
+#if 0
+       ndisc_cleanup();
+#endif
+       igmp6_cleanup();
 }
 
 static struct icmp6_err {
index 71ad7e1a09776c6029290d7bdf45ed607b2be45f..5f024dddbd700af723234829eaad253b216d016b 100644 (file)
@@ -6,7 +6,7 @@
  *     Pedro Roque             <roque@di.fc.ul.pt>
  *     Ian P. Morris           <I.P.Morris@soton.ac.uk>
  *
- *     $Id: ip6_input.c,v 1.8 1998/02/12 07:43:43 davem Exp $
+ *     $Id: ip6_input.c,v 1.9 1998/04/30 16:24:24 freitag Exp $
  *
  *     Based in linux/net/ipv4/ip_input.c
  *
@@ -70,12 +70,6 @@ struct ipv6_tlvtype {
        u8 len;
 };
 
-struct ipv6_destopt_hdr {
-       u8 nexthdr;
-       u8 hdrlen;
-};
-
-
 struct tlvtype_proc {
        u8      type;
        int     (*func) (struct sk_buff *, struct device *dev, __u8 *ptr,
index 9bb2d4d3c654e1a5efd83e22c4b9f035cc93e377..ebd3365cd431168b2fb81275399fec09e33a4675 100644 (file)
@@ -7,7 +7,7 @@
  *
  *     Based on linux/net/ipv4/ip_sockglue.c
  *
- *     $Id: ipv6_sockglue.c,v 1.18 1998/03/20 09:12:18 davem Exp $
+ *     $Id: ipv6_sockglue.c,v 1.19 1998/04/30 16:24:26 freitag Exp $
  *
  *     This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -242,7 +242,7 @@ void ipv6_cleanup(void)
        ipv6_sysctl_unregister();       
 #endif
        ip6_route_cleanup();
-       ndisc_cleanup();
+       icmpv6_cleanup();
        addrconf_cleanup();     
 }
 #endif
index 407698eb11b39f1a21d3a6fcbd44d2b9799dbe82..0e10dcf0b9ab9973dd8be5617f2a50d0cbf961a1 100644 (file)
@@ -5,7 +5,7 @@
  *     Authors:
  *     Pedro Roque             <roque@di.fc.ul.pt>     
  *
- *     $Id: mcast.c,v 1.14 1998/03/20 09:12:18 davem Exp $
+ *     $Id: mcast.c,v 1.15 1998/04/30 16:24:28 freitag Exp $
  *
  *     Based on linux/ipv4/igmp.c and linux/ipv4/ip_sockglue.c 
  *
@@ -619,8 +619,6 @@ __initfunc(void igmp6_init(struct net_proto_family *ops))
                printk(KERN_DEBUG 
                       "Failed to create the IGMP6 control socket.\n");
 
-       MOD_DEC_USE_COUNT;
-
        sk = igmp6_socket->sk;
        sk->allocation = GFP_ATOMIC;
        sk->num = 256;                  /* Don't receive any data */
@@ -632,3 +630,9 @@ __initfunc(void igmp6_init(struct net_proto_family *ops))
 #endif
 }
 
+void igmp6_cleanup(void)
+{
+#ifdef CONFIG_PROC_FS
+       remove_proc_entry("net/igmp6", 0); 
+#endif
+}
index 2e437f2ded8d59c4a23ab6ca6e69ca4a7aee64cf..e69d90332d6455524dacf464cc8ae47491fb5bcf 100644 (file)
@@ -1152,9 +1152,6 @@ __initfunc(void ndisc_init(struct net_proto_family *ops))
                printk(KERN_DEBUG 
                       "Failed to create the NDISC control socket.\n");
 
-       /* Eeeh... What is it? --ANK */
-       MOD_DEC_USE_COUNT;
-
        sk = ndisc_socket->sk;
        sk->allocation = GFP_ATOMIC;
        sk->net_pinfo.af_inet6.hop_limit = 255;
index 55fecc6766ac6439bd32f3711f37041deff0697f..e78cf97a23f97257f2a1af01cae17bdea8c5ec66 100644 (file)
@@ -5,7 +5,7 @@
  *     Authors:
  *     Pedro Roque             <roque@di.fc.ul.pt>     
  *
- *     $Id: reassembly.c,v 1.9 1998/02/12 07:43:48 davem Exp $
+ *     $Id: reassembly.c,v 1.10 1998/04/30 16:24:32 freitag Exp $
  *
  *     Based on: net/ipv4/ip_fragment.c
  *
  *      2 of the License, or (at your option) any later version.
  */
 
+/* 
+ *     Fixes:  
+ *     Andi Kleen      Make it work with multiple hosts.
+ *                     More RFC compliance.
+ */
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/socket.h>
@@ -39,8 +44,9 @@
 
 static struct frag_queue ipv6_frag_queue = {
        &ipv6_frag_queue, &ipv6_frag_queue,
-       0, {0}, NULL, NULL,
-       0
+       0, {{{0}}}, {{{0}}},
+       {0}, NULL, NULL,
+       0, 0, NULL
 };
 
 static void                    create_frag_entry(struct sk_buff *skb, 
@@ -72,12 +78,11 @@ static int reasm_frag(struct frag_queue *fq, struct sk_buff **skb,
         *      one it's the kmalloc for a struct ipv6_frag.
         *      Feel free to try other alternatives...
         */
-       reasm_queue(fq, *skb, fhdr);
-
        if ((fhdr->frag_off & __constant_htons(0x0001)) == 0) {
                fq->last_in = 1;
                fq->nhptr = nhptr;
        }
+       reasm_queue(fq, *skb, fhdr);
 
        if (fq->last_in) {
                if ((nh = reasm_frag_1(fq, skb)))
@@ -90,18 +95,27 @@ static int reasm_frag(struct frag_queue *fq, struct sk_buff **skb,
        return 0;
 }
 
-int ipv6_reassembly(struct sk_buff **skb, struct device *dev, __u8 *nhptr,
+int ipv6_reassembly(struct sk_buff **skbp, struct device *dev, __u8 *nhptr,
                    struct ipv6_options *opt)
 {
-       struct frag_hdr *fhdr = (struct frag_hdr *) ((*skb)->h.raw);
+       struct sk_buff *skb = *skbp; 
+       struct frag_hdr *fhdr = (struct frag_hdr *) (skb->h.raw);
        struct frag_queue *fq;
-       
+       struct ipv6hdr *hdr;
+
+       if ((u8 *)(fhdr+1) > skb->tail) {
+               icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, skb->h.raw);
+               return 0;
+       }
+       hdr = skb->nh.ipv6h;
        for (fq = ipv6_frag_queue.next; fq != &ipv6_frag_queue; fq = fq->next) {
-               if (fq->id == fhdr->identification)
-                       return reasm_frag(fq, skb, nhptr,fhdr);
+               if (fq->id == fhdr->identification && 
+                   !ipv6_addr_cmp(&hdr->saddr, &fq->saddr) &&
+                   !ipv6_addr_cmp(&hdr->daddr, &fq->daddr))
+                       return reasm_frag(fq, skbp, nhptr,fhdr);
        }
        
-       create_frag_entry(*skb, dev, nhptr, fhdr);
+       create_frag_entry(skb, dev, nhptr, fhdr);
 
        return 0;
 }
@@ -154,6 +168,7 @@ static void create_frag_entry(struct sk_buff *skb, struct device *dev,
                              struct frag_hdr *fhdr)
 {
        struct frag_queue *fq;
+       struct ipv6hdr *hdr; 
 
        fq = (struct frag_queue *) kmalloc(sizeof(struct frag_queue), 
                                           GFP_ATOMIC);
@@ -167,6 +182,10 @@ static void create_frag_entry(struct sk_buff *skb, struct device *dev,
 
        fq->id = fhdr->identification;
 
+       hdr = skb->nh.ipv6h;
+       ipv6_addr_copy(&fq->saddr, &hdr->saddr);
+       ipv6_addr_copy(&fq->daddr, &hdr->daddr);
+
        fq->dev = dev;
 
        /* init_timer has been done by the memset */
@@ -193,14 +212,14 @@ static void create_frag_entry(struct sk_buff *skb, struct device *dev,
 
 
 static void reasm_queue(struct frag_queue *fq, struct sk_buff *skb, 
-                       struct frag_hdr *fhdr)
+                                    struct frag_hdr *fhdr)
 {
        struct ipv6_frag *nfp, *fp, **bptr;
 
        nfp = (struct ipv6_frag *) kmalloc(sizeof(struct ipv6_frag), 
                                           GFP_ATOMIC);
 
-       if (nfp == NULL) {
+       if (nfp == NULL) {              
                kfree_skb(skb);
                return;
        }
@@ -209,6 +228,10 @@ static void reasm_queue(struct frag_queue *fq, struct sk_buff *skb,
        nfp->len = (ntohs(skb->nh.ipv6h->payload_len) -
                    ((u8 *) (fhdr + 1) - (u8 *) (skb->nh.ipv6h + 1)));
 
+       if ((u32)nfp->offset + (u32)nfp->len > 65536) {
+               icmpv6_param_prob(skb,ICMPV6_HDR_FIELD, (u8*)&fhdr->frag_off); 
+               goto err;
+       }
 
        nfp->skb  = skb;
        nfp->fhdr = fhdr;
@@ -224,19 +247,37 @@ static void reasm_queue(struct frag_queue *fq, struct sk_buff *skb,
        }
        
        if (fp && fp->offset == nfp->offset) {
-               if (fp->len != nfp->len) {
-                       /* this cannot happen */
+               if (nfp->len != fp->len) {
                        printk(KERN_DEBUG "reasm_queue: dup with wrong len\n");
                }
 
                /* duplicate. discard it. */
-               kfree_skb(skb);
-               kfree(nfp);
-               return;
+               goto err;
        }
        
        *bptr = nfp;
        nfp->next = fp;
+
+#ifdef STRICT_RFC
+       if (fhdr->frag_off & __constant_htons(0x0001)) {
+               /* Check if the fragment is rounded to 8 bytes.
+                * Required by the RFC.
+                */
+               if (nfp->len & 0x7) {
+                       printk(KERN_DEBUG "fragment not rounded to 8bytes\n");
+
+                       icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, 
+                                         &skb->nh.ipv6h->payload_len);
+                       goto err;
+               }
+       }
+#endif 
+
+       return;
+
+err:
+       kfree(nfp);
+       kfree_skb(skb);
 }
 
 /*
@@ -303,6 +344,8 @@ static int reasm_frag_1(struct frag_queue *fq, struct sk_buff **skb_in)
        /*
         *      FIXME: If we don't have a checksum we ought to be able
         *      to defragment and checksum in this pass. [AC]
+        *      Note that we don't really know yet whether the protocol
+        *      needs checksums at all. It might still be a good idea. -AK
         */
        for(fp = fq->fragments; fp; ) {
                struct ipv6_frag *back;
index 721677fa6350559549112eac97a14881663c3fe3..0a4a95c7c22cb928cacd735f08f7ef19a69bbd50 100644 (file)
@@ -5,7 +5,7 @@
  *     Authors:
  *     Pedro Roque             <roque@di.fc.ul.pt>     
  *
- *     $Id: tcp_ipv6.c,v 1.78 1998/04/16 16:29:22 freitag Exp $
+ *     $Id: tcp_ipv6.c,v 1.80 1998/05/02 12:47:15 davem Exp $
  *
  *     Based on: 
  *     linux/net/ipv4/tcp.c
@@ -123,10 +123,21 @@ static int tcp_v6_verify_bind(struct sock *sk, unsigned short snum)
                                result = 1;
                }
        }
-       if((result == 0) &&
-          (tb == NULL) &&
-          (tcp_bucket_create(snum) == NULL))
-               result = 1;
+       if(result == 0) {
+               if(tb == NULL) {
+                       if(tcp_bucket_create(snum) == NULL)
+                               result = 1;
+               } else {
+                       /* It could be pending garbage collection, this
+                        * kills the race and prevents it from disappearing
+                        * out from under us by the time we use it.  -DaveM
+                        */
+                       if(tb->owners == NULL && !(tb->flags & TCPB_FLAG_LOCKED)) {
+                               tb->flags = TCPB_FLAG_LOCKED;
+                               tcp_dec_slow_timer(TCP_SLT_BUCKETGC);
+                       }
+               }
+       }
 go_like_smoke:
        SOCKHASH_UNLOCK();
        return result;
@@ -731,7 +742,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb, void *ptr,
                isn = tcp_v6_init_sequence(sk,skb);
 
        /*
-        *      There are no SYN attacks on IPv6, yet...
+        *      There are no SYN attacks on IPv6, yet...        
         */
        if (BACKLOG(sk) >= BACKLOGMAX(sk)) {
                printk(KERN_DEBUG "droping syn ack:%d max:%d\n",
index 5d380fbb6c07400acf7ddb3c9b03f56d1fa7e3c6..52be530335a9beaff5a78b4c737836c5185e68ff 100644 (file)
@@ -458,7 +458,7 @@ EXPORT_SYMBOL(qdisc_put_rtab);
 EXPORT_SYMBOL(qdisc_new_estimator);
 EXPORT_SYMBOL(qdisc_kill_estimator);
 #endif
-#ifdef CONFIG_NET_POLICE
+#ifdef CONFIG_NET_CLS_POLICE
 EXPORT_SYMBOL(tcf_police);
 EXPORT_SYMBOL(tcf_police_locate);
 EXPORT_SYMBOL(tcf_police_destroy);