Exemple #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);
}
Exemple #2
0
/* 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;
}
Exemple #3
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;
}
Exemple #4
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;
}
int
main(int argc, char *argv[])
#endif
{
	int ret;
	char *table = "filter";
	iptc_handle_t handle = NULL;

	program_name = "iptables";
	program_version = IPTABLES_VERSION;

	lib_dir = getenv("IPTABLES_LIB_DIR");
	if (!lib_dir)
		lib_dir = IPT_LIB_DIR;

#ifdef NO_SHARED_LIBS
	init_extensions();
#endif

	ret = do_command(argc, argv, &table, &handle);

	if (ret)
		ret = iptc_commit(&handle);
	
	if (!ret) {
		fprintf(stderr, "iptables: %s\n",
			iptc_strerror(errno));
		if (errno == EAGAIN) {
			exit(RESOURCE_PROBLEM);
		}
	}

	exit(!ret);
}
/* iptc_init_verify_and_append()
 * return 0 on success, -1 on failure */
static int
iptc_init_verify_and_append(const char * table, struct ipt_entry * e,
                            const char * logcaller)
{
	iptc_handle_t h;
	h = iptc_init(table);
	if(!h)
	{
		syslog(LOG_ERR, "%s : iptc_init() error : %s\n",
		       logcaller, iptc_strerror(errno));
		return -1;
	}
	if(!iptc_is_chain(miniupnpd_chain, h))
	{
		syslog(LOG_ERR, "%s : iptc_is_chain() error : %s\n",
		       logcaller, iptc_strerror(errno));
		return -1;
	}
	if(!iptc_append_entry(miniupnpd_chain, e, &h))
	{
		syslog(LOG_ERR, "%s : iptc_append_entry() error : %s\n",
		       logcaller, iptc_strerror(errno));
		return -1;
	}
	if(!iptc_commit(&h))
	{
		syslog(LOG_ERR, "%s : iptc_commit() error : %s\n",
		       logcaller, iptc_strerror(errno));
		return -1;
	}
	return 0;
}
int
iptables_main(int argc, char *argv[])
{
	int ret;
	char *table = "filter";
	struct xtc_handle *handle = NULL;
    FILE *pfLockFile = NULL;

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

    ATP_UTIL_RegUnLock(pfLockFile);

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

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

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

	exit(!ret);
}
Exemple #8
0
/*
 * 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;
}
Exemple #9
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);
}
Exemple #10
0
static void
remove_inhibitor_rules(struct ipt_entry *caller_inhibitor_entry, struct ipt_entry *callee_inhibitor_entry)
{
    struct iptc_handle *ipt_handle;
    unsigned char matchmask[IPTC_FULL_SIZE];

    if ((ipt_handle = iptc_init("raw")) != NULL) {
        memset(matchmask, 255, IPTC_FULL_SIZE);
        // We release all rules to workaround stray rules that may remain in the
        // raw table after the application crashes without a chance to clean up.
        while(iptc_delete_entry("PREROUTING", caller_inhibitor_entry, matchmask, ipt_handle));
        while(iptc_delete_entry("PREROUTING", callee_inhibitor_entry, matchmask, ipt_handle));
        if (!iptc_commit(ipt_handle))
            iptc_free(ipt_handle);
    }
}
/* delete_rule_and_commit() :
 * subfunction used in delete_redirect_and_filter_rules() */
static int
delete_rule_and_commit(unsigned int index, iptc_handle_t *h,
                       const char * logcaller)
{
	int r = 0;
	if(!iptc_delete_num_entry(miniupnpd_chain, index, h))
	{
		syslog(LOG_ERR, "%s() : iptc_delete_num_entry(): %s\n",
	    	   logcaller, iptc_strerror(errno));
		r = -1;
	}
	else if(!iptc_commit(h))
	{
		syslog(LOG_ERR, "%s() : iptc_commit(): %s\n",
	    	   logcaller, iptc_strerror(errno));
		r = -1;
	}
	return r;
}
Exemple #12
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 ) ;
}
Exemple #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;
}
Exemple #14
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;
	}
Exemple #15
0
static void fwd_ipt_defaults_create(struct fwd_data *d)
{
	struct fwd_defaults *def = &d->section.defaults;
	struct iptc_handle *h_filter, *h_nat;

	if( !(h_filter = iptc_init("filter")) || !(h_nat = iptc_init("nat")) )
		fwd_fatal("Unable to obtain libiptc handle");

	/* policies */
	fwd_r_set_policy(h_filter, "INPUT",
		def->input == FWD_P_ACCEPT ? "ACCEPT" : "DROP");
	fwd_r_set_policy(h_filter, "OUTPUT",
		def->output == FWD_P_ACCEPT ? "ACCEPT" : "DROP");
	fwd_r_set_policy(h_filter, "FORWARD",
		def->forward == FWD_P_ACCEPT ? "ACCEPT" : "DROP");

	/* invalid state drop */
	if( def->drop_invalid )
	{
		fwd_r_drop_invalid(h_filter, "INPUT");
		fwd_r_drop_invalid(h_filter, "OUTPUT");
		fwd_r_drop_invalid(h_filter, "FORWARD");
	}

	/* default accept related */
	fwd_r_accept_related(h_filter, "INPUT");
	fwd_r_accept_related(h_filter, "OUTPUT");
	fwd_r_accept_related(h_filter, "FORWARD");

	/* default accept on lo */
	fwd_r_accept_lo(h_filter);

	/* syn flood protection */
	if( def->syn_flood )
	{
		fwd_r_add_synflood(h_filter, def);
	}

	/* rule container chains */
	fwd_r_new_chain(h_filter, "mssfix");
	fwd_r_new_chain(h_filter, "zones");
	fwd_r_new_chain(h_filter, "rules");
	fwd_r_new_chain(h_filter, "redirects");
	fwd_r_new_chain(h_filter, "forwardings");
	fwd_r_jump_chain(h_filter, "INPUT", "rules");
	fwd_r_jump_chain(h_filter, "FORWARD", "mssfix");
	fwd_r_jump_chain(h_filter, "FORWARD", "zones");
	fwd_r_jump_chain(h_filter, "FORWARD", "rules");
	fwd_r_jump_chain(h_filter, "FORWARD", "redirects");
	fwd_r_jump_chain(h_filter, "FORWARD", "forwardings");
	fwd_r_new_chain(h_nat, "zonemasq");
	fwd_r_new_chain(h_nat, "redirects");
	fwd_r_new_chain(h_nat, "loopback");
	fwd_r_jump_chain(h_nat, "POSTROUTING", "zonemasq");
	fwd_r_jump_chain(h_nat, "PREROUTING", "redirects");
	fwd_r_jump_chain(h_nat, "POSTROUTING", "loopback");

	/* standard drop, accept, reject chain */
	fwd_r_handle_drop(h_filter);
	fwd_r_handle_accept(h_filter);
	fwd_r_handle_reject(h_filter);


	if( !iptc_commit(h_nat) )
		fwd_fatal("Cannot commit nat table: %s", iptc_strerror(errno));

	if( !iptc_commit(h_filter) )
		fwd_fatal("Cannot commit filter table: %s", iptc_strerror(errno));

	iptc_free(h_nat);
	iptc_free(h_filter);
}
int
main(int argc, char *argv[])
#endif
{
	iptc_handle_t handle = NULL;
	char buffer[10240];
	int c;
	char curtable[IPT_TABLE_MAXNAMELEN + 1];
	FILE *in;
	const char *modprobe = 0;
	int in_table = 0, testing = 0;

	program_name = "iptables-restore";
	program_version = IPTABLES_VERSION;
	line = 0;

	lib_dir = getenv("IPTABLES_LIB_DIR");
	if (!lib_dir)
		lib_dir = IPT_LIB_DIR;

#ifdef NO_SHARED_LIBS
	init_extensions();
#endif

	while ((c = getopt_long(argc, argv, "bcvthnM:", options, NULL)) != -1) {
		switch (c) {
			case 'b':
				binary = 1;
				break;
			case 'c':
				counters = 1;
				break;
			case 'v':
				verbose = 1;
				break;
			case 't':
				testing = 1;
				break;
			case 'h':
				print_usage("iptables-restore",
					    IPTABLES_VERSION);
				break;
			case 'n':
				noflush = 1;
				break;
			case 'M':
				modprobe = optarg;
				break;
		}
	}
	
	if (optind == argc - 1) {
		in = fopen(argv[optind], "r");
		if (!in) {
			fprintf(stderr, "Can't open %s: %s", argv[optind],
				strerror(errno));
			exit(1);
		}
	}
	else if (optind < argc) {
		fprintf(stderr, "Unknown arguments found on commandline");
		exit(1);
	}
	else in = stdin;
	
	/* Grab standard input. */
	while (fgets(buffer, sizeof(buffer), in)) {
		int ret = 0;

		line++;
		if (buffer[0] == '\n')
			continue;
		else if (buffer[0] == '#') {
			if (verbose)
				fputs(buffer, stdout);
			continue;
		} else if ((strcmp(buffer, "COMMIT\n") == 0) && (in_table)) {
			if (!testing) {
				DEBUGP("Calling commit\n");
				ret = iptc_commit(&handle);
			} else {
				DEBUGP("Not calling commit, testing\n");
				ret = 1;
			}
			in_table = 0;
		} else if ((buffer[0] == '*') && (!in_table)) {
			/* New table */
			char *table;

			table = strtok(buffer+1, " \t\n");
			DEBUGP("line %u, table '%s'\n", line, table);
			if (!table) {
				exit_error(PARAMETER_PROBLEM, 
					"%s: line %u table name invalid\n",
					program_name, line);
				exit(1);
			}
			strncpy(curtable, table, IPT_TABLE_MAXNAMELEN);
			curtable[IPT_TABLE_MAXNAMELEN] = '\0';

			if (handle)
				iptc_free(&handle);

			handle = create_handle(table, modprobe);
			if (noflush == 0) {
				DEBUGP("Cleaning all chains of table '%s'\n",
					table);
				for_each_chain(flush_entries, verbose, 1, 
						&handle);
	
				DEBUGP("Deleting all user-defined chains "
				       "of table '%s'\n", table);
				for_each_chain(delete_chain, verbose, 0, 
						&handle) ;
			}

			ret = 1;
			in_table = 1;

		} else if ((buffer[0] == ':') && (in_table)) {
			/* New chain. */
			char *policy, *chain;

			chain = strtok(buffer+1, " \t\n");
			DEBUGP("line %u, chain '%s'\n", line, chain);
			if (!chain) {
				exit_error(PARAMETER_PROBLEM,
					   "%s: line %u chain name invalid\n",
					   program_name, line);
				exit(1);
			}

			if (iptc_builtin(chain, handle) <= 0) {
				if (noflush && iptc_is_chain(chain, handle)) {
					DEBUGP("Flushing existing user defined chain '%s'\n", chain);
					if (!iptc_flush_entries(chain, &handle))
						exit_error(PARAMETER_PROBLEM,
							   "error flushing chain "
							   "'%s':%s\n", chain,
							   strerror(errno));
				} else {
					DEBUGP("Creating new chain '%s'\n", chain);
					if (!iptc_create_chain(chain, &handle))
						exit_error(PARAMETER_PROBLEM,
							   "error creating chain "
							   "'%s':%s\n", chain,
							   strerror(errno));
				}
			}

			policy = strtok(NULL, " \t\n");
			DEBUGP("line %u, policy '%s'\n", line, policy);
			if (!policy) {
				exit_error(PARAMETER_PROBLEM,
					   "%s: line %u policy invalid\n",
					   program_name, line);
				exit(1);
			}

			if (strcmp(policy, "-") != 0) {
				struct ipt_counters count;

				if (counters) {
					char *ctrs;
					ctrs = strtok(NULL, " \t\n");

					if (!ctrs || !parse_counters(ctrs, &count))
						exit_error(PARAMETER_PROBLEM,
							   "invalid policy counters "
							   "for chain '%s'\n", chain);

				} else {
					memset(&count, 0, 
					       sizeof(struct ipt_counters));
				}

				DEBUGP("Setting policy of chain %s to %s\n",
					chain, policy);

				if (!iptc_set_policy(chain, policy, &count,
						     &handle))
					exit_error(OTHER_PROBLEM,
						"Can't set policy `%s'"
						" on `%s' line %u: %s\n",
						chain, policy, line,
						iptc_strerror(errno));
			}

			ret = 1;

		} else if (in_table) {
			int a;
			char *ptr = buffer;
			char *pcnt = NULL;
			char *bcnt = NULL;
			char *parsestart;

			/* the parser */
			char *param_start, *curchar;
			int quote_open;

			/* reset the newargv */
			newargc = 0;

			if (buffer[0] == '[') {
				/* we have counters in our input */
				ptr = strchr(buffer, ']');
				if (!ptr)
					exit_error(PARAMETER_PROBLEM,
						   "Bad line %u: need ]\n",
						   line);

				pcnt = strtok(buffer+1, ":");
				if (!pcnt)
					exit_error(PARAMETER_PROBLEM,
						   "Bad line %u: need :\n",
						   line);

				bcnt = strtok(NULL, "]");
				if (!bcnt)
					exit_error(PARAMETER_PROBLEM,
						   "Bad line %u: need ]\n",
						   line);

				/* start command parsing after counter */
				parsestart = ptr + 1;
			} else {
				/* start command parsing at start of line */
				parsestart = buffer;
			}

			add_argv(argv[0]);
			add_argv("-t");
			add_argv((char *) &curtable);
			
			if (counters && pcnt && bcnt) {
				add_argv("--set-counters");
				add_argv((char *) pcnt);
				add_argv((char *) bcnt);
			}

			/* After fighting with strtok enough, here's now
			 * a 'real' parser. According to Rusty I'm now no
			 * longer a real hacker, but I can live with that */

			quote_open = 0;
			param_start = parsestart;
			
			for (curchar = parsestart; *curchar; curchar++) {
				if (*curchar == '"') {
					/* quote_open cannot be true if there
					 * was no previous character.  Thus, 
					 * curchar-1 has to be within bounds */
					if (quote_open && 
					    *(curchar-1) != '\\') {
						quote_open = 0;
						*curchar = ' ';
					} else {
						quote_open = 1;
						param_start++;
					}
				} 
				if (*curchar == ' '
				    || *curchar == '\t'
				    || * curchar == '\n') {
					char param_buffer[1024];
					int param_len = curchar-param_start;

					if (quote_open)
						continue;

					if (!param_len) {
						/* two spaces? */
						param_start++;
						continue;
					}
					
					/* end of one parameter */
					strncpy(param_buffer, param_start,
						param_len);
					*(param_buffer+param_len) = '\0';

					/* check if table name specified */
					if (!strncmp(param_buffer, "-t", 3)
                                            || !strncmp(param_buffer, "--table", 8)) {
						exit_error(PARAMETER_PROBLEM, 
						   "Line %u seems to have a "
						   "-t table option.\n", line);
						exit(1);
					}

					add_argv(param_buffer);
					param_start += param_len + 1;
				} else {
					/* regular character, skip */
				}
			}

			DEBUGP("calling do_command(%u, argv, &%s, handle):\n",
				newargc, curtable);

			for (a = 0; a < newargc; a++)
				DEBUGP("argv[%u]: %s\n", a, newargv[a]);

			ret = do_command(newargc, newargv, 
					 &newargv[2], &handle);

			free_argv();
		}
		if (!ret) {
			fprintf(stderr, "%s: line %u failed\n",
					program_name, line);
			exit(1);
		}
	}
	if (in_table) {
		fprintf(stderr, "%s: COMMIT expected at line %u\n",
				program_name, line + 1);
		exit(1);
	}

	return 0;
}
Exemple #17
0
void fwd_ipt_addif(struct fwd_handle *h, const char *net)
{
	struct fwd_data *e;
	struct fwd_zone *z;
	struct fwd_rule *c;
	struct fwd_redirect *r;
	struct fwd_forwarding *f;
	struct fwd_cidr *a, *a2;
	struct fwd_network *n, *n2;
	struct fwd_proto p;

	struct fwd_xt_rule *x;
	struct xtables_match *m;
	struct xtables_target *t;

	struct iptc_handle *h_filter, *h_nat;

	if( !(h_filter = iptc_init("filter")) || !(h_nat = iptc_init("nat")) )
		fwd_fatal("Unable to obtain libiptc handle");


	if( !(z = fwd_lookup_zone(h, net)) )
		return;

	if( !(n = fwd_lookup_network(z, net)) )
		return;

	if( !(a = n->addr) || fwd_empty_cidr(a) )
		return;


	fwd_log_info("Adding network %s (interface %s)",
		n->name, n->ifname);

	/* Build masquerading rule */
	if( z->masq )
	{
		if( (x = fwd_xt_init_rule(h_nat)) != NULL )
		{
			fwd_xt_parse_out(x, n, 0);				/* -o ... */
			fwd_xt_get_target(x, "MASQUERADE");		/* -j MASQUERADE */
			fwd_r_add_comment(x, "masq", z, n);		/* -m comment ... */
			fwd_xt_append_rule(x, "zonemasq");		/* -A zonemasq */
		}
	}

	/* Build MSS fix rule */
	if( z->mtu_fix )
	{
		if( (x = fwd_xt_init_rule(h_filter)) != NULL )
		{
			p.type = FWD_PR_TCP;
			fwd_xt_parse_out(x, n, 0);					/* -o ... */
			fwd_xt_parse_proto(x, &p, 0);				/* -p tcp */

			/* -m tcp --tcp-flags SYN,RST SYN */
			if( (m = fwd_xt_get_match(x, "tcp")) != NULL )
				fwd_xt_parse_match(x, m, "--tcp-flags", "SYN,RST", "SYN");

			/* -j TCPMSS --clamp-mss-to-pmtu */
			if( (t = fwd_xt_get_target(x, "TCPMSS")) != NULL )
				fwd_xt_parse_target(x, t, "--clamp-mss-to-pmtu");

			/* -m comment ... */
			fwd_r_add_comment(x, "mssfix", z, n);

			/* -A mssfix */
			fwd_xt_append_rule(x, "mssfix");
		}
	}

	/* Build intra-zone forwarding rules */
	for( n2 = z->networks; n2; n2 = n2->next )
	{
		if( (a2 = n2->addr) != NULL )
		{
			if( (x = fwd_xt_init_rule(h_filter)) != NULL )
			{
				fwd_xt_parse_in(x, n, 0);				/* -i ... */
				fwd_xt_parse_out(x, n2, 0);				/* -o ... */
				fwd_r_add_policytarget(x, z->forward);	/* -j handle_... */
				fwd_r_add_comment(x, "zone", z, n);		/* -m comment ... */
				fwd_xt_append_rule(x, "zones");			/* -A zones */
			}
		}
	}

	/* Build inter-zone forwarding rules */
	for( e = z->forwardings; e && (f = &e->section.forwarding); e = e->next )
	{
		for( n2 = f->dest->networks; n2; n2 = n2->next )
		{
			/* Build forwarding rule */
			if( (x = fwd_xt_init_rule(h_filter)) != NULL )
			{
				fwd_xt_parse_in(x, n, 0);					/* -i ... */
				fwd_xt_parse_out(x, n2, 0);					/* -o ... */
				fwd_r_add_policytarget(x, FWD_P_ACCEPT);	/* -j handle_... */
				fwd_r_add_comment(x, "forward", z, n);		/* -m comment ... */
				fwd_xt_append_rule(x, "forwardings");		/* -A forwardings */
			}
		}
	}

	/* Build DNAT rules */
	for( e = z->redirects; e && (r = &e->section.redirect); e = e->next )
	{
		/* DNAT */
		if( (x = fwd_xt_init_rule(h_nat)) != NULL )
		{
			fwd_xt_parse_in(x, n, 0);					/* -i ... */
			fwd_xt_parse_src(x, r->src_ip, 0);			/* -s ... */
			fwd_xt_parse_dest(x, a, 0);					/* -d ... */
			fwd_xt_parse_proto(x, r->proto, 0);			/* -p ... */
			fwd_r_add_sport(x, r->src_port);			/* --sport ... */
			fwd_r_add_dport(x, r->src_dport);			/* --dport ... */
			fwd_r_add_srcmac(x, r->src_mac);			/* -m mac --mac-source ... */
			fwd_r_add_dnattarget(x, r->dest_ip, r->dest_port);	/* -j DNAT ... */
			fwd_r_add_comment(x, "redir", z, n);		/* -m comment ... */
			fwd_xt_append_rule(x, "redirects");			/* -A redirects */
		}

		/* Forward */
		if( (x = fwd_xt_init_rule(h_filter)) != NULL )
		{
			fwd_xt_parse_in(x, n, 0);					/* -i ... */
			fwd_xt_parse_src(x, r->src_ip, 0);			/* -s ... */
			fwd_xt_parse_dest(x, r->dest_ip, 0);		/* -d ... */
			fwd_xt_parse_proto(x, r->proto, 0);			/* -p ... */
			fwd_r_add_srcmac(x, r->src_mac);			/* -m mac --mac-source ... */
			fwd_r_add_sport(x, r->src_port);			/* --sport ... */
			fwd_r_add_dport(x, r->dest_port);			/* --dport ... */
			fwd_r_add_policytarget(x, FWD_P_ACCEPT);	/* -j handle_accept */
			fwd_r_add_comment(x, "redir", z, n);		/* -m comment ... */
			fwd_xt_append_rule(x, "redirects");			/* -A redirects */
		}

		/* Add loopback rule if neither src_ip nor src_mac are defined */
		if( !r->src_ip && !r->src_mac )
		{
			if( (x = fwd_xt_init_rule(h_nat)) != NULL )
			{
				fwd_xt_parse_in(x, n, 1);				/* -i ! ... */
				fwd_xt_parse_dest(x, r->dest_ip, 0);	/* -d ... */
				fwd_xt_parse_proto(x, r->proto, 0);		/* -p ... */
				fwd_r_add_sport(x, r->src_port);		/* --sport ... */
				fwd_r_add_dport(x, r->src_dport);		/* --dport ... */
				fwd_xt_get_target(x, "MASQUERADE");		/* -j MASQUERADE */
				fwd_r_add_comment(x, "redir", z, n);	/* -m comment ... */
				fwd_xt_append_rule(x, "loopback");		/* -A loopback */
			}
		}
	}

	/* Build rules */
	for( e = z->rules; e && (c = &e->section.rule); e = e->next )
	{
		/* Has destination, add forward rule for each network in target zone */
		if( c->dest )
		{
			for( n2 = c->dest->networks; n2; n2 = n2->next )
			{
				if( (x = fwd_xt_init_rule(h_filter)) != NULL )
				{
					fwd_xt_parse_in(x, n, 0);				/* -i ... */
					fwd_xt_parse_out(x, n2, 0);				/* -o ... */
					fwd_xt_parse_src(x, c->src_ip, 0);		/* -s ... */
					fwd_xt_parse_dest(x, c->dest_ip, 0);	/* -d ... */
					fwd_xt_parse_proto(x, c->proto, 0);		/* -p ... */
					fwd_r_add_icmptype(x, c->icmp_type);	/* --icmp-type ... */
					fwd_r_add_srcmac(x, c->src_mac);		/* --mac-source ... */
					fwd_r_add_sport(x, c->src_port);		/* --sport ... */
					fwd_r_add_dport(x, c->dest_port);		/* --dport ... */
					fwd_r_add_policytarget(x, c->target);	/* -j handle_... */
					fwd_r_add_comment(x, "rule", z, n);		/* -m comment ... */
					fwd_xt_append_rule(x, "rules");			/* -A rules */
				}
			}
		}

		/* No destination specified, treat it as input rule */
		else
		{
			if( (x = fwd_xt_init_rule(h_filter)) != NULL )
			{
				fwd_xt_parse_in(x, n, 0);				/* -i ... */
				fwd_xt_parse_src(x, c->src_ip, 0);		/* -s ... */
				fwd_xt_parse_dest(x, c->dest_ip, 0);	/* -d ... */
				fwd_xt_parse_proto(x, c->proto, 0);		/* -p ... */
				fwd_r_add_icmptype(x, c->icmp_type);	/* --icmp-type ... */
				fwd_r_add_srcmac(x, c->src_mac);		/* --mac-source ... */
				fwd_r_add_sport(x, c->src_port);		/* --sport ... */
				fwd_r_add_dport(x, c->dest_port);		/* --dport ... */
				fwd_r_add_policytarget(x, c->target);	/* -j handle_... */
				fwd_r_add_comment(x, "rule", z, n);		/* -m comment ... */
				fwd_xt_append_rule(x, "rules");			/* -A rules */
			}
		}
	}

	if( !iptc_commit(h_nat) )
		fwd_fatal("Cannot commit nat table: %s", iptc_strerror(errno));

	if( !iptc_commit(h_filter) )
		fwd_fatal("Cannot commit filter table: %s", iptc_strerror(errno));

	iptc_free(h_nat);
	iptc_free(h_filter);
}
Exemple #18
0
/* 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;
}
Exemple #19
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);
}
Exemple #20
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");
}
int
main(int argc, char *argv[])
#endif
{
	struct iptc_handle *handle = NULL;
	char buffer[10240];
	int c;
	char curtable[IPT_TABLE_MAXNAMELEN + 1];
	FILE *in;
	int in_table = 0, testing = 0;
	const char *tablename = NULL;

	line = 0;

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

	while ((c = getopt_long(argc, argv, "bcvthnM:T:", options, NULL)) != -1) {
		switch (c) {
			case 'b':
				binary = 1;
				break;
			case 'c':
				counters = 1;
				break;
			case 'v':
				verbose = 1;
				break;
			case 't':
				testing = 1;
				break;
			case 'h':
				print_usage("iptables-restore",
					    IPTABLES_VERSION);
				break;
			case 'n':
				noflush = 1;
				break;
			case 'M':
				xtables_modprobe_program = optarg;
				break;
			case 'T':
				tablename = optarg;
				break;
		}
	}

	if (optind == argc - 1) {
		in = fopen(argv[optind], "r");
		if (!in) {
			fprintf(stderr, "Can't open %s: %s\n", argv[optind],
				strerror(errno));
			exit(1);
		}
	}
	else if (optind < argc) {
		fprintf(stderr, "Unknown arguments found on commandline\n");
		exit(1);
	}
	else in = stdin;

	/* Grab standard input. */
	while (fgets(buffer, sizeof(buffer), in)) {
		int ret = 0;

		line++;
		if (buffer[0] == '\n')
			continue;
		else if (buffer[0] == '#') {
			if (verbose)
				fputs(buffer, stdout);
			continue;
		} else if ((strcmp(buffer, "COMMIT\n") == 0) && (in_table)) {
			if (!testing) {
				DEBUGP("Calling commit\n");
				ret = iptc_commit(handle);
				iptc_free(handle);
				handle = NULL;
			} else {
				DEBUGP("Not calling commit, testing\n");
				ret = 1;
			}
			in_table = 0;
		} else if ((buffer[0] == '*') && (!in_table)) {
			/* New table */
			char *table;

			table = strtok(buffer+1, " \t\n");
			DEBUGP("line %u, table '%s'\n", line, table);
			if (!table) {
				xtables_error(PARAMETER_PROBLEM,
					"%s: line %u table name invalid\n",
					prog_name, line);
				exit(1);
			}
			strncpy(curtable, table, IPT_TABLE_MAXNAMELEN);
			curtable[IPT_TABLE_MAXNAMELEN] = '\0';

			if (tablename && (strcmp(tablename, table) != 0))
				continue;
			if (handle)
				iptc_free(handle);

			handle = create_handle(table);
			if (noflush == 0) {
				DEBUGP("Cleaning all chains of table '%s'\n",
					table);
				for_each_chain(flush_entries, verbose, 1,
						handle);

				DEBUGP("Deleting all user-defined chains "
				       "of table '%s'\n", table);
				for_each_chain(delete_chain, verbose, 0,
						handle);
			}

			ret = 1;
			in_table = 1;

		} else if ((buffer[0] == ':') && (in_table)) {
			/* New chain. */
			char *policy, *chain;

			chain = strtok(buffer+1, " \t\n");
			DEBUGP("line %u, chain '%s'\n", line, chain);
			if (!chain) {
				xtables_error(PARAMETER_PROBLEM,
					   "%s: line %u chain name invalid\n",
					   prog_name, line);
				exit(1);
			}

			if (strlen(chain) >= XT_EXTENSION_MAXNAMELEN)
				xtables_error(PARAMETER_PROBLEM,
					   "Invalid chain name `%s' "
					   "(%u chars max)",
					   chain, XT_EXTENSION_MAXNAMELEN - 1);

			if (iptc_builtin(chain, handle) <= 0) {
				if (noflush && iptc_is_chain(chain, handle)) {
					DEBUGP("Flushing existing user defined chain '%s'\n", chain);
					if (!iptc_flush_entries(chain, handle))
						xtables_error(PARAMETER_PROBLEM,
							   "error flushing chain "
							   "'%s':%s\n", chain,
							   strerror(errno));
				} else {
					DEBUGP("Creating new chain '%s'\n", chain);
					if (!iptc_create_chain(chain, handle))
						xtables_error(PARAMETER_PROBLEM,
							   "error creating chain "
							   "'%s':%s\n", chain,
							   strerror(errno));
				}
			}

			policy = strtok(NULL, " \t\n");
			DEBUGP("line %u, policy '%s'\n", line, policy);
			if (!policy) {
				xtables_error(PARAMETER_PROBLEM,
					   "%s: line %u policy invalid\n",
					   prog_name, line);
				exit(1);
			}

			if (strcmp(policy, "-") != 0) {
				struct ipt_counters count;

				if (counters) {
					char *ctrs;
					ctrs = strtok(NULL, " \t\n");

					if (!ctrs || !parse_counters(ctrs, &count))
						xtables_error(PARAMETER_PROBLEM,
							   "invalid policy counters "
							   "for chain '%s'\n", chain);

				} else {
					memset(&count, 0,
					       sizeof(struct ipt_counters));
				}

				DEBUGP("Setting policy of chain %s to %s\n",
					chain, policy);

				if (!iptc_set_policy(chain, policy, &count,
						     handle))
					xtables_error(OTHER_PROBLEM,
						"Can't set policy `%s'"
						" on `%s' line %u: %s\n",
						chain, policy, line,
						iptc_strerror(errno));
			}

			ret = 1;

		} else if (in_table) {
			int a;
			char *ptr = buffer;
			char *pcnt = NULL;
			char *bcnt = NULL;
			char *parsestart;

			/* the parser */
			char *curchar;
			int quote_open, escaped;
			size_t param_len;

			/* reset the newargv */
			newargc = 0;

			if (buffer[0] == '[') {
				/* we have counters in our input */
				ptr = strchr(buffer, ']');
				if (!ptr)
					xtables_error(PARAMETER_PROBLEM,
						   "Bad line %u: need ]\n",
						   line);

				pcnt = strtok(buffer+1, ":");
				if (!pcnt)
					xtables_error(PARAMETER_PROBLEM,
						   "Bad line %u: need :\n",
						   line);

				bcnt = strtok(NULL, "]");
				if (!bcnt)
					xtables_error(PARAMETER_PROBLEM,
						   "Bad line %u: need ]\n",
						   line);

				/* start command parsing after counter */
				parsestart = ptr + 1;
			} else {
				/* start command parsing at start of line */
				parsestart = buffer;
			}

			add_argv(argv[0]);
			add_argv("-t");
			add_argv((char *) &curtable);

			if (counters && pcnt && bcnt) {
				add_argv("--set-counters");
				add_argv((char *) pcnt);
				add_argv((char *) bcnt);
			}

			/* After fighting with strtok enough, here's now
			 * a 'real' parser. According to Rusty I'm now no
			 * longer a real hacker, but I can live with that */

			quote_open = 0;
			escaped = 0;
			param_len = 0;

			for (curchar = parsestart; *curchar; curchar++) {
				char param_buffer[1024];

				if (quote_open) {
					if (escaped) {
						param_buffer[param_len++] = *curchar;
						escaped = 0;
						continue;
					} else if (*curchar == '\\') {
						escaped = 1;
						continue;
					} else if (*curchar == '"') {
						quote_open = 0;
						*curchar = ' ';
					} else {
						param_buffer[param_len++] = *curchar;
						continue;
					}
				} else {
					if (*curchar == '"') {
						quote_open = 1;
						continue;
					}
				}

				if (*curchar == ' '
				    || *curchar == '\t'
				    || * curchar == '\n') {
					if (!param_len) {
						/* two spaces? */
						continue;
					}

					param_buffer[param_len] = '\0';

					/* check if table name specified */
					if (!strncmp(param_buffer, "-t", 2)
					    || !strncmp(param_buffer, "--table", 8)) {
						xtables_error(PARAMETER_PROBLEM,
						   "Line %u seems to have a "
						   "-t table option.\n", line);
						exit(1);
					}

					add_argv(param_buffer);
					param_len = 0;
				} else {
					/* regular character, copy to buffer */
					param_buffer[param_len++] = *curchar;

					if (param_len >= sizeof(param_buffer))
						xtables_error(PARAMETER_PROBLEM,
						   "Parameter too long!");
				}
			}

			DEBUGP("calling do_command(%u, argv, &%s, handle):\n",
				newargc, curtable);

			for (a = 0; a < newargc; a++)
				DEBUGP("argv[%u]: %s\n", a, newargv[a]);

			ret = do_command(newargc, newargv,
					 &newargv[2], &handle);

			free_argv();
			fflush(stdout);
		}
		if (tablename && (strcmp(tablename, curtable) != 0))
			continue;
		if (!ret) {
			fprintf(stderr, "%s: line %u failed\n",
					prog_name, line);
			exit(1);
		}
	}
	if (in_table) {
		fprintf(stderr, "%s: COMMIT expected at line %u\n",
				prog_name, line + 1);
		exit(1);
	}

	if (in != NULL)
		fclose(in);
	return 0;
}
int main ( int argc, char * argv[] )
{
	int have_committed = 1; // prevent double commits, 'clean' state to begin with
        int c;

	program_name = argv[0];
	program_name = "ipbatch CLI";
	// this is really important for locating shared libs
	program_version = IPTABLES_VERSION;
        c = xtables_init_all(&iptables_globals, NFPROTO_IPV4);
        if (c < 0) {
                fprintf(stderr, "%s/%s Failed to initialize xtables\n",
                                program_name,
                                program_version);
                exit(1);
        }


	openlog( "SmoothIPSubsys", LOG_NDELAY | LOG_CONS, LOG_DAEMON );
	
/*        lib_dir = getenv("IPTABLES_LIB_DIR");*/
/*	if (!lib_dir)*/
/*		lib_dir = IPT_LIB_DIR;*/

	/* read lines from STDIN */

	char buffer[ BUFFER_SIZE ];
	int error = 0;

	// syslog( LOG_ERR, "Checking input" );
	// there are two special commands end is the same as eof and commit
	// does an early commit rather than the changes only being committed at the end
	while ( fgets( buffer, BUFFER_SIZE - 2, stdin ) != NULL ){
		/* terminate the line at the carriage return */

		if ( strlen( buffer ) > BUFFER_SIZE ){
			// silently ignore long lines
			continue;
		}

		buffer[ strlen( buffer ) - 1 ] = '\0';

		//syslog( LOG_ERR, "Received command %s", buffer );

		if ( strcmp( buffer, "end" ) == 0 ){
			break;
		}

		if ( strcmp( buffer, "commit" ) == 0 ){
			/* commit changes */
			error = iptc_commit(handle);
			iptc_free(handle);
			handle = NULL;
			have_committed = 1;
		} else {
			/* excute the command */
			if(!have_committed) {

				if(table_changed(buffer)) {   
					//syslog( LOG_ERR, "Table change for %s", buffer );
					error = iptc_commit(handle);
					iptc_free(handle);
					handle = NULL;
					have_committed = 1;
				}
			}
			if(*buffer)
			    error = execute( buffer );
			have_committed = 0;
		}

		if ( !error ){
			/* if an error has occured then we're */
			/* in trouble and might as well just  */
			/* leave                              */
			syslog( LOG_ERR, "error: %s", iptc_strerror(errno));
			return !error;
		}

	}

	//syslog( LOG_ERR, "Finished" );
	/* commit the changes, that is flush */
	/* the iptables buffer               */

	if(!have_committed) {
		error = iptc_commit(handle);
		iptc_free(handle);
		handle = NULL;
		syslog( LOG_ERR, "Unable to commit IPTables rules \"%s\"", iptc_strerror( errno ) );
	}

	return !error;
}