示例#1
0
static int
export_config_cb(struct namedobj_instance *ni, struct named_object *no,
    void *arg)
{
	struct nat64_dump_arg *da = (struct nat64_dump_arg *)arg;
	ipfw_nat64lsn_cfg *uc;

	uc = (struct _ipfw_nat64lsn_cfg *)ipfw_get_sopt_space(da->sd,
	    sizeof(*uc));
	nat64lsn_export_config(da->ch, (struct nat64lsn_cfg *)no, uc);
	return (0);
}
示例#2
0
/*
 * Reply: [ ipfw_obj_header ipfw_obj_data [ ipfw_nat64lsn_stg
 *	ipfw_nat64lsn_state x count, ... ] ]
 */
static int
export_pg_states(struct nat64lsn_cfg *cfg, struct nat64lsn_portgroup *pg,
    ipfw_nat64lsn_stg *stg, struct sockopt_data *sd)
{
	ipfw_nat64lsn_state *ste;
	struct nat64lsn_state *st;
	int i, count;

	NAT64_LOCK(pg->host);
	count = 0;
	for (i = 0; i < 64; i++) {
		if (PG_IS_BUSY_IDX(pg, i))
			count++;
	}
	DPRINTF(DP_STATE, "EXPORT PG %d, count %d", pg->idx, count);

	if (count == 0) {
		stg->count = 0;
		NAT64_UNLOCK(pg->host);
		return (0);
	}
	ste = (ipfw_nat64lsn_state *)ipfw_get_sopt_space(sd,
	    count * sizeof(ipfw_nat64lsn_state));
	if (ste == NULL) {
		NAT64_UNLOCK(pg->host);
		return (1);
	}

	stg->alias4.s_addr = pg->aaddr;
	stg->proto = nat64lsn_rproto_map[pg->nat_proto];
	stg->flags = 0;
	stg->host6 = pg->host->addr;
	stg->count = count;
	for (i = 0; i < 64; i++) {
		if (PG_IS_FREE_IDX(pg, i))
			continue;
		st = &pg->states[i];
		ste->daddr.s_addr = st->u.s.faddr;
		ste->dport = st->u.s.fport;
		ste->aport = pg->aport + i;
		ste->sport = st->u.s.lport;
		ste->flags = st->flags; /* XXX filter flags */
		ste->idle = GET_AGE(st->timestamp);
		ste++;
	}
	NAT64_UNLOCK(pg->host);

	return (0);
}
示例#3
0
/*
 * Exports real value data into ipfw_table_value structure.
 * Utilizes "spare1" field to store kernel index.
 */
static void
dump_tvalue(struct namedobj_instance *ni, struct named_object *no, void *arg)
{
	struct vdump_args *da;
	struct table_val_link *ptv;
	struct table_value *v;

	da = (struct vdump_args *)arg;
	ptv = (struct table_val_link *)no;

	v = (struct table_value *)ipfw_get_sopt_space(da->sd, sizeof(*v));
	/* Out of memory, returning */
	if (v == NULL) {
		da->error = ENOMEM;
		return;
	}

	memcpy(v, ptv->pval, sizeof(*v));
	v->spare1 = ptv->no.kidx;
}
示例#4
0
static void
export_iface_internal(struct namedobj_instance *ii, struct named_object *no,
    void *arg)
{
	ipfw_iface_info *i;
	struct dump_iface_args *da;
	struct ipfw_iface *iif;

	da = (struct dump_iface_args *)arg;

	i = (ipfw_iface_info *)ipfw_get_sopt_space(da->sd, sizeof(*i));
	KASSERT(i != 0, ("previously checked buffer is not enough"));

	iif = (struct ipfw_iface *)no;

	strlcpy(i->ifname, iif->ifname, sizeof(i->ifname));
	if (iif->resolved)
		i->flags |= IPFW_IFFLAG_RESOLVED;
	i->ifindex = iif->ifindex;
	i->refcnt = iif->no.refcnt;
	i->gencnt = iif->gencnt;
}
示例#5
0
/*
 * Lists nat64lsn states.
 * Data layout (v0)(current):
 * Request: [ ipfw_obj_header ipfw_obj_data [ uint64_t ]]
 * Reply: [ ipfw_obj_header ipfw_obj_data [
 *		ipfw_nat64lsn_stg ipfw_nat64lsn_state x N] ]
 *
 * Returns 0 on success
 */
static int
nat64lsn_states(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
    struct sockopt_data *sd)
{
	ipfw_obj_header *oh;
	ipfw_obj_data *od;
	ipfw_nat64lsn_stg *stg;
	struct nat64lsn_cfg *cfg;
	struct nat64lsn_portgroup *pg, *pg_next;
	uint64_t next_idx;
	size_t sz;
	uint32_t addr, states;
	uint16_t port;
	uint8_t nat_proto;

	sz = sizeof(ipfw_obj_header) + sizeof(ipfw_obj_data) +
	    sizeof(uint64_t);
	/* Check minimum header size */
	if (sd->valsize < sz)
		return (EINVAL);

	oh = (ipfw_obj_header *)sd->kbuf;
	od = (ipfw_obj_data *)(oh + 1);
	if (od->head.type != IPFW_TLV_OBJDATA ||
	    od->head.length != sz - sizeof(ipfw_obj_header))
		return (EINVAL);

	next_idx = *(uint64_t *)(od + 1);
	/* Translate index to the request position to start from */
	UNPACK_IDX(next_idx, addr, nat_proto, port);
	if (nat_proto >= NAT_MAX_PROTO)
		return (EINVAL);
	if (nat_proto == 0 && addr != 0)
		return (EINVAL);

	IPFW_UH_RLOCK(ch);
	cfg = nat64lsn_find(CHAIN_TO_SRV(ch), oh->ntlv.name, oh->ntlv.set);
	if (cfg == NULL) {
		IPFW_UH_RUNLOCK(ch);
		return (ESRCH);
	}
	/* Fill in starting point */
	if (addr == 0) {
		addr = cfg->prefix4;
		nat_proto = 1;
		port = 0;
	}
	if (addr < cfg->prefix4 || addr > cfg->pmask4) {
		IPFW_UH_RUNLOCK(ch);
		DPRINTF(DP_GENERIC | DP_STATE, "XXX: %lu %u %u",
		    next_idx, addr, cfg->pmask4);
		return (EINVAL);
	}

	sz = sizeof(ipfw_obj_header) + sizeof(ipfw_obj_data) +
	    sizeof(ipfw_nat64lsn_stg);
	if (sd->valsize < sz)
		return (ENOMEM);
	oh = (ipfw_obj_header *)ipfw_get_sopt_space(sd, sz);
	od = (ipfw_obj_data *)(oh + 1);
	od->head.type = IPFW_TLV_OBJDATA;
	od->head.length = sz - sizeof(ipfw_obj_header);
	stg = (ipfw_nat64lsn_stg *)(od + 1);

	pg = get_first_pg(cfg, &addr, &nat_proto, &port);
	if (pg == NULL) {
		/* No states */
		stg->next_idx = 0xFF;
		stg->count = 0;
		IPFW_UH_RUNLOCK(ch);
		return (0);
	}
	states = 0;
	pg_next = NULL;
	while (pg != NULL) {
		pg_next = get_next_pg(cfg, &addr, &nat_proto, &port);
		if (pg_next == NULL)
			stg->next_idx = 0xFF;
		else
			stg->next_idx = PACK_IDX(addr, nat_proto, port);

		if (export_pg_states(cfg, pg, stg, sd) != 0) {
			IPFW_UH_RUNLOCK(ch);
			return (states == 0 ? ENOMEM: 0);
		}
		states += stg->count;
		od->head.length += stg->count * sizeof(ipfw_nat64lsn_state);
		sz += stg->count * sizeof(ipfw_nat64lsn_state);
		if (pg_next != NULL) {
			sz += sizeof(ipfw_nat64lsn_stg);
			if (sd->valsize < sz)
				break;
			stg = (ipfw_nat64lsn_stg *)ipfw_get_sopt_space(sd,
			    sizeof(ipfw_nat64lsn_stg));
		}
		pg = pg_next;
	}
	IPFW_UH_RUNLOCK(ch);
	return (0);
}
示例#6
0
/*
 * Change existing nat64lsn instance configuration.
 * Data layout (v0)(current):
 * Request: [ ipfw_obj_header ipfw_nat64lsn_cfg ]
 * Reply: [ ipfw_obj_header ipfw_nat64lsn_cfg ]
 *
 * Returns 0 on success
 */
static int
nat64lsn_config(struct ip_fw_chain *ch, ip_fw3_opheader *op,
    struct sockopt_data *sd)
{
	ipfw_obj_header *oh;
	ipfw_nat64lsn_cfg *uc;
	struct nat64lsn_cfg *cfg;
	struct namedobj_instance *ni;

	if (sd->valsize != sizeof(*oh) + sizeof(*uc))
		return (EINVAL);

	oh = (ipfw_obj_header *)ipfw_get_sopt_space(sd,
	    sizeof(*oh) + sizeof(*uc));
	uc = (ipfw_nat64lsn_cfg *)(oh + 1);

	if (ipfw_check_object_name_generic(oh->ntlv.name) != 0 ||
	    oh->ntlv.set >= IPFW_MAX_SETS)
		return (EINVAL);

	ni = CHAIN_TO_SRV(ch);
	if (sd->sopt->sopt_dir == SOPT_GET) {
		IPFW_UH_RLOCK(ch);
		cfg = nat64lsn_find(ni, oh->ntlv.name, oh->ntlv.set);
		if (cfg == NULL) {
			IPFW_UH_RUNLOCK(ch);
			return (EEXIST);
		}
		nat64lsn_export_config(ch, cfg, uc);
		IPFW_UH_RUNLOCK(ch);
		return (0);
	}

	nat64lsn_default_config(uc);

	IPFW_UH_WLOCK(ch);
	cfg = nat64lsn_find(ni, oh->ntlv.name, oh->ntlv.set);
	if (cfg == NULL) {
		IPFW_UH_WUNLOCK(ch);
		return (EEXIST);
	}

	/*
	 * For now allow to change only following values:
	 *  jmaxlen, nh_del_age, pg_del_age, tcp_syn_age, tcp_close_age,
	 *  tcp_est_age, udp_age, icmp_age, flags, max_ports.
	 */

	cfg->max_chunks = uc->max_ports / NAT64_CHUNK_SIZE;
	cfg->jmaxlen = uc->jmaxlen;
	cfg->nh_delete_delay = uc->nh_delete_delay;
	cfg->pg_delete_delay = uc->pg_delete_delay;
	cfg->st_syn_ttl = uc->st_syn_ttl;
	cfg->st_close_ttl = uc->st_close_ttl;
	cfg->st_estab_ttl = uc->st_estab_ttl;
	cfg->st_udp_ttl = uc->st_udp_ttl;
	cfg->st_icmp_ttl = uc->st_icmp_ttl;
	cfg->flags = uc->flags & NAT64LSN_FLAGSMASK;

	IPFW_UH_WUNLOCK(ch);

	return (0);
}