finally move buildroot-ng to trunk
This commit is contained in:
82
target/linux/generic-2.6/files/init
Executable file
82
target/linux/generic-2.6/files/init
Executable file
@@ -0,0 +1,82 @@
|
||||
#!/bin/sh
|
||||
# Copyright (C) 2006 OpenWrt.org
|
||||
|
||||
export PATH=/bin:/sbin:/usr/bin:/usr/sbin
|
||||
mount none /proc -t proc
|
||||
mount none /dev -t devfs
|
||||
mount non /dev/pts -t devpts
|
||||
|
||||
# the root mount point can come from the kernel command line
|
||||
# or it can be overridden in the preinit.arch file
|
||||
[ -f /etc/preinit.arch ] && . /etc/preinit.arch
|
||||
|
||||
# if we have no root parameter, just go to running from ramfs
|
||||
[ -z $rootfs ] && {
|
||||
export NOMOUNT="No Root"
|
||||
exec /sbin/init
|
||||
}
|
||||
|
||||
#if we have a failsafe boot selected, dont bother
|
||||
#trying to find or wait for a root mount point
|
||||
[ -z "$FAILSAFE" ] || {
|
||||
exec /bin/busybox init
|
||||
}
|
||||
|
||||
# Load the modules we have in initramfs, this should
|
||||
# make the media accessible, but, it may take some time
|
||||
. /etc/functions.sh
|
||||
load_modules /etc/modules /etc/modules.d/*
|
||||
|
||||
#wait 10 seconds for the disc to show up
|
||||
#usb stick typically takes 4 to 6 seconds
|
||||
#till it's readable
|
||||
#it's quite possible the disc never shows up
|
||||
#if we netbooted this kernel
|
||||
COUNTER=0
|
||||
while [ $COUNTER -lt 10 ]; do
|
||||
sleep 1
|
||||
[ -e $rootfs ] && let COUNTER=10;
|
||||
let COUNTER=COUNTER+1
|
||||
done
|
||||
[ -e $rootfs ] || {
|
||||
export FAILSAFE="NoDisc"
|
||||
exec /bin/busybox init
|
||||
}
|
||||
|
||||
# now we'll try mount it, again with a timeout
|
||||
# This will fail if the inserted stick is formatted
|
||||
# in a manner we dont understand
|
||||
COUNTER=0
|
||||
while [ $COUNTER -lt 10 ]; do
|
||||
sleep 1
|
||||
mount $rootfs /mnt
|
||||
[ $? -eq "0" ] && let COUNTER=100;
|
||||
let COUNTER=COUNTER+1
|
||||
done
|
||||
[ $? -ne "0" ] && {
|
||||
export FAILSAFE="MountFail"
|
||||
exec /bin/busybox init
|
||||
}
|
||||
|
||||
#It mounted, lets look for a postinit file, again, give it time
|
||||
#I've seen this take 6 seconds to actually complete
|
||||
COUNTER=0
|
||||
while [ $COUNTER -lt 10 ]; do
|
||||
sleep 1
|
||||
[ -e /mnt/etc/banner ] && let COUNTER=10;
|
||||
let COUNTER=COUNTER+1
|
||||
done
|
||||
[ -e /mnt/etc/banner ] || {
|
||||
export FAILSAFE="No Openwrt FS"
|
||||
exec /bin/busybox init
|
||||
}
|
||||
|
||||
unset rootfs
|
||||
|
||||
mount -o move /proc /mnt/proc
|
||||
mount -o move /dev /mnt/dev
|
||||
mount -o move /dev/pts /mnt/dev/pts
|
||||
mount -o move /tmp /mnt/tmp
|
||||
mount -o move /sys /mnt/sys
|
||||
mount none /tmp -t tmpfs
|
||||
exec switch_root -c /dev/console /mnt /sbin/init
|
||||
718
target/linux/generic-2.6/patches/000-reenable_devfs.patch
Normal file
718
target/linux/generic-2.6/patches/000-reenable_devfs.patch
Normal file
@@ -0,0 +1,718 @@
|
||||
diff -ur linux-2.6.15-rc5/drivers/mtd/mtd_blkdevs.c linux-2.6.15-rc5-openwrt/drivers/mtd/mtd_blkdevs.c
|
||||
--- linux-2.6.15-rc5/drivers/mtd/mtd_blkdevs.c 2005-12-04 06:10:42.000000000 +0100
|
||||
+++ linux-2.6.15-rc5-openwrt/drivers/mtd/mtd_blkdevs.c 2005-12-15 07:53:20.000000000 +0100
|
||||
@@ -21,6 +21,9 @@
|
||||
#include <linux/init.h>
|
||||
#include <asm/semaphore.h>
|
||||
#include <asm/uaccess.h>
|
||||
+#ifdef CONFIG_DEVFS_FS
|
||||
+#include <linux/devfs_fs_kernel.h>
|
||||
+#endif
|
||||
|
||||
static LIST_HEAD(blktrans_majors);
|
||||
|
||||
@@ -302,6 +305,11 @@
|
||||
snprintf(gd->disk_name, sizeof(gd->disk_name),
|
||||
"%s%d", tr->name, new->devnum);
|
||||
|
||||
+#ifdef CONFIG_DEVFS_FS
|
||||
+ snprintf(gd->devfs_name, sizeof(gd->devfs_name),
|
||||
+ "%s/%c", tr->name, (tr->part_bits?'a':'0') + new->devnum);
|
||||
+#endif
|
||||
+
|
||||
/* 2.5 has capacity in units of 512 bytes while still
|
||||
having BLOCK_SIZE_BITS set to 10. Just to keep us amused. */
|
||||
set_capacity(gd, (new->size * new->blksize) >> 9);
|
||||
@@ -418,6 +426,10 @@
|
||||
return ret;
|
||||
}
|
||||
|
||||
+#ifdef CONFIG_DEVFS_FS
|
||||
+ devfs_mk_dir(tr->name);
|
||||
+#endif
|
||||
+
|
||||
INIT_LIST_HEAD(&tr->devs);
|
||||
list_add(&tr->list, &blktrans_majors);
|
||||
|
||||
@@ -450,6 +462,10 @@
|
||||
tr->remove_dev(dev);
|
||||
}
|
||||
|
||||
+#ifdef CONFIG_DEVFS_FS
|
||||
+ devfs_remove(tr->name);
|
||||
+#endif
|
||||
+
|
||||
blk_cleanup_queue(tr->blkcore_priv->rq);
|
||||
unregister_blkdev(tr->major, tr->name);
|
||||
|
||||
diff -ur linux-2.6.15-rc5/drivers/mtd/mtdchar.c linux-2.6.15-rc5-openwrt/drivers/mtd/mtdchar.c
|
||||
--- linux-2.6.15-rc5/drivers/mtd/mtdchar.c 2005-12-04 06:10:42.000000000 +0100
|
||||
+++ linux-2.6.15-rc5-openwrt/drivers/mtd/mtdchar.c 2005-12-15 07:49:15.000000000 +0100
|
||||
@@ -19,19 +18,33 @@
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
+#ifdef CONFIG_DEVFS_FS
|
||||
+#include <linux/devfs_fs_kernel.h>
|
||||
+#else
|
||||
+#include <linux/device.h>
|
||||
+
|
||||
static struct class *mtd_class;
|
||||
+#endif
|
||||
|
||||
static void mtd_notify_add(struct mtd_info* mtd)
|
||||
{
|
||||
if (!mtd)
|
||||
return;
|
||||
|
||||
+#ifdef CONFIG_DEVFS_FS
|
||||
+ devfs_mk_cdev(MKDEV(MTD_CHAR_MAJOR, mtd->index*2),
|
||||
+ S_IFCHR | S_IRUGO | S_IWUGO, "mtd/%d", mtd->index);
|
||||
+
|
||||
+ devfs_mk_cdev(MKDEV(MTD_CHAR_MAJOR, mtd->index*2+1),
|
||||
+ S_IFCHR | S_IRUGO, "mtd/%dro", mtd->index);
|
||||
+#else
|
||||
class_device_create(mtd_class, NULL, MKDEV(MTD_CHAR_MAJOR, mtd->index*2),
|
||||
NULL, "mtd%d", mtd->index);
|
||||
|
||||
class_device_create(mtd_class, NULL,
|
||||
MKDEV(MTD_CHAR_MAJOR, mtd->index*2+1),
|
||||
NULL, "mtd%dro", mtd->index);
|
||||
+#endif
|
||||
}
|
||||
|
||||
static void mtd_notify_remove(struct mtd_info* mtd)
|
||||
@@ -39,8 +52,13 @@
|
||||
if (!mtd)
|
||||
return;
|
||||
|
||||
+#ifdef CONFIG_DEVFS_FS
|
||||
+ devfs_remove("mtd/%d", mtd->index);
|
||||
+ devfs_remove("mtd/%dro", mtd->index);
|
||||
+#else
|
||||
class_device_destroy(mtd_class, MKDEV(MTD_CHAR_MAJOR, mtd->index*2));
|
||||
class_device_destroy(mtd_class, MKDEV(MTD_CHAR_MAJOR, mtd->index*2+1));
|
||||
+#endif
|
||||
}
|
||||
|
||||
static struct mtd_notifier notifier = {
|
||||
@@ -48,6 +66,22 @@
|
||||
.remove = mtd_notify_remove,
|
||||
};
|
||||
|
||||
+#ifdef CONFIG_DEVFS_FS
|
||||
+ static inline void mtdchar_devfs_init(void)
|
||||
+ {
|
||||
+ devfs_mk_dir("mtd");
|
||||
+ register_mtd_user(¬ifier);
|
||||
+ }
|
||||
+ static inline void mtdchar_devfs_exit(void)
|
||||
+ {
|
||||
+ unregister_mtd_user(¬ifier);
|
||||
+ devfs_remove("mtd");
|
||||
+ }
|
||||
+ #else /* !DEVFS */
|
||||
+ #define mtdchar_devfs_init() do { } while(0)
|
||||
+ #define mtdchar_devfs_exit() do { } while(0)
|
||||
+#endif
|
||||
+
|
||||
/*
|
||||
* We use file->private_data to store a pointer to the MTDdevice.
|
||||
* Since alighment is at least 32 bits, we have 2 bits free for OTP
|
||||
@@ -643,6 +677,9 @@
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
+#ifdef CONFIG_DEVFS_FS
|
||||
+ mtdchar_devfs_init();
|
||||
+#else
|
||||
mtd_class = class_create(THIS_MODULE, "mtd");
|
||||
|
||||
if (IS_ERR(mtd_class)) {
|
||||
@@ -652,13 +689,19 @@
|
||||
}
|
||||
|
||||
register_mtd_user(¬ifier);
|
||||
+#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit cleanup_mtdchar(void)
|
||||
{
|
||||
+
|
||||
+#ifdef CONFIG_DEVFS_FS
|
||||
+ mtdchar_devfs_exit();
|
||||
+#else
|
||||
unregister_mtd_user(¬ifier);
|
||||
class_destroy(mtd_class);
|
||||
+#endif
|
||||
unregister_chrdev(MTD_CHAR_MAJOR, "mtd");
|
||||
}
|
||||
|
||||
diff -ur linux-2.6.15-rc5/fs/Kconfig linux-2.6.15-rc5-openwrt/fs/Kconfig
|
||||
--- linux-2.6.15-rc5/fs/Kconfig 2005-12-04 06:10:42.000000000 +0100
|
||||
+++ linux-2.6.15-rc5-openwrt/fs/Kconfig 2005-12-15 07:44:01.000000000 +0100
|
||||
@@ -772,6 +772,56 @@
|
||||
help
|
||||
Exports the dump image of crashed kernel in ELF format.
|
||||
|
||||
+config DEVFS_FS
|
||||
+ bool "/dev file system support (OBSOLETE)"
|
||||
+ depends on EXPERIMENTAL
|
||||
+ help
|
||||
+ This is support for devfs, a virtual file system (like /proc) which
|
||||
+ provides the file system interface to device drivers, normally found
|
||||
+ in /dev. Devfs does not depend on major and minor number
|
||||
+ allocations. Device drivers register entries in /dev which then
|
||||
+ appear automatically, which means that the system administrator does
|
||||
+ not have to create character and block special device files in the
|
||||
+ /dev directory using the mknod command (or MAKEDEV script) anymore.
|
||||
+
|
||||
+ This is work in progress. If you want to use this, you *must* read
|
||||
+ the material in <file:Documentation/filesystems/devfs/>, especially
|
||||
+ the file README there.
|
||||
+
|
||||
+ Note that devfs no longer manages /dev/pts! If you are using UNIX98
|
||||
+ ptys, you will also need to mount the /dev/pts filesystem (devpts).
|
||||
+
|
||||
+ Note that devfs has been obsoleted by udev,
|
||||
+ <http://www.kernel.org/pub/linux/utils/kernel/hotplug/>.
|
||||
+ It has been stripped down to a bare minimum and is only provided for
|
||||
+ legacy installations that use its naming scheme which is
|
||||
+ unfortunately different from the names normal Linux installations
|
||||
+ use.
|
||||
+
|
||||
+ If unsure, say N.
|
||||
+
|
||||
+config DEVFS_MOUNT
|
||||
+ bool "Automatically mount at boot"
|
||||
+ depends on DEVFS_FS
|
||||
+ help
|
||||
+ This option appears if you have CONFIG_DEVFS_FS enabled. Setting
|
||||
+ this to 'Y' will make the kernel automatically mount devfs onto /dev
|
||||
+ when the system is booted, before the init thread is started.
|
||||
+ You can override this with the "devfs=nomount" boot option.
|
||||
+
|
||||
+ If unsure, say N.
|
||||
+
|
||||
+config DEVFS_DEBUG
|
||||
+ bool "Debug devfs"
|
||||
+ depends on DEVFS_FS
|
||||
+ help
|
||||
+ If you say Y here, then the /dev file system code will generate
|
||||
+ debugging messages. See the file
|
||||
+ <file:Documentation/filesystems/devfs/boot-options> for more
|
||||
+ details.
|
||||
+
|
||||
+ If unsure, say N.
|
||||
+
|
||||
config SYSFS
|
||||
bool "sysfs file system support" if EMBEDDED
|
||||
default y
|
||||
diff -ur linux-2.6.17/drivers/ieee1394/dv1394.c linux-2.6.17-devfs/drivers/ieee1394/dv1394.c
|
||||
--- linux-2.6.17/drivers/ieee1394/dv1394.c 2006-06-17 18:49:35.000000000 -0700
|
||||
+++ linux-2.6.17-devfs/drivers/ieee1394/dv1394.c 2006-08-25 11:06:18.000000000 -0700
|
||||
@@ -73,7 +73,7 @@
|
||||
- fix all XXX showstoppers
|
||||
- disable IR/IT DMA interrupts on shutdown
|
||||
- flush pci writes to the card by issuing a read
|
||||
- - character device dispatching
|
||||
+ - devfs and character device dispatching (* needs testing with Linux 2.2.x)
|
||||
- switch over to the new kernel DMA API (pci_map_*()) (* needs testing on platforms with IOMMU!)
|
||||
- keep all video_cards in a list (for open() via chardev), set file->private_data = video
|
||||
- dv1394_poll should indicate POLLIN when receiving buffers are available
|
||||
@@ -1096,6 +1096,7 @@
|
||||
|
||||
init.api_version = DV1394_API_VERSION;
|
||||
init.n_frames = DV1394_MAX_FRAMES / 4;
|
||||
+ /* the following are now set via devfs */
|
||||
init.channel = video->channel;
|
||||
init.format = video->pal_or_ntsc;
|
||||
init.cip_n = video->cip_n;
|
||||
@@ -1790,6 +1791,8 @@
|
||||
{
|
||||
struct video_card *video = NULL;
|
||||
|
||||
+ /* if the device was opened through devfs, then file->private_data
|
||||
+ has already been set to video by devfs */
|
||||
if (file->private_data) {
|
||||
video = (struct video_card*) file->private_data;
|
||||
|
||||
@@ -2208,7 +2211,7 @@
|
||||
video = kzalloc(sizeof(*video), GFP_KERNEL);
|
||||
if (!video) {
|
||||
printk(KERN_ERR "dv1394: cannot allocate video_card\n");
|
||||
- return -1;
|
||||
+ goto err;
|
||||
}
|
||||
|
||||
video->ohci = ohci;
|
||||
@@ -2263,14 +2266,37 @@
|
||||
list_add_tail(&video->list, &dv1394_cards);
|
||||
spin_unlock_irqrestore(&dv1394_cards_lock, flags);
|
||||
|
||||
+ if (devfs_mk_cdev(MKDEV(IEEE1394_MAJOR,
|
||||
+ IEEE1394_MINOR_BLOCK_DV1394*16 + video->id),
|
||||
+ S_IFCHR|S_IRUGO|S_IWUGO,
|
||||
+ "ieee1394/dv/host%d/%s/%s",
|
||||
+ (video->id>>2),
|
||||
+ (video->pal_or_ntsc == DV1394_NTSC ? "NTSC" : "PAL"),
|
||||
+ (video->mode == MODE_RECEIVE ? "in" : "out")) < 0)
|
||||
+ goto err_free;
|
||||
+
|
||||
debug_printk("dv1394: dv1394_init() OK on ID %d\n", video->id);
|
||||
+
|
||||
return 0;
|
||||
+
|
||||
+ err_free:
|
||||
+ kfree(video);
|
||||
+ err:
|
||||
+ return -1;
|
||||
}
|
||||
|
||||
static void dv1394_un_init(struct video_card *video)
|
||||
{
|
||||
+ char buf[32];
|
||||
+
|
||||
/* obviously nobody has the driver open at this point */
|
||||
do_dv1394_shutdown(video, 1);
|
||||
+ snprintf(buf, sizeof(buf), "dv/host%d/%s/%s", (video->id >> 2),
|
||||
+ (video->pal_or_ntsc == DV1394_NTSC ? "NTSC" : "PAL"),
|
||||
+ (video->mode == MODE_RECEIVE ? "in" : "out")
|
||||
+ );
|
||||
+
|
||||
+ devfs_remove("ieee1394/%s", buf);
|
||||
kfree(video);
|
||||
}
|
||||
|
||||
@@ -2307,6 +2333,9 @@
|
||||
|
||||
class_device_destroy(hpsb_protocol_class,
|
||||
MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)));
|
||||
+ devfs_remove("ieee1394/dv/host%d/NTSC", id);
|
||||
+ devfs_remove("ieee1394/dv/host%d/PAL", id);
|
||||
+ devfs_remove("ieee1394/dv/host%d", id);
|
||||
}
|
||||
|
||||
static void dv1394_add_host (struct hpsb_host *host)
|
||||
@@ -2323,6 +2352,9 @@
|
||||
class_device_create(hpsb_protocol_class, NULL, MKDEV(
|
||||
IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)),
|
||||
NULL, "dv1394-%d", id);
|
||||
+ devfs_mk_dir("ieee1394/dv/host%d", id);
|
||||
+ devfs_mk_dir("ieee1394/dv/host%d/NTSC", id);
|
||||
+ devfs_mk_dir("ieee1394/dv/host%d/PAL", id);
|
||||
|
||||
dv1394_init(ohci, DV1394_NTSC, MODE_RECEIVE);
|
||||
dv1394_init(ohci, DV1394_NTSC, MODE_TRANSMIT);
|
||||
@@ -2579,8 +2611,10 @@
|
||||
static void __exit dv1394_exit_module(void)
|
||||
{
|
||||
hpsb_unregister_protocol(&dv1394_driver);
|
||||
+
|
||||
hpsb_unregister_highlevel(&dv1394_highlevel);
|
||||
cdev_del(&dv1394_cdev);
|
||||
+ devfs_remove("ieee1394/dv");
|
||||
}
|
||||
|
||||
static int __init dv1394_init_module(void)
|
||||
@@ -2596,12 +2630,15 @@
|
||||
return ret;
|
||||
}
|
||||
|
||||
+ devfs_mk_dir("ieee1394/dv");
|
||||
+
|
||||
hpsb_register_highlevel(&dv1394_highlevel);
|
||||
|
||||
ret = hpsb_register_protocol(&dv1394_driver);
|
||||
if (ret) {
|
||||
printk(KERN_ERR "dv1394: failed to register protocol\n");
|
||||
hpsb_unregister_highlevel(&dv1394_highlevel);
|
||||
+ devfs_remove("ieee1394/dv");
|
||||
cdev_del(&dv1394_cdev);
|
||||
return ret;
|
||||
}
|
||||
diff -ur linux-2.6.17/drivers/ieee1394/ieee1394_core.c linux-2.6.17-devfs/drivers/ieee1394/ieee1394_core.c
|
||||
--- linux-2.6.17/drivers/ieee1394/ieee1394_core.c 2006-06-17 18:49:35.000000000 -0700
|
||||
+++ linux-2.6.17-devfs/drivers/ieee1394/ieee1394_core.c 2006-08-25 11:06:18.000000000 -0700
|
||||
@@ -1078,10 +1078,17 @@
|
||||
goto exit_release_kernel_thread;
|
||||
}
|
||||
|
||||
+ /* actually this is a non-fatal error */
|
||||
+ ret = devfs_mk_dir("ieee1394");
|
||||
+ if (ret < 0) {
|
||||
+ HPSB_ERR("unable to make devfs dir for device major %d!\n", IEEE1394_MAJOR);
|
||||
+ goto release_chrdev;
|
||||
+ }
|
||||
+
|
||||
ret = bus_register(&ieee1394_bus_type);
|
||||
if (ret < 0) {
|
||||
HPSB_INFO("bus register failed");
|
||||
- goto release_chrdev;
|
||||
+ goto release_devfs;
|
||||
}
|
||||
|
||||
for (i = 0; fw_bus_attrs[i]; i++) {
|
||||
@@ -1092,7 +1099,7 @@
|
||||
fw_bus_attrs[i--]);
|
||||
}
|
||||
bus_unregister(&ieee1394_bus_type);
|
||||
- goto release_chrdev;
|
||||
+ goto release_devfs;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1145,6 +1152,8 @@
|
||||
for (i = 0; fw_bus_attrs[i]; i++)
|
||||
bus_remove_file(&ieee1394_bus_type, fw_bus_attrs[i]);
|
||||
bus_unregister(&ieee1394_bus_type);
|
||||
+release_devfs:
|
||||
+ devfs_remove("ieee1394");
|
||||
release_chrdev:
|
||||
unregister_chrdev_region(IEEE1394_CORE_DEV, 256);
|
||||
exit_release_kernel_thread:
|
||||
@@ -1182,6 +1191,7 @@
|
||||
hpsb_cleanup_config_roms();
|
||||
|
||||
unregister_chrdev_region(IEEE1394_CORE_DEV, 256);
|
||||
+ devfs_remove("ieee1394");
|
||||
}
|
||||
|
||||
module_init(ieee1394_init);
|
||||
diff -ur linux-2.6.17/drivers/ieee1394/ieee1394_core.h linux-2.6.17-devfs/drivers/ieee1394/ieee1394_core.h
|
||||
--- linux-2.6.17/drivers/ieee1394/ieee1394_core.h 2006-06-17 18:49:35.000000000 -0700
|
||||
+++ linux-2.6.17-devfs/drivers/ieee1394/ieee1394_core.h 2006-08-25 11:06:18.000000000 -0700
|
||||
@@ -3,6 +3,7 @@
|
||||
#define _IEEE1394_CORE_H
|
||||
|
||||
#include <linux/slab.h>
|
||||
+#include <linux/devfs_fs_kernel.h>
|
||||
#include <asm/atomic.h>
|
||||
#include <asm/semaphore.h>
|
||||
#include "hosts.h"
|
||||
diff -ur linux-2.6.17/drivers/ieee1394/raw1394.c linux-2.6.17-devfs/drivers/ieee1394/raw1394.c
|
||||
--- linux-2.6.17/drivers/ieee1394/raw1394.c 2006-06-17 18:49:35.000000000 -0700
|
||||
+++ linux-2.6.17-devfs/drivers/ieee1394/raw1394.c 2006-08-25 11:06:18.000000000 -0700
|
||||
@@ -41,6 +41,7 @@
|
||||
#include <linux/cdev.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/atomic.h>
|
||||
+#include <linux/devfs_fs_kernel.h>
|
||||
#include <linux/compat.h>
|
||||
|
||||
#include "csr1212.h"
|
||||
@@ -2998,6 +2999,9 @@
|
||||
goto out_unreg;
|
||||
}
|
||||
|
||||
+ devfs_mk_cdev(MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16),
|
||||
+ S_IFCHR | S_IRUSR | S_IWUSR, RAW1394_DEVICE_NAME);
|
||||
+
|
||||
cdev_init(&raw1394_cdev, &raw1394_fops);
|
||||
raw1394_cdev.owner = THIS_MODULE;
|
||||
kobject_set_name(&raw1394_cdev.kobj, RAW1394_DEVICE_NAME);
|
||||
@@ -3019,6 +3023,7 @@
|
||||
goto out;
|
||||
|
||||
out_dev:
|
||||
+ devfs_remove(RAW1394_DEVICE_NAME);
|
||||
class_device_destroy(hpsb_protocol_class,
|
||||
MKDEV(IEEE1394_MAJOR,
|
||||
IEEE1394_MINOR_BLOCK_RAW1394 * 16));
|
||||
@@ -3034,6 +3039,7 @@
|
||||
MKDEV(IEEE1394_MAJOR,
|
||||
IEEE1394_MINOR_BLOCK_RAW1394 * 16));
|
||||
cdev_del(&raw1394_cdev);
|
||||
+ devfs_remove(RAW1394_DEVICE_NAME);
|
||||
hpsb_unregister_highlevel(&raw1394_highlevel);
|
||||
hpsb_unregister_protocol(&raw1394_driver);
|
||||
}
|
||||
diff -ur linux-2.6.17/drivers/ieee1394/video1394.c linux-2.6.17-devfs/drivers/ieee1394/video1394.c
|
||||
--- linux-2.6.17/drivers/ieee1394/video1394.c 2006-06-17 18:49:35.000000000 -0700
|
||||
+++ linux-2.6.17-devfs/drivers/ieee1394/video1394.c 2006-08-25 11:06:18.000000000 -0700
|
||||
@@ -42,6 +42,7 @@
|
||||
#include <linux/poll.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/delay.h>
|
||||
+#include <linux/devfs_fs_kernel.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/vmalloc.h>
|
||||
@@ -1321,6 +1322,9 @@
|
||||
class_device_create(hpsb_protocol_class, NULL, MKDEV(
|
||||
IEEE1394_MAJOR, minor),
|
||||
NULL, "%s-%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
|
||||
+ devfs_mk_cdev(MKDEV(IEEE1394_MAJOR, minor),
|
||||
+ S_IFCHR | S_IRUSR | S_IWUSR,
|
||||
+ "%s/%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
|
||||
}
|
||||
|
||||
|
||||
@@ -1328,9 +1332,12 @@
|
||||
{
|
||||
struct ti_ohci *ohci = hpsb_get_hostinfo(&video1394_highlevel, host);
|
||||
|
||||
- if (ohci)
|
||||
+ if (ohci) {
|
||||
class_device_destroy(hpsb_protocol_class, MKDEV(IEEE1394_MAJOR,
|
||||
IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id));
|
||||
+ devfs_remove("%s/%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
|
||||
+ }
|
||||
+
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1471,8 +1478,12 @@
|
||||
static void __exit video1394_exit_module (void)
|
||||
{
|
||||
hpsb_unregister_protocol(&video1394_driver);
|
||||
+
|
||||
hpsb_unregister_highlevel(&video1394_highlevel);
|
||||
+
|
||||
+ devfs_remove(VIDEO1394_DRIVER_NAME);
|
||||
cdev_del(&video1394_cdev);
|
||||
+
|
||||
PRINT_G(KERN_INFO, "Removed " VIDEO1394_DRIVER_NAME " module");
|
||||
}
|
||||
|
||||
@@ -1489,12 +1500,15 @@
|
||||
return ret;
|
||||
}
|
||||
|
||||
+ devfs_mk_dir(VIDEO1394_DRIVER_NAME);
|
||||
+
|
||||
hpsb_register_highlevel(&video1394_highlevel);
|
||||
|
||||
ret = hpsb_register_protocol(&video1394_driver);
|
||||
if (ret) {
|
||||
PRINT_G(KERN_ERR, "video1394: failed to register protocol");
|
||||
hpsb_unregister_highlevel(&video1394_highlevel);
|
||||
+ devfs_remove(VIDEO1394_DRIVER_NAME);
|
||||
cdev_del(&video1394_cdev);
|
||||
return ret;
|
||||
}
|
||||
diff -ur linux-2.6.17/drivers/scsi/osst.c linux-2.6.17-devfs/drivers/scsi/osst.c
|
||||
--- linux-2.6.17/drivers/scsi/osst.c 2006-06-17 18:49:35.000000000 -0700
|
||||
+++ linux-2.6.17-devfs/drivers/scsi/osst.c 2006-08-25 11:06:18.000000000 -0700
|
||||
@@ -48,6 +48,7 @@
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/moduleparam.h>
|
||||
+#include <linux/devfs_fs_kernel.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <asm/uaccess.h>
|
||||
@@ -5721,7 +5722,7 @@
|
||||
struct st_partstat * STps;
|
||||
struct osst_buffer * buffer;
|
||||
struct gendisk * drive;
|
||||
- int i, dev_num;
|
||||
+ int i, mode, dev_num;
|
||||
|
||||
if (SDp->type != TYPE_TAPE || !osst_supports(SDp))
|
||||
return -ENODEV;
|
||||
@@ -5857,6 +5858,18 @@
|
||||
snprintf(name, 8, "%s%s", "n", tape_name(tpnt));
|
||||
osst_sysfs_add(MKDEV(OSST_MAJOR, dev_num + 128), dev, tpnt, name);
|
||||
}
|
||||
+ for (mode = 0; mode < ST_NBR_MODES; ++mode) {
|
||||
+ /* Rewind entry */
|
||||
+ devfs_mk_cdev(MKDEV(OSST_MAJOR, dev_num + (mode << 5)),
|
||||
+ S_IFCHR | S_IRUGO | S_IWUGO,
|
||||
+ "%s/ot%s", SDp->devfs_name, osst_formats[mode]);
|
||||
+
|
||||
+ /* No-rewind entry */
|
||||
+ devfs_mk_cdev(MKDEV(OSST_MAJOR, dev_num + (mode << 5) + 128),
|
||||
+ S_IFCHR | S_IRUGO | S_IWUGO,
|
||||
+ "%s/ot%sn", SDp->devfs_name, osst_formats[mode]);
|
||||
+ }
|
||||
+ drive->number = devfs_register_tape(SDp->devfs_name);
|
||||
|
||||
sdev_printk(KERN_INFO, SDp,
|
||||
"osst :I: Attached OnStream %.5s tape as %s\n",
|
||||
@@ -5873,7 +5886,7 @@
|
||||
{
|
||||
struct scsi_device * SDp = to_scsi_device(dev);
|
||||
struct osst_tape * tpnt;
|
||||
- int i;
|
||||
+ int i, mode;
|
||||
|
||||
if ((SDp->type != TYPE_TAPE) || (osst_nr_dev <= 0))
|
||||
return 0;
|
||||
@@ -5884,6 +5897,11 @@
|
||||
osst_sysfs_destroy(MKDEV(OSST_MAJOR, i));
|
||||
osst_sysfs_destroy(MKDEV(OSST_MAJOR, i+128));
|
||||
tpnt->device = NULL;
|
||||
+ for (mode = 0; mode < ST_NBR_MODES; ++mode) {
|
||||
+ devfs_remove("%s/ot%s", SDp->devfs_name, osst_formats[mode]);
|
||||
+ devfs_remove("%s/ot%sn", SDp->devfs_name, osst_formats[mode]);
|
||||
+ }
|
||||
+ devfs_unregister_tape(tpnt->drive->number);
|
||||
put_disk(tpnt->drive);
|
||||
os_scsi_tapes[i] = NULL;
|
||||
osst_nr_dev--;
|
||||
diff -ur linux-2.6.17/drivers/scsi/scsi.c linux-2.6.17-devfs/drivers/scsi/scsi.c
|
||||
--- linux-2.6.17/drivers/scsi/scsi.c 2006-06-17 18:49:35.000000000 -0700
|
||||
+++ linux-2.6.17-devfs/drivers/scsi/scsi.c 2006-08-25 11:07:42.000000000 -0700
|
||||
@@ -48,6 +48,7 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/completion.h>
|
||||
+#include <linux/devfs_fs_kernel.h>
|
||||
#include <linux/unistd.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/kmod.h>
|
||||
@@ -1247,6 +1248,7 @@
|
||||
for_each_possible_cpu(i)
|
||||
INIT_LIST_HEAD(&per_cpu(scsi_done_q, i));
|
||||
|
||||
+ devfs_mk_dir("scsi");
|
||||
printk(KERN_NOTICE "SCSI subsystem initialized\n");
|
||||
return 0;
|
||||
|
||||
@@ -1271,6 +1273,7 @@
|
||||
scsi_exit_sysctl();
|
||||
scsi_exit_hosts();
|
||||
scsi_exit_devinfo();
|
||||
+ devfs_remove("scsi");
|
||||
scsi_exit_procfs();
|
||||
scsi_exit_queue();
|
||||
}
|
||||
diff -ur linux-2.6.17/drivers/scsi/scsi_scan.c linux-2.6.17-devfs/drivers/scsi/scsi_scan.c
|
||||
--- linux-2.6.17/drivers/scsi/scsi_scan.c 2006-06-17 18:49:35.000000000 -0700
|
||||
+++ linux-2.6.17-devfs/drivers/scsi/scsi_scan.c 2006-08-25 11:06:18.000000000 -0700
|
||||
@@ -716,8 +716,12 @@
|
||||
if (inq_result[7] & 0x10)
|
||||
sdev->sdtr = 1;
|
||||
|
||||
+ sprintf(sdev->devfs_name, "scsi/host%d/bus%d/target%d/lun%d",
|
||||
+ sdev->host->host_no, sdev->channel,
|
||||
+ sdev->id, sdev->lun);
|
||||
+
|
||||
/*
|
||||
- * End sysfs code.
|
||||
+ * End driverfs/devfs code.
|
||||
*/
|
||||
|
||||
if ((sdev->scsi_level >= SCSI_2) && (inq_result[7] & 2) &&
|
||||
diff -ur linux-2.6.17/drivers/scsi/sd.c linux-2.6.17-devfs/drivers/scsi/sd.c
|
||||
--- linux-2.6.17/drivers/scsi/sd.c 2006-06-17 18:49:35.000000000 -0700
|
||||
+++ linux-2.6.17-devfs/drivers/scsi/sd.c 2006-08-25 11:06:18.000000000 -0700
|
||||
@@ -1683,6 +1683,8 @@
|
||||
'a' + m1, 'a' + m2, 'a' + m3);
|
||||
}
|
||||
|
||||
+ strcpy(gd->devfs_name, sdp->devfs_name);
|
||||
+
|
||||
gd->private_data = &sdkp->driver;
|
||||
gd->queue = sdkp->device->request_queue;
|
||||
|
||||
diff -ur linux-2.6.17/drivers/scsi/sg.c linux-2.6.17-devfs/drivers/scsi/sg.c
|
||||
--- linux-2.6.17/drivers/scsi/sg.c 2006-06-17 18:49:35.000000000 -0700
|
||||
+++ linux-2.6.17-devfs/drivers/scsi/sg.c 2006-08-25 11:06:18.000000000 -0700
|
||||
@@ -44,6 +44,7 @@
|
||||
#include <linux/poll.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/moduleparam.h>
|
||||
+#include <linux/devfs_fs_kernel.h>
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/blkdev.h>
|
||||
@@ -1427,10 +1428,14 @@
|
||||
k = error;
|
||||
sdp = sg_dev_arr[k];
|
||||
|
||||
+ devfs_mk_cdev(MKDEV(SCSI_GENERIC_MAJOR, k),
|
||||
+ S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP,
|
||||
+ "%s/generic", scsidp->devfs_name);
|
||||
error = cdev_add(cdev, MKDEV(SCSI_GENERIC_MAJOR, k), 1);
|
||||
- if (error)
|
||||
+ if (error) {
|
||||
+ devfs_remove("%s/generic", scsidp->devfs_name);
|
||||
goto out;
|
||||
-
|
||||
+ }
|
||||
sdp->cdev = cdev;
|
||||
if (sg_sysfs_valid) {
|
||||
struct class_device * sg_class_member;
|
||||
@@ -1520,6 +1525,7 @@
|
||||
class_device_destroy(sg_sysfs_class, MKDEV(SCSI_GENERIC_MAJOR, k));
|
||||
cdev_del(sdp->cdev);
|
||||
sdp->cdev = NULL;
|
||||
+ devfs_remove("%s/generic", scsidp->devfs_name);
|
||||
put_disk(sdp->disk);
|
||||
sdp->disk = NULL;
|
||||
if (NULL == sdp->headfp)
|
||||
diff -ur linux-2.6.17/drivers/scsi/sr.c linux-2.6.17-devfs/drivers/scsi/sr.c
|
||||
--- linux-2.6.17/drivers/scsi/sr.c 2006-06-17 18:49:35.000000000 -0700
|
||||
+++ linux-2.6.17-devfs/drivers/scsi/sr.c 2006-08-25 11:06:18.000000000 -0700
|
||||
@@ -592,6 +592,8 @@
|
||||
get_capabilities(cd);
|
||||
sr_vendor_init(cd);
|
||||
|
||||
+ snprintf(disk->devfs_name, sizeof(disk->devfs_name),
|
||||
+ "%s/cd", sdev->devfs_name);
|
||||
disk->driverfs_dev = &sdev->sdev_gendev;
|
||||
set_capacity(disk, cd->capacity);
|
||||
disk->private_data = &cd->driver;
|
||||
diff -ur linux-2.6.17/drivers/scsi/st.c linux-2.6.17-devfs/drivers/scsi/st.c
|
||||
--- linux-2.6.17/drivers/scsi/st.c 2006-06-17 18:49:35.000000000 -0700
|
||||
+++ linux-2.6.17-devfs/drivers/scsi/st.c 2006-08-25 11:06:18.000000000 -0700
|
||||
@@ -35,6 +35,7 @@
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/moduleparam.h>
|
||||
+#include <linux/devfs_fs_kernel.h>
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/mutex.h>
|
||||
@@ -4053,8 +4054,23 @@
|
||||
do_create_class_files(tpnt, dev_num, mode);
|
||||
}
|
||||
|
||||
+ for (mode = 0; mode < ST_NBR_MODES; ++mode) {
|
||||
+ /* Make sure that the minor numbers corresponding to the four
|
||||
+ first modes always get the same names */
|
||||
+ i = mode << (4 - ST_NBR_MODE_BITS);
|
||||
+ /* Rewind entry */
|
||||
+ devfs_mk_cdev(MKDEV(SCSI_TAPE_MAJOR, TAPE_MINOR(dev_num, mode, 0)),
|
||||
+ S_IFCHR | S_IRUGO | S_IWUGO,
|
||||
+ "%s/mt%s", SDp->devfs_name, st_formats[i]);
|
||||
+ /* No-rewind entry */
|
||||
+ devfs_mk_cdev(MKDEV(SCSI_TAPE_MAJOR, TAPE_MINOR(dev_num, mode, 1)),
|
||||
+ S_IFCHR | S_IRUGO | S_IWUGO,
|
||||
+ "%s/mt%sn", SDp->devfs_name, st_formats[i]);
|
||||
+ }
|
||||
+ disk->number = devfs_register_tape(SDp->devfs_name);
|
||||
+
|
||||
sdev_printk(KERN_WARNING, SDp,
|
||||
"Attached scsi tape %s\n", tape_name(tpnt));
|
||||
printk(KERN_WARNING "%s: try direct i/o: %s (alignment %d B)\n",
|
||||
tape_name(tpnt), tpnt->try_dio ? "yes" : "no",
|
||||
queue_dma_alignment(SDp->request_queue) + 1);
|
||||
@@ -4106,9 +4122,13 @@
|
||||
scsi_tapes[i] = NULL;
|
||||
st_nr_dev--;
|
||||
write_unlock(&st_dev_arr_lock);
|
||||
+ devfs_unregister_tape(tpnt->disk->number);
|
||||
sysfs_remove_link(&tpnt->device->sdev_gendev.kobj,
|
||||
"tape");
|
||||
for (mode = 0; mode < ST_NBR_MODES; ++mode) {
|
||||
+ j = mode << (4 - ST_NBR_MODE_BITS);
|
||||
+ devfs_remove("%s/mt%s", SDp->devfs_name, st_formats[j]);
|
||||
+ devfs_remove("%s/mt%sn", SDp->devfs_name, st_formats[j]);
|
||||
for (j=0; j < 2; j++) {
|
||||
class_device_destroy(st_sysfs_class,
|
||||
MKDEV(SCSI_TAPE_MAJOR,
|
||||
diff -ur linux-2.6.17/include/scsi/scsi_device.h linux-2.6.17-devfs/include/scsi/scsi_device.h
|
||||
--- linux-2.6.17/include/scsi/scsi_device.h 2006-06-17 18:49:35.000000000 -0700
|
||||
+++ linux-2.6.17-devfs/include/scsi/scsi_device.h 2006-08-25 11:06:18.000000000 -0700
|
||||
@@ -74,6 +74,7 @@
|
||||
unsigned sector_size; /* size in bytes */
|
||||
|
||||
void *hostdata; /* available to low-level driver */
|
||||
+ char devfs_name[256]; /* devfs junk */
|
||||
char type;
|
||||
char scsi_level;
|
||||
char inq_periph_qual; /* PQ from INQUIRY data */
|
||||
4173
target/linux/generic-2.6/patches/001-squashfs.patch
Normal file
4173
target/linux/generic-2.6/patches/001-squashfs.patch
Normal file
File diff suppressed because it is too large
Load Diff
886
target/linux/generic-2.6/patches/002-squashfs_lzma.patch
Normal file
886
target/linux/generic-2.6/patches/002-squashfs_lzma.patch
Normal file
@@ -0,0 +1,886 @@
|
||||
diff -Nur linux-2.6.16/fs/squashfs/inode.c linux-2.6.16-owrt/fs/squashfs/inode.c
|
||||
--- linux-2.6.16/fs/squashfs/inode.c 2006-03-21 10:55:59.000000000 +0100
|
||||
+++ linux-2.6.16-owrt/fs/squashfs/inode.c 2006-03-21 12:24:37.000000000 +0100
|
||||
@@ -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 "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 super_block *, struct kstatfs *);
|
||||
static int squashfs_symlink_readpage(struct file *file, struct page *page);
|
||||
@@ -64,7 +81,11 @@
|
||||
const char *, void *);
|
||||
|
||||
|
||||
+#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,6 +293,7 @@
|
||||
bytes = 0;
|
||||
} else
|
||||
bytes = stream.total_out;
|
||||
+#endif
|
||||
|
||||
up(&msblk->read_data_mutex);
|
||||
}
|
||||
@@ -2046,15 +2077,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();
|
||||
}
|
||||
|
||||
@@ -2065,7 +2100,9 @@
|
||||
|
||||
static void __exit exit_squashfs_fs(void)
|
||||
{
|
||||
+#ifndef SQUASHFS_LZMA
|
||||
vfree(stream.workspace);
|
||||
+#endif
|
||||
unregister_filesystem(&squashfs_fs_type);
|
||||
destroy_inodecache();
|
||||
}
|
||||
diff -Nur linux-2.6.16/fs/squashfs/LzmaDecode.c linux-2.6.16-owrt/fs/squashfs/LzmaDecode.c
|
||||
--- linux-2.6.16/fs/squashfs/LzmaDecode.c 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ linux-2.6.16-owrt/fs/squashfs/LzmaDecode.c 2006-03-21 10:56:57.000000000 +0100
|
||||
@@ -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 "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 -Nur linux-2.6.16/fs/squashfs/LzmaDecode.h linux-2.6.16-owrt/fs/squashfs/LzmaDecode.h
|
||||
--- linux-2.6.16/fs/squashfs/LzmaDecode.h 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ linux-2.6.16-owrt/fs/squashfs/LzmaDecode.h 2006-03-21 10:56:57.000000000 +0100
|
||||
@@ -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 -Nur linux-2.6.16/fs/squashfs/Makefile linux-2.6.16-owrt/fs/squashfs/Makefile
|
||||
--- linux-2.6.16/fs/squashfs/Makefile 2006-03-21 10:55:59.000000000 +0100
|
||||
+++ linux-2.6.16-owrt/fs/squashfs/Makefile 2006-03-21 10:57:08.000000000 +0100
|
||||
@@ -5,3 +5,4 @@
|
||||
obj-$(CONFIG_SQUASHFS) += squashfs.o
|
||||
squashfs-y += inode.o
|
||||
squashfs-y += squashfs2_0.o
|
||||
+squashfs-y += LzmaDecode.o
|
||||
@@ -0,0 +1,12 @@
|
||||
--- linux-2.6.12.5/Makefile.old 2005-10-23 22:56:29.017270000 +0200
|
||||
+++ linux-2.6.12.5/Makefile 2005-10-23 22:57:23.226138500 +0200
|
||||
@@ -533,6 +533,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,)
|
||||
|
||||
221
target/linux/generic-2.6/patches/005-gcc4_fix.patch
Normal file
221
target/linux/generic-2.6/patches/005-gcc4_fix.patch
Normal file
@@ -0,0 +1,221 @@
|
||||
diff -ruN linux-2.6.15.1/include/asm-ppc/libgcc.h linux-2.6.15.1-openwrt/include/asm-ppc/libgcc.h
|
||||
--- linux-2.6.15.1/include/asm-ppc/libgcc.h 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ linux-2.6.15.1-openwrt/include/asm-ppc/libgcc.h 2006-02-01 15:47:53.000000000 +0100
|
||||
@@ -0,0 +1,8 @@
|
||||
+#ifndef __ASM_LIBGCC_H
|
||||
+#define __ASM_LIBGCC_H
|
||||
+
|
||||
+#undef ARCH_NEEDS_ashldi3
|
||||
+#undef ARCH_NEEDS_ashrdi3
|
||||
+#undef ARCH_NEEDS_lshrdi3
|
||||
+
|
||||
+#endif /* __ASM_LIBGCC_H */
|
||||
diff -ruN linux-2.6.15.1/include/asm-i386/libgcc.h linux-2.6.15.1-openwrt/include/asm-i386/libgcc.h
|
||||
--- linux-2.6.15.1/include/asm-i386/libgcc.h 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ linux-2.6.15.1-openwrt/include/asm-i386/libgcc.h 2006-02-01 15:47:53.000000000 +0100
|
||||
@@ -0,0 +1,8 @@
|
||||
+#ifndef __ASM_LIBGCC_H
|
||||
+#define __ASM_LIBGCC_H
|
||||
+
|
||||
+#undef ARCH_NEEDS_ashldi3
|
||||
+#undef ARCH_NEEDS_ashrdi3
|
||||
+#undef ARCH_NEEDS_lshrdi3
|
||||
+
|
||||
+#endif /* __ASM_LIBGCC_H */
|
||||
diff -ruN linux-2.6.15.1/include/asm-um/libgcc.h linux-2.6.15.1-openwrt/include/asm-i386/libgcc.h
|
||||
--- linux-2.6.15.1/include/asm-um/libgcc.h 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ linux-2.6.15.1-openwrt/include/asm-um/libgcc.h 2006-02-01 15:47:53.000000000 +0100
|
||||
@@ -0,0 +1,8 @@
|
||||
+#ifndef __ASM_LIBGCC_H
|
||||
+#define __ASM_LIBGCC_H
|
||||
+
|
||||
+#undef ARCH_NEEDS_ashldi3
|
||||
+#undef ARCH_NEEDS_ashrdi3
|
||||
+#undef ARCH_NEEDS_lshrdi3
|
||||
+
|
||||
+#endif /* __ASM_LIBGCC_H */
|
||||
diff -Nur linux-2.6.15.1/include/asm-mips/libgcc.h linux-2.6.15.1-openwrt/include/asm-mips/libgcc.h
|
||||
--- linux-2.6.15.1/include/asm-mips/libgcc.h 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ linux-2.6.15.1-openwrt/include/asm-mips/libgcc.h 2006-01-20 10:32:28.000000000 +0100
|
||||
@@ -0,0 +1,8 @@
|
||||
+#ifndef __ASM_LIBGCC_H
|
||||
+#define __ASM_LIBGCC_H
|
||||
+
|
||||
+#define ARCH_NEEDS_ashldi3
|
||||
+#define ARCH_NEEDS_ashrdi3
|
||||
+#define ARCH_NEEDS_lshrdi3
|
||||
+
|
||||
+#endif /* __ASM_LIBGCC_H */
|
||||
diff -Nur linux-2.6.15.1/include/linux/libgcc.h linux-2.6.15.1-openwrt/include/linux/libgcc.h
|
||||
--- linux-2.6.15.1/include/linux/libgcc.h 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ linux-2.6.15.1-openwrt/include/linux/libgcc.h 2006-01-20 10:33:38.000000000 +0100
|
||||
@@ -0,0 +1,32 @@
|
||||
+#ifndef __LINUX_LIBGCC_H
|
||||
+#define __LINUX_LIBGCC_H
|
||||
+
|
||||
+#include <asm/byteorder.h>
|
||||
+#include <asm/libgcc.h>
|
||||
+
|
||||
+typedef long long DWtype;
|
||||
+typedef int Wtype;
|
||||
+typedef unsigned int UWtype;
|
||||
+typedef int word_type __attribute__ ((mode (__word__)));
|
||||
+
|
||||
+#define BITS_PER_UNIT 8
|
||||
+
|
||||
+#ifdef __BIG_ENDIAN
|
||||
+struct DWstruct {
|
||||
+ Wtype high, low;
|
||||
+};
|
||||
+#elif defined(__LITTLE_ENDIAN)
|
||||
+struct DWstruct {
|
||||
+ Wtype low, high;
|
||||
+};
|
||||
+#else
|
||||
+#error I feel sick.
|
||||
+#endif
|
||||
+
|
||||
+typedef union
|
||||
+{
|
||||
+ struct DWstruct s;
|
||||
+ DWtype ll;
|
||||
+} DWunion;
|
||||
+
|
||||
+#endif /* __LINUX_LIBGCC_H */
|
||||
diff -Nur linux-2.6.15.1/lib/ashldi3.c linux-2.6.15.1-openwrt/lib/ashldi3.c
|
||||
--- linux-2.6.15.1/lib/ashldi3.c 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ linux-2.6.15.1-openwrt/lib/ashldi3.c 2006-01-20 10:38:41.000000000 +0100
|
||||
@@ -0,0 +1,32 @@
|
||||
+#include <linux/libgcc.h>
|
||||
+#include <linux/module.h>
|
||||
+
|
||||
+#ifdef ARCH_NEEDS_ashldi3
|
||||
+
|
||||
+DWtype __ashldi3(DWtype u, word_type b)
|
||||
+{
|
||||
+ DWunion uu, w;
|
||||
+ word_type bm;
|
||||
+
|
||||
+ if (b == 0)
|
||||
+ return u;
|
||||
+
|
||||
+ uu.ll = u;
|
||||
+ bm = (sizeof(Wtype) * BITS_PER_UNIT) - b;
|
||||
+
|
||||
+ if (bm <= 0) {
|
||||
+ w.s.low = 0;
|
||||
+ w.s.high = (UWtype) uu.s.low << -bm;
|
||||
+ } else {
|
||||
+ const UWtype carries = (UWtype) uu.s.low >> bm;
|
||||
+
|
||||
+ w.s.low = (UWtype) uu.s.low << b;
|
||||
+ w.s.high = ((UWtype) uu.s.high << b) | carries;
|
||||
+ }
|
||||
+
|
||||
+ return w.ll;
|
||||
+}
|
||||
+
|
||||
+EXPORT_SYMBOL(__ashldi3);
|
||||
+
|
||||
+#endif /* ARCH_NEEDS_ashldi3 */
|
||||
diff -Nur linux-2.6.15.1/lib/ashrdi3.c linux-2.6.15.1-openwrt/lib/ashrdi3.c
|
||||
--- linux-2.6.15.1/lib/ashrdi3.c 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ linux-2.6.15.1-openwrt/lib/ashrdi3.c 2006-01-20 10:39:29.000000000 +0100
|
||||
@@ -0,0 +1,36 @@
|
||||
+#include <linux/libgcc.h>
|
||||
+#include <linux/module.h>
|
||||
+
|
||||
+/* Unless shift functions are defined with full ANSI prototypes,
|
||||
+ parameter b will be promoted to int if word_type is smaller than an int. */
|
||||
+#ifdef ARCH_NEEDS_ashrdi3
|
||||
+
|
||||
+DWtype __ashrdi3(DWtype u, word_type b)
|
||||
+{
|
||||
+ DWunion uu, w;
|
||||
+ word_type bm;
|
||||
+
|
||||
+ if (b == 0)
|
||||
+ return u;
|
||||
+
|
||||
+ uu.ll = u;
|
||||
+ bm = (sizeof(Wtype) * BITS_PER_UNIT) - b;
|
||||
+
|
||||
+ if (bm <= 0) {
|
||||
+ /* w.s.high = 1..1 or 0..0 */
|
||||
+ w.s.high =
|
||||
+ uu.s.high >> (sizeof(Wtype) * BITS_PER_UNIT - 1);
|
||||
+ w.s.low = uu.s.high >> -bm;
|
||||
+ } else {
|
||||
+ const UWtype carries = (UWtype) uu.s.high << bm;
|
||||
+
|
||||
+ w.s.high = uu.s.high >> b;
|
||||
+ w.s.low = ((UWtype) uu.s.low >> b) | carries;
|
||||
+ }
|
||||
+
|
||||
+ return w.ll;
|
||||
+}
|
||||
+
|
||||
+EXPORT_SYMBOL(__ashrdi3);
|
||||
+
|
||||
+#endif /* ARCH_NEEDS_ashrdi3 */
|
||||
diff -Nur linux-2.6.15.1/lib/lshrdi3.c linux-2.6.15.1-openwrt/lib/lshrdi3.c
|
||||
--- linux-2.6.15.1/lib/lshrdi3.c 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ linux-2.6.15.1-openwrt/lib/lshrdi3.c 2006-01-20 10:40:10.000000000 +0100
|
||||
@@ -0,0 +1,34 @@
|
||||
+#include <linux/libgcc.h>
|
||||
+#include <linux/module.h>
|
||||
+
|
||||
+/* Unless shift functions are defined with full ANSI prototypes,
|
||||
+ parameter b will be promoted to int if word_type is smaller than an int. */
|
||||
+#ifdef ARCH_NEEDS_lshrdi3
|
||||
+
|
||||
+DWtype __lshrdi3(DWtype u, word_type b)
|
||||
+{
|
||||
+ DWunion uu, w;
|
||||
+ word_type bm;
|
||||
+
|
||||
+ if (b == 0)
|
||||
+ return u;
|
||||
+
|
||||
+ uu.ll = u;
|
||||
+ bm = (sizeof(Wtype) * BITS_PER_UNIT) - b;
|
||||
+
|
||||
+ if (bm <= 0) {
|
||||
+ w.s.high = 0;
|
||||
+ w.s.low = (UWtype) uu.s.high >> -bm;
|
||||
+ } else {
|
||||
+ const UWtype carries = (UWtype) uu.s.high << bm;
|
||||
+
|
||||
+ w.s.high = (UWtype) uu.s.high >> b;
|
||||
+ w.s.low = ((UWtype) uu.s.low >> b) | carries;
|
||||
+ }
|
||||
+
|
||||
+ return w.ll;
|
||||
+}
|
||||
+
|
||||
+EXPORT_SYMBOL(__lshrdi3);
|
||||
+
|
||||
+#endif /* ARCH_NEEDS_lshrdi3 */
|
||||
diff -Nur linux-2.6.15.1/lib/Makefile linux-2.6.15.1-openwrt/lib/Makefile
|
||||
--- linux-2.6.15.1/lib/Makefile 2006-01-15 07:16:02.000000000 +0100
|
||||
+++ linux-2.6.15.1-openwrt/lib/Makefile 2006-01-20 10:34:19.000000000 +0100
|
||||
@@ -8,6 +8,7 @@
|
||||
sha1.o
|
||||
|
||||
lib-y += kobject.o kref.o kobject_uevent.o klist.o
|
||||
+obj-y += ashldi3.o ashrdi3.o lshrdi3.o
|
||||
|
||||
obj-y += sort.o parser.o halfmd4.o
|
||||
|
||||
diff -Nur linux-2.6.15.1/include/asm-arm/libgcc.h linux-2.6.15.1-openwrt/include/asm-arm/libgcc.h
|
||||
--- linux-2.6.15.1/include/asm-arm/libgcc.h 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ linux-2.6.15.1-openwrt/include/asm-arm/libgcc.h 2006-04-12 23:01:18.000000000 +0200
|
||||
@@ -0,0 +1,8 @@
|
||||
+#ifndef __ASM_LIBGCC_H
|
||||
+#define __ASM_LIBGCC_H
|
||||
+
|
||||
+#undef ARCH_NEEDS_ashldi3
|
||||
+#undef ARCH_NEEDS_ashrdi3
|
||||
+#undef ARCH_NEEDS_lshrdi3
|
||||
+
|
||||
+#endif /* __ASM_LIBGCC_H */
|
||||
11
target/linux/generic-2.6/patches/006-gcc4_inline_fix.patch
Normal file
11
target/linux/generic-2.6/patches/006-gcc4_inline_fix.patch
Normal file
@@ -0,0 +1,11 @@
|
||||
--- linux-2.6.15.1.old/include/asm-mips/system.h 2006-01-28 15:02:54.481032280 +0100
|
||||
+++ linux-2.6.15.1.dev/include/asm-mips/system.h 2006-01-28 14:47:51.634285848 +0100
|
||||
@@ -273,7 +273,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:
|
||||
@@ -0,0 +1,22 @@
|
||||
diff -Nur linux-2.6.16/fs/squashfs/Makefile linux-2.6.16-owrt/fs/squashfs/Makefile
|
||||
--- linux-2.6.16/fs/squashfs/Makefile 2006-03-21 13:50:31.000000000 +0100
|
||||
+++ linux-2.6.16-owrt/fs/squashfs/Makefile 2006-03-21 13:51:09.000000000 +0100
|
||||
@@ -4,5 +4,4 @@
|
||||
|
||||
obj-$(CONFIG_SQUASHFS) += squashfs.o
|
||||
squashfs-y += inode.o
|
||||
-squashfs-y += squashfs2_0.o
|
||||
squashfs-y += LzmaDecode.o
|
||||
diff -Nur linux-2.6.16/fs/squashfs/squashfs.h linux-2.6.16-owrt/fs/squashfs/squashfs.h
|
||||
--- linux-2.6.16/fs/squashfs/squashfs.h 2006-03-21 10:55:59.000000000 +0100
|
||||
+++ linux-2.6.16-owrt/fs/squashfs/squashfs.h 2006-03-21 13:50:58.000000000 +0100
|
||||
@@ -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)
|
||||
15
target/linux/generic-2.6/patches/011-mips_boot.patch
Normal file
15
target/linux/generic-2.6/patches/011-mips_boot.patch
Normal file
@@ -0,0 +1,15 @@
|
||||
diff -Nur linux-cvs/arch/mips/kernel/head.S linux-aruba/arch/mips/kernel/head.S
|
||||
--- linux-cvs/arch/mips/kernel/head.S 2004-12-23 00:21:39.000000000 -0800
|
||||
+++ linux-aruba/arch/mips/kernel/head.S 2005-10-20 09:16:08.000000000 -0700
|
||||
@@ -122,6 +122,10 @@
|
||||
#endif
|
||||
.endm
|
||||
|
||||
+
|
||||
+ j kernel_entry
|
||||
+ nop
|
||||
+
|
||||
/*
|
||||
* Reserved space for exception handlers.
|
||||
* Necessary for machines which link their kernels at KSEG0.
|
||||
|
||||
2071
target/linux/generic-2.6/patches/100-netfilter_layer7_2.1nbd.patch
Normal file
2071
target/linux/generic-2.6/patches/100-netfilter_layer7_2.1nbd.patch
Normal file
File diff suppressed because it is too large
Load Diff
935
target/linux/generic-2.6/patches/101-ipp2p_0.8.1rc1.patch
Normal file
935
target/linux/generic-2.6/patches/101-ipp2p_0.8.1rc1.patch
Normal file
@@ -0,0 +1,935 @@
|
||||
diff -Nur linux-2.6.17/include/linux/netfilter_ipv4/ipt_ipp2p.h linux-2.6.17-owrt/include/linux/netfilter_ipv4/ipt_ipp2p.h
|
||||
--- linux-2.6.17/include/linux/netfilter_ipv4/ipt_ipp2p.h 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ linux-2.6.17-owrt/include/linux/netfilter_ipv4/ipt_ipp2p.h 2006-06-18 12:37:14.000000000 +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 -Nur linux-2.6.17/net/ipv4/netfilter/ipt_ipp2p.c linux-2.6.17-owrt/net/ipv4/netfilter/ipt_ipp2p.c
|
||||
--- linux-2.6.17/net/ipv4/netfilter/ipt_ipp2p.c 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ linux-2.6.17-owrt/net/ipv4/netfilter/ipt_ipp2p.c 2006-06-18 12:37:14.000000000 +0200
|
||||
@@ -0,0 +1,868 @@
|
||||
+#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,
|
||||
+ const void *matchinfo,
|
||||
+ int offset,
|
||||
+
|
||||
+#if 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 = skb->nh.iph;
|
||||
+ 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,
|
||||
+ const struct ipt_ip *ip,
|
||||
+ void *matchinfo,
|
||||
+ unsigned int matchsize,
|
||||
+ 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,
|
||||
+ .checkentry = &checkentry,
|
||||
+ .me = THIS_MODULE,
|
||||
+#endif
|
||||
+};
|
||||
+
|
||||
+
|
||||
+static int __init init(void)
|
||||
+{
|
||||
+ printk(KERN_INFO "IPP2P v%s loading\n", IPP2P_VERSION);
|
||||
+ return ipt_register_match(&ipp2p_match);
|
||||
+}
|
||||
+
|
||||
+static void __exit fini(void)
|
||||
+{
|
||||
+ ipt_unregister_match(&ipp2p_match);
|
||||
+ printk(KERN_INFO "IPP2P v%s unloaded\n", IPP2P_VERSION);
|
||||
+}
|
||||
+
|
||||
+module_init(init);
|
||||
+module_exit(fini);
|
||||
+
|
||||
+
|
||||
diff -Nur linux-2.6.17/net/ipv4/netfilter/Kconfig linux-2.6.17-owrt/net/ipv4/netfilter/Kconfig
|
||||
--- linux-2.6.17/net/ipv4/netfilter/Kconfig 2006-06-18 12:36:55.000000000 +0200
|
||||
+++ linux-2.6.17-owrt/net/ipv4/netfilter/Kconfig 2006-06-18 12:37:14.000000000 +0200
|
||||
@@ -222,6 +222,12 @@
|
||||
|
||||
To compile it as a module, choose M here. If unsure, say N.
|
||||
|
||||
+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 -Nur linux-2.6.17/net/ipv4/netfilter/Makefile linux-2.6.17-owrt/net/ipv4/netfilter/Makefile
|
||||
--- linux-2.6.17/net/ipv4/netfilter/Makefile 2006-06-18 12:36:55.000000000 +0200
|
||||
+++ linux-2.6.17-owrt/net/ipv4/netfilter/Makefile 2006-06-18 12:38:11.000000000 +0200
|
||||
@@ -61,7 +61,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
|
||||
@@ -0,0 +1,171 @@
|
||||
diff -Nur linux-2.6.16/include/net/xfrmudp.h linux-2.6.16-owrt/include/net/xfrmudp.h
|
||||
--- linux-2.6.16/include/net/xfrmudp.h 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ linux-2.6.16-owrt/include/net/xfrmudp.h 2006-03-22 21:39:54.000000000 +0100
|
||||
@@ -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 -Nur linux-2.6.16/net/ipv4/Kconfig linux-2.6.16-owrt/net/ipv4/Kconfig
|
||||
--- linux-2.6.16/net/ipv4/Kconfig 2006-03-20 06:53:29.000000000 +0100
|
||||
+++ linux-2.6.16-owrt/net/ipv4/Kconfig 2006-03-22 21:49:04.000000000 +0100
|
||||
@@ -271,6 +271,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 -Nur linux-2.6.16/net/ipv4/udp.c linux-2.6.16-owrt/net/ipv4/udp.c
|
||||
--- linux-2.6.16/net/ipv4/udp.c 2006-03-20 06:53:29.000000000 +0100
|
||||
+++ linux-2.6.16-owrt/net/ipv4/udp.c 2006-03-22 21:39:54.000000000 +0100
|
||||
@@ -109,11 +109,14 @@
|
||||
#include <net/inet_common.h>
|
||||
#include <net/checksum.h>
|
||||
#include <net/xfrm.h>
|
||||
+#include <net/xfrmudp.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];
|
||||
@@ -882,6 +885,42 @@
|
||||
sk_common_release(sk);
|
||||
}
|
||||
|
||||
+#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 the UDP system should process it
|
||||
* 0 if we should drop this packet
|
||||
@@ -889,9 +928,9 @@
|
||||
*/
|
||||
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
|
||||
+#else /* either CONFIG_XFRM or CONFIG_IPSEC_NAT_TRAVERSAL */
|
||||
struct udp_sock *up = udp_sk(sk);
|
||||
struct udphdr *uh = skb->h.uh;
|
||||
struct iphdr *iph;
|
||||
@@ -903,11 +942,11 @@
|
||||
|
||||
/* if we're overly short, let UDP handle it */
|
||||
if (udpdata > skb->tail)
|
||||
- return 1;
|
||||
+ return 2;
|
||||
|
||||
/* if this is not encapsulated socket, then just return now */
|
||||
if (!encap_type)
|
||||
- return 1;
|
||||
+ return 3;
|
||||
|
||||
len = skb->tail - udpdata;
|
||||
|
||||
@@ -922,7 +961,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. */
|
||||
@@ -935,7 +974,7 @@
|
||||
len = sizeof(struct udphdr) + 2 * sizeof(u32);
|
||||
} else
|
||||
/* Must be an IKE packet.. pass it through */
|
||||
- return 1;
|
||||
+ return 5;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -946,6 +985,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 = skb->nh.iph;
|
||||
@@ -1010,9 +1051,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);
|
||||
+ if(xfrm4_rcv_encap_func != NULL) {
|
||||
+ ret = (*xfrm4_rcv_encap_func)(skb, up->encap_type);
|
||||
+ UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS);
|
||||
+ } else {
|
||||
+ UDP_INC_STATS_BH(UDP_MIB_INERRORS);
|
||||
+ ret = 1;
|
||||
+ }
|
||||
return -ret;
|
||||
}
|
||||
/* FALLTHROUGH -- it's a UDP Packet */
|
||||
@@ -1559,3 +1604,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
|
||||
+
|
||||
5739
target/linux/generic-2.6/patches/103-netfilter-ipset.patch
Normal file
5739
target/linux/generic-2.6/patches/103-netfilter-ipset.patch
Normal file
File diff suppressed because it is too large
Load Diff
241
target/linux/generic-2.6/patches/105-netfilter_time.patch
Normal file
241
target/linux/generic-2.6/patches/105-netfilter_time.patch
Normal file
@@ -0,0 +1,241 @@
|
||||
diff -urN linux-2.6.15-rc6.orig/net/ipv4/netfilter/ipt_time.c linux-2.6.15-rc6/net/ipv4/netfilter/ipt_time.c
|
||||
--- linux-2.6.15-rc6.orig/net/ipv4/netfilter/ipt_time.c 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ linux-2.6.15-rc6/net/ipv4/netfilter/ipt_time.c 2006-01-07 13:02:59.000000000 +0100
|
||||
@@ -0,0 +1,178 @@
|
||||
+/*
|
||||
+ 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 void *matchinfo,
|
||||
+ int offset,
|
||||
+ int *hotdrop)
|
||||
+{
|
||||
+ const struct ipt_time_info *info = matchinfo; /* match info for rule */
|
||||
+ 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.off_sec == 0)
|
||||
+ __net_timestamp((struct sk_buff *)skb);
|
||||
+
|
||||
+ /* First we make sure we are in the date start-stop boundaries */
|
||||
+ if ((skb->tstamp.off_sec < info->date_start) || (skb->tstamp.off_sec > info->date_stop))
|
||||
+ return 0; /* We are outside the date boundaries */
|
||||
+
|
||||
+ /* Transform the timestamp of the packet, in a human readable form */
|
||||
+ localtime(skb->tstamp.off_sec, ¤ttime);
|
||||
+
|
||||
+ /* 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 struct ipt_ip *ip,
|
||||
+ void *matchinfo,
|
||||
+ unsigned int matchsize,
|
||||
+ 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;
|
||||
+ }
|
||||
+
|
||||
+ /* Check the size */
|
||||
+ if (matchsize != IPT_ALIGN(sizeof(struct ipt_time_info)))
|
||||
+ 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,
|
||||
+ .checkentry = &checkentry,
|
||||
+ .me = THIS_MODULE
|
||||
+};
|
||||
+
|
||||
+static int __init init(void)
|
||||
+{
|
||||
+ printk("ipt_time loading\n");
|
||||
+ return ipt_register_match(&time_match);
|
||||
+}
|
||||
+
|
||||
+static void __exit fini(void)
|
||||
+{
|
||||
+ ipt_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.15-rc6.orig/net/ipv4/netfilter/Kconfig linux-2.6.15-rc6/net/ipv4/netfilter/Kconfig
|
||||
--- linux-2.6.15-rc6.orig/net/ipv4/netfilter/Kconfig 2006-01-07 13:00:21.000000000 +0100
|
||||
+++ linux-2.6.15-rc6/net/ipv4/netfilter/Kconfig 2006-01-07 13:05:07.000000000 +0100
|
||||
@@ -278,6 +278,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.15-rc6.orig/net/ipv4/netfilter/Makefile linux-2.6.15-rc6/net/ipv4/netfilter/Makefile
|
||||
--- linux-2.6.15-rc6.orig/net/ipv4/netfilter/Makefile 2006-01-07 13:00:21.000000000 +0100
|
||||
+++ linux-2.6.15-rc6/net/ipv4/netfilter/Makefile 2006-01-07 13:03:50.000000000 +0100
|
||||
@@ -58,6 +58,7 @@
|
||||
obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.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_DSCP) += ipt_dscp.o
|
||||
diff -urN linux-2.6.15-rc6.orig/include/linux/netfilter_ipv4/ipt_time.h linux-2.6.15-rc6/include/linux/netfilter_ipv4/ipt_time.h
|
||||
--- linux-2.6.15-rc6.orig/include/linux/netfilter_ipv4/ipt_time.h 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ linux-2.6.15-rc6/include/linux/netfilter_ipv4/ipt_time.h 2006-01-07 13:02:14.000000000 +0100
|
||||
@@ -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__ */
|
||||
885
target/linux/generic-2.6/patches/106-netfilter_imq.patch
Normal file
885
target/linux/generic-2.6/patches/106-netfilter_imq.patch
Normal file
@@ -0,0 +1,885 @@
|
||||
diff -Nur linux-2.6.16/drivers/net/imq.c linux-2.6.16-owrt/drivers/net/imq.c
|
||||
--- linux-2.6.16/drivers/net/imq.c 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ linux-2.6.16-owrt/drivers/net/imq.c 2006-03-20 12:59:23.000000000 +0100
|
||||
@@ -0,0 +1,403 @@
|
||||
+/*
|
||||
+ * 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/config.h>
|
||||
+#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>
|
||||
+
|
||||
+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_restart(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 -Nur linux-2.6.16/drivers/net/Kconfig linux-2.6.16-owrt/drivers/net/Kconfig
|
||||
--- linux-2.6.16/drivers/net/Kconfig 2006-03-20 06:53:29.000000000 +0100
|
||||
+++ linux-2.6.16-owrt/drivers/net/Kconfig 2006-03-20 12:59:23.000000000 +0100
|
||||
@@ -93,6 +93,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 -Nur linux-2.6.16/drivers/net/Makefile linux-2.6.16-owrt/drivers/net/Makefile
|
||||
--- linux-2.6.16/drivers/net/Makefile 2006-03-20 06:53:29.000000000 +0100
|
||||
+++ linux-2.6.16-owrt/drivers/net/Makefile 2006-03-20 13:00:13.000000000 +0100
|
||||
@@ -125,6 +125,7 @@
|
||||
endif
|
||||
|
||||
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 -Nur linux-2.6.16/include/linux/imq.h linux-2.6.16-owrt/include/linux/imq.h
|
||||
--- linux-2.6.16/include/linux/imq.h 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ linux-2.6.16-owrt/include/linux/imq.h 2006-03-20 12:59:23.000000000 +0100
|
||||
@@ -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 -Nur linux-2.6.16/include/linux/netfilter_ipv4/ipt_IMQ.h linux-2.6.16-owrt/include/linux/netfilter_ipv4/ipt_IMQ.h
|
||||
--- linux-2.6.16/include/linux/netfilter_ipv4/ipt_IMQ.h 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ linux-2.6.16-owrt/include/linux/netfilter_ipv4/ipt_IMQ.h 2006-03-20 12:59:23.000000000 +0100
|
||||
@@ -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 -Nur linux-2.6.16/include/linux/netfilter_ipv6/ip6t_IMQ.h linux-2.6.16-owrt/include/linux/netfilter_ipv6/ip6t_IMQ.h
|
||||
--- linux-2.6.16/include/linux/netfilter_ipv6/ip6t_IMQ.h 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ linux-2.6.16-owrt/include/linux/netfilter_ipv6/ip6t_IMQ.h 2006-03-20 12:59:23.000000000 +0100
|
||||
@@ -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 -Nur linux-2.6.16/include/linux/skbuff.h linux-2.6.16-owrt/include/linux/skbuff.h
|
||||
--- linux-2.6.16/include/linux/skbuff.h 2006-03-20 06:53:29.000000000 +0100
|
||||
+++ linux-2.6.16-owrt/include/linux/skbuff.h 2006-03-20 12:59:23.000000000 +0100
|
||||
@@ -275,6 +275,10 @@
|
||||
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
|
||||
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 -Nur linux-2.6.16/net/core/skbuff.c linux-2.6.16-owrt/net/core/skbuff.c
|
||||
--- linux-2.6.16/net/core/skbuff.c 2006-03-20 06:53:29.000000000 +0100
|
||||
+++ linux-2.6.16-owrt/net/core/skbuff.c 2006-03-20 12:59:23.000000000 +0100
|
||||
@@ -425,6 +425,10 @@
|
||||
C(nfct_reasm);
|
||||
nf_conntrack_get_reasm(skb->nfct_reasm);
|
||||
#endif
|
||||
+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
|
||||
+ C(imq_flags);
|
||||
+ C(nf_info);
|
||||
+#endif /*CONFIG_IMQ*/
|
||||
#ifdef CONFIG_BRIDGE_NETFILTER
|
||||
C(nf_bridge);
|
||||
nf_bridge_get(skb->nf_bridge);
|
||||
@@ -489,6 +493,10 @@
|
||||
#if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE)
|
||||
new->ipvs_property = old->ipvs_property;
|
||||
#endif
|
||||
+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
|
||||
+ new->imq_flags = old->imq_flags;
|
||||
+ new->nf_info = old->nf_info;
|
||||
+#endif /*CONFIG_IMQ*/
|
||||
#ifdef CONFIG_BRIDGE_NETFILTER
|
||||
new->nf_bridge = old->nf_bridge;
|
||||
nf_bridge_get(old->nf_bridge);
|
||||
diff -Nur linux-2.6.16/net/ipv4/netfilter/ipt_IMQ.c linux-2.6.16-owrt/net/ipv4/netfilter/ipt_IMQ.c
|
||||
--- linux-2.6.16/net/ipv4/netfilter/ipt_IMQ.c 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ linux-2.6.16-owrt/net/ipv4/netfilter/ipt_IMQ.c 2006-03-20 12:59:23.000000000 +0100
|
||||
@@ -0,0 +1,80 @@
|
||||
+/*
|
||||
+ * 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 void *targinfo,
|
||||
+ void *userdata)
|
||||
+{
|
||||
+ 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 struct ipt_entry *e,
|
||||
+ void *targinfo,
|
||||
+ unsigned int targinfosize,
|
||||
+ unsigned int hook_mask)
|
||||
+{
|
||||
+ struct ipt_imq_info *mr;
|
||||
+
|
||||
+ if (targinfosize != IPT_ALIGN(sizeof(struct ipt_imq_info))) {
|
||||
+ printk(KERN_WARNING "IMQ: invalid targinfosize\n");
|
||||
+ return 0;
|
||||
+ }
|
||||
+ mr = (struct ipt_imq_info*)targinfo;
|
||||
+
|
||||
+ if (strcmp(tablename, "mangle") != 0) {
|
||||
+ printk(KERN_WARNING
|
||||
+ "IMQ: IMQ can only be called from \"mangle\" table, not \"%s\"\n",
|
||||
+ tablename);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ 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,
|
||||
+ .checkentry = imq_checkentry,
|
||||
+ .me = THIS_MODULE
|
||||
+};
|
||||
+
|
||||
+static int __init init(void)
|
||||
+{
|
||||
+ if (ipt_register_target(&ipt_imq_reg))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void __exit fini(void)
|
||||
+{
|
||||
+ ipt_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 -Nur linux-2.6.16/net/ipv4/netfilter/Kconfig linux-2.6.16-owrt/net/ipv4/netfilter/Kconfig
|
||||
--- linux-2.6.16/net/ipv4/netfilter/Kconfig 2006-03-20 12:58:53.000000000 +0100
|
||||
+++ linux-2.6.16-owrt/net/ipv4/netfilter/Kconfig 2006-03-20 12:59:23.000000000 +0100
|
||||
@@ -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_LOG
|
||||
tristate "LOG target support"
|
||||
depends on IP_NF_IPTABLES
|
||||
diff -Nur linux-2.6.16/net/ipv4/netfilter/Makefile linux-2.6.16-owrt/net/ipv4/netfilter/Makefile
|
||||
--- linux-2.6.16/net/ipv4/netfilter/Makefile 2006-03-20 12:58:53.000000000 +0100
|
||||
+++ linux-2.6.16-owrt/net/ipv4/netfilter/Makefile 2006-03-20 13:01:12.000000000 +0100
|
||||
@@ -67,6 +67,7 @@
|
||||
obj-$(CONFIG_IP_NF_TARGET_TOS) += ipt_TOS.o
|
||||
obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
|
||||
obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.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 -Nur linux-2.6.16/net/ipv6/netfilter/ip6t_IMQ.c linux-2.6.16-owrt/net/ipv6/netfilter/ip6t_IMQ.c
|
||||
--- linux-2.6.16/net/ipv6/netfilter/ip6t_IMQ.c 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ linux-2.6.16-owrt/net/ipv6/netfilter/ip6t_IMQ.c 2006-03-20 12:59:23.000000000 +0100
|
||||
@@ -0,0 +1,80 @@
|
||||
+/*
|
||||
+ * 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,
|
||||
+ unsigned int hooknum,
|
||||
+ const struct net_device *in,
|
||||
+ const struct net_device *out,
|
||||
+ const void *targinfo,
|
||||
+ void *userdata)
|
||||
+{
|
||||
+ 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 struct ip6t_entry *e,
|
||||
+ void *targinfo,
|
||||
+ unsigned int targinfosize,
|
||||
+ unsigned int hook_mask)
|
||||
+{
|
||||
+ struct ip6t_imq_info *mr;
|
||||
+
|
||||
+ if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_imq_info))) {
|
||||
+ printk(KERN_WARNING "IMQ: invalid targinfosize\n");
|
||||
+ return 0;
|
||||
+ }
|
||||
+ mr = (struct ip6t_imq_info*)targinfo;
|
||||
+
|
||||
+ if (strcmp(tablename, "mangle") != 0) {
|
||||
+ printk(KERN_WARNING
|
||||
+ "IMQ: IMQ can only be called from \"mangle\" table, not \"%s\"\n",
|
||||
+ tablename);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ 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,
|
||||
+ .checkentry = imq_checkentry,
|
||||
+ .me = THIS_MODULE
|
||||
+};
|
||||
+
|
||||
+static int __init init(void)
|
||||
+{
|
||||
+ if (ip6t_register_target(&ip6t_imq_reg))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void __exit fini(void)
|
||||
+{
|
||||
+ ip6t_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 -Nur linux-2.6.16/net/ipv6/netfilter/Kconfig linux-2.6.16-owrt/net/ipv6/netfilter/Kconfig
|
||||
--- linux-2.6.16/net/ipv6/netfilter/Kconfig 2006-03-20 06:53:29.000000000 +0100
|
||||
+++ linux-2.6.16-owrt/net/ipv6/netfilter/Kconfig 2006-03-20 12:59:23.000000000 +0100
|
||||
@@ -154,6 +154,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_LOG
|
||||
tristate "LOG target support"
|
||||
depends on IP6_NF_FILTER
|
||||
diff -Nur linux-2.6.16/net/ipv6/netfilter/Makefile linux-2.6.16-owrt/net/ipv6/netfilter/Makefile
|
||||
--- linux-2.6.16/net/ipv6/netfilter/Makefile 2006-03-20 06:53:29.000000000 +0100
|
||||
+++ linux-2.6.16-owrt/net/ipv6/netfilter/Makefile 2006-03-20 13:02:14.000000000 +0100
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
# Link order matters here.
|
||||
obj-$(CONFIG_IP6_NF_IPTABLES) += ip6_tables.o
|
||||
+obj-$(CONFIG_IP6_NF_TARGET_IMQ) += ip6t_IMQ.o
|
||||
obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o
|
||||
obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o
|
||||
obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o
|
||||
diff -Nur linux-2.6.16/net/sched/sch_generic.c linux-2.6.16-owrt/net/sched/sch_generic.c
|
||||
--- linux-2.6.16/net/sched/sch_generic.c 2006-03-20 06:53:29.000000000 +0100
|
||||
+++ linux-2.6.16-owrt/net/sched/sch_generic.c 2006-03-20 12:59:23.000000000 +0100
|
||||
@@ -29,6 +29,9 @@
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
|
||||
+#include <linux/imq.h>
|
||||
+#endif
|
||||
#include <linux/init.h>
|
||||
#include <linux/rcupdate.h>
|
||||
#include <linux/list.h>
|
||||
@@ -136,7 +139,13 @@
|
||||
|
||||
if (!netif_queue_stopped(dev)) {
|
||||
int ret;
|
||||
- if (netdev_nit)
|
||||
+
|
||||
+ if (netdev_nit
|
||||
+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
|
||||
+ && !(skb->imq_flags & IMQ_F_ENQUEUE)
|
||||
+#endif
|
||||
+ )
|
||||
+
|
||||
dev_queue_xmit_nit(skb, dev);
|
||||
|
||||
ret = dev->hard_start_xmit(skb, dev);
|
||||
830
target/linux/generic-2.6/patches/107-netfilter_nat_sip.patch
Normal file
830
target/linux/generic-2.6/patches/107-netfilter_nat_sip.patch
Normal file
@@ -0,0 +1,830 @@
|
||||
diff -urN linux-2.6.16.4/net/ipv4/netfilter/ip_conntrack_sip.c linux-2.6.16.4.new/net/ipv4/netfilter/ip_conntrack_sip.c
|
||||
--- linux-2.6.16.4/net/ipv4/netfilter/ip_conntrack_sip.c 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ linux-2.6.16.4.new/net/ipv4/netfilter/ip_conntrack_sip.c 2006-04-12 17:31:44.000000000 +0200
|
||||
@@ -0,0 +1,414 @@
|
||||
+/* SIP extension for IP connection tracking.
|
||||
+ *
|
||||
+ * (C) 2005 by Christian Hentschel <chentschel@arnet.com.ar>
|
||||
+ * based on RR's ip_conntrack_ftp.c and other modules.
|
||||
+ *
|
||||
+ * 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/config.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/netfilter.h>
|
||||
+#include <linux/ip.h>
|
||||
+#include <linux/ctype.h>
|
||||
+#include <linux/in.h>
|
||||
+#include <linux/udp.h>
|
||||
+#include <net/checksum.h>
|
||||
+#include <net/udp.h>
|
||||
+
|
||||
+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
|
||||
+#include <linux/netfilter_ipv4/ip_conntrack_sip.h>
|
||||
+
|
||||
+MODULE_LICENSE("GPL");
|
||||
+MODULE_AUTHOR("Christian Hentschel <chentschel@arnet.com.ar>");
|
||||
+MODULE_DESCRIPTION("SIP connection tracking helper");
|
||||
+
|
||||
+static DEFINE_SPINLOCK(sipbf_lock);
|
||||
+
|
||||
+
|
||||
+#define MAX_PORTS 8
|
||||
+static int ports[MAX_PORTS];
|
||||
+static int ports_c;
|
||||
+module_param_array(ports, int, &ports_c, 0400);
|
||||
+MODULE_PARM_DESC(ports, " port numbers of sip servers");
|
||||
+
|
||||
+static unsigned int sip_timeout = SIP_TIMEOUT;
|
||||
+
|
||||
+module_param(sip_timeout, int, 0600);
|
||||
+MODULE_PARM_DESC(sip_timeout, "timeout for the master sip session");
|
||||
+
|
||||
+unsigned int (*ip_nat_sip_hook)(struct sk_buff **pskb,
|
||||
+ enum ip_conntrack_info ctinfo,
|
||||
+ struct ip_conntrack *ct,
|
||||
+ const char **dptr);
|
||||
+EXPORT_SYMBOL_GPL(ip_nat_sip_hook);
|
||||
+
|
||||
+unsigned int (*ip_nat_sdp_hook)(struct sk_buff **pskb,
|
||||
+ enum ip_conntrack_info ctinfo,
|
||||
+ struct ip_conntrack_expect *exp,
|
||||
+ const char *dptr);
|
||||
+EXPORT_SYMBOL_GPL(ip_nat_sdp_hook);
|
||||
+
|
||||
+int ct_sip_get_info(const char *dptr, size_t dlen,
|
||||
+ unsigned int *matchoff,
|
||||
+ unsigned int *matchlen,
|
||||
+ struct sip_header_nfo *hnfo);
|
||||
+EXPORT_SYMBOL(ct_sip_get_info);
|
||||
+
|
||||
+#if 0
|
||||
+#define DEBUGP printk
|
||||
+#else
|
||||
+#define DEBUGP(format, args...)
|
||||
+#endif
|
||||
+
|
||||
+static int digits_len(const char *dptr, const char *limit, int *shift);
|
||||
+static int epaddr_len(const char *dptr, const char *limit, int *shift);
|
||||
+static int skp_digits_len(const char *dptr, const char *limit, int *shift);
|
||||
+static int skp_epaddr_len(const char *dptr, const char *limit, int *shift);
|
||||
+
|
||||
+struct sip_header_nfo ct_sip_hdrs[] = {
|
||||
+ { /* Via header */
|
||||
+ "Via:", sizeof("Via:") - 1,
|
||||
+ "\r\nv:", sizeof("\r\nv:") - 1, /* rfc3261 "\r\n" */
|
||||
+ "UDP ", sizeof("UDP ") - 1,
|
||||
+ epaddr_len
|
||||
+ },
|
||||
+ { /* Contact header */
|
||||
+ "Contact:", sizeof("Contact:") - 1,
|
||||
+ "\r\nm:", sizeof("\r\nm:") - 1,
|
||||
+ "sip:", sizeof("sip:") - 1,
|
||||
+ skp_epaddr_len
|
||||
+ },
|
||||
+ { /* Content length header */
|
||||
+ "Content-Length:", sizeof("Content-Length:") - 1,
|
||||
+ "\r\nl:", sizeof("\r\nl:") - 1,
|
||||
+ ":", sizeof(":") - 1,
|
||||
+ skp_digits_len
|
||||
+ },
|
||||
+ { /* SDP media info */
|
||||
+ "\nm=", sizeof("\nm=") - 1,
|
||||
+ "\rm=", sizeof("\rm=") - 1,
|
||||
+ "audio ", sizeof("audio ") - 1,
|
||||
+ digits_len
|
||||
+ },
|
||||
+ { /* SDP owner address*/
|
||||
+ "\no=", sizeof("\no=") - 1,
|
||||
+ "\ro=", sizeof("\ro=") - 1,
|
||||
+ "IN IP4 ", sizeof("IN IP4 ") - 1,
|
||||
+ epaddr_len
|
||||
+ },
|
||||
+ { /* SDP connection info */
|
||||
+ "\nc=", sizeof("\nc=") - 1,
|
||||
+ "\rc=", sizeof("\rc=") - 1,
|
||||
+ "IN IP4 ", sizeof("IN IP4 ") - 1,
|
||||
+ epaddr_len
|
||||
+ },
|
||||
+ { /* Requests headers */
|
||||
+ "sip:", sizeof("sip:") - 1,
|
||||
+ "sip:", sizeof("sip:") - 1, /* yes, i know.. ;) */
|
||||
+ "@", sizeof("@") - 1,
|
||||
+ epaddr_len
|
||||
+ },
|
||||
+ { /* SDP version header */
|
||||
+ "\nv=", sizeof("\nv=") - 1,
|
||||
+ "\rv=", sizeof("\rv=") - 1,
|
||||
+ "=", sizeof("=") - 1,
|
||||
+ digits_len
|
||||
+ }
|
||||
+};
|
||||
+EXPORT_SYMBOL(ct_sip_hdrs);
|
||||
+
|
||||
+
|
||||
+static int digits_len(const char *dptr, const char *limit, int *shift)
|
||||
+{
|
||||
+ int len = 0;
|
||||
+ while (dptr <= limit && isdigit(*dptr)) {
|
||||
+ dptr++;
|
||||
+ len++;
|
||||
+ }
|
||||
+ return len;
|
||||
+}
|
||||
+
|
||||
+/* get digits lenght, skiping blank spaces. */
|
||||
+static int skp_digits_len(const char *dptr, const char *limit, int *shift)
|
||||
+{
|
||||
+ for (; dptr <= limit && *dptr == ' '; dptr++)
|
||||
+ (*shift)++;
|
||||
+
|
||||
+ return digits_len(dptr, limit, shift);
|
||||
+}
|
||||
+
|
||||
+/* Simple ipaddr parser.. */
|
||||
+static int parse_ipaddr(const char *cp, const char **endp,
|
||||
+ uint32_t *ipaddr, const char *limit)
|
||||
+{
|
||||
+ unsigned long int val;
|
||||
+ int i, digit = 0;
|
||||
+
|
||||
+ for (i = 0, *ipaddr = 0; cp <= limit && i < 4; i++) {
|
||||
+ digit = 0;
|
||||
+ if (!isdigit(*cp))
|
||||
+ break;
|
||||
+
|
||||
+ val = simple_strtoul(cp, (char **)&cp, 10);
|
||||
+ if (val > 0xFF)
|
||||
+ return -1;
|
||||
+
|
||||
+ ((uint8_t *)ipaddr)[i] = val;
|
||||
+ digit = 1;
|
||||
+
|
||||
+ if (*cp != '.')
|
||||
+ break;
|
||||
+ cp++;
|
||||
+ }
|
||||
+ if (!digit)
|
||||
+ return -1;
|
||||
+
|
||||
+ if (endp)
|
||||
+ *endp = cp;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/* skip ip address. returns it lenght. */
|
||||
+static int epaddr_len(const char *dptr, const char *limit, int *shift)
|
||||
+{
|
||||
+ const char *aux = dptr;
|
||||
+ uint32_t ip;
|
||||
+
|
||||
+ if (parse_ipaddr(dptr, &dptr, &ip, limit) < 0) {
|
||||
+ DEBUGP("ip: %s parse failed.!\n", dptr);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ /* Port number */
|
||||
+ if (*dptr == ':') {
|
||||
+ dptr++;
|
||||
+ dptr += digits_len(dptr, limit, shift);
|
||||
+ }
|
||||
+ return dptr - aux;
|
||||
+}
|
||||
+
|
||||
+/* get address lenght, skiping user info. */
|
||||
+static int skp_epaddr_len(const char *dptr, const char *limit, int *shift)
|
||||
+{
|
||||
+ for (; dptr <= limit && *dptr != '@'; dptr++)
|
||||
+ (*shift)++;
|
||||
+
|
||||
+ if (*dptr == '@') {
|
||||
+ dptr++;
|
||||
+ (*shift)++;
|
||||
+ return epaddr_len(dptr, limit, shift);
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/* Returns 0 if not found, -1 error parsing. */
|
||||
+int ct_sip_get_info(const char *dptr, size_t dlen,
|
||||
+ unsigned int *matchoff,
|
||||
+ unsigned int *matchlen,
|
||||
+ struct sip_header_nfo *hnfo)
|
||||
+{
|
||||
+ const char *limit, *aux, *k = dptr;
|
||||
+ int shift = 0;
|
||||
+
|
||||
+ limit = dptr + (dlen - hnfo->lnlen);
|
||||
+
|
||||
+ while (dptr <= limit) {
|
||||
+ if ((strncmp(dptr, hnfo->lname, hnfo->lnlen) != 0) &&
|
||||
+ (strncmp(dptr, hnfo->sname, hnfo->snlen) != 0))
|
||||
+ {
|
||||
+ dptr++;
|
||||
+ continue;
|
||||
+ }
|
||||
+ aux = ct_sip_search(hnfo->ln_str, dptr, hnfo->ln_strlen,
|
||||
+ ct_sip_lnlen(dptr, limit));
|
||||
+ if (!aux) {
|
||||
+ DEBUGP("'%s' not found in '%s'.\n", hnfo->ln_str, hnfo->lname);
|
||||
+ return -1;
|
||||
+ }
|
||||
+ aux += hnfo->ln_strlen;
|
||||
+
|
||||
+ *matchlen = hnfo->match_len(aux, limit, &shift);
|
||||
+ if (!*matchlen)
|
||||
+ return -1;
|
||||
+
|
||||
+ *matchoff = (aux - k) + shift;
|
||||
+
|
||||
+ DEBUGP("%s match succeeded! - len: %u\n", hnfo->lname, *matchlen);
|
||||
+ return 1;
|
||||
+ }
|
||||
+ DEBUGP("%s header not found.\n", hnfo->lname);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int set_expected_rtp(struct sk_buff **pskb,
|
||||
+ struct ip_conntrack *ct,
|
||||
+ enum ip_conntrack_info ctinfo,
|
||||
+ uint32_t ipaddr, uint16_t port,
|
||||
+ const char *dptr)
|
||||
+{
|
||||
+ struct ip_conntrack_expect *exp;
|
||||
+ int ret;
|
||||
+
|
||||
+ exp = ip_conntrack_expect_alloc(ct);
|
||||
+ if (exp == NULL)
|
||||
+ return NF_DROP;
|
||||
+
|
||||
+ exp->tuple = ((struct ip_conntrack_tuple)
|
||||
+ { { ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip, { 0 } },
|
||||
+ { ipaddr, { .udp = { htons(port) } }, IPPROTO_UDP }});
|
||||
+
|
||||
+ exp->mask = ((struct ip_conntrack_tuple)
|
||||
+ { { 0xFFFFFFFF, { 0 } },
|
||||
+ { 0xFFFFFFFF, { .udp = { 0xFFFF } }, 0xFF }});
|
||||
+
|
||||
+ exp->expectfn = NULL;
|
||||
+
|
||||
+ if (ip_nat_sdp_hook)
|
||||
+ ret = ip_nat_sdp_hook(pskb, ctinfo, exp, dptr);
|
||||
+ else {
|
||||
+ if (ip_conntrack_expect_related(exp) != 0)
|
||||
+ ret = NF_DROP;
|
||||
+ else
|
||||
+ ret = NF_ACCEPT;
|
||||
+ }
|
||||
+ ip_conntrack_expect_put(exp);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int sip_help(struct sk_buff **pskb,
|
||||
+ struct ip_conntrack *ct,
|
||||
+ enum ip_conntrack_info ctinfo)
|
||||
+{
|
||||
+ unsigned int dataoff, datalen;
|
||||
+ const char *dptr;
|
||||
+ int ret = NF_ACCEPT;
|
||||
+ int matchoff, matchlen;
|
||||
+ uint32_t ipaddr;
|
||||
+ uint16_t port;
|
||||
+
|
||||
+ /* No Data ? */
|
||||
+ dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
|
||||
+ if (dataoff >= (*pskb)->len) {
|
||||
+ DEBUGP("skb->len = %u\n", (*pskb)->len);
|
||||
+ return NF_ACCEPT;
|
||||
+ }
|
||||
+
|
||||
+ ip_ct_refresh(ct, *pskb, sip_timeout * HZ);
|
||||
+
|
||||
+ spin_lock_bh(&sipbf_lock);
|
||||
+
|
||||
+ if ((dataoff + (*pskb)->len - dataoff) <= skb_headlen(*pskb))
|
||||
+ dptr = (*pskb)->data + dataoff;
|
||||
+ else {
|
||||
+ DEBUGP("Copy of skbuff not supported yet.\n");
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ if (ip_nat_sip_hook) {
|
||||
+ if (!ip_nat_sip_hook(pskb, ctinfo, ct, &dptr)) {
|
||||
+ ret = NF_DROP;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if ((ctinfo) >= IP_CT_IS_REPLY)
|
||||
+ goto out;
|
||||
+
|
||||
+ /* After this point NAT, could have mangled skb, so
|
||||
+ we need to recalculate payload lenght. */
|
||||
+ datalen = (*pskb)->len - dataoff;
|
||||
+
|
||||
+ if (datalen < (sizeof("SIP/2.0 200") - 1))
|
||||
+ goto out;
|
||||
+
|
||||
+ /* RTP info only in some SDP pkts */
|
||||
+ if (memcmp(dptr, "INVITE", sizeof("INVITE") - 1) != 0 &&
|
||||
+ memcmp(dptr, "SIP/2.0 200", sizeof("SIP/2.0 200") - 1) != 0) {
|
||||
+ goto out;
|
||||
+ }
|
||||
+ /* Get ip and port address from SDP packet. */
|
||||
+ if (ct_sip_get_info(dptr, datalen, &matchoff, &matchlen,
|
||||
+ &ct_sip_hdrs[POS_CONECTION]) > 0) {
|
||||
+
|
||||
+ /* We'll drop only if there are parse problems. */
|
||||
+ if (parse_ipaddr(dptr + matchoff, NULL, &ipaddr,
|
||||
+ dptr + datalen) < 0) {
|
||||
+ ret = NF_DROP;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ if (ct_sip_get_info(dptr, datalen, &matchoff, &matchlen,
|
||||
+ &ct_sip_hdrs[POS_MEDIA]) > 0) {
|
||||
+
|
||||
+ port = simple_strtoul(dptr + matchoff, NULL, 10);
|
||||
+ if (port < 1024) {
|
||||
+ ret = NF_DROP;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ ret = set_expected_rtp(pskb, ct, ctinfo,
|
||||
+ ipaddr, port, dptr);
|
||||
+ }
|
||||
+ }
|
||||
+out: spin_unlock_bh(&sipbf_lock);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static struct ip_conntrack_helper sip[MAX_PORTS];
|
||||
+static char sip_names[MAX_PORTS][10];
|
||||
+
|
||||
+static void fini(void)
|
||||
+{
|
||||
+ int i = 0;
|
||||
+ for (; i < ports_c; i++) {
|
||||
+ DEBUGP("unregistering helper for port %d\n", ports[i]);
|
||||
+ ip_conntrack_helper_unregister(&sip[i]);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int __init init(void)
|
||||
+{
|
||||
+ int i, ret;
|
||||
+ char *tmpname;
|
||||
+
|
||||
+ if (ports_c == 0)
|
||||
+ ports[ports_c++] = SIP_PORT;
|
||||
+
|
||||
+ for (i = 0; i < ports_c; i++) {
|
||||
+ /* Create helper structure */
|
||||
+ memset(&sip[i], 0, sizeof(struct ip_conntrack_helper));
|
||||
+
|
||||
+ sip[i].tuple.dst.protonum = IPPROTO_UDP;
|
||||
+ sip[i].tuple.src.u.udp.port = htons(ports[i]);
|
||||
+ sip[i].mask.src.u.udp.port = 0xFFFF;
|
||||
+ sip[i].mask.dst.protonum = 0xFF;
|
||||
+ sip[i].max_expected = 1;
|
||||
+ sip[i].timeout = 3 * 60; /* 3 minutes */
|
||||
+ sip[i].me = THIS_MODULE;
|
||||
+ sip[i].help = sip_help;
|
||||
+
|
||||
+ tmpname = &sip_names[i][0];
|
||||
+ if (ports[i] == SIP_PORT)
|
||||
+ sprintf(tmpname, "sip");
|
||||
+ else
|
||||
+ sprintf(tmpname, "sip-%d", i);
|
||||
+ sip[i].name = tmpname;
|
||||
+
|
||||
+ DEBUGP("port #%d: %d\n", i, ports[i]);
|
||||
+
|
||||
+ ret=ip_conntrack_helper_register(&sip[i]);
|
||||
+ if (ret) {
|
||||
+ printk("ERROR registering helper for port %d\n",
|
||||
+ ports[i]);
|
||||
+ fini();
|
||||
+ return(ret);
|
||||
+ }
|
||||
+ }
|
||||
+ return(0);
|
||||
+}
|
||||
+
|
||||
+module_init(init);
|
||||
+module_exit(fini);
|
||||
diff -urN linux-2.6.16.4/net/ipv4/netfilter/ip_nat_sip.c linux-2.6.16.4.new/net/ipv4/netfilter/ip_nat_sip.c
|
||||
--- linux-2.6.16.4/net/ipv4/netfilter/ip_nat_sip.c 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ linux-2.6.16.4.new/net/ipv4/netfilter/ip_nat_sip.c 2006-04-12 17:31:53.000000000 +0200
|
||||
@@ -0,0 +1,249 @@
|
||||
+/* SIP extension for UDP NAT alteration.
|
||||
+ *
|
||||
+ * (C) 2005 by Christian Hentschel <chentschel@arnet.com.ar>
|
||||
+ * based on RR's ip_nat_ftp.c and other modules.
|
||||
+ *
|
||||
+ * 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/netfilter_ipv4.h>
|
||||
+#include <linux/ip.h>
|
||||
+#include <linux/udp.h>
|
||||
+#include <net/udp.h>
|
||||
+
|
||||
+#include <linux/netfilter_ipv4/ip_nat.h>
|
||||
+#include <linux/netfilter_ipv4/ip_nat_helper.h>
|
||||
+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
|
||||
+#include <linux/netfilter_ipv4/ip_conntrack_sip.h>
|
||||
+
|
||||
+MODULE_LICENSE("GPL");
|
||||
+MODULE_AUTHOR("Christian Hentschel <chentschel@arnet.com.ar>");
|
||||
+MODULE_DESCRIPTION("SIP NAT helper");
|
||||
+
|
||||
+#if 0
|
||||
+#define DEBUGP printk
|
||||
+#else
|
||||
+#define DEBUGP(format, args...)
|
||||
+#endif
|
||||
+
|
||||
+extern struct sip_header_nfo ct_sip_hdrs[];
|
||||
+
|
||||
+static unsigned int mangle_sip_packet(struct sk_buff **pskb,
|
||||
+ enum ip_conntrack_info ctinfo,
|
||||
+ struct ip_conntrack *ct,
|
||||
+ const char **dptr, size_t dlen,
|
||||
+ char *buffer, int bufflen,
|
||||
+ struct sip_header_nfo *hnfo)
|
||||
+{
|
||||
+ unsigned int matchlen, matchoff;
|
||||
+
|
||||
+ if (ct_sip_get_info(*dptr, dlen, &matchoff, &matchlen, hnfo) <= 0)
|
||||
+ return 0;
|
||||
+
|
||||
+ if (!ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
|
||||
+ matchoff, matchlen, buffer, bufflen)) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+ /* We need to reload this. Thanks Patrick. */
|
||||
+ *dptr = (*pskb)->data + (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+static unsigned int ip_nat_sip(struct sk_buff **pskb,
|
||||
+ enum ip_conntrack_info ctinfo,
|
||||
+ struct ip_conntrack *ct,
|
||||
+ const char **dptr)
|
||||
+{
|
||||
+ char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
|
||||
+ unsigned int bufflen, dataoff;
|
||||
+ uint32_t ip;
|
||||
+ uint16_t port;
|
||||
+
|
||||
+ dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
|
||||
+
|
||||
+ if ((ctinfo) >= IP_CT_IS_REPLY) {
|
||||
+ ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
|
||||
+ port = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port;
|
||||
+ } else {
|
||||
+ ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
|
||||
+ port = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port;
|
||||
+ }
|
||||
+ bufflen = sprintf(buffer, "%u.%u.%u.%u:%u", NIPQUAD(ip), ntohs(port));
|
||||
+
|
||||
+ /* short packet ? */
|
||||
+ if (((*pskb)->len - dataoff) < (sizeof("SIP/2.0") - 1))
|
||||
+ return 0;
|
||||
+
|
||||
+ /* Basic rules: requests and responses. */
|
||||
+ if (memcmp(*dptr, "SIP/2.0", sizeof("SIP/2.0") - 1) == 0) {
|
||||
+
|
||||
+ if ((ctinfo) < IP_CT_IS_REPLY) {
|
||||
+ mangle_sip_packet(pskb, ctinfo, ct, dptr,
|
||||
+ (*pskb)->len - dataoff, buffer, bufflen,
|
||||
+ &ct_sip_hdrs[POS_CONTACT]);
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ if (!mangle_sip_packet(pskb, ctinfo, ct, dptr, (*pskb)->len - dataoff,
|
||||
+ buffer, bufflen, &ct_sip_hdrs[POS_VIA])) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ /* This search should ignore case, but later.. */
|
||||
+ const char *aux = ct_sip_search("CSeq:", *dptr, sizeof("CSeq:") - 1,
|
||||
+ (*pskb)->len - dataoff);
|
||||
+ if (!aux)
|
||||
+ return 0;
|
||||
+
|
||||
+ if (!ct_sip_search("REGISTER", aux, sizeof("REGISTER"),
|
||||
+ ct_sip_lnlen(aux, *dptr + (*pskb)->len - dataoff))) {
|
||||
+ return 1;
|
||||
+ }
|
||||
+ return mangle_sip_packet(pskb, ctinfo, ct, dptr, (*pskb)->len - dataoff,
|
||||
+ buffer, bufflen, &ct_sip_hdrs[POS_CONTACT]);
|
||||
+ }
|
||||
+ if ((ctinfo) < IP_CT_IS_REPLY) {
|
||||
+ if (!mangle_sip_packet(pskb, ctinfo, ct, dptr, (*pskb)->len - dataoff,
|
||||
+ buffer, bufflen, &ct_sip_hdrs[POS_VIA])) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ /* Mangle Contact if exists only. - watch udp_nat_mangle()! */
|
||||
+ mangle_sip_packet(pskb, ctinfo, ct, dptr, (*pskb)->len - dataoff,
|
||||
+ buffer, bufflen, &ct_sip_hdrs[POS_CONTACT]);
|
||||
+ return 1;
|
||||
+ }
|
||||
+ /* This mangle requests headers. */
|
||||
+ return mangle_sip_packet(pskb, ctinfo, ct, dptr,
|
||||
+ ct_sip_lnlen(*dptr, *dptr + (*pskb)->len - dataoff),
|
||||
+ buffer, bufflen, &ct_sip_hdrs[POS_REQ_HEADER]);
|
||||
+}
|
||||
+
|
||||
+static int mangle_content_len(struct sk_buff **pskb,
|
||||
+ enum ip_conntrack_info ctinfo,
|
||||
+ struct ip_conntrack *ct,
|
||||
+ const char *dptr)
|
||||
+{
|
||||
+ unsigned int dataoff, matchoff, matchlen;
|
||||
+ char buffer[sizeof("65536")];
|
||||
+ int bufflen;
|
||||
+
|
||||
+ dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
|
||||
+
|
||||
+ /* Get actual SDP lenght */
|
||||
+ if (ct_sip_get_info(dptr, (*pskb)->len - dataoff, &matchoff,
|
||||
+ &matchlen, &ct_sip_hdrs[POS_SDP_HEADER]) > 0) {
|
||||
+
|
||||
+ /* since ct_sip_get_info() give us a pointer passing 'v='
|
||||
+ we need to add 2 bytes in this count. */
|
||||
+ int c_len = (*pskb)->len - dataoff - matchoff + 2;
|
||||
+
|
||||
+ /* Now, update SDP lenght */
|
||||
+ if (ct_sip_get_info(dptr, (*pskb)->len - dataoff, &matchoff,
|
||||
+ &matchlen, &ct_sip_hdrs[POS_CONTENT]) > 0) {
|
||||
+
|
||||
+ bufflen = sprintf(buffer, "%u", c_len);
|
||||
+
|
||||
+ return ip_nat_mangle_udp_packet(pskb, ct, ctinfo, matchoff,
|
||||
+ matchlen, buffer, bufflen);
|
||||
+ }
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static unsigned int mangle_sdp(struct sk_buff **pskb,
|
||||
+ enum ip_conntrack_info ctinfo,
|
||||
+ struct ip_conntrack *ct,
|
||||
+ uint32_t newip, uint16_t port,
|
||||
+ const char *dptr)
|
||||
+{
|
||||
+ char buffer[sizeof("nnn.nnn.nnn.nnn")];
|
||||
+ unsigned int dataoff, bufflen;
|
||||
+
|
||||
+ dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
|
||||
+
|
||||
+ /* Mangle owner and contact info. */
|
||||
+ bufflen = sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(newip));
|
||||
+ if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff,
|
||||
+ buffer, bufflen, &ct_sip_hdrs[POS_OWNER])) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff,
|
||||
+ buffer, bufflen, &ct_sip_hdrs[POS_CONECTION])) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ /* Mangle media port. */
|
||||
+ bufflen = sprintf(buffer, "%u", port);
|
||||
+ if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff,
|
||||
+ buffer, bufflen, &ct_sip_hdrs[POS_MEDIA])) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ return mangle_content_len(pskb, ctinfo, ct, dptr);
|
||||
+}
|
||||
+
|
||||
+/* So, this packet has hit the connection tracking matching code.
|
||||
+ Mangle it, and change the expectation to match the new version. */
|
||||
+static unsigned int ip_nat_sdp(struct sk_buff **pskb,
|
||||
+ enum ip_conntrack_info ctinfo,
|
||||
+ struct ip_conntrack_expect *exp,
|
||||
+ const char *dptr)
|
||||
+{
|
||||
+ struct ip_conntrack *ct = exp->master;
|
||||
+ uint32_t newip;
|
||||
+ uint16_t port;
|
||||
+
|
||||
+ DEBUGP("ip_nat_sdp():\n");
|
||||
+
|
||||
+ /* Connection will come from reply */
|
||||
+ newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
|
||||
+
|
||||
+ exp->tuple.dst.ip = newip;
|
||||
+ exp->saved_proto.udp.port = exp->tuple.dst.u.udp.port;
|
||||
+ exp->dir = IP_CT_DIR_REPLY;
|
||||
+
|
||||
+ /* When you see the packet, we need to NAT it the same as the
|
||||
+ this one. */
|
||||
+ exp->expectfn = ip_nat_follow_master;
|
||||
+
|
||||
+ /* Try to get same port: if not, try to change it. */
|
||||
+ for (port = ntohs(exp->saved_proto.udp.port); port != 0; port++) {
|
||||
+ exp->tuple.dst.u.udp.port = htons(port);
|
||||
+ if (ip_conntrack_expect_related(exp) == 0)
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (port == 0)
|
||||
+ return NF_DROP;
|
||||
+
|
||||
+ if (!mangle_sdp(pskb, ctinfo, ct, newip, port, dptr)) {
|
||||
+ ip_conntrack_unexpect_related(exp);
|
||||
+ return NF_DROP;
|
||||
+ }
|
||||
+ return NF_ACCEPT;
|
||||
+}
|
||||
+
|
||||
+static void __exit fini(void)
|
||||
+{
|
||||
+ ip_nat_sip_hook = NULL;
|
||||
+ ip_nat_sdp_hook = NULL;
|
||||
+ /* Make sure noone calls it, meanwhile. */
|
||||
+ synchronize_net();
|
||||
+}
|
||||
+
|
||||
+static int __init init(void)
|
||||
+{
|
||||
+ BUG_ON(ip_nat_sip_hook);
|
||||
+ BUG_ON(ip_nat_sdp_hook);
|
||||
+ ip_nat_sip_hook = ip_nat_sip;
|
||||
+ ip_nat_sdp_hook = ip_nat_sdp;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+module_init(init);
|
||||
+module_exit(fini);
|
||||
diff -urN linux-2.6.16.4/net/ipv4/netfilter/Kconfig linux-2.6.16.4.new/net/ipv4/netfilter/Kconfig
|
||||
--- linux-2.6.16.4/net/ipv4/netfilter/Kconfig 2006-04-12 17:29:19.000000000 +0200
|
||||
+++ linux-2.6.16.4.new/net/ipv4/netfilter/Kconfig 2006-04-12 17:32:53.000000000 +0200
|
||||
@@ -168,6 +168,19 @@
|
||||
If you want to compile it as a module, say M here and read
|
||||
Documentation/modules.txt. If unsure, say `N'.
|
||||
|
||||
+config IP_NF_SIP
|
||||
+ tristate 'SIP support'
|
||||
+ depends on IP_NF_CONNTRACK
|
||||
+ help
|
||||
+ SIP is an application-layer control protocol that can establish,
|
||||
+ modify, and terminate multimedia sessions (conferences) such as
|
||||
+ Internet telephony calls. With the ip_conntrack_sip and
|
||||
+ the ip_nat_sip modules you can support the protocol on a connection
|
||||
+ tracking/NATing firewall.
|
||||
+
|
||||
+ If you want to compile it as a module, say 'M' here and read
|
||||
+ Documentation/modules.txt. If unsure, say 'N'.
|
||||
+
|
||||
config IP_NF_QUEUE
|
||||
tristate "IP Userspace queueing via NETLINK (OBSOLETE)"
|
||||
help
|
||||
@@ -545,6 +558,12 @@
|
||||
default IP_NF_NAT if IP_NF_PPTP=y
|
||||
default m if IP_NF_PPTP=m
|
||||
|
||||
+config IP_NF_NAT_SIP
|
||||
+ tristate
|
||||
+ depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
|
||||
+ default IP_NF_NAT if IP_NF_SIP=y
|
||||
+ default m if IP_NF_SIP=m
|
||||
+
|
||||
# mangle + specific targets
|
||||
config IP_NF_MANGLE
|
||||
tristate "Packet mangling"
|
||||
diff -urN linux-2.6.16.4/net/ipv4/netfilter/Makefile linux-2.6.16.4.new/net/ipv4/netfilter/Makefile
|
||||
--- linux-2.6.16.4/net/ipv4/netfilter/Makefile 2006-04-12 17:29:19.000000000 +0200
|
||||
+++ linux-2.6.16.4.new/net/ipv4/netfilter/Makefile 2006-04-12 17:33:39.000000000 +0200
|
||||
@@ -28,6 +28,7 @@
|
||||
obj-$(CONFIG_IP_NF_FTP) += ip_conntrack_ftp.o
|
||||
obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o
|
||||
obj-$(CONFIG_IP_NF_NETBIOS_NS) += ip_conntrack_netbios_ns.o
|
||||
+obj-$(CONFIG_IP_NF_SIP) += ip_conntrack_sip.o
|
||||
|
||||
# NAT helpers
|
||||
obj-$(CONFIG_IP_NF_NAT_PPTP) += ip_nat_pptp.o
|
||||
@@ -35,6 +36,7 @@
|
||||
obj-$(CONFIG_IP_NF_NAT_TFTP) += ip_nat_tftp.o
|
||||
obj-$(CONFIG_IP_NF_NAT_FTP) += ip_nat_ftp.o
|
||||
obj-$(CONFIG_IP_NF_NAT_IRC) += ip_nat_irc.o
|
||||
+obj-$(CONFIG_IP_NF_NAT_SIP) += ip_nat_sip.o
|
||||
|
||||
# generic IP tables
|
||||
obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
|
||||
diff -urN linux-2.6.16.4/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.6.16.4.new/include/linux/netfilter_ipv4/ip_conntrack.h
|
||||
--- linux-2.6.16.4/include/linux/netfilter_ipv4/ip_conntrack.h 2006-04-12 17:29:19.000000000 +0200
|
||||
+++ linux-2.6.16.4.new/include/linux/netfilter_ipv4/ip_conntrack.h 2006-04-12 17:30:38.000000000 +0200
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <linux/netfilter_ipv4/ip_conntrack_amanda.h>
|
||||
#include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
|
||||
#include <linux/netfilter_ipv4/ip_conntrack_irc.h>
|
||||
+#include <linux/netfilter_ipv4/ip_conntrack_sip.h>
|
||||
|
||||
/* per conntrack: application helper private data */
|
||||
union ip_conntrack_help {
|
||||
@@ -40,6 +41,7 @@
|
||||
struct ip_ct_pptp_master ct_pptp_info;
|
||||
struct ip_ct_ftp_master ct_ftp_info;
|
||||
struct ip_ct_irc_master ct_irc_info;
|
||||
+ struct ip_ct_sip_master ct_sip_info;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_IP_NF_NAT_NEEDED
|
||||
diff -urN linux-2.6.16.4/include/linux/netfilter_ipv4/ip_conntrack_sip.h linux-2.6.16.4.new/include/linux/netfilter_ipv4/ip_conntrack_sip.h
|
||||
--- linux-2.6.16.4/include/linux/netfilter_ipv4/ip_conntrack_sip.h 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ linux-2.6.16.4.new/include/linux/netfilter_ipv4/ip_conntrack_sip.h 2006-04-12 17:31:12.000000000 +0200
|
||||
@@ -0,0 +1,81 @@
|
||||
+#ifndef __IP_CONNTRACK_SIP_H__
|
||||
+#define __IP_CONNTRACK_SIP_H__
|
||||
+/* SIP tracking. */
|
||||
+
|
||||
+#ifdef __KERNEL__
|
||||
+
|
||||
+#define SIP_PORT 5060
|
||||
+#define SIP_TIMEOUT 3600
|
||||
+
|
||||
+#define POS_VIA 0
|
||||
+#define POS_CONTACT 1
|
||||
+#define POS_CONTENT 2
|
||||
+#define POS_MEDIA 3
|
||||
+#define POS_OWNER 4
|
||||
+#define POS_CONECTION 5
|
||||
+#define POS_REQ_HEADER 6
|
||||
+#define POS_SDP_HEADER 7
|
||||
+
|
||||
+struct ip_ct_sip_master {
|
||||
+};
|
||||
+
|
||||
+struct sip_header_nfo {
|
||||
+ const char *lname;
|
||||
+ size_t lnlen;
|
||||
+ const char *sname;
|
||||
+ size_t snlen;
|
||||
+ const char *ln_str;
|
||||
+ size_t ln_strlen;
|
||||
+ int (*match_len)(const char *, const char *, int *);
|
||||
+
|
||||
+};
|
||||
+
|
||||
+extern unsigned int (*ip_nat_sip_hook)(struct sk_buff **pskb,
|
||||
+ enum ip_conntrack_info ctinfo,
|
||||
+ struct ip_conntrack *ct,
|
||||
+ const char **dptr);
|
||||
+
|
||||
+/* For NAT to hook in when on expect. */
|
||||
+extern unsigned int (*ip_nat_sdp_hook)(struct sk_buff **pskb,
|
||||
+ enum ip_conntrack_info ctinfo,
|
||||
+ struct ip_conntrack_expect *exp,
|
||||
+ const char *dptr);
|
||||
+
|
||||
+extern int ct_sip_get_info(const char *dptr, size_t dlen,
|
||||
+ unsigned int *matchoff,
|
||||
+ unsigned int *matchlen,
|
||||
+ struct sip_header_nfo *hnfo);
|
||||
+
|
||||
+/* get line lenght until first CR or LF seen. */
|
||||
+static __inline__ int ct_sip_lnlen(const char *line, const char *limit)
|
||||
+{
|
||||
+ const char *k = line;
|
||||
+
|
||||
+ while ((line <= limit) && (*line == '\r' || *line == '\n'))
|
||||
+ line++;
|
||||
+
|
||||
+ while (line <= limit) {
|
||||
+ if (*line == '\r' || *line == '\n')
|
||||
+ break;
|
||||
+ line++;
|
||||
+ }
|
||||
+ return line - k;
|
||||
+}
|
||||
+
|
||||
+/* Linear string search, case sensitive. */
|
||||
+static __inline__
|
||||
+const char *ct_sip_search(const char *needle, const char *haystack,
|
||||
+ size_t needle_len, size_t haystack_len)
|
||||
+{
|
||||
+ const char *limit = haystack + (haystack_len - needle_len);
|
||||
+
|
||||
+ while (haystack <= limit) {
|
||||
+ if (memcmp(haystack, needle, needle_len) == 0)
|
||||
+ return haystack;
|
||||
+ haystack++;
|
||||
+ }
|
||||
+ return NULL;
|
||||
+}
|
||||
+#endif /* __KERNEL__ */
|
||||
+
|
||||
+#endif /* __IP_CONNTRACK_SIP_H__ */
|
||||
914
target/linux/generic-2.6/patches/108-netfilter_route.patch
Normal file
914
target/linux/generic-2.6/patches/108-netfilter_route.patch
Normal file
@@ -0,0 +1,914 @@
|
||||
diff -u'rNF^function' linux-2.6.16.7/include/linux/netfilter_ipv4/ipt_ROUTE.h linux-2.6.16.7-ROUTE/include/linux/netfilter_ipv4/ipt_ROUTE.h
|
||||
--- linux-2.6.16.7/include/linux/netfilter_ipv4/ipt_ROUTE.h 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ linux-2.6.16.7-ROUTE/include/linux/netfilter_ipv4/ipt_ROUTE.h 2006-06-14 16:40:49.000000000 +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 -u'rNF^function' linux-2.6.16.7/include/linux/netfilter_ipv6/ip6t_ROUTE.h linux-2.6.16.7-ROUTE/include/linux/netfilter_ipv6/ip6t_ROUTE.h
|
||||
--- linux-2.6.16.7/include/linux/netfilter_ipv6/ip6t_ROUTE.h 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ linux-2.6.16.7-ROUTE/include/linux/netfilter_ipv6/ip6t_ROUTE.h 2006-06-14 16:41:08.000000000 +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 -u'rNF^function' linux-2.6.16.7/net/ipv4/netfilter/Kconfig linux-2.6.16.7-ROUTE/net/ipv4/netfilter/Kconfig
|
||||
--- linux-2.6.16.7/net/ipv4/netfilter/Kconfig 2006-06-14 16:05:44.000000000 +0200
|
||||
+++ linux-2.6.16.7-ROUTE/net/ipv4/netfilter/Kconfig 2006-06-14 16:46:40.000000000 +0200
|
||||
@@ -491,6 +491,23 @@
|
||||
|
||||
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'.
|
||||
+
|
||||
config IP_NF_TARGET_NETMAP
|
||||
tristate "NETMAP target support"
|
||||
depends on IP_NF_NAT
|
||||
diff -u'rNF^function' linux-2.6.16.7/net/ipv4/netfilter/Makefile linux-2.6.16.7-ROUTE/net/ipv4/netfilter/Makefile
|
||||
--- linux-2.6.16.7/net/ipv4/netfilter/Makefile 2006-06-14 16:05:44.000000000 +0200
|
||||
+++ linux-2.6.16.7-ROUTE/net/ipv4/netfilter/Makefile 2006-06-14 16:44:02.000000000 +0200
|
||||
@@ -74,6 +74,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_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
|
||||
diff -u'rNF^function' linux-2.6.16.7/net/ipv4/netfilter/ipt_ROUTE.c linux-2.6.16.7-ROUTE/net/ipv4/netfilter/ipt_ROUTE.c
|
||||
--- linux-2.6.16.7/net/ipv4/netfilter/ipt_ROUTE.c 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ linux-2.6.16.7-ROUTE/net/ipv4/netfilter/ipt_ROUTE.c 2006-06-14 16:42:23.000000000 +0200
|
||||
@@ -0,0 +1,461 @@
|
||||
+/*
|
||||
+ * 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 <linux/netfilter_ipv4/ip_conntrack.h>
|
||||
+#include <linux/netfilter_ipv4/ipt_ROUTE.h>
|
||||
+#include <linux/netdevice.h>
|
||||
+#include <linux/route.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 = skb->nh.iph;
|
||||
+ 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 ip_conntrack 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,
|
||||
+ const void *targinfo,
|
||||
+ void *userinfo)
|
||||
+{
|
||||
+ 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 = skb->nh.iph;
|
||||
+
|
||||
+ 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,
|
||||
+ const void *e,
|
||||
+ void *targinfo,
|
||||
+ unsigned int targinfosize,
|
||||
+ 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 (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;
|
||||
+ }
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static struct ipt_target ipt_route_reg = {
|
||||
+ .name = "ROUTE",
|
||||
+ .target = ipt_route_target,
|
||||
+ .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 ipt_register_target(&ipt_route_reg);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static void __exit fini(void)
|
||||
+{
|
||||
+ ipt_unregister_target(&ipt_route_reg);
|
||||
+}
|
||||
+
|
||||
+module_init(init);
|
||||
+module_exit(fini);
|
||||
diff -u'rNF^function' linux-2.6.16.7/net/ipv6/ipv6_syms.c linux-2.6.16.7-ROUTE/net/ipv6/ipv6_syms.c
|
||||
--- linux-2.6.16.7/net/ipv6/ipv6_syms.c 2006-04-17 23:53:25.000000000 +0200
|
||||
+++ linux-2.6.16.7-ROUTE/net/ipv6/ipv6_syms.c 2006-06-14 17:02:32.000000000 +0200
|
||||
@@ -12,6 +12,7 @@
|
||||
EXPORT_SYMBOL(icmpv6_statistics);
|
||||
EXPORT_SYMBOL(icmpv6_err_convert);
|
||||
EXPORT_SYMBOL(ndisc_mc_map);
|
||||
+EXPORT_SYMBOL(nd_tbl);
|
||||
EXPORT_SYMBOL(register_inet6addr_notifier);
|
||||
EXPORT_SYMBOL(unregister_inet6addr_notifier);
|
||||
EXPORT_SYMBOL(ip6_route_output);
|
||||
diff -u'rNF^function' linux-2.6.16.7/net/ipv6/netfilter/Kconfig linux-2.6.16.7-ROUTE/net/ipv6/netfilter/Kconfig
|
||||
--- linux-2.6.16.7/net/ipv6/netfilter/Kconfig 2006-06-14 16:05:44.000000000 +0200
|
||||
+++ linux-2.6.16.7-ROUTE/net/ipv6/netfilter/Kconfig 2006-06-14 16:45:45.000000000 +0200
|
||||
@@ -182,6 +182,19 @@
|
||||
|
||||
To compile it as a module, choose M here. 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.
|
||||
+
|
||||
config IP6_NF_MANGLE
|
||||
tristate "Packet mangling"
|
||||
depends on IP6_NF_IPTABLES
|
||||
diff -u'rNF^function' linux-2.6.16.7/net/ipv6/netfilter/Makefile linux-2.6.16.7-ROUTE/net/ipv6/netfilter/Makefile
|
||||
--- linux-2.6.16.7/net/ipv6/netfilter/Makefile 2006-06-14 16:05:44.000000000 +0200
|
||||
+++ linux-2.6.16.7-ROUTE/net/ipv6/netfilter/Makefile 2006-06-14 16:45:00.000000000 +0200
|
||||
@@ -22,6 +22,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
|
||||
|
||||
# objects for l3 independent conntrack
|
||||
nf_conntrack_ipv6-objs := nf_conntrack_l3proto_ipv6.o nf_conntrack_proto_icmpv6.o nf_conntrack_reasm.o
|
||||
diff -u'rNF^function' linux-2.6.16.7/net/ipv6/netfilter/ip6t_ROUTE.c linux-2.6.16.7-ROUTE/net/ipv6/netfilter/ip6t_ROUTE.c
|
||||
--- linux-2.6.16.7/net/ipv6/netfilter/ip6t_ROUTE.c 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ linux-2.6.16.7-ROUTE/net/ipv6/netfilter/ip6t_ROUTE.c 2006-06-14 16:42:44.000000000 +0200
|
||||
@@ -0,0 +1,308 @@
|
||||
+/*
|
||||
+ * 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 <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 = skb->nh.ipv6h;
|
||||
+ 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,
|
||||
+ const void *targinfo,
|
||||
+ void *userinfo)
|
||||
+{
|
||||
+ 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 = skb->nh.ipv6h;
|
||||
+
|
||||
+ 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,
|
||||
+ const struct ip6t_entry *e,
|
||||
+ void *targinfo,
|
||||
+ unsigned int targinfosize,
|
||||
+ unsigned int hook_mask)
|
||||
+{
|
||||
+ if (strcmp(tablename, "mangle") != 0) {
|
||||
+ printk("ip6t_ROUTE: can only be called from \"mangle\" table.\n");
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ 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;
|
||||
+ }
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static struct ip6t_target ip6t_route_reg = {
|
||||
+ .name = "ROUTE",
|
||||
+ .target = ip6t_route_target,
|
||||
+ .checkentry = ip6t_route_checkentry,
|
||||
+ .me = THIS_MODULE
|
||||
+};
|
||||
+
|
||||
+
|
||||
+static int __init init(void)
|
||||
+{
|
||||
+ printk(KERN_DEBUG "registering ipv6 ROUTE target\n");
|
||||
+ if (ip6t_register_target(&ip6t_route_reg))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static void __exit fini(void)
|
||||
+{
|
||||
+ ip6t_unregister_target(&ip6t_route_reg);
|
||||
+}
|
||||
+
|
||||
+module_init(init);
|
||||
+module_exit(fini);
|
||||
+MODULE_LICENSE("GPL");
|
||||
730
target/linux/generic-2.6/patches/200-sched_esfq.patch
Normal file
730
target/linux/generic-2.6/patches/200-sched_esfq.patch
Normal file
@@ -0,0 +1,730 @@
|
||||
diff -Naur linux-2.6.15.1.orig/include/linux/pkt_sched.h linux-2.6.15.1/include/linux/pkt_sched.h
|
||||
--- linux-2.6.15.1.orig/include/linux/pkt_sched.h 2006-01-14 22:16:02.000000000 -0800
|
||||
+++ linux-2.6.15.1/include/linux/pkt_sched.h 2006-01-30 16:02:32.000000000 -0800
|
||||
@@ -146,8 +146,35 @@
|
||||
*
|
||||
* 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,
|
||||
+};
|
||||
+
|
||||
+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 -Naur linux-2.6.15.1.orig/net/sched/Kconfig linux-2.6.15.1/net/sched/Kconfig
|
||||
--- linux-2.6.15.1.orig/net/sched/Kconfig 2006-01-14 22:16:02.000000000 -0800
|
||||
+++ linux-2.6.15.1/net/sched/Kconfig 2006-01-30 16:02:32.000000000 -0800
|
||||
@@ -185,6 +185,28 @@
|
||||
To compile this code as a module, choose M here: the
|
||||
module will be called sch_sfq.
|
||||
|
||||
+config NET_SCH_ESFQ
|
||||
+ tristate "ESFQ queue"
|
||||
+ depends on NET_SCHED
|
||||
+ ---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: queue depth, hash table size,
|
||||
+ and queues limit.
|
||||
+
|
||||
+ ESFQ also adds control to the hash function used to identify packet
|
||||
+ flows. The original SFQ hashes by individual flow (TCP session or UDP
|
||||
+ stream); ESFQ can hash by src or dst IP as well, 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 -Naur linux-2.6.15.1.orig/net/sched/Makefile linux-2.6.15.1/net/sched/Makefile
|
||||
--- linux-2.6.15.1.orig/net/sched/Makefile 2006-01-14 22:16:02.000000000 -0800
|
||||
+++ linux-2.6.15.1/net/sched/Makefile 2006-01-30 16:02:32.000000000 -0800
|
||||
@@ -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 -Naur linux-2.6.15.1.orig/net/sched/sch_esfq.c linux-2.6.15.1/net/sched/sch_esfq.c
|
||||
--- linux-2.6.15.1.orig/net/sched/sch_esfq.c 1969-12-31 16:00:00.000000000 -0800
|
||||
+++ linux-2.6.15.1/net/sched/sch_esfq.c 2006-01-30 16:12:29.000000000 -0800
|
||||
@@ -0,0 +1,644 @@
|
||||
+/*
|
||||
+ * 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.
|
||||
+ *
|
||||
+ */
|
||||
+
|
||||
+#include <linux/config.h>
|
||||
+#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>
|
||||
+
|
||||
+
|
||||
+/* 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 7 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
|
||||
+
|
||||
+ TODO:
|
||||
+ make sfq_change work.
|
||||
+*/
|
||||
+
|
||||
+
|
||||
+/* 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 */
|
||||
+};
|
||||
+
|
||||
+static __inline__ unsigned esfq_hash_u32(struct esfq_sched_data *q,u32 h)
|
||||
+{
|
||||
+ int pert = q->perturbation;
|
||||
+
|
||||
+ if (pert)
|
||||
+ h = (h<<pert) ^ (h>>(0x1F - pert));
|
||||
+
|
||||
+ h = ntohl(h) * 2654435761UL;
|
||||
+ return h & (q->hash_divisor-1);
|
||||
+}
|
||||
+
|
||||
+/* 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. */
|
||||
+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_fold_hash_classic(struct esfq_sched_data *q, u32 h, u32 h1)
|
||||
+{
|
||||
+ int pert = q->perturbation;
|
||||
+
|
||||
+ /* Have we any rotation primitives? If not, WHY? */
|
||||
+ h ^= (h1<<pert) ^ (h1>>(0x1F - pert));
|
||||
+ h ^= h>>10;
|
||||
+ return h & (q->hash_divisor-1);
|
||||
+}
|
||||
+
|
||||
+static unsigned esfq_hash(struct esfq_sched_data *q, struct sk_buff *skb)
|
||||
+{
|
||||
+ u32 h, h2;
|
||||
+ u32 hs;
|
||||
+ u32 nfm;
|
||||
+
|
||||
+ switch (skb->protocol) {
|
||||
+ case __constant_htons(ETH_P_IP):
|
||||
+ {
|
||||
+ struct iphdr *iph = skb->nh.iph;
|
||||
+ h = iph->daddr;
|
||||
+ hs = iph->saddr;
|
||||
+ nfm = skb->nfmark;
|
||||
+ h2 = hs^iph->protocol;
|
||||
+ 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))
|
||||
+ h2 ^= *(((u32*)iph) + iph->ihl);
|
||||
+ break;
|
||||
+ }
|
||||
+ case __constant_htons(ETH_P_IPV6):
|
||||
+ {
|
||||
+ struct ipv6hdr *iph = skb->nh.ipv6h;
|
||||
+ h = iph->daddr.s6_addr32[3];
|
||||
+ hs = iph->saddr.s6_addr32[3];
|
||||
+ nfm = skb->nfmark;
|
||||
+ h2 = hs^iph->nexthdr;
|
||||
+ if (iph->nexthdr == IPPROTO_TCP ||
|
||||
+ iph->nexthdr == IPPROTO_UDP ||
|
||||
+ iph->nexthdr == IPPROTO_SCTP ||
|
||||
+ iph->nexthdr == IPPROTO_DCCP ||
|
||||
+ iph->nexthdr == IPPROTO_ESP)
|
||||
+ h2 ^= *(u32*)&iph[1];
|
||||
+ break;
|
||||
+ }
|
||||
+ default:
|
||||
+ h = (u32)(unsigned long)skb->dst;
|
||||
+ hs = (u32)(unsigned long)skb->sk;
|
||||
+ nfm = skb->nfmark;
|
||||
+ h2 = hs^skb->protocol;
|
||||
+ }
|
||||
+ switch(q->hash_kind)
|
||||
+ {
|
||||
+ case TCA_SFQ_HASH_CLASSIC:
|
||||
+ return esfq_fold_hash_classic(q, h, h2);
|
||||
+ case TCA_SFQ_HASH_DST:
|
||||
+ return esfq_hash_u32(q,h);
|
||||
+ case TCA_SFQ_HASH_DSTDIR:
|
||||
+ return esfq_hash_direct(q, ntohl(h));
|
||||
+ case TCA_SFQ_HASH_SRC:
|
||||
+ return esfq_hash_u32(q,hs);
|
||||
+ case TCA_SFQ_HASH_SRCDIR:
|
||||
+ return esfq_hash_direct(q, ntohl(hs));
|
||||
+#ifdef CONFIG_NETFILTER
|
||||
+ case TCA_SFQ_HASH_FWMARK:
|
||||
+ return esfq_hash_u32(q,nfm);
|
||||
+ case TCA_SFQ_HASH_FWMARKDIR:
|
||||
+ return esfq_hash_direct(q,nfm);
|
||||
+#endif
|
||||
+ default:
|
||||
+ if (net_ratelimit())
|
||||
+ printk(KERN_WARNING "ESFQ: Unknown hash method. Falling back to classic.\n");
|
||||
+ }
|
||||
+ return esfq_fold_hash_classic(q, h, h2);
|
||||
+}
|
||||
+
|
||||
+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++;
|
||||
+ 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++;
|
||||
+ 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;
|
||||
+ }
|
||||
+ __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;
|
||||
+ }
|
||||
+ __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--;
|
||||
+
|
||||
+ /* 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 = ~0UL/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");
|
||||
1238
target/linux/generic-2.6/patches/201-multiple_default_gateways.patch
Normal file
1238
target/linux/generic-2.6/patches/201-multiple_default_gateways.patch
Normal file
File diff suppressed because it is too large
Load Diff
12
target/linux/generic-2.6/patches/202-mips-freestanding.patch
Normal file
12
target/linux/generic-2.6/patches/202-mips-freestanding.patch
Normal file
@@ -0,0 +1,12 @@
|
||||
--- linux-2.6.17/arch/mips/Makefile 2006-06-19 15:12:09.000000000 -0700
|
||||
+++ linux-2.6.17/arch/mips/Makefile 2006-06-19 15:11:59.000000000 -0700
|
||||
@@ -602,6 +602,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/
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
diff -Nurb linux-2.6.17/usr/Makefile linux-2.6.17/usr/Makefile
|
||||
--- linux-2.6.17/usr/Makefile 2006-06-20 11:51:27.000000000 -0700
|
||||
+++ linux-2.6.17/usr/Makefile 2006-06-20 11:51:34.000000000 -0700
|
||||
@@ -21,8 +21,7 @@
|
||||
$(CONFIG_INITRAMFS_SOURCE),-d)
|
||||
ramfs-args := \
|
||||
$(if $(CONFIG_INITRAMFS_ROOT_UID), -u $(CONFIG_INITRAMFS_ROOT_UID)) \
|
||||
- $(if $(CONFIG_INITRAMFS_ROOT_GID), -g $(CONFIG_INITRAMFS_ROOT_GID)) \
|
||||
- $(ramfs-input)
|
||||
+ $(if $(CONFIG_INITRAMFS_ROOT_GID), -g $(CONFIG_INITRAMFS_ROOT_GID))
|
||||
|
||||
# .initramfs_data.cpio.gz.d is used to identify all files included
|
||||
# in initramfs and to detect if any files are added/removed.
|
||||
58
target/linux/generic-2.6/patches/204-jffs2_eofdetect.patch
Normal file
58
target/linux/generic-2.6/patches/204-jffs2_eofdetect.patch
Normal file
@@ -0,0 +1,58 @@
|
||||
diff -urN linux.old/fs/jffs2/build.c linux.dev/fs/jffs2/build.c
|
||||
--- linux.old/fs/jffs2/build.c 2006-06-18 03:49:35.000000000 +0200
|
||||
+++ linux.dev/fs/jffs2/build.c 2006-06-23 21:46:48.000000000 +0200
|
||||
@@ -107,6 +107,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.old/fs/jffs2/scan.c linux.dev/fs/jffs2/scan.c
|
||||
--- linux.old/fs/jffs2/scan.c 2006-06-23 21:39:38.000000000 +0200
|
||||
+++ linux.dev/fs/jffs2/scan.c 2006-06-23 21:42:18.000000000 +0200
|
||||
@@ -119,9 +119,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;
|
||||
@@ -389,6 +392,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;
|
||||
|
||||
235
target/linux/generic-2.6/patches/205-block2mtd_fix.patch
Normal file
235
target/linux/generic-2.6/patches/205-block2mtd_fix.patch
Normal file
@@ -0,0 +1,235 @@
|
||||
diff -urN linux.old/drivers/mtd/devices/block2mtd.c linux.dev/drivers/mtd/devices/block2mtd.c
|
||||
--- linux.old/drivers/mtd/devices/block2mtd.c 2006-07-29 19:53:54.000000000 +0200
|
||||
+++ linux.dev/drivers/mtd/devices/block2mtd.c 2006-07-29 19:47:03.000000000 +0200
|
||||
@@ -4,11 +4,10 @@
|
||||
* block2mtd.c - create an mtd from a block device
|
||||
*
|
||||
* Copyright (C) 2001,2002 Simon Evans <spse@secret.org.uk>
|
||||
- * Copyright (C) 2004,2005 J<>rn Engel <joern@wh.fh-wedel.de>
|
||||
+ * Copyright (C) 2004-2006 Jörn Engel <joern@wh.fh-wedel.de>
|
||||
*
|
||||
* Licence: GPL
|
||||
*/
|
||||
-#include <linux/config.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/blkdev.h>
|
||||
@@ -19,6 +18,7 @@ #include <linux/init.h>
|
||||
#include <linux/mtd/mtd.h>
|
||||
#include <linux/buffer_head.h>
|
||||
#include <linux/mutex.h>
|
||||
+#include <linux/mount.h>
|
||||
|
||||
#define VERSION "$Revision: 1.30 $"
|
||||
|
||||
@@ -62,10 +61,8 @@
|
||||
read_lock_irq(&mapping->tree_lock);
|
||||
for (i = 0; i < PAGE_READAHEAD; i++) {
|
||||
pagei = index + i;
|
||||
- if (pagei > end_index) {
|
||||
- INFO("Overrun end of disk in cache readahead\n");
|
||||
+ if (pagei > end_index)
|
||||
break;
|
||||
- }
|
||||
page = radix_tree_lookup(&mapping->page_tree, pagei);
|
||||
if (page && (!i))
|
||||
break;
|
||||
@@ -237,6 +237,8 @@ static int _block2mtd_write(struct block
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
+
|
||||
+
|
||||
static int block2mtd_write(struct mtd_info *mtd, loff_t to, size_t len,
|
||||
size_t *retlen, const u_char *buf)
|
||||
{
|
||||
@@ -300,6 +302,19 @@ static struct block2mtd_dev *add_device(
|
||||
|
||||
/* Get a handle on the device */
|
||||
bdev = open_bdev_excl(devname, O_RDWR, NULL);
|
||||
+#ifndef MODULE
|
||||
+ if (IS_ERR(bdev)) {
|
||||
+
|
||||
+ /* We might not have rootfs mounted at this point. Try
|
||||
+ to resolve the device name by other means. */
|
||||
+
|
||||
+ dev_t dev = name_to_dev_t(devname);
|
||||
+ if (dev != 0) {
|
||||
+ bdev = open_by_devnum(dev, FMODE_WRITE | FMODE_READ);
|
||||
+ }
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
if (IS_ERR(bdev)) {
|
||||
ERROR("error: cannot open device %s", devname);
|
||||
goto devinit_err;
|
||||
@@ -331,7 +347,6 @@ static struct block2mtd_dev *add_device(
|
||||
dev->mtd.writev = default_mtd_writev;
|
||||
dev->mtd.sync = block2mtd_sync;
|
||||
dev->mtd.read = block2mtd_read;
|
||||
- dev->mtd.readv = default_mtd_readv;
|
||||
dev->mtd.priv = dev;
|
||||
dev->mtd.owner = THIS_MODULE;
|
||||
|
||||
@@ -351,6 +366,12 @@ devinit_err:
|
||||
}
|
||||
|
||||
|
||||
+/* This function works similar to reguler strtoul. In addition, it
|
||||
+ * allows some suffixes for a more human-readable number format:
|
||||
+ * ki, Ki, kiB, KiB - multiply result with 1024
|
||||
+ * Mi, MiB - multiply result with 1024^2
|
||||
+ * Gi, GiB - multiply result with 1024^3
|
||||
+ */
|
||||
static int ustrtoul(const char *cp, char **endp, unsigned int base)
|
||||
{
|
||||
unsigned long result = simple_strtoul(cp, endp, base);
|
||||
@@ -359,11 +380,16 @@ static int ustrtoul(const char *cp, char
|
||||
result *= 1024;
|
||||
case 'M':
|
||||
result *= 1024;
|
||||
+ case 'K':
|
||||
case 'k':
|
||||
result *= 1024;
|
||||
/* By dwmw2 editorial decree, "ki", "Mi" or "Gi" are to be used. */
|
||||
- if ((*endp)[1] == 'i')
|
||||
- (*endp) += 2;
|
||||
+ if ((*endp)[1] == 'i') {
|
||||
+ if ((*endp)[2] == 'B')
|
||||
+ (*endp) += 3;
|
||||
+ else
|
||||
+ (*endp) += 2;
|
||||
+ }
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -383,26 +409,6 @@ static int parse_num(size_t *num, const
|
||||
}
|
||||
|
||||
|
||||
-static int parse_name(char **pname, const char *token, size_t limit)
|
||||
-{
|
||||
- size_t len;
|
||||
- char *name;
|
||||
-
|
||||
- len = strlen(token) + 1;
|
||||
- if (len > limit)
|
||||
- return -ENOSPC;
|
||||
-
|
||||
- name = kmalloc(len, GFP_KERNEL);
|
||||
- if (!name)
|
||||
- return -ENOMEM;
|
||||
-
|
||||
- strcpy(name, token);
|
||||
-
|
||||
- *pname = name;
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-
|
||||
static inline void kill_final_newline(char *str)
|
||||
{
|
||||
char *newline = strrchr(str, '\n');
|
||||
@@ -416,9 +422,16 @@ #define parse_err(fmt, args...) do { \
|
||||
return 0; \
|
||||
} while (0)
|
||||
|
||||
-static int block2mtd_setup(const char *val, struct kernel_param *kp)
|
||||
+#ifndef MODULE
|
||||
+static int block2mtd_init_called = 0;
|
||||
+static __initdata char block2mtd_paramline[80 + 12]; /* 80 for device, 12 for erase size */
|
||||
+#endif
|
||||
+
|
||||
+
|
||||
+static int block2mtd_setup2(const char *val)
|
||||
{
|
||||
- char buf[80+12], *str=buf; /* 80 for device, 12 for erase size */
|
||||
+ char buf[80 + 12]; /* 80 for device, 12 for erase size */
|
||||
+ char *str = buf;
|
||||
char *token[2];
|
||||
char *name;
|
||||
size_t erase_size = PAGE_SIZE;
|
||||
@@ -430,7 +443,7 @@ static int block2mtd_setup(const char *v
|
||||
strcpy(str, val);
|
||||
kill_final_newline(str);
|
||||
|
||||
- for (i=0; i<2; i++)
|
||||
+ for (i = 0; i < 2; i++)
|
||||
token[i] = strsep(&str, ",");
|
||||
|
||||
if (str)
|
||||
@@ -439,18 +452,16 @@ static int block2mtd_setup(const char *v
|
||||
if (!token[0])
|
||||
parse_err("no argument");
|
||||
|
||||
- ret = parse_name(&name, token[0], 80);
|
||||
- if (ret == -ENOMEM)
|
||||
- parse_err("out of memory");
|
||||
- if (ret == -ENOSPC)
|
||||
- parse_err("name too long");
|
||||
- if (ret)
|
||||
- return 0;
|
||||
+ name = token[0];
|
||||
+ if (strlen(name) + 1 > 80)
|
||||
+ parse_err("device name too long");
|
||||
|
||||
if (token[1]) {
|
||||
ret = parse_num(&erase_size, token[1]);
|
||||
- if (ret)
|
||||
+ if (ret) {
|
||||
+ kfree(name);
|
||||
parse_err("illegal erase size");
|
||||
+ }
|
||||
}
|
||||
|
||||
add_device(name, erase_size);
|
||||
@@ -459,13 +470,48 @@ static int block2mtd_setup(const char *v
|
||||
}
|
||||
|
||||
|
||||
+static int block2mtd_setup(const char *val, struct kernel_param *kp)
|
||||
+{
|
||||
+#ifdef MODULE
|
||||
+ return block2mtd_setup2(val);
|
||||
+#else
|
||||
+ /* If more parameters are later passed in via
|
||||
+ /sys/module/block2mtd/parameters/block2mtd
|
||||
+ and block2mtd_init() has already been called,
|
||||
+ we can parse the argument now. */
|
||||
+
|
||||
+ if (block2mtd_init_called)
|
||||
+ return block2mtd_setup2(val);
|
||||
+
|
||||
+ /* During early boot stage, we only save the parameters
|
||||
+ here. We must parse them later: if the param passed
|
||||
+ from kernel boot command line, block2mtd_setup() is
|
||||
+ called so early that it is not possible to resolve
|
||||
+ the device (even kmalloc() fails). Deter that work to
|
||||
+ block2mtd_setup2(). */
|
||||
+
|
||||
+ strlcpy(block2mtd_paramline, val, sizeof(block2mtd_paramline));
|
||||
+
|
||||
+ return 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+
|
||||
module_param_call(block2mtd, block2mtd_setup, NULL, NULL, 0200);
|
||||
MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=<dev>[,<erasesize>]\"");
|
||||
|
||||
static int __init block2mtd_init(void)
|
||||
{
|
||||
+ int ret = 0;
|
||||
INFO("version " VERSION);
|
||||
- return 0;
|
||||
+
|
||||
+#ifndef MODULE
|
||||
+ if (strlen(block2mtd_paramline))
|
||||
+ ret = block2mtd_setup2(block2mtd_paramline);
|
||||
+ block2mtd_init_called = 1;
|
||||
+#endif
|
||||
+
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
|
||||
12
target/linux/generic-2.6/patches/206-pppoe_mtu_fix.patch
Normal file
12
target/linux/generic-2.6/patches/206-pppoe_mtu_fix.patch
Normal file
@@ -0,0 +1,12 @@
|
||||
--- linux-2.6.17/drivers/net/pppoe.c.old 2006-10-10 13:47:56.000000000 +0200
|
||||
+++ linux-2.6.17/drivers/net/pppoe.c 2006-10-10 13:52:02.000000000 +0200
|
||||
@@ -600,6 +600,9 @@
|
||||
po->chan.hdrlen = (sizeof(struct pppoe_hdr) +
|
||||
dev->hard_header_len);
|
||||
|
||||
+ if (po->chan.mtu > dev->mtu - sizeof(struct pppoe_hdr))
|
||||
+ po->chan.mtu = dev->mtu - sizeof(struct pppoe_hdr);
|
||||
+
|
||||
po->chan.private = sk;
|
||||
po->chan.ops = &pppoe_chan_ops;
|
||||
|
||||
Reference in New Issue
Block a user