From fcbb2f45e58e4f2f22c2175c13fcc6025835a8f6 Mon Sep 17 00:00:00 2001 From: rusty Date: Wed, 19 Apr 2000 11:26:44 +0000 Subject: Changes to allow matching (for delete) on part of a rule, for rules which change in the kernel (eg. ipt_limit). --- extensions/libipt_DNAT.c | 1 + extensions/libipt_LOG.c | 1 + extensions/libipt_MARK.c | 1 + extensions/libipt_REJECT.c | 1 + extensions/libipt_SNAT.c | 1 + extensions/libipt_TOS.c | 1 + extensions/libipt_icmp.c | 1 + extensions/libipt_limit.c | 1 + extensions/libipt_mac.c | 1 + extensions/libipt_mark.c | 1 + extensions/libipt_multiport.c | 1 + extensions/libipt_owner.c | 1 + extensions/libipt_standard.c | 1 + extensions/libipt_state.c | 1 + extensions/libipt_tcp.c | 17 +++++++----- extensions/libipt_tos.c | 1 + extensions/libipt_udp.c | 1 + extensions/libipt_unclean.c | 1 + include/iptables.h | 6 +++++ include/libiptc/libiptc.h | 4 ++- libiptc/libiptc.c | 61 +++++++++++++++++++++++++++---------------- 21 files changed, 74 insertions(+), 31 deletions(-) diff --git a/extensions/libipt_DNAT.c b/extensions/libipt_DNAT.c index e3c3722..6251cf1 100644 --- a/extensions/libipt_DNAT.c +++ b/extensions/libipt_DNAT.c @@ -229,6 +229,7 @@ struct iptables_target dnat "DNAT", NETFILTER_VERSION, sizeof(struct ip_nat_multi_range), + sizeof(struct ip_nat_multi_range), &help, &init, &parse, diff --git a/extensions/libipt_LOG.c b/extensions/libipt_LOG.c index ce4adb2..d634cd5 100644 --- a/extensions/libipt_LOG.c +++ b/extensions/libipt_LOG.c @@ -245,6 +245,7 @@ struct iptables_target log "LOG", NETFILTER_VERSION, sizeof(struct ipt_log_info), + sizeof(struct ipt_log_info), &help, &init, &parse, diff --git a/extensions/libipt_MARK.c b/extensions/libipt_MARK.c index a7cb60c..b8afe55 100644 --- a/extensions/libipt_MARK.c +++ b/extensions/libipt_MARK.c @@ -105,6 +105,7 @@ struct iptables_target mark "MARK", NETFILTER_VERSION, sizeof(struct ipt_mark_target_info), + sizeof(struct ipt_mark_target_info), &help, &init, &parse, diff --git a/extensions/libipt_REJECT.c b/extensions/libipt_REJECT.c index 3f5c128..2c0b85b 100644 --- a/extensions/libipt_REJECT.c +++ b/extensions/libipt_REJECT.c @@ -142,6 +142,7 @@ struct iptables_target reject "REJECT", NETFILTER_VERSION, sizeof(struct ipt_reject_info), + sizeof(struct ipt_reject_info), &help, &init, &parse, diff --git a/extensions/libipt_SNAT.c b/extensions/libipt_SNAT.c index 86ba39b..f769cd4 100644 --- a/extensions/libipt_SNAT.c +++ b/extensions/libipt_SNAT.c @@ -229,6 +229,7 @@ struct iptables_target snat "SNAT", NETFILTER_VERSION, sizeof(struct ip_nat_multi_range), + sizeof(struct ip_nat_multi_range), &help, &init, &parse, diff --git a/extensions/libipt_TOS.c b/extensions/libipt_TOS.c index f01fc26..ed59900 100644 --- a/extensions/libipt_TOS.c +++ b/extensions/libipt_TOS.c @@ -158,6 +158,7 @@ struct iptables_target tos "TOS", NETFILTER_VERSION, sizeof(struct ipt_tos_target_info), + sizeof(struct ipt_tos_target_info), &help, &init, &parse, diff --git a/extensions/libipt_icmp.c b/extensions/libipt_icmp.c index 65857ce..0a47e41 100644 --- a/extensions/libipt_icmp.c +++ b/extensions/libipt_icmp.c @@ -280,6 +280,7 @@ struct iptables_match icmp "icmp", NETFILTER_VERSION, sizeof(struct ipt_icmp), + sizeof(struct ipt_icmp), &help, &init, &parse, diff --git a/extensions/libipt_limit.c b/extensions/libipt_limit.c index b6cc74f..822109b 100644 --- a/extensions/libipt_limit.c +++ b/extensions/libipt_limit.c @@ -181,6 +181,7 @@ struct iptables_match limit "limit", NETFILTER_VERSION, sizeof(struct ipt_rateinfo), + offsetof(struct ipt_rateinfo, prev), &help, &init, &parse, diff --git a/extensions/libipt_mac.c b/extensions/libipt_mac.c index 36d8969..f740ecc 100644 --- a/extensions/libipt_mac.c +++ b/extensions/libipt_mac.c @@ -129,6 +129,7 @@ struct iptables_match mac "mac", NETFILTER_VERSION, sizeof(struct ipt_mac_info), + sizeof(struct ipt_mac_info), &help, &init, &parse, diff --git a/extensions/libipt_mark.c b/extensions/libipt_mark.c index dcf5448..2cd6193 100644 --- a/extensions/libipt_mark.c +++ b/extensions/libipt_mark.c @@ -113,6 +113,7 @@ struct iptables_match mark "mark", NETFILTER_VERSION, sizeof(struct ipt_mark_info), + sizeof(struct ipt_mark_info), &help, &init, &parse, diff --git a/extensions/libipt_multiport.c b/extensions/libipt_multiport.c index 727f95f..8c58bdd 100644 --- a/extensions/libipt_multiport.c +++ b/extensions/libipt_multiport.c @@ -246,6 +246,7 @@ struct iptables_match multiport "multiport", NETFILTER_VERSION, sizeof(struct ipt_multiport), + sizeof(struct ipt_multiport), &help, &init, &parse, diff --git a/extensions/libipt_owner.c b/extensions/libipt_owner.c index 2931102..027f538 100644 --- a/extensions/libipt_owner.c +++ b/extensions/libipt_owner.c @@ -204,6 +204,7 @@ struct iptables_match owner "owner", NETFILTER_VERSION, sizeof(struct ipt_owner_info), + sizeof(struct ipt_owner_info), &help, &init, &parse, diff --git a/extensions/libipt_standard.c b/extensions/libipt_standard.c index 9a746b2..c63669f 100644 --- a/extensions/libipt_standard.c +++ b/extensions/libipt_standard.c @@ -52,6 +52,7 @@ struct iptables_target standard "standard", NETFILTER_VERSION, sizeof(int), + sizeof(int), &help, &init, &parse, diff --git a/extensions/libipt_state.c b/extensions/libipt_state.c index 19751d7..d3dcbc2 100644 --- a/extensions/libipt_state.c +++ b/extensions/libipt_state.c @@ -147,6 +147,7 @@ struct iptables_match state "state", NETFILTER_VERSION, sizeof(struct ipt_state_info), + sizeof(struct ipt_state_info), &help, &init, &parse, diff --git a/extensions/libipt_tcp.c b/extensions/libipt_tcp.c index 2febc28..276d0e2 100644 --- a/extensions/libipt_tcp.c +++ b/extensions/libipt_tcp.c @@ -308,21 +308,23 @@ print_option(u_int8_t option, int invert, int numeric) static void print_tcpf(u_int8_t flags) { - int sole_flag = 1; + int have_flag = 0; - do { + while (flags) { unsigned int i; - /* Terminates because last flag is 0 */ - for (i = 0; !(flags & tcp_flag_names[i].flag); i++); + for (i = 0; (flags & tcp_flag_names[i].flag) == 0; i++); - if (!sole_flag) + if (have_flag) printf(","); printf("%s", tcp_flag_names[i].name); - sole_flag = 0; + have_flag = 1; flags &= ~tcp_flag_names[i].flag; - } while (flags); + } + + if (!have_flag) + printf("NONE"); } static void @@ -424,6 +426,7 @@ struct iptables_match tcp "tcp", NETFILTER_VERSION, sizeof(struct ipt_tcp), + sizeof(struct ipt_tcp), &help, &init, &parse, diff --git a/extensions/libipt_tos.c b/extensions/libipt_tos.c index 6d2d772..99c89ea 100644 --- a/extensions/libipt_tos.c +++ b/extensions/libipt_tos.c @@ -156,6 +156,7 @@ struct iptables_match tos "tos", NETFILTER_VERSION, sizeof(struct ipt_tos_info), + sizeof(struct ipt_tos_info), &help, &init, &parse, diff --git a/extensions/libipt_udp.c b/extensions/libipt_udp.c index 603a486..507937b 100644 --- a/extensions/libipt_udp.c +++ b/extensions/libipt_udp.c @@ -236,6 +236,7 @@ struct iptables_match udp "udp", NETFILTER_VERSION, sizeof(struct ipt_udp), + sizeof(struct ipt_udp), &help, &init, &parse, diff --git a/extensions/libipt_unclean.c b/extensions/libipt_unclean.c index 50f62bd..bef513e 100644 --- a/extensions/libipt_unclean.c +++ b/extensions/libipt_unclean.c @@ -51,6 +51,7 @@ struct iptables_match unclean "unclean", NETFILTER_VERSION, 0, + 0, &help, &init, &parse, diff --git a/include/iptables.h b/include/iptables.h index 9b1a4a1..1ddd871 100644 --- a/include/iptables.h +++ b/include/iptables.h @@ -15,6 +15,9 @@ struct iptables_match /* Size of match data. */ size_t size; + /* Size of match data relevent for userspace comparison purposes */ + size_t userspacesize; + /* Function which prints out usage message. */ void (*help)(void); @@ -59,6 +62,9 @@ struct iptables_target /* Size of target data. */ size_t size; + /* Size of target data relevent for userspace comparison purposes */ + size_t userspacesize; + /* Function which prints out usage message. */ void (*help)(void); diff --git a/include/libiptc/libiptc.h b/include/libiptc/libiptc.h index 4a964e0..0a49107 100644 --- a/include/libiptc/libiptc.h +++ b/include/libiptc/libiptc.h @@ -73,9 +73,11 @@ int iptc_append_entry(const ipt_chainlabel chain, const struct ipt_entry *e, iptc_handle_t *handle); -/* Delete the first rule in `chain' which matches `e'. */ +/* Delete the first rule in `chain' which matches `e', subject to + matchmask (array of length == origfw) */ int iptc_delete_entry(const ipt_chainlabel chain, const struct ipt_entry *origfw, + unsigned char *matchmask, iptc_handle_t *handle); /* Delete the rule in position `rulenum' in `chain'. */ diff --git a/libiptc/libiptc.c b/libiptc/libiptc.c index de819f2..a90d46e 100644 --- a/libiptc/libiptc.c +++ b/libiptc/libiptc.c @@ -16,13 +16,14 @@ #include #include #include -#include +#include #if !defined(__GLIBC__) || (__GLIBC__ < 2) typedef unsigned int socklen_t; #endif #include +#include #define IP_VERSION 4 #define IP_OFFSET 0x1FFF @@ -1000,10 +1001,12 @@ iptc_append_entry(const ipt_chainlabel chain, static inline int match_different(const struct ipt_entry_match *a, - const char *a_elems, - const char *b_elems) + const unsigned char *a_elems, + const unsigned char *b_elems, + unsigned char **maskptr) { const struct ipt_entry_match *b; + unsigned int i; /* Offset of b is the same as a. */ b = (void *)b_elems + ((char *)a-a_elems); @@ -1014,28 +1017,38 @@ match_different(const struct ipt_entry_match *a, if (strcmp(a->u.name, b->u.name) != 0) return 1; - /* FIXME: This is really, really gross --RR */ - if (strcmp(a->u.name,"limit") == 0) { - /* Special case, the kernel writes in this data, so we - * need to make sure that we only check the parts - * that are user specified */ - if (((struct ipt_rateinfo *)a->data)->avg - != ((struct ipt_rateinfo *)b->data)->avg - || ((struct ipt_rateinfo *)a->data)->burst - != ((struct ipt_rateinfo *)b->data)->burst) + *maskptr += sizeof(*a); + + for (i = 0; i < a->match_size - sizeof(*a); i++) + if (((a->data[i] ^ b->data[i]) & (*maskptr)[i]) != 0) + return 1; + *maskptr += i; + return 0; +} + +static inline int +target_different(const unsigned char *a_targdata, + const unsigned char *b_targdata, + unsigned int tdatasize, + const unsigned char *mask) +{ + unsigned int i; + for (i = 0; i < tdatasize; i++) + if (((a_targdata[i] ^ b_targdata[i]) & mask[i]) != 0) return 1; - } else if (memcmp(a->data, b->data, a->match_size - sizeof(*a)) != 0) - return 1; return 0; } static inline int -is_same(const struct ipt_entry *a, const struct ipt_entry *b) +is_same(const struct ipt_entry *a, const struct ipt_entry *b, + unsigned char *matchmask) { unsigned int i; struct ipt_entry_target *ta, *tb; + unsigned char *mptr; + /* Always compare head structures: ignore mask here. */ if (a->ip.src.s_addr != b->ip.src.s_addr || a->ip.dst.s_addr != b->ip.dst.s_addr || a->ip.smsk.s_addr != b->ip.smsk.s_addr @@ -1063,7 +1076,8 @@ is_same(const struct ipt_entry *a, const struct ipt_entry *b) || a->next_offset != b->next_offset) return 0; - if (IPT_MATCH_ITERATE(a, match_different, a->elems, b->elems)) + mptr = matchmask + sizeof(struct ipt_entry); + if (IPT_MATCH_ITERATE(a, match_different, a->elems, b->elems, &mptr)) return 0; ta = ipt_get_target((struct ipt_entry *)a); @@ -1072,12 +1086,12 @@ is_same(const struct ipt_entry *a, const struct ipt_entry *b) return 0; if (strcmp(ta->u.name, tb->u.name) != 0) return 0; - - /* FIXME: If kernel modifies these, then we never match --RR */ - - if (memcmp(ta->data, tb->data, ta->target_size - sizeof(*ta)) != 0) - return 0; - + + mptr += sizeof(*ta) + if (target_different(ta->data, tb->data, + ta->target_size - sizeof(*ta), mptr)) + return 0; + return 1; } @@ -1085,6 +1099,7 @@ is_same(const struct ipt_entry *a, const struct ipt_entry *b) int iptc_delete_entry(const ipt_chainlabel chain, const struct ipt_entry *origfw, + unsigned char *matchmask, iptc_handle_t *handle) { unsigned int offset, lastoff; @@ -1120,7 +1135,7 @@ iptc_delete_entry(const ipt_chainlabel chain, printf("Deleting:\n"); dump_entry(newe); #endif - if (is_same(e, fw)) { + if (is_same(e, fw, matchmask)) { int ret; ret = delete_rules(1, e->next_offset, offset, entry2index(*handle, e), -- cgit v1.2.3