diff options
author | 2018-06-18 11:00:31 +0000 | |
---|---|---|
committer | 2018-06-18 11:00:31 +0000 | |
commit | 672fea2ccb3e4cbe11883d167309a4904628e2e2 (patch) | |
tree | a9c544d37a53aaec677522ae61bd3664eb4b20e5 | |
parent | fix memory leak: freeaddrinfo() the data from getaddrinfo(). (diff) | |
download | wireguard-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.c | 197 | ||||
-rw-r--r-- | sys/net/pf_norm.c | 255 | ||||
-rw-r--r-- | sys/net/pf_syncookies.c | 38 | ||||
-rw-r--r-- | sys/net/pfvar.h | 4 |
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, |