/* 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 void fwd_ipt_delif_table(struct iptc_handle *h, const char *net) { const struct xt_entry_match *m; const struct ipt_entry *e; const char *chain, *comment; size_t off = 0, num = 0; /* iterate chains */ for( chain = iptc_first_chain(h); chain; chain = iptc_next_chain(h) ) { /* iterate rules */ for( e = iptc_first_rule(chain, h), num = 0; e; e = iptc_next_rule(e, h), num++ ) { repeat_rule: /* skip entries w/o matches */ if( ! e->target_offset ) continue; /* iterate matches */ for( off = sizeof(struct ipt_entry); off < e->target_offset; off += m->u.match_size ) { m = (void *)e + off; /* yay */ if( ! strcmp(m->u.user.name, "comment") ) { /* better use struct_xt_comment_info but well... */ comment = (void *)m + sizeof(struct xt_entry_match); if( fwd_r_cmp("net=", comment, net) ) { e = iptc_next_rule(e, h); iptc_delete_num_entry(chain, num, h); if( e != NULL ) goto repeat_rule; else break; } } } } } }
/* * Delete rule -rule.rule- on chain rule.chain. * Returns * 0 if deletion is Ok or if nothing * has to be deleted * -1 error */ int delete_rule(rule_store * rule, iptc_handle_t * t) { int pos, res; pos = rule_position(rule, t); if (pos == -1) { debug(DBG_NORMAL, "No rule in %s to be deleted.", rule->chain); return 0; } res = iptc_delete_num_entry(rule->chain, pos, t); if (!res) { debug(DBG_NORMAL, "Unable to delete rule in chain %s.", rule->chain); err_ret(ERR_NETDEL, -1); } return 0; }
/* delete the first rule of a chain. * Unused. */ int delete_first_rule(iptc_handle_t * t, const char *chain) { int res; const struct ipt_entry *e; e = iptc_first_rule(chain, t); if (!e) return 0; res = iptc_delete_num_entry(chain, 0, t); if (!res) goto cannot_delete; return 0; cannot_delete: error("In delete_first_rule: -> %s", iptc_strerror(errno)); err_ret(ERR_NETDEL, -1); }
/* 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; }
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"); }