## Automatically generated incremental diff ## From: linux-2.0.40-rc6 ## To: linux-2.0.40-rc7 ## Robot: $Id: make-incremental-diff,v 1.12 2004/01/06 07:19:36 hpa Exp $ diff -urN linux-2.0.40-rc6/COPYING linux-2.0.40-rc7/COPYING --- linux-2.0.40-rc6/COPYING 1998-07-13 13:47:25.000000000 -0700 +++ linux-2.0.40-rc7/COPYING 2004-01-15 07:19:51.000000000 -0800 @@ -14,7 +14,7 @@ Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 675 Mass Ave, Cambridge, MA 02139, USA + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. @@ -67,7 +67,7 @@ The precise terms and conditions for copying, distribution and modification follow. - + GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION @@ -122,7 +122,7 @@ License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) - + These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in @@ -180,7 +180,7 @@ access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. - + 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is @@ -237,7 +237,7 @@ This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. - + 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License @@ -290,8 +290,8 @@ POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS - - Appendix: How to Apply These Terms to Your New Programs + + How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it @@ -303,7 +303,7 @@ the "copyright" line and a pointer to where the full notice is found. - Copyright (C) 19yy + Copyright (C) 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 @@ -317,14 +317,14 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: - Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. diff -urN linux-2.0.40-rc6/CREDITS linux-2.0.40-rc7/CREDITS --- linux-2.0.40-rc6/CREDITS 2004-01-15 07:19:51.000000000 -0800 +++ linux-2.0.40-rc7/CREDITS 2004-01-15 07:19:51.000000000 -0800 @@ -1547,10 +1547,12 @@ N: David Weinehall E: tao@acc.umu.se W: http://www.acc.umu.se/~tao/ +P: 1024D/DC47CA16 7ACE 0FB0 7A74 F994 9B36 E1D1 D14E 8526 DC47 CA16 +D: v2.0 kernel maintainer D: Miscellaneous fixes D: Cleanup of the Config-files -S: Axtorpsvagen 40:20 -S: S-903 37 UMEA +S: Västra Varmvattnet 63 +S: S-922 67 TAVELSJÖ S: Sweden N: Matt Welsh @@ -1671,14 +1673,10 @@ S: Germany N: Leonard N. Zubkoff -E: lnz@dandelion.com -W: http://www.dandelion.com/Linux/ D: BusLogic SCSI driver D: Mylex DAC960 PCI RAID driver D: Miscellaneous kernel fixes -S: 3078 Sulphur Spring Court -S: San Jose, California 95148 -S: USA +D: Rest in peace N: Marc Zyngier E: maz@wild-wind.fr.eu.org diff -urN linux-2.0.40-rc6/Documentation/Changes linux-2.0.40-rc7/Documentation/Changes --- linux-2.0.40-rc6/Documentation/Changes 2001-01-09 13:29:20.000000000 -0800 +++ linux-2.0.40-rc7/Documentation/Changes 2004-01-15 07:19:51.000000000 -0800 @@ -68,6 +68,10 @@ - Net-tools 1.32-alpha - Kbd 0.91 +Note that it is _very_ unlikely that you will be able to compile the +2.0 kernel with gcc-3.x or binutils 2.9.x, and even if it compiles, it +might not work properly. + Upgrade notes ************* @@ -107,7 +111,7 @@ use the new features you'll need to upgrade your bootloaders. Lilo can be found at ftp://lrcftp.epfl.ch/pub/linux/local/lilo/lilo.19.tar.gz. LOADLIN is at -ftp://sunsite.unc.edu/pub/Linux/system/Linux-boot/lodlin16.tgz. If +ftp://sunsite.unc.edu/pub/linux/system/boot/dualboot/lodlin16.tgz. If you're using more unusual loaders like SysLinux or etherboot, the latest versions are 1.3 and 2.0, respectively. @@ -169,7 +173,7 @@ in linux/fs/locks.c and recompile. If you're still running a.out, there's an unofficial libc-4.7.6 release out to which you can upgrade to fix this problem. Libc is available from -ftp://sunsite.unc.edu/pub/Linux/GCC/. +ftp://ftp.win.tue.nl/pub/linux-local/libc.archive/libc/. GCC Signal 11 error =================== @@ -198,7 +202,7 @@ upgrade procps to the latest release, currently 1.01. Otherwise, you'll get floating point errors with some ps commands or other similar surprises. Grab -ftp://sunsite.unc.edu/pub/Linux/system/Status/ps/procps-1.01.tgz. +ftp://sunsite.unc.edu/pub/historic-linux/ftp-archives/sunsite.unc.edu/Sep-29-1996/system/Status/ps/procps-1.01.tar.gz. Kernel Modules ============== @@ -206,8 +210,9 @@ Almost all drivers in 2.0.x can be modules, and kerneld is now incorporated into the kernel. To take advantage of this, you'll need the latest version of the module support apps. These are available at -http://www.pi.se/blox/modules/modules-2.0.0.tar.gz. Note: If you try to -load a module and get a message like +ftp://sunsite.unc.edu/pub/linux/kernel.org/pub/linux/kernel/v2.0/modules-2.0.0.tar.gz. + +Note: If you try to load a module and get a message like `gcc2_compiled, undefined Failed to load module! The symbols from kernel 1.3.foo don't match 1.3.foo' @@ -241,7 +246,7 @@ You need to be running a pppd from ppp-2.2.0.tar.gz or greater. The latest stable release is 2.2.0f and is available at -ftp://sunsite.unc.edu/pub/Linux/system/Network/serial/ppp/ppp-2.2.0f.tar.gz. +ftp://sunsite.unc.edu/pub/historic-linux/distributions/slackware/3.1/source/n/ppp/ppp-2.2.0f.tar.gz Named pipes (SysVinit) ====================== @@ -253,7 +258,7 @@ your computer shuts down fine but "INIT: error reading initrequest" or words to that effect scroll across your screen hundreds of times. To fix, upgrade to -ftp://sunsite.unc.edu/pub/Linux/system/Daemons/init/sysvinit-2.64.tar.gz. +ftp://sunsite.unc.edu/pub/historic-linux/ftp-archives/sunsite.unc.edu/Sep-29-1996/system/Daemons/init/sysvinit-2.64.tar.gz. If you're trying to run NCSA httpd, you might have problems with pre-spawning daemons. Upgrade to the latest release (1.5.2), available @@ -284,20 +289,20 @@ details. Among the programs this has impacted are older sendmails. If you get a message that sendmail cannot lock aliases.dir (or other files), you'll need to upgrade to at least 8.7.x. The latest sendmail -is at ftp://ftp.cs.berkeley.edu/ucb/src/sendmail/sendmail.8.8.7.tar.gz. +is at ftp://ftp.cs.berkeley.edu/ucb/src/sendmail/. Uugetty ======= Older uugettys will not allow use of a bidirectional serial line. To fix this problem, upgrade to -ftp://sunsite.unc.edu/pub/Linux/system/Serial/getty_ps-2.0.7i.tar.gz. +ftp://tucows.belgium.eu.net/pub/linux/slackware/slackware-3.3/source/a/getty/getty_ps-2.0.7i.tar.gz. Kbd === For those of you needing non-ASCII character/font support, you should -upgrade to ftp.funet.fi:/pub/OS/Linux/PEOPLE/Linus/kbd-0.91.tar.gz. +upgrade to ftp.funet.fi:/pub/OS/Linux/PEOPLE/Linus/old-kbd/kbd-0.91.tar.gz. Mount ===== @@ -306,7 +311,7 @@ currently at release 2.5. Some may find, especially when using the loop or xiafs file system, NFS, or automounting, that they need to upgrade to the latest release of mount, available from -ftp://ftp.win.tue.nl/pub/linux/util/mount-2.5p.tar.gz. +ftp://ftp.win.tue.nl/pub/linux/utils/attic/mount/mount-2.5p.tar.gz. Console ======= @@ -321,14 +326,15 @@ ln -s /usr/lib/terminfo/l/linux /usr/lib/terminfo/c/console Better yet, just get the latest official Linux termcap from -ftp://sunsite.unc.edu/pub/Linux/GCC/termcap-2.0.8.tar.gz. If you -upgrade to this release read the `README' file contained into the -package to get some important information about the `tgetent' function -changes! Note that there is now a fixed version at -ftp://sunsite.unc.edu/pub/Linux/GCC/termcap-2.0.8.fix. If some of your -apps complain that termcap entries are too long and you don't need some -of the more esoteric terms in the standard 2.0.8 termcap, just download -termcap-2.0.8.fix and move it to /etc/termcap. +ftp://sunsite.unc.edu/pub/historic-linux/distributions/slackware/3.1/source/d/libc/termcap-2.0.8.tar.gz. +If you upgrade to this release read the `README' file contained into +the package to get some important information about the `tgetent' +function changes! +Note that there is now a fixed version at +ftp://sunsite.unc.edu/pub/historic-linux/ftp-archives/sunsite.unc.edu/Sep-19-1996/GCC/termcap-2.0.8.fix. +If some of your apps complain that termcap entries are too long and +you don't need some of the more esoteric terms in the standard 2.0.8 +termcap, just download termcap-2.0.8.fix and move it to /etc/termcap. Also, the console driver is now responsible for keeping track of correspondence between character codes and glyph bitmaps. If you @@ -340,7 +346,7 @@ Hdparm has been upgraded to take advantage of the latest features of the kernel drivers. The latest non-beta version can be found at -ftp://sunsite.unc.edu/pub/Linux/kernel/patches/diskdrives/hdparm-3.1.tar.gz. +ftp://sunsite.unc.edu/pub/linux-historic/ftp-archives/sunsite.unc.edu/Sep-19-1996/kernel/patches/diskdrives/hdparm-3.1.tar.gz. IP Accounting ============= @@ -354,7 +360,8 @@ There also exists a possibility to match on device names and/or device addresses, so that only packets coming in/going out via that device (network interface) match with a rule. You'll need to get -ipfwadm from ftp://ftp.xos.nl/pub/linux/ipfwadm/ipfwadm-2.3.0.tar.gz to +ipfwadm from +ftp://ftp.sunsite.auc.dk/disk2/slackware/slackware-8.0/pasture/pasture-sources/ipfwadm-2.3.0/ipfwadm-2.3.0.tar.gz to use this. IP Firewalls @@ -367,7 +374,8 @@ so that only packets coming in/going out via that device (network interface) match with a rule. This is especially useful to prevent spoofing. You'll need to get -ftp://ftp.xos.nl/pub/linux/ipfwadm/ipfwadm-2.3.0.tar.gz to use this. +ftp://ftp.sunsite.auc.dk/disk2/slackware/slackware-8.0/pasture/pasture-sources/ipfwadm-2.3.0/ipfwadm-2.3.0.tar.gz to +to use this. IP Masquerading =============== @@ -376,7 +384,8 @@ always need to load separate modules (ip_masq_ftp.o and/or ip_masq_irc.o) if you are going to use FTP or IRC in combination with masquerading. You'll need to get -ftp://ftp.xos.nl/pub/linux/ipfwadm/ipfwadm-2.3.0.tar.gz to use this. +ftp://ftp.sunsite.auc.dk/disk2/slackware/slackware-8.0/pasture/pasture-sources/ipfwadm-2.3.0/ipfwadm-2.3.0.tar.gz to +to use this. To enable IP forwarding, you may need to @@ -388,28 +397,28 @@ ============ The new kernels support ISDN. You'll need ISDN utils available from -ftp://ftp.franken.de/pub/isdn4linux/v2.0/isdn4k-utils-2.0.tar.gz to try -this. +ftp://ftp.uni-jena.de/pub/fsu/rz/software/linux/internetworking/isdn/isdn4k-utils-2.0.tar.gz +to try this. Frame Relay =========== Frame relay support for Linux is now available as well. Currently, only Sangoma cards are supported, but the interface is such that others -will be as drivers become available. To use this, grab -ftp://linux.invlogic.com/pub/fr/frad-0.15.tgz (soon to be -frad-0.20.tgz). Another package of interest is -ftp://linux.invlogic.com/pub/routing/routing.tgz (which allows Linux to -make routing decisions based on packet source). +will be as drivers become available. To use this, grab +ftp://ftp.task.gda.pl/mirror/ftp.invlogic.com/pub/fr/frad-0.15.tgz +(soon to be frad-0.20.tgz). Another package of interest is +ftp://ftp.task.gda.pl/mirror/ftp.invlogic.com/pub/routing/routing-2.0.33.tgz +(which allows Linux to make routing decisions based on packet source). Networking ========== Some of the /proc/net entries have changed. You'll need to upgrade to the latest net-tools in -ftp://ftp.inka.de/pub/comp/Linux/networking/NetTools/, where the latest -is currently net-tools-1.32-alpha.tar.gz. See -http://www.inka.de/sites/lina/linux/NetTools/index_en.html for more +ftp://ftp.task.gda.pl/mirror/ftp.invlogic.com/pub/linux/routing/, +where the latest is currently net-tools-1.33.tar.gz. +See http://www.inka.de/sites/lina/linux/NetTools/index_en.html for more information. Note that there is currently no ipfw (which is part of net-tools) which works with 2.0.x kernels. If you need its functions, learn how to use ipfwadm or patch ipfw to get it to work (ipfw's current @@ -427,9 +436,10 @@ The sound driver was upgraded in the 2.0.x kernels, breaking vplay. To fix this problem, get a new version of the sndkit from -ftp://ftp.best.com/pub/front/tasd/snd-util-3.5.tar.gz. Some users -report that various other sound utils (cdd2wav-sbpcd, for example) need -to be recompiled before they will work with the new kernels. +ftp://sunsite.unc.edu/pub/historic-linux/distributions/slackware/3.1/source/extra-stuff/sound-utilities/snd-util-3.5.tar.gz. +Some users report that various other sound utils (cdd2wav-sbpcd, for +example) need to be recompiled before they will work with the new +kernels. Tcsh ==== @@ -459,8 +469,8 @@ file as a file system, which can allow for all sorts of cool things like encrypted file systems and such. To use it, you'll need a modified version of mount from -ftp://ftp.win.tue.nl/pub/linux/util/mount-2.5k.tar.gz; preliminary work -on encrypted file system support can be found in +ftp://ftp.win.tue.nl/pub/linux-local/utils/attic/mount/mount-2.5k.tar.gz; +preliminary work on encrypted file system support can be found in ftp.funet.fi:/pub/Linux/BETA/loop/des.1.tar.gz. Multiple device diff -urN linux-2.0.40-rc6/Documentation/Configure.help linux-2.0.40-rc7/Documentation/Configure.help --- linux-2.0.40-rc6/Documentation/Configure.help 2004-01-15 07:19:51.000000000 -0800 +++ linux-2.0.40-rc7/Documentation/Configure.help 2004-01-15 07:19:51.000000000 -0800 @@ -3868,6 +3868,13 @@ the same IRQ). Several programs depend on this, so everyone should say Y here. +Enable mmap on /proc/*/mem (UNSECURE!) +CONFIG_UNSAFE_MMAP + As of linux-2.0.40, mmap on /proc/*/mem has been disabled due to + security problems. If you need this functionality, and have no + (potentially hostile) local users, you can enable this option to + restore the old functionality. If unsure, say N. + NFS file system support CONFIG_NFS_FS If you are connected to some other (usually local) Unix computer diff -urN linux-2.0.40-rc6/Documentation/ioctl-number.txt linux-2.0.40-rc7/Documentation/ioctl-number.txt --- linux-2.0.40-rc6/Documentation/ioctl-number.txt 1996-08-10 00:03:14.000000000 -0700 +++ linux-2.0.40-rc7/Documentation/ioctl-number.txt 2004-01-15 07:19:51.000000000 -0800 @@ -20,7 +20,7 @@ The first argument to _IO, _IOW, _IOR, or _IOWR is an identifying letter or number from the table below. If you are writing a driver for a new device and need a letter, pick an unused letter. You can register the -letter by patching this file and submitting the patch to Linus Torvalds. +letter by patching this file and submitting the patch to David Weinehall. Or you can e-mail me at and I'll register one for you. diff -urN linux-2.0.40-rc6/Documentation/mandatory.txt linux-2.0.40-rc7/Documentation/mandatory.txt --- linux-2.0.40-rc6/Documentation/mandatory.txt 1997-08-03 13:59:07.000000000 -0700 +++ linux-2.0.40-rc7/Documentation/mandatory.txt 2004-01-15 07:19:51.000000000 -0800 @@ -140,7 +140,7 @@ Note 3: I may have overlooked some system calls that need mandatory lock checking in my eagerness to get this code out the door. Please let me know, or -better still fix the system calls yourself and submit a patch to me or Linus. +better still fix the system calls yourself and submit a patch to me or David. 6. Warning! ----------- diff -urN linux-2.0.40-rc6/Documentation/unicode.txt linux-2.0.40-rc7/Documentation/unicode.txt --- linux-2.0.40-rc6/Documentation/unicode.txt 1996-11-12 00:30:48.000000000 -0800 +++ linux-2.0.40-rc7/Documentation/unicode.txt 2004-01-15 07:19:51.000000000 -0800 @@ -50,6 +50,20 @@ character, and hence has been coded as U+2500 FORMS LIGHT HORIZONTAL. However, I left U+F802 blank should the need arise. +< +>> + Klingon language support ------------------------ diff -urN linux-2.0.40-rc6/MAINTAINERS linux-2.0.40-rc7/MAINTAINERS --- linux-2.0.40-rc6/MAINTAINERS 2004-01-15 07:19:51.000000000 -0800 +++ linux-2.0.40-rc7/MAINTAINERS 2004-01-15 07:19:51.000000000 -0800 @@ -119,13 +119,6 @@ L: linux-hams@vger.kernel.org S: Maintained -BUSLOGIC SCSI DRIVER -P: Leonard N. Zubkoff -M: Leonard N. Zubkoff -L: linux-scsi@vger.kernel.org -W: http://www.dandelion.com/Linux/ -S: Maintained - CREDITS FILE P: John A. Martin M: jam@acm.org @@ -137,12 +130,6 @@ W: http://www.cyclades.com/ S: Supported -DAC960 RAID DRIVER -P: Leonard N. Zubkoff -M: Leonard N. Zubkoff -L: linux-raid@vger.kernel.org -S: Maintained - DAMA SLAVE for AX.25 P: Joerg Reuter M: jreuter@yaina.de @@ -317,13 +304,6 @@ L: linux-net@vger.kernel.org S: Maintained -MCA-SUPPORT -P: David Weinehall -M: tao@acc.umu.se -W: http://www.acc.umu.se/~tao/ -L: linux-kernel@vger.kernel.org -S: Maintained - MENUCONFIG P: William Roadcap M: roadcapw@titus.org @@ -488,6 +468,6 @@ THE REST P: David Weinehall -M: tao@acc.umu.se +M: tao@kernel.org L: linux-kernel@vger.kernel.org S: Maintained diff -urN linux-2.0.40-rc6/Makefile linux-2.0.40-rc7/Makefile --- linux-2.0.40-rc6/Makefile 2004-01-15 07:19:51.000000000 -0800 +++ linux-2.0.40-rc7/Makefile 2004-01-15 07:19:51.000000000 -0800 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 0 SUBLEVEL = 40 -EXTRAVERSION =-rc5 +EXTRAVERSION =-rc7 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) diff -urN linux-2.0.40-rc6/README linux-2.0.40-rc7/README --- linux-2.0.40-rc6/README 1999-06-13 10:20:59.000000000 -0700 +++ linux-2.0.40-rc7/README 2004-01-15 07:19:51.000000000 -0800 @@ -50,17 +50,23 @@ latest kernel. If you use GNU tar, cd /usr/src - tar -xzvf linux-2.1.XX.tar.gz + tar -xzvf linux-2.0.XX.tar.gz is equivalent. - You can also upgrade between 2.0.xx releases by patching. Each patch that is released for 2.0.xx contains only bugfixes. No - new features will be added to the Linux kernel until the 2.1.xx - development effort begins. To install by patching, get all the - newer patch files and do + new features will be added to the Linux kernel 2.0 any more. If + you are interested in new kernel features, you may want to + help developing a more recent kernel. + + To patch to a newer 2.0 kernel version, get all the newer files + (you will find these patches at the kernel FTP servers: + , replace + xx with your two letter country code here, e.g. se for Sweden), + then do: - cd /usr/src + cd /usr/src/linux gzip -cd patchXX.gz | patch -p0 (repeat xx for all versions bigger than the version of your current @@ -96,7 +102,7 @@ - Alternate configuration commands are: "make menuconfig" Text based color menus, radiolists & dialogs. - "make xconfig" X windows based configuration tool. + "make xconfig" X window system based configuration tool. NOTES on "make config": - having unnecessary drivers will make the kernel bigger, and can @@ -160,7 +166,7 @@ If you boot Linux from the hard drive, chances are you use LILO which uses the kernel image as specified in the file /etc/lilo.conf. The - kernel image file is usually /vmlinuz, or /zImage, or /etc/zImage. + kernel image file is usually /vmlinuz, /zImage, or /boot/vmlinuz. To use the new kernel, copy the new image over the old one (save a backup of the original!). Then, you MUST RERUN LILO to update the loading map!! If you don't, you won't be able to boot the new kernel @@ -187,10 +193,8 @@ the file MAINTAINERS to see if there is a particular person associated with the part of the kernel that you are having trouble with. If there isn't anyone listed there, then the second best thing is to mail - them to me (Linus.Torvalds@Helsinki.FI), and possibly to any other - relevant mailing-list or to the newsgroup. The mailing-lists are - useful especially for SCSI and NETworking problems, as I can't test - either of those personally anyway. + them to me (David Weinehall, tao@kernel.org), and possibly to any other + relevant mailing-list or to the newsgroup. - In all bug-reports, *please* tell what kernel you are talking about, how to duplicate the problem, and what your setup is (use your common diff -urN linux-2.0.40-rc6/arch/alpha/defconfig linux-2.0.40-rc7/arch/alpha/defconfig --- linux-2.0.40-rc6/arch/alpha/defconfig 1999-06-13 10:20:59.000000000 -0700 +++ linux-2.0.40-rc7/arch/alpha/defconfig 2004-01-15 07:19:51.000000000 -0800 @@ -193,6 +193,7 @@ # CONFIG_VFAT_FS is not set # CONFIG_UMSDOS_FS is not set CONFIG_PROC_FS=y +# CONFIG_UNSAFE_MMAP is not set CONFIG_NFS_FS=y # CONFIG_ROOT_NFS is not set # CONFIG_SMB_FS is not set diff -urN linux-2.0.40-rc6/arch/i386/defconfig linux-2.0.40-rc7/arch/i386/defconfig --- linux-2.0.40-rc6/arch/i386/defconfig 1999-06-13 10:20:59.000000000 -0700 +++ linux-2.0.40-rc7/arch/i386/defconfig 2004-01-15 07:19:51.000000000 -0800 @@ -178,6 +178,7 @@ # CONFIG_NLS_ISO8859_9 is not set # CONFIG_NLS_KOI8_R is not set CONFIG_PROC_FS=y +# CONFIG_UNSAFE_MMAP is not set CONFIG_NFS_FS=y # CONFIG_ROOT_NFS is not set # CONFIG_SMB_FS is not set diff -urN linux-2.0.40-rc6/arch/i386/kernel/entry.S linux-2.0.40-rc7/arch/i386/kernel/entry.S --- linux-2.0.40-rc6/arch/i386/kernel/entry.S 1998-11-15 10:32:46.000000000 -0800 +++ linux-2.0.40-rc7/arch/i386/kernel/entry.S 2004-01-15 07:19:51.000000000 -0800 @@ -65,7 +65,9 @@ OLDSS = 0x40 CF_MASK = 0x00000001 +TF_MASK = 0x00000100 IF_MASK = 0x00000200 +DF_MASK = 0x00000400 NT_MASK = 0x00004000 VM_MASK = 0x00020000 @@ -270,6 +272,9 @@ movl CS(%esp),%edx # this is eip.. movl EFLAGS(%esp),%ecx # and this is cs.. movl %eax,EFLAGS(%esp) # + andl $~(NT_MASK|TF_MASK|DF_MASK), %eax + pushl %eax + popfl movl %edx,EIP(%esp) # Now we move them to their "normal" places movl %ecx,CS(%esp) # movl %esp,%eax @@ -401,6 +406,9 @@ pushl $ SYMBOL_NAME(do_divide_error) ALIGN error_code: + pushfl + andl $~(NT_MASK|TF_MASK|DF_MASK), (%esp) + popfl push %fs push %es push %ds @@ -413,7 +421,6 @@ decl %eax # eax = -1 pushl %ecx pushl %ebx - cld xorl %ebx,%ebx # zero ebx xchgl %eax, ORIG_EAX(%esp) # orig_eax (get the error code. ) mov %gs,%bx # get the lower order bits of gs diff -urN linux-2.0.40-rc6/arch/i386/kernel/setup.c linux-2.0.40-rc7/arch/i386/kernel/setup.c --- linux-2.0.40-rc6/arch/i386/kernel/setup.c 2004-01-15 07:19:51.000000000 -0800 +++ linux-2.0.40-rc7/arch/i386/kernel/setup.c 2004-01-15 07:19:51.000000000 -0800 @@ -50,13 +50,13 @@ char x86_vendor_id[13] = "GenuineIntel";/* default */ -static char *Cx86_step = "unknown"; /* stepping info for Cyrix CPUs */ +static char Cx86_step[8] = "unknown"; /* stepping info for Cyrix CPUs */ static unsigned char Cx86_mult = 0; /* clock multiplier for Cyrix CPUs */ static const char *x86_clkmult[] = { - "unknown", "1", "1.5", "2", "2.5", "3", "3.5", "4", "4.5", "5", "5.5", - "6", "6.5", "7", "7.5", "8" + "unknown", "1x", "1.5x", "2x", "2.5x", "3x", "3.5x", "4x", + "4.5x", "5x", "5.5x", "6x", "6.5x", "7x", "7.5x", "8x" }; char ignore_irq13 = 0; /* set if exception 16 works */ @@ -500,7 +500,7 @@ } else if (strncmp(x86_vendor_id, "Cy", 2) == 0) { len += sprintf(buffer+len, - "stepping\t: %s, core/bus clock ratio: %sx\n", + "stepping\t: %s, core/bus clock ratio: %s\n", Cx86_step, x86_clkmult[Cx86_mult]); } else { diff -urN linux-2.0.40-rc6/arch/m68k/defconfig linux-2.0.40-rc7/arch/m68k/defconfig --- linux-2.0.40-rc6/arch/m68k/defconfig 1997-09-05 20:43:58.000000000 -0700 +++ linux-2.0.40-rc7/arch/m68k/defconfig 2004-01-15 07:19:51.000000000 -0800 @@ -116,6 +116,7 @@ # CONFIG_VFAT_FS is not set # CONFIG_UMSDOS_FS is not set CONFIG_PROC_FS=y +# CONFIG_UNSAFE_MMAP is not set CONFIG_NFS_FS=y # CONFIG_ROOT_NFS is not set # CONFIG_SMB_FS is not set diff -urN linux-2.0.40-rc6/arch/mips/defconfig linux-2.0.40-rc7/arch/mips/defconfig --- linux-2.0.40-rc6/arch/mips/defconfig 1999-06-13 10:21:00.000000000 -0700 +++ linux-2.0.40-rc7/arch/mips/defconfig 2004-01-15 07:19:51.000000000 -0800 @@ -58,6 +58,7 @@ # CONFIG_XIA_FS is not set # CONFIG_MSDOS_FS is not set CONFIG_PROC_FS=y +# CONFIG_UNSAFE_MMAP is not set # CONFIG_ISO9660_FS is not set # CONFIG_HPFS_FS is not set # CONFIG_SYSV_FS is not set diff -urN linux-2.0.40-rc6/arch/sparc/defconfig linux-2.0.40-rc7/arch/sparc/defconfig --- linux-2.0.40-rc6/arch/sparc/defconfig 1997-09-05 20:43:58.000000000 -0700 +++ linux-2.0.40-rc7/arch/sparc/defconfig 2004-01-15 07:19:51.000000000 -0800 @@ -105,6 +105,7 @@ # CONFIG_VFAT_FS is not set # CONFIG_UMSDOS_FS is not set CONFIG_PROC_FS=y +# CONFIG_UNSAFE_MMAP is not set CONFIG_NFS_FS=y CONFIG_ROOT_NFS=y CONFIG_RNFS_BOOTP=y diff -urN linux-2.0.40-rc6/drivers/char/rtc.c linux-2.0.40-rc7/drivers/char/rtc.c --- linux-2.0.40-rc6/drivers/char/rtc.c 1998-06-03 15:17:47.000000000 -0700 +++ linux-2.0.40-rc7/drivers/char/rtc.c 2004-01-15 07:19:51.000000000 -0800 @@ -1,5 +1,5 @@ /* - * Real Time Clock interface for Linux + * Real Time Clock interface for Linux * * Copyright (C) 1996 Paul Gortmaker * @@ -17,7 +17,7 @@ * has been received. If a RTC interrupt has already happened, * it will output an unsigned long and then block. The output value * contains the interrupt status in the low byte and the number of - * interrupts since the last read in the remaining high bytes. The + * interrupts since the last read in the remaining high bytes. The * /dev/rtc interface can also be used with the select(2) call. * * This program is free software; you can redistribute it and/or @@ -37,7 +37,7 @@ #define RTC_VERSION "1.09" -#define RTC_IRQ 8 /* Can't see this changing soon. */ +#define RTC_IRQ 8 /* Can't see this changing soon. */ #define RTC_IO_EXTENT 0x10 /* Only really two ports, but... */ /* @@ -110,7 +110,7 @@ static unsigned long epoch = 1900; /* year corresponding to 0x00 */ -unsigned char days_in_mo[] = +unsigned char days_in_mo[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; /* @@ -136,7 +136,7 @@ rtc_irq_data += 0x100; rtc_irq_data &= ~0xff; rtc_irq_data |= (CMOS_READ(RTC_INTR_FLAGS) & 0xF0); - wake_up_interruptible(&rtc_wait); + wake_up_interruptible(&rtc_wait); if (rtc_status & RTC_TIMER_ON) { del_timer(&rtc_irq_timer); @@ -164,7 +164,7 @@ #else struct wait_queue wait = { current, NULL }; int retval; - + if (count < sizeof(unsigned long)) return -EINVAL; @@ -175,7 +175,7 @@ add_wait_queue(&rtc_wait, &wait); current->state = TASK_INTERRUPTIBLE; - + while (rtc_irq_data == 0) { if (file->f_flags & O_NONBLOCK) { retval = -EAGAIN; @@ -279,7 +279,7 @@ get_rtc_alm_time(&alm_tm); memcpy_tofs((struct rtc_time*)arg, &alm_tm, sizeof(struct rtc_time)); - + return 0; } case RTC_ALM_SET: /* Store a time into the alarm */ @@ -303,23 +303,25 @@ min = alm_tm.tm_min; sec = alm_tm.tm_sec; - if (hrs >= 24) - hrs = 0xff; - - if (min >= 60) - min = 0xff; - - if (sec >= 60) - sec = 0xff; - save_flags(flags); cli(); if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { - BIN_TO_BCD(sec); - BIN_TO_BCD(min); - BIN_TO_BCD(hrs); + if (sec < 60) + BIN_TO_BCD(sec); + else + sec = 0xff; + + if (min < 60) + BIN_TO_BCD(min); + else + min = 0xff; + + if (hrs < 24) + BIN_TO_BCD(hrs); + else + hrs = 0xff; } CMOS_WRITE(hrs, RTC_HOURS_ALARM); CMOS_WRITE(min, RTC_MINUTES_ALARM); @@ -332,7 +334,7 @@ { int retval; struct rtc_time rtc_tm; - + retval = verify_area(VERIFY_WRITE, (struct rtc_time*)arg, sizeof(struct rtc_time)); if (retval !=0 ) return retval; @@ -349,12 +351,12 @@ unsigned char save_control, save_freq_select; unsigned int yrs; unsigned long flags; - + if (!suser()) return -EACCES; retval = verify_area(VERIFY_READ, (struct rtc_time*)arg, sizeof(struct rtc_time)); - if (retval !=0 ) + if (retval != 0) return retval; memcpy_fromfs(&rtc_tm, (struct rtc_time*)arg, sizeof(struct rtc_time)); @@ -376,7 +378,7 @@ if (day > (days_in_mo[mon] + ((mon == 2) && leap_yr))) return -EINVAL; - + if ((hrs >= 24) || (min >= 60) || (sec >= 60)) return -EINVAL; @@ -436,7 +438,7 @@ int tmp = 0; unsigned char val; - /* + /* * The max we can do is 8192Hz. */ if ((arg < 2) || (arg > 8192)) @@ -482,7 +484,7 @@ } case RTC_EPOCH_SET: /* Set the epoch. */ { - /* + /* * There were no RTC clocks before 1900. */ if (arg < 1900) @@ -656,14 +658,14 @@ } /* - * At IRQ rates >= 4096Hz, an interrupt may get lost altogether. + * At IRQ rates >= 4096Hz, an interrupt may get lost altogether. * (usually during an IDE disk interrupt, with IRQ unmasking off) * Since the interrupt handler doesn't get called, the IRQ status * byte doesn't get read, and the RTC stops generating interrupts. * A timer is set, and will call this function if/when that happens. * To get it out of this stalled state, we just read the status. * At least a jiffy of interrupts (rtc_freq/HZ) will have been lost. - * (You *really* shouldn't be trying to use a non-realtime system + * (You *really* shouldn't be trying to use a non-realtime system * for something that requires a steady > 1KHz signal anyways.) */ @@ -789,7 +791,7 @@ * can take just over 2ms. We wait 10 to 20ms. There is no need to * to poll-wait (up to 1s - eeccch) for the falling edge of RTC_UIP. * If you need to know *exactly* when a second has started, enable - * periodic update complete interrupts, (via ioctl) and then + * periodic update complete interrupts, (via ioctl) and then * immediately read /dev/rtc which will block until you get the IRQ. * Once the read clears, read the RTC time (again via ioctl). Easy. */ diff -urN linux-2.0.40-rc6/drivers/isdn/isdn_net.c linux-2.0.40-rc7/drivers/isdn/isdn_net.c --- linux-2.0.40-rc6/drivers/isdn/isdn_net.c 2004-01-15 07:19:51.000000000 -0800 +++ linux-2.0.40-rc7/drivers/isdn/isdn_net.c 2004-01-15 07:19:51.000000000 -0800 @@ -376,8 +376,9 @@ icmp_send(skb, ICMP_DEST_UNREACH, ICMP_NET_UNKNOWN, 0 #if (LINUX_VERSION_CODE < 0x02010f) /* 2.1.15 */ - ,dev + , dev #endif + , 1 ); } } @@ -396,6 +397,7 @@ #if (LINUX_VERSION_CODE < 0x02010f) /* 2.1.15 */ , dev #endif + , 1 ); } dev_kfree_skb(skb, FREE_WRITE); diff -urN linux-2.0.40-rc6/drivers/net/3c501.c linux-2.0.40-rc7/drivers/net/3c501.c --- linux-2.0.40-rc6/drivers/net/3c501.c 1996-11-06 04:39:42.000000000 -0800 +++ linux-2.0.40-rc7/drivers/net/3c501.c 2004-01-15 07:19:51.000000000 -0800 @@ -9,15 +9,15 @@ This is a device driver for the 3Com Etherlink 3c501. Do not purchase this card, even as a joke. It's performance is horrible, - and it breaks in many ways. + and it breaks in many ways. The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O Center of Excellence in Space Data and Information Sciences Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771 - + Fixed (again!) the missing interrupt locking on TX/RX shifting. - Alan Cox - + Alan Cox + Removed calls to init_etherdev since they are no longer needed, and cleaned up modularization just a bit. The driver still allows only the default address for cards when loaded as a module, but that's @@ -28,51 +28,50 @@ the board. Now getting 150K/second FTP with a 3c501 card. Still playing with a TX-TX optimisation to see if we can touch 180-200K/second as seems theoretically maximum. - 19950402 Alan Cox - + 19950402 Alan Cox + Some notes on this thing if you have to hack it. [Alan] - + 1] Some documentation is available from 3Com. Due to the boards age - standard responses when you ask for this will range from 'be serious' - to 'give it to a museum'. The documentation is incomplete and mostly - of historical interest anyway. - + standard responses when you ask for this will range from 'be serious' + to 'give it to a museum'. The documentation is incomplete and mostly + of historical interest anyway. + 2] The basic system is a single buffer which can be used to receive or - transmit a packet. A third command mode exists when you are setting - things up. - - 3] If it's transmitting it's not receiving and vice versa. In fact the - time to get the board back into useful state after an operation is - quite large. - + transmit a packet. A third command mode exists when you are setting + things up. + + 3] If it's transmitting it's not receiving and vice versa. In fact the + time to get the board back into useful state after an operation is + quite large. + 4] The driver works by keeping the board in receive mode waiting for a - packet to arrive. When one arrives it is copied out of the buffer - and delivered to the kernel. The card is reloaded and off we go. - + packet to arrive. When one arrives it is copied out of the buffer + and delivered to the kernel. The card is reloaded and off we go. + 5] When transmitting dev->tbusy is set and the card is reset (from - receive mode) [possibly losing a packet just received] to command - mode. A packet is loaded and transmit mode triggered. The interrupt - handler runs different code for transmit interrupts and can handle - returning to receive mode or retransmissions (yes you have to help - out with those too). - + receive mode) [possibly losing a packet just received] to command + mode. A packet is loaded and transmit mode triggered. The interrupt + handler runs different code for transmit interrupts and can handle + returning to receive mode or retransmissions (yes you have to help + out with those too). + Problems: - There are a wide variety of undocumented error returns from the card - and you basically have to kick the board and pray if they turn up. Most + There are a wide variety of undocumented error returns from the card + and you basically have to kick the board and pray if they turn up. Most only occur under extreme load or if you do something the board doesn't like (eg touching a register at the wrong time). - - The driver is less efficient than it could be. It switches through + + The driver is less efficient than it could be. It switches through receive mode even if more transmits are queued. If this worries you buy a real ethernet card. - - The combination of slow receive restart and no real multicast + + The combination of slow receive restart and no real multicast filter makes the board unusable with a kernel compiled for IP - multicasting in a real multicast environment. That's down to the board, + multicasting in a real multicast environment. That's down to the board, but even with no multicast programs running a multicast IP kernel is in group 224.0.0.1 and you will therefore be listening to all multicasts. One nv conference running over that ethernet and you can give up. - */ static const char *version = @@ -107,22 +106,20 @@ /* A zero-terminated list of I/O addresses to be probed. The 3c501 can be at many locations, but here are the popular ones. */ -static unsigned int netcard_portlist[] = - { 0x280, 0x300, 0}; +static unsigned int netcard_portlist[] = { 0x280, 0x300, 0 }; - /* - * Index to functions. + * Index to functions. */ - + int el1_probe(struct device *dev); -static int el1_probe1(struct device *dev, int ioaddr); -static int el_open(struct device *dev); -static int el_start_xmit(struct sk_buff *skb, struct device *dev); +static int el1_probe1(struct device *dev, int ioaddr); +static int el_open(struct device *dev); +static int el_start_xmit(struct sk_buff *skb, struct device *dev); static void el_interrupt(int irq, void *dev_id, struct pt_regs *regs); static void el_receive(struct device *dev); static void el_reset(struct device *dev); -static int el1_close(struct device *dev); +static int el1_close(struct device *dev); static struct enet_statistics *el1_get_stats(struct device *dev); static void set_multicast_list(struct device *dev); @@ -132,12 +129,12 @@ #define EL_DEBUG 0 /* use 0 for production, 1 for devel., >2 for debug */ #endif /* Anything above 5 is wordy death! */ static int el_debug = EL_DEBUG; - -/* - * Board-specific info in dev->priv. + +/* + * Board-specific info in dev->priv. */ - -struct net_local + +struct net_local { struct enet_statistics stats; int tx_pkt_start; /* The length of the current Tx packet. */ @@ -145,12 +142,11 @@ int loading; /* Spot buffer load collisions */ }; - #define RX_STATUS (ioaddr + 0x06) #define RX_CMD RX_STATUS #define TX_STATUS (ioaddr + 0x07) #define TX_CMD TX_STATUS -#define GP_LOW (ioaddr + 0x08) +#define GP_LOW (ioaddr + 0x08) #define GP_HIGH (ioaddr + 0x09) #define RX_BUF_CLR (ioaddr + 0x0A) #define RX_LOW (ioaddr + 0x0A) @@ -164,12 +160,12 @@ #define EL1_DATAPTR 0x08 #define EL1_RXPTR 0x0A #define EL1_SAPROM 0x0C -#define EL1_DATAPORT 0x0f +#define EL1_DATAPORT 0x0f /* * Writes to the ax command register. */ - + #define AX_OFF 0x00 /* Irq off, buffer access on */ #define AX_SYS 0x40 /* Load the buffer */ #define AX_XMIT 0x44 /* Transmit a packet */ @@ -181,16 +177,16 @@ * Normal receive mode written to RX_STATUS. We must intr on short packets * to avoid bogus rx lockups. */ - + #define RX_NORM 0xA8 /* 0x68 == all addrs, 0xA8 only to me. */ #define RX_PROM 0x68 /* Senior Prom, uhmm promiscuous mode. */ #define RX_MULT 0xE8 /* Accept multicast packets. */ #define TX_NORM 0x0A /* Interrupt on everything that might hang the chip */ /* - * TX_STATUS register. + * TX_STATUS register. */ - + #define TX_COLLISION 0x02 #define TX_16COLLISIONS 0x04 #define TX_READY 0x08 @@ -198,14 +194,18 @@ #define RX_RUNT 0x08 #define RX_MISSED 0x01 /* Missed a packet due to 3c501 braindamage. */ #define RX_GOOD 0x30 /* Good packet 0x20, or simple overflow 0x10. */ - /* * The boilerplate probe code. */ - + #ifdef HAVE_DEVLIST -struct netdev_entry el1_drv = {"3c501", el1_probe1, EL1_IO_EXTENT, netcard_portlist}; +struct netdev_entry el1_drv = { + "3c501", + el1_probe1, + EL1_IO_EXTENT, + netcard_portlist +}; #else int el1_probe(struct device *dev) @@ -218,8 +218,7 @@ else if (base_addr != 0) /* Don't probe at all. */ return ENXIO; - for (i = 0; netcard_portlist[i]; i++) - { + for (i = 0; netcard_portlist[i]; i++) { int ioaddr = netcard_portlist[i]; if (check_region(ioaddr, EL1_IO_EXTENT)) continue; @@ -232,8 +231,8 @@ #endif /* - * The actual probe. - */ + * The actual probe. + */ static int el1_probe1(struct device *dev, int ioaddr) { @@ -243,55 +242,50 @@ int i; /* - * Read the station address PROM data from the special port. + * Read the station address PROM data from the special port. */ - - for (i = 0; i < 6; i++) - { + + for (i = 0; i < 6; i++) { outw(i, ioaddr + EL1_DATAPTR); station_addr[i] = inb(ioaddr + EL1_SAPROM); } /* * Check the first three octets of the S.A. for 3Com's prefix, or - * for the Sager NP943 prefix. - */ - - if (station_addr[0] == 0x02 && station_addr[1] == 0x60 - && station_addr[2] == 0x8c) - { + * for the Sager NP943 prefix. + */ + + if (station_addr[0] == 0x02 && station_addr[1] == 0x60 && + station_addr[2] == 0x8c) { mname = "3c501"; - } else if (station_addr[0] == 0x00 && station_addr[1] == 0x80 - && station_addr[2] == 0xC8) - { + } else if (station_addr[0] == 0x00 && station_addr[1] == 0x80 && + station_addr[2] == 0xC8) { mname = "NP943"; - } - else + } else return ENODEV; /* - * Grab the region so we can find the another board if autoIRQ fails. + * Grab the region so we can find the another board if autoIRQ + * fails. */ - request_region(ioaddr, EL1_IO_EXTENT,"3c501"); + request_region(ioaddr, EL1_IO_EXTENT, "3c501"); - /* - * We auto-IRQ by shutting off the interrupt line and letting it float - * high. + /* + * We auto-IRQ by shutting off the interrupt line and letting it + * float high. */ - if (dev->irq < 2) - { + if (dev->irq < 2) { autoirq_setup(2); inb(RX_STATUS); /* Clear pending interrupts. */ inb(TX_STATUS); outb(AX_LOOP + 1, AX_CMD); outb(0x00, AX_CMD); - + autoirq = autoirq_report(1); - if (autoirq == 0) - { + if (autoirq == 0) { printk("%s probe at %#x failed to detect IRQ line.\n", mname, ioaddr); return EAGAIN; @@ -307,29 +301,30 @@ if (autoirq) dev->irq = autoirq; - printk("%s: %s EtherLink at %#lx, using %sIRQ %d.\n", dev->name, mname, dev->base_addr, - autoirq ? "auto":"assigned ", dev->irq); - + printk("%s: %s EtherLink at %#lx, using %sIRQ %d.\n", + dev->name, mname, dev->base_addr, + autoirq ? "auto" : "assigned ", dev->irq); + #ifdef CONFIG_IP_MULTICAST printk("WARNING: Use of the 3c501 in a multicast kernel is NOT recommended.\n"); -#endif +#endif if (el_debug) printk("%s", version); /* - * Initialize the device structure. + * Initialize the device structure. */ - - dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL); + + dev->priv = kmalloc(sizeof (struct net_local), GFP_KERNEL); if (dev->priv == NULL) return -ENOMEM; - memset(dev->priv, 0, sizeof(struct net_local)); + memset(dev->priv, 0, sizeof (struct net_local)); /* - * The EL1-specific entries in the device structure. + * The EL1-specific entries in the device structure. */ - + dev->open = &el_open; dev->hard_start_xmit = &el_start_xmit; dev->stop = &el1_close; @@ -337,7 +332,7 @@ dev->set_multicast_list = &set_multicast_list; /* - * Setup the generic properties + * Setup the generic properties */ ether_setup(dev); @@ -346,9 +341,9 @@ } /* - * Open/initialize the board. + * Open/initialize the board. */ - + static int el_open(struct device *dev) { int ioaddr = dev->base_addr; @@ -356,7 +351,7 @@ if (el_debug > 2) printk("%s: Doing el_open()...", dev->name); - if (request_irq(dev->irq, &el_interrupt, 0, "3c501", NULL)) + if (request_irq(dev->irq, &el_interrupt, 0, "3c501", NULL)) return -EAGAIN; irq2dev_map[dev->irq] = dev; @@ -374,21 +369,20 @@ struct net_local *lp = (struct net_local *)dev->priv; int ioaddr = dev->base_addr; unsigned long flags; - - if(dev->interrupt) /* May be unloading, don't stamp on */ + + if (dev->interrupt) /* May be unloading, don't stamp on */ return 1; /* the packet buffer this time */ - if (dev->tbusy) - { - if (jiffies - dev->trans_start < 20) - { + if (dev->tbusy) { + if (jiffies - dev->trans_start < 20) { if (el_debug > 2) printk(" transmitter busy, deferred.\n"); return 1; } if (el_debug) printk ("%s: transmit timed out, txsr %#2x axsr=%02x rxsr=%02x.\n", - dev->name, inb(TX_STATUS), inb(AX_STATUS), inb(RX_STATUS)); + dev->name, inb(TX_STATUS), inb(AX_STATUS), + inb(RX_STATUS)); lp->stats.tx_errors++; outb(TX_NORM, TX_CMD); outb(RX_NORM, RX_CMD); @@ -398,8 +392,7 @@ dev->trans_start = jiffies; } - if (skb == NULL) - { + if (skb == NULL) { dev_tint(dev); return 0; } @@ -411,77 +404,84 @@ * mode as the driver assumes tbusy is a faithful indicator of card * state */ - + cli(); - + /* - * Avoid timer-based retransmission conflicts. + * Avoid timer-based retransmission conflicts. */ - - if (set_bit(0, (void*)&dev->tbusy) != 0) - { + + if (set_bit(0, (void *)&dev->tbusy) != 0) { restore_flags(flags); printk("%s: Transmitter access conflict.\n", dev->name); - } - else - { - int gp_start = 0x800 - (ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN); + } else { + int len = skb->len; + int pad = 0; + int gp_start; unsigned char *buf = skb->data; + if (len < ETH_ZLEN) + pad = ETH_ZLEN - len; + + gp_start = 0x800 - (len + pad); + load_it_again_sam: lp->tx_pkt_start = gp_start; - lp->collisions = 0; + lp->collisions = 0; /* * Command mode with status cleared should [in theory] * mean no more interrupts can be pending on the card. */ - + #ifdef BLOCKOUT_1 - disable_irq(dev->irq); -#endif + disable_irq(dev->irq); +#endif outb_p(AX_SYS, AX_CMD); inb_p(RX_STATUS); inb_p(TX_STATUS); - - lp->loading=1; - - /* - * Turn interrupts back on while we spend a pleasant afternoon - * loading bytes into the board + + lp->loading = 1; + + /* + * Turn interrupts back on while we spend a pleasant + * afternoon loading bytes into the board */ restore_flags(flags); outw(0x00, RX_BUF_CLR); /* Set rx packet area to 0. */ outw(gp_start, GP_LOW); /* aim - packet will be loaded into buffer start */ - outsb(DATAPORT,buf,skb->len); /* load buffer (usual thing each byte increments the pointer) */ + outsb(DATAPORT, buf, len); /* load buffer (usual thing each byte increments the pointer) */ + if (pad) { + while (pad--) + outb(0, DATAPORT); + } outw(gp_start, GP_LOW); /* the board reuses the same register */ -#ifndef BLOCKOUT_1 - if(lp->loading==2) /* A receive upset our load, despite our best efforts */ - { - if(el_debug>2) +#ifndef BLOCKOUT_1 + if (lp->loading == 2) { + /* A receive upset our load, despite our best efforts */ + if (el_debug > 2) printk("%s: burped during tx load.\n", dev->name); goto load_it_again_sam; /* Sigh... */ } #endif outb(AX_XMIT, AX_CMD); /* fire ... Trigger xmit. */ - lp->loading=0; -#ifdef BLOCKOUT_1 + lp->loading = 0; +#ifdef BLOCKOUT_1 enable_irq(dev->irq); -#endif +#endif dev->trans_start = jiffies; } if (el_debug > 2) printk(" queued xmit.\n"); - dev_kfree_skb (skb, FREE_WRITE); + dev_kfree_skb(skb, FREE_WRITE); return 0; } - /* * The typical workload of the driver: - * Handle the ether interface interrupts. + * Handle the ether interface interrupts. */ static void el_interrupt(int irq, void *dev_id, struct pt_regs *regs) @@ -491,9 +491,8 @@ int ioaddr; int axsr; /* Aux. status reg. */ - if (dev == NULL || dev->irq != irq) - { - printk ("3c501 driver: irq %d for unknown device.\n", irq); + if (dev == NULL || dev->irq != irq) { + printk("3c501 driver: irq %d for unknown device.\n", irq); return; } @@ -501,9 +500,9 @@ lp = (struct net_local *)dev->priv; /* - * What happened ? + * What happened? */ - + axsr = inb(AX_STATUS); /* @@ -515,55 +514,53 @@ if (dev->interrupt) printk("%s: Reentering the interrupt driver!\n", dev->name); dev->interrupt = 1; -#ifndef BLOCKOUT_1 - if(lp->loading==1 && !dev->tbusy) - printk("%s: Inconsistent state loading while not in tx\n", - dev->name); -#endif +#ifndef BLOCKOUT_1 + if (lp->loading == 1 && !dev->tbusy) + printk("%s: Inconsistent state loading while not in tx\n", + dev->name); +#endif #ifdef BLOCKOUT_3 - lp->loading=2; /* So we can spot loading interruptions */ + lp->loading = 2; /* So we can spot loading interruptions */ #endif - if (dev->tbusy) - { - - /* - * Board in transmit mode. May be loading. If we are - * loading we shouldn't have got this. - */ - + if (dev->tbusy) { + /* + * Board in transmit mode. May be loading. If we are + * loading we shouldn't have got this. + */ + int txsr = inb(TX_STATUS); -#ifdef BLOCKOUT_2 - if(lp->loading==1) - { - if(el_debug > 2) - { - printk("%s: Interrupt while loading [", dev->name); - printk(" txsr=%02x gp=%04x rp=%04x]\n", txsr, inw(GP_LOW),inw(RX_LOW)); +#ifdef BLOCKOUT_2 + if (lp->loading == 1) { + if(el_debug > 2) { + printk("%s: Interrupt while loading [", + dev->name); + printk(" txsr=%02x gp=%04x rp=%04x]\n", + txsr, inw(GP_LOW), inw(RX_LOW)); } - lp->loading=2; /* Force a reload */ + lp->loading = 2; /* Force a reload */ dev->interrupt = 0; return; } #endif if (el_debug > 6) - printk(" txsr=%02x gp=%04x rp=%04x", txsr, inw(GP_LOW),inw(RX_LOW)); + printk(" txsr=%02x gp=%04x rp=%04x", + txsr, inw(GP_LOW), inw(RX_LOW)); - if ((axsr & 0x80) && (txsr & TX_READY) == 0) - { + if ((axsr & 0x80) && (txsr & TX_READY) == 0) { /* - * FIXME: is there a logic to whether to keep on trying or - * reset immediately ? + * FIXME: is there a logic to whether to keep on + * trying or reset immediately ? */ - if(el_debug>1) - printk("%s: Unusual interrupt during Tx, txsr=%02x axsr=%02x" - " gp=%03x rp=%03x.\n", dev->name, txsr, axsr, + if (el_debug > 1) + printk("%s: Unusual interrupt during Tx, " + "txsr=%02x axsr=%02x" + " gp=%03x rp=%03x.\n", dev->name, + txsr, axsr, inw(ioaddr + EL1_DATAPTR), inw(ioaddr + EL1_RXPTR)); dev->tbusy = 0; mark_bh(NET_BH); - } - else if (txsr & TX_16COLLISIONS) - { + } else if (txsr & TX_16COLLISIONS) { /* * Timed out */ @@ -571,35 +568,32 @@ printk("%s: Transmit failed 16 times, ethernet jammed?\n",dev->name); outb(AX_SYS, AX_CMD); lp->stats.tx_aborted_errors++; - } - else if (txsr & TX_COLLISION) - { + } else if (txsr & TX_COLLISION) { /* - * Retrigger xmit. + * Retrigger xmit. */ - + if (el_debug > 6) printk(" retransmitting after a collision.\n"); /* - * Poor little chip can't reset its own start pointer + * Poor little chip can't reset its own start + * pointer */ - + outb(AX_SYS, AX_CMD); outw(lp->tx_pkt_start, GP_LOW); outb(AX_XMIT, AX_CMD); lp->stats.collisions++; dev->interrupt = 0; return; - } - else - { + } else { /* * It worked.. we will now fall through and receive */ lp->stats.tx_packets++; if (el_debug > 6) printk(" Tx succeeded %s\n", - (txsr & TX_RDY) ? "." : "but tx is busy!"); + (txsr & TX_RDY) ? "." : "but tx is busy!"); /* * This is safe the interrupt is atomic WRT itself. */ @@ -607,36 +601,31 @@ dev->tbusy = 0; mark_bh(NET_BH); /* In case more to transmit */ } - } - else - { - /* - * In receive mode. - */ - + } else { + /* + * In receive mode. + */ + int rxsr = inb(RX_STATUS); if (el_debug > 5) - printk(" rxsr=%02x txsr=%02x rp=%04x", rxsr, inb(TX_STATUS),inw(RX_LOW)); + printk(" rxsr=%02x txsr=%02x rp=%04x", rxsr, + inb(TX_STATUS),inw(RX_LOW)); /* - * Just reading rx_status fixes most errors. + * Just reading rx_status fixes most errors. */ if (rxsr & RX_MISSED) lp->stats.rx_missed_errors++; - else if (rxsr & RX_RUNT) - { /* Handled to avoid board lock-up. */ + else if (rxsr & RX_RUNT) { + /* Handled to avoid board lock-up. */ lp->stats.rx_length_errors++; - if (el_debug > 5) + if (el_debug > 5) printk(" runt.\n"); - } - else if (rxsr & RX_GOOD) - { + } else if (rxsr & RX_GOOD) { /* * Receive worked. */ el_receive(dev); - } - else - { + } else { /* * Nothing? Something is broken! */ @@ -650,7 +639,7 @@ } /* - * Move into receive mode + * Move into receive mode */ outb(AX_RX, AX_CMD); @@ -661,10 +650,9 @@ return; } - /* * We have a good packet. Well, not really "good", just mostly not broken. - * We must check everything to see if it is good. + * We must check everything to see if it is good. */ static void el_receive(struct device *dev) @@ -679,43 +667,39 @@ if (el_debug > 4) printk(" el_receive %d.\n", pkt_len); - if ((pkt_len < 60) || (pkt_len > 1536)) - { + if ((pkt_len < 60) || (pkt_len > 1536)) { if (el_debug) printk("%s: bogus packet, length=%d\n", dev->name, pkt_len); lp->stats.rx_over_errors++; return; } - + /* * Command mode so we can empty the buffer */ - + outb(AX_SYS, AX_CMD); - skb = dev_alloc_skb(pkt_len+2); + skb = dev_alloc_skb(pkt_len + 2); /* * Start of frame */ outw(0x00, GP_LOW); - if (skb == NULL) - { + if (skb == NULL) { printk("%s: Memory squeeze, dropping packet.\n", dev->name); lp->stats.rx_dropped++; return; - } - else - { - skb_reserve(skb,2); /* Force 16 byte alignment */ + } else { + skb_reserve(skb,2); /* Force 16 byte alignment */ skb->dev = dev; /* * The read increments through the bytes. The interrupt - * handler will fix the pointer when it returns to + * handler will fix the pointer when it returns to * receive mode. */ - insb(DATAPORT, skb_put(skb,pkt_len), pkt_len); - skb->protocol=eth_type_trans(skb,dev); + insb(DATAPORT, skb_put(skb, pkt_len), pkt_len); + skb->protocol = eth_type_trans(skb, dev); netif_rx(skb); lp->stats.rx_packets++; } @@ -735,7 +719,7 @@ for (i = 0; i < 6; i++) /* Set the station address. */ outb(dev->dev_addr[i], ioaddr + i); } - + outw(0, RX_BUF_CLR); /* Set rx packet area to 0. */ cli(); /* Avoid glitch on writes to CMD regs */ outb(TX_NORM, TX_CMD); /* tx irq on done, collision */ @@ -752,13 +736,14 @@ int ioaddr = dev->base_addr; if (el_debug > 2) - printk("%s: Shutting down ethercard at %#x.\n", dev->name, ioaddr); + printk("%s: Shutting down ethercard at %#x.\n", dev->name, + ioaddr); dev->tbusy = 1; dev->start = 0; /* - * Free and disable the IRQ. + * Free and disable the IRQ. */ free_irq(dev->irq, NULL); @@ -784,18 +769,13 @@ { int ioaddr = dev->base_addr; - if(dev->flags&IFF_PROMISC) - { + if(dev->flags&IFF_PROMISC) { outb(RX_PROM, RX_CMD); inb(RX_STATUS); - } - else if (dev->mc_list || dev->flags&IFF_ALLMULTI) - { + } else if (dev->mc_list || dev->flags&IFF_ALLMULTI) { outb(RX_MULT, RX_CMD); /* Multicast or all multicast is the same */ inb(RX_STATUS); /* Clear status. */ - } - else - { + } else { outb(RX_NORM, RX_CMD); inb(RX_STATUS); } @@ -805,17 +785,17 @@ static char devicename[9] = { 0, }; -static struct device dev_3c501 = +static struct device dev_3c501 = { devicename, /* device name is inserted by linux/drivers/net/net_init.c */ 0, 0, 0, 0, 0x280, 5, - 0, 0, 0, NULL, el1_probe + 0, 0, 0, NULL, el1_probe }; -static int io=0x280; -static int irq=5; - +static int io = 0x280; +static int irq = 5; + int init_module(void) { dev_3c501.irq=irq; @@ -830,24 +810,23 @@ /* * No need to check MOD_IN_USE, as sys_delete_module() checks. */ - + unregister_netdev(&dev_3c501); /* - * Free up the private structure, or leak memory :-) + * Free up the private structure, or leak memory :-) */ - + kfree(dev_3c501.priv); dev_3c501.priv = NULL; /* gets re-allocated by el1_probe1 */ /* - * If we don't do this, we can't re-insmod it later. + * If we don't do this, we can't re-insmod it later. */ release_region(dev_3c501.base_addr, EL1_IO_EXTENT); } #endif /* MODULE */ - /* * Local variables: * compile-command: "gcc -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -m486 -c -o 3c501.o 3c501.c" diff -urN linux-2.0.40-rc6/drivers/net/3c505.c linux-2.0.40-rc7/drivers/net/3c505.c --- linux-2.0.40-rc6/drivers/net/3c505.c 1996-08-05 00:13:52.000000000 -0700 +++ linux-2.0.40-rc7/drivers/net/3c505.c 2004-01-15 07:19:51.000000000 -0800 @@ -3,7 +3,7 @@ * By Craig Southeren, Juha Laiho and Philip Blundell * * 3c505.c This module implements an interface to the 3Com - * Etherlink Plus (3c505) ethernet card. Linux device + * Etherlink Plus (3c505) ethernet card. Linux device * driver interface reverse engineered from the Linux 3C509 * device drivers. Some 3C505 information gleaned from * the Crynwr packet driver. Still this driver would not @@ -1092,8 +1092,9 @@ adapter->current_dma.start_time = jiffies; target = virt_to_bus(skb->data); - if ((target + nlen) >= MAX_DMA_ADDRESS) { - memcpy(adapter->dma_buffer, skb->data, nlen); + if ((target + nlen) >= MAX_DMA_ADDRESS || nlen != skb->len) { + memcpy(adapter->dma_buffer, skb->data, skb->len); + memset(adapter->dma_buffer + skb->len, 0, nlen - skb->len); target = virt_to_bus(adapter->dma_buffer); } adapter->current_dma.skb = skb; @@ -1132,7 +1133,7 @@ */ if (dev->tbusy) { elp_device *adapter = dev->priv; - int tickssofar = jiffies - dev->trans_start; + int tickssofar = jiffies - dev->trans_start; int stat; if (tickssofar < 1000) diff -urN linux-2.0.40-rc6/drivers/net/3c507.c linux-2.0.40-rc7/drivers/net/3c507.c --- linux-2.0.40-rc6/drivers/net/3c507.c 1996-02-29 21:50:42.000000000 -0800 +++ linux-2.0.40-rc7/drivers/net/3c507.c 2004-01-15 07:19:51.000000000 -0800 @@ -66,6 +66,7 @@ #define NET_DEBUG 1 #endif static unsigned int net_debug = NET_DEBUG; +static char padding[ETH_ZLEN]; /* A zero-terminated list of common I/O addresses to be probed. */ static unsigned int netcard_portlist[] = @@ -285,10 +286,10 @@ static int el16_close(struct device *dev); static struct enet_statistics *el16_get_stats(struct device *dev); -static void hardware_send_packet(struct device *dev, void *buf, short length); +static void hardware_send_packet(struct device *dev, void *buf, short length, + short pad); void init_82586_mem(struct device *dev); - #ifdef HAVE_DEVLIST struct netdev_entry netcard_drv = {"3c507", el16_probe1, EL16_IO_EXTENT, netcard_portlist}; @@ -428,8 +429,6 @@ return 0; } - - static int el16_open(struct device *dev) { @@ -438,6 +437,7 @@ /* Initialize the 82586 memory and start it. */ init_82586_mem(dev); + memset(padding, 0, ETH_ZLEN); dev->tbusy = 0; dev->interrupt = 0; dev->start = 1; @@ -497,7 +497,7 @@ /* Disable the 82586's input to the interrupt line. */ outb(0x80, ioaddr + MISC_CTRL); - hardware_send_packet(dev, buf, length); + hardware_send_packet(dev, buf, length, length - skb->len); dev->trans_start = jiffies; /* Enable the 82586 interrupt input. */ outb(0x84, ioaddr + MISC_CTRL); @@ -509,7 +509,7 @@ return 0; } - + /* The typical workload of the driver: Handle the network interface interrupts. */ static void @@ -759,7 +759,7 @@ } static void -hardware_send_packet(struct device *dev, void *buf, short length) +hardware_send_packet(struct device *dev, void *buf, short length, short pad) { struct net_local *lp = (struct net_local *)dev->priv; short ioaddr = dev->base_addr; @@ -767,14 +767,14 @@ ushort *write_ptr = (ushort *)(dev->mem_start + tx_block); /* Set the write pointer to the Tx block, and put out the header. */ - *write_ptr++ = 0x0000; /* Tx status */ + *write_ptr++ = 0x0000; /* Tx status */ *write_ptr++ = CMD_INTR|CmdTx; /* Tx command */ - *write_ptr++ = tx_block+16; /* Next command is a NoOp. */ - *write_ptr++ = tx_block+8; /* Data Buffer offset. */ + *write_ptr++ = tx_block+16; /* Next command is a NoOp. */ + *write_ptr++ = tx_block+8; /* Data Buffer offset. */ /* Output the data buffer descriptor. */ - *write_ptr++ = length | 0x8000; /* Byte count parameter. */ - *write_ptr++ = -1; /* No next data buffer. */ + *write_ptr++ = (pad + length) | 0x8000; /* Byte count parameter. */ + *write_ptr++ = -1; /* No next data buffer. */ *write_ptr++ = tx_block+22+SCB_BASE;/* Buffer follows the NoOp command. */ *write_ptr++ = 0x0000; /* Buffer address high bits (always zero). */ @@ -785,6 +785,8 @@ /* Output the packet at the write pointer. */ memcpy(write_ptr, buf, length); + if (pad) + memcpy(write_ptr + length, padding, pad); /* Set the old command link pointing to this send packet. */ *(ushort*)(dev->mem_start + lp->tx_cmd_link) = tx_block; @@ -911,7 +913,6 @@ release_region(dev_3c507.base_addr, EL16_IO_EXTENT); } #endif /* MODULE */ - /* * Local variables: * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -I/usr/src/linux/drivers/net -Wall -Wstrict-prototypes -O6 -m486 -c 3c507.c" diff -urN linux-2.0.40-rc6/drivers/net/8390.c linux-2.0.40-rc7/drivers/net/8390.c --- linux-2.0.40-rc6/drivers/net/8390.c 1996-05-18 01:15:09.000000000 -0700 +++ linux-2.0.40-rc7/drivers/net/8390.c 2004-01-15 07:19:51.000000000 -0800 @@ -97,12 +97,13 @@ static void ei_receive(struct device *dev); static void ei_rx_overrun(struct device *dev); +static char scratch[ETH_ZLEN]; + /* Routines generic to NS8390-based boards. */ static void NS8390_trigger_send(struct device *dev, unsigned int length, int start_page); static void set_multicast_list(struct device *dev); - /* Open/initialize the board. This routine goes all-out, setting everything up anew at each open, even though many of these registers should only need to be set once at boot. @@ -238,8 +239,13 @@ * trigger the send later, upon receiving a Tx done interrupt. */ - ei_block_output(dev, length, skb->data, output_page); - if (! ei_local->txing) { + if (length == send_length) + ei_block_output(dev, length, skb->data, output_page); + else { + memcpy(scratch, skb->data, skb->len); + ei_block_output(dev, ETH_ZLEN, scratch, output_page); + } + if (!ei_local->txing) { ei_local->txing = 1; NS8390_trigger_send(dev, send_length, output_page); dev->trans_start = jiffies; @@ -263,7 +269,12 @@ * reasonable hardware if you only use one Tx buffer. */ - ei_block_output(dev, length, skb->data, ei_local->tx_start_page); + if (length == send_length) + ei_block_output(dev, length, skb->data, ei_local->tx_start_page); + else { + memcpy(scratch, skb->data, skb->len); + ei_block_output(dev, ETH_ZLEN, scratch, ei_local->tx_start_page); + } ei_local->txing = 1; NS8390_trigger_send(dev, send_length, ei_local->tx_start_page); dev->trans_start = jiffies; @@ -754,7 +765,10 @@ /* Clear the pending interrupts and mask. */ outb_p(0xFF, e8390_base + EN0_ISR); outb_p(0x00, e8390_base + EN0_IMR); - + + /* Zerofill the padding buffer */ + memset(scratch, 0, ETH_ZLEN); + /* Copy the station address into the DS8390 registers, and set the multicast hash bitmap to receive all multicasts. */ save_flags(flags); diff -urN linux-2.0.40-rc6/drivers/net/atarilance.c linux-2.0.40-rc7/drivers/net/atarilance.c --- linux-2.0.40-rc6/drivers/net/atarilance.c 1997-04-08 08:47:45.000000000 -0700 +++ linux-2.0.40-rc7/drivers/net/atarilance.c 2004-01-15 07:19:51.000000000 -0800 @@ -771,6 +771,17 @@ DPRINTK( 2, ( "%s: lance_start_xmit() called, csr0 %4.4x.\n", dev->name, DREG )); + /* The old LANCE chips doesn't automatically pad buffers to min size */ + if ((len = skb->len) < ETH_ZLEN) + len = ETH_ZLEN; + else if (lp->cardtype == PAM_CARD && (len & 1)) + ++len; + + if (len > skb->len) { + if (!(skb = skb_padto(skb, len))) + return 0; + } + /* Block a timer-based transmit from overlapping. This could better be done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ if (set_bit( 0, (void*)&dev->tbusy ) != 0) { @@ -807,17 +818,11 @@ /* Mask to ring buffer boundary. */ entry = lp->cur_tx & TX_RING_MOD_MASK; head = &(MEM->tx_head[entry]); - + /* Caution: the write order is important here, set the "ownership" bits * last. */ - /* The old LANCE chips doesn't automatically pad buffers to min. size. */ - len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN; - /* PAM-Card has a bug: Can only send packets with even number of bytes! */ - if (lp->cardtype == PAM_CARD && (len & 1)) - ++len; - head->length = -len; head->misc = 0; lp->memcpy_f( PKTBUF_ADDR(head), (void *)skb->data, skb->len ); diff -urN linux-2.0.40-rc6/drivers/net/de600.c linux-2.0.40-rc7/drivers/net/de600.c --- linux-2.0.40-rc6/drivers/net/de600.c 1996-02-29 21:50:43.000000000 -0800 +++ linux-2.0.40-rc7/drivers/net/de600.c 2004-01-15 07:19:51.000000000 -0800 @@ -36,7 +36,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * **************************************************************/ /* Add another "; SLOW_DOWN_IO" here if your adapter won't work OK: */ @@ -400,6 +400,7 @@ int len; int tickssofar; byte *buffer = skb->data; + int i; /* * If some higher layer thinks we've missed a @@ -454,8 +455,10 @@ #endif de600_setup_address(transmit_from, RW_ADDR); - for ( ; len > 0; --len, ++buffer) + for (i = 0 ; i < skb->len; ++i, ++buffer) de600_put_byte(*buffer); + for (; i < len; ++i) + de600_put_byte(0); if (free_tx_pages-- == TX_PAGES) { /* No transmission going on */ dev->trans_start = jiffies; @@ -468,9 +471,9 @@ dev->tbusy = !free_tx_pages; select_prn(); } - + sti(); /* interrupts back on */ - + #ifdef FAKE_SMALL_MAX /* This will "patch" the socket TCP proto at an early moment */ if (skb->sk && (skb->sk->protocol == IPPROTO_TCP) && @@ -812,7 +815,7 @@ /* * Hack! You might want to play with commenting away the following line, * if you know what you do! - sk->max_unacked = DE600_MAX_WINDOW - DE600_TCP_WINDOW_DIFF; + sk->max_unacked = DE600_MAX_WINDOW - DE600_TCP_WINDOW_DIFF; */ if (sk->rmem_alloc >= sk->rcvbuf-2*DE600_MIN_WINDOW) return(0); @@ -823,7 +826,7 @@ return(0); } #endif - + #ifdef MODULE static char nullname[8]; static struct device de600_dev = { diff -urN linux-2.0.40-rc6/drivers/net/de620.c linux-2.0.40-rc7/drivers/net/de620.c --- linux-2.0.40-rc6/drivers/net/de620.c 1996-02-29 21:50:43.000000000 -0800 +++ linux-2.0.40-rc7/drivers/net/de620.c 2004-01-15 07:19:51.000000000 -0800 @@ -304,7 +304,7 @@ } static inline void -de620_write_block(struct device *dev, byte *buffer, int count) +de620_write_block(struct device *dev, byte *buffer, int count, int pad) { #ifndef LOWSPEED byte uflip = NIC_Cmd ^ (DS0 | DS1); @@ -320,9 +320,10 @@ tot_cnt = 0; #endif /* COUNT_LOOPS */ /* No further optimization useful, the limit is in the adapter. */ - for ( ; count > 0; --count, ++buffer) { + for (; count > 0; --count, ++buffer) de620_put_byte(dev,*buffer); - } + for (count = pad; count > 0; --count, ++buffer) + de620_put_byte(dev, 0); de620_send_command(dev,W_DUMMY); #ifdef COUNT_LOOPS /* trial debug output: loops per byte in de620_ready() */ @@ -578,20 +579,20 @@ return 1; break; } - de620_write_block(dev, buffer, len); + de620_write_block(dev, buffer, skb->len, len - skb->len); dev->trans_start = jiffies; dev->tbusy = (using_txbuf == (TXBF0 | TXBF1)); /* Boolean! */ ((struct netstats *)(dev->priv))->tx_packets++; - + restore_flags(flags); /* interrupts maybe back on */ - + dev_kfree_skb (skb, FREE_WRITE); return 0; } - + /***************************************************** * * Handle the network interface interrupts. diff -urN linux-2.0.40-rc6/drivers/net/depca.c linux-2.0.40-rc7/drivers/net/depca.c --- linux-2.0.40-rc6/drivers/net/depca.c 2004-01-15 07:19:51.000000000 -0800 +++ linux-2.0.40-rc7/drivers/net/depca.c 2004-01-15 07:19:51.000000000 -0800 @@ -843,6 +843,10 @@ } else if (skb == NULL) { dev_tint(dev); } else if (skb->len > 0) { + if (skb->len < ETH_ZLEN) { + if (!(skb = skb_padto(skb, ETH_ZLEN))) + return 0; + } /* Enforce 1 process per h/w access */ if (set_bit(0, (void*)&dev->tbusy) != 0) { printk("%s: Transmitter access conflict.\n", dev->name); diff -urN linux-2.0.40-rc6/drivers/net/epic100.c linux-2.0.40-rc7/drivers/net/epic100.c --- linux-2.0.40-rc6/drivers/net/epic100.c 1999-06-13 10:21:01.000000000 -0700 +++ linux-2.0.40-rc7/drivers/net/epic100.c 2004-01-15 07:19:51.000000000 -0800 @@ -865,6 +865,11 @@ int entry; u32 flag; + if (skb->len < ETH_ZLEN) { + if (!(skb = skb_padto(skb, ETH_ZLEN))) + return 0; + } + /* Block a timer-based transmit from overlapping. This could better be done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { diff -urN linux-2.0.40-rc6/drivers/net/hp100.c linux-2.0.40-rc7/drivers/net/hp100.c --- linux-2.0.40-rc6/drivers/net/hp100.c 1998-11-15 10:33:03.000000000 -0800 +++ linux-2.0.40-rc7/drivers/net/hp100.c 2004-01-15 07:19:51.000000000 -0800 @@ -1555,9 +1555,14 @@ #endif return 0; } - - if ( skb->len <= 0 ) return 0; - + + if (skb->len <= 0) + return 0; + + if (skb->len < ETH_ZLEN && lp->chip == HP100_CHIPID_SHASTA) { + if (!(skb = skb_padto(skb, ETH_ZLEN))) + return 0; + } /* Get Tx ring tail pointer */ if( lp->txrtail->next==lp->txrhead ) { diff -urN linux-2.0.40-rc6/drivers/net/ni52.c linux-2.0.40-rc7/drivers/net/ni52.c --- linux-2.0.40-rc6/drivers/net/ni52.c 1999-06-13 10:21:01.000000000 -0700 +++ linux-2.0.40-rc7/drivers/net/ni52.c 2004-01-15 07:19:51.000000000 -0800 @@ -1176,10 +1176,13 @@ return 1; } #endif - else - { + else { + if ((len = skb->len) < ETH_ZLEN) { + len = ETH_ZLEN; + memset((char *)p->xmit_cbuffs[p->xmit_count] + skb->len, 0, + len - skb->len); + } memcpy((char *)p->xmit_cbuffs[p->xmit_count],(char *)(skb->data),skb->len); - len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN; #if (NUM_XMIT_BUFFS == 1) # ifdef NO_NOPCOMMANDS diff -urN linux-2.0.40-rc6/drivers/net/ni65.c linux-2.0.40-rc7/drivers/net/ni65.c --- linux-2.0.40-rc6/drivers/net/ni65.c 1996-11-01 13:07:23.000000000 -0800 +++ linux-2.0.40-rc7/drivers/net/ni65.c 2004-01-15 07:19:51.000000000 -0800 @@ -1112,8 +1112,11 @@ if( (unsigned long) (skb->data + skb->len) > 0x1000000) { #endif - memcpy((char *) p->tmdbounce[p->tmdbouncenum] ,(char *)skb->data, + memcpy((char *) p->tmdbounce[p->tmdbouncenum], (char *)skb->data, (skb->len > T_BUF_SIZE) ? T_BUF_SIZE : skb->len); + if (len > skb->len) + memset((char *)p->tmdbounce[p->tmdbouncenum] + skb->len, 0 + len - skb->len); dev_kfree_skb (skb, FREE_WRITE); save_flags(flags); diff -urN linux-2.0.40-rc6/drivers/net/rtl8139.c linux-2.0.40-rc7/drivers/net/rtl8139.c --- linux-2.0.40-rc6/drivers/net/rtl8139.c 1999-06-13 10:21:01.000000000 -0700 +++ linux-2.0.40-rc7/drivers/net/rtl8139.c 2004-01-15 07:19:51.000000000 -0800 @@ -922,6 +922,12 @@ return 1; } + if (skb->len < ETH_ZLEN) { + if (!(skb = skb_padto(skb, ETH_ZLEN))) { + clear_bit(0, (void *)&dev->tbusy); + return 0; + } + /* Calculate the next Tx descriptor entry. */ entry = tp->cur_tx % NUM_TX_DESC; diff -urN linux-2.0.40-rc6/drivers/net/seeq8005.c linux-2.0.40-rc7/drivers/net/seeq8005.c --- linux-2.0.40-rc6/drivers/net/seeq8005.c 1996-05-06 02:26:08.000000000 -0700 +++ linux-2.0.40-rc7/drivers/net/seeq8005.c 2004-01-15 07:19:51.000000000 -0800 @@ -402,10 +402,18 @@ if (set_bit(0, (void*)&dev->tbusy) != 0) printk("%s: Transmitter access conflict.\n", dev->name); else { - short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; + short length = skb->len; unsigned char *buf = skb->data; - hardware_send_packet(dev, buf, length); + if (length < ETH_ZLEN) { + if (!(skb = skb_padto(skb, ETH_ZLEN))) { + dev->tbusy = 0; + return 0; + } + length = ETH_ZLEN; + } + + hardware_send_packet(dev, buf, length); dev->trans_start = jiffies; } dev_kfree_skb (skb, FREE_WRITE); diff -urN linux-2.0.40-rc6/drivers/net/sk_g16.c linux-2.0.40-rc7/drivers/net/sk_g16.c --- linux-2.0.40-rc6/drivers/net/sk_g16.c 1998-06-03 15:17:47.000000000 -0700 +++ linux-2.0.40-rc7/drivers/net/sk_g16.c 2004-01-15 07:19:51.000000000 -0800 @@ -1192,6 +1192,7 @@ { struct priv *p = (struct priv *) dev->priv; struct tmd *tmdp; + static char pad[64]; if (dev->tbusy) { @@ -1253,8 +1254,11 @@ /* Copy data into dual ported ram */ - memcpy((char *) (tmdp->u.buffer & 0x00ffffff), (char *)skb->data, + memcpy((char *)(tmdp->u.buffer & 0x00ffffff), (char *)skb->data, skb->len); + if (len != skb->len) + memcpy((char *)(tmdp->u.buffer & 0x00ffffff) + skb->len, pad, + len - skb->len); tmdp->blen = -len; /* set length to transmit */ diff -urN linux-2.0.40-rc6/drivers/net/smc9194.c linux-2.0.40-rc7/drivers/net/smc9194.c --- linux-2.0.40-rc6/drivers/net/smc9194.c 1996-04-11 23:49:39.000000000 -0700 +++ linux-2.0.40-rc7/drivers/net/smc9194.c 2004-01-15 07:19:51.000000000 -0800 @@ -558,10 +558,15 @@ printk(CARDNAME": Bad Craziness - sent packet while busy.\n" ); return 1; } + + if ((length = skb->len) < ETH_ZLEN) { + if (!(skb = skb_padto(skb, ETH_ZLEN))) { + return 0; + } + length = ETH_ZLEN; + } lp->saved_skb = skb; - length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; - /* . the MMU wants the number of pages to be the number of 256 bytes . 'pages', minus 1 ( since a packet can't ever have 0 pages :) ) diff -urN linux-2.0.40-rc6/drivers/net/tulip.c linux-2.0.40-rc7/drivers/net/tulip.c --- linux-2.0.40-rc6/drivers/net/tulip.c 2004-01-15 07:19:51.000000000 -0800 +++ linux-2.0.40-rc7/drivers/net/tulip.c 2004-01-15 07:19:51.000000000 -0800 @@ -585,7 +585,11 @@ if (tulip_debug > 0 && did_version++ == 0) printk(KERN_INFO "%s", version); - dev = init_etherdev(dev, 0); + if (!(dev = init_etherdev(dev, 0))) { + printk(KERN_ERR "tulip: Unable to allocate net_device " + "structure!\n"); + return NULL; + } /* Bring the 21143 out of sleep mode. Caution: Snooze mode does not work with some boards! */ diff -urN linux-2.0.40-rc6/drivers/net/via-rhine.c linux-2.0.40-rc7/drivers/net/via-rhine.c --- linux-2.0.40-rc6/drivers/net/via-rhine.c 1998-11-15 10:33:04.000000000 -0800 +++ linux-2.0.40-rc7/drivers/net/via-rhine.c 2004-01-15 07:19:51.000000000 -0800 @@ -848,6 +848,13 @@ /* Calculate the next Tx descriptor entry. */ entry = np->cur_tx % TX_RING_SIZE; + if (skb->len < ETH_ZLEN) { + if (!(skb = skb_padto(skb,ETH_ZLEN))) { + dev->tbusy = 0; + return 0; + } + } + np->tx_skbuff[entry] = skb; if ((long)skb->data & 3) { /* Must use alignment buffer. */ diff -urN linux-2.0.40-rc6/drivers/net/znet.c linux-2.0.40-rc7/drivers/net/znet.c --- linux-2.0.40-rc6/drivers/net/znet.c 1996-02-29 21:50:49.000000000 -0800 +++ linux-2.0.40-rc7/drivers/net/znet.c 2004-01-15 07:19:51.000000000 -0800 @@ -317,10 +317,17 @@ static int znet_send_packet(struct sk_buff *skb, struct device *dev) { int ioaddr = dev->base_addr; + short length = skb->len; if (znet_debug > 4) printk(KERN_DEBUG "%s: ZNet_send_packet(%ld).\n", dev->name, dev->tbusy); + if (length < ETH_ZLEN) { + if (!(skb = skb_padto(skb, ETH_ZLEN))) + return 0; + length = ETH_ZLEN; + } + /* Transmitter timeout, likely just recovery after suspending the machine. */ if (dev->tbusy) { ushort event, tx_status, rx_offset, state; @@ -357,7 +364,6 @@ if (set_bit(0, (void*)&dev->tbusy) != 0) printk(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name); else { - short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; unsigned char *buf = (void *)skb->data; ushort *tx_link = zn.tx_cur - 1; ushort rnd_len = (length + 1)>>1; diff -urN linux-2.0.40-rc6/fs/Config.in linux-2.0.40-rc7/fs/Config.in --- linux-2.0.40-rc6/fs/Config.in 2001-01-09 13:29:20.000000000 -0800 +++ linux-2.0.40-rc7/fs/Config.in 2004-01-15 07:19:51.000000000 -0800 @@ -53,6 +53,9 @@ fi bool '/proc filesystem support' CONFIG_PROC_FS +if [ "$CONFIG_PROC_FS" = "y" ]; then + bool ' Enable mmap on /proc/*/mem (UNSECURE!)' CONFIG_UNSAFE_MMAP +fi if [ "$CONFIG_INET" = "y" ]; then tristate 'NFS filesystem support' CONFIG_NFS_FS if [ "$CONFIG_NFS_FS" = "y" ]; then diff -urN linux-2.0.40-rc6/fs/proc/mem.c linux-2.0.40-rc7/fs/proc/mem.c --- linux-2.0.40-rc6/fs/proc/mem.c 1998-11-15 10:33:14.000000000 -0800 +++ linux-2.0.40-rc7/fs/proc/mem.c 2004-01-15 07:19:51.000000000 -0800 @@ -4,6 +4,7 @@ * Copyright (C) 1991, 1992 Linus Torvalds */ +#include #include #include #include @@ -17,7 +18,7 @@ /* * mem_write isn't really a good idea right now. It needs - * to check a lot more: if the process we try to write to + * to check a lot more: if the process we try to write to * dies in the middle right now, mem_write will overwrite * kernel memory.. This disables it altogether. */ @@ -209,6 +210,7 @@ } } +#ifdef CONFIG_UNSAFE_MMAP /* * This isn't really reliable by any means.. */ @@ -311,6 +313,7 @@ flush_tlb_range(src_vma->vm_mm, src_vma->vm_start, src_vma->vm_end); return 0; } +#endif /* CONFIG_UNSAFE_MMAP */ static struct file_operations proc_mem_operations = { mem_lseek, @@ -319,7 +322,11 @@ NULL, /* mem_readdir */ NULL, /* mem_select */ NULL, /* mem_ioctl */ +#ifdef CONFIG_UNSAFE_MMAP mem_mmap, /* mmap */ +#else + NULL, /* mmap */ +#endif /* CONFIG_UNSAFE_MMAP */ NULL, /* no special open code */ NULL, /* no special release code */ NULL /* can't fsync */ diff -urN linux-2.0.40-rc6/include/linux/skbuff.h linux-2.0.40-rc7/include/linux/skbuff.h --- linux-2.0.40-rc6/include/linux/skbuff.h 2004-01-15 07:19:51.000000000 -0800 +++ linux-2.0.40-rc7/include/linux/skbuff.h 2004-01-15 07:19:51.000000000 -0800 @@ -163,6 +163,7 @@ extern void kfree_skbmem(struct sk_buff *skb); extern struct sk_buff * skb_clone(struct sk_buff *skb, int priority); extern struct sk_buff * skb_copy(struct sk_buff *skb, int priority); +extern struct sk_buff * skb_pad(struct sk_buff *skb, int pad); extern void skb_device_lock(struct sk_buff *skb); extern void skb_device_unlock(struct sk_buff *skb); extern void dev_kfree_skb(struct sk_buff *skb, int mode); @@ -197,19 +198,19 @@ /* * Return the length of an sk_buff queue */ - + extern __inline__ __u32 skb_queue_len(struct sk_buff_head *list_) { return(list_->qlen); } #if CONFIG_SKB_CHECK -extern int skb_check(struct sk_buff *skb,int,int, char *); -#define IS_SKB(skb) skb_check((skb), 0, __LINE__,__FILE__) -#define IS_SKB_HEAD(skb) skb_check((skb), 1, __LINE__,__FILE__) -#define IS_SKB_LINKED(skb) skb_check((skb), 2, __LINE__,__FILE__) -#define IS_SKB_UNLINKED(skb) skb_check((skb), 3, __LINE__,__FILE__) -/* Note: IS_SKB_LINKED will accept skb_heads in addition to linked-in +extern int skb_check(struct sk_buff *skb, int, int, char *); +#define IS_SKB(skb) skb_check((skb), 0, __LINE__, __FILE__) +#define IS_SKB_HEAD(skb) skb_check((skb), 1, __LINE__, __FILE__) +#define IS_SKB_LINKED(skb) skb_check((skb), 2, __LINE__, __FILE__) +#define IS_SKB_UNLINKED(skb) skb_check((skb), 3, __LINE__, __FILE__) +/* Note: IS_SKB_LINKED will accept skb_heads in addition to linked-in * data skbs */ extern void __skb_queue_head(struct sk_buff_head *list, struct sk_buff *newsk); @@ -221,10 +222,10 @@ extern void __skb_unlink(struct sk_buff *skb, struct sk_buff_head *list); #else -#define IS_SKB(skb) -#define IS_SKB_HEAD(skb) -#define IS_SKB_LINKED(skb) -#define IS_SKB_UNLINKED(skb) +#define IS_SKB(skb) +#define IS_SKB_HEAD(skb) +#define IS_SKB_LINKED(skb) +#define IS_SKB_UNLINKED(skb) extern __inline__ void skb_queue_head_init(struct sk_buff_head *list) { @@ -474,6 +475,14 @@ #endif +static inline struct sk_buff *skb_padto(struct sk_buff *skb, unsigned int len) +{ + unsigned int size = skb->len; + if (size >= len) + return skb; + return skb_pad(skb, len-size); +} + extern struct sk_buff * skb_recv_datagram(struct sock *sk,unsigned flags,int noblock, int *err); extern int datagram_select(struct sock *sk, int sel_type, select_table *wait); extern void skb_copy_datagram(struct sk_buff *from, int offset, char *to,int size); diff -urN linux-2.0.40-rc6/include/net/icmp.h linux-2.0.40-rc7/include/net/icmp.h --- linux-2.0.40-rc6/include/net/icmp.h 1997-12-02 14:20:24.000000000 -0800 +++ linux-2.0.40-rc7/include/net/icmp.h 2004-01-15 07:19:51.000000000 -0800 @@ -28,7 +28,8 @@ extern struct icmp_mib icmp_statistics; extern void icmp_send(struct sk_buff *skb_in, int type, int code, - unsigned long info, struct device *dev); + unsigned long info, struct device *dev, + int hdrincl); extern int icmp_rcv(struct sk_buff *skb1, struct device *dev, struct options *opt, __u32 daddr, unsigned short len, __u32 saddr, diff -urN linux-2.0.40-rc6/ipc/msg.c linux-2.0.40-rc7/ipc/msg.c --- linux-2.0.40-rc6/ipc/msg.c 1996-08-31 23:15:33.000000000 -0700 +++ linux-2.0.40-rc7/ipc/msg.c 2004-01-15 07:19:51.000000000 -0800 @@ -609,6 +609,8 @@ if (err) return err; break; + default: + break; } id = (unsigned int) msqid % MSGMNI; diff -urN linux-2.0.40-rc6/ipc/sem.c linux-2.0.40-rc7/ipc/sem.c --- linux-2.0.40-rc6/ipc/sem.c 2004-01-15 07:19:51.000000000 -0800 +++ linux-2.0.40-rc7/ipc/sem.c 2004-01-15 07:19:51.000000000 -0800 @@ -416,6 +416,8 @@ tbuf.sem_nsems = sma->sem_nsems; memcpy_tofs(buf, &tbuf, sizeof (*buf)); return id; + default: + break; } id = (unsigned int) semid % SEMMNI; @@ -437,6 +439,8 @@ return -EINVAL; curr = &sma->sem_base[semnum]; break; + default: + break; } switch (cmd) { @@ -490,6 +494,8 @@ return i; memcpy_fromfs(&tbuf, buf, sizeof (*buf)); break; + default: + break; } if (semary[id] == IPC_UNUSED || semary[id] == IPC_NOID) diff -urN linux-2.0.40-rc6/ipc/shm.c linux-2.0.40-rc7/ipc/shm.c --- linux-2.0.40-rc6/ipc/shm.c 1998-11-15 10:33:19.000000000 -0800 +++ linux-2.0.40-rc7/ipc/shm.c 2004-01-15 07:19:51.000000000 -0800 @@ -275,6 +275,8 @@ tbuf.shm_nattch = shp->shm_nattch; memcpy_tofs (buf, &tbuf, sizeof(*buf)); return id; + default: + break; } shp = shm_segs[id = (unsigned int) shmid % SHMMNI]; diff -urN linux-2.0.40-rc6/lib/vsprintf.c linux-2.0.40-rc7/lib/vsprintf.c --- linux-2.0.40-rc6/lib/vsprintf.c 2004-01-15 07:19:51.000000000 -0800 +++ linux-2.0.40-rc7/lib/vsprintf.c 2004-01-15 07:19:51.000000000 -0800 @@ -152,19 +152,31 @@ *str++ = *fmt; continue; } - + /* process flags */ flags = 0; - repeat: - ++fmt; /* this also skips first '%' */ - switch (*fmt) { - case '-': flags |= LEFT; goto repeat; - case '+': flags |= PLUS; goto repeat; - case ' ': flags |= SPACE; goto repeat; - case '#': flags |= SPECIAL; goto repeat; - case '0': flags |= ZEROPAD; goto repeat; - } - + repeat: + ++fmt; /* this also skips first '%' */ + switch (*fmt) { + case '-': + flags |= LEFT; + goto repeat; + case '+': + flags |= PLUS; + goto repeat; + case ' ': + flags |= SPACE; + goto repeat; + case '#': + flags |= SPECIAL; + goto repeat; + case '0': + flags |= ZEROPAD; + goto repeat; + default: + break; + } + /* get field width */ field_width = -1; if (is_digit(*fmt)) diff -urN linux-2.0.40-rc6/net/core/skbuff.c linux-2.0.40-rc7/net/core/skbuff.c --- linux-2.0.40-rc6/net/core/skbuff.c 2004-01-15 07:19:51.000000000 -0800 +++ linux-2.0.40-rc7/net/core/skbuff.c 2004-01-15 07:19:51.000000000 -0800 @@ -924,11 +924,76 @@ n->users=0; n->pkt_type=skb->pkt_type; n->stamp=skb->stamp; - + IS_SKB(n); return n; } +struct sk_buff *skb_copy_grow(struct sk_buff *skb, int pad, int gfp_mask) +{ + struct sk_buff *n; + unsigned long offset; + + /* + * Allocate the copy buffer + */ + + if (!(n = alloc_skb(skb->end - skb->head + pad, gfp_mask))) + return NULL; + + /* + * Shift between the two data areas in bytes + */ + + offset = n->head-skb->head; + + /* Set the data pointer */ + skb_reserve(n, skb->data - skb->head); + /* Set the tail pointer and length */ + skb_put(n, skb->len); + /* Copy the bytes */ + memcpy(n->head, skb->head, skb->end - skb->head); + n->csum = skb->csum; + n->list = NULL; + n->sk = NULL; + n->dev = skb->dev; + n->priority = skb->priority; + n->protocol = skb->protocol; + n->dst = dst_clone(skb->dst); + n->h.raw = skb->h.raw + offset; + n->nh.raw = skb->nh.raw + offset; + n->mac.raw = skb->mac.raw + offset; + memcpy(n->cb, skb->cb, sizeof (skb->cb)); + n->used = skb->used; + n->is_clone = 0; + atomic_set(&n->users, 1); + n->pkt_type = skb->pkt_type; + n->stamp = skb->stamp; + n->destructor = NULL; + n->security = skb->security; +#ifdef CONFIG_IP_FIREWALL + n->fwmark = skb->fwmark; +#endif + return n; +} + +struct sk_buff *skb_pad(struct sk_buff *skb, int pad) +{ + struct sk_buff *nskb; + + /* If the skbuff is non linear tailroom is always zero.. */ + if (skb_tailroom(skb) >= pad) { + memset(skb->data + skb->len, 0, pad); + return skb; + } + + nskb = skb_copy_grow(skb, pad, GFP_ATOMIC); + kfree_skb(skb); + if (nskb) + memset(nskb->data + nskb->len, 0, pad); + return nskb; +} + /* * Skbuff device locking */ diff -urN linux-2.0.40-rc6/net/ipv4/arp.c linux-2.0.40-rc7/net/ipv4/arp.c --- linux-2.0.40-rc6/net/ipv4/arp.c 1999-06-13 10:21:04.000000000 -0700 +++ linux-2.0.40-rc7/net/ipv4/arp.c 2004-01-15 07:19:51.000000000 -0800 @@ -1430,7 +1430,7 @@ */ else { - icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0, dev); + icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0, dev, 1); skb_device_unlock(skb); /* else it is lost forever */ dev_kfree_skb(skb, FREE_WRITE); } diff -urN linux-2.0.40-rc6/net/ipv4/icmp.c linux-2.0.40-rc7/net/ipv4/icmp.c --- linux-2.0.40-rc6/net/ipv4/icmp.c 2004-01-15 07:19:51.000000000 -0800 +++ linux-2.0.40-rc7/net/ipv4/icmp.c 2004-01-15 07:19:51.000000000 -0800 @@ -1,6 +1,6 @@ /* - * NET3: Implementation of the ICMP protocol layer. - * + * NET3: Implementation of the ICMP protocol layer. + * * Alan Cox, * * This program is free software; you can redistribute it and/or @@ -16,25 +16,25 @@ * Fixes: * Mike Shaver : RFC1122 checks. * Alan Cox : Multicast ping reply as self. - * Alan Cox : Fix atomicity lockup in ip_build_xmit + * Alan Cox : Fix atomicity lockup in ip_build_xmit * call. - * Alan Cox : Added 216,128 byte paths to the MTU + * Alan Cox : Added 216,128 byte paths to the MTU * code. * Martin Mares : RFC1812 checks. - * Martin Mares : Can be configured to follow redirects + * Martin Mares : Can be configured to follow redirects * if acting as a router _without_ a * routing protocol (RFC 1812). - * Martin Mares : Echo requests may be configured to + * Martin Mares : Echo requests may be configured to * be ignored (RFC 1812). - * Martin Mares : Limitation of ICMP error message + * Martin Mares : Limitation of ICMP error message * transmit rate (RFC 1812). - * Martin Mares : TOS and Precedence set correctly + * Martin Mares : TOS and Precedence set correctly * (RFC 1812). - * Martin Mares : Now copying as much data from the + * Martin Mares : Now copying as much data from the * original packet as we can without * exceeding 576 bytes (RFC 1812). * Willy Konynenberg : Transparent proxying support. - * Keith Owens : RFC1191 correction for 4.2BSD based + * Keith Owens : RFC1191 correction for 4.2BSD based * path MTU bug. * Thomas Quinot : ICMP Dest Unreach codes up to 15 are * valid (RFC 1812). @@ -76,7 +76,7 @@ * 3.2.2.5 (Parameter Problem) * SHOULD generate these (OK) * MUST pass received PARAMPROBLEM to transport layer (NOT YET) - * [Solaris 2.X seems to assert EPROTO when this occurs] -- AC + * [Solaris 2.X seems to assert EPROTO when this occurs] -- AC * 3.2.2.6 (Echo Request/Reply) * MUST reply to ECHO_REQUEST, and give app to do ECHO stuff (OK, OK) * MAY discard broadcast ECHO_REQUESTs. (We don't, but that's OK.) @@ -95,7 +95,7 @@ * MAY discard broadcast REQUESTs. (OK, but see source for inconsistency) * MUST reply using same source address as the request was sent to. (OK) * MUST reverse source route, as per ECHO (NOT YET) - * MUST pass REPLYs to transport/user layer (requires RAW, just like + * MUST pass REPLYs to transport/user layer (requires RAW, just like * ECHO) (OK) * MUST update clock for timestamp at least 15 times/sec (OK) * MUST be "correct within a few minutes" (OK) @@ -123,10 +123,10 @@ * MUST use one of addresses for the interface the orig. packet arrived as * source address (OK) * 4.3.2.5 (TOS and Precedence) - * SHOULD leave TOS set to the same value unless the packet would be + * SHOULD leave TOS set to the same value unless the packet would be * discarded for that reason (OK) * MUST use TOS=0 if not possible to leave original value (OK) - * MUST leave IP Precedence for Source Quench messages (OK -- not sent + * MUST leave IP Precedence for Source Quench messages (OK -- not sent * at all) * SHOULD use IP Precedence = 6 (Internetwork Control) or 7 (Network Control) * for all other error messages (OK, we use 6) @@ -153,7 +153,7 @@ * is enabled on the interface (OK -- ignores) * 4.3.3.3 (Source Quench) * SHOULD NOT originate SQ messages (OK) - * MUST be able to limit SQ rate if originates them (OK as we don't + * MUST be able to limit SQ rate if originates them (OK as we don't * send them) * MAY ignore SQ messages it receives (OK -- we don't) * 4.3.3.4 (Time Exceeded) @@ -183,18 +183,18 @@ * MUST reply using same source address as the request was sent to. (OK) * MUST use reversed Source Route if possible (NOT YET) * SHOULD update Record Route / Timestamp options (??) - * MUST pass REPLYs to transport/user layer (requires RAW, just like + * MUST pass REPLYs to transport/user layer (requires RAW, just like * ECHO) (OK) * MUST update clock for timestamp at least 16 times/sec (OK) * MUST be "correct within a few minutes" (OK) * 4.3.3.9 (Address Mask Request/Reply) - * MUST have support for receiving AMRq and responding with AMRe (OK, + * MUST have support for receiving AMRq and responding with AMRe (OK, * but only as a compile-time option) - * SHOULD have option for each interface for AMRe's, MUST default to + * SHOULD have option for each interface for AMRe's, MUST default to * NO (NOT YET) * MUST NOT reply to AMRq before knows the correct AM (OK) * MUST NOT respond to AMRq with source address 0.0.0.0 on physical - * interfaces having multiple logical i-faces with different masks + * interfaces having multiple logical i-faces with different masks * (NOT YET) * SHOULD examine all AMRe's it receives and check them (NOT YET) * SHOULD log invalid AMRe's (AM+sender) (NOT YET) @@ -267,7 +267,7 @@ /* * Statistics */ - + struct icmp_mib icmp_statistics; /* An array of errno for error messages from dest unreach. */ @@ -280,7 +280,7 @@ { ECONNREFUSED, 1 }, /* ICMP_PORT_UNREACH */ { EOPNOTSUPP, 0 }, /* ICMP_FRAG_NEEDED */ { EOPNOTSUPP, 0 }, /* ICMP_SR_FAILED */ - { ENETUNREACH, 1 }, /* ICMP_NET_UNKNOWN */ + { ENETUNREACH, 1 }, /* ICMP_NET_UNKNOWN */ { EHOSTDOWN, 1 }, /* ICMP_HOST_UNKNOWN */ { ENONET, 1 }, /* ICMP_HOST_ISOLATED */ { ENETUNREACH, 1 }, /* ICMP_NET_ANO */ @@ -295,7 +295,7 @@ /* * A spare long used to speed up statistics updating */ - + unsigned long dummy; /* @@ -329,7 +329,7 @@ /* * ICMP control array. This specifies what to do with each ICMP. */ - + struct icmp_control { unsigned long *output; /* Address to increment on output */ @@ -352,7 +352,7 @@ struct icmphdr icmph; unsigned long csum; struct options replyopts; - unsigned char optbuf[40]; + unsigned char optbuf[40]; }; /* @@ -360,7 +360,7 @@ * our ICMP output as well as maintain a clean interface throughout * all layers. All Socketless IP sends will soon be gone. */ - + struct socket icmp_socket; /* @@ -379,10 +379,10 @@ int type, entry; struct icmp_xrlim *xr; - for (type=0; type<=18; type++) { + for (type = 0; type <= 18; type++) { xr = icmp_pointers[type].xrlim; if (xr) { - for (entry=0; entrycache[entry].daddr = INADDR_NONE; } } @@ -392,7 +392,7 @@ * Check transmit rate limitation for given message. * * RFC 1812: 4.3.2.8 SHOULD be able to limit error message rate - * SHOULD allow setting of rate limits (we allow + * SHOULD allow setting of rate limits (we allow * in the source) */ @@ -408,7 +408,7 @@ if (!r) return 1; - for (c = r->cache; c < &r->cache[XRLIM_CACHE_SIZE]; c++) + for (c = r->cache; c < &r->cache[XRLIM_CACHE_SIZE]; c++) /* Cache lookup */ if (c->daddr == addr) break; @@ -464,19 +464,19 @@ /* * Maintain the counters used in the SNMP statistics for outgoing ICMP */ - + static void icmp_out_count(int type) { - if(type>18) + if (type > 18) return; (*icmp_pointers[type].output)++; icmp_statistics.IcmpOutMsgs++; } - + /* * Checksum each fragment, and on the first include the headers and final checksum. */ - + static void icmp_glue_bits(const void *p, __u32 saddr, char *to, unsigned int offset, unsigned int fraglen) { struct icmp_bxm *icmp_param = (struct icmp_bxm *)p; @@ -484,8 +484,11 @@ unsigned long csum; if (offset) { - icmp_param->csum=csum_partial_copy(icmp_param->data_ptr+offset-sizeof(struct icmphdr), - to, fraglen,icmp_param->csum); + icmp_param->csum = csum_partial_copy(icmp_param->data_ptr + + offset - + sizeof (struct icmphdr), + to, fraglen, + icmp_param->csum); return; } @@ -495,32 +498,31 @@ * for the whole packet here. */ csum = csum_partial_copy((void *)&icmp_param->icmph, - to, sizeof(struct icmphdr), - icmp_param->csum); + to, sizeof (struct icmphdr), + icmp_param->csum); csum = csum_partial_copy(icmp_param->data_ptr, - to+sizeof(struct icmphdr), - fraglen-sizeof(struct icmphdr), csum); - icmph=(struct icmphdr *)to; + to + sizeof (struct icmphdr), + fraglen - sizeof (struct icmphdr), csum); + icmph = (struct icmphdr *)to; icmph->checksum = csum_fold(csum); } - + /* * Driving logic for building and sending ICMP messages. */ static void icmp_build_xmit(struct icmp_bxm *icmp_param, __u32 saddr, __u32 daddr, __u8 tos) { - struct sock *sk=icmp_socket.data; - icmp_param->icmph.checksum=0; - icmp_param->csum=0; + struct sock *sk = icmp_socket.data; + icmp_param->icmph.checksum = 0; + icmp_param->csum = 0; icmp_out_count(icmp_param->icmph.type); sk->ip_tos = tos; - ip_build_xmit(sk, icmp_glue_bits, icmp_param, - icmp_param->data_len+sizeof(struct icmphdr), + ip_build_xmit(sk, icmp_glue_bits, icmp_param, + icmp_param->data_len + sizeof (struct icmphdr), daddr, saddr, &icmp_param->replyopts, 0, IPPROTO_ICMP, 1); } - /* * Send an ICMP message in response to a situation * @@ -531,61 +533,62 @@ * MUST reply to only the first fragment. */ -void icmp_send(struct sk_buff *skb_in, int type, int code, unsigned long info, struct device *dev) +void icmp_send(struct sk_buff *skb_in, int type, int code, unsigned long info, struct device *dev, int hdrincl) { struct iphdr *iph; struct icmphdr *icmph; int atype, room; struct icmp_bxm icmp_param; __u32 saddr; - + /* * Find the original header */ - + iph = skb_in->ip_hdr; - + /* * No replies to physical multicast/broadcast */ - - if(skb_in->pkt_type!=PACKET_HOST) + + if (skb_in->pkt_type!=PACKET_HOST) return; - + /* * Now check at the protocol level */ - - atype=ip_chk_addr(iph->daddr); - if(atype==IS_BROADCAST||atype==IS_MULTICAST) + + atype = ip_chk_addr(iph->daddr); + if (atype == IS_BROADCAST || atype == IS_MULTICAST) return; - + /* * Only reply to fragment 0. We byte re-order the constant * mask for efficiency. */ - - if(iph->frag_off&htons(IP_OFFSET)) + + if (iph->frag_off&htons(IP_OFFSET)) return; - - /* + + /* * If we send an ICMP error to an ICMP error a mess would result.. */ - - if(icmp_pointers[type].error) - { + + if (icmp_pointers[type].error) { /* - * We are an error, check if we are replying to an ICMP error + * We are an error, + * check if we are replying to an ICMP error */ - - if(iph->protocol==IPPROTO_ICMP) - { + + if (iph->protocol == IPPROTO_ICMP) { icmph = (struct icmphdr *)((char *)iph + (iph->ihl<<2)); /* - * Assume any unknown ICMP type is an error. This isn't - * specified by the RFC, but think about it.. + * Assume any unknown ICMP type is an error. + * This isn't specified by the RFC, + * but think about it.. */ - if(icmph->type>18 || icmp_pointers[icmph->type].error) + if (icmph->type > 18 || + icmp_pointers[icmph->type].error) return; } } @@ -597,203 +600,214 @@ #ifndef CONFIG_NO_ICMP_LIMIT if (!xrlim_allow(type, iph->saddr)) return; -#endif +#endif /* * Construct source address and options. */ - - saddr=iph->daddr; - if(saddr!=dev->pa_addr && ip_chk_addr(saddr)!=IS_MYADDR) - saddr=dev->pa_addr; - if(ip_options_echo(&icmp_param.replyopts, NULL, saddr, iph->saddr, skb_in)) + + saddr = iph->daddr; + if (saddr != dev->pa_addr && ip_chk_addr(saddr) != IS_MYADDR) + saddr = dev->pa_addr; + if (ip_options_echo(&icmp_param.replyopts, NULL, saddr, + iph->saddr, skb_in)) return; /* * Prepare data for ICMP header. */ - icmp_param.icmph.type=type; - icmp_param.icmph.code=code; + icmp_param.icmph.type = type; + icmp_param.icmph.code = code; icmp_param.icmph.un.gateway = info; - icmp_param.data_ptr=iph; - room = 576 - sizeof(struct iphdr) - icmp_param.replyopts.optlen; - icmp_param.data_len=(iph->ihl<<2)+skb_in->len; /* RFC says return as much as we can without exceeding 576 bytes */ + icmp_param.data_ptr = iph; + /* + * RFC says return as much as we can without exceeding 576 bytes + */ + room = 576 - sizeof (struct iphdr) - icmp_param.replyopts.optlen; + icmp_param.data_len = skb_in->len; + if (!hdrincl) + icmp_param.data_len += (iph->ihl << 2); if (icmp_param.data_len > room) icmp_param.data_len = room; - + /* * Build and send the packet. */ - icmp_build_xmit(&icmp_param, saddr, iph->saddr, - icmp_pointers[type].error ? + icmp_build_xmit(&icmp_param, saddr, iph->saddr, + icmp_pointers[type].error ? (iph->tos & 0x1E) | 0xC0 : iph->tos); } -/* - * Handle ICMP_DEST_UNREACH, ICMP_TIME_EXCEED, and ICMP_QUENCH. +/* + * Handle ICMP_DEST_UNREACH, ICMP_TIME_EXCEED, and ICMP_QUENCH. */ - + static void icmp_unreach(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev, __u32 saddr, __u32 daddr, int len) { struct iphdr *iph; int hash; struct inet_protocol *ipprot; - unsigned char *dp; - int match_addr=0; - - if(lenihl<<2; - if(len<0) + + iph = (struct iphdr *)(icmph + 1); + + len -= iph->ihl<<2; + if (len < 0) goto flush_it; - - dp= ((unsigned char *)iph)+(iph->ihl<<2); - - if(icmph->type==ICMP_DEST_UNREACH) - { - switch(icmph->code & 15) - { - case ICMP_NET_UNREACH: - break; - case ICMP_HOST_UNREACH: - break; - case ICMP_PROT_UNREACH: - NETDEBUG(printk(KERN_INFO "ICMP: %s:%d: protocol unreachable.\n", - in_ntoa(iph->daddr), (int)iph->protocol)); + + dp = ((unsigned char *)iph) + (iph->ihl << 2); + + if (icmph->type == ICMP_DEST_UNREACH) { + switch (icmph->code & 15) { + case ICMP_NET_UNREACH: + break; + case ICMP_HOST_UNREACH: + break; + case ICMP_PROT_UNREACH: + NETDEBUG(printk(KERN_INFO + "ICMP: %s:%d: protocol unreachable.\n", + in_ntoa(iph->daddr), + (int)iph->protocol)); /* Drop through */ - case ICMP_PORT_UNREACH: - match_addr=1; - break; - case ICMP_FRAG_NEEDED: + case ICMP_PORT_UNREACH: + match_addr = 1; + break; + case ICMP_FRAG_NEEDED: #ifdef CONFIG_NO_PATH_MTU_DISCOVERY - NETDEBUG(printk(KERN_INFO "ICMP: %s: fragmentation needed and DF set.\n", - in_ntoa(iph->daddr))); - break; + NETDEBUG(printk(KERN_INFO + "ICMP: %s: fragmentation needed and DF set.\n", + in_ntoa(iph->daddr))); + break; #else - { - unsigned short old_mtu = ntohs(iph->tot_len); - unsigned short new_mtu = ntohs(icmph->un.echo.sequence); + { + unsigned short old_mtu = ntohs(iph->tot_len); + unsigned short new_mtu = ntohs(icmph->un.echo.sequence); + /* + * RFC1191 5. 4.2BSD based router can return incorrect + * Total Length. If current mtu is unknown or old_mtu + * is not less than current mtu, reduce old_mtu by + * 4 times the header length. + */ + + if (skb->sk == NULL || /* can this happen? */ + skb->sk->ip_route_cache == NULL || + skb->sk->ip_route_cache->rt_mtu <= old_mtu) { + NETDEBUG(printk(KERN_INFO + "4.2BSD based fragmenting router between here and %s, mtu corrected from %d", + in_ntoa(iph->daddr), old_mtu)); + old_mtu -= 4 * iph->ihl; + NETDEBUG(printk(" to %d\n", old_mtu)); + } + + if (new_mtu < 68 || new_mtu >= old_mtu) { /* - * RFC1191 5. 4.2BSD based router can return incorrect - * Total Length. If current mtu is unknown or old_mtu - * is not less than current mtu, reduce old_mtu by 4 times - * the header length. + * It is either dumb router, which does not + * understand Path MTU Disc. protocol + * or broken (f.e. Linux<=1.3.37 8) router. + * Try to guess... + * The table is taken from RFC-1191. */ - - if (skb->sk == NULL /* can this happen? */ - || skb->sk->ip_route_cache == NULL - || skb->sk->ip_route_cache->rt_mtu <= old_mtu) - { - NETDEBUG(printk(KERN_INFO "4.2BSD based fragmenting router between here and %s, mtu corrected from %d", in_ntoa(iph->daddr), old_mtu)); - old_mtu -= 4 * iph->ihl; - NETDEBUG(printk(" to %d\n", old_mtu)); - } - - if (new_mtu < 68 || new_mtu >= old_mtu) - { - /* - * It is either dumb router, which does not - * understand Path MTU Disc. protocol - * or broken (f.e. Linux<=1.3.37 8) router. - * Try to guess... - * The table is taken from RFC-1191. - */ - if (old_mtu > 32000) - new_mtu = 32000; - else if (old_mtu > 17914) - new_mtu = 17914; - else if (old_mtu > 8166) - new_mtu = 8166; - else if (old_mtu > 4352) - new_mtu = 4352; - else if (old_mtu > 2002) - new_mtu = 2002; - else if (old_mtu > 1492) - new_mtu = 1492; - else if (old_mtu > 576) - new_mtu = 576; - else if (old_mtu > 296) - new_mtu = 296; - /* - * These two are not from the RFC but - * are needed for AMPRnet AX.25 paths. - */ - else if (old_mtu > 216) - new_mtu = 216; - else if (old_mtu > 128) - new_mtu = 128; - else - /* - * Despair.. - */ - new_mtu = 68; - } + if (old_mtu > 32000) + new_mtu = 32000; + else if (old_mtu > 17914) + new_mtu = 17914; + else if (old_mtu > 8166) + new_mtu = 8166; + else if (old_mtu > 4352) + new_mtu = 4352; + else if (old_mtu > 2002) + new_mtu = 2002; + else if (old_mtu > 1492) + new_mtu = 1492; + else if (old_mtu > 576) + new_mtu = 576; + else if (old_mtu > 296) + new_mtu = 296; /* - * Ugly trick to pass MTU to protocol layer. - * Really we should add argument "info" to error handler. + * These two are not from the RFC but + * are needed for AMPRnet AX.25 paths. */ - iph->id = htons(new_mtu); - break; + else if (old_mtu > 216) + new_mtu = 216; + else if (old_mtu > 128) + new_mtu = 128; + else + /* + * Despair.. + */ + new_mtu = 68; } + /* + * Ugly trick to pass MTU to protocol layer. + * Really we should add argument "info" to error handler. + */ + iph->id = htons(new_mtu); + break; + } #endif - case ICMP_SR_FAILED: - NETDEBUG(printk(KERN_INFO "ICMP: %s: Source Route Failed.\n", in_ntoa(iph->daddr))); - break; - default: - break; + case ICMP_SR_FAILED: + NETDEBUG(printk(KERN_INFO + "ICMP: %s: Source Route Failed.\n", + in_ntoa(iph->daddr))); + break; + default: + break; } - if(icmph->code>NR_ICMP_UNREACH) /* Invalid type */ + if (icmph->code > NR_ICMP_UNREACH) /* Invalid type */ goto flush_it; } - + /* * Throw it at our lower layers * - * RFC 1122: 3.2.2 MUST extract the protocol ID from the passed header. - * RFC 1122: 3.2.2.1 MUST pass ICMP unreach messages to the transport layer. - * RFC 1122: 3.2.2.2 MUST pass ICMP time expired messages to transport layer. + * RFC 1122: 3.2.2 MUST extract the protocol ID from the passed + * header. + * RFC 1122: 3.2.2.1 MUST pass ICMP unreach messages to the + * transport layer. + * RFC 1122: 3.2.2.2 MUST pass ICMP time expired messages to + * transport layer. * * Rule: Require port unreachable and protocol unreachable come * from the host in question. Stop junk spoofs. */ - - if(!match_addr || saddr == iph->daddr) - { + + if (!match_addr || saddr == iph->daddr) { /* - * Get the protocol(s). + * Get the protocol(s). */ - + hash = iph->protocol & (MAX_INET_PROTOS -1); /* - * This can't change while we are doing it. + * This can't change while we are doing it. */ - - ipprot = (struct inet_protocol *) inet_protos[hash]; - while(ipprot != NULL) - { + + ipprot = (struct inet_protocol *)inet_protos[hash]; + while (ipprot != NULL) { struct inet_protocol *nextip; - + nextip = (struct inet_protocol *) ipprot->next; - - /* - * Pass it off to everyone who wants it. + + /* + * Pass it off to everyone who wants it. */ - + /* RFC1122: OK. Passes appropriate ICMP errors to the */ /* appropriate protocol layer (MUST), as per 3.2.2. */ - - if (iph->protocol == ipprot->protocol && ipprot->err_handler) - { - ipprot->err_handler(icmph->type, icmph->code, dp, - iph->daddr, iph->saddr, ipprot, len); + + if (iph->protocol == ipprot->protocol && + ipprot->err_handler) { + ipprot->err_handler(icmph->type, icmph->code, + dp, iph->daddr, iph->saddr, + ipprot, len); } ipprot = nextip; @@ -803,9 +817,8 @@ kfree_skb(skb, FREE_READ); } - /* - * Handle ICMP_REDIRECT. + * Handle ICMP_REDIRECT. */ static void icmp_redirect(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev, __u32 source, __u32 daddr, int len) @@ -816,122 +829,128 @@ /* * Get the copied header of the packet that caused the redirect */ - - if(len<=sizeof(struct iphdr)) + + if (len <= sizeof (struct iphdr)) goto flush_it; - - iph = (struct iphdr *) (icmph + 1); + + iph = (struct iphdr *)(icmph + 1); ip = iph->daddr; /* - * If we are a router and we run a routing protocol, we MUST NOT follow redirects. - * When using no routing protocol, we MAY follow redirects. (RFC 1812, 5.2.7.2) + * If we are a router and we run a routing protocol, we MUST NOT + * follow redirects. + * When using no routing protocol, we MAY follow redirects. (RFC + * 1812, 5.2.7.2) */ #if !defined(CONFIG_IP_DUMB_ROUTER) if (sysctl_ip_forward) { - NETDEBUG(printk(KERN_INFO "icmp: ICMP redirect ignored. dest = %lX, " - "orig gw = %lX, \"new\" gw = %lX, device = %s.\n", ntohl(ip), - ntohl(source), ntohl(icmph->un.gateway), dev->name)); + NETDEBUG(printk(KERN_INFO + "icmp: ICMP redirect ignored. dest = %lX, " + "orig gw = %lX, \"new\" gw = %lX, device = %s.\n", + ntohl(ip), ntohl(source), + ntohl(icmph->un.gateway), dev->name)); goto flush_it; } #endif - switch(icmph->code & 7) - { - case ICMP_REDIR_NET: - /* - * This causes a problem with subnetted networks. What we should do - * is use ICMP_ADDRESS to get the subnet mask of the problem route - * and set both. But we don't.. [RFC1812 says routers MUST NOT - * generate Network Redirects] - */ + switch (icmph->code & 7) { + case ICMP_REDIR_NET: + /* + * This causes a problem with subnetted networks. What we + * should do is use ICMP_ADDRESS to get the subnet mask of + * the problem route and set both. But we don't.. [RFC1812 + * says routers MUST NOT generate Network Redirects] + */ #ifdef not_a_good_idea - ip_rt_add((RTF_DYNAMIC | RTF_MODIFIED | RTF_GATEWAY), - ip, 0, icmph->un.gateway, dev,0, 0, 0); + ip_rt_add((RTF_DYNAMIC | RTF_MODIFIED | RTF_GATEWAY), + ip, 0, icmph->un.gateway, dev, 0, 0, 0); #endif - /* - * As per RFC recommendations now handle it as - * a host redirect. - */ - - case ICMP_REDIR_HOST: - /* - * Add better route to host. - * But first check that the redirect - * comes from the old gateway.. - * And make sure it's an ok host address - * (not some confused thing sending our - * address) - */ - NETDEBUG(printk(KERN_INFO "ICMP redirect from %s\n", in_ntoa(source))); - ip_rt_redirect(source, ip, icmph->un.gateway, dev); - break; - case ICMP_REDIR_NETTOS: - case ICMP_REDIR_HOSTTOS: - NETDEBUG(printk(KERN_INFO "ICMP: cannot handle TOS redirects yet!\n")); - break; - default: - break; - } + /* + * As per RFC recommendations now handle it as + * a host redirect. + */ + + case ICMP_REDIR_HOST: + /* + * Add better route to host. But first check that the + * redirect comes from the old gateway.. And make sure + * it's an ok host address (not some confused thing + * sending our address) + */ + NETDEBUG(printk(KERN_INFO + "ICMP redirect from %s\n", in_ntoa(source))); + ip_rt_redirect(source, ip, icmph->un.gateway, dev); + break; + case ICMP_REDIR_NETTOS: + case ICMP_REDIR_HOSTTOS: + NETDEBUG(printk(KERN_INFO + "ICMP: cannot handle TOS redirects yet!\n")); + break; + default: + break; + } - /* - * Discard the original packet - */ + /* + * Discard the original packet + */ flush_it: - kfree_skb(skb, FREE_READ); + kfree_skb(skb, FREE_READ); } /* - * Handle ICMP_ECHO ("ping") requests. + * Handle ICMP_ECHO ("ping") requests. * - * RFC 1122: 3.2.2.6 MUST have an echo server that answers ICMP echo requests. - * RFC 1122: 3.2.2.6 Data received in the ICMP_ECHO request MUST be included in the reply. - * RFC 1812: 4.3.3.6 SHOULD have a config option for silently ignoring echo requests, MUST have default=NOT. + * RFC 1122: 3.2.2.6 MUST have an echo server that answers ICMP echo + * requests. + * RFC 1122: 3.2.2.6 Data received in the ICMP_ECHO request MUST be + * included in the reply. + * RFC 1812: 4.3.3.6 SHOULD have a config option for silently ignoring + * echo requests, MUST have default=NOT. * See also WRT handling of options once they are done and working. */ - + static void icmp_echo(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev, __u32 saddr, __u32 daddr, int len) { #ifndef CONFIG_IP_IGNORE_ECHO_REQUESTS struct icmp_bxm icmp_param; - icmp_param.icmph=*icmph; - icmp_param.icmph.type=ICMP_ECHOREPLY; - icmp_param.data_ptr=(icmph+1); - icmp_param.data_len=len; - if (ip_options_echo(&icmp_param.replyopts, NULL, daddr, saddr, skb)==0) + icmp_param.icmph = *icmph; + icmp_param.icmph.type = ICMP_ECHOREPLY; + icmp_param.data_ptr = (icmph + 1); + icmp_param.data_len = len; + if (ip_options_echo(&icmp_param.replyopts, + NULL, daddr, saddr, skb) == 0) icmp_build_xmit(&icmp_param, daddr, saddr, skb->ip_hdr->tos); #endif kfree_skb(skb, FREE_READ); } /* - * Handle ICMP Timestamp requests. + * Handle ICMP Timestamp requests. * RFC 1122: 3.2.2.8 MAY implement ICMP timestamp requests. * SHOULD be in the kernel for minimum random latency. * MUST be accurate to a few minutes. * MUST be updated at least at 15Hz. */ - + static void icmp_timestamp(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev, __u32 saddr, __u32 daddr, int len) { __u32 times[3]; /* So the new timestamp works on ALPHA's.. */ struct icmp_bxm icmp_param; - + /* * Too short. */ - - if(len<12) - { + + if (len < 12) { icmp_statistics.IcmpInErrors++; kfree_skb(skb, FREE_READ); return; } - + /* - * Fill in the current time as ms since midnight UT: + * Fill in the current time as ms since midnight UT: */ - + { struct timeval tv; do_gettimeofday(&tv); @@ -939,43 +958,44 @@ } times[2] = times[1]; memcpy((void *)×[0], icmph+1, 4); /* Incoming stamp */ - icmp_param.icmph=*icmph; - icmp_param.icmph.type=ICMP_TIMESTAMPREPLY; - icmp_param.icmph.code=0; - icmp_param.data_ptr=× - icmp_param.data_len=12; - if (ip_options_echo(&icmp_param.replyopts, NULL, daddr, saddr, skb)==0) + icmp_param.icmph = *icmph; + icmp_param.icmph.type = ICMP_TIMESTAMPREPLY; + icmp_param.icmph.code = 0; + icmp_param.data_ptr = × + icmp_param.data_len = 12; + if (ip_options_echo(&icmp_param.replyopts, + NULL, daddr, saddr, skb) == 0) icmp_build_xmit(&icmp_param, daddr, saddr, skb->ip_hdr->tos); kfree_skb(skb,FREE_READ); } - -/* +/* * Handle ICMP_ADDRESS_MASK requests. (RFC950) * - * RFC1122 (3.2.2.9). A host MUST only send replies to - * ADDRESS_MASK requests if it's been configured as an address mask - * agent. Receiving a request doesn't constitute implicit permission to - * act as one. Of course, implementing this correctly requires (SHOULD) - * a way to turn the functionality on and off. Another one for sysctl(), - * I guess. -- MS - * Botched with a CONFIG option for now - Linus add scts sysctl please.. + * RFC1122 (3.2.2.9). A host MUST only send replies to + * ADDRESS_MASK requests if it's been configured as an address mask + * agent. Receiving a request doesn't constitute implicit permission to + * act as one. Of course, implementing this correctly requires (SHOULD) + * a way to turn the functionality on and off. Another one for sysctl(), + * I guess. -- MS + * Botched with a CONFIG option for now - Linus add scts sysctl please.. */ - + static void icmp_address(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev, __u32 saddr, __u32 daddr, int len) { #ifdef CONFIG_IP_ADDR_AGENT /* Don't use, broken */ struct icmp_bxm icmp_param; - icmp_param.icmph.type=ICMP_ADDRESSREPLY; - icmp_param.icmph.code=0; + icmp_param.icmph.type = ICMP_ADDRESSREPLY; + icmp_param.icmph.code = 0; icmp_param.icmph.un.echo.id = icmph->un.echo.id; icmp_param.icmph.un.echo.sequence = icmph->un.echo.sequence; - icmp_param.data_ptr=&dev->pa_mask; - icmp_param.data_len=4; - if (ip_options_echo(&icmp_param.replyopts, NULL, daddr, saddr, skb)==0) + icmp_param.data_ptr = &dev->pa_mask; + icmp_param.data_len = 4; + if (ip_options_echo(&icmp_param.replyopts, + NULL, daddr, saddr, skb) == 0) icmp_build_xmit(&icmp_param, daddr, saddr, skb->iph->tos); -#endif - kfree_skb(skb, FREE_READ); +#endif + kfree_skb(skb, FREE_READ); } static void icmp_discard(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev, __u32 saddr, __u32 daddr, int len) @@ -999,52 +1019,63 @@ int icmp_chkaddr(struct sk_buff *skb) { - struct icmphdr *icmph=(struct icmphdr *)(skb->h.raw + skb->h.iph->ihl*4); - struct iphdr *iph = (struct iphdr *) (icmph + 1); - void (*handler)(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev, __u32 saddr, __u32 daddr, int len) = icmp_pointers[icmph->type].handler; + struct icmphdr *icmph = (struct icmphdr *)(skb->h.raw + + skb->h.iph->ihl * 4); + struct iphdr *iph = (struct iphdr *)(icmph + 1); + void (*handler)(struct icmphdr *icmph, struct sk_buff *skb, + struct device *dev, __u32 saddr, __u32 daddr, + int len) = icmp_pointers[icmph->type].handler; if (handler == icmp_unreach || handler == icmp_redirect) { struct sock *sk; switch (iph->protocol) { case IPPROTO_TCP: - { - struct tcphdr *th = (struct tcphdr *)(((unsigned char *)iph)+(iph->ihl<<2)); + { + struct tcphdr *th = (struct tcphdr *)(((unsigned char *)iph) + (iph->ihl << 2)); - sk = tcp_v4_lookup(iph->daddr, th->dest, iph->saddr, th->source, skb->dev); - if (!sk) return 0; - if (sk->saddr != iph->saddr) return 0; - if (sk->daddr != iph->daddr) return 0; - if (sk->dummy_th.dest != th->dest) return 0; + sk = tcp_v4_lookup(iph->daddr, th->dest, iph->saddr, + th->source, skb->dev); + if (!sk) + return 0; + if (sk->saddr != iph->saddr) + return 0; + if (sk->daddr != iph->daddr) + return 0; + if (sk->dummy_th.dest != th->dest) + return 0; /* * This packet came from us. */ return 1; - } + } case IPPROTO_UDP: - { - struct udphdr *uh = (struct udphdr *)(((unsigned char *)iph)+(iph->ihl<<2)); + { + struct udphdr *uh = (struct udphdr *)(((unsigned char *)iph) + (iph->ihl << 2)); - sk = udp_v4_lookup(iph->daddr, uh->dest, iph->saddr, uh->source, skb->dev); - if (!sk) return 0; - if (sk->saddr != iph->saddr && ip_chk_addr(iph->saddr) != IS_MYADDR) + sk = udp_v4_lookup(iph->daddr, uh->dest, iph->saddr, + uh->source, skb->dev); + if (!sk) + return 0; + if (sk->saddr != iph->saddr && + ip_chk_addr(iph->saddr) != IS_MYADDR) return 0; /* * This packet may have come from us. * Assume it did. */ return 1; - } + } } } return 0; } #endif -/* - * Deal with incoming ICMP packets. +/* + * Deal with incoming ICMP packets. */ - + int icmp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt, __u32 daddr, unsigned short len, __u32 saddr, int redo, struct inet_protocol *protocol) @@ -1054,43 +1085,43 @@ int r; #endif icmp_statistics.IcmpInMsgs++; - - if(len < sizeof(struct icmphdr)) - { + + if (len < sizeof (struct icmphdr)) { icmp_statistics.IcmpInErrors++; NETDEBUG(printk(KERN_INFO "ICMP: runt packet\n")); kfree_skb(skb, FREE_READ); return 0; } - - /* + + /* * Validate the packet - */ - - if (ip_compute_csum((unsigned char *) icmph, len)) - { + */ + + if (ip_compute_csum((unsigned char *)icmph, len)) { /* Failed checksum! */ icmp_statistics.IcmpInErrors++; - NETDEBUG(printk(KERN_INFO "ICMP: failed checksum from %s!\n", in_ntoa(saddr))); + NETDEBUG(printk(KERN_INFO + "ICMP: failed checksum from %s!\n", + in_ntoa(saddr))); kfree_skb(skb, FREE_READ); - return(0); + return 0; } - + /* * 18 is the highest 'known' ICMP type. Anything else is a mystery * - * RFC 1122: 3.2.2 Unknown ICMP messages types MUST be silently discarded. + * RFC 1122: 3.2.2 Unknown ICMP messages types MUST be silently + * discarded. */ - - if(icmph->type > 18) - { + + if (icmph->type > 18) { icmp_statistics.IcmpInErrors++; /* Is this right - or do we ignore ? */ kfree_skb(skb,FREE_READ); - return(0); + return 0; } - + /* - * Parse the ICMP message + * Parse the ICMP message */ #ifdef CONFIG_IP_TRANSPARENT_PROXY @@ -1099,38 +1130,41 @@ * locally, due to transparent proxying. * Thus, narrow down the test to what is really meant. */ - if (daddr!=dev->pa_addr && ((r = ip_chk_addr(daddr)) == IS_BROADCAST || r == IS_MULTICAST)) + if (daddr != dev->pa_addr && + ((r = ip_chk_addr(daddr)) == IS_BROADCAST || r == IS_MULTICAST)) { #else - if (daddr!=dev->pa_addr && ip_chk_addr(daddr) != IS_MYADDR) + if (daddr != dev->pa_addr && ip_chk_addr(daddr) != IS_MYADDR) { #endif - { /* - * RFC 1122: 3.2.2.6 An ICMP_ECHO to broadcast MAY be silently ignored (we don't as it is used - * by some network mapping tools). - * RFC 1122: 3.2.2.8 An ICMP_TIMESTAMP MAY be silently discarded if to broadcast/multicast. + * RFC 1122: 3.2.2.6 An ICMP_ECHO to broadcast MAY be + * silently ignored (we don't as it is used by some + * network mapping tools). + * RFC 1122: 3.2.2.8 An ICMP_TIMESTAMP MAY be silently + * discarded if to broadcast/multicast. */ - if (icmph->type != ICMP_ECHO) - { + if (icmph->type != ICMP_ECHO) { icmp_statistics.IcmpInErrors++; kfree_skb(skb, FREE_READ); - return(0); - } - /* - * Reply the multicast/broadcast using a legal - * interface - in this case the device we got - * it from. - */ - daddr=dev->pa_addr; + return 0; + } + /* + * Reply the multicast/broadcast using a legal + * interface - in this case the device we got + * it from. + */ + daddr = dev->pa_addr; } - - len-=sizeof(struct icmphdr); + + len -= sizeof (struct icmphdr); (*icmp_pointers[icmph->type].input)++; - (icmp_pointers[icmph->type].handler)(icmph,skb,skb->dev,saddr,daddr,len); + (icmp_pointers[icmph->type].handler)(icmph, skb, skb->dev, saddr, + daddr, len); return 0; } /* - * This table defined limits of ICMP sending rate for various ICMP messages. + * This table defined limits of ICMP sending rate for various ICMP + * messages. */ static struct icmp_xrlim @@ -1141,7 +1175,7 @@ /* * This table is the definition of how we handle ICMP. */ - + static struct icmp_control icmp_pointers[19] = { /* ECHO REPLY (0) */ { &icmp_statistics.IcmpOutEchoReps, &icmp_statistics.IcmpInEchoReps, icmp_discard, 0, NULL }, @@ -1182,15 +1216,14 @@ { struct sock *sk; int err; - icmp_socket.type=SOCK_RAW; - icmp_socket.ops=ops; - if((err=ops->create(&icmp_socket, IPPROTO_ICMP))<0) + icmp_socket.type = SOCK_RAW; + icmp_socket.ops = ops; + if ((err = ops->create(&icmp_socket, IPPROTO_ICMP)) < 0) panic("Failed to create the ICMP control socket.\n"); - sk=icmp_socket.data; - sk->allocation=GFP_ATOMIC; + sk = icmp_socket.data; + sk->allocation = GFP_ATOMIC; sk->num = 256; /* Don't receive any data */ #ifndef CONFIG_NO_ICMP_LIMIT xrlim_init(); #endif } - diff -urN linux-2.0.40-rc6/net/ipv4/ip_forward.c linux-2.0.40-rc7/net/ipv4/ip_forward.c --- linux-2.0.40-rc6/net/ipv4/ip_forward.c 1998-06-03 15:17:50.000000000 -0700 +++ linux-2.0.40-rc7/net/ipv4/ip_forward.c 2004-01-15 07:19:51.000000000 -0800 @@ -4,13 +4,13 @@ * interface as the means of communication with the user level. * * The IP forwarding functionality. - * + * * Authors: see ip.c * * Fixes: - * Many : Split from ip.c , see ip_input.c for + * Many : Split from ip.c , see ip_input.c for * history. - * Dave Gregorich : NULL ip_rt_put fix for multicast + * Dave Gregorich : NULL ip_rt_put fix for multicast * routing. * Jos Vos : Add call_out_firewall before sending, * use output device for accounting. @@ -42,19 +42,18 @@ #include #ifdef CONFIG_IP_FORWARD /* set the default */ -int sysctl_ip_forward = 1; +int sysctl_ip_forward = 1; #else -int sysctl_ip_forward = 0; +int sysctl_ip_forward = 0; #endif #ifdef CONFIG_IP_MROUTE - /* - * Encapsulate a packet by attaching a valid IPIP header to it. + * Encapsulate a packet by attaching a valid IPIP header to it. * This avoids tunnel drivers and other mess and gives us the speed so * important for multicast video. */ - + static void ip_encap(struct sk_buff *skb, int len, struct device *out, __u32 daddr) { /* @@ -62,46 +61,46 @@ * * Firstly push down and install the IPIP header. */ - struct iphdr *iph=(struct iphdr *)skb_push(skb,sizeof(struct iphdr)); - - if(len>65515) - len=65515; + struct iphdr *iph = (struct iphdr *)skb_push(skb, + sizeof (struct iphdr)); + if (len > 65515) + len = 65515; - iph->version = 4; - iph->tos = skb->ip_hdr->tos; - iph->ttl = skb->ip_hdr->ttl; - iph->frag_off = 0; - iph->daddr = daddr; - iph->saddr = out->pa_addr; - iph->protocol = IPPROTO_IPIP; - iph->ihl = 5; - iph->tot_len = htons(skb->len + len); /* Anand, ernet */ - iph->id = htons(ip_id_count++); + iph->version = 4; + iph->tos = skb->ip_hdr->tos; + iph->ttl = skb->ip_hdr->ttl; + iph->frag_off = 0; + iph->daddr = daddr; + iph->saddr = out->pa_addr; + iph->protocol = IPPROTO_IPIP; + iph->ihl = 5; + iph->tot_len = htons(skb->len + len); /* Anand, ernet */ + iph->id = htons(ip_id_count++); ip_send_check(iph); skb->dev = out; skb->arp = 1; - skb->raddr=daddr; /* Router address is not destination address. The - * correct value is given eventually. I have not - * removed this statement. But could have. - * Anand, ernet. - */ + skb->raddr = daddr; /* Router address is not destination address. + * The correct value is given eventually. I + * have not removed this statement. But could + * have. Anand, ernet. + */ /* * Now add the physical header (driver will push it down). */ /* The last parameter of out->hard_header() needed skb->len + len. - * Anand, ernet. + * Anand, ernet. */ - if (out->hard_header && out->hard_header(skb, out, ETH_P_IP, NULL, NULL, - skb->len + len)<0) - skb->arp=0; + if (out->hard_header && + out->hard_header(skb, out, ETH_P_IP, NULL, NULL, + skb->len + len) < 0) + skb->arp = 0; /* * Read to queue for transmission. */ } - #endif /* @@ -121,16 +120,16 @@ struct hh_cache *hh = NULL; int encap = 0; /* Encap length */ #ifdef CONFIG_FIREWALL - int fw_res = 0; /* Forwarding result */ -#ifdef CONFIG_IP_MASQUERADE + int fw_res = 0; /* Forwarding result */ +#ifdef CONFIG_IP_MASQUERADE struct sk_buff *skb_in = skb; /* So we can remember if the masquerader did some swaps */ #endif /* CONFIG_IP_MASQUERADE */ #endif /* CONFIG_FIREWALL */ - + /* * According to the RFC, we must first decrease the TTL field. If - * that reaches zero, we must reply an ICMP control message telling - * that the packet's lifetime expired. + * that reaches zero, we must reply an ICMP control message + * telling that the packet's lifetime expired. * * Exception: * We may not generate an ICMP for an ICMP. icmp_send does the @@ -139,8 +138,7 @@ */ iph = skb->h.iph; - if (!(is_frag&IPFWD_NOTTLDEC)) - { + if (!(is_frag&IPFWD_NOTTLDEC)) { unsigned long checksum = iph->check; iph->ttl--; @@ -156,41 +154,39 @@ iph->check = checksum; } - if (iph->ttl <= 0) - { + if (iph->ttl <= 0) { /* Tell the sender its packet died... */ - icmp_send(skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0, dev); + icmp_send(skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0, dev, 1); return -1; } /* If IPFWD_MULTITUNNEL flag is set, then we have to perform routing * decision so as to reach the other end of the tunnel. This condition - * also means that we are dealing with a unicast IP packet "in a way". + * also means that we are dealing with a unicast IP packet "in a way". * Anand, ernet. */ #ifdef CONFIG_IP_MROUTE - if(!(is_frag&IPFWD_MULTICASTING) || (is_frag&IPFWD_MULTITUNNEL)) - { -#endif + if (!(is_frag & IPFWD_MULTICASTING) || (is_frag & IPFWD_MULTITUNNEL)) { +#endif /* - * OK, the packet is still valid. Fetch its destination address, - * and give it to the IP sender for further processing. + * OK, the packet is still valid. Fetch its destination + * address, and give it to the IP sender for further + * processing. */ rt = ip_rt_route(target_addr, 0, NULL); - if (rt == NULL) - { + if (rt == NULL) { /* * Tell the sender its packet cannot be delivered. Again * ICMP is screened later. */ - icmp_send(skb, ICMP_DEST_UNREACH, ICMP_NET_UNREACH, 0, dev); + icmp_send(skb, ICMP_DEST_UNREACH, ICMP_NET_UNREACH, + 0, dev, 1); return -1; } - - + /* * Gosh. Not only is the packet valid; we even know how to * forward it onto its final destination. Can we say this @@ -200,14 +196,15 @@ */ raddr = rt->rt_gateway; - + if (opt->is_strictroute && (rt->rt_flags & RTF_GATEWAY)) { /* * Strict routing permits no gatewaying */ - + ip_rt_put(rt); - icmp_send(skb, ICMP_DEST_UNREACH, ICMP_SR_FAILED, 0, dev); + icmp_send(skb, ICMP_DEST_UNREACH, ICMP_SR_FAILED, + 0, dev, 1); return -1; } @@ -219,66 +216,61 @@ dev2 = rt->rt_dev; hh = rt->rt_hh; /* - * In IP you never have to forward a frame on the interface that it - * arrived upon. We now generate an ICMP HOST REDIRECT giving the route - * we calculated. + * In IP you never have to forward a frame on the + * interface that it arrived upon. We now generate an ICMP + * HOST REDIRECT giving the route we calculated. */ #ifndef CONFIG_IP_NO_ICMP_REDIRECT - if (dev == dev2 && - !((iph->saddr^dev->pa_addr)&dev->pa_mask) && - /* The daddr!=raddr test isn't obvious - what it's doing - is avoiding sending a frame the receiver will not - believe anyway.. */ - iph->daddr != raddr/*ANK*/ && !opt->srr) - icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, raddr, dev); + /* The daddr != raddr test isn't obvious - what it's doing is + * avoiding sending a frame the receiver will not believe + * anyway.. + */ + if (dev == dev2 && + !((iph->saddr ^ dev->pa_addr) & dev->pa_mask) && + iph->daddr != raddr && !opt->srr) + icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, + raddr, dev, 1); #endif #ifdef CONFIG_IP_MROUTE - /* This is for ip encap. Anand, ernet.*/ + /* This is for ip encap. Anand, ernet. */ - if (is_frag&IPFWD_MULTITUNNEL) - { - encap=20; + if (is_frag & IPFWD_MULTITUNNEL) { + encap = 20; } - } - else - { + } else { /* * Multicast route forward. Routing is already done */ - dev2=skb->dev; - raddr=skb->raddr; - if(is_frag&IPFWD_MULTITUNNEL) /* VIFF_TUNNEL mode */ - encap=20; - rt=NULL; + dev2 = skb->dev; + raddr = skb->raddr; + if (is_frag & IPFWD_MULTITUNNEL) /* VIFF_TUNNEL mode */ + encap = 20; + rt = NULL; } -#endif - - /* +#endif + + /* * See if we are allowed to forward this. - * Note: demasqueraded fragments are always 'back'warded. + * Note: demasqueraded fragments are always 'back'warded. */ - + #ifdef CONFIG_FIREWALL - if(!(is_frag&IPFWD_MASQUERADED)) - { + if (!(is_frag & IPFWD_MASQUERADED)) { #ifdef CONFIG_IP_MASQUERADE - /* - * Check that any ICMP packets are not for a + /* + * Check that any ICMP packets are not for a * masqueraded connection. If so rewrite them * and skip the firewall checks */ - if (iph->protocol == IPPROTO_ICMP) - { + if (iph->protocol == IPPROTO_ICMP) { #ifdef CONFIG_IP_MASQUERADE_ICMP -#define icmph ((struct icmphdr *)((char *)iph + (iph->ihl<<2))) - if ((icmph->type==ICMP_DEST_UNREACH)|| - (icmph->type==ICMP_SOURCE_QUENCH)|| - (icmph->type==ICMP_TIME_EXCEEDED)) - { +#define icmph ((struct icmphdr *)((char *)iph + (iph->ihl << 2))) + if ((icmph->type == ICMP_DEST_UNREACH) || + (icmph->type == ICMP_SOURCE_QUENCH) || + (icmph->type == ICMP_TIME_EXCEEDED)) { #endif - if ((fw_res = ip_fw_masq_icmp(&skb, dev2)) < 0) - { + if ((fw_res = ip_fw_masq_icmp(&skb, dev2)) < 0) { if (rt) ip_rt_put(rt); /* Problem - ie bad checksum */ @@ -290,16 +282,17 @@ goto skip_call_fw_firewall; #ifdef CONFIG_IP_MASQUERADE_ICMP } -#endif +#endif } #endif - fw_res=call_fw_firewall(PF_INET, dev2, iph, NULL); + fw_res = call_fw_firewall(PF_INET, dev2, iph, NULL); switch (fw_res) { case FW_ACCEPT: case FW_MASQUERADE: break; case FW_REJECT: - icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0, dev); + icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, + 0, dev, 1); /* fall thru */ default: if (rt) @@ -308,8 +301,8 @@ } #ifdef CONFIG_IP_MASQUERADE - skip_call_fw_firewall: -#endif +skip_call_fw_firewall: +#endif } #endif @@ -318,17 +311,15 @@ * If the indicated interface is up and running, kick it. */ - if (dev2->flags & IFF_UP) - { + if (dev2->flags & IFF_UP) { #ifdef CONFIG_IP_MASQUERADE - __u32 premasq_saddr = iph->saddr; - __u16 premasq_sport = 0; - __u16 *portptr=NULL; - long premasq_len_diff = skb->len; - - if (iph->protocol==IPPROTO_UDP || - iph->protocol==IPPROTO_TCP) { - portptr = (__u16 *)&(((char *)iph)[iph->ihl*4]); + __u32 premasq_saddr = iph->saddr; + __u16 premasq_sport = 0; + __u16 *portptr = NULL; + long premasq_len_diff = skb->len; + + if (iph->protocol==IPPROTO_UDP || iph->protocol==IPPROTO_TCP) { + portptr = (__u16 *)&(((char *)iph)[iph->ihl * 4]); premasq_sport = portptr[0]; } @@ -336,9 +327,8 @@ * If this fragment needs masquerading, make it so... * (Don't masquerade de-masqueraded fragments) */ - if (!(is_frag&IPFWD_MASQUERADED) && fw_res==FW_MASQUERADE) - if (ip_fw_masquerade(&skb, dev2) < 0) - { + if (!(is_frag & IPFWD_MASQUERADED) && fw_res == FW_MASQUERADE) + if (ip_fw_masquerade(&skb, dev2) < 0) { /* * Masquerading failed; silently discard this packet. */ @@ -349,75 +339,80 @@ #endif IS_SKB(skb); - if (skb->len+encap > dev2->mtu && (iph->frag_off & htons(IP_DF))) - { + if (skb->len + encap > dev2->mtu && + (iph->frag_off & htons(IP_DF))) { ip_statistics.IpFragFails++; #ifdef CONFIG_IP_MASQUERADE - /* If we're demasquerading, put the correct daddr back */ + /* If we're demasquerading, put the correct daddr back + */ if (is_frag&IPFWD_MASQUERADED) iph->daddr = dev->pa_addr; - /* If we're masquerading, put the correct source back */ else if (fw_res==FW_MASQUERADE) { iph->saddr = premasq_saddr; if (premasq_sport) portptr[0] = premasq_sport; } - - /* If the packet has got larger and this has caused it to - exceed the MTU, then we'll claim that our MTU just got - smaller and hope it works */ + + /* If the packet has got larger and this has caused it + * to exceed the MTU, then we'll claim that our MTU + * just got smaller and hope it works + */ premasq_len_diff -= skb->len; if (premasq_len_diff < 0) - icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, - htonl(dev2->mtu+premasq_len_diff), dev); + icmp_send(skb, ICMP_DEST_UNREACH, + ICMP_FRAG_NEEDED, + htonl(dev2->mtu + premasq_len_diff), + dev); else #endif - icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(dev2->mtu), dev); - if(rt) + icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, + htonl(dev2->mtu), dev, 1); + if (rt) ip_rt_put(rt); return -1; } #ifdef CONFIG_IP_MROUTE - if(skb_headroom(skb)-encaphard_header_len) - { - skb2 = alloc_skb(dev2->hard_header_len + skb->len + encap + 15, GFP_ATOMIC); + if (skb_headroom(skb) - encap < dev2->hard_header_len) { + skb2 = alloc_skb(dev2->hard_header_len + skb->len + + encap + 15, GFP_ATOMIC); #else - if(skb_headroom(skb)hard_header_len) - { - skb2 = alloc_skb(dev2->hard_header_len + skb->len + 15, GFP_ATOMIC); -#endif + if (skb_headroom(skb) < dev2->hard_header_len) { + skb2 = alloc_skb(dev2->hard_header_len + skb->len + 15, + GFP_ATOMIC); +#endif /* * This is rare and since IP is tolerant of network failures * quite harmless. */ - - if (skb2 == NULL) - { + + if (skb2 == NULL) { NETDEBUG(printk("\nIP: No memory available for IP forward\n")); - if(rt) + if (rt) ip_rt_put(rt); return -1; } - + IS_SKB(skb2); /* * Add the physical headers. */ - skb2->protocol=htons(ETH_P_IP); + skb2->protocol = htons(ETH_P_IP); #ifdef CONFIG_IP_MROUTE - if(is_frag&IPFWD_MULTITUNNEL) - { - skb_reserve(skb2,(encap+dev2->hard_header_len+15)&~15); /* 16 byte aligned IP headers are good */ - -/* We need to pass on IP information of the incoming packet to ip_encap() - * to fillin ttl, and tos fields.The destination should be target_addr. - * Anand, ernet. + if (is_frag & IPFWD_MULTITUNNEL) { + /* 16 byte aligned IP headers are good */ + skb_reserve(skb2, + (encap + + dev2->hard_header_len + 15) & ~15); + +/* We need to pass on IP information of the incoming packet to ip_encap() + * to fillin ttl, and tos fields.The destination should be target_addr. + * Anand, ernet. */ - skb2->ip_hdr = skb->ip_hdr; + skb2->ip_hdr = skb->ip_hdr; ip_encap(skb2,skb->len, dev2, target_addr); @@ -425,69 +420,71 @@ * Anand, ernet. */ skb2->raddr = rt->rt_gateway; - } - else -#endif - ip_send(rt,skb2,raddr,skb->len,dev2,dev2->pa_addr); + } else +#endif + ip_send(rt, skb2, raddr, skb->len, dev2, dev2->pa_addr); /* * We have to copy the bytes over as the new header wouldn't fit * the old buffer. This should be very rare. - */ - - ptr = skb_put(skb2,skb->len); + */ + + ptr = skb_put(skb2, skb->len); skb2->free = 1; skb2->h.raw = ptr; /* * Copy the packet data into the new buffer. */ memcpy(ptr, skb->h.raw, skb->len); - memcpy(skb2->proto_priv, skb->proto_priv, sizeof(skb->proto_priv)); + memcpy(skb2->proto_priv, skb->proto_priv, + sizeof (skb->proto_priv)); iph = skb2->ip_hdr = skb2->h.iph; - } - else - { - /* - * Build a new MAC header. + } else { + /* + * Build a new MAC header. */ - skb2 = skb; + skb2 = skb; skb2->dev=dev2; #ifdef CONFIG_IP_MROUTE - if(is_frag&IPFWD_MULTITUNNEL) + if (is_frag&IPFWD_MULTITUNNEL) ip_encap(skb, 0, dev2, target_addr); - else - { + else { #endif - skb->arp=1; - skb->raddr=raddr; - if (hh) - { - memcpy(skb_push(skb, dev2->hard_header_len), hh->hh_data, dev2->hard_header_len); - if (!hh->hh_uptodate) - { + skb->arp = 1; + skb->raddr = raddr; + if (hh) { + memcpy(skb_push(skb, + dev2->hard_header_len), + hh->hh_data, + dev2->hard_header_len); + if (!hh->hh_uptodate) { #if RT_CACHE_DEBUG >= 2 - printk("ip_forward: hh miss %08x via %08x\n", target_addr, rt->rt_gateway); -#endif + printk("ip_forward: hh miss %08x via %08x\n", + target_addr, + rt->rt_gateway); +#endif skb->arp = 0; } - } - else if (dev2->hard_header) - { - if(dev2->hard_header(skb, dev2, ETH_P_IP, NULL, NULL, skb->len)<0) - skb->arp=0; + } else if (dev2->hard_header) { + if (dev2->hard_header(skb, dev2, + ETH_P_IP, NULL, + NULL, + skb->len) < 0) + skb->arp = 0; } #ifdef CONFIG_IP_MROUTE - } -#endif + } +#endif } #ifdef CONFIG_FIREWALL - if((fw_res = call_out_firewall(PF_INET, skb2->dev, iph, NULL)) < FW_ACCEPT) - { + if ((fw_res = call_out_firewall(PF_INET, skb2->dev, + iph, NULL)) < FW_ACCEPT) { /* FW_ACCEPT and FW_MASQUERADE are treated equal: masquerading is only supported via forward rules */ if (fw_res == FW_REJECT) - icmp_send(skb2, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0, dev); + icmp_send(skb2, ICMP_DEST_UNREACH, + ICMP_HOST_UNREACH, 0, dev, 1); if (skb != skb2) kfree_skb(skb2,FREE_WRITE); if (rt) @@ -497,49 +494,41 @@ #endif ip_statistics.IpForwDatagrams++; - if (opt->optlen) - { + if (opt->optlen) { unsigned char * optptr; - if (opt->rr_needaddr) - { + if (opt->rr_needaddr) { optptr = (unsigned char *)iph + opt->rr; memcpy(&optptr[optptr[2]-5], &dev2->pa_addr, 4); opt->is_changed = 1; } - if (opt->srr_is_hit) - { + if (opt->srr_is_hit) { int srrptr, srrspace; optptr = (unsigned char *)iph + opt->srr; - for ( srrptr=optptr[2], srrspace = optptr[1]; - srrptr <= srrspace; - srrptr += 4 - ) - { + for (srrptr = optptr[2], srrspace = optptr[1]; + srrptr <= srrspace; srrptr += 4) { if (srrptr + 3 > srrspace) break; - if (memcmp(&target_addr, &optptr[srrptr-1], 4) == 0) + if (memcmp(&target_addr, + &optptr[srrptr-1], 4) == 0) break; } - if (srrptr + 3 <= srrspace) - { + if (srrptr + 3 <= srrspace) { opt->is_changed = 1; memcpy(&optptr[srrptr-1], &dev2->pa_addr, 4); iph->daddr = target_addr; - optptr[2] = srrptr+4; - } - else - printk(KERN_CRIT "ip_forward(): Argh! Destination lost!\n"); + optptr[2] = srrptr + 4; + } else + printk(KERN_CRIT + "ip_forward(): Argh! Destination lost!\n"); } - if (opt->ts_needaddr) - { + if (opt->ts_needaddr) { optptr = (unsigned char *)iph + opt->ts; memcpy(&optptr[optptr[2]-9], &dev2->pa_addr, 4); opt->is_changed = 1; } - if (opt->is_changed) - { + if (opt->is_changed) { opt->is_changed = 0; ip_send_check(iph); } @@ -555,65 +544,55 @@ * the fragmenter does the right thing. */ - if(skb2->len > dev2->mtu + dev2->hard_header_len) - { - ip_fragment(NULL,skb2,dev2, is_frag); - kfree_skb(skb2,FREE_WRITE); - } - else - { -#ifdef CONFIG_IP_ACCT + if (skb2->len > dev2->mtu + dev2->hard_header_len) { + ip_fragment(NULL, skb2, dev2, is_frag); + kfree_skb(skb2, FREE_WRITE); + } else { +#ifdef CONFIG_IP_ACCT /* * Count mapping we shortcut */ - - ip_fw_chk(iph,dev2,NULL,ip_acct_chain,0,IP_FW_MODE_ACCT_OUT); -#endif - + + ip_fw_chk(iph, dev2, NULL, ip_acct_chain, + 0, IP_FW_MODE_ACCT_OUT); +#endif + /* * Map service types to priority. We lie about * throughput being low priority, but it's a good * choice to help improve general usage. */ - if(iph->tos & IPTOS_LOWDELAY) + if (iph->tos & IPTOS_LOWDELAY) dev_queue_xmit(skb2, dev2, SOPRI_INTERACTIVE); - else if(iph->tos & IPTOS_THROUGHPUT) + else if (iph->tos & IPTOS_THROUGHPUT) dev_queue_xmit(skb2, dev2, SOPRI_BACKGROUND); else dev_queue_xmit(skb2, dev2, SOPRI_NORMAL); } - } - else - { - if(rt) - ip_rt_put(rt); + } else { + if (rt) + ip_rt_put(rt); return -1; } - if(rt) + if (rt) ip_rt_put(rt); - + /* * Tell the caller if their buffer is free. - */ - - if(skb==skb2) - return 0; + */ + + if (skb == skb2) + return 0; -#ifdef CONFIG_IP_MASQUERADE +#ifdef CONFIG_IP_MASQUERADE /* * The original is free. Free our copy and * tell the caller not to free. */ - if(skb!=skb_in) - { + if (skb != skb_in) { kfree_skb(skb_in, FREE_WRITE); return 0; } -#endif +#endif return 1; } - - - - - diff -urN linux-2.0.40-rc6/net/ipv4/ip_fragment.c linux-2.0.40-rc7/net/ipv4/ip_fragment.c --- linux-2.0.40-rc6/net/ipv4/ip_fragment.c 2004-01-15 07:19:51.000000000 -0800 +++ linux-2.0.40-rc7/net/ipv4/ip_fragment.c 2004-01-15 07:19:51.000000000 -0800 @@ -4,12 +4,13 @@ * interface as the means of communication with the user level. * * The IP fragmentation functionality. - * + * * Authors: Fred N. van Kempen * Alan Cox * * Fixes: - * Alan Cox : Split from ip.c , see ip_input.c for history. + * Alan Cox : Split from ip.c, see ip_input.c for + * history. * Alan Cox : Handling oversized frames * Uriel Maimon : Accounting errors in two fringe cases. */ @@ -37,16 +38,16 @@ * even the most extreme cases without allowing an attacker to measurably * harm machine performance. */ - -#define IPFRAG_HIGH_THRESH (256*1024) -#define IPFRAG_LOW_THRESH (192*1024) + +#define IPFRAG_HIGH_THRESH (256 * 1024) +#define IPFRAG_LOW_THRESH (192 * 1024) /* - * This fragment handler is a bit of a heap. On the other hand it works quite - * happily and handles things quite well. + * This fragment handler is a bit of a heap. On the other hand it works + * quite happily and handles things quite well. */ -static struct ipq *ipqueue = NULL; /* IP fragment queue */ +static struct ipq *ipqueue = NULL; /* IP fragment queue */ atomic_t ip_frag_mem = 0; /* Memory used for fragments */ @@ -55,28 +56,28 @@ /* * Memory Tracking Functions */ - + extern __inline__ void frag_kfree_skb(struct sk_buff *skb, int type) { atomic_sub(skb->truesize, &ip_frag_mem); - kfree_skb(skb,type); + kfree_skb(skb, type); } extern __inline__ void frag_kfree_s(void *ptr, int len) { atomic_sub(len, &ip_frag_mem); - kfree_s(ptr,len); + kfree_s(ptr, len); } - + extern __inline__ void *frag_kmalloc(int size, int pri) { - void *vp=kmalloc(size,pri); - if(!vp) + void *vp = kmalloc(size,pri); + if (!vp) return NULL; atomic_add(size, &ip_frag_mem); return vp; } - + /* * Create a new fragment entry. */ @@ -86,13 +87,12 @@ struct ipfrag *fp; unsigned long flags; - fp = (struct ipfrag *) frag_kmalloc(sizeof(struct ipfrag), GFP_ATOMIC); - if (fp == NULL) - { + fp = (struct ipfrag *)frag_kmalloc(sizeof (struct ipfrag), GFP_ATOMIC); + if (fp == NULL) { NETDEBUG(printk("IP: frag_create: no memory left !\n")); - return(NULL); + return NULL; } - memset(fp, 0, sizeof(struct ipfrag)); + memset(fp, 0, sizeof (struct ipfrag)); /* Fill in the structure. */ fp->offset = offset; @@ -100,20 +100,19 @@ fp->len = end - offset; fp->skb = skb; fp->ptr = ptr; - + /* * Charge for the SKB as well. */ - + save_flags(flags); cli(); - ip_frag_mem+=skb->truesize; + ip_frag_mem += skb->truesize; restore_flags(flags); - return(fp); + return fp; } - /* * Find the correct entry in the "incomplete datagrams" queue for * this IP datagram, and return the queue entry address if found. @@ -126,21 +125,22 @@ cli(); qplast = NULL; - for(qp = ipqueue; qp != NULL; qplast = qp, qp = qp->next) - { - if (iph->id== qp->iph->id && iph->saddr == qp->iph->saddr && - iph->daddr == qp->iph->daddr && iph->protocol == qp->iph->protocol) - { - del_timer(&qp->timer); /* So it doesn't vanish on us. The timer will be reset anyway */ + for (qp = ipqueue; qp != NULL; qplast = qp, qp = qp->next) { + if (iph->id == qp->iph->id && iph->saddr == qp->iph->saddr && + iph->daddr == qp->iph->daddr && + iph->protocol == qp->iph->protocol) { + /* So it doesn't vanish on us. The timer will be reset + * anyway + */ + del_timer(&qp->timer); sti(); - return(qp); + return qp; } } sti(); - return(NULL); + return NULL; } - /* * Remove an entry from the "incomplete datagrams" queue, either * because we completed, reassembled and processed it, or because @@ -160,14 +160,11 @@ /* Remove this entry from the "incomplete datagrams" queue. */ cli(); - if (qp->prev == NULL) - { + if (qp->prev == NULL) { ipqueue = qp->next; if (ipqueue != NULL) ipqueue->prev = NULL; - } - else - { + } else { qp->prev->next = qp->next; if (qp->next != NULL) qp->next->prev = qp->prev; @@ -176,12 +173,11 @@ /* Release all fragment data. */ fp = qp->fragments; - while (fp != NULL) - { + while (fp != NULL) { xp = fp->next; IS_SKB(fp->skb); - frag_kfree_skb(fp->skb,FREE_READ); - frag_kfree_s(fp, sizeof(struct ipfrag)); + frag_kfree_skb(fp->skb, FREE_READ); + frag_kfree_s(fp, sizeof (struct ipfrag)); fp = xp; } @@ -189,11 +185,10 @@ frag_kfree_s(qp->iph, 64 + 8); /* Finally, release the queue descriptor itself. */ - frag_kfree_s(qp, sizeof(struct ipq)); + frag_kfree_s(qp, sizeof (struct ipq)); sti(); } - /* * Oops- a fragment queue timed out. Kill it and send an ICMP reply. */ @@ -209,9 +204,9 @@ */ ip_statistics.IpReasmTimeout++; - ip_statistics.IpReasmFails++; + ip_statistics.IpReasmFails++; /* This if is always true... shrug */ - if(qp->fragments!=NULL) { + if (qp->fragments != NULL) { struct sk_buff *skb = qp->fragments->skb; struct iphdr *iph = skb->ip_hdr; @@ -221,7 +216,7 @@ skb_pull(skb, iph->ihl * 4); icmp_send(skb, ICMP_TIME_EXCEEDED, - ICMP_EXC_FRAGTIME, 0, qp->dev); + ICMP_EXC_FRAGTIME, 0, qp->dev, 1); } /* @@ -231,25 +226,24 @@ } /* - * Memory limiting on fragments. Evictor trashes the oldest + * Memory limiting on fragments. Evictor trashes the oldest * fragment queue until we are back under the low threshold */ - + static void ip_evictor(void) { - while(ip_frag_mem>IPFRAG_LOW_THRESH) - { - if(!ipqueue) + while (ip_frag_mem > IPFRAG_LOW_THRESH) { + if (!ipqueue) panic("ip_evictor: memcount"); ip_free(ipqueue); } } /* - * Add an entry to the 'ipq' queue for a newly received IP datagram. - * We will (hopefully :-) receive all other fragments of this datagram - * in time, so we just create a queue for this datagram, in which we - * will insert the received fragments at their respective positions. + * Add an entry to the 'ipq' queue for a newly received IP datagram. + * We will (hopefully :-) receive all other fragments of this datagram + * in time, so we just create a queue for this datagram, in which we + * will insert the received fragments at their respective positions. */ static struct ipq *ip_create(struct sk_buff *skb, struct iphdr *iph, struct device *dev) @@ -257,13 +251,12 @@ struct ipq *qp; int ihlen; - qp = (struct ipq *) frag_kmalloc(sizeof(struct ipq), GFP_ATOMIC); - if (qp == NULL) - { + qp = (struct ipq *)frag_kmalloc(sizeof (struct ipq), GFP_ATOMIC); + if (qp == NULL) { NETDEBUG(printk("IP: create: no memory left !\n")); - return(NULL); + return NULL; } - memset(qp, 0, sizeof(struct ipq)); + memset(qp, 0, sizeof (struct ipq)); /* * Allocate memory for the IP header (plus 8 octets for ICMP). @@ -271,11 +264,10 @@ ihlen = iph->ihl * 4; qp->iph = (struct iphdr *) frag_kmalloc(64 + 8, GFP_ATOMIC); - if (qp->iph == NULL) - { + if (qp->iph == NULL) { NETDEBUG(printk("IP: create: no memory left !\n")); - frag_kfree_s(qp, sizeof(struct ipq)); - return(NULL); + frag_kfree_s(qp, sizeof (struct ipq)); + return NULL; } memcpy(qp->iph, iph, ihlen + 8); @@ -286,7 +278,7 @@ /* Start a timer for this entry. */ qp->timer.expires = jiffies + IP_FRAG_TIME; /* about 30 seconds */ - qp->timer.data = (unsigned long) qp; /* pointer to queue */ + qp->timer.data = (unsigned long)qp; /* pointer to queue */ qp->timer.function = ip_expire; /* expire function */ add_timer(&qp->timer); @@ -298,10 +290,9 @@ qp->next->prev = qp; ipqueue = qp; sti(); - return(qp); + return qp; } - /* * See if a fragment queue is complete. */ @@ -313,30 +304,28 @@ /* Only possible if we received the final fragment. */ if (qp->len == 0) - return(0); + return 0; /* Check all fragment offsets to see if they connect. */ fp = qp->fragments; offset = 0; - while (fp != NULL) - { + while (fp != NULL) { if (fp->offset > offset) - return(0); /* fragment(s) missing */ + return 0; /* fragment(s) missing */ offset = fp->end; fp = fp->next; } /* All fragments are present. */ - return(1); + return 1; } - /* * Build a new IP datagram from all its fragments. * * FIXME: We copy here because we lack an effective way of handling lists * of bits on input. Until the new skb data handling is in I'm not going - * to touch this with a bargepole. + * to touch this with a bargepole. */ static struct sk_buff *ip_glue(struct ipq *qp) @@ -351,21 +340,20 @@ * Allocate a new buffer for the datagram. */ len = qp->ihlen + qp->len; - - if(len>65535) - { - NETDEBUG(printk("Oversized IP packet from %s.\n", in_ntoa(qp->iph->saddr))); + + if (len > 65535) { + NETDEBUG(printk("Oversized IP packet from %s.\n", + in_ntoa(qp->iph->saddr))); ip_statistics.IpReasmFails++; ip_free(qp); return NULL; } - - if ((skb = dev_alloc_skb(len)) == NULL) - { + + if ((skb = dev_alloc_skb(len)) == NULL) { ip_statistics.IpReasmFails++; NETDEBUG(printk("IP: queue_glue: no memory for gluing queue %p\n", qp)); ip_free(qp); - return(NULL); + return NULL; } /* Fill in the basic details. */ @@ -374,21 +362,19 @@ skb->free = 1; /* Copy the original IP headers into the new buffer. */ - ptr = (unsigned char *) skb->h.raw; - memcpy(ptr, ((unsigned char *) qp->iph), qp->ihlen); + ptr = (unsigned char *)skb->h.raw; + memcpy(ptr, ((unsigned char *)qp->iph), qp->ihlen); ptr += qp->ihlen; count = 0; /* Copy the data portions of all fragments into the new buffer. */ fp = qp->fragments; - while(fp != NULL) - { - if (fp->len < 0 || fp->offset+qp->ihlen+fp->len > skb->len) - { + while (fp != NULL) { + if (fp->len < 0 || fp->offset+qp->ihlen+fp->len > skb->len) { NETDEBUG(printk("Invalid fragment list: Fragment over size.\n")); ip_free(qp); - kfree_skb(skb,FREE_WRITE); + kfree_skb(skb, FREE_WRITE); ip_statistics.IpReasmFails++; return NULL; } @@ -409,10 +395,9 @@ skb->ip_hdr = iph; ip_statistics.IpReasmOKs++; - return(skb); + return skb; } - /* * Process an incoming IP datagram fragment. */ @@ -426,30 +411,30 @@ unsigned char *ptr; int flags, offset; int i, ihl, end; - + ip_statistics.IpReasmReqds++; /* * Start by cleaning up the memory */ - if(ip_frag_mem>IPFRAG_HIGH_THRESH) + if (ip_frag_mem > IPFRAG_HIGH_THRESH) ip_evictor(); - /* - * Find the entry of this IP datagram in the "incomplete datagrams" queue. + /* + * Find the entry of this IP datagram in the "incomplete + * datagrams" queue. */ - + qp = ip_find(iph); /* Is this a non-fragmented datagram? */ offset = ntohs(iph->frag_off); flags = offset & ~IP_OFFSET; offset &= IP_OFFSET; - if (((flags & IP_MF) == 0) && (offset == 0)) - { + if (((flags & IP_MF) == 0) && (offset == 0)) { if (qp != NULL) ip_free(qp); /* Fragmented frame replaced by full unfragmented copy */ - return(skb); + return skb; } offset <<= 3; /* offset is in 8-byte chunks */ @@ -461,48 +446,43 @@ * queue entry. */ - if (qp != NULL) - { + if (qp != NULL) { /* ANK. If the first fragment is received, * we should remember the correct IP header (with options) */ - if (offset == 0) - { + if (offset == 0) { qp->ihlen = ihl; - memcpy(qp->iph, iph, ihl+8); + memcpy(qp->iph, iph, ihl + 8); } del_timer(&qp->timer); qp->timer.expires = jiffies + IP_FRAG_TIME; /* about 30 seconds */ qp->timer.data = (unsigned long) qp; /* pointer to queue */ qp->timer.function = ip_expire; /* expire function */ add_timer(&qp->timer); - } - else - { + } else { /* * If we failed to create it, then discard the frame */ - if ((qp = ip_create(skb, iph, dev)) == NULL) - { + if ((qp = ip_create(skb, iph, dev)) == NULL) { skb->sk = NULL; kfree_skb(skb, FREE_READ); ip_statistics.IpReasmFails++; return NULL; } } - + /* * Attempt to construct an oversize packet. */ - - if(ntohs(iph->tot_len)+(int)offset>65535) - { + + if (ntohs(iph->tot_len) + (int)offset > 65535) { skb->sk = NULL; - NETDEBUG(printk("Oversized packet received from %s\n",in_ntoa(iph->saddr))); + NETDEBUG(printk("Oversized packet received from %s\n", + in_ntoa(iph->saddr))); kfree_skb(skb, FREE_READ); ip_statistics.IpReasmFails++; return NULL; - } + } /* * Determine the position of this fragment. @@ -524,26 +504,24 @@ qp->len = end; /* - * Find out which fragments are in front and at the back of us - * in the chain of fragments so far. We must know where to put - * this fragment, right? + * Find out which fragments are in front and at the back of us + * in the chain of fragments so far. We must know where to put + * this fragment, right? */ prev = NULL; - for(next = qp->fragments; next != NULL; next = next->next) - { + for (next = qp->fragments; next != NULL; next = next->next) { if (next->offset >= offset) break; /* bingo! */ prev = next; } /* - * We found where to put this one. - * Check for overlap with preceding fragment, and, if needed, - * align things so that any overlaps are eliminated. + * We found where to put this one. + * Check for overlap with preceding fragment, and, if needed, + * align things so that any overlaps are eliminated. */ - if (prev != NULL && offset < prev->end) - { + if (prev != NULL && offset < prev->end) { i = prev->end - offset; offset += i; /* ptr into datagram */ ptr += i; /* ptr into fragment data */ @@ -554,15 +532,14 @@ * If we can merge fragments, do it. */ - for(tmp=next; tmp != NULL; tmp = tfp) - { + for (tmp = next; tmp != NULL; tmp = tfp) { tfp = tmp->next; if (tmp->offset >= end) break; /* no overlaps at all */ - i = end - next->offset; /* overlap is 'i' bytes */ - tmp->len -= i; /* so reduce size of */ - tmp->offset += i; /* next fragment */ + i = end - next->offset; /* overlap is 'i' bytes */ + tmp->len -= i; /* so reduce size of */ + tmp->offset += i; /* next fragment */ tmp->ptr += i; /* * If we get a frag size of <= 0, remove it and the packet @@ -571,8 +548,7 @@ * We never throw the new frag away, so the frag being * dumped has always been charged for. */ - if (tmp->len <= 0) - { + if (tmp->len <= 0) { if (tmp->prev != NULL) tmp->prev->next = tmp->next; else @@ -580,11 +556,11 @@ if (tmp->next != NULL) tmp->next->prev = tmp->prev; - - next=tfp; /* We have killed the original next frame */ - frag_kfree_skb(tmp->skb,FREE_READ); - frag_kfree_s(tmp, sizeof(struct ipfrag)); + next = tfp; /* We have killed the original next frame */ + + frag_kfree_skb(tmp->skb, FREE_READ); + frag_kfree_s(tmp, sizeof (struct ipfrag)); } } @@ -600,17 +576,16 @@ * failed the frag_create we haven't charged the queue. */ - if (!tfp) - { + if (!tfp) { skb->sk = NULL; kfree_skb(skb, FREE_READ); return NULL; } - + /* * From now on our buffer is charged to the queues. */ - + tfp->prev = prev; tfp->next = next; if (prev != NULL) @@ -622,32 +597,31 @@ next->prev = tfp; /* - * OK, so we inserted this new fragment into the chain. - * Check if we now have a full IP datagram which we can - * bump up to the IP layer... + * OK, so we inserted this new fragment into the chain. + * Check if we now have a full IP datagram which we can + * bump up to the IP layer... */ - if (ip_done(qp)) - { + if (ip_done(qp)) { skb2 = ip_glue(qp); /* glue together the fragments */ - return(skb2); + return skb2; } - return(NULL); + return NULL; } /* - * This IP datagram is too large to be sent in one piece. Break it up into - * smaller pieces (each of size equal to the MAC header plus IP header plus - * a block of the data of the original IP data part) that will yet fit in a - * single device frame, and queue such a frame for sending by calling the - * ip_queue_xmit(). Note that this is recursion, and bad things will happen - * if this function causes a loop... + * This IP datagram is too large to be sent in one piece. Break it up + * into smaller pieces (each of size equal to the MAC header plus IP + * header plus a block of the data of the original IP data part) that will + * yet fit in a single device frame, and queue such a frame for sending by + * calling the ip_queue_xmit(). Note that this is recursion, and bad + * things will happen if this function causes a loop... * * Yes this is inefficient, feel free to submit a quicker one. * */ - + void ip_fragment(struct sock *sk, struct sk_buff *skb, struct device *dev, int is_frag) { struct iphdr *iph; @@ -656,7 +630,7 @@ struct sk_buff *skb2; int left, mtu, hlen, len; int offset; - + unsigned short true_hard_header_len; /* @@ -665,7 +639,7 @@ raw = skb->data; #if 0 - iph = (struct iphdr *) (raw + dev->hard_header_len); + iph = (struct iphdr *) (raw + dev->hard_header_len); skb->ip_hdr = iph; #else iph = skb->ip_hdr; @@ -691,23 +665,22 @@ * Check for any "DF" flag. [DF means do not fragment] */ - if (iph->frag_off & htons(IP_DF)) - { + if (iph->frag_off & htons(IP_DF)) { ip_statistics.IpFragFails++; NETDEBUG(printk("ip_queue_xmit: frag needed\n")); return; } /* - * The protocol doesn't seem to say what to do in the case that the - * frame + options doesn't fit the mtu. As it used to fall down dead - * in this case we were fortunate it didn't happen + * The protocol doesn't seem to say what to do in the case that + * the frame + options doesn't fit the mtu. As it used to fall + * down dead in this case we were fortunate it didn't happen */ - if(mtu<8) - { + if (mtu < 8) { /* It's wrong but it's better than nothing */ - icmp_send(skb,ICMP_DEST_UNREACH,ICMP_FRAG_NEEDED,htons(dev->mtu), dev); + icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, + htons(dev->mtu), dev, 1); ip_statistics.IpFragFails++; return; } @@ -726,30 +699,26 @@ else offset = 0; - /* * Keep copying data until we run out. */ - while(left > 0) - { + while (left > 0) { len = left; /* IF: it doesn't fit, use 'mtu' - the data space left */ if (len > mtu) len = mtu; /* IF: we are not sending upto and including the packet end then align the next start on an eight byte boundary */ - if (len < left) - { - len/=8; - len*=8; + if (len < left) { + len /= 8; + len *= 8; } /* * Allocate buffer. */ - if ((skb2 = alloc_skb(len + hlen+15,GFP_ATOMIC)) == NULL) - { + if ((skb2 = alloc_skb(len + hlen + 15, GFP_ATOMIC)) == NULL) { NETDEBUG(printk("IP: frag: no memory for new fragment!\n")); ip_statistics.IpFragFails++; return; @@ -761,22 +730,22 @@ skb2->arp = skb->arp; skb2->protocol = htons(ETH_P_IP); /* Atleast PPP needs this */ -#if 0 - if(skb->free==0) - printk(KERN_ERR "IP fragmenter: BUG free!=1 in fragmenter\n"); -#endif +#if 0 + if (skb->free == 0) + printk(KERN_ERR + "IP fragmenter: BUG free!=1 in fragmenter\n"); +#endif skb2->free = 1; - skb_put(skb2,len + hlen); - skb2->h.raw=(char *) skb2->data; + skb_put(skb2, len + hlen); + skb2->h.raw = (char *) skb2->data; /* * Charge the memory for the fragment to any owner * it might possess */ - if (sk) - { + if (sk) { atomic_add(skb2->truesize, &sk->wmem_alloc); - skb2->sk=sk; + skb2->sk = sk; } skb2->raddr = skb->raddr; /* For rebuild_header - must be here */ @@ -792,7 +761,7 @@ memcpy(skb2->h.raw + hlen, ptr, len); left -= len; - skb2->h.raw+=true_hard_header_len; + skb2->h.raw += true_hard_header_len; /* * Fill in the new header fields. @@ -811,8 +780,8 @@ ip_options_fragment(skb); /* - * Added AC : If we are fragmenting a fragment that's not the - * last fragment then keep MF on each bit + * Added AC: If we are fragmenting a fragment that's not + * the last fragment then keep MF on each bit */ if (left > 0 || (is_frag & 1)) iph->frag_off |= htons(IP_MF); @@ -829,5 +798,3 @@ } ip_statistics.IpFragOKs++; } - - diff -urN linux-2.0.40-rc6/net/ipv4/ip_input.c linux-2.0.40-rc7/net/ipv4/ip_input.c --- linux-2.0.40-rc6/net/ipv4/ip_input.c 1998-11-15 10:33:21.000000000 -0800 +++ linux-2.0.40-rc7/net/ipv4/ip_input.c 2004-01-15 07:19:51.000000000 -0800 @@ -15,28 +15,34 @@ * Stefan Becker, * Jorge Cwik, * Arnt Gulbrandsen, - * + * * * Fixes: - * Alan Cox : Commented a couple of minor bits of surplus code - * Alan Cox : Undefining IP_FORWARD doesn't include the code + * Alan Cox : Commented a couple of minor bits of + * surplus code + * Alan Cox : Undefining IP_FORWARD doesn't include + * the code * (just stops a compiler warning). - * Alan Cox : Frames with >=MAX_ROUTE record routes, strict routes or loose routes - * are junked rather than corrupting things. - * Alan Cox : Frames to bad broadcast subnets are dumped - * We used to process them non broadcast and - * boy could that cause havoc. + * Alan Cox : Frames with >= MAX_ROUTE record routes, + * strict routes or loose routes are + * junked rather than corrupting things. + * Alan Cox : Frames to bad broadcast subnets + * are dumped + * We used to process them non broadcast + * and boy could that cause havoc. * Alan Cox : ip_forward sets the free flag on the * new frame it queues. Still crap because * it copies the frame but at least it * doesn't eat memory too. * Alan Cox : Generic queue code and memory fixes. - * Fred Van Kempen : IP fragment support (borrowed from NET2E) + * Fred Van Kempen : IP fragment support + * (borrowed from NET2E) * Gerhard Koerting: Forward fragmented frames correctly. - * Gerhard Koerting: Fixes to my fix of the above 8-). + * Gerhard Koerting: Fixes to my fix of the above 8-). * Gerhard Koerting: IP interface addressing fix. * Linus Torvalds : More robustness checks - * Alan Cox : Even more checks: Still not as robust as it ought to be + * Alan Cox : Even more checks: Still not as robust + * as it ought to be * Alan Cox : Save IP header pointer for later * Alan Cox : ip option setting * Alan Cox : Use ip_tos/ip_ttl settings @@ -55,13 +61,15 @@ * Alan Cox : BSD address rule semantics. Also see * UDP as there is a nasty checksum issue * if you do things the wrong way. - * Alan Cox : Always defrag, moved IP_FORWARD to the config.in file - * Alan Cox : IP options adjust sk->priority. + * Alan Cox : Always defrag, moved IP_FORWARD to the + * config.in file + * Alan Cox : IP options adjust sk->priority. * Pedro Roque : Fix mtu/length error in ip_forward. * Alan Cox : Avoid ip_chk_addr when possible. * Richard Underwood : IP multicasting. * Alan Cox : Cleaned up multicast handlers. - * Alan Cox : RAW sockets demultiplex in the BSD style. + * Alan Cox : RAW sockets demultiplex in the BSD + * style. * Gunther Mayer : Fix the SNMP reporting typo * Alan Cox : Always in group 224.0.0.1 * Pauline Middelink : Fast ip_checksum update when forwarding @@ -75,17 +83,22 @@ * Arnt Gulbrandsen : ip_build_xmit * Alan Cox : Per socket routing cache * Alan Cox : Fixed routing cache, added header cache. - * Alan Cox : Loopback didn't work right in original ip_build_xmit - fixed it. - * Alan Cox : Only send ICMP_REDIRECT if src/dest are the same net. + * Alan Cox : Loopback didn't work right in original + * ip_build_xmit - fixed it. + * Alan Cox : Only send ICMP_REDIRECT if src/dest are + * the same net. * Alan Cox : Incoming IP option handling. - * Alan Cox : Set saddr on raw output frames as per BSD. - * Alan Cox : Stopped broadcast source route explosions. + * Alan Cox : Set saddr on raw output frames as per + * BSD. + * Alan Cox : Stopped broadcast source route + * explosions. * Alan Cox : Can disable source routing * Takeshi Sone : Masquerading didn't work. * Dave Bonn,Alan Cox : Faster IP forwarding whenever possible. * Alan Cox : Memory leaks, tramples, misc debugging. * Alan Cox : Fixed multicast (by popular demand 8)) - * Alan Cox : Fixed forwarding (by even more popular demand 8)) + * Alan Cox : Fixed forwarding (by even more popular + * demand 8)) * Alan Cox : Fixed SNMP statistics [I think] * Gerhard Koerting : IP fragmentation forwarding fix * Alan Cox : Device lock against page fault. @@ -98,16 +111,19 @@ * Jos Vos : Do accounting *before* call_in_firewall * Willy Konynenberg : Transparent proxying support * - * + * * * To Fix: - * IP fragmentation wants rewriting cleanly. The RFC815 algorithm is much more efficient - * and could be made very efficient with the addition of some virtual memory hacks to permit - * the allocation of a buffer that can then be 'grown' by twiddling page tables. - * Output fragmentation wants updating along with the buffer management to use a single - * interleaved copy algorithm so that fragmenting has a one copy overhead. Actual packet - * output should probably do its own fragmentation at the UDP/RAW layer. TCP shouldn't cause - * fragmentation anyway. + * IP fragmentation wants rewriting cleanly. The RFC815 algorithm + * is much more efficient and could be made very efficient with + * the addition of some virtual memory hacks to permit the + * allocation of a buffer that can then be 'grown' by twiddling + * page tables. + * Output fragmentation wants updating along with the buffer + * management to use a single interleaved copy algorithm so that + * fragmenting has a one copy overhead. Actual packet output + * should probably do its own fragmentation at the UDP/RAW layer. + * TCP shouldn't cause fragmentation anyway. * * FIXME: copy frag 0 iph to qp->iph * @@ -163,16 +179,16 @@ extern int last_retran; extern void sort_send(struct sock *sk); -#define min(a,b) ((a)<(b)?(a):(b)) +#define min(a, b) ((a) < (b) ? (a) : (b)) /* * SNMP management statistics */ #ifdef CONFIG_IP_FORWARD -struct ip_mib ip_statistics={1,64,}; /* Forwarding=Yes, Default TTL=64 */ +struct ip_mib ip_statistics = {1, 64,}; /* Forwarding = Yes, Default TTL = 64 */ #else -struct ip_mib ip_statistics={2,64,}; /* Forwarding=No, Default TTL=64 */ +struct ip_mib ip_statistics = {2, 64,}; /* Forwarding = No, Default TTL = 64 */ #endif /* @@ -183,11 +199,7 @@ int ip_ioctl(struct sock *sk, int cmd, unsigned long arg) { - switch(cmd) - { - default: - return(-EINVAL); - } + return -EINVAL; } #ifdef CONFIG_IP_TRANSPARENT_PROXY @@ -207,8 +219,10 @@ case IPPROTO_UDP: return udp_chkaddr(skb); default: - return 0; + break; } + + return 0; } #endif @@ -227,30 +241,30 @@ unsigned char hash; unsigned char flag = 0; struct inet_protocol *ipprot; - int brd=IS_MYADDR; + int brd = IS_MYADDR; struct options * opt = NULL; - int is_frag=0; + int is_frag = 0; __u32 daddr; #ifdef CONFIG_FIREWALL int fwres; __u16 rport; -#endif +#endif #ifdef CONFIG_IP_MROUTE - int mroute_pkt=0; -#endif + int mroute_pkt = 0; +#endif #ifdef CONFIG_NET_IPV6 - /* - * Intercept IPv6 frames. We dump ST-II and invalid types just below.. + /* + * Intercept IPv6 frames. We dump ST-II and invalid types just + * below.. */ - - if(iph->version == 6) - return ipv6_rcv(skb,dev,pt); -#endif - ip_statistics.IpInReceives++; + if (iph->version == 6) + return ipv6_rcv(skb, dev, pt); +#endif + ip_statistics.IpInReceives++; /* * Tag the ip header of this packet so we can find it @@ -259,36 +273,40 @@ skb->ip_hdr = iph; /* - * RFC1122: 3.1.2.2 MUST silently discard any IP frame that fails the checksum. - * RFC1122: 3.1.2.3 MUST discard a frame with invalid source address [NEEDS FIXING]. + * RFC1122: 3.1.2.2 MUST silently discard any IP frame that fails + * the checksum. + * RFC1122: 3.1.2.3 MUST discard a frame with invalid source + * address [NEEDS FIXING]. * * Is the datagram acceptable? * * 1. Length at least the size of an ip header * 2. Version of 4 - * 3. Checksums correctly. [Speed optimisation for later, skip loopback checksums] + * 3. Checksums correctly. [Speed optimisation for later, + * skip loopback checksums] * 4. Doesn't have a bogus length - * (5. We ought to check for IP multicast addresses and undefined types.. does this matter ?) + * (5. We ought to check for IP multicast addresses and + * undefined types.. does this matter ?) */ - if (skb->lenihl<5 || iph->version != 4 || ip_fast_csum((unsigned char *)iph, iph->ihl) !=0 - || skb->len < ntohs(iph->tot_len)) - { + if (skb->len < sizeof (struct iphdr) || + iph->ihl < 5 || iph->version != 4 || + ip_fast_csum((unsigned char *)iph, iph->ihl) != 0 || + skb->len < ntohs(iph->tot_len)) { ip_statistics.IpInHdrErrors++; kfree_skb(skb, FREE_WRITE); - return(0); + return 0; } /* - * Our transport medium may have padded the buffer out. Now we know it - * is IP we can trim to the true length of the frame. + * Our transport medium may have padded the buffer out. Now we + * know it is IP we can trim to the true length of the frame. * Note this now means skb->len holds ntohs(iph->tot_len). */ skb_trim(skb,ntohs(iph->tot_len)); - - if(skb->len < (iph->ihl<<2)) - { + + if (skb->len < (iph->ihl << 2)) { ip_statistics.IpInHdrErrors++; kfree_skb(skb, FREE_WRITE); return 0; @@ -302,39 +320,39 @@ */ #ifdef CONFIG_IP_ACCT - ip_fw_chk(iph,dev,NULL,ip_acct_chain,0,IP_FW_MODE_ACCT_IN); -#endif + ip_fw_chk(iph, dev, NULL, ip_acct_chain, 0, IP_FW_MODE_ACCT_IN); +#endif /* * Try to select closest alias device, if any. - * net_alias_dev_rx32 returns main device if it + * net_alias_dev_rx32 returns main device if it * fails to found other. - * If successful, also incr. alias rx count. + * If successful, also incr. alias rx count. * * Only makes sense for unicasts - Thanks ANK. */ #ifdef CONFIG_NET_ALIAS - if (skb->pkt_type == PACKET_HOST && iph->daddr != skb->dev->pa_addr && net_alias_has(skb->dev)) { - skb->dev = dev = net_alias_dev_rx32(skb->dev, AF_INET, iph->saddr, iph->daddr); + if (skb->pkt_type == PACKET_HOST && + iph->daddr != skb->dev->pa_addr && net_alias_has(skb->dev)) { + skb->dev = dev = net_alias_dev_rx32(skb->dev, AF_INET, + iph->saddr, iph->daddr); } #endif - if (iph->ihl > 5) - { + if (iph->ihl > 5) { skb->ip_summed = 0; if (ip_options_compile(NULL, skb)) - return(0); + return 0; opt = (struct options*)skb->proto_priv; #ifdef CONFIG_IP_NOSR - if (opt->srr) - { + if (opt->srr) { kfree_skb(skb, FREE_READ); return -EINVAL; } -#endif +#endif } - + #if defined(CONFIG_IP_TRANSPARENT_PROXY) && !defined(CONFIG_IP_ALWAYS_DEFRAG) #define CONFIG_IP_ALWAYS_DEFRAG 1 #endif @@ -351,30 +369,28 @@ /* * See if the frame is fragmented. */ - - if(iph->frag_off) - { + + if (iph->frag_off) { if (iph->frag_off & htons(IP_MF)) - is_frag|=IPFWD_FRAGMENT; + is_frag |= IPFWD_FRAGMENT; /* - * Last fragment ? + * Last fragment? */ - + if (iph->frag_off & htons(IP_OFFSET)) - is_frag|=IPFWD_LASTFRAG; - + is_frag |= IPFWD_LASTFRAG; + /* * Reassemble IP fragments. */ - if(is_frag) - { + if (is_frag) { /* Defragment. Obtain the complete packet if there is one */ - skb=ip_defrag(iph,skb,dev); - if(skb==NULL) + skb = ip_defrag(iph, skb, dev); + if (skb == NULL) return 0; skb->dev = dev; - iph=skb->h.iph; + iph = skb->h.iph; is_frag = 0; /* * When the reassembled packet gets forwarded, the ip @@ -389,51 +405,51 @@ #endif /* - * See if the firewall wants to dispose of the packet. + * See if the firewall wants to dispose of the packet. */ - -#ifdef CONFIG_FIREWALL - if ((fwres=call_in_firewall(PF_INET, skb->dev, iph, &rport))dev, + iph, &rport)) < FW_ACCEPT) { + if (fwres == FW_REJECT) + icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, + 0, dev, 1); kfree_skb(skb, FREE_WRITE); - return 0; + return 0; } #ifdef CONFIG_IP_TRANSPARENT_PROXY - if (fwres==FW_REDIRECT) + if (fwres == FW_REDIRECT) skb->redirport = rport; else #endif skb->redirport = 0; #endif - + #ifndef CONFIG_IP_ALWAYS_DEFRAG /* * Remember if the frame is fragmented. */ - - if(iph->frag_off) - { + + if (iph->frag_off) { if (iph->frag_off & htons(IP_MF)) - is_frag|=IPFWD_FRAGMENT; + is_frag |= IPFWD_FRAGMENT; /* - * Last fragment ? + * Last fragment? */ - + if (iph->frag_off & htons(IP_OFFSET)) - is_frag|=IPFWD_LASTFRAG; + is_frag |= IPFWD_LASTFRAG; } - + #endif /* - * Do any IP forwarding required. chk_addr() is expensive -- avoid it someday. + * Do any IP forwarding required. chk_addr() is expensive -- + * avoid it someday. * - * This is inefficient. While finding out if it is for us we could also compute - * the routing table entry. This is where the great unified cache theory comes - * in as and when someone implements it + * This is inefficient. While finding out if it is for us we could + * also compute the routing table entry. This is where the great + * unified cache theory comes in as and when someone implements it * * For most hosts over 99% of packets match the first conditional * and don't go via ip_chk_addr. Note: brd is set to IS_MYADDR at @@ -444,58 +460,54 @@ /* * ip_chksock adds still more overhead for forwarded traffic... */ - if ( iph->daddr == skb->dev->pa_addr || skb->redirport || (brd = ip_chk_addr(iph->daddr)) != 0 || ip_chksock(skb)) + if (iph->daddr == skb->dev->pa_addr || skb->redirport || + (brd = ip_chk_addr(iph->daddr)) != 0 || ip_chksock(skb)) { #else - if ( iph->daddr == skb->dev->pa_addr || (brd = ip_chk_addr(iph->daddr)) != 0) + if (iph->daddr == skb->dev->pa_addr || + (brd = ip_chk_addr(iph->daddr)) != 0) { #endif - { - if (opt && opt->srr) - { + if (opt && opt->srr) { int srrspace, srrptr; __u32 nexthop; - unsigned char * optptr = ((unsigned char *)iph) + opt->srr; + unsigned char * optptr = ((unsigned char *)iph) + + opt->srr; - if (brd != IS_MYADDR || skb->pkt_type != PACKET_HOST) - { + if (brd != IS_MYADDR || skb->pkt_type != PACKET_HOST) { kfree_skb(skb, FREE_WRITE); return 0; } - for ( srrptr=optptr[2], srrspace = optptr[1]; - srrptr <= srrspace; - srrptr += 4 - ) - { + for (srrptr=optptr[2], srrspace = optptr[1]; + srrptr <= srrspace; srrptr += 4) { int brd2; - if (srrptr + 3 > srrspace) - { - icmp_send(skb, ICMP_PARAMETERPROB, 0, opt->srr+2, - skb->dev); + if (srrptr + 3 > srrspace) { + icmp_send(skb, ICMP_PARAMETERPROB, 0, + opt->srr + 2, skb->dev, 1); kfree_skb(skb, FREE_WRITE); return 0; } - memcpy(&nexthop, &optptr[srrptr-1], 4); + memcpy(&nexthop, &optptr[srrptr - 1], 4); if ((brd2 = ip_chk_addr(nexthop)) == 0) break; - if (brd2 != IS_MYADDR) - { - + if (brd2 != IS_MYADDR) { /* - * ANK: should we implement weak tunneling of multicasts? - * Are they obsolete? DVMRP specs (RFC-1075) is old enough... + * ANK: should we implement weak + * tunneling of multicasts? + * Are they obsolete? DVMRP specs + * (RFC-1075) is old enough... * [They are obsolete] */ kfree_skb(skb, FREE_WRITE); return -EINVAL; } - memcpy(&daddr, &optptr[srrptr-1], 4); + memcpy(&daddr, &optptr[srrptr - 1], 4); } - if (srrptr <= srrspace) - { + if (srrptr <= srrspace) { opt->srr_is_hit = 1; opt->is_changed = 1; if (sysctl_ip_forward) { - if (ip_forward(skb, dev, is_frag, nexthop)) + if (ip_forward(skb, dev, is_frag, + nexthop)) kfree_skb(skb, FREE_WRITE); } else { ip_statistics.IpInAddrErrors++; @@ -505,25 +517,23 @@ } } -#ifdef CONFIG_IP_MULTICAST - if(!(dev->flags&IFF_ALLMULTI) && brd==IS_MULTICAST && iph->daddr!=IGMP_ALL_HOSTS && !(dev->flags&IFF_LOOPBACK)) - { +#ifdef CONFIG_IP_MULTICAST + if (!(dev->flags & IFF_ALLMULTI) && brd == IS_MULTICAST && + iph->daddr != IGMP_ALL_HOSTS && + !(dev->flags & IFF_LOOPBACK)) { /* * Check it is for one of our groups */ struct ip_mc_list *ip_mc=dev->ip_mc_list; - do - { - if(ip_mc==NULL) - { + do { + if (ip_mc == NULL) { kfree_skb(skb, FREE_WRITE); return 0; } - if(ip_mc->multiaddr==iph->daddr) + if (ip_mc->multiaddr == iph->daddr) break; - ip_mc=ip_mc->next; - } - while(1); + ip_mc = ip_mc->next; + } while (1); } #endif @@ -532,14 +542,13 @@ * Reassemble IP fragments. */ - if(is_frag) - { + if (is_frag) { /* Defragment. Obtain the complete packet if there is one */ - skb=ip_defrag(iph,skb,dev); - if(skb==NULL) + skb = ip_defrag(iph,skb,dev); + if (skb == NULL) return 0; skb->dev = dev; - iph=skb->h.iph; + iph = skb->h.iph; } #endif @@ -555,10 +564,10 @@ return 0; } - if (ret) - { - struct iphdr *iph=skb->h.iph; - if (ip_forward(skb, dev, IPFWD_MASQUERADED, iph->daddr)) + if (ret) { + struct iphdr *iph = skb->h.iph; + if (ip_forward(skb, dev, IPFWD_MASQUERADED, + iph->daddr)) kfree_skb(skb, FREE_WRITE); return 0; } @@ -570,99 +579,109 @@ */ skb->ip_hdr = iph; - skb->h.raw += iph->ihl*4; + skb->h.raw += iph->ihl * 4; -#ifdef CONFIG_IP_MROUTE +#ifdef CONFIG_IP_MROUTE /* * Check the state on multicast routing (multicast and not 224.0.0.z) */ - - if(brd==IS_MULTICAST && (iph->daddr&htonl(0xFFFFFF00))!=htonl(0xE0000000)) - mroute_pkt=1; + + if (brd == IS_MULTICAST && + (iph->daddr & htonl(0xFFFFFF00)) != htonl(0xE0000000)) + mroute_pkt = 1; #endif /* - * Deliver to raw sockets. This is fun as to avoid copies we want to make no surplus copies. + * Deliver to raw sockets. This is fun as to avoid copies + * we want to make no surplus copies. * - * RFC 1122: SHOULD pass TOS value up to the transport layer. + * RFC 1122: SHOULD pass TOS value up to the transport + * layer. + */ + + /* Note: See raw.c and net/raw.h, + * RAWV4_HTABLE_SIZE == MAX_INET_PROTOS */ - - /* Note: See raw.c and net/raw.h, RAWV4_HTABLE_SIZE==MAX_INET_PROTOS */ hash = iph->protocol & (MAX_INET_PROTOS - 1); - /* - * If there maybe a raw socket we must check - if not we don't care less + /* + * If there maybe a raw socket we must check - if not we + * don't care less */ - - if((raw_sk = raw_v4_htable[hash]) != NULL) { + + if ((raw_sk = raw_v4_htable[hash]) != NULL) { struct sock *sknext = NULL; struct sk_buff *skb1; raw_sk = raw_v4_lookup(raw_sk, iph->protocol, iph->saddr, iph->daddr); - if(raw_sk) { /* Any raw sockets */ + if (raw_sk) { /* Any raw sockets */ do { /* Find the next */ sknext = raw_v4_lookup(raw_sk->next, iph->protocol, iph->saddr, iph->daddr); - if(sknext) - skb1 = skb_clone(skb, GFP_ATOMIC); + if (sknext) + skb1 = skb_clone(skb, + GFP_ATOMIC); else break; /* One pending raw socket left */ - if(skb1) - raw_rcv(raw_sk, skb1, dev, iph->saddr,daddr); + if (skb1) + raw_rcv(raw_sk, skb1, dev, + iph->saddr,daddr); raw_sk = sknext; - } while(raw_sk!=NULL); - + } while (raw_sk != NULL); + /* - * Here either raw_sk is the last raw socket, or NULL if none + * Here either raw_sk is the last raw + * socket, or NULL if none */ - + /* - * We deliver to the last raw socket AFTER the protocol checks as it avoids a surplus copy + * We deliver to the last raw socket AFTER + * the protocol checks as it avoids a + * surplus copy */ } } - + /* * skb->h.raw now points at the protocol beyond the IP header. */ - - for (ipprot = (struct inet_protocol *)inet_protos[hash];ipprot != NULL;ipprot=(struct inet_protocol *)ipprot->next) - { + + for (ipprot = (struct inet_protocol *)inet_protos[hash]; + ipprot != NULL; + ipprot = (struct inet_protocol *)ipprot->next) { struct sk_buff *skb2; - + if (ipprot->protocol != iph->protocol) continue; /* - * See if we need to make a copy of it. This will - * only be set if more than one protocol wants it. - * and then not for the last one. If there is a pending - * raw delivery wait for that + * See if we need to make a copy of it. This will + * only be set if more than one protocol wants it. + * and then not for the last one. If there is a + * pending raw delivery wait for that */ - + #ifdef CONFIG_IP_MROUTE - if (ipprot->copy || raw_sk || mroute_pkt) -#else - if (ipprot->copy || raw_sk) -#endif - { + if (ipprot->copy || raw_sk || mroute_pkt) { +#else + if (ipprot->copy || raw_sk) { +#endif skb2 = skb_clone(skb, GFP_ATOMIC); - if(skb2==NULL) + if (skb2 == NULL) continue; - } - else - { + } else { skb2 = skb; } flag = 1; /* - * Pass on the datagram to each protocol that wants it, - * based on the datagram protocol. We should really - * check the protocol handler's return values here... + * Pass on the datagram to each protocol that + * wants it, based on the datagram protocol. We + * should really check the protocol handler's + * return values here... */ ipprot->handler(skb2, dev, opt, daddr, @@ -672,58 +691,56 @@ /* * All protocols checked. - * If this packet was a broadcast, we may *not* reply to it, since that - * causes (proven, grin) ARP storms and a leakage of memory (i.e. all - * ICMP reply messages get queued up for transmission...) + * If this packet was a broadcast, we may *not* reply to + * it, since that causes (proven, grin) ARP storms and a + * leakage of memory (i.e. all ICMP reply messages get + * queued up for transmission...) */ -#ifdef CONFIG_IP_MROUTE +#ifdef CONFIG_IP_MROUTE /* * Forward the last copy to the multicast router. If * there is a pending raw delivery however make a copy * and forward that. */ - - if(mroute_pkt) - { - flag=1; - if(raw_sk==NULL) + + if (mroute_pkt) { + flag = 1; + if (raw_sk == NULL) ipmr_forward(skb, is_frag); - else - { - struct sk_buff *skb2=skb_clone(skb, GFP_ATOMIC); - if(skb2) - { - skb2->free=1; + else { + struct sk_buff *skb2 = skb_clone(skb, + GFP_ATOMIC); + if (skb2) { + skb2->free = 1; ipmr_forward(skb2, is_frag); } } } -#endif +#endif - if(raw_sk!=NULL) /* Shift to last raw user */ + if (raw_sk != NULL) /* Shift to last raw user */ raw_rcv(raw_sk, skb, dev, iph->saddr, daddr); - else if (!flag) /* Free and report errors */ - { - if (brd != IS_BROADCAST && brd!=IS_MULTICAST) - icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, 0, dev); + else if (!flag) { /* Free and report errors */ + if (brd != IS_BROADCAST && brd != IS_MULTICAST) + icmp_send(skb, ICMP_DEST_UNREACH, + ICMP_PROT_UNREACH, 0, dev, 1); kfree_skb(skb, FREE_WRITE); } - return(0); + return 0; } /* * Do any unicast IP forwarding required. */ - + /* * Don't forward multicast or broadcast frames. */ - if(skb->pkt_type!=PACKET_HOST || brd==IS_BROADCAST) - { - kfree_skb(skb,FREE_WRITE); + if (skb->pkt_type != PACKET_HOST || brd == IS_BROADCAST) { + kfree_skb(skb, FREE_WRITE); return 0; } @@ -732,21 +749,20 @@ */ if (sysctl_ip_forward) { - if (opt && opt->is_strictroute) - { - icmp_send(skb, ICMP_PARAMETERPROB, 0, 16, skb->dev); + if (opt && opt->is_strictroute) { + icmp_send(skb, ICMP_PARAMETERPROB, 0, 16, skb->dev, 1); kfree_skb(skb, FREE_WRITE); return -1; } if (ip_forward(skb, dev, is_frag, iph->daddr)) kfree_skb(skb, FREE_WRITE); } else { -/* printk("Machine %lx tried to use us as a forwarder to %lx but we have forwarding disabled!\n", - iph->saddr,iph->daddr);*/ +/* + printk("Machine %lx tried to use us as a forwarder to %lx but we have forwarding disabled!\n", + iph->saddr, iph->daddr); +*/ ip_statistics.IpInAddrErrors++; kfree_skb(skb, FREE_WRITE); } - return(0); + return 0; } - - diff -urN linux-2.0.40-rc6/net/ipv4/ip_options.c linux-2.0.40-rc7/net/ipv4/ip_options.c --- linux-2.0.40-rc6/net/ipv4/ip_options.c 1996-04-17 23:47:39.000000000 -0700 +++ linux-2.0.40-rc7/net/ipv4/ip_options.c 2004-01-15 07:19:51.000000000 -0800 @@ -6,7 +6,7 @@ * The options processing module for ip.c * * Authors: A.N.Kuznetsov - * + * */ #include @@ -18,7 +18,7 @@ #include #include -/* +/* * Write options to IP header, record destination address to * source route option, address of outgoing interface * (we should already know it, so that this function is allowed be @@ -26,118 +26,104 @@ * if we originate this datagram. */ -void ip_options_build(struct sk_buff * skb, struct options * opt, - __u32 daddr, __u32 saddr, - int is_frag) +void ip_options_build(struct sk_buff *skb, struct options *opt, + __u32 daddr, __u32 saddr, int is_frag) { - unsigned char * iph = (unsigned char*)skb->ip_hdr; + unsigned char *iph = (unsigned char *)skb->ip_hdr; - memcpy(skb->proto_priv, opt, sizeof(struct options)); - memcpy(iph+sizeof(struct iphdr), opt->__data, opt->optlen); - opt = (struct options*)skb->proto_priv; + memcpy(skb->proto_priv, opt, sizeof (struct options)); + memcpy(iph + sizeof (struct iphdr), opt->__data, opt->optlen); + opt = (struct options *)skb->proto_priv; opt->is_data = 0; if (opt->srr) - memcpy(iph+opt->srr+iph[opt->srr+1]-4, &daddr, 4); + memcpy(iph + opt->srr + iph[opt->srr + 1] - 4, &daddr, 4); - if (!is_frag) - { + if (!is_frag) { if (opt->rr_needaddr) - memcpy(iph+opt->rr+iph[opt->rr+2]-5, &saddr, 4); + memcpy(iph + opt->rr + iph[opt->rr + 2] - 5, &saddr, 4); if (opt->ts_needaddr) - memcpy(iph+opt->ts+iph[opt->ts+2]-9, &saddr, 4); - if (opt->ts_needtime) - { + memcpy(iph + opt->ts + iph[opt->ts + 2] - 9, &saddr, 4); + if (opt->ts_needtime) { struct timeval tv; __u32 midtime; do_gettimeofday(&tv); midtime = htonl((tv.tv_sec % 86400) * 1000 + tv.tv_usec / 1000); - memcpy(iph+opt->ts+iph[opt->ts+2]-5, &midtime, 4); + memcpy(iph + opt->ts + iph[opt->ts + 2] - 5, &midtime, 4); } return; } - if (opt->rr) - { - memset(iph+opt->rr, IPOPT_NOP, iph[opt->rr+1]); + if (opt->rr) { + memset(iph + opt->rr, IPOPT_NOP, iph[opt->rr + 1]); opt->rr = 0; opt->rr_needaddr = 0; } - if (opt->ts) - { - memset(iph+opt->ts, IPOPT_NOP, iph[opt->ts+1]); + if (opt->ts) { + memset(iph + opt->ts, IPOPT_NOP, iph[opt->ts + 1]); opt->ts = 0; opt->ts_needaddr = opt->ts_needtime = 0; } } -int ip_options_echo(struct options * dopt, struct options * sopt, - __u32 daddr, __u32 saddr, - struct sk_buff * skb) +int ip_options_echo(struct options *dopt, struct options *sopt, + __u32 daddr, __u32 saddr, struct sk_buff *skb) { unsigned char *sptr, *dptr; int soffset, doffset; - int optlen; + int optlen; - memset(dopt, 0, sizeof(struct options)); + memset(dopt, 0, sizeof (struct options)); dopt->is_data = 1; if (!sopt) - sopt = (struct options*)skb->proto_priv; + sopt = (struct options *)skb->proto_priv; - if (sopt->optlen == 0) - { + if (sopt->optlen == 0) { dopt->optlen = 0; return 0; } - sptr = (sopt->is_data ? sopt->__data - sizeof(struct iphdr) : + sptr = (sopt->is_data ? sopt->__data - sizeof (struct iphdr) : (unsigned char *)skb->ip_hdr); dptr = dopt->__data; - if (sopt->rr) - { - optlen = sptr[sopt->rr+1]; - soffset = sptr[sopt->rr+2]; - dopt->rr = dopt->optlen + sizeof(struct iphdr); - memcpy(dptr, sptr+sopt->rr, optlen); + if (sopt->rr) { + optlen = sptr[sopt->rr + 1]; + soffset = sptr[sopt->rr + 2]; + dopt->rr = dopt->optlen + sizeof (struct iphdr); + memcpy(dptr, sptr + sopt->rr, optlen); if (sopt->rr_needaddr && soffset <= optlen) { if (soffset + 3 > optlen) return -EINVAL; dptr[2] = soffset + 4; dopt->rr_needaddr = 1; } - dptr += optlen; + dptr += optlen; dopt->optlen += optlen; } - if (sopt->ts) - { - optlen = sptr[sopt->ts+1]; - soffset = sptr[sopt->ts+2]; - dopt->ts = dopt->optlen + sizeof(struct iphdr); - memcpy(dptr, sptr+sopt->ts, optlen); - if (soffset <= optlen) - { - if (sopt->ts_needaddr) - { + if (sopt->ts) { + optlen = sptr[sopt->ts + 1]; + soffset = sptr[sopt->ts + 2]; + dopt->ts = dopt->optlen + sizeof (struct iphdr); + memcpy(dptr, sptr + sopt->ts, optlen); + if (soffset <= optlen) { + if (sopt->ts_needaddr) { if (soffset + 3 > optlen) return -EINVAL; dopt->ts_needaddr = 1; soffset += 4; } - if (sopt->ts_needtime) - { + if (sopt->ts_needtime) { if (soffset + 3 > optlen) return -EINVAL; dopt->ts_needtime = 1; soffset += 4; } - if (((struct timestamp*)(dptr+1))->flags == IPOPT_TS_PRESPEC) - { + if (((struct timestamp *)(dptr + 1))->flags == IPOPT_TS_PRESPEC) { __u32 addr; - memcpy(&addr, sptr+soffset-9, 4); - if (ip_chk_addr(addr) == 0) - { + memcpy(&addr, sptr + soffset - 9, 4); + if (ip_chk_addr(addr) == 0) { dopt->ts_needtime = 0; dopt->ts_needaddr = 0; soffset -= 8; @@ -148,9 +134,8 @@ dptr += optlen; dopt->optlen += optlen; } - if (sopt->srr) - { - unsigned char * start = sptr+sopt->srr; + if (sopt->srr) { + unsigned char *start = sptr + sopt->srr; __u32 faddr; optlen = start[1]; @@ -159,58 +144,55 @@ if (soffset > optlen) soffset = optlen + 1; soffset -= 4; - if (soffset > 3) - { - memcpy(&faddr, &start[soffset-1], 4); - for (soffset-=4, doffset=4; soffset > 3; soffset-=4, doffset+=4) - memcpy(&dptr[doffset-1], &start[soffset-1], 4); + if (soffset > 3) { + memcpy(&faddr, &start[soffset - 1], 4); + for (soffset -= 4, doffset = 4; soffset > 3; soffset -= 4, doffset += 4) + memcpy(&dptr[doffset - 1], &start[soffset - 1], 4); /* * RFC1812 requires to fix illegal source routes. */ - if (memcmp(&saddr, &start[soffset+3], 4) == 0) + if (memcmp(&saddr, &start[soffset + 3], 4) == 0) doffset -= 4; } - if (doffset > 3) - { - memcpy(&start[doffset-1], &daddr, 4); + if (doffset > 3) { + memcpy(&start[doffset - 1], &daddr, 4); dopt->faddr = faddr; dptr[0] = start[0]; - dptr[1] = doffset+3; + dptr[1] = doffset + 3; dptr[2] = 4; - dptr += doffset+3; - dopt->srr = dopt->optlen + sizeof(struct iphdr); - dopt->optlen += doffset+3; + dptr += doffset + 3; + dopt->srr = dopt->optlen + sizeof (struct iphdr); + dopt->optlen += doffset + 3; dopt->is_strictroute = sopt->is_strictroute; } } - while (dopt->optlen & 3) - { + while (dopt->optlen & 3) { *dptr++ = IPOPT_END; dopt->optlen++; } return 0; } -void ip_options_fragment(struct sk_buff * skb) +void ip_options_fragment(struct sk_buff *skb) { - unsigned char * optptr = (unsigned char*)skb->ip_hdr; - struct options * opt = (struct options*)skb->proto_priv; + unsigned char *optptr = (unsigned char *)skb->ip_hdr; + struct options *opt = (struct options *)skb->proto_priv; int l = opt->optlen; int optlen; - while (l > 0) - { - switch (*optptr) - { - case IPOPT_END: + while (l > 0) { + switch (*optptr) { + case IPOPT_END: return; - case IPOPT_NOOP: + case IPOPT_NOOP: l--; optptr++; continue; + default: + break; } optlen = optptr[1]; - if (optlen<2 || optlen>l) + if (optlen < 2 || optlen > l) return; if (!(*optptr & 0x80)) memset(optptr, IPOPT_NOOP, optlen); @@ -231,114 +213,96 @@ * If opt == NULL, then skb->data should point to IP header. */ -int ip_options_compile(struct options * opt, struct sk_buff * skb) +int ip_options_compile(struct options *opt, struct sk_buff *skb) { int l; - unsigned char * iph; - unsigned char * optptr; + unsigned char *iph; + unsigned char *optptr; int optlen; - unsigned char * pp_ptr = NULL; + unsigned char *pp_ptr = NULL; - if (!opt) - { - opt = (struct options*)skb->proto_priv; - memset(opt, 0, sizeof(struct options)); - iph = (unsigned char*)skb->ip_hdr; - opt->optlen = ((struct iphdr *)iph)->ihl*4 - sizeof(struct iphdr); - optptr = iph + sizeof(struct iphdr); + if (!opt) { + opt = (struct options *)skb->proto_priv; + memset(opt, 0, sizeof (struct options)); + iph = (unsigned char *)skb->ip_hdr; + opt->optlen = ((struct iphdr *)iph)->ihl * 4 - sizeof (struct iphdr); + optptr = iph + sizeof (struct iphdr); opt->is_data = 0; - } - else - { - optptr = opt->is_data ? opt->__data : (unsigned char*)&skb->ip_hdr[1]; - iph = optptr - sizeof(struct iphdr); + } else { + optptr = opt->is_data ? opt->__data : (unsigned char *)&skb->ip_hdr[1]; + iph = optptr - sizeof (struct iphdr); } - for (l = opt->optlen; l > 0; ) - { - switch (*optptr) - { - case IPOPT_END: - for (optptr++, l--; l>0; l--) - { - if (*optptr != IPOPT_END) - { + for (l = opt->optlen; l > 0; ) { + switch (*optptr) { + case IPOPT_END: + for (optptr++, l--; l > 0; optptr++, l--) { + if (*optptr != IPOPT_END) { *optptr = IPOPT_END; opt->is_changed = 1; } } - goto eol; - case IPOPT_NOOP: + goto EOL; + case IPOPT_NOOP: l--; optptr++; continue; } optlen = optptr[1]; - if (optlen<2 || optlen>l) - { + if (optlen < 2 || optlen > l) { pp_ptr = optptr; - goto error; + goto ERROR; } - switch (*optptr) - { - case IPOPT_SSRR: - case IPOPT_LSRR: - if (optlen < 3) - { + switch (*optptr) { + case IPOPT_SSRR: + case IPOPT_LSRR: + if (optlen < 3) { pp_ptr = optptr + 1; - goto error; + goto ERROR; } - if (optptr[2] < 4) - { + if (optptr[2] < 4) { pp_ptr = optptr + 2; - goto error; + goto ERROR; } /* NB: cf RFC-1812 5.2.4.1 */ - if (opt->srr) - { + if (opt->srr) { pp_ptr = optptr; - goto error; + goto ERROR; } - if (!skb) - { - if (optptr[2] != 4 || optlen < 7 || ((optlen-3) & 3)) - { + if (!skb) { + if (optptr[2] != 4 || + optlen < 7 || ((optlen - 3) & 3)) { pp_ptr = optptr + 1; - goto error; + goto ERROR; } memcpy(&opt->faddr, &optptr[3], 4); if (optlen > 7) - memmove(&optptr[3], &optptr[7], optlen-7); + memmove(&optptr[3], &optptr[7], + optlen - 7); } opt->is_strictroute = (optptr[0] == IPOPT_SSRR); opt->srr = optptr - iph; break; - case IPOPT_RR: - if (opt->rr) - { + case IPOPT_RR: + if (opt->rr) { pp_ptr = optptr; - goto error; + goto ERROR; } - if (optlen < 3) - { + if (optlen < 3) { pp_ptr = optptr + 1; - goto error; + goto ERROR; } - if (optptr[2] < 4) - { + if (optptr[2] < 4) { pp_ptr = optptr + 2; - goto error; + goto ERROR; } - if (optptr[2] <= optlen) - { - if (optptr[2]+3 > optlen) - { + if (optptr[2] <= optlen) { + if (optptr[2] + 3 > optlen) { pp_ptr = optptr + 2; - goto error; + goto ERROR; } - if (skb) - { - memcpy(&optptr[optptr[2]-1], &skb->dev->pa_addr, 4); + if (skb) { + memcpy(&optptr[optptr[2] - 1], &skb->dev->pa_addr, 4); opt->is_changed = 1; } optptr[2] += 4; @@ -346,112 +310,97 @@ } opt->rr = optptr - iph; break; - case IPOPT_TIMESTAMP: - if (opt->ts) - { + case IPOPT_TIMESTAMP: + if (opt->ts) { pp_ptr = optptr; - goto error; + goto ERROR; } - if (optlen < 4) - { + if (optlen < 4) { pp_ptr = optptr + 1; - goto error; + goto ERROR; } - if (optptr[2] < 5) - { + if (optptr[2] < 5) { pp_ptr = optptr + 2; - goto error; + goto ERROR; } - if (optptr[2] <= optlen) - { - struct timestamp * ts = (struct timestamp*)(optptr+1); - __u32 * timeptr = NULL; - if (ts->ptr+3 > ts->len) - { + if (optptr[2] <= optlen) { + struct timestamp *ts = (struct timestamp *)(optptr + 1); + __u32 *timeptr = NULL; + if (ts->ptr + 3 > ts->len) { pp_ptr = optptr + 2; - goto error; + goto ERROR; } - switch (ts->flags) - { - case IPOPT_TS_TSONLY: + switch (ts->flags) { + case IPOPT_TS_TSONLY: opt->ts = optptr - iph; - if (skb) - timeptr = (__u32*)&optptr[ts->ptr-1]; + if (skb) + timeptr = (__u32 *)&optptr[ts->ptr - 1]; opt->ts_needtime = 1; ts->ptr += 4; break; - case IPOPT_TS_TSANDADDR: - if (ts->ptr+7 > ts->len) - { + case IPOPT_TS_TSANDADDR: + if (ts->ptr + 7 > ts->len) { pp_ptr = optptr + 2; - goto error; + goto ERROR; } opt->ts = optptr - iph; - if (skb) - { - memcpy(&optptr[ts->ptr-1], &skb->dev->pa_addr, 4); - timeptr = (__u32*)&optptr[ts->ptr+3]; + if (skb) { + memcpy(&optptr[ts->ptr - 1], &skb->dev->pa_addr, 4); + timeptr = (__u32 *)&optptr[ts->ptr + 3]; } opt->ts_needaddr = 1; opt->ts_needtime = 1; ts->ptr += 8; break; - case IPOPT_TS_PRESPEC: - if (ts->ptr+7 > ts->len) - { + case IPOPT_TS_PRESPEC: + if (ts->ptr + 7 > ts->len) { pp_ptr = optptr + 2; - goto error; + goto ERROR; } opt->ts = optptr - iph; { __u32 addr; - memcpy(&addr, &optptr[ts->ptr-1], 4); + memcpy(&addr, &optptr[ts->ptr - 1], 4); if (ip_chk_addr(addr) == 0) break; if (skb) - timeptr = (__u32*)&optptr[ts->ptr+3]; + timeptr = (__u32 *)&optptr[ts->ptr + 3]; } opt->ts_needaddr = 1; opt->ts_needtime = 1; ts->ptr += 8; break; - default: + default: pp_ptr = optptr + 3; - goto error; + goto ERROR; } - if (timeptr) - { + if (timeptr) { struct timeval tv; - __u32 midtime; + __u32 midtime; do_gettimeofday(&tv); midtime = htonl((tv.tv_sec % 86400) * 1000 + tv.tv_usec / 1000); - memcpy(timeptr, &midtime, sizeof(__u32)); + memcpy(timeptr, &midtime, sizeof (__u32)); opt->is_changed = 1; } - } - else - { - struct timestamp * ts = (struct timestamp*)(optptr+1); - if (ts->overflow == 15) - { + } else { + struct timestamp *ts = (struct timestamp *)(optptr + 1); + if (ts->overflow == 15) { pp_ptr = optptr + 3; - goto error; + goto ERROR; } opt->ts = optptr - iph; - if (skb) - { + if (skb) { ts->overflow++; opt->is_changed = 1; } } break; - case IPOPT_SEC: - case IPOPT_SID: - default: - if (!skb) - { + case IPOPT_SEC: + case IPOPT_SID: + default: + if (!skb) { pp_ptr = optptr; - goto error; + goto ERROR; } break; } @@ -459,16 +408,15 @@ optptr += optlen; } -eol: +EOL: if (!pp_ptr) return 0; -error: - if (skb) - { - icmp_send(skb, ICMP_PARAMETERPROB, 0, pp_ptr-iph, skb->dev); +ERROR: + if (skb) { + icmp_send(skb, ICMP_PARAMETERPROB, 0, + pp_ptr - iph, skb->dev, 1); kfree_skb(skb, FREE_READ); } return -EINVAL; } - diff -urN linux-2.0.40-rc6/net/ipv4/udp.c linux-2.0.40-rc7/net/ipv4/udp.c --- linux-2.0.40-rc6/net/ipv4/udp.c 1997-12-10 09:14:01.000000000 -0800 +++ linux-2.0.40-rc7/net/ipv4/udp.c 2004-01-15 07:19:51.000000000 -0800 @@ -14,35 +14,41 @@ * * Fixes: * Alan Cox : verify_area() calls - * Alan Cox : stopped close while in use off icmp + * Alan Cox : stopped close while in use off icmp * messages. Not a fix but a botch that * for udp at least is 'valid'. * Alan Cox : Fixed icmp handling properly - * Alan Cox : Correct error for oversized datagrams - * Alan Cox : Tidied select() semantics. - * Alan Cox : udp_err() fixed properly, also now + * Alan Cox : Correct error for oversized datagrams + * Alan Cox : Tidied select() semantics. + * Alan Cox : udp_err() fixed properly, also now * select and read wake correctly on errors - * Alan Cox : udp_send verify_area moved to avoid mem leak + * Alan Cox : udp_send verify_area moved to avoid mem + * leak * Alan Cox : UDP can count its memory * Alan Cox : send to an unknown connection causes * an ECONNREFUSED off the icmp, but * does NOT close. - * Alan Cox : Switched to new sk_buff handlers. No more backlog! - * Alan Cox : Using generic datagram code. Even smaller and the PEEK - * bug no longer crashes it. - * Fred Van Kempen : Net2e support for sk->broadcast. + * Alan Cox : Switched to new sk_buff handlers. No + * more backlog! + * Alan Cox : Using generic datagram code. Even + * smaller and the PEEK bug no longer + * crashes it. + * Fred Van Kempen : Net2e support for sk->broadcast. * Alan Cox : Uses skb_free_datagram * Alan Cox : Added get/set sockopt support. - * Alan Cox : Broadcasting without option set returns EACCES. - * Alan Cox : No wakeup calls. Instead we now use the callbacks. + * Alan Cox : Broadcasting without option set returns + * EACCES. + * Alan Cox : No wakeup calls. Instead we now use the + * callbacks. * Alan Cox : Use ip_tos and ip_ttl * Alan Cox : SNMP Mibs * Alan Cox : MSG_DONTROUTE, and 0.0.0.0 support. * Matt Dillon : UDP length checks. * Alan Cox : Smarter af_inet used properly. * Alan Cox : Use new kernel side addressing. - * Alan Cox : Incorrect return on truncated datagram receive. - * Arnt Gulbrandsen : New udp_send and stuff + * Alan Cox : Incorrect return on truncated datagram + * receive. + * Arnt Gulbrandsen : New udp_send and stuff * Alan Cox : Cache last socket * Alan Cox : Route cache * Jon Peatfield : Minor efficiency fix to sendto(). @@ -63,10 +69,10 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ - + /* RFC1122 Status: 4.1.3.1 (Ports): - SHOULD send ICMP_PORT_UNREACHABLE in response to datagrams to + SHOULD send ICMP_PORT_UNREACHABLE in response to datagrams to an un-listened port. (OK) 4.1.3.2 (IP Options) MUST pass IP options from IP -> application (OK) @@ -81,12 +87,14 @@ 4.1.3.5 (UDP Multihoming) MUST allow application to specify source address (OK) SHOULD be able to communicate the chosen src addr up to application - when application doesn't choose (NOT YET - doesn't seem to be in the BSD API) + when application doesn't choose (NOT YET - doesn't seem to be in the BSD + API) [Does opening a SOCK_PACKET and snooping your output count 8)] 4.1.3.6 (Invalid Addresses) MUST discard invalid source addresses (NOT YET -- will be implemented in IP, so UDP will eventually be OK. Right now it's a violation.) - MUST only send datagrams with one of our addresses (NOT YET - ought to be OK ) + MUST only send datagrams with one of our addresses (NOT YET - ought to be + OK) 950728 -- MS */ @@ -120,7 +128,7 @@ * Snmp MIB for the UDP layer */ -struct udp_mib udp_statistics; +struct udp_mib udp_statistics; struct sock *udp_hash[UDP_HTABLE_SIZE]; @@ -130,8 +138,9 @@ int retval = 0, sk_reuse = sk->reuse; SOCKHASH_LOCK(); - for(sk2 = udp_hash[snum & (UDP_HTABLE_SIZE - 1)]; sk2 != NULL; sk2 = sk2->next) { - if((sk2->num == snum) && (sk2 != sk)) { + for (sk2 = udp_hash[snum & (UDP_HTABLE_SIZE - 1)]; + sk2 != NULL; sk2 = sk2->next) { + if ((sk2->num == snum) && (sk2 != sk)) { int sk2_reuse = sk2->reuse; /* Two sockets can be bound to the same port if they're @@ -139,13 +148,13 @@ if (sk->bound_device != sk2->bound_device) continue; - if(!sk2->rcv_saddr || !sk->rcv_saddr) { - if((!sk2_reuse) || (!sk_reuse)) { + if (!sk2->rcv_saddr || !sk->rcv_saddr) { + if ((!sk2_reuse) || (!sk_reuse)) { retval = 1; break; } - } else if(sk2->rcv_saddr == sk->rcv_saddr) { - if((!sk_reuse) || (!sk2_reuse)) { + } else if (sk2->rcv_saddr == sk->rcv_saddr) { + if ((!sk_reuse) || (!sk2_reuse)) { retval = 1; break; } @@ -160,8 +169,8 @@ { struct sock *sk = udp_hash[num & (UDP_HTABLE_SIZE - 1)]; - for(; sk != NULL; sk = sk->next) { - if(sk->num == num) + for (; sk != NULL; sk = sk->next) { + if (sk->num == num) return 1; } return 0; @@ -193,9 +202,9 @@ /* Is this one better than our best so far? */ size = 0; do { - if(++size >= best_size_so_far) + if (++size >= best_size_so_far) goto next; - } while((sk = sk->next) != NULL); + } while ((sk = sk->next) != NULL); best_size_so_far = size; best = result; next: @@ -234,8 +243,8 @@ skp = &udp_hash[num]; SOCKHASH_LOCK(); - while(*skp != NULL) { - if(*skp == sk) { + while (*skp != NULL) { + if (*skp == sk) { *skp = sk->next; break; } @@ -254,8 +263,8 @@ skp = &udp_hash[oldnum]; SOCKHASH_LOCK(); - while(*skp != NULL) { - if(*skp == sk) { + while (*skp != NULL) { + if (*skp == sk) { *skp = sk->next; break; } @@ -270,28 +279,29 @@ /* UDP is nearly always wildcards out the wazoo, it makes no sense to try * harder than this. -DaveM */ -__inline__ struct sock *udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, - struct device *dev) +__inline__ struct sock *udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, struct device *dev) { struct sock *sk, *result = NULL; unsigned short hnum = ntohs(dport); int badness = -1; - for(sk = udp_hash[hnum & (UDP_HTABLE_SIZE - 1)]; sk != NULL; sk = sk->next) { - if((sk->num == hnum) && !(sk->dead && (sk->state == TCP_CLOSE))) { + for (sk = udp_hash[hnum & (UDP_HTABLE_SIZE - 1)]; + sk != NULL; sk = sk->next) { + if ((sk->num == hnum) && !(sk->dead && + (sk->state == TCP_CLOSE))) { int score = 0; - if(sk->rcv_saddr) { - if(sk->rcv_saddr != daddr) + if (sk->rcv_saddr) { + if (sk->rcv_saddr != daddr) continue; score++; } - if(sk->daddr) { - if(sk->daddr != saddr) + if (sk->daddr) { + if (sk->daddr != saddr) continue; score++; } - if(sk->dummy_th.dest) { - if(sk->dummy_th.dest != sport) + if (sk->dummy_th.dest) { + if (sk->dummy_th.dest != sport) continue; score++; } @@ -303,10 +313,10 @@ else continue; /* mismatch--not this sock */ } - if(score == 4) { + if (score == 4) { result = sk; break; - } else if(score > badness) { + } else if (score > badness) { result = sk; badness = score; } @@ -329,38 +339,38 @@ hh[0] = udp_hash[hnum & (UDP_HTABLE_SIZE - 1)]; hh[1] = udp_hash[hpnum & (UDP_HTABLE_SIZE - 1)]; for (i = 0; i < 2; i++) { - for(sk = hh[i]; sk != NULL; sk = sk->next) { - if(sk->num == hnum || sk->num == hpnum) { + for (sk = hh[i]; sk != NULL; sk = sk->next) { + if (sk->num == hnum || sk->num == hpnum) { int score = 0; - if(sk->dead && (sk->state == TCP_CLOSE)) + if (sk->dead && (sk->state == TCP_CLOSE)) continue; - if(sk->rcv_saddr) { - if((sk->num != hpnum || sk->rcv_saddr != paddr) && + if (sk->rcv_saddr) { + if ((sk->num != hpnum || sk->rcv_saddr != paddr) && (sk->num != hnum || sk->rcv_saddr != daddr)) continue; score++; } - if(sk->daddr) { - if(sk->daddr != saddr) + if (sk->daddr) { + if (sk->daddr != saddr) continue; score++; } - if(sk->dummy_th.dest) { - if(sk->dummy_th.dest != sport) + if (sk->dummy_th.dest) { + if (sk->dummy_th.dest != sport) continue; score++; } /* If this socket is bound to a particular interface, * did the packet come in on it? */ - if(sk->bound_device) { + if (sk->bound_device) { if (sk->bound_device != dev) continue; score++; } - if(score == 4 && sk->num == hnum) { + if (score == 4 && sk->num == hnum) { result = sk; break; - } else if(score > badness && (sk->num == hpnum || sk->rcv_saddr)) { + } else if (score > badness && (sk->num == hpnum || sk->rcv_saddr)) { result = sk; badness = score; } @@ -381,27 +391,27 @@ { struct sock *s = sk; unsigned short hnum = ntohs(num); - for(; s; s = s->next) { - if ((s->num != hnum) || - (s->dead && (s->state == TCP_CLOSE)) || - (s->daddr && s->daddr!=raddr) || + for (; s; s = s->next) { + if ((s->num != hnum) || + (s->dead && (s->state == TCP_CLOSE)) || + (s->daddr && s->daddr != raddr) || (s->dummy_th.dest != rnum && s->dummy_th.dest != 0) || - ((s->bound_device) && (s->bound_device!=dev)) || - (s->rcv_saddr && s->rcv_saddr != laddr)) + ((s->bound_device) && (s->bound_device!=dev)) || + (s->rcv_saddr && s->rcv_saddr != laddr)) continue; break; - } - return s; + } + return s; } -#define min(a,b) ((a)<(b)?(a):(b)) +#define min(a, b) ((a) < (b) ? (a) : (b)) /* * This routine is called by the ICMP module when it gets some * sort of error condition. If err < 0 then the socket should * be closed and the error returned to the user. If err > 0 - * it's just the icmp type << 8 | icmp code. + * it's just the icmp type << 8 | icmp code. * Header points to the ip header of the error packet. We move * on past this. Then (as it used to claim before adjustment) * header points to the first 8 bytes of the udp header. We need @@ -416,50 +426,47 @@ /* * Find the 8 bytes of post IP header ICMP included for us - */ - - if(lendest, saddr, uh->source, NULL); - if (sk == NULL) - return; /* No socket for error */ - - if (type == ICMP_SOURCE_QUENCH) - { /* Slow down! */ - if (sk->cong_window > 1) + if (sk == NULL) + return; /* No socket for error */ + + if (type == ICMP_SOURCE_QUENCH) { /* Slow down! */ + if (sk->cong_window > 1) sk->cong_window = sk->cong_window/2; return; } - if (type == ICMP_PARAMETERPROB) - { + if (type == ICMP_PARAMETERPROB) { sk->err = EPROTO; sk->error_report(sk); return; } - + /* - * Various people wanted BSD UDP semantics. Well they've come + * Various people wanted BSD UDP semantics. Well they've come * back out because they slow down response to stuff like dead * or unreachable name servers and they screw term users something - * chronic. Oh and it violates RFC1122. So basically fix your + * chronic. Oh and it violates RFC1122. So basically fix your * client code people. */ - + /* RFC1122: OK. Passes ICMP errors back to application, as per */ /* 4.1.3.3. */ /* After the comment above, that should be no surprise. */ - if(code<=NR_ICMP_UNREACH && icmp_err_convert[code].fatal) - { + if (code <= NR_ICMP_UNREACH && icmp_err_convert[code].fatal) { /* * 4.x BSD compatibility item. Break RFC1122 to * get BSD socket semantics. */ - if(sk->bsdism && sk->state!=TCP_ESTABLISHED) + if (sk->bsdism && sk->state != TCP_ESTABLISHED) return; sk->err = icmp_err_convert[code].errno; sk->error_report(sk); @@ -469,10 +476,10 @@ static unsigned short udp_check(struct udphdr *uh, int len, unsigned long saddr, unsigned long daddr, unsigned long base) { - return(csum_tcpudp_magic(saddr, daddr, len, IPPROTO_UDP, base)); + return csum_tcpudp_magic(saddr, daddr, len, IPPROTO_UDP, base); } -struct udpfakehdr +struct udpfakehdr { struct udphdr uh; __u32 daddr; @@ -482,73 +489,68 @@ }; /* - * Copy and checksum a UDP packet from user space into a buffer. We still have to do the planning to - * get ip_build_xmit to spot direct transfer to network card and provide an additional callback mode - * for direct user->board I/O transfers. That one will be fun. + * Copy and checksum a UDP packet from user space into a buffer. We still + * have to do the planning to get ip_build_xmit to spot direct transfer to + * network card and provide an additional callback mode for direct + * user->board I/O transfers. That one will be fun. */ - -static void udp_getfrag(const void *p, __u32 saddr, char * to, unsigned int offset, unsigned int fraglen) + +static void udp_getfrag(const void *p, __u32 saddr, char * to, unsigned int offset, unsigned int fraglen) { struct udpfakehdr *ufh = (struct udpfakehdr *)p; const char *src; char *dst; unsigned int len; - if (offset) - { + if (offset) { len = fraglen; - src = ufh->from+(offset-sizeof(struct udphdr)); - dst = to; - } - else - { - len = fraglen-sizeof(struct udphdr); - src = ufh->from; - dst = to+sizeof(struct udphdr); + src = ufh->from + (offset - sizeof (struct udphdr)); + dst = to; + } else { + len = fraglen - sizeof (struct udphdr); + src = ufh->from; + dst = to + sizeof (struct udphdr); } ufh->wcheck = csum_partial_copy_fromuser(src, dst, len, ufh->wcheck); - if (offset == 0) - { - ufh->wcheck = csum_partial((char *)ufh, sizeof(struct udphdr), - ufh->wcheck); - ufh->uh.check = csum_tcpudp_magic(saddr, ufh->daddr, - ntohs(ufh->uh.len), - IPPROTO_UDP, ufh->wcheck); + if (offset == 0) { + ufh->wcheck = csum_partial((char *)ufh, sizeof (struct udphdr), + ufh->wcheck); + ufh->uh.check = csum_tcpudp_magic(saddr, ufh->daddr, + ntohs(ufh->uh.len), + IPPROTO_UDP, ufh->wcheck); if (ufh->uh.check == 0) ufh->uh.check = -1; - memcpy(to, ufh, sizeof(struct udphdr)); + memcpy(to, ufh, sizeof (struct udphdr)); } } /* - * Unchecksummed UDP is sufficiently critical to stuff like ATM video conferencing - * that we use two routines for this for speed. Probably we ought to have a CONFIG_FAST_NET - * set for >10Mb/second boards to activate this sort of coding. Timing needed to verify if - * this is a valid decision. + * Unchecksummed UDP is sufficiently critical to stuff like ATM video + * conferencing that we use two routines for this for speed. Probably we + * ought to have a CONFIG_FAST_NET set for >10Mb/second boards to activate + * this sort of coding. Timing needed to verify if this is a valid + * decision. */ - -static void udp_getfrag_nosum(const void *p, __u32 saddr, char * to, unsigned int offset, unsigned int fraglen) + +static void udp_getfrag_nosum(const void *p, __u32 saddr, char * to, unsigned int offset, unsigned int fraglen) { struct udpfakehdr *ufh = (struct udpfakehdr *)p; const char *src; char *dst; unsigned int len; - if (offset) - { + if (offset) { len = fraglen; - src = ufh->from+(offset-sizeof(struct udphdr)); - dst = to; - } - else - { - len = fraglen-sizeof(struct udphdr); - src = ufh->from; - dst = to+sizeof(struct udphdr); - } - memcpy_fromfs(dst,src,len); - if (offset == 0) - memcpy(to, ufh, sizeof(struct udphdr)); + src = ufh->from + (offset - sizeof (struct udphdr)); + dst = to; + } else { + len = fraglen - sizeof (struct udphdr); + src = ufh->from; + dst = to + sizeof (struct udphdr); + } + memcpy_fromfs(dst, src, len); + if (offset == 0) + memcpy(to, ufh, sizeof (struct udphdr)); } @@ -558,13 +560,13 @@ static int udp_send(struct sock *sk, struct sockaddr_in *sin, const unsigned char *from, int len, int rt, - __u32 saddr, int noblock) + __u32 saddr, int noblock) { - int ulen = len + sizeof(struct udphdr); + int ulen = len + sizeof (struct udphdr); int a; struct udpfakehdr ufh; - - if(ulen>65535-sizeof(struct iphdr)) + + if (ulen > 65535 - sizeof (struct iphdr)) return -EMSGSIZE; ufh.uh.source = sk->dummy_th.source; @@ -586,14 +588,14 @@ * easily, without adding system calls. */ struct sockaddr_in *sinfrom = - (struct sockaddr_in *) sin->sin_zero; + (struct sockaddr_in *)sin->sin_zero; if (!suser()) - return(-EPERM); + return -EPERM; if (sinfrom->sin_family && sinfrom->sin_family != AF_INET) - return(-EINVAL); + return -EINVAL; if (sinfrom->sin_port == 0) - return(-EINVAL); + return -EINVAL; saddr = sinfrom->sin_addr.s_addr; ufh.uh.source = sinfrom->sin_port; } @@ -604,13 +606,15 @@ /* (MAY) and it defaults to on (MUST). Almost makes up for the */ /* violation above. -- MS */ - if(sk->no_check) - a = ip_build_xmit(sk, udp_getfrag_nosum, &ufh, ulen, - sin->sin_addr.s_addr, saddr, sk->opt, rt, IPPROTO_UDP, noblock); + if (sk->no_check) + a = ip_build_xmit(sk, udp_getfrag_nosum, &ufh, ulen, + sin->sin_addr.s_addr, saddr, sk->opt, rt, + IPPROTO_UDP, noblock); else - a = ip_build_xmit(sk, udp_getfrag, &ufh, ulen, - sin->sin_addr.s_addr, saddr, sk->opt, rt, IPPROTO_UDP, noblock); - if(a<0) + a = ip_build_xmit(sk, udp_getfrag, &ufh, ulen, + sin->sin_addr.s_addr, saddr, sk->opt, rt, + IPPROTO_UDP, noblock); + if (a < 0) return a; udp_statistics.UdpOutDatagrams++; return len; @@ -622,51 +626,48 @@ { struct sockaddr_in sin; int tmp; - __u32 saddr=0; + __u32 saddr = 0; - /* + /* * Check the flags. We support no flags for UDP sending */ #ifdef CONFIG_IP_TRANSPARENT_PROXY - if (flags&~(MSG_DONTROUTE|MSG_PROXY)) + if (flags & ~(MSG_DONTROUTE | MSG_PROXY)) #else - if (flags&~MSG_DONTROUTE) + if (flags & ~MSG_DONTROUTE) #endif - return(-EINVAL); + return -EINVAL; /* - * Get and verify the address. + * Get and verify the address. */ - - if (usin) - { - if (addr_len < sizeof(sin)) - return(-EINVAL); - if (usin->sin_family && usin->sin_family != AF_INET) - return(-EINVAL); - if (usin->sin_port == 0) - return(-EINVAL); - } - else - { + + if (usin) { + if (addr_len < sizeof (sin)) + return -EINVAL; + if (usin->sin_family && usin->sin_family != AF_INET) + return -EINVAL; + if (usin->sin_port == 0) + return -EINVAL; + } else { #ifdef CONFIG_IP_TRANSPARENT_PROXY /* We need to provide a sockaddr_in when using MSG_PROXY. */ - if (flags&MSG_PROXY) - return(-EINVAL); + if (flags & MSG_PROXY) + return -EINVAL; #endif - if (sk->state != TCP_ESTABLISHED) - return(-EINVAL); + if (sk->state != TCP_ESTABLISHED) + return -EINVAL; sin.sin_family = AF_INET; sin.sin_port = sk->dummy_th.dest; sin.sin_addr.s_addr = sk->daddr; usin = &sin; - } - - /* - * BSD socket semantics. You must set SO_BROADCAST to permit - * broadcasting of data. - */ - + } + + /* + * BSD socket semantics. You must set SO_BROADCAST to permit + * broadcasting of data. + */ + /* RFC1122: OK. Allows the application to select the specific */ /* source address for an outgoing packet (MUST) as per 4.1.3.5. */ /* Optional addition: a mechanism for telling the application what */ @@ -677,11 +678,12 @@ /* af_inet.c checks these. It does need work to allow BSD style */ /* bind to multicast as is done by xntpd */ - if(usin->sin_addr.s_addr==INADDR_ANY) - usin->sin_addr.s_addr=ip_my_addr(); - - if(!sk->broadcast && ip_chk_addr(usin->sin_addr.s_addr)==IS_BROADCAST) - return -EACCES; /* Must turn broadcast on first */ + if (usin->sin_addr.s_addr == INADDR_ANY) + usin->sin_addr.s_addr = ip_my_addr(); + + if (!sk->broadcast && + ip_chk_addr(usin->sin_addr.s_addr) == IS_BROADCAST) + return -EACCES; /* Must turn broadcast on first */ lock_sock(sk); @@ -690,40 +692,40 @@ /* The datagram has been sent off. Release the socket. */ release_sock(sk); - return(tmp); + return tmp; } /* * Temporary */ - -static int udp_sendmsg(struct sock *sk, struct msghdr *msg, int len, int noblock, - int flags) + +static int udp_sendmsg(struct sock *sk, struct msghdr *msg, int len, int noblock, int flags) { - if(msg->msg_iovlen==1) - return udp_sendto(sk,msg->msg_iov[0].iov_base,len, noblock, flags, msg->msg_name, msg->msg_namelen); - else - { + if (msg->msg_iovlen == 1) + return udp_sendto(sk, msg->msg_iov[0].iov_base, len, noblock, + flags, msg->msg_name, msg->msg_namelen); + else { /* * For awkward cases we linearise the buffer first. In theory this is only frames * whose iovec's don't split on 4 byte boundaries, and soon encrypted stuff (to keep * skip happy). We are a bit more general about it. */ - + unsigned char *buf; int fs; int err; - if(len>65515) + if (len > 65515) return -EMSGSIZE; - buf=kmalloc(len, GFP_KERNEL); - if(buf==NULL) + buf = kmalloc(len, GFP_KERNEL); + if (buf == NULL) return -ENOBUFS; memcpy_fromiovec(buf, msg->msg_iov, len); - fs=get_fs(); + fs = get_fs(); set_fs(get_ds()); - err=udp_sendto(sk,buf,len, noblock, flags, msg->msg_name, msg->msg_namelen); + err = udp_sendto(sk, buf, len, noblock, flags, msg->msg_name, + msg->msg_namelen); set_fs(fs); - kfree_s(buf,len); + kfree_s(buf, len); return err; } } @@ -731,106 +733,105 @@ /* * IOCTL requests applicable to the UDP protocol */ - + int udp_ioctl(struct sock *sk, int cmd, unsigned long arg) { int err; - switch(cmd) + switch (cmd) { + case TIOCOUTQ: { - case TIOCOUTQ: - { - unsigned long amount; - - if (sk->state == TCP_LISTEN) return(-EINVAL); - amount = sock_wspace(sk); - err=verify_area(VERIFY_WRITE,(void *)arg, - sizeof(unsigned long)); - if(err) - return(err); - put_fs_long(amount,(unsigned long *)arg); - return(0); - } + unsigned long amount; - case TIOCINQ: - { - struct sk_buff *skb; - unsigned long amount; - - if (sk->state == TCP_LISTEN) return(-EINVAL); - amount = 0; - skb = skb_peek(&sk->receive_queue); - if (skb != NULL) { - /* - * We will only return the amount - * of this packet since that is all - * that will be read. - */ - amount = skb->len-sizeof(struct udphdr); - } - err=verify_area(VERIFY_WRITE,(void *)arg, - sizeof(unsigned long)); - if(err) - return(err); - put_fs_long(amount,(unsigned long *)arg); - return(0); + if (sk->state == TCP_LISTEN) + return -EINVAL; + amount = sock_wspace(sk); + err = verify_area(VERIFY_WRITE, (void *)arg, + sizeof (unsigned long)); + if (err) + return err; + put_fs_long(amount, (unsigned long *)arg); + return 0; + } + + case TIOCINQ: + { + struct sk_buff *skb; + unsigned long amount; + + if (sk->state == TCP_LISTEN) + return -EINVAL; + amount = 0; + skb = skb_peek(&sk->receive_queue); + if (skb != NULL) { + /* + * We will only return the amount + * of this packet since that is all + * that will be read. + */ + amount = skb->len - sizeof (struct udphdr); } + err = verify_area(VERIFY_WRITE, (void *)arg, + sizeof (unsigned long)); + if (err) + return err; + put_fs_long(amount, (unsigned long *)arg); + return 0; + } - default: - return(-EINVAL); + default: + return -EINVAL; } - return(0); + return 0; } - /* - * This should be easy, if there is something there we\ - * return it, otherwise we block. + * This should be easy, if there is something there we\ + * return it, otherwise we block. */ int udp_recvmsg(struct sock *sk, struct msghdr *msg, int len, - int noblock, int flags,int *addr_len) + int noblock, int flags, int *addr_len) { - int copied = 0; - int truesize; - struct sk_buff *skb; - int er; - struct sockaddr_in *sin=(struct sockaddr_in *)msg->msg_name; + int copied = 0; + int truesize; + struct sk_buff *skb; + int er; + struct sockaddr_in *sin = (struct sockaddr_in *)msg->msg_name; /* * Check any passed addresses */ - - if (addr_len) - *addr_len=sizeof(*sin); - + + if (addr_len) + *addr_len = sizeof (*sin); + /* * From here the generic datagram does a lot of the work. Come * the finished NET3, it will do _ALL_ the work! */ - - skb=skb_recv_datagram(sk,flags,noblock,&er); - if(skb==NULL) - return er; - - truesize = skb->len - sizeof(struct udphdr); - copied = min(len, truesize); - - /* - * FIXME : should use udp header size info value - */ - - skb_copy_datagram_iovec(skb,sizeof(struct udphdr),msg->msg_iov,copied); - sk->stamp=skb->stamp; + + skb = skb_recv_datagram(sk, flags, noblock, &er); + if (skb == NULL) + return er; + + truesize = skb->len - sizeof (struct udphdr); + copied = min(len, truesize); + + /* + * FIXME : should use udp header size info value + */ + + skb_copy_datagram_iovec(skb, sizeof (struct udphdr), + msg->msg_iov, copied); + sk->stamp = skb->stamp; /* Copy the address. */ - if (sin) - { + if (sin) { sin->sin_family = AF_INET; sin->sin_port = skb->h.uh->source; sin->sin_addr.s_addr = skb->daddr; #ifdef CONFIG_IP_TRANSPARENT_PROXY - if (flags&MSG_PROXY) - { + if (flags&MSG_PROXY) { /* * We map the first 8 bytes of a second sockaddr_in * into the last 8 (unused) bytes of a sockaddr_in. @@ -838,39 +839,41 @@ * easily, without adding system calls. */ struct sockaddr_in *sinto = - (struct sockaddr_in *) sin->sin_zero; + (struct sockaddr_in *)sin->sin_zero; sinto->sin_family = AF_INET; sinto->sin_port = skb->h.uh->dest; sinto->sin_addr.s_addr = skb->saddr; } #endif - } - - skb_free_datagram(sk, skb); - return(copied); + } + + skb_free_datagram(sk, skb); + return copied; } int udp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len) { struct rtable *rt; - if (addr_len < sizeof(*usin)) - return(-EINVAL); + if (addr_len < sizeof (*usin)) + return -EINVAL; - if (usin->sin_family && usin->sin_family != AF_INET) - return(-EAFNOSUPPORT); - if (usin->sin_addr.s_addr==INADDR_ANY) - usin->sin_addr.s_addr=ip_my_addr(); - - if(!sk->broadcast && ip_chk_addr(usin->sin_addr.s_addr)==IS_BROADCAST) - return -EACCES; /* Must turn broadcast on first */ - - rt=ip_rt_route((__u32)usin->sin_addr.s_addr, sk->localroute, sk->bound_device); - if (rt==NULL) - return -ENETUNREACH; - if(!sk->saddr) - sk->saddr = rt->rt_src; /* Update source address */ - if(!sk->rcv_saddr) + if (usin->sin_family && usin->sin_family != AF_INET) + return -EAFNOSUPPORT; + if (usin->sin_addr.s_addr == INADDR_ANY) + usin->sin_addr.s_addr = ip_my_addr(); + + if (!sk->broadcast && + ip_chk_addr(usin->sin_addr.s_addr) == IS_BROADCAST) + return -EACCES; /* Must turn broadcast on first */ + + rt = ip_rt_route((__u32)usin->sin_addr.s_addr, + sk->localroute, sk->bound_device); + if (rt == NULL) + return -ENETUNREACH; + if (!sk->saddr) + sk->saddr = rt->rt_src; /* Update source address */ + if (!sk->rcv_saddr) sk->rcv_saddr = rt->rt_src; sk->daddr = usin->sin_addr.s_addr; sk->dummy_th.dest = usin->sin_port; @@ -878,7 +881,7 @@ if (sk->ip_route_cache) ip_rt_put(sk->ip_route_cache); sk->ip_route_cache = rt; - return(0); + return 0; } @@ -901,7 +904,7 @@ /* I assume this includes the IP options, as per RFC1122 (4.1.3.2). */ /* If not, please let me know. -- MS */ - if (__sock_queue_rcv_skb(sk,skb)<0) { + if (__sock_queue_rcv_skb(sk, skb) < 0) { udp_statistics.UdpInErrors++; ip_statistics.IpInDiscards++; ip_statistics.IpInDelivers--; @@ -959,8 +962,9 @@ SOCKHASH_LOCK(); sk = udp_hash[ntohs(uh->dest) & (UDP_HTABLE_SIZE - 1)]; - sk = udp_v4_mcast_next(sk, uh->dest, saddr, uh->source, daddr, skb->dev); - if(sk) { + sk = udp_v4_mcast_next(sk, uh->dest, saddr, uh->source, + daddr, skb->dev); + if (sk) { struct sock *sknext = NULL; do { @@ -968,32 +972,32 @@ sknext = udp_v4_mcast_next(sk->next, uh->dest, saddr, uh->source, daddr, skb->dev); - if(sknext) + if (sknext) skb1 = skb_clone(skb, GFP_ATOMIC); - if(skb1) + if (skb1) udp_deliver(sk, skb1); sk = sknext; - } while(sknext); + } while (sknext); given = 1; } SOCKHASH_UNLOCK(); - if(!given) + if (!given) kfree_skb(skb, FREE_READ); return 0; } #endif /* - * All we need to do is get the socket, and then do a checksum. + * All we need to do is get the socket, and then do a checksum. */ - + int udp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt, __u32 daddr, unsigned short len, __u32 saddr, int redo, struct inet_protocol *protocol) { - struct sock *sk; - struct udphdr *uh; + struct sock *sk; + struct udphdr *uh; unsigned short ulen; int addr_type; @@ -1012,29 +1016,28 @@ */ addr_type = IS_MYADDR; - if(!dev || dev->pa_addr!=daddr) - addr_type=ip_chk_addr(daddr); - + if (!dev || dev->pa_addr != daddr) + addr_type = ip_chk_addr(daddr); + /* * Get the header. */ - - uh = (struct udphdr *) skb->h.uh; - - ip_statistics.IpInDelivers++; + + uh = (struct udphdr *)skb->h.uh; + + ip_statistics.IpInDelivers++; /* * Validate the packet and the UDP length. */ - + ulen = ntohs(uh->len); - - if (ulen > len || len < sizeof(*uh) || ulen < sizeof(*uh)) - { + + if (ulen > len || len < sizeof (*uh) || ulen < sizeof (*uh)) { NETDEBUG(printk("UDP: short packet: %d/%d\n", ulen, len)); udp_statistics.UdpInErrors++; kfree_skb(skb, FREE_WRITE); - return(0); + return 0; } /* RFC1122 warning: According to 4.1.3.6, we MUST discard any */ @@ -1044,13 +1047,13 @@ /* FIXME list for IP, though, so I wouldn't worry about it. */ /* (That's the Right Place to do it, IMHO.) -- MS */ - if (uh->check && ( - ( (skb->ip_summed == CHECKSUM_HW) && udp_check(uh, len, saddr, daddr, skb->csum ) ) || - ( (skb->ip_summed == CHECKSUM_NONE) && udp_check(uh, len, saddr, daddr,csum_partial((char*)uh, len, 0))) - /* skip if CHECKSUM_UNNECESSARY */ - ) - ) - { + /* Skip csum_partial if CHECKSUM_UNNECESSARY */ + if (uh->check && + (((skb->ip_summed == CHECKSUM_HW) && + udp_check(uh, len, saddr, daddr, skb->csum)) || + ((skb->ip_summed == CHECKSUM_NONE) && + udp_check(uh, len, saddr, daddr, + csum_partial((char *)uh, len, 0))))) { /* wants to know, who sent it, to go and stomp on the garbage sender... */ @@ -1058,44 +1061,43 @@ /* the network is concerned, anyway) as per 4.1.3.4 (MUST). */ NETDEBUG(printk("UDP: bad checksum. From %08lX:%d to %08lX:%d ulen %d\n", - ntohl(saddr),ntohs(uh->source), - ntohl(daddr),ntohs(uh->dest), - ulen)); + ntohl(saddr), ntohs(uh->source), + ntohl(daddr), ntohs(uh->dest), + ulen)); udp_statistics.UdpInErrors++; kfree_skb(skb, FREE_WRITE); - return(0); + return 0; } /* - * These are supposed to be switched. + * These are supposed to be switched. */ - + skb->daddr = saddr; skb->saddr = daddr; - len=ulen; + len = ulen; skb->dev = dev; - skb_trim(skb,len); + skb_trim(skb, len); #ifdef CONFIG_IP_MULTICAST - if (addr_type==IS_BROADCAST || addr_type==IS_MULTICAST) + if (addr_type == IS_BROADCAST || addr_type == IS_MULTICAST) return udp_v4_mcast_deliver(skb, uh, saddr, daddr); #endif #ifdef CONFIG_IP_TRANSPARENT_PROXY - if(skb->redirport) + if (skb->redirport) sk = udp_v4_proxy_lookup(saddr, uh->source, daddr, uh->dest, dev->pa_addr, skb->redirport, dev); else #endif sk = udp_v4_lookup(saddr, uh->source, daddr, uh->dest, dev); - - if (sk == NULL) - { - udp_statistics.UdpNoPorts++; - if (addr_type != IS_BROADCAST && addr_type != IS_MULTICAST) - { - icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0, dev); + + if (sk == NULL) { + udp_statistics.UdpNoPorts++; + if (addr_type != IS_BROADCAST && addr_type != IS_MULTICAST) { + icmp_send(skb, ICMP_DEST_UNREACH, + ICMP_PORT_UNREACH, 0, dev, 0); } /* * Hmm. We got an UDP broadcast to a port to which we @@ -1103,8 +1105,8 @@ */ skb->sk = NULL; kfree_skb(skb, FREE_WRITE); - return(0); - } + return 0; + } udp_deliver(sk, skb); return 0; } diff -urN linux-2.0.40-rc6/net/netsyms.c linux-2.0.40-rc7/net/netsyms.c --- linux-2.0.40-rc6/net/netsyms.c 1999-06-13 10:21:04.000000000 -0700 +++ linux-2.0.40-rc7/net/netsyms.c 2004-01-15 07:19:51.000000000 -0800 @@ -166,6 +166,7 @@ X(kfree_skb), X(skb_clone), X(skb_copy), + X(skb_pad), X(dev_alloc_skb), X(dev_kfree_skb), X(skb_device_unlock),