]> git.neil.brown.name Git - history.git/commitdiff
Import 1.1.5 1.1.5
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:09:27 +0000 (15:09 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:09:27 +0000 (15:09 -0500)
Makefile
drivers/net/loopback.c
net/inet/arp.c
net/inet/dev.c
net/inet/icmp.c

index 51e5c5736e6af776f02a14bd16bc26bdbd19ac57..ba24d95451985798c0a57a8e72f81c6f6821202d 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 1
-SUBLEVEL = 4
+SUBLEVEL = 5
 
 all:   Version zImage
 
index bdb22b5ad5c37d044b7692e9eb3f3ce746240c5d..3eba233233ed3627bf3dec2e2bc27e9ba3dc1c1f 100644 (file)
@@ -50,23 +50,17 @@ loopback_xmit(struct sk_buff *skb, struct device *dev)
   cli();
   if (dev->tbusy != 0) {
        sti();
-       printk("loopback error: called by %08lx\n",
-               ((unsigned long *)&skb)[-1]);
        stats->tx_errors++;
        return(1);
   }
   dev->tbusy = 1;
   sti();
 
-  start_bh_atomic();
   done = dev_rint(skb->data, skb->len, 0, dev);
   if (skb->free) kfree_skb(skb, FREE_WRITE);
-  end_bh_atomic();
 
   while (done != 1) {
-       start_bh_atomic();
        done = dev_rint(NULL, 0, 0, dev);
-       end_bh_atomic();
   }
   stats->tx_packets++;
 
index 48a904b691f049268742b15e1f0a1e4483702af3..826a122ef273d7d29443c7f22b1d4794467aef53 100644 (file)
@@ -26,7 +26,7 @@
  *             Alan Cox        :       Make ARP add its own protocol entry
  *
  */
+
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
  *     This structure defines the ARP mapping cache. As long as we make changes
  *     in this structure, we keep interrupts of. But normally we can copy the
  *     hardware address and the device pointer in a local variable and then make
- *     any "long calls" to send a packet out. 
+ *     any "long calls" to send a packet out.
  */
-struct arp_table 
+
+struct arp_table
 {
        struct arp_table                *next;                  /* Linked entry list            */
        unsigned long                   last_used;              /* For expiry                   */
@@ -73,19 +73,19 @@ struct arp_table
        struct device                   *dev;                   /* Device the entry is tied to  */
 
        /*
-        *      The following entries are only used for unresolved hw addresses. 
+        *      The following entries are only used for unresolved hw addresses.
         */
-        
-       struct timer_list               timer;                  /* expire timer                 */      
+       
+       struct timer_list               timer;                  /* expire timer                 */
        int                             retries;                /* remaining retries            */
        struct sk_buff_head             skb;                    /* list of queued packets       */
 };
 
-/* 
- *     This structure defines an ethernet arp header. 
+/*
+ *     This structure defines an ethernet arp header.
  */
-struct arphdr 
+
+struct arphdr
 {
        unsigned short  ar_hrd;         /* format of hardware address   */
        unsigned short  ar_pro;         /* format of protocol address   */
@@ -108,31 +108,31 @@ struct arphdr
 /*
  *     Configurable Parameters (don't touch unless you know what you are doing
  */
+
 /*
  *     If an arp request is send, ARP_RES_TIME is the timeout value until the
- *     next request is send. 
+ *     next request is send.
  */
+
 #define ARP_RES_TIME           (250*(HZ/10))
 
 /*
  *     The number of times an arp request is send, until the host is
- *     considered unreachable. 
+ *     considered unreachable.
  */
+
 #define ARP_MAX_TRIES          3
 
 /*
- *     After that time, an unused entry is deleted from the arp table. 
+ *     After that time, an unused entry is deleted from the arp table.
  */
+
 #define ARP_TIMEOUT            (600*HZ)
 
 /*
  *     How often is the function 'arp_check_retries' called.
  *     An entry is invalidated in the time between ARP_TIMEOUT and
- *     (ARP_TIMEOUT+ARP_CHECK_INTERVAL). 
+ *     (ARP_TIMEOUT+ARP_CHECK_INTERVAL).
  */
 
 #define ARP_CHECK_INTERVAL     (60 * HZ)
@@ -147,27 +147,27 @@ static struct timer_list arp_timer =
 /*
  *     The size of the hash table. Must be a power of two.
  *     Maybe we should remove hashing in the future for arp and concentrate
- *     on Patrick Schaaf's Host-Cache-Lookup... 
+ *     on Patrick Schaaf's Host-Cache-Lookup...
  */
 
 #define ARP_TABLE_SIZE  16
 
-struct arp_table *arp_tables[ARP_TABLE_SIZE] = 
+struct arp_table *arp_tables[ARP_TABLE_SIZE] =
 {
        NULL,
 };
 
 /*
- *     The last bits in the IP address are used for the cache lookup. 
+ *     The last bits in the IP address are used for the cache lookup.
  */
+
 #define HASH(paddr)            (htonl(paddr) & (ARP_TABLE_SIZE - 1))
 
 /*
  *     Number of proxy arp entries. This is normally zero and we use it to do
- *     some optimizing for normal uses
+ *     some optimizing for normal uses.
  */
+
 static int proxies = 0;
 
 
@@ -176,9 +176,9 @@ static int proxies = 0;
  *     flag is set, they are always left in the arp cache (permanent entry).
  *     Note: Only fully resolved entries, which don't have any packets in
  *     the queue, can be deleted, since ARP_TIMEOUT is much greater than
- *     ARP_MAX_TRIES*ARP_RES_TIME. 
+ *     ARP_MAX_TRIES*ARP_RES_TIME.
  */
+
 static void arp_check_expire(unsigned long dummy)
 {
        int i;
@@ -186,43 +186,43 @@ static void arp_check_expire(unsigned long dummy)
        unsigned long flags;
        save_flags(flags);
        cli();
-       
-       for (i = 0; i < ARP_TABLE_SIZE; i++) 
+
+       for (i = 0; i < ARP_TABLE_SIZE; i++)
        {
                struct arp_table *entry;
                struct arp_table **pentry = &arp_tables[i];
 
-               while ((entry = *pentry) != NULL) 
+               while ((entry = *pentry) != NULL)
                {
                        if ((now - entry->last_used) > ARP_TIMEOUT
-                               && !(entry->flags & ATF_PERM)) 
+                               && !(entry->flags & ATF_PERM))
                        {
                                *pentry = entry->next;  /* remove from list */
                                if (entry->flags & ATF_PUBL)
                                        proxies--;
-                               del_timer(&entry->timer);       /* Paranoia */                  
+                               del_timer(&entry->timer);       /* Paranoia */
                                kfree_s(entry, sizeof(struct arp_table));
-                       } 
-                       else 
+                       }
+                       else
                                pentry = &entry->next;  /* go to next entry */
                }
        }
        restore_flags(flags);
 
        /*
-        *      Set the timer again. 
+        *      Set the timer again.
         */
 
        del_timer(&arp_timer);
-       arp_timer.expires = ARP_CHECK_INTERVAL; 
+       arp_timer.expires = ARP_CHECK_INTERVAL;
        add_timer(&arp_timer);
 }
 
 
 /*
- *     Release all linked skb's and the memory for this entry. 
+ *     Release all linked skb's and the memory for this entry.
  */
+
 static void arp_release_entry(struct arp_table *entry)
 {
        struct sk_buff *skb;
@@ -230,7 +230,7 @@ static void arp_release_entry(struct arp_table *entry)
        if (entry->flags & ATF_PUBL)
                proxies--;
        /* Release the list of `skb' pointers. */
-       while ((skb = skb_dequeue(&entry->skb)) != NULL) 
+       while ((skb = skb_dequeue(&entry->skb)) != NULL)
        {
                if (skb->free)
                        kfree_skb(skb, FREE_WRITE);
@@ -243,9 +243,9 @@ static void arp_release_entry(struct arp_table *entry)
 
 /*
  *     Create and send an arp packet. If (dest_hw == NULL), we create a broadcast
- *     message. 
+ *     message.
  */
+
 static void arp_send(int type, unsigned long dest_ip, struct device *dev,
        unsigned long src_ip, unsigned char *dest_hw, unsigned char *src_hw)
 {
@@ -256,17 +256,17 @@ static void arp_send(int type, unsigned long dest_ip, struct device *dev,
        /*
         *      No arp on this interface.
         */
-               
+       
        if(dev->flags&IFF_NOARP)
                return;
-               
+
        /*
         *      Allocate a buffer
         */
-        
+       
        skb = alloc_skb(sizeof(struct arphdr)+ 2*(dev->addr_len+4)
                                + dev->hard_header_len, GFP_ATOMIC);
-       if (skb == NULL) 
+       if (skb == NULL)
        {
                printk("ARP: no memory to send an arp packet\n");
                return;
@@ -277,7 +277,7 @@ static void arp_send(int type, unsigned long dest_ip, struct device *dev,
        skb->free = 1;
 
        /*
-        *      Fill the device header for the ARP frame 
+        *      Fill the device header for the ARP frame
         */
 
        dev->hard_header(skb->data,dev,ETH_P_ARP,dest_hw?dest_hw:dev->broadcast,src_hw?src_hw:NULL,skb->len,skb);
@@ -285,17 +285,17 @@ static void arp_send(int type, unsigned long dest_ip, struct device *dev,
        /* Fill out the arp protocol part. */
        arp = (struct arphdr *) (skb->data + dev->hard_header_len);
        arp->ar_hrd = htons(dev->type);
-#ifdef CONFIG_AX25     
+#ifdef CONFIG_AX25
        arp->ar_pro = (dev->type != ARPHRD_AX25)? htons(ETH_P_IP) : htons(AX25_P_IP);
 #else
        arp->ar_pro = htons(ETH_P_IP);
-#endif 
+#endif
        arp->ar_hln = dev->addr_len;
        arp->ar_pln = 4;
        arp->ar_op = htons(type);
 
        arp_ptr=(unsigned char *)(arp+1);
-       
+
        memcpy(arp_ptr, src_hw, dev->addr_len);
        arp_ptr+=dev->addr_len;
        memcpy(arp_ptr, &src_ip,4);
@@ -306,39 +306,39 @@ static void arp_send(int type, unsigned long dest_ip, struct device *dev,
                memset(arp_ptr, 0, dev->addr_len);
        arp_ptr+=dev->addr_len;
        memcpy(arp_ptr, &dest_ip, 4);
-       
+
        dev_queue_xmit(skb, dev, 0);
 }
 
 
 /*
  *     This function is called, if an entry is not resolved in ARP_RES_TIME.
- *     Either resend a request, or give it up and free the entry. 
+ *     Either resend a request, or give it up and free the entry.
  */
+
 static void arp_expire_request (unsigned long arg)
 {
        struct arp_table *entry = (struct arp_table *) arg;
        struct arp_table **pentry;
        unsigned long hash;
        unsigned long flags;
-       
+
        save_flags(flags);
        cli();
-       
+
        /*
         *      Since all timeouts are handled with interrupts enabled, there is a
         *      small chance, that this entry has just been resolved by an incoming
-        *      packet. This is the only race condition, but it is handled... 
+        *      packet. This is the only race condition, but it is handled...
         */
-        
-       if (entry->flags & ATF_COM) 
+       
+       if (entry->flags & ATF_COM)
        {
                restore_flags(flags);
                return;
        }
-       
-       if (--entry->retries > 0) 
+
+       if (--entry->retries > 0)
        {
                unsigned long ip = entry->ip;
                struct device *dev = entry->dev;
@@ -352,19 +352,19 @@ static void arp_expire_request (unsigned long arg)
                                dev->dev_addr);
                return;
        }
-       
+
        /*
         *      Arp request timed out. Delete entry and all waiting packets.
         *      If we give each entry a pointer to itself, we don't have to
         *      loop through everything again. Maybe hash is good enough, but
-        *      I will look at it later. 
+        *      I will look at it later.
         */
-        
+       
        hash = HASH(entry->ip);
        pentry = &arp_tables[hash];
-       while (*pentry != NULL) 
+       while (*pentry != NULL)
        {
-               if (*pentry == entry) 
+               if (*pentry == entry)
                {
                        *pentry = entry->next;  /* delete from linked list */
                        del_timer(&entry->timer);
@@ -377,37 +377,37 @@ static void arp_expire_request (unsigned long arg)
        restore_flags(flags);
        printk("Possible ARP queue corruption.\n");
        /*
-        *      We should never arrive here. 
+        *      We should never arrive here.
         */
 }
 
 
 /*
- *     This will try to retransmit everything on the queue. 
+ *     This will try to retransmit everything on the queue.
  */
+
 static void arp_send_q(struct arp_table *entry, unsigned char *hw_dest)
 {
        struct sk_buff *skb;
-       
-       
+
+
        /*
         *      Empty the entire queue, building its data up ready to send
         */
-        
+       
        if(!(entry->flags&ATF_COM))
        {
                printk("arp_send_q: incomplete entry for %s\n",
                                in_ntoa(entry->ip));
                return;
        }
-       
-       while((skb = skb_dequeue(&entry->skb)) != NULL) 
+
+       while((skb = skb_dequeue(&entry->skb)) != NULL)
        {
                IS_SKB(skb);
                if(!skb->dev->rebuild_header(skb->data,skb->dev,skb->raddr,skb))
                {
-                       skb->arp  = 1;          
+                       skb->arp  = 1;
                        if(skb->sk==NULL)
                                dev_queue_xmit(skb, skb->dev, 0);
                        else
@@ -426,9 +426,9 @@ static void arp_send_q(struct arp_table *entry, unsigned char *hw_dest)
 
 
 /*
- *     Delete an ARP mapping entry in the cache. 
+ *     Delete an ARP mapping entry in the cache.
  */
+
 void arp_destroy(unsigned long ip_addr, int force)
 {
        struct arp_table *entry;
@@ -437,15 +437,15 @@ void arp_destroy(unsigned long ip_addr, int force)
 
        cli();
        pentry = &arp_tables[hash];
-       while ((entry = *pentry) != NULL) 
+       while ((entry = *pentry) != NULL)
        {
-               if (entry->ip == ip_addr) 
+               if (entry->ip == ip_addr)
                {
                        if ((entry->flags & ATF_PERM) && !force)
                                return;
                        *pentry = entry->next;
-                       sti();
                        del_timer(&entry->timer);
+                       sti();
                        arp_release_entry(entry);
                        return;
                }
@@ -455,18 +455,18 @@ void arp_destroy(unsigned long ip_addr, int force)
 }
 
 
-/* 
+/*
  *     Receive an arp request by the device layer. Maybe I rewrite it, to
  *     use the incoming packet for the reply. The time for the current
- *     "overhead" isn't that high... 
+ *     "overhead" isn't that high...
  */
+
 int arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
 {
        /*
-        *      We shouldn't use this type conversion. Check later. 
+        *      We shouldn't use this type conversion. Check later.
         */
-        
+       
        struct arphdr *arp = (struct arphdr *)skb->h.raw;
        unsigned char *arp_ptr= (unsigned char *)(arp+1);
        struct arp_table *entry;
@@ -480,22 +480,22 @@ int arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
        /*
         *      If this test doesn't pass, its not IP, or we should ignore it anyway
         */
-        
-       if (arp->ar_hln != dev->addr_len || dev->type != ntohs(arp->ar_hrd) || dev->flags&IFF_NOARP) 
+       
+       if (arp->ar_hln != dev->addr_len || dev->type != ntohs(arp->ar_hrd) || dev->flags&IFF_NOARP)
        {
                kfree_skb(skb, FREE_READ);
                return 0;
        }
 
        /*
-        *      For now we will only deal with IP addresses. 
+        *      For now we will only deal with IP addresses.
         */
        if (
-#ifdef CONFIG_AX25     
+#ifdef CONFIG_AX25
                (arp->ar_pro != htons(AX25_P_IP) && dev->type == ARPHRD_AX25) ||
-#endif         
+#endif
                (arp->ar_pro != htons(ETH_P_IP) && dev->type != ARPHRD_AX25)
-               || arp->ar_pln != 4) 
+               || arp->ar_pln != 4)
        {
                /* This packet is not for us. Remove it. */
                kfree_skb(skb, FREE_READ);
@@ -513,21 +513,21 @@ int arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
        tha=arp_ptr;
        arp_ptr+=dev->addr_len;
        memcpy(&tip,arp_ptr,4);
-       
+
        /*
         *      Process entry
         */
-       
+
        addr_hint = ip_chk_addr(tip);
 
        hash = HASH(sip);
        proxy_entry = NULL;
-       if (proxies != 0 && addr_hint != IS_MYADDR) 
+       if (proxies != 0 && addr_hint != IS_MYADDR)
        {
                unsigned long dest_hash = HASH(tip);
                cli();
                proxy_entry = arp_tables[dest_hash];
-               while (proxy_entry != NULL) 
+               while (proxy_entry != NULL)
                {
                        if (proxy_entry->ip == tip && proxy_entry->htype==arp->ar_hrd)
                                break;
@@ -537,15 +537,15 @@ int arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
                        memcpy(ha, proxy_entry->ha, dev->addr_len);
                else
                        proxy_entry = NULL;
-       } 
-       else 
+       }
+       else
                cli();
 
        for (entry = arp_tables[hash]; entry != NULL; entry = entry->next)
-               if (entry->ip == sip) 
+               if (entry->ip == sip)
                        break;
-                       
-       if (entry != NULL) 
+
+       if (entry != NULL)
        {
                int old_flags = entry->flags;
                memcpy(entry->ha, sha, arp->ar_hln);
@@ -555,28 +555,28 @@ int arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
                if(entry->htype==0)
                        entry->htype = dev->type;       /* Not good but we have no choice */
                entry->last_used = jiffies;
-               if (!(entry->flags & ATF_COM)) 
+               if (!(entry->flags & ATF_COM))
                {
                        del_timer(&entry->timer);
                        entry->flags |= ATF_COM;
                }
                sti();
-               if (!(old_flags & ATF_COM)) 
+               if (!(old_flags & ATF_COM))
                {
                        /* Send out waiting packets. We might have problems,
                           if someone is manually removing entries right now.
                           I will fix this one. */
                        arp_send_q(entry, sha);
                }
-               if (addr_hint != IS_MYADDR && proxy_entry == NULL) 
+               if (addr_hint != IS_MYADDR && proxy_entry == NULL)
                {
                        kfree_skb(skb, FREE_READ);
                        return 0;
                }
-       } 
-       else 
+       }
+       else
        {
-               if (addr_hint != IS_MYADDR && proxy_entry == NULL) 
+               if (addr_hint != IS_MYADDR && proxy_entry == NULL)
                {
                        /* We don't do "smart arp" and cache all possible
                           entries. That just makes us more work. */
@@ -586,7 +586,7 @@ int arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
                }
                entry = (struct arp_table *)kmalloc(sizeof(struct arp_table),
                                        GFP_ATOMIC);
-               if (entry == NULL) 
+               if (entry == NULL)
                {
                        sti();
                        kfree_skb(skb, FREE_READ);
@@ -610,7 +610,7 @@ int arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
           any more. */
 
        if (arp->ar_op != htons(ARPOP_REQUEST)
-               || tip == INADDR_LOOPBACK) 
+               || tip == INADDR_LOOPBACK)
        {
                /* This wasn't a request, or some bad request for 127.0.0.1
                   has made its way to the net, so delete it. */
@@ -629,16 +629,16 @@ int arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
 
 
 /*
- *     Find an arp mapping in the cache. If not found, post a request. 
+ *     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 sk_buff *skb)
 {
        struct arp_table *entry;
        unsigned long hash;
 
-       switch (ip_chk_addr(paddr)) 
+       switch (ip_chk_addr(paddr))
        {
                case IS_MYADDR:
                        printk("ARP: arp called for own IP address\n");
@@ -653,34 +653,34 @@ int arp_find(unsigned char *haddr, unsigned long paddr, struct device *dev,
 
        hash = HASH(paddr);
        cli();
-       
+
        /*
-        *      Find an entry 
+        *      Find an entry
         */
        for (entry = arp_tables[hash]; entry != NULL; entry = entry->next)
-               if (entry->ip == paddr) 
+               if (entry->ip == paddr)
                        break;
-                       
-       
+
+
        if (entry != NULL)      /* It exists */
        {
-               if (!(entry->flags & ATF_COM)) 
+               if (!(entry->flags & ATF_COM))
                {
-                       /* 
+                       /*
                         *      A request was already send, but no reply yet. Thus
                         *      queue the packet with the previous attempt
                         */
-                        
+                       
                        if (skb != NULL)
                                skb_queue_tail(&entry->skb, skb);
                        sti();
                        return 1;
                }
-               
+
                /*
                 *      Update the record
                 */
-                
+               
                entry->last_used = jiffies;
                memcpy(haddr, entry->ha, dev->addr_len);
                if (skb)
@@ -690,12 +690,12 @@ int arp_find(unsigned char *haddr, unsigned long paddr, struct device *dev,
        }
 
        /*
-        *      Create a new unresolved entry. 
+        *      Create a new unresolved entry.
         */
-        
+       
        entry = (struct arp_table *) kmalloc(sizeof(struct arp_table),
                                        GFP_ATOMIC);
-       if (entry != NULL) 
+       if (entry != NULL)
        {
                entry->ip = paddr;
                entry->hlen = dev->addr_len;
@@ -714,8 +714,8 @@ int arp_find(unsigned char *haddr, unsigned long paddr, struct device *dev,
                skb_queue_head_init(&entry->skb);
                if (skb != NULL)
                        skb_queue_tail(&entry->skb, skb);
-       } 
-       else 
+       }
+       else
        {
                if (skb != NULL && skb->free)
                        kfree_skb(skb, FREE_WRITE);
@@ -723,21 +723,21 @@ int arp_find(unsigned char *haddr, unsigned long paddr, struct device *dev,
        sti();
 
        /*
-        *      If we didn't find an entry, we will try to send an ARP packet. 
+        *      If we didn't find an entry, we will try to send an ARP packet.
         */
-        
+       
        arp_send(ARPOP_REQUEST, paddr, dev, saddr, NULL, dev->dev_addr);
 
        return 1;
 }
 
 
-/* 
- *     Write the contents of the ARP cache to a PROCfs file. 
+/*
+ *     Write the contents of the ARP cache to a PROCfs file.
  *
  *     Will change soon to ASCII format
  */
+
 int arp_get_info(char *buffer, char **start, off_t offset, int length)
 {
        struct arp_table *entry;
@@ -749,9 +749,9 @@ int arp_get_info(char *buffer, char **start, off_t offset, int length)
 
        cli();
        /* Loop over the ARP table and copy structures to the buffer. */
-       for (i = 0; i < ARP_TABLE_SIZE; i++) 
+       for (i = 0; i < ARP_TABLE_SIZE; i++)
        {
-               for (entry = arp_tables[i]; entry; entry = entry->next) 
+               for (entry = arp_tables[i]; entry; entry = entry->next)
                {
                        memset(req, 0, sizeof(struct arpreq));
                        req->arp_pa.sa_family = AF_INET;
@@ -783,11 +783,11 @@ int arp_get_info(char *buffer, char **start, off_t offset, int length)
 }
 
 
-/* 
+/*
  *     This will find an entry in the ARP table by looking at the IP address.
- *     Be careful, interrupts are turned off on exit!!!  
+ *     Be careful, interrupts are turned off on exit!!!
  */
+
 static struct arp_table *arp_lookup(unsigned long paddr)
 {
        struct arp_table *entry;
@@ -801,9 +801,9 @@ static struct arp_table *arp_lookup(unsigned long paddr)
 
 
 /*
- *     Set (create) an ARP cache entry. 
+ *     Set (create) an ARP cache entry.
  */
+
 static int arp_req_set(struct arpreq *req)
 {
        struct arpreq r;
@@ -824,7 +824,7 @@ static int arp_req_set(struct arpreq *req)
         * We have to be compatible with BSD UNIX, so we have to
         * assume that a "not set" value (i.e. 0) means Ethernet.
         */
-        
+       
        switch (r.arp_ha.sa_family) {
                case 0:
                        /* Moan about this. ARP family 0 is NetROM and _will_ be needed */
@@ -833,24 +833,24 @@ static int arp_req_set(struct arpreq *req)
                        htype = ARPHRD_ETHER;
                        hlen = ETH_ALEN;
                        break;
-#ifdef CONFIG_AX25                     
+#ifdef CONFIG_AX25
                case ARPHRD_AX25:
                        htype = ARPHRD_AX25;
                        hlen = 7;
                        break;
-#endif                 
+#endif
                default:
                        return -EPFNOSUPPORT;
        }
 
        si = (struct sockaddr_in *) &r.arp_pa;
        ip = si->sin_addr.s_addr;
-       if (ip == 0) 
+       if (ip == 0)
        {
                printk("ARP: SETARP: requested PA is 0.0.0.0 !\n");
                return -EINVAL;
        }
-       
+
        /*
         *      Is it reachable directly ?
         */
@@ -860,28 +860,28 @@ static int arp_req_set(struct arpreq *req)
                return -ENETUNREACH;
 
        /*
-        *      Is there an existing entry for this address? 
+        *      Is there an existing entry for this address?
         */
-        
+       
        hash = HASH(ip);
        cli();
-       
+
        /*
         *      Find the entry
         */
        for (entry = arp_tables[hash]; entry != NULL; entry = entry->next)
-               if (entry->ip == ip) 
+               if (entry->ip == ip)
                        break;
-                       
+
        /*
         *      Do we need to create a new entry
         */
-        
-       if (entry == NULL) 
+       
+       if (entry == NULL)
        {
                entry = (struct arp_table *) kmalloc(sizeof(struct arp_table),
                                        GFP_ATOMIC);
-               if (entry == NULL) 
+               if (entry == NULL)
                {
                        sti();
                        return -ENOMEM;
@@ -892,14 +892,14 @@ static int arp_req_set(struct arpreq *req)
                entry->next = arp_tables[hash];
                arp_tables[hash] = entry;
                skb_queue_head_init(&entry->skb);
-       } 
-       else 
+       }
+       else
                if (entry->flags & ATF_PUBL)
                        proxies--;
        /*
-        *      We now have a pointer to an ARP entry.  Update it! 
+        *      We now have a pointer to an ARP entry.  Update it!
         */
-        
+       
        memcpy(&entry->ha, &r.arp_ha.sa_data, hlen);
        entry->last_used = jiffies;
        entry->flags = r.arp_flags | ATF_COM;
@@ -913,9 +913,9 @@ static int arp_req_set(struct arpreq *req)
 
 
 /*
- *     Get an ARP cache entry. 
+ *     Get an ARP cache entry.
  */
+
 static int arp_req_get(struct arpreq *req)
 {
        struct arpreq r;
@@ -923,64 +923,64 @@ static int arp_req_get(struct arpreq *req)
        struct sockaddr_in *si;
 
        /*
-        *      We only understand about IP addresses... 
+        *      We only understand about IP addresses...
         */
-        
-       memcpy_fromfs(&r, req, sizeof(r));
        
-       if (r.arp_pa.sa_family != AF_INET) 
+       memcpy_fromfs(&r, req, sizeof(r));
+
+       if (r.arp_pa.sa_family != AF_INET)
                return -EPFNOSUPPORT;
 
        /*
-        *      Is there an existing entry for this address? 
+        *      Is there an existing entry for this address?
         */
-        
+       
        si = (struct sockaddr_in *) &r.arp_pa;
        entry = arp_lookup(si->sin_addr.s_addr);
 
-       if (entry == NULL) 
+       if (entry == NULL)
        {
                sti();
                return -ENXIO;
        }
 
        /*
-        *      We found it; copy into structure. 
+        *      We found it; copy into structure.
         */
-        
+       
        memcpy(r.arp_ha.sa_data, &entry->ha, entry->hlen);
        r.arp_ha.sa_family = entry->htype;
        r.arp_flags = entry->flags;
        sti();
 
        /*
-        *      Copy the information back 
+        *      Copy the information back
         */
-        
+       
        memcpy_tofs(req, &r, sizeof(r));
        return 0;
 }
 
 
 /*
- *     Handle an ARP layer I/O control request. 
+ *     Handle an ARP layer I/O control request.
  */
+
 int arp_ioctl(unsigned int cmd, void *arg)
 {
        struct arpreq r;
        struct sockaddr_in *si;
        int err;
 
-       switch(cmd) 
+       switch(cmd)
        {
                case DDIOCSDBG:
                        return dbg_ioctl(arg, DBG_ARP);
                case SIOCDARP:
-                       if (!suser()) 
+                       if (!suser())
                                return -EPERM;
                        err = verify_area(VERIFY_READ, arg, sizeof(struct arpreq));
-                       if(err) 
+                       if(err)
                                return err;
                        memcpy_fromfs(&r, arg, sizeof(r));
                        if (r.arp_pa.sa_family != AF_INET)
@@ -990,14 +990,14 @@ int arp_ioctl(unsigned int cmd, void *arg)
                        return 0;
                case SIOCGARP:
                        err = verify_area(VERIFY_WRITE, arg, sizeof(struct arpreq));
-                       if(err) 
+                       if(err)
                                return err;
                        return arp_req_get((struct arpreq *)arg);
                case SIOCSARP:
-                       if (!suser()) 
+                       if (!suser())
                                return -EPERM;
                        err = verify_area(VERIFY_READ, arg, sizeof(struct arpreq));
-                       if(err) 
+                       if(err)
                                return err;
                        return arp_req_set((struct arpreq *)arg);
                default:
@@ -1009,10 +1009,10 @@ int arp_ioctl(unsigned int cmd, void *arg)
 
 
 /*
- *     Called once on startup. 
+ *     Called once on startup.
  */
 
-static struct packet_type arp_packet_type = 
+static struct packet_type arp_packet_type =
 {
        0,      /* Should be: __constant_htons(ETH_P_ARP) - but this _doesn't_ come out constant! */
        0,              /* copy */
@@ -1020,7 +1020,7 @@ static struct packet_type arp_packet_type =
        NULL,
        NULL
 };
+
 void arp_init (void)
 {
        /* Register the packet type */
index 963e32a0b01b9e794f2183f148a737779d3fb2ab..2a30284bda0b61119bf3e62b75bd5dd8fc5cf607 100644 (file)
@@ -319,6 +319,7 @@ int dev_close(struct device *dev)
 
 void dev_queue_xmit(struct sk_buff *skb, struct device *dev, int pri)
 {
+       unsigned long flags;
        int where = 0;          /* used to say if the packet should go  */
                                /* at the front or the back of the      */
                                /* queue.                               */
@@ -335,7 +336,6 @@ void dev_queue_xmit(struct sk_buff *skb, struct device *dev, int pri)
        IS_SKB(skb);
     
        skb->dev = dev;
-       start_bh_atomic();
 
        /*
         *      This just eliminates some race conditions, but not all... 
@@ -348,7 +348,6 @@ void dev_queue_xmit(struct sk_buff *skb, struct device *dev, int pri)
                 */
                printk("dev_queue_xmit: worked around a missed interrupt\n");
                dev->hard_start_xmit(NULL, dev);
-               end_bh_atomic();
                return;
        }
 
@@ -376,33 +375,27 @@ void dev_queue_xmit(struct sk_buff *skb, struct device *dev, int pri)
         */
         
        if (!skb->arp && dev->rebuild_header(skb->data, dev, skb->raddr, skb)) {
-               end_bh_atomic();
                return;
        }
 
-       /*
-        *      This is vitally important. We _MUST_ keep packets in order. While tcp/ip
-        *      suffers only a slow down some IPX apps, and all the AX.25 code will break
-        *      if it occurs out of order. 
-        *
-        *      This is commented out while I fix a few 'side effects'
-        */
+       save_flags(flags);
+       cli();  
+       if (!where) {
+               skb_queue_tail(dev->buffs + pri,skb);
+               skb = skb_dequeue(dev->buffs + pri);
+       }
+       restore_flags(flags);
 
-       if ((where==1 || skb_peek(&dev->buffs[pri])==NULL) && dev->hard_start_xmit(skb, dev) == 0) 
-       {
-               end_bh_atomic();
+       if (dev->hard_start_xmit(skb, dev) == 0) {
                return;
        }
 
        /*
         *      Transmission failed, put skb back into a list. 
         */
-
-       if(where)
-               skb_queue_head(&dev->buffs[pri],skb);
-       else
-               skb_queue_tail(&dev->buffs[pri],skb);
-       end_bh_atomic();
+       cli();
+       skb_queue_head(dev->buffs + pri,skb);
+       restore_flags(flags);
 }
 
 /*
index 0aa98ea6b9612b448ed938feb70f209d8c1a5e3e..5dacf6de9eab4a22263562be99b7f627aae4690a 100644 (file)
@@ -28,7 +28,6 @@
  *             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
-#include <linux/string.h>
  *             2 of the License, or (at your option) any later version.
  */
 #include <linux/types.h>
@@ -39,6 +38,7 @@
 #include <linux/in.h>
 #include <linux/inet.h>
 #include <linux/netdevice.h>
+#include <linux/string.h>
 #include "snmp.h"
 #include "ip.h"
 #include "route.h"
@@ -313,8 +313,10 @@ static void icmp_unreach(struct icmphdr *icmph, struct sk_buff *skb)
  *     Handle ICMP_REDIRECT. 
  */
 
-static void icmp_redirect(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev)
+static void icmp_redirect(struct icmphdr *icmph, struct sk_buff *skb,
+       struct device *dev, unsigned long source)
 {
+       struct rtable *rt;
        struct iphdr *iph;
        unsigned long ip;
 
@@ -340,8 +342,16 @@ static void icmp_redirect(struct icmphdr *icmph, struct sk_buff *skb, struct dev
 #endif
                case ICMP_REDIR_HOST:
                        /*
-                        *      Add better route to host
+                        *      Add better route to host.
+                        *      But first check that the redirect
+                        *      comes from the old gateway..
                         */
+                       rt = ip_rt_route(ip, NULL, NULL);
+                       if (!rt)
+                               break;
+                       if (rt->rt_gateway != source)
+                               break;
+                       printk("redirect from %08lx\n", source);
                        ip_rt_add((RTF_DYNAMIC | RTF_MODIFIED | RTF_HOST | RTF_GATEWAY),
                                ip, 0, icmph->un.gateway, dev);
                        break;
@@ -657,7 +667,7 @@ int icmp_rcv(struct sk_buff *skb1, struct device *dev, struct options *opt,
                        return(0);
                case ICMP_REDIRECT:
                        icmp_statistics.IcmpInRedirects++;
-                       icmp_redirect(icmph, skb1, dev);
+                       icmp_redirect(icmph, skb1, dev, saddr);
                        return(0);
                case ICMP_ECHO: 
                        icmp_statistics.IcmpInEchos++;