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); }
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; }
//TODO:print interface name int do_list_entries(struct iptargs *ipt) { struct iptc_handle *handle; handle = iptc_init(ipt->table); const char *this; for (this=iptc_first_chain(handle); this; this=iptc_next_chain(handle)) { const struct ipt_entry *i; unsigned int num; if (ipt->chain && strcmp(ipt->chain, this) != 0) continue; print_header(this, handle); i = iptc_first_rule(this, handle); num = 0; while (i) { num++; printf("%d\t | ", num); print_entry(this, i, handle); i = iptc_next_rule(i, handle); } } iptc_free(handle); 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; }
/* 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; }
/* Initializes a new iptables instance and returns an iptables resource associated with the new iptables table */ struct iptc_handle* ip4tables_open ( const char* tablename ) { struct iptc_handle *h ; if ( !( h = iptc_init ( tablename ) ) ) return NULL ; return h ; }
iptc_handle_t create_handle(const char *tablename, const char* modprobe ) { iptc_handle_t handle; handle = iptc_init(tablename); if (!handle) { /* try to insmod the module if iptc_init failed */ iptables_insmod("ip_tables", modprobe); handle = iptc_init(tablename); } if (!handle) { exit_error(PARAMETER_PROBLEM, "%s: unable to initialize" "table '%s'\n", program_name, tablename); exit(1); } return handle; }
static struct xtc_handle *create_handle(const char *tablename) { struct xtc_handle *handle; handle = iptc_init(tablename); if (!handle) { /* try to insmod the module if iptc_init failed */ xtables_load_ko(xtables_modprobe_program, false); handle = iptc_init(tablename); } if (!handle) { xtables_error(PARAMETER_PROBLEM, "%s: unable to initialize " "table '%s'\n", prog_name, tablename); exit(1); } return handle; }
int do_flush_entries(struct iptargs *ipt) { struct iptc_handle *handle; handle = iptc_init(ipt->table); printf("ipt->chain=%s\n",ipt->chain); if (!ipt->chain){ const char *this; for (this=iptc_first_chain(handle); this; this=iptc_next_chain(handle)) { iptc_flush_entries(this, handle); } } else {
/* 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; }
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); } }
int fetch_counts(const char *chain, struct iptable_data *dp, int max) { unsigned int num = 0; const char *thischain; const struct ipt_entry *ipt; struct iptc_handle *handle; handle = iptc_init("mangle"); if(handle) { for (thischain = iptc_first_chain(handle); thischain; thischain = iptc_next_chain(handle)) { if(!strcmp(thischain, chain)) { // go through rules in this chain for (ipt = iptc_first_rule(thischain, handle),num=0; ipt; ipt = iptc_next_rule(ipt, handle),num++) { if(!ipt || num >= max) break; dp->pcnt = ipt->counters.pcnt; dp->bcnt = ipt->counters.bcnt; strncpy(dp->iniface, ipt->ip.iniface, IFNAMSIZ); strncpy(dp->outiface, ipt->ip.outiface, IFNAMSIZ); dp->src.s_addr = ipt->ip.src.s_addr; dp->dst.s_addr = ipt->ip.dst.s_addr; dp->smsk.s_addr = ipt->ip.smsk.s_addr; dp->dmsk.s_addr = ipt->ip.dmsk.s_addr; dp->proto = ipt->ip.proto; dp++; // on to next } break; // no need to look at other chains } } iptc_free(handle); } // number of rules matched if == max then there may be more return (num); }
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_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 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); }
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; }
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); }
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; }
/* 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 genIPTablesRules(const std::string &filter, QueryData &results) { Row r; r["filter_name"] = filter; // Initialize the access to iptc auto handle = (struct iptc_handle *)iptc_init(filter.c_str()); if (handle == nullptr) { return; } // Iterate through chains for (auto chain = iptc_first_chain(handle); chain != nullptr; chain = iptc_next_chain(handle)) { r["chain"] = TEXT(chain); struct ipt_counters counters; auto policy = iptc_get_policy(chain, &counters, handle); if (policy != nullptr) { r["policy"] = TEXT(policy); r["packets"] = INTEGER(counters.pcnt); r["bytes"] = INTEGER(counters.bcnt); } else { r["policy"] = ""; r["packets"] = "0"; r["bytes"] = "0"; } const struct ipt_entry *prev_rule = nullptr; // Iterating through all the rules per chain for (const struct ipt_entry *chain_rule = iptc_first_rule(chain, handle); chain_rule; chain_rule = iptc_next_rule(prev_rule, handle)) { prev_rule = chain_rule; auto target = iptc_get_target(chain_rule, handle); if (target != nullptr) { r["target"] = TEXT(target); } else { r["target"] = ""; } if (chain_rule->target_offset) { r["match"] = "yes"; // fill protocol port details parseEntryMatch(chain_rule, r); } else { r["match"] = "no"; r["src_port"] = ""; r["dst_port"] = ""; } const struct ipt_ip *ip = &chain_rule->ip; parseIpEntry(ip, r); results.push_back(r); } // Rule iteration results.push_back(r); } // Chain iteration iptc_free(handle); }
/* 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; }
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"); }
/* * 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; }