Commit 9300725c authored by Linus Torvalds's avatar Linus Torvalds

Import 0.99.15i

parent 0acb47cd
VERSION = 0.99
PATCHLEVEL = 15
ALPHA = h
ALPHA = i
all: Version zImage
......
Linux kernel release 0.99 patchlevel 14
Linux kernel release 0.99 patchlevel 15
These are the release notes for linux version 0.99.14. Read them
These are the release notes for linux version 0.99.15. Read them
carefully, as they tell you what's new, explain how to install the
kernel, and what to do if something goes wrong.
INSTALLING the kernel:
- if you install by patching, you need a *clean* 0.99.13 source tree,
- if you install by patching, you need a *clean* 0.99.14 source tree,
which presumably exists in /usr/src/linux. If so, to get the kernel
patched, just do a
cd /usr/src
patch -p0 < linux-0.99.patch14
patch -p0 < linux-0.99.patch15
and you should be ok. You may want to remove the backup files (xxx~
or xxx.orig), and make sure that there are no failed patches (xxx# or
......@@ -21,7 +21,7 @@ INSTALLING the kernel:
- If you install the full sources, do a
cd /usr/src
tar xvf linux-0.99.14.tar
tar xvf linux-0.99.15.tar
to get it all put in place.
......
......@@ -97,9 +97,19 @@ void emu_printall()
printk(" [%02x]", byte1);
address++;
}
if ( i == MAX_PRINTED_BYTES ) printk(" [more..]");
printk("\n");
FPU_modrm = get_fs_byte(1 + (unsigned char *) address);
if ( i == MAX_PRINTED_BYTES )
printk(" [more..]\n");
else
{
FPU_modrm = get_fs_byte(1 + (unsigned char *) address);
if (FPU_modrm >= 0300)
printk(" %02x (%02x+%d)\n", FPU_modrm, FPU_modrm & 0xf8, FPU_modrm & 7);
else
printk(" /%d, mod=%d rm=%d\n",
(FPU_modrm >> 3) & 7, (FPU_modrm >> 6) & 3, FPU_modrm & 7);
}
partial_status = status_word();
#ifdef DEBUGGING
......@@ -118,12 +128,6 @@ if ( partial_status & SW_Denorm_Op ) printk("SW: denormalized operand\n");
if ( partial_status & SW_Invalid ) printk("SW: invalid operation\n");
#endif DEBUGGING
if (FPU_modrm >= 0300)
printk("%02x (%02x+%d)\n", FPU_modrm, FPU_modrm & 0xf8, FPU_modrm & 7);
else
printk("/%d, mod=%d rm=%d\n",
(FPU_modrm >> 3) & 7, (FPU_modrm >> 6) & 3, FPU_modrm & 7);
printk(" SW: b=%d st=%ld es=%d sf=%d cc=%d%d%d%d ef=%d%d%d%d%d%d\n",
partial_status & 0x8000 ? 1 : 0, /* busy */
(partial_status & 0x3800) >> 11, /* stack top pointer */
......
......@@ -51,11 +51,10 @@ int reg_mul(FPU_REG const *a, FPU_REG const *b,
one valid and the other zero.
The result is therefore zero. */
reg_move(&CONST_Z, dest);
#ifdef PECULIAR_486
/* The 80486 book says that the answer is +0, but a real
80486 appears to behave this way... */
80486 behaves this way.
IEEE-754 apparently says it should be this way. */
dest->sign = sign;
#endif PECULIAR_486
return 0;
}
else
......
......@@ -1828,6 +1828,14 @@ static void clear_selection()
/*
* PIO_FONT support.
*
* The font loading code goes back to the codepage package by
* Joel Hoffman (joel@wam.umd.edu). (He reports that the original
* reference is: "From: p. 307 of _Programmer's Guide to PC & PS/2
* Video Systems_ by Richard Wilton. 1987. Microsoft Press".)
*
* Change for certain monochrome monitors by Yury Shevchuck
* (sizif@botik.yaroslavl.su).
*/
#define colourmap ((char *)0xa0000)
......@@ -1843,14 +1851,17 @@ static int set_get_font(char * arg, int set)
#ifdef CAN_LOAD_EGA_FONTS
int i;
char *charmap;
int beg;
/* no use to "load" CGA... */
if (video_type == VIDEO_TYPE_EGAC)
if (video_type == VIDEO_TYPE_EGAC) {
charmap = colourmap;
else if (video_type == VIDEO_TYPE_EGAM)
beg = 0x0e;
} else if (video_type == VIDEO_TYPE_EGAM) {
charmap = blackwmap;
else
beg = 0x0a;
} else
return -EINVAL;
i = verify_area(set ? VERIFY_READ : VERIFY_WRITE, (void *)arg, cmapsz);
......@@ -1897,7 +1908,7 @@ static int set_get_font(char * arg, int set)
outb_p( 0x05, gr_port_reg );
outb_p( 0x10, gr_port_val ); /* enable even-odd addressing */
outb_p( 0x06, gr_port_reg );
outb_p( 0x0e, gr_port_val ); /* map starts at b800:0000 */
outb_p( beg, gr_port_val ); /* map starts at b800:0 or b000:0 */
sti();
return 0;
......
......@@ -930,10 +930,7 @@ int is_ignored(int sig)
static inline int input_available_p(struct tty_struct *tty)
{
/* Avoid calling TTY_READ_FLUSH unnecessarily. */
if (L_ICANON(tty)) {
if (tty->canon_data || FULL(&tty->read_q))
return 1;
} else if (!EMPTY(&tty->secondary))
if (L_ICANON(tty) ? tty->canon_data : !EMPTY(&tty->secondary))
return 1;
/* Shuffle any pending data down the queues. */
......@@ -941,10 +938,7 @@ static inline int input_available_p(struct tty_struct *tty)
if (tty->link)
TTY_WRITE_FLUSH(tty->link);
if (L_ICANON(tty)) {
if (tty->canon_data || FULL(&tty->read_q))
return 1;
} else if (!EMPTY(&tty->secondary))
if (L_ICANON(tty) ? tty->canon_data : !EMPTY(&tty->secondary))
return 1;
return 0;
}
......@@ -1036,7 +1030,7 @@ static int read_chan(struct tty_struct *tty, struct file *file,
nr--;
}
while (nr > 0) {
while (1) {
int eol;
cli();
......@@ -1047,6 +1041,24 @@ static int read_chan(struct tty_struct *tty, struct file *file,
eol = clear_bit(tty->secondary.tail,
&tty->secondary_flags);
c = tty->secondary.buf[tty->secondary.tail];
if (!nr) {
/* Gobble up an immediately following EOF if
there is no more room in buf (this can
happen if the user "pushes" some characters
using ^D). This prevents the next read()
from falsely returning EOF. */
if (eol) {
if (c == __DISABLED_CHAR) {
tty->canon_data--;
INC(tty->secondary.tail);
} else {
set_bit(tty->secondary.tail,
&tty->secondary_flags);
}
}
sti();
break;
}
INC(tty->secondary.tail);
sti();
if (eol) {
......@@ -1067,10 +1079,9 @@ static int read_chan(struct tty_struct *tty, struct file *file,
/* If there is enough space in the secondary queue now, let the
low-level driver know. */
if (tty->throttle && (LEFT(&tty->secondary) >= SQ_THRESHOLD_HW)
&& !clear_bit(TTY_SQ_THROTTLED, &tty->flags))
&& clear_bit(TTY_SQ_THROTTLED, &tty->flags))
tty->throttle(tty, TTY_THROTTLE_SQ_AVAIL);
/* XXX packet mode's status byte is mistakenly counted */
if (b - buf >= minimum || !nr)
break;
if (time)
......@@ -1121,6 +1132,10 @@ static int write_chan(struct tty_struct * tty, struct file * file,
break;
if (EMPTY(&tty->write_q) && !need_resched)
continue;
if (file->f_flags & O_NONBLOCK) {
retval = -EAGAIN;
break;
}
schedule();
}
current->state = TASK_RUNNING;
......@@ -1594,7 +1609,7 @@ static int normal_select(struct tty_struct * tty, struct inode * inode,
select_wait(&tty->secondary.proc_list, wait);
return 0;
case SEL_OUT:
if (!FULL(&tty->write_q))
if (LEFT(&tty->write_q) > WAKEUP_CHARS)
return 1;
select_wait(&tty->write_q.proc_list, wait);
return 0;
......
......@@ -487,6 +487,8 @@ int tty_ioctl(struct inode * inode, struct file * file,
sizeof (pid_t));
if (retval)
return retval;
if (current->tty != termios_dev)
return -ENOTTY;
put_fs_long(termios_tty->pgrp, (pid_t *) arg);
return 0;
case TIOCSPGRP:
......@@ -526,7 +528,7 @@ int tty_ioctl(struct inode * inode, struct file * file,
return 0;
case TIOCSTI:
if ((current->tty != dev) && !suser())
return -EACCES;
return -EPERM;
retval = verify_area(VERIFY_READ, (void *) arg, 1);
if (retval)
return retval;
......@@ -580,7 +582,7 @@ int tty_ioctl(struct inode * inode, struct file * file,
else if (IS_A_PTY_SLAVE(dev))
redirect = tty;
else
return -EINVAL;
return -ENOTTY;
return 0;
case FIONBIO:
arg = get_fs_long((unsigned long *) arg);
......@@ -590,8 +592,8 @@ int tty_ioctl(struct inode * inode, struct file * file,
file->f_flags &= ~O_NONBLOCK;
return 0;
case TIOCNOTTY:
if (MINOR(file->f_rdev) != current->tty)
return -EINVAL;
if (current->tty != dev)
return -ENOTTY;
if (current->leader)
disassociate_ctty(0);
current->tty = -1;
......@@ -629,7 +631,7 @@ int tty_ioctl(struct inode * inode, struct file * file,
return 0;
case TIOCPKT:
if (!IS_A_PTY_MASTER(dev))
return -EINVAL;
return -ENOTTY;
retval = verify_area(VERIFY_READ, (void *) arg,
sizeof (unsigned long));
if (retval)
......@@ -637,7 +639,7 @@ int tty_ioctl(struct inode * inode, struct file * file,
if (get_fs_long(arg)) {
if (!tty->packet) {
tty->packet = 1;
tty->ctrl_status = 0;
tty->link->ctrl_status = 0;
}
} else
tty->packet = 0;
......
......@@ -13,7 +13,7 @@
C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
*/
static char *version = "3c509.c:pl13t 11/24/93 becker@super.org\n";
static char *version = "3c509.c:pl15i 2/23/94 becker@super.org\n";
#include <linux/config.h>
#include <linux/kernel.h>
......@@ -549,19 +549,19 @@ el3_rx(struct device *dev)
inw(ioaddr+EL3_STATUS), inw(ioaddr+RX_STATUS));
while ((rx_status = inw(ioaddr + RX_STATUS)) > 0) {
if (rx_status & 0x4000) { /* Error, update stats. */
short error = rx_status & 0x3C00;
short error = rx_status & 0x3800;
lp->stats.rx_errors++;
switch (error) {
case 0x2000: lp->stats.rx_over_errors++; break;
case 0x2C00: lp->stats.rx_length_errors++; break;
case 0x3400: lp->stats.rx_crc_errors++; break;
case 0x2400: lp->stats.rx_length_errors++; break;
case 0x3000: lp->stats.rx_frame_errors++; break;
case 0x0800: lp->stats.rx_frame_errors++; break;
case 0x0000: lp->stats.rx_over_errors++; break;
case 0x0800: lp->stats.rx_length_errors++; break;
case 0x1000: lp->stats.rx_frame_errors++; break;
case 0x1800: lp->stats.rx_length_errors++; break;
case 0x2000: lp->stats.rx_frame_errors++; break;
case 0x2800: lp->stats.rx_crc_errors++; break;
}
}
if ( (! (rx_status & 0x4000))
|| ! (rx_status & 0x2000)) { /* Dribble bits are OK. */
|| ! (rx_status & 0x1000)) { /* Dribble bits are OK. */
short pkt_len = rx_status & 0x7ff;
int sksize = sizeof(struct sk_buff) + pkt_len + 3;
struct sk_buff *skb;
......
......@@ -12,7 +12,7 @@
*/
static char *version =
"atp.c:v0.03 1/19/94 Donald Becker (becker@super.org)\n";
"atp.c:v0.04 2/25/94 Donald Becker (becker@super.org)\n";
/*
This file is a device driver for the RealTek (aka AT-Lan-Tec) pocket
......@@ -477,7 +477,7 @@ net_send_packet(struct sk_buff *skb, struct device *dev)
/* For ethernet, fill in the header. This should really be done by a
higher level, rather than duplicated for each ethernet adaptor. */
if (!skb->arp && dev->rebuild_header(skb+1, dev)) {
if (!skb->arp && dev->rebuild_header(skb->data, dev)) {
skb->dev = dev;
arp_queue (skb);
return 0;
......@@ -490,7 +490,7 @@ net_send_packet(struct sk_buff *skb, struct device *dev)
printk("%s: Transmitter access conflict.\n", dev->name);
else {
short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
unsigned char *buf = (void *)(skb+1);
unsigned char *buf = skb->data;
int flags;
/* Disable interrupts by writing 0x00 to the Interrupt Mask Register.
......@@ -611,7 +611,7 @@ net_interrupt(int reg_ptr)
} else if (num_tx_since_rx > 8
&& jiffies > dev->last_rx + 100) {
if (net_debug > 2)
printk("%s: Missed packet? No Rx after %d Tx and %d jiffies"
printk("%s: Missed packet? No Rx after %d Tx and %ld jiffies"
" status %02x CMR1 %02x.\n", dev->name,
num_tx_since_rx, jiffies - dev->last_rx, status,
(read_nibble(ioaddr, CMR1) >> 3) & 15);
......@@ -623,6 +623,8 @@ net_interrupt(int reg_ptr)
break;
}
/* This following code fixes a rare (and very difficult to track down)
problem where the adaptor forgets its ethernet address. */
{
int i;
for (i = 0; i < 6; i++)
......@@ -686,12 +688,12 @@ static void net_rx(struct device *dev)
skb->len = pkt_len;
skb->dev = dev;
/* 'skb+1' points to the start of sk_buff data area. */
read_block(ioaddr, pkt_len, (unsigned char *)(skb + 1), dev->if_port);
read_block(ioaddr, pkt_len, skb->data, dev->if_port);
if (net_debug > 6) {
unsigned char *data = (unsigned char *)(skb + 1);
printk(" data %02x%02x%02x %02x%02x%02x %02x%02x%02x %02x%02x%02x %02x%02x..",
unsigned char *data = skb->data;
printk(" data %02x%02x%02x %02x%02x%02x %02x%02x%02x"
"%02x%02x%02x %02x%02x..",
data[0], data[1], data[2], data[3], data[4], data[5],
data[6], data[7], data[8], data[9], data[10], data[11],
data[12], data[13]);
......
......@@ -135,8 +135,6 @@ static char *version = "depca.c:v0.32 2/19/94 davies@wanton.enet.dec.com\n";
#include "arp.h"
#include "depca.h"
extern int vsprintf(char *buf, const char *fmt, ...);
#ifdef DEPCA_DEBUG
int depca_debug = DEPCA_DEBUG;
#else
......@@ -344,7 +342,7 @@ int depca_probe(struct device *dev)
(num_eth > 0) && (num_eth < 9999)) {
dev = dev->next; /* point to the new device */
dev->name = (char *)(dev + sizeof(struct device));
vsprintf(dev->name,"eth%d", num_eth); /* New device name */
sprintf(dev->name,"eth%d", num_eth); /* New device name */
dev->base_addr = ioaddr; /* assign the io address */
dev->next = (struct device *)NULL; /* mark the end of list */
dev->init = &depca_probe;/* initialisation routine */
......
......@@ -562,9 +562,9 @@ lance_start_xmit(struct sk_buff *skb, struct device *dev)
(int)(lp->tx_bounce_buffs + entry) | 0x83000000;
if (skb->free)
kfree_skb (skb, FREE_WRITE);
} else
{
/* Gimme!!! */
} else {
/* We can't free the packet yet, so we inform the memory management
code that we are still using it. */
if(skb->free==0)
skb_kept_by_device(skb);
lp->tx_ring[entry].base = (int)(skb+1) | 0x83000000;
......@@ -655,7 +655,8 @@ lance_interrupt(int reg_ptr)
kfree_skb(skb, FREE_WRITE);
else
skb_device_release(skb,FREE_WRITE);
/* Warning: skb may well vanish at the point you call device_release! */
/* Warning: skb may well vanish at the point you call
device_release! */
}
dirty_tx++;
}
......@@ -705,8 +706,13 @@ lance_rx(struct device *dev)
while (lp->rx_ring[entry].base >= 0) {
int status = lp->rx_ring[entry].base >> 24;
if (status & 0x40) { /* There was an error. */
lp->stats.rx_errors++;
if (status != 0x03) { /* There was an error. */
/* There is an tricky error noted by John Murphy,
<murf@perftech.com> to Russ Nelson: Even with full-sized
buffers it's possible for a jabber packet to use two
buffers, with only the last correctly noting the error. */
if (status & 0x01) /* Only count a general error at the */
lp->stats.rx_errors++; /* end of a packet.*/
if (status & 0x20) lp->stats.rx_frame_errors++;
if (status & 0x10) lp->stats.rx_over_errors++;
if (status & 0x08) lp->stats.rx_crc_errors++;
......
......@@ -14,7 +14,7 @@
*/
static char *version =
"smc-ultra.c:v0.06 2/9/94 Donald Becker (becker@super.org)\n";
"smc-ultra.c:v0.07 3/1/94 Donald Becker (becker@super.org)\n";
#include <linux/config.h>
#include <linux/kernel.h>
......@@ -63,7 +63,7 @@ int ultra_probe(struct device *dev)
unsigned short ioaddr = dev->base_addr;
if (ioaddr > 0x1ff)
return ! ultraprobe1(ioaddr, dev);
return ultraprobe1(ioaddr, dev);
else if (ioaddr > 0)
return ENXIO; /* Don't probe at all. */
......@@ -158,7 +158,7 @@ int ultraprobe1(int ioaddr, struct device *dev)
dev->mem_end = dev->rmem_end
= dev->mem_start + (ei_status.stop_page - START_PG)*256;
printk(",%s IRQ %d memory %#x-%#x.\n", eeprom_irq ? "" : "assigned ",
printk(",%s IRQ %d memory %#lx-%#lx.\n", eeprom_irq ? "" : "assigned ",
dev->irq, dev->mem_start, dev->mem_end-1);
if (ei_debug > 0)
printk(version);
......@@ -193,7 +193,7 @@ ultra_reset_8390(struct device *dev)
int cmd_port = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC base addr */
outb(ULTRA_RESET, cmd_port);
if (ei_debug > 1) printk("resetting Ultra, t=%d...", jiffies);
if (ei_debug > 1) printk("resetting Ultra, t=%ld...", jiffies);
ei_status.txing = 0;
outb(ULTRA_MEMENB, cmd_port);
......
Linux can read, but not write, OS/2 HPFS partitions.
Mount options are the same as for msdos partitions.
uid=nnn All files in the partition will be owned by user id nnn.
gid=nnn All files in the partition will be in group nnn.
umask=nnn The permission mask (see umask(1)) for the partition.
conv=binary Data is returned exactly as is, with CRLF's. [default]
conv=text (Carriage return, line feed) is replaced with newline.
conv=auto Chooses, file by file, conv=binary or conv=text (by guessing)
There is one mount option unique to HPFS.
case=lower Convert file names to lower case. [default]
case=asis Return file names as is, in mixed case.
Case is not significant in filename matching, like real HPFS.
Command line example
mkdir -p /os2/c
mount -t hpfs -o uid=100,gid=100 /dev/sda6 /os2/c
/etc/fstab example
/dev/sdb5 /d/f hpfs ro,uid=402,gid=402,umask=002
......@@ -131,7 +131,7 @@ struct hpfs_spare_block
/* The code page info pointed to by the spare block consists of an index
block and blocks containing character maps. The following is pretty
sketchy, but Linux is Latin-1 so it doesn't matter. */
sketchy, but Linux doesn't use code pages so it doesn't matter. */
/* block pointed to by spareblock->code_page_dir */
......
......@@ -6,7 +6,7 @@
* Chris Smith 1993
*
* Sources & references:
* Duncan, _Design ... of HPFS_, MSSJ 4(5) (C) 1989 Microsoft Corp
* Duncan, _Design ... of HPFS_, MSJ 4(5) (C) 1989 Microsoft Corp
* linux/fs/minix Copyright (C) 1991, 1992, 1993 Linus Torvalds
* linux/fs/msdos Written 1992, 1993 by Werner Almesberger
* linux/fs/isofs Copyright (C) 1991 Eric Youngdale
......
......@@ -191,6 +191,8 @@ static int isofs_readdir(struct inode * inode, struct file * filp,
for (i = 0; i < dlen && i < NAME_MAX; i++) {
if (!(c = dpnt[i])) break;
if (c >= 'A' && c <= 'Z') c |= 0x20; /* lower case */
if (c == '.' && i == dlen-3 && de->name[i+1] == ';' && de->name[i+2] == '1')
break; /* Drop trailing '.;1' (ISO9660:1988 7.5.1 requires period) */
if (c == ';' && i == dlen-2 && de->name[i+1] == '1')
break; /* Drop trailing ';1' */
if (c == ';') c = '.'; /* Convert remaining ';' to '.' */
......
......@@ -316,6 +316,7 @@ int parse_rock_ridge_inode(struct iso_directory_record * de,
struct SL_component * slp;
slen = rr->len - 5;
slp = &rr->u.SL.link;
inode->i_size = 0;
while (slen > 1){
rootflag = 0;
switch(slp->flags &~1){
......
......@@ -108,7 +108,7 @@ static int do_nfs_rpc_call(struct nfs_server *server, int *start, int *end)
continue;
if (server->flags & NFS_MOUNT_SOFT) {
printk("NFS server %s not responding, "
"timed out", server_name);
"timed out\n", server_name);
result = -EIO;
break;
}
......
......@@ -84,7 +84,8 @@ void proc_read_inode(struct inode * inode)
inode->i_nlink = 1;
inode->i_size = 0;
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
inode->i_blocks = inode->i_blksize = 0;
inode->i_blocks = 0;
inode->i_blksize = 1024;
ino = inode->i_ino;
pid = ino >> 16;
p = task[0];
......
......@@ -223,11 +223,10 @@ asmlinkage int sys_select( unsigned long *buffer )
i = verify_area(VERIFY_WRITE, tvp, sizeof(*tvp));
if (i)
return i;
timeout = jiffies;
timeout += ROUND_UP(get_fs_long((unsigned long *)&tvp->tv_usec),(1000000/HZ));
timeout = ROUND_UP(get_fs_long((unsigned long *)&tvp->tv_usec),(1000000/HZ));
timeout += get_fs_long((unsigned long *)&tvp->tv_sec) * HZ;
if (timeout <= jiffies)
timeout = 0;
if (timeout)
timeout += jiffies + 1;
}
current->timeout = timeout;
i = do_select(n, &in, &out, &ex, &res_in, &res_out, &res_ex);
......
......@@ -166,7 +166,7 @@ struct tss_struct {
struct task_struct {
/* these are hardcoded - don't touch */
long state; /* -1 unrunnable, 0 runnable, >0 stopped */
volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */
long counter;
long priority;
unsigned long signal;
......
......@@ -150,9 +150,9 @@ struct termios {
#define VTDLY 0040000
#define VT0 0000000
#define VT1 0040000
#define FFDLY 0040000
#define FFDLY 0100000
#define FF0 0000000
#define FF1 0040000
#define FF1 0100000
/* c_cflag bit meaning */
#define CBAUD 0000017
......
......@@ -462,6 +462,8 @@ int sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr)
shp->attaches = shmd;
shp->shm_lpid = current->pid;
shp->shm_atime = CURRENT_TIME;
if (!raddr)
return addr;
put_fs_long (addr, raddr);
return 0;
}
......
......@@ -80,23 +80,33 @@ asmlinkage void alignment_check(void);
/*static*/ void die_if_kernel(char * str, struct pt_regs * regs, long err)
{
int i;
unsigned long esp;
unsigned short ss;
esp = (unsigned long) &regs->esp;
ss = KERNEL_DS;
if ((regs->eflags & VM_MASK) || (3 & regs->cs) == 3)
return;
if (regs->cs & 3) {
esp = regs->esp;
ss = regs->ss;
}
console_verbose();
printk("%s: %04lx\n", str, err & 0xffff);
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\n",
regs->esi, regs->edi, regs->ebp);
printk("ds: %04x es: %04x fs: %04x gs: %04x\n",
regs->ds, regs->es, regs->fs, regs->gs);
printk("esi: %08lx edi: %08lx ebp: %08lx esp: %08lx\n",
regs->esi, regs->edi, regs->ebp, esp);
printk("ds: %04x es: %04x fs: %04x gs: %04x ss: %04x\n",
regs->ds, regs->es, regs->fs, regs->gs, ss);
store_TR(i);
printk("Pid: %d, process nr: %d (%s)\n", current->pid, 0xffff & i, current->comm);
printk("Pid: %d, process nr: %d (%s)\nCode: ", current->pid, 0xffff & i, current->comm);
for(i=0;i<20;i++)
printk("%02x ",0xff & get_seg_byte(regs->cs,(i+(char *)regs->eip)));
printk("\nStack: ");
for(i=0;i<5;i++)
printk("%08lx ", get_seg_long(ss,(i+(unsigned long *)esp)));
printk("\n");
do_exit(SIGSEGV);
}
......
......@@ -304,9 +304,9 @@ int unmap_page_range(unsigned long from, unsigned long size)
if ((page = *page_table) != 0) {
*page_table = 0;
if (1 & page) {
if (!(mem_map[MAP_NR(page)]
& MAP_PAGE_RESERVED))
--current->rss;
if (!(mem_map[MAP_NR(page)] & MAP_PAGE_RESERVED))
if (current->rss > 0)
--current->rss;
free_page(PAGE_MASK & page);
} else
swap_free(page);
......@@ -364,9 +364,9 @@ int zeromap_page_range(unsigned long from, unsigned long size, int mask)
if ((page = *page_table) != 0) {
*page_table = 0;
if (page & PAGE_PRESENT) {
if (!(mem_map[MAP_NR(page)]
& MAP_PAGE_RESERVED))
--current->rss;
if (!(mem_map[MAP_NR(page)] & MAP_PAGE_RESERVED))
if (current->rss > 0)
--current->rss;
free_page(PAGE_MASK & page);
} else
swap_free(page);
......@@ -426,9 +426,9 @@ int remap_page_range(unsigned long from, unsigned long to, unsigned long size, i
if ((page = *page_table) != 0) {
*page_table = 0;
if (PAGE_PRESENT & page) {
if (!(mem_map[MAP_NR(page)]
& MAP_PAGE_RESERVED))
--current->rss;
if (!(mem_map[MAP_NR(page)] & MAP_PAGE_RESERVED))
if (current->rss > 0)
--current->rss;
free_page(PAGE_MASK & page);
} else
swap_free(page);
......
......@@ -210,9 +210,11 @@ icmp_redirect(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev)
ip = iph->daddr;
switch(icmph->code & 7) {
case ICMP_REDIR_NET:
#ifdef not_a_good_idea
rt_add((RTF_DYNAMIC | RTF_MODIFIED | RTF_GATEWAY),
ip, 0, icmph->un.gateway, dev);
break;
#endif
case ICMP_REDIR_HOST:
rt_add((RTF_DYNAMIC | RTF_MODIFIED | RTF_HOST | RTF_GATEWAY),
ip, 0, icmph->un.gateway, dev);
......
......@@ -394,8 +394,8 @@ void kfree_skb(struct sk_buff *skb, int rw)
skb->magic = 0;
if (skb->sk)
{
if(skb->sk->prot!=NULL)
{
if(skb->sk->prot!=NULL)
{
if (rw)
skb->sk->prot->rfree(skb->sk, skb->mem_addr, skb->mem_len);
else
......
......@@ -1578,10 +1578,13 @@ sock_wmalloc(struct sock *sk, unsigned long size, int force,
{
if (sk) {
if (sk->wmem_alloc + size < sk->sndbuf || force) {
cli();
sk->wmem_alloc+= size;
sti();
return(alloc_skb(size, priority));
struct sk_buff * c = alloc_skb(size, priority);
if (c) {
cli();
sk->wmem_alloc+= size;
sti();
}
return c;
}
DPRINTF((DBG_INET, "sock_wmalloc(%X,%d,%d,%d) returning NULL\n",
sk, size, force, priority));
......@@ -1597,9 +1600,11 @@ sock_rmalloc(struct sock *sk, unsigned long size, int force, int priority)
if (sk) {
if (sk->rmem_alloc + size < sk->rcvbuf || force) {
struct sk_buff *c = alloc_skb(size, priority);
cli();
if (c) sk->rmem_alloc += size;
sti();
if (c) {
cli();
sk->rmem_alloc += size;
sti();
}
return(c);
}
DPRINTF((DBG_INET, "sock_rmalloc(%X,%d,%d,%d) returning NULL\n",
......
......@@ -117,28 +117,29 @@ min(unsigned int a, unsigned int b)
}
void
print_th(struct tcphdr *th)
static void __print_th(struct tcphdr *th)
{
unsigned char *ptr;
if (inet_debug != DBG_TCP) return;
printk("TCP header:\n");
ptr =(unsigned char *)(th + 1);
printk(" source=%d, dest=%d, seq =%ld, ack_seq = %ld\n",
ntohs(th->source), ntohs(th->dest),
ntohl(th->seq), ntohl(th->ack_seq));
printk(" fin=%d, syn=%d, rst=%d, psh=%d, ack=%d, urg=%d res1=%d res2=%d\n",
th->fin, th->syn, th->rst, th->psh, th->ack,
th->urg, th->res1, th->res2);
printk(" window = %d, check = %d urg_ptr = %d\n",
ntohs(th->window), ntohs(th->check), ntohs(th->urg_ptr));
printk(" doff = %d\n", th->doff);
printk(" options = %d %d %d %d\n", ptr[0], ptr[1], ptr[2], ptr[3]);
}
unsigned char *ptr;
printk("TCP header:\n");
printk(" source=%d, dest=%d, seq =%ld, ack_seq = %ld\n",
ntohs(th->source), ntohs(th->dest),
ntohl(th->seq), ntohl(th->ack_seq));
printk(" fin=%d, syn=%d, rst=%d, psh=%d, ack=%d, urg=%d res1=%d res2=%d\n",
th->fin, th->syn, th->rst, th->psh, th->ack,
th->urg, th->res1, th->res2);
printk(" window = %d, check = %d urg_ptr = %d\n",
ntohs(th->window), ntohs(th->check), ntohs(th->urg_ptr));
printk(" doff = %d\n", th->doff);
ptr =(unsigned char *)(th + 1);
printk(" options = %d %d %d %d\n", ptr[0], ptr[1], ptr[2], ptr[3]);
}
static inline void print_th(struct tcphdr *th)
{
if (inet_debug == DBG_TCP)
__print_th(th);
}
/* This routine grabs the first thing off of a rcv queue. */
static struct sk_buff *
......@@ -616,6 +617,13 @@ static void tcp_send_skb(struct sock *sk, struct sk_buff *skb)
/* We need to complete and send the packet. */
tcp_send_check(skb->h.th, sk->saddr, sk->daddr, size, sk);
size -= 4*skb->h.th->doff;
if (skb->h.th->syn)
size++;
if (skb->h.th->fin)
size++;
sk->send_seq += size;
skb->h.seq = sk->send_seq;
if (after(sk->send_seq , sk->window_seq) ||
(sk->retransmits && sk->timeout == TIME_WRITE) ||
......@@ -737,6 +745,10 @@ if (inet_debug == DBG_SLIP) printk("\rtcp_ack: build_header failed\n");
/* FIXME: */
memcpy(t1, th, sizeof(*t1)); /* this should probably be removed */
/* hack-around */
if (after(sequence, sk->window_seq))
sequence = sk->window_seq;
/* swap the send and the receive. */
t1->dest = th->source;
t1->source = th->dest;
......@@ -920,7 +932,6 @@ tcp_write(struct sock *sk, unsigned char *from,
from += copy;
copied += copy;
len -= copy;
sk->send_seq += copy;
}
if ((skb->len - hdrlen) >= sk->mss ||
(flags & MSG_OOB) ||
......@@ -943,14 +954,11 @@ tcp_write(struct sock *sk, unsigned char *from,
* be queued for later rather than sent.
*/
copy = diff(sk->window_seq, sk->send_seq);
/* what if max_window == 1? In that case max_window >> 1 is 0.
* however in that case copy == max_window, so it's OK to use
* the window */
if (copy < (sk->max_window >> 1))
copy = sk->mss;
copy = min(copy, sk->mss);
copy = min(copy, len);
copy = sk->window_seq - sk->send_seq;
if (copy <= 0 || copy < (sk->max_window >> 1) || copy > sk->mss)
copy = sk->mss;
if (copy > len)
copy = len;
/* We should really check the window here also. */
send_tmp = NULL;
......@@ -1043,7 +1051,6 @@ tcp_write(struct sock *sk, unsigned char *from,
len -= copy;
skb->len += copy;
skb->free = 0;
sk->send_seq += copy;
if (send_tmp != NULL && sk->packets_out) {
tcp_enqueue_partial(send_tmp, sk);
......@@ -1136,7 +1143,10 @@ tcp_read_wakeup(struct sock *sk)
t1 =(struct tcphdr *)(buff->data +tmp);
memcpy(t1,(void *) &sk->dummy_th, sizeof(*t1));
t1->seq = ntohl(sk->send_seq);
if (after(sk->send_seq, sk->window_seq))
t1->seq = ntohl(sk->window_seq);
else
t1->seq = ntohl(sk->send_seq);
t1->ack = 1;
t1->res1 = 0;
t1->res2 = 0;
......@@ -1613,13 +1623,13 @@ tcp_reset(unsigned long saddr, unsigned long daddr, struct tcphdr *th,
if(th->ack)
{
t1->ack=0;
t1->seq=th->ack_seq;
t1->ack_seq=0;
t1->ack = 0;
t1->seq = th->ack_seq;
t1->ack_seq = 0;
}
else
{
t1->ack=1;
t1->ack = 1;
if(!th->syn)
t1->ack_seq=htonl(th->seq);
else
......@@ -3049,75 +3059,60 @@ tcp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len)
}
/* This functions checks to see if the tcp header is actually acceptible. */
/* This functions checks to see if the tcp header is actually acceptable. */
static int
tcp_sequence(struct sock *sk, struct tcphdr *th, short len,
struct options *opt, unsigned long saddr, struct device *dev)
{
/*
* This isn't quite right. sk->acked_seq could be more recent
* than sk->window. This is however close enough. We will accept
* slightly more packets than we should, but it should not cause
* problems unless someone is trying to forge packets.
*/
DPRINTF((DBG_TCP, "tcp_sequence(sk=%X, th=%X, len = %d, opt=%d, saddr=%X)\n",
sk, th, len, opt, saddr));
if (between(th->seq, sk->acked_seq, sk->acked_seq + sk->window)||
between(th->seq + len-(th->doff*4), sk->acked_seq + 1,
sk->acked_seq + sk->window) ||
(before(th->seq, sk->acked_seq) &&
after(th->seq + len -(th->doff*4), sk->acked_seq + sk->window))) {
return(1);
}
DPRINTF((DBG_TCP, "tcp_sequence: rejecting packet.\n"));
unsigned long next_seq;
/*
* Send a reset if we get something not ours and we are
* unsynchronized. Note: We don't do anything to our end. We
* are just killing the bogus remote connection then we will
* connect again and it will work (with luck).
*/
if(sk->state==TCP_SYN_SENT||sk->state==TCP_SYN_RECV)
{
tcp_reset(sk->saddr,sk->daddr,th,sk->prot,NULL,dev, sk->ip_tos,sk->ip_ttl);
return(1);
}
next_seq = len - 4*th->doff;
/* if we have a zero window, we can't have any data in the packet.. */
if (next_seq && !sk->window)
goto ignore_it;
next_seq += th->seq;
if (th->syn)
next_seq++;
/*
* If it's too far ahead, send an ack to let the
* other end know what we expect.
*/
if (after(th->seq, sk->acked_seq + sk->window)) {
if(!th->rst)
tcp_send_ack(sk->send_seq, sk->acked_seq, sk, th, saddr);
return(0);
}
/*
* This isn't quite right. sk->acked_seq could be more recent
* than sk->window. This is however close enough. We will accept
* slightly more packets than we should, but it should not cause
* problems unless someone is trying to forge packets.
*/
#ifdef undef
/*
* if we do this, we won't respond to keepalive packets, since those
* are slightly out of window, and we have to generate an ack
* a late ack out still not to have a sequence number less than
* one we've seen before. Berkeley doesn't seem to do this, but it's
* always hard to be sure.
*/
/* In case it's just a late ack, let it through. */
if (th->ack && len == (th->doff * 4) &&
after(th->seq, sk->acked_seq - 32767) &&
!th->fin && !th->syn) return(1);
#endif
/* have we already seen all of this packet? */
if (!after(next_seq+1, sk->acked_seq))
goto ignore_it;
/* or does it start beyond the window? */
if (!before(th->seq, sk->acked_seq + sk->window + 1))
goto ignore_it;
if (!th->rst) {
/* Try to resync things. */
tcp_send_ack(sk->send_seq, sk->acked_seq, sk, th, saddr);
}
return(0);
}
/* ok, at least part of this packet would seem interesting.. */
return 1;
ignore_it:
DPRINTF((DBG_TCP, "tcp_sequence: rejecting packet.\n"));
/*
* Send a reset if we get something not ours and we are
* unsynchronized. Note: We don't do anything to our end. We
* are just killing the bogus remote connection then we will
* connect again and it will work (with luck).
*/
if (sk->state==TCP_SYN_SENT || sk->state==TCP_SYN_RECV) {
tcp_reset(sk->saddr,sk->daddr,th,sk->prot,NULL,dev, sk->ip_tos,sk->ip_ttl);
return 1;
}
if (th->rst)
return 0;
/* Try to resync things. */
tcp_send_ack(sk->send_seq, sk->acked_seq, sk, th, saddr);
return 0;
}
int
......@@ -3175,14 +3170,12 @@ if (inet_debug == DBG_SLIP) printk("\rtcp_rcv: bad checksum\n");
return(0);
}
th->seq = ntohl(th->seq);
/* See if we know about the socket. */
if (sk == NULL) {
if (!th->rst)
{
th->seq = ntohl(th->seq);
/* So reset is always called with th->seq in host order */
if (!th->rst)
tcp_reset(daddr, saddr, th, &tcp_prot, opt,dev,skb->ip_hdr->tos,255);
}
skb->sk = NULL;
kfree_skb(skb, FREE_READ);
return(0);
......@@ -3196,8 +3189,6 @@ if (inet_debug == DBG_SLIP) printk("\rtcp_rcv: bad checksum\n");
skb->saddr = daddr;
skb->daddr = saddr;
th->seq = ntohl(th->seq);
/* We may need to add it to the backlog here. */
cli();
if (sk->inuse) {
......@@ -3317,12 +3308,11 @@ if (inet_debug == DBG_SLIP) printk("\rtcp_rcv: not in seq\n");
release_sock(sk);
return(0);
}
if (th->ack) {
if (!tcp_ack(sk, th, saddr, len)) {
kfree_skb(skb, FREE_READ);
release_sock(sk);
return(0);
}
if (th->ack && !tcp_ack(sk, th, saddr, len)) {
kfree_skb(skb, FREE_READ);
release_sock(sk);
return(0);
}
if (tcp_urg(sk, th, saddr, len)) {
......@@ -3684,10 +3674,8 @@ tcp_send_probe0(struct sock *sk)
* sends fin in a separate packet
* syn, rst, had better be zero in original */
t1->ack = 1;
t1->urg = 0; /* urgent pointer might be beyond this fragment */
t1->res2 = 0;
t1->window = ntohs(tcp_select_window(sk)/*sk->prot->rspace(sk)*/);
t1->urg_ptr = 0;
tcp_send_check(t1, sk->saddr, sk->daddr, len - hlen, sk);
/* Send it and free it.
* This will prevent the timer from automatically being restarted.
......
......@@ -80,10 +80,7 @@
*/
static inline int before(unsigned long seq1, unsigned long seq2)
{
/* this inequality is strict. */
if (seq1 == seq2)
return 0;
seq2 -= seq1;
seq2 -= seq1+1;
return (seq2 < 65536);
}
......@@ -118,7 +115,6 @@ tcp_connected(const int state)
extern struct proto tcp_prot;
extern void print_th(struct tcphdr *);
extern void tcp_err(int err, unsigned char *header, unsigned long daddr,
unsigned long saddr, struct inet_protocol *protocol);
extern void tcp_shutdown (struct sock *sk, int how);
......
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