Example #1
0
/*
 * 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);
}
Example #2
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;
}
Example #3
0
//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;
}
Example #4
0
/*
 * Count the number of rules in ntk_mangle_chain.
 *
 * Returns the number of rules present in
 * this chain.
 */
int
count_ntk_mark_chain(iptc_handle_t * t)
{
	int nchain = 0;
	const struct ipt_entry *e;

	e = iptc_first_rule(NTK_MARK_CHAIN, t);
	while (e) {
		nchain++;
		e = iptc_next_rule(e, t);
	}
	return nchain;
}
Example #5
0
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;
					}
				}
			}
		}
	}
}
Example #6
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);
}
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);
}
Example #8
0
/*
 * Search for the position of rule -rule.rule-
 * on the chain rule.chain
 * Returns:
 * 	pos if rule was found
 * 	-1  if rule wasn't found
 */
int
rule_position(rule_store * rule, iptc_handle_t * t)
{
	const struct ipt_entry *e;
	int res, count = -1, found = 0;

	e = iptc_first_rule(rule->chain, t);
	while (e) {
		count++;
		res = memcmp(e, rule->e, rule->sz);
		if (!res) {
			found = 1;
			break;
		}
		e = iptc_next_rule(e, t);
	}
	return found ? count : -1;
}
Example #9
0
/* 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;
}
Example #10
0
/* 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;
}
Example #11
0
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;
}
Example #12
0
/* 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;
}
Example #13
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;
}
Example #14
0
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);
}
Example #15
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;
}
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;
}
Example #17
0
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");
}
Example #18
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;
}
Example #19
0
/*
 * 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;
	}