1 /* $OpenBSD: pf_norm.c,v 1.75 2003/08/29 01:49:08 dhartmei Exp $ */ 2 3 /* 4 * Copyright 2001 Niels Provos <provos@citi.umich.edu> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include "pflog.h" 29 30 #include <sys/param.h> 31 #include <sys/systm.h> 32 #include <sys/mbuf.h> 33 #include <sys/filio.h> 34 #include <sys/fcntl.h> 35 #include <sys/socket.h> 36 #include <sys/kernel.h> 37 #include <sys/time.h> 38 #include <sys/pool.h> 39 40 #include <dev/rndvar.h> 41 #include <net/if.h> 42 #include <net/if_types.h> 43 #include <net/bpf.h> 44 #include <net/route.h> 45 #include <net/if_pflog.h> 46 47 #include <netinet/in.h> 48 #include <netinet/in_var.h> 49 #include <netinet/in_systm.h> 50 #include <netinet/ip.h> 51 #include <netinet/ip_var.h> 52 #include <netinet/tcp.h> 53 #include <netinet/tcp_seq.h> 54 #include <netinet/udp.h> 55 #include <netinet/ip_icmp.h> 56 57 #ifdef INET6 58 #include <netinet/ip6.h> 59 #endif /* INET6 */ 60 61 #include <net/pfvar.h> 62 63 struct pf_frent { 64 LIST_ENTRY(pf_frent) fr_next; 65 struct ip *fr_ip; 66 struct mbuf *fr_m; 67 }; 68 69 struct pf_frcache { 70 LIST_ENTRY(pf_frcache) fr_next; 71 uint16_t fr_off; 72 uint16_t fr_end; 73 }; 74 75 #define PFFRAG_SEENLAST 0x0001 /* Seen the last fragment for this */ 76 #define PFFRAG_NOBUFFER 0x0002 /* Non-buffering fragment cache */ 77 #define PFFRAG_DROP 0x0004 /* Drop all fragments */ 78 #define BUFFER_FRAGMENTS(fr) (!((fr)->fr_flags & PFFRAG_NOBUFFER)) 79 80 struct pf_fragment { 81 RB_ENTRY(pf_fragment) fr_entry; 82 TAILQ_ENTRY(pf_fragment) frag_next; 83 struct in_addr fr_src; 84 struct in_addr fr_dst; 85 u_int8_t fr_p; /* protocol of this fragment */ 86 u_int8_t fr_flags; /* status flags */ 87 u_int16_t fr_id; /* fragment id for reassemble */ 88 u_int16_t fr_max; /* fragment data max */ 89 u_int32_t fr_timeout; 90 #define fr_queue fr_u.fru_queue 91 #define fr_cache fr_u.fru_cache 92 union { 93 LIST_HEAD(pf_fragq, pf_frent) fru_queue; /* buffering */ 94 LIST_HEAD(pf_cacheq, pf_frcache) fru_cache; /* non-buf */ 95 } fr_u; 96 }; 97 98 TAILQ_HEAD(pf_fragqueue, pf_fragment) pf_fragqueue; 99 TAILQ_HEAD(pf_cachequeue, pf_fragment) pf_cachequeue; 100 101 static __inline int pf_frag_compare(struct pf_fragment *, 102 struct pf_fragment *); 103 RB_HEAD(pf_frag_tree, pf_fragment) pf_frag_tree, pf_cache_tree; 104 RB_PROTOTYPE(pf_frag_tree, pf_fragment, fr_entry, pf_frag_compare); 105 RB_GENERATE(pf_frag_tree, pf_fragment, fr_entry, pf_frag_compare); 106 107 /* Private prototypes */ 108 void pf_ip2key(struct pf_fragment *, struct ip *); 109 void pf_remove_fragment(struct pf_fragment *); 110 void pf_flush_fragments(void); 111 void pf_free_fragment(struct pf_fragment *); 112 struct pf_fragment *pf_find_fragment(struct ip *, struct pf_frag_tree *); 113 struct mbuf *pf_reassemble(struct mbuf **, struct pf_fragment **, 114 struct pf_frent *, int); 115 struct mbuf *pf_fragcache(struct mbuf **, struct ip*, 116 struct pf_fragment **, int, int, int *); 117 u_int16_t pf_cksum_fixup(u_int16_t, u_int16_t, u_int16_t); 118 int pf_normalize_tcpopt(struct pf_rule *, struct mbuf *, 119 struct tcphdr *, int); 120 121 #define DPFPRINTF(x) if (pf_status.debug >= PF_DEBUG_MISC) \ 122 { printf("%s: ", __func__); printf x ;} 123 124 /* Globals */ 125 struct pool pf_frent_pl, pf_frag_pl, pf_cache_pl, pf_cent_pl; 126 struct pool pf_state_scrub_pl; 127 int pf_nfrents, pf_ncache; 128 129 void 130 pf_normalize_init(void) 131 { 132 pool_init(&pf_frent_pl, sizeof(struct pf_frent), 0, 0, 0, "pffrent", 133 NULL); 134 pool_init(&pf_frag_pl, sizeof(struct pf_fragment), 0, 0, 0, "pffrag", 135 NULL); 136 pool_init(&pf_cache_pl, sizeof(struct pf_fragment), 0, 0, 0, 137 "pffrcache", NULL); 138 pool_init(&pf_cent_pl, sizeof(struct pf_frcache), 0, 0, 0, "pffrcent", 139 NULL); 140 pool_init(&pf_state_scrub_pl, sizeof(struct pf_state_scrub), 0, 0, 0, 141 "pfstscr", NULL); 142 143 pool_sethiwat(&pf_frag_pl, PFFRAG_FRAG_HIWAT); 144 pool_sethardlimit(&pf_frent_pl, PFFRAG_FRENT_HIWAT, NULL, 0); 145 pool_sethardlimit(&pf_cache_pl, PFFRAG_FRCACHE_HIWAT, NULL, 0); 146 pool_sethardlimit(&pf_cent_pl, PFFRAG_FRCENT_HIWAT, NULL, 0); 147 148 TAILQ_INIT(&pf_fragqueue); 149 TAILQ_INIT(&pf_cachequeue); 150 } 151 152 static __inline int 153 pf_frag_compare(struct pf_fragment *a, struct pf_fragment *b) 154 { 155 int diff; 156 157 if ((diff = a->fr_id - b->fr_id)) 158 return (diff); 159 else if ((diff = a->fr_p - b->fr_p)) 160 return (diff); 161 else if (a->fr_src.s_addr < b->fr_src.s_addr) 162 return (-1); 163 else if (a->fr_src.s_addr > b->fr_src.s_addr) 164 return (1); 165 else if (a->fr_dst.s_addr < b->fr_dst.s_addr) 166 return (-1); 167 else if (a->fr_dst.s_addr > b->fr_dst.s_addr) 168 return (1); 169 return (0); 170 } 171 172 void 173 pf_purge_expired_fragments(void) 174 { 175 struct pf_fragment *frag; 176 u_int32_t expire = time.tv_sec - 177 pf_default_rule.timeout[PFTM_FRAG]; 178 179 while ((frag = TAILQ_LAST(&pf_fragqueue, pf_fragqueue)) != NULL) { 180 KASSERT(BUFFER_FRAGMENTS(frag)); 181 if (frag->fr_timeout > expire) 182 break; 183 184 DPFPRINTF(("expiring %d(%p)\n", frag->fr_id, frag)); 185 pf_free_fragment(frag); 186 } 187 188 while ((frag = TAILQ_LAST(&pf_cachequeue, pf_cachequeue)) != NULL) { 189 KASSERT(!BUFFER_FRAGMENTS(frag)); 190 if (frag->fr_timeout > expire) 191 break; 192 193 DPFPRINTF(("expiring %d(%p)\n", frag->fr_id, frag)); 194 pf_free_fragment(frag); 195 KASSERT(TAILQ_EMPTY(&pf_cachequeue) || 196 TAILQ_LAST(&pf_cachequeue, pf_cachequeue) != frag); 197 } 198 } 199 200 /* 201 * Try to flush old fragments to make space for new ones 202 */ 203 204 void 205 pf_flush_fragments(void) 206 { 207 struct pf_fragment *frag; 208 int goal; 209 210 goal = pf_nfrents * 9 / 10; 211 DPFPRINTF(("trying to free > %d frents\n", 212 pf_nfrents - goal)); 213 while (goal < pf_nfrents) { 214 frag = TAILQ_LAST(&pf_fragqueue, pf_fragqueue); 215 if (frag == NULL) 216 break; 217 pf_free_fragment(frag); 218 } 219 220 221 goal = pf_ncache * 9 / 10; 222 DPFPRINTF(("trying to free > %d cache entries\n", 223 pf_ncache - goal)); 224 while (goal < pf_ncache) { 225 frag = TAILQ_LAST(&pf_cachequeue, pf_cachequeue); 226 if (frag == NULL) 227 break; 228 pf_free_fragment(frag); 229 } 230 } 231 232 /* Frees the fragments and all associated entries */ 233 234 void 235 pf_free_fragment(struct pf_fragment *frag) 236 { 237 struct pf_frent *frent; 238 struct pf_frcache *frcache; 239 240 /* Free all fragments */ 241 if (BUFFER_FRAGMENTS(frag)) { 242 for (frent = LIST_FIRST(&frag->fr_queue); frent; 243 frent = LIST_FIRST(&frag->fr_queue)) { 244 LIST_REMOVE(frent, fr_next); 245 246 m_freem(frent->fr_m); 247 pool_put(&pf_frent_pl, frent); 248 pf_nfrents--; 249 } 250 } else { 251 for (frcache = LIST_FIRST(&frag->fr_cache); frcache; 252 frcache = LIST_FIRST(&frag->fr_cache)) { 253 LIST_REMOVE(frcache, fr_next); 254 255 KASSERT(LIST_EMPTY(&frag->fr_cache) || 256 LIST_FIRST(&frag->fr_cache)->fr_off > 257 frcache->fr_end); 258 259 pool_put(&pf_cent_pl, frcache); 260 pf_ncache--; 261 } 262 } 263 264 pf_remove_fragment(frag); 265 } 266 267 void 268 pf_ip2key(struct pf_fragment *key, struct ip *ip) 269 { 270 key->fr_p = ip->ip_p; 271 key->fr_id = ip->ip_id; 272 key->fr_src.s_addr = ip->ip_src.s_addr; 273 key->fr_dst.s_addr = ip->ip_dst.s_addr; 274 } 275 276 struct pf_fragment * 277 pf_find_fragment(struct ip *ip, struct pf_frag_tree *tree) 278 { 279 struct pf_fragment key; 280 struct pf_fragment *frag; 281 282 pf_ip2key(&key, ip); 283 284 frag = RB_FIND(pf_frag_tree, tree, &key); 285 if (frag != NULL) { 286 /* XXX Are we sure we want to update the timeout? */ 287 frag->fr_timeout = time.tv_sec; 288 if (BUFFER_FRAGMENTS(frag)) { 289 TAILQ_REMOVE(&pf_fragqueue, frag, frag_next); 290 TAILQ_INSERT_HEAD(&pf_fragqueue, frag, frag_next); 291 } else { 292 TAILQ_REMOVE(&pf_cachequeue, frag, frag_next); 293 TAILQ_INSERT_HEAD(&pf_cachequeue, frag, frag_next); 294 } 295 } 296 297 return (frag); 298 } 299 300 /* Removes a fragment from the fragment queue and frees the fragment */ 301 302 void 303 pf_remove_fragment(struct pf_fragment *frag) 304 { 305 if (BUFFER_FRAGMENTS(frag)) { 306 RB_REMOVE(pf_frag_tree, &pf_frag_tree, frag); 307 TAILQ_REMOVE(&pf_fragqueue, frag, frag_next); 308 pool_put(&pf_frag_pl, frag); 309 } else { 310 RB_REMOVE(pf_frag_tree, &pf_cache_tree, frag); 311 TAILQ_REMOVE(&pf_cachequeue, frag, frag_next); 312 pool_put(&pf_cache_pl, frag); 313 } 314 } 315 316 #define FR_IP_OFF(fr) ((ntohs((fr)->fr_ip->ip_off) & IP_OFFMASK) << 3) 317 struct mbuf * 318 pf_reassemble(struct mbuf **m0, struct pf_fragment **frag, 319 struct pf_frent *frent, int mff) 320 { 321 struct mbuf *m = *m0, *m2; 322 struct pf_frent *frea, *next; 323 struct pf_frent *frep = NULL; 324 struct ip *ip = frent->fr_ip; 325 int hlen = ip->ip_hl << 2; 326 u_int16_t off = (ntohs(ip->ip_off) & IP_OFFMASK) << 3; 327 u_int16_t ip_len = ntohs(ip->ip_len) - ip->ip_hl * 4; 328 u_int16_t max = ip_len + off; 329 330 KASSERT(*frag == NULL || BUFFER_FRAGMENTS(*frag)); 331 332 /* Strip off ip header */ 333 m->m_data += hlen; 334 m->m_len -= hlen; 335 336 /* Create a new reassembly queue for this packet */ 337 if (*frag == NULL) { 338 *frag = pool_get(&pf_frag_pl, PR_NOWAIT); 339 if (*frag == NULL) { 340 pf_flush_fragments(); 341 *frag = pool_get(&pf_frag_pl, PR_NOWAIT); 342 if (*frag == NULL) 343 goto drop_fragment; 344 } 345 346 (*frag)->fr_flags = 0; 347 (*frag)->fr_max = 0; 348 (*frag)->fr_src = frent->fr_ip->ip_src; 349 (*frag)->fr_dst = frent->fr_ip->ip_dst; 350 (*frag)->fr_p = frent->fr_ip->ip_p; 351 (*frag)->fr_id = frent->fr_ip->ip_id; 352 (*frag)->fr_timeout = time.tv_sec; 353 LIST_INIT(&(*frag)->fr_queue); 354 355 RB_INSERT(pf_frag_tree, &pf_frag_tree, *frag); 356 TAILQ_INSERT_HEAD(&pf_fragqueue, *frag, frag_next); 357 358 /* We do not have a previous fragment */ 359 frep = NULL; 360 goto insert; 361 } 362 363 /* 364 * Find a fragment after the current one: 365 * - off contains the real shifted offset. 366 */ 367 LIST_FOREACH(frea, &(*frag)->fr_queue, fr_next) { 368 if (FR_IP_OFF(frea) > off) 369 break; 370 frep = frea; 371 } 372 373 KASSERT(frep != NULL || frea != NULL); 374 375 if (frep != NULL && 376 FR_IP_OFF(frep) + ntohs(frep->fr_ip->ip_len) - frep->fr_ip->ip_hl * 377 4 > off) 378 { 379 u_int16_t precut; 380 381 precut = FR_IP_OFF(frep) + ntohs(frep->fr_ip->ip_len) - 382 frep->fr_ip->ip_hl * 4 - off; 383 if (precut >= ip_len) 384 goto drop_fragment; 385 m_adj(frent->fr_m, precut); 386 DPFPRINTF(("overlap -%d\n", precut)); 387 /* Enforce 8 byte boundaries */ 388 ip->ip_off = htons(ntohs(ip->ip_off) + (precut >> 3)); 389 off = (ntohs(ip->ip_off) & IP_OFFMASK) << 3; 390 ip_len -= precut; 391 ip->ip_len = htons(ip_len); 392 } 393 394 for (; frea != NULL && ip_len + off > FR_IP_OFF(frea); 395 frea = next) 396 { 397 u_int16_t aftercut; 398 399 aftercut = ip_len + off - FR_IP_OFF(frea); 400 DPFPRINTF(("adjust overlap %d\n", aftercut)); 401 if (aftercut < ntohs(frea->fr_ip->ip_len) - frea->fr_ip->ip_hl 402 * 4) 403 { 404 frea->fr_ip->ip_len = 405 htons(ntohs(frea->fr_ip->ip_len) - aftercut); 406 frea->fr_ip->ip_off = htons(ntohs(frea->fr_ip->ip_off) + 407 (aftercut >> 3)); 408 m_adj(frea->fr_m, aftercut); 409 break; 410 } 411 412 /* This fragment is completely overlapped, loose it */ 413 next = LIST_NEXT(frea, fr_next); 414 m_freem(frea->fr_m); 415 LIST_REMOVE(frea, fr_next); 416 pool_put(&pf_frent_pl, frea); 417 pf_nfrents--; 418 } 419 420 insert: 421 /* Update maximum data size */ 422 if ((*frag)->fr_max < max) 423 (*frag)->fr_max = max; 424 /* This is the last segment */ 425 if (!mff) 426 (*frag)->fr_flags |= PFFRAG_SEENLAST; 427 428 if (frep == NULL) 429 LIST_INSERT_HEAD(&(*frag)->fr_queue, frent, fr_next); 430 else 431 LIST_INSERT_AFTER(frep, frent, fr_next); 432 433 /* Check if we are completely reassembled */ 434 if (!((*frag)->fr_flags & PFFRAG_SEENLAST)) 435 return (NULL); 436 437 /* Check if we have all the data */ 438 off = 0; 439 for (frep = LIST_FIRST(&(*frag)->fr_queue); frep; frep = next) { 440 next = LIST_NEXT(frep, fr_next); 441 442 off += ntohs(frep->fr_ip->ip_len) - frep->fr_ip->ip_hl * 4; 443 if (off < (*frag)->fr_max && 444 (next == NULL || FR_IP_OFF(next) != off)) 445 { 446 DPFPRINTF(("missing fragment at %d, next %d, max %d\n", 447 off, next == NULL ? -1 : FR_IP_OFF(next), 448 (*frag)->fr_max)); 449 return (NULL); 450 } 451 } 452 DPFPRINTF(("%d < %d?\n", off, (*frag)->fr_max)); 453 if (off < (*frag)->fr_max) 454 return (NULL); 455 456 /* We have all the data */ 457 frent = LIST_FIRST(&(*frag)->fr_queue); 458 KASSERT(frent != NULL); 459 if ((frent->fr_ip->ip_hl << 2) + off > IP_MAXPACKET) { 460 DPFPRINTF(("drop: too big: %d\n", off)); 461 pf_free_fragment(*frag); 462 *frag = NULL; 463 return (NULL); 464 } 465 next = LIST_NEXT(frent, fr_next); 466 467 /* Magic from ip_input */ 468 ip = frent->fr_ip; 469 m = frent->fr_m; 470 m2 = m->m_next; 471 m->m_next = NULL; 472 m_cat(m, m2); 473 pool_put(&pf_frent_pl, frent); 474 pf_nfrents--; 475 for (frent = next; frent != NULL; frent = next) { 476 next = LIST_NEXT(frent, fr_next); 477 478 m2 = frent->fr_m; 479 pool_put(&pf_frent_pl, frent); 480 pf_nfrents--; 481 m_cat(m, m2); 482 } 483 484 ip->ip_src = (*frag)->fr_src; 485 ip->ip_dst = (*frag)->fr_dst; 486 487 /* Remove from fragment queue */ 488 pf_remove_fragment(*frag); 489 *frag = NULL; 490 491 hlen = ip->ip_hl << 2; 492 ip->ip_len = htons(off + hlen); 493 m->m_len += hlen; 494 m->m_data -= hlen; 495 496 /* some debugging cruft by sklower, below, will go away soon */ 497 /* XXX this should be done elsewhere */ 498 if (m->m_flags & M_PKTHDR) { 499 int plen = 0; 500 for (m2 = m; m2; m2 = m2->m_next) 501 plen += m2->m_len; 502 m->m_pkthdr.len = plen; 503 } 504 505 DPFPRINTF(("complete: %p(%d)\n", m, ntohs(ip->ip_len))); 506 return (m); 507 508 drop_fragment: 509 /* Oops - fail safe - drop packet */ 510 pool_put(&pf_frent_pl, frent); 511 pf_nfrents--; 512 m_freem(m); 513 return (NULL); 514 } 515 516 struct mbuf * 517 pf_fragcache(struct mbuf **m0, struct ip *h, struct pf_fragment **frag, int mff, 518 int drop, int *nomem) 519 { 520 struct mbuf *m = *m0; 521 struct pf_frcache *frp, *fra, *cur = NULL; 522 int ip_len = ntohs(h->ip_len) - (h->ip_hl << 2); 523 u_int16_t off = ntohs(h->ip_off) << 3; 524 u_int16_t max = ip_len + off; 525 int hosed = 0; 526 527 KASSERT(*frag == NULL || !BUFFER_FRAGMENTS(*frag)); 528 529 /* Create a new range queue for this packet */ 530 if (*frag == NULL) { 531 *frag = pool_get(&pf_cache_pl, PR_NOWAIT); 532 if (*frag == NULL) { 533 pf_flush_fragments(); 534 *frag = pool_get(&pf_cache_pl, PR_NOWAIT); 535 if (*frag == NULL) 536 goto no_mem; 537 } 538 539 /* Get an entry for the queue */ 540 cur = pool_get(&pf_cent_pl, PR_NOWAIT); 541 if (cur == NULL) { 542 pool_put(&pf_cache_pl, *frag); 543 *frag = NULL; 544 goto no_mem; 545 } 546 pf_ncache++; 547 548 (*frag)->fr_flags = PFFRAG_NOBUFFER; 549 (*frag)->fr_max = 0; 550 (*frag)->fr_src = h->ip_src; 551 (*frag)->fr_dst = h->ip_dst; 552 (*frag)->fr_p = h->ip_p; 553 (*frag)->fr_id = h->ip_id; 554 (*frag)->fr_timeout = time.tv_sec; 555 556 cur->fr_off = off; 557 cur->fr_end = max; 558 LIST_INIT(&(*frag)->fr_cache); 559 LIST_INSERT_HEAD(&(*frag)->fr_cache, cur, fr_next); 560 561 RB_INSERT(pf_frag_tree, &pf_cache_tree, *frag); 562 TAILQ_INSERT_HEAD(&pf_cachequeue, *frag, frag_next); 563 564 DPFPRINTF(("fragcache[%d]: new %d-%d\n", h->ip_id, off, max)); 565 566 goto pass; 567 } 568 569 /* 570 * Find a fragment after the current one: 571 * - off contains the real shifted offset. 572 */ 573 frp = NULL; 574 LIST_FOREACH(fra, &(*frag)->fr_cache, fr_next) { 575 if (fra->fr_off > off) 576 break; 577 frp = fra; 578 } 579 580 KASSERT(frp != NULL || fra != NULL); 581 582 if (frp != NULL) { 583 int precut; 584 585 precut = frp->fr_end - off; 586 if (precut >= ip_len) { 587 /* Fragment is entirely a duplicate */ 588 DPFPRINTF(("fragcache[%d]: dead (%d-%d) %d-%d\n", 589 h->ip_id, frp->fr_off, frp->fr_end, off, max)); 590 goto drop_fragment; 591 } 592 if (precut == 0) { 593 /* They are adjacent. Fixup cache entry */ 594 DPFPRINTF(("fragcache[%d]: adjacent (%d-%d) %d-%d\n", 595 h->ip_id, frp->fr_off, frp->fr_end, off, max)); 596 frp->fr_end = max; 597 } else if (precut > 0) { 598 /* The first part of this payload overlaps with a 599 * fragment that has already been passed. 600 * Need to trim off the first part of the payload. 601 * But to do so easily, we need to create another 602 * mbuf to throw the original header into. 603 */ 604 605 DPFPRINTF(("fragcache[%d]: chop %d (%d-%d) %d-%d\n", 606 h->ip_id, precut, frp->fr_off, frp->fr_end, off, 607 max)); 608 609 off += precut; 610 max -= precut; 611 /* Update the previous frag to encompass this one */ 612 frp->fr_end = max; 613 614 if (!drop) { 615 /* XXX Optimization opportunity 616 * This is a very heavy way to trim the payload. 617 * we could do it much faster by diddling mbuf 618 * internals but that would be even less legible 619 * than this mbuf magic. For my next trick, 620 * I'll pull a rabbit out of my laptop. 621 */ 622 *m0 = m_copym2(m, 0, h->ip_hl << 2, M_NOWAIT); 623 if (*m0 == NULL) 624 goto no_mem; 625 KASSERT((*m0)->m_next == NULL); 626 m_adj(m, precut + (h->ip_hl << 2)); 627 m_cat(*m0, m); 628 m = *m0; 629 if (m->m_flags & M_PKTHDR) { 630 int plen = 0; 631 struct mbuf *t; 632 for (t = m; t; t = t->m_next) 633 plen += t->m_len; 634 m->m_pkthdr.len = plen; 635 } 636 637 638 h = mtod(m, struct ip *); 639 640 641 KASSERT((int)m->m_len == ntohs(h->ip_len) - precut); 642 h->ip_off = htons(ntohs(h->ip_off) + (precut >> 3)); 643 h->ip_len = htons(ntohs(h->ip_len) - precut); 644 } else { 645 hosed++; 646 } 647 } else { 648 /* There is a gap between fragments */ 649 650 DPFPRINTF(("fragcache[%d]: gap %d (%d-%d) %d-%d\n", 651 h->ip_id, -precut, frp->fr_off, frp->fr_end, off, 652 max)); 653 654 cur = pool_get(&pf_cent_pl, PR_NOWAIT); 655 if (cur == NULL) 656 goto no_mem; 657 pf_ncache++; 658 659 cur->fr_off = off; 660 cur->fr_end = max; 661 LIST_INSERT_AFTER(frp, cur, fr_next); 662 } 663 } 664 665 if (fra != NULL) { 666 int aftercut; 667 int merge = 0; 668 669 aftercut = max - fra->fr_off; 670 if (aftercut == 0) { 671 /* Adjacent fragments */ 672 DPFPRINTF(("fragcache[%d]: adjacent %d-%d (%d-%d)\n", 673 h->ip_id, off, max, fra->fr_off, fra->fr_end)); 674 fra->fr_off = off; 675 merge = 1; 676 } else if (aftercut > 0) { 677 /* Need to chop off the tail of this fragment */ 678 DPFPRINTF(("fragcache[%d]: chop %d %d-%d (%d-%d)\n", 679 h->ip_id, aftercut, off, max, fra->fr_off, 680 fra->fr_end)); 681 fra->fr_off = off; 682 max -= aftercut; 683 684 merge = 1; 685 686 if (!drop) { 687 m_adj(m, -aftercut); 688 if (m->m_flags & M_PKTHDR) { 689 int plen = 0; 690 struct mbuf *t; 691 for (t = m; t; t = t->m_next) 692 plen += t->m_len; 693 m->m_pkthdr.len = plen; 694 } 695 h = mtod(m, struct ip *); 696 KASSERT((int)m->m_len == ntohs(h->ip_len) - aftercut); 697 h->ip_len = htons(ntohs(h->ip_len) - aftercut); 698 } else { 699 hosed++; 700 } 701 } else { 702 /* There is a gap between fragments */ 703 DPFPRINTF(("fragcache[%d]: gap %d %d-%d (%d-%d)\n", 704 h->ip_id, -aftercut, off, max, fra->fr_off, 705 fra->fr_end)); 706 707 cur = pool_get(&pf_cent_pl, PR_NOWAIT); 708 if (cur == NULL) 709 goto no_mem; 710 pf_ncache++; 711 712 cur->fr_off = off; 713 cur->fr_end = max; 714 LIST_INSERT_BEFORE(fra, cur, fr_next); 715 } 716 717 718 /* Need to glue together two separate fragment descriptors */ 719 if (merge) { 720 if (cur && fra->fr_off <= cur->fr_end) { 721 /* Need to merge in a previous 'cur' */ 722 DPFPRINTF(("fragcache[%d]: adjacent(merge " 723 "%d-%d) %d-%d (%d-%d)\n", 724 h->ip_id, cur->fr_off, cur->fr_end, off, 725 max, fra->fr_off, fra->fr_end)); 726 fra->fr_off = cur->fr_off; 727 LIST_REMOVE(cur, fr_next); 728 pool_put(&pf_cent_pl, cur); 729 pf_ncache--; 730 cur = NULL; 731 732 } else if (frp && fra->fr_off <= frp->fr_end) { 733 /* Need to merge in a modified 'frp' */ 734 KASSERT(cur == NULL); 735 DPFPRINTF(("fragcache[%d]: adjacent(merge " 736 "%d-%d) %d-%d (%d-%d)\n", 737 h->ip_id, frp->fr_off, frp->fr_end, off, 738 max, fra->fr_off, fra->fr_end)); 739 fra->fr_off = frp->fr_off; 740 LIST_REMOVE(frp, fr_next); 741 pool_put(&pf_cent_pl, frp); 742 pf_ncache--; 743 frp = NULL; 744 745 } 746 } 747 } 748 749 if (hosed) { 750 /* 751 * We must keep tracking the overall fragment even when 752 * we're going to drop it anyway so that we know when to 753 * free the overall descriptor. Thus we drop the frag late. 754 */ 755 goto drop_fragment; 756 } 757 758 759 pass: 760 /* Update maximum data size */ 761 if ((*frag)->fr_max < max) 762 (*frag)->fr_max = max; 763 764 /* This is the last segment */ 765 if (!mff) 766 (*frag)->fr_flags |= PFFRAG_SEENLAST; 767 768 /* Check if we are completely reassembled */ 769 if (((*frag)->fr_flags & PFFRAG_SEENLAST) && 770 LIST_FIRST(&(*frag)->fr_cache)->fr_off == 0 && 771 LIST_FIRST(&(*frag)->fr_cache)->fr_end == (*frag)->fr_max) { 772 /* Remove from fragment queue */ 773 DPFPRINTF(("fragcache[%d]: done 0-%d\n", h->ip_id, 774 (*frag)->fr_max)); 775 pf_free_fragment(*frag); 776 *frag = NULL; 777 } 778 779 return (m); 780 781 no_mem: 782 *nomem = 1; 783 784 /* Still need to pay attention to !IP_MF */ 785 if (!mff && *frag != NULL) 786 (*frag)->fr_flags |= PFFRAG_SEENLAST; 787 788 m_freem(m); 789 return (NULL); 790 791 drop_fragment: 792 793 /* Still need to pay attention to !IP_MF */ 794 if (!mff && *frag != NULL) 795 (*frag)->fr_flags |= PFFRAG_SEENLAST; 796 797 if (drop) { 798 /* This fragment has been deemed bad. Don't reass */ 799 if (((*frag)->fr_flags & PFFRAG_DROP) == 0) 800 DPFPRINTF(("fragcache[%d]: dropping overall fragment\n", 801 h->ip_id)); 802 (*frag)->fr_flags |= PFFRAG_DROP; 803 } 804 805 m_freem(m); 806 return (NULL); 807 } 808 809 int 810 pf_normalize_ip(struct mbuf **m0, int dir, struct ifnet *ifp, u_short *reason) 811 { 812 struct mbuf *m = *m0; 813 struct pf_rule *r; 814 struct pf_frent *frent; 815 struct pf_fragment *frag = NULL; 816 struct ip *h = mtod(m, struct ip *); 817 int mff = (ntohs(h->ip_off) & IP_MF); 818 int hlen = h->ip_hl << 2; 819 u_int16_t fragoff = (ntohs(h->ip_off) & IP_OFFMASK) << 3; 820 u_int16_t max; 821 int ip_len; 822 int ip_off; 823 824 r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_SCRUB].active.ptr); 825 while (r != NULL) { 826 r->evaluations++; 827 if (r->ifp != NULL && r->ifp != ifp) 828 r = r->skip[PF_SKIP_IFP].ptr; 829 else if (r->direction && r->direction != dir) 830 r = r->skip[PF_SKIP_DIR].ptr; 831 else if (r->af && r->af != AF_INET) 832 r = r->skip[PF_SKIP_AF].ptr; 833 else if (r->proto && r->proto != h->ip_p) 834 r = r->skip[PF_SKIP_PROTO].ptr; 835 else if (PF_MISMATCHAW(&r->src.addr, 836 (struct pf_addr *)&h->ip_src.s_addr, AF_INET, r->src.not)) 837 r = r->skip[PF_SKIP_SRC_ADDR].ptr; 838 else if (PF_MISMATCHAW(&r->dst.addr, 839 (struct pf_addr *)&h->ip_dst.s_addr, AF_INET, r->dst.not)) 840 r = r->skip[PF_SKIP_DST_ADDR].ptr; 841 else 842 break; 843 } 844 845 if (r == NULL) 846 return (PF_PASS); 847 else 848 r->packets++; 849 850 /* Check for illegal packets */ 851 if (hlen < (int)sizeof(struct ip)) 852 goto drop; 853 854 if (hlen > ntohs(h->ip_len)) 855 goto drop; 856 857 /* Clear IP_DF if the rule uses the no-df option */ 858 if (r->rule_flag & PFRULE_NODF) 859 h->ip_off &= htons(~IP_DF); 860 861 /* We will need other tests here */ 862 if (!fragoff && !mff) 863 goto no_fragment; 864 865 /* We're dealing with a fragment now. Don't allow fragments 866 * with IP_DF to enter the cache. If the flag was cleared by 867 * no-df above, fine. Otherwise drop it. 868 */ 869 if (h->ip_off & htons(IP_DF)) { 870 DPFPRINTF(("IP_DF\n")); 871 goto bad; 872 } 873 874 ip_len = ntohs(h->ip_len) - hlen; 875 ip_off = (ntohs(h->ip_off) & IP_OFFMASK) << 3; 876 877 /* All fragments are 8 byte aligned */ 878 if (mff && (ip_len & 0x7)) { 879 DPFPRINTF(("mff and %d\n", ip_len)); 880 goto bad; 881 } 882 883 /* Respect maximum length */ 884 if (fragoff + ip_len > IP_MAXPACKET) { 885 DPFPRINTF(("max packet %d\n", fragoff + ip_len)); 886 goto bad; 887 } 888 max = fragoff + ip_len; 889 890 if ((r->rule_flag & (PFRULE_FRAGCROP|PFRULE_FRAGDROP)) == 0) { 891 /* Fully buffer all of the fragments */ 892 893 frag = pf_find_fragment(h, &pf_frag_tree); 894 895 /* Check if we saw the last fragment already */ 896 if (frag != NULL && (frag->fr_flags & PFFRAG_SEENLAST) && 897 max > frag->fr_max) 898 goto bad; 899 900 /* Get an entry for the fragment queue */ 901 frent = pool_get(&pf_frent_pl, PR_NOWAIT); 902 if (frent == NULL) { 903 REASON_SET(reason, PFRES_MEMORY); 904 return (PF_DROP); 905 } 906 pf_nfrents++; 907 frent->fr_ip = h; 908 frent->fr_m = m; 909 910 /* Might return a completely reassembled mbuf, or NULL */ 911 DPFPRINTF(("reass frag %d @ %d-%d\n", h->ip_id, fragoff, max)); 912 *m0 = m = pf_reassemble(m0, &frag, frent, mff); 913 914 if (m == NULL) 915 return (PF_DROP); 916 917 if (frag != NULL && (frag->fr_flags & PFFRAG_DROP)) 918 goto drop; 919 920 h = mtod(m, struct ip *); 921 } else { 922 /* non-buffering fragment cache (drops or masks overlaps) */ 923 int nomem = 0; 924 925 if (dir == PF_OUT) { 926 if (m_tag_find(m, PACKET_TAG_PF_FRAGCACHE, NULL) != 927 NULL) { 928 /* Already passed the fragment cache in the 929 * input direction. If we continued, it would 930 * appear to be a dup and would be dropped. 931 */ 932 goto fragment_pass; 933 } 934 } 935 936 frag = pf_find_fragment(h, &pf_cache_tree); 937 938 /* Check if we saw the last fragment already */ 939 if (frag != NULL && (frag->fr_flags & PFFRAG_SEENLAST) && 940 max > frag->fr_max) { 941 if (r->rule_flag & PFRULE_FRAGDROP) 942 frag->fr_flags |= PFFRAG_DROP; 943 goto bad; 944 } 945 946 *m0 = m = pf_fragcache(m0, h, &frag, mff, 947 (r->rule_flag & PFRULE_FRAGDROP) ? 1 : 0, &nomem); 948 if (m == NULL) { 949 if (nomem) 950 goto no_mem; 951 goto drop; 952 } 953 954 if (dir == PF_IN) { 955 struct m_tag *mtag; 956 957 mtag = m_tag_get(PACKET_TAG_PF_FRAGCACHE, 0, M_NOWAIT); 958 if (mtag == NULL) 959 goto no_mem; 960 m_tag_prepend(m, mtag); 961 } 962 if (frag != NULL && (frag->fr_flags & PFFRAG_DROP)) 963 goto drop; 964 goto fragment_pass; 965 } 966 967 no_fragment: 968 /* At this point, only IP_DF is allowed in ip_off */ 969 h->ip_off &= htons(IP_DF); 970 971 /* Enforce a minimum ttl, may cause endless packet loops */ 972 if (r->min_ttl && h->ip_ttl < r->min_ttl) 973 h->ip_ttl = r->min_ttl; 974 975 if (r->rule_flag & PFRULE_RANDOMID) 976 h->ip_id = ip_randomid(); 977 978 return (PF_PASS); 979 980 fragment_pass: 981 /* Enforce a minimum ttl, may cause endless packet loops */ 982 if (r->min_ttl && h->ip_ttl < r->min_ttl) 983 h->ip_ttl = r->min_ttl; 984 985 return (PF_PASS); 986 987 no_mem: 988 REASON_SET(reason, PFRES_MEMORY); 989 if (r != NULL && r->log) 990 PFLOG_PACKET(ifp, h, m, AF_INET, dir, *reason, r, NULL, NULL); 991 return (PF_DROP); 992 993 drop: 994 REASON_SET(reason, PFRES_NORM); 995 if (r != NULL && r->log) 996 PFLOG_PACKET(ifp, h, m, AF_INET, dir, *reason, r, NULL, NULL); 997 return (PF_DROP); 998 999 bad: 1000 DPFPRINTF(("dropping bad fragment\n")); 1001 1002 /* Free associated fragments */ 1003 if (frag != NULL) 1004 pf_free_fragment(frag); 1005 1006 REASON_SET(reason, PFRES_FRAG); 1007 if (r != NULL && r->log) 1008 PFLOG_PACKET(ifp, h, m, AF_INET, dir, *reason, r, NULL, NULL); 1009 1010 return (PF_DROP); 1011 } 1012 1013 #ifdef INET6 1014 int 1015 pf_normalize_ip6(struct mbuf **m0, int dir, struct ifnet *ifp, u_short *reason) 1016 { 1017 struct mbuf *m = *m0; 1018 struct pf_rule *r; 1019 struct ip6_hdr *h = mtod(m, struct ip6_hdr *); 1020 int off; 1021 struct ip6_ext ext; 1022 struct ip6_opt opt; 1023 struct ip6_opt_jumbo jumbo; 1024 struct ip6_frag frag; 1025 u_int32_t jumbolen = 0, plen; 1026 u_int16_t fragoff = 0; 1027 int optend; 1028 int ooff; 1029 u_int8_t proto; 1030 int terminal; 1031 1032 r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_SCRUB].active.ptr); 1033 while (r != NULL) { 1034 r->evaluations++; 1035 if (r->ifp != NULL && r->ifp != ifp) 1036 r = r->skip[PF_SKIP_IFP].ptr; 1037 else if (r->direction && r->direction != dir) 1038 r = r->skip[PF_SKIP_DIR].ptr; 1039 else if (r->af && r->af != AF_INET6) 1040 r = r->skip[PF_SKIP_AF].ptr; 1041 #if 0 /* header chain! */ 1042 else if (r->proto && r->proto != h->ip6_nxt) 1043 r = r->skip[PF_SKIP_PROTO].ptr; 1044 #endif 1045 else if (PF_MISMATCHAW(&r->src.addr, 1046 (struct pf_addr *)&h->ip6_src, AF_INET6, r->src.not)) 1047 r = r->skip[PF_SKIP_SRC_ADDR].ptr; 1048 else if (PF_MISMATCHAW(&r->dst.addr, 1049 (struct pf_addr *)&h->ip6_dst, AF_INET6, r->dst.not)) 1050 r = r->skip[PF_SKIP_DST_ADDR].ptr; 1051 else 1052 break; 1053 } 1054 1055 if (r == NULL) 1056 return (PF_PASS); 1057 else 1058 r->packets++; 1059 1060 /* Check for illegal packets */ 1061 if (sizeof(struct ip6_hdr) + IPV6_MAXPACKET < m->m_pkthdr.len) 1062 goto drop; 1063 1064 off = sizeof(struct ip6_hdr); 1065 proto = h->ip6_nxt; 1066 terminal = 0; 1067 do { 1068 switch (proto) { 1069 case IPPROTO_FRAGMENT: 1070 goto fragment; 1071 break; 1072 case IPPROTO_AH: 1073 case IPPROTO_ROUTING: 1074 case IPPROTO_DSTOPTS: 1075 if (!pf_pull_hdr(m, off, &ext, sizeof(ext), NULL, 1076 NULL, AF_INET6)) 1077 goto shortpkt; 1078 if (proto == IPPROTO_AH) 1079 off += (ext.ip6e_len + 2) * 4; 1080 else 1081 off += (ext.ip6e_len + 1) * 8; 1082 proto = ext.ip6e_nxt; 1083 break; 1084 case IPPROTO_HOPOPTS: 1085 if (!pf_pull_hdr(m, off, &ext, sizeof(ext), NULL, 1086 NULL, AF_INET6)) 1087 goto shortpkt; 1088 optend = off + (ext.ip6e_len + 1) * 8; 1089 ooff = off + sizeof(ext); 1090 do { 1091 if (!pf_pull_hdr(m, ooff, &opt.ip6o_type, 1092 sizeof(opt.ip6o_type), NULL, NULL, 1093 AF_INET6)) 1094 goto shortpkt; 1095 if (opt.ip6o_type == IP6OPT_PAD1) { 1096 ooff++; 1097 continue; 1098 } 1099 if (!pf_pull_hdr(m, ooff, &opt, sizeof(opt), 1100 NULL, NULL, AF_INET6)) 1101 goto shortpkt; 1102 if (ooff + sizeof(opt) + opt.ip6o_len > optend) 1103 goto drop; 1104 switch (opt.ip6o_type) { 1105 case IP6OPT_JUMBO: 1106 if (h->ip6_plen != 0) 1107 goto drop; 1108 if (!pf_pull_hdr(m, ooff, &jumbo, 1109 sizeof(jumbo), NULL, NULL, 1110 AF_INET6)) 1111 goto shortpkt; 1112 memcpy(&jumbolen, jumbo.ip6oj_jumbo_len, 1113 sizeof(jumbolen)); 1114 jumbolen = ntohl(jumbolen); 1115 if (jumbolen <= IPV6_MAXPACKET) 1116 goto drop; 1117 if (sizeof(struct ip6_hdr) + jumbolen != 1118 m->m_pkthdr.len) 1119 goto drop; 1120 break; 1121 default: 1122 break; 1123 } 1124 ooff += sizeof(opt) + opt.ip6o_len; 1125 } while (ooff < optend); 1126 1127 off = optend; 1128 proto = ext.ip6e_nxt; 1129 break; 1130 default: 1131 terminal = 1; 1132 break; 1133 } 1134 } while (!terminal); 1135 1136 /* jumbo payload option must be present, or plen > 0 */ 1137 if (ntohs(h->ip6_plen) == 0) 1138 plen = jumbolen; 1139 else 1140 plen = ntohs(h->ip6_plen); 1141 if (plen == 0) 1142 goto drop; 1143 if (sizeof(struct ip6_hdr) + plen > m->m_pkthdr.len) 1144 goto shortpkt; 1145 1146 /* Enforce a minimum ttl, may cause endless packet loops */ 1147 if (r->min_ttl && h->ip6_hlim < r->min_ttl) 1148 h->ip6_hlim = r->min_ttl; 1149 1150 return (PF_PASS); 1151 1152 fragment: 1153 if (ntohs(h->ip6_plen) == 0 || jumbolen) 1154 goto drop; 1155 plen = ntohs(h->ip6_plen); 1156 1157 if (!pf_pull_hdr(m, off, &frag, sizeof(frag), NULL, NULL, AF_INET6)) 1158 goto shortpkt; 1159 fragoff = ntohs(frag.ip6f_offlg & IP6F_OFF_MASK); 1160 if (fragoff + (plen - off - sizeof(frag)) > IPV6_MAXPACKET) 1161 goto badfrag; 1162 1163 /* do something about it */ 1164 return (PF_PASS); 1165 1166 shortpkt: 1167 REASON_SET(reason, PFRES_SHORT); 1168 if (r != NULL && r->log) 1169 PFLOG_PACKET(ifp, h, m, AF_INET6, dir, *reason, r, NULL, NULL); 1170 return (PF_DROP); 1171 1172 drop: 1173 REASON_SET(reason, PFRES_NORM); 1174 if (r != NULL && r->log) 1175 PFLOG_PACKET(ifp, h, m, AF_INET6, dir, *reason, r, NULL, NULL); 1176 return (PF_DROP); 1177 1178 badfrag: 1179 REASON_SET(reason, PFRES_FRAG); 1180 if (r != NULL && r->log) 1181 PFLOG_PACKET(ifp, h, m, AF_INET6, dir, *reason, r, NULL, NULL); 1182 return (PF_DROP); 1183 } 1184 #endif 1185 1186 int 1187 pf_normalize_tcp(int dir, struct ifnet *ifp, struct mbuf *m, int ipoff, 1188 int off, void *h, struct pf_pdesc *pd) 1189 { 1190 struct pf_rule *r, *rm = NULL; 1191 struct tcphdr *th = pd->hdr.tcp; 1192 int rewrite = 0; 1193 u_short reason; 1194 u_int8_t flags; 1195 sa_family_t af = pd->af; 1196 1197 r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_SCRUB].active.ptr); 1198 while (r != NULL) { 1199 r->evaluations++; 1200 if (r->ifp != NULL && r->ifp != ifp) 1201 r = r->skip[PF_SKIP_IFP].ptr; 1202 else if (r->direction && r->direction != dir) 1203 r = r->skip[PF_SKIP_DIR].ptr; 1204 else if (r->af && r->af != af) 1205 r = r->skip[PF_SKIP_AF].ptr; 1206 else if (r->proto && r->proto != pd->proto) 1207 r = r->skip[PF_SKIP_PROTO].ptr; 1208 else if (PF_MISMATCHAW(&r->src.addr, pd->src, af, r->src.not)) 1209 r = r->skip[PF_SKIP_SRC_ADDR].ptr; 1210 else if (r->src.port_op && !pf_match_port(r->src.port_op, 1211 r->src.port[0], r->src.port[1], th->th_sport)) 1212 r = r->skip[PF_SKIP_SRC_PORT].ptr; 1213 else if (PF_MISMATCHAW(&r->dst.addr, pd->dst, af, r->dst.not)) 1214 r = r->skip[PF_SKIP_DST_ADDR].ptr; 1215 else if (r->dst.port_op && !pf_match_port(r->dst.port_op, 1216 r->dst.port[0], r->dst.port[1], th->th_dport)) 1217 r = r->skip[PF_SKIP_DST_PORT].ptr; 1218 else if (r->os_fingerprint != PF_OSFP_ANY && !pf_osfp_match( 1219 pf_osfp_fingerprint(pd, m, off, th), 1220 r->os_fingerprint)) 1221 r = TAILQ_NEXT(r, entries); 1222 else { 1223 rm = r; 1224 break; 1225 } 1226 } 1227 1228 if (rm == NULL) 1229 return (PF_PASS); 1230 else 1231 r->packets++; 1232 1233 if (rm->rule_flag & PFRULE_REASSEMBLE_TCP) 1234 pd->flags |= PFDESC_TCP_NORM; 1235 1236 flags = th->th_flags; 1237 if (flags & TH_SYN) { 1238 /* Illegal packet */ 1239 if (flags & TH_RST) 1240 goto tcp_drop; 1241 1242 if (flags & TH_FIN) 1243 flags &= ~TH_FIN; 1244 } else { 1245 /* Illegal packet */ 1246 if (!(flags & (TH_ACK|TH_RST))) 1247 goto tcp_drop; 1248 } 1249 1250 if (!(flags & TH_ACK)) { 1251 /* These flags are only valid if ACK is set */ 1252 if ((flags & TH_FIN) || (flags & TH_PUSH) || (flags & TH_URG)) 1253 goto tcp_drop; 1254 } 1255 1256 /* Check for illegal header length */ 1257 if (th->th_off < (sizeof(struct tcphdr) >> 2)) 1258 goto tcp_drop; 1259 1260 /* If flags changed, or reserved data set, then adjust */ 1261 if (flags != th->th_flags || th->th_x2 != 0) { 1262 u_int16_t ov, nv; 1263 1264 ov = *(u_int16_t *)(&th->th_ack + 1); 1265 th->th_flags = flags; 1266 th->th_x2 = 0; 1267 nv = *(u_int16_t *)(&th->th_ack + 1); 1268 1269 th->th_sum = pf_cksum_fixup(th->th_sum, ov, nv); 1270 rewrite = 1; 1271 } 1272 1273 /* Remove urgent pointer, if TH_URG is not set */ 1274 if (!(flags & TH_URG) && th->th_urp) { 1275 th->th_sum = pf_cksum_fixup(th->th_sum, th->th_urp, 0); 1276 th->th_urp = 0; 1277 rewrite = 1; 1278 } 1279 1280 /* Process options */ 1281 if (r->max_mss && pf_normalize_tcpopt(r, m, th, off)) 1282 rewrite = 1; 1283 1284 /* copy back packet headers if we sanitized */ 1285 if (rewrite) 1286 m_copyback(m, off, sizeof(*th), th); 1287 1288 return (PF_PASS); 1289 1290 tcp_drop: 1291 REASON_SET(&reason, PFRES_NORM); 1292 if (rm != NULL && r->log) 1293 PFLOG_PACKET(ifp, h, m, AF_INET, dir, reason, r, NULL, NULL); 1294 return (PF_DROP); 1295 } 1296 1297 int 1298 pf_normalize_tcp_init(struct mbuf *m, int off, struct pf_pdesc *pd, 1299 struct tcphdr *th, struct pf_state_peer *src, struct pf_state_peer *dst) 1300 { 1301 u_int8_t hdr[60]; 1302 u_int8_t *opt; 1303 1304 KASSERT(src->scrub == NULL); 1305 1306 src->scrub = pool_get(&pf_state_scrub_pl, PR_NOWAIT); 1307 if (src->scrub == NULL) 1308 return (1); 1309 bzero(src->scrub, sizeof(*src->scrub)); 1310 1311 switch (pd->af) { 1312 #ifdef INET 1313 case AF_INET: { 1314 struct ip *h = mtod(m, struct ip *); 1315 src->scrub->pfss_ttl = h->ip_ttl; 1316 break; 1317 } 1318 #endif /* INET */ 1319 #ifdef INET6 1320 case AF_INET6: { 1321 struct ip6_hdr *h = mtod(m, struct ip6_hdr *); 1322 src->scrub->pfss_ttl = h->ip6_hlim; 1323 break; 1324 } 1325 #endif /* INET6 */ 1326 } 1327 1328 1329 /* 1330 * All normalizations below are only begun if we see the start of 1331 * the connections. They must all set an enabled bit in pfss_flags 1332 */ 1333 if ((th->th_flags & TH_SYN) == 0) 1334 return 0; 1335 1336 1337 if (th->th_off > (sizeof(struct tcphdr) >> 2) && src->scrub && 1338 pf_pull_hdr(m, off, hdr, th->th_off << 2, NULL, NULL, pd->af)) { 1339 /* Diddle with TCP options */ 1340 int hlen; 1341 opt = hdr + sizeof(struct tcphdr); 1342 hlen = (th->th_off << 2) - sizeof(struct tcphdr); 1343 while (hlen >= TCPOLEN_TIMESTAMP) { 1344 switch (*opt) { 1345 case TCPOPT_EOL: /* FALLTHROUGH */ 1346 case TCPOPT_NOP: 1347 opt++; 1348 hlen--; 1349 break; 1350 case TCPOPT_TIMESTAMP: 1351 if (opt[1] >= TCPOLEN_TIMESTAMP) { 1352 src->scrub->pfss_flags |= 1353 PFSS_TIMESTAMP; 1354 src->scrub->pfss_ts_mod = arc4random(); 1355 } 1356 /* FALLTHROUGH */ 1357 default: 1358 hlen -= opt[1]; 1359 opt += opt[1]; 1360 break; 1361 } 1362 } 1363 } 1364 1365 return (0); 1366 } 1367 1368 void 1369 pf_normalize_tcp_cleanup(struct pf_state *state) 1370 { 1371 if (state->src.scrub) 1372 pool_put(&pf_state_scrub_pl, state->src.scrub); 1373 if (state->dst.scrub) 1374 pool_put(&pf_state_scrub_pl, state->dst.scrub); 1375 1376 /* Someday... flush the TCP segment reassembly descriptors. */ 1377 } 1378 1379 int 1380 pf_normalize_tcp_stateful(struct mbuf *m, int off, struct pf_pdesc *pd, 1381 u_short *reason, struct tcphdr *th, struct pf_state_peer *src, 1382 struct pf_state_peer *dst, int *writeback) 1383 { 1384 u_int8_t hdr[60]; 1385 u_int8_t *opt; 1386 int copyback = 0; 1387 1388 KASSERT(src->scrub || dst->scrub); 1389 1390 /* 1391 * Enforce the minimum TTL seen for this connection. Negate a common 1392 * technique to evade an intrusion detection system and confuse 1393 * firewall state code. 1394 */ 1395 switch (pd->af) { 1396 #ifdef INET 1397 case AF_INET: { 1398 if (src->scrub) { 1399 struct ip *h = mtod(m, struct ip *); 1400 if (h->ip_ttl > src->scrub->pfss_ttl) 1401 src->scrub->pfss_ttl = h->ip_ttl; 1402 h->ip_ttl = src->scrub->pfss_ttl; 1403 } 1404 break; 1405 } 1406 #endif /* INET */ 1407 #ifdef INET6 1408 case AF_INET6: { 1409 if (dst->scrub) { 1410 struct ip6_hdr *h = mtod(m, struct ip6_hdr *); 1411 if (h->ip6_hlim > src->scrub->pfss_ttl) 1412 src->scrub->pfss_ttl = h->ip6_hlim; 1413 h->ip6_hlim = src->scrub->pfss_ttl; 1414 } 1415 break; 1416 } 1417 #endif /* INET6 */ 1418 } 1419 1420 if (th->th_off > (sizeof(struct tcphdr) >> 2) && 1421 ((src->scrub && (src->scrub->pfss_flags & PFSS_TIMESTAMP)) || 1422 (dst->scrub && (dst->scrub->pfss_flags & PFSS_TIMESTAMP))) && 1423 pf_pull_hdr(m, off, hdr, th->th_off << 2, NULL, NULL, pd->af)) { 1424 /* Diddle with TCP options */ 1425 int hlen; 1426 opt = hdr + sizeof(struct tcphdr); 1427 hlen = (th->th_off << 2) - sizeof(struct tcphdr); 1428 while (hlen >= TCPOLEN_TIMESTAMP) { 1429 switch (*opt) { 1430 case TCPOPT_EOL: /* FALLTHROUGH */ 1431 case TCPOPT_NOP: 1432 opt++; 1433 hlen--; 1434 break; 1435 case TCPOPT_TIMESTAMP: 1436 /* Modulate the timestamps. Can be used for 1437 * NAT detection, OS uptime determination or 1438 * reboot detection. 1439 */ 1440 if (opt[1] >= TCPOLEN_TIMESTAMP) { 1441 u_int32_t ts_value; 1442 if (src->scrub && 1443 (src->scrub->pfss_flags & 1444 PFSS_TIMESTAMP)) { 1445 memcpy(&ts_value, &opt[2], 1446 sizeof(u_int32_t)); 1447 ts_value = htonl(ntohl(ts_value) 1448 + src->scrub->pfss_ts_mod); 1449 pf_change_a(&opt[2], 1450 &th->th_sum, ts_value, 0); 1451 copyback = 1; 1452 } 1453 if (dst->scrub && 1454 (dst->scrub->pfss_flags & 1455 PFSS_TIMESTAMP)) { 1456 memcpy(&ts_value, &opt[6], 1457 sizeof(u_int32_t)); 1458 ts_value = htonl(ntohl(ts_value) 1459 - dst->scrub->pfss_ts_mod); 1460 pf_change_a(&opt[6], 1461 &th->th_sum, ts_value, 0); 1462 copyback = 1; 1463 } 1464 } 1465 /* FALLTHROUGH */ 1466 default: 1467 hlen -= opt[1]; 1468 opt += opt[1]; 1469 break; 1470 } 1471 } 1472 if (copyback) { 1473 /* Copyback the options, caller copys back header */ 1474 *writeback = 1; 1475 m_copyback(m, off + sizeof(struct tcphdr), 1476 (th->th_off << 2) - sizeof(struct tcphdr), hdr + 1477 sizeof(struct tcphdr)); 1478 } 1479 } 1480 1481 1482 /* I have a dream.... TCP segment reassembly.... */ 1483 return (0); 1484 } 1485 int 1486 pf_normalize_tcpopt(struct pf_rule *r, struct mbuf *m, struct tcphdr *th, 1487 int off) 1488 { 1489 u_int16_t *mss; 1490 int thoff; 1491 int opt, cnt, optlen = 0; 1492 int rewrite = 0; 1493 u_char *optp; 1494 1495 thoff = th->th_off << 2; 1496 cnt = thoff - sizeof(struct tcphdr); 1497 optp = mtod(m, caddr_t) + off + sizeof(struct tcphdr); 1498 1499 for (; cnt > 0; cnt -= optlen, optp += optlen) { 1500 opt = optp[0]; 1501 if (opt == TCPOPT_EOL) 1502 break; 1503 if (opt == TCPOPT_NOP) 1504 optlen = 1; 1505 else { 1506 if (cnt < 2) 1507 break; 1508 optlen = optp[1]; 1509 if (optlen < 2 || optlen > cnt) 1510 break; 1511 } 1512 switch (opt) { 1513 case TCPOPT_MAXSEG: 1514 mss = (u_int16_t *)(optp + 2); 1515 if ((ntohs(*mss)) > r->max_mss) { 1516 th->th_sum = pf_cksum_fixup(th->th_sum, 1517 *mss, htons(r->max_mss)); 1518 *mss = htons(r->max_mss); 1519 rewrite = 1; 1520 } 1521 break; 1522 default: 1523 break; 1524 } 1525 } 1526 1527 return (rewrite); 1528 } 1529