1/* $FreeBSD: head/sys/contrib/pf/net/pf_norm.c 126261 2004-02-26 02:34:12Z mlaier $ */ |
2/* $OpenBSD: pf_norm.c,v 1.75 2003/08/29 01:49:08 dhartmei 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 --- 11 unchanged lines hidden (view full) --- 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#if defined(__FreeBSD__) 30#include "opt_inet.h" 31#include "opt_inet6.h" 32#include "opt_random_ip_id.h" /* or ip_var does not export it */ 33#include "opt_pf.h" 34#define NPFLOG DEV_PFLOG 35#else |
36#include "pflog.h" |
37#endif |
38 39#include <sys/param.h> 40#include <sys/systm.h> 41#include <sys/mbuf.h> 42#include <sys/filio.h> 43#include <sys/fcntl.h> 44#include <sys/socket.h> 45#include <sys/kernel.h> 46#include <sys/time.h> |
47#if !defined(__FreeBSD__) |
48#include <sys/pool.h> |
49#endif |
50 |
51#if !defined(__FreeBSD__) |
52#include <dev/rndvar.h> |
53#endif |
54#include <net/if.h> 55#include <net/if_types.h> 56#include <net/bpf.h> 57#include <net/route.h> 58#include <net/if_pflog.h> 59 60#include <netinet/in.h> 61#include <netinet/in_var.h> --- 6 unchanged lines hidden (view full) --- 68#include <netinet/ip_icmp.h> 69 70#ifdef INET6 71#include <netinet/ip6.h> 72#endif /* INET6 */ 73 74#include <net/pfvar.h> 75 |
76#if defined(__FreeBSD__) && defined(INET6) 77/* 78 * XXX: This should go to netinet/ip6.h (KAME) 79 */ 80/* IPv6 options: common part */ 81struct ip6_opt { 82 u_int8_t ip6o_type; 83 u_int8_t ip6o_len; 84} __packed; 85 86/* Jumbo Payload Option */ 87struct ip6_opt_jumbo { 88 u_int8_t ip6oj_type; 89 u_int8_t ip6oj_len; 90 u_int8_t ip6oj_jumbo_len[4]; 91} __packed; 92 93/* NSAP Address Option */ 94struct ip6_opt_nsap { 95 u_int8_t ip6on_type; 96 u_int8_t ip6on_len; 97 u_int8_t ip6on_src_nsap_len; 98 u_int8_t ip6on_dst_nsap_len; 99 /* followed by source NSAP */ 100 /* followed by destination NSAP */ 101} __packed; 102 103/* Tunnel Limit Option */ 104struct ip6_opt_tunnel { 105 u_int8_t ip6ot_type; 106 u_int8_t ip6ot_len; 107 u_int8_t ip6ot_encap_limit; 108} __packed; 109 110/* Router Alert Option */ 111struct ip6_opt_router { 112 u_int8_t ip6or_type; 113 u_int8_t ip6or_len; 114 u_int8_t ip6or_value[2]; 115} __packed; 116#endif /* __FreeBSD__ && INET6 */ 117 118#if !defined(__FreeBSD__) |
119struct pf_frent { 120 LIST_ENTRY(pf_frent) fr_next; 121 struct ip *fr_ip; 122 struct mbuf *fr_m; 123}; 124 125struct pf_frcache { 126 LIST_ENTRY(pf_frcache) fr_next; 127 uint16_t fr_off; 128 uint16_t fr_end; 129}; |
130#endif |
131 132#define PFFRAG_SEENLAST 0x0001 /* Seen the last fragment for this */ 133#define PFFRAG_NOBUFFER 0x0002 /* Non-buffering fragment cache */ 134#define PFFRAG_DROP 0x0004 /* Drop all fragments */ 135#define BUFFER_FRAGMENTS(fr) (!((fr)->fr_flags & PFFRAG_NOBUFFER)) 136 |
137#if !defined(__FreeBSD__) |
138struct pf_fragment { 139 RB_ENTRY(pf_fragment) fr_entry; 140 TAILQ_ENTRY(pf_fragment) frag_next; 141 struct in_addr fr_src; 142 struct in_addr fr_dst; 143 u_int8_t fr_p; /* protocol of this fragment */ 144 u_int8_t fr_flags; /* status flags */ 145 u_int16_t fr_id; /* fragment id for reassemble */ 146 u_int16_t fr_max; /* fragment data max */ 147 u_int32_t fr_timeout; 148#define fr_queue fr_u.fru_queue 149#define fr_cache fr_u.fru_cache 150 union { 151 LIST_HEAD(pf_fragq, pf_frent) fru_queue; /* buffering */ 152 LIST_HEAD(pf_cacheq, pf_frcache) fru_cache; /* non-buf */ 153 } fr_u; 154}; |
155#endif |
156 157TAILQ_HEAD(pf_fragqueue, pf_fragment) pf_fragqueue; 158TAILQ_HEAD(pf_cachequeue, pf_fragment) pf_cachequeue; 159 160static __inline int pf_frag_compare(struct pf_fragment *, 161 struct pf_fragment *); 162RB_HEAD(pf_frag_tree, pf_fragment) pf_frag_tree, pf_cache_tree; 163RB_PROTOTYPE(pf_frag_tree, pf_fragment, fr_entry, pf_frag_compare); 164RB_GENERATE(pf_frag_tree, pf_fragment, fr_entry, pf_frag_compare); 165 166/* Private prototypes */ |
167#ifndef RANDOM_IP_ID 168extern u_int16_t ip_randomid(void); 169#endif |
170void pf_ip2key(struct pf_fragment *, struct ip *); 171void pf_remove_fragment(struct pf_fragment *); 172void pf_flush_fragments(void); 173void pf_free_fragment(struct pf_fragment *); 174struct pf_fragment *pf_find_fragment(struct ip *, struct pf_frag_tree *); 175struct mbuf *pf_reassemble(struct mbuf **, struct pf_fragment **, 176 struct pf_frent *, int); 177struct mbuf *pf_fragcache(struct mbuf **, struct ip*, 178 struct pf_fragment **, int, int, int *); 179u_int16_t pf_cksum_fixup(u_int16_t, u_int16_t, u_int16_t); 180int pf_normalize_tcpopt(struct pf_rule *, struct mbuf *, 181 struct tcphdr *, int); 182 183#define DPFPRINTF(x) if (pf_status.debug >= PF_DEBUG_MISC) \ 184 { printf("%s: ", __func__); printf x ;} 185 186/* Globals */ |
187#if defined(__FreeBSD__) 188uma_zone_t pf_frent_pl, pf_frag_pl, pf_cache_pl, pf_cent_pl; 189uma_zone_t pf_state_scrub_pl; 190#else |
191struct pool pf_frent_pl, pf_frag_pl, pf_cache_pl, pf_cent_pl; 192struct pool pf_state_scrub_pl; |
193#endif |
194int pf_nfrents, pf_ncache; 195 196void 197pf_normalize_init(void) 198{ |
199#if defined(__FreeBSD__) 200 /* 201 * XXX 202 * No high water mark support(It's hint not hard limit). 203 * uma_zone_set_max(pf_frag_pl, PFFRAG_FRAG_HIWAT); 204 */ 205 uma_zone_set_max(pf_frent_pl, PFFRAG_FRENT_HIWAT); 206 uma_zone_set_max(pf_cache_pl, PFFRAG_FRCACHE_HIWAT); 207 uma_zone_set_max(pf_cent_pl, PFFRAG_FRCENT_HIWAT); 208#else |
209 pool_init(&pf_frent_pl, sizeof(struct pf_frent), 0, 0, 0, "pffrent", 210 NULL); 211 pool_init(&pf_frag_pl, sizeof(struct pf_fragment), 0, 0, 0, "pffrag", 212 NULL); 213 pool_init(&pf_cache_pl, sizeof(struct pf_fragment), 0, 0, 0, 214 "pffrcache", NULL); 215 pool_init(&pf_cent_pl, sizeof(struct pf_frcache), 0, 0, 0, "pffrcent", 216 NULL); 217 pool_init(&pf_state_scrub_pl, sizeof(struct pf_state_scrub), 0, 0, 0, 218 "pfstscr", NULL); 219 220 pool_sethiwat(&pf_frag_pl, PFFRAG_FRAG_HIWAT); 221 pool_sethardlimit(&pf_frent_pl, PFFRAG_FRENT_HIWAT, NULL, 0); 222 pool_sethardlimit(&pf_cache_pl, PFFRAG_FRCACHE_HIWAT, NULL, 0); 223 pool_sethardlimit(&pf_cent_pl, PFFRAG_FRCENT_HIWAT, NULL, 0); |
224#endif |
225 226 TAILQ_INIT(&pf_fragqueue); 227 TAILQ_INIT(&pf_cachequeue); 228} 229 230static __inline int 231pf_frag_compare(struct pf_fragment *a, struct pf_fragment *b) 232{ --- 13 unchanged lines hidden (view full) --- 246 return (1); 247 return (0); 248} 249 250void 251pf_purge_expired_fragments(void) 252{ 253 struct pf_fragment *frag; |
254#if defined(__FreeBSD__) 255 u_int32_t expire = time_second - 256 pf_default_rule.timeout[PFTM_FRAG]; 257#else |
258 u_int32_t expire = time.tv_sec - 259 pf_default_rule.timeout[PFTM_FRAG]; |
260#endif |
261 262 while ((frag = TAILQ_LAST(&pf_fragqueue, pf_fragqueue)) != NULL) { |
263#if defined(__FreeBSD__) 264 KASSERT((BUFFER_FRAGMENTS(frag)), 265 ("BUFFER_FRAGMENTS(frag) == 0: %s", __FUNCTION__)); 266#else |
267 KASSERT(BUFFER_FRAGMENTS(frag)); |
268#endif |
269 if (frag->fr_timeout > expire) 270 break; 271 272 DPFPRINTF(("expiring %d(%p)\n", frag->fr_id, frag)); 273 pf_free_fragment(frag); 274 } 275 276 while ((frag = TAILQ_LAST(&pf_cachequeue, pf_cachequeue)) != NULL) { |
277#if defined(__FreeBSD__) 278 KASSERT((!BUFFER_FRAGMENTS(frag)), 279 ("BUFFER_FRAGMENTS(frag) != 0: %s", __FUNCTION__)); 280#else |
281 KASSERT(!BUFFER_FRAGMENTS(frag)); |
282#endif |
283 if (frag->fr_timeout > expire) 284 break; 285 286 DPFPRINTF(("expiring %d(%p)\n", frag->fr_id, frag)); 287 pf_free_fragment(frag); |
288#if defined(__FreeBSD__) 289 KASSERT((TAILQ_EMPTY(&pf_cachequeue) || 290 TAILQ_LAST(&pf_cachequeue, pf_cachequeue) != frag), 291 ("!(TAILQ_EMPTY() || TAILQ_LAST() == farg): %s", 292 __FUNCTION__)); 293#else |
294 KASSERT(TAILQ_EMPTY(&pf_cachequeue) || 295 TAILQ_LAST(&pf_cachequeue, pf_cachequeue) != frag); |
296#endif |
297 } 298} 299 300/* 301 * Try to flush old fragments to make space for new ones 302 */ 303 304void --- 42 unchanged lines hidden (view full) --- 347 pool_put(&pf_frent_pl, frent); 348 pf_nfrents--; 349 } 350 } else { 351 for (frcache = LIST_FIRST(&frag->fr_cache); frcache; 352 frcache = LIST_FIRST(&frag->fr_cache)) { 353 LIST_REMOVE(frcache, fr_next); 354 |
355#if defined(__FreeBSD__) 356 KASSERT((LIST_EMPTY(&frag->fr_cache) || 357 LIST_FIRST(&frag->fr_cache)->fr_off > 358 frcache->fr_end), 359 ("! (LIST_EMPTY() || LIST_FIRST()->fr_off >" 360 " frcache->fr_end): %s", __FUNCTION__)); 361#else |
362 KASSERT(LIST_EMPTY(&frag->fr_cache) || 363 LIST_FIRST(&frag->fr_cache)->fr_off > 364 frcache->fr_end); |
365#endif |
366 367 pool_put(&pf_cent_pl, frcache); 368 pf_ncache--; 369 } 370 } 371 372 pf_remove_fragment(frag); 373} --- 13 unchanged lines hidden (view full) --- 387 struct pf_fragment key; 388 struct pf_fragment *frag; 389 390 pf_ip2key(&key, ip); 391 392 frag = RB_FIND(pf_frag_tree, tree, &key); 393 if (frag != NULL) { 394 /* XXX Are we sure we want to update the timeout? */ |
395#if defined(__FreeBSD__) 396 frag->fr_timeout = time_second; 397#else |
398 frag->fr_timeout = time.tv_sec; |
399#endif |
400 if (BUFFER_FRAGMENTS(frag)) { 401 TAILQ_REMOVE(&pf_fragqueue, frag, frag_next); 402 TAILQ_INSERT_HEAD(&pf_fragqueue, frag, frag_next); 403 } else { 404 TAILQ_REMOVE(&pf_cachequeue, frag, frag_next); 405 TAILQ_INSERT_HEAD(&pf_cachequeue, frag, frag_next); 406 } 407 } --- 26 unchanged lines hidden (view full) --- 434 struct pf_frent *frea, *next; 435 struct pf_frent *frep = NULL; 436 struct ip *ip = frent->fr_ip; 437 int hlen = ip->ip_hl << 2; 438 u_int16_t off = (ntohs(ip->ip_off) & IP_OFFMASK) << 3; 439 u_int16_t ip_len = ntohs(ip->ip_len) - ip->ip_hl * 4; 440 u_int16_t max = ip_len + off; 441 |
442#if defined(__FreeBSD__) 443 KASSERT((*frag == NULL || BUFFER_FRAGMENTS(*frag)), 444 ("! (*frag == NULL || BUFFER_FRAGMENTS(*frag)): %s", __FUNCTION__)); 445#else |
446 KASSERT(*frag == NULL || BUFFER_FRAGMENTS(*frag)); |
447#endif |
448 449 /* Strip off ip header */ 450 m->m_data += hlen; 451 m->m_len -= hlen; 452 453 /* Create a new reassembly queue for this packet */ 454 if (*frag == NULL) { 455 *frag = pool_get(&pf_frag_pl, PR_NOWAIT); --- 5 unchanged lines hidden (view full) --- 461 } 462 463 (*frag)->fr_flags = 0; 464 (*frag)->fr_max = 0; 465 (*frag)->fr_src = frent->fr_ip->ip_src; 466 (*frag)->fr_dst = frent->fr_ip->ip_dst; 467 (*frag)->fr_p = frent->fr_ip->ip_p; 468 (*frag)->fr_id = frent->fr_ip->ip_id; |
469#if defined(__FreeBSD__) 470 (*frag)->fr_timeout = time_second; 471#else |
472 (*frag)->fr_timeout = time.tv_sec; |
473#endif |
474 LIST_INIT(&(*frag)->fr_queue); 475 476 RB_INSERT(pf_frag_tree, &pf_frag_tree, *frag); 477 TAILQ_INSERT_HEAD(&pf_fragqueue, *frag, frag_next); 478 479 /* We do not have a previous fragment */ 480 frep = NULL; 481 goto insert; --- 4 unchanged lines hidden (view full) --- 486 * - off contains the real shifted offset. 487 */ 488 LIST_FOREACH(frea, &(*frag)->fr_queue, fr_next) { 489 if (FR_IP_OFF(frea) > off) 490 break; 491 frep = frea; 492 } 493 |
494#if defined(__FreeBSD__) 495 KASSERT((frep != NULL || frea != NULL), 496 ("!(frep != NULL || frea != NULL): %s", __FUNCTION__));; 497#else |
498 KASSERT(frep != NULL || frea != NULL); |
499#endif |
500 501 if (frep != NULL && 502 FR_IP_OFF(frep) + ntohs(frep->fr_ip->ip_len) - frep->fr_ip->ip_hl * 503 4 > off) 504 { 505 u_int16_t precut; 506 507 precut = FR_IP_OFF(frep) + ntohs(frep->fr_ip->ip_len) - --- 68 unchanged lines hidden (view full) --- 576 } 577 } 578 DPFPRINTF(("%d < %d?\n", off, (*frag)->fr_max)); 579 if (off < (*frag)->fr_max) 580 return (NULL); 581 582 /* We have all the data */ 583 frent = LIST_FIRST(&(*frag)->fr_queue); |
584#if defined(__FreeBSD__) 585 KASSERT((frent != NULL), ("frent == NULL: %s", __FUNCTION__)); 586#else |
587 KASSERT(frent != NULL); |
588#endif |
589 if ((frent->fr_ip->ip_hl << 2) + off > IP_MAXPACKET) { 590 DPFPRINTF(("drop: too big: %d\n", off)); 591 pf_free_fragment(*frag); 592 *frag = NULL; 593 return (NULL); 594 } 595 next = LIST_NEXT(frent, fr_next); 596 --- 52 unchanged lines hidden (view full) --- 649{ 650 struct mbuf *m = *m0; 651 struct pf_frcache *frp, *fra, *cur = NULL; 652 int ip_len = ntohs(h->ip_len) - (h->ip_hl << 2); 653 u_int16_t off = ntohs(h->ip_off) << 3; 654 u_int16_t max = ip_len + off; 655 int hosed = 0; 656 |
657#if defined(__FreeBSD__) 658 KASSERT((*frag == NULL || !BUFFER_FRAGMENTS(*frag)), 659 ("!(*frag == NULL || !BUFFER_FRAGMENTS(*frag)): %s", __FUNCTION__)); 660#else |
661 KASSERT(*frag == NULL || !BUFFER_FRAGMENTS(*frag)); |
662#endif |
663 664 /* Create a new range queue for this packet */ 665 if (*frag == NULL) { 666 *frag = pool_get(&pf_cache_pl, PR_NOWAIT); 667 if (*frag == NULL) { 668 pf_flush_fragments(); 669 *frag = pool_get(&pf_cache_pl, PR_NOWAIT); 670 if (*frag == NULL) --- 10 unchanged lines hidden (view full) --- 681 pf_ncache++; 682 683 (*frag)->fr_flags = PFFRAG_NOBUFFER; 684 (*frag)->fr_max = 0; 685 (*frag)->fr_src = h->ip_src; 686 (*frag)->fr_dst = h->ip_dst; 687 (*frag)->fr_p = h->ip_p; 688 (*frag)->fr_id = h->ip_id; |
689#if defined(__FreeBSD__) 690 (*frag)->fr_timeout = time_second; 691#else |
692 (*frag)->fr_timeout = time.tv_sec; |
693#endif |
694 695 cur->fr_off = off; 696 cur->fr_end = max; 697 LIST_INIT(&(*frag)->fr_cache); 698 LIST_INSERT_HEAD(&(*frag)->fr_cache, cur, fr_next); 699 700 RB_INSERT(pf_frag_tree, &pf_cache_tree, *frag); 701 TAILQ_INSERT_HEAD(&pf_cachequeue, *frag, frag_next); --- 9 unchanged lines hidden (view full) --- 711 */ 712 frp = NULL; 713 LIST_FOREACH(fra, &(*frag)->fr_cache, fr_next) { 714 if (fra->fr_off > off) 715 break; 716 frp = fra; 717 } 718 |
719#if defined(__FreeBSD__) 720 KASSERT((frp != NULL || fra != NULL), 721 ("!(frp != NULL || fra != NULL): %s", __FUNCTION__)); 722#else |
723 KASSERT(frp != NULL || fra != NULL); |
724#endif |
725 726 if (frp != NULL) { 727 int precut; 728 729 precut = frp->fr_end - off; 730 if (precut >= ip_len) { 731 /* Fragment is entirely a duplicate */ 732 DPFPRINTF(("fragcache[%d]: dead (%d-%d) %d-%d\n", --- 25 unchanged lines hidden (view full) --- 758 if (!drop) { 759 /* XXX Optimization opportunity 760 * This is a very heavy way to trim the payload. 761 * we could do it much faster by diddling mbuf 762 * internals but that would be even less legible 763 * than this mbuf magic. For my next trick, 764 * I'll pull a rabbit out of my laptop. 765 */ |
766#if defined(__FreeBSD__) 767 *m0 = m_dup(m, M_DONTWAIT); 768 /* From KAME Project : We have missed this! */ 769 m_adj(*m0, (h->ip_hl << 2) - 770 (*m0)->m_pkthdr.len); 771#else |
772 *m0 = m_copym2(m, 0, h->ip_hl << 2, M_NOWAIT); |
773#endif |
774 if (*m0 == NULL) 775 goto no_mem; |
776#if defined(__FreeBSD__) 777 KASSERT(((*m0)->m_next == NULL), 778 ("(*m0)->m_next != NULL: %s", 779 __FUNCTION__)); 780#else |
781 KASSERT((*m0)->m_next == NULL); |
782#endif |
783 m_adj(m, precut + (h->ip_hl << 2)); 784 m_cat(*m0, m); 785 m = *m0; 786 if (m->m_flags & M_PKTHDR) { 787 int plen = 0; 788 struct mbuf *t; 789 for (t = m; t; t = t->m_next) 790 plen += t->m_len; 791 m->m_pkthdr.len = plen; 792 } 793 794 795 h = mtod(m, struct ip *); 796 |
797#if defined(__FreeBSD__) 798 KASSERT(((int)m->m_len == ntohs(h->ip_len) - precut), 799 ("m->m_len != ntohs(h->ip_len) - precut: %s", 800 __FUNCTION__)); 801#else |
802 KASSERT((int)m->m_len == ntohs(h->ip_len) - precut); |
803#endif |
804 h->ip_off = htons(ntohs(h->ip_off) + (precut >> 3)); 805 h->ip_len = htons(ntohs(h->ip_len) - precut); 806 } else { 807 hosed++; 808 } 809 } else { 810 /* There is a gap between fragments */ 811 --- 38 unchanged lines hidden (view full) --- 850 if (m->m_flags & M_PKTHDR) { 851 int plen = 0; 852 struct mbuf *t; 853 for (t = m; t; t = t->m_next) 854 plen += t->m_len; 855 m->m_pkthdr.len = plen; 856 } 857 h = mtod(m, struct ip *); |
858#if defined(__FreeBSD__) 859 KASSERT(((int)m->m_len == ntohs(h->ip_len) - aftercut), 860 ("m->m_len != ntohs(h->ip_len) - aftercut: %s", 861 __FUNCTION__)); 862#else |
863 KASSERT((int)m->m_len == ntohs(h->ip_len) - aftercut); |
864#endif |
865 h->ip_len = htons(ntohs(h->ip_len) - aftercut); 866 } else { 867 hosed++; 868 } 869 } else { 870 /* There is a gap between fragments */ 871 DPFPRINTF(("fragcache[%d]: gap %d %d-%d (%d-%d)\n", 872 h->ip_id, -aftercut, off, max, fra->fr_off, --- 21 unchanged lines hidden (view full) --- 894 fra->fr_off = cur->fr_off; 895 LIST_REMOVE(cur, fr_next); 896 pool_put(&pf_cent_pl, cur); 897 pf_ncache--; 898 cur = NULL; 899 900 } else if (frp && fra->fr_off <= frp->fr_end) { 901 /* Need to merge in a modified 'frp' */ |
902#if defined(__FreeBSD__) 903 KASSERT((cur == NULL), ("cur != NULL: %s", 904 __FUNCTION__)); 905#else |
906 KASSERT(cur == NULL); |
907#endif |
908 DPFPRINTF(("fragcache[%d]: adjacent(merge " 909 "%d-%d) %d-%d (%d-%d)\n", 910 h->ip_id, frp->fr_off, frp->fr_end, off, 911 max, fra->fr_off, fra->fr_end)); 912 fra->fr_off = frp->fr_off; 913 LIST_REMOVE(frp, fr_next); 914 pool_put(&pf_cent_pl, frp); 915 pf_ncache--; --- 535 unchanged lines hidden (view full) --- 1451 } 1452 1453 /* Process options */ 1454 if (r->max_mss && pf_normalize_tcpopt(r, m, th, off)) 1455 rewrite = 1; 1456 1457 /* copy back packet headers if we sanitized */ 1458 if (rewrite) |
1459 m_copyback(m, off, sizeof(*th), (caddr_t)th); |
1460 1461 return (PF_PASS); 1462 1463 tcp_drop: 1464 REASON_SET(&reason, PFRES_NORM); 1465 if (rm != NULL && r->log) 1466 PFLOG_PACKET(ifp, h, m, AF_INET, dir, reason, r, NULL, NULL); 1467 return (PF_DROP); 1468} 1469 1470int 1471pf_normalize_tcp_init(struct mbuf *m, int off, struct pf_pdesc *pd, 1472 struct tcphdr *th, struct pf_state_peer *src, struct pf_state_peer *dst) 1473{ 1474 u_int8_t hdr[60]; 1475 u_int8_t *opt; 1476 |
1477#if defined(__FreeBSD__) 1478 KASSERT((src->scrub == NULL), 1479 ("pf_normalize_tcp_init: src->scrub != NULL")); 1480#else |
1481 KASSERT(src->scrub == NULL); |
1482#endif |
1483 1484 src->scrub = pool_get(&pf_state_scrub_pl, PR_NOWAIT); 1485 if (src->scrub == NULL) 1486 return (1); 1487 bzero(src->scrub, sizeof(*src->scrub)); 1488 1489 switch (pd->af) { 1490#ifdef INET --- 67 unchanged lines hidden (view full) --- 1558pf_normalize_tcp_stateful(struct mbuf *m, int off, struct pf_pdesc *pd, 1559 u_short *reason, struct tcphdr *th, struct pf_state_peer *src, 1560 struct pf_state_peer *dst, int *writeback) 1561{ 1562 u_int8_t hdr[60]; 1563 u_int8_t *opt; 1564 int copyback = 0; 1565 |
1566#if defined(__FreeBSD__) 1567 KASSERT((src->scrub || dst->scrub), 1568 ("pf_normalize_tcp_statefull: src->scrub && dst->scrub!")); 1569#else |
1570 KASSERT(src->scrub || dst->scrub); |
1571#endif |
1572 1573 /* 1574 * Enforce the minimum TTL seen for this connection. Negate a common 1575 * technique to evade an intrusion detection system and confuse 1576 * firewall state code. 1577 */ 1578 switch (pd->af) { 1579#ifdef INET --- 132 unchanged lines hidden --- |