]> git.ipfire.org Git - thirdparty/iptables.git/commitdiff
Alignment fixes (requires kernel patch).
authorRusty Russell <rusty@linuxcare.com.au>
Thu, 27 Apr 2000 10:28:06 +0000 (10:28 +0000)
committerRusty Russell <rusty@rustcorp.com.au>
Thu, 27 Apr 2000 10:28:06 +0000 (10:28 +0000)
extensions/libipt_DNAT.c
extensions/libipt_SNAT.c
include/libiptc/libiptc.h
iptables.c
libiptc/libiptc.c

index 6251cf1c210c613ca62969b11256edef8e6f412a..af08cc0a7cb9d98883071301950d51ba86e0fe4c 100644 (file)
@@ -53,7 +53,7 @@ append_range(struct ipt_natinfo *info, const struct ip_nat_range *range)
        if (!info)
                exit_error(OTHER_PROBLEM, "Out of memory\n");
 
-       info->t.target_size = size;
+       info->t.u.target_size = size;
        info->mr.range[info->mr.rangesize] = *range;
        info->mr.rangesize++;
 
index f769cd4e7470c08cc6b0f4cadda8ed9105801b86..e1d275234e738cddde2fbd957c34be6dd7e148f2 100644 (file)
@@ -53,7 +53,7 @@ append_range(struct ipt_natinfo *info, const struct ip_nat_range *range)
        if (!info)
                exit_error(OTHER_PROBLEM, "Out of memory\n");
 
-       info->t.target_size = size;
+       info->t.u.target_size = size;
        info->mr.range[info->mr.rangesize] = *range;
        info->mr.rangesize++;
 
index 9058cffc139d4e16283e2c079c04377b14aa8d55..fa0a4eaf2d5b22a7d170ebd05b59166f784ace22 100644 (file)
@@ -6,9 +6,13 @@
 #include <linux/netfilter_ipv4/ip_tables.h>
 
 #ifndef IPT_MIN_ALIGN
-#define IPT_MIN_ALIGN (__alignof__(struct ipt_entry_match))
+/* ipt_entry has pointers and u_int64_t's in it, so if you align to
+   it, you'll also align to any crazy matches and targets someone
+   might write */
+#define IPT_MIN_ALIGN (__alignof__(struct ipt_entry))
 #endif
-#define IPT_ALIGN(s) (((s) + (IPT_MIN_ALIGN-1)) & ~(IPT_MIN_ALIGN-1))
+
+#define IPT_ALIGN(s) (((s) + ((IPT_MIN_ALIGN)-1)) & ~((IPT_MIN_ALIGN)-1))
 
 typedef char ipt_chainlabel[32];
 
index c4846fd9d6fc043e3393f973b321652d68da3bbd..eab710e88895878fe922d8218c552d4236806a2c 100644 (file)
@@ -1014,14 +1014,14 @@ print_match(const struct ipt_entry_match *m,
            const struct ipt_ip *ip,
            int numeric)
 {
-       struct iptables_match *match = find_match(m->u.name, 1);
+       struct iptables_match *match = find_match(m->u.user.name, 1);
 
        if (match) {
                if (match->print)
                        match->print(ip, m, numeric);
        } else {
-               if (m->u.name[0])
-                       printf("UNKNOWN match `%s' ", m->u.name);
+               if (m->u.user.name[0])
+                       printf("UNKNOWN match `%s' ", m->u.user.name);
        }
        /* Don't stop iterating. */
        return 0;
@@ -1150,9 +1150,9 @@ print_firewall(const struct ipt_entry *fw,
                if (target->print)
                        /* Print the target information. */
                        target->print(&fw->ip, t, format & FMT_NUMERIC);
-       } else if (t->target_size != sizeof(*t))
+       } else if (t->u.target_size != sizeof(*t))
                printf("[%u bytes of unknown target data] ",
-                      t->target_size - sizeof(*t));
+                      t->u.target_size - sizeof(*t));
 
        if (!(format & FMT_NONEWLINE))
                fputc('\n', stdout);
@@ -1165,7 +1165,7 @@ print_firewall_line(const struct ipt_entry *fw,
        struct ipt_entry_target *t;
 
        t = ipt_get_target((struct ipt_entry *)fw);
-       print_firewall(fw, t->u.name, 0, FMT_PRINT_RULE, h);
+       print_firewall(fw, t->u.user.name, 0, FMT_PRINT_RULE, h);
 }
 
 static int
@@ -1462,19 +1462,19 @@ generate_entry(const struct ipt_entry *fw,
 
        size = sizeof(struct ipt_entry);
        for (m = matches; m; m = m->next)
-               size += m->m->match_size;
+               size += m->m->u.match_size;
 
-       e = fw_malloc(size + target->target_size);
+       e = fw_malloc(size + target->u.target_size);
        *e = *fw;
        e->target_offset = size;
-       e->next_offset = size + target->target_size;
+       e->next_offset = size + target->u.target_size;
 
        size = 0;
        for (m = matches; m; m = m->next) {
-               memcpy(e->elems + size, m->m, m->m->match_size);
-               size += m->m->match_size;
+               memcpy(e->elems + size, m->m, m->m->u.match_size);
+               size += m->m->u.match_size;
        }
-       memcpy(e->elems + size, target, target->target_size);
+       memcpy(e->elems + size, target, target->u.target_size);
 
        return e;
 }
@@ -1678,12 +1678,14 @@ int do_command(int argc, char *argv[], char **table, iptc_handle_t *handle)
                        target = find_target(jumpto, 1);
 
                        if (target) {
-                               size_t size = sizeof(struct ipt_entry_target)
-                                       + IPT_ALIGN(target->size);
+                               size_t size;
+
+                               size = IPT_ALIGN(sizeof(struct ipt_entry_target)
+                                                + target->size);
 
                                target->t = fw_calloc(1, size);
-                               target->t->target_size = size;
-                               strcpy(target->t->u.name, jumpto);
+                               target->t->u.target_size = size;
+                               strcpy(target->t->u.user.name, jumpto);
                                target->init(target->t, &fw.nfcache);
                        }
                        break;
@@ -1735,11 +1737,13 @@ int do_command(int argc, char *argv[], char **table, iptc_handle_t *handle)
                                exit_error(PARAMETER_PROBLEM,
                                           "Couldn't load match `%s'", optarg);
                        else {
-                               size_t size = sizeof(struct ipt_entry_match)
-                                       + IPT_ALIGN(m->size);
+                               size_t size;
+
+                               size = IPT_ALIGN(sizeof(struct ipt_entry_match)
+                                                + m->size);
                                m->m = fw_calloc(1, size);
-                               m->m->match_size = size;
-                               strcpy(m->m->u.name, optarg);
+                               m->m->u.match_size = size;
+                               strcpy(m->m->u.user.name, optarg);
                                m->init(m->m, &fw.nfcache);
                        }
                        break;
@@ -1812,12 +1816,14 @@ int do_command(int argc, char *argv[], char **table, iptc_handle_t *handle)
                                    && !find_match(protocol, 0)
                                    && (m = find_match(protocol, 1))) {
                                        /* Try loading protocol */
-                                       size_t size = sizeof(struct ipt_entry_match)
-                                               + IPT_ALIGN(m->size);
+                                       size_t size;
+
+                                       size = IPT_ALIGN(sizeof(struct ipt_entry_match)
+                                                        + m->size);
 
                                        m->m = fw_calloc(1, size);
-                                       m->m->match_size = size;
-                                       strcpy(m->m->u.name, protocol);
+                                       m->m->u.match_size = size;
+                                       strcpy(m->m->u.user.name, protocol);
                                        m->init(m->m, &fw.nfcache);
 
                                        optind--;
@@ -1935,10 +1941,10 @@ int do_command(int argc, char *argv[], char **table, iptc_handle_t *handle)
                                           "Can't find standard target\n");
 
                        size = sizeof(struct ipt_entry_target)
-                               + IPT_ALIGN(target->size);
+                               + target->size;
                        target->t = fw_calloc(1, size);
-                       target->t->target_size = size;
-                       strcpy(target->t->u.name, jumpto);
+                       target->t->u.target_size = size;
+                       strcpy(target->t->u.user.name, jumpto);
                        target->init(target->t, &fw.nfcache);
                }
 
@@ -1947,8 +1953,8 @@ int do_command(int argc, char *argv[], char **table, iptc_handle_t *handle)
 
                        /* Don't know it.  Must be extension with no
                            options? */
-                       unknown_target.target_size = sizeof(unknown_target);
-                       strcpy(unknown_target.u.name, jumpto);
+                       unknown_target.u.target_size = sizeof(unknown_target);
+                       strcpy(unknown_target.u.user.name, jumpto);
 
                        e = generate_entry(&fw, iptables_matches,
                                           &unknown_target);
index fee3a042f74518e1ebd987829847e806049120ec..019de66f19fc42f3ef8118590d9d8d40db634324 100644 (file)
@@ -199,7 +199,7 @@ get_errorlabel(iptc_handle_t h, unsigned int offset)
        struct ipt_entry *e;
 
        e = get_entry(h, offset);
-       if (strcmp(ipt_get_target(e)->u.name, IPT_ERROR_TARGET) != 0) {
+       if (strcmp(ipt_get_target(e)->u.user.name, IPT_ERROR_TARGET) != 0) {
                fprintf(stderr, "ERROR: offset %u not an error node!\n",
                        offset);
                abort();
@@ -313,7 +313,7 @@ iptc_init(const char *tablename)
 static inline int
 print_match(const struct ipt_entry_match *m)
 {
-       printf("Match name: `%s'\n", m->u.name);
+       printf("Match name: `%s'\n", m->u.user.name);
        return 0;
 }
 
@@ -359,8 +359,8 @@ dump_entry(struct ipt_entry *e, const iptc_handle_t handle)
        IPT_MATCH_ITERATE(e, print_match);
 
        t = ipt_get_target(e);
-       printf("Target name: `%s' [%u]\n", t->u.name, t->target_size);
-       if (strcmp(t->u.name, IPT_STANDARD_TARGET) == 0) {
+       printf("Target name: `%s' [%u]\n", t->u.user.name, t->u.target_size);
+       if (strcmp(t->u.user.name, IPT_STANDARD_TARGET) == 0) {
                int pos = *(int *)t->data;
                if (pos < 0)
                        printf("verdict=%s\n",
@@ -371,7 +371,7 @@ dump_entry(struct ipt_entry *e, const iptc_handle_t handle)
                               : "UNKNOWN");
                else
                        printf("verdict=%u\n", pos);
-       } else if (strcmp(t->u.name, IPT_ERROR_TARGET) == 0)
+       } else if (strcmp(t->u.user.name, IPT_ERROR_TARGET) == 0)
                printf("error=`%s'\n", t->data);
 
        printf("\n");
@@ -432,7 +432,7 @@ add_chain(struct ipt_entry *e, iptc_handle_t h, struct ipt_entry **prev)
 
        /* We know this is the start of a new chain if it's an ERROR
           target, or a hook entry point */
-       if (strcmp(ipt_get_target(e)->u.name, IPT_ERROR_TARGET) == 0) {
+       if (strcmp(ipt_get_target(e)->u.user.name, IPT_ERROR_TARGET) == 0) {
                /* prev was last entry in previous chain */
                h->cache_chain_heads[h->cache_num_chains-1].end
                        = *prev;
@@ -551,7 +551,7 @@ get_chain_end(const iptc_handle_t handle, unsigned int start)
 
                /* We hit a user chain label */
                t = ipt_get_target(e);
-               if (strcmp(t->u.name, IPT_ERROR_TARGET) == 0)
+               if (strcmp(t->u.user.name, IPT_ERROR_TARGET) == 0)
                        return last_off;
        }
        /* SHOULD NEVER HAPPEN */
@@ -667,8 +667,8 @@ target_name(iptc_handle_t handle, const struct ipt_entry *ce)
        /* To avoid const warnings */
        struct ipt_entry *e = (struct ipt_entry *)ce;
 
-       if (strcmp(ipt_get_target(e)->u.name, IPT_STANDARD_TARGET) != 0)
-               return ipt_get_target(e)->u.name;
+       if (strcmp(ipt_get_target(e)->u.user.name, IPT_STANDARD_TARGET) != 0)
+               return ipt_get_target(e)->u.user.name;
 
        /* Standard target: evaluate */
        spos = *(int *)ipt_get_target(e)->data;
@@ -753,7 +753,7 @@ correct_verdict(struct ipt_entry *e,
 
        /* Trap: insert of fall-through rule.  Don't change fall-through
           verdict to jump-over-next-rule. */
-       if (strcmp(t->target.u.name, IPT_STANDARD_TARGET) == 0
+       if (strcmp(t->target.u.user.name, IPT_STANDARD_TARGET) == 0
            && t->verdict > (int)offset
            && !(curr == offset &&
                 t->verdict == curr + e->next_offset)) {
@@ -914,13 +914,13 @@ standard_map(struct ipt_entry *e, int verdict)
 
        t = (struct ipt_standard_target *)ipt_get_target(e);
 
-       if (t->target.target_size != IPT_ALIGN(sizeof(struct ipt_standard_target))) {
+       if (t->target.u.target_size != sizeof(struct ipt_standard_target)) {
                errno = EINVAL;
                return 0;
        }
        /* memset for memcmp convenience on delete/replace */
-       memset(t->target.u.name, 0, IPT_FUNCTION_MAXNAMELEN);
-       strcpy(t->target.u.name, IPT_STANDARD_TARGET);
+       memset(t->target.u.user.name, 0, IPT_FUNCTION_MAXNAMELEN);
+       strcpy(t->target.u.user.name, IPT_STANDARD_TARGET);
        t->verdict = verdict;
 
        return 1;
@@ -939,18 +939,18 @@ map_target(const iptc_handle_t handle,
        *old = *t;
 
        /* Maybe it's empty (=> fall through) */
-       if (strcmp(t->u.name, "") == 0)
+       if (strcmp(t->u.user.name, "") == 0)
                return standard_map(e, offset + e->next_offset);
        /* Maybe it's a standard target name... */
-       else if (strcmp(t->u.name, IPTC_LABEL_ACCEPT) == 0)
+       else if (strcmp(t->u.user.name, IPTC_LABEL_ACCEPT) == 0)
                return standard_map(e, -NF_ACCEPT - 1);
-       else if (strcmp(t->u.name, IPTC_LABEL_DROP) == 0)
+       else if (strcmp(t->u.user.name, IPTC_LABEL_DROP) == 0)
                return standard_map(e, -NF_DROP - 1);
-       else if (strcmp(t->u.name, IPTC_LABEL_QUEUE) == 0)
+       else if (strcmp(t->u.user.name, IPTC_LABEL_QUEUE) == 0)
                return standard_map(e, -NF_QUEUE - 1);
-       else if (strcmp(t->u.name, IPTC_LABEL_RETURN) == 0)
+       else if (strcmp(t->u.user.name, IPTC_LABEL_RETURN) == 0)
                return standard_map(e, IPT_RETURN);
-       else if (iptc_builtin(t->u.name, handle)) {
+       else if (iptc_builtin(t->u.user.name, handle)) {
                /* Can't jump to builtins. */
                errno = EINVAL;
                return 0;
@@ -958,16 +958,16 @@ map_target(const iptc_handle_t handle,
                /* Maybe it's an existing chain name. */
                struct chain_cache *c;
 
-               c = find_label(t->u.name, handle);
+               c = find_label(t->u.user.name, handle);
                if (c)
                        return standard_map(e, entry2offset(handle, c->start));
        }
 
        /* Must be a module?  If not, kernel will reject... */
        /* memset to all 0 for your memcmp convenience. */
-       memset(t->u.name + strlen(t->u.name),
+       memset(t->u.user.name + strlen(t->u.user.name),
               0,
-              IPT_FUNCTION_MAXNAMELEN - strlen(t->u.name));
+              IPT_FUNCTION_MAXNAMELEN - strlen(t->u.user.name));
        return 1;
 }
 
@@ -1100,15 +1100,15 @@ match_different(const struct ipt_entry_match *a,
        /* Offset of b is the same as a. */
        b = (void *)b_elems + ((unsigned char *)a - a_elems);
 
-       if (a->match_size != b->match_size)
+       if (a->u.match_size != b->u.match_size)
                return 1;
 
-       if (strcmp(a->u.name, b->u.name) != 0)
+       if (strcmp(a->u.user.name, b->u.user.name) != 0)
                return 1;
 
        *maskptr += sizeof(*a);
 
-       for (i = 0; i < a->match_size - sizeof(*a); i++)
+       for (i = 0; i < a->u.match_size - sizeof(*a); i++)
                if (((a->data[i] ^ b->data[i]) & (*maskptr)[i]) != 0)
                        return 1;
        *maskptr += i;
@@ -1171,14 +1171,14 @@ is_same(const struct ipt_entry *a, const struct ipt_entry *b,
 
        ta = ipt_get_target((struct ipt_entry *)a);
        tb = ipt_get_target((struct ipt_entry *)b);
-       if (ta->target_size != tb->target_size)
+       if (ta->u.target_size != tb->u.target_size)
                return 0;
-       if (strcmp(ta->u.name, tb->u.name) != 0)
+       if (strcmp(ta->u.user.name, tb->u.user.name) != 0)
                return 0;
 
        mptr += sizeof(*ta);
        if (target_different(ta->data, tb->data,
-                            ta->target_size - sizeof(*ta), mptr))
+                            ta->u.target_size - sizeof(*ta), mptr))
                return 0;
 
        return 1;
@@ -1369,15 +1369,15 @@ iptc_create_chain(const ipt_chainlabel chain, iptc_handle_t *handle)
        newc.head.target_offset = sizeof(struct ipt_entry);
        newc.head.next_offset
                = sizeof(struct ipt_entry) + sizeof(struct ipt_error_target);
-       strcpy(newc.name.t.u.name, IPT_ERROR_TARGET);
-       newc.name.t.target_size = sizeof(struct ipt_error_target);
+       strcpy(newc.name.t.u.user.name, IPT_ERROR_TARGET);
+       newc.name.t.u.target_size = sizeof(struct ipt_error_target);
        strcpy(newc.name.error, chain);
 
        newc.ret.target_offset = sizeof(struct ipt_entry);
        newc.ret.next_offset
                = sizeof(struct ipt_entry)+sizeof(struct ipt_standard_target);
-       strcpy(newc.target.target.u.name, IPT_STANDARD_TARGET);
-       newc.target.target.target_size = sizeof(struct ipt_standard_target);
+       strcpy(newc.target.target.u.user.name, IPT_STANDARD_TARGET);
+       newc.target.target.u.target_size = sizeof(struct ipt_standard_target);
        newc.target.verdict = IPT_RETURN;
 
        /* Add just before terminal entry */
@@ -1393,7 +1393,7 @@ count_ref(struct ipt_entry *e, unsigned int offset, unsigned int *ref)
 {
        struct ipt_standard_target *t;
 
-       if (strcmp(ipt_get_target(e)->u.name, IPT_STANDARD_TARGET) == 0) {
+       if (strcmp(ipt_get_target(e)->u.user.name, IPT_STANDARD_TARGET) == 0) {
                t = (struct ipt_standard_target *)ipt_get_target(e);
 
                if (t->verdict == offset)
@@ -1765,9 +1765,10 @@ unconditional(const struct ipt_ip *ip)
 static inline int
 check_match(const struct ipt_entry_match *m, unsigned int *off)
 {
-       assert(m->match_size >= sizeof(struct ipt_entry_match));
+       assert(m->u.match_size >= sizeof(struct ipt_entry_match));
+       assert(IPT_ALIGN(m->u.match_size) == m->u.match_size);
 
-       (*off) += m->match_size;
+       (*off) += m->u.match_size;
        return 0;
 }
 
@@ -1789,11 +1790,14 @@ check_entry(const struct ipt_entry *e, unsigned int *i, unsigned int *off,
 
        t = (struct ipt_standard_target *)
                ipt_get_target((struct ipt_entry *)e);
-       assert(t->target.target_size == e->next_offset - e->target_offset);
-       assert(!iptc_is_chain(t->target.u.name, h));
-
-       if (strcmp(t->target.u.name, IPT_STANDARD_TARGET) == 0) {
-               assert(t->target.target_size
+       /* next_offset will have to be multiple of entry alignment. */
+       assert(e->next_offset == IPT_ALIGN(e->next_offset));
+       assert(e->target_offset == IPT_ALIGN(e->target_offset));
+       assert(t->target.u.target_size == IPT_ALIGN(t->target.u.target_size));
+       assert(!iptc_is_chain(t->target.u.user.name, h));
+
+       if (strcmp(t->target.u.user.name, IPT_STANDARD_TARGET) == 0) {
+               assert(t->target.u.target_size
                       == IPT_ALIGN(sizeof(struct ipt_standard_target)));
 
                assert(t->verdict == -NF_DROP-1
@@ -1806,7 +1810,7 @@ check_entry(const struct ipt_entry *e, unsigned int *i, unsigned int *off,
                        int idx;
 
                        idx = entry2index(h, te);
-                       assert(strcmp(ipt_get_target(te)->u.name,
+                       assert(strcmp(ipt_get_target(te)->u.user.name,
                                      IPT_ERROR_TARGET)
                               != 0);
                        assert(te != e);
@@ -1814,7 +1818,7 @@ check_entry(const struct ipt_entry *e, unsigned int *i, unsigned int *off,
                        /* Prior node must be error node, or this node. */
                        assert(t->verdict == entry2offset(h, e)+e->next_offset
                               || strcmp(ipt_get_target(index2entry(h, idx-1))
-                                        ->u.name, IPT_ERROR_TARGET)
+                                        ->u.user.name, IPT_ERROR_TARGET)
                               == 0);
                }
 
@@ -1824,8 +1828,8 @@ check_entry(const struct ipt_entry *e, unsigned int *i, unsigned int *off,
                        *was_return = 1;
                else
                        *was_return = 0;
-       } else if (strcmp(t->target.u.name, IPT_ERROR_TARGET) == 0) {
-               assert(t->target.target_size
+       } else if (strcmp(t->target.u.user.name, IPT_ERROR_TARGET) == 0) {
+               assert(t->target.u.target_size
                       == IPT_ALIGN(sizeof(struct ipt_error_target)));
 
                /* If this is in user area, previous must have been return */
@@ -1837,7 +1841,7 @@ check_entry(const struct ipt_entry *e, unsigned int *i, unsigned int *off,
        else *was_return = 0;
 
        if (*off == user_offset)
-               assert(strcmp(t->target.u.name, IPT_ERROR_TARGET) == 0);
+               assert(strcmp(t->target.u.user.name, IPT_ERROR_TARGET) == 0);
 
        (*off) += e->next_offset;
        (*i)++;
@@ -1926,7 +1930,7 @@ do_check(iptc_handle_t h, unsigned int line)
                assert(e->next_offset == sizeof(*e) + sizeof(*t));
                t = (struct ipt_standard_target *)ipt_get_target(e);
 
-               assert(strcmp(t->target.u.name, IPT_STANDARD_TARGET) == 0);
+               assert(strcmp(t->target.u.user.name, IPT_STANDARD_TARGET)==0);
                assert(t->verdict == -NF_DROP-1 || t->verdict == -NF_ACCEPT-1);
 
                /* Hooks and underflows must be valid entries */
@@ -1954,7 +1958,8 @@ do_check(iptc_handle_t h, unsigned int line)
        assert(n == h->entries.size);
 
        /* Final entry must be error node */
-       assert(strcmp(ipt_get_target(index2entry(h, h->new_number-1))->u.name,
+       assert(strcmp(ipt_get_target(index2entry(h, h->new_number-1))
+                     ->u.user.name,
                      IPT_ERROR_TARGET) == 0);
 }
 #endif /*NDEBUG*/