From: Linus Torvalds Date: Fri, 23 Nov 2007 20:12:51 +0000 (-0500) Subject: Import 2.1.22 X-Git-Tag: 2.1.22 X-Git-Url: http://git.neil.brown.name/?a=commitdiff_plain;h=e788e5a889ede0a2478f78f4cf352731689b0e83;p=history.git Import 2.1.22 --- diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX index 72030a072f0e..09d482dac082 100644 --- a/Documentation/00-INDEX +++ b/Documentation/00-INDEX @@ -52,6 +52,8 @@ magic-number.txt - list of magic numbers used to mark/protect kernel data structures. mandatory.txt - info on the linux implementation of Sys V mandatory file locking. +memory.txt + - info on typical Linux memory problems. mca.txt - info on supporting Micro Channel Architecture (e.g. PS/2) systems. modules.txt diff --git a/Documentation/Changes b/Documentation/Changes index 7dccb468646d..571fcede5176 100644 --- a/Documentation/Changes +++ b/Documentation/Changes @@ -49,7 +49,8 @@ General Information now performs a cold reboot instead of a warm reboot for increased hardware compatibility. If you want a warm reboot and know it works on your hardware, add a "reboot=warm" command line option -in Lilo. +in Lilo. A small number of machines need "reboot=bios" to reboot via the +BIOS. Libc ==== @@ -128,15 +129,18 @@ How to know the version of the installed programs installed programs and libraries. The SysVinit version display requires that you be logged in as root. +Binutils: ld -v Gnu C: gcc -v or gcc --version +Kbd: loadkeys -h +Ld.so: ldd -v Libc: ls -l /lib/libc.so.* Libc++: ls -l /usr/lib/libg++.so.* -Ld.so: ldd-v -Binutils: ld -v -modules: insmod -V +modules: /sbin/insmod -V +mount: mount --version procps: ps --version -SysVinit: cat /proc/`cat /var/run/klogd.pid`/environ|strings|awk '$1 ~ -/INIT_VERSION/ {print}' +SysVinit: (must be logged in as root) + strings `egrep -li INIT_VERSION=sysvinit- /proc/*/environ | head -1` | \ + egrep -i INIT_VERSION=sysvinit- RPM: rpm --version Where to get the files diff --git a/Documentation/Configure.help b/Documentation/Configure.help index a15ec3d9262f..44269f1e740f 100644 --- a/Documentation/Configure.help +++ b/Documentation/Configure.help @@ -550,27 +550,6 @@ CONFIG_ALPHA_XL Machine") (as opposed to Mustang (AS200), M3 (AS250) or Avanti (AS400)), say Y, otherwise N. -Limit memory to low 16MB -CONFIG_MAX_16M - This is for some buggy motherboards which cannot properly deal with - the memory above 16MB. If you have more than 16MB of RAM and - experience weird problems, you might want to try Y, everyone else - says N. Note for machines with more that 64MB of RAM: in order for - the kernel to be able to use the memory above 64MB, pass the command - line option "mem=XXXM" (where XXX is the memory size in megabytes) - to your kernel during boot time. See the documentation of your boot - loader (lilo or loadlin) about how to pass options to the - kernel. The lilo procedure is also explained in the SCSI-HOWTO, - available via ftp (user: anonymous) in - sunsite.unc.edu:/pub/Linux/docs/HOWTO. You also need at least 512kB - of RAM cache if you have more than 64MB of RAM. Some other things - to try when experiencing seemingly random, "weird" problems: 1) - passing the "no-hlt" option to the kernel 2) passing the "no-387" - option to the kernel 3) passing the "mem=4M" option to the kernel - (thereby disabling all but the first 4M of RAM) 4) disabling the - cache from your BIOS settings 5) exchanging RAM chips 6) exchanging - the motherboard. - Using SRM as bootloader CONFIG_ALPHA_SRM There are two different types of booting firmware on Alphas: SRM, diff --git a/Documentation/memory.txt b/Documentation/memory.txt new file mode 100644 index 000000000000..8e43d27b5c74 --- /dev/null +++ b/Documentation/memory.txt @@ -0,0 +1,60 @@ +There are several classic problems related to memory on Linux +systems. + + 1) There are some buggy motherboards which cannot properly + deal with the memory above 16MB. Consider exchanging + your motherboard. + + 2) You cannot do DMA on the ISA bus to addresses above + 16M. Most device drivers under Linux allow the use + of bounce buffers which work around this problem. Drivers + that don't use bounce buffers will be unstable with + more than 16M installed. Drivers that use bounce buffers + will be OK, but may have slightly higher overhead. + + 3) There are some motherboards that will not cache above + a certain quantity of memory. If you have one of these + motherboards, your system will be SLOWER, not faster + as you add more memory. Consider exchanging your + motherboard. + + 4) Linux will not currently detect above 64M of RAM, + regardless of how much memory is actually installed. + +All of these problems can be addressed with the "mem=XXXM" boot option +(where XXX is the size of RAM to use in megabytes). Adding this boot +option to your boot loader can help Linux see more than 64M. It can +also tell Linux to use less memory than is actually installed. + +See the documentation of your boot loader (LILO, loadlin, etc.) about +how to pass options to the kernel. + +There are other memory problems which Linux cannot deal with. Random +corruption of memory is usually a sign of serious hardware trouble. +Try: + + * Reducing memory settings in the BIOS to the most conservative + timings. + + * Adding a cooling fan. + + * Not overclocking your CPU. + + * Having the memory tested in a memory tester or exchanged + with the vendor. + + * Exchanging your CPU, cache, or motherboard for one that works. + + * Disabling the cache from the BIOS. + + * Try passing the "mem=4M" option to the kernel to limit + Linux to using a very small amount of memory. + + +Other tricks: + + * Try passing the "no-387" option to the kernel to ignore + a buggy FPU. + + * Try passing the "no-hlt" option to disable the potentially + buggy HLT instruction in your CPU. diff --git a/Documentation/pcwd-watchdog.txt b/Documentation/pcwd-watchdog.txt new file mode 100644 index 000000000000..878ca69f337e --- /dev/null +++ b/Documentation/pcwd-watchdog.txt @@ -0,0 +1,131 @@ + Berkshire Products PC Watchdog Card + Support for ISA Cards Revision A and C + Documentation and Driver by Ken Hollis + + The PC Watchdog is a card that offers the same type of functionality that + the WDT card does, only it doesn't require an IRQ to run. Furthermore, + the Revision C card allows you to monitor any IO Port to automatically + trigger the card into being reset. This way you can make the card + monitor hard drive status, or anything else you need. + + The Watchdog Driver has one basic role: to talk to the card and send + signals to it so it doesn't reset your computer ... at least during + normal operation. + + The Watchdog Driver will automatically find your watchdog card, and will + attach a running driver for use with that card. After the watchdog + drivers have initialized, you can then talk to the card using the PC + Watchdog program, available from ftp.bitgate.com:/pub/bitgate/pcwd. + + I suggest putting a "watchdog -d" before the beginning of an fsck, and + a "watchdog -e -t 1" immediately after the end of an fsck. (Remember + to run the program with an "&" to run it in the background!) + + If you want to write a program to be compatible with the PC Watchdog + driver, simply do the following: + +-- Snippet of code -- +/* + * Watchdog Driver Test Program + */ + +#include +#include +#include +#include +#include +#include +#include + +int fd; + +/* + * This function simply sends an IOCTL to the driver, which in turn ticks + * the PC Watchdog card to reset its internal timer so it doesn't trigger + * a computer reset. + */ +void keep_alive(void) +{ + int dummy; + + ioctl(fd, WDIOC_KEEPALIVE, &dummy); +} + +/* + * The main program. Run the program with "-d" to disable the card, + * or "-e" to enable the card. + */ +int main(int argc, char *argv[]) +{ + fd = open("/dev/watchdog", O_WRONLY); + + if (fd == -1) { + fprintf(stderr, "Watchdog device not enabled.\n"); + fflush(stderr); + exit(-1); + } + + if (argc > 1) { + if (!strncasecmp(argv[1], "-d", 2)) { + ioctl(fd, WDIOC_SETOPTIONS, WDIOS_DISABLECARD); + fprintf(stderr, "Watchdog card disabled.\n"); + fflush(stderr); + exit(0); + } else if (!strncasecmp(argv[1], "-e", 2)) { + ioctl(fd, WDIOC_SETOPTIONS, WDIOS_ENABLECARD); + fprintf(stderr, "Watchdog card enabled.\n"); + fflush(stderr); + exit(0); + } else { + fprintf(stderr, "-d to disable, -e to enable.\n"); + fprintf(stderr, "run by itself to tick the card.\n"); + fflush(stderr); + exit(0); + } + } else { + fprintf(stderr, "Watchdog Ticking Away!\n"); + fflush(stderr); + } + + while(1) { + keep_alive(); + sleep(1); + } +} +-- End snippet -- + + Other IOCTL functions include: + + WDIOC_GETSUPPORT + This returns the support of the card itself. This + returns in structure "PCWDS" which returns: + options = WDIOS_TEMPPANIC + (This card supports temperature) + firmware_version = xxxx + (Firmware version of the card) + + WDIOC_GETSTATUS + This returns the status of the card, with the bits of + WDIOF_* bitwise-anded into the value. (The comments + are in linux/pcwd.h) + + WDIOC_GETBOOTSTATUS + This returns the status of the card that was reported + at bootup. + + WDIOC_GETTEMP + This returns the temperature of the card. (You can also + read /dev/watchdog, which gives a temperature update + every second.) + + WDIOC_SETOPTIONS + This lets you set the options of the card. You can either + enable or disable the card this way. + + WDIOC_KEEPALIVE + This pings the card to tell it not to reset your computer. + + And that's all she wrote! + + -- Ken Hollis + (khollis@nurk.org) diff --git a/Documentation/watchdog.txt b/Documentation/watchdog.txt index 940313a9448b..1a398dc4b4c6 100644 --- a/Documentation/watchdog.txt +++ b/Documentation/watchdog.txt @@ -11,17 +11,20 @@ The following watchdog drivers are currently implemented: ICS WDT501-P (no fan tachometer) ICS WDT500-P Software Only + Berkshire Products PC Watchdog Revision A & C (by Ken Hollis) -All four interfaces provide /dev/watchdog, which when open must be written -to within a minute or the machine will reboot. Each write delays the reboot -time another minute. In the case of the software watchdog the ability to + +All five interfaces provide /dev/watchdog, which when open must be written +to within a timeout or the machine will reboot. Each write delays the reboot +time another timeout. In the case of the software watchdog the ability to reboot will depend on the state of the machines and interrupts. The hardware boards physically pull the machine down off their own onboard timers and will reboot from almost anything. A second temperature monitoring interface is available on the WDT501P cards -and provides /dev/temperature. This is the machine internal temperature in -degrees farenheit. Each read returns a single byte giving the temperature. +and some Berkshire cards. This provides /dev/temperature. This is the machine +internal temperature in degrees farenheit. Each read returns a single byte +giving the temperature. The third interface logs kernel messages on additional alert events. @@ -29,16 +32,20 @@ Both software and hardware watchdog drivers are available in the standard kernel. If you are using the software watchdog, you probably also want to use "panic=60" as a boot argument as well. +The wdt card cannot be safely probed for. Instead you need to pass +wdt=ioaddr,irq as a boot parameter - eg "wdt=0x240,11". + Features -------- - WDT501P WDT500P Software -Reboot Timer X X X -External Reboot X X o -Temperature X o o -Fan Speed X o o -Power Under X o o -Power Over X o o -Overheat X o o + WDT501P WDT500P Software Berkshire +Reboot Timer X X X X +External Reboot X X o o +I/O Port Monitor o o o X +Temperature X o o X +Fan Speed X o o o +Power Under X o o o +Power Over X o o o +Overheat X o o o The external event interfaces on the WDT boards are not currently supported. Minor numbers are however allocated for it. @@ -81,3 +88,5 @@ Industrial Computer Source San Diego, CA and please mention Linux when enquiring. + +For full information about the PCWD cards see the pcwd-watchdog.txt document. diff --git a/MAINTAINERS b/MAINTAINERS index c4bc03fae763..7da57b73699f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -28,7 +28,7 @@ trivial patch so apply some common sense. job the maintainers (and especially Linus) do is to keep things looking the same. Sometimes this means that the clever hack in your driver to get around a problem actual needs to become a - generalised kernel feature ready for next time. + generalized kernel feature ready for next time. PLEASE try to include any credit lines you want added with the patch. It avoids people being missed off by mistake and makes @@ -387,4 +387,4 @@ S: Maintained REST: P: Linus Torvalds -S: Buried alive in email +S: Buried alive in diapers diff --git a/Makefile b/Makefile index cbad89bd492e..46be0ab21d16 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 1 -SUBLEVEL = 21 +SUBLEVEL = 22 ARCH = i386 diff --git a/README b/README index 20e3b83bc675..0eeb9ff85bda 100644 --- a/README +++ b/README @@ -108,15 +108,35 @@ INSTALLING the kernel: You should now have the sources correctly installed. +SOFTWARE REQUIREMENTS + + Compiling and running the 2.1.x kernels requires up-to-date + versions of various software packages. Consult + ./Documentation/Changes for the minimum version numbers required + and how to get updates for these packages. Beware that using + excessively old versions of these packages can cause indirect + errors that are very difficult to track down, so don't assume that + you can just update packages when obvious problems arise during + build or operation. + CONFIGURING the kernel: - Do a "make config" to configure the basic kernel. "make config" needs bash to work: it will search for bash in $BASH, /bin/bash and /bin/sh (in that order), so hopefully one of those is correct. + (Do not skip this step even if you are only upgrading one minor + version. New configuration options are added in each release, and + odd problems will turn up if the configuration files are not set up + as expected. If you want to carry your existing configuration to a + new version with minimal work, use "make oldconfig", which will + only ask you for the answers to new questions.) + - Alternate configuration commands are: "make menuconfig" Text based color menus, radiolists & dialogs. "make xconfig" X windows based configuration tool. + "make oldconfig" Default all questions based on the contents of + your existing ./.config file. NOTES on "make config": - having unnecessary drivers will make the kernel bigger, and can @@ -134,8 +154,8 @@ CONFIGURING the kernel: bigger or slower kernel (or both), and can even make the kernel less stable by configuring some routines to actively try to break bad code to find kernel problems (kmalloc()). Thus you - should probably answer 'n' to the questions for a "production" - kernel. + should probably answer 'n' to the questions for + "development", "experimental", or "debugging" features. - Check the top Makefile for further site-dependent configuration (default SVGA mode etc). diff --git a/arch/alpha/defconfig b/arch/alpha/defconfig index bc4f937e5ca3..1998d0814c69 100644 --- a/arch/alpha/defconfig +++ b/arch/alpha/defconfig @@ -165,6 +165,7 @@ CONFIG_DE4X5=y # CONFIG_PLIP is not set # CONFIG_PPP is not set # CONFIG_NET_RADIO is not set +# CONFIG_LAPBETHER is not set # CONFIG_SLIP is not set # CONFIG_TR is not set @@ -196,6 +197,7 @@ CONFIG_ISO9660_FS=y # CONFIG_HPFS_FS is not set # CONFIG_SYSV_FS is not set # CONFIG_AFFS_FS is not set +# CONFIG_ROMFS_FS is not set # CONFIG_UFS_FS is not set # diff --git a/arch/i386/boot/compressed/misc.c b/arch/i386/boot/compressed/misc.c index 296517feea0c..76d0dd160d99 100644 --- a/arch/i386/boot/compressed/misc.c +++ b/arch/i386/boot/compressed/misc.c @@ -340,7 +340,11 @@ main(argc, argv) void setup_normal_output_buffer() { - if (EXT_MEM_K < 1024) error("Less than 2MB of memory.\n"); +#ifdef STANDARD_MEMORY_BIOS_CALL + if (EXT_MEM_K < 1024) error("<2M of mem\n"); +#else + if (EXT_MEM_K*64 < 1024) error("<2M of mem\n"); +#endif output_data = (char *)0x100000; /* Points to 1M */ } diff --git a/arch/i386/boot/setup.S b/arch/i386/boot/setup.S index 65b6acf729f7..3ded0974b8ad 100644 --- a/arch/i386/boot/setup.S +++ b/arch/i386/boot/setup.S @@ -232,9 +232,40 @@ loader_panic_mess: loader_ok: ! Get memory size (extended mem, kB) +#ifdef STANDARD_MEMORY_BIOS_CALL mov ah,#0x88 int 0x15 mov [2],ax +#else + push ax + push cx + push dx + mov ax,#0xe801 + int 0x15 + jc oldstylemem + +! memory size is (ax+(64*bx)) * 1024; we store bx+(ax/64) + + mov [2],bx ! store extended memory size + xor dx,dx + mov cx,#64 ! convert lower memory size from K into + div cx ! 64k chunks. + + add [2],ax ! add lower memory into total size. + jmp gotmem + +oldstylemem: + mov ah,#0x88 + int 0x15 + mov cx,#64 ! got memory size in kbytes, so we need to + xor dx,dx ! adjust to 64k chunks for the system. + div cx + mov [2],ax +gotmem: + pop dx + pop cx + pop ax +#endif ! Set the keyboard repeat rate to the max diff --git a/arch/i386/config.in b/arch/i386/config.in index 957d0f0ca8da..13e2e8c401e3 100644 --- a/arch/i386/config.in +++ b/arch/i386/config.in @@ -23,7 +23,6 @@ comment 'General setup' bool 'Kernel math emulation' CONFIG_MATH_EMULATION bool 'Networking support' CONFIG_NET -bool 'Limit memory to low 16MB' CONFIG_MAX_16M bool 'PCI bios support' CONFIG_PCI if [ "$CONFIG_PCI" = "y" ]; then if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then diff --git a/arch/i386/defconfig b/arch/i386/defconfig index 7b0d67bd8747..4ed71aa03ec0 100644 --- a/arch/i386/defconfig +++ b/arch/i386/defconfig @@ -19,7 +19,6 @@ CONFIG_MODULES=y # # CONFIG_MATH_EMULATION is not set CONFIG_NET=y -# CONFIG_MAX_16M is not set CONFIG_PCI=y # CONFIG_MCA is not set CONFIG_SYSVIPC=y diff --git a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c index e131e5a45af6..541af11289b9 100644 --- a/arch/i386/kernel/irq.c +++ b/arch/i386/kernel/irq.c @@ -285,7 +285,7 @@ int get_smp_prof_list(char *buf) { for (j=0;jflags & SA_INTERRUPT) ? '+' : ' ', action->name); for (action=action->next; action; action = action->next) { @@ -293,6 +293,7 @@ int get_smp_prof_list(char *buf) { (action->flags & SA_INTERRUPT) ? " +" : "", action->name); } + len += sprintf(buf+len, "\n"); } len+=sprintf(buf+len, "LCK: %10lu", sum_spins); diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c index 112ebcf32af2..950a4ff66d32 100644 --- a/arch/i386/kernel/setup.c +++ b/arch/i386/kernel/setup.c @@ -142,16 +142,16 @@ void setup_arch(char **cmdline_p, BIOS_revision = SYS_DESC_TABLE.table[2]; } aux_device_present = AUX_DEVICE_INFO; +#ifdef STANDARD_MEMORY_BIOS_CALL memory_end = (1<<20) + (EXT_MEM_K<<10); +#else + memory_end = (1<<20) + (EXT_MEM_K*64L*1024L); /* 64kb chunks */ +#endif memory_end &= PAGE_MASK; #ifdef CONFIG_BLK_DEV_RAM rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK; rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0); rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0); -#endif -#ifdef CONFIG_MAX_16M - if (memory_end > 16*1024*1024) - memory_end = 16*1024*1024; #endif if (!MOUNT_ROOT_RDONLY) root_mountflags &= ~MS_RDONLY; diff --git a/arch/i386/lib/semaphore.S b/arch/i386/lib/semaphore.S index f2d11099f8f8..ff2443c40daf 100644 --- a/arch/i386/lib/semaphore.S +++ b/arch/i386/lib/semaphore.S @@ -7,21 +7,26 @@ #include /* - * "down_failed" is called with the eventual return address - * in %eax, and the address of the semaphore in %ecx. We need - * to call "__down()", and then re-try until we succeed.. + * The semaphore operations have a special calling sequence that + * allow us to do a simpler in-line version of them. These routines + * need to convert that sequence back into the C sequence when + * there is contention on the semaphore. */ ENTRY(__down_failed) pushl %eax /* return address */ pushl %edx /* save %edx */ -1: pushl %ecx /* save %ecx (and argument) */ + pushl %ecx /* save %ecx (and argument) */ call SYMBOL_NAME(__down) popl %ecx /* restore %ecx (count on __down not changing it) */ -#ifdef __SMP__ - lock -#endif - decl (%ecx) - js 1b + popl %edx /* restore %edx */ + ret + +ENTRY(__down_failed_interruptible) + pushl %eax /* return address */ + pushl %edx /* save %edx */ + pushl %ecx /* save %ecx (and argument) */ + call SYMBOL_NAME(__down_interruptible) + popl %ecx /* restore %ecx (count on __down_interruptible not changing it) */ popl %edx /* restore %edx */ ret diff --git a/arch/ppc/config.in b/arch/ppc/config.in index bf436ceebd08..56c636d2a1a4 100644 --- a/arch/ppc/config.in +++ b/arch/ppc/config.in @@ -23,7 +23,6 @@ comment 'General setup' bool 'Kernel math emulation' CONFIG_MATH_EMULATION bool 'Networking support' CONFIG_NET -bool 'Limit memory to low 16MB' CONFIG_MAX_16M bool 'PCI bios support' CONFIG_PCI if [ "$CONFIG_PCI" = "y" ]; then if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then diff --git a/drivers/block/README.fd b/drivers/block/README.fd index c3742498c689..3ceb16c0beda 100644 --- a/drivers/block/README.fd +++ b/drivers/block/README.fd @@ -49,14 +49,9 @@ isn't, use the old method using environment variables. The floppy related options include: - floppy=,allowed_drive_mask - Obsolete. Use the floppy=,,cmos option instead - - floppy=all_drives - Obsolete. Use the floppy=,,cmos option instead - floppy=asus_pci - Sets the bit mask to allow only units 0 and 1. (The default) + Sets the bit mask to allow only units 0 and 1. Obsolete, as + this is the default setting anyways floppy=daring Tells the floppy driver that you have a well behaved floppy controller. @@ -161,6 +156,28 @@ floppy=fifo to be an interaction between video and floppy. The unexpected interrupts only affect performance, and can safely be ignored.) + floppy=broken_dcl + Don't use the disk change line, but assume that the disk was + changed whenever the device node is reopened. Needed on some + boxes where the disk change line is broken or unsupported. + This should be regarded as a stopgap measure, indeed it makes + floppy operation less efficient due to unneeded cache + flushings, and slightly more unreliable. Please verify your + cable, connection and jumper settings if you have any DCL + problems. However, some older drives, and also some Laptops + are known not to have a DCL. + + floppy=debug + Print debugging messages + + floppy=messages + Print informational messages for some operations (disk change + notifications, warnings about over and underruns, and about + autodetection) + + floppy=silent_dcl_clear + Uses a less noisy way to clear the disk change line (which + doesn't involve seeks). Implied by daring. Supporting utilities and additional documentation: ================================================== diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 90d8280ce43a..8271ff9bd74d 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -2252,7 +2252,8 @@ static void rw_interrupt(void) return; } current_type[current_drive] = _floppy; - floppy_sizes[TOMINOR(current_drive) ]= _floppy->size>>1; + floppy_sizes[TOMINOR(current_drive) ]= + (_floppy->size+1)>>1; break; } @@ -2261,7 +2262,7 @@ static void rw_interrupt(void) DPRINT("Auto-detected floppy type %s in fd%d\n", _floppy->name,current_drive); current_type[current_drive] = _floppy; - floppy_sizes[TOMINOR(current_drive)] = _floppy->size >> 1; + floppy_sizes[TOMINOR(current_drive)] = (_floppy->size+1) >> 1; probing = 0; } @@ -2450,8 +2451,13 @@ static int make_raw_rw_request(void) TRACK = CURRENT->sector / max_sector; sector_t = CURRENT->sector % max_sector; - if (_floppy->track && TRACK >= _floppy->track) - return 0; + if (_floppy->track && TRACK >= _floppy->track) { + if(CURRENT->current_nr_sectors & 1) { + current_count_sectors = 1; + return 1; + } else + return 0; + } HEAD = sector_t / _floppy->sect; if (((_floppy->stretch & FD_SWAPSIDES) || TESTF(FD_NEED_TWADDLE)) && @@ -3108,7 +3114,7 @@ static inline int set_geometry(unsigned int cmd, struct floppy_struct *g, floppy_type[type].name="user format"; for (cnt = type << 2; cnt < (type << 2) + 4; cnt++) floppy_sizes[cnt]= floppy_sizes[cnt+0x80]= - floppy_type[type].size>>1; + (floppy_type[type].size+1)>>1; process_fd_request(); for (cnt = 0; cnt < N_DRIVE; cnt++){ if (ITYPE(drive_state[cnt].fd_device) == type && @@ -3127,7 +3133,7 @@ static inline int set_geometry(unsigned int cmd, struct floppy_struct *g, if (buffer_drive == drive) SUPBOUND(buffer_max, user_params[drive].sect); current_type[drive] = &user_params[drive]; - floppy_sizes[drive] = user_params[drive].size >> 1; + floppy_sizes[drive] = (user_params[drive].size+1) >> 1; if (cmd == FDDEFPRM) DRS->keep_data = -1; else @@ -3794,23 +3800,20 @@ static char get_fdc_version(void) /* lilo configuration */ -/* we make the invert_dcl function global. One day, somebody might - * want to centralize all thinkpad related options into one lilo option, - * there are just so many thinkpad related quirks! */ -void floppy_invert_dcl(int *ints,int param) +void floppy_set_flags(int *ints,int param, int param2) { int i; for (i=0; i < ARRAY_SIZE(default_drive_params); i++){ if (param) - default_drive_params[i].params.flags |= 0x80; + default_drive_params[i].params.flags |= param2; else - default_drive_params[i].params.flags &= ~0x80; + default_drive_params[i].params.flags &= ~param2; } - DPRINT("Configuring drives for inverted dcl\n"); + DPRINT("%s flag 0x%x\n", param2 ? "Setting" : "Clearing", param); } -static void daring(int *ints,int param) +static void daring(int *ints,int param, int param2) { int i; @@ -3826,7 +3829,7 @@ static void daring(int *ints,int param) DPRINT("Assuming %s floppy hardware\n", param ? "standard" : "broken"); } -static void set_cmos(int *ints, int dummy) +static void set_cmos(int *ints, int dummy, int dummy2) { int current_drive=0; @@ -3852,34 +3855,39 @@ static void set_cmos(int *ints, int dummy) static struct param_table { const char *name; - void (*fn)(int *ints, int param); + void (*fn)(int *ints, int param, int param2); int *var; int def_param; + int param2; } config_params[]={ - { "allowed_drive_mask", 0, &allowed_drive_mask, 0xff }, - { "all_drives", 0, &allowed_drive_mask, 0xff }, - { "asus_pci", 0, &allowed_drive_mask, 0x33 }, + { "allowed_drive_mask", 0, &allowed_drive_mask, 0xff, 0}, /* obsolete */ + { "all_drives", 0, &allowed_drive_mask, 0xff, 0 }, /* obsolete */ + { "asus_pci", 0, &allowed_drive_mask, 0x33, 0}, - { "daring", daring, 0, 1}, + { "daring", daring, 0, 1, 0}, - { "two_fdc", 0, &FDC2, 0x370 }, - { "one_fdc", 0, &FDC2, 0 }, + { "two_fdc", 0, &FDC2, 0x370, 0 }, + { "one_fdc", 0, &FDC2, 0, 0 }, - { "thinkpad", floppy_invert_dcl, 0, 1 }, + { "thinkpad", floppy_set_flags, 0, 1, FD_INVERTED_DCL }, + { "broken_dcl", floppy_set_flags, 0, 1, FD_BROKEN_DCL }, + { "messages", floppy_set_flags, 0, 1, FTD_MSG }, + { "silent_dcl_clear", floppy_set_flags, 0, 1, FD_SILENT_DCL_CLEAR }, + { "debug", floppy_set_flags, 0, 1, FD_DEBUG }, - { "nodma", 0, &use_virtual_dma, 1 }, - { "omnibook", 0, &use_virtual_dma, 1 }, - { "dma", 0, &use_virtual_dma, 0 }, + { "nodma", 0, &use_virtual_dma, 1, 0 }, + { "omnibook", 0, &use_virtual_dma, 1, 0 }, + { "dma", 0, &use_virtual_dma, 0, 0 }, - { "fifo_depth", 0, &fifo_depth, 0xa }, - { "nofifo", 0, &no_fifo, 0x20 }, - { "usefifo", 0, &no_fifo, 0 }, + { "fifo_depth", 0, &fifo_depth, 0xa, 0 }, + { "nofifo", 0, &no_fifo, 0x20, 0 }, + { "usefifo", 0, &no_fifo, 0, 0 }, - { "cmos", set_cmos, 0, 0 }, + { "cmos", set_cmos, 0, 0, 0 }, - { "unexpected_interrupts", 0, &print_unex, 1 }, - { "no_unexpected_interrupts", 0, &print_unex, 0 }, - { "L40SX", 0, &print_unex, 0 } }; + { "unexpected_interrupts", 0, &print_unex, 1, 0 }, + { "no_unexpected_interrupts", 0, &print_unex, 0, 0 }, + { "L40SX", 0, &print_unex, 0, 0 } }; #define FLOPPY_SETUP void floppy_setup(char *str, int *ints) @@ -3894,7 +3902,9 @@ void floppy_setup(char *str, int *ints) else param = config_params[i].def_param; if(config_params[i].fn) - config_params[i].fn(ints,param); + config_params[i]. + fn(ints,param, + config_params[i].param2); if(config_params[i].var) { DPRINT("%s=%d\n", str, param); *config_params[i].var = param; @@ -3928,7 +3938,7 @@ int floppy_init(void) for (i=0; i<256; i++) if (ITYPE(i)) - floppy_sizes[i] = floppy_type[ITYPE(i)].size >> 1; + floppy_sizes[i] = (floppy_type[ITYPE(i)].size+1) >> 1; else floppy_sizes[i] = MAX_DISK_SIZE; @@ -4210,6 +4220,12 @@ void cleanup_module(void) dummy = fd_eject(0); } +MODULE_PARM(floppy,"s"); +MODULE_PARM(FLOPPY_IRQ,"i"); +MODULE_PARM(FLOPPY_DMA,"i"); +MODULE_AUTHOR("Alain L. Knaff"); +MODULE_SUPPORTED_DEVICE("fd"); + #ifdef __cplusplus } #endif diff --git a/drivers/block/ps2esdi.c b/drivers/block/ps2esdi.c index 29ee6277e8a9..6d8803442c53 100644 --- a/drivers/block/ps2esdi.c +++ b/drivers/block/ps2esdi.c @@ -431,7 +431,7 @@ static void do_ps2esdi_request(void) list + sanity checks. */ INIT_REQUEST; - if (virt_to_bus((u_int) CURRENT->buffer + CURRENT->nr_sectors * 512) > 16 * MB) { + if (virt_to_bus(CURRENT->buffer + CURRENT->nr_sectors * 512) > 16 * MB) { printk("%s: DMA above 16MB not supported\n", DEVICE_NAME); end_request(FAIL); if (CURRENT) diff --git a/drivers/block/xd.c b/drivers/block/xd.c index c85ca6b58daf..3aab0f871675 100644 --- a/drivers/block/xd.c +++ b/drivers/block/xd.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -250,77 +251,75 @@ static void do_xd_request (void) /* xd_ioctl: handle device ioctl's */ static int xd_ioctl (struct inode *inode,struct file *file,u_int cmd,u_long arg) { - XD_GEOMETRY *geometry = (XD_GEOMETRY *) arg; - int dev = DEVICE_NR(inode->i_rdev),err; - - if (inode && (dev < xd_drives)) - switch (cmd) { - case HDIO_GETGEO: - if (arg) { - if ((err = verify_area(VERIFY_WRITE,geometry,sizeof(*geometry)))) - return (err); - put_user(xd_info[dev].heads, &geometry->heads); - put_user(xd_info[dev].sectors, &geometry->sectors); - put_user(xd_info[dev].cylinders, &geometry->cylinders); - put_user(xd[MINOR(inode->i_rdev)].start_sect,&geometry->start); - - return (0); - } - break; - case BLKRASET: - if(!suser()) - return -EACCES; - if(!(inode->i_rdev)) - return -EINVAL; - if(arg > 0xff) - return -EINVAL; - read_ahead[MAJOR(inode->i_rdev)] = arg; - return 0; - case BLKGETSIZE: - if (arg) { - if ((err = verify_area(VERIFY_WRITE,(long *) arg,sizeof(long)))) - return (err); - put_user(xd[MINOR(inode->i_rdev)].nr_sects,(long *) arg); - - return (0); - } - break; - case BLKFLSBUF: - if(!suser()) return -EACCES; - if(!(inode->i_rdev)) - return -EINVAL; - fsync_dev(inode->i_rdev); - invalidate_buffers(inode->i_rdev); - return 0; - - case BLKRRPART: - return (xd_reread_partitions(inode->i_rdev)); - RO_IOCTLS(inode->i_rdev,arg); + int dev; + + if ((!inode) || !(inode->i_rdev)) + return -EINVAL; + dev = DEVICE_NR(inode->i_rdev); + + if (dev >= xd_drives) return -EINVAL; + switch (cmd) { + case HDIO_GETGEO: + { + struct hd_geometry *geometry = (struct hd_geometry *) arg; + if (!geometry) return -EINVAL; + if(put_user(xd_info[dev].heads, (char *) &geometry->heads) + || put_user(xd_info[dev].sectors, (char *) &geometry->sectors) + || put_user(xd_info[dev].cylinders, (short *) &geometry->cylinders) + || put_user(xd[MINOR(inode->i_rdev)].start_sect, + (unsigned long *) &geometry->start)) + return -EFAULT; + return 0; } - return (-EINVAL); + case BLKRASET: + if(!suser()) return -EACCES; + if(arg > 0xff) return -EINVAL; + read_ahead[MAJOR(inode->i_rdev)] = arg; + return 0; + case BLKGETSIZE: + if (!arg) return -EINVAL; + put_user(xd[MINOR(inode->i_rdev)].nr_sects,(long *) arg); + return 0; + case BLKFLSBUF: /* Return devices size */ + if(!suser()) return -EACCES; + fsync_dev(inode->i_rdev); + invalidate_buffers(inode->i_rdev); + return 0; + case BLKRRPART: + return xd_reread_partitions(inode->i_rdev); + RO_IOCTLS(inode->i_rdev,arg); + default: + return -EINVAL; + } } /* xd_release: release the device */ static void xd_release (struct inode *inode, struct file *file) { - int dev = DEVICE_NR(inode->i_rdev); + int target; - if (dev < xd_drives) { + target= DEVICE_NR(inode->i_rdev); + if (target < xd_drives) { sync_dev(inode->i_rdev); - xd_access[dev]--; + xd_access[target]--; } } /* xd_reread_partitions: rereads the partition table from a drive */ static int xd_reread_partitions(kdev_t dev) { - int target = DEVICE_NR(dev); - int start = target << xd_gendisk.minor_shift; + int target; + int start; int partition; + + target = DEVICE_NR(dev); + start = target << xd_gendisk.minor_shift; - cli(); xd_valid[target] = (xd_access[target] != 1); sti(); + cli(); + xd_valid[target] = (xd_access[target] != 1); + sti(); if (xd_valid[target]) - return (-EBUSY); + return -EBUSY; for (partition = xd_gendisk.max_p - 1; partition >= 0; partition--) { int minor = (start | partition); @@ -338,7 +337,7 @@ static int xd_reread_partitions(kdev_t dev) xd_valid[target] = 1; wake_up(&xd_wait_open); - return (0); + return 0; } /* xd_readwrite: handle a read/write request */ diff --git a/drivers/char/Config.in b/drivers/char/Config.in index 0905205f141b..256e514c65ee 100644 --- a/drivers/char/Config.in +++ b/drivers/char/Config.in @@ -70,15 +70,9 @@ if [ "$CONFIG_WATCHDOG" != "n" ]; then if [ "$CONFIG_WDT_501" = "y" ]; then bool ' Fan Tachometer' CONFIG_WDT_501_FAN fi - else - tristate ' Software Watchdog' CONFIG_SOFT_WATCHDOG fi + tristate ' Software Watchdog' CONFIG_SOFT_WATCHDOG tristate ' Berkshire Products PC Watchdog' CONFIG_PCWATCHDOG - if [ "$CONFIG_PCWATCHDOG" != "n" ]; then - bool ' Support for Revision A cards' CONFIG_PCWD_REV_A - bool ' Support for Revision C cards' CONFIG_PCWD_REV_C - bool ' Show card state on reset' CONFIG_PCWD_SHOW_PREVSTAT - fi fi bool 'Enhanced Real Time Clock Support' CONFIG_RTC endmenu diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 36764df22da5..8f223e986e1d 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -231,14 +231,39 @@ static long write_null(struct inode * inode, struct file * file, } /* - * For fun, somebody might look into using the MMU for this. - * NOTE! It's not trivial: you have to check that the mapping - * is a private mapping and if so you can just map in the - * zero page directly. But shared mappings _have_ to use the - * physical copy. + * For fun, we are using the MMU for this. */ static inline unsigned long read_zero_pagealigned(char * buf, unsigned long size) { + struct vm_area_struct * curr_vma; + unsigned long addr=(unsigned long)buf; + +/* + * First we take the most obvious case: when we have one VM area to deal with, + * and it's privately mapped. + */ + curr_vma = find_vma(current->mm, addr); + + if ( !(curr_vma->vm_flags & VM_SHARED) && + (addr + size <= curr_vma->vm_end) ) { + + flush_cache_range(current->mm, addr, addr + size); + zap_page_range(current->mm, addr, size); + zeromap_page_range(addr, size, PAGE_COPY); + flush_tlb_range(current->mm, addr, addr + size); + + return 0; + } + +/* + * Ooops, the shared case is hard. Lets do the conventional + * zeroing. + * + * FIXME: same for the multiple-vma case, we dont handle it + * now for simplicity, although it's much easier than + * the shared case. Not that it should happen often ... + */ + do { if (clear_user(buf, PAGE_SIZE)) break; @@ -247,6 +272,7 @@ static inline unsigned long read_zero_pagealigned(char * buf, unsigned long size buf += PAGE_SIZE; size -= PAGE_SIZE; } while (size); + return size; } diff --git a/drivers/char/misc.c b/drivers/char/misc.c index d3cf60d97338..036e78d124c0 100644 --- a/drivers/char/misc.c +++ b/drivers/char/misc.c @@ -175,7 +175,6 @@ void cleanup_module(void) #endif -/* Should this be surrounded with "#ifdef CONFIG_MODULES" ? */ EXPORT_SYMBOL(misc_register); EXPORT_SYMBOL(misc_deregister); #ifndef MODULE @@ -219,14 +218,20 @@ int misc_init(void) #ifdef CONFIG_SUN_MOUSE sun_mouse_init(); #endif -#ifdef CONFIG_SOFT_WATCHDOG - watchdog_init(); +/* + * Only one watchdog can succeed. We probe the pcwatchdog first, + * then the wdt cards and finally the software watchdog which always + * works. This means if your hardware watchdog dies or is 'borrowed' + * for some reason the software watchdog still gives you some cover. + */ +#ifdef CONFIG_PCWATCHDOG + pcwatchdog_init(); #endif #ifdef CONFIG_WDT wdt_init(); #endif -#ifdef CONFIG_PCWATCHDOG - pcwatchdog_init(); +#ifdef CONFIG_SOFT_WATCHDOG + watchdog_init(); #endif #ifdef CONFIG_APM apm_bios_init(); diff --git a/drivers/char/pcwd.c b/drivers/char/pcwd.c index 783a36e2534b..198dfed88150 100644 --- a/drivers/char/pcwd.c +++ b/drivers/char/pcwd.c @@ -19,6 +19,15 @@ * typedefs to replace them. Made heartbeat reset only available * via ioctl, and removed the write routine. * 960828 Added new items for PC Watchdog Rev.C card. + * 960829 Changed around all of the IOCTLs, added new features, + * added watchdog disable/re-enable routines. Added firmware + * version reporting. Added read routine for temperature. + * Removed some extra defines, added an autodetect Revision + * routine. + * 961006 Revised some documentation, fixed some cosmetic bugs. Made + * drivers to panic the system if it's overheating at bootup. + * 961118 Changed some verbiage on some of the output, tidied up + * code bits, and added compatibility to 2.1.x. */ #include @@ -39,65 +48,60 @@ #include #include #include -#include -#include -typedef struct pcwd_ioports { - int first_port; - int range; -} IOPS; +#include +#include /* -** These are the auto-probe addresses available for the Rev.A version of the -** PC Watchdog card. -*/ - -static IOPS pcwd_ioports[] = { - { 0x270, 3 }, - { 0x350, 3 }, - { 0x370, 3 }, - { 0x000, 0 } -}; + * These are the auto-probe addresses available. + * + * Revision A only uses ports 0x270 and 0x370. Revision C introduced 0x350. + * Revision A has an address range of 2 addresses, while Revision C has 3. + */ +static int pcwd_ioports[] = { 0x270, 0x350, 0x370, 0x000 }; -#ifdef DEBUG -#define dprintk(x) printk(x) -#else -#define dprintk(x) +#define WD_VER "1.0 (11/18/96)" +#define WD_MINOR 130 /* Minor device number */ +#ifndef TEMP_MINOR +#define TEMP_MINOR 131 /* Uses the same as WDT */ #endif -#ifdef CONFIG_PCWD_REV_A -#define CARD_REV "A" -#define PORT_OFFSET 0 -#define PORT_RANGE 2 +/* + * It should be noted that PCWD_REVISION_B was removed because A and B + * are essentially the same types of card, with the exception that B + * has temperature reporting. Since I didn't receive a Rev.B card, + * the Rev.B card is not supported. (It's a good thing too, as they + * are no longer in production.) + */ +#define PCWD_REVISION_A 1 +#define PCWD_REVISION_C 2 + +#define WD_TIMEOUT 3 /* 1 1/2 seconds for a timeout */ + +/* + * These are the defines for the PC Watchdog card, revision A. + */ #define WD_WDRST 0x01 /* Previously reset state */ #define WD_T110 0x02 /* Temperature overheat sense */ #define WD_HRTBT 0x04 /* Heartbeat sense */ #define WD_RLY2 0x08 /* External relay triggered */ #define WD_SRLY2 0x80 /* Software external relay triggered */ -#endif -#ifdef CONFIG_PCWD_REV_C -#define CARD_REV "C" -#define PORT_OFFSET 1 -#define PORT_RANGE 4 -#define WD_WDRST 0x01 /* Previously reset state */ -#define WD_T110 0x04 /* Temperature overheat sense */ -#endif - -#define WD_VER "0.52 (08/28/96)" -#define WD_MINOR 130 /* Minor device number */ -#define WD_TIMEOUT 3 /* 1 1/2 seconds for a timeout */ - - -static int current_readport; +static int current_readport, revision, temp_panic; static int is_open, initial_status, supports_temp, mode_debug; -int pcwd_checkcard(void) +/* + * PCWD_CHECKCARD + * + * This routine checks the "current_readport" to see if the card lies there. + * If it does, it returns accordingly. + */ +static int pcwd_checkcard(void) { int card_dat, prev_card_dat, found = 0, count = 0, done = 0; - /* As suggested by Alan Cox */ - if (check_region(current_readport, PORT_RANGE)) { + /* As suggested by Alan Cox - this is a safety measure. */ + if (check_region(current_readport, 4)) { printk("pcwd: Port 0x%x unavailable.\n", current_readport); return 0; } @@ -106,13 +110,10 @@ int pcwd_checkcard(void) prev_card_dat = 0x00; prev_card_dat = inb(current_readport); - if (prev_card_dat == 0xFF) { - dprintk(("pcwd: No card detected at 0x%03x\n", current_readport)); + if (prev_card_dat == 0xFF) return 0; - } while(count < WD_TIMEOUT) { - dprintk(("pcwd: Run #%d on port 0x%03x\n", count, current_readport)); /* Read the raw card data from the port, and strip off the first 4 bits */ @@ -125,17 +126,6 @@ int pcwd_checkcard(void) udelay(500000L); done = 0; - /* 0x0F usually means that no card data is present, or the card - is not installed on this port. If 0x0F is present here, it's - normally safe to assume there's no card at that base address. */ - - if (card_dat == 0x0F) { - count++; - done = 1; - - dprintk(("pcwd: I show nothing on this port.\n")); - } - /* If there's a heart beat in both instances, then this means we found our card. This also means that either the card was previously reset, or the computer was power-cycled. */ @@ -144,8 +134,6 @@ int pcwd_checkcard(void) (!done)) { found = 1; done = 1; - - dprintk(("pcwd: I show alternate heart beats. Card detected.\n")); break; } @@ -159,7 +147,6 @@ int pcwd_checkcard(void) if ((card_dat == prev_card_dat) && (!done)) { count++; - dprintk(("pcwd: The card data is exactly the same (possibility).\n")); done = 1; } @@ -169,7 +156,6 @@ int pcwd_checkcard(void) if ((card_dat != prev_card_dat) && (!done)) { done = 1; found = 1; - dprintk(("pcwd: I show alternate heart beats. Card detected.\n")); break; } @@ -186,18 +172,36 @@ void pcwd_showprevstate(void) { int card_status = 0x0000; - initial_status = card_status = inb(current_readport + PORT_OFFSET); + if (revision == PCWD_REVISION_A) + initial_status = card_status = inb(current_readport); + else + initial_status = card_status = inb(current_readport + 1); - if (card_status & WD_WDRST) - printk("pcwd: Previous reboot was caused by the card.\n"); + if (revision == PCWD_REVISION_A) { + if (card_status & WD_WDRST) + printk("pcwd: Previous reboot was caused by the card.\n"); - if (supports_temp) - if(card_status & WD_T110) - printk("pcwd: CPU overheat sense.\n"); + if (card_status & WD_T110) { + printk("pcwd: Card senses a CPU Overheat. Panicking!\n"); + panic("pcwd: CPU Overheat.\n"); + } + + if ((!(card_status & WD_WDRST)) && + (!(card_status & WD_T110))) + printk("pcwd: Cold boot sense.\n"); + } else { + if (card_status & 0x01) + printk("pcwd: Previous reboot was caused by the card.\n"); + + if (card_status & 0x04) { + printk("pcwd: Card senses a CPU Overheat. Panicking!\n"); + panic("pcwd: CPU Overheat.\n"); + } - if ((!(card_status & WD_WDRST)) && - (!(card_status & WD_T110))) - printk("pcwd: Cold boot sense.\n"); + if ((!(card_status & 0x01)) && + (!(card_status & 0x04))) + printk("pcwd: Cold boot sense.\n"); + } } static void pcwd_send_heartbeat(void) @@ -207,14 +211,15 @@ static void pcwd_send_heartbeat(void) if (!is_open) return; - dprintk(("pcwd: heartbeat\n")); - wdrst_stat = inb_p(current_readport); wdrst_stat &= 0x0F; wdrst_stat |= WD_WDRST; - outb_p(wdrst_stat, current_readport + PORT_OFFSET); + if (revision == PCWD_REVISION_A) + outb_p(wdrst_stat, current_readport + 1); + else + outb_p(wdrst_stat, current_readport); } static int pcwd_ioctl(struct inode *inode, struct file *file, @@ -223,15 +228,12 @@ static int pcwd_ioctl(struct inode *inode, struct file *file, int i, cdat, rv; static struct watchdog_info ident= { + /* FIXME: should set A/C here */ WDIOF_OVERHEAT|WDIOF_CARDRESET, -#ifdef CONFIG_PCWD_REV_A 1, -#else - 3, -#endif - "PCWD revision "CARD_REV"." + "PCWD." }; - + switch(cmd) { default: return -ENOIOCTLCMD; @@ -244,33 +246,112 @@ static int pcwd_ioctl(struct inode *inode, struct file *file, cdat = inb(current_readport); rv = 0; - if (cdat & WD_WDRST) - rv |= WDIOF_CARDRESET; + if (revision == PCWD_REVISION_A) + { + if (cdat & WD_WDRST) + rv |= WDIOF_CARDRESET; - if (cdat & WD_T110) - rv |= WDIOF_OVERHEAT; + if (cdat & WD_T110) + { + rv |= WDIOF_OVERHEAT; - return put_user(rv, (int *) arg); - break; + if (temp_panic) + panic("pcwd: Temperature overheat trip!\n"); + } + } + else + { + if (cdat & 0x01) + rv |= WDIOF_CARDRESET; + + if (cdat & 0x04) + { + rv |= WDIOF_OVERHEAT; + + if (temp_panic) + panic("pcwd: Temperature overheat trip!\n"); + } + } + + if(put_user(rv, (int *) arg)) + return -EFAULT; + return 0; case WDIOC_GETBOOTSTATUS: rv = 0; - if (initial_status & WD_WDRST) - rv |= WDIOF_CARDRESET; + if (revision == PCWD_REVISION_A) + { + if (initial_status & WD_WDRST) + rv |= WDIOF_CARDRESET; - if (initial_status & WD_T110) - rv |= WDIOF_OVERHEAT; - return put_user(rv, (int *) arg); + if (initial_status & WD_T110) + rv |= WDIOF_OVERHEAT; + } + else + { + if (initial_status & 0x01) + rv |= WDIOF_CARDRESET; + + if (initial_status & 0x04) + rv |= WDIOF_OVERHEAT; + } + + if(put_user(rv, (int *) arg)) + return -EFAULT; + return 0; case WDIOC_GETTEMP: + rv = 0; - if ((supports_temp) && (mode_debug == 0)) { + if ((supports_temp) && (mode_debug == 0)) + { rv = inb(current_readport); - return put_user(rv, (int*) arg); - } else - return put_user(rv, (int*) arg); + if(put_user(rv, (int*) arg)) + return -EFAULT; + } else if(put_user(rv, (int*) arg)) + return -EFAULT; + return 0; + case WDIOC_SETOPTIONS: + if (revision == PCWD_REVISION_C) + { + if(copy_from_user(&rv, (int*) arg, sizeof(int))) + return -EFAULT; + + if (rv & WDIOS_DISABLECARD) + { + outb_p(0xA5, current_readport + 3); + outb_p(0xA5, current_readport + 3); + cdat = inb_p(current_readport + 2); + if ((cdat & 0x10) == 0) + { + printk("pcwd: Could not disable card.\n"); + return -EIO; + } + + return 0; + } + + if (rv & WDIOS_ENABLECARD) + { + outb_p(0x00, current_readport + 3); + cdat = inb_p(current_readport + 2); + if (cdat & 0x10) + { + printk("pcwd: Could not enable card.\n"); + return -EIO; + } + return 0; + } + + if (rv & WDIOS_TEMPPANIC) + { + temp_panic = 1; + } + } + return -EINVAL; + case WDIOC_KEEPALIVE: pcwd_send_heartbeat(); return 0; @@ -279,7 +360,7 @@ static int pcwd_ioctl(struct inode *inode, struct file *file, return 0; } -static long pcwd_write(struct file *file, struct inode *inode, const char *buf, unsigned long len) +static long pcwd_write(struct inode *inode, struct file *file, const char *buf, unsigned long len) { if (len) { @@ -291,30 +372,107 @@ static long pcwd_write(struct file *file, struct inode *inode, const char *buf, static int pcwd_open(struct inode *ino, struct file *filep) { - dprintk(("pcwd: open request\n")); - MOD_INC_USE_COUNT; return(0); } -static void pcwd_close(struct inode *ino, struct file *filep) +static long pcwd_read(struct inode *inode, struct file *file, char *buf, + unsigned long count) { - dprintk(("pcwd: close request\n")); + unsigned short c = inb(current_readport); + unsigned char cp; + + switch(MINOR(inode->i_rdev)) + { + case TEMP_MINOR: + cp = c; + if(copy_to_user(buf, &cp, 1)) + return -EFAULT; + return 1; + default: + return -EINVAL; + } +} +static void pcwd_close(struct inode *ino, struct file *filep) +{ MOD_DEC_USE_COUNT; } static void get_support(void) { -#ifdef CONFIG_PCWD_REV_C if (inb(current_readport) != 0xF0) -#endif supports_temp = 1; } +static int get_revision(void) +{ + if ((inb(current_readport + 2) == 0xFF) || + (inb(current_readport + 3) == 0xFF)) + return(PCWD_REVISION_A); + + return(PCWD_REVISION_C); +} + +static int send_command(int cmd) +{ + int i; + + outb_p(cmd, current_readport + 2); + udelay(1000L); + + i = inb(current_readport); + i = inb(current_readport); + + return(i); +} + +static char *get_firmware(void) +{ + int i, found = 0, count = 0, one, ten, hund, minor; + char *ret; + + ret = kmalloc(6, GFP_KERNEL); + + while((count < 3) && (!found)) { + outb_p(0x80, current_readport + 2); + i = inb(current_readport); + + if (i == 0x00) + found = 1; + else if (i == 0xF3) + outb_p(0x00, current_readport + 2); + + udelay(400L); + count++; + } + + if (found) { + mode_debug = 1; + + one = send_command(0x81); + ten = send_command(0x82); + hund = send_command(0x83); + minor = send_command(0x84); + } + + if (found) + sprintf(ret, "%c.%c%c%c", one, ten, hund, minor); + else + sprintf(ret, "ERROR"); + + return(ret); +} + +static void debug_off(void) +{ + outb_p(0x00, current_readport + 2); + mode_debug = 0; +} + static struct file_operations pcwd_fops = { NULL, /* Seek */ - NULL, /* Read */ + pcwd_read, /* Read */ pcwd_write, /* Write */ NULL, /* Readdir */ NULL, /* Select */ @@ -329,6 +487,12 @@ static struct miscdevice pcwd_miscdev = { "pcwatchdog", &pcwd_fops }; + +static struct miscdevice temp_miscdev = { + TEMP_MINOR, + "temperature", + &pcwd_fops +}; #ifdef MODULE int init_module(void) @@ -338,24 +502,21 @@ int pcwatchdog_init(void) { int i, found = 0; - dprintk(("pcwd: Success.\n")); - printk(KERN_INFO "pcwd: v%s Ken Hollis (khollis@bitgate.com)\n", WD_VER); + revision = PCWD_REVISION_A; - dprintk(("pcwd: About to perform card autosense loop.\n")); + printk("pcwd: v%s Ken Hollis (khollis@nurk.org)\n", WD_VER); /* Initial variables */ is_open = 0; supports_temp = 0; mode_debug = 0; + temp_panic = 0; initial_status = 0x0000; - dprintk(("pcwd: Revision " CARD_REV " support defined.\n")); - - for (i = 0; pcwd_ioports[i].first_port != 0; i++) { - current_readport = pcwd_ioports[i].first_port; +#ifndef PCWD_BLIND + for (i = 0; pcwd_ioports[i] != 0; i++) { + current_readport = pcwd_ioports[i]; - if (!pcwd_checkcard()) { - dprintk(("pcwd: Trying port 0x%03x.\n", pcwd_ioports[i].first_port)); if (pcwd_checkcard()) { found = 1; break; @@ -363,33 +524,45 @@ int pcwatchdog_init(void) } if (!found) { - printk("pcwd: No card detected.\n"); + printk("pcwd: No card detected, or port not available.\n"); return(-EIO); } +#endif is_open = 1; - get_support(); - -#ifdef CONFIG_PCWD_REV_A - printk("pcwd: PC Watchdog (REV.A) detected at port 0x%03x\n", current_readport); -#endif -#ifdef CONFIG_PCWD_REV_C - printk("pcwd: PC Watchdog (REV.C) detected at port 0x%03x -%stemp. support\n", - current_readport, (supports_temp) ? " Has " : " No "); +#ifdef PCWD_BLIND + current_readport = PCWD_BLIND; #endif -#ifdef CONFIG_PCWD_SHOW_PREVSTAT - pcwd_showprevstate(); -#endif - dprintk(("pcwd: Requesting region entry\n")); + get_support(); + revision = get_revision(); + + if (revision == PCWD_REVISION_A) + printk("pcwd: PC Watchdog (REV.A) detected at port 0x%03x\n", current_readport); + else if (revision == PCWD_REVISION_C) + printk("pcwd: PC Watchdog (REV.C) detected at port 0x%03x (Firmware version: %s)\n", + current_readport, get_firmware()); + else { + /* Should NEVER happen, unless get_revision() fails. */ + printk("pcwd: Unable to get revision.\n"); + return -1; + } - request_region(current_readport, PORT_RANGE, "PCWD Rev." CARD_REV "(Berkshire)"); + debug_off(); - dprintk(("pcwd: character device creation.\n")); + pcwd_showprevstate(); + + if (revision == PCWD_REVISION_A) + request_region(current_readport, 2, "PCWD Rev.A (Berkshire)"); + else + request_region(current_readport, 4, "PCWD Rev.C (Berkshire)"); misc_register(&pcwd_miscdev); + if (supports_temp) + misc_register(&temp_miscdev); + return 0; } @@ -397,23 +570,9 @@ int pcwatchdog_init(void) void cleanup_module(void) { misc_deregister(&pcwd_miscdev); - release_region(current_readport, PORT_RANGE); + if (supports_temp) + misc_deregister(&temp_miscdev); - dprintk(("pcwd: Cleanup successful.\n")); + release_region(current_readport, (revision == PCWD_REVISION_A) ? 2 : 4); } #endif - -/* -** TODO: -** -** Both Revisions: -** o) Implement the rest of the IOCTLs as discussed with Alan Cox -** o) Faster card detection routines -** o) /proc device creation -** -** Revision B functions: -** o) /dev/temp device creation for temperature device (possibly use -** the one from the WDT drivers?) -** o) Direct Motorola controller chip access via read/write routines -** o) Autoprobe IO Ports for autodetection (possibly by chip detect?) -*/ diff --git a/drivers/char/tpqic02.c b/drivers/char/tpqic02.c index c67cdc7056e8..1d7e97ec9a52 100644 --- a/drivers/char/tpqic02.c +++ b/drivers/char/tpqic02.c @@ -2696,7 +2696,7 @@ static int qic02_tape_ioctl(struct inode * inode, struct file * filp, */ /* copy results to user space */ - if (copy_to_user((char *) &ioctl_status, (char *) ioarg, sizeof(ioctl_status))) + if (copy_to_user((char *) ioarg, (char *) &ioctl_status, sizeof(ioctl_status))) { return -EFAULT; } diff --git a/drivers/char/wdt.c b/drivers/char/wdt.c index 216bb1f73cfc..957df12999f2 100644 --- a/drivers/char/wdt.c +++ b/drivers/char/wdt.c @@ -50,8 +50,8 @@ static int wdt_is_open=0; * You can use wdt=x,y to set these now. */ -int io=0x240; -int irq=14; +static int io=0x240; +static int irq=14; #define WD_TIMO (100*60) /* 1 minute */ diff --git a/drivers/net/3c523.c b/drivers/net/3c523.c index 8ac249c59348..21b411b6636d 100644 --- a/drivers/net/3c523.c +++ b/drivers/net/3c523.c @@ -1134,19 +1134,6 @@ elmc_send_packet(struct sk_buff *skb, struct device *dev) return 0; } - if(skb == NULL) { - dev_tint(dev); - return 0; - } - - if (skb->len <= 0) { - return 0; - } - if(skb->len > XMIT_BUFF_SIZE) { - printk("%s: Sorry, max. framelength is %d bytes. The length of your frame is %ld bytes.\n",dev->name,XMIT_BUFF_SIZE,skb->len); - return 0; - } - if (set_bit(0, (void*)&dev->tbusy) != 0) { printk("%s: Transmitter access conflict.\n", dev->name); } else { diff --git a/drivers/net/atp.c b/drivers/net/atp.c index 6017a6743c03..466fb821fcac 100644 --- a/drivers/net/atp.c +++ b/drivers/net/atp.c @@ -762,7 +762,7 @@ static void set_multicast_list(struct device *dev) { struct net_local *lp = (struct net_local *)dev->priv; short ioaddr = dev->base_addr; - int num_addrs=dev->mc_list; + int num_addrs=dev->mc_count; if(dev->flags&(IFF_ALLMULTI|IFF_PROMISC)) num_addrs=1; diff --git a/drivers/net/dlci.c b/drivers/net/dlci.c index 191d82d0af69..eeb629c14103 100644 --- a/drivers/net/dlci.c +++ b/drivers/net/dlci.c @@ -587,7 +587,6 @@ int dlci_ioctl(unsigned int cmd, void *arg) int dlci_init(struct device *dev) { struct dlci_local *dlp; - int i; dev->priv = kmalloc(sizeof(struct dlci_local), GFP_KERNEL); if (!dev->priv) diff --git a/drivers/net/eql.c b/drivers/net/eql.c index 0ff21a9f0664..7ea10dc233f0 100644 --- a/drivers/net/eql.c +++ b/drivers/net/eql.c @@ -213,7 +213,6 @@ int eql_init(struct device *dev) static unsigned version_printed = 0; /* static unsigned num_masters = 0; */ equalizer_t *eql = 0; - int i; if ( version_printed++ == 0 && eql_debug > 0) printk(version); diff --git a/drivers/net/hdlcdrv.c b/drivers/net/hdlcdrv.c index 32cbbdb03431..eca6f6f626a0 100644 --- a/drivers/net/hdlcdrv.c +++ b/drivers/net/hdlcdrv.c @@ -50,6 +50,7 @@ #include #include #include +#include /* make genksyms happy */ #include @@ -743,7 +744,6 @@ static int hdlcdrv_ioctl(struct device *dev, struct ifreq *ifr, int cmd) static int hdlcdrv_probe(struct device *dev) { struct hdlcdrv_channel_params dflt_ch_params = { 20, 2, 10, 40, 0 }; - int i; struct hdlcdrv_state *s; if (!dev) diff --git a/drivers/net/ibmtr.c b/drivers/net/ibmtr.c index fd6c78b5581d..97fc35e3ee67 100644 --- a/drivers/net/ibmtr.c +++ b/drivers/net/ibmtr.c @@ -1,61 +1,59 @@ -/* ibmtr.c: A shared-memory IBM Token Ring 16/4 driver for linux */ -/* - Written 1993 by Mark Swanson and Peter De Schrijver. - This software may be used and distributed according to the terms - of the GNU Public License, incorporated herein by reference. - - This device driver should work with Any IBM Token Ring Card that does - not use DMA. - - I used Donald Becker's (becker@super.org) device driver work - as a base for most of my initial work. -*/ - -/* - Changes by Peter De Schrijver (Peter.Deschrijver@linux.cc.kuleuven.ac.be) : - - + changed name to ibmtr.c in anticipation of other tr boards. - + changed reset code and adapter open code. - + added SAP open code. - + a first attempt to write interrupt, transmit and receive routines. - - Changes by David W. Morris (dwm@shell.portal.com) : - 941003 dwm: - Restructure tok_probe for multiple adapters, devices - - Add comments, misc reorg for clarity - - Flatten interrupt handler levels - - Changes by Farzad Farid (farzy@zen.via.ecp.fr) - and Pascal Andre (andre@chimay.via.ecp.fr) (March 9 1995) : - - multi ring support clean up - - RFC1042 compliance enhanced - - Changes by Pascal Andre (andre@chimay.via.ecp.fr) (September 7 1995) : - - bug correction in tr_tx - - removed redundant information display - - some code reworking - - Changes by Michel Lespinasse (walken@via.ecp.fr), - Yann Doussot (doussot@via.ecp.fr) and Pascal Andre (andre@via.ecp.fr) - (February 18, 1996) : - - modified shared memory and mmio access port the driver to - alpha platform (structure access -> readb/writeb) - - Changes by Steve Kipisz (bungy@ibm.net or kipisz@vnet.ibm.com) - (January 18 1996): - - swapped WWOR and WWCR in ibmtr.h - - moved some init code from tok_probe into trdev_init. The - PCMCIA code can call trdev_init to complete initializing - the driver. - - added -DPCMCIA to support PCMCIA - - detecting PCMCIA Card Removal in interrupt handler. if - ISRP is FF, then a PCMCIA card has been removed - - Changes by Paul Norton (pnorton@cts.com) : - - restructured the READ.LOG logic to prevent the transmit SRB - from being rudely overwritten before the transmit cycle is - complete. (August 15 1996) - - completed multiple adapter support. (November 20 1996) -*/ +/* ibmtr.c: A shared-memory IBM Token Ring 16/4 driver for linux + * + * Written 1993 by Mark Swanson and Peter De Schrijver. + * This software may be used and distributed according to the terms + * of the GNU Public License, incorporated herein by reference. + * + * This device driver should work with Any IBM Token Ring Card that does + * not use DMA. + * + * I used Donald Becker's (becker@cesdis.gsfc.nasa.gov) device driver work + * as a base for most of my initial work. + * + * Changes by Peter De Schrijver (Peter.Deschrijver@linux.cc.kuleuven.ac.be) : + * + * + changed name to ibmtr.c in anticipation of other tr boards. + * + changed reset code and adapter open code. + * + added SAP open code. + * + a first attempt to write interrupt, transmit and receive routines. + * + * Changes by David W. Morris (dwm@shell.portal.com) : + * 941003 dwm: - Restructure tok_probe for multiple adapters, devices. + * + Add comments, misc reorg for clarity. + * + Flatten interrupt handler levels. + * + * Changes by Farzad Farid (farzy@zen.via.ecp.fr) + * and Pascal Andre (andre@chimay.via.ecp.fr) (March 9 1995) : + * + multi ring support clean up. + * + RFC1042 compliance enhanced. + * + * Changes by Pascal Andre (andre@chimay.via.ecp.fr) (September 7 1995) : + * + bug correction in tr_tx + * + removed redundant information display + * + some code reworking + * + * Changes by Michel Lespinasse (walken@via.ecp.fr), + * Yann Doussot (doussot@via.ecp.fr) and Pascal Andre (andre@via.ecp.fr) + * (February 18, 1996) : + * + modified shared memory and mmio access port the driver to + * alpha platform (structure access -> readb/writeb) + * + * Changes by Steve Kipisz (bungy@ibm.net or kipisz@vnet.ibm.com) + * (January 18 1996): + * + swapped WWOR and WWCR in ibmtr.h + * + moved some init code from tok_probe into trdev_init. The + * PCMCIA code can call trdev_init to complete initializing + * the driver. + * + added -DPCMCIA to support PCMCIA + * + detecting PCMCIA Card Removal in interrupt handler. If + * ISRP is FF, then a PCMCIA card has been removed + * + * Changes by Paul Norton (pnorton@cts.com) : + * + restructured the READ.LOG logic to prevent the transmit SRB + * from being rudely overwritten before the transmit cycle is + * complete. (August 15 1996) + * + completed multiple adapter support. (November 20 1996) + */ #ifdef PCMCIA #define MODULE @@ -89,18 +87,23 @@ static char *version = "ibmtr.c: v1.3.57 8/ 7/94 Peter De Schrijver and Mark Swanson\n" " v2.1.10 11/20/96 Paul Norton \n"; -static char pcchannelid[]={0x05, 0x00, 0x04, 0x09, - 0x04, 0x03, 0x04, 0x0f, - 0x03, 0x06, 0x03, 0x01, - 0x03, 0x01, 0x03, 0x00, - 0x03, 0x09, 0x03, 0x09, - 0x03, 0x00, 0x02, 0x00}; -static char mcchannelid[]={0x04, 0x0d, 0x04, 0x01, - 0x05, 0x02, 0x05, 0x03, - 0x03, 0x06, 0x03, 0x03, - 0x05, 0x08, 0x03, 0x04, - 0x03, 0x05, 0x03, 0x01, - 0x03, 0x08, 0x02, 0x00}; +static char pcchannelid[] = { + 0x05, 0x00, 0x04, 0x09, + 0x04, 0x03, 0x04, 0x0f, + 0x03, 0x06, 0x03, 0x01, + 0x03, 0x01, 0x03, 0x00, + 0x03, 0x09, 0x03, 0x09, + 0x03, 0x00, 0x02, 0x00 +}; + +static char mcchannelid[] = { + 0x04, 0x0d, 0x04, 0x01, + 0x05, 0x02, 0x05, 0x03, + 0x03, 0x06, 0x03, 0x03, + 0x05, 0x08, 0x03, 0x04, + 0x03, 0x05, 0x03, 0x01, + 0x03, 0x08, 0x02, 0x00 +}; #include #include @@ -130,11 +133,15 @@ static char mcchannelid[]={0x04, 0x0d, 0x04, 0x01, #if TR_NEWFORMAT /* this allows displaying full adapter information */ -const char *channel_def[] = { "ISA", "MCA", "ISA P&P" }; + +const char *channel_def[] = { + "ISA", "MCA", "ISA P&P" +}; char *adapter_def(char type) { - switch (type) { + switch (type) + { case 0xF : return "PC Adapter | PC Adapter II | Adapter/A"; case 0xE : return "16/4 Adapter | 16/4 Adapter/A (long)"; case 0xD : return "16/4 Adapter/A (short) | 16/4 ISA-16 Adapter"; @@ -153,42 +160,43 @@ unsigned char ibmtr_debug_trace=0; #define TRC_INIT 0x01 /* Trace initialization & PROBEs */ #define TRC_INITV 0x02 /* verbose init trace points */ -int ibmtr_probe(struct device *dev); -static int ibmtr_probe1(struct device *dev, int ioaddr); -unsigned char get_sram_size(struct tok_info *adapt_info); - -static int tok_init_card(struct device *dev); -int trdev_init(struct device *dev); -void tok_interrupt(int irq, void *dev_id, struct pt_regs *regs); - -static void initial_tok_int(struct device *dev); - -static void open_sap(unsigned char type,struct device *dev); -void tok_open_adapter(unsigned long dev_addr); -static void tr_rx(struct device *dev); -static void tr_tx(struct device *dev); - -static int tok_open(struct device *dev); -static int tok_close(struct device *dev); -static int tok_send_packet(struct sk_buff *skb, struct device *dev); +int ibmtr_probe(struct device *dev); +static int ibmtr_probe1(struct device *dev, int ioaddr); +unsigned char get_sram_size(struct tok_info *adapt_info); +static int tok_init_card(struct device *dev); +int trdev_init(struct device *dev); +void tok_interrupt(int irq, void *dev_id, struct pt_regs *regs); +static void initial_tok_int(struct device *dev); +static void open_sap(unsigned char type,struct device *dev); +void tok_open_adapter(unsigned long dev_addr); +static void tr_rx(struct device *dev); +static void tr_tx(struct device *dev); +static int tok_open(struct device *dev); +static int tok_close(struct device *dev); +static int tok_send_packet(struct sk_buff *skb, struct device *dev); static struct enet_statistics * tok_get_stats(struct device *dev); -void tr_readlog(struct device *dev); +void tr_readlog(struct device *dev); -static struct timer_list tr_timer={NULL,NULL,0,0L,tok_open_adapter}; -static unsigned int ibmtr_portlist[] = {0xa20, 0xa24, 0}; -static __u32 ibmtr_mem_base = 0xd0000; - -#if 0 -int DummyCallCount=0; +/* FIXME: Should use init_timer and friends not assume the structure + is constant! */ + +static struct timer_list tr_timer = +{ + NULL, + NULL, + 0, + 0L, + tok_open_adapter +}; -/* This routine combined with the #DEFINE DPRINTD serves - to workaround the gcc apparent bug. in tr_tx() */ +static unsigned int ibmtr_portlist[] = { + 0xa20, 0xa24, 0 +}; -static void DummyCall(const char * fmt,...) -{ DummyCallCount++; return; } -#endif +static __u32 ibmtr_mem_base = 0xd0000; -static void PrtChanID(char *pcid, short stride) { +static void PrtChanID(char *pcid, short stride) +{ short i, j; for (i=0, j=0; i<24; i++, j+=stride) printk("%1x", ((int) pcid[j]) & 0x0f); @@ -203,35 +211,44 @@ static void HWPrtChanID (__u32 pcid, short stride) printk("\n"); } -/* ibmtr_probe(): Routine specified in the network device structure - to probe for an IBM Token Ring Adapter. Routine outline: - I. Interrogate hardware to determine if an adapter exists - and what the speeds and feeds are - II. Setup data structures to control execution based upon - adapter characteristics. - III. Initialize adapter operation - We expect ibmtr_probe to be called once for each device entry - which references it. +/* + * ibmtr_probe(): Routine specified in the network device structure + * to probe for an IBM Token Ring Adapter. Routine outline: + * I. Interrogate hardware to determine if an adapter exists + * and what the speeds and feeds are + * II. Setup data structures to control execution based upon + * adapter characteristics. + * III. Initialize adapter operation + * + * We expect ibmtr_probe to be called once for each device entry + * which references it. */ + int ibmtr_probe(struct device *dev) { int i; int base_addr = dev ? dev->base_addr : 0; - if (base_addr > 0x1ff) { /* check a single specified location. */ - if (ibmtr_probe1(dev, base_addr)) { + if (base_addr > 0x1ff) + { + /* + * Check a single specified location. + */ + + if (ibmtr_probe1(dev, base_addr)) + { #ifndef MODULE tr_freedev(dev); #endif return -ENODEV; - } else { + } else return 0; - } } else if (base_addr != 0) /* Don't probe at all. */ return -ENXIO; - for (i = 0; ibmtr_portlist[i]; i++) { + for (i = 0; ibmtr_portlist[i]; i++) + { int ioaddr = ibmtr_portlist[i]; if (check_region(ioaddr, IBMTR_IO_EXTENT)) continue; @@ -239,9 +256,8 @@ int ibmtr_probe(struct device *dev) #ifndef MODULE tr_freedev(dev); #endif - } else { + } else return 0; - } } return -ENODEV; @@ -259,30 +275,44 @@ static int ibmtr_probe1(struct device *dev, int PIOaddr) dev = init_trdev(dev,0); #endif - /* Query the adapter PIO base port which will return - indication of where MMIO was placed. We also have a - coded interrupt number. */ + /* Query the adapter PIO base port which will return + * indication of where MMIO was placed. We also have a + * coded interrupt number. + */ segment = inb(PIOaddr); - /* out of range values so we'll assume non-existent IO device */ + + /* + * Out of range values so we'll assume non-existent IO device + */ + if (segment < 0x40 || segment > 0xe0) return -ENODEV; - /* Compute the linear base address of the MMIO area - as LINUX doesn't care about segments */ + /* + * Compute the linear base address of the MMIO area + * as LINUX doesn't care about segments + */ + t_mmio=(((__u32)(segment & 0xfc) << 11) + 0x80000); intr = segment & 0x03; /* low bits is coded interrupt # */ if (ibmtr_debug_trace & TRC_INIT) DPRINTK("PIOaddr: %4hx seg/intr: %2x mmio base: %08X intr: %d\n", PIOaddr, (int)segment, t_mmio, (int)intr); - /* Now we will compare expected 'channelid' strings with - what we is there to learn of ISA/MCA or not TR card */ + /* + * Now we will compare expected 'channelid' strings with + * what we is there to learn of ISA/MCA or not TR card + */ + cd_chanid = (CHANNEL_ID + t_mmio); /* for efficiency */ tchanid=pcchannelid; cardpresent=TR_ISA; /* try ISA */ - /* suboptimize knowing first byte different */ + /* + * Suboptimize knowing first byte different + */ + ctemp = readb(cd_chanid) & 0x0f; if (ctemp != *tchanid) { /* NOT ISA card, try MCA */ tchanid=mcchannelid; @@ -291,8 +321,13 @@ static int ibmtr_probe1(struct device *dev, int PIOaddr) cardpresent=NOTOK; } - if (cardpresent != NOTOK) { /* know presumed type, try rest of ID */ - for (i=2,j=1; i<=46; i=i+2,j++) { + if (cardpresent != NOTOK) + { + /* + * Know presumed type, try rest of ID + */ + for (i=2,j=1; i<=46; i=i+2,j++) + { if ((readb(cd_chanid+i) & 0x0f) != tchanid[j]) { cardpresent=NOTOK; /* match failed, not TR card */ break; @@ -300,8 +335,11 @@ static int ibmtr_probe1(struct device *dev, int PIOaddr) } } - /* If we have an ISA board check for the ISA P&P version, - as it has different IRQ settings */ + /* + * If we have an ISA board check for the ISA P&P version, + * as it has different IRQ settings + */ + if (cardpresent == TR_ISA && (readb(AIPFID + t_mmio)==0x0e)) cardpresent=TR_ISAPNP; @@ -317,7 +355,8 @@ static int ibmtr_probe1(struct device *dev, int PIOaddr) /* Now, allocate some of the pl0 buffers for this driver.. */ ti = (struct tok_info *)kmalloc(sizeof(struct tok_info), GFP_KERNEL); - if (ti == NULL) return -ENOMEM; + if (ti == NULL) + return -ENOMEM; memset(ti, 0, sizeof(struct tok_info)); @@ -330,39 +369,54 @@ static int ibmtr_probe1(struct device *dev, int PIOaddr) should fit with out future hope of multiple adapter support as well /dwm */ - switch (cardpresent) { - case TR_ISA: - if (intr==0) irq=9; /* irq2 really is irq9 */ - if (intr==1) irq=3; - if (intr==2) irq=6; - if (intr==3) irq=7; - ti->global_int_enable=GLOBAL_INT_ENABLE+((irq==9) ? 2 : irq); - ti->adapter_int_enable=PIOaddr+ADAPTINTREL; - ti->sram=0; + switch (cardpresent) + { + case TR_ISA: + if (intr==0) + irq=9; /* irq2 really is irq9 */ + if (intr==1) + irq=3; + if (intr==2) + irq=6; + if (intr==3) + irq=7; + ti->global_int_enable=GLOBAL_INT_ENABLE+((irq==9) ? 2 : irq); + ti->adapter_int_enable=PIOaddr+ADAPTINTREL; + ti->sram=0; #if !TR_NEWFORMAT - DPRINTK("ti->global_int_enable: %04X\n",ti->global_int_enable); + DPRINTK("ti->global_int_enable: %04X\n",ti->global_int_enable); #endif - break; - case TR_MCA: - if (intr==0) irq=9; - if (intr==1) irq=3; - if (intr==2) irq=10; - if (intr==3) irq=11; - ti->global_int_enable=0; - ti->adapter_int_enable=0; - ti->sram=((__u32)(inb(PIOaddr+ADAPTRESETREL) & 0xfe) << 12); - break; - case TR_ISAPNP: - if (intr==0) irq=9; - if (intr==1) irq=3; - if (intr==2) irq=10; - if (intr==3) irq=11; - while(!readb(ti->mmio + ACA_OFFSET + ACA_RW + RRR_EVEN)); - ti->sram=((__u32)readb(ti->mmio + ACA_OFFSET + ACA_RW + RRR_EVEN)<<12); - ti->global_int_enable=PIOaddr+ADAPTINTREL; - ti->adapter_int_enable=PIOaddr+ADAPTINTREL; - break; - + break; + case TR_MCA: + if (intr==0) + irq=9; + if (intr==1) + irq=3; + if (intr==2) + irq=10; + if (intr==3) + irq=11; + ti->global_int_enable=0; + ti->adapter_int_enable=0; + ti->sram=((__u32)(inb(PIOaddr+ADAPTRESETREL) & 0xfe) << 12); + break; + case TR_ISAPNP: + if (intr==0) + irq=9; + if (intr==1) + irq=3; + if (intr==2) + irq=10; + if (intr==3) + irq=11; + /* + * FIXME: this wait should have a timeout + */ + while(!readb(ti->mmio + ACA_OFFSET + ACA_RW + RRR_EVEN)); + ti->sram=((__u32)readb(ti->mmio + ACA_OFFSET + ACA_RW + RRR_EVEN)<<12); + ti->global_int_enable=PIOaddr+ADAPTINTREL; + ti->adapter_int_enable=PIOaddr+ADAPTINTREL; + break; } if (ibmtr_debug_trace & TRC_INIT) { /* just report int */ @@ -379,7 +433,8 @@ static int ibmtr_probe1(struct device *dev, int PIOaddr) DPRINTK("hw address: "); #endif j=0; - for (i=0; i<0x18; i=i+2) { + for (i=0; i<0x18; i=i+2) + { /* technical reference states to do this */ temp = readb(ti->mmio + AIP + i) & 0x0f; #if !TR_NEWFORMAT @@ -424,14 +479,17 @@ static int ibmtr_probe1(struct device *dev, int PIOaddr) ti->shared_ram_paging, ti->dhb_size4mb, ti->dhb_size16mb); #endif - /* We must figure out how much shared memory space this adapter - will occupy so that if there are two adapters we can fit both - in. Given a choice, we will limit this adapter to 32K. The - maximum space will will use for two adapters is 64K so if the - adapter we are working on demands 64K (it also doesn't support - paging), then only one adapter can be supported. */ - - /* determine how much of total RAM is mapped into PC space */ + /* We must figure out how much shared memory space this adapter + * will occupy so that if there are two adapters we can fit both + * in. Given a choice, we will limit this adapter to 32K. The + * maximum space will will use for two adapters is 64K so if the + * adapter we are working on demands 64K (it also doesn't support + * paging), then only one adapter can be supported. + */ + + /* + * determine how much of total RAM is mapped into PC space + */ ti->mapped_ram_size=1<<((((readb(ti->mmio+ ACA_OFFSET + ACA_RW + RRR_ODD)) >>2) & 0x03) + 4); ti->page_mask=0; if (ti->shared_ram_paging == 0xf) { /* No paging in adapter */ @@ -445,33 +503,34 @@ static int ibmtr_probe1(struct device *dev, int PIOaddr) DPRINTK("shared ram page size: %dK\n",ti->mapped_ram_size/2); #endif #ifdef ENABLE_PAGING - switch(ti->shared_ram_paging) { - case 0xf: - break; - case 0xe: - ti->page_mask=(ti->mapped_ram_size==32) ? 0xc0 : 0; - pg_size=32; /* 16KB page size */ - break; - case 0xd: - ti->page_mask=(ti->mapped_ram_size==64) ? 0x80 : 0; - pg_size=64; /* 32KB page size */ - break; - case 0xc: - ti->page_mask=(ti->mapped_ram_size==32) ? 0xc0 : 0; - ti->page_mask=(ti->mapped_ram_size==64) ? 0x80 : 0; - DPRINTK("Dual size shared RAM page (code=0xC), don't support it!\n"); - /* nb/dwm: I did this because RRR (3,2) bits are documented as - R/O and I can't find how to select which page size - Also, the above conditional statement sequence is invalid - as page_mask will always be set by the second stmt */ - kfree_s(ti, sizeof(struct tok_info)); - return -ENODEV; - break; - default: - DPRINTK("Unknown shared ram paging info %01X\n",ti->shared_ram_paging); - kfree_s(ti, sizeof(struct tok_info)); - return -ENODEV; - break; + switch(ti->shared_ram_paging) + { + case 0xf: + break; + case 0xe: + ti->page_mask=(ti->mapped_ram_size==32) ? 0xc0 : 0; + pg_size=32; /* 16KB page size */ + break; + case 0xd: + ti->page_mask=(ti->mapped_ram_size==64) ? 0x80 : 0; + pg_size=64; /* 32KB page size */ + break; + case 0xc: + ti->page_mask=(ti->mapped_ram_size==32) ? 0xc0 : 0; + ti->page_mask=(ti->mapped_ram_size==64) ? 0x80 : 0; + DPRINTK("Dual size shared RAM page (code=0xC), don't support it!\n"); + /* nb/dwm: I did this because RRR (3,2) bits are documented as + R/O and I can't find how to select which page size + Also, the above conditional statement sequence is invalid + as page_mask will always be set by the second stmt */ + kfree_s(ti, sizeof(struct tok_info)); + return -ENODEV; + break; + default: + DPRINTK("Unknown shared ram paging info %01X\n",ti->shared_ram_paging); + kfree_s(ti, sizeof(struct tok_info)); + return -ENODEV; + break; } if (ti->page_mask) { if (pg_size > ti->mapped_ram_size) { @@ -571,24 +630,22 @@ unsigned char get_sram_size(struct tok_info *adapt_info) int trdev_init(struct device *dev) { - struct tok_info *ti=(struct tok_info *)dev->priv; + struct tok_info *ti=(struct tok_info *)dev->priv; - ti->open_status=CLOSED; + ti->open_status = CLOSED; - dev->init=tok_init_card; - dev->open=tok_open; - dev->stop=tok_close; - dev->hard_start_xmit=tok_send_packet; - dev->get_stats = NULL; - dev->get_stats = tok_get_stats; - dev->set_multicast_list = NULL; + dev->init = tok_init_card; + dev->open = tok_open; + dev->stop = tok_close; + dev->hard_start_xmit = tok_send_packet; + dev->get_stats = NULL; + dev->get_stats = tok_get_stats; + dev->set_multicast_list = NULL; #ifndef MODULE - tr_setup(dev); + tr_setup(dev); #endif - - - return 0; + return 0; } @@ -670,7 +727,7 @@ void tok_interrupt (int irq, void *dev_id, struct pt_regs *regs) original solution. */ status=readb(ti->mmio + ACA_OFFSET + ACA_RW + ISRP_ODD); - #ifdef PCMCIA +#ifdef PCMCIA /* Check if the PCMCIA card was pulled. */ if (status == 0xFF) { @@ -680,13 +737,13 @@ void tok_interrupt (int irq, void *dev_id, struct pt_regs *regs) } /* Check ISRP EVEN too. */ - if ( *(unsigned char *)(ti->mmio + ACA_OFFSET + ACA_RW + ISRP_EVEN) == 0xFF) + if ( readb (ti->mmio + ACA_OFFSET + ACA_RW + ISRP_EVEN) == 0xFF) { DPRINTK("PCMCIA card removed.\n"); dev->interrupt = 0; return; } - #endif +#endif if (status & ADAP_CHK_INT) { @@ -706,7 +763,7 @@ void tok_interrupt (int irq, void *dev_id, struct pt_regs *regs) writeb(INT_ENABLE, ti->mmio + ACA_OFFSET + ACA_SET + ISRP_EVEN); dev->interrupt=0; - } else if (readb(ti->mmio + ACA_OFFSET + ACA_RW + ISRP_EVEN) + } else if (readb(ti->mmio + ACA_OFFSET + ACA_RW + ISRP_EVEN) & (TCR_INT | ERR_INT | ACCESS_INT)) { DPRINTK("adapter error: ISRP_EVEN : %02x\n", @@ -774,15 +831,21 @@ void tok_interrupt (int irq, void *dev_id, struct pt_regs *regs) if (open_ret_code==7) { if (!ti->auto_ringspeedsave && (open_error_code==0x24)) { - DPRINTK("open failed: Adapter speed must match ring " - "speed if Automatic Ring Speed Save is disabled\n"); + DPRINTK("Open failed: Adapter speed must match ring " + "speed if Automatic Ring Speed Save is disabled.\n"); ti->open_status=FAILURE; wake_up(&ti->wait_for_reset); } else if (open_error_code==0x24) - DPRINTK("retrying open to adjust to ring speed\n"); + DPRINTK("Retrying open to adjust to ring speed.\n"); else if ((open_error_code==0x2d) && ti->auto_ringspeedsave) - DPRINTK("No signal detected for Auto Speed Detection\n"); - else DPRINTK("Unrecoverable error: error code = %04x\n", + DPRINTK("No signal detected for Auto Speed Detection.\n"); + else if (open_error_code==0x11) + { + ti->open_status=FAILURE; + DPRINTK("Ring broken/disconnected.\n"); + wake_up(&ti->wait_for_reset); + } + else DPRINTK("Unrecoverable error: error code = %04x.\n", open_error_code); } else if (!open_ret_code) { diff --git a/drivers/net/lance.c b/drivers/net/lance.c index b8bb6ac9be7f..3104e1de9660 100644 --- a/drivers/net/lance.c +++ b/drivers/net/lance.c @@ -309,7 +309,7 @@ int lance_init(void) { int *port; - if (high_memory <= 16*1024*1024) + if (virt_to_bus(high_memory) <= 16*1024*1024) lance_need_isa_bounce_buffers = 0; #if defined(CONFIG_PCI) diff --git a/drivers/net/lapbether.c b/drivers/net/lapbether.c index 37eb26e65323..40e1c44a5786 100644 --- a/drivers/net/lapbether.c +++ b/drivers/net/lapbether.c @@ -48,12 +48,8 @@ #include #include -#include - static char bcast_addr[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; -static char lapbeth_eth_addr[6]; - static int lapbeth_rcv(struct sk_buff *, struct device *, struct packet_type *); static int lapbeth_device_event(struct notifier_block *, unsigned long, void *); @@ -79,8 +75,6 @@ static struct lapbethdev { struct device *ethdev; /* link to ethernet device */ struct device axdev; /* lapbeth device (lapb#) */ struct enet_statistics stats; /* some statistics */ - char dest_addr[6]; /* ether destination address */ - char acpt_addr[6]; /* accept ether frames from this address only */ } *lapbeth_devices = NULL; @@ -171,7 +165,6 @@ static int lapbeth_check_devices(struct device *dev) static int lapbeth_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *ptype) { int len, err; - struct ethhdr *eth = (struct ethhdr *)skb->mac.raw; struct lapbethdev *lapbeth; skb->sk = NULL; /* Initially we don't know who it's for */ @@ -183,20 +176,9 @@ static int lapbeth_rcv(struct sk_buff *skb, struct device *dev, struct packet_ty return 0; } - /* - * if we want to accept frames from just one ethernet device - * we check the source address of the sender. - */ - lapbeth = (struct lapbethdev *)dev->priv; - if (!(lapbeth->acpt_addr[0] & 0x01) && memcmp(eth->h_source, lapbeth->acpt_addr, ETH_ALEN)) { - printk(KERN_DEBUG "lapbeth: wrong dest address\n"); - kfree_skb(skb, FREE_READ); - return 0; - } - - ((struct lapbethdev *)dev->priv)->stats.rx_packets++; + lapbeth->stats.rx_packets++; len = skb->data[0] + skb->data[1] * 256; @@ -296,7 +278,7 @@ static void lapbeth_data_transmit(void *token, struct sk_buff *skb) skb->dev = dev = lapbeth->ethdev; - dev->hard_header(skb, dev, ETH_P_DEC, lapbeth->dest_addr, NULL, 0); + dev->hard_header(skb, dev, ETH_P_DEC, bcast_addr, NULL, 0); dev->hard_start_xmit(skb, dev); } @@ -369,37 +351,9 @@ static int lapbeth_set_mac_address(struct device *dev, void *addr) return 0; } -/* Ioctl commands - * - * SIOCSLAPBETHADDR set the destination and accepted - * source ethernet address (broadcast - * or multicast: accept all) - */ static int lapbeth_ioctl(struct device *dev, struct ifreq *ifr, int cmd) { - int err; - struct lapbeth_ethaddr *ethaddr = (struct lapbeth_ethaddr *)ifr->ifr_data; - struct lapbethdev *lapbeth = dev->priv; - - if (!suser()) - return -EPERM; - - if (lapbeth == NULL) /* woops! */ - return -ENODEV; - - switch (cmd) { - case SIOCSLAPBETHADDR: - if ((err = verify_area(VERIFY_READ, ethaddr, sizeof(struct lapbeth_ethaddr))) != 0) - return err; - copy_from_user(lapbeth->dest_addr, ethaddr->destination, ETH_ALEN); - copy_from_user(lapbeth->acpt_addr, ethaddr->accept, ETH_ALEN); - break; - - default: - return -EINVAL; - } - - return 0; + return -EINVAL; } /* @@ -482,9 +436,6 @@ static int lapbeth_new_device(struct device *dev) lapbeth->ethname[sizeof(lapbeth->ethname)-1] = '\0'; strncpy(lapbeth->ethname, dev->name, sizeof(lapbeth->ethname)-1); - memcpy(lapbeth->dest_addr, bcast_addr, sizeof(lapbeth_eth_addr)); - memcpy(lapbeth->acpt_addr, bcast_addr, sizeof(lapbeth_eth_addr)); - dev = &lapbeth->axdev; buf = (unsigned char *)kmalloc(14, GFP_KERNEL); diff --git a/drivers/net/net_init.c b/drivers/net/net_init.c index 3a8d48b10fdb..37987960b00b 100644 --- a/drivers/net/net_init.c +++ b/drivers/net/net_init.c @@ -38,9 +38,7 @@ #include #include #include -#ifdef CONFIG_NET_ALIAS #include -#endif /* The network devices currently exist only in the socket namespace, so these entries are unused. The only ones that make sense are @@ -304,6 +302,7 @@ int register_netdev(struct device *dev) else dev_base = dev; dev->next = NULL; + dev->ifindex = dev_new_index(); } restore_flags(flags); return 0; diff --git a/drivers/net/pi2.c b/drivers/net/pi2.c index 498ff4b6ce75..0dd7b5d46a43 100644 --- a/drivers/net/pi2.c +++ b/drivers/net/pi2.c @@ -1283,7 +1283,6 @@ static int pi_probe(struct device *dev, int card_type) { short ioaddr; struct pi_local *lp; - int i; unsigned long flags; unsigned long mem_ptr; @@ -1401,7 +1400,7 @@ static int pi_probe(struct device *dev, int card_type) /* Fill in the fields of the device structure */ - dev_init_buffers(dev): + dev_init_buffers(dev); #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) dev->hard_header = ax25_encapsulate; diff --git a/drivers/net/ppp.c b/drivers/net/ppp.c index 10244b7e6616..3f21195e6447 100644 --- a/drivers/net/ppp.c +++ b/drivers/net/ppp.c @@ -388,8 +388,6 @@ ppp_first_time (void) static int ppp_init_dev (struct device *dev) { - int indx; - dev->hard_header_len = PPP_HARD_HDR_LEN; /* device INFO */ @@ -3354,6 +3352,8 @@ static struct compressor *find_compressor (int type) return (struct compressor *) 0; } +#ifdef CONFIG_MODULES + static int ppp_register_compressor (struct compressor *cp) { struct compressor_link *new; @@ -3406,6 +3406,8 @@ static void ppp_unregister_compressor (struct compressor *cp) restore_flags(flags); } +#endif + /************************************************************* * Module support routines *************************************************************/ diff --git a/drivers/net/scc.c b/drivers/net/scc.c index 8e1a465bbc4b..0dfb7c623d55 100644 --- a/drivers/net/scc.c +++ b/drivers/net/scc.c @@ -1,4 +1,4 @@ -#define RCS_ID "$Id: scc.c,v 1.64 1996/10/30 18:58:26 jreuter Exp jreuter $" +#define RCS_ID "$Id: scc.c,v 1.66 1997/01/08 22:56:06 jreuter Exp jreuter $" #define VERSION "3.0" #define BANNER "Z8530 SCC driver version "VERSION".dl1bke (experimental) by DL1BKE\n" @@ -83,9 +83,10 @@ * Invents brand new bugs... ;-) The move to version number 3.0 reflects theses changes. - You can use version 2.4a if you need a KISS TNC emulator. + You can use 'kissbridge' if you need a KISS TNC emulator. - 961213 - Fixed for Linux networking changes. + 961213 - Fixed for Linux networking changes. (G4KLX) + 960108 - Fixed the remaining problems. Thanks to all who contributed to this driver with ideas and bug reports! @@ -202,7 +203,6 @@ static void scc_net_rx(struct scc_channel *scc, struct sk_buff *skb); static int scc_net_tx(struct sk_buff *skb, struct device *dev); static int scc_net_ioctl(struct device *dev, struct ifreq *ifr, int cmd); static int scc_net_set_mac_address(struct device *dev, void *addr); -static int scc_net_rebuild_header(void *buff, struct device *dev, unsigned long raddr, struct sk_buff *skb); static int scc_net_header(struct sk_buff *skb, struct device *dev, unsigned short type, void *daddr, void *saddr, unsigned len); static struct enet_statistics * scc_net_get_stats(struct device *dev); @@ -347,7 +347,6 @@ extern __inline__ void scc_notify(struct scc_channel *scc, int event) skb = dev_alloc_skb(2); if (skb != NULL) { - skb->free = 1; bp = skb_put(skb, 2); *bp++ = PARAM_HWEVENT; *bp++ = event; @@ -548,9 +547,7 @@ extern __inline__ void scc_rxint(struct scc_channel *scc) return; } - skb->free = 1; scc->rx_buff = skb; - *(skb_put(skb, 1)) = 0; /* KISS data */ } @@ -1540,7 +1537,7 @@ static int scc_net_init(struct device *dev) dev->hard_start_xmit = scc_net_tx; dev->hard_header = scc_net_header; - dev->rebuild_header = scc_net_rebuild_header; + dev->rebuild_header = ax25_rebuild_header; dev->set_mac_address = scc_net_set_mac_address; dev->get_stats = scc_net_get_stats; dev->do_ioctl = scc_net_ioctl; @@ -1969,13 +1966,6 @@ static int scc_net_set_mac_address(struct device *dev, void *addr) return 0; } -/* ----> rebuild header <---- */ - -static int scc_net_rebuild_header(struct sk_buff *skb) -{ - return ax25_rebuild_header(skb); -} - /* ----> "hard" header <---- */ static int scc_net_header(struct sk_buff *skb, struct device *dev, diff --git a/drivers/net/smc-mca.c b/drivers/net/smc-mca.c index b2721cfa99ab..3188c8240bad 100644 --- a/drivers/net/smc-mca.c +++ b/drivers/net/smc-mca.c @@ -74,7 +74,10 @@ int ultramca_probe(struct device *dev) unsigned char pos2, pos3, pos4, pos5; int i; - if( (slot=mca_find_adapter(0x61c8,0)) != MCA_NOTFOUND) + /* Look for two flavors of SMC Elite/A (3013EP/A) -jeh- */ + if(( (slot=mca_find_adapter(0x61c8,0)) != MCA_NOTFOUND) || + ((slot=mca_find_adapter(0xefd5,0)) != MCA_NOTFOUND) ) + { #ifndef MODULE mca_set_adapter_name( slot, "SMC Elite/A (8013EP/A)" ); diff --git a/drivers/net/strip.c b/drivers/net/strip.c index 3f420d1734a3..47517b1e15fb 100644 --- a/drivers/net/strip.c +++ b/drivers/net/strip.c @@ -1,3 +1,5 @@ +#error "Doesn't run with 2.1.x" + /* * Copyright 1996 The Board of Trustees of The Leland Stanford * Junior University. All Rights Reserved. @@ -1804,17 +1806,16 @@ static int strip_header(struct sk_buff *skb, struct device *dev, * or non-zero if it needs more time to do an address lookup */ -static int strip_rebuild_header(void *buff, struct device *dev, - unsigned long dst, struct sk_buff *skb) +static int strip_rebuild_header(struct sk_buff *skb) { - STRIP_Header *header = (STRIP_Header *)buff; + STRIP_Header *header = (STRIP_Header *)skb->data; - /*printk(KERN_INFO "%s: strip_rebuild_header\n", dev->name);*/ + /*printk(KERN_INFO "%s: strip_rebuild_header\n", skb->dev->name);*/ #ifdef CONFIG_INET /* Arp find returns zero if if knows the address, */ /* or if it doesn't know the address it sends an ARP packet and returns non-zero */ - return arp_find(header->dst_addr.c, dst, dev, dev->pa_addr, skb)? 1 : 0; + return arp_find(header->dst_addr.c, skb)? 1 : 0; #else return 0; #endif diff --git a/drivers/net/tunnel.c b/drivers/net/tunnel.c index 55c14db31c4d..30cea81967e0 100644 --- a/drivers/net/tunnel.c +++ b/drivers/net/tunnel.c @@ -122,7 +122,6 @@ static int tunnel_xmit(struct sk_buff *skb, struct device *dev) { struct enet_statistics *stats; /* This device's statistics */ struct rtable *rt; /* Route to the other host */ - struct hh_cache *hh; struct device *tdev; /* Device to other host */ struct iphdr *iph; /* Our new IP header */ int max_headroom; /* The extra header space needed */ @@ -143,7 +142,6 @@ static int tunnel_xmit(struct sk_buff *skb, struct device *dev) return 0; } tdev = rt->u.dst.dev; - hh = rt->u.dst.hh; if (tdev->type == ARPHRD_TUNNEL) { /* Tunnel to tunnel? -- I don't think so. */ @@ -161,7 +159,7 @@ static int tunnel_xmit(struct sk_buff *skb, struct device *dev) */ max_headroom = (((tdev->hard_header_len+15)&~15)+tunnel_hlen); - if (skb_headroom(skb) < max_headroom || skb->users != 1) { + if (skb_headroom(skb) < max_headroom || skb_shared(skb)) { struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom); if (!new_skb) { ip_rt_put(rt); diff --git a/drivers/net/wavelan.c b/drivers/net/wavelan.c index b6f6d3ada4c8..81749fa9c0e0 100644 --- a/drivers/net/wavelan.c +++ b/drivers/net/wavelan.c @@ -4017,8 +4017,8 @@ wavelan_config(device * dev) * We follow the example in drivers/net/ne.c.) * (called in "Space.c") */ -extern int -wavelan_probe(device * dev) + +int wavelan_probe(device * dev) { short base_addr; mac_addr mac; /* Mac address (check wavelan existence) */ diff --git a/drivers/net/wic.c b/drivers/net/wic.c index 894128ade859..dce1bb3f2a0e 100644 --- a/drivers/net/wic.c +++ b/drivers/net/wic.c @@ -920,7 +920,7 @@ int wic_rebuild_header(struct sk_buff *skb) for (i=0; i < ETH_ALEN - sizeof(unsigned long); i++) eth->h_dest[i] = 0xfc; - memcpy(&(eth->h_dest[i]), &dst, sizeof(unsigned long)); + memcpy(&(eth->h_dest[i]), &skb->daddr, 4); return 0; } diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 378f33ddd89a..b053aaf431cb 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -72,6 +72,7 @@ struct pci_dev_info dev_info[] = { DEVICE( DEC, DEC_TULIP_PLUS, "DC21041"), DEVICE( DEC, DEC_21052, "DC21052"), DEVICE( DEC, DEC_21152, "DC21152"), + DEVICE( CIRRUS, CIRRUS_7548, "GD 7548"), DEVICE( CIRRUS, CIRRUS_5430, "GD 5430"), DEVICE( CIRRUS, CIRRUS_5434_4, "GD 5434"), DEVICE( CIRRUS, CIRRUS_5434_8, "GD 5434"), @@ -158,6 +159,7 @@ struct pci_dev_info dev_info[] = { DEVICE( AL, AL_M1511, "M1511"), DEVICE( AL, AL_M1513, "M1513"), DEVICE( AL, AL_M4803, "M4803"), + DEVICE( NEOMAGIC, NEOMAGIC_MAGICGRAPH_NM2070, "Magicgraph NM2070"), DEVICE( ASP, ASP_ABP940, "ABP940"), DEVICE( CERN, CERN_SPSB_PMC, "STAR/RD24 SCI-PCI (PMC)"), DEVICE( CERN, CERN_SPSB_PCI, "STAR/RD24 SCI-PCI (PMC)"), @@ -165,6 +167,7 @@ struct pci_dev_info dev_info[] = { DEVICE( TEKRAM2, TEKRAM2_690c, "DC690c"), DEVICE( AMCC, AMCC_MYRINET, "Myrinet PCI (M2-PCI-32)"), DEVICE( INTERG, INTERG_1680, "IGA-1680"), + DEVICE( INTERG, INTERG_1682, "IGA-1682"), DEVICE( REALTEK, REALTEK_8029, "8029"), DEVICE( INIT, INIT_320P, "320 P"), DEVICE( VIA, VIA_82C505, "VT 82C505"), @@ -242,6 +245,8 @@ struct pci_dev_info dev_info[] = { DEVICE( INTEL, INTEL_82437, "82437"), DEVICE( INTEL, INTEL_82371_0, "82371 Triton PIIX"), DEVICE( INTEL, INTEL_82371_1, "82371 Triton PIIX"), + DEVICE( INTEL, INTEL_430MX_0, "Triton I"), + DEVICE( INTEL, INTEL_430MX_1, "Triton I"), DEVICE( INTEL, INTEL_82441, "82441FX Natoma"), DEVICE( INTEL, INTEL_82439, "82439HX Triton II"), DEVICE( INTEL, INTEL_82371SB_0,"82371SB Natoma/Triton II PIIX3"), @@ -506,6 +511,7 @@ const char *pci_strvendor(unsigned int vendor) case PCI_VENDOR_ID_WINBOND: return "Winbond"; case PCI_VENDOR_ID_3COM: return "3Com"; case PCI_VENDOR_ID_AL: return "Acer Labs"; + case PCI_VENDOR_ID_NEOMAGIC: return "Neomagic"; case PCI_VENDOR_ID_ASP: return "Advanced System Products"; case PCI_VENDOR_ID_CERN: return "CERN"; case PCI_VENDOR_ID_IMS: return "IMS"; diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 863a782c1696..e20baf99e0c1 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -77,7 +77,7 @@ extern int sd_ioctl(struct inode *, struct file *, unsigned int, unsigned long); static int check_scsidisk_media_change(kdev_t); static int fop_revalidate_scsidisk(kdev_t); -static sd_init_onedisk(int); +static int sd_init_onedisk(int); static void requeue_sd_request (Scsi_Cmnd * SCpnt); diff --git a/fs/dquot.c b/fs/dquot.c index aa3c5e517a20..7720af505b2a 100644 --- a/fs/dquot.c +++ b/fs/dquot.c @@ -586,7 +586,6 @@ static int set_dqblk(kdev_t dev, int id, short type, int flags, struct dqblk *dq { struct dquot *dquot; struct dqblk dq_dqblk; - int error; if (dqblk == (struct dqblk *)NULL) return(-EFAULT); @@ -660,8 +659,6 @@ static int get_quota(kdev_t dev, int id, short type, struct dqblk *dqblk) static int get_stats(caddr_t addr) { - int error; - dqstats.allocated_dquots = nr_dquots; dqstats.free_dquots = nr_free_dquots; return copy_to_user(addr, (caddr_t)&dqstats, sizeof(struct dqstats)) diff --git a/fs/ext2/symlink.c b/fs/ext2/symlink.c index fca0f7923c00..ef4dd5226da1 100644 --- a/fs/ext2/symlink.c +++ b/fs/ext2/symlink.c @@ -124,11 +124,11 @@ static int ext2_readlink (struct inode * inode, char * buffer, int buflen) link = (char *) inode->u.ext2_i.i_data; /* XXX I hope link is always '\0'-terminated. */ - i = strlen(link)+1; - if (i > buflen) - i = buflen; - if (copy_to_user(buffer, link, i)) - i = -EFAULT; + i = strlen(link); + if (i >= buflen) + i = buflen-1; + if (copy_to_user(buffer, link, i+1)) + i = -EFAULT; if (DO_UPDATE_ATIME(inode)) { inode->i_atime = CURRENT_TIME; inode->i_dirt = 1; diff --git a/fs/fat/misc.c b/fs/fat/misc.c index ce8dde69a5b8..092823bad96a 100644 --- a/fs/fat/misc.c +++ b/fs/fat/misc.c @@ -77,7 +77,7 @@ int is_binary(char conversion,char *extension) /* (rename might deadlock before detecting cross-FS moves.) */ static struct wait_queue *creation_wait = NULL; -static creation_lock = 0; +static int creation_lock = 0; void fat_lock_creation(void) diff --git a/fs/namei.c b/fs/namei.c index b969615eee88..3523ceaed2ec 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -17,6 +17,7 @@ #include #include +#include #define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE]) @@ -162,7 +163,7 @@ int lookup(struct inode * dir,const char * name, int len, return -ENOENT; /* check permissions before traversing mount-points */ perm = permission(dir,MAY_EXEC); - if (len==2 && name[0] == '.' && name[1] == '.') { + if (len==2 && get_unaligned((u16 *) name) == 0x2e2e) { if (dir == current->fs->root) { *result = dir; return 0; @@ -215,7 +216,7 @@ int follow_link(struct inode * dir, struct inode * inode, static int dir_namei(const char *pathname, int *namelen, const char **name, struct inode * base, struct inode **res_inode) { - char c; + unsigned char c; const char * thisname; int len,error; struct inode * inode; diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c index a6ddf3fbd687..180f4e9e9928 100644 --- a/fs/ncpfs/inode.c +++ b/fs/ncpfs/inode.c @@ -552,11 +552,8 @@ int init_ncp_fs(void) #ifdef MODULE EXPORT_NO_SYMBOLS; -int -init_module( void) +int init_module( void) { - int status; - DPRINTK("ncpfs: init_module called\n"); #ifdef DEBUG_NCP_MALLOC diff --git a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c index bbc17c28f1f5..e39a471d2ba3 100644 --- a/fs/nfs/nfsroot.c +++ b/fs/nfs/nfsroot.c @@ -154,11 +154,6 @@ static int nfs_port; /* Port to connect to for NFS */ /* Yes, we use sys_socket, but there's no include file for it */ extern asmlinkage int sys_socket(int family, int type, int protocol); -extern void fib_lock(void); -extern void fib_unlock(void); -extern int rtmsg_process(struct nlmsghdr *n, struct in_rtmsg *r); -extern unsigned long ip_get_mask(unsigned long addr); - /*************************************************************************** Device Handling Subroutines @@ -182,13 +177,12 @@ static int root_dev_open(void) !(dev->flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) && (0 != strncmp(dev->name, "dummy", 5)) && (!user_dev_name[0] || !strcmp(dev->name, user_dev_name))) { - /* First up the interface */ + struct ifreq ifr; old_flags = dev->flags; - dev->flags = IFF_UP | IFF_BROADCAST | IFF_RUNNING; - if (!(old_flags & IFF_UP) && dev_open(dev)) { - dev->flags = old_flags; + strncpy(ifr.ifr_name, dev->name, IFNAMSIZ); + ifr.ifr_flags = old_flags | IFF_UP | IFF_RUNNING; + if (dev_ioctl(SIOCSIFFLAGS, &ifr) < 0) continue; - } openp = (struct open_dev *) kmalloc(sizeof(struct open_dev), GFP_ATOMIC); if (openp == NULL) @@ -229,9 +223,10 @@ static void root_dev_close(void) nextp = openp->next; openp->next = NULL; if (openp->dev != root_dev) { - if (!(openp->old_flags & IFF_UP)) - dev_close(openp->dev); - openp->dev->flags = openp->old_flags; + struct ifreq ifr; + strncpy(ifr.ifr_name, openp->dev->name, IFNAMSIZ); + ifr.ifr_flags = openp->old_flags; + dev_ioctl(SIOCSIFFLAGS, &ifr); } kfree_s(openp, sizeof(struct open_dev)); openp = nextp; @@ -467,20 +462,22 @@ static inline int root_alloc_bootp(void) */ static int root_add_bootp_route(void) { - struct nlmsghdr dummy_nlh; - struct in_rtmsg rtm; + struct { + struct nlmsghdr nlh; + struct in_rtmsg rtm; + } rtreq; int err; - - memset(&rtm, 0, sizeof(struct in_rtmsg)); - dummy_nlh.nlmsg_seq = 0; - dummy_nlh.nlmsg_pid = current->pid; - dummy_nlh.nlmsg_type = RTMSG_NEWROUTE; - memcpy(&rtm.rtmsg_device, bootp_dev->name, 15); - rtm.rtmsg_mtu = bootp_dev->mtu; - rtm.rtmsg_flags = RTF_UP; - fib_lock(); - err = rtmsg_process(&dummy_nlh, &rtm); - fib_unlock(); + unsigned short fs; + + memset(&rtreq, 0, sizeof(rtreq)); + rtreq.nlh.nlmsg_type = RTMSG_NEWROUTE; + rtreq.nlh.nlmsg_len = sizeof(rtreq); + rtreq.rtm.rtmsg_ifindex = bootp_dev->ifindex; + rtreq.rtm.rtmsg_flags = RTF_UP; + fs = get_fs(); + set_fs(get_ds()); + err = ip_rt_ioctl(SIOCRTMSG, &rtreq); + set_fs(fs); if (err) { printk(KERN_ERR "BOOTP: Adding of route failed!\n"); return -1; @@ -495,19 +492,24 @@ static int root_add_bootp_route(void) */ static int root_del_bootp_route(void) { - struct nlmsghdr dummy_nlh; - struct in_rtmsg rtm; + struct { + struct nlmsghdr nlh; + struct in_rtmsg rtm; + } rtreq; int err; + unsigned short fs; if (!bootp_have_route) return 0; - memset(&rtm, 0, sizeof(struct in_rtmsg)); - dummy_nlh.nlmsg_seq = 0; - dummy_nlh.nlmsg_pid = current->pid; - dummy_nlh.nlmsg_type = RTMSG_DELROUTE; - fib_lock(); - err = rtmsg_process(&dummy_nlh, &rtm); - fib_unlock(); + memset(&rtreq, 0, sizeof(rtreq)); + rtreq.nlh.nlmsg_type = RTMSG_DELROUTE; + rtreq.nlh.nlmsg_len = sizeof(rtreq); + rtreq.rtm.rtmsg_ifindex = bootp_dev->ifindex; + rtreq.rtm.rtmsg_flags = RTF_UP; + fs = get_fs(); + set_fs(get_ds()); + err = ip_rt_ioctl(SIOCRTMSG, &rtreq); + set_fs(fs); if (err) { printk(KERN_ERR "BOOTP: Deleting of route failed!\n"); return -1; @@ -596,6 +598,8 @@ static inline int root_send_udp(struct socket *sock, void *buf, int size) msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_flags = 0; result = sock_sendmsg(sock, &msg, size); set_fs(oldfs); return (result != size); @@ -620,6 +624,7 @@ static inline int root_recv_udp(struct socket *sock, void *buf, int size) msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_control = NULL; + msg.msg_controllen = 0; msg.msg_namelen = 0; result = sock_recvmsg(sock, &msg, size, MSG_DONTWAIT); set_fs(oldfs); @@ -1286,14 +1291,36 @@ static void root_nfs_addrs(char *addrs) rarp_serv = server; } +static int root_nfs_add_default_route(struct in_addr gw, struct device *dev) +{ + unsigned short fs; + int err; + struct { + struct nlmsghdr nlh; + struct in_rtmsg rtm; + } rtreq; + + memset(&rtreq, 0, sizeof(rtreq)); + rtreq.nlh.nlmsg_type = RTMSG_NEWROUTE; + rtreq.nlh.nlmsg_len = sizeof(rtreq); + + rtreq.rtm.rtmsg_ifindex = dev->ifindex; + rtreq.rtm.rtmsg_flags = RTF_UP|RTF_GATEWAY; + rtreq.rtm.rtmsg_gateway = gw; + fs = get_fs(); + set_fs(get_ds()); + err = ip_rt_ioctl(SIOCRTMSG, &rtreq); + set_fs(fs); + return err; +} /* * Set the interface address and configure a route to the server. */ static int root_nfs_setup(void) { - struct in_rtmsg rtm; - struct nlmsghdr dummy_nlh; + unsigned short fs; + struct ifreq ifr; int err; /* Set the default system name in case none was previously found */ @@ -1302,16 +1329,21 @@ static int root_nfs_setup(void) system_utsname.nodename[__NEW_UTS_LEN] = '\0'; } - /* Set the correct netmask */ - if (netmask.sin_addr.s_addr == INADDR_NONE) - netmask.sin_addr.s_addr = ip_get_mask(myaddr.sin_addr.s_addr); - - /* Setup the device correctly */ - root_dev->family = myaddr.sin_family; - root_dev->pa_addr = myaddr.sin_addr.s_addr; - root_dev->pa_mask = netmask.sin_addr.s_addr; - root_dev->pa_brdaddr = root_dev->pa_addr | ~root_dev->pa_mask; - root_dev->pa_dstaddr = 0; + fs = get_fs(); + set_fs(get_ds()); + strncpy(ifr.ifr_name, root_dev->name, IFNAMSIZ); + memcpy(&ifr.ifr_addr, &myaddr, sizeof(myaddr)); + devinet_ioctl(SIOCSIFADDR, &ifr); + if (netmask.sin_addr.s_addr != INADDR_NONE && + netmask.sin_addr.s_addr != root_dev->pa_mask) { + memcpy(&ifr.ifr_netmask, &netmask, sizeof(netmask)); + devinet_ioctl(SIOCSIFNETMASK, &ifr); + memcpy(&ifr.ifr_broadaddr, &netmask, sizeof(netmask)); + ((struct sockaddr_in*)&ifr.ifr_broadaddr)->sin_addr.s_addr = + root_dev->pa_addr | ~root_dev->pa_mask; + devinet_ioctl(SIOCSIFBRDADDR, &ifr); + } + set_fs(fs); /* * Now add a route to the server. If there is no gateway given, @@ -1321,36 +1353,9 @@ static int root_nfs_setup(void) * gatewayed default route. Note that this gives sufficient network * setup even for full system operation in all common cases. */ - dummy_nlh.nlmsg_seq = 0; - dummy_nlh.nlmsg_pid = current->pid; - dummy_nlh.nlmsg_type = RTMSG_NEWROUTE; - - memset(&rtm, 0, sizeof(struct in_rtmsg)); /* Local subnet route */ - memcpy(&rtm.rtmsg_device, root_dev->name, 15); - rtm.rtmsg_mtu = root_dev->mtu; - rtm.rtmsg_flags = RTF_UP; - rtm.rtmsg_prefixlen = (32 - ffz(~(netmask.sin_addr.s_addr))); - rtm.rtmsg_prefix = myaddr.sin_addr; - fib_lock(); - err = rtmsg_process(&dummy_nlh, &rtm); - fib_unlock(); - if (err) { - printk(KERN_ERR "Root-NFS: Adding of local route failed!\n"); - return -1; - } if (gateway.sin_addr.s_addr != INADDR_NONE) { /* Default route */ - rtm.rtmsg_prefix.s_addr = INADDR_ANY; - rtm.rtmsg_prefixlen = 32; - rtm.rtmsg_gateway = gateway.sin_addr; - rtm.rtmsg_flags |= RTF_GATEWAY; - if ((gateway.sin_addr.s_addr ^ myaddr.sin_addr.s_addr) & netmask.sin_addr.s_addr) { - printk(KERN_ERR "Root-NFS: Gateway not on local network!\n"); - return -1; - } - fib_lock(); - err = rtmsg_process(&dummy_nlh, &rtm); - fib_unlock(); + err = root_nfs_add_default_route(gateway.sin_addr, root_dev); if (err) { printk(KERN_ERR "Root-NFS: Adding of default route failed!\n"); return -1; diff --git a/fs/nfs/rpcsock.c b/fs/nfs/rpcsock.c index e5021d940221..d3415041bffe 100644 --- a/fs/nfs/rpcsock.c +++ b/fs/nfs/rpcsock.c @@ -361,6 +361,9 @@ rpc_grok(struct rpc_sock *rsock) if (result < 4) { printk(KERN_WARNING "RPC: impossible RPC reply size %d\n", result); + iov[0].iov_base=(void*)&xid; /* xid=32bits, which is large enough */ + iov[0].iov_len=result; + rpc_recvmsg(rsock, iov, 1, result, 0); return 0; } diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c index a8227ba51d00..efc5a7f30865 100644 --- a/fs/smbfs/inode.c +++ b/fs/smbfs/inode.c @@ -444,8 +444,6 @@ EXPORT_NO_SYMBOLS; int init_module(void) { - int status; - DPRINTK("smbfs: init_module called\n"); #ifdef DEBUG_SMB_MALLOC diff --git a/include/asm-alpha/semaphore.h b/include/asm-alpha/semaphore.h index 210c2a5b3501..d6ed29385627 100644 --- a/include/asm-alpha/semaphore.h +++ b/include/asm-alpha/semaphore.h @@ -11,7 +11,7 @@ struct semaphore { atomic_t count; - atomic_t waiting; + atomic_t waking; struct wait_queue * wait; }; @@ -19,6 +19,7 @@ struct semaphore { #define MUTEX_LOCKED ((struct semaphore) { 0, 0, NULL }) extern void __down(struct semaphore * sem); +extern int __down_interruptible(struct semaphore * sem); extern void __up(struct semaphore * sem); /* @@ -27,11 +28,16 @@ extern void __up(struct semaphore * sem); */ extern inline void down(struct semaphore * sem) { - for (;;) { - if (atomic_dec_return(&sem->count) >= 0) - break; + if (atomic_dec_return(&sem->count) < 0) __down(sem); - } +} + +extern inline int down_interruptible(struct semaphore * sem) +{ + int ret = 0; + if (atomic_dec_return(&sem->count) < 0) + ret = __down_interruptible(sem); + return ret; } extern inline void up(struct semaphore * sem) diff --git a/include/asm-i386/semaphore.h b/include/asm-i386/semaphore.h index 930b39edb833..0c6c13e9c062 100644 --- a/include/asm-i386/semaphore.h +++ b/include/asm-i386/semaphore.h @@ -7,11 +7,21 @@ * SMP- and interrupt-safe semaphores.. * * (C) Copyright 1996 Linus Torvalds + * + * Modified 1996-12-23 by Dave Grothe to fix bugs in + * the original code and to make semaphore waits + * interruptible so that processes waiting on + * semaphores can be killed. + * + * If you would like to see an analysis of this implementation, please + * ftp to gcom.com and download the file + * /pub/linux/src/semaphore/semaphore-2.0.24.tar.gz. + * */ struct semaphore { int count; - int waiting; + int waking; struct wait_queue * wait; }; @@ -19,6 +29,7 @@ struct semaphore { #define MUTEX_LOCKED ((struct semaphore) { 0, 0, NULL }) asmlinkage void __down_failed(void /* special register calling convention */); +asmlinkage int __down_failed_interruptible(void /* params in registers */); asmlinkage void __up_wakeup(void /* special register calling convention */); extern void __down(struct semaphore * sem); @@ -29,20 +40,46 @@ extern void __up(struct semaphore * sem); * "down_failed" is a special asm handler that calls the C * routine that actually waits. See arch/i386/lib/semaphore.S */ -extern __inline__ void down(struct semaphore * sem) +extern inline void down(struct semaphore * sem) { __asm__ __volatile__( "# atomic down operation\n\t" + "movl $1f,%%eax\n\t" #ifdef __SMP__ "lock ; " #endif - "decl %0\n\t" - "movl $1f,%%eax\n\t" + "decl 0(%0)\n\t" "js " SYMBOL_NAME_STR(__down_failed) "\n1:" :/* no outputs */ - :"m" (sem->count), "c" (sem) - :"ax", "memory"); + :"c" (sem) + :"ax","memory"); +} + +/* + * This version waits in interruptible state so that the waiting + * process can be killed. The down_failed_interruptible routine + * returns negative for signalled and zero for semaphore acquired. + */ +extern inline int down_interruptible(struct semaphore * sem) +{ + int ret; + + __asm__ __volatile__( + "# atomic interruptible down operation\n\t" + "movl $1f,%0\n\t" +#ifdef __SMP__ + "lock ; " +#endif + "decl 0(%1)\n\t" + "js " SYMBOL_NAME_STR(__down_failed_interruptible) "\n\t" + "xorl %0,%0" + "\n1:" + :"=a" (ret) + :"c" (sem) + :"memory"); + + return ret; } /* @@ -51,19 +88,19 @@ extern __inline__ void down(struct semaphore * sem) * The default case (no contention) will result in NO * jumps for both down() and up(). */ -extern __inline__ void up(struct semaphore * sem) +extern inline void up(struct semaphore * sem) { __asm__ __volatile__( "# atomic up operation\n\t" + "movl $1f,%%eax\n\t" #ifdef __SMP__ "lock ; " #endif - "incl %0\n\t" - "movl $1f,%%eax\n\t" + "incl 0(%0)\n\t" "jle " SYMBOL_NAME_STR(__up_wakeup) "\n1:" :/* no outputs */ - :"m" (sem->count), "c" (sem) + :"c" (sem) :"ax", "memory"); } diff --git a/include/linux/atalk.h b/include/linux/atalk.h index 7b7242c7f972..0dc30f8eaff8 100644 --- a/include/linux/atalk.h +++ b/include/linux/atalk.h @@ -88,7 +88,7 @@ struct ddpehdr }; /* - * Unused (and currently unsupported) + * Short form header */ struct ddpshdr @@ -134,7 +134,16 @@ struct elapaarp extern struct datalink_proto *ddp_dl, *aarp_dl; extern void aarp_proto_init(void); /* Inter module exports */ -extern struct atalk_iface *atalk_find_dev(struct device *dev); + +/* + * Give a device find its atif control structure + */ + +extern __inline__ struct atalk_iface *atalk_find_dev(struct device *dev) +{ + return dev->atalk_ptr; +} + extern struct at_addr *atalk_find_dev_addr(struct device *dev); extern int aarp_send_ddp(struct device *dev,struct sk_buff *skb, struct at_addr *sa, void *hwaddr); extern void aarp_send_probe(struct device *dev, struct at_addr *addr); diff --git a/include/linux/ax25.h b/include/linux/ax25.h index 7cf2c6410959..8f255da82f11 100644 --- a/include/linux/ax25.h +++ b/include/linux/ax25.h @@ -2,10 +2,10 @@ * These are the public elements of the Linux kernel AX.25 code. A similar * file netrom.h exists for the NET/ROM protocol. */ - + #ifndef AX25_KERNEL_H #define AX25_KERNEL_H - + #define PF_AX25 AF_AX25 #define AX25_MTU 256 #define AX25_MAX_DIGIS 6 /* This is wrong, should be 8 */ @@ -21,6 +21,7 @@ #define AX25_IDLE 9 #define AX25_PACLEN 10 #define AX25_MAXQUEUE 11 +#define AX25_IAMDIGI 12 #define AX25_KILL 99 @@ -28,8 +29,11 @@ #define SIOCAX25ADDUID (SIOCPROTOPRIVATE+1) #define SIOCAX25DELUID (SIOCPROTOPRIVATE+2) #define SIOCAX25NOUID (SIOCPROTOPRIVATE+3) -#define SIOCAX25OPTRT (SIOCPROTOPRIVATE+4) -#define SIOCAX25CTLCON (SIOCPROTOPRIVATE+5) +#define SIOCAX25OPTRT (SIOCPROTOPRIVATE+7) +#define SIOCAX25CTLCON (SIOCPROTOPRIVATE+8) +#define SIOCAX25GETINFO (SIOCPROTOPRIVATE+9) +#define SIOCAX25ADDFWD (SIOCPROTOPRIVATE+10) +#define SIOCAX25DELFWD (SIOCPROTOPRIVATE+11) #define AX25_SET_RT_IPMODE 2 @@ -37,13 +41,13 @@ #define AX25_NOUID_BLOCK 1 typedef struct { - char ax25_call[7]; /* 6 call + SSID (shifted ascii!) */ + char ax25_call[7]; /* 6 call + SSID (shifted ascii!) */ } ax25_address; struct sockaddr_ax25 { - sa_family_t sax25_family; - ax25_address sax25_call; - int sax25_ndigis; + sa_family_t sax25_family; + ax25_address sax25_call; + int sax25_ndigis; /* Digipeater ax25_address sets follow */ }; @@ -51,29 +55,44 @@ struct sockaddr_ax25 { struct full_sockaddr_ax25 { struct sockaddr_ax25 fsa_ax25; - ax25_address fsa_digipeater[AX25_MAX_DIGIS]; + ax25_address fsa_digipeater[AX25_MAX_DIGIS]; }; struct ax25_routes_struct { - ax25_address port_addr; - ax25_address dest_addr; - unsigned char digi_count; - ax25_address digi_addr[AX25_MAX_DIGIS]; + ax25_address port_addr; + ax25_address dest_addr; + unsigned char digi_count; + ax25_address digi_addr[AX25_MAX_DIGIS]; }; struct ax25_route_opt_struct { - ax25_address port_addr; - ax25_address dest_addr; - int cmd; - int arg; + ax25_address port_addr; + ax25_address dest_addr; + int cmd; + int arg; }; struct ax25_ctl_struct { - ax25_address port_addr; - ax25_address source_addr; - ax25_address dest_addr; - unsigned int cmd; - unsigned long arg; + ax25_address port_addr; + ax25_address source_addr; + ax25_address dest_addr; + unsigned int cmd; + unsigned long arg; +}; + +struct ax25_info_struct { + unsigned int n2, n2count; + unsigned int t1, t1timer; + unsigned int t2, t2timer; + unsigned int t3, t3timer; + unsigned int idle, idletimer; + unsigned int state; + unsigned int rcv_q, snd_q; +}; + +struct ax25_fwd_struct { + ax25_address port_from; + ax25_address port_to; }; #endif diff --git a/include/linux/bios32.h b/include/linux/bios32.h index d3632092a6d5..7944a53fe40c 100644 --- a/include/linux/bios32.h +++ b/include/linux/bios32.h @@ -54,8 +54,8 @@ extern int pcibios_write_config_byte (unsigned char bus, unsigned char dev_fn, unsigned char where, unsigned char val); extern int pcibios_write_config_word (unsigned char bus, unsigned char dev_fn, unsigned char where, unsigned short val); -extern pcibios_write_config_dword (unsigned char bus, unsigned char dev_fn, - unsigned char where, unsigned int val); +extern int pcibios_write_config_dword (unsigned char bus, unsigned char dev_fn, + unsigned char where, unsigned int val); extern const char *pcibios_strerror (int error); #endif /* BIOS32_H */ diff --git a/include/linux/fd.h b/include/linux/fd.h index a05cf3900c66..da7293c35b1c 100644 --- a/include/linux/fd.h +++ b/include/linux/fd.h @@ -153,7 +153,8 @@ struct floppy_drive_params { #define FD_BROKEN_DCL 0x20 #define FD_DEBUG 0x02 #define FD_SILENT_DCL_CLEAR 0x4 -#define FD_INVERTED_DCL 0x80 +#define FD_INVERTED_DCL 0x80 /* must be 0x80, because of hardware + considerations */ char read_track; /* use readtrack during probing? */ diff --git a/include/linux/in.h b/include/linux/in.h index 20fd2f86aabb..5383ed6f1ddc 100644 --- a/include/linux/in.h +++ b/include/linux/in.h @@ -49,10 +49,12 @@ struct in_addr { #define IP_TTL 2 #define IP_HDRINCL 3 #define IP_OPTIONS 4 -#define IP_LOCALADDR 5 +#define IP_LOCALADDR 5 /* Cannot remove; a lot of apps still use it. ANK */ #define IP_RECVOPTS 6 #define IP_RETOPTS 7 -#define IP_LOCALDEV 8 +#define IP_RXINFO 8 +#define IP_TXINFO IP_RXINFO +/* Gated uses it. Remove later or preserve for 4.4BSD compatibility??? */ #define IP_RECVDSTADDR 9 #define IP_PMTUDISC 10 #define IP_RECVERR 11 @@ -91,11 +93,14 @@ struct ip_mreqn { struct in_addr imr_multiaddr; /* IP multicast address of group */ struct in_addr imr_address; /* local IP address of interface */ -#if 1 - char imr_interface[16]; -#else int imr_ifindex; /* Interface index */ -#endif +}; + +struct in_pktinfo +{ + int ipi_ifindex; + struct in_addr ipi_spec_dst; + struct in_addr ipi_addr; }; /* Structure describing an Internet (IP) socket address. */ diff --git a/include/linux/in6.h b/include/linux/in6.h index 30d0ae2db99d..23552fb32ba7 100644 --- a/include/linux/in6.h +++ b/include/linux/in6.h @@ -31,12 +31,14 @@ struct in6_addr union { __u8 u6_addr8[16]; + __u16 u6_addr16[8]; __u32 u6_addr32[4]; #if (~0UL) > 0xffffffff __u64 u6_addr64[2]; #endif } in6_u; #define s6_addr in6_u.u6_addr8 +#define s6_addr16 in6_u.u6_addr16 #define s6_addr32 in6_u.u6_addr32 #define s6_addr64 in6_u.u6_addr64 }; diff --git a/include/linux/lapb.h b/include/linux/lapb.h index 0d1ff4e7977e..bf1825a6b0fb 100644 --- a/include/linux/lapb.h +++ b/include/linux/lapb.h @@ -1,10 +1,10 @@ /* * These are the public elements of the Linux LAPB module. */ - + #ifndef LAPB_KERNEL_H #define LAPB_KERNEL_H - + #define LAPB_OK 0 #define LAPB_BADTOKEN 1 #define LAPB_INVALUE 2 diff --git a/include/linux/lapbether.h b/include/linux/lapbether.h deleted file mode 100644 index b528c37d3982..000000000000 --- a/include/linux/lapbether.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef __LAPBETHER_H -#define __LAPBETHER_H - -/* - * Defines for the LAPBETHER pseudo device driver - */ - -#ifndef __LINUX_IF_ETHER_H -#include -#endif - -#define SIOCSLAPBETHADDR (SIOCDEVPRIVATE+1) - -struct lapbeth_ethaddr { - unsigned char destination[ETH_ALEN]; - unsigned char accept[ETH_ALEN]; -}; - -#endif diff --git a/include/linux/module.h b/include/linux/module.h index 556f4b4cae3e..853acca8f59d 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -221,7 +221,7 @@ extern struct module *module_list; /* We want the EXPORT_SYMBOL tag left intact for recognition. */ -#elif !defined(EXPORT_SYMTAB) +#elif !defined(EXPORT_SYMTAB) && defined(CONFIG_MODULES) #define __EXPORT_SYMBOL(sym,str) error EXPORT_SYMTAB_not_defined #define EXPORT_SYMBOL(var) error EXPORT_SYMTAB_not_defined diff --git a/include/linux/net_alias.h b/include/linux/net_alias.h index c31df3a36c32..54ba8525c974 100644 --- a/include/linux/net_alias.h +++ b/include/linux/net_alias.h @@ -18,6 +18,8 @@ #define _NET_ALIAS_H #include + +#ifdef CONFIG_NET_ALIAS #include #include #include @@ -174,4 +176,12 @@ extern struct device * net_alias_dev_rcv_sel32(struct device *main_dev, int fami +#else + +#define net_alias_is(a) 0 +#define net_alias_main_dev(dev) (dev) +#define net_alias_has(dev) 0 + +#endif + #endif /* _NET_ALIAS_H */ diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 4a99e5062715..1efdf1393a4f 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -145,6 +145,7 @@ struct device * Some hardware also needs these fields, but they are not * part of the usual set specified in Space.c. */ + unsigned char if_port; /* Selectable AUI, TP,..*/ unsigned char dma; /* DMA channel */ @@ -155,9 +156,7 @@ struct device */ struct enet_statistics* (*get_stats)(struct device *dev); -#ifdef CONFIG_NET_RADIO struct iw_statistics* (*get_wireless_stats)(struct device *dev); -#endif /* * This marks the end of the "visible" part of the structure. All @@ -194,7 +193,6 @@ struct device struct ip_mc_list *ip_mc_list; /* IP multicast filter chain */ unsigned ip_flags; /* IP layer control flags */ - __u8 hash; /* Hashing index */ __u32 tx_queue_len; /* Max frames per queue allowed */ /* For load balancing driver pair support */ @@ -203,7 +201,12 @@ struct device struct device *slave; /* Slave device */ struct net_alias_info *alias_info; /* main dev alias info */ struct net_alias *my_alias; /* alias devs */ - + + /* Protocol specific pointers */ + + void *atalk_ptr; /* Appletalk link */ + void *ip_ptr; /* Not used yet */ + /* Pointer to the interface buffers. */ struct sk_buff_head buffs[DEV_NUMBUFFS]; @@ -322,31 +325,6 @@ extern __inline__ void dev_lock_wait(void) schedule(); } -/* NOTE: about to be replaced with if_index */ - -extern __inline__ __u8 dev_hash_name(char *name) -{ - __u8 hash = 0; - __u8 *p; - for (p=name; *p; p++) - hash ^= *p; - return hash; -} - -extern __inline__ __u8 dev_hash_mc_name(char *name) -{ - int i; - __u8 hash = 0; - unsigned *p = (unsigned*)name; - for (i=0; i>16); - h ^= (h>>8); - hash ^= h; - } - return hash; -} - /* * Buffer initialisation function. This used to appear in all the * drivers but is now an inline in case we ever want to change the @@ -384,6 +362,8 @@ extern void dev_mc_add(struct device *dev, void *addr, int alen, int newonly); extern void dev_mc_discard(struct device *dev); /* Load a device via the kerneld */ extern void dev_load(const char *name); +extern int dev_new_index(void); +extern struct device * dev_get_by_index(int ifindex); #endif /* __KERNEL__ */ diff --git a/include/linux/netrom.h b/include/linux/netrom.h index 8732761bd007..e14f183aee50 100644 --- a/include/linux/netrom.h +++ b/include/linux/netrom.h @@ -3,7 +3,7 @@ * For kernel AX.25 see the file ax25.h. This file requires ax25.h for the * definition of the ax25_address structure. */ - + #ifndef NETROM_KERNEL_H #define NETROM_KERNEL_H @@ -20,28 +20,28 @@ #define NETROM_KILL 99 -#define SIOCNRDECOBS (SIOCPROTOPRIVATE+0) -#define SIOCNRCTLCON (SIOCPROTOPRIVATE+1) +#define SIOCNRDECOBS (SIOCPROTOPRIVATE+2) +#define SIOCNRCTLCON (SIOCPROTOPRIVATE+4) struct nr_route_struct { #define NETROM_NEIGH 0 #define NETROM_NODE 1 - int type; - ax25_address callsign; - char device[16]; - unsigned int quality; - char mnemonic[7]; - ax25_address neighbour; - unsigned int obs_count; - unsigned int ndigis; - ax25_address digipeaters[AX25_MAX_DIGIS]; + int type; + ax25_address callsign; + char device[16]; + unsigned int quality; + char mnemonic[7]; + ax25_address neighbour; + unsigned int obs_count; + unsigned int ndigis; + ax25_address digipeaters[AX25_MAX_DIGIS]; }; struct nr_ctl_struct { - unsigned char index; - unsigned char id; - unsigned int cmd; - unsigned long arg; + unsigned char index; + unsigned char id; + unsigned int cmd; + unsigned long arg; }; #endif diff --git a/include/linux/notifier.h b/include/linux/notifier.h index 7425e3b70c71..4ac590f0296a 100644 --- a/include/linux/notifier.h +++ b/include/linux/notifier.h @@ -93,6 +93,10 @@ extern __inline__ int notifier_call_chain(struct notifier_block **n, unsigned lo - we can use this eg to kick tcp sessions once done */ #define NETDEV_CHANGE 0x0004 /* Notify device state change */ +#define NETDEV_REGISTER 0x0005 +#define NETDEV_UNREGISTER 0x0006 +#define NETDEV_CHANGEMTU 0x0007 +#define NETDEV_CHANGEADDR 0x0008 #define SYS_DOWN 0x0001 /* Notify of system down */ #define SYS_HALT 0x0002 /* Notify of system halt */ diff --git a/include/linux/pci.h b/include/linux/pci.h index 41e6d632c044..b92191a3dca6 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -269,6 +269,7 @@ #define PCI_DEVICE_ID_DEC_21152 0x0024 #define PCI_VENDOR_ID_CIRRUS 0x1013 +#define PCI_DEVICE_ID_CIRRUS_7548 0x0038 #define PCI_DEVICE_ID_CIRRUS_5430 0x00a0 #define PCI_DEVICE_ID_CIRRUS_5434_4 0x00a4 #define PCI_DEVICE_ID_CIRRUS_5434_8 0x00a8 @@ -427,6 +428,9 @@ #define PCI_DEVICE_ID_AL_M1513 0x1513 #define PCI_DEVICE_ID_AL_M4803 0x5215 +#define PCI_VENDOR_ID_NEOMAGIC 0x10c8 +#define PCI_DEVICE_ID_NEOMAGIC_MAGICGRAPH_NM2070 0x0001 + #define PCI_VENDOR_ID_ASP 0x10cd #define PCI_DEVICE_ID_ASP_ABP940 0x1200 @@ -445,6 +449,7 @@ #define PCI_VENDOR_ID_INTERG 0x10ea #define PCI_DEVICE_ID_INTERG_1680 0x1680 +#define PCI_DEVICE_ID_INTERG_1682 0x1682 #define PCI_VENDOR_ID_REALTEK 0x10ec #define PCI_DEVICE_ID_REALTEK_8029 0x8029 @@ -572,6 +577,8 @@ #define PCI_DEVICE_ID_INTEL_82437 0x122d #define PCI_DEVICE_ID_INTEL_82371_0 0x122e #define PCI_DEVICE_ID_INTEL_82371_1 0x1230 +#define PCI_DEVICE_ID_INTEL_430MX_0 0x1234 +#define PCI_DEVICE_ID_INTEL_430MX_1 0x1235 #define PCI_DEVICE_ID_INTEL_82441 0x1237 #define PCI_DEVICE_ID_INTEL_82439 0x1250 #define PCI_DEVICE_ID_INTEL_82371SB_0 0x7000 diff --git a/include/linux/rose.h b/include/linux/rose.h index 4fe0c8fa50bd..cd69214c347f 100644 --- a/include/linux/rose.h +++ b/include/linux/rose.h @@ -3,7 +3,7 @@ * For kernel AX.25 see the file ax25.h. This file requires ax25.h for the * definition of the ax25_address structure. */ - + #ifndef ROSE_KERNEL_H #define ROSE_KERNEL_H @@ -20,10 +20,11 @@ #define ROSE_KILL 99 -#define SIOCRSCTLCON (SIOCPROTOPRIVATE+0) +#define SIOCRSCTLCON (SIOCPROTOPRIVATE+1) +#define SIOCRSL2CALL (SIOCPROTOPRIVATE+2) typedef struct { - char rose_addr[5]; + char rose_addr[5]; } rose_address; struct sockaddr_rose { @@ -44,10 +45,10 @@ struct rose_route_struct { }; struct rose_ctl_struct { - unsigned int lci; - char dev[20]; - unsigned int cmd; - unsigned long arg; + unsigned int lci; + char dev[20]; + unsigned int cmd; + unsigned long arg; }; #endif diff --git a/include/linux/route.h b/include/linux/route.h index 95e47ed90fdb..3214294c8787 100644 --- a/include/linux/route.h +++ b/include/linux/route.h @@ -125,7 +125,7 @@ struct in_rtmsg unsigned char rtmsg_class; unsigned char rtmsg_prefixlen; unsigned char rtmsg_reserved; - char rtmsg_device[16]; + int rtmsg_ifindex; }; @@ -139,7 +139,8 @@ struct in_ifmsg short ifmsg_metric; unsigned char ifmsg_prefixlen; unsigned char ifmsg_reserved; - char ifmsg_device[16]; + int ifmsg_index; + char ifmsg_name[16]; }; enum rtrule_actions @@ -160,11 +161,11 @@ struct in_rtrulemsg struct in_addr rtrmsg_src; struct in_addr rtrmsg_dst; struct in_addr rtrmsg_srcmap; + int rtrmsg_ifindex; unsigned char rtrmsg_srclen; unsigned char rtrmsg_dstlen; unsigned char rtrmsg_tos; unsigned char rtrmsg_class; - char rtrmsg_device[16]; unsigned char rtrmsg_flags; unsigned char rtrmsg_action; unsigned char rtrmsg_preference; diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 480139021ef7..0998a9741465 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -199,10 +199,27 @@ extern __inline__ void kfree_skb(struct sk_buff *skb, int rw) __kfree_skb(skb); } +extern __inline__ int skb_cloned(struct sk_buff *skb) +{ + return (skb->data_skb->count != 1); +} + +extern __inline__ int skb_shared(struct sk_buff *skb) +{ + return (skb->users != 1); +} + +/* + * Copy shared buffers into a new sk_buff. We effectively do COW on + * packets to handle cases where we have a local reader and forward + * and a couple of other messy ones. The normal one is tcpdumping + * a packet thats being forwarded. + */ + extern __inline__ struct sk_buff *skb_unshare(struct sk_buff *skb, int pri, int dir) { struct sk_buff *nskb; - if(skb->users==1) + if(!skb_cloned(skb)) return skb; nskb=skb_copy(skb, pri); kfree_skb(skb, dir); /* Free our shared copy */ @@ -215,6 +232,7 @@ extern __inline__ struct sk_buff *skb_unshare(struct sk_buff *skb, int pri, int * list and someone else may run off with it. For an interrupt * type system cli() peek the buffer copy the data and sti(); */ + extern __inline__ struct sk_buff *skb_peek(struct sk_buff_head *list_) { struct sk_buff *list = ((struct sk_buff *)list_)->next; diff --git a/include/linux/socket.h b/include/linux/socket.h index 28a6bb18e193..3e594a90bc7b 100644 --- a/include/linux/socket.h +++ b/include/linux/socket.h @@ -63,9 +63,16 @@ struct cmsghdr { #define CMSG_ALIGN(len) ( ((len)+sizeof(long)-1) & ~(sizeof(long)-1) ) -#define CMSG_FIRST(msg) ((msg)->msg_controllen >= sizeof(struct cmsghdr) ? \ - (struct cmsghdr *)(msg)->msg_control : \ - (struct cmsghdr *)NULL) +/* Stevens's Adv. API specifies CMSG_SPACE & CMSG_LENGTH, + * I cannot understand, what the differenece? --ANK + */ + +#define CMSG_SPACE(len) CMSG_ALIGN((len)+sizeof(struct cmsghdr)) +#define CMSG_LENGTH(len) CMSG_ALIGN((len)+sizeof(struct cmsghdr)) + +#define CMSG_FIRSTHDR(msg) ((msg)->msg_controllen >= sizeof(struct cmsghdr) ? \ + (struct cmsghdr *)(msg)->msg_control : \ + (struct cmsghdr *)NULL) extern __inline__ struct cmsghdr * cmsg_nxthdr(struct msghdr *mhdr, struct cmsghdr *cmsg) @@ -83,20 +90,6 @@ extern __inline__ struct cmsghdr * cmsg_nxthdr(struct msghdr *mhdr, return (struct cmsghdr *) ptr; } -#ifdef __KERNEL__ - -#define KCMSG_NXTHDR(msg, cmsg) ({ \ - struct cmsghdr * __cmptr = (struct cmsghdr *)((unsigned char*)(cmsg) + CMSG_ALIGN(kcm.cmsg_len)); \ - ( (void *)(__cmptr + 1) <= (msg)->msg_control + (msg)->msg_controllen && \ - !copy_from_user(&kcm, __cmptr, sizeof(struct cmsghdr)) ? __cmptr : NULL); }) - -#define KCMSG_FIRSTHDR(msg) ((msg)->msg_control && (msg)->msg_controllen >= sizeof(struct cmsghdr) \ - && !copy_from_user(&kcm, (msg)->msg_control, sizeof(struct cmsghdr)) ? \ - (struct cmsghdr *)(msg)->msg_control : \ - (struct cmsghdr *)NULL) - -#endif - /* "Socket"-level control message types: */ #define SCM_RIGHTS 0x01 /* rw: access rights (array of int) */ @@ -154,7 +147,7 @@ struct ucred #define PF_AAL5 AF_AAL5 #define PF_X25 AF_X25 #define PF_INET6 AF_INET6 -#define PR_ROSE AF_ROSE +#define PF_ROSE AF_ROSE #define PF_DECNET AF_DECNET #define PF_NETBEUI AF_NETBEUI diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index cafbf031e68d..37f6f0b0ac71 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -139,7 +139,8 @@ enum { NET_NETROM_TRANSPORT_REQUESTED_WINDOW_SIZE, NET_NETROM_TRANSPORT_NO_ACTIVITY_TIMEOUT, NET_NETROM_TRANSPORT_PACKET_LENGTH, - NET_NETROM_ROUTING_CONTROL + NET_NETROM_ROUTING_CONTROL, + NET_NETROM_LINK_FAILS_COUNT }; /* /proc/sys/net/ax25 */ diff --git a/include/linux/watchdog.h b/include/linux/watchdog.h index f9f08c660ba0..3f358258be0d 100644 --- a/include/linux/watchdog.h +++ b/include/linux/watchdog.h @@ -37,3 +37,4 @@ struct watchdog_info { #define WDIOS_DISABLECARD 0x0001 /* Turn off the watchdog timer */ #define WDIOS_ENABLECARD 0x0002 /* Turn on the watchdog timer */ +#define WDIOS_TEMPPANIC 0x0004 /* Kernel panic on temperature trip */ diff --git a/include/linux/x25.h b/include/linux/x25.h index 7c49cf33bd69..6af8e9a5bc6d 100644 --- a/include/linux/x25.h +++ b/include/linux/x25.h @@ -1,22 +1,23 @@ /* * These are the public elements of the Linux kernel X.25 implementation. */ - + #ifndef X25_KERNEL_H #define X25_KERNEL_H #define PF_X25 AF_X25 -#define SIOCX25SETSUBSCR (SIOCPROTOPRIVATE + 0) +#define SIOCX25GSUBSCRIP (SIOCPROTOPRIVATE + 0) +#define SIOCX25SSUBSCRIP (SIOCPROTOPRIVATE + 1) +#define SIOCX25GFACILITIES (SIOCPROTOPRIVATE + 2) +#define SIOCX25SFACILITIES (SIOCPROTOPRIVATE + 3) +#define SIOCX25GCALLUSERDATA (SIOCPROTOPRIVATE + 4) +#define SIOCX25SCALLUSERDATA (SIOCPROTOPRIVATE + 5) /* * Values for {get,set}sockopt. */ #define X25_QBITINCL 1 -#define X25_PACKET_SIZE 10 -#define X25_WINDOW_SIZE 11 -#define X25_THROUGHPUT_SPEED 12 -#define X25_REVERSE_CHARGE 13 /* * X.25 Packet Size values. @@ -95,4 +96,22 @@ struct x25_route_struct { char device[200]; }; +/* + * Facilities structure. + */ +struct x25_facilities { + unsigned int winsize_in, winsize_out; + unsigned int pacsize_in, pacsize_out; + unsigned int throughput; + unsigned int reverse; +}; + +/* + * Call User Data structure. + */ +struct x25_calluserdata { + unsigned int cudlength; + unsigned char cuddata[128]; +}; + #endif diff --git a/include/net/arp.h b/include/net/arp.h index 405951b3a807..e02b388c20be 100644 --- a/include/net/arp.h +++ b/include/net/arp.h @@ -7,7 +7,6 @@ extern void arp_init(void); extern int arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt); -extern int arp_query(unsigned char *haddr, u32 paddr, struct device *dev); extern int arp_find(unsigned char *haddr, struct sk_buff *skb); extern int arp_find_1(unsigned char *haddr, struct dst_entry* dst, struct dst_entry *neigh); extern int arp_ioctl(unsigned int cmd, void *arg); diff --git a/include/net/ax25.h b/include/net/ax25.h index 42875ba79c22..7b1ddd50fda4 100644 --- a/include/net/ax25.h +++ b/include/net/ax25.h @@ -8,45 +8,43 @@ #define _AX25_H #include -#define PR_SLOWHZ 10 /* Run timing at 1/10 second - gives us better resolution for 56kbit links */ +#define AX25_SLOWHZ 10 /* Run timing at 1/10 second - gives us better resolution for 56kbit links */ -#define AX25_T1CLAMPLO (1 * PR_SLOWHZ) /* If defined, clamp at 1 second **/ -#define AX25_T1CLAMPHI (30 * PR_SLOWHZ) /* If defined, clamp at 30 seconds **/ +#define AX25_T1CLAMPLO (1 * AX25_SLOWHZ) /* If defined, clamp at 1 second **/ +#define AX25_T1CLAMPHI (30 * AX25_SLOWHZ) /* If defined, clamp at 30 seconds **/ -#define AX25_BROKEN_NETMAC +#define AX25_BPQ_HEADER_LEN 16 +#define AX25_KISS_HEADER_LEN 1 -#define AX25_BPQ_HEADER_LEN 16 -#define AX25_KISS_HEADER_LEN 1 +#define AX25_HEADER_LEN 17 +#define AX25_ADDR_LEN 7 +#define AX25_DIGI_HEADER_LEN (AX25_MAX_DIGIS * AX25_ADDR_LEN) +#define AX25_MAX_HEADER_LEN (AX25_HEADER_LEN + AX25_DIGI_HEADER_LEN) -#define AX25_HEADER_LEN 17 -#define AX25_ADDR_LEN 7 -#define AX25_DIGI_HEADER_LEN (AX25_MAX_DIGIS * AX25_ADDR_LEN) -#define AX25_MAX_HEADER_LEN (AX25_HEADER_LEN + AX25_DIGI_HEADER_LEN) - -#define AX25_P_ROSE 0x01 -#define AX25_P_IP 0xCC -#define AX25_P_ARP 0xCD -#define AX25_P_TEXT 0xF0 -#define AX25_P_NETROM 0xCF -#define AX25_P_SEGMENT 0x08 - -#define SEG_REM 0x7F -#define SEG_FIRST 0x80 +/* AX.25 Protocol IDs */ +#define AX25_P_ROSE 0x01 +#define AX25_P_IP 0xCC +#define AX25_P_ARP 0xCD +#define AX25_P_TEXT 0xF0 +#define AX25_P_NETROM 0xCF +#define AX25_P_SEGMENT 0x08 -#define LAPB_UI 0x03 -#define LAPB_C 0x80 -#define LAPB_E 0x01 +/* AX.25 Segment control values */ +#define AX25_SEG_REM 0x7F +#define AX25_SEG_FIRST 0x80 -#define SSSID_SPARE 0x60 /* Unused bits in SSID for standard AX.25 */ -#define ESSID_SPARE 0x20 /* Unused bits in SSID for extended AX.25 */ -#define DAMA_FLAG 0x20 /* Well, it is *NOT* unused! (dl1bke 951121 */ +#define AX25_CBIT 0x80 /* Command/Response bit */ +#define AX25_EBIT 0x01 /* HDLC Address Extension bit */ +#define AX25_HBIT 0x80 /* Has been repeated bit */ -#define AX25_REPEATED 0x80 +#define AX25_SSSID_SPARE 0x60 /* Unused bits in SSID for standard AX.25 */ +#define AX25_ESSID_SPARE 0x20 /* Unused bits in SSID for extended AX.25 */ +#define AX25_DAMA_FLAG 0x20 /* Well, it is *NOT* unused! (dl1bke 951121 */ -#define ACK_PENDING_CONDITION 0x01 -#define REJECT_CONDITION 0x02 -#define PEER_RX_BUSY_CONDITION 0x04 -#define OWN_RX_BUSY_CONDITION 0x08 +#define AX25_COND_ACK_PENDING 0x01 +#define AX25_COND_REJECT 0x02 +#define AX25_COND_PEER_RX_BUSY 0x04 +#define AX25_COND_OWN_RX_BUSY 0x08 #ifndef _LINUX_NETDEVICE_H #include @@ -76,44 +74,43 @@ /* Upper sub-layer (LAPB) definitions */ /* Control field templates */ -#define I 0x00 /* Information frames */ -#define S 0x01 /* Supervisory frames */ -#define RR 0x01 /* Receiver ready */ -#define RNR 0x05 /* Receiver not ready */ -#define REJ 0x09 /* Reject */ -#define U 0x03 /* Unnumbered frames */ -#define SABM 0x2f /* Set Asynchronous Balanced Mode */ -#define SABME 0x6f /* Set Asynchronous Balanced Mode Extended */ -#define DISC 0x43 /* Disconnect */ -#define DM 0x0f /* Disconnected mode */ -#define UA 0x63 /* Unnumbered acknowledge */ -#define FRMR 0x87 /* Frame reject */ -#define UI 0x03 /* Unnumbered information */ -#define PF 0x10 /* Poll/final bit for standard AX.25 */ -#define EPF 0x01 /* Poll/final bit for extended AX.25 */ - -#define ILLEGAL 0x100 /* Impossible to be a real frame type */ - -#define POLLOFF 0 -#define POLLON 1 +#define AX25_I 0x00 /* Information frames */ +#define AX25_S 0x01 /* Supervisory frames */ +#define AX25_RR 0x01 /* Receiver ready */ +#define AX25_RNR 0x05 /* Receiver not ready */ +#define AX25_REJ 0x09 /* Reject */ +#define AX25_U 0x03 /* Unnumbered frames */ +#define AX25_SABM 0x2f /* Set Asynchronous Balanced Mode */ +#define AX25_SABME 0x6f /* Set Asynchronous Balanced Mode Extended */ +#define AX25_DISC 0x43 /* Disconnect */ +#define AX25_DM 0x0f /* Disconnected mode */ +#define AX25_UA 0x63 /* Unnumbered acknowledge */ +#define AX25_FRMR 0x87 /* Frame reject */ +#define AX25_UI 0x03 /* Unnumbered information */ + +#define AX25_PF 0x10 /* Poll/final bit for standard AX.25 */ +#define AX25_EPF 0x01 /* Poll/final bit for extended AX.25 */ + +#define AX25_ILLEGAL 0x100 /* Impossible to be a real frame type */ + +#define AX25_POLLOFF 0 +#define AX25_POLLON 1 /* AX25 L2 C-bit */ - -#define C_COMMAND 1 /* C_ otherwise it clashes with the de600 defines (sigh)) */ -#define C_RESPONSE 2 +#define AX25_COMMAND 1 +#define AX25_RESPONSE 2 /* Define Link State constants. */ - -#define AX25_STATE_0 0 -#define AX25_STATE_1 1 -#define AX25_STATE_2 2 -#define AX25_STATE_3 3 -#define AX25_STATE_4 4 +#define AX25_STATE_0 0 +#define AX25_STATE_1 1 +#define AX25_STATE_2 2 +#define AX25_STATE_3 3 +#define AX25_STATE_4 4 #define AX25_MAX_DEVICES 20 /* Max No of AX.25 devices */ -#define MODULUS 8 /* Standard AX.25 modulus */ -#define EMODULUS 128 /* Extended AX.25 modulus */ +#define AX25_MODULUS 8 /* Standard AX.25 modulus */ +#define AX25_EMODULUS 128 /* Extended AX.25 modulus */ #define AX25_DIGI_INBAND 0x01 /* Allow digipeating within port **/ #define AX25_DIGI_XBAND 0x02 /* Allow digipeating across ports **/ @@ -142,11 +139,11 @@ #define AX25_DEF_CONMODE 1 /* Connected mode allowed */ #define AX25_DEF_WINDOW 2 /* Window=2 */ #define AX25_DEF_EWINDOW 32 /* Module-128 Window=32 */ -#define AX25_DEF_T1 (10 * PR_SLOWHZ) /* T1=10s */ -#define AX25_DEF_T2 (3 * PR_SLOWHZ) /* T2=3s */ -#define AX25_DEF_T3 (300 * PR_SLOWHZ) /* T3=300s */ +#define AX25_DEF_T1 (10 * AX25_SLOWHZ) /* T1=10s */ +#define AX25_DEF_T2 (3 * AX25_SLOWHZ) /* T2=3s */ +#define AX25_DEF_T3 (300 * AX25_SLOWHZ) /* T3=300s */ #define AX25_DEF_N2 10 /* N2=10 */ -#define AX25_DEF_IDLE (20 * 60 * PR_SLOWHZ) /* Idle=20 mins */ +#define AX25_DEF_IDLE (20 * 60 * AX25_SLOWHZ) /* Idle=20 mins */ #define AX25_DEF_PACLEN 256 /* Paclen=256 */ #define AX25_DEF_MAXQUEUE 2 /* 1 * ax25->window */ #define AX25_DEF_DIGI 0x03 /* All digis alowed */ @@ -168,7 +165,7 @@ typedef struct ax25_cb { struct ax25_cb *next; ax25_address source_addr, dest_addr; struct device *device; - unsigned char dama_slave; /* dl1bke 951121 */ + unsigned char dama_slave, iamdigi; unsigned char state, modulus, hdrincl; unsigned short vs, vr, va; unsigned char condition, backoff; @@ -191,6 +188,7 @@ typedef struct ax25_cb { struct ax25_dev { char name[20]; struct device *dev; + struct device *forward; int values[AX25_MAX_VALUES]; }; @@ -245,6 +243,8 @@ extern char ax25_ip_mode_get(ax25_address *, struct device *); extern int ax25_dev_get_value(struct device *, int); extern void ax25_dev_device_up(struct device *); extern void ax25_dev_device_down(struct device *); +extern int ax25_fwd_ioctl(unsigned int, struct ax25_fwd_struct *); +extern struct device *ax25_fwd_dev(struct device *); extern void ax25_rt_free(void); /* ax25_subr.c */ @@ -289,5 +289,6 @@ extern int ax25_linkfail_register(void (*)(ax25_address *, struct device *)); extern void ax25_linkfail_release(void (*)(ax25_address *, struct device *)); extern int ax25_listen_register(ax25_address *, struct device *); extern void ax25_listen_release(ax25_address *, struct device *); +extern int ax25_protocol_is_registered(unsigned int); #endif diff --git a/include/net/ip.h b/include/net/ip.h index 97227ec235dc..c0e600a37541 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -199,7 +199,7 @@ extern void ip_options_build(struct sk_buff *skb, struct ip_options *opt, u32 da extern int ip_options_echo(struct ip_options *dopt, struct sk_buff *skb); extern void ip_options_fragment(struct sk_buff *skb); extern int ip_options_compile(struct ip_options *opt, struct sk_buff *skb); -extern int ip_options_getfromuser(struct ip_options **optp, unsigned char *data, int optlen); +extern int ip_options_get(struct ip_options **optp, unsigned char *data, int optlen, int user); extern void ip_options_undo(struct ip_options * opt); extern void ip_forward_options(struct sk_buff *skb); extern int ip_options_rcv_srr(struct sk_buff *skb); diff --git a/include/net/lapb.h b/include/net/lapb.h index e974dc27686b..d6c87f7b323d 100644 --- a/include/net/lapb.h +++ b/include/net/lapb.h @@ -116,6 +116,6 @@ extern void lapb_set_timer(lapb_cb *); * 2 = Packets I/O and State Changes * 3 = Hex dumps, Packets I/O and State Changes. */ -#define LAPB_DEBUG 2 +#define LAPB_DEBUG 0 #endif diff --git a/include/net/netrom.h b/include/net/netrom.h index 5427bdf02574..baa94d6007dd 100644 --- a/include/net/netrom.h +++ b/include/net/netrom.h @@ -3,50 +3,59 @@ * * Jonathan Naylor G4KLX 9/4/95 */ - + #ifndef _NETROM_H #define _NETROM_H #include -#define NR_T1CLAMPLO (1 * PR_SLOWHZ) /* If defined, clamp at 1 second **/ -#define NR_T1CLAMPHI (300 * PR_SLOWHZ) /* If defined, clamp at 30 seconds **/ +#define NR_SLOWHZ 10 /* Run timing at 1/10 second */ + +#define NR_T1CLAMPLO (1 * NR_SLOWHZ) /* If defined, clamp at 1 second **/ +#define NR_T1CLAMPHI (300 * NR_SLOWHZ) /* If defined, clamp at 30 seconds **/ + +#define NR_NETWORK_LEN 15 +#define NR_TRANSPORT_LEN 5 -#define NR_NETWORK_LEN 15 -#define NR_TRANSPORT_LEN 5 - -#define NR_PROTO_IP 0x0C +#define NR_PROTO_IP 0x0C -#define NR_PROTOEXT 0x00 -#define NR_CONNREQ 0x01 -#define NR_CONNACK 0x02 -#define NR_DISCREQ 0x03 -#define NR_DISCACK 0x04 -#define NR_INFO 0x05 -#define NR_INFOACK 0x06 +#define NR_PROTOEXT 0x00 +#define NR_CONNREQ 0x01 +#define NR_CONNACK 0x02 +#define NR_DISCREQ 0x03 +#define NR_DISCACK 0x04 +#define NR_INFO 0x05 +#define NR_INFOACK 0x06 -#define NR_CHOKE_FLAG 0x80 -#define NR_NAK_FLAG 0x40 -#define NR_MORE_FLAG 0x20 +#define NR_CHOKE_FLAG 0x80 +#define NR_NAK_FLAG 0x40 +#define NR_MORE_FLAG 0x20 /* Define Link State constants. */ -#define NR_STATE_0 0 -#define NR_STATE_1 1 -#define NR_STATE_2 2 -#define NR_STATE_3 3 - -#define NR_DEFAULT_T1 (120 * PR_SLOWHZ) /* Outstanding frames - 120 seconds */ -#define NR_DEFAULT_T2 (5 * PR_SLOWHZ) /* Response delay - 5 seconds */ -#define NR_DEFAULT_N2 3 /* Number of Retries - 3 */ -#define NR_DEFAULT_T4 (180 * PR_SLOWHZ) /* Busy Delay - 180 seconds */ -#define NR_DEFAULT_IDLE (20* 60 * PR_SLOWHZ) /* No Activuty Timeout - 900 seconds*/ -#define NR_DEFAULT_WINDOW 4 /* Default Window Size - 4 */ -#define NR_DEFAULT_OBS 6 /* Default Obsolescence Count - 6 */ -#define NR_DEFAULT_QUAL 10 /* Default Neighbour Quality - 10 */ -#define NR_DEFAULT_TTL 16 /* Default Time To Live - 16 */ -#define NR_MODULUS 256 -#define NR_MAX_WINDOW_SIZE 127 /* Maximum Window Allowable - 127 */ -#define NR_DEFAULT_PACLEN 236 /* Default Packet Length - 236 */ +#define NR_STATE_0 0 +#define NR_STATE_1 1 +#define NR_STATE_2 2 +#define NR_STATE_3 3 + +#define NR_COND_ACK_PENDING 0x01 +#define NR_COND_REJECT 0x02 +#define NR_COND_PEER_RX_BUSY 0x04 +#define NR_COND_OWN_RX_BUSY 0x08 + +#define NR_DEFAULT_T1 (120 * NR_SLOWHZ) /* Outstanding frames - 120 seconds */ +#define NR_DEFAULT_T2 (5 * NR_SLOWHZ) /* Response delay - 5 seconds */ +#define NR_DEFAULT_N2 3 /* Number of Retries - 3 */ +#define NR_DEFAULT_T4 (180 * NR_SLOWHZ) /* Busy Delay - 180 seconds */ +#define NR_DEFAULT_IDLE (20* 60 * NR_SLOWHZ) /* No Activuty Timeout - 900 seconds*/ +#define NR_DEFAULT_WINDOW 4 /* Default Window Size - 4 */ +#define NR_DEFAULT_OBS 6 /* Default Obsolescence Count - 6 */ +#define NR_DEFAULT_QUAL 10 /* Default Neighbour Quality - 10 */ +#define NR_DEFAULT_TTL 16 /* Default Time To Live - 16 */ +#define NR_MODULUS 256 +#define NR_MAX_WINDOW_SIZE 127 /* Maximum Window Allowable - 127 */ +#define NR_DEFAULT_PACLEN 236 /* Default Packet Length - 236 */ +#define NR_DEFAULT_ROUTING 1 /* Is routing enabled ? */ +#define NR_DEFAULT_FAILS 2 /* Link fails until route fails */ typedef struct { ax25_address user_addr, source_addr, dest_addr; @@ -74,6 +83,7 @@ struct nr_neigh { unsigned char locked; unsigned short count; unsigned int number; + unsigned char failed; }; struct nr_route { @@ -103,6 +113,7 @@ extern int sysctl_netrom_transport_requested_window_size; extern int sysctl_netrom_transport_no_activity_timeout; extern int sysctl_netrom_transport_packet_length; extern int sysctl_netrom_routing_control; +extern int sysctl_netrom_link_fails_count; extern int nr_rx_frame(struct sk_buff *, struct device *); extern void nr_destroy_socket(struct sock *); diff --git a/include/net/rose.h b/include/net/rose.h index f24d2cd69071..03b92d652f24 100644 --- a/include/net/rose.h +++ b/include/net/rose.h @@ -3,20 +3,22 @@ * * Jonathan Naylor G4KLX 25/8/96 */ - + #ifndef _ROSE_H #define _ROSE_H #include +#define ROSE_SLOWHZ 10 /* Run timing at 1/10 second */ + #define ROSE_ADDR_LEN 5 #define ROSE_MIN_LEN 3 -#define GFI 0x10 -#define Q_BIT 0x80 -#define D_BIT 0x40 -#define M_BIT 0x10 - +#define ROSE_GFI 0x10 +#define ROSE_Q_BIT 0x80 +#define ROSE_D_BIT 0x40 +#define ROSE_M_BIT 0x10 + #define ROSE_CALL_REQUEST 0x0B #define ROSE_CALL_ACCEPTED 0x0F #define ROSE_CLEAR_REQUEST 0x13 @@ -38,33 +40,37 @@ /* Define Link State constants. */ -#define ROSE_STATE_0 0 /* Ready */ -#define ROSE_STATE_1 1 /* Awaiting Call Accepted */ -#define ROSE_STATE_2 2 /* Awaiting Clear Confirmation */ -#define ROSE_STATE_3 3 /* Data Transfer */ -#define ROSE_STATE_4 4 /* Awaiting Reset Confirmation */ - -#define ROSE_DEFAULT_T0 (180 * PR_SLOWHZ) /* Default T10 T20 value */ -#define ROSE_DEFAULT_T1 (200 * PR_SLOWHZ) /* Default T11 T21 value */ -#define ROSE_DEFAULT_T2 (180 * PR_SLOWHZ) /* Default T12 T22 value */ -#define ROSE_DEFAULT_T3 (180 * PR_SLOWHZ) /* Default T13 T23 value */ -#define ROSE_DEFAULT_HB (5 * PR_SLOWHZ) /* Default Holdback value */ -#define ROSE_DEFAULT_IDLE (20 * 60 * PR_SLOWHZ) /* Default No Activity value */ -#define ROSE_DEFAULT_WINDOW 2 /* Default Window Size */ -#define ROSE_MODULUS 8 -#define ROSE_MAX_WINDOW_SIZE 7 /* Maximum Window Allowable */ -#define ROSE_PACLEN 128 /* Default Packet Length */ - -#define FAC_NATIONAL 0x00 -#define FAC_CCITT 0x0F - -#define FAC_NATIONAL_RAND 0x7F -#define FAC_NATIONAL_FLAGS 0x3F -#define FAC_NATIONAL_DEST_DIGI 0xE9 -#define FAC_NATIONAL_SRC_DIGI 0xEB - -#define FAC_CCITT_DEST_NSAP 0xC9 -#define FAC_CCITT_SRC_NSAP 0xCB +#define ROSE_STATE_0 0 /* Ready */ +#define ROSE_STATE_1 1 /* Awaiting Call Accepted */ +#define ROSE_STATE_2 2 /* Awaiting Clear Confirmation */ +#define ROSE_STATE_3 3 /* Data Transfer */ +#define ROSE_STATE_4 4 /* Awaiting Reset Confirmation */ + +#define ROSE_DEFAULT_T0 (180 * ROSE_SLOWHZ) /* Default T10 T20 value */ +#define ROSE_DEFAULT_T1 (200 * ROSE_SLOWHZ) /* Default T11 T21 value */ +#define ROSE_DEFAULT_T2 (180 * ROSE_SLOWHZ) /* Default T12 T22 value */ +#define ROSE_DEFAULT_T3 (180 * ROSE_SLOWHZ) /* Default T13 T23 value */ +#define ROSE_DEFAULT_HB (5 * ROSE_SLOWHZ) /* Default Holdback value */ +#define ROSE_DEFAULT_IDLE (20 * 60 * ROSE_SLOWHZ) /* Default No Activity value */ +#define ROSE_DEFAULT_WINDOW 2 /* Default Window Size */ +#define ROSE_MODULUS 8 +#define ROSE_MAX_WINDOW_SIZE 7 /* Maximum Window Allowable */ +#define ROSE_PACLEN 128 /* Default Packet Length */ + +#define ROSE_COND_ACK_PENDING 0x01 +#define ROSE_COND_PEER_RX_BUSY 0x02 +#define ROSE_COND_OWN_RX_BUSY 0x04 + +#define FAC_NATIONAL 0x00 +#define FAC_CCITT 0x0F + +#define FAC_NATIONAL_RAND 0x7F +#define FAC_NATIONAL_FLAGS 0x3F +#define FAC_NATIONAL_DEST_DIGI 0xE9 +#define FAC_NATIONAL_SRC_DIGI 0xEB + +#define FAC_CCITT_DEST_NSAP 0xC9 +#define FAC_CCITT_SRC_NSAP 0xCB struct rose_neigh { struct rose_neigh *next; @@ -108,12 +114,12 @@ typedef struct { unsigned short timer; unsigned short t1, t2, t3, hb, idle; unsigned short fraglen; - struct sk_buff_head ack_queue; struct sk_buff_head frag_queue; struct sock *sk; /* Backlink to socket */ } rose_cb; /* af_rose.c */ +extern ax25_address rose_callsign; extern int sysctl_rose_restart_request_timeout; extern int sysctl_rose_call_request_timeout; extern int sysctl_rose_reset_request_timeout; @@ -169,8 +175,6 @@ extern void rose_rt_free(void); /* rose_subr.c */ extern void rose_clear_queues(struct sock *); -extern void rose_frames_acked(struct sock *, unsigned short); -extern void rose_requeue_frames(struct sock *); extern int rose_validate_nr(struct sock *, unsigned short); extern void rose_write_internal(struct sock *, int); extern int rose_decode(struct sk_buff *, int *, int *, int *, int *, int *); diff --git a/include/net/route.h b/include/net/route.h index 3c1d06a9572e..f5cafb8ab988 100644 --- a/include/net/route.h +++ b/include/net/route.h @@ -115,7 +115,7 @@ extern void ip_rt_check_expire(void); extern void ip_rt_advice(struct rtable **rp, int advice); extern void rt_cache_flush(int how); extern int ip_route_output(struct rtable **, u32 dst, u32 src, u8 tos, struct device *devout); -extern int ip_route_output_dev(struct rtable **, u32 dst, u32 src, u8 tos, char *devname); +extern int ip_route_output_dev(struct rtable **, u32 dst, u32 src, u8 tos, int); extern int ip_route_input(struct sk_buff*, u32 dst, u32 src, u8 tos, struct device *devin); extern unsigned short ip_rt_frag_needed(struct iphdr *iph, unsigned short new_mtu); extern void ip_rt_send_redirect(struct sk_buff *skb); diff --git a/include/net/scm.h b/include/net/scm.h index 11dfadde4ab8..d8bb8d1ebf02 100644 --- a/include/net/scm.h +++ b/include/net/scm.h @@ -39,7 +39,7 @@ static __inline__ int scm_send(struct socket *sock, struct msghdr *msg, scm->creds.gid = current->gid; scm->creds.pid = current->pid; scm->sock = sock; - if (!msg->msg_control) + if (msg->msg_controllen <= 0) return 0; return __scm_send(sock, msg, scm); } diff --git a/include/net/sock.h b/include/net/sock.h index 8fc63808e47c..15104ef81f81 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -466,7 +466,8 @@ struct sock __u8 ip_mc_loop; /* Loopback */ __u8 ip_recverr; __u8 ip_pmtudisc; - char ip_mc_name[MAX_ADDR_LEN];/* Multicast device name */ + int ip_mc_index; /* Multicast device index */ + __u32 ip_mc_addr; struct ip_mc_socklist *ip_mc_list; /* Group array */ /* @@ -686,11 +687,23 @@ extern int sock_setsockopt(struct socket *sock, int level, extern int sock_getsockopt(struct socket *sock, int level, int op, char *optval, int *optlen); -extern struct sk_buff *sock_alloc_send_skb(struct sock *skb, +extern struct sk_buff *sock_alloc_send_skb(struct sock *sk, unsigned long size, unsigned long fallback, int noblock, int *errcode); +extern int sock_no_fcntl(struct socket *, unsigned int, unsigned long); + +/* + * Default socket callbacks and setup code + */ + +extern void sock_def_callback1(struct sock *); +extern void sock_def_callback2(struct sock *, int); +extern void sock_def_callback3(struct sock *); + +/* Initialise core socket variables */ +extern void sock_init_data(struct socket *sock, struct sock *sk); extern void sklist_remove_socket(struct sock **list, struct sock *sk); extern void sklist_insert_socket(struct sock **list, struct sock *sk); diff --git a/include/net/x25.h b/include/net/x25.h index fedc80a61443..8a1b81f4c1fd 100644 --- a/include/net/x25.h +++ b/include/net/x25.h @@ -3,7 +3,7 @@ * * Jonathan Naylor 17/11/96 */ - + #ifndef _X25_H #define _X25_H #include @@ -25,7 +25,7 @@ #define X25_D_BIT 0x40 #define X25_STD_M_BIT 0x10 #define X25_EXT_M_BIT 0x01 - + #define X25_CALL_REQUEST 0x0B #define X25_CALL_ACCEPTED 0x0F #define X25_CLEAR_REQUEST 0x13 @@ -95,6 +95,7 @@ #define X25_FAC_WINDOW_SIZE 0x43 #define X25_MAX_FAC_LEN 20 /* Plenty to spare */ +#define X25_MAX_CUD_LEN 128 struct x25_route { struct x25_route *next; @@ -113,27 +114,21 @@ struct x25_neigh { struct timer_list timer; }; -struct x25_facilities { - int window_size; - int packet_size; - int throughput; - int reverse; -}; - typedef struct { x25_address source_addr, dest_addr; struct x25_neigh *neighbour; unsigned int lci; - unsigned char state, condition, qbitincl, intflg; + unsigned char state, condition, qbitincl, intflag; unsigned short vs, vr, va, vl; unsigned short timer; unsigned short t2, t21, t22, t23; unsigned short fraglen; - struct sk_buff_head ack_queue; struct sk_buff_head fragment_queue; - struct sk_buff_head interrupt_queue; + struct sk_buff_head interrupt_in_queue; + struct sk_buff_head interrupt_out_queue; struct sock *sk; /* Backlink to socket */ struct x25_facilities facilities; + struct x25_calluserdata calluserdata; } x25_cb; /* af_x25.c */ @@ -194,8 +189,6 @@ extern void x25_route_free(void); /* x25_subr.c */ extern void x25_clear_queues(struct sock *); -extern void x25_frames_acked(struct sock *, unsigned short); -extern void x25_requeue_frames(struct sock *); extern int x25_validate_nr(struct sock *, unsigned short); extern void x25_write_internal(struct sock *, int); extern int x25_decode(struct sock *, struct sk_buff *, int *, int *, int *, int *, int *); diff --git a/init/main.c b/init/main.c index 070f9e62a425..d3b746e6c0ba 100644 --- a/init/main.c +++ b/init/main.c @@ -224,7 +224,7 @@ kdev_t real_root_dev; #endif int root_mountflags = MS_RDONLY; -char *execute_command = 0; +char *execute_command = NULL; #ifdef CONFIG_ROOT_NFS char nfs_root_name[NFS_ROOT_NAME_LEN] = { "default" }; @@ -960,7 +960,7 @@ static int init(void * unused) smp_begin(); #endif - #ifdef CONFIG_UMSDOS_FS +#ifdef CONFIG_UMSDOS_FS { /* When mounting a umsdos fs as root, we detect @@ -973,13 +973,14 @@ static int init(void * unused) current->fs->pwd = pseudo_root; } } - #endif +#endif #ifdef CONFIG_BLK_DEV_INITRD root_mountflags = real_root_mountflags; if (mount_initrd && ROOT_DEV != real_root_dev && ROOT_DEV == MKDEV(RAMDISK_MAJOR,0)) { int error; - + int pid,i; + pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD); if (pid>0) while (pid != wait(&i)); @@ -1012,10 +1013,11 @@ static int init(void * unused) * trying to recover a really broken machine. */ - execve(execute_command,argv_init,envp_init); + if (execute_command) + execve(execute_command,argv_init,envp_init); + execve("/sbin/init",argv_init,envp_init); execve("/etc/init",argv_init,envp_init); execve("/bin/init",argv_init,envp_init); - execve("/sbin/init",argv_init,envp_init); execve("/bin/sh",argv_init,envp_init); panic("No init found. Try passing init= option to kernel."); } diff --git a/kernel/sched.c b/kernel/sched.c index 8d13c21a62b7..09697cf3fc5a 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -4,6 +4,8 @@ * Copyright (C) 1991, 1992 Linus Torvalds * * 1996-04-21 Modified by Ulrich Windl to make NTP work + * 1996-12-23 Modified by Dave Grothe to fix bugs in semaphores and + * make semaphores SMP safe */ /* @@ -482,32 +484,48 @@ bad: printk(" *q = %p\n",*q); } + /* * Semaphores are implemented using a two-way counter: * The "count" variable is decremented for each process - * that tries to sleep, while the "waiting" variable is - * incremented _while_ the process is sleeping on that - * semaphore. + * that tries to sleep, while the "waking" variable is + * incremented when the "up()" code goes to wake up waiting + * processes. * * Notably, the inline "up()" and "down()" functions can * efficiently test if they need to do any extra work (up * needs to do something only if count was negative before * the increment operation. + * + * This routine must execute atomically. */ -static inline void normalize_semaphore(struct semaphore *sem) +static inline int waking_non_zero(struct semaphore *sem) { - atomic_add(xchg(&sem->waiting,0), &sem->count); + int ret; + long flags; + + save_flags(flags); + cli(); + + ret = 0; + if (sem->waking > 0) { + sem->waking--; + ret = 1; + } + + restore_flags(flags); + return ret; } /* * When __up() is called, the count was negative before - * incrementing it, and we need to wake up somebody. In - * most cases "waiting" will be positive, and the normalization - * will allow things to continue. However, if somebody has - * /just/ done a down(), it may be that count was negative - * without waiting being positive (or in the generic case - * "count is more negative than waiting is positive"), and - * the waiter needs to check this itself (see __down). + * incrementing it, and we need to wake up somebody. + * + * This routine adds one to the count of processes that need to + * wake up and exit. ALL waiting processes actually wake up but + * only the one that gets to the "waking" field first will gate + * through and acquire the semaphore. The others will go back + * to sleep. * * Note that these functions are only called when there is * contention on the lock, and as such all this is the @@ -517,55 +535,83 @@ static inline void normalize_semaphore(struct semaphore *sem) */ void __up(struct semaphore *sem) { - normalize_semaphore(sem); + atomic_inc(&sem->waking); wake_up(&sem->wait); } -void __down(struct semaphore * sem) +/* + * Perform the "down" function. Return zero for semaphore acquired, + * return negative for signalled out of the function. + * + * If called from __down, the return is ignored and the wait loop is + * not interruptible. This means that a task waiting on a semaphore + * using "down()" cannot be killed until someone does an "up()" on + * the semaphore. + * + * If called from __down_interruptible, the return value gets checked + * upon return. If the return value is negative then the task continues + * with the negative value in the return register (it can be tested by + * the caller). + * + * Either form may be used in conjunction with "up()". + * + */ +static inline int __do_down(struct semaphore * sem, int task_state) { struct task_struct *tsk = current; struct wait_queue wait = { tsk, NULL }; + int ret = 0; - /* - * The order here is important. We add ourselves to the - * wait queues and mark ourselves sleeping _first_. That - * way, if a "up()" comes in here, we'll either get - * woken up (up happens after the wait queues are set up) - * OR we'll have "waiting > 0". - */ - tsk->state = TASK_UNINTERRUPTIBLE; + tsk->state = task_state; add_wait_queue(&sem->wait, &wait); - atomic_inc(&sem->waiting); /* - * Ok, we're set up. The only race here is really that - * an "up()" might have incremented count before we got - * here, so we check "count+waiting". If that is larger - * than zero, we shouldn't sleep, but re-try the lock. + * Ok, we're set up. sem->count is known to be less than zero + * so we must wait. + * + * We can let go the lock for purposes of waiting. + * We re-acquire it after awaking so as to protect + * all semaphore operations. + * + * If "up()" is called before we call waking_non_zero() then + * we will catch it right away. If it is called later then + * we will have to go through a wakeup cycle to catch it. + * + * Multiple waiters contend for the semaphore lock to see + * who gets to gate through and who has to wait some more. */ - if (sem->count+sem->waiting <= 0) { - /* - * If "count+waiting" <= 0, we have to wait - * for a up(), which will normalize the count. - * Remember, at this point we have decremented - * count, and incremented up, so if count is - * zero or positive we need to return to re-try - * the lock. It _may_ be that both count and - * waiting is zero and that it is still locked, - * but we still want to re-try the lock in that - * case to make count go negative again so that - * the optimized "up()" wake_up sequence works. - */ - do { - schedule(); - tsk->state = TASK_UNINTERRUPTIBLE; - } while (sem->count < 0); + for (;;) { + if (waking_non_zero(sem)) /* are we waking up? */ + break; /* yes, exit loop */ + + if ( task_state == TASK_INTERRUPTIBLE + && (tsk->signal & ~tsk->blocked) /* signalled */ + ) { + ret = -EINTR; /* interrupted */ + atomic_inc(&sem->count); /* give up on down operation */ + break; + } + + schedule(); + tsk->state = task_state; } + tsk->state = TASK_RUNNING; remove_wait_queue(&sem->wait, &wait); - normalize_semaphore(sem); + return ret; +} + +void __down(struct semaphore * sem) +{ + __do_down(sem,TASK_UNINTERRUPTIBLE); } +int __down_interruptible(struct semaphore * sem) +{ + return __do_down(sem,TASK_INTERRUPTIBLE); +} + + static inline void __sleep_on(struct wait_queue **p, int state) { unsigned long flags; diff --git a/kernel/sys.c b/kernel/sys.c index 7018cf662d21..bdd06e83b819 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -182,7 +182,7 @@ extern void hard_reset_now(void); #ifdef __sparc__ extern void halt_now(void); #endif -extern asmlinkage sys_kill(int, int); +extern asmlinkage int sys_kill(int, int); /* * Reboot system call: for obvious reasons only root may call it, diff --git a/net/802/Makefile b/net/802/Makefile index 45ef8e410f15..c32b0950618c 100644 --- a/net/802/Makefile +++ b/net/802/Makefile @@ -12,8 +12,8 @@ O_OBJS = p8023.o sysctl_net_802.o ifeq ($(CONFIG_LLC),y) SUB_DIRS += transit -O_OBJS += llc_macinit.o llc_sendpdu.o llc_utility.o cl2llc.o - +O_OBJS += llc_sendpdu.o llc_utility.o cl2llc.o +OX_OBJS += llc_macinit.o endif diff --git a/net/802/llc_macinit.c b/net/802/llc_macinit.c index 8e3374106ef3..f420997441ee 100644 --- a/net/802/llc_macinit.c +++ b/net/802/llc_macinit.c @@ -19,6 +19,7 @@ * Started restructuring handlers */ +#include #include #include #include diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index 2d5e3d9fb4fc..cdbbba3fd1dd 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c @@ -248,6 +248,7 @@ static void atif_drop_device(struct device *dev) { *iface = tmp->next; kfree_s(tmp, sizeof(struct atalk_iface)); + dev->atalk_ptr=NULL; } else iface = &tmp->next; @@ -262,6 +263,7 @@ static struct atalk_iface *atif_add_device(struct device *dev, struct at_addr *s if(iface==NULL) return NULL; iface->dev=dev; + dev->atalk_ptr=iface; iface->address= *sa; iface->status=0; save_flags(flags); @@ -377,10 +379,9 @@ static int atif_probe_device(struct atalk_iface *atif) struct at_addr *atalk_find_dev_addr(struct device *dev) { - struct atalk_iface *iface; - for(iface=atalk_iface_list;iface!=NULL;iface=iface->next) - if(iface->dev==dev) - return &iface->address; + struct atalk_iface *iface=dev->atalk_ptr; + if(iface) + return &iface->address; return NULL; } @@ -390,24 +391,10 @@ static struct at_addr *atalk_find_primary(void) for(iface=atalk_iface_list;iface!=NULL;iface=iface->next) if(!(iface->dev->flags&IFF_LOOPBACK)) return &iface->address; - if ( atalk_iface_list != NULL ) { - return &atalk_iface_list->address; - } else { - return NULL; - } -} - -/* - * Give a device find its atif control structure - */ - -struct atalk_iface *atalk_find_dev(struct device *dev) -{ - struct atalk_iface *iface; - for(iface=atalk_iface_list;iface!=NULL;iface=iface->next) - if(iface->dev==dev) - return iface; - return NULL; + if ( atalk_iface_list != NULL ) + return &atalk_iface_list->address; + else + return NULL; } /* @@ -472,7 +459,7 @@ static struct atalk_route *atrtr_find(struct at_addr *target) /* * Given an appletalk network find the device to use. This can be - * a simple lookup. Funny stuff like routers can wait 8) + * a simple lookup. */ static struct device *atrtr_get_dev(struct at_addr *sa) @@ -924,21 +911,6 @@ unsigned short atalk_checksum(struct ddpehdr *ddp, int len) return 0xFFFF; /* Use 0xFFFF for 0. 0 itself means none */ } -/* - * Generic fcntl calls are already dealt with. If we don't need funny ones - * this is the all you need. Async I/O is also separate. - */ - -static int atalk_fcntl(struct socket *sock, unsigned int cmd, unsigned long arg) -{ -/* struct sock *sk=sock->sk;*/ - switch(cmd) - { - default: - return(-EINVAL); - } -} - /* * Set 'magic' options for appletalk. If we don't have any this is fine * as it is. @@ -946,31 +918,7 @@ static int atalk_fcntl(struct socket *sock, unsigned int cmd, unsigned long arg) static int atalk_setsockopt(struct socket *sock, int level, int optname, char *optval, int optlen) { - struct sock *sk; - int err,opt; - - sk=sock->sk; - - if(optval==NULL) - return(-EINVAL); - - err = get_user(opt, (int *)optval); - if (err) - return err; - - switch(level) - { - case SOL_ATALK: - switch(optname) - { - default: - return -EOPNOTSUPP; - } - break; - - default: - return -EOPNOTSUPP; - } + return -EOPNOTSUPP; } @@ -981,30 +929,7 @@ static int atalk_setsockopt(struct socket *sock, int level, int optname, char *o static int atalk_getsockopt(struct socket *sock, int level, int optname, char *optval, int *optlen) { - struct sock *sk; - int val=0; - int err; - - sk=sock->sk; - - switch(level) - { - - case SOL_ATALK: - switch(optname) - { - default: - return -ENOPROTOOPT; - } - break; - - default: - return -EOPNOTSUPP; - } - err = put_user(sizeof(int),optlen); - if (!err) - err = put_user(val, (int *) optval); - return err; + return -ENOPROTOOPT; } /* @@ -1016,34 +941,6 @@ static int atalk_listen(struct socket *sock, int backlog) return -EOPNOTSUPP; } -/* - * These are standard. - */ - -static void def_callback1(struct sock *sk) -{ - if(!sk->dead) - wake_up_interruptible(sk->sleep); -} - -static void def_callback2(struct sock *sk, int len) -{ - if(!sk->dead) - { - wake_up_interruptible(sk->sleep); - sock_wake_async(sk->socket,1); - } -} - -static void def_callback3(struct sock *sk) -{ - if(!sk->dead) - { - wake_up_interruptible(sk->sleep); - sock_wake_async(sk->socket, 2); - } -} - /* * Create a socket. Initialise the socket, blank the addresses * set the state. @@ -1071,32 +968,10 @@ static int atalk_create(struct socket *sock, int protocol) MOD_INC_USE_COUNT; - sk->no_check=0; /* Checksums on by default */ - sk->allocation=GFP_KERNEL; - sk->rcvbuf=SK_RMEM_MAX; - sk->sndbuf=SK_WMEM_MAX; - sk->pair=NULL; - sk->priority=1; - skb_queue_head_init(&sk->receive_queue); - skb_queue_head_init(&sk->write_queue); - skb_queue_head_init(&sk->back_log); - sk->state=TCP_CLOSE; - sk->socket=sock; - sk->type=sock->type; - + sock_init_data(sock,sk); + + /* Checksums on by default */ sk->mtu=DDP_MAXSZ; - - if(sock!=NULL) - { - sk->sleep=&sock->wait; - sock->sk=sk; - } - - sk->state_change=def_callback1; - sk->data_ready=def_callback2; - sk->write_space=def_callback3; - sk->error_report=def_callback1; - sk->zapped=1; return(0); } @@ -1909,7 +1784,7 @@ static struct proto_ops atalk_dgram_ops = { atalk_shutdown, atalk_setsockopt, atalk_getsockopt, - atalk_fcntl, + sock_no_fcntl, atalk_sendmsg, atalk_recvmsg }; diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index dbb6b692fbdf..4b69a7dafce3 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c @@ -90,6 +90,8 @@ * format. * Hans(PE1AYX) Fixed interface to IP layer. * Alan(GW4PTS) Added asynchronous support. + * Frederic(F1OAT) Support for pseudo-digipeating. + * Jonathan(G4KLX) Support for packet forwarding. * * To do: * Restructure the ax25_rcv code to be cleaner/faster and @@ -136,7 +138,7 @@ */ ax25_address null_ax25_address = {{0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00}}; -ax25_cb *volatile ax25_list = NULL; +ax25_cb *ax25_list = NULL; static struct proto_ops ax25_proto_ops; @@ -227,6 +229,26 @@ int ax25cmp(ax25_address *a, ax25_address *b) return 2; /* Partial match */ } +/* + * Compare two AX.25 digipeater paths. + */ +static int ax25digicmp(ax25_digi *digi1, ax25_digi *digi2) +{ + int i; + + if (digi1->ndigi != digi2->ndigi) + return 1; + + if (digi1->lastrepeat != digi2->lastrepeat) + return 1; + + for (i = 0; i < digi1->ndigi; i++) + if (ax25cmp(&digi1->calls[i], &digi2->calls[i]) != 0) + return 1; + + return 0; +} + /* * Free an allocated ax25 control block. This is done to centralise * the MOD count code. @@ -343,7 +365,7 @@ static void ax25_insert_socket(ax25_cb *ax25) * Find a socket that wants to accept the SABM we have just * received. */ -static struct sock *ax25_find_listener(ax25_address *addr, struct device *dev, int type) +static struct sock *ax25_find_listener(ax25_address *addr, int digi, struct device *dev, int type) { unsigned long flags; ax25_cb *s; @@ -352,6 +374,8 @@ static struct sock *ax25_find_listener(ax25_address *addr, struct device *dev, i cli(); for (s = ax25_list; s != NULL; s = s->next) { + if ((s->iamdigi && !digi) || (!s->iamdigi && digi)) + continue; if (s->sk != NULL && ax25cmp(&s->source_addr, addr) == 0 && s->sk->type == type && s->sk->state == TCP_LISTEN) { /* If device is null we match any device */ if (s->device == NULL || s->device == dev) { @@ -393,7 +417,7 @@ static struct sock *ax25_find_socket(ax25_address *my_addr, ax25_address *dest_a * floating AX.25 control blocks or non Raw socket bound control blocks. */ -static ax25_cb *ax25_find_cb(ax25_address *my_addr, ax25_address *dest_addr, struct device *dev) +static ax25_cb *ax25_find_cb(ax25_address *my_addr, ax25_address *dest_addr, ax25_digi *digi, struct device *dev) { ax25_cb *s; unsigned long flags; @@ -405,6 +429,12 @@ static ax25_cb *ax25_find_cb(ax25_address *my_addr, ax25_address *dest_addr, str if (s->sk != NULL && s->sk->type != SOCK_SEQPACKET) continue; if (ax25cmp(&s->source_addr, my_addr) == 0 && ax25cmp(&s->dest_addr, dest_addr) == 0 && s->device == dev) { + if (digi != NULL) { + if (s->digipeat == NULL && digi->ndigi != 0) + continue; + if (s->digipeat != NULL && ax25digicmp(s->digipeat, digi) != 0) + continue; + } restore_flags(flags); return s; } @@ -418,7 +448,6 @@ static ax25_cb *ax25_find_cb(ax25_address *my_addr, ax25_address *dest_addr, str /* * Look for any matching address - RAW sockets can bind to arbitrary names */ - static struct sock *ax25_addr_match(ax25_address *addr) { unsigned long flags; @@ -615,13 +644,13 @@ static int ax25_ctl_ioctl(const unsigned int cmd, void *arg) if ((dev = ax25rtr_get_dev(&ax25_ctl.port_addr)) == NULL) return -ENODEV; - if ((ax25 = ax25_find_cb(&ax25_ctl.source_addr, &ax25_ctl.dest_addr, dev)) == NULL) + if ((ax25 = ax25_find_cb(&ax25_ctl.source_addr, &ax25_ctl.dest_addr, NULL, dev)) == NULL) return -ENOTCONN; switch (ax25_ctl.cmd) { case AX25_KILL: ax25_clear_queues(ax25); - ax25_send_control(ax25, DISC, POLLON, C_COMMAND); + ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND); ax25->state = AX25_STATE_0; if (ax25->sk != NULL) { @@ -638,7 +667,7 @@ static int ax25_ctl_ioctl(const unsigned int cmd, void *arg) break; case AX25_WINDOW: - if (ax25->modulus == MODULUS) { + if (ax25->modulus == AX25_MODULUS) { if (ax25_ctl.arg < 1 || ax25_ctl.arg > 7) return -EINVAL; } else { @@ -651,8 +680,8 @@ static int ax25_ctl_ioctl(const unsigned int cmd, void *arg) case AX25_T1: if (ax25_ctl.arg < 1) return -EINVAL; - ax25->rtt = (ax25_ctl.arg * PR_SLOWHZ) / 2; - ax25->t1 = ax25_ctl.arg * PR_SLOWHZ; + ax25->rtt = (ax25_ctl.arg * AX25_SLOWHZ) / 2; + ax25->t1 = ax25_ctl.arg * AX25_SLOWHZ; save_flags(flags); cli(); if (ax25->t1timer > ax25->t1) ax25->t1timer = ax25->t1; @@ -663,7 +692,7 @@ static int ax25_ctl_ioctl(const unsigned int cmd, void *arg) if (ax25_ctl.arg < 1) return -EINVAL; save_flags(flags); cli(); - ax25->t2 = ax25_ctl.arg * PR_SLOWHZ; + ax25->t2 = ax25_ctl.arg * AX25_SLOWHZ; if (ax25->t2timer > ax25->t2) ax25->t2timer = ax25->t2; restore_flags(flags); @@ -680,7 +709,7 @@ static int ax25_ctl_ioctl(const unsigned int cmd, void *arg) if (ax25_ctl.arg < 0) return -EINVAL; save_flags(flags); cli(); - ax25->t3 = ax25_ctl.arg * PR_SLOWHZ; + ax25->t3 = ax25_ctl.arg * AX25_SLOWHZ; if (ax25->t3timer != 0) ax25->t3timer = ax25->t3; restore_flags(flags); @@ -690,7 +719,7 @@ static int ax25_ctl_ioctl(const unsigned int cmd, void *arg) if (ax25_ctl.arg < 0) return -EINVAL; save_flags(flags); cli(); - ax25->idle = ax25_ctl.arg * PR_SLOWHZ * 60; + ax25->idle = ax25_ctl.arg * AX25_SLOWHZ * 60; if (ax25->idletimer != 0) ax25->idletimer = ax25->idle; restore_flags(flags); @@ -750,10 +779,10 @@ static ax25_cb *ax25_create_cb(void) ax25->idle = AX25_DEF_IDLE; if (AX25_DEF_AXDEFMODE) { - ax25->modulus = EMODULUS; + ax25->modulus = AX25_EMODULUS; ax25->window = AX25_DEF_EWINDOW; } else { - ax25->modulus = MODULUS; + ax25->modulus = AX25_MODULUS; ax25->window = AX25_DEF_WINDOW; } @@ -802,10 +831,10 @@ static void ax25_fillin_cb(ax25_cb *ax25, struct device *dev) ax25->idle = ax25_dev_get_value(dev, AX25_VALUES_IDLE); if (ax25_dev_get_value(dev, AX25_VALUES_AXDEFMODE)) { - ax25->modulus = EMODULUS; + ax25->modulus = AX25_EMODULUS; ax25->window = ax25_dev_get_value(dev, AX25_VALUES_EWINDOW); } else { - ax25->modulus = MODULUS; + ax25->modulus = AX25_MODULUS; ax25->window = ax25_dev_get_value(dev, AX25_VALUES_WINDOW); } @@ -914,19 +943,13 @@ struct device *ax25rtr_get_dev(ax25_address *addr) * Handling for system calls applied via the various interfaces to an * AX25 socket object */ -static int ax25_fcntl(struct socket *sock, unsigned int cmd, unsigned long arg) -{ - return -EINVAL; -} static int ax25_setsockopt(struct socket *sock, int level, int optname, char *optval, int optlen) { - struct sock *sk; + struct sock *sk = sock->sk; int err, opt; - sk = (struct sock *)sock->sk; - if (level != SOL_AX25) return -EOPNOTSUPP; @@ -940,7 +963,7 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname, switch (optname) { case AX25_WINDOW: - if (sk->protinfo.ax25->modulus == MODULUS) { + if (sk->protinfo.ax25->modulus == AX25_MODULUS) { if (opt < 1 || opt > 7) return -EINVAL; } else { @@ -953,13 +976,13 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname, case AX25_T1: if (opt < 1) return -EINVAL; - sk->protinfo.ax25->rtt = (opt * PR_SLOWHZ) / 2; + sk->protinfo.ax25->rtt = (opt * AX25_SLOWHZ) / 2; return 0; case AX25_T2: if (opt < 1) return -EINVAL; - sk->protinfo.ax25->t2 = opt * PR_SLOWHZ; + sk->protinfo.ax25->t2 = opt * AX25_SLOWHZ; return 0; case AX25_N2: @@ -971,13 +994,13 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname, case AX25_T3: if (opt < 1) return -EINVAL; - sk->protinfo.ax25->t3 = opt * PR_SLOWHZ; + sk->protinfo.ax25->t3 = opt * AX25_SLOWHZ; return 0; case AX25_IDLE: if (opt < 0) return -EINVAL; - sk->protinfo.ax25->idle = opt * PR_SLOWHZ * 60; + sk->protinfo.ax25->idle = opt * AX25_SLOWHZ * 60; return 0; case AX25_BACKOFF: @@ -985,13 +1008,17 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname, return 0; case AX25_EXTSEQ: - sk->protinfo.ax25->modulus = opt ? EMODULUS : MODULUS; + sk->protinfo.ax25->modulus = opt ? AX25_EMODULUS : AX25_MODULUS; return 0; case AX25_HDRINCL: sk->protinfo.ax25->hdrincl = opt ? 1 : 0; return 0; + case AX25_IAMDIGI: + sk->protinfo.ax25->iamdigi = opt ? 1 : 0; + return 0; + case AX25_PACLEN: if (opt < 16 || opt > 65535) return -EINVAL; @@ -1006,12 +1033,10 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname, static int ax25_getsockopt(struct socket *sock, int level, int optname, char *optval, int *optlen) { - struct sock *sk; + struct sock *sk = sock->sk; int val = 0; int err; - sk = (struct sock *)sock->sk; - if (level != SOL_AX25) return -EOPNOTSUPP; @@ -1021,11 +1046,11 @@ static int ax25_getsockopt(struct socket *sock, int level, int optname, break; case AX25_T1: - val = (sk->protinfo.ax25->t1 * 2) / PR_SLOWHZ; + val = (sk->protinfo.ax25->t1 * 2) / AX25_SLOWHZ; break; case AX25_T2: - val = sk->protinfo.ax25->t2 / PR_SLOWHZ; + val = sk->protinfo.ax25->t2 / AX25_SLOWHZ; break; case AX25_N2: @@ -1033,11 +1058,11 @@ static int ax25_getsockopt(struct socket *sock, int level, int optname, break; case AX25_T3: - val = sk->protinfo.ax25->t3 / PR_SLOWHZ; + val = sk->protinfo.ax25->t3 / AX25_SLOWHZ; break; case AX25_IDLE: - val = sk->protinfo.ax25->idle / (PR_SLOWHZ * 60); + val = sk->protinfo.ax25->idle / (AX25_SLOWHZ * 60); break; case AX25_BACKOFF: @@ -1045,13 +1070,17 @@ static int ax25_getsockopt(struct socket *sock, int level, int optname, break; case AX25_EXTSEQ: - val = (sk->protinfo.ax25->modulus == EMODULUS); + val = (sk->protinfo.ax25->modulus == AX25_EMODULUS); break; case AX25_HDRINCL: val = sk->protinfo.ax25->hdrincl; break; + case AX25_IAMDIGI: + val = sk->protinfo.ax25->iamdigi; + break; + case AX25_PACLEN: val = sk->protinfo.ax25->paclen; break; @@ -1075,7 +1104,7 @@ static int ax25_getsockopt(struct socket *sock, int level, int optname, static int ax25_listen(struct socket *sock, int backlog) { - struct sock *sk = (struct sock *)sock->sk; + struct sock *sk = sock->sk; if (sk->type == SOCK_SEQPACKET && sk->state != TCP_LISTEN) { sk->max_ack_backlog = backlog; @@ -1086,30 +1115,6 @@ static int ax25_listen(struct socket *sock, int backlog) return -EOPNOTSUPP; } -static void def_callback1(struct sock *sk) -{ - if (!sk->dead) - wake_up_interruptible(sk->sleep); -} - -static void def_callback2(struct sock *sk, int len) -{ - if (!sk->dead) - { - wake_up_interruptible(sk->sleep); - sock_wake_async(sk->socket,1); - } -} - -static void def_callback3(struct sock *sk, int len) -{ - if (!sk->dead) - { - wake_up_interruptible(sk->sleep); - sock_wake_async(sk->socket,2); - } -} - static int ax25_create(struct socket *sock, int protocol) { struct sock *sk; @@ -1131,13 +1136,23 @@ static int ax25_create(struct socket *sock, int protocol) case AX25_P_ARP: case AX25_P_IP: #endif -#if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE) +#ifdef CONFIG_NETROM case AX25_P_NETROM: #endif -#if defined(CONFIG_ROSE) || defined(CONFIG_ROSE_MODULE) +#ifdef CONFIG_ROSE case AX25_P_ROSE: #endif return -ESOCKTNOSUPPORT; +#ifdef CONFIG_NETROM_MODULE + case AX25_P_NETROM: + if (ax25_protocol_is_registered(AX25_P_NETROM)) + return -ESOCKTNOSUPPORT; +#endif +#ifdef CONFIG_ROSE_MODULE + case AX25_P_ROSE: + if (ax25_protocol_is_registered(AX25_P_ROSE)) + return -ESOCKTNOSUPPORT; +#endif default: break; } @@ -1156,33 +1171,12 @@ static int ax25_create(struct socket *sock, int protocol) return -ENOMEM; } + sock_init_data(sock,sk); + sock->ops = &ax25_proto_ops; - skb_queue_head_init(&sk->receive_queue); - skb_queue_head_init(&sk->write_queue); - skb_queue_head_init(&sk->back_log); - - sk->socket = sock; - sk->type = sock->type; sk->protocol = protocol; - sk->next = NULL; - sk->allocation = GFP_KERNEL; - sk->rcvbuf = SK_RMEM_MAX; - sk->sndbuf = SK_WMEM_MAX; - sk->state = TCP_CLOSE; - sk->priority = SOPRI_NORMAL; sk->mtu = AX25_MTU; /* 256 */ - sk->zapped = 1; - - sk->state_change = def_callback1; - sk->data_ready = def_callback2; - sk->write_space = def_callback3; - sk->error_report = def_callback1; - - if (sock != NULL) { - sock->sk = sk; - sk->sleep = &sock->wait; - } ax25->sk = sk; sk->protinfo.ax25 = ax25; @@ -1219,11 +1213,8 @@ static struct sock *ax25_make_new(struct sock *osk, struct device *dev) return NULL; } - skb_queue_head_init(&sk->receive_queue); - skb_queue_head_init(&sk->write_queue); - skb_queue_head_init(&sk->back_log); - - sk->next = NULL; + sock_init_data(NULL,sk); + sk->priority = osk->priority; sk->protocol = osk->protocol; sk->rcvbuf = osk->rcvbuf; @@ -1234,14 +1225,10 @@ static struct sock *ax25_make_new(struct sock *osk, struct device *dev) sk->sleep = osk->sleep; sk->zapped = osk->zapped; - sk->state_change = def_callback1; - sk->data_ready = def_callback2; - sk->write_space = def_callback3; - sk->error_report = def_callback1; - ax25->modulus = osk->protinfo.ax25->modulus; ax25->backoff = osk->protinfo.ax25->backoff; ax25->hdrincl = osk->protinfo.ax25->hdrincl; + ax25->iamdigi = osk->protinfo.ax25->iamdigi; ax25->rtt = osk->protinfo.ax25->rtt; ax25->t1 = osk->protinfo.ax25->t1; ax25->t2 = osk->protinfo.ax25->t2; @@ -1273,14 +1260,17 @@ static struct sock *ax25_make_new(struct sock *osk, struct device *dev) static int ax25_dup(struct socket *newsock, struct socket *oldsock) { - struct sock *sk = (struct sock *)oldsock->sk; + struct sock *sk = oldsock->sk; + + if (sk == NULL || newsock == NULL) + return -EINVAL; return ax25_create(newsock, sk->protocol); } static int ax25_release(struct socket *sock, struct socket *peer) { - struct sock *sk = (struct sock *)sock->sk; + struct sock *sk = sock->sk; if (sk == NULL) return 0; @@ -1295,7 +1285,7 @@ static int ax25_release(struct socket *sock, struct socket *peer) break; case AX25_STATE_1: - ax25_send_control(sk->protinfo.ax25, DISC, POLLON, C_COMMAND); + ax25_send_control(sk->protinfo.ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND); sk->protinfo.ax25->state = AX25_STATE_0; sk->state = TCP_CLOSE; sk->shutdown |= SEND_SHUTDOWN; @@ -1306,9 +1296,9 @@ static int ax25_release(struct socket *sock, struct socket *peer) case AX25_STATE_2: if (sk->protinfo.ax25->dama_slave) - ax25_send_control(sk->protinfo.ax25, DISC, POLLON, C_COMMAND); + ax25_send_control(sk->protinfo.ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND); else - ax25_send_control(sk->protinfo.ax25, DM, POLLON, C_RESPONSE); + ax25_send_control(sk->protinfo.ax25, AX25_DM, AX25_POLLON, AX25_RESPONSE); sk->protinfo.ax25->state = AX25_STATE_0; sk->state = TCP_CLOSE; sk->shutdown |= SEND_SHUTDOWN; @@ -1322,7 +1312,7 @@ static int ax25_release(struct socket *sock, struct socket *peer) ax25_clear_queues(sk->protinfo.ax25); sk->protinfo.ax25->n2count = 0; if (!sk->protinfo.ax25->dama_slave) { - ax25_send_control(sk->protinfo.ax25, DISC, POLLON, C_COMMAND); + ax25_send_control(sk->protinfo.ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND); sk->protinfo.ax25->t3timer = 0; } else { sk->protinfo.ax25->t3timer = sk->protinfo.ax25->t3; /* DAMA slave timeout */ @@ -1358,24 +1348,23 @@ static int ax25_release(struct socket *sock, struct socket *peer) * digipeated via a local address as source. This is a hack until we add * BSD 4.4 ADDIFADDR type support. It is however small and trivially backward * compatible 8) - * - * FIXME: Check family */ static int ax25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) { - struct sock *sk; + struct sock *sk = sock->sk; struct full_sockaddr_ax25 *addr = (struct full_sockaddr_ax25 *)uaddr; struct device *dev; ax25_address *call; - sk = (struct sock *)sock->sk; - if (sk->zapped == 0) return -EINVAL; if (addr_len != sizeof(struct sockaddr_ax25) && addr_len != sizeof(struct full_sockaddr_ax25)) return -EINVAL; + if (addr->fsa_ax25.sax25_family != AF_AX25) + return -EINVAL; + call = ax25_findbyuid(current->euid); if (call == NULL && ax25_uid_policy && !suser()) return -EACCES; @@ -1424,14 +1413,12 @@ static int ax25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) } /* - * FIXME: nonblock behaviour looks like it may have a bug. Also check - * the family in the connect. + * FIXME: nonblock behaviour looks like it may have a bug. */ - static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags) { - struct sock *sk = (struct sock *)sock->sk; + struct sock *sk = sock->sk; struct sockaddr_ax25 *addr = (struct sockaddr_ax25 *)uaddr; int err; @@ -1454,6 +1441,9 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, if (addr_len != sizeof(struct sockaddr_ax25) && addr_len != sizeof(struct full_sockaddr_ax25)) return -EINVAL; + if (addr->sax25_family != AF_AX25) + return -EINVAL; + /* * Handle digi-peaters to be used. */ @@ -1470,15 +1460,19 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, return -ENOBUFS; } - sk->protinfo.ax25->digipeat->ndigi = addr->sax25_ndigis; + sk->protinfo.ax25->digipeat->ndigi = addr->sax25_ndigis; + sk->protinfo.ax25->digipeat->lastrepeat = -1; while (ct < addr->sax25_ndigis) { - sk->protinfo.ax25->digipeat->repeated[ct] = 0; + if ((fsa->fsa_digipeater[ct].ax25_call[6] & AX25_HBIT) && sk->protinfo.ax25->iamdigi) { + sk->protinfo.ax25->digipeat->repeated[ct] = 1; + sk->protinfo.ax25->digipeat->lastrepeat = ct; + } else { + sk->protinfo.ax25->digipeat->repeated[ct] = 0; + } sk->protinfo.ax25->digipeat->calls[ct] = fsa->fsa_digipeater[ct]; ct++; } - - sk->protinfo.ax25->digipeat->lastrepeat = 0; } /* @@ -1496,7 +1490,7 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, return -EHOSTUNREACH; } - if (sk->type == SOCK_SEQPACKET && ax25_find_cb(&sk->protinfo.ax25->source_addr, &addr->sax25_call, sk->protinfo.ax25->device) != NULL) + if (sk->type == SOCK_SEQPACKET && ax25_find_cb(&sk->protinfo.ax25->source_addr, &addr->sax25_call, NULL, sk->protinfo.ax25->device) != NULL) return -EADDRINUSE; /* Already such a connection */ sk->protinfo.ax25->dest_addr = addr->sax25_call; @@ -1560,12 +1554,13 @@ static int ax25_accept(struct socket *sock, struct socket *newsock, int flags) struct sock *newsk; struct sk_buff *skb; - if (newsock->sk) - sk_free(newsock->sk); + if (newsock->sk != NULL) + ax25_destroy_socket(newsock->sk->protinfo.ax25); newsock->sk = NULL; - sk = (struct sock *)sock->sk; + if ((sk = sock->sk) == NULL) + return -EINVAL; if (sk->type != SOCK_SEQPACKET) return -EOPNOTSUPP; @@ -1582,7 +1577,7 @@ static int ax25_accept(struct socket *sock, struct socket *newsock, int flags) if ((skb = skb_dequeue(&sk->receive_queue)) == NULL) { if (flags & O_NONBLOCK) { sti(); - return 0; + return -EWOULDBLOCK; } interruptible_sleep_on(sk->sleep); if (current->signal & ~current->blocked) { @@ -1609,11 +1604,9 @@ static int ax25_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_len, int peer) { struct full_sockaddr_ax25 *sax = (struct full_sockaddr_ax25 *)uaddr; - struct sock *sk; + struct sock *sk = sock->sk; unsigned char ndigi, i; - sk = (struct sock *)sock->sk; - if (peer != 0) { if (sk->state != TCP_ESTABLISHED) return -ENOTCONN; @@ -1649,9 +1642,10 @@ static int ax25_rcv(struct sk_buff *skb, struct device *dev, ax25_address *dev_a struct sock *make; struct sock *sk; int type = 0; - ax25_digi dp; + ax25_digi dp, reverse_dp; ax25_cb *ax25; ax25_address src, dest; + ax25_address *next_digi = NULL; struct sock *raw; int mine = 0; int dama; @@ -1682,6 +1676,7 @@ static int ax25_rcv(struct sk_buff *skb, struct device *dev, ax25_address *dev_a * Ours perhaps ? */ if (dp.lastrepeat + 1 < dp.ndigi) { /* Not yet digipeated completely */ + next_digi = &dp.calls[dp.lastrepeat + 1]; if (ax25cmp(&dp.calls[dp.lastrepeat + 1], dev_addr) == 0) { struct device *dev_out = dev; @@ -1713,7 +1708,7 @@ static int ax25_rcv(struct sk_buff *skb, struct device *dev, ax25_address *dev_a return 0; } - build_ax25_addr(skb->data, &src, &dest, &dp, type, MODULUS); + build_ax25_addr(skb->data, &src, &dest, &dp, type, AX25_MODULUS); #ifdef CONFIG_FIREWALL if (call_fw_firewall(PF_AX25, skb->dev, skb->data, NULL) != FW_ACCEPT) { kfree_skb(skb, FREE_READ); @@ -1724,11 +1719,9 @@ static int ax25_rcv(struct sk_buff *skb, struct device *dev, ax25_address *dev_a skb->dev = dev_out; skb->priority = SOPRI_NORMAL; ax25_queue_xmit(skb); - } else { - kfree_skb(skb, FREE_READ); - } - return 0; + return 0; + } } /* @@ -1737,14 +1730,15 @@ static int ax25_rcv(struct sk_buff *skb, struct device *dev, ax25_address *dev_a skb_pull(skb, size_ax25_addr(&dp)); /* For our port addresses ? */ - if (ax25cmp(&dest, dev_addr) == 0) + if (ax25cmp(&dest, dev_addr) == 0 && dp.lastrepeat + 1 == dp.ndigi) mine = 1; /* Also match on any registered callsign from L3/4 */ - if (!mine && ax25_listen_mine(&dest, dev)) + if (!mine && ax25_listen_mine(&dest, dev) && dp.lastrepeat + 1 == dp.ndigi) mine = 1; - if ((*skb->data & ~0x10) == LAPB_UI) { /* UI frame - bypass LAPB processing */ + /* UI frame - bypass LAPB processing */ + if ((*skb->data & ~0x10) == AX25_UI && dp.lastrepeat + 1 == dp.ndigi) { skb->h.raw = skb->data + 2; /* skip control and pid */ if ((raw = ax25_addr_match(&dest)) != NULL) @@ -1786,8 +1780,8 @@ static int ax25_rcv(struct sk_buff *skb, struct device *dev, ax25_address *dev_a * Remove the control and PID. */ skb_pull(skb, 2); - skb_queue_tail(&sk->receive_queue, skb); skb_set_owner_r(skb, sk); + skb_queue_tail(&sk->receive_queue, skb); if (!sk->dead) sk->data_ready(sk, skb->len); } @@ -1818,7 +1812,9 @@ static int ax25_rcv(struct sk_buff *skb, struct device *dev, ax25_address *dev_a /* AX.25 state 1-4 */ - if ((ax25 = ax25_find_cb(&dest, &src, dev)) != NULL) { + ax25_digi_invert(&dp, &reverse_dp); + + if ((ax25 = ax25_find_cb(&dest, &src, &reverse_dp, dev)) != NULL) { /* * Process the frame. If it is queued up internally it returns one otherwise we * free it immediately. This routine itself wakes the user context layers so we @@ -1834,12 +1830,12 @@ static int ax25_rcv(struct sk_buff *skb, struct device *dev, ax25_address *dev_a /* a) received not a SABM(E) */ - if ((*skb->data & ~PF) != SABM && (*skb->data & ~PF) != SABME) { + if ((*skb->data & ~AX25_PF) != AX25_SABM && (*skb->data & ~AX25_PF) != AX25_SABME) { /* * Never reply to a DM. Also ignore any connects for * addresses that are not our interfaces and not a socket. */ - if ((*skb->data & ~PF) != DM && mine) + if ((*skb->data & ~AX25_PF) != AX25_DM && mine) ax25_return_dm(dev, &src, &dest, &dp); kfree_skb(skb, FREE_READ); @@ -1848,7 +1844,12 @@ static int ax25_rcv(struct sk_buff *skb, struct device *dev, ax25_address *dev_a /* b) received SABM(E) */ - if ((sk = ax25_find_listener(&dest, dev, SOCK_SEQPACKET)) != NULL) { + if (dp.lastrepeat + 1 == dp.ndigi) + sk = ax25_find_listener(&dest, 0, dev, SOCK_SEQPACKET); + else + sk = ax25_find_listener(next_digi, 1, dev, SOCK_SEQPACKET); + + if (sk != NULL) { if (sk->ack_backlog == sk->max_ack_backlog || (make = ax25_make_new(sk, dev)) == NULL) { if (mine) ax25_return_dm(dev, &src, &dest, &dp); @@ -1901,20 +1902,20 @@ static int ax25_rcv(struct sk_buff *skb, struct device *dev, ax25_address *dev_a } } else { /* Reverse the source SABM's path */ - ax25_digi_invert(&dp, ax25->digipeat); + *ax25->digipeat = reverse_dp; } - if ((*skb->data & ~PF) == SABME) { - ax25->modulus = EMODULUS; + if ((*skb->data & ~AX25_PF) == AX25_SABME) { + ax25->modulus = AX25_EMODULUS; ax25->window = ax25_dev_get_value(dev, AX25_VALUES_EWINDOW); } else { - ax25->modulus = MODULUS; + ax25->modulus = AX25_MODULUS; ax25->window = ax25_dev_get_value(dev, AX25_VALUES_WINDOW); } ax25->device = dev; - ax25_send_control(ax25, UA, POLLON, C_RESPONSE); + ax25_send_control(ax25, AX25_UA, AX25_POLLON, AX25_RESPONSE); if (dama) ax25_dama_on(ax25); /* bke 951121 */ @@ -1957,7 +1958,7 @@ static int kiss_rcv(struct sk_buff *skb, struct device *dev, struct packet_type static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct scm_cookie *scm) { - struct sock *sk = (struct sock *)sock->sk; + struct sock *sk = sock->sk; struct sockaddr_ax25 *usax = (struct sockaddr_ax25 *)msg->msg_name; int err; struct sockaddr_ax25 sax; @@ -1968,21 +1969,21 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, ax25_digi dtmp; int lv; int addr_len = msg->msg_namelen; - + if (msg->msg_flags & ~MSG_DONTWAIT) return -EINVAL; if (sk->zapped) return -EADDRNOTAVAIL; - + if (sk->shutdown & SEND_SHUTDOWN) { send_sig(SIGPIPE, current, 0); return -EPIPE; } - + if (sk->protinfo.ax25->device == NULL) return -ENETUNREACH; - + if (usax) { if (addr_len != sizeof(struct sockaddr_ax25) && addr_len != sizeof(struct full_sockaddr_ax25)) return -EINVAL; @@ -2040,8 +2041,7 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, if ((skb = sock_alloc_send_skb(sk, size, 0, msg->msg_flags & MSG_DONTWAIT, &err)) == NULL) return err; - skb->sk = sk; - skb->arp = 1; + skb->arp = 1; skb_reserve(skb, size - len); @@ -2078,7 +2078,7 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, } /* Build an AX.25 header */ - asmptr += (lv = build_ax25_addr(asmptr, &sk->protinfo.ax25->source_addr, &sax.sax25_call, dp, C_COMMAND, MODULUS)); + asmptr += (lv = build_ax25_addr(asmptr, &sk->protinfo.ax25->source_addr, &sax.sax25_call, dp, AX25_COMMAND, AX25_MODULUS)); if (sk->debug) printk("Built header (%d bytes)\n",lv); @@ -2088,7 +2088,7 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, if (sk->debug) printk("base=%p pos=%p\n", skb->data, asmptr); - *asmptr = LAPB_UI; + *asmptr = AX25_UI; /* Datagram frames go straight out of the door as UI */ skb->dev = sk->protinfo.ax25->device; @@ -2104,7 +2104,7 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, static int ax25_recvmsg(struct socket *sock, struct msghdr *msg, int size, int flags, struct scm_cookie *scm) { - struct sock *sk = (struct sock *)sock->sk; + struct sock *sk = sock->sk; struct sockaddr_ax25 *sax = (struct sockaddr_ax25 *)msg->msg_name; int copied, length; struct sk_buff *skb; @@ -2179,7 +2179,8 @@ static int ax25_shutdown(struct socket *sk, int how) static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) { - struct sock *sk = (struct sock *)sock->sk; + struct sock *sk = sock->sk; + struct ax25_info_struct ax25_info; int err; long amount = 0; @@ -2248,6 +2249,36 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) return -EPERM; return ax25_ctl_ioctl(cmd, (void *)arg); + case SIOCAX25GETINFO: + if ((err = verify_area(VERIFY_WRITE, (void *)arg, sizeof(ax25_info))) != 0) + return err; + ax25_info.t1 = sk->protinfo.ax25->t1; + ax25_info.t2 = sk->protinfo.ax25->t2; + ax25_info.t3 = sk->protinfo.ax25->t3; + ax25_info.idle = sk->protinfo.ax25->idle; + ax25_info.n2 = sk->protinfo.ax25->n2; + ax25_info.t1timer = sk->protinfo.ax25->t1timer; + ax25_info.t2timer = sk->protinfo.ax25->t2timer; + ax25_info.t3timer = sk->protinfo.ax25->t3timer; + ax25_info.idletimer = sk->protinfo.ax25->idletimer; + ax25_info.n2count = sk->protinfo.ax25->n2count; + ax25_info.state = sk->protinfo.ax25->state; + ax25_info.rcv_q = sk->rmem_alloc; + ax25_info.snd_q = sk->wmem_alloc; + copy_to_user((void *)arg, &ax25_info, sizeof(ax25_info)); + return 0; + + case SIOCAX25ADDFWD: + case SIOCAX25DELFWD: { + struct ax25_fwd_struct ax25_fwd; + if (!suser()) + return -EPERM; + if ((err = verify_area(VERIFY_READ, (void *)arg, sizeof(ax25_fwd))) != 0) + return err; + copy_from_user(&ax25_fwd, (void *)arg, sizeof(ax25_fwd)); + return ax25_fwd_ioctl(cmd, &ax25_fwd); + } + case SIOCGIFADDR: case SIOCSIFADDR: case SIOCGIFDSTADDR: @@ -2294,16 +2325,16 @@ static int ax25_get_info(char *buffer, char **start, off_t offset, int length, i ax2asc(&ax25->source_addr), devname, ax25->state, ax25->vs, ax25->vr, ax25->va, - ax25->t1timer / PR_SLOWHZ, - ax25->t1 / PR_SLOWHZ, - ax25->t2timer / PR_SLOWHZ, - ax25->t2 / PR_SLOWHZ, - ax25->t3timer / PR_SLOWHZ, - ax25->t3 / PR_SLOWHZ, - ax25->idletimer / (PR_SLOWHZ * 60), - ax25->idle / (PR_SLOWHZ * 60), + ax25->t1timer / AX25_SLOWHZ, + ax25->t1 / AX25_SLOWHZ, + ax25->t2timer / AX25_SLOWHZ, + ax25->t2 / AX25_SLOWHZ, + ax25->t3timer / AX25_SLOWHZ, + ax25->t3 / AX25_SLOWHZ, + ax25->idletimer / (AX25_SLOWHZ * 60), + ax25->idle / (AX25_SLOWHZ * 60), ax25->n2count, ax25->n2, - ax25->rtt / PR_SLOWHZ, + ax25->rtt / AX25_SLOWHZ, ax25->window, ax25->paclen); @@ -2360,7 +2391,7 @@ static struct proto_ops ax25_proto_ops = { ax25_shutdown, ax25_setsockopt, ax25_getsockopt, - ax25_fcntl, + sock_no_fcntl, ax25_sendmsg, ax25_recvmsg }; @@ -2384,7 +2415,6 @@ static struct notifier_block ax25_dev_notifier = { EXPORT_SYMBOL(ax25_encapsulate); EXPORT_SYMBOL(ax25_rebuild_header); -#if defined(CONFIG_NETROM_MODULE) || defined(CONFIG_ROSE_MODULE) EXPORT_SYMBOL(ax25_findbyuid); EXPORT_SYMBOL(ax25_link_up); EXPORT_SYMBOL(ax25_linkfail_register); @@ -2399,7 +2429,6 @@ EXPORT_SYMBOL(ax25cmp); EXPORT_SYMBOL(ax2asc); EXPORT_SYMBOL(asc2ax); EXPORT_SYMBOL(null_ax25_address); -#endif #ifdef CONFIG_PROC_FS static struct proc_dir_entry proc_ax25_route = { @@ -2440,7 +2469,8 @@ void ax25_proto_init(struct net_proto *pro) } /* - * A small shim to dev_queue_xmit to add the KISS control byte. + * A small shim to dev_queue_xmit to add the KISS control byte, and do + * any packet forwarding in operation. */ void ax25_queue_xmit(struct sk_buff *skb) { @@ -2454,6 +2484,7 @@ void ax25_queue_xmit(struct sk_buff *skb) #endif skb->protocol = htons(ETH_P_AX25); + skb->dev = ax25_fwd_dev(skb->dev); ptr = skb_push(skb, 1); *ptr++ = 0; /* KISS */ @@ -2482,9 +2513,9 @@ int ax25_encapsulate(struct sk_buff *skb, struct device *dev, unsigned short typ if (daddr != NULL) memcpy(buff, daddr, dev->addr_len); /* Address specified */ - buff[6] &= ~LAPB_C; - buff[6] &= ~LAPB_E; - buff[6] |= SSSID_SPARE; + buff[6] &= ~AX25_CBIT; + buff[6] &= ~AX25_EBIT; + buff[6] |= AX25_SSSID_SPARE; buff += AX25_ADDR_LEN; if (saddr != NULL) @@ -2492,19 +2523,18 @@ int ax25_encapsulate(struct sk_buff *skb, struct device *dev, unsigned short typ else memcpy(buff, dev->dev_addr, dev->addr_len); - buff[6] &= ~LAPB_C; - buff[6] |= LAPB_E; - buff[6] |= SSSID_SPARE; + buff[6] &= ~AX25_CBIT; + buff[6] |= AX25_EBIT; + buff[6] |= AX25_SSSID_SPARE; buff += AX25_ADDR_LEN; - *buff++ = LAPB_UI; /* UI */ + *buff++ = AX25_UI; /* UI */ /* Append a suitable AX.25 PID */ switch (type) { case ETH_P_IP: *buff++ = AX25_P_IP; break; - case ETH_P_ARP: *buff++ = AX25_P_ARP; break; @@ -2548,8 +2578,8 @@ int ax25_rebuild_header(struct sk_buff *skb) return 1; } - if (ourskb->sk != NULL) - skb_set_owner_w(ourskb, ourskb->sk); + if (skb->sk != NULL) + skb_set_owner_w(ourskb, skb->sk); kfree_skb(skb, FREE_WRITE); @@ -2561,13 +2591,13 @@ int ax25_rebuild_header(struct sk_buff *skb) } } - bp[7] &= ~LAPB_C; - bp[7] &= ~LAPB_E; - bp[7] |= SSSID_SPARE; + bp[7] &= ~AX25_CBIT; + bp[7] &= ~AX25_EBIT; + bp[7] |= AX25_SSSID_SPARE; - bp[14] &= ~LAPB_C; - bp[14] |= LAPB_E; - bp[14] |= SSSID_SPARE; + bp[14] &= ~AX25_CBIT; + bp[14] |= AX25_EBIT; + bp[14] |= AX25_SSSID_SPARE; /* * dl1bke 960317: we use ax25_queue_xmit here to allow mode datagram diff --git a/net/ax25/ax25_in.c b/net/ax25/ax25_in.c index 1e94adfda053..3320cdcd3131 100644 --- a/net/ax25/ax25_in.c +++ b/net/ax25/ax25_in.c @@ -72,12 +72,12 @@ static int ax25_rx_fragment(ax25_cb *ax25, struct sk_buff *skb) { struct sk_buff *skbn, *skbo; int hdrlen, nhdrlen; - + if (ax25->fragno != 0) { - if (!(*skb->data & SEG_FIRST)) { - if ((ax25->fragno - 1) == (*skb->data & SEG_REM)) { + if (!(*skb->data & AX25_SEG_FIRST)) { + if ((ax25->fragno - 1) == (*skb->data & AX25_SEG_REM)) { /* Enqueue fragment */ - ax25->fragno = *skb->data & SEG_REM; + ax25->fragno = *skb->data & AX25_SEG_REM; skb_pull(skb, 1); /* skip fragno */ ax25->fraglen += skb->len; skb_queue_tail(&ax25->frag_queue, skb); @@ -123,16 +123,16 @@ static int ax25_rx_fragment(ax25_cb *ax25, struct sk_buff *skb) if (ax25_rx_iframe(ax25, skbn) == 0) kfree_skb(skbn, FREE_READ); } - + return 1; } } } else { /* First fragment received */ - if (*skb->data & SEG_FIRST) { + if (*skb->data & AX25_SEG_FIRST) { while ((skbo = skb_dequeue(&ax25->frag_queue)) != NULL) kfree_skb(skbo, FREE_READ); - ax25->fragno = *skb->data & SEG_REM; + ax25->fragno = *skb->data & AX25_SEG_REM; skb_pull(skb, 1); /* skip fragno */ ax25->fraglen = skb->len; skb_queue_tail(&ax25->frag_queue, skb); @@ -152,7 +152,7 @@ static int ax25_rx_iframe(ax25_cb *ax25, struct sk_buff *skb) int (*func)(struct sk_buff *, ax25_cb *); volatile int queued = 0; unsigned char pid; - + if (skb == NULL) return 0; ax25->idletimer = ax25->idle; @@ -179,12 +179,12 @@ static int ax25_rx_iframe(ax25_cb *ax25, struct sk_buff *skb) skb_pull(skb, 1); /* Remove PID */ return (*func)(skb, ax25); } - + if (ax25->sk != NULL && ax25_dev_get_value(ax25->device, AX25_VALUES_TEXT) && ax25->sk->protocol == pid) { if (sock_queue_rcv_skb(ax25->sk, skb) == 0) queued = 1; else - ax25->condition |= OWN_RX_BUSY_CONDITION; + ax25->condition |= AX25_COND_OWN_RX_BUSY; } return queued; @@ -198,23 +198,23 @@ static int ax25_rx_iframe(ax25_cb *ax25, struct sk_buff *skb) static int ax25_state1_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype, int pf, int type, int dama) { switch (frametype) { - case SABM: - ax25->modulus = MODULUS; + case AX25_SABM: + ax25->modulus = AX25_MODULUS; ax25->window = ax25_dev_get_value(ax25->device, AX25_VALUES_WINDOW); - ax25_send_control(ax25, UA, pf, C_RESPONSE); + ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE); break; - case SABME: - ax25->modulus = EMODULUS; + case AX25_SABME: + ax25->modulus = AX25_EMODULUS; ax25->window = ax25_dev_get_value(ax25->device, AX25_VALUES_EWINDOW); - ax25_send_control(ax25, UA, pf, C_RESPONSE); + ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE); break; - case DISC: - ax25_send_control(ax25, DM, pf, C_RESPONSE); + case AX25_DISC: + ax25_send_control(ax25, AX25_DM, pf, AX25_RESPONSE); break; - case UA: + case AX25_UA: if (pf || dama) { if (dama) ax25_dama_on(ax25); /* bke */ @@ -238,9 +238,9 @@ static int ax25_state1_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype } break; - case DM: + case AX25_DM: if (pf) { - if (ax25->modulus == MODULUS) { + if (ax25->modulus == AX25_MODULUS) { ax25_clear_queues(ax25); ax25->state = AX25_STATE_0; if (ax25->sk != NULL) { @@ -252,7 +252,7 @@ static int ax25_state1_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype ax25->sk->dead = 1; } } else { - ax25->modulus = MODULUS; + ax25->modulus = AX25_MODULUS; ax25->window = ax25_dev_get_value(ax25->device, AX25_VALUES_WINDOW); } } @@ -260,7 +260,7 @@ static int ax25_state1_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype default: if (dama && pf) - ax25_send_control(ax25, SABM, POLLON, C_COMMAND); + ax25_send_control(ax25, AX25_SABM, AX25_POLLON, AX25_COMMAND); break; } @@ -275,15 +275,15 @@ static int ax25_state1_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype static int ax25_state2_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype, int pf, int type) { switch (frametype) { - case SABM: - case SABME: - ax25_send_control(ax25, DM, pf, C_RESPONSE); + case AX25_SABM: + case AX25_SABME: + ax25_send_control(ax25, AX25_DM, pf, AX25_RESPONSE); if (ax25->dama_slave) - ax25_send_control(ax25, DISC, POLLON, C_COMMAND); + ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND); break; - case DISC: - ax25_send_control(ax25, UA, pf, C_RESPONSE); + case AX25_DISC: + ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE); if (ax25->dama_slave) { ax25->state = AX25_STATE_0; ax25_dama_off(ax25); @@ -298,7 +298,7 @@ static int ax25_state2_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype } break; - case UA: + case AX25_UA: if (pf) { ax25->state = AX25_STATE_0; ax25_dama_off(ax25); @@ -313,7 +313,7 @@ static int ax25_state2_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype } break; - case DM: + case AX25_DM: if (pf) { ax25->state = AX25_STATE_0; ax25_dama_off(ax25); @@ -328,18 +328,18 @@ static int ax25_state2_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype } break; - case I: - case REJ: - case RNR: - case RR: + case AX25_I: + case AX25_REJ: + case AX25_RNR: + case AX25_RR: if (pf) { if (ax25->dama_slave) - ax25_send_control(ax25, DISC, POLLON, C_COMMAND); + ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND); else - ax25_send_control(ax25, DM, POLLON, C_RESPONSE); + ax25_send_control(ax25, AX25_DM, AX25_POLLON, AX25_RESPONSE); } break; - + default: break; } @@ -357,11 +357,11 @@ static int ax25_state3_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype int queued = 0; switch (frametype) { - case SABM: + case AX25_SABM: if (dama) ax25_dama_on(ax25); - ax25->modulus = MODULUS; + ax25->modulus = AX25_MODULUS; ax25->window = ax25_dev_get_value(ax25->device, AX25_VALUES_WINDOW); - ax25_send_control(ax25, UA, pf, C_RESPONSE); + ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE); ax25->condition = 0x00; ax25->t1timer = 0; ax25->t3timer = ax25->t3; @@ -372,11 +372,11 @@ static int ax25_state3_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype ax25->dama_slave = dama; break; - case SABME: + case AX25_SABME: if (dama) ax25_dama_on(ax25); - ax25->modulus = EMODULUS; + ax25->modulus = AX25_EMODULUS; ax25->window = ax25_dev_get_value(ax25->device, AX25_VALUES_EWINDOW); - ax25_send_control(ax25, UA, pf, C_RESPONSE); + ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE); ax25->condition = 0x00; ax25->t1timer = 0; ax25->t3timer = ax25->t3; @@ -387,9 +387,9 @@ static int ax25_state3_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype ax25->dama_slave = dama; break; - case DISC: + case AX25_DISC: ax25_clear_queues(ax25); - ax25_send_control(ax25, UA, pf, C_RESPONSE); + ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE); ax25->t3timer = 0; ax25->state = AX25_STATE_0; ax25_dama_off(ax25); @@ -403,7 +403,7 @@ static int ax25_state3_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype } break; - case DM: + case AX25_DM: ax25_clear_queues(ax25); ax25->t3timer = 0; ax25->state = AX25_STATE_0; @@ -418,8 +418,8 @@ static int ax25_state3_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype } break; - case RNR: - ax25->condition |= PEER_RX_BUSY_CONDITION; + case AX25_RNR: + ax25->condition |= AX25_COND_PEER_RX_BUSY; ax25_check_need_response(ax25, type, pf); if (ax25_validate_nr(ax25, nr)) { ax25_check_iframes_acked(ax25, nr); @@ -429,9 +429,9 @@ static int ax25_state3_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype ax25->state = AX25_STATE_1; } break; - - case RR: - ax25->condition &= ~PEER_RX_BUSY_CONDITION; + + case AX25_RR: + ax25->condition &= ~AX25_COND_PEER_RX_BUSY; ax25_check_need_response(ax25, type, pf); if (ax25_validate_nr(ax25, nr)) { ax25_check_iframes_acked(ax25, nr); @@ -441,9 +441,9 @@ static int ax25_state3_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype ax25->state = AX25_STATE_1; } break; - - case REJ: - ax25->condition &= ~PEER_RX_BUSY_CONDITION; + + case AX25_REJ: + ax25->condition &= ~AX25_COND_PEER_RX_BUSY; ax25_check_need_response(ax25, type, pf); if (ax25_validate_nr(ax25, nr)) { ax25_frames_acked(ax25, nr); @@ -457,23 +457,19 @@ static int ax25_state3_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype ax25->state = AX25_STATE_1; } break; - - case I: -#ifndef AX25_BROKEN_NETMAC - if (type != C_COMMAND) - break; -#endif + + case AX25_I: if (!ax25_validate_nr(ax25, nr)) { ax25_nr_error_recovery(ax25); ax25->state = AX25_STATE_1; break; } - if (ax25->condition & PEER_RX_BUSY_CONDITION) { + if (ax25->condition & AX25_COND_PEER_RX_BUSY) { ax25_frames_acked(ax25, nr); } else { ax25_check_iframes_acked(ax25, nr); } - if (ax25->condition & OWN_RX_BUSY_CONDITION) { + if (ax25->condition & AX25_COND_OWN_RX_BUSY) { if (pf) { if (ax25->dama_slave) dama_enquiry_response(ax25); @@ -485,7 +481,7 @@ static int ax25_state3_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype if (ns == ax25->vr) { ax25->vr = (ax25->vr + 1) % ax25->modulus; queued = ax25_rx_iframe(ax25, skb); - if (ax25->condition & OWN_RX_BUSY_CONDITION) { + if (ax25->condition & AX25_COND_OWN_RX_BUSY) { ax25->vr = ns; /* ax25->vr - 1 */ if (pf) { if (ax25->dama_slave) @@ -495,20 +491,20 @@ static int ax25_state3_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype } break; } - ax25->condition &= ~REJECT_CONDITION; + ax25->condition &= ~AX25_COND_REJECT; if (pf) { if (ax25->dama_slave) dama_enquiry_response(ax25); else ax25_enquiry_response(ax25); } else { - if (!(ax25->condition & ACK_PENDING_CONDITION)) { + if (!(ax25->condition & AX25_COND_ACK_PENDING)) { ax25->t2timer = ax25->t2; - ax25->condition |= ACK_PENDING_CONDITION; + ax25->condition |= AX25_COND_ACK_PENDING; } } } else { - if (ax25->condition & REJECT_CONDITION) { + if (ax25->condition & AX25_COND_REJECT) { if (pf) { if (ax25->dama_slave) dama_enquiry_response(ax25); @@ -516,18 +512,18 @@ static int ax25_state3_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype ax25_enquiry_response(ax25); } } else { - ax25->condition |= REJECT_CONDITION; + ax25->condition |= AX25_COND_REJECT; if (ax25->dama_slave) dama_enquiry_response(ax25); else - ax25_send_control(ax25, REJ, pf, C_RESPONSE); - ax25->condition &= ~ACK_PENDING_CONDITION; + ax25_send_control(ax25, AX25_REJ, pf, AX25_RESPONSE); + ax25->condition &= ~AX25_COND_ACK_PENDING; } } break; - case FRMR: - case ILLEGAL: + case AX25_FRMR: + case AX25_ILLEGAL: ax25_establish_data_link(ax25); ax25->state = AX25_STATE_1; break; @@ -549,12 +545,12 @@ static int ax25_state4_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype int queued = 0; switch (frametype) { - case SABM: + case AX25_SABM: if (dama) ax25_dama_on(ax25); ax25->dama_slave = dama; - ax25->modulus = MODULUS; + ax25->modulus = AX25_MODULUS; ax25->window = ax25_dev_get_value(ax25->device, AX25_VALUES_WINDOW); - ax25_send_control(ax25, UA, pf, C_RESPONSE); + ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE); ax25->condition = 0x00; ax25->t1timer = 0; ax25->t3timer = ax25->t3; @@ -566,12 +562,12 @@ static int ax25_state4_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype ax25->n2count = 0; break; - case SABME: + case AX25_SABME: if (dama) ax25_dama_on(ax25); ax25->dama_slave = dama; - ax25->modulus = EMODULUS; + ax25->modulus = AX25_EMODULUS; ax25->window = ax25_dev_get_value(ax25->device, AX25_VALUES_EWINDOW); - ax25_send_control(ax25, UA, pf, C_RESPONSE); + ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE); ax25->condition = 0x00; ax25->t1timer = 0; ax25->t3timer = ax25->t3; @@ -583,9 +579,9 @@ static int ax25_state4_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype ax25->n2count = 0; break; - case DISC: + case AX25_DISC: ax25_clear_queues(ax25); - ax25_send_control(ax25, UA, pf, C_RESPONSE); + ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE); ax25->t3timer = 0; ax25->state = AX25_STATE_0; ax25_dama_off(ax25); @@ -599,7 +595,7 @@ static int ax25_state4_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype } break; - case DM: + case AX25_DM: ax25_clear_queues(ax25); ax25->t3timer = 0; ax25->state = AX25_STATE_0; @@ -614,9 +610,9 @@ static int ax25_state4_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype } break; - case RNR: - ax25->condition |= PEER_RX_BUSY_CONDITION; - if (type == C_RESPONSE && pf) { + case AX25_RNR: + ax25->condition |= AX25_COND_PEER_RX_BUSY; + if (type == AX25_RESPONSE && pf) { ax25->t1timer = 0; if (ax25_validate_nr(ax25, nr)) { ax25_frames_acked(ax25, nr); @@ -631,7 +627,7 @@ static int ax25_state4_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype } break; } - + ax25_check_need_response(ax25, type, pf); if (ax25_validate_nr(ax25, nr)) { ax25_frames_acked(ax25, nr); @@ -641,10 +637,10 @@ static int ax25_state4_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype ax25->state = AX25_STATE_1; } break; - - case RR: - ax25->condition &= ~PEER_RX_BUSY_CONDITION; - if (pf && (type == C_RESPONSE || (ax25->dama_slave && type == C_COMMAND))) { + + case AX25_RR: + ax25->condition &= ~AX25_COND_PEER_RX_BUSY; + if (pf && (type == AX25_RESPONSE || (ax25->dama_slave && type == AX25_COMMAND))) { ax25->t1timer = 0; if (ax25_validate_nr(ax25, nr)) { ax25_frames_acked(ax25, nr); @@ -673,9 +669,9 @@ static int ax25_state4_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype } break; - case REJ: - ax25->condition &= ~PEER_RX_BUSY_CONDITION; - if (pf && (type == C_RESPONSE || (ax25->dama_slave && type == C_COMMAND))) { + case AX25_REJ: + ax25->condition &= ~AX25_COND_PEER_RX_BUSY; + if (pf && (type == AX25_RESPONSE || (ax25->dama_slave && type == AX25_COMMAND))) { ax25->t1timer = 0; if (ax25_validate_nr(ax25, nr)) { ax25_frames_acked(ax25, nr); @@ -693,7 +689,7 @@ static int ax25_state4_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype } break; } - + ax25_check_need_response(ax25, type, pf); if (ax25_validate_nr(ax25, nr)) { ax25_frames_acked(ax25, nr); @@ -707,18 +703,14 @@ static int ax25_state4_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype } break; - case I: -#ifndef AX25_BROKEN_NETMAC - if (type != C_COMMAND) - break; -#endif + case AX25_I: if (!ax25_validate_nr(ax25, nr)) { ax25_nr_error_recovery(ax25); ax25->state = AX25_STATE_1; break; } ax25_frames_acked(ax25, nr); - if (ax25->condition & OWN_RX_BUSY_CONDITION) { + if (ax25->condition & AX25_COND_OWN_RX_BUSY) { if (pf) { if (ax25->dama_slave) ax25_enquiry_response(ax25); @@ -730,7 +722,7 @@ static int ax25_state4_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype if (ns == ax25->vr) { ax25->vr = (ax25->vr + 1) % ax25->modulus; queued = ax25_rx_iframe(ax25, skb); - if (ax25->condition & OWN_RX_BUSY_CONDITION) { + if (ax25->condition & AX25_COND_OWN_RX_BUSY) { ax25->vr = ns; /* ax25->vr - 1 */ if (pf) { if (ax25->dama_slave) @@ -740,20 +732,20 @@ static int ax25_state4_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype } break; } - ax25->condition &= ~REJECT_CONDITION; + ax25->condition &= ~AX25_COND_REJECT; if (pf) { if (ax25->dama_slave) dama_enquiry_response(ax25); else ax25_enquiry_response(ax25); } else { - if (!(ax25->condition & ACK_PENDING_CONDITION)) { + if (!(ax25->condition & AX25_COND_ACK_PENDING)) { ax25->t2timer = ax25->t2; - ax25->condition |= ACK_PENDING_CONDITION; + ax25->condition |= AX25_COND_ACK_PENDING; } } } else { - if (ax25->condition & REJECT_CONDITION) { + if (ax25->condition & AX25_COND_REJECT) { if (pf) { if (ax25->dama_slave) dama_enquiry_response(ax25); @@ -761,18 +753,18 @@ static int ax25_state4_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype ax25_enquiry_response(ax25); } } else { - ax25->condition |= REJECT_CONDITION; + ax25->condition |= AX25_COND_REJECT; if (ax25->dama_slave) dama_enquiry_response(ax25); else - ax25_send_control(ax25, REJ, pf, C_RESPONSE); - ax25->condition &= ~ACK_PENDING_CONDITION; + ax25_send_control(ax25, AX25_REJ, pf, AX25_RESPONSE); + ax25->condition &= ~AX25_COND_ACK_PENDING; } } break; - - case FRMR: - case ILLEGAL: + + case AX25_FRMR: + case AX25_ILLEGAL: ax25_establish_data_link(ax25); ax25->state = AX25_STATE_1; break; @@ -790,7 +782,7 @@ static int ax25_state4_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype int ax25_process_rx_frame(ax25_cb *ax25, struct sk_buff *skb, int type, int dama) { int queued = 0, frametype, ns, nr, pf; - + if (ax25->state == AX25_STATE_0) return 0; diff --git a/net/ax25/ax25_out.c b/net/ax25/ax25_out.c index a12f18fa544b..2ebb77f56066 100644 --- a/net/ax25/ax25_out.c +++ b/net/ax25/ax25_out.c @@ -64,17 +64,9 @@ void ax25_output(ax25_cb *ax25, struct sk_buff *skb) unsigned char *p; int frontlen, mtu, len, fragno, ka9qfrag, first = 1; long flags; - - /* - * dl1bke 960301: We use the new PACLEN parameter as MTU of the AX.25 layer. - * This will (hopefully) allow user programs to write() data - * w/o having to think of the maximal amount of data we can - * send with one call. It's called PACLEN to (1) avoid confusion - * with (IP) MTU and (2) TAPR calls this PACLEN, too ;-) - */ mtu = ax25->paclen; - + if ((skb->len - 1) > mtu) { if (*skb->data == AX25_P_TEXT) { skb_pull(skb, 1); /* skip PID */ @@ -83,7 +75,7 @@ void ax25_output(ax25_cb *ax25, struct sk_buff *skb) mtu -= 2; /* Allow for fragment control info */ ka9qfrag = 1; } - + fragno = skb->len / mtu; if (skb->len % mtu == 0) fragno--; @@ -92,17 +84,14 @@ void ax25_output(ax25_cb *ax25, struct sk_buff *skb) while (skb->len > 0) { save_flags(flags); cli(); - /* - * do _not_ use sock_alloc_send_skb, our socket may have - * sk->shutdown set... - */ + if ((skbn = alloc_skb(mtu + 2 + frontlen, GFP_ATOMIC)) == NULL) { restore_flags(flags); printk(KERN_DEBUG "ax25_output: alloc_skb returned NULL\n"); return; } - if (skbn->sk) + if (skb->sk != NULL) skb_set_owner_w(skbn, skb->sk); restore_flags(flags); @@ -110,7 +99,7 @@ void ax25_output(ax25_cb *ax25, struct sk_buff *skb) skbn->arp = 1; len = (mtu > skb->len) ? skb->len : mtu; - + if (ka9qfrag == 1) { skb_reserve(skbn, frontlen + 2); @@ -121,7 +110,7 @@ void ax25_output(ax25_cb *ax25, struct sk_buff *skb) *p = fragno--; if (first) { - *p |= SEG_FIRST; + *p |= AX25_SEG_FIRST; first = 0; } } else { @@ -134,7 +123,7 @@ void ax25_output(ax25_cb *ax25, struct sk_buff *skb) skb_pull(skb, len); skb_queue_tail(&ax25->write_queue, skbn); /* Throw it on the queue */ } - + kfree_skb(skb, FREE_WRITE); } else { skb_queue_tail(&ax25->write_queue, skb); /* Throw it on the queue */ @@ -157,23 +146,23 @@ static void ax25_send_iframe(ax25_cb *ax25, struct sk_buff *skb, int poll_bit) if (skb == NULL) return; - if (ax25->modulus == MODULUS) { + if (ax25->modulus == AX25_MODULUS) { frame = skb_push(skb, 1); - *frame = I; - *frame |= (poll_bit) ? PF : 0; + *frame = AX25_I; + *frame |= (poll_bit) ? AX25_PF : 0; *frame |= (ax25->vr << 5); *frame |= (ax25->vs << 1); } else { frame = skb_push(skb, 2); - frame[0] = I; + frame[0] = AX25_I; frame[0] |= (ax25->vs << 1); - frame[1] = (poll_bit) ? EPF : 0; + frame[1] = (poll_bit) ? AX25_EPF : 0; frame[1] |= (ax25->vr << 1); } - ax25_transmit_buffer(ax25, skb, C_COMMAND); + ax25_transmit_buffer(ax25, skb, AX25_COMMAND); } void ax25_kick(ax25_cb *ax25) @@ -187,8 +176,8 @@ void ax25_kick(ax25_cb *ax25) start = (skb_peek(&ax25->ack_queue) == NULL) ? ax25->va : ax25->vs; end = (ax25->va + ax25->window) % ax25->modulus; - if (!(ax25->condition & PEER_RX_BUSY_CONDITION) && - start != end && + if (!(ax25->condition & AX25_COND_PEER_RX_BUSY) && + start != end && skb_peek(&ax25->write_queue) != NULL) { ax25->vs = start; @@ -210,18 +199,18 @@ void ax25_kick(ax25_cb *ax25) break; } + if (skb->sk != NULL) + skb_set_owner_w(skbn, skb->sk); + next = (ax25->vs + 1) % ax25->modulus; -#ifdef notdef - last = (next == end) || skb_peek(&ax25->write_queue) == NULL; -#else last = (next == end); -#endif + /* * Transmit the frame copy. * bke 960114: do not set the Poll bit on the last frame * in DAMA mode. */ - ax25_send_iframe(ax25, skbn, (last && !ax25->dama_slave) ? POLLON : POLLOFF); + ax25_send_iframe(ax25, skbn, (last && !ax25->dama_slave) ? AX25_POLLON : AX25_POLLOFF); ax25->vs = next; @@ -229,12 +218,10 @@ void ax25_kick(ax25_cb *ax25) * Requeue the original data frame. */ skb_queue_tail(&ax25->ack_queue, skb); -#ifdef notdef - } while (!last); -#else + } while (!last && (skb = skb_dequeue(&ax25->write_queue)) != NULL); -#endif - ax25->condition &= ~ACK_PENDING_CONDITION; + + ax25->condition &= ~AX25_COND_ACK_PENDING; if (ax25->t1timer == 0) { ax25->t3timer = 0; @@ -292,12 +279,11 @@ void ax25_establish_data_link(ax25_cb *ax25) ax25->condition = 0x00; ax25->n2count = 0; - if (ax25->modulus == MODULUS) { - ax25_send_control(ax25, SABM, POLLON, C_COMMAND); - } else { - ax25_send_control(ax25, SABME, POLLON, C_COMMAND); - } - + if (ax25->modulus == AX25_MODULUS) + ax25_send_control(ax25, AX25_SABM, AX25_POLLON, AX25_COMMAND); + else + ax25_send_control(ax25, AX25_SABME, AX25_POLLON, AX25_COMMAND); + ax25->t3timer = 0; ax25->t2timer = 0; ax25->t1timer = ax25->t1 = ax25_calculate_t1(ax25); @@ -305,34 +291,34 @@ void ax25_establish_data_link(ax25_cb *ax25) void ax25_transmit_enquiry(ax25_cb *ax25) { - if (ax25->condition & OWN_RX_BUSY_CONDITION) - ax25_send_control(ax25, RNR, POLLON, C_COMMAND); + if (ax25->condition & AX25_COND_OWN_RX_BUSY) + ax25_send_control(ax25, AX25_RNR, AX25_POLLON, AX25_COMMAND); else - ax25_send_control(ax25, RR, POLLON, C_COMMAND); + ax25_send_control(ax25, AX25_RR, AX25_POLLON, AX25_COMMAND); - ax25->condition &= ~ACK_PENDING_CONDITION; + ax25->condition &= ~AX25_COND_ACK_PENDING; ax25->t1timer = ax25->t1 = ax25_calculate_t1(ax25); } void ax25_enquiry_response(ax25_cb *ax25) { - if (ax25->condition & OWN_RX_BUSY_CONDITION) - ax25_send_control(ax25, RNR, POLLON, C_RESPONSE); + if (ax25->condition & AX25_COND_OWN_RX_BUSY) + ax25_send_control(ax25, AX25_RNR, AX25_POLLON, AX25_RESPONSE); else - ax25_send_control(ax25, RR, POLLON, C_RESPONSE); + ax25_send_control(ax25, AX25_RR, AX25_POLLON, AX25_RESPONSE); - ax25->condition &= ~ACK_PENDING_CONDITION; + ax25->condition &= ~AX25_COND_ACK_PENDING; } void ax25_timeout_response(ax25_cb *ax25) { - if (ax25->condition & OWN_RX_BUSY_CONDITION) - ax25_send_control(ax25, RNR, POLLOFF, C_RESPONSE); + if (ax25->condition & AX25_COND_OWN_RX_BUSY) + ax25_send_control(ax25, AX25_RNR, AX25_POLLOFF, AX25_RESPONSE); else - ax25_send_control(ax25, RR, POLLOFF, C_RESPONSE); + ax25_send_control(ax25, AX25_RR, AX25_POLLOFF, AX25_RESPONSE); - ax25->condition &= ~ACK_PENDING_CONDITION; + ax25->condition &= ~AX25_COND_ACK_PENDING; } void ax25_check_iframes_acked(ax25_cb *ax25, unsigned short nr) @@ -356,7 +342,7 @@ void ax25_check_iframes_acked(ax25_cb *ax25, unsigned short nr) */ void ax25_check_need_response(ax25_cb *ax25, int type, int pf) { - if (!ax25->dama_slave && type == C_COMMAND && pf) + if (!ax25->dama_slave && type == AX25_COMMAND && pf) ax25_enquiry_response(ax25); } @@ -366,35 +352,32 @@ void ax25_check_need_response(ax25_cb *ax25, int type, int pf) void dama_enquiry_response(ax25_cb *ax25) { ax25_cb *ax25o; - - if (!(ax25->condition & PEER_RX_BUSY_CONDITION)) { + + if (!(ax25->condition & AX25_COND_PEER_RX_BUSY)) { ax25_requeue_frames(ax25); ax25_kick(ax25); } - if (ax25->state == AX25_STATE_1 || ax25->state == AX25_STATE_2 || - skb_peek(&ax25->ack_queue) != NULL) { + if (ax25->state == AX25_STATE_1 || ax25->state == AX25_STATE_2 || skb_peek(&ax25->ack_queue) != NULL) ax25_t1_timeout(ax25); - } else { + else ax25->n2count = 0; - } - + ax25->t3timer = ax25->t3; - /* The FLEXNET DAMA master implementation refuses to send us ANY */ /* I frame for this connection if we send a REJ here, probably */ /* due to its frame collector scheme? A simple RR or RNR will */ /* invoke the retransmission, and in fact REJs are superfluous */ /* in DAMA mode anyway... */ - + #if 0 - if (ax25->condition & REJECT_CONDITION) - ax25_send_control(ax25, REJ, POLLOFF, C_RESPONSE); + if (ax25->condition & AX25_COND_REJECT) + ax25_send_control(ax25, AX25_REJ, AX25_POLLOFF, AX25_RESPONSE); else -#endif +#endif ax25_enquiry_response(ax25); - + /* Note that above response to the poll could be sent behind the */ /* transmissions of the other channels as well... This version */ /* gives better performance on FLEXNET nodes. (Why, Gunter?) */ @@ -413,18 +396,16 @@ void dama_enquiry_response(ax25_cb *ax25) if (!ax25o->dama_slave) continue; - - if ( !(ax25o->condition & PEER_RX_BUSY_CONDITION) && + + if ( !(ax25o->condition & AX25_COND_PEER_RX_BUSY) && (ax25o->state == AX25_STATE_3 || (ax25o->state == AX25_STATE_4 && ax25o->t1timer == 0))) { ax25_requeue_frames(ax25o); ax25_kick(ax25o); } - - if (ax25o->state == AX25_STATE_1 || ax25o->state == AX25_STATE_2 || - skb_peek(&ax25o->ack_queue) != NULL) { + + if (ax25o->state == AX25_STATE_1 || ax25o->state == AX25_STATE_2 || skb_peek(&ax25o->ack_queue) != NULL) ax25_t1_timeout(ax25o); - } ax25o->t3timer = ax25o->t3; } @@ -432,7 +413,7 @@ void dama_enquiry_response(ax25_cb *ax25) void dama_check_need_response(ax25_cb *ax25, int type, int pf) { - if (ax25->dama_slave && type == C_COMMAND && pf) + if (ax25->dama_slave && type == AX25_COMMAND && pf) dama_enquiry_response(ax25); } diff --git a/net/ax25/ax25_route.c b/net/ax25/ax25_route.c index 4ad193d3b0d0..afbe00cd4bd7 100644 --- a/net/ax25/ax25_route.c +++ b/net/ax25/ax25_route.c @@ -39,8 +39,10 @@ * on routes. * AX.25 033 Jonathan(G4KLX) Remove auto-router. * Joerg(DL1BKE) Moved BPQ Ethernet driver to seperate device. + * AX.25 035 Frederic(F1OAT) Support for pseudo-digipeating. + * Jonathan(G4KLX) Support for packet forwarding. */ - + #include #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) #include @@ -121,7 +123,7 @@ void ax25_rt_device_down(struct device *dev) kfree_s((void *)s, sizeof(*s)); break; } - } + } } } } @@ -154,7 +156,7 @@ int ax25_rt_ioctl(unsigned int cmd, void *arg) if (route.digi_count != 0) { if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) return -ENOMEM; - ax25_rt->digipeat->lastrepeat = 0; + ax25_rt->digipeat->lastrepeat = -1; ax25_rt->digipeat->ndigi = route.digi_count; for (i = 0; i < route.digi_count; i++) { ax25_rt->digipeat->repeated[i] = 0; @@ -175,7 +177,7 @@ int ax25_rt_ioctl(unsigned int cmd, void *arg) kfree_s(ax25_rt, sizeof(struct ax25_route)); return -ENOMEM; } - ax25_rt->digipeat->lastrepeat = 0; + ax25_rt->digipeat->lastrepeat = -1; ax25_rt->digipeat->ndigi = route.digi_count; for (i = 0; i < route.digi_count; i++) { ax25_rt->digipeat->repeated[i] = 0; @@ -287,20 +289,20 @@ int ax25_rt_get_info(char *buffer, char **start, off_t offset, int length, int d len += sprintf(buffer + len, " *"); break; } - + if (ax25_rt->digipeat != NULL) for (i = 0; i < ax25_rt->digipeat->ndigi; i++) len += sprintf(buffer + len, " %s", ax2asc(&ax25_rt->digipeat->calls[i])); - + len += sprintf(buffer + len, "\n"); - + pos = begin + len; if (pos < offset) { len = 0; begin = pos; } - + if (pos > offset + length) break; } @@ -358,7 +360,7 @@ static struct ax25_route *ax25_find_route(ax25_address *addr, struct device *dev struct ax25_route *ax25_spe_rt = NULL; struct ax25_route *ax25_def_rt = NULL; struct ax25_route *ax25_rt; - + /* * Bind to the physical interface we heard them on, or the default * route if none is found; @@ -379,7 +381,7 @@ static struct ax25_route *ax25_find_route(ax25_address *addr, struct device *dev if (ax25_spe_rt != NULL) return ax25_spe_rt; - + return ax25_def_rt; } @@ -391,12 +393,12 @@ static struct ax25_route *ax25_find_route(ax25_address *addr, struct device *dev static inline void ax25_adjust_path(ax25_address *addr, ax25_digi *digipeat) { int k; - + for (k = 0; k < digipeat->ndigi; k++) { if (ax25cmp(addr, &digipeat->calls[k]) == 0) break; } - + digipeat->ndigi = k; } @@ -411,7 +413,7 @@ int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr) if ((ax25_rt = ax25_find_route(addr, NULL)) == NULL) return -EHOSTUNREACH; - + ax25->device = ax25_rt->dev; if ((call = ax25_findbyuid(current->euid)) == NULL) { @@ -442,10 +444,10 @@ int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr) void ax25_rt_build_path(ax25_cb *ax25, ax25_address *addr, struct device *dev) { struct ax25_route *ax25_rt; - + if ((ax25_rt = ax25_find_route(addr, dev)) == NULL) return; - + if (ax25_rt->digipeat == NULL) return; @@ -472,24 +474,24 @@ void ax25_dg_build_path(struct sk_buff *skb, ax25_address *addr, struct device * if (ax25_rt->digipeat == NULL) return; - + digipeat = *ax25_rt->digipeat; - + ax25_adjust_path(addr, &digipeat); len = ax25_rt->digipeat->ndigi * AX25_ADDR_LEN; - + if (skb_headroom(skb) < len) { printk(KERN_CRIT "ax25_dg_build_path: not enough headroom for digis in skb\n"); return; } - + memcpy(&dest, skb->data , AX25_ADDR_LEN); memcpy(&src, skb->data + 7, AX25_ADDR_LEN); bp = skb_push(skb, len); - build_ax25_addr(bp, &src, &dest, ax25_rt->digipeat, C_COMMAND, MODULUS); + build_ax25_addr(bp, &src, &dest, ax25_rt->digipeat, AX25_COMMAND, AX25_MODULUS); } /* @@ -506,20 +508,30 @@ char ax25_ip_mode_get(ax25_address *callsign, struct device *dev) return ' '; } +static struct ax25_dev *ax25_dev_get_dev(struct device *dev) +{ + int i; + + for (i = 0; i < AX25_MAX_DEVICES; i++) + if (ax25_device[i].dev != NULL && ax25_device[i].dev == dev) + return ax25_device + i; + + return NULL; +} + /* * Wow, a bit of data hiding. Is this C++ or what ? */ int ax25_dev_get_value(struct device *dev, int valueno) { - int i; + struct ax25_dev *ax25_dev; - for (i = 0; i < AX25_MAX_DEVICES; i++) - if (ax25_device[i].dev != NULL && ax25_device[i].dev == dev) - return ax25_device[i].values[valueno]; - - printk(KERN_WARNING "ax25_dev_get_value called with invalid device\n"); + if ((ax25_dev = ax25_dev_get_dev(dev)) == NULL) { + printk(KERN_WARNING "ax25_dev_get_value called with invalid device\n"); + return 1; + } - return 0; + return ax25_dev->values[valueno]; } /* @@ -530,7 +542,7 @@ void ax25_dev_device_up(struct device *dev) { struct ax25_dev *ax25_dev = NULL; int i; - + for (i = 0; i < AX25_MAX_DEVICES; i++) { if (ax25_device[i].dev == NULL) { ax25_dev = ax25_device + i; @@ -547,7 +559,8 @@ void ax25_dev_device_up(struct device *dev) sprintf(ax25_dev->name, "%s.parms", dev->name); - ax25_dev->dev = dev; + ax25_dev->dev = dev; + ax25_dev->forward = NULL; ax25_dev->values[AX25_VALUES_IPDEFMODE] = AX25_DEF_IPDEFMODE; ax25_dev->values[AX25_VALUES_AXDEFMODE] = AX25_DEF_AXDEFMODE; @@ -570,16 +583,61 @@ void ax25_dev_device_up(struct device *dev) void ax25_dev_device_down(struct device *dev) { - int i; + struct ax25_dev *ax25_dev; ax25_unregister_sysctl(); - for (i = 0; i < AX25_MAX_DEVICES; i++) - if (ax25_device[i].dev != NULL && ax25_device[i].dev == dev) - ax25_device[i].dev = NULL; + if ((ax25_dev = ax25_dev_get_dev(dev)) != NULL) + ax25_dev->dev = NULL; ax25_register_sysctl(); } + +int ax25_fwd_ioctl(unsigned int cmd, struct ax25_fwd_struct *fwd) +{ + struct device *dev; + struct ax25_dev *ax25_dev; + + if ((dev = ax25rtr_get_dev(&fwd->port_from)) == NULL) + return -EINVAL; + + if ((ax25_dev = ax25_dev_get_dev(dev)) == NULL) + return -EINVAL; + + switch (cmd) { + case SIOCAX25ADDFWD: + if ((dev = ax25rtr_get_dev(&fwd->port_to)) == NULL) + return -EINVAL; + if (ax25_dev->forward != NULL) + return -EINVAL; + ax25_dev->forward = dev; + break; + + case SIOCAX25DELFWD: + if (ax25_dev->forward == NULL) + return -EINVAL; + ax25_dev->forward = NULL; + break; + + default: + return -EINVAL; + } + + return 0; +} + +struct device *ax25_fwd_dev(struct device *dev) +{ + struct ax25_dev *ax25_dev; + + if ((ax25_dev = ax25_dev_get_dev(dev)) == NULL) + return dev; + + if (ax25_dev->forward == NULL) + return dev; + + return ax25_dev->forward; +} #ifdef MODULE @@ -589,7 +647,7 @@ void ax25_dev_device_down(struct device *dev) void ax25_rt_free(void) { struct ax25_route *s, *ax25_rt = ax25_route; - + while (ax25_rt != NULL) { s = ax25_rt; ax25_rt = ax25_rt->next; @@ -604,4 +662,3 @@ void ax25_rt_free(void) #endif #endif - diff --git a/net/ax25/ax25_subr.c b/net/ax25/ax25_subr.c index aac8d7eb8849..e4274aeac84b 100644 --- a/net/ax25/ax25_subr.c +++ b/net/ax25/ax25_subr.c @@ -32,6 +32,7 @@ * Joerg(DL1BKE) Found the real bug in ax25.h, sri. * AX.25 032 Joerg(DL1BKE) Added ax25_queue_length to count the number of * enqueued buffers of a socket.. + * AX.25 035 Frederic(F1OAT) Support for pseudo-digipeating. */ #include @@ -134,7 +135,7 @@ int ax25_validate_nr(ax25_cb *ax25, unsigned short nr) if (nr == vc) return 1; vc = (vc + 1) % ax25->modulus; } - + if (nr == ax25->vs) return 1; return 0; @@ -147,41 +148,41 @@ int ax25_validate_nr(ax25_cb *ax25, unsigned short nr) int ax25_decode(ax25_cb *ax25, struct sk_buff *skb, int *ns, int *nr, int *pf) { unsigned char *frame; - int frametype = ILLEGAL; + int frametype = AX25_ILLEGAL; frame = skb->data; *ns = *nr = *pf = 0; - if (ax25->modulus == MODULUS) { - if ((frame[0] & S) == 0) { - frametype = I; /* I frame - carries NR/NS/PF */ + if (ax25->modulus == AX25_MODULUS) { + if ((frame[0] & AX25_S) == 0) { + frametype = AX25_I; /* I frame - carries NR/NS/PF */ *ns = (frame[0] >> 1) & 0x07; *nr = (frame[0] >> 5) & 0x07; - *pf = frame[0] & PF; - } else if ((frame[0] & U) == 1) { /* S frame - take out PF/NR */ + *pf = frame[0] & AX25_PF; + } else if ((frame[0] & AX25_U) == 1) { /* S frame - take out PF/NR */ frametype = frame[0] & 0x0F; *nr = (frame[0] >> 5) & 0x07; - *pf = frame[0] & PF; - } else if ((frame[0] & U) == 3) { /* U frame - take out PF */ - frametype = frame[0] & ~PF; - *pf = frame[0] & PF; + *pf = frame[0] & AX25_PF; + } else if ((frame[0] & AX25_U) == 3) { /* U frame - take out PF */ + frametype = frame[0] & ~AX25_PF; + *pf = frame[0] & AX25_PF; } skb_pull(skb, 1); } else { - if ((frame[0] & S) == 0) { - frametype = I; /* I frame - carries NR/NS/PF */ + if ((frame[0] & AX25_S) == 0) { + frametype = AX25_I; /* I frame - carries NR/NS/PF */ *ns = (frame[0] >> 1) & 0x7F; *nr = (frame[1] >> 1) & 0x7F; - *pf = frame[1] & EPF; + *pf = frame[1] & AX25_EPF; skb_pull(skb, 2); - } else if ((frame[0] & U) == 1) { /* S frame - take out PF/NR */ + } else if ((frame[0] & AX25_U) == 1) { /* S frame - take out PF/NR */ frametype = frame[0] & 0x0F; *nr = (frame[1] >> 1) & 0x7F; - *pf = frame[1] & EPF; + *pf = frame[1] & AX25_EPF; skb_pull(skb, 2); - } else if ((frame[0] & U) == 3) { /* U frame - take out PF */ - frametype = frame[0] & ~PF; - *pf = frame[0] & PF; + } else if ((frame[0] & AX25_U) == 3) { /* U frame - take out PF */ + frametype = frame[0] & ~AX25_PF; + *pf = frame[0] & AX25_PF; skb_pull(skb, 1); } } @@ -199,7 +200,7 @@ void ax25_send_control(ax25_cb *ax25, int frametype, int poll_bit, int type) struct sk_buff *skb; unsigned char *dptr; struct device *dev; - + if ((dev = ax25->device) == NULL) return; /* Route died */ @@ -208,26 +209,23 @@ void ax25_send_control(ax25_cb *ax25, int frametype, int poll_bit, int type) skb_reserve(skb, AX25_BPQ_HEADER_LEN + size_ax25_addr(ax25->digipeat)); - if (ax25->sk != NULL) - skb_set_owner_w(skb, ax25->sk); - /* Assume a response - address structure for DTE */ - if (ax25->modulus == MODULUS) { + if (ax25->modulus == AX25_MODULUS) { dptr = skb_put(skb, 1); *dptr = frametype; - *dptr |= (poll_bit) ? PF : 0; - if ((frametype & U) == S) /* S frames carry NR */ + *dptr |= (poll_bit) ? AX25_PF : 0; + if ((frametype & AX25_U) == AX25_S) /* S frames carry NR */ *dptr |= (ax25->vr << 5); } else { - if ((frametype & U) == U) { + if ((frametype & AX25_U) == AX25_U) { dptr = skb_put(skb, 1); *dptr = frametype; - *dptr |= (poll_bit) ? PF : 0; + *dptr |= (poll_bit) ? AX25_PF : 0; } else { dptr = skb_put(skb, 2); dptr[0] = frametype; dptr[1] = (ax25->vr << 1); - dptr[1] |= (poll_bit) ? EPF : 0; + dptr[1] |= (poll_bit) ? AX25_EPF : 0; } } @@ -256,16 +254,15 @@ void ax25_return_dm(struct device *dev, ax25_address *src, ax25_address *dest, a ax25_digi_invert(digi, &retdigi); dptr = skb_put(skb, 1); - skb->sk = NULL; - *dptr = DM | PF; + *dptr = AX25_DM | AX25_PF; /* * Do the address ourselves */ dptr = skb_push(skb, size_ax25_addr(digi)); - dptr += build_ax25_addr(dptr, dest, src, &retdigi, C_RESPONSE, MODULUS); + dptr += build_ax25_addr(dptr, dest, src, &retdigi, AX25_RESPONSE, AX25_MODULUS); skb->arp = 1; skb->dev = dev; @@ -299,19 +296,11 @@ void ax25_calculate_rtt(ax25_cb *ax25) if (ax25->t1timer > 0 && ax25->n2count == 0) ax25->rtt = (9 * ax25->rtt + ax25->t1 - ax25->t1timer) / 10; -#ifdef AX25_T1CLAMPLO - /* Don't go below one tenth of a second */ - if (ax25->rtt < (AX25_T1CLAMPLO)) - ax25->rtt = (AX25_T1CLAMPLO); -#else /* Failsafe - some people might have sub 1/10th RTTs :-) **/ - if (ax25->rtt == 0) - ax25->rtt = PR_SLOWHZ; -#endif -#ifdef AX25_T1CLAMPHI - /* OR above clamped seconds **/ - if (ax25->rtt > (AX25_T1CLAMPHI)) - ax25->rtt = (AX25_T1CLAMPHI); -#endif + if (ax25->rtt < AX25_T1CLAMPLO) + ax25->rtt = AX25_T1CLAMPLO; + + if (ax25->rtt > AX25_T1CLAMPHI) + ax25->rtt = AX25_T1CLAMPHI; } /* @@ -326,23 +315,21 @@ void ax25_calculate_rtt(ax25_cb *ax25) unsigned char *ax25_parse_addr(unsigned char *buf, int len, ax25_address *src, ax25_address *dest, ax25_digi *digi, int *flags, int *dama) { int d = 0; - + if (len < 14) return NULL; - + if (flags != NULL) { *flags = 0; - - if (buf[6] & LAPB_C) { - *flags = C_COMMAND; - } - if (buf[13] & LAPB_C) { - *flags = C_RESPONSE; - } + + if (buf[6] & AX25_CBIT) + *flags = AX25_COMMAND; + if (buf[13] & AX25_CBIT) + *flags = AX25_RESPONSE; } - + if (dama != NULL) - *dama = ~buf[13] & DAMA_FLAG; - + *dama = ~buf[13] & AX25_DAMA_FLAG; + /* Copy to, from */ if (dest != NULL) memcpy(dest, buf + 0, AX25_ADDR_LEN); @@ -352,15 +339,15 @@ unsigned char *ax25_parse_addr(unsigned char *buf, int len, ax25_address *src, a len -= 2 * AX25_ADDR_LEN; digi->lastrepeat = -1; digi->ndigi = 0; - - while (!(buf[-1] & LAPB_E)) { + + while (!(buf[-1] & AX25_EBIT)) { if (d >= AX25_MAX_DIGIS) return NULL; /* Max of 6 digis */ if (len < 7) return NULL; /* Short packet */ if (digi != NULL) { memcpy(&digi->calls[d], buf, AX25_ADDR_LEN); digi->ndigi = d + 1; - if (buf[6] & AX25_REPEATED) { + if (buf[6] & AX25_HBIT) { digi->repeated[d] = 1; digi->lastrepeat = d; } else { @@ -385,53 +372,54 @@ int build_ax25_addr(unsigned char *buf, ax25_address *src, ax25_address *dest, a int ct = 0; memcpy(buf, dest, AX25_ADDR_LEN); - buf[6] &= ~(LAPB_E | LAPB_C); - buf[6] |= SSSID_SPARE; + buf[6] &= ~(AX25_EBIT | AX25_CBIT); + buf[6] |= AX25_SSSID_SPARE; - if (flag == C_COMMAND) buf[6] |= LAPB_C; + if (flag == AX25_COMMAND) buf[6] |= AX25_CBIT; buf += AX25_ADDR_LEN; len += AX25_ADDR_LEN; memcpy(buf, src, AX25_ADDR_LEN); - buf[6] &= ~(LAPB_E | LAPB_C); - buf[6] &= ~SSSID_SPARE; + buf[6] &= ~(AX25_EBIT | AX25_CBIT); + buf[6] &= ~AX25_SSSID_SPARE; - if (modulus == MODULUS) { - buf[6] |= SSSID_SPARE; - } else { - buf[6] |= ESSID_SPARE; - } + if (modulus == AX25_MODULUS) + buf[6] |= AX25_SSSID_SPARE; + else + buf[6] |= AX25_ESSID_SPARE; - if (flag == C_RESPONSE) buf[6] |= LAPB_C; + if (flag == AX25_RESPONSE) buf[6] |= AX25_CBIT; /* * Fast path the normal digiless path */ if (d == NULL || d->ndigi == 0) { - buf[6] |= LAPB_E; + buf[6] |= AX25_EBIT; return 2 * AX25_ADDR_LEN; } - + buf += AX25_ADDR_LEN; len += AX25_ADDR_LEN; - + while (ct < d->ndigi) { memcpy(buf, &d->calls[ct], AX25_ADDR_LEN); + if (d->repeated[ct]) - buf[6] |= AX25_REPEATED; + buf[6] |= AX25_HBIT; else - buf[6] &= ~AX25_REPEATED; - buf[6] &= ~LAPB_E; - buf[6] |= SSSID_SPARE; + buf[6] &= ~AX25_HBIT; + + buf[6] &= ~AX25_EBIT; + buf[6] |= AX25_SSSID_SPARE; buf += AX25_ADDR_LEN; len += AX25_ADDR_LEN; ct++; } - buf[-1] |= LAPB_E; - + buf[-1] |= AX25_EBIT; + return len; } @@ -442,34 +430,36 @@ int size_ax25_addr(ax25_digi *dp) return AX25_ADDR_LEN * (2 + dp->ndigi); } - + /* * Reverse Digipeat List. May not pass both parameters as same struct - */ + */ void ax25_digi_invert(ax25_digi *in, ax25_digi *out) { int ct = 0; - + + out->ndigi = in->ndigi; + out->lastrepeat = in->ndigi - in->lastrepeat - 2; + /* Invert the digipeaters */ - + while (ct < in->ndigi) { out->calls[ct] = in->calls[in->ndigi - ct - 1]; - out->repeated[ct] = 0; + if (ct <= out->lastrepeat) { + out->calls[ct].ax25_call[6] |= AX25_HBIT; + out->repeated[ct] = 1; + } else { + out->calls[ct].ax25_call[6] &= ~AX25_HBIT; + out->repeated[ct] = 0; + } ct++; } - - /* Copy ndigis */ - out->ndigi = in->ndigi; - - /* Finish off */ - out->lastrepeat = 0; } /* * count the number of buffers on a list belonging to the same * socket as skb */ - static int ax25_list_length(struct sk_buff_head *list, struct sk_buff *skb) { int count = 0; @@ -489,6 +479,7 @@ static int ax25_list_length(struct sk_buff_head *list, struct sk_buff *skb) count++; restore_flags(flags); + return count; } @@ -521,20 +512,15 @@ void ax25_kiss_cmd(ax25_cb *ax25, unsigned char cmd, unsigned char param) if ((skb = alloc_skb(2, GFP_ATOMIC)) == NULL) return; - skb->arp = 1; - - if (ax25->sk != NULL) - skb_set_owner_w(skb, ax25->sk); - - skb->protocol = htons(ETH_P_AX25); - p = skb_put(skb, 2); *p++ = cmd; *p++ = param; + skb->arp = 1; skb->dev = ax25->device; skb->priority = SOPRI_NORMAL; + skb->protocol = htons(ETH_P_AX25); dev_queue_xmit(skb); } diff --git a/net/ax25/ax25_timer.c b/net/ax25/ax25_timer.c index d07465c94e62..398563f87a0e 100644 --- a/net/ax25/ax25_timer.c +++ b/net/ax25/ax25_timer.c @@ -20,6 +20,7 @@ * AX.25 031 Joerg(DL1BKE) Added DAMA support * AX.25 032 Joerg(DL1BKE) Fixed DAMA timeout bug * AX.25 033 Jonathan(G4KLX) Modularisation functions. + * AX.25 035 Frederic(F1OAT) Support for pseudo-digipeating. */ #include @@ -109,11 +110,11 @@ static void ax25_timer(unsigned long param) * Check the state of the receive buffer. */ if (ax25->sk != NULL) { - if (ax25->sk->rmem_alloc < (ax25->sk->rcvbuf / 2) && (ax25->condition & OWN_RX_BUSY_CONDITION)) { - ax25->condition &= ~OWN_RX_BUSY_CONDITION; + if (ax25->sk->rmem_alloc < (ax25->sk->rcvbuf / 2) && (ax25->condition & AX25_COND_OWN_RX_BUSY)) { + ax25->condition &= ~AX25_COND_OWN_RX_BUSY; + ax25->condition &= ~AX25_COND_ACK_PENDING; if (!ax25->dama_slave) - ax25_send_control(ax25, RR, POLLOFF, C_RESPONSE); - ax25->condition &= ~ACK_PENDING_CONDITION; + ax25_send_control(ax25, AX25_RR, AX25_POLLOFF, AX25_RESPONSE); break; } } @@ -130,8 +131,8 @@ static void ax25_timer(unsigned long param) if (ax25->t2timer > 0 && --ax25->t2timer == 0) { if (ax25->state == AX25_STATE_3 || ax25->state == AX25_STATE_4) { - if (ax25->condition & ACK_PENDING_CONDITION) { - ax25->condition &= ~ACK_PENDING_CONDITION; + if (ax25->condition & AX25_COND_ACK_PENDING) { + ax25->condition &= ~AX25_COND_ACK_PENDING; if (!ax25->dama_slave) ax25_timeout_response(ax25); } @@ -144,8 +145,8 @@ static void ax25_timer(unsigned long param) if (ax25->dama_slave) { ax25_link_failed(&ax25->dest_addr, ax25->device); ax25_clear_queues(ax25); - ax25_send_control(ax25, DISC, POLLON, C_COMMAND); - + ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND); + ax25->state = AX25_STATE_0; if (ax25->sk != NULL) { if (ax25->sk->debug) @@ -161,7 +162,7 @@ static void ax25_timer(unsigned long param) ax25_reset_timer(ax25); return; } - + if (ax25->state == AX25_STATE_3) { ax25->n2count = 0; ax25_transmit_enquiry(ax25); @@ -169,7 +170,7 @@ static void ax25_timer(unsigned long param) } ax25->t3timer = ax25->t3; } - + if (ax25->idletimer > 0 && --ax25->idletimer == 0) { /* dl1bke 960228: close the connection when IDLE expires */ /* similar to DAMA T3 timeout but with */ @@ -180,13 +181,13 @@ static void ax25_timer(unsigned long param) ax25->n2count = 0; if (!ax25->dama_slave) { ax25->t3timer = 0; - ax25_send_control(ax25, DISC, POLLON, C_COMMAND); + ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND); } else { ax25->t3timer = ax25->t3; } - + /* state 1 or 2 should not happen, but... */ - + if (ax25->state == AX25_STATE_1 || ax25->state == AX25_STATE_2) ax25->state = AX25_STATE_0; else @@ -204,10 +205,10 @@ static void ax25_timer(unsigned long param) ax25->sk->destroy = 1; } } - + /* dl1bke 960114: DAMA T1 timeouts are handled in ax25_dama_slave_transmit */ /* nevertheless we have to re-enqueue the timer struct... */ - + if (ax25->t1timer == 0 || --ax25->t1timer > 0) { ax25_reset_timer(ax25); return; @@ -225,7 +226,7 @@ static void ax25_timer(unsigned long param) * within the poll of any connected channel. Remember * that we are not allowed to send anything unless we * get polled by the Master. - * + * * Thus we'll have to do parts of our T1 handling in * ax25_enquiry_response(). */ @@ -234,7 +235,7 @@ void ax25_t1_timeout(ax25_cb * ax25) switch (ax25->state) { case AX25_STATE_1: if (ax25->n2count == ax25->n2) { - if (ax25->modulus == MODULUS) { + if (ax25->modulus == AX25_MODULUS) { ax25_link_failed(&ax25->dest_addr, ax25->device); ax25_clear_queues(ax25); ax25->state = AX25_STATE_0; @@ -247,18 +248,17 @@ void ax25_t1_timeout(ax25_cb * ax25) ax25->sk->dead = 1; } } else { - ax25->modulus = MODULUS; + ax25->modulus = AX25_MODULUS; ax25->window = ax25_dev_get_value(ax25->device, AX25_VALUES_WINDOW); ax25->n2count = 0; - ax25_send_control(ax25, SABM, ax25_dev_is_dama_slave(ax25->device)? POLLOFF : POLLON, C_COMMAND); + ax25_send_control(ax25, AX25_SABM, ax25_dev_is_dama_slave(ax25->device) ? AX25_POLLOFF : AX25_POLLON, AX25_COMMAND); } } else { ax25->n2count++; - if (ax25->modulus == MODULUS) { - ax25_send_control(ax25, SABM, ax25_dev_is_dama_slave(ax25->device)? POLLOFF : POLLON, C_COMMAND); - } else { - ax25_send_control(ax25, SABME, ax25_dev_is_dama_slave(ax25->device)? POLLOFF : POLLON, C_COMMAND); - } + if (ax25->modulus == AX25_MODULUS) + ax25_send_control(ax25, AX25_SABM, ax25_dev_is_dama_slave(ax25->device) ? AX25_POLLOFF : AX25_POLLON, AX25_COMMAND); + else + ax25_send_control(ax25, AX25_SABME, ax25_dev_is_dama_slave(ax25->device) ? AX25_POLLOFF : AX25_POLLON, AX25_COMMAND); } break; @@ -267,8 +267,8 @@ void ax25_t1_timeout(ax25_cb * ax25) ax25_link_failed(&ax25->dest_addr, ax25->device); ax25_clear_queues(ax25); ax25->state = AX25_STATE_0; - ax25_send_control(ax25, DISC, POLLON, C_COMMAND); - + ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND); + if (ax25->sk != NULL) { ax25->sk->state = TCP_CLOSE; ax25->sk->err = ETIMEDOUT; @@ -280,7 +280,7 @@ void ax25_t1_timeout(ax25_cb * ax25) } else { ax25->n2count++; if (!ax25_dev_is_dama_slave(ax25->device)) - ax25_send_control(ax25, DISC, POLLON, C_COMMAND); + ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND); } break; @@ -295,7 +295,7 @@ void ax25_t1_timeout(ax25_cb * ax25) if (ax25->n2count == ax25->n2) { ax25_link_failed(&ax25->dest_addr, ax25->device); ax25_clear_queues(ax25); - ax25_send_control(ax25, DM, POLLON, C_RESPONSE); + ax25_send_control(ax25, AX25_DM, AX25_POLLON, AX25_RESPONSE); ax25->state = AX25_STATE_0; if (ax25->sk != NULL) { if (ax25->sk->debug) @@ -357,13 +357,13 @@ int ax25_protocol_register(unsigned int pid, int (*func)(struct sk_buff *, ax25_ protocol->pid = pid; protocol->func = func; - + save_flags(flags); cli(); - + protocol->next = protocol_list; protocol_list = protocol; - + restore_flags(flags); return 1; @@ -395,10 +395,10 @@ void ax25_protocol_release(unsigned int pid) kfree_s(s, sizeof(struct protocol_struct)); return; } - + protocol = protocol->next; } - + restore_flags(flags); } @@ -411,13 +411,13 @@ int ax25_linkfail_register(void (*func)(ax25_address *, struct device *)) return 0; linkfail->func = func; - + save_flags(flags); cli(); - + linkfail->next = linkfail_list; linkfail_list = linkfail; - + restore_flags(flags); return 1; @@ -449,10 +449,10 @@ void ax25_linkfail_release(void (*func)(ax25_address *, struct device *)) kfree_s(s, sizeof(struct linkfail_struct)); return; } - + linkfail = linkfail->next; } - + restore_flags(flags); } @@ -469,13 +469,13 @@ int ax25_listen_register(ax25_address *callsign, struct device *dev) listen->callsign = *callsign; listen->dev = dev; - + save_flags(flags); cli(); - + listen->next = listen_list; listen_list = listen; - + restore_flags(flags); return 1; @@ -507,10 +507,10 @@ void ax25_listen_release(ax25_address *callsign, struct device *dev) kfree_s(s, sizeof(struct listen_struct)); return; } - + listen = listen->next; } - + restore_flags(flags); } @@ -539,9 +539,20 @@ int ax25_listen_mine(ax25_address *callsign, struct device *dev) void ax25_link_failed(ax25_address *callsign, struct device *dev) { struct linkfail_struct *linkfail; - + for (linkfail = linkfail_list; linkfail != NULL; linkfail = linkfail->next) (linkfail->func)(callsign, dev); } +int ax25_protocol_is_registered(unsigned int pid) +{ + struct protocol_struct *protocol; + + for (protocol = protocol_list; protocol != NULL; protocol = protocol->next) + if (protocol->pid == pid) + return 1; + + return 0; +} + #endif diff --git a/net/ax25/sysctl_net_ax25.c b/net/ax25/sysctl_net_ax25.c index 302d210f8009..da40a3dbb800 100644 --- a/net/ax25/sysctl_net_ax25.c +++ b/net/ax25/sysctl_net_ax25.c @@ -9,10 +9,10 @@ #include #include -static int min_ax25[] = {0, 0, 0, 0, 0, 1, 1, 1, 1, - 0, 0, 1, 1, 1, 0x00}; -static int max_ax25[] = {1, 1, 1, 1, 1, 7, 63, 30 * PR_SLOWHZ, 20 * PR_SLOWHZ, - 3600 * PR_SLOWHZ, 65535 * PR_SLOWHZ, 31, 512, 20, 0x03}; +static int min_ax25[] = {0, 0, 0, 0, 0, 1, 1, 1, 1, + 0, 0, 1, 1, 1, 0x00}; +static int max_ax25[] = {1, 1, 1, 1, 1, 7, 63, 30 * AX25_SLOWHZ, 20 * AX25_SLOWHZ, + 3600 * AX25_SLOWHZ, 65535 * AX25_SLOWHZ, 31, 512, 20, 0x03}; static struct ctl_table_header *ax25_table_header; diff --git a/net/core/dev.c b/net/core/dev.c index 14addfb7fbef..c7122e2b4b8f 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -224,6 +224,32 @@ struct device *dev_get(const char *name) } return NULL; } + +struct device * dev_get_by_index(int ifindex) +{ + struct device *dev; + + for (dev = dev_base; dev != NULL; dev = dev->next) + { + if (dev->ifindex == ifindex) + return(dev); + } + return NULL; +} + +struct device *dev_getbyhwaddr(unsigned short type, char *ha) +{ + struct device *dev; + + for (dev = dev_base; dev != NULL; dev = dev->next) + { + if (dev->type == type && + !(dev->flags&(IFF_LOOPBACK|IFF_NOARP)) && + memcmp(dev->dev_addr, ha, dev->addr_len) == 0) + return(dev); + } + return(NULL); +} /* * Find and possibly load an interface. @@ -268,18 +294,17 @@ int dev_open(struct device *dev) if (ret == 0) { dev->flags |= (IFF_UP | IFF_RUNNING); - dev->hash = dev_hash_name(dev->name); /* * Initialise multicasting status */ dev_mc_upload(dev); notifier_call_chain(&netdev_chain, NETDEV_UP, dev); - /* - * FIXME: This logic was wrong before. Now its - * obviously so. I think the change here (removing the - * ! on the net_alias_is) is right. ANK ?? + + /* + * Passive non transmitting devices (including + * aliases) need not be on this chain. */ - if (net_alias_is(dev) || dev->tx_queue_len) + if (!net_alias_is(dev) && dev->tx_queue_len) { cli(); dev->next_up = dev_up_base; @@ -931,8 +956,6 @@ static int dev_ifconf(char *arg) for (dev = dev_base; dev != NULL; dev = dev->next) { - if(!(dev->flags & IFF_UP)) /* Downed devices don't count */ - continue; /* * Have we run out of space here ? */ @@ -1282,9 +1305,9 @@ static int dev_ifsioc(void *arg, unsigned int getset) dev->mtu = ifr.ifr_mtu; ret = 0; } - if (!ret && (dev->flags&IFF_UP)) { + if (!ret && dev->flags&IFF_UP) { printk(KERN_DEBUG "SIFMTU %s(%s)\n", dev->name, current->comm); - notifier_call_chain(&netdev_chain, NETDEV_CHANGE, dev); + notifier_call_chain(&netdev_chain, NETDEV_CHANGEMTU, dev); } break; @@ -1308,6 +1331,8 @@ static int dev_ifsioc(void *arg, unsigned int getset) if(ifr.ifr_hwaddr.sa_family!=dev->type) return -EINVAL; ret=dev->set_mac_address(dev,&ifr.ifr_hwaddr); + if (!ret) + notifier_call_chain(&netdev_chain, NETDEV_CHANGEADDR, dev); break; case SIOCGIFMAP: @@ -1339,6 +1364,12 @@ static int dev_ifsioc(void *arg, unsigned int getset) return -EINVAL; dev_mc_delete(dev,ifr.ifr_hwaddr.sa_data,dev->addr_len, 1); return 0; + + case SIOGIFINDEX: + ifr.ifr_ifindex = dev->ifindex; + goto rarok; + + /* * Unknown or private ioctl */ @@ -1417,6 +1448,7 @@ int dev_ioctl(unsigned int cmd, void *arg) case SIOCSIFHWADDR: case SIOCGIFSLAVE: case SIOCGIFMAP: + case SIOGIFINDEX: return dev_ifsioc(arg, cmd); /* @@ -1459,6 +1491,11 @@ int dev_ioctl(unsigned int cmd, void *arg) } } +int dev_new_index() +{ + static int ifindex; + return ++ifindex; +} /* * Initialize the DEV module. At boot time this walks the device list and @@ -1585,6 +1622,7 @@ int net_dev_init(void) else { dp = &dev->next; + dev->ifindex = dev_new_index(); } } diff --git a/net/core/dev_mcast.c b/net/core/dev_mcast.c index f86bc158b398..4aa6cbb0c33e 100644 --- a/net/core/dev_mcast.c +++ b/net/core/dev_mcast.c @@ -72,7 +72,12 @@ void dev_mc_upload(struct device *dev) /* * An aliased device should end up with the combined * multicast list of all its aliases. - * [Check this is still ok -AC] + * Really, multicasting with logical interfaces is very + * subtle question. Now we DO forward multicast packets + * to logical interfcases, that doubles multicast + * traffic but allows mrouted to work. + * Alas, mrouted does not understand aliases even + * in 4.4BSD --ANK */ dev = net_alias_main_dev(dev); diff --git a/net/core/iovec.c b/net/core/iovec.c index 80bd3e0177f0..1acdc47d1913 100644 --- a/net/core/iovec.c +++ b/net/core/iovec.c @@ -60,14 +60,6 @@ int verify_iovec(struct msghdr *m, struct iovec *iov, char *address, int mode) } else m->msg_name = NULL; - if(m->msg_controllen) - { - err=verify_area(mode, m->msg_control, m->msg_controllen); - if(err) - return err; - } else - m->msg_control = NULL; - if (m->msg_iovlen > UIO_FASTIOV) { iov = kmalloc(m->msg_iovlen*sizeof(struct iovec), GFP_KERNEL); diff --git a/net/core/net_alias.c b/net/core/net_alias.c index 54aafeadf90e..147f31436379 100644 --- a/net/core/net_alias.c +++ b/net/core/net_alias.c @@ -275,6 +275,7 @@ static int net_alias_devsetup(struct net_alias *alias, dev->init = net_alias_devinit; dev->hard_start_xmit = net_alias_hard_start_xmit; dev->flags = main_dev->flags & NET_ALIAS_IFF_MASK & ~IFF_UP; + dev->ifindex = dev_new_index(); /* * Only makes sense if same family (arguable) diff --git a/net/core/scm.c b/net/core/scm.c index 2ca00d5b2038..481f69f4f157 100644 --- a/net/core/scm.c +++ b/net/core/scm.c @@ -8,6 +8,7 @@ * 2 of the License, or (at your option) any later version. */ +#include #include #include #include @@ -59,7 +60,7 @@ static int scm_fp_copy(struct cmsghdr *cmsg, struct scm_fp_list **fplp) { int num; struct scm_fp_list *fpl = *fplp; - struct file **fpp = &fpl->fp[fpl->count]; + struct file **fpp; int *fdp = (int*)cmsg->cmsg_data; int i; @@ -79,6 +80,7 @@ static int scm_fp_copy(struct cmsghdr *cmsg, struct scm_fp_list **fplp) *fplp = fpl; fpl->count = 0; } + fpp = &fpl->fp[fpl->count]; if (fpl->count + num > SCM_MAX_FD) return -EINVAL; @@ -92,7 +94,6 @@ static int scm_fp_copy(struct cmsghdr *cmsg, struct scm_fp_list **fplp) int fd; fd = fdp[i]; - if (fd < 0 || fd >= NR_OPEN) return -EBADF; if (current->files->fd[fd]==NULL) @@ -133,27 +134,19 @@ extern __inline__ int not_one_bit(unsigned val) int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *p) { int err; - struct cmsghdr kcm, *cmsg; + struct cmsghdr *cmsg; struct file *file; int acc_fd; unsigned scm_flags=0; - for (cmsg = KCMSG_FIRSTHDR(msg); cmsg; cmsg = KCMSG_NXTHDR(msg, cmsg)) + for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) { - if (kcm.cmsg_level != SOL_SOCKET) + if (cmsg->cmsg_level != SOL_SOCKET) continue; err = -EINVAL; - /* - * Temporary hack: no protocols except for AF_UNIX - * undestand scm now. - */ - - if (sock->ops->family != AF_UNIX) - goto error; - - switch (kcm.cmsg_type) + switch (cmsg->cmsg_type) { case SCM_RIGHTS: err=scm_fp_copy(cmsg, &p->fp); @@ -161,7 +154,7 @@ int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *p) goto error; break; case SCM_CREDENTIALS: - if (kcm.cmsg_len < sizeof(kcm) + sizeof(struct ucred)) + if (cmsg->cmsg_len < sizeof(*cmsg) + sizeof(struct ucred)) goto error; memcpy(&p->creds, cmsg->cmsg_data, sizeof(struct ucred)); err = scm_check_creds(&p->creds); @@ -171,10 +164,9 @@ int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *p) case SCM_CONNECT: if (scm_flags) goto error; - if (kcm.cmsg_len < sizeof(kcm) + sizeof(int)) + if (cmsg->cmsg_len < sizeof(*cmsg) + sizeof(int)) goto error; memcpy(&acc_fd, cmsg->cmsg_data, sizeof(int)); - p->sock = NULL; if (acc_fd != -1) { if (acc_fd < 0 || acc_fd >= NR_OPEN || @@ -193,7 +185,6 @@ int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *p) } } - if (p->fp && !p->fp->count) { kfree(p->fp); @@ -218,6 +209,7 @@ void put_cmsg(struct msghdr * msg, int level, int type, int len, void *data) { struct cmsghdr *cm = (struct cmsghdr*)msg->msg_control; int cmlen = sizeof(*cm) + len; + int err; if (cm==NULL || msg->msg_controllen < sizeof(*cm)) { msg->msg_flags |= MSG_CTRUNC; @@ -227,16 +219,18 @@ void put_cmsg(struct msghdr * msg, int level, int type, int len, void *data) msg->msg_flags |= MSG_CTRUNC; cmlen = msg->msg_controllen; } - - cm->cmsg_level = level; - cm->cmsg_type = type; - cm->cmsg_len = cmlen; - memcpy(cm->cmsg_data, data, cmlen - sizeof(*cm)); - - cmlen = CMSG_ALIGN(cmlen); - msg->msg_control += cmlen; - msg->msg_controllen -= cmlen; - + err = put_user(level, &cm->cmsg_level); + if (!err) + err = put_user(type, &cm->cmsg_type); + if (!err) + err = put_user(cmlen, &cm->cmsg_len); + if (!err) + err = copy_to_user(cm->cmsg_data, data, cmlen - sizeof(*cm)); + if (!err) { + cmlen = CMSG_ALIGN(cmlen); + msg->msg_control += cmlen; + msg->msg_controllen -= cmlen; + } } void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm) @@ -246,6 +240,7 @@ void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm) int fdmax = (msg->msg_controllen - sizeof(struct cmsghdr))/sizeof(int); int fdnum = scm->fp->count; int *cmfptr; + int err = 0; int i; struct file **fp = scm->fp->fp; @@ -258,23 +253,29 @@ void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm) if (new_fd < 0) break; current->files->fd[new_fd] = fp[i]; - *cmfptr = new_fd; + err = put_user(new_fd, cmfptr); cmfptr++; } if (i > 0) { int cmlen = i*sizeof(int) + sizeof(struct cmsghdr); - - cm->cmsg_level = SOL_SOCKET; - cm->cmsg_type = SCM_RIGHTS; - cm->cmsg_len = cmlen; - - cmlen = CMSG_ALIGN(cmlen); - msg->msg_control += cmlen; - msg->msg_controllen -= cmlen; + if (!err) + err = put_user(SOL_SOCKET, &cm->cmsg_level); + if (!err) + err = put_user(SCM_RIGHTS, &cm->cmsg_type); + if (!err) + err = put_user(cmlen, &cm->cmsg_len); + if (!err) { + cmlen = CMSG_ALIGN(cmlen); + msg->msg_control += cmlen; + msg->msg_controllen -= cmlen; + } } + if (err) + i = 0; + /* * Dump those that don't fit. */ diff --git a/net/core/sock.c b/net/core/sock.c index b822b3fb93f2..bd08736d495c 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -701,3 +701,95 @@ void sklist_destroy_socket(struct sock **list,struct sock *sk) } } +/* + * Support routines for general vectors + */ + +/* + * Socket with no special fcntl calls. + */ + +int sock_no_fcntl(struct socket *sock, unsigned int cmd, unsigned long arg) +{ + struct sock *sk = sock->sk; + + switch(cmd) + { + case F_SETOWN: + /* + * This is a little restrictive, but it's the only + * way to make sure that you can't send a sigurg to + * another process. + */ + if (!suser() && current->pgrp != -arg && + current->pid != arg) return(-EPERM); + sk->proc = arg; + return(0); + case F_GETOWN: + return(sk->proc); + default: + return(-EINVAL); + } +} + +/* + * Default Socket Callbacks + */ + +void sock_def_callback1(struct sock *sk) +{ + if(!sk->dead) + wake_up_interruptible(sk->sleep); +} + +void sock_def_callback2(struct sock *sk, int len) +{ + if(!sk->dead) + { + wake_up_interruptible(sk->sleep); + sock_wake_async(sk->socket,1); + } +} + +void sock_def_callback3(struct sock *sk) +{ + if(!sk->dead) + { + wake_up_interruptible(sk->sleep); + sock_wake_async(sk->socket, 2); + } +} + +void sock_init_data(struct socket *sock, struct sock *sk) +{ + skb_queue_head_init(&sk->receive_queue); + skb_queue_head_init(&sk->write_queue); + skb_queue_head_init(&sk->back_log); + skb_queue_head_init(&sk->error_queue); + + init_timer(&sk->timer); + + sk->allocation = GFP_KERNEL; + sk->rcvbuf = SK_RMEM_MAX; + sk->sndbuf = SK_WMEM_MAX; + sk->priority = SOPRI_NORMAL; + sk->state = TCP_CLOSE; + sk->zapped = 1; + sk->socket = sock; + if(sock) + { + sk->type = sock->type; + sk->sleep = &sock->wait; + sock->sk = sk; + } + + sk->state_change = sock_def_callback1; + sk->data_ready = sock_def_callback2; + sk->write_space = sock_def_callback3; + sk->error_report = sock_def_callback1; + + sk->peercred.pid = 0; + sk->peercred.uid = -1; + sk->peercred.gid = -1; + +} diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index f5b6920d8c55..ff390e6e3343 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -429,28 +429,6 @@ void destroy_sock(struct sock *sk) * the work. */ -int inet_fcntl(struct socket *sock, unsigned int cmd, unsigned long arg) -{ - struct sock *sk = sock->sk; - - switch(cmd) - { - case F_SETOWN: - /* - * This is a little restrictive, but it's the only - * way to make sure that you can't send a sigurg to - * another process. - */ - if (!suser() && current->pgrp != -arg && - current->pid != arg) return(-EPERM); - sk->proc = arg; - return(0); - case F_GETOWN: - return(sk->proc); - default: - return(-EINVAL); - } -} /* * Set socket options on an inet socket. @@ -537,36 +515,6 @@ int inet_listen(struct socket *sock, int backlog) return(0); } -/* - * Default callbacks for user INET sockets. These just wake up - * the user owning the socket. - */ - -static void def_callback1(struct sock *sk) -{ - if(!sk->dead) - wake_up_interruptible(sk->sleep); -} - -static void def_callback2(struct sock *sk,int len) -{ - if(!sk->dead) - { - wake_up_interruptible(sk->sleep); - sock_wake_async(sk->socket, 1); - } -} - -static void def_callback3(struct sock *sk) -{ - if(!sk->dead && sk->wmem_alloc*2 <= sk->sndbuf) - { - wake_up_interruptible(sk->sleep); - sock_wake_async(sk->socket, 2); - } -} - - /* * Create an inet socket. * @@ -660,39 +608,19 @@ static int inet_create(struct socket *sock, int protocol) sk_free(sk); return(-ESOCKTNOSUPPORT); } - sk->type = sock->type; - sk->socket = sock; - sk->sleep = &sock->wait; - sk->peercred.pid = 0; - sk->peercred.uid = -1; - sk->peercred.gid = -1; - - sock->sk = sk; + sock_init_data(sock,sk); + + sk->zapped=0; #ifdef CONFIG_TCP_NAGLE_OFF sk->nonagle = 1; #endif sk->family = AF_INET; sk->protocol = protocol; - sk->allocation = GFP_KERNEL; - sk->sndbuf = SK_WMEM_MAX; - sk->rcvbuf = SK_RMEM_MAX; - sk->priority = SOPRI_NORMAL; sk->prot = prot; sk->backlog_rcv = prot->backlog_rcv; - sk->sleep = &sock->wait; - sock->sk = sk; - - sk->state = TCP_CLOSE; - - skb_queue_head_init(&sk->write_queue); - skb_queue_head_init(&sk->receive_queue); - skb_queue_head_init(&sk->error_queue); - skb_queue_head_init(&sk->back_log); - - sk->timer.data = (unsigned long)sk; sk->timer.function = &net_timer; @@ -705,26 +633,22 @@ static int inet_create(struct socket *sock, int protocol) sk->ip_mc_loop=1; sk->ip_mc_ttl=1; - *sk->ip_mc_name=0; + sk->ip_mc_index=0; sk->ip_mc_list=NULL; + /* * Speed up by setting some standard state for the dummy_th * if TCP uses it (maybe move to tcp_init later) */ - sk->state_change = def_callback1; - sk->data_ready = def_callback2; - sk->write_space = def_callback3; - sk->error_report = def_callback1; - if (sk->num) { - /* - * It assumes that any protocol which allows - * the user to assign a number at socket - * creation time automatically - * shares. - */ + /* + * It assumes that any protocol which allows + * the user to assign a number at socket + * creation time automatically + * shares. + */ inet_put_sock(sk->num, sk); sk->dummy_th.source = ntohs(sk->num); } @@ -1296,7 +1220,6 @@ static int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) err = get_user(pid, (int *) arg); if (err) return err; - /* see inet_fcntl */ if (current->pid != pid && current->pgrp != -pid && !suser()) return -EPERM; sk->proc = pid; @@ -1359,6 +1282,7 @@ static int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) case SIOCGIFMAP: case SIOCSIFSLAVE: case SIOCGIFSLAVE: + case SIOGIFINDEX: return(dev_ioctl(cmd,(void *) arg)); case SIOCGIFBR: @@ -1671,7 +1595,7 @@ struct proto_ops inet_stream_ops = { inet_shutdown, inet_setsockopt, inet_getsockopt, - inet_fcntl, + sock_no_fcntl, inet_sendmsg, inet_recvmsg }; @@ -1692,7 +1616,7 @@ struct proto_ops inet_dgram_ops = { inet_shutdown, inet_setsockopt, inet_getsockopt, - inet_fcntl, + sock_no_fcntl, inet_sendmsg, inet_recvmsg }; diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 44b962cb4a72..8a95ece71f41 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -572,7 +572,7 @@ static int arp_force_expire(void) unsigned long now = jiffies; int result = 0; - static last_index; + static int last_index; if (last_index >= ARP_TABLE_SIZE) last_index = 0; @@ -1001,33 +1001,6 @@ static __inline__ struct arp_table *arp_lookup(u32 paddr, struct device * dev) return NULL; } -/* - * Find an arp mapping in the cache. If not found, return false. - */ - -int arp_query(unsigned char *haddr, u32 paddr, struct device * dev) -{ - struct arp_table *entry; - - start_bh_atomic(); - - entry = arp_lookup(paddr, dev); - - if (entry != NULL) - { - entry->u.dst.lastuse = jiffies; - if (entry->flags & ATF_COM) - { - memcpy(haddr, entry->ha, dev->addr_len); - end_bh_atomic(); - return 1; - } - } - end_bh_atomic(); - return 0; -} - - static int arp_set_predefined(int addr_hint, unsigned char * haddr, u32 paddr, struct device * dev) { switch (addr_hint) diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index e49ff05824f2..da0685340858 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -43,9 +43,7 @@ #include #include #include -#ifdef CONFIG_NET_ALIAS #include -#endif #ifdef CONFIG_KERNELD #include #endif @@ -56,7 +54,7 @@ extern struct notifier_block *netdev_chain; * Determine a default network mask, based on the IP address. */ -unsigned long ip_get_mask(unsigned long addr) +static unsigned long ip_get_mask(unsigned long addr) { unsigned long dst; @@ -78,19 +76,6 @@ unsigned long ip_get_mask(unsigned long addr) return(0); } -struct device *dev_getbyhwaddr(unsigned short type, char *ha) -{ - struct device *dev; - - for (dev = dev_base; dev != NULL; dev = dev->next) - { - if (dev->type == type && - !(dev->flags&(IFF_LOOPBACK|IFF_NOARP)) && - memcmp(dev->dev_addr, ha, dev->addr_len) == 0) - return(dev); - } - return(NULL); -} /* * This checks bitmasks for the ioctl calls for devices. @@ -180,9 +165,13 @@ int devinet_ioctl(unsigned int cmd, void *arg) if(ifr.ifr_addr.sa_family==AF_UNSPEC) { + int ret; if(dev->set_mac_address==NULL) return -EOPNOTSUPP; - return dev->set_mac_address(dev,&ifr.ifr_addr); + ret = dev->set_mac_address(dev,&ifr.ifr_addr); + if (!ret) + notifier_call_chain(&netdev_chain, NETDEV_CHANGEADDR, dev); + return ret; } if(ifr.ifr_addr.sa_family!=AF_INET) return -EINVAL; diff --git a/net/ipv4/fib.c b/net/ipv4/fib.c index f73d2ab7f2af..e99bf15edac6 100644 --- a/net/ipv4/fib.c +++ b/net/ipv4/fib.c @@ -66,7 +66,7 @@ static struct fib_info *fib_info_list; static int fib_stamp; -int rtmsg_process(struct nlmsghdr *n, struct in_rtmsg *r); +static int rtmsg_process(struct nlmsghdr *n, struct in_rtmsg *r); #ifdef CONFIG_RTNETLINK @@ -119,7 +119,7 @@ static void rtmsg_dev(unsigned long type, struct device *dev, struct nlmsghdr *n static struct wait_queue *fib_wait; atomic_t fib_users; -void fib_lock(void) +static void fib_lock(void) { while (fib_users) sleep_on(&fib_wait); @@ -127,7 +127,7 @@ void fib_lock(void) dev_lock_list(); } -void fib_unlock(void) +static void fib_unlock(void) { dev_unlock_list(); if (atomic_dec_and_test(&fib_users)) { @@ -496,7 +496,7 @@ fib_lookup(struct fib_result *res, u32 daddr, u32 src, u8 tos, struct fib_zone * fz; if (((src^cl->cl_src) & cl->cl_srcmask) || - ((dst^cl->cl_dst) & cl->cl_dstmask) || + ((daddr^cl->cl_dst) & cl->cl_dstmask) || (cl->cl_tos && cl->cl_tos != tos) || (cl->cl_dev && cl->cl_dev != devin)) continue; @@ -561,7 +561,7 @@ static int fib_autopublish(int op, struct fib_node *f, int logmask) ((struct sockaddr_in*)&r.arp_pa)->sin_family = AF_INET; ((struct sockaddr_in*)&r.arp_pa)->sin_addr.s_addr = addr; ((struct sockaddr_in*)&r.arp_netmask)->sin_family = AF_INET; - ((struct sockaddr_in*)&r.arp_netmask)->sin_addr.s_addr = fib_netmask(logmask); + ((struct sockaddr_in*)&r.arp_netmask)->sin_addr.s_addr = fib_mask(logmask); if (op) return arp_req_set(&r, NULL); @@ -570,7 +570,8 @@ static int fib_autopublish(int op, struct fib_node *f, int logmask) for (f1 = fz_hash(f->fib_key, fz); f1; f1=f1->fib_next) { if (f->fib_key != f1->fib_key || f1->fib_flag || - f->fib_info->fib_flags != f1->fib_info->fib_flags) + (!RT_LOCALADDR(f1->fib_info->fib_flags) && + !(f1->fib_info->fib_flags&RTF_NAT))) continue; return 0; } @@ -1032,6 +1033,8 @@ static int fib_flush_list(struct fib_node ** fp, struct device *dev, cli(); *fp = f->fib_next; sti(); + if (class == &local_class) + fib_autopublish(0, f, logmask); #ifdef CONFIG_RTNETLINK if (rt_nl_flags&RTCTL_FLUSH) rtmsg_fib(RTMSG_DELROUTE, f, logmask, class, 0); @@ -1397,7 +1400,7 @@ done: #endif -int rtmsg_process(struct nlmsghdr *n, struct in_rtmsg *r) +static int rtmsg_process(struct nlmsghdr *n, struct in_rtmsg *r) { unsigned long cmd=n->nlmsg_type; struct device * dev = NULL; @@ -1414,7 +1417,7 @@ int rtmsg_process(struct nlmsghdr *n, struct in_rtmsg *r) /* Reject/throw directives have no interface/gateway specification */ if (r->rtmsg_flags & (RTF_REJECT|RTF_THROW)) { - r->rtmsg_device[0] = 0; + r->rtmsg_ifindex = 0; r->rtmsg_gateway.s_addr = 0; r->rtmsg_flags &= ~RTF_GATEWAY; } @@ -1430,8 +1433,8 @@ int rtmsg_process(struct nlmsghdr *n, struct in_rtmsg *r) if (cmd == RTMSG_DELROUTE) r->rtmsg_flags &= RTF_FIB; - if (r->rtmsg_device[0]) { - dev = dev_get(r->rtmsg_device); + if (r->rtmsg_ifindex) { + dev = dev_get_by_index(r->rtmsg_ifindex); if (!dev) { rtmsg_ack(n, ENODEV); return -ENODEV; @@ -1525,8 +1528,8 @@ static int rtrulemsg_process(struct nlmsghdr *n, struct in_rtrulemsg *r) (r->rtrmsg_tos & ~IPTOS_TOS_MASK)) return -EINVAL; - if (r->rtrmsg_device[0]) { - dev = dev_get(r->rtrmsg_device); + if (r->rtrmsg_ifindex) { + dev = dev_get_by_index(r->rtrmsg_ifindex); if (!dev) return -ENODEV; if (dev->family != AF_INET) @@ -1574,9 +1577,18 @@ static int get_rt_from_user(struct in_rtmsg *rtm, void *arg) err = copy_from_user(&r, arg, sizeof(struct rtentry)); if (err) return -EFAULT; - if (r.rt_dev) - if (copy_from_user(&rtm->rtmsg_device, r.rt_dev, 15)) + if (r.rt_dev) { + struct device *dev; + char devname[16]; + + if (copy_from_user(devname, r.rt_dev, 15)) return -EFAULT; + devname[15] = 0; + dev = dev_get(devname); + if (!dev) + return -ENODEV; + rtm->rtmsg_ifindex = dev->ifindex; + } rtm->rtmsg_flags = r.rt_flags; @@ -1740,9 +1752,7 @@ rtmsg_fib(unsigned long type, struct fib_node *f, int logmask, r->rtmsg_mtu = fi->fib_mtu; r->rtmsg_window = fi->fib_window; r->rtmsg_rtt = fi->fib_irtt; - memset(r->rtmsg_device, 0, sizeof(r->rtmsg_device)); - if (fi->fib_dev) - strcpy(r->rtmsg_device, fi->fib_dev->name); + r->rtmsg_ifindex = fi->fib_dev ? fi->fib_dev->ifindex : 0; } } end_bh_atomic(); @@ -1777,7 +1787,8 @@ rtmsg_dev(unsigned long type, struct device *dev, struct nlmsghdr *n) r->ifmsg_mtu = dev->mtu; r->ifmsg_metric = dev->metric; r->ifmsg_prefixlen = 32 - fib_logmask(dev->pa_mask); - strcpy(r->ifmsg_device, dev->name); + r->ifmsg_index = dev->ifindex; + strcpy(r->ifmsg_name, dev->name); } end_bh_atomic(); } @@ -1866,6 +1877,28 @@ static int fib_magic(int op, unsigned flags, u32 dst, u32 mask, struct device *d (&r, dev, (flags&RTF_LOCAL) ? &local_class : &main_class, &n); } +static void ip_rt_del_broadcasts(struct device *dev) +{ + u32 net = dev->pa_addr&dev->pa_mask; + + fib_magic(RTMSG_DELROUTE, RTF_IFBRD, dev->pa_brdaddr, ~0, dev); + fib_magic(RTMSG_DELROUTE, RTF_IFBRD, net, ~0, dev); + fib_magic(RTMSG_DELROUTE, RTF_IFBRD, net|~dev->pa_mask, ~0, dev); +} + +static void ip_rt_add_broadcasts(struct device *dev, u32 brd, u32 mask) +{ + u32 net = dev->pa_addr&mask; + + if (dev->flags&IFF_BROADCAST) + fib_magic(RTMSG_NEWROUTE, RTF_IFBRD, brd, ~0, dev); + + if (net && !(mask&htonl(1))) { + fib_magic(RTMSG_NEWROUTE, RTF_IFBRD, net, ~0, dev); + fib_magic(RTMSG_NEWROUTE, RTF_IFBRD, net|~mask, ~0, dev); + } +} + void ip_rt_change_broadcast(struct device *dev, u32 new_brd) { fib_lock(); @@ -1875,7 +1908,7 @@ void ip_rt_change_broadcast(struct device *dev, u32 new_brd) fib_magic(RTMSG_DELROUTE, RTF_IFBRD, dev->pa_brdaddr, ~0, dev); rtmsg_dev(RTMSG_DELDEVICE, dev, NULL); rtmsg_dev(RTMSG_NEWDEVICE, dev, NULL); - fib_magic(RTMSG_NEWROUTE, RTF_IFBRD, new_brd, ~0, dev); + ip_rt_add_broadcasts(dev, new_brd, dev->pa_mask); } fib_unlock(); } @@ -1908,22 +1941,19 @@ void ip_rt_change_netmask(struct device *dev, u32 mask) } net = dev->pa_addr&dev->pa_mask; fib_magic(RTMSG_DELROUTE, RTF_IFPREFIX, net, dev->pa_mask, dev); - fib_magic(RTMSG_DELROUTE, RTF_IFBRD, net, ~0, dev); - fib_magic(RTMSG_DELROUTE, RTF_IFBRD, net|~dev->pa_mask, ~0, dev); + ip_rt_del_broadcasts(dev); if (mask != 0xFFFFFFFF && dev->flags&IFF_POINTOPOINT) fib_magic(RTMSG_DELROUTE, RTF_IFPREFIX, dev->pa_dstaddr, ~0, dev); rtmsg_dev(RTMSG_DELDEVICE, dev, NULL); - dev->flags &= ~IFF_POINTOPOINT; + if (mask != 0xFFFFFFFF) + dev->flags &= ~IFF_POINTOPOINT; rtmsg_dev(RTMSG_NEWDEVICE, dev, NULL); net = dev->pa_addr&mask; if (net) fib_magic(RTMSG_NEWROUTE, RTF_IFPREFIX, net, mask, dev); - if (net && mask != 0xFFFFFFFF) { - fib_magic(RTMSG_NEWROUTE, RTF_IFBRD, net, ~0, dev); - fib_magic(RTMSG_NEWROUTE, RTF_IFBRD, net|~mask, ~0, dev); - } + ip_rt_add_broadcasts(dev, dev->pa_addr, mask); fib_unlock(); } @@ -1947,8 +1977,7 @@ int ip_rt_event(int event, struct device *dev) else { u32 net = dev->pa_addr&dev->pa_mask; fib_magic(RTMSG_DELROUTE, RTF_IFPREFIX, net, dev->pa_mask, dev); - fib_magic(RTMSG_DELROUTE, RTF_IFBRD, net, ~0, dev); - fib_magic(RTMSG_DELROUTE, RTF_IFBRD, net|~dev->pa_mask, ~0, dev); + ip_rt_del_broadcasts(dev); } rtmsg_dev(RTMSG_DELDEVICE, dev, NULL); } @@ -1971,14 +2000,12 @@ int ip_rt_event(int event, struct device *dev) if (dev->flags&IFF_POINTOPOINT) { if (dev->pa_dstaddr && dev->type != ARPHRD_TUNNEL) fib_magic(RTMSG_NEWROUTE, RTF_IFPREFIX, dev->pa_dstaddr, ~0, dev); - } else if (dev->pa_addr&dev->pa_mask) { + } else { u32 net = dev->pa_addr&dev->pa_mask; - fib_magic(RTMSG_NEWROUTE, RTF_IFPREFIX, net, dev->pa_mask, dev); - if (dev->pa_mask != 0xFFFFFFFF) { - fib_magic(RTMSG_NEWROUTE, RTF_IFBRD, net, ~0, dev); - fib_magic(RTMSG_NEWROUTE, RTF_IFBRD, net|~dev->pa_mask, ~0, dev); - } + if (net) + fib_magic(RTMSG_NEWROUTE, RTF_IFPREFIX, net, dev->pa_mask, dev); + ip_rt_add_broadcasts(dev, dev->pa_brdaddr, dev->pa_mask); } fib_magic(RTMSG_NEWROUTE, RTF_IFLOCAL, dev->pa_addr, ~0, dev); if (dev == &loopback_dev) { @@ -1992,9 +2019,9 @@ int ip_rt_event(int event, struct device *dev) mask, dev); } } - if (dev->flags&IFF_BROADCAST) - fib_magic(RTMSG_NEWROUTE, RTF_IFBRD, dev->pa_brdaddr, ~0, dev); } + if (event == NETDEV_CHANGEMTU || event == NETDEV_CHANGEADDR) + rtmsg_dev(RTMSG_NEWDEVICE, dev, NULL); fib_unlock(); return NOTIFY_DONE; } diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c index 94fbcbbe6733..5f4d3562084f 100644 --- a/net/ipv4/ip_forward.c +++ b/net/ipv4/ip_forward.c @@ -205,7 +205,7 @@ skip_call_fw_firewall: } #endif - if (skb_headroom(skb) < dev2->hard_header_len) { + if (skb_headroom(skb) < dev2->hard_header_len || skb_cloned(skb)) { struct sk_buff *skb2; skb2 = skb_realloc_headroom(skb, (dev2->hard_header_len + 15)&~15); kfree_skb(skb, FREE_WRITE); diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index 95c59709a162..850d729e8982 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c @@ -154,9 +154,7 @@ #include #include #include -#ifdef CONFIG_NET_ALIAS #include -#endif /* * SNMP management statistics diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c index f24f4dc38eb0..2c79745064c4 100644 --- a/net/ipv4/ip_options.c +++ b/net/ipv4/ip_options.c @@ -484,15 +484,21 @@ void ip_options_undo(struct ip_options * opt) } } -int ip_options_getfromuser(struct ip_options **optp, unsigned char *data, int optlen) +int ip_options_get(struct ip_options **optp, unsigned char *data, int optlen, int user) { struct ip_options *opt; + opt = kmalloc(sizeof(struct ip_options)+((optlen+3)&~3), GFP_KERNEL); if (!opt) return -ENOMEM; memset(opt, 0, sizeof(struct ip_options)); - if (optlen && copy_from_user(opt->__data, data, optlen)) - return -EFAULT; + if (optlen) { + if (user) { + if (copy_from_user(opt->__data, data, optlen)) + return -EFAULT; + } else + memcpy(opt->__data, data, optlen); + } while (optlen & 3) opt->__data[optlen++] = IPOPT_END; opt->optlen = optlen; diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 0d7584cfd409..2be8be456152 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c @@ -40,11 +40,16 @@ * SOL_IP control messages. */ -static void ip_cmsg_recv_localdev(struct msghdr *msg, struct sk_buff *skb) +static void ip_cmsg_recv_rxinfo(struct msghdr *msg, struct sk_buff *skb) { - static char empty_name[MAX_ADDR_LEN]; - put_cmsg(msg, SOL_IP, IP_LOCALDEV, MAX_ADDR_LEN, - skb->dev ? skb->dev->name : empty_name); + struct in_pktinfo info; + struct rtable *rt = (struct rtable *)skb->dst; + + info.ipi_ifindex = skb->dev->ifindex; + info.ipi_addr.s_addr = skb->nh.iph->daddr; + info.ipi_spec_dst.s_addr = rt->rt_spec_dst; + + put_cmsg(msg, SOL_IP, IP_RXINFO, sizeof(info), &info); } static void ip_cmsg_recv_localaddr(struct msghdr *msg, struct sk_buff *skb, int local) @@ -94,20 +99,20 @@ void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb) /* Ordered by supposed usage frequency */ if (flags & 1) - ip_cmsg_recv_localaddr(msg, skb, 1); - if ((flags>>1) == 0) + ip_cmsg_recv_rxinfo(msg, skb); + if ((flags>>=1) == 0) return; if (flags & 1) - ip_cmsg_recv_localdev(msg, skb); - if ((flags>>1) == 0) + ip_cmsg_recv_localaddr(msg, skb, 1); + if ((flags>>=1) == 0) return; if (flags & 1) ip_cmsg_recv_opts(msg, skb); - if ((flags>>1) == 0) + if ((flags>>=1) == 0) return; if (flags & 1) ip_cmsg_recv_retopts(msg, skb); - if ((flags>>1) == 0) + if ((flags>>=1) == 0) return; if (flags & 1) ip_cmsg_recv_localaddr(msg, skb, 0); @@ -116,38 +121,38 @@ void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb) int ip_cmsg_send(struct msghdr *msg, struct ipcm_cookie *ipc, struct device **devp) { int err; - struct cmsghdr kcm, *cmsg; - char devname[MAX_ADDR_LEN]; + struct cmsghdr *cmsg; - for (cmsg = KCMSG_FIRSTHDR(msg); cmsg; cmsg = KCMSG_NXTHDR(msg, cmsg)) { - if (kcm.cmsg_level != SOL_IP) + for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) { + if (cmsg->cmsg_level != SOL_IP) continue; - switch (kcm.cmsg_type) + switch (cmsg->cmsg_type) { case IP_LOCALADDR: - if (kcm.cmsg_len < sizeof(struct in_addr)+sizeof(kcm)) + if (cmsg->cmsg_len < sizeof(struct in_addr)+sizeof(*cmsg)) return -EINVAL; - if (copy_from_user(&ipc->addr, cmsg->cmsg_data, 4)) - return -EFAULT; + memcpy(&ipc->addr, cmsg->cmsg_data, 4); break; case IP_RETOPTS: - err = kcm.cmsg_len - sizeof(kcm); - err = ip_options_getfromuser(&ipc->opt, cmsg->cmsg_data, - err < 40 ? err : 40); + err = cmsg->cmsg_len - sizeof(*cmsg); + err = ip_options_get(&ipc->opt, cmsg->cmsg_data, + err < 40 ? err : 40, 0); if (err) return err; break; - case IP_LOCALDEV: - if (kcm.cmsg_len < MAX_ADDR_LEN+sizeof(kcm)) + case IP_TXINFO: + { + struct in_pktinfo *info; + if (cmsg->cmsg_len < sizeof(*info)+sizeof(*cmsg)) return -EINVAL; - if (!devp) + info = (struct in_pktinfo*)cmsg->cmsg_data; + if (info->ipi_ifindex && !devp) return -EINVAL; - if (copy_from_user(devname, cmsg->cmsg_data, MAX_ADDR_LEN-1)) - return -EFAULT; - devname[MAX_ADDR_LEN-1] = 0; - if ((*devp = dev_get(devname)) == NULL) + if ((*devp = dev_get_by_index(info->ipi_ifindex)) == NULL) return -ENODEV; + ipc->addr = info->ipi_spec_dst.s_addr; break; + } default: return -EINVAL; } @@ -200,7 +205,7 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt struct ip_options * old_opt; if (optlen > 40 || optlen < 0) return -EINVAL; - err = ip_options_getfromuser(&opt, optval, optlen); + err = ip_options_get(&opt, optval, optlen, 1); if (err) return err; /* @@ -215,13 +220,13 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt kfree_s(old_opt, sizeof(struct optlen) + old_opt->optlen); return 0; } - case IP_LOCALADDR: + case IP_RXINFO: if (val) sk->ip_cmsg_flags |= 1; else sk->ip_cmsg_flags &= ~1; return 0; - case IP_LOCALDEV: + case IP_LOCALADDR: if (val) sk->ip_cmsg_flags |= 2; else @@ -313,7 +318,7 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt if (addr.s_addr==INADDR_ANY) /* Default */ { - memset(sk->ip_mc_name, 0, sizeof(sk->ip_mc_name)); + sk->ip_mc_index = 0; return 0; } @@ -329,8 +334,7 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt if(dev) { - memset(sk->ip_mc_name, 0, sizeof(sk->ip_mc_name)); - strcpy(sk->ip_mc_name, dev->name); + sk->ip_mc_index = dev->ifindex; return 0; } return -EADDRNOTAVAIL; @@ -425,25 +429,28 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt case IP_MULTICAST_IFN: { - struct device *dev; - char *devname; + struct ip_mreqn mreq; + struct device *dev = NULL; - err = getname(optval, &devname); + err = copy_from_user(&mreq,optval,sizeof(mreq)); if (err) - return err; - if (!devname[0]) - { - memset(sk->ip_mc_name, 0, sizeof(sk->ip_mc_name)); - putname(devname); - return 0; - } - dev = dev_get(devname); - putname(devname); + return -EFAULT; + + if (!mreq.imr_ifindex) { + if (!mreq.imr_address.s_addr) { + sk->ip_mc_index = 0; + sk->ip_mc_addr = 0; + return 0; + } + dev = ip_dev_find(mreq.imr_address.s_addr, NULL); + } else + dev = dev_get_by_index(mreq.imr_ifindex); + if (!dev) return -ENODEV; - memset(sk->ip_mc_name, 0, sizeof(sk->ip_mc_name)); - strcpy(sk->ip_mc_name,dev->name); + sk->ip_mc_index = mreq.imr_ifindex; + sk->ip_mc_addr = mreq.imr_address.s_addr; return 0; } case IP_ADD_MEMBERSHIPN: @@ -451,14 +458,10 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt struct ip_mreqn mreq; struct device *dev = NULL; - /* - * Check the arguments. - */ - err = copy_from_user(&mreq,optval,sizeof(mreq)); if (err) return -EFAULT; - dev = dev_get(mreq.imr_interface); + dev = dev_get_by_index(mreq.imr_ifindex); if (!dev) return -ENODEV; return ip_mc_join_group(sk,dev,mreq.imr_multiaddr.s_addr); @@ -477,7 +480,7 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt if (err) return -EFAULT; - dev=dev_get(mreq.imr_interface); + dev=dev_get_by_index(mreq.imr_ifindex); if(!dev) return -ENODEV; @@ -583,10 +586,10 @@ int ip_getsockopt(struct sock *sk, int level, int optname, char *optval, int *op return err; } return 0; - case IP_LOCALADDR: + case IP_RXINFO: val = (sk->ip_cmsg_flags & 1) != 0; return 0; - case IP_LOCALDEV: + case IP_LOCALADDR: val = (sk->ip_cmsg_flags & 2) != 0; return 0; case IP_RECVOPTS: @@ -619,17 +622,40 @@ int ip_getsockopt(struct sock *sk, int level, int optname, char *optval, int *op case IP_MULTICAST_LOOP: val=sk->ip_mc_loop; break; - case IP_MULTICAST_IF: case IP_MULTICAST_IFN: - len=strlen(sk->ip_mc_name); + { + struct ip_mreqn mreq; + len = sizeof(struct ip_mreqn); + err = put_user(len, optlen); + mreq.imr_ifindex = sk->ip_mc_index; + mreq.imr_address.s_addr = sk->ip_mc_addr; + mreq.imr_multiaddr.s_addr = 0; + if (!err) { + err = copy_to_user((void *)optval, &mreq, len); + if (err) + err = -EFAULT; + } + return err; + } + case IP_MULTICAST_IF: + { + struct device *dev = dev_get_by_index(sk->ip_mc_index); + if (dev == NULL) { + len = 0; + return put_user(len, optlen); + } + dev_lock_list(); + len = strlen(dev->name); err = put_user(len, optlen); if (!err) { - err = copy_to_user((void *)optval,sk->ip_mc_name, len); + err = copy_to_user((void *)optval,dev->name, len); if (err) err = -EFAULT; } + dev_unlock_list(); return err; + } default: return(-ENOPROTOOPT); } diff --git a/net/ipv4/packet.c b/net/ipv4/packet.c index c0ddaa2175ca..8187b20c8793 100644 --- a/net/ipv4/packet.c +++ b/net/ipv4/packet.c @@ -248,6 +248,7 @@ static void packet_close(struct sock *sk, unsigned long timeout) } release_sock(sk); + sk->dead = 1; destroy_sock(sk); } diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 4b4918df4be9..69a2bd476ff7 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -249,8 +249,8 @@ static int raw_sendto(struct sock *sk, const unsigned char *from, } tos = RT_TOS(sk->ip_tos) | (sk->localroute || (msg->msg_flags&MSG_DONTROUTE)); - if (MULTICAST(daddr) && sk->ip_mc_name[0] && dev==NULL) - err = ip_route_output_dev(&rt, daddr, rfh.saddr, tos, sk->ip_mc_name); + if (MULTICAST(daddr) && sk->ip_mc_index && dev==NULL) + err = ip_route_output_dev(&rt, daddr, rfh.saddr, tos, sk->ip_mc_index); else err = ip_route_output(&rt, daddr, rfh.saddr, tos, dev); diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 9f6382f59c06..a39d256f4067 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -78,7 +78,11 @@ #include #include #include - + +/* Compile time configuretion flags */ + +#define CONFIG_IP_LOCAL_RT_POLICY 1 + static void rt_run_flush(unsigned long); static struct timer_list rt_flush_timer = @@ -629,7 +633,8 @@ void ip_rt_send_redirect(struct sk_buff *skb) icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, rt->rt_gateway); rt->last_error = jiffies; if (ipv4_config.log_martians && ++rt->errors == RT_REDIRECT_NUMBER) - printk(KERN_WARNING "host %08x/%s ignores redirects.\n", rt->rt_src, rt->rt_src_dev->name); + printk(KERN_WARNING "host %08x/%s ignores redirects for %08x to %08x.\n", + rt->rt_src, rt->rt_src_dev->name, rt->rt_dst, rt->rt_gateway); } } @@ -1187,13 +1192,8 @@ int ip_route_output_slow(struct rtable **rp, u32 daddr, u32 saddr, u8 tos, fi = res.f->fib_info; dst_map = daddr; - if (fi->fib_flags&RTF_NAT) { - dst_map = htonl((ntohl(daddr)&((1<fib_gateway; - fi = fib_lookup_info(dst_map, saddr, tos, &loopback_dev, dev_out); - if (!fi || fi->fib_flags&(RTF_NAT|RTF_LOCAL|RTF_MULTICAST|RTF_BROADCAST)) - return -EINVAL; - flags = RTCF_NAT; - } + if (fi->fib_flags&RTF_NAT) + return -EINVAL; if (!saddr) { saddr = fi->fib_dev->pa_addr; @@ -1305,9 +1305,7 @@ make_route: rth->u.dst.rtt = TCP_TIMEOUT_INIT; } rth->rt_flags = flags; - hash = rt_hash_code(dst_key, src_key, tos); - if (dst_dev_key) - hash ^= dev_hash_name(dst_dev_key->name); + hash = rt_hash_code(dst_key, dst_dev_key ? src_key^(dst_dev_key->ifindex<<5) : src_key, tos); *rp = rt_intern_hash(hash, rth, ETH_P_IP); return 0; } @@ -1317,9 +1315,8 @@ int ip_route_output(struct rtable **rp, u32 daddr, u32 saddr, u8 tos, struct dev unsigned hash; struct rtable *rth; - hash = rt_hash_code(daddr, saddr, tos); - if (dev_out) - hash ^= dev_out->hash; + hash = rt_hash_code(daddr, dev_out ? saddr^(dev_out->ifindex<<5) + : saddr, tos); start_bh_atomic(); for (rth=rt_hash_table[hash]; rth; rth=rth->u.rt_next) { @@ -1341,13 +1338,13 @@ int ip_route_output(struct rtable **rp, u32 daddr, u32 saddr, u8 tos, struct dev return ip_route_output_slow(rp, daddr, saddr, tos, dev_out); } -int ip_route_output_dev(struct rtable **rp, u32 daddr, u32 saddr, u8 tos, char *devname) +int ip_route_output_dev(struct rtable **rp, u32 daddr, u32 saddr, u8 tos, int ifindex) { unsigned hash; struct rtable *rth; struct device *dev_out; - hash = rt_hash_code(daddr, saddr, tos)^dev_hash_mc_name(devname); + hash = rt_hash_code(daddr, saddr^(ifindex<<5), tos); start_bh_atomic(); for (rth=rt_hash_table[hash]; rth; rth=rth->u.rt_next) { @@ -1356,7 +1353,7 @@ int ip_route_output_dev(struct rtable **rp, u32 daddr, u32 saddr, u8 tos, char * rth->key.src_dev == NULL && rth->key.tos == tos && rth->key.dst_dev && - strcmp(rth->key.dst_dev->name, devname)==0) { + rth->key.dst_dev->ifindex == ifindex) { rth->u.dst.lastuse = jiffies; atomic_inc(&rth->u.dst.use); atomic_inc(&rth->u.dst.refcnt); @@ -1367,7 +1364,7 @@ int ip_route_output_dev(struct rtable **rp, u32 daddr, u32 saddr, u8 tos, char * } end_bh_atomic(); - dev_out = dev_get(devname); + dev_out = dev_get_by_index(ifindex); if (!dev_out) return -ENODEV; return ip_route_output_slow(rp, daddr, saddr, tos, dev_out); diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index fdb375ea73f8..bfb3259f3001 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -895,7 +895,7 @@ int tcp_do_sendmsg(struct sock *sk, int iovlen, struct iovec *iov, } /* - *Now we need to check if we have a half built packet. + * Now we need to check if we have a half built packet. */ /* if we have queued packets */ @@ -912,9 +912,8 @@ int tcp_do_sendmsg(struct sock *sk, int iovlen, struct iovec *iov, /* * This window_seq test is somewhat dangerous * If the remote does SWS avoidance we should - * queue the best we can - * if not we should in fact send multiple - * packets... + * queue the best we can if not we should in + * fact send multiple packets... * a method for detecting this would be most * welcome */ diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 440a81369f3b..705c9dfe15d8 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -375,8 +375,8 @@ static int udp_sendto(struct sock *sk, const unsigned char *from, int len, tos = RT_TOS(sk->ip_tos) | (sk->localroute || (msg->msg_flags&MSG_DONTROUTE) || (ipc.opt && ipc.opt->is_strictroute)); - if (MULTICAST(daddr) && sk->ip_mc_name[0] && dev == NULL) - err = ip_route_output_dev(&rt, daddr, ufh.saddr, tos, sk->ip_mc_name); + if (MULTICAST(daddr) && sk->ip_mc_index && dev == NULL) + err = ip_route_output_dev(&rt, daddr, ufh.saddr, tos, sk->ip_mc_index); else err = ip_route_output(&rt, daddr, ufh.saddr, tos, dev); diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index f812ab0a35a0..30f32d99cfe0 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -56,7 +56,6 @@ struct ipv6_mc_list *inet6_mcast_lst[HASH_SIZE]; * AF_INET6 device list */ struct inet6_dev *inet6_dev_lst; -int in6_ifnum = 0; atomic_t addr_list_lock = 0; @@ -167,7 +166,7 @@ struct inet6_dev * ipv6_add_dev(struct device *dev) memset(dev6, 0, sizeof(struct inet6_dev)); dev6->dev = dev; - dev6->if_index = ++in6_ifnum; + dev6->if_index = dev->ifindex; /* * insert at head. @@ -894,40 +893,6 @@ err_exit: return err; } -/* - * Obtain if_index from device name - */ -int addrconf_get_ifindex(void *arg) -{ - struct ifreq ifr; - int res = -ENODEV; - - if (copy_from_user(&ifr, arg, sizeof(struct ifreq))) - { - res = -EFAULT; - } - else - { - struct inet6_dev *idev; - - for (idev = inet6_dev_lst; idev; idev=idev->next) - { - if (!strncmp(ifr.ifr_name, idev->dev->name, IFNAMSIZ)) - { - res = 0; - ifr.ifr_ifindex = idev->if_index; - if (copy_to_user(arg, &ifr, sizeof(ifr))) - { - res = -EFAULT; - } - break; - } - } - } - - return res; -} - /* * Manual configuration of address on an interface */ diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index c1b9d1f028e6..dc545116a449 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -61,44 +61,6 @@ #include #include -/* - * Default callbacks for user INET sockets. These just wake up - * the user owning the socket. - */ - -static void def_callback1(struct sock *sk) -{ - if(!sk->dead) - wake_up_interruptible(sk->sleep); -} - -static void def_callback2(struct sock *sk,int len) -{ - if(!sk->dead) - { - wake_up_interruptible(sk->sleep); - sock_wake_async(sk->socket, 1); - } -} - -static void def_callback3(struct sock *sk) -{ - long wmem; - - wmem = (long) sk->wmem_alloc; - - if (wmem < 0) { - printk(KERN_DEBUG "bug wmem_alloc < 0\n"); - sk->wmem_alloc = 0; - } - - if(!sk->dead && sk->wmem_alloc*2 <= sk->sndbuf) - { - wake_up_interruptible(sk->sleep); - sock_wake_async(sk->socket, 2); - } -} - struct sock * rawv6_sock_array[SOCK_ARRAY_SIZE]; extern struct proto_ops inet6_stream_ops; @@ -114,9 +76,6 @@ static int inet6_create(struct socket *sock, int protocol) if (sk == NULL) return(-ENOBUFS); - /* Efficient way to set most fields to zero */ - memset(sk,0,sizeof(*sk)); - /* * Note for tcp that also wiped the dummy_th block for us. */ @@ -168,39 +127,19 @@ static int inet6_create(struct socket *sock, int protocol) sk_free(sk); return(-ESOCKTNOSUPPORT); } - - sk->socket = sock; + + sock_init_data(sock,sk); sk->family = AF_INET6; - sk->type = sock->type; sk->protocol = protocol; - sk->allocation = GFP_KERNEL; - sk->sndbuf = SK_WMEM_MAX; - sk->rcvbuf = SK_RMEM_MAX; - sk->priority = 1; sk->prot = prot; sk->backlog_rcv = prot->backlog_rcv; - sk->sleep = &sock->wait; - sock->sk = sk; - - sk->state = TCP_CLOSE; - - skb_queue_head_init(&sk->write_queue); - skb_queue_head_init(&sk->receive_queue); - skb_queue_head_init(&sk->error_queue); - skb_queue_head_init(&sk->back_log); - sk->timer.data = (unsigned long)sk; sk->timer.function = &net_timer; init_timer(&sk->timer); - sk->state_change = def_callback1; - sk->data_ready = def_callback2; - sk->write_space = def_callback3; - sk->error_report = def_callback1; - sk->net_pinfo.af_inet6.hop_limit = ipv6_hop_limit; sk->net_pinfo.af_inet6.mcast_hops = IPV6_DEFAULT_MCASTHOPS; sk->net_pinfo.af_inet6.mc_loop = 1; @@ -212,12 +151,10 @@ static int inet6_create(struct socket *sock, int protocol) sk->ip_ttl=64; -#ifdef CONFIG_IP_MULTICAST sk->ip_mc_loop=1; sk->ip_mc_ttl=1; - *sk->ip_mc_name=0; + sk->ip_mc_index=0; sk->ip_mc_list=NULL; -#endif if (sk->type==SOCK_RAW && protocol==IPPROTO_RAW) @@ -490,7 +427,7 @@ static int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) if(err) return err; - /* see inet_fcntl */ + /* see sock_no_fcntl */ if (current->pid != pid && current->pgrp != -pid && !suser()) return -EPERM; sk->proc = pid; @@ -551,18 +488,10 @@ static int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) case SIOCGIFMAP: case SIOCSIFSLAVE: case SIOCGIFSLAVE: + case SIOGIFINDEX: return(dev_ioctl(cmd,(void *) arg)); - return -EINVAL; - - case SIOGIFINDEX: - /* - * This one will be moved to the generic device - * layer in the near future - */ - return addrconf_get_ifindex((void *) arg); - case SIOCSIFADDR: return addrconf_add_ifaddr((void *) arg); case SIOCSIFDSTADDR: @@ -804,7 +733,7 @@ struct proto_ops inet6_stream_ops = { inet_shutdown, /* ok */ inet_setsockopt, /* ok */ inet_getsockopt, /* ok */ - inet_fcntl, /* ok */ + sock_no_fcntl, /* ok */ inet_sendmsg, /* ok */ inet_recvmsg /* ok */ }; @@ -825,7 +754,7 @@ struct proto_ops inet6_dgram_ops = { inet_shutdown, /* ok */ inet_setsockopt, /* ok */ inet_getsockopt, /* ok */ - inet_fcntl, /* ok */ + sock_no_fcntl, /* ok */ inet_sendmsg, /* ok */ inet_recvmsg /* ok */ }; @@ -844,9 +773,16 @@ void inet6_proto_init(struct net_proto *pro) #endif { int i; + struct sk_buff *dummy_skb; printk(KERN_INFO "IPv6 v0.1 for NET3.037\n"); + if (sizeof(struct ipv6_options) > sizeof(dummy_skb->cb)) + { + printk(KERN_CRIT "inet6_proto_init: panic\n"); + return; + } + (void) sock_register(&inet6_family_ops); for(i = 0; i < SOCK_ARRAY_SIZE; i++) diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index bc138c178bef..a9eb6ab5cd41 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c @@ -31,79 +31,30 @@ int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb) { struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6; struct ipv6_options *opt = (struct ipv6_options *) skb->cb; - struct cmsghdr *cmsg = msg->msg_control; - int len = msg->msg_controllen; - - msg->msg_controllen = 0; - if (np->rxinfo && (len >= sizeof(struct cmsghdr) + - sizeof(struct in6_pktinfo))) + if (np->rxinfo) { - struct in6_pktinfo *src_info; - struct inet6_dev *in6_dev; - - cmsg->cmsg_len = (sizeof(struct cmsghdr) + - sizeof(struct in6_pktinfo)); - cmsg->cmsg_level = SOL_IPV6; - cmsg->cmsg_type = IPV6_RXINFO; - - src_info = (struct in6_pktinfo *) cmsg->cmsg_data; - in6_dev = ipv6_get_idev(skb->dev); + struct in6_pktinfo src_info; - if (in6_dev == NULL) - { - printk(KERN_DEBUG "recv_ctl: unknown device\n"); - return -ENODEV; - } - - src_info->ipi6_ifindex = in6_dev->if_index; - ipv6_addr_copy(&src_info->ipi6_addr, - &skb->nh.ipv6h->daddr); - - len -= cmsg->cmsg_len; - msg->msg_controllen += cmsg->cmsg_len; - cmsg = (struct cmsghdr *)((u8*) cmsg + cmsg->cmsg_len); + src_info.ipi6_ifindex = skb->dev->ifindex; + ipv6_addr_copy(&src_info.ipi6_addr, &skb->nh.ipv6h->daddr); + put_cmsg(msg, SOL_IPV6, IPV6_RXINFO, sizeof(src_info), &src_info); } - if (np->rxhlim && (len >= sizeof(struct cmsghdr) + sizeof(int))) + if (np->rxhlim) { - int *hlim; - - cmsg->cmsg_len = (sizeof(struct cmsghdr) + sizeof(int)); - cmsg->cmsg_level = SOL_IPV6; - cmsg->cmsg_type = IPV6_HOPLIMIT; - - hlim = (int *) cmsg->cmsg_data; - *hlim = skb->nh.ipv6h->hop_limit; - - len -= cmsg->cmsg_len; - msg->msg_controllen += cmsg->cmsg_len; - cmsg = (struct cmsghdr *)((u8*) cmsg + cmsg->cmsg_len); + int hlim = skb->nh.ipv6h->hop_limit; + put_cmsg(msg, SOL_IPV6, IPV6_HOPLIMIT, sizeof(hlim), &hlim); } if (opt->srcrt) { int hdrlen = sizeof(struct rt0_hdr) + (opt->srcrt->hdrlen << 3); - if (len >= sizeof(struct cmsghdr) + hdrlen) - { - struct rt0_hdr *rt0; - - cmsg->cmsg_len = sizeof(struct cmsghdr) + hdrlen; - cmsg->cmsg_level = SOL_IPV6; - cmsg->cmsg_type = IPV6_RXINFO; - - rt0 = (struct rt0_hdr *) cmsg->cmsg_data; - memcpy(rt0, opt->srcrt, hdrlen); - - len -= cmsg->cmsg_len; - msg->msg_controllen += cmsg->cmsg_len; - cmsg = (struct cmsghdr *)((u8*) cmsg + cmsg->cmsg_len); - } + put_cmsg(msg, SOL_IPV6, IPV6_RXSRCRT, hdrlen, opt->srcrt); } return 0; } - int datagram_send_ctl(struct msghdr *msg, struct device **src_dev, struct in6_addr **src_addr, struct ipv6_options *opt, @@ -116,7 +67,7 @@ int datagram_send_ctl(struct msghdr *msg, struct device **src_dev, int len; int err = 0; - for (cmsg = msg->msg_control; cmsg; cmsg = cmsg_nxthdr(msg, cmsg)) + for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) { if (cmsg->cmsg_level != SOL_IPV6) { @@ -165,7 +116,7 @@ int datagram_send_ctl(struct msghdr *msg, struct device **src_dev, break; - case SCM_SRCRT: + case IPV6_RXSRCRT: len = cmsg->cmsg_len; diff --git a/net/ipv6/ipv6_input.c b/net/ipv6/ipv6_input.c index ba1a00ab699d..e02802c2554a 100644 --- a/net/ipv6/ipv6_input.c +++ b/net/ipv6/ipv6_input.c @@ -269,6 +269,11 @@ int ipv6_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt) __u8 *nhptr; int pkt_len; + if (skb->pkt_type == PACKET_OTHERHOST) { + kfree_skb(skb, FREE_READ); + return 0; + } + hdr = skb->nh.ipv6h; skb->h.raw = (__u8*)hdr; @@ -408,6 +413,11 @@ int ipv6_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt) } else { + if (skb->pkt_type != PACKET_HOST) { + kfree_skb(skb, FREE_READ); + return 0; + } + if (ipv6_forwarding) { if (addr_type & IPV6_ADDR_LINKLOCAL) diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 0775d1a605d7..ec090bad1d83 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -150,16 +150,7 @@ int rawv6_recvmsg(struct sock *sk, struct msghdr *msg, int len, } if (msg->msg_controllen) - { - int err; - - err = datagram_recv_ctl(sk, msg, skb); - - if (err < 0) - { - copied = err; - } - } + datagram_recv_ctl(sk, msg, skb); skb_free_datagram(sk, skb); return (copied); @@ -311,7 +302,7 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, int len) if (len + (sk->ip_hdrincl ? 0 : sizeof(struct ipv6hdr)) > 65535) return -EMSGSIZE; - if (msg->msg_control) + if (msg->msg_controllen) { opt = &opt_space; memset(opt, 0, sizeof(struct ipv6_options)); diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 7b13506fe29c..90267b7f1464 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -208,7 +208,7 @@ static int sit_init_dev(struct device *dev) dev->hard_header_len = MAX_HEADER; dev->mtu = 1500 - sizeof(struct iphdr); dev->addr_len = 0; - dev->tx_queue_len = 2; + dev->tx_queue_len = 0; memset(dev->broadcast, 0, MAX_ADDR_LEN); memset(dev->dev_addr, 0, MAX_ADDR_LEN); @@ -415,31 +415,19 @@ static int sit_xmit(struct sk_buff *skb, struct device *dev) struct enet_statistics *stats; struct sit_mtu_info *minfo; struct in6_addr *addr6; - unsigned long flags; struct rtable *rt; struct iphdr *iph; __u32 saddr; __u32 daddr; - __u32 raddr; int addr_type; int mtu; - int len; + int headroom; /* * Make sure we are not busy (check lock variable) */ stats = (struct enet_statistics *)dev->priv; - save_flags(flags); - cli(); - if (dev->tbusy != 0) - { - restore_flags(flags); - printk(KERN_DEBUG "sit_xmit: busy\n"); - return(1); - } - dev->tbusy = 1; - restore_flags(flags); daddr = dev->pa_dstaddr; if (daddr == 0) @@ -470,79 +458,57 @@ static int sit_xmit(struct sk_buff *skb, struct device *dev) daddr = addr6->s6_addr32[3]; } - len = skb->tail - (skb->data + sizeof(struct ipv6hdr)); - - skb_orphan(skb); - - iph = (struct iphdr *) skb_push(skb, sizeof(struct iphdr)); - - skb->protocol = htons(ETH_P_IP); - - /* get route */ - if (ip_route_output(&rt, daddr, 0, 0, NULL)) { printk(KERN_DEBUG "sit: no route to host\n"); goto on_error; } - skb->dst = dst_clone(&rt->u.dst); minfo = sit_mtu_lookup(daddr); + /* IP should calculate pmtu correctly, + * let's check it... + */ +#if 0 if (minfo) mtu = minfo->mtu; else - mtu = rt->u.dst.dev->mtu; +#endif + mtu = rt->u.dst.pmtu; - if (mtu > 576 && len > mtu) + if (mtu > 576 && skb->tail - (skb->data + sizeof(struct ipv6hdr)) > mtu) { icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, dev); + ip_rt_put(rt); goto on_error; } - saddr = rt->rt_src; - skb->dev = rt->u.dst.dev; - raddr = rt->rt_gateway; - - if (raddr == 0) - raddr = daddr; - - /* now for the device header */ - - skb->arp = 1; - - if (skb->dev->hard_header_len) - { - int mac; + headroom = ((rt->u.dst.dev->hard_header_len+15)&~15)+sizeof(struct iphdr); - if (skb->data - skb->head < skb->dev->hard_header_len) - { - printk(KERN_DEBUG "sit: space at head < dev header\n"); + if (skb_headroom(skb) < headroom || skb_shared(skb)) { + struct sk_buff *new_skb = skb_realloc_headroom(skb, headroom); + if (!new_skb) { + ip_rt_put(rt); goto on_error; } - - if (skb->dev->hard_header) - { - mac = skb->dev->hard_header(skb, skb->dev, ETH_P_IP, - NULL, NULL, len); - - if (mac < 0) - skb->arp = 0; - - } - + dev_kfree_skb(skb, FREE_WRITE); + skb = new_skb; } + + memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); - ip_rt_put(rt); + iph = (struct iphdr *) skb_push(skb, sizeof(struct iphdr)); + skb->nh.iph = iph; + saddr = rt->rt_src; + dst_release(skb->dst); + skb->dst = &rt->u.dst; iph->version = 4; iph->ihl = 5; iph->tos = 0; /* tos set to 0... */ if (mtu > 576) - { iph->frag_off = htons(IP_DF); - } else iph->frag_off = 0; @@ -550,20 +516,18 @@ static int sit_xmit(struct sk_buff *skb, struct device *dev) iph->saddr = saddr; iph->daddr = daddr; iph->protocol = IPPROTO_IPV6; - skb->nh.iph = iph; - + iph->tot_len = htons(skb->len); + iph->id = htons(ip_id_count++); ip_send_check(iph); - ip_queue_xmit(skb); + ip_send(skb); stats->tx_packets++; - dev->tbusy=0; return 0; on_error: - kfree_skb(skb, FREE_WRITE); - dev->tbusy=0; + dev_kfree_skb(skb, FREE_WRITE); stats->tx_errors++; return 0; } diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index fb6434b4599d..6429a7cb283d 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -231,17 +231,8 @@ int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, int len, memcpy(&sin6->sin6_addr, &skb->nh.ipv6h->saddr, sizeof(struct in6_addr)); - if (msg->msg_control) - { - int err; - - err = datagram_recv_ctl(sk, msg, skb); - - if (err < 0) - { - copied = err; - } - } + if (msg->msg_controllen) + datagram_recv_ctl(sk, msg, skb); } } @@ -556,7 +547,7 @@ static int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, int ulen) udh.daddr = NULL; - if (msg->msg_control) + if (msg->msg_controllen) { opt = &opt_space; memset(opt, 0, sizeof(struct ipv6_options)); diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c index 0247d0bb2ff6..035920e072c6 100644 --- a/net/ipx/af_ipx.c +++ b/net/ipx/af_ipx.c @@ -760,6 +760,12 @@ static int ipxitf_rcv(ipx_interface *intrfc, struct sk_buff *skb) struct sk_buff *skb2; long *l; char *c; + + if(skb->pkt_type!=PACKET_HOST) + { + kfree_skb(skb, FREE_READ); + return 0; + } #ifdef DEBUG_IPX_PPROP_ROUTING printk(KERN_INFO "IPX: PPROP packet received\n" @@ -812,6 +818,16 @@ static int ipxitf_rcv(ipx_interface *intrfc, struct sk_buff *skb) printk( "IPX: Forward PPROP onto net num %08x\n", (unsigned int) htonl(ifcs->if_netnum) ); #endif skb2 = skb_clone(skb, GFP_ATOMIC); +#ifdef CONFIG_FIREWALL + /* + * See if we are allowed to firewall forward + */ + if (call_fw_firewall(PF_IPX, skb2->dev, ipx, NULL)!=FW_ACCEPT) + { + kfree_skb(skb, FREE_READ); + return 0; + } +#endif ipxrtr_route_skb(skb2); } #ifdef DEBUG_IPX_PPROP_ROUTING @@ -846,8 +862,7 @@ static int ipxitf_rcv(ipx_interface *intrfc, struct sk_buff *skb) } #endif /* We only route point-to-point packets. */ - if ((skb->pkt_type != PACKET_BROADCAST) && - (skb->pkt_type != PACKET_MULTICAST)) + if (skb->pkt_type == PACKET_HOST) { skb=skb_unshare(skb, GFP_ATOMIC, FREE_READ); if(skb) @@ -1699,15 +1714,6 @@ static int ipx_rt_get_info(char *buffer, char **start, off_t offset, * * \*******************************************************************************************************************/ -static int ipx_fcntl(struct socket *sock, unsigned int cmd, unsigned long arg) -{ - switch(cmd) - { - default: - return(-EINVAL); - } -} - static int ipx_setsockopt(struct socket *sock, int level, int optname, char *optval, int optlen) { struct sock *sk; @@ -1777,30 +1783,6 @@ static int ipx_listen(struct socket *sock, int backlog) return -EOPNOTSUPP; } -static void def_callback1(struct sock *sk) -{ - if(!sk->dead) - wake_up_interruptible(sk->sleep); -} - -static void def_callback2(struct sock *sk, int len) -{ - if(!sk->dead) - { - wake_up_interruptible(sk->sleep); - sock_wake_async(sk->socket, 1); - } -} - -static void def_callback3(struct sock *sk, int len) -{ - if(!sk->dead) - { - wake_up_interruptible(sk->sleep); - sock_wake_async(sk->socket, 2); - } -} - static int ipx_create(struct socket *sock, int protocol) { struct sock *sk; @@ -1816,30 +1798,9 @@ static int ipx_create(struct socket *sock, int protocol) sk_free(sk); return(-ESOCKTNOSUPPORT); } - sk->rcvbuf=SK_RMEM_MAX; - sk->sndbuf=SK_WMEM_MAX; - sk->prot=NULL; /* So we use default free mechanisms */ - skb_queue_head_init(&sk->receive_queue); - skb_queue_head_init(&sk->write_queue); - sk->send_head=NULL; - skb_queue_head_init(&sk->back_log); - sk->state=TCP_CLOSE; - sk->socket=sock; - sk->type=sock->type; + sock_init_data(sock,sk); sk->mtu=IPX_MTU; sk->no_check = 1; /* Checksum off by default */ - if(sock!=NULL) - { - sk->sleep=&sock->wait; - sock->sk=sk; - } - - sk->state_change=def_callback1; - sk->data_ready=def_callback2; - sk->write_space=def_callback3; - sk->error_report=def_callback1; - - sk->zapped=1; MOD_INC_USE_COUNT; return 0; } @@ -2384,7 +2345,7 @@ static struct proto_ops ipx_dgram_ops = { ipx_shutdown, ipx_setsockopt, ipx_getsockopt, - ipx_fcntl, + sock_no_fcntl, ipx_sendmsg, ipx_recvmsg }; diff --git a/net/lapb/lapb_iface.c b/net/lapb/lapb_iface.c index 12b48c991c14..1f0e69942d04 100644 --- a/net/lapb/lapb_iface.c +++ b/net/lapb/lapb_iface.c @@ -63,7 +63,7 @@ static void lapb_remove_cb(lapb_cb *lapb) { lapb_cb *s; unsigned long flags; - + save_flags(flags); cli(); @@ -152,7 +152,7 @@ int lapb_register(void *token, struct lapb_register_struct *callbacks) if (lapb_tokentostruct(token) != NULL) return LAPB_BADTOKEN; - + if ((lapb = lapb_create_cb()) == NULL) return LAPB_NOMEM; @@ -160,7 +160,7 @@ int lapb_register(void *token, struct lapb_register_struct *callbacks) lapb->callbacks = *callbacks; lapb_insert_cb(lapb); - + return LAPB_OK; } @@ -176,7 +176,7 @@ int lapb_unregister(void *token) lapb_remove_cb(lapb); lapb_free_cb(lapb); - + return LAPB_OK; } @@ -224,7 +224,7 @@ int lapb_setparms(void *token, struct lapb_parms_struct *parms) if (parms->window < 1 || parms->window > 7) return LAPB_INVALUE; } - + lapb->mode = parms->mode; lapb->window = parms->window; diff --git a/net/lapb/lapb_in.c b/net/lapb/lapb_in.c index 91d61db93df3..2671a26eaa5b 100644 --- a/net/lapb/lapb_in.c +++ b/net/lapb/lapb_in.c @@ -232,7 +232,7 @@ static void lapb_state2_machine(lapb_cb *lapb, struct sk_buff *skb, int frametyp printk(KERN_DEBUG "lapb: (%p) S2 RX DISC(%d)\n", lapb->token, pf); printk(KERN_DEBUG "lapb: (%p) S2 TX UA(%d)\n", lapb->token, pf); #endif - lapb_send_control(lapb, LAPB_UA, pf, C_RESPONSE); + lapb_send_control(lapb, LAPB_UA, pf, LAPB_RESPONSE); break; case LAPB_UA: @@ -386,7 +386,7 @@ static void lapb_state3_machine(lapb_cb *lapb, struct sk_buff *skb, int frametyp lapb->state = LAPB_STATE_1; } break; - + case LAPB_RR: #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S3 RX RR(%d) R%d\n", lapb->token, pf, nr); @@ -403,7 +403,7 @@ static void lapb_state3_machine(lapb_cb *lapb, struct sk_buff *skb, int frametyp lapb->state = LAPB_STATE_1; } break; - + case LAPB_REJ: #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S3 RX REJ(%d) R%d\n", lapb->token, pf, nr); @@ -422,13 +422,11 @@ static void lapb_state3_machine(lapb_cb *lapb, struct sk_buff *skb, int frametyp lapb->state = LAPB_STATE_1; } break; - + case LAPB_I: #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S3 RX I(%d) S%d R%d\n", lapb->token, pf, ns, nr); #endif - if (type != LAPB_COMMAND) - break; if (!lapb_validate_nr(lapb, nr)) { #if LAPB_DEBUG > 0 printk(KERN_DEBUG "lapb: (%p) S3 -> S1\n", lapb->token); @@ -613,7 +611,7 @@ static void lapb_state4_machine(lapb_cb *lapb, struct sk_buff *skb, int frametyp lapb->state = LAPB_STATE_1; } break; - + case LAPB_RR: #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S4 RX RR(%d) R%d\n", lapb->token, pf, nr); @@ -700,8 +698,6 @@ static void lapb_state4_machine(lapb_cb *lapb, struct sk_buff *skb, int frametyp #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S4 RX I(%d) S%d R%d\n", lapb->token, pf, ns, nr); #endif - if (type != LAPB_COMMAND) - break; if (!lapb_validate_nr(lapb, nr)) { #if LAPB_DEBUG > 0 printk(KERN_DEBUG "lapb: (%p) S4 -> S1\n", lapb->token); @@ -737,7 +733,7 @@ static void lapb_state4_machine(lapb_cb *lapb, struct sk_buff *skb, int frametyp } } break; - + case LAPB_FRMR: case LAPB_ILLEGAL: #if LAPB_DEBUG > 1 @@ -765,7 +761,7 @@ int lapb_data_received(void *token, struct sk_buff *skb) { int frametype, ns, nr, pf, type; lapb_cb *lapb; - + if ((lapb = lapb_tokentostruct(token)) == NULL) return LAPB_BADTOKEN; diff --git a/net/lapb/lapb_out.c b/net/lapb/lapb_out.c index 43481e416416..1d0f5e5cfac2 100644 --- a/net/lapb/lapb_out.c +++ b/net/lapb/lapb_out.c @@ -52,27 +52,30 @@ static void lapb_send_iframe(lapb_cb *lapb, struct sk_buff *skb, int poll_bit) if (lapb->mode & LAPB_EXTENDED) { frame = skb_push(skb, 2); - frame[0] = I; + frame[0] = LAPB_I; frame[0] |= (lapb->vs << 1); frame[1] = (poll_bit) ? LAPB_EPF : 0; frame[1] |= (lapb->vr << 1); } else { frame = skb_push(skb, 1); - *frame = I; + *frame = LAPB_I; *frame |= (poll_bit) ? LAPB_SPF : 0; *frame |= (lapb->vr << 5); *frame |= (lapb->vs << 1); } +#if LAPB_DEBUG > 1 + printk(KERN_DEBUG "lapb: (%p) S%d TX I(%d) S%d R%d\n", lapb->token, lapb->state, poll_bit, lapb->vs, lapb->vr); +#endif + lapb_transmit_buffer(lapb, skb, LAPB_COMMAND); } void lapb_kick(lapb_cb *lapb) { struct sk_buff *skb, *skbn; - int modulus, last = 1; - unsigned short start, end, next; + unsigned short modulus, start, end; del_timer(&lapb->timer); @@ -81,7 +84,7 @@ void lapb_kick(lapb_cb *lapb) start = (skb_peek(&lapb->ack_queue) == NULL) ? lapb->va : lapb->vs; end = (lapb->va + lapb->window) % modulus; - if (!(lapb->condition & PEER_RX_BUSY_CONDITION) && + if (!(lapb->condition & LAPB_PEER_RX_BUSY_CONDITION) && start != end && skb_peek(&lapb->write_queue) != NULL) { @@ -98,28 +101,23 @@ void lapb_kick(lapb_cb *lapb) break; } - next = (lapb->vs + 1) % modulus; -#ifdef notdef - last = (next == end) || skb_peek(&lapb->write_queue) == NULL; -#else - last = (next == end); -#endif + if (skb->sk != NULL) + skb_set_owner_w(skbn, skb->sk); + /* * Transmit the frame copy. */ - lapb_send_iframe(lapb, skbn, POLLOFF); + lapb_send_iframe(lapb, skbn, LAPB_POLLOFF); - lapb->vs = next; + lapb->vs = (lapb->vs + 1) % modulus; /* * Requeue the original data frame. */ skb_queue_tail(&lapb->ack_queue, skb); -#ifdef notdef - } while (!last); -#else - } while (!last && (skb = skb_dequeue(&lapb->write_queue)) != NULL); -#endif + + } while (lapb->vs != end && (skb = skb_dequeue(&lapb->write_queue)) != NULL); + lapb->condition &= ~LAPB_ACK_PENDING_CONDITION; if (lapb->t1timer == 0) @@ -183,14 +181,14 @@ void lapb_establish_data_link(lapb_cb *lapb) #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S%d TX SABME(1)\n", lapb->token, lapb->state); #endif - lapb_send_control(lapb, SABME, POLLON, LAPB_COMMAND); + lapb_send_control(lapb, LAPB_SABME, LAPB_POLLON, LAPB_COMMAND); } else { #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S%d TX SABM(1)\n", lapb->token, lapb->state); #endif - lapb_send_control(lapb, SABM, POLLON, LAPB_COMMAND); + lapb_send_control(lapb, LAPB_SABM, LAPB_POLLON, LAPB_COMMAND); } - + lapb->t2timer = 0; lapb->t1timer = lapb->t1; } @@ -201,20 +199,20 @@ void lapb_transmit_enquiry(lapb_cb *lapb) printk(KERN_DEBUG "lapb: (%p) S%d TX RR(1) R%d\n", lapb->token, lapb->state, lapb->vr); #endif - lapb_send_control(lapb, RR, POLLON, C_COMMAND); + lapb_send_control(lapb, LAPB_RR, LAPB_POLLON, LAPB_COMMAND); lapb->condition &= ~LAPB_ACK_PENDING_CONDITION; lapb->t1timer = lapb->t1; } - + void lapb_enquiry_response(lapb_cb *lapb) { #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S%d TX RR(1) R%d\n", lapb->token, lapb->state, lapb->vr); #endif - lapb_send_control(lapb, RR, POLLON, LAPB_RESPONSE); + lapb_send_control(lapb, LAPB_RR, LAPB_POLLON, LAPB_RESPONSE); lapb->condition &= ~LAPB_ACK_PENDING_CONDITION; } @@ -225,7 +223,7 @@ void lapb_timeout_response(lapb_cb *lapb) printk(KERN_DEBUG "lapb: (%p) S%d TX RR(0) R%d\n", lapb->token, lapb->state, lapb->vr); #endif - lapb_send_control(lapb, RR, POLLOFF, LAPB_RESPONSE); + lapb_send_control(lapb, LAPB_RR, LAPB_POLLOFF, LAPB_RESPONSE); lapb->condition &= ~LAPB_ACK_PENDING_CONDITION; } diff --git a/net/lapb/lapb_subr.c b/net/lapb/lapb_subr.c index 56117293ee0b..271978d76b9b 100644 --- a/net/lapb/lapb_subr.c +++ b/net/lapb/lapb_subr.c @@ -131,26 +131,26 @@ int lapb_decode(lapb_cb *lapb, struct sk_buff *skb, int *ns, int *nr, int *pf, i if (lapb->mode & LAPB_MLP) { if (lapb->mode & LAPB_DCE) { - if (skb->data[0] == LAPB_ADDR_C) - *type = LAPB_COMMAND; if (skb->data[0] == LAPB_ADDR_D) + *type = LAPB_COMMAND; + if (skb->data[0] == LAPB_ADDR_C) *type = LAPB_RESPONSE; } else { - if (skb->data[0] == LAPB_ADDR_D) - *type = LAPB_COMMAND; if (skb->data[0] == LAPB_ADDR_C) + *type = LAPB_COMMAND; + if (skb->data[0] == LAPB_ADDR_D) *type = LAPB_RESPONSE; } } else { if (lapb->mode & LAPB_DCE) { - if (skb->data[0] == LAPB_ADDR_A) - *type = LAPB_COMMAND; if (skb->data[0] == LAPB_ADDR_B) + *type = LAPB_COMMAND; + if (skb->data[0] == LAPB_ADDR_A) *type = LAPB_RESPONSE; } else { - if (skb->data[0] == LAPB_ADDR_B) - *type = LAPB_COMMAND; if (skb->data[0] == LAPB_ADDR_A) + *type = LAPB_COMMAND; + if (skb->data[0] == LAPB_ADDR_B) *type = LAPB_RESPONSE; } } @@ -185,7 +185,7 @@ int lapb_decode(lapb_cb *lapb, struct sk_buff *skb, int *ns, int *nr, int *pf, i *nr = (skb->data[0] >> 5) & 0x07; *pf = skb->data[0] & LAPB_SPF; } else if ((skb->data[0] & LAPB_U) == 3) { /* U frame - take out PF */ - frametype = skb->data[0] & ~PF; + frametype = skb->data[0] & ~LAPB_SPF; *pf = skb->data[0] & LAPB_SPF; } @@ -204,7 +204,7 @@ void lapb_send_control(lapb_cb *lapb, int frametype, int poll_bit, int type) { struct sk_buff *skb; unsigned char *dptr; - + if ((skb = alloc_skb(LAPB_HEADER_LEN + 3, GFP_ATOMIC)) == NULL) return; diff --git a/net/lapb/lapb_timer.c b/net/lapb/lapb_timer.c index 6586056c6515..cf59172e51b7 100644 --- a/net/lapb/lapb_timer.c +++ b/net/lapb/lapb_timer.c @@ -63,7 +63,7 @@ void lapb_set_timer(lapb_cb *lapb) static void lapb_reset_timer(lapb_cb *lapb) { unsigned long flags; - + save_flags(flags); cli(); del_timer(&lapb->timer); diff --git a/net/netbeui/netbeui.c b/net/netbeui/netbeui.c index 48be8e54586d..4392aa327314 100644 --- a/net/netbeui/netbeui.c +++ b/net/netbeui/netbeui.c @@ -161,21 +161,6 @@ static int nb_device_event(struct notifier_block *this, unsigned long event, voi * * \*******************************************************************************************************************/ -/* - * Generic fcntl calls are already dealt with. If we don't need funny ones - * this is the all you need. Async I/O is also separate. - */ - -static int netbeui_fcntl(struct socket *sock, unsigned int cmd, unsigned long arg) -{ -/* netbeui_socket *sk=(netbeui_socket *)sock->data;*/ - switch(cmd) - { - default: - return(-EINVAL); - } -} - /* * Set 'magic' options for netbeui. If we don't have any this is fine * as it is. @@ -265,34 +250,6 @@ static int netbeui_listen(struct socket *sock, int backlog) return 0; } -/* - * These are standard. - */ - -static void def_callback1(struct sock *sk) -{ - if(!sk->dead) - wake_up_interruptible(sk->sleep); -} - -static void def_callback2(struct sock *sk, int len) -{ - if(!sk->dead) - { - wake_up_interruptible(sk->sleep); - sock_wake_async(sk->socket,1); - } -} - -static void def_callback3(struct sock *sk, int len) -{ - if(!sk->dead) - { - wake_up_interruptible(sk->sleep); - sock_wake_async(sk->socket,2); - } -} - /* * Create a socket. Initialise the socket, blank the addresses * set the state. @@ -317,30 +274,8 @@ static int netbeui_create(struct socket *sock, int protocol) MOD_INC_USE_COUNT; - sk->allocation=GFP_KERNEL; - sk->rcvbuf=SK_RMEM_MAX; - sk->sndbuf=SK_WMEM_MAX; - sk->pair=NULL; - sk->priority=SOPRI_NORMAL; - skb_queue_head_init(&sk->receive_queue); - skb_queue_head_init(&sk->write_queue); - skb_queue_head_init(&sk->back_log); - sk->state=TCP_CLOSE; - sk->socket=sock; - sk->type=sock->type; + sock_init_data(sock,sk); sk->mtu=1500; - - if(sock!=NULL) - { - sock->data=(void *)sk; - sk->sleep=sock->wait; - } - - sk->state_change=def_callback1; - sk->data_ready=def_callback2; - sk->write_space=def_callback3; - sk->error_report=def_callback1; - sk->zapped=1; return(0); } @@ -881,7 +816,7 @@ static struct proto_ops netbeui_proto_ops = { netbeui_shutdown, netbeui_setsockopt, netbeui_getsockopt, - netbeui_fcntl, + sock_no_fcntl, netbeui_sendmsg, netbeui_recvmsg }; diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index e911abf88ea1..75c9f77a7674 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c @@ -31,7 +31,7 @@ * Alan(GW4PTS) Started POSIXisms * NET/ROM 006 Alan(GW4PTS) Brought in line with the ANK changes */ - + #include #if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE) #include @@ -75,7 +75,8 @@ int sysctl_netrom_transport_busy_delay = NR_DEFAULT_T4; int sysctl_netrom_transport_requested_window_size = NR_DEFAULT_WINDOW; int sysctl_netrom_transport_no_activity_timeout = NR_DEFAULT_IDLE; int sysctl_netrom_transport_packet_length = NR_DEFAULT_PACLEN; -int sysctl_netrom_routing_control = 1; +int sysctl_netrom_routing_control = NR_DEFAULT_ROUTING; +int sysctl_netrom_link_fails_count = NR_DEFAULT_FAILS; static unsigned short circuit = 0x101; @@ -88,7 +89,7 @@ static void nr_free_sock(struct sock *sk) kfree_s(sk->protinfo.nr, sizeof(*sk->protinfo.nr)); sk_free(sk); - + MOD_DEC_USE_COUNT; } @@ -118,11 +119,12 @@ static struct sock *nr_alloc_sock(void) /* * Socket removal during an interrupt is now safe. */ + static void nr_remove_socket(struct sock *sk) { struct sock *s; unsigned long flags; - + save_flags(flags); cli(); @@ -151,7 +153,7 @@ static void nr_remove_socket(struct sock *sk) static void nr_kill_by_device(struct device *dev) { struct sock *s; - + for (s = nr_list; s != NULL; s = s->next) { if (s->protinfo.nr->device == dev) { s->protinfo.nr->state = NR_STATE_0; @@ -174,7 +176,7 @@ static int nr_device_event(struct notifier_block *this, unsigned long event, voi if (event != NETDEV_DOWN) return NOTIFY_DONE; - + nr_kill_by_device(dev); nr_rt_device_down(dev); @@ -269,7 +271,7 @@ static struct sock *nr_find_peer(unsigned char index, unsigned char id) /* * Deferred destroy. */ -void nr_destroy_socket(struct sock * sk); +void nr_destroy_socket(struct sock *); /* * Handler for deferred kills. @@ -289,15 +291,15 @@ void nr_destroy_socket(struct sock *sk) /* Not static as it's used by the timer { struct sk_buff *skb; unsigned long flags; - + save_flags(flags); cli(); - + del_timer(&sk->timer); - + nr_remove_socket(sk); nr_clear_queues(sk); /* Flush the queues */ - + while ((skb = skb_dequeue(&sk->receive_queue)) != NULL) { if (skb->sk != sk) { /* A pending connection */ skb->sk->dead = 1; /* Queue the unaccepted socket for death */ @@ -307,8 +309,8 @@ void nr_destroy_socket(struct sock *sk) /* Not static as it's used by the timer kfree_skb(skb, FREE_READ); } - - if (sk->wmem_alloc || sk->rmem_alloc) { /* Defer: outstanding buffers */ + + if (sk->wmem_alloc || sk->rmem_alloc) { /* Defer: outstanding buffers */ init_timer(&sk->timer); sk->timer.expires = jiffies + 10 * HZ; sk->timer.function = nr_destroy_timer; @@ -325,11 +327,6 @@ void nr_destroy_socket(struct sock *sk) /* Not static as it's used by the timer * Handling for system calls applied via the various interfaces to a * NET/ROM socket object. */ - -static int nr_fcntl(struct socket *sock, unsigned int cmd, unsigned long arg) -{ - return -EINVAL; -} /* * dl1bke 960311: set parameters for existing NET/ROM connections, @@ -342,12 +339,12 @@ static int nr_ctl_ioctl(const unsigned int cmd, void *arg) struct sock *sk; unsigned long flags; int err; - + if ((err = verify_area(VERIFY_READ, arg, sizeof(nr_ctl))) != 0) return err; copy_from_user(&nr_ctl, arg, sizeof(nr_ctl)); - + if ((sk = nr_find_socket(nr_ctl.index, nr_ctl.id)) == NULL) return -ENOTCONN; @@ -368,8 +365,8 @@ static int nr_ctl_ioctl(const unsigned int cmd, void *arg) case NETROM_T1: if (nr_ctl.arg < 1) return -EINVAL; - sk->protinfo.nr->rtt = (nr_ctl.arg * PR_SLOWHZ) / 2; - sk->protinfo.nr->t1 = nr_ctl.arg * PR_SLOWHZ; + sk->protinfo.nr->rtt = (nr_ctl.arg * NR_SLOWHZ) / 2; + sk->protinfo.nr->t1 = nr_ctl.arg * NR_SLOWHZ; save_flags(flags); cli(); if (sk->protinfo.nr->t1timer > sk->protinfo.nr->t1) sk->protinfo.nr->t1timer = sk->protinfo.nr->t1; @@ -380,7 +377,7 @@ static int nr_ctl_ioctl(const unsigned int cmd, void *arg) if (nr_ctl.arg < 1) return -EINVAL; save_flags(flags); cli(); - sk->protinfo.nr->t2 = nr_ctl.arg * PR_SLOWHZ; + sk->protinfo.nr->t2 = nr_ctl.arg * NR_SLOWHZ; if (sk->protinfo.nr->t2timer > sk->protinfo.nr->t2) sk->protinfo.nr->t2timer = sk->protinfo.nr->t2; restore_flags(flags); @@ -397,7 +394,7 @@ static int nr_ctl_ioctl(const unsigned int cmd, void *arg) if (nr_ctl.arg < 1) return -EINVAL; save_flags(flags); cli(); - sk->protinfo.nr->t4 = nr_ctl.arg * PR_SLOWHZ; + sk->protinfo.nr->t4 = nr_ctl.arg * NR_SLOWHZ; if (sk->protinfo.nr->t4timer > sk->protinfo.nr->t4) sk->protinfo.nr->t4timer = sk->protinfo.nr->t4; restore_flags(flags); @@ -407,7 +404,7 @@ static int nr_ctl_ioctl(const unsigned int cmd, void *arg) if (nr_ctl.arg < 1) return -EINVAL; save_flags(flags); cli(); - sk->protinfo.nr->idle = nr_ctl.arg * 60 * PR_SLOWHZ; + sk->protinfo.nr->idle = nr_ctl.arg * 60 * NR_SLOWHZ; if (sk->protinfo.nr->idletimer > sk->protinfo.nr->idle) sk->protinfo.nr->idletimer = sk->protinfo.nr->idle; restore_flags(flags); @@ -431,11 +428,9 @@ static int nr_ctl_ioctl(const unsigned int cmd, void *arg) static int nr_setsockopt(struct socket *sock, int level, int optname, char *optval, int optlen) { - struct sock *sk; + struct sock *sk = sock->sk; int err, opt; - sk = sock->sk; - if (level != SOL_NETROM) return -EOPNOTSUPP; @@ -446,38 +441,38 @@ static int nr_setsockopt(struct socket *sock, int level, int optname, return err; get_user(opt, (int *)optval); - + switch (optname) { case NETROM_T1: if (opt < 1) return -EINVAL; - sk->protinfo.nr->rtt = (opt * PR_SLOWHZ) / 2; + sk->protinfo.nr->rtt = (opt * NR_SLOWHZ) / 2; return 0; case NETROM_T2: if (opt < 1) return -EINVAL; - sk->protinfo.nr->t2 = opt * PR_SLOWHZ; + sk->protinfo.nr->t2 = opt * NR_SLOWHZ; return 0; - + case NETROM_N2: if (opt < 1 || opt > 31) return -EINVAL; sk->protinfo.nr->n2 = opt; return 0; - + case NETROM_T4: if (opt < 1) return -EINVAL; - sk->protinfo.nr->t4 = opt * PR_SLOWHZ; + sk->protinfo.nr->t4 = opt * NR_SLOWHZ; return 0; - + case NETROM_IDLE: if (opt < 1) return -EINVAL; - sk->protinfo.nr->idle = opt * 60 * PR_SLOWHZ; + sk->protinfo.nr->idle = opt * 60 * NR_SLOWHZ; return 0; - + case NETROM_HDRINCL: sk->protinfo.nr->hdrincl = opt ? 1 : 0; return 0; @@ -487,7 +482,7 @@ static int nr_setsockopt(struct socket *sock, int level, int optname, return -EINVAL; sk->protinfo.nr->paclen = opt; return 0; - + default: return -ENOPROTOOPT; } @@ -496,36 +491,34 @@ static int nr_setsockopt(struct socket *sock, int level, int optname, static int nr_getsockopt(struct socket *sock, int level, int optname, char *optval, int *optlen) { - struct sock *sk; + struct sock *sk = sock->sk; int val = 0; int err; - sk = sock->sk; - if (level != SOL_NETROM) return -EOPNOTSUPP; - + switch (optname) { case NETROM_T1: - val = (sk->protinfo.nr->t1 * 2) / PR_SLOWHZ; + val = (sk->protinfo.nr->t1 * 2) / NR_SLOWHZ; break; - + case NETROM_T2: - val = sk->protinfo.nr->t2 / PR_SLOWHZ; + val = sk->protinfo.nr->t2 / NR_SLOWHZ; break; - + case NETROM_N2: val = sk->protinfo.nr->n2; break; - + case NETROM_T4: - val = sk->protinfo.nr->t4 / PR_SLOWHZ; + val = sk->protinfo.nr->t4 / NR_SLOWHZ; break; - + case NETROM_IDLE: - val = sk->protinfo.nr->idle / (PR_SLOWHZ * 60); + val = sk->protinfo.nr->idle / (NR_SLOWHZ * 60); break; - + case NETROM_HDRINCL: val = sk->protinfo.nr->hdrincl; break; @@ -565,30 +558,6 @@ static int nr_listen(struct socket *sock, int backlog) return -EOPNOTSUPP; } -static void def_callback1(struct sock *sk) -{ - if (!sk->dead) - wake_up_interruptible(sk->sleep); -} - -static void def_callback2(struct sock *sk, int len) -{ - if (!sk->dead) - { - sock_wake_async(sk->socket,1); - wake_up_interruptible(sk->sleep); - } -} - -static void def_callback3(struct sock *sk, int len) -{ - if (!sk->dead) - { - sock_wake_async(sk->socket,2); - wake_up_interruptible(sk->sleep); - } -} - static int nr_create(struct socket *sock, int protocol) { struct sock *sk; @@ -602,34 +571,14 @@ static int nr_create(struct socket *sock, int protocol) nr = sk->protinfo.nr; - skb_queue_head_init(&sk->receive_queue); - skb_queue_head_init(&sk->write_queue); - skb_queue_head_init(&sk->back_log); + sock_init_data(sock,sk); init_timer(&sk->timer); - + sock->ops = &nr_proto_ops; - sk->socket = sock; - sk->type = sock->type; sk->protocol = protocol; - sk->allocation = GFP_KERNEL; - sk->rcvbuf = SK_RMEM_MAX; - sk->sndbuf = SK_WMEM_MAX; - sk->state = TCP_CLOSE; - sk->priority = SOPRI_NORMAL; sk->mtu = NETROM_MTU; /* 236 */ - sk->zapped = 1; - - sk->state_change = def_callback1; - sk->data_ready = def_callback2; - sk->write_space = def_callback3; - sk->error_report = def_callback1; - - if (sock != NULL) { - sock->sk = sk; - sk->sleep = &sock->wait; - } skb_queue_head_init(&nr->ack_queue); skb_queue_head_init(&nr->reseq_queue); @@ -663,9 +612,7 @@ static struct sock *nr_make_new(struct sock *osk) nr = sk->protinfo.nr; - skb_queue_head_init(&sk->receive_queue); - skb_queue_head_init(&sk->write_queue); - skb_queue_head_init(&sk->back_log); + sock_init_data(NULL,sk); init_timer(&sk->timer); @@ -681,11 +628,6 @@ static struct sock *nr_make_new(struct sock *osk) sk->sleep = osk->sleep; sk->zapped = osk->zapped; - sk->state_change = def_callback1; - sk->data_ready = def_callback2; - sk->write_space = def_callback3; - sk->error_report = def_callback1; - skb_queue_head_init(&nr->ack_queue); skb_queue_head_init(&nr->reseq_queue); skb_queue_head_init(&nr->frag_queue); @@ -710,6 +652,9 @@ static int nr_dup(struct socket *newsock, struct socket *oldsock) { struct sock *sk = oldsock->sk; + if (sk == NULL || newsock == NULL) + return -EINVAL; + return nr_create(newsock, sk->protocol); } @@ -775,19 +720,20 @@ static int nr_release(struct socket *sock, struct socket *peer) static int nr_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) { - struct sock *sk; + struct sock *sk = sock->sk; struct full_sockaddr_ax25 *addr = (struct full_sockaddr_ax25 *)uaddr; struct device *dev; ax25_address *user, *source; - - sk = sock->sk; if (sk->zapped == 0) return -EINVAL; - + if (addr_len != sizeof(struct sockaddr_ax25) && addr_len != sizeof(struct full_sockaddr_ax25)) return -EINVAL; + if (addr->fsa_ax25.sax25_family != AF_NETROM) + return -EINVAL; + if ((dev = nr_dev_get(&addr->fsa_ax25.sax25_call)) == NULL) { if (sk->debug) printk("NET/ROM: bind failed: invalid node callsign\n"); @@ -833,26 +779,29 @@ static int nr_connect(struct socket *sock, struct sockaddr *uaddr, struct sockaddr_ax25 *addr = (struct sockaddr_ax25 *)uaddr; ax25_address *user, *source = NULL; struct device *dev; - + if (sk->state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) { sock->state = SS_CONNECTED; return 0; /* Connect completed during a ERESTARTSYS event */ } - + if (sk->state == TCP_CLOSE && sock->state == SS_CONNECTING) { sock->state = SS_UNCONNECTED; return -ECONNREFUSED; } - + if (sk->state == TCP_ESTABLISHED) return -EISCONN; /* No reconnect on a seqpacket socket */ - + sk->state = TCP_CLOSE; sock->state = SS_UNCONNECTED; if (addr_len != sizeof(struct sockaddr_ax25) && addr_len != sizeof(struct full_sockaddr_ax25)) return -EINVAL; + if (addr->sax25_family != AF_NETROM) + return -EINVAL; + if (sk->zapped) { /* Must bind first - autobinding in this may or may not work */ sk->zapped = 0; @@ -883,14 +832,14 @@ static int nr_connect(struct socket *sock, struct sockaddr *uaddr, sk->protinfo.nr->my_id = circuit % 256; circuit++; - + /* Move to connecting socket, start sending Connect Requests */ sock->state = SS_CONNECTING; sk->state = TCP_SYN_SENT; nr_establish_data_link(sk); sk->protinfo.nr->state = NR_STATE_1; nr_set_timer(sk); - + /* Now the loop */ if (sk->state != TCP_ESTABLISHED && (flags & O_NONBLOCK)) return -EINPROGRESS; @@ -913,14 +862,14 @@ static int nr_connect(struct socket *sock, struct sockaddr *uaddr, sock->state = SS_UNCONNECTED; return sock_error(sk); /* Always set at this point */ } - + sock->state = SS_CONNECTED; sti(); - + return 0; } - + static int nr_socketpair(struct socket *sock1, struct socket *sock2) { return -EOPNOTSUPP; @@ -932,19 +881,20 @@ static int nr_accept(struct socket *sock, struct socket *newsock, int flags) struct sock *newsk; struct sk_buff *skb; - if (newsock->sk) - sk_free(newsock->sk); + if (newsock->sk != NULL) + nr_destroy_socket(newsock->sk); newsock->sk = NULL; - - sk = sock->sk; + + if ((sk = sock->sk) == NULL) + return -EINVAL; if (sk->type != SOCK_SEQPACKET) return -EOPNOTSUPP; - + if (sk->state != TCP_LISTEN) return -EINVAL; - + /* * The write queue this time is holding sockets ready to use * hooked into the SABM we saved @@ -954,7 +904,7 @@ static int nr_accept(struct socket *sock, struct socket *newsock, int flags) if ((skb = skb_dequeue(&sk->receive_queue)) == NULL) { if (flags & O_NONBLOCK) { sti(); - return 0; + return -EWOULDBLOCK; } interruptible_sleep_on(sk->sleep); if (current->signal & ~current->blocked) { @@ -981,10 +931,8 @@ static int nr_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_len, int peer) { struct full_sockaddr_ax25 *sax = (struct full_sockaddr_ax25 *)uaddr; - struct sock *sk; - - sk = sock->sk; - + struct sock *sk = sock->sk; + if (peer != 0) { if (sk->state != TCP_ESTABLISHED) return -ENOTCONN; @@ -1002,7 +950,7 @@ static int nr_getname(struct socket *sock, struct sockaddr *uaddr, return 0; } - + int nr_rx_frame(struct sk_buff *skb, struct device *dev) { struct sock *sk; @@ -1054,7 +1002,7 @@ int nr_rx_frame(struct sk_buff *skb, struct device *dev) if ((frametype & 0x0F) != NR_CONNREQ) return 0; - + sk = nr_find_listener(dest); user = (ax25_address *)(skb->data + 21); @@ -1079,7 +1027,7 @@ int nr_rx_frame(struct sk_buff *skb, struct device *dev) make->protinfo.nr->my_index = circuit / 256; make->protinfo.nr->my_id = circuit % 256; - + circuit++; /* Window negotiation */ @@ -1089,8 +1037,8 @@ int nr_rx_frame(struct sk_buff *skb, struct device *dev) /* L4 timeout negotiation */ if (skb->len == 37) { timeout = skb->data[36] * 256 + skb->data[35]; - if (timeout * PR_SLOWHZ < make->protinfo.nr->rtt * 2) - make->protinfo.nr->rtt = (timeout * PR_SLOWHZ) / 2; + if (timeout * NR_SLOWHZ < make->protinfo.nr->rtt * 2) + make->protinfo.nr->rtt = (timeout * NR_SLOWHZ) / 2; make->protinfo.nr->bpqext = 1; } else { make->protinfo.nr->bpqext = 0; @@ -1128,7 +1076,7 @@ static int nr_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct s struct sk_buff *skb; unsigned char *asmptr; int size; - + if (msg->msg_flags & ~MSG_DONTWAIT) return -EINVAL; @@ -1142,7 +1090,7 @@ static int nr_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct s if (sk->protinfo.nr->device == NULL) return -ENETUNREACH; - + if (usax) { if (msg->msg_namelen < sizeof(sax)) return -EINVAL; @@ -1157,7 +1105,7 @@ static int nr_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct s sax.sax25_family = AF_NETROM; sax.sax25_call = sk->protinfo.nr->dest_addr; } - + if (sk->debug) printk("NET/ROM: sendto: Addresses built.\n"); @@ -1170,11 +1118,10 @@ static int nr_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct s if ((skb = sock_alloc_send_skb(sk, size, 0, msg->msg_flags & MSG_DONTWAIT, &err)) == NULL) return err; - skb->sk = sk; - skb->arp = 1; + skb->arp = 1; skb_reserve(skb, size - len); - + /* * Push down the NET/ROM header */ @@ -1191,7 +1138,7 @@ static int nr_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct s *asmptr++ = 0; /* To be filled in later */ *asmptr++ = 0; /* Ditto */ *asmptr++ = NR_INFO; - + if (sk->debug) printk("Built header.\n"); @@ -1202,7 +1149,7 @@ static int nr_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct s skb->h.raw = skb_put(skb, len); asmptr = skb->h.raw; - + if (sk->debug) printk("NET/ROM: Appending user data\n"); @@ -1257,17 +1204,13 @@ static int nr_recvmsg(struct socket *sock, struct msghdr *msg, int size, } skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); - - if (sax != NULL) { - struct sockaddr_ax25 addr; - - addr.sax25_family = AF_NETROM; - memcpy(&addr.sax25_call, skb->data + 7, AX25_ADDR_LEN); - *sax = addr; + if (sax != NULL) { + sax->sax25_family = AF_NETROM; + memcpy(sax->sax25_call.ax25_call, skb->data + 7, AX25_ADDR_LEN); } - msg->msg_namelen=sizeof(*sax); + msg->msg_namelen = sizeof(*sax); skb_free_datagram(sk, skb); @@ -1355,7 +1298,7 @@ static int nr_get_info(char *buffer, char **start, off_t offset, int length, int int len = 0; off_t pos = 0; off_t begin = 0; - + cli(); len += sprintf(buffer, "user_addr dest_node src_node dev my your st vs vr va t1 t2 n2 rtt wnd paclen Snd-Q Rcv-Q\n"); @@ -1365,7 +1308,7 @@ static int nr_get_info(char *buffer, char **start, off_t offset, int length, int devname = "???"; else devname = dev->name; - + len += sprintf(buffer + len, "%-9s ", ax2asc(&s->protinfo.nr->user_addr)); len += sprintf(buffer + len, "%-9s ", @@ -1376,22 +1319,22 @@ static int nr_get_info(char *buffer, char **start, off_t offset, int length, int s->protinfo.nr->your_index, s->protinfo.nr->your_id, s->protinfo.nr->state, s->protinfo.nr->vs, s->protinfo.nr->vr, s->protinfo.nr->va, - s->protinfo.nr->t1timer / PR_SLOWHZ, - s->protinfo.nr->t1 / PR_SLOWHZ, - s->protinfo.nr->t2timer / PR_SLOWHZ, - s->protinfo.nr->t2 / PR_SLOWHZ, + s->protinfo.nr->t1timer / NR_SLOWHZ, + s->protinfo.nr->t1 / NR_SLOWHZ, + s->protinfo.nr->t2timer / NR_SLOWHZ, + s->protinfo.nr->t2 / NR_SLOWHZ, s->protinfo.nr->n2count, s->protinfo.nr->n2, - s->protinfo.nr->rtt / PR_SLOWHZ, + s->protinfo.nr->rtt / NR_SLOWHZ, s->protinfo.nr->window, s->protinfo.nr->paclen, s->wmem_alloc, s->rmem_alloc); - + pos = begin + len; if (pos < offset) { len = 0; begin = pos; } - + if (pos > offset + length) break; } @@ -1414,7 +1357,7 @@ static struct net_proto_family nr_family_ops = static struct proto_ops nr_proto_ops = { AF_NETROM, - + nr_dup, nr_release, nr_bind, @@ -1428,7 +1371,7 @@ static struct proto_ops nr_proto_ops = { nr_shutdown, nr_setsockopt, nr_getsockopt, - nr_fcntl, + sock_no_fcntl, nr_sendmsg, nr_recvmsg }; diff --git a/net/netrom/nr_dev.c b/net/netrom/nr_dev.c index 997011304c94..4982ccb340c3 100644 --- a/net/netrom/nr_dev.c +++ b/net/netrom/nr_dev.c @@ -86,16 +86,16 @@ static int nr_header(struct sk_buff *skb, struct device *dev, unsigned short typ unsigned char *buff = skb_push(skb, NR_NETWORK_LEN + NR_TRANSPORT_LEN); memcpy(buff, (saddr != NULL) ? saddr : dev->dev_addr, dev->addr_len); - buff[6] &= ~LAPB_C; - buff[6] &= ~LAPB_E; - buff[6] |= SSSID_SPARE; + buff[6] &= ~AX25_CBIT; + buff[6] &= ~AX25_EBIT; + buff[6] |= AX25_SSSID_SPARE; buff += AX25_ADDR_LEN; if (daddr != NULL) memcpy(buff, daddr, dev->addr_len); - buff[6] &= ~LAPB_C; - buff[6] |= LAPB_E; - buff[6] |= SSSID_SPARE; + buff[6] &= ~AX25_CBIT; + buff[6] |= AX25_EBIT; + buff[6] |= AX25_SSSID_SPARE; buff += AX25_ADDR_LEN; *buff++ = sysctl_netrom_network_ttl_initialiser; @@ -124,21 +124,21 @@ static int nr_rebuild_header(struct sk_buff *skb) return 1; } - bp[6] &= ~LAPB_C; - bp[6] &= ~LAPB_E; - bp[6] |= SSSID_SPARE; + bp[6] &= ~AX25_CBIT; + bp[6] &= ~AX25_EBIT; + bp[6] |= AX25_SSSID_SPARE; bp += AX25_ADDR_LEN; - bp[6] &= ~LAPB_C; - bp[6] |= LAPB_E; - bp[6] |= SSSID_SPARE; + bp[6] &= ~AX25_CBIT; + bp[6] |= AX25_EBIT; + bp[6] |= AX25_SSSID_SPARE; if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) { kfree_skb(skb, FREE_WRITE); return 1; } - if (skbn->sk != NULL) + if (skb->sk != NULL) skb_set_owner_w(skbn, skb->sk); kfree_skb(skb, FREE_WRITE); diff --git a/net/netrom/nr_in.c b/net/netrom/nr_in.c index d2e9d53f0b1f..7e4d3ac81519 100644 --- a/net/netrom/nr_in.c +++ b/net/netrom/nr_in.c @@ -59,7 +59,7 @@ static int nr_queue_rx_frame(struct sock *sk, struct sk_buff *skb, int more) skb_queue_tail(&sk->protinfo.nr->frag_queue, skb); return 0; } - + if (!more && sk->protinfo.nr->fraglen > 0) { /* End of fragment */ sk->protinfo.nr->fraglen += skb->len; skb_queue_tail(&sk->protinfo.nr->frag_queue, skb); @@ -213,10 +213,10 @@ static int nr_state3_machine(struct sock *sk, struct sk_buff *skb, int frametype case NR_INFOACK | NR_NAK_FLAG: case NR_INFOACK | NR_NAK_FLAG | NR_CHOKE_FLAG: if (frametype & NR_CHOKE_FLAG) { - sk->protinfo.nr->condition |= PEER_RX_BUSY_CONDITION; + sk->protinfo.nr->condition |= NR_COND_PEER_RX_BUSY; sk->protinfo.nr->t4timer = sk->protinfo.nr->t4; } else { - sk->protinfo.nr->condition &= ~PEER_RX_BUSY_CONDITION; + sk->protinfo.nr->condition &= ~NR_COND_PEER_RX_BUSY; sk->protinfo.nr->t4timer = 0; } if (!nr_validate_nr(sk, nr)) { @@ -226,14 +226,14 @@ static int nr_state3_machine(struct sock *sk, struct sk_buff *skb, int frametype nr_frames_acked(sk, nr); nr_send_nak_frame(sk); } else { - if (sk->protinfo.nr->condition & PEER_RX_BUSY_CONDITION) { + if (sk->protinfo.nr->condition & NR_COND_PEER_RX_BUSY) { nr_frames_acked(sk, nr); } else { nr_check_iframes_acked(sk, nr); } } break; - + case NR_INFO: case NR_INFO | NR_NAK_FLAG: case NR_INFO | NR_CHOKE_FLAG: @@ -243,10 +243,10 @@ static int nr_state3_machine(struct sock *sk, struct sk_buff *skb, int frametype case NR_INFO | NR_NAK_FLAG | NR_MORE_FLAG: case NR_INFO | NR_NAK_FLAG | NR_CHOKE_FLAG | NR_MORE_FLAG: if (frametype & NR_CHOKE_FLAG) { - sk->protinfo.nr->condition |= PEER_RX_BUSY_CONDITION; + sk->protinfo.nr->condition |= NR_COND_PEER_RX_BUSY; sk->protinfo.nr->t4timer = sk->protinfo.nr->t4; } else { - sk->protinfo.nr->condition &= ~PEER_RX_BUSY_CONDITION; + sk->protinfo.nr->condition &= ~NR_COND_PEER_RX_BUSY; sk->protinfo.nr->t4timer = 0; } if (nr_validate_nr(sk, nr)) { @@ -254,7 +254,7 @@ static int nr_state3_machine(struct sock *sk, struct sk_buff *skb, int frametype nr_frames_acked(sk, nr); nr_send_nak_frame(sk); } else { - if (sk->protinfo.nr->condition & PEER_RX_BUSY_CONDITION) { + if (sk->protinfo.nr->condition & NR_COND_PEER_RX_BUSY) { nr_frames_acked(sk, nr); } else { nr_check_iframes_acked(sk, nr); @@ -263,7 +263,7 @@ static int nr_state3_machine(struct sock *sk, struct sk_buff *skb, int frametype } queued = 1; skb_queue_head(&sk->protinfo.nr->reseq_queue, skb); - if (sk->protinfo.nr->condition & OWN_RX_BUSY_CONDITION) + if (sk->protinfo.nr->condition & NR_COND_OWN_RX_BUSY) break; skb_queue_head_init(&temp_queue); do { @@ -274,7 +274,7 @@ static int nr_state3_machine(struct sock *sk, struct sk_buff *skb, int frametype if (nr_queue_rx_frame(sk, skbn, frametype & NR_MORE_FLAG) == 0) { sk->protinfo.nr->vr = (sk->protinfo.nr->vr + 1) % NR_MODULUS; } else { - sk->protinfo.nr->condition |= OWN_RX_BUSY_CONDITION; + sk->protinfo.nr->condition |= NR_COND_OWN_RX_BUSY; skb_queue_tail(&temp_queue, skbn); } } else if (nr_in_rx_window(sk, ns)) { @@ -293,9 +293,9 @@ static int nr_state3_machine(struct sock *sk, struct sk_buff *skb, int frametype if (((sk->protinfo.nr->vl + sk->protinfo.nr->window) % NR_MODULUS) == sk->protinfo.nr->vr) { nr_enquiry_response(sk); } else { - if (!(sk->protinfo.nr->condition & ACK_PENDING_CONDITION)) { + if (!(sk->protinfo.nr->condition & NR_COND_ACK_PENDING)) { sk->protinfo.nr->t2timer = sk->protinfo.nr->t2; - sk->protinfo.nr->condition |= ACK_PENDING_CONDITION; + sk->protinfo.nr->condition |= NR_COND_ACK_PENDING; } } break; diff --git a/net/netrom/nr_out.c b/net/netrom/nr_out.c index 777cf91398c8..af3e0e5c2013 100644 --- a/net/netrom/nr_out.c +++ b/net/netrom/nr_out.c @@ -53,7 +53,7 @@ void nr_output(struct sock *sk, struct sk_buff *skb) int err, frontlen, len, mtu; mtu = sk->protinfo.nr->paclen; - + if (skb->len - NR_TRANSPORT_LEN > mtu) { /* Save a copy of the Transport Header */ memcpy(transport, skb->data, NR_TRANSPORT_LEN); @@ -82,10 +82,10 @@ void nr_output(struct sock *sk, struct sk_buff *skb) if (skb->len > 0) skbn->data[4] |= NR_MORE_FLAG; - + skb_queue_tail(&sk->write_queue, skbn); /* Throw it on the queue */ } - + kfree_skb(skb, FREE_WRITE); } else { skb_queue_tail(&sk->write_queue, skb); /* Throw it on the queue */ @@ -107,7 +107,7 @@ static void nr_send_iframe(struct sock *sk, struct sk_buff *skb) skb->data[2] = sk->protinfo.nr->vs; skb->data[3] = sk->protinfo.nr->vr; - if (sk->protinfo.nr->condition & OWN_RX_BUSY_CONDITION) + if (sk->protinfo.nr->condition & NR_COND_OWN_RX_BUSY) skb->data[4] |= NR_CHOKE_FLAG; nr_transmit_buffer(sk, skb); @@ -116,22 +116,22 @@ static void nr_send_iframe(struct sock *sk, struct sk_buff *skb) void nr_send_nak_frame(struct sock *sk) { struct sk_buff *skb, *skbn; - + if ((skb = skb_peek(&sk->protinfo.nr->ack_queue)) == NULL) return; - + if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) return; skbn->data[2] = sk->protinfo.nr->va; skbn->data[3] = sk->protinfo.nr->vr; - if (sk->protinfo.nr->condition & OWN_RX_BUSY_CONDITION) + if (sk->protinfo.nr->condition & NR_COND_OWN_RX_BUSY) skbn->data[4] |= NR_CHOKE_FLAG; nr_transmit_buffer(sk, skbn); - sk->protinfo.nr->condition &= ~ACK_PENDING_CONDITION; + sk->protinfo.nr->condition &= ~NR_COND_ACK_PENDING; sk->protinfo.nr->vl = sk->protinfo.nr->vr; sk->protinfo.nr->t1timer = 0; } @@ -139,16 +139,15 @@ void nr_send_nak_frame(struct sock *sk) void nr_kick(struct sock *sk) { struct sk_buff *skb, *skbn; - int last = 1; - unsigned short start, end, next; + unsigned short start, end; del_timer(&sk->timer); start = (skb_peek(&sk->protinfo.nr->ack_queue) == NULL) ? sk->protinfo.nr->va : sk->protinfo.nr->vs; end = (sk->protinfo.nr->va + sk->protinfo.nr->window) % NR_MODULUS; - if (!(sk->protinfo.nr->condition & PEER_RX_BUSY_CONDITION) && - start != end && + if (!(sk->protinfo.nr->condition & NR_COND_PEER_RX_BUSY) && + start != end && skb_peek(&sk->write_queue) != NULL) { sk->protinfo.nr->vs = start; @@ -169,25 +168,24 @@ void nr_kick(struct sock *sk) break; } - next = (sk->protinfo.nr->vs + 1) % NR_MODULUS; - last = (next == end); + skb_set_owner_w(skbn, sk); /* * Transmit the frame copy. */ nr_send_iframe(sk, skbn); - sk->protinfo.nr->vs = next; + sk->protinfo.nr->vs = (sk->protinfo.nr->vs + 1) % NR_MODULUS; /* * Requeue the original data frame. */ skb_queue_tail(&sk->protinfo.nr->ack_queue, skb); - } while (!last && (skb = skb_dequeue(&sk->write_queue)) != NULL); + } while (sk->protinfo.nr->vs != end && (skb = skb_dequeue(&sk->write_queue)) != NULL); sk->protinfo.nr->vl = sk->protinfo.nr->vr; - sk->protinfo.nr->condition &= ~ACK_PENDING_CONDITION; + sk->protinfo.nr->condition &= ~NR_COND_ACK_PENDING; if (sk->protinfo.nr->t1timer == 0) { sk->protinfo.nr->t1timer = sk->protinfo.nr->t1 = nr_calculate_t1(sk); @@ -207,15 +205,15 @@ void nr_transmit_buffer(struct sock *sk, struct sk_buff *skb) dptr = skb_push(skb, NR_NETWORK_LEN); memcpy(dptr, &sk->protinfo.nr->source_addr, AX25_ADDR_LEN); - dptr[6] &= ~LAPB_C; - dptr[6] &= ~LAPB_E; - dptr[6] |= SSSID_SPARE; + dptr[6] &= ~AX25_CBIT; + dptr[6] &= ~AX25_EBIT; + dptr[6] |= AX25_SSSID_SPARE; dptr += AX25_ADDR_LEN; memcpy(dptr, &sk->protinfo.nr->dest_addr, AX25_ADDR_LEN); - dptr[6] &= ~LAPB_C; - dptr[6] |= LAPB_E; - dptr[6] |= SSSID_SPARE; + dptr[6] &= ~AX25_CBIT; + dptr[6] |= AX25_EBIT; + dptr[6] |= AX25_SSSID_SPARE; dptr += AX25_ADDR_LEN; *dptr++ = sysctl_netrom_network_ttl_initialiser; @@ -256,19 +254,19 @@ void nr_establish_data_link(struct sock *sk) void nr_enquiry_response(struct sock *sk) { int frametype = NR_INFOACK; - - if (sk->protinfo.nr->condition & OWN_RX_BUSY_CONDITION) { + + if (sk->protinfo.nr->condition & NR_COND_OWN_RX_BUSY) { frametype |= NR_CHOKE_FLAG; } else { if (skb_peek(&sk->protinfo.nr->reseq_queue) != NULL) { frametype |= NR_NAK_FLAG; } } - + nr_write_internal(sk, frametype); sk->protinfo.nr->vl = sk->protinfo.nr->vr; - sk->protinfo.nr->condition &= ~ACK_PENDING_CONDITION; + sk->protinfo.nr->condition &= ~NR_COND_ACK_PENDING; } void nr_check_iframes_acked(struct sock *sk, unsigned short nr) diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c index afd3fd0beb43..70395ed40fc1 100644 --- a/net/netrom/nr_route.c +++ b/net/netrom/nr_route.c @@ -21,8 +21,9 @@ * as node callsign. * Alan Cox(GW4PTS) Added the firewall hooks. * NET/ROM 006 Jonathan(G4KLX) Added the setting of digipeated neighbours. + * Tomi(OH2BNS) Routing quality and link failure changes. */ - + #include #if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE) #include @@ -83,6 +84,9 @@ static int nr_add_node(ax25_address *nr, const char *mnemonic, ax25_address *ax2 if (ax25cmp(ax25, &nr_neigh->callsign) == 0 && nr_neigh->dev == dev) break; + if (nr_neigh != NULL) + nr_neigh->failed = 0; + if (quality == 0 && nr_neigh != NULL && nr_node != NULL) return 0; @@ -93,10 +97,7 @@ static int nr_add_node(ax25_address *nr, const char *mnemonic, ax25_address *ax2 nr_neigh->callsign = *ax25; nr_neigh->digipeat = NULL; nr_neigh->dev = dev; - if (ax25cmp(nr, ax25) == 0) - nr_neigh->quality = quality; - else - nr_neigh->quality = sysctl_netrom_default_path_quality; + nr_neigh->quality = sysctl_netrom_default_path_quality; nr_neigh->locked = 0; nr_neigh->count = 0; nr_neigh->number = nr_neigh_no++; @@ -118,6 +119,9 @@ static int nr_add_node(ax25_address *nr, const char *mnemonic, ax25_address *ax2 restore_flags(flags); } + if (quality != 0 && ax25cmp(nr, ax25) == 0) + nr_neigh->quality = quality; + if (nr_node == NULL) { if ((nr_node = (struct nr_node *)kmalloc(sizeof(*nr_node), GFP_ATOMIC)) == NULL) return -ENOMEM; @@ -131,7 +135,7 @@ static int nr_add_node(ax25_address *nr, const char *mnemonic, ax25_address *ax2 nr_node->routes[0].quality = quality; nr_node->routes[0].obs_count = obs_count; nr_node->routes[0].neighbour = nr_neigh; - + save_flags(flags); cli(); @@ -139,15 +143,15 @@ static int nr_add_node(ax25_address *nr, const char *mnemonic, ax25_address *ax2 nr_node_list = nr_node; restore_flags(flags); - + nr_neigh->count++; return 0; - } else { - if (nr_node->mnemonic[0] == '\0') - strcpy(nr_node->mnemonic, mnemonic); } + if (quality != 0) + strcpy(nr_node->mnemonic, mnemonic); + for (found = 0, i = 0; i < nr_node->count; i++) { if (nr_node->routes[i].neighbour == nr_neigh) { nr_node->routes[i].quality = quality; @@ -166,7 +170,7 @@ static int nr_add_node(ax25_address *nr, const char *mnemonic, ax25_address *ax2 nr_node->routes[0].quality = quality; nr_node->routes[0].obs_count = obs_count; nr_node->routes[0].neighbour = nr_neigh; - + nr_node->which++; nr_node->count++; nr_neigh->count++; @@ -174,10 +178,10 @@ static int nr_add_node(ax25_address *nr, const char *mnemonic, ax25_address *ax2 /* It must be better than the worst */ if (quality > nr_node->routes[2].quality) { nr_node->routes[2].neighbour->count--; - + if (nr_node->routes[2].neighbour->count == 0 && !nr_node->routes[2].neighbour->locked) nr_remove_neigh(nr_node->routes[2].neighbour); - + nr_node->routes[2].quality = quality; nr_node->routes[2].obs_count = obs_count; nr_node->routes[2].neighbour = nr_neigh; @@ -240,7 +244,7 @@ static void nr_remove_node(struct nr_node *nr_node) { struct nr_node *s; unsigned long flags; - + save_flags(flags); cli(); @@ -307,7 +311,7 @@ static int nr_del_node(ax25_address *callsign, ax25_address *neighbour, struct d struct nr_node *nr_node; struct nr_neigh *nr_neigh; int i; - + for (nr_node = nr_node_list; nr_node != NULL; nr_node = nr_node->next) if (ax25cmp(callsign, &nr_node->callsign) == 0) break; @@ -319,7 +323,7 @@ static int nr_del_node(ax25_address *callsign, ax25_address *neighbour, struct d break; if (nr_neigh == NULL) return -EINVAL; - + for (i = 0; i < nr_node->count; i++) { if (nr_node->routes[i].neighbour == nr_neigh) { nr_neigh->count--; @@ -328,7 +332,7 @@ static int nr_del_node(ax25_address *callsign, ax25_address *neighbour, struct d nr_remove_neigh(nr_neigh); nr_node->count--; - + if (nr_node->count == 0) { nr_remove_node(nr_node); } else { @@ -375,6 +379,7 @@ static int nr_add_neigh(ax25_address *callsign, ax25_digi *ax25_digi, struct dev nr_neigh->locked = 1; nr_neigh->count = 0; nr_neigh->number = nr_neigh_no++; + nr_neigh->failed = 0; if (ax25_digi != NULL && ax25_digi->ndigi > 0) { if ((nr_neigh->digipeat = kmalloc(sizeof(*ax25_digi), GFP_KERNEL)) == NULL) { @@ -386,7 +391,7 @@ static int nr_add_neigh(ax25_address *callsign, ax25_digi *ax25_digi, struct dev save_flags(flags); cli(); - + nr_neigh->next = nr_neigh_list; nr_neigh_list = nr_neigh; @@ -443,9 +448,9 @@ static int nr_dec_obs(void) case 1: /* From 1 -> 0 */ nr_neigh = s->routes[i].neighbour; - + nr_neigh->count--; - + if (nr_neigh->count == 0 && !nr_neigh->locked) nr_remove_neigh(nr_neigh); @@ -487,14 +492,14 @@ void nr_rt_device_down(struct device *dev) while (nr_neigh != NULL) { s = nr_neigh; nr_neigh = nr_neigh->next; - + if (s->dev == dev) { nr_node = nr_node_list; while (nr_node != NULL) { t = nr_node; nr_node = nr_node->next; - + for (i = 0; i < t->count; i++) { if (t->routes[i].neighbour == s) { t->count--; @@ -509,11 +514,11 @@ void nr_rt_device_down(struct device *dev) } } } - + if (t->count <= 0) nr_remove_node(t); } - + nr_remove_neigh(s); } } @@ -561,7 +566,7 @@ struct device *nr_dev_get(ax25_address *addr) for (dev = dev_base; dev != NULL; dev = dev->next) if ((dev->flags & IFF_UP) && dev->type == ARPHRD_NETROM && ax25cmp(addr, (ax25_address *)dev->dev_addr) == 0) return dev; - + return NULL; } @@ -658,9 +663,11 @@ void nr_link_failed(ax25_address *callsign, struct device *dev) for (nr_neigh = nr_neigh_list; nr_neigh != NULL; nr_neigh = nr_neigh->next) if (ax25cmp(&nr_neigh->callsign, callsign) == 0 && nr_neigh->dev == dev) break; - + if (nr_neigh == NULL) return; - + + if (++nr_neigh->failed < sysctl_netrom_link_fails_count) return; + for (nr_node = nr_node_list; nr_node != NULL; nr_node = nr_node->next) if (nr_node->which < nr_node->count && nr_node->routes[nr_node->which].neighbour == nr_neigh) nr_node->which++; @@ -677,7 +684,7 @@ int nr_route_frame(struct sk_buff *skb, ax25_cb *ax25) struct nr_node *nr_node; struct device *dev; unsigned char *dptr; - + #ifdef CONFIG_FIREWALL if (ax25 != NULL && call_in_firewall(PF_NETROM, skb->dev, skb->data, NULL) != FW_ACCEPT) return 0; @@ -786,16 +793,17 @@ int nr_neigh_get_info(char *buffer, char **start, off_t offset, cli(); - len += sprintf(buffer, "addr callsign dev qual lock count digipeaters\n"); + len += sprintf(buffer, "addr callsign dev qual lock count failed digipeaters\n"); for (nr_neigh = nr_neigh_list; nr_neigh != NULL; nr_neigh = nr_neigh->next) { - len += sprintf(buffer + len, "%05d %-9s %-4s %3d %d %3d", + len += sprintf(buffer + len, "%05d %-9s %-4s %3d %d %3d %3d", nr_neigh->number, ax2asc(&nr_neigh->callsign), nr_neigh->dev ? nr_neigh->dev->name : "???", nr_neigh->quality, nr_neigh->locked, - nr_neigh->count); + nr_neigh->count, + nr_neigh->failed); if (nr_neigh->digipeat != NULL) { for (i = 0; i < nr_neigh->digipeat->ndigi; i++) @@ -810,7 +818,7 @@ int nr_neigh_get_info(char *buffer, char **start, off_t offset, len = 0; begin = pos; } - + if (pos > offset + length) break; } diff --git a/net/netrom/nr_subr.c b/net/netrom/nr_subr.c index ee8a4c4c1e30..3f7928e10c12 100644 --- a/net/netrom/nr_subr.c +++ b/net/netrom/nr_subr.c @@ -16,7 +16,7 @@ * NET/ROM 001 Jonathan(G4KLX) Cloned from ax25_subr.c * NET/ROM 003 Jonathan(G4KLX) Added G8BPQ NET/ROM extensions. */ - + #include #if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE) #include @@ -48,23 +48,17 @@ void nr_clear_queues(struct sock *sk) { struct sk_buff *skb; - while ((skb = skb_dequeue(&sk->write_queue)) != NULL) { - skb->sk = sk; + while ((skb = skb_dequeue(&sk->write_queue)) != NULL) kfree_skb(skb, FREE_WRITE); - } - while ((skb = skb_dequeue(&sk->protinfo.nr->ack_queue)) != NULL) { - skb->sk = sk; + while ((skb = skb_dequeue(&sk->protinfo.nr->ack_queue)) != NULL) kfree_skb(skb, FREE_WRITE); - } - while ((skb = skb_dequeue(&sk->protinfo.nr->reseq_queue)) != NULL) { + while ((skb = skb_dequeue(&sk->protinfo.nr->reseq_queue)) != NULL) kfree_skb(skb, FREE_READ); - } - while ((skb = skb_dequeue(&sk->protinfo.nr->frag_queue)) != NULL) { + while ((skb = skb_dequeue(&sk->protinfo.nr->frag_queue)) != NULL) kfree_skb(skb, FREE_READ); - } } /* @@ -82,7 +76,6 @@ void nr_frames_acked(struct sock *sk, unsigned short nr) if (sk->protinfo.nr->va != nr) { while (skb_peek(&sk->protinfo.nr->ack_queue) != NULL && sk->protinfo.nr->va != nr) { skb = skb_dequeue(&sk->protinfo.nr->ack_queue); - skb->sk = sk; kfree_skb(skb, FREE_WRITE); sk->protinfo.nr->va = (sk->protinfo.nr->va + 1) % NR_MODULUS; } @@ -119,7 +112,7 @@ int nr_validate_nr(struct sock *sk, unsigned short nr) if (nr == vc) return 1; vc = (vc + 1) % NR_MODULUS; } - + if (nr == sk->protinfo.nr->vs) return 1; return 0; @@ -152,7 +145,7 @@ void nr_write_internal(struct sock *sk, int frametype) int len, timeout; len = AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + NR_NETWORK_LEN + NR_TRANSPORT_LEN; - + switch (frametype & 0x0F) { case NR_CONNREQ: len += 17; @@ -168,7 +161,7 @@ void nr_write_internal(struct sock *sk, int frametype) printk(KERN_ERR "nr_write_internal: invalid frame type %d\n", frametype); return; } - + if ((skb = alloc_skb(len, GFP_ATOMIC)) == NULL) return; @@ -182,7 +175,7 @@ void nr_write_internal(struct sock *sk, int frametype) switch (frametype & 0x0F) { case NR_CONNREQ: - timeout = (sk->protinfo.nr->rtt / PR_SLOWHZ) * 2; + timeout = (sk->protinfo.nr->rtt / NR_SLOWHZ) * 2; *dptr++ = sk->protinfo.nr->my_index; *dptr++ = sk->protinfo.nr->my_id; *dptr++ = 0; @@ -190,14 +183,14 @@ void nr_write_internal(struct sock *sk, int frametype) *dptr++ = frametype; *dptr++ = sk->protinfo.nr->window; memcpy(dptr, &sk->protinfo.nr->user_addr, AX25_ADDR_LEN); - dptr[6] &= ~LAPB_C; - dptr[6] &= ~LAPB_E; - dptr[6] |= SSSID_SPARE; + dptr[6] &= ~AX25_CBIT; + dptr[6] &= ~AX25_EBIT; + dptr[6] |= AX25_SSSID_SPARE; dptr += AX25_ADDR_LEN; memcpy(dptr, &sk->protinfo.nr->source_addr, AX25_ADDR_LEN); - dptr[6] &= ~LAPB_C; - dptr[6] &= ~LAPB_E; - dptr[6] |= SSSID_SPARE; + dptr[6] &= ~AX25_CBIT; + dptr[6] &= ~AX25_EBIT; + dptr[6] |= AX25_SSSID_SPARE; dptr += AX25_ADDR_LEN; *dptr++ = timeout % 256; *dptr++ = timeout / 256; @@ -254,15 +247,15 @@ void nr_transmit_dm(struct sk_buff *skb) dptr = skb_put(skbn, NR_NETWORK_LEN + NR_TRANSPORT_LEN); memcpy(dptr, skb->data + 7, AX25_ADDR_LEN); - dptr[6] &= ~LAPB_C; - dptr[6] &= ~LAPB_E; - dptr[6] |= SSSID_SPARE; + dptr[6] &= ~AX25_CBIT; + dptr[6] &= ~AX25_EBIT; + dptr[6] |= AX25_SSSID_SPARE; dptr += AX25_ADDR_LEN; memcpy(dptr, skb->data + 0, AX25_ADDR_LEN); - dptr[6] &= ~LAPB_C; - dptr[6] |= LAPB_E; - dptr[6] |= SSSID_SPARE; + dptr[6] &= ~AX25_CBIT; + dptr[6] |= AX25_EBIT; + dptr[6] |= AX25_SSSID_SPARE; dptr += AX25_ADDR_LEN; *dptr++ = sysctl_netrom_network_ttl_initialiser; @@ -303,19 +296,11 @@ void nr_calculate_rtt(struct sock *sk) if (sk->protinfo.nr->t1timer > 0 && sk->protinfo.nr->n2count == 0) sk->protinfo.nr->rtt = (9 * sk->protinfo.nr->rtt + sk->protinfo.nr->t1 - sk->protinfo.nr->t1timer) / 10; -#ifdef NR_T1CLAMPLO - /* Don't go below one tenth of a second */ - if (sk->protinfo.nr->rtt < (NR_T1CLAMPLO)) - sk->protinfo.nr->rtt = (NR_T1CLAMPLO); -#else /* Failsafe - some people might have sub 1/10th RTTs :-) **/ - if (sk->protinfo.nr->rtt == 0) - sk->protinfo.nr->rtt = PR_SLOWHZ; -#endif -#ifdef NR_T1CLAMPHI - /* OR above clamped seconds **/ - if (sk->protinfo.nr->rtt > (NR_T1CLAMPHI)) - sk->protinfo.nr->rtt = (NR_T1CLAMPHI); -#endif + if (sk->protinfo.nr->rtt < NR_T1CLAMPLO) + sk->protinfo.nr->rtt = NR_T1CLAMPLO; + + if (sk->protinfo.nr->rtt > NR_T1CLAMPHI) + sk->protinfo.nr->rtt = NR_T1CLAMPHI; } #endif diff --git a/net/netrom/nr_timer.c b/net/netrom/nr_timer.c index db5de2c53691..566f2a6f7266 100644 --- a/net/netrom/nr_timer.c +++ b/net/netrom/nr_timer.c @@ -48,7 +48,7 @@ static void nr_timer(unsigned long); void nr_set_timer(struct sock *sk) { unsigned long flags; - + save_flags(flags); cli(); del_timer(&sk->timer); @@ -65,7 +65,7 @@ void nr_set_timer(struct sock *sk) static void nr_reset_timer(struct sock *sk) { unsigned long flags; - + save_flags(flags); cli(); del_timer(&sk->timer); @@ -102,11 +102,11 @@ static void nr_timer(unsigned long param) /* * Check for the state of the receive buffer. */ - if (sk->rmem_alloc < (sk->rcvbuf / 2) && (sk->protinfo.nr->condition & OWN_RX_BUSY_CONDITION)) { - sk->protinfo.nr->condition &= ~OWN_RX_BUSY_CONDITION; - nr_write_internal(sk, NR_INFOACK); - sk->protinfo.nr->condition &= ~ACK_PENDING_CONDITION; + if (sk->rmem_alloc < (sk->rcvbuf / 2) && (sk->protinfo.nr->condition & NR_COND_OWN_RX_BUSY)) { + sk->protinfo.nr->condition &= ~NR_COND_OWN_RX_BUSY; + sk->protinfo.nr->condition &= ~NR_COND_ACK_PENDING; sk->protinfo.nr->vl = sk->protinfo.nr->vr; + nr_write_internal(sk, NR_INFOACK); break; } /* @@ -121,15 +121,15 @@ static void nr_timer(unsigned long param) if (sk->protinfo.nr->t2timer > 0 && --sk->protinfo.nr->t2timer == 0) { if (sk->protinfo.nr->state == NR_STATE_3) { - if (sk->protinfo.nr->condition & ACK_PENDING_CONDITION) { - sk->protinfo.nr->condition &= ~ACK_PENDING_CONDITION; + if (sk->protinfo.nr->condition & NR_COND_ACK_PENDING) { + sk->protinfo.nr->condition &= ~NR_COND_ACK_PENDING; nr_enquiry_response(sk); } } } if (sk->protinfo.nr->t4timer > 0 && --sk->protinfo.nr->t4timer == 0) { - sk->protinfo.nr->condition &= ~PEER_RX_BUSY_CONDITION; + sk->protinfo.nr->condition &= ~NR_COND_PEER_RX_BUSY; } if (sk->protinfo.nr->t1timer == 0 || --sk->protinfo.nr->t1timer > 0) { diff --git a/net/netrom/sysctl_net_netrom.c b/net/netrom/sysctl_net_netrom.c index 3cbc0b761cdb..f6eac6179d1e 100644 --- a/net/netrom/sysctl_net_netrom.c +++ b/net/netrom/sysctl_net_netrom.c @@ -16,18 +16,19 @@ static int min_quality[] = {0}, max_quality[] = {255}; static int min_obs[] = {0}, max_obs[] = {255}; static int min_ttl[] = {0}, max_ttl[] = {255}; -static int min_t1[] = {5 * PR_SLOWHZ}; -static int max_t1[] = {600 * PR_SLOWHZ}; +static int min_t1[] = {5 * NR_SLOWHZ}; +static int max_t1[] = {600 * NR_SLOWHZ}; static int min_n2[] = {2}, max_n2[] = {127}; -static int min_t2[] = {1 * PR_SLOWHZ}; -static int max_t2[] = {60 * PR_SLOWHZ}; -static int min_t4[] = {1 * PR_SLOWHZ}; -static int max_t4[] = {1000 * PR_SLOWHZ}; +static int min_t2[] = {1 * NR_SLOWHZ}; +static int max_t2[] = {60 * NR_SLOWHZ}; +static int min_t4[] = {1 * NR_SLOWHZ}; +static int max_t4[] = {1000 * NR_SLOWHZ}; static int min_window[] = {1}, max_window[] = {127}; -static int min_idle[] = {0 * PR_SLOWHZ}; -static int max_idle[] = {65535 * PR_SLOWHZ}; +static int min_idle[] = {0 * NR_SLOWHZ}; +static int max_idle[] = {65535 * NR_SLOWHZ}; static int min_n1[] = {1}, max_n1[] = {236}; static int min_route[] = {0}, max_route[] = {1}; +static int min_fails[] = {1}, max_fails[] = {10}; static struct ctl_table_header *nr_table_header; @@ -65,6 +66,9 @@ static ctl_table nr_table[] = { {NET_NETROM_ROUTING_CONTROL, "routing_control", &sysctl_netrom_routing_control, sizeof(int), 0644, NULL, &proc_dointvec_minmax, &sysctl_intvec, NULL, &min_route, &max_route}, + {NET_NETROM_LINK_FAILS_COUNT, "link_fails_count", + &sysctl_netrom_link_fails_count, sizeof(int), 0644, NULL, + &proc_dointvec_minmax, &sysctl_intvec, NULL, &min_fails, &max_fails}, {0} }; diff --git a/net/netsyms.c b/net/netsyms.c index a443e27ac0da..09bd3a9c44c1 100644 --- a/net/netsyms.c +++ b/net/netsyms.c @@ -66,6 +66,10 @@ extern void destroy_EII_client(struct datalink_proto *); extern void destroy_8023_client(struct datalink_proto *); #endif +#ifdef CONFIG_ATALK_MODULE +#include +#endif + extern char *skb_push_errstr; extern char *skb_put_errstr; @@ -87,6 +91,7 @@ EXPORT_SYMBOL(sk_alloc); EXPORT_SYMBOL(sk_free); EXPORT_SYMBOL(sock_wake_async); EXPORT_SYMBOL(sock_alloc_send_skb); +EXPORT_SYMBOL(sock_no_fcntl); EXPORT_SYMBOL(sock_rfree); EXPORT_SYMBOL(sock_wfree); EXPORT_SYMBOL(skb_recv_datagram); @@ -107,6 +112,11 @@ EXPORT_SYMBOL(make_EII_client); EXPORT_SYMBOL(destroy_EII_client); #endif +#ifdef CONFIG_ATALK_MODULE +EXPORT_SYMBOL(sklist_destroy_socket); +EXPORT_SYMBOL(sklist_insert_socket); +#endif + #ifdef CONFIG_INET /* Internet layer registration */ EXPORT_SYMBOL(get_new_socknum); @@ -125,10 +135,6 @@ EXPORT_SYMBOL(ip_fragment); EXPORT_SYMBOL(ip_dev_find_tunnel); EXPORT_SYMBOL(inet_family_ops); -#ifdef CONFIG_IP_FORWARD -EXPORT_SYMBOL(ip_forward); -#endif - #ifdef CONFIG_IPV6_MODULE /* inet functions common to v4 and v6 */ EXPORT_SYMBOL(inet_stream_ops); @@ -245,7 +251,6 @@ EXPORT_SYMBOL(unregister_netdev); EXPORT_SYMBOL(ether_setup); EXPORT_SYMBOL(eth_type_trans); EXPORT_SYMBOL(eth_copy_and_sum); -EXPORT_SYMBOL(arp_query); EXPORT_SYMBOL(alloc_skb); EXPORT_SYMBOL(__kfree_skb); EXPORT_SYMBOL(skb_clone); diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index 79f0150e0d51..8f0b6895e6be 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c @@ -18,7 +18,7 @@ * Terry (VK2KTJ) Added support for variable length * address masks. */ - + #include #if defined(CONFIG_ROSE) || defined(CONFIG_ROSE_MODULE) #include @@ -67,6 +67,8 @@ static struct sock *volatile rose_list = NULL; static struct proto_ops rose_proto_ops; +ax25_address rose_callsign; + /* * Convert a Rose address into text. */ @@ -99,7 +101,7 @@ int rosecmp(rose_address *addr1, rose_address *addr2) for (i = 0; i < 5; i++) if (addr1->rose_addr[i] != addr2->rose_addr[i]) return 1; - + return 0; } @@ -113,15 +115,15 @@ int rosecmpm(rose_address *addr1, rose_address *addr2, unsigned short mask) if (mask > 10) return 1; - for (i = 0, j = 0; i < mask; i++) { + for (i = 0; i < mask; i++) { j = i / 2; - if ((i % 2) != 0) { /* odd place */ - if ((addr1->rose_addr[j] & 0xF0) != (addr2->rose_addr[j] & 0xF0)) - return 1; - } else { /* even place */ + if ((i % 2) != 0) { if ((addr1->rose_addr[j] & 0x0F) != (addr2->rose_addr[j] & 0x0F)) return 1; + } else { + if ((addr1->rose_addr[j] & 0xF0) != (addr2->rose_addr[j] & 0xF0)) + return 1; } } @@ -151,7 +153,7 @@ static struct sock *rose_alloc_sock(void) } MOD_INC_USE_COUNT; - + memset(rose, 0x00, sizeof(*rose)); sk->protinfo.rose = rose; @@ -167,7 +169,7 @@ static void rose_remove_socket(struct sock *sk) { struct sock *s; unsigned long flags; - + save_flags(flags); cli(); @@ -223,7 +225,7 @@ static int rose_device_event(struct notifier_block *this, unsigned long event, v rose_kill_by_device(dev); rose_rt_device_down(dev); rose_link_device_down(dev); - + return NOTIFY_DONE; } @@ -237,8 +239,8 @@ static void rose_insert_socket(struct sock *sk) save_flags(flags); cli(); - sk->next = rose_list; - rose_list = sk; + sk->next = rose_list; + rose_list = sk; restore_flags(flags); } @@ -335,15 +337,15 @@ void rose_destroy_socket(struct sock *sk) /* Not static as it's used by the time { struct sk_buff *skb; unsigned long flags; - + save_flags(flags); cli(); - + del_timer(&sk->timer); - + rose_remove_socket(sk); rose_clear_queues(sk); /* Flush the queues */ - + while ((skb = skb_dequeue(&sk->receive_queue)) != NULL) { if (skb->sk != sk) { /* A pending connection */ skb->sk->dead = 1; /* Queue the unaccepted socket for death */ @@ -353,8 +355,8 @@ void rose_destroy_socket(struct sock *sk) /* Not static as it's used by the time kfree_skb(skb, FREE_READ); } - - if (sk->wmem_alloc || sk->rmem_alloc) { /* Defer: outstanding buffers */ + + if (sk->wmem_alloc || sk->rmem_alloc) { /* Defer: outstanding buffers */ init_timer(&sk->timer); sk->timer.expires = jiffies + 10 * HZ; sk->timer.function = rose_destroy_timer; @@ -371,11 +373,6 @@ void rose_destroy_socket(struct sock *sk) /* Not static as it's used by the time * Handling for system calls applied via the various interfaces to a * Rose socket object. */ - -static int rose_fcntl(struct socket *sock, unsigned int cmd, unsigned long arg) -{ - return -EINVAL; -} /* * dl1bke 960311: set parameters for existing Rose connections, @@ -420,7 +417,7 @@ static int rose_ctl_ioctl(const unsigned int cmd, void *arg) return -EINVAL; if (sk->protinfo.rose->neighbour != NULL) { save_flags(flags); cli(); - sk->protinfo.rose->neighbour->t0 = rose_ctl.arg * PR_SLOWHZ; + sk->protinfo.rose->neighbour->t0 = rose_ctl.arg * ROSE_SLOWHZ; restore_flags(flags); } break; @@ -429,7 +426,7 @@ static int rose_ctl_ioctl(const unsigned int cmd, void *arg) if (rose_ctl.arg < 1) return -EINVAL; save_flags(flags); cli(); - sk->protinfo.rose->t1 = rose_ctl.arg * PR_SLOWHZ; + sk->protinfo.rose->t1 = rose_ctl.arg * ROSE_SLOWHZ; restore_flags(flags); break; @@ -437,7 +434,7 @@ static int rose_ctl_ioctl(const unsigned int cmd, void *arg) if (rose_ctl.arg < 1) return -EINVAL; save_flags(flags); cli(); - sk->protinfo.rose->t2 = rose_ctl.arg * PR_SLOWHZ; + sk->protinfo.rose->t2 = rose_ctl.arg * ROSE_SLOWHZ; restore_flags(flags); break; @@ -445,7 +442,7 @@ static int rose_ctl_ioctl(const unsigned int cmd, void *arg) if (rose_ctl.arg < 1) return -EINVAL; save_flags(flags); cli(); - sk->protinfo.rose->t3 = rose_ctl.arg * PR_SLOWHZ; + sk->protinfo.rose->t3 = rose_ctl.arg * ROSE_SLOWHZ; restore_flags(flags); break; @@ -453,7 +450,7 @@ static int rose_ctl_ioctl(const unsigned int cmd, void *arg) if (rose_ctl.arg < 1) return -EINVAL; save_flags(flags); cli(); - sk->protinfo.rose->hb = rose_ctl.arg * PR_SLOWHZ; + sk->protinfo.rose->hb = rose_ctl.arg * ROSE_SLOWHZ; restore_flags(flags); break; @@ -461,7 +458,7 @@ static int rose_ctl_ioctl(const unsigned int cmd, void *arg) if (rose_ctl.arg < 1) return -EINVAL; save_flags(flags); cli(); - sk->protinfo.rose->idle = rose_ctl.arg * 60 * PR_SLOWHZ; + sk->protinfo.rose->idle = rose_ctl.arg * 60 * ROSE_SLOWHZ; restore_flags(flags); break; @@ -475,11 +472,9 @@ static int rose_ctl_ioctl(const unsigned int cmd, void *arg) static int rose_setsockopt(struct socket *sock, int level, int optname, char *optval, int optlen) { - struct sock *sk; + struct sock *sk = sock->sk; int err, opt; - sk = (struct sock *)sock->sk; - if (level != SOL_ROSE) return -EOPNOTSUPP; @@ -490,45 +485,45 @@ static int rose_setsockopt(struct socket *sock, int level, int optname, return err; get_user(opt, (int *)optval); - + switch (optname) { case ROSE_T0: if (opt < 1) return -EINVAL; if (sk->protinfo.rose->neighbour != NULL) - sk->protinfo.rose->neighbour->t0 = opt * PR_SLOWHZ; + sk->protinfo.rose->neighbour->t0 = opt * ROSE_SLOWHZ; return 0; case ROSE_T1: if (opt < 1) return -EINVAL; - sk->protinfo.rose->t1 = opt * PR_SLOWHZ; + sk->protinfo.rose->t1 = opt * ROSE_SLOWHZ; return 0; case ROSE_T2: if (opt < 1) return -EINVAL; - sk->protinfo.rose->t2 = opt * PR_SLOWHZ; + sk->protinfo.rose->t2 = opt * ROSE_SLOWHZ; return 0; - + case ROSE_T3: if (opt < 1) return -EINVAL; - sk->protinfo.rose->t3 = opt * PR_SLOWHZ; + sk->protinfo.rose->t3 = opt * ROSE_SLOWHZ; return 0; - + case ROSE_HOLDBACK: if (opt < 1) return -EINVAL; - sk->protinfo.rose->hb = opt * PR_SLOWHZ; + sk->protinfo.rose->hb = opt * ROSE_SLOWHZ; return 0; - + case ROSE_IDLE: if (opt < 1) return -EINVAL; - sk->protinfo.rose->idle = opt * 60 * PR_SLOWHZ; + sk->protinfo.rose->idle = opt * 60 * ROSE_SLOWHZ; return 0; - + case ROSE_HDRINCL: sk->protinfo.rose->hdrincl = opt ? 1 : 0; return 0; @@ -541,43 +536,41 @@ static int rose_setsockopt(struct socket *sock, int level, int optname, static int rose_getsockopt(struct socket *sock, int level, int optname, char *optval, int *optlen) { - struct sock *sk; + struct sock *sk = sock->sk; int val = 0; int err; - sk = (struct sock *)sock->sk; - if (level != SOL_ROSE) return -EOPNOTSUPP; switch (optname) { case ROSE_T0: if (sk->protinfo.rose->neighbour != NULL) - val = sk->protinfo.rose->neighbour->t0 / PR_SLOWHZ; + val = sk->protinfo.rose->neighbour->t0 / ROSE_SLOWHZ; else - val = sysctl_rose_restart_request_timeout / PR_SLOWHZ; + val = sysctl_rose_restart_request_timeout / ROSE_SLOWHZ; break; - + case ROSE_T1: - val = sk->protinfo.rose->t1 / PR_SLOWHZ; + val = sk->protinfo.rose->t1 / ROSE_SLOWHZ; break; - + case ROSE_T2: - val = sk->protinfo.rose->t2 / PR_SLOWHZ; + val = sk->protinfo.rose->t2 / ROSE_SLOWHZ; break; - + case ROSE_T3: - val = sk->protinfo.rose->t3 / PR_SLOWHZ; + val = sk->protinfo.rose->t3 / ROSE_SLOWHZ; break; - + case ROSE_HOLDBACK: - val = sk->protinfo.rose->hb / PR_SLOWHZ; + val = sk->protinfo.rose->hb / ROSE_SLOWHZ; break; - + case ROSE_IDLE: - val = sk->protinfo.rose->idle / (PR_SLOWHZ * 60); + val = sk->protinfo.rose->idle / (ROSE_SLOWHZ * 60); break; - + case ROSE_HDRINCL: val = sk->protinfo.rose->hdrincl; break; @@ -601,7 +594,7 @@ static int rose_getsockopt(struct socket *sock, int level, int optname, static int rose_listen(struct socket *sock, int backlog) { - struct sock *sk = (struct sock *)sock->sk; + struct sock *sk = sock->sk; if (sk->state != TCP_LISTEN) { sk->protinfo.rose->dest_ndigis = 0; @@ -624,18 +617,17 @@ static void def_callback1(struct sock *sk) static void def_callback2(struct sock *sk, int len) { - if (!sk->dead) - { + if (!sk->dead) { wake_up_interruptible(sk->sleep); - sock_wake_async(sk->socket,1); + sock_wake_async(sk->socket, 1); } } -static void def_callback3(struct sock *sk, int len) + +static void def_callback3(struct sock *sk) { - if (!sk->dead) - { + if (!sk->dead) { wake_up_interruptible(sk->sleep); - sock_wake_async(sk->socket,2); + sock_wake_async(sk->socket, 2); } } @@ -652,35 +644,12 @@ static int rose_create(struct socket *sock, int protocol) rose = sk->protinfo.rose; - skb_queue_head_init(&sk->receive_queue); - skb_queue_head_init(&sk->write_queue); - skb_queue_head_init(&sk->back_log); - - init_timer(&sk->timer); - + sock_init_data(sock,sk); + sock->ops = &rose_proto_ops; - sk->socket = sock; - sk->type = sock->type; sk->protocol = protocol; - sk->allocation = GFP_KERNEL; - sk->rcvbuf = SK_RMEM_MAX; - sk->sndbuf = SK_WMEM_MAX; - sk->state = TCP_CLOSE; - sk->priority = SOPRI_NORMAL; sk->mtu = ROSE_MTU; /* 128 */ - sk->zapped = 1; - sk->state_change = def_callback1; - sk->data_ready = def_callback2; - sk->write_space = def_callback1; - sk->error_report = def_callback1; - - if (sock != NULL) { - sock->sk = sk; - sk->sleep = &sock->wait; - } - - skb_queue_head_init(&rose->ack_queue); skb_queue_head_init(&rose->frag_queue); rose->t1 = sysctl_rose_call_request_timeout; @@ -727,10 +696,9 @@ static struct sock *rose_make_new(struct sock *osk) sk->state_change = def_callback1; sk->data_ready = def_callback2; - sk->write_space = def_callback1; + sk->write_space = def_callback3; sk->error_report = def_callback1; - skb_queue_head_init(&rose->ack_queue); skb_queue_head_init(&rose->frag_queue); rose->t1 = osk->protinfo.rose->t1; @@ -747,14 +715,17 @@ static struct sock *rose_make_new(struct sock *osk) static int rose_dup(struct socket *newsock, struct socket *oldsock) { - struct sock *sk = (struct sock *)oldsock->sk; + struct sock *sk = oldsock->sk; + + if (sk == NULL || newsock == NULL) + return -EINVAL; return rose_create(newsock, sk->protocol); } static int rose_release(struct socket *sock, struct socket *peer) { - struct sock *sk = (struct sock *)sock->sk; + struct sock *sk = sock->sk; if (sk == NULL) return 0; @@ -811,19 +782,20 @@ static int rose_release(struct socket *sock, struct socket *peer) static int rose_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) { - struct sock *sk; + struct sock *sk = sock->sk; struct sockaddr_rose *addr = (struct sockaddr_rose *)uaddr; struct device *dev; ax25_address *user, *source; - - sk = (struct sock *)sock->sk; if (sk->zapped == 0) return -EINVAL; - + if (addr_len != sizeof(struct sockaddr_rose)) return -EINVAL; + if (addr->srose_family != AF_ROSE) + return -EINVAL; + if ((dev = rose_dev_get(&addr->srose_addr)) == NULL) { if (sk->debug) printk("Rose: bind failed: invalid address\n"); @@ -859,30 +831,33 @@ static int rose_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags) { - struct sock *sk = (struct sock *)sock->sk; + struct sock *sk = sock->sk; struct sockaddr_rose *addr = (struct sockaddr_rose *)uaddr; ax25_address *user; struct device *dev; - + if (sk->state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) { sock->state = SS_CONNECTED; return 0; /* Connect completed during a ERESTARTSYS event */ } - + if (sk->state == TCP_CLOSE && sock->state == SS_CONNECTING) { sock->state = SS_UNCONNECTED; return -ECONNREFUSED; } - + if (sk->state == TCP_ESTABLISHED) return -EISCONN; /* No reconnect on a seqpacket socket */ - + sk->state = TCP_CLOSE; sock->state = SS_UNCONNECTED; if (addr_len != sizeof(struct sockaddr_rose)) return -EINVAL; + if (addr->srose_family != AF_ROSE) + return -EINVAL; + if ((sk->protinfo.rose->neighbour = rose_get_neigh(&addr->srose_addr)) == NULL) return -ENETUNREACH; @@ -919,7 +894,7 @@ static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le rose_write_internal(sk, ROSE_CALL_REQUEST); rose_set_timer(sk); - + /* Now the loop */ if (sk->state != TCP_ESTABLISHED && (flags & O_NONBLOCK)) return -EINPROGRESS; @@ -942,11 +917,11 @@ static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le sock->state = SS_UNCONNECTED; return sock_error(sk); /* Always set at this point */ } - + sock->state = SS_CONNECTED; sti(); - + return 0; } @@ -961,19 +936,20 @@ static int rose_accept(struct socket *sock, struct socket *newsock, int flags) struct sock *newsk; struct sk_buff *skb; - if (newsock->sk) - sk_free(newsock->sk); + if (newsock->sk != NULL) + rose_destroy_socket(newsock->sk); newsock->sk = NULL; - - sk = (struct sock *)sock->sk; + + if ((sk = sock->sk) == NULL) + return -EINVAL; if (sk->type != SOCK_SEQPACKET) return -EOPNOTSUPP; - + if (sk->state != TCP_LISTEN) return -EINVAL; - + /* * The write queue this time is holding sockets ready to use * hooked into the SABM we saved @@ -983,7 +959,7 @@ static int rose_accept(struct socket *sock, struct socket *newsock, int flags) if ((skb = skb_dequeue(&sk->receive_queue)) == NULL) { if (flags & O_NONBLOCK) { sti(); - return 0; + return -EWOULDBLOCK; } interruptible_sleep_on(sk->sleep); if (current->signal & ~current->blocked) { @@ -1010,10 +986,8 @@ static int rose_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_len, int peer) { struct sockaddr_rose *srose = (struct sockaddr_rose *)uaddr; - struct sock *sk; - - sk = (struct sock *)sock->sk; - + struct sock *sk = sock->sk; + if (peer != 0) { if (sk->state != TCP_ESTABLISHED) return -ENOTCONN; @@ -1040,11 +1014,11 @@ static int rose_getname(struct socket *sock, struct sockaddr *uaddr, return 0; } - + int rose_rx_call_request(struct sk_buff *skb, struct device *dev, struct rose_neigh *neigh, unsigned int lci) { struct sock *sk; - struct sock *make; + struct sock *make; rose_cb rose; skb->sk = NULL; /* Initially we don't know who it's for */ @@ -1059,7 +1033,7 @@ int rose_rx_call_request(struct sk_buff *skb, struct device *dev, struct rose_ne if (!rose_parse_facilities(skb, &rose)) { return 0; } - + sk = rose_find_listener(&rose.source_call); /* @@ -1084,7 +1058,7 @@ int rose_rx_call_request(struct sk_buff *skb, struct device *dev, struct rose_ne make->protinfo.rose->source_digi = rose.source_digi; make->protinfo.rose->neighbour = neigh; make->protinfo.rose->device = dev; - + rose_write_internal(make, ROSE_CALL_ACCEPTED); make->protinfo.rose->condition = 0x00; @@ -1111,14 +1085,14 @@ int rose_rx_call_request(struct sk_buff *skb, struct device *dev, struct rose_ne static int rose_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct scm_cookie *scm) { - struct sock *sk = (struct sock *)sock->sk; + struct sock *sk = sock->sk; struct sockaddr_rose *usrose = (struct sockaddr_rose *)msg->msg_name; int err; struct sockaddr_rose srose; struct sk_buff *skb; unsigned char *asmptr; int size; - + if (msg->msg_flags & ~MSG_DONTWAIT) return -EINVAL; @@ -1132,7 +1106,7 @@ static int rose_sendmsg(struct socket *sock, struct msghdr *msg, int len, if (sk->protinfo.rose->device == NULL) return -ENETUNREACH; - + if (usrose != NULL) { if (msg->msg_namelen < sizeof(srose)) return -EINVAL; @@ -1160,7 +1134,7 @@ static int rose_sendmsg(struct socket *sock, struct msghdr *msg, int len, srose.srose_digi = sk->protinfo.rose->dest_digi; } } - + if (sk->debug) printk("Rose: sendto: Addresses built.\n"); @@ -1173,11 +1147,10 @@ static int rose_sendmsg(struct socket *sock, struct msghdr *msg, int len, if ((skb = sock_alloc_send_skb(sk, size, 0, msg->msg_flags & MSG_DONTWAIT, &err)) == NULL) return err; - skb->sk = sk; - skb->arp = 1; + skb->arp = 1; skb_reserve(skb, size - len); - + /* * Push down the Rose header */ @@ -1189,10 +1162,10 @@ static int rose_sendmsg(struct socket *sock, struct msghdr *msg, int len, /* Build a Rose Transport header */ - *asmptr++ = ((sk->protinfo.rose->lci >> 8) & 0x0F) | GFI; + *asmptr++ = ((sk->protinfo.rose->lci >> 8) & 0x0F) | ROSE_GFI; *asmptr++ = (sk->protinfo.rose->lci >> 0) & 0xFF; *asmptr++ = ROSE_DATA; - + if (sk->debug) printk("Built header.\n"); @@ -1203,7 +1176,7 @@ static int rose_sendmsg(struct socket *sock, struct msghdr *msg, int len, skb->h.raw = skb_put(skb, len); asmptr = skb->h.raw; - + if (sk->debug) printk("Rose: Appending user data\n"); @@ -1227,7 +1200,7 @@ static int rose_sendmsg(struct socket *sock, struct msghdr *msg, int len, static int rose_recvmsg(struct socket *sock, struct msghdr *msg, int size, int flags, struct scm_cookie *scm) { - struct sock *sk = (struct sock *)sock->sk; + struct sock *sk = sock->sk; struct sockaddr_rose *srose = (struct sockaddr_rose *)msg->msg_name; int copied; struct sk_buff *skb; @@ -1250,28 +1223,24 @@ static int rose_recvmsg(struct socket *sock, struct msghdr *msg, int size, } copied = skb->len; - + if (copied > size) { copied = size; msg->msg_flags |= MSG_TRUNC; } - + skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); - + if (srose != NULL) { - struct sockaddr_rose addr; - - addr.srose_family = AF_ROSE; - addr.srose_addr = sk->protinfo.rose->dest_addr; - addr.srose_call = sk->protinfo.rose->dest_call; - addr.srose_ndigis = 0; + srose->srose_family = AF_ROSE; + srose->srose_addr = sk->protinfo.rose->dest_addr; + srose->srose_call = sk->protinfo.rose->dest_call; + srose->srose_ndigis = 0; if (sk->protinfo.rose->dest_ndigis == 1) { - addr.srose_ndigis = 1; - addr.srose_digi = sk->protinfo.rose->dest_digi; + srose->srose_ndigis = 1; + srose->srose_digi = sk->protinfo.rose->dest_digi; } - - *srose = addr; } msg->msg_namelen = sizeof(struct sockaddr_rose); @@ -1288,7 +1257,7 @@ static int rose_shutdown(struct socket *sk, int how) static int rose_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) { - struct sock *sk = (struct sock *)sock->sk; + struct sock *sk = sock->sk; int err; long amount = 0; @@ -1341,11 +1310,22 @@ static int rose_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) if (!suser()) return -EPERM; return rose_rt_ioctl(cmd, (void *)arg); - case SIOCRSCTLCON: + case SIOCRSCTLCON: if (!suser()) return -EPERM; return rose_ctl_ioctl(cmd, (void *)arg); - - default: + + case SIOCRSL2CALL: + if (!suser()) return -EPERM; + if ((err = verify_area(VERIFY_READ, (void *)arg, sizeof(ax25_address))) != 0) + return err; + if (ax25cmp(&rose_callsign, &null_ax25_address) != 0) + ax25_listen_release(&rose_callsign, NULL); + copy_from_user(&rose_callsign, (void *)arg, sizeof(ax25_address)); + if (ax25cmp(&rose_callsign, &null_ax25_address) != 0) + ax25_listen_register(&rose_callsign, NULL); + return 0; + + default: return dev_ioctl(cmd, (void *)arg); } @@ -1361,10 +1341,10 @@ static int rose_get_info(char *buffer, char **start, off_t offset, int length, i int len = 0; off_t pos = 0; off_t begin = 0; - + cli(); - len += sprintf(buffer, "dest_addr dest_call dest_digi src_addr src_call src_digi dev lci st vs vr va t t1 t2 t3 hb Snd-Q Rcv-Q\n"); + len += sprintf(buffer, "dest_addr dest_call src_addr src_call dev lci st vs vr va t t1 t2 t3 hb Snd-Q Rcv-Q\n"); for (s = rose_list; s != NULL; s = s->next) { if ((dev = s->protinfo.rose->device) == NULL) @@ -1375,36 +1355,31 @@ static int rose_get_info(char *buffer, char **start, off_t offset, int length, i len += sprintf(buffer + len, "%-10s %-9s ", rose2asc(&s->protinfo.rose->dest_addr), ax2asc(&s->protinfo.rose->dest_call)); - len += sprintf(buffer + len, "%-9s ", - ax2asc(&s->protinfo.rose->dest_digi)); if (ax25cmp(&s->protinfo.rose->source_call, &null_ax25_address) == 0) callsign = "??????-?"; else callsign = ax2asc(&s->protinfo.rose->source_call); - len += sprintf(buffer + len, "%-10s %-9s ", - rose2asc(&s->protinfo.rose->source_addr), - callsign); - len += sprintf(buffer + len, "%-9s %-5s %3.3X %d %d %d %d %3d %3d %3d %3d %3d %5d %5d\n", - ax2asc(&s->protinfo.rose->source_digi), + len += sprintf(buffer + len, "%-10s %-9s %-5s %3.3X %d %d %d %d %3d %3d %3d %3d %3d %5d %5d\n", + rose2asc(&s->protinfo.rose->source_addr), callsign, devname, s->protinfo.rose->lci & 0x0FFF, s->protinfo.rose->state, s->protinfo.rose->vs, s->protinfo.rose->vr, s->protinfo.rose->va, - s->protinfo.rose->timer / PR_SLOWHZ, - s->protinfo.rose->t1 / PR_SLOWHZ, - s->protinfo.rose->t2 / PR_SLOWHZ, - s->protinfo.rose->t3 / PR_SLOWHZ, - s->protinfo.rose->hb / PR_SLOWHZ, + s->protinfo.rose->timer / ROSE_SLOWHZ, + s->protinfo.rose->t1 / ROSE_SLOWHZ, + s->protinfo.rose->t2 / ROSE_SLOWHZ, + s->protinfo.rose->t3 / ROSE_SLOWHZ, + s->protinfo.rose->hb / ROSE_SLOWHZ, s->wmem_alloc, s->rmem_alloc); - + pos = begin + len; if (pos < offset) { len = 0; begin = pos; } - + if (pos > offset + length) break; } @@ -1426,7 +1401,7 @@ static struct net_proto_family rose_family_ops = { static struct proto_ops rose_proto_ops = { AF_ROSE, - + rose_dup, rose_release, rose_bind, @@ -1440,7 +1415,7 @@ static struct proto_ops rose_proto_ops = { rose_shutdown, rose_setsockopt, rose_getsockopt, - rose_fcntl, + sock_no_fcntl, rose_sendmsg, rose_recvmsg }; @@ -1490,6 +1465,8 @@ void rose_proto_init(struct net_proto *pro) { int i; + rose_callsign = null_ax25_address; + sock_register(&rose_family_ops); register_netdevice_notifier(&rose_dev_notifier); printk(KERN_INFO "G4KLX Rose for Linux. Version 0.1 for AX25.035 Linux 2.1\n"); @@ -1537,6 +1514,9 @@ void cleanup_module(void) ax25_protocol_release(AX25_P_ROSE); ax25_linkfail_release(rose_link_failed); + if (ax25cmp(&rose_callsign, &null_ax25_address) != 0) + ax25_listen_release(&rose_callsign, NULL); + rose_unregister_sysctl(); unregister_netdevice_notifier(&rose_dev_notifier); diff --git a/net/rose/rose_dev.c b/net/rose/rose_dev.c index b21994894643..b13680e90585 100644 --- a/net/rose/rose_dev.c +++ b/net/rose/rose_dev.c @@ -81,7 +81,7 @@ static int rose_header(struct sk_buff *skb, struct device *dev, unsigned short t { unsigned char *buff = skb_push(skb, ROSE_MIN_LEN + 2); - *buff++ = GFI | Q_BIT; + *buff++ = ROSE_GFI | ROSE_Q_BIT; *buff++ = 0x00; *buff++ = ROSE_DATA; *buff++ = 0x7F; @@ -110,7 +110,7 @@ static int rose_rebuild_header(struct sk_buff *skb) return 1; } - if (skbn->sk != NULL) + if (skb->sk != NULL) skb_set_owner_w(skbn, skb->sk); kfree_skb(skb, FREE_WRITE); diff --git a/net/rose/rose_in.c b/net/rose/rose_in.c index a7d2c49d2258..e30d550b0a2a 100644 --- a/net/rose/rose_in.c +++ b/net/rose/rose_in.c @@ -56,7 +56,7 @@ static int rose_queue_rx_frame(struct sock *sk, struct sk_buff *skb, int more) skb_queue_tail(&sk->protinfo.rose->frag_queue, skb); return 0; } - + if (!more && sk->protinfo.rose->fraglen > 0) { /* End of fragment */ sk->protinfo.rose->fraglen += skb->len; skb_queue_tail(&sk->protinfo.rose->frag_queue, skb); @@ -190,9 +190,9 @@ static int rose_state3_machine(struct sock *sk, struct sk_buff *skb, int framety case ROSE_RR: case ROSE_RNR: if (frametype == ROSE_RNR) { - sk->protinfo.rose->condition |= PEER_RX_BUSY_CONDITION; + sk->protinfo.rose->condition |= ROSE_COND_PEER_RX_BUSY; } else { - sk->protinfo.rose->condition &= ~PEER_RX_BUSY_CONDITION; + sk->protinfo.rose->condition &= ~ROSE_COND_PEER_RX_BUSY; } if (!rose_validate_nr(sk, nr)) { rose_clear_queues(sk); @@ -205,16 +205,16 @@ static int rose_state3_machine(struct sock *sk, struct sk_buff *skb, int framety sk->protinfo.rose->state = ROSE_STATE_4; sk->protinfo.rose->timer = sk->protinfo.rose->t2; } else { - if (sk->protinfo.rose->condition & PEER_RX_BUSY_CONDITION) { - rose_frames_acked(sk, nr); + if (sk->protinfo.rose->condition & ROSE_COND_PEER_RX_BUSY) { + sk->protinfo.rose->va = nr; } else { rose_check_iframes_acked(sk, nr); } } break; - + case ROSE_DATA: /* XXX */ - sk->protinfo.rose->condition &= ~PEER_RX_BUSY_CONDITION; + sk->protinfo.rose->condition &= ~ROSE_COND_PEER_RX_BUSY; if (!rose_validate_nr(sk, nr)) { rose_clear_queues(sk); rose_write_internal(sk, ROSE_RESET_REQUEST); @@ -227,19 +227,19 @@ static int rose_state3_machine(struct sock *sk, struct sk_buff *skb, int framety sk->protinfo.rose->timer = sk->protinfo.rose->t2; break; } - if (sk->protinfo.rose->condition & PEER_RX_BUSY_CONDITION) { - rose_frames_acked(sk, nr); + if (sk->protinfo.rose->condition & ROSE_COND_PEER_RX_BUSY) { + sk->protinfo.rose->va = nr; } else { rose_check_iframes_acked(sk, nr); } - if (sk->protinfo.rose->condition & OWN_RX_BUSY_CONDITION) + if (sk->protinfo.rose->condition & ROSE_COND_OWN_RX_BUSY) break; if (ns == sk->protinfo.rose->vr) { if (rose_queue_rx_frame(sk, skb, m) == 0) { sk->protinfo.rose->vr = (sk->protinfo.rose->vr + 1) % ROSE_MODULUS; queued = 1; } else { - sk->protinfo.rose->condition |= OWN_RX_BUSY_CONDITION; + sk->protinfo.rose->condition |= ROSE_COND_OWN_RX_BUSY; } } /* @@ -247,11 +247,11 @@ static int rose_state3_machine(struct sock *sk, struct sk_buff *skb, int framety * acknowledge hold back timer. */ if (((sk->protinfo.rose->vl + ROSE_DEFAULT_WINDOW) % ROSE_MODULUS) == sk->protinfo.rose->vr) { - sk->protinfo.rose->condition &= ~ACK_PENDING_CONDITION; + sk->protinfo.rose->condition &= ~ROSE_COND_ACK_PENDING; sk->protinfo.rose->timer = 0; rose_enquiry_response(sk); } else { - sk->protinfo.rose->condition |= ACK_PENDING_CONDITION; + sk->protinfo.rose->condition |= ROSE_COND_ACK_PENDING; sk->protinfo.rose->timer = sk->protinfo.rose->hb; } break; @@ -309,7 +309,7 @@ static int rose_state4_machine(struct sock *sk, struct sk_buff *skb, int framety int rose_process_rx_frame(struct sock *sk, struct sk_buff *skb) { int queued = 0, frametype, ns, nr, q, d, m; - + if (sk->protinfo.rose->state == ROSE_STATE_0) return 0; diff --git a/net/rose/rose_link.c b/net/rose/rose_link.c index 4b1d63c4482a..bab651fc4f54 100644 --- a/net/rose/rose_link.c +++ b/net/rose/rose_link.c @@ -49,7 +49,7 @@ static void rose_link_timer(unsigned long); static void rose_link_set_timer(struct rose_neigh *neigh) { unsigned long flags; - + save_flags(flags); cli(); del_timer(&neigh->timer); @@ -66,7 +66,7 @@ static void rose_link_set_timer(struct rose_neigh *neigh) static void rose_link_reset_timer(struct rose_neigh *neigh) { unsigned long flags; - + save_flags(flags); cli(); del_timer(&neigh->timer); @@ -103,6 +103,40 @@ static void rose_link_timer(unsigned long param) rose_link_set_timer(neigh); } +/* + * Interface to ax25_send_frame. Changes my level 2 callsign depending + * on whether we have a global ROSE callsign or use the default port + * callsign. + */ +static int rose_send_frame(struct sk_buff *skb, struct rose_neigh *neigh) +{ + ax25_address *rose_call; + + if (ax25cmp(&rose_callsign, &null_ax25_address) == 0) + rose_call = (ax25_address *)neigh->dev->dev_addr; + else + rose_call = &rose_callsign; + + return ax25_send_frame(skb, rose_call, &neigh->callsign, neigh->digipeat, neigh->dev); +} + +/* + * Interface to ax25_link_up. Changes my level 2 callsign depending + * on whether we have a global ROSE callsign or use the default port + * callsign. + */ +static int rose_link_up(struct rose_neigh *neigh) +{ + ax25_address *rose_call; + + if (ax25cmp(&rose_callsign, &null_ax25_address) == 0) + rose_call = (ax25_address *)neigh->dev->dev_addr; + else + rose_call = &rose_callsign; + + return ax25_link_up(rose_call, &neigh->callsign, neigh->dev); +} + /* * This handles all restart and diagnostic frames. */ @@ -127,7 +161,7 @@ void rose_link_rx_restart(struct sk_buff *skb, struct rose_neigh *neigh, unsigne case ROSE_DIAGNOSTIC: printk(KERN_WARNING "rose: diagnostic #%d\n", skb->data[3]); break; - + default: printk(KERN_WARNING "rose: received unknown %02X with LCI 000\n", frametype); break; @@ -135,7 +169,7 @@ void rose_link_rx_restart(struct sk_buff *skb, struct rose_neigh *neigh, unsigne if (neigh->restarted) { while ((skbn = skb_dequeue(&neigh->queue)) != NULL) - if (!ax25_send_frame(skbn, (ax25_address *)neigh->dev->dev_addr, &neigh->callsign, neigh->digipeat, neigh->dev)) + if (!rose_send_frame(skbn, neigh)) kfree_skb(skbn, FREE_WRITE); } } @@ -159,7 +193,7 @@ void rose_transmit_restart_request(struct rose_neigh *neigh) dptr = skb_put(skb, ROSE_MIN_LEN + 3); *dptr++ = AX25_P_ROSE; - *dptr++ = GFI; + *dptr++ = ROSE_GFI; *dptr++ = 0x00; *dptr++ = ROSE_RESTART_REQUEST; *dptr++ = 0x00; @@ -167,7 +201,7 @@ void rose_transmit_restart_request(struct rose_neigh *neigh) skb->sk = NULL; - if (!ax25_send_frame(skb, (ax25_address *)neigh->dev->dev_addr, &neigh->callsign, neigh->digipeat, neigh->dev)) + if (!rose_send_frame(skb, neigh)) kfree_skb(skb, FREE_WRITE); } @@ -190,13 +224,13 @@ void rose_transmit_restart_confirmation(struct rose_neigh *neigh) dptr = skb_put(skb, ROSE_MIN_LEN + 1); *dptr++ = AX25_P_ROSE; - *dptr++ = GFI; + *dptr++ = ROSE_GFI; *dptr++ = 0x00; *dptr++ = ROSE_RESTART_CONFIRMATION; skb->sk = NULL; - if (!ax25_send_frame(skb, (ax25_address *)neigh->dev->dev_addr, &neigh->callsign, neigh->digipeat, neigh->dev)) + if (!rose_send_frame(skb, neigh)) kfree_skb(skb, FREE_WRITE); } @@ -219,14 +253,14 @@ void rose_transmit_diagnostic(struct rose_neigh *neigh, unsigned char diag) dptr = skb_put(skb, ROSE_MIN_LEN + 2); *dptr++ = AX25_P_ROSE; - *dptr++ = GFI; + *dptr++ = ROSE_GFI; *dptr++ = 0x00; *dptr++ = ROSE_DIAGNOSTIC; *dptr++ = diag; skb->sk = NULL; - if (!ax25_send_frame(skb, (ax25_address *)neigh->dev->dev_addr, &neigh->callsign, neigh->digipeat, neigh->dev)) + if (!rose_send_frame(skb, neigh)) kfree_skb(skb, FREE_WRITE); } @@ -250,7 +284,7 @@ void rose_transmit_clear_request(struct rose_neigh *neigh, unsigned int lci, uns dptr = skb_put(skb, ROSE_MIN_LEN + 3); *dptr++ = AX25_P_ROSE; - *dptr++ = ((lci >> 8) & 0x0F) | GFI; + *dptr++ = ((lci >> 8) & 0x0F) | ROSE_GFI; *dptr++ = ((lci >> 0) & 0xFF); *dptr++ = ROSE_CLEAR_REQUEST; *dptr++ = cause; @@ -258,7 +292,7 @@ void rose_transmit_clear_request(struct rose_neigh *neigh, unsigned int lci, uns skb->sk = NULL; - if (!ax25_send_frame(skb, (ax25_address *)neigh->dev->dev_addr, &neigh->callsign, neigh->digipeat, neigh->dev)) + if (!rose_send_frame(skb, neigh)) kfree_skb(skb, FREE_WRITE); } @@ -271,7 +305,7 @@ void rose_transmit_link(struct sk_buff *skb, struct rose_neigh *neigh) return; #endif - if (!ax25_link_up((ax25_address *)neigh->dev->dev_addr, &neigh->callsign, neigh->dev)) + if (!rose_link_up(neigh)) neigh->restarted = 0; dptr = skb_push(skb, 1); @@ -280,11 +314,11 @@ void rose_transmit_link(struct sk_buff *skb, struct rose_neigh *neigh) skb->arp = 1; if (neigh->restarted) { - if (!ax25_send_frame(skb, (ax25_address *)neigh->dev->dev_addr, &neigh->callsign, neigh->digipeat, neigh->dev)) + if (!rose_send_frame(skb, neigh)) kfree_skb(skb, FREE_WRITE); } else { skb_queue_tail(&neigh->queue, skb); - + if (neigh->t0timer == 0) { rose_transmit_restart_request(neigh); neigh->t0timer = neigh->t0; diff --git a/net/rose/rose_out.c b/net/rose/rose_out.c index b58edeb706a8..0ea18e522a12 100644 --- a/net/rose/rose_out.c +++ b/net/rose/rose_out.c @@ -76,11 +76,11 @@ void rose_output(struct sock *sk, struct sk_buff *skb) memcpy(skbn->data, header, ROSE_MIN_LEN); if (skb->len > 0) - skbn->data[2] |= M_BIT; - + skbn->data[2] |= ROSE_M_BIT; + skb_queue_tail(&sk->write_queue, skbn); /* Throw it on the queue */ } - + kfree_skb(skb, FREE_WRITE); } else { skb_queue_tail(&sk->write_queue, skb); /* Throw it on the queue */ @@ -107,56 +107,35 @@ static void rose_send_iframe(struct sock *sk, struct sk_buff *skb) void rose_kick(struct sock *sk) { - struct sk_buff *skb, *skbn; - int last = 1; - unsigned short start, end, next; + struct sk_buff *skb; + unsigned short end; del_timer(&sk->timer); - start = (skb_peek(&sk->protinfo.rose->ack_queue) == NULL) ? sk->protinfo.rose->va : sk->protinfo.rose->vs; - end = (sk->protinfo.rose->va + ROSE_DEFAULT_WINDOW) % ROSE_MODULUS; + end = (sk->protinfo.rose->va + ROSE_DEFAULT_WINDOW) % ROSE_MODULUS; - if (!(sk->protinfo.rose->condition & PEER_RX_BUSY_CONDITION) && - start != end && + if (!(sk->protinfo.rose->condition & ROSE_COND_PEER_RX_BUSY) && + sk->protinfo.rose->vs != end && skb_peek(&sk->write_queue) != NULL) { - - sk->protinfo.rose->vs = start; - /* * Transmit data until either we're out of data to send or * the window is full. */ - /* - * Dequeue the frame and copy it. - */ skb = skb_dequeue(&sk->write_queue); do { - if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) { - skb_queue_head(&sk->write_queue, skb); - break; - } - - next = (sk->protinfo.rose->vs + 1) % ROSE_MODULUS; - last = (next == end); - /* - * Transmit the frame copy. + * Transmit the frame. */ - rose_send_iframe(sk, skbn); - - sk->protinfo.rose->vs = next; + rose_send_iframe(sk, skb); - /* - * Requeue the original data frame. - */ - skb_queue_tail(&sk->protinfo.rose->ack_queue, skb); + sk->protinfo.rose->vs = (sk->protinfo.rose->vs + 1) % ROSE_MODULUS; - } while (!last && (skb = skb_dequeue(&sk->write_queue)) != NULL); + } while (sk->protinfo.rose->vs != end && (skb = skb_dequeue(&sk->write_queue)) != NULL); sk->protinfo.rose->vl = sk->protinfo.rose->vr; - sk->protinfo.rose->condition &= ~ACK_PENDING_CONDITION; + sk->protinfo.rose->condition &= ~ROSE_COND_ACK_PENDING; sk->protinfo.rose->timer = 0; } @@ -170,25 +149,24 @@ void rose_kick(struct sock *sk) void rose_enquiry_response(struct sock *sk) { - if (sk->protinfo.rose->condition & OWN_RX_BUSY_CONDITION) { + if (sk->protinfo.rose->condition & ROSE_COND_OWN_RX_BUSY) { rose_write_internal(sk, ROSE_RNR); } else { rose_write_internal(sk, ROSE_RR); } sk->protinfo.rose->vl = sk->protinfo.rose->vr; - sk->protinfo.rose->condition &= ~ACK_PENDING_CONDITION; + sk->protinfo.rose->condition &= ~ROSE_COND_ACK_PENDING; sk->protinfo.rose->timer = 0; } void rose_check_iframes_acked(struct sock *sk, unsigned short nr) { if (sk->protinfo.rose->vs == nr) { - rose_frames_acked(sk, nr); + sk->protinfo.rose->va = nr; } else { - if (sk->protinfo.rose->va != nr) { - rose_frames_acked(sk, nr); - } + if (sk->protinfo.rose->va != nr) + sk->protinfo.rose->va = nr; } } diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c index bc1073a9d81f..6ac59bcd8f91 100644 --- a/net/rose/rose_route.c +++ b/net/rose/rose_route.c @@ -17,7 +17,7 @@ * Terry(VK2KTJ) Added support for variable length * address masks. */ - + #include #if defined(CONFIG_ROSE) || defined(CONFIG_ROSE_MODULE) #include @@ -99,7 +99,7 @@ static int rose_add_node(struct rose_route_struct *rose_route, struct device *de for (i = 0; i < rose_route->ndigis; i++) rose_neigh->digipeat->calls[i] = rose_route->digipeaters[i]; } - + save_flags(flags); cli(); rose_neigh->next = rose_neigh_list; rose_neigh_list = rose_neigh; @@ -157,7 +157,7 @@ static int rose_add_node(struct rose_route_struct *rose_route, struct device *de } restore_flags(flags); - + rose_neigh->count++; return 0; @@ -169,7 +169,7 @@ static int rose_add_node(struct rose_route_struct *rose_route, struct device *de rose_node->neighbour[1] = rose_node->neighbour[0]; rose_node->neighbour[0] = rose_neigh; - + rose_node->count++; rose_neigh->count++; } @@ -213,10 +213,10 @@ static void rose_remove_neigh(struct rose_neigh *rose_neigh) struct sk_buff *skb; del_timer(&rose_neigh->timer); - + while ((skb = skb_dequeue(&rose_neigh->queue)) != NULL) kfree_skb(skb, FREE_WRITE); - + save_flags(flags); cli(); @@ -283,7 +283,7 @@ static int rose_del_node(struct rose_route_struct *rose_route, struct device *de struct rose_node *rose_node; struct rose_neigh *rose_neigh; int i; - + for (rose_node = rose_node_list; rose_node != NULL; rose_node = rose_node->next) if ((rose_node->mask == rose_route->mask) && (rosecmpm(&rose_route->address, &rose_node->address, rose_route->mask) == 0)) break; @@ -295,7 +295,7 @@ static int rose_del_node(struct rose_route_struct *rose_route, struct device *de break; if (rose_neigh == NULL) return -EINVAL; - + for (i = 0; i < rose_node->count; i++) { if (rose_node->neighbour[i] == rose_neigh) { rose_neigh->count--; @@ -304,7 +304,7 @@ static int rose_del_node(struct rose_route_struct *rose_route, struct device *de rose_remove_neigh(rose_neigh); rose_node->count--; - + if (rose_node->count == 0) { rose_remove_node(rose_node); } else { @@ -337,14 +337,14 @@ void rose_rt_device_down(struct device *dev) while (rose_neigh != NULL) { s = rose_neigh; rose_neigh = rose_neigh->next; - + if (s->dev == dev) { rose_node = rose_node_list; while (rose_node != NULL) { t = rose_node; rose_node = rose_node->next; - + for (i = 0; i < t->count; i++) { if (t->neighbour[i] == s) { t->count--; @@ -359,11 +359,11 @@ void rose_rt_device_down(struct device *dev) } } } - + if (t->count <= 0) rose_remove_node(t); } - + rose_remove_neigh(s); } } @@ -379,7 +379,7 @@ void rose_route_device_down(struct device *dev) while (rose_route != NULL) { s = rose_route; rose_route = rose_route->next; - + if (s->neigh1->dev == dev || s->neigh2->dev == dev) rose_remove_route(s); } @@ -442,9 +442,9 @@ struct rose_neigh *rose_get_neigh(rose_address *addr) break; if (node == NULL) return NULL; - + if (node->which >= node->count) return NULL; - + return node->neighbour[node->which]; } @@ -509,7 +509,7 @@ void rose_link_failed(ax25_address *callsign, struct device *dev) while ((skb = skb_dequeue(&rose_neigh->queue)) != NULL) kfree_skb(skb, FREE_WRITE); - + for (rose_node = rose_node_list; rose_node != NULL; rose_node = rose_node->next) if (rose_node->which < rose_node->count && rose_node->neighbour[rose_node->which] == rose_neigh) rose_node->which++; @@ -748,8 +748,8 @@ int rose_neigh_get_info(char *buffer, char **start, off_t offset, rose_neigh->dev ? rose_neigh->dev->name : "???", rose_neigh->count, (rose_neigh->restarted) ? "yes" : "no", - rose_neigh->t0timer / PR_SLOWHZ, - rose_neigh->t0 / PR_SLOWHZ); + rose_neigh->t0timer / ROSE_SLOWHZ, + rose_neigh->t0 / ROSE_SLOWHZ); pos = begin + len; @@ -757,7 +757,7 @@ int rose_neigh_get_info(char *buffer, char **start, off_t offset, len = 0; begin = pos; } - + if (pos > offset + length) break; } @@ -800,7 +800,7 @@ int rose_routes_get_info(char *buffer, char **start, off_t offset, len = 0; begin = pos; } - + if (pos > offset + length) break; } @@ -829,21 +829,21 @@ void rose_rt_free(void) while (rose_neigh != NULL) { s = rose_neigh; rose_neigh = rose_neigh->next; - + rose_remove_neigh(s); } while (rose_node != NULL) { t = rose_node; rose_node = rose_node->next; - + rose_remove_node(t); } while (rose_route != NULL) { u = rose_route; rose_route = rose_route->next; - + rose_remove_route(u); } } diff --git a/net/rose/rose_subr.c b/net/rose/rose_subr.c index 8a166f3aef74..5befcbb60170 100644 --- a/net/rose/rose_subr.c +++ b/net/rose/rose_subr.c @@ -15,7 +15,7 @@ * History * Rose 001 Jonathan(G4KLX) Cloned from nr_subr.c */ - + #include #if defined(CONFIG_ROSE) || defined(CONFIG_ROSE_MODULE) #include @@ -47,59 +47,11 @@ void rose_clear_queues(struct sock *sk) { struct sk_buff *skb; - while ((skb = skb_dequeue(&sk->write_queue)) != NULL) { - skb->sk = sk; - kfree_skb(skb, FREE_WRITE); - } - - while ((skb = skb_dequeue(&sk->protinfo.rose->ack_queue)) != NULL) { - skb->sk = sk; + while ((skb = skb_dequeue(&sk->write_queue)) != NULL) kfree_skb(skb, FREE_WRITE); - } - while ((skb = skb_dequeue(&sk->protinfo.rose->frag_queue)) != NULL) { + while ((skb = skb_dequeue(&sk->protinfo.rose->frag_queue)) != NULL) kfree_skb(skb, FREE_READ); - } -} - -/* - * This routine purges the input queue of those frames that have been - * acknowledged. This replaces the boxes labelled "V(a) <- N(r)" on the - * SDL diagram. - */ -void rose_frames_acked(struct sock *sk, unsigned short nr) -{ - struct sk_buff *skb; - - /* - * Remove all the ack-ed frames from the ack queue. - */ - if (sk->protinfo.rose->va != nr) { - while (skb_peek(&sk->protinfo.rose->ack_queue) != NULL && sk->protinfo.rose->va != nr) { - skb = skb_dequeue(&sk->protinfo.rose->ack_queue); - skb->sk = sk; - kfree_skb(skb, FREE_WRITE); - sk->protinfo.rose->va = (sk->protinfo.rose->va + 1) % ROSE_MODULUS; - } - } -} - -/* - * Requeue all the un-ack-ed frames on the output queue to be picked - * up by rose_kick called from the timer. This arrangement handles the - * possibility of an empty output queue. - */ -void rose_requeue_frames(struct sock *sk) -{ - struct sk_buff *skb, *skb_prev = NULL; - - while ((skb = skb_dequeue(&sk->protinfo.rose->ack_queue)) != NULL) { - if (skb_prev == NULL) - skb_queue_head(&sk->write_queue, skb); - else - skb_append(skb_prev, skb); - skb_prev = skb; - } } /* @@ -114,7 +66,7 @@ int rose_validate_nr(struct sock *sk, unsigned short nr) if (nr == vc) return 1; vc = (vc + 1) % ROSE_MODULUS; } - + if (nr == sk->protinfo.rose->vs) return 1; return 0; @@ -133,7 +85,7 @@ void rose_write_internal(struct sock *sk, int frametype) int len, faclen = 0; len = AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + ROSE_MIN_LEN + 1; - + switch (frametype) { case ROSE_CALL_REQUEST: len += 1 + ROSE_ADDR_LEN + ROSE_ADDR_LEN; @@ -150,7 +102,7 @@ void rose_write_internal(struct sock *sk, int frametype) len += 1; break; } - + if ((skb = alloc_skb(len, GFP_ATOMIC)) == NULL) return; @@ -165,9 +117,9 @@ void rose_write_internal(struct sock *sk, int frametype) lci2 = (sk->protinfo.rose->lci >> 0) & 0xFF; switch (frametype) { - + case ROSE_CALL_REQUEST: - *dptr++ = GFI | lci1; + *dptr++ = ROSE_GFI | lci1; *dptr++ = lci2; *dptr++ = frametype; *dptr++ = 0xAA; @@ -180,7 +132,7 @@ void rose_write_internal(struct sock *sk, int frametype) break; case ROSE_CALL_ACCEPTED: - *dptr++ = GFI | lci1; + *dptr++ = ROSE_GFI | lci1; *dptr++ = lci2; *dptr++ = frametype; *dptr++ = 0x00; /* Address length */ @@ -189,7 +141,7 @@ void rose_write_internal(struct sock *sk, int frametype) case ROSE_CLEAR_REQUEST: case ROSE_RESET_REQUEST: - *dptr++ = GFI | lci1; + *dptr++ = ROSE_GFI | lci1; *dptr++ = lci2; *dptr++ = frametype; *dptr++ = 0x00; /* XXX */ @@ -197,7 +149,7 @@ void rose_write_internal(struct sock *sk, int frametype) break; case ROSE_INTERRUPT: - *dptr++ = GFI | lci1; + *dptr++ = ROSE_GFI | lci1; *dptr++ = lci2; *dptr++ = frametype; *dptr++ = 0x00; /* XXX */ @@ -206,16 +158,16 @@ void rose_write_internal(struct sock *sk, int frametype) case ROSE_RR: case ROSE_RNR: case ROSE_REJ: - *dptr++ = GFI | lci1; + *dptr++ = ROSE_GFI | lci1; *dptr++ = lci2; *dptr = frametype; *dptr++ |= (sk->protinfo.rose->vr << 5) & 0xE0; break; - + case ROSE_CLEAR_CONFIRMATION: case ROSE_INTERRUPT_CONFIRMATION: case ROSE_RESET_CONFIRMATION: - *dptr++ = GFI | lci1; + *dptr++ = ROSE_GFI | lci1; *dptr++ = lci2; *dptr++ = frametype; break; @@ -232,11 +184,11 @@ void rose_write_internal(struct sock *sk, int frametype) int rose_decode(struct sk_buff *skb, int *ns, int *nr, int *q, int *d, int *m) { unsigned char *frame; - + frame = skb->data; - + *ns = *nr = *q = *d = *m = 0; - + switch (frame[2]) { case ROSE_CALL_REQUEST: case ROSE_CALL_ACCEPTED: @@ -264,14 +216,14 @@ int rose_decode(struct sk_buff *skb, int *ns, int *nr, int *q, int *d, int *m) } if ((frame[2] & 0x01) == ROSE_DATA) { - *q = (frame[0] & Q_BIT) == Q_BIT; - *d = (frame[0] & D_BIT) == D_BIT; - *m = (frame[2] & M_BIT) == M_BIT; + *q = (frame[0] & ROSE_Q_BIT) == ROSE_Q_BIT; + *d = (frame[0] & ROSE_D_BIT) == ROSE_D_BIT; + *m = (frame[2] & ROSE_M_BIT) == ROSE_M_BIT; *nr = (frame[2] >> 5) & 0x07; *ns = (frame[2] >> 1) & 0x07; return ROSE_DATA; } - + return ROSE_ILLEGAL; } @@ -286,7 +238,7 @@ static int rose_parse_national(unsigned char *p, rose_cb *rose, int len) n += 2; len -= 2; break; - + case 0x40: if (*p == FAC_NATIONAL_RAND) rose->rand = ((p[1] << 8) & 0xFF00) + ((p[2] << 0) & 0x00FF); @@ -300,7 +252,7 @@ static int rose_parse_national(unsigned char *p, rose_cb *rose, int len) n += 4; len -= 4; break; - + case 0xC0: l = p[1]; if (*p == FAC_NATIONAL_DEST_DIGI) { @@ -333,7 +285,7 @@ static int rose_parse_ccitt(unsigned char *p, rose_cb *rose, int len) n += 2; len -= 2; break; - + case 0x40: p += 3; n += 3; @@ -345,7 +297,7 @@ static int rose_parse_ccitt(unsigned char *p, rose_cb *rose, int len) n += 4; len -= 4; break; - + case 0xC0: l = p[1]; if (*p == FAC_CCITT_DEST_NSAP) { @@ -383,7 +335,7 @@ int rose_parse_facilities(struct sk_buff *skb, rose_cb *rose) p = skb->data + len + 4; facilities_len = *p++; - + if (facilities_len == 0) return 0; @@ -398,13 +350,13 @@ int rose_parse_facilities(struct sk_buff *skb, rose_cb *rose) facilities_len -= len + 1; p += len + 1; break; - + case FAC_CCITT: /* CCITT */ len = rose_parse_ccitt(p + 1, rose, facilities_len - 1); facilities_len -= len + 1; p += len + 1; break; - + default: printk(KERN_DEBUG "rose_parse_facilities: unknown facilities family %02X\n", *p); facilities_len--; @@ -422,7 +374,7 @@ int rose_create_facilities(unsigned char *buffer, rose_cb *rose) unsigned char *p = buffer + 1; char *callsign; int len; - + /* National Facilities */ if (rose->rand != 0 || rose->source_ndigis == 1 || rose->dest_ndigis == 1) { *p++ = 0x00; @@ -433,7 +385,7 @@ int rose_create_facilities(unsigned char *buffer, rose_cb *rose) *p++ = (rose->rand >> 8) & 0xFF; *p++ = (rose->rand >> 0) & 0xFF; } - + if (rose->source_ndigis == 1) { *p++ = FAC_NATIONAL_SRC_DIGI; *p++ = AX25_ADDR_LEN; @@ -451,9 +403,9 @@ int rose_create_facilities(unsigned char *buffer, rose_cb *rose) *p++ = 0x00; *p++ = FAC_CCITT; - + *p++ = FAC_CCITT_DEST_NSAP; - + callsign = ax2asc(&rose->dest_call); *p++ = strlen(callsign) + 10; @@ -466,7 +418,7 @@ int rose_create_facilities(unsigned char *buffer, rose_cb *rose) memcpy(p, callsign, strlen(callsign)); p += strlen(callsign); - + *p++ = FAC_CCITT_SRC_NSAP; callsign = ax2asc(&rose->source_call); @@ -484,7 +436,7 @@ int rose_create_facilities(unsigned char *buffer, rose_cb *rose) len = p - buffer; buffer[0] = len - 1; - + return len; } diff --git a/net/rose/rose_timer.c b/net/rose/rose_timer.c index e56f9edb1ede..77ebabb1e1ff 100644 --- a/net/rose/rose_timer.c +++ b/net/rose/rose_timer.c @@ -48,7 +48,7 @@ static void rose_timer(unsigned long); void rose_set_timer(struct sock *sk) { unsigned long flags; - + save_flags(flags); cli(); del_timer(&sk->timer); @@ -65,7 +65,7 @@ void rose_set_timer(struct sock *sk) static void rose_reset_timer(struct sock *sk) { unsigned long flags; - + save_flags(flags); cli(); del_timer(&sk->timer); @@ -102,9 +102,9 @@ static void rose_timer(unsigned long param) /* * Check for the state of the receive buffer. */ - if (sk->rmem_alloc < (sk->rcvbuf / 2) && (sk->protinfo.rose->condition & OWN_RX_BUSY_CONDITION)) { - sk->protinfo.rose->condition &= ~OWN_RX_BUSY_CONDITION; - sk->protinfo.rose->condition &= ~ACK_PENDING_CONDITION; + if (sk->rmem_alloc < (sk->rcvbuf / 2) && (sk->protinfo.rose->condition & ROSE_COND_OWN_RX_BUSY)) { + sk->protinfo.rose->condition &= ~ROSE_COND_OWN_RX_BUSY; + sk->protinfo.rose->condition &= ~ROSE_COND_ACK_PENDING; sk->protinfo.rose->vl = sk->protinfo.rose->vr; sk->protinfo.rose->timer = 0; rose_write_internal(sk, ROSE_RR); @@ -131,8 +131,8 @@ static void rose_timer(unsigned long param) */ switch (sk->protinfo.rose->state) { case ROSE_STATE_3: /* HB */ - if (sk->protinfo.rose->condition & ACK_PENDING_CONDITION) { - sk->protinfo.rose->condition &= ~ACK_PENDING_CONDITION; + if (sk->protinfo.rose->condition & ROSE_COND_ACK_PENDING) { + sk->protinfo.rose->condition &= ~ROSE_COND_ACK_PENDING; rose_enquiry_response(sk); } break; diff --git a/net/rose/sysctl_net_rose.c b/net/rose/sysctl_net_rose.c index 6db89e155d45..95234881756f 100644 --- a/net/rose/sysctl_net_rose.c +++ b/net/rose/sysctl_net_rose.c @@ -10,12 +10,12 @@ #include #include -static int min_timer[] = {1 * PR_SLOWHZ}; -static int max_timer[] = {300 * PR_SLOWHZ}; -static int min_idle[] = {0 * PR_SLOWHZ}; -static int max_idle[] = {65535 * PR_SLOWHZ}; +static int min_timer[] = {1 * ROSE_SLOWHZ}; +static int max_timer[] = {300 * ROSE_SLOWHZ}; +static int min_idle[] = {0 * ROSE_SLOWHZ}; +static int max_idle[] = {65535 * ROSE_SLOWHZ}; static int min_route[] = {0}; -static int max_route[] = {0}; +static int max_route[] = {1}; static struct ctl_table_header *rose_table_header; diff --git a/net/socket.c b/net/socket.c index 591f3d7015b3..bb2ca9088194 100644 --- a/net/socket.c +++ b/net/socket.c @@ -554,32 +554,18 @@ int sock_wake_async(struct socket *sock, int how) } -/* - * Perform the socket system call. we locate the appropriate - * family, then create a fresh socket. - */ - -static int find_protocol_family(int family) -{ - register int i; - for (i = 0; i < NPROTO; i++) - { - if (net_families[i] == NULL) - continue; - if (net_families[i]->family == family) - return i; - } - return -1; -} - asmlinkage int sys_socket(int family, int type, int protocol) { int i, fd; struct socket *sock; - /* Locate the correct protocol family. */ - i = find_protocol_family(family); - + /* + * Check protocol is in range + */ + + if(family<0||family>=NPROTO) + return -EINVAL; + #if defined(CONFIG_KERNELD) && defined(CONFIG_NET) /* Attempt to load a protocol module if the find failed. * @@ -587,16 +573,15 @@ asmlinkage int sys_socket(int family, int type, int protocol) * requested real, full-featured networking support upon configuration. * Otherwise module support will break! */ - if (i < 0) + if (net_families[family]==NULL) { char module_name[30]; sprintf(module_name,"net-pf-%d",family); request_module(module_name); - i = find_protocol_family(family); } #endif - if (i < 0) + if (net_families[family]==NULL) return -EINVAL; /* @@ -625,7 +610,7 @@ asmlinkage int sys_socket(int family, int type, int protocol) sock->type = type; - if ((i = net_families[i]->create(sock, protocol)) < 0) + if ((i = net_families[family]->create(sock, protocol)) < 0) { sock_release(sock); return(i); @@ -1121,8 +1106,8 @@ asmlinkage int sys_sendmsg(int fd, struct msghdr *msg, unsigned flags) struct socket *sock; char address[MAX_SOCK_ADDR]; struct iovec iov[UIO_FASTIOV]; + unsigned char ctl[sizeof(struct cmsghdr) + 20]; /* 20 is size of ipv6_pktinfo */ struct msghdr msg_sys; - void * krn_msg_ctl = NULL; int err; int total_len; @@ -1133,7 +1118,7 @@ asmlinkage int sys_sendmsg(int fd, struct msghdr *msg, unsigned flags) return -EOPNOTSUPP; if (copy_from_user(&msg_sys,msg,sizeof(struct msghdr))) - return -EFAULT; + return -EFAULT; /* do not move before msg_sys is valid */ if (msg_sys.msg_iovlen>UIO_MAXIOV) @@ -1145,23 +1130,21 @@ asmlinkage int sys_sendmsg(int fd, struct msghdr *msg, unsigned flags) return err; total_len=err; - if (msg_sys.msg_control==NULL) - msg_sys.msg_controllen = 0; - - if (msg_sys.msg_controllen) - { - krn_msg_ctl = kmalloc(msg_sys.msg_controllen, GFP_KERNEL); - - if (!krn_msg_ctl) - { - err = -ENOBUFS; - goto flush_it; - } - err = copy_from_user(krn_msg_ctl, msg_sys.msg_control, - msg_sys.msg_controllen); + if (msg_sys.msg_controllen) { + if (msg_sys.msg_controllen > sizeof(ctl)) { + char *tmp = kmalloc(msg_sys.msg_controllen, GFP_KERNEL); + if (tmp == NULL) { + err = -ENOBUFS; + goto failed2; + } + err = copy_from_user(tmp, msg_sys.msg_control, msg_sys.msg_controllen); + msg_sys.msg_control = tmp; + } else { + err = copy_from_user(ctl, msg_sys.msg_control, msg_sys.msg_controllen); + msg_sys.msg_control = ctl; + } if (err) - goto flush_it; - msg_sys.msg_control = krn_msg_ctl; + goto failed; } msg_sys.msg_flags = flags; @@ -1170,15 +1153,12 @@ asmlinkage int sys_sendmsg(int fd, struct msghdr *msg, unsigned flags) err = sock_sendmsg(sock, &msg_sys, total_len); -flush_it: +failed: + if (msg_sys.msg_controllen && msg_sys.msg_control != ctl) + kfree(msg_sys.msg_control); +failed2: if (msg_sys.msg_iov != iov) - kfree(iov); - - if (krn_msg_ctl) - { - kfree(krn_msg_ctl); - } - + kfree(msg_sys.msg_iov); return err; } @@ -1192,8 +1172,7 @@ asmlinkage int sys_recvmsg(int fd, struct msghdr *msg, unsigned int flags) struct iovec iovstack[UIO_FASTIOV]; struct iovec *iov=iovstack; struct msghdr msg_sys; - void * krn_msg_ctl = NULL; - void * usr_msg_ctl = NULL; + unsigned long cmsg_ptr; int err; int total_len; int len = 0; @@ -1227,79 +1206,27 @@ asmlinkage int sys_recvmsg(int fd, struct msghdr *msg, unsigned int flags) total_len=err; + cmsg_ptr = (unsigned long)msg_sys.msg_control; msg_sys.msg_flags = 0; - if (msg_sys.msg_control==NULL) - msg_sys.msg_controllen = 0; - - if (msg_sys.msg_controllen) - { - /* - * FIXME: - * I'm assuming that the kernel may have to examine - * the acciliary control messages passed by the user. - * Find out what POSIX says about this... - */ - krn_msg_ctl = kmalloc(msg_sys.msg_controllen, GFP_KERNEL); - - if (!krn_msg_ctl) - { - err=-ENOBUFS; - goto flush_it; - } - err = copy_from_user(krn_msg_ctl, msg_sys.msg_control, - msg_sys.msg_controllen); - if (err) - { - err = -EFAULT; - goto flush_it; - } - usr_msg_ctl = msg_sys.msg_control; - msg_sys.msg_control = krn_msg_ctl; - } - if (current->files->fd[fd]->f_flags&O_NONBLOCK) flags |= MSG_DONTWAIT; - len=sock_recvmsg(sock, &msg_sys, total_len, flags); if (msg_sys.msg_iov != iov) - kfree(iov); + kfree(msg_sys.msg_iov); if (len<0) - { - err=len; - goto flush_it; - } - - if (uaddr != NULL) - { - err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr, - uaddr_len); - } - - if (err >= 0 && msg_sys.msg_controllen) - { - err = copy_to_user(usr_msg_ctl, krn_msg_ctl, - msg_sys.msg_controllen); - } - -flush_it: - if (msg_sys.msg_iov != iov) - kfree(iov); + return len; - if (krn_msg_ctl) + if (uaddr != NULL) { - kfree(krn_msg_ctl); + err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr, uaddr_len); + if (err) + return err; } - - if (err < 0) - return err; - if (put_user(msg_sys.msg_flags, &msg->msg_flags)) return -EFAULT; - - if (put_user(msg_sys.msg_controllen, &msg->msg_controllen)) + if (put_user((unsigned long)msg_sys.msg_control-cmsg_ptr, &msg->msg_controllen)) return -EFAULT; - return len; } @@ -1431,19 +1358,8 @@ asmlinkage int sys_socketcall(int call, unsigned long *args) int sock_register(struct net_proto_family *ops) { - int i; - - cli(); - for(i = 0; i < NPROTO; i++) - { - if (net_families[i] != NULL) - continue; - net_families[i] = ops; - sti(); - return(i); - } - sti(); - return(-ENOMEM); + net_families[ops->family]=ops; + return 0; } /* @@ -1454,22 +1370,8 @@ int sock_register(struct net_proto_family *ops) int sock_unregister(int family) { - int i; - - cli(); - for(i = 0; i < NPROTO; i++) - { - if (net_families[i] == NULL) - continue; - if (net_families[i]->family == family) - { - net_families[i]=NULL; - sti(); - return(i); - } - } - sti(); - return(-ENOENT); + net_families[family]=NULL; + return 0; } void proto_init(void) diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 450396b0a380..9490c29030b0 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -3,11 +3,6 @@ * * Authors: Alan Cox, * - * Currently this contains all but the file descriptor passing code. - * Before that goes in the odd bugs in the iovec handlers need - * fixing, and this bit testing. BSD fd passing is not a trivial part - * of the exercise it turns out. Anyone like writing garbage collectors. - * * 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 @@ -298,11 +293,6 @@ static void unix_destroy_socket(unix_socket *sk) } } -static int unix_fcntl(struct socket *sock, unsigned int cmd, unsigned long arg) -{ - return -EINVAL; -} - static int unix_listen(struct socket *sock, int backlog) { struct sock *sk = sock->sk; @@ -321,30 +311,6 @@ static int unix_listen(struct socket *sock, int backlog) return 0; } -static void def_callback1(struct sock *sk) -{ - if(!sk->dead) - wake_up_interruptible(sk->sleep); -} - -static void def_callback2(struct sock *sk, int len) -{ - if(!sk->dead) - { - wake_up_interruptible(sk->sleep); - sock_wake_async(sk->socket, 1); - } -} - -static void def_callback3(struct sock *sk) -{ - if(!sk->dead) - { - wake_up_interruptible(sk->sleep); - sock_wake_async(sk->socket, 2); - } -} - extern struct proto_ops unix_stream_ops; extern struct proto_ops unix_dgram_ops; @@ -377,33 +343,13 @@ static int unix_create(struct socket *sock, int protocol) sk = sk_alloc(GFP_KERNEL); if (!sk) return -ENOMEM; - sock->sk = sk; - sk->type = sock->type; - sk->socket=sock; - sk->sleep= &sock->wait; - - sk->peercred.pid = 0; - sk->peercred.uid = -1; - sk->peercred.gid = -1; + + sock_init_data(sock,sk); - init_timer(&sk->timer); - skb_queue_head_init(&sk->write_queue); - skb_queue_head_init(&sk->receive_queue); - skb_queue_head_init(&sk->error_queue); - skb_queue_head_init(&sk->back_log); sk->protinfo.af_unix.family=AF_UNIX; sk->protinfo.af_unix.inode=NULL; sk->users=1; /* Us */ sk->protinfo.af_unix.readsem=MUTEX; /* single task reading lock */ - sk->rcvbuf=SK_RMEM_MAX; - sk->sndbuf=SK_WMEM_MAX; - sk->allocation=GFP_KERNEL; - sk->state=TCP_CLOSE; - sk->priority=SOPRI_NORMAL; - sk->state_change=def_callback1; - sk->data_ready=def_callback2; - sk->write_space=def_callback3; - sk->error_report=def_callback1; sk->mtu=4096; sk->protinfo.af_unix.list=&unix_sockets_unbound; unix_insert_socket(sk); @@ -1489,7 +1435,7 @@ struct proto_ops unix_stream_ops = { unix_shutdown, NULL, NULL, - unix_fcntl, + sock_no_fcntl, unix_stream_sendmsg, unix_stream_recvmsg }; @@ -1510,7 +1456,7 @@ struct proto_ops unix_dgram_ops = { unix_shutdown, NULL, NULL, - unix_fcntl, + sock_no_fcntl, unix_dgram_sendmsg, unix_dgram_recvmsg }; diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index 843ca54a337d..e66c01a5ea9a 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c @@ -15,7 +15,7 @@ * History * X.25 001 Jonathan Naylor Started coding. */ - + #include #if defined(CONFIG_X25) || defined(CONFIG_X25_MODULE) #include @@ -107,9 +107,9 @@ int x25_addr_aton(unsigned char *p, x25_address *called_addr, x25_address *calli called_len = strlen(called); calling_len = strlen(calling); - + *p++ = (calling_len << 4) | (called_len << 0); - + for (i = 0; i < (called_len + calling_len); i++) { if (i < called_len) { if (i % 2 != 0) { @@ -129,16 +129,38 @@ int x25_addr_aton(unsigned char *p, x25_address *called_addr, x25_address *calli } } } - + return 1 + (called_len + calling_len + 1) / 2; } /* * Socket removal during an interrupt is now safe. */ -extern inline void x25_remove_socket(struct sock *sk) +static void x25_remove_socket(struct sock *sk) { - sklist_remove_socket(&x25_list,sk); + struct sock *s; + unsigned long flags; + + save_flags(flags); + cli(); + + if ((s = x25_list) == sk) { + x25_list = s->next; + restore_flags(flags); + return; + } + + while (s != NULL && s->next != NULL) { + if (s->next == sk) { + s->next = sk->next; + restore_flags(flags); + return; + } + + s = s->next; + } + + restore_flags(flags); } /* @@ -147,7 +169,7 @@ extern inline void x25_remove_socket(struct sock *sk) static void x25_kill_by_device(struct device *dev) { struct sock *s; - + for (s = x25_list; s != NULL; s = s->next) { if (s->protinfo.x25->neighbour->dev == dev) { s->protinfo.x25->state = X25_STATE_0; @@ -190,10 +212,17 @@ static int x25_device_event(struct notifier_block *this, unsigned long event, vo /* * Add a socket to the bound sockets list. */ - -extern inline void x25_insert_socket(struct sock *sk) +static void x25_insert_socket(struct sock *sk) { - sklist_insert_socket(&x25_list,sk); + unsigned long flags; + + save_flags(flags); + cli(); + + sk->next = x25_list; + x25_list = sk; + + restore_flags(flags); } /* @@ -263,7 +292,7 @@ unsigned int x25_new_lci(void) void x25_destroy_socket(struct sock *); /* - * Handler for deferred kills. + * handler for deferred kills. */ static void x25_destroy_timer(unsigned long data) { @@ -280,15 +309,15 @@ void x25_destroy_socket(struct sock *sk) /* Not static as it's used by the timer { struct sk_buff *skb; unsigned long flags; - + save_flags(flags); cli(); - + del_timer(&sk->timer); - + x25_remove_socket(sk); x25_clear_queues(sk); /* Flush the queues */ - + while ((skb = skb_dequeue(&sk->receive_queue)) != NULL) { if (skb->sk != sk) { /* A pending connection */ skb->sk->dead = 1; /* Queue the unaccepted socket for death */ @@ -298,8 +327,8 @@ void x25_destroy_socket(struct sock *sk) /* Not static as it's used by the timer kfree_skb(skb, FREE_READ); } - - if (sk->wmem_alloc || sk->rmem_alloc) { /* Defer: outstanding buffers */ + + if (sk->wmem_alloc || sk->rmem_alloc) { /* Defer: outstanding buffers */ init_timer(&sk->timer); sk->timer.expires = jiffies + 10 * HZ; sk->timer.function = x25_destroy_timer; @@ -318,20 +347,13 @@ void x25_destroy_socket(struct sock *sk) /* Not static as it's used by the timer * Handling for system calls applied via the various interfaces to a * X.25 socket object. */ - -static int x25_fcntl(struct socket *sock, unsigned int cmd, unsigned long arg) -{ - return -EINVAL; -} static int x25_setsockopt(struct socket *sock, int level, int optname, char *optval, int optlen) { - struct sock *sk; + struct sock *sk = sock->sk; int err, opt; - sk = (struct sock *)sock->sk; - if (level != SOL_X25) return -EOPNOTSUPP; @@ -342,49 +364,12 @@ static int x25_setsockopt(struct socket *sock, int level, int optname, return err; get_user(opt, (int *)optval); - + switch (optname) { case X25_QBITINCL: sk->protinfo.x25->qbitincl = opt ? 1 : 0; return 0; - case X25_PACKET_SIZE: - if (sk->state != TCP_LISTEN) - return -EINVAL; - if (opt < X25_PS16 || opt > X25_PS4096) - return -EINVAL; - sk->protinfo.x25->facilities.packet_size = opt; - return 0; - - case X25_WINDOW_SIZE: - if (sk->state != TCP_LISTEN) - return -EINVAL; - if (sk->protinfo.x25->neighbour->extended) { - if (opt < 1 || opt > 127) - return -EINVAL; - } else { - if (opt < 1 || opt > 7) - return -EINVAL; - } - sk->protinfo.x25->facilities.window_size = opt; - return 0; - - case X25_THROUGHPUT_SPEED: - if (sk->state != TCP_LISTEN) - return -EINVAL; - if (opt < 0x03 || opt > 0x2C) - return -EINVAL; - sk->protinfo.x25->facilities.throughput = opt; - return 0; - - case X25_REVERSE_CHARGE: - if (sk->state != TCP_LISTEN) - return -EINVAL; - if (opt != 0 && opt != 1) - return -EINVAL; - sk->protinfo.x25->facilities.reverse = opt; - return 0; - default: return -ENOPROTOOPT; } @@ -393,36 +378,18 @@ static int x25_setsockopt(struct socket *sock, int level, int optname, static int x25_getsockopt(struct socket *sock, int level, int optname, char *optval, int *optlen) { - struct sock *sk; + struct sock *sk = sock->sk; int val = 0; int err; - sk = (struct sock *)sock->sk; - if (level != SOL_X25) return -EOPNOTSUPP; - + switch (optname) { case X25_QBITINCL: val = sk->protinfo.x25->qbitincl; break; - case X25_PACKET_SIZE: - val = sk->protinfo.x25->facilities.packet_size; - break; - - case X25_WINDOW_SIZE: - val = sk->protinfo.x25->facilities.window_size; - break; - - case X25_THROUGHPUT_SPEED: - val = sk->protinfo.x25->facilities.throughput; - break; - - case X25_REVERSE_CHARGE: - val = sk->protinfo.x25->facilities.reverse; - break; - default: return -ENOPROTOOPT; } @@ -442,7 +409,7 @@ static int x25_getsockopt(struct socket *sock, int level, int optname, static int x25_listen(struct socket *sock, int backlog) { - struct sock *sk = (struct sock *)sock->sk; + struct sock *sk = sock->sk; if (sk->state != TCP_LISTEN) { memset(&sk->protinfo.x25->dest_addr, '\0', X25_ADDR_LEN); @@ -462,8 +429,18 @@ static void def_callback1(struct sock *sk) static void def_callback2(struct sock *sk, int len) { - if (!sk->dead) + if (!sk->dead) { wake_up_interruptible(sk->sleep); + sock_wake_async(sk->socket, 1); + } +} + +static void def_callback3(struct sock *sk) +{ + if (!sk->dead) { + wake_up_interruptible(sk->sleep); + sock_wake_async(sk->socket, 2); + } } static struct sock *x25_alloc_socket(void) @@ -494,12 +471,12 @@ static struct sock *x25_alloc_socket(void) sk->state_change = def_callback1; sk->data_ready = def_callback2; - sk->write_space = def_callback1; + sk->write_space = def_callback3; sk->error_report = def_callback1; - skb_queue_head_init(&x25->ack_queue); skb_queue_head_init(&x25->fragment_queue); - skb_queue_head_init(&x25->interrupt_queue); + skb_queue_head_init(&x25->interrupt_in_queue); + skb_queue_head_init(&x25->interrupt_out_queue); return sk; } @@ -542,8 +519,10 @@ static int x25_create(struct socket *sock, int protocol) x25->state = X25_STATE_0; - x25->facilities.window_size = X25_DEFAULT_WINDOW_SIZE; - x25->facilities.packet_size = X25_DEFAULT_PACKET_SIZE; + x25->facilities.winsize_in = X25_DEFAULT_WINDOW_SIZE; + x25->facilities.winsize_out = X25_DEFAULT_WINDOW_SIZE; + x25->facilities.pacsize_in = X25_DEFAULT_PACKET_SIZE; + x25->facilities.pacsize_out = X25_DEFAULT_PACKET_SIZE; x25->facilities.throughput = X25_DEFAULT_THROUGHPUT; x25->facilities.reverse = X25_DEFAULT_REVERSE; @@ -589,14 +568,17 @@ static struct sock *x25_make_new(struct sock *osk) static int x25_dup(struct socket *newsock, struct socket *oldsock) { - struct sock *sk = (struct sock *)oldsock->sk; + struct sock *sk = oldsock->sk; + + if (sk == NULL || newsock == NULL) + return -EINVAL; return x25_create(newsock, sk->protocol); } static int x25_release(struct socket *sock, struct socket *peer) { - struct sock *sk = (struct sock *)sock->sk; + struct sock *sk = sock->sk; if (sk == NULL) return 0; @@ -653,14 +635,12 @@ static int x25_release(struct socket *sock, struct socket *peer) static int x25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) { - struct sock *sk; + struct sock *sk = sock->sk; struct sockaddr_x25 *addr = (struct sockaddr_x25 *)uaddr; - - sk = (struct sock *)sock->sk; if (sk->zapped == 0) return -EINVAL; - + if (addr_len != sizeof(struct sockaddr_x25)) return -EINVAL; @@ -681,29 +661,32 @@ static int x25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) static int x25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags) { - struct sock *sk = (struct sock *)sock->sk; + struct sock *sk = sock->sk; struct sockaddr_x25 *addr = (struct sockaddr_x25 *)uaddr; struct device *dev; - + if (sk->state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) { sock->state = SS_CONNECTED; return 0; /* Connect completed during a ERESTARTSYS event */ } - + if (sk->state == TCP_CLOSE && sock->state == SS_CONNECTING) { sock->state = SS_UNCONNECTED; return -ECONNREFUSED; } - + if (sk->state == TCP_ESTABLISHED) return -EISCONN; /* No reconnect on a seqpacket socket */ - + sk->state = TCP_CLOSE; sock->state = SS_UNCONNECTED; if (addr_len != sizeof(struct sockaddr_x25)) return -EINVAL; + if (addr->sx25_family != AF_X25) + return -EINVAL; + if ((dev = x25_get_route(&addr->sx25_addr)) == NULL) return -ENETUNREACH; @@ -725,11 +708,11 @@ static int x25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len x25_write_internal(sk, X25_CALL_REQUEST); x25_set_timer(sk); - + /* Now the loop */ if (sk->state != TCP_ESTABLISHED && (flags & O_NONBLOCK)) return -EINPROGRESS; - + cli(); /* To avoid races on the sleep */ /* @@ -748,11 +731,11 @@ static int x25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len sock->state = SS_UNCONNECTED; return sock_error(sk); /* Always set at this point */ } - + sock->state = SS_CONNECTED; sti(); - + return 0; } @@ -767,19 +750,20 @@ static int x25_accept(struct socket *sock, struct socket *newsock, int flags) struct sock *newsk; struct sk_buff *skb; - if (newsock->sk) - sk_free(newsock->sk); + if (newsock->sk != NULL) + x25_destroy_socket(newsock->sk); newsock->sk = NULL; - - sk = (struct sock *)sock->sk; + + if ((sk = sock->sk) == NULL) + return -EINVAL; if (sk->type != SOCK_SEQPACKET) return -EOPNOTSUPP; - + if (sk->state != TCP_LISTEN) return -EINVAL; - + /* * The write queue this time is holding sockets ready to use * hooked into the CALL INDICATION we saved @@ -789,7 +773,7 @@ static int x25_accept(struct socket *sock, struct socket *newsock, int flags) if ((skb = skb_dequeue(&sk->receive_queue)) == NULL) { if (flags & O_NONBLOCK) { sti(); - return 0; + return -EWOULDBLOCK; } interruptible_sleep_on(sk->sleep); if (current->signal & ~current->blocked) { @@ -815,10 +799,8 @@ static int x25_accept(struct socket *sock, struct socket *newsock, int flags) static int x25_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_len, int peer) { struct sockaddr_x25 *sx25 = (struct sockaddr_x25 *)uaddr; - struct sock *sk; - - sk = (struct sock *)sock->sk; - + struct sock *sk = sock->sk; + if (peer != 0) { if (sk->state != TCP_ESTABLISHED) return -ENOTCONN; @@ -839,11 +821,6 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *neigh, unsigned i struct sock *make; x25_address source_addr, dest_addr; struct x25_facilities facilities; - int len; - - /* - * skb->data points to the x25 frame start - */ /* * Remove the LCI and frame type. @@ -851,14 +828,10 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *neigh, unsigned i skb_pull(skb, X25_STD_MIN_LEN); /* - * Extract the X.25 addresses and convert them to ASCII strings. + * Extract the X.25 addresses and convert them to ASCII strings, + * and remove them. */ - len = x25_addr_ntoa(skb->data, &source_addr, &dest_addr); - - /* - * Remove address lengths and addresses. - */ - skb_pull(skb, len); + skb_pull(skb, x25_addr_ntoa(skb->data, &source_addr, &dest_addr)); /* * Find a listener for the particular address. @@ -874,14 +847,10 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *neigh, unsigned i } /* - * Parse the facilities. - */ - len = x25_parse_facilities(skb, &facilities); - - /* - * Then remove them, leaving any Call User Data. + * Parse the facilities, and remove them, leaving any Call User + * Data. */ - skb_pull(skb, len); + skb_pull(skb, x25_parse_facilities(skb, &facilities)); skb->sk = make; make->state = TCP_ESTABLISHED; @@ -897,11 +866,15 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *neigh, unsigned i */ make->protinfo.x25->facilities = facilities; + x25_write_internal(make, X25_CALL_ACCEPTED); + /* - * Incoming Call User Data. XXX + * Incoming Call User Data. */ - - x25_write_internal(make, X25_CALL_ACCEPTED); + if (skb->len >= 0) { + memcpy(make->protinfo.x25->calluserdata.cuddata, skb->data, skb->len); + make->protinfo.x25->calluserdata.cudlength = skb->len; + } make->protinfo.x25->state = X25_STATE_3; @@ -922,7 +895,7 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *neigh, unsigned i static int x25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct scm_cookie *scm) { - struct sock *sk = (struct sock *)sock->sk; + struct sock *sk = sock->sk; struct sockaddr_x25 *usx25 = (struct sockaddr_x25 *)msg->msg_name; int err; struct sockaddr_x25 sx25; @@ -930,7 +903,7 @@ static int x25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct unsigned char *asmptr; int size, qbit = 0; - if (msg->msg_flags & ~MSG_DONTWAIT) + if (msg->msg_flags & ~(MSG_DONTWAIT | MSG_OOB)) return -EINVAL; if (sk->zapped) @@ -943,7 +916,7 @@ static int x25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct if (sk->protinfo.x25->neighbour == NULL) return -ENETUNREACH; - + if (usx25 != NULL) { if (msg->msg_namelen < sizeof(sx25)) return -EINVAL; @@ -964,7 +937,7 @@ static int x25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct sx25.sx25_family = AF_X25; sx25.sx25_addr = sk->protinfo.x25->dest_addr; } - + if (sk->debug) printk(KERN_DEBUG "x25_sendmsg: sendto: Addresses built.\n"); @@ -972,16 +945,16 @@ static int x25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct if (sk->debug) printk(KERN_DEBUG "x25_sendmsg: sendto: building packet.\n"); + if ((msg->msg_flags & MSG_OOB) && len > 32) + len = 32; + size = len + X25_MAX_L2_LEN + X25_EXT_MIN_LEN; if ((skb = sock_alloc_send_skb(sk, size, 0, msg->msg_flags & MSG_DONTWAIT, &err)) == NULL) return err; - skb->sk = sk; - skb->arp = 1; - skb_reserve(skb, X25_MAX_L2_LEN + X25_EXT_MIN_LEN); - + /* * Put the data on the end */ @@ -1005,26 +978,40 @@ static int x25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct /* * Push down the X.25 header */ - if (sk->debug) + if (sk->debug) printk(KERN_DEBUG "x25_sendmsg: Building X.25 Header.\n"); - if (sk->protinfo.x25->neighbour->extended) { - /* Build an Extended X.25 header */ - asmptr = skb_push(skb, X25_EXT_MIN_LEN); - *asmptr++ = ((sk->protinfo.x25->lci >> 8) & 0x0F) | X25_GFI_EXTSEQ; - *asmptr++ = (sk->protinfo.x25->lci >> 0) & 0xFF; - *asmptr++ = X25_DATA; - *asmptr++ = X25_DATA; + if (msg->msg_flags & MSG_OOB) { + if (sk->protinfo.x25->neighbour->extended) { + asmptr = skb_push(skb, X25_STD_MIN_LEN); + *asmptr++ = ((sk->protinfo.x25->lci >> 8) & 0x0F) | X25_GFI_EXTSEQ; + *asmptr++ = (sk->protinfo.x25->lci >> 0) & 0xFF; + *asmptr++ = X25_INTERRUPT; + } else { + asmptr = skb_push(skb, X25_STD_MIN_LEN); + *asmptr++ = ((sk->protinfo.x25->lci >> 8) & 0x0F) | X25_GFI_STDSEQ; + *asmptr++ = (sk->protinfo.x25->lci >> 0) & 0xFF; + *asmptr++ = X25_INTERRUPT; + } } else { - /* Build an Standard X.25 header */ - asmptr = skb_push(skb, X25_STD_MIN_LEN); - *asmptr++ = ((sk->protinfo.x25->lci >> 8) & 0x0F) | X25_GFI_STDSEQ; - *asmptr++ = (sk->protinfo.x25->lci >> 0) & 0xFF; - *asmptr++ = X25_DATA; - } + if (sk->protinfo.x25->neighbour->extended) { + /* Build an Extended X.25 header */ + asmptr = skb_push(skb, X25_EXT_MIN_LEN); + *asmptr++ = ((sk->protinfo.x25->lci >> 8) & 0x0F) | X25_GFI_EXTSEQ; + *asmptr++ = (sk->protinfo.x25->lci >> 0) & 0xFF; + *asmptr++ = X25_DATA; + *asmptr++ = X25_DATA; + } else { + /* Build an Standard X.25 header */ + asmptr = skb_push(skb, X25_STD_MIN_LEN); + *asmptr++ = ((sk->protinfo.x25->lci >> 8) & 0x0F) | X25_GFI_STDSEQ; + *asmptr++ = (sk->protinfo.x25->lci >> 0) & 0xFF; + *asmptr++ = X25_DATA; + } - if (qbit) - skb->data[0] |= X25_Q_BIT; + if (qbit) + skb->data[0] |= X25_Q_BIT; + } if (sk->debug) printk(KERN_DEBUG "x25_sendmsg: Built header.\n"); @@ -1037,7 +1024,14 @@ static int x25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct return -ENOTCONN; } - x25_output(sk, skb); /* Shove it onto the queue */ + if (msg->msg_flags & MSG_OOB) { + skb_queue_tail(&sk->protinfo.x25->interrupt_out_queue, skb); + } else { + x25_output(sk, skb); + } + + if (sk->protinfo.x25->state == X25_STATE_3) + x25_kick(sk); return len; } @@ -1045,7 +1039,7 @@ static int x25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct static int x25_recvmsg(struct socket *sock, struct msghdr *msg, int size, int flags, struct scm_cookie *scm) { - struct sock *sk = (struct sock *)sock->sk; + struct sock *sk = sock->sk; struct sockaddr_x25 *sx25 = (struct sockaddr_x25 *)msg->msg_name; int copied, qbit; struct sk_buff *skb; @@ -1059,37 +1053,52 @@ static int x25_recvmsg(struct socket *sock, struct msghdr *msg, int size, int fl if (sk->state != TCP_ESTABLISHED) return -ENOTCONN; - /* Now we can treat all alike */ - if ((skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, flags & MSG_DONTWAIT, &er)) == NULL) - return er; + if (flags & MSG_OOB) { + if (sk->urginline || skb_peek(&sk->protinfo.x25->interrupt_in_queue) == NULL) + return -EINVAL; - qbit = (skb->data[0] & X25_Q_BIT) == X25_Q_BIT; + skb = skb_dequeue(&sk->protinfo.x25->interrupt_in_queue); - skb_pull(skb, (sk->protinfo.x25->neighbour->extended) ? X25_EXT_MIN_LEN : X25_STD_MIN_LEN); - skb->h.raw = skb->data; + skb_pull(skb, X25_STD_MIN_LEN); - if (sk->protinfo.x25->qbitincl) { - asmptr = skb_push(skb, 1); - *asmptr = qbit; - skb->h.raw = skb->data; + /* + * No Q bit information on Interrupt data. + */ + if (sk->protinfo.x25->qbitincl) { + asmptr = skb_push(skb, 1); + *asmptr = 0x00; + } + + msg->msg_flags |= MSG_OOB; + } else { + /* Now we can treat all alike */ + if ((skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, flags & MSG_DONTWAIT, &er)) == NULL) + return er; + + qbit = (skb->data[0] & X25_Q_BIT) == X25_Q_BIT; + + skb_pull(skb, (sk->protinfo.x25->neighbour->extended) ? X25_EXT_MIN_LEN : X25_STD_MIN_LEN); + + if (sk->protinfo.x25->qbitincl) { + asmptr = skb_push(skb, 1); + *asmptr = qbit; + } } + skb->h.raw = skb->data; + copied = skb->len; - + if (copied > size) { copied = size; msg->msg_flags |= MSG_TRUNC; } skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); - - if (sx25 != NULL) { - struct sockaddr_x25 addr; - - addr.sx25_family = AF_X25; - addr.sx25_addr = sk->protinfo.x25->dest_addr; - *sx25 = addr; + if (sx25 != NULL) { + sx25->sx25_family = AF_X25; + sx25->sx25_addr = sk->protinfo.x25->dest_addr; } msg->msg_namelen = sizeof(struct sockaddr_x25); @@ -1106,7 +1115,9 @@ static int x25_shutdown(struct socket *sk, int how) static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) { - struct sock *sk = (struct sock *)sock->sk; + struct x25_facilities facilities; + struct x25_calluserdata calluserdata; + struct sock *sk = sock->sk; int err; long amount = 0; @@ -1159,10 +1170,64 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) if (!suser()) return -EPERM; return x25_route_ioctl(cmd, (void *)arg); - case SIOCX25SETSUBSCR: + case SIOCX25GSUBSCRIP: + return x25_subscr_ioctl(cmd, (void *)arg); + + case SIOCX25SSUBSCRIP: if (!suser()) return -EPERM; return x25_subscr_ioctl(cmd, (void *)arg); + case SIOCX25GFACILITIES: + if ((err = verify_area(VERIFY_WRITE, (void *)arg, sizeof(facilities))) != 0) + return err; + facilities = sk->protinfo.x25->facilities; + copy_to_user((void *)arg, &facilities, sizeof(facilities)); + return 0; + + case SIOCX25SFACILITIES: + if ((err = verify_area(VERIFY_READ, (void *)arg, sizeof(facilities))) != 0) + return err; + copy_from_user(&facilities, (void *)arg, sizeof(facilities)); + if (sk->state != TCP_LISTEN) + return -EINVAL; + if (facilities.pacsize_in < X25_PS16 || facilities.pacsize_in > X25_PS4096) + return -EINVAL; + if (facilities.pacsize_out < X25_PS16 || facilities.pacsize_out > X25_PS4096) + return -EINVAL; + if (sk->protinfo.x25->neighbour->extended) { + if (facilities.winsize_in < 1 || facilities.winsize_in > 127) + return -EINVAL; + if (facilities.winsize_out < 1 || facilities.winsize_out > 127) + return -EINVAL; + } else { + if (facilities.winsize_in < 1 || facilities.winsize_in > 7) + return -EINVAL; + if (facilities.winsize_out < 1 || facilities.winsize_out > 7) + return -EINVAL; + } + if (facilities.throughput < 0x03 || facilities.throughput > 0x2C) + return -EINVAL; + if (facilities.reverse != 0 && facilities.reverse != 1) + return -EINVAL; + sk->protinfo.x25->facilities = facilities; + return 0; + + case SIOCX25GCALLUSERDATA: + if ((err = verify_area(VERIFY_WRITE, (void *)arg, sizeof(calluserdata))) != 0) + return err; + calluserdata = sk->protinfo.x25->calluserdata; + copy_to_user((void *)arg, &calluserdata, sizeof(calluserdata)); + return 0; + + case SIOCX25SCALLUSERDATA: + if ((err = verify_area(VERIFY_READ, (void *)arg, sizeof(calluserdata))) != 0) + return err; + copy_from_user(&calluserdata, (void *)arg, sizeof(calluserdata)); + if (calluserdata.cudlength > X25_MAX_CUD_LEN) + return -EINVAL; + sk->protinfo.x25->calluserdata = calluserdata; + return 0; + default: return dev_ioctl(cmd, (void *)arg); } @@ -1179,7 +1244,7 @@ static int x25_get_info(char *buffer, char **start, off_t offset, int length, in int len = 0; off_t pos = 0; off_t begin = 0; - + cli(); len += sprintf(buffer, "dest_addr src_addr dev lci st vs vr va t t2 t21 t22 t23 Snd-Q Rcv-Q\n"); @@ -1202,14 +1267,14 @@ static int x25_get_info(char *buffer, char **start, off_t offset, int length, in s->protinfo.x25->t22 / X25_SLOWHZ, s->protinfo.x25->t23 / X25_SLOWHZ, s->wmem_alloc, s->rmem_alloc); - + pos = begin + len; if (pos < offset) { len = 0; begin = pos; } - + if (pos > offset + length) break; } @@ -1245,7 +1310,7 @@ static struct proto_ops x25_proto_ops = { x25_shutdown, x25_setsockopt, x25_getsockopt, - x25_fcntl, + sock_no_fcntl, x25_sendmsg, x25_recvmsg }; @@ -1254,7 +1319,7 @@ static struct packet_type x25_packet_type = { 0, /* MUTTER ntohs(ETH_P_X25),*/ 0, /* copy */ - x25_llc_receive_frame, + x25_lapb_receive_frame, NULL, NULL, }; @@ -1264,6 +1329,27 @@ struct notifier_block x25_dev_notifier = { 0 }; +#ifdef CONFIG_PROC_FS +static struct proc_dir_entry proc_net_x25 = { + PROC_NET_X25, 3, "x25", + S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_net_inode_operations, + x25_get_info +}; +static struct proc_dir_entry proc_net_x25_links = { + PROC_NET_X25_LINKS, 9, "x25_links", + S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_net_inode_operations, + x25_link_get_info +}; +static struct proc_dir_entry proc_net_x25_routes = { + PROC_NET_X25_ROUTES, 10, "x25_routes", + S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_net_inode_operations, + x25_routes_get_info +}; +#endif + void x25_proto_init(struct net_proto *pro) { sock_register(&x25_family_ops); @@ -1278,26 +1364,9 @@ void x25_proto_init(struct net_proto *pro) x25_register_sysctl(); #ifdef CONFIG_PROC_FS - proc_net_register(&(struct proc_dir_entry) { - PROC_NET_X25, 3, "x25", - S_IFREG | S_IRUGO, 1, 0, 0, - 0, &proc_net_inode_operations, - x25_get_info - }); - - proc_net_register(&(struct proc_dir_entry) { - PROC_NET_X25_LINKS, 9, "x25_links", - S_IFREG | S_IRUGO, 1, 0, 0, - 0, &proc_net_inode_operations, - x25_link_get_info - }); - - proc_net_register(&(struct proc_dir_entry) { - PROC_NET_X25_ROUTES, 10, "x25_routes", - S_IFREG | S_IRUGO, 1, 0, 0, - 0, &proc_net_inode_operations, - x25_routes_get_info - }); + proc_net_register(&proc_net_x25); + proc_net_register(&proc_net_x25_links); + proc_net_register(&proc_net_x25_routes); #endif } @@ -1306,7 +1375,20 @@ EXPORT_NO_SYMBOLS; int init_module(void) { + struct device *dev; + x25_proto_init(NULL); + + /* + * Register any pre existing devices. + */ + for (dev = dev_base; dev != NULL; dev = dev->next) + if ((dev->flags & IFF_UP) && (dev->type == ARPHRD_X25 +#if defined(CONFIG_LLC) || defined(CONFIG_LLC_MODULE) + || dev->type == ARPHRD_ETHER +#endif + )) + x25_link_device_up(dev); return 0; } diff --git a/net/x25/x25_dev.c b/net/x25/x25_dev.c index 5fca44cc86f0..b6ce9e127451 100644 --- a/net/x25/x25_dev.c +++ b/net/x25/x25_dev.c @@ -15,7 +15,7 @@ * History * X.25 001 Jonathan Naylor Started coding. */ - + #include #if defined(CONFIG_X25) || defined(CONFIG_X25_MODULE) #include @@ -89,8 +89,9 @@ static int x25_receive_data(struct sk_buff *skb, struct x25_neigh *neigh) /* * Its not a Call Request, nor is it a control frame, throw it awa */ +/* x25_transmit_clear_request(neigh, lci, 0x0D); - +*/ kfree_skb(skb, FREE_READ); return 0; @@ -101,11 +102,12 @@ int x25_lapb_receive_frame(struct sk_buff *skb, struct device *dev, struct packe struct x25_neigh *neigh; skb->sk = NULL; - + /* * Packet received from unrecognised device, throw it away. */ if ((neigh = x25_get_neigh(dev)) == NULL) { + printk(KERN_DEBUG "X.25: unknown neighbour - %s\n", dev->name); kfree_skb(skb, FREE_READ); return 0; } @@ -129,10 +131,6 @@ int x25_lapb_receive_frame(struct sk_buff *skb, struct device *dev, struct packe kfree_skb(skb, FREE_READ); return 0; - case 0x04: - kfree_skb(skb, FREE_READ); - return 0; - default: kfree_skb(skb, FREE_READ); return 0; @@ -144,11 +142,12 @@ int x25_llc_receive_frame(struct sk_buff *skb, struct device *dev, struct packet struct x25_neigh *neigh; skb->sk = NULL; - + /* * Packet received from unrecognised device, throw it away. */ if ((neigh = x25_get_neigh(dev)) == NULL) { + printk(KERN_DEBUG "X.25: unknown_neighbour - %s\n", dev->name); kfree_skb(skb, FREE_READ); return 0; } diff --git a/net/x25/x25_in.c b/net/x25/x25_in.c index 47da943cb390..34b54ded4b00 100644 --- a/net/x25/x25_in.c +++ b/net/x25/x25_in.c @@ -49,7 +49,7 @@ static int x25_queue_rx_frame(struct sock *sk, struct sk_buff *skb, int more) skb_queue_tail(&sk->protinfo.x25->fragment_queue, skb); return 0; } - + if (!more && sk->protinfo.x25->fraglen > 0) { /* End of fragment */ sk->protinfo.x25->fraglen += skb->len; skb_queue_tail(&sk->protinfo.x25->fragment_queue, skb); @@ -57,7 +57,6 @@ static int x25_queue_rx_frame(struct sock *sk, struct sk_buff *skb, int more) if ((skbn = alloc_skb(sk->protinfo.x25->fraglen, GFP_ATOMIC)) == NULL) return 1; - skbn->arp = 1; skb_set_owner_r(skbn, sk); skbn->h.raw = skbn->data; @@ -84,6 +83,9 @@ static int x25_queue_rx_frame(struct sock *sk, struct sk_buff *skb, int more) */ static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametype) { + x25_address source_addr, dest_addr; + struct x25_facilities facilities; + switch (frametype) { case X25_CALL_ACCEPTED: @@ -95,6 +97,20 @@ static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametyp sk->protinfo.x25->vl = 0; sk->protinfo.x25->state = X25_STATE_3; sk->state = TCP_ESTABLISHED; + /* + * Parse the data in the frame. + */ + skb_pull(skb, X25_STD_MIN_LEN); + skb_pull(skb, x25_addr_ntoa(skb->data, &source_addr, &dest_addr)); + skb_pull(skb, x25_parse_facilities(skb, &facilities)); + /* + * Facilities XXX + * Copy any Call User Data. + */ + if (skb->len >= 0) { + memcpy(sk->protinfo.x25->calluserdata.cuddata, skb->data, skb->len); + sk->protinfo.x25->calluserdata.cudlength = skb->len; + } if (!sk->dead) sk->state_change(sk); break; @@ -202,13 +218,13 @@ static int x25_state3_machine(struct sock *sk, struct sk_buff *skb, int frametyp sk->protinfo.x25->timer = sk->protinfo.x25->t22; } else { if (sk->protinfo.x25->condition & X25_COND_PEER_RX_BUSY) { - x25_frames_acked(sk, nr); + sk->protinfo.x25->va = nr; } else { x25_check_iframes_acked(sk, nr); } } break; - + case X25_DATA: /* XXX */ sk->protinfo.x25->condition &= ~X25_COND_PEER_RX_BUSY; if (!x25_validate_nr(sk, nr)) { @@ -224,7 +240,7 @@ static int x25_state3_machine(struct sock *sk, struct sk_buff *skb, int frametyp break; } if (sk->protinfo.x25->condition & X25_COND_PEER_RX_BUSY) { - x25_frames_acked(sk, nr); + sk->protinfo.x25->va = nr; } else { x25_check_iframes_acked(sk, nr); } @@ -242,7 +258,7 @@ static int x25_state3_machine(struct sock *sk, struct sk_buff *skb, int frametyp * If the window is full Ack it immediately, else * start the holdback timer. */ - if (((sk->protinfo.x25->vl + sk->protinfo.x25->facilities.window_size) % modulus) == sk->protinfo.x25->vr) { + if (((sk->protinfo.x25->vl + sk->protinfo.x25->facilities.winsize_in) % modulus) == sk->protinfo.x25->vr) { sk->protinfo.x25->condition &= ~X25_COND_ACK_PENDING; sk->protinfo.x25->timer = 0; x25_enquiry_response(sk); @@ -252,6 +268,27 @@ static int x25_state3_machine(struct sock *sk, struct sk_buff *skb, int frametyp } break; + case X25_INTERRUPT_CONFIRMATION: + sk->protinfo.x25->intflag = 0; + break; + + case X25_INTERRUPT: + if (sk->urginline) { + queued = (sock_queue_rcv_skb(sk, skb) == 0); + } else { + skb_set_owner_r(skb, sk); + skb_queue_tail(&sk->protinfo.x25->interrupt_in_queue, skb); + queued = 1; + } + if (sk->proc != 0) { + if (sk->proc > 0) + kill_proc(sk->proc, SIGURG, 1); + else + kill_pg(-sk->proc, SIGURG, 1); + } + x25_write_internal(sk, X25_INTERRUPT_CONFIRMATION); + break; + default: printk(KERN_WARNING "x25: unknown %02X in state 3\n", frametype); break; @@ -305,7 +342,7 @@ static int x25_state4_machine(struct sock *sk, struct sk_buff *skb, int frametyp int x25_process_rx_frame(struct sock *sk, struct sk_buff *skb) { int queued = 0, frametype, ns, nr, q, d, m; - + if (sk->protinfo.x25->state == X25_STATE_0) return 0; diff --git a/net/x25/x25_link.c b/net/x25/x25_link.c index af75513f40e0..63ac3587a19d 100644 --- a/net/x25/x25_link.c +++ b/net/x25/x25_link.c @@ -51,7 +51,7 @@ static void x25_link_timer(unsigned long); static void x25_link_set_timer(struct x25_neigh *neigh) { unsigned long flags; - + save_flags(flags); cli(); del_timer(&neigh->timer); @@ -68,7 +68,7 @@ static void x25_link_set_timer(struct x25_neigh *neigh) static void x25_link_reset_timer(struct x25_neigh *neigh) { unsigned long flags; - + save_flags(flags); cli(); del_timer(&neigh->timer); @@ -278,6 +278,9 @@ void x25_transmit_link(struct sk_buff *skb, struct x25_neigh *neigh) } } +/* + * Called when the link layer has become established. + */ void x25_link_established(struct x25_neigh *neigh) { switch (neigh->state) { @@ -293,6 +296,10 @@ void x25_link_established(struct x25_neigh *neigh) } } +/* + * Called when the link layer has terminated, or an establishment + * request has failed. XXX should tell sockets. + */ void x25_link_terminated(struct x25_neigh *neigh) { neigh->state = X25_LINK_STATE_0; @@ -332,7 +339,7 @@ static void x25_remove_neigh(struct x25_neigh *x25_neigh) while ((skb = skb_dequeue(&x25_neigh->queue)) != NULL) kfree_skb(skb, FREE_WRITE); - + del_timer(&x25_neigh->timer); save_flags(flags); @@ -369,7 +376,7 @@ void x25_link_device_down(struct device *dev) while (x25_neigh != NULL) { neigh = x25_neigh; x25_neigh = x25_neigh->next; - + if (neigh->dev == dev) x25_remove_neigh(neigh); } @@ -401,7 +408,18 @@ int x25_subscr_ioctl(unsigned int cmd, void *arg) switch (cmd) { - case SIOCX25SETSUBSCR: + case SIOCX25GSUBSCRIP: + if ((err = verify_area(VERIFY_WRITE, arg, sizeof(struct x25_subscrip_struct))) != 0) + return err; + if ((dev = x25_dev_get(x25_subscr.device)) == NULL) + return -EINVAL; + if ((x25_neigh = x25_get_neigh(dev)) == NULL) + return -EINVAL; + x25_subscr.extended = x25_neigh->extended; + copy_to_user(arg, &x25_subscr, sizeof(struct x25_subscrip_struct)); + break; + + case SIOCX25SSUBSCRIP: if ((err = verify_area(VERIFY_READ, arg, sizeof(struct x25_subscrip_struct))) != 0) return err; copy_from_user(&x25_subscr, arg, sizeof(struct x25_subscrip_struct)); @@ -446,7 +464,7 @@ int x25_link_get_info(char *buffer, char **start, off_t offset, int length, int len = 0; begin = pos; } - + if (pos > offset + length) break; } @@ -473,7 +491,7 @@ void x25_link_free(void) while (x25_neigh != NULL) { neigh = x25_neigh; x25_neigh = x25_neigh->next; - + x25_remove_neigh(neigh); } } diff --git a/net/x25/x25_out.c b/net/x25/x25_out.c index 5fe37d01c3e1..321baa5d6cf6 100644 --- a/net/x25/x25_out.c +++ b/net/x25/x25_out.c @@ -39,6 +39,19 @@ #include #include +static int x25_pacsize_to_bytes(unsigned int pacsize) +{ + int bytes = 1; + + if (pacsize == 0) + return 128; + + while (pacsize-- > 0) + bytes *= 2; + + return bytes; +} + /* * This is where all X.25 information frames pass; */ @@ -46,35 +59,33 @@ void x25_output(struct sock *sk, struct sk_buff *skb) { struct sk_buff *skbn; unsigned char header[X25_EXT_MIN_LEN]; - int err, frontlen, len, min_len; - - min_len = (sk->protinfo.x25->neighbour->extended) ? X25_EXT_MIN_LEN : X25_STD_MIN_LEN; + int err, frontlen, len, header_len, max_len; + + header_len = (sk->protinfo.x25->neighbour->extended) ? X25_EXT_MIN_LEN : X25_STD_MIN_LEN; + max_len = x25_pacsize_to_bytes(sk->protinfo.x25->facilities.pacsize_out); - if (skb->len - min_len > 128) { /* XXX */ + if (skb->len - header_len > max_len) { /* Save a copy of the Header */ - memcpy(header, skb->data, min_len); - skb_pull(skb, min_len); + memcpy(header, skb->data, header_len); + skb_pull(skb, header_len); frontlen = skb_headroom(skb); while (skb->len > 0) { - if ((skbn = sock_alloc_send_skb(sk, frontlen + 128, 0, 0, &err)) == NULL) /* XXX */ + if ((skbn = sock_alloc_send_skb(sk, frontlen + max_len, 0, 0, &err)) == NULL) return; - skbn->sk = sk; - skbn->arp = 1; - skb_reserve(skbn, frontlen); - len = (128 > skb->len) ? skb->len : 128; /* XXX */ + len = (max_len > skb->len) ? skb->len : max_len; /* Copy the user data */ memcpy(skb_put(skbn, len), skb->data, len); skb_pull(skb, len); /* Duplicate the Header */ - skb_push(skbn, min_len); - memcpy(skbn->data, header, min_len); + skb_push(skbn, header_len); + memcpy(skbn->data, header, header_len); if (skb->len > 0) { if (sk->protinfo.x25->neighbour->extended) @@ -82,17 +93,14 @@ void x25_output(struct sock *sk, struct sk_buff *skb) else skbn->data[2] |= X25_STD_M_BIT; } - - skb_queue_tail(&sk->write_queue, skbn); /* Throw it on the queue */ + + skb_queue_tail(&sk->write_queue, skbn); } kfree_skb(skb, FREE_WRITE); } else { - skb_queue_tail(&sk->write_queue, skb); /* Throw it on the queue */ + skb_queue_tail(&sk->write_queue, skb); } - - if (sk->protinfo.x25->state == X25_STATE_3) - x25_kick(sk); } /* @@ -117,56 +125,46 @@ static void x25_send_iframe(struct sock *sk, struct sk_buff *skb) void x25_kick(struct sock *sk) { - struct sk_buff *skb, *skbn; - int last = 1; - unsigned short start, end, next; + struct sk_buff *skb; + unsigned short end; int modulus; - - modulus = (sk->protinfo.x25->neighbour->extended) ? X25_EMODULUS : X25_SMODULUS; del_timer(&sk->timer); - start = (skb_peek(&sk->protinfo.x25->ack_queue) == NULL) ? sk->protinfo.x25->va : sk->protinfo.x25->vs; - end = (sk->protinfo.x25->va + sk->protinfo.x25->facilities.window_size) % modulus; + /* + * Transmit interrupt data. + */ + if (!sk->protinfo.x25->intflag && skb_peek(&sk->protinfo.x25->interrupt_out_queue) != NULL) { + sk->protinfo.x25->intflag = 1; + skb = skb_dequeue(&sk->protinfo.x25->interrupt_out_queue); + x25_transmit_link(skb, sk->protinfo.x25->neighbour); + } + modulus = (sk->protinfo.x25->neighbour->extended) ? X25_EMODULUS : X25_SMODULUS; + end = (sk->protinfo.x25->va + sk->protinfo.x25->facilities.winsize_out) % modulus; + + /* + * Transmit normal stream data. + */ if (!(sk->protinfo.x25->condition & X25_COND_PEER_RX_BUSY) && - start != end && + sk->protinfo.x25->vs != end && skb_peek(&sk->write_queue) != NULL) { - - sk->protinfo.x25->vs = start; - /* * Transmit data until either we're out of data to send or * the window is full. */ - /* - * Dequeue the frame and copy it. - */ - skb = skb_dequeue(&sk->write_queue); + skb = skb_dequeue(&sk->write_queue); do { - if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) { - skb_queue_head(&sk->write_queue, skb); - break; - } - - next = (sk->protinfo.x25->vs + 1) % modulus; - last = (next == end); - /* - * Transmit the frame copy. + * Transmit the frame. */ - x25_send_iframe(sk, skbn); + x25_send_iframe(sk, skb); - sk->protinfo.x25->vs = next; - - /* - * Requeue the original data frame. - */ - skb_queue_tail(&sk->protinfo.x25->ack_queue, skb); + sk->protinfo.x25->vs = (sk->protinfo.x25->vs + 1) % modulus; - } while (!last && (skb = skb_dequeue(&sk->write_queue)) != NULL); + } while (sk->protinfo.x25->vs != end && (skb = skb_dequeue(&sk->write_queue)) != NULL); sk->protinfo.x25->vl = sk->protinfo.x25->vr; sk->protinfo.x25->condition &= ~X25_COND_ACK_PENDING; @@ -196,10 +194,10 @@ void x25_enquiry_response(struct sock *sk) void x25_check_iframes_acked(struct sock *sk, unsigned short nr) { if (sk->protinfo.x25->vs == nr) { - x25_frames_acked(sk, nr); + sk->protinfo.x25->va = nr; } else { if (sk->protinfo.x25->va != nr) { - x25_frames_acked(sk, nr); + sk->protinfo.x25->va = nr; } } } diff --git a/net/x25/x25_route.c b/net/x25/x25_route.c index 7a012374823e..fc1bfc54bfb4 100644 --- a/net/x25/x25_route.c +++ b/net/x25/x25_route.c @@ -15,7 +15,7 @@ * History * X.25 001 Jonathan Naylor Started coding. */ - + #include #if defined(CONFIG_X25) || defined(CONFIG_X25_MODULE) #include @@ -72,7 +72,7 @@ static int x25_add_route(x25_address *address, unsigned int sigdigits, struct de x25_route->next = x25_route_list; x25_route_list = x25_route; restore_flags(flags); - + return 0; } @@ -80,7 +80,7 @@ static void x25_remove_route(struct x25_route *x25_route) { struct x25_route *s; unsigned long flags; - + save_flags(flags); cli(); @@ -108,7 +108,7 @@ static void x25_remove_route(struct x25_route *x25_route) static int x25_del_route(x25_address *address, unsigned int sigdigits, struct device *dev) { struct x25_route *x25_route; - + for (x25_route = x25_route_list; x25_route != NULL; x25_route = x25_route->next) { if (memcmp(&x25_route->address, address, sigdigits) == 0 && x25_route->sigdigits == sigdigits && x25_route->dev == dev) { x25_remove_route(x25_route); @@ -129,7 +129,7 @@ void x25_route_device_down(struct device *dev) while (x25_route != NULL) { route = x25_route; x25_route = x25_route->next; - + if (route->dev == dev) x25_remove_route(route); } @@ -161,7 +161,7 @@ struct device *x25_dev_get(char *devname) struct device *x25_get_route(x25_address *addr) { struct x25_route *route, *use = NULL; - + for (route = x25_route_list; route != NULL; route = route->next) { if (memcmp(&route->address, addr, route->sigdigits) == 0) { if (use == NULL) { @@ -236,7 +236,7 @@ int x25_routes_get_info(char *buffer, char **start, off_t offset, int length, in len = 0; begin = pos; } - + if (pos > offset + length) break; } @@ -263,7 +263,7 @@ void x25_route_free(void) while (x25_route != NULL) { route = x25_route; x25_route = x25_route->next; - + x25_remove_route(route); } } diff --git a/net/x25/x25_subr.c b/net/x25/x25_subr.c index 5b8cbb5acc29..245109ee9ecb 100644 --- a/net/x25/x25_subr.c +++ b/net/x25/x25_subr.c @@ -15,7 +15,7 @@ * History * X.25 001 Jonathan Naylor Started coding. */ - + #include #if defined(CONFIG_X25) || defined(CONFIG_X25_MODULE) #include @@ -46,68 +46,17 @@ void x25_clear_queues(struct sock *sk) { struct sk_buff *skb; - while ((skb = skb_dequeue(&sk->write_queue)) != NULL) { - skb->sk = sk; + while ((skb = skb_dequeue(&sk->write_queue)) != NULL) kfree_skb(skb, FREE_WRITE); - } - while ((skb = skb_dequeue(&sk->protinfo.x25->ack_queue)) != NULL) { - skb->sk = sk; - kfree_skb(skb, FREE_WRITE); - } + while ((skb = skb_dequeue(&sk->protinfo.x25->interrupt_in_queue)) != NULL) + kfree_skb(skb, FREE_READ); - while ((skb = skb_dequeue(&sk->protinfo.x25->interrupt_queue)) != NULL) { - skb->sk = sk; + while ((skb = skb_dequeue(&sk->protinfo.x25->interrupt_out_queue)) != NULL) kfree_skb(skb, FREE_WRITE); - } - while ((skb = skb_dequeue(&sk->protinfo.x25->fragment_queue)) != NULL) { - skb->sk = sk; + while ((skb = skb_dequeue(&sk->protinfo.x25->fragment_queue)) != NULL) kfree_skb(skb, FREE_READ); - } -} - -/* - * This routine purges the input queue of those frames that have been - * acknowledged. This replaces the boxes labelled "V(a) <- N(r)" on the - * SDL diagram. - */ -void x25_frames_acked(struct sock *sk, unsigned short nr) -{ - struct sk_buff *skb; - int modulus; - - modulus = (sk->protinfo.x25->neighbour->extended) ? X25_EMODULUS : X25_SMODULUS; - - /* - * Remove all the ack-ed frames from the ack queue. - */ - if (sk->protinfo.x25->va != nr) { - while (skb_peek(&sk->protinfo.x25->ack_queue) != NULL && sk->protinfo.x25->va != nr) { - skb = skb_dequeue(&sk->protinfo.x25->ack_queue); - skb->sk = sk; - kfree_skb(skb, FREE_WRITE); - sk->protinfo.x25->va = (sk->protinfo.x25->va + 1) % modulus; - } - } -} - -/* - * Requeue all the un-ack-ed frames on the output queue to be picked - * up by x25_kick called from the timer. This arrangement handles the - * possibility of an empty output queue. - */ -void x25_requeue_frames(struct sock *sk) -{ - struct sk_buff *skb, *skb_prev = NULL; - - while ((skb = skb_dequeue(&sk->protinfo.x25->ack_queue)) != NULL) { - if (skb_prev == NULL) - skb_queue_head(&sk->write_queue, skb); - else - skb_append(skb_prev, skb); - skb_prev = skb; - } } /* @@ -125,7 +74,7 @@ int x25_validate_nr(struct sock *sk, unsigned short nr) if (nr == vc) return 1; vc = (vc + 1) % modulus; } - + if (nr == sk->protinfo.x25->vs) return 1; return 0; @@ -151,13 +100,13 @@ void x25_write_internal(struct sock *sk, int frametype) /* * Adjust frame size. - */ + */ switch (frametype) { case X25_CALL_REQUEST: - len += 1 + X25_ADDR_LEN + X25_MAX_FAC_LEN; + len += 1 + X25_ADDR_LEN + X25_MAX_FAC_LEN + X25_MAX_CUD_LEN; break; case X25_CALL_ACCEPTED: - len += 1 + X25_MAX_FAC_LEN; + len += 1 + X25_MAX_FAC_LEN + X25_MAX_CUD_LEN; break; case X25_CLEAR_REQUEST: case X25_RESET_REQUEST: @@ -174,7 +123,7 @@ void x25_write_internal(struct sock *sk, int frametype) printk(KERN_ERR "X.25: invalid frame type %02X\n", frametype); return; } - + if ((skb = alloc_skb(len, GFP_ATOMIC)) == NULL) return; @@ -182,7 +131,7 @@ void x25_write_internal(struct sock *sk, int frametype) * Space for Ethernet and 802.2 LLC headers. */ skb_reserve(skb, X25_MAX_L2_LEN); - + /* * Make space for the GFI and LCI, and fill them in. */ @@ -203,7 +152,7 @@ void x25_write_internal(struct sock *sk, int frametype) * Now fill in the frame type specific information. */ switch (frametype) { - + case X25_CALL_REQUEST: dptr = skb_put(skb, 1); *dptr++ = X25_CALL_REQUEST; @@ -213,6 +162,9 @@ void x25_write_internal(struct sock *sk, int frametype) len = x25_create_facilities(facilities, &sk->protinfo.x25->facilities); dptr = skb_put(skb, len); memcpy(dptr, facilities, len); + dptr = skb_put(skb, sk->protinfo.x25->calluserdata.cudlength); + memcpy(dptr, sk->protinfo.x25->calluserdata.cuddata, sk->protinfo.x25->calluserdata.cudlength); + sk->protinfo.x25->calluserdata.cudlength = 0; break; case X25_CALL_ACCEPTED: @@ -222,6 +174,9 @@ void x25_write_internal(struct sock *sk, int frametype) len = x25_create_facilities(facilities, &sk->protinfo.x25->facilities); dptr = skb_put(skb, len); memcpy(dptr, facilities, len); + dptr = skb_put(skb, sk->protinfo.x25->calluserdata.cudlength); + memcpy(dptr, sk->protinfo.x25->calluserdata.cuddata, sk->protinfo.x25->calluserdata.cudlength); + sk->protinfo.x25->calluserdata.cudlength = 0; break; case X25_CLEAR_REQUEST: @@ -245,7 +200,7 @@ void x25_write_internal(struct sock *sk, int frametype) *dptr++ |= (sk->protinfo.x25->vr << 5) & 0xE0; } break; - + case X25_CLEAR_CONFIRMATION: case X25_INTERRUPT_CONFIRMATION: case X25_RESET_CONFIRMATION: @@ -263,9 +218,9 @@ void x25_write_internal(struct sock *sk, int frametype) int x25_decode(struct sock *sk, struct sk_buff *skb, int *ns, int *nr, int *q, int *d, int *m) { unsigned char *frame; - + frame = skb->data; - + *ns = *nr = *q = *d = *m = 0; switch (frame[2]) { @@ -322,7 +277,7 @@ int x25_decode(struct sock *sk, struct sk_buff *skb, int *ns, int *nr, int *q, i } printk(KERN_DEBUG "X.25: invalid PLP frame %02X %02X %02X\n", frame[0], frame[1], frame[2]); - + return X25_ILLEGAL; } @@ -335,10 +290,7 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities) unsigned int len; unsigned char *p = skb->data; - facilities->window_size = -1; - facilities->packet_size = -1; - facilities->throughput = -1; - facilities->reverse = -1; + memset(facilities, 0x00, sizeof(struct x25_facilities)); len = *p++; @@ -359,14 +311,16 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities) p += 2; len -= 2; break; - + case X25_FAC_CLASS_B: switch (*p) { case X25_FAC_PACKET_SIZE: - facilities->packet_size = p[1]; + facilities->pacsize_in = p[1]; + facilities->pacsize_out = p[2]; break; case X25_FAC_WINDOW_SIZE: - facilities->window_size = p[1]; + facilities->winsize_in = p[1]; + facilities->winsize_out = p[2]; break; default: printk(KERN_DEBUG "X.25: unknown facility %02X, values %02X, %02X\n", p[0], p[1], p[2]); @@ -381,7 +335,7 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities) p += 4; len -= 4; break; - + case X25_FAC_CLASS_D: printk(KERN_DEBUG "X.25: unknown facility %02X, length %d, values %02X, %02X, %02X, %02X\n", p[0], p[1], p[2], p[3], p[4], p[5]); p += p[1] + 2; @@ -401,31 +355,31 @@ int x25_create_facilities(unsigned char *buffer, struct x25_facilities *faciliti unsigned char *p = buffer + 1; int len; - if (facilities->reverse != -1) { + if (facilities->reverse != 0) { *p++ = X25_FAC_REVERSE; *p++ = (facilities->reverse) ? 0x01 : 0x00; } - if (facilities->throughput != -1) { + if (facilities->throughput != 0) { *p++ = X25_FAC_THROUGHPUT; *p++ = facilities->throughput; } - if (facilities->packet_size != -1) { + if (facilities->pacsize_in != 0 || facilities->pacsize_out != 0) { *p++ = X25_FAC_PACKET_SIZE; - *p++ = facilities->packet_size; - *p++ = facilities->packet_size; + *p++ = (facilities->pacsize_in == 0) ? facilities->pacsize_out : facilities->pacsize_in; + *p++ = (facilities->pacsize_out == 0) ? facilities->pacsize_in : facilities->pacsize_out; } - if (facilities->window_size != -1) { + if (facilities->winsize_in != 0 || facilities->winsize_out != 0) { *p++ = X25_FAC_WINDOW_SIZE; - *p++ = facilities->window_size; - *p++ = facilities->window_size; + *p++ = (facilities->winsize_in == 0) ? facilities->winsize_out : facilities->winsize_in; + *p++ = (facilities->winsize_out == 0) ? facilities->winsize_in : facilities->winsize_out; } len = p - buffer; buffer[0] = len - 1; - + return len; } diff --git a/net/x25/x25_timer.c b/net/x25/x25_timer.c index 1bdc23831b96..26266327178d 100644 --- a/net/x25/x25_timer.c +++ b/net/x25/x25_timer.c @@ -47,7 +47,7 @@ static void x25_timer(unsigned long); void x25_set_timer(struct sock *sk) { unsigned long flags; - + save_flags(flags); cli(); @@ -66,7 +66,7 @@ void x25_set_timer(struct sock *sk) static void x25_reset_timer(struct sock *sk) { unsigned long flags; - + save_flags(flags); cli();