summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorprocter <procter@openbsd.org>2018-06-18 11:00:31 +0000
committerprocter <procter@openbsd.org>2018-06-18 11:00:31 +0000
commit672fea2ccb3e4cbe11883d167309a4904628e2e2 (patch)
treea9c544d37a53aaec677522ae61bd3664eb4b20e5
parentfix memory leak: freeaddrinfo() the data from getaddrinfo(). (diff)
downloadwireguard-openbsd-672fea2ccb3e4cbe11883d167309a4904628e2e2.tar.xz
wireguard-openbsd-672fea2ccb3e4cbe11883d167309a4904628e2e2.zip
Refactor the six ways to find TCP options into one new function. As a result:
- MSS and WSCALE option candidates must now meet their min type length. - 'max-mss' is now more tolerant of malformed option lists. These changes were immaterial to the live traffic I've examined. OK sashan@ mpi@
-rw-r--r--sys/net/pf.c197
-rw-r--r--sys/net/pf_norm.c255
-rw-r--r--sys/net/pf_syncookies.c38
-rw-r--r--sys/net/pfvar.h4
4 files changed, 197 insertions, 297 deletions
diff --git a/sys/net/pf.c b/sys/net/pf.c
index fc6fce33716..77aa957072b 100644
--- a/sys/net/pf.c
+++ b/sys/net/pf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf.c,v 1.1067 2018/06/04 12:22:45 bluhm Exp $ */
+/* $OpenBSD: pf.c,v 1.1068 2018/06/18 11:00:31 procter Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -1986,7 +1986,7 @@ pf_patch_32(struct pf_pdesc *pd, u_int32_t *f, u_int32_t v)
/* optimise: inline udp fixup code is unused; let compiler scrub it */
if (proto == IPPROTO_UDP)
- panic("pf_patch_32: udp");
+ panic("%s: udp", __func__);
/* optimise: skip *f != v guard; true for all use-cases */
pf_cksum_fixup(pc, *f / (1 << 16), v / (1 << 16), proto);
@@ -2689,59 +2689,41 @@ pf_translate_icmp_af(struct pf_pdesc *pd, int af, void *arg)
int
pf_modulate_sack(struct pf_pdesc *pd, struct pf_state_peer *dst)
{
- struct tcphdr *th = &pd->hdr.tcp;
- int hlen = (th->th_off << 2) - sizeof(*th);
- int thoptlen = hlen;
- u_int8_t opts[MAX_TCPOPTLEN], *opt = opts;
- int copyback = 0, i, olen;
struct sackblk sack;
+ int copyback = 0, i;
+ int olen, optsoff;
+ u_int8_t opts[MAX_TCPOPTLEN], *opt, *eoh;
+
+ olen = (pd->hdr.tcp.th_off << 2) - sizeof(struct tcphdr);
+ optsoff = pd->off + sizeof(struct tcphdr);
+#define TCPOLEN_MINSACK (TCPOLEN_SACK + 2)
+ if (olen < TCPOLEN_MINSACK ||
+ !pf_pull_hdr(pd->m, optsoff, opts, olen, NULL, NULL, pd->af))
+ return (0);
-#define TCPOLEN_SACKLEN (TCPOLEN_SACK + 2)
- if (hlen < TCPOLEN_SACKLEN || hlen > MAX_TCPOPTLEN || !pf_pull_hdr(
- pd->m, pd->off + sizeof(*th), opts, hlen, NULL, NULL, pd->af))
- return 0;
-
- while (hlen >= TCPOLEN_SACKLEN) {
- olen = opt[1];
- switch (*opt) {
- case TCPOPT_EOL: /* FALLTHROUGH */
- case TCPOPT_NOP:
- opt++;
- hlen--;
- break;
- case TCPOPT_SACK:
- if (olen > hlen)
- olen = hlen;
- if (olen >= TCPOLEN_SACKLEN) {
- for (i = 2; i + TCPOLEN_SACK <= olen;
- i += TCPOLEN_SACK) {
- size_t startoff = (opt + i) - opts;
- memcpy(&sack, &opt[i], sizeof(sack));
- pf_patch_32_unaligned(pd, &sack.start,
- htonl(ntohl(sack.start) -
- dst->seqdiff),
- PF_ALGNMNT(startoff));
- pf_patch_32_unaligned(pd, &sack.end,
- htonl(ntohl(sack.end) -
- dst->seqdiff),
- PF_ALGNMNT(startoff +
- sizeof(sack.start)));
- memcpy(&opt[i], &sack, sizeof(sack));
- }
- copyback = 1;
- }
- /* FALLTHROUGH */
- default:
- if (olen < 2)
- olen = 2;
- hlen -= olen;
- opt += olen;
+ eoh = opts + olen;
+ opt = opts;
+ while ((opt = pf_find_tcpopt(opt, opts, olen,
+ TCPOPT_SACK, TCPOLEN_MINSACK)) != NULL)
+ {
+ size_t safelen = MIN(opt[1], (eoh - opt));
+ for (i = 2; i + TCPOLEN_SACK <= safelen; i += TCPOLEN_SACK) {
+ size_t startoff = (opt + i) - opts;
+ memcpy(&sack, &opt[i], sizeof(sack));
+ pf_patch_32_unaligned(pd, &sack.start,
+ htonl(ntohl(sack.start) - dst->seqdiff),
+ PF_ALGNMNT(startoff));
+ pf_patch_32_unaligned(pd, &sack.end,
+ htonl(ntohl(sack.end) - dst->seqdiff),
+ PF_ALGNMNT(startoff + sizeof(sack.start)));
+ memcpy(&opt[i], &sack, sizeof(sack));
}
+ copyback = 1;
+ opt += opt[1];
}
if (copyback)
- m_copyback(pd->m, pd->off + sizeof(*th), thoptlen, opts,
- M_NOWAIT);
+ m_copyback(pd->m, optsoff, olen, opts, M_NOWAIT);
return (copyback);
}
@@ -3265,82 +3247,85 @@ pf_socket_lookup(struct pf_pdesc *pd)
return (1);
}
-u_int8_t
-pf_get_wscale(struct pf_pdesc *pd)
+/* post: r => (r[0] == type /\ r[1] >= min_typelen >= 2 "validity"
+ * /\ (eoh - r) >= min_typelen >= 2 "safety" )
+ *
+ * warning: r + r[1] may exceed opts bounds for r[1] > min_typelen
+ */
+u_int8_t*
+pf_find_tcpopt(u_int8_t *opt, u_int8_t *opts, size_t hlen, u_int8_t type,
+ u_int8_t min_typelen)
{
- struct tcphdr *th = &pd->hdr.tcp;
- int hlen;
- u_int8_t hdr[60];
- u_int8_t *opt, optlen;
- u_int8_t wscale = 0;
+ u_int8_t *eoh = opts + hlen;
- hlen = th->th_off << 2; /* hlen <= sizeof(hdr) */
- if (hlen <= sizeof(struct tcphdr))
- return (0);
- if (!pf_pull_hdr(pd->m, pd->off, hdr, hlen, NULL, NULL, pd->af))
- return (0);
- opt = hdr + sizeof(struct tcphdr);
- hlen -= sizeof(struct tcphdr);
- while (hlen >= 3) {
+ if (min_typelen < 2)
+ return (NULL);
+
+ while ((eoh - opt) >= min_typelen) {
switch (*opt) {
case TCPOPT_EOL:
+ /* FALLTHROUGH - Workaround the failure of some
+ systems to NOP-pad their bzero'd option buffers,
+ producing spurious EOLs */
case TCPOPT_NOP:
- ++opt;
- --hlen;
- break;
- case TCPOPT_WINDOW:
- wscale = opt[2];
- if (wscale > TCP_MAX_WINSHIFT)
- wscale = TCP_MAX_WINSHIFT;
- wscale |= PF_WSCALE_FLAG;
- /* FALLTHROUGH */
+ opt++;
+ continue;
default:
- optlen = opt[1];
- if (optlen < 2)
- optlen = 2;
- hlen -= optlen;
- opt += optlen;
- break;
+ if (opt[0] == type &&
+ opt[1] >= min_typelen)
+ return (opt);
}
+
+ opt += MAX(opt[1], 2); /* evade infinite loops */
}
+
+ return (NULL);
+}
+
+u_int8_t
+pf_get_wscale(struct pf_pdesc *pd)
+{
+ int olen;
+ u_int8_t opts[MAX_TCPOPTLEN], *opt;
+ u_int8_t wscale = 0;
+
+ olen = (pd->hdr.tcp.th_off << 2) - sizeof(struct tcphdr);
+ if (olen < TCPOLEN_WINDOW || !pf_pull_hdr(pd->m,
+ pd->off + sizeof(struct tcphdr), opts, olen, NULL, NULL, pd->af))
+ return (0);
+
+ opt = opts;
+ while ((opt = pf_find_tcpopt(opt, opts, olen,
+ TCPOPT_WINDOW, TCPOLEN_WINDOW)) != NULL) {
+ wscale = opt[2];
+ wscale = MIN(wscale, TCP_MAX_WINSHIFT);
+ wscale |= PF_WSCALE_FLAG;
+
+ opt += opt[1];
+ }
+
return (wscale);
}
u_int16_t
pf_get_mss(struct pf_pdesc *pd)
{
- struct tcphdr *th = &pd->hdr.tcp;
- int hlen;
- u_int8_t hdr[60];
- u_int8_t *opt, optlen;
+ int olen;
+ u_int8_t opts[MAX_TCPOPTLEN], *opt;
u_int16_t mss = tcp_mssdflt;
- hlen = th->th_off << 2; /* hlen <= sizeof(hdr) */
- if (hlen <= sizeof(struct tcphdr))
+ olen = (pd->hdr.tcp.th_off << 2) - sizeof(struct tcphdr);
+ if (olen < TCPOLEN_MAXSEG || !pf_pull_hdr(pd->m,
+ pd->off + sizeof(struct tcphdr), opts, olen, NULL, NULL, pd->af))
return (0);
- if (!pf_pull_hdr(pd->m, pd->off, hdr, hlen, NULL, NULL, pd->af))
- return (0);
- opt = hdr + sizeof(struct tcphdr);
- hlen -= sizeof(struct tcphdr);
- while (hlen >= TCPOLEN_MAXSEG) {
- switch (*opt) {
- case TCPOPT_EOL:
- case TCPOPT_NOP:
- ++opt;
- --hlen;
- break;
- case TCPOPT_MAXSEG:
+
+ opt = opts;
+ while ((opt = pf_find_tcpopt(opt, opts, olen,
+ TCPOPT_MAXSEG, TCPOLEN_MAXSEG)) != NULL) {
memcpy(&mss, (opt + 2), 2);
mss = ntohs(mss);
- /* FALLTHROUGH */
- default:
- optlen = opt[1];
- if (optlen < 2)
- optlen = 2;
- hlen -= optlen;
- opt += optlen;
- break;
- }
+
+ opt += opt[1];
}
return (mss);
}
diff --git a/sys/net/pf_norm.c b/sys/net/pf_norm.c
index f01e850d2c0..725489845e9 100644
--- a/sys/net/pf_norm.c
+++ b/sys/net/pf_norm.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf_norm.c,v 1.209 2018/02/06 09:16:11 henning Exp $ */
+/* $OpenBSD: pf_norm.c,v 1.210 2018/06/18 11:00:31 procter Exp $ */
/*
* Copyright 2001 Niels Provos <provos@citi.umich.edu>
@@ -1008,8 +1008,9 @@ pf_normalize_tcp_init(struct pf_pdesc *pd, struct pf_state_peer *src)
{
struct tcphdr *th = &pd->hdr.tcp;
u_int32_t tsval, tsecr;
- u_int8_t hdr[60];
- u_int8_t *opt;
+ int olen;
+ u_int8_t opts[MAX_TCPOPTLEN], *opt;
+
KASSERT(src->scrub == NULL);
@@ -1042,44 +1043,26 @@ pf_normalize_tcp_init(struct pf_pdesc *pd, struct pf_state_peer *src)
if ((th->th_flags & TH_SYN) == 0)
return (0);
- if (th->th_off > (sizeof(struct tcphdr) >> 2) && src->scrub &&
- pf_pull_hdr(pd->m, pd->off, hdr, th->th_off << 2, NULL, NULL,
- pd->af)) {
- /* Diddle with TCP options */
- int hlen;
-
- opt = hdr + sizeof(struct tcphdr);
- hlen = (th->th_off << 2) - sizeof(struct tcphdr);
- while (hlen >= TCPOLEN_TIMESTAMP) {
- switch (*opt) {
- case TCPOPT_EOL: /* FALLTHROUGH */
- case TCPOPT_NOP:
- opt++;
- hlen--;
- break;
- case TCPOPT_TIMESTAMP:
- if (opt[1] >= TCPOLEN_TIMESTAMP) {
- src->scrub->pfss_flags |=
- PFSS_TIMESTAMP;
- src->scrub->pfss_ts_mod = arc4random();
-
- /* note PFSS_PAWS not set yet */
- memcpy(&tsval, &opt[2],
- sizeof(u_int32_t));
- memcpy(&tsecr, &opt[6],
- sizeof(u_int32_t));
- src->scrub->pfss_tsval0 = ntohl(tsval);
- src->scrub->pfss_tsval = ntohl(tsval);
- src->scrub->pfss_tsecr = ntohl(tsecr);
- getmicrouptime(&src->scrub->pfss_last);
- }
- /* FALLTHROUGH */
- default:
- hlen -= MAX(opt[1], 2);
- opt += MAX(opt[1], 2);
- break;
- }
- }
+ olen = (th->th_off << 2) - sizeof(*th);
+ if (olen < TCPOLEN_TIMESTAMP || !pf_pull_hdr(pd->m,
+ pd->off + sizeof(*th), opts, olen, NULL, NULL, pd->af))
+ return (0);
+
+ opt = opts;
+ while ((opt = pf_find_tcpopt(opt, opts, olen,
+ TCPOPT_TIMESTAMP, TCPOLEN_TIMESTAMP)) != NULL) {
+
+ src->scrub->pfss_flags |= PFSS_TIMESTAMP;
+ src->scrub->pfss_ts_mod = arc4random();
+ /* note PFSS_PAWS not set yet */
+ memcpy(&tsval, &opt[2], sizeof(u_int32_t));
+ memcpy(&tsecr, &opt[6], sizeof(u_int32_t));
+ src->scrub->pfss_tsval0 = ntohl(tsval);
+ src->scrub->pfss_tsval = ntohl(tsval);
+ src->scrub->pfss_tsecr = ntohl(tsecr);
+ getmicrouptime(&src->scrub->pfss_last);
+
+ opt += opt[1];
}
return (0);
@@ -1103,12 +1086,12 @@ pf_normalize_tcp_stateful(struct pf_pdesc *pd, u_short *reason,
{
struct tcphdr *th = &pd->hdr.tcp;
struct timeval uptime;
- u_int32_t tsval, tsecr;
u_int tsval_from_last;
- u_int8_t hdr[60];
- u_int8_t *opts, *opt;
+ u_int32_t tsval, tsecr;
int copyback = 0;
int got_ts = 0;
+ int olen;
+ u_int8_t opts[MAX_TCPOPTLEN], *opt;
KASSERT(src->scrub || dst->scrub);
@@ -1140,87 +1123,68 @@ pf_normalize_tcp_stateful(struct pf_pdesc *pd, u_short *reason,
unhandled_af(pd->af);
}
- if (th->th_off > (sizeof(struct tcphdr) >> 2) &&
+ olen = (th->th_off << 2) - sizeof(*th);
+
+ if (olen >= TCPOLEN_TIMESTAMP &&
((src->scrub && (src->scrub->pfss_flags & PFSS_TIMESTAMP)) ||
(dst->scrub && (dst->scrub->pfss_flags & PFSS_TIMESTAMP))) &&
- pf_pull_hdr(pd->m, pd->off, hdr, th->th_off << 2, NULL, NULL,
+ pf_pull_hdr(pd->m, pd->off + sizeof(*th), opts, olen, NULL, NULL,
pd->af)) {
- /* Diddle with TCP options */
- int hlen;
- opt = opts = hdr + sizeof(struct tcphdr);
- hlen = (th->th_off << 2) - sizeof(struct tcphdr);
- while (hlen >= TCPOLEN_TIMESTAMP) {
- switch (*opt) {
- case TCPOPT_EOL: /* FALLTHROUGH */
- case TCPOPT_NOP:
- opt++;
- hlen--;
- break;
- case TCPOPT_TIMESTAMP:
- /* Modulate the timestamps. Can be used for
- * NAT detection, OS uptime determination or
- * reboot detection.
- */
-
- if (got_ts) {
- /* Huh? Multiple timestamps!? */
- if (pf_status.debug >= LOG_NOTICE) {
- log(LOG_NOTICE,
- "pf: %s: multiple TS??",
- __func__);
- pf_print_state(state);
- addlog("\n");
- }
- REASON_SET(reason, PFRES_TS);
- return (PF_DROP);
- }
- if (opt[1] >= TCPOLEN_TIMESTAMP) {
- u_int8_t *ts = opt + 2;
- u_int8_t *tsr = opt + 6;
-
- memcpy(&tsval, ts, sizeof(u_int32_t));
- memcpy(&tsecr, tsr, sizeof(u_int32_t));
-
- /* modulate TS */
- if (tsval && src->scrub &&
- (src->scrub->pfss_flags &
- PFSS_TIMESTAMP)) {
- /* tsval used further on */
- tsval = ntohl(tsval);
- pf_patch_32_unaligned(pd, ts,
- htonl(tsval +
- src->scrub->pfss_ts_mod),
- PF_ALGNMNT(ts - opts));
- copyback = 1;
- }
-
- /* modulate TS reply if any (!0) */
- if (tsecr && dst->scrub &&
- (dst->scrub->pfss_flags &
- PFSS_TIMESTAMP)) {
- /* tsecr used further on */
- tsecr = ntohl(tsecr)
- - dst->scrub->pfss_ts_mod;
- pf_patch_32_unaligned(pd, tsr,
- htonl(tsecr),
- PF_ALGNMNT(tsr - opts));
- copyback = 1;
- }
- got_ts = 1;
+
+ /* Modulate the timestamps. Can be used for NAT detection, OS
+ * uptime determination or reboot detection.
+ */
+ opt = opts;
+ while ((opt = pf_find_tcpopt(opt, opts, olen,
+ TCPOPT_TIMESTAMP, TCPOLEN_TIMESTAMP)) != NULL) {
+
+ u_int8_t *ts = opt + 2;
+ u_int8_t *tsr = opt + 6;
+
+ if (got_ts) {
+ /* Huh? Multiple timestamps!? */
+ if (pf_status.debug >= LOG_NOTICE) {
+ log(LOG_NOTICE,
+ "pf: %s: multiple TS??", __func__);
+ pf_print_state(state);
+ addlog("\n");
}
- /* FALLTHROUGH */
- default:
- hlen -= MAX(opt[1], 2);
- opt += MAX(opt[1], 2);
- break;
+ REASON_SET(reason, PFRES_TS);
+ return (PF_DROP);
}
+
+ memcpy(&tsval, ts, sizeof(u_int32_t));
+ memcpy(&tsecr, tsr, sizeof(u_int32_t));
+
+ /* modulate TS */
+ if (tsval && src->scrub &&
+ (src->scrub->pfss_flags & PFSS_TIMESTAMP)) {
+ /* tsval used further on */
+ tsval = ntohl(tsval);
+ pf_patch_32_unaligned(pd,
+ ts, htonl(tsval + src->scrub->pfss_ts_mod),
+ PF_ALGNMNT(ts - opts));
+ copyback = 1;
+ }
+
+ /* modulate TS reply if any (!0) */
+ if (tsecr && dst->scrub &&
+ (dst->scrub->pfss_flags & PFSS_TIMESTAMP)) {
+ /* tsecr used further on */
+ tsecr = ntohl(tsecr) - dst->scrub->pfss_ts_mod;
+ pf_patch_32_unaligned(pd,
+ tsr, htonl(tsecr), PF_ALGNMNT(tsr - opts));
+ copyback = 1;
+ }
+
+ got_ts = 1;
+ opt += opt[1];
}
+
if (copyback) {
/* Copyback the options, caller copys back header */
*writeback = 1;
- m_copyback(pd->m, pd->off + sizeof(struct tcphdr),
- (th->th_off << 2) - sizeof(struct tcphdr), hdr +
- sizeof(struct tcphdr), M_NOWAIT);
+ m_copyback(pd->m, pd->off + sizeof(*th), olen, opts, M_NOWAIT);
}
}
@@ -1492,47 +1456,32 @@ pf_normalize_tcp_stateful(struct pf_pdesc *pd, u_short *reason,
int
pf_normalize_mss(struct pf_pdesc *pd, u_int16_t maxmss)
{
- struct tcphdr *th = &pd->hdr.tcp;
- u_int16_t mss;
- int thoff;
- int opt, cnt, optlen = 0;
- u_int8_t opts[MAX_TCPOPTLEN];
- u_int8_t *optp = opts;
-
- thoff = th->th_off << 2;
- cnt = thoff - sizeof(struct tcphdr);
+ int olen, optsoff;
+ u_int8_t opts[MAX_TCPOPTLEN], *opt;
- if (cnt <= 0 || cnt > MAX_TCPOPTLEN || !pf_pull_hdr(pd->m,
- pd->off + sizeof(*th), opts, cnt, NULL, NULL, pd->af))
+ olen = (pd->hdr.tcp.th_off << 2) - sizeof(struct tcphdr);
+ optsoff = pd->off + sizeof(struct tcphdr);
+ if (olen < TCPOLEN_MAXSEG ||
+ !pf_pull_hdr(pd->m, optsoff, opts, olen, NULL, NULL, pd->af))
return (0);
- for (; cnt > 0; cnt -= optlen, optp += optlen) {
- opt = optp[0];
- if (opt == TCPOPT_EOL)
- break;
- if (opt == TCPOPT_NOP)
- optlen = 1;
- else {
- if (cnt < 2)
- break;
- optlen = optp[1];
- if (optlen < 2 || optlen > cnt)
- break;
- }
- if (opt == TCPOPT_MAXSEG) {
- u_int8_t *mssp = optp + 2;
- memcpy(&mss, mssp, sizeof(mss));
- if (ntohs(mss) > maxmss) {
- size_t mssoffopts = mssp - opts;
- pf_patch_16_unaligned(pd, &mss,
- htons(maxmss), PF_ALGNMNT(mssoffopts));
- m_copyback(pd->m,
- pd->off + sizeof(*th) + mssoffopts,
- sizeof(mss), &mss, M_NOWAIT);
- m_copyback(pd->m, pd->off, sizeof(*th), th,
- M_NOWAIT);
- }
+ opt = opts;
+ while ((opt = pf_find_tcpopt(opt, opts, olen,
+ TCPOPT_MAXSEG, TCPOLEN_MAXSEG)) != NULL) {
+ u_int16_t mss;
+ u_int8_t *mssp = opt + 2;
+ memcpy(&mss, mssp, sizeof(mss));
+ if (ntohs(mss) > maxmss) {
+ size_t mssoffopts = mssp - opts;
+ pf_patch_16_unaligned(pd, &mss,
+ htons(maxmss), PF_ALGNMNT(mssoffopts));
+ m_copyback(pd->m, optsoff + mssoffopts,
+ sizeof(mss), &mss, M_NOWAIT);
+ m_copyback(pd->m, pd->off,
+ sizeof(struct tcphdr), &pd->hdr.tcp, M_NOWAIT);
}
+
+ opt += opt[1];
}
return (0);
diff --git a/sys/net/pf_syncookies.c b/sys/net/pf_syncookies.c
index 63d15f12bc2..bc73aae7bac 100644
--- a/sys/net/pf_syncookies.c
+++ b/sys/net/pf_syncookies.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf_syncookies.c,v 1.5 2018/02/08 09:15:46 henning Exp $ */
+/* $OpenBSD: pf_syncookies.c,v 1.6 2018/06/18 11:00:31 procter Exp $ */
/* Copyright (c) 2016,2017 Henning Brauer <henning@openbsd.org>
* Copyright (c) 2016 Alexandr Nedvedicky <sashan@openbsd.org>
@@ -385,39 +385,3 @@ pf_syncookie_recreate_syn(struct pf_pdesc *pd)
*pd->dport, seq, 0, TH_SYN, wscale, mss, pd->ttl, 0,
PF_TAG_SYNCOOKIE_RECREATED, cookie.flags.sack_ok, pd->rdomain));
}
-
-#define PF_TCPOPTLEN_SACKPERMITTED 2
-
-int
-pf_check_sack(struct pf_pdesc *pd)
-{
- struct tcphdr *th = &pd->hdr.tcp;
- int hlen = (th->th_off << 2) - sizeof(*th);
- uint8_t opts[MAX_TCPOPTLEN], *opt = opts;
- int olen;
-
- if (hlen < PF_TCPOPTLEN_SACKPERMITTED || hlen > MAX_TCPOPTLEN ||
- !pf_pull_hdr(pd->m, pd->off + sizeof(*th), opts, hlen, NULL, NULL,
- pd->af))
- return (0);
-
- while (hlen >= PF_TCPOPTLEN_SACKPERMITTED) {
- olen = opt[1];
- switch (*opt) {
- case TCPOPT_EOL: /* FALLTHROUGH */
- case TCPOPT_NOP:
- opt++;
- hlen--;
- break;
- case TCPOPT_SACK_PERMITTED:
- return (1);
- default:
- if (olen < 2)
- olen = 2;
- hlen -= olen;
- opt += olen;
- }
- }
-
- return (0);
-}
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index dc7d7adf767..58b28583e1b 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfvar.h,v 1.477 2018/04/05 03:32:39 lteo Exp $ */
+/* $OpenBSD: pfvar.h,v 1.478 2018/06/18 11:00:31 procter Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -1934,6 +1934,8 @@ void pf_mbuf_link_state_key(struct mbuf *,
struct pf_state_key *);
void pf_mbuf_unlink_state_key(struct mbuf *);
+u_int8_t* pf_find_tcpopt(u_int8_t *, u_int8_t *, size_t,
+ u_int8_t, u_int8_t);
u_int8_t pf_get_wscale(struct pf_pdesc *);
u_int16_t pf_get_mss(struct pf_pdesc *);
struct mbuf * pf_build_tcp(const struct pf_rule *, sa_family_t,