예제 #1
0
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);
}
예제 #2
0
파일: iptcrdr.c 프로젝트: hajuuk/asuswrt
/* delete_rule_and_commit() :
 * subfunction used in delete_redirect_and_filter_rules() */
static int
delete_rule_and_commit(unsigned int index, IPTC_HANDLE h,
                       const char * miniupnpd_chain,
                       const char * logcaller)
{
	int r = 0;
#ifdef IPTABLES_143
	if(!iptc_delete_num_entry(miniupnpd_chain, index, h))
#else
	if(!iptc_delete_num_entry(miniupnpd_chain, index, &h))
#endif
	{
		syslog(LOG_ERR, "%s() : iptc_delete_num_entry(): %s\n",
	    	   logcaller, iptc_strerror(errno));
		r = -1;
	}
#ifdef IPTABLES_143
	else if(!iptc_commit(h))
#else
	else if(!iptc_commit(&h))
#endif
	{
		syslog(LOG_ERR, "%s() : iptc_commit(): %s\n",
	    	   logcaller, iptc_strerror(errno));
		r = -1;
	}
	if(h)
#ifdef IPTABLES_143
		iptc_free(h);
#else
		iptc_free(&h);
#endif
	return r;
}
int
iptables_main(int argc, char *argv[])
{
	int ret;
	char *table = "filter";
	struct xtc_handle *handle = NULL;
    FILE *pfLockFile = NULL;

    pfLockFile = ATP_UTIL_LockProc(IPTABLES_LOCK_FILE);
    if (NULL == pfLockFile) {
        printf("iptables get lock failed\n");
        exit(-1);
    }

    ATP_UTIL_RegUnLock(pfLockFile);

	iptables_globals.program_name = "iptables";
	ret = xtables_init_all(&iptables_globals, NFPROTO_IPV4);
	if (ret < 0) {
		fprintf(stderr, "%s/%s Failed to initialize xtables\n",
				iptables_globals.program_name,
				iptables_globals.program_version);
				exit(1);
	}
#if defined(ALL_INCLUSIVE) || defined(NO_SHARED_LIBS)
	init_extensions();
	init_extensions4();
#endif

	ret = do_command4(argc, argv, &table, &handle);
	if (ret) {
		ret = iptc_commit(handle);
		iptc_free(handle);
	}

	if (!ret) {
		if (errno == EINVAL) {
			fprintf(stderr, "iptables: %s. "
					"Run `dmesg' for more information.\n",
				iptc_strerror(errno));
		} else {
			fprintf(stderr, "iptables: %s.\n",
				iptc_strerror(errno));
		}
		if (errno == EAGAIN) {
			exit(RESOURCE_PROBLEM);
		}
	}

	exit(!ret);
}
예제 #4
0
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;
}
예제 #5
0
// 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;
}
예제 #6
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;
}
예제 #7
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);
}
예제 #8
0
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;
}
예제 #9
0
/* 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;
}
예제 #10
0
파일: mark.c 프로젝트: willsure/netsukuku
/*
 * Takes committed rules and copies them
 * to structs. This is usefule to delete
 * the rules on exit, even if netfilter
 * was modified before the deletion/
 * Returns:
 * 	0
 * 	-1
 */
int
store_rules()
{
	int res;
	iptc_handle_t t;
	struct ipt_entry *r, *f, *d;

	res = table_init(MANGLE_TABLE, &t);
	if (res) {
		error(err_str);
		err_ret(ERR_NETSTO, -1);
	}
	r = (struct ipt_entry *) iptc_first_rule(CHAIN_OUTPUT, &t);
	f = (struct ipt_entry *) iptc_first_rule(CHAIN_POSTROUTING, &t);
	/* Not elegant style, but faster */
	if (death_loop_rule) {
		d = (struct ipt_entry *) iptc_first_rule(CHAIN_PREROUTING, &t);
		if (r && f && d) {
			rr.sz = RESTORE_OUTPUT_RULE_SZ;
			memcpy(rr.e, r, rr.sz);
			rr.chain = CHAIN_OUTPUT;
			fr.sz = NTK_FORWARD_RULE_SZ;
			memcpy(fr.e, f, fr.sz);
			fr.chain = CHAIN_POSTROUTING;
			dr.sz = IGW_FILTER_RULE_SZ;
			memcpy(dr.e, d, dr.sz);
			dr.chain = CHAIN_PREROUTING;
			error("This is store_rules, And the value of t is: %p", t);
			commit_rules(&t);
			return 0;
		} else {

			error("This is store_rules else, And the value of t is: %p",
				  t);
			commit_rules(&t);
			error("In store_rules: %s.", iptc_strerror(errno));
			err_ret(ERR_NETSTO, -1);
		}
	}
	if (r && f) {
		rr.sz = RESTORE_OUTPUT_RULE_SZ;
		memcpy(rr.e, r, rr.sz);
		rr.chain = CHAIN_OUTPUT;
		fr.sz = NTK_FORWARD_RULE_SZ;
		memcpy(fr.e, f, fr.sz);
		fr.chain = CHAIN_POSTROUTING;
		commit_rules(&t);
		return 0;
	}
	commit_rules(&t);
	err_ret(ERR_NETSTO, -1);
}
예제 #11
0
파일: mark.c 프로젝트: willsure/netsukuku
/*
 * append the rule -rule- on chain -chain-.
 * Returns:
 * 	0
 * 	-1
 */
int
append_rule(const char *rule, iptc_handle_t * t, const char *chain)
{
	int res;
	res = iptc_append_entry(chain, (struct ipt_entry *) rule, t);
	error("res is: %d, chain: %s, rule: %s, t: %s, Errno is: %d", res,
		  chain, rule, t, errno);
	if (!res) {
		error("In append_rule: %s.", iptc_strerror(errno));
		err_ret(ERR_NETRUL, -1);
	}
	return 0;
}
예제 #12
0
파일: mark.c 프로젝트: willsure/netsukuku
/* 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;

}
예제 #13
0
int do_append_nat_entry(struct iptargs *ipt,struct ipt_natinfo *target)
{
    int ret;
    unsigned short size;

    char *chain = ipt->chain;

    struct ipt_entry *entry;
    struct iptc_handle *handle = iptc_init(ipt->table);
    size = sizeof(*target);

    entry = malloc(sizeof(struct ipt_entry)+target->t.target_size);
    memset(entry, 0, sizeof(struct ipt_entry)+target->t.target_size);
    iptargs_to_ipt_entry(ipt,entry);
    printf("%s\n", target->t.name);

    //memcpy(entry->elems, &, sizeof(unsigned short));
    //memcpy(entry->elems+sizeof(unsigned short), target, size);

    entry->target_offset = sizeof(struct ipt_entry);
    entry->next_offset = entry->target_offset + target->t.target_size;
    //entry->ip.flags |= IPT_SNAT_OPT_SOURCE;
    //target->t.revision = 1;
    printf("SIZE = %d %d\n", target->t.target_size, target->mr.rangesize);
    memcpy(entry->elems, target, target->t.target_size);
    ret = iptc_append_entry(chain, entry, handle);
    if (ret)
        printf("Append successfully\n");
    else
        printf("ERROR %d %s\n", ret, iptc_strerror(ret));
    ret = iptc_commit(handle);
    if (ret)
        printf("Commit successfully\n");
    else
        printf("ERROR %d %s\n", ret, iptc_strerror(ret));
    iptc_free(handle);
    return ret;
}
예제 #14
0
파일: mark.c 프로젝트: willsure/netsukuku
/*
 * 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;
}
예제 #15
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);
}
예제 #16
0
파일: mark.c 프로젝트: willsure/netsukuku
/*
 * insert the rule -rule- on chain -chain-
 * at the position pos.
 * Returns:
 * 	0
 * 	-1
 */
int
insert_rule(const char *rule, iptc_handle_t * t, const char *chain,
			int pos)
{
	int res;
	res = iptc_insert_entry(chain, (struct ipt_entry *) rule, 0, t);
	error
		("res is: %d rule is: %p chain is: %s pos is: %d t is: %p errno is: %d",
		 res, rule, chain, pos, t, errno);
	if (!res) {
		error("In insert_rule: %s.", iptc_strerror(errno));
		err_ret(ERR_NETRUL, -1);
	}
	return 0;
}
예제 #17
0
파일: mark.c 프로젝트: willsure/netsukuku
/* 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);
}
예제 #18
0
static int
do_iptables(int argc, char* argv[])
{
	char *table = "filter";
	int ret = 0;

	if(!find_table(argc, argv))
		return 0;

#ifdef IP6T
	ret = do_command6(argc, argv, &table, &current_table->handle, true);

	if (!ret)
	{
		fprintf(stderr, "line %d: %s\n", current_line, ip6tc_strerror(errno));
	}
	else
	{
		if(!table || strcmp(table, current_table->name))
		{
			fprintf(stderr, "line %d: expected table %s, got %s\n",
					current_line, current_table->name, table);
			exit(1);
		}
	}
#else
        ret = do_command4(argc, argv, &table, &current_table->handle, true);

	if (!ret)
	{
		fprintf(stderr, "line %d: %s\n", current_line, iptc_strerror(errno));
	}
	else
	{
		if(!table || strcmp(table, current_table->name))
		{
			fprintf(stderr, "line %d: expected table %s, got %s\n",
					current_line, current_table->name, table);
			exit(1);
		}
	}
#endif

	return ret;
}
예제 #19
0
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 ) ;
}
예제 #20
0
파일: mark.c 프로젝트: willsure/netsukuku
int
delete_ntk_forward_chain(iptc_handle_t * t)
{
	int res;

	res = iptc_is_chain(NTK_MARK_CHAIN, *t);
	if (!res)
		return 0;
	res = iptc_flush_entries(NTK_MARK_CHAIN, t);
	if (!res)
		goto cannot_delete;
	res = iptc_delete_chain(NTK_MARK_CHAIN, t);
	if (!res)
		goto cannot_delete;
	return 0;

  cannot_delete:
	error("In delete_ntk_forward_chain: -> %s", iptc_strerror(errno));
	err_ret(ERR_NETDEL, -1);
}
예제 #21
0
파일: mark.c 프로젝트: willsure/netsukuku
/*
 * Build the chain ntk_mark_chain on
 * mangle table.
 */
int
ntk_mark_chain_init(iptc_handle_t * t)
{
	int res;
	res = iptc_is_chain(NTK_MARK_CHAIN, *t);
	if (res) {
		debug(DBG_NORMAL, "In mark_init: bizarre, ntk mangle"
			  "chain is present yet. it will be flushed.");
		res = iptc_flush_entries(NTK_MARK_CHAIN, t);
		if (!res)
			goto dontwork;
	} else {
		res = iptc_create_chain(NTK_MARK_CHAIN, t);
		if (!res)
			goto dontwork;
	}
	return 0;
  dontwork:
	error("In ntk_mark_chain_init: -> %s", iptc_strerror(errno));
	err_ret(ERR_NETCHA, -1)
}
예제 #22
0
/* 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;
}
예제 #23
0
/* 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;
}
예제 #24
0
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;
}
예제 #25
0
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;
}
예제 #26
0
static int for_save_table()
{
	int ret = 1;
	FILE *procfile = NULL;
	char tablename[] ="filter";
	const char *returnvalue =NULL;
	time_t now = time(NULL);
	const char *target_name;

	procfile = fopen("/data/ip_tables_save_temp", "w+");
	if (!procfile)
		return ret;


	struct iptc_handle *h;
	const char *chain = NULL;

	h = iptc_init(tablename);
	if (h == NULL) {
		xtables_load_ko(xtables_modprobe_program, false);
		h = iptc_init(tablename);
	}
	if (!h)
		xtables_error(OTHER_PROBLEM, "Cannot initialize: %s\n",
			   iptc_strerror(errno));

		printf("# for_save_table...LGE \n");

		/* Dump out chain names first,
		 * thereby preventing dependency conflicts */

		for (chain = iptc_first_chain(h);
		     chain;
		     chain = iptc_next_chain(h)) {
			const struct ipt_entry *e;

			printf(":%s\n ", chain);
			if(!strcmp(chain,"OUTPUT")){

				/* Dump out rules */
				e = iptc_first_rule(chain, h);
				while(e) {
						target_name = iptc_get_target(e, h);
						
						if(!strcmp(target_name,"DROP")){
							printf("target :%s\n ", target_name);
							printf("out_iface :%s\n ", e->ip.outiface);
							fprintf(procfile,"%s\t%s\n", target_name, e->ip.outiface);
							
						}
						e = iptc_next_rule(e, h);
				}
			}	
		}

	//fputs(returnvalue, procfile);

	iptc_free(h);

	fclose(procfile);
	return ret;
}
예제 #27
0
파일: iptcrdr.c 프로젝트: hajuuk/asuswrt
/* 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;
}
예제 #28
0
파일: iptcrdr.c 프로젝트: hajuuk/asuswrt
/* 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;
}
예제 #29
0
파일: iptcrdr.c 프로젝트: hajuuk/asuswrt
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;
}
예제 #30
0
파일: iptcrdr.c 프로젝트: hajuuk/asuswrt
/* 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;
}