]> git.ipfire.org Git - thirdparty/iptables.git/commitdiff
Changes to allow matching (for delete) on part of a rule, for rules which
authorRusty Russell <rusty@linuxcare.com.au>
Wed, 19 Apr 2000 11:26:44 +0000 (11:26 +0000)
committerRusty Russell <rusty@rustcorp.com.au>
Wed, 19 Apr 2000 11:26:44 +0000 (11:26 +0000)
change in the kernel (eg. ipt_limit).

21 files changed:
extensions/libipt_DNAT.c
extensions/libipt_LOG.c
extensions/libipt_MARK.c
extensions/libipt_REJECT.c
extensions/libipt_SNAT.c
extensions/libipt_TOS.c
extensions/libipt_icmp.c
extensions/libipt_limit.c
extensions/libipt_mac.c
extensions/libipt_mark.c
extensions/libipt_multiport.c
extensions/libipt_owner.c
extensions/libipt_standard.c
extensions/libipt_state.c
extensions/libipt_tcp.c
extensions/libipt_tos.c
extensions/libipt_udp.c
extensions/libipt_unclean.c
include/iptables.h
include/libiptc/libiptc.h
libiptc/libiptc.c

index e3c37222159d174798f5592c29a02bae0c5d103d..6251cf1c210c613ca62969b11256edef8e6f412a 100644 (file)
@@ -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,
index ce4adb230eb13a9c15263a94bfb420cf09befbb0..d634cd5532a5d3bfdb2782ff465c5dee2768c8b1 100644 (file)
@@ -245,6 +245,7 @@ struct iptables_target log
     "LOG",
     NETFILTER_VERSION,
     sizeof(struct ipt_log_info),
+    sizeof(struct ipt_log_info),
     &help,
     &init,
     &parse,
index a7cb60c09ed4a13cba9d4f13f72dd74c7a4f9193..b8afe5504b64c666cade438255216d73c435ce08 100644 (file)
@@ -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,
index 3f5c128a3eeae2eed43d3b853800235cc3623c1d..2c0b85b75b027fc73018010fdd33c84857252947 100644 (file)
@@ -142,6 +142,7 @@ struct iptables_target reject
     "REJECT",
     NETFILTER_VERSION,
     sizeof(struct ipt_reject_info),
+    sizeof(struct ipt_reject_info),
     &help,
     &init,
     &parse,
index 86ba39b9fb8d1953b0e45970095b4443390132ee..f769cd4e7470c08cc6b0f4cadda8ed9105801b86 100644 (file)
@@ -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,
index f01fc26487e15bbd98c84016ca0c5faf86f499b1..ed599005b923bb28c147f66c10d77079cfa057e6 100644 (file)
@@ -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,
index 65857ce3eeec6f01ad52772a4dfcef34640da432..0a47e4121f63fd10b22340b244b0f68db01d7245 100644 (file)
@@ -280,6 +280,7 @@ struct iptables_match icmp
     "icmp",
     NETFILTER_VERSION,
     sizeof(struct ipt_icmp),
+    sizeof(struct ipt_icmp),
     &help,
     &init,
     &parse,
index b6cc74f258e5d014b0eec2492440b3f9f38d8f67..822109bfabb26f5e3582432df39441425bda9dd3 100644 (file)
@@ -181,6 +181,7 @@ struct iptables_match limit
     "limit",
     NETFILTER_VERSION,
     sizeof(struct ipt_rateinfo),
+    offsetof(struct ipt_rateinfo, prev),
     &help,
     &init,
     &parse,
index 36d896927b78a09712f4d2f95021a96ebba19c34..f740ecc5097c09d598734a5d20f55ad3e41de872 100644 (file)
@@ -129,6 +129,7 @@ struct iptables_match mac
     "mac",
     NETFILTER_VERSION,
     sizeof(struct ipt_mac_info),
+    sizeof(struct ipt_mac_info),
     &help,
     &init,
     &parse,
index dcf54488edd5099c63c6d8dbf75574ef2995d8c9..2cd6193b9a7667e8a28735cd7a5ea7b81f2bab8f 100644 (file)
@@ -113,6 +113,7 @@ struct iptables_match mark
     "mark",
     NETFILTER_VERSION,
     sizeof(struct ipt_mark_info),
+    sizeof(struct ipt_mark_info),
     &help,
     &init,
     &parse,
index 727f95fc7ca923b165b3f15b9eb29de1e2c286f1..8c58bddddf4e239923e32a46a50a7706d3f30e80 100644 (file)
@@ -246,6 +246,7 @@ struct iptables_match multiport
     "multiport",
     NETFILTER_VERSION,
     sizeof(struct ipt_multiport),
+    sizeof(struct ipt_multiport),
     &help,
     &init,
     &parse,
index 29311022b4982a8b28c963e126635f15d196907a..027f5383dfd196460b58560310da4e71f04a700c 100644 (file)
@@ -204,6 +204,7 @@ struct iptables_match owner
     "owner",
     NETFILTER_VERSION,
     sizeof(struct ipt_owner_info),
+    sizeof(struct ipt_owner_info),
     &help,
     &init,
     &parse,
index 9a746b2dbd3b83156dbf6ffd5861a71cf0e538a4..c63669f03536f4c19c9b8d5d2979bb33bbe89a7f 100644 (file)
@@ -52,6 +52,7 @@ struct iptables_target standard
     "standard",
     NETFILTER_VERSION,
     sizeof(int),
+    sizeof(int),
     &help,
     &init,
     &parse,
index 19751d72fb0ba58fa4e4b787ad9698a5843e3f8c..d3dcbc2d837246c2345568cb13ef1c83868dd0d4 100644 (file)
@@ -147,6 +147,7 @@ struct iptables_match state
     "state",
     NETFILTER_VERSION,
     sizeof(struct ipt_state_info),
+    sizeof(struct ipt_state_info),
     &help,
     &init,
     &parse,
index 2febc28cc14551d331bdec5c7b6b39541c762072..276d0e2a39ebf5e5030b72f04743cf47c9fa03bb 100644 (file)
@@ -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,
index 6d2d77247e9767c00894feb15da5992e59bd2458..99c89ea778369a4147f46c2bdbf458255804d988 100644 (file)
@@ -156,6 +156,7 @@ struct iptables_match tos
     "tos",
     NETFILTER_VERSION,
     sizeof(struct ipt_tos_info),
+    sizeof(struct ipt_tos_info),
     &help,
     &init,
     &parse,
index 603a4860b68dbd2dcc183378fea1a4853f971c40..507937b190e16e851c65a76224f9ef9df043a16d 100644 (file)
@@ -236,6 +236,7 @@ struct iptables_match udp
     "udp",
     NETFILTER_VERSION,
     sizeof(struct ipt_udp),
+    sizeof(struct ipt_udp),
     &help,
     &init,
     &parse,
index 50f62bdc7ae26cbf71bb37c881f4e12cd5f34244..bef513e6835333d150b57dc33805df1942c2a3b1 100644 (file)
@@ -51,6 +51,7 @@ struct iptables_match unclean
     "unclean",
     NETFILTER_VERSION,
     0,
+    0,
     &help,
     &init,
     &parse,
index 9b1a4a167659f4c433cfd6216430bb50485649e3..1ddd8712437f18b6aaa2e9455624cacd98e20668 100644 (file)
@@ -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);
 
index 4a964e034c477fb0b56b5da8578a092cae42bf3e..0a491071661865fb3ffea3993711957bc1d323a1 100644 (file)
@@ -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'. */
index de819f2b03a66b2a350cef753bc81858a749e639..a90d46ea620e7da81b41087ac382ff339031ad20 100644 (file)
 #include <errno.h>
 #include <stdlib.h>
 #include <stdio.h>
-#include <linux/netfilter_ipv4/ipt_limit.h>
+#include <limits.h>
 
 #if !defined(__GLIBC__) || (__GLIBC__ < 2)
 typedef unsigned int socklen_t;
 #endif
 
 #include <libiptc/libiptc.h>
+#include <linux/netfilter_ipv4/ipt_limit.h>
 
 #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),