--- linux-2.5/net/ipv4/netfilter/ipt_multiport.c 2005-01-01 19:03:25.000000000 +0100 +++ revision/net/ipv4/netfilter/ipt_multiport.c 2005-01-01 19:03:13.000000000 +0100 @@ -46,16 +46,55 @@ return 0; } -static int -match(const struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - const void *matchinfo, - int offset, - int *hotdrop) +/* Returns 1 if the port is matched by the test, 0 otherwise. */ +static inline int +ports_match_v1(const struct ipt_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 == IPT_MULTIPORT_SOURCE + && src >= s && src <= e) + return 1; + if (minfo->flags == IPT_MULTIPORT_DESTINATION + && dst >= s && dst <= e) + return 1; + if (minfo->flags == IPT_MULTIPORT_EITHER + && dst >= s && dst <= e) + return 1; + } else { + /* exact port matching */ + duprintf("src or dst matches with %d?\n", s); + if (minfo->flags == IPT_MULTIPORT_SOURCE + && src == s) + return 1; + if (minfo->flags == IPT_MULTIPORT_DESTINATION + && dst == s) + return 1; + if (minfo->flags == IPT_MULTIPORT_EITHER + && (src == s || dst == s)) + return 1; + } + } + + return 0; +} + +static u16 * +__match(const struct sk_buff *skb, + const void *matchinfo, + int offset) { u16 _ports[2], *pptr; - const struct ipt_multiport *multiinfo = matchinfo; /* Must not be a fragment. */ if (offset) @@ -65,6 +104,21 @@ them at the start). */ pptr = skb_header_pointer(skb, skb->nh.iph->ihl * 4, sizeof(_ports), &_ports[0]); + return pptr; +} + +static int +match(const struct sk_buff *skb, + const struct net_device *in, + const struct net_device *out, + const void *matchinfo, + int offset, + int *hotdrop) +{ + u16 *pptr; + const struct ipt_multiport *multiinfo = matchinfo; + + pptr = __match(skb, matchinfo, offset); if (pptr == NULL) { /* We've been asked to examine this packet, and we * can't. Hence, no choice but to drop. @@ -80,6 +134,31 @@ 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 void *matchinfo, + int offset, + int *hotdrop) +{ + u16 *pptr; + const struct ipt_multiport_v1 *multiinfo = matchinfo; + + pptr = __match(skb, matchinfo, offset); + 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])); +} + /* Called when user tries to insert an entry of this type. */ static int checkentry(const char *tablename, @@ -91,21 +170,50 @@ return (matchsize == IPT_ALIGN(sizeof(struct ipt_multiport))); } +static int +checkentry_v1(const char *tablename, + const struct ipt_ip *ip, + void *matchinfo, + unsigned int matchsize, + unsigned int hook_mask) +{ + return (matchsize == IPT_ALIGN(sizeof(struct ipt_multiport_v1))); +} + static struct ipt_match multiport_match = { .name = "multiport", + .revision = 0, .match = &match, .checkentry = &checkentry, .me = THIS_MODULE, }; +static struct ipt_match multiport_match_v1 = { + .name = "multiport", + .revision = 1, + .match = &match_v1, + .checkentry = &checkentry_v1, + .me = THIS_MODULE, +}; + static int __init init(void) { - return ipt_register_match(&multiport_match); + 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 fini(void) { ipt_unregister_match(&multiport_match); + ipt_unregister_match(&multiport_match_v1); } module_init(init); --- linux-2.5/include/linux/netfilter_ipv4/ipt_multiport.h 2005-01-01 19:03:21.000000000 +0100 +++ revision/include/linux/netfilter_ipv4/ipt_multiport.h 2005-01-01 19:03:13.000000000 +0100 @@ -18,4 +18,12 @@ 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 */ +}; #endif /*_IPT_MULTIPORT_H*/