extern int ip_optcopy(struct ip *, struct ip *);
extern int debug_pfugidhack;
+struct lwkt_token pf_token = LWKT_TOKEN_MP_INITIALIZER(pf_token);
+
#define DPFPRINTF(n, x) if (pf_status.debug >= (n)) kprintf x
/*
pf_unlink_state(struct pf_state *cur)
{
if (cur->src.state == PF_TCPS_PROXY_DST) {
+ lwkt_reltoken(&pf_token);
pf_send_tcp(cur->rule.ptr, cur->state_key->af,
&cur->state_key->ext.addr, &cur->state_key->lan.addr,
cur->state_key->ext.port, cur->state_key->lan.port,
cur->src.seqhi, cur->src.seqlo + 1,
TH_RST|TH_ACK, 0, 0, 0, 1, cur->tag, NULL, NULL);
+ lwkt_gettoken(&pf_token);
}
RB_REMOVE(pf_state_tree_id, &tree_id, cur);
#if NPFSYNC
struct tcphdr *th = NULL;
char *opt;
+ lwkt_gettoken(&pf_token);
+
/* maximum segment size tcp option */
tlen = sizeof(struct tcphdr);
if (mss)
/* create outgoing mbuf */
m = m_gethdr(MB_DONTWAIT, MT_HEADER);
- if (m == NULL)
+ if (m == NULL) {
+ lwkt_reltoken(&pf_token);
return;
+ }
if (tag)
m->m_pkthdr.pf.flags |= PF_TAG_GENERATED;
m->m_pkthdr.pf.tag = rtag;
h->ip_ttl = ttl ? ttl : ip_defttl;
h->ip_sum = 0;
if (eh == NULL) {
+ lwkt_reltoken(&pf_token);
ip_output(m, NULL, NULL, 0, NULL, NULL);
+ lwkt_gettoken(&pf_token);
} else {
struct route ro;
struct rtentry rt;
if (ifp == NULL) {
m_freem(m);
+ lwkt_reltoken(&pf_token);
return;
}
rt.rt_ifp = ifp;
bcopy(eh->ether_shost, e->ether_dhost, ETHER_ADDR_LEN);
e->ether_type = eh->ether_type;
/* XXX_IMPORT: later */
+ lwkt_reltoken(&pf_token);
ip_output(m, (void *)NULL, &ro, 0,
(void *)NULL, (void *)NULL);
+ lwkt_gettoken(&pf_token);
}
break;
#endif /* INET */
h6->ip6_vfc |= IPV6_VERSION;
h6->ip6_hlim = IPV6_DEFHLIM;
+ lwkt_reltoken(&pf_token);
ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL);
+ lwkt_gettoken(&pf_token);
break;
#endif /* INET6 */
}
+ lwkt_reltoken(&pf_token);
}
void
ack++;
if (th->th_flags & TH_FIN)
ack++;
+ lwkt_reltoken(&pf_token);
pf_send_tcp(r, af, pd->dst,
pd->src, th->th_dport, th->th_sport,
ntohl(th->th_ack), ack, TH_RST|TH_ACK, 0, 0,
r->return_ttl, 1, 0, pd->eh, kif->pfik_ifp);
+ lwkt_gettoken(&pf_token);
}
} else if ((af == AF_INET) && r->return_icmp)
pf_send_icmp(m, r->return_icmp >> 8,
mss = pf_calc_mss(saddr, af, mss);
mss = pf_calc_mss(daddr, af, mss);
s->src.mss = mss;
+ lwkt_reltoken(&pf_token);
pf_send_tcp(r, af, daddr, saddr, th->th_dport,
th->th_sport, s->src.seqhi, ntohl(th->th_seq) + 1,
TH_SYN|TH_ACK, 0, s->src.mss, 0, 1, 0, NULL, NULL);
+ lwkt_gettoken(&pf_token);
REASON_SET(&reason, PFRES_SYNPROXY);
return (PF_SYNPROXY_DROP);
}
REASON_SET(reason, PFRES_SYNPROXY);
return (PF_DROP);
}
+ lwkt_reltoken(&pf_token);
pf_send_tcp((*state)->rule.ptr, pd->af, pd->dst,
pd->src, th->th_dport, th->th_sport,
(*state)->src.seqhi, ntohl(th->th_seq) + 1,
TH_SYN|TH_ACK, 0, (*state)->src.mss, 0, 1,
0, NULL, NULL);
+ lwkt_gettoken(&pf_token);
REASON_SET(reason, PFRES_SYNPROXY);
return (PF_SYNPROXY_DROP);
} else if (!(th->th_flags & TH_ACK) ||
(*state)->src.max_win = MAX(ntohs(th->th_win), 1);
if ((*state)->dst.seqhi == 1)
(*state)->dst.seqhi = htonl(karc4random());
+ lwkt_reltoken(&pf_token);
pf_send_tcp((*state)->rule.ptr, pd->af, &src->addr,
&dst->addr, src->port, dst->port,
(*state)->dst.seqhi, 0, TH_SYN, 0,
(*state)->src.mss, 0, 0, (*state)->tag, NULL, NULL);
+ lwkt_gettoken(&pf_token);
REASON_SET(reason, PFRES_SYNPROXY);
return (PF_SYNPROXY_DROP);
} else if (((th->th_flags & (TH_SYN|TH_ACK)) !=
} else {
(*state)->dst.max_win = MAX(ntohs(th->th_win), 1);
(*state)->dst.seqlo = ntohl(th->th_seq);
+ lwkt_reltoken(&pf_token);
pf_send_tcp((*state)->rule.ptr, pd->af, pd->dst,
pd->src, th->th_dport, th->th_sport,
ntohl(th->th_ack), ntohl(th->th_seq) + 1,
(*state)->src.seqhi + 1, (*state)->src.seqlo + 1,
TH_ACK, (*state)->dst.max_win, 0, 0, 1,
0, NULL, NULL);
+ lwkt_gettoken(&pf_token);
(*state)->src.seqdiff = (*state)->dst.seqhi -
(*state)->src.seqlo;
(*state)->dst.seqdiff = (*state)->src.seqhi -
(*state)->src.state == TCPS_SYN_SENT) {
/* Send RST for state mismatches during handshake */
if (!(th->th_flags & TH_RST))
+ lwkt_reltoken(&pf_token);
pf_send_tcp((*state)->rule.ptr, pd->af,
pd->dst, pd->src, th->th_dport,
th->th_sport, ntohl(th->th_ack), 0,
TH_RST, 0, 0,
(*state)->rule.ptr->return_ttl, 1, 0,
pd->eh, kif->pfik_ifp);
+ lwkt_gettoken(&pf_token);
src->seqlo = 0;
src->seqhi = 1;
src->max_win = 1;
* the protocol stack on the wrong cpu for the
* post-translated address.
*/
- m->m_pkthdr.fw_flags |= FW_MBUF_REDISPATCH;
+ /* m->m_pkthdr.fw_flags |= FW_MBUF_REDISPATCH; */
+ m->m_flags &= ~M_HASH;
pf_change_ap(pd->dst, &th->th_dport, pd->ip_sum,
&th->th_sum, &(*state)->state_key->lan.addr,
(*state)->state_key->lan.port, 0, pd->af);
* the protocol stack on the wrong cpu for the
* post-translated address.
*/
- m->m_pkthdr.fw_flags |= FW_MBUF_REDISPATCH;
+ /* m->m_pkthdr.fw_flags |= FW_MBUF_REDISPATCH; */
+ m->m_flags &= ~M_HASH;
pf_change_ap(pd->dst, &uh->uh_dport, pd->ip_sum,
&uh->uh_sum, &(*state)->state_key->lan.addr,
(*state)->state_key->lan.port, 1, pd->af);
#endif
int ret = 0;
+ lwkt_gettoken(&pf_token);
+
bzero(&ro, sizeof(ro));
switch (af) {
case AF_INET:
break;
#endif /* INET6 */
default:
+ lwkt_reltoken(&pf_token);
return (0);
}
RTFREE(ro.ro_rt);
}
+ lwkt_reltoken(&pf_token);
return (ret);
}
struct m_tag *mtag;
#endif /* IPSEC */
+ lwkt_gettoken(&pf_token);
+
if (m == NULL || *m == NULL || r == NULL ||
(dir != PF_IN && dir != PF_OUT) || oifp == NULL)
panic("pf_route: invalid parameters");
}
if (r->rt == PF_DUPTO) {
- if ((m0 = m_dup(*m, MB_DONTWAIT)) == NULL)
+ if ((m0 = m_dup(*m, MB_DONTWAIT)) == NULL) {
+ lwkt_reltoken(&pf_token);
return;
+ }
} else {
- if ((r->rt == PF_REPLYTO) == (r->direction == dir))
+ if ((r->rt == PF_REPLYTO) == (r->direction == dir)) {
+ lwkt_reltoken(&pf_token);
return;
+ }
m0 = *m;
}
ip->ip_sum = in_cksum(m0, ip->ip_hl << 2);
}
}
+ lwkt_reltoken(&pf_token);
crit_exit();
error = ifp->if_output(ifp, m0, sintosa(dst), ro->ro_rt);
crit_enter();
+ lwkt_gettoken(&pf_token);
goto done;
}
m1 = m0->m_nextpkt;
m0->m_nextpkt = 0;
if (error == 0) {
+ lwkt_reltoken(&pf_token);
crit_exit();
error = (*ifp->if_output)(ifp, m0, sintosa(dst),
NULL);
crit_enter();
+ lwkt_gettoken(&pf_token);
} else
m_freem(m0);
}
*m = NULL;
if (ro == &iproute && ro->ro_rt)
RTFREE(ro->ro_rt);
+ lwkt_reltoken(&pf_token);
return;
bad:
int
pfopen(struct dev_open_args *ap)
{
+ lwkt_gettoken(&pf_token);
cdev_t dev = ap->a_head.a_dev;
- if (minor(dev) >= 1)
+ if (minor(dev) >= 1) {
+ lwkt_reltoken(&pf_token);
return (ENXIO);
+ }
+ lwkt_reltoken(&pf_token);
return (0);
}
int
pfclose(struct dev_close_args *ap)
{
+ lwkt_gettoken(&pf_token);
cdev_t dev = ap->a_head.a_dev;
- if (minor(dev) >= 1)
+ if (minor(dev) >= 1) {
+ lwkt_reltoken(&pf_token);
return (ENXIO);
+ }
+ lwkt_reltoken(&pf_token);
return (0);
}
struct pf_pool *pool = NULL;
int error = 0;
+ lwkt_gettoken(&pf_token);
+
/* XXX keep in sync with switch() below */
if (securelevel > 1)
switch (cmd) {
if (((struct pfioc_table *)addr)->pfrio_flags &
PFR_FLAG_DUMMY)
break; /* dummy operation ok */
+ lwkt_reltoken(&pf_token);
return (EPERM);
default:
+ lwkt_reltoken(&pf_token);
return (EPERM);
}
if (((struct pfioc_table *)addr)->pfrio_flags &
PFR_FLAG_DUMMY)
break; /* dummy operation ok */
+ lwkt_reltoken(&pf_token);
return (EACCES);
case DIOCGETRULE:
- if (((struct pfioc_rule *)addr)->action == PF_GET_CLR_CNTR)
+ if (((struct pfioc_rule *)addr)->action == PF_GET_CLR_CNTR) {
+ lwkt_reltoken(&pf_token);
return (EACCES);
+ }
break;
default:
+ lwkt_reltoken(&pf_token);
return (EACCES);
}
break;
}
fail:
+ lwkt_reltoken(&pf_token);
return (error);
}
*/
int chk;
+ lwkt_gettoken(&pf_token);
+
chk = pf_test(PF_IN, ifp, m, NULL, NULL);
if (chk && *m) {
m_freem(*m);
*m = NULL;
}
+ lwkt_reltoken(&pf_token);
return chk;
}
*/
int chk;
+ lwkt_gettoken(&pf_token);
+
/* We need a proper CSUM befor we start (s. OpenBSD ip_output) */
if ((*m)->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
in_delayed_cksum(*m);
m_freem(*m);
*m = NULL;
}
+ lwkt_reltoken(&pf_token);
return chk;
}
*/
int chk;
+ lwkt_gettoken(&pf_token);
+
chk = pf_test6(PF_IN, ifp, m, NULL, NULL);
if (chk && *m) {
m_freem(*m);
*m = NULL;
}
+ lwkt_reltoken(&pf_token);
return chk;
}
*/
int chk;
+ lwkt_gettoken(&pf_token);
+
/* We need a proper CSUM befor we start (s. OpenBSD ip_output) */
if ((*m)->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
in_delayed_cksum(*m);
m_freem(*m);
*m = NULL;
}
+ lwkt_reltoken(&pf_token);
return chk;
}
#endif /* INET6 */
#ifdef INET6
struct pfil_head *pfh_inet6;
#endif
-
- if (pf_pfil_hooked)
- return (0);
+
+ lwkt_gettoken(&pf_token);
+
+ if (pf_pfil_hooked) {
+ lwkt_reltoken(&pf_token);
+ return (0);
+ }
pfh_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET);
- if (pfh_inet == NULL)
+ if (pfh_inet == NULL) {
+ lwkt_reltoken(&pf_token);
return (ENODEV);
+ }
pfil_add_hook(pf_check_in, NULL, PFIL_IN, pfh_inet);
pfil_add_hook(pf_check_out, NULL, PFIL_OUT, pfh_inet);
#ifdef INET6
if (pfh_inet6 == NULL) {
pfil_remove_hook(pf_check_in, NULL, PFIL_IN, pfh_inet);
pfil_remove_hook(pf_check_out, NULL, PFIL_OUT, pfh_inet);
+ lwkt_reltoken(&pf_token);
return (ENODEV);
}
pfil_add_hook(pf_check6_in, NULL, PFIL_IN, pfh_inet6);
#endif
pf_pfil_hooked = 1;
+ lwkt_reltoken(&pf_token);
return (0);
}
struct pfil_head *pfh_inet6;
#endif
- if (pf_pfil_hooked == 0)
+ lwkt_gettoken(&pf_token);
+
+ if (pf_pfil_hooked == 0) {
+ lwkt_reltoken(&pf_token);
return (0);
+ }
pfh_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET);
- if (pfh_inet == NULL)
+ if (pfh_inet == NULL) {
+ lwkt_reltoken(&pf_token);
return (ENODEV);
+ }
pfil_remove_hook(pf_check_in, NULL, PFIL_IN, pfh_inet);
pfil_remove_hook(pf_check_out, NULL, PFIL_OUT, pfh_inet);
#ifdef INET6
pfh_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6);
- if (pfh_inet6 == NULL)
+ if (pfh_inet6 == NULL) {
+ lwkt_reltoken(&pf_token);
return (ENODEV);
+ }
pfil_remove_hook(pf_check6_in, NULL, PFIL_IN, pfh_inet6);
pfil_remove_hook(pf_check6_out, NULL, PFIL_OUT, pfh_inet6);
#endif
pf_pfil_hooked = 0;
+ lwkt_reltoken(&pf_token);
return (0);
}
{
int error;
+ lwkt_gettoken(&pf_token);
+
init_zone_var();
lockinit(&pf_mod_lck, "pf task lck", 0, LK_CANRECURSE);
pf_dev = make_dev(&pf_ops, 0, 0, 0, 0600, PF_NAME);
if (error) {
dev_ops_remove_all(&pf_ops);
lockuninit(&pf_mod_lck);
+ lwkt_reltoken(&pf_token);
return (error);
}
lockinit(&pf_consistency_lock, "pfconslck", 0, LK_CANRECURSE);
+ lwkt_reltoken(&pf_token);
return (0);
}
pf_unload(void)
{
int error;
-
pf_status.running = 0;
+
+ lwkt_gettoken(&pf_token);
+
error = dehook_pf();
if (error) {
/*
* a message like 'No such process'.
*/
kprintf("pfil unregistration fail\n");
+ lwkt_reltoken(&pf_token);
return error;
}
shutdown_pf();
dev_ops_remove_all(&pf_ops);
lockuninit(&pf_consistency_lock);
lockuninit(&pf_mod_lck);
+ lwkt_reltoken(&pf_token);
return 0;
}
{
int error = 0;
+ lwkt_gettoken(&pf_token);
+
switch(type) {
case MOD_LOAD:
error = pf_load();
error = EINVAL;
break;
}
+ lwkt_reltoken(&pf_token);
return error;
}