aboutsummaryrefslogtreecommitdiff
path: root/sys/netpfil
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netpfil')
-rw-r--r--sys/netpfil/ipfw/ip_fw2.c2
-rw-r--r--sys/netpfil/pf/if_pflog.c4
-rw-r--r--sys/netpfil/pf/if_pfsync.c27
-rw-r--r--sys/netpfil/pf/pf.c345
-rw-r--r--sys/netpfil/pf/pf.h2
-rw-r--r--sys/netpfil/pf/pf_ioctl.c298
-rw-r--r--sys/netpfil/pf/pf_lb.c65
-rw-r--r--sys/netpfil/pf/pf_norm.c109
-rw-r--r--sys/netpfil/pf/pf_osfp.c17
-rw-r--r--sys/netpfil/pf/pf_ruleset.c13
-rw-r--r--sys/netpfil/pf/pf_syncookies.c6
-rw-r--r--sys/netpfil/pf/pf_table.c31
12 files changed, 537 insertions, 382 deletions
diff --git a/sys/netpfil/ipfw/ip_fw2.c b/sys/netpfil/ipfw/ip_fw2.c
index 923633d76df7..c129c8c49921 100644
--- a/sys/netpfil/ipfw/ip_fw2.c
+++ b/sys/netpfil/ipfw/ip_fw2.c
@@ -196,7 +196,7 @@ SYSCTL_NODE(_net_inet_ip, OID_AUTO, fw, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
"Firewall");
SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, one_pass,
CTLFLAG_VNET | CTLFLAG_RW | CTLFLAG_SECURE3, &VNET_NAME(fw_one_pass), 0,
- "Only do a single pass through ipfw when using dummynet(4)");
+ "Only do a single pass through ipfw when using dummynet(4), ipfw_nat or other divert(4)-like interfaces");
SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, autoinc_step,
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(autoinc_step), 0,
"Rule number auto-increment step");
diff --git a/sys/netpfil/pf/if_pflog.c b/sys/netpfil/pf/if_pflog.c
index 0a84f9d680ac..cb96d2fcc44c 100644
--- a/sys/netpfil/pf/if_pflog.c
+++ b/sys/netpfil/pf/if_pflog.c
@@ -284,9 +284,9 @@ pflog_packet(uint8_t action, u_int8_t reason,
* state lock, since this leads to unsafe LOR.
* These conditions are very very rare, however.
*/
- if (trigger->log & PF_LOG_SOCKET_LOOKUP && !pd->lookup.done && lookupsafe)
+ if (trigger->log & PF_LOG_USER && !pd->lookup.done && lookupsafe)
pd->lookup.done = pf_socket_lookup(pd);
- if (pd->lookup.done > 0)
+ if (trigger->log & PF_LOG_USER && pd->lookup.done > 0)
hdr.uid = pd->lookup.uid;
else
hdr.uid = -1;
diff --git a/sys/netpfil/pf/if_pfsync.c b/sys/netpfil/pf/if_pfsync.c
index 2391edaf1a5a..ee10a997c977 100644
--- a/sys/netpfil/pf/if_pfsync.c
+++ b/sys/netpfil/pf/if_pfsync.c
@@ -110,8 +110,6 @@
#include <netpfil/pf/pfsync_nv.h>
-#define DPFPRINTF(n, x) if (V_pf_status.debug >= (n)) printf x
-
struct pfsync_bucket;
struct pfsync_softc;
@@ -532,6 +530,7 @@ pfsync_state_import(union pfsync_state_union *sp, int flags, int msg_version)
struct pf_kpooladdr *rpool_first;
int error;
uint8_t rt = 0;
+ int n = 0;
PF_RULES_RASSERT();
@@ -557,10 +556,12 @@ pfsync_state_import(union pfsync_state_union *sp, int flags, int msg_version)
*/
if (sp->pfs_1301.rule != htonl(-1) && sp->pfs_1301.anchor == htonl(-1) &&
(flags & (PFSYNC_SI_IOCTL | PFSYNC_SI_CKSUM)) && ntohl(sp->pfs_1301.rule) <
- pf_main_ruleset.rules[PF_RULESET_FILTER].active.rcount)
- r = pf_main_ruleset.rules[
- PF_RULESET_FILTER].active.ptr_array[ntohl(sp->pfs_1301.rule)];
- else
+ pf_main_ruleset.rules[PF_RULESET_FILTER].active.rcount) {
+ TAILQ_FOREACH(r, pf_main_ruleset.rules[
+ PF_RULESET_FILTER].active.ptr, entries)
+ if (ntohl(sp->pfs_1301.rule) == n++)
+ break;
+ } else
r = &V_pf_default_rule;
/*
@@ -594,9 +595,9 @@ pfsync_state_import(union pfsync_state_union *sp, int flags, int msg_version)
if ((rpool_first == NULL) ||
(TAILQ_NEXT(rpool_first, entries) != NULL)) {
DPFPRINTF(PF_DEBUG_MISC,
- ("%s: can't recover routing information "
- "because of empty or bad redirection pool\n",
- __func__));
+ "%s: can't recover routing information "
+ "because of empty or bad redirection pool",
+ __func__);
return ((flags & PFSYNC_SI_IOCTL) ? EINVAL : 0);
}
rt = r->rt;
@@ -607,8 +608,8 @@ pfsync_state_import(union pfsync_state_union *sp, int flags, int msg_version)
* give up on recovering.
*/
DPFPRINTF(PF_DEBUG_MISC,
- ("%s: can't recover routing information "
- "because of different ruleset\n", __func__));
+ "%s: can't recover routing information "
+ "because of different ruleset", __func__);
return ((flags & PFSYNC_SI_IOCTL) ? EINVAL : 0);
}
break;
@@ -621,8 +622,8 @@ pfsync_state_import(union pfsync_state_union *sp, int flags, int msg_version)
rt_kif = pfi_kkif_find(sp->pfs_1400.rt_ifname);
if (rt_kif == NULL) {
DPFPRINTF(PF_DEBUG_MISC,
- ("%s: unknown route interface: %s\n",
- __func__, sp->pfs_1400.rt_ifname));
+ "%s: unknown route interface: %s",
+ __func__, sp->pfs_1400.rt_ifname);
return ((flags & PFSYNC_SI_IOCTL) ? EINVAL : 0);
}
rt = sp->pfs_1400.rt;
diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c
index acdeebb85e30..c669be47b063 100644
--- a/sys/netpfil/pf/pf.c
+++ b/sys/netpfil/pf/pf.c
@@ -119,8 +119,6 @@
#include <machine/in_cksum.h>
#include <security/mac/mac_framework.h>
-#define DPFPRINTF(n, x) if (V_pf_status.debug >= (n)) printf x
-
SDT_PROVIDER_DEFINE(pf);
SDT_PROBE_DEFINE2(pf, , test, reason_set, "int", "int");
SDT_PROBE_DEFINE4(pf, ip, test, done, "int", "int", "struct pf_krule *",
@@ -161,6 +159,7 @@ SDT_PROBE_DEFINE2(pf, eth, test_rule, match, "int", "struct pf_keth_rule *");
SDT_PROBE_DEFINE2(pf, eth, test_rule, final_match,
"int", "struct pf_keth_rule *");
SDT_PROBE_DEFINE2(pf, purge, state, rowcount, "int", "size_t");
+SDT_PROBE_DEFINE2(pf, , log, log, "int", "const char *");
/*
* Global variables
@@ -375,6 +374,8 @@ static u_int16_t pf_calc_mss(struct pf_addr *, sa_family_t,
int, u_int16_t);
static int pf_check_proto_cksum(struct mbuf *, int, int,
u_int8_t, sa_family_t);
+static int pf_walk_option(struct pf_pdesc *, struct ip *,
+ int, int, u_short *);
static int pf_walk_header(struct pf_pdesc *, struct ip *, u_short *);
#ifdef INET6
static int pf_walk_option6(struct pf_pdesc *, struct ip6_hdr *,
@@ -4615,8 +4616,8 @@ pf_match_rcvif(struct mbuf *m, struct pf_krule *r)
if (kif == NULL) {
DPFPRINTF(PF_DEBUG_URGENT,
- ("%s: kif == NULL, @%d via %s\n", __func__, r->nr,
- r->rcv_ifname));
+ "%s: kif == NULL, @%d via %s", __func__, r->nr,
+ r->rcv_ifname);
return (0);
}
@@ -5242,8 +5243,8 @@ pf_test_eth_rule(int dir, struct pfi_kkif *kif, struct mbuf **m0)
if (__predict_false(m->m_len < sizeof(struct ether_header)) &&
(m = *m0 = m_pullup(*m0, sizeof(struct ether_header))) == NULL) {
DPFPRINTF(PF_DEBUG_URGENT,
- ("%s: m_len < sizeof(struct ether_header)"
- ", pullup failed\n", __func__));
+ "%s: m_len < sizeof(struct ether_header)"
+ ", pullup failed", __func__);
return (PF_DROP);
}
e = mtod(m, struct ether_header *);
@@ -5906,11 +5907,12 @@ pf_test_rule(struct pf_krule **rm, struct pf_kstate **sm,
* it is applied only from the last pass rule.
*/
pd->act.rt = r->rt;
- /* Don't use REASON_SET, pf_map_addr increases the reason counters */
- ctx.reason = pf_map_addr_sn(pd->af, r, pd->src, &pd->act.rt_addr,
- &pd->act.rt_kif, NULL, &(r->route), PF_SN_ROUTE);
- if (ctx.reason != 0)
+ if ((transerror = pf_map_addr_sn(pd->af, r, pd->src,
+ &pd->act.rt_addr, &pd->act.rt_kif, NULL, &(r->route),
+ PF_SN_ROUTE)) != PFRES_MATCH) {
+ REASON_SET(&ctx.reason, transerror);
goto cleanup;
+ }
}
if (pd->virtual_proto != PF_VPROTO_FRAGMENT &&
@@ -6167,8 +6169,8 @@ pf_create_state(struct pf_krule *r, struct pf_test_ctx *ctx,
&s->src, &s->dst, &ctx->rewrite)) {
/* This really shouldn't happen!!! */
DPFPRINTF(PF_DEBUG_URGENT,
- ("%s: tcp normalize failed on first "
- "pkt\n", __func__));
+ "%s: tcp normalize failed on first "
+ "pkt", __func__);
goto csfailed;
}
} else if (pd->proto == IPPROTO_SCTP) {
@@ -6218,7 +6220,7 @@ pf_create_state(struct pf_krule *r, struct pf_test_ctx *ctx,
if (ctx->tag > 0)
s->tag = ctx->tag;
if (pd->proto == IPPROTO_TCP && (tcp_get_flags(th) & (TH_SYN|TH_ACK)) ==
- TH_SYN && r->keep_state == PF_STATE_SYNPROXY) {
+ TH_SYN && r->keep_state == PF_STATE_SYNPROXY && pd->dir == PF_IN) {
pf_set_protostate(s, PF_PEER_SRC, PF_TCPS_PROXY_SRC);
pf_undo_nat(ctx->nr, pd, bip_sum);
s->src.seqhi = arc4random();
@@ -7964,8 +7966,8 @@ pf_test_state_icmp(struct pf_kstate **state, struct pf_pdesc *pd,
if (!pf_pull_hdr(pd->m, ipoff2, &h2, sizeof(h2),
NULL, reason, pd2.af)) {
DPFPRINTF(PF_DEBUG_MISC,
- ("pf: ICMP error message too short "
- "(ip)\n"));
+ "pf: ICMP error message too short "
+ "(ip)");
return (PF_DROP);
}
/*
@@ -7995,8 +7997,8 @@ pf_test_state_icmp(struct pf_kstate **state, struct pf_pdesc *pd,
if (!pf_pull_hdr(pd->m, ipoff2, &h2_6, sizeof(h2_6),
NULL, reason, pd2.af)) {
DPFPRINTF(PF_DEBUG_MISC,
- ("pf: ICMP error message too short "
- "(ip6)\n"));
+ "pf: ICMP error message too short "
+ "(ip6)");
return (PF_DROP);
}
pd2.off = ipoff2;
@@ -8048,8 +8050,8 @@ pf_test_state_icmp(struct pf_kstate **state, struct pf_pdesc *pd,
if (!pf_pull_hdr(pd->m, pd2.off, th, 8, NULL, reason,
pd2.af)) {
DPFPRINTF(PF_DEBUG_MISC,
- ("pf: ICMP error message too short "
- "(tcp)\n"));
+ "pf: ICMP error message too short "
+ "(tcp)");
return (PF_DROP);
}
pd2.pcksum = &pd2.hdr.tcp.th_sum;
@@ -8243,8 +8245,8 @@ pf_test_state_icmp(struct pf_kstate **state, struct pf_pdesc *pd,
if (!pf_pull_hdr(pd->m, pd2.off, uh, sizeof(*uh),
NULL, reason, pd2.af)) {
DPFPRINTF(PF_DEBUG_MISC,
- ("pf: ICMP error message too short "
- "(udp)\n"));
+ "pf: ICMP error message too short "
+ "(udp)");
return (PF_DROP);
}
pd2.pcksum = &pd2.hdr.udp.uh_sum;
@@ -8375,8 +8377,8 @@ pf_test_state_icmp(struct pf_kstate **state, struct pf_pdesc *pd,
if (! pf_pull_hdr(pd->m, pd2.off, sh, sizeof(*sh), NULL, reason,
pd2.af)) {
DPFPRINTF(PF_DEBUG_MISC,
- ("pf: ICMP error message too short "
- "(sctp)\n"));
+ "pf: ICMP error message too short "
+ "(sctp)");
return (PF_DROP);
}
pd2.pcksum = &pd2.sctp_dummy_sum;
@@ -8406,8 +8408,8 @@ pf_test_state_icmp(struct pf_kstate **state, struct pf_pdesc *pd,
if (src->scrub->pfss_v_tag != sh->v_tag) {
DPFPRINTF(PF_DEBUG_MISC,
- ("pf: ICMP error message has incorrect "
- "SCTP v_tag\n"));
+ "pf: ICMP error message has incorrect "
+ "SCTP v_tag");
return (PF_DROP);
}
@@ -8530,8 +8532,8 @@ pf_test_state_icmp(struct pf_kstate **state, struct pf_pdesc *pd,
if (!pf_pull_hdr(pd->m, pd2.off, iih, ICMP_MINLEN,
NULL, reason, pd2.af)) {
DPFPRINTF(PF_DEBUG_MISC,
- ("pf: ICMP error message too short i"
- "(icmp)\n"));
+ "pf: ICMP error message too short i"
+ "(icmp)");
return (PF_DROP);
}
pd2.pcksum = &pd2.hdr.icmp.icmp_cksum;
@@ -8650,8 +8652,8 @@ pf_test_state_icmp(struct pf_kstate **state, struct pf_pdesc *pd,
if (!pf_pull_hdr(pd->m, pd2.off, iih,
sizeof(struct icmp6_hdr), NULL, reason, pd2.af)) {
DPFPRINTF(PF_DEBUG_MISC,
- ("pf: ICMP error message too short "
- "(icmp6)\n"));
+ "pf: ICMP error message too short "
+ "(icmp6)");
return (PF_DROP);
}
pd2.pcksum = &pd2.hdr.icmp6.icmp6_cksum;
@@ -9067,6 +9069,9 @@ pf_route(struct pf_krule *r, struct ifnet *oifp,
goto bad;
}
+ if (r->rt == PF_DUPTO)
+ skip_test = true;
+
if (pd->dir == PF_IN && !skip_test) {
if (pf_test(AF_INET, PF_OUT, PFIL_FWD, ifp, &m0, inp,
&pd->act) != PF_PASS) {
@@ -9078,7 +9083,7 @@ pf_route(struct pf_krule *r, struct ifnet *oifp,
}
if (m0->m_len < sizeof(struct ip)) {
DPFPRINTF(PF_DEBUG_URGENT,
- ("%s: m0->m_len < sizeof(struct ip)\n", __func__));
+ "%s: m0->m_len < sizeof(struct ip)", __func__);
SDT_PROBE1(pf, ip, route_to, drop, __LINE__);
goto bad;
}
@@ -9369,6 +9374,9 @@ pf_route6(struct pf_krule *r, struct ifnet *oifp,
goto bad;
}
+ if (r->rt == PF_DUPTO)
+ skip_test = true;
+
if (pd->dir == PF_IN && !skip_test) {
if (pf_test(AF_INET6, PF_OUT, PFIL_FWD | PF_PFIL_NOREFRAGMENT,
ifp, &m0, inp, &pd->act) != PF_PASS) {
@@ -9380,8 +9388,8 @@ pf_route6(struct pf_krule *r, struct ifnet *oifp,
}
if (m0->m_len < sizeof(struct ip6_hdr)) {
DPFPRINTF(PF_DEBUG_URGENT,
- ("%s: m0->m_len < sizeof(struct ip6_hdr)\n",
- __func__));
+ "%s: m0->m_len < sizeof(struct ip6_hdr)",
+ __func__);
SDT_PROBE1(pf, ip6, route_to, drop, __LINE__);
goto bad;
}
@@ -9676,7 +9684,7 @@ pf_test_eth(int dir, int pflags, struct ifnet *ifp, struct mbuf **m0,
if (kif == NULL) {
DPFPRINTF(PF_DEBUG_URGENT,
- ("%s: kif == NULL, if_xname %s\n", __func__, ifp->if_xname));
+ "%s: kif == NULL, if_xname %s", __func__, ifp->if_xname);
return (PF_DROP);
}
if (kif->pfik_flags & PFI_IFLAG_SKIP)
@@ -9791,6 +9799,62 @@ pf_dummynet_route(struct pf_pdesc *pd, struct pf_kstate *s,
}
static int
+pf_walk_option(struct pf_pdesc *pd, struct ip *h, int off, int end,
+ u_short *reason)
+{
+ uint8_t type, length, opts[15 * 4 - sizeof(struct ip)];
+
+ /* IP header in payload of ICMP packet may be too short */
+ if (pd->m->m_pkthdr.len < end) {
+ DPFPRINTF(PF_DEBUG_MISC, "IP option too short");
+ REASON_SET(reason, PFRES_SHORT);
+ return (PF_DROP);
+ }
+
+ MPASS(end - off <= sizeof(opts));
+ m_copydata(pd->m, off, end - off, opts);
+ end -= off;
+ off = 0;
+
+ while (off < end) {
+ type = opts[off];
+ if (type == IPOPT_EOL)
+ break;
+ if (type == IPOPT_NOP) {
+ off++;
+ continue;
+ }
+ if (off + 2 > end) {
+ DPFPRINTF(PF_DEBUG_MISC, "IP length opt");
+ REASON_SET(reason, PFRES_IPOPTIONS);
+ return (PF_DROP);
+ }
+ length = opts[off + 1];
+ if (length < 2) {
+ DPFPRINTF(PF_DEBUG_MISC, "IP short opt");
+ REASON_SET(reason, PFRES_IPOPTIONS);
+ return (PF_DROP);
+ }
+ if (off + length > end) {
+ DPFPRINTF(PF_DEBUG_MISC, "IP long opt");
+ REASON_SET(reason, PFRES_IPOPTIONS);
+ return (PF_DROP);
+ }
+ switch (type) {
+ case IPOPT_RA:
+ pd->badopts |= PF_OPT_ROUTER_ALERT;
+ break;
+ default:
+ pd->badopts |= PF_OPT_OTHER;
+ break;
+ }
+ off += length;
+ }
+
+ return (PF_PASS);
+}
+
+static int
pf_walk_header(struct pf_pdesc *pd, struct ip *h, u_short *reason)
{
struct ah ext;
@@ -9802,11 +9866,28 @@ pf_walk_header(struct pf_pdesc *pd, struct ip *h, u_short *reason)
REASON_SET(reason, PFRES_SHORT);
return (PF_DROP);
}
- if (hlen != sizeof(struct ip))
- pd->badopts++;
+ if (hlen != sizeof(struct ip)) {
+ if (pf_walk_option(pd, h, pd->off + sizeof(struct ip),
+ pd->off + hlen, reason) != PF_PASS)
+ return (PF_DROP);
+ /* header options which contain only padding is fishy */
+ if (pd->badopts == 0)
+ pd->badopts |= PF_OPT_OTHER;
+ }
end = pd->off + ntohs(h->ip_len);
pd->off += hlen;
pd->proto = h->ip_p;
+ /* IGMP packets have router alert options, allow them */
+ if (pd->proto == IPPROTO_IGMP) {
+ /* According to RFC 1112 ttl must be set to 1. */
+ if ((h->ip_ttl != 1) ||
+ !IN_MULTICAST(ntohl(h->ip_dst.s_addr))) {
+ DPFPRINTF(PF_DEBUG_MISC, "Invalid IGMP");
+ REASON_SET(reason, PFRES_IPOPTIONS);
+ return (PF_DROP);
+ }
+ pd->badopts &= ~PF_OPT_ROUTER_ALERT;
+ }
/* stop walking over non initial fragments */
if ((h->ip_off & htons(IP_OFFMASK)) != 0)
return (PF_PASS);
@@ -9819,7 +9900,7 @@ pf_walk_header(struct pf_pdesc *pd, struct ip *h, u_short *reason)
return (PF_PASS);
if (!pf_pull_hdr(pd->m, pd->off, &ext, sizeof(ext),
NULL, reason, AF_INET)) {
- DPFPRINTF(PF_DEBUG_MISC, ("IP short exthdr"));
+ DPFPRINTF(PF_DEBUG_MISC, "IP short exthdr");
return (PF_DROP);
}
pd->off += (ext.ah_len + 2) * 4;
@@ -9829,7 +9910,7 @@ pf_walk_header(struct pf_pdesc *pd, struct ip *h, u_short *reason)
return (PF_PASS);
}
}
- DPFPRINTF(PF_DEBUG_MISC, ("IPv4 nested authentication header limit"));
+ DPFPRINTF(PF_DEBUG_MISC, "IPv4 nested authentication header limit");
REASON_SET(reason, PFRES_IPOPTIONS);
return (PF_DROP);
}
@@ -9845,7 +9926,7 @@ pf_walk_option6(struct pf_pdesc *pd, struct ip6_hdr *h, int off, int end,
while (off < end) {
if (!pf_pull_hdr(pd->m, off, &opt.ip6o_type,
sizeof(opt.ip6o_type), NULL, reason, AF_INET6)) {
- DPFPRINTF(PF_DEBUG_MISC, ("IPv6 short opt type"));
+ DPFPRINTF(PF_DEBUG_MISC, "IPv6 short opt type");
return (PF_DROP);
}
if (opt.ip6o_type == IP6OPT_PAD1) {
@@ -9854,41 +9935,48 @@ pf_walk_option6(struct pf_pdesc *pd, struct ip6_hdr *h, int off, int end,
}
if (!pf_pull_hdr(pd->m, off, &opt, sizeof(opt), NULL,
reason, AF_INET6)) {
- DPFPRINTF(PF_DEBUG_MISC, ("IPv6 short opt"));
+ DPFPRINTF(PF_DEBUG_MISC, "IPv6 short opt");
return (PF_DROP);
}
if (off + sizeof(opt) + opt.ip6o_len > end) {
- DPFPRINTF(PF_DEBUG_MISC, ("IPv6 long opt"));
+ DPFPRINTF(PF_DEBUG_MISC, "IPv6 long opt");
REASON_SET(reason, PFRES_IPOPTIONS);
return (PF_DROP);
}
switch (opt.ip6o_type) {
+ case IP6OPT_PADN:
+ break;
case IP6OPT_JUMBO:
+ pd->badopts |= PF_OPT_JUMBO;
if (pd->jumbolen != 0) {
- DPFPRINTF(PF_DEBUG_MISC, ("IPv6 multiple jumbo"));
+ DPFPRINTF(PF_DEBUG_MISC, "IPv6 multiple jumbo");
REASON_SET(reason, PFRES_IPOPTIONS);
return (PF_DROP);
}
if (ntohs(h->ip6_plen) != 0) {
- DPFPRINTF(PF_DEBUG_MISC, ("IPv6 bad jumbo plen"));
+ DPFPRINTF(PF_DEBUG_MISC, "IPv6 bad jumbo plen");
REASON_SET(reason, PFRES_IPOPTIONS);
return (PF_DROP);
}
if (!pf_pull_hdr(pd->m, off, &jumbo, sizeof(jumbo), NULL,
reason, AF_INET6)) {
- DPFPRINTF(PF_DEBUG_MISC, ("IPv6 short jumbo"));
+ DPFPRINTF(PF_DEBUG_MISC, "IPv6 short jumbo");
return (PF_DROP);
}
memcpy(&pd->jumbolen, jumbo.ip6oj_jumbo_len,
sizeof(pd->jumbolen));
pd->jumbolen = ntohl(pd->jumbolen);
if (pd->jumbolen < IPV6_MAXPACKET) {
- DPFPRINTF(PF_DEBUG_MISC, ("IPv6 short jumbolen"));
+ DPFPRINTF(PF_DEBUG_MISC, "IPv6 short jumbolen");
REASON_SET(reason, PFRES_IPOPTIONS);
return (PF_DROP);
}
break;
+ case IP6OPT_ROUTER_ALERT:
+ pd->badopts |= PF_OPT_ROUTER_ALERT;
+ break;
default:
+ pd->badopts |= PF_OPT_OTHER;
break;
}
off += sizeof(opt) + opt.ip6o_len;
@@ -9902,6 +9990,7 @@ pf_walk_header6(struct pf_pdesc *pd, struct ip6_hdr *h, u_short *reason)
{
struct ip6_frag frag;
struct ip6_ext ext;
+ struct icmp6_hdr icmp6;
struct ip6_rthdr rthdr;
uint32_t end;
int hdr_cnt, fraghdr_cnt = 0, rthdr_cnt = 0;
@@ -9913,27 +10002,40 @@ pf_walk_header6(struct pf_pdesc *pd, struct ip6_hdr *h, u_short *reason)
for (hdr_cnt = 0; hdr_cnt < PF_HDR_LIMIT; hdr_cnt++) {
switch (pd->proto) {
case IPPROTO_ROUTING:
- case IPPROTO_HOPOPTS:
case IPPROTO_DSTOPTS:
- pd->badopts++;
+ pd->badopts |= PF_OPT_OTHER;
+ break;
+ case IPPROTO_HOPOPTS:
+ if (!pf_pull_hdr(pd->m, pd->off, &ext, sizeof(ext),
+ NULL, reason, AF_INET6)) {
+ DPFPRINTF(PF_DEBUG_MISC, "IPv6 short exthdr");
+ return (PF_DROP);
+ }
+ if (pf_walk_option6(pd, h, pd->off + sizeof(ext),
+ pd->off + (ext.ip6e_len + 1) * 8,
+ reason) != PF_PASS)
+ return (PF_DROP);
+ /* option header which contains only padding is fishy */
+ if (pd->badopts == 0)
+ pd->badopts |= PF_OPT_OTHER;
break;
}
switch (pd->proto) {
case IPPROTO_FRAGMENT:
if (fraghdr_cnt++) {
- DPFPRINTF(PF_DEBUG_MISC, ("IPv6 multiple fragment"));
+ DPFPRINTF(PF_DEBUG_MISC, "IPv6 multiple fragment");
REASON_SET(reason, PFRES_FRAG);
return (PF_DROP);
}
/* jumbo payload packets cannot be fragmented */
if (pd->jumbolen != 0) {
- DPFPRINTF(PF_DEBUG_MISC, ("IPv6 fragmented jumbo"));
+ DPFPRINTF(PF_DEBUG_MISC, "IPv6 fragmented jumbo");
REASON_SET(reason, PFRES_FRAG);
return (PF_DROP);
}
if (!pf_pull_hdr(pd->m, pd->off, &frag, sizeof(frag),
NULL, reason, AF_INET6)) {
- DPFPRINTF(PF_DEBUG_MISC, ("IPv6 short fragment"));
+ DPFPRINTF(PF_DEBUG_MISC, "IPv6 short fragment");
return (PF_DROP);
}
/* stop walking over non initial fragments */
@@ -9949,7 +10051,7 @@ pf_walk_header6(struct pf_pdesc *pd, struct ip6_hdr *h, u_short *reason)
break;
case IPPROTO_ROUTING:
if (rthdr_cnt++) {
- DPFPRINTF(PF_DEBUG_MISC, ("IPv6 multiple rthdr"));
+ DPFPRINTF(PF_DEBUG_MISC, "IPv6 multiple rthdr");
REASON_SET(reason, PFRES_IPOPTIONS);
return (PF_DROP);
}
@@ -9961,11 +10063,11 @@ pf_walk_header6(struct pf_pdesc *pd, struct ip6_hdr *h, u_short *reason)
}
if (!pf_pull_hdr(pd->m, pd->off, &rthdr, sizeof(rthdr),
NULL, reason, AF_INET6)) {
- DPFPRINTF(PF_DEBUG_MISC, ("IPv6 short rthdr"));
+ DPFPRINTF(PF_DEBUG_MISC, "IPv6 short rthdr");
return (PF_DROP);
}
if (rthdr.ip6r_type == IPV6_RTHDR_TYPE_0) {
- DPFPRINTF(PF_DEBUG_MISC, ("IPv6 rthdr0"));
+ DPFPRINTF(PF_DEBUG_MISC, "IPv6 rthdr0");
REASON_SET(reason, PFRES_IPOPTIONS);
return (PF_DROP);
}
@@ -9973,7 +10075,7 @@ pf_walk_header6(struct pf_pdesc *pd, struct ip6_hdr *h, u_short *reason)
case IPPROTO_HOPOPTS:
/* RFC2460 4.1: Hop-by-Hop only after IPv6 header */
if (pd->proto == IPPROTO_HOPOPTS && hdr_cnt > 0) {
- DPFPRINTF(PF_DEBUG_MISC, ("IPv6 hopopts not first"));
+ DPFPRINTF(PF_DEBUG_MISC, "IPv6 hopopts not first");
REASON_SET(reason, PFRES_IPOPTIONS);
return (PF_DROP);
}
@@ -9982,7 +10084,7 @@ pf_walk_header6(struct pf_pdesc *pd, struct ip6_hdr *h, u_short *reason)
case IPPROTO_DSTOPTS:
if (!pf_pull_hdr(pd->m, pd->off, &ext, sizeof(ext),
NULL, reason, AF_INET6)) {
- DPFPRINTF(PF_DEBUG_MISC, ("IPv6 short exthdr"));
+ DPFPRINTF(PF_DEBUG_MISC, "IPv6 short exthdr");
return (PF_DROP);
}
/* fragments may be short */
@@ -9994,18 +10096,11 @@ pf_walk_header6(struct pf_pdesc *pd, struct ip6_hdr *h, u_short *reason)
/* reassembly needs the ext header before the frag */
if (pd->fragoff == 0)
pd->extoff = pd->off;
- if (pd->proto == IPPROTO_HOPOPTS && pd->fragoff == 0) {
- if (pf_walk_option6(pd, h,
- pd->off + sizeof(ext),
- pd->off + (ext.ip6e_len + 1) * 8, reason)
- != PF_PASS)
- return (PF_DROP);
- if (ntohs(h->ip6_plen) == 0 && pd->jumbolen != 0) {
- DPFPRINTF(PF_DEBUG_MISC,
- ("IPv6 missing jumbo"));
- REASON_SET(reason, PFRES_IPOPTIONS);
- return (PF_DROP);
- }
+ if (pd->proto == IPPROTO_HOPOPTS && pd->fragoff == 0 &&
+ ntohs(h->ip6_plen) == 0 && pd->jumbolen != 0) {
+ DPFPRINTF(PF_DEBUG_MISC, "IPv6 missing jumbo");
+ REASON_SET(reason, PFRES_IPOPTIONS);
+ return (PF_DROP);
}
if (pd->proto == IPPROTO_AH)
pd->off += (ext.ip6e_len + 2) * 4;
@@ -10013,10 +10108,45 @@ pf_walk_header6(struct pf_pdesc *pd, struct ip6_hdr *h, u_short *reason)
pd->off += (ext.ip6e_len + 1) * 8;
pd->proto = ext.ip6e_nxt;
break;
+ case IPPROTO_ICMPV6:
+ /* fragments may be short, ignore inner header then */
+ if (pd->fragoff != 0 && end < pd->off + sizeof(icmp6)) {
+ pd->off = pd->fragoff;
+ pd->proto = IPPROTO_FRAGMENT;
+ return (PF_PASS);
+ }
+ if (!pf_pull_hdr(pd->m, pd->off, &icmp6, sizeof(icmp6),
+ NULL, reason, AF_INET6)) {
+ DPFPRINTF(PF_DEBUG_MISC,
+ "IPv6 short icmp6hdr");
+ return (PF_DROP);
+ }
+ /* ICMP multicast packets have router alert options */
+ switch (icmp6.icmp6_type) {
+ case MLD_LISTENER_QUERY:
+ case MLD_LISTENER_REPORT:
+ case MLD_LISTENER_DONE:
+ case MLDV2_LISTENER_REPORT:
+ /*
+ * According to RFC 2710 all MLD messages are
+ * sent with hop-limit (ttl) set to 1, and link
+ * local source address. If either one is
+ * missing then MLD message is invalid and
+ * should be discarded.
+ */
+ if ((h->ip6_hlim != 1) ||
+ !IN6_IS_ADDR_LINKLOCAL(&h->ip6_src)) {
+ DPFPRINTF(PF_DEBUG_MISC, "Invalid MLD");
+ REASON_SET(reason, PFRES_IPOPTIONS);
+ return (PF_DROP);
+ }
+ pd->badopts &= ~PF_OPT_ROUTER_ALERT;
+ break;
+ }
+ return (PF_PASS);
case IPPROTO_TCP:
case IPPROTO_UDP:
case IPPROTO_SCTP:
- case IPPROTO_ICMPV6:
/* fragments may be short, ignore inner header then */
if (pd->fragoff != 0 && end < pd->off +
(pd->proto == IPPROTO_TCP ? sizeof(struct tcphdr) :
@@ -10031,7 +10161,7 @@ pf_walk_header6(struct pf_pdesc *pd, struct ip6_hdr *h, u_short *reason)
return (PF_PASS);
}
}
- DPFPRINTF(PF_DEBUG_MISC, ("IPv6 nested extension header limit"));
+ DPFPRINTF(PF_DEBUG_MISC, "IPv6 nested extension header limit");
REASON_SET(reason, PFRES_IPOPTIONS);
return (PF_DROP);
}
@@ -10057,6 +10187,8 @@ pf_setup_pdesc(sa_family_t af, int dir, struct pf_pdesc *pd, struct mbuf **m0,
pd->didx = (dir == PF_IN) ? 1 : 0;
pd->af = pd->naf = af;
+ PF_RULES_ASSERT();
+
TAILQ_INIT(&pd->sctp_multihome_jobs);
if (default_actions != NULL)
memcpy(&pd->act, default_actions, sizeof(pd->act));
@@ -10074,8 +10206,15 @@ pf_setup_pdesc(sa_family_t af, int dir, struct pf_pdesc *pd, struct mbuf **m0,
if (__predict_false((*m0)->m_len < sizeof(struct ip)) &&
(pd->m = *m0 = m_pullup(*m0, sizeof(struct ip))) == NULL) {
DPFPRINTF(PF_DEBUG_URGENT,
- ("%s: m_len < sizeof(struct ip), pullup failed\n",
- __func__));
+ "%s: m_len < sizeof(struct ip), pullup failed",
+ __func__);
+ *action = PF_DROP;
+ REASON_SET(reason, PFRES_SHORT);
+ return (-1);
+ }
+
+ h = mtod(pd->m, struct ip *);
+ if (pd->m->m_pkthdr.len < ntohs(h->ip_len)) {
*action = PF_DROP;
REASON_SET(reason, PFRES_SHORT);
return (-1);
@@ -10088,13 +10227,7 @@ pf_setup_pdesc(sa_family_t af, int dir, struct pf_pdesc *pd, struct mbuf **m0,
return (-1);
}
*m0 = pd->m;
-
h = mtod(pd->m, struct ip *);
- if (pd->m->m_pkthdr.len < ntohs(h->ip_len)) {
- *action = PF_DROP;
- REASON_SET(reason, PFRES_SHORT);
- return (-1);
- }
if (pf_walk_header(pd, h, reason) != PF_PASS) {
*action = PF_DROP;
@@ -10124,14 +10257,29 @@ pf_setup_pdesc(sa_family_t af, int dir, struct pf_pdesc *pd, struct mbuf **m0,
if (__predict_false((*m0)->m_len < sizeof(struct ip6_hdr)) &&
(pd->m = *m0 = m_pullup(*m0, sizeof(struct ip6_hdr))) == NULL) {
DPFPRINTF(PF_DEBUG_URGENT,
- ("%s: m_len < sizeof(struct ip6_hdr)"
- ", pullup failed\n", __func__));
+ "%s: m_len < sizeof(struct ip6_hdr)"
+ ", pullup failed", __func__);
*action = PF_DROP;
REASON_SET(reason, PFRES_SHORT);
return (-1);
}
h = mtod(pd->m, struct ip6_hdr *);
+ if (pd->m->m_pkthdr.len <
+ sizeof(struct ip6_hdr) + ntohs(h->ip6_plen)) {
+ *action = PF_DROP;
+ REASON_SET(reason, PFRES_SHORT);
+ return (-1);
+ }
+
+ /*
+ * we do not support jumbogram. if we keep going, zero ip6_plen
+ * will do something bad, so drop the packet for now.
+ */
+ if (htons(h->ip6_plen) == 0) {
+ *action = PF_DROP;
+ return (-1);
+ }
if (pf_walk_header6(pd, h, reason) != PF_PASS) {
*action = PF_DROP;
@@ -10152,15 +10300,6 @@ pf_setup_pdesc(sa_family_t af, int dir, struct pf_pdesc *pd, struct mbuf **m0,
pd->virtual_proto = (pd->fragoff != 0) ?
PF_VPROTO_FRAGMENT : pd->proto;
- /*
- * we do not support jumbogram. if we keep going, zero ip6_plen
- * will do something bad, so drop the packet for now.
- */
- if (htons(h->ip6_plen) == 0) {
- *action = PF_DROP;
- return (-1);
- }
-
/* We do IP header normalization and packet reassembly here */
if (pf_normalize_ip6(pd->fragoff, reason, pd) !=
PF_PASS) {
@@ -10470,35 +10609,30 @@ pf_test(sa_family_t af, int dir, int pflags, struct ifnet *ifp, struct mbuf **m0
PF_RULES_RLOCK_TRACKER;
KASSERT(dir == PF_IN || dir == PF_OUT, ("%s: bad direction %d\n", __func__, dir));
M_ASSERTPKTHDR(*m0);
+ NET_EPOCH_ASSERT();
if (!V_pf_status.running)
return (PF_PASS);
- PF_RULES_RLOCK();
-
kif = (struct pfi_kkif *)ifp->if_pf_kif;
if (__predict_false(kif == NULL)) {
DPFPRINTF(PF_DEBUG_URGENT,
- ("%s: kif == NULL, if_xname %s\n",
- __func__, ifp->if_xname));
- PF_RULES_RUNLOCK();
+ "%s: kif == NULL, if_xname %s",
+ __func__, ifp->if_xname);
return (PF_DROP);
}
if (kif->pfik_flags & PFI_IFLAG_SKIP) {
- PF_RULES_RUNLOCK();
return (PF_PASS);
}
if ((*m0)->m_flags & M_SKIP_FIREWALL) {
- PF_RULES_RUNLOCK();
return (PF_PASS);
}
if (__predict_false(! M_WRITABLE(*m0))) {
*m0 = m_unshare(*m0, M_NOWAIT);
if (*m0 == NULL) {
- PF_RULES_RUNLOCK();
return (PF_DROP);
}
}
@@ -10511,12 +10645,10 @@ pf_test(sa_family_t af, int dir, int pflags, struct ifnet *ifp, struct mbuf **m0
ifp = ifnet_byindexgen(pd.pf_mtag->if_index,
pd.pf_mtag->if_idxgen);
if (ifp == NULL || ifp->if_flags & IFF_DYING) {
- PF_RULES_RUNLOCK();
m_freem(*m0);
*m0 = NULL;
return (PF_PASS);
}
- PF_RULES_RUNLOCK();
(ifp->if_output)(ifp, *m0, sintosa(&pd.pf_mtag->dst), NULL);
*m0 = NULL;
return (PF_PASS);
@@ -10531,11 +10663,12 @@ pf_test(sa_family_t af, int dir, int pflags, struct ifnet *ifp, struct mbuf **m0
/* But only once. We may see the packet multiple times (e.g.
* PFIL_IN/PFIL_OUT). */
pf_dummynet_flag_remove(pd.m, pd.pf_mtag);
- PF_RULES_RUNLOCK();
return (PF_PASS);
}
+ PF_RULES_RLOCK();
+
if (pf_setup_pdesc(af, dir, &pd, m0, &action, &reason,
kif, default_actions) == -1) {
if (action != PF_PASS)
@@ -10690,14 +10823,14 @@ pf_test(sa_family_t af, int dir, int pflags, struct ifnet *ifp, struct mbuf **m0
action = PF_DROP;
REASON_SET(&reason, PFRES_NORM);
DPFPRINTF(PF_DEBUG_MISC,
- ("dropping IPv6 packet with ICMPv4 payload"));
+ "dropping IPv6 packet with ICMPv4 payload");
break;
}
if (pd.virtual_proto == IPPROTO_ICMPV6 && af != AF_INET6) {
action = PF_DROP;
REASON_SET(&reason, PFRES_NORM);
DPFPRINTF(PF_DEBUG_MISC,
- ("pf: dropping IPv4 packet with ICMPv6 payload\n"));
+ "pf: dropping IPv4 packet with ICMPv6 payload");
break;
}
action = pf_test_state_icmp(&s, &pd, &reason);
@@ -10723,12 +10856,12 @@ done:
if (s)
memcpy(&pd.act, &s->act, sizeof(s->act));
- if (action == PF_PASS && pd.badopts && !pd.act.allow_opts) {
+ if (action == PF_PASS && pd.badopts != 0 && !pd.act.allow_opts) {
action = PF_DROP;
REASON_SET(&reason, PFRES_IPOPTIONS);
pd.act.log = PF_LOG_FORCE;
DPFPRINTF(PF_DEBUG_MISC,
- ("pf: dropping packet with dangerous headers\n"));
+ "pf: dropping packet with dangerous headers");
}
if (pd.act.max_pkt_size && pd.act.max_pkt_size &&
@@ -10737,7 +10870,7 @@ done:
REASON_SET(&reason, PFRES_NORM);
pd.act.log = PF_LOG_FORCE;
DPFPRINTF(PF_DEBUG_MISC,
- ("pf: dropping overly long packet\n"));
+ "pf: dropping overly long packet");
}
if (s) {
@@ -10769,7 +10902,7 @@ done:
REASON_SET(&reason, PFRES_MEMORY);
pd.act.log = PF_LOG_FORCE;
DPFPRINTF(PF_DEBUG_MISC,
- ("pf: failed to allocate 802.1q mtag\n"));
+ "pf: failed to allocate 802.1q mtag");
}
}
@@ -10826,7 +10959,7 @@ done:
REASON_SET(&reason, PFRES_MEMORY);
pd.act.log = PF_LOG_FORCE;
DPFPRINTF(PF_DEBUG_MISC,
- ("pf: failed to allocate tag\n"));
+ "pf: failed to allocate tag");
} else {
pd.pf_mtag->flags |=
PF_MTAG_FLAG_FASTFWD_OURS_PRESENT;
@@ -10843,7 +10976,7 @@ done:
REASON_SET(&reason, PFRES_MEMORY);
pd.act.log = PF_LOG_FORCE;
DPFPRINTF(PF_DEBUG_MISC,
- ("pf: failed to allocate divert tag\n"));
+ "pf: failed to allocate divert tag");
}
}
/* XXX: Anybody working on it?! */
diff --git a/sys/netpfil/pf/pf.h b/sys/netpfil/pf/pf.h
index db353d185368..cfff58064922 100644
--- a/sys/netpfil/pf/pf.h
+++ b/sys/netpfil/pf/pf.h
@@ -140,7 +140,7 @@ enum { PF_ADDR_ADDRMASK, PF_ADDR_NOROUTE, PF_ADDR_DYNIFTL,
#define PF_LOG 0x01
#define PF_LOG_ALL 0x02
-#define PF_LOG_SOCKET_LOOKUP 0x04
+#define PF_LOG_USER 0x04
#define PF_LOG_FORCE 0x08
#define PF_LOG_MATCHES 0x10
diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c
index c14211edf10f..ea9f7fe441c6 100644
--- a/sys/netpfil/pf/pf_ioctl.c
+++ b/sys/netpfil/pf/pf_ioctl.c
@@ -217,8 +217,6 @@ static u_int16_t tagname2tag(struct pf_tagset *, const char *);
static u_int16_t pf_tagname2tag(const char *);
static void tag_unref(struct pf_tagset *, u_int16_t);
-#define DPFPRINTF(n, x) if (V_pf_status.debug >= (n)) printf x
-
struct cdev *pf_dev;
/*
@@ -1359,7 +1357,7 @@ static int
pf_commit_rules(u_int32_t ticket, int rs_num, char *anchor)
{
struct pf_kruleset *rs;
- struct pf_krule *rule, **old_array, *old_rule;
+ struct pf_krule *rule, *old_rule;
struct pf_krulequeue *old_rules;
struct pf_krule_global *old_tree;
int error;
@@ -1384,13 +1382,10 @@ pf_commit_rules(u_int32_t ticket, int rs_num, char *anchor)
/* Swap rules, keep the old. */
old_rules = rs->rules[rs_num].active.ptr;
old_rcount = rs->rules[rs_num].active.rcount;
- old_array = rs->rules[rs_num].active.ptr_array;
old_tree = rs->rules[rs_num].active.tree;
rs->rules[rs_num].active.ptr =
rs->rules[rs_num].inactive.ptr;
- rs->rules[rs_num].active.ptr_array =
- rs->rules[rs_num].inactive.ptr_array;
rs->rules[rs_num].active.tree =
rs->rules[rs_num].inactive.tree;
rs->rules[rs_num].active.rcount =
@@ -1420,7 +1415,6 @@ pf_commit_rules(u_int32_t ticket, int rs_num, char *anchor)
}
rs->rules[rs_num].inactive.ptr = old_rules;
- rs->rules[rs_num].inactive.ptr_array = old_array;
rs->rules[rs_num].inactive.tree = NULL; /* important for pf_ioctl_addrule */
rs->rules[rs_num].inactive.rcount = old_rcount;
@@ -1433,9 +1427,6 @@ pf_commit_rules(u_int32_t ticket, int rs_num, char *anchor)
while ((rule = TAILQ_FIRST(old_rules)) != NULL)
pf_unlink_rule_locked(old_rules, rule);
PF_UNLNKDRULES_UNLOCK();
- if (rs->rules[rs_num].inactive.ptr_array)
- free(rs->rules[rs_num].inactive.ptr_array, M_TEMP);
- rs->rules[rs_num].inactive.ptr_array = NULL;
rs->rules[rs_num].inactive.rcount = 0;
rs->rules[rs_num].inactive.open = 0;
pf_remove_if_empty_kruleset(rs);
@@ -1458,24 +1449,11 @@ pf_setup_pfsync_matching(struct pf_kruleset *rs)
if (rs_cnt == PF_RULESET_SCRUB)
continue;
- if (rs->rules[rs_cnt].inactive.ptr_array)
- free(rs->rules[rs_cnt].inactive.ptr_array, M_TEMP);
- rs->rules[rs_cnt].inactive.ptr_array = NULL;
-
if (rs->rules[rs_cnt].inactive.rcount) {
- rs->rules[rs_cnt].inactive.ptr_array =
- mallocarray(rs->rules[rs_cnt].inactive.rcount,
- sizeof(struct pf_rule **),
- M_TEMP, M_NOWAIT);
-
- if (!rs->rules[rs_cnt].inactive.ptr_array)
- return (ENOMEM);
- }
-
- TAILQ_FOREACH(rule, rs->rules[rs_cnt].inactive.ptr,
- entries) {
- pf_hash_rule_rolling(&ctx, rule);
- (rs->rules[rs_cnt].inactive.ptr_array)[rule->nr] = rule;
+ TAILQ_FOREACH(rule, rs->rules[rs_cnt].inactive.ptr,
+ entries) {
+ pf_hash_rule_rolling(&ctx, rule);
+ }
}
}
@@ -2061,6 +2039,47 @@ pf_ioctl_getrules(struct pfioc_rule *pr)
return (0);
}
+static int
+pf_rule_checkaf(struct pf_krule *r)
+{
+ switch (r->af) {
+ case 0:
+ if (r->rule_flag & PFRULE_AFTO)
+ return (EPFNOSUPPORT);
+ break;
+ case AF_INET:
+ if ((r->rule_flag & PFRULE_AFTO) && r->naf != AF_INET6)
+ return (EPFNOSUPPORT);
+ break;
+#ifdef INET6
+ case AF_INET6:
+ if ((r->rule_flag & PFRULE_AFTO) && r->naf != AF_INET)
+ return (EPFNOSUPPORT);
+ break;
+#endif /* INET6 */
+ default:
+ return (EPFNOSUPPORT);
+ }
+
+ if ((r->rule_flag & PFRULE_AFTO) == 0 && r->naf != 0)
+ return (EPFNOSUPPORT);
+
+ return (0);
+}
+
+static int
+pf_validate_range(uint8_t op, uint16_t port[2])
+{
+ uint16_t a = ntohs(port[0]);
+ uint16_t b = ntohs(port[1]);
+
+ if ((op == PF_OP_RRG && a > b) || /* 34:12, i.e. none */
+ (op == PF_OP_IRG && a >= b) || /* 34><12, i.e. none */
+ (op == PF_OP_XRG && a > b)) /* 34<>22, i.e. all */
+ return 1;
+ return 0;
+}
+
int
pf_ioctl_addrule(struct pf_krule *rule, uint32_t ticket,
uint32_t pool_ticket, const char *anchor, const char *anchor_call,
@@ -2080,6 +2099,13 @@ pf_ioctl_addrule(struct pf_krule *rule, uint32_t ticket,
#define ERROUT(x) ERROUT_FUNCTION(errout, x)
+ if ((error = pf_rule_checkaf(rule)))
+ ERROUT(error);
+ if (pf_validate_range(rule->src.port_op, rule->src.port))
+ ERROUT(EINVAL);
+ if (pf_validate_range(rule->dst.port_op, rule->dst.port))
+ ERROUT(EINVAL);
+
if (rule->ifname[0])
kif = pf_kkif_create(M_WAITOK);
if (rule->rcv_ifname[0])
@@ -2115,14 +2141,14 @@ pf_ioctl_addrule(struct pf_krule *rule, uint32_t ticket,
ERROUT(EINVAL);
if (ticket != ruleset->rules[rs_num].inactive.ticket) {
DPFPRINTF(PF_DEBUG_MISC,
- ("ticket: %d != [%d]%d\n", ticket, rs_num,
- ruleset->rules[rs_num].inactive.ticket));
+ "ticket: %d != [%d]%d", ticket, rs_num,
+ ruleset->rules[rs_num].inactive.ticket);
ERROUT(EBUSY);
}
if (pool_ticket != V_ticket_pabuf) {
DPFPRINTF(PF_DEBUG_MISC,
- ("pool_ticket: %d != %d\n", pool_ticket,
- V_ticket_pabuf));
+ "pool_ticket: %d != %d", pool_ticket,
+ V_ticket_pabuf);
ERROUT(EBUSY);
}
/*
@@ -2441,7 +2467,7 @@ pf_start(void)
V_pf_status.since = time_uptime;
new_unrhdr64(&V_pf_stateid, time_second);
- DPFPRINTF(PF_DEBUG_MISC, ("pf: started\n"));
+ DPFPRINTF(PF_DEBUG_MISC, "pf: started");
}
sx_xunlock(&V_pf_ioctl_lock);
@@ -2461,7 +2487,7 @@ pf_stop(void)
dehook_pf();
dehook_pf_eth();
V_pf_status.since = time_uptime;
- DPFPRINTF(PF_DEBUG_MISC, ("pf: stopped\n"));
+ DPFPRINTF(PF_DEBUG_MISC, "pf: stopped");
}
sx_xunlock(&V_pf_ioctl_lock);
@@ -3236,9 +3262,9 @@ DIOCGETETHRULE_error:
if (nvlist_get_number(nvl, "ticket") !=
ruleset->inactive.ticket) {
DPFPRINTF(PF_DEBUG_MISC,
- ("ticket: %d != %d\n",
+ "ticket: %d != %d",
(u_int32_t)nvlist_get_number(nvl, "ticket"),
- ruleset->inactive.ticket));
+ ruleset->inactive.ticket);
ERROUT(EBUSY);
}
@@ -3569,7 +3595,7 @@ DIOCADDRULENV_error:
error = pf_rule_to_krule(&pr->rule, rule);
if (error != 0) {
pf_krule_free(rule);
- break;
+ goto fail;
}
pr->anchor[sizeof(pr->anchor) - 1] = '\0';
@@ -3728,11 +3754,11 @@ DIOCGETRULENV_error:
if (pcr->action < PF_CHANGE_ADD_HEAD ||
pcr->action > PF_CHANGE_GET_TICKET) {
error = EINVAL;
- break;
+ goto fail;
}
if (pcr->rule.return_icmp >> 8 > ICMP_MAXTYPE) {
error = EINVAL;
- break;
+ goto fail;
}
if (pcr->action != PF_CHANGE_REMOVE) {
@@ -3740,9 +3766,13 @@ DIOCGETRULENV_error:
error = pf_rule_to_krule(&pcr->rule, newrule);
if (error != 0) {
pf_krule_free(newrule);
- break;
+ goto fail;
}
+ if ((error = pf_rule_checkaf(newrule))) {
+ pf_krule_free(newrule);
+ goto fail;
+ }
if (newrule->ifname[0])
kif = pf_kkif_create(M_WAITOK);
pf_counter_u64_init(&newrule->evaluations, M_WAITOK);
@@ -3890,7 +3920,7 @@ DIOCGETRULENV_error:
pf_free_rule(newrule);
PF_RULES_WUNLOCK();
PF_CONFIG_UNLOCK();
- break;
+ goto fail;
}
newrule->nat.cur = TAILQ_FIRST(&newrule->nat.list);
@@ -3917,7 +3947,7 @@ DIOCGETRULENV_error:
PF_RULES_WUNLOCK();
PF_CONFIG_UNLOCK();
error = EINVAL;
- break;
+ goto fail;
}
}
@@ -3935,7 +3965,7 @@ DIOCGETRULENV_error:
PF_RULES_WUNLOCK();
PF_CONFIG_UNLOCK();
error = EEXIST;
- break;
+ goto fail;
}
if (oldrule == NULL)
@@ -3991,7 +4021,7 @@ DIOCCHANGERULE_error:
if (sp->timeout >= PFTM_MAX) {
error = EINVAL;
- break;
+ goto fail;
}
if (V_pfsync_state_import_ptr != NULL) {
PF_RULES_RLOCK();
@@ -4011,7 +4041,7 @@ DIOCCHANGERULE_error:
s = pf_find_state_byid(ps->state.id, ps->state.creatorid);
if (s == NULL) {
error = ENOENT;
- break;
+ goto fail;
}
pfsync_state_export((union pfsync_state_union*)&ps->state,
@@ -4090,7 +4120,7 @@ DIOCGETSTATES_retry:
error = copyout(pstore, out,
sizeof(struct pfsync_state_1301) * count);
if (error)
- break;
+ goto fail;
out = ps->ps_states + nr;
}
DIOCGETSTATES_full:
@@ -4110,7 +4140,7 @@ DIOCGETSTATES_full:
if (ps->ps_req_version > PF_STATE_VERSION) {
error = ENOTSUP;
- break;
+ goto fail;
}
if (ps->ps_len <= 0) {
@@ -4168,7 +4198,7 @@ DIOCGETSTATESV2_retry:
error = copyout(pstore, out,
sizeof(struct pf_state_export) * count);
if (error)
- break;
+ goto fail;
out = ps->ps_states + nr;
}
DIOCGETSTATESV2_full:
@@ -4274,12 +4304,12 @@ DIOCGETSTATESV2_full:
if (psp->ifname[0] == '\0') {
error = EINVAL;
- break;
+ goto fail;
}
error = pf_user_strcpy(ps.ifname, psp->ifname, IFNAMSIZ);
if (error != 0)
- break;
+ goto fail;
ifp = ifunit(ps.ifname);
if (ifp != NULL) {
psp->baudrate32 =
@@ -4308,7 +4338,7 @@ DIOCGETSTATESV2_full:
if (error == 0)
V_pf_altq_running = 1;
PF_RULES_WUNLOCK();
- DPFPRINTF(PF_DEBUG_MISC, ("altq: started\n"));
+ DPFPRINTF(PF_DEBUG_MISC, "altq: started");
break;
}
@@ -4327,7 +4357,7 @@ DIOCGETSTATESV2_full:
if (error == 0)
V_pf_altq_running = 0;
PF_RULES_WUNLOCK();
- DPFPRINTF(PF_DEBUG_MISC, ("altq: stopped\n"));
+ DPFPRINTF(PF_DEBUG_MISC, "altq: stopped");
break;
}
@@ -4340,7 +4370,7 @@ DIOCGETSTATESV2_full:
altq = malloc(sizeof(*altq), M_PFALTQ, M_WAITOK | M_ZERO);
error = pf_import_kaltq(pa, altq, IOCPARM_LEN(cmd));
if (error)
- break;
+ goto fail;
altq->local_flags = 0;
PF_RULES_WLOCK();
@@ -4348,7 +4378,7 @@ DIOCGETSTATESV2_full:
PF_RULES_WUNLOCK();
free(altq, M_PFALTQ);
error = EBUSY;
- break;
+ goto fail;
}
/*
@@ -4360,7 +4390,7 @@ DIOCGETSTATESV2_full:
PF_RULES_WUNLOCK();
error = EBUSY;
free(altq, M_PFALTQ);
- break;
+ goto fail;
}
altq->altq_disc = NULL;
TAILQ_FOREACH(a, V_pf_altq_ifs_inactive, entries) {
@@ -4380,7 +4410,7 @@ DIOCGETSTATESV2_full:
if (error) {
PF_RULES_WUNLOCK();
free(altq, M_PFALTQ);
- break;
+ goto fail;
}
if (altq->qname[0] != 0)
@@ -4418,13 +4448,13 @@ DIOCGETSTATESV2_full:
if (pa->ticket != V_ticket_altqs_active) {
PF_RULES_RUNLOCK();
error = EBUSY;
- break;
+ goto fail;
}
altq = pf_altq_get_nth_active(pa->nr);
if (altq == NULL) {
PF_RULES_RUNLOCK();
error = EBUSY;
- break;
+ goto fail;
}
pf_export_kaltq(altq, pa, IOCPARM_LEN(cmd));
PF_RULES_RUNLOCK();
@@ -4448,20 +4478,20 @@ DIOCGETSTATESV2_full:
if (pq->ticket != V_ticket_altqs_active) {
PF_RULES_RUNLOCK();
error = EBUSY;
- break;
+ goto fail;
}
nbytes = pq->nbytes;
altq = pf_altq_get_nth_active(pq->nr);
if (altq == NULL) {
PF_RULES_RUNLOCK();
error = EBUSY;
- break;
+ goto fail;
}
if ((altq->local_flags & PFALTQ_FLAG_IF_REMOVED) != 0) {
PF_RULES_RUNLOCK();
error = ENXIO;
- break;
+ goto fail;
}
PF_RULES_RUNLOCK();
if (cmd == DIOCGETQSTATSV0)
@@ -4530,30 +4560,30 @@ DIOCGETSTATESV2_full:
if (pca->action < PF_CHANGE_ADD_HEAD ||
pca->action > PF_CHANGE_REMOVE) {
error = EINVAL;
- break;
+ goto fail;
}
if (pca->addr.addr.type != PF_ADDR_ADDRMASK &&
pca->addr.addr.type != PF_ADDR_DYNIFTL &&
pca->addr.addr.type != PF_ADDR_TABLE) {
error = EINVAL;
- break;
+ goto fail;
}
if (pca->addr.addr.p.dyn != NULL) {
error = EINVAL;
- break;
+ goto fail;
}
if (pca->action != PF_CHANGE_REMOVE) {
#ifndef INET
if (pca->af == AF_INET) {
error = EAFNOSUPPORT;
- break;
+ goto fail;
}
#endif /* INET */
#ifndef INET6
if (pca->af == AF_INET6) {
error = EAFNOSUPPORT;
- break;
+ goto fail;
}
#endif /* INET6 */
newpa = malloc(sizeof(*newpa), M_PFRULE, M_WAITOK);
@@ -4676,7 +4706,7 @@ DIOCCHANGEADDR_error:
if (io->pfrio_esize != 0) {
error = ENODEV;
- break;
+ goto fail;
}
PF_RULES_WLOCK();
error = pfr_clr_tables(&io->pfrio_table, &io->pfrio_ndel,
@@ -4692,13 +4722,13 @@ DIOCCHANGEADDR_error:
if (io->pfrio_esize != sizeof(struct pfr_table)) {
error = ENODEV;
- break;
+ goto fail;
}
if (io->pfrio_size < 0 || io->pfrio_size > pf_ioctl_maxcount ||
WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_table))) {
error = ENOMEM;
- break;
+ goto fail;
}
totlen = io->pfrio_size * sizeof(struct pfr_table);
@@ -4707,7 +4737,7 @@ DIOCCHANGEADDR_error:
error = copyin(io->pfrio_buffer, pfrts, totlen);
if (error) {
free(pfrts, M_TEMP);
- break;
+ goto fail;
}
PF_RULES_WLOCK();
error = pfr_add_tables(pfrts, io->pfrio_size,
@@ -4724,13 +4754,13 @@ DIOCCHANGEADDR_error:
if (io->pfrio_esize != sizeof(struct pfr_table)) {
error = ENODEV;
- break;
+ goto fail;
}
if (io->pfrio_size < 0 || io->pfrio_size > pf_ioctl_maxcount ||
WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_table))) {
error = ENOMEM;
- break;
+ goto fail;
}
totlen = io->pfrio_size * sizeof(struct pfr_table);
@@ -4739,7 +4769,7 @@ DIOCCHANGEADDR_error:
error = copyin(io->pfrio_buffer, pfrts, totlen);
if (error) {
free(pfrts, M_TEMP);
- break;
+ goto fail;
}
PF_RULES_WLOCK();
error = pfr_del_tables(pfrts, io->pfrio_size,
@@ -4757,14 +4787,14 @@ DIOCCHANGEADDR_error:
if (io->pfrio_esize != sizeof(struct pfr_table)) {
error = ENODEV;
- break;
+ goto fail;
}
PF_RULES_RLOCK();
n = pfr_table_count(&io->pfrio_table, io->pfrio_flags);
if (n < 0) {
PF_RULES_RUNLOCK();
error = EINVAL;
- break;
+ goto fail;
}
io->pfrio_size = min(io->pfrio_size, n);
@@ -4775,7 +4805,7 @@ DIOCCHANGEADDR_error:
if (pfrts == NULL) {
error = ENOMEM;
PF_RULES_RUNLOCK();
- break;
+ goto fail;
}
error = pfr_get_tables(&io->pfrio_table, pfrts,
&io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
@@ -4794,7 +4824,7 @@ DIOCCHANGEADDR_error:
if (io->pfrio_esize != sizeof(struct pfr_tstats)) {
error = ENODEV;
- break;
+ goto fail;
}
PF_TABLE_STATS_LOCK();
PF_RULES_RLOCK();
@@ -4803,7 +4833,7 @@ DIOCCHANGEADDR_error:
PF_RULES_RUNLOCK();
PF_TABLE_STATS_UNLOCK();
error = EINVAL;
- break;
+ goto fail;
}
io->pfrio_size = min(io->pfrio_size, n);
@@ -4814,7 +4844,7 @@ DIOCCHANGEADDR_error:
error = ENOMEM;
PF_RULES_RUNLOCK();
PF_TABLE_STATS_UNLOCK();
- break;
+ goto fail;
}
error = pfr_get_tstats(&io->pfrio_table, pfrtstats,
&io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
@@ -4833,7 +4863,7 @@ DIOCCHANGEADDR_error:
if (io->pfrio_esize != sizeof(struct pfr_table)) {
error = ENODEV;
- break;
+ goto fail;
}
if (io->pfrio_size < 0 || io->pfrio_size > pf_ioctl_maxcount ||
@@ -4842,7 +4872,7 @@ DIOCCHANGEADDR_error:
* size, so we didn't fail on overly large requests.
* Keep doing so. */
io->pfrio_size = pf_ioctl_maxcount;
- break;
+ goto fail;
}
totlen = io->pfrio_size * sizeof(struct pfr_table);
@@ -4851,7 +4881,7 @@ DIOCCHANGEADDR_error:
error = copyin(io->pfrio_buffer, pfrts, totlen);
if (error) {
free(pfrts, M_TEMP);
- break;
+ goto fail;
}
PF_TABLE_STATS_LOCK();
@@ -4872,7 +4902,7 @@ DIOCCHANGEADDR_error:
if (io->pfrio_esize != sizeof(struct pfr_table)) {
error = ENODEV;
- break;
+ goto fail;
}
PF_RULES_RLOCK();
@@ -4880,7 +4910,7 @@ DIOCCHANGEADDR_error:
if (n < 0) {
PF_RULES_RUNLOCK();
error = EINVAL;
- break;
+ goto fail;
}
io->pfrio_size = min(io->pfrio_size, n);
@@ -4892,7 +4922,7 @@ DIOCCHANGEADDR_error:
error = copyin(io->pfrio_buffer, pfrts, totlen);
if (error) {
free(pfrts, M_TEMP);
- break;
+ goto fail;
}
PF_RULES_WLOCK();
error = pfr_set_tflags(pfrts, io->pfrio_size,
@@ -4908,7 +4938,7 @@ DIOCCHANGEADDR_error:
if (io->pfrio_esize != 0) {
error = ENODEV;
- break;
+ goto fail;
}
PF_RULES_WLOCK();
error = pfr_clr_addrs(&io->pfrio_table, &io->pfrio_ndel,
@@ -4924,13 +4954,13 @@ DIOCCHANGEADDR_error:
if (io->pfrio_esize != sizeof(struct pfr_addr)) {
error = ENODEV;
- break;
+ goto fail;
}
if (io->pfrio_size < 0 ||
io->pfrio_size > pf_ioctl_maxcount ||
WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_addr))) {
error = EINVAL;
- break;
+ goto fail;
}
totlen = io->pfrio_size * sizeof(struct pfr_addr);
pfras = mallocarray(io->pfrio_size, sizeof(struct pfr_addr),
@@ -4938,7 +4968,7 @@ DIOCCHANGEADDR_error:
error = copyin(io->pfrio_buffer, pfras, totlen);
if (error) {
free(pfras, M_TEMP);
- break;
+ goto fail;
}
PF_RULES_WLOCK();
error = pfr_add_addrs(&io->pfrio_table, pfras,
@@ -4958,13 +4988,13 @@ DIOCCHANGEADDR_error:
if (io->pfrio_esize != sizeof(struct pfr_addr)) {
error = ENODEV;
- break;
+ goto fail;
}
if (io->pfrio_size < 0 ||
io->pfrio_size > pf_ioctl_maxcount ||
WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_addr))) {
error = EINVAL;
- break;
+ goto fail;
}
totlen = io->pfrio_size * sizeof(struct pfr_addr);
pfras = mallocarray(io->pfrio_size, sizeof(struct pfr_addr),
@@ -4972,7 +5002,7 @@ DIOCCHANGEADDR_error:
error = copyin(io->pfrio_buffer, pfras, totlen);
if (error) {
free(pfras, M_TEMP);
- break;
+ goto fail;
}
PF_RULES_WLOCK();
error = pfr_del_addrs(&io->pfrio_table, pfras,
@@ -4992,17 +5022,17 @@ DIOCCHANGEADDR_error:
if (io->pfrio_esize != sizeof(struct pfr_addr)) {
error = ENODEV;
- break;
+ goto fail;
}
if (io->pfrio_size < 0 || io->pfrio_size2 < 0) {
error = EINVAL;
- break;
+ goto fail;
}
count = max(io->pfrio_size, io->pfrio_size2);
if (count > pf_ioctl_maxcount ||
WOULD_OVERFLOW(count, sizeof(struct pfr_addr))) {
error = EINVAL;
- break;
+ goto fail;
}
totlen = count * sizeof(struct pfr_addr);
pfras = mallocarray(count, sizeof(struct pfr_addr), M_TEMP,
@@ -5010,7 +5040,7 @@ DIOCCHANGEADDR_error:
error = copyin(io->pfrio_buffer, pfras, totlen);
if (error) {
free(pfras, M_TEMP);
- break;
+ goto fail;
}
PF_RULES_WLOCK();
error = pfr_set_addrs(&io->pfrio_table, pfras,
@@ -5031,13 +5061,13 @@ DIOCCHANGEADDR_error:
if (io->pfrio_esize != sizeof(struct pfr_addr)) {
error = ENODEV;
- break;
+ goto fail;
}
if (io->pfrio_size < 0 ||
io->pfrio_size > pf_ioctl_maxcount ||
WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_addr))) {
error = EINVAL;
- break;
+ goto fail;
}
totlen = io->pfrio_size * sizeof(struct pfr_addr);
pfras = mallocarray(io->pfrio_size, sizeof(struct pfr_addr),
@@ -5059,13 +5089,13 @@ DIOCCHANGEADDR_error:
if (io->pfrio_esize != sizeof(struct pfr_astats)) {
error = ENODEV;
- break;
+ goto fail;
}
if (io->pfrio_size < 0 ||
io->pfrio_size > pf_ioctl_maxcount ||
WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_astats))) {
error = EINVAL;
- break;
+ goto fail;
}
totlen = io->pfrio_size * sizeof(struct pfr_astats);
pfrastats = mallocarray(io->pfrio_size,
@@ -5087,13 +5117,13 @@ DIOCCHANGEADDR_error:
if (io->pfrio_esize != sizeof(struct pfr_addr)) {
error = ENODEV;
- break;
+ goto fail;
}
if (io->pfrio_size < 0 ||
io->pfrio_size > pf_ioctl_maxcount ||
WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_addr))) {
error = EINVAL;
- break;
+ goto fail;
}
totlen = io->pfrio_size * sizeof(struct pfr_addr);
pfras = mallocarray(io->pfrio_size, sizeof(struct pfr_addr),
@@ -5101,7 +5131,7 @@ DIOCCHANGEADDR_error:
error = copyin(io->pfrio_buffer, pfras, totlen);
if (error) {
free(pfras, M_TEMP);
- break;
+ goto fail;
}
PF_RULES_WLOCK();
error = pfr_clr_astats(&io->pfrio_table, pfras,
@@ -5121,13 +5151,13 @@ DIOCCHANGEADDR_error:
if (io->pfrio_esize != sizeof(struct pfr_addr)) {
error = ENODEV;
- break;
+ goto fail;
}
if (io->pfrio_size < 0 ||
io->pfrio_size > pf_ioctl_maxcount ||
WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_addr))) {
error = EINVAL;
- break;
+ goto fail;
}
totlen = io->pfrio_size * sizeof(struct pfr_addr);
pfras = mallocarray(io->pfrio_size, sizeof(struct pfr_addr),
@@ -5135,7 +5165,7 @@ DIOCCHANGEADDR_error:
error = copyin(io->pfrio_buffer, pfras, totlen);
if (error) {
free(pfras, M_TEMP);
- break;
+ goto fail;
}
PF_RULES_RLOCK();
error = pfr_tst_addrs(&io->pfrio_table, pfras,
@@ -5155,13 +5185,13 @@ DIOCCHANGEADDR_error:
if (io->pfrio_esize != sizeof(struct pfr_addr)) {
error = ENODEV;
- break;
+ goto fail;
}
if (io->pfrio_size < 0 ||
io->pfrio_size > pf_ioctl_maxcount ||
WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_addr))) {
error = EINVAL;
- break;
+ goto fail;
}
totlen = io->pfrio_size * sizeof(struct pfr_addr);
pfras = mallocarray(io->pfrio_size, sizeof(struct pfr_addr),
@@ -5169,7 +5199,7 @@ DIOCCHANGEADDR_error:
error = copyin(io->pfrio_buffer, pfras, totlen);
if (error) {
free(pfras, M_TEMP);
- break;
+ goto fail;
}
PF_RULES_WLOCK();
error = pfr_ina_define(&io->pfrio_table, pfras,
@@ -5204,13 +5234,13 @@ DIOCCHANGEADDR_error:
if (io->esize != sizeof(*ioe)) {
error = ENODEV;
- break;
+ goto fail;
}
if (io->size < 0 ||
io->size > pf_ioctl_maxcount ||
WOULD_OVERFLOW(io->size, sizeof(struct pfioc_trans_e))) {
error = EINVAL;
- break;
+ goto fail;
}
totlen = sizeof(struct pfioc_trans_e) * io->size;
ioes = mallocarray(io->size, sizeof(struct pfioc_trans_e),
@@ -5218,7 +5248,7 @@ DIOCCHANGEADDR_error:
error = copyin(io->array, ioes, totlen);
if (error) {
free(ioes, M_TEMP);
- break;
+ goto fail;
}
PF_RULES_WLOCK();
for (i = 0, ioe = ioes; i < io->size; i++, ioe++) {
@@ -5285,13 +5315,13 @@ DIOCCHANGEADDR_error:
if (io->esize != sizeof(*ioe)) {
error = ENODEV;
- break;
+ goto fail;
}
if (io->size < 0 ||
io->size > pf_ioctl_maxcount ||
WOULD_OVERFLOW(io->size, sizeof(struct pfioc_trans_e))) {
error = EINVAL;
- break;
+ goto fail;
}
totlen = sizeof(struct pfioc_trans_e) * io->size;
ioes = mallocarray(io->size, sizeof(struct pfioc_trans_e),
@@ -5299,7 +5329,7 @@ DIOCCHANGEADDR_error:
error = copyin(io->array, ioes, totlen);
if (error) {
free(ioes, M_TEMP);
- break;
+ goto fail;
}
PF_RULES_WLOCK();
for (i = 0, ioe = ioes; i < io->size; i++, ioe++) {
@@ -5368,14 +5398,14 @@ DIOCCHANGEADDR_error:
if (io->esize != sizeof(*ioe)) {
error = ENODEV;
- break;
+ goto fail;
}
if (io->size < 0 ||
io->size > pf_ioctl_maxcount ||
WOULD_OVERFLOW(io->size, sizeof(struct pfioc_trans_e))) {
error = EINVAL;
- break;
+ goto fail;
}
totlen = sizeof(struct pfioc_trans_e) * io->size;
@@ -5384,7 +5414,7 @@ DIOCCHANGEADDR_error:
error = copyin(io->array, ioes, totlen);
if (error) {
free(ioes, M_TEMP);
- break;
+ goto fail;
}
PF_RULES_WLOCK();
/* First makes sure everything will succeed. */
@@ -5525,7 +5555,7 @@ DIOCCHANGEADDR_error:
if (psn->psn_len == 0) {
psn->psn_len = sizeof(struct pf_src_node) * nr;
- break;
+ goto fail;
}
nr = 0;
@@ -5550,7 +5580,7 @@ DIOCCHANGEADDR_error:
sizeof(struct pf_src_node) * nr);
if (error) {
free(pstore, M_TEMP);
- break;
+ goto fail;
}
psn->psn_len = sizeof(struct pf_src_node) * nr;
free(pstore, M_TEMP);
@@ -5606,14 +5636,14 @@ DIOCCHANGEADDR_error:
if (io->pfiio_esize != sizeof(struct pfi_kif)) {
error = ENODEV;
- break;
+ goto fail;
}
if (io->pfiio_size < 0 ||
io->pfiio_size > pf_ioctl_maxcount ||
WOULD_OVERFLOW(io->pfiio_size, sizeof(struct pfi_kif))) {
error = EINVAL;
- break;
+ goto fail;
}
io->pfiio_name[sizeof(io->pfiio_name) - 1] = '\0';
@@ -6425,9 +6455,9 @@ shutdown_pf(void)
for (rs_num = 0; rs_num < PF_RULESET_MAX; ++rs_num) {
if ((error = pf_begin_rules(&t[rs_num], rs_num,
anchor->path)) != 0) {
- DPFPRINTF(PF_DEBUG_MISC, ("%s: "
- "anchor.path=%s rs_num=%d\n",
- __func__, anchor->path, rs_num));
+ DPFPRINTF(PF_DEBUG_MISC, "%s: "
+ "anchor.path=%s rs_num=%d",
+ __func__, anchor->path, rs_num);
goto error; /* XXX: rollback? */
}
}
@@ -6449,9 +6479,9 @@ shutdown_pf(void)
eth_anchor->refcnt = 1;
if ((error = pf_begin_eth(&t[0], eth_anchor->path))
!= 0) {
- DPFPRINTF(PF_DEBUG_MISC, ("%s: eth "
- "anchor.path=%s\n", __func__,
- eth_anchor->path));
+ DPFPRINTF(PF_DEBUG_MISC, "%s: eth "
+ "anchor.path=%s", __func__,
+ eth_anchor->path);
goto error;
}
error = pf_commit_eth(t[0], eth_anchor->path);
@@ -6460,27 +6490,27 @@ shutdown_pf(void)
if ((error = pf_begin_rules(&t[0], PF_RULESET_SCRUB, &nn))
!= 0) {
- DPFPRINTF(PF_DEBUG_MISC, ("%s: SCRUB\n", __func__));
+ DPFPRINTF(PF_DEBUG_MISC, "%s: SCRUB", __func__);
break;
}
if ((error = pf_begin_rules(&t[1], PF_RULESET_FILTER, &nn))
!= 0) {
- DPFPRINTF(PF_DEBUG_MISC, ("%s: FILTER\n", __func__));
+ DPFPRINTF(PF_DEBUG_MISC, "%s: FILTER", __func__);
break; /* XXX: rollback? */
}
if ((error = pf_begin_rules(&t[2], PF_RULESET_NAT, &nn))
!= 0) {
- DPFPRINTF(PF_DEBUG_MISC, ("%s: NAT\n", __func__));
+ DPFPRINTF(PF_DEBUG_MISC, "%s: NAT", __func__);
break; /* XXX: rollback? */
}
if ((error = pf_begin_rules(&t[3], PF_RULESET_BINAT, &nn))
!= 0) {
- DPFPRINTF(PF_DEBUG_MISC, ("%s: BINAT\n", __func__));
+ DPFPRINTF(PF_DEBUG_MISC, "%s: BINAT", __func__);
break; /* XXX: rollback? */
}
if ((error = pf_begin_rules(&t[4], PF_RULESET_RDR, &nn))
!= 0) {
- DPFPRINTF(PF_DEBUG_MISC, ("%s: RDR\n", __func__));
+ DPFPRINTF(PF_DEBUG_MISC, "%s: RDR", __func__);
break; /* XXX: rollback? */
}
@@ -6499,7 +6529,7 @@ shutdown_pf(void)
break;
if ((error = pf_begin_eth(&t[0], &nn)) != 0) {
- DPFPRINTF(PF_DEBUG_MISC, ("%s: eth\n", __func__));
+ DPFPRINTF(PF_DEBUG_MISC, "%s: eth", __func__);
break;
}
error = pf_commit_eth(t[0], &nn);
@@ -6507,7 +6537,7 @@ shutdown_pf(void)
#ifdef ALTQ
if ((error = pf_begin_altq(&t[0])) != 0) {
- DPFPRINTF(PF_DEBUG_MISC, ("%s: ALTQ\n", __func__));
+ DPFPRINTF(PF_DEBUG_MISC, "%s: ALTQ", __func__);
break;
}
pf_commit_altq(t[0]);
diff --git a/sys/netpfil/pf/pf_lb.c b/sys/netpfil/pf/pf_lb.c
index d4728f61dce8..ea0d6facf695 100644
--- a/sys/netpfil/pf/pf_lb.c
+++ b/sys/netpfil/pf/pf_lb.c
@@ -71,8 +71,6 @@
#define V_pf_rdr_srcport_rewrite_tries VNET(pf_rdr_srcport_rewrite_tries)
VNET_DEFINE_STATIC(int, pf_rdr_srcport_rewrite_tries) = 16;
-#define DPFPRINTF(n, x) if (V_pf_status.debug >= (n)) printf x
-
static uint64_t pf_hash(struct pf_addr *, struct pf_addr *,
struct pf_poolhashkey *, sa_family_t);
struct pf_krule *pf_match_translation(int, struct pf_test_ctx *);
@@ -617,7 +615,7 @@ pf_map_addr(sa_family_t af, struct pf_krule *r, struct pf_addr *saddr,
rpool->tblidx = (int)arc4random_uniform(cnt);
memset(&rpool->counter, 0, sizeof(rpool->counter));
if (pfr_pool_get(kt, &rpool->tblidx, &rpool->counter,
- af, pf_islinklocal)) {
+ af, pf_islinklocal, false)) {
reason = PFRES_MAPFAILED;
goto done_pool_mtx; /* unsupported */
}
@@ -684,7 +682,7 @@ pf_map_addr(sa_family_t af, struct pf_krule *r, struct pf_addr *saddr,
rpool->tblidx = (int)(hashidx % cnt);
memset(&rpool->counter, 0, sizeof(rpool->counter));
if (pfr_pool_get(kt, &rpool->tblidx, &rpool->counter,
- af, pf_islinklocal)) {
+ af, pf_islinklocal, false)) {
reason = PFRES_MAPFAILED;
goto done_pool_mtx; /* unsupported */
}
@@ -701,11 +699,12 @@ pf_map_addr(sa_family_t af, struct pf_krule *r, struct pf_addr *saddr,
if (rpool->cur->addr.type == PF_ADDR_TABLE) {
if (!pfr_pool_get(rpool->cur->addr.p.tbl,
- &rpool->tblidx, &rpool->counter, af, NULL))
+ &rpool->tblidx, &rpool->counter, af, NULL, true))
goto get_addr;
} else if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) {
if (!pfr_pool_get(rpool->cur->addr.p.dyn->pfid_kt,
- &rpool->tblidx, &rpool->counter, af, pf_islinklocal))
+ &rpool->tblidx, &rpool->counter, af, pf_islinklocal,
+ true))
goto get_addr;
} else if (pf_match_addr(0, raddr, rmask, &rpool->counter, af))
goto get_addr;
@@ -715,9 +714,10 @@ pf_map_addr(sa_family_t af, struct pf_krule *r, struct pf_addr *saddr,
rpool->cur = TAILQ_FIRST(&rpool->list);
else
rpool->cur = TAILQ_NEXT(rpool->cur, entries);
+ rpool->tblidx = -1;
if (rpool->cur->addr.type == PF_ADDR_TABLE) {
if (pfr_pool_get(rpool->cur->addr.p.tbl,
- &rpool->tblidx, &rpool->counter, af, NULL)) {
+ &rpool->tblidx, &rpool->counter, af, NULL, true)) {
/* table contains no address of type 'af' */
if (rpool->cur != acur)
goto try_next;
@@ -725,9 +725,9 @@ pf_map_addr(sa_family_t af, struct pf_krule *r, struct pf_addr *saddr,
goto done_pool_mtx;
}
} else if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) {
- rpool->tblidx = -1;
if (pfr_pool_get(rpool->cur->addr.p.dyn->pfid_kt,
- &rpool->tblidx, &rpool->counter, af, pf_islinklocal)) {
+ &rpool->tblidx, &rpool->counter, af, pf_islinklocal,
+ true)) {
/* table contains no address of type 'af' */
if (rpool->cur != acur)
goto try_next;
@@ -755,10 +755,6 @@ pf_map_addr(sa_family_t af, struct pf_krule *r, struct pf_addr *saddr,
done_pool_mtx:
mtx_unlock(&rpool->mtx);
- if (reason) {
- counter_u64_add(V_pf_status.counters[reason], 1);
- }
-
return (reason);
}
@@ -793,7 +789,7 @@ pf_map_addr_sn(sa_family_t af, struct pf_krule *r, struct pf_addr *saddr,
if (nkif)
*nkif = sn->rkif;
if (V_pf_status.debug >= PF_DEBUG_NOISY) {
- printf("pf_map_addr: src tracking maps ");
+ printf("%s: src tracking maps ", __func__);
pf_print_host(saddr, 0, af);
printf(" to ");
pf_print_host(naddr, 0, af);
@@ -808,14 +804,16 @@ pf_map_addr_sn(sa_family_t af, struct pf_krule *r, struct pf_addr *saddr,
* Source node has not been found. Find a new address and store it
* in variables given by the caller.
*/
- if (pf_map_addr(af, r, saddr, naddr, nkif, init_addr, rpool) != 0) {
- /* pf_map_addr() sets reason counters on its own */
+ if ((reason = pf_map_addr(af, r, saddr, naddr, nkif, init_addr,
+ rpool)) != 0) {
+ if (V_pf_status.debug >= PF_DEBUG_MISC)
+ printf("%s: pf_map_addr has failed\n", __func__);
goto done;
}
if (V_pf_status.debug >= PF_DEBUG_NOISY &&
(rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_NONE) {
- printf("pf_map_addr: selected address ");
+ printf("%s: selected address ", __func__);
pf_print_host(naddr, 0, af);
if (nkif)
printf("@%s", (*nkif)->pfik_name);
@@ -826,10 +824,6 @@ done:
if (sn != NULL)
PF_SRC_NODE_UNLOCK(sn);
- if (reason) {
- counter_u64_add(V_pf_status.counters[reason], 1);
- }
-
return (reason);
}
@@ -908,19 +902,19 @@ pf_get_transaddr(struct pf_test_ctx *ctx, struct pf_krule *r,
if (pf_get_mape_sport(pd, r, naddr, nportp,
&ctx->udp_mapping, rpool)) {
DPFPRINTF(PF_DEBUG_MISC,
- ("pf: MAP-E port allocation (%u/%u/%u)"
- " failed\n",
+ "pf: MAP-E port allocation (%u/%u/%u)"
+ " failed",
rpool->mape.offset,
rpool->mape.psidlen,
- rpool->mape.psid));
+ rpool->mape.psid);
reason = PFRES_MAPFAILED;
goto notrans;
}
} else if (pf_get_sport(pd, r, naddr, nportp, low, high,
rpool, &ctx->udp_mapping, PF_SN_NAT)) {
DPFPRINTF(PF_DEBUG_MISC,
- ("pf: NAT proxy port allocation (%u-%u) failed\n",
- rpool->proxy_port[0], rpool->proxy_port[1]));
+ "pf: NAT proxy port allocation (%u-%u) failed",
+ rpool->proxy_port[0], rpool->proxy_port[1]);
reason = PFRES_MAPFAILED;
goto notrans;
}
@@ -1016,10 +1010,13 @@ pf_get_transaddr(struct pf_test_ctx *ctx, struct pf_krule *r,
if (rpool->proxy_port[1]) {
uint32_t tmp_nport;
+ uint16_t div;
+
+ div = r->rdr.proxy_port[1] - r->rdr.proxy_port[0] + 1;
+ div = (div == 0) ? 1 : div;
- tmp_nport = ((ntohs(pd->ndport) - ntohs(r->dst.port[0])) %
- (rpool->proxy_port[1] - rpool->proxy_port[0] +
- 1)) + rpool->proxy_port[0];
+ tmp_nport = ((ntohs(pd->ndport) - ntohs(r->dst.port[0])) % div) +
+ rpool->proxy_port[0];
/* Wrap around if necessary. */
if (tmp_nport > 65535)
@@ -1086,13 +1083,13 @@ pf_get_transaddr(struct pf_test_ctx *ctx, struct pf_krule *r,
* the state may be reused if the TCP state is terminal.
*/
DPFPRINTF(PF_DEBUG_MISC,
- ("pf: RDR source port allocation failed\n"));
+ "pf: RDR source port allocation failed");
break;
out:
DPFPRINTF(PF_DEBUG_MISC,
- ("pf: RDR source port allocation %u->%u\n",
- ntohs(pd->nsport), ntohs(ctx->nk->port[0])));
+ "pf: RDR source port allocation %u->%u",
+ ntohs(pd->nsport), ntohs(ctx->nk->port[0]));
break;
}
default:
@@ -1141,8 +1138,8 @@ pf_get_transaddr_af(struct pf_krule *r, struct pf_pdesc *pd)
if (pf_get_sport(pd, r, &nsaddr, &nport, r->nat.proxy_port[0],
r->nat.proxy_port[1], &r->nat, NULL, PF_SN_NAT)) {
DPFPRINTF(PF_DEBUG_MISC,
- ("pf: af-to NAT proxy port allocation (%u-%u) failed",
- r->nat.proxy_port[0], r->nat.proxy_port[1]));
+ "pf: af-to NAT proxy port allocation (%u-%u) failed",
+ r->nat.proxy_port[0], r->nat.proxy_port[1]);
return (-1);
}
diff --git a/sys/netpfil/pf/pf_norm.c b/sys/netpfil/pf/pf_norm.c
index 369292ca365e..8cea9557633c 100644
--- a/sys/netpfil/pf/pf_norm.c
+++ b/sys/netpfil/pf/pf_norm.c
@@ -160,13 +160,6 @@ static int pf_reassemble6(struct mbuf **,
struct ip6_frag *, uint16_t, uint16_t, u_short *);
#endif /* INET6 */
-#define DPFPRINTF(x) do { \
- if (V_pf_status.debug >= PF_DEBUG_MISC) { \
- printf("%s: ", __func__); \
- printf x ; \
- } \
-} while(0)
-
#ifdef INET
static void
pf_ip2key(struct ip *ip, struct pf_frnode *key)
@@ -262,7 +255,8 @@ pf_purge_fragments(uint32_t expire)
if (frag->fr_timeout > expire)
break;
- DPFPRINTF(("expiring %d(%p)\n", frag->fr_id, frag));
+ DPFPRINTF(PF_DEBUG_MISC, "expiring %d(%p)",
+ frag->fr_id, frag);
pf_free_fragment(frag);
}
@@ -281,7 +275,7 @@ pf_flush_fragments(void)
PF_FRAG_ASSERT();
goal = uma_zone_get_cur(V_pf_frent_z) * 9 / 10;
- DPFPRINTF(("trying to free %d frag entriess\n", goal));
+ DPFPRINTF(PF_DEBUG_MISC, "trying to free %d frag entriess", goal);
while (goal < uma_zone_get_cur(V_pf_frent_z)) {
frag = TAILQ_LAST(&V_pf_fragqueue, pf_fragqueue);
if (frag)
@@ -573,26 +567,30 @@ pf_fillup_fragment(struct pf_frnode *key, uint32_t id,
/* No empty fragments. */
if (frent->fe_len == 0) {
- DPFPRINTF(("bad fragment: len 0\n"));
+ DPFPRINTF(PF_DEBUG_MISC, "bad fragment: len 0");
goto bad_fragment;
}
/* All fragments are 8 byte aligned. */
if (frent->fe_mff && (frent->fe_len & 0x7)) {
- DPFPRINTF(("bad fragment: mff and len %d\n", frent->fe_len));
+ DPFPRINTF(PF_DEBUG_MISC, "bad fragment: mff and len %d",
+ frent->fe_len);
goto bad_fragment;
}
/* Respect maximum length, IP_MAXPACKET == IPV6_MAXPACKET. */
if (frent->fe_off + frent->fe_len > IP_MAXPACKET) {
- DPFPRINTF(("bad fragment: max packet %d\n",
- frent->fe_off + frent->fe_len));
+ DPFPRINTF(PF_DEBUG_MISC, "bad fragment: max packet %d",
+ frent->fe_off + frent->fe_len);
goto bad_fragment;
}
- DPFPRINTF((key->fn_af == AF_INET ?
- "reass frag %d @ %d-%d\n" : "reass frag %#08x @ %d-%d\n",
- id, frent->fe_off, frent->fe_off + frent->fe_len));
+ if (key->fn_af == AF_INET)
+ DPFPRINTF(PF_DEBUG_MISC, "reass frag %d @ %d-%d\n",
+ id, frent->fe_off, frent->fe_off + frent->fe_len);
+ else
+ DPFPRINTF(PF_DEBUG_MISC, "reass frag %#08x @ %d-%d",
+ id, frent->fe_off, frent->fe_off + frent->fe_len);
/* Fully buffer all of the fragments in this fragment queue. */
frag = pf_find_fragment(key, id);
@@ -690,10 +688,10 @@ pf_fillup_fragment(struct pf_frnode *key, uint32_t id,
precut = prev->fe_off + prev->fe_len - frent->fe_off;
if (precut >= frent->fe_len) {
- DPFPRINTF(("new frag overlapped\n"));
+ DPFPRINTF(PF_DEBUG_MISC, "new frag overlapped");
goto drop_fragment;
}
- DPFPRINTF(("frag head overlap %d\n", precut));
+ DPFPRINTF(PF_DEBUG_MISC, "frag head overlap %d", precut);
m_adj(frent->fe_m, precut);
frent->fe_off += precut;
frent->fe_len -= precut;
@@ -705,7 +703,8 @@ pf_fillup_fragment(struct pf_frnode *key, uint32_t id,
aftercut = frent->fe_off + frent->fe_len - after->fe_off;
if (aftercut < after->fe_len) {
- DPFPRINTF(("frag tail overlap %d", aftercut));
+ DPFPRINTF(PF_DEBUG_MISC, "frag tail overlap %d",
+ aftercut);
m_adj(after->fe_m, aftercut);
/* Fragment may switch queue as fe_off changes */
pf_frent_remove(frag, after);
@@ -713,7 +712,8 @@ pf_fillup_fragment(struct pf_frnode *key, uint32_t id,
after->fe_len -= aftercut;
/* Insert into correct queue */
if (pf_frent_insert(frag, after, prev)) {
- DPFPRINTF(("fragment requeue limit exceeded"));
+ DPFPRINTF(PF_DEBUG_MISC,
+ "fragment requeue limit exceeded");
m_freem(after->fe_m);
uma_zfree(V_pf_frent_z, after);
/* There is not way to recover */
@@ -723,7 +723,7 @@ pf_fillup_fragment(struct pf_frnode *key, uint32_t id,
}
/* This fragment is completely overlapped, lose it. */
- DPFPRINTF(("old frag overlapped\n"));
+ DPFPRINTF(PF_DEBUG_MISC, "old frag overlapped");
next = TAILQ_NEXT(after, fr_next);
pf_frent_remove(frag, after);
m_freem(after->fe_m);
@@ -732,7 +732,7 @@ pf_fillup_fragment(struct pf_frnode *key, uint32_t id,
/* If part of the queue gets too long, there is not way to recover. */
if (pf_frent_insert(frag, frent, prev)) {
- DPFPRINTF(("fragment queue limit exceeded\n"));
+ DPFPRINTF(PF_DEBUG_MISC, "fragment queue limit exceeded");
goto bad_fragment;
}
@@ -748,7 +748,7 @@ free_fragment:
* fragment, the entire datagram (and any constituent fragments) MUST
* be silently discarded.
*/
- DPFPRINTF(("flush overlapping fragments\n"));
+ DPFPRINTF(PF_DEBUG_MISC, "flush overlapping fragments");
pf_free_fragment(frag);
bad_fragment:
@@ -826,7 +826,8 @@ pf_reassemble(struct mbuf **m0, u_short *reason)
m = *m0 = NULL;
if (frag->fr_holes) {
- DPFPRINTF(("frag %d, holes %d\n", frag->fr_id, frag->fr_holes));
+ DPFPRINTF(PF_DEBUG_MISC, "frag %d, holes %d",
+ frag->fr_id, frag->fr_holes);
return (PF_PASS); /* drop because *m0 is NULL, no error */
}
@@ -872,14 +873,14 @@ pf_reassemble(struct mbuf **m0, u_short *reason)
ip->ip_off &= ~(IP_MF|IP_OFFMASK);
if (hdrlen + total > IP_MAXPACKET) {
- DPFPRINTF(("drop: too big: %d\n", total));
+ DPFPRINTF(PF_DEBUG_MISC, "drop: too big: %d", total);
ip->ip_len = 0;
REASON_SET(reason, PFRES_SHORT);
/* PF_DROP requires a valid mbuf *m0 in pf_test() */
return (PF_DROP);
}
- DPFPRINTF(("complete: %p(%d)\n", m, ntohs(ip->ip_len)));
+ DPFPRINTF(PF_DEBUG_MISC, "complete: %p(%d)", m, ntohs(ip->ip_len));
return (PF_PASS);
}
#endif /* INET */
@@ -931,8 +932,8 @@ pf_reassemble6(struct mbuf **m0, struct ip6_frag *fraghdr,
m = *m0 = NULL;
if (frag->fr_holes) {
- DPFPRINTF(("frag %d, holes %d\n", frag->fr_id,
- frag->fr_holes));
+ DPFPRINTF(PF_DEBUG_MISC, "frag %d, holes %d", frag->fr_id,
+ frag->fr_holes);
PF_FRAG_UNLOCK();
return (PF_PASS); /* Drop because *m0 is NULL, no error. */
}
@@ -993,14 +994,15 @@ pf_reassemble6(struct mbuf **m0, struct ip6_frag *fraghdr,
ip6->ip6_nxt = proto;
if (hdrlen - sizeof(struct ip6_hdr) + total > IPV6_MAXPACKET) {
- DPFPRINTF(("drop: too big: %d\n", total));
+ DPFPRINTF(PF_DEBUG_MISC, "drop: too big: %d", total);
ip6->ip6_plen = 0;
REASON_SET(reason, PFRES_SHORT);
/* PF_DROP requires a valid mbuf *m0 in pf_test6(). */
return (PF_DROP);
}
- DPFPRINTF(("complete: %p(%d)\n", m, ntohs(ip6->ip6_plen)));
+ DPFPRINTF(PF_DEBUG_MISC, "complete: %p(%d)", m,
+ ntohs(ip6->ip6_plen));
return (PF_PASS);
fail:
@@ -1090,7 +1092,7 @@ pf_refragment6(struct ifnet *ifp, struct mbuf **m0, struct m_tag *mtag,
action = PF_PASS;
} else {
/* Drop expects an mbuf to free. */
- DPFPRINTF(("refragment error %d\n", error));
+ DPFPRINTF(PF_DEBUG_MISC, "refragment error %d", error);
action = PF_DROP;
}
for (; m; m = t) {
@@ -1230,7 +1232,7 @@ pf_normalize_ip(u_short *reason, struct pf_pdesc *pd)
* no-df above, fine. Otherwise drop it.
*/
if (h->ip_off & htons(IP_DF)) {
- DPFPRINTF(("IP_DF\n"));
+ DPFPRINTF(PF_DEBUG_MISC, "IP_DF");
goto bad;
}
@@ -1238,13 +1240,13 @@ pf_normalize_ip(u_short *reason, struct pf_pdesc *pd)
/* All fragments are 8 byte aligned */
if (mff && (ip_len & 0x7)) {
- DPFPRINTF(("mff and %d\n", ip_len));
+ DPFPRINTF(PF_DEBUG_MISC, "mff and %d", ip_len);
goto bad;
}
/* Respect maximum length */
if (fragoff + ip_len > IP_MAXPACKET) {
- DPFPRINTF(("max packet %d\n", fragoff + ip_len));
+ DPFPRINTF(PF_DEBUG_MISC, "max packet %d", fragoff + ip_len);
goto bad;
}
@@ -1256,7 +1258,8 @@ pf_normalize_ip(u_short *reason, struct pf_pdesc *pd)
/* Fully buffer all of the fragments
* Might return a completely reassembled mbuf, or NULL */
PF_FRAG_LOCK();
- DPFPRINTF(("reass frag %d @ %d-%d\n", h->ip_id, fragoff, max));
+ DPFPRINTF(PF_DEBUG_MISC, "reass frag %d @ %d-%d",
+ h->ip_id, fragoff, max);
verdict = pf_reassemble(&pd->m, reason);
PF_FRAG_UNLOCK();
@@ -1282,7 +1285,7 @@ pf_normalize_ip(u_short *reason, struct pf_pdesc *pd)
return (PF_PASS);
bad:
- DPFPRINTF(("dropping bad fragment\n"));
+ DPFPRINTF(PF_DEBUG_MISC, "dropping bad fragment");
REASON_SET(reason, PFRES_FRAG);
drop:
if (r != NULL && r->log)
@@ -1711,7 +1714,7 @@ pf_normalize_tcp_stateful(struct pf_pdesc *pd,
(uptime.tv_sec - src->scrub->pfss_last.tv_sec > TS_MAX_IDLE ||
time_uptime - (state->creation / 1000) > TS_MAX_CONN)) {
if (V_pf_status.debug >= PF_DEBUG_MISC) {
- DPFPRINTF(("src idled out of PAWS\n"));
+ DPFPRINTF(PF_DEBUG_MISC, "src idled out of PAWS");
pf_print_state(state);
printf("\n");
}
@@ -1721,7 +1724,7 @@ pf_normalize_tcp_stateful(struct pf_pdesc *pd,
if (dst->scrub && (dst->scrub->pfss_flags & PFSS_PAWS) &&
uptime.tv_sec - dst->scrub->pfss_last.tv_sec > TS_MAX_IDLE) {
if (V_pf_status.debug >= PF_DEBUG_MISC) {
- DPFPRINTF(("dst idled out of PAWS\n"));
+ DPFPRINTF(PF_DEBUG_MISC, "dst idled out of PAWS");
pf_print_state(state);
printf("\n");
}
@@ -1826,22 +1829,22 @@ pf_normalize_tcp_stateful(struct pf_pdesc *pd,
* an old timestamp.
*/
- DPFPRINTF(("Timestamp failed %c%c%c%c\n",
+ DPFPRINTF(PF_DEBUG_MISC, "Timestamp failed %c%c%c%c",
SEQ_LT(tsval, dst->scrub->pfss_tsecr) ? '0' : ' ',
SEQ_GT(tsval, src->scrub->pfss_tsval +
tsval_from_last) ? '1' : ' ',
SEQ_GT(tsecr, dst->scrub->pfss_tsval) ? '2' : ' ',
- SEQ_LT(tsecr, dst->scrub->pfss_tsval0)? '3' : ' '));
- DPFPRINTF((" tsval: %u tsecr: %u +ticks: %u "
- "idle: %jus %lums\n",
+ SEQ_LT(tsecr, dst->scrub->pfss_tsval0)? '3' : ' ');
+ DPFPRINTF(PF_DEBUG_MISC, " tsval: %u tsecr: %u +ticks: "
+ "%u idle: %jus %lums",
tsval, tsecr, tsval_from_last,
(uintmax_t)delta_ts.tv_sec,
- delta_ts.tv_usec / 1000));
- DPFPRINTF((" src->tsval: %u tsecr: %u\n",
- src->scrub->pfss_tsval, src->scrub->pfss_tsecr));
- DPFPRINTF((" dst->tsval: %u tsecr: %u tsval0: %u"
- "\n", dst->scrub->pfss_tsval,
- dst->scrub->pfss_tsecr, dst->scrub->pfss_tsval0));
+ delta_ts.tv_usec / 1000);
+ DPFPRINTF(PF_DEBUG_MISC, " src->tsval: %u tsecr: %u",
+ src->scrub->pfss_tsval, src->scrub->pfss_tsecr);
+ DPFPRINTF(PF_DEBUG_MISC, " dst->tsval: %u tsecr: %u "
+ "tsval0: %u", dst->scrub->pfss_tsval,
+ dst->scrub->pfss_tsecr, dst->scrub->pfss_tsval0);
if (V_pf_status.debug >= PF_DEBUG_MISC) {
pf_print_state(state);
pf_print_flags(tcp_get_flags(th));
@@ -1891,8 +1894,8 @@ pf_normalize_tcp_stateful(struct pf_pdesc *pd,
* stack changed its RFC1323 behavior?!?!
*/
if (V_pf_status.debug >= PF_DEBUG_MISC) {
- DPFPRINTF(("Did not receive expected RFC1323 "
- "timestamp\n"));
+ DPFPRINTF(PF_DEBUG_MISC, "Did not receive expected "
+ "RFC1323 timestamp");
pf_print_state(state);
pf_print_flags(tcp_get_flags(th));
printf("\n");
@@ -1919,9 +1922,9 @@ pf_normalize_tcp_stateful(struct pf_pdesc *pd,
if (V_pf_status.debug >= PF_DEBUG_MISC && dst->scrub &&
(dst->scrub->pfss_flags & PFSS_TIMESTAMP)) {
/* Don't warn if other host rejected RFC1323 */
- DPFPRINTF(("Broken RFC1323 stack did not "
- "timestamp data packet. Disabled PAWS "
- "security.\n"));
+ DPFPRINTF(PF_DEBUG_MISC, "Broken RFC1323 stack did "
+ "not timestamp data packet. Disabled PAWS "
+ "security.");
pf_print_state(state);
pf_print_flags(tcp_get_flags(th));
printf("\n");
diff --git a/sys/netpfil/pf/pf_osfp.c b/sys/netpfil/pf/pf_osfp.c
index 3e00cc7c80a2..150626c5f3fb 100644
--- a/sys/netpfil/pf/pf_osfp.c
+++ b/sys/netpfil/pf/pf_osfp.c
@@ -40,9 +40,6 @@
#endif
static MALLOC_DEFINE(M_PFOSFP, "pf_osfp", "pf(4) operating system fingerprints");
-#define DPFPRINTF(format, x...) \
- if (V_pf_status.debug >= PF_DEBUG_NOISY) \
- printf(format , ##x)
SLIST_HEAD(pf_osfp_list, pf_os_fingerprint);
VNET_DEFINE_STATIC(struct pf_osfp_list, pf_osfp_list) =
@@ -189,8 +186,8 @@ pf_osfp_fingerprint_hdr(const struct ip *ip, const struct ip6_hdr *ip6, const st
optlen = MAX(optlen, 1); /* paranoia */
}
- DPFPRINTF("fingerprinted %s:%d %d:%d:%d:%d:%llx (%d) "
- "(TS=%s,M=%s%d,W=%s%d)\n",
+ DPFPRINTF(PF_DEBUG_NOISY, "fingerprinted %s:%d %d:%d:%d:%d:%llx (%d) "
+ "(TS=%s,M=%s%d,W=%s%d)",
srcname, ntohs(tcp->th_sport),
fp.fp_wsize, fp.fp_ttl, (fp.fp_flags & PF_OSFP_DF) != 0,
fp.fp_psize, (long long int)fp.fp_tcpopts, fp.fp_optcnt,
@@ -219,7 +216,7 @@ pf_osfp_match(struct pf_osfp_enlist *list, pf_osfp_t os)
if (os == PF_OSFP_ANY)
return (1);
if (list == NULL) {
- DPFPRINTF("osfp no match against %x\n", os);
+ DPFPRINTF(PF_DEBUG_NOISY, "osfp no match against %x", os);
return (os == PF_OSFP_UNKNOWN);
}
PF_OSFP_UNPACK(os, os_class, os_version, os_subtype);
@@ -228,13 +225,13 @@ pf_osfp_match(struct pf_osfp_enlist *list, pf_osfp_t os)
if ((os_class == PF_OSFP_ANY || en_class == os_class) &&
(os_version == PF_OSFP_ANY || en_version == os_version) &&
(os_subtype == PF_OSFP_ANY || en_subtype == os_subtype)) {
- DPFPRINTF("osfp matched %s %s %s %x==%x\n",
+ DPFPRINTF(PF_DEBUG_NOISY, "osfp matched %s %s %s %x==%x",
entry->fp_class_nm, entry->fp_version_nm,
entry->fp_subtype_nm, os, entry->fp_os);
return (1);
}
}
- DPFPRINTF("fingerprint 0x%x didn't match\n", os);
+ DPFPRINTF(PF_DEBUG_NOISY, "fingerprint 0x%x didn't match", os);
return (0);
}
@@ -275,8 +272,8 @@ pf_osfp_add(struct pf_osfp_ioctl *fpioc)
fpadd.fp_ttl = fpioc->fp_ttl;
#if 0 /* XXX RYAN wants to fix logging */
- DPFPRINTF("adding osfp %s %s %s = %s%d:%d:%d:%s%d:0x%llx %d "
- "(TS=%s,M=%s%d,W=%s%d) %x\n",
+ DPFPRINTF(PF_DEBUG_NOISY, "adding osfp %s %s %s ="
+ " %s%d:%d:%d:%s%d:0x%llx %d (TS=%s,M=%s%d,W=%s%d) %x",
fpioc->fp_os.fp_class_nm, fpioc->fp_os.fp_version_nm,
fpioc->fp_os.fp_subtype_nm,
(fpadd.fp_flags & PF_OSFP_WSIZE_MOD) ? "%" :
diff --git a/sys/netpfil/pf/pf_ruleset.c b/sys/netpfil/pf/pf_ruleset.c
index 2e5165a9900c..43b51f2933f4 100644
--- a/sys/netpfil/pf/pf_ruleset.c
+++ b/sys/netpfil/pf/pf_ruleset.c
@@ -59,9 +59,6 @@
#error "Kernel only file. Please use sbin/pfctl/pf_ruleset.c instead."
#endif
-#define DPFPRINTF(format, x...) \
- if (V_pf_status.debug >= PF_DEBUG_NOISY) \
- printf(format , ##x)
#define rs_malloc(x) malloc(x, M_TEMP, M_NOWAIT|M_ZERO)
#define rs_free(x) free(x, M_TEMP)
@@ -386,7 +383,8 @@ pf_kanchor_setup(struct pf_krule *r, const struct pf_kruleset *s,
strlcpy(path, s->anchor->path, MAXPATHLEN);
while (name[0] == '.' && name[1] == '.' && name[2] == '/') {
if (!path[0]) {
- DPFPRINTF("%s: .. beyond root\n", __func__);
+ DPFPRINTF(PF_DEBUG_NOISY, "%s: .. beyond root",
+ __func__);
rs_free(path);
return (1);
}
@@ -408,7 +406,7 @@ pf_kanchor_setup(struct pf_krule *r, const struct pf_kruleset *s,
ruleset = pf_find_or_create_kruleset(path);
rs_free(path);
if (ruleset == NULL || ruleset == &pf_main_ruleset) {
- DPFPRINTF("%s: ruleset\n", __func__);
+ DPFPRINTF(PF_DEBUG_NOISY, "%s: ruleset", __func__);
return (1);
}
r->anchor = ruleset->anchor;
@@ -690,7 +688,8 @@ pf_keth_anchor_setup(struct pf_keth_rule *r, const struct pf_keth_ruleset *s,
strlcpy(path, s->anchor->path, MAXPATHLEN);
while (name[0] == '.' && name[1] == '.' && name[2] == '/') {
if (!path[0]) {
- DPFPRINTF("%s: .. beyond root\n", __func__);
+ DPFPRINTF(PF_DEBUG_NOISY, "%s: .. beyond root",
+ __func__);
rs_free(path);
return (1);
}
@@ -712,7 +711,7 @@ pf_keth_anchor_setup(struct pf_keth_rule *r, const struct pf_keth_ruleset *s,
ruleset = pf_find_or_create_keth_ruleset(path);
rs_free(path);
if (ruleset == NULL || ruleset->anchor == NULL) {
- DPFPRINTF("%s: ruleset\n", __func__);
+ DPFPRINTF(PF_DEBUG_NOISY, "%s: ruleset", __func__);
return (1);
}
r->anchor = ruleset->anchor;
diff --git a/sys/netpfil/pf/pf_syncookies.c b/sys/netpfil/pf/pf_syncookies.c
index 66757fa4b756..4a935bc65767 100644
--- a/sys/netpfil/pf/pf_syncookies.c
+++ b/sys/netpfil/pf/pf_syncookies.c
@@ -88,8 +88,6 @@
#include <net/pfvar.h>
#include <netpfil/pf/pf_nv.h>
-#define DPFPRINTF(n, x) if (V_pf_status.debug >= (n)) printf x
-
union pf_syncookie {
uint8_t cookie;
struct {
@@ -281,7 +279,7 @@ pf_synflood_check(struct pf_pdesc *pd)
pf_syncookie_rotate, curvnet);
V_pf_status.syncookies_active = true;
DPFPRINTF(LOG_WARNING,
- ("synflood detected, enabling syncookies\n"));
+ "synflood detected, enabling syncookies");
// XXXTODO V_pf_status.lcounters[LCNT_SYNFLOODS]++;
}
@@ -367,7 +365,7 @@ pf_syncookie_rotate(void *arg)
V_pf_status.syncookies_mode == PF_SYNCOOKIES_NEVER)
) {
V_pf_status.syncookies_active = false;
- DPFPRINTF(PF_DEBUG_MISC, ("syncookies disabled\n"));
+ DPFPRINTF(PF_DEBUG_MISC, "syncookies disabled");
}
/* nothing in flight any more? delete keys and return */
diff --git a/sys/netpfil/pf/pf_table.c b/sys/netpfil/pf/pf_table.c
index 2034f4422ef1..ecc185f89ad7 100644
--- a/sys/netpfil/pf/pf_table.c
+++ b/sys/netpfil/pf/pf_table.c
@@ -49,8 +49,6 @@
#include <net/vnet.h>
#include <net/pfvar.h>
-#define DPFPRINTF(n, x) if (V_pf_status.debug >= (n)) printf x
-
#define ACCEPT_FLAGS(flags, oklist) \
do { \
if ((flags & ~(oklist)) & \
@@ -819,10 +817,10 @@ pfr_create_kentry(struct pfr_addr *ad, bool counters)
static void
pfr_destroy_kentries(struct pfr_kentryworkq *workq)
{
- struct pfr_kentry *p, *q;
+ struct pfr_kentry *p;
- for (p = SLIST_FIRST(workq); p != NULL; p = q) {
- q = SLIST_NEXT(p, pfrke_workq);
+ while ((p = SLIST_FIRST(workq)) != NULL) {
+ SLIST_REMOVE_HEAD(workq, pfrke_workq);
pfr_destroy_kentry(p);
}
}
@@ -1680,8 +1678,7 @@ pfr_ina_commit(struct pfr_table *trs, u_int32_t ticket, int *nadd,
}
if (!(flags & PFR_FLAG_DUMMY)) {
- for (p = SLIST_FIRST(&workq); p != NULL; p = q) {
- q = SLIST_NEXT(p, pfrkt_workq);
+ SLIST_FOREACH_SAFE(p, &workq, pfrkt_workq, q) {
pfr_commit_ktable(p, tzero);
}
rs->topen = 0;
@@ -1710,7 +1707,7 @@ pfr_commit_ktable(struct pfr_ktable *kt, time_t tzero)
} else if (kt->pfrkt_flags & PFR_TFLAG_ACTIVE) {
/* kt might contain addresses */
struct pfr_kentryworkq addrq, addq, changeq, delq, garbageq;
- struct pfr_kentry *p, *q, *next;
+ struct pfr_kentry *p, *q;
struct pfr_addr ad;
pfr_enqueue_addrs(shadow, &addrq, NULL, 0);
@@ -1720,7 +1717,8 @@ pfr_commit_ktable(struct pfr_ktable *kt, time_t tzero)
SLIST_INIT(&delq);
SLIST_INIT(&garbageq);
pfr_clean_node_mask(shadow, &addrq);
- SLIST_FOREACH_SAFE(p, &addrq, pfrke_workq, next) {
+ while ((p = SLIST_FIRST(&addrq)) != NULL) {
+ SLIST_REMOVE_HEAD(&addrq, pfrke_workq);
pfr_copyout_addr(&ad, p);
q = pfr_lookup_addr(kt, &ad, 1);
if (q != NULL) {
@@ -1864,8 +1862,7 @@ pfr_setflags_ktables(struct pfr_ktableworkq *workq)
{
struct pfr_ktable *p, *q;
- for (p = SLIST_FIRST(workq); p; p = q) {
- q = SLIST_NEXT(p, pfrkt_workq);
+ SLIST_FOREACH_SAFE(p, workq, pfrkt_workq, q) {
pfr_setflags_ktable(p, p->pfrkt_nflags);
}
}
@@ -2015,10 +2012,10 @@ pfr_create_ktable(struct pfr_table *tbl, time_t tzero, int attachruleset)
static void
pfr_destroy_ktables(struct pfr_ktableworkq *workq, int flushaddr)
{
- struct pfr_ktable *p, *q;
+ struct pfr_ktable *p;
- for (p = SLIST_FIRST(workq); p; p = q) {
- q = SLIST_NEXT(p, pfrkt_workq);
+ while ((p = SLIST_FIRST(workq)) != NULL) {
+ SLIST_REMOVE_HEAD(workq, pfrkt_workq);
pfr_destroy_ktable(p, flushaddr);
}
}
@@ -2190,7 +2187,7 @@ pfr_update_stats(struct pfr_ktable *kt, struct pf_addr *a, sa_family_t af,
if ((ke == NULL || ke->pfrke_not) != notrule) {
if (op_pass != PFR_OP_PASS)
DPFPRINTF(PF_DEBUG_URGENT,
- ("pfr_update_stats: assertion failed.\n"));
+ "pfr_update_stats: assertion failed.");
op_pass = PFR_OP_XPASS;
}
pfr_kstate_counter_add(&kt->pfrkt_packets[dir_out][op_pass], 1);
@@ -2294,7 +2291,7 @@ pfr_detach_table(struct pfr_ktable *kt)
int
pfr_pool_get(struct pfr_ktable *kt, int *pidx, struct pf_addr *counter,
- sa_family_t af, pf_addr_filter_func_t filter)
+ sa_family_t af, pf_addr_filter_func_t filter, bool loop_once)
{
struct pf_addr *addr, cur, mask, umask_addr;
union sockaddr_union uaddr, umask;
@@ -2339,7 +2336,7 @@ _next_block:
ke = pfr_kentry_byidx(kt, idx, af);
if (ke == NULL) {
/* we don't have this idx, try looping */
- if (loop || (ke = pfr_kentry_byidx(kt, 0, af)) == NULL) {
+ if ((loop || loop_once) || (ke = pfr_kentry_byidx(kt, 0, af)) == NULL) {
pfr_kstate_counter_add(&kt->pfrkt_nomatch, 1);
return (1);
}