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