This source file includes following definitions.
- TAILQ_HEAD
- pf_normalize_init
- pf_frag_compare
- pf_purge_expired_fragments
- pf_flush_fragments
- pf_free_fragment
- pf_ip2key
- pf_find_fragment
- pf_remove_fragment
- pf_reassemble
- pf_fragcache
- pf_normalize_ip
- pf_normalize_ip6
- pf_normalize_tcp
- pf_normalize_tcp_init
- pf_normalize_tcp_cleanup
- pf_normalize_tcp_stateful
- pf_normalize_tcpopt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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
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
76 #define PFFRAG_NOBUFFER 0x0002
77 #define PFFRAG_DROP 0x0004
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;
86 u_int8_t fr_flags;
87 u_int16_t fr_id;
88 u_int16_t fr_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;
94 LIST_HEAD(pf_cacheq, pf_frcache) fru_cache;
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
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 int pf_normalize_tcpopt(struct pf_rule *, struct mbuf *,
118 struct tcphdr *, int);
119
120 #define DPFPRINTF(x) do { \
121 if (pf_status.debug >= PF_DEBUG_MISC) { \
122 printf("%s: ", __func__); \
123 printf x ; \
124 } \
125 } while(0)
126
127
128 struct pool pf_frent_pl, pf_frag_pl, pf_cache_pl, pf_cent_pl;
129 struct pool pf_state_scrub_pl;
130 int pf_nfrents, pf_ncache;
131
132 void
133 pf_normalize_init(void)
134 {
135 pool_init(&pf_frent_pl, sizeof(struct pf_frent), 0, 0, 0, "pffrent",
136 NULL);
137 pool_init(&pf_frag_pl, sizeof(struct pf_fragment), 0, 0, 0, "pffrag",
138 NULL);
139 pool_init(&pf_cache_pl, sizeof(struct pf_fragment), 0, 0, 0,
140 "pffrcache", NULL);
141 pool_init(&pf_cent_pl, sizeof(struct pf_frcache), 0, 0, 0, "pffrcent",
142 NULL);
143 pool_init(&pf_state_scrub_pl, sizeof(struct pf_state_scrub), 0, 0, 0,
144 "pfstscr", NULL);
145
146 pool_sethiwat(&pf_frag_pl, PFFRAG_FRAG_HIWAT);
147 pool_sethardlimit(&pf_frent_pl, PFFRAG_FRENT_HIWAT, NULL, 0);
148 pool_sethardlimit(&pf_cache_pl, PFFRAG_FRCACHE_HIWAT, NULL, 0);
149 pool_sethardlimit(&pf_cent_pl, PFFRAG_FRCENT_HIWAT, NULL, 0);
150
151 TAILQ_INIT(&pf_fragqueue);
152 TAILQ_INIT(&pf_cachequeue);
153 }
154
155 static __inline int
156 pf_frag_compare(struct pf_fragment *a, struct pf_fragment *b)
157 {
158 int diff;
159
160 if ((diff = a->fr_id - b->fr_id))
161 return (diff);
162 else if ((diff = a->fr_p - b->fr_p))
163 return (diff);
164 else if (a->fr_src.s_addr < b->fr_src.s_addr)
165 return (-1);
166 else if (a->fr_src.s_addr > b->fr_src.s_addr)
167 return (1);
168 else if (a->fr_dst.s_addr < b->fr_dst.s_addr)
169 return (-1);
170 else if (a->fr_dst.s_addr > b->fr_dst.s_addr)
171 return (1);
172 return (0);
173 }
174
175 void
176 pf_purge_expired_fragments(void)
177 {
178 struct pf_fragment *frag;
179 u_int32_t expire = time_second -
180 pf_default_rule.timeout[PFTM_FRAG];
181
182 while ((frag = TAILQ_LAST(&pf_fragqueue, pf_fragqueue)) != NULL) {
183 KASSERT(BUFFER_FRAGMENTS(frag));
184 if (frag->fr_timeout > expire)
185 break;
186
187 DPFPRINTF(("expiring %d(%p)\n", frag->fr_id, frag));
188 pf_free_fragment(frag);
189 }
190
191 while ((frag = TAILQ_LAST(&pf_cachequeue, pf_cachequeue)) != NULL) {
192 KASSERT(!BUFFER_FRAGMENTS(frag));
193 if (frag->fr_timeout > expire)
194 break;
195
196 DPFPRINTF(("expiring %d(%p)\n", frag->fr_id, frag));
197 pf_free_fragment(frag);
198 KASSERT(TAILQ_EMPTY(&pf_cachequeue) ||
199 TAILQ_LAST(&pf_cachequeue, pf_cachequeue) != frag);
200 }
201 }
202
203
204
205
206
207 void
208 pf_flush_fragments(void)
209 {
210 struct pf_fragment *frag;
211 int goal;
212
213 goal = pf_nfrents * 9 / 10;
214 DPFPRINTF(("trying to free > %d frents\n",
215 pf_nfrents - goal));
216 while (goal < pf_nfrents) {
217 frag = TAILQ_LAST(&pf_fragqueue, pf_fragqueue);
218 if (frag == NULL)
219 break;
220 pf_free_fragment(frag);
221 }
222
223
224 goal = pf_ncache * 9 / 10;
225 DPFPRINTF(("trying to free > %d cache entries\n",
226 pf_ncache - goal));
227 while (goal < pf_ncache) {
228 frag = TAILQ_LAST(&pf_cachequeue, pf_cachequeue);
229 if (frag == NULL)
230 break;
231 pf_free_fragment(frag);
232 }
233 }
234
235
236
237 void
238 pf_free_fragment(struct pf_fragment *frag)
239 {
240 struct pf_frent *frent;
241 struct pf_frcache *frcache;
242
243
244 if (BUFFER_FRAGMENTS(frag)) {
245 for (frent = LIST_FIRST(&frag->fr_queue); frent;
246 frent = LIST_FIRST(&frag->fr_queue)) {
247 LIST_REMOVE(frent, fr_next);
248
249 m_freem(frent->fr_m);
250 pool_put(&pf_frent_pl, frent);
251 pf_nfrents--;
252 }
253 } else {
254 for (frcache = LIST_FIRST(&frag->fr_cache); frcache;
255 frcache = LIST_FIRST(&frag->fr_cache)) {
256 LIST_REMOVE(frcache, fr_next);
257
258 KASSERT(LIST_EMPTY(&frag->fr_cache) ||
259 LIST_FIRST(&frag->fr_cache)->fr_off >
260 frcache->fr_end);
261
262 pool_put(&pf_cent_pl, frcache);
263 pf_ncache--;
264 }
265 }
266
267 pf_remove_fragment(frag);
268 }
269
270 void
271 pf_ip2key(struct pf_fragment *key, struct ip *ip)
272 {
273 key->fr_p = ip->ip_p;
274 key->fr_id = ip->ip_id;
275 key->fr_src.s_addr = ip->ip_src.s_addr;
276 key->fr_dst.s_addr = ip->ip_dst.s_addr;
277 }
278
279 struct pf_fragment *
280 pf_find_fragment(struct ip *ip, struct pf_frag_tree *tree)
281 {
282 struct pf_fragment key;
283 struct pf_fragment *frag;
284
285 pf_ip2key(&key, ip);
286
287 frag = RB_FIND(pf_frag_tree, tree, &key);
288 if (frag != NULL) {
289
290 frag->fr_timeout = time_second;
291 if (BUFFER_FRAGMENTS(frag)) {
292 TAILQ_REMOVE(&pf_fragqueue, frag, frag_next);
293 TAILQ_INSERT_HEAD(&pf_fragqueue, frag, frag_next);
294 } else {
295 TAILQ_REMOVE(&pf_cachequeue, frag, frag_next);
296 TAILQ_INSERT_HEAD(&pf_cachequeue, frag, frag_next);
297 }
298 }
299
300 return (frag);
301 }
302
303
304
305 void
306 pf_remove_fragment(struct pf_fragment *frag)
307 {
308 if (BUFFER_FRAGMENTS(frag)) {
309 RB_REMOVE(pf_frag_tree, &pf_frag_tree, frag);
310 TAILQ_REMOVE(&pf_fragqueue, frag, frag_next);
311 pool_put(&pf_frag_pl, frag);
312 } else {
313 RB_REMOVE(pf_frag_tree, &pf_cache_tree, frag);
314 TAILQ_REMOVE(&pf_cachequeue, frag, frag_next);
315 pool_put(&pf_cache_pl, frag);
316 }
317 }
318
319 #define FR_IP_OFF(fr) ((ntohs((fr)->fr_ip->ip_off) & IP_OFFMASK) << 3)
320 struct mbuf *
321 pf_reassemble(struct mbuf **m0, struct pf_fragment **frag,
322 struct pf_frent *frent, int mff)
323 {
324 struct mbuf *m = *m0, *m2;
325 struct pf_frent *frea, *next;
326 struct pf_frent *frep = NULL;
327 struct ip *ip = frent->fr_ip;
328 int hlen = ip->ip_hl << 2;
329 u_int16_t off = (ntohs(ip->ip_off) & IP_OFFMASK) << 3;
330 u_int16_t ip_len = ntohs(ip->ip_len) - ip->ip_hl * 4;
331 u_int16_t max = ip_len + off;
332
333 KASSERT(*frag == NULL || BUFFER_FRAGMENTS(*frag));
334
335
336 m->m_data += hlen;
337 m->m_len -= hlen;
338
339
340 if (*frag == NULL) {
341 *frag = pool_get(&pf_frag_pl, PR_NOWAIT);
342 if (*frag == NULL) {
343 pf_flush_fragments();
344 *frag = pool_get(&pf_frag_pl, PR_NOWAIT);
345 if (*frag == NULL)
346 goto drop_fragment;
347 }
348
349 (*frag)->fr_flags = 0;
350 (*frag)->fr_max = 0;
351 (*frag)->fr_src = frent->fr_ip->ip_src;
352 (*frag)->fr_dst = frent->fr_ip->ip_dst;
353 (*frag)->fr_p = frent->fr_ip->ip_p;
354 (*frag)->fr_id = frent->fr_ip->ip_id;
355 (*frag)->fr_timeout = time_second;
356 LIST_INIT(&(*frag)->fr_queue);
357
358 RB_INSERT(pf_frag_tree, &pf_frag_tree, *frag);
359 TAILQ_INSERT_HEAD(&pf_fragqueue, *frag, frag_next);
360
361
362 frep = NULL;
363 goto insert;
364 }
365
366
367
368
369
370 LIST_FOREACH(frea, &(*frag)->fr_queue, fr_next) {
371 if (FR_IP_OFF(frea) > off)
372 break;
373 frep = frea;
374 }
375
376 KASSERT(frep != NULL || frea != NULL);
377
378 if (frep != NULL &&
379 FR_IP_OFF(frep) + ntohs(frep->fr_ip->ip_len) - frep->fr_ip->ip_hl *
380 4 > off)
381 {
382 u_int16_t precut;
383
384 precut = FR_IP_OFF(frep) + ntohs(frep->fr_ip->ip_len) -
385 frep->fr_ip->ip_hl * 4 - off;
386 if (precut >= ip_len)
387 goto drop_fragment;
388 m_adj(frent->fr_m, precut);
389 DPFPRINTF(("overlap -%d\n", precut));
390
391 ip->ip_off = htons(ntohs(ip->ip_off) + (precut >> 3));
392 off = (ntohs(ip->ip_off) & IP_OFFMASK) << 3;
393 ip_len -= precut;
394 ip->ip_len = htons(ip_len);
395 }
396
397 for (; frea != NULL && ip_len + off > FR_IP_OFF(frea);
398 frea = next)
399 {
400 u_int16_t aftercut;
401
402 aftercut = ip_len + off - FR_IP_OFF(frea);
403 DPFPRINTF(("adjust overlap %d\n", aftercut));
404 if (aftercut < ntohs(frea->fr_ip->ip_len) - frea->fr_ip->ip_hl
405 * 4)
406 {
407 frea->fr_ip->ip_len =
408 htons(ntohs(frea->fr_ip->ip_len) - aftercut);
409 frea->fr_ip->ip_off = htons(ntohs(frea->fr_ip->ip_off) +
410 (aftercut >> 3));
411 m_adj(frea->fr_m, aftercut);
412 break;
413 }
414
415
416 next = LIST_NEXT(frea, fr_next);
417 m_freem(frea->fr_m);
418 LIST_REMOVE(frea, fr_next);
419 pool_put(&pf_frent_pl, frea);
420 pf_nfrents--;
421 }
422
423 insert:
424
425 if ((*frag)->fr_max < max)
426 (*frag)->fr_max = max;
427
428 if (!mff)
429 (*frag)->fr_flags |= PFFRAG_SEENLAST;
430
431 if (frep == NULL)
432 LIST_INSERT_HEAD(&(*frag)->fr_queue, frent, fr_next);
433 else
434 LIST_INSERT_AFTER(frep, frent, fr_next);
435
436
437 if (!((*frag)->fr_flags & PFFRAG_SEENLAST))
438 return (NULL);
439
440
441 off = 0;
442 for (frep = LIST_FIRST(&(*frag)->fr_queue); frep; frep = next) {
443 next = LIST_NEXT(frep, fr_next);
444
445 off += ntohs(frep->fr_ip->ip_len) - frep->fr_ip->ip_hl * 4;
446 if (off < (*frag)->fr_max &&
447 (next == NULL || FR_IP_OFF(next) != off))
448 {
449 DPFPRINTF(("missing fragment at %d, next %d, max %d\n",
450 off, next == NULL ? -1 : FR_IP_OFF(next),
451 (*frag)->fr_max));
452 return (NULL);
453 }
454 }
455 DPFPRINTF(("%d < %d?\n", off, (*frag)->fr_max));
456 if (off < (*frag)->fr_max)
457 return (NULL);
458
459
460 frent = LIST_FIRST(&(*frag)->fr_queue);
461 KASSERT(frent != NULL);
462 if ((frent->fr_ip->ip_hl << 2) + off > IP_MAXPACKET) {
463 DPFPRINTF(("drop: too big: %d\n", off));
464 pf_free_fragment(*frag);
465 *frag = NULL;
466 return (NULL);
467 }
468 next = LIST_NEXT(frent, fr_next);
469
470
471 ip = frent->fr_ip;
472 m = frent->fr_m;
473 m2 = m->m_next;
474 m->m_next = NULL;
475 m_cat(m, m2);
476 pool_put(&pf_frent_pl, frent);
477 pf_nfrents--;
478 for (frent = next; frent != NULL; frent = next) {
479 next = LIST_NEXT(frent, fr_next);
480
481 m2 = frent->fr_m;
482 pool_put(&pf_frent_pl, frent);
483 pf_nfrents--;
484 m_cat(m, m2);
485 }
486
487 ip->ip_src = (*frag)->fr_src;
488 ip->ip_dst = (*frag)->fr_dst;
489
490
491 pf_remove_fragment(*frag);
492 *frag = NULL;
493
494 hlen = ip->ip_hl << 2;
495 ip->ip_len = htons(off + hlen);
496 m->m_len += hlen;
497 m->m_data -= hlen;
498
499
500
501 if (m->m_flags & M_PKTHDR) {
502 int plen = 0;
503 for (m2 = m; m2; m2 = m2->m_next)
504 plen += m2->m_len;
505 m->m_pkthdr.len = plen;
506 }
507
508 DPFPRINTF(("complete: %p(%d)\n", m, ntohs(ip->ip_len)));
509 return (m);
510
511 drop_fragment:
512
513 pool_put(&pf_frent_pl, frent);
514 pf_nfrents--;
515 m_freem(m);
516 return (NULL);
517 }
518
519 struct mbuf *
520 pf_fragcache(struct mbuf **m0, struct ip *h, struct pf_fragment **frag, int mff,
521 int drop, int *nomem)
522 {
523 struct mbuf *m = *m0;
524 struct pf_frcache *frp, *fra, *cur = NULL;
525 int ip_len = ntohs(h->ip_len) - (h->ip_hl << 2);
526 u_int16_t off = ntohs(h->ip_off) << 3;
527 u_int16_t max = ip_len + off;
528 int hosed = 0;
529
530 KASSERT(*frag == NULL || !BUFFER_FRAGMENTS(*frag));
531
532
533 if (*frag == NULL) {
534 *frag = pool_get(&pf_cache_pl, PR_NOWAIT);
535 if (*frag == NULL) {
536 pf_flush_fragments();
537 *frag = pool_get(&pf_cache_pl, PR_NOWAIT);
538 if (*frag == NULL)
539 goto no_mem;
540 }
541
542
543 cur = pool_get(&pf_cent_pl, PR_NOWAIT);
544 if (cur == NULL) {
545 pool_put(&pf_cache_pl, *frag);
546 *frag = NULL;
547 goto no_mem;
548 }
549 pf_ncache++;
550
551 (*frag)->fr_flags = PFFRAG_NOBUFFER;
552 (*frag)->fr_max = 0;
553 (*frag)->fr_src = h->ip_src;
554 (*frag)->fr_dst = h->ip_dst;
555 (*frag)->fr_p = h->ip_p;
556 (*frag)->fr_id = h->ip_id;
557 (*frag)->fr_timeout = time_second;
558
559 cur->fr_off = off;
560 cur->fr_end = max;
561 LIST_INIT(&(*frag)->fr_cache);
562 LIST_INSERT_HEAD(&(*frag)->fr_cache, cur, fr_next);
563
564 RB_INSERT(pf_frag_tree, &pf_cache_tree, *frag);
565 TAILQ_INSERT_HEAD(&pf_cachequeue, *frag, frag_next);
566
567 DPFPRINTF(("fragcache[%d]: new %d-%d\n", h->ip_id, off, max));
568
569 goto pass;
570 }
571
572
573
574
575
576 frp = NULL;
577 LIST_FOREACH(fra, &(*frag)->fr_cache, fr_next) {
578 if (fra->fr_off > off)
579 break;
580 frp = fra;
581 }
582
583 KASSERT(frp != NULL || fra != NULL);
584
585 if (frp != NULL) {
586 int precut;
587
588 precut = frp->fr_end - off;
589 if (precut >= ip_len) {
590
591 DPFPRINTF(("fragcache[%d]: dead (%d-%d) %d-%d\n",
592 h->ip_id, frp->fr_off, frp->fr_end, off, max));
593 goto drop_fragment;
594 }
595 if (precut == 0) {
596
597 DPFPRINTF(("fragcache[%d]: adjacent (%d-%d) %d-%d\n",
598 h->ip_id, frp->fr_off, frp->fr_end, off, max));
599 frp->fr_end = max;
600 } else if (precut > 0) {
601
602
603
604
605
606
607
608 DPFPRINTF(("fragcache[%d]: chop %d (%d-%d) %d-%d\n",
609 h->ip_id, precut, frp->fr_off, frp->fr_end, off,
610 max));
611
612 off += precut;
613 max -= precut;
614
615 frp->fr_end = max;
616
617 if (!drop) {
618
619
620
621
622
623
624
625 *m0 = m_copym2(m, 0, h->ip_hl << 2, M_NOWAIT);
626 if (*m0 == NULL)
627 goto no_mem;
628 KASSERT((*m0)->m_next == NULL);
629 m_adj(m, precut + (h->ip_hl << 2));
630 m_cat(*m0, m);
631 m = *m0;
632 if (m->m_flags & M_PKTHDR) {
633 int plen = 0;
634 struct mbuf *t;
635 for (t = m; t; t = t->m_next)
636 plen += t->m_len;
637 m->m_pkthdr.len = plen;
638 }
639
640
641 h = mtod(m, struct ip *);
642
643
644 KASSERT((int)m->m_len ==
645 ntohs(h->ip_len) - precut);
646 h->ip_off = htons(ntohs(h->ip_off) +
647 (precut >> 3));
648 h->ip_len = htons(ntohs(h->ip_len) - precut);
649 } else {
650 hosed++;
651 }
652 } else {
653
654
655 DPFPRINTF(("fragcache[%d]: gap %d (%d-%d) %d-%d\n",
656 h->ip_id, -precut, frp->fr_off, frp->fr_end, off,
657 max));
658
659 cur = pool_get(&pf_cent_pl, PR_NOWAIT);
660 if (cur == NULL)
661 goto no_mem;
662 pf_ncache++;
663
664 cur->fr_off = off;
665 cur->fr_end = max;
666 LIST_INSERT_AFTER(frp, cur, fr_next);
667 }
668 }
669
670 if (fra != NULL) {
671 int aftercut;
672 int merge = 0;
673
674 aftercut = max - fra->fr_off;
675 if (aftercut == 0) {
676
677 DPFPRINTF(("fragcache[%d]: adjacent %d-%d (%d-%d)\n",
678 h->ip_id, off, max, fra->fr_off, fra->fr_end));
679 fra->fr_off = off;
680 merge = 1;
681 } else if (aftercut > 0) {
682
683 DPFPRINTF(("fragcache[%d]: chop %d %d-%d (%d-%d)\n",
684 h->ip_id, aftercut, off, max, fra->fr_off,
685 fra->fr_end));
686 fra->fr_off = off;
687 max -= aftercut;
688
689 merge = 1;
690
691 if (!drop) {
692 m_adj(m, -aftercut);
693 if (m->m_flags & M_PKTHDR) {
694 int plen = 0;
695 struct mbuf *t;
696 for (t = m; t; t = t->m_next)
697 plen += t->m_len;
698 m->m_pkthdr.len = plen;
699 }
700 h = mtod(m, struct ip *);
701 KASSERT((int)m->m_len ==
702 ntohs(h->ip_len) - aftercut);
703 h->ip_len = htons(ntohs(h->ip_len) - aftercut);
704 } else {
705 hosed++;
706 }
707 } else if (frp == NULL) {
708
709 DPFPRINTF(("fragcache[%d]: gap %d %d-%d (%d-%d)\n",
710 h->ip_id, -aftercut, off, max, fra->fr_off,
711 fra->fr_end));
712
713 cur = pool_get(&pf_cent_pl, PR_NOWAIT);
714 if (cur == NULL)
715 goto no_mem;
716 pf_ncache++;
717
718 cur->fr_off = off;
719 cur->fr_end = max;
720 LIST_INSERT_BEFORE(fra, cur, fr_next);
721 }
722
723
724
725 if (merge) {
726 if (cur && fra->fr_off <= cur->fr_end) {
727
728 DPFPRINTF(("fragcache[%d]: adjacent(merge "
729 "%d-%d) %d-%d (%d-%d)\n",
730 h->ip_id, cur->fr_off, cur->fr_end, off,
731 max, fra->fr_off, fra->fr_end));
732 fra->fr_off = cur->fr_off;
733 LIST_REMOVE(cur, fr_next);
734 pool_put(&pf_cent_pl, cur);
735 pf_ncache--;
736 cur = NULL;
737
738 } else if (frp && fra->fr_off <= frp->fr_end) {
739
740 KASSERT(cur == NULL);
741 DPFPRINTF(("fragcache[%d]: adjacent(merge "
742 "%d-%d) %d-%d (%d-%d)\n",
743 h->ip_id, frp->fr_off, frp->fr_end, off,
744 max, fra->fr_off, fra->fr_end));
745 fra->fr_off = frp->fr_off;
746 LIST_REMOVE(frp, fr_next);
747 pool_put(&pf_cent_pl, frp);
748 pf_ncache--;
749 frp = NULL;
750
751 }
752 }
753 }
754
755 if (hosed) {
756
757
758
759
760
761 goto drop_fragment;
762 }
763
764
765 pass:
766
767 if ((*frag)->fr_max < max)
768 (*frag)->fr_max = max;
769
770
771 if (!mff)
772 (*frag)->fr_flags |= PFFRAG_SEENLAST;
773
774
775 if (((*frag)->fr_flags & PFFRAG_SEENLAST) &&
776 LIST_FIRST(&(*frag)->fr_cache)->fr_off == 0 &&
777 LIST_FIRST(&(*frag)->fr_cache)->fr_end == (*frag)->fr_max) {
778
779 DPFPRINTF(("fragcache[%d]: done 0-%d\n", h->ip_id,
780 (*frag)->fr_max));
781 pf_free_fragment(*frag);
782 *frag = NULL;
783 }
784
785 return (m);
786
787 no_mem:
788 *nomem = 1;
789
790
791 if (!mff && *frag != NULL)
792 (*frag)->fr_flags |= PFFRAG_SEENLAST;
793
794 m_freem(m);
795 return (NULL);
796
797 drop_fragment:
798
799
800 if (!mff && *frag != NULL)
801 (*frag)->fr_flags |= PFFRAG_SEENLAST;
802
803 if (drop) {
804
805 if (((*frag)->fr_flags & PFFRAG_DROP) == 0)
806 DPFPRINTF(("fragcache[%d]: dropping overall fragment\n",
807 h->ip_id));
808 (*frag)->fr_flags |= PFFRAG_DROP;
809 }
810
811 m_freem(m);
812 return (NULL);
813 }
814
815 int
816 pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason,
817 struct pf_pdesc *pd)
818 {
819 struct mbuf *m = *m0;
820 struct pf_rule *r;
821 struct pf_frent *frent;
822 struct pf_fragment *frag = NULL;
823 struct ip *h = mtod(m, struct ip *);
824 int mff = (ntohs(h->ip_off) & IP_MF);
825 int hlen = h->ip_hl << 2;
826 u_int16_t fragoff = (ntohs(h->ip_off) & IP_OFFMASK) << 3;
827 u_int16_t max;
828 int ip_len;
829 int ip_off;
830
831 r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_SCRUB].active.ptr);
832 while (r != NULL) {
833 r->evaluations++;
834 if (pfi_kif_match(r->kif, kif) == r->ifnot)
835 r = r->skip[PF_SKIP_IFP].ptr;
836 else if (r->direction && r->direction != dir)
837 r = r->skip[PF_SKIP_DIR].ptr;
838 else if (r->af && r->af != AF_INET)
839 r = r->skip[PF_SKIP_AF].ptr;
840 else if (r->proto && r->proto != h->ip_p)
841 r = r->skip[PF_SKIP_PROTO].ptr;
842 else if (PF_MISMATCHAW(&r->src.addr,
843 (struct pf_addr *)&h->ip_src.s_addr, AF_INET,
844 r->src.neg, kif))
845 r = r->skip[PF_SKIP_SRC_ADDR].ptr;
846 else if (PF_MISMATCHAW(&r->dst.addr,
847 (struct pf_addr *)&h->ip_dst.s_addr, AF_INET,
848 r->dst.neg, NULL))
849 r = r->skip[PF_SKIP_DST_ADDR].ptr;
850 else
851 break;
852 }
853
854 if (r == NULL || r->action == PF_NOSCRUB)
855 return (PF_PASS);
856 else {
857 r->packets[dir == PF_OUT]++;
858 r->bytes[dir == PF_OUT] += pd->tot_len;
859 }
860
861
862 if (hlen < (int)sizeof(struct ip))
863 goto drop;
864
865 if (hlen > ntohs(h->ip_len))
866 goto drop;
867
868
869 if (r->rule_flag & PFRULE_NODF && h->ip_off & htons(IP_DF)) {
870 u_int16_t ip_off = h->ip_off;
871
872 h->ip_off &= htons(~IP_DF);
873 h->ip_sum = pf_cksum_fixup(h->ip_sum, ip_off, h->ip_off, 0);
874 }
875
876
877 if (!fragoff && !mff)
878 goto no_fragment;
879
880
881
882
883
884 if (h->ip_off & htons(IP_DF)) {
885 DPFPRINTF(("IP_DF\n"));
886 goto bad;
887 }
888
889 ip_len = ntohs(h->ip_len) - hlen;
890 ip_off = (ntohs(h->ip_off) & IP_OFFMASK) << 3;
891
892
893 if (mff && (ip_len & 0x7)) {
894 DPFPRINTF(("mff and %d\n", ip_len));
895 goto bad;
896 }
897
898
899 if (fragoff + ip_len > IP_MAXPACKET) {
900 DPFPRINTF(("max packet %d\n", fragoff + ip_len));
901 goto bad;
902 }
903 max = fragoff + ip_len;
904
905 if ((r->rule_flag & (PFRULE_FRAGCROP|PFRULE_FRAGDROP)) == 0) {
906
907
908 frag = pf_find_fragment(h, &pf_frag_tree);
909
910
911 if (frag != NULL && (frag->fr_flags & PFFRAG_SEENLAST) &&
912 max > frag->fr_max)
913 goto bad;
914
915
916 frent = pool_get(&pf_frent_pl, PR_NOWAIT);
917 if (frent == NULL) {
918 REASON_SET(reason, PFRES_MEMORY);
919 return (PF_DROP);
920 }
921 pf_nfrents++;
922 frent->fr_ip = h;
923 frent->fr_m = m;
924
925
926 DPFPRINTF(("reass frag %d @ %d-%d\n", h->ip_id, fragoff, max));
927 *m0 = m = pf_reassemble(m0, &frag, frent, mff);
928
929 if (m == NULL)
930 return (PF_DROP);
931
932 if (frag != NULL && (frag->fr_flags & PFFRAG_DROP))
933 goto drop;
934
935 h = mtod(m, struct ip *);
936 } else {
937
938 int nomem = 0;
939
940 if (dir == PF_OUT && m->m_pkthdr.pf.flags & PF_TAG_FRAGCACHE) {
941
942
943
944
945
946 goto fragment_pass;
947 }
948
949 frag = pf_find_fragment(h, &pf_cache_tree);
950
951
952 if (frag != NULL && (frag->fr_flags & PFFRAG_SEENLAST) &&
953 max > frag->fr_max) {
954 if (r->rule_flag & PFRULE_FRAGDROP)
955 frag->fr_flags |= PFFRAG_DROP;
956 goto bad;
957 }
958
959 *m0 = m = pf_fragcache(m0, h, &frag, mff,
960 (r->rule_flag & PFRULE_FRAGDROP) ? 1 : 0, &nomem);
961 if (m == NULL) {
962 if (nomem)
963 goto no_mem;
964 goto drop;
965 }
966
967 if (dir == PF_IN)
968 m->m_pkthdr.pf.flags |= PF_TAG_FRAGCACHE;
969
970 if (frag != NULL && (frag->fr_flags & PFFRAG_DROP))
971 goto drop;
972 goto fragment_pass;
973 }
974
975 no_fragment:
976
977 if (h->ip_off & ~htons(IP_DF)) {
978 u_int16_t ip_off = h->ip_off;
979
980 h->ip_off &= htons(IP_DF);
981 h->ip_sum = pf_cksum_fixup(h->ip_sum, ip_off, h->ip_off, 0);
982 }
983
984
985 if (r->min_ttl && h->ip_ttl < r->min_ttl) {
986 u_int16_t ip_ttl = h->ip_ttl;
987
988 h->ip_ttl = r->min_ttl;
989 h->ip_sum = pf_cksum_fixup(h->ip_sum, ip_ttl, h->ip_ttl, 0);
990 }
991
992 if (r->rule_flag & PFRULE_RANDOMID) {
993 u_int16_t ip_id = h->ip_id;
994
995 h->ip_id = ip_randomid();
996 h->ip_sum = pf_cksum_fixup(h->ip_sum, ip_id, h->ip_id, 0);
997 }
998 if ((r->rule_flag & (PFRULE_FRAGCROP|PFRULE_FRAGDROP)) == 0)
999 pd->flags |= PFDESC_IP_REAS;
1000
1001 return (PF_PASS);
1002
1003 fragment_pass:
1004
1005 if (r->min_ttl && h->ip_ttl < r->min_ttl) {
1006 u_int16_t ip_ttl = h->ip_ttl;
1007
1008 h->ip_ttl = r->min_ttl;
1009 h->ip_sum = pf_cksum_fixup(h->ip_sum, ip_ttl, h->ip_ttl, 0);
1010 }
1011 if ((r->rule_flag & (PFRULE_FRAGCROP|PFRULE_FRAGDROP)) == 0)
1012 pd->flags |= PFDESC_IP_REAS;
1013 return (PF_PASS);
1014
1015 no_mem:
1016 REASON_SET(reason, PFRES_MEMORY);
1017 if (r != NULL && r->log)
1018 PFLOG_PACKET(kif, h, m, AF_INET, dir, *reason, r, NULL, NULL, pd);
1019 return (PF_DROP);
1020
1021 drop:
1022 REASON_SET(reason, PFRES_NORM);
1023 if (r != NULL && r->log)
1024 PFLOG_PACKET(kif, h, m, AF_INET, dir, *reason, r, NULL, NULL, pd);
1025 return (PF_DROP);
1026
1027 bad:
1028 DPFPRINTF(("dropping bad fragment\n"));
1029
1030
1031 if (frag != NULL)
1032 pf_free_fragment(frag);
1033
1034 REASON_SET(reason, PFRES_FRAG);
1035 if (r != NULL && r->log)
1036 PFLOG_PACKET(kif, h, m, AF_INET, dir, *reason, r, NULL, NULL, pd);
1037
1038 return (PF_DROP);
1039 }
1040
1041 #ifdef INET6
1042 int
1043 pf_normalize_ip6(struct mbuf **m0, int dir, struct pfi_kif *kif,
1044 u_short *reason, struct pf_pdesc *pd)
1045 {
1046 struct mbuf *m = *m0;
1047 struct pf_rule *r;
1048 struct ip6_hdr *h = mtod(m, struct ip6_hdr *);
1049 int off;
1050 struct ip6_ext ext;
1051 struct ip6_opt opt;
1052 struct ip6_opt_jumbo jumbo;
1053 struct ip6_frag frag;
1054 u_int32_t jumbolen = 0, plen;
1055 u_int16_t fragoff = 0;
1056 int optend;
1057 int ooff;
1058 u_int8_t proto;
1059 int terminal;
1060
1061 r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_SCRUB].active.ptr);
1062 while (r != NULL) {
1063 r->evaluations++;
1064 if (pfi_kif_match(r->kif, kif) == r->ifnot)
1065 r = r->skip[PF_SKIP_IFP].ptr;
1066 else if (r->direction && r->direction != dir)
1067 r = r->skip[PF_SKIP_DIR].ptr;
1068 else if (r->af && r->af != AF_INET6)
1069 r = r->skip[PF_SKIP_AF].ptr;
1070 #if 0
1071 else if (r->proto && r->proto != h->ip6_nxt)
1072 r = r->skip[PF_SKIP_PROTO].ptr;
1073 #endif
1074 else if (PF_MISMATCHAW(&r->src.addr,
1075 (struct pf_addr *)&h->ip6_src, AF_INET6,
1076 r->src.neg, kif))
1077 r = r->skip[PF_SKIP_SRC_ADDR].ptr;
1078 else if (PF_MISMATCHAW(&r->dst.addr,
1079 (struct pf_addr *)&h->ip6_dst, AF_INET6,
1080 r->dst.neg, NULL))
1081 r = r->skip[PF_SKIP_DST_ADDR].ptr;
1082 else
1083 break;
1084 }
1085
1086 if (r == NULL || r->action == PF_NOSCRUB)
1087 return (PF_PASS);
1088 else {
1089 r->packets[dir == PF_OUT]++;
1090 r->bytes[dir == PF_OUT] += pd->tot_len;
1091 }
1092
1093
1094 if (sizeof(struct ip6_hdr) + IPV6_MAXPACKET < m->m_pkthdr.len)
1095 goto drop;
1096
1097 off = sizeof(struct ip6_hdr);
1098 proto = h->ip6_nxt;
1099 terminal = 0;
1100 do {
1101 switch (proto) {
1102 case IPPROTO_FRAGMENT:
1103 goto fragment;
1104 break;
1105 case IPPROTO_AH:
1106 case IPPROTO_ROUTING:
1107 case IPPROTO_DSTOPTS:
1108 if (!pf_pull_hdr(m, off, &ext, sizeof(ext), NULL,
1109 NULL, AF_INET6))
1110 goto shortpkt;
1111 if (proto == IPPROTO_AH)
1112 off += (ext.ip6e_len + 2) * 4;
1113 else
1114 off += (ext.ip6e_len + 1) * 8;
1115 proto = ext.ip6e_nxt;
1116 break;
1117 case IPPROTO_HOPOPTS:
1118 if (!pf_pull_hdr(m, off, &ext, sizeof(ext), NULL,
1119 NULL, AF_INET6))
1120 goto shortpkt;
1121 optend = off + (ext.ip6e_len + 1) * 8;
1122 ooff = off + sizeof(ext);
1123 do {
1124 if (!pf_pull_hdr(m, ooff, &opt.ip6o_type,
1125 sizeof(opt.ip6o_type), NULL, NULL,
1126 AF_INET6))
1127 goto shortpkt;
1128 if (opt.ip6o_type == IP6OPT_PAD1) {
1129 ooff++;
1130 continue;
1131 }
1132 if (!pf_pull_hdr(m, ooff, &opt, sizeof(opt),
1133 NULL, NULL, AF_INET6))
1134 goto shortpkt;
1135 if (ooff + sizeof(opt) + opt.ip6o_len > optend)
1136 goto drop;
1137 switch (opt.ip6o_type) {
1138 case IP6OPT_JUMBO:
1139 if (h->ip6_plen != 0)
1140 goto drop;
1141 if (!pf_pull_hdr(m, ooff, &jumbo,
1142 sizeof(jumbo), NULL, NULL,
1143 AF_INET6))
1144 goto shortpkt;
1145 memcpy(&jumbolen, jumbo.ip6oj_jumbo_len,
1146 sizeof(jumbolen));
1147 jumbolen = ntohl(jumbolen);
1148 if (jumbolen <= IPV6_MAXPACKET)
1149 goto drop;
1150 if (sizeof(struct ip6_hdr) + jumbolen !=
1151 m->m_pkthdr.len)
1152 goto drop;
1153 break;
1154 default:
1155 break;
1156 }
1157 ooff += sizeof(opt) + opt.ip6o_len;
1158 } while (ooff < optend);
1159
1160 off = optend;
1161 proto = ext.ip6e_nxt;
1162 break;
1163 default:
1164 terminal = 1;
1165 break;
1166 }
1167 } while (!terminal);
1168
1169
1170 if (ntohs(h->ip6_plen) == 0)
1171 plen = jumbolen;
1172 else
1173 plen = ntohs(h->ip6_plen);
1174 if (plen == 0)
1175 goto drop;
1176 if (sizeof(struct ip6_hdr) + plen > m->m_pkthdr.len)
1177 goto shortpkt;
1178
1179
1180 if (r->min_ttl && h->ip6_hlim < r->min_ttl)
1181 h->ip6_hlim = r->min_ttl;
1182
1183 return (PF_PASS);
1184
1185 fragment:
1186 if (ntohs(h->ip6_plen) == 0 || jumbolen)
1187 goto drop;
1188 plen = ntohs(h->ip6_plen);
1189
1190 if (!pf_pull_hdr(m, off, &frag, sizeof(frag), NULL, NULL, AF_INET6))
1191 goto shortpkt;
1192 fragoff = ntohs(frag.ip6f_offlg & IP6F_OFF_MASK);
1193 if (fragoff + (plen - off - sizeof(frag)) > IPV6_MAXPACKET)
1194 goto badfrag;
1195
1196
1197
1198 return (PF_PASS);
1199
1200 shortpkt:
1201 REASON_SET(reason, PFRES_SHORT);
1202 if (r != NULL && r->log)
1203 PFLOG_PACKET(kif, h, m, AF_INET6, dir, *reason, r, NULL, NULL, pd);
1204 return (PF_DROP);
1205
1206 drop:
1207 REASON_SET(reason, PFRES_NORM);
1208 if (r != NULL && r->log)
1209 PFLOG_PACKET(kif, h, m, AF_INET6, dir, *reason, r, NULL, NULL, pd);
1210 return (PF_DROP);
1211
1212 badfrag:
1213 REASON_SET(reason, PFRES_FRAG);
1214 if (r != NULL && r->log)
1215 PFLOG_PACKET(kif, h, m, AF_INET6, dir, *reason, r, NULL, NULL, pd);
1216 return (PF_DROP);
1217 }
1218 #endif
1219
1220 int
1221 pf_normalize_tcp(int dir, struct pfi_kif *kif, struct mbuf *m, int ipoff,
1222 int off, void *h, struct pf_pdesc *pd)
1223 {
1224 struct pf_rule *r, *rm = NULL;
1225 struct tcphdr *th = pd->hdr.tcp;
1226 int rewrite = 0;
1227 u_short reason;
1228 u_int8_t flags;
1229 sa_family_t af = pd->af;
1230
1231 r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_SCRUB].active.ptr);
1232 while (r != NULL) {
1233 r->evaluations++;
1234 if (pfi_kif_match(r->kif, kif) == r->ifnot)
1235 r = r->skip[PF_SKIP_IFP].ptr;
1236 else if (r->direction && r->direction != dir)
1237 r = r->skip[PF_SKIP_DIR].ptr;
1238 else if (r->af && r->af != af)
1239 r = r->skip[PF_SKIP_AF].ptr;
1240 else if (r->proto && r->proto != pd->proto)
1241 r = r->skip[PF_SKIP_PROTO].ptr;
1242 else if (PF_MISMATCHAW(&r->src.addr, pd->src, af,
1243 r->src.neg, kif))
1244 r = r->skip[PF_SKIP_SRC_ADDR].ptr;
1245 else if (r->src.port_op && !pf_match_port(r->src.port_op,
1246 r->src.port[0], r->src.port[1], th->th_sport))
1247 r = r->skip[PF_SKIP_SRC_PORT].ptr;
1248 else if (PF_MISMATCHAW(&r->dst.addr, pd->dst, af,
1249 r->dst.neg, NULL))
1250 r = r->skip[PF_SKIP_DST_ADDR].ptr;
1251 else if (r->dst.port_op && !pf_match_port(r->dst.port_op,
1252 r->dst.port[0], r->dst.port[1], th->th_dport))
1253 r = r->skip[PF_SKIP_DST_PORT].ptr;
1254 else if (r->os_fingerprint != PF_OSFP_ANY && !pf_osfp_match(
1255 pf_osfp_fingerprint(pd, m, off, th),
1256 r->os_fingerprint))
1257 r = TAILQ_NEXT(r, entries);
1258 else {
1259 rm = r;
1260 break;
1261 }
1262 }
1263
1264 if (rm == NULL || rm->action == PF_NOSCRUB)
1265 return (PF_PASS);
1266 else {
1267 r->packets[dir == PF_OUT]++;
1268 r->bytes[dir == PF_OUT] += pd->tot_len;
1269 }
1270
1271 if (rm->rule_flag & PFRULE_REASSEMBLE_TCP)
1272 pd->flags |= PFDESC_TCP_NORM;
1273
1274 flags = th->th_flags;
1275 if (flags & TH_SYN) {
1276
1277 if (flags & TH_RST)
1278 goto tcp_drop;
1279
1280 if (flags & TH_FIN)
1281 flags &= ~TH_FIN;
1282 } else {
1283
1284 if (!(flags & (TH_ACK|TH_RST)))
1285 goto tcp_drop;
1286 }
1287
1288 if (!(flags & TH_ACK)) {
1289
1290 if ((flags & TH_FIN) || (flags & TH_PUSH) || (flags & TH_URG))
1291 goto tcp_drop;
1292 }
1293
1294
1295 if (th->th_off < (sizeof(struct tcphdr) >> 2))
1296 goto tcp_drop;
1297
1298
1299 if (flags != th->th_flags || th->th_x2 != 0) {
1300 u_int16_t ov, nv;
1301
1302 ov = *(u_int16_t *)(&th->th_ack + 1);
1303 th->th_flags = flags;
1304 th->th_x2 = 0;
1305 nv = *(u_int16_t *)(&th->th_ack + 1);
1306
1307 th->th_sum = pf_cksum_fixup(th->th_sum, ov, nv, 0);
1308 rewrite = 1;
1309 }
1310
1311
1312 if (!(flags & TH_URG) && th->th_urp) {
1313 th->th_sum = pf_cksum_fixup(th->th_sum, th->th_urp, 0, 0);
1314 th->th_urp = 0;
1315 rewrite = 1;
1316 }
1317
1318
1319 if (r->max_mss && pf_normalize_tcpopt(r, m, th, off))
1320 rewrite = 1;
1321
1322
1323 if (rewrite)
1324 m_copyback(m, off, sizeof(*th), th);
1325
1326 return (PF_PASS);
1327
1328 tcp_drop:
1329 REASON_SET(&reason, PFRES_NORM);
1330 if (rm != NULL && r->log)
1331 PFLOG_PACKET(kif, h, m, AF_INET, dir, reason, r, NULL, NULL, pd);
1332 return (PF_DROP);
1333 }
1334
1335 int
1336 pf_normalize_tcp_init(struct mbuf *m, int off, struct pf_pdesc *pd,
1337 struct tcphdr *th, struct pf_state_peer *src, struct pf_state_peer *dst)
1338 {
1339 u_int32_t tsval, tsecr;
1340 u_int8_t hdr[60];
1341 u_int8_t *opt;
1342
1343 KASSERT(src->scrub == NULL);
1344
1345 src->scrub = pool_get(&pf_state_scrub_pl, PR_NOWAIT);
1346 if (src->scrub == NULL)
1347 return (1);
1348 bzero(src->scrub, sizeof(*src->scrub));
1349
1350 switch (pd->af) {
1351 #ifdef INET
1352 case AF_INET: {
1353 struct ip *h = mtod(m, struct ip *);
1354 src->scrub->pfss_ttl = h->ip_ttl;
1355 break;
1356 }
1357 #endif
1358 #ifdef INET6
1359 case AF_INET6: {
1360 struct ip6_hdr *h = mtod(m, struct ip6_hdr *);
1361 src->scrub->pfss_ttl = h->ip6_hlim;
1362 break;
1363 }
1364 #endif
1365 }
1366
1367
1368
1369
1370
1371
1372 if ((th->th_flags & TH_SYN) == 0)
1373 return (0);
1374
1375
1376 if (th->th_off > (sizeof(struct tcphdr) >> 2) && src->scrub &&
1377 pf_pull_hdr(m, off, hdr, th->th_off << 2, NULL, NULL, pd->af)) {
1378
1379 int hlen;
1380 opt = hdr + sizeof(struct tcphdr);
1381 hlen = (th->th_off << 2) - sizeof(struct tcphdr);
1382 while (hlen >= TCPOLEN_TIMESTAMP) {
1383 switch (*opt) {
1384 case TCPOPT_EOL:
1385 case TCPOPT_NOP:
1386 opt++;
1387 hlen--;
1388 break;
1389 case TCPOPT_TIMESTAMP:
1390 if (opt[1] >= TCPOLEN_TIMESTAMP) {
1391 src->scrub->pfss_flags |=
1392 PFSS_TIMESTAMP;
1393 src->scrub->pfss_ts_mod =
1394 htonl(arc4random());
1395
1396
1397 memcpy(&tsval, &opt[2],
1398 sizeof(u_int32_t));
1399 memcpy(&tsecr, &opt[6],
1400 sizeof(u_int32_t));
1401 src->scrub->pfss_tsval0 = ntohl(tsval);
1402 src->scrub->pfss_tsval = ntohl(tsval);
1403 src->scrub->pfss_tsecr = ntohl(tsecr);
1404 getmicrouptime(&src->scrub->pfss_last);
1405 }
1406
1407 default:
1408 hlen -= MAX(opt[1], 2);
1409 opt += MAX(opt[1], 2);
1410 break;
1411 }
1412 }
1413 }
1414
1415 return (0);
1416 }
1417
1418 void
1419 pf_normalize_tcp_cleanup(struct pf_state *state)
1420 {
1421 if (state->src.scrub)
1422 pool_put(&pf_state_scrub_pl, state->src.scrub);
1423 if (state->dst.scrub)
1424 pool_put(&pf_state_scrub_pl, state->dst.scrub);
1425
1426
1427 }
1428
1429 int
1430 pf_normalize_tcp_stateful(struct mbuf *m, int off, struct pf_pdesc *pd,
1431 u_short *reason, struct tcphdr *th, struct pf_state *state,
1432 struct pf_state_peer *src, struct pf_state_peer *dst, int *writeback)
1433 {
1434 struct timeval uptime;
1435 u_int32_t tsval, tsecr;
1436 u_int tsval_from_last;
1437 u_int8_t hdr[60];
1438 u_int8_t *opt;
1439 int copyback = 0;
1440 int got_ts = 0;
1441
1442 KASSERT(src->scrub || dst->scrub);
1443
1444
1445
1446
1447
1448
1449 switch (pd->af) {
1450 #ifdef INET
1451 case AF_INET: {
1452 if (src->scrub) {
1453 struct ip *h = mtod(m, struct ip *);
1454 if (h->ip_ttl > src->scrub->pfss_ttl)
1455 src->scrub->pfss_ttl = h->ip_ttl;
1456 h->ip_ttl = src->scrub->pfss_ttl;
1457 }
1458 break;
1459 }
1460 #endif
1461 #ifdef INET6
1462 case AF_INET6: {
1463 if (src->scrub) {
1464 struct ip6_hdr *h = mtod(m, struct ip6_hdr *);
1465 if (h->ip6_hlim > src->scrub->pfss_ttl)
1466 src->scrub->pfss_ttl = h->ip6_hlim;
1467 h->ip6_hlim = src->scrub->pfss_ttl;
1468 }
1469 break;
1470 }
1471 #endif
1472 }
1473
1474 if (th->th_off > (sizeof(struct tcphdr) >> 2) &&
1475 ((src->scrub && (src->scrub->pfss_flags & PFSS_TIMESTAMP)) ||
1476 (dst->scrub && (dst->scrub->pfss_flags & PFSS_TIMESTAMP))) &&
1477 pf_pull_hdr(m, off, hdr, th->th_off << 2, NULL, NULL, pd->af)) {
1478
1479 int hlen;
1480 opt = hdr + sizeof(struct tcphdr);
1481 hlen = (th->th_off << 2) - sizeof(struct tcphdr);
1482 while (hlen >= TCPOLEN_TIMESTAMP) {
1483 switch (*opt) {
1484 case TCPOPT_EOL:
1485 case TCPOPT_NOP:
1486 opt++;
1487 hlen--;
1488 break;
1489 case TCPOPT_TIMESTAMP:
1490
1491
1492
1493
1494
1495 if (got_ts) {
1496
1497 if (pf_status.debug >= PF_DEBUG_MISC) {
1498 DPFPRINTF(("multiple TS??"));
1499 pf_print_state(state);
1500 printf("\n");
1501 }
1502 REASON_SET(reason, PFRES_TS);
1503 return (PF_DROP);
1504 }
1505 if (opt[1] >= TCPOLEN_TIMESTAMP) {
1506 memcpy(&tsval, &opt[2],
1507 sizeof(u_int32_t));
1508 if (tsval && src->scrub &&
1509 (src->scrub->pfss_flags &
1510 PFSS_TIMESTAMP)) {
1511 tsval = ntohl(tsval);
1512 pf_change_a(&opt[2],
1513 &th->th_sum,
1514 htonl(tsval +
1515 src->scrub->pfss_ts_mod),
1516 0);
1517 copyback = 1;
1518 }
1519
1520
1521 memcpy(&tsecr, &opt[6],
1522 sizeof(u_int32_t));
1523 if (tsecr && dst->scrub &&
1524 (dst->scrub->pfss_flags &
1525 PFSS_TIMESTAMP)) {
1526 tsecr = ntohl(tsecr)
1527 - dst->scrub->pfss_ts_mod;
1528 pf_change_a(&opt[6],
1529 &th->th_sum, htonl(tsecr),
1530 0);
1531 copyback = 1;
1532 }
1533 got_ts = 1;
1534 }
1535
1536 default:
1537 hlen -= MAX(opt[1], 2);
1538 opt += MAX(opt[1], 2);
1539 break;
1540 }
1541 }
1542 if (copyback) {
1543
1544 *writeback = 1;
1545 m_copyback(m, off + sizeof(struct tcphdr),
1546 (th->th_off << 2) - sizeof(struct tcphdr), hdr +
1547 sizeof(struct tcphdr));
1548 }
1549 }
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559 #define TS_MAX_IDLE (24*24*60*60)
1560 #define TS_MAX_CONN (12*24*60*60)
1561
1562 getmicrouptime(&uptime);
1563 if (src->scrub && (src->scrub->pfss_flags & PFSS_PAWS) &&
1564 (uptime.tv_sec - src->scrub->pfss_last.tv_sec > TS_MAX_IDLE ||
1565 time_second - state->creation > TS_MAX_CONN)) {
1566 if (pf_status.debug >= PF_DEBUG_MISC) {
1567 DPFPRINTF(("src idled out of PAWS\n"));
1568 pf_print_state(state);
1569 printf("\n");
1570 }
1571 src->scrub->pfss_flags = (src->scrub->pfss_flags & ~PFSS_PAWS)
1572 | PFSS_PAWS_IDLED;
1573 }
1574 if (dst->scrub && (dst->scrub->pfss_flags & PFSS_PAWS) &&
1575 uptime.tv_sec - dst->scrub->pfss_last.tv_sec > TS_MAX_IDLE) {
1576 if (pf_status.debug >= PF_DEBUG_MISC) {
1577 DPFPRINTF(("dst idled out of PAWS\n"));
1578 pf_print_state(state);
1579 printf("\n");
1580 }
1581 dst->scrub->pfss_flags = (dst->scrub->pfss_flags & ~PFSS_PAWS)
1582 | PFSS_PAWS_IDLED;
1583 }
1584
1585 if (got_ts && src->scrub && dst->scrub &&
1586 (src->scrub->pfss_flags & PFSS_PAWS) &&
1587 (dst->scrub->pfss_flags & PFSS_PAWS)) {
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649 struct timeval delta_ts;
1650 int ts_fudge;
1651
1652
1653
1654
1655
1656
1657
1658
1659 if ((ts_fudge = state->rule.ptr->timeout[PFTM_TS_DIFF]) == 0)
1660 ts_fudge = pf_default_rule.timeout[PFTM_TS_DIFF];
1661
1662
1663
1664 #define TS_MAXFREQ 1100
1665 #define TS_MICROSECS 1000000
1666 timersub(&uptime, &src->scrub->pfss_last, &delta_ts);
1667 tsval_from_last = (delta_ts.tv_sec + ts_fudge) * TS_MAXFREQ;
1668 tsval_from_last += delta_ts.tv_usec / (TS_MICROSECS/TS_MAXFREQ);
1669
1670
1671 if ((src->state >= TCPS_ESTABLISHED &&
1672 dst->state >= TCPS_ESTABLISHED) &&
1673 (SEQ_LT(tsval, dst->scrub->pfss_tsecr) ||
1674 SEQ_GT(tsval, src->scrub->pfss_tsval + tsval_from_last) ||
1675 (tsecr && (SEQ_GT(tsecr, dst->scrub->pfss_tsval) ||
1676 SEQ_LT(tsecr, dst->scrub->pfss_tsval0))))) {
1677
1678
1679
1680
1681
1682
1683
1684 DPFPRINTF(("Timestamp failed %c%c%c%c\n",
1685 SEQ_LT(tsval, dst->scrub->pfss_tsecr) ? '0' : ' ',
1686 SEQ_GT(tsval, src->scrub->pfss_tsval +
1687 tsval_from_last) ? '1' : ' ',
1688 SEQ_GT(tsecr, dst->scrub->pfss_tsval) ? '2' : ' ',
1689 SEQ_LT(tsecr, dst->scrub->pfss_tsval0)? '3' : ' '));
1690 DPFPRINTF((" tsval: %lu tsecr: %lu +ticks: %lu "
1691 "idle: %lus %lums\n",
1692 tsval, tsecr, tsval_from_last, delta_ts.tv_sec,
1693 delta_ts.tv_usec / 1000));
1694 DPFPRINTF((" src->tsval: %lu tsecr: %lu\n",
1695 src->scrub->pfss_tsval, src->scrub->pfss_tsecr));
1696 DPFPRINTF((" dst->tsval: %lu tsecr: %lu tsval0: %lu"
1697 "\n", dst->scrub->pfss_tsval,
1698 dst->scrub->pfss_tsecr, dst->scrub->pfss_tsval0));
1699 if (pf_status.debug >= PF_DEBUG_MISC) {
1700 pf_print_state(state);
1701 pf_print_flags(th->th_flags);
1702 printf("\n");
1703 }
1704 REASON_SET(reason, PFRES_TS);
1705 return (PF_DROP);
1706 }
1707
1708
1709
1710 } else if (!got_ts && (th->th_flags & TH_RST) == 0 &&
1711 ((src->state == TCPS_ESTABLISHED && dst->state == TCPS_ESTABLISHED)
1712 || pd->p_len > 0 || (th->th_flags & TH_SYN)) &&
1713 src->scrub && dst->scrub &&
1714 (src->scrub->pfss_flags & PFSS_PAWS) &&
1715 (dst->scrub->pfss_flags & PFSS_PAWS)) {
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742 if (pd->p_len > 0 && (src->scrub->pfss_flags & PFSS_DATA_TS)) {
1743
1744
1745
1746
1747 if (pf_status.debug >= PF_DEBUG_MISC) {
1748 DPFPRINTF(("Did not receive expected RFC1323 "
1749 "timestamp\n"));
1750 pf_print_state(state);
1751 pf_print_flags(th->th_flags);
1752 printf("\n");
1753 }
1754 REASON_SET(reason, PFRES_TS);
1755 return (PF_DROP);
1756 }
1757 }
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768 if (pd->p_len > 0 && src->scrub && (src->scrub->pfss_flags &
1769 (PFSS_TIMESTAMP|PFSS_DATA_TS|PFSS_DATA_NOTS)) == PFSS_TIMESTAMP) {
1770 if (got_ts)
1771 src->scrub->pfss_flags |= PFSS_DATA_TS;
1772 else {
1773 src->scrub->pfss_flags |= PFSS_DATA_NOTS;
1774 if (pf_status.debug >= PF_DEBUG_MISC && dst->scrub &&
1775 (dst->scrub->pfss_flags & PFSS_TIMESTAMP)) {
1776
1777 DPFPRINTF(("Broken RFC1323 stack did not "
1778 "timestamp data packet. Disabled PAWS "
1779 "security.\n"));
1780 pf_print_state(state);
1781 pf_print_flags(th->th_flags);
1782 printf("\n");
1783 }
1784 }
1785 }
1786
1787
1788
1789
1790
1791 if (got_ts && src->scrub && PFSS_TIMESTAMP == (src->scrub->pfss_flags &
1792 (PFSS_PAWS_IDLED|PFSS_TIMESTAMP))) {
1793 getmicrouptime(&src->scrub->pfss_last);
1794 if (SEQ_GEQ(tsval, src->scrub->pfss_tsval) ||
1795 (src->scrub->pfss_flags & PFSS_PAWS) == 0)
1796 src->scrub->pfss_tsval = tsval;
1797
1798 if (tsecr) {
1799 if (SEQ_GEQ(tsecr, src->scrub->pfss_tsecr) ||
1800 (src->scrub->pfss_flags & PFSS_PAWS) == 0)
1801 src->scrub->pfss_tsecr = tsecr;
1802
1803 if ((src->scrub->pfss_flags & PFSS_PAWS) == 0 &&
1804 (SEQ_LT(tsval, src->scrub->pfss_tsval0) ||
1805 src->scrub->pfss_tsval0 == 0)) {
1806
1807 src->scrub->pfss_tsval0 = tsval;
1808 }
1809
1810
1811 if ((src->scrub->pfss_flags & PFSS_PAWS) == 0)
1812 src->scrub->pfss_flags |= PFSS_PAWS;
1813 }
1814 }
1815
1816
1817 return (0);
1818 }
1819
1820 int
1821 pf_normalize_tcpopt(struct pf_rule *r, struct mbuf *m, struct tcphdr *th,
1822 int off)
1823 {
1824 u_int16_t *mss;
1825 int thoff;
1826 int opt, cnt, optlen = 0;
1827 int rewrite = 0;
1828 u_char *optp;
1829
1830 thoff = th->th_off << 2;
1831 cnt = thoff - sizeof(struct tcphdr);
1832 optp = mtod(m, caddr_t) + off + sizeof(struct tcphdr);
1833
1834 for (; cnt > 0; cnt -= optlen, optp += optlen) {
1835 opt = optp[0];
1836 if (opt == TCPOPT_EOL)
1837 break;
1838 if (opt == TCPOPT_NOP)
1839 optlen = 1;
1840 else {
1841 if (cnt < 2)
1842 break;
1843 optlen = optp[1];
1844 if (optlen < 2 || optlen > cnt)
1845 break;
1846 }
1847 switch (opt) {
1848 case TCPOPT_MAXSEG:
1849 mss = (u_int16_t *)(optp + 2);
1850 if ((ntohs(*mss)) > r->max_mss) {
1851 th->th_sum = pf_cksum_fixup(th->th_sum,
1852 *mss, htons(r->max_mss), 0);
1853 *mss = htons(r->max_mss);
1854 rewrite = 1;
1855 }
1856 break;
1857 default:
1858 break;
1859 }
1860 }
1861
1862 return (rewrite);
1863 }