Received: (qmail 4222 invoked by uid 1004); 6 Oct 2004 10:35:34 -0000 Sender: khilman@www2.muking.org To: Dan Kegel Cc: crossgcc Subject: Re: crosstool-0.28-rc37: Cygwin target. 2nd try at Linux kernel build test. References: <41638A00.1080309@kegel.com> From: Kevin Hilman Organization: None to speak of. Date: 06 Oct 2004 03:35:34 -0700 In-Reply-To: <41638A00.1080309@kegel.com> Message-ID: <83655ogmmh.fsf@www2.muking.org> Lines: 26 --=-=-= Dan Kegel writes: > I'm working through the problems building the Linux kernel. As mentioned in a previous thread (case-sensitive filenames during kernel build) there are problems with the questionable usage of filenames such as ipt_DSCP.h and ipt_dscp.h in the same directory. Attached is a patch to fix the netfilter problems. This patch basically renames the upper-case files from ipt_XXXX.[ch] to ipt_XXXX_u.[ch]. Using this patch I've successfuly built an ARM linux kernel (for a TI OMAP platform) on cygwin using a crosstool-on-cygwin-built arm-softfloat toolchain. However, for crosstool there's still a problem on how to apply the patch to the kernel because after untarring the the kernel on a case-sensitive filesystem, you've already lost some files. Kevin http://hilman.org/ diff -Nru linux-2.6.8/include/linux/netfilter_ipv4/ipt_DSCP.h linux-2.6.8-case/include/linux/netfilter_ipv4/ipt_DSCP.h --- linux-2.6.8/include/linux/netfilter_ipv4/ipt_DSCP.h 2004-08-14 07:37:39.000000000 +0200 +++ linux-2.6.8-case/include/linux/netfilter_ipv4/ipt_DSCP.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,20 +0,0 @@ -/* iptables module for setting the IPv4 DSCP field - * - * (C) 2002 Harald Welte - * based on ipt_FTOS.c (C) 2000 by Matthew G. Marsh - * This software is distributed under GNU GPL v2, 1991 - * - * See RFC2474 for a description of the DSCP field within the IP Header. - * - * ipt_DSCP.h,v 1.7 2002/03/14 12:03:13 laforge Exp -*/ -#ifndef _IPT_DSCP_TARGET_H -#define _IPT_DSCP_TARGET_H -#include - -/* target info */ -struct ipt_DSCP_info { - u_int8_t dscp; -}; - -#endif /* _IPT_DSCP_TARGET_H */ diff -Nru linux-2.6.8/include/linux/netfilter_ipv4/ipt_DSCP_u.h linux-2.6.8-case/include/linux/netfilter_ipv4/ipt_DSCP_u.h --- linux-2.6.8/include/linux/netfilter_ipv4/ipt_DSCP_u.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.8-case/include/linux/netfilter_ipv4/ipt_DSCP_u.h 2004-08-14 07:37:39.000000000 +0200 @@ -0,0 +1,20 @@ +/* iptables module for setting the IPv4 DSCP field + * + * (C) 2002 Harald Welte + * based on ipt_FTOS.c (C) 2000 by Matthew G. Marsh + * This software is distributed under GNU GPL v2, 1991 + * + * See RFC2474 for a description of the DSCP field within the IP Header. + * + * ipt_DSCP.h,v 1.7 2002/03/14 12:03:13 laforge Exp +*/ +#ifndef _IPT_DSCP_TARGET_H +#define _IPT_DSCP_TARGET_H +#include + +/* target info */ +struct ipt_DSCP_info { + u_int8_t dscp; +}; + +#endif /* _IPT_DSCP_TARGET_H */ diff -Nru linux-2.6.8/include/linux/netfilter_ipv4/ipt_ECN.h linux-2.6.8-case/include/linux/netfilter_ipv4/ipt_ECN.h --- linux-2.6.8/include/linux/netfilter_ipv4/ipt_ECN.h 2004-08-14 07:36:11.000000000 +0200 +++ linux-2.6.8-case/include/linux/netfilter_ipv4/ipt_ECN.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,31 +0,0 @@ -/* Header file for iptables ipt_ECN target - * - * (C) 2002 by Harald Welte - * - * This software is distributed under GNU GPL v2, 1991 - * - * ipt_ECN.h,v 1.3 2002/05/29 12:17:40 laforge Exp -*/ -#ifndef _IPT_ECN_TARGET_H -#define _IPT_ECN_TARGET_H -#include - -#define IPT_ECN_IP_MASK (~IPT_DSCP_MASK) - -#define IPT_ECN_OP_SET_IP 0x01 /* set ECN bits of IPv4 header */ -#define IPT_ECN_OP_SET_ECE 0x10 /* set ECE bit of TCP header */ -#define IPT_ECN_OP_SET_CWR 0x20 /* set CWR bit of TCP header */ - -#define IPT_ECN_OP_MASK 0xce - -struct ipt_ECN_info { - u_int8_t operation; /* bitset of operations */ - u_int8_t ip_ect; /* ECT codepoint of IPv4 header, pre-shifted */ - union { - struct { - u_int8_t ece:1, cwr:1; /* TCP ECT bits */ - } tcp; - } proto; -}; - -#endif /* _IPT_ECN_TARGET_H */ diff -Nru linux-2.6.8/include/linux/netfilter_ipv4/ipt_ECN_u.h linux-2.6.8-case/include/linux/netfilter_ipv4/ipt_ECN_u.h --- linux-2.6.8/include/linux/netfilter_ipv4/ipt_ECN_u.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.8-case/include/linux/netfilter_ipv4/ipt_ECN_u.h 2004-09-24 14:25:52.000000000 +0200 @@ -0,0 +1,31 @@ +/* Header file for iptables ipt_ECN target + * + * (C) 2002 by Harald Welte + * + * This software is distributed under GNU GPL v2, 1991 + * + * ipt_ECN.h,v 1.3 2002/05/29 12:17:40 laforge Exp +*/ +#ifndef _IPT_ECN_TARGET_H +#define _IPT_ECN_TARGET_H +#include + +#define IPT_ECN_IP_MASK (~IPT_DSCP_MASK) + +#define IPT_ECN_OP_SET_IP 0x01 /* set ECN bits of IPv4 header */ +#define IPT_ECN_OP_SET_ECE 0x10 /* set ECE bit of TCP header */ +#define IPT_ECN_OP_SET_CWR 0x20 /* set CWR bit of TCP header */ + +#define IPT_ECN_OP_MASK 0xce + +struct ipt_ECN_info { + u_int8_t operation; /* bitset of operations */ + u_int8_t ip_ect; /* ECT codepoint of IPv4 header, pre-shifted */ + union { + struct { + u_int8_t ece:1, cwr:1; /* TCP ECT bits */ + } tcp; + } proto; +}; + +#endif /* _IPT_ECN_TARGET_H */ diff -Nru linux-2.6.8/include/linux/netfilter_ipv4/ipt_MARK.h linux-2.6.8-case/include/linux/netfilter_ipv4/ipt_MARK.h --- linux-2.6.8/include/linux/netfilter_ipv4/ipt_MARK.h 2004-08-14 07:36:33.000000000 +0200 +++ linux-2.6.8-case/include/linux/netfilter_ipv4/ipt_MARK.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,8 +0,0 @@ -#ifndef _IPT_MARK_H_target -#define _IPT_MARK_H_target - -struct ipt_mark_target_info { - unsigned long mark; -}; - -#endif /*_IPT_MARK_H_target*/ diff -Nru linux-2.6.8/include/linux/netfilter_ipv4/ipt_MARK_u.h linux-2.6.8-case/include/linux/netfilter_ipv4/ipt_MARK_u.h --- linux-2.6.8/include/linux/netfilter_ipv4/ipt_MARK_u.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.8-case/include/linux/netfilter_ipv4/ipt_MARK_u.h 2004-08-14 07:36:33.000000000 +0200 @@ -0,0 +1,8 @@ +#ifndef _IPT_MARK_H_target +#define _IPT_MARK_H_target + +struct ipt_mark_target_info { + unsigned long mark; +}; + +#endif /*_IPT_MARK_H_target*/ diff -Nru linux-2.6.8/include/linux/netfilter_ipv4/ipt_TCPMSS.h linux-2.6.8-case/include/linux/netfilter_ipv4/ipt_TCPMSS.h --- linux-2.6.8/include/linux/netfilter_ipv4/ipt_TCPMSS.h 2004-08-14 07:37:15.000000000 +0200 +++ linux-2.6.8-case/include/linux/netfilter_ipv4/ipt_TCPMSS.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,10 +0,0 @@ -#ifndef _IPT_TCPMSS_H -#define _IPT_TCPMSS_H - -struct ipt_tcpmss_info { - u_int16_t mss; -}; - -#define IPT_TCPMSS_CLAMP_PMTU 0xffff - -#endif /*_IPT_TCPMSS_H*/ diff -Nru linux-2.6.8/include/linux/netfilter_ipv4/ipt_TCPMSS_u.h linux-2.6.8-case/include/linux/netfilter_ipv4/ipt_TCPMSS_u.h --- linux-2.6.8/include/linux/netfilter_ipv4/ipt_TCPMSS_u.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.8-case/include/linux/netfilter_ipv4/ipt_TCPMSS_u.h 2004-08-14 07:37:15.000000000 +0200 @@ -0,0 +1,10 @@ +#ifndef _IPT_TCPMSS_H +#define _IPT_TCPMSS_H + +struct ipt_tcpmss_info { + u_int16_t mss; +}; + +#define IPT_TCPMSS_CLAMP_PMTU 0xffff + +#endif /*_IPT_TCPMSS_H*/ diff -Nru linux-2.6.8/include/linux/netfilter_ipv4/ipt_TOS.h linux-2.6.8-case/include/linux/netfilter_ipv4/ipt_TOS.h --- linux-2.6.8/include/linux/netfilter_ipv4/ipt_TOS.h 2004-08-14 07:36:17.000000000 +0200 +++ linux-2.6.8-case/include/linux/netfilter_ipv4/ipt_TOS.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,12 +0,0 @@ -#ifndef _IPT_TOS_H_target -#define _IPT_TOS_H_target - -#ifndef IPTOS_NORMALSVC -#define IPTOS_NORMALSVC 0 -#endif - -struct ipt_tos_target_info { - u_int8_t tos; -}; - -#endif /*_IPT_TOS_H_target*/ diff -Nru linux-2.6.8/include/linux/netfilter_ipv4/ipt_TOS_u.h linux-2.6.8-case/include/linux/netfilter_ipv4/ipt_TOS_u.h --- linux-2.6.8/include/linux/netfilter_ipv4/ipt_TOS_u.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.8-case/include/linux/netfilter_ipv4/ipt_TOS_u.h 2004-08-14 07:36:17.000000000 +0200 @@ -0,0 +1,12 @@ +#ifndef _IPT_TOS_H_target +#define _IPT_TOS_H_target + +#ifndef IPTOS_NORMALSVC +#define IPTOS_NORMALSVC 0 +#endif + +struct ipt_tos_target_info { + u_int8_t tos; +}; + +#endif /*_IPT_TOS_H_target*/ diff -Nru linux-2.6.8/net/ipv4/netfilter/Makefile linux-2.6.8-case/net/ipv4/netfilter/Makefile --- linux-2.6.8/net/ipv4/netfilter/Makefile 2004-08-14 07:36:32.000000000 +0200 +++ linux-2.6.8-case/net/ipv4/netfilter/Makefile 2004-09-24 14:11:12.000000000 +0200 @@ -71,10 +71,10 @@ # targets obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o -obj-$(CONFIG_IP_NF_TARGET_TOS) += ipt_TOS.o -obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o -obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o -obj-$(CONFIG_IP_NF_TARGET_MARK) += ipt_MARK.o +obj-$(CONFIG_IP_NF_TARGET_TOS) += ipt_TOS_u.o +obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN_u.o +obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP_u.o +obj-$(CONFIG_IP_NF_TARGET_MARK) += ipt_MARK_u.o obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o @@ -83,7 +83,7 @@ obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o -obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o +obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS_u.o obj-$(CONFIG_IP_NF_TARGET_NOTRACK) += ipt_NOTRACK.o # generic ARP tables diff -Nru linux-2.6.8/net/ipv4/netfilter/ipt_DSCP.c linux-2.6.8-case/net/ipv4/netfilter/ipt_DSCP.c --- linux-2.6.8/net/ipv4/netfilter/ipt_DSCP.c 2004-08-14 07:38:04.000000000 +0200 +++ linux-2.6.8-case/net/ipv4/netfilter/ipt_DSCP.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,106 +0,0 @@ -/* iptables module for setting the IPv4 DSCP field, Version 1.8 - * - * (C) 2002 by Harald Welte - * based on ipt_FTOS.c (C) 2000 by Matthew G. Marsh - * - * 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. - * - * See RFC2474 for a description of the DSCP field within the IP Header. - * - * ipt_DSCP.c,v 1.8 2002/08/06 18:41:57 laforge Exp -*/ - -#include -#include -#include -#include - -#include -#include - -MODULE_AUTHOR("Harald Welte "); -MODULE_DESCRIPTION("iptables DSCP modification module"); -MODULE_LICENSE("GPL"); - -static unsigned int -target(struct sk_buff **pskb, - const struct net_device *in, - const struct net_device *out, - unsigned int hooknum, - const void *targinfo, - void *userinfo) -{ - const struct ipt_DSCP_info *dinfo = targinfo; - u_int8_t sh_dscp = ((dinfo->dscp << IPT_DSCP_SHIFT) & IPT_DSCP_MASK); - - - if (((*pskb)->nh.iph->tos & IPT_DSCP_MASK) != sh_dscp) { - u_int16_t diffs[2]; - - if (!skb_ip_make_writable(pskb, sizeof(struct iphdr))) - return NF_DROP; - - diffs[0] = htons((*pskb)->nh.iph->tos) ^ 0xFFFF; - (*pskb)->nh.iph->tos = ((*pskb)->nh.iph->tos & ~IPT_DSCP_MASK) - | sh_dscp; - diffs[1] = htons((*pskb)->nh.iph->tos); - (*pskb)->nh.iph->check - = csum_fold(csum_partial((char *)diffs, - sizeof(diffs), - (*pskb)->nh.iph->check - ^ 0xFFFF)); - (*pskb)->nfcache |= NFC_ALTERED; - } - return IPT_CONTINUE; -} - -static int -checkentry(const char *tablename, - const struct ipt_entry *e, - void *targinfo, - unsigned int targinfosize, - unsigned int hook_mask) -{ - const u_int8_t dscp = ((struct ipt_DSCP_info *)targinfo)->dscp; - - if (targinfosize != IPT_ALIGN(sizeof(struct ipt_DSCP_info))) { - printk(KERN_WARNING "DSCP: targinfosize %u != %Zu\n", - targinfosize, - IPT_ALIGN(sizeof(struct ipt_DSCP_info))); - return 0; - } - - if (strcmp(tablename, "mangle") != 0) { - printk(KERN_WARNING "DSCP: can only be called from \"mangle\" table, not \"%s\"\n", tablename); - return 0; - } - - if ((dscp > IPT_DSCP_MAX)) { - printk(KERN_WARNING "DSCP: dscp %x out of range\n", dscp); - return 0; - } - - return 1; -} - -static struct ipt_target ipt_dscp_reg = { - .name = "DSCP", - .target = target, - .checkentry = checkentry, - .me = THIS_MODULE, -}; - -static int __init init(void) -{ - return ipt_register_target(&ipt_dscp_reg); -} - -static void __exit fini(void) -{ - ipt_unregister_target(&ipt_dscp_reg); -} - -module_init(init); -module_exit(fini); diff -Nru linux-2.6.8/net/ipv4/netfilter/ipt_DSCP_u.c linux-2.6.8-case/net/ipv4/netfilter/ipt_DSCP_u.c --- linux-2.6.8/net/ipv4/netfilter/ipt_DSCP_u.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.8-case/net/ipv4/netfilter/ipt_DSCP_u.c 2004-09-24 14:24:27.000000000 +0200 @@ -0,0 +1,106 @@ +/* iptables module for setting the IPv4 DSCP field, Version 1.8 + * + * (C) 2002 by Harald Welte + * based on ipt_FTOS.c (C) 2000 by Matthew G. Marsh + * + * 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. + * + * See RFC2474 for a description of the DSCP field within the IP Header. + * + * ipt_DSCP.c,v 1.8 2002/08/06 18:41:57 laforge Exp +*/ + +#include +#include +#include +#include + +#include +#include + +MODULE_AUTHOR("Harald Welte "); +MODULE_DESCRIPTION("iptables DSCP modification module"); +MODULE_LICENSE("GPL"); + +static unsigned int +target(struct sk_buff **pskb, + const struct net_device *in, + const struct net_device *out, + unsigned int hooknum, + const void *targinfo, + void *userinfo) +{ + const struct ipt_DSCP_info *dinfo = targinfo; + u_int8_t sh_dscp = ((dinfo->dscp << IPT_DSCP_SHIFT) & IPT_DSCP_MASK); + + + if (((*pskb)->nh.iph->tos & IPT_DSCP_MASK) != sh_dscp) { + u_int16_t diffs[2]; + + if (!skb_ip_make_writable(pskb, sizeof(struct iphdr))) + return NF_DROP; + + diffs[0] = htons((*pskb)->nh.iph->tos) ^ 0xFFFF; + (*pskb)->nh.iph->tos = ((*pskb)->nh.iph->tos & ~IPT_DSCP_MASK) + | sh_dscp; + diffs[1] = htons((*pskb)->nh.iph->tos); + (*pskb)->nh.iph->check + = csum_fold(csum_partial((char *)diffs, + sizeof(diffs), + (*pskb)->nh.iph->check + ^ 0xFFFF)); + (*pskb)->nfcache |= NFC_ALTERED; + } + return IPT_CONTINUE; +} + +static int +checkentry(const char *tablename, + const struct ipt_entry *e, + void *targinfo, + unsigned int targinfosize, + unsigned int hook_mask) +{ + const u_int8_t dscp = ((struct ipt_DSCP_info *)targinfo)->dscp; + + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_DSCP_info))) { + printk(KERN_WARNING "DSCP: targinfosize %u != %Zu\n", + targinfosize, + IPT_ALIGN(sizeof(struct ipt_DSCP_info))); + return 0; + } + + if (strcmp(tablename, "mangle") != 0) { + printk(KERN_WARNING "DSCP: can only be called from \"mangle\" table, not \"%s\"\n", tablename); + return 0; + } + + if ((dscp > IPT_DSCP_MAX)) { + printk(KERN_WARNING "DSCP: dscp %x out of range\n", dscp); + return 0; + } + + return 1; +} + +static struct ipt_target ipt_dscp_reg = { + .name = "DSCP", + .target = target, + .checkentry = checkentry, + .me = THIS_MODULE, +}; + +static int __init init(void) +{ + return ipt_register_target(&ipt_dscp_reg); +} + +static void __exit fini(void) +{ + ipt_unregister_target(&ipt_dscp_reg); +} + +module_init(init); +module_exit(fini); diff -Nru linux-2.6.8/net/ipv4/netfilter/ipt_ECN.c linux-2.6.8-case/net/ipv4/netfilter/ipt_ECN.c --- linux-2.6.8/net/ipv4/netfilter/ipt_ECN.c 2004-08-14 07:38:08.000000000 +0200 +++ linux-2.6.8-case/net/ipv4/netfilter/ipt_ECN.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,173 +0,0 @@ -/* iptables module for the IPv4 and TCP ECN bits, Version 1.5 - * - * (C) 2002 by Harald Welte - * - * 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. - * - * ipt_ECN.c,v 1.5 2002/08/18 19:36:51 laforge Exp -*/ - -#include -#include -#include -#include -#include - -#include -#include - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Harald Welte "); -MODULE_DESCRIPTION("iptables ECN modification module"); - -/* set ECT codepoint from IP header. - * return 0 if there was an error. */ -static inline int -set_ect_ip(struct sk_buff **pskb, const struct ipt_ECN_info *einfo) -{ - if (((*pskb)->nh.iph->tos & IPT_ECN_IP_MASK) - != (einfo->ip_ect & IPT_ECN_IP_MASK)) { - u_int16_t diffs[2]; - - if (!skb_ip_make_writable(pskb, sizeof(struct iphdr))) - return 0; - - diffs[0] = htons((*pskb)->nh.iph->tos) ^ 0xFFFF; - (*pskb)->nh.iph->tos &= ~IPT_ECN_IP_MASK; - (*pskb)->nh.iph->tos |= (einfo->ip_ect & IPT_ECN_IP_MASK); - diffs[1] = htons((*pskb)->nh.iph->tos); - (*pskb)->nh.iph->check - = csum_fold(csum_partial((char *)diffs, - sizeof(diffs), - (*pskb)->nh.iph->check - ^0xFFFF)); - (*pskb)->nfcache |= NFC_ALTERED; - } - return 1; -} - -/* Return 0 if there was an error. */ -static inline int -set_ect_tcp(struct sk_buff **pskb, const struct ipt_ECN_info *einfo, int inward) -{ - struct tcphdr tcph; - u_int16_t diffs[2]; - - /* Not enought header? */ - if (skb_copy_bits(*pskb, (*pskb)->nh.iph->ihl*4, &tcph, sizeof(tcph)) - < 0) - return 0; - - diffs[0] = ((u_int16_t *)&tcph)[6]; - if (einfo->operation & IPT_ECN_OP_SET_ECE) - tcph.ece = einfo->proto.tcp.ece; - - if (einfo->operation & IPT_ECN_OP_SET_CWR) - tcph.cwr = einfo->proto.tcp.cwr; - diffs[1] = ((u_int16_t *)&tcph)[6]; - - /* Only mangle if it's changed. */ - if (diffs[0] != diffs[1]) { - diffs[0] = diffs[0] ^ 0xFFFF; - if (!skb_ip_make_writable(pskb, - (*pskb)->nh.iph->ihl*4+sizeof(tcph))) - return 0; - if ((*pskb)->ip_summed != CHECKSUM_HW) - tcph.check = csum_fold(csum_partial((char *)diffs, - sizeof(diffs), - tcph.check^0xFFFF)); - memcpy((*pskb)->data + (*pskb)->nh.iph->ihl*4, - &tcph, sizeof(tcph)); - if ((*pskb)->ip_summed == CHECKSUM_HW) - if (skb_checksum_help(pskb, inward)) - return 0; - (*pskb)->nfcache |= NFC_ALTERED; - } - return 1; -} - -static unsigned int -target(struct sk_buff **pskb, - const struct net_device *in, - const struct net_device *out, - unsigned int hooknum, - const void *targinfo, - void *userinfo) -{ - const struct ipt_ECN_info *einfo = targinfo; - - if (einfo->operation & IPT_ECN_OP_SET_IP) - if (!set_ect_ip(pskb, einfo)) - return NF_DROP; - - if (einfo->operation & (IPT_ECN_OP_SET_ECE | IPT_ECN_OP_SET_CWR) - && (*pskb)->nh.iph->protocol == IPPROTO_TCP) - if (!set_ect_tcp(pskb, einfo, (out == NULL))) - return NF_DROP; - - return IPT_CONTINUE; -} - -static int -checkentry(const char *tablename, - const struct ipt_entry *e, - void *targinfo, - unsigned int targinfosize, - unsigned int hook_mask) -{ - const struct ipt_ECN_info *einfo = (struct ipt_ECN_info *)targinfo; - - if (targinfosize != IPT_ALIGN(sizeof(struct ipt_ECN_info))) { - printk(KERN_WARNING "ECN: targinfosize %u != %Zu\n", - targinfosize, - IPT_ALIGN(sizeof(struct ipt_ECN_info))); - return 0; - } - - if (strcmp(tablename, "mangle") != 0) { - printk(KERN_WARNING "ECN: can only be called from \"mangle\" table, not \"%s\"\n", tablename); - return 0; - } - - if (einfo->operation & IPT_ECN_OP_MASK) { - printk(KERN_WARNING "ECN: unsupported ECN operation %x\n", - einfo->operation); - return 0; - } - if (einfo->ip_ect & ~IPT_ECN_IP_MASK) { - printk(KERN_WARNING "ECN: new ECT codepoint %x out of mask\n", - einfo->ip_ect); - return 0; - } - - if ((einfo->operation & (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR)) - && e->ip.proto != IPPROTO_TCP) { - printk(KERN_WARNING "ECN: cannot use TCP operations on a " - "non-tcp rule\n"); - return 0; - } - - return 1; -} - -static struct ipt_target ipt_ecn_reg = { - .name = "ECN", - .target = target, - .checkentry = checkentry, - .me = THIS_MODULE, -}; - -static int __init init(void) -{ - return ipt_register_target(&ipt_ecn_reg); -} - -static void __exit fini(void) -{ - ipt_unregister_target(&ipt_ecn_reg); -} - -module_init(init); -module_exit(fini); diff -Nru linux-2.6.8/net/ipv4/netfilter/ipt_ECN_u.c linux-2.6.8-case/net/ipv4/netfilter/ipt_ECN_u.c --- linux-2.6.8/net/ipv4/netfilter/ipt_ECN_u.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.8-case/net/ipv4/netfilter/ipt_ECN_u.c 2004-09-24 14:24:33.000000000 +0200 @@ -0,0 +1,173 @@ +/* iptables module for the IPv4 and TCP ECN bits, Version 1.5 + * + * (C) 2002 by Harald Welte + * + * 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. + * + * ipt_ECN.c,v 1.5 2002/08/18 19:36:51 laforge Exp +*/ + +#include +#include +#include +#include +#include + +#include +#include + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Harald Welte "); +MODULE_DESCRIPTION("iptables ECN modification module"); + +/* set ECT codepoint from IP header. + * return 0 if there was an error. */ +static inline int +set_ect_ip(struct sk_buff **pskb, const struct ipt_ECN_info *einfo) +{ + if (((*pskb)->nh.iph->tos & IPT_ECN_IP_MASK) + != (einfo->ip_ect & IPT_ECN_IP_MASK)) { + u_int16_t diffs[2]; + + if (!skb_ip_make_writable(pskb, sizeof(struct iphdr))) + return 0; + + diffs[0] = htons((*pskb)->nh.iph->tos) ^ 0xFFFF; + (*pskb)->nh.iph->tos &= ~IPT_ECN_IP_MASK; + (*pskb)->nh.iph->tos |= (einfo->ip_ect & IPT_ECN_IP_MASK); + diffs[1] = htons((*pskb)->nh.iph->tos); + (*pskb)->nh.iph->check + = csum_fold(csum_partial((char *)diffs, + sizeof(diffs), + (*pskb)->nh.iph->check + ^0xFFFF)); + (*pskb)->nfcache |= NFC_ALTERED; + } + return 1; +} + +/* Return 0 if there was an error. */ +static inline int +set_ect_tcp(struct sk_buff **pskb, const struct ipt_ECN_info *einfo, int inward) +{ + struct tcphdr tcph; + u_int16_t diffs[2]; + + /* Not enought header? */ + if (skb_copy_bits(*pskb, (*pskb)->nh.iph->ihl*4, &tcph, sizeof(tcph)) + < 0) + return 0; + + diffs[0] = ((u_int16_t *)&tcph)[6]; + if (einfo->operation & IPT_ECN_OP_SET_ECE) + tcph.ece = einfo->proto.tcp.ece; + + if (einfo->operation & IPT_ECN_OP_SET_CWR) + tcph.cwr = einfo->proto.tcp.cwr; + diffs[1] = ((u_int16_t *)&tcph)[6]; + + /* Only mangle if it's changed. */ + if (diffs[0] != diffs[1]) { + diffs[0] = diffs[0] ^ 0xFFFF; + if (!skb_ip_make_writable(pskb, + (*pskb)->nh.iph->ihl*4+sizeof(tcph))) + return 0; + if ((*pskb)->ip_summed != CHECKSUM_HW) + tcph.check = csum_fold(csum_partial((char *)diffs, + sizeof(diffs), + tcph.check^0xFFFF)); + memcpy((*pskb)->data + (*pskb)->nh.iph->ihl*4, + &tcph, sizeof(tcph)); + if ((*pskb)->ip_summed == CHECKSUM_HW) + if (skb_checksum_help(pskb, inward)) + return 0; + (*pskb)->nfcache |= NFC_ALTERED; + } + return 1; +} + +static unsigned int +target(struct sk_buff **pskb, + const struct net_device *in, + const struct net_device *out, + unsigned int hooknum, + const void *targinfo, + void *userinfo) +{ + const struct ipt_ECN_info *einfo = targinfo; + + if (einfo->operation & IPT_ECN_OP_SET_IP) + if (!set_ect_ip(pskb, einfo)) + return NF_DROP; + + if (einfo->operation & (IPT_ECN_OP_SET_ECE | IPT_ECN_OP_SET_CWR) + && (*pskb)->nh.iph->protocol == IPPROTO_TCP) + if (!set_ect_tcp(pskb, einfo, (out == NULL))) + return NF_DROP; + + return IPT_CONTINUE; +} + +static int +checkentry(const char *tablename, + const struct ipt_entry *e, + void *targinfo, + unsigned int targinfosize, + unsigned int hook_mask) +{ + const struct ipt_ECN_info *einfo = (struct ipt_ECN_info *)targinfo; + + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_ECN_info))) { + printk(KERN_WARNING "ECN: targinfosize %u != %Zu\n", + targinfosize, + IPT_ALIGN(sizeof(struct ipt_ECN_info))); + return 0; + } + + if (strcmp(tablename, "mangle") != 0) { + printk(KERN_WARNING "ECN: can only be called from \"mangle\" table, not \"%s\"\n", tablename); + return 0; + } + + if (einfo->operation & IPT_ECN_OP_MASK) { + printk(KERN_WARNING "ECN: unsupported ECN operation %x\n", + einfo->operation); + return 0; + } + if (einfo->ip_ect & ~IPT_ECN_IP_MASK) { + printk(KERN_WARNING "ECN: new ECT codepoint %x out of mask\n", + einfo->ip_ect); + return 0; + } + + if ((einfo->operation & (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR)) + && e->ip.proto != IPPROTO_TCP) { + printk(KERN_WARNING "ECN: cannot use TCP operations on a " + "non-tcp rule\n"); + return 0; + } + + return 1; +} + +static struct ipt_target ipt_ecn_reg = { + .name = "ECN", + .target = target, + .checkentry = checkentry, + .me = THIS_MODULE, +}; + +static int __init init(void) +{ + return ipt_register_target(&ipt_ecn_reg); +} + +static void __exit fini(void) +{ + ipt_unregister_target(&ipt_ecn_reg); +} + +module_init(init); +module_exit(fini); diff -Nru linux-2.6.8/net/ipv4/netfilter/ipt_MARK.c linux-2.6.8-case/net/ipv4/netfilter/ipt_MARK.c --- linux-2.6.8/net/ipv4/netfilter/ipt_MARK.c 2004-08-14 07:36:58.000000000 +0200 +++ linux-2.6.8-case/net/ipv4/netfilter/ipt_MARK.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,79 +0,0 @@ -/* This is a module which is used for setting the NFMARK field of an skb. */ - -/* (C) 1999-2001 Marc Boucher - * - * 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("Marc Boucher "); -MODULE_DESCRIPTION("iptables MARK modification module"); - -static unsigned int -target(struct sk_buff **pskb, - const struct net_device *in, - const struct net_device *out, - unsigned int hooknum, - const void *targinfo, - void *userinfo) -{ - const struct ipt_mark_target_info *markinfo = targinfo; - - if((*pskb)->nfmark != markinfo->mark) { - (*pskb)->nfmark = markinfo->mark; - (*pskb)->nfcache |= NFC_ALTERED; - } - return IPT_CONTINUE; -} - -static int -checkentry(const char *tablename, - const struct ipt_entry *e, - void *targinfo, - unsigned int targinfosize, - unsigned int hook_mask) -{ - if (targinfosize != IPT_ALIGN(sizeof(struct ipt_mark_target_info))) { - printk(KERN_WARNING "MARK: targinfosize %u != %Zu\n", - targinfosize, - IPT_ALIGN(sizeof(struct ipt_mark_target_info))); - return 0; - } - - if (strcmp(tablename, "mangle") != 0) { - printk(KERN_WARNING "MARK: can only be called from \"mangle\" table, not \"%s\"\n", tablename); - return 0; - } - - return 1; -} - -static struct ipt_target ipt_mark_reg = { - .name = "MARK", - .target = target, - .checkentry = checkentry, - .me = THIS_MODULE, -}; - -static int __init init(void) -{ - return ipt_register_target(&ipt_mark_reg); -} - -static void __exit fini(void) -{ - ipt_unregister_target(&ipt_mark_reg); -} - -module_init(init); -module_exit(fini); diff -Nru linux-2.6.8/net/ipv4/netfilter/ipt_MARK_u.c linux-2.6.8-case/net/ipv4/netfilter/ipt_MARK_u.c --- linux-2.6.8/net/ipv4/netfilter/ipt_MARK_u.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.8-case/net/ipv4/netfilter/ipt_MARK_u.c 2004-09-24 14:24:40.000000000 +0200 @@ -0,0 +1,79 @@ +/* This is a module which is used for setting the NFMARK field of an skb. */ + +/* (C) 1999-2001 Marc Boucher + * + * 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("Marc Boucher "); +MODULE_DESCRIPTION("iptables MARK modification module"); + +static unsigned int +target(struct sk_buff **pskb, + const struct net_device *in, + const struct net_device *out, + unsigned int hooknum, + const void *targinfo, + void *userinfo) +{ + const struct ipt_mark_target_info *markinfo = targinfo; + + if((*pskb)->nfmark != markinfo->mark) { + (*pskb)->nfmark = markinfo->mark; + (*pskb)->nfcache |= NFC_ALTERED; + } + return IPT_CONTINUE; +} + +static int +checkentry(const char *tablename, + const struct ipt_entry *e, + void *targinfo, + unsigned int targinfosize, + unsigned int hook_mask) +{ + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_mark_target_info))) { + printk(KERN_WARNING "MARK: targinfosize %u != %Zu\n", + targinfosize, + IPT_ALIGN(sizeof(struct ipt_mark_target_info))); + return 0; + } + + if (strcmp(tablename, "mangle") != 0) { + printk(KERN_WARNING "MARK: can only be called from \"mangle\" table, not \"%s\"\n", tablename); + return 0; + } + + return 1; +} + +static struct ipt_target ipt_mark_reg = { + .name = "MARK", + .target = target, + .checkentry = checkentry, + .me = THIS_MODULE, +}; + +static int __init init(void) +{ + return ipt_register_target(&ipt_mark_reg); +} + +static void __exit fini(void) +{ + ipt_unregister_target(&ipt_mark_reg); +} + +module_init(init); +module_exit(fini); diff -Nru linux-2.6.8/net/ipv4/netfilter/ipt_TCPMSS.c linux-2.6.8-case/net/ipv4/netfilter/ipt_TCPMSS.c --- linux-2.6.8/net/ipv4/netfilter/ipt_TCPMSS.c 2004-08-14 07:36:58.000000000 +0200 +++ linux-2.6.8-case/net/ipv4/netfilter/ipt_TCPMSS.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,262 +0,0 @@ -/* - * This is a module which is used for setting the MSS option in TCP packets. - * - * Copyright (C) 2000 Marc Boucher - * - * 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("Marc Boucher "); -MODULE_DESCRIPTION("iptables TCP MSS modification module"); - -#if 0 -#define DEBUGP printk -#else -#define DEBUGP(format, args...) -#endif - -static u_int16_t -cheat_check(u_int32_t oldvalinv, u_int32_t newval, u_int16_t oldcheck) -{ - u_int32_t diffs[] = { oldvalinv, newval }; - return csum_fold(csum_partial((char *)diffs, sizeof(diffs), - oldcheck^0xFFFF)); -} - -static inline unsigned int -optlen(const u_int8_t *opt, unsigned int offset) -{ - /* Beware zero-length options: make finite progress */ - if (opt[offset] <= TCPOPT_NOP || opt[offset+1] == 0) return 1; - else return opt[offset+1]; -} - -static unsigned int -ipt_tcpmss_target(struct sk_buff **pskb, - const struct net_device *in, - const struct net_device *out, - unsigned int hooknum, - const void *targinfo, - void *userinfo) -{ - const struct ipt_tcpmss_info *tcpmssinfo = targinfo; - struct tcphdr *tcph; - struct iphdr *iph; - u_int16_t tcplen, newtotlen, oldval, newmss; - unsigned int i; - u_int8_t *opt; - - if (!skb_ip_make_writable(pskb, (*pskb)->len)) - return NF_DROP; - - iph = (*pskb)->nh.iph; - tcplen = (*pskb)->len - iph->ihl*4; - - tcph = (void *)iph + iph->ihl*4; - - /* Since it passed flags test in tcp match, we know it is is - not a fragment, and has data >= tcp header length. SYN - packets should not contain data: if they did, then we risk - running over MTU, sending Frag Needed and breaking things - badly. --RR */ - if (tcplen != tcph->doff*4) { - if (net_ratelimit()) - printk(KERN_ERR - "ipt_tcpmss_target: bad length (%d bytes)\n", - (*pskb)->len); - return NF_DROP; - } - - if(tcpmssinfo->mss == IPT_TCPMSS_CLAMP_PMTU) { - if(!(*pskb)->dst) { - if (net_ratelimit()) - printk(KERN_ERR - "ipt_tcpmss_target: no dst?! can't determine path-MTU\n"); - return NF_DROP; /* or IPT_CONTINUE ?? */ - } - - if(dst_pmtu((*pskb)->dst) <= (sizeof(struct iphdr) + sizeof(struct tcphdr))) { - if (net_ratelimit()) - printk(KERN_ERR - "ipt_tcpmss_target: unknown or invalid path-MTU (%d)\n", dst_pmtu((*pskb)->dst)); - return NF_DROP; /* or IPT_CONTINUE ?? */ - } - - newmss = dst_pmtu((*pskb)->dst) - sizeof(struct iphdr) - sizeof(struct tcphdr); - } else - newmss = tcpmssinfo->mss; - - opt = (u_int8_t *)tcph; - for (i = sizeof(struct tcphdr); i < tcph->doff*4; i += optlen(opt, i)){ - if ((opt[i] == TCPOPT_MSS) && - ((tcph->doff*4 - i) >= TCPOLEN_MSS) && - (opt[i+1] == TCPOLEN_MSS)) { - u_int16_t oldmss; - - oldmss = (opt[i+2] << 8) | opt[i+3]; - - if((tcpmssinfo->mss == IPT_TCPMSS_CLAMP_PMTU) && - (oldmss <= newmss)) - return IPT_CONTINUE; - - opt[i+2] = (newmss & 0xff00) >> 8; - opt[i+3] = (newmss & 0x00ff); - - tcph->check = cheat_check(htons(oldmss)^0xFFFF, - htons(newmss), - tcph->check); - - DEBUGP(KERN_INFO "ipt_tcpmss_target: %u.%u.%u.%u:%hu" - "->%u.%u.%u.%u:%hu changed TCP MSS option" - " (from %u to %u)\n", - NIPQUAD((*pskb)->nh.iph->saddr), - ntohs(tcph->source), - NIPQUAD((*pskb)->nh.iph->daddr), - ntohs(tcph->dest), - oldmss, newmss); - goto retmodified; - } - } - - /* - * MSS Option not found ?! add it.. - */ - if (skb_tailroom((*pskb)) < TCPOLEN_MSS) { - struct sk_buff *newskb; - - newskb = skb_copy_expand(*pskb, skb_headroom(*pskb), - TCPOLEN_MSS, GFP_ATOMIC); - if (!newskb) { - if (net_ratelimit()) - printk(KERN_ERR "ipt_tcpmss_target:" - " unable to allocate larger skb\n"); - return NF_DROP; - } - - kfree_skb(*pskb); - *pskb = newskb; - iph = (*pskb)->nh.iph; - tcph = (void *)iph + iph->ihl*4; - } - - skb_put((*pskb), TCPOLEN_MSS); - - opt = (u_int8_t *)tcph + sizeof(struct tcphdr); - memmove(opt + TCPOLEN_MSS, opt, tcplen - sizeof(struct tcphdr)); - - tcph->check = cheat_check(htons(tcplen) ^ 0xFFFF, - htons(tcplen + TCPOLEN_MSS), tcph->check); - tcplen += TCPOLEN_MSS; - - opt[0] = TCPOPT_MSS; - opt[1] = TCPOLEN_MSS; - opt[2] = (newmss & 0xff00) >> 8; - opt[3] = (newmss & 0x00ff); - - tcph->check = cheat_check(~0, *((u_int32_t *)opt), tcph->check); - - oldval = ((u_int16_t *)tcph)[6]; - tcph->doff += TCPOLEN_MSS/4; - tcph->check = cheat_check(oldval ^ 0xFFFF, - ((u_int16_t *)tcph)[6], tcph->check); - - newtotlen = htons(ntohs(iph->tot_len) + TCPOLEN_MSS); - iph->check = cheat_check(iph->tot_len ^ 0xFFFF, - newtotlen, iph->check); - iph->tot_len = newtotlen; - - DEBUGP(KERN_INFO "ipt_tcpmss_target: %u.%u.%u.%u:%hu" - "->%u.%u.%u.%u:%hu added TCP MSS option (%u)\n", - NIPQUAD((*pskb)->nh.iph->saddr), - ntohs(tcph->source), - NIPQUAD((*pskb)->nh.iph->daddr), - ntohs(tcph->dest), - newmss); - - retmodified: - /* We never hw checksum SYN packets. */ - BUG_ON((*pskb)->ip_summed == CHECKSUM_HW); - - (*pskb)->nfcache |= NFC_UNKNOWN | NFC_ALTERED; - return IPT_CONTINUE; -} - -#define TH_SYN 0x02 - -static inline int find_syn_match(const struct ipt_entry_match *m) -{ - const struct ipt_tcp *tcpinfo = (const struct ipt_tcp *)m->data; - - if (strcmp(m->u.kernel.match->name, "tcp") == 0 - && (tcpinfo->flg_cmp & TH_SYN) - && !(tcpinfo->invflags & IPT_TCP_INV_FLAGS)) - return 1; - - return 0; -} - -/* Must specify -p tcp --syn/--tcp-flags SYN */ -static int -ipt_tcpmss_checkentry(const char *tablename, - const struct ipt_entry *e, - void *targinfo, - unsigned int targinfosize, - unsigned int hook_mask) -{ - const struct ipt_tcpmss_info *tcpmssinfo = targinfo; - - if (targinfosize != IPT_ALIGN(sizeof(struct ipt_tcpmss_info))) { - DEBUGP("ipt_tcpmss_checkentry: targinfosize %u != %u\n", - targinfosize, IPT_ALIGN(sizeof(struct ipt_tcpmss_info))); - return 0; - } - - - if((tcpmssinfo->mss == IPT_TCPMSS_CLAMP_PMTU) && - ((hook_mask & ~((1 << NF_IP_FORWARD) - | (1 << NF_IP_LOCAL_OUT) - | (1 << NF_IP_POST_ROUTING))) != 0)) { - printk("TCPMSS: path-MTU clamping only supported in FORWARD, OUTPUT and POSTROUTING hooks\n"); - return 0; - } - - if (e->ip.proto == IPPROTO_TCP - && !(e->ip.invflags & IPT_INV_PROTO) - && IPT_MATCH_ITERATE(e, find_syn_match)) - return 1; - - printk("TCPMSS: Only works on TCP SYN packets\n"); - return 0; -} - -static struct ipt_target ipt_tcpmss_reg = { - .name = "TCPMSS", - .target = ipt_tcpmss_target, - .checkentry = ipt_tcpmss_checkentry, - .me = THIS_MODULE, -}; - -static int __init init(void) -{ - return ipt_register_target(&ipt_tcpmss_reg); -} - -static void __exit fini(void) -{ - ipt_unregister_target(&ipt_tcpmss_reg); -} - -module_init(init); -module_exit(fini); diff -Nru linux-2.6.8/net/ipv4/netfilter/ipt_TCPMSS_u.c linux-2.6.8-case/net/ipv4/netfilter/ipt_TCPMSS_u.c --- linux-2.6.8/net/ipv4/netfilter/ipt_TCPMSS_u.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.8-case/net/ipv4/netfilter/ipt_TCPMSS_u.c 2004-09-24 14:24:52.000000000 +0200 @@ -0,0 +1,262 @@ +/* + * This is a module which is used for setting the MSS option in TCP packets. + * + * Copyright (C) 2000 Marc Boucher + * + * 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("Marc Boucher "); +MODULE_DESCRIPTION("iptables TCP MSS modification module"); + +#if 0 +#define DEBUGP printk +#else +#define DEBUGP(format, args...) +#endif + +static u_int16_t +cheat_check(u_int32_t oldvalinv, u_int32_t newval, u_int16_t oldcheck) +{ + u_int32_t diffs[] = { oldvalinv, newval }; + return csum_fold(csum_partial((char *)diffs, sizeof(diffs), + oldcheck^0xFFFF)); +} + +static inline unsigned int +optlen(const u_int8_t *opt, unsigned int offset) +{ + /* Beware zero-length options: make finite progress */ + if (opt[offset] <= TCPOPT_NOP || opt[offset+1] == 0) return 1; + else return opt[offset+1]; +} + +static unsigned int +ipt_tcpmss_target(struct sk_buff **pskb, + const struct net_device *in, + const struct net_device *out, + unsigned int hooknum, + const void *targinfo, + void *userinfo) +{ + const struct ipt_tcpmss_info *tcpmssinfo = targinfo; + struct tcphdr *tcph; + struct iphdr *iph; + u_int16_t tcplen, newtotlen, oldval, newmss; + unsigned int i; + u_int8_t *opt; + + if (!skb_ip_make_writable(pskb, (*pskb)->len)) + return NF_DROP; + + iph = (*pskb)->nh.iph; + tcplen = (*pskb)->len - iph->ihl*4; + + tcph = (void *)iph + iph->ihl*4; + + /* Since it passed flags test in tcp match, we know it is is + not a fragment, and has data >= tcp header length. SYN + packets should not contain data: if they did, then we risk + running over MTU, sending Frag Needed and breaking things + badly. --RR */ + if (tcplen != tcph->doff*4) { + if (net_ratelimit()) + printk(KERN_ERR + "ipt_tcpmss_target: bad length (%d bytes)\n", + (*pskb)->len); + return NF_DROP; + } + + if(tcpmssinfo->mss == IPT_TCPMSS_CLAMP_PMTU) { + if(!(*pskb)->dst) { + if (net_ratelimit()) + printk(KERN_ERR + "ipt_tcpmss_target: no dst?! can't determine path-MTU\n"); + return NF_DROP; /* or IPT_CONTINUE ?? */ + } + + if(dst_pmtu((*pskb)->dst) <= (sizeof(struct iphdr) + sizeof(struct tcphdr))) { + if (net_ratelimit()) + printk(KERN_ERR + "ipt_tcpmss_target: unknown or invalid path-MTU (%d)\n", dst_pmtu((*pskb)->dst)); + return NF_DROP; /* or IPT_CONTINUE ?? */ + } + + newmss = dst_pmtu((*pskb)->dst) - sizeof(struct iphdr) - sizeof(struct tcphdr); + } else + newmss = tcpmssinfo->mss; + + opt = (u_int8_t *)tcph; + for (i = sizeof(struct tcphdr); i < tcph->doff*4; i += optlen(opt, i)){ + if ((opt[i] == TCPOPT_MSS) && + ((tcph->doff*4 - i) >= TCPOLEN_MSS) && + (opt[i+1] == TCPOLEN_MSS)) { + u_int16_t oldmss; + + oldmss = (opt[i+2] << 8) | opt[i+3]; + + if((tcpmssinfo->mss == IPT_TCPMSS_CLAMP_PMTU) && + (oldmss <= newmss)) + return IPT_CONTINUE; + + opt[i+2] = (newmss & 0xff00) >> 8; + opt[i+3] = (newmss & 0x00ff); + + tcph->check = cheat_check(htons(oldmss)^0xFFFF, + htons(newmss), + tcph->check); + + DEBUGP(KERN_INFO "ipt_tcpmss_target: %u.%u.%u.%u:%hu" + "->%u.%u.%u.%u:%hu changed TCP MSS option" + " (from %u to %u)\n", + NIPQUAD((*pskb)->nh.iph->saddr), + ntohs(tcph->source), + NIPQUAD((*pskb)->nh.iph->daddr), + ntohs(tcph->dest), + oldmss, newmss); + goto retmodified; + } + } + + /* + * MSS Option not found ?! add it.. + */ + if (skb_tailroom((*pskb)) < TCPOLEN_MSS) { + struct sk_buff *newskb; + + newskb = skb_copy_expand(*pskb, skb_headroom(*pskb), + TCPOLEN_MSS, GFP_ATOMIC); + if (!newskb) { + if (net_ratelimit()) + printk(KERN_ERR "ipt_tcpmss_target:" + " unable to allocate larger skb\n"); + return NF_DROP; + } + + kfree_skb(*pskb); + *pskb = newskb; + iph = (*pskb)->nh.iph; + tcph = (void *)iph + iph->ihl*4; + } + + skb_put((*pskb), TCPOLEN_MSS); + + opt = (u_int8_t *)tcph + sizeof(struct tcphdr); + memmove(opt + TCPOLEN_MSS, opt, tcplen - sizeof(struct tcphdr)); + + tcph->check = cheat_check(htons(tcplen) ^ 0xFFFF, + htons(tcplen + TCPOLEN_MSS), tcph->check); + tcplen += TCPOLEN_MSS; + + opt[0] = TCPOPT_MSS; + opt[1] = TCPOLEN_MSS; + opt[2] = (newmss & 0xff00) >> 8; + opt[3] = (newmss & 0x00ff); + + tcph->check = cheat_check(~0, *((u_int32_t *)opt), tcph->check); + + oldval = ((u_int16_t *)tcph)[6]; + tcph->doff += TCPOLEN_MSS/4; + tcph->check = cheat_check(oldval ^ 0xFFFF, + ((u_int16_t *)tcph)[6], tcph->check); + + newtotlen = htons(ntohs(iph->tot_len) + TCPOLEN_MSS); + iph->check = cheat_check(iph->tot_len ^ 0xFFFF, + newtotlen, iph->check); + iph->tot_len = newtotlen; + + DEBUGP(KERN_INFO "ipt_tcpmss_target: %u.%u.%u.%u:%hu" + "->%u.%u.%u.%u:%hu added TCP MSS option (%u)\n", + NIPQUAD((*pskb)->nh.iph->saddr), + ntohs(tcph->source), + NIPQUAD((*pskb)->nh.iph->daddr), + ntohs(tcph->dest), + newmss); + + retmodified: + /* We never hw checksum SYN packets. */ + BUG_ON((*pskb)->ip_summed == CHECKSUM_HW); + + (*pskb)->nfcache |= NFC_UNKNOWN | NFC_ALTERED; + return IPT_CONTINUE; +} + +#define TH_SYN 0x02 + +static inline int find_syn_match(const struct ipt_entry_match *m) +{ + const struct ipt_tcp *tcpinfo = (const struct ipt_tcp *)m->data; + + if (strcmp(m->u.kernel.match->name, "tcp") == 0 + && (tcpinfo->flg_cmp & TH_SYN) + && !(tcpinfo->invflags & IPT_TCP_INV_FLAGS)) + return 1; + + return 0; +} + +/* Must specify -p tcp --syn/--tcp-flags SYN */ +static int +ipt_tcpmss_checkentry(const char *tablename, + const struct ipt_entry *e, + void *targinfo, + unsigned int targinfosize, + unsigned int hook_mask) +{ + const struct ipt_tcpmss_info *tcpmssinfo = targinfo; + + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_tcpmss_info))) { + DEBUGP("ipt_tcpmss_checkentry: targinfosize %u != %u\n", + targinfosize, IPT_ALIGN(sizeof(struct ipt_tcpmss_info))); + return 0; + } + + + if((tcpmssinfo->mss == IPT_TCPMSS_CLAMP_PMTU) && + ((hook_mask & ~((1 << NF_IP_FORWARD) + | (1 << NF_IP_LOCAL_OUT) + | (1 << NF_IP_POST_ROUTING))) != 0)) { + printk("TCPMSS: path-MTU clamping only supported in FORWARD, OUTPUT and POSTROUTING hooks\n"); + return 0; + } + + if (e->ip.proto == IPPROTO_TCP + && !(e->ip.invflags & IPT_INV_PROTO) + && IPT_MATCH_ITERATE(e, find_syn_match)) + return 1; + + printk("TCPMSS: Only works on TCP SYN packets\n"); + return 0; +} + +static struct ipt_target ipt_tcpmss_reg = { + .name = "TCPMSS", + .target = ipt_tcpmss_target, + .checkentry = ipt_tcpmss_checkentry, + .me = THIS_MODULE, +}; + +static int __init init(void) +{ + return ipt_register_target(&ipt_tcpmss_reg); +} + +static void __exit fini(void) +{ + ipt_unregister_target(&ipt_tcpmss_reg); +} + +module_init(init); +module_exit(fini); diff -Nru linux-2.6.8/net/ipv4/netfilter/ipt_TOS.c linux-2.6.8-case/net/ipv4/netfilter/ipt_TOS.c --- linux-2.6.8/net/ipv4/netfilter/ipt_TOS.c 2004-08-14 07:36:13.000000000 +0200 +++ linux-2.6.8-case/net/ipv4/netfilter/ipt_TOS.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,105 +0,0 @@ -/* This is a module which is used for setting the TOS field of a packet. */ - -/* (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 TOS mangling module"); - -static unsigned int -target(struct sk_buff **pskb, - const struct net_device *in, - const struct net_device *out, - unsigned int hooknum, - const void *targinfo, - void *userinfo) -{ - const struct ipt_tos_target_info *tosinfo = targinfo; - - if (((*pskb)->nh.iph->tos & IPTOS_TOS_MASK) != tosinfo->tos) { - u_int16_t diffs[2]; - - if (!skb_ip_make_writable(pskb, sizeof(struct iphdr))) - return NF_DROP; - - diffs[0] = htons((*pskb)->nh.iph->tos) ^ 0xFFFF; - (*pskb)->nh.iph->tos - = ((*pskb)->nh.iph->tos & IPTOS_PREC_MASK) - | tosinfo->tos; - diffs[1] = htons((*pskb)->nh.iph->tos); - (*pskb)->nh.iph->check - = csum_fold(csum_partial((char *)diffs, - sizeof(diffs), - (*pskb)->nh.iph->check - ^0xFFFF)); - (*pskb)->nfcache |= NFC_ALTERED; - } - return IPT_CONTINUE; -} - -static int -checkentry(const char *tablename, - const struct ipt_entry *e, - void *targinfo, - unsigned int targinfosize, - unsigned int hook_mask) -{ - const u_int8_t tos = ((struct ipt_tos_target_info *)targinfo)->tos; - - if (targinfosize != IPT_ALIGN(sizeof(struct ipt_tos_target_info))) { - printk(KERN_WARNING "TOS: targinfosize %u != %Zu\n", - targinfosize, - IPT_ALIGN(sizeof(struct ipt_tos_target_info))); - return 0; - } - - if (strcmp(tablename, "mangle") != 0) { - printk(KERN_WARNING "TOS: can only be called from \"mangle\" table, not \"%s\"\n", tablename); - return 0; - } - - if (tos != IPTOS_LOWDELAY - && tos != IPTOS_THROUGHPUT - && tos != IPTOS_RELIABILITY - && tos != IPTOS_MINCOST - && tos != IPTOS_NORMALSVC) { - printk(KERN_WARNING "TOS: bad tos value %#x\n", tos); - return 0; - } - - return 1; -} - -static struct ipt_target ipt_tos_reg = { - .name = "TOS", - .target = target, - .checkentry = checkentry, - .me = THIS_MODULE, -}; - -static int __init init(void) -{ - return ipt_register_target(&ipt_tos_reg); -} - -static void __exit fini(void) -{ - ipt_unregister_target(&ipt_tos_reg); -} - -module_init(init); -module_exit(fini); diff -Nru linux-2.6.8/net/ipv4/netfilter/ipt_TOS_u.c linux-2.6.8-case/net/ipv4/netfilter/ipt_TOS_u.c --- linux-2.6.8/net/ipv4/netfilter/ipt_TOS_u.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.8-case/net/ipv4/netfilter/ipt_TOS_u.c 2004-09-24 14:24:06.000000000 +0200 @@ -0,0 +1,105 @@ +/* This is a module which is used for setting the TOS field of a packet. */ + +/* (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 TOS mangling module"); + +static unsigned int +target(struct sk_buff **pskb, + const struct net_device *in, + const struct net_device *out, + unsigned int hooknum, + const void *targinfo, + void *userinfo) +{ + const struct ipt_tos_target_info *tosinfo = targinfo; + + if (((*pskb)->nh.iph->tos & IPTOS_TOS_MASK) != tosinfo->tos) { + u_int16_t diffs[2]; + + if (!skb_ip_make_writable(pskb, sizeof(struct iphdr))) + return NF_DROP; + + diffs[0] = htons((*pskb)->nh.iph->tos) ^ 0xFFFF; + (*pskb)->nh.iph->tos + = ((*pskb)->nh.iph->tos & IPTOS_PREC_MASK) + | tosinfo->tos; + diffs[1] = htons((*pskb)->nh.iph->tos); + (*pskb)->nh.iph->check + = csum_fold(csum_partial((char *)diffs, + sizeof(diffs), + (*pskb)->nh.iph->check + ^0xFFFF)); + (*pskb)->nfcache |= NFC_ALTERED; + } + return IPT_CONTINUE; +} + +static int +checkentry(const char *tablename, + const struct ipt_entry *e, + void *targinfo, + unsigned int targinfosize, + unsigned int hook_mask) +{ + const u_int8_t tos = ((struct ipt_tos_target_info *)targinfo)->tos; + + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_tos_target_info))) { + printk(KERN_WARNING "TOS: targinfosize %u != %Zu\n", + targinfosize, + IPT_ALIGN(sizeof(struct ipt_tos_target_info))); + return 0; + } + + if (strcmp(tablename, "mangle") != 0) { + printk(KERN_WARNING "TOS: can only be called from \"mangle\" table, not \"%s\"\n", tablename); + return 0; + } + + if (tos != IPTOS_LOWDELAY + && tos != IPTOS_THROUGHPUT + && tos != IPTOS_RELIABILITY + && tos != IPTOS_MINCOST + && tos != IPTOS_NORMALSVC) { + printk(KERN_WARNING "TOS: bad tos value %#x\n", tos); + return 0; + } + + return 1; +} + +static struct ipt_target ipt_tos_reg = { + .name = "TOS", + .target = target, + .checkentry = checkentry, + .me = THIS_MODULE, +}; + +static int __init init(void) +{ + return ipt_register_target(&ipt_tos_reg); +} + +static void __exit fini(void) +{ + ipt_unregister_target(&ipt_tos_reg); +} + +module_init(init); +module_exit(fini);