Commit 728d1c78 authored by Linus Torvalds's avatar Linus Torvalds

Import 0.99.15c

parent f938a5c8
VERSION = 0.99
PATCHLEVEL = 15
ALPHA = b
ALPHA = c
all: Version zImage
......
......@@ -301,7 +301,7 @@ static void select_callback(unsigned long unused)
static void floppy_select(unsigned int nr)
{
static struct timer_list select = { NULL, 0, 0, select_callback };
static struct timer_list select = { NULL, NULL, 0, 0, select_callback };
if (current_drive == (current_DOR & 3)) {
floppy_ready();
......@@ -324,10 +324,10 @@ static void motor_on_callback(unsigned long nr)
}
static struct timer_list motor_on_timer[4] = {
{ NULL, 0, 0, motor_on_callback },
{ NULL, 0, 1, motor_on_callback },
{ NULL, 0, 2, motor_on_callback },
{ NULL, 0, 3, motor_on_callback }
{ NULL, NULL, 0, 0, motor_on_callback },
{ NULL, NULL, 0, 1, motor_on_callback },
{ NULL, NULL, 0, 2, motor_on_callback },
{ NULL, NULL, 0, 3, motor_on_callback }
};
static void motor_off_callback(unsigned long nr)
......@@ -341,10 +341,10 @@ static void motor_off_callback(unsigned long nr)
}
static struct timer_list motor_off_timer[4] = {
{ NULL, 0, 0, motor_off_callback },
{ NULL, 0, 1, motor_off_callback },
{ NULL, 0, 2, motor_off_callback },
{ NULL, 0, 3, motor_off_callback }
{ NULL, NULL, 0, 0, motor_off_callback },
{ NULL, NULL, 0, 1, motor_off_callback },
{ NULL, NULL, 0, 2, motor_off_callback },
{ NULL, NULL, 0, 3, motor_off_callback }
};
static void floppy_on(unsigned int nr)
......
......@@ -60,6 +60,7 @@ static XD_SIGNATURE xd_sigs[] = {
{ 0x0008,"06/24/88(C) Copyright 1988 Western Digital Corp.",xd_wd_init_controller,xd_wd_init_drive," Western Digital WDXT-GEN2" }, /* Dan Newcombe, newcombe@aa.csc.peachnet.edu */
{ 0x0015,"SEAGATE ST11 BIOS REVISION",xd_seagate_init_controller,xd_seagate_init_drive," Seagate ST11M/R" }, /* Salvador Abreu, spa@fct.unl.pt */
{ 0x0010,"ST11R BIOS",xd_seagate_init_controller,xd_seagate_init_drive," Seagate ST11M/R" }, /* Risto Kankkunen, risto.kankkunen@cs.helsinki.fi */
{ 0x1000,"(c)Copyright 1987 SMS",xd_omti_init_controller,xd_omti_init_drive,"n OMTI 5520" }, /* Dirk Melchers, dirk@merlin.nbg.sub.org */
};
static u_char *xd_bases[] =
{
......@@ -580,6 +581,34 @@ static void xd_seagate_init_drive (u_char drive)
printk("xd_seagate_init_drive: error reading geometry from drive %d\n",drive);
}
/* Omti support courtesy Dirk Melchers */
static void xd_omti_init_controller (u_char *address)
{
switch ((u_long) address) {
case 0xC8000: xd_iobase = 0x320; break;
case 0xD0000: xd_iobase = 0x324; break;
case 0xD8000: xd_iobase = 0x328; break;
case 0xE0000: xd_iobase = 0x32C; break;
default: printk("xd_omti_init_controller: unsupported BIOS address %p\n",address);
xd_iobase = 0x320; break;
}
xd_irq = 5; /* the IRQ and DMA channel are fixed on the Omti controllers */
xd_dma = 3;
xd_maxsectors = 0x40;
outb(0,XD_RESET); /* reset the controller */
}
static void xd_omti_init_drive (u_char drive)
{
/* gets infos from drive */
xd_override_init_drive(drive);
/* set other parameters, Hardcoded, not that nice :-) */
xd_info[drive].control = 2;
}
/* xd_override_init_drive: this finds disk geometry in a "binary search" style, narrowing in on the "correct" number of heads
etc. by trying values until it gets the highest successful value. Idea courtesy Salvador Abreu (spa@fct.unl.pt). */
static void xd_override_init_drive (u_char drive)
......
......@@ -34,7 +34,11 @@
#endif
#ifndef KBD_DEFLEDS
#define KBD_DEFLEDS (1 << VC_NUMLOCK)
/*
* Some laptops take the 789uiojklm,. keys as number pad when NumLock
* is on. This seems a good reason to start with NumLock off.
*/
#define KBD_DEFLEDS 0
#endif
#ifndef KBD_DEFLOCK
......
......@@ -523,6 +523,9 @@ int tty_ioctl(struct inode * inode, struct file * file,
case TIOCSTI:
if ((current->tty != dev) && !suser())
return -EACCES;
retval = verify_area(VERIFY_READ, (void *) arg, 1);
if (retval)
return retval;
put_tty_queue(get_fs_byte((char *) arg), &tty->read_q);
TTY_READ_FLUSH(tty);
return 0;
......
......@@ -86,7 +86,7 @@ kd_nosound(unsigned long ignored)
void
kd_mksound(unsigned int count, unsigned int ticks)
{
static struct timer_list sound_timer = { NULL, 0, 0, kd_nosound };
static struct timer_list sound_timer = { NULL, NULL, 0, 0, kd_nosound };
cli();
del_timer(&sound_timer);
......
......@@ -377,7 +377,7 @@ el3_start_xmit(struct sk_buff *skb, struct device *dev)
return 0;
if (el3_debug > 4) {
printk("%s: el3_start_xmit(lenght = %d) called, status %4.4x.\n",
printk("%s: el3_start_xmit(lenght = %ld) called, status %4.4x.\n",
dev->name, skb->len, inw(ioaddr + EL3_STATUS));
}
#ifndef final_version
......
......@@ -127,10 +127,12 @@ static unsigned char generic_sense[6] = {REQUEST_SENSE, 0,0,0, 255, 0};
static struct blist blacklist[] =
{
{"DENON","DRD-25X","V"}, /* A cdrom that locks up when probed at lun != 0 */
{"MAXTOR","XT-3280","PR02"}, /* Locks-up when LUN>0 polled. */
{"MAXTOR","XT-4380S","B3C"}, /* Locks-up when LUN>0 polled. */
{"MAXTOR","MXT-1240S","I1.2"}, /* Locks up when LUN > 0 polled */
{"MAXTOR","XT-4170S","B5A"}, /* Locks-up sometimes when LUN>0 polled. */
{"NEC","CD-ROM DRIVE:841","1.0"}, /* Locks-up when LUN>0 polled. */
{"RODIME","RO3000S","2.33"}, /* Locks up if polled for lun != 0 */
{"SEAGATE", "ST157N", "\004|j"}, /* causes failed REQUEST SENSE on lun 1 for aha152x
* controller, which causes SCSI code to reset bus.*/
{"SEAGATE", "ST296","921"}, /* Responds to all lun */
......@@ -387,7 +389,7 @@ static void scan_scsis (void)
scsi_devices[NR_SCSI_DEVICES].tagged_queue = 0;
if ((scsi_devices[NR_SCSI_DEVICES].scsi_level == SCSI_2) &&
if ((scsi_devices[NR_SCSI_DEVICES].scsi_level >= SCSI_2) &&
(scsi_result[7] & 2)) {
scsi_devices[NR_SCSI_DEVICES].tagged_supported = 1;
scsi_devices[NR_SCSI_DEVICES].current_tag = 0;
......@@ -451,6 +453,9 @@ static void scan_scsis (void)
/* Some scsi devices cannot be polled for lun != 0
due to firmware bugs */
if(blacklisted(scsi_result)) break;
/* Old drives like the MAXTOR XT-3280 say vers=0 */
if ((scsi_result[2] & 0x07) == 0)
break;
/* Some scsi-1 peripherals do not handle lun != 0.
I am assuming that scsi-2 peripherals do better */
if((scsi_result[2] & 0x07) == 1 &&
......
......@@ -140,7 +140,7 @@ struct snd_wait {
#define DEFINE_TIMER(name, proc) \
static struct timer_list name = \
{NULL, 0, 0, proc}
{NULL, NULL, 0, 0, proc}
/*
* The ACTIVATE_TIMER requests system to call 'proc' after 'time' ticks.
......
......@@ -363,11 +363,9 @@ int ext2_new_block (struct super_block * sb, unsigned long goal,
/*
* First, test whether the goal block is free.
*/
i = ((goal - es->s_first_data_block) / EXT2_BLOCKS_PER_GROUP(sb));
if (i >= EXT2_BLOCKS_PER_GROUP(sb) || i < 0) {
i = 0;
if (goal < es->s_first_data_block || goal >= es->s_blocks_count)
goal = es->s_first_data_block;
}
i = (goal - es->s_first_data_block) / EXT2_BLOCKS_PER_GROUP(sb);
gdp = get_group_desc (sb, i, &bh2);
if (gdp->bg_free_blocks_count > 0) {
j = ((goal - es->s_first_data_block) % EXT2_BLOCKS_PER_GROUP(sb));
......
......@@ -653,15 +653,13 @@ int ext2_rmdir (struct inode * dir, const char * name, int len)
retval = -ENOTDIR;
goto end_rmdir;
}
if (!empty_dir (inode)) {
down(&inode->i_sem);
if (!empty_dir (inode))
retval = -ENOTEMPTY;
goto end_rmdir;
}
if (de->inode != inode->i_ino) {
else if (de->inode != inode->i_ino)
retval = -ENOENT;
goto end_rmdir;
}
if (inode->i_count > 1) {
else {
if (inode->i_count > 1) {
/*
* Are we deleting the last instance of a busy directory?
* Better clean up if so.
......@@ -669,9 +667,11 @@ int ext2_rmdir (struct inode * dir, const char * name, int len)
* Make directory empty (it will be truncated when finally
* dereferenced). This also inhibits ext2_add_entry.
*/
inode->i_size = 0;
inode->i_size = 0;
}
retval = ext2_delete_entry (de, bh);
}
retval = ext2_delete_entry (de, bh);
up(&inode->i_sem);
if (retval)
goto end_rmdir;
bh->b_dirt = 1;
......
......@@ -124,7 +124,7 @@ typedef void nonconst;
static void hpfs_read_inode(struct inode *);
static void hpfs_put_super(struct super_block *);
static void hpfs_statfs(struct super_block *, struct statfs *);
static int hpfs_remount_fs(struct super_block *, int *);
static int hpfs_remount_fs(struct super_block *, int *, char *);
static const struct super_operations hpfs_sops =
{
......@@ -752,7 +752,7 @@ static void hpfs_statfs(struct super_block *s, struct statfs *buf)
* remount. Don't let read only be turned off.
*/
static int hpfs_remount_fs(struct super_block *s, int *flags)
static int hpfs_remount_fs(struct super_block *s, int *flags, char *data)
{
if (!(*flags & MS_RDONLY))
return -EINVAL;
......
......@@ -384,6 +384,7 @@ struct inode * get_empty_inode(void)
clear_inode(inode);
inode->i_count = 1;
inode->i_nlink = 1;
inode->i_sem.count = 1;
nr_free_inodes--;
if (nr_free_inodes < 0) {
printk ("VFS: get_empty_inode: bad free inode count.\n");
......
......@@ -275,7 +275,7 @@ int open_namei(const char * pathname, int flag, int mode,
struct inode ** res_inode, struct inode * base)
{
const char * basename;
int namelen,error,i;
int namelen,error;
struct inode * dir, *inode;
struct task_struct ** p;
......@@ -297,43 +297,35 @@ int open_namei(const char * pathname, int flag, int mode,
*res_inode=dir;
return 0;
}
for (i = 0; i < 5; i++) { /* races... */
dir->i_count++; /* lookup eats the dir */
dir->i_count++; /* lookup eats the dir */
if (flag & O_CREAT) {
down(&dir->i_sem);
error = lookup(dir,basename,namelen,&inode);
if (!error)
break;
if (!(flag & O_CREAT)) {
iput(dir);
return error;
}
if (!permission(dir,MAY_WRITE | MAY_EXEC)) {
iput(dir);
return -EACCES;
}
if (!dir->i_op || !dir->i_op->create) {
iput(dir);
return -EACCES;
}
if (IS_RDONLY(dir)) {
iput(dir);
return -EROFS;
}
dir->i_count++; /* create eats the dir */
error = dir->i_op->create(dir,basename,namelen,mode,res_inode);
if (error != -EEXIST) {
if (!error) {
if (flag & O_EXCL) {
iput(inode);
error = -EEXIST;
}
} else if (!permission(dir,MAY_WRITE | MAY_EXEC))
error = -EACCES;
else if (!dir->i_op || !dir->i_op->create)
error = -EACCES;
else if (IS_RDONLY(dir))
error = -EROFS;
else {
dir->i_count++; /* create eats the dir */
error = dir->i_op->create(dir,basename,namelen,mode,res_inode);
up(&dir->i_sem);
iput(dir);
return error;
}
}
up(&dir->i_sem);
} else
error = lookup(dir,basename,namelen,&inode);
if (error) {
iput(dir);
return error;
}
if ((flag & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) {
iput(dir);
iput(inode);
return -EEXIST;
}
error = follow_link(dir,inode,flag,mode,&inode);
if (error)
return error;
......@@ -415,7 +407,10 @@ int do_mknod(const char * filename, int mode, dev_t dev)
iput(dir);
return -EPERM;
}
return dir->i_op->mknod(dir,basename,namelen,mode,dev);
down(&dir->i_sem);
error = dir->i_op->mknod(dir,basename,namelen,mode,dev);
up(&dir->i_sem);
return error;
}
asmlinkage int sys_mknod(const char * filename, int mode, dev_t dev)
......@@ -467,7 +462,10 @@ static int do_mkdir(const char * pathname, int mode)
iput(dir);
return -EPERM;
}
return dir->i_op->mkdir(dir,basename,namelen,mode);
down(&dir->i_sem);
error = dir->i_op->mkdir(dir,basename,namelen,mode);
up(&dir->i_sem);
return error;
}
asmlinkage int sys_mkdir(const char * pathname, int mode)
......@@ -590,7 +588,10 @@ static int do_symlink(const char * oldname, const char * newname)
iput(dir);
return -EPERM;
}
return dir->i_op->symlink(dir,basename,namelen,oldname);
down(&dir->i_sem);
error = dir->i_op->symlink(dir,basename,namelen,oldname);
up(&dir->i_sem);
return error;
}
asmlinkage int sys_symlink(const char * oldname, const char * newname)
......@@ -646,7 +647,10 @@ static int do_link(struct inode * oldinode, const char * newname)
iput(oldinode);
return -EPERM;
}
return dir->i_op->link(oldinode, dir, basename, namelen);
down(&dir->i_sem);
error = dir->i_op->link(oldinode, dir, basename, namelen);
up(&dir->i_sem);
return error;
}
asmlinkage int sys_link(const char * oldname, const char * newname)
......@@ -719,8 +723,11 @@ static int do_rename(const char * oldname, const char * newname)
iput(new_dir);
return -EPERM;
}
return old_dir->i_op->rename(old_dir, old_base, old_len,
down(&new_dir->i_sem);
error = old_dir->i_op->rename(old_dir, old_base, old_len,
new_dir, new_base, new_len);
up(&new_dir->i_sem);
return error;
}
asmlinkage int sys_rename(const char * oldname, const char * newname)
......
......@@ -441,7 +441,7 @@ static int get_maps(int pid, char *buf)
return sz;
}
asmlinkage int get_module_list( char *);
extern int get_module_list(char *);
static int array_read(struct inode * inode, struct file * file,char * buf, int count)
{
......
......@@ -89,7 +89,7 @@ extern __inline__ int clear_bit(int nr, int * addr)
addr += nr >> 5;
mask = 1 << (nr & 0x1f);
cli();
retval = (mask & *addr) == 0;
retval = (mask & *addr) != 0;
*addr &= ~mask;
sti();
return retval;
......
......@@ -171,6 +171,7 @@ struct inode {
time_t i_ctime;
unsigned long i_blksize;
unsigned long i_blocks;
struct semaphore i_sem;
struct inode_operations * i_op;
struct super_block * i_sb;
struct wait_queue * i_wait;
......
......@@ -21,7 +21,7 @@
/* IEEE 802.3 Ethernet magic constants. */
#define ETH_ALEN 6 /* #bytes in eth addr */
#define ETH_HLEN 14 /* #bytes in eth header */
#define ETH_ZLEN 64 /* min #bytes in frame */
#define ETH_ZLEN 60 /* min #bytes in frame */
#define ETH_FLEN 1536 /* max #bytes in frame */
#define ETH_DLEN (ETH_FLEN - ETH_HLEN) /* max #bytes of data */
......
......@@ -21,21 +21,32 @@
#include <linux/if.h>
/* This structure gets passed by the SIOCADDRTOLD and SIOCDELRTOLD calls. */
struct old_rtentry {
unsigned long rt_genmask;
struct sockaddr rt_dst;
struct sockaddr rt_gateway;
short rt_flags;
short rt_refcnt;
unsigned long rt_use;
char *rt_dev;
};
/* This structure gets passed by the SIOCADDRT and SIOCDELRT calls. */
struct rtentry {
unsigned long rt_hash; /* hash key for lookups */
#define rt_genmask rt_hash
struct sockaddr rt_dst;
struct sockaddr rt_gateway;
short rt_flags;
short rt_refcnt;
unsigned long rt_use;
#ifdef BSD_COMPATIBLE
struct ifnet *rt_ifp;
#else
void *rt_dev;
#endif
unsigned long rt_hash; /* hash key for lookups */
struct sockaddr rt_dst; /* target address */
struct sockaddr rt_gateway; /* gateway addr (RTF_GATEWAY) */
struct sockaddr rt_genmask; /* target network mask (IP) */
short rt_flags;
short rt_refcnt;
unsigned long rt_use;
struct ifnet *rt_ifp;
short rt_metric; /* +1 for binary compatibility! */
char *rt_dev; /* forcing the device at add */
};
#define RTF_UP 0x0001 /* route useable */
#define RTF_GATEWAY 0x0002 /* destination is a gateway */
#define RTF_HOST 0x0004 /* host entry (net otherwise) */
......
......@@ -479,6 +479,21 @@ extern inline void select_wait(struct wait_queue ** wait_address, select_table *
p->nr++;
}
extern void __down(struct semaphore * sem);
extern inline void down(struct semaphore * sem)
{
if (sem->count <= 0)
__down(sem);
sem->count--;
}
extern inline void up(struct semaphore * sem)
{
sem->count++;
wake_up(&sem->wait);
}
static inline unsigned long _get_base(char * addr)
{
unsigned long __base;
......
......@@ -39,6 +39,10 @@ struct ip_config {
#define SIOCGPGRP 0x8904
#define SIOCATMARK 0x8905
/* Routing table calls. */
#define SIOCADDRT 0x890B /* add routing table entry */
#define SIOCDELRT 0x890C /* delete routing table entry */
/* Socket configuration controls. */
#define SIOCGIFNAME 0x8910 /* get iface name */
#define SIOCSIFLINK 0x8911 /* set iface channel */
......@@ -64,9 +68,9 @@ struct ip_config {
#define SIOCGIFENCAP 0x8925 /* get/set slip encapsulation */
#define SIOCSIFENCAP 0x8926
/* Routing table calls. */
#define SIOCADDRT 0x8940 /* add routing table entry */
#define SIOCDELRT 0x8941 /* delete routing table entry */
/* Routing table calls (oldrtent - don't use) */
#define SIOCADDRTOLD 0x8940 /* add routing table entry */
#define SIOCDELRTOLD 0x8941 /* delete routing table entry */
/* ARP cache control calls. */
#define SIOCDARP 0x8950 /* delete ARP table entry */
......
......@@ -75,6 +75,7 @@ extern struct timer_struct timer_table[32];
*/
struct timer_list {
struct timer_list *next;
struct timer_list *prev;
unsigned long expires;
unsigned long data;
void (*function)(unsigned long);
......
......@@ -11,6 +11,13 @@ struct wait_queue {
struct wait_queue * next;
};
struct semaphore {
int count;
struct wait_queue * wait;
};
#define MUTEX ((struct semaphore) { 1, NULL })
struct select_table_entry {
struct wait_queue wait;
struct wait_queue ** wait_address;
......
......@@ -131,6 +131,8 @@ static void xd_wd_init_controller (u_char *address);
static void xd_wd_init_drive (u_char drive);
static void xd_seagate_init_controller (u_char *address);
static void xd_seagate_init_drive (u_char drive);
static void xd_omti_init_controller (u_char *address);
static void xd_omti_init_drive (u_char drive);
static void xd_setparam (u_char command,u_char drive,u_char heads,u_short cylinders,u_short rwrite,u_short wprecomp,u_char ecc);
static void xd_override_init_drive (u_char drive);
......
......@@ -233,8 +233,7 @@ free_modules( void)
/*
* Called by the /proc file system to return a current list of modules.
*/
int
get_module_list( char *buf)
int get_module_list(char *buf)
{
char *p;
char *q;
......
......@@ -361,6 +361,19 @@ void wake_up_interruptible(struct wait_queue **q)
} while (tmp != *q);
}
void __down(struct semaphore * sem)
{
struct wait_queue wait = { current, NULL };
add_wait_queue(&sem->wait, &wait);
current->state = TASK_UNINTERRUPTIBLE;
while (sem->count <= 0) {
schedule();
current->state = TASK_UNINTERRUPTIBLE;
}
current->state = TASK_RUNNING;
remove_wait_queue(&sem->wait, &wait);
}
static inline void __sleep_on(struct wait_queue **p, int state)
{
unsigned long flags;
......
......@@ -211,30 +211,34 @@ asmlinkage int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options);
*/
asmlinkage int sys_sigreturn(unsigned long __unused)
{
#define CHECK_SEG(x) if (x) x |= 3
#define COPY(x) regs->x = context.x
#define COPY_SEG(x) \
if ((context.x & 0xfffc) && (context.x & 3) != 3) goto badframe; COPY(x);
#define COPY_SEG_STRICT(x) \
if (!(context.x & 0xfffc) || (context.x & 3) != 3) goto badframe; COPY(x);
struct sigcontext_struct context;
struct pt_regs * regs;
regs = (struct pt_regs *) &__unused;
if (verify_area(VERIFY_READ, (void *) regs->esp, sizeof(context)))
goto badframe;
memcpy_fromfs(&context,(void *) regs->esp, sizeof(context));
current->blocked = context.oldmask & _BLOCKABLE;
CHECK_SEG(context.ss);
CHECK_SEG(context.cs);
CHECK_SEG(context.ds);
CHECK_SEG(context.es);
CHECK_SEG(context.fs);
CHECK_SEG(context.gs);
COPY_SEG(ds);
COPY_SEG(es);
COPY_SEG(fs);
COPY_SEG(gs);
COPY_SEG_STRICT(ss);
COPY_SEG_STRICT(cs);
COPY(eip); COPY(eflags);
COPY(ecx); COPY(edx);
COPY(ebx);
COPY(esp); COPY(ebp);
COPY(edi); COPY(esi);
COPY(cs); COPY(ss);
COPY(ds); COPY(es);
COPY(fs); COPY(gs);
regs->orig_eax = -1; /* disable syscall checks */
return context.eax;
badframe:
do_exit(SIGSEGV);
}
/*
......
......@@ -89,7 +89,7 @@ asmlinkage void alignment_check(void);
printk("EIP: %04x:%08lx\nEFLAGS: %08lx\n", 0xffff & regs->cs,regs->eip,regs->eflags);
printk("eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n",
regs->eax, regs->ebx, regs->ecx, regs->edx);
printk("esi: %08lx edi: %08lx ebp: %08lx esp: %08x\n",
printk("esi: %08lx edi: %08lx ebp: %08lx esp: %08lx\n",
regs->esi, regs->edi, regs->ebp, regs->esp);
printk("ds: %04x es: %04x fs: %04x gs: %04x\n",
regs->ds, regs->es, regs->fs, regs->gs);
......@@ -98,9 +98,11 @@ asmlinkage void alignment_check(void);
for(i=0;i<20;i++)
printk("%02x ",0xff & get_seg_byte(regs->cs,(i+(char *)regs->eip)));
printk("\n");
#if 0
for(i=0;i<5;i++)
printk("%08x ", get_seg_long(regs->ss,(i+(unsigned long *)regs->esp)));
printk("%08lx ", get_seg_long(regs->ss,(i+(unsigned long *)regs->esp)));
printk("\n");
#endif
do_exit(SIGSEGV);
}
......
......@@ -39,6 +39,7 @@
* Dominik Kubla : Better checking
* Tegge : Assorted corrections on cross port stuff
* Alan Cox : ATF_PERM was backwards! - might be useful now (sigh)
* Alan Cox : Arp timer added.
*
* To Fix:
* : arp response allocates an skbuff to send. However there is a perfectly
......@@ -60,6 +61,7 @@
#include <linux/config.h>
#include <linux/socket.h>
#include <linux/sockios.h>
#include <linux/timer.h>
#include <linux/errno.h>
#include <linux/if_arp.h>
#include <linux/in.h>
......@@ -250,6 +252,28 @@ arp_send_q(void)
}
static struct timer_list arp_timer;
static void arp_queue_ticker(unsigned long data);
static void arp_queue_kick(void)
{
arp_timer.expires = 500; /* 5 seconds */
arp_timer.data = 0;
arp_timer.function = arp_queue_ticker;
del_timer(&arp_timer);
add_timer(&arp_timer);
}
static void arp_queue_ticker(unsigned long data/*UNUSED*/)
{
arp_send_q();
if (skb_peek(&arp_q))
arp_queue_kick();
}
/* Create and send our response to an ARP request. */
static int
arp_response(struct arphdr *arp1, struct device *dev, int addrtype)
......@@ -753,6 +777,8 @@ arp_queue(struct sk_buff *skb)
printk("ARP: arp_queue skb already on queue magic=%X.\n", skb->magic);
return;
}
if(arp_q==NULL)
arp_queue_kick();
skb_queue_tail(&arp_q,skb);
skb->magic = ARP_QUEUE_MAGIC;
sti();
......
......@@ -186,7 +186,7 @@ int datagram_select(struct sock *sk, int sel_type, select_table *wait)
return(0);
case SEL_OUT:
if (sk->prot->wspace(sk) >= MIN_WRITE_SPACE)
if (sk->prot && sk->prot->wspace(sk) >= MIN_WRITE_SPACE)
{
return(1);
}
......
......@@ -253,17 +253,33 @@ static inline int bad_mask(unsigned long mask, unsigned long addr)
static int rt_new(struct rtentry *r)
{
struct device *dev;
int err;
char * devname;
struct device * dev = NULL;
unsigned long flags, daddr, mask, gw;
if ((devname = r->rt_dev) != NULL) {
err = getname(devname, &devname);
if (err)
return err;
dev = dev_get(devname);
putname(devname);
if (!dev)
return -EINVAL;
}
if (r->rt_dst.sa_family != AF_INET)
return -EAFNOSUPPORT;
flags = r->rt_flags;
daddr = ((struct sockaddr_in *) &r->rt_dst)->sin_addr.s_addr;
mask = r->rt_genmask;
mask = ((struct sockaddr_in *) &r->rt_genmask)->sin_addr.s_addr;
gw = ((struct sockaddr_in *) &r->rt_gateway)->sin_addr.s_addr;
dev = (struct device *) r->rt_dev;
if (flags & RTF_HOST)
mask = 0xffffffff;
else if (r->rt_genmask.sa_family != AF_INET)
return -EAFNOSUPPORT;
if (flags & RTF_GATEWAY) {
if (r->rt_gateway.sa_family != AF_INET)
......@@ -343,19 +359,41 @@ struct rtable * rt_route(unsigned long daddr, struct options *opt)
return NULL;
}
static int get_old_rtent(struct old_rtentry * src, struct rtentry * rt)
{
int err;
struct old_rtentry tmp;
err=verify_area(VERIFY_READ, src, sizeof(*src));
if (err)
return err;
memcpy_fromfs(&tmp, src, sizeof(*src));
memset(rt, 0, sizeof(*rt));
rt->rt_dst = tmp.rt_dst;
rt->rt_gateway = tmp.rt_gateway;
rt->rt_genmask.sa_family = AF_INET;
((struct sockaddr_in *) &rt->rt_genmask)->sin_addr.s_addr = tmp.rt_genmask;
rt->rt_flags = tmp.rt_flags;
rt->rt_dev = tmp.rt_dev;
return 0;
}
int rt_ioctl(unsigned int cmd, void *arg)
{
struct device *dev;
struct rtentry rt;
char *devname;
int ret;
int err;
struct rtentry rt;
switch(cmd) {
case DDIOCSDBG:
ret = dbg_ioctl(arg, DBG_RT);
break;
return dbg_ioctl(arg, DBG_RT);
case SIOCADDRTOLD:
case SIOCDELRTOLD:
if (!suser())
return -EPERM;
err = get_old_rtent((struct old_rtentry *) arg, &rt);
if (err)
return err;
return (cmd == SIOCDELRTOLD) ? rt_kill(&rt) : rt_new(&rt);
case SIOCADDRT:
case SIOCDELRT:
if (!suser())
......@@ -364,21 +402,8 @@ int rt_ioctl(unsigned int cmd, void *arg)
if (err)
return err;
memcpy_fromfs(&rt, arg, sizeof(struct rtentry));
if ((devname = (char *) rt.rt_dev) != NULL) {
err = getname(devname, &devname);
if (err)
return err;
dev = dev_get(devname);
putname(devname);
if (!dev)
return -EINVAL;
rt.rt_dev = dev;
}
ret = (cmd == SIOCDELRT) ? rt_kill(&rt) : rt_new(&rt);
break;
default:
ret = -EINVAL;
return (cmd == SIOCDELRT) ? rt_kill(&rt) : rt_new(&rt);
}
return ret;
return -EINVAL;
}
......@@ -1531,8 +1531,8 @@ inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
case DDIOCSDBG:
return(dbg_ioctl((void *) arg, DBG_INET));
case SIOCADDRT:
case SIOCDELRT:
case SIOCADDRT: case SIOCADDRTOLD:
case SIOCDELRT: case SIOCDELRTOLD:
return(rt_ioctl(cmd,(void *) arg));
case SIOCDARP:
......@@ -1595,7 +1595,7 @@ sock_rmalloc(struct sock *sk, unsigned long size, int force, int priority)
{
if (sk) {
if (sk->rmem_alloc + size < sk->rcvbuf || force) {
void *c = alloc_skb(size, priority);
struct sk_buff *c = alloc_skb(size, priority);
cli();
if (c) sk->rmem_alloc += size;
sti();
......
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