Commit 28067f4d authored by Linus Torvalds's avatar Linus Torvalds

Import 0.99.14n

parent 170720a2
VERSION = 0.99
PATCHLEVEL = 14
ALPHA = m
ALPHA = n
all: Version zImage
......
......@@ -10,7 +10,7 @@
* This module exports the console io functions:
*
* 'long con_init(long)'
* 'void con_open(struct tty_queue * queue, struct )'
* 'int con_open(struct tty_struct *tty, struct file * filp)'
* 'void update_screen(int new_console)'
* 'void blank_screen(void)'
* 'void unblank_screen(void)'
......@@ -73,9 +73,10 @@ static char sel_buffer[SEL_BUFFER_SIZE] = { '\0' };
extern void vt_init(void);
extern void register_console(void (*proc)(const char *));
extern void compute_shiftstate(void);
unsigned long video_num_columns; /* Number of text columns */
unsigned long video_num_lines; /* Number of test lines */
unsigned long video_num_lines; /* Number of text lines */
static unsigned char video_type; /* Type of display being used */
static unsigned long video_mem_base; /* Base of video memory */
......@@ -215,29 +216,29 @@ static unsigned char * translations[] = {
/* 8-bit Latin-1 mapped to the PC charater set: '\0' means non-printable */
(unsigned char *)
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\0\0\0\0\0\0\0\0\0\0\376\0\0\0\0\0"
" !\"#$%&'()*+,-./0123456789:;<=>?"
"@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
"`abcdefghijklmnopqrstuvwxyz{|}~\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\040\255\233\234\376\235\174\025\376\376\246\256\252\055\376\376"
"\377\255\233\234\376\235\174\025\376\376\246\256\252\055\376\376"
"\370\361\375\376\376\346\024\371\376\376\247\257\254\253\376\250"
"\376\376\376\376\216\217\222\200\376\220\376\376\376\376\376\376"
"\376\245\376\376\376\376\231\376\235\376\376\376\232\376\376\341"
"\376\245\376\376\376\376\231\376\350\376\376\376\232\376\376\341"
"\205\240\203\376\204\206\221\207\212\202\210\211\215\241\214\213"
"\376\244\225\242\223\376\224\366\233\227\243\226\201\376\376\230",
"\376\244\225\242\223\376\224\366\355\227\243\226\201\376\376\230",
/* vt100 graphics */
(unsigned char *)
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\0\0\0\0\0\0\0\0\0\0\376\0\0\0\0\0"
" !\"#$%&'()*+,-./0123456789:;<=>?"
"@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^ "
"\004\261\007\007\007\007\370\361\007\007\331\277\332\300\305\304"
"\304\304\137\137\303\264\301\302\263\363\362\343\330\234\007\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\040\255\233\234\376\235\174\025\376\376\246\256\252\055\376\376"
"\377\255\233\234\376\235\174\025\376\376\246\256\252\055\376\376"
"\370\361\375\376\376\346\024\371\376\376\247\257\254\253\376\250"
"\376\376\376\376\216\217\222\200\376\220\376\376\376\376\376\376"
"\376\245\376\376\376\376\231\376\376\376\376\376\232\376\376\341"
......@@ -498,12 +499,16 @@ static inline void bs(int currcons)
static inline void del(int currcons)
{
#if 0
if (x) {
pos -= 2;
x--;
if (!need_wrap) { /* this is not the right condition */
pos -= 2;
x--;
}
*(unsigned short *)pos = video_erase_char;
need_wrap = 0;
}
#endif
}
static void csi_J(int currcons, int vpar)
......@@ -1547,6 +1552,7 @@ void update_screen(int new_console)
set_origin(fg_console);
set_cursor(new_console);
set_leds();
compute_shiftstate();
lock = 0;
}
......
This diff is collapsed.
......@@ -5,6 +5,7 @@ keycode 2 = one exclam
alt keycode 2 = Meta_one
keycode 3 = two at at
control keycode 3 = nul
shift control keycode 3 = nul
alt keycode 3 = Meta_two
keycode 4 = three numbersign
control keycode 4 = Escape
......@@ -30,6 +31,7 @@ keycode 11 = zero parenright braceright
alt keycode 11 = Meta_zero
keycode 12 = minus underscore backslash
control keycode 12 = Control_underscore
shift control keycode 12 = Control_underscore
alt keycode 12 = Meta_minus
keycode 13 = equal plus
alt keycode 13 = Meta_equal
......@@ -54,7 +56,7 @@ keycode 27 = bracketright braceright asciitilde
control keycode 27 = Control_bracketright
alt keycode 27 = Meta_bracketright
keycode 28 = Return
alt keycode 28 = 0x080d
alt keycode 28 = Meta_Control_m
keycode 29 = Control
keycode 30 = a
keycode 31 = s
......@@ -87,6 +89,7 @@ keycode 50 = m
keycode 51 = comma less
alt keycode 51 = Meta_comma
keycode 52 = period greater
control keycode 52 = Compose
alt keycode 52 = Meta_period
keycode 53 = slash question
control keycode 53 = Delete
......@@ -196,14 +199,14 @@ keycode 110 = Insert
keycode 111 = Remove
altgr control keycode 111 = Boot
control alt keycode 111 = Boot
keycode 112 =
keycode 113 =
keycode 114 =
keycode 115 =
keycode 116 =
keycode 117 =
keycode 118 =
keycode 119 =
keycode 112 = Macro
keycode 113 = F13
keycode 114 = F14
keycode 115 = Help
keycode 116 = Do
keycode 117 = F17
keycode 118 = KP_MinPlus
keycode 119 = Pause
keycode 120 =
keycode 121 =
keycode 122 =
......@@ -238,9 +241,81 @@ string Remove = "\033[3~"
string Select = "\033[4~"
string Prior = "\033[5~"
string Next = "\033[6~"
string Help = ""
string Do = ""
string Macro = "\033[M"
string Pause = "\033[P"
string F21 = ""
string F22 = ""
string F23 = ""
string F24 = ""
string F25 = ""
string F26 = ""
compose '`' 'A' to ''
compose '`' 'a' to ''
compose '\'' 'A' to ''
compose '\'' 'a' to ''
compose '^' 'A' to ''
compose '^' 'a' to ''
compose '~' 'A' to ''
compose '~' 'a' to ''
compose '"' 'A' to ''
compose '"' 'a' to ''
compose 'O' 'A' to ''
compose 'o' 'a' to ''
compose '0' 'A' to ''
compose '0' 'a' to ''
compose 'A' 'A' to ''
compose 'a' 'a' to ''
compose 'A' 'E' to ''
compose 'a' 'e' to ''
compose ',' 'C' to ''
compose ',' 'c' to ''
compose '`' 'E' to ''
compose '`' 'e' to ''
compose '\'' 'E' to ''
compose '\'' 'e' to ''
compose '^' 'E' to ''
compose '^' 'e' to ''
compose '"' 'E' to ''
compose '"' 'e' to ''
compose '`' 'I' to ''
compose '`' 'i' to ''
compose '\'' 'I' to ''
compose '\'' 'i' to ''
compose '^' 'I' to ''
compose '^' 'i' to ''
compose '"' 'I' to ''
compose '"' 'i' to ''
compose '-' 'D' to ''
compose '-' 'd' to ''
compose '~' 'N' to ''
compose '~' 'n' to ''
compose '`' 'O' to ''
compose '`' 'o' to ''
compose '\'' 'O' to ''
compose '\'' 'o' to ''
compose '^' 'O' to ''
compose '^' 'o' to ''
compose '~' 'O' to ''
compose '~' 'o' to ''
compose '"' 'O' to ''
compose '"' 'o' to ''
compose '/' 'O' to ''
compose '/' 'o' to ''
compose '`' 'U' to ''
compose '`' 'u' to ''
compose '\'' 'U' to ''
compose '\'' 'u' to ''
compose '^' 'U' to ''
compose '^' 'u' to ''
compose '"' 'U' to ''
compose '"' 'u' to ''
compose '\'' 'Y' to ''
compose '\'' 'y' to ''
compose 'T' 'H' to ''
compose 't' 'h' to ''
compose 's' 's' to ''
compose '"' 'y' to ''
compose 's' 'z' to ''
compose 'i' 'j' to ''
#ifndef _DIACR_H
#define _DIACR_H
#include <linux/kd.h>
extern struct kbdiacr accent_table[];
extern unsigned int accent_table_size;
#endif /* _DIACR_H */
This diff is collapsed.
......@@ -586,57 +586,41 @@ void copy_to_cooked(struct tty_struct * tty)
if (c == __DISABLED_CHAR)
tty->lnext = 1;
if (L_CANON(tty) && !tty->lnext) {
if (c == KILL_CHAR(tty) || c == WERASE_CHAR(tty)) {
if (c == ERASE_CHAR(tty) || c == KILL_CHAR(tty) || c == WERASE_CHAR(tty)) {
int seen_alnums =
(c == WERASE_CHAR(tty)) ? 0 : -1;
int cc;
/* deal with killing the input line */
/* deal with killing in the input line */
while(!(EMPTY(&tty->secondary) ||
(c=LAST(&tty->secondary))==10 ||
(cc=LAST(&tty->secondary))==10 ||
((EOF_CHAR(tty) != __DISABLED_CHAR) &&
(c==EOF_CHAR(tty))))) {
(cc==EOF_CHAR(tty))))) {
/* if killing just a word, kill all
non-alnum chars, then all alnum
chars. */
if (seen_alnums >= 0) {
if (isalnum(c))
if (isalnum(cc))
seen_alnums++;
else if (seen_alnums)
break;
}
if (L_ECHO(tty)) {
if (c<32) {
int ct = 1;
if (cc < 32)
ct = (L_ECHOCTL(tty) ? 2 : 0);
while(ct--) {
put_tty_queue('\b', &tty->write_q);
put_tty_queue(' ', &tty->write_q);
put_tty_queue('\b',&tty->write_q);
}
put_tty_queue('\b',&tty->write_q);
put_tty_queue(' ',&tty->write_q);
put_tty_queue('\b',&tty->write_q);
}
DEC(tty->secondary.head);
if(c == ERASE_CHAR(tty))
break;
}
continue;
}
if (c == ERASE_CHAR(tty)) {
if (EMPTY(&tty->secondary) ||
(c=LAST(&tty->secondary))==10 ||
((EOF_CHAR(tty) != __DISABLED_CHAR) &&
(c==EOF_CHAR(tty))))
continue;
if (L_ECHO(tty)) {
if (c<32) {
put_tty_queue('\b',&tty->write_q);
put_tty_queue(' ',&tty->write_q);
put_tty_queue('\b',&tty->write_q);
}
put_tty_queue('\b',&tty->write_q);
put_tty_queue(' ',&tty->write_q);
put_tty_queue('\b',&tty->write_q);
}
DEC(tty->secondary.head);
continue;
}
if (c == LNEXT_CHAR(tty)) {
tty->lnext = 1;
if (L_ECHO(tty)) {
......
......@@ -2,6 +2,7 @@
* kernel/chr_drv/vt.c
*
* Copyright (C) 1992 obz under the linux copyright
* Dynamic diacritical handling - aeb@cwi.nl - Dec 1993
*/
#include <linux/types.h>
......@@ -19,6 +20,7 @@
#include <asm/segment.h>
#include "vt_kern.h"
#include "diacr.h"
/*
* Console (vt and kd) routines, as defined by USL SVR4 manual, and by
......@@ -37,6 +39,7 @@ struct vt_struct vt_cons[NR_CONSOLES];
asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on);
extern void compute_shiftstate(void);
extern void change_console(unsigned int new_console);
extern void complete_change_console(unsigned int new_console);
extern int vt_waitactive(void);
......@@ -212,6 +215,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
} else if (arg == K_XLATE) {
clr_vc_kbd_flag(kbd, VC_RAW);
clr_vc_kbd_flag(kbd, VC_MEDIUMRAW);
compute_shiftstate();
} else if (arg == K_MEDIUMRAW) {
clr_vc_kbd_flag(kbd, VC_RAW);
set_vc_kbd_flag(kbd, VC_MEDIUMRAW);
......@@ -278,10 +282,17 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
i = verify_area(VERIFY_WRITE, (void *)a, sizeof(struct kbsentry));
if (i)
return i;
if ((i = get_fs_byte(&a->kb_func)) >= NR_FUNC)
if ((i = get_fs_byte(&a->kb_func)) >= NR_FUNC || i < 0)
return -EINVAL;
q = a->kb_string;
for (p = func_table[i]; *p; p++)
p = func_table[i];
if(!p) {
/* beware of tables generated for a smaller NR_FUNC */
printk("KDGKBSENT error: func_table[%d] is nil.\n",
i);
return -EINVAL;
}
for ( ; *p; p++)
put_fs_byte(*p, q++);
put_fs_byte(0, q);
return 0;
......@@ -301,7 +312,14 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
return i;
if ((i = get_fs_byte(&a->kb_func)) >= NR_FUNC)
return -EINVAL;
delta = -strlen(func_table[i]);
q = func_table[i];
if (!q) {
/* beware of tables generated for a smaller NR_FUNC */
printk("KDSKBSENT error: func_table[%d] is nil.\n",
i);
return -EINVAL;
}
delta = -strlen(q);
for (p = a->kb_string; get_fs_byte(p); p++)
delta++;
first_free = func_table[NR_FUNC - 1] +
......@@ -317,6 +335,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
func_table[i + 1],
first_free - func_table[i + 1]);
for (k = i + 1; k < NR_FUNC; k++)
if (func_table[k]) /* just to be sure */
func_table[k] += delta;
}
for (p = a->kb_string, q = func_table[i]; ; p++, q++)
......@@ -325,6 +344,35 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
return 0;
}
case KDGKBDIACR:
{
struct kbdiacrs *a = (struct kbdiacrs *)arg;
i = verify_area(VERIFY_WRITE, (void *) a, sizeof(struct kbdiacrs));
if (i)
return i;
put_fs_long(accent_table_size, &a->kb_cnt);
memcpy_tofs(a->kbdiacr, accent_table,
accent_table_size*sizeof(struct kbdiacr));
return 0;
}
case KDSKBDIACR:
{
struct kbdiacrs *a = (struct kbdiacrs *)arg;
unsigned int ct;
i = verify_area(VERIFY_READ, (void *) a, sizeof(struct kbdiacrs));
if (i)
return i;
ct = get_fs_long(&a->kb_cnt);
if (ct >= MAX_DIACR)
return -EINVAL;
accent_table_size = ct;
memcpy_fromfs(accent_table, a->kbdiacr, ct*sizeof(struct kbdiacr));
return 0;
}
case KDGETLED:
i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned char));
if (i)
......
......@@ -8,8 +8,8 @@
include CONFIG
NETDRV_OBJS := net.a(Space.o) net.a(auto_irq.o) net.a(net_init.o)
CFLAGS := $(CFLAGS) -I../../net/inet
CPP := $(CPP) -I../../net/inet
CFLAGS := $(CFLAGS) -I../../net/inet -I../../net/socket -I../../net
CPP := $(CPP) -I../../net/inet -I../../net/socket -I../../net
# The point of the makefile...
all: net.a
......
......@@ -18,6 +18,7 @@
* Pauline Middelink : Slip driver fixes.
* Alan Cox : Honours the old SL_COMPRESSED flag
* Alan Cox : KISS AX.25 and AXUI IP support
* Michael Riepe : Automatic CSLIP recognition added
*/
#include <asm/segment.h>
......@@ -39,9 +40,9 @@
#include <linux/tty.h>
#include <linux/in.h>
#include "inet.h"
#include "dev.h"
#include "devinet.h"
#ifdef CONFIG_AX25
#include "ax25.h"
#include "ax25/ax25.h"
#endif
#include "eth.h"
#include "ip.h"
......@@ -135,10 +136,14 @@ sl_initialize(struct slip *sl, struct device *dev)
sl->sending = 0;
sl->escape = 0;
sl->flags = 0;
#ifdef SL_ADAPTIVE
sl->mode = SL_MODE_ADAPTIVE; /* automatic CSLIP recognition */
#else
#ifdef SL_COMPRESSED
sl->mode = SL_MODE_CSLIP; /* Default */
sl->mode = SL_MODE_CSLIP | SL_MODE_ADAPTIVE; /* Default */
#else
sl->mode = SL_MODE_SLIP; /* Default for non compressors */
#endif
#endif
sl->line = dev->base_addr;
......@@ -351,8 +356,15 @@ sl_bump(struct slip *sl)
int count;
count = sl->rcount;
if (sl->mode & SL_MODE_CSLIP) {
if (sl->mode & (SL_MODE_ADAPTIVE | SL_MODE_CSLIP)) {
if ((c = sl->rbuff[0]) & SL_TYPE_COMPRESSED_TCP) {
#if 1
/* ignore compressed packets when CSLIP is off */
if (!(sl->mode & SL_MODE_CSLIP)) {
printk("SLIP: compressed packet ignored\n");
return;
}
#endif
/* make sure we've reserved enough space for uncompress to use */
save_flags(flags);
cli();
......@@ -374,6 +386,11 @@ sl_bump(struct slip *sl)
return;
}
} else if (c >= SL_TYPE_UNCOMPRESSED_TCP) {
if (!(sl->mode & SL_MODE_CSLIP)) {
/* turn on header compression */
sl->mode |= SL_MODE_CSLIP;
printk("SLIP: header compression turned on\n");
}
sl->rbuff[0] &= 0x4f;
if (slhc_remember(sl->slcomp, sl->rbuff, count) <= 0) {
sl->errors++;
......@@ -485,6 +502,21 @@ sl_encaps(struct slip *sl, unsigned char *icp, int len)
}
}
/*static void sl_hex_dump(unsigned char *x,int l)
{
int n=0;
printk("sl_xmit: (%d bytes)\n",l);
while(l)
{
printk("%2X ",(int)*x++);
l--;
n++;
if(n%32==0)
printk("\n");
}
if(n%32)
printk("\n");
}*/
/* Encapsulate an IP datagram and kick it into a TTY queue. */
static int
......@@ -525,6 +557,7 @@ sl_xmit(struct sk_buff *skb, struct device *dev)
}
#endif
sl_lock(sl);
/* sl_hex_dump((unsigned char *)(skb+1),skb->len);*/
sl_encaps(sl, (unsigned char *) (skb + 1), skb->len);
if (skb->free) kfree_skb(skb, FREE_WRITE);
}
......
......@@ -66,8 +66,9 @@ struct slip {
#define SL_MODE_SLIP 0
#define SL_MODE_CSLIP 1
#define SL_MODE_SLIP6 2 /* Matt Dillon's printable slip */
#define SL_MODE_CSLIP6 (SL_MODE_SLIP|SL_MODE_CSLIP)
#define SL_MODE_CSLIP6 (SL_MODE_SLIP6|SL_MODE_CSLIP)
#define SL_MODE_AX25 4
#define SL_MODE_ADAPTIVE 8
int xdata,xbits; /* 6 bit slip controls */
};
......
......@@ -315,6 +315,7 @@ int sr_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigne
}
/* Now mask and substitute our own volume and reuse the rest */
buffer[0] = 0; /* Clear reserved field */
buffer[21] = volctrl.channel0 & mask[21];
buffer[23] = volctrl.channel1 & mask[23];
......
......@@ -25,7 +25,7 @@ all: local.h sound.a
/usr/include/sys/soundcard.h:
@echo "WARNING! Your /usr/include/sys/soundcard.h not found."
@echo "Please make a new /usr/include/sys/soundcard.h containing
@echo "Please make a new /usr/include/sys/soundcard.h containing"
@echo "just a line #include <linux/soundcard.h>"
sound.a: $(OBJS)
......
......@@ -682,7 +682,7 @@ sb_dsp_init (long mem_start, struct address_info *hw_config)
sb_mixer_init(major);
#endif
#ifndef EXCLUDE_YM8312
#ifndef EXCLUDE_YM3812
if (major > 3 || (major == 3 && minor > 0)) /* SB Pro2 or later */
{
enable_opl3_mode (OPL3_LEFT, OPL3_RIGHT, OPL3_BOTH);
......
Changes from version 0.4a to version 0.4b
=========================================
- Copyrights changed to include the name of my laboratory.
- Clean up of balloc.c and ialloc.c.
- More consistency checks.
- Block preallocation added by Stephen Tweedie.
- Direct reads of directories disallowed if CONFIG_EXT2_FS_DIR_READ not
defined.
- Readahead implemented in readdir by Stephen Tweedie.
- Bugs in block and inodes allocation fixed.
- Readahead implemented in ext2_find_entry by Chip Salzenberg.
- New mount options:
`check=none|normal|strict'
`debug'
`errors=continue|remount-ro|panic'
`grpid', `bsdgroups'
`nocheck'
`nogrpid', `sysvgroups'
- truncate() now tries to deallocate contigous blocks in a single call
to ext2_free_blocks().
- lots of cosmetic changes.
Changes from version 0.4 to version 0.4a
========================================
- the `sync' option support is now complete. Version 0.4 was not
supporting it when truncating a file. I have tested the synchronous
writes and they work but they make the system very slow :-( I have
to work again on this to make it faster.
- when detecting an error on a mounted filesystem, version 0.4 used
to try to write a flag in the super block even if the filesystem had
been mounted read-only. This is fixed.
- the `sb=#' option now causes the kernel code to use the filesystem
descriptors located at block #+1. Version 0.4 used the superblock
backup located at block # but used the main copy of the descriptors.
- a new file attribute `S' is supported. This attribute causes
synchronous writes but is applied to a file not to the entire file
system (thanks to Michael Kraehe <kraehe@bakunin.north.de> for
suggesting it).
- the directory cache is inhibited by default. The cache management
code seems to be buggy and I have to look at it carefully before
using it again.
- deleting a file with the `s' attribute (secure deletion) causes its
blocks to be overwritten with random values not with zeros (thanks to
Michael A. Griffith <grif@cs.ucr.edu> for suggesting it).
- lots of cosmetic changes have been made.
Changes from version 0.3 to version 0.4
=======================================
- Three new mount options are supported: `check', `sync' and `sb=#'.
`check' tells the kernel code to make more consistency checks
when the file system is mounted. Currently, the kernel code checks
that the blocks and inodes bitmaps are consistent with the free
blocks and inodes counts. More checks will be added in future
releases.
`sync' tells the kernel code to use synchronous writes when updating
an inode, a bitmap, a directory entry or an indirect block. This
can make the file system much slower but can be a big win for files
recovery in case of a crash (and we can now say to the BSD folks
that Linux also supports synchronous updates :-).
`sb=#' tells the kernel code to use an alternate super block instead
of its master copy. `#' is the number of the block (counted in
1024 bytes blocks) which contains the alternate super block.
An ext2 file system typically contains backups of the super block
at blocks 8193, 16385, and so on.
- I have change the meaning of the valid flag used by e2fsck. it
now contains the state of the file system. If the kernel code
detects an inconsistency while the file system is mounted, it flags
it as erroneous and e2fsck will detect that on next run.
- The super block now contains a mount counter. This counter is
incremented each time the file system is mounted read/write. When
this counter becomes bigger than a maximal mount counts (also stored
in the super block), e2fsck checks the file system, even if it had
been unmounted cleany, and resets this counter to 0.
- File attributes are now supported. One can associate a set of
attributes to a file. Three attributes are defined:
`c': the file is marked for automatic compression,
`s': the file is marked for secure deletion: when the file is
deleted, its blocks are zeroed and written back to the disk,
`u': the file is marked for undeletion: when the file is deleted,
its contents are saved to allow a future undeletion.
Currently, only the `s' attribute is implemented in the kernel
code. Support for the other attributes will be added in a future
release.
- a few bugs related to times updates have been fixed by Bruce
Evans and me.
- a bug related to the links count of deleted inodes has been fixed.
Previous versions used to keep the links count set to 1 when a file
was deleted. The new version now sets links_count to 0 when deleting
the last link.
- a race condition when deallocating an inode has been fixed by
Stephen Tweedie.
......@@ -462,7 +462,7 @@ int ext2_new_block (struct super_block * sb, unsigned long goal,
EXT2_BLOCKS_PER_GROUP(sb));
if (j >= EXT2_BLOCKS_PER_GROUP(sb)) {
ext2_error (sb, "ext2_new_block",
"Unable to locate free bit in block group %d", i);
"Free blocks count corrupted for block group %d", i);
unlock_super (sb);
return 0;
}
......@@ -486,8 +486,8 @@ int ext2_new_block (struct super_block * sb, unsigned long goal,
tmp == gdp->bg_inode_bitmap ||
in_range (tmp, gdp->bg_inode_table, sb->u.ext2_sb.s_itb_per_group)))
ext2_panic (sb, "ext2_new_block",
"Allocating block in system zone\nblock = %u",
tmp);
"Allocating block in system zone\n"
"block = %u", tmp);
if (set_bit (j, bh->b_data)) {
ext2_warning (sb, "ext2_new_block",
......
......@@ -410,7 +410,7 @@ struct inode * ext2_new_inode (const struct inode * dir, int mode)
/*
* That failed: try linear search for a free inode
*/
i = dir->u.ext2_i.i_block_group + 2;
i = dir->u.ext2_i.i_block_group + 1;
for (j = 2; j < sb->u.ext2_sb.s_groups_count; j++) {
if (++i >= sb->u.ext2_sb.s_groups_count)
i = 0;
......@@ -443,8 +443,17 @@ struct inode * ext2_new_inode (const struct inode * dir, int mode)
ll_rw_block (WRITE, 1, &bh);
wait_on_buffer (bh);
}
} else
} else {
if (gdp->bg_free_inodes_count != 0) {
ext2_error (sb, "ext2_new_inode",
"Free inodes count corrupted in group %d",
i);
unlock_super (sb);
iput (inode);
return NULL;
}
goto repeat;
}
j += i * EXT2_INODES_PER_GROUP(sb) + 1;
if (j < EXT2_FIRST_INO || j > es->s_inodes_count) {
ext2_error (sb, "ext2_new_inode",
......@@ -467,9 +476,13 @@ struct inode * ext2_new_inode (const struct inode * dir, int mode)
inode->i_nlink = 1;
inode->i_dev = sb->s_dev;
inode->i_uid = current->euid;
if ((dir->i_mode & S_ISGID) || test_opt (sb, GRPID))
if (test_opt (sb, GRPID))
inode->i_gid = dir->i_gid;
else if (dir->i_mode & S_ISGID) {
inode->i_gid = dir->i_gid;
else
if (S_ISDIR(mode))
mode |= S_ISGID;
} else
inode->i_gid = current->egid;
inode->i_dirt = 1;
inode->i_ino = j;
......
......@@ -299,7 +299,7 @@ static struct buffer_head * block_getblk (struct inode * inode,
}
}
if (!goal)
goal = bh->b_blocknr + 1;
goal = bh->b_blocknr;
}
tmp = ext2_alloc_block (inode, goal);
if (!tmp) {
......
......@@ -233,13 +233,15 @@ static int parse_options (char * options, unsigned long * sb_block,
return 0;
}
}
else if (!strcmp (this_char, "grpid"))
else if (!strcmp (this_char, "grpid") ||
!strcmp (this_char, "bsdgroups"))
set_opt (*mount_options, GRPID);
else if (!strcmp (this_char, "nocheck")) {
clear_opt (*mount_options, CHECK_NORMAL);
clear_opt (*mount_options, CHECK_STRICT);
}
else if (!strcmp (this_char, "nogrpid"))
else if (!strcmp (this_char, "nogrpid") ||
!strcmp (this_char, "sysvgroups"))
clear_opt (*mount_options, GRPID);
else if (!strcmp (this_char, "sb")) {
if (!value || !*value) {
......@@ -271,7 +273,8 @@ static void ext2_setup_super (struct super_block * sb,
else if ((sb->u.ext2_sb.s_mount_state & EXT2_ERROR_FS))
printk ("EXT2-fs warning: mounting fs with errors, "
"running e2fsck is recommended\n");
else if (es->s_mnt_count >= es->s_max_mnt_count)
else if (es->s_max_mnt_count >= 0 &&
es->s_mnt_count >= es->s_max_mnt_count)
printk ("EXT2-fs warning: maximal mount count reached, "
"running e2fsck is recommended\n");
if (!(sb->s_flags & MS_RDONLY)) {
......@@ -390,8 +393,8 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data,
unlock_super (sb);
brelse (bh);
if (!silent)
printk ("VFS: Can't find an ext2 filesystem on dev 0x%04x.\n",
dev);
printk ("VFS: Can't find an ext2 filesystem on dev %d/%d.\n",
MAJOR(dev), MINOR(dev));
return NULL;
}
sb->s_blocksize = EXT2_MIN_BLOCK_SIZE << es->s_log_block_size;
......@@ -477,8 +480,8 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data,
unlock_super (sb);
brelse (bh);
if (!silent)
printk ("VFS: Can't find an ext2 filesystem on dev 0x%04x.\n",
dev);
printk ("VFS: Can't find an ext2 filesystem on dev %d/%d.\n",
MAJOR(dev), MINOR(dev));
return NULL;
}
if (sb->s_blocksize != bh->b_size) {
......@@ -522,7 +525,7 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data,
sb->s_dev = 0;
unlock_super (sb);
for (j = 0; j < i; j++)
brelse (sb->u.ext2_sb.s_group_desc[i]);
brelse (sb->u.ext2_sb.s_group_desc[j]);
brelse (bh);
printk ("EXT2-fs: unable to read group descriptors\n");
return NULL;
......@@ -532,7 +535,7 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data,
sb->s_dev = 0;
unlock_super (sb);
for (j = 0; j < i; j++)
brelse (sb->u.ext2_sb.s_group_desc[i]);
brelse (sb->u.ext2_sb.s_group_desc[j]);
brelse (bh);
printk ("EXT2-fs: group descriptors corrupted !\n");
return NULL;
......
......@@ -46,6 +46,8 @@ static int trunc_direct (struct inode * inode)
int i, tmp;
unsigned long * p;
struct buffer_head * bh;
unsigned long block_to_free = 0;
unsigned long free_count = 0;
int retry = 0;
int blocks = inode->i_sb->s_blocksize / 512;
#define DIRECT_BLOCK ((inode->i_size + inode->i_sb->s_blocksize - 1) / \
......@@ -82,8 +84,20 @@ static int trunc_direct (struct inode * inode)
bh->b_dirt = 1;
}
brelse (bh);
ext2_free_blocks (inode->i_sb, tmp, 1);
if (free_count == 0) {
block_to_free = tmp;
free_count++;
} else if (free_count > 0 && block_to_free == tmp - free_count)
free_count++;
else {
ext2_free_blocks (inode->i_sb, block_to_free, free_count);
block_to_free = tmp;
free_count = 1;
}
/* ext2_free_blocks (inode->i_sb, tmp, 1); */
}
if (free_count > 0)
ext2_free_blocks (inode->i_sb, block_to_free, free_count);
return retry;
}
......@@ -93,6 +107,8 @@ static int trunc_indirect (struct inode * inode, int offset, unsigned long * p)
struct buffer_head * bh;
struct buffer_head * ind_bh;
unsigned long * ind;
unsigned long block_to_free = 0;
unsigned long free_count = 0;
int retry = 0;
int addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb);
int blocks = inode->i_sb->s_blocksize / 512;
......@@ -144,10 +160,22 @@ static int trunc_indirect (struct inode * inode, int offset, unsigned long * p)
bh->b_dirt = 1;
}
brelse (bh);
ext2_free_blocks (inode->i_sb, tmp, 1);
if (free_count == 0) {
block_to_free = tmp;
free_count++;
} else if (free_count > 0 && block_to_free == tmp - free_count)
free_count++;
else {
ext2_free_blocks (inode->i_sb, block_to_free, free_count);
block_to_free = tmp;
free_count = 1;
}
/* ext2_free_blocks (inode->i_sb, tmp, 1); */
inode->i_blocks -= blocks;
inode->i_dirt = 1;
}
if (free_count > 0)
ext2_free_blocks (inode->i_sb, block_to_free, free_count);
ind = (unsigned long *) ind_bh->b_data;
for (i = 0; i < addr_per_block; i++)
if (*(ind++))
......
......@@ -486,6 +486,7 @@ asmlinkage int sys_mount(char * dev_name, char * dir_name, char * type,
return retval;
}
}
page = 0;
if ((new_flags & MS_MGC_MSK) == MS_MGC_VAL) {
flags = new_flags & ~MS_MGC_MSK;
retval = copy_mount_options(data, &page);
......
......@@ -52,7 +52,7 @@
/*
* The second extended file system version
*/
#define EXT2FS_DATE "93/12/30"
#define EXT2FS_DATE "94/01/05"
#define EXT2FS_VERSION "0.4b"
/*
......@@ -289,7 +289,7 @@ struct ext2_super_block {
unsigned long s_mtime; /* Mount time */
unsigned long s_wtime; /* Write time */
unsigned short s_mnt_count; /* Mount count */
unsigned short s_max_mnt_count; /* Maximal mount count */
short s_max_mnt_count; /* Maximal mount count */
unsigned short s_magic; /* Magic signature */
unsigned short s_state; /* File system state */
unsigned short s_errors; /* Behaviour when detecting errors */
......
......@@ -59,6 +59,8 @@ struct options {
unsigned short handling;
unsigned short stream;
unsigned tcc;
int option_length;
void *option_data;
};
......
......@@ -184,4 +184,14 @@ struct kbsentry {
#define KDGKBSENT 0x4B48 /* gets one function key string entry */
#define KDSKBSENT 0x4B49 /* sets one function key string entry */
struct kbdiacr {
u_char diacr, base, result;
};
struct kbdiacrs {
unsigned int kb_cnt; /* number of entries in following array */
struct kbdiacr kbdiacr[256]; /* MAX_DIACR from keyboard.h */
};
#define KDGKBDIACR 0x4B4A /* read kernel accent table */
#define KDSKBDIACR 0x4B4B /* write kernel accent table */
#endif /* _LINUX_KD_H */
......@@ -4,19 +4,6 @@
#include <linux/interrupt.h>
#define set_leds() mark_bh(KEYBOARD_BH)
/*
* "dead" keys - prefix key values that are valid only for the next
* character code (sticky shift, E0/E1 special scancodes, diacriticals)
*/
extern unsigned long kbd_dead_keys;
extern unsigned long kbd_prev_dead_keys;
/*
* these are the hardcoded dead key flags
*/
#define KGD_E0 0
#define KGD_E1 1
/*
* kbd->xxx contains the VC-local things (flag settings etc..)
* The low 3 local flags are hardcoded to be the led setting..
......@@ -52,26 +39,6 @@ extern struct kbd_struct kbd_table[];
extern unsigned long kbd_init(unsigned long);
extern inline int kbd_dead(int flag)
{
return kbd_prev_dead_keys & (1 << flag);
}
extern inline void set_kbd_dead(int flag)
{
kbd_dead_keys |= 1 << flag;
}
extern inline void clr_kbd_dead(int flag)
{
kbd_dead_keys &= ~(1 << flag);
}
extern inline void chg_kbd_dead(int flag)
{
kbd_dead_keys ^= 1 << flag;
}
extern inline int vc_kbd_flag(struct kbd_struct * kbd, int flag)
{
return ((kbd->flags >> flag) & 1);
......@@ -98,7 +65,7 @@ extern const int NR_TYPES;
extern const int max_vals[];
extern unsigned short key_map[NR_KEYMAPS][NR_KEYS];
#define NR_FUNC 32
#define NR_FUNC 36
#define FUNC_BUFSIZE 512
extern char func_buf[FUNC_BUFSIZE];
extern char *func_table[NR_FUNC];
......@@ -145,6 +112,10 @@ extern char *func_table[NR_FUNC];
#define K_SELECT K(KT_FN,23)
#define K_PGUP K(KT_FN,24)
#define K_PGDN K(KT_FN,25)
#define K_MACRO K(KT_FN,26)
#define K_HELP K(KT_FN,27)
#define K_DO K(KT_FN,28)
#define K_PAUSE K(KT_FN,29)
#define K_HOLE K(KT_SPEC,0)
#define K_ENTER K(KT_SPEC,1)
......@@ -160,6 +131,7 @@ extern char *func_table[NR_FUNC];
#define K_SCROLLBACK K(KT_SPEC,11)
#define K_BOOT K(KT_SPEC,12)
#define K_CAPSON K(KT_SPEC,13)
#define K_COMPOSE K(KT_SPEC,14)
#define K_P0 K(KT_PAD,0)
#define K_P1 K(KT_PAD,1)
......@@ -178,6 +150,7 @@ extern char *func_table[NR_FUNC];
#define K_PENTER K(KT_PAD,14) /* key-pad enter */
#define K_PCOMMA K(KT_PAD,15) /* key-pad comma: kludge... */
#define K_PDOT K(KT_PAD,16) /* key-pad dot (period): kludge... */
#define K_PPLUSMINUS K(KT_PAD,17) /* key-pad plus/minus */
#define K_DGRAVE K(KT_DEAD,0)
#define K_DACUTE K(KT_DEAD,1)
......@@ -220,4 +193,5 @@ extern char *func_table[NR_FUNC];
#define K_ALTLOCK K(KT_LOCK,3)
#define K_ALTGRLOCK K(KT_LOCK,1)
#define MAX_DIACR 256
#endif
......@@ -30,10 +30,14 @@ struct linger {
#define AF_UNSPEC 0
#define AF_UNIX 1
#define AF_INET 2
#define AF_AX25 3
#define AF_IPX 4
/* Protocol families, same as address families. */
#define PF_UNIX AF_UNIX
#define PF_INET AF_INET
#define PF_AX25 AF_AX25
#define PF_IPX AF_IPX
/* Flags we can use with send/ and recv. */
#define MSG_OOB 1
......@@ -41,6 +45,10 @@ struct linger {
/* Setsockoptions(2) level. */
#define SOL_SOCKET 1
#define SOL_IP 2
#define SOL_IPX 3
#define SOL_AX25 4
#define SOL_TCP 5
/* For setsockoptions(2) */
#define SO_DEBUG 1
......@@ -56,6 +64,19 @@ struct linger {
#define SO_NO_CHECK 11
#define SO_PRIORITY 12
#define SO_LINGER 13
/* IP options */
#define IP_TOS 1
#define IPTOS_LOWDELAY 0x10
#define IPTOS_THROUGHPUT 0x08
#define IPTOS_RELIABILITY 0x04
#define IP_TTL 2
/* IPX options */
#define IPX_TYPE 1
/* AX.25 options */
#define AX25_WINDOW 1
/* TCP options */
#define TCP_MSS 1
#define TCP_NODELAY 2
/* The various priorities. */
#define SOPRI_INTERACTIVE 0
......
......@@ -24,11 +24,11 @@
#define IP_SET_DEV 0x2401
struct ip_config {
char name[MAX_IP_NAME];
unsigned long paddr;
unsigned long router;
unsigned long net;
unsigned int up:1,destroy:1;
char name[MAX_IP_NAME];
unsigned long paddr;
unsigned long router;
unsigned long net;
unsigned int up:1,destroy:1;
};
#endif /* FIXME: */
......
......@@ -149,7 +149,9 @@ sys_get_kernel_syms(struct kernel_sym *table)
if (table != NULL) {
from = symbol_table;
to = table;
verify_area(VERIFY_WRITE, to, symbol_table_size * sizeof *table);
i = verify_area(VERIFY_WRITE, to, symbol_table_size * sizeof *table);
if (i)
return i;
for (i = symbol_table_size ; --i >= 0 ; ) {
sym.value = from->addr;
strncpy(sym.name, from->name, sizeof sym.name);
......
......@@ -7,10 +7,17 @@
#
# Note 2! The CFLAGS definition is now in the main makefile...
# only these two lines should need to be changed to remove inet sockets.
# (and the inet/tcpip.o in net.o)
SUBDIRS := unix socket
SUBDIRS := unix inet
ifdef CONFIG_INET
SUBDIRS := $(SUBDIRS) inet
endif
ifdef CONFIG_IPX
SUBDIRS := $(SUBDIRS) ipx
endif
ifdef CONFIG_AX25
SUBDIRS := $(SUBDIRS) ax25
endif
SUBOBJS := $(foreach f,$(SUBDIRS),$f/$f.o)
......
......@@ -30,10 +30,10 @@
# include "inet/inet.h"
#endif
#ifdef CONFIG_IPX
#include "inet/ipxcall.h"
#include "ipx/ipxcall.h"
#endif
#ifdef CONFIG_AX25
#include "inet/ax25call.h"
#include "ax25/ax25call.h"
#endif
struct ddi_proto protocols[] = {
......@@ -53,43 +53,3 @@ struct ddi_proto protocols[] = {
};
/*
* Section B: Device Driver Modules.
* This section defines which network device drivers
* get linked into the Linux kernel. It is currently
* only used by the INET protocol. Any takers for the
* other protocols like XNS or Novell?
*
* WARNING: THIS SECTION IS NOT YET USED BY THE DRIVERS !!!!!
*/
/*#include "drv/we8003/we8003.h" Western Digital WD-80[01]3 */
/*#include "drv/dp8390/dp8390.h" Donald Becker's DP8390 kit */
/*#inclde "drv/slip/slip.h" Laurence Culhane's SLIP kit */
struct ddi_device devices[] = {
#if CONF_WE8003
{ "WD80x3[EBT]",
"", 0, 1, we8003_init, NULL,
19, 0, DDI_FCHRDEV,
{ 0x280, 0, 15, 0, 32768, 0xD0000 } },
#endif
#if CONF_DP8390
{ "DP8390/WD80x3",
"", 0, 1, dpwd8003_init, NULL,
20, 0, DDI_FCHRDEV,
{ 0, 0, 0, 0, 0, 0, } },
{ "DP8390/NE-x000",
"", 0, 1, dpne2000_init, NULL,
20, 8, DDI_FCHRDEV,
{ 0, 0, 0, 0, 0, 0, } },
{ "DP8390/3C50x",
"", 0, 1, dpec503_init, NULL,
20, 16, DDI_FCHRDEV,
{ 0, 0, 0, 0, 0, 0, } },
#endif
{ NULL,
"", 0, 0, NULL, NULL,
0, 0, 0,
{ 0, 0, 0, 0, 0, 0 } }
};
......@@ -4,9 +4,11 @@
* but it eventually might move to an upper directory of
* the system.
*
* Version: @(#)ddi.c 1.0.5 04/22/93
* Version: @(#)ddi.c 1.28 27/12/93
*
* Author: Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
*
* Unused pieces nobbled.
*/
#include <asm/segment.h>
#include <asm/system.h>
......@@ -18,6 +20,9 @@
#include <linux/mm.h>
#include <linux/socket.h>
#include <linux/ddi.h>
#include <linux/interrupt.h>
#include "socket/dev.h"
#undef DDI_DEBUG
......@@ -28,64 +33,32 @@
#endif
extern struct ddi_device devices[]; /* device driver map */
extern struct ddi_proto protocols[]; /* network protocols */
/*
* This function gets called with an ASCII string representing the
* ID of some DDI driver. We loop through the DDI Devices table
* and return the address of the control block that has a matching
* "name" field. It is used by upper-level layers that want to
* dynamically bind some UNIX-domain "/dev/XXXX" file name to a
* DDI device driver. The "iflink(8)" program is an example of
* this behaviour.
*/
struct ddi_device *
ddi_map(const char *id)
{
register struct ddi_device *dev;
PRINTK (("DDI: MAP: looking for \"%s\": ", id));
dev = devices;
while (dev->title != NULL) {
if (strncmp(dev->name, id, DDI_MAXNAME) == 0) {
PRINTK (("OK at 0x%X\n", dev));
return(dev);
}
dev++;
}
PRINTK (("NOT FOUND\n"));
return(NULL);
}
/*
* This is the function that is called by a kernel routine during
* system startup. Its purpose is to walk trough the "devices"
* table (defined above), and to call all moduled defined in it.
*/
void
ddi_init(void)
void ddi_init(void)
{
struct ddi_proto *pro;
struct ddi_device *dev;
struct ddi_proto *pro;
PRINTK (("DDI: Starting up!\n"));
PRINTK (("DDI: Starting up!\n"));
/* First off, kick all configured protocols. */
pro = protocols;
while (pro->name != NULL) {
(*pro->init)(pro);
pro++;
}
/* First off, kick all configured protocols. */
pro = protocols;
while (pro->name != NULL)
{
(*pro->init)(pro);
pro++;
}
/* Done. Now kick all configured device drivers. */
dev = devices;
while (dev->title != NULL) {
(*dev->init)(dev);
dev++;
}
/* We're all done... */
}
dev_init();
/* Initialize the "Buffer Head" pointers. */
bh_base[INET_BH].routine = inet_bh;
/* We're all done... */
}
......@@ -7,6 +7,9 @@
#
# Note 2! The CFLAGS definition is now in the main makefile...
CFLAGS := $(CFLAGS) -I../socket -I..
CPP := $(CPP) -I../socket -I..
.c.o:
$(CC) $(CFLAGS) -c -o $*.o $<
.s.o:
......@@ -15,10 +18,8 @@
$(CC) $(CFLAGS) -S -o $*.s $<
OBJS = sock.o utils.o route.o proc.o timer.o protocol.o loopback.o \
eth.o packet.o arp.o dev.o ip.o raw.o icmp.o tcp.o udp.o \
datagram.o skbuff.o
# ipx.o ax25.o ax25_in.o ax25_out.o ax25_subr.o ax25_timer.o
OBJS = sockinet.o utils.o route.o proc.o timer.o protocol.o loopback.o \
eth.o packet.o arp.o devinet.o ip.o raw.o icmp.o tcp.o udp.o
ifdef CONFIG_INET
......
NET2Debugged 1.24 README
NET2Debugged 1.28 README
------------------------
Major Changes
o PLIP driver sort of works
o UDP and RAW have been partially rewritten for speed
o Internals heavily cleaned up, and memory monitoring of network
memory is now done. (On shift-scroll-lock)
o ARP should now not generate garbage
o Using MSG_PEEK can't cause race conditions and crashes
o Support for bootp clients.
o Supports RFC931 TAP authd
o NFS problems with certain types of network configuration are
fixed.
o Doesn't forward packets for other subnet (can cause packet storms)
o TCP won't ack rst frames causing packet storms (especially with
Lan workplace for DOS).
o Numerous fixes for solidity
o Verify_area used properly.
o MSG_PEEK is faster again
o Minor TCP fixes. Hopefully no more TCP lockups (ha!)
o Donald's promiscuous mode. Go forth and write protocol analysers...
-------------------------------------------------------------------------
NOTE:
Drivers for this stack set must be using alloc_skb() not just
......
This diff is collapsed.
......@@ -5,7 +5,7 @@
*
* Definitions for the ARP protocol module.
*
* Version: @(#)arp.h 1.0.6 05/21/93
* Version: @(#)arp.h 1.28 24/12/93
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
......@@ -26,29 +26,31 @@
#define ARP_QUEUE_MAGIC 0x0432447A /* magic # for queues */
/* This structure defines the ARP mapping cache. */
struct arp_table {
struct arp_table *next;
volatile unsigned long last_used;
unsigned int flags;
#if 1
unsigned long ip;
#else
unsigned char pa[MAX_ADDR_LEN];
unsigned char plen;
unsigned char ptype;
#endif
unsigned char ha[MAX_ADDR_LEN];
unsigned char hlen;
unsigned char htype;
/*
* This structure defines the ARP mapping cache.
*/
struct arp_table
{
struct arp_table *next;
volatile unsigned long last_used;
unsigned int flags;
unsigned long ip;
unsigned char ha[MAX_ADDR_LEN];
unsigned char hlen;
unsigned char htype;
};
/* This is also used in "sock.c" and "tcp.c" - YUCK! - FvK */
/*
* This is also used in "sock.c" and "tcp.c" - YUCK! - FvK
*/
extern struct sk_buff *arp_q;
extern void arp_destroy(unsigned long paddr);
extern void arp_destroy_maybe(unsigned long paddr);
extern int arp_rcv(struct sk_buff *skb, struct device *dev,
struct packet_type *pt);
extern int arp_find(unsigned char *haddr, unsigned long paddr,
......
......@@ -790,7 +790,6 @@ static inline int bad_mask(unsigned long mask, unsigned long addr)
return 0;
}
/* Perform the SIOCxIFxxx calls. */
static int
dev_ifsioc(void *arg, unsigned int getset)
......
/*
* INET An implementation of the TCP/IP protocol suite for the LINUX
* operating system. INET is implemented using the BSD Socket
* interface as the means of communication with the user level.
*
* Interface (streams) handling functions.
*
* Version: @(#)dev.c 1.28 20/12/93
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
* Mark Evans, <evansmp@uhura.aston.ac.uk>
*
* Fixes:
* Alan Cox: check_addr returns a value for a wrong subnet
* ie not us but don't forward this!
* Alan Cox: block timer if the inet_bh handler is running
* Alan Cox: generic queue code added. A lot neater now
* C.E.Hawkins: SIOCGIFCONF only reports 'upped' interfaces
* C.E.Hawkins: IFF_PROMISC support
* Alan Cox: Supports Donald Beckers new hardware
* multicast layer, but not yet multicast lists.
* Alan Cox: ip_addr_match problems with class A/B nets.
* C.E.Hawkins IP 0.0.0.0 and also same net route fix. [FIXME: Ought to cause ICMP_REDIRECT]
* Alan Cox: Removed bogus subnet check now the subnet code
* a) actually works for all A/B nets
* b) doesn't forward off the same interface.
* Alan Cox: Multiple extra protocols
* Alan Cox: A Couple more escaped verify_area calls die
* Alan Cox: IP_SET_DEV is gone (forever) as per Fred's comment.
* Alan Cox: Grand tidy up ready for the big day.
* Alan Cox: Handles dev_open errors correctly.
* Alan Cox: IP and generic parts split
*
* 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
* 2 of the License, or (at your option) any later version.
*/
#include <asm/segment.h>
#include <asm/system.h>
#include <asm/bitops.h>
#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/socket.h>
#include <linux/sockios.h>
#include <linux/in.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/if_ether.h>
#include "inet.h"
#include "devinet.h"
#include "eth.h"
#include "ip.h"
#include "route.h"
#include "protocol.h"
#include "tcp.h"
#include "skbuff.h"
/*
* Determine a default network mask, based on the IP address.
*/
unsigned long ip_get_mask(unsigned long addr)
{
unsigned long dst;
if (addr == 0L)
return(0L); /* special case */
dst = ntohl(addr);
if (IN_CLASSA(dst))
return(htonl(IN_CLASSA_NET));
if (IN_CLASSB(dst))
return(htonl(IN_CLASSB_NET));
if (IN_CLASSC(dst))
return(htonl(IN_CLASSC_NET));
/* Something else, probably a subnet. */
return(0);
}
/*
* See if a pair of addresses match.
*/
int ip_addr_match(unsigned long me, unsigned long him)
{
int i;
unsigned long mask=0xFFFFFFFF;
DPRINTF((DBG_DEV, "ip_addr_match(%s, ", in_ntoa(me)));
DPRINTF((DBG_DEV, "%s)\n", in_ntoa(him)));
/* Fast path for 99.9% of cases */
if (me == him)
return(1);
for (i = 0; i < 4; i++, me >>= 8, him >>= 8, mask >>= 8)
{
if ((me & 0xFF) != (him & 0xFF))
{
/*
* The only way this could be a match is for
* the rest of addr1 to be 0 or 255.
*/
if (me != 0 && me != mask)
return(0);
return(1);
}
}
return(1);
}
/*
* Check the address for our address, broadcasts, etc.
*
* This routine is used a lot, and in many time critical
* places. It's already _TOO_ slow so be careful how you
* alter it.
*/
int chk_addr(unsigned long addr)
{
struct device *dev;
unsigned long dst;
DPRINTF((DBG_DEV, "chk_addr(%s) --> ", in_ntoa(addr)));
dst = ntohl(addr);
/*
* Accept both `all ones' and `all zeros' as BROADCAST.
* All 0's is the old BSD broadcast.
*/
if (dst == INADDR_ANY || dst == INADDR_BROADCAST)
{
DPRINTF((DBG_DEV, "BROADCAST\n"));
return(IS_BROADCAST);
}
/* Accept all of the `loopback' class A net. */
if ((dst & IN_CLASSA_NET) == 0x7F000000L)
{
DPRINTF((DBG_DEV, "LOOPBACK\n"));
/*
* We force `loopback' to be equal to MY_ADDR.
*/
return(IS_MYADDR);
/* return(IS_LOOPBACK); */
}
/* OK, now check the interface addresses. */
for (dev = dev_base; dev != NULL; dev = dev->next)
{
if (!(dev->flags&IFF_UP))
continue;
if ((dev->pa_addr == 0)/* || (dev->flags&IFF_PROMISC)*/)
return(IS_MYADDR);
/* Is it the exact IP address? */
if (addr == dev->pa_addr)
{
DPRINTF((DBG_DEV, "MYADDR\n"));
return(IS_MYADDR);
}
/* Nope. Check for a subnetwork broadcast. */
if ((addr & dev->pa_mask) == (dev->pa_addr & dev->pa_mask))
{
if ((addr & ~dev->pa_mask) == 0)
{
DPRINTF((DBG_DEV, "SUBBROADCAST-0\n"));
return(IS_BROADCAST);
}
if (((addr & ~dev->pa_mask) | dev->pa_mask)
== INADDR_BROADCAST)
{
DPRINTF((DBG_DEV, "SUBBROADCAST-1\n"));
return(IS_BROADCAST);
}
}
/* Nope. Check for Network broadcast. */
if(IN_CLASSA(dst))
{
if( addr == (dev->pa_addr | 0xffffff00))
{
DPRINTF((DBG_DEV, "CLASS A BROADCAST-1\n"));
return(IS_BROADCAST);
}
}
else if(IN_CLASSB(dst))
{
if( addr == (dev->pa_addr | 0xffff0000))
{
DPRINTF((DBG_DEV, "CLASS B BROADCAST-1\n"));
return(IS_BROADCAST);
}
}
else
{ /* IN_CLASSC */
if( addr == (dev->pa_addr | 0xff000000))
{
DPRINTF((DBG_DEV, "CLASS C BROADCAST-1\n"));
return(IS_BROADCAST);
}
}
}
DPRINTF((DBG_DEV, "NONE\n"));
return(0); /* no match at all */
}
/*
* Retrieve our own address.
* Because the loopback address (127.0.0.1) is already recognized
* automatically, we can use the loopback interface's address as
* our "primary" interface. This is the addressed used by IP et
* al when it doesn't know which address to use (i.e. it does not
* yet know from or to which interface to go...).
*/
unsigned long my_addr(void)
{
struct device *dev;
for (dev = dev_base; dev != NULL; dev = dev->next)
{
if (dev->flags & IFF_LOOPBACK)
return(dev->pa_addr);
}
return(0);
}
/*
* Find an interface that can handle addresses for a certain address.
*/
struct device *dev_check(unsigned long addr)
{
struct device *dev;
for (dev = dev_base; dev; dev = dev->next)
if ((dev->flags & IFF_UP) && (dev->flags & IFF_POINTOPOINT) &&
(addr == dev->pa_dstaddr))
return dev;
for (dev = dev_base; dev; dev = dev->next)
if ((dev->flags & IFF_UP) && !(dev->flags & IFF_POINTOPOINT) &&
(dev->flags & IFF_LOOPBACK ? (addr == dev->pa_addr) :
(dev->pa_mask & addr) == (dev->pa_addr & dev->pa_mask)))
break;
/* no need to check broadcast addresses */
return dev;
}
/*
* INET An implementation of the TCP/IP protocol suite for the LINUX
* operating system. INET is implemented using the BSD Socket
* interface as the means of communication with the user level.
*
* Definitions for the INET bits of the interfaces handler.
*
*/
#ifndef _DEVINET_H
#define _DEVINET_H
#ifndef _DEV_H
#include "dev.h"
#endif
extern int ip_addr_match(unsigned long addr1, unsigned long addr2);
extern int chk_addr(unsigned long addr);
extern struct device *dev_check(unsigned long daddr);
extern unsigned long my_addr(void);
#endif /* _DEVINET_H */
......@@ -5,24 +5,27 @@
*
* Ethernet-type device handling.
*
* Version: @(#)eth.c 1.0.7 05/25/93
* Version: @(#)eth.c 1.28 20/12/93
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
* Mark Evans, <evansmp@uhura.aston.ac.uk>
*
* Fixes:
* Mr Linux : Arp problems
* Alan Cox : Generic queue tidyup (very tiny here)
* Alan Cox : eth_header ntohs should be htons
* Mr Linux : Arp problems.
* Alan Cox : Generic queue tidyup (very tiny here).
* Alan Cox : eth_header ntohs should be htons.
* Alan Cox : eth_rebuild_header missing an htons and
* minor other things.
* Tegge : Arp bug fixes.
* Alan Cox : Tidy up ready for the big day.
*
* 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
* 2 of the License, or (at your option) any later version.
*/
#include <asm/segment.h>
#include <asm/system.h>
#include <linux/types.h>
......@@ -33,18 +36,19 @@
#include <linux/socket.h>
#include <linux/in.h>
#include "inet.h"
#include "dev.h"
#include "devinet.h"
#include "eth.h"
#include "ip.h"
#include "route.h"
#include "protocol.h"
#include "tcp.h"
#include "skbuff.h"
#include "sock.h"
#include "sockinet.h"
#include <linux/errno.h>
#include "arp.h"
#ifdef ETH_DEBUG
/* Display an Ethernet address in readable format. */
char *eth_print(unsigned char *ptr)
{
......@@ -57,32 +61,16 @@ char *eth_print(unsigned char *ptr)
);
return(buff);
}
#endif
void eth_setup(char *str, int *ints)
{
struct device *d = dev_base;
if (!str || !*str)
return;
while (d) {
if (!strcmp(str,d->name)) {
if (ints[0] > 0)
d->irq=ints[1];
if (ints[0] > 1)
d->base_addr=ints[2];
if (ints[0] > 2)
d->mem_start=ints[3];
if (ints[0] > 3)
d->mem_end=ints[4];
break;
}
d=d->next;
}
}
/* Display the contents of the Ethernet MAC header. */
void
eth_dump(struct ethhdr *eth)
#ifdef ETH_DEBUG
/*
* Display the contents of the Ethernet MAC header.
*/
void eth_dump(struct ethhdr *eth)
{
if (inet_debug != DBG_ETH) return;
......@@ -91,96 +79,128 @@ eth_dump(struct ethhdr *eth)
printk("TYPE = %04X\n", ntohs(eth->h_proto));
}
#endif
/* Create the Ethernet MAC header. */
int
eth_header(unsigned char *buff, struct device *dev, unsigned short type,
/*
* Create the Ethernet MAC header.
*
* ARP might prevent this from working all in one go. See also
* the rebuild header function.
*/
int eth_header(unsigned char *buff, struct device *dev, unsigned short type,
unsigned long daddr, unsigned long saddr, unsigned len)
{
struct ethhdr *eth;
DPRINTF((DBG_DEV, "ETH: header(%s, ", in_ntoa(saddr)));
DPRINTF((DBG_DEV, "%s, 0x%X)\n", in_ntoa(daddr), type));
/* Fill in the basic Ethernet MAC header. */
eth = (struct ethhdr *) buff;
eth->h_proto = htons(type);
/* We don't ARP for the LOOPBACK device... */
if (dev->flags & IFF_LOOPBACK) {
DPRINTF((DBG_DEV, "ETH: No header for loopback\n"));
memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
memset(eth->h_dest, 0, dev->addr_len);
return(dev->hard_header_len);
}
/* Check if we can use the MAC BROADCAST address. */
if (chk_addr(daddr) == IS_BROADCAST) {
DPRINTF((DBG_DEV, "ETH: Using MAC Broadcast\n"));
memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
memcpy(eth->h_dest, dev->broadcast, dev->addr_len);
return(dev->hard_header_len);
}
cli();
memcpy(eth->h_source, &saddr, 4);
/* No. Ask ARP to resolve the Ethernet address. */
if (arp_find(eth->h_dest, daddr, dev, saddr))
{
sti();
if(type!=ETH_P_IP)
printk("Erk: protocol %X got into an arp request state!\n",type);
return(-dev->hard_header_len);
}
else
{
memcpy(eth->h_source,dev->dev_addr,dev->addr_len); /* This was missing causing chaos if the
header built correctly! */
sti();
return(dev->hard_header_len);
}
struct ethhdr *eth;
DPRINTF((DBG_DEV, "ETH: header(%s, ", in_ntoa(saddr)));
DPRINTF((DBG_DEV, "%s, 0x%X)\n", in_ntoa(daddr), type));
/* Fill in the basic Ethernet MAC header. */
eth = (struct ethhdr *) buff;
eth->h_proto = htons(type);
/* We don't ARP for the LOOPBACK device... */
if (dev->flags & IFF_LOOPBACK)
{
DPRINTF((DBG_DEV, "ETH: No header for loopback\n"));
memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
memset(eth->h_dest, 0, dev->addr_len);
return(dev->hard_header_len);
}
/* Check if we can use the MAC BROADCAST address. */
if (chk_addr(daddr) == IS_BROADCAST)
{
DPRINTF((DBG_DEV, "ETH: Using MAC Broadcast\n"));
memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
memcpy(eth->h_dest, dev->broadcast, dev->addr_len);
return(dev->hard_header_len);
}
/*
* We disable interrupts here to avoid a race if the ARP
* reply is too quick.
*/
cli();
memcpy(eth->h_source, &saddr, 4);
/* No. Ask ARP to resolve the Ethernet address. */
if (arp_find(eth->h_dest, daddr, dev, dev->pa_addr/* saddr */))
{
sti();
if(type!=ETH_P_IP)
printk("Erk: protocol %X got into an arp request state!\n",type);
return(-dev->hard_header_len);
}
else
{
memcpy(eth->h_source,dev->dev_addr,dev->addr_len); /* This was missing causing chaos if the
header built correctly! */
sti();
return(dev->hard_header_len);
}
}
/* Rebuild the Ethernet MAC header. */
int
eth_rebuild_header(void *buff, struct device *dev)
/*
* Rebuild the Ethernet MAC header.
*
* We've got a 'stuck' packet that failed to go out before. See if
* the arp is resolved and we can finally shift it.
*/
int eth_rebuild_header(void *buff, struct device *dev)
{
struct ethhdr *eth;
unsigned long src, dst;
DPRINTF((DBG_DEV, "ETH: Using MAC Broadcast\n"));
eth = (struct ethhdr *) buff;
src = *(unsigned long *) eth->h_source;
dst = *(unsigned long *) eth->h_dest;
DPRINTF((DBG_DEV, "ETH: RebuildHeader: SRC=%s ", in_ntoa(src)));
DPRINTF((DBG_DEV, "DST=%s\n", in_ntoa(dst)));
if(eth->h_proto!=htons(ETH_P_ARP)) /* This ntohs kind of helps a bit! */
if (arp_find(eth->h_dest, dst, dev, src)) return(1);
memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
return(0);
struct ethhdr *eth;
unsigned long src, dst;
DPRINTF((DBG_DEV, "ETH: Using MAC Broadcast\n"));
eth = (struct ethhdr *) buff;
src = *(unsigned long *) eth->h_source;
dst = *(unsigned long *) eth->h_dest;
DPRINTF((DBG_DEV, "ETH: RebuildHeader: SRC=%s ", in_ntoa(src)));
DPRINTF((DBG_DEV, "DST=%s\n", in_ntoa(dst)));
if(eth->h_proto!=htons(ETH_P_ARP)) /* This ntohs kind of helps a bit! */
if (arp_find(eth->h_dest, dst, dev, dev->pa_addr /* src */))
/* Still not known */
return(1);
memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
return(0);
}
/* Add an ARP entry for a host on this interface. */
void
eth_add_arp(unsigned long addr, struct sk_buff *skb, struct device *dev)
/*
* Add an ARP entry for a host on this interface.
*/
void eth_add_arp(unsigned long addr, struct sk_buff *skb, struct device *dev)
{
struct ethhdr *eth;
struct ethhdr *eth;
eth = (struct ethhdr *) (skb + 1);
arp_add(addr, eth->h_source, dev);
eth = (struct ethhdr *) (skb + 1);
arp_add(addr, eth->h_source, dev);
}
/* Determine the packet's protocol ID. */
unsigned short
eth_type_trans(struct sk_buff *skb, struct device *dev)
/*
* Determine the packet's protocol ID.
*
* Ethernet comes in two 'species' DIX (Digitial Intel Xerox) and IEE802.3
* needless to say they are different. Fortunately there is a way of telling
* them apart. All 'normal' modern DIX service ID's are >1536.
* All IEE802.3 frames have a length at this position and that cannot be
* >=1536. Note IEE802.3 frames have a second 802.2 header normally. We don't
* deal with this bit in the current kernel, but a user using SOCK_PACKET
* for 802.3 frames can do so.
*/
unsigned short eth_type_trans(struct sk_buff *skb, struct device *dev)
{
struct ethhdr *eth;
struct ethhdr *eth;
eth = (struct ethhdr *) (skb + 1);
eth = (struct ethhdr *) (skb + 1);
if(ntohs(eth->h_proto)<1536)
return(htons(ETH_P_802_3));
return(eth->h_proto);
if(ntohs(eth->h_proto)<1536)
return(htons(ETH_P_802_3));
return(eth->h_proto);
}
This diff is collapsed.
This diff is collapsed.
......@@ -21,8 +21,8 @@
#include <linux/ip.h>
#include "sockinet.h"
#include "sock.h" /* struct sock */
/* IP flags. */
#define IP_CE 0x8000 /* Flag: "Congestion" */
......@@ -69,7 +69,8 @@ extern int ip_build_header(struct sk_buff *skb,
unsigned long saddr,
unsigned long daddr,
struct device **dev, int type,
struct options *opt, int len);
struct options *opt, int len,
int tos,int ttl);
extern unsigned short ip_compute_csum(unsigned char * buff, int len);
extern int ip_rcv(struct sk_buff *skb, struct device *dev,
struct packet_type *pt);
......@@ -77,5 +78,6 @@ extern void ip_queue_xmit(struct sock *sk,
struct device *dev, struct sk_buff *skb,
int free);
extern void ip_retransmit(struct sock *sk, int all);
extern int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int optlen);
extern int ip_getsockopt(struct sock *sk, int level, int optname, char *optval, int *optlen);
#endif /* _IP_H */
......@@ -5,71 +5,77 @@
*
* Pseudo-driver for the loopback interface.
*
* Version: @(#)loopback.c 1.0.4b 08/16/93
* Version: @(#)loopback.c 1.28 20/12/93
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
* Donald Becker, <becker@super.org>
*
* This file should be in drivers/net, but our glorious leader
* has put it here, and who are we to argue with the Linus 8-)
*
* 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
* 2 of the License, or (at your option) any later version.
*/
#include <asm/system.h>
#include <asm/segment.h>
#include <asm/io.h>
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/tty.h>
#include <linux/types.h>
#include <linux/ptrace.h>
#include <linux/string.h>
#include <linux/socket.h>
#include <linux/errno.h>
#include <linux/fcntl.h>
#include <linux/in.h>
#include <linux/if_ether.h> /* For the statistics structure. */
#include <asm/system.h>
#include <asm/segment.h>
#include <asm/io.h>
#include "inet.h"
#include "dev.h"
#include "devinet.h"
#include "eth.h"
#include "ip.h"
#include "protocol.h"
#include "tcp.h"
#include "skbuff.h"
#include "sock.h"
#include "sockinet.h"
#include "arp.h"
static int
loopback_xmit(struct sk_buff *skb, struct device *dev)
static int loopback_xmit(struct sk_buff *skb, struct device *dev)
{
struct enet_statistics *stats = (struct enet_statistics *)dev->priv;
int done;
struct enet_statistics *stats = (struct enet_statistics *)dev->priv;
int done;
DPRINTF((DBG_LOOPB, "loopback_xmit(dev=%X, skb=%X)\n", dev, skb));
if (skb == NULL || dev == NULL) return(0);
DPRINTF((DBG_LOOPB, "loopback_xmit(dev=%X, skb=%X)\n", dev, skb));
if (skb == NULL || dev == NULL)
return(0);
cli();
if (dev->tbusy != 0) {
sti();
stats->tx_errors++;
return(1);
}
dev->tbusy = 1;
sti();
cli();
if (dev->tbusy != 0)
{
sti();
stats->tx_errors++;
return(1);
}
dev->tbusy = 1;
sti();
done = dev_rint((unsigned char *)(skb+1), skb->len, 0, dev);
if (skb->free) kfree_skb(skb, FREE_WRITE);
done = dev_rint((unsigned char *)(skb+1), skb->len, 0, dev);
if (skb->free)
kfree_skb(skb, FREE_WRITE);
while (done != 1) {
done = dev_rint(NULL, 0, 0, dev);
}
stats->tx_packets++;
while (done != 1)
{
done = dev_rint(NULL, 0, 0, dev);
}
stats->tx_packets++;
dev->tbusy = 0;
dev->tbusy = 0;
#if 1
__asm__("cmpl $0,_intr_count\n\t"
......@@ -86,52 +92,50 @@ loopback_xmit(struct sk_buff *skb, struct device *dev)
: "ax", "dx", "cx");
#endif
return(0);
return(0);
}
static struct enet_statistics *
get_stats(struct device *dev)
static struct enet_statistics *get_stats(struct device *dev)
{
return (struct enet_statistics *)dev->priv;
}
/* Initialize the rest of the LOOPBACK device. */
int
loopback_init(struct device *dev)
int loopback_init(struct device *dev)
{
dev->mtu = 2000; /* MTU */
dev->tbusy = 0;
dev->hard_start_xmit = loopback_xmit;
dev->open = NULL;
dev->mtu = 2000; /* MTU */
dev->tbusy = 0;
dev->hard_start_xmit = loopback_xmit;
dev->open = NULL;
#if 1
dev->hard_header = eth_header;
dev->add_arp = NULL;
dev->hard_header_len = ETH_HLEN; /* 14 */
dev->addr_len = ETH_ALEN; /* 6 */
dev->type = ARPHRD_ETHER; /* 0x0001 */
dev->type_trans = eth_type_trans;
dev->rebuild_header = eth_rebuild_header;
dev->hard_header = eth_header;
dev->add_arp = NULL;
dev->hard_header_len = ETH_HLEN; /* 14 */
dev->addr_len = ETH_ALEN; /* 6 */
dev->type = ARPHRD_ETHER; /* 0x0001 */
dev->type_trans = eth_type_trans;
dev->rebuild_header = eth_rebuild_header;
#else
dev->hard_header_length = 0;
dev->add_arp = NULL;
dev->addr_len = 0;
dev->type = 0; /* loopback_type (0) */
dev->hard_header = NULL;
dev->type_trans = NULL;
dev->rebuild_header = NULL;
dev->hard_header_length = 0;
dev->add_arp = NULL;
dev->addr_len = 0;
dev->type = 0; /* loopback_type (0) */
dev->hard_header = NULL;
dev->type_trans = NULL;
dev->rebuild_header = NULL;
#endif
dev->queue_xmit = dev_queue_xmit;
dev->queue_xmit = dev_queue_xmit;
/* New-style flags. */
dev->flags = IFF_LOOPBACK;
dev->family = AF_INET;
dev->pa_addr = in_aton("127.0.0.1");
dev->pa_brdaddr = in_aton("127.255.255.255");
dev->pa_mask = in_aton("255.0.0.0");
dev->pa_alen = sizeof(unsigned long);
dev->priv = kmalloc(sizeof(struct enet_statistics), GFP_KERNEL);
memset(dev->priv, 0, sizeof(struct enet_statistics));
dev->get_stats = get_stats;
dev->flags = IFF_LOOPBACK;
dev->family = AF_INET;
dev->pa_addr = in_aton("127.0.0.1");
dev->pa_brdaddr = in_aton("127.255.255.255");
dev->pa_mask = in_aton("255.0.0.0");
dev->pa_alen = sizeof(unsigned long);
dev->priv = kmalloc(sizeof(struct enet_statistics), GFP_KERNEL);
memset(dev->priv, 0, sizeof(struct enet_statistics));
dev->get_stats = get_stats;
return(0);
return(0);
};
This diff is collapsed.
......@@ -7,7 +7,7 @@
* PROC file system. It is mainly used for debugging and
* statistics.
*
* Version: @(#)proc.c 1.0.5 05/27/93
* Version: @(#)proc.c 1.28 20/12/93
*
* Authors: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
* Gerald J. Heim, <heim@peanuts.informatik.uni-tuebingen.de>
......@@ -18,10 +18,7 @@
* using hint flag for the netinfo.
* Pauline Middelink : Pidentd support
* Alan Cox : Make /proc safer.
*
* To Do:
* Put the creating userid in the proc/net/... files. This will
* allow us to write an RFC931 daemon for Linux
* Alan Cox : Final clean up.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
......@@ -37,13 +34,13 @@
#include <linux/in.h>
#include <linux/param.h>
#include "inet.h"
#include "dev.h"
#include "devinet.h"
#include "ip.h"
#include "protocol.h"
#include "tcp.h"
#include "udp.h"
#include "skbuff.h"
#include "sock.h"
#include "socket/skbuff.h"
#include "sockinet.h"
#include "raw.h"
/*
......@@ -53,81 +50,83 @@
* As in get_unix_netinfo, the buffer might be too small. If this
* happens, get__netinfo returns only part of the available infos.
*/
static int
get__netinfo(struct proto *pro, char *buffer, int format)
static int get__netinfo(struct proto *pro, char *buffer, int format)
{
struct sock **s_array;
struct sock *sp;
char *pos=buffer;
int i;
int timer_active;
unsigned long dest, src;
unsigned short destp, srcp;
s_array = pro->sock_array;
pos+=sprintf(pos, "sl local_address rem_address st tx_queue rx_queue tr tm->when uid\n");
struct sock **s_array;
struct sock *sp;
char *pos=buffer;
int i;
int timer_active;
unsigned long dest, src;
unsigned short destp, srcp;
s_array = pro->sock_array;
pos+=sprintf(pos, "sl local_address rem_address st tx_queue rx_queue tr tm->when uid\n");
/*
* This was very pretty but didn't work when a socket is destroyed at the wrong moment
* (eg a syn recv socket getting a reset), or a memory timer destroy. Instead of playing
* with timers we just concede defeat and cli().
*/
for(i = 0; i < SOCK_ARRAY_SIZE; i++) {
cli();
sp = s_array[i];
while(sp != NULL) {
dest = sp->daddr;
src = sp->saddr;
destp = sp->dummy_th.dest;
srcp = sp->dummy_th.source;
for(i = 0; i < SOCK_ARRAY_SIZE; i++)
{
cli();
sp = s_array[i];
while(sp != NULL)
{
dest = sp->daddr;
src = sp->saddr;
destp = sp->dummy_th.dest;
srcp = sp->dummy_th.source;
/* Since we are Little Endian we need to swap the bytes :-( */
destp = ntohs(destp);
srcp = ntohs(srcp);
timer_active = del_timer(&sp->timer);
if (!timer_active)
sp->timer.expires = 0;
pos+=sprintf(pos, "%2d: %08lX:%04X %08lX:%04X %02X %08lX:%08lX %02X:%08lX %08X %d\n",
i, src, srcp, dest, destp, sp->state,
format==0?sp->send_seq-sp->rcv_ack_seq:sp->rmem_alloc,
format==0?sp->acked_seq-sp->copied_seq:sp->wmem_alloc,
timer_active, sp->timer.expires, (unsigned) sp->retransmits,
SOCK_INODE(sp->socket)->i_uid);
if (timer_active)
add_timer(&sp->timer);
/* Is place in buffer too rare? then abort. */
if (pos > buffer+PAGE_SIZE-80) {
printk("oops, too many %s sockets for netinfo.\n",
/* Since we are Little Endian we need to swap the bytes :-( */
destp = ntohs(destp);
srcp = ntohs(srcp);
timer_active = del_timer(&sp->timer);
if (!timer_active)
sp->timer.expires = 0;
pos+=sprintf(pos, "%2d: %08lX:%04X %08lX:%04X %02X %08lX:%08lX %02X:%08lX %08X %d\n",
i, src, srcp, dest, destp, sp->state,
format==0?sp->send_seq-sp->rcv_ack_seq:sp->rmem_alloc,
format==0?sp->acked_seq-sp->copied_seq:sp->wmem_alloc,
timer_active, sp->timer.expires, (unsigned) sp->retransmits,
SOCK_INODE(sp->socket)->i_uid);
if (timer_active)
add_timer(&sp->timer);
/* Is place in buffer too rare? then abort. */
if (pos > buffer+PAGE_SIZE-80)
{
printk("oops, too many %s sockets for netinfo.\n",
pro->name);
return(strlen(buffer));
}
return(strlen(buffer));
}
/*
* All sockets with (port mod SOCK_ARRAY_SIZE) = i
* are kept in sock_array[i], so we must follow the
* 'next' link to get them all.
*/
sp = sp->next;
}
sti(); /* We only turn interrupts back on for a moment, but because the interrupt queues anything built up
/*
* All sockets with (port mod SOCK_ARRAY_SIZE) = i
* are kept in sock_array[i], so we must follow the
* 'next' link to get them all.
*/
sp = sp->next;
}
sti(); /* We only turn interrupts back on for a moment, but because the interrupt queues anything built up
before this will clear before we jump back and cli, so its not as bad as it looks */
}
return(strlen(buffer));
}
return(strlen(buffer));
}
int tcp_get_info(char *buffer)
{
return get__netinfo(&tcp_prot, buffer,0);
return get__netinfo(&tcp_prot, buffer,0);
}
int udp_get_info(char *buffer)
{
return get__netinfo(&udp_prot, buffer,1);
return get__netinfo(&udp_prot, buffer,1);
}
int raw_get_info(char *buffer)
{
return get__netinfo(&raw_prot, buffer,1);
return get__netinfo(&raw_prot, buffer,1);
}
......@@ -5,7 +5,7 @@
*
* INET protocol dispatch tables.
*
* Version: @(#)protocol.c 1.0.5 05/25/93
* Version: @(#)protocol.c 1.28 20/12/93
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
......@@ -14,7 +14,8 @@
* Alan Cox : Ahah! udp icmp errors don't work because
* udp_err is never called!
* Alan Cox : Added new fields for init and ready for
* proper fragmentation (_NO_ 4K limits!)
* proper fragmentation (_NO_ 4K limits!).
* Alan Cox : Final clean up.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
......@@ -30,132 +31,143 @@
#include <linux/socket.h>
#include <linux/in.h>
#include "inet.h"
#include "dev.h"
#include "devinet.h"
#include "ip.h"
#include "protocol.h"
#include "tcp.h"
#include "skbuff.h"
#include "sock.h"
#include "socket/skbuff.h"
#include "sockinet.h"
#include "icmp.h"
#include "udp.h"
static struct inet_protocol tcp_protocol = {
tcp_rcv, /* TCP handler */
NULL, /* No fragment handler (and won't be for a long time) */
tcp_err, /* TCP error control */
NULL, /* next */
IPPROTO_TCP, /* protocol ID */
0, /* copy */
NULL, /* data */
"TCP" /* name */
static struct inet_protocol tcp_protocol =
{
tcp_rcv, /* TCP handler */
NULL, /* No fragment handler (and won't be for a long time) */
tcp_err, /* TCP error control */
NULL, /* next */
IPPROTO_TCP, /* protocol ID */
0, /* copy */
NULL, /* data */
"TCP" /* name */
};
static struct inet_protocol udp_protocol = {
udp_rcv, /* UDP handler */
NULL, /* Will be UDP fraglist handler */
udp_err, /* UDP error control */
&tcp_protocol, /* next */
IPPROTO_UDP, /* protocol ID */
0, /* copy */
NULL, /* data */
"UDP" /* name */
static struct inet_protocol udp_protocol =
{
udp_rcv, /* UDP handler */
NULL, /* Will be UDP fraglist handler */
udp_err, /* UDP error control */
&tcp_protocol, /* next */
IPPROTO_UDP, /* protocol ID */
0, /* copy */
NULL, /* data */
"UDP" /* name */
};
static struct inet_protocol icmp_protocol = {
icmp_rcv, /* ICMP handler */
NULL, /* ICMP never fragments anyway */
NULL, /* ICMP error control */
&udp_protocol, /* next */
IPPROTO_ICMP, /* protocol ID */
0, /* copy */
NULL, /* data */
"ICMP" /* name */
static struct inet_protocol icmp_protocol =
{
icmp_rcv, /* ICMP handler */
NULL, /* ICMP never fragments anyway */
NULL, /* ICMP error control */
&udp_protocol, /* next */
IPPROTO_ICMP, /* protocol ID */
0, /* copy */
NULL, /* data */
"ICMP" /* name */
};
struct inet_protocol *inet_protocol_base = &icmp_protocol;
struct inet_protocol *inet_protos[MAX_INET_PROTOS] = {
NULL
struct inet_protocol *inet_protos[MAX_INET_PROTOS] =
{
NULL
};
struct inet_protocol *
inet_get_protocol(unsigned char prot)
struct inet_protocol *inet_get_protocol(unsigned char prot)
{
unsigned char hash;
struct inet_protocol *p;
DPRINTF((DBG_PROTO, "get_protocol (%d)\n ", prot));
hash = prot & (MAX_INET_PROTOS - 1);
for (p = inet_protos[hash] ; p != NULL; p=p->next) {
DPRINTF((DBG_PROTO, "trying protocol %d\n", p->protocol));
if (p->protocol == prot) return((struct inet_protocol *) p);
}
return(NULL);
unsigned char hash;
struct inet_protocol *p;
DPRINTF((DBG_PROTO, "get_protocol (%d)\n ", prot));
hash = prot & (MAX_INET_PROTOS - 1);
for (p = inet_protos[hash] ; p != NULL; p=p->next)
{
DPRINTF((DBG_PROTO, "trying protocol %d\n", p->protocol));
if (p->protocol == prot)
return((struct inet_protocol *) p);
}
return(NULL);
}
void
inet_add_protocol(struct inet_protocol *prot)
void inet_add_protocol(struct inet_protocol *prot)
{
unsigned char hash;
struct inet_protocol *p2;
hash = prot->protocol & (MAX_INET_PROTOS - 1);
prot ->next = inet_protos[hash];
inet_protos[hash] = prot;
prot->copy = 0;
/* Set the copy bit if we need to. */
p2 = (struct inet_protocol *) prot->next;
while(p2 != NULL) {
if (p2->protocol == prot->protocol) {
prot->copy = 1;
break;
}
p2 = (struct inet_protocol *) prot->next;
}
unsigned char hash;
struct inet_protocol *p2;
hash = prot->protocol & (MAX_INET_PROTOS - 1);
prot ->next = inet_protos[hash];
inet_protos[hash] = prot;
prot->copy = 0;
/* Set the copy bit if we need to. */
p2 = (struct inet_protocol *) prot->next;
while(p2 != NULL)
{
if (p2->protocol == prot->protocol)
{
prot->copy = 1;
break;
}
p2 = (struct inet_protocol *) prot->next;
}
}
int
inet_del_protocol(struct inet_protocol *prot)
int inet_del_protocol(struct inet_protocol *prot)
{
struct inet_protocol *p;
struct inet_protocol *lp = NULL;
unsigned char hash;
hash = prot->protocol & (MAX_INET_PROTOS - 1);
if (prot == inet_protos[hash]) {
inet_protos[hash] = (struct inet_protocol *) inet_protos[hash]->next;
return(0);
}
p = (struct inet_protocol *) inet_protos[hash];
while(p != NULL) {
/*
* We have to worry if the protocol being deleted is
* the last one on the list, then we may need to reset
* someones copied bit.
*/
if (p->next != NULL && p->next == prot) {
/*
* if we are the last one with this protocol and
* there is a previous one, reset its copy bit.
*/
if (p->copy == 0 && lp != NULL) lp->copy = 0;
p->next = prot->next;
return(0);
}
if (p->next != NULL && p->next->protocol == prot->protocol) {
lp = p;
struct inet_protocol *p;
struct inet_protocol *lp = NULL;
unsigned char hash;
hash = prot->protocol & (MAX_INET_PROTOS - 1);
if (prot == inet_protos[hash])
{
inet_protos[hash] = (struct inet_protocol *) inet_protos[hash]->next;
return(0);
}
p = (struct inet_protocol *) p->next;
}
return(-1);
p = (struct inet_protocol *) inet_protos[hash];
while(p != NULL)
{
/*
* We have to worry if the protocol being deleted is
* the last one on the list, then we may need to reset
* someones copied bit.
*/
if (p->next != NULL && p->next == prot)
{
/*
* if we are the last one with this protocol and
* there is a previous one, reset its copy bit.
*/
if (p->copy == 0 && lp != NULL)
lp->copy = 0;
p->next = prot->next;
return(0);
}
if (p->next != NULL && p->next->protocol == prot->protocol)
{
lp = p;
}
p = (struct inet_protocol *) p->next;
}
return(-1);
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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