diff options
Diffstat (limited to 'libiptc/libiptc.c')
-rw-r--r-- | libiptc/libiptc.c | 108 |
1 files changed, 67 insertions, 41 deletions
diff --git a/libiptc/libiptc.c b/libiptc/libiptc.c index 7a9c742..f0f7815 100644 --- a/libiptc/libiptc.c +++ b/libiptc/libiptc.c @@ -29,9 +29,13 @@ * - performance work: speedup initial ruleset parsing. * - sponsored by ComX Networks A/S (http://www.comx.dk/) */ +#include <unistd.h> +#include <fcntl.h> #include <sys/types.h> #include <sys/socket.h> +#include <stdbool.h> #include <xtables.h> +#include <libiptc/xtcshared.h> #include "linux_list.h" @@ -60,18 +64,9 @@ static const char *hooknames[] = { [HOOK_FORWARD] = "FORWARD", [HOOK_LOCAL_OUT] = "OUTPUT", [HOOK_POST_ROUTING] = "POSTROUTING", -#ifdef HOOK_DROPPING - [HOOK_DROPPING] = "DROPPING" -#endif }; /* Convenience structures */ -struct ipt_error_target -{ - STRUCT_ENTRY_TARGET t; - char error[TABLE_MAXNAMELEN]; -}; - struct chain_head; struct rule_head; @@ -129,8 +124,7 @@ struct chain_head unsigned int foot_offset; /* offset in rule blob */ }; -STRUCT_TC_HANDLE -{ +struct xtc_handle { int sockfd; int changed; /* Have changes been made? */ @@ -402,7 +396,7 @@ __iptcc_bsearch_chain_index(const char *name, unsigned int offset, } debug("jump back to pos:%d (end:%d)\n", pos, end); goto loop; - } else if (res > 0 ){ /* Not far enough, jump forward */ + } else { /* res > 0; Not far enough, jump forward */ /* Exit case: Last element of array */ if (pos == handle->chain_index_sz-1) { @@ -429,8 +423,6 @@ __iptcc_bsearch_chain_index(const char *name, unsigned int offset, debug("jump forward to pos:%d (end:%d)\n", pos, end); goto loop; } - - return list_pos; } /* Wrapper for string chain name based bsearch */ @@ -607,7 +599,7 @@ static int iptcc_chain_index_rebuild(struct xtc_handle *h) */ static int iptcc_chain_index_delete_chain(struct chain_head *c, struct xtc_handle *h) { - struct list_head *index_ptr, *index_ptr2, *next; + struct list_head *index_ptr, *next; struct chain_head *c2; unsigned int idx, idx2; @@ -627,7 +619,7 @@ static int iptcc_chain_index_delete_chain(struct chain_head *c, struct xtc_handl * is located in the same index bucket. */ c2 = list_entry(next, struct chain_head, list); - index_ptr2 = iptcc_bsearch_chain_index(c2->name, &idx2, h); + iptcc_bsearch_chain_index(c2->name, &idx2, h); if (idx != idx2) { /* Rebuild needed */ return iptcc_chain_index_rebuild(h); @@ -1013,6 +1005,7 @@ new_rule: if (t->target.u.target_size != ALIGN(sizeof(STRUCT_STANDARD_TARGET))) { errno = EINVAL; + free(r); return -1; } @@ -1093,10 +1086,10 @@ static int parse_table(struct xtc_handle *h) /* Convenience structures */ struct iptcb_chain_start{ STRUCT_ENTRY e; - struct ipt_error_target name; + struct xt_error_target name; }; #define IPTCB_CHAIN_START_SIZE (sizeof(STRUCT_ENTRY) + \ - ALIGN(sizeof(struct ipt_error_target))) + ALIGN(sizeof(struct xt_error_target))) struct iptcb_chain_foot { STRUCT_ENTRY e; @@ -1107,10 +1100,10 @@ struct iptcb_chain_foot { struct iptcb_chain_error { STRUCT_ENTRY entry; - struct ipt_error_target target; + struct xt_error_target target; }; #define IPTCB_CHAIN_ERROR_SIZE (sizeof(STRUCT_ENTRY) + \ - ALIGN(sizeof(struct ipt_error_target))) + ALIGN(sizeof(struct xt_error_target))) @@ -1153,10 +1146,10 @@ static int iptcc_compile_chain(struct xtc_handle *h, STRUCT_REPLACE *repl, struc head = (void *)repl->entries + c->head_offset; head->e.target_offset = sizeof(STRUCT_ENTRY); head->e.next_offset = IPTCB_CHAIN_START_SIZE; - strcpy(head->name.t.u.user.name, ERROR_TARGET); - head->name.t.u.target_size = - ALIGN(sizeof(struct ipt_error_target)); - strcpy(head->name.error, c->name); + strcpy(head->name.target.u.user.name, ERROR_TARGET); + head->name.target.u.target_size = + ALIGN(sizeof(struct xt_error_target)); + strcpy(head->name.errorname, c->name); } else { repl->hook_entry[c->hooknum-1] = c->head_offset; repl->underflow[c->hooknum-1] = c->foot_offset; @@ -1199,7 +1192,7 @@ static int iptcc_compile_chain_offsets(struct xtc_handle *h, struct chain_head * if (!iptcc_is_builtin(c)) { /* Chain has header */ *offset += sizeof(STRUCT_ENTRY) - + ALIGN(sizeof(struct ipt_error_target)); + + ALIGN(sizeof(struct xt_error_target)); (*num)++; } @@ -1239,7 +1232,7 @@ static int iptcc_compile_table_prep(struct xtc_handle *h, unsigned int *size) /* Append one error rule at end of chain */ num++; offset += sizeof(STRUCT_ENTRY) - + ALIGN(sizeof(struct ipt_error_target)); + + ALIGN(sizeof(struct xt_error_target)); /* ruleset size is now in offset */ *size = offset; @@ -1262,10 +1255,10 @@ static int iptcc_compile_table(struct xtc_handle *h, STRUCT_REPLACE *repl) error = (void *)repl->entries + repl->size - IPTCB_CHAIN_ERROR_SIZE; error->entry.target_offset = sizeof(STRUCT_ENTRY); error->entry.next_offset = IPTCB_CHAIN_ERROR_SIZE; - error->target.t.u.user.target_size = - ALIGN(sizeof(struct ipt_error_target)); - strcpy((char *)&error->target.t.u.user.name, ERROR_TARGET); - strcpy((char *)&error->target.error, "ERROR"); + error->target.target.u.user.target_size = + ALIGN(sizeof(struct xt_error_target)); + strcpy((char *)&error->target.target.u.user.name, ERROR_TARGET); + strcpy((char *)&error->target.errorname, "ERROR"); return 1; } @@ -1278,12 +1271,9 @@ static int iptcc_compile_table(struct xtc_handle *h, STRUCT_REPLACE *repl) static struct xtc_handle * alloc_handle(const char *tablename, unsigned int size, unsigned int num_rules) { - size_t len; struct xtc_handle *h; - len = sizeof(STRUCT_TC_HANDLE) + size; - - h = malloc(sizeof(STRUCT_TC_HANDLE)); + h = malloc(sizeof(*h)); if (!h) { errno = ENOMEM; return NULL; @@ -1317,6 +1307,7 @@ TC_INIT(const char *tablename) socklen_t s; int sockfd; +retry: iptc_fn = TC_INIT; if (strlen(tablename) >= TABLE_MAXNAMELEN) { @@ -1328,7 +1319,12 @@ TC_INIT(const char *tablename) if (sockfd < 0) return NULL; -retry: + if (fcntl(sockfd, F_SETFD, FD_CLOEXEC) == -1) { + fprintf(stderr, "Could not set close on exec: %s\n", + strerror(errno)); + abort(); + } + s = sizeof(info); strcpy(info.name, tablename); @@ -1956,12 +1952,11 @@ is_same(const STRUCT_ENTRY *a, const STRUCT_ENTRY *b, unsigned char *matchmask); -/* Delete the first rule in `chain' which matches `fw'. */ -int -TC_DELETE_ENTRY(const IPT_CHAINLABEL chain, - const STRUCT_ENTRY *origfw, - unsigned char *matchmask, - struct xtc_handle *handle) + +/* find the first rule in `chain' which matches `fw' and remove it unless dry_run is set */ +static int delete_entry(const IPT_CHAINLABEL chain, const STRUCT_ENTRY *origfw, + unsigned char *matchmask, struct xtc_handle *handle, + bool dry_run) { struct chain_head *c; struct rule_head *r, *i; @@ -2005,6 +2000,12 @@ TC_DELETE_ENTRY(const IPT_CHAINLABEL chain, if (!target_same(r, i, mask)) continue; + /* if we are just doing a dry run, we simply skip the rest */ + if (dry_run){ + free(r); + return 1; + } + /* If we are about to delete the rule that is the * current iterator, move rule iterator back. next * pointer will then point to real next node */ @@ -2027,6 +2028,20 @@ TC_DELETE_ENTRY(const IPT_CHAINLABEL chain, return 0; } +/* check whether a specified rule is present */ +int TC_CHECK_ENTRY(const IPT_CHAINLABEL chain, const STRUCT_ENTRY *origfw, + unsigned char *matchmask, struct xtc_handle *handle) +{ + /* do a dry-run delete to find out whether a matching rule exists */ + return delete_entry(chain, origfw, matchmask, handle, true); +} + +/* Delete the first rule in `chain' which matches `fw'. */ +int TC_DELETE_ENTRY(const IPT_CHAINLABEL chain, const STRUCT_ENTRY *origfw, + unsigned char *matchmask, struct xtc_handle *handle) +{ + return delete_entry(chain, origfw, matchmask, handle, false); +} /* Delete the rule in position `rulenum' in `chain'. */ int @@ -2728,3 +2743,14 @@ TC_STRERROR(int err) return strerror(err); } + +const struct xtc_ops TC_OPS = { + .commit = TC_COMMIT, + .free = TC_FREE, + .builtin = TC_BUILTIN, + .is_chain = TC_IS_CHAIN, + .flush_entries = TC_FLUSH_ENTRIES, + .create_chain = TC_CREATE_CHAIN, + .set_policy = TC_SET_POLICY, + .strerror = TC_STRERROR, +}; |