void fwd_ipt_clear_ruleset(struct fwd_handle *h) { struct iptc_handle *h_filter, *h_nat; if( !(h_filter = iptc_init("filter")) || !(h_nat = iptc_init("nat")) ) fwd_fatal("Unable to obtain libiptc handle"); /* flush tables */ fwd_ipt_clear_ruleset_table(h_nat); fwd_ipt_clear_ruleset_table(h_filter); /* revert policies */ fwd_r_set_policy(h_filter, "INPUT", "ACCEPT"); fwd_r_set_policy(h_filter, "OUTPUT", "ACCEPT"); fwd_r_set_policy(h_filter, "FORWARD", "ACCEPT"); if( !iptc_commit(h_nat) ) fwd_fatal("Cannot commit nat table: %s", iptc_strerror(errno)); if( !iptc_commit(h_filter) ) fwd_fatal("Cannot commit filter table: %s", iptc_strerror(errno)); iptc_free(h_nat); iptc_free(h_filter); }
/* delete_rule_and_commit() : * subfunction used in delete_redirect_and_filter_rules() */ static int delete_rule_and_commit(unsigned int index, IPTC_HANDLE h, const char * miniupnpd_chain, const char * logcaller) { int r = 0; #ifdef IPTABLES_143 if(!iptc_delete_num_entry(miniupnpd_chain, index, h)) #else if(!iptc_delete_num_entry(miniupnpd_chain, index, &h)) #endif { syslog(LOG_ERR, "%s() : iptc_delete_num_entry(): %s\n", logcaller, iptc_strerror(errno)); r = -1; } #ifdef IPTABLES_143 else if(!iptc_commit(h)) #else else if(!iptc_commit(&h)) #endif { syslog(LOG_ERR, "%s() : iptc_commit(): %s\n", logcaller, iptc_strerror(errno)); r = -1; } if(h) #ifdef IPTABLES_143 iptc_free(h); #else iptc_free(&h); #endif return r; }
int iptables_main(int argc, char *argv[]) { int ret; char *table = "filter"; struct xtc_handle *handle = NULL; FILE *pfLockFile = NULL; pfLockFile = ATP_UTIL_LockProc(IPTABLES_LOCK_FILE); if (NULL == pfLockFile) { printf("iptables get lock failed\n"); exit(-1); } ATP_UTIL_RegUnLock(pfLockFile); iptables_globals.program_name = "iptables"; ret = xtables_init_all(&iptables_globals, NFPROTO_IPV4); if (ret < 0) { fprintf(stderr, "%s/%s Failed to initialize xtables\n", iptables_globals.program_name, iptables_globals.program_version); exit(1); } #if defined(ALL_INCLUSIVE) || defined(NO_SHARED_LIBS) init_extensions(); init_extensions4(); #endif ret = do_command4(argc, argv, &table, &handle); if (ret) { ret = iptc_commit(handle); iptc_free(handle); } if (!ret) { if (errno == EINVAL) { fprintf(stderr, "iptables: %s. " "Run `dmesg' for more information.\n", iptc_strerror(errno)); } else { fprintf(stderr, "iptables: %s.\n", iptc_strerror(errno)); } if (errno == EAGAIN) { exit(RESOURCE_PROBLEM); } } exit(!ret); }
static int do_output(const char *tablename) { struct xtc_handle *h; const char *chain = NULL; if (!tablename) return for_each_table(&do_output); h = iptc_init(tablename); if (h == NULL) { xtables_load_ko(xtables_modprobe_program, false); h = iptc_init(tablename); } if (!h) xtables_error(OTHER_PROBLEM, "Cannot initialize: %s\n", iptc_strerror(errno)); time_t now = time(NULL); printf("# Generated by iptables-save v%s on %s", IPTABLES_VERSION, ctime(&now)); printf("*%s\n", tablename); /* Dump out chain names first, * thereby preventing dependency conflicts */ for (chain = iptc_first_chain(h); chain; chain = iptc_next_chain(h)) { printf(":%s ", chain); if (iptc_builtin(chain, h)) { struct xt_counters count; printf("%s ", iptc_get_policy(chain, &count, h)); printf("[%llu:%llu]\n", (unsigned long long)count.pcnt, (unsigned long long)count.bcnt); } else { printf("- [0:0]\n"); } } for (chain = iptc_first_chain(h); chain; chain = iptc_next_chain(h)) { const struct ipt_entry *e; /* Dump out rules */ e = iptc_first_rule(chain, h); while(e) { print_rule4(e, h, chain, show_counters); e = iptc_next_rule(e, h); } } now = time(NULL); printf("COMMIT\n"); printf("# Completed on %s", ctime(&now)); iptc_free(h); return 1; }
// Commit table changes. static int __lua_iptc_commit(lua_State *L) { int i, r; const char *table = luaL_checkstring(L, 1); i = find_table(table); if(i == -1) return eprintf("Invalid table: %s", table); if(!tables[i].handle) return eprintf("Invalid table: %s", table); if(pretend) return 0; r = iptc_commit(tables[i].handle); tables[i].handle = NULL; if(!r) { return eprintf("Unable to commit: %s: %s.", table, iptc_strerror(errno)); } return 0; }
// Initialize built-in iptable tables (filter, mangle, nat). static int __lua_iptc_init(lua_State *L) { int i; if(!tables) { tables = calloc(4, sizeof(struct table_t)); tables[0].name = strdup("filter"); tables[1].name = strdup("mangle"); tables[2].name = strdup("nat"); } for(i = 0; tables[i].name; i++) { if(tables[i].handle) continue; tables[i].handle = iptc_init(tables[i].name); if(!tables[i].handle) { return eprintf("Unable to initialize table: %s: %s.", tables[i].name, iptc_strerror(errno)); } } return 0; }
int main(int argc, char *argv[]) #endif { int ret; char *table = "filter"; iptc_handle_t handle = NULL; program_name = "iptables"; program_version = IPTABLES_VERSION; lib_dir = getenv("IPTABLES_LIB_DIR"); if (!lib_dir) lib_dir = IPT_LIB_DIR; #ifdef NO_SHARED_LIBS init_extensions(); #endif ret = do_command(argc, argv, &table, &handle); if (ret) ret = iptc_commit(&handle); if (!ret) { fprintf(stderr, "iptables: %s\n", iptc_strerror(errno)); if (errno == EAGAIN) { exit(RESOURCE_PROBLEM); } } exit(!ret); }
static int do_commit(void) { unsigned i; int ret = 1; for(i = 0; i < num_tables; ++i) { if(tables[i].handle) { #ifdef IP6T ret = ip6tc_commit(tables[i].handle); if (!ret) fprintf(stderr, "commit failed on table %s: %s\n", tables[i].name, ip6tc_strerror(errno)); ip6tc_free(tables[i].handle); tables[i].handle = NULL; #else ret = iptc_commit(tables[i].handle); if (!ret) fprintf(stderr, "commit failed on table %s: %s\n", tables[i].name, iptc_strerror(errno)); iptc_free(tables[i].handle); tables[i].handle = NULL; #endif } } return ret; }
/* delete_rule_and_commit() : * subfunction used in delete_redirect_and_filter_rules() */ static int delete_rule_and_commit(unsigned int index, iptc_handle_t *h, const char * logcaller) { int r = 0; if(!iptc_delete_num_entry(miniupnpd_chain, index, h)) { syslog(LOG_ERR, "%s() : iptc_delete_num_entry(): %s\n", logcaller, iptc_strerror(errno)); r = -1; } else if(!iptc_commit(h)) { syslog(LOG_ERR, "%s() : iptc_commit(): %s\n", logcaller, iptc_strerror(errno)); r = -1; } return r; }
/* * Takes committed rules and copies them * to structs. This is usefule to delete * the rules on exit, even if netfilter * was modified before the deletion/ * Returns: * 0 * -1 */ int store_rules() { int res; iptc_handle_t t; struct ipt_entry *r, *f, *d; res = table_init(MANGLE_TABLE, &t); if (res) { error(err_str); err_ret(ERR_NETSTO, -1); } r = (struct ipt_entry *) iptc_first_rule(CHAIN_OUTPUT, &t); f = (struct ipt_entry *) iptc_first_rule(CHAIN_POSTROUTING, &t); /* Not elegant style, but faster */ if (death_loop_rule) { d = (struct ipt_entry *) iptc_first_rule(CHAIN_PREROUTING, &t); if (r && f && d) { rr.sz = RESTORE_OUTPUT_RULE_SZ; memcpy(rr.e, r, rr.sz); rr.chain = CHAIN_OUTPUT; fr.sz = NTK_FORWARD_RULE_SZ; memcpy(fr.e, f, fr.sz); fr.chain = CHAIN_POSTROUTING; dr.sz = IGW_FILTER_RULE_SZ; memcpy(dr.e, d, dr.sz); dr.chain = CHAIN_PREROUTING; error("This is store_rules, And the value of t is: %p", t); commit_rules(&t); return 0; } else { error("This is store_rules else, And the value of t is: %p", t); commit_rules(&t); error("In store_rules: %s.", iptc_strerror(errno)); err_ret(ERR_NETSTO, -1); } } if (r && f) { rr.sz = RESTORE_OUTPUT_RULE_SZ; memcpy(rr.e, r, rr.sz); rr.chain = CHAIN_OUTPUT; fr.sz = NTK_FORWARD_RULE_SZ; memcpy(fr.e, f, fr.sz); fr.chain = CHAIN_POSTROUTING; commit_rules(&t); return 0; } commit_rules(&t); err_ret(ERR_NETSTO, -1); }
/* * append the rule -rule- on chain -chain-. * Returns: * 0 * -1 */ int append_rule(const char *rule, iptc_handle_t * t, const char *chain) { int res; res = iptc_append_entry(chain, (struct ipt_entry *) rule, t); error("res is: %d, chain: %s, rule: %s, t: %s, Errno is: %d", res, chain, rule, t, errno); if (!res) { error("In append_rule: %s.", iptc_strerror(errno)); err_ret(ERR_NETRUL, -1); } return 0; }
/* Table init: is too easy for comments. * Returns: * 0 * -1 */ int table_init(const char *table, iptc_handle_t * t) { *t = iptc_init(table); error("In table_int, t: %s and errno %d", table, errno); if (!(*t)) { error("In table_init, table %s: -> %s", table, iptc_strerror(errno)); err_ret(ERR_NETFIL, -1); } return 0; }
int do_append_nat_entry(struct iptargs *ipt,struct ipt_natinfo *target) { int ret; unsigned short size; char *chain = ipt->chain; struct ipt_entry *entry; struct iptc_handle *handle = iptc_init(ipt->table); size = sizeof(*target); entry = malloc(sizeof(struct ipt_entry)+target->t.target_size); memset(entry, 0, sizeof(struct ipt_entry)+target->t.target_size); iptargs_to_ipt_entry(ipt,entry); printf("%s\n", target->t.name); //memcpy(entry->elems, &, sizeof(unsigned short)); //memcpy(entry->elems+sizeof(unsigned short), target, size); entry->target_offset = sizeof(struct ipt_entry); entry->next_offset = entry->target_offset + target->t.target_size; //entry->ip.flags |= IPT_SNAT_OPT_SOURCE; //target->t.revision = 1; printf("SIZE = %d %d\n", target->t.target_size, target->mr.rangesize); memcpy(entry->elems, target, target->t.target_size); ret = iptc_append_entry(chain, entry, handle); if (ret) printf("Append successfully\n"); else printf("ERROR %d %s\n", ret, iptc_strerror(ret)); ret = iptc_commit(handle); if (ret) printf("Commit successfully\n"); else printf("ERROR %d %s\n", ret, iptc_strerror(ret)); iptc_free(handle); return ret; }
/* * commit modified rules and chains. * Returns: * 0 * -1 */ int commit_rules(iptc_handle_t * t) { int res; res = iptc_commit(t); error ("This is the value of res: %i This is the value of t is: %p errno is: %d", res, t, errno); if (!res) { error("In commit_rules: %s.", iptc_strerror(errno)); err_ret(ERR_NETCOM, -1); } return 0; }
void fwd_ipt_delif(struct fwd_handle *h, const char *net) { struct iptc_handle *h_filter, *h_nat; if( !(h_filter = iptc_init("filter")) || !(h_nat = iptc_init("nat")) ) fwd_fatal("Unable to obtain libiptc handle"); fwd_log_info("Removing network %s", net); /* delete network related rules */ fwd_ipt_delif_table(h_nat, net); fwd_ipt_delif_table(h_filter, net); if( !iptc_commit(h_nat) ) fwd_fatal("Cannot commit nat table: %s", iptc_strerror(errno)); if( !iptc_commit(h_filter) ) fwd_fatal("Cannot commit filter table: %s", iptc_strerror(errno)); iptc_free(h_nat); iptc_free(h_filter); }
/* * insert the rule -rule- on chain -chain- * at the position pos. * Returns: * 0 * -1 */ int insert_rule(const char *rule, iptc_handle_t * t, const char *chain, int pos) { int res; res = iptc_insert_entry(chain, (struct ipt_entry *) rule, 0, t); error ("res is: %d rule is: %p chain is: %s pos is: %d t is: %p errno is: %d", res, rule, chain, pos, t, errno); if (!res) { error("In insert_rule: %s.", iptc_strerror(errno)); err_ret(ERR_NETRUL, -1); } return 0; }
/* delete the first rule of a chain. * Unused. */ int delete_first_rule(iptc_handle_t * t, const char *chain) { int res; const struct ipt_entry *e; e = iptc_first_rule(chain, t); if (!e) return 0; res = iptc_delete_num_entry(chain, 0, t); if (!res) goto cannot_delete; return 0; cannot_delete: error("In delete_first_rule: -> %s", iptc_strerror(errno)); err_ret(ERR_NETDEL, -1); }
static int do_iptables(int argc, char* argv[]) { char *table = "filter"; int ret = 0; if(!find_table(argc, argv)) return 0; #ifdef IP6T ret = do_command6(argc, argv, &table, ¤t_table->handle, true); if (!ret) { fprintf(stderr, "line %d: %s\n", current_line, ip6tc_strerror(errno)); } else { if(!table || strcmp(table, current_table->name)) { fprintf(stderr, "line %d: expected table %s, got %s\n", current_line, current_table->name, table); exit(1); } } #else ret = do_command4(argc, argv, &table, ¤t_table->handle, true); if (!ret) { fprintf(stderr, "line %d: %s\n", current_line, iptc_strerror(errno)); } else { if(!table || strcmp(table, current_table->name)) { fprintf(stderr, "line %d: expected table %s, got %s\n", current_line, current_table->name, table); exit(1); } } #endif return ret; }
int ip4tables_close ( struct iptc_handle* handle, int updated ) { int res = 1; int sav_errno ; if (updated) { if ( ( res = iptc_commit ( handle ) ) != 1 ) { sav_errno = errno ; log_message(LOG_INFO, "iptc_commit returned %d: %s", res, iptc_strerror (sav_errno) ); } } iptc_free ( handle ) ; if ( res == 1 ) return 0 ; else return ( sav_errno ) ; }
int delete_ntk_forward_chain(iptc_handle_t * t) { int res; res = iptc_is_chain(NTK_MARK_CHAIN, *t); if (!res) return 0; res = iptc_flush_entries(NTK_MARK_CHAIN, t); if (!res) goto cannot_delete; res = iptc_delete_chain(NTK_MARK_CHAIN, t); if (!res) goto cannot_delete; return 0; cannot_delete: error("In delete_ntk_forward_chain: -> %s", iptc_strerror(errno)); err_ret(ERR_NETDEL, -1); }
/* * Build the chain ntk_mark_chain on * mangle table. */ int ntk_mark_chain_init(iptc_handle_t * t) { int res; res = iptc_is_chain(NTK_MARK_CHAIN, *t); if (res) { debug(DBG_NORMAL, "In mark_init: bizarre, ntk mangle" "chain is present yet. it will be flushed."); res = iptc_flush_entries(NTK_MARK_CHAIN, t); if (!res) goto dontwork; } else { res = iptc_create_chain(NTK_MARK_CHAIN, t); if (!res) goto dontwork; } return 0; dontwork: error("In ntk_mark_chain_init: -> %s", iptc_strerror(errno)); err_ret(ERR_NETCHA, -1) }
/* delete_redirect_and_filter_rules() */ int delete_redirect_and_filter_rules(unsigned short eport, int proto) { int r = -1; unsigned index = 0; unsigned i = 0; iptc_handle_t h; const struct ipt_entry * e; const struct ipt_entry_match *match; h = iptc_init("nat"); if(!h) { syslog(LOG_ERR, "delete_redirect_and_filter_rules() : " "iptc_init() failed : %s", iptc_strerror(errno)); return -1; } if(!iptc_is_chain(miniupnpd_chain, h)) { syslog(LOG_ERR, "chain %s not found", miniupnpd_chain); } else { for(e = iptc_first_rule(miniupnpd_chain, &h); e; e = iptc_next_rule(e, &h), i++) { if(proto==e->ip.proto) { match = (const struct ipt_entry_match *)&e->elems; if(0 == strncmp(match->u.user.name, "tcp", IPT_FUNCTION_MAXNAMELEN)) { const struct ipt_tcp * info; info = (const struct ipt_tcp *)match->data; if(eport != info->dpts[0]) continue; } else { const struct ipt_udp * info; info = (const struct ipt_udp *)match->data; if(eport != info->dpts[0]) continue; } index = i; r = 0; break; } } } iptc_free(&h); if(r == 0) { syslog(LOG_INFO, "Trying to delete rules at index %u", index); /* Now delete both rules */ h = iptc_init("nat"); if(h) { r = delete_rule_and_commit(index, &h, "delete_redirect_rule"); } h = iptc_init("filter"); if(h && (r == 0)) { r = delete_rule_and_commit(index, &h, "delete_filter_rule"); } } del_redirect_desc(eport, proto); return r; }
/* get_redirect_rule_by_index() * return -1 when the rule was not found */ int get_redirect_rule_by_index(int index, char * ifname, unsigned short * eport, char * iaddr, int iaddrlen, unsigned short * iport, int * proto, char * desc, int desclen, u_int64_t * packets, u_int64_t * bytes) { int r = -1; int i = 0; iptc_handle_t h; const struct ipt_entry * e; const struct ipt_entry_target * target; const struct ip_nat_multi_range * mr; const struct ipt_entry_match *match; h = iptc_init("nat"); if(!h) { syslog(LOG_ERR, "get_redirect_rule_by_index() : " "iptc_init() failed : %s", iptc_strerror(errno)); return -1; } if(!iptc_is_chain(miniupnpd_chain, h)) { syslog(LOG_ERR, "chain %s not found", miniupnpd_chain); } else { for(e = iptc_first_rule(miniupnpd_chain, &h); e; e = iptc_next_rule(e, &h)) { if(i==index) { *proto = e->ip.proto; match = (const struct ipt_entry_match *)&e->elems; if(0 == strncmp(match->u.user.name, "tcp", IPT_FUNCTION_MAXNAMELEN)) { const struct ipt_tcp * info; info = (const struct ipt_tcp *)match->data; *eport = info->dpts[0]; } else { const struct ipt_udp * info; info = (const struct ipt_udp *)match->data; *eport = info->dpts[0]; } target = (void *)e + e->target_offset; mr = (const struct ip_nat_multi_range *)&target->data[0]; snprintip(iaddr, iaddrlen, ntohl(mr->range[0].min_ip)); *iport = ntohs(mr->range[0].min.all); /*if(desc) strncpy(desc, "miniupnpd", desclen);*/ get_redirect_desc(*eport, *proto, desc, desclen); if(packets) *packets = e->counters.pcnt; if(bytes) *bytes = e->counters.bcnt; r = 0; break; } i++; } } iptc_free(&h); return r; }
static int do_output(const char *tablename) { iptc_handle_t h; const char *chain = NULL; if (!tablename) return for_each_table(&do_output); h = iptc_init(tablename); if (!h) exit_error(OTHER_PROBLEM, "Can't initialize: %s\n", iptc_strerror(errno)); if (!binary) { time_t now = time(NULL); printf("# Generated by iptables-save v%s on %s", IPTABLES_VERSION, ctime(&now)); printf("*%s\n", tablename); /* Dump out chain names first, * thereby preventing dependency conflicts */ for (chain = iptc_first_chain(&h); chain; chain = iptc_next_chain(&h)) { printf(":%s ", chain); if (iptc_builtin(chain, h)) { struct ipt_counters count; printf("%s ", iptc_get_policy(chain, &count, &h)); printf("[%llu:%llu]\n", count.pcnt, count.bcnt); } else { printf("- [0:0]\n"); } } for (chain = iptc_first_chain(&h); chain; chain = iptc_next_chain(&h)) { const struct ipt_entry *e; /* Dump out rules */ e = iptc_first_rule(chain, &h); while(e) { print_rule(e, &h, chain, counters); e = iptc_next_rule(e, &h); } } now = time(NULL); printf("COMMIT\n"); printf("# Completed on %s", ctime(&now)); } else { /* Binary, huh? OK. */ exit_error(OTHER_PROBLEM, "Binary NYI\n"); } return 1; }
int main(int argc, char *argv[]) #endif { iptc_handle_t handle = NULL; char buffer[10240]; int c; char curtable[IPT_TABLE_MAXNAMELEN + 1]; FILE *in; const char *modprobe = 0; int in_table = 0, testing = 0; program_name = "iptables-restore"; program_version = IPTABLES_VERSION; line = 0; lib_dir = getenv("IPTABLES_LIB_DIR"); if (!lib_dir) lib_dir = IPT_LIB_DIR; #ifdef NO_SHARED_LIBS init_extensions(); #endif while ((c = getopt_long(argc, argv, "bcvthnM:", options, NULL)) != -1) { switch (c) { case 'b': binary = 1; break; case 'c': counters = 1; break; case 'v': verbose = 1; break; case 't': testing = 1; break; case 'h': print_usage("iptables-restore", IPTABLES_VERSION); break; case 'n': noflush = 1; break; case 'M': modprobe = optarg; break; } } if (optind == argc - 1) { in = fopen(argv[optind], "r"); if (!in) { fprintf(stderr, "Can't open %s: %s", argv[optind], strerror(errno)); exit(1); } } else if (optind < argc) { fprintf(stderr, "Unknown arguments found on commandline"); exit(1); } else in = stdin; /* Grab standard input. */ while (fgets(buffer, sizeof(buffer), in)) { int ret = 0; line++; if (buffer[0] == '\n') continue; else if (buffer[0] == '#') { if (verbose) fputs(buffer, stdout); continue; } else if ((strcmp(buffer, "COMMIT\n") == 0) && (in_table)) { if (!testing) { DEBUGP("Calling commit\n"); ret = iptc_commit(&handle); } else { DEBUGP("Not calling commit, testing\n"); ret = 1; } in_table = 0; } else if ((buffer[0] == '*') && (!in_table)) { /* New table */ char *table; table = strtok(buffer+1, " \t\n"); DEBUGP("line %u, table '%s'\n", line, table); if (!table) { exit_error(PARAMETER_PROBLEM, "%s: line %u table name invalid\n", program_name, line); exit(1); } strncpy(curtable, table, IPT_TABLE_MAXNAMELEN); curtable[IPT_TABLE_MAXNAMELEN] = '\0'; if (handle) iptc_free(&handle); handle = create_handle(table, modprobe); if (noflush == 0) { DEBUGP("Cleaning all chains of table '%s'\n", table); for_each_chain(flush_entries, verbose, 1, &handle); DEBUGP("Deleting all user-defined chains " "of table '%s'\n", table); for_each_chain(delete_chain, verbose, 0, &handle) ; } ret = 1; in_table = 1; } else if ((buffer[0] == ':') && (in_table)) { /* New chain. */ char *policy, *chain; chain = strtok(buffer+1, " \t\n"); DEBUGP("line %u, chain '%s'\n", line, chain); if (!chain) { exit_error(PARAMETER_PROBLEM, "%s: line %u chain name invalid\n", program_name, line); exit(1); } if (iptc_builtin(chain, handle) <= 0) { if (noflush && iptc_is_chain(chain, handle)) { DEBUGP("Flushing existing user defined chain '%s'\n", chain); if (!iptc_flush_entries(chain, &handle)) exit_error(PARAMETER_PROBLEM, "error flushing chain " "'%s':%s\n", chain, strerror(errno)); } 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)); } } policy = strtok(NULL, " \t\n"); DEBUGP("line %u, policy '%s'\n", line, policy); if (!policy) { exit_error(PARAMETER_PROBLEM, "%s: line %u policy invalid\n", program_name, line); exit(1); } if (strcmp(policy, "-") != 0) { struct ipt_counters count; if (counters) { char *ctrs; ctrs = strtok(NULL, " \t\n"); if (!ctrs || !parse_counters(ctrs, &count)) exit_error(PARAMETER_PROBLEM, "invalid policy counters " "for chain '%s'\n", chain); } else { memset(&count, 0, sizeof(struct ipt_counters)); } DEBUGP("Setting policy of chain %s to %s\n", chain, policy); if (!iptc_set_policy(chain, policy, &count, &handle)) exit_error(OTHER_PROBLEM, "Can't set policy `%s'" " on `%s' line %u: %s\n", chain, policy, line, iptc_strerror(errno)); } ret = 1; } else if (in_table) { int a; char *ptr = buffer; char *pcnt = NULL; char *bcnt = NULL; char *parsestart; /* the parser */ char *param_start, *curchar; int quote_open; /* reset the newargv */ newargc = 0; if (buffer[0] == '[') { /* we have counters in our input */ ptr = strchr(buffer, ']'); if (!ptr) exit_error(PARAMETER_PROBLEM, "Bad line %u: need ]\n", line); pcnt = strtok(buffer+1, ":"); if (!pcnt) exit_error(PARAMETER_PROBLEM, "Bad line %u: need :\n", line); bcnt = strtok(NULL, "]"); if (!bcnt) exit_error(PARAMETER_PROBLEM, "Bad line %u: need ]\n", line); /* start command parsing after counter */ parsestart = ptr + 1; } else { /* start command parsing at start of line */ parsestart = buffer; } add_argv(argv[0]); add_argv("-t"); add_argv((char *) &curtable); if (counters && pcnt && bcnt) { add_argv("--set-counters"); add_argv((char *) pcnt); add_argv((char *) bcnt); } /* After fighting with strtok enough, here's now * a 'real' parser. According to Rusty I'm now no * longer a real hacker, but I can live with that */ quote_open = 0; param_start = parsestart; for (curchar = parsestart; *curchar; curchar++) { if (*curchar == '"') { /* quote_open cannot be true if there * was no previous character. Thus, * curchar-1 has to be within bounds */ if (quote_open && *(curchar-1) != '\\') { quote_open = 0; *curchar = ' '; } else { quote_open = 1; param_start++; } } if (*curchar == ' ' || *curchar == '\t' || * curchar == '\n') { char param_buffer[1024]; int param_len = curchar-param_start; if (quote_open) continue; if (!param_len) { /* two spaces? */ param_start++; continue; } /* end of one parameter */ strncpy(param_buffer, param_start, param_len); *(param_buffer+param_len) = '\0'; /* check if table name specified */ if (!strncmp(param_buffer, "-t", 3) || !strncmp(param_buffer, "--table", 8)) { exit_error(PARAMETER_PROBLEM, "Line %u seems to have a " "-t table option.\n", line); exit(1); } add_argv(param_buffer); param_start += param_len + 1; } else { /* regular character, skip */ } } DEBUGP("calling do_command(%u, argv, &%s, handle):\n", newargc, curtable); for (a = 0; a < newargc; a++) DEBUGP("argv[%u]: %s\n", a, newargv[a]); ret = do_command(newargc, newargv, &newargv[2], &handle); free_argv(); } if (!ret) { fprintf(stderr, "%s: line %u failed\n", program_name, line); exit(1); } } if (in_table) { fprintf(stderr, "%s: COMMIT expected at line %u\n", program_name, line + 1); exit(1); } return 0; }
static int for_save_table() { int ret = 1; FILE *procfile = NULL; char tablename[] ="filter"; const char *returnvalue =NULL; time_t now = time(NULL); const char *target_name; procfile = fopen("/data/ip_tables_save_temp", "w+"); if (!procfile) return ret; struct iptc_handle *h; const char *chain = NULL; h = iptc_init(tablename); if (h == NULL) { xtables_load_ko(xtables_modprobe_program, false); h = iptc_init(tablename); } if (!h) xtables_error(OTHER_PROBLEM, "Cannot initialize: %s\n", iptc_strerror(errno)); printf("# for_save_table...LGE \n"); /* Dump out chain names first, * thereby preventing dependency conflicts */ for (chain = iptc_first_chain(h); chain; chain = iptc_next_chain(h)) { const struct ipt_entry *e; printf(":%s\n ", chain); if(!strcmp(chain,"OUTPUT")){ /* Dump out rules */ e = iptc_first_rule(chain, h); while(e) { target_name = iptc_get_target(e, h); if(!strcmp(target_name,"DROP")){ printf("target :%s\n ", target_name); printf("out_iface :%s\n ", e->ip.outiface); fprintf(procfile,"%s\t%s\n", target_name, e->ip.outiface); } e = iptc_next_rule(e, h); } } } //fputs(returnvalue, procfile); iptc_free(h); fclose(procfile); return ret; }
/* delete_redirect_and_filter_rules() */ int delete_redirect_and_filter_rules(unsigned short eport, int proto) { int r = -1, r2 = -1; unsigned index = 0; unsigned i = 0; IPTC_HANDLE h; const struct ipt_entry * e; const struct ipt_entry_target * target; const struct ip_nat_multi_range * mr; const struct ipt_entry_match *match; unsigned short iport = 0; uint32_t iaddr = 0; h = iptc_init("nat"); if(!h) { syslog(LOG_ERR, "delete_redirect_and_filter_rules() : " "iptc_init() failed : %s", iptc_strerror(errno)); return -1; } /* First step : find the right nat rule */ if(!iptc_is_chain(miniupnpd_nat_chain, h)) { syslog(LOG_ERR, "chain %s not found", miniupnpd_nat_chain); } else { #ifdef IPTABLES_143 for(e = iptc_first_rule(miniupnpd_nat_chain, h); e; e = iptc_next_rule(e, h), i++) #else for(e = iptc_first_rule(miniupnpd_nat_chain, &h); e; e = iptc_next_rule(e, &h), i++) #endif { if(proto==e->ip.proto) { match = (const struct ipt_entry_match *)&e->elems; if(0 == strncmp(match->u.user.name, "tcp", IPT_FUNCTION_MAXNAMELEN)) { const struct ipt_tcp * info; info = (const struct ipt_tcp *)match->data; if(eport != info->dpts[0]) continue; } else { const struct ipt_udp * info; info = (const struct ipt_udp *)match->data; if(eport != info->dpts[0]) continue; } /* get the index, the internal address and the internal port * of the rule */ index = i; target = (void *)e + e->target_offset; mr = (const struct ip_nat_multi_range *)&target->data[0]; iaddr = mr->range[0].min_ip; iport = ntohs(mr->range[0].min.all); r = 0; break; } } } if(h) #ifdef IPTABLES_143 iptc_free(h); #else iptc_free(&h); #endif if(r == 0) { syslog(LOG_INFO, "Trying to delete nat rule at index %u", index); /* Now delete both rules */ /* first delete the nat rule */ h = iptc_init("nat"); if(h) { r = delete_rule_and_commit(index, h, miniupnpd_nat_chain, "delete_redirect_rule"); } if((r == 0) && (h = iptc_init("filter"))) { i = 0; /* we must find the right index for the filter rule */ #ifdef IPTABLES_143 for(e = iptc_first_rule(miniupnpd_forward_chain, h); e; e = iptc_next_rule(e, h), i++) #else for(e = iptc_first_rule(miniupnpd_forward_chain, &h); e; e = iptc_next_rule(e, &h), i++) #endif { if(proto==e->ip.proto) { match = (const struct ipt_entry_match *)&e->elems; /*syslog(LOG_DEBUG, "filter rule #%u: %s %s", i, match->u.user.name, inet_ntoa(e->ip.dst));*/ if(0 == strncmp(match->u.user.name, "tcp", IPT_FUNCTION_MAXNAMELEN)) { const struct ipt_tcp * info; info = (const struct ipt_tcp *)match->data; if(iport != info->dpts[0]) continue; } else { const struct ipt_udp * info; info = (const struct ipt_udp *)match->data; if(iport != info->dpts[0]) continue; } if(iaddr != e->ip.dst.s_addr) continue; index = i; syslog(LOG_INFO, "Trying to delete filter rule at index %u", index); r = delete_rule_and_commit(index, h, miniupnpd_forward_chain, "delete_filter_rule"); h = NULL; break; } } } if(h) #ifdef IPTABLES_143 iptc_free(h); #else iptc_free(&h); #endif } /*delete PEER rule*/ if((h = iptc_init("nat"))) { i = 0; /* we must find the right index for the filter rule */ #ifdef IPTABLES_143 for(e = iptc_first_rule(miniupnpd_peer_chain, h); e; e = iptc_next_rule(e, h), i++) #else for(e = iptc_first_rule(miniupnpd_peer_chain, &h); e; e = iptc_next_rule(e, &h), i++) #endif { if(proto==e->ip.proto) { target = (void *)e + e->target_offset; mr = (const struct ip_nat_multi_range *)&target->data[0]; if (eport != ntohs(mr->range[0].min.all)) { continue; } iaddr = e->ip.src.s_addr; match = (const struct ipt_entry_match *)&e->elems; if(0 == strncmp(match->u.user.name, "tcp", IPT_FUNCTION_MAXNAMELEN)) { const struct ipt_tcp * info; info = (const struct ipt_tcp *)match->data; iport = info->spts[0]; } else { const struct ipt_udp * info; info = (const struct ipt_udp *)match->data; iport = info->dpts[0]; } index = i; syslog(LOG_INFO, "Trying to delete peer rule at index %u", index); r2 = delete_rule_and_commit(index, h, miniupnpd_peer_chain, "delete_peer_rule"); h = NULL; break; } } } if(h) #ifdef IPTABLES_143 iptc_free(h); #else iptc_free(&h); #endif /*delete DSCP rule*/ if((r2==0)&&(h = iptc_init("mangle"))) { i = 0; index = -1; /* we must find the right index for the filter rule */ #ifdef IPTABLES_143 for(e = iptc_first_rule(miniupnpd_nat_chain, h); e; e = iptc_next_rule(e, h), i++) #else for(e = iptc_first_rule(miniupnpd_nat_chain, &h); e; e = iptc_next_rule(e, &h), i++) #endif { if(proto==e->ip.proto) { match = (const struct ipt_entry_match *)&e->elems; /*syslog(LOG_DEBUG, "filter rule #%u: %s %s", i, match->u.user.name, inet_ntoa(e->ip.dst));*/ if(0 == strncmp(match->u.user.name, "tcp", IPT_FUNCTION_MAXNAMELEN)) { const struct ipt_tcp * info; info = (const struct ipt_tcp *)match->data; if(iport != info->spts[0]) continue; } else { const struct ipt_udp * info; info = (const struct ipt_udp *)match->data; if(iport != info->spts[0]) continue; } if(iaddr != e->ip.src.s_addr) continue; index = i; syslog(LOG_INFO, "Trying to delete dscp rule at index %u", index); r2 = delete_rule_and_commit(index, h, miniupnpd_nat_chain, "delete_dscp_rule"); h = NULL; break; } } if (h) #ifdef IPTABLES_143 iptc_free(h); #else iptc_free(&h); #endif } del_redirect_desc(eport, proto); return r*r2; }
/* get_peer_rule_by_index() * return -1 when the rule was not found */ int get_peer_rule_by_index(int index, char * ifname, unsigned short * eport, char * iaddr, int iaddrlen, unsigned short * iport, int * proto, char * desc, int desclen, char * rhost, int rhostlen, unsigned short * rport, unsigned int * timestamp, u_int64_t * packets, u_int64_t * bytes) { int r = -1; #if USE_INDEX_FROM_DESC_LIST && 0 r = get_redirect_desc_by_index(index, eport, proto, desc, desclen, timestamp); if (r==0) { r = get_redirect_rule(ifname, *eport, *proto, iaddr, iaddrlen, iport, 0, 0, packets, bytes); } #else int i = 0; IPTC_HANDLE h; const struct ipt_entry * e; const struct ipt_entry_target * target; const struct ip_nat_multi_range * mr; const struct ipt_entry_match *match; UNUSED(ifname); h = iptc_init("nat"); if(!h) { syslog(LOG_ERR, "get_peer_rule_by_index() : " "iptc_init() failed : %s", iptc_strerror(errno)); return -1; } if(!iptc_is_chain(miniupnpd_peer_chain, h)) { syslog(LOG_ERR, "chain %s not found", miniupnpd_peer_chain); } else { #ifdef IPTABLES_143 for(e = iptc_first_rule(miniupnpd_peer_chain, h); e; e = iptc_next_rule(e, h)) #else for(e = iptc_first_rule(miniupnpd_peer_chain, &h); e; e = iptc_next_rule(e, &h)) #endif { if(i==index) { *proto = e->ip.proto; match = (const struct ipt_entry_match *)&e->elems; if(0 == strncmp(match->u.user.name, "tcp", IPT_FUNCTION_MAXNAMELEN)) { const struct ipt_tcp * info; info = (const struct ipt_tcp *)match->data; if (rport) *rport = info->dpts[0]; if (iport) *iport = info->spts[0]; } else { const struct ipt_udp * info; info = (const struct ipt_udp *)match->data; if (rport) *rport = info->dpts[0]; if (iport) *iport = info->spts[0]; } target = (void *)e + e->target_offset; mr = (const struct ip_nat_multi_range *)&target->data[0]; *eport = ntohs(mr->range[0].min.all); get_redirect_desc(*eport, *proto, desc, desclen, timestamp); if(packets) *packets = e->counters.pcnt; if(bytes) *bytes = e->counters.bcnt; /* rhost */ if(rhost && rhostlen > 0) { if(e->ip.dst.s_addr) { snprintip(rhost, rhostlen, ntohl(e->ip.dst.s_addr)); } else { rhost[0] = '\0'; } } if(iaddr && iaddrlen > 0) { if(e->ip.src.s_addr) { snprintip(iaddr, iaddrlen, ntohl(e->ip.src.s_addr)); } else { rhost[0] = '\0'; } } r = 0; break; } i++; } } if(h) #ifdef IPTABLES_143 iptc_free(h); #else iptc_free(&h); #endif #endif return r; }
int get_nat_redirect_rule(const char * nat_chain_name, const char * ifname, unsigned short eport, int proto, char * iaddr, int iaddrlen, unsigned short * iport, char * desc, int desclen, char * rhost, int rhostlen, unsigned int * timestamp, u_int64_t * packets, u_int64_t * bytes) { int r = -1; IPTC_HANDLE h; const struct ipt_entry * e; const struct ipt_entry_target * target; const struct ip_nat_multi_range * mr; const struct ipt_entry_match *match; UNUSED(ifname); h = iptc_init("nat"); if(!h) { syslog(LOG_ERR, "get_redirect_rule() : " "iptc_init() failed : %s", iptc_strerror(errno)); return -1; } if(!iptc_is_chain(nat_chain_name, h)) { syslog(LOG_ERR, "chain %s not found", nat_chain_name); } else { #ifdef IPTABLES_143 for(e = iptc_first_rule(nat_chain_name, h); e; e = iptc_next_rule(e, h)) #else for(e = iptc_first_rule(nat_chain_name, &h); e; e = iptc_next_rule(e, &h)) #endif { if(proto==e->ip.proto) { match = (const struct ipt_entry_match *)&e->elems; if(0 == strncmp(match->u.user.name, "tcp", IPT_FUNCTION_MAXNAMELEN)) { const struct ipt_tcp * info; info = (const struct ipt_tcp *)match->data; if(eport != info->dpts[0]) continue; } else { const struct ipt_udp * info; info = (const struct ipt_udp *)match->data; if(eport != info->dpts[0]) continue; } target = (void *)e + e->target_offset; /* target = ipt_get_target(e); */ mr = (const struct ip_nat_multi_range *)&target->data[0]; snprintip(iaddr, iaddrlen, ntohl(mr->range[0].min_ip)); *iport = ntohs(mr->range[0].min.all); get_redirect_desc(eport, proto, desc, desclen, timestamp); if(packets) *packets = e->counters.pcnt; if(bytes) *bytes = e->counters.bcnt; /* rhost */ if(e->ip.src.s_addr && rhost) { snprintip(rhost, rhostlen, ntohl(e->ip.src.s_addr)); } r = 0; break; } } } if(h) #ifdef IPTABLES_143 iptc_free(h); #else iptc_free(&h); #endif return r; }
/* return an (malloc'ed) array of "external" port for which there is * a port mapping. number is the size of the array */ unsigned short * get_portmappings_in_range(unsigned short startport, unsigned short endport, int proto, unsigned int * number) { unsigned short * array; unsigned int capacity; unsigned short eport; IPTC_HANDLE h; const struct ipt_entry * e; const struct ipt_entry_match *match; *number = 0; capacity = 128; array = calloc(capacity, sizeof(unsigned short)); if(!array) { syslog(LOG_ERR, "get_portmappings_in_range() : calloc error"); return NULL; } h = iptc_init("nat"); if(!h) { syslog(LOG_ERR, "get_redirect_rule_by_index() : " "iptc_init() failed : %s", iptc_strerror(errno)); free(array); return NULL; } if(!iptc_is_chain(miniupnpd_nat_chain, h)) { syslog(LOG_ERR, "chain %s not found", miniupnpd_nat_chain); free(array); array = NULL; } else { #ifdef IPTABLES_143 for(e = iptc_first_rule(miniupnpd_nat_chain, h); e; e = iptc_next_rule(e, h)) #else for(e = iptc_first_rule(miniupnpd_nat_chain, &h); e; e = iptc_next_rule(e, &h)) #endif { if(proto == e->ip.proto) { match = (const struct ipt_entry_match *)&e->elems; if(0 == strncmp(match->u.user.name, "tcp", IPT_FUNCTION_MAXNAMELEN)) { const struct ipt_tcp * info; info = (const struct ipt_tcp *)match->data; eport = info->dpts[0]; } else { const struct ipt_udp * info; info = (const struct ipt_udp *)match->data; eport = info->dpts[0]; } if(startport <= eport && eport <= endport) { if(*number >= capacity) { unsigned short * tmp; /* need to increase the capacity of the array */ tmp = realloc(array, sizeof(unsigned short)*capacity); if(!tmp) { syslog(LOG_ERR, "get_portmappings_in_range() : realloc(%u) error", (unsigned)sizeof(unsigned short)*capacity); *number = 0; free(array); array = NULL; break; } array = tmp; } array[*number] = eport; (*number)++; } } } } if(h) #ifdef IPTABLES_143 iptc_free(h); #else iptc_free(&h); #endif return array; }