Пример #1
0
static int
table_do_get_stdlist(uint16_t opcode, ipfw_obj_lheader **polh)
{
	ipfw_obj_lheader req, *olh;
	size_t sz;

	memset(&req, 0, sizeof(req));
	sz = sizeof(req);

	if (do_get3(opcode, &req.opheader, &sz) != 0)
		if (errno != ENOMEM)
			return (errno);

	sz = req.size;
	if ((olh = calloc(1, sz)) == NULL)
		return (ENOMEM);

	olh->size = sz;
	if (do_get3(opcode, &olh->opheader, &sz) != 0) {
		free(olh);
		return (errno);
	}

	*polh = olh;
	return (0);
}
Пример #2
0
/*
 * Retrieves all entries for given table @i in
 * eXtended format. Allocate buffer large enough
 * to store result. Called needs to free it later.
 *
 * Returns 0 on success.
 */
static int
table_do_get_list(ipfw_xtable_info *i, ipfw_obj_header **poh)
{
	ipfw_obj_header *oh;
	size_t sz;
	int c;

	sz = 0;
	oh = NULL;
	for (c = 0; c < 8; c++) {
		if (sz < i->size)
			sz = i->size + 44;
		if (oh != NULL)
			free(oh);
		if ((oh = calloc(1, sz)) == NULL)
			continue;
		table_fill_objheader(oh, i);
		oh->opheader.version = 1; /* Current version */
		if (do_get3(IP_FW_TABLE_XLIST, &oh->opheader, &sz) == 0) {
			*poh = oh;
			return (0);
		}

		if (errno != ENOMEM)
			break;
	}
	free(oh);

	return (errno);
}
Пример #3
0
static int
table_do_lookup(ipfw_obj_header *oh, char *key, ipfw_xtable_info *xi,
    ipfw_obj_tentry *xtent)
{
	char xbuf[sizeof(ipfw_obj_header) + sizeof(ipfw_obj_tentry)];
	ipfw_obj_tentry *tent;
	uint8_t type;
	uint32_t vmask;
	size_t sz;

	memcpy(xbuf, oh, sizeof(*oh));
	oh = (ipfw_obj_header *)xbuf;
	tent = (ipfw_obj_tentry *)(oh + 1);

	memset(tent, 0, sizeof(*tent));
	tent->head.length = sizeof(*tent);
	tent->idx = 1;

	tentry_fill_key(oh, tent, key, 0, &type, &vmask, xi);
	oh->ntlv.type = type;

	sz = sizeof(xbuf);
	if (do_get3(IP_FW_TABLE_XFIND, &oh->opheader, &sz) != 0)
		return (errno);

	if (sz < sizeof(xbuf))
		return (EINVAL);

	*xtent = *tent;

	return (0);
}
Пример #4
0
static int
table_do_modify_record(int cmd, ipfw_obj_header *oh,
    ipfw_obj_tentry *tent, int count, int atomic)
{
	ipfw_obj_ctlv *ctlv;
	ipfw_obj_tentry *tent_base;
	caddr_t pbuf;
	char xbuf[sizeof(*oh) + sizeof(ipfw_obj_ctlv) + sizeof(*tent)];
	int error, i;
	size_t sz;

	sz = sizeof(*ctlv) + sizeof(*tent) * count;
	if (count == 1) {
		memset(xbuf, 0, sizeof(xbuf));
		pbuf = xbuf;
	} else {
		if ((pbuf = calloc(1, sizeof(*oh) + sz)) == NULL)
			return (ENOMEM);
	}

	memcpy(pbuf, oh, sizeof(*oh));
	oh = (ipfw_obj_header *)pbuf;
	oh->opheader.version = 1;

	ctlv = (ipfw_obj_ctlv *)(oh + 1);
	ctlv->count = count;
	ctlv->head.length = sz;
	if (atomic != 0)
		ctlv->flags |= IPFW_CTF_ATOMIC;

	tent_base = tent;
	memcpy(ctlv + 1, tent, sizeof(*tent) * count);
	tent = (ipfw_obj_tentry *)(ctlv + 1);
	for (i = 0; i < count; i++, tent++) {
		tent->head.length = sizeof(ipfw_obj_tentry);
		tent->idx = oh->idx;
	}

	sz += sizeof(*oh);
	error = do_get3(cmd, &oh->opheader, &sz);
	tent = (ipfw_obj_tentry *)(ctlv + 1);
	/* Copy result back to provided buffer */
	memcpy(tent_base, ctlv + 1, sizeof(*tent) * count);

	if (pbuf != xbuf)
		free(pbuf);

	return (error);
}
Пример #5
0
/*
 * Get NPTv6 instance statistics.
 * Request: [ ipfw_obj_header ]
 * Reply: [ ipfw_obj_header ipfw_obj_ctlv [ uint64_t x N ] ]
 */
static int
nptv6_get_stats(const char *name, uint8_t set, struct ipfw_nptv6_stats *stats)
{
	ipfw_obj_header *oh;
	ipfw_obj_ctlv *oc;
	size_t sz;

	sz = sizeof(*oh) + sizeof(*oc) + sizeof(*stats);
	oh = calloc(1, sz);
	nptv6_fill_ntlv(&oh->ntlv, name, set);
	if (do_get3(IP_FW_NPTV6_STATS, &oh->opheader, &sz) == 0) {
		oc = (ipfw_obj_ctlv *)(oh + 1);
		memcpy(stats, oc + 1, sizeof(*stats));
		free(oh);
		return (0);
	}
	free(oh);
	return (-1);
}
Пример #6
0
/*
 * Retrieves table in given table specified by @oh->ntlv.
 * it inside @i.
 * Returns 0 on success.
 */
static int
table_get_info(ipfw_obj_header *oh, ipfw_xtable_info *i)
{
	char tbuf[sizeof(ipfw_obj_header) + sizeof(ipfw_xtable_info)];
	size_t sz;

	sz = sizeof(tbuf);
	memset(tbuf, 0, sizeof(tbuf));
	memcpy(tbuf, oh, sizeof(*oh));
	oh = (ipfw_obj_header *)tbuf;

	if (do_get3(IP_FW_TABLE_XINFO, &oh->opheader, &sz) != 0)
		return (errno);

	if (sz < sizeof(tbuf))
		return (EINVAL);

	*i = *(ipfw_xtable_info *)(oh + 1);

	return (0);
}
Пример #7
0
/*
 * Retrieves table list from kernel,
 * optionally sorts it and calls requested function for each table.
 * Returns 0 on success.
 */
static int
tables_foreach(table_cb_t *f, void *arg, int sort)
{
	ipfw_obj_lheader *olh;
	ipfw_xtable_info *info;
	size_t sz;
	int i, error;

	/* Start with reasonable default */
	sz = sizeof(*olh) + 16 * sizeof(ipfw_xtable_info);

	for (;;) {
		if ((olh = calloc(1, sz)) == NULL)
			return (ENOMEM);

		olh->size = sz;
		if (do_get3(IP_FW_TABLES_XLIST, &olh->opheader, &sz) != 0) {
			sz = olh->size;
			free(olh);
			if (errno != ENOMEM)
				return (errno);
			continue;
		}

		if (sort != 0)
			qsort(olh + 1, olh->count, olh->objsize, tablename_cmp);

		info = (ipfw_xtable_info *)(olh + 1);
		for (i = 0; i < olh->count; i++) {
			error = f(info, arg); /* Ignore errors for now */
			info = (ipfw_xtable_info *)((caddr_t)info + olh->objsize);
		}

		free(olh);
		break;
	}

	return (0);
}
Пример #8
0
/*
 * Retrieves nat64lsn instance list from kernel,
 * optionally sorts it and calls requested function for each instance.
 *
 * Request: [ ipfw_obj_lheader ]
 * Reply: [ ipfw_obj_lheader ipfw_nat64lsn_cfg x N ]
 */
static int
nat64lsn_foreach(nat64lsn_cb_t *f, const char *name, uint8_t set,  int sort)
{
	ipfw_obj_lheader *olh;
	ipfw_nat64lsn_cfg *cfg;
	size_t sz;
	int i, error;

	/* Start with reasonable default */
	sz = sizeof(*olh) + 16 * sizeof(ipfw_nat64lsn_cfg);

	for (;;) {
		if ((olh = calloc(1, sz)) == NULL)
			return (ENOMEM);

		olh->size = sz;
		if (do_get3(IP_FW_NAT64LSN_LIST, &olh->opheader, &sz) != 0) {
			sz = olh->size;
			free(olh);
			if (errno != ENOMEM)
				return (errno);
			continue;
		}

		if (sort != 0)
			qsort(olh + 1, olh->count, olh->objsize,
			    nat64name_cmp);

		cfg = (ipfw_nat64lsn_cfg *)(olh + 1);
		for (i = 0; i < olh->count; i++) {
			error = f(cfg, name, set); /* Ignore errors for now */
			cfg = (ipfw_nat64lsn_cfg *)((caddr_t)cfg +
			    olh->objsize);
		}
		free(olh);
		break;
	}
	return (0);
}
Пример #9
0
static int
nat64lsn_states_cb(ipfw_nat64lsn_cfg *cfg, const char *name, uint8_t set)
{
	ipfw_obj_header *oh;
	ipfw_obj_data *od;
	void *buf;
	uint64_t next_idx;
	size_t sz;

	if (name != NULL && strcmp(cfg->name, name) != 0)
		return (ESRCH);

	if (set != 0 && cfg->set != set)
		return (ESRCH);

	next_idx = 0;
	sz = 4096;
	if ((buf = calloc(1, sz)) == NULL)
		err(EX_OSERR, NULL);
	do {
		oh = (ipfw_obj_header *)buf;
		od = (ipfw_obj_data *)(oh + 1);
		nat64lsn_fill_ntlv(&oh->ntlv, cfg->name, set);
		od->head.type = IPFW_TLV_OBJDATA;
		od->head.length = sizeof(*od) + sizeof(next_idx);
		*((uint64_t *)(od + 1)) = next_idx;
		if (do_get3(IP_FW_NAT64LSN_LIST_STATES, &oh->opheader, &sz))
			err(EX_OSERR, "Error reading nat64lsn states");
		next_idx = nat64lsn_print_states(buf);
		sz = 4096;
		memset(buf, 0, sz);
	} while (next_idx != 0xFF);

	free(buf);
	return (0);
}
Пример #10
0
/*
 * Configures existing nat64clat instance
 * ipfw nat64clat <NAME> config <options>
 * Request: [ ipfw_obj_header ipfw_nat64clat_cfg ]
 */
static void
nat64clat_config(const char *name, uint8_t set, int ac, char **av)
{
	char buf[sizeof(ipfw_obj_header) + sizeof(ipfw_nat64clat_cfg)];
	ipfw_nat64clat_cfg *cfg;
	ipfw_obj_header *oh;
	char *opt;
	char *p;
	size_t sz;
	int tcmd;
	struct in6_addr prefix;
	uint8_t plen;

	if (ac == 0)
		errx(EX_USAGE, "config options required");
	memset(&buf, 0, sizeof(buf));
	oh = (ipfw_obj_header *)buf;
	cfg = (ipfw_nat64clat_cfg *)(oh + 1);
	sz = sizeof(buf);

	nat64clat_fill_ntlv(&oh->ntlv, name, set);
	if (do_get3(IP_FW_NAT64CLAT_CONFIG, &oh->opheader, &sz) != 0)
		err(EX_OSERR, "failed to get config for instance %s", name);

	while (ac > 0) {
		tcmd = get_token(nat64newcmds, *av, "option");
		opt = *av;
		ac--; av++;

		switch (tcmd) {
		case TOK_PLAT_PREFIX:
		case TOK_CLAT_PREFIX:
			if (tcmd == TOK_PLAT_PREFIX) {
				NEED1("IPv6 plat_prefix required");
			} else {
				NEED1("IPv6 clat_prefix required");
			}

			if ((p = strchr(*av, '/')) != NULL)
				*p++ = '\0';
			if (inet_pton(AF_INET6, *av, &prefix) != 1)
				errx(EX_USAGE,
				    "Bad prefix: %s", *av);
			plen = strtol(p, NULL, 10);
			if (ipfw_check_nat64prefix(&prefix, plen) != 0)
				errx(EX_USAGE,
				    "Bad prefix length: %s", p);
			if (tcmd == TOK_PLAT_PREFIX) {
				cfg->plat_prefix = prefix;
				cfg->plat_plen = plen;
			} else {
				cfg->clat_prefix = prefix;
				cfg->clat_plen = plen;
			}
			ac--; av++;
			break;
		case TOK_LOG:
			cfg->flags |= NAT64_LOG;
			break;
		case TOK_LOGOFF:
			cfg->flags &= ~NAT64_LOG;
			break;
		case TOK_PRIVATE:
			cfg->flags |= NAT64_ALLOW_PRIVATE;
			break;
		case TOK_PRIVATEOFF:
			cfg->flags &= ~NAT64_ALLOW_PRIVATE;
			break;
		default:
			errx(EX_USAGE, "Can't change %s option", opt);
		}
	}

	if (do_set3(IP_FW_NAT64CLAT_CONFIG, &oh->opheader, sizeof(buf)) != 0)
		err(EX_OSERR, "nat64clat instance configuration failed");
}
Пример #11
0
/*
 * Configures existing nat64lsn instance
 * ipfw nat64lsn <NAME> config <options>
 * Request: [ ipfw_obj_header ipfw_nat64lsn_cfg ]
 */
static void
nat64lsn_config(const char *name, uint8_t set, int ac, char **av)
{
	char buf[sizeof(ipfw_obj_header) + sizeof(ipfw_nat64lsn_cfg)];
	ipfw_nat64lsn_cfg *cfg;
	ipfw_obj_header *oh;
	size_t sz;
	char *opt;
	int tcmd;

	if (ac == 0)
		errx(EX_USAGE, "config options required");
	memset(&buf, 0, sizeof(buf));
	oh = (ipfw_obj_header *)buf;
	cfg = (ipfw_nat64lsn_cfg *)(oh + 1);
	sz = sizeof(buf);

	nat64lsn_fill_ntlv(&oh->ntlv, name, set);
	if (do_get3(IP_FW_NAT64LSN_CONFIG, &oh->opheader, &sz) != 0)
		err(EX_OSERR, "failed to get config for instance %s", name);

	while (ac > 0) {
		tcmd = get_token(nat64newcmds, *av, "option");
		opt = *av;
		ac--; av++;

		switch (tcmd) {
		case TOK_MAX_PORTS:
			NEED1("Max per-user ports required");
			cfg->max_ports = nat64lsn_parse_int(*av, opt);
			ac--; av++;
			break;
		case TOK_JMAXLEN:
			NEED1("job queue length required");
			cfg->jmaxlen = nat64lsn_parse_int(*av, opt);
			ac--; av++;
			break;
		case TOK_HOST_DEL_AGE:
			NEED1("host delete delay required");
			cfg->nh_delete_delay = (uint16_t)nat64lsn_parse_int(
			    *av, opt);
			ac--; av++;
			break;
		case TOK_PG_DEL_AGE:
			NEED1("portgroup delete delay required");
			cfg->pg_delete_delay = (uint16_t)nat64lsn_parse_int(
			    *av, opt);
			ac--; av++;
			break;
		case TOK_TCP_SYN_AGE:
			NEED1("tcp syn age required");
			cfg->st_syn_ttl = (uint16_t)nat64lsn_parse_int(
			    *av, opt);
			ac--; av++;
			break;
		case TOK_TCP_CLOSE_AGE:
			NEED1("tcp close age required");
			cfg->st_close_ttl = (uint16_t)nat64lsn_parse_int(
			    *av, opt);
			ac--; av++;
			break;
		case TOK_TCP_EST_AGE:
			NEED1("tcp est age required");
			cfg->st_estab_ttl = (uint16_t)nat64lsn_parse_int(
			    *av, opt);
			ac--; av++;
			break;
		case TOK_UDP_AGE:
			NEED1("udp age required");
			cfg->st_udp_ttl = (uint16_t)nat64lsn_parse_int(
			    *av, opt);
			ac--; av++;
			break;
		case TOK_ICMP_AGE:
			NEED1("icmp age required");
			cfg->st_icmp_ttl = (uint16_t)nat64lsn_parse_int(
			    *av, opt);
			ac--; av++;
			break;
		case TOK_LOG:
			cfg->flags |= NAT64_LOG;
			break;
		case TOK_LOGOFF:
			cfg->flags &= ~NAT64_LOG;
			break;
		default:
			errx(EX_USAGE, "Can't change %s option", opt);
		}
	}

	if (do_set3(IP_FW_NAT64LSN_CONFIG, &oh->opheader, sizeof(buf)) != 0)
		err(EX_OSERR, "nat64lsn instance configuration failed");
}