Commit 37b4c9bd authored by Linus Torvalds's avatar Linus Torvalds

Import 1.1.5

parent b12c3ada
VERSION = 1
PATCHLEVEL = 1
SUBLEVEL = 4
SUBLEVEL = 5
all: Version zImage
......
......@@ -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++;
......
......@@ -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>
......@@ -58,10 +58,10 @@
* 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 */
......
......@@ -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);
}
/*
......
......@@ -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++;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment