コード例 #1
0
ファイル: pf_lb.c プロジェクト: bradla/OpenBSD-Hammer2
int
pf_get_transaddr(struct pf_rule *r, struct pf_pdesc *pd,
    struct pf_src_node **sns, struct pf_rule **nr)
{
	struct pf_addr	naddr;
	u_int16_t	nport = 0;

#ifdef INET6
	if (pd->af != pd->naf)
		return (pf_get_transaddr_af(r, pd, sns));
#endif /* INET6 */

	if (r->nat.addr.type != PF_ADDR_NONE) {
		/* XXX is this right? what if rtable is changed at the same
		 * XXX time? where do I need to figure out the sport? */
		if (pf_get_sport(pd, r, &naddr, &nport,
		    r->nat.proxy_port[0], r->nat.proxy_port[1], sns)) {
			DPFPRINTF(LOG_NOTICE,
			    "pf: NAT proxy port allocation (%u-%u) failed",
			    r->nat.proxy_port[0],
			    r->nat.proxy_port[1]);
			return (-1);
		}
		*nr = r;
		PF_ACPY(&pd->nsaddr, &naddr, pd->af);
		pd->nsport = nport;
	}
	if (r->rdr.addr.type != PF_ADDR_NONE) {
		if (pf_map_addr(pd->af, r, &pd->nsaddr, &naddr, NULL, sns,
		    &r->rdr, PF_SN_RDR))
			return (-1);
		if ((r->rdr.opts & PF_POOL_TYPEMASK) == PF_POOL_BITMASK)
			PF_POOLMASK(&naddr, &naddr,  &r->rdr.addr.v.a.mask,
			    &pd->ndaddr, pd->af);

			if (r->rdr.proxy_port[1]) {
				u_int32_t	tmp_nport;

				tmp_nport = ((ntohs(pd->ndport) -
				    ntohs(r->dst.port[0])) %
				    (r->rdr.proxy_port[1] -
				    r->rdr.proxy_port[0] + 1)) +
				    r->rdr.proxy_port[0];

				/* wrap around if necessary */
				if (tmp_nport > 65535)
					tmp_nport -= 65535;
				nport = htons((u_int16_t)tmp_nport);
			} else if (r->rdr.proxy_port[0])
				nport = htons(r->rdr.proxy_port[0]);
		*nr = r;
		PF_ACPY(&pd->ndaddr, &naddr, pd->af);
		if (nport)
			pd->ndport = nport;
	}

	return (0);
}
コード例 #2
0
ファイル: pf_lb.c プロジェクト: 7shi/openbsd-loongson-vc
int
pf_get_transaddr(struct pf_rule *r, struct pf_pdesc *pd, struct pf_addr *saddr,
    u_int16_t *sport, struct pf_addr *daddr, u_int16_t *dport,
    struct pf_src_node **sns)
{
	struct pf_addr	naddr;
	u_int16_t	nport = 0;

	if (!TAILQ_EMPTY(&r->nat.list)) {
		/* XXX is this right? what if rtable is changed at the same
		 * XXX time? where do I need to figure out the sport? */
		if (pf_get_sport(pd->af, pd->proto, r, saddr,
		    daddr, *dport, &naddr, &nport, r->nat.proxy_port[0],
		    r->nat.proxy_port[1], sns, pd->rdomain)) {
			DPFPRINTF(PF_DEBUG_MISC,
			    ("pf: NAT proxy port allocation "
			    "(%u-%u) failed\n",
			    r->nat.proxy_port[0],
			    r->nat.proxy_port[1]));
			return (-1);
		}
		PF_ACPY(saddr, &naddr, pd->af);
		if (nport)
			*sport = nport;
	}
	if (!TAILQ_EMPTY(&r->rdr.list)) {
		if (pf_map_addr(pd->af, r, saddr, &naddr, NULL, sns, &r->rdr,
		    PF_SN_RDR))
			return (-1);
		if ((r->rdr.opts & PF_POOL_TYPEMASK) == PF_POOL_BITMASK)
			PF_POOLMASK(&naddr, &naddr,  &r->rdr.cur->addr.v.a.mask,
			    daddr, pd->af);

			if (r->rdr.proxy_port[1]) {
				u_int32_t	tmp_nport;

				tmp_nport = ((ntohs(*dport) -
				    ntohs(r->dst.port[0])) %
				    (r->rdr.proxy_port[1] -
				    r->rdr.proxy_port[0] + 1)) +
				    r->rdr.proxy_port[0];

				/* wrap around if necessary */
				if (tmp_nport > 65535)
					tmp_nport -= 65535;
				nport = htons((u_int16_t)tmp_nport);
			} else if (r->rdr.proxy_port[0])
				nport = htons(r->rdr.proxy_port[0]);

		PF_ACPY(daddr, &naddr, pd->af);
		if (nport)
			*dport = nport;
	}

	return (0);
}
コード例 #3
0
struct pf_rule *
pf_get_translation(struct pf_pdesc *pd, struct mbuf *m, int off, int direction,
    struct pfi_kif *kif, struct pf_src_node **sn,
    struct pf_state_key **skp, struct pf_state_key **nkp,
    struct pf_addr *saddr, struct pf_addr *daddr,
    uint16_t sport, uint16_t dport, struct pf_anchor_stackframe *anchor_stack)
{
	struct pf_rule	*r = NULL;
	struct pf_addr	*naddr;
	uint16_t	*nport;

	PF_RULES_RASSERT();
	KASSERT(*skp == NULL, ("*skp not NULL"));
	KASSERT(*nkp == NULL, ("*nkp not NULL"));

	if (direction == PF_OUT) {
		r = pf_match_translation(pd, m, off, direction, kif, saddr,
		    sport, daddr, dport, PF_RULESET_BINAT, anchor_stack);
		if (r == NULL)
			r = pf_match_translation(pd, m, off, direction, kif,
			    saddr, sport, daddr, dport, PF_RULESET_NAT,
			    anchor_stack);
	} else {
		r = pf_match_translation(pd, m, off, direction, kif, saddr,
		    sport, daddr, dport, PF_RULESET_RDR, anchor_stack);
		if (r == NULL)
			r = pf_match_translation(pd, m, off, direction, kif,
			    saddr, sport, daddr, dport, PF_RULESET_BINAT,
			    anchor_stack);
	}

	if (r == NULL)
		return (NULL);

	switch (r->action) {
	case PF_NONAT:
	case PF_NOBINAT:
	case PF_NORDR:
		return (NULL);
	}

	*skp = pf_state_key_setup(pd, saddr, daddr, sport, dport);
	if (*skp == NULL)
		return (NULL);
	*nkp = pf_state_key_clone(*skp);
	if (*nkp == NULL) {
		uma_zfree(V_pf_state_key_z, skp);
		*skp = NULL;
		return (NULL);
	}

	/* XXX We only modify one side for now. */
	naddr = &(*nkp)->addr[1];
	nport = &(*nkp)->port[1];

	switch (r->action) {
	case PF_NAT:
		if (pf_get_sport(pd->af, pd->proto, r, saddr, sport, daddr,
		    dport, naddr, nport, r->rpool.proxy_port[0],
		    r->rpool.proxy_port[1], sn)) {
			DPFPRINTF(PF_DEBUG_MISC,
			    ("pf: NAT proxy port allocation (%u-%u) failed\n",
			    r->rpool.proxy_port[0], r->rpool.proxy_port[1]));
			goto notrans;
		}
		break;
	case PF_BINAT:
		switch (direction) {
		case PF_OUT:
			if (r->rpool.cur->addr.type == PF_ADDR_DYNIFTL){
				switch (pd->af) {
#ifdef INET
				case AF_INET:
					if (r->rpool.cur->addr.p.dyn->
					    pfid_acnt4 < 1)
						goto notrans;
					PF_POOLMASK(naddr,
					    &r->rpool.cur->addr.p.dyn->
					    pfid_addr4,
					    &r->rpool.cur->addr.p.dyn->
					    pfid_mask4, saddr, AF_INET);
					break;
#endif /* INET */
#ifdef INET6
				case AF_INET6:
					if (r->rpool.cur->addr.p.dyn->
					    pfid_acnt6 < 1)
						goto notrans;
					PF_POOLMASK(naddr,
					    &r->rpool.cur->addr.p.dyn->
					    pfid_addr6,
					    &r->rpool.cur->addr.p.dyn->
					    pfid_mask6, saddr, AF_INET6);
					break;
#endif /* INET6 */
				}
			} else
				PF_POOLMASK(naddr,
				    &r->rpool.cur->addr.v.a.addr,
				    &r->rpool.cur->addr.v.a.mask, saddr,
				    pd->af);
			break;
		case PF_IN:
			if (r->src.addr.type == PF_ADDR_DYNIFTL) {
				switch (pd->af) {
#ifdef INET
				case AF_INET:
					if (r->src.addr.p.dyn-> pfid_acnt4 < 1)
						goto notrans;
					PF_POOLMASK(naddr,
					    &r->src.addr.p.dyn->pfid_addr4,
					    &r->src.addr.p.dyn->pfid_mask4,
					    daddr, AF_INET);
					break;
#endif /* INET */
#ifdef INET6
				case AF_INET6:
					if (r->src.addr.p.dyn->pfid_acnt6 < 1)
						goto notrans;
					PF_POOLMASK(naddr,
					    &r->src.addr.p.dyn->pfid_addr6,
					    &r->src.addr.p.dyn->pfid_mask6,
					    daddr, AF_INET6);
					break;
#endif /* INET6 */
				}
			} else
				PF_POOLMASK(naddr, &r->src.addr.v.a.addr,
				    &r->src.addr.v.a.mask, daddr, pd->af);
			break;
		}
		break;
	case PF_RDR: {
		if (pf_map_addr(pd->af, r, saddr, naddr, NULL, sn))
			goto notrans;
		if ((r->rpool.opts & PF_POOL_TYPEMASK) == PF_POOL_BITMASK)
			PF_POOLMASK(naddr, naddr, &r->rpool.cur->addr.v.a.mask,
			    daddr, pd->af);

		if (r->rpool.proxy_port[1]) {
			uint32_t	tmp_nport;

			tmp_nport = ((ntohs(dport) - ntohs(r->dst.port[0])) %
			    (r->rpool.proxy_port[1] - r->rpool.proxy_port[0] +
			    1)) + r->rpool.proxy_port[0];

			/* Wrap around if necessary. */
			if (tmp_nport > 65535)
				tmp_nport -= 65535;
			*nport = htons((uint16_t)tmp_nport);
		} else if (r->rpool.proxy_port[0])
			*nport = htons(r->rpool.proxy_port[0]);
		break;
	}
	default:
		panic("%s: unknown action %u", __func__, r->action);
	}

	/* Return success only if translation really happened. */
	if (bcmp(*skp, *nkp, sizeof(struct pf_state_key_cmp)))
		return (r);

notrans:
	uma_zfree(V_pf_state_key_z, *nkp);
	uma_zfree(V_pf_state_key_z, *skp);
	*skp = *nkp = NULL;
	*sn = NULL;

	return (NULL);
}
コード例 #4
0
ファイル: pf_lb.c プロジェクト: bradla/OpenBSD-Hammer2
int
pf_get_transaddr_af(struct pf_rule *r, struct pf_pdesc *pd,
    struct pf_src_node **sns)
{
	struct pf_addr	ndaddr, nsaddr, naddr;
	u_int16_t	nport = 0;
	int		prefixlen = 96;

	if (pf_status.debug >= LOG_NOTICE) {
		log(LOG_NOTICE, "pf: af-to %s %s, ",
		    pd->naf == AF_INET ? "inet" : "inet6",
		    r->rdr.addr.type == PF_ADDR_NONE ? "nat" : "rdr");
		pf_print_host(&pd->nsaddr, pd->nsport, pd->af);
		addlog(" -> ");
		pf_print_host(&pd->ndaddr, pd->ndport, pd->af);
		addlog("\n");
	}

	if (r->nat.addr.type == PF_ADDR_NONE)
		panic("pf_get_transaddr_af: no nat pool for source address");

	/* get source address and port */
	if (pf_get_sport(pd, r, &nsaddr, &nport,
	    r->nat.proxy_port[0], r->nat.proxy_port[1], sns)) {
		DPFPRINTF(LOG_NOTICE,
		    "pf: af-to NAT proxy port allocation (%u-%u) failed",
		    r->nat.proxy_port[0],
		    r->nat.proxy_port[1]);
		return (-1);
	}
	pd->nsport = nport;

	if (pd->proto == IPPROTO_ICMPV6 && pd->naf == AF_INET) {
		if (pd->dir == PF_IN) {
			NTOHS(pd->ndport);
			if (pd->ndport == ICMP6_ECHO_REQUEST)
				pd->ndport = ICMP_ECHO;
			else if (pd->ndport == ICMP6_ECHO_REPLY)
				pd->ndport = ICMP_ECHOREPLY;
			HTONS(pd->ndport);
		} else {
			NTOHS(pd->nsport);
			if (pd->nsport == ICMP6_ECHO_REQUEST)
				pd->nsport = ICMP_ECHO;
			else if (pd->nsport == ICMP6_ECHO_REPLY)
				pd->nsport = ICMP_ECHOREPLY;
			HTONS(pd->nsport);
		}
	} else if (pd->proto == IPPROTO_ICMP && pd->naf == AF_INET6) {
		if (pd->dir == PF_IN) {
			NTOHS(pd->ndport);
			if (pd->ndport == ICMP_ECHO)
				pd->ndport = ICMP6_ECHO_REQUEST;
			else if (pd->ndport == ICMP_ECHOREPLY)
				pd->ndport = ICMP6_ECHO_REPLY;
			HTONS(pd->ndport);
		} else {
			NTOHS(pd->nsport);
			if (pd->nsport == ICMP_ECHO)
				pd->nsport = ICMP6_ECHO_REQUEST;
			else if (pd->nsport == ICMP_ECHOREPLY)
				pd->nsport = ICMP6_ECHO_REPLY;
			HTONS(pd->nsport);
		}
	}

	/* get the destination address and port */
	if (r->rdr.addr.type != PF_ADDR_NONE) {
		if (pf_map_addr(pd->naf, r, &nsaddr, &naddr, NULL, sns,
		    &r->rdr, PF_SN_RDR))
			return (-1);
		if (r->rdr.proxy_port[0])
			pd->ndport = htons(r->rdr.proxy_port[0]);

		if (pd->naf == AF_INET) {
			/* The prefix is the IPv4 rdr address */
			prefixlen = in_mask2len((struct in_addr *)
			    &r->rdr.addr.v.a.mask);
			inet_nat46(pd->naf, &pd->ndaddr,
			    &ndaddr, &naddr, prefixlen);
		} else {
			/* The prefix is the IPv6 rdr address */
			prefixlen =
			    in6_mask2len((struct in6_addr *)
			    &r->rdr.addr.v.a.mask, NULL);
			inet_nat64(pd->naf, &pd->ndaddr,
			    &ndaddr, &naddr, prefixlen);
		}
	} else {
		if (pd->naf == AF_INET) {
			/* The prefix is the IPv6 dst address */
			prefixlen =
			    in6_mask2len((struct in6_addr *)
			    &r->dst.addr.v.a.mask, NULL);
			if (prefixlen < 32)
				prefixlen = 96;
			inet_nat64(pd->naf, &pd->ndaddr,
			    &ndaddr, &pd->ndaddr, prefixlen);
		} else {
			/*
			 * The prefix is the IPv6 nat address
			 * (that was stored in pd->nsaddr)
			 */
			prefixlen = in6_mask2len((struct in6_addr *)
			    &r->nat.addr.v.a.mask, NULL);
			if (prefixlen > 96)
				prefixlen = 96;
			inet_nat64(pd->naf, &pd->ndaddr,
			    &ndaddr, &nsaddr, prefixlen);
		}
	}

	PF_ACPY(&pd->nsaddr, &nsaddr, pd->naf);
	PF_ACPY(&pd->ndaddr, &ndaddr, pd->naf);

	if (pf_status.debug >= LOG_NOTICE) {
		log(LOG_NOTICE, "pf: af-to %s %s done, prefixlen %d, ",
		    pd->naf == AF_INET ? "inet" : "inet6",
		    r->rdr.addr.type == PF_ADDR_NONE ? "nat" : "rdr",
		    prefixlen);
		pf_print_host(&pd->nsaddr, pd->nsport, pd->naf);
		addlog(" -> ");
		pf_print_host(&pd->ndaddr, pd->ndport, pd->naf);
		addlog("\n");
	}

	return (0);
}