prepare for the transition to linux 2.6.22 - make it possible to override the kernel version in the target makefile

SVN-Revision: 7644
owl
Felix Fietkau 2007-06-16 01:56:04 +00:00
parent 4f16e9cc3e
commit f019ac4dc9
62 changed files with 44816 additions and 29 deletions

View File

@ -11,9 +11,11 @@ include $(INCLUDE_DIR)/host.mk
include $(INCLUDE_DIR)/kernel.mk
include $(INCLUDE_DIR)/prereq.mk
LINUX_CONFIG ?= ./config/default
GENERIC_LINUX_CONFIG:=$(GENERIC_PLATFORM_DIR)/config-$(shell [ -f "$(GENERIC_PLATFORM_DIR)/config-$(KERNEL_PATCHVER)" ] && echo "$(KERNEL_PATCHVER)" || echo template )
LINUX_CONFIG_DIR ?= ./config$(shell [ -d "./config-$(KERNEL_PATCHVER)" ] && printf -- "-$(KERNEL_PATCHVER)" || true )
LINUX_CONFIG ?= $(LINUX_CONFIG_DIR)/default
-include $(TOPDIR)/target/linux/generic-$(KERNEL)/config-template
-include $(GENERIC_LINUX_CONFIG)
-include $(LINUX_CONFIG)
ifneq ($(CONFIG_ATM),)
@ -166,9 +168,9 @@ prepare: $(LINUX_DIR)/.configured
compile: $(LINUX_DIR)/.modules
menuconfig: $(LINUX_DIR)/.prepared FORCE
$(call Kernel/Configure)
$(SCRIPT_DIR)/config.pl '+' $(GENERIC_PLATFORM_DIR)/config-template $(LINUX_CONFIG) > $(LINUX_DIR)/.config
$(SCRIPT_DIR)/config.pl '+' $(GENERIC_LINUX_CONFIG) $(LINUX_CONFIG) > $(LINUX_DIR)/.config
$(MAKE) -C $(LINUX_DIR) $(KERNEL_MAKEOPTS) menuconfig
$(SCRIPT_DIR)/config.pl '>' $(GENERIC_PLATFORM_DIR)/config-template $(LINUX_DIR)/.config > $(LINUX_CONFIG)
$(SCRIPT_DIR)/config.pl '>' $(GENERIC_LINUX_CONFIG) $(LINUX_DIR)/.config > $(LINUX_CONFIG)
install: $(LINUX_DIR)/.image

View File

@ -47,9 +47,9 @@ define Kernel/Configure/2.6
endef
define Kernel/Configure/Default
@if [ -f "./config/profile-$(PROFILE)" ]; then \
$(SCRIPT_DIR)/config.pl '+' $(GENERIC_PLATFORM_DIR)/config-template '+' $(LINUX_CONFIG) ./config/profile-$(PROFILE) > $(LINUX_DIR)/.config; \
$(SCRIPT_DIR)/config.pl '+' $(GENERIC_LINUX_CONFIG) '+' $(LINUX_CONFIG) ./config/profile-$(PROFILE) > $(LINUX_DIR)/.config; \
else \
$(SCRIPT_DIR)/config.pl '+' $(GENERIC_PLATFORM_DIR)/config-template $(LINUX_CONFIG) > $(LINUX_DIR)/.config; \
$(SCRIPT_DIR)/config.pl '+' $(GENERIC_LINUX_CONFIG) $(LINUX_CONFIG) > $(LINUX_DIR)/.config; \
fi
$(call Kernel/Configure/$(KERNEL))
rm -rf $(KERNEL_BUILD_DIR)/modules

View File

@ -26,8 +26,11 @@ else
KERNEL_CROSS:=$(TARGET_CROSS)
endif
KERNEL_PATCHVER:=$(shell echo $(LINUX_VERSION) | cut -d. -f1,2,3 | cut -d- -f1)
PLATFORM_DIR := $(TOPDIR)/target/linux/$(BOARD)-$(KERNEL)
PATCH_DIR := ./patches$(shell [ -d "./patches-$(KERNEL_PATCHVER)" ] && printf -- "-$(KERNEL_PATCHVER)" || true )
GENERIC_PLATFORM_DIR := $(TOPDIR)/target/linux/generic-$(KERNEL)
GENERIC_PATCH_DIR := $(GENERIC_PLATFORM_DIR)/patches$(shell [ -d "$(GENERIC_PLATFORM_DIR)/patches-$(KERNEL_PATCHVER)" ] && printf -- "-$(KERNEL_PATCHVER)" || true )
KERNEL_BUILD_DIR:=$(BUILD_DIR)/linux-$(KERNEL)-$(BOARD)
LINUX_DIR := $(KERNEL_BUILD_DIR)/linux-$(LINUX_VERSION)
@ -37,10 +40,11 @@ else
LINUX_KERNEL:=$(KERNEL_BUILD_DIR)/vmlinux
LINUX_SOURCE:=linux-$(LINUX_VERSION).tar.bz2
LINUX_SITE:=http://www.us.kernel.org/pub/linux/kernel/v$(KERNEL) \
http://www.us.kernel.org/pub/linux/kernel/v$(KERNEL) \
http://www.kernel.org/pub/linux/kernel/v$(KERNEL) \
http://www.de.kernel.org/pub/linux/kernel/v$(KERNEL)
TESTING:=$(if $(findstring -rc,$(LINUX_VERSION)),/testing,)
LINUX_SITE:=http://www.us.kernel.org/pub/linux/kernel/v$(KERNEL)$(TESTING) \
http://www.us.kernel.org/pub/linux/kernel/v$(KERNEL)$(TESTING) \
http://www.kernel.org/pub/linux/kernel/v$(KERNEL)$(TESTING) \
http://www.de.kernel.org/pub/linux/kernel/v$(KERNEL)$(TESTING)
PKG_BUILD_DIR ?= $(KERNEL_BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)

View File

@ -46,11 +46,11 @@ endif
define Kernel/Patch/Default
if [ -d $(GENERIC_PLATFORM_DIR)/files ]; then $(CP) $(GENERIC_PLATFORM_DIR)/files/* $(LINUX_DIR)/; fi
if [ -d ./files ]; then $(CP) ./files/* $(LINUX_DIR)/; fi
$(if $(strip $(QUILT)),$(call Quilt/Patch,$(GENERIC_PLATFORM_DIR)/patches,generic/), \
if [ -d $(GENERIC_PLATFORM_DIR)/patches ]; then $(PATCH) $(LINUX_DIR) $(GENERIC_PLATFORM_DIR)/patches; fi \
$(if $(strip $(QUILT)),$(call Quilt/Patch,$(GENERIC_PATCH_DIR),generic/), \
if [ -d $(GENERIC_PATCH_DIR) ]; then $(PATCH) $(LINUX_DIR) $(GENERIC_PATCH_DIR); fi \
)
$(if $(strip $(QUILT)),$(call Quilt/Patch,./patches,platform/), \
if [ -d ./patches ]; then $(PATCH) $(LINUX_DIR) ./patches; fi \
$(if $(strip $(QUILT)),$(call Quilt/Patch,$(PATCH_DIR),platform/), \
if [ -d $(PATCH_DIR) ]; then $(PATCH) $(LINUX_DIR) $(PATCH_DIR); fi \
)
$(if $(strip $(QUILT)),touch $(PKG_BUILD_DIR)/.quilt_used)
endef
@ -79,8 +79,8 @@ define Quilt/Refresh/Kernel
echo "All kernel patches must start with either generic/ or platform/"; \
false; \
}
$(call Quilt/RefreshDir,$(GENERIC_PLATFORM_DIR)/patches,generic/)
$(call Quilt/RefreshDir,./patches,platform/)
$(call Quilt/RefreshDir,$(GENERIC_PATCH_DIR),generic/)
$(call Quilt/RefreshDir,$(PATCH_DIR),platform/)
endef
quilt-check: $(STAMP_PREPARED) FORCE

View File

@ -3,6 +3,7 @@ CONFIG_32BIT=y
# CONFIG_64BIT_PHYS_ADDR is not set
CONFIG_ADM5120_GPIO=y
CONFIG_ADM5120_NR_UARTS=2
# CONFIG_ATM_DRIVERS is not set
# CONFIG_ARCH_HAS_ILOG2_U32 is not set
# CONFIG_ARCH_HAS_ILOG2_U64 is not set
CONFIG_BASE_SMALL=0
@ -62,7 +63,7 @@ CONFIG_GENERIC_GPIO=y
# CONFIG_GEN_RTC is not set
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
CONFIG_HID=y
CONFIG_HID=m
CONFIG_HWMON=y
# CONFIG_HWMON_DEBUG_CHIP is not set
CONFIG_HW_HAS_PCI=y
@ -96,6 +97,7 @@ CONFIG_JFFS2_SUMMARY=y
# CONFIG_JOLIET is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_MACH_ALCHEMY is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MACH_JAZZ is not set
# CONFIG_MACH_VR41XX is not set
@ -175,7 +177,9 @@ CONFIG_MTD_NAND=y
# CONFIG_MTD_NAND_DISKONCHIP is not set
# CONFIG_MTD_NAND_ECC_SMC is not set
CONFIG_MTD_NAND_IDS=y
# CONFIG_MTD_NAND_MUSEUM_IDS is not set
# CONFIG_MTD_NAND_NANDSIM is not set
# CONFIG_MTD_NAND_PLATFORM is not set
CONFIG_MTD_NAND_RB100=y
# CONFIG_MTD_NAND_VERIFY_WRITE is not set
# CONFIG_MTD_OBSOLETE_CHIPS is not set
@ -199,6 +203,7 @@ CONFIG_NET_KEY=y
# CONFIG_NET_PKTGEN is not set
CONFIG_NET_SCH_FIFO=y
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_NETDEV_1000 is not set
# CONFIG_PAGE_SIZE_16KB is not set
CONFIG_PAGE_SIZE_4KB=y
# CONFIG_PAGE_SIZE_64KB is not set

View File

@ -3,6 +3,7 @@ CONFIG_32BIT=y
# CONFIG_64BIT_PHYS_ADDR is not set
CONFIG_ADM5120_GPIO=y
CONFIG_ADM5120_NR_UARTS=2
# CONFIG_ATM_DRIVERS is not set
# CONFIG_ARCH_HAS_ILOG2_U32 is not set
# CONFIG_ARCH_HAS_ILOG2_U64 is not set
CONFIG_BASE_SMALL=0
@ -60,9 +61,9 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_GENERIC_GPIO=y
# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
# CONFIG_GEN_RTC is not set
CONFIG_HID=m
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
CONFIG_HID=y
CONFIG_HWMON=y
# CONFIG_HWMON_DEBUG_CHIP is not set
CONFIG_HW_HAS_PCI=y
@ -96,6 +97,7 @@ CONFIG_JFFS2_SUMMARY=y
# CONFIG_JOLIET is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_MACH_ALCHEMY is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MACH_JAZZ is not set
# CONFIG_MACH_VR41XX is not set
@ -194,6 +196,7 @@ CONFIG_NET_KEY=y
# CONFIG_NET_PKTGEN is not set
CONFIG_NET_SCH_FIFO=y
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_NETDEV_1000 is not set
# CONFIG_PAGE_SIZE_16KB is not set
CONFIG_PAGE_SIZE_4KB=y
# CONFIG_PAGE_SIZE_64KB is not set

View File

@ -4,6 +4,7 @@ CONFIG_4xx=y
# CONFIG_6xx is not set
# CONFIG_8139TOO is not set
# CONFIG_8xx is not set
# CONFIG_ATM_DRIVERS is not set
# CONFIG_BAMBOO is not set
# CONFIG_E200 is not set
# CONFIG_E500 is not set
@ -65,6 +66,7 @@ CONFIG_JFFS2_FS_DEBUG=0
CONFIG_KERNEL_START=0xc0000000
# CONFIG_KEXEC is not set
CONFIG_LOWMEM_SIZE=0x30000000
# CONFIG_MACINTOSH_DRIVERS is not set
CONFIG_MATH_EMULATION=y
CONFIG_MINI_FO=y
CONFIG_MTD=y
@ -123,6 +125,7 @@ CONFIG_MTD_SPLIT_ROOTFS=y
# CONFIG_NATSEMI is not set
# CONFIG_NE2K_PCI is not set
# CONFIG_NET_VENDOR_3COM is not set
CONFIG_NETDEV_1000=y
CONFIG_NOT_COHERENT_CACHE=y
# CONFIG_NVRAM is not set
# CONFIG_PCIPCWATCHDOG is not set

View File

@ -6,6 +6,7 @@ CONFIG_AR7_GPIO=y
CONFIG_AR7_WDT=y
# CONFIG_ARCH_HAS_ILOG2_U32 is not set
# CONFIG_ARCH_HAS_ILOG2_U64 is not set
CONFIG_ATM_DRIVERS=y
# CONFIG_ATMEL is not set
CONFIG_BASE_SMALL=0
# CONFIG_BCM43XX is not set
@ -73,6 +74,7 @@ CONFIG_JFFS2_FS_DEBUG=0
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
CONFIG_LEDS_AR7=y
# CONFIG_MACH_ALCHEMY is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MACH_JAZZ is not set
# CONFIG_MACH_VR41XX is not set
@ -159,6 +161,7 @@ CONFIG_NEED_MULTIPLE_NODES=y
# CONFIG_NET_PCI is not set
CONFIG_NET_SCH_FIFO=y
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_NETDEV_1000 is not set
CONFIG_NODES_SHIFT=6
# CONFIG_PAGE_SIZE_16KB is not set
CONFIG_PAGE_SIZE_4KB=y

View File

@ -3,6 +3,7 @@ CONFIG_32BIT=y
# CONFIG_64BIT_PHYS_ADDR is not set
# CONFIG_8139TOO is not set
CONFIG_AR2313=y
# CONFIG_ATM_DRIVERS is not set
# CONFIG_B44 is not set
CONFIG_BASE_SMALL=0
CONFIG_CPU_BIG_ENDIAN=y
@ -63,6 +64,7 @@ CONFIG_INITRAMFS_SOURCE=""
# CONFIG_IPW2200 is not set
CONFIG_JFFS2_FS_DEBUG=0
# CONFIG_LAN_SAA9730 is not set
# CONFIG_MACH_ALCHEMY is not set
CONFIG_MACH_ARUBA=y
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MACH_JAZZ is not set
@ -155,6 +157,7 @@ CONFIG_MTD_SPLIT_ROOTFS=y
CONFIG_NATSEMI=y
# CONFIG_NE2K_PCI is not set
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_NETDEV_1000 is not set
# CONFIG_PAGE_SIZE_16KB is not set
CONFIG_PAGE_SIZE_4KB=y
# CONFIG_PAGE_SIZE_64KB is not set
@ -191,6 +194,7 @@ CONFIG_SYS_HAS_CPU_MIPS32_R1=y
CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
# CONFIG_TC35815 is not set
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set

View File

@ -60,6 +60,7 @@ CONFIG_HW_RANDOM=y
CONFIG_INITRAMFS_SOURCE=""
CONFIG_IRQ_CPU=y
CONFIG_JFFS2_FS_DEBUG=0
# CONFIG_MACH_ALCHEMY is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MACH_JAZZ is not set
# CONFIG_MACH_VR41XX is not set
@ -149,6 +150,7 @@ CONFIG_MTD_REDBOOT_PARTS_READONLY=y
# CONFIG_MTD_SLRAM is not set
CONFIG_MTD_SPIFLASH=y
CONFIG_NET_SCH_FIFO=y
# CONFIG_NETDEV_1000 is not set
# CONFIG_PAGE_SIZE_16KB is not set
CONFIG_PAGE_SIZE_4KB=y
# CONFIG_PAGE_SIZE_64KB is not set

View File

@ -77,6 +77,7 @@ CONFIG_INITRAMFS_SOURCE=""
CONFIG_JFFS2_FS_DEBUG=0
CONFIG_LEDS_MTX1=y
# CONFIG_LEDS_TRIGGERS is not set
CONFIG_MACH_ALCHEMY=y
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MACH_JAZZ is not set
# CONFIG_MACH_VR41XX is not set
@ -164,6 +165,7 @@ CONFIG_MTX1_WATCHDOG=y
# CONFIG_NE2K_PCI is not set
CONFIG_NET_SCH_FIFO=y
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_NETDEV_1000 is not set
CONFIG_NF_CONNTRACK=y
CONFIG_NF_CONNTRACK_MARK=y
CONFIG_NF_CT_ACCT=y
@ -228,6 +230,7 @@ CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
CONFIG_SYS_SUPPORTS_KGDB=y
CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
# CONFIG_TMD_HERMES is not set
# CONFIG_TC35815 is not set
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
@ -244,5 +247,6 @@ CONFIG_USB_EHCI_HCD=m
CONFIG_USB_OHCI_HCD=m
CONFIG_USB_UHCI_HCD=m
# CONFIG_VIA_RHINE is not set
CONFIG_WDT_MTX1=y
CONFIG_ZONE_DMA=y
CONFIG_ZONE_DMA_FLAG=1

View File

@ -2,6 +2,7 @@ CONFIG_AP7000_16_BIT_SMC=y
# CONFIG_AP7000_32_BIT_SMC is not set
# CONFIG_AP7000_8_BIT_SMC is not set
# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
# CONFIG_ATM_DRIVERS is not set
CONFIG_AVR32=y
CONFIG_BOARD_ATNGW100=y
# CONFIG_BOARD_ATSTK1000 is not set
@ -52,6 +53,7 @@ CONFIG_MTD_MAP_BANK_WIDTH_4=y
# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
# CONFIG_MTD_MTDRAM is not set
# CONFIG_MTD_NAND is not set
# CONFIG_NETDEV_1000 is not set
# CONFIG_MTD_OBSOLETE_CHIPS is not set
# CONFIG_MTD_ONENAND is not set
CONFIG_MTD_PARTITIONS=y
@ -80,6 +82,7 @@ CONFIG_SPI_ATMEL=y
# CONFIG_SPI_BITBANG is not set
# CONFIG_SPI_DEBUG is not set
CONFIG_SPI_MASTER=y
# CONFIG_SPI_SPIDEV is not set
CONFIG_SPI=y
CONFIG_SUBARCH_AVR32B=y
# CONFIG_UNUSED_SYMBOLS is not set

View File

@ -5,6 +5,7 @@ CONFIG_32BIT=y
# CONFIG_ARCH_HAS_ILOG2_U32 is not set
# CONFIG_ARCH_HAS_ILOG2_U64 is not set
# CONFIG_ARPD is not set
# CONFIG_ATM_DRIVERS is not set
# CONFIG_ATMEL is not set
CONFIG_B44=y
CONFIG_BASE_SMALL=0
@ -117,6 +118,7 @@ CONFIG_IRQ_CPU=y
CONFIG_JFFS2_FS_DEBUG=0
# CONFIG_LIBCRC32C is not set
# CONFIG_LLC2 is not set
# CONFIG_MACH_ALCHEMY is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MACH_JAZZ is not set
# CONFIG_MACH_VR41XX is not set
@ -198,6 +200,7 @@ CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_SLRAM is not set
# CONFIG_NATSEMI is not set
# CONFIG_NE2K_PCI is not set
CONFIG_NETDEV_1000=y
# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set
# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
@ -260,6 +263,7 @@ CONFIG_SYS_HAS_CPU_MIPS32_R1=y
CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
# CONFIG_TC35815 is not set
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set

View File

@ -4,6 +4,7 @@ CONFIG_32BIT=y
# CONFIG_8139TOO is not set
# CONFIG_ARCH_HAS_ILOG2_U32 is not set
# CONFIG_ARCH_HAS_ILOG2_U64 is not set
CONFIG_ATM_DRIVERS=y
CONFIG_AUDIT=y
CONFIG_AUDIT_GENERIC=y
CONFIG_BASE_SMALL=0
@ -116,14 +117,7 @@ CONFIG_HZ_250=y
# CONFIG_IDE is not set
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
CONFIG_INPUT=m
# CONFIG_INPUT_EVDEV is not set
CONFIG_INPUT_KEYBOARD=y
CONFIG_INPUT_MOUSE=y
CONFIG_INPUT_MOUSEDEV=m
CONFIG_INPUT_MOUSEDEV_PSAUX=y
CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_INPUT is not set
CONFIG_IOSCHED_CFQ=y
# CONFIG_IOSCHED_DEADLINE is not set
# CONFIG_IP6_NF_MATCH_FRAG is not set
@ -165,10 +159,12 @@ CONFIG_LBD=y
# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set
# CONFIG_LLC2 is not set
CONFIG_LXT_PHY=m
# CONFIG_MACH_ALCHEMY is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MACH_JAZZ is not set
# CONFIG_MACH_VR41XX is not set
# CONFIG_MAC_PARTITION is not set
# CONFIG_MAC80211_DEBUGFS is not set
CONFIG_MAGIC_SYSRQ=y
CONFIG_MARVELL_PHY=m
CONFIG_MII=m
@ -206,9 +202,6 @@ CONFIG_MODVERSIONS=y
# CONFIG_MOMENCO_OCELOT_3 is not set
# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
CONFIG_MOUSE_PS2=m
# CONFIG_MOUSE_SERIAL is not set
# CONFIG_MOUSE_VSXXXAA is not set
CONFIG_MTD=y
# CONFIG_MTD_ABSENT is not set
CONFIG_MTD_BCM963XX=y
@ -277,6 +270,7 @@ CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y
# CONFIG_NET_SCH_CLK_JIFFIES is not set
CONFIG_NET_SCH_FIFO=y
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_NETDEV_1000 is not set
CONFIG_NLS=y
CONFIG_NLS_ASCII=m
# CONFIG_PAGE_SIZE_16KB is not set
@ -332,6 +326,7 @@ CONFIG_SYS_HAS_CPU_MIPS32_R1=y
CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
# CONFIG_TC35815 is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_TCP_CONG_HSTCP is not set
# CONFIG_TCP_CONG_HYBLA is not set

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,791 @@
diff -urN linux-2.6.21.1.old/include/linux/LzmaDecode.h linux-2.6.21.1.dev/include/linux/LzmaDecode.h
--- linux-2.6.21.1.old/include/linux/LzmaDecode.h 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.21.1.dev/include/linux/LzmaDecode.h 2007-05-26 19:03:45.705682584 +0200
@@ -0,0 +1,100 @@
+/*
+ LzmaDecode.h
+ LZMA Decoder interface
+
+ LZMA SDK 4.05 Copyright (c) 1999-2004 Igor Pavlov (2004-08-25)
+ http://www.7-zip.org/
+
+ LZMA SDK is licensed under two licenses:
+ 1) GNU Lesser General Public License (GNU LGPL)
+ 2) Common Public License (CPL)
+ It means that you can select one of these two licenses and
+ follow rules of that license.
+
+ SPECIAL EXCEPTION:
+ Igor Pavlov, as the author of this code, expressly permits you to
+ statically or dynamically link your code (or bind by name) to the
+ interfaces of this file without subjecting your linked code to the
+ terms of the CPL or GNU LGPL. Any modifications or additions
+ to this file, however, are subject to the LGPL or CPL terms.
+*/
+
+#ifndef __LZMADECODE_H
+#define __LZMADECODE_H
+
+/* #define _LZMA_IN_CB */
+/* Use callback for input data */
+
+/* #define _LZMA_OUT_READ */
+/* Use read function for output data */
+
+/* #define _LZMA_PROB32 */
+/* It can increase speed on some 32-bit CPUs,
+ but memory usage will be doubled in that case */
+
+/* #define _LZMA_LOC_OPT */
+/* Enable local speed optimizations inside code */
+
+#ifndef UInt32
+#ifdef _LZMA_UINT32_IS_ULONG
+#define UInt32 unsigned long
+#else
+#define UInt32 unsigned int
+#endif
+#endif
+
+#ifdef _LZMA_PROB32
+#define CProb UInt32
+#else
+#define CProb unsigned short
+#endif
+
+#define LZMA_RESULT_OK 0
+#define LZMA_RESULT_DATA_ERROR 1
+#define LZMA_RESULT_NOT_ENOUGH_MEM 2
+
+#ifdef _LZMA_IN_CB
+typedef struct _ILzmaInCallback
+{
+ int (*Read)(void *object, unsigned char **buffer, UInt32 *bufferSize);
+} ILzmaInCallback;
+#endif
+
+#define LZMA_BASE_SIZE 1846
+#define LZMA_LIT_SIZE 768
+
+/*
+bufferSize = (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << (lc + lp)))* sizeof(CProb)
+bufferSize += 100 in case of _LZMA_OUT_READ
+by default CProb is unsigned short,
+but if specify _LZMA_PROB_32, CProb will be UInt32(unsigned int)
+*/
+
+#ifdef _LZMA_OUT_READ
+int LzmaDecoderInit(
+ unsigned char *buffer, UInt32 bufferSize,
+ int lc, int lp, int pb,
+ unsigned char *dictionary, UInt32 dictionarySize,
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *inCallback
+ #else
+ unsigned char *inStream, UInt32 inSize
+ #endif
+);
+#endif
+
+int LzmaDecode(
+ unsigned char *buffer,
+ #ifndef _LZMA_OUT_READ
+ UInt32 bufferSize,
+ int lc, int lp, int pb,
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *inCallback,
+ #else
+ unsigned char *inStream, UInt32 inSize,
+ #endif
+ #endif
+ unsigned char *outStream, UInt32 outSize,
+ UInt32 *outSizeProcessed);
+
+#endif
diff -urN linux-2.6.21.1.old/lib/LzmaDecode.c linux-2.6.21.1.dev/lib/LzmaDecode.c
--- linux-2.6.21.1.old/lib/LzmaDecode.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.21.1.dev/lib/LzmaDecode.c 2007-05-26 19:03:45.706682432 +0200
@@ -0,0 +1,663 @@
+/*
+ LzmaDecode.c
+ LZMA Decoder
+
+ LZMA SDK 4.05 Copyright (c) 1999-2004 Igor Pavlov (2004-08-25)
+ http://www.7-zip.org/
+
+ LZMA SDK is licensed under two licenses:
+ 1) GNU Lesser General Public License (GNU LGPL)
+ 2) Common Public License (CPL)
+ It means that you can select one of these two licenses and
+ follow rules of that license.
+
+ SPECIAL EXCEPTION:
+ Igor Pavlov, as the author of this code, expressly permits you to
+ statically or dynamically link your code (or bind by name) to the
+ interfaces of this file without subjecting your linked code to the
+ terms of the CPL or GNU LGPL. Any modifications or additions
+ to this file, however, are subject to the LGPL or CPL terms.
+*/
+
+#include <linux/LzmaDecode.h>
+
+#ifndef Byte
+#define Byte unsigned char
+#endif
+
+#define kNumTopBits 24
+#define kTopValue ((UInt32)1 << kNumTopBits)
+
+#define kNumBitModelTotalBits 11
+#define kBitModelTotal (1 << kNumBitModelTotalBits)
+#define kNumMoveBits 5
+
+typedef struct _CRangeDecoder
+{
+ Byte *Buffer;
+ Byte *BufferLim;
+ UInt32 Range;
+ UInt32 Code;
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *InCallback;
+ int Result;
+ #endif
+ int ExtraBytes;
+} CRangeDecoder;
+
+Byte RangeDecoderReadByte(CRangeDecoder *rd)
+{
+ if (rd->Buffer == rd->BufferLim)
+ {
+ #ifdef _LZMA_IN_CB
+ UInt32 size;
+ rd->Result = rd->InCallback->Read(rd->InCallback, &rd->Buffer, &size);
+ rd->BufferLim = rd->Buffer + size;
+ if (size == 0)
+ #endif
+ {
+ rd->ExtraBytes = 1;
+ return 0xFF;
+ }
+ }
+ return (*rd->Buffer++);
+}
+
+/* #define ReadByte (*rd->Buffer++) */
+#define ReadByte (RangeDecoderReadByte(rd))
+
+void RangeDecoderInit(CRangeDecoder *rd,
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *inCallback
+ #else
+ Byte *stream, UInt32 bufferSize
+ #endif
+ )
+{
+ int i;
+ #ifdef _LZMA_IN_CB
+ rd->InCallback = inCallback;
+ rd->Buffer = rd->BufferLim = 0;
+ #else
+ rd->Buffer = stream;
+ rd->BufferLim = stream + bufferSize;
+ #endif
+ rd->ExtraBytes = 0;
+ rd->Code = 0;
+ rd->Range = (0xFFFFFFFF);
+ for(i = 0; i < 5; i++)
+ rd->Code = (rd->Code << 8) | ReadByte;
+}
+
+#define RC_INIT_VAR UInt32 range = rd->Range; UInt32 code = rd->Code;
+#define RC_FLUSH_VAR rd->Range = range; rd->Code = code;
+#define RC_NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | ReadByte; }
+
+UInt32 RangeDecoderDecodeDirectBits(CRangeDecoder *rd, int numTotalBits)
+{
+ RC_INIT_VAR
+ UInt32 result = 0;
+ int i;
+ for (i = numTotalBits; i > 0; i--)
+ {
+ /* UInt32 t; */
+ range >>= 1;
+
+ result <<= 1;
+ if (code >= range)
+ {
+ code -= range;
+ result |= 1;
+ }
+ /*
+ t = (code - range) >> 31;
+ t &= 1;
+ code -= range & (t - 1);
+ result = (result + result) | (1 - t);
+ */
+ RC_NORMALIZE
+ }
+ RC_FLUSH_VAR
+ return result;
+}
+
+int RangeDecoderBitDecode(CProb *prob, CRangeDecoder *rd)
+{
+ UInt32 bound = (rd->Range >> kNumBitModelTotalBits) * *prob;
+ if (rd->Code < bound)
+ {
+ rd->Range = bound;
+ *prob += (kBitModelTotal - *prob) >> kNumMoveBits;
+ if (rd->Range < kTopValue)
+ {
+ rd->Code = (rd->Code << 8) | ReadByte;
+ rd->Range <<= 8;
+ }
+ return 0;
+ }
+ else
+ {
+ rd->Range -= bound;
+ rd->Code -= bound;
+ *prob -= (*prob) >> kNumMoveBits;
+ if (rd->Range < kTopValue)
+ {
+ rd->Code = (rd->Code << 8) | ReadByte;
+ rd->Range <<= 8;
+ }
+ return 1;
+ }
+}
+
+#define RC_GET_BIT2(prob, mi, A0, A1) \
+ UInt32 bound = (range >> kNumBitModelTotalBits) * *prob; \
+ if (code < bound) \
+ { A0; range = bound; *prob += (kBitModelTotal - *prob) >> kNumMoveBits; mi <<= 1; } \
+ else \
+ { A1; range -= bound; code -= bound; *prob -= (*prob) >> kNumMoveBits; mi = (mi + mi) + 1; } \
+ RC_NORMALIZE
+
+#define RC_GET_BIT(prob, mi) RC_GET_BIT2(prob, mi, ; , ;)
+
+int RangeDecoderBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd)
+{
+ int mi = 1;
+ int i;
+ #ifdef _LZMA_LOC_OPT
+ RC_INIT_VAR
+ #endif
+ for(i = numLevels; i > 0; i--)
+ {
+ #ifdef _LZMA_LOC_OPT
+ CProb *prob = probs + mi;
+ RC_GET_BIT(prob, mi)
+ #else
+ mi = (mi + mi) + RangeDecoderBitDecode(probs + mi, rd);
+ #endif
+ }
+ #ifdef _LZMA_LOC_OPT
+ RC_FLUSH_VAR
+ #endif
+ return mi - (1 << numLevels);
+}
+
+int RangeDecoderReverseBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd)
+{
+ int mi = 1;
+ int i;
+ int symbol = 0;
+ #ifdef _LZMA_LOC_OPT
+ RC_INIT_VAR
+ #endif
+ for(i = 0; i < numLevels; i++)
+ {
+ #ifdef _LZMA_LOC_OPT
+ CProb *prob = probs + mi;
+ RC_GET_BIT2(prob, mi, ; , symbol |= (1 << i))
+ #else
+ int bit = RangeDecoderBitDecode(probs + mi, rd);
+ mi = mi + mi + bit;
+ symbol |= (bit << i);
+ #endif
+ }
+ #ifdef _LZMA_LOC_OPT
+ RC_FLUSH_VAR
+ #endif
+ return symbol;
+}
+
+Byte LzmaLiteralDecode(CProb *probs, CRangeDecoder *rd)
+{
+ int symbol = 1;
+ #ifdef _LZMA_LOC_OPT
+ RC_INIT_VAR
+ #endif
+ do
+ {
+ #ifdef _LZMA_LOC_OPT
+ CProb *prob = probs + symbol;
+ RC_GET_BIT(prob, symbol)
+ #else
+ symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd);
+ #endif
+ }
+ while (symbol < 0x100);
+ #ifdef _LZMA_LOC_OPT
+ RC_FLUSH_VAR
+ #endif
+ return symbol;
+}
+
+Byte LzmaLiteralDecodeMatch(CProb *probs, CRangeDecoder *rd, Byte matchByte)
+{
+ int symbol = 1;
+ #ifdef _LZMA_LOC_OPT
+ RC_INIT_VAR
+ #endif
+ do
+ {
+ int bit;
+ int matchBit = (matchByte >> 7) & 1;
+ matchByte <<= 1;
+ #ifdef _LZMA_LOC_OPT
+ {
+ CProb *prob = probs + ((1 + matchBit) << 8) + symbol;
+ RC_GET_BIT2(prob, symbol, bit = 0, bit = 1)
+ }
+ #else
+ bit = RangeDecoderBitDecode(probs + ((1 + matchBit) << 8) + symbol, rd);
+ symbol = (symbol << 1) | bit;
+ #endif
+ if (matchBit != bit)
+ {
+ while (symbol < 0x100)
+ {
+ #ifdef _LZMA_LOC_OPT
+ CProb *prob = probs + symbol;
+ RC_GET_BIT(prob, symbol)
+ #else
+ symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd);
+ #endif
+ }
+ break;
+ }
+ }
+ while (symbol < 0x100);
+ #ifdef _LZMA_LOC_OPT
+ RC_FLUSH_VAR
+ #endif
+ return symbol;
+}
+
+#define kNumPosBitsMax 4
+#define kNumPosStatesMax (1 << kNumPosBitsMax)
+
+#define kLenNumLowBits 3
+#define kLenNumLowSymbols (1 << kLenNumLowBits)
+#define kLenNumMidBits 3
+#define kLenNumMidSymbols (1 << kLenNumMidBits)
+#define kLenNumHighBits 8
+#define kLenNumHighSymbols (1 << kLenNumHighBits)
+
+#define LenChoice 0
+#define LenChoice2 (LenChoice + 1)
+#define LenLow (LenChoice2 + 1)
+#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
+#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
+#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
+
+int LzmaLenDecode(CProb *p, CRangeDecoder *rd, int posState)
+{
+ if(RangeDecoderBitDecode(p + LenChoice, rd) == 0)
+ return RangeDecoderBitTreeDecode(p + LenLow +
+ (posState << kLenNumLowBits), kLenNumLowBits, rd);
+ if(RangeDecoderBitDecode(p + LenChoice2, rd) == 0)
+ return kLenNumLowSymbols + RangeDecoderBitTreeDecode(p + LenMid +
+ (posState << kLenNumMidBits), kLenNumMidBits, rd);
+ return kLenNumLowSymbols + kLenNumMidSymbols +
+ RangeDecoderBitTreeDecode(p + LenHigh, kLenNumHighBits, rd);
+}
+
+#define kNumStates 12
+
+#define kStartPosModelIndex 4
+#define kEndPosModelIndex 14
+#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
+
+#define kNumPosSlotBits 6
+#define kNumLenToPosStates 4
+
+#define kNumAlignBits 4
+#define kAlignTableSize (1 << kNumAlignBits)
+
+#define kMatchMinLen 2
+
+#define IsMatch 0
+#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
+#define IsRepG0 (IsRep + kNumStates)
+#define IsRepG1 (IsRepG0 + kNumStates)
+#define IsRepG2 (IsRepG1 + kNumStates)
+#define IsRep0Long (IsRepG2 + kNumStates)
+#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
+#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
+#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
+#define LenCoder (Align + kAlignTableSize)
+#define RepLenCoder (LenCoder + kNumLenProbs)
+#define Literal (RepLenCoder + kNumLenProbs)
+
+#if Literal != LZMA_BASE_SIZE
+StopCompilingDueBUG
+#endif
+
+#ifdef _LZMA_OUT_READ
+
+typedef struct _LzmaVarState
+{
+ CRangeDecoder RangeDecoder;
+ Byte *Dictionary;
+ UInt32 DictionarySize;
+ UInt32 DictionaryPos;
+ UInt32 GlobalPos;
+ UInt32 Reps[4];
+ int lc;
+ int lp;
+ int pb;
+ int State;
+ int PreviousIsMatch;
+ int RemainLen;
+} LzmaVarState;
+
+int LzmaDecoderInit(
+ unsigned char *buffer, UInt32 bufferSize,
+ int lc, int lp, int pb,
+ unsigned char *dictionary, UInt32 dictionarySize,
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *inCallback
+ #else
+ unsigned char *inStream, UInt32 inSize
+ #endif
+ )
+{
+ LzmaVarState *vs = (LzmaVarState *)buffer;
+ CProb *p = (CProb *)(buffer + sizeof(LzmaVarState));
+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + lp));
+ UInt32 i;
+ if (bufferSize < numProbs * sizeof(CProb) + sizeof(LzmaVarState))
+ return LZMA_RESULT_NOT_ENOUGH_MEM;
+ vs->Dictionary = dictionary;
+ vs->DictionarySize = dictionarySize;
+ vs->DictionaryPos = 0;
+ vs->GlobalPos = 0;
+ vs->Reps[0] = vs->Reps[1] = vs->Reps[2] = vs->Reps[3] = 1;
+ vs->lc = lc;
+ vs->lp = lp;
+ vs->pb = pb;
+ vs->State = 0;
+ vs->PreviousIsMatch = 0;
+ vs->RemainLen = 0;
+ dictionary[dictionarySize - 1] = 0;
+ for (i = 0; i < numProbs; i++)
+ p[i] = kBitModelTotal >> 1;
+ RangeDecoderInit(&vs->RangeDecoder,
+ #ifdef _LZMA_IN_CB
+ inCallback
+ #else
+ inStream, inSize
+ #endif
+ );
+ return LZMA_RESULT_OK;
+}
+
+int LzmaDecode(unsigned char *buffer,
+ unsigned char *outStream, UInt32 outSize,
+ UInt32 *outSizeProcessed)
+{
+ LzmaVarState *vs = (LzmaVarState *)buffer;
+ CProb *p = (CProb *)(buffer + sizeof(LzmaVarState));
+ CRangeDecoder rd = vs->RangeDecoder;
+ int state = vs->State;
+ int previousIsMatch = vs->PreviousIsMatch;
+ Byte previousByte;
+ UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
+ UInt32 nowPos = 0;
+ UInt32 posStateMask = (1 << (vs->pb)) - 1;
+ UInt32 literalPosMask = (1 << (vs->lp)) - 1;
+ int lc = vs->lc;
+ int len = vs->RemainLen;
+ UInt32 globalPos = vs->GlobalPos;
+
+ Byte *dictionary = vs->Dictionary;
+ UInt32 dictionarySize = vs->DictionarySize;
+ UInt32 dictionaryPos = vs->DictionaryPos;
+
+ if (len == -1)
+ {
+ *outSizeProcessed = 0;
+ return LZMA_RESULT_OK;
+ }
+
+ while(len > 0 && nowPos < outSize)
+ {
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ len--;
+ }
+ if (dictionaryPos == 0)
+ previousByte = dictionary[dictionarySize - 1];
+ else
+ previousByte = dictionary[dictionaryPos - 1];
+#else
+
+int LzmaDecode(
+ Byte *buffer, UInt32 bufferSize,
+ int lc, int lp, int pb,
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *inCallback,
+ #else
+ unsigned char *inStream, UInt32 inSize,
+ #endif
+ unsigned char *outStream, UInt32 outSize,
+ UInt32 *outSizeProcessed)
+{
+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + lp));
+ CProb *p = (CProb *)buffer;
+ CRangeDecoder rd;
+ UInt32 i;
+ int state = 0;
+ int previousIsMatch = 0;
+ Byte previousByte = 0;
+ UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
+ UInt32 nowPos = 0;
+ UInt32 posStateMask = (1 << pb) - 1;
+ UInt32 literalPosMask = (1 << lp) - 1;
+ int len = 0;
+ if (bufferSize < numProbs * sizeof(CProb))
+ return LZMA_RESULT_NOT_ENOUGH_MEM;
+ for (i = 0; i < numProbs; i++)
+ p[i] = kBitModelTotal >> 1;
+ RangeDecoderInit(&rd,
+ #ifdef _LZMA_IN_CB
+ inCallback
+ #else
+ inStream, inSize
+ #endif
+ );
+#endif
+
+ *outSizeProcessed = 0;
+ while(nowPos < outSize)
+ {
+ int posState = (int)(
+ (nowPos
+ #ifdef _LZMA_OUT_READ
+ + globalPos
+ #endif
+ )
+ & posStateMask);
+ #ifdef _LZMA_IN_CB
+ if (rd.Result != LZMA_RESULT_OK)
+ return rd.Result;
+ #endif
+ if (rd.ExtraBytes != 0)
+ return LZMA_RESULT_DATA_ERROR;
+ if (RangeDecoderBitDecode(p + IsMatch + (state << kNumPosBitsMax) + posState, &rd) == 0)
+ {
+ CProb *probs = p + Literal + (LZMA_LIT_SIZE *
+ (((
+ (nowPos
+ #ifdef _LZMA_OUT_READ
+ + globalPos
+ #endif
+ )
+ & literalPosMask) << lc) + (previousByte >> (8 - lc))));
+
+ if (state < 4) state = 0;
+ else if (state < 10) state -= 3;
+ else state -= 6;
+ if (previousIsMatch)
+ {
+ Byte matchByte;
+ #ifdef _LZMA_OUT_READ
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ matchByte = dictionary[pos];
+ #else
+ matchByte = outStream[nowPos - rep0];
+ #endif
+ previousByte = LzmaLiteralDecodeMatch(probs, &rd, matchByte);
+ previousIsMatch = 0;
+ }
+ else
+ previousByte = LzmaLiteralDecode(probs, &rd);
+ outStream[nowPos++] = previousByte;
+ #ifdef _LZMA_OUT_READ
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ #endif
+ }
+ else
+ {
+ previousIsMatch = 1;
+ if (RangeDecoderBitDecode(p + IsRep + state, &rd) == 1)
+ {
+ if (RangeDecoderBitDecode(p + IsRepG0 + state, &rd) == 0)
+ {
+ if (RangeDecoderBitDecode(p + IsRep0Long + (state << kNumPosBitsMax) + posState, &rd) == 0)
+ {
+ #ifdef _LZMA_OUT_READ
+ UInt32 pos;
+ #endif
+ if (
+ (nowPos
+ #ifdef _LZMA_OUT_READ
+ + globalPos
+ #endif
+ )
+ == 0)
+ return LZMA_RESULT_DATA_ERROR;
+ state = state < 7 ? 9 : 11;
+ #ifdef _LZMA_OUT_READ
+ pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ previousByte = dictionary[pos];
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ #else
+ previousByte = outStream[nowPos - rep0];
+ #endif
+ outStream[nowPos++] = previousByte;
+ continue;
+ }
+ }
+ else
+ {
+ UInt32 distance;
+ if(RangeDecoderBitDecode(p + IsRepG1 + state, &rd) == 0)
+ distance = rep1;
+ else
+ {
+ if(RangeDecoderBitDecode(p + IsRepG2 + state, &rd) == 0)
+ distance = rep2;
+ else
+ {
+ distance = rep3;
+ rep3 = rep2;
+ }
+ rep2 = rep1;
+ }
+ rep1 = rep0;
+ rep0 = distance;
+ }
+ len = LzmaLenDecode(p + RepLenCoder, &rd, posState);
+ state = state < 7 ? 8 : 11;
+ }
+ else
+ {
+ int posSlot;
+ rep3 = rep2;
+ rep2 = rep1;
+ rep1 = rep0;
+ state = state < 7 ? 7 : 10;
+ len = LzmaLenDecode(p + LenCoder, &rd, posState);
+ posSlot = RangeDecoderBitTreeDecode(p + PosSlot +
+ ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
+ kNumPosSlotBits), kNumPosSlotBits, &rd);
+ if (posSlot >= kStartPosModelIndex)
+ {
+ int numDirectBits = ((posSlot >> 1) - 1);
+ rep0 = ((2 | ((UInt32)posSlot & 1)) << numDirectBits);
+ if (posSlot < kEndPosModelIndex)
+ {
+ rep0 += RangeDecoderReverseBitTreeDecode(
+ p + SpecPos + rep0 - posSlot - 1, numDirectBits, &rd);
+ }
+ else
+ {
+ rep0 += RangeDecoderDecodeDirectBits(&rd,
+ numDirectBits - kNumAlignBits) << kNumAlignBits;
+ rep0 += RangeDecoderReverseBitTreeDecode(p + Align, kNumAlignBits, &rd);
+ }
+ }
+ else
+ rep0 = posSlot;
+ rep0++;
+ }
+ if (rep0 == (UInt32)(0))
+ {
+ /* it's for stream version */
+ len = -1;
+ break;
+ }
+ if (rep0 > nowPos
+ #ifdef _LZMA_OUT_READ
+ + globalPos
+ #endif
+ )
+ {
+ return LZMA_RESULT_DATA_ERROR;
+ }
+ len += kMatchMinLen;
+ do
+ {
+ #ifdef _LZMA_OUT_READ
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ previousByte = dictionary[pos];
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ #else
+ previousByte = outStream[nowPos - rep0];
+ #endif
+ outStream[nowPos++] = previousByte;
+ len--;
+ }
+ while(len > 0 && nowPos < outSize);
+ }
+ }
+
+ #ifdef _LZMA_OUT_READ
+ vs->RangeDecoder = rd;
+ vs->DictionaryPos = dictionaryPos;
+ vs->GlobalPos = globalPos + nowPos;
+ vs->Reps[0] = rep0;
+ vs->Reps[1] = rep1;
+ vs->Reps[2] = rep2;
+ vs->Reps[3] = rep3;
+ vs->State = state;
+ vs->PreviousIsMatch = previousIsMatch;
+ vs->RemainLen = len;
+ #endif
+
+ *outSizeProcessed = nowPos;
+ return LZMA_RESULT_OK;
+}
diff -urN linux-2.6.21.1.old/lib/Makefile linux-2.6.21.1.dev/lib/Makefile
--- linux-2.6.21.1.old/lib/Makefile 2007-04-27 23:49:26.000000000 +0200
+++ linux-2.6.21.1.dev/lib/Makefile 2007-05-26 19:03:45.721680152 +0200
@@ -13,7 +13,7 @@
lib-y += kobject.o kref.o kobject_uevent.o klist.o
obj-y += div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \
- bust_spinlocks.o hexdump.o
+ bust_spinlocks.o hexdump.o LzmaDecode.o
ifeq ($(CONFIG_DEBUG_KOBJECT),y)
CFLAGS_kobject.o += -DDEBUG
@@ -58,6 +58,7 @@
obj-$(CONFIG_AUDIT_GENERIC) += audit.o
obj-$(CONFIG_SWIOTLB) += swiotlb.o
+
obj-$(CONFIG_FAULT_INJECTION) += fault-inject.o
lib-$(CONFIG_GENERIC_BUG) += bug.o

View File

@ -0,0 +1,108 @@
diff -urN linux-2.6.21.1.old/fs/squashfs/inode.c linux-2.6.21.1.dev/fs/squashfs/inode.c
--- linux-2.6.21.1.old/fs/squashfs/inode.c 2007-05-26 19:03:45.499713896 +0200
+++ linux-2.6.21.1.dev/fs/squashfs/inode.c 2007-05-26 19:07:27.951896024 +0200
@@ -4,6 +4,9 @@
* Copyright (c) 2002, 2003, 2004, 2005, 2006
* Phillip Lougher <phillip@lougher.org.uk>
*
+ * LZMA decompressor support added by Oleg I. Vdovikin
+ * Copyright (c) 2005 Oleg I.Vdovikin <oleg@cs.msu.su>
+ *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2,
@@ -21,6 +24,7 @@
* inode.c
*/
+#define SQUASHFS_LZMA
#include <linux/types.h>
#include <linux/squashfs_fs.h>
#include <linux/module.h>
@@ -44,6 +48,19 @@
#include "squashfs.h"
+#ifdef SQUASHFS_LZMA
+#include <linux/LzmaDecode.h>
+
+/* default LZMA settings, should be in sync with mksquashfs */
+#define LZMA_LC 3
+#define LZMA_LP 0
+#define LZMA_PB 2
+
+#define LZMA_WORKSPACE_SIZE ((LZMA_BASE_SIZE + \
+ (LZMA_LIT_SIZE << (LZMA_LC + LZMA_LP))) * sizeof(CProb))
+
+#endif
+
static void squashfs_put_super(struct super_block *);
static int squashfs_statfs(struct dentry *, struct kstatfs *);
static int squashfs_symlink_readpage(struct file *file, struct page *page);
@@ -64,7 +81,11 @@
const char *, void *, struct vfsmount *);
+#ifdef SQUASHFS_LZMA
+static unsigned char lzma_workspace[LZMA_WORKSPACE_SIZE];
+#else
static z_stream stream;
+#endif
static struct file_system_type squashfs_fs_type = {
.owner = THIS_MODULE,
@@ -249,6 +270,15 @@
if (compressed) {
int zlib_err;
+#ifdef SQUASHFS_LZMA
+ if ((zlib_err = LzmaDecode(lzma_workspace,
+ LZMA_WORKSPACE_SIZE, LZMA_LC, LZMA_LP, LZMA_PB,
+ c_buffer, c_byte, buffer, msblk->read_size, &bytes)) != LZMA_RESULT_OK)
+ {
+ ERROR("lzma returned unexpected result 0x%x\n", zlib_err);
+ bytes = 0;
+ }
+#else
stream.next_in = c_buffer;
stream.avail_in = c_byte;
stream.next_out = buffer;
@@ -263,7 +293,7 @@
bytes = 0;
} else
bytes = stream.total_out;
-
+#endif
up(&msblk->read_data_mutex);
}
@@ -2045,15 +2075,19 @@
printk(KERN_INFO "squashfs: version 3.0 (2006/03/15) "
"Phillip Lougher\n");
+#ifndef SQUASHFS_LZMA
if (!(stream.workspace = vmalloc(zlib_inflate_workspacesize()))) {
ERROR("Failed to allocate zlib workspace\n");
destroy_inodecache();
err = -ENOMEM;
goto out;
}
+#endif
if ((err = register_filesystem(&squashfs_fs_type))) {
+#ifndef SQUASHFS_LZMA
vfree(stream.workspace);
+#endif
destroy_inodecache();
}
@@ -2064,7 +2098,9 @@
static void __exit exit_squashfs_fs(void)
{
+#ifndef SQUASHFS_LZMA
vfree(stream.workspace);
+#endif
unregister_filesystem(&squashfs_fs_type);
destroy_inodecache();
}

View File

@ -0,0 +1,13 @@
diff -urN linux-2.6.21.1.old/Makefile linux-2.6.21.1.dev/Makefile
--- linux-2.6.21.1.old/Makefile 2007-04-27 23:49:26.000000000 +0200
+++ linux-2.6.21.1.dev/Makefile 2007-05-26 19:14:22.967804016 +0200
@@ -507,6 +507,9 @@
NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include)
CHECKFLAGS += $(NOSTDINC_FLAGS)
+# improve gcc optimization
+CFLAGS += $(call cc-option,-funit-at-a-time,)
+
# warn about C99 declaration after statement
CFLAGS += $(call cc-option,-Wdeclaration-after-statement,)

View File

@ -0,0 +1,12 @@
diff -urN linux-2.6.21.1.old/include/asm-mips/system.h linux-2.6.21.1.dev/include/asm-mips/system.h
--- linux-2.6.21.1.old/include/asm-mips/system.h 2007-04-27 23:49:26.000000000 +0200
+++ linux-2.6.21.1.dev/include/asm-mips/system.h 2007-05-26 19:26:30.870146040 +0200
@@ -188,7 +188,7 @@
if something tries to do an invalid xchg(). */
extern void __xchg_called_with_bad_pointer(void);
-static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
+static __always_inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
{
switch (size) {
case 4:

View File

@ -0,0 +1,37 @@
diff -urN linux-2.6.21.1.old/drivers/mtd/chips/cfi_cmdset_0002.c linux-2.6.21.1.dev/drivers/mtd/chips/cfi_cmdset_0002.c
--- linux-2.6.21.1.old/drivers/mtd/chips/cfi_cmdset_0002.c 2007-04-27 23:49:26.000000000 +0200
+++ linux-2.6.21.1.dev/drivers/mtd/chips/cfi_cmdset_0002.c 2007-05-26 19:30:01.049193968 +0200
@@ -51,6 +51,7 @@
#define SST49LF040B 0x0050
#define SST49LF008A 0x005a
#define AT49BV6416 0x00d6
+#define MANUFACTURER_SAMSUNG 0x00ec
static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
static int cfi_amdstd_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
@@ -294,12 +295,19 @@
if (extp->MajorVersion != '1' ||
(extp->MinorVersion < '0' || extp->MinorVersion > '4')) {
- printk(KERN_ERR " Unknown Amd/Fujitsu Extended Query "
- "version %c.%c.\n", extp->MajorVersion,
- extp->MinorVersion);
- kfree(extp);
- kfree(mtd);
- return NULL;
+ if (cfi->mfr == MANUFACTURER_SAMSUNG &&
+ (extp->MajorVersion == '3' && extp->MinorVersion == '3')) {
+ printk(KERN_NOTICE " Newer Samsung flash detected, "
+ "should be compatibile with Amd/Fujitsu.\n");
+ }
+ else {
+ printk(KERN_ERR " Unknown Amd/Fujitsu Extended Query "
+ "version %c.%c.\n", extp->MajorVersion,
+ extp->MinorVersion);
+ kfree(extp);
+ kfree(mtd);
+ return NULL;
+ }
}
/* Install our own private info structure */

View File

@ -0,0 +1,170 @@
diff -urN linux-2.6.21.1.old/drivers/mtd/chips/cfi_cmdset_0001.c linux-2.6.21.1.dev/drivers/mtd/chips/cfi_cmdset_0001.c
--- linux-2.6.21.1.old/drivers/mtd/chips/cfi_cmdset_0001.c 2007-04-27 23:49:26.000000000 +0200
+++ linux-2.6.21.1.dev/drivers/mtd/chips/cfi_cmdset_0001.c 2007-05-26 19:40:46.809023552 +0200
@@ -933,7 +933,7 @@
static int __xipram xip_wait_for_operation(
struct map_info *map, struct flchip *chip,
- unsigned long adr, unsigned int chip_op_time )
+ unsigned long adr, int *chip_op_time )
{
struct cfi_private *cfi = map->fldrv_priv;
struct cfi_pri_intelext *cfip = cfi->cmdset_priv;
@@ -942,7 +942,7 @@
flstate_t oldstate, newstate;
start = xip_currtime();
- usec = chip_op_time * 8;
+ usec = *chip_op_time * 8;
if (usec == 0)
usec = 500000;
done = 0;
@@ -1052,8 +1052,8 @@
#define XIP_INVAL_CACHED_RANGE(map, from, size) \
INVALIDATE_CACHED_RANGE(map, from, size)
-#define INVAL_CACHE_AND_WAIT(map, chip, cmd_adr, inval_adr, inval_len, usec) \
- xip_wait_for_operation(map, chip, cmd_adr, usec)
+#define INVAL_CACHE_AND_WAIT(map, chip, cmd_adr, inval_adr, inval_len, p_usec) \
+ xip_wait_for_operation(map, chip, cmd_adr, p_usec)
#else
@@ -1065,65 +1065,65 @@
static int inval_cache_and_wait_for_operation(
struct map_info *map, struct flchip *chip,
unsigned long cmd_adr, unsigned long inval_adr, int inval_len,
- unsigned int chip_op_time)
+ int *chip_op_time )
{
struct cfi_private *cfi = map->fldrv_priv;
map_word status, status_OK = CMD(0x80);
- int chip_state = chip->state;
- unsigned int timeo, sleep_time;
+ int z, chip_state = chip->state;
+ unsigned long timeo;
spin_unlock(chip->mutex);
if (inval_len)
INVALIDATE_CACHED_RANGE(map, inval_adr, inval_len);
+ if (*chip_op_time)
+ cfi_udelay(*chip_op_time);
spin_lock(chip->mutex);
- /* set our timeout to 8 times the expected delay */
- timeo = chip_op_time * 8;
- if (!timeo)
- timeo = 500000;
- sleep_time = chip_op_time / 2;
+ timeo = *chip_op_time * 8 * HZ / 1000000;
+ if (timeo < HZ/2)
+ timeo = HZ/2;
+ timeo += jiffies;
+ z = 0;
for (;;) {
+ if (chip->state != chip_state) {
+ /* Someone's suspended the operation: sleep */
+ DECLARE_WAITQUEUE(wait, current);
+
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ add_wait_queue(&chip->wq, &wait);
+ spin_unlock(chip->mutex);
+ schedule();
+ remove_wait_queue(&chip->wq, &wait);
+ timeo = jiffies + (HZ / 2); /* FIXME */
+ spin_lock(chip->mutex);
+ continue;
+ }
+
status = map_read(map, cmd_adr);
if (map_word_andequal(map, status, status_OK, status_OK))
break;
- if (!timeo) {
+ /* OK Still waiting */
+ if (time_after(jiffies, timeo)) {
map_write(map, CMD(0x70), cmd_adr);
chip->state = FL_STATUS;
return -ETIME;
}
- /* OK Still waiting. Drop the lock, wait a while and retry. */
+ /* Latency issues. Drop the lock, wait a while and retry */
+ z++;
spin_unlock(chip->mutex);
- if (sleep_time >= 1000000/HZ) {
- /*
- * Half of the normal delay still remaining
- * can be performed with a sleeping delay instead
- * of busy waiting.
- */
- msleep(sleep_time/1000);
- timeo -= sleep_time;
- sleep_time = 1000000/HZ;
- } else {
- udelay(1);
- cond_resched();
- timeo--;
- }
+ cfi_udelay(1);
spin_lock(chip->mutex);
-
- while (chip->state != chip_state) {
- /* Someone's suspended the operation: sleep */
- DECLARE_WAITQUEUE(wait, current);
- set_current_state(TASK_UNINTERRUPTIBLE);
- add_wait_queue(&chip->wq, &wait);
- spin_unlock(chip->mutex);
- schedule();
- remove_wait_queue(&chip->wq, &wait);
- spin_lock(chip->mutex);
- }
}
+ if (!z) {
+ if (!--(*chip_op_time))
+ *chip_op_time = 1;
+ } else if (z > 1)
+ ++(*chip_op_time);
+
/* Done and happy. */
chip->state = FL_STATUS;
return 0;
@@ -1132,7 +1132,8 @@
#endif
#define WAIT_TIMEOUT(map, chip, adr, udelay) \
- INVAL_CACHE_AND_WAIT(map, chip, adr, 0, 0, udelay);
+ ({ int __udelay = (udelay); \
+ INVAL_CACHE_AND_WAIT(map, chip, adr, 0, 0, &__udelay); })
static int do_point_onechip (struct map_info *map, struct flchip *chip, loff_t adr, size_t len)
@@ -1356,7 +1357,7 @@
ret = INVAL_CACHE_AND_WAIT(map, chip, adr,
adr, map_bankwidth(map),
- chip->word_write_time);
+ &chip->word_write_time);
if (ret) {
xip_enable(map, chip, adr);
printk(KERN_ERR "%s: word write error (status timeout)\n", map->name);
@@ -1593,7 +1594,7 @@
ret = INVAL_CACHE_AND_WAIT(map, chip, cmd_adr,
adr, len,
- chip->buffer_write_time);
+ &chip->buffer_write_time);
if (ret) {
map_write(map, CMD(0x70), cmd_adr);
chip->state = FL_STATUS;
@@ -1728,7 +1729,7 @@
ret = INVAL_CACHE_AND_WAIT(map, chip, adr,
adr, len,
- chip->erase_time);
+ &chip->erase_time);
if (ret) {
map_write(map, CMD(0x70), adr);
chip->state = FL_STATUS;

View File

@ -0,0 +1,21 @@
diff -urN linux-2.6.21.1.old/fs/squashfs/Makefile linux-2.6.21.1.dev/fs/squashfs/Makefile
--- linux-2.6.21.1.old/fs/squashfs/Makefile 2007-05-26 19:03:45.499713896 +0200
+++ linux-2.6.21.1.dev/fs/squashfs/Makefile 2007-05-26 19:43:37.064140840 +0200
@@ -4,4 +4,3 @@
obj-$(CONFIG_SQUASHFS) += squashfs.o
squashfs-y += inode.o
-squashfs-y += squashfs2_0.o
diff -urN linux-2.6.21.1.old/fs/squashfs/squashfs.h linux-2.6.21.1.dev/fs/squashfs/squashfs.h
--- linux-2.6.21.1.old/fs/squashfs/squashfs.h 2007-05-26 19:03:45.500713744 +0200
+++ linux-2.6.21.1.dev/fs/squashfs/squashfs.h 2007-05-26 19:43:37.075139168 +0200
@@ -24,6 +24,9 @@
#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
#undef CONFIG_SQUASHFS_1_0_COMPATIBILITY
#endif
+#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY
+#undef CONFIG_SQUASHFS_2_0_COMPATIBILITY
+#endif
#ifdef SQUASHFS_TRACE
#define TRACE(s, args...) printk(KERN_NOTICE "SQUASHFS: "s, ## args)

View File

@ -0,0 +1,20 @@
diff -urN linux-2.6.21.1.old/arch/mips/kernel/head.S linux-2.6.21.1.dev/arch/mips/kernel/head.S
--- linux-2.6.21.1.old/arch/mips/kernel/head.S 2007-04-27 23:49:26.000000000 +0200
+++ linux-2.6.21.1.dev/arch/mips/kernel/head.S 2007-05-26 19:46:49.061952736 +0200
@@ -129,11 +129,15 @@
#endif
.endm
+
+ j kernel_entry
+ nop
+
/*
* Reserved space for exception handlers.
* Necessary for machines which link their kernels at KSEG0.
*/
- .fill 0x400
+ .align 10
EXPORT(stext) # used for profiling
EXPORT(_stext)

View File

@ -0,0 +1,19 @@
diff -urN linux-2.6.21.1.old/arch/mips/mm/tlbex.c linux-2.6.21.1.dev/arch/mips/mm/tlbex.c
--- linux-2.6.21.1.old/arch/mips/mm/tlbex.c 2007-04-27 23:49:26.000000000 +0200
+++ linux-2.6.21.1.dev/arch/mips/mm/tlbex.c 2007-05-26 19:50:19.046030304 +0200
@@ -887,7 +887,6 @@
case CPU_R10000:
case CPU_R12000:
case CPU_R14000:
- case CPU_4KC:
case CPU_SB1:
case CPU_SB1A:
case CPU_4KSC:
@@ -915,6 +914,7 @@
tlbw(p);
break;
+ case CPU_4KC:
case CPU_4KEC:
case CPU_24K:
case CPU_34K:

View File

@ -0,0 +1,35 @@
diff -urN linux-2.6.21.1.old/arch/mips/defconfig linux-2.6.21.1.dev/arch/mips/defconfig
--- linux-2.6.21.1.old/arch/mips/defconfig 2007-04-27 23:49:26.000000000 +0200
+++ linux-2.6.21.1.dev/arch/mips/defconfig 2007-05-26 19:55:17.542651920 +0200
@@ -69,6 +69,7 @@
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_GPIO=n
CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
CONFIG_ARC=y
diff -urN linux-2.6.21.1.old/arch/mips/Kconfig linux-2.6.21.1.dev/arch/mips/Kconfig
--- linux-2.6.21.1.old/arch/mips/Kconfig 2007-04-27 23:49:26.000000000 +0200
+++ linux-2.6.21.1.dev/arch/mips/Kconfig 2007-05-26 19:55:17.500658304 +0200
@@ -704,6 +704,10 @@
bool
default y
+config GENERIC_GPIO
+ bool
+ default n
+
config SCHED_NO_NO_OMIT_FRAME_POINTER
bool
default y
diff -urN linux-2.6.21.1.old/include/asm-mips/gpio.h linux-2.6.21.1.dev/include/asm-mips/gpio.h
--- linux-2.6.21.1.old/include/asm-mips/gpio.h 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.21.1.dev/include/asm-mips/gpio.h 2007-05-26 19:55:17.500658304 +0200
@@ -0,0 +1,6 @@
+#ifndef _ASM_MIPS_GPIO_H
+#define _ASM_MIPS_GPIO_H
+
+#include <gpio.h>
+
+#endif /* _ASM_MIPS_GPIO_H */

View File

@ -0,0 +1,410 @@
diff -urN linux-2.6.21.1.old/drivers/mtd/Kconfig linux-2.6.21.1.dev/drivers/mtd/Kconfig
--- linux-2.6.21.1.old/drivers/mtd/Kconfig 2007-04-27 23:49:26.000000000 +0200
+++ linux-2.6.21.1.dev/drivers/mtd/Kconfig 2007-05-26 19:58:42.320520952 +0200
@@ -47,6 +47,11 @@
devices. Partitioning on NFTL 'devices' is a different - that's the
'normal' form of partitioning used on a block device.
+config MTD_SPLIT_ROOTFS
+ bool "Automatically split rootfs partition for squashfs"
+ depends on MTD_PARTITIONS
+ default y
+
config MTD_REDBOOT_PARTS
tristate "RedBoot partition table parsing"
depends on MTD_PARTITIONS
diff -urN linux-2.6.21.1.old/drivers/mtd/mtdpart.c linux-2.6.21.1.dev/drivers/mtd/mtdpart.c
--- linux-2.6.21.1.old/drivers/mtd/mtdpart.c 2007-04-27 23:49:26.000000000 +0200
+++ linux-2.6.21.1.dev/drivers/mtd/mtdpart.c 2007-05-26 19:58:42.331519280 +0200
@@ -20,6 +20,8 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/compatmac.h>
+#include <linux/squashfs_fs.h>
+#include <linux/root_dev.h>
/* Our partition linked list */
static LIST_HEAD(mtd_partitions);
@@ -308,6 +310,171 @@
return 0;
}
+static u_int32_t cur_offset = 0;
+static int add_mtd_partition(struct mtd_info *master, const struct mtd_partition *part, int i)
+{
+ struct mtd_part *slave;
+
+ /* allocate the partition structure */
+ slave = kzalloc (sizeof(*slave), GFP_KERNEL);
+ if (!slave) {
+ printk ("memory allocation error while creating partitions for \"%s\"\n",
+ master->name);
+ del_mtd_partitions(master);
+ return -ENOMEM;
+ }
+ list_add(&slave->list, &mtd_partitions);
+
+ /* set up the MTD object for this partition */
+ slave->mtd.type = master->type;
+ slave->mtd.flags = master->flags & ~part->mask_flags;
+ slave->mtd.size = part->size;
+ slave->mtd.writesize = master->writesize;
+ slave->mtd.oobsize = master->oobsize;
+ slave->mtd.oobavail = master->oobavail;
+ slave->mtd.subpage_sft = master->subpage_sft;
+
+ slave->mtd.name = part->name;
+ slave->mtd.owner = master->owner;
+
+ slave->mtd.read = part_read;
+ slave->mtd.write = part_write;
+
+ if(master->point && master->unpoint){
+ slave->mtd.point = part_point;
+ slave->mtd.unpoint = part_unpoint;
+ }
+
+ if (master->read_oob)
+ slave->mtd.read_oob = part_read_oob;
+ if (master->write_oob)
+ slave->mtd.write_oob = part_write_oob;
+ if(master->read_user_prot_reg)
+ slave->mtd.read_user_prot_reg = part_read_user_prot_reg;
+ if(master->read_fact_prot_reg)
+ slave->mtd.read_fact_prot_reg = part_read_fact_prot_reg;
+ if(master->write_user_prot_reg)
+ slave->mtd.write_user_prot_reg = part_write_user_prot_reg;
+ if(master->lock_user_prot_reg)
+ slave->mtd.lock_user_prot_reg = part_lock_user_prot_reg;
+ if(master->get_user_prot_info)
+ slave->mtd.get_user_prot_info = part_get_user_prot_info;
+ if(master->get_fact_prot_info)
+ slave->mtd.get_fact_prot_info = part_get_fact_prot_info;
+ if (master->sync)
+ slave->mtd.sync = part_sync;
+ if (!i && master->suspend && master->resume) {
+ slave->mtd.suspend = part_suspend;
+ slave->mtd.resume = part_resume;
+ }
+ if (master->writev)
+ slave->mtd.writev = part_writev;
+ if (master->lock)
+ slave->mtd.lock = part_lock;
+ if (master->unlock)
+ slave->mtd.unlock = part_unlock;
+ if (master->block_isbad)
+ slave->mtd.block_isbad = part_block_isbad;
+ if (master->block_markbad)
+ slave->mtd.block_markbad = part_block_markbad;
+ slave->mtd.erase = part_erase;
+ slave->master = master;
+ slave->offset = part->offset;
+ slave->index = i;
+
+ if (slave->offset == MTDPART_OFS_APPEND)
+ slave->offset = cur_offset;
+ if (slave->offset == MTDPART_OFS_NXTBLK) {
+ slave->offset = cur_offset;
+ if ((cur_offset % master->erasesize) != 0) {
+ /* Round up to next erasesize */
+ slave->offset = ((cur_offset / master->erasesize) + 1) * master->erasesize;
+ printk(KERN_NOTICE "Moving partition %d: "
+ "0x%08x -> 0x%08x\n", i,
+ cur_offset, slave->offset);
+ }
+ }
+ if (slave->mtd.size == MTDPART_SIZ_FULL)
+ slave->mtd.size = master->size - slave->offset;
+ cur_offset = slave->offset + slave->mtd.size;
+
+ printk (KERN_NOTICE "0x%08x-0x%08x : \"%s\"\n", slave->offset,
+ slave->offset + slave->mtd.size, slave->mtd.name);
+
+ /* let's do some sanity checks */
+ if (slave->offset >= master->size) {
+ /* let's register it anyway to preserve ordering */
+ slave->offset = 0;
+ slave->mtd.size = 0;
+ printk ("mtd: partition \"%s\" is out of reach -- disabled\n",
+ part->name);
+ }
+ if (slave->offset + slave->mtd.size > master->size) {
+ slave->mtd.size = master->size - slave->offset;
+ printk ("mtd: partition \"%s\" extends beyond the end of device \"%s\" -- size truncated to %#x\n",
+ part->name, master->name, slave->mtd.size);
+ }
+ if (master->numeraseregions>1) {
+ /* Deal with variable erase size stuff */
+ int i;
+ struct mtd_erase_region_info *regions = master->eraseregions;
+
+ /* Find the first erase regions which is part of this partition. */
+ for (i=0; i < master->numeraseregions && slave->offset >= regions[i].offset; i++)
+ ;
+
+ for (i--; i < master->numeraseregions && slave->offset + slave->mtd.size > regions[i].offset; i++) {
+ if (slave->mtd.erasesize < regions[i].erasesize) {
+ slave->mtd.erasesize = regions[i].erasesize;
+ }
+ }
+ } else {
+ /* Single erase size */
+ slave->mtd.erasesize = master->erasesize;
+ }
+
+ if ((slave->mtd.flags & MTD_WRITEABLE) &&
+ (slave->offset % slave->mtd.erasesize)) {
+ /* Doesn't start on a boundary of major erase size */
+ /* FIXME: Let it be writable if it is on a boundary of _minor_ erase size though */
+ slave->mtd.flags &= ~MTD_WRITEABLE;
+ printk ("mtd: partition \"%s\" doesn't start on an erase block boundary -- force read-only\n",
+ part->name);
+ }
+ if ((slave->mtd.flags & MTD_WRITEABLE) &&
+ (slave->mtd.size % slave->mtd.erasesize)) {
+ slave->mtd.flags &= ~MTD_WRITEABLE;
+ printk ("mtd: partition \"%s\" doesn't end on an erase block -- force read-only\n",
+ part->name);
+ }
+
+ slave->mtd.ecclayout = master->ecclayout;
+ if (master->block_isbad) {
+ uint32_t offs = 0;
+
+ while(offs < slave->mtd.size) {
+ if (master->block_isbad(master,
+ offs + slave->offset))
+ slave->mtd.ecc_stats.badblocks++;
+ offs += slave->mtd.erasesize;
+ }
+ }
+
+ if(part->mtdp)
+ { /* store the object pointer (caller may or may not register it */
+ *part->mtdp = &slave->mtd;
+ slave->registered = 0;
+ }
+ else
+ {
+ /* register our partition */
+ add_mtd_device(&slave->mtd);
+ slave->registered = 1;
+ }
+
+ return 0;
+}
+
/*
* This function, given a master MTD object and a partition table, creates
* and registers slave MTD objects which are bound to the master according to
@@ -319,169 +487,53 @@
const struct mtd_partition *parts,
int nbparts)
{
- struct mtd_part *slave;
- u_int32_t cur_offset = 0;
- int i;
+ struct mtd_partition *part;
+ int i, ret = 0;
printk (KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name);
for (i = 0; i < nbparts; i++) {
+ part = (struct mtd_partition *) &parts[i];
+ ret = add_mtd_partition(master, part, i);
+ if (ret)
+ return ret;
+ if (strcmp(part->name, "rootfs") == 0) {
+#ifdef CONFIG_MTD_SPLIT_ROOTFS
+ int len;
+ char buf[512];
+ struct squashfs_super_block *sb = (struct squashfs_super_block *) buf;
+#define ROOTFS_SPLIT_NAME "rootfs_data"
+ if ((master->read(master, part->offset, sizeof(struct squashfs_super_block), &len, buf) == 0) &&
+ (len == sizeof(struct squashfs_super_block)) &&
+ (*((u32 *) buf) == SQUASHFS_MAGIC) &&
+ (sb->bytes_used > 0)) {
+
+
+ part = kmalloc(sizeof(struct mtd_partition), GFP_KERNEL);
+ memcpy(part, &parts[i], sizeof(struct mtd_partition));
+
+ part->name = kmalloc(sizeof(ROOTFS_SPLIT_NAME) + 1, GFP_KERNEL);
+ strcpy(part->name, ROOTFS_SPLIT_NAME);
+
+ len = (u32) sb->bytes_used;
+ len += (part->offset & 0x000fffff);
+ len += (master->erasesize - 1);
+ len &= ~(master->erasesize - 1);
+ len -= (part->offset & 0x000fffff);
+ part->offset += len;
+ part->size -= len;
+
+ if (master->erasesize <= part->size)
+ ret = add_mtd_partition(master, part, i + 1);
+ else
+ kfree(part->name);
+ if (ret)
+ return ret;
- /* allocate the partition structure */
- slave = kzalloc (sizeof(*slave), GFP_KERNEL);
- if (!slave) {
- printk ("memory allocation error while creating partitions for \"%s\"\n",
- master->name);
- del_mtd_partitions(master);
- return -ENOMEM;
- }
- list_add(&slave->list, &mtd_partitions);
-
- /* set up the MTD object for this partition */
- slave->mtd.type = master->type;
- slave->mtd.flags = master->flags & ~parts[i].mask_flags;
- slave->mtd.size = parts[i].size;
- slave->mtd.writesize = master->writesize;
- slave->mtd.oobsize = master->oobsize;
- slave->mtd.oobavail = master->oobavail;
- slave->mtd.subpage_sft = master->subpage_sft;
-
- slave->mtd.name = parts[i].name;
- slave->mtd.owner = master->owner;
-
- slave->mtd.read = part_read;
- slave->mtd.write = part_write;
-
- if(master->point && master->unpoint){
- slave->mtd.point = part_point;
- slave->mtd.unpoint = part_unpoint;
- }
-
- if (master->read_oob)
- slave->mtd.read_oob = part_read_oob;
- if (master->write_oob)
- slave->mtd.write_oob = part_write_oob;
- if(master->read_user_prot_reg)
- slave->mtd.read_user_prot_reg = part_read_user_prot_reg;
- if(master->read_fact_prot_reg)
- slave->mtd.read_fact_prot_reg = part_read_fact_prot_reg;
- if(master->write_user_prot_reg)
- slave->mtd.write_user_prot_reg = part_write_user_prot_reg;
- if(master->lock_user_prot_reg)
- slave->mtd.lock_user_prot_reg = part_lock_user_prot_reg;
- if(master->get_user_prot_info)
- slave->mtd.get_user_prot_info = part_get_user_prot_info;
- if(master->get_fact_prot_info)
- slave->mtd.get_fact_prot_info = part_get_fact_prot_info;
- if (master->sync)
- slave->mtd.sync = part_sync;
- if (!i && master->suspend && master->resume) {
- slave->mtd.suspend = part_suspend;
- slave->mtd.resume = part_resume;
- }
- if (master->writev)
- slave->mtd.writev = part_writev;
- if (master->lock)
- slave->mtd.lock = part_lock;
- if (master->unlock)
- slave->mtd.unlock = part_unlock;
- if (master->block_isbad)
- slave->mtd.block_isbad = part_block_isbad;
- if (master->block_markbad)
- slave->mtd.block_markbad = part_block_markbad;
- slave->mtd.erase = part_erase;
- slave->master = master;
- slave->offset = parts[i].offset;
- slave->index = i;
-
- if (slave->offset == MTDPART_OFS_APPEND)
- slave->offset = cur_offset;
- if (slave->offset == MTDPART_OFS_NXTBLK) {
- slave->offset = cur_offset;
- if ((cur_offset % master->erasesize) != 0) {
- /* Round up to next erasesize */
- slave->offset = ((cur_offset / master->erasesize) + 1) * master->erasesize;
- printk(KERN_NOTICE "Moving partition %d: "
- "0x%08x -> 0x%08x\n", i,
- cur_offset, slave->offset);
+ kfree(part);
}
- }
- if (slave->mtd.size == MTDPART_SIZ_FULL)
- slave->mtd.size = master->size - slave->offset;
- cur_offset = slave->offset + slave->mtd.size;
-
- printk (KERN_NOTICE "0x%08x-0x%08x : \"%s\"\n", slave->offset,
- slave->offset + slave->mtd.size, slave->mtd.name);
-
- /* let's do some sanity checks */
- if (slave->offset >= master->size) {
- /* let's register it anyway to preserve ordering */
- slave->offset = 0;
- slave->mtd.size = 0;
- printk ("mtd: partition \"%s\" is out of reach -- disabled\n",
- parts[i].name);
- }
- if (slave->offset + slave->mtd.size > master->size) {
- slave->mtd.size = master->size - slave->offset;
- printk ("mtd: partition \"%s\" extends beyond the end of device \"%s\" -- size truncated to %#x\n",
- parts[i].name, master->name, slave->mtd.size);
- }
- if (master->numeraseregions>1) {
- /* Deal with variable erase size stuff */
- int i;
- struct mtd_erase_region_info *regions = master->eraseregions;
-
- /* Find the first erase regions which is part of this partition. */
- for (i=0; i < master->numeraseregions && slave->offset >= regions[i].offset; i++)
- ;
-
- for (i--; i < master->numeraseregions && slave->offset + slave->mtd.size > regions[i].offset; i++) {
- if (slave->mtd.erasesize < regions[i].erasesize) {
- slave->mtd.erasesize = regions[i].erasesize;
- }
- }
- } else {
- /* Single erase size */
- slave->mtd.erasesize = master->erasesize;
- }
-
- if ((slave->mtd.flags & MTD_WRITEABLE) &&
- (slave->offset % slave->mtd.erasesize)) {
- /* Doesn't start on a boundary of major erase size */
- /* FIXME: Let it be writable if it is on a boundary of _minor_ erase size though */
- slave->mtd.flags &= ~MTD_WRITEABLE;
- printk ("mtd: partition \"%s\" doesn't start on an erase block boundary -- force read-only\n",
- parts[i].name);
- }
- if ((slave->mtd.flags & MTD_WRITEABLE) &&
- (slave->mtd.size % slave->mtd.erasesize)) {
- slave->mtd.flags &= ~MTD_WRITEABLE;
- printk ("mtd: partition \"%s\" doesn't end on an erase block -- force read-only\n",
- parts[i].name);
- }
-
- slave->mtd.ecclayout = master->ecclayout;
- if (master->block_isbad) {
- uint32_t offs = 0;
-
- while(offs < slave->mtd.size) {
- if (master->block_isbad(master,
- offs + slave->offset))
- slave->mtd.ecc_stats.badblocks++;
- offs += slave->mtd.erasesize;
- }
- }
-
- if(parts[i].mtdp)
- { /* store the object pointer (caller may or may not register it */
- *parts[i].mtdp = &slave->mtd;
- slave->registered = 0;
- }
- else
- {
- /* register our partition */
- add_mtd_device(&slave->mtd);
- slave->registered = 1;
+#endif /* CONFIG_MTD_SPLIT_ROOTFS */
+ ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, i);
}
}

View File

@ -0,0 +1,113 @@
diff -urN linux-2.6.21.1.old/drivers/mtd/devices/block2mtd.c linux-2.6.21.1.dev/drivers/mtd/devices/block2mtd.c
--- linux-2.6.21.1.old/drivers/mtd/devices/block2mtd.c 2007-04-27 23:49:26.000000000 +0200
+++ linux-2.6.21.1.dev/drivers/mtd/devices/block2mtd.c 2007-05-26 20:06:13.547923960 +0200
@@ -16,6 +16,7 @@
#include <linux/list.h>
#include <linux/init.h>
#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
#include <linux/buffer_head.h>
#include <linux/mutex.h>
#include <linux/mount.h>
@@ -237,10 +238,11 @@
/* FIXME: ensure that mtd->size % erase_size == 0 */
-static struct block2mtd_dev *add_device(char *devname, int erase_size)
+static struct block2mtd_dev *add_device(char *devname, int erase_size, char *mtdname)
{
struct block_device *bdev;
struct block2mtd_dev *dev;
+ struct mtd_partition *part;
if (!devname)
return NULL;
@@ -279,14 +281,18 @@
/* Setup the MTD structure */
/* make the name contain the block device in */
- dev->mtd.name = kmalloc(sizeof("block2mtd: ") + strlen(devname),
- GFP_KERNEL);
+
+ if (!mtdname)
+ mtdname = devname;
+
+ dev->mtd.name = kmalloc(strlen(mtdname), GFP_KERNEL);
+
if (!dev->mtd.name)
goto devinit_err;
+
+ strcpy(dev->mtd.name, mtdname);
- sprintf(dev->mtd.name, "block2mtd: %s", devname);
-
- dev->mtd.size = dev->blkdev->bd_inode->i_size & PAGE_MASK;
+ dev->mtd.size = dev->blkdev->bd_inode->i_size & PAGE_MASK & ~(erase_size - 1);
dev->mtd.erasesize = erase_size;
dev->mtd.writesize = 1;
dev->mtd.type = MTD_RAM;
@@ -298,15 +304,18 @@
dev->mtd.read = block2mtd_read;
dev->mtd.priv = dev;
dev->mtd.owner = THIS_MODULE;
-
- if (add_mtd_device(&dev->mtd)) {
+
+ part = kzalloc(sizeof(struct mtd_partition), GFP_KERNEL);
+ part->name = dev->mtd.name;
+ part->offset = 0;
+ part->size = dev->mtd.size;
+ if (add_mtd_partitions(&dev->mtd, part, 1)) {
/* Device didnt get added, so free the entry */
goto devinit_err;
}
list_add(&dev->list, &blkmtd_device_list);
INFO("mtd%d: [%s] erase_size = %dKiB [%d]", dev->mtd.index,
- dev->mtd.name + strlen("blkmtd: "),
- dev->mtd.erasesize >> 10, dev->mtd.erasesize);
+ mtdname, dev->mtd.erasesize >> 10, dev->mtd.erasesize);
return dev;
devinit_err:
@@ -379,9 +388,9 @@
static int block2mtd_setup2(const char *val)
{
- char buf[80 + 12]; /* 80 for device, 12 for erase size */
+ char buf[80 + 12 + 80]; /* 80 for device, 12 for erase size, 80 for name */
char *str = buf;
- char *token[2];
+ char *token[3];
char *name;
size_t erase_size = PAGE_SIZE;
int i, ret;
@@ -392,7 +401,7 @@
strcpy(str, val);
kill_final_newline(str);
- for (i = 0; i < 2; i++)
+ for (i = 0; i < 3; i++)
token[i] = strsep(&str, ",");
if (str)
@@ -412,8 +421,10 @@
parse_err("illegal erase size");
}
}
+ if (token[2] && (strlen(token[2]) + 1 > 80))
+ parse_err("mtd device name too long");
- add_device(name, erase_size);
+ add_device(name, erase_size, token[2]);
return 0;
}
@@ -447,7 +458,7 @@
module_param_call(block2mtd, block2mtd_setup, NULL, NULL, 0200);
-MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=<dev>[,<erasesize>]\"");
+MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=<dev>[,<erasesize>[,<name>]]\"");
static int __init block2mtd_init(void)
{

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,108 @@
diff -urN linux-2.6.21.1.old/include/linux/netfilter_ipv4/ipt_layer7.h linux-2.6.21.1.dev/include/linux/netfilter_ipv4/ipt_layer7.h
--- linux-2.6.21.1.old/include/linux/netfilter_ipv4/ipt_layer7.h 2007-05-26 20:17:47.624408296 +0200
+++ linux-2.6.21.1.dev/include/linux/netfilter_ipv4/ipt_layer7.h 2007-05-26 20:17:48.729240336 +0200
@@ -21,6 +21,7 @@
char protocol[MAX_PROTOCOL_LEN];
char invert:1;
char pattern[MAX_PATTERN_LEN];
+ char pkt;
};
#endif /* _IPT_LAYER7_H */
diff -urN linux-2.6.21.1.old/net/ipv4/netfilter/ipt_layer7.c linux-2.6.21.1.dev/net/ipv4/netfilter/ipt_layer7.c
--- linux-2.6.21.1.old/net/ipv4/netfilter/ipt_layer7.c 2007-05-26 20:17:47.626407992 +0200
+++ linux-2.6.21.1.dev/net/ipv4/netfilter/ipt_layer7.c 2007-05-26 20:17:48.729240336 +0200
@@ -296,33 +296,34 @@
}
}
-/* add the new app data to the conntrack. Return number of bytes added. */
-static int add_data(struct ip_conntrack * master_conntrack,
- char * app_data, int appdatalen)
+static int add_datastr(char *target, int offset, char *app_data, int len)
{
int length = 0, i;
- int oldlength = master_conntrack->layer7.app_data_len;
-
- // This is a fix for a race condition by Deti Fliegl. However, I'm not
- // clear on whether the race condition exists or whether this really
- // fixes it. I might just be being dense... Anyway, if it's not really
- // a fix, all it does is waste a very small amount of time.
- if(!master_conntrack->layer7.app_data) return 0;
+ if(!target) return 0;
/* Strip nulls. Make everything lower case (our regex lib doesn't
do case insensitivity). Add it to the end of the current data. */
- for(i = 0; i < maxdatalen-oldlength-1 &&
- i < appdatalen; i++) {
+ for(i = 0; i < maxdatalen-offset-1 && i < len; i++) {
if(app_data[i] != '\0') {
- master_conntrack->layer7.app_data[length+oldlength] =
+ target[length+offset] =
/* the kernel version of tolower mungs 'upper ascii' */
isascii(app_data[i])? tolower(app_data[i]) : app_data[i];
length++;
}
}
+ target[length+offset] = '\0';
- master_conntrack->layer7.app_data[length+oldlength] = '\0';
- master_conntrack->layer7.app_data_len = length + oldlength;
+ return length;
+}
+
+/* add the new app data to the conntrack. Return number of bytes added. */
+static int add_data(struct ip_conntrack * master_conntrack,
+ char * app_data, int appdatalen)
+{
+ int length;
+
+ length = add_datastr(master_conntrack->layer7.app_data, master_conntrack->layer7.app_data_len, app_data, appdatalen);
+ master_conntrack->layer7.app_data_len += length;
return length;
}
@@ -339,7 +340,7 @@
struct ipt_layer7_info * info = (struct ipt_layer7_info *)matchinfo;
enum ip_conntrack_info master_ctinfo, ctinfo;
struct ip_conntrack *master_conntrack, *conntrack;
- unsigned char * app_data;
+ unsigned char *app_data, *tmp_data;
unsigned int pattern_result, appdatalen;
regexp * comppattern;
@@ -362,8 +363,8 @@
master_conntrack = master_ct(master_conntrack);
/* if we've classified it or seen too many packets */
- if(TOTAL_PACKETS > num_packets ||
- master_conntrack->layer7.app_proto) {
+ if(!info->pkt && (TOTAL_PACKETS > num_packets ||
+ master_conntrack->layer7.app_proto)) {
pattern_result = match_no_append(conntrack, master_conntrack, ctinfo, master_ctinfo, info);
@@ -394,6 +395,23 @@
comppattern = compile_and_cache(info->pattern, info->protocol);
spin_unlock_bh(&list_lock);
+ if (info->pkt) {
+ tmp_data = kmalloc(maxdatalen, GFP_ATOMIC);
+ if(!tmp_data){
+ if (net_ratelimit())
+ printk(KERN_ERR "layer7: out of memory in match, bailing.\n");
+ return info->invert;
+ }
+
+ tmp_data[0] = '\0';
+ add_datastr(tmp_data, 0, app_data, appdatalen);
+ pattern_result = ((comppattern && regexec(comppattern, tmp_data)) ? 1 : 0);
+ kfree(tmp_data);
+ tmp_data = NULL;
+
+ return (pattern_result ^ info->invert);
+ }
+
/* On the first packet of a connection, allocate space for app data */
write_lock(&ct_lock);
if(TOTAL_PACKETS == 1 && !skb->cb[0] && !master_conntrack->layer7.app_data) {

View File

@ -0,0 +1,948 @@
diff -urN linux-2.6.21.1.old/include/linux/netfilter_ipv4/ipt_ipp2p.h linux-2.6.21.1.dev/include/linux/netfilter_ipv4/ipt_ipp2p.h
--- linux-2.6.21.1.old/include/linux/netfilter_ipv4/ipt_ipp2p.h 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.21.1.dev/include/linux/netfilter_ipv4/ipt_ipp2p.h 2007-05-26 20:21:54.586864296 +0200
@@ -0,0 +1,31 @@
+#ifndef __IPT_IPP2P_H
+#define __IPT_IPP2P_H
+#define IPP2P_VERSION "0.8.1_rc1"
+
+struct ipt_p2p_info {
+ int cmd;
+ int debug;
+};
+
+#endif //__IPT_IPP2P_H
+
+#define SHORT_HAND_IPP2P 1 /* --ipp2p switch*/
+//#define SHORT_HAND_DATA 4 /* --ipp2p-data switch*/
+#define SHORT_HAND_NONE 5 /* no short hand*/
+
+#define IPP2P_EDK (1 << 1)
+#define IPP2P_DATA_KAZAA (1 << 2)
+#define IPP2P_DATA_EDK (1 << 3)
+#define IPP2P_DATA_DC (1 << 4)
+#define IPP2P_DC (1 << 5)
+#define IPP2P_DATA_GNU (1 << 6)
+#define IPP2P_GNU (1 << 7)
+#define IPP2P_KAZAA (1 << 8)
+#define IPP2P_BIT (1 << 9)
+#define IPP2P_APPLE (1 << 10)
+#define IPP2P_SOUL (1 << 11)
+#define IPP2P_WINMX (1 << 12)
+#define IPP2P_ARES (1 << 13)
+#define IPP2P_MUTE (1 << 14)
+#define IPP2P_WASTE (1 << 15)
+#define IPP2P_XDCC (1 << 16)
diff -urN linux-2.6.21.1.old/net/ipv4/netfilter/ipt_ipp2p.c linux-2.6.21.1.dev/net/ipv4/netfilter/ipt_ipp2p.c
--- linux-2.6.21.1.old/net/ipv4/netfilter/ipt_ipp2p.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.21.1.dev/net/ipv4/netfilter/ipt_ipp2p.c 2007-05-26 20:21:54.587864144 +0200
@@ -0,0 +1,881 @@
+#if defined(MODVERSIONS)
+#include <linux/modversions.h>
+#endif
+#include <linux/module.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/version.h>
+#include <linux/netfilter_ipv4/ipt_ipp2p.h>
+#include <net/tcp.h>
+#include <net/udp.h>
+
+#define get_u8(X,O) (*(__u8 *)(X + O))
+#define get_u16(X,O) (*(__u16 *)(X + O))
+#define get_u32(X,O) (*(__u32 *)(X + O))
+
+MODULE_AUTHOR("Eicke Friedrich/Klaus Degner <ipp2p@ipp2p.org>");
+MODULE_DESCRIPTION("An extension to iptables to identify P2P traffic.");
+MODULE_LICENSE("GPL");
+
+
+/*Search for UDP eDonkey/eMule/Kad commands*/
+int
+udp_search_edk (unsigned char *haystack, int packet_len)
+{
+ unsigned char *t = haystack;
+ t += 8;
+
+ switch (t[0]) {
+ case 0xe3:
+ { /*edonkey*/
+ switch (t[1])
+ {
+ /* client -> server status request */
+ case 0x96:
+ if (packet_len == 14) return ((IPP2P_EDK * 100) + 50);
+ break;
+ /* server -> client status request */
+ case 0x97: if (packet_len == 42) return ((IPP2P_EDK * 100) + 51);
+ break;
+ /* server description request */
+ /* e3 2a ff f0 .. | size == 6 */
+ case 0xa2: if ( (packet_len == 14) && ( get_u16(t,2) == __constant_htons(0xfff0) ) ) return ((IPP2P_EDK * 100) + 52);
+ break;
+ /* server description response */
+ /* e3 a3 ff f0 .. | size > 40 && size < 200 */
+ //case 0xa3: return ((IPP2P_EDK * 100) + 53);
+ // break;
+ case 0x9a: if (packet_len==26) return ((IPP2P_EDK * 100) + 54);
+ break;
+
+ case 0x92: if (packet_len==18) return ((IPP2P_EDK * 100) + 55);
+ break;
+ }
+ break;
+ }
+ case 0xe4:
+ {
+ switch (t[1])
+ {
+ /* e4 20 .. | size == 43 */
+ case 0x20: if ((packet_len == 43) && (t[2] != 0x00) && (t[34] != 0x00)) return ((IPP2P_EDK * 100) + 60);
+ break;
+ /* e4 00 .. 00 | size == 35 ? */
+ case 0x00: if ((packet_len == 35) && (t[26] == 0x00)) return ((IPP2P_EDK * 100) + 61);
+ break;
+ /* e4 10 .. 00 | size == 35 ? */
+ case 0x10: if ((packet_len == 35) && (t[26] == 0x00)) return ((IPP2P_EDK * 100) + 62);
+ break;
+ /* e4 18 .. 00 | size == 35 ? */
+ case 0x18: if ((packet_len == 35) && (t[26] == 0x00)) return ((IPP2P_EDK * 100) + 63);
+ break;
+ /* e4 52 .. | size = 44 */
+ case 0x52: if (packet_len == 44 ) return ((IPP2P_EDK * 100) + 64);
+ break;
+ /* e4 58 .. | size == 6 */
+ case 0x58: if (packet_len == 14 ) return ((IPP2P_EDK * 100) + 65);
+ break;
+ /* e4 59 .. | size == 2 */
+ case 0x59: if (packet_len == 10 )return ((IPP2P_EDK * 100) + 66);
+ break;
+ /* e4 28 .. | packet_len == 52,77,102,127... */
+ case 0x28: if (((packet_len-52) % 25) == 0) return ((IPP2P_EDK * 100) + 67);
+ break;
+ /* e4 50 xx xx | size == 4 */
+ case 0x50: if (packet_len == 12) return ((IPP2P_EDK * 100) + 68);
+ break;
+ /* e4 40 xx xx | size == 48 */
+ case 0x40: if (packet_len == 56) return ((IPP2P_EDK * 100) + 69);
+ break;
+ }
+ break;
+ }
+ } /* end of switch (t[0]) */
+ return 0;
+}/*udp_search_edk*/
+
+
+/*Search for UDP Gnutella commands*/
+int
+udp_search_gnu (unsigned char *haystack, int packet_len)
+{
+ unsigned char *t = haystack;
+ t += 8;
+
+ if (memcmp(t, "GND", 3) == 0) return ((IPP2P_GNU * 100) + 51);
+ if (memcmp(t, "GNUTELLA ", 9) == 0) return ((IPP2P_GNU * 100) + 52);
+ return 0;
+}/*udp_search_gnu*/
+
+
+/*Search for UDP KaZaA commands*/
+int
+udp_search_kazaa (unsigned char *haystack, int packet_len)
+{
+ unsigned char *t = haystack;
+
+ if (t[packet_len-1] == 0x00){
+ t += (packet_len - 6);
+ if (memcmp(t, "KaZaA", 5) == 0) return (IPP2P_KAZAA * 100 +50);
+ }
+
+ return 0;
+}/*udp_search_kazaa*/
+
+/*Search for UDP DirectConnect commands*/
+int
+udp_search_directconnect (unsigned char *haystack, int packet_len)
+{
+ unsigned char *t = haystack;
+ if ((*(t + 8) == 0x24) && (*(t + packet_len - 1) == 0x7c)) {
+ t+=8;
+ if (memcmp(t, "SR ", 3) == 0) return ((IPP2P_DC * 100) + 60);
+ if (memcmp(t, "Ping ", 5) == 0) return ((IPP2P_DC * 100) + 61);
+ }
+ return 0;
+}/*udp_search_directconnect*/
+
+
+
+/*Search for UDP BitTorrent commands*/
+int
+udp_search_bit (unsigned char *haystack, int packet_len)
+{
+ switch(packet_len)
+ {
+ case 24:
+ /* ^ 00 00 04 17 27 10 19 80 */
+ if ((ntohl(get_u32(haystack, 8)) == 0x00000417) && (ntohl(get_u32(haystack, 12)) == 0x27101980))
+ return (IPP2P_BIT * 100 + 50);
+ break;
+ case 44:
+ if (get_u32(haystack, 16) == __constant_htonl(0x00000400) && get_u32(haystack, 36) == __constant_htonl(0x00000104))
+ return (IPP2P_BIT * 100 + 51);
+ if (get_u32(haystack, 16) == __constant_htonl(0x00000400))
+ return (IPP2P_BIT * 100 + 61);
+ break;
+ case 65:
+ if (get_u32(haystack, 16) == __constant_htonl(0x00000404) && get_u32(haystack, 36) == __constant_htonl(0x00000104))
+ return (IPP2P_BIT * 100 + 52);
+ if (get_u32(haystack, 16) == __constant_htonl(0x00000404))
+ return (IPP2P_BIT * 100 + 62);
+ break;
+ case 67:
+ if (get_u32(haystack, 16) == __constant_htonl(0x00000406) && get_u32(haystack, 36) == __constant_htonl(0x00000104))
+ return (IPP2P_BIT * 100 + 53);
+ if (get_u32(haystack, 16) == __constant_htonl(0x00000406))
+ return (IPP2P_BIT * 100 + 63);
+ break;
+ case 211:
+ if (get_u32(haystack, 8) == __constant_htonl(0x00000405))
+ return (IPP2P_BIT * 100 + 54);
+ break;
+ case 29:
+ if ((get_u32(haystack, 8) == __constant_htonl(0x00000401)))
+ return (IPP2P_BIT * 100 + 55);
+ break;
+ case 52:
+ if (get_u32(haystack,8) == __constant_htonl(0x00000827) &&
+ get_u32(haystack,12) == __constant_htonl(0x37502950))
+ return (IPP2P_BIT * 100 + 80);
+ break;
+ default:
+ /* this packet does not have a constant size */
+ if (packet_len >= 40 && get_u32(haystack, 16) == __constant_htonl(0x00000402) && get_u32(haystack, 36) == __constant_htonl(0x00000104))
+ return (IPP2P_BIT * 100 + 56);
+ break;
+ }
+
+ /* some extra-bitcomet rules:
+ * "d1:" [a|r] "d2:id20:"
+ */
+ if (packet_len > 30 && get_u8(haystack, 8) == 'd' && get_u8(haystack, 9) == '1' && get_u8(haystack, 10) == ':' )
+ {
+ if (get_u8(haystack, 11) == 'a' || get_u8(haystack, 11) == 'r')
+ {
+ if (memcmp(haystack+12,"d2:id20:",8)==0)
+ return (IPP2P_BIT * 100 + 57);
+ }
+ }
+
+#if 0
+ /* bitlord rules */
+ /* packetlen must be bigger than 40 */
+ /* first 4 bytes are zero */
+ if (packet_len > 40 && get_u32(haystack, 8) == 0x00000000)
+ {
+ /* first rule: 00 00 00 00 01 00 00 xx xx xx xx 00 00 00 00*/
+ if (get_u32(haystack, 12) == 0x00000000 &&
+ get_u32(haystack, 16) == 0x00010000 &&
+ get_u32(haystack, 24) == 0x00000000 )
+ return (IPP2P_BIT * 100 + 71);
+
+ /* 00 01 00 00 0d 00 00 xx xx xx xx 00 00 00 00*/
+ if (get_u32(haystack, 12) == 0x00000001 &&
+ get_u32(haystack, 16) == 0x000d0000 &&
+ get_u32(haystack, 24) == 0x00000000 )
+ return (IPP2P_BIT * 100 + 71);
+
+
+ }
+#endif
+
+ return 0;
+}/*udp_search_bit*/
+
+
+
+/*Search for Ares commands*/
+//#define IPP2P_DEBUG_ARES
+int
+search_ares (const unsigned char *payload, const u16 plen)
+//int search_ares (unsigned char *haystack, int packet_len, int head_len)
+{
+// const unsigned char *t = haystack + head_len;
+
+ /* all ares packets start with */
+ if (payload[1] == 0 && (plen - payload[0]) == 3)
+ {
+ switch (payload[2])
+ {
+ case 0x5a:
+ /* ares connect */
+ if ( plen == 6 && payload[5] == 0x05 ) return ((IPP2P_ARES * 100) + 1);
+ break;
+ case 0x09:
+ /* ares search, min 3 chars --> 14 bytes
+ * lets define a search can be up to 30 chars --> max 34 bytes
+ */
+ if ( plen >= 14 && plen <= 34 ) return ((IPP2P_ARES * 100) + 1);
+ break;
+#ifdef IPP2P_DEBUG_ARES
+ default:
+ printk(KERN_DEBUG "Unknown Ares command %x recognized, len: %u \n", (unsigned int) payload[2],plen);
+#endif /* IPP2P_DEBUG_ARES */
+ }
+ }
+
+#if 0
+ /* found connect packet: 03 00 5a 04 03 05 */
+ /* new version ares 1.8: 03 00 5a xx xx 05 */
+ if ((plen) == 6){ /* possible connect command*/
+ if ((payload[0] == 0x03) && (payload[1] == 0x00) && (payload[2] == 0x5a) && (payload[5] == 0x05))
+ return ((IPP2P_ARES * 100) + 1);
+ }
+ if ((plen) == 60){ /* possible download command*/
+ if ((payload[59] == 0x0a) && (payload[58] == 0x0a)){
+ if (memcmp(t, "PUSH SHA1:", 10) == 0) /* found download command */
+ return ((IPP2P_ARES * 100) + 2);
+ }
+ }
+#endif
+
+ return 0;
+} /*search_ares*/
+
+/*Search for SoulSeek commands*/
+int
+search_soul (const unsigned char *payload, const u16 plen)
+{
+//#define IPP2P_DEBUG_SOUL
+ /* match: xx xx xx xx | xx = sizeof(payload) - 4 */
+ if (get_u32(payload, 0) == (plen - 4)){
+ const __u32 m=get_u32(payload, 4);
+ /* match 00 yy yy 00, yy can be everything */
+ if ( get_u8(payload, 4) == 0x00 && get_u8(payload, 7) == 0x00 )
+ {
+#ifdef IPP2P_DEBUG_SOUL
+ printk(KERN_DEBUG "0: Soulseek command 0x%x recognized\n",get_u32(payload, 4));
+#endif /* IPP2P_DEBUG_SOUL */
+ return ((IPP2P_SOUL * 100) + 1);
+ }
+
+ /* next match: 01 yy 00 00 | yy can be everything */
+ if ( get_u8(payload, 4) == 0x01 && get_u16(payload, 6) == 0x0000 )
+ {
+#ifdef IPP2P_DEBUG_SOUL
+ printk(KERN_DEBUG "1: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
+#endif /* IPP2P_DEBUG_SOUL */
+ return ((IPP2P_SOUL * 100) + 2);
+ }
+
+ /* other soulseek commandos are: 1-5,7,9,13-18,22,23,26,28,35-37,40-46,50,51,60,62-69,91,92,1001 */
+ /* try to do this in an intelligent way */
+ /* get all small commandos */
+ switch(m)
+ {
+ case 7:
+ case 9:
+ case 22:
+ case 23:
+ case 26:
+ case 28:
+ case 50:
+ case 51:
+ case 60:
+ case 91:
+ case 92:
+ case 1001:
+#ifdef IPP2P_DEBUG_SOUL
+ printk(KERN_DEBUG "2: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
+#endif /* IPP2P_DEBUG_SOUL */
+ return ((IPP2P_SOUL * 100) + 3);
+ }
+
+ if (m > 0 && m < 6 )
+ {
+#ifdef IPP2P_DEBUG_SOUL
+ printk(KERN_DEBUG "3: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
+#endif /* IPP2P_DEBUG_SOUL */
+ return ((IPP2P_SOUL * 100) + 4);
+ }
+ if (m > 12 && m < 19 )
+ {
+#ifdef IPP2P_DEBUG_SOUL
+ printk(KERN_DEBUG "4: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
+#endif /* IPP2P_DEBUG_SOUL */
+ return ((IPP2P_SOUL * 100) + 5);
+ }
+
+ if (m > 34 && m < 38 )
+ {
+#ifdef IPP2P_DEBUG_SOUL
+ printk(KERN_DEBUG "5: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
+#endif /* IPP2P_DEBUG_SOUL */
+ return ((IPP2P_SOUL * 100) + 6);
+ }
+
+ if (m > 39 && m < 47 )
+ {
+#ifdef IPP2P_DEBUG_SOUL
+ printk(KERN_DEBUG "6: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
+#endif /* IPP2P_DEBUG_SOUL */
+ return ((IPP2P_SOUL * 100) + 7);
+ }
+
+ if (m > 61 && m < 70 )
+ {
+#ifdef IPP2P_DEBUG_SOUL
+ printk(KERN_DEBUG "7: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
+#endif /* IPP2P_DEBUG_SOUL */
+ return ((IPP2P_SOUL * 100) + 8);
+ }
+
+#ifdef IPP2P_DEBUG_SOUL
+ printk(KERN_DEBUG "unknown SOULSEEK command: 0x%x, first 16 bit: 0x%x, first 8 bit: 0x%x ,soulseek ???\n",get_u32(payload, 4),get_u16(payload, 4) >> 16,get_u8(payload, 4) >> 24);
+#endif /* IPP2P_DEBUG_SOUL */
+ }
+
+ /* match 14 00 00 00 01 yy 00 00 00 STRING(YY) 01 00 00 00 00 46|50 00 00 00 00 */
+ /* without size at the beginning !!! */
+ if ( get_u32(payload, 0) == 0x14 && get_u8(payload, 4) == 0x01 )
+ {
+ __u32 y=get_u32(payload, 5);
+ /* we need 19 chars + string */
+ if ( (y + 19) <= (plen) )
+ {
+ const unsigned char *w=payload+9+y;
+ if (get_u32(w, 0) == 0x01 && ( get_u16(w, 4) == 0x4600 || get_u16(w, 4) == 0x5000) && get_u32(w, 6) == 0x00);
+#ifdef IPP2P_DEBUG_SOUL
+ printk(KERN_DEBUG "Soulssek special client command recognized\n");
+#endif /* IPP2P_DEBUG_SOUL */
+ return ((IPP2P_SOUL * 100) + 9);
+ }
+ }
+ return 0;
+}
+
+
+/*Search for WinMX commands*/
+int
+search_winmx (const unsigned char *payload, const u16 plen)
+{
+//#define IPP2P_DEBUG_WINMX
+ if (((plen) == 4) && (memcmp(payload, "SEND", 4) == 0)) return ((IPP2P_WINMX * 100) + 1);
+ if (((plen) == 3) && (memcmp(payload, "GET", 3) == 0)) return ((IPP2P_WINMX * 100) + 2);
+ //if (packet_len < (head_len + 10)) return 0;
+ if (plen < 10) return 0;
+
+ if ((memcmp(payload, "SEND", 4) == 0) || (memcmp(payload, "GET", 3) == 0)){
+ u16 c=4;
+ const u16 end=plen-2;
+ u8 count=0;
+ while (c < end)
+ {
+ if (payload[c]== 0x20 && payload[c+1] == 0x22)
+ {
+ c++;
+ count++;
+ if (count>=2) return ((IPP2P_WINMX * 100) + 3);
+ }
+ c++;
+ }
+ }
+
+ if ( plen == 149 && payload[0] == '8' )
+ {
+#ifdef IPP2P_DEBUG_WINMX
+ printk(KERN_INFO "maybe WinMX\n");
+#endif
+ if (get_u32(payload,17) == 0 && get_u32(payload,21) == 0 && get_u32(payload,25) == 0 &&
+// get_u32(payload,33) == __constant_htonl(0x71182b1a) && get_u32(payload,37) == __constant_htonl(0x05050000) &&
+// get_u32(payload,133) == __constant_htonl(0x31097edf) && get_u32(payload,145) == __constant_htonl(0xdcb8f792))
+ get_u16(payload,39) == 0 && get_u16(payload,135) == __constant_htons(0x7edf) && get_u16(payload,147) == __constant_htons(0xf792))
+
+ {
+#ifdef IPP2P_DEBUG_WINMX
+ printk(KERN_INFO "got WinMX\n");
+#endif
+ return ((IPP2P_WINMX * 100) + 4);
+ }
+ }
+ return 0;
+} /*search_winmx*/
+
+
+/*Search for appleJuice commands*/
+int
+search_apple (const unsigned char *payload, const u16 plen)
+{
+ if ( (plen > 7) && (payload[6] == 0x0d) && (payload[7] == 0x0a) && (memcmp(payload, "ajprot", 6) == 0)) return (IPP2P_APPLE * 100);
+
+ return 0;
+}
+
+
+/*Search for BitTorrent commands*/
+int
+search_bittorrent (const unsigned char *payload, const u16 plen)
+{
+ if (plen > 20)
+ {
+ /* test for match 0x13+"BitTorrent protocol" */
+ if (payload[0] == 0x13)
+ {
+ if (memcmp(payload+1, "BitTorrent protocol", 19) == 0) return (IPP2P_BIT * 100);
+ }
+
+ /* get tracker commandos, all starts with GET /
+ * then it can follow: scrape| announce
+ * and then ?hash_info=
+ */
+ if (memcmp(payload,"GET /",5) == 0)
+ {
+ /* message scrape */
+ if ( memcmp(payload+5,"scrape?info_hash=",17)==0 ) return (IPP2P_BIT * 100 + 1);
+ /* message announce */
+ if ( memcmp(payload+5,"announce?info_hash=",19)==0 ) return (IPP2P_BIT * 100 + 2);
+ }
+ }
+ else
+ {
+ /* bitcomet encryptes the first packet, so we have to detect another
+ * one later in the flow */
+ /* first try failed, too many missdetections */
+ //if ( size == 5 && get_u32(t,0) == __constant_htonl(1) && t[4] < 3) return (IPP2P_BIT * 100 + 3);
+
+ /* second try: block request packets */
+ if ( plen == 17 && get_u32(payload,0) == __constant_htonl(0x0d) && payload[4] == 0x06 && get_u32(payload,13) == __constant_htonl(0x4000) ) return (IPP2P_BIT * 100 + 3);
+ }
+
+ return 0;
+}
+
+
+
+/*check for Kazaa get command*/
+int
+search_kazaa (const unsigned char *payload, const u16 plen)
+
+{
+ if ((payload[plen-2] == 0x0d) && (payload[plen-1] == 0x0a) && memcmp(payload, "GET /.hash=", 11) == 0)
+ return (IPP2P_DATA_KAZAA * 100);
+
+ return 0;
+}
+
+
+/*check for gnutella get command*/
+int
+search_gnu (const unsigned char *payload, const u16 plen)
+{
+ if ((payload[plen-2] == 0x0d) && (payload[plen-1] == 0x0a))
+ {
+ if (memcmp(payload, "GET /get/", 9) == 0) return ((IPP2P_DATA_GNU * 100) + 1);
+ if (memcmp(payload, "GET /uri-res/", 13) == 0) return ((IPP2P_DATA_GNU * 100) + 2);
+ }
+ return 0;
+}
+
+
+/*check for gnutella get commands and other typical data*/
+int
+search_all_gnu (const unsigned char *payload, const u16 plen)
+{
+
+ if ((payload[plen-2] == 0x0d) && (payload[plen-1] == 0x0a))
+ {
+
+ if (memcmp(payload, "GNUTELLA CONNECT/", 17) == 0) return ((IPP2P_GNU * 100) + 1);
+ if (memcmp(payload, "GNUTELLA/", 9) == 0) return ((IPP2P_GNU * 100) + 2);
+
+
+ if ((memcmp(payload, "GET /get/", 9) == 0) || (memcmp(payload, "GET /uri-res/", 13) == 0))
+ {
+ u16 c=8;
+ const u16 end=plen-22;
+ while (c < end) {
+ if ( payload[c] == 0x0a && payload[c+1] == 0x0d && ((memcmp(&payload[c+2], "X-Gnutella-", 11) == 0) || (memcmp(&payload[c+2], "X-Queue:", 8) == 0)))
+ return ((IPP2P_GNU * 100) + 3);
+ c++;
+ }
+ }
+ }
+ return 0;
+}
+
+
+/*check for KaZaA download commands and other typical data*/
+int
+search_all_kazaa (const unsigned char *payload, const u16 plen)
+{
+ if ((payload[plen-2] == 0x0d) && (payload[plen-1] == 0x0a))
+ {
+
+ if (memcmp(payload, "GIVE ", 5) == 0) return ((IPP2P_KAZAA * 100) + 1);
+
+ if (memcmp(payload, "GET /", 5) == 0) {
+ u16 c = 8;
+ const u16 end=plen-22;
+ while (c < end) {
+ if ( payload[c] == 0x0a && payload[c+1] == 0x0d && ((memcmp(&payload[c+2], "X-Kazaa-Username: ", 18) == 0) || (memcmp(&payload[c+2], "User-Agent: PeerEnabler/", 24) == 0)))
+ return ((IPP2P_KAZAA * 100) + 2);
+ c++;
+ }
+ }
+ }
+ return 0;
+}
+
+/*fast check for edonkey file segment transfer command*/
+int
+search_edk (const unsigned char *payload, const u16 plen)
+{
+ if (payload[0] != 0xe3)
+ return 0;
+ else {
+ if (payload[5] == 0x47)
+ return (IPP2P_DATA_EDK * 100);
+ else
+ return 0;
+ }
+}
+
+
+
+/*intensive but slower search for some edonkey packets including size-check*/
+int
+search_all_edk (const unsigned char *payload, const u16 plen)
+{
+ if (payload[0] != 0xe3)
+ return 0;
+ else {
+ //t += head_len;
+ const u16 cmd = get_u16(payload, 1);
+ if (cmd == (plen - 5)) {
+ switch (payload[5]) {
+ case 0x01: return ((IPP2P_EDK * 100) + 1); /*Client: hello or Server:hello*/
+ case 0x4c: return ((IPP2P_EDK * 100) + 9); /*Client: Hello-Answer*/
+ }
+ }
+ return 0;
+ }
+}
+
+
+/*fast check for Direct Connect send command*/
+int
+search_dc (const unsigned char *payload, const u16 plen)
+{
+
+ if (payload[0] != 0x24 )
+ return 0;
+ else {
+ if (memcmp(&payload[1], "Send|", 5) == 0)
+ return (IPP2P_DATA_DC * 100);
+ else
+ return 0;
+ }
+
+}
+
+
+/*intensive but slower check for all direct connect packets*/
+int
+search_all_dc (const unsigned char *payload, const u16 plen)
+{
+// unsigned char *t = haystack;
+
+ if (payload[0] == 0x24 && payload[plen-1] == 0x7c)
+ {
+ const unsigned char *t=&payload[1];
+ /* Client-Hub-Protocol */
+ if (memcmp(t, "Lock ", 5) == 0) return ((IPP2P_DC * 100) + 1);
+ /* Client-Client-Protocol, some are already recognized by client-hub (like lock) */
+ if (memcmp(t, "MyNick ", 7) == 0) return ((IPP2P_DC * 100) + 38);
+ }
+ return 0;
+}
+
+/*check for mute*/
+int
+search_mute (const unsigned char *payload, const u16 plen)
+{
+ if ( plen == 209 || plen == 345 || plen == 473 || plen == 609 || plen == 1121 )
+ {
+ //printk(KERN_DEBUG "size hit: %u",size);
+ if (memcmp(payload,"PublicKey: ",11) == 0 )
+ {
+ return ((IPP2P_MUTE * 100) + 0);
+
+/* if (memcmp(t+size-14,"\x0aEndPublicKey\x0a",14) == 0)
+ {
+ printk(KERN_DEBUG "end pubic key hit: %u",size);
+
+ }*/
+ }
+ }
+ return 0;
+}
+
+
+/* check for xdcc */
+int
+search_xdcc (const unsigned char *payload, const u16 plen)
+{
+ /* search in small packets only */
+ if (plen > 20 && plen < 200 && payload[plen-1] == 0x0a && payload[plen-2] == 0x0d && memcmp(payload,"PRIVMSG ",8) == 0)
+ {
+
+ u16 x=10;
+ const u16 end=plen - 13;
+
+ /* is seems to be a irc private massage, chedck for xdcc command */
+ while (x < end)
+ {
+ if (payload[x] == ':')
+ {
+ if ( memcmp(&payload[x+1],"xdcc send #",11) == 0 )
+ return ((IPP2P_XDCC * 100) + 0);
+ }
+ x++;
+ }
+ }
+ return 0;
+}
+
+/* search for waste */
+int search_waste(const unsigned char *payload, const u16 plen)
+{
+ if ( plen >= 8 && memcmp(payload,"GET.sha1:",9) == 0)
+ return ((IPP2P_WASTE * 100) + 0);
+
+ return 0;
+}
+
+
+static struct {
+ int command;
+ __u8 short_hand; /*for fucntions included in short hands*/
+ int packet_len;
+ int (*function_name) (const unsigned char *, const u16);
+} matchlist[] = {
+ {IPP2P_EDK,SHORT_HAND_IPP2P,20, &search_all_edk},
+// {IPP2P_DATA_KAZAA,SHORT_HAND_DATA,200, &search_kazaa},
+// {IPP2P_DATA_EDK,SHORT_HAND_DATA,60, &search_edk},
+// {IPP2P_DATA_DC,SHORT_HAND_DATA,26, &search_dc},
+ {IPP2P_DC,SHORT_HAND_IPP2P,5, search_all_dc},
+// {IPP2P_DATA_GNU,SHORT_HAND_DATA,40, &search_gnu},
+ {IPP2P_GNU,SHORT_HAND_IPP2P,5, &search_all_gnu},
+ {IPP2P_KAZAA,SHORT_HAND_IPP2P,5, &search_all_kazaa},
+ {IPP2P_BIT,SHORT_HAND_IPP2P,20, &search_bittorrent},
+ {IPP2P_APPLE,SHORT_HAND_IPP2P,5, &search_apple},
+ {IPP2P_SOUL,SHORT_HAND_IPP2P,5, &search_soul},
+ {IPP2P_WINMX,SHORT_HAND_IPP2P,2, &search_winmx},
+ {IPP2P_ARES,SHORT_HAND_IPP2P,5, &search_ares},
+ {IPP2P_MUTE,SHORT_HAND_NONE,200, &search_mute},
+ {IPP2P_WASTE,SHORT_HAND_NONE,5, &search_waste},
+ {IPP2P_XDCC,SHORT_HAND_NONE,5, &search_xdcc},
+ {0,0,0,NULL}
+};
+
+
+static struct {
+ int command;
+ __u8 short_hand; /*for fucntions included in short hands*/
+ int packet_len;
+ int (*function_name) (unsigned char *, int);
+} udp_list[] = {
+ {IPP2P_KAZAA,SHORT_HAND_IPP2P,14, &udp_search_kazaa},
+ {IPP2P_BIT,SHORT_HAND_IPP2P,23, &udp_search_bit},
+ {IPP2P_GNU,SHORT_HAND_IPP2P,11, &udp_search_gnu},
+ {IPP2P_EDK,SHORT_HAND_IPP2P,9, &udp_search_edk},
+ {IPP2P_DC,SHORT_HAND_IPP2P,12, &udp_search_directconnect},
+ {0,0,0,NULL}
+};
+
+
+static int
+match(const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
+ const struct xt_match *match,
+#endif
+ const void *matchinfo,
+ int offset,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
+ unsigned int protoff,
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+ const void *hdr,
+ u_int16_t datalen,
+#endif
+ int *hotdrop)
+{
+ const struct ipt_p2p_info *info = matchinfo;
+ unsigned char *haystack;
+ struct iphdr *ip = ip_hdr(skb);
+ int p2p_result = 0, i = 0;
+// int head_len;
+ int hlen = ntohs(ip->tot_len)-(ip->ihl*4); /*hlen = packet-data length*/
+
+ /*must not be a fragment*/
+ if (offset) {
+ if (info->debug) printk("IPP2P.match: offset found %i \n",offset);
+ return 0;
+ }
+
+ /*make sure that skb is linear*/
+ if(skb_is_nonlinear(skb)){
+ if (info->debug) printk("IPP2P.match: nonlinear skb found\n");
+ return 0;
+ }
+
+
+ haystack=(char *)ip+(ip->ihl*4); /*haystack = packet data*/
+
+ switch (ip->protocol){
+ case IPPROTO_TCP: /*what to do with a TCP packet*/
+ {
+ struct tcphdr *tcph = (void *) ip + ip->ihl * 4;
+
+ if (tcph->fin) return 0; /*if FIN bit is set bail out*/
+ if (tcph->syn) return 0; /*if SYN bit is set bail out*/
+ if (tcph->rst) return 0; /*if RST bit is set bail out*/
+
+ haystack += tcph->doff * 4; /*get TCP-Header-Size*/
+ hlen -= tcph->doff * 4;
+ while (matchlist[i].command) {
+ if ((((info->cmd & matchlist[i].command) == matchlist[i].command) ||
+ ((info->cmd & matchlist[i].short_hand) == matchlist[i].short_hand)) &&
+ (hlen > matchlist[i].packet_len)) {
+ p2p_result = matchlist[i].function_name(haystack, hlen);
+ if (p2p_result)
+ {
+ if (info->debug) printk("IPP2P.debug:TCP-match: %i from: %u.%u.%u.%u:%i to: %u.%u.%u.%u:%i Length: %i\n",
+ p2p_result, NIPQUAD(ip->saddr),ntohs(tcph->source), NIPQUAD(ip->daddr),ntohs(tcph->dest),hlen);
+ return p2p_result;
+ }
+ }
+ i++;
+ }
+ return p2p_result;
+ }
+
+ case IPPROTO_UDP: /*what to do with an UDP packet*/
+ {
+ struct udphdr *udph = (void *) ip + ip->ihl * 4;
+
+ while (udp_list[i].command){
+ if ((((info->cmd & udp_list[i].command) == udp_list[i].command) ||
+ ((info->cmd & udp_list[i].short_hand) == udp_list[i].short_hand)) &&
+ (hlen > udp_list[i].packet_len)) {
+ p2p_result = udp_list[i].function_name(haystack, hlen);
+ if (p2p_result){
+ if (info->debug) printk("IPP2P.debug:UDP-match: %i from: %u.%u.%u.%u:%i to: %u.%u.%u.%u:%i Length: %i\n",
+ p2p_result, NIPQUAD(ip->saddr),ntohs(udph->source), NIPQUAD(ip->daddr),ntohs(udph->dest),hlen);
+ return p2p_result;
+ }
+ }
+ i++;
+ }
+ return p2p_result;
+ }
+
+ default: return 0;
+ }
+}
+
+
+
+static int
+checkentry(const char *tablename,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
+ const void *ip,
+ const struct xt_match *match,
+#else
+ const struct ipt_ip *ip,
+#endif
+ void *matchinfo,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
+ unsigned int matchsize,
+#endif
+ unsigned int hook_mask)
+{
+ /* Must specify -p tcp */
+/* if (ip->proto != IPPROTO_TCP || (ip->invflags & IPT_INV_PROTO)) {
+ * printk("ipp2p: Only works on TCP packets, use -p tcp\n");
+ * return 0;
+ * }*/
+ return 1;
+}
+
+
+
+
+static struct ipt_match ipp2p_match = {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+ { NULL, NULL },
+ "ipp2p",
+ &match,
+ &checkentry,
+ NULL,
+ THIS_MODULE
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ .name = "ipp2p",
+ .match = &match,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
+ .matchsize = sizeof(struct ipt_p2p_info),
+#endif
+ .checkentry = &checkentry,
+ .me = THIS_MODULE,
+#endif
+};
+
+
+static int __init init(void)
+{
+ printk(KERN_INFO "IPP2P v%s loading\n", IPP2P_VERSION);
+ return xt_register_match(&ipp2p_match);
+}
+
+static void __exit fini(void)
+{
+ xt_unregister_match(&ipp2p_match);
+ printk(KERN_INFO "IPP2P v%s unloaded\n", IPP2P_VERSION);
+}
+
+module_init(init);
+module_exit(fini);
+
+
diff -urN linux-2.6.21.1.old/net/ipv4/netfilter/Kconfig linux-2.6.21.1.dev/net/ipv4/netfilter/Kconfig
--- linux-2.6.21.1.old/net/ipv4/netfilter/Kconfig 2007-05-26 20:17:47.626407992 +0200
+++ linux-2.6.21.1.dev/net/ipv4/netfilter/Kconfig 2007-05-26 20:21:54.587864144 +0200
@@ -81,6 +81,12 @@
help
Say Y to get lots of debugging output.
+config IP_NF_MATCH_IPP2P
+ tristate "IPP2P"
+ depends on IP_NF_IPTABLES
+ help
+ Module for matching traffic of various Peer-to-Peer applications
+
config IP_NF_MATCH_TOS
tristate "TOS match support"
depends on IP_NF_IPTABLES
diff -urN linux-2.6.21.1.old/net/ipv4/netfilter/Makefile linux-2.6.21.1.dev/net/ipv4/netfilter/Makefile
--- linux-2.6.21.1.old/net/ipv4/netfilter/Makefile 2007-05-26 20:17:47.638406168 +0200
+++ linux-2.6.21.1.dev/net/ipv4/netfilter/Makefile 2007-05-26 20:21:54.588863992 +0200
@@ -49,7 +49,7 @@
obj-$(CONFIG_IP_NF_MATCH_AH) += ipt_ah.o
obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
-
+obj-$(CONFIG_IP_NF_MATCH_IPP2P) += ipt_ipp2p.o
obj-$(CONFIG_IP_NF_MATCH_LAYER7) += ipt_layer7.o
# targets

View File

@ -0,0 +1,169 @@
diff -urN linux-2.6.21.1.old/include/net/xfrmudp.h linux-2.6.21.1.dev/include/net/xfrmudp.h
--- linux-2.6.21.1.old/include/net/xfrmudp.h 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.21.1.dev/include/net/xfrmudp.h 2007-05-26 20:24:53.933599448 +0200
@@ -0,0 +1,10 @@
+/*
+ * pointer to function for type that xfrm4_input wants, to permit
+ * decoupling of XFRM from udp.c
+ */
+#define HAVE_XFRM4_UDP_REGISTER
+
+typedef int (*xfrm4_rcv_encap_t)(struct sk_buff *skb, __u16 encap_type);
+extern int udp4_register_esp_rcvencap(xfrm4_rcv_encap_t func
+ , xfrm4_rcv_encap_t *oldfunc);
+extern int udp4_unregister_esp_rcvencap(xfrm4_rcv_encap_t func);
diff -urN linux-2.6.21.1.old/net/ipv4/Kconfig linux-2.6.21.1.dev/net/ipv4/Kconfig
--- linux-2.6.21.1.old/net/ipv4/Kconfig 2007-04-27 23:49:26.000000000 +0200
+++ linux-2.6.21.1.dev/net/ipv4/Kconfig 2007-05-26 20:24:53.965594584 +0200
@@ -266,6 +266,12 @@
Network), but can be distributed all over the Internet. If you want
to do that, say Y here and to "IP multicast routing" below.
+config IPSEC_NAT_TRAVERSAL
+ bool "IPSEC NAT-Traversal (KLIPS compatible)"
+ depends on INET
+ ---help---
+ Includes support for RFC3947/RFC3948 NAT-Traversal of ESP over UDP.
+
config IP_MROUTE
bool "IP: multicast routing"
depends on IP_MULTICAST
diff -urN linux-2.6.21.1.old/net/ipv4/udp.c linux-2.6.21.1.dev/net/ipv4/udp.c
--- linux-2.6.21.1.old/net/ipv4/udp.c 2007-04-27 23:49:26.000000000 +0200
+++ linux-2.6.21.1.dev/net/ipv4/udp.c 2007-05-26 20:24:53.966594432 +0200
@@ -101,12 +101,15 @@
#include <net/route.h>
#include <net/checksum.h>
#include <net/xfrm.h>
+#include <net/xfrmudp.h>
#include "udp_impl.h"
/*
* Snmp MIB for the UDP layer
*/
+static xfrm4_rcv_encap_t xfrm4_rcv_encap_func;
+
DEFINE_SNMP_STAT(struct udp_mib, udp_statistics) __read_mostly;
struct hlist_head udp_hash[UDP_HTABLE_SIZE];
@@ -1008,6 +1011,42 @@
return 0;
}
+#if defined(CONFIG_XFRM) || defined(CONFIG_IPSEC_NAT_TRAVERSAL)
+
+/* if XFRM isn't a module, then register it directly. */
+#if 0 && !defined(CONFIG_XFRM_MODULE) && !defined(CONFIG_IPSEC_NAT_TRAVERSAL)
+static xfrm4_rcv_encap_t xfrm4_rcv_encap_func = xfrm4_rcv_encap;
+#else
+static xfrm4_rcv_encap_t xfrm4_rcv_encap_func = NULL;
+#endif
+
+int udp4_register_esp_rcvencap(xfrm4_rcv_encap_t func
+ , xfrm4_rcv_encap_t *oldfunc)
+{
+ if(oldfunc != NULL) {
+ *oldfunc = xfrm4_rcv_encap_func;
+ }
+
+#if 0
+ if(xfrm4_rcv_encap_func != NULL)
+ return -1;
+#endif
+
+ xfrm4_rcv_encap_func = func;
+ return 0;
+}
+
+int udp4_unregister_esp_rcvencap(xfrm4_rcv_encap_t func)
+{
+ if(xfrm4_rcv_encap_func != func)
+ return -1;
+
+ xfrm4_rcv_encap_func = NULL;
+ return 0;
+}
+#endif /* CONFIG_XFRM_MODULE || CONFIG_IPSEC_NAT_TRAVERSAL */
+
+
/* return:
* 1 if the UDP system should process it
* 0 if we should drop this packet
@@ -1015,7 +1054,7 @@
*/
static int udp_encap_rcv(struct sock * sk, struct sk_buff *skb)
{
-#ifndef CONFIG_XFRM
+#if !defined(CONFIG_XFRM) && !defined(CONFIG_IPSEC_NAT_TRAVERSAL)
return 1;
#else
struct udp_sock *up = udp_sk(sk);
@@ -1030,11 +1069,11 @@
/* if we're overly short, let UDP handle it */
len = skb->len - sizeof(struct udphdr);
if (len <= 0)
- return 1;
+ return 2;
/* if this is not encapsulated socket, then just return now */
if (!encap_type)
- return 1;
+ return 3;
/* If this is a paged skb, make sure we pull up
* whatever data we need to look at. */
@@ -1057,7 +1096,7 @@
len = sizeof(struct udphdr);
} else
/* Must be an IKE packet.. pass it through */
- return 1;
+ return 4;
break;
case UDP_ENCAP_ESPINUDP_NON_IKE:
/* Check if this is a keepalive packet. If so, eat it. */
@@ -1070,7 +1109,7 @@
len = sizeof(struct udphdr) + 2 * sizeof(u32);
} else
/* Must be an IKE packet.. pass it through */
- return 1;
+ return 5;
break;
}
@@ -1081,6 +1120,8 @@
*/
if (skb_cloned(skb) && pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
return 0;
+ if (skb_cloned(skb) && pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
+ return 0;
/* Now we can update and verify the packet length... */
iph = ip_hdr(skb);
@@ -1145,9 +1186,13 @@
return 0;
}
if (ret < 0) {
- /* process the ESP packet */
- ret = xfrm4_rcv_encap(skb, up->encap_type);
- UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS, up->pcflag);
+ if(xfrm4_rcv_encap_func != NULL) {
+ ret = (*xfrm4_rcv_encap_func)(skb, up->encap_type);
+ UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS, up->pcflag);
+ } else {
+ UDP_INC_STATS_BH(UDP_MIB_INERRORS, up->pcflag);
+ ret = 1;
+ }
return -ret;
}
/* FALLTHROUGH -- it's a UDP Packet */
@@ -1847,3 +1892,9 @@
EXPORT_SYMBOL(udp_proc_register);
EXPORT_SYMBOL(udp_proc_unregister);
#endif
+
+#if defined(CONFIG_IPSEC_NAT_TRAVERSAL)
+EXPORT_SYMBOL(udp4_register_esp_rcvencap);
+EXPORT_SYMBOL(udp4_unregister_esp_rcvencap);
+#endif
+

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,243 @@
diff -urN linux-2.6.21.1.old/include/linux/netfilter_ipv4/ipt_time.h linux-2.6.21.1.dev/include/linux/netfilter_ipv4/ipt_time.h
--- linux-2.6.21.1.old/include/linux/netfilter_ipv4/ipt_time.h 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.21.1.dev/include/linux/netfilter_ipv4/ipt_time.h 2007-05-26 20:31:03.596402160 +0200
@@ -0,0 +1,18 @@
+#ifndef __ipt_time_h_included__
+#define __ipt_time_h_included__
+
+
+struct ipt_time_info {
+ u_int8_t days_match; /* 1 bit per day. -SMTWTFS */
+ u_int16_t time_start; /* 0 < time_start < 23*60+59 = 1439 */
+ u_int16_t time_stop; /* 0:0 < time_stat < 23:59 */
+
+ /* FIXME: Keep this one for userspace iptables binary compability: */
+ u_int8_t kerneltime; /* ignore skb time (and use kerneltime) or not. */
+
+ time_t date_start;
+ time_t date_stop;
+};
+
+
+#endif /* __ipt_time_h_included__ */
diff -urN linux-2.6.21.1.old/net/ipv4/netfilter/ipt_time.c linux-2.6.21.1.dev/net/ipv4/netfilter/ipt_time.c
--- linux-2.6.21.1.old/net/ipv4/netfilter/ipt_time.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.21.1.dev/net/ipv4/netfilter/ipt_time.c 2007-05-26 20:31:03.596402160 +0200
@@ -0,0 +1,180 @@
+/*
+ This is a module which is used for time matching
+ It is using some modified code from dietlibc (localtime() function)
+ that you can find at http://www.fefe.de/dietlibc/
+ This file is distributed under the terms of the GNU General Public
+ License (GPL). Copies of the GPL can be obtained from: ftp://prep.ai.mit.edu/pub/gnu/GPL
+ 2001-05-04 Fabrice MARIE <fabrice@netfilter.org> : initial development.
+ 2001-21-05 Fabrice MARIE <fabrice@netfilter.org> : bug fix in the match code,
+ thanks to "Zeng Yu" <zengy@capitel.com.cn> for bug report.
+ 2001-26-09 Fabrice MARIE <fabrice@netfilter.org> : force the match to be in LOCAL_IN or PRE_ROUTING only.
+ 2001-30-11 Fabrice : added the possibility to use the match in FORWARD/OUTPUT with a little hack,
+ added Nguyen Dang Phuoc Dong <dongnd@tlnet.com.vn> patch to support timezones.
+ 2004-05-02 Fabrice : added support for date matching, from an idea of Fabien COELHO.
+*/
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ipt_time.h>
+#include <linux/time.h>
+
+MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
+MODULE_DESCRIPTION("Match arrival timestamp/date");
+MODULE_LICENSE("GPL");
+
+struct tm
+{
+ int tm_sec; /* Seconds. [0-60] (1 leap second) */
+ int tm_min; /* Minutes. [0-59] */
+ int tm_hour; /* Hours. [0-23] */
+ int tm_mday; /* Day. [1-31] */
+ int tm_mon; /* Month. [0-11] */
+ int tm_year; /* Year - 1900. */
+ int tm_wday; /* Day of week. [0-6] */
+ int tm_yday; /* Days in year.[0-365] */
+ int tm_isdst; /* DST. [-1/0/1]*/
+
+ long int tm_gmtoff; /* we don't care, we count from GMT */
+ const char *tm_zone; /* we don't care, we count from GMT */
+};
+
+void
+localtime(const u32 time, struct tm *r);
+
+static int
+match(const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const struct xt_match *match,
+ const void *matchinfo,
+ int offset,
+ unsigned int protoff,
+ int *hotdrop)
+{
+ const struct ipt_time_info *info = matchinfo; /* match info for rule */
+ struct timeval tv;
+ struct tm currenttime; /* time human readable */
+ u_int8_t days_of_week[7] = {64, 32, 16, 8, 4, 2, 1};
+ u_int16_t packet_time;
+
+ /* We might not have a timestamp, get one */
+ if (skb->tstamp.tv64 == 0)
+ __net_timestamp((struct sk_buff *)skb);
+
+ skb_get_timestamp(skb, &tv);
+ /* First we make sure we are in the date start-stop boundaries */
+ if ((tv.tv_sec < info->date_start) || (tv.tv_sec > info->date_stop))
+ return 0; /* We are outside the date boundaries */
+
+ /* Transform the timestamp of the packet, in a human readable form */
+ localtime(tv.tv_sec, &currenttime);
+
+ /* check if we match this timestamp, we start by the days... */
+ if ((days_of_week[currenttime.tm_wday] & info->days_match) != days_of_week[currenttime.tm_wday])
+ return 0; /* the day doesn't match */
+
+ /* ... check the time now */
+ packet_time = (currenttime.tm_hour * 60) + currenttime.tm_min;
+ if ((packet_time < info->time_start) || (packet_time > info->time_stop))
+ return 0;
+
+ /* here we match ! */
+ return 1;
+}
+
+static int
+checkentry(const char *tablename,
+ const void *ip,
+ const struct xt_match *match,
+ void *matchinfo,
+ unsigned int hook_mask)
+{
+ struct ipt_time_info *info = matchinfo; /* match info for rule */
+
+ /* First, check that we are in the correct hooks */
+ if (hook_mask
+ & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT)))
+ {
+ printk("ipt_time: error, only valid for PRE_ROUTING, LOCAL_IN, FORWARD and OUTPUT)\n");
+ return 0;
+ }
+
+ /* Now check the coherence of the data ... */
+ if ((info->time_start > 1439) || /* 23*60+59 = 1439*/
+ (info->time_stop > 1439))
+ {
+ printk(KERN_WARNING "ipt_time: invalid argument\n");
+ return 0;
+ }
+
+ return 1;
+}
+
+static struct ipt_match time_match = {
+ .name = "time",
+ .match = &match,
+ .matchsize = sizeof(struct ipt_time_info),
+ .checkentry = &checkentry,
+ .me = THIS_MODULE
+};
+
+static int __init init(void)
+{
+ printk("ipt_time loading\n");
+ return xt_register_match(&time_match);
+}
+
+static void __exit fini(void)
+{
+ xt_unregister_match(&time_match);
+ printk("ipt_time unloaded\n");
+}
+
+module_init(init);
+module_exit(fini);
+
+
+/* The part below is borowed and modified from dietlibc */
+
+/* seconds per day */
+#define SPD 24*60*60
+
+void
+localtime(const u32 time, struct tm *r) {
+ u32 i, timep;
+ extern struct timezone sys_tz;
+ const unsigned int __spm[12] =
+ { 0,
+ (31),
+ (31+28),
+ (31+28+31),
+ (31+28+31+30),
+ (31+28+31+30+31),
+ (31+28+31+30+31+30),
+ (31+28+31+30+31+30+31),
+ (31+28+31+30+31+30+31+31),
+ (31+28+31+30+31+30+31+31+30),
+ (31+28+31+30+31+30+31+31+30+31),
+ (31+28+31+30+31+30+31+31+30+31+30),
+ };
+ register u32 work;
+
+ timep = time - (sys_tz.tz_minuteswest * 60);
+ work=timep%(SPD);
+ r->tm_sec=work%60; work/=60;
+ r->tm_min=work%60; r->tm_hour=work/60;
+ work=timep/(SPD);
+ r->tm_wday=(4+work)%7;
+ for (i=1970; ; ++i) {
+ register time_t k= (!(i%4) && ((i%100) || !(i%400)))?366:365;
+ if (work>k)
+ work-=k;
+ else
+ break;
+ }
+ r->tm_year=i-1900;
+ for (i=11; i && __spm[i]>work; --i) ;
+ r->tm_mon=i;
+ r->tm_mday=work-__spm[i]+1;
+}
diff -urN linux-2.6.21.1.old/net/ipv4/netfilter/Kconfig linux-2.6.21.1.dev/net/ipv4/netfilter/Kconfig
--- linux-2.6.21.1.old/net/ipv4/netfilter/Kconfig 2007-05-26 20:31:03.452424048 +0200
+++ linux-2.6.21.1.dev/net/ipv4/netfilter/Kconfig 2007-05-26 20:31:03.597402008 +0200
@@ -96,6 +96,22 @@
To compile it as a module, choose M here. If unsure, say N.
+
+config IP_NF_MATCH_TIME
+ tristate 'TIME match support'
+ depends on IP_NF_IPTABLES
+ help
+ This option adds a `time' match, which allows you
+ to match based on the packet arrival time/date
+ (arrival time/date at the machine which netfilter is running on) or
+ departure time/date (for locally generated packets).
+
+ If you say Y here, try iptables -m time --help for more information.
+ If you want to compile it as a module, say M here and read
+
+ Documentation/modules.txt. If unsure, say `N'.
+
+
config IP_NF_MATCH_RECENT
tristate "recent match support"
depends on IP_NF_IPTABLES
diff -urN linux-2.6.21.1.old/net/ipv4/netfilter/Makefile linux-2.6.21.1.dev/net/ipv4/netfilter/Makefile
--- linux-2.6.21.1.old/net/ipv4/netfilter/Makefile 2007-05-26 20:31:03.452424048 +0200
+++ linux-2.6.21.1.dev/net/ipv4/netfilter/Makefile 2007-05-26 20:31:03.597402008 +0200
@@ -44,6 +44,7 @@
obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o
obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
+obj-$(CONFIG_IP_NF_MATCH_TIME) += ipt_time.o
obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o
obj-$(CONFIG_IP_NF_MATCH_AH) += ipt_ah.o

View File

@ -0,0 +1,867 @@
diff -urN linux-2.6.21.1.old/drivers/net/imq.c linux-2.6.21.1.dev/drivers/net/imq.c
--- linux-2.6.21.1.old/drivers/net/imq.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.21.1.dev/drivers/net/imq.c 2007-05-26 20:34:15.180276984 +0200
@@ -0,0 +1,402 @@
+/*
+ * Pseudo-driver for the intermediate queue device.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Authors: Patrick McHardy, <kaber@trash.net>
+ *
+ * The first version was written by Martin Devera, <devik@cdi.cz>
+ *
+ * Credits: Jan Rafaj <imq2t@cedric.vabo.cz>
+ * - Update patch to 2.4.21
+ * Sebastian Strollo <sstrollo@nortelnetworks.com>
+ * - Fix "Dead-loop on netdevice imq"-issue
+ * Marcel Sebek <sebek64@post.cz>
+ * - Update to 2.6.2-rc1
+ *
+ * After some time of inactivity there is a group taking care
+ * of IMQ again: http://www.linuximq.net
+ *
+ *
+ * 2004/06/30 - New version of IMQ patch to kernels <=2.6.7 including
+ * the following changes:
+ *
+ * - Correction of ipv6 support "+"s issue (Hasso Tepper)
+ * - Correction of imq_init_devs() issue that resulted in
+ * kernel OOPS unloading IMQ as module (Norbert Buchmuller)
+ * - Addition of functionality to choose number of IMQ devices
+ * during kernel config (Andre Correa)
+ * - Addition of functionality to choose how IMQ hooks on
+ * PRE and POSTROUTING (after or before NAT) (Andre Correa)
+ * - Cosmetic corrections (Norbert Buchmuller) (Andre Correa)
+ *
+ *
+ * 2005/12/16 - IMQ versions between 2.6.7 and 2.6.13 were
+ * released with almost no problems. 2.6.14-x was released
+ * with some important changes: nfcache was removed; After
+ * some weeks of trouble we figured out that some IMQ fields
+ * in skb were missing in skbuff.c - skb_clone and copy_skb_header.
+ * These functions are correctly patched by this new patch version.
+ *
+ * Thanks for all who helped to figure out all the problems with
+ * 2.6.14.x: Patrick McHardy, Rune Kock, VeNoMouS, Max CtRiX,
+ * Kevin Shanahan, Richard Lucassen, Valery Dachev (hopefully
+ * I didn't forget anybody). I apologize again for my lack of time.
+ *
+ * More info at: http://www.linuximq.net/ (Andre Correa)
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/moduleparam.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/rtnetlink.h>
+#include <linux/if_arp.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv4.h>
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+ #include <linux/netfilter_ipv6.h>
+#endif
+#include <linux/imq.h>
+#include <net/pkt_sched.h>
+
+extern int qdisc_restart1(struct net_device *dev);
+
+static nf_hookfn imq_nf_hook;
+
+static struct nf_hook_ops imq_ingress_ipv4 = {
+ .hook = imq_nf_hook,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_PRE_ROUTING,
+#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
+ .priority = NF_IP_PRI_MANGLE + 1
+#else
+ .priority = NF_IP_PRI_NAT_DST + 1
+#endif
+};
+
+static struct nf_hook_ops imq_egress_ipv4 = {
+ .hook = imq_nf_hook,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_POST_ROUTING,
+#if defined(CONFIG_IMQ_BEHAVIOR_AA) || defined(CONFIG_IMQ_BEHAVIOR_BA)
+ .priority = NF_IP_PRI_LAST
+#else
+ .priority = NF_IP_PRI_NAT_SRC - 1
+#endif
+};
+
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+static struct nf_hook_ops imq_ingress_ipv6 = {
+ .hook = imq_nf_hook,
+ .owner = THIS_MODULE,
+ .pf = PF_INET6,
+ .hooknum = NF_IP6_PRE_ROUTING,
+#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
+ .priority = NF_IP6_PRI_MANGLE + 1
+#else
+ .priority = NF_IP6_PRI_NAT_DST + 1
+#endif
+};
+
+static struct nf_hook_ops imq_egress_ipv6 = {
+ .hook = imq_nf_hook,
+ .owner = THIS_MODULE,
+ .pf = PF_INET6,
+ .hooknum = NF_IP6_POST_ROUTING,
+#if defined(CONFIG_IMQ_BEHAVIOR_AA) || defined(CONFIG_IMQ_BEHAVIOR_BA)
+ .priority = NF_IP6_PRI_LAST
+#else
+ .priority = NF_IP6_PRI_NAT_SRC - 1
+#endif
+};
+#endif
+
+#if defined(CONFIG_IMQ_NUM_DEVS)
+static unsigned int numdevs = CONFIG_IMQ_NUM_DEVS;
+#else
+static unsigned int numdevs = 2;
+#endif
+
+static struct net_device *imq_devs;
+
+static struct net_device_stats *imq_get_stats(struct net_device *dev)
+{
+ return (struct net_device_stats *)dev->priv;
+}
+
+/* called for packets kfree'd in qdiscs at places other than enqueue */
+static void imq_skb_destructor(struct sk_buff *skb)
+{
+ struct nf_info *info = skb->nf_info;
+
+ if (info) {
+ if (info->indev)
+ dev_put(info->indev);
+ if (info->outdev)
+ dev_put(info->outdev);
+ kfree(info);
+ }
+}
+
+static int imq_dev_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct net_device_stats *stats = (struct net_device_stats*) dev->priv;
+
+ stats->tx_bytes += skb->len;
+ stats->tx_packets++;
+
+ skb->imq_flags = 0;
+ skb->destructor = NULL;
+
+ dev->trans_start = jiffies;
+ nf_reinject(skb, skb->nf_info, NF_ACCEPT);
+ return 0;
+}
+
+static int imq_nf_queue(struct sk_buff *skb, struct nf_info *info, unsigned queue_num, void *data)
+{
+ struct net_device *dev;
+ struct net_device_stats *stats;
+ struct sk_buff *skb2 = NULL;
+ struct Qdisc *q;
+ unsigned int index = skb->imq_flags&IMQ_F_IFMASK;
+ int ret = -1;
+
+ if (index > numdevs)
+ return -1;
+
+ dev = imq_devs + index;
+ if (!(dev->flags & IFF_UP)) {
+ skb->imq_flags = 0;
+ nf_reinject(skb, info, NF_ACCEPT);
+ return 0;
+ }
+ dev->last_rx = jiffies;
+
+ if (skb->destructor) {
+ skb2 = skb;
+ skb = skb_clone(skb, GFP_ATOMIC);
+ if (!skb)
+ return -1;
+ }
+ skb->nf_info = info;
+
+ stats = (struct net_device_stats *)dev->priv;
+ stats->rx_bytes+= skb->len;
+ stats->rx_packets++;
+
+ spin_lock_bh(&dev->queue_lock);
+ q = dev->qdisc;
+ if (q->enqueue) {
+ q->enqueue(skb_get(skb), q);
+ if (skb_shared(skb)) {
+ skb->destructor = imq_skb_destructor;
+ kfree_skb(skb);
+ ret = 0;
+ }
+ }
+ if (spin_is_locked(&dev->_xmit_lock))
+ netif_schedule(dev);
+ else
+ while (!netif_queue_stopped(dev) && qdisc_restart1(dev) < 0)
+ /* NOTHING */;
+
+ spin_unlock_bh(&dev->queue_lock);
+
+ if (skb2)
+ kfree_skb(ret ? skb : skb2);
+
+ return ret;
+}
+
+static struct nf_queue_handler nfqh = {
+ .name = "imq",
+ .outfn = imq_nf_queue,
+};
+
+static unsigned int imq_nf_hook(unsigned int hook, struct sk_buff **pskb,
+ const struct net_device *indev,
+ const struct net_device *outdev,
+ int (*okfn)(struct sk_buff *))
+{
+ if ((*pskb)->imq_flags & IMQ_F_ENQUEUE)
+ return NF_QUEUE;
+
+ return NF_ACCEPT;
+}
+
+
+static int __init imq_init_hooks(void)
+{
+ int err;
+
+ err = nf_register_queue_handler(PF_INET, &nfqh);
+ if (err > 0)
+ goto err1;
+ if ((err = nf_register_hook(&imq_ingress_ipv4)))
+ goto err2;
+ if ((err = nf_register_hook(&imq_egress_ipv4)))
+ goto err3;
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+ if ((err = nf_register_queue_handler(PF_INET6, &nfqh)))
+ goto err4;
+ if ((err = nf_register_hook(&imq_ingress_ipv6)))
+ goto err5;
+ if ((err = nf_register_hook(&imq_egress_ipv6)))
+ goto err6;
+#endif
+
+ return 0;
+
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+err6:
+ nf_unregister_hook(&imq_ingress_ipv6);
+err5:
+ nf_unregister_queue_handler(PF_INET6);
+err4:
+ nf_unregister_hook(&imq_egress_ipv6);
+#endif
+err3:
+ nf_unregister_hook(&imq_ingress_ipv4);
+err2:
+ nf_unregister_queue_handler(PF_INET);
+err1:
+ return err;
+}
+
+static void __exit imq_unhook(void)
+{
+ nf_unregister_hook(&imq_ingress_ipv4);
+ nf_unregister_hook(&imq_egress_ipv4);
+ nf_unregister_queue_handler(PF_INET);
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+ nf_unregister_hook(&imq_ingress_ipv6);
+ nf_unregister_hook(&imq_egress_ipv6);
+ nf_unregister_queue_handler(PF_INET6);
+#endif
+}
+
+static int __init imq_dev_init(struct net_device *dev)
+{
+ dev->hard_start_xmit = imq_dev_xmit;
+ dev->type = ARPHRD_VOID;
+ dev->mtu = 1500;
+ dev->tx_queue_len = 30;
+ dev->flags = IFF_NOARP;
+ dev->priv = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL);
+ if (dev->priv == NULL)
+ return -ENOMEM;
+ memset(dev->priv, 0, sizeof(struct net_device_stats));
+ dev->get_stats = imq_get_stats;
+
+ return 0;
+}
+
+static void imq_dev_uninit(struct net_device *dev)
+{
+ kfree(dev->priv);
+}
+
+static int __init imq_init_devs(void)
+{
+ struct net_device *dev;
+ int i,j;
+ j = numdevs;
+
+ if (!numdevs || numdevs > IMQ_MAX_DEVS) {
+ printk(KERN_ERR "IMQ: numdevs has to be betweed 1 and %u\n",
+ IMQ_MAX_DEVS);
+ return -EINVAL;
+ }
+
+ imq_devs = kmalloc(sizeof(struct net_device) * numdevs, GFP_KERNEL);
+ if (!imq_devs)
+ return -ENOMEM;
+ memset(imq_devs, 0, sizeof(struct net_device) * numdevs);
+
+ /* we start counting at zero */
+ numdevs--;
+
+ for (i = 0, dev = imq_devs; i <= numdevs; i++, dev++) {
+ SET_MODULE_OWNER(dev);
+ strcpy(dev->name, "imq%d");
+ dev->init = imq_dev_init;
+ dev->uninit = imq_dev_uninit;
+
+ if (register_netdev(dev) < 0)
+ goto err_register;
+ }
+ printk(KERN_INFO "IMQ starting with %u devices...\n", j);
+ return 0;
+
+err_register:
+ for (; i; i--)
+ unregister_netdev(--dev);
+ kfree(imq_devs);
+ return -EIO;
+}
+
+static void imq_cleanup_devs(void)
+{
+ int i;
+ struct net_device *dev = imq_devs;
+
+ for (i = 0; i <= numdevs; i++)
+ unregister_netdev(dev++);
+
+ kfree(imq_devs);
+}
+
+static int __init imq_init_module(void)
+{
+ int err;
+
+ if ((err = imq_init_devs())) {
+ printk(KERN_ERR "IMQ: Error trying imq_init_devs()\n");
+ return err;
+ }
+ if ((err = imq_init_hooks())) {
+ printk(KERN_ERR "IMQ: Error trying imq_init_hooks()\n");
+ imq_cleanup_devs();
+ return err;
+ }
+
+ printk(KERN_INFO "IMQ driver loaded successfully.\n");
+
+#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
+ printk(KERN_INFO "\tHooking IMQ before NAT on PREROUTING.\n");
+#else
+ printk(KERN_INFO "\tHooking IMQ after NAT on PREROUTING.\n");
+#endif
+#if defined(CONFIG_IMQ_BEHAVIOR_AB) || defined(CONFIG_IMQ_BEHAVIOR_BB)
+ printk(KERN_INFO "\tHooking IMQ before NAT on POSTROUTING.\n");
+#else
+ printk(KERN_INFO "\tHooking IMQ after NAT on POSTROUTING.\n");
+#endif
+
+ return 0;
+}
+
+static void __exit imq_cleanup_module(void)
+{
+ imq_unhook();
+ imq_cleanup_devs();
+ printk(KERN_INFO "IMQ driver unloaded successfully.\n");
+}
+
+
+module_init(imq_init_module);
+module_exit(imq_cleanup_module);
+
+module_param(numdevs, int, 0);
+MODULE_PARM_DESC(numdevs, "number of IMQ devices (how many imq* devices will be created)");
+MODULE_AUTHOR("http://www.linuximq.net");
+MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See http://www.linuximq.net/ for more information.");
+MODULE_LICENSE("GPL");
diff -urN linux-2.6.21.1.old/drivers/net/Kconfig linux-2.6.21.1.dev/drivers/net/Kconfig
--- linux-2.6.21.1.old/drivers/net/Kconfig 2007-04-27 23:49:26.000000000 +0200
+++ linux-2.6.21.1.dev/drivers/net/Kconfig 2007-05-26 20:34:15.193275008 +0200
@@ -96,6 +96,129 @@
To compile this driver as a module, choose M here: the module
will be called eql. If unsure, say N.
+config IMQ
+ tristate "IMQ (intermediate queueing device) support"
+ depends on NETDEVICES && NETFILTER
+ ---help---
+ The IMQ device(s) is used as placeholder for QoS queueing
+ disciplines. Every packet entering/leaving the IP stack can be
+ directed through the IMQ device where it's enqueued/dequeued to the
+ attached qdisc. This allows you to treat network devices as classes
+ and distribute bandwidth among them. Iptables is used to specify
+ through which IMQ device, if any, packets travel.
+
+ More information at: http://www.linuximq.net/
+
+ To compile this driver as a module, choose M here: the module
+ will be called imq. If unsure, say N.
+
+choice
+ prompt "IMQ behavior (PRE/POSTROUTING)"
+ depends on IMQ
+ default IMQ_BEHAVIOR_BA
+ help
+
+ This settings defines how IMQ behaves in respect to its
+ hooking in PREROUTING and POSTROUTING.
+
+ IMQ can work in any of the following ways:
+
+ PREROUTING | POSTROUTING
+ -----------------|-------------------
+ #1 After NAT | After NAT
+ #2 After NAT | Before NAT
+ #3 Before NAT | After NAT
+ #4 Before NAT | Before NAT
+
+ The default behavior is to hook before NAT on PREROUTING
+ and after NAT on POSTROUTING (#3).
+
+ This settings are specially usefull when trying to use IMQ
+ to shape NATed clients.
+
+ More information can be found at: www.linuximq.net
+
+ If not sure leave the default settings alone.
+
+config IMQ_BEHAVIOR_AA
+ bool "IMQ AA"
+ help
+ This settings defines how IMQ behaves in respect to its
+ hooking in PREROUTING and POSTROUTING.
+
+ Choosing this option will make IMQ hook like this:
+
+ PREROUTING: After NAT
+ POSTROUTING: After NAT
+
+ More information can be found at: www.linuximq.net
+
+ If not sure leave the default settings alone.
+
+config IMQ_BEHAVIOR_AB
+ bool "IMQ AB"
+ help
+ This settings defines how IMQ behaves in respect to its
+ hooking in PREROUTING and POSTROUTING.
+
+ Choosing this option will make IMQ hook like this:
+
+ PREROUTING: After NAT
+ POSTROUTING: Before NAT
+
+ More information can be found at: www.linuximq.net
+
+ If not sure leave the default settings alone.
+
+config IMQ_BEHAVIOR_BA
+ bool "IMQ BA"
+ help
+ This settings defines how IMQ behaves in respect to its
+ hooking in PREROUTING and POSTROUTING.
+
+ Choosing this option will make IMQ hook like this:
+
+ PREROUTING: Before NAT
+ POSTROUTING: After NAT
+
+ More information can be found at: www.linuximq.net
+
+ If not sure leave the default settings alone.
+
+config IMQ_BEHAVIOR_BB
+ bool "IMQ BB"
+ help
+ This settings defines how IMQ behaves in respect to its
+ hooking in PREROUTING and POSTROUTING.
+
+ Choosing this option will make IMQ hook like this:
+
+ PREROUTING: Before NAT
+ POSTROUTING: Before NAT
+
+ More information can be found at: www.linuximq.net
+
+ If not sure leave the default settings alone.
+
+endchoice
+
+config IMQ_NUM_DEVS
+
+ int "Number of IMQ devices"
+ range 2 8
+ depends on IMQ
+ default "2"
+ help
+
+ This settings defines how many IMQ devices will be
+ created.
+
+ The default value is 2.
+
+ More information can be found at: www.linuximq.net
+
+ If not sure leave the default settings alone.
+
config TUN
tristate "Universal TUN/TAP device driver support"
select CRC32
diff -urN linux-2.6.21.1.old/drivers/net/Makefile linux-2.6.21.1.dev/drivers/net/Makefile
--- linux-2.6.21.1.old/drivers/net/Makefile 2007-04-27 23:49:26.000000000 +0200
+++ linux-2.6.21.1.dev/drivers/net/Makefile 2007-05-26 20:34:15.194274856 +0200
@@ -124,6 +124,7 @@
obj-$(CONFIG_SLHC) += slhc.o
obj-$(CONFIG_DUMMY) += dummy.o
+obj-$(CONFIG_IMQ) += imq.o
obj-$(CONFIG_IFB) += ifb.o
obj-$(CONFIG_DE600) += de600.o
obj-$(CONFIG_DE620) += de620.o
diff -urN linux-2.6.21.1.old/include/linux/imq.h linux-2.6.21.1.dev/include/linux/imq.h
--- linux-2.6.21.1.old/include/linux/imq.h 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.21.1.dev/include/linux/imq.h 2007-05-26 20:34:15.458234728 +0200
@@ -0,0 +1,9 @@
+#ifndef _IMQ_H
+#define _IMQ_H
+
+#define IMQ_MAX_DEVS 16
+
+#define IMQ_F_IFMASK 0x7f
+#define IMQ_F_ENQUEUE 0x80
+
+#endif /* _IMQ_H */
diff -urN linux-2.6.21.1.old/include/linux/netfilter_ipv4/ipt_IMQ.h linux-2.6.21.1.dev/include/linux/netfilter_ipv4/ipt_IMQ.h
--- linux-2.6.21.1.old/include/linux/netfilter_ipv4/ipt_IMQ.h 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.21.1.dev/include/linux/netfilter_ipv4/ipt_IMQ.h 2007-05-26 20:34:15.458234728 +0200
@@ -0,0 +1,8 @@
+#ifndef _IPT_IMQ_H
+#define _IPT_IMQ_H
+
+struct ipt_imq_info {
+ unsigned int todev; /* target imq device */
+};
+
+#endif /* _IPT_IMQ_H */
diff -urN linux-2.6.21.1.old/include/linux/netfilter_ipv6/ip6t_IMQ.h linux-2.6.21.1.dev/include/linux/netfilter_ipv6/ip6t_IMQ.h
--- linux-2.6.21.1.old/include/linux/netfilter_ipv6/ip6t_IMQ.h 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.21.1.dev/include/linux/netfilter_ipv6/ip6t_IMQ.h 2007-05-26 20:34:15.495229104 +0200
@@ -0,0 +1,8 @@
+#ifndef _IP6T_IMQ_H
+#define _IP6T_IMQ_H
+
+struct ip6t_imq_info {
+ unsigned int todev; /* target imq device */
+};
+
+#endif /* _IP6T_IMQ_H */
diff -urN linux-2.6.21.1.old/include/linux/skbuff.h linux-2.6.21.1.dev/include/linux/skbuff.h
--- linux-2.6.21.1.old/include/linux/skbuff.h 2007-04-27 23:49:26.000000000 +0200
+++ linux-2.6.21.1.dev/include/linux/skbuff.h 2007-05-26 20:34:15.496228952 +0200
@@ -285,6 +285,10 @@
struct nf_conntrack *nfct;
struct sk_buff *nfct_reasm;
#endif
+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
+ unsigned char imq_flags;
+ struct nf_info *nf_info;
+#endif
#ifdef CONFIG_BRIDGE_NETFILTER
struct nf_bridge_info *nf_bridge;
#endif
diff -urN linux-2.6.21.1.old/net/core/dev.c linux-2.6.21.1.dev/net/core/dev.c
--- linux-2.6.21.1.old/net/core/dev.c 2007-04-27 23:49:26.000000000 +0200
+++ linux-2.6.21.1.dev/net/core/dev.c 2007-05-26 20:34:15.497228800 +0200
@@ -94,6 +94,9 @@
#include <linux/skbuff.h>
#include <net/sock.h>
#include <linux/rtnetlink.h>
+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
+#include <linux/imq.h>
+#endif
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
@@ -1403,7 +1406,11 @@
int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
if (likely(!skb->next)) {
- if (!list_empty(&ptype_all))
+ if (!list_empty(&ptype_all)
+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
+ && !(skb->imq_flags & IMQ_F_ENQUEUE)
+#endif
+ )
dev_queue_xmit_nit(skb, dev);
if (netif_needs_gso(dev, skb)) {
diff -urN linux-2.6.21.1.old/net/ipv4/netfilter/ipt_IMQ.c linux-2.6.21.1.dev/net/ipv4/netfilter/ipt_IMQ.c
--- linux-2.6.21.1.old/net/ipv4/netfilter/ipt_IMQ.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.21.1.dev/net/ipv4/netfilter/ipt_IMQ.c 2007-05-26 20:34:15.498228648 +0200
@@ -0,0 +1,71 @@
+/*
+ * This target marks packets to be enqueued to an imq device
+ */
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ipt_IMQ.h>
+#include <linux/imq.h>
+
+static unsigned int imq_target(struct sk_buff **pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ unsigned int hooknum,
+ const struct xt_target *target,
+ const void *targinfo)
+{
+ struct ipt_imq_info *mr = (struct ipt_imq_info*)targinfo;
+
+ (*pskb)->imq_flags = mr->todev | IMQ_F_ENQUEUE;
+
+ return IPT_CONTINUE;
+}
+
+static int imq_checkentry(const char *tablename,
+ const void *e,
+ const struct xt_target *target,
+ void *targinfo,
+ unsigned int hook_mask)
+{
+ struct ipt_imq_info *mr;
+
+ mr = (struct ipt_imq_info*)targinfo;
+
+ if (mr->todev > IMQ_MAX_DEVS) {
+ printk(KERN_WARNING
+ "IMQ: invalid device specified, highest is %u\n",
+ IMQ_MAX_DEVS);
+ return 0;
+ }
+
+ return 1;
+}
+
+static struct ipt_target ipt_imq_reg = {
+ .name = "IMQ",
+ .target = imq_target,
+ .targetsize = sizeof(struct ipt_imq_info),
+ .checkentry = imq_checkentry,
+ .me = THIS_MODULE,
+ .table = "mangle"
+};
+
+static int __init init(void)
+{
+ if (xt_register_target(&ipt_imq_reg))
+ return -EINVAL;
+
+ return 0;
+}
+
+static void __exit fini(void)
+{
+ xt_unregister_target(&ipt_imq_reg);
+}
+
+module_init(init);
+module_exit(fini);
+
+MODULE_AUTHOR("http://www.linuximq.net");
+MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See http://www.linuximq.net/ for more information.");
+MODULE_LICENSE("GPL");
diff -urN linux-2.6.21.1.old/net/ipv4/netfilter/Kconfig linux-2.6.21.1.dev/net/ipv4/netfilter/Kconfig
--- linux-2.6.21.1.old/net/ipv4/netfilter/Kconfig 2007-05-26 20:34:13.929467136 +0200
+++ linux-2.6.21.1.dev/net/ipv4/netfilter/Kconfig 2007-05-26 20:34:15.498228648 +0200
@@ -351,6 +351,17 @@
To compile it as a module, choose M here. If unsure, say N.
+config IP_NF_TARGET_IMQ
+ tristate "IMQ target support"
+ depends on IP_NF_MANGLE
+ help
+ This option adds a `IMQ' target which is used to specify if and
+ to which IMQ device packets should get enqueued/dequeued.
+
+ For more information visit: http://www.linuximq.net/
+
+ To compile it as a module, choose M here. If unsure, say N.
+
config IP_NF_TARGET_TOS
tristate "TOS target support"
depends on IP_NF_MANGLE
diff -urN linux-2.6.21.1.old/net/ipv4/netfilter/Makefile linux-2.6.21.1.dev/net/ipv4/netfilter/Makefile
--- linux-2.6.21.1.old/net/ipv4/netfilter/Makefile 2007-05-26 20:34:13.930466984 +0200
+++ linux-2.6.21.1.dev/net/ipv4/netfilter/Makefile 2007-05-26 20:34:15.499228496 +0200
@@ -58,6 +58,7 @@
obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
obj-$(CONFIG_IP_NF_TARGET_TOS) += ipt_TOS.o
obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
+obj-$(CONFIG_IP_NF_TARGET_IMQ) += ipt_IMQ.o
obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o
diff -urN linux-2.6.21.1.old/net/ipv6/netfilter/ip6t_IMQ.c linux-2.6.21.1.dev/net/ipv6/netfilter/ip6t_IMQ.c
--- linux-2.6.21.1.old/net/ipv6/netfilter/ip6t_IMQ.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.21.1.dev/net/ipv6/netfilter/ip6t_IMQ.c 2007-05-26 20:34:15.531223632 +0200
@@ -0,0 +1,71 @@
+/*
+ * This target marks packets to be enqueued to an imq device
+ */
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <linux/netfilter_ipv6/ip6t_IMQ.h>
+#include <linux/imq.h>
+
+static unsigned int imq_target(struct sk_buff **pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ unsigned int hooknum,
+ const struct xt_target *target,
+ const void *targinfo)
+{
+ struct ip6t_imq_info *mr = (struct ip6t_imq_info*)targinfo;
+
+ (*pskb)->imq_flags = mr->todev | IMQ_F_ENQUEUE;
+
+ return IP6T_CONTINUE;
+}
+
+static int imq_checkentry(const char *tablename,
+ const void *entry,
+ const struct xt_target *target,
+ void *targinfo,
+ unsigned int hook_mask)
+{
+ struct ip6t_imq_info *mr;
+
+ mr = (struct ip6t_imq_info*)targinfo;
+
+ if (mr->todev > IMQ_MAX_DEVS) {
+ printk(KERN_WARNING
+ "IMQ: invalid device specified, highest is %u\n",
+ IMQ_MAX_DEVS);
+ return 0;
+ }
+
+ return 1;
+}
+
+static struct ip6t_target ip6t_imq_reg = {
+ .name = "IMQ",
+ .target = imq_target,
+ .targetsize = sizeof(struct ip6t_imq_info),
+ .table = "mangle",
+ .checkentry = imq_checkentry,
+ .me = THIS_MODULE
+};
+
+static int __init init(void)
+{
+ if (xt_register_target(&ip6t_imq_reg))
+ return -EINVAL;
+
+ return 0;
+}
+
+static void __exit fini(void)
+{
+ xt_unregister_target(&ip6t_imq_reg);
+}
+
+module_init(init);
+module_exit(fini);
+
+MODULE_AUTHOR("http://www.linuximq.net");
+MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See http://www.linuximq.net/ for more information.");
+MODULE_LICENSE("GPL");
diff -urN linux-2.6.21.1.old/net/ipv6/netfilter/Kconfig linux-2.6.21.1.dev/net/ipv6/netfilter/Kconfig
--- linux-2.6.21.1.old/net/ipv6/netfilter/Kconfig 2007-04-27 23:49:26.000000000 +0200
+++ linux-2.6.21.1.dev/net/ipv6/netfilter/Kconfig 2007-05-26 20:34:15.531223632 +0200
@@ -173,6 +173,15 @@
To compile it as a module, choose M here. If unsure, say N.
+config IP6_NF_TARGET_IMQ
+ tristate "IMQ target support"
+ depends on IP6_NF_MANGLE
+ help
+ This option adds a `IMQ' target which is used to specify if and
+ to which imq device packets should get enqueued/dequeued.
+
+ To compile it as a module, choose M here. If unsure, say N.
+
config IP6_NF_TARGET_HL
tristate 'HL (hoplimit) target support'
depends on IP6_NF_MANGLE
diff -urN linux-2.6.21.1.old/net/ipv6/netfilter/Makefile linux-2.6.21.1.dev/net/ipv6/netfilter/Makefile
--- linux-2.6.21.1.old/net/ipv6/netfilter/Makefile 2007-04-27 23:49:26.000000000 +0200
+++ linux-2.6.21.1.dev/net/ipv6/netfilter/Makefile 2007-05-26 20:34:15.558219528 +0200
@@ -13,6 +13,7 @@
obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o
obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
+obj-$(CONFIG_IP6_NF_TARGET_IMQ) += ip6t_IMQ.o
obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o
obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o
obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
diff -urN linux-2.6.21.1.old/net/sched/sch_generic.c linux-2.6.21.1.dev/net/sched/sch_generic.c
--- linux-2.6.21.1.old/net/sched/sch_generic.c 2007-04-27 23:49:26.000000000 +0200
+++ linux-2.6.21.1.dev/net/sched/sch_generic.c 2007-05-26 20:34:15.599213296 +0200
@@ -77,7 +77,6 @@
NOTE: Called under dev->queue_lock with locally disabled BH.
*/
-
static inline int qdisc_restart(struct net_device *dev)
{
struct Qdisc *q = dev->qdisc;
@@ -177,6 +176,11 @@
return q->q.qlen;
}
+int qdisc_restart1(struct net_device *dev)
+{
+ return qdisc_restart(dev);
+}
+
void __qdisc_run(struct net_device *dev)
{
do {
@@ -607,3 +611,4 @@
EXPORT_SYMBOL(qdisc_reset);
EXPORT_SYMBOL(qdisc_lock_tree);
EXPORT_SYMBOL(qdisc_unlock_tree);
+EXPORT_SYMBOL(qdisc_restart1);

View File

@ -0,0 +1,957 @@
diff -urN linux-2.6.21.1.old/include/linux/netfilter_ipv4/ipt_ROUTE.h linux-2.6.21.1.dev/include/linux/netfilter_ipv4/ipt_ROUTE.h
--- linux-2.6.21.1.old/include/linux/netfilter_ipv4/ipt_ROUTE.h 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.21.1.dev/include/linux/netfilter_ipv4/ipt_ROUTE.h 2007-05-26 20:37:08.971856648 +0200
@@ -0,0 +1,23 @@
+/* Header file for iptables ipt_ROUTE target
+ *
+ * (C) 2002 by Cédric de Launois <delaunois@info.ucl.ac.be>
+ *
+ * This software is distributed under GNU GPL v2, 1991
+ */
+#ifndef _IPT_ROUTE_H_target
+#define _IPT_ROUTE_H_target
+
+#define IPT_ROUTE_IFNAMSIZ 16
+
+struct ipt_route_target_info {
+ char oif[IPT_ROUTE_IFNAMSIZ]; /* Output Interface Name */
+ char iif[IPT_ROUTE_IFNAMSIZ]; /* Input Interface Name */
+ u_int32_t gw; /* IP address of gateway */
+ u_int8_t flags;
+};
+
+/* Values for "flags" field */
+#define IPT_ROUTE_CONTINUE 0x01
+#define IPT_ROUTE_TEE 0x02
+
+#endif /*_IPT_ROUTE_H_target*/
diff -urN linux-2.6.21.1.old/include/linux/netfilter_ipv6/ip6t_ROUTE.h linux-2.6.21.1.dev/include/linux/netfilter_ipv6/ip6t_ROUTE.h
--- linux-2.6.21.1.old/include/linux/netfilter_ipv6/ip6t_ROUTE.h 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.21.1.dev/include/linux/netfilter_ipv6/ip6t_ROUTE.h 2007-05-26 20:37:09.001852088 +0200
@@ -0,0 +1,23 @@
+/* Header file for iptables ip6t_ROUTE target
+ *
+ * (C) 2003 by Cédric de Launois <delaunois@info.ucl.ac.be>
+ *
+ * This software is distributed under GNU GPL v2, 1991
+ */
+#ifndef _IPT_ROUTE_H_target
+#define _IPT_ROUTE_H_target
+
+#define IP6T_ROUTE_IFNAMSIZ 16
+
+struct ip6t_route_target_info {
+ char oif[IP6T_ROUTE_IFNAMSIZ]; /* Output Interface Name */
+ char iif[IP6T_ROUTE_IFNAMSIZ]; /* Input Interface Name */
+ u_int32_t gw[4]; /* IPv6 address of gateway */
+ u_int8_t flags;
+};
+
+/* Values for "flags" field */
+#define IP6T_ROUTE_CONTINUE 0x01
+#define IP6T_ROUTE_TEE 0x02
+
+#endif /*_IP6T_ROUTE_H_target*/
diff -urN linux-2.6.21.1.old/net/ipv4/netfilter/ipt_ROUTE.c linux-2.6.21.1.dev/net/ipv4/netfilter/ipt_ROUTE.c
--- linux-2.6.21.1.old/net/ipv4/netfilter/ipt_ROUTE.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.21.1.dev/net/ipv4/netfilter/ipt_ROUTE.c 2007-05-26 20:37:09.001852088 +0200
@@ -0,0 +1,483 @@
+/*
+ * This implements the ROUTE target, which enables you to setup unusual
+ * routes not supported by the standard kernel routing table.
+ *
+ * Copyright (C) 2002 Cedric de Launois <delaunois@info.ucl.ac.be>
+ *
+ * v 1.11 2004/11/23
+ *
+ * This software is distributed under GNU GPL v2, 1991
+ */
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/ip.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <net/netfilter/nf_conntrack.h>
+#include <linux/netfilter_ipv4/ipt_ROUTE.h>
+#include <linux/netdevice.h>
+#include <linux/route.h>
+#include <linux/version.h>
+#include <linux/if_arp.h>
+#include <net/ip.h>
+#include <net/route.h>
+#include <net/icmp.h>
+#include <net/checksum.h>
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(format, args...)
+#endif
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Cedric de Launois <delaunois@info.ucl.ac.be>");
+MODULE_DESCRIPTION("iptables ROUTE target module");
+
+/* Try to route the packet according to the routing keys specified in
+ * route_info. Keys are :
+ * - ifindex :
+ * 0 if no oif preferred,
+ * otherwise set to the index of the desired oif
+ * - route_info->gw :
+ * 0 if no gateway specified,
+ * otherwise set to the next host to which the pkt must be routed
+ * If success, skb->dev is the output device to which the packet must
+ * be sent and skb->dst is not NULL
+ *
+ * RETURN: -1 if an error occured
+ * 1 if the packet was succesfully routed to the
+ * destination desired
+ * 0 if the kernel routing table could not route the packet
+ * according to the keys specified
+ */
+static int route(struct sk_buff *skb,
+ unsigned int ifindex,
+ const struct ipt_route_target_info *route_info)
+{
+ int err;
+ struct rtable *rt;
+ struct iphdr *iph = ip_hdr(skb);
+ struct flowi fl = {
+ .oif = ifindex,
+ .nl_u = {
+ .ip4_u = {
+ .daddr = iph->daddr,
+ .saddr = 0,
+ .tos = RT_TOS(iph->tos),
+ .scope = RT_SCOPE_UNIVERSE,
+ }
+ }
+ };
+
+ /* The destination address may be overloaded by the target */
+ if (route_info->gw)
+ fl.fl4_dst = route_info->gw;
+
+ /* Trying to route the packet using the standard routing table. */
+ if ((err = ip_route_output_key(&rt, &fl))) {
+ if (net_ratelimit())
+ DEBUGP("ipt_ROUTE: couldn't route pkt (err: %i)",err);
+ return -1;
+ }
+
+ /* Drop old route. */
+ dst_release(skb->dst);
+ skb->dst = NULL;
+
+ /* Success if no oif specified or if the oif correspond to the
+ * one desired */
+ if (!ifindex || rt->u.dst.dev->ifindex == ifindex) {
+ skb->dst = &rt->u.dst;
+ skb->dev = skb->dst->dev;
+ skb->protocol = htons(ETH_P_IP);
+ return 1;
+ }
+
+ /* The interface selected by the routing table is not the one
+ * specified by the user. This may happen because the dst address
+ * is one of our own addresses.
+ */
+ if (net_ratelimit())
+ DEBUGP("ipt_ROUTE: failed to route as desired gw=%u.%u.%u.%u oif=%i (got oif=%i)\n",
+ NIPQUAD(route_info->gw), ifindex, rt->u.dst.dev->ifindex);
+
+ return 0;
+}
+
+
+/* Stolen from ip_finish_output2
+ * PRE : skb->dev is set to the device we are leaving by
+ * skb->dst is not NULL
+ * POST: the packet is sent with the link layer header pushed
+ * the packet is destroyed
+ */
+static void ip_direct_send(struct sk_buff *skb)
+{
+ struct dst_entry *dst = skb->dst;
+ struct hh_cache *hh = dst->hh;
+ struct net_device *dev = dst->dev;
+ int hh_len = LL_RESERVED_SPACE(dev);
+
+ /* Be paranoid, rather than too clever. */
+ if (unlikely(skb_headroom(skb) < hh_len && dev->hard_header)) {
+ struct sk_buff *skb2;
+
+ skb2 = skb_realloc_headroom(skb, LL_RESERVED_SPACE(dev));
+ if (skb2 == NULL) {
+ kfree_skb(skb);
+ return;
+ }
+ if (skb->sk)
+ skb_set_owner_w(skb2, skb->sk);
+ kfree_skb(skb);
+ skb = skb2;
+ }
+
+ if (hh) {
+ int hh_alen;
+
+ read_lock_bh(&hh->hh_lock);
+ hh_alen = HH_DATA_ALIGN(hh->hh_len);
+ memcpy(skb->data - hh_alen, hh->hh_data, hh_alen);
+ read_unlock_bh(&hh->hh_lock);
+ skb_push(skb, hh->hh_len);
+ hh->hh_output(skb);
+ } else if (dst->neighbour)
+ dst->neighbour->output(skb);
+ else {
+ if (net_ratelimit())
+ DEBUGP(KERN_DEBUG "ipt_ROUTE: no hdr & no neighbour cache!\n");
+ kfree_skb(skb);
+ }
+}
+
+
+/* PRE : skb->dev is set to the device we are leaving by
+ * POST: - the packet is directly sent to the skb->dev device, without
+ * pushing the link layer header.
+ * - the packet is destroyed
+ */
+static inline int dev_direct_send(struct sk_buff *skb)
+{
+ return dev_queue_xmit(skb);
+}
+
+
+static unsigned int route_oif(const struct ipt_route_target_info *route_info,
+ struct sk_buff *skb)
+{
+ unsigned int ifindex = 0;
+ struct net_device *dev_out = NULL;
+
+ /* The user set the interface name to use.
+ * Getting the current interface index.
+ */
+ if ((dev_out = dev_get_by_name(route_info->oif))) {
+ ifindex = dev_out->ifindex;
+ } else {
+ /* Unknown interface name : packet dropped */
+ if (net_ratelimit())
+ DEBUGP("ipt_ROUTE: oif interface %s not found\n", route_info->oif);
+ return NF_DROP;
+ }
+
+ /* Trying the standard way of routing packets */
+ switch (route(skb, ifindex, route_info)) {
+ case 1:
+ dev_put(dev_out);
+ if (route_info->flags & IPT_ROUTE_CONTINUE)
+ return IPT_CONTINUE;
+
+ ip_direct_send(skb);
+ return NF_STOLEN;
+
+ case 0:
+ /* Failed to send to oif. Trying the hard way */
+ if (route_info->flags & IPT_ROUTE_CONTINUE)
+ return NF_DROP;
+
+ if (net_ratelimit())
+ DEBUGP("ipt_ROUTE: forcing the use of %i\n",
+ ifindex);
+
+ /* We have to force the use of an interface.
+ * This interface must be a tunnel interface since
+ * otherwise we can't guess the hw address for
+ * the packet. For a tunnel interface, no hw address
+ * is needed.
+ */
+ if ((dev_out->type != ARPHRD_TUNNEL)
+ && (dev_out->type != ARPHRD_IPGRE)) {
+ if (net_ratelimit())
+ DEBUGP("ipt_ROUTE: can't guess the hw addr !\n");
+ dev_put(dev_out);
+ return NF_DROP;
+ }
+
+ /* Send the packet. This will also free skb
+ * Do not go through the POST_ROUTING hook because
+ * skb->dst is not set and because it will probably
+ * get confused by the destination IP address.
+ */
+ skb->dev = dev_out;
+ dev_direct_send(skb);
+ dev_put(dev_out);
+ return NF_STOLEN;
+
+ default:
+ /* Unexpected error */
+ dev_put(dev_out);
+ return NF_DROP;
+ }
+}
+
+
+static unsigned int route_iif(const struct ipt_route_target_info *route_info,
+ struct sk_buff *skb)
+{
+ struct net_device *dev_in = NULL;
+
+ /* Getting the current interface index. */
+ if (!(dev_in = dev_get_by_name(route_info->iif))) {
+ if (net_ratelimit())
+ DEBUGP("ipt_ROUTE: iif interface %s not found\n", route_info->iif);
+ return NF_DROP;
+ }
+
+ skb->dev = dev_in;
+ dst_release(skb->dst);
+ skb->dst = NULL;
+
+ netif_rx(skb);
+ dev_put(dev_in);
+ return NF_STOLEN;
+}
+
+
+static unsigned int route_gw(const struct ipt_route_target_info *route_info,
+ struct sk_buff *skb)
+{
+ if (route(skb, 0, route_info)!=1)
+ return NF_DROP;
+
+ if (route_info->flags & IPT_ROUTE_CONTINUE)
+ return IPT_CONTINUE;
+
+ ip_direct_send(skb);
+ return NF_STOLEN;
+}
+
+
+/* To detect and deter routed packet loopback when using the --tee option,
+ * we take a page out of the raw.patch book: on the copied skb, we set up
+ * a fake ->nfct entry, pointing to the local &route_tee_track. We skip
+ * routing packets when we see they already have that ->nfct.
+ */
+
+static struct nf_conn route_tee_track;
+
+static unsigned int ipt_route_target(struct sk_buff **pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ unsigned int hooknum,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
+ const struct xt_target *target,
+#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
+ const void *targinfo,
+ void *userinfo)
+#else
+ const void *targinfo)
+#endif
+{
+ const struct ipt_route_target_info *route_info = targinfo;
+ struct sk_buff *skb = *pskb;
+ unsigned int res;
+
+ if (skb->nfct == &route_tee_track.ct_general) {
+ /* Loopback - a packet we already routed, is to be
+ * routed another time. Avoid that, now.
+ */
+ if (net_ratelimit())
+ DEBUGP(KERN_DEBUG "ipt_ROUTE: loopback - DROP!\n");
+ return NF_DROP;
+ }
+
+ /* If we are at PREROUTING or INPUT hook
+ * the TTL isn't decreased by the IP stack
+ */
+ if (hooknum == NF_IP_PRE_ROUTING ||
+ hooknum == NF_IP_LOCAL_IN) {
+
+ struct iphdr *iph = ip_hdr(skb);
+
+ if (iph->ttl <= 1) {
+ struct rtable *rt;
+ struct flowi fl = {
+ .oif = 0,
+ .nl_u = {
+ .ip4_u = {
+ .daddr = iph->daddr,
+ .saddr = iph->saddr,
+ .tos = RT_TOS(iph->tos),
+ .scope = ((iph->tos & RTO_ONLINK) ?
+ RT_SCOPE_LINK :
+ RT_SCOPE_UNIVERSE)
+ }
+ }
+ };
+
+ if (ip_route_output_key(&rt, &fl)) {
+ return NF_DROP;
+ }
+
+ if (skb->dev == rt->u.dst.dev) {
+ /* Drop old route. */
+ dst_release(skb->dst);
+ skb->dst = &rt->u.dst;
+
+ /* this will traverse normal stack, and
+ * thus call conntrack on the icmp packet */
+ icmp_send(skb, ICMP_TIME_EXCEEDED,
+ ICMP_EXC_TTL, 0);
+ }
+
+ return NF_DROP;
+ }
+
+ /*
+ * If we are at INPUT the checksum must be recalculated since
+ * the length could change as the result of a defragmentation.
+ */
+ if(hooknum == NF_IP_LOCAL_IN) {
+ iph->ttl = iph->ttl - 1;
+ iph->check = 0;
+ iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
+ } else {
+ ip_decrease_ttl(iph);
+ }
+ }
+
+ if ((route_info->flags & IPT_ROUTE_TEE)) {
+ /*
+ * Copy the *pskb, and route the copy. Will later return
+ * IPT_CONTINUE for the original skb, which should continue
+ * on its way as if nothing happened. The copy should be
+ * independantly delivered to the ROUTE --gw.
+ */
+ skb = skb_copy(*pskb, GFP_ATOMIC);
+ if (!skb) {
+ if (net_ratelimit())
+ DEBUGP(KERN_DEBUG "ipt_ROUTE: copy failed!\n");
+ return IPT_CONTINUE;
+ }
+ }
+
+ /* Tell conntrack to forget this packet since it may get confused
+ * when a packet is leaving with dst address == our address.
+ * Good idea ? Dunno. Need advice.
+ *
+ * NEW: mark the skb with our &route_tee_track, so we avoid looping
+ * on any already routed packet.
+ */
+ if (!(route_info->flags & IPT_ROUTE_CONTINUE)) {
+ nf_conntrack_put(skb->nfct);
+ skb->nfct = &route_tee_track.ct_general;
+ skb->nfctinfo = IP_CT_NEW;
+ nf_conntrack_get(skb->nfct);
+ }
+
+ if (route_info->oif[0] != '\0') {
+ res = route_oif(route_info, skb);
+ } else if (route_info->iif[0] != '\0') {
+ res = route_iif(route_info, skb);
+ } else if (route_info->gw) {
+ res = route_gw(route_info, skb);
+ } else {
+ if (net_ratelimit())
+ DEBUGP(KERN_DEBUG "ipt_ROUTE: no parameter !\n");
+ res = IPT_CONTINUE;
+ }
+
+ if ((route_info->flags & IPT_ROUTE_TEE))
+ res = IPT_CONTINUE;
+
+ return res;
+}
+
+
+static int ipt_route_checkentry(const char *tablename,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
+ const void *e,
+#else
+ const struct ipt_ip *ip,
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
+ const struct xt_target *target,
+#endif
+ void *targinfo,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
+ unsigned int targinfosize,
+#endif
+ unsigned int hook_mask)
+{
+ if (strcmp(tablename, "mangle") != 0) {
+ printk("ipt_ROUTE: bad table `%s', use the `mangle' table.\n",
+ tablename);
+ return 0;
+ }
+
+ if (hook_mask & ~( (1 << NF_IP_PRE_ROUTING)
+ | (1 << NF_IP_LOCAL_IN)
+ | (1 << NF_IP_FORWARD)
+ | (1 << NF_IP_LOCAL_OUT)
+ | (1 << NF_IP_POST_ROUTING))) {
+ printk("ipt_ROUTE: bad hook\n");
+ return 0;
+ }
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
+ if (targinfosize != IPT_ALIGN(sizeof(struct ipt_route_target_info))) {
+ printk(KERN_WARNING "ipt_ROUTE: targinfosize %u != %Zu\n",
+ targinfosize,
+ IPT_ALIGN(sizeof(struct ipt_route_target_info)));
+ return 0;
+ }
+#endif
+
+ return 1;
+}
+
+
+static struct ipt_target ipt_route_reg = {
+ .name = "ROUTE",
+ .target = ipt_route_target,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
+ .targetsize = sizeof(struct ipt_route_target_info),
+#endif
+ .checkentry = ipt_route_checkentry,
+ .me = THIS_MODULE,
+};
+
+static int __init init(void)
+{
+ /* Set up fake conntrack (stolen from raw.patch):
+ - to never be deleted, not in any hashes */
+ atomic_set(&route_tee_track.ct_general.use, 1);
+ /* - and look it like as a confirmed connection */
+ set_bit(IPS_CONFIRMED_BIT, &route_tee_track.status);
+ /* Initialize fake conntrack so that NAT will skip it */
+ route_tee_track.status |= IPS_NAT_DONE_MASK;
+
+ return xt_register_target(&ipt_route_reg);
+}
+
+
+static void __exit fini(void)
+{
+ xt_unregister_target(&ipt_route_reg);
+}
+
+module_init(init);
+module_exit(fini);
diff -urN linux-2.6.21.1.old/net/ipv4/netfilter/Kconfig linux-2.6.21.1.dev/net/ipv4/netfilter/Kconfig
--- linux-2.6.21.1.old/net/ipv4/netfilter/Kconfig 2007-05-26 20:37:08.734892672 +0200
+++ linux-2.6.21.1.dev/net/ipv4/netfilter/Kconfig 2007-05-26 20:37:09.002851936 +0200
@@ -562,5 +562,22 @@
To compile it as a module, choose M here. If unsure, say N.
+config IP_NF_TARGET_ROUTE
+ tristate 'ROUTE target support'
+ depends on IP_NF_MANGLE
+ help
+ This option adds a `ROUTE' target, which enables you to setup unusual
+ routes. For example, the ROUTE lets you route a received packet through
+ an interface or towards a host, even if the regular destination of the
+ packet is the router itself. The ROUTE target is also able to change the
+ incoming interface of a packet.
+
+ The target can be or not a final target. It has to be used inside the
+ mangle table.
+
+ If you want to compile it as a module, say M here and read
+ Documentation/modules.txt. The module will be called ipt_ROUTE.o.
+ If unsure, say `N'.
+
endmenu
diff -urN linux-2.6.21.1.old/net/ipv4/netfilter/Makefile linux-2.6.21.1.dev/net/ipv4/netfilter/Makefile
--- linux-2.6.21.1.old/net/ipv4/netfilter/Makefile 2007-05-26 20:37:08.735892520 +0200
+++ linux-2.6.21.1.dev/net/ipv4/netfilter/Makefile 2007-05-26 20:37:09.002851936 +0200
@@ -61,6 +61,7 @@
obj-$(CONFIG_IP_NF_TARGET_IMQ) += ipt_IMQ.o
obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
+obj-$(CONFIG_IP_NF_TARGET_ROUTE) += ipt_ROUTE.o
obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o
obj-$(CONFIG_IP_NF_TARGET_SAME) += ipt_SAME.o
obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
diff -urN linux-2.6.21.1.old/net/ipv6/ndisc.c linux-2.6.21.1.dev/net/ipv6/ndisc.c
--- linux-2.6.21.1.old/net/ipv6/ndisc.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.21.1.dev/net/ipv6/ndisc.c 2007-05-26 20:37:09.003851784 +0200
@@ -154,6 +154,8 @@
.gc_thresh3 = 1024,
};
+EXPORT_SYMBOL(nd_tbl);
+
/* ND options */
struct ndisc_options {
struct nd_opt_hdr *nd_opt_array[__ND_OPT_ARRAY_MAX];
diff -urN linux-2.6.21.1.old/net/ipv6/netfilter/ip6t_ROUTE.c linux-2.6.21.1.dev/net/ipv6/netfilter/ip6t_ROUTE.c
--- linux-2.6.21.1.old/net/ipv6/netfilter/ip6t_ROUTE.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.21.1.dev/net/ipv6/netfilter/ip6t_ROUTE.c 2007-05-26 20:37:09.003851784 +0200
@@ -0,0 +1,330 @@
+/*
+ * This implements the ROUTE v6 target, which enables you to setup unusual
+ * routes not supported by the standard kernel routing table.
+ *
+ * Copyright (C) 2003 Cedric de Launois <delaunois@info.ucl.ac.be>
+ *
+ * v 1.1 2004/11/23
+ *
+ * This software is distributed under GNU GPL v2, 1991
+ */
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/ipv6.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <linux/netfilter_ipv6/ip6t_ROUTE.h>
+#include <linux/netdevice.h>
+#include <linux/version.h>
+#include <net/ipv6.h>
+#include <net/ndisc.h>
+#include <net/ip6_route.h>
+#include <linux/icmpv6.h>
+
+#if 1
+#define DEBUGP printk
+#else
+#define DEBUGP(format, args...)
+#endif
+
+#define NIP6(addr) \
+ ntohs((addr).s6_addr16[0]), \
+ ntohs((addr).s6_addr16[1]), \
+ ntohs((addr).s6_addr16[2]), \
+ ntohs((addr).s6_addr16[3]), \
+ ntohs((addr).s6_addr16[4]), \
+ ntohs((addr).s6_addr16[5]), \
+ ntohs((addr).s6_addr16[6]), \
+ ntohs((addr).s6_addr16[7])
+
+/* Route the packet according to the routing keys specified in
+ * route_info. Keys are :
+ * - ifindex :
+ * 0 if no oif preferred,
+ * otherwise set to the index of the desired oif
+ * - route_info->gw :
+ * 0 if no gateway specified,
+ * otherwise set to the next host to which the pkt must be routed
+ * If success, skb->dev is the output device to which the packet must
+ * be sent and skb->dst is not NULL
+ *
+ * RETURN: 1 if the packet was succesfully routed to the
+ * destination desired
+ * 0 if the kernel routing table could not route the packet
+ * according to the keys specified
+ */
+static int
+route6(struct sk_buff *skb,
+ unsigned int ifindex,
+ const struct ip6t_route_target_info *route_info)
+{
+ struct rt6_info *rt = NULL;
+ struct ipv6hdr *ipv6h = ipv6_hdr(skb);
+ struct in6_addr *gw = (struct in6_addr*)&route_info->gw;
+
+ DEBUGP("ip6t_ROUTE: called with: ");
+ DEBUGP("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ipv6h->daddr));
+ DEBUGP("GATEWAY=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(*gw));
+ DEBUGP("OUT=%s\n", route_info->oif);
+
+ if (ipv6_addr_any(gw))
+ rt = rt6_lookup(&ipv6h->daddr, &ipv6h->saddr, ifindex, 1);
+ else
+ rt = rt6_lookup(gw, &ipv6h->saddr, ifindex, 1);
+
+ if (!rt)
+ goto no_route;
+
+ DEBUGP("ip6t_ROUTE: routing gives: ");
+ DEBUGP("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(rt->rt6i_dst.addr));
+ DEBUGP("GATEWAY=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(rt->rt6i_gateway));
+ DEBUGP("OUT=%s\n", rt->rt6i_dev->name);
+
+ if (ifindex && rt->rt6i_dev->ifindex!=ifindex)
+ goto wrong_route;
+
+ if (!rt->rt6i_nexthop) {
+ DEBUGP("ip6t_ROUTE: discovering neighbour\n");
+ rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_dst.addr);
+ }
+
+ /* Drop old route. */
+ dst_release(skb->dst);
+ skb->dst = &rt->u.dst;
+ skb->dev = rt->rt6i_dev;
+ return 1;
+
+ wrong_route:
+ dst_release(&rt->u.dst);
+ no_route:
+ if (!net_ratelimit())
+ return 0;
+
+ printk("ip6t_ROUTE: no explicit route found ");
+ if (ifindex)
+ printk("via interface %s ", route_info->oif);
+ if (!ipv6_addr_any(gw))
+ printk("via gateway %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", NIP6(*gw));
+ printk("\n");
+ return 0;
+}
+
+
+/* Stolen from ip6_output_finish
+ * PRE : skb->dev is set to the device we are leaving by
+ * skb->dst is not NULL
+ * POST: the packet is sent with the link layer header pushed
+ * the packet is destroyed
+ */
+static void ip_direct_send(struct sk_buff *skb)
+{
+ struct dst_entry *dst = skb->dst;
+ struct hh_cache *hh = dst->hh;
+
+ if (hh) {
+ read_lock_bh(&hh->hh_lock);
+ memcpy(skb->data - 16, hh->hh_data, 16);
+ read_unlock_bh(&hh->hh_lock);
+ skb_push(skb, hh->hh_len);
+ hh->hh_output(skb);
+ } else if (dst->neighbour)
+ dst->neighbour->output(skb);
+ else {
+ if (net_ratelimit())
+ DEBUGP(KERN_DEBUG "ip6t_ROUTE: no hdr & no neighbour cache!\n");
+ kfree_skb(skb);
+ }
+}
+
+
+static unsigned int
+route6_oif(const struct ip6t_route_target_info *route_info,
+ struct sk_buff *skb)
+{
+ unsigned int ifindex = 0;
+ struct net_device *dev_out = NULL;
+
+ /* The user set the interface name to use.
+ * Getting the current interface index.
+ */
+ if ((dev_out = dev_get_by_name(route_info->oif))) {
+ ifindex = dev_out->ifindex;
+ } else {
+ /* Unknown interface name : packet dropped */
+ if (net_ratelimit())
+ DEBUGP("ip6t_ROUTE: oif interface %s not found\n", route_info->oif);
+
+ if (route_info->flags & IP6T_ROUTE_CONTINUE)
+ return IP6T_CONTINUE;
+ else
+ return NF_DROP;
+ }
+
+ /* Trying the standard way of routing packets */
+ if (route6(skb, ifindex, route_info)) {
+ dev_put(dev_out);
+ if (route_info->flags & IP6T_ROUTE_CONTINUE)
+ return IP6T_CONTINUE;
+
+ ip_direct_send(skb);
+ return NF_STOLEN;
+ } else
+ return NF_DROP;
+}
+
+
+static unsigned int
+route6_gw(const struct ip6t_route_target_info *route_info,
+ struct sk_buff *skb)
+{
+ if (route6(skb, 0, route_info)) {
+ if (route_info->flags & IP6T_ROUTE_CONTINUE)
+ return IP6T_CONTINUE;
+
+ ip_direct_send(skb);
+ return NF_STOLEN;
+ } else
+ return NF_DROP;
+}
+
+
+static unsigned int
+ip6t_route_target(struct sk_buff **pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ unsigned int hooknum,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
+ const struct xt_target *target,
+#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
+ const void *targinfo,
+ void *userinfo)
+#else
+ const void *targinfo)
+#endif
+{
+ const struct ip6t_route_target_info *route_info = targinfo;
+ struct sk_buff *skb = *pskb;
+ struct in6_addr *gw = (struct in6_addr*)&route_info->gw;
+ unsigned int res;
+
+ if (route_info->flags & IP6T_ROUTE_CONTINUE)
+ goto do_it;
+
+ /* If we are at PREROUTING or INPUT hook
+ * the TTL isn't decreased by the IP stack
+ */
+ if (hooknum == NF_IP6_PRE_ROUTING ||
+ hooknum == NF_IP6_LOCAL_IN) {
+
+ struct ipv6hdr *ipv6h = ipv6_hdr(skb);
+
+ if (ipv6h->hop_limit <= 1) {
+ /* Force OUTPUT device used as source address */
+ skb->dev = skb->dst->dev;
+
+ icmpv6_send(skb, ICMPV6_TIME_EXCEED,
+ ICMPV6_EXC_HOPLIMIT, 0, skb->dev);
+
+ return NF_DROP;
+ }
+
+ ipv6h->hop_limit--;
+ }
+
+ if ((route_info->flags & IP6T_ROUTE_TEE)) {
+ /*
+ * Copy the *pskb, and route the copy. Will later return
+ * IP6T_CONTINUE for the original skb, which should continue
+ * on its way as if nothing happened. The copy should be
+ * independantly delivered to the ROUTE --gw.
+ */
+ skb = skb_copy(*pskb, GFP_ATOMIC);
+ if (!skb) {
+ if (net_ratelimit())
+ DEBUGP(KERN_DEBUG "ip6t_ROUTE: copy failed!\n");
+ return IP6T_CONTINUE;
+ }
+ }
+
+do_it:
+ if (route_info->oif[0]) {
+ res = route6_oif(route_info, skb);
+ } else if (!ipv6_addr_any(gw)) {
+ res = route6_gw(route_info, skb);
+ } else {
+ if (net_ratelimit())
+ DEBUGP(KERN_DEBUG "ip6t_ROUTE: no parameter !\n");
+ res = IP6T_CONTINUE;
+ }
+
+ if ((route_info->flags & IP6T_ROUTE_TEE))
+ res = IP6T_CONTINUE;
+
+ return res;
+}
+
+
+static int
+ip6t_route_checkentry(const char *tablename,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
+ const void *entry,
+#else
+ const struct ip6t_entry *entry
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
+ const struct xt_target *target,
+#endif
+ void *targinfo,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
+ unsigned int targinfosize,
+#endif
+ unsigned int hook_mask)
+{
+ if (strcmp(tablename, "mangle") != 0) {
+ printk("ip6t_ROUTE: can only be called from \"mangle\" table.\n");
+ return 0;
+ }
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
+ if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_route_target_info))) {
+ printk(KERN_WARNING "ip6t_ROUTE: targinfosize %u != %Zu\n",
+ targinfosize,
+ IP6T_ALIGN(sizeof(struct ip6t_route_target_info)));
+ return 0;
+ }
+#endif
+
+ return 1;
+}
+
+
+static struct ip6t_target ip6t_route_reg = {
+ .name = "ROUTE",
+ .target = ip6t_route_target,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
+ .targetsize = sizeof(struct ip6t_route_target_info),
+#endif
+ .checkentry = ip6t_route_checkentry,
+ .me = THIS_MODULE
+};
+
+
+static int __init init(void)
+{
+ printk(KERN_DEBUG "registering ipv6 ROUTE target\n");
+ if (xt_register_target(&ip6t_route_reg))
+ return -EINVAL;
+
+ return 0;
+}
+
+
+static void __exit fini(void)
+{
+ xt_unregister_target(&ip6t_route_reg);
+}
+
+module_init(init);
+module_exit(fini);
+MODULE_LICENSE("GPL");
diff -urN linux-2.6.21.1.old/net/ipv6/netfilter/Kconfig linux-2.6.21.1.dev/net/ipv6/netfilter/Kconfig
--- linux-2.6.21.1.old/net/ipv6/netfilter/Kconfig 2007-05-26 20:37:08.809881272 +0200
+++ linux-2.6.21.1.dev/net/ipv6/netfilter/Kconfig 2007-05-26 20:37:09.003851784 +0200
@@ -209,5 +209,18 @@
If you want to compile it as a module, say M here and read
<file:Documentation/kbuild/modules.txt>. If unsure, say `N'.
+config IP6_NF_TARGET_ROUTE
+ tristate 'ROUTE target support'
+ depends on IP6_NF_MANGLE
+ help
+ This option adds a `ROUTE' target, which enables you to setup unusual
+ routes. The ROUTE target is also able to change the incoming interface
+ of a packet.
+
+ The target can be or not a final target. It has to be used inside the
+ mangle table.
+
+ Not working as a module.
+
endmenu
diff -urN linux-2.6.21.1.old/net/ipv6/netfilter/Makefile linux-2.6.21.1.dev/net/ipv6/netfilter/Makefile
--- linux-2.6.21.1.old/net/ipv6/netfilter/Makefile 2007-05-26 20:37:08.809881272 +0200
+++ linux-2.6.21.1.dev/net/ipv6/netfilter/Makefile 2007-05-26 20:37:09.003851784 +0200
@@ -20,6 +20,7 @@
obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o
obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o
obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o
+obj-$(CONFIG_IP6_NF_TARGET_ROUTE) += ip6t_ROUTE.o
obj-$(CONFIG_IP6_NF_MATCH_MH) += ip6t_mh.o
# objects for l3 independent conntrack

View File

@ -0,0 +1,958 @@
diff -urN linux-2.6.21.1.old/include/linux/netfilter/oot_conntrack.h linux-2.6.21.1.dev/include/linux/netfilter/oot_conntrack.h
--- linux-2.6.21.1.old/include/linux/netfilter/oot_conntrack.h 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.21.1.dev/include/linux/netfilter/oot_conntrack.h 2007-05-26 20:40:10.922195992 +0200
@@ -0,0 +1,5 @@
+#if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE)
+# include <linux/netfilter_ipv4/ip_conntrack.h>
+#else /* linux-2.6.20+ */
+# include <net/netfilter/nf_nat_rule.h>
+#endif
diff -urN linux-2.6.21.1.old/include/linux/netfilter/oot_trans.h linux-2.6.21.1.dev/include/linux/netfilter/oot_trans.h
--- linux-2.6.21.1.old/include/linux/netfilter/oot_trans.h 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.21.1.dev/include/linux/netfilter/oot_trans.h 2007-05-26 20:40:10.940193256 +0200
@@ -0,0 +1,14 @@
+/* Out of tree workarounds */
+#include <linux/version.h>
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)
+# define HAVE_MATCHINFOSIZE 1
+# define HAVE_TARGUSERINFO 1
+# define HAVE_TARGINFOSIZE 1
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
+# define nfmark mark
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 21)
+# define tcp_v4_check(tcph, tcph_sz, s, d, csp) \
+ tcp_v4_check((tcph_sz), (s), (d), (csp))
+#endif
diff -urN linux-2.6.21.1.old/include/linux/netfilter/xt_CHAOS.h linux-2.6.21.1.dev/include/linux/netfilter/xt_CHAOS.h
--- linux-2.6.21.1.old/include/linux/netfilter/xt_CHAOS.h 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.21.1.dev/include/linux/netfilter/xt_CHAOS.h 2007-05-26 20:40:10.940193256 +0200
@@ -0,0 +1,14 @@
+#ifndef _LINUX_XT_CHAOS_H
+#define _LINUX_XT_CHAOS_H 1
+
+enum xt_chaos_variant {
+ XTCHAOS_NORMAL,
+ XTCHAOS_TARPIT,
+ XTCHAOS_DELUDE,
+};
+
+struct xt_chaos_info {
+ enum xt_chaos_variant variant;
+};
+
+#endif /* _LINUX_XT_CHAOS_H */
diff -urN linux-2.6.21.1.old/include/linux/netfilter/xt_portscan.h linux-2.6.21.1.dev/include/linux/netfilter/xt_portscan.h
--- linux-2.6.21.1.old/include/linux/netfilter/xt_portscan.h 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.21.1.dev/include/linux/netfilter/xt_portscan.h 2007-05-26 20:40:10.940193256 +0200
@@ -0,0 +1,8 @@
+#ifndef _LINUX_XT_PORTSCAN_H
+#define _LINUX_XT_PORTSCAN_H 1
+
+struct xt_portscan_info {
+ unsigned int match_stealth, match_syn, match_cn, match_gr;
+};
+
+#endif /* _LINUX_XT_PORTSCAN_H */
diff -urN linux-2.6.21.1.old/net/netfilter/find_match.c linux-2.6.21.1.dev/net/netfilter/find_match.c
--- linux-2.6.21.1.old/net/netfilter/find_match.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.21.1.dev/net/netfilter/find_match.c 2007-05-26 20:40:10.970188696 +0200
@@ -0,0 +1,39 @@
+/*
+ xt_request_find_match
+ by Jan Engelhardt <jengelh [at] gmx de>, 2006 - 2007
+
+ Based upon linux-2.6.18.5/net/netfilter/x_tables.c:
+ Copyright (C) 2006-2006 Harald Welte <laforge@netfilter.org>
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License version 2 as
+ published by the Free Software Foundation.
+*/
+#include <linux/err.h>
+#include <linux/netfilter_arp.h>
+#include <linux/socket.h>
+#include <linux/netfilter/x_tables.h>
+
+/*
+ * Yeah this code is sub-optimal, but the function is missing in
+ * mainline so far. -jengelh
+ */
+static struct xt_match *xt_request_find_match_lo(int af, const char *name,
+ u8 revision)
+{
+ static const char *const xt_prefix[] = {
+ [AF_INET] = "ip",
+ [AF_INET6] = "ip6",
+ [NF_ARP] = "arp",
+ };
+ struct xt_match *match;
+
+ match = try_then_request_module(xt_find_match(af, name, revision),
+ "%st_%s", xt_prefix[af], name);
+ if(IS_ERR(match) || match == NULL)
+ return NULL;
+
+ return match;
+}
+
+/* In case it goes into mainline, let this out-of-tree package compile */
+#define xt_request_find_match xt_request_find_match_lo
diff -urN linux-2.6.21.1.old/net/netfilter/Kconfig linux-2.6.21.1.dev/net/netfilter/Kconfig
--- linux-2.6.21.1.old/net/netfilter/Kconfig 2007-04-27 23:49:26.000000000 +0200
+++ linux-2.6.21.1.dev/net/netfilter/Kconfig 2007-05-26 20:40:11.003183680 +0200
@@ -255,6 +255,14 @@
# alphabetically ordered list of targets
+config NETFILTER_XT_TARGET_CHAOS
+ tristate '"CHAOS" target support'
+ depends on NETFILTER_XTABLES
+ help
+ This option adds a `CHAOS' target.
+
+ To compile it as a module, choose M here. If unsure, say N.
+
config NETFILTER_XT_TARGET_CLASSIFY
tristate '"CLASSIFY" target support'
depends on NETFILTER_XTABLES
@@ -282,6 +290,14 @@
<file:Documentation/kbuild/modules.txt>. The module will be called
ipt_CONNMARK.ko. If unsure, say `N'.
+config NETFILTER_XT_TARGET_DELUDE
+ tristate '"DELUDE" target support'
+ depends on NETFILTER_XTABLES
+ help
+ This option adds a `DELUDE' target.
+
+ To compile it as a module, choose M here. If unsure, say N.
+
config NETFILTER_XT_TARGET_DSCP
tristate '"DSCP" target support'
depends on NETFILTER_XTABLES
@@ -526,6 +542,14 @@
To compile it as a module, choose M here. If unsure, say N.
+config NETFILTER_XT_MATCH_PORTSCAN
+ tristate '"portscan" match support'
+ depends on NETFILTER_XTABLES
+ help
+ This option adds a 'portscan' match support.
+
+ To compile it as a module, choose M here. If unsure, say N.
+
config NETFILTER_XT_MATCH_MULTIPORT
tristate "Multiple port match support"
depends on NETFILTER_XTABLES
diff -urN linux-2.6.21.1.old/net/netfilter/Makefile linux-2.6.21.1.dev/net/netfilter/Makefile
--- linux-2.6.21.1.old/net/netfilter/Makefile 2007-04-27 23:49:26.000000000 +0200
+++ linux-2.6.21.1.dev/net/netfilter/Makefile 2007-05-26 20:40:11.003183680 +0200
@@ -37,8 +37,10 @@
obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o
# targets
+obj-$(CONFIG_NETFILTER_XT_TARGET_CHAOS) += xt_CHAOS.o
obj-$(CONFIG_NETFILTER_XT_TARGET_CLASSIFY) += xt_CLASSIFY.o
obj-$(CONFIG_NETFILTER_XT_TARGET_CONNMARK) += xt_CONNMARK.o
+obj-$(CONFIG_NETFILTER_XT_TARGET_DELUDE) += xt_DELUDE.o
obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o
obj-$(CONFIG_NETFILTER_XT_TARGET_MARK) += xt_MARK.o
obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o
@@ -63,6 +65,7 @@
obj-$(CONFIG_NETFILTER_XT_MATCH_MARK) += xt_mark.o
obj-$(CONFIG_NETFILTER_XT_MATCH_MULTIPORT) += xt_multiport.o
obj-$(CONFIG_NETFILTER_XT_MATCH_POLICY) += xt_policy.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_PORTSCAN) += xt_portscan.o
obj-$(CONFIG_NETFILTER_XT_MATCH_PKTTYPE) += xt_pkttype.o
obj-$(CONFIG_NETFILTER_XT_MATCH_QUOTA) += xt_quota.o
obj-$(CONFIG_NETFILTER_XT_MATCH_REALM) += xt_realm.o
diff -urN linux-2.6.21.1.old/net/netfilter/xt_CHAOS.c linux-2.6.21.1.dev/net/netfilter/xt_CHAOS.c
--- linux-2.6.21.1.old/net/netfilter/xt_CHAOS.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.21.1.dev/net/netfilter/xt_CHAOS.c 2007-05-26 20:40:11.004183528 +0200
@@ -0,0 +1,204 @@
+/*
+ CHAOS target for netfilter
+
+ Copyright © Jan Engelhardt <jengelh [at] gmx de>, 2006 - 2007
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License version 2 as
+ published by the Free Software Foundation.
+*/
+#include <linux/icmp.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/stat.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_tcpudp.h>
+#include <linux/netfilter_ipv4/ipt_REJECT.h>
+#include <net/ip.h>
+#include <linux/netfilter/xt_CHAOS.h>
+#include "find_match.c"
+#include <linux/netfilter/oot_trans.h>
+#define PFX KBUILD_MODNAME ": "
+
+/* Module parameters */
+static unsigned int reject_percentage = ~0U * .01;
+static unsigned int delude_percentage = ~0U * .0101;
+module_param(reject_percentage, uint, S_IRUGO | S_IWUSR);
+module_param(delude_percentage, uint, S_IRUGO | S_IWUSR);
+
+/* References to other matches/targets */
+static struct xt_match *xm_tcp;
+static struct xt_target *xt_delude, *xt_reject, *xt_tarpit;
+
+static int have_delude, have_tarpit;
+
+/* Static data for other matches/targets */
+static const struct ipt_reject_info reject_params = {
+ .with = ICMP_HOST_UNREACH,
+};
+
+static const struct xt_tcp tcp_params = {
+ .spts = {0, ~0},
+ .dpts = {0, ~0},
+};
+
+/* CHAOS functions */
+static void xt_chaos_total(const struct xt_chaos_info *info,
+ struct sk_buff **pskb, const struct net_device *in,
+ const struct net_device *out, unsigned int hooknum)
+{
+ const int protoff = ip_hdrlen(*pskb);
+ const int offset = ntohs(ip_hdr(*pskb)->frag_off) & IP_OFFSET;
+ const struct xt_target *destiny;
+ int hotdrop = 0, ret;
+
+ ret = xm_tcp->match(*pskb, in, out, xm_tcp, &tcp_params,
+ offset, protoff, &hotdrop);
+ if(!ret || hotdrop || (unsigned int)net_random() > delude_percentage)
+ return;
+
+ destiny = (info->variant == XTCHAOS_TARPIT) ? xt_tarpit : xt_delude;
+#ifdef HAVE_TARGUSERINFO
+ destiny->target(pskb, in, out, hooknum, destiny, NULL, NULL);
+#else
+ destiny->target(pskb, in, out, hooknum, destiny, NULL);
+#endif
+ return;
+}
+
+static unsigned int xt_chaos_target(struct sk_buff **pskb,
+ const struct net_device *in, const struct net_device *out,
+ unsigned int hooknum, const struct xt_target *target, const void *targinfo
+#ifdef HAVE_TARGUSERINFO
+ ,
+ void *userinfo
+#endif
+ )
+{
+ /* Equivalent to:
+ * -A chaos -m statistic --mode random --probability \
+ * $reject_percentage -j REJECT --reject-with host-unreach;
+ * -A chaos -p tcp -m statistic --mode random --probability \
+ * $delude_percentage -j DELUDE;
+ * -A chaos -j DROP;
+ */
+ const struct xt_chaos_info *info = targinfo;
+
+ if((unsigned int)net_random() <= reject_percentage)
+#ifdef HAVE_TARGUSERINFO
+ return xt_reject->target(pskb, in, out, hooknum, target,
+ &reject_params, userinfo);
+#else
+ return xt_reject->target(pskb, in, out, hooknum, target,
+ &reject_params);
+#endif
+
+ /* TARPIT/DELUDE may not be called from the OUTPUT chain */
+ if(ip_hdr(*pskb)->protocol == IPPROTO_TCP &&
+ info->variant != XTCHAOS_NORMAL && hooknum != NF_IP_LOCAL_OUT)
+ xt_chaos_total(info, pskb, in, out, hooknum);
+
+ return NF_DROP;
+}
+
+static int xt_chaos_checkentry(const char *tablename, const void *entry,
+ const struct xt_target *target, void *targinfo,
+#ifdef HAVE_TARGINFOSIZE
+ unsigned int targinfosize,
+#endif
+ unsigned int hook_mask)
+{
+ const struct xt_chaos_info *info = targinfo;
+ if(info->variant == XTCHAOS_DELUDE && !have_delude) {
+ printk(KERN_WARNING PFX "Error: Cannot use --delude when "
+ "DELUDE module not available\n");
+ return 0;
+ }
+ if(info->variant == XTCHAOS_TARPIT && !have_tarpit) {
+ printk(KERN_WARNING PFX "Error: Cannot use --tarpit when "
+ "TARPIT module not available\n");
+ return 0;
+ }
+ return 1;
+}
+
+static struct xt_target xt_chaos_info = {
+ .name = "CHAOS",
+ .target = xt_chaos_target,
+ .checkentry = xt_chaos_checkentry,
+ .table = "filter",
+ .targetsize = sizeof(struct xt_chaos_info),
+ .hooks = (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD) |
+ (1 << NF_IP_LOCAL_OUT),
+ .family = AF_INET,
+ .me = THIS_MODULE,
+};
+
+static int __init xt_chaos_init(void)
+{
+ int ret = -EINVAL;
+
+ xm_tcp = xt_request_find_match(AF_INET, "tcp", 0);
+ if(xm_tcp == NULL) {
+ printk(KERN_WARNING PFX "Error: Could not find or load "
+ "\"tcp\" match\n");
+ return -EINVAL;
+ }
+
+ xt_reject = xt_request_find_target(AF_INET, "REJECT", 0);
+ if(xt_reject == NULL) {
+ printk(KERN_WARNING PFX "Error: Could not find or load "
+ "\"REJECT\" target\n");
+ goto out2;
+ }
+
+ xt_tarpit = xt_request_find_target(AF_INET, "TARPIT", 0);
+ have_tarpit = xt_tarpit != NULL;
+ if(!have_tarpit)
+ printk(KERN_WARNING PFX "Warning: Could not find or load "
+ "\"TARPIT\" target\n");
+
+ xt_delude = xt_request_find_target(AF_INET, "DELUDE", 0);
+ have_delude = xt_delude != NULL;
+ if(!have_delude)
+ printk(KERN_WARNING PFX "Warning: Could not find or load "
+ "\"DELUDE\" target\n");
+
+ if((ret = xt_register_target(&xt_chaos_info)) != 0) {
+ printk(KERN_WARNING PFX "xt_register_target returned "
+ "error %d\n", ret);
+ goto out3;
+ }
+
+ return 0;
+
+ out3:
+ if(have_delude)
+ module_put(xt_delude->me);
+ if(have_tarpit)
+ module_put(xt_tarpit->me);
+ module_put(xt_reject->me);
+ out2:
+ module_put(xm_tcp->me);
+ return ret;
+}
+
+static void __exit xt_chaos_exit(void)
+{
+ xt_unregister_target(&xt_chaos_info);
+ module_put(xm_tcp->me);
+ module_put(xt_reject->me);
+ if(have_delude)
+ module_put(xt_delude->me);
+ if(have_tarpit)
+ module_put(xt_tarpit->me);
+ return;
+}
+
+module_init(xt_chaos_init);
+module_exit(xt_chaos_exit);
+MODULE_AUTHOR("Jan Engelhardt <jengelh@gmx.de>");
+MODULE_DESCRIPTION("netfilter CHAOS target");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ipt_CHAOS");
diff -urN linux-2.6.21.1.old/net/netfilter/xt_DELUDE.c linux-2.6.21.1.dev/net/netfilter/xt_DELUDE.c
--- linux-2.6.21.1.old/net/netfilter/xt_DELUDE.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.21.1.dev/net/netfilter/xt_DELUDE.c 2007-05-26 20:40:11.004183528 +0200
@@ -0,0 +1,288 @@
+/*
+ DELUDE target
+ Copyright © Jan Engelhardt <jengelh [at] gmx de>, 2007
+
+ Based upon linux-2.6.18.5/net/ipv4/netfilter/ipt_REJECT.c:
+ (C) 1999-2001 Paul `Rusty' Russell
+ (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
+
+ xt_DELUDE acts like REJECT, but does reply with SYN-ACK on SYN.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License version 2 as
+ published by the Free Software Foundation.
+*/
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/ip.h>
+#include <linux/random.h>
+#include <linux/tcp.h>
+#include <linux/udp.h>
+#include <linux/icmp.h>
+#include <net/icmp.h>
+#include <net/ip.h>
+#include <net/tcp.h>
+#include <net/route.h>
+#include <net/dst.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#ifdef CONFIG_BRIDGE_NETFILTER
+# include <linux/netfilter_bridge.h>
+#endif
+#include <linux/netfilter/oot_trans.h>
+#define PFX KBUILD_MODNAME ": "
+
+static inline struct rtable *route_reverse(struct sk_buff *skb,
+ struct tcphdr *tcph, int hook)
+{
+ struct iphdr *iph = ip_hdr(skb);
+ struct dst_entry *odst;
+ struct flowi fl = {};
+ struct rtable *rt;
+
+ /* We don't require ip forwarding to be enabled to be able to
+ * send a RST reply for bridged traffic. */
+ if (hook != NF_IP_FORWARD
+#ifdef CONFIG_BRIDGE_NETFILTER
+ || (skb->nf_bridge && skb->nf_bridge->mask & BRNF_BRIDGED)
+#endif
+ ) {
+ fl.nl_u.ip4_u.daddr = iph->saddr;
+ if (hook == NF_IP_LOCAL_IN)
+ fl.nl_u.ip4_u.saddr = iph->daddr;
+ fl.nl_u.ip4_u.tos = RT_TOS(iph->tos);
+
+ if (ip_route_output_key(&rt, &fl) != 0)
+ return NULL;
+ } else {
+ /* non-local src, find valid iif to satisfy
+ * rp-filter when calling ip_route_input. */
+ fl.nl_u.ip4_u.daddr = iph->daddr;
+ if (ip_route_output_key(&rt, &fl) != 0)
+ return NULL;
+
+ odst = skb->dst;
+ if (ip_route_input(skb, iph->saddr, iph->daddr,
+ RT_TOS(iph->tos), rt->u.dst.dev) != 0) {
+ dst_release(&rt->u.dst);
+ return NULL;
+ }
+ dst_release(&rt->u.dst);
+ rt = (struct rtable *)skb->dst;
+ skb->dst = odst;
+
+ fl.nl_u.ip4_u.daddr = iph->saddr;
+ fl.nl_u.ip4_u.saddr = iph->daddr;
+ fl.nl_u.ip4_u.tos = RT_TOS(iph->tos);
+ }
+
+ if (rt->u.dst.error) {
+ dst_release(&rt->u.dst);
+ return NULL;
+ }
+
+ fl.proto = IPPROTO_TCP;
+ fl.fl_ip_sport = tcph->dest;
+ fl.fl_ip_dport = tcph->source;
+
+ xfrm_lookup((struct dst_entry **)&rt, &fl, NULL, 0);
+
+ return rt;
+}
+
+static void send_reset(struct sk_buff *oldskb, int hook)
+{
+ struct sk_buff *nskb;
+ struct iphdr *iph = ip_hdr(oldskb);
+ struct tcphdr _otcph, *oth, *tcph;
+ __be16 tmp_port;
+ __be32 tmp_addr;
+ int needs_ack;
+ unsigned int addr_type;
+
+ /* IP header checks: fragment. */
+ if (iph->frag_off & htons(IP_OFFSET))
+ return;
+
+ oth = skb_header_pointer(oldskb, ip_hdrlen(oldskb),
+ sizeof(_otcph), &_otcph);
+ if (oth == NULL)
+ return;
+
+ /* No RST for RST. */
+ if (oth->rst)
+ return;
+
+ /* Check checksum */
+ if (nf_ip_checksum(oldskb, hook, ip_hdrlen(oldskb), IPPROTO_TCP))
+ return;
+
+ /* We need a linear, writeable skb. We also need to expand
+ headroom in case hh_len of incoming interface < hh_len of
+ outgoing interface */
+ nskb = skb_copy_expand(oldskb, LL_MAX_HEADER, skb_tailroom(oldskb),
+ GFP_ATOMIC);
+ if (!nskb)
+ return;
+
+ /* This packet will not be the same as the other: clear nf fields */
+ nf_reset(nskb);
+ nskb->nfmark = 0;
+ skb_init_secmark(nskb);
+
+ skb_shinfo(nskb)->gso_size = 0;
+ skb_shinfo(nskb)->gso_segs = 0;
+ skb_shinfo(nskb)->gso_type = 0;
+
+ tcph = tcp_hdr(nskb);
+
+ /* Swap source and dest */
+ tmp_addr = ip_hdr(nskb)->saddr;
+ ip_hdr(nskb)->saddr = ip_hdr(nskb)->daddr;
+ ip_hdr(nskb)->daddr = tmp_addr;
+ tmp_port = tcph->source;
+ tcph->source = tcph->dest;
+ tcph->dest = tmp_port;
+
+ /* Truncate to length (no data) */
+ tcph->doff = sizeof(struct tcphdr)/4;
+ skb_trim(nskb, ip_hdrlen(nskb) + sizeof(struct tcphdr));
+ ip_hdr(nskb)->tot_len = htons(nskb->len);
+
+ if(oth->syn && !oth->ack && !oth->rst && !oth->fin) {
+ /* DELUDE essential part */
+ tcph->ack_seq = htonl(ntohl(oth->seq) + oth->syn + oth->fin +
+ oldskb->len - ip_hdrlen(oldskb) -
+ (oth->doff << 2));
+ tcph->seq = htonl(secure_tcp_sequence_number(
+ ip_hdr(nskb)->saddr, ip_hdr(nskb)->daddr,
+ tcph->source, tcph->dest));
+ tcph->ack = 1;
+ } else {
+ if(!tcph->ack) {
+ needs_ack = 1;
+ tcph->ack_seq = htonl(ntohl(oth->seq) + oth->syn + oth->fin
+ + oldskb->len - ip_hdrlen(oldskb)
+ - (oth->doff<<2));
+ tcph->seq = 0;
+ } else {
+ needs_ack = 0;
+ tcph->seq = oth->ack_seq;
+ tcph->ack_seq = 0;
+ }
+
+ /* Reset flags */
+ ((u_int8_t *)tcph)[13] = 0;
+ tcph->rst = 1;
+ tcph->ack = needs_ack;
+ }
+
+
+ tcph->window = 0;
+ tcph->urg_ptr = 0;
+
+ /* Adjust TCP checksum */
+ tcph->check = 0;
+ tcph->check = tcp_v4_check(tcph, sizeof(struct tcphdr),
+ ip_hdr(nskb)->saddr,
+ ip_hdr(nskb)->daddr,
+ csum_partial((char *)tcph,
+ sizeof(struct tcphdr), 0));
+
+ /* Set DF, id = 0 */
+ ip_hdr(nskb)->frag_off = htons(IP_DF);
+ ip_hdr(nskb)->id = 0;
+
+ addr_type = RTN_UNSPEC;
+ if (hook != NF_IP_FORWARD
+#ifdef CONFIG_BRIDGE_NETFILTER
+ || (nskb->nf_bridge && nskb->nf_bridge->mask & BRNF_BRIDGED)
+#endif
+ )
+ addr_type = RTN_LOCAL;
+
+ if (ip_route_me_harder(&nskb, addr_type))
+ goto free_nskb;
+
+ nskb->ip_summed = CHECKSUM_NONE;
+
+ /* Adjust IP TTL */
+ ip_hdr(nskb)->ttl = dst_metric(nskb->dst, RTAX_HOPLIMIT);
+
+ /* Adjust IP checksum */
+ ip_hdr(nskb)->check = 0;
+ ip_hdr(nskb)->check = ip_fast_csum((unsigned char *)ip_hdr(nskb),
+ ip_hdr(nskb)->ihl);
+
+ /* "Never happens" */
+ if (nskb->len > dst_mtu(nskb->dst))
+ goto free_nskb;
+
+ nf_ct_attach(nskb, oldskb);
+
+ NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
+ dst_output);
+ return;
+
+ free_nskb:
+ kfree_skb(nskb);
+}
+
+static unsigned int xt_delude_target(struct sk_buff **pskb,
+ const struct net_device *in, const struct net_device *out,
+ unsigned int hooknum, const struct xt_target *target, const void *targinfo
+#ifdef HAVE_TARGUSERINFO
+ ,
+ void *userinfo
+#endif
+ )
+{
+ /* WARNING: This code causes reentry within iptables.
+ This means that the iptables jump stack is now crap. We
+ must return an absolute verdict. --RR */
+ send_reset(*pskb, hooknum);
+ return NF_DROP;
+}
+
+static int xt_delude_check(const char *tablename, const void *e_void,
+ const struct xt_target *target, void *targinfo,
+#ifdef HAVE_TARGINFOSIZE
+ unsigned int targinfosize,
+#endif
+ unsigned int hook_mask)
+{
+ if(hook_mask & ~((1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD))) {
+ printk(KERN_WARNING PFX "DELUDE may not be used in chains "
+ "other than INPUT and FORWARD\n");
+ return 0;
+ }
+ return 1;
+}
+
+static struct xt_target xt_delude_info = {
+ .name = "DELUDE",
+ .target = xt_delude_target,
+ .checkentry = xt_delude_check,
+ .table = "filter",
+ .hooks = (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD) |
+ (1 << NF_IP_LOCAL_OUT),
+ .proto = IPPROTO_TCP,
+ .family = AF_INET,
+ .me = THIS_MODULE,
+};
+
+static int __init xt_delude_init(void)
+{
+ return xt_register_target(&xt_delude_info);
+}
+
+static void __exit xt_delude_exit(void)
+{
+ xt_unregister_target(&xt_delude_info);
+}
+
+module_init(xt_delude_init);
+module_exit(xt_delude_exit);
+MODULE_AUTHOR("Jan Engelhardt <jengelh@gmx.de>");
+MODULE_DESCRIPTION("netfilter DELUDE target");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ipt_DELUDE");
diff -urN linux-2.6.21.1.old/net/netfilter/xt_portscan.c linux-2.6.21.1.dev/net/netfilter/xt_portscan.c
--- linux-2.6.21.1.old/net/netfilter/xt_portscan.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.21.1.dev/net/netfilter/xt_portscan.c 2007-05-26 20:40:11.004183528 +0200
@@ -0,0 +1,272 @@
+/*
+ portscan match for netfilter
+
+ Written by Jan Engelhardt, 2006 - 2007
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License version 2 as
+ published by the Free Software Foundation.
+*/
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/skbuff.h>
+#include <linux/stat.h>
+#include <linux/tcp.h>
+#include <linux/types.h>
+#include <linux/version.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_tcpudp.h>
+#include <linux/netfilter/oot_conntrack.h>
+#include <linux/netfilter/xt_portscan.h>
+#include <linux/netfilter/oot_trans.h>
+#define PFX KBUILD_MODNAME ": "
+
+enum {
+ TCP_FLAGS_ALL3 = TCP_FLAG_FIN | TCP_FLAG_RST | TCP_FLAG_SYN,
+ TCP_FLAGS_ALL4 = TCP_FLAGS_ALL3 | TCP_FLAG_ACK,
+ TCP_FLAGS_ALL6 = TCP_FLAGS_ALL4 | TCP_FLAG_PSH | TCP_FLAG_URG,
+};
+
+/* Module parameters */
+static unsigned int
+ connmark_mask = ~0,
+ packet_mask = ~0,
+ mark_seen = 0x9,
+ mark_synrcv = 0x1,
+ mark_closed = 0x2,
+ mark_synscan = 0x3,
+ mark_estab1 = 0x4,
+ mark_estab2 = 0x5,
+ mark_cnscan = 0x6,
+ mark_grscan = 0x7,
+ mark_valid = 0x8;
+
+module_param(connmark_mask, uint, S_IRUGO | S_IWUSR);
+module_param(packet_mask, uint, S_IRUGO | S_IWUSR);
+module_param(mark_seen, uint, S_IRUGO | S_IWUSR);
+module_param(mark_synrcv, uint, S_IRUGO | S_IWUSR);
+module_param(mark_closed, uint, S_IRUGO | S_IWUSR);
+module_param(mark_synscan, uint, S_IRUGO | S_IWUSR);
+module_param(mark_estab1, uint, S_IRUGO | S_IWUSR);
+module_param(mark_estab2, uint, S_IRUGO | S_IWUSR);
+module_param(mark_cnscan, uint, S_IRUGO | S_IWUSR);
+module_param(mark_grscan, uint, S_IRUGO | S_IWUSR);
+module_param(mark_valid, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(connmark_mask, "only set specified bits in connection mark");
+MODULE_PARM_DESC(packet_mask, "only set specified bits in packet mark");
+MODULE_PARM_DESC(mark_seen, "nfmark value for packet-seen state");
+MODULE_PARM_DESC(mark_synrcv, "connmark value for SYN Received state");
+MODULE_PARM_DESC(mark_closed, "connmark value for closed state");
+MODULE_PARM_DESC(mark_synscan, "connmark value for SYN Scan state");
+MODULE_PARM_DESC(mark_estab1, "connmark value for Established-1 state");
+MODULE_PARM_DESC(mark_estab2, "connmark value for Established-2 state");
+MODULE_PARM_DESC(mark_cnscan, "connmark value for Connect Scan state");
+MODULE_PARM_DESC(mark_grscan, "connmark value for Grab Scan state");
+MODULE_PARM_DESC(mark_valid, "connmark value for Valid state");
+
+/* TCP flag functions */
+static inline int tflg_ack4(const struct tcphdr *th)
+{
+ return (tcp_flag_word(th) & TCP_FLAGS_ALL4) == TCP_FLAG_ACK;
+}
+
+static inline int tflg_ack6(const struct tcphdr *th)
+{
+ return (tcp_flag_word(th) & TCP_FLAGS_ALL6) == TCP_FLAG_ACK;
+}
+
+static inline int tflg_fin(const struct tcphdr *th)
+{
+ return (tcp_flag_word(th) & TCP_FLAGS_ALL3) == TCP_FLAG_FIN;
+}
+
+static inline int tflg_rst(const struct tcphdr *th)
+{
+ return (tcp_flag_word(th) & TCP_FLAGS_ALL3) == TCP_FLAG_RST;
+}
+
+static inline int tflg_rstack(const struct tcphdr *th)
+{
+ return (tcp_flag_word(th) & TCP_FLAGS_ALL4) ==
+ (TCP_FLAG_ACK | TCP_FLAG_RST);
+}
+
+static inline int tflg_syn(const struct tcphdr *th)
+{
+ return (tcp_flag_word(th) & TCP_FLAGS_ALL4) == TCP_FLAG_SYN;
+}
+
+static inline int tflg_synack(const struct tcphdr *th)
+{
+ return (tcp_flag_word(th) & TCP_FLAGS_ALL4) ==
+ (TCP_FLAG_SYN | TCP_FLAG_ACK);
+}
+
+/* portscan functions */
+static inline int xt_portscan_stealth(const struct tcphdr *th)
+{
+ /*
+ * "Connection refused" replies to our own probes must not be matched.
+ */
+ if(tflg_rstack(th))
+ return 0;
+
+ if(tflg_rst(th) && printk_ratelimit()) {
+ printk(KERN_WARNING PFX "Warning: Pure RST received\n");
+ return 0;
+ }
+
+ /*
+ * -p tcp ! --syn -m conntrack --ctstate INVALID: Looking for non-start
+ * packets that are not associated with any connection -- this will
+ * match most scan types (NULL, XMAS, FIN) and ridiculous flag
+ * combinations (SYN-RST, SYN-FIN, SYN-FIN-RST, FIN-RST, etc.).
+ */
+ return !tflg_syn(th);
+}
+
+static inline int xt_portscan_full(int mark, enum ip_conntrack_info ctstate,
+ int loopback, const struct tcphdr *tcph, int payload_len)
+{
+ if(mark == mark_estab2) {
+ /*
+ * -m connmark --mark $ESTAB2
+ */
+ if(tflg_ack4(tcph) && payload_len == 0)
+ return mark; /* keep mark */
+ else if(tflg_rst(tcph) || tflg_fin(tcph))
+ return mark_grscan;
+ else
+ return mark_valid;
+ } else if(mark == mark_estab1) {
+ /*
+ * -m connmark --mark $ESTAB1
+ */
+ if(tflg_rst(tcph) || tflg_fin(tcph))
+ return mark_cnscan;
+ else if(!loopback && tflg_ack4(tcph) && payload_len == 0)
+ return mark_estab2;
+ else
+ return mark_valid;
+ } else if(mark == mark_synrcv) {
+ /*
+ * -m connmark --mark $SYN
+ */
+ if(loopback && tflg_synack(tcph))
+ return mark; /* keep mark */
+ else if(loopback && tflg_rstack(tcph))
+ return mark_closed;
+ else if(tflg_ack6(tcph))
+ return mark_estab1;
+ else
+ return mark_synscan;
+ } else if(ctstate == IP_CT_NEW && tflg_syn(tcph)) {
+ /*
+ * -p tcp --syn --ctstate NEW
+ */
+ return mark_synrcv;
+ }
+ return mark;
+}
+
+static int xt_portscan_match(const struct sk_buff *skb,
+ const struct net_device *in, const struct net_device *out,
+ const struct xt_match *match, const void *matchinfo, int offset,
+ unsigned int protoff, int *hotdrop)
+{
+ const struct xt_portscan_info *info = matchinfo;
+ enum ip_conntrack_info ctstate;
+ struct nf_conn *ctdata;
+ const struct tcphdr *tcph;
+ struct tcphdr tcph_buf;
+
+ tcph = skb_header_pointer(skb, protoff, sizeof(tcph_buf), &tcph_buf);
+ if(tcph == NULL)
+ return 0;
+
+ /* Check for invalid packets: -m conntrack --ctstate INVALID */
+ if((ctdata = nf_ct_get(skb, &ctstate)) == NULL) {
+ if(info->match_stealth)
+ return xt_portscan_stealth(tcph);
+ /*
+ * If @ctdata is NULL, we cannot match the other scan
+ * types, return.
+ */
+ return 0;
+ }
+
+ /*
+ * If -m portscan was previously applied to this packet, the rules we
+ * simulate must not be run through again. And for speedup, do not call
+ * it either when the connection is already VALID.
+ */
+ if((ctdata->mark & connmark_mask) == mark_valid ||
+ (skb->nfmark & packet_mask) != mark_seen)
+ {
+ unsigned int n;
+ n = xt_portscan_full(ctdata->mark & connmark_mask, ctstate,
+ in == &loopback_dev, tcph,
+ skb->len - protoff - 4 * tcph->doff);
+
+ ctdata->mark = (ctdata->mark & ~connmark_mask) | n;
+ ((struct sk_buff *)skb)->nfmark =
+ (skb->nfmark & ~packet_mask) | mark_seen;
+ }
+
+ return (info->match_syn && ctdata->mark == mark_synscan) ||
+ (info->match_cn && ctdata->mark == mark_cnscan) ||
+ (info->match_gr && ctdata->mark == mark_grscan);
+}
+
+static int xt_portscan_checkentry(const char *tablename, const void *entry,
+ const struct xt_match *match, void *matchinfo,
+#ifdef HAVE_MATCHINFOSIZE
+ unsigned int matchinfosize,
+#endif
+ unsigned int hook_mask)
+{
+ const struct xt_portscan_info *info = matchinfo;
+#ifdef HAVE_MATCHINFOSIZE
+ if(matchinfosize != XT_ALIGN(sizeof(struct xt_portscan_info))) {
+ printk(KERN_WARNING PFX "matchinfosize %u != %Zu\n",
+ matchinfosize,
+ XT_ALIGN(sizeof(struct xt_portscan_info)));
+ return 0;
+ }
+#endif
+ if((info->match_stealth & ~1) || (info->match_syn & ~1) ||
+ (info->match_cn & ~1) || (info->match_gr & ~1)) {
+ printk(KERN_WARNING PFX "Invalid flags\n");
+ return 0;
+ }
+ return 1;
+}
+
+static struct xt_match xt_portscan = {
+ .name = "portscan",
+ .match = xt_portscan_match,
+ .checkentry = xt_portscan_checkentry,
+ .matchsize = sizeof(struct xt_portscan_info),
+ .proto = IPPROTO_TCP,
+ .family = AF_INET,
+ .me = THIS_MODULE,
+};
+
+static int __init xt_portscan_init(void)
+{
+ return xt_register_match(&xt_portscan);
+}
+
+static void __exit xt_portscan_exit(void)
+{
+ xt_unregister_match(&xt_portscan);
+ return;
+}
+
+module_init(xt_portscan_init);
+module_exit(xt_portscan_exit);
+MODULE_AUTHOR("Jan Engelhardt <jengelh@gmx.de>");
+MODULE_DESCRIPTION("netfilter portscan match module");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ipt_portscan");
diff -urN linux-2.6.22-rc3.old/drivers/char/random.c linux-2.6.22-rc3.dev/drivers/char/random.c
--- linux-2.6.22-rc3.old/drivers/char/random.c 2007-05-26 03:55:14.000000000 +0100
+++ linux-2.6.22-rc3.dev/drivers/char/random.c 2007-05-29 11:21:53.000000000 +0100
@@ -1557,6 +1557,8 @@
return seq;
}
+EXPORT_SYMBOL(secure_tcp_sequence_number);
+
/* Generate secure starting point for ephemeral IPV4 transport port search */
u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport)
{

View File

@ -0,0 +1,20 @@
--- linux.old/net/netfilter/Kconfig 2007-05-26 20:05:39.270134976 +0200
+++ linux.dev/net/netfilter/Kconfig 2007-05-26 20:12:44.258526920 +0200
@@ -133,7 +133,7 @@
config NF_CONNTRACK_H323
tristate "H.323 protocol support (EXPERIMENTAL)"
- depends on EXPERIMENTAL && NF_CONNTRACK && (IPV6 || IPV6=n)
+ depends on EXPERIMENTAL && NF_CONNTRACK
help
H.323 is a VoIP signalling protocol from ITU-T. As one of the most
important VoIP protocols, it is widely used by voice hardware and
@@ -381,7 +381,7 @@
config NETFILTER_XT_TARGET_TCPMSS
tristate '"TCPMSS" target support'
- depends on NETFILTER_XTABLES && (IPV6 || IPV6=n)
+ depends on NETFILTER_XTABLES
---help---
This option adds a `TCPMSS' target, which allows you to alter the
MSS value of TCP SYN packets, to control the maximum size for that

View File

@ -0,0 +1,793 @@
diff -urN linux-2.6.21.1.old/include/linux/pkt_sched.h linux-2.6.21.1.dev/include/linux/pkt_sched.h
--- linux-2.6.21.1.old/include/linux/pkt_sched.h 2007-04-27 23:49:26.000000000 +0200
+++ linux-2.6.21.1.dev/include/linux/pkt_sched.h 2007-05-26 20:43:12.530587320 +0200
@@ -146,8 +146,40 @@
*
* The only reason for this is efficiency, it is possible
* to change these parameters in compile time.
+ *
+ * If you need to play with these values use esfq instead.
*/
+/* ESFQ section */
+
+enum
+{
+ /* traditional */
+ TCA_SFQ_HASH_CLASSIC,
+ TCA_SFQ_HASH_DST,
+ TCA_SFQ_HASH_SRC,
+ TCA_SFQ_HASH_FWMARK,
+ /* direct */
+ TCA_SFQ_HASH_DSTDIR,
+ TCA_SFQ_HASH_SRCDIR,
+ TCA_SFQ_HASH_FWMARKDIR,
+ /* conntrack */
+ TCA_SFQ_HASH_CTORIGDST,
+ TCA_SFQ_HASH_CTORIGSRC,
+ TCA_SFQ_HASH_CTREPLDST,
+ TCA_SFQ_HASH_CTREPLSRC,
+};
+
+struct tc_esfq_qopt
+{
+ unsigned quantum; /* Bytes per round allocated to flow */
+ int perturb_period; /* Period of hash perturbation */
+ __u32 limit; /* Maximal packets in queue */
+ unsigned divisor; /* Hash divisor */
+ unsigned flows; /* Maximal number of flows */
+ unsigned hash_kind; /* Hash function to use for flow identification */
+};
+
/* RED section */
enum
diff -urN linux-2.6.21.1.old/net/sched/Kconfig linux-2.6.21.1.dev/net/sched/Kconfig
--- linux-2.6.21.1.old/net/sched/Kconfig 2007-04-27 23:49:26.000000000 +0200
+++ linux-2.6.21.1.dev/net/sched/Kconfig 2007-05-26 20:43:12.572580936 +0200
@@ -133,6 +133,26 @@
To compile this code as a module, choose M here: the
module will be called sch_sfq.
+config NET_SCH_ESFQ
+ tristate "Enhanced Stochastic Fairness Queueing (ESFQ)"
+ ---help---
+ Say Y here if you want to use the Enhanced Stochastic Fairness
+ Queueing (ESFQ) packet scheduling algorithm for some of your network
+ devices or as a leaf discipline for a classful qdisc such as HTB or
+ CBQ (see the top of <file:net/sched/sch_esfq.c> for details and
+ references to the SFQ algorithm).
+
+ This is an enchanced SFQ version which allows you to control some
+ hardcoded values in the SFQ scheduler.
+
+ ESFQ also adds control of the hash function used to identify packet
+ flows. The original SFQ discipline hashes by connection; ESFQ add
+ several other hashing methods, such as by src IP or by dst IP, which
+ can be more fair to users in some networking situations.
+
+ To compile this code as a module, choose M here: the
+ module will be called sch_esfq.
+
config NET_SCH_TEQL
tristate "True Link Equalizer (TEQL)"
---help---
diff -urN linux-2.6.21.1.old/net/sched/Makefile linux-2.6.21.1.dev/net/sched/Makefile
--- linux-2.6.21.1.old/net/sched/Makefile 2007-04-27 23:49:26.000000000 +0200
+++ linux-2.6.21.1.dev/net/sched/Makefile 2007-05-26 20:43:12.577580176 +0200
@@ -23,6 +23,7 @@
obj-$(CONFIG_NET_SCH_INGRESS) += sch_ingress.o
obj-$(CONFIG_NET_SCH_DSMARK) += sch_dsmark.o
obj-$(CONFIG_NET_SCH_SFQ) += sch_sfq.o
+obj-$(CONFIG_NET_SCH_ESFQ) += sch_esfq.o
obj-$(CONFIG_NET_SCH_TBF) += sch_tbf.o
obj-$(CONFIG_NET_SCH_TEQL) += sch_teql.o
obj-$(CONFIG_NET_SCH_PRIO) += sch_prio.o
diff -urN linux-2.6.21.1.old/net/sched/sch_esfq.c linux-2.6.21.1.dev/net/sched/sch_esfq.c
--- linux-2.6.21.1.old/net/sched/sch_esfq.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.21.1.dev/net/sched/sch_esfq.c 2007-05-26 20:43:12.578580024 +0200
@@ -0,0 +1,704 @@
+/*
+ * net/sched/sch_esfq.c Extended Stochastic Fairness Queueing discipline.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
+ *
+ * Changes: Alexander Atanasov, <alex@ssi.bg>
+ * Added dynamic depth,limit,divisor,hash_kind options.
+ * Added dst and src hashes.
+ *
+ * Alexander Clouter, <alex@digriz.org.uk>
+ * Ported ESFQ to Linux 2.6.
+ *
+ * Corey Hickey, <bugfood-c@fatooh.org>
+ * Maintenance of the Linux 2.6 port.
+ * Added fwmark hash (thanks to Robert Kurjata).
+ * Added direct hashing for src, dst, and fwmark.
+ * Added usage of jhash.
+ *
+ */
+
+#include <linux/module.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <linux/bitops.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/jiffies.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <linux/in.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/if_ether.h>
+#include <linux/inet.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/notifier.h>
+#include <linux/init.h>
+#include <net/ip.h>
+#include <linux/ipv6.h>
+#include <net/route.h>
+#include <linux/skbuff.h>
+#include <net/sock.h>
+#include <net/pkt_sched.h>
+#include <linux/jhash.h>
+
+#ifdef CONFIG_NF_CONNTRACK_ENABLED
+#include <net/netfilter/nf_conntrack.h>
+#endif
+
+/* Stochastic Fairness Queuing algorithm.
+ For more comments look at sch_sfq.c.
+ The difference is that you can change limit, depth,
+ hash table size and choose alternate hash types.
+
+ classic: same as in sch_sfq.c
+ dst: destination IP address
+ src: source IP address
+ fwmark: netfilter mark value
+ dst_direct:
+ src_direct:
+ fwmark_direct: direct hashing of the above sources
+ ctorigdst: original destination IP address
+ ctorigsrc: original source IP address
+ ctrepldst: reply destination IP address
+ ctreplsrc: reply source IP
+
+*/
+
+
+/* This type should contain at least SFQ_DEPTH*2 values */
+typedef unsigned int esfq_index;
+
+struct esfq_head
+{
+ esfq_index next;
+ esfq_index prev;
+};
+
+struct esfq_sched_data
+{
+/* Parameters */
+ int perturb_period;
+ unsigned quantum; /* Allotment per round: MUST BE >= MTU */
+ int limit;
+ unsigned depth;
+ unsigned hash_divisor;
+ unsigned hash_kind;
+/* Variables */
+ struct timer_list perturb_timer;
+ int perturbation;
+ esfq_index tail; /* Index of current slot in round */
+ esfq_index max_depth; /* Maximal depth */
+
+ esfq_index *ht; /* Hash table */
+ esfq_index *next; /* Active slots link */
+ short *allot; /* Current allotment per slot */
+ unsigned short *hash; /* Hash value indexed by slots */
+ struct sk_buff_head *qs; /* Slot queue */
+ struct esfq_head *dep; /* Linked list of slots, indexed by depth */
+ unsigned dyn_min; /* For dynamic divisor adjustment; minimum value seen */
+ unsigned dyn_max; /* maximum value seen */
+ unsigned dyn_range; /* saved range */
+};
+
+/* This contains the info we will hash. */
+struct esfq_packet_info
+{
+ u32 proto; /* protocol or port */
+ u32 src; /* source from packet header */
+ u32 dst; /* destination from packet header */
+ u32 ctorigsrc; /* original source from conntrack */
+ u32 ctorigdst; /* original destination from conntrack */
+ u32 ctreplsrc; /* reply source from conntrack */
+ u32 ctrepldst; /* reply destination from conntrack */
+ u32 mark; /* netfilter mark (fwmark) */
+};
+
+/* Hash input values directly into the "nearest" slot, taking into account the
+ * range of input values seen. This is most useful when the hash table is at
+ * least as large as the range of possible values.
+ * Note: this functionality was added before the change to using jhash, and may
+ * no longer be useful. */
+static __inline__ unsigned esfq_hash_direct(struct esfq_sched_data *q, u32 h)
+{
+ /* adjust minimum and maximum */
+ if (h < q->dyn_min || h > q->dyn_max) {
+ q->dyn_min = h < q->dyn_min ? h : q->dyn_min;
+ q->dyn_max = h > q->dyn_max ? h : q->dyn_max;
+
+ /* find new range */
+ if ((q->dyn_range = q->dyn_max - q->dyn_min) >= q->hash_divisor)
+ printk(KERN_WARNING "ESFQ: (direct hash) Input range %u is larger than hash "
+ "table. See ESFQ README for details.\n", q->dyn_range);
+ }
+
+ /* hash input values into slot numbers */
+ if (q->dyn_min == q->dyn_max)
+ return 0; /* only one value seen; avoid division by 0 */
+ else
+ return (h - q->dyn_min) * (q->hash_divisor - 1) / q->dyn_range;
+}
+
+static __inline__ unsigned esfq_jhash_1word(struct esfq_sched_data *q,u32 a)
+{
+ return jhash_1word(a, q->perturbation) & (q->hash_divisor-1);
+}
+
+static __inline__ unsigned esfq_jhash_2words(struct esfq_sched_data *q, u32 a, u32 b)
+{
+ return jhash_2words(a, b, q->perturbation) & (q->hash_divisor-1);
+}
+
+static __inline__ unsigned esfq_jhash_3words(struct esfq_sched_data *q, u32 a, u32 b, u32 c)
+{
+ return jhash_3words(a, b, c, q->perturbation) & (q->hash_divisor-1);
+}
+
+
+static unsigned esfq_hash(struct esfq_sched_data *q, struct sk_buff *skb)
+{
+ struct esfq_packet_info info;
+#ifdef CONFIG_NF_CONNTRACK_ENABLED
+ enum ip_conntrack_info ctinfo;
+ struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
+#endif
+
+ switch (skb->protocol) {
+ case __constant_htons(ETH_P_IP):
+ {
+ struct iphdr *iph = ip_hdr(skb);
+ info.dst = iph->daddr;
+ info.src = iph->saddr;
+ if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) &&
+ (iph->protocol == IPPROTO_TCP ||
+ iph->protocol == IPPROTO_UDP ||
+ iph->protocol == IPPROTO_SCTP ||
+ iph->protocol == IPPROTO_DCCP ||
+ iph->protocol == IPPROTO_ESP))
+ info.proto = *(((u32*)iph) + iph->ihl);
+ else
+ info.proto = iph->protocol;
+ break;
+ }
+ case __constant_htons(ETH_P_IPV6):
+ {
+ struct ipv6hdr *iph = ipv6_hdr(skb);
+ /* Hash ipv6 addresses into a u32. This isn't ideal,
+ * but the code is simple. */
+ info.dst = jhash2(iph->daddr.s6_addr32, 4, q->perturbation);
+ info.src = jhash2(iph->saddr.s6_addr32, 4, q->perturbation);
+ if (iph->nexthdr == IPPROTO_TCP ||
+ iph->nexthdr == IPPROTO_UDP ||
+ iph->nexthdr == IPPROTO_SCTP ||
+ iph->nexthdr == IPPROTO_DCCP ||
+ iph->nexthdr == IPPROTO_ESP)
+ info.proto = *(u32*)&iph[1];
+ else
+ info.proto = iph->nexthdr;
+ break;
+ }
+ default:
+ info.dst = (u32)(unsigned long)skb->dst;
+ info.src = (u32)(unsigned long)skb->sk;
+ info.proto = skb->protocol;
+ }
+
+ info.mark = skb->mark;
+
+#ifdef CONFIG_NF_CONNTRACK_ENABLED
+ /* defaults if there is no conntrack info */
+ info.ctorigsrc = info.src;
+ info.ctorigdst = info.dst;
+ info.ctreplsrc = info.dst;
+ info.ctrepldst = info.src;
+ /* collect conntrack info */
+ if (ct && ct != &nf_conntrack_untracked) {
+ if (skb->protocol == __constant_htons(ETH_P_IP)) {
+ info.ctorigsrc = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip;
+ info.ctorigdst = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip;
+ info.ctreplsrc = ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip;
+ info.ctrepldst = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip;
+ }
+ else if (skb->protocol == __constant_htons(ETH_P_IPV6)) {
+ /* Again, hash ipv6 addresses into a single u32. */
+ info.ctorigsrc = jhash2(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip6, 4, q->perturbation);
+ info.ctorigdst = jhash2(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip6, 4, q->perturbation);
+ info.ctreplsrc = jhash2(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip6, 4, q->perturbation);
+ info.ctrepldst = jhash2(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip6, 4, q->perturbation);
+ }
+
+ }
+#endif
+
+ switch(q->hash_kind)
+ {
+ case TCA_SFQ_HASH_CLASSIC:
+ return esfq_jhash_3words(q, info.dst, info.src, info.proto);
+ case TCA_SFQ_HASH_DST:
+ return esfq_jhash_1word(q, info.dst);
+ case TCA_SFQ_HASH_DSTDIR:
+ return esfq_hash_direct(q, ntohl(info.dst));
+ case TCA_SFQ_HASH_SRC:
+ return esfq_jhash_1word(q, info.src);
+ case TCA_SFQ_HASH_SRCDIR:
+ return esfq_hash_direct(q, ntohl(info.src));
+ case TCA_SFQ_HASH_FWMARK:
+ return esfq_jhash_1word(q, info.mark);
+ case TCA_SFQ_HASH_FWMARKDIR:
+ return esfq_hash_direct(q, info.mark);
+#ifdef CONFIG_NF_CONNTRACK_ENABLED
+ case TCA_SFQ_HASH_CTORIGDST:
+ return esfq_jhash_1word(q, info.ctorigdst);
+ case TCA_SFQ_HASH_CTORIGSRC:
+ return esfq_jhash_1word(q, info.ctorigsrc);
+ case TCA_SFQ_HASH_CTREPLDST:
+ return esfq_jhash_1word(q, info.ctrepldst);
+ case TCA_SFQ_HASH_CTREPLSRC:
+ return esfq_jhash_1word(q, info.ctreplsrc);
+#endif
+ default:
+ if (net_ratelimit())
+ printk(KERN_WARNING "ESFQ: Unknown hash method. Falling back to classic.\n");
+ }
+ return esfq_jhash_3words(q, info.dst, info.src, info.proto);
+}
+
+static inline void esfq_link(struct esfq_sched_data *q, esfq_index x)
+{
+ esfq_index p, n;
+ int d = q->qs[x].qlen + q->depth;
+
+ p = d;
+ n = q->dep[d].next;
+ q->dep[x].next = n;
+ q->dep[x].prev = p;
+ q->dep[p].next = q->dep[n].prev = x;
+}
+
+static inline void esfq_dec(struct esfq_sched_data *q, esfq_index x)
+{
+ esfq_index p, n;
+
+ n = q->dep[x].next;
+ p = q->dep[x].prev;
+ q->dep[p].next = n;
+ q->dep[n].prev = p;
+
+ if (n == p && q->max_depth == q->qs[x].qlen + 1)
+ q->max_depth--;
+
+ esfq_link(q, x);
+}
+
+static inline void esfq_inc(struct esfq_sched_data *q, esfq_index x)
+{
+ esfq_index p, n;
+ int d;
+
+ n = q->dep[x].next;
+ p = q->dep[x].prev;
+ q->dep[p].next = n;
+ q->dep[n].prev = p;
+ d = q->qs[x].qlen;
+ if (q->max_depth < d)
+ q->max_depth = d;
+
+ esfq_link(q, x);
+}
+
+static unsigned int esfq_drop(struct Qdisc *sch)
+{
+ struct esfq_sched_data *q = qdisc_priv(sch);
+ esfq_index d = q->max_depth;
+ struct sk_buff *skb;
+ unsigned int len;
+
+ /* Queue is full! Find the longest slot and
+ drop a packet from it */
+
+ if (d > 1) {
+ esfq_index x = q->dep[d+q->depth].next;
+ skb = q->qs[x].prev;
+ len = skb->len;
+ __skb_unlink(skb, &q->qs[x]);
+ kfree_skb(skb);
+ esfq_dec(q, x);
+ sch->q.qlen--;
+ sch->qstats.drops++;
+ sch->qstats.backlog -= len;
+ return len;
+ }
+
+ if (d == 1) {
+ /* It is difficult to believe, but ALL THE SLOTS HAVE LENGTH 1. */
+ d = q->next[q->tail];
+ q->next[q->tail] = q->next[d];
+ q->allot[q->next[d]] += q->quantum;
+ skb = q->qs[d].prev;
+ len = skb->len;
+ __skb_unlink(skb, &q->qs[d]);
+ kfree_skb(skb);
+ esfq_dec(q, d);
+ sch->q.qlen--;
+ q->ht[q->hash[d]] = q->depth;
+ sch->qstats.drops++;
+ sch->qstats.backlog -= len;
+ return len;
+ }
+
+ return 0;
+}
+
+static int
+esfq_enqueue(struct sk_buff *skb, struct Qdisc* sch)
+{
+ struct esfq_sched_data *q = qdisc_priv(sch);
+ unsigned hash = esfq_hash(q, skb);
+ unsigned depth = q->depth;
+ esfq_index x;
+
+ x = q->ht[hash];
+ if (x == depth) {
+ q->ht[hash] = x = q->dep[depth].next;
+ q->hash[x] = hash;
+ }
+ sch->qstats.backlog += skb->len;
+ __skb_queue_tail(&q->qs[x], skb);
+ esfq_inc(q, x);
+ if (q->qs[x].qlen == 1) { /* The flow is new */
+ if (q->tail == depth) { /* It is the first flow */
+ q->tail = x;
+ q->next[x] = x;
+ q->allot[x] = q->quantum;
+ } else {
+ q->next[x] = q->next[q->tail];
+ q->next[q->tail] = x;
+ q->tail = x;
+ }
+ }
+ if (++sch->q.qlen < q->limit-1) {
+ sch->bstats.bytes += skb->len;
+ sch->bstats.packets++;
+ return 0;
+ }
+
+ esfq_drop(sch);
+ return NET_XMIT_CN;
+}
+
+static int
+esfq_requeue(struct sk_buff *skb, struct Qdisc* sch)
+{
+ struct esfq_sched_data *q = qdisc_priv(sch);
+ unsigned hash = esfq_hash(q, skb);
+ unsigned depth = q->depth;
+ esfq_index x;
+
+ x = q->ht[hash];
+ if (x == depth) {
+ q->ht[hash] = x = q->dep[depth].next;
+ q->hash[x] = hash;
+ }
+ sch->qstats.backlog += skb->len;
+ __skb_queue_head(&q->qs[x], skb);
+ esfq_inc(q, x);
+ if (q->qs[x].qlen == 1) { /* The flow is new */
+ if (q->tail == depth) { /* It is the first flow */
+ q->tail = x;
+ q->next[x] = x;
+ q->allot[x] = q->quantum;
+ } else {
+ q->next[x] = q->next[q->tail];
+ q->next[q->tail] = x;
+ q->tail = x;
+ }
+ }
+ if (++sch->q.qlen < q->limit - 1) {
+ sch->qstats.requeues++;
+ return 0;
+ }
+
+ sch->qstats.drops++;
+ esfq_drop(sch);
+ return NET_XMIT_CN;
+}
+
+
+
+
+static struct sk_buff *
+esfq_dequeue(struct Qdisc* sch)
+{
+ struct esfq_sched_data *q = qdisc_priv(sch);
+ struct sk_buff *skb;
+ unsigned depth = q->depth;
+ esfq_index a, old_a;
+
+ /* No active slots */
+ if (q->tail == depth)
+ return NULL;
+
+ a = old_a = q->next[q->tail];
+
+ /* Grab packet */
+ skb = __skb_dequeue(&q->qs[a]);
+ esfq_dec(q, a);
+ sch->q.qlen--;
+ sch->qstats.backlog -= skb->len;
+
+ /* Is the slot empty? */
+ if (q->qs[a].qlen == 0) {
+ q->ht[q->hash[a]] = depth;
+ a = q->next[a];
+ if (a == old_a) {
+ q->tail = depth;
+ return skb;
+ }
+ q->next[q->tail] = a;
+ q->allot[a] += q->quantum;
+ } else if ((q->allot[a] -= skb->len) <= 0) {
+ q->tail = a;
+ a = q->next[a];
+ q->allot[a] += q->quantum;
+ }
+
+ return skb;
+}
+
+static void
+esfq_reset(struct Qdisc* sch)
+{
+ struct sk_buff *skb;
+
+ while ((skb = esfq_dequeue(sch)) != NULL)
+ kfree_skb(skb);
+}
+
+static void esfq_perturbation(unsigned long arg)
+{
+ struct Qdisc *sch = (struct Qdisc*)arg;
+ struct esfq_sched_data *q = qdisc_priv(sch);
+
+ q->perturbation = net_random()&0x1F;
+
+ if (q->perturb_period) {
+ q->perturb_timer.expires = jiffies + q->perturb_period;
+ add_timer(&q->perturb_timer);
+ }
+}
+
+static int esfq_change(struct Qdisc *sch, struct rtattr *opt)
+{
+ struct esfq_sched_data *q = qdisc_priv(sch);
+ struct tc_esfq_qopt *ctl = RTA_DATA(opt);
+ int old_perturb = q->perturb_period;
+
+ if (opt->rta_len < RTA_LENGTH(sizeof(*ctl)))
+ return -EINVAL;
+
+ sch_tree_lock(sch);
+ q->quantum = ctl->quantum ? : psched_mtu(sch->dev);
+ q->perturb_period = ctl->perturb_period*HZ;
+// q->hash_divisor = ctl->divisor;
+// q->tail = q->limit = q->depth = ctl->flows;
+
+ if (ctl->limit)
+ q->limit = min_t(u32, ctl->limit, q->depth);
+
+ if (ctl->hash_kind) {
+ q->hash_kind = ctl->hash_kind;
+ if (q->hash_kind != TCA_SFQ_HASH_CLASSIC)
+ q->perturb_period = 0;
+ }
+
+ // is sch_tree_lock enough to do this ?
+ while (sch->q.qlen >= q->limit-1)
+ esfq_drop(sch);
+
+ if (old_perturb)
+ del_timer(&q->perturb_timer);
+ if (q->perturb_period) {
+ q->perturb_timer.expires = jiffies + q->perturb_period;
+ add_timer(&q->perturb_timer);
+ } else {
+ q->perturbation = 0;
+ }
+ sch_tree_unlock(sch);
+ return 0;
+}
+
+static int esfq_init(struct Qdisc *sch, struct rtattr *opt)
+{
+ struct esfq_sched_data *q = qdisc_priv(sch);
+ struct tc_esfq_qopt *ctl;
+ esfq_index p = ~0U/2;
+ int i;
+
+ if (opt && opt->rta_len < RTA_LENGTH(sizeof(*ctl)))
+ return -EINVAL;
+
+ init_timer(&q->perturb_timer);
+ q->perturb_timer.data = (unsigned long)sch;
+ q->perturb_timer.function = esfq_perturbation;
+ q->perturbation = 0;
+ q->hash_kind = TCA_SFQ_HASH_CLASSIC;
+ q->max_depth = 0;
+ q->dyn_min = ~0U; /* maximum value for this type */
+ q->dyn_max = 0; /* dyn_min/dyn_max will be set properly upon first packet */
+ if (opt == NULL) {
+ q->quantum = psched_mtu(sch->dev);
+ q->perturb_period = 0;
+ q->hash_divisor = 1024;
+ q->tail = q->limit = q->depth = 128;
+
+ } else {
+ ctl = RTA_DATA(opt);
+ q->quantum = ctl->quantum ? : psched_mtu(sch->dev);
+ q->perturb_period = ctl->perturb_period*HZ;
+ q->hash_divisor = ctl->divisor ? : 1024;
+ q->tail = q->limit = q->depth = ctl->flows ? : 128;
+
+ if ( q->depth > p - 1 )
+ return -EINVAL;
+
+ if (ctl->limit)
+ q->limit = min_t(u32, ctl->limit, q->depth);
+
+ if (ctl->hash_kind) {
+ q->hash_kind = ctl->hash_kind;
+ }
+
+ if (q->perturb_period) {
+ q->perturb_timer.expires = jiffies + q->perturb_period;
+ add_timer(&q->perturb_timer);
+ }
+ }
+
+ q->ht = kmalloc(q->hash_divisor*sizeof(esfq_index), GFP_KERNEL);
+ if (!q->ht)
+ goto err_case;
+
+ q->dep = kmalloc((1+q->depth*2)*sizeof(struct esfq_head), GFP_KERNEL);
+ if (!q->dep)
+ goto err_case;
+ q->next = kmalloc(q->depth*sizeof(esfq_index), GFP_KERNEL);
+ if (!q->next)
+ goto err_case;
+
+ q->allot = kmalloc(q->depth*sizeof(short), GFP_KERNEL);
+ if (!q->allot)
+ goto err_case;
+ q->hash = kmalloc(q->depth*sizeof(unsigned short), GFP_KERNEL);
+ if (!q->hash)
+ goto err_case;
+ q->qs = kmalloc(q->depth*sizeof(struct sk_buff_head), GFP_KERNEL);
+ if (!q->qs)
+ goto err_case;
+
+ for (i=0; i< q->hash_divisor; i++)
+ q->ht[i] = q->depth;
+ for (i=0; i<q->depth; i++) {
+ skb_queue_head_init(&q->qs[i]);
+ q->dep[i+q->depth].next = i+q->depth;
+ q->dep[i+q->depth].prev = i+q->depth;
+ }
+
+ for (i=0; i<q->depth; i++)
+ esfq_link(q, i);
+ return 0;
+err_case:
+ del_timer(&q->perturb_timer);
+ if (q->ht)
+ kfree(q->ht);
+ if (q->dep)
+ kfree(q->dep);
+ if (q->next)
+ kfree(q->next);
+ if (q->allot)
+ kfree(q->allot);
+ if (q->hash)
+ kfree(q->hash);
+ if (q->qs)
+ kfree(q->qs);
+ return -ENOBUFS;
+}
+
+static void esfq_destroy(struct Qdisc *sch)
+{
+ struct esfq_sched_data *q = qdisc_priv(sch);
+ del_timer(&q->perturb_timer);
+ if(q->ht)
+ kfree(q->ht);
+ if(q->dep)
+ kfree(q->dep);
+ if(q->next)
+ kfree(q->next);
+ if(q->allot)
+ kfree(q->allot);
+ if(q->hash)
+ kfree(q->hash);
+ if(q->qs)
+ kfree(q->qs);
+}
+
+static int esfq_dump(struct Qdisc *sch, struct sk_buff *skb)
+{
+ struct esfq_sched_data *q = qdisc_priv(sch);
+ unsigned char *b = skb->tail;
+ struct tc_esfq_qopt opt;
+
+ opt.quantum = q->quantum;
+ opt.perturb_period = q->perturb_period/HZ;
+
+ opt.limit = q->limit;
+ opt.divisor = q->hash_divisor;
+ opt.flows = q->depth;
+ opt.hash_kind = q->hash_kind;
+
+ RTA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);
+
+ return skb->len;
+
+rtattr_failure:
+ skb_trim(skb, b - skb->data);
+ return -1;
+}
+
+static struct Qdisc_ops esfq_qdisc_ops =
+{
+ .next = NULL,
+ .cl_ops = NULL,
+ .id = "esfq",
+ .priv_size = sizeof(struct esfq_sched_data),
+ .enqueue = esfq_enqueue,
+ .dequeue = esfq_dequeue,
+ .requeue = esfq_requeue,
+ .drop = esfq_drop,
+ .init = esfq_init,
+ .reset = esfq_reset,
+ .destroy = esfq_destroy,
+ .change = NULL, /* esfq_change - needs more work */
+ .dump = esfq_dump,
+ .owner = THIS_MODULE,
+};
+
+static int __init esfq_module_init(void)
+{
+ return register_qdisc(&esfq_qdisc_ops);
+}
+static void __exit esfq_module_exit(void)
+{
+ unregister_qdisc(&esfq_qdisc_ops);
+}
+module_init(esfq_module_init)
+module_exit(esfq_module_exit)
+MODULE_LICENSE("GPL");

View File

@ -0,0 +1,339 @@
diff -urN linux-2.6.21.1.old/include/linux/rtnetlink.h linux-2.6.21.1.dev/include/linux/rtnetlink.h
--- linux-2.6.21.1.old/include/linux/rtnetlink.h 2007-04-27 23:49:26.000000000 +0200
+++ linux-2.6.21.1.dev/include/linux/rtnetlink.h 2007-05-26 20:46:11.883321560 +0200
@@ -293,6 +293,8 @@
#define RTNH_F_DEAD 1 /* Nexthop is dead (used by multipath) */
#define RTNH_F_PERVASIVE 2 /* Do recursive gateway lookup */
#define RTNH_F_ONLINK 4 /* Gateway is forced on link */
+#define RTNH_F_SUSPECT 8 /* We don't know the real state */
+#define RTNH_F_BADSTATE (RTNH_F_DEAD | RTNH_F_SUSPECT)
/* Macros to handle hexthops */
diff -urN linux-2.6.21.1.old/include/net/flow.h linux-2.6.21.1.dev/include/net/flow.h
--- linux-2.6.21.1.old/include/net/flow.h 2007-04-27 23:49:26.000000000 +0200
+++ linux-2.6.21.1.dev/include/net/flow.h 2007-05-26 20:46:11.922315632 +0200
@@ -19,6 +19,8 @@
struct {
__be32 daddr;
__be32 saddr;
+ __u32 lsrc;
+ __u32 gw;
__u8 tos;
__u8 scope;
} ip4_u;
@@ -43,6 +45,8 @@
#define fl6_flowlabel nl_u.ip6_u.flowlabel
#define fl4_dst nl_u.ip4_u.daddr
#define fl4_src nl_u.ip4_u.saddr
+#define fl4_lsrc nl_u.ip4_u.lsrc
+#define fl4_gw nl_u.ip4_u.gw
#define fl4_tos nl_u.ip4_u.tos
#define fl4_scope nl_u.ip4_u.scope
diff -urN linux-2.6.21.1.old/net/ipv4/route.c linux-2.6.21.1.dev/net/ipv4/route.c
--- linux-2.6.21.1.old/net/ipv4/route.c 2007-04-27 23:49:26.000000000 +0200
+++ linux-2.6.21.1.dev/net/ipv4/route.c 2007-05-26 20:46:11.967308792 +0200
@@ -1208,6 +1208,7 @@
/* Gateway is different ... */
rt->rt_gateway = new_gw;
+ if (rt->fl.fl4_gw) rt->fl.fl4_gw = new_gw;
/* Redirect received -> path was valid */
dst_confirm(&rth->u.dst);
@@ -1643,6 +1644,7 @@
rth->fl.fl4_tos = tos;
rth->fl.mark = skb->mark;
rth->fl.fl4_src = saddr;
+ rth->fl.fl4_lsrc = 0;
rth->rt_src = saddr;
#ifdef CONFIG_NET_CLS_ROUTE
rth->u.dst.tclassid = itag;
@@ -1653,6 +1655,7 @@
dev_hold(rth->u.dst.dev);
rth->idev = in_dev_get(rth->u.dst.dev);
rth->fl.oif = 0;
+ rth->fl.fl4_gw = 0;
rth->rt_gateway = daddr;
rth->rt_spec_dst= spec_dst;
rth->rt_type = RTN_MULTICAST;
@@ -1716,7 +1719,7 @@
static inline int __mkroute_input(struct sk_buff *skb,
struct fib_result* res,
struct in_device *in_dev,
- __be32 daddr, __be32 saddr, u32 tos,
+ __be32 daddr, __be32 saddr, u32 tos, u32 lsrc,
struct rtable **result)
{
@@ -1751,6 +1754,7 @@
flags |= RTCF_DIRECTSRC;
if (out_dev == in_dev && err && !(flags & (RTCF_NAT | RTCF_MASQ)) &&
+ !lsrc &&
(IN_DEV_SHARED_MEDIA(out_dev) ||
inet_addr_onlink(out_dev, saddr, FIB_RES_GW(*res))))
flags |= RTCF_DOREDIRECT;
@@ -1788,6 +1792,7 @@
rth->fl.mark = skb->mark;
rth->fl.fl4_src = saddr;
rth->rt_src = saddr;
+ rth->fl.fl4_lsrc = lsrc;
rth->rt_gateway = daddr;
rth->rt_iif =
rth->fl.iif = in_dev->dev->ifindex;
@@ -1795,6 +1800,7 @@
dev_hold(rth->u.dst.dev);
rth->idev = in_dev_get(rth->u.dst.dev);
rth->fl.oif = 0;
+ rth->fl.fl4_gw = 0;
rth->rt_spec_dst= spec_dst;
rth->u.dst.input = ip_forward;
@@ -1816,19 +1822,21 @@
struct fib_result* res,
const struct flowi *fl,
struct in_device *in_dev,
- __be32 daddr, __be32 saddr, u32 tos)
+ __be32 daddr, __be32 saddr, u32 tos,
+ u32 lsrc)
{
struct rtable* rth = NULL;
int err;
unsigned hash;
+ fib_select_default(fl, res);
#ifdef CONFIG_IP_ROUTE_MULTIPATH
- if (res->fi && res->fi->fib_nhs > 1 && fl->oif == 0)
+ if (res->fi && res->fi->fib_nhs > 1)
fib_select_multipath(fl, res);
#endif
/* create a routing cache entry */
- err = __mkroute_input(skb, res, in_dev, daddr, saddr, tos, &rth);
+ err = __mkroute_input(skb, res, in_dev, daddr, saddr, tos, lsrc, &rth);
if (err)
return err;
@@ -1841,7 +1849,8 @@
struct fib_result* res,
const struct flowi *fl,
struct in_device *in_dev,
- __be32 daddr, __be32 saddr, u32 tos)
+ __be32 daddr, __be32 saddr, u32 tos,
+ u32 lsrc)
{
#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
struct rtable* rth = NULL, *rtres;
@@ -1857,7 +1866,7 @@
/* distinguish between multipath and singlepath */
if (hopcount < 2)
return ip_mkroute_input_def(skb, res, fl, in_dev, daddr,
- saddr, tos);
+ saddr, tos, 0);
/* add all alternatives to the routing cache */
for (hop = 0; hop < hopcount; hop++) {
@@ -1869,7 +1878,7 @@
/* create a routing cache entry */
err = __mkroute_input(skb, res, in_dev, daddr, saddr, tos,
- &rth);
+ 0, &rth);
if (err)
return err;
@@ -1889,7 +1898,7 @@
skb->dst = &rtres->u.dst;
return err;
#else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
- return ip_mkroute_input_def(skb, res, fl, in_dev, daddr, saddr, tos);
+ return ip_mkroute_input_def(skb, res, fl, in_dev, daddr, saddr, tos, lsrc);
#endif /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
}
@@ -1905,18 +1914,18 @@
*/
static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
- u8 tos, struct net_device *dev)
+ u8 tos, struct net_device *dev, u32 lsrc)
{
struct fib_result res;
struct in_device *in_dev = in_dev_get(dev);
struct flowi fl = { .nl_u = { .ip4_u =
{ .daddr = daddr,
- .saddr = saddr,
+ .saddr = lsrc ? : saddr,
.tos = tos,
.scope = RT_SCOPE_UNIVERSE,
} },
.mark = skb->mark,
- .iif = dev->ifindex };
+ .iif = lsrc? loopback_dev.ifindex : dev->ifindex };
unsigned flags = 0;
u32 itag = 0;
struct rtable * rth;
@@ -1949,6 +1958,12 @@
if (BADCLASS(daddr) || ZERONET(daddr) || LOOPBACK(daddr))
goto martian_destination;
+ if (lsrc) {
+ if (MULTICAST(lsrc) || BADCLASS(lsrc) ||
+ ZERONET(lsrc) || LOOPBACK(lsrc))
+ goto e_inval;
+ }
+
/*
* Now we are ready to route packet.
*/
@@ -1958,6 +1973,10 @@
goto no_route;
}
free_res = 1;
+ if (lsrc && res.type != RTN_UNICAST && res.type != RTN_NAT)
+ goto e_inval;
+ fl.iif = dev->ifindex;
+ fl.fl4_src = saddr;
RT_CACHE_STAT_INC(in_slow_tot);
@@ -1982,7 +2001,7 @@
if (res.type != RTN_UNICAST)
goto martian_destination;
- err = ip_mkroute_input(skb, &res, &fl, in_dev, daddr, saddr, tos);
+ err = ip_mkroute_input(skb, &res, &fl, in_dev, daddr, saddr, tos, lsrc);
if (err == -ENOBUFS)
goto e_nobufs;
if (err == -EINVAL)
@@ -1997,6 +2016,8 @@
brd_input:
if (skb->protocol != htons(ETH_P_IP))
goto e_inval;
+ if (lsrc)
+ goto e_inval;
if (ZERONET(saddr))
spec_dst = inet_select_addr(dev, 0, RT_SCOPE_LINK);
@@ -2037,6 +2058,7 @@
rth->u.dst.dev = &loopback_dev;
dev_hold(rth->u.dst.dev);
rth->idev = in_dev_get(rth->u.dst.dev);
+ rth->fl.fl4_gw = 0;
rth->rt_gateway = daddr;
rth->rt_spec_dst= spec_dst;
rth->u.dst.input= ip_local_deliver;
@@ -2086,8 +2108,9 @@
goto e_inval;
}
-int ip_route_input(struct sk_buff *skb, __be32 daddr, __be32 saddr,
- u8 tos, struct net_device *dev)
+static inline int
+ip_route_input_cached(struct sk_buff *skb, __be32 daddr, __be32 saddr,
+ u8 tos, struct net_device *dev, u32 lsrc)
{
struct rtable * rth;
unsigned hash;
@@ -2102,6 +2125,7 @@
if (rth->fl.fl4_dst == daddr &&
rth->fl.fl4_src == saddr &&
rth->fl.iif == iif &&
+ rth->fl.fl4_lsrc == lsrc &&
rth->fl.oif == 0 &&
rth->fl.mark == skb->mark &&
rth->fl.fl4_tos == tos) {
@@ -2148,7 +2172,19 @@
rcu_read_unlock();
return -EINVAL;
}
- return ip_route_input_slow(skb, daddr, saddr, tos, dev);
+ return ip_route_input_slow(skb, daddr, saddr, tos, dev, lsrc);
+}
+
+int ip_route_input(struct sk_buff *skb, u32 daddr, u32 saddr,
+ u8 tos, struct net_device *dev)
+{
+ return ip_route_input_cached(skb, daddr, saddr, tos, dev, 0);
+}
+
+int ip_route_input_lookup(struct sk_buff *skb, u32 daddr, u32 saddr,
+ u8 tos, struct net_device *dev, u32 lsrc)
+{
+ return ip_route_input_cached(skb, daddr, saddr, tos, dev, lsrc);
}
static inline int __mkroute_output(struct rtable **result,
@@ -2227,6 +2263,7 @@
rth->fl.fl4_tos = tos;
rth->fl.fl4_src = oldflp->fl4_src;
rth->fl.oif = oldflp->oif;
+ rth->fl.fl4_gw = oldflp->fl4_gw;
rth->fl.mark = oldflp->mark;
rth->rt_dst = fl->fl4_dst;
rth->rt_src = fl->fl4_src;
@@ -2367,6 +2404,7 @@
struct flowi fl = { .nl_u = { .ip4_u =
{ .daddr = oldflp->fl4_dst,
.saddr = oldflp->fl4_src,
+ .gw = oldflp->fl4_gw,
.tos = tos & IPTOS_RT_MASK,
.scope = ((tos & RTO_ONLINK) ?
RT_SCOPE_LINK :
@@ -2470,6 +2508,7 @@
dev_out = &loopback_dev;
dev_hold(dev_out);
fl.oif = loopback_dev.ifindex;
+ fl.fl4_gw = 0;
res.type = RTN_LOCAL;
flags |= RTCF_LOCAL;
goto make_route;
@@ -2477,7 +2516,7 @@
if (fib_lookup(&fl, &res)) {
res.fi = NULL;
- if (oldflp->oif) {
+ if (oldflp->oif && dev_out->flags & IFF_UP) {
/* Apparently, routing tables are wrong. Assume,
that the destination is on link.
@@ -2517,6 +2556,7 @@
dev_out = &loopback_dev;
dev_hold(dev_out);
fl.oif = dev_out->ifindex;
+ fl.fl4_gw = 0;
if (res.fi)
fib_info_put(res.fi);
res.fi = NULL;
@@ -2524,13 +2564,12 @@
goto make_route;
}
+ if (res.type == RTN_UNICAST)
+ fib_select_default(&fl, &res);
#ifdef CONFIG_IP_ROUTE_MULTIPATH
- if (res.fi->fib_nhs > 1 && fl.oif == 0)
+ if (res.fi->fib_nhs > 1)
fib_select_multipath(&fl, &res);
- else
#endif
- if (!res.prefixlen && res.type == RTN_UNICAST && !fl.oif)
- fib_select_default(&fl, &res);
if (!fl.fl4_src)
fl.fl4_src = FIB_RES_PREFSRC(res);
@@ -2567,6 +2606,7 @@
rth->fl.fl4_src == flp->fl4_src &&
rth->fl.iif == 0 &&
rth->fl.oif == flp->oif &&
+ rth->fl.fl4_gw == flp->fl4_gw &&
rth->fl.mark == flp->mark &&
!((rth->fl.fl4_tos ^ flp->fl4_tos) &
(IPTOS_RT_MASK | RTO_ONLINK))) {
@@ -3271,3 +3311,4 @@
EXPORT_SYMBOL(__ip_select_ident);
EXPORT_SYMBOL(ip_route_input);
EXPORT_SYMBOL(ip_route_output_key);
+EXPORT_SYMBOL(ip_route_input_lookup);

View File

@ -0,0 +1,13 @@
diff -urN linux-2.6.21.1.old/arch/mips/Makefile linux-2.6.21.1.dev/arch/mips/Makefile
--- linux-2.6.21.1.old/arch/mips/Makefile 2007-04-27 23:49:26.000000000 +0200
+++ linux-2.6.21.1.dev/arch/mips/Makefile 2007-05-26 20:49:09.358341256 +0200
@@ -589,6 +589,9 @@
core-$(CONFIG_TOSHIBA_RBTX4938) += arch/mips/tx4938/common/
load-$(CONFIG_TOSHIBA_RBTX4938) += 0xffffffff80100000
+# temporary until string.h is fixed
+cflags-y += -ffreestanding
+
cflags-y += -Iinclude/asm-mips/mach-generic
drivers-$(CONFIG_PCI) += arch/mips/pci/

View File

@ -0,0 +1,58 @@
diff -urN linux-2.6.21.1.old/fs/jffs2/build.c linux-2.6.21.1.dev/fs/jffs2/build.c
--- linux-2.6.21.1.old/fs/jffs2/build.c 2007-04-27 23:49:26.000000000 +0200
+++ linux-2.6.21.1.dev/fs/jffs2/build.c 2007-05-26 20:52:04.425726968 +0200
@@ -105,6 +105,17 @@
dbg_fsbuild("scanned flash completely\n");
jffs2_dbg_dump_block_lists_nolock(c);
+ if (c->flags & (1 << 7)) {
+ printk("%s(): unlocking the mtd device... ", __func__);
+ if (c->mtd->unlock)
+ c->mtd->unlock(c->mtd, 0, c->mtd->size);
+ printk("done.\n");
+
+ printk("%s(): erasing all blocks after the end marker... ", __func__);
+ jffs2_erase_pending_blocks(c, -1);
+ printk("done.\n");
+ }
+
dbg_fsbuild("pass 1 starting\n");
c->flags |= JFFS2_SB_FLAG_BUILDING;
/* Now scan the directory tree, increasing nlink according to every dirent found. */
diff -urN linux-2.6.21.1.old/fs/jffs2/scan.c linux-2.6.21.1.dev/fs/jffs2/scan.c
--- linux-2.6.21.1.old/fs/jffs2/scan.c 2007-04-27 23:49:26.000000000 +0200
+++ linux-2.6.21.1.dev/fs/jffs2/scan.c 2007-05-26 20:52:04.491716936 +0200
@@ -142,9 +142,12 @@
/* reset summary info for next eraseblock scan */
jffs2_sum_reset_collected(s);
-
- ret = jffs2_scan_eraseblock(c, jeb, buf_size?flashbuf:(flashbuf+jeb->offset),
- buf_size, s);
+
+ if (c->flags & (1 << 7))
+ ret = BLK_STATE_ALLFF;
+ else
+ ret = jffs2_scan_eraseblock(c, jeb, buf_size?flashbuf:(flashbuf+jeb->offset),
+ buf_size, s);
if (ret < 0)
goto out;
@@ -545,6 +548,17 @@
return err;
}
+ if ((buf[0] == 0xde) &&
+ (buf[1] == 0xad) &&
+ (buf[2] == 0xc0) &&
+ (buf[3] == 0xde)) {
+ /* end of filesystem. erase everything after this point */
+ printk("%s(): End of filesystem marker found at 0x%x\n", __func__, jeb->offset);
+ c->flags |= (1 << 7);
+
+ return BLK_STATE_ALLFF;
+ }
+
/* We temporarily use 'ofs' as a pointer into the buffer/jeb */
ofs = 0;

View File

@ -0,0 +1,10 @@
diff -urN linux-2.6.21.1.old/include/asm-powerpc/segment.h linux-2.6.21.1.dev/include/asm-powerpc/segment.h
--- linux-2.6.21.1.old/include/asm-powerpc/segment.h 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.21.1.dev/include/asm-powerpc/segment.h 2007-05-26 20:55:12.738099136 +0200
@@ -0,0 +1,6 @@
+#ifndef _ASM_SEGMENT_H
+#define _ASM_SEGMENT_H
+
+/* Only here because we have some old header files that expect it.. */
+
+#endif /* _ASM_SEGMENT_H */

View File

@ -0,0 +1,25 @@
diff -urN linux-2.6.21.1.old/drivers/net/r8169.c linux-2.6.21.1.dev/drivers/net/r8169.c
--- linux-2.6.21.1.old/drivers/net/r8169.c 2007-04-27 23:49:26.000000000 +0200
+++ linux-2.6.21.1.dev/drivers/net/r8169.c 2007-05-26 20:58:17.370030816 +0200
@@ -494,7 +494,7 @@
#endif
static const u16 rtl8169_intr_mask =
- SYSErr | LinkChg | RxOverflow | RxFIFOOver | TxErr | TxOK | RxErr | RxOK;
+ LinkChg | RxOverflow | RxFIFOOver | TxErr | TxOK | RxErr | RxOK;
static const u16 rtl8169_napi_event =
RxOK | RxOverflow | RxFIFOOver | TxOK | TxErr;
static const unsigned int rtl8169_rx_config =
@@ -2640,10 +2640,12 @@
if (!(status & rtl8169_intr_mask))
break;
+#if 0
if (unlikely(status & SYSErr)) {
rtl8169_pcierr_interrupt(dev);
break;
}
+#endif
if (status & LinkChg)
rtl8169_check_link_status(dev, tp, ioaddr);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,48 @@
diff -urN linux-2.6.21.1.old/include/linux/time.h linux-2.6.21.1.dev/include/linux/time.h
--- linux-2.6.21.1.old/include/linux/time.h 2007-04-27 23:49:26.000000000 +0200
+++ linux-2.6.21.1.dev/include/linux/time.h 2007-05-26 21:23:19.859617680 +0200
@@ -1,6 +1,10 @@
#ifndef _LINUX_TIME_H
#define _LINUX_TIME_H
+#ifndef __KERNEL__
+#include <time.h>
+#else
+
#include <linux/types.h>
#ifdef __KERNEL__
@@ -225,4 +229,6 @@
*/
#define TIMER_ABSTIME 0x01
+#endif /* __KERNEL__ DEBIAN */
+
#endif
diff -urN linux-2.6.21.1.old/include/linux/types.h linux-2.6.21.1.dev/include/linux/types.h
--- linux-2.6.21.1.old/include/linux/types.h 2007-04-27 23:49:26.000000000 +0200
+++ linux-2.6.21.1.dev/include/linux/types.h 2007-05-26 21:23:19.859617680 +0200
@@ -1,6 +1,14 @@
#ifndef _LINUX_TYPES_H
#define _LINUX_TYPES_H
+/* Debian: Use userland types instead. */
+#ifndef __KERNEL__
+# include <sys/types.h>
+/* For other kernel headers. */
+# include <linux/posix_types.h>
+# include <asm/types.h>
+#else
+
#ifdef __KERNEL__
#define BITS_TO_LONGS(bits) \
@@ -162,6 +170,8 @@
#endif /* __KERNEL_STRICT_NAMES */
+#endif /* __KERNEL__ DEBIAN */
+
/*
* Below are truly Linux-specific types that should never collide with
* any application/library that wants linux/types.h.

View File

@ -0,0 +1,108 @@
diff -urN linux-2.6.21.1.old/scripts/genksyms/parse.c_shipped linux-2.6.21.1.dev/scripts/genksyms/parse.c_shipped
--- linux-2.6.21.1.old/scripts/genksyms/parse.c_shipped 2007-04-27 23:49:26.000000000 +0200
+++ linux-2.6.21.1.dev/scripts/genksyms/parse.c_shipped 2007-05-26 21:26:23.565690112 +0200
@@ -144,7 +144,9 @@
#include <assert.h>
+#ifndef __APPLE__
#include <malloc.h>
+#endif
#include "genksyms.h"
static int is_typedef;
diff -urN linux-2.6.21.1.old/scripts/genksyms/parse.y linux-2.6.21.1.dev/scripts/genksyms/parse.y
--- linux-2.6.21.1.old/scripts/genksyms/parse.y 2007-04-27 23:49:26.000000000 +0200
+++ linux-2.6.21.1.dev/scripts/genksyms/parse.y 2007-05-26 21:26:23.563690416 +0200
@@ -24,7 +24,9 @@
%{
#include <assert.h>
+#ifndef __APPLE__
#include <malloc.h>
+#endif
#include "genksyms.h"
static int is_typedef;
diff -urN linux-2.6.21.1.old/scripts/kallsyms.c linux-2.6.21.1.dev/scripts/kallsyms.c
--- linux-2.6.21.1.old/scripts/kallsyms.c 2007-04-27 23:49:26.000000000 +0200
+++ linux-2.6.21.1.dev/scripts/kallsyms.c 2007-05-26 21:26:23.579687984 +0200
@@ -30,6 +30,35 @@
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
+#ifdef __APPLE__
+/* Darwin has no memmem implementation, this one is ripped of the uClibc-0.9.28 source */
+void *memmem (const void *haystack, size_t haystack_len,
+ const void *needle, size_t needle_len)
+{
+ const char *begin;
+ const char *const last_possible
+ = (const char *) haystack + haystack_len - needle_len;
+
+ if (needle_len == 0)
+ /* The first occurrence of the empty string is deemed to occur at
+ the beginning of the string. */
+ return (void *) haystack;
+
+ /* Sanity check, otherwise the loop might search through the whole
+ memory. */
+ if (__builtin_expect (haystack_len < needle_len, 0))
+ return NULL;
+
+ for (begin = (const char *) haystack; begin <= last_possible; ++begin)
+ if (begin[0] == ((const char *) needle)[0] &&
+ !memcmp ((const void *) &begin[1],
+ (const void *) ((const char *) needle + 1),
+ needle_len - 1))
+ return (void *) begin;
+
+ return NULL;
+}
+#endif
#define KSYM_NAME_LEN 127
diff -urN linux-2.6.21.1.old/scripts/kconfig/Makefile linux-2.6.21.1.dev/scripts/kconfig/Makefile
--- linux-2.6.21.1.old/scripts/kconfig/Makefile 2007-04-27 23:49:26.000000000 +0200
+++ linux-2.6.21.1.dev/scripts/kconfig/Makefile 2007-05-26 21:26:23.553691936 +0200
@@ -87,6 +87,9 @@
# we really need to do so. (Do not call gcc as part of make mrproper)
HOST_EXTRACFLAGS = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ccflags)
HOST_LOADLIBES = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ldflags $(HOSTCC))
+ifeq ($(shell uname -s),Darwin)
+HOST_LOADLIBES += -lncurses
+endif
HOST_EXTRACFLAGS += -DLOCALE
diff -urN linux-2.6.21.1.old/scripts/mod/mk_elfconfig.c linux-2.6.21.1.dev/scripts/mod/mk_elfconfig.c
--- linux-2.6.21.1.old/scripts/mod/mk_elfconfig.c 2007-04-27 23:49:26.000000000 +0200
+++ linux-2.6.21.1.dev/scripts/mod/mk_elfconfig.c 2007-05-26 21:26:23.553691936 +0200
@@ -1,7 +1,11 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#ifndef __APPLE__
#include <elf.h>
+#else
+#include "../../../../../tools/sstrip/include/elf.h"
+#endif
int
main(int argc, char **argv)
diff -urN linux-2.6.21.1.old/scripts/mod/modpost.h linux-2.6.21.1.dev/scripts/mod/modpost.h
--- linux-2.6.21.1.old/scripts/mod/modpost.h 2007-04-27 23:49:26.000000000 +0200
+++ linux-2.6.21.1.dev/scripts/mod/modpost.h 2007-05-26 21:26:23.553691936 +0200
@@ -7,7 +7,11 @@
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
+#ifndef __APPLE__
#include <elf.h>
+#else
+#include "../../../../../tools/sstrip/include/elf.h"
+#endif
#include "elfconfig.h"

View File

@ -0,0 +1,18 @@
diff -urN linux-2.6.21.1.old/include/linux/stddef.h linux-2.6.21.1.dev/include/linux/stddef.h
--- linux-2.6.21.1.old/include/linux/stddef.h 2007-04-27 23:49:26.000000000 +0200
+++ linux-2.6.21.1.dev/include/linux/stddef.h 2007-05-26 21:29:46.108898864 +0200
@@ -16,6 +16,7 @@
false = 0,
true = 1
};
+#endif /* __KERNEL__ */
#undef offsetof
#ifdef __compiler_offsetof
@@ -23,6 +24,5 @@
#else
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif
-#endif /* __KERNEL__ */
#endif

View File

@ -0,0 +1,21 @@
diff -urN linux-2.6.21.1.old/scripts/gen_initramfs_list.sh linux-2.6.21.1.dev/scripts/gen_initramfs_list.sh
--- linux-2.6.21.1.old/scripts/gen_initramfs_list.sh 2007-04-27 23:49:26.000000000 +0200
+++ linux-2.6.21.1.dev/scripts/gen_initramfs_list.sh 2007-05-26 21:32:53.679383816 +0200
@@ -125,7 +125,7 @@
str="${ftype} ${name} ${location} ${str}"
;;
"nod")
- local dev=`LC_ALL=C ls -l "${location}"`
+ local dev=`LC_ALL=C ls -l --time-style=locale "${location}"`
local maj=`field 5 ${dev}`
local min=`field 6 ${dev}`
maj=${maj%,}
@@ -135,7 +135,7 @@
str="${ftype} ${name} ${str} ${dev} ${maj} ${min}"
;;
"slink")
- local target=`field 11 $(LC_ALL=C ls -l "${location}")`
+ local target=`field 11 $(LC_ALL=C ls -l --time-style=locale "${location}")`
str="${ftype} ${name} ${target} ${str}"
;;
*)

View File

@ -7,6 +7,7 @@ CONFIG_ALIGNMENT_TRAP=y
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CLPS7500 is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_DAVINCI is not set
# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
# CONFIG_ARCH_EBSA110 is not set
# CONFIG_ARCH_EP93XX is not set
@ -22,6 +23,7 @@ CONFIG_ARCH_IOP32X=y
# CONFIG_ARCH_IXP23XX is not set
# CONFIG_ARCH_IQ80321 is not set
# CONFIG_ARCH_IQ31244 is not set
# CONFIG_ARCH_KS8695 is not set
# CONFIG_ARCH_L7200 is not set
# CONFIG_ARCH_LH7A40X is not set
# CONFIG_ARCH_NETX is not set
@ -103,6 +105,9 @@ CONFIG_DLCI_MAX=8
CONFIG_DNOTIFY=y
# CONFIG_DSCC4 is not set
# CONFIG_E100 is not set
CONFIG_E1000=y
# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
CONFIG_E1000_NAPI=y
# CONFIG_FARSYNC is not set
CONFIG_FIRMWARE_EDID=y
# CONFIG_FPE_FASTFPE is not set
@ -157,6 +162,7 @@ CONFIG_I2C_CHARDEV=y
# CONFIG_IEEE80211_SOFTMAC is not set
# CONFIG_IKCONFIG is not set
CONFIG_INITRAMFS_SOURCE=""
CONFIG_IOP3XX_ATU=y
# CONFIG_IP6_NF_MANGLE is not set
# CONFIG_IP6_NF_MATCH_EUI64 is not set
# CONFIG_IP6_NF_MATCH_FRAG is not set
@ -255,6 +261,7 @@ CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
# CONFIG_MTD_SLRAM is not set
# CONFIG_NATSEMI is not set
# CONFIG_NE2K_PCI is not set
CONFIG_NETDEV_1000=y
CONFIG_NETFILTER_NETLINK=m
# CONFIG_NETFILTER_NETLINK_LOG is not set
# CONFIG_NETFILTER_NETLINK_QUEUE is not set
@ -319,6 +326,9 @@ CONFIG_PLAT_IOP=y
# CONFIG_PM is not set
# CONFIG_PPP is not set
# CONFIG_PRISM54 is not set
CONFIG_R8169=y
CONFIG_R8169_NAPI=y
CONFIG_R8169_VLAN=y
# CONFIG_REISERFS_FS is not set
# CONFIG_ROMFS_FS is not set
# CONFIG_RPCSEC_GSS_KRB5 is not set

View File

@ -8,6 +8,7 @@ CONFIG_ALIGNMENT_TRAP=y
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CLPS7500 is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_DAVINCI is not set
# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
# CONFIG_ARCH_EBSA110 is not set
# CONFIG_ARCH_EP93XX is not set
@ -24,6 +25,7 @@ CONFIG_ARCH_IXDP4XX=y
# CONFIG_ARCH_IXP2000 is not set
# CONFIG_ARCH_IXP23XX is not set
CONFIG_ARCH_IXP4XX=y
# CONFIG_ARCH_KS8695 is not set
# CONFIG_ARCH_L7200 is not set
# CONFIG_ARCH_LH7A40X is not set
# CONFIG_ARCH_NETX is not set
@ -144,6 +146,7 @@ CONFIG_I2C_CHARDEV=y
# CONFIG_I2C_DEBUG_BUS is not set
# CONFIG_I2C_DEBUG_CHIP is not set
# CONFIG_I2C_DEBUG_CORE is not set
CONFIG_I2C_GPIO=y
# CONFIG_I2C_I801 is not set
# CONFIG_I2C_I810 is not set
# CONFIG_I2C_IOP3XX is not set
@ -221,10 +224,12 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_LLC2 is not set
CONFIG_MACH_AVILA=y
CONFIG_MACH_COMPEX=y
CONFIG_MACH_DSMG600=y
CONFIG_MACH_GATEWAY7001=y
# CONFIG_MACH_GTWX5715 is not set
# CONFIG_MACH_IXDP465 is not set
# CONFIG_MACH_IXDPG425 is not set
# CONFIG_MACH_KIXRP435 is not set
CONFIG_MACH_LOFT=y
CONFIG_MACH_NAS100D=y
CONFIG_MACH_NSLU2=y
@ -291,6 +296,7 @@ CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
# CONFIG_MTD_SLRAM is not set
# CONFIG_NATSEMI is not set
# CONFIG_NE2K_PCI is not set
# CONFIG_NETDEV_1000 is not set
CONFIG_NETFILTER_NETLINK=m
# CONFIG_NETFILTER_NETLINK_LOG is not set
# CONFIG_NETFILTER_NETLINK_QUEUE is not set

View File

@ -9,6 +9,7 @@ CONFIG_4xx=y
# CONFIG_AGP is not set
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
# CONFIG_ATM_DRIVERS is not set
# CONFIG_B44 is not set
CONFIG_BASE_SMALL=0
CONFIG_BIOS_FIXUP=y
@ -64,6 +65,7 @@ CONFIG_IDE=m
# CONFIG_IDE_ARM is not set
CONFIG_IDE_GENERIC=m
CONFIG_IDE_MAX_HWIFS=4
# CONFIG_IDE_PROC_FS is not set
# CONFIG_IDE_TASK_IOCTL is not set
CONFIG_INITRAMFS_SOURCE=""
CONFIG_ISA_DMA_API=y
@ -72,6 +74,7 @@ CONFIG_KERNEL_START=0xc0000000
# CONFIG_KEXEC is not set
# CONFIG_LEDS_TRIGGER_IDE_DISK is not set
CONFIG_LOWMEM_SIZE=0x30000000
# CONFIG_MACINTOSH_DRIVERS is not set
CONFIG_MAGICBOX=y
CONFIG_MATH_EMULATION=y
CONFIG_MINI_FO=y
@ -130,6 +133,7 @@ CONFIG_MTD_SPLIT_ROOTFS=y
# CONFIG_NATSEMI is not set
# CONFIG_NE2K_PCI is not set
# CONFIG_NET_VENDOR_3COM is not set
CONFIG_NETDEV_1000=y
CONFIG_NOT_COHERENT_CACHE=y
# CONFIG_NVRAM is not set
# CONFIG_PCIPCWATCHDOG is not set

View File

@ -58,6 +58,7 @@ CONFIG_INITRAMFS_SOURCE=""
CONFIG_IRQ_CPU=y
CONFIG_JFFS2_FS_DEBUG=0
CONFIG_KORINA=y
# CONFIG_MACH_ALCHEMY is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MACH_JAZZ is not set
# CONFIG_MACH_VR41XX is not set
@ -125,7 +126,9 @@ CONFIG_MTD_NAND=y
# CONFIG_MTD_NAND_DISKONCHIP is not set
# CONFIG_MTD_NAND_ECC_SMC is not set
CONFIG_MTD_NAND_IDS=y
# CONFIG_MTD_NAND_MUSEUM_IDS is not set
# CONFIG_MTD_NAND_NANDSIM is not set
# CONFIG_MTD_NAND_PLATFORM is not set
CONFIG_MTD_NAND_RB500=y
CONFIG_MTD_NAND_VERIFY_WRITE=y
# CONFIG_MTD_OBSOLETE_CHIPS is not set
@ -142,6 +145,7 @@ CONFIG_MTD_PARTITIONS=y
# CONFIG_NE2K_PCI is not set
CONFIG_NET_SCH_FIFO=y
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_NETDEV_1000 is not set
# CONFIG_PAGE_SIZE_16KB is not set
CONFIG_PAGE_SIZE_4KB=y
# CONFIG_PAGE_SIZE_64KB is not set
@ -176,6 +180,7 @@ CONFIG_SYS_HAS_CPU_MIPS32_R1=y
CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
# CONFIG_TC35815 is not set
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set

View File

@ -9,6 +9,7 @@
# CONFIG_ARCH_HAS_ILOG2_U64 is not set
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
# CONFIG_ATM_DRIVERS is not set
CONFIG_BASE_SMALL=0
CONFIG_BINFMT_AOUT=m
CONFIG_BINFMT_MISC=m
@ -112,6 +113,7 @@ CONFIG_M486=y
# CONFIG_M586TSC is not set
# CONFIG_M686 is not set
# CONFIG_MACHZ_WDT is not set
# CONFIG_MACINTOSH_DRIVERS is not set
CONFIG_MATH_EMULATION=y
# CONFIG_MCA is not set
# CONFIG_MCORE2 is not set
@ -185,6 +187,7 @@ CONFIG_MTD_RDC3210_SIZE=0x400000
# CONFIG_MTD_TS5500 is not set
# CONFIG_MTRR is not set
# CONFIG_MVIAC3_2 is not set
# CONFIG_MVIAC7 is not set
# CONFIG_MWAVE is not set
# CONFIG_MWINCHIP2 is not set
# CONFIG_MWINCHIP3D is not set
@ -198,6 +201,7 @@ CONFIG_NET_ACT_SIMP=m
# CONFIG_NET_PKTGEN is not set
CONFIG_NET_SCH_FIFO=y
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_NETDEV_1000 is not set
# CONFIG_NFS_V4 is not set
CONFIG_NOHIGHMEM=y
CONFIG_NO_HZ=y
@ -261,6 +265,7 @@ CONFIG_USB_XUSBATM=m
# CONFIG_VM86 is not set
# CONFIG_VMSPLIT_1G is not set
# CONFIG_VMSPLIT_2G is not set
# CONFIG_VMSPLIT_2G_OPT is not set
CONFIG_VMSPLIT_3G=y
# CONFIG_VMSPLIT_3G_OPT is not set
CONFIG_VM_EVENT_COUNTERS=y

View File

@ -142,6 +142,7 @@ CONFIG_JFFS2_FS_DEBUG=0
# CONFIG_LLC2 is not set
CONFIG_LOCK_KERNEL=y
CONFIG_LOG_BUF_SHIFT=15
# CONFIG_MACH_ALCHEMY is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MACH_JAZZ is not set
# CONFIG_MACH_VR41XX is not set
@ -247,6 +248,7 @@ CONFIG_MTD_PARTITIONS=y
CONFIG_NET_SB1250_MAC=y
# CONFIG_NET_SCH_NETEM is not set
# CONFIG_NET_VENDOR_3COM is not set
CONFIG_NETDEV_1000=y
CONFIG_NR_CPUS=2
# CONFIG_NTFS_FS is not set
# CONFIG_N_HDLC is not set

View File

@ -80,6 +80,7 @@ CONFIG_MPENTIUMII=y
# CONFIG_MPENTIUMIII is not set
# CONFIG_MPENTIUMM is not set
# CONFIG_MVIAC3_2 is not set
# CONFIG_MVIAC7 is not set
# CONFIG_MWINCHIP2 is not set
# CONFIG_MWINCHIP3D is not set
# CONFIG_MWINCHIPC6 is not set

View File

@ -11,6 +11,9 @@ BOARD:=x86
BOARDNAME:=x86
FEATURES:=squashfs jffs2 ext2
#LINUX_VERSION:=2.6.22-rc4
#LINUX_KERNEL_MD5SUM:=125879208b47a4c27e4f31a33ab3011c
include $(INCLUDE_DIR)/kernel-build.mk
DEFAULT_PACKAGES += kmod-natsemi kmod-ne2k-pci

View File

@ -25,6 +25,7 @@ CONFIG_ATA=m
# CONFIG_ATA_GENERIC is not set
# CONFIG_ATA_NONSTANDARD is not set
CONFIG_ATA_PIIX=m
# CONFIG_ATM_DRIVERS is not set
CONFIG_BASE_SMALL=0
# CONFIG_BINFMT_AOUT is not set
CONFIG_BITREVERSE=y
@ -134,6 +135,7 @@ CONFIG_IDEPCI_SHARE_IRQ=y
# CONFIG_IDE_CHIPSETS is not set
CONFIG_IDE_GENERIC=y
CONFIG_IDE_MAX_HWIFS=4
# CONFIG_IDE_PROC_FS is not set
# CONFIG_IDE_TASK_IOCTL is not set
CONFIG_INITRAMFS_SOURCE=""
CONFIG_INPUT=y
@ -169,6 +171,7 @@ CONFIG_M486=y
# CONFIG_M586TSC is not set
# CONFIG_M686 is not set
# CONFIG_MACHZ_WDT is not set
# CONFIG_MACINTOSH_DRIVERS is not set
# CONFIG_MATH_EMULATION is not set
# CONFIG_MCA is not set
# CONFIG_MCORE2 is not set
@ -183,10 +186,17 @@ CONFIG_M486=y
# CONFIG_MK6 is not set
# CONFIG_MK7 is not set
# CONFIG_MK8 is not set
# CONFIG_MOUSE_APPLETOUCH is not set
# CONFIG_MOUSE_INPORT is not set
# CONFIG_MOUSE_LOGIBM is not set
# CONFIG_MOUSE_PC110PAD is not set
CONFIG_MOUSE_PS2=y
# CONFIG_MOUSE_PS2_ALPS is not set
# CONFIG_MOUSE_PS2_LIFEBOOK is not set
# CONFIG_MOUSE_PS2_LOGIPS2PP is not set
# CONFIG_MOUSE_PS2_SYNAPTICS is not set
# CONFIG_MOUSE_PS2_TRACKPOINT is not set
# CONFIG_MOUSE_PS2_TOUCHKIT is not set
# CONFIG_MOUSE_SERIAL is not set
# CONFIG_MOUSE_VSXXXAA is not set
# CONFIG_MPENTIUM4 is not set
@ -232,6 +242,7 @@ CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_TS5500 is not set
# CONFIG_MTRR is not set
# CONFIG_MVIAC3_2 is not set
# CONFIG_MVIAC7 is not set
# CONFIG_MWAVE is not set
# CONFIG_MWINCHIP2 is not set
# CONFIG_MWINCHIP3D is not set
@ -244,6 +255,7 @@ CONFIG_NET_SCH_FIFO=y
CONFIG_NET_VENDOR_3COM=y
# CONFIG_NET_VENDOR_RACAL is not set
# CONFIG_NET_VENDOR_SMC is not set
CONFIG_NETDEV_1000=y
CONFIG_NOHIGHMEM=y
# CONFIG_NO_HZ is not set
CONFIG_NSC_GPIO=m
@ -295,6 +307,8 @@ CONFIG_SCx200_I2C_SDA=13
CONFIG_SCx200_WDT=m
# CONFIG_SECCOMP is not set
CONFIG_SEMAPHORE_SLEEPERS=y
# CONFIG_SENSORS_APPLESMC is not set
# CONFIG_SENSORS_CORETEMP is not set
CONFIG_SENSORS_PC87360=m
# CONFIG_SERIAL_8250_CS is not set
# CONFIG_SERIAL_8250_EXTENDED is not set
@ -341,6 +355,7 @@ CONFIG_VIA_RHINE_NAPI=y
# CONFIG_VM86 is not set
# CONFIG_VMSPLIT_1G is not set
# CONFIG_VMSPLIT_2G is not set
# CONFIG_VMSPLIT_2G_OPT is not set
CONFIG_VMSPLIT_3G=y
# CONFIG_VMSPLIT_3G_OPT is not set
CONFIG_VORTEX=m