In response to my last question, I had to recompile both the kernel and the ppp modules to get ppp multilink support to work. With that now functionnal, I hit another wall with netfilter. Since I have multiple ISP accounts and multiple broadband connections, being able to use connection tracking and extended MARK target (to use Shorewall's HIGH_ROUTE_MARKS) was necessary. Here are the required kernel and iptables patches needed to get both working.
For kernel 2.4.34.6: *** linux-2.4.34.6.orig/include/linux/netfilter_ipv4/ipt_MARK.h 2007-07-22 09:50:47.000000000 -0400 --- linux-2.4.34.6/include/linux/netfilter_ipv4/ipt_MARK.h 2008-10-22 15:44:35.000000000 -0400 *************** *** 3,8 **** --- 3,15 ---- struct ipt_mark_target_info { unsigned long mark; + u_int8_t mode; + }; + + enum { + IPT_MARK_SET=0, + IPT_MARK_AND, + IPT_MARK_OR }; #endif /*_IPT_MARK_H_target*/ *** linux-2.4.34.6.orig/net/ipv4/netfilter/ip_conntrack_core.c 2008-10-22 12:47:22.000000000 -0400 --- linux-2.4.34.6/net/ipv4/netfilter/ip_conntrack_core.c 2008-10-20 12:22:36.000000000 -0400 *************** *** 746,752 **** __set_bit(IPS_EXPECTED_BIT, &conntrack->status); conntrack->master = expected; expected->sibling = conntrack; ! #if CONFIG_IP_NF_CONNTRACK_MARK conntrack->mark = expected->expectant->mark; #endif LIST_DELETE(&ip_conntrack_expect_list, expected); --- 746,752 ---- __set_bit(IPS_EXPECTED_BIT, &conntrack->status); conntrack->master = expected; expected->sibling = conntrack; ! #if defined(CONFIG_IP_NF_CONNTRACK_MARK) conntrack->mark = expected->expectant->mark; #endif LIST_DELETE(&ip_conntrack_expect_list, expected); *** linux-2.4.34.6.orig/net/ipv4/netfilter/ipt_MARK.c 2007-07-22 09:50:47.000000000 -0400 --- linux-2.4.34.6/net/ipv4/netfilter/ipt_MARK.c 2008-10-22 12:59:55.000000000 -0400 *************** *** 16,29 **** 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, --- 16,45 ---- void *userinfo) { const struct ipt_mark_target_info *markinfo = targinfo; + int mark = 0; ! switch (markinfo->mode) { ! case IPT_MARK_SET: ! mark = markinfo->mark; ! break; ! ! case IPT_MARK_AND: ! mark = (*pskb)->nfmark & markinfo->mark; ! break; ! ! case IPT_MARK_OR: ! mark = (*pskb)->nfmark | markinfo->mark; ! break; ! } ! ! if((*pskb)->nfmark != mark) { ! (*pskb)->nfmark = mark; (*pskb)->nfcache |= NFC_ALTERED; } return IPT_CONTINUE; } + static int checkentry(const char *tablename, const struct ipt_entry *e, *************** *** 31,37 **** 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))); --- 47,55 ---- unsigned int targinfosize, unsigned int hook_mask) { ! struct ipt_mark_target_info *markinfo = targinfo; ! ! 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))); *************** *** 43,48 **** --- 61,74 ---- return 0; } + if (markinfo->mode != IPT_MARK_SET + && markinfo->mode != IPT_MARK_AND + && markinfo->mode != IPT_MARK_OR) { + printk(KERN_WARNING "MARK: unknown mode %u\n", + markinfo->mode); + return 0; + } + return 1; } *************** *** 51,60 **** static int __init init(void) { ! if (ipt_register_target(&ipt_mark_reg)) ! return -EINVAL; ! return 0; } static void __exit fini(void) --- 77,86 ---- static int __init init(void) { ! int err; ! err = ipt_register_target(&ipt_mark_reg); ! return err; } static void __exit fini(void) And for iptables 1.3.5: *** iptables-1.3.5.orig/include/linux/netfilter_ipv4/ipt_MARK.h 2005-01-04 05:38:28.000000000 -0500 --- iptables-1.3.5/include/linux/netfilter_ipv4/ipt_MARK.h 2008-10-20 11:58:25.000000000 -0400 *************** *** 7,12 **** --- 7,13 ---- #else unsigned long mark; #endif + u_int8_t mode; }; enum { *** iptables-1.3.5.orig/include/linux/netfilter_ipv4/ipt_conntrack.h 2006-02-01 07:48:01.000000000 -0500 --- iptables-1.3.5/include/linux/netfilter_ipv4/ipt_conntrack.h 2008-10-22 12:01:18.000000000 -0400 *************** *** 6,11 **** --- 6,12 ---- #define _IPT_CONNTRACK_H #include <linux/netfilter_ipv4/ip_conntrack.h> + #include <linux/netfilter_ipv4/ip_conntrack_tuple.h> /* backwards compatibility crap. only exists in userspace - HW */ #include <linux/version.h> *************** *** 64,70 **** { unsigned int statemask, statusmask; ! struct ip_conntrack_old_tuple tuple[IP_CT_DIR_MAX]; struct in_addr sipmsk[IP_CT_DIR_MAX], dipmsk[IP_CT_DIR_MAX]; #ifdef KERNEL_64_USERSPACE_32 --- 65,71 ---- { unsigned int statemask, statusmask; ! struct ip_conntrack_tuple tuple[IP_CT_DIR_MAX]; struct in_addr sipmsk[IP_CT_DIR_MAX], dipmsk[IP_CT_DIR_MAX]; #ifdef KERNEL_64_USERSPACE_32 *** iptables-1.3.5.orig/include/linux/netfilter_ipv4/ip_conntrack_tuple.h 1969-12-31 19:00:00.000000000 -0500 --- iptables-1.3.5/include/linux/netfilter_ipv4/ip_conntrack_tuple.h 2008-10-22 11:59:02.000000000 -0400 *************** *** 0 **** --- 1,151 ---- + #ifndef _IP_CONNTRACK_TUPLE_H + #define _IP_CONNTRACK_TUPLE_H + + /* A `tuple' is a structure containing the information to uniquely + identify a connection. ie. if two packets have the same tuple, they + are in the same connection; if not, they are not. + + We divide the structure along "manipulatable" and + "non-manipulatable" lines, for the benefit of the NAT code. + */ + + /* The protocol-specific manipulable parts of the tuple: always in + network order! */ + union ip_conntrack_manip_proto + { + /* Add other protocols here. */ + u_int32_t all; + + struct { + u_int16_t port; + } tcp; + struct { + u_int16_t port; + } udp; + struct { + u_int16_t id; + } icmp; + struct { + u_int32_t key; + } gre; + }; + + /* The manipulable part of the tuple. */ + struct ip_conntrack_manip + { + u_int32_t ip; + union ip_conntrack_manip_proto u; + }; + + /* This contains the information to distinguish a connection. */ + struct ip_conntrack_tuple + { + struct ip_conntrack_manip src; + + /* These are the parts of the tuple which are fixed. */ + struct { + u_int32_t ip; + union { + /* Add other protocols here. */ + u_int32_t all; + + struct { + u_int16_t port; + } tcp; + struct { + u_int16_t port; + } udp; + struct { + u_int8_t type, code; + } icmp; + struct { + u_int32_t key; + } gre; + } u; + + /* The protocol. */ + u_int16_t protonum; + } dst; + }; + + /* This is optimized opposed to a memset of the whole structure. Everything we + * really care about is the source/destination unions */ + #define IP_CT_TUPLE_U_BLANK(tuple) \ + do { \ + (tuple)->src.u.all = 0; \ + (tuple)->dst.u.all = 0; \ + } while (0) + + enum ip_conntrack_dir + { + IP_CT_DIR_ORIGINAL, + IP_CT_DIR_REPLY, + IP_CT_DIR_MAX + }; + + #ifdef __KERNEL__ + + #define DUMP_TUPLE(tp) \ + DEBUGP("tuple %p: %u %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u\n", \ + (tp), (tp)->dst.protonum, \ + NIPQUAD((tp)->src.ip), ntohl((tp)->src.u.all), \ + NIPQUAD((tp)->dst.ip), ntohl((tp)->dst.u.all)) + + #define DUMP_TUPLE_RAW(x) \ + DEBUGP("tuple %p: %u %u.%u.%u.%u:0x%08x -> %u.%u.%u.%u:0x%08x\n",\ + (x), (x)->dst.protonum, \ + NIPQUAD((x)->src.ip), ntohl((x)->src.u.all), \ + NIPQUAD((x)->dst.ip), ntohl((x)->dst.u.all)) + + #define CTINFO2DIR(ctinfo) ((ctinfo) >= IP_CT_IS_REPLY ? IP_CT_DIR_REPLY : IP_CT_DIR_ORIGINAL) + + /* If we're the first tuple, it's the original dir. */ + #define DIRECTION(h) ((enum ip_conntrack_dir)(&(h)->ctrack->tuplehash[1] == (h))) + + /* Connections have two entries in the hash table: one for each way */ + struct ip_conntrack_tuple_hash + { + struct list_head list; + + struct ip_conntrack_tuple tuple; + + /* this == &ctrack->tuplehash[DIRECTION(this)]. */ + struct ip_conntrack *ctrack; + }; + + #endif /* __KERNEL__ */ + + static inline int ip_ct_tuple_src_equal(const struct ip_conntrack_tuple *t1, + const struct ip_conntrack_tuple *t2) + { + return t1->src.ip == t2->src.ip + && t1->src.u.all == t2->src.u.all; + } + + static inline int ip_ct_tuple_dst_equal(const struct ip_conntrack_tuple *t1, + const struct ip_conntrack_tuple *t2) + { + return t1->dst.ip == t2->dst.ip + && t1->dst.u.all == t2->dst.u.all + && t1->dst.protonum == t2->dst.protonum; + } + + static inline int ip_ct_tuple_equal(const struct ip_conntrack_tuple *t1, + const struct ip_conntrack_tuple *t2) + { + return ip_ct_tuple_src_equal(t1, t2) && ip_ct_tuple_dst_equal(t1, t2); + } + + static inline int ip_ct_tuple_mask_cmp(const struct ip_conntrack_tuple *t, + const struct ip_conntrack_tuple *tuple, + const struct ip_conntrack_tuple *mask) + { + return !(((t->src.ip ^ tuple->src.ip) & mask->src.ip) + || ((t->dst.ip ^ tuple->dst.ip) & mask->dst.ip) + || ((t->src.u.all ^ tuple->src.u.all) & mask->src.u.all) + || ((t->dst.u.all ^ tuple->dst.u.all) & mask->dst.u.all) + || ((t->dst.protonum ^ tuple->dst.protonum) + & mask->dst.protonum)); + } + + #endif /* _IP_CONNTRACK_TUPLE_H */ pgm ------------------------------------------------------------------------- This SF.Net email is sponsored by the Moblin Your Move Developer's challenge Build the coolest Linux based applications with Moblin SDK & win great prizes Grand prize is a trip for two to an Open Source event anywhere in the world http://moblin-contest.org/redirect.php?banner_id=100&url=/ ------------------------------------------------------------------------ leaf-user mailing list: leaf-user@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/leaf-user Support Request -- http://leaf-project.org/