]>
git.saurik.com Git - apple/xnu.git/blob - bsd/net/pf_norm.c
053cdc13c3aafdb977e1b8d7ac8300b8a6ff3607
2 * Copyright (c) 2007-2008 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 /* $apfw: pf_norm.c,v 1.10 2008/08/28 19:10:53 jhw Exp $ */
30 /* $OpenBSD: pf_norm.c,v 1.107 2006/04/16 00:59:52 pascoe Exp $ */
33 * Copyright 2001 Niels Provos <provos@citi.umich.edu>
34 * All rights reserved.
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in the
43 * documentation and/or other materials provided with the distribution.
45 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
46 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
47 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
48 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
49 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
50 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
51 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
52 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
53 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
54 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
57 #include <sys/param.h>
58 #include <sys/systm.h>
60 #include <sys/filio.h>
61 #include <sys/fcntl.h>
62 #include <sys/socket.h>
63 #include <sys/kernel.h>
65 #include <sys/random.h>
66 #include <sys/mcache.h>
69 #include <net/if_types.h>
71 #include <net/route.h>
72 #include <net/if_pflog.h>
74 #include <netinet/in.h>
75 #include <netinet/in_var.h>
76 #include <netinet/in_systm.h>
77 #include <netinet/ip.h>
78 #include <netinet/ip_var.h>
79 #include <netinet/tcp.h>
80 #include <netinet/tcp_seq.h>
81 #include <netinet/tcp_fsm.h>
82 #include <netinet/udp.h>
83 #include <netinet/ip_icmp.h>
86 #include <netinet/ip6.h>
89 #include <net/pfvar.h>
92 LIST_ENTRY(pf_frent
) fr_next
;
98 LIST_ENTRY(pf_frcache
) fr_next
;
103 #define PFFRAG_SEENLAST 0x0001 /* Seen the last fragment for this */
104 #define PFFRAG_NOBUFFER 0x0002 /* Non-buffering fragment cache */
105 #define PFFRAG_DROP 0x0004 /* Drop all fragments */
106 #define BUFFER_FRAGMENTS(fr) (!((fr)->fr_flags & PFFRAG_NOBUFFER))
109 RB_ENTRY(pf_fragment
) fr_entry
;
110 TAILQ_ENTRY(pf_fragment
) frag_next
;
111 struct in_addr fr_src
;
112 struct in_addr fr_dst
;
113 u_int8_t fr_p
; /* protocol of this fragment */
114 u_int8_t fr_flags
; /* status flags */
115 u_int16_t fr_id
; /* fragment id for reassemble */
116 u_int16_t fr_max
; /* fragment data max */
117 u_int32_t fr_timeout
;
118 #define fr_queue fr_u.fru_queue
119 #define fr_cache fr_u.fru_cache
121 LIST_HEAD(pf_fragq
, pf_frent
) fru_queue
; /* buffering */
122 LIST_HEAD(pf_cacheq
, pf_frcache
) fru_cache
; /* non-buf */
126 static TAILQ_HEAD(pf_fragqueue
, pf_fragment
) pf_fragqueue
;
127 static TAILQ_HEAD(pf_cachequeue
, pf_fragment
) pf_cachequeue
;
129 static __inline
int pf_frag_compare(struct pf_fragment
*,
130 struct pf_fragment
*);
131 static RB_HEAD(pf_frag_tree
, pf_fragment
) pf_frag_tree
, pf_cache_tree
;
132 RB_PROTOTYPE_SC(__private_extern__
, pf_frag_tree
, pf_fragment
, fr_entry
,
134 RB_GENERATE(pf_frag_tree
, pf_fragment
, fr_entry
, pf_frag_compare
);
136 /* Private prototypes */
137 static void pf_ip2key(struct pf_fragment
*, struct ip
*);
138 static void pf_remove_fragment(struct pf_fragment
*);
139 static void pf_flush_fragments(void);
140 static void pf_free_fragment(struct pf_fragment
*);
141 static struct pf_fragment
*pf_find_fragment(struct ip
*, struct pf_frag_tree
*);
142 static struct mbuf
*pf_reassemble(struct mbuf
**, struct pf_fragment
**,
143 struct pf_frent
*, int);
144 static struct mbuf
*pf_fragcache(struct mbuf
**, struct ip
*,
145 struct pf_fragment
**, int, int, int *);
146 #ifndef NO_APPLE_MODIFICATIONS
147 static int pf_normalize_tcpopt(struct pf_rule
*, int, struct pfi_kif
*,
148 struct pf_pdesc
*, struct mbuf
*, struct tcphdr
*, int, int *);
150 static int pf_normalize_tcpopt(struct pf_rule
*, struct mbuf
*,
151 struct tcphdr
*, int, sa_family_t
);
154 #define DPFPRINTF(x) do { \
155 if (pf_status.debug >= PF_DEBUG_MISC) { \
156 printf("%s: ", __func__); \
162 struct pool pf_frent_pl
, pf_frag_pl
;
163 static struct pool pf_cache_pl
, pf_cent_pl
;
164 struct pool pf_state_scrub_pl
;
166 static int pf_nfrents
, pf_ncache
;
169 pf_normalize_init(void)
171 pool_init(&pf_frent_pl
, sizeof (struct pf_frent
), 0, 0, 0, "pffrent",
173 pool_init(&pf_frag_pl
, sizeof (struct pf_fragment
), 0, 0, 0, "pffrag",
175 pool_init(&pf_cache_pl
, sizeof (struct pf_fragment
), 0, 0, 0,
177 pool_init(&pf_cent_pl
, sizeof (struct pf_frcache
), 0, 0, 0, "pffrcent",
179 pool_init(&pf_state_scrub_pl
, sizeof (struct pf_state_scrub
), 0, 0, 0,
182 pool_sethiwat(&pf_frag_pl
, PFFRAG_FRAG_HIWAT
);
183 pool_sethardlimit(&pf_frent_pl
, PFFRAG_FRENT_HIWAT
, NULL
, 0);
184 pool_sethardlimit(&pf_cache_pl
, PFFRAG_FRCACHE_HIWAT
, NULL
, 0);
185 pool_sethardlimit(&pf_cent_pl
, PFFRAG_FRCENT_HIWAT
, NULL
, 0);
187 TAILQ_INIT(&pf_fragqueue
);
188 TAILQ_INIT(&pf_cachequeue
);
193 pf_normalize_destroy(void)
195 pool_destroy(&pf_state_scrub_pl
);
196 pool_destroy(&pf_cent_pl
);
197 pool_destroy(&pf_cache_pl
);
198 pool_destroy(&pf_frag_pl
);
199 pool_destroy(&pf_frent_pl
);
204 pf_normalize_isempty(void)
206 return (TAILQ_EMPTY(&pf_fragqueue
) && TAILQ_EMPTY(&pf_cachequeue
));
210 pf_frag_compare(struct pf_fragment
*a
, struct pf_fragment
*b
)
214 if ((diff
= a
->fr_id
- b
->fr_id
))
216 else if ((diff
= a
->fr_p
- b
->fr_p
))
218 else if (a
->fr_src
.s_addr
< b
->fr_src
.s_addr
)
220 else if (a
->fr_src
.s_addr
> b
->fr_src
.s_addr
)
222 else if (a
->fr_dst
.s_addr
< b
->fr_dst
.s_addr
)
224 else if (a
->fr_dst
.s_addr
> b
->fr_dst
.s_addr
)
230 pf_purge_expired_fragments(void)
232 struct pf_fragment
*frag
;
233 u_int32_t expire
= pf_time_second() -
234 pf_default_rule
.timeout
[PFTM_FRAG
];
236 while ((frag
= TAILQ_LAST(&pf_fragqueue
, pf_fragqueue
)) != NULL
) {
237 VERIFY(BUFFER_FRAGMENTS(frag
));
238 if (frag
->fr_timeout
> expire
)
241 DPFPRINTF(("expiring %d(%p)\n", frag
->fr_id
, frag
));
242 pf_free_fragment(frag
);
245 while ((frag
= TAILQ_LAST(&pf_cachequeue
, pf_cachequeue
)) != NULL
) {
246 VERIFY(!BUFFER_FRAGMENTS(frag
));
247 if (frag
->fr_timeout
> expire
)
250 DPFPRINTF(("expiring %d(%p)\n", frag
->fr_id
, frag
));
251 pf_free_fragment(frag
);
252 VERIFY(TAILQ_EMPTY(&pf_cachequeue
) ||
253 TAILQ_LAST(&pf_cachequeue
, pf_cachequeue
) != frag
);
258 * Try to flush old fragments to make space for new ones
262 pf_flush_fragments(void)
264 struct pf_fragment
*frag
;
267 goal
= pf_nfrents
* 9 / 10;
268 DPFPRINTF(("trying to free > %d frents\n",
270 while (goal
< pf_nfrents
) {
271 frag
= TAILQ_LAST(&pf_fragqueue
, pf_fragqueue
);
274 pf_free_fragment(frag
);
278 goal
= pf_ncache
* 9 / 10;
279 DPFPRINTF(("trying to free > %d cache entries\n",
281 while (goal
< pf_ncache
) {
282 frag
= TAILQ_LAST(&pf_cachequeue
, pf_cachequeue
);
285 pf_free_fragment(frag
);
289 /* Frees the fragments and all associated entries */
292 pf_free_fragment(struct pf_fragment
*frag
)
294 struct pf_frent
*frent
;
295 struct pf_frcache
*frcache
;
297 /* Free all fragments */
298 if (BUFFER_FRAGMENTS(frag
)) {
299 for (frent
= LIST_FIRST(&frag
->fr_queue
); frent
;
300 frent
= LIST_FIRST(&frag
->fr_queue
)) {
301 LIST_REMOVE(frent
, fr_next
);
303 m_freem(frent
->fr_m
);
304 pool_put(&pf_frent_pl
, frent
);
308 for (frcache
= LIST_FIRST(&frag
->fr_cache
); frcache
;
309 frcache
= LIST_FIRST(&frag
->fr_cache
)) {
310 LIST_REMOVE(frcache
, fr_next
);
312 VERIFY(LIST_EMPTY(&frag
->fr_cache
) ||
313 LIST_FIRST(&frag
->fr_cache
)->fr_off
>
316 pool_put(&pf_cent_pl
, frcache
);
321 pf_remove_fragment(frag
);
325 pf_ip2key(struct pf_fragment
*key
, struct ip
*ip
)
327 key
->fr_p
= ip
->ip_p
;
328 key
->fr_id
= ip
->ip_id
;
329 key
->fr_src
.s_addr
= ip
->ip_src
.s_addr
;
330 key
->fr_dst
.s_addr
= ip
->ip_dst
.s_addr
;
333 static struct pf_fragment
*
334 pf_find_fragment(struct ip
*ip
, struct pf_frag_tree
*tree
)
336 struct pf_fragment key
;
337 struct pf_fragment
*frag
;
341 frag
= RB_FIND(pf_frag_tree
, tree
, &key
);
343 /* XXX Are we sure we want to update the timeout? */
344 frag
->fr_timeout
= pf_time_second();
345 if (BUFFER_FRAGMENTS(frag
)) {
346 TAILQ_REMOVE(&pf_fragqueue
, frag
, frag_next
);
347 TAILQ_INSERT_HEAD(&pf_fragqueue
, frag
, frag_next
);
349 TAILQ_REMOVE(&pf_cachequeue
, frag
, frag_next
);
350 TAILQ_INSERT_HEAD(&pf_cachequeue
, frag
, frag_next
);
357 /* Removes a fragment from the fragment queue and frees the fragment */
360 pf_remove_fragment(struct pf_fragment
*frag
)
362 if (BUFFER_FRAGMENTS(frag
)) {
363 RB_REMOVE(pf_frag_tree
, &pf_frag_tree
, frag
);
364 TAILQ_REMOVE(&pf_fragqueue
, frag
, frag_next
);
365 pool_put(&pf_frag_pl
, frag
);
367 RB_REMOVE(pf_frag_tree
, &pf_cache_tree
, frag
);
368 TAILQ_REMOVE(&pf_cachequeue
, frag
, frag_next
);
369 pool_put(&pf_cache_pl
, frag
);
373 #define FR_IP_OFF(fr) ((ntohs((fr)->fr_ip->ip_off) & IP_OFFMASK) << 3)
375 pf_reassemble(struct mbuf
**m0
, struct pf_fragment
**frag
,
376 struct pf_frent
*frent
, int mff
)
378 struct mbuf
*m
= *m0
, *m2
;
379 struct pf_frent
*frea
, *next
;
380 struct pf_frent
*frep
= NULL
;
381 struct ip
*ip
= frent
->fr_ip
;
382 int hlen
= ip
->ip_hl
<< 2;
383 u_int16_t off
= (ntohs(ip
->ip_off
) & IP_OFFMASK
) << 3;
384 u_int16_t ip_len
= ntohs(ip
->ip_len
) - ip
->ip_hl
* 4;
385 u_int16_t fr_max
= ip_len
+ off
;
387 VERIFY(*frag
== NULL
|| BUFFER_FRAGMENTS(*frag
));
389 /* Strip off ip header */
393 /* Create a new reassembly queue for this packet */
395 *frag
= pool_get(&pf_frag_pl
, PR_NOWAIT
);
397 pf_flush_fragments();
398 *frag
= pool_get(&pf_frag_pl
, PR_NOWAIT
);
403 (*frag
)->fr_flags
= 0;
405 (*frag
)->fr_src
= frent
->fr_ip
->ip_src
;
406 (*frag
)->fr_dst
= frent
->fr_ip
->ip_dst
;
407 (*frag
)->fr_p
= frent
->fr_ip
->ip_p
;
408 (*frag
)->fr_id
= frent
->fr_ip
->ip_id
;
409 (*frag
)->fr_timeout
= pf_time_second();
410 LIST_INIT(&(*frag
)->fr_queue
);
412 RB_INSERT(pf_frag_tree
, &pf_frag_tree
, *frag
);
413 TAILQ_INSERT_HEAD(&pf_fragqueue
, *frag
, frag_next
);
415 /* We do not have a previous fragment */
421 * Find a fragment after the current one:
422 * - off contains the real shifted offset.
424 LIST_FOREACH(frea
, &(*frag
)->fr_queue
, fr_next
) {
425 if (FR_IP_OFF(frea
) > off
)
430 VERIFY(frep
!= NULL
|| frea
!= NULL
);
433 FR_IP_OFF(frep
) + ntohs(frep
->fr_ip
->ip_len
) - frep
->fr_ip
->ip_hl
*
437 precut
= FR_IP_OFF(frep
) + ntohs(frep
->fr_ip
->ip_len
) -
438 frep
->fr_ip
->ip_hl
* 4 - off
;
439 if (precut
>= ip_len
)
441 m_adj(frent
->fr_m
, precut
);
442 DPFPRINTF(("overlap -%d\n", precut
));
443 /* Enforce 8 byte boundaries */
444 ip
->ip_off
= htons(ntohs(ip
->ip_off
) + (precut
>> 3));
445 off
= (ntohs(ip
->ip_off
) & IP_OFFMASK
) << 3;
447 ip
->ip_len
= htons(ip_len
);
450 for (; frea
!= NULL
&& ip_len
+ off
> FR_IP_OFF(frea
);
454 aftercut
= ip_len
+ off
- FR_IP_OFF(frea
);
455 DPFPRINTF(("adjust overlap %d\n", aftercut
));
456 if (aftercut
< ntohs(frea
->fr_ip
->ip_len
) - frea
->fr_ip
->ip_hl
458 frea
->fr_ip
->ip_len
=
459 htons(ntohs(frea
->fr_ip
->ip_len
) - aftercut
);
460 frea
->fr_ip
->ip_off
= htons(ntohs(frea
->fr_ip
->ip_off
) +
462 m_adj(frea
->fr_m
, aftercut
);
466 /* This fragment is completely overlapped, lose it */
467 next
= LIST_NEXT(frea
, fr_next
);
469 LIST_REMOVE(frea
, fr_next
);
470 pool_put(&pf_frent_pl
, frea
);
475 /* Update maximum data size */
476 if ((*frag
)->fr_max
< fr_max
)
477 (*frag
)->fr_max
= fr_max
;
478 /* This is the last segment */
480 (*frag
)->fr_flags
|= PFFRAG_SEENLAST
;
483 LIST_INSERT_HEAD(&(*frag
)->fr_queue
, frent
, fr_next
);
485 LIST_INSERT_AFTER(frep
, frent
, fr_next
);
487 /* Check if we are completely reassembled */
488 if (!((*frag
)->fr_flags
& PFFRAG_SEENLAST
))
491 /* Check if we have all the data */
493 for (frep
= LIST_FIRST(&(*frag
)->fr_queue
); frep
; frep
= next
) {
494 next
= LIST_NEXT(frep
, fr_next
);
496 off
+= ntohs(frep
->fr_ip
->ip_len
) - frep
->fr_ip
->ip_hl
* 4;
497 if (off
< (*frag
)->fr_max
&&
498 (next
== NULL
|| FR_IP_OFF(next
) != off
)) {
499 DPFPRINTF(("missing fragment at %d, next %d, max %d\n",
500 off
, next
== NULL
? -1 : FR_IP_OFF(next
),
505 DPFPRINTF(("%d < %d?\n", off
, (*frag
)->fr_max
));
506 if (off
< (*frag
)->fr_max
)
509 /* We have all the data */
510 frent
= LIST_FIRST(&(*frag
)->fr_queue
);
511 VERIFY(frent
!= NULL
);
512 if ((frent
->fr_ip
->ip_hl
<< 2) + off
> IP_MAXPACKET
) {
513 DPFPRINTF(("drop: too big: %d\n", off
));
514 pf_free_fragment(*frag
);
518 next
= LIST_NEXT(frent
, fr_next
);
520 /* Magic from ip_input */
526 pool_put(&pf_frent_pl
, frent
);
528 for (frent
= next
; frent
!= NULL
; frent
= next
) {
529 next
= LIST_NEXT(frent
, fr_next
);
532 pool_put(&pf_frent_pl
, frent
);
537 ip
->ip_src
= (*frag
)->fr_src
;
538 ip
->ip_dst
= (*frag
)->fr_dst
;
540 /* Remove from fragment queue */
541 pf_remove_fragment(*frag
);
544 hlen
= ip
->ip_hl
<< 2;
545 ip
->ip_len
= htons(off
+ hlen
);
549 /* some debugging cruft by sklower, below, will go away soon */
550 /* XXX this should be done elsewhere */
551 if (m
->m_flags
& M_PKTHDR
) {
553 for (m2
= m
; m2
; m2
= m2
->m_next
)
555 m
->m_pkthdr
.len
= plen
;
558 DPFPRINTF(("complete: %p(%d)\n", m
, ntohs(ip
->ip_len
)));
562 /* Oops - fail safe - drop packet */
563 pool_put(&pf_frent_pl
, frent
);
570 pf_fragcache(struct mbuf
**m0
, struct ip
*h
, struct pf_fragment
**frag
, int mff
,
571 int drop
, int *nomem
)
573 struct mbuf
*m
= *m0
;
574 struct pf_frcache
*frp
, *fra
, *cur
= NULL
;
575 int ip_len
= ntohs(h
->ip_len
) - (h
->ip_hl
<< 2);
576 u_int16_t off
= ntohs(h
->ip_off
) << 3;
577 u_int16_t fr_max
= ip_len
+ off
;
580 VERIFY(*frag
== NULL
|| !BUFFER_FRAGMENTS(*frag
));
582 /* Create a new range queue for this packet */
584 *frag
= pool_get(&pf_cache_pl
, PR_NOWAIT
);
586 pf_flush_fragments();
587 *frag
= pool_get(&pf_cache_pl
, PR_NOWAIT
);
592 /* Get an entry for the queue */
593 cur
= pool_get(&pf_cent_pl
, PR_NOWAIT
);
595 pool_put(&pf_cache_pl
, *frag
);
601 (*frag
)->fr_flags
= PFFRAG_NOBUFFER
;
603 (*frag
)->fr_src
= h
->ip_src
;
604 (*frag
)->fr_dst
= h
->ip_dst
;
605 (*frag
)->fr_p
= h
->ip_p
;
606 (*frag
)->fr_id
= h
->ip_id
;
607 (*frag
)->fr_timeout
= pf_time_second();
610 cur
->fr_end
= fr_max
;
611 LIST_INIT(&(*frag
)->fr_cache
);
612 LIST_INSERT_HEAD(&(*frag
)->fr_cache
, cur
, fr_next
);
614 RB_INSERT(pf_frag_tree
, &pf_cache_tree
, *frag
);
615 TAILQ_INSERT_HEAD(&pf_cachequeue
, *frag
, frag_next
);
617 DPFPRINTF(("fragcache[%d]: new %d-%d\n", h
->ip_id
, off
,
624 * Find a fragment after the current one:
625 * - off contains the real shifted offset.
628 LIST_FOREACH(fra
, &(*frag
)->fr_cache
, fr_next
) {
629 if (fra
->fr_off
> off
)
634 VERIFY(frp
!= NULL
|| fra
!= NULL
);
639 precut
= frp
->fr_end
- off
;
640 if (precut
>= ip_len
) {
641 /* Fragment is entirely a duplicate */
642 DPFPRINTF(("fragcache[%d]: dead (%d-%d) %d-%d\n",
643 h
->ip_id
, frp
->fr_off
, frp
->fr_end
, off
, fr_max
));
647 /* They are adjacent. Fixup cache entry */
648 DPFPRINTF(("fragcache[%d]: adjacent (%d-%d) %d-%d\n",
649 h
->ip_id
, frp
->fr_off
, frp
->fr_end
, off
, fr_max
));
650 frp
->fr_end
= fr_max
;
651 } else if (precut
> 0) {
653 * The first part of this payload overlaps with a
654 * fragment that has already been passed.
655 * Need to trim off the first part of the payload.
656 * But to do so easily, we need to create another
657 * mbuf to throw the original header into.
660 DPFPRINTF(("fragcache[%d]: chop %d (%d-%d) %d-%d\n",
661 h
->ip_id
, precut
, frp
->fr_off
, frp
->fr_end
, off
,
666 /* Update the previous frag to encompass this one */
667 frp
->fr_end
= fr_max
;
671 * XXX Optimization opportunity
672 * This is a very heavy way to trim the payload.
673 * we could do it much faster by diddling mbuf
674 * internals but that would be even less legible
675 * than this mbuf magic. For my next trick,
676 * I'll pull a rabbit out of my laptop.
678 *m0
= m_copym(m
, 0, h
->ip_hl
<< 2, M_NOWAIT
);
681 VERIFY((*m0
)->m_next
== NULL
);
682 m_adj(m
, precut
+ (h
->ip_hl
<< 2));
685 if (m
->m_flags
& M_PKTHDR
) {
688 for (t
= m
; t
; t
= t
->m_next
)
690 m
->m_pkthdr
.len
= plen
;
694 h
= mtod(m
, struct ip
*);
697 VERIFY((int)m
->m_len
==
698 ntohs(h
->ip_len
) - precut
);
699 h
->ip_off
= htons(ntohs(h
->ip_off
) +
701 h
->ip_len
= htons(ntohs(h
->ip_len
) - precut
);
706 /* There is a gap between fragments */
708 DPFPRINTF(("fragcache[%d]: gap %d (%d-%d) %d-%d\n",
709 h
->ip_id
, -precut
, frp
->fr_off
, frp
->fr_end
, off
,
712 cur
= pool_get(&pf_cent_pl
, PR_NOWAIT
);
718 cur
->fr_end
= fr_max
;
719 LIST_INSERT_AFTER(frp
, cur
, fr_next
);
727 aftercut
= fr_max
- fra
->fr_off
;
729 /* Adjacent fragments */
730 DPFPRINTF(("fragcache[%d]: adjacent %d-%d (%d-%d)\n",
731 h
->ip_id
, off
, fr_max
, fra
->fr_off
, fra
->fr_end
));
734 } else if (aftercut
> 0) {
735 /* Need to chop off the tail of this fragment */
736 DPFPRINTF(("fragcache[%d]: chop %d %d-%d (%d-%d)\n",
737 h
->ip_id
, aftercut
, off
, fr_max
, fra
->fr_off
,
746 if (m
->m_flags
& M_PKTHDR
) {
749 for (t
= m
; t
; t
= t
->m_next
)
751 m
->m_pkthdr
.len
= plen
;
753 h
= mtod(m
, struct ip
*);
754 VERIFY((int)m
->m_len
==
755 ntohs(h
->ip_len
) - aftercut
);
756 h
->ip_len
= htons(ntohs(h
->ip_len
) - aftercut
);
760 } else if (frp
== NULL
) {
761 /* There is a gap between fragments */
762 DPFPRINTF(("fragcache[%d]: gap %d %d-%d (%d-%d)\n",
763 h
->ip_id
, -aftercut
, off
, fr_max
, fra
->fr_off
,
766 cur
= pool_get(&pf_cent_pl
, PR_NOWAIT
);
772 cur
->fr_end
= fr_max
;
773 LIST_INSERT_BEFORE(fra
, cur
, fr_next
);
777 /* Need to glue together two separate fragment descriptors */
779 if (cur
&& fra
->fr_off
<= cur
->fr_end
) {
780 /* Need to merge in a previous 'cur' */
781 DPFPRINTF(("fragcache[%d]: adjacent(merge "
782 "%d-%d) %d-%d (%d-%d)\n",
783 h
->ip_id
, cur
->fr_off
, cur
->fr_end
, off
,
784 fr_max
, fra
->fr_off
, fra
->fr_end
));
785 fra
->fr_off
= cur
->fr_off
;
786 LIST_REMOVE(cur
, fr_next
);
787 pool_put(&pf_cent_pl
, cur
);
791 } else if (frp
&& fra
->fr_off
<= frp
->fr_end
) {
792 /* Need to merge in a modified 'frp' */
794 DPFPRINTF(("fragcache[%d]: adjacent(merge "
795 "%d-%d) %d-%d (%d-%d)\n",
796 h
->ip_id
, frp
->fr_off
, frp
->fr_end
, off
,
797 fr_max
, fra
->fr_off
, fra
->fr_end
));
798 fra
->fr_off
= frp
->fr_off
;
799 LIST_REMOVE(frp
, fr_next
);
800 pool_put(&pf_cent_pl
, frp
);
810 * We must keep tracking the overall fragment even when
811 * we're going to drop it anyway so that we know when to
812 * free the overall descriptor. Thus we drop the frag late.
819 /* Update maximum data size */
820 if ((*frag
)->fr_max
< fr_max
)
821 (*frag
)->fr_max
= fr_max
;
823 /* This is the last segment */
825 (*frag
)->fr_flags
|= PFFRAG_SEENLAST
;
827 /* Check if we are completely reassembled */
828 if (((*frag
)->fr_flags
& PFFRAG_SEENLAST
) &&
829 LIST_FIRST(&(*frag
)->fr_cache
)->fr_off
== 0 &&
830 LIST_FIRST(&(*frag
)->fr_cache
)->fr_end
== (*frag
)->fr_max
) {
831 /* Remove from fragment queue */
832 DPFPRINTF(("fragcache[%d]: done 0-%d\n", h
->ip_id
,
834 pf_free_fragment(*frag
);
843 /* Still need to pay attention to !IP_MF */
844 if (!mff
&& *frag
!= NULL
)
845 (*frag
)->fr_flags
|= PFFRAG_SEENLAST
;
852 /* Still need to pay attention to !IP_MF */
853 if (!mff
&& *frag
!= NULL
)
854 (*frag
)->fr_flags
|= PFFRAG_SEENLAST
;
857 /* This fragment has been deemed bad. Don't reass */
858 if (((*frag
)->fr_flags
& PFFRAG_DROP
) == 0)
859 DPFPRINTF(("fragcache[%d]: dropping overall fragment\n",
861 (*frag
)->fr_flags
|= PFFRAG_DROP
;
869 pf_normalize_ip(struct mbuf
**m0
, int dir
, struct pfi_kif
*kif
, u_short
*reason
,
872 struct mbuf
*m
= *m0
;
874 struct pf_frent
*frent
;
875 struct pf_fragment
*frag
= NULL
;
876 struct ip
*h
= mtod(m
, struct ip
*);
877 int mff
= (ntohs(h
->ip_off
) & IP_MF
);
878 int hlen
= h
->ip_hl
<< 2;
879 u_int16_t fragoff
= (ntohs(h
->ip_off
) & IP_OFFMASK
) << 3;
884 struct pf_ruleset
*ruleset
= NULL
;
886 r
= TAILQ_FIRST(pf_main_ruleset
.rules
[PF_RULESET_SCRUB
].active
.ptr
);
889 if (pfi_kif_match(r
->kif
, kif
) == r
->ifnot
)
890 r
= r
->skip
[PF_SKIP_IFP
].ptr
;
891 else if (r
->direction
&& r
->direction
!= dir
)
892 r
= r
->skip
[PF_SKIP_DIR
].ptr
;
893 else if (r
->af
&& r
->af
!= AF_INET
)
894 r
= r
->skip
[PF_SKIP_AF
].ptr
;
895 else if (r
->proto
&& r
->proto
!= h
->ip_p
)
896 r
= r
->skip
[PF_SKIP_PROTO
].ptr
;
897 else if (PF_MISMATCHAW(&r
->src
.addr
,
898 (struct pf_addr
*)&h
->ip_src
.s_addr
, AF_INET
,
900 r
= r
->skip
[PF_SKIP_SRC_ADDR
].ptr
;
901 else if (PF_MISMATCHAW(&r
->dst
.addr
,
902 (struct pf_addr
*)&h
->ip_dst
.s_addr
, AF_INET
,
904 r
= r
->skip
[PF_SKIP_DST_ADDR
].ptr
;
906 if (r
->anchor
== NULL
)
909 pf_step_into_anchor(&asd
, &ruleset
,
910 PF_RULESET_SCRUB
, &r
, NULL
, NULL
);
912 if (r
== NULL
&& pf_step_out_of_anchor(&asd
, &ruleset
,
913 PF_RULESET_SCRUB
, &r
, NULL
, NULL
))
917 if (r
== NULL
|| r
->action
== PF_NOSCRUB
)
920 r
->packets
[dir
== PF_OUT
]++;
921 r
->bytes
[dir
== PF_OUT
] += pd
->tot_len
;
924 /* Check for illegal packets */
925 if (hlen
< (int)sizeof (struct ip
))
928 if (hlen
> ntohs(h
->ip_len
))
931 /* Clear IP_DF if the rule uses the no-df option */
932 if (r
->rule_flag
& PFRULE_NODF
&& h
->ip_off
& htons(IP_DF
)) {
933 u_int16_t ipoff
= h
->ip_off
;
935 h
->ip_off
&= htons(~IP_DF
);
936 h
->ip_sum
= pf_cksum_fixup(h
->ip_sum
, ipoff
, h
->ip_off
, 0);
939 /* We will need other tests here */
940 if (!fragoff
&& !mff
)
944 * We're dealing with a fragment now. Don't allow fragments
945 * with IP_DF to enter the cache. If the flag was cleared by
946 * no-df above, fine. Otherwise drop it.
948 if (h
->ip_off
& htons(IP_DF
)) {
949 DPFPRINTF(("IP_DF\n"));
953 ip_len
= ntohs(h
->ip_len
) - hlen
;
954 ip_off
= (ntohs(h
->ip_off
) & IP_OFFMASK
) << 3;
956 /* All fragments are 8 byte aligned */
957 if (mff
&& (ip_len
& 0x7)) {
958 DPFPRINTF(("mff and %d\n", ip_len
));
962 /* Respect maximum length */
963 if (fragoff
+ ip_len
> IP_MAXPACKET
) {
964 DPFPRINTF(("max packet %d\n", fragoff
+ ip_len
));
967 fr_max
= fragoff
+ ip_len
;
969 if ((r
->rule_flag
& (PFRULE_FRAGCROP
|PFRULE_FRAGDROP
)) == 0) {
970 /* Fully buffer all of the fragments */
972 frag
= pf_find_fragment(h
, &pf_frag_tree
);
974 /* Check if we saw the last fragment already */
975 if (frag
!= NULL
&& (frag
->fr_flags
& PFFRAG_SEENLAST
) &&
976 fr_max
> frag
->fr_max
)
979 /* Get an entry for the fragment queue */
980 frent
= pool_get(&pf_frent_pl
, PR_NOWAIT
);
982 REASON_SET(reason
, PFRES_MEMORY
);
989 /* Might return a completely reassembled mbuf, or NULL */
990 DPFPRINTF(("reass frag %d @ %d-%d\n", h
->ip_id
, fragoff
,
992 *m0
= m
= pf_reassemble(m0
, &frag
, frent
, mff
);
997 /* use mtag from concatenated mbuf chain */
998 pd
->pf_mtag
= pf_find_mtag(m
);
1000 if (pd
->pf_mtag
== NULL
) {
1001 printf("%s: pf_find_mtag returned NULL(1)\n", __func__
);
1002 if ((pd
->pf_mtag
= pf_get_mtag(m
)) == NULL
) {
1009 if (frag
!= NULL
&& (frag
->fr_flags
& PFFRAG_DROP
))
1012 h
= mtod(m
, struct ip
*);
1014 /* non-buffering fragment cache (drops or masks overlaps) */
1017 if (dir
== PF_OUT
&& (pd
->pf_mtag
->flags
& PF_TAG_FRAGCACHE
)) {
1019 * Already passed the fragment cache in the
1020 * input direction. If we continued, it would
1021 * appear to be a dup and would be dropped.
1026 frag
= pf_find_fragment(h
, &pf_cache_tree
);
1028 /* Check if we saw the last fragment already */
1029 if (frag
!= NULL
&& (frag
->fr_flags
& PFFRAG_SEENLAST
) &&
1030 fr_max
> frag
->fr_max
) {
1031 if (r
->rule_flag
& PFRULE_FRAGDROP
)
1032 frag
->fr_flags
|= PFFRAG_DROP
;
1036 *m0
= m
= pf_fragcache(m0
, h
, &frag
, mff
,
1037 (r
->rule_flag
& PFRULE_FRAGDROP
) ? 1 : 0, &nomem
);
1044 /* use mtag from copied and trimmed mbuf chain */
1045 pd
->pf_mtag
= pf_find_mtag(m
);
1047 if (pd
->pf_mtag
== NULL
) {
1048 printf("%s: pf_find_mtag returned NULL(2)\n", __func__
);
1049 if ((pd
->pf_mtag
= pf_get_mtag(m
)) == NULL
) {
1057 pd
->pf_mtag
->flags
|= PF_TAG_FRAGCACHE
;
1059 if (frag
!= NULL
&& (frag
->fr_flags
& PFFRAG_DROP
))
1065 /* At this point, only IP_DF is allowed in ip_off */
1066 if (h
->ip_off
& ~htons(IP_DF
)) {
1067 u_int16_t ipoff
= h
->ip_off
;
1069 h
->ip_off
&= htons(IP_DF
);
1070 h
->ip_sum
= pf_cksum_fixup(h
->ip_sum
, ipoff
, h
->ip_off
, 0);
1073 /* Enforce a minimum ttl, may cause endless packet loops */
1074 if (r
->min_ttl
&& h
->ip_ttl
< r
->min_ttl
) {
1075 u_int16_t ip_ttl
= h
->ip_ttl
;
1077 h
->ip_ttl
= r
->min_ttl
;
1078 h
->ip_sum
= pf_cksum_fixup(h
->ip_sum
, ip_ttl
, h
->ip_ttl
, 0);
1081 if (r
->rule_flag
& PFRULE_RANDOMID
) {
1082 u_int16_t ip_id
= h
->ip_id
;
1084 h
->ip_id
= ip_randomid();
1085 h
->ip_sum
= pf_cksum_fixup(h
->ip_sum
, ip_id
, h
->ip_id
, 0);
1087 #endif /* RANDOM_IP_ID */
1088 if ((r
->rule_flag
& (PFRULE_FRAGCROP
|PFRULE_FRAGDROP
)) == 0)
1089 pd
->flags
|= PFDESC_IP_REAS
;
1094 /* Enforce a minimum ttl, may cause endless packet loops */
1095 if (r
->min_ttl
&& h
->ip_ttl
< r
->min_ttl
) {
1096 u_int16_t ip_ttl
= h
->ip_ttl
;
1098 h
->ip_ttl
= r
->min_ttl
;
1099 h
->ip_sum
= pf_cksum_fixup(h
->ip_sum
, ip_ttl
, h
->ip_ttl
, 0);
1101 if ((r
->rule_flag
& (PFRULE_FRAGCROP
|PFRULE_FRAGDROP
)) == 0)
1102 pd
->flags
|= PFDESC_IP_REAS
;
1106 REASON_SET(reason
, PFRES_MEMORY
);
1107 if (r
!= NULL
&& r
->log
)
1108 PFLOG_PACKET(kif
, h
, m
, AF_INET
, dir
, *reason
, r
,
1113 REASON_SET(reason
, PFRES_NORM
);
1114 if (r
!= NULL
&& r
->log
)
1115 PFLOG_PACKET(kif
, h
, m
, AF_INET
, dir
, *reason
, r
,
1120 DPFPRINTF(("dropping bad fragment\n"));
1122 /* Free associated fragments */
1124 pf_free_fragment(frag
);
1126 REASON_SET(reason
, PFRES_FRAG
);
1127 if (r
!= NULL
&& r
->log
)
1128 PFLOG_PACKET(kif
, h
, m
, AF_INET
, dir
, *reason
, r
, NULL
, NULL
, pd
);
1135 pf_normalize_ip6(struct mbuf
**m0
, int dir
, struct pfi_kif
*kif
,
1136 u_short
*reason
, struct pf_pdesc
*pd
)
1138 struct mbuf
*m
= *m0
;
1140 struct ip6_hdr
*h
= mtod(m
, struct ip6_hdr
*);
1146 struct ip6_opt_jumbo jumbo
;
1150 struct ip6_frag frag
;
1151 u_int32_t jumbolen
= 0, plen
;
1152 u_int16_t fragoff
= 0;
1156 struct pf_ruleset
*ruleset
= NULL
;
1158 r
= TAILQ_FIRST(pf_main_ruleset
.rules
[PF_RULESET_SCRUB
].active
.ptr
);
1161 if (pfi_kif_match(r
->kif
, kif
) == r
->ifnot
)
1162 r
= r
->skip
[PF_SKIP_IFP
].ptr
;
1163 else if (r
->direction
&& r
->direction
!= dir
)
1164 r
= r
->skip
[PF_SKIP_DIR
].ptr
;
1165 else if (r
->af
&& r
->af
!= AF_INET6
)
1166 r
= r
->skip
[PF_SKIP_AF
].ptr
;
1167 #if 0 /* header chain! */
1168 else if (r
->proto
&& r
->proto
!= h
->ip6_nxt
)
1169 r
= r
->skip
[PF_SKIP_PROTO
].ptr
;
1171 else if (PF_MISMATCHAW(&r
->src
.addr
,
1172 (struct pf_addr
*)&h
->ip6_src
, AF_INET6
,
1174 r
= r
->skip
[PF_SKIP_SRC_ADDR
].ptr
;
1175 else if (PF_MISMATCHAW(&r
->dst
.addr
,
1176 (struct pf_addr
*)&h
->ip6_dst
, AF_INET6
,
1178 r
= r
->skip
[PF_SKIP_DST_ADDR
].ptr
;
1180 if (r
->anchor
== NULL
)
1183 pf_step_into_anchor(&asd
, &ruleset
,
1184 PF_RULESET_SCRUB
, &r
, NULL
, NULL
);
1186 if (r
== NULL
&& pf_step_out_of_anchor(&asd
, &ruleset
,
1187 PF_RULESET_SCRUB
, &r
, NULL
, NULL
))
1191 if (r
== NULL
|| r
->action
== PF_NOSCRUB
)
1194 r
->packets
[dir
== PF_OUT
]++;
1195 r
->bytes
[dir
== PF_OUT
] += pd
->tot_len
;
1198 /* Check for illegal packets */
1199 if ((int)(sizeof (struct ip6_hdr
) + IPV6_MAXPACKET
) < m
->m_pkthdr
.len
)
1202 off
= sizeof (struct ip6_hdr
);
1207 case IPPROTO_FRAGMENT
:
1211 case IPPROTO_ROUTING
:
1212 case IPPROTO_DSTOPTS
:
1213 if (!pf_pull_hdr(m
, off
, &ext
, sizeof (ext
), NULL
,
1216 #ifndef NO_APPLE_EXTENSIONS
1219 * Routing header type zero considered harmful.
1221 if (proto
== IPPROTO_ROUTING
) {
1222 const struct ip6_rthdr
*rh
=
1223 (const struct ip6_rthdr
*)&ext
;
1224 if (rh
->ip6r_type
== IPV6_RTHDR_TYPE_0
)
1229 if (proto
== IPPROTO_AH
)
1230 off
+= (ext
.ip6e_len
+ 2) * 4;
1232 off
+= (ext
.ip6e_len
+ 1) * 8;
1233 proto
= ext
.ip6e_nxt
;
1235 case IPPROTO_HOPOPTS
:
1238 if (!pf_pull_hdr(m
, off
, &ext
, sizeof (ext
), NULL
,
1241 optend
= off
+ (ext
.ip6e_len
+ 1) * 8;
1242 ooff
= off
+ sizeof (ext
);
1244 if (!pf_pull_hdr(m
, ooff
, &opt
.ip6o_type
,
1245 sizeof (opt
.ip6o_type
), NULL
, NULL
,
1248 if (opt
.ip6o_type
== IP6OPT_PAD1
) {
1252 if (!pf_pull_hdr(m
, ooff
, &opt
, sizeof (opt
),
1253 NULL
, NULL
, AF_INET6
))
1255 if (ooff
+ sizeof (opt
) + opt
.ip6o_len
> optend
)
1257 switch (opt
.ip6o_type
) {
1259 if (h
->ip6_plen
!= 0)
1261 if (!pf_pull_hdr(m
, ooff
, &jumbo
,
1262 sizeof (jumbo
), NULL
, NULL
,
1265 memcpy(&jumbolen
, jumbo
.ip6oj_jumbo_len
,
1267 jumbolen
= ntohl(jumbolen
);
1268 if (jumbolen
<= IPV6_MAXPACKET
)
1270 if (sizeof (struct ip6_hdr
) +
1271 jumbolen
!= m
->m_pkthdr
.len
)
1277 ooff
+= sizeof (opt
) + opt
.ip6o_len
;
1278 } while (ooff
< optend
);
1281 proto
= ext
.ip6e_nxt
;
1288 } while (!terminal
);
1290 /* jumbo payload option must be present, or plen > 0 */
1291 if (ntohs(h
->ip6_plen
) == 0)
1294 plen
= ntohs(h
->ip6_plen
);
1297 if ((int)(sizeof (struct ip6_hdr
) + plen
) > m
->m_pkthdr
.len
)
1300 /* Enforce a minimum ttl, may cause endless packet loops */
1301 if (r
->min_ttl
&& h
->ip6_hlim
< r
->min_ttl
)
1302 h
->ip6_hlim
= r
->min_ttl
;
1307 if (ntohs(h
->ip6_plen
) == 0 || jumbolen
)
1309 plen
= ntohs(h
->ip6_plen
);
1311 if (!pf_pull_hdr(m
, off
, &frag
, sizeof (frag
), NULL
, NULL
, AF_INET6
))
1313 fragoff
= ntohs(frag
.ip6f_offlg
& IP6F_OFF_MASK
);
1314 if (fragoff
+ (plen
- off
- sizeof (frag
)) > IPV6_MAXPACKET
)
1317 /* do something about it */
1318 /* remember to set pd->flags |= PFDESC_IP_REAS */
1322 REASON_SET(reason
, PFRES_SHORT
);
1323 if (r
!= NULL
&& r
->log
)
1324 PFLOG_PACKET(kif
, h
, m
, AF_INET6
, dir
, *reason
, r
,
1329 REASON_SET(reason
, PFRES_NORM
);
1330 if (r
!= NULL
&& r
->log
)
1331 PFLOG_PACKET(kif
, h
, m
, AF_INET6
, dir
, *reason
, r
,
1336 REASON_SET(reason
, PFRES_FRAG
);
1337 if (r
!= NULL
&& r
->log
)
1338 PFLOG_PACKET(kif
, h
, m
, AF_INET6
, dir
, *reason
, r
,
1345 pf_normalize_tcp(int dir
, struct pfi_kif
*kif
, struct mbuf
*m
, int ipoff
,
1346 int off
, void *h
, struct pf_pdesc
*pd
)
1348 #pragma unused(ipoff, h)
1349 struct pf_rule
*r
, *rm
= NULL
;
1350 struct tcphdr
*th
= pd
->hdr
.tcp
;
1355 sa_family_t af
= pd
->af
;
1356 struct pf_ruleset
*ruleset
= NULL
;
1357 #ifndef NO_APPLE_EXTENSIONS
1358 union pf_state_xport sxport
, dxport
;
1360 sxport
.port
= th
->th_sport
;
1361 dxport
.port
= th
->th_dport
;
1364 r
= TAILQ_FIRST(pf_main_ruleset
.rules
[PF_RULESET_SCRUB
].active
.ptr
);
1367 if (pfi_kif_match(r
->kif
, kif
) == r
->ifnot
)
1368 r
= r
->skip
[PF_SKIP_IFP
].ptr
;
1369 else if (r
->direction
&& r
->direction
!= dir
)
1370 r
= r
->skip
[PF_SKIP_DIR
].ptr
;
1371 else if (r
->af
&& r
->af
!= af
)
1372 r
= r
->skip
[PF_SKIP_AF
].ptr
;
1373 else if (r
->proto
&& r
->proto
!= pd
->proto
)
1374 r
= r
->skip
[PF_SKIP_PROTO
].ptr
;
1375 else if (PF_MISMATCHAW(&r
->src
.addr
, pd
->src
, af
,
1377 r
= r
->skip
[PF_SKIP_SRC_ADDR
].ptr
;
1378 #ifndef NO_APPLE_EXTENSIONS
1379 else if (r
->src
.xport
.range
.op
&&
1380 !pf_match_xport(r
->src
.xport
.range
.op
, r
->proto_variant
,
1381 &r
->src
.xport
, &sxport
))
1383 else if (r
->src
.port_op
&& !pf_match_port(r
->src
.port_op
,
1384 r
->src
.port
[0], r
->src
.port
[1], th
->th_sport
))
1386 r
= r
->skip
[PF_SKIP_SRC_PORT
].ptr
;
1387 else if (PF_MISMATCHAW(&r
->dst
.addr
, pd
->dst
, af
,
1389 r
= r
->skip
[PF_SKIP_DST_ADDR
].ptr
;
1390 #ifndef NO_APPLE_EXTENSIONS
1391 else if (r
->dst
.xport
.range
.op
&&
1392 !pf_match_xport(r
->dst
.xport
.range
.op
, r
->proto_variant
,
1393 &r
->dst
.xport
, &dxport
))
1395 else if (r
->dst
.port_op
&& !pf_match_port(r
->dst
.port_op
,
1396 r
->dst
.port
[0], r
->dst
.port
[1], th
->th_dport
))
1398 r
= r
->skip
[PF_SKIP_DST_PORT
].ptr
;
1399 else if (r
->os_fingerprint
!= PF_OSFP_ANY
&&
1400 !pf_osfp_match(pf_osfp_fingerprint(pd
, m
, off
, th
),
1402 r
= TAILQ_NEXT(r
, entries
);
1404 if (r
->anchor
== NULL
) {
1408 pf_step_into_anchor(&asd
, &ruleset
,
1409 PF_RULESET_SCRUB
, &r
, NULL
, NULL
);
1412 if (r
== NULL
&& pf_step_out_of_anchor(&asd
, &ruleset
,
1413 PF_RULESET_SCRUB
, &r
, NULL
, NULL
))
1417 if (rm
== NULL
|| rm
->action
== PF_NOSCRUB
)
1420 r
->packets
[dir
== PF_OUT
]++;
1421 r
->bytes
[dir
== PF_OUT
] += pd
->tot_len
;
1424 if (rm
->rule_flag
& PFRULE_REASSEMBLE_TCP
)
1425 pd
->flags
|= PFDESC_TCP_NORM
;
1427 flags
= th
->th_flags
;
1428 if (flags
& TH_SYN
) {
1429 /* Illegal packet */
1436 /* Illegal packet */
1437 if (!(flags
& (TH_ACK
|TH_RST
)))
1441 if (!(flags
& TH_ACK
)) {
1442 /* These flags are only valid if ACK is set */
1443 if ((flags
& TH_FIN
) || (flags
& TH_PUSH
) || (flags
& TH_URG
))
1447 /* Check for illegal header length */
1448 if (th
->th_off
< (sizeof (struct tcphdr
) >> 2))
1451 /* If flags changed, or reserved data set, then adjust */
1452 if (flags
!= th
->th_flags
|| th
->th_x2
!= 0) {
1455 ov
= *(u_int16_t
*)(&th
->th_ack
+ 1);
1456 th
->th_flags
= flags
;
1458 nv
= *(u_int16_t
*)(&th
->th_ack
+ 1);
1460 th
->th_sum
= pf_cksum_fixup(th
->th_sum
, ov
, nv
, 0);
1464 /* Remove urgent pointer, if TH_URG is not set */
1465 if (!(flags
& TH_URG
) && th
->th_urp
) {
1466 th
->th_sum
= pf_cksum_fixup(th
->th_sum
, th
->th_urp
, 0, 0);
1471 /* copy back packet headers if we sanitized */
1472 #ifndef NO_APPLE_EXTENSIONS
1473 /* Process options */
1475 int rv
= pf_normalize_tcpopt(r
, dir
, kif
, pd
, m
, th
, off
,
1483 struct mbuf
*mw
= pf_lazy_makewritable(pd
, m
,
1484 off
+ sizeof (*th
));
1486 REASON_SET(&reason
, PFRES_MEMORY
);
1488 PFLOG_PACKET(kif
, h
, m
, AF_INET
, dir
, reason
,
1493 m_copyback(mw
, off
, sizeof (*th
), th
);
1496 /* Process options */
1497 if (r
->max_mss
&& pf_normalize_tcpopt(r
, m
, th
, off
, pd
->af
))
1501 m_copyback(m
, off
, sizeof (*th
), th
);
1507 REASON_SET(&reason
, PFRES_NORM
);
1508 if (rm
!= NULL
&& r
->log
)
1509 PFLOG_PACKET(kif
, h
, m
, AF_INET
, dir
, reason
, r
, NULL
, NULL
, pd
);
1514 pf_normalize_tcp_init(struct mbuf
*m
, int off
, struct pf_pdesc
*pd
,
1515 struct tcphdr
*th
, struct pf_state_peer
*src
, struct pf_state_peer
*dst
)
1518 u_int32_t tsval
, tsecr
;
1522 VERIFY(src
->scrub
== NULL
);
1524 src
->scrub
= pool_get(&pf_state_scrub_pl
, PR_NOWAIT
);
1525 if (src
->scrub
== NULL
)
1527 bzero(src
->scrub
, sizeof (*src
->scrub
));
1532 struct ip
*h
= mtod(m
, struct ip
*);
1533 src
->scrub
->pfss_ttl
= h
->ip_ttl
;
1539 struct ip6_hdr
*h
= mtod(m
, struct ip6_hdr
*);
1540 src
->scrub
->pfss_ttl
= h
->ip6_hlim
;
1548 * All normalizations below are only begun if we see the start of
1549 * the connections. They must all set an enabled bit in pfss_flags
1551 if ((th
->th_flags
& TH_SYN
) == 0)
1555 if (th
->th_off
> (sizeof (struct tcphdr
) >> 2) && src
->scrub
&&
1556 pf_pull_hdr(m
, off
, hdr
, th
->th_off
<< 2, NULL
, NULL
, pd
->af
)) {
1557 /* Diddle with TCP options */
1559 opt
= hdr
+ sizeof (struct tcphdr
);
1560 hlen
= (th
->th_off
<< 2) - sizeof (struct tcphdr
);
1561 while (hlen
>= TCPOLEN_TIMESTAMP
) {
1563 case TCPOPT_EOL
: /* FALLTHROUGH */
1568 case TCPOPT_TIMESTAMP
:
1569 if (opt
[1] >= TCPOLEN_TIMESTAMP
) {
1570 src
->scrub
->pfss_flags
|=
1572 src
->scrub
->pfss_ts_mod
=
1575 /* note PFSS_PAWS not set yet */
1576 memcpy(&tsval
, &opt
[2],
1577 sizeof (u_int32_t
));
1578 memcpy(&tsecr
, &opt
[6],
1579 sizeof (u_int32_t
));
1580 src
->scrub
->pfss_tsval0
= ntohl(tsval
);
1581 src
->scrub
->pfss_tsval
= ntohl(tsval
);
1582 src
->scrub
->pfss_tsecr
= ntohl(tsecr
);
1583 getmicrouptime(&src
->scrub
->pfss_last
);
1587 hlen
-= MAX(opt
[1], 2);
1588 opt
+= MAX(opt
[1], 2);
1598 pf_normalize_tcp_cleanup(struct pf_state
*state
)
1600 if (state
->src
.scrub
)
1601 pool_put(&pf_state_scrub_pl
, state
->src
.scrub
);
1602 if (state
->dst
.scrub
)
1603 pool_put(&pf_state_scrub_pl
, state
->dst
.scrub
);
1605 /* Someday... flush the TCP segment reassembly descriptors. */
1609 pf_normalize_tcp_stateful(struct mbuf
*m
, int off
, struct pf_pdesc
*pd
,
1610 u_short
*reason
, struct tcphdr
*th
, struct pf_state
*state
,
1611 struct pf_state_peer
*src
, struct pf_state_peer
*dst
, int *writeback
)
1613 struct timeval uptime
;
1614 u_int32_t tsval
, tsecr
;
1615 u_int tsval_from_last
;
1621 VERIFY(src
->scrub
|| dst
->scrub
);
1624 * Enforce the minimum TTL seen for this connection. Negate a common
1625 * technique to evade an intrusion detection system and confuse
1626 * firewall state code.
1632 struct ip
*h
= mtod(m
, struct ip
*);
1633 if (h
->ip_ttl
> src
->scrub
->pfss_ttl
)
1634 src
->scrub
->pfss_ttl
= h
->ip_ttl
;
1635 h
->ip_ttl
= src
->scrub
->pfss_ttl
;
1643 struct ip6_hdr
*h
= mtod(m
, struct ip6_hdr
*);
1644 if (h
->ip6_hlim
> src
->scrub
->pfss_ttl
)
1645 src
->scrub
->pfss_ttl
= h
->ip6_hlim
;
1646 h
->ip6_hlim
= src
->scrub
->pfss_ttl
;
1653 if (th
->th_off
> (sizeof (struct tcphdr
) >> 2) &&
1654 ((src
->scrub
&& (src
->scrub
->pfss_flags
& PFSS_TIMESTAMP
)) ||
1655 (dst
->scrub
&& (dst
->scrub
->pfss_flags
& PFSS_TIMESTAMP
))) &&
1656 pf_pull_hdr(m
, off
, hdr
, th
->th_off
<< 2, NULL
, NULL
, pd
->af
)) {
1657 /* Diddle with TCP options */
1659 opt
= hdr
+ sizeof (struct tcphdr
);
1660 hlen
= (th
->th_off
<< 2) - sizeof (struct tcphdr
);
1661 while (hlen
>= TCPOLEN_TIMESTAMP
) {
1663 case TCPOPT_EOL
: /* FALLTHROUGH */
1668 case TCPOPT_TIMESTAMP
:
1670 * Modulate the timestamps. Can be used for
1671 * NAT detection, OS uptime determination or
1676 /* Huh? Multiple timestamps!? */
1677 if (pf_status
.debug
>= PF_DEBUG_MISC
) {
1678 DPFPRINTF(("multiple TS??"));
1679 pf_print_state(state
);
1682 REASON_SET(reason
, PFRES_TS
);
1685 if (opt
[1] >= TCPOLEN_TIMESTAMP
) {
1686 memcpy(&tsval
, &opt
[2],
1687 sizeof (u_int32_t
));
1688 if (tsval
&& src
->scrub
&&
1689 (src
->scrub
->pfss_flags
&
1691 tsval
= ntohl(tsval
);
1692 pf_change_a(&opt
[2],
1695 src
->scrub
->pfss_ts_mod
),
1700 /* Modulate TS reply iff valid (!0) */
1701 memcpy(&tsecr
, &opt
[6],
1702 sizeof (u_int32_t
));
1703 if (tsecr
&& dst
->scrub
&&
1704 (dst
->scrub
->pfss_flags
&
1706 tsecr
= ntohl(tsecr
)
1707 - dst
->scrub
->pfss_ts_mod
;
1708 pf_change_a(&opt
[6],
1709 &th
->th_sum
, htonl(tsecr
),
1717 hlen
-= MAX(opt
[1], 2);
1718 opt
+= MAX(opt
[1], 2);
1723 /* Copyback the options, caller copys back header */
1724 #ifndef NO_APPLE_EXTENSIONS
1725 int optoff
= off
+ sizeof (*th
);
1726 int optlen
= (th
->th_off
<< 2) - sizeof (*th
);
1727 m
= pf_lazy_makewritable(pd
, m
, optoff
+ optlen
);
1729 REASON_SET(reason
, PFRES_MEMORY
);
1732 *writeback
= optoff
+ optlen
;
1733 m_copyback(m
, optoff
, optlen
, hdr
+ sizeof (*th
));
1736 m_copyback(m
, off
+ sizeof (struct tcphdr
),
1737 (th
->th_off
<< 2) - sizeof (struct tcphdr
), hdr
+
1738 sizeof (struct tcphdr
));
1745 * Must invalidate PAWS checks on connections idle for too long.
1746 * The fastest allowed timestamp clock is 1ms. That turns out to
1747 * be about 24 days before it wraps. XXX Right now our lowerbound
1748 * TS echo check only works for the first 12 days of a connection
1749 * when the TS has exhausted half its 32bit space
1751 #define TS_MAX_IDLE (24*24*60*60)
1752 #define TS_MAX_CONN (12*24*60*60) /* XXX remove when better tsecr check */
1754 getmicrouptime(&uptime
);
1755 if (src
->scrub
&& (src
->scrub
->pfss_flags
& PFSS_PAWS
) &&
1756 (uptime
.tv_sec
- src
->scrub
->pfss_last
.tv_sec
> TS_MAX_IDLE
||
1757 pf_time_second() - state
->creation
> TS_MAX_CONN
)) {
1758 if (pf_status
.debug
>= PF_DEBUG_MISC
) {
1759 DPFPRINTF(("src idled out of PAWS\n"));
1760 pf_print_state(state
);
1763 src
->scrub
->pfss_flags
= (src
->scrub
->pfss_flags
& ~PFSS_PAWS
)
1766 if (dst
->scrub
&& (dst
->scrub
->pfss_flags
& PFSS_PAWS
) &&
1767 uptime
.tv_sec
- dst
->scrub
->pfss_last
.tv_sec
> TS_MAX_IDLE
) {
1768 if (pf_status
.debug
>= PF_DEBUG_MISC
) {
1769 DPFPRINTF(("dst idled out of PAWS\n"));
1770 pf_print_state(state
);
1773 dst
->scrub
->pfss_flags
= (dst
->scrub
->pfss_flags
& ~PFSS_PAWS
)
1777 if (got_ts
&& src
->scrub
&& dst
->scrub
&&
1778 (src
->scrub
->pfss_flags
& PFSS_PAWS
) &&
1779 (dst
->scrub
->pfss_flags
& PFSS_PAWS
)) {
1781 * Validate that the timestamps are "in-window".
1782 * RFC1323 describes TCP Timestamp options that allow
1783 * measurement of RTT (round trip time) and PAWS
1784 * (protection against wrapped sequence numbers). PAWS
1785 * gives us a set of rules for rejecting packets on
1786 * long fat pipes (packets that were somehow delayed
1787 * in transit longer than the time it took to send the
1788 * full TCP sequence space of 4Gb). We can use these
1789 * rules and infer a few others that will let us treat
1790 * the 32bit timestamp and the 32bit echoed timestamp
1791 * as sequence numbers to prevent a blind attacker from
1792 * inserting packets into a connection.
1795 * - The timestamp on this packet must be greater than
1796 * or equal to the last value echoed by the other
1797 * endpoint. The RFC says those will be discarded
1798 * since it is a dup that has already been acked.
1799 * This gives us a lowerbound on the timestamp.
1800 * timestamp >= other last echoed timestamp
1801 * - The timestamp will be less than or equal to
1802 * the last timestamp plus the time between the
1803 * last packet and now. The RFC defines the max
1804 * clock rate as 1ms. We will allow clocks to be
1805 * up to 10% fast and will allow a total difference
1806 * or 30 seconds due to a route change. And this
1807 * gives us an upperbound on the timestamp.
1808 * timestamp <= last timestamp + max ticks
1809 * We have to be careful here. Windows will send an
1810 * initial timestamp of zero and then initialize it
1811 * to a random value after the 3whs; presumably to
1812 * avoid a DoS by having to call an expensive RNG
1813 * during a SYN flood. Proof MS has at least one
1814 * good security geek.
1816 * - The TCP timestamp option must also echo the other
1817 * endpoints timestamp. The timestamp echoed is the
1818 * one carried on the earliest unacknowledged segment
1819 * on the left edge of the sequence window. The RFC
1820 * states that the host will reject any echoed
1821 * timestamps that were larger than any ever sent.
1822 * This gives us an upperbound on the TS echo.
1823 * tescr <= largest_tsval
1824 * - The lowerbound on the TS echo is a little more
1825 * tricky to determine. The other endpoint's echoed
1826 * values will not decrease. But there may be
1827 * network conditions that re-order packets and
1828 * cause our view of them to decrease. For now the
1829 * only lowerbound we can safely determine is that
1830 * the TS echo will never be less than the original
1831 * TS. XXX There is probably a better lowerbound.
1832 * Remove TS_MAX_CONN with better lowerbound check.
1833 * tescr >= other original TS
1835 * It is also important to note that the fastest
1836 * timestamp clock of 1ms will wrap its 32bit space in
1837 * 24 days. So we just disable TS checking after 24
1838 * days of idle time. We actually must use a 12d
1839 * connection limit until we can come up with a better
1840 * lowerbound to the TS echo check.
1842 struct timeval delta_ts
;
1847 * PFTM_TS_DIFF is how many seconds of leeway to allow
1848 * a host's timestamp. This can happen if the previous
1849 * packet got delayed in transit for much longer than
1852 if ((ts_fudge
= state
->rule
.ptr
->timeout
[PFTM_TS_DIFF
]) == 0)
1853 ts_fudge
= pf_default_rule
.timeout
[PFTM_TS_DIFF
];
1856 /* Calculate max ticks since the last timestamp */
1857 #define TS_MAXFREQ 1100 /* RFC max TS freq of 1Khz + 10% skew */
1858 #define TS_MICROSECS 1000000 /* microseconds per second */
1859 timersub(&uptime
, &src
->scrub
->pfss_last
, &delta_ts
);
1860 tsval_from_last
= (delta_ts
.tv_sec
+ ts_fudge
) * TS_MAXFREQ
;
1861 tsval_from_last
+= delta_ts
.tv_usec
/ (TS_MICROSECS
/TS_MAXFREQ
);
1864 if ((src
->state
>= TCPS_ESTABLISHED
&&
1865 dst
->state
>= TCPS_ESTABLISHED
) &&
1866 (SEQ_LT(tsval
, dst
->scrub
->pfss_tsecr
) ||
1867 SEQ_GT(tsval
, src
->scrub
->pfss_tsval
+ tsval_from_last
) ||
1868 (tsecr
&& (SEQ_GT(tsecr
, dst
->scrub
->pfss_tsval
) ||
1869 SEQ_LT(tsecr
, dst
->scrub
->pfss_tsval0
))))) {
1871 * Bad RFC1323 implementation or an insertion attack.
1873 * - Solaris 2.6 and 2.7 are known to send another ACK
1874 * after the FIN,FIN|ACK,ACK closing that carries
1878 DPFPRINTF(("Timestamp failed %c%c%c%c\n",
1879 SEQ_LT(tsval
, dst
->scrub
->pfss_tsecr
) ? '0' : ' ',
1880 SEQ_GT(tsval
, src
->scrub
->pfss_tsval
+
1881 tsval_from_last
) ? '1' : ' ',
1882 SEQ_GT(tsecr
, dst
->scrub
->pfss_tsval
) ? '2' : ' ',
1883 SEQ_LT(tsecr
, dst
->scrub
->pfss_tsval0
)? '3' : ' '));
1884 DPFPRINTF((" tsval: %u tsecr: %u +ticks: %u "
1885 "idle: %lus %ums\n",
1886 tsval
, tsecr
, tsval_from_last
, delta_ts
.tv_sec
,
1887 delta_ts
.tv_usec
/ 1000));
1888 DPFPRINTF((" src->tsval: %u tsecr: %u\n",
1889 src
->scrub
->pfss_tsval
, src
->scrub
->pfss_tsecr
));
1890 DPFPRINTF((" dst->tsval: %u tsecr: %u tsval0: %u\n",
1891 dst
->scrub
->pfss_tsval
, dst
->scrub
->pfss_tsecr
,
1892 dst
->scrub
->pfss_tsval0
));
1893 if (pf_status
.debug
>= PF_DEBUG_MISC
) {
1894 pf_print_state(state
);
1895 pf_print_flags(th
->th_flags
);
1898 REASON_SET(reason
, PFRES_TS
);
1902 /* XXX I'd really like to require tsecr but it's optional */
1904 } else if (!got_ts
&& (th
->th_flags
& TH_RST
) == 0 &&
1905 ((src
->state
== TCPS_ESTABLISHED
&& dst
->state
== TCPS_ESTABLISHED
)
1906 || pd
->p_len
> 0 || (th
->th_flags
& TH_SYN
)) &&
1907 src
->scrub
&& dst
->scrub
&&
1908 (src
->scrub
->pfss_flags
& PFSS_PAWS
) &&
1909 (dst
->scrub
->pfss_flags
& PFSS_PAWS
)) {
1911 * Didn't send a timestamp. Timestamps aren't really useful
1913 * - connection opening or closing (often not even sent).
1914 * but we must not let an attacker to put a FIN on a
1915 * data packet to sneak it through our ESTABLISHED check.
1916 * - on a TCP reset. RFC suggests not even looking at TS.
1917 * - on an empty ACK. The TS will not be echoed so it will
1918 * probably not help keep the RTT calculation in sync and
1919 * there isn't as much danger when the sequence numbers
1920 * got wrapped. So some stacks don't include TS on empty
1923 * To minimize the disruption to mostly RFC1323 conformant
1924 * stacks, we will only require timestamps on data packets.
1926 * And what do ya know, we cannot require timestamps on data
1927 * packets. There appear to be devices that do legitimate
1928 * TCP connection hijacking. There are HTTP devices that allow
1929 * a 3whs (with timestamps) and then buffer the HTTP request.
1930 * If the intermediate device has the HTTP response cache, it
1931 * will spoof the response but not bother timestamping its
1932 * packets. So we can look for the presence of a timestamp in
1933 * the first data packet and if there, require it in all future
1937 if (pd
->p_len
> 0 && (src
->scrub
->pfss_flags
& PFSS_DATA_TS
)) {
1939 * Hey! Someone tried to sneak a packet in. Or the
1940 * stack changed its RFC1323 behavior?!?!
1942 if (pf_status
.debug
>= PF_DEBUG_MISC
) {
1943 DPFPRINTF(("Did not receive expected RFC1323 "
1945 pf_print_state(state
);
1946 pf_print_flags(th
->th_flags
);
1949 REASON_SET(reason
, PFRES_TS
);
1956 * We will note if a host sends his data packets with or without
1957 * timestamps. And require all data packets to contain a timestamp
1958 * if the first does. PAWS implicitly requires that all data packets be
1959 * timestamped. But I think there are middle-man devices that hijack
1960 * TCP streams immediately after the 3whs and don't timestamp their
1961 * packets (seen in a WWW accelerator or cache).
1963 if (pd
->p_len
> 0 && src
->scrub
&& (src
->scrub
->pfss_flags
&
1964 (PFSS_TIMESTAMP
|PFSS_DATA_TS
|PFSS_DATA_NOTS
)) == PFSS_TIMESTAMP
) {
1966 src
->scrub
->pfss_flags
|= PFSS_DATA_TS
;
1968 src
->scrub
->pfss_flags
|= PFSS_DATA_NOTS
;
1969 if (pf_status
.debug
>= PF_DEBUG_MISC
&& dst
->scrub
&&
1970 (dst
->scrub
->pfss_flags
& PFSS_TIMESTAMP
)) {
1971 /* Don't warn if other host rejected RFC1323 */
1972 DPFPRINTF(("Broken RFC1323 stack did not "
1973 "timestamp data packet. Disabled PAWS "
1975 pf_print_state(state
);
1976 pf_print_flags(th
->th_flags
);
1984 * Update PAWS values
1986 if (got_ts
&& src
->scrub
&& PFSS_TIMESTAMP
== (src
->scrub
->pfss_flags
&
1987 (PFSS_PAWS_IDLED
|PFSS_TIMESTAMP
))) {
1988 getmicrouptime(&src
->scrub
->pfss_last
);
1989 if (SEQ_GEQ(tsval
, src
->scrub
->pfss_tsval
) ||
1990 (src
->scrub
->pfss_flags
& PFSS_PAWS
) == 0)
1991 src
->scrub
->pfss_tsval
= tsval
;
1994 if (SEQ_GEQ(tsecr
, src
->scrub
->pfss_tsecr
) ||
1995 (src
->scrub
->pfss_flags
& PFSS_PAWS
) == 0)
1996 src
->scrub
->pfss_tsecr
= tsecr
;
1998 if ((src
->scrub
->pfss_flags
& PFSS_PAWS
) == 0 &&
1999 (SEQ_LT(tsval
, src
->scrub
->pfss_tsval0
) ||
2000 src
->scrub
->pfss_tsval0
== 0)) {
2001 /* tsval0 MUST be the lowest timestamp */
2002 src
->scrub
->pfss_tsval0
= tsval
;
2005 /* Only fully initialized after a TS gets echoed */
2006 if ((src
->scrub
->pfss_flags
& PFSS_PAWS
) == 0)
2007 src
->scrub
->pfss_flags
|= PFSS_PAWS
;
2011 /* I have a dream.... TCP segment reassembly.... */
2015 #ifndef NO_APPLE_EXTENSIONS
2017 pf_normalize_tcpopt(struct pf_rule
*r
, int dir
, struct pfi_kif
*kif
,
2018 struct pf_pdesc
*pd
, struct mbuf
*m
, struct tcphdr
*th
, int off
,
2021 #pragma unused(dir, kif)
2022 sa_family_t af
= pd
->af
;
2025 pf_normalize_tcpopt(struct pf_rule
*r
, struct mbuf
*m
, struct tcphdr
*th
,
2026 int off
, sa_family_t af
)
2031 int opt
, cnt
, optlen
= 0;
2033 u_char opts
[MAX_TCPOPTLEN
];
2034 u_char
*optp
= opts
;
2036 thoff
= th
->th_off
<< 2;
2037 cnt
= thoff
- sizeof (struct tcphdr
);
2039 #ifndef NO_APPLE_MODIFICATIONS
2040 if (cnt
> 0 && !pf_pull_hdr(m
, off
+ sizeof (*th
), opts
, cnt
,
2044 if (cnt
> 0 && !pf_pull_hdr(m
, off
+ sizeof (*th
), opts
, cnt
,
2049 for (; cnt
> 0; cnt
-= optlen
, optp
+= optlen
) {
2051 if (opt
== TCPOPT_EOL
)
2053 if (opt
== TCPOPT_NOP
)
2059 if (optlen
< 2 || optlen
> cnt
)
2064 mss
= (u_int16_t
*)(optp
+ 2);
2065 if ((ntohs(*mss
)) > r
->max_mss
) {
2066 #ifndef NO_APPLE_MODIFICATIONS
2069 * Only do the TCP checksum fixup if delayed
2070 * checksum calculation will not be performed.
2072 if (m
->m_pkthdr
.rcvif
||
2073 !(m
->m_pkthdr
.csum_flags
& CSUM_TCP
))
2074 th
->th_sum
= pf_cksum_fixup(th
->th_sum
,
2075 *mss
, htons(r
->max_mss
), 0);
2077 th
->th_sum
= pf_cksum_fixup(th
->th_sum
,
2078 *mss
, htons(r
->max_mss
), 0);
2080 *mss
= htons(r
->max_mss
);
2089 #ifndef NO_APPLE_MODIFICATIONS
2094 mw
= pf_lazy_makewritable(pd
, pd
->mp
,
2095 off
+ sizeof (*th
) + thoff
);
2097 REASON_SET(&reason
, PFRES_MEMORY
);
2099 PFLOG_PACKET(kif
, h
, m
, AF_INET
, dir
, reason
,
2105 m_copyback(mw
, off
+ sizeof (*th
), thoff
- sizeof (*th
), opts
);
2111 m_copyback(m
, off
+ sizeof (*th
), thoff
- sizeof (*th
), opts
);