From 3288a990d1ae809279b67221de7607dc35a79bfe Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 28 Mar 2006 13:29:26 -0800 Subject: [PATCH] --- yaml --- r: 25028 b: refs/heads/master c: 6f25f3986af0353b0bdc220f79b89c997d0ceda4 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/arch/powerpc/kernel/systbl.S | 1 - trunk/arch/sparc64/kernel/smp.c | 9 +- trunk/drivers/net/arcnet/com90xx.c | 4 +- trunk/drivers/net/tg3.c | 57 +- trunk/fs/splice.c | 25 +- trunk/include/linux/netfilter/x_tables.h | 67 - trunk/include/linux/netfilter/xt_esp.h | 14 - trunk/include/linux/netfilter/xt_multiport.h | 30 - .../include/linux/netfilter_ipv4/ip_tables.h | 18 - trunk/include/linux/netfilter_ipv4/ipt_esp.h | 14 +- .../linux/netfilter_ipv4/ipt_multiport.h | 31 +- trunk/include/linux/netfilter_ipv6/ip6t_esp.h | 12 +- .../linux/netfilter_ipv6/ip6t_multiport.h | 25 +- trunk/include/linux/pipe_fs_i.h | 3 - trunk/include/net/xfrm.h | 19 +- trunk/net/compat.c | 3 +- trunk/net/ipv4/ah4.c | 2 +- trunk/net/ipv4/esp4.c | 5 +- trunk/net/ipv4/ipcomp.c | 3 +- trunk/net/ipv4/netfilter/Kconfig | 18 +- trunk/net/ipv4/netfilter/Makefile | 3 +- .../net/ipv4/netfilter/ip_conntrack_netlink.c | 2 +- trunk/net/ipv4/netfilter/ip_tables.c | 1288 +++-------------- .../xt_esp.c => ipv4/netfilter/ipt_esp.c} | 81 +- trunk/net/ipv4/netfilter/ipt_multiport.c | 195 +++ trunk/net/ipv4/xfrm4_input.c | 15 +- trunk/net/ipv4/xfrm4_tunnel.c | 2 +- trunk/net/ipv6/ah6.c | 2 +- trunk/net/ipv6/esp6.c | 2 +- trunk/net/ipv6/ipcomp6.c | 2 +- trunk/net/ipv6/netfilter/Kconfig | 16 +- trunk/net/ipv6/netfilter/Makefile | 3 +- trunk/net/ipv6/netfilter/ip6t_esp.c | 115 ++ trunk/net/ipv6/netfilter/ip6t_multiport.c | 125 ++ trunk/net/ipv6/xfrm6_input.c | 11 +- trunk/net/ipv6/xfrm6_tunnel.c | 2 +- trunk/net/netfilter/Kconfig | 19 - trunk/net/netfilter/Makefile | 2 - trunk/net/netfilter/nf_conntrack_netlink.c | 6 +- trunk/net/netfilter/x_tables.c | 113 -- trunk/net/netfilter/xt_multiport.c | 314 ---- trunk/net/netfilter/xt_policy.c | 2 +- trunk/net/socket.c | 7 +- trunk/net/xfrm/xfrm_input.c | 4 +- trunk/net/xfrm/xfrm_policy.c | 10 +- 46 files changed, 862 insertions(+), 1841 deletions(-) delete mode 100644 trunk/include/linux/netfilter/xt_esp.h delete mode 100644 trunk/include/linux/netfilter/xt_multiport.h rename trunk/net/{netfilter/xt_esp.c => ipv4/netfilter/ipt_esp.c} (51%) create mode 100644 trunk/net/ipv4/netfilter/ipt_multiport.c create mode 100644 trunk/net/ipv6/netfilter/ip6t_esp.c create mode 100644 trunk/net/ipv6/netfilter/ip6t_multiport.c delete mode 100644 trunk/net/netfilter/xt_multiport.c diff --git a/[refs] b/[refs] index 477cc376e25c..54fb584409f0 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: bacd3add087770333bdce65cd3dd25e3b2cd67ac +refs/heads/master: 6f25f3986af0353b0bdc220f79b89c997d0ceda4 diff --git a/trunk/arch/powerpc/kernel/systbl.S b/trunk/arch/powerpc/kernel/systbl.S index 1424eab450ee..1ad55f0466fd 100644 --- a/trunk/arch/powerpc/kernel/systbl.S +++ b/trunk/arch/powerpc/kernel/systbl.S @@ -322,4 +322,3 @@ SYSCALL(spu_create) COMPAT_SYS(pselect6) COMPAT_SYS(ppoll) SYSCALL(unshare) -SYSCALL(splice) diff --git a/trunk/arch/sparc64/kernel/smp.c b/trunk/arch/sparc64/kernel/smp.c index 7dc28a484268..8175a6968c6b 100644 --- a/trunk/arch/sparc64/kernel/smp.c +++ b/trunk/arch/sparc64/kernel/smp.c @@ -830,9 +830,16 @@ void smp_call_function_client(int irq, struct pt_regs *regs) static void tsb_sync(void *info) { + struct trap_per_cpu *tp = &trap_block[raw_smp_processor_id()]; struct mm_struct *mm = info; - if (current->active_mm == mm) + /* It is not valid to test "currrent->active_mm == mm" here. + * + * The value of "current" is not changed atomically with + * switch_mm(). But that's OK, we just need to check the + * current cpu's trap block PGD physical address. + */ + if (tp->pgd_paddr == __pa(mm->pgd)) tsb_context_switch(mm); } diff --git a/trunk/drivers/net/arcnet/com90xx.c b/trunk/drivers/net/arcnet/com90xx.c index 0d45553ff75c..43150b2bd13f 100644 --- a/trunk/drivers/net/arcnet/com90xx.c +++ b/trunk/drivers/net/arcnet/com90xx.c @@ -125,11 +125,11 @@ static void __init com90xx_probe(void) if (!io && !irq && !shmem && !*device && com90xx_skip_probe) return; - shmems = kzalloc(((0x100000-0xa0000) / 0x800) * sizeof(unsigned long), + shmems = kzalloc(((0x10000-0xa0000) / 0x800) * sizeof(unsigned long), GFP_KERNEL); if (!shmems) return; - iomem = kzalloc(((0x100000-0xa0000) / 0x800) * sizeof(void __iomem *), + iomem = kzalloc(((0x10000-0xa0000) / 0x800) * sizeof(void __iomem *), GFP_KERNEL); if (!iomem) { kfree(shmems); diff --git a/trunk/drivers/net/tg3.c b/trunk/drivers/net/tg3.c index 770e6b6cec60..964c09644832 100644 --- a/trunk/drivers/net/tg3.c +++ b/trunk/drivers/net/tg3.c @@ -69,8 +69,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.56" -#define DRV_MODULE_RELDATE "Apr 1, 2006" +#define DRV_MODULE_VERSION "3.55" +#define DRV_MODULE_RELDATE "Mar 27, 2006" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -497,21 +497,20 @@ static void tg3_write_mem(struct tg3 *tp, u32 off, u32 val) unsigned long flags; spin_lock_irqsave(&tp->indirect_lock, flags); - pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off); - pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val); + if (tp->write32 != tg3_write_indirect_reg32) { + tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, off); + tw32_f(TG3PCI_MEM_WIN_DATA, val); - /* Always leave this as zero. */ - pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0); - spin_unlock_irqrestore(&tp->indirect_lock, flags); -} + /* Always leave this as zero. */ + tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, 0); + } else { + pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off); + pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val); -static void tg3_write_mem_fast(struct tg3 *tp, u32 off, u32 val) -{ - /* If no workaround is needed, write to mem space directly */ - if (tp->write32 != tg3_write_indirect_reg32) - tw32(NIC_SRAM_WIN_BASE + off, val); - else - tg3_write_mem(tp, off, val); + /* Always leave this as zero. */ + pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0); + } + spin_unlock_irqrestore(&tp->indirect_lock, flags); } static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val) @@ -519,11 +518,19 @@ static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val) unsigned long flags; spin_lock_irqsave(&tp->indirect_lock, flags); - pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off); - pci_read_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val); + if (tp->write32 != tg3_write_indirect_reg32) { + tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, off); + *val = tr32(TG3PCI_MEM_WIN_DATA); - /* Always leave this as zero. */ - pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0); + /* Always leave this as zero. */ + tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, 0); + } else { + pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off); + pci_read_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val); + + /* Always leave this as zero. */ + pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0); + } spin_unlock_irqrestore(&tp->indirect_lock, flags); } @@ -1367,12 +1374,12 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) } } + tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN); + /* Finally, set the new power state. */ pci_write_config_word(tp->pdev, pm + PCI_PM_CTRL, power_control); udelay(100); /* Delay after power state change */ - tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN); - return 0; } @@ -6540,11 +6547,11 @@ static void tg3_timer(unsigned long __opaque) if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) { u32 val; - tg3_write_mem_fast(tp, NIC_SRAM_FW_CMD_MBOX, - FWCMD_NICDRV_ALIVE2); - tg3_write_mem_fast(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 4); + tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, + FWCMD_NICDRV_ALIVE2); + tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 4); /* 5 seconds timeout */ - tg3_write_mem_fast(tp, NIC_SRAM_FW_CMD_DATA_MBOX, 5); + tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX, 5); val = tr32(GRC_RX_CPU_EVENT); val |= (1 << 14); tw32(GRC_RX_CPU_EVENT, val); diff --git a/trunk/fs/splice.c b/trunk/fs/splice.c index 6081cf7d2d1b..7c2bbf18d7a7 100644 --- a/trunk/fs/splice.c +++ b/trunk/fs/splice.c @@ -106,7 +106,7 @@ static struct pipe_buf_operations page_cache_pipe_buf_ops = { static ssize_t move_to_pipe(struct inode *inode, struct page **pages, int nr_pages, unsigned long offset, - unsigned long len, unsigned int flags) + unsigned long len) { struct pipe_inode_info *info; int ret, do_wakeup, i; @@ -159,12 +159,6 @@ static ssize_t move_to_pipe(struct inode *inode, struct page **pages, break; } - if (flags & SPLICE_F_NONBLOCK) { - if (!ret) - ret = -EAGAIN; - break; - } - if (signal_pending(current)) { if (!ret) ret = -ERESTARTSYS; @@ -197,7 +191,7 @@ static ssize_t move_to_pipe(struct inode *inode, struct page **pages, } static int __generic_file_splice_read(struct file *in, struct inode *pipe, - size_t len, unsigned int flags) + size_t len) { struct address_space *mapping = in->f_mapping; unsigned int offset, nr_pages; @@ -285,7 +279,7 @@ static int __generic_file_splice_read(struct file *in, struct inode *pipe, * Now we splice them into the pipe.. */ splice_them: - return move_to_pipe(pipe, pages, i, offset, len, flags); + return move_to_pipe(pipe, pages, i, offset, len); } ssize_t generic_file_splice_read(struct file *in, struct inode *pipe, @@ -297,7 +291,7 @@ ssize_t generic_file_splice_read(struct file *in, struct inode *pipe, ret = 0; spliced = 0; while (len) { - ret = __generic_file_splice_read(in, pipe, len, flags); + ret = __generic_file_splice_read(in, pipe, len); if (ret <= 0) break; @@ -305,11 +299,6 @@ ssize_t generic_file_splice_read(struct file *in, struct inode *pipe, in->f_pos += ret; len -= ret; spliced += ret; - - if (!(flags & SPLICE_F_NONBLOCK)) - continue; - ret = -EAGAIN; - break; } if (spliced) @@ -538,12 +527,6 @@ static ssize_t move_from_pipe(struct inode *inode, struct file *out, break; } - if (flags & SPLICE_F_NONBLOCK) { - if (!ret) - ret = -EAGAIN; - break; - } - if (signal_pending(current)) { if (!ret) ret = -ERESTARTSYS; diff --git a/trunk/include/linux/netfilter/x_tables.h b/trunk/include/linux/netfilter/x_tables.h index f6bdef82a322..1350e47b0234 100644 --- a/trunk/include/linux/netfilter/x_tables.h +++ b/trunk/include/linux/netfilter/x_tables.h @@ -142,12 +142,6 @@ struct xt_counters_info #define ASSERT_WRITE_LOCK(x) #include -#ifdef CONFIG_COMPAT -#define COMPAT_TO_USER 1 -#define COMPAT_FROM_USER -1 -#define COMPAT_CALC_SIZE 0 -#endif - struct xt_match { struct list_head list; @@ -181,9 +175,6 @@ struct xt_match void (*destroy)(const struct xt_match *match, void *matchinfo, unsigned int matchinfosize); - /* Called when userspace align differs from kernel space one */ - int (*compat)(void *match, void **dstptr, int *size, int convert); - /* Set this to THIS_MODULE if you are a module, otherwise NULL */ struct module *me; @@ -229,9 +220,6 @@ struct xt_target void (*destroy)(const struct xt_target *target, void *targinfo, unsigned int targinfosize); - /* Called when userspace align differs from kernel space one */ - int (*compat)(void *target, void **dstptr, int *size, int convert); - /* Set this to THIS_MODULE if you are a module, otherwise NULL */ struct module *me; @@ -326,61 +314,6 @@ extern void xt_proto_fini(int af); extern struct xt_table_info *xt_alloc_table_info(unsigned int size); extern void xt_free_table_info(struct xt_table_info *info); -#ifdef CONFIG_COMPAT -#include - -struct compat_xt_entry_match -{ - union { - struct { - u_int16_t match_size; - char name[XT_FUNCTION_MAXNAMELEN - 1]; - u_int8_t revision; - } user; - u_int16_t match_size; - } u; - unsigned char data[0]; -}; - -struct compat_xt_entry_target -{ - union { - struct { - u_int16_t target_size; - char name[XT_FUNCTION_MAXNAMELEN - 1]; - u_int8_t revision; - } user; - u_int16_t target_size; - } u; - unsigned char data[0]; -}; - -/* FIXME: this works only on 32 bit tasks - * need to change whole approach in order to calculate align as function of - * current task alignment */ - -struct compat_xt_counters -{ - u_int32_t cnt[4]; -}; - -struct compat_xt_counters_info -{ - char name[XT_TABLE_MAXNAMELEN]; - compat_uint_t num_counters; - struct compat_xt_counters counters[0]; -}; - -#define COMPAT_XT_ALIGN(s) (((s) + (__alignof__(struct compat_xt_counters)-1)) \ - & ~(__alignof__(struct compat_xt_counters)-1)) - -extern void xt_compat_lock(int af); -extern void xt_compat_unlock(int af); -extern int xt_compat_match(void *match, void **dstptr, int *size, int convert); -extern int xt_compat_target(void *target, void **dstptr, int *size, - int convert); - -#endif /* CONFIG_COMPAT */ #endif /* __KERNEL__ */ #endif /* _X_TABLES_H */ diff --git a/trunk/include/linux/netfilter/xt_esp.h b/trunk/include/linux/netfilter/xt_esp.h deleted file mode 100644 index 9380fb1c27da..000000000000 --- a/trunk/include/linux/netfilter/xt_esp.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef _XT_ESP_H -#define _XT_ESP_H - -struct xt_esp -{ - u_int32_t spis[2]; /* Security Parameter Index */ - u_int8_t invflags; /* Inverse flags */ -}; - -/* Values for "invflags" field in struct xt_esp. */ -#define XT_ESP_INV_SPI 0x01 /* Invert the sense of spi. */ -#define XT_ESP_INV_MASK 0x01 /* All possible flags. */ - -#endif /*_XT_ESP_H*/ diff --git a/trunk/include/linux/netfilter/xt_multiport.h b/trunk/include/linux/netfilter/xt_multiport.h deleted file mode 100644 index d49ee4183710..000000000000 --- a/trunk/include/linux/netfilter/xt_multiport.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef _XT_MULTIPORT_H -#define _XT_MULTIPORT_H - -enum xt_multiport_flags -{ - XT_MULTIPORT_SOURCE, - XT_MULTIPORT_DESTINATION, - XT_MULTIPORT_EITHER -}; - -#define XT_MULTI_PORTS 15 - -/* Must fit inside union xt_matchinfo: 16 bytes */ -struct xt_multiport -{ - u_int8_t flags; /* Type of comparison */ - u_int8_t count; /* Number of ports */ - u_int16_t ports[XT_MULTI_PORTS]; /* Ports */ -}; - -struct xt_multiport_v1 -{ - u_int8_t flags; /* Type of comparison */ - u_int8_t count; /* Number of ports */ - u_int16_t ports[XT_MULTI_PORTS]; /* Ports */ - u_int8_t pflags[XT_MULTI_PORTS]; /* Port flags */ - u_int8_t invert; /* Invert flag */ -}; - -#endif /*_XT_MULTIPORT_H*/ diff --git a/trunk/include/linux/netfilter_ipv4/ip_tables.h b/trunk/include/linux/netfilter_ipv4/ip_tables.h index c0dac16e1902..d5b8c0d6a12b 100644 --- a/trunk/include/linux/netfilter_ipv4/ip_tables.h +++ b/trunk/include/linux/netfilter_ipv4/ip_tables.h @@ -316,23 +316,5 @@ extern unsigned int ipt_do_table(struct sk_buff **pskb, void *userdata); #define IPT_ALIGN(s) XT_ALIGN(s) - -#ifdef CONFIG_COMPAT -#include - -struct compat_ipt_entry -{ - struct ipt_ip ip; - compat_uint_t nfcache; - u_int16_t target_offset; - u_int16_t next_offset; - compat_uint_t comefrom; - struct compat_xt_counters counters; - unsigned char elems[0]; -}; - -#define COMPAT_IPT_ALIGN(s) COMPAT_XT_ALIGN(s) - -#endif /* CONFIG_COMPAT */ #endif /*__KERNEL__*/ #endif /* _IPTABLES_H */ diff --git a/trunk/include/linux/netfilter_ipv4/ipt_esp.h b/trunk/include/linux/netfilter_ipv4/ipt_esp.h index 78296e7eeff9..c782a83e53e0 100644 --- a/trunk/include/linux/netfilter_ipv4/ipt_esp.h +++ b/trunk/include/linux/netfilter_ipv4/ipt_esp.h @@ -1,10 +1,16 @@ #ifndef _IPT_ESP_H #define _IPT_ESP_H -#include +struct ipt_esp +{ + u_int32_t spis[2]; /* Security Parameter Index */ + u_int8_t invflags; /* Inverse flags */ +}; -#define ipt_esp xt_esp -#define IPT_ESP_INV_SPI XT_ESP_INV_SPI -#define IPT_ESP_INV_MASK XT_ESP_INV_MASK + + +/* Values for "invflags" field in struct ipt_esp. */ +#define IPT_ESP_INV_SPI 0x01 /* Invert the sense of spi. */ +#define IPT_ESP_INV_MASK 0x01 /* All possible flags. */ #endif /*_IPT_ESP_H*/ diff --git a/trunk/include/linux/netfilter_ipv4/ipt_multiport.h b/trunk/include/linux/netfilter_ipv4/ipt_multiport.h index 55fe85eca88c..e6b6fff811df 100644 --- a/trunk/include/linux/netfilter_ipv4/ipt_multiport.h +++ b/trunk/include/linux/netfilter_ipv4/ipt_multiport.h @@ -1,15 +1,30 @@ #ifndef _IPT_MULTIPORT_H #define _IPT_MULTIPORT_H +#include -#include +enum ipt_multiport_flags +{ + IPT_MULTIPORT_SOURCE, + IPT_MULTIPORT_DESTINATION, + IPT_MULTIPORT_EITHER +}; -#define IPT_MULTIPORT_SOURCE XT_MULTIPORT_SOURCE -#define IPT_MULTIPORT_DESTINATION XT_MULTIPORT_DESTINATION -#define IPT_MULTIPORT_EITHER XT_MULTIPORT_EITHER +#define IPT_MULTI_PORTS 15 -#define IPT_MULTI_PORTS XT_MULTI_PORTS - -#define ipt_multiport xt_multiport -#define ipt_multiport_v1 xt_multiport_v1 +/* Must fit inside union ipt_matchinfo: 16 bytes */ +struct ipt_multiport +{ + u_int8_t flags; /* Type of comparison */ + u_int8_t count; /* Number of ports */ + u_int16_t ports[IPT_MULTI_PORTS]; /* Ports */ +}; +struct ipt_multiport_v1 +{ + u_int8_t flags; /* Type of comparison */ + u_int8_t count; /* Number of ports */ + u_int16_t ports[IPT_MULTI_PORTS]; /* Ports */ + u_int8_t pflags[IPT_MULTI_PORTS]; /* Port flags */ + u_int8_t invert; /* Invert flag */ +}; #endif /*_IPT_MULTIPORT_H*/ diff --git a/trunk/include/linux/netfilter_ipv6/ip6t_esp.h b/trunk/include/linux/netfilter_ipv6/ip6t_esp.h index f62eaf53c16c..a91b6abc8079 100644 --- a/trunk/include/linux/netfilter_ipv6/ip6t_esp.h +++ b/trunk/include/linux/netfilter_ipv6/ip6t_esp.h @@ -1,10 +1,14 @@ #ifndef _IP6T_ESP_H #define _IP6T_ESP_H -#include +struct ip6t_esp +{ + u_int32_t spis[2]; /* Security Parameter Index */ + u_int8_t invflags; /* Inverse flags */ +}; -#define ip6t_esp xt_esp -#define IP6T_ESP_INV_SPI XT_ESP_INV_SPI -#define IP6T_ESP_INV_MASK XT_ESP_INV_MASK +/* Values for "invflags" field in struct ip6t_esp. */ +#define IP6T_ESP_INV_SPI 0x01 /* Invert the sense of spi. */ +#define IP6T_ESP_INV_MASK 0x01 /* All possible flags. */ #endif /*_IP6T_ESP_H*/ diff --git a/trunk/include/linux/netfilter_ipv6/ip6t_multiport.h b/trunk/include/linux/netfilter_ipv6/ip6t_multiport.h index 042c92661cee..efe4954a8681 100644 --- a/trunk/include/linux/netfilter_ipv6/ip6t_multiport.h +++ b/trunk/include/linux/netfilter_ipv6/ip6t_multiport.h @@ -1,14 +1,21 @@ #ifndef _IP6T_MULTIPORT_H #define _IP6T_MULTIPORT_H +#include -#include +enum ip6t_multiport_flags +{ + IP6T_MULTIPORT_SOURCE, + IP6T_MULTIPORT_DESTINATION, + IP6T_MULTIPORT_EITHER +}; -#define IP6T_MULTIPORT_SOURCE XT_MULTIPORT_SOURCE -#define IP6T_MULTIPORT_DESTINATION XT_MULTIPORT_DESTINATION -#define IP6T_MULTIPORT_EITHER XT_MULTIPORT_EITHER +#define IP6T_MULTI_PORTS 15 -#define IP6T_MULTI_PORTS XT_MULTI_PORTS - -#define ip6t_multiport xt_multiport - -#endif /*_IP6T_MULTIPORT_H*/ +/* Must fit inside union ip6t_matchinfo: 16 bytes */ +struct ip6t_multiport +{ + u_int8_t flags; /* Type of comparison */ + u_int8_t count; /* Number of ports */ + u_int16_t ports[IP6T_MULTI_PORTS]; /* Ports */ +}; +#endif /*_IPT_MULTIPORT_H*/ diff --git a/trunk/include/linux/pipe_fs_i.h b/trunk/include/linux/pipe_fs_i.h index d218fc729319..75c7f55023ab 100644 --- a/trunk/include/linux/pipe_fs_i.h +++ b/trunk/include/linux/pipe_fs_i.h @@ -60,8 +60,5 @@ void free_pipe_info(struct inode* inode); * add the splice flags here. */ #define SPLICE_F_MOVE (0x01) /* move pages instead of copying */ -#define SPLICE_F_NONBLOCK (0x02) /* don't block on the pipe splicing (but */ - /* we may still block on the fd we splice */ - /* from/to, of course */ #endif diff --git a/trunk/include/net/xfrm.h b/trunk/include/net/xfrm.h index 0d5529c382e8..e100291e43f4 100644 --- a/trunk/include/net/xfrm.h +++ b/trunk/include/net/xfrm.h @@ -242,6 +242,7 @@ extern int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo); extern void xfrm_state_delete_tunnel(struct xfrm_state *x); +struct xfrm_decap_state; struct xfrm_type { char *description; @@ -250,7 +251,7 @@ struct xfrm_type int (*init_state)(struct xfrm_state *x); void (*destructor)(struct xfrm_state *); - int (*input)(struct xfrm_state *, struct sk_buff *skb); + int (*input)(struct xfrm_state *, struct xfrm_decap_state *, struct sk_buff *skb); int (*output)(struct xfrm_state *, struct sk_buff *pskb); /* Estimate maximal size of result of transformation of a dgram */ u32 (*get_max_size)(struct xfrm_state *, int size); @@ -605,11 +606,25 @@ static inline void xfrm_dst_destroy(struct xfrm_dst *xdst) extern void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev); +/* Decapsulation state, used by the input to store data during + * decapsulation procedure, to be used later (during the policy + * check + */ +struct xfrm_decap_state { + char decap_data[20]; + __u16 decap_type; +}; + +struct sec_decap_state { + struct xfrm_state *xvec; + struct xfrm_decap_state decap; +}; + struct sec_path { atomic_t refcnt; int len; - struct xfrm_state *xvec[XFRM_MAX_DEPTH]; + struct sec_decap_state x[XFRM_MAX_DEPTH]; }; static inline struct sec_path * diff --git a/trunk/net/compat.c b/trunk/net/compat.c index d5d69fa15d07..8fd37cd7b501 100644 --- a/trunk/net/compat.c +++ b/trunk/net/compat.c @@ -476,7 +476,8 @@ asmlinkage long compat_sys_setsockopt(int fd, int level, int optname, int err; struct socket *sock; - if (level == SOL_IPV6 && optname == IPT_SO_SET_REPLACE) + /* SO_SET_REPLACE seems to be the same in all levels */ + if (optname == IPT_SO_SET_REPLACE) return do_netfilter_replace(fd, level, optname, optval, optlen); diff --git a/trunk/net/ipv4/ah4.c b/trunk/net/ipv4/ah4.c index e2e4771fa4c6..e16d8b42b953 100644 --- a/trunk/net/ipv4/ah4.c +++ b/trunk/net/ipv4/ah4.c @@ -116,7 +116,7 @@ static int ah_output(struct xfrm_state *x, struct sk_buff *skb) return err; } -static int ah_input(struct xfrm_state *x, struct sk_buff *skb) +static int ah_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb) { int ah_hlen; struct iphdr *iph; diff --git a/trunk/net/ipv4/esp4.c b/trunk/net/ipv4/esp4.c index 9d1881c07a32..bf88c620a954 100644 --- a/trunk/net/ipv4/esp4.c +++ b/trunk/net/ipv4/esp4.c @@ -133,7 +133,7 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb) * expensive, so we only support truncated data, which is the recommended * and common case. */ -static int esp_input(struct xfrm_state *x, struct sk_buff *skb) +static int esp_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb) { struct iphdr *iph; struct ip_esp_hdr *esph; @@ -208,6 +208,9 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb) struct xfrm_encap_tmpl *encap = x->encap; struct udphdr *uh; + if (encap->encap_type != decap->decap_type) + goto out; + uh = (struct udphdr *)(iph + 1); encap_len = (void*)esph - (void*)uh; diff --git a/trunk/net/ipv4/ipcomp.c b/trunk/net/ipv4/ipcomp.c index 0a1d86a0f632..c95020f7c81e 100644 --- a/trunk/net/ipv4/ipcomp.c +++ b/trunk/net/ipv4/ipcomp.c @@ -81,7 +81,8 @@ static int ipcomp_decompress(struct xfrm_state *x, struct sk_buff *skb) return err; } -static int ipcomp_input(struct xfrm_state *x, struct sk_buff *skb) +static int ipcomp_input(struct xfrm_state *x, + struct xfrm_decap_state *decap, struct sk_buff *skb) { u8 nexthdr; int err = 0; diff --git a/trunk/net/ipv4/netfilter/Kconfig b/trunk/net/ipv4/netfilter/Kconfig index 77855ccd6b43..882b842c25d4 100644 --- a/trunk/net/ipv4/netfilter/Kconfig +++ b/trunk/net/ipv4/netfilter/Kconfig @@ -221,6 +221,16 @@ config IP_NF_MATCH_IPRANGE To compile it as a module, choose M here. If unsure, say N. +config IP_NF_MATCH_MULTIPORT + tristate "Multiple port match support" + depends on IP_NF_IPTABLES + help + Multiport matching allows you to match TCP or UDP packets based on + a series of source or destination ports: normally a rule can only + match a single range of ports. + + To compile it as a module, choose M here. If unsure, say N. + config IP_NF_MATCH_TOS tristate "TOS match support" depends on IP_NF_IPTABLES @@ -262,12 +272,12 @@ config IP_NF_MATCH_DSCP To compile it as a module, choose M here. If unsure, say N. -config IP_NF_MATCH_AH - tristate "AH match support" +config IP_NF_MATCH_AH_ESP + tristate "AH/ESP match support" depends on IP_NF_IPTABLES help - This match extension allows you to match a range of SPIs - inside AH header of IPSec packets. + These two match extensions (`ah' and `esp') allow you to match a + range of SPIs inside AH or ESP headers of IPSec packets. To compile it as a module, choose M here. If unsure, say N. diff --git a/trunk/net/ipv4/netfilter/Makefile b/trunk/net/ipv4/netfilter/Makefile index 461cb1eb5de7..f2cd9a6c5b91 100644 --- a/trunk/net/ipv4/netfilter/Makefile +++ b/trunk/net/ipv4/netfilter/Makefile @@ -53,12 +53,13 @@ obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o # matches obj-$(CONFIG_IP_NF_MATCH_HASHLIMIT) += ipt_hashlimit.o obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o +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_RECENT) += ipt_recent.o obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o obj-$(CONFIG_IP_NF_MATCH_DSCP) += ipt_dscp.o -obj-$(CONFIG_IP_NF_MATCH_AH) += ipt_ah.o +obj-$(CONFIG_IP_NF_MATCH_AH_ESP) += ipt_ah.o ipt_esp.o obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o diff --git a/trunk/net/ipv4/netfilter/ip_conntrack_netlink.c b/trunk/net/ipv4/netfilter/ip_conntrack_netlink.c index 01bd7cab9367..9b6e19bae90f 100644 --- a/trunk/net/ipv4/netfilter/ip_conntrack_netlink.c +++ b/trunk/net/ipv4/netfilter/ip_conntrack_netlink.c @@ -1658,7 +1658,7 @@ static void __exit ctnetlink_exit(void) printk("ctnetlink: unregistering from nfnetlink.\n"); #ifdef CONFIG_IP_NF_CONNTRACK_EVENTS - ip_conntrack_expect_unregister_notifier(&ctnl_notifier_exp); + ip_conntrack_unregister_notifier(&ctnl_notifier_exp); ip_conntrack_unregister_notifier(&ctnl_notifier); #endif diff --git a/trunk/net/ipv4/netfilter/ip_tables.c b/trunk/net/ipv4/netfilter/ip_tables.c index d5b8cdd361ce..460fd905fad0 100644 --- a/trunk/net/ipv4/netfilter/ip_tables.c +++ b/trunk/net/ipv4/netfilter/ip_tables.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include @@ -800,11 +799,17 @@ get_counters(const struct xt_table_info *t, } } -static inline struct xt_counters * alloc_counters(struct ipt_table *table) +static int +copy_entries_to_user(unsigned int total_size, + struct ipt_table *table, + void __user *userptr) { - unsigned int countersize; + unsigned int off, num, countersize; + struct ipt_entry *e; struct xt_counters *counters; struct xt_table_info *private = table->private; + int ret = 0; + void *loc_cpu_entry; /* We need atomic snapshot of counters: rest doesn't change (other than comefrom, which userspace doesn't care @@ -813,32 +818,13 @@ static inline struct xt_counters * alloc_counters(struct ipt_table *table) counters = vmalloc_node(countersize, numa_node_id()); if (counters == NULL) - return ERR_PTR(-ENOMEM); + return -ENOMEM; /* First, sum counters... */ write_lock_bh(&table->lock); get_counters(private, counters); write_unlock_bh(&table->lock); - return counters; -} - -static int -copy_entries_to_user(unsigned int total_size, - struct ipt_table *table, - void __user *userptr) -{ - unsigned int off, num; - struct ipt_entry *e; - struct xt_counters *counters; - struct xt_table_info *private = table->private; - int ret = 0; - void *loc_cpu_entry; - - counters = alloc_counters(table); - if (IS_ERR(counters)) - return PTR_ERR(counters); - /* choose the copy that is on our node/cpu, ... * This choice is lazy (because current thread is * allowed to migrate to another cpu) @@ -894,903 +880,48 @@ copy_entries_to_user(unsigned int total_size, } free_counters: - vfree(counters); - return ret; -} - -#ifdef CONFIG_COMPAT -struct compat_delta { - struct compat_delta *next; - u_int16_t offset; - short delta; -}; - -static struct compat_delta *compat_offsets = NULL; - -static int compat_add_offset(u_int16_t offset, short delta) -{ - struct compat_delta *tmp; - - tmp = kmalloc(sizeof(struct compat_delta), GFP_KERNEL); - if (!tmp) - return -ENOMEM; - tmp->offset = offset; - tmp->delta = delta; - if (compat_offsets) { - tmp->next = compat_offsets->next; - compat_offsets->next = tmp; - } else { - compat_offsets = tmp; - tmp->next = NULL; - } - return 0; -} - -static void compat_flush_offsets(void) -{ - struct compat_delta *tmp, *next; - - if (compat_offsets) { - for(tmp = compat_offsets; tmp; tmp = next) { - next = tmp->next; - kfree(tmp); - } - compat_offsets = NULL; - } -} - -static short compat_calc_jump(u_int16_t offset) -{ - struct compat_delta *tmp; - short delta; - - for(tmp = compat_offsets, delta = 0; tmp; tmp = tmp->next) - if (tmp->offset < offset) - delta += tmp->delta; - return delta; -} - -struct compat_ipt_standard_target -{ - struct compat_xt_entry_target target; - compat_int_t verdict; -}; - -#define IPT_ST_OFFSET (sizeof(struct ipt_standard_target) - \ - sizeof(struct compat_ipt_standard_target)) - -struct compat_ipt_standard -{ - struct compat_ipt_entry entry; - struct compat_ipt_standard_target target; -}; - -static int compat_ipt_standard_fn(void *target, - void **dstptr, int *size, int convert) -{ - struct compat_ipt_standard_target compat_st, *pcompat_st; - struct ipt_standard_target st, *pst; - int ret; - - ret = 0; - switch (convert) { - case COMPAT_TO_USER: - pst = (struct ipt_standard_target *)target; - memcpy(&compat_st.target, &pst->target, - sizeof(struct ipt_entry_target)); - compat_st.verdict = pst->verdict; - if (compat_st.verdict > 0) - compat_st.verdict -= - compat_calc_jump(compat_st.verdict); - compat_st.target.u.user.target_size = - sizeof(struct compat_ipt_standard_target); - if (__copy_to_user(*dstptr, &compat_st, - sizeof(struct compat_ipt_standard_target))) - ret = -EFAULT; - *size -= IPT_ST_OFFSET; - *dstptr += sizeof(struct compat_ipt_standard_target); - break; - case COMPAT_FROM_USER: - pcompat_st = - (struct compat_ipt_standard_target *)target; - memcpy(&st.target, &pcompat_st->target, - sizeof(struct ipt_entry_target)); - st.verdict = pcompat_st->verdict; - if (st.verdict > 0) - st.verdict += compat_calc_jump(st.verdict); - st.target.u.user.target_size = - sizeof(struct ipt_standard_target); - memcpy(*dstptr, &st, - sizeof(struct ipt_standard_target)); - *size += IPT_ST_OFFSET; - *dstptr += sizeof(struct ipt_standard_target); - break; - case COMPAT_CALC_SIZE: - *size += IPT_ST_OFFSET; - break; - default: - ret = -ENOPROTOOPT; - break; - } - return ret; -} - -static inline int -compat_calc_match(struct ipt_entry_match *m, int * size) -{ - if (m->u.kernel.match->compat) - m->u.kernel.match->compat(m, NULL, size, COMPAT_CALC_SIZE); - else - xt_compat_match(m, NULL, size, COMPAT_CALC_SIZE); - return 0; -} - -static int compat_calc_entry(struct ipt_entry *e, struct xt_table_info *info, - void *base, struct xt_table_info *newinfo) -{ - struct ipt_entry_target *t; - u_int16_t entry_offset; - int off, i, ret; - - off = 0; - entry_offset = (void *)e - base; - IPT_MATCH_ITERATE(e, compat_calc_match, &off); - t = ipt_get_target(e); - if (t->u.kernel.target->compat) - t->u.kernel.target->compat(t, NULL, &off, COMPAT_CALC_SIZE); - else - xt_compat_target(t, NULL, &off, COMPAT_CALC_SIZE); - newinfo->size -= off; - ret = compat_add_offset(entry_offset, off); - if (ret) - return ret; - - for (i = 0; i< NF_IP_NUMHOOKS; i++) { - if (info->hook_entry[i] && (e < (struct ipt_entry *) - (base + info->hook_entry[i]))) - newinfo->hook_entry[i] -= off; - if (info->underflow[i] && (e < (struct ipt_entry *) - (base + info->underflow[i]))) - newinfo->underflow[i] -= off; - } - return 0; -} - -static int compat_table_info(struct xt_table_info *info, - struct xt_table_info *newinfo) -{ - void *loc_cpu_entry; - int i; - - if (!newinfo || !info) - return -EINVAL; - - memset(newinfo, 0, sizeof(struct xt_table_info)); - newinfo->size = info->size; - newinfo->number = info->number; - for (i = 0; i < NF_IP_NUMHOOKS; i++) { - newinfo->hook_entry[i] = info->hook_entry[i]; - newinfo->underflow[i] = info->underflow[i]; - } - loc_cpu_entry = info->entries[raw_smp_processor_id()]; - return IPT_ENTRY_ITERATE(loc_cpu_entry, info->size, - compat_calc_entry, info, loc_cpu_entry, newinfo); -} -#endif - -static int get_info(void __user *user, int *len, int compat) -{ - char name[IPT_TABLE_MAXNAMELEN]; - struct ipt_table *t; - int ret; - - if (*len != sizeof(struct ipt_getinfo)) { - duprintf("length %u != %u\n", *len, - (unsigned int)sizeof(struct ipt_getinfo)); - return -EINVAL; - } - - if (copy_from_user(name, user, sizeof(name)) != 0) - return -EFAULT; - - name[IPT_TABLE_MAXNAMELEN-1] = '\0'; -#ifdef CONFIG_COMPAT - if (compat) - xt_compat_lock(AF_INET); -#endif - t = try_then_request_module(xt_find_table_lock(AF_INET, name), - "iptable_%s", name); - if (t && !IS_ERR(t)) { - struct ipt_getinfo info; - struct xt_table_info *private = t->private; - -#ifdef CONFIG_COMPAT - if (compat) { - struct xt_table_info tmp; - ret = compat_table_info(private, &tmp); - compat_flush_offsets(); - private = &tmp; - } -#endif - info.valid_hooks = t->valid_hooks; - memcpy(info.hook_entry, private->hook_entry, - sizeof(info.hook_entry)); - memcpy(info.underflow, private->underflow, - sizeof(info.underflow)); - info.num_entries = private->number; - info.size = private->size; - strcpy(info.name, name); - - if (copy_to_user(user, &info, *len) != 0) - ret = -EFAULT; - else - ret = 0; - - xt_table_unlock(t); - module_put(t->me); - } else - ret = t ? PTR_ERR(t) : -ENOENT; -#ifdef CONFIG_COMPAT - if (compat) - xt_compat_unlock(AF_INET); -#endif - return ret; -} - -static int -get_entries(struct ipt_get_entries __user *uptr, int *len) -{ - int ret; - struct ipt_get_entries get; - struct ipt_table *t; - - if (*len < sizeof(get)) { - duprintf("get_entries: %u < %d\n", *len, - (unsigned int)sizeof(get)); - return -EINVAL; - } - if (copy_from_user(&get, uptr, sizeof(get)) != 0) - return -EFAULT; - if (*len != sizeof(struct ipt_get_entries) + get.size) { - duprintf("get_entries: %u != %u\n", *len, - (unsigned int)(sizeof(struct ipt_get_entries) + - get.size)); - return -EINVAL; - } - - t = xt_find_table_lock(AF_INET, get.name); - if (t && !IS_ERR(t)) { - struct xt_table_info *private = t->private; - duprintf("t->private->number = %u\n", - private->number); - if (get.size == private->size) - ret = copy_entries_to_user(private->size, - t, uptr->entrytable); - else { - duprintf("get_entries: I've got %u not %u!\n", - private->size, - get.size); - ret = -EINVAL; - } - module_put(t->me); - xt_table_unlock(t); - } else - ret = t ? PTR_ERR(t) : -ENOENT; - - return ret; -} - -static int -__do_replace(const char *name, unsigned int valid_hooks, - struct xt_table_info *newinfo, unsigned int num_counters, - void __user *counters_ptr) -{ - int ret; - struct ipt_table *t; - struct xt_table_info *oldinfo; - struct xt_counters *counters; - void *loc_cpu_old_entry; - - ret = 0; - counters = vmalloc(num_counters * sizeof(struct xt_counters)); - if (!counters) { - ret = -ENOMEM; - goto out; - } - - t = try_then_request_module(xt_find_table_lock(AF_INET, name), - "iptable_%s", name); - if (!t || IS_ERR(t)) { - ret = t ? PTR_ERR(t) : -ENOENT; - goto free_newinfo_counters_untrans; - } - - /* You lied! */ - if (valid_hooks != t->valid_hooks) { - duprintf("Valid hook crap: %08X vs %08X\n", - valid_hooks, t->valid_hooks); - ret = -EINVAL; - goto put_module; - } - - oldinfo = xt_replace_table(t, num_counters, newinfo, &ret); - if (!oldinfo) - goto put_module; - - /* Update module usage count based on number of rules */ - duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%u\n", - oldinfo->number, oldinfo->initial_entries, newinfo->number); - if ((oldinfo->number > oldinfo->initial_entries) || - (newinfo->number <= oldinfo->initial_entries)) - module_put(t->me); - if ((oldinfo->number > oldinfo->initial_entries) && - (newinfo->number <= oldinfo->initial_entries)) - module_put(t->me); - - /* Get the old counters. */ - get_counters(oldinfo, counters); - /* Decrease module usage counts and free resource */ - loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; - IPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,NULL); - xt_free_table_info(oldinfo); - if (copy_to_user(counters_ptr, counters, - sizeof(struct xt_counters) * num_counters) != 0) - ret = -EFAULT; - vfree(counters); - xt_table_unlock(t); - return ret; - - put_module: - module_put(t->me); - xt_table_unlock(t); - free_newinfo_counters_untrans: - vfree(counters); - out: - return ret; -} - -static int -do_replace(void __user *user, unsigned int len) -{ - int ret; - struct ipt_replace tmp; - struct xt_table_info *newinfo; - void *loc_cpu_entry; - - if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) - return -EFAULT; - - /* Hack: Causes ipchains to give correct error msg --RR */ - if (len != sizeof(tmp) + tmp.size) - return -ENOPROTOOPT; - - /* overflow check */ - if (tmp.size >= (INT_MAX - sizeof(struct xt_table_info)) / NR_CPUS - - SMP_CACHE_BYTES) - return -ENOMEM; - if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) - return -ENOMEM; - - newinfo = xt_alloc_table_info(tmp.size); - if (!newinfo) - return -ENOMEM; - - /* choose the copy that is our node/cpu */ - loc_cpu_entry = newinfo->entries[raw_smp_processor_id()]; - if (copy_from_user(loc_cpu_entry, user + sizeof(tmp), - tmp.size) != 0) { - ret = -EFAULT; - goto free_newinfo; - } - - ret = translate_table(tmp.name, tmp.valid_hooks, - newinfo, loc_cpu_entry, tmp.size, tmp.num_entries, - tmp.hook_entry, tmp.underflow); - if (ret != 0) - goto free_newinfo; - - duprintf("ip_tables: Translated table\n"); - - ret = __do_replace(tmp.name, tmp.valid_hooks, - newinfo, tmp.num_counters, - tmp.counters); - if (ret) - goto free_newinfo_untrans; - return 0; - - free_newinfo_untrans: - IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL); - free_newinfo: - xt_free_table_info(newinfo); - return ret; -} - -/* We're lazy, and add to the first CPU; overflow works its fey magic - * and everything is OK. */ -static inline int -add_counter_to_entry(struct ipt_entry *e, - const struct xt_counters addme[], - unsigned int *i) -{ -#if 0 - duprintf("add_counter: Entry %u %lu/%lu + %lu/%lu\n", - *i, - (long unsigned int)e->counters.pcnt, - (long unsigned int)e->counters.bcnt, - (long unsigned int)addme[*i].pcnt, - (long unsigned int)addme[*i].bcnt); -#endif - - ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt); - - (*i)++; - return 0; -} - -static int -do_add_counters(void __user *user, unsigned int len, int compat) -{ - unsigned int i; - struct xt_counters_info tmp; - struct xt_counters *paddc; - unsigned int num_counters; - char *name; - int size; - void *ptmp; - struct ipt_table *t; - struct xt_table_info *private; - int ret = 0; - void *loc_cpu_entry; -#ifdef CONFIG_COMPAT - struct compat_xt_counters_info compat_tmp; - - if (compat) { - ptmp = &compat_tmp; - size = sizeof(struct compat_xt_counters_info); - } else -#endif - { - ptmp = &tmp; - size = sizeof(struct xt_counters_info); - } - - if (copy_from_user(ptmp, user, size) != 0) - return -EFAULT; - -#ifdef CONFIG_COMPAT - if (compat) { - num_counters = compat_tmp.num_counters; - name = compat_tmp.name; - } else -#endif - { - num_counters = tmp.num_counters; - name = tmp.name; - } - - if (len != size + num_counters * sizeof(struct xt_counters)) - return -EINVAL; - - paddc = vmalloc_node(len - size, numa_node_id()); - if (!paddc) - return -ENOMEM; - - if (copy_from_user(paddc, user + size, len - size) != 0) { - ret = -EFAULT; - goto free; - } - - t = xt_find_table_lock(AF_INET, name); - if (!t || IS_ERR(t)) { - ret = t ? PTR_ERR(t) : -ENOENT; - goto free; - } - - write_lock_bh(&t->lock); - private = t->private; - if (private->number != num_counters) { - ret = -EINVAL; - goto unlock_up_free; - } - - i = 0; - /* Choose the copy that is on our node */ - loc_cpu_entry = private->entries[raw_smp_processor_id()]; - IPT_ENTRY_ITERATE(loc_cpu_entry, - private->size, - add_counter_to_entry, - paddc, - &i); - unlock_up_free: - write_unlock_bh(&t->lock); - xt_table_unlock(t); - module_put(t->me); - free: - vfree(paddc); - - return ret; -} - -#ifdef CONFIG_COMPAT -struct compat_ipt_replace { - char name[IPT_TABLE_MAXNAMELEN]; - u32 valid_hooks; - u32 num_entries; - u32 size; - u32 hook_entry[NF_IP_NUMHOOKS]; - u32 underflow[NF_IP_NUMHOOKS]; - u32 num_counters; - compat_uptr_t counters; /* struct ipt_counters * */ - struct compat_ipt_entry entries[0]; -}; - -static inline int compat_copy_match_to_user(struct ipt_entry_match *m, - void __user **dstptr, compat_uint_t *size) -{ - if (m->u.kernel.match->compat) - return m->u.kernel.match->compat(m, dstptr, size, - COMPAT_TO_USER); - else - return xt_compat_match(m, dstptr, size, COMPAT_TO_USER); -} - -static int compat_copy_entry_to_user(struct ipt_entry *e, - void __user **dstptr, compat_uint_t *size) -{ - struct ipt_entry_target __user *t; - struct compat_ipt_entry __user *ce; - u_int16_t target_offset, next_offset; - compat_uint_t origsize; - int ret; - - ret = -EFAULT; - origsize = *size; - ce = (struct compat_ipt_entry __user *)*dstptr; - if (__copy_to_user(ce, e, sizeof(struct ipt_entry))) - goto out; - - *dstptr += sizeof(struct compat_ipt_entry); - ret = IPT_MATCH_ITERATE(e, compat_copy_match_to_user, dstptr, size); - target_offset = e->target_offset - (origsize - *size); - if (ret) - goto out; - t = ipt_get_target(e); - if (t->u.kernel.target->compat) - ret = t->u.kernel.target->compat(t, dstptr, size, - COMPAT_TO_USER); - else - ret = xt_compat_target(t, dstptr, size, COMPAT_TO_USER); - if (ret) - goto out; - ret = -EFAULT; - next_offset = e->next_offset - (origsize - *size); - if (__put_user(target_offset, &ce->target_offset)) - goto out; - if (__put_user(next_offset, &ce->next_offset)) - goto out; - return 0; -out: - return ret; -} - -static inline int -compat_check_calc_match(struct ipt_entry_match *m, - const char *name, - const struct ipt_ip *ip, - unsigned int hookmask, - int *size, int *i) -{ - struct ipt_match *match; - - match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name, - m->u.user.revision), - "ipt_%s", m->u.user.name); - if (IS_ERR(match) || !match) { - duprintf("compat_check_calc_match: `%s' not found\n", - m->u.user.name); - return match ? PTR_ERR(match) : -ENOENT; - } - m->u.kernel.match = match; - - if (m->u.kernel.match->compat) - m->u.kernel.match->compat(m, NULL, size, COMPAT_CALC_SIZE); - else - xt_compat_match(m, NULL, size, COMPAT_CALC_SIZE); - - (*i)++; - return 0; -} - -static inline int -check_compat_entry_size_and_hooks(struct ipt_entry *e, - struct xt_table_info *newinfo, - unsigned int *size, - unsigned char *base, - unsigned char *limit, - unsigned int *hook_entries, - unsigned int *underflows, - unsigned int *i, - const char *name) -{ - struct ipt_entry_target *t; - struct ipt_target *target; - u_int16_t entry_offset; - int ret, off, h, j; - - duprintf("check_compat_entry_size_and_hooks %p\n", e); - if ((unsigned long)e % __alignof__(struct compat_ipt_entry) != 0 - || (unsigned char *)e + sizeof(struct compat_ipt_entry) >= limit) { - duprintf("Bad offset %p, limit = %p\n", e, limit); - return -EINVAL; - } - - if (e->next_offset < sizeof(struct compat_ipt_entry) + - sizeof(struct compat_xt_entry_target)) { - duprintf("checking: element %p size %u\n", - e, e->next_offset); - return -EINVAL; - } - - if (!ip_checkentry(&e->ip)) { - duprintf("ip_tables: ip check failed %p %s.\n", e, name); - return -EINVAL; - } - - off = 0; - entry_offset = (void *)e - (void *)base; - j = 0; - ret = IPT_MATCH_ITERATE(e, compat_check_calc_match, name, &e->ip, - e->comefrom, &off, &j); - if (ret != 0) - goto out; - - t = ipt_get_target(e); - target = try_then_request_module(xt_find_target(AF_INET, - t->u.user.name, - t->u.user.revision), - "ipt_%s", t->u.user.name); - if (IS_ERR(target) || !target) { - duprintf("check_entry: `%s' not found\n", t->u.user.name); - ret = target ? PTR_ERR(target) : -ENOENT; - goto out; - } - t->u.kernel.target = target; - - if (t->u.kernel.target->compat) - t->u.kernel.target->compat(t, NULL, &off, COMPAT_CALC_SIZE); - else - xt_compat_target(t, NULL, &off, COMPAT_CALC_SIZE); - *size += off; - ret = compat_add_offset(entry_offset, off); - if (ret) - goto out; - - /* Check hooks & underflows */ - for (h = 0; h < NF_IP_NUMHOOKS; h++) { - if ((unsigned char *)e - base == hook_entries[h]) - newinfo->hook_entry[h] = hook_entries[h]; - if ((unsigned char *)e - base == underflows[h]) - newinfo->underflow[h] = underflows[h]; - } - - /* Clear counters and comefrom */ - e->counters = ((struct ipt_counters) { 0, 0 }); - e->comefrom = 0; - - (*i)++; - return 0; -out: - IPT_MATCH_ITERATE(e, cleanup_match, &j); - return ret; -} - -static inline int compat_copy_match_from_user(struct ipt_entry_match *m, - void **dstptr, compat_uint_t *size, const char *name, - const struct ipt_ip *ip, unsigned int hookmask) -{ - struct ipt_entry_match *dm; - struct ipt_match *match; - int ret; - - dm = (struct ipt_entry_match *)*dstptr; - match = m->u.kernel.match; - if (match->compat) - match->compat(m, dstptr, size, COMPAT_FROM_USER); - else - xt_compat_match(m, dstptr, size, COMPAT_FROM_USER); - - ret = xt_check_match(match, AF_INET, dm->u.match_size - sizeof(*dm), - name, hookmask, ip->proto, - ip->invflags & IPT_INV_PROTO); - if (ret) - return ret; - - if (m->u.kernel.match->checkentry - && !m->u.kernel.match->checkentry(name, ip, match, dm->data, - dm->u.match_size - sizeof(*dm), - hookmask)) { - duprintf("ip_tables: check failed for `%s'.\n", - m->u.kernel.match->name); - return -EINVAL; - } - return 0; -} - -static int compat_copy_entry_from_user(struct ipt_entry *e, void **dstptr, - unsigned int *size, const char *name, - struct xt_table_info *newinfo, unsigned char *base) -{ - struct ipt_entry_target *t; - struct ipt_target *target; - struct ipt_entry *de; - unsigned int origsize; - int ret, h; - - ret = 0; - origsize = *size; - de = (struct ipt_entry *)*dstptr; - memcpy(de, e, sizeof(struct ipt_entry)); - - *dstptr += sizeof(struct compat_ipt_entry); - ret = IPT_MATCH_ITERATE(e, compat_copy_match_from_user, dstptr, size, - name, &de->ip, de->comefrom); - if (ret) - goto out; - de->target_offset = e->target_offset - (origsize - *size); - t = ipt_get_target(e); - target = t->u.kernel.target; - if (target->compat) - target->compat(t, dstptr, size, COMPAT_FROM_USER); - else - xt_compat_target(t, dstptr, size, COMPAT_FROM_USER); - - de->next_offset = e->next_offset - (origsize - *size); - for (h = 0; h < NF_IP_NUMHOOKS; h++) { - if ((unsigned char *)de - base < newinfo->hook_entry[h]) - newinfo->hook_entry[h] -= origsize - *size; - if ((unsigned char *)de - base < newinfo->underflow[h]) - newinfo->underflow[h] -= origsize - *size; - } - - t = ipt_get_target(de); - target = t->u.kernel.target; - ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t), - name, e->comefrom, e->ip.proto, - e->ip.invflags & IPT_INV_PROTO); - if (ret) - goto out; - - ret = -EINVAL; - if (t->u.kernel.target == &ipt_standard_target) { - if (!standard_check(t, *size)) - goto out; - } else if (t->u.kernel.target->checkentry - && !t->u.kernel.target->checkentry(name, de, target, - t->data, t->u.target_size - sizeof(*t), - de->comefrom)) { - duprintf("ip_tables: compat: check failed for `%s'.\n", - t->u.kernel.target->name); - goto out; - } - ret = 0; -out: + vfree(counters); return ret; } static int -translate_compat_table(const char *name, - unsigned int valid_hooks, - struct xt_table_info **pinfo, - void **pentry0, - unsigned int total_size, - unsigned int number, - unsigned int *hook_entries, - unsigned int *underflows) +get_entries(const struct ipt_get_entries *entries, + struct ipt_get_entries __user *uptr) { - unsigned int i; - struct xt_table_info *newinfo, *info; - void *pos, *entry0, *entry1; - unsigned int size; int ret; + struct ipt_table *t; - info = *pinfo; - entry0 = *pentry0; - size = total_size; - info->number = number; - - /* Init all hooks to impossible value. */ - for (i = 0; i < NF_IP_NUMHOOKS; i++) { - info->hook_entry[i] = 0xFFFFFFFF; - info->underflow[i] = 0xFFFFFFFF; - } - - duprintf("translate_compat_table: size %u\n", info->size); - i = 0; - xt_compat_lock(AF_INET); - /* Walk through entries, checking offsets. */ - ret = IPT_ENTRY_ITERATE(entry0, total_size, - check_compat_entry_size_and_hooks, - info, &size, entry0, - entry0 + total_size, - hook_entries, underflows, &i, name); - if (ret != 0) - goto out_unlock; - - ret = -EINVAL; - if (i != number) { - duprintf("translate_compat_table: %u not %u entries\n", - i, number); - goto out_unlock; - } - - /* Check hooks all assigned */ - for (i = 0; i < NF_IP_NUMHOOKS; i++) { - /* Only hooks which are valid */ - if (!(valid_hooks & (1 << i))) - continue; - if (info->hook_entry[i] == 0xFFFFFFFF) { - duprintf("Invalid hook entry %u %u\n", - i, hook_entries[i]); - goto out_unlock; - } - if (info->underflow[i] == 0xFFFFFFFF) { - duprintf("Invalid underflow %u %u\n", - i, underflows[i]); - goto out_unlock; + t = xt_find_table_lock(AF_INET, entries->name); + if (t && !IS_ERR(t)) { + struct xt_table_info *private = t->private; + duprintf("t->private->number = %u\n", + private->number); + if (entries->size == private->size) + ret = copy_entries_to_user(private->size, + t, uptr->entrytable); + else { + duprintf("get_entries: I've got %u not %u!\n", + private->size, + entries->size); + ret = -EINVAL; } - } - - ret = -ENOMEM; - newinfo = xt_alloc_table_info(size); - if (!newinfo) - goto out_unlock; - - newinfo->number = number; - for (i = 0; i < NF_IP_NUMHOOKS; i++) { - newinfo->hook_entry[i] = info->hook_entry[i]; - newinfo->underflow[i] = info->underflow[i]; - } - entry1 = newinfo->entries[raw_smp_processor_id()]; - pos = entry1; - size = total_size; - ret = IPT_ENTRY_ITERATE(entry0, total_size, - compat_copy_entry_from_user, &pos, &size, - name, newinfo, entry1); - compat_flush_offsets(); - xt_compat_unlock(AF_INET); - if (ret) - goto free_newinfo; - - ret = -ELOOP; - if (!mark_source_chains(newinfo, valid_hooks, entry1)) - goto free_newinfo; - - /* And one copy for every other CPU */ - for_each_cpu(i) - if (newinfo->entries[i] && newinfo->entries[i] != entry1) - memcpy(newinfo->entries[i], entry1, newinfo->size); - - *pinfo = newinfo; - *pentry0 = entry1; - xt_free_table_info(info); - return 0; + module_put(t->me); + xt_table_unlock(t); + } else + ret = t ? PTR_ERR(t) : -ENOENT; -free_newinfo: - xt_free_table_info(newinfo); -out: return ret; -out_unlock: - xt_compat_unlock(AF_INET); - goto out; } static int -compat_do_replace(void __user *user, unsigned int len) +do_replace(void __user *user, unsigned int len) { int ret; - struct compat_ipt_replace tmp; - struct xt_table_info *newinfo; - void *loc_cpu_entry; + struct ipt_replace tmp; + struct ipt_table *t; + struct xt_table_info *newinfo, *oldinfo; + struct xt_counters *counters; + void *loc_cpu_entry, *loc_cpu_old_entry; if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) return -EFAULT; @@ -1818,201 +949,151 @@ compat_do_replace(void __user *user, unsigned int len) goto free_newinfo; } - ret = translate_compat_table(tmp.name, tmp.valid_hooks, - &newinfo, &loc_cpu_entry, tmp.size, - tmp.num_entries, tmp.hook_entry, tmp.underflow); - if (ret != 0) + counters = vmalloc(tmp.num_counters * sizeof(struct xt_counters)); + if (!counters) { + ret = -ENOMEM; goto free_newinfo; + } - duprintf("compat_do_replace: Translated table\n"); - - ret = __do_replace(tmp.name, tmp.valid_hooks, - newinfo, tmp.num_counters, - compat_ptr(tmp.counters)); - if (ret) - goto free_newinfo_untrans; - return 0; + ret = translate_table(tmp.name, tmp.valid_hooks, + newinfo, loc_cpu_entry, tmp.size, tmp.num_entries, + tmp.hook_entry, tmp.underflow); + if (ret != 0) + goto free_newinfo_counters; - free_newinfo_untrans: - IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL); - free_newinfo: - xt_free_table_info(newinfo); - return ret; -} + duprintf("ip_tables: Translated table\n"); -static int -compat_do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, - unsigned int len) -{ - int ret; + t = try_then_request_module(xt_find_table_lock(AF_INET, tmp.name), + "iptable_%s", tmp.name); + if (!t || IS_ERR(t)) { + ret = t ? PTR_ERR(t) : -ENOENT; + goto free_newinfo_counters_untrans; + } - if (!capable(CAP_NET_ADMIN)) - return -EPERM; + /* You lied! */ + if (tmp.valid_hooks != t->valid_hooks) { + duprintf("Valid hook crap: %08X vs %08X\n", + tmp.valid_hooks, t->valid_hooks); + ret = -EINVAL; + goto put_module; + } - switch (cmd) { - case IPT_SO_SET_REPLACE: - ret = compat_do_replace(user, len); - break; + oldinfo = xt_replace_table(t, tmp.num_counters, newinfo, &ret); + if (!oldinfo) + goto put_module; - case IPT_SO_SET_ADD_COUNTERS: - ret = do_add_counters(user, len, 1); - break; + /* Update module usage count based on number of rules */ + duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%u\n", + oldinfo->number, oldinfo->initial_entries, newinfo->number); + if ((oldinfo->number > oldinfo->initial_entries) || + (newinfo->number <= oldinfo->initial_entries)) + module_put(t->me); + if ((oldinfo->number > oldinfo->initial_entries) && + (newinfo->number <= oldinfo->initial_entries)) + module_put(t->me); - default: - duprintf("do_ipt_set_ctl: unknown request %i\n", cmd); - ret = -EINVAL; - } + /* Get the old counters. */ + get_counters(oldinfo, counters); + /* Decrease module usage counts and free resource */ + loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; + IPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,NULL); + xt_free_table_info(oldinfo); + if (copy_to_user(tmp.counters, counters, + sizeof(struct xt_counters) * tmp.num_counters) != 0) + ret = -EFAULT; + vfree(counters); + xt_table_unlock(t); + return ret; + put_module: + module_put(t->me); + xt_table_unlock(t); + free_newinfo_counters_untrans: + IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL); + free_newinfo_counters: + vfree(counters); + free_newinfo: + xt_free_table_info(newinfo); return ret; } -struct compat_ipt_get_entries -{ - char name[IPT_TABLE_MAXNAMELEN]; - compat_uint_t size; - struct compat_ipt_entry entrytable[0]; -}; - -static int compat_copy_entries_to_user(unsigned int total_size, - struct ipt_table *table, void __user *userptr) +/* We're lazy, and add to the first CPU; overflow works its fey magic + * and everything is OK. */ +static inline int +add_counter_to_entry(struct ipt_entry *e, + const struct xt_counters addme[], + unsigned int *i) { - unsigned int off, num; - struct compat_ipt_entry e; - struct xt_counters *counters; - struct xt_table_info *private = table->private; - void __user *pos; - unsigned int size; - int ret = 0; - void *loc_cpu_entry; - - counters = alloc_counters(table); - if (IS_ERR(counters)) - return PTR_ERR(counters); - - /* choose the copy that is on our node/cpu, ... - * This choice is lazy (because current thread is - * allowed to migrate to another cpu) - */ - loc_cpu_entry = private->entries[raw_smp_processor_id()]; - pos = userptr; - size = total_size; - ret = IPT_ENTRY_ITERATE(loc_cpu_entry, total_size, - compat_copy_entry_to_user, &pos, &size); - if (ret) - goto free_counters; - - /* ... then go back and fix counters and names */ - for (off = 0, num = 0; off < size; off += e.next_offset, num++) { - unsigned int i; - struct ipt_entry_match m; - struct ipt_entry_target t; - - ret = -EFAULT; - if (copy_from_user(&e, userptr + off, - sizeof(struct compat_ipt_entry))) - goto free_counters; - if (copy_to_user(userptr + off + - offsetof(struct compat_ipt_entry, counters), - &counters[num], sizeof(counters[num]))) - goto free_counters; +#if 0 + duprintf("add_counter: Entry %u %lu/%lu + %lu/%lu\n", + *i, + (long unsigned int)e->counters.pcnt, + (long unsigned int)e->counters.bcnt, + (long unsigned int)addme[*i].pcnt, + (long unsigned int)addme[*i].bcnt); +#endif - for (i = sizeof(struct compat_ipt_entry); - i < e.target_offset; i += m.u.match_size) { - if (copy_from_user(&m, userptr + off + i, - sizeof(struct ipt_entry_match))) - goto free_counters; - if (copy_to_user(userptr + off + i + - offsetof(struct ipt_entry_match, u.user.name), - m.u.kernel.match->name, - strlen(m.u.kernel.match->name) + 1)) - goto free_counters; - } + ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt); - if (copy_from_user(&t, userptr + off + e.target_offset, - sizeof(struct ipt_entry_target))) - goto free_counters; - if (copy_to_user(userptr + off + e.target_offset + - offsetof(struct ipt_entry_target, u.user.name), - t.u.kernel.target->name, - strlen(t.u.kernel.target->name) + 1)) - goto free_counters; - } - ret = 0; -free_counters: - vfree(counters); - return ret; + (*i)++; + return 0; } static int -compat_get_entries(struct compat_ipt_get_entries __user *uptr, int *len) +do_add_counters(void __user *user, unsigned int len) { - int ret; - struct compat_ipt_get_entries get; + unsigned int i; + struct xt_counters_info tmp, *paddc; struct ipt_table *t; + struct xt_table_info *private; + int ret = 0; + void *loc_cpu_entry; + if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) + return -EFAULT; - if (*len < sizeof(get)) { - duprintf("compat_get_entries: %u < %u\n", - *len, (unsigned int)sizeof(get)); + if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct xt_counters)) return -EINVAL; - } - if (copy_from_user(&get, uptr, sizeof(get)) != 0) - return -EFAULT; + paddc = vmalloc_node(len, numa_node_id()); + if (!paddc) + return -ENOMEM; - if (*len != sizeof(struct compat_ipt_get_entries) + get.size) { - duprintf("compat_get_entries: %u != %u\n", *len, - (unsigned int)(sizeof(struct compat_ipt_get_entries) + - get.size)); - return -EINVAL; + if (copy_from_user(paddc, user, len) != 0) { + ret = -EFAULT; + goto free; } - xt_compat_lock(AF_INET); - t = xt_find_table_lock(AF_INET, get.name); - if (t && !IS_ERR(t)) { - struct xt_table_info *private = t->private; - struct xt_table_info info; - duprintf("t->private->number = %u\n", - private->number); - ret = compat_table_info(private, &info); - if (!ret && get.size == info.size) { - ret = compat_copy_entries_to_user(private->size, - t, uptr->entrytable); - } else if (!ret) { - duprintf("compat_get_entries: I've got %u not %u!\n", - private->size, - get.size); - ret = -EINVAL; - } - compat_flush_offsets(); - module_put(t->me); - xt_table_unlock(t); - } else + t = xt_find_table_lock(AF_INET, tmp.name); + if (!t || IS_ERR(t)) { ret = t ? PTR_ERR(t) : -ENOENT; + goto free; + } - xt_compat_unlock(AF_INET); - return ret; -} - -static int -compat_do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) -{ - int ret; - - switch (cmd) { - case IPT_SO_GET_INFO: - ret = get_info(user, len, 1); - break; - case IPT_SO_GET_ENTRIES: - ret = compat_get_entries(user, len); - break; - default: - duprintf("compat_do_ipt_get_ctl: unknown request %i\n", cmd); + write_lock_bh(&t->lock); + private = t->private; + if (private->number != paddc->num_counters) { ret = -EINVAL; + goto unlock_up_free; } + + i = 0; + /* Choose the copy that is on our node */ + loc_cpu_entry = private->entries[raw_smp_processor_id()]; + IPT_ENTRY_ITERATE(loc_cpu_entry, + private->size, + add_counter_to_entry, + paddc->counters, + &i); + unlock_up_free: + write_unlock_bh(&t->lock); + xt_table_unlock(t); + module_put(t->me); + free: + vfree(paddc); + return ret; } -#endif static int do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len) @@ -2028,7 +1109,7 @@ do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len) break; case IPT_SO_SET_ADD_COUNTERS: - ret = do_add_counters(user, len, 0); + ret = do_add_counters(user, len); break; default: @@ -2048,13 +1129,65 @@ do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) return -EPERM; switch (cmd) { - case IPT_SO_GET_INFO: - ret = get_info(user, len, 0); - break; + case IPT_SO_GET_INFO: { + char name[IPT_TABLE_MAXNAMELEN]; + struct ipt_table *t; + + if (*len != sizeof(struct ipt_getinfo)) { + duprintf("length %u != %u\n", *len, + sizeof(struct ipt_getinfo)); + ret = -EINVAL; + break; + } + + if (copy_from_user(name, user, sizeof(name)) != 0) { + ret = -EFAULT; + break; + } + name[IPT_TABLE_MAXNAMELEN-1] = '\0'; + + t = try_then_request_module(xt_find_table_lock(AF_INET, name), + "iptable_%s", name); + if (t && !IS_ERR(t)) { + struct ipt_getinfo info; + struct xt_table_info *private = t->private; + + info.valid_hooks = t->valid_hooks; + memcpy(info.hook_entry, private->hook_entry, + sizeof(info.hook_entry)); + memcpy(info.underflow, private->underflow, + sizeof(info.underflow)); + info.num_entries = private->number; + info.size = private->size; + memcpy(info.name, name, sizeof(info.name)); + + if (copy_to_user(user, &info, *len) != 0) + ret = -EFAULT; + else + ret = 0; + xt_table_unlock(t); + module_put(t->me); + } else + ret = t ? PTR_ERR(t) : -ENOENT; + } + break; - case IPT_SO_GET_ENTRIES: - ret = get_entries(user, len); + case IPT_SO_GET_ENTRIES: { + struct ipt_get_entries get; + + if (*len < sizeof(get)) { + duprintf("get_entries: %u < %u\n", *len, sizeof(get)); + ret = -EINVAL; + } else if (copy_from_user(&get, user, sizeof(get)) != 0) { + ret = -EFAULT; + } else if (*len != sizeof(struct ipt_get_entries) + get.size) { + duprintf("get_entries: %u != %u\n", *len, + sizeof(struct ipt_get_entries) + get.size); + ret = -EINVAL; + } else + ret = get_entries(&get, user); break; + } case IPT_SO_GET_REVISION_MATCH: case IPT_SO_GET_REVISION_TARGET: { @@ -2203,9 +1336,6 @@ static struct ipt_target ipt_standard_target = { .name = IPT_STANDARD_TARGET, .targetsize = sizeof(int), .family = AF_INET, -#ifdef CONFIG_COMPAT - .compat = &compat_ipt_standard_fn, -#endif }; static struct ipt_target ipt_error_target = { @@ -2220,15 +1350,9 @@ static struct nf_sockopt_ops ipt_sockopts = { .set_optmin = IPT_BASE_CTL, .set_optmax = IPT_SO_SET_MAX+1, .set = do_ipt_set_ctl, -#ifdef CONFIG_COMPAT - .compat_set = compat_do_ipt_set_ctl, -#endif .get_optmin = IPT_BASE_CTL, .get_optmax = IPT_SO_GET_MAX+1, .get = do_ipt_get_ctl, -#ifdef CONFIG_COMPAT - .compat_get = compat_do_ipt_get_ctl, -#endif }; static struct ipt_match icmp_matchstruct = { diff --git a/trunk/net/netfilter/xt_esp.c b/trunk/net/ipv4/netfilter/ipt_esp.c similarity index 51% rename from trunk/net/netfilter/xt_esp.c rename to trunk/net/ipv4/netfilter/ipt_esp.c index 9dad6281e0c1..3840b417a3c5 100644 --- a/trunk/net/netfilter/xt_esp.c +++ b/trunk/net/ipv4/netfilter/ipt_esp.c @@ -9,22 +9,16 @@ #include #include -#include #include -#include -#include - +#include #include -#include MODULE_LICENSE("GPL"); MODULE_AUTHOR("Yon Uriarte "); -MODULE_DESCRIPTION("x_tables ESP SPI match module"); -MODULE_ALIAS("ipt_esp"); -MODULE_ALIAS("ip6t_esp"); +MODULE_DESCRIPTION("iptables ESP SPI match module"); -#if 0 +#ifdef DEBUG_CONNTRACK #define duprintf(format, args...) printk(format , ## args) #else #define duprintf(format, args...) @@ -34,11 +28,11 @@ MODULE_ALIAS("ip6t_esp"); static inline int spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, int invert) { - int r = 0; - duprintf("esp spi_match:%c 0x%x <= 0x%x <= 0x%x", invert ? '!' : ' ', - min, spi, max); - r = (spi >= min && spi <= max) ^ invert; - duprintf(" result %s\n", r ? "PASS" : "FAILED"); + int r=0; + duprintf("esp spi_match:%c 0x%x <= 0x%x <= 0x%x",invert? '!':' ', + min,spi,max); + r=(spi >= min && spi <= max) ^ invert; + duprintf(" result %s\n",r? "PASS" : "FAILED"); return r; } @@ -53,13 +47,14 @@ match(const struct sk_buff *skb, int *hotdrop) { struct ip_esp_hdr _esp, *eh; - const struct xt_esp *espinfo = matchinfo; + const struct ipt_esp *espinfo = matchinfo; /* Must not be a fragment. */ if (offset) return 0; - eh = skb_header_pointer(skb, protoff, sizeof(_esp), &_esp); + eh = skb_header_pointer(skb, protoff, + sizeof(_esp), &_esp); if (eh == NULL) { /* We've been asked to examine this packet, and we * can't. Hence, no choice but to drop. @@ -69,8 +64,9 @@ match(const struct sk_buff *skb, return 0; } - return spi_match(espinfo->spis[0], espinfo->spis[1], ntohl(eh->spi), - !!(espinfo->invflags & XT_ESP_INV_SPI)); + return spi_match(espinfo->spis[0], espinfo->spis[1], + ntohl(eh->spi), + !!(espinfo->invflags & IPT_ESP_INV_SPI)); } /* Called when user tries to insert an entry of this type. */ @@ -82,55 +78,34 @@ checkentry(const char *tablename, unsigned int matchinfosize, unsigned int hook_mask) { - const struct xt_esp *espinfo = matchinfo; + const struct ipt_esp *espinfo = matchinfo; - if (espinfo->invflags & ~XT_ESP_INV_MASK) { - duprintf("xt_esp: unknown flags %X\n", espinfo->invflags); + /* Must specify no unknown invflags */ + if (espinfo->invflags & ~IPT_ESP_INV_MASK) { + duprintf("ipt_esp: unknown flags %X\n", espinfo->invflags); return 0; } - return 1; } -static struct xt_match esp_match = { +static struct ipt_match esp_match = { .name = "esp", - .family = AF_INET, + .match = match, + .matchsize = sizeof(struct ipt_esp), .proto = IPPROTO_ESP, - .match = &match, - .matchsize = sizeof(struct xt_esp), - .checkentry = &checkentry, + .checkentry = checkentry, .me = THIS_MODULE, }; -static struct xt_match esp6_match = { - .name = "esp", - .family = AF_INET6, - .proto = IPPROTO_ESP, - .match = &match, - .matchsize = sizeof(struct xt_esp), - .checkentry = &checkentry, - .me = THIS_MODULE, -}; - -static int __init xt_esp_init(void) +static int __init ipt_esp_init(void) { - int ret; - ret = xt_register_match(&esp_match); - if (ret) - return ret; - - ret = xt_register_match(&esp6_match); - if (ret) - xt_unregister_match(&esp_match); - - return ret; + return ipt_register_match(&esp_match); } -static void __exit xt_esp_cleanup(void) +static void __exit ipt_esp_fini(void) { - xt_unregister_match(&esp_match); - xt_unregister_match(&esp6_match); + ipt_unregister_match(&esp_match); } -module_init(xt_esp_init); -module_exit(xt_esp_cleanup); +module_init(ipt_esp_init); +module_exit(ipt_esp_fini); diff --git a/trunk/net/ipv4/netfilter/ipt_multiport.c b/trunk/net/ipv4/netfilter/ipt_multiport.c new file mode 100644 index 000000000000..ac95d8390bcc --- /dev/null +++ b/trunk/net/ipv4/netfilter/ipt_multiport.c @@ -0,0 +1,195 @@ +/* Kernel module to match one of a list of TCP/UDP ports: ports are in + the same place so we can treat them as equal. */ + +/* (C) 1999-2001 Paul `Rusty' Russell + * (C) 2002-2004 Netfilter Core Team + * + * 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 +#include +#include +#include + +#include +#include + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Netfilter Core Team "); +MODULE_DESCRIPTION("iptables multiple port match module"); + +#if 0 +#define duprintf(format, args...) printk(format , ## args) +#else +#define duprintf(format, args...) +#endif + +/* Returns 1 if the port is matched by the test, 0 otherwise. */ +static inline int +ports_match(const u_int16_t *portlist, enum ipt_multiport_flags flags, + u_int8_t count, u_int16_t src, u_int16_t dst) +{ + unsigned int i; + for (i=0; icount; i++) { + s = minfo->ports[i]; + + if (minfo->pflags[i]) { + /* range port matching */ + e = minfo->ports[++i]; + duprintf("src or dst matches with %d-%d?\n", s, e); + + if (minfo->flags == IPT_MULTIPORT_SOURCE + && src >= s && src <= e) + return 1 ^ minfo->invert; + if (minfo->flags == IPT_MULTIPORT_DESTINATION + && dst >= s && dst <= e) + return 1 ^ minfo->invert; + if (minfo->flags == IPT_MULTIPORT_EITHER + && ((dst >= s && dst <= e) + || (src >= s && src <= e))) + return 1 ^ minfo->invert; + } else { + /* exact port matching */ + duprintf("src or dst matches with %d?\n", s); + + if (minfo->flags == IPT_MULTIPORT_SOURCE + && src == s) + return 1 ^ minfo->invert; + if (minfo->flags == IPT_MULTIPORT_DESTINATION + && dst == s) + return 1 ^ minfo->invert; + if (minfo->flags == IPT_MULTIPORT_EITHER + && (src == s || dst == s)) + return 1 ^ minfo->invert; + } + } + + return minfo->invert; +} + +static int +match(const struct sk_buff *skb, + const struct net_device *in, + const struct net_device *out, + const struct xt_match *match, + const void *matchinfo, + int offset, + unsigned int protoff, + int *hotdrop) +{ + u16 _ports[2], *pptr; + const struct ipt_multiport *multiinfo = matchinfo; + + if (offset) + return 0; + + pptr = skb_header_pointer(skb, protoff, + sizeof(_ports), _ports); + if (pptr == NULL) { + /* We've been asked to examine this packet, and we + * can't. Hence, no choice but to drop. + */ + duprintf("ipt_multiport:" + " Dropping evil offset=0 tinygram.\n"); + *hotdrop = 1; + return 0; + } + + return ports_match(multiinfo->ports, + multiinfo->flags, multiinfo->count, + ntohs(pptr[0]), ntohs(pptr[1])); +} + +static int +match_v1(const struct sk_buff *skb, + const struct net_device *in, + const struct net_device *out, + const struct xt_match *match, + const void *matchinfo, + int offset, + unsigned int protoff, + int *hotdrop) +{ + u16 _ports[2], *pptr; + const struct ipt_multiport_v1 *multiinfo = matchinfo; + + if (offset) + return 0; + + pptr = skb_header_pointer(skb, protoff, + sizeof(_ports), _ports); + if (pptr == NULL) { + /* We've been asked to examine this packet, and we + * can't. Hence, no choice but to drop. + */ + duprintf("ipt_multiport:" + " Dropping evil offset=0 tinygram.\n"); + *hotdrop = 1; + return 0; + } + + return ports_match_v1(multiinfo, ntohs(pptr[0]), ntohs(pptr[1])); +} + +static struct ipt_match multiport_match = { + .name = "multiport", + .revision = 0, + .match = match, + .matchsize = sizeof(struct ipt_multiport), + .me = THIS_MODULE, +}; + +static struct ipt_match multiport_match_v1 = { + .name = "multiport", + .revision = 1, + .match = match_v1, + .matchsize = sizeof(struct ipt_multiport_v1), + .me = THIS_MODULE, +}; + +static int __init ipt_multiport_init(void) +{ + int err; + + err = ipt_register_match(&multiport_match); + if (!err) { + err = ipt_register_match(&multiport_match_v1); + if (err) + ipt_unregister_match(&multiport_match); + } + + return err; +} + +static void __exit ipt_multiport_fini(void) +{ + ipt_unregister_match(&multiport_match); + ipt_unregister_match(&multiport_match_v1); +} + +module_init(ipt_multiport_init); +module_exit(ipt_multiport_fini); diff --git a/trunk/net/ipv4/xfrm4_input.c b/trunk/net/ipv4/xfrm4_input.c index e1b8f4b90d80..850d919591d1 100644 --- a/trunk/net/ipv4/xfrm4_input.c +++ b/trunk/net/ipv4/xfrm4_input.c @@ -68,7 +68,7 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type) { int err; u32 spi, seq; - struct xfrm_state *xfrm_vec[XFRM_MAX_DEPTH]; + struct sec_decap_state xfrm_vec[XFRM_MAX_DEPTH]; struct xfrm_state *x; int xfrm_nr = 0; int decaps = 0; @@ -90,16 +90,14 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type) if (unlikely(x->km.state != XFRM_STATE_VALID)) goto drop_unlock; - if (x->encap->encap_type != encap_type) - goto drop_unlock; - if (x->props.replay_window && xfrm_replay_check(x, seq)) goto drop_unlock; if (xfrm_state_check_expire(x)) goto drop_unlock; - if (x->type->input(x, skb)) + xfrm_vec[xfrm_nr].decap.decap_type = encap_type; + if (x->type->input(x, &(xfrm_vec[xfrm_nr].decap), skb)) goto drop_unlock; /* only the first xfrm gets the encap type */ @@ -113,7 +111,7 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type) spin_unlock(&x->lock); - xfrm_vec[xfrm_nr++] = x; + xfrm_vec[xfrm_nr++].xvec = x; iph = skb->nh.iph; @@ -155,8 +153,7 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type) if (xfrm_nr + skb->sp->len > XFRM_MAX_DEPTH) goto drop; - memcpy(skb->sp->xvec + skb->sp->len, xfrm_vec, - xfrm_nr * sizeof(xfrm_vec[0])); + memcpy(skb->sp->x+skb->sp->len, xfrm_vec, xfrm_nr*sizeof(struct sec_decap_state)); skb->sp->len += xfrm_nr; nf_reset(skb); @@ -187,7 +184,7 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type) xfrm_state_put(x); drop: while (--xfrm_nr >= 0) - xfrm_state_put(xfrm_vec[xfrm_nr]); + xfrm_state_put(xfrm_vec[xfrm_nr].xvec); kfree_skb(skb); return 0; diff --git a/trunk/net/ipv4/xfrm4_tunnel.c b/trunk/net/ipv4/xfrm4_tunnel.c index f8ceaa127c83..2d670935c2b5 100644 --- a/trunk/net/ipv4/xfrm4_tunnel.c +++ b/trunk/net/ipv4/xfrm4_tunnel.c @@ -21,7 +21,7 @@ static int ipip_output(struct xfrm_state *x, struct sk_buff *skb) return 0; } -static int ipip_xfrm_rcv(struct xfrm_state *x, struct sk_buff *skb) +static int ipip_xfrm_rcv(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb) { return 0; } diff --git a/trunk/net/ipv6/ah6.c b/trunk/net/ipv6/ah6.c index 6778173a3dda..cf58251df4b3 100644 --- a/trunk/net/ipv6/ah6.c +++ b/trunk/net/ipv6/ah6.c @@ -229,7 +229,7 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb) return err; } -static int ah6_input(struct xfrm_state *x, struct sk_buff *skb) +static int ah6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb) { /* * Before process AH diff --git a/trunk/net/ipv6/esp6.c b/trunk/net/ipv6/esp6.c index 22f046079037..3dcaac7a0972 100644 --- a/trunk/net/ipv6/esp6.c +++ b/trunk/net/ipv6/esp6.c @@ -130,7 +130,7 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb) return err; } -static int esp6_input(struct xfrm_state *x, struct sk_buff *skb) +static int esp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb) { struct ipv6hdr *iph; struct ipv6_esp_hdr *esph; diff --git a/trunk/net/ipv6/ipcomp6.c b/trunk/net/ipv6/ipcomp6.c index 00f3fadfcca7..d4cfec3f414e 100644 --- a/trunk/net/ipv6/ipcomp6.c +++ b/trunk/net/ipv6/ipcomp6.c @@ -63,7 +63,7 @@ static void **ipcomp6_scratches; static int ipcomp6_scratch_users; static LIST_HEAD(ipcomp6_tfms_list); -static int ipcomp6_input(struct xfrm_state *x, struct sk_buff *skb) +static int ipcomp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb) { int err = 0; u8 nexthdr = 0; diff --git a/trunk/net/ipv6/netfilter/Kconfig b/trunk/net/ipv6/netfilter/Kconfig index 4bc4e5b33794..98f78759f1ab 100644 --- a/trunk/net/ipv6/netfilter/Kconfig +++ b/trunk/net/ipv6/netfilter/Kconfig @@ -87,6 +87,16 @@ config IP6_NF_MATCH_HL To compile it as a module, choose M here. If unsure, say N. +config IP6_NF_MATCH_MULTIPORT + tristate "Multiple port match support" + depends on IP6_NF_IPTABLES + help + Multiport matching allows you to match TCP or UDP packets based on + a series of source or destination ports: normally a rule can only + match a single range of ports. + + To compile it as a module, choose M here. If unsure, say N. + config IP6_NF_MATCH_OWNER tristate "Owner match support" depends on IP6_NF_IPTABLES @@ -105,11 +115,11 @@ config IP6_NF_MATCH_IPV6HEADER To compile it as a module, choose M here. If unsure, say N. -config IP6_NF_MATCH_AH - tristate "AH match support" +config IP6_NF_MATCH_AHESP + tristate "AH/ESP match support" depends on IP6_NF_IPTABLES help - This module allows one to match AH packets. + This module allows one to match AH and ESP packets. To compile it as a module, choose M here. If unsure, say N. diff --git a/trunk/net/ipv6/netfilter/Makefile b/trunk/net/ipv6/netfilter/Makefile index eeeb57d4c9c5..8436a1a1731f 100644 --- a/trunk/net/ipv6/netfilter/Makefile +++ b/trunk/net/ipv6/netfilter/Makefile @@ -8,8 +8,9 @@ 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 obj-$(CONFIG_IP6_NF_MATCH_FRAG) += ip6t_frag.o -obj-$(CONFIG_IP6_NF_MATCH_AH) += ip6t_ah.o +obj-$(CONFIG_IP6_NF_MATCH_AHESP) += ip6t_esp.o ip6t_ah.o obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o +obj-$(CONFIG_IP6_NF_MATCH_MULTIPORT) += ip6t_multiport.o obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o diff --git a/trunk/net/ipv6/netfilter/ip6t_esp.c b/trunk/net/ipv6/netfilter/ip6t_esp.c new file mode 100644 index 000000000000..36bedad2c6f7 --- /dev/null +++ b/trunk/net/ipv6/netfilter/ip6t_esp.c @@ -0,0 +1,115 @@ +/* Kernel module to match ESP parameters. */ +/* (C) 2001-2002 Andras Kis-Szabo + * + * 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 +#include +#include +#include +#include +#include +#include + +#include +#include + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("IPv6 ESP match"); +MODULE_AUTHOR("Andras Kis-Szabo "); + +#if 0 +#define DEBUGP printk +#else +#define DEBUGP(format, args...) +#endif + +/* Returns 1 if the spi is matched by the range, 0 otherwise */ +static inline int +spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, int invert) +{ + int r=0; + DEBUGP("esp spi_match:%c 0x%x <= 0x%x <= 0x%x",invert? '!':' ', + min,spi,max); + r=(spi >= min && spi <= max) ^ invert; + DEBUGP(" result %s\n",r? "PASS\n" : "FAILED\n"); + return r; +} + +static int +match(const struct sk_buff *skb, + const struct net_device *in, + const struct net_device *out, + const struct xt_match *match, + const void *matchinfo, + int offset, + unsigned int protoff, + int *hotdrop) +{ + struct ip_esp_hdr _esp, *eh; + const struct ip6t_esp *espinfo = matchinfo; + unsigned int ptr; + + /* Make sure this isn't an evil packet */ + /*DEBUGP("ipv6_esp entered \n");*/ + + if (ipv6_find_hdr(skb, &ptr, NEXTHDR_ESP, NULL) < 0) + return 0; + + eh = skb_header_pointer(skb, ptr, sizeof(_esp), &_esp); + if (eh == NULL) { + *hotdrop = 1; + return 0; + } + + DEBUGP("IPv6 ESP SPI %u %08X\n", ntohl(eh->spi), ntohl(eh->spi)); + + return (eh != NULL) + && spi_match(espinfo->spis[0], espinfo->spis[1], + ntohl(eh->spi), + !!(espinfo->invflags & IP6T_ESP_INV_SPI)); +} + +/* Called when user tries to insert an entry of this type. */ +static int +checkentry(const char *tablename, + const void *ip, + const struct xt_match *match, + void *matchinfo, + unsigned int matchinfosize, + unsigned int hook_mask) +{ + const struct ip6t_esp *espinfo = matchinfo; + + if (espinfo->invflags & ~IP6T_ESP_INV_MASK) { + DEBUGP("ip6t_esp: unknown flags %X\n", + espinfo->invflags); + return 0; + } + return 1; +} + +static struct ip6t_match esp_match = { + .name = "esp", + .match = match, + .matchsize = sizeof(struct ip6t_esp), + .checkentry = checkentry, + .me = THIS_MODULE, +}; + +static int __init ip6t_esp_init(void) +{ + return ip6t_register_match(&esp_match); +} + +static void __exit ip6t_esp_fini(void) +{ + ip6t_unregister_match(&esp_match); +} + +module_init(ip6t_esp_init); +module_exit(ip6t_esp_fini); diff --git a/trunk/net/ipv6/netfilter/ip6t_multiport.c b/trunk/net/ipv6/netfilter/ip6t_multiport.c new file mode 100644 index 000000000000..10c48ba596d6 --- /dev/null +++ b/trunk/net/ipv6/netfilter/ip6t_multiport.c @@ -0,0 +1,125 @@ +/* Kernel module to match one of a list of TCP/UDP ports: ports are in + the same place so we can treat them as equal. */ + +/* (C) 1999-2001 Paul `Rusty' Russell + * (C) 2002-2004 Netfilter Core Team + * + * 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 +#include +#include +#include +#include + +#include +#include + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Netfilter Core Team "); +MODULE_DESCRIPTION("ip6tables match for multiple ports"); + +#if 0 +#define duprintf(format, args...) printk(format , ## args) +#else +#define duprintf(format, args...) +#endif + +/* Returns 1 if the port is matched by the test, 0 otherwise. */ +static inline int +ports_match(const u_int16_t *portlist, enum ip6t_multiport_flags flags, + u_int8_t count, u_int16_t src, u_int16_t dst) +{ + unsigned int i; + for (i=0; iports, + multiinfo->flags, multiinfo->count, + ntohs(pptr[0]), ntohs(pptr[1])); +} + +/* Called when user tries to insert an entry of this type. */ +static int +checkentry(const char *tablename, + const void *info, + const struct xt_match *match, + void *matchinfo, + unsigned int matchsize, + unsigned int hook_mask) +{ + const struct ip6t_ip6 *ip = info; + const struct ip6t_multiport *multiinfo = matchinfo; + + /* Must specify proto == TCP/UDP, no unknown flags or bad count */ + return (ip->proto == IPPROTO_TCP || ip->proto == IPPROTO_UDP) + && !(ip->invflags & IP6T_INV_PROTO) + && (multiinfo->flags == IP6T_MULTIPORT_SOURCE + || multiinfo->flags == IP6T_MULTIPORT_DESTINATION + || multiinfo->flags == IP6T_MULTIPORT_EITHER) + && multiinfo->count <= IP6T_MULTI_PORTS; +} + +static struct ip6t_match multiport_match = { + .name = "multiport", + .match = match, + .matchsize = sizeof(struct ip6t_multiport), + .checkentry = checkentry, + .me = THIS_MODULE, +}; + +static int __init ip6t_multiport_init(void) +{ + return ip6t_register_match(&multiport_match); +} + +static void __exit ip6t_multiport_fini(void) +{ + ip6t_unregister_match(&multiport_match); +} + +module_init(ip6t_multiport_init); +module_exit(ip6t_multiport_fini); diff --git a/trunk/net/ipv6/xfrm6_input.c b/trunk/net/ipv6/xfrm6_input.c index 00cfdee18dca..cccf8b76f046 100644 --- a/trunk/net/ipv6/xfrm6_input.c +++ b/trunk/net/ipv6/xfrm6_input.c @@ -32,7 +32,7 @@ int xfrm6_rcv_spi(struct sk_buff *skb, u32 spi) { int err; u32 seq; - struct xfrm_state *xfrm_vec[XFRM_MAX_DEPTH]; + struct sec_decap_state xfrm_vec[XFRM_MAX_DEPTH]; struct xfrm_state *x; int xfrm_nr = 0; int decaps = 0; @@ -65,7 +65,7 @@ int xfrm6_rcv_spi(struct sk_buff *skb, u32 spi) if (xfrm_state_check_expire(x)) goto drop_unlock; - nexthdr = x->type->input(x, skb); + nexthdr = x->type->input(x, &(xfrm_vec[xfrm_nr].decap), skb); if (nexthdr <= 0) goto drop_unlock; @@ -79,7 +79,7 @@ int xfrm6_rcv_spi(struct sk_buff *skb, u32 spi) spin_unlock(&x->lock); - xfrm_vec[xfrm_nr++] = x; + xfrm_vec[xfrm_nr++].xvec = x; if (x->props.mode) { /* XXX */ if (nexthdr != IPPROTO_IPV6) @@ -118,8 +118,7 @@ int xfrm6_rcv_spi(struct sk_buff *skb, u32 spi) if (xfrm_nr + skb->sp->len > XFRM_MAX_DEPTH) goto drop; - memcpy(skb->sp->xvec + skb->sp->len, xfrm_vec, - xfrm_nr * sizeof(xfrm_vec[0])); + memcpy(skb->sp->x+skb->sp->len, xfrm_vec, xfrm_nr*sizeof(struct sec_decap_state)); skb->sp->len += xfrm_nr; skb->ip_summed = CHECKSUM_NONE; @@ -150,7 +149,7 @@ int xfrm6_rcv_spi(struct sk_buff *skb, u32 spi) xfrm_state_put(x); drop: while (--xfrm_nr >= 0) - xfrm_state_put(xfrm_vec[xfrm_nr]); + xfrm_state_put(xfrm_vec[xfrm_nr].xvec); kfree_skb(skb); return -1; } diff --git a/trunk/net/ipv6/xfrm6_tunnel.c b/trunk/net/ipv6/xfrm6_tunnel.c index d37768e5064f..a8f6776c518d 100644 --- a/trunk/net/ipv6/xfrm6_tunnel.c +++ b/trunk/net/ipv6/xfrm6_tunnel.c @@ -351,7 +351,7 @@ static int xfrm6_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) return 0; } -static int xfrm6_tunnel_input(struct xfrm_state *x, struct sk_buff *skb) +static int xfrm6_tunnel_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb) { return 0; } diff --git a/trunk/net/netfilter/Kconfig b/trunk/net/netfilter/Kconfig index e2893effdfaa..332acb37b385 100644 --- a/trunk/net/netfilter/Kconfig +++ b/trunk/net/netfilter/Kconfig @@ -231,15 +231,6 @@ config NETFILTER_XT_MATCH_DCCP If you want to compile it as a module, say M here and read . If unsure, say `N'. -config NETFILTER_XT_MATCH_ESP - tristate '"ESP" match support' - depends on NETFILTER_XTABLES - help - This match extension allows you to match a range of SPIs - inside ESP header of IPSec packets. - - To compile it as a module, choose M here. If unsure, say N. - config NETFILTER_XT_MATCH_HELPER tristate '"helper" match support' depends on NETFILTER_XTABLES @@ -298,16 +289,6 @@ config NETFILTER_XT_MATCH_POLICY To compile it as a module, choose M here. If unsure, say N. -config NETFILTER_XT_MATCH_MULTIPORT - tristate "Multiple port match support" - depends on NETFILTER_XTABLES - help - Multiport matching allows you to match TCP or UDP packets based on - a series of source or destination ports: normally a rule can only - match a single range of ports. - - To compile it as a module, choose M here. If unsure, say N. - config NETFILTER_XT_MATCH_PHYSDEV tristate '"physdev" match support' depends on NETFILTER_XTABLES && BRIDGE_NETFILTER diff --git a/trunk/net/netfilter/Makefile b/trunk/net/netfilter/Makefile index 95b7e416512d..9558727f5e79 100644 --- a/trunk/net/netfilter/Makefile +++ b/trunk/net/netfilter/Makefile @@ -35,13 +35,11 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_CONNBYTES) += xt_connbytes.o obj-$(CONFIG_NETFILTER_XT_MATCH_CONNMARK) += xt_connmark.o obj-$(CONFIG_NETFILTER_XT_MATCH_CONNTRACK) += xt_conntrack.o obj-$(CONFIG_NETFILTER_XT_MATCH_DCCP) += xt_dccp.o -obj-$(CONFIG_NETFILTER_XT_MATCH_ESP) += xt_esp.o obj-$(CONFIG_NETFILTER_XT_MATCH_HELPER) += xt_helper.o obj-$(CONFIG_NETFILTER_XT_MATCH_LENGTH) += xt_length.o obj-$(CONFIG_NETFILTER_XT_MATCH_LIMIT) += xt_limit.o obj-$(CONFIG_NETFILTER_XT_MATCH_MAC) += xt_mac.o obj-$(CONFIG_NETFILTER_XT_MATCH_MARK) += xt_mark.o -obj-$(CONFIG_NETFILTER_XT_MATCH_MULTIPORT) += xt_multiport.o obj-$(CONFIG_NETFILTER_XT_MATCH_POLICY) += xt_policy.o obj-$(CONFIG_NETFILTER_XT_MATCH_PKTTYPE) += xt_pkttype.o obj-$(CONFIG_NETFILTER_XT_MATCH_REALM) += xt_realm.o diff --git a/trunk/net/netfilter/nf_conntrack_netlink.c b/trunk/net/netfilter/nf_conntrack_netlink.c index bd10eb944b65..0e0e9d7b34c8 100644 --- a/trunk/net/netfilter/nf_conntrack_netlink.c +++ b/trunk/net/netfilter/nf_conntrack_netlink.c @@ -1022,7 +1022,7 @@ ctnetlink_change_conntrack(struct nf_conn *ct, struct nfattr *cda[]) return err; } -#if defined(CONFIG_NF_CONNTRACK_MARK) +#if defined(CONFIG_IP_NF_CONNTRACK_MARK) if (cda[CTA_MARK-1]) ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1])); #endif @@ -1062,7 +1062,7 @@ ctnetlink_create_conntrack(struct nfattr *cda[], return err; } -#if defined(CONFIG_NF_CONNTRACK_MARK) +#if defined(CONFIG_IP_NF_CONNTRACK_MARK) if (cda[CTA_MARK-1]) ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1])); #endif @@ -1687,7 +1687,7 @@ static void __exit ctnetlink_exit(void) printk("ctnetlink: unregistering from nfnetlink.\n"); #ifdef CONFIG_NF_CONNTRACK_EVENTS - nf_conntrack_expect_unregister_notifier(&ctnl_notifier_exp); + nf_conntrack_unregister_notifier(&ctnl_notifier_exp); nf_conntrack_unregister_notifier(&ctnl_notifier); #endif diff --git a/trunk/net/netfilter/x_tables.c b/trunk/net/netfilter/x_tables.c index feb8a9e066b0..a657ab5394c3 100644 --- a/trunk/net/netfilter/x_tables.c +++ b/trunk/net/netfilter/x_tables.c @@ -38,7 +38,6 @@ struct xt_af { struct list_head match; struct list_head target; struct list_head tables; - struct mutex compat_mutex; }; static struct xt_af *xt; @@ -273,54 +272,6 @@ int xt_check_match(const struct xt_match *match, unsigned short family, } EXPORT_SYMBOL_GPL(xt_check_match); -#ifdef CONFIG_COMPAT -int xt_compat_match(void *match, void **dstptr, int *size, int convert) -{ - struct xt_match *m; - struct compat_xt_entry_match *pcompat_m; - struct xt_entry_match *pm; - u_int16_t msize; - int off, ret; - - ret = 0; - m = ((struct xt_entry_match *)match)->u.kernel.match; - off = XT_ALIGN(m->matchsize) - COMPAT_XT_ALIGN(m->matchsize); - switch (convert) { - case COMPAT_TO_USER: - pm = (struct xt_entry_match *)match; - msize = pm->u.user.match_size; - if (__copy_to_user(*dstptr, pm, msize)) { - ret = -EFAULT; - break; - } - msize -= off; - if (put_user(msize, (u_int16_t *)*dstptr)) - ret = -EFAULT; - *size -= off; - *dstptr += msize; - break; - case COMPAT_FROM_USER: - pcompat_m = (struct compat_xt_entry_match *)match; - pm = (struct xt_entry_match *)*dstptr; - msize = pcompat_m->u.user.match_size; - memcpy(pm, pcompat_m, msize); - msize += off; - pm->u.user.match_size = msize; - *size += off; - *dstptr += msize; - break; - case COMPAT_CALC_SIZE: - *size += off; - break; - default: - ret = -ENOPROTOOPT; - break; - } - return ret; -} -EXPORT_SYMBOL_GPL(xt_compat_match); -#endif - int xt_check_target(const struct xt_target *target, unsigned short family, unsigned int size, const char *table, unsigned int hook_mask, unsigned short proto, int inv_proto) @@ -350,54 +301,6 @@ int xt_check_target(const struct xt_target *target, unsigned short family, } EXPORT_SYMBOL_GPL(xt_check_target); -#ifdef CONFIG_COMPAT -int xt_compat_target(void *target, void **dstptr, int *size, int convert) -{ - struct xt_target *t; - struct compat_xt_entry_target *pcompat; - struct xt_entry_target *pt; - u_int16_t tsize; - int off, ret; - - ret = 0; - t = ((struct xt_entry_target *)target)->u.kernel.target; - off = XT_ALIGN(t->targetsize) - COMPAT_XT_ALIGN(t->targetsize); - switch (convert) { - case COMPAT_TO_USER: - pt = (struct xt_entry_target *)target; - tsize = pt->u.user.target_size; - if (__copy_to_user(*dstptr, pt, tsize)) { - ret = -EFAULT; - break; - } - tsize -= off; - if (put_user(tsize, (u_int16_t *)*dstptr)) - ret = -EFAULT; - *size -= off; - *dstptr += tsize; - break; - case COMPAT_FROM_USER: - pcompat = (struct compat_xt_entry_target *)target; - pt = (struct xt_entry_target *)*dstptr; - tsize = pcompat->u.user.target_size; - memcpy(pt, pcompat, tsize); - tsize += off; - pt->u.user.target_size = tsize; - *size += off; - *dstptr += tsize; - break; - case COMPAT_CALC_SIZE: - *size += off; - break; - default: - ret = -ENOPROTOOPT; - break; - } - return ret; -} -EXPORT_SYMBOL_GPL(xt_compat_target); -#endif - struct xt_table_info *xt_alloc_table_info(unsigned int size) { struct xt_table_info *newinfo; @@ -468,19 +371,6 @@ void xt_table_unlock(struct xt_table *table) } EXPORT_SYMBOL_GPL(xt_table_unlock); -#ifdef CONFIG_COMPAT -void xt_compat_lock(int af) -{ - mutex_lock(&xt[af].compat_mutex); -} -EXPORT_SYMBOL_GPL(xt_compat_lock); - -void xt_compat_unlock(int af) -{ - mutex_unlock(&xt[af].compat_mutex); -} -EXPORT_SYMBOL_GPL(xt_compat_unlock); -#endif struct xt_table_info * xt_replace_table(struct xt_table *table, @@ -781,9 +671,6 @@ static int __init xt_init(void) for (i = 0; i < NPROTO; i++) { mutex_init(&xt[i].mutex); -#ifdef CONFIG_COMPAT - mutex_init(&xt[i].compat_mutex); -#endif INIT_LIST_HEAD(&xt[i].target); INIT_LIST_HEAD(&xt[i].match); INIT_LIST_HEAD(&xt[i].tables); diff --git a/trunk/net/netfilter/xt_multiport.c b/trunk/net/netfilter/xt_multiport.c deleted file mode 100644 index b56cd2baaac2..000000000000 --- a/trunk/net/netfilter/xt_multiport.c +++ /dev/null @@ -1,314 +0,0 @@ -/* Kernel module to match one of a list of TCP/UDP ports: ports are in - the same place so we can treat them as equal. */ - -/* (C) 1999-2001 Paul `Rusty' Russell - * (C) 2002-2004 Netfilter Core Team - * - * 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 -#include -#include -#include -#include - -#include -#include -#include -#include - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Netfilter Core Team "); -MODULE_DESCRIPTION("x_tables multiple port match module"); -MODULE_ALIAS("ipt_multiport"); -MODULE_ALIAS("ip6t_multiport"); - -#if 0 -#define duprintf(format, args...) printk(format , ## args) -#else -#define duprintf(format, args...) -#endif - -/* Returns 1 if the port is matched by the test, 0 otherwise. */ -static inline int -ports_match(const u_int16_t *portlist, enum xt_multiport_flags flags, - u_int8_t count, u_int16_t src, u_int16_t dst) -{ - unsigned int i; - for (i = 0; i < count; i++) { - if (flags != XT_MULTIPORT_DESTINATION && portlist[i] == src) - return 1; - - if (flags != XT_MULTIPORT_SOURCE && portlist[i] == dst) - return 1; - } - - return 0; -} - -/* Returns 1 if the port is matched by the test, 0 otherwise. */ -static inline int -ports_match_v1(const struct xt_multiport_v1 *minfo, - u_int16_t src, u_int16_t dst) -{ - unsigned int i; - u_int16_t s, e; - - for (i = 0; i < minfo->count; i++) { - s = minfo->ports[i]; - - if (minfo->pflags[i]) { - /* range port matching */ - e = minfo->ports[++i]; - duprintf("src or dst matches with %d-%d?\n", s, e); - - if (minfo->flags == XT_MULTIPORT_SOURCE - && src >= s && src <= e) - return 1 ^ minfo->invert; - if (minfo->flags == XT_MULTIPORT_DESTINATION - && dst >= s && dst <= e) - return 1 ^ minfo->invert; - if (minfo->flags == XT_MULTIPORT_EITHER - && ((dst >= s && dst <= e) - || (src >= s && src <= e))) - return 1 ^ minfo->invert; - } else { - /* exact port matching */ - duprintf("src or dst matches with %d?\n", s); - - if (minfo->flags == XT_MULTIPORT_SOURCE - && src == s) - return 1 ^ minfo->invert; - if (minfo->flags == XT_MULTIPORT_DESTINATION - && dst == s) - return 1 ^ minfo->invert; - if (minfo->flags == XT_MULTIPORT_EITHER - && (src == s || dst == s)) - return 1 ^ minfo->invert; - } - } - - return minfo->invert; -} - -static int -match(const struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - const struct xt_match *match, - const void *matchinfo, - int offset, - unsigned int protoff, - int *hotdrop) -{ - u16 _ports[2], *pptr; - const struct xt_multiport *multiinfo = matchinfo; - - if (offset) - return 0; - - pptr = skb_header_pointer(skb, protoff, sizeof(_ports), _ports); - if (pptr == NULL) { - /* We've been asked to examine this packet, and we - * can't. Hence, no choice but to drop. - */ - duprintf("xt_multiport: Dropping evil offset=0 tinygram.\n"); - *hotdrop = 1; - return 0; - } - - return ports_match(multiinfo->ports, - multiinfo->flags, multiinfo->count, - ntohs(pptr[0]), ntohs(pptr[1])); -} - -static int -match_v1(const struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - const struct xt_match *match, - const void *matchinfo, - int offset, - unsigned int protoff, - int *hotdrop) -{ - u16 _ports[2], *pptr; - const struct xt_multiport_v1 *multiinfo = matchinfo; - - if (offset) - return 0; - - pptr = skb_header_pointer(skb, protoff, sizeof(_ports), _ports); - if (pptr == NULL) { - /* We've been asked to examine this packet, and we - * can't. Hence, no choice but to drop. - */ - duprintf("xt_multiport: Dropping evil offset=0 tinygram.\n"); - *hotdrop = 1; - return 0; - } - - return ports_match_v1(multiinfo, ntohs(pptr[0]), ntohs(pptr[1])); -} - -static inline int -check(u_int16_t proto, - u_int8_t ip_invflags, - u_int8_t match_flags, - u_int8_t count) -{ - /* Must specify proto == TCP/UDP, no unknown flags or bad count */ - return (proto == IPPROTO_TCP || proto == IPPROTO_UDP) - && !(ip_invflags & XT_INV_PROTO) - && (match_flags == XT_MULTIPORT_SOURCE - || match_flags == XT_MULTIPORT_DESTINATION - || match_flags == XT_MULTIPORT_EITHER) - && count <= XT_MULTI_PORTS; -} - -/* Called when user tries to insert an entry of this type. */ -static int -checkentry(const char *tablename, - const void *info, - const struct xt_match *match, - void *matchinfo, - unsigned int matchsize, - unsigned int hook_mask) -{ - const struct ipt_ip *ip = info; - const struct xt_multiport *multiinfo = matchinfo; - - return check(ip->proto, ip->invflags, multiinfo->flags, - multiinfo->count); -} - -static int -checkentry_v1(const char *tablename, - const void *info, - const struct xt_match *match, - void *matchinfo, - unsigned int matchsize, - unsigned int hook_mask) -{ - const struct ipt_ip *ip = info; - const struct xt_multiport_v1 *multiinfo = matchinfo; - - return check(ip->proto, ip->invflags, multiinfo->flags, - multiinfo->count); -} - -static int -checkentry6(const char *tablename, - const void *info, - const struct xt_match *match, - void *matchinfo, - unsigned int matchsize, - unsigned int hook_mask) -{ - const struct ip6t_ip6 *ip = info; - const struct xt_multiport *multiinfo = matchinfo; - - return check(ip->proto, ip->invflags, multiinfo->flags, - multiinfo->count); -} - -static int -checkentry6_v1(const char *tablename, - const void *info, - const struct xt_match *match, - void *matchinfo, - unsigned int matchsize, - unsigned int hook_mask) -{ - const struct ip6t_ip6 *ip = info; - const struct xt_multiport_v1 *multiinfo = matchinfo; - - return check(ip->proto, ip->invflags, multiinfo->flags, - multiinfo->count); -} - -static struct xt_match multiport_match = { - .name = "multiport", - .revision = 0, - .matchsize = sizeof(struct xt_multiport), - .match = &match, - .checkentry = &checkentry, - .family = AF_INET, - .me = THIS_MODULE, -}; - -static struct xt_match multiport_match_v1 = { - .name = "multiport", - .revision = 1, - .matchsize = sizeof(struct xt_multiport_v1), - .match = &match_v1, - .checkentry = &checkentry_v1, - .family = AF_INET, - .me = THIS_MODULE, -}; - -static struct xt_match multiport6_match = { - .name = "multiport", - .revision = 0, - .matchsize = sizeof(struct xt_multiport), - .match = &match, - .checkentry = &checkentry6, - .family = AF_INET6, - .me = THIS_MODULE, -}; - -static struct xt_match multiport6_match_v1 = { - .name = "multiport", - .revision = 1, - .matchsize = sizeof(struct xt_multiport_v1), - .match = &match_v1, - .checkentry = &checkentry6_v1, - .family = AF_INET6, - .me = THIS_MODULE, -}; - -static int __init xt_multiport_init(void) -{ - int ret; - - ret = xt_register_match(&multiport_match); - if (ret) - goto out; - - ret = xt_register_match(&multiport_match_v1); - if (ret) - goto out_unreg_multi_v0; - - ret = xt_register_match(&multiport6_match); - if (ret) - goto out_unreg_multi_v1; - - ret = xt_register_match(&multiport6_match_v1); - if (ret) - goto out_unreg_multi6_v0; - - return ret; - -out_unreg_multi6_v0: - xt_unregister_match(&multiport6_match); -out_unreg_multi_v1: - xt_unregister_match(&multiport_match_v1); -out_unreg_multi_v0: - xt_unregister_match(&multiport_match); -out: - return ret; -} - -static void __exit xt_multiport_fini(void) -{ - xt_unregister_match(&multiport_match); - xt_unregister_match(&multiport_match_v1); - xt_unregister_match(&multiport6_match); - xt_unregister_match(&multiport6_match_v1); -} - -module_init(xt_multiport_init); -module_exit(xt_multiport_fini); diff --git a/trunk/net/netfilter/xt_policy.c b/trunk/net/netfilter/xt_policy.c index a3aa62fbda6f..1099cb005fcc 100644 --- a/trunk/net/netfilter/xt_policy.c +++ b/trunk/net/netfilter/xt_policy.c @@ -71,7 +71,7 @@ match_policy_in(const struct sk_buff *skb, const struct xt_policy_info *info, return 0; e = &info->pol[pos]; - if (match_xfrm_state(sp->xvec[i], e, family)) { + if (match_xfrm_state(sp->x[i].xvec, e, family)) { if (!strict) return 1; } else if (strict) diff --git a/trunk/net/socket.c b/trunk/net/socket.c index b807f360e02c..b13042f68c02 100644 --- a/trunk/net/socket.c +++ b/trunk/net/socket.c @@ -1418,8 +1418,7 @@ asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, int _ newfd = sock_alloc_fd(&newfile); if (unlikely(newfd < 0)) { err = newfd; - sock_release(newsock); - goto out_put; + goto out_release; } err = sock_attach_fd(newsock, newfile); @@ -1456,8 +1455,10 @@ asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, int _ out: return err; out_fd: - fput(newfile); + put_filp(newfile); put_unused_fd(newfd); +out_release: + sock_release(newsock); goto out_put; } diff --git a/trunk/net/xfrm/xfrm_input.c b/trunk/net/xfrm/xfrm_input.c index b54971059f16..2407a7072327 100644 --- a/trunk/net/xfrm/xfrm_input.c +++ b/trunk/net/xfrm/xfrm_input.c @@ -18,7 +18,7 @@ void __secpath_destroy(struct sec_path *sp) { int i; for (i = 0; i < sp->len; i++) - xfrm_state_put(sp->xvec[i]); + xfrm_state_put(sp->x[i].xvec); kmem_cache_free(secpath_cachep, sp); } EXPORT_SYMBOL(__secpath_destroy); @@ -37,7 +37,7 @@ struct sec_path *secpath_dup(struct sec_path *src) memcpy(sp, src, sizeof(*sp)); for (i = 0; i < sp->len; i++) - xfrm_state_hold(sp->xvec[i]); + xfrm_state_hold(sp->x[i].xvec); } atomic_set(&sp->refcnt, 1); return sp; diff --git a/trunk/net/xfrm/xfrm_policy.c b/trunk/net/xfrm/xfrm_policy.c index c3725fe2a8fb..f5eae9febd26 100644 --- a/trunk/net/xfrm/xfrm_policy.c +++ b/trunk/net/xfrm/xfrm_policy.c @@ -943,9 +943,9 @@ xfrm_policy_ok(struct xfrm_tmpl *tmpl, struct sec_path *sp, int start, } else start = -1; for (; idx < sp->len; idx++) { - if (xfrm_state_ok(tmpl, sp->xvec[idx], family)) + if (xfrm_state_ok(tmpl, sp->x[idx].xvec, family)) return ++idx; - if (sp->xvec[idx]->props.mode) + if (sp->x[idx].xvec->props.mode) break; } return start; @@ -968,7 +968,7 @@ EXPORT_SYMBOL(xfrm_decode_session); static inline int secpath_has_tunnel(struct sec_path *sp, int k) { for (; k < sp->len; k++) { - if (sp->xvec[k]->props.mode) + if (sp->x[k].xvec->props.mode) return 1; } @@ -994,8 +994,8 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, int i; for (i=skb->sp->len-1; i>=0; i--) { - struct xfrm_state *x = skb->sp->xvec[i]; - if (!xfrm_selector_match(&x->sel, &fl, family)) + struct sec_decap_state *xvec = &(skb->sp->x[i]); + if (!xfrm_selector_match(&xvec->xvec->sel, &fl, family)) return 0; } }