/*
- * Copyright (c) 2007-2014 Apple Inc. All rights reserved.
+ * Copyright (c) 2007-2015 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
#endif /* PF_ALTQ */
u_int32_t pf_hash_seed;
+int16_t pf_nat64_configured = 0;
/*
* These are the pf enabled reference counting variables
sp->lan.xport = sk->lan.xport;
sp->gwy.addr = sk->gwy.addr;
sp->gwy.xport = sk->gwy.xport;
- sp->ext.addr = sk->ext.addr;
- sp->ext.xport = sk->ext.xport;
+ sp->ext_lan.addr = sk->ext_lan.addr;
+ sp->ext_lan.xport = sk->ext_lan.xport;
+ sp->ext_gwy.addr = sk->ext_gwy.addr;
+ sp->ext_gwy.xport = sk->ext_gwy.xport;
sp->proto_variant = sk->proto_variant;
sp->tag = s->tag;
sp->proto = sk->proto;
- sp->af = sk->af;
+ sp->af_lan = sk->af_lan;
+ sp->af_gwy = sk->af_gwy;
sp->direction = sk->direction;
sp->flowhash = sk->flowhash;
sk->lan.xport = sp->lan.xport;
sk->gwy.addr = sp->gwy.addr;
sk->gwy.xport = sp->gwy.xport;
- sk->ext.addr = sp->ext.addr;
- sk->ext.xport = sp->ext.xport;
+ sk->ext_lan.addr = sp->ext_lan.addr;
+ sk->ext_lan.xport = sp->ext_lan.xport;
+ sk->ext_gwy.addr = sp->ext_gwy.addr;
+ sk->ext_gwy.xport = sp->ext_gwy.xport;
sk->proto_variant = sp->proto_variant;
s->tag = sp->tag;
sk->proto = sp->proto;
- sk->af = sp->af;
+ sk->af_lan = sp->af_lan;
+ sk->af_gwy = sp->af_gwy;
sk->direction = sp->direction;
sk->flowhash = pf_calc_state_key_flowhash(sk);
}
if (rule == NULL)
return (ENOENT);
- else
+ else
i--;
if (strcmp(rule->owner, pr->rule.owner))
if (rule == NULL)
panic("%s: rule not found!", __func__);
- /*
+ /*
* if reqest device != rule's device, bail :
* with error if ticket matches;
* without error if ticket doesn't match (i.e. its just cleanup)
++delete_ruleset->rules[i].inactive.ticket;
goto delete_rule;
} else {
- /*
+ /*
* process deleting rule only if device that added the
* rule matches device that issued the request
*/
ruleset = &pf_main_ruleset;
while (rule) {
next = TAILQ_NEXT(rule, entries);
- /*
+ /*
* process deleting rule only if device that added the
* rule matches device that issued the request
*/
}
pf_mv_pool(&pf_pabuf, &rule->rpool.list);
+
if (((((rule->action == PF_NAT) || (rule->action == PF_RDR) ||
- (rule->action == PF_BINAT)) && rule->anchor == NULL) ||
+ (rule->action == PF_BINAT) || (rule->action == PF_NAT64)) &&
+ rule->anchor == NULL) ||
(rule->rt > PF_FASTROUTE)) &&
(TAILQ_FIRST(&rule->rpool.list) == NULL))
error = EINVAL;
pf_rm_rule(NULL, rule);
return (error);
}
+ /* For a NAT64 rule the rule's address family is AF_INET6 whereas
+ * the address pool's family will be AF_INET
+ */
+ rule->rpool.af = (rule->action == PF_NAT64) ? AF_INET: rule->af;
rule->rpool.cur = TAILQ_FIRST(&rule->rpool.list);
rule->evaluations = rule->packets[0] = rule->packets[1] =
rule->bytes[0] = rule->bytes[1] = 0;
ruleset->rules[rs_num].inactive.rcount++;
if (rule->rule_flag & PFRULE_PFM)
pffwrules++;
+
+ if (rule->action == PF_NAT64)
+ atomic_add_16(&pf_nat64_configured, 1);
break;
}
pf_rule_copyout(rule, &pr->rule);
if (rule->rule_flag & PFRULE_PFM)
pffwrules++;
+ if (rule->action == PF_NAT64)
+ atomic_add_16(&pf_nat64_configured, 1);
break;
}
} else
pf_delete_rule_by_owner(pr->rule.owner, req_dev);
pr->nr = pffwrules;
+ if (pr->rule.action == PF_NAT64)
+ atomic_add_16(&pf_nat64_configured, -1);
break;
}
if (sk->direction == PF_OUT) {
src = &sk->lan;
- dst = &sk->ext;
+ dst = &sk->ext_lan;
} else {
- src = &sk->ext;
+ src = &sk->ext_lan;
dst = &sk->lan;
}
- if ((!psk->psk_af || sk->af == psk->psk_af) &&
+ if ((!psk->psk_af || sk->af_lan == psk->psk_af) &&
(!psk->psk_proto || psk->psk_proto == sk->proto) &&
PF_MATCHA(psk->psk_src.neg,
&psk->psk_src.addr.v.a.addr,
&psk->psk_src.addr.v.a.mask,
- &src->addr, sk->af) &&
+ &src->addr, sk->af_lan) &&
PF_MATCHA(psk->psk_dst.neg,
&psk->psk_dst.addr.v.a.addr,
&psk->psk_dst.addr.v.a.mask,
- &dst->addr, sk->af) &&
+ &dst->addr, sk->af_lan) &&
(pf_match_xport(psk->psk_proto,
psk->psk_proto_variant, &psk->psk_src.xport,
&src->xport)) &&
struct pf_state_key_cmp key;
int m = 0, direction = pnl->direction;
- key.af = pnl->af;
key.proto = pnl->proto;
key.proto_variant = pnl->proto_variant;
* state tree.
*/
if (direction == PF_IN) {
- PF_ACPY(&key.ext.addr, &pnl->daddr, pnl->af);
- memcpy(&key.ext.xport, &pnl->dxport,
- sizeof (key.ext.xport));
+ key.af_gwy = pnl->af;
+ PF_ACPY(&key.ext_gwy.addr, &pnl->daddr,
+ pnl->af);
+ memcpy(&key.ext_gwy.xport, &pnl->dxport,
+ sizeof (key.ext_gwy.xport));
PF_ACPY(&key.gwy.addr, &pnl->saddr, pnl->af);
memcpy(&key.gwy.xport, &pnl->sxport,
sizeof (key.gwy.xport));
state = pf_find_state_all(&key, PF_IN, &m);
} else {
+ key.af_lan = pnl->af;
PF_ACPY(&key.lan.addr, &pnl->daddr, pnl->af);
memcpy(&key.lan.xport, &pnl->dxport,
sizeof (key.lan.xport));
- PF_ACPY(&key.ext.addr, &pnl->saddr, pnl->af);
- memcpy(&key.ext.xport, &pnl->sxport,
- sizeof (key.ext.xport));
+ PF_ACPY(&key.ext_lan.addr, &pnl->saddr,
+ pnl->af);
+ memcpy(&key.ext_lan.xport, &pnl->sxport,
+ sizeof (key.ext_lan.xport));
state = pf_find_state_all(&key, PF_OUT, &m);
}
if (m > 1)
sk = state->state_key;
if (direction == PF_IN) {
PF_ACPY(&pnl->rsaddr, &sk->lan.addr,
- sk->af);
+ sk->af_lan);
memcpy(&pnl->rsxport, &sk->lan.xport,
sizeof (pnl->rsxport));
PF_ACPY(&pnl->rdaddr, &pnl->daddr,
sizeof (pnl->rdxport));
} else {
PF_ACPY(&pnl->rdaddr, &sk->gwy.addr,
- sk->af);
+ sk->af_gwy);
memcpy(&pnl->rdxport, &sk->gwy.xport,
sizeof (pnl->rdxport));
PF_ACPY(&pnl->rsaddr, &pnl->saddr,
net_thread_marks_t marks;
struct ifnet * pf_ifp = ifp;
+ /* Always allow traffic on co-processor interfaces. */
+ if (ifp && IFNET_IS_INTCOPROC(ifp))
+ return (0);
+
marks = net_thread_marks_push(NET_THREAD_HELD_PF);
if (marks != net_thread_marks_none) {