===== include/linux/netfilter_ipv4/ipt_multiport.h 1.1 vs edited ===== --- 1.1/include/linux/netfilter_ipv4/ipt_multiport.h Tue Feb 5 18:39:43 2002 +++ edited/include/linux/netfilter_ipv4/ipt_multiport.h Mon Sep 27 03:11:13 2004 @@ -4,18 +4,28 @@ enum ipt_multiport_flags { - IPT_MULTIPORT_SOURCE, - IPT_MULTIPORT_DESTINATION, - IPT_MULTIPORT_EITHER + IPT_MULTIPORT_SOURCE_BIT = 0, + IPT_MULTIPORT_SOURCE = (1 << IPT_MULTIPORT_SOURCE_BIT), + + IPT_MULTIPORT_DESTINATION_BIT = 1, + IPT_MULTIPORT_DESTINATION = (1 << IPT_MULTIPORT_DESTINATION_BIT), + + IPT_MULTIPORT_EITHER = IPT_MULTIPORT_SOURCE|IPT_MULTIPORT_DESTINATION, }; #define IPT_MULTI_PORTS 15 -/* Must fit inside union ipt_matchinfo: 16 bytes */ +/* Must fit inside union ipt_matchinfo: 32 bytes */ +/* every entry in ports[] except for the last one has one bit in pflags + * associated with it. If this bit is set, the port is the first port of + * a portrange, with the next entry being the last. + * End of list is marked with pflags bit set and port=65535. + * If 14 ports are used (last one does not have a pflag), the last port + * is repeated to fill the last entry in ports[] */ struct ipt_multiport { - u_int8_t flags; /* Type of comparison */ - u_int8_t count; /* Number of ports */ + u_int8_t flags:2; /* Type of comparison */ + u_int16_t pflags:14; /* Port flags */ u_int16_t ports[IPT_MULTI_PORTS]; /* Ports */ }; #endif /*_IPT_MULTIPORT_H*/ ===== net/ipv4/netfilter/ipt_multiport.c 1.8 vs edited ===== --- 1.8/net/ipv4/netfilter/ipt_multiport.c Thu Aug 19 02:14:53 2004 +++ edited/net/ipv4/netfilter/ipt_multiport.c Mon Sep 27 02:54:46 2004 @@ -29,17 +29,31 @@ /* 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) +ports_match(const struct ipt_multiport *minfo, u_int16_t src, u_int16_t dst) { unsigned int i; - for (i=0; ipflags; + for (i=0, m=1; iports[i] == 65535) + return 0; + + s = minfo->ports[i]; + + if (pflags & m) { + e = minfo->ports[++i]; + m <<= 1; + } else + e = s; + + if (minfo->flags & IPT_MULTIPORT_SOURCE + && src >= s && src <= e) return 1; - if (flags != IPT_MULTIPORT_SOURCE - && portlist[i] == dst) + if (minfo->flags & IPT_MULTIPORT_DESTINATION + && dst >= s && dst <= e) return 1; } @@ -69,15 +83,12 @@ /* 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"); + 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])); + return ports_match(multiinfo, ntohs(pptr[0]), ntohs(pptr[1])); } /* Called when user tries to insert an entry of this type. */ @@ -90,17 +101,13 @@ { const struct ipt_multiport *multiinfo = matchinfo; - if (matchsize != IPT_ALIGN(sizeof(struct ipt_multiport))) - return 0; - /* Must specify proto == TCP/UDP, no unknown flags or bad count */ return (ip->proto == IPPROTO_TCP || ip->proto == IPPROTO_UDP) && !(ip->invflags & IPT_INV_PROTO) && matchsize == IPT_ALIGN(sizeof(struct ipt_multiport)) && (multiinfo->flags == IPT_MULTIPORT_SOURCE || multiinfo->flags == IPT_MULTIPORT_DESTINATION - || multiinfo->flags == IPT_MULTIPORT_EITHER) - && multiinfo->count <= IPT_MULTI_PORTS; + || multiinfo->flags == IPT_MULTIPORT_EITHER); } static struct ipt_match multiport_match = {