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

Import 0.99.14n

parent 170720a2
VERSION = 0.99 VERSION = 0.99
PATCHLEVEL = 14 PATCHLEVEL = 14
ALPHA = m ALPHA = n
all: Version zImage all: Version zImage
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* This module exports the console io functions: * This module exports the console io functions:
* *
* 'long con_init(long)' * '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 update_screen(int new_console)'
* 'void blank_screen(void)' * 'void blank_screen(void)'
* 'void unblank_screen(void)' * 'void unblank_screen(void)'
...@@ -73,9 +73,10 @@ static char sel_buffer[SEL_BUFFER_SIZE] = { '\0' }; ...@@ -73,9 +73,10 @@ static char sel_buffer[SEL_BUFFER_SIZE] = { '\0' };
extern void vt_init(void); extern void vt_init(void);
extern void register_console(void (*proc)(const char *)); 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_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 char video_type; /* Type of display being used */
static unsigned long video_mem_base; /* Base of video memory */ static unsigned long video_mem_base; /* Base of video memory */
...@@ -215,29 +216,29 @@ static unsigned char * translations[] = { ...@@ -215,29 +216,29 @@ static unsigned char * translations[] = {
/* 8-bit Latin-1 mapped to the PC charater set: '\0' means non-printable */ /* 8-bit Latin-1 mapped to the PC charater set: '\0' means non-printable */
(unsigned char *) (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\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\376\0\0\0\0\0"
" !\"#$%&'()*+,-./0123456789:;<=>?" " !\"#$%&'()*+,-./0123456789:;<=>?"
"@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
"`abcdefghijklmnopqrstuvwxyz{|}~\0" "`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"
"\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" "\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\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" "\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 */ /* vt100 graphics */
(unsigned char *) (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\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\376\0\0\0\0\0"
" !\"#$%&'()*+,-./0123456789:;<=>?" " !\"#$%&'()*+,-./0123456789:;<=>?"
"@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^ " "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^ "
"\004\261\007\007\007\007\370\361\007\007\331\277\332\300\305\304" "\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" "\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"
"\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" "\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\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" "\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) ...@@ -498,12 +499,16 @@ static inline void bs(int currcons)
static inline void del(int currcons) static inline void del(int currcons)
{ {
#if 0
if (x) { if (x) {
if (!need_wrap) { /* this is not the right condition */
pos -= 2; pos -= 2;
x--; x--;
}
*(unsigned short *)pos = video_erase_char; *(unsigned short *)pos = video_erase_char;
need_wrap = 0; need_wrap = 0;
} }
#endif
} }
static void csi_J(int currcons, int vpar) static void csi_J(int currcons, int vpar)
...@@ -1547,6 +1552,7 @@ void update_screen(int new_console) ...@@ -1547,6 +1552,7 @@ void update_screen(int new_console)
set_origin(fg_console); set_origin(fg_console);
set_cursor(new_console); set_cursor(new_console);
set_leds(); set_leds();
compute_shiftstate();
lock = 0; lock = 0;
} }
......
This diff is collapsed.
...@@ -5,6 +5,7 @@ keycode 2 = one exclam ...@@ -5,6 +5,7 @@ keycode 2 = one exclam
alt keycode 2 = Meta_one alt keycode 2 = Meta_one
keycode 3 = two at at keycode 3 = two at at
control keycode 3 = nul control keycode 3 = nul
shift control keycode 3 = nul
alt keycode 3 = Meta_two alt keycode 3 = Meta_two
keycode 4 = three numbersign keycode 4 = three numbersign
control keycode 4 = Escape control keycode 4 = Escape
...@@ -30,6 +31,7 @@ keycode 11 = zero parenright braceright ...@@ -30,6 +31,7 @@ keycode 11 = zero parenright braceright
alt keycode 11 = Meta_zero alt keycode 11 = Meta_zero
keycode 12 = minus underscore backslash keycode 12 = minus underscore backslash
control keycode 12 = Control_underscore control keycode 12 = Control_underscore
shift control keycode 12 = Control_underscore
alt keycode 12 = Meta_minus alt keycode 12 = Meta_minus
keycode 13 = equal plus keycode 13 = equal plus
alt keycode 13 = Meta_equal alt keycode 13 = Meta_equal
...@@ -54,7 +56,7 @@ keycode 27 = bracketright braceright asciitilde ...@@ -54,7 +56,7 @@ keycode 27 = bracketright braceright asciitilde
control keycode 27 = Control_bracketright control keycode 27 = Control_bracketright
alt keycode 27 = Meta_bracketright alt keycode 27 = Meta_bracketright
keycode 28 = Return keycode 28 = Return
alt keycode 28 = 0x080d alt keycode 28 = Meta_Control_m
keycode 29 = Control keycode 29 = Control
keycode 30 = a keycode 30 = a
keycode 31 = s keycode 31 = s
...@@ -87,6 +89,7 @@ keycode 50 = m ...@@ -87,6 +89,7 @@ keycode 50 = m
keycode 51 = comma less keycode 51 = comma less
alt keycode 51 = Meta_comma alt keycode 51 = Meta_comma
keycode 52 = period greater keycode 52 = period greater
control keycode 52 = Compose
alt keycode 52 = Meta_period alt keycode 52 = Meta_period
keycode 53 = slash question keycode 53 = slash question
control keycode 53 = Delete control keycode 53 = Delete
...@@ -196,14 +199,14 @@ keycode 110 = Insert ...@@ -196,14 +199,14 @@ keycode 110 = Insert
keycode 111 = Remove keycode 111 = Remove
altgr control keycode 111 = Boot altgr control keycode 111 = Boot
control alt keycode 111 = Boot control alt keycode 111 = Boot
keycode 112 = keycode 112 = Macro
keycode 113 = keycode 113 = F13
keycode 114 = keycode 114 = F14
keycode 115 = keycode 115 = Help
keycode 116 = keycode 116 = Do
keycode 117 = keycode 117 = F17
keycode 118 = keycode 118 = KP_MinPlus
keycode 119 = keycode 119 = Pause
keycode 120 = keycode 120 =
keycode 121 = keycode 121 =
keycode 122 = keycode 122 =
...@@ -238,9 +241,81 @@ string Remove = "\033[3~" ...@@ -238,9 +241,81 @@ string Remove = "\033[3~"
string Select = "\033[4~" string Select = "\033[4~"
string Prior = "\033[5~" string Prior = "\033[5~"
string Next = "\033[6~" string Next = "\033[6~"
string Help = ""
string Do = ""
string Macro = "\033[M"
string Pause = "\033[P"
string F21 = "" string F21 = ""
string F22 = "" string F22 = ""
string F23 = "" string F23 = ""
string F24 = "" string F24 = ""
string F25 = "" string F25 = ""
string F26 = "" 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) ...@@ -586,57 +586,41 @@ void copy_to_cooked(struct tty_struct * tty)
if (c == __DISABLED_CHAR) if (c == __DISABLED_CHAR)
tty->lnext = 1; tty->lnext = 1;
if (L_CANON(tty) && !tty->lnext) { 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 = int seen_alnums =
(c == WERASE_CHAR(tty)) ? 0 : -1; (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) || while(!(EMPTY(&tty->secondary) ||
(c=LAST(&tty->secondary))==10 || (cc=LAST(&tty->secondary))==10 ||
((EOF_CHAR(tty) != __DISABLED_CHAR) && ((EOF_CHAR(tty) != __DISABLED_CHAR) &&
(c==EOF_CHAR(tty))))) { (cc==EOF_CHAR(tty))))) {
/* if killing just a word, kill all /* if killing just a word, kill all
non-alnum chars, then all alnum non-alnum chars, then all alnum
chars. */ chars. */
if (seen_alnums >= 0) { if (seen_alnums >= 0) {
if (isalnum(c)) if (isalnum(cc))
seen_alnums++; seen_alnums++;
else if (seen_alnums) else if (seen_alnums)
break; break;
} }
if (L_ECHO(tty)) { 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('\b', &tty->write_q);
put_tty_queue(' ', &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('\b',&tty->write_q);
put_tty_queue(' ',&tty->write_q);
put_tty_queue('\b',&tty->write_q);
} }
DEC(tty->secondary.head); DEC(tty->secondary.head);
if(c == ERASE_CHAR(tty))
break;
} }
continue; 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)) { if (c == LNEXT_CHAR(tty)) {
tty->lnext = 1; tty->lnext = 1;
if (L_ECHO(tty)) { if (L_ECHO(tty)) {
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
* kernel/chr_drv/vt.c * kernel/chr_drv/vt.c
* *
* Copyright (C) 1992 obz under the linux copyright * Copyright (C) 1992 obz under the linux copyright
* Dynamic diacritical handling - aeb@cwi.nl - Dec 1993
*/ */
#include <linux/types.h> #include <linux/types.h>
...@@ -19,6 +20,7 @@ ...@@ -19,6 +20,7 @@
#include <asm/segment.h> #include <asm/segment.h>
#include "vt_kern.h" #include "vt_kern.h"
#include "diacr.h"
/* /*
* Console (vt and kd) routines, as defined by USL SVR4 manual, and by * Console (vt and kd) routines, as defined by USL SVR4 manual, and by
...@@ -37,6 +39,7 @@ struct vt_struct vt_cons[NR_CONSOLES]; ...@@ -37,6 +39,7 @@ struct vt_struct vt_cons[NR_CONSOLES];
asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on); 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 change_console(unsigned int new_console);
extern void complete_change_console(unsigned int new_console); extern void complete_change_console(unsigned int new_console);
extern int vt_waitactive(void); extern int vt_waitactive(void);
...@@ -212,6 +215,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, ...@@ -212,6 +215,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
} else if (arg == K_XLATE) { } else if (arg == K_XLATE) {
clr_vc_kbd_flag(kbd, VC_RAW); clr_vc_kbd_flag(kbd, VC_RAW);
clr_vc_kbd_flag(kbd, VC_MEDIUMRAW); clr_vc_kbd_flag(kbd, VC_MEDIUMRAW);
compute_shiftstate();
} else if (arg == K_MEDIUMRAW) { } else if (arg == K_MEDIUMRAW) {
clr_vc_kbd_flag(kbd, VC_RAW); clr_vc_kbd_flag(kbd, VC_RAW);
set_vc_kbd_flag(kbd, VC_MEDIUMRAW); set_vc_kbd_flag(kbd, VC_MEDIUMRAW);
...@@ -278,10 +282,17 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, ...@@ -278,10 +282,17 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
i = verify_area(VERIFY_WRITE, (void *)a, sizeof(struct kbsentry)); i = verify_area(VERIFY_WRITE, (void *)a, sizeof(struct kbsentry));
if (i) if (i)
return 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; return -EINVAL;
q = a->kb_string; 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(*p, q++);
put_fs_byte(0, q); put_fs_byte(0, q);
return 0; return 0;
...@@ -301,7 +312,14 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, ...@@ -301,7 +312,14 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
return i; return i;
if ((i = get_fs_byte(&a->kb_func)) >= NR_FUNC) if ((i = get_fs_byte(&a->kb_func)) >= NR_FUNC)
return -EINVAL; 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++) for (p = a->kb_string; get_fs_byte(p); p++)
delta++; delta++;
first_free = func_table[NR_FUNC - 1] + first_free = func_table[NR_FUNC - 1] +
...@@ -317,6 +335,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, ...@@ -317,6 +335,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
func_table[i + 1], func_table[i + 1],
first_free - func_table[i + 1]); first_free - func_table[i + 1]);
for (k = i + 1; k < NR_FUNC; k++) for (k = i + 1; k < NR_FUNC; k++)
if (func_table[k]) /* just to be sure */
func_table[k] += delta; func_table[k] += delta;
} }
for (p = a->kb_string, q = func_table[i]; ; p++, q++) 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, ...@@ -325,6 +344,35 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
return 0; 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: case KDGETLED:
i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned char)); i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned char));
if (i) if (i)
......
...@@ -8,8 +8,8 @@ ...@@ -8,8 +8,8 @@
include CONFIG include CONFIG
NETDRV_OBJS := net.a(Space.o) net.a(auto_irq.o) net.a(net_init.o) NETDRV_OBJS := net.a(Space.o) net.a(auto_irq.o) net.a(net_init.o)
CFLAGS := $(CFLAGS) -I../../net/inet CFLAGS := $(CFLAGS) -I../../net/inet -I../../net/socket -I../../net
CPP := $(CPP) -I../../net/inet CPP := $(CPP) -I../../net/inet -I../../net/socket -I../../net
# The point of the makefile... # The point of the makefile...
all: net.a all: net.a
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
* Pauline Middelink : Slip driver fixes. * Pauline Middelink : Slip driver fixes.
* Alan Cox : Honours the old SL_COMPRESSED flag * Alan Cox : Honours the old SL_COMPRESSED flag
* Alan Cox : KISS AX.25 and AXUI IP support * Alan Cox : KISS AX.25 and AXUI IP support
* Michael Riepe : Automatic CSLIP recognition added
*/ */
#include <asm/segment.h> #include <asm/segment.h>
...@@ -39,9 +40,9 @@ ...@@ -39,9 +40,9 @@
#include <linux/tty.h> #include <linux/tty.h>
#include <linux/in.h> #include <linux/in.h>
#include "inet.h" #include "inet.h"
#include "dev.h" #include "devinet.h"
#ifdef CONFIG_AX25 #ifdef CONFIG_AX25
#include "ax25.h" #include "ax25/ax25.h"
#endif #endif
#include "eth.h" #include "eth.h"
#include "ip.h" #include "ip.h"
...@@ -135,10 +136,14 @@ sl_initialize(struct slip *sl, struct device *dev) ...@@ -135,10 +136,14 @@ sl_initialize(struct slip *sl, struct device *dev)
sl->sending = 0; sl->sending = 0;
sl->escape = 0; sl->escape = 0;
sl->flags = 0; sl->flags = 0;
#ifdef SL_ADAPTIVE
sl->mode = SL_MODE_ADAPTIVE; /* automatic CSLIP recognition */
#else
#ifdef SL_COMPRESSED #ifdef SL_COMPRESSED
sl->mode = SL_MODE_CSLIP; /* Default */ sl->mode = SL_MODE_CSLIP | SL_MODE_ADAPTIVE; /* Default */
#else #else
sl->mode = SL_MODE_SLIP; /* Default for non compressors */ sl->mode = SL_MODE_SLIP; /* Default for non compressors */
#endif
#endif #endif
sl->line = dev->base_addr; sl->line = dev->base_addr;
...@@ -351,8 +356,15 @@ sl_bump(struct slip *sl) ...@@ -351,8 +356,15 @@ sl_bump(struct slip *sl)
int count; int count;
count = sl->rcount; 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 ((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 */ /* make sure we've reserved enough space for uncompress to use */
save_flags(flags); save_flags(flags);
cli(); cli();
...@@ -374,6 +386,11 @@ sl_bump(struct slip *sl) ...@@ -374,6 +386,11 @@ sl_bump(struct slip *sl)
return; return;
} }
} else if (c >= SL_TYPE_UNCOMPRESSED_TCP) { } 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; sl->rbuff[0] &= 0x4f;
if (slhc_remember(sl->slcomp, sl->rbuff, count) <= 0) { if (slhc_remember(sl->slcomp, sl->rbuff, count) <= 0) {
sl->errors++; sl->errors++;
...@@ -485,6 +502,21 @@ sl_encaps(struct slip *sl, unsigned char *icp, int len) ...@@ -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. */ /* Encapsulate an IP datagram and kick it into a TTY queue. */
static int static int
...@@ -525,6 +557,7 @@ sl_xmit(struct sk_buff *skb, struct device *dev) ...@@ -525,6 +557,7 @@ sl_xmit(struct sk_buff *skb, struct device *dev)
} }
#endif #endif
sl_lock(sl); sl_lock(sl);
/* sl_hex_dump((unsigned char *)(skb+1),skb->len);*/
sl_encaps(sl, (unsigned char *) (skb + 1), skb->len); sl_encaps(sl, (unsigned char *) (skb + 1), skb->len);
if (skb->free) kfree_skb(skb, FREE_WRITE); if (skb->free) kfree_skb(skb, FREE_WRITE);
} }
......
...@@ -66,8 +66,9 @@ struct slip { ...@@ -66,8 +66,9 @@ struct slip {
#define SL_MODE_SLIP 0 #define SL_MODE_SLIP 0
#define SL_MODE_CSLIP 1 #define SL_MODE_CSLIP 1
#define SL_MODE_SLIP6 2 /* Matt Dillon's printable slip */ #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_AX25 4
#define SL_MODE_ADAPTIVE 8
int xdata,xbits; /* 6 bit slip controls */ int xdata,xbits; /* 6 bit slip controls */
}; };
......
...@@ -315,6 +315,7 @@ int sr_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigne ...@@ -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 */ /* Now mask and substitute our own volume and reuse the rest */
buffer[0] = 0; /* Clear reserved field */
buffer[21] = volctrl.channel0 & mask[21]; buffer[21] = volctrl.channel0 & mask[21];
buffer[23] = volctrl.channel1 & mask[23]; buffer[23] = volctrl.channel1 & mask[23];
......
...@@ -25,7 +25,7 @@ all: local.h sound.a ...@@ -25,7 +25,7 @@ all: local.h sound.a
/usr/include/sys/soundcard.h: /usr/include/sys/soundcard.h:
@echo "WARNING! Your /usr/include/sys/soundcard.h not found." @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>" @echo "just a line #include <linux/soundcard.h>"
sound.a: $(OBJS) sound.a: $(OBJS)
......
...@@ -682,7 +682,7 @@ sb_dsp_init (long mem_start, struct address_info *hw_config) ...@@ -682,7 +682,7 @@ sb_dsp_init (long mem_start, struct address_info *hw_config)
sb_mixer_init(major); sb_mixer_init(major);
#endif #endif
#ifndef EXCLUDE_YM8312 #ifndef EXCLUDE_YM3812
if (major > 3 || (major == 3 && minor > 0)) /* SB Pro2 or later */ if (major > 3 || (major == 3 && minor > 0)) /* SB Pro2 or later */
{ {
enable_opl3_mode (OPL3_LEFT, OPL3_RIGHT, OPL3_BOTH); 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, ...@@ -462,7 +462,7 @@ int ext2_new_block (struct super_block * sb, unsigned long goal,
EXT2_BLOCKS_PER_GROUP(sb)); EXT2_BLOCKS_PER_GROUP(sb));
if (j >= EXT2_BLOCKS_PER_GROUP(sb)) { if (j >= EXT2_BLOCKS_PER_GROUP(sb)) {
ext2_error (sb, "ext2_new_block", 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); unlock_super (sb);
return 0; return 0;
} }
...@@ -486,8 +486,8 @@ int ext2_new_block (struct super_block * sb, unsigned long goal, ...@@ -486,8 +486,8 @@ int ext2_new_block (struct super_block * sb, unsigned long goal,
tmp == gdp->bg_inode_bitmap || tmp == gdp->bg_inode_bitmap ||
in_range (tmp, gdp->bg_inode_table, sb->u.ext2_sb.s_itb_per_group))) in_range (tmp, gdp->bg_inode_table, sb->u.ext2_sb.s_itb_per_group)))
ext2_panic (sb, "ext2_new_block", ext2_panic (sb, "ext2_new_block",
"Allocating block in system zone\nblock = %u", "Allocating block in system zone\n"
tmp); "block = %u", tmp);
if (set_bit (j, bh->b_data)) { if (set_bit (j, bh->b_data)) {
ext2_warning (sb, "ext2_new_block", ext2_warning (sb, "ext2_new_block",
......
...@@ -410,7 +410,7 @@ struct inode * ext2_new_inode (const struct inode * dir, int mode) ...@@ -410,7 +410,7 @@ struct inode * ext2_new_inode (const struct inode * dir, int mode)
/* /*
* That failed: try linear search for a free inode * 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++) { for (j = 2; j < sb->u.ext2_sb.s_groups_count; j++) {
if (++i >= sb->u.ext2_sb.s_groups_count) if (++i >= sb->u.ext2_sb.s_groups_count)
i = 0; i = 0;
...@@ -443,8 +443,17 @@ struct inode * ext2_new_inode (const struct inode * dir, int mode) ...@@ -443,8 +443,17 @@ struct inode * ext2_new_inode (const struct inode * dir, int mode)
ll_rw_block (WRITE, 1, &bh); ll_rw_block (WRITE, 1, &bh);
wait_on_buffer (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; goto repeat;
}
j += i * EXT2_INODES_PER_GROUP(sb) + 1; j += i * EXT2_INODES_PER_GROUP(sb) + 1;
if (j < EXT2_FIRST_INO || j > es->s_inodes_count) { if (j < EXT2_FIRST_INO || j > es->s_inodes_count) {
ext2_error (sb, "ext2_new_inode", ext2_error (sb, "ext2_new_inode",
...@@ -467,9 +476,13 @@ struct inode * ext2_new_inode (const struct inode * dir, int mode) ...@@ -467,9 +476,13 @@ struct inode * ext2_new_inode (const struct inode * dir, int mode)
inode->i_nlink = 1; inode->i_nlink = 1;
inode->i_dev = sb->s_dev; inode->i_dev = sb->s_dev;
inode->i_uid = current->euid; 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; inode->i_gid = dir->i_gid;
else else if (dir->i_mode & S_ISGID) {
inode->i_gid = dir->i_gid;
if (S_ISDIR(mode))
mode |= S_ISGID;
} else
inode->i_gid = current->egid; inode->i_gid = current->egid;
inode->i_dirt = 1; inode->i_dirt = 1;
inode->i_ino = j; inode->i_ino = j;
......
...@@ -299,7 +299,7 @@ static struct buffer_head * block_getblk (struct inode * inode, ...@@ -299,7 +299,7 @@ static struct buffer_head * block_getblk (struct inode * inode,
} }
} }
if (!goal) if (!goal)
goal = bh->b_blocknr + 1; goal = bh->b_blocknr;
} }
tmp = ext2_alloc_block (inode, goal); tmp = ext2_alloc_block (inode, goal);
if (!tmp) { if (!tmp) {
......
...@@ -233,13 +233,15 @@ static int parse_options (char * options, unsigned long * sb_block, ...@@ -233,13 +233,15 @@ static int parse_options (char * options, unsigned long * sb_block,
return 0; return 0;
} }
} }
else if (!strcmp (this_char, "grpid")) else if (!strcmp (this_char, "grpid") ||
!strcmp (this_char, "bsdgroups"))
set_opt (*mount_options, GRPID); set_opt (*mount_options, GRPID);
else if (!strcmp (this_char, "nocheck")) { else if (!strcmp (this_char, "nocheck")) {
clear_opt (*mount_options, CHECK_NORMAL); clear_opt (*mount_options, CHECK_NORMAL);
clear_opt (*mount_options, CHECK_STRICT); 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); clear_opt (*mount_options, GRPID);
else if (!strcmp (this_char, "sb")) { else if (!strcmp (this_char, "sb")) {
if (!value || !*value) { if (!value || !*value) {
...@@ -271,7 +273,8 @@ static void ext2_setup_super (struct super_block * sb, ...@@ -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)) else if ((sb->u.ext2_sb.s_mount_state & EXT2_ERROR_FS))
printk ("EXT2-fs warning: mounting fs with errors, " printk ("EXT2-fs warning: mounting fs with errors, "
"running e2fsck is recommended\n"); "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, " printk ("EXT2-fs warning: maximal mount count reached, "
"running e2fsck is recommended\n"); "running e2fsck is recommended\n");
if (!(sb->s_flags & MS_RDONLY)) { if (!(sb->s_flags & MS_RDONLY)) {
...@@ -390,8 +393,8 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data, ...@@ -390,8 +393,8 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data,
unlock_super (sb); unlock_super (sb);
brelse (bh); brelse (bh);
if (!silent) if (!silent)
printk ("VFS: Can't find an ext2 filesystem on dev 0x%04x.\n", printk ("VFS: Can't find an ext2 filesystem on dev %d/%d.\n",
dev); MAJOR(dev), MINOR(dev));
return NULL; return NULL;
} }
sb->s_blocksize = EXT2_MIN_BLOCK_SIZE << es->s_log_block_size; 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, ...@@ -477,8 +480,8 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data,
unlock_super (sb); unlock_super (sb);
brelse (bh); brelse (bh);
if (!silent) if (!silent)
printk ("VFS: Can't find an ext2 filesystem on dev 0x%04x.\n", printk ("VFS: Can't find an ext2 filesystem on dev %d/%d.\n",
dev); MAJOR(dev), MINOR(dev));
return NULL; return NULL;
} }
if (sb->s_blocksize != bh->b_size) { if (sb->s_blocksize != bh->b_size) {
...@@ -522,7 +525,7 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data, ...@@ -522,7 +525,7 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data,
sb->s_dev = 0; sb->s_dev = 0;
unlock_super (sb); unlock_super (sb);
for (j = 0; j < i; j++) 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); brelse (bh);
printk ("EXT2-fs: unable to read group descriptors\n"); printk ("EXT2-fs: unable to read group descriptors\n");
return NULL; return NULL;
...@@ -532,7 +535,7 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data, ...@@ -532,7 +535,7 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data,
sb->s_dev = 0; sb->s_dev = 0;
unlock_super (sb); unlock_super (sb);
for (j = 0; j < i; j++) 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); brelse (bh);
printk ("EXT2-fs: group descriptors corrupted !\n"); printk ("EXT2-fs: group descriptors corrupted !\n");
return NULL; return NULL;
......
...@@ -46,6 +46,8 @@ static int trunc_direct (struct inode * inode) ...@@ -46,6 +46,8 @@ static int trunc_direct (struct inode * inode)
int i, tmp; int i, tmp;
unsigned long * p; unsigned long * p;
struct buffer_head * bh; struct buffer_head * bh;
unsigned long block_to_free = 0;
unsigned long free_count = 0;
int retry = 0; int retry = 0;
int blocks = inode->i_sb->s_blocksize / 512; int blocks = inode->i_sb->s_blocksize / 512;
#define DIRECT_BLOCK ((inode->i_size + inode->i_sb->s_blocksize - 1) / \ #define DIRECT_BLOCK ((inode->i_size + inode->i_sb->s_blocksize - 1) / \
...@@ -82,8 +84,20 @@ static int trunc_direct (struct inode * inode) ...@@ -82,8 +84,20 @@ static int trunc_direct (struct inode * inode)
bh->b_dirt = 1; bh->b_dirt = 1;
} }
brelse (bh); 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; return retry;
} }
...@@ -93,6 +107,8 @@ static int trunc_indirect (struct inode * inode, int offset, unsigned long * p) ...@@ -93,6 +107,8 @@ static int trunc_indirect (struct inode * inode, int offset, unsigned long * p)
struct buffer_head * bh; struct buffer_head * bh;
struct buffer_head * ind_bh; struct buffer_head * ind_bh;
unsigned long * ind; unsigned long * ind;
unsigned long block_to_free = 0;
unsigned long free_count = 0;
int retry = 0; int retry = 0;
int addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb); int addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb);
int blocks = inode->i_sb->s_blocksize / 512; int blocks = inode->i_sb->s_blocksize / 512;
...@@ -144,10 +160,22 @@ static int trunc_indirect (struct inode * inode, int offset, unsigned long * p) ...@@ -144,10 +160,22 @@ static int trunc_indirect (struct inode * inode, int offset, unsigned long * p)
bh->b_dirt = 1; bh->b_dirt = 1;
} }
brelse (bh); 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_blocks -= blocks;
inode->i_dirt = 1; 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; ind = (unsigned long *) ind_bh->b_data;
for (i = 0; i < addr_per_block; i++) for (i = 0; i < addr_per_block; i++)
if (*(ind++)) if (*(ind++))
......
...@@ -486,6 +486,7 @@ asmlinkage int sys_mount(char * dev_name, char * dir_name, char * type, ...@@ -486,6 +486,7 @@ asmlinkage int sys_mount(char * dev_name, char * dir_name, char * type,
return retval; return retval;
} }
} }
page = 0;
if ((new_flags & MS_MGC_MSK) == MS_MGC_VAL) { if ((new_flags & MS_MGC_MSK) == MS_MGC_VAL) {
flags = new_flags & ~MS_MGC_MSK; flags = new_flags & ~MS_MGC_MSK;
retval = copy_mount_options(data, &page); retval = copy_mount_options(data, &page);
......
...@@ -52,7 +52,7 @@ ...@@ -52,7 +52,7 @@
/* /*
* The second extended file system version * The second extended file system version
*/ */
#define EXT2FS_DATE "93/12/30" #define EXT2FS_DATE "94/01/05"
#define EXT2FS_VERSION "0.4b" #define EXT2FS_VERSION "0.4b"
/* /*
...@@ -289,7 +289,7 @@ struct ext2_super_block { ...@@ -289,7 +289,7 @@ struct ext2_super_block {
unsigned long s_mtime; /* Mount time */ unsigned long s_mtime; /* Mount time */
unsigned long s_wtime; /* Write time */ unsigned long s_wtime; /* Write time */
unsigned short s_mnt_count; /* Mount count */ 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_magic; /* Magic signature */
unsigned short s_state; /* File system state */ unsigned short s_state; /* File system state */
unsigned short s_errors; /* Behaviour when detecting errors */ unsigned short s_errors; /* Behaviour when detecting errors */
......
...@@ -59,6 +59,8 @@ struct options { ...@@ -59,6 +59,8 @@ struct options {
unsigned short handling; unsigned short handling;
unsigned short stream; unsigned short stream;
unsigned tcc; unsigned tcc;
int option_length;
void *option_data;
}; };
......
...@@ -184,4 +184,14 @@ struct kbsentry { ...@@ -184,4 +184,14 @@ struct kbsentry {
#define KDGKBSENT 0x4B48 /* gets one function key string entry */ #define KDGKBSENT 0x4B48 /* gets one function key string entry */
#define KDSKBSENT 0x4B49 /* sets 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 */ #endif /* _LINUX_KD_H */
...@@ -4,19 +4,6 @@ ...@@ -4,19 +4,6 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#define set_leds() mark_bh(KEYBOARD_BH) #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..) * kbd->xxx contains the VC-local things (flag settings etc..)
* The low 3 local flags are hardcoded to be the led setting.. * The low 3 local flags are hardcoded to be the led setting..
...@@ -52,26 +39,6 @@ extern struct kbd_struct kbd_table[]; ...@@ -52,26 +39,6 @@ extern struct kbd_struct kbd_table[];
extern unsigned long kbd_init(unsigned long); 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) extern inline int vc_kbd_flag(struct kbd_struct * kbd, int flag)
{ {
return ((kbd->flags >> flag) & 1); return ((kbd->flags >> flag) & 1);
...@@ -98,7 +65,7 @@ extern const int NR_TYPES; ...@@ -98,7 +65,7 @@ extern const int NR_TYPES;
extern const int max_vals[]; extern const int max_vals[];
extern unsigned short key_map[NR_KEYMAPS][NR_KEYS]; extern unsigned short key_map[NR_KEYMAPS][NR_KEYS];
#define NR_FUNC 32 #define NR_FUNC 36
#define FUNC_BUFSIZE 512 #define FUNC_BUFSIZE 512
extern char func_buf[FUNC_BUFSIZE]; extern char func_buf[FUNC_BUFSIZE];
extern char *func_table[NR_FUNC]; extern char *func_table[NR_FUNC];
...@@ -145,6 +112,10 @@ 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_SELECT K(KT_FN,23)
#define K_PGUP K(KT_FN,24) #define K_PGUP K(KT_FN,24)
#define K_PGDN K(KT_FN,25) #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_HOLE K(KT_SPEC,0)
#define K_ENTER K(KT_SPEC,1) #define K_ENTER K(KT_SPEC,1)
...@@ -160,6 +131,7 @@ extern char *func_table[NR_FUNC]; ...@@ -160,6 +131,7 @@ extern char *func_table[NR_FUNC];
#define K_SCROLLBACK K(KT_SPEC,11) #define K_SCROLLBACK K(KT_SPEC,11)
#define K_BOOT K(KT_SPEC,12) #define K_BOOT K(KT_SPEC,12)
#define K_CAPSON K(KT_SPEC,13) #define K_CAPSON K(KT_SPEC,13)
#define K_COMPOSE K(KT_SPEC,14)
#define K_P0 K(KT_PAD,0) #define K_P0 K(KT_PAD,0)
#define K_P1 K(KT_PAD,1) #define K_P1 K(KT_PAD,1)
...@@ -178,6 +150,7 @@ extern char *func_table[NR_FUNC]; ...@@ -178,6 +150,7 @@ extern char *func_table[NR_FUNC];
#define K_PENTER K(KT_PAD,14) /* key-pad enter */ #define K_PENTER K(KT_PAD,14) /* key-pad enter */
#define K_PCOMMA K(KT_PAD,15) /* key-pad comma: kludge... */ #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_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_DGRAVE K(KT_DEAD,0)
#define K_DACUTE K(KT_DEAD,1) #define K_DACUTE K(KT_DEAD,1)
...@@ -220,4 +193,5 @@ extern char *func_table[NR_FUNC]; ...@@ -220,4 +193,5 @@ extern char *func_table[NR_FUNC];
#define K_ALTLOCK K(KT_LOCK,3) #define K_ALTLOCK K(KT_LOCK,3)
#define K_ALTGRLOCK K(KT_LOCK,1) #define K_ALTGRLOCK K(KT_LOCK,1)
#define MAX_DIACR 256
#endif #endif
...@@ -30,10 +30,14 @@ struct linger { ...@@ -30,10 +30,14 @@ struct linger {
#define AF_UNSPEC 0 #define AF_UNSPEC 0
#define AF_UNIX 1 #define AF_UNIX 1
#define AF_INET 2 #define AF_INET 2
#define AF_AX25 3
#define AF_IPX 4
/* Protocol families, same as address families. */ /* Protocol families, same as address families. */
#define PF_UNIX AF_UNIX #define PF_UNIX AF_UNIX
#define PF_INET AF_INET #define PF_INET AF_INET
#define PF_AX25 AF_AX25
#define PF_IPX AF_IPX
/* Flags we can use with send/ and recv. */ /* Flags we can use with send/ and recv. */
#define MSG_OOB 1 #define MSG_OOB 1
...@@ -41,6 +45,10 @@ struct linger { ...@@ -41,6 +45,10 @@ struct linger {
/* Setsockoptions(2) level. */ /* Setsockoptions(2) level. */
#define SOL_SOCKET 1 #define SOL_SOCKET 1
#define SOL_IP 2
#define SOL_IPX 3
#define SOL_AX25 4
#define SOL_TCP 5
/* For setsockoptions(2) */ /* For setsockoptions(2) */
#define SO_DEBUG 1 #define SO_DEBUG 1
...@@ -56,6 +64,19 @@ struct linger { ...@@ -56,6 +64,19 @@ struct linger {
#define SO_NO_CHECK 11 #define SO_NO_CHECK 11
#define SO_PRIORITY 12 #define SO_PRIORITY 12
#define SO_LINGER 13 #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. */ /* The various priorities. */
#define SOPRI_INTERACTIVE 0 #define SOPRI_INTERACTIVE 0
......
...@@ -149,7 +149,9 @@ sys_get_kernel_syms(struct kernel_sym *table) ...@@ -149,7 +149,9 @@ sys_get_kernel_syms(struct kernel_sym *table)
if (table != NULL) { if (table != NULL) {
from = symbol_table; from = symbol_table;
to = 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 ; ) { for (i = symbol_table_size ; --i >= 0 ; ) {
sym.value = from->addr; sym.value = from->addr;
strncpy(sym.name, from->name, sizeof sym.name); strncpy(sym.name, from->name, sizeof sym.name);
......
...@@ -7,10 +7,17 @@ ...@@ -7,10 +7,17 @@
# #
# Note 2! The CFLAGS definition is now in the main makefile... # Note 2! The CFLAGS definition is now in the main makefile...
# only these two lines should need to be changed to remove inet sockets. SUBDIRS := unix socket
# (and the inet/tcpip.o in net.o)
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) SUBOBJS := $(foreach f,$(SUBDIRS),$f/$f.o)
......
...@@ -30,10 +30,10 @@ ...@@ -30,10 +30,10 @@
# include "inet/inet.h" # include "inet/inet.h"
#endif #endif
#ifdef CONFIG_IPX #ifdef CONFIG_IPX
#include "inet/ipxcall.h" #include "ipx/ipxcall.h"
#endif #endif
#ifdef CONFIG_AX25 #ifdef CONFIG_AX25
#include "inet/ax25call.h" #include "ax25/ax25call.h"
#endif #endif
struct ddi_proto protocols[] = { struct ddi_proto protocols[] = {
...@@ -53,43 +53,3 @@ 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 @@ ...@@ -4,9 +4,11 @@
* but it eventually might move to an upper directory of * but it eventually might move to an upper directory of
* the system. * 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> * Author: Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
*
* Unused pieces nobbled.
*/ */
#include <asm/segment.h> #include <asm/segment.h>
#include <asm/system.h> #include <asm/system.h>
...@@ -18,6 +20,9 @@ ...@@ -18,6 +20,9 @@
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/socket.h> #include <linux/socket.h>
#include <linux/ddi.h> #include <linux/ddi.h>
#include <linux/interrupt.h>
#include "socket/dev.h"
#undef DDI_DEBUG #undef DDI_DEBUG
...@@ -28,64 +33,32 @@ ...@@ -28,64 +33,32 @@
#endif #endif
extern struct ddi_device devices[]; /* device driver map */
extern struct ddi_proto protocols[]; /* network protocols */ 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 * This is the function that is called by a kernel routine during
* system startup. Its purpose is to walk trough the "devices" * system startup. Its purpose is to walk trough the "devices"
* table (defined above), and to call all moduled defined in it. * 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_proto *pro;
struct ddi_device *dev;
PRINTK (("DDI: Starting up!\n")); PRINTK (("DDI: Starting up!\n"));
/* First off, kick all configured protocols. */ /* First off, kick all configured protocols. */
pro = protocols; pro = protocols;
while (pro->name != NULL) { while (pro->name != NULL)
{
(*pro->init)(pro); (*pro->init)(pro);
pro++; pro++;
} }
/* Done. Now kick all configured device drivers. */ dev_init();
dev = devices; /* Initialize the "Buffer Head" pointers. */
while (dev->title != NULL) { bh_base[INET_BH].routine = inet_bh;
(*dev->init)(dev);
dev++;
}
/* We're all done... */ /* We're all done... */
} }
...@@ -7,6 +7,9 @@ ...@@ -7,6 +7,9 @@
# #
# Note 2! The CFLAGS definition is now in the main makefile... # Note 2! The CFLAGS definition is now in the main makefile...
CFLAGS := $(CFLAGS) -I../socket -I..
CPP := $(CPP) -I../socket -I..
.c.o: .c.o:
$(CC) $(CFLAGS) -c -o $*.o $< $(CC) $(CFLAGS) -c -o $*.o $<
.s.o: .s.o:
...@@ -15,10 +18,8 @@ ...@@ -15,10 +18,8 @@
$(CC) $(CFLAGS) -S -o $*.s $< $(CC) $(CFLAGS) -S -o $*.s $<
OBJS = sock.o utils.o route.o proc.o timer.o protocol.o loopback.o \ OBJS = sockinet.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 \ eth.o packet.o arp.o devinet.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
ifdef CONFIG_INET 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: NOTE:
Drivers for this stack set must be using alloc_skb() not just Drivers for this stack set must be using alloc_skb() not just
......
This diff is collapsed.
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* *
* Definitions for the ARP protocol module. * 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> * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
...@@ -26,29 +26,31 @@ ...@@ -26,29 +26,31 @@
#define ARP_QUEUE_MAGIC 0x0432447A /* magic # for queues */ #define ARP_QUEUE_MAGIC 0x0432447A /* magic # for queues */
/* This structure defines the ARP mapping cache. */ /*
struct arp_table { * This structure defines the ARP mapping cache.
*/
struct arp_table
{
struct arp_table *next; struct arp_table *next;
volatile unsigned long last_used; volatile unsigned long last_used;
unsigned int flags; unsigned int flags;
#if 1
unsigned long ip; 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 ha[MAX_ADDR_LEN];
unsigned char hlen; unsigned char hlen;
unsigned char htype; 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 struct sk_buff *arp_q;
extern void arp_destroy(unsigned long paddr); 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, extern int arp_rcv(struct sk_buff *skb, struct device *dev,
struct packet_type *pt); struct packet_type *pt);
extern int arp_find(unsigned char *haddr, unsigned long paddr, 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) ...@@ -790,7 +790,6 @@ static inline int bad_mask(unsigned long mask, unsigned long addr)
return 0; return 0;
} }
/* Perform the SIOCxIFxxx calls. */ /* Perform the SIOCxIFxxx calls. */
static int static int
dev_ifsioc(void *arg, unsigned int getset) 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 @@ ...@@ -5,24 +5,27 @@
* *
* Ethernet-type device handling. * 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> * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
* Mark Evans, <evansmp@uhura.aston.ac.uk> * Mark Evans, <evansmp@uhura.aston.ac.uk>
* *
* Fixes: * Fixes:
* Mr Linux : Arp problems * Mr Linux : Arp problems.
* Alan Cox : Generic queue tidyup (very tiny here) * Alan Cox : Generic queue tidyup (very tiny here).
* Alan Cox : eth_header ntohs should be htons * Alan Cox : eth_header ntohs should be htons.
* Alan Cox : eth_rebuild_header missing an htons and * Alan Cox : eth_rebuild_header missing an htons and
* minor other things. * 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 * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version * as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version. * 2 of the License, or (at your option) any later version.
*/ */
#include <asm/segment.h> #include <asm/segment.h>
#include <asm/system.h> #include <asm/system.h>
#include <linux/types.h> #include <linux/types.h>
...@@ -33,18 +36,19 @@ ...@@ -33,18 +36,19 @@
#include <linux/socket.h> #include <linux/socket.h>
#include <linux/in.h> #include <linux/in.h>
#include "inet.h" #include "inet.h"
#include "dev.h" #include "devinet.h"
#include "eth.h" #include "eth.h"
#include "ip.h" #include "ip.h"
#include "route.h" #include "route.h"
#include "protocol.h" #include "protocol.h"
#include "tcp.h" #include "tcp.h"
#include "skbuff.h" #include "skbuff.h"
#include "sock.h" #include "sockinet.h"
#include <linux/errno.h> #include <linux/errno.h>
#include "arp.h" #include "arp.h"
#ifdef ETH_DEBUG
/* Display an Ethernet address in readable format. */ /* Display an Ethernet address in readable format. */
char *eth_print(unsigned char *ptr) char *eth_print(unsigned char *ptr)
{ {
...@@ -57,32 +61,16 @@ char *eth_print(unsigned char *ptr) ...@@ -57,32 +61,16 @@ char *eth_print(unsigned char *ptr)
); );
return(buff); 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. */ #ifdef ETH_DEBUG
void
eth_dump(struct ethhdr *eth) /*
* Display the contents of the Ethernet MAC header.
*/
void eth_dump(struct ethhdr *eth)
{ {
if (inet_debug != DBG_ETH) return; if (inet_debug != DBG_ETH) return;
...@@ -91,10 +79,17 @@ eth_dump(struct ethhdr *eth) ...@@ -91,10 +79,17 @@ eth_dump(struct ethhdr *eth)
printk("TYPE = %04X\n", ntohs(eth->h_proto)); printk("TYPE = %04X\n", ntohs(eth->h_proto));
} }
#endif
/*
* Create the Ethernet MAC header.
*
* ARP might prevent this from working all in one go. See also
* the rebuild header function.
*/
/* Create the Ethernet MAC header. */ int eth_header(unsigned char *buff, struct device *dev, unsigned short type,
int
eth_header(unsigned char *buff, struct device *dev, unsigned short type,
unsigned long daddr, unsigned long saddr, unsigned len) unsigned long daddr, unsigned long saddr, unsigned len)
{ {
struct ethhdr *eth; struct ethhdr *eth;
...@@ -107,7 +102,8 @@ eth_header(unsigned char *buff, struct device *dev, unsigned short type, ...@@ -107,7 +102,8 @@ eth_header(unsigned char *buff, struct device *dev, unsigned short type,
eth->h_proto = htons(type); eth->h_proto = htons(type);
/* We don't ARP for the LOOPBACK device... */ /* We don't ARP for the LOOPBACK device... */
if (dev->flags & IFF_LOOPBACK) { if (dev->flags & IFF_LOOPBACK)
{
DPRINTF((DBG_DEV, "ETH: No header for loopback\n")); DPRINTF((DBG_DEV, "ETH: No header for loopback\n"));
memcpy(eth->h_source, dev->dev_addr, dev->addr_len); memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
memset(eth->h_dest, 0, dev->addr_len); memset(eth->h_dest, 0, dev->addr_len);
...@@ -115,16 +111,21 @@ eth_header(unsigned char *buff, struct device *dev, unsigned short type, ...@@ -115,16 +111,21 @@ eth_header(unsigned char *buff, struct device *dev, unsigned short type,
} }
/* Check if we can use the MAC BROADCAST address. */ /* Check if we can use the MAC BROADCAST address. */
if (chk_addr(daddr) == IS_BROADCAST) { if (chk_addr(daddr) == IS_BROADCAST)
{
DPRINTF((DBG_DEV, "ETH: Using MAC Broadcast\n")); DPRINTF((DBG_DEV, "ETH: Using MAC Broadcast\n"));
memcpy(eth->h_source, dev->dev_addr, dev->addr_len); memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
memcpy(eth->h_dest, dev->broadcast, dev->addr_len); memcpy(eth->h_dest, dev->broadcast, dev->addr_len);
return(dev->hard_header_len); return(dev->hard_header_len);
} }
/*
* We disable interrupts here to avoid a race if the ARP
* reply is too quick.
*/
cli(); cli();
memcpy(eth->h_source, &saddr, 4); memcpy(eth->h_source, &saddr, 4);
/* No. Ask ARP to resolve the Ethernet address. */ /* No. Ask ARP to resolve the Ethernet address. */
if (arp_find(eth->h_dest, daddr, dev, saddr)) if (arp_find(eth->h_dest, daddr, dev, dev->pa_addr/* saddr */))
{ {
sti(); sti();
if(type!=ETH_P_IP) if(type!=ETH_P_IP)
...@@ -141,9 +142,14 @@ eth_header(unsigned char *buff, struct device *dev, unsigned short type, ...@@ -141,9 +142,14 @@ eth_header(unsigned char *buff, struct device *dev, unsigned short type,
} }
/* Rebuild the Ethernet MAC header. */ /*
int * Rebuild the Ethernet MAC header.
eth_rebuild_header(void *buff, struct device *dev) *
* 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; struct ethhdr *eth;
unsigned long src, dst; unsigned long src, dst;
...@@ -155,15 +161,19 @@ eth_rebuild_header(void *buff, struct device *dev) ...@@ -155,15 +161,19 @@ eth_rebuild_header(void *buff, struct device *dev)
DPRINTF((DBG_DEV, "ETH: RebuildHeader: SRC=%s ", in_ntoa(src))); DPRINTF((DBG_DEV, "ETH: RebuildHeader: SRC=%s ", in_ntoa(src)));
DPRINTF((DBG_DEV, "DST=%s\n", in_ntoa(dst))); 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(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); 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); memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
return(0); return(0);
} }
/* Add an ARP entry for a host on this interface. */ /*
void * Add an ARP entry for a host on this interface.
eth_add_arp(unsigned long addr, struct sk_buff *skb, struct device *dev) */
void eth_add_arp(unsigned long addr, struct sk_buff *skb, struct device *dev)
{ {
struct ethhdr *eth; struct ethhdr *eth;
...@@ -172,9 +182,19 @@ eth_add_arp(unsigned long addr, struct sk_buff *skb, struct device *dev) ...@@ -172,9 +182,19 @@ eth_add_arp(unsigned long addr, struct sk_buff *skb, struct device *dev)
} }
/* Determine the packet's protocol ID. */ /*
unsigned short * Determine the packet's protocol ID.
eth_type_trans(struct sk_buff *skb, struct device *dev) *
* 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;
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* *
* Internet Control Message Protocol (ICMP) * Internet Control Message Protocol (ICMP)
* *
* Version: @(#)icmp.c 1.0.11 06/02/93 * Version: @(#)icmp.c 1.28 20/12/93
* *
* Authors: Ross Biro, <bir7@leland.Stanford.Edu> * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
* Fixes: * Fixes:
* Alan Cox : Generic queue usage. * Alan Cox : Generic queue usage.
* Gerhard Koerting: ICMP addressing corrected * Gerhard Koerting: ICMP addressing corrected
* Tegge : Subnet problems
* *
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
...@@ -21,6 +22,7 @@ ...@@ -21,6 +22,7 @@
* as published by the Free Software Foundation; either version * as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version. * 2 of the License, or (at your option) any later version.
*/ */
#include <linux/types.h> #include <linux/types.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -28,14 +30,14 @@ ...@@ -28,14 +30,14 @@
#include <linux/socket.h> #include <linux/socket.h>
#include <linux/in.h> #include <linux/in.h>
#include "inet.h" #include "inet.h"
#include "dev.h" #include "devinet.h"
#include "ip.h" #include "ip.h"
#include "route.h" #include "route.h"
#include "protocol.h" #include "protocol.h"
#include "icmp.h" #include "icmp.h"
#include "tcp.h" #include "tcp.h"
#include "skbuff.h" #include "skbuff.h"
#include "sock.h" #include "sockinet.h"
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/timer.h> #include <linux/timer.h>
#include <asm/system.h> #include <asm/system.h>
...@@ -63,21 +65,30 @@ struct icmp_err icmp_err_convert[] = { ...@@ -63,21 +65,30 @@ struct icmp_err icmp_err_convert[] = {
}; };
#ifdef ICMP_DEBUG
/* Display the contents of an ICMP header. */ /* Display the contents of an ICMP header. */
static void static void
print_icmp(struct icmphdr *icmph) print_icmp(struct icmphdr *icmph)
{ {
if (inet_debug != DBG_ICMP) return; if (inet_debug != DBG_ICMP)
return;
printk("ICMP: type = %d, code = %d, checksum = %X\n", printk("ICMP: type = %d, code = %d, checksum = %X\n",
icmph->type, icmph->code, icmph->checksum); icmph->type, icmph->code, icmph->checksum);
printk(" gateway = %s\n", in_ntoa(icmph->un.gateway)); printk(" gateway = %s\n", in_ntoa(icmph->un.gateway));
} }
#endif
/* Send an ICMP message. */ /*
void * Send an ICMP message.
icmp_send(struct sk_buff *skb_in, int type, int code, struct device *dev) *
* ICMP is the control message protocol for error reporting in IP.
* A good document to start with for this stuff is RFC 791.
*/
void icmp_send(struct sk_buff *skb_in, int type, int code, struct device *dev)
{ {
struct sk_buff *skb; struct sk_buff *skb;
struct iphdr *iph; struct iphdr *iph;
...@@ -94,12 +105,13 @@ icmp_send(struct sk_buff *skb_in, int type, int code, struct device *dev) ...@@ -94,12 +105,13 @@ icmp_send(struct sk_buff *skb_in, int type, int code, struct device *dev)
sizeof(struct iphdr) + 8; /* amount of header to return */ sizeof(struct iphdr) + 8; /* amount of header to return */
skb = (struct sk_buff *) alloc_skb(len, GFP_ATOMIC); skb = (struct sk_buff *) alloc_skb(len, GFP_ATOMIC);
/* We just forget about failed ICMP messages. ICMP is unreliable anyway and
things will sort out in time */
if (skb == NULL) if (skb == NULL)
return; return;
skb->sk = NULL; skb->sk = NULL;
skb->mem_addr = skb;
skb->mem_len = len;
len -= sizeof(struct sk_buff); len -= sizeof(struct sk_buff);
/* Find the IP header. */ /* Find the IP header. */
...@@ -108,8 +120,9 @@ icmp_send(struct sk_buff *skb_in, int type, int code, struct device *dev) ...@@ -108,8 +120,9 @@ icmp_send(struct sk_buff *skb_in, int type, int code, struct device *dev)
/* Build Layer 2-3 headers for message back to source. */ /* Build Layer 2-3 headers for message back to source. */
offset = ip_build_header(skb, dev->pa_addr, iph->saddr, offset = ip_build_header(skb, dev->pa_addr, iph->saddr,
&dev, IPPROTO_ICMP, NULL, len); &dev, IPPROTO_ICMP, NULL, len, 25, IPTOS_RELIABILITY);
if (offset < 0) { if (offset < 0)
{
skb->sk = NULL; skb->sk = NULL;
kfree_skb(skb, FREE_READ); kfree_skb(skb, FREE_READ);
return; return;
...@@ -127,17 +140,20 @@ icmp_send(struct sk_buff *skb_in, int type, int code, struct device *dev) ...@@ -127,17 +140,20 @@ icmp_send(struct sk_buff *skb_in, int type, int code, struct device *dev)
icmph->checksum = ip_compute_csum((unsigned char *)icmph, icmph->checksum = ip_compute_csum((unsigned char *)icmph,
sizeof(struct icmphdr) + sizeof(struct iphdr) + 8); sizeof(struct icmphdr) + sizeof(struct iphdr) + 8);
#ifdef ICMP_DEBUG
DPRINTF((DBG_ICMP, ">>\n")); DPRINTF((DBG_ICMP, ">>\n"));
print_icmp(icmph); print_icmp(icmph);
#endif
/* Send it and free it. */ /* Send it and free it. */
ip_queue_xmit(NULL, dev, skb, 1); ip_queue_xmit(NULL, dev, skb, 1);
} }
/* Handle ICMP_UNREACH and ICMP_QUENCH. */ /*
static void * Handle ICMP_UNREACH and ICMP_QUENCH.
icmp_unreach(struct icmphdr *icmph, struct sk_buff *skb) */
static void icmp_unreach(struct icmphdr *icmph, struct sk_buff *skb)
{ {
struct inet_protocol *ipprot; struct inet_protocol *ipprot;
struct iphdr *iph; struct iphdr *iph;
...@@ -146,7 +162,8 @@ icmp_unreach(struct icmphdr *icmph, struct sk_buff *skb) ...@@ -146,7 +162,8 @@ icmp_unreach(struct icmphdr *icmph, struct sk_buff *skb)
err = (icmph->type << 8) | icmph->code; err = (icmph->type << 8) | icmph->code;
iph = (struct iphdr *) (icmph + 1); iph = (struct iphdr *) (icmph + 1);
switch(icmph->code & 7) { switch(icmph->code & 7)
{
case ICMP_NET_UNREACH: case ICMP_NET_UNREACH:
DPRINTF((DBG_ICMP, "ICMP: %s: network unreachable.\n", DPRINTF((DBG_ICMP, "ICMP: %s: network unreachable.\n",
in_ntoa(iph->daddr))); in_ntoa(iph->daddr)));
...@@ -181,13 +198,15 @@ icmp_unreach(struct icmphdr *icmph, struct sk_buff *skb) ...@@ -181,13 +198,15 @@ icmp_unreach(struct icmphdr *icmph, struct sk_buff *skb)
/* This can change while we are doing it. */ /* This can change while we are doing it. */
ipprot = (struct inet_protocol *) inet_protos[hash]; ipprot = (struct inet_protocol *) inet_protos[hash];
while(ipprot != NULL) { while(ipprot != NULL)
{
struct inet_protocol *nextip; struct inet_protocol *nextip;
nextip = (struct inet_protocol *) ipprot->next; nextip = (struct inet_protocol *) ipprot->next;
/* Pass it off to everyone who wants it. */ /* Pass it off to everyone who wants it. */
if (iph->protocol == ipprot->protocol && ipprot->err_handler) { if (iph->protocol == ipprot->protocol && ipprot->err_handler)
{
ipprot->err_handler(err, (unsigned char *)(icmph + 1), ipprot->err_handler(err, (unsigned char *)(icmph + 1),
iph->daddr, iph->saddr, ipprot); iph->daddr, iph->saddr, ipprot);
} }
...@@ -199,16 +218,19 @@ icmp_unreach(struct icmphdr *icmph, struct sk_buff *skb) ...@@ -199,16 +218,19 @@ icmp_unreach(struct icmphdr *icmph, struct sk_buff *skb)
} }
/* Handle ICMP_REDIRECT. */ /*
static void * Handle ICMP_REDIRECT.
icmp_redirect(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev) */
static void icmp_redirect(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev)
{ {
struct iphdr *iph; struct iphdr *iph;
unsigned long ip; unsigned long ip;
iph = (struct iphdr *) (icmph + 1); iph = (struct iphdr *) (icmph + 1);
ip = iph->daddr; ip = iph->daddr;
switch(icmph->code & 7) { switch(icmph->code & 7)
{
case ICMP_REDIR_NET: case ICMP_REDIR_NET:
rt_add((RTF_DYNAMIC | RTF_MODIFIED | RTF_GATEWAY), rt_add((RTF_DYNAMIC | RTF_MODIFIED | RTF_GATEWAY),
ip, 0, icmph->un.gateway, dev); ip, 0, icmph->un.gateway, dev);
...@@ -232,8 +254,7 @@ icmp_redirect(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev) ...@@ -232,8 +254,7 @@ icmp_redirect(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev)
/* Handle ICMP_ECHO ("ping") requests. */ /* Handle ICMP_ECHO ("ping") requests. */
static void static void icmp_echo(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev,
icmp_echo(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev,
unsigned long saddr, unsigned long daddr, int len, unsigned long saddr, unsigned long daddr, int len,
struct options *opt) struct options *opt)
{ {
...@@ -243,20 +264,20 @@ icmp_echo(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev, ...@@ -243,20 +264,20 @@ icmp_echo(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev,
size = sizeof(struct sk_buff) + dev->hard_header_len + 64 + len; size = sizeof(struct sk_buff) + dev->hard_header_len + 64 + len;
skb2 = alloc_skb(size, GFP_ATOMIC); skb2 = alloc_skb(size, GFP_ATOMIC);
if (skb2 == NULL) { if (skb2 == NULL)
{
skb->sk = NULL; skb->sk = NULL;
kfree_skb(skb, FREE_READ); kfree_skb(skb, FREE_READ);
return; return;
} }
skb2->sk = NULL; skb2->sk = NULL;
skb2->mem_addr = skb2;
skb2->mem_len = size;
skb2->free = 1; skb2->free = 1;
/* Build Layer 2-3 headers for message back to source */ /* Build Layer 2-3 headers for message back to source */
offset = ip_build_header(skb2, daddr, saddr, &dev, offset = ip_build_header(skb2, daddr, saddr, &dev,
IPPROTO_ICMP, opt, len); IPPROTO_ICMP, opt, len, 255, IPTOS_RELIABILITY);
if (offset < 0) { if (offset < 0)
{
printk("ICMP: Could not build IP Header for ICMP ECHO Response\n"); printk("ICMP: Could not build IP Header for ICMP ECHO Response\n");
kfree_skb(skb2,FREE_WRITE); kfree_skb(skb2,FREE_WRITE);
skb->sk = NULL; skb->sk = NULL;
...@@ -283,9 +304,11 @@ icmp_echo(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev, ...@@ -283,9 +304,11 @@ icmp_echo(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev,
} }
/* Handle the ICMP INFORMATION REQUEST. */ /*
static void * Handle the ICMP INFORMATION REQUEST.
icmp_info(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev, */
static void icmp_info(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev,
unsigned long saddr, unsigned long daddr, int len, unsigned long saddr, unsigned long daddr, int len,
struct options *opt) struct options *opt)
{ {
...@@ -295,9 +318,11 @@ icmp_info(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev, ...@@ -295,9 +318,11 @@ icmp_info(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev,
} }
/* Handle ICMP_ADRESS_MASK requests. */ /*
static void * Handle ICMP_ADRESS_MASK requests.
icmp_address(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev, */
static void icmp_address(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev,
unsigned long saddr, unsigned long daddr, int len, unsigned long saddr, unsigned long daddr, int len,
struct options *opt) struct options *opt)
{ {
...@@ -307,20 +332,20 @@ icmp_address(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev, ...@@ -307,20 +332,20 @@ icmp_address(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev,
size = sizeof(struct sk_buff) + dev->hard_header_len + 64 + len; size = sizeof(struct sk_buff) + dev->hard_header_len + 64 + len;
skb2 = alloc_skb(size, GFP_ATOMIC); skb2 = alloc_skb(size, GFP_ATOMIC);
if (skb2 == NULL) { if (skb2 == NULL)
{
skb->sk = NULL; skb->sk = NULL;
kfree_skb(skb, FREE_READ); kfree_skb(skb, FREE_READ);
return; return;
} }
skb2->sk = NULL; skb2->sk = NULL;
skb2->mem_addr = skb2;
skb2->mem_len = size;
skb2->free = 1; skb2->free = 1;
/* Build Layer 2-3 headers for message back to source */ /* Build Layer 2-3 headers for message back to source */
offset = ip_build_header(skb2, daddr, saddr, &dev, offset = ip_build_header(skb2, daddr, saddr, &dev,
IPPROTO_ICMP, opt, len); IPPROTO_ICMP, opt, len, 255, IPTOS_RELIABILITY);
if (offset < 0) { if (offset < 0)
{
printk("ICMP: Could not build IP Header for ICMP ADDRESS Response\n"); printk("ICMP: Could not build IP Header for ICMP ADDRESS Response\n");
kfree_skb(skb2,FREE_WRITE); kfree_skb(skb2,FREE_WRITE);
skb->sk = NULL; skb->sk = NULL;
...@@ -350,9 +375,11 @@ icmp_address(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev, ...@@ -350,9 +375,11 @@ icmp_address(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev,
} }
/* Deal with incoming ICMP packets. */ /*
int * Deal with incoming ICMP packets.
icmp_rcv(struct sk_buff *skb1, struct device *dev, struct options *opt, */
int icmp_rcv(struct sk_buff *skb1, struct device *dev, struct options *opt,
unsigned long daddr, unsigned short len, unsigned long daddr, unsigned short len,
unsigned long saddr, int redo, struct inet_protocol *protocol) unsigned long saddr, int redo, struct inet_protocol *protocol)
{ {
...@@ -360,7 +387,8 @@ icmp_rcv(struct sk_buff *skb1, struct device *dev, struct options *opt, ...@@ -360,7 +387,8 @@ icmp_rcv(struct sk_buff *skb1, struct device *dev, struct options *opt,
unsigned char *buff; unsigned char *buff;
/* Drop broadcast packets. */ /* Drop broadcast packets. */
if (chk_addr(daddr) == IS_BROADCAST) { if (chk_addr(daddr) == IS_BROADCAST)
{
DPRINTF((DBG_ICMP, "ICMP: Discarded broadcast from %s\n", DPRINTF((DBG_ICMP, "ICMP: Discarded broadcast from %s\n",
in_ntoa(saddr))); in_ntoa(saddr)));
skb1->sk = NULL; skb1->sk = NULL;
...@@ -372,17 +400,20 @@ icmp_rcv(struct sk_buff *skb1, struct device *dev, struct options *opt, ...@@ -372,17 +400,20 @@ icmp_rcv(struct sk_buff *skb1, struct device *dev, struct options *opt,
icmph = (struct icmphdr *) buff; icmph = (struct icmphdr *) buff;
/* Validate the packet first */ /* Validate the packet first */
if (ip_compute_csum((unsigned char *) icmph, len)) { if (ip_compute_csum((unsigned char *) icmph, len))
{
/* Failed checksum! */ /* Failed checksum! */
printk("ICMP: failed checksum from %s!\n", in_ntoa(saddr)); printk("ICMP: failed checksum from %s!\n", in_ntoa(saddr));
skb1->sk = NULL; skb1->sk = NULL;
kfree_skb(skb1, FREE_READ); kfree_skb(skb1, FREE_READ);
return(0); return(0);
} }
#ifdef ICMP_DEBUG
print_icmp(icmph); print_icmp(icmph);
#endif
/* Parse the ICMP message */ /* Parse the ICMP message */
switch(icmph->type) { switch(icmph->type)
{
case ICMP_TIME_EXCEEDED: case ICMP_TIME_EXCEEDED:
case ICMP_DEST_UNREACH: case ICMP_DEST_UNREACH:
case ICMP_SOURCE_QUENCH: case ICMP_SOURCE_QUENCH:
...@@ -427,11 +458,16 @@ icmp_rcv(struct sk_buff *skb1, struct device *dev, struct options *opt, ...@@ -427,11 +458,16 @@ icmp_rcv(struct sk_buff *skb1, struct device *dev, struct options *opt,
} }
/* Perform any ICMP-related I/O control requests. */ /*
int * Perform any ICMP-related I/O control requests.
icmp_ioctl(struct sock *sk, int cmd, unsigned long arg) *
* In the case of ICMP all the user can do is play with the debygging
*/
int icmp_ioctl(struct sock *sk, int cmd, unsigned long arg)
{ {
switch(cmd) { switch(cmd)
{
case DDIOCSDBG: case DDIOCSDBG:
return(dbg_ioctl((void *) arg, DBG_ICMP)); return(dbg_ioctl((void *) arg, DBG_ICMP));
default: default:
......
This diff is collapsed.
...@@ -21,8 +21,8 @@ ...@@ -21,8 +21,8 @@
#include <linux/ip.h> #include <linux/ip.h>
#include "sockinet.h"
#include "sock.h" /* struct sock */
/* IP flags. */ /* IP flags. */
#define IP_CE 0x8000 /* Flag: "Congestion" */ #define IP_CE 0x8000 /* Flag: "Congestion" */
...@@ -69,7 +69,8 @@ extern int ip_build_header(struct sk_buff *skb, ...@@ -69,7 +69,8 @@ extern int ip_build_header(struct sk_buff *skb,
unsigned long saddr, unsigned long saddr,
unsigned long daddr, unsigned long daddr,
struct device **dev, int type, 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 unsigned short ip_compute_csum(unsigned char * buff, int len);
extern int ip_rcv(struct sk_buff *skb, struct device *dev, extern int ip_rcv(struct sk_buff *skb, struct device *dev,
struct packet_type *pt); struct packet_type *pt);
...@@ -77,5 +78,6 @@ extern void ip_queue_xmit(struct sock *sk, ...@@ -77,5 +78,6 @@ extern void ip_queue_xmit(struct sock *sk,
struct device *dev, struct sk_buff *skb, struct device *dev, struct sk_buff *skb,
int free); int free);
extern void ip_retransmit(struct sock *sk, int all); 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 */ #endif /* _IP_H */
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.
...@@ -13,6 +13,8 @@ ...@@ -13,6 +13,8 @@
* Alan Cox : Rewrote skb_read_datagram to avoid the skb_peek_copy stuff. * Alan Cox : Rewrote skb_read_datagram to avoid the skb_peek_copy stuff.
* Alan Cox : Added support for SOCK_SEQPACKET. IPX can no longer use the SO_TYPE hack but * Alan Cox : Added support for SOCK_SEQPACKET. IPX can no longer use the SO_TYPE hack but
* AX.25 now works right, and SPX is feasible. * AX.25 now works right, and SPX is feasible.
* Alan Cox : Tidied up ready for the big day.
* Alan Cox : Fixed write select of no IP protocol crash.
*/ */
#include <linux/config.h> #include <linux/config.h>
...@@ -136,6 +138,13 @@ struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags, int noblock, ...@@ -136,6 +138,13 @@ struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags, int noblock,
return skb; return skb;
} }
/*
* Free a datagram buffer. This has some conditions to watch. We keep
* a user count so the last user may free the buffer. If however the
* buffer has a valid next pointer it was never removed and all the
* users PEEKed at it - so don't free it yet.
*/
void skb_free_datagram(struct sk_buff *skb) void skb_free_datagram(struct sk_buff *skb)
{ {
unsigned long flags; unsigned long flags;
...@@ -185,7 +194,11 @@ int datagram_select(struct sock *sk, int sel_type, select_table *wait) ...@@ -185,7 +194,11 @@ int datagram_select(struct sock *sk, int sel_type, select_table *wait)
return(0); return(0);
case SEL_OUT: case SEL_OUT:
if (sk->prot->wspace(sk) >= MIN_WRITE_SPACE) if(sk->prot && sk->prot->wspace(sk) >= MIN_WRITE_SPACE)
{
return(1);
}
if(sk->prot==NULL && sk->sndbuf-sk->wmem_alloc >= MIN_WRITE_SPACE)
{ {
return(1); 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.
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