]> git.neil.brown.name Git - history.git/commitdiff
Import 2.1.22 2.1.22
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:12:51 +0000 (15:12 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:12:51 +0000 (15:12 -0500)
162 files changed:
Documentation/00-INDEX
Documentation/Changes
Documentation/Configure.help
Documentation/memory.txt [new file with mode: 0644]
Documentation/pcwd-watchdog.txt [new file with mode: 0644]
Documentation/watchdog.txt
MAINTAINERS
Makefile
README
arch/alpha/defconfig
arch/i386/boot/compressed/misc.c
arch/i386/boot/setup.S
arch/i386/config.in
arch/i386/defconfig
arch/i386/kernel/irq.c
arch/i386/kernel/setup.c
arch/i386/lib/semaphore.S
arch/ppc/config.in
drivers/block/README.fd
drivers/block/floppy.c
drivers/block/ps2esdi.c
drivers/block/xd.c
drivers/char/Config.in
drivers/char/mem.c
drivers/char/misc.c
drivers/char/pcwd.c
drivers/char/tpqic02.c
drivers/char/wdt.c
drivers/net/3c523.c
drivers/net/atp.c
drivers/net/dlci.c
drivers/net/eql.c
drivers/net/hdlcdrv.c
drivers/net/ibmtr.c
drivers/net/lance.c
drivers/net/lapbether.c
drivers/net/net_init.c
drivers/net/pi2.c
drivers/net/ppp.c
drivers/net/scc.c
drivers/net/smc-mca.c
drivers/net/strip.c
drivers/net/tunnel.c
drivers/net/wavelan.c
drivers/net/wic.c
drivers/pci/pci.c
drivers/scsi/sd.c
fs/dquot.c
fs/ext2/symlink.c
fs/fat/misc.c
fs/namei.c
fs/ncpfs/inode.c
fs/nfs/nfsroot.c
fs/nfs/rpcsock.c
fs/smbfs/inode.c
include/asm-alpha/semaphore.h
include/asm-i386/semaphore.h
include/linux/atalk.h
include/linux/ax25.h
include/linux/bios32.h
include/linux/fd.h
include/linux/in.h
include/linux/in6.h
include/linux/lapb.h
include/linux/lapbether.h [deleted file]
include/linux/module.h
include/linux/net_alias.h
include/linux/netdevice.h
include/linux/netrom.h
include/linux/notifier.h
include/linux/pci.h
include/linux/rose.h
include/linux/route.h
include/linux/skbuff.h
include/linux/socket.h
include/linux/sysctl.h
include/linux/watchdog.h
include/linux/x25.h
include/net/arp.h
include/net/ax25.h
include/net/ip.h
include/net/lapb.h
include/net/netrom.h
include/net/rose.h
include/net/route.h
include/net/scm.h
include/net/sock.h
include/net/x25.h
init/main.c
kernel/sched.c
kernel/sys.c
net/802/Makefile
net/802/llc_macinit.c
net/appletalk/ddp.c
net/ax25/af_ax25.c
net/ax25/ax25_in.c
net/ax25/ax25_out.c
net/ax25/ax25_route.c
net/ax25/ax25_subr.c
net/ax25/ax25_timer.c
net/ax25/sysctl_net_ax25.c
net/core/dev.c
net/core/dev_mcast.c
net/core/iovec.c
net/core/net_alias.c
net/core/scm.c
net/core/sock.c
net/ipv4/af_inet.c
net/ipv4/arp.c
net/ipv4/devinet.c
net/ipv4/fib.c
net/ipv4/ip_forward.c
net/ipv4/ip_input.c
net/ipv4/ip_options.c
net/ipv4/ip_sockglue.c
net/ipv4/packet.c
net/ipv4/raw.c
net/ipv4/route.c
net/ipv4/tcp.c
net/ipv4/udp.c
net/ipv6/addrconf.c
net/ipv6/af_inet6.c
net/ipv6/datagram.c
net/ipv6/ipv6_input.c
net/ipv6/raw.c
net/ipv6/sit.c
net/ipv6/udp.c
net/ipx/af_ipx.c
net/lapb/lapb_iface.c
net/lapb/lapb_in.c
net/lapb/lapb_out.c
net/lapb/lapb_subr.c
net/lapb/lapb_timer.c
net/netbeui/netbeui.c
net/netrom/af_netrom.c
net/netrom/nr_dev.c
net/netrom/nr_in.c
net/netrom/nr_out.c
net/netrom/nr_route.c
net/netrom/nr_subr.c
net/netrom/nr_timer.c
net/netrom/sysctl_net_netrom.c
net/netsyms.c
net/rose/af_rose.c
net/rose/rose_dev.c
net/rose/rose_in.c
net/rose/rose_link.c
net/rose/rose_out.c
net/rose/rose_route.c
net/rose/rose_subr.c
net/rose/rose_timer.c
net/rose/sysctl_net_rose.c
net/socket.c
net/unix/af_unix.c
net/x25/af_x25.c
net/x25/x25_dev.c
net/x25/x25_in.c
net/x25/x25_link.c
net/x25/x25_out.c
net/x25/x25_route.c
net/x25/x25_subr.c
net/x25/x25_timer.c

index 72030a072f0ec1c2deda607411f5644a430fafc6..09d482dac082167c0a42bca9aafaabc3924dd312 100644 (file)
@@ -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
index 7dccb468646d5cbe0acd8195bf2b77c6e24a32bb..571fcede51765a9c3a7b7da140e21d65cf7db208 100644 (file)
@@ -49,7 +49,8 @@ General Information
    <CTRL><ALT><DEL> 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
index a15ec3d9262f82cf4e213c149c93e1d86ed5ba1d..44269f1e740fc2fce0b81eb50f0ae2803eb3661e 100644 (file)
@@ -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 (file)
index 0000000..8e43d27
--- /dev/null
@@ -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 (file)
index 0000000..878ca69
--- /dev/null
@@ -0,0 +1,131 @@
+                     Berkshire Products PC Watchdog Card
+                   Support for ISA Cards  Revision A and C
+           Documentation and Driver by Ken Hollis <khollis@nurk.org>
+
+ 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <linux/pcwd.h>
+
+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)
index 940313a9448b4e46d8e20f24b4bbe6ef20e35565..1a398dc4b4c6d25dd8dbe347475f84a8155456ad 100644 (file)
@@ -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.
index c4bc03fae76352b6d675edab07321e6f79925ee9..7da57b73699f17d3a7f749f9181737606a0a0988 100644 (file)
@@ -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
index cbad89bd492ef18fdc948916e0a462c394a8b012..46be0ab21d166f2cb7c5474bff0d07da70977bd4 100644 (file)
--- 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 20e3b83bc675c951659a5149a90b8cabc3ed393c..0eeb9ff85bdacc24aaecfad0bf2c31fa64e37abf 100644 (file)
--- 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). 
index bc4f937e5ca3322b67580650e748f60040f7ab57..1998d0814c69c0e9f43bd6c35084a1e7ec3ff0f2 100644 (file)
@@ -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
 
 #
index 296517feea0c55c265f61d92bb3cd9a299b6c370..76d0dd160d99f490c8697fd3fee63251318cdcc0 100644 (file)
@@ -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 */
 }
 
index 65b6acf729f76dc1d9bfdea5030c2d12d9d3594b..3ded0974b8ad9d8ee1cc075044673d871dc8309b 100644 (file)
@@ -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
 
index 957d0f0ca8da0e9c7b07d4a06307adf24ed0fb2c..13e2e8c401e3e9b597643cf389eb4b8faf9619d8 100644 (file)
@@ -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
index 7b0d67bd874705f41a7362d16441bcbdf6d9926d..4ed71aa03ec0525045d72a7ccfe9c2cfd4398701 100644 (file)
@@ -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
index e131e5a45af683bb08995a6b2958149f94baa00b..541af11289b94d27dc70690230feb9d837db9563 100644 (file)
@@ -285,7 +285,7 @@ int get_smp_prof_list(char *buf) {
                for (j=0;j<smp_num_cpus;j++)
                        len+=sprintf(buf+len, "%10d ",
                                int_count[cpu_logical_map[j]][i]);
-               len += sprintf(buf+len, "%c %s\n",
+               len += sprintf(buf+len, "%c %s",
                        (action->flags & 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);
index 112ebcf32af287d70ba702ef8b1eab90bf2d8019..950a4ff66d32d82114695abdf2098223c40627f8 100644 (file)
@@ -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;
index f2d11099f8f80207a44c84132d91d6232e4c7f6b..ff2443c40daf296b368036d835f3caf5267865f3 100644 (file)
@@ -7,21 +7,26 @@
 #include <linux/linkage.h>
 
 /*
- * "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
 
index bf436ceebd08406598ca0e0669d8e0a6ed011612..56c636d2a1a4164925c1ac435b0f3fd6a8a19e51 100644 (file)
@@ -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
index c3742498c68934ec23195a7426f3fb8a29a2bd37..3ceb16c0bedad3a2f5865b54b51c44f8cc7bc375 100644 (file)
@@ -49,14 +49,9 @@ isn't, use the old method using environment variables.
 
  The floppy related options include:
 
- floppy=<mask>,allowed_drive_mask         
-       Obsolete. Use the floppy=<drive>,<type>,cmos option instead
-
- floppy=all_drives
-       Obsolete. Use the floppy=<drive>,<type>,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:
 ==================================================
index 90d8280ce43a9b6c20b0a016a6a6688abd404b91..8271ff9bd74dd51c93cc3f71a222b11f42c7a2fc 100644 (file)
@@ -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
index 29ee6277e8a9d1781222591cf90a54d2d9291f21..6d8803442c531a7fcc6f68d1de9e4a68644817d6 100644 (file)
@@ -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)
index c85ca6b58daf1a09f9a72e35a9e94a81e5e414e9..3aab0f871675b32c80c0d100ba48758f79baa6fd 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/fs.h>
 #include <linux/kernel.h>
 #include <linux/genhd.h>
+#include <linux/hdreg.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
@@ -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 */
index 0905205f141bd6e5d26f526d8f0cfbcc4bcd3e0a..256e514c65ee68003defb6346e3642cf3fa6c2e8 100644 (file)
@@ -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
index 36764df22da5ba2b7a22564b6e023bfe2096a4a6..8f223e986e1d4f5a3d6fab3b760d68808be465f8 100644 (file)
@@ -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;
 }
 
index d3cf60d9733817121f39de5ab540cd882351ddc6..036e78d124c001be0d9baedc30ac205bc0765abd 100644 (file)
@@ -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();
index 783a36e2534bfa2b1a7357e43054e1de6e22cd42..198dfed881509283e8384cc7bee48e9a4c9c01e0 100644 (file)
  *             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 <linux/module.h>
 #include <linux/fs.h>
 #include <linux/mm.h>
 #include <linux/watchdog.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
 
-typedef struct pcwd_ioports {
-       int first_port;
-       int range;
-} IOPS;
+#include <asm/uaccess.h>
+#include <asm/io.h>
 
 /*
-** 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?)
-*/
index c67cdc7056e8ba0516a90cf0a8ea3b4e70192367..1d7e97ec9a52366f0fd07102a636698c1f1e8119 100644 (file)
@@ -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;
        }       
index 216bb1f73cfc5b60520a33c764360eb6f8181aa9..957df12999f2d8a6226d017cc3daa8939e794547 100644 (file)
@@ -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 */
 
index 8ac249c59348960b4593946595b6796da7a2f85f..21b411b6636d2a8f58edd5be4793b49e95b981ea 100644 (file)
@@ -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 {
index 6017a6743c0359bce238e7775dc96c172181c271..466fb821fcac8e99a5f8f80b4a6550ae671af4e3 100644 (file)
@@ -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;
index 191d82d0af695acfbee795a34eda23ed62aaec20..eeb629c14103c4a818acae09206e140849f2c87e 100644 (file)
@@ -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)
index 0ff21a9f0664503b112e1ff3d5b055b78f915cc4..7ea10dc233f0ff67677562c4c798bb72035e756c 100644 (file)
@@ -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);
index 32cbbdb03431cebb2a9768b9f82631e85e82b5b7..eca6f6f626a01bc4edd80e2b15992fd73951d45b 100644 (file)
@@ -50,6 +50,7 @@
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/hdlcdrv.h>
+#include <net/ax25.h>
 
 /* make genksyms happy */
 #include <linux/ip.h>
@@ -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)
index fd6c78b5581dacd3b4680511944f175a18df7d28..97fc35e3ee677420ab10ee95f2bab1f69306643e 100644 (file)
@@ -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 <pnorton@cts.com>\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 <linux/kernel.h>
 #include <linux/sched.h>
@@ -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) {
index b8bb6ac9be7f24f2ba3445e520513be010818d37..3104e1de966051781fdd81ea574cfde911c42099 100644 (file)
@@ -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)
index 37eb26e65323c9ad66ec44c22d48da7b331edeb8..40e1c44a5786eb7b0cb7b576de02335cebadf448 100644 (file)
 #include <linux/net_alias.h>
 #include <linux/lapb.h>
 
-#include <linux/lapbether.h>
-
 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);
 
index 3a8d48b10fdbff743c3ace76c0b827fbed8bcb94..37987960b00be79b2a31708628703f05b37210df 100644 (file)
@@ -38,9 +38,7 @@
 #include <linux/trdevice.h>
 #include <linux/if_arp.h>
 #include <linux/fddidevice.h>
-#ifdef CONFIG_NET_ALIAS
 #include <linux/net_alias.h>
-#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;
index 498ff4b6ce75c06c9135337c4d60a5fbbfb3e4ed..0dd7b5d46a43e98021debfb66eccc08812c4e323 100644 (file)
@@ -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;
index 10244b7e66165089610486d272af88423f853e4a..3f21195e6447868cf28fe2d1fbd49941907f6da0 100644 (file)
@@ -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
  *************************************************************/
index 8e1a465bbc4bc81f220f171423b082c25f4b885b..0dfb7c623d55719b430b76da8f0a76c6706dad4e 100644 (file)
@@ -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"
                  * 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, 
index b2721cfa99abf931ec8cf2fab90d1bd7723075b6..3188c8240badda92d7598f8ae7ba00fb10a831b8 100644 (file)
@@ -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)" );
index 3f420d1734a33bc692cb0c0ca6c5600816705c00..47517b1e15fb4c89be6f04806b85e02b41b76973 100644 (file)
@@ -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
index 55c14db31c4da6a339db24b6a01f909680179aff..30cea81967e0d0eb9353d71154e5f12327e49675 100644 (file)
@@ -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);
index b6f6d3ada4c8f094b124cd61a8f36e337054e337..81749fa9c0e0a8b082eb4458cb61b4f90d5fb165 100644 (file)
@@ -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) */
index 894128ade859da284ad029bcc20f8ea51e759a7c..dce1bb3f2a0e5a35c2126e1476c5ac03329f318d 100644 (file)
@@ -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;
 }
 
index 378f33ddd89af35e8ae93c4e7ce39842edb82afa..b053aaf431cb2bbd98e976e24aca44d75a45c61b 100644 (file)
@@ -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";
index 863a782c16967d197bc6c5620be4eb9090f53c2e..e20baf99e0c12929a6e2e43586de5dda73f97566 100644 (file)
@@ -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);
 
index aa3c5e517a202522798d2ad193f91eedcc492973..7720af505b2a51a43a3466a113c57a2b420e0bcb 100644 (file)
@@ -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)) 
index fca0f7923c00fa90a893f12134a8b7df9d1d3cf9..ef4dd5226da1d8111cafd88b26b6904add69813d 100644 (file)
@@ -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;
index ce8dde69a5b8f3ea9a7712799d028c825cfbb109..092823bad96aef9c0eb1d6bebb7298d38176fef9 100644 (file)
@@ -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)
index b969615eee888ebc2acc3286eab395054759d965..3523ceaed2ece0932b48b663e227b96a34e1403a 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/mm.h>
 
 #include <asm/uaccess.h>
+#include <asm/unaligned.h>
 
 #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;
index a6ddf3fbd687c85eede7fde1b175d8974fe72eb1..180f4e9e99286cb3eabb8c4be13d13466919515b 100644 (file)
@@ -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
index bbc17c28f1f5e8b85abe27a2050c3c34fdb2586a..e39a471d2ba3f1ffb6a4bab4373fb8a2c5bfb5ca 100644 (file)
@@ -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;
index e5021d940221a1fcba76df02e8bd7cdef8f04406..d3415041bffe8223629d897b019decd24b3fe8a0 100644 (file)
@@ -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;
        }
 
index a8227ba51d008667328f818556df2caea0857ece..efc5a7f308658ea249900607003adeec09753a63 100644 (file)
@@ -444,8 +444,6 @@ EXPORT_NO_SYMBOLS;
 int
 init_module(void)
 {
-       int status;
-
        DPRINTK("smbfs: init_module called\n");
 
 #ifdef DEBUG_SMB_MALLOC
index 210c2a5b3501dbf69403fb5d517b6b787e4e0ccb..d6ed29385627fbc9558bc9e58deff786d26709ca 100644 (file)
@@ -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)
index 930b39edb8333b45096a093459e3ea6409b36041..0c6c13e9c062d99e718f7921fed4a7a4f5aa4ac2 100644 (file)
@@ -7,11 +7,21 @@
  * SMP- and interrupt-safe semaphores..
  *
  * (C) Copyright 1996 Linus Torvalds
+ *
+ * Modified 1996-12-23 by Dave Grothe <dave@gcom.com> 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");
 }
 
index 7b7242c7f97248e8f8cd3a8bcb39b1d8c008496e..0dc30f8eaff885e710d5cd44644156f37153b00a 100644 (file)
@@ -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);
index 7cf2c64109596c87018ccef9e5de1b3d371be013..8f255da82f116acb1c80855016c8720e7737b43c 100644 (file)
@@ -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
 
 #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
 
 #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
index d3632092a6d55a97cececa0f2b3562a2b052c4e0..7944a53fe40c28bfad7c8ea1cc9d75c579ea4a8b 100644 (file)
@@ -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 */
index a05cf3900c668d3d4d73b0db3dfbe4732076c75c..da7293c35b1c9f10081170e9e7985ac13887c1a9 100644 (file)
@@ -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? */
 
index 20fd2f86aabb8e608359dfe8e31af5f8f25efa25..5383ed6f1ddc3fbeafc482387e5ab56685b8a068 100644 (file)
@@ -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. */
index 30d0ae2db99d52bc3da0ba8b92ce8154fc41a7e4..23552fb32ba7fc0a6f3457c76870f4ea1532255a 100644 (file)
@@ -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
 };
index 0d1ff4e7977e6d425b61ddbcbcb9e829de57bc10..bf1825a6b0fba92b04514355844ddcbe7fd2e5a9 100644 (file)
@@ -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 (file)
index b528c37..0000000
+++ /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 <linux/if_ether.h>
-#endif
-
-#define SIOCSLAPBETHADDR       (SIOCDEVPRIVATE+1)
-struct lapbeth_ethaddr {
-       unsigned char destination[ETH_ALEN];
-       unsigned char accept[ETH_ALEN];
-};
-
-#endif
index 556f4b4cae3e7adafa6da510975910a3e02556ad..853acca8f59db2c5b8961f8b8726f6356e0cb835 100644 (file)
@@ -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
index c31df3a36c32262123f6a2a873022b22984419d7..54ba8525c974d1129b24b9aedbbd774eb99741ab 100644 (file)
@@ -18,6 +18,8 @@
 #define _NET_ALIAS_H
 
 #include <linux/config.h>
+
+#ifdef CONFIG_NET_ALIAS
 #include <linux/types.h>
 #include <linux/if.h>
 #include <linux/netdevice.h>
@@ -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 */
index 4a99e5062715240b41f2ee823d4abd43a62a0c49..1efdf1393a4f1225ea1aad5b91fac257cd725b85 100644 (file)
@@ -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<MAX_ADDR_LEN/sizeof(unsigned); i++) {
-               unsigned h = p[i];
-               h ^= (h>>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__ */
 
index 8732761bd0072761d8b4dc3fcb8318ddbf9a66a2..e14f183aee506a9e3892c014f0ff594d41e62c3b 100644 (file)
@@ -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
 
 
 #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
index 7425e3b70c717399f1dde62bbf2baaf04298cb94..4ac590f0296a97a6047bcf943cc0be2e978fcb09 100644 (file)
@@ -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 */
index 41e6d632c0446362921270dadaf8472c71fa4046..b92191a3dca6c43e77739b374bf7459133a69144 100644 (file)
 #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
 #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
 
 
 #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
 #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
index 4fe0c8fa50bd667c2ee3b7fbefab3ac6ab9f569e..cd69214c347f83e331cd2507a53afc3c6c61d343 100644 (file)
@@ -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
 
 
 #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
index 95e47ed90fdbca4aed9945c53a2735531725aec5..3214294c878714cd59f3f95a2e799a89eda46c85 100644 (file)
@@ -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;
index 480139021ef7ca2e5152f340eaaaa2a998863716..0998a97414653fcf5f89cc9faaca0f84fbc466e8 100644 (file)
@@ -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;
index 28a6bb18e193f4adddb6b02a52cac992410a5aa5..3e594a90bc7b7e8eec32b2ec8f4635e55ef721d6 100644 (file)
@@ -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
 
index cafbf031e68d7383006240db33470595f69f5bac..37f6f0b0ac71c5d6861c8ef69cce94819230fe35 100644 (file)
@@ -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 */
index f9f08c660ba0fa5b4fc17fa3d74efbe811bf6d31..3f358258be0df20025654d9ae3668f33c51fdda7 100644 (file)
@@ -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 */
index 7c49cf33bd6994349625ac05ab08ff019576c989..6af8e9a5bc6d2e74aefe9d357346ca5075f8f29c 100644 (file)
@@ -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
index 405951b3a807a7230f79b3b1f9f48cf7e1af4797..e02b388c20be5c8833e71446d70b634cd221d753 100644 (file)
@@ -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);
index 42875ba79c22f81facbd202d1441da56929f387e..7b1ddd50fda4e38046dcf6945d69a958659f7144 100644 (file)
@@ -8,45 +8,43 @@
 #define _AX25_H 
 #include <linux/ax25.h>
 
-#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 <linux/netdevice.h>
 /* 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 **/
 #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
index 97227ec235dc85a2b78ae77210ad5ed7f3e7365b..c0e600a3754177ddf10f293ab93382b9d9fff4ea 100644 (file)
@@ -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);
index e974dc27686b2a696c82eca6271f7671c58a6c29..d6c87f7b323d73e4e0c8e3b281fbbb8b26d51f5e 100644 (file)
@@ -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
index 5427bdf0257442d4d7205d3b0f54d66bf1437b88..baa94d6007dd249dc94c1f20a0b3bbcd272f63a0 100644 (file)
@@ -3,50 +3,59 @@
  *
  *     Jonathan Naylor G4KLX   9/4/95
  */
+
 #ifndef _NETROM_H
 #define _NETROM_H 
 #include <linux/netrom.h>
 
-#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 *);
 
index f24d2cd690716aa363581e4f235fa53fab8b0fb0..03b92d652f2431bb19ff48ecf1b1004a9863a0a5 100644 (file)
@@ -3,20 +3,22 @@
  *
  *     Jonathan Naylor G4KLX   25/8/96
  */
+
 #ifndef _ROSE_H
 #define _ROSE_H 
 #include <linux/rose.h>
 
+#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
 
 /* 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 *);
index 3c1d06a9572e2a801799824e62e77d873f693ade..f5cafb8ab98861c790badb6c2900f62eacb9fa32 100644 (file)
@@ -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);
index 11dfadde4ab8abde2b231721df453a035d673d24..d8bb8d1ebf02d4314a8c1b18832adc6d2c7cecd5 100644 (file)
@@ -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);
 }
index 8fc63808e47c703957f29f59c7a4df4beb303cd8..15104ef81f813d480053ffc8daa61570875b8d11 100644 (file)
@@ -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);
index fedc80a614434d930859d253a028dc951c7a939e..8a1b81f4c1fd3b89971a6fdef71fa7515d49af41 100644 (file)
@@ -3,7 +3,7 @@
  *
  *     Jonathan Naylor         17/11/96
  */
+
 #ifndef _X25_H
 #define _X25_H 
 #include <linux/x25.h>
@@ -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 *);
index 070f9e62a425d2bdf9fc77a2647541574a8e9cc5..d3b746e6c0ba561dbee53edfca1d4f059429a5b5 100644 (file)
@@ -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.");
 }
index 8d13c21a62b7ec9e4b0df69289fdbce081dd2b99..09697cf3fc5aeadff1c13183f8f08899cd734ae7 100644 (file)
@@ -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;
index 7018cf662d214b57ca6424ccd83047a83096c599..bdd06e83b819e21221df135791d81bf503ef0b14 100644 (file)
@@ -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,
index 45ef8e410f15a4c0b9fda3c8cde633646c5ce7e2..c32b0950618cbd9965b1a366e1ac7cff0eb41578 100644 (file)
@@ -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
 
index 8e3374106ef30714443f2300783ed89c241a8caf..f420997441ee8ef89f5e589cc026d456cb866c4c 100644 (file)
@@ -19,6 +19,7 @@
  *                                     Started restructuring handlers
  */
 
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/version.h>
 #include <linux/kernel.h>
index 2d5e3d9fb4fcbfd54f8f06c96ea9c2ddf9dda341..cdbbba3fd1dd285e58c2301555e9d012298395ac 100644 (file)
@@ -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
 };
index dbb6b692fbdf3da1d670beb9340bb70cd6c36eb8..4b69a7dafce3235620c6941b60e3f33c9e30c8f2 100644 (file)
@@ -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
  */
 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
index 1e94adfda053ef34403172e8f4290761c4a7d5f4..3320cdcd3131b41eb0f73d599a86e9de923275b9 100644 (file)
@@ -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;
 
index a12f18fa544b3521704fdcc227d88d92d20d4ee9..2ebb77f560666d0267546351db6bc0d522b2f1bb 100644 (file)
@@ -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);
 }
 
index 4ad193d3b0d0e68ee4667acddc9a857ff2c9c8f7..afbe00cd4bd70387fda26a740b81584c88431e69 100644 (file)
  *                                     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 <linux/config.h>
 #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
 #include <linux/errno.h>
@@ -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
-            
index aac8d7eb8849baa0a24aa65c3ab47d86e5559032..e4274aeac84b917cc047220033be012e1e54a2cf 100644 (file)
@@ -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 <linux/config.h>
@@ -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);
 }
index d07465c94e62c953b6e0b4615aca9c4db9e09f56..398563f87a0e7e9f0a6acc10e93e4ed2bbc0a56e 100644 (file)
@@ -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 <linux/config.h>
@@ -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
index 302d210f80093d08aeaacf4233a865128c39865a..da40a3dbb800efe7b68822cd39b4d54c61dddc7e 100644 (file)
@@ -9,10 +9,10 @@
 #include <linux/sysctl.h>
 #include <net/ax25.h>
 
-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;
 
index 14addfb7fbefb8c799d2c72c64f16cd31d0a063c..c7122e2b4b8f85d14272c6963a82270773c19b98 100644 (file)
@@ -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();
                }
        }
 
index f86bc158b398b9162496c0b75bbb84713e06035e..4aa6cbb0c33e2007f7a04deeb924d9686d26e047 100644 (file)
@@ -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);
index 80bd3e0177f0cf8592b6f0263b25b5e431a528d6..1acdc47d19136075f8efa23d1e68488fd381adb4 100644 (file)
@@ -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);
index 54aafeadf90eeecba3955ee1070ad8259ef2480a..147f31436379be96567f2f1ae934babd23a2593c 100644 (file)
@@ -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)
index 2ca00d5b203844fa58005448d05eb6c41c027539..481f69f4f1579bf6293562de1d82ab3c37ff512a 100644 (file)
@@ -8,6 +8,7 @@
  *             2 of the License, or (at your option) any later version.
  */
 
+#include <linux/config.h>
 #include <linux/signal.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
@@ -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.
         */
index b822b3fb93f21bff18cb745de57eb589c5b6a2b6..bd08736d495c773ae636142398de25ae46cf6976 100644 (file)
@@ -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;
+
+}
index f5b6920d8c55c3bfd6f847537d0959296b3d1281..ff390e6e33431a40d70492c98d8554c4ec10b377 100644 (file)
@@ -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
 };
index 44b962cb4a728de53390ffcd1d2fc14cb66b40ba..8a95ece71f41b6f830a7929e061f23c297936513 100644 (file)
@@ -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)
index e49ff05824f2d8d82bb04ac2e23b66c6d2fff70a..da0685340858f3c771d6954aec3dcad561402e5c 100644 (file)
@@ -43,9 +43,7 @@
 #include <net/sock.h>
 #include <net/arp.h>
 #include <linux/notifier.h>
-#ifdef CONFIG_NET_ALIAS
 #include <linux/net_alias.h>
-#endif
 #ifdef CONFIG_KERNELD
 #include <linux/kerneld.h>
 #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;
index f73d2ab7f2af0f219c51d0757c3147fe98c8c957..e99bf15edac645d567e488b2e219b613d16c922d 100644 (file)
@@ -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;
 }
index 94fbcbbe673304afe8f354b342a13d9adc5eea8e..5f4d3562084f39c38d81b72081a77c7a0adc9d3e 100644 (file)
@@ -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);
index 95c59709a1624bf8c71dca73934138417f50d489..850d729e8982aef663c3ecf396d25f42c27e322e 100644 (file)
 #include <linux/firewall.h>
 #include <linux/mroute.h>
 #include <net/netlink.h>
-#ifdef CONFIG_NET_ALIAS
 #include <linux/net_alias.h>
-#endif
 
 /*
  *     SNMP management statistics
index f24f4dc38eb04df1058783712502b696c7485c00..2c79745064c4dbb106c1401ba4c8a26a81c794ca 100644 (file)
@@ -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;
index 0d7584cfd40947cf1f3c9cf8e056c33aed7bfbc1..2be8be45615290ca9f1d18109b0272503b441a65 100644 (file)
  *     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);
        }
index c0ddaa2175ca99173c0ea1d65078c335ca7af971..8187b20c8793b0c4426a5fd4e3c981a9bed73937 100644 (file)
@@ -248,6 +248,7 @@ static void packet_close(struct sock *sk, unsigned long timeout)
        }
        
        release_sock(sk);
+       sk->dead = 1;
        destroy_sock(sk);
 }
 
index 4b4918df4be9a0f15a7c87bbfefbe47a7e0a3429..69a2bd476ff7f84fd5808de4f318b4b0503892ed 100644 (file)
@@ -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);
 
index 9f6382f59c06932f3b72d2ac2ad58163c3926c5b..a39d256f406708d16029b99ea7d59ac23efddf1a 100644 (file)
 #include <net/sock.h>
 #include <net/icmp.h>
 #include <linux/net_alias.h>
-  
+
+/* 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<<res.fm)-1)))|fi->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);
index fdb375ea73f89c1e61be06293c59df4e5d5d1582..bfb3259f30016d0632c18aba8c125a074f6eeaa6 100644 (file)
@@ -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
                                 */
index 440a81369f3b41889e9b98e073c1ce79830fa2eb..705c9dfe15d8b56d70ad3fe1ed92904bc0290fb7 100644 (file)
@@ -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);
 
index f812ab0a35a07d27e150d38c75a796caa2f97faf..30f32d99cfe002d3f989e69e8f79e0440bd44c3b 100644 (file)
@@ -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
  */
index c1b9d1f028e6224176d91df818fd2b770e57ca1d..dc545116a449749bdc836b952c534e0c28416ba2 100644 (file)
 #include <linux/ip_fw.h>
 #include <net/addrconf.h>
 
-/*
- *     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++) 
index bc138c178befb85c5ff3254adef13048fad65789..a9eb6ab5cd4163fa7d5f82044f797a215e7cffdf 100644 (file)
@@ -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;
 
index ba1a00ab699d3ad490ab0d16bd18e87f179c0aec..e02802c2554a82535f012cda6eeed6ff8ab5d07e 100644 (file)
@@ -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)
index 0775d1a605d76185bbbdca86bc0f51c6e12f96fa..ec090bad1d83778f54abd8f58fa3f475a1a113fc 100644 (file)
@@ -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));
index 7b13506fe29cb431b4919f47baba952f0da71d89..90267b7f1464e8d109ced0a320d2c0825de3f4d4 100644 (file)
@@ -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;       
 }
index fb6434b4599ddc055ff2b236003195dffbf857ad..6429a7cb283dd3326ba362c2db84ab793e961278 100644 (file)
@@ -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));
index 0247d0bb2ff6abc51370901b81c55f70b9e071af..035920e072c6bcb119eb58bd56bacc50db0180f9 100644 (file)
@@ -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
 };
index 12b48c991c1446acd4223a0f3fc024c74845364d..1f0e69942d04f5cf846699ceaf5a36d1154765bd 100644 (file)
@@ -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;
 
index 91d61db93df38070535ed59c1e7f7bb4fe55cf09..2671a26eaa5b0193768dec6210304ccc57570659 100644 (file)
@@ -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;
 
index 43481e41641667ef96d395dff2f1870b11ee5d7c..1d0f5e5cfac2f540d74c66321eefa29988a62073 100644 (file)
@@ -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;
 }
index 56117293ee0bf341c0c54ef1a34c4f9e57bc182a..271978d76b9b5b087a87c4b32b02f30b0311a623 100644 (file)
@@ -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;
 
index 6586056c651527548d850c757b15cbacd9e563ff..cf59172e51b7f7adffce965846a5885d9427c475 100644 (file)
@@ -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);
index 48be8e54586d2ac9bc37f547e8cc3da354bbab57..4392aa327314012d72445f9771ce040cf8adf99a 100644 (file)
@@ -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
 };
index e911abf88ea18638d8cfc40e2db0846e353950d3..75c9f77a7674a624e5f66e23612555130e1983f0 100644 (file)
@@ -31,7 +31,7 @@
  *                     Alan(GW4PTS)    Started POSIXisms
  *     NET/ROM 006     Alan(GW4PTS)    Brought in line with the ANK changes
  */
-  
+
 #include <linux/config.h>
 #if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE)
 #include <linux/module.h>
@@ -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
 };
index 997011304c946a033d4c8de99466043af6080c6a..4982ccb340c353f86f09a91fe129c00b9637c7af 100644 (file)
@@ -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);
index d2e9d53f0b1f5149a148b6f495904e1154305f6f..7e4d3ac81519f1e8f2a4a4c0855af7e4fe7a5ac7 100644 (file)
@@ -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;
index 777cf91398c8837a9aadd2fdef6eaba733c13134..af3e0e5c20131571e1d670137dbbf463db89ceca 100644 (file)
@@ -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)
index afd3fd0beb43d51d43afba1694d9a0db20d64896..70395ed40fc106945592cef7669f35c5a130ffdd 100644 (file)
@@ -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 <linux/config.h>
 #if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE)
 #include <linux/errno.h>
@@ -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;
        }
index ee8a4c4c1e3022cba45da2b8b934956b5f2c2e74..3f7928e10c1201454cc8a5cdef192f9113545fbf 100644 (file)
@@ -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 <linux/config.h>
 #if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE)
 #include <linux/errno.h>
@@ -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
index db5de2c53691a60bb08a5f5f92d133159ca6ba81..566f2a6f72669a780122167fe8832fe92a1f2263 100644 (file)
@@ -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) {
index 3cbc0b761cdb46344d21a1ba075c4a545a761fed..f6eac6179d1e98b441ab2a60a5e5e53588e4bb94 100644 (file)
 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}
 };
 
index a443e27ac0dabfc928d2c3f3692bebb7f17a20f5..09bd3a9c44c17557ab0483d83df54d7e49515ebe 100644 (file)
@@ -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 <net/sock.h>
+#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);
index 79f0150e0d51d90329f35610acf52c9a01d460d1..8f0b6895e6bec64aea836b6cad70943015c0295c 100644 (file)
@@ -18,7 +18,7 @@
  *                     Terry (VK2KTJ)  Added support for variable length
  *                                     address masks.
  */
-  
+
 #include <linux/config.h>
 #if defined(CONFIG_ROSE) || defined(CONFIG_ROSE_MODULE)
 #include <linux/module.h>
@@ -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);
index b21994894643c78b2194dcbdac040abe450d922e..b13680e90585e2d0c7d65fff73a0ca98e8a50089 100644 (file)
@@ -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);
index a7d2c49d2258830d41d7ca8fcd0474cc5346d906..e30d550b0a2a7641cf490faaedc98f80cb34fbca 100644 (file)
@@ -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;
 
index 4b1d63c4482a9cb82f95983d7d020a08984c9102..bab651fc4f54565304e431db3d53e400599f263c 100644 (file)
@@ -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;
index b58edeb706a838bb60665cc5e04506c8ba1cb71f..0ea18e522a1272b265854696d33767cb1c238cd3 100644 (file)
@@ -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;
        }
 }
 
index bc1073a9d81f8c1566f215c826c4183c45374cec..6ac59bcd8f911be435314409ada8c679ab6c13c4 100644 (file)
@@ -17,7 +17,7 @@
  *                     Terry(VK2KTJ)   Added support for variable length
  *                                     address masks.
  */
+
 #include <linux/config.h>
 #if defined(CONFIG_ROSE) || defined(CONFIG_ROSE_MODULE)
 #include <linux/errno.h>
@@ -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);
        }
 }
index 8a166f3aef7483e44087598c384719d30c5cb364..5befcbb601709394624e9d552db8d8a8cfebab78 100644 (file)
@@ -15,7 +15,7 @@
  *     History
  *     Rose 001        Jonathan(G4KLX) Cloned from nr_subr.c
  */
+
 #include <linux/config.h>
 #if defined(CONFIG_ROSE) || defined(CONFIG_ROSE_MODULE)
 #include <linux/errno.h>
@@ -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;
 }
 
index e56f9edb1ede9436c5f87984fedf94044e736833..77ebabb1e1ffe0fee1eb75f2e7fa52703f847b0c 100644 (file)
@@ -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;
index 6db89e155d450bd62bc6bffa22d4cc88d8ea5495..95234881756fbbd2a537293a95f26df26c51e5aa 100644 (file)
 #include <net/ax25.h>
 #include <net/rose.h>
 
-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;
 
index 591f3d7015b367a49b09d3bf320e375d10e81dd3..bb2ca908819445b7320561c0dc6f00812669e121 100644 (file)
@@ -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)
index 450396b0a38085c3fa7fb0f2c5b75d25f1b848bc..9490c29030b00cad3e8a2c1e097eda2d6ee3be98 100644 (file)
@@ -3,11 +3,6 @@
  *
  * Authors:    Alan Cox, <alan.cox@linux.org>
  *
- *             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
 };
index 843ca54a337df7525f5f5535ca97f7714445189b..e66c01a5ea9ae1912c0b8879a9e9db8238349dc3 100644 (file)
@@ -15,7 +15,7 @@
  *     History
  *     X.25 001        Jonathan Naylor Started coding.
  */
-  
+
 #include <linux/config.h>
 #if defined(CONFIG_X25) || defined(CONFIG_X25_MODULE)
 #include <linux/module.h>
@@ -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;
 }
index 5fca44cc86f087a36bb6b476fd54505ccbaf6ba3..b6ce9e1274518f0566f0fe8998da10ac1707f52b 100644 (file)
@@ -15,7 +15,7 @@
  *     History
  *     X.25 001        Jonathan Naylor Started coding.
  */
-  
+
 #include <linux/config.h>
 #if defined(CONFIG_X25) || defined(CONFIG_X25_MODULE)
 #include <linux/errno.h>
@@ -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;
        }
index 47da943cb39030b4d7377ff443d921d443a0298c..34b54ded4b0040fce364f1f447ea0a34bf83ef0b 100644 (file)
@@ -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;
 
index af75513f40e09409faa23b823698d4909a36555a..63ac3587a19d2f8192002921ab8fad07daefc913 100644 (file)
@@ -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);
        }
 }
index 5fe37d01c3e1e0c092ae1962358091a9674a0194..321baa5d6cf694b812ff351ef42d46de7ea67e90 100644 (file)
 #include <linux/interrupt.h>
 #include <net/x25.h>
 
+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;
                }
        }
 }
index 7a012374823eed24bb9acd1b24c639b21d7e55f6..fc1bfc54bfb4b474ba8a8906065de37a8d682637 100644 (file)
@@ -15,7 +15,7 @@
  *     History
  *     X.25 001        Jonathan Naylor Started coding.
  */
+
 #include <linux/config.h>
 #if defined(CONFIG_X25) || defined(CONFIG_X25_MODULE)
 #include <linux/errno.h>
@@ -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);
        }
 }
index 5b8cbb5acc2936c5b777ed46cbfb98b138960352..245109ee9ecbd59ab7f2f20c8abb40aff9c1674d 100644 (file)
@@ -15,7 +15,7 @@
  *     History
  *     X.25 001        Jonathan Naylor Started coding.
  */
+
 #include <linux/config.h>
 #if defined(CONFIG_X25) || defined(CONFIG_X25_MODULE)
 #include <linux/errno.h>
@@ -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;
 }
 
index 1bdc23831b96350e152fcf4a141223b6b773e3b4..26266327178dffdb360a80bd3309ed2fa962efe8 100644 (file)
@@ -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();