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); }
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); }
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); }
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); }