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; }
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; }
// 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; }
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); }
/* iptc_init_verify_and_append() * return 0 on success, -1 on failure */ static int iptc_init_verify_and_append(const char * table, struct ipt_entry * e, const char * logcaller) { iptc_handle_t h; h = iptc_init(table); if(!h) { syslog(LOG_ERR, "%s : iptc_init() error : %s\n", logcaller, iptc_strerror(errno)); return -1; } if(!iptc_is_chain(miniupnpd_chain, h)) { syslog(LOG_ERR, "%s : iptc_is_chain() error : %s\n", logcaller, iptc_strerror(errno)); return -1; } if(!iptc_append_entry(miniupnpd_chain, e, &h)) { syslog(LOG_ERR, "%s : iptc_append_entry() error : %s\n", logcaller, iptc_strerror(errno)); return -1; } if(!iptc_commit(&h)) { syslog(LOG_ERR, "%s : iptc_commit() error : %s\n", logcaller, iptc_strerror(errno)); return -1; } return 0; }
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); }
/* * 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); }
static void remove_inhibitor_rules(struct ipt_entry *caller_inhibitor_entry, struct ipt_entry *callee_inhibitor_entry) { struct iptc_handle *ipt_handle; unsigned char matchmask[IPTC_FULL_SIZE]; if ((ipt_handle = iptc_init("raw")) != NULL) { memset(matchmask, 255, IPTC_FULL_SIZE); // We release all rules to workaround stray rules that may remain in the // raw table after the application crashes without a chance to clean up. while(iptc_delete_entry("PREROUTING", caller_inhibitor_entry, matchmask, ipt_handle)); while(iptc_delete_entry("PREROUTING", callee_inhibitor_entry, matchmask, ipt_handle)); if (!iptc_commit(ipt_handle)) iptc_free(ipt_handle); } }
/* 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; }
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 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; }
/* * Get a list of the current firewall entries * @param fw_list list of firewall entries * @return 0 on success and errno on failure */ int netconf_get_fw(netconf_fw_t *fw_list) { const char **table; const char *chain; const struct ipt_entry *entry; struct iptc_handle *handle = NULL; /* Initialize list */ netconf_list_init(fw_list); /* Search all default tables */ for (table = &netconf_table_names[0]; *table; table++) { if (strcmp(*table, "filter") && strcmp(*table, "nat")) continue; if (!(handle = iptc_init(*table))) { fprintf(stderr, "%s\n", iptc_strerror(errno)); goto err; } /* Search all default chains */ for (chain = iptc_first_chain(handle); chain; chain = iptc_next_chain(handle)) { if (strcmp(chain, "INPUT") && strcmp(chain, "FORWARD") && strcmp(chain, "OUTPUT") && strcmp(chain, "PREROUTING") && strcmp(chain, "POSTROUTING") && strcmp(chain, "VSERVER") && strcmp(chain, "UPNP")) continue; /* Search all entries */ for (entry = iptc_first_rule(chain, handle); entry; entry = iptc_next_rule(entry, handle)) { int num = target_num(entry, handle); netconf_fw_t *fw = NULL; netconf_filter_t *filter = NULL; netconf_nat_t *nat = NULL; netconf_app_t *app = NULL; const struct ipt_entry_match *match; const struct ipt_entry_target *target; struct ipt_mac_info *mac = NULL; struct ipt_state_info *state = NULL; struct ipt_conntrack_info *conntrack = NULL; struct ipt_time_info *time = NULL; /* Only know about TCP/UDP */ if (!netconf_valid_ipproto(entry->ip.proto)) continue; /* Only know about target types in the specified tables */ if (!netconf_valid_target(num) || (netconf_table_name[num] && strncmp(netconf_table_name[num], *table, IPT_FUNCTION_MAXNAMELEN) != 0)) continue; /* Only know about specified target types */ if (netconf_valid_filter(num)) fw = (netconf_fw_t *) (filter = calloc(1, sizeof(netconf_filter_t))); else if (netconf_valid_nat(num)) fw = (netconf_fw_t *) (nat = calloc(1, sizeof(netconf_nat_t))); else if (num == NETCONF_APP) fw = (netconf_fw_t *) (app = calloc(1, sizeof(netconf_app_t))); else continue; if (!fw) { perror("calloc"); goto err; } netconf_list_add(fw, fw_list); /* Get IP addresses */ fw->match.src.ipaddr.s_addr = entry->ip.src.s_addr; fw->match.src.netmask.s_addr = entry->ip.smsk.s_addr; fw->match.dst.ipaddr.s_addr = entry->ip.dst.s_addr; fw->match.dst.netmask.s_addr = entry->ip.dmsk.s_addr; fw->match.flags |= (entry->ip.invflags & IPT_INV_SRCIP) ? NETCONF_INV_SRCIP : 0; fw->match.flags |= (entry->ip.invflags & IPT_INV_DSTIP) ? NETCONF_INV_DSTIP : 0; /* Get interface names */ strncpy(fw->match.in.name, entry->ip.iniface, IFNAMSIZ); strncpy(fw->match.out.name, entry->ip.outiface, IFNAMSIZ); fw->match.flags |= (entry->ip.invflags & IPT_INV_VIA_IN) ? NETCONF_INV_IN : 0; fw->match.flags |= (entry->ip.invflags & IPT_INV_VIA_OUT) ? NETCONF_INV_OUT : 0; fw->match.ipproto = entry->ip.proto; /* Get TCP port(s) */ if (entry->ip.proto == IPPROTO_TCP) { struct ipt_tcp *tcp = NULL; for_each_ipt_match(match, entry) { if (strncmp(match->u.user.name, "tcp", IPT_FUNCTION_MAXNAMELEN) != 0) continue; tcp = (struct ipt_tcp *) &match->data[0]; break; } if (tcp) { /* Match ports stored in host order for some stupid reason */ fw->match.src.ports[0] = htons(tcp->spts[0]); fw->match.src.ports[1] = htons(tcp->spts[1]); fw->match.dst.ports[0] = htons(tcp->dpts[0]); fw->match.dst.ports[1] = htons(tcp->dpts[1]); fw->match.flags |= (tcp->invflags & IPT_TCP_INV_SRCPT) ? NETCONF_INV_SRCPT : 0; fw->match.flags |= (tcp->invflags & IPT_TCP_INV_DSTPT) ? NETCONF_INV_DSTPT : 0; } } /* Get UDP port(s) */ else if (entry->ip.proto == IPPROTO_UDP) { struct ipt_udp *udp = NULL; for_each_ipt_match(match, entry) { if (strncmp(match->u.user.name, "udp", IPT_FUNCTION_MAXNAMELEN) != 0) continue; udp = (struct ipt_udp *) &match->data[0]; break; } if (udp) { /* Match ports stored in host order for some stupid reason */ fw->match.src.ports[0] = htons(udp->spts[0]); fw->match.src.ports[1] = htons(udp->spts[1]); fw->match.dst.ports[0] = htons(udp->dpts[0]); fw->match.dst.ports[1] = htons(udp->dpts[1]); fw->match.flags |= (udp->invflags & IPT_UDP_INV_SRCPT) ? NETCONF_INV_SRCPT : 0; fw->match.flags |= (udp->invflags & IPT_UDP_INV_DSTPT) ? NETCONF_INV_DSTPT : 0; } } /* Get source MAC address */ for_each_ipt_match(match, entry) { if (strncmp(match->u.user.name, "mac", IPT_FUNCTION_MAXNAMELEN) != 0) continue; mac = (struct ipt_mac_info *) &match->data[0]; break; } if (mac) { memcpy(fw->match.mac.octet, mac->srcaddr, ETHER_ADDR_LEN); fw->match.flags |= mac->invert ? NETCONF_INV_MAC : 0; } /* Get packet state */ for_each_ipt_match(match, entry) { if (strncmp(match->u.user.name, "state", IPT_FUNCTION_MAXNAMELEN) == 0) { state = (struct ipt_state_info *) &match->data[0]; break; } else if (strncmp(match->u.user.name, "conntrack", IPT_FUNCTION_MAXNAMELEN) == 0) { conntrack = (struct ipt_conntrack_info *) &match->data[0]; break; } } if (conntrack && (conntrack->match_flags & XT_CONNTRACK_STATE)) { fw->match.state |= (conntrack->state_mask & XT_CONNTRACK_STATE_INVALID) ? NETCONF_INVALID : 0; fw->match.state |= (conntrack->state_mask & XT_CONNTRACK_STATE_BIT(IP_CT_ESTABLISHED)) ? NETCONF_ESTABLISHED : 0; fw->match.state |= (conntrack->state_mask & XT_CONNTRACK_STATE_BIT(IP_CT_RELATED)) ? NETCONF_RELATED : 0; fw->match.state |= (conntrack->state_mask & XT_CONNTRACK_STATE_BIT(IP_CT_NEW)) ? NETCONF_NEW : 0; fw->match.state |= (conntrack->state_mask & XT_CONNTRACK_STATE_UNTRACKED) ? NETCONF_UNTRACKED : 0; fw->match.state |= (conntrack->state_mask & XT_CONNTRACK_STATE_SNAT) ? NETCONF_STATE_SNAT : 0; fw->match.state |= (conntrack->state_mask & XT_CONNTRACK_STATE_DNAT) ? NETCONF_STATE_DNAT : 0; } else if (state) { fw->match.state |= (state->statemask & IPT_STATE_INVALID) ? NETCONF_INVALID : 0; fw->match.state |= (state->statemask & IPT_STATE_BIT(IP_CT_ESTABLISHED)) ? NETCONF_ESTABLISHED : 0; fw->match.state |= (state->statemask & IPT_STATE_BIT(IP_CT_RELATED)) ? NETCONF_RELATED : 0; fw->match.state |= (state->statemask & IPT_STATE_BIT(IP_CT_NEW)) ? NETCONF_NEW : 0; } /* Get local time */ for_each_ipt_match(match, entry) { if (strncmp(match->u.user.name, "time", IPT_FUNCTION_MAXNAMELEN) != 0) continue; /* We added 8 bytes of day range at the end */ if (match->u.match_size < (IPT_ALIGN(sizeof(struct ipt_entry_match)) + IPT_ALIGN(sizeof(struct ipt_time_info) + 8))) continue; time = (struct ipt_time_info *) &match->data[0]; break; } if (time) { fw->match.days = time->weekdays_match; fw->match.secs[0] = time->daytime_start; fw->match.secs[1] = time->daytime_stop; } /* Set target type */ fw->target = num; target = (struct ipt_entry_target *) ((int) entry + entry->target_offset); /* Get filter target information */ if (filter) { if (!netconf_valid_dir(filter->dir = filter_dir(chain))) { fprintf(stderr, "error direction in %s\n", chain); goto err; } } /* Get NAT target information */ else if (nat) { struct ip_nat_multi_range *mr = (struct ip_nat_multi_range *) &target->data[0]; struct ip_nat_range *range = (struct ip_nat_range *) &mr->range[0]; /* Get mapped IP address */ nat->ipaddr.s_addr = range->min_ip; /* Get mapped TCP port(s) */ if (entry->ip.proto == IPPROTO_TCP) { nat->ports[0] = range->min.tcp.port; nat->ports[1] = range->max.tcp.port; } /* Get mapped UDP port(s) */ else if (entry->ip.proto == IPPROTO_UDP) { nat->ports[0] = range->min.udp.port; nat->ports[1] = range->max.udp.port; } } /* Get application specific port forward information */ else if (app) { struct ip_autofw_info *info = (struct ip_autofw_info *) &target->data[0]; app->proto = info->proto; app->dport[0] = info->dport[0]; app->dport[1] = info->dport[1]; app->to[0] = info->to[0]; app->to[1] = info->to[1]; } } } if (!iptc_commit(handle)) { fprintf(stderr, "%s\n", iptc_strerror(errno)); goto err; } iptc_free(handle); handle = NULL; }
static void fwd_ipt_defaults_create(struct fwd_data *d) { struct fwd_defaults *def = &d->section.defaults; 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"); /* policies */ fwd_r_set_policy(h_filter, "INPUT", def->input == FWD_P_ACCEPT ? "ACCEPT" : "DROP"); fwd_r_set_policy(h_filter, "OUTPUT", def->output == FWD_P_ACCEPT ? "ACCEPT" : "DROP"); fwd_r_set_policy(h_filter, "FORWARD", def->forward == FWD_P_ACCEPT ? "ACCEPT" : "DROP"); /* invalid state drop */ if( def->drop_invalid ) { fwd_r_drop_invalid(h_filter, "INPUT"); fwd_r_drop_invalid(h_filter, "OUTPUT"); fwd_r_drop_invalid(h_filter, "FORWARD"); } /* default accept related */ fwd_r_accept_related(h_filter, "INPUT"); fwd_r_accept_related(h_filter, "OUTPUT"); fwd_r_accept_related(h_filter, "FORWARD"); /* default accept on lo */ fwd_r_accept_lo(h_filter); /* syn flood protection */ if( def->syn_flood ) { fwd_r_add_synflood(h_filter, def); } /* rule container chains */ fwd_r_new_chain(h_filter, "mssfix"); fwd_r_new_chain(h_filter, "zones"); fwd_r_new_chain(h_filter, "rules"); fwd_r_new_chain(h_filter, "redirects"); fwd_r_new_chain(h_filter, "forwardings"); fwd_r_jump_chain(h_filter, "INPUT", "rules"); fwd_r_jump_chain(h_filter, "FORWARD", "mssfix"); fwd_r_jump_chain(h_filter, "FORWARD", "zones"); fwd_r_jump_chain(h_filter, "FORWARD", "rules"); fwd_r_jump_chain(h_filter, "FORWARD", "redirects"); fwd_r_jump_chain(h_filter, "FORWARD", "forwardings"); fwd_r_new_chain(h_nat, "zonemasq"); fwd_r_new_chain(h_nat, "redirects"); fwd_r_new_chain(h_nat, "loopback"); fwd_r_jump_chain(h_nat, "POSTROUTING", "zonemasq"); fwd_r_jump_chain(h_nat, "PREROUTING", "redirects"); fwd_r_jump_chain(h_nat, "POSTROUTING", "loopback"); /* standard drop, accept, reject chain */ fwd_r_handle_drop(h_filter); fwd_r_handle_accept(h_filter); fwd_r_handle_reject(h_filter); 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); }
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; }
void fwd_ipt_addif(struct fwd_handle *h, const char *net) { struct fwd_data *e; struct fwd_zone *z; struct fwd_rule *c; struct fwd_redirect *r; struct fwd_forwarding *f; struct fwd_cidr *a, *a2; struct fwd_network *n, *n2; struct fwd_proto p; struct fwd_xt_rule *x; struct xtables_match *m; struct xtables_target *t; 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"); if( !(z = fwd_lookup_zone(h, net)) ) return; if( !(n = fwd_lookup_network(z, net)) ) return; if( !(a = n->addr) || fwd_empty_cidr(a) ) return; fwd_log_info("Adding network %s (interface %s)", n->name, n->ifname); /* Build masquerading rule */ if( z->masq ) { if( (x = fwd_xt_init_rule(h_nat)) != NULL ) { fwd_xt_parse_out(x, n, 0); /* -o ... */ fwd_xt_get_target(x, "MASQUERADE"); /* -j MASQUERADE */ fwd_r_add_comment(x, "masq", z, n); /* -m comment ... */ fwd_xt_append_rule(x, "zonemasq"); /* -A zonemasq */ } } /* Build MSS fix rule */ if( z->mtu_fix ) { if( (x = fwd_xt_init_rule(h_filter)) != NULL ) { p.type = FWD_PR_TCP; fwd_xt_parse_out(x, n, 0); /* -o ... */ fwd_xt_parse_proto(x, &p, 0); /* -p tcp */ /* -m tcp --tcp-flags SYN,RST SYN */ if( (m = fwd_xt_get_match(x, "tcp")) != NULL ) fwd_xt_parse_match(x, m, "--tcp-flags", "SYN,RST", "SYN"); /* -j TCPMSS --clamp-mss-to-pmtu */ if( (t = fwd_xt_get_target(x, "TCPMSS")) != NULL ) fwd_xt_parse_target(x, t, "--clamp-mss-to-pmtu"); /* -m comment ... */ fwd_r_add_comment(x, "mssfix", z, n); /* -A mssfix */ fwd_xt_append_rule(x, "mssfix"); } } /* Build intra-zone forwarding rules */ for( n2 = z->networks; n2; n2 = n2->next ) { if( (a2 = n2->addr) != NULL ) { if( (x = fwd_xt_init_rule(h_filter)) != NULL ) { fwd_xt_parse_in(x, n, 0); /* -i ... */ fwd_xt_parse_out(x, n2, 0); /* -o ... */ fwd_r_add_policytarget(x, z->forward); /* -j handle_... */ fwd_r_add_comment(x, "zone", z, n); /* -m comment ... */ fwd_xt_append_rule(x, "zones"); /* -A zones */ } } } /* Build inter-zone forwarding rules */ for( e = z->forwardings; e && (f = &e->section.forwarding); e = e->next ) { for( n2 = f->dest->networks; n2; n2 = n2->next ) { /* Build forwarding rule */ if( (x = fwd_xt_init_rule(h_filter)) != NULL ) { fwd_xt_parse_in(x, n, 0); /* -i ... */ fwd_xt_parse_out(x, n2, 0); /* -o ... */ fwd_r_add_policytarget(x, FWD_P_ACCEPT); /* -j handle_... */ fwd_r_add_comment(x, "forward", z, n); /* -m comment ... */ fwd_xt_append_rule(x, "forwardings"); /* -A forwardings */ } } } /* Build DNAT rules */ for( e = z->redirects; e && (r = &e->section.redirect); e = e->next ) { /* DNAT */ if( (x = fwd_xt_init_rule(h_nat)) != NULL ) { fwd_xt_parse_in(x, n, 0); /* -i ... */ fwd_xt_parse_src(x, r->src_ip, 0); /* -s ... */ fwd_xt_parse_dest(x, a, 0); /* -d ... */ fwd_xt_parse_proto(x, r->proto, 0); /* -p ... */ fwd_r_add_sport(x, r->src_port); /* --sport ... */ fwd_r_add_dport(x, r->src_dport); /* --dport ... */ fwd_r_add_srcmac(x, r->src_mac); /* -m mac --mac-source ... */ fwd_r_add_dnattarget(x, r->dest_ip, r->dest_port); /* -j DNAT ... */ fwd_r_add_comment(x, "redir", z, n); /* -m comment ... */ fwd_xt_append_rule(x, "redirects"); /* -A redirects */ } /* Forward */ if( (x = fwd_xt_init_rule(h_filter)) != NULL ) { fwd_xt_parse_in(x, n, 0); /* -i ... */ fwd_xt_parse_src(x, r->src_ip, 0); /* -s ... */ fwd_xt_parse_dest(x, r->dest_ip, 0); /* -d ... */ fwd_xt_parse_proto(x, r->proto, 0); /* -p ... */ fwd_r_add_srcmac(x, r->src_mac); /* -m mac --mac-source ... */ fwd_r_add_sport(x, r->src_port); /* --sport ... */ fwd_r_add_dport(x, r->dest_port); /* --dport ... */ fwd_r_add_policytarget(x, FWD_P_ACCEPT); /* -j handle_accept */ fwd_r_add_comment(x, "redir", z, n); /* -m comment ... */ fwd_xt_append_rule(x, "redirects"); /* -A redirects */ } /* Add loopback rule if neither src_ip nor src_mac are defined */ if( !r->src_ip && !r->src_mac ) { if( (x = fwd_xt_init_rule(h_nat)) != NULL ) { fwd_xt_parse_in(x, n, 1); /* -i ! ... */ fwd_xt_parse_dest(x, r->dest_ip, 0); /* -d ... */ fwd_xt_parse_proto(x, r->proto, 0); /* -p ... */ fwd_r_add_sport(x, r->src_port); /* --sport ... */ fwd_r_add_dport(x, r->src_dport); /* --dport ... */ fwd_xt_get_target(x, "MASQUERADE"); /* -j MASQUERADE */ fwd_r_add_comment(x, "redir", z, n); /* -m comment ... */ fwd_xt_append_rule(x, "loopback"); /* -A loopback */ } } } /* Build rules */ for( e = z->rules; e && (c = &e->section.rule); e = e->next ) { /* Has destination, add forward rule for each network in target zone */ if( c->dest ) { for( n2 = c->dest->networks; n2; n2 = n2->next ) { if( (x = fwd_xt_init_rule(h_filter)) != NULL ) { fwd_xt_parse_in(x, n, 0); /* -i ... */ fwd_xt_parse_out(x, n2, 0); /* -o ... */ fwd_xt_parse_src(x, c->src_ip, 0); /* -s ... */ fwd_xt_parse_dest(x, c->dest_ip, 0); /* -d ... */ fwd_xt_parse_proto(x, c->proto, 0); /* -p ... */ fwd_r_add_icmptype(x, c->icmp_type); /* --icmp-type ... */ fwd_r_add_srcmac(x, c->src_mac); /* --mac-source ... */ fwd_r_add_sport(x, c->src_port); /* --sport ... */ fwd_r_add_dport(x, c->dest_port); /* --dport ... */ fwd_r_add_policytarget(x, c->target); /* -j handle_... */ fwd_r_add_comment(x, "rule", z, n); /* -m comment ... */ fwd_xt_append_rule(x, "rules"); /* -A rules */ } } } /* No destination specified, treat it as input rule */ else { if( (x = fwd_xt_init_rule(h_filter)) != NULL ) { fwd_xt_parse_in(x, n, 0); /* -i ... */ fwd_xt_parse_src(x, c->src_ip, 0); /* -s ... */ fwd_xt_parse_dest(x, c->dest_ip, 0); /* -d ... */ fwd_xt_parse_proto(x, c->proto, 0); /* -p ... */ fwd_r_add_icmptype(x, c->icmp_type); /* --icmp-type ... */ fwd_r_add_srcmac(x, c->src_mac); /* --mac-source ... */ fwd_r_add_sport(x, c->src_port); /* --sport ... */ fwd_r_add_dport(x, c->dest_port); /* --dport ... */ fwd_r_add_policytarget(x, c->target); /* -j handle_... */ fwd_r_add_comment(x, "rule", z, n); /* -m comment ... */ fwd_xt_append_rule(x, "rules"); /* -A rules */ } } } 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); }
/* iptc_init_verify_and_append() * return 0 on success, -1 on failure */ static int iptc_init_verify_and_append(const char * table, const char * miniupnpd_chain, struct ipt_entry * e, const char * logcaller) { IPTC_HANDLE h; h = iptc_init(table); if(!h) { syslog(LOG_ERR, "%s : iptc_init() error : %s\n", logcaller, iptc_strerror(errno)); return -1; } if(!iptc_is_chain(miniupnpd_chain, h)) { syslog(LOG_ERR, "%s : chain %s not found", logcaller, miniupnpd_chain); if(h) #ifdef IPTABLES_143 iptc_free(h); #else iptc_free(&h); #endif return -1; } /* iptc_insert_entry(miniupnpd_chain, e, n, h/&h) could also be used */ #ifdef IPTABLES_143 if(!iptc_append_entry(miniupnpd_chain, e, h)) #else if(!iptc_append_entry(miniupnpd_chain, e, &h)) #endif { syslog(LOG_ERR, "%s : iptc_append_entry() error : %s\n", logcaller, iptc_strerror(errno)); if(h) #ifdef IPTABLES_143 iptc_free(h); #else iptc_free(&h); #endif return -1; } #ifdef IPTABLES_143 if(!iptc_commit(h)) #else if(!iptc_commit(&h)) #endif { syslog(LOG_ERR, "%s : iptc_commit() error : %s\n", logcaller, iptc_strerror(errno)); if(h) #ifdef IPTABLES_143 iptc_free(h); #else iptc_free(&h); #endif return -1; } if(h) #ifdef IPTABLES_143 iptc_free(h); #else iptc_free(&h); #endif return 0; }
void iptc_add_rule(const char *table, const char *chain, const char *protocol, const char *iniface, const char *outiface, const char *src, const char *dest, const char *srcports, const char *destports, const char *target, const char *dnat_to, const int append) { iptc_handle_t handle; struct ipt_entry *chain_entry; struct ipt_entry_match *entry_match = NULL; struct ipt_entry_target *entry_target = NULL; ipt_chainlabel labelit; long match_size; int result = 0; chain_entry = calloc(1, sizeof(*chain_entry)); if (src) { chain_entry->ip.src.s_addr = inet_addr(src); chain_entry->ip.smsk.s_addr = inet_addr("255.255.255.255"); } if (dest) { chain_entry->ip.dst.s_addr = inet_addr(dest); chain_entry->ip.dmsk.s_addr = inet_addr("255.255.255.255"); } if (iniface) strncpy(chain_entry->ip.iniface, iniface, IFNAMSIZ); if (outiface) strncpy(chain_entry->ip.outiface, outiface, IFNAMSIZ); if (strcmp(protocol, "TCP") == 0) { chain_entry->ip.proto = IPPROTO_TCP; entry_match = get_tcp_match(srcports, destports, &chain_entry->nfcache); } else if (strcmp(protocol, "UDP") == 0) { chain_entry->ip.proto = IPPROTO_UDP; entry_match = get_udp_match(srcports, destports, &chain_entry->nfcache); } else { trace(1, "Unsupported protocol: %s", protocol); return; } if (strcmp(target, "") == 0 || strcmp(target, IPTC_LABEL_ACCEPT) == 0 || strcmp(target, IPTC_LABEL_DROP) == 0 || strcmp(target, IPTC_LABEL_QUEUE) == 0 || strcmp(target, IPTC_LABEL_RETURN) == 0) { size_t size; size = IPT_ALIGN(sizeof(struct ipt_entry_target)) + IPT_ALIGN(sizeof(int)); entry_target = calloc(1, size); entry_target->u.user.target_size = size; strncpy(entry_target->u.user.name, target, IPT_FUNCTION_MAXNAMELEN); } else if (strcmp(target, "DNAT") == 0) { entry_target = get_dnat_target(dnat_to, &chain_entry->nfcache); } if (entry_match) match_size = entry_match->u.match_size; else match_size = 0; chain_entry = realloc(chain_entry, sizeof(*chain_entry) + match_size + entry_target->u.target_size); memcpy(chain_entry->elems + match_size, entry_target, entry_target->u.target_size); chain_entry->target_offset = sizeof(*chain_entry) + match_size; chain_entry->next_offset = sizeof(*chain_entry) + match_size + entry_target->u.target_size; if (entry_match) memcpy(chain_entry->elems, entry_match, match_size); handle = iptc_init(table); if (!handle) { trace(1, "libiptc error: Can't initialize table %s, %s", table, iptc_strerror(errno)); return; } strncpy(labelit, chain, sizeof(ipt_chainlabel)); result = iptc_is_chain(chain, handle); if (!result) { trace(1, "libiptc error: Chain %s does not exist!", chain); return; } if (append) result = iptc_append_entry(labelit, chain_entry, &handle); else result = iptc_insert_entry(labelit, chain_entry, 0, &handle); if (!result) { trace(1, "libiptc error: Can't add, %s", iptc_strerror(errno)); return; } result = iptc_commit(&handle); if (!result) { trace(1, "libiptc error: Commit error, %s", iptc_strerror(errno)); return; } else trace(3, "added new rule to block successfully"); if (entry_match) free(entry_match); free(entry_target); free(chain_entry); }
void iptc_delete_rule(const char *table, const char *chain, const char *protocol, const char *iniface, const char *outiface, const char *src, const char *dest, const char *srcports, const char *destports, const char *target, const char *dnat_to) { iptc_handle_t handle; const struct ipt_entry *e; ipt_chainlabel labelit; int i, result; unsigned long int s_src = INADDR_NONE, s_dest = INADDR_NONE; if (src) s_src = inet_addr(src); if (dest) s_dest = inet_addr(dest); handle = iptc_init(table); if (!handle) { trace(1, "libiptc error: Can't initialize table %s, %s", table, iptc_strerror(errno)); return; } strncpy(labelit, chain, sizeof(ipt_chainlabel)); result = iptc_is_chain(chain, handle); if (!result) { trace(1, "libiptc error: Chain %s does not exist!", chain); return; } /* check through rules to find match */ for (e = iptc_first_rule(chain, &handle), i=0; e; e = iptc_next_rule(e, &handle), i++) { if (s_src != INADDR_NONE && e->ip.src.s_addr != s_src) continue; if (s_dest != INADDR_NONE && e->ip.dst.s_addr != s_dest) continue; if (iniface && strcmp(e->ip.iniface, iniface) != 0) continue; if (outiface && strcmp(e->ip.outiface, outiface) != 0) continue; if (protocol && strcmp(protocol, "TCP") == 0 && e->ip.proto != IPPROTO_TCP) continue; if (protocol && strcmp(protocol, "UDP") == 0 && e->ip.proto != IPPROTO_UDP) continue; if ((srcports || destports) && IPT_MATCH_ITERATE(e, matchcmp, srcports, destports) == 0) continue; if (target && strcmp(target, iptc_get_target(e, &handle)) != 0) continue; if (dnat_to && strcmp(target, "DNAT") == 0) { struct ipt_entry_target *t; struct ip_nat_multi_range *mr; struct ip_nat_range *r, range; t = (void *) e+e->target_offset; mr = (void *) &t->data; if (mr->rangesize != 1) continue; /* we have only single dnat_to target now */ r = mr->range; parse_range(dnat_to, &range); if (r->flags == range.flags && r->min_ip == range.min_ip && r->max_ip == range.max_ip && r->min.all == range.min.all && r->max.all == range.max.all) { break; } } break; } if (!e) return; result = iptc_delete_num_entry(chain, i, &handle); if (!result) { trace(1, "libiptc error: Delete error, %s", iptc_strerror(errno)); return; } result = iptc_commit(&handle); if (!result) { trace(1, "libiptc error: Commit error, %s", iptc_strerror(errno)); return; } else trace(3, "deleted rule from block successfully"); }
int main(int argc, char *argv[]) #endif { struct iptc_handle *handle = NULL; char buffer[10240]; int c; char curtable[IPT_TABLE_MAXNAMELEN + 1]; FILE *in; int in_table = 0, testing = 0; const char *tablename = NULL; line = 0; iptables_globals.program_name = "iptables-restore"; c = xtables_init_all(&iptables_globals, NFPROTO_IPV4); if (c < 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(); #endif while ((c = getopt_long(argc, argv, "bcvthnM:T:", 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': xtables_modprobe_program = optarg; break; case 'T': tablename = optarg; break; } } if (optind == argc - 1) { in = fopen(argv[optind], "r"); if (!in) { fprintf(stderr, "Can't open %s: %s\n", argv[optind], strerror(errno)); exit(1); } } else if (optind < argc) { fprintf(stderr, "Unknown arguments found on commandline\n"); 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); iptc_free(handle); handle = NULL; } 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) { xtables_error(PARAMETER_PROBLEM, "%s: line %u table name invalid\n", prog_name, line); exit(1); } strncpy(curtable, table, IPT_TABLE_MAXNAMELEN); curtable[IPT_TABLE_MAXNAMELEN] = '\0'; if (tablename && (strcmp(tablename, table) != 0)) continue; if (handle) iptc_free(handle); handle = create_handle(table); 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) { xtables_error(PARAMETER_PROBLEM, "%s: line %u chain name invalid\n", prog_name, line); exit(1); } if (strlen(chain) >= XT_EXTENSION_MAXNAMELEN) xtables_error(PARAMETER_PROBLEM, "Invalid chain name `%s' " "(%u chars max)", chain, XT_EXTENSION_MAXNAMELEN - 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)) xtables_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)) xtables_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) { xtables_error(PARAMETER_PROBLEM, "%s: line %u policy invalid\n", prog_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)) xtables_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)) xtables_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 *curchar; int quote_open, escaped; size_t param_len; /* reset the newargv */ newargc = 0; if (buffer[0] == '[') { /* we have counters in our input */ ptr = strchr(buffer, ']'); if (!ptr) xtables_error(PARAMETER_PROBLEM, "Bad line %u: need ]\n", line); pcnt = strtok(buffer+1, ":"); if (!pcnt) xtables_error(PARAMETER_PROBLEM, "Bad line %u: need :\n", line); bcnt = strtok(NULL, "]"); if (!bcnt) xtables_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; escaped = 0; param_len = 0; for (curchar = parsestart; *curchar; curchar++) { char param_buffer[1024]; if (quote_open) { if (escaped) { param_buffer[param_len++] = *curchar; escaped = 0; continue; } else if (*curchar == '\\') { escaped = 1; continue; } else if (*curchar == '"') { quote_open = 0; *curchar = ' '; } else { param_buffer[param_len++] = *curchar; continue; } } else { if (*curchar == '"') { quote_open = 1; continue; } } if (*curchar == ' ' || *curchar == '\t' || * curchar == '\n') { if (!param_len) { /* two spaces? */ continue; } param_buffer[param_len] = '\0'; /* check if table name specified */ if (!strncmp(param_buffer, "-t", 2) || !strncmp(param_buffer, "--table", 8)) { xtables_error(PARAMETER_PROBLEM, "Line %u seems to have a " "-t table option.\n", line); exit(1); } add_argv(param_buffer); param_len = 0; } else { /* regular character, copy to buffer */ param_buffer[param_len++] = *curchar; if (param_len >= sizeof(param_buffer)) xtables_error(PARAMETER_PROBLEM, "Parameter too long!"); } } 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(); fflush(stdout); } if (tablename && (strcmp(tablename, curtable) != 0)) continue; if (!ret) { fprintf(stderr, "%s: line %u failed\n", prog_name, line); exit(1); } } if (in_table) { fprintf(stderr, "%s: COMMIT expected at line %u\n", prog_name, line + 1); exit(1); } if (in != NULL) fclose(in); return 0; }
int main ( int argc, char * argv[] ) { int have_committed = 1; // prevent double commits, 'clean' state to begin with int c; program_name = argv[0]; program_name = "ipbatch CLI"; // this is really important for locating shared libs program_version = IPTABLES_VERSION; c = xtables_init_all(&iptables_globals, NFPROTO_IPV4); if (c < 0) { fprintf(stderr, "%s/%s Failed to initialize xtables\n", program_name, program_version); exit(1); } openlog( "SmoothIPSubsys", LOG_NDELAY | LOG_CONS, LOG_DAEMON ); /* lib_dir = getenv("IPTABLES_LIB_DIR");*/ /* if (!lib_dir)*/ /* lib_dir = IPT_LIB_DIR;*/ /* read lines from STDIN */ char buffer[ BUFFER_SIZE ]; int error = 0; // syslog( LOG_ERR, "Checking input" ); // there are two special commands end is the same as eof and commit // does an early commit rather than the changes only being committed at the end while ( fgets( buffer, BUFFER_SIZE - 2, stdin ) != NULL ){ /* terminate the line at the carriage return */ if ( strlen( buffer ) > BUFFER_SIZE ){ // silently ignore long lines continue; } buffer[ strlen( buffer ) - 1 ] = '\0'; //syslog( LOG_ERR, "Received command %s", buffer ); if ( strcmp( buffer, "end" ) == 0 ){ break; } if ( strcmp( buffer, "commit" ) == 0 ){ /* commit changes */ error = iptc_commit(handle); iptc_free(handle); handle = NULL; have_committed = 1; } else { /* excute the command */ if(!have_committed) { if(table_changed(buffer)) { //syslog( LOG_ERR, "Table change for %s", buffer ); error = iptc_commit(handle); iptc_free(handle); handle = NULL; have_committed = 1; } } if(*buffer) error = execute( buffer ); have_committed = 0; } if ( !error ){ /* if an error has occured then we're */ /* in trouble and might as well just */ /* leave */ syslog( LOG_ERR, "error: %s", iptc_strerror(errno)); return !error; } } //syslog( LOG_ERR, "Finished" ); /* commit the changes, that is flush */ /* the iptables buffer */ if(!have_committed) { error = iptc_commit(handle); iptc_free(handle); handle = NULL; syslog( LOG_ERR, "Unable to commit IPTables rules \"%s\"", iptc_strerror( errno ) ); } return !error; }