]>
git.saurik.com Git - apple/xnu.git/blob - bsd/net/pf_norm.c
   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         r 
= TAILQ_FIRST(pf_main_ruleset
.rules
[PF_RULESET_SCRUB
].active
.ptr
); 
 887                 if (pfi_kif_match(r
->kif
, kif
) == r
->ifnot
) 
 888                         r 
= r
->skip
[PF_SKIP_IFP
].ptr
; 
 889                 else if (r
->direction 
&& r
->direction 
!= dir
) 
 890                         r 
= r
->skip
[PF_SKIP_DIR
].ptr
; 
 891                 else if (r
->af 
&& r
->af 
!= AF_INET
) 
 892                         r 
= r
->skip
[PF_SKIP_AF
].ptr
; 
 893                 else if (r
->proto 
&& r
->proto 
!= h
->ip_p
) 
 894                         r 
= r
->skip
[PF_SKIP_PROTO
].ptr
; 
 895                 else if (PF_MISMATCHAW(&r
->src
.addr
, 
 896                     (struct pf_addr 
*)&h
->ip_src
.s_addr
, AF_INET
, 
 898                         r 
= r
->skip
[PF_SKIP_SRC_ADDR
].ptr
; 
 899                 else if (PF_MISMATCHAW(&r
->dst
.addr
, 
 900                     (struct pf_addr 
*)&h
->ip_dst
.s_addr
, AF_INET
, 
 902                         r 
= r
->skip
[PF_SKIP_DST_ADDR
].ptr
; 
 907         if (r 
== NULL 
|| r
->action 
== PF_NOSCRUB
) 
 910                 r
->packets
[dir 
== PF_OUT
]++; 
 911                 r
->bytes
[dir 
== PF_OUT
] += pd
->tot_len
; 
 914         /* Check for illegal packets */ 
 915         if (hlen 
< (int)sizeof (struct ip
)) 
 918         if (hlen 
> ntohs(h
->ip_len
)) 
 921         /* Clear IP_DF if the rule uses the no-df option */ 
 922         if (r
->rule_flag 
& PFRULE_NODF 
&& h
->ip_off 
& htons(IP_DF
)) { 
 923                 u_int16_t ipoff 
= h
->ip_off
; 
 925                 h
->ip_off 
&= htons(~IP_DF
); 
 926                 h
->ip_sum 
= pf_cksum_fixup(h
->ip_sum
, ipoff
, h
->ip_off
, 0); 
 929         /* We will need other tests here */ 
 930         if (!fragoff 
&& !mff
) 
 934          * We're dealing with a fragment now. Don't allow fragments 
 935          * with IP_DF to enter the cache. If the flag was cleared by 
 936          * no-df above, fine. Otherwise drop it. 
 938         if (h
->ip_off 
& htons(IP_DF
)) { 
 939                 DPFPRINTF(("IP_DF\n")); 
 943         ip_len 
= ntohs(h
->ip_len
) - hlen
; 
 944         ip_off 
= (ntohs(h
->ip_off
) & IP_OFFMASK
) << 3; 
 946         /* All fragments are 8 byte aligned */ 
 947         if (mff 
&& (ip_len 
& 0x7)) { 
 948                 DPFPRINTF(("mff and %d\n", ip_len
)); 
 952         /* Respect maximum length */ 
 953         if (fragoff 
+ ip_len 
> IP_MAXPACKET
) { 
 954                 DPFPRINTF(("max packet %d\n", fragoff 
+ ip_len
)); 
 957         fr_max 
= fragoff 
+ ip_len
; 
 959         if ((r
->rule_flag 
& (PFRULE_FRAGCROP
|PFRULE_FRAGDROP
)) == 0) { 
 960                 /* Fully buffer all of the fragments */ 
 962                 frag 
= pf_find_fragment(h
, &pf_frag_tree
); 
 964                 /* Check if we saw the last fragment already */ 
 965                 if (frag 
!= NULL 
&& (frag
->fr_flags 
& PFFRAG_SEENLAST
) && 
 966                     fr_max 
> frag
->fr_max
) 
 969                 /* Get an entry for the fragment queue */ 
 970                 frent 
= pool_get(&pf_frent_pl
, PR_NOWAIT
); 
 972                         REASON_SET(reason
, PFRES_MEMORY
); 
 979                 /* Might return a completely reassembled mbuf, or NULL */ 
 980                 DPFPRINTF(("reass frag %d @ %d-%d\n", h
->ip_id
, fragoff
, 
 982                 *m0 
= m 
= pf_reassemble(m0
, &frag
, frent
, mff
); 
 987                 /* use mtag from concatenated mbuf chain */ 
 988                 pd
->pf_mtag 
= pf_find_mtag(m
); 
 990                 if (pd
->pf_mtag 
== NULL
) { 
 991                         printf("%s: pf_find_mtag returned NULL(1)\n", __func__
); 
 992                         if ((pd
->pf_mtag 
= pf_get_mtag(m
)) == NULL
) { 
 999                 if (frag 
!= NULL 
&& (frag
->fr_flags 
& PFFRAG_DROP
)) 
1002                 h 
= mtod(m
, struct ip 
*); 
1004                 /* non-buffering fragment cache (drops or masks overlaps) */ 
1007                 if (dir 
== PF_OUT 
&& (pd
->pf_mtag
->flags 
& PF_TAG_FRAGCACHE
)) { 
1009                          * Already passed the fragment cache in the 
1010                          * input direction.  If we continued, it would 
1011                          * appear to be a dup and would be dropped. 
1016                 frag 
= pf_find_fragment(h
, &pf_cache_tree
); 
1018                 /* Check if we saw the last fragment already */ 
1019                 if (frag 
!= NULL 
&& (frag
->fr_flags 
& PFFRAG_SEENLAST
) && 
1020                     fr_max 
> frag
->fr_max
) { 
1021                         if (r
->rule_flag 
& PFRULE_FRAGDROP
) 
1022                                 frag
->fr_flags 
|= PFFRAG_DROP
; 
1026                 *m0 
= m 
= pf_fragcache(m0
, h
, &frag
, mff
, 
1027                     (r
->rule_flag 
& PFRULE_FRAGDROP
) ? 1 : 0, &nomem
); 
1034                 /* use mtag from copied and trimmed mbuf chain */ 
1035                 pd
->pf_mtag 
= pf_find_mtag(m
); 
1037                 if (pd
->pf_mtag 
== NULL
) { 
1038                         printf("%s: pf_find_mtag returned NULL(2)\n", __func__
); 
1039                         if ((pd
->pf_mtag 
= pf_get_mtag(m
)) == NULL
) { 
1047                         pd
->pf_mtag
->flags 
|= PF_TAG_FRAGCACHE
; 
1049                 if (frag 
!= NULL 
&& (frag
->fr_flags 
& PFFRAG_DROP
)) 
1055         /* At this point, only IP_DF is allowed in ip_off */ 
1056         if (h
->ip_off 
& ~htons(IP_DF
)) { 
1057                 u_int16_t ipoff 
= h
->ip_off
; 
1059                 h
->ip_off 
&= htons(IP_DF
); 
1060                 h
->ip_sum 
= pf_cksum_fixup(h
->ip_sum
, ipoff
, h
->ip_off
, 0); 
1063         /* Enforce a minimum ttl, may cause endless packet loops */ 
1064         if (r
->min_ttl 
&& h
->ip_ttl 
< r
->min_ttl
) { 
1065                 u_int16_t ip_ttl 
= h
->ip_ttl
; 
1067                 h
->ip_ttl 
= r
->min_ttl
; 
1068                 h
->ip_sum 
= pf_cksum_fixup(h
->ip_sum
, ip_ttl
, h
->ip_ttl
, 0); 
1071         if (r
->rule_flag 
& PFRULE_RANDOMID
) { 
1072                 u_int16_t ip_id 
= h
->ip_id
; 
1074                 h
->ip_id 
= ip_randomid(); 
1075                 h
->ip_sum 
= pf_cksum_fixup(h
->ip_sum
, ip_id
, h
->ip_id
, 0); 
1077 #endif /* RANDOM_IP_ID */ 
1078         if ((r
->rule_flag 
& (PFRULE_FRAGCROP
|PFRULE_FRAGDROP
)) == 0) 
1079                 pd
->flags 
|= PFDESC_IP_REAS
; 
1084         /* Enforce a minimum ttl, may cause endless packet loops */ 
1085         if (r
->min_ttl 
&& h
->ip_ttl 
< r
->min_ttl
) { 
1086                 u_int16_t ip_ttl 
= h
->ip_ttl
; 
1088                 h
->ip_ttl 
= r
->min_ttl
; 
1089                 h
->ip_sum 
= pf_cksum_fixup(h
->ip_sum
, ip_ttl
, h
->ip_ttl
, 0); 
1091         if ((r
->rule_flag 
& (PFRULE_FRAGCROP
|PFRULE_FRAGDROP
)) == 0) 
1092                 pd
->flags 
|= PFDESC_IP_REAS
; 
1096         REASON_SET(reason
, PFRES_MEMORY
); 
1097         if (r 
!= NULL 
&& r
->log
) 
1098                 PFLOG_PACKET(kif
, h
, m
, AF_INET
, dir
, *reason
, r
, 
1103         REASON_SET(reason
, PFRES_NORM
); 
1104         if (r 
!= NULL 
&& r
->log
) 
1105                 PFLOG_PACKET(kif
, h
, m
, AF_INET
, dir
, *reason
, r
, 
1110         DPFPRINTF(("dropping bad fragment\n")); 
1112         /* Free associated fragments */ 
1114                 pf_free_fragment(frag
); 
1116         REASON_SET(reason
, PFRES_FRAG
); 
1117         if (r 
!= NULL 
&& r
->log
) 
1118                 PFLOG_PACKET(kif
, h
, m
, AF_INET
, dir
, *reason
, r
, NULL
, NULL
, pd
); 
1125 pf_normalize_ip6(struct mbuf 
**m0
, int dir
, struct pfi_kif 
*kif
, 
1126     u_short 
*reason
, struct pf_pdesc 
*pd
) 
1128         struct mbuf             
*m 
= *m0
; 
1130         struct ip6_hdr          
*h 
= mtod(m
, struct ip6_hdr 
*); 
1136         struct ip6_opt_jumbo     jumbo
; 
1140         struct ip6_frag          frag
; 
1141         u_int32_t                jumbolen 
= 0, plen
; 
1142         u_int16_t                fragoff 
= 0; 
1146         r 
= TAILQ_FIRST(pf_main_ruleset
.rules
[PF_RULESET_SCRUB
].active
.ptr
); 
1149                 if (pfi_kif_match(r
->kif
, kif
) == r
->ifnot
) 
1150                         r 
= r
->skip
[PF_SKIP_IFP
].ptr
; 
1151                 else if (r
->direction 
&& r
->direction 
!= dir
) 
1152                         r 
= r
->skip
[PF_SKIP_DIR
].ptr
; 
1153                 else if (r
->af 
&& r
->af 
!= AF_INET6
) 
1154                         r 
= r
->skip
[PF_SKIP_AF
].ptr
; 
1155 #if 0 /* header chain! */ 
1156                 else if (r
->proto 
&& r
->proto 
!= h
->ip6_nxt
) 
1157                         r 
= r
->skip
[PF_SKIP_PROTO
].ptr
; 
1159                 else if (PF_MISMATCHAW(&r
->src
.addr
, 
1160                     (struct pf_addr 
*)&h
->ip6_src
, AF_INET6
, 
1162                         r 
= r
->skip
[PF_SKIP_SRC_ADDR
].ptr
; 
1163                 else if (PF_MISMATCHAW(&r
->dst
.addr
, 
1164                     (struct pf_addr 
*)&h
->ip6_dst
, AF_INET6
, 
1166                         r 
= r
->skip
[PF_SKIP_DST_ADDR
].ptr
; 
1171         if (r 
== NULL 
|| r
->action 
== PF_NOSCRUB
) 
1174                 r
->packets
[dir 
== PF_OUT
]++; 
1175                 r
->bytes
[dir 
== PF_OUT
] += pd
->tot_len
; 
1178         /* Check for illegal packets */ 
1179         if ((int)(sizeof (struct ip6_hdr
) + IPV6_MAXPACKET
) < m
->m_pkthdr
.len
) 
1182         off 
= sizeof (struct ip6_hdr
); 
1187                 case IPPROTO_FRAGMENT
: 
1191                 case IPPROTO_ROUTING
: 
1192                 case IPPROTO_DSTOPTS
: 
1193                         if (!pf_pull_hdr(m
, off
, &ext
, sizeof (ext
), NULL
, 
1196 #ifndef NO_APPLE_EXTENSIONS 
1199                          * Routing header type zero considered harmful. 
1201                         if (proto 
== IPPROTO_ROUTING
) { 
1202                                 const struct ip6_rthdr 
*rh 
= 
1203                                     (const struct ip6_rthdr 
*)&ext
; 
1204                                 if (rh
->ip6r_type 
== IPV6_RTHDR_TYPE_0
) 
1209                         if (proto 
== IPPROTO_AH
) 
1210                                 off 
+= (ext
.ip6e_len 
+ 2) * 4; 
1212                                 off 
+= (ext
.ip6e_len 
+ 1) * 8; 
1213                         proto 
= ext
.ip6e_nxt
; 
1215                 case IPPROTO_HOPOPTS
: 
1218                         if (!pf_pull_hdr(m
, off
, &ext
, sizeof (ext
), NULL
, 
1221                         optend 
= off 
+ (ext
.ip6e_len 
+ 1) * 8; 
1222                         ooff 
= off 
+ sizeof (ext
); 
1224                                 if (!pf_pull_hdr(m
, ooff
, &opt
.ip6o_type
, 
1225                                     sizeof (opt
.ip6o_type
), NULL
, NULL
, 
1228                                 if (opt
.ip6o_type 
== IP6OPT_PAD1
) { 
1232                                 if (!pf_pull_hdr(m
, ooff
, &opt
, sizeof (opt
), 
1233                                     NULL
, NULL
, AF_INET6
)) 
1235                                 if (ooff 
+ sizeof (opt
) + opt
.ip6o_len 
> optend
) 
1237                                 switch (opt
.ip6o_type
) { 
1239                                         if (h
->ip6_plen 
!= 0) 
1241                                         if (!pf_pull_hdr(m
, ooff
, &jumbo
, 
1242                                             sizeof (jumbo
), NULL
, NULL
, 
1245                                         memcpy(&jumbolen
, jumbo
.ip6oj_jumbo_len
, 
1247                                         jumbolen 
= ntohl(jumbolen
); 
1248                                         if (jumbolen 
<= IPV6_MAXPACKET
) 
1250                                         if (sizeof (struct ip6_hdr
) + 
1251                                             jumbolen 
!= m
->m_pkthdr
.len
) 
1257                                 ooff 
+= sizeof (opt
) + opt
.ip6o_len
; 
1258                         } while (ooff 
< optend
); 
1261                         proto 
= ext
.ip6e_nxt
; 
1268         } while (!terminal
); 
1270         /* jumbo payload option must be present, or plen > 0 */ 
1271         if (ntohs(h
->ip6_plen
) == 0) 
1274                 plen 
= ntohs(h
->ip6_plen
); 
1277         if ((int)(sizeof (struct ip6_hdr
) + plen
) > m
->m_pkthdr
.len
) 
1280         /* Enforce a minimum ttl, may cause endless packet loops */ 
1281         if (r
->min_ttl 
&& h
->ip6_hlim 
< r
->min_ttl
) 
1282                 h
->ip6_hlim 
= r
->min_ttl
; 
1287         if (ntohs(h
->ip6_plen
) == 0 || jumbolen
) 
1289         plen 
= ntohs(h
->ip6_plen
); 
1291         if (!pf_pull_hdr(m
, off
, &frag
, sizeof (frag
), NULL
, NULL
, AF_INET6
)) 
1293         fragoff 
= ntohs(frag
.ip6f_offlg 
& IP6F_OFF_MASK
); 
1294         if (fragoff 
+ (plen 
- off 
- sizeof (frag
)) > IPV6_MAXPACKET
) 
1297         /* do something about it */ 
1298         /* remember to set pd->flags |= PFDESC_IP_REAS */ 
1302         REASON_SET(reason
, PFRES_SHORT
); 
1303         if (r 
!= NULL 
&& r
->log
) 
1304                 PFLOG_PACKET(kif
, h
, m
, AF_INET6
, dir
, *reason
, r
, 
1309         REASON_SET(reason
, PFRES_NORM
); 
1310         if (r 
!= NULL 
&& r
->log
) 
1311                 PFLOG_PACKET(kif
, h
, m
, AF_INET6
, dir
, *reason
, r
, 
1316         REASON_SET(reason
, PFRES_FRAG
); 
1317         if (r 
!= NULL 
&& r
->log
) 
1318                 PFLOG_PACKET(kif
, h
, m
, AF_INET6
, dir
, *reason
, r
, 
1325 pf_normalize_tcp(int dir
, struct pfi_kif 
*kif
, struct mbuf 
*m
, int ipoff
, 
1326     int off
, void *h
, struct pf_pdesc 
*pd
) 
1328 #pragma unused(ipoff, h) 
1329         struct pf_rule  
*r
, *rm 
= NULL
; 
1330         struct tcphdr   
*th 
= pd
->hdr
.tcp
; 
1334         sa_family_t      af 
= pd
->af
; 
1335 #ifndef NO_APPLE_EXTENSIONS 
1336         union pf_state_xport sxport
, dxport
; 
1338         sxport
.port 
= th
->th_sport
; 
1339         dxport
.port 
= th
->th_dport
; 
1342         r 
= TAILQ_FIRST(pf_main_ruleset
.rules
[PF_RULESET_SCRUB
].active
.ptr
); 
1345                 if (pfi_kif_match(r
->kif
, kif
) == r
->ifnot
) 
1346                         r 
= r
->skip
[PF_SKIP_IFP
].ptr
; 
1347                 else if (r
->direction 
&& r
->direction 
!= dir
) 
1348                         r 
= r
->skip
[PF_SKIP_DIR
].ptr
; 
1349                 else if (r
->af 
&& r
->af 
!= af
) 
1350                         r 
= r
->skip
[PF_SKIP_AF
].ptr
; 
1351                 else if (r
->proto 
&& r
->proto 
!= pd
->proto
) 
1352                         r 
= r
->skip
[PF_SKIP_PROTO
].ptr
; 
1353                 else if (PF_MISMATCHAW(&r
->src
.addr
, pd
->src
, af
, 
1355                         r 
= r
->skip
[PF_SKIP_SRC_ADDR
].ptr
; 
1356 #ifndef NO_APPLE_EXTENSIONS 
1357                 else if (r
->src
.xport
.range
.op 
&& 
1358                     !pf_match_xport(r
->src
.xport
.range
.op
, r
->proto_variant
, 
1359                     &r
->src
.xport
, &sxport
)) 
1361                 else if (r
->src
.port_op 
&& !pf_match_port(r
->src
.port_op
, 
1362                     r
->src
.port
[0], r
->src
.port
[1], th
->th_sport
)) 
1364                         r 
= r
->skip
[PF_SKIP_SRC_PORT
].ptr
; 
1365                 else if (PF_MISMATCHAW(&r
->dst
.addr
, pd
->dst
, af
, 
1367                         r 
= r
->skip
[PF_SKIP_DST_ADDR
].ptr
; 
1368 #ifndef NO_APPLE_EXTENSIONS 
1369                 else if (r
->dst
.xport
.range
.op 
&& 
1370                     !pf_match_xport(r
->dst
.xport
.range
.op
, r
->proto_variant
, 
1371                     &r
->dst
.xport
, &dxport
)) 
1373                 else if (r
->dst
.port_op 
&& !pf_match_port(r
->dst
.port_op
, 
1374                     r
->dst
.port
[0], r
->dst
.port
[1], th
->th_dport
)) 
1376                         r 
= r
->skip
[PF_SKIP_DST_PORT
].ptr
; 
1377                 else if (r
->os_fingerprint 
!= PF_OSFP_ANY 
&& 
1378                     !pf_osfp_match(pf_osfp_fingerprint(pd
, m
, off
, th
), 
1380                         r 
= TAILQ_NEXT(r
, entries
); 
1387         if (rm 
== NULL 
|| rm
->action 
== PF_NOSCRUB
) 
1390                 r
->packets
[dir 
== PF_OUT
]++; 
1391                 r
->bytes
[dir 
== PF_OUT
] += pd
->tot_len
; 
1394         if (rm
->rule_flag 
& PFRULE_REASSEMBLE_TCP
) 
1395                 pd
->flags 
|= PFDESC_TCP_NORM
; 
1397         flags 
= th
->th_flags
; 
1398         if (flags 
& TH_SYN
) { 
1399                 /* Illegal packet */ 
1406                 /* Illegal packet */ 
1407                 if (!(flags 
& (TH_ACK
|TH_RST
))) 
1411         if (!(flags 
& TH_ACK
)) { 
1412                 /* These flags are only valid if ACK is set */ 
1413                 if ((flags 
& TH_FIN
) || (flags 
& TH_PUSH
) || (flags 
& TH_URG
)) 
1417         /* Check for illegal header length */ 
1418         if (th
->th_off 
< (sizeof (struct tcphdr
) >> 2)) 
1421         /* If flags changed, or reserved data set, then adjust */ 
1422         if (flags 
!= th
->th_flags 
|| th
->th_x2 
!= 0) { 
1425                 ov 
= *(u_int16_t 
*)(&th
->th_ack 
+ 1); 
1426                 th
->th_flags 
= flags
; 
1428                 nv 
= *(u_int16_t 
*)(&th
->th_ack 
+ 1); 
1430                 th
->th_sum 
= pf_cksum_fixup(th
->th_sum
, ov
, nv
, 0); 
1434         /* Remove urgent pointer, if TH_URG is not set */ 
1435         if (!(flags 
& TH_URG
) && th
->th_urp
) { 
1436                 th
->th_sum 
= pf_cksum_fixup(th
->th_sum
, th
->th_urp
, 0, 0); 
1441         /* copy back packet headers if we sanitized */ 
1442 #ifndef NO_APPLE_EXTENSIONS 
1443         /* Process options */ 
1445                 int rv 
= pf_normalize_tcpopt(r
, dir
, kif
, pd
, m
, th
, off
, 
1453                 struct mbuf 
*mw 
= pf_lazy_makewritable(pd
, m
, 
1454                     off 
+ sizeof (*th
)); 
1456                         REASON_SET(&reason
, PFRES_MEMORY
); 
1458                                 PFLOG_PACKET(kif
, h
, m
, AF_INET
, dir
, reason
, 
1463                 m_copyback(mw
, off
, sizeof (*th
), th
); 
1466         /* Process options */ 
1467         if (r
->max_mss 
&& pf_normalize_tcpopt(r
, m
, th
, off
, pd
->af
)) 
1471                 m_copyback(m
, off
, sizeof (*th
), th
); 
1477         REASON_SET(&reason
, PFRES_NORM
); 
1478         if (rm 
!= NULL 
&& r
->log
) 
1479                 PFLOG_PACKET(kif
, h
, m
, AF_INET
, dir
, reason
, r
, NULL
, NULL
, pd
); 
1484 pf_normalize_tcp_init(struct mbuf 
*m
, int off
, struct pf_pdesc 
*pd
, 
1485     struct tcphdr 
*th
, struct pf_state_peer 
*src
, struct pf_state_peer 
*dst
) 
1488         u_int32_t tsval
, tsecr
; 
1492         VERIFY(src
->scrub 
== NULL
); 
1494         src
->scrub 
= pool_get(&pf_state_scrub_pl
, PR_NOWAIT
); 
1495         if (src
->scrub 
== NULL
) 
1497         bzero(src
->scrub
, sizeof (*src
->scrub
)); 
1502                 struct ip 
*h 
= mtod(m
, struct ip 
*); 
1503                 src
->scrub
->pfss_ttl 
= h
->ip_ttl
; 
1509                 struct ip6_hdr 
*h 
= mtod(m
, struct ip6_hdr 
*); 
1510                 src
->scrub
->pfss_ttl 
= h
->ip6_hlim
; 
1518          * All normalizations below are only begun if we see the start of 
1519          * the connections.  They must all set an enabled bit in pfss_flags 
1521         if ((th
->th_flags 
& TH_SYN
) == 0) 
1525         if (th
->th_off 
> (sizeof (struct tcphdr
) >> 2) && src
->scrub 
&& 
1526             pf_pull_hdr(m
, off
, hdr
, th
->th_off 
<< 2, NULL
, NULL
, pd
->af
)) { 
1527                 /* Diddle with TCP options */ 
1529                 opt 
= hdr 
+ sizeof (struct tcphdr
); 
1530                 hlen 
= (th
->th_off 
<< 2) - sizeof (struct tcphdr
); 
1531                 while (hlen 
>= TCPOLEN_TIMESTAMP
) { 
1533                         case TCPOPT_EOL
:        /* FALLTHROUGH */ 
1538                         case TCPOPT_TIMESTAMP
: 
1539                                 if (opt
[1] >= TCPOLEN_TIMESTAMP
) { 
1540                                         src
->scrub
->pfss_flags 
|= 
1542                                         src
->scrub
->pfss_ts_mod 
= 
1545                                         /* note PFSS_PAWS not set yet */ 
1546                                         memcpy(&tsval
, &opt
[2], 
1547                                             sizeof (u_int32_t
)); 
1548                                         memcpy(&tsecr
, &opt
[6], 
1549                                             sizeof (u_int32_t
)); 
1550                                         src
->scrub
->pfss_tsval0 
= ntohl(tsval
); 
1551                                         src
->scrub
->pfss_tsval 
= ntohl(tsval
); 
1552                                         src
->scrub
->pfss_tsecr 
= ntohl(tsecr
); 
1553                                         getmicrouptime(&src
->scrub
->pfss_last
); 
1557                                 hlen 
-= MAX(opt
[1], 2); 
1558                                 opt 
+= MAX(opt
[1], 2); 
1568 pf_normalize_tcp_cleanup(struct pf_state 
*state
) 
1570         if (state
->src
.scrub
) 
1571                 pool_put(&pf_state_scrub_pl
, state
->src
.scrub
); 
1572         if (state
->dst
.scrub
) 
1573                 pool_put(&pf_state_scrub_pl
, state
->dst
.scrub
); 
1575         /* Someday... flush the TCP segment reassembly descriptors. */ 
1579 pf_normalize_tcp_stateful(struct mbuf 
*m
, int off
, struct pf_pdesc 
*pd
, 
1580     u_short 
*reason
, struct tcphdr 
*th
, struct pf_state 
*state
, 
1581     struct pf_state_peer 
*src
, struct pf_state_peer 
*dst
, int *writeback
) 
1583         struct timeval uptime
; 
1584         u_int32_t tsval
, tsecr
; 
1585         u_int tsval_from_last
; 
1591         VERIFY(src
->scrub 
|| dst
->scrub
); 
1594          * Enforce the minimum TTL seen for this connection.  Negate a common 
1595          * technique to evade an intrusion detection system and confuse 
1596          * firewall state code. 
1602                         struct ip 
*h 
= mtod(m
, struct ip 
*); 
1603                         if (h
->ip_ttl 
> src
->scrub
->pfss_ttl
) 
1604                                 src
->scrub
->pfss_ttl 
= h
->ip_ttl
; 
1605                         h
->ip_ttl 
= src
->scrub
->pfss_ttl
; 
1613                         struct ip6_hdr 
*h 
= mtod(m
, struct ip6_hdr 
*); 
1614                         if (h
->ip6_hlim 
> src
->scrub
->pfss_ttl
) 
1615                                 src
->scrub
->pfss_ttl 
= h
->ip6_hlim
; 
1616                         h
->ip6_hlim 
= src
->scrub
->pfss_ttl
; 
1623         if (th
->th_off 
> (sizeof (struct tcphdr
) >> 2) && 
1624             ((src
->scrub 
&& (src
->scrub
->pfss_flags 
& PFSS_TIMESTAMP
)) || 
1625             (dst
->scrub 
&& (dst
->scrub
->pfss_flags 
& PFSS_TIMESTAMP
))) && 
1626             pf_pull_hdr(m
, off
, hdr
, th
->th_off 
<< 2, NULL
, NULL
, pd
->af
)) { 
1627                 /* Diddle with TCP options */ 
1629                 opt 
= hdr 
+ sizeof (struct tcphdr
); 
1630                 hlen 
= (th
->th_off 
<< 2) - sizeof (struct tcphdr
); 
1631                 while (hlen 
>= TCPOLEN_TIMESTAMP
) { 
1633                         case TCPOPT_EOL
:        /* FALLTHROUGH */ 
1638                         case TCPOPT_TIMESTAMP
: 
1640                                  * Modulate the timestamps.  Can be used for 
1641                                  * NAT detection, OS uptime determination or 
1646                                         /* Huh?  Multiple timestamps!? */ 
1647                                         if (pf_status
.debug 
>= PF_DEBUG_MISC
) { 
1648                                                 DPFPRINTF(("multiple TS??")); 
1649                                                 pf_print_state(state
); 
1652                                         REASON_SET(reason
, PFRES_TS
); 
1655                                 if (opt
[1] >= TCPOLEN_TIMESTAMP
) { 
1656                                         memcpy(&tsval
, &opt
[2], 
1657                                             sizeof (u_int32_t
)); 
1658                                         if (tsval 
&& src
->scrub 
&& 
1659                                             (src
->scrub
->pfss_flags 
& 
1661                                                 tsval 
= ntohl(tsval
); 
1662                                                 pf_change_a(&opt
[2], 
1665                                                     src
->scrub
->pfss_ts_mod
), 
1670                                         /* Modulate TS reply iff valid (!0) */ 
1671                                         memcpy(&tsecr
, &opt
[6], 
1672                                             sizeof (u_int32_t
)); 
1673                                         if (tsecr 
&& dst
->scrub 
&& 
1674                                             (dst
->scrub
->pfss_flags 
& 
1676                                                 tsecr 
= ntohl(tsecr
) 
1677                                                     - dst
->scrub
->pfss_ts_mod
; 
1678                                                 pf_change_a(&opt
[6], 
1679                                                     &th
->th_sum
, htonl(tsecr
), 
1687                                 hlen 
-= MAX(opt
[1], 2); 
1688                                 opt 
+= MAX(opt
[1], 2); 
1693                         /* Copyback the options, caller copys back header */ 
1694 #ifndef NO_APPLE_EXTENSIONS 
1695                         int optoff 
= off 
+ sizeof (*th
); 
1696                         int optlen 
= (th
->th_off 
<< 2) - sizeof (*th
); 
1697                         m 
= pf_lazy_makewritable(pd
, m
, optoff 
+ optlen
); 
1699                                 REASON_SET(reason
, PFRES_MEMORY
); 
1702                         *writeback 
= optoff 
+ optlen
; 
1703                         m_copyback(m
, optoff
, optlen
, hdr 
+ sizeof (*th
)); 
1706                         m_copyback(m
, off 
+ sizeof (struct tcphdr
), 
1707                             (th
->th_off 
<< 2) - sizeof (struct tcphdr
), hdr 
+ 
1708                             sizeof (struct tcphdr
)); 
1715          * Must invalidate PAWS checks on connections idle for too long. 
1716          * The fastest allowed timestamp clock is 1ms.  That turns out to 
1717          * be about 24 days before it wraps.  XXX Right now our lowerbound 
1718          * TS echo check only works for the first 12 days of a connection 
1719          * when the TS has exhausted half its 32bit space 
1721 #define TS_MAX_IDLE     (24*24*60*60) 
1722 #define TS_MAX_CONN     (12*24*60*60)   /* XXX remove when better tsecr check */ 
1724         getmicrouptime(&uptime
); 
1725         if (src
->scrub 
&& (src
->scrub
->pfss_flags 
& PFSS_PAWS
) && 
1726             (uptime
.tv_sec 
- src
->scrub
->pfss_last
.tv_sec 
> TS_MAX_IDLE 
|| 
1727             pf_time_second() - state
->creation 
> TS_MAX_CONN
))  { 
1728                 if (pf_status
.debug 
>= PF_DEBUG_MISC
) { 
1729                         DPFPRINTF(("src idled out of PAWS\n")); 
1730                         pf_print_state(state
); 
1733                 src
->scrub
->pfss_flags 
= (src
->scrub
->pfss_flags 
& ~PFSS_PAWS
) 
1736         if (dst
->scrub 
&& (dst
->scrub
->pfss_flags 
& PFSS_PAWS
) && 
1737             uptime
.tv_sec 
- dst
->scrub
->pfss_last
.tv_sec 
> TS_MAX_IDLE
) { 
1738                 if (pf_status
.debug 
>= PF_DEBUG_MISC
) { 
1739                         DPFPRINTF(("dst idled out of PAWS\n")); 
1740                         pf_print_state(state
); 
1743                 dst
->scrub
->pfss_flags 
= (dst
->scrub
->pfss_flags 
& ~PFSS_PAWS
) 
1747         if (got_ts 
&& src
->scrub 
&& dst
->scrub 
&& 
1748             (src
->scrub
->pfss_flags 
& PFSS_PAWS
) && 
1749             (dst
->scrub
->pfss_flags 
& PFSS_PAWS
)) { 
1751                  * Validate that the timestamps are "in-window". 
1752                  * RFC1323 describes TCP Timestamp options that allow 
1753                  * measurement of RTT (round trip time) and PAWS 
1754                  * (protection against wrapped sequence numbers).  PAWS 
1755                  * gives us a set of rules for rejecting packets on 
1756                  * long fat pipes (packets that were somehow delayed 
1757                  * in transit longer than the time it took to send the 
1758                  * full TCP sequence space of 4Gb).  We can use these 
1759                  * rules and infer a few others that will let us treat 
1760                  * the 32bit timestamp and the 32bit echoed timestamp 
1761                  * as sequence numbers to prevent a blind attacker from 
1762                  * inserting packets into a connection. 
1765                  *  - The timestamp on this packet must be greater than 
1766                  *    or equal to the last value echoed by the other 
1767                  *    endpoint.  The RFC says those will be discarded 
1768                  *    since it is a dup that has already been acked. 
1769                  *    This gives us a lowerbound on the timestamp. 
1770                  *        timestamp >= other last echoed timestamp 
1771                  *  - The timestamp will be less than or equal to 
1772                  *    the last timestamp plus the time between the 
1773                  *    last packet and now.  The RFC defines the max 
1774                  *    clock rate as 1ms.  We will allow clocks to be 
1775                  *    up to 10% fast and will allow a total difference 
1776                  *    or 30 seconds due to a route change.  And this 
1777                  *    gives us an upperbound on the timestamp. 
1778                  *        timestamp <= last timestamp + max ticks 
1779                  *    We have to be careful here.  Windows will send an 
1780                  *    initial timestamp of zero and then initialize it 
1781                  *    to a random value after the 3whs; presumably to 
1782                  *    avoid a DoS by having to call an expensive RNG 
1783                  *    during a SYN flood.  Proof MS has at least one 
1784                  *    good security geek. 
1786                  *  - The TCP timestamp option must also echo the other 
1787                  *    endpoints timestamp.  The timestamp echoed is the 
1788                  *    one carried on the earliest unacknowledged segment 
1789                  *    on the left edge of the sequence window.  The RFC 
1790                  *    states that the host will reject any echoed 
1791                  *    timestamps that were larger than any ever sent. 
1792                  *    This gives us an upperbound on the TS echo. 
1793                  *        tescr <= largest_tsval 
1794                  *  - The lowerbound on the TS echo is a little more 
1795                  *    tricky to determine.  The other endpoint's echoed 
1796                  *    values will not decrease.  But there may be 
1797                  *    network conditions that re-order packets and 
1798                  *    cause our view of them to decrease.  For now the 
1799                  *    only lowerbound we can safely determine is that 
1800                  *    the TS echo will never be less than the original 
1801                  *    TS.  XXX There is probably a better lowerbound. 
1802                  *    Remove TS_MAX_CONN with better lowerbound check. 
1803                  *        tescr >= other original TS 
1805                  * It is also important to note that the fastest 
1806                  * timestamp clock of 1ms will wrap its 32bit space in 
1807                  * 24 days.  So we just disable TS checking after 24 
1808                  * days of idle time.  We actually must use a 12d 
1809                  * connection limit until we can come up with a better 
1810                  * lowerbound to the TS echo check. 
1812                 struct timeval delta_ts
; 
1817                  * PFTM_TS_DIFF is how many seconds of leeway to allow 
1818                  * a host's timestamp.  This can happen if the previous 
1819                  * packet got delayed in transit for much longer than 
1822                 if ((ts_fudge 
= state
->rule
.ptr
->timeout
[PFTM_TS_DIFF
]) == 0) 
1823                         ts_fudge 
= pf_default_rule
.timeout
[PFTM_TS_DIFF
]; 
1826                 /* Calculate max ticks since the last timestamp */ 
1827 #define TS_MAXFREQ      1100            /* RFC max TS freq of 1Khz + 10% skew */ 
1828 #define TS_MICROSECS    1000000         /* microseconds per second */ 
1829                 timersub(&uptime
, &src
->scrub
->pfss_last
, &delta_ts
); 
1830                 tsval_from_last 
= (delta_ts
.tv_sec 
+ ts_fudge
) * TS_MAXFREQ
; 
1831                 tsval_from_last 
+= delta_ts
.tv_usec 
/ (TS_MICROSECS
/TS_MAXFREQ
); 
1834                 if ((src
->state 
>= TCPS_ESTABLISHED 
&& 
1835                     dst
->state 
>= TCPS_ESTABLISHED
) && 
1836                     (SEQ_LT(tsval
, dst
->scrub
->pfss_tsecr
) || 
1837                     SEQ_GT(tsval
, src
->scrub
->pfss_tsval 
+ tsval_from_last
) || 
1838                     (tsecr 
&& (SEQ_GT(tsecr
, dst
->scrub
->pfss_tsval
) || 
1839                     SEQ_LT(tsecr
, dst
->scrub
->pfss_tsval0
))))) { 
1841                          * Bad RFC1323 implementation or an insertion attack. 
1843                          * - Solaris 2.6 and 2.7 are known to send another ACK 
1844                          *   after the FIN,FIN|ACK,ACK closing that carries 
1848                         DPFPRINTF(("Timestamp failed %c%c%c%c\n", 
1849                             SEQ_LT(tsval
, dst
->scrub
->pfss_tsecr
) ? '0' : ' ', 
1850                             SEQ_GT(tsval
, src
->scrub
->pfss_tsval 
+ 
1851                             tsval_from_last
) ? '1' : ' ', 
1852                             SEQ_GT(tsecr
, dst
->scrub
->pfss_tsval
) ? '2' : ' ', 
1853                             SEQ_LT(tsecr
, dst
->scrub
->pfss_tsval0
)? '3' : ' ')); 
1854                         DPFPRINTF((" tsval: %u  tsecr: %u  +ticks: %u  " 
1855                             "idle: %lus %ums\n", 
1856                             tsval
, tsecr
, tsval_from_last
, delta_ts
.tv_sec
, 
1857                             delta_ts
.tv_usec 
/ 1000)); 
1858                         DPFPRINTF((" src->tsval: %u  tsecr: %u\n", 
1859                             src
->scrub
->pfss_tsval
, src
->scrub
->pfss_tsecr
)); 
1860                         DPFPRINTF((" dst->tsval: %u  tsecr: %u  tsval0: %u\n", 
1861                             dst
->scrub
->pfss_tsval
, dst
->scrub
->pfss_tsecr
, 
1862                             dst
->scrub
->pfss_tsval0
)); 
1863                         if (pf_status
.debug 
>= PF_DEBUG_MISC
) { 
1864                                 pf_print_state(state
); 
1865                                 pf_print_flags(th
->th_flags
); 
1868                         REASON_SET(reason
, PFRES_TS
); 
1872                 /* XXX I'd really like to require tsecr but it's optional */ 
1874         } else if (!got_ts 
&& (th
->th_flags 
& TH_RST
) == 0 && 
1875             ((src
->state 
== TCPS_ESTABLISHED 
&& dst
->state 
== TCPS_ESTABLISHED
) 
1876             || pd
->p_len 
> 0 || (th
->th_flags 
& TH_SYN
)) && 
1877             src
->scrub 
&& dst
->scrub 
&& 
1878             (src
->scrub
->pfss_flags 
& PFSS_PAWS
) && 
1879             (dst
->scrub
->pfss_flags 
& PFSS_PAWS
)) { 
1881                  * Didn't send a timestamp.  Timestamps aren't really useful 
1883                  *  - connection opening or closing (often not even sent). 
1884                  *    but we must not let an attacker to put a FIN on a 
1885                  *    data packet to sneak it through our ESTABLISHED check. 
1886                  *  - on a TCP reset.  RFC suggests not even looking at TS. 
1887                  *  - on an empty ACK.  The TS will not be echoed so it will 
1888                  *    probably not help keep the RTT calculation in sync and 
1889                  *    there isn't as much danger when the sequence numbers 
1890                  *    got wrapped.  So some stacks don't include TS on empty 
1893                  * To minimize the disruption to mostly RFC1323 conformant 
1894                  * stacks, we will only require timestamps on data packets. 
1896                  * And what do ya know, we cannot require timestamps on data 
1897                  * packets.  There appear to be devices that do legitimate 
1898                  * TCP connection hijacking.  There are HTTP devices that allow 
1899                  * a 3whs (with timestamps) and then buffer the HTTP request. 
1900                  * If the intermediate device has the HTTP response cache, it 
1901                  * will spoof the response but not bother timestamping its 
1902                  * packets.  So we can look for the presence of a timestamp in 
1903                  * the first data packet and if there, require it in all future 
1907                 if (pd
->p_len 
> 0 && (src
->scrub
->pfss_flags 
& PFSS_DATA_TS
)) { 
1909                          * Hey!  Someone tried to sneak a packet in.  Or the 
1910                          * stack changed its RFC1323 behavior?!?! 
1912                         if (pf_status
.debug 
>= PF_DEBUG_MISC
) { 
1913                                 DPFPRINTF(("Did not receive expected RFC1323 " 
1915                                 pf_print_state(state
); 
1916                                 pf_print_flags(th
->th_flags
); 
1919                         REASON_SET(reason
, PFRES_TS
); 
1926          * We will note if a host sends his data packets with or without 
1927          * timestamps.  And require all data packets to contain a timestamp 
1928          * if the first does.  PAWS implicitly requires that all data packets be 
1929          * timestamped.  But I think there are middle-man devices that hijack 
1930          * TCP streams immediately after the 3whs and don't timestamp their 
1931          * packets (seen in a WWW accelerator or cache). 
1933         if (pd
->p_len 
> 0 && src
->scrub 
&& (src
->scrub
->pfss_flags 
& 
1934             (PFSS_TIMESTAMP
|PFSS_DATA_TS
|PFSS_DATA_NOTS
)) == PFSS_TIMESTAMP
) { 
1936                         src
->scrub
->pfss_flags 
|= PFSS_DATA_TS
; 
1938                         src
->scrub
->pfss_flags 
|= PFSS_DATA_NOTS
; 
1939                         if (pf_status
.debug 
>= PF_DEBUG_MISC 
&& dst
->scrub 
&& 
1940                             (dst
->scrub
->pfss_flags 
& PFSS_TIMESTAMP
)) { 
1941                                 /* Don't warn if other host rejected RFC1323 */ 
1942                                 DPFPRINTF(("Broken RFC1323 stack did not " 
1943                                     "timestamp data packet. Disabled PAWS " 
1945                                 pf_print_state(state
); 
1946                                 pf_print_flags(th
->th_flags
); 
1954          * Update PAWS values 
1956         if (got_ts 
&& src
->scrub 
&& PFSS_TIMESTAMP 
== (src
->scrub
->pfss_flags 
& 
1957             (PFSS_PAWS_IDLED
|PFSS_TIMESTAMP
))) { 
1958                 getmicrouptime(&src
->scrub
->pfss_last
); 
1959                 if (SEQ_GEQ(tsval
, src
->scrub
->pfss_tsval
) || 
1960                     (src
->scrub
->pfss_flags 
& PFSS_PAWS
) == 0) 
1961                         src
->scrub
->pfss_tsval 
= tsval
; 
1964                         if (SEQ_GEQ(tsecr
, src
->scrub
->pfss_tsecr
) || 
1965                             (src
->scrub
->pfss_flags 
& PFSS_PAWS
) == 0) 
1966                                 src
->scrub
->pfss_tsecr 
= tsecr
; 
1968                         if ((src
->scrub
->pfss_flags 
& PFSS_PAWS
) == 0 && 
1969                             (SEQ_LT(tsval
, src
->scrub
->pfss_tsval0
) || 
1970                             src
->scrub
->pfss_tsval0 
== 0)) { 
1971                                 /* tsval0 MUST be the lowest timestamp */ 
1972                                 src
->scrub
->pfss_tsval0 
= tsval
; 
1975                         /* Only fully initialized after a TS gets echoed */ 
1976                         if ((src
->scrub
->pfss_flags 
& PFSS_PAWS
) == 0) 
1977                                 src
->scrub
->pfss_flags 
|= PFSS_PAWS
; 
1981         /* I have a dream....  TCP segment reassembly.... */ 
1985 #ifndef NO_APPLE_EXTENSIONS 
1987 pf_normalize_tcpopt(struct pf_rule 
*r
, int dir
, struct pfi_kif 
*kif
, 
1988     struct pf_pdesc 
*pd
, struct mbuf 
*m
, struct tcphdr 
*th
, int off
, 
1991 #pragma unused(dir, kif) 
1992         sa_family_t af 
= pd
->af
; 
1995 pf_normalize_tcpopt(struct pf_rule 
*r
, struct mbuf 
*m
, struct tcphdr 
*th
, 
1996     int off
, sa_family_t af
) 
2001         int             opt
, cnt
, optlen 
= 0; 
2003         u_char          opts
[MAX_TCPOPTLEN
]; 
2004         u_char          
*optp 
= opts
; 
2006         thoff 
= th
->th_off 
<< 2; 
2007         cnt 
= thoff 
- sizeof (struct tcphdr
); 
2009 #ifndef NO_APPLE_MODIFICATIONS 
2010         if (cnt 
> 0 && !pf_pull_hdr(m
, off 
+ sizeof (*th
), opts
, cnt
, 
2014         if (cnt 
> 0 && !pf_pull_hdr(m
, off 
+ sizeof (*th
), opts
, cnt
, 
2019         for (; cnt 
> 0; cnt 
-= optlen
, optp 
+= optlen
) { 
2021                 if (opt 
== TCPOPT_EOL
) 
2023                 if (opt 
== TCPOPT_NOP
) 
2029                         if (optlen 
< 2 || optlen 
> cnt
) 
2034                         mss 
= (u_int16_t 
*)(optp 
+ 2); 
2035                         if ((ntohs(*mss
)) > r
->max_mss
) { 
2036 #ifndef NO_APPLE_MODIFICATIONS 
2039                                  *  Only do the TCP checksum fixup if delayed 
2040                                  * checksum calculation will not be performed. 
2042                                 if (m
->m_pkthdr
.rcvif 
|| 
2043                                     !(m
->m_pkthdr
.csum_flags 
& CSUM_TCP
)) 
2044                                         th
->th_sum 
= pf_cksum_fixup(th
->th_sum
, 
2045                                             *mss
, htons(r
->max_mss
), 0); 
2047                                 th
->th_sum 
= pf_cksum_fixup(th
->th_sum
, 
2048                                     *mss
, htons(r
->max_mss
), 0); 
2050                                 *mss 
= htons(r
->max_mss
); 
2059 #ifndef NO_APPLE_MODIFICATIONS 
2064                 mw 
= pf_lazy_makewritable(pd
, pd
->mp
, 
2065                     off 
+ sizeof (*th
) + thoff
); 
2067                         REASON_SET(&reason
, PFRES_MEMORY
); 
2069                                 PFLOG_PACKET(kif
, h
, m
, AF_INET
, dir
, reason
, 
2075                 m_copyback(mw
, off 
+ sizeof (*th
), thoff 
- sizeof (*th
), opts
); 
2081                 m_copyback(m
, off 
+ sizeof (*th
), thoff 
- sizeof (*th
), opts
);