diff -X /home/gandalf/dontdiff.ny -urNp iptables-1.3.8-20070910.orig/include/libiptc/libip6tc.h iptables-1.3.8-20070910/include/libiptc/libip6tc.h --- iptables-1.3.8-20070910.orig/include/libiptc/libip6tc.h 2003-05-05 21:33:40.000000000 +0200 +++ iptables-1.3.8-20070910/include/libiptc/libip6tc.h 2007-09-11 10:20:45.000000000 +0200 @@ -17,6 +17,10 @@ typedef char ip6t_chainlabel[32]; #define IP6TC_LABEL_QUEUE "QUEUE" #define IP6TC_LABEL_RETURN "RETURN" +#ifndef TC_LIBNAME +#define TC_LIBNAME "libip6tc" +#endif + /* Transparent handle type. */ typedef struct ip6tc_handle *ip6tc_handle_t; @@ -145,8 +149,11 @@ int ip6tc_commit(ip6tc_handle_t *handle) /* Get raw socket. */ int ip6tc_get_raw_socket(); +/* Report errors */ +void ip6tc_error(const char *, int); + /* Translates errno numbers into more human-readable form than strerror. */ -const char *ip6tc_strerror(int err); +const char *ip6tc_strerror(); /* Return prefix length, or -1 if not contiguous */ int ipv6_prefix_length(const struct in6_addr *a); diff -X /home/gandalf/dontdiff.ny -urNp iptables-1.3.8-20070910.orig/include/libiptc/libiptc.h iptables-1.3.8-20070910/include/libiptc/libiptc.h --- iptables-1.3.8-20070910.orig/include/libiptc/libiptc.h 2003-05-02 17:30:11.000000000 +0200 +++ iptables-1.3.8-20070910/include/libiptc/libiptc.h 2007-09-11 10:20:45.000000000 +0200 @@ -25,6 +25,10 @@ typedef char ipt_chainlabel[32]; #define IPTC_LABEL_QUEUE "QUEUE" #define IPTC_LABEL_RETURN "RETURN" +#ifndef TC_LIBNAME +#define TC_LIBNAME "libip4tc" +#endif + /* Transparent handle type. */ typedef struct iptc_handle *iptc_handle_t; @@ -155,8 +159,11 @@ int iptc_commit(iptc_handle_t *handle); /* Get raw socket. */ int iptc_get_raw_socket(); +/* Report errors */ +void iptc_error(const char *, int); + /* Translates errno numbers into more human-readable form than strerror. */ -const char *iptc_strerror(int err); +const char *iptc_strerror(); #ifdef __cplusplus } diff -X /home/gandalf/dontdiff.ny -urNp iptables-1.3.8-20070910.orig/ip6tables-restore.c iptables-1.3.8-20070910/ip6tables-restore.c --- iptables-1.3.8-20070910.orig/ip6tables-restore.c 2007-07-24 07:52:07.000000000 +0200 +++ iptables-1.3.8-20070910/ip6tables-restore.c 2007-09-11 10:20:45.000000000 +0200 @@ -240,14 +240,14 @@ int main(int argc, char *argv[]) exit_error(PARAMETER_PROBLEM, "error flushing chain " "'%s':%s\n", chain, - strerror(errno)); + ip6tc_strerror()); } else { DEBUGP("Creating new chain '%s'\n", chain); if (!ip6tc_create_chain(chain, &handle)) exit_error(PARAMETER_PROBLEM, "error creating chain " "'%s':%s\n", chain, - strerror(errno)); + ip6tc_strerror()); } } @@ -286,7 +286,7 @@ int main(int argc, char *argv[]) "Can't set policy `%s'" " on `%s' line %u: %s\n", chain, policy, line, - ip6tc_strerror(errno)); + ip6tc_strerror()); } ret = 1; diff -X /home/gandalf/dontdiff.ny -urNp iptables-1.3.8-20070910.orig/ip6tables-save.c iptables-1.3.8-20070910/ip6tables-save.c --- iptables-1.3.8-20070910.orig/ip6tables-save.c 2007-05-10 17:00:39.000000000 +0200 +++ iptables-1.3.8-20070910/ip6tables-save.c 2007-09-11 10:20:45.000000000 +0200 @@ -257,7 +257,7 @@ static int do_output(const char *tablena h = ip6tc_init(tablename); if (!h) exit_error(OTHER_PROBLEM, "Can't initialize: %s\n", - ip6tc_strerror(errno)); + ip6tc_strerror()); if (!binary) { time_t now = time(NULL); diff -X /home/gandalf/dontdiff.ny -urNp iptables-1.3.8-20070910.orig/ip6tables-standalone.c iptables-1.3.8-20070910/ip6tables-standalone.c --- iptables-1.3.8-20070910.orig/ip6tables-standalone.c 2004-12-27 20:49:28.000000000 +0100 +++ iptables-1.3.8-20070910/ip6tables-standalone.c 2007-09-11 10:20:45.000000000 +0200 @@ -60,7 +60,7 @@ main(int argc, char *argv[]) if (!ret) fprintf(stderr, "ip6tables: %s\n", - ip6tc_strerror(errno)); + ip6tc_strerror()); exit(!ret); } diff -X /home/gandalf/dontdiff.ny -urNp iptables-1.3.8-20070910.orig/ip6tables.c iptables-1.3.8-20070910/ip6tables.c --- iptables-1.3.8-20070910.orig/ip6tables.c 2007-09-08 18:00:01.000000000 +0200 +++ iptables-1.3.8-20070910/ip6tables.c 2007-09-11 10:20:45.000000000 +0200 @@ -1330,7 +1330,9 @@ list_entries(const ip6t_chainlabel chain found = 1; } - errno = ENOENT; + if (!found) + ip6tc_error(__FUNCTION__, ENOENT); + return found; } @@ -1898,7 +1900,7 @@ int do_command6(int argc, char *argv[], if (!*handle) exit_error(VERSION_PROBLEM, "can't initialize ip6tables table `%s': %s", - *table, ip6tc_strerror(errno)); + *table, ip6tc_strerror()); if (command == CMD_APPEND || command == CMD_DELETE diff -X /home/gandalf/dontdiff.ny -urNp iptables-1.3.8-20070910.orig/iptables-restore.c iptables-1.3.8-20070910/iptables-restore.c --- iptables-1.3.8-20070910.orig/iptables-restore.c 2007-09-05 16:10:53.000000000 +0200 +++ iptables-1.3.8-20070910/iptables-restore.c 2007-09-11 10:20:45.000000000 +0200 @@ -247,14 +247,14 @@ main(int argc, char *argv[]) exit_error(PARAMETER_PROBLEM, "error flushing chain " "'%s':%s\n", chain, - strerror(errno)); + iptc_strerror()); } else { DEBUGP("Creating new chain '%s'\n", chain); if (!iptc_create_chain(chain, &handle)) exit_error(PARAMETER_PROBLEM, "error creating chain " "'%s':%s\n", chain, - strerror(errno)); + iptc_strerror()); } } @@ -293,7 +293,7 @@ main(int argc, char *argv[]) "Can't set policy `%s'" " on `%s' line %u: %s\n", chain, policy, line, - iptc_strerror(errno)); + iptc_strerror()); } ret = 1; diff -X /home/gandalf/dontdiff.ny -urNp iptables-1.3.8-20070910.orig/iptables-save.c iptables-1.3.8-20070910/iptables-save.c --- iptables-1.3.8-20070910.orig/iptables-save.c 2007-05-10 17:00:39.000000000 +0200 +++ iptables-1.3.8-20070910/iptables-save.c 2007-09-11 10:20:45.000000000 +0200 @@ -268,7 +268,7 @@ static int do_output(const char *tablena h = iptc_init(tablename); if (!h) exit_error(OTHER_PROBLEM, "Can't initialize: %s\n", - iptc_strerror(errno)); + iptc_strerror()); if (!binary) { time_t now = time(NULL); diff -X /home/gandalf/dontdiff.ny -urNp iptables-1.3.8-20070910.orig/iptables-standalone.c iptables-1.3.8-20070910/iptables-standalone.c --- iptables-1.3.8-20070910.orig/iptables-standalone.c 2006-06-19 18:53:03.000000000 +0200 +++ iptables-1.3.8-20070910/iptables-standalone.c 2007-09-11 10:20:45.000000000 +0200 @@ -66,7 +66,7 @@ main(int argc, char *argv[]) if (!ret) { fprintf(stderr, "iptables: %s\n", - iptc_strerror(errno)); + iptc_strerror()); if (errno == EAGAIN) { exit(RESOURCE_PROBLEM); } diff -X /home/gandalf/dontdiff.ny -urNp iptables-1.3.8-20070910.orig/iptables.c iptables-1.3.8-20070910/iptables.c --- iptables-1.3.8-20070910.orig/iptables.c 2007-09-08 18:00:01.000000000 +0200 +++ iptables-1.3.8-20070910/iptables.c 2007-09-11 10:20:45.000000000 +0200 @@ -1371,7 +1371,9 @@ list_entries(const ipt_chainlabel chain, found = 1; } - errno = ENOENT; + if (!found) + iptc_error(__FUNCTION__, ENOENT); + return found; } @@ -1963,7 +1965,7 @@ int do_command(int argc, char *argv[], c if (!*handle) exit_error(VERSION_PROBLEM, "can't initialize iptables table `%s': %s", - *table, iptc_strerror(errno)); + *table, iptc_strerror()); if (command == CMD_APPEND || command == CMD_DELETE diff -X /home/gandalf/dontdiff.ny -urNp iptables-1.3.8-20070910.orig/libiptc/libip4tc.c iptables-1.3.8-20070910/libiptc/libip4tc.c --- iptables-1.3.8-20070910.orig/libiptc/libip4tc.c 2007-09-02 15:09:07.000000000 +0200 +++ iptables-1.3.8-20070910/libiptc/libip4tc.c 2007-09-11 10:20:45.000000000 +0200 @@ -93,6 +93,7 @@ typedef unsigned int socklen_t; #define TC_INIT iptc_init #define TC_FREE iptc_free #define TC_COMMIT iptc_commit +#define TC_ERROR iptc_error #define TC_STRERROR iptc_strerror #define TC_NUM_RULES iptc_num_rules #define TC_GET_RULE iptc_get_rule @@ -115,6 +116,8 @@ typedef unsigned int socklen_t; #define ALIGN IPT_ALIGN #define RETURN IPT_RETURN +#define TC_ERR(x) TC_ERROR(__FUNCTION__, (x)) + #include "libiptc.c" #define IP_PARTS_NATIVE(n) \ diff -X /home/gandalf/dontdiff.ny -urNp iptables-1.3.8-20070910.orig/libiptc/libip6tc.c iptables-1.3.8-20070910/libiptc/libip6tc.c --- iptables-1.3.8-20070910.orig/libiptc/libip6tc.c 2007-09-02 15:09:07.000000000 +0200 +++ iptables-1.3.8-20070910/libiptc/libip6tc.c 2007-09-11 10:20:45.000000000 +0200 @@ -88,6 +88,7 @@ typedef unsigned int socklen_t; #define TC_INIT ip6tc_init #define TC_FREE ip6tc_free #define TC_COMMIT ip6tc_commit +#define TC_ERROR ip6tc_error #define TC_STRERROR ip6tc_strerror #define TC_NUM_RULES ip6tc_num_rules #define TC_GET_RULE ip6tc_get_rule @@ -110,6 +111,8 @@ typedef unsigned int socklen_t; #define ALIGN IP6T_ALIGN #define RETURN IP6T_RETURN +#define TC_ERR(x) TC_ERROR(__FUNCTION__, (x)) + #include "libiptc.c" #define BIT6(a, l) \ diff -X /home/gandalf/dontdiff.ny -urNp iptables-1.3.8-20070910.orig/libiptc/libiptc.c iptables-1.3.8-20070910/libiptc/libiptc.c --- iptables-1.3.8-20070910.orig/libiptc/libiptc.c 2007-09-08 18:52:25.000000000 +0200 +++ iptables-1.3.8-20070910/libiptc/libiptc.c 2007-09-11 10:29:14.000000000 +0200 @@ -46,7 +46,13 @@ static int sockfd = -1; static int sockfd_use = 0; -static void *iptc_fn = NULL; + +/* Silly games to get cpp to perform recursive macro expansion when quoting */ +#define QUOTE(x) #x +#define QF(x) QUOTE(x) + +static int iptc_errno = 0; +static char iptc_errfn[64]; static const char *hooknames[] = { [HOOK_PRE_ROUTING] = "PREROUTING", @@ -456,7 +462,7 @@ static int cache_add_entry(STRUCT_ENTRY DEBUGP_C("%u:%u:new userdefined chain %s: %p\n", *num, offset, (char *)c->name, c); if (!c) { - errno = -ENOMEM; + TC_ERR(ENOMEM); return -1; } @@ -469,7 +475,7 @@ static int cache_add_entry(STRUCT_ENTRY DEBUGP_C("%u:%u new builtin chain: %p (rules=%p)\n", *num, offset, c, &c->rules); if (!c) { - errno = -ENOMEM; + TC_ERR(ENOMEM); return -1; } @@ -486,9 +492,10 @@ new_rule: if (!(r = iptcc_alloc_rule(h->chain_iterator_cur, e->next_offset))) { - errno = ENOMEM; + TC_ERR(ENOMEM); return -1; } + DEBUGP_C("%u:%u normal rule: %p: ", *num, offset, r); r->index = *num; @@ -504,7 +511,7 @@ new_rule: t = (STRUCT_STANDARD_TARGET *)GET_TARGET(e); if (t->target.u.target_size != ALIGN(sizeof(STRUCT_STANDARD_TARGET))) { - errno = EINVAL; + TC_ERR(EINVAL); return -1; } @@ -770,7 +777,7 @@ alloc_handle(const char *tablename, unsi h = malloc(sizeof(STRUCT_TC_HANDLE)); if (!h) { - errno = ENOMEM; + TC_ERR(ENOMEM); return NULL; } memset(h, 0, sizeof(*h)); @@ -778,8 +785,10 @@ alloc_handle(const char *tablename, unsi strcpy(h->info.name, tablename); h->entries = malloc(sizeof(STRUCT_GET_ENTRIES) + size); - if (!h->entries) + if (!h->entries) { + TC_ERR(ENOMEM); goto out_free_handle; + } strcpy(h->entries->name, tablename); h->entries->size = size; @@ -801,17 +810,21 @@ TC_INIT(const char *tablename) unsigned int tmp; socklen_t s; - iptc_fn = TC_INIT; + /* ugly hack to avoid warnings if called multiple times */ + memset(iptc_errfn, 0, 64); + iptc_errno = 0; if (strlen(tablename) >= TABLE_MAXNAMELEN) { - errno = EINVAL; + TC_ERR(E2BIG); return NULL; } if (sockfd_use == 0) { sockfd = socket(TC_AF, SOCK_RAW, IPPROTO_RAW); - if (sockfd < 0) + if (sockfd < 0) { + TC_ERR(errno); return NULL; + } } sockfd_use++; @@ -823,6 +836,7 @@ TC_INIT(const char *tablename) close(sockfd); sockfd = -1; } + TC_ERR(errno); return NULL; } @@ -835,6 +849,7 @@ TC_INIT(const char *tablename) close(sockfd); sockfd = -1; } + TC_ERR(ENOMEM); return NULL; } @@ -846,8 +861,10 @@ TC_INIT(const char *tablename) tmp = sizeof(STRUCT_GET_ENTRIES) + h->info.size; if (getsockopt(sockfd, TC_IPPROTO, SO_GET_ENTRIES, h->entries, - &tmp) < 0) + &tmp) < 0) { + TC_ERR(errno); goto error; + } #ifdef IPTC_DEBUG2 { @@ -879,7 +896,6 @@ TC_FREE(TC_HANDLE_T *h) { struct chain_head *c, *tmp; - iptc_fn = TC_FREE; if (--sockfd_use == 0) { close(sockfd); sockfd = -1; @@ -913,7 +929,6 @@ static int dump_entry(STRUCT_ENTRY *e, c void TC_DUMP_ENTRIES(const TC_HANDLE_T handle) { - iptc_fn = TC_DUMP_ENTRIES; CHECK(handle); printf("libiptc v%s. %u bytes.\n", @@ -939,7 +954,6 @@ TC_DUMP_ENTRIES(const TC_HANDLE_T handle /* Does this chain exist? */ int TC_IS_CHAIN(const char *chain, const TC_HANDLE_T handle) { - iptc_fn = TC_IS_CHAIN; return iptcc_find_label(chain, handle) != NULL; } @@ -961,11 +975,9 @@ TC_FIRST_CHAIN(TC_HANDLE_T *handle) struct chain_head *c = list_entry((*handle)->chains.next, struct chain_head, list); - iptc_fn = TC_FIRST_CHAIN; - - if (list_empty(&(*handle)->chains)) { DEBUGP(": no chains\n"); + TC_ERR(ENOENT); return NULL; } @@ -982,8 +994,6 @@ TC_NEXT_CHAIN(TC_HANDLE_T *handle) { struct chain_head *c = (*handle)->chain_iterator_cur; - iptc_fn = TC_NEXT_CHAIN; - if (!c) { DEBUGP(": no more chains\n"); return NULL; @@ -1002,13 +1012,11 @@ TC_FIRST_RULE(const char *chain, TC_HAND struct chain_head *c; struct rule_head *r; - iptc_fn = TC_FIRST_RULE; - DEBUGP("first rule(%s): ", chain); c = iptcc_find_label(chain, *handle); if (!c) { - errno = ENOENT; + TC_ERR(ENOENT); return NULL; } @@ -1031,7 +1039,6 @@ TC_NEXT_RULE(const STRUCT_ENTRY *prev, T { struct rule_head *r; - iptc_fn = TC_NEXT_RULE; DEBUGP("rule_iterator_cur=%p...", (*handle)->rule_iterator_cur); if (!(*handle)->rule_iterator_cur) { @@ -1042,8 +1049,6 @@ TC_NEXT_RULE(const STRUCT_ENTRY *prev, T r = list_entry((*handle)->rule_iterator_cur->list.next, struct rule_head, list); - iptc_fn = TC_NEXT_RULE; - DEBUGP_C("next=%p, head=%p...", &r->list, &(*handle)->rule_iterator_cur->chain->rules); @@ -1065,12 +1070,11 @@ unsigned int TC_NUM_RULES(const char *chain, TC_HANDLE_T *handle) { struct chain_head *c; - iptc_fn = TC_NUM_RULES; CHECK(*handle); c = iptcc_find_label(chain, *handle); if (!c) { - errno = ENOENT; + TC_ERR(ENOENT); return (unsigned int)-1; } @@ -1084,13 +1088,11 @@ const STRUCT_ENTRY *TC_GET_RULE(const ch struct chain_head *c; struct rule_head *r; - iptc_fn = TC_GET_RULE; - CHECK(*handle); c = iptcc_find_label(chain, *handle); if (!c) { - errno = ENOENT; + TC_ERR(ENOENT); return NULL; } @@ -1133,8 +1135,6 @@ const char *TC_GET_TARGET(const STRUCT_E STRUCT_ENTRY *e = (STRUCT_ENTRY *)ce; struct rule_head *r = container_of(e, struct rule_head, entry[0]); - iptc_fn = TC_GET_TARGET; - switch(r->type) { int spos; case IPTCC_R_FALLTHROUGH: @@ -1161,13 +1161,9 @@ TC_BUILTIN(const char *chain, const TC_H { struct chain_head *c; - iptc_fn = TC_BUILTIN; - c = iptcc_find_label(chain, handle); - if (!c) { - errno = ENOENT; + if (!c) return 0; - } return iptcc_is_builtin(c); } @@ -1180,13 +1176,11 @@ TC_GET_POLICY(const char *chain, { struct chain_head *c; - iptc_fn = TC_GET_POLICY; - DEBUGP("called for chain %s\n", chain); c = iptcc_find_label(chain, *handle); if (!c) { - errno = ENOENT; + TC_ERR(ENOENT); return NULL; } @@ -1208,7 +1202,7 @@ iptcc_standard_map(struct rule_head *r, if (t->target.u.target_size != ALIGN(sizeof(STRUCT_STANDARD_TARGET))) { - errno = EINVAL; + TC_ERR(EINVAL); return 0; } /* memset for memcmp convenience on delete/replace */ @@ -1244,7 +1238,7 @@ iptcc_map_target(const TC_HANDLE_T handl return iptcc_standard_map(r, RETURN); else if (TC_BUILTIN(t->u.user.name, handle)) { /* Can't jump to builtins. */ - errno = EINVAL; + TC_ERR(EINVAL); return 0; } else { /* Maybe it's an existing chain name. */ @@ -1283,17 +1277,15 @@ TC_INSERT_ENTRY(const IPT_CHAINLABEL cha struct rule_head *r; struct list_head *prev; - iptc_fn = TC_INSERT_ENTRY; - if (!(c = iptcc_find_label(chain, *handle))) { - errno = ENOENT; + TC_ERR(ENOENT); return 0; } /* first rulenum index = 0 first c->num_rules index = 1 */ if (rulenum > c->num_rules) { - errno = E2BIG; + TC_ERR(E2BIG); return 0; } @@ -1311,7 +1303,7 @@ TC_INSERT_ENTRY(const IPT_CHAINLABEL cha } if (!(r = iptcc_alloc_rule(c, e->next_offset))) { - errno = ENOMEM; + TC_ERR(ENOMEM); return 0; } @@ -1341,15 +1333,13 @@ TC_REPLACE_ENTRY(const IPT_CHAINLABEL ch struct chain_head *c; struct rule_head *r, *old; - iptc_fn = TC_REPLACE_ENTRY; - if (!(c = iptcc_find_label(chain, *handle))) { - errno = ENOENT; + TC_ERR(ENOENT); return 0; } if (rulenum >= c->num_rules) { - errno = E2BIG; + TC_ERR(E2BIG); return 0; } @@ -1361,7 +1351,7 @@ TC_REPLACE_ENTRY(const IPT_CHAINLABEL ch } if (!(r = iptcc_alloc_rule(c, e->next_offset))) { - errno = ENOMEM; + TC_ERR(ENOMEM); return 0; } @@ -1391,16 +1381,15 @@ TC_APPEND_ENTRY(const IPT_CHAINLABEL cha struct chain_head *c; struct rule_head *r; - iptc_fn = TC_APPEND_ENTRY; if (!(c = iptcc_find_label(chain, *handle))) { DEBUGP("unable to find chain `%s'\n", chain); - errno = ENOENT; + TC_ERR(ENOENT); return 0; } if (!(r = iptcc_alloc_rule(c, e->next_offset))) { DEBUGP("unable to allocate rule for chain `%s'\n", chain); - errno = ENOMEM; + TC_ERR(ENOMEM); return 0; } @@ -1499,16 +1488,15 @@ TC_DELETE_ENTRY(const IPT_CHAINLABEL cha struct chain_head *c; struct rule_head *r, *i; - iptc_fn = TC_DELETE_ENTRY; if (!(c = iptcc_find_label(chain, *handle))) { - errno = ENOENT; + TC_ERR(ENOENT); return 0; } /* Create a rule_head from origfw. */ r = iptcc_alloc_rule(c, origfw->next_offset); if (!r) { - errno = ENOMEM; + TC_ERR(ENOMEM); return 0; } @@ -1556,7 +1544,7 @@ TC_DELETE_ENTRY(const IPT_CHAINLABEL cha } free(r); - errno = ENOENT; + TC_ERR(EINVAL); return 0; } @@ -1570,15 +1558,13 @@ TC_DELETE_NUM_ENTRY(const IPT_CHAINLABEL struct chain_head *c; struct rule_head *r; - iptc_fn = TC_DELETE_NUM_ENTRY; - if (!(c = iptcc_find_label(chain, *handle))) { - errno = ENOENT; + TC_ERR(ENOENT); return 0; } if (rulenum >= c->num_rules) { - errno = E2BIG; + TC_ERR(E2BIG); return 0; } @@ -1613,8 +1599,7 @@ TC_CHECK_PACKET(const IPT_CHAINLABEL cha STRUCT_ENTRY *entry, TC_HANDLE_T *handle) { - iptc_fn = TC_CHECK_PACKET; - errno = ENOSYS; + TC_ERR(ENOSYS); return NULL; } @@ -1625,9 +1610,8 @@ TC_FLUSH_ENTRIES(const IPT_CHAINLABEL ch struct chain_head *c; struct rule_head *r, *tmp; - iptc_fn = TC_FLUSH_ENTRIES; if (!(c = iptcc_find_label(chain, *handle))) { - errno = ENOENT; + TC_ERR(ENOENT); return 0; } @@ -1649,9 +1633,8 @@ TC_ZERO_ENTRIES(const IPT_CHAINLABEL cha struct chain_head *c; struct rule_head *r; - iptc_fn = TC_ZERO_ENTRIES; if (!(c = iptcc_find_label(chain, *handle))) { - errno = ENOENT; + TC_ERR(ENOENT); return 0; } @@ -1676,16 +1659,15 @@ TC_READ_COUNTER(const IPT_CHAINLABEL cha struct chain_head *c; struct rule_head *r; - iptc_fn = TC_READ_COUNTER; CHECK(*handle); if (!(c = iptcc_find_label(chain, *handle))) { - errno = ENOENT; + TC_ERR(ENOENT); return NULL; } if (!(r = iptcc_get_rule_num(c, rulenum))) { - errno = E2BIG; + TC_ERR(E2BIG); return NULL; } @@ -1700,16 +1682,15 @@ TC_ZERO_COUNTER(const IPT_CHAINLABEL cha struct chain_head *c; struct rule_head *r; - iptc_fn = TC_ZERO_COUNTER; CHECK(*handle); if (!(c = iptcc_find_label(chain, *handle))) { - errno = ENOENT; + TC_ERR(ENOENT); return 0; } if (!(r = iptcc_get_rule_num(c, rulenum))) { - errno = E2BIG; + TC_ERR(E2BIG); return 0; } @@ -1731,16 +1712,15 @@ TC_SET_COUNTER(const IPT_CHAINLABEL chai struct rule_head *r; STRUCT_ENTRY *e; - iptc_fn = TC_SET_COUNTER; CHECK(*handle); if (!(c = iptcc_find_label(chain, *handle))) { - errno = ENOENT; + TC_ERR(ENOENT); return 0; } if (!(r = iptcc_get_rule_num(c, rulenum))) { - errno = E2BIG; + TC_ERR(E2BIG); return 0; } @@ -1762,8 +1742,6 @@ TC_CREATE_CHAIN(const IPT_CHAINLABEL cha { static struct chain_head *c; - iptc_fn = TC_CREATE_CHAIN; - /* find_label doesn't cover built-in targets: DROP, ACCEPT, QUEUE, RETURN. */ if (iptcc_find_label(chain, *handle) @@ -1772,20 +1750,20 @@ TC_CREATE_CHAIN(const IPT_CHAINLABEL cha || strcmp(chain, LABEL_QUEUE) == 0 || strcmp(chain, LABEL_RETURN) == 0) { DEBUGP("Chain `%s' already exists\n", chain); - errno = EEXIST; + TC_ERR(EEXIST); return 0; } if (strlen(chain)+1 > sizeof(IPT_CHAINLABEL)) { DEBUGP("Chain name `%s' too long\n", chain); - errno = EINVAL; + TC_ERR(E2BIG); return 0; } c = iptcc_alloc_chain_head(chain, 0); if (!c) { DEBUGP("Cannot allocate memory for chain `%s'\n", chain); - errno = ENOMEM; + TC_ERR(ENOMEM); return 0; } @@ -1805,9 +1783,8 @@ TC_GET_REFERENCES(unsigned int *ref, con { struct chain_head *c; - iptc_fn = TC_GET_REFERENCES; if (!(c = iptcc_find_label(chain, *handle))) { - errno = ENOENT; + TC_ERR(ENOENT); return 0; } @@ -1823,34 +1800,33 @@ TC_DELETE_CHAIN(const IPT_CHAINLABEL cha unsigned int references; struct chain_head *c; - iptc_fn = TC_DELETE_CHAIN; - if (!(c = iptcc_find_label(chain, *handle))) { DEBUGP("cannot find chain `%s'\n", chain); - errno = ENOENT; + TC_ERR(ENOENT); return 0; } if (TC_BUILTIN(chain, *handle)) { DEBUGP("cannot remove builtin chain `%s'\n", chain); - errno = EINVAL; + TC_ERR(EINVAL); return 0; } if (!TC_GET_REFERENCES(&references, chain, handle)) { DEBUGP("cannot get references on chain `%s'\n", chain); + TC_ERR(ENOSYS); return 0; } if (references > 0) { DEBUGP("chain `%s' still has references\n", chain); - errno = EMLINK; + TC_ERR(EMLINK); return 0; } if (c->num_rules) { DEBUGP("chain `%s' is not empty\n", chain); - errno = ENOTEMPTY; + TC_ERR(ENOTEMPTY); return 0; } @@ -1875,7 +1851,17 @@ int TC_RENAME_CHAIN(const IPT_CHAINLABEL TC_HANDLE_T *handle) { struct chain_head *c; - iptc_fn = TC_RENAME_CHAIN; + + if (!(c = iptcc_find_label(oldname, *handle)) + || TC_BUILTIN(oldname, *handle)) { + TC_ERR(ENOENT); + return 0; + } + + if (strlen(newname)+1 > sizeof(IPT_CHAINLABEL)) { + TC_ERR(E2BIG); + return 0; + } /* find_label doesn't cover built-in targets: DROP, ACCEPT, QUEUE, RETURN. */ @@ -1884,18 +1870,7 @@ int TC_RENAME_CHAIN(const IPT_CHAINLABEL || strcmp(newname, LABEL_ACCEPT) == 0 || strcmp(newname, LABEL_QUEUE) == 0 || strcmp(newname, LABEL_RETURN) == 0) { - errno = EEXIST; - return 0; - } - - if (!(c = iptcc_find_label(oldname, *handle)) - || TC_BUILTIN(oldname, *handle)) { - errno = ENOENT; - return 0; - } - - if (strlen(newname)+1 > sizeof(IPT_CHAINLABEL)) { - errno = EINVAL; + TC_ERR(EEXIST); return 0; } @@ -1915,17 +1890,15 @@ TC_SET_POLICY(const IPT_CHAINLABEL chain { struct chain_head *c; - iptc_fn = TC_SET_POLICY; - if (!(c = iptcc_find_label(chain, *handle))) { DEBUGP("cannot find chain `%s'\n", chain); - errno = ENOENT; + TC_ERR(ENOENT); return 0; } if (!iptcc_is_builtin(c)) { DEBUGP("cannot set policy of userdefinedchain `%s'\n", chain); - errno = ENOENT; + TC_ERR(ENOENT); return 0; } @@ -1934,7 +1907,7 @@ TC_SET_POLICY(const IPT_CHAINLABEL chain else if (strcmp(policy, LABEL_DROP) == 0) c->verdict = -NF_DROP - 1; else { - errno = EINVAL; + TC_ERR(EINVAL); return 0; } @@ -2034,7 +2007,6 @@ TC_COMMIT(TC_HANDLE_T *handle) int new_number; unsigned int new_size; - iptc_fn = TC_COMMIT; CHECK(*handle); /* Don't commit if nothing changed. */ @@ -2043,13 +2015,13 @@ TC_COMMIT(TC_HANDLE_T *handle) new_number = iptcc_compile_table_prep(*handle, &new_size); if (new_number < 0) { - errno = ENOMEM; + TC_ERR(ENOMEM); goto out_zero; } repl = malloc(sizeof(*repl) + new_size); if (!repl) { - errno = ENOMEM; + TC_ERR(ENOMEM); goto out_zero; } memset(repl, 0, sizeof(*repl) + new_size); @@ -2065,13 +2037,13 @@ TC_COMMIT(TC_HANDLE_T *handle) repl->counters = malloc(sizeof(STRUCT_COUNTERS) * (*handle)->info.num_entries); if (!repl->counters) { - errno = ENOMEM; + TC_ERR(ENOMEM); goto out_free_repl; } /* These are the counters we're going to put back, later. */ newcounters = malloc(counterlen); if (!newcounters) { - errno = ENOMEM; + TC_ERR(ENOMEM); goto out_free_repl_counters; } memset(newcounters, 0, counterlen); @@ -2088,7 +2060,7 @@ TC_COMMIT(TC_HANDLE_T *handle) ret = iptcc_compile_table(*handle, repl); if (ret < 0) { - errno = ret; + TC_ERR(EINVAL); goto out_free_newcounters; } @@ -2106,8 +2078,10 @@ TC_COMMIT(TC_HANDLE_T *handle) ret = setsockopt(sockfd, TC_IPPROTO, SO_SET_REPLACE, repl, sizeof(*repl) + repl->size); - if (ret < 0) + if (ret < 0) { + TC_ERR(errno); goto out_free_newcounters; + } /* Put counters back. */ strcpy(newcounters->name, (*handle)->info.name); @@ -2182,8 +2156,10 @@ TC_COMMIT(TC_HANDLE_T *handle) ret = setsockopt(sockfd, TC_IPPROTO, SO_SET_ADD_COUNTERS, newcounters, counterlen); - if (ret < 0) + if (ret < 0) { + TC_ERR(errno); goto out_free_newcounters; + } free(repl->counters); free(repl); @@ -2210,57 +2186,98 @@ TC_GET_RAW_SOCKET(void) return sockfd; } +void +TC_ERROR(const char *function, int error) +{ + if (strlen(iptc_errfn)) + printf("%s: %s\n", TC_LIBNAME, TC_STRERROR()); + strncpy(iptc_errfn, function, 63); + iptc_errno = error; +} + /* Translates errno numbers into more human-readable form than strerror. */ const char * -TC_STRERROR(int err) +TC_STRERROR() { - unsigned int i; + unsigned int i, length; + static char strbuf[256]; + struct table_struct { - void *fn; + const char *fn; int err; const char *message; } table [] = - { { TC_INIT, EPERM, "Permission denied (you must be root)" }, - { TC_INIT, EINVAL, "Module is wrong version" }, - { TC_INIT, ENOENT, - "Table does not exist (do you need to insmod?)" }, - { TC_DELETE_CHAIN, ENOTEMPTY, "Chain is not empty" }, - { TC_DELETE_CHAIN, EINVAL, "Can't delete built-in chain" }, - { TC_DELETE_CHAIN, EMLINK, - "Can't delete chain with references left" }, - { TC_CREATE_CHAIN, EEXIST, "Chain already exists" }, - { TC_INSERT_ENTRY, E2BIG, "Index of insertion too big" }, - { TC_REPLACE_ENTRY, E2BIG, "Index of replacement too big" }, - { TC_DELETE_NUM_ENTRY, E2BIG, "Index of deletion too big" }, - { TC_READ_COUNTER, E2BIG, "Index of counter too big" }, - { TC_ZERO_COUNTER, E2BIG, "Index of counter too big" }, - { TC_INSERT_ENTRY, ELOOP, "Loop found in table" }, - { TC_INSERT_ENTRY, EINVAL, "Target problem" }, - /* EINVAL for CHECK probably means bad interface. */ - { TC_CHECK_PACKET, EINVAL, - "Bad arguments (does that interface exist?)" }, - { TC_CHECK_PACKET, ENOSYS, + { { QF(TC_APPEND_ENTRY), ENOENT, "No chain by that name" }, + { QF(TC_CHECK_PACKET), ENOSYS, "Checking will most likely never get implemented" }, - /* ENOENT for DELETE probably means no matching rule */ - { TC_DELETE_ENTRY, ENOENT, + { QF(TC_COMMIT), EINVAL, "Table compilation failed" }, + { QF(TC_COMMIT), ELOOP, "Loop found in table" }, + { QF(TC_COMMIT), EPERM, "Permission denied (you must be root)" }, + { QF(TC_CREATE_CHAIN), EEXIST, "Chain already exists" }, + { QF(TC_CREATE_CHAIN), E2BIG, "Chain name too long" }, + { QF(TC_DELETE_CHAIN), ENOTEMPTY, "Chain is not empty" }, + { QF(TC_DELETE_CHAIN), EINVAL, "Can't delete built-in chain" }, + { QF(TC_DELETE_CHAIN), EMLINK, + "Can't delete chain with references left" }, + { QF(TC_DELETE_CHAIN), ENOENT, "No chain by that name" }, + { QF(TC_DELETE_CHAIN), ENOSYS, "Couldn't get reference list for chain" }, + { QF(TC_DELETE_ENTRY), ENOENT, "No chain by that name" }, + { QF(TC_DELETE_ENTRY), EINVAL, "Bad rule (does a matching rule exist in that chain?)" }, - { TC_SET_POLICY, ENOENT, - "Bad built-in chain name" }, - { TC_SET_POLICY, EINVAL, - "Bad policy name" }, + { QF(TC_DELETE_NUM_ENTRY), ENOENT, "No chain by that name" }, + { QF(TC_DELETE_NUM_ENTRY), E2BIG, "Index of deletion too big" }, + { QF(TC_FIRST_CHAIN), ENOENT, "No chains to be found" }, + { QF(TC_FIRST_RULE), ENOENT, "No chain by that name" }, + { QF(TC_FLUSH_ENTRIES), ENOENT, "No chain by that name" }, + { QF(TC_GET_POLICY), ENOENT, "No chain by that name" }, + { QF(TC_GET_REFERENCES), ENOENT, "No chain by that name" }, + { QF(TC_GET_RULE), ENOENT, "No chain by that name" }, + { QF(TC_INIT), EPERM, "Permission denied (you must be root)" }, + { QF(TC_INIT), EINVAL, "Module is wrong version" }, + { QF(TC_INIT), E2BIG, "Table name too long" }, + { QF(TC_INIT), ENOENT, + "Table does not exist (do you need to insmod?)" }, + { QF(TC_INSERT_ENTRY), E2BIG, "Index of insertion too big" }, + { QF(TC_INSERT_ENTRY), ENOENT, "No chain by that name" }, + { QF(TC_NUM_RULES), ENOENT, "No chain by that name" }, + { QF(TC_READ_COUNTER), E2BIG, "Index of counter read too big" }, + { QF(TC_READ_COUNTER), ENOENT, "No chain by that name" }, + { QF(TC_RENAME_CHAIN), E2BIG, "Chain name too long" }, + { QF(TC_RENAME_CHAIN), ENOENT, "No chain by that name" }, + { QF(TC_RENAME_CHAIN), EEXIST, "Chain already exists" }, + { QF(TC_REPLACE_ENTRY), E2BIG, "Index of replacement too big" }, + { QF(TC_REPLACE_ENTRY), ENOENT, "No chain by that name" }, + { QF(TC_SET_COUNTER), E2BIG, "Index of counter too big" }, + { QF(TC_SET_COUNTER), ENOENT, "No chain by that name" }, + { QF(TC_SET_POLICY), ENOENT, "Bad built-in chain name" }, + { QF(TC_SET_POLICY), EINVAL, "Bad policy name" }, + { QF(TC_ZERO_COUNTER), E2BIG, "Index of counter too big" }, + { QF(TC_ZERO_COUNTER), ENOENT, "No chain by that name" }, + { QF(TC_ZERO_ENTRIES), ENOENT, "No chain by that name" }, + + { QF(cache_add_entry), EINVAL, "Target problem" }, + { QF(iptcc_map_target), EINVAL, "Can't jump to a built-in target" }, + { QF(iptcc_standard_map), EINVAL, "Target problem" }, + { QF(list_entries), ENOENT, "No chain by that name" }, - { NULL, 0, "Incompatible with this kernel" }, { NULL, ENOPROTOOPT, "iptables who? (do you need to insmod?)" }, - { NULL, ENOSYS, "Will be implemented real soon. I promise ;)" }, { NULL, ENOMEM, "Memory allocation problem" }, - { NULL, ENOENT, "No chain/target/match by that name" }, }; + + if (!strlen(iptc_errfn)) + return "Something forgot to set the error reason"; for (i = 0; i < sizeof(table)/sizeof(struct table_struct); i++) { - if ((!table[i].fn || table[i].fn == iptc_fn) - && table[i].err == err) + if ((!table[i].fn || !strcmp(table[i].fn, iptc_errfn)) + && table[i].err == iptc_errno) return table[i].message; } - return strerror(err); + length = snprintf(strbuf, 256, "Unknown error, %s: %i", iptc_errfn, iptc_errno); + + /* Avoid printing "(Success)" */ + if (iptc_errno) + snprintf(strbuf + length, 256 - length, " (%s)", strerror(iptc_errno)); + + return strbuf; }