[BACK]Return to pf_norm.c CVS log [TXT][DIR] Up to [local] / sys / net

Annotation of sys/net/pf_norm.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: pf_norm.c,v 1.109 2007/05/28 17:16:39 henning Exp $ */
                      2:
                      3: /*
                      4:  * Copyright 2001 Niels Provos <provos@citi.umich.edu>
                      5:  * All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  *
                     16:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     17:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     18:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     19:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     20:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     21:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     22:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     23:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     24:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     25:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     26:  */
                     27:
                     28: #include "pflog.h"
                     29:
                     30: #include <sys/param.h>
                     31: #include <sys/systm.h>
                     32: #include <sys/mbuf.h>
                     33: #include <sys/filio.h>
                     34: #include <sys/fcntl.h>
                     35: #include <sys/socket.h>
                     36: #include <sys/kernel.h>
                     37: #include <sys/time.h>
                     38: #include <sys/pool.h>
                     39:
                     40: #include <dev/rndvar.h>
                     41: #include <net/if.h>
                     42: #include <net/if_types.h>
                     43: #include <net/bpf.h>
                     44: #include <net/route.h>
                     45: #include <net/if_pflog.h>
                     46:
                     47: #include <netinet/in.h>
                     48: #include <netinet/in_var.h>
                     49: #include <netinet/in_systm.h>
                     50: #include <netinet/ip.h>
                     51: #include <netinet/ip_var.h>
                     52: #include <netinet/tcp.h>
                     53: #include <netinet/tcp_seq.h>
                     54: #include <netinet/udp.h>
                     55: #include <netinet/ip_icmp.h>
                     56:
                     57: #ifdef INET6
                     58: #include <netinet/ip6.h>
                     59: #endif /* INET6 */
                     60:
                     61: #include <net/pfvar.h>
                     62:
                     63: struct pf_frent {
                     64:        LIST_ENTRY(pf_frent) fr_next;
                     65:        struct ip *fr_ip;
                     66:        struct mbuf *fr_m;
                     67: };
                     68:
                     69: struct pf_frcache {
                     70:        LIST_ENTRY(pf_frcache) fr_next;
                     71:        uint16_t        fr_off;
                     72:        uint16_t        fr_end;
                     73: };
                     74:
                     75: #define PFFRAG_SEENLAST        0x0001          /* Seen the last fragment for this */
                     76: #define PFFRAG_NOBUFFER        0x0002          /* Non-buffering fragment cache */
                     77: #define PFFRAG_DROP    0x0004          /* Drop all fragments */
                     78: #define BUFFER_FRAGMENTS(fr)   (!((fr)->fr_flags & PFFRAG_NOBUFFER))
                     79:
                     80: struct pf_fragment {
                     81:        RB_ENTRY(pf_fragment) fr_entry;
                     82:        TAILQ_ENTRY(pf_fragment) frag_next;
                     83:        struct in_addr  fr_src;
                     84:        struct in_addr  fr_dst;
                     85:        u_int8_t        fr_p;           /* protocol of this fragment */
                     86:        u_int8_t        fr_flags;       /* status flags */
                     87:        u_int16_t       fr_id;          /* fragment id for reassemble */
                     88:        u_int16_t       fr_max;         /* fragment data max */
                     89:        u_int32_t       fr_timeout;
                     90: #define fr_queue       fr_u.fru_queue
                     91: #define fr_cache       fr_u.fru_cache
                     92:        union {
                     93:                LIST_HEAD(pf_fragq, pf_frent) fru_queue;        /* buffering */
                     94:                LIST_HEAD(pf_cacheq, pf_frcache) fru_cache;     /* non-buf */
                     95:        } fr_u;
                     96: };
                     97:
                     98: TAILQ_HEAD(pf_fragqueue, pf_fragment)  pf_fragqueue;
                     99: TAILQ_HEAD(pf_cachequeue, pf_fragment) pf_cachequeue;
                    100:
                    101: static __inline int     pf_frag_compare(struct pf_fragment *,
                    102:                            struct pf_fragment *);
                    103: RB_HEAD(pf_frag_tree, pf_fragment)     pf_frag_tree, pf_cache_tree;
                    104: RB_PROTOTYPE(pf_frag_tree, pf_fragment, fr_entry, pf_frag_compare);
                    105: RB_GENERATE(pf_frag_tree, pf_fragment, fr_entry, pf_frag_compare);
                    106:
                    107: /* Private prototypes */
                    108: void                    pf_ip2key(struct pf_fragment *, struct ip *);
                    109: void                    pf_remove_fragment(struct pf_fragment *);
                    110: void                    pf_flush_fragments(void);
                    111: void                    pf_free_fragment(struct pf_fragment *);
                    112: struct pf_fragment     *pf_find_fragment(struct ip *, struct pf_frag_tree *);
                    113: struct mbuf            *pf_reassemble(struct mbuf **, struct pf_fragment **,
                    114:                            struct pf_frent *, int);
                    115: struct mbuf            *pf_fragcache(struct mbuf **, struct ip*,
                    116:                            struct pf_fragment **, int, int, int *);
                    117: 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: /* Globals */
                    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:  * Try to flush old fragments to make space for new ones
                    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: /* Frees the fragments and all associated entries */
                    236:
                    237: void
                    238: pf_free_fragment(struct pf_fragment *frag)
                    239: {
                    240:        struct pf_frent         *frent;
                    241:        struct pf_frcache       *frcache;
                    242:
                    243:        /* Free all fragments */
                    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:                /* XXX Are we sure we want to update the timeout? */
                    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: /* Removes a fragment from the fragment queue and frees the fragment */
                    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:        /* Strip off ip header */
                    336:        m->m_data += hlen;
                    337:        m->m_len -= hlen;
                    338:
                    339:        /* Create a new reassembly queue for this packet */
                    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:                /* We do not have a previous fragment */
                    362:                frep = NULL;
                    363:                goto insert;
                    364:        }
                    365:
                    366:        /*
                    367:         * Find a fragment after the current one:
                    368:         *  - off contains the real shifted offset.
                    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:                /* Enforce 8 byte boundaries */
                    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:                /* This fragment is completely overlapped, lose it */
                    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:        /* Update maximum data size */
                    425:        if ((*frag)->fr_max < max)
                    426:                (*frag)->fr_max = max;
                    427:        /* This is the last segment */
                    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:        /* Check if we are completely reassembled */
                    437:        if (!((*frag)->fr_flags & PFFRAG_SEENLAST))
                    438:                return (NULL);
                    439:
                    440:        /* Check if we have all the data */
                    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:        /* We have all the data */
                    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:        /* Magic from ip_input */
                    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:        /* Remove from fragment queue */
                    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:        /* some debugging cruft by sklower, below, will go away soon */
                    500:        /* XXX this should be done elsewhere */
                    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:        /* Oops - fail safe - drop packet */
                    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:        /* Create a new range queue for this packet */
                    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:                /* Get an entry for the queue */
                    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:         * Find a fragment after the current one:
                    574:         *  - off contains the real shifted offset.
                    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:                        /* Fragment is entirely a duplicate */
                    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:                        /* They are adjacent.  Fixup cache entry */
                    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:                        /* The first part of this payload overlaps with a
                    602:                         * fragment that has already been passed.
                    603:                         * Need to trim off the first part of the payload.
                    604:                         * But to do so easily, we need to create another
                    605:                         * mbuf to throw the original header into.
                    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:                        /* Update the previous frag to encompass this one */
                    615:                        frp->fr_end = max;
                    616:
                    617:                        if (!drop) {
                    618:                                /* XXX Optimization opportunity
                    619:                                 * This is a very heavy way to trim the payload.
                    620:                                 * we could do it much faster by diddling mbuf
                    621:                                 * internals but that would be even less legible
                    622:                                 * than this mbuf magic.  For my next trick,
                    623:                                 * I'll pull a rabbit out of my laptop.
                    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:                        /* There is a gap between fragments */
                    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:                        /* Adjacent fragments */
                    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:                        /* Need to chop off the tail of this fragment */
                    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:                        /* There is a gap between fragments */
                    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:                /* Need to glue together two separate fragment descriptors */
                    725:                if (merge) {
                    726:                        if (cur && fra->fr_off <= cur->fr_end) {
                    727:                                /* Need to merge in a previous 'cur' */
                    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:                                /* Need to merge in a modified 'frp' */
                    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:                 * We must keep tracking the overall fragment even when
                    758:                 * we're going to drop it anyway so that we know when to
                    759:                 * free the overall descriptor.  Thus we drop the frag late.
                    760:                 */
                    761:                goto drop_fragment;
                    762:        }
                    763:
                    764:
                    765:  pass:
                    766:        /* Update maximum data size */
                    767:        if ((*frag)->fr_max < max)
                    768:                (*frag)->fr_max = max;
                    769:
                    770:        /* This is the last segment */
                    771:        if (!mff)
                    772:                (*frag)->fr_flags |= PFFRAG_SEENLAST;
                    773:
                    774:        /* Check if we are completely reassembled */
                    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:                /* Remove from fragment queue */
                    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:        /* Still need to pay attention to !IP_MF */
                    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:        /* Still need to pay attention to !IP_MF */
                    800:        if (!mff && *frag != NULL)
                    801:                (*frag)->fr_flags |= PFFRAG_SEENLAST;
                    802:
                    803:        if (drop) {
                    804:                /* This fragment has been deemed bad.  Don't reass */
                    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:        /* Check for illegal packets */
                    862:        if (hlen < (int)sizeof(struct ip))
                    863:                goto drop;
                    864:
                    865:        if (hlen > ntohs(h->ip_len))
                    866:                goto drop;
                    867:
                    868:        /* Clear IP_DF if the rule uses the no-df option */
                    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:        /* We will need other tests here */
                    877:        if (!fragoff && !mff)
                    878:                goto no_fragment;
                    879:
                    880:        /* We're dealing with a fragment now. Don't allow fragments
                    881:         * with IP_DF to enter the cache. If the flag was cleared by
                    882:         * no-df above, fine. Otherwise drop it.
                    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:        /* All fragments are 8 byte aligned */
                    893:        if (mff && (ip_len & 0x7)) {
                    894:                DPFPRINTF(("mff and %d\n", ip_len));
                    895:                goto bad;
                    896:        }
                    897:
                    898:        /* Respect maximum length */
                    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:                /* Fully buffer all of the fragments */
                    907:
                    908:                frag = pf_find_fragment(h, &pf_frag_tree);
                    909:
                    910:                /* Check if we saw the last fragment already */
                    911:                if (frag != NULL && (frag->fr_flags & PFFRAG_SEENLAST) &&
                    912:                    max > frag->fr_max)
                    913:                        goto bad;
                    914:
                    915:                /* Get an entry for the fragment queue */
                    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:                /* Might return a completely reassembled mbuf, or NULL */
                    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:                /* non-buffering fragment cache (drops or masks overlaps) */
                    938:                int     nomem = 0;
                    939:
                    940:                if (dir == PF_OUT && m->m_pkthdr.pf.flags & PF_TAG_FRAGCACHE) {
                    941:                        /*
                    942:                         * Already passed the fragment cache in the
                    943:                         * input direction.  If we continued, it would
                    944:                         * appear to be a dup and would be dropped.
                    945:                         */
                    946:                        goto fragment_pass;
                    947:                }
                    948:
                    949:                frag = pf_find_fragment(h, &pf_cache_tree);
                    950:
                    951:                /* Check if we saw the last fragment already */
                    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:        /* At this point, only IP_DF is allowed in ip_off */
                    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:        /* Enforce a minimum ttl, may cause endless packet loops */
                    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:        /* Enforce a minimum ttl, may cause endless packet loops */
                   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:        /* Free associated fragments */
                   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 /* header chain! */
                   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:        /* Check for illegal packets */
                   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:        /* jumbo payload option must be present, or plen > 0 */
                   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:        /* Enforce a minimum ttl, may cause endless packet loops */
                   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:        /* do something about it */
                   1197:        /* remember to set pd->flags |= PFDESC_IP_REAS */
                   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 /* INET6 */
                   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:                /* Illegal packet */
                   1277:                if (flags & TH_RST)
                   1278:                        goto tcp_drop;
                   1279:
                   1280:                if (flags & TH_FIN)
                   1281:                        flags &= ~TH_FIN;
                   1282:        } else {
                   1283:                /* Illegal packet */
                   1284:                if (!(flags & (TH_ACK|TH_RST)))
                   1285:                        goto tcp_drop;
                   1286:        }
                   1287:
                   1288:        if (!(flags & TH_ACK)) {
                   1289:                /* These flags are only valid if ACK is set */
                   1290:                if ((flags & TH_FIN) || (flags & TH_PUSH) || (flags & TH_URG))
                   1291:                        goto tcp_drop;
                   1292:        }
                   1293:
                   1294:        /* Check for illegal header length */
                   1295:        if (th->th_off < (sizeof(struct tcphdr) >> 2))
                   1296:                goto tcp_drop;
                   1297:
                   1298:        /* If flags changed, or reserved data set, then adjust */
                   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:        /* Remove urgent pointer, if TH_URG is not set */
                   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:        /* Process options */
                   1319:        if (r->max_mss && pf_normalize_tcpopt(r, m, th, off))
                   1320:                rewrite = 1;
                   1321:
                   1322:        /* copy back packet headers if we sanitized */
                   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 /* INET */
                   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 /* INET6 */
                   1365:        }
                   1366:
                   1367:
                   1368:        /*
                   1369:         * All normalizations below are only begun if we see the start of
                   1370:         * the connections.  They must all set an enabled bit in pfss_flags
                   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:                /* Diddle with TCP options */
                   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:        /* FALLTHROUGH */
                   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:                                        /* note PFSS_PAWS not set yet */
                   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:                                /* FALLTHROUGH */
                   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:        /* Someday... flush the TCP segment reassembly descriptors. */
                   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:         * Enforce the minimum TTL seen for this connection.  Negate a common
                   1446:         * technique to evade an intrusion detection system and confuse
                   1447:         * firewall state code.
                   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 /* INET */
                   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 /* INET6 */
                   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:                /* Diddle with TCP options */
                   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:        /* FALLTHROUGH */
                   1485:                        case TCPOPT_NOP:
                   1486:                                opt++;
                   1487:                                hlen--;
                   1488:                                break;
                   1489:                        case TCPOPT_TIMESTAMP:
                   1490:                                /* Modulate the timestamps.  Can be used for
                   1491:                                 * NAT detection, OS uptime determination or
                   1492:                                 * reboot detection.
                   1493:                                 */
                   1494:
                   1495:                                if (got_ts) {
                   1496:                                        /* Huh?  Multiple timestamps!? */
                   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:                                        /* Modulate TS reply iff valid (!0) */
                   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:                                /* FALLTHROUGH */
                   1536:                        default:
                   1537:                                hlen -= MAX(opt[1], 2);
                   1538:                                opt += MAX(opt[1], 2);
                   1539:                                break;
                   1540:                        }
                   1541:                }
                   1542:                if (copyback) {
                   1543:                        /* Copyback the options, caller copys back header */
                   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:         * Must invalidate PAWS checks on connections idle for too long.
                   1554:         * The fastest allowed timestamp clock is 1ms.  That turns out to
                   1555:         * be about 24 days before it wraps.  XXX Right now our lowerbound
                   1556:         * TS echo check only works for the first 12 days of a connection
                   1557:         * when the TS has exhausted half its 32bit space
                   1558:         */
                   1559: #define TS_MAX_IDLE    (24*24*60*60)
                   1560: #define TS_MAX_CONN    (12*24*60*60)   /* XXX remove when better tsecr check */
                   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:                /* Validate that the timestamps are "in-window".
                   1589:                 * RFC1323 describes TCP Timestamp options that allow
                   1590:                 * measurement of RTT (round trip time) and PAWS
                   1591:                 * (protection against wrapped sequence numbers).  PAWS
                   1592:                 * gives us a set of rules for rejecting packets on
                   1593:                 * long fat pipes (packets that were somehow delayed
                   1594:                 * in transit longer than the time it took to send the
                   1595:                 * full TCP sequence space of 4Gb).  We can use these
                   1596:                 * rules and infer a few others that will let us treat
                   1597:                 * the 32bit timestamp and the 32bit echoed timestamp
                   1598:                 * as sequence numbers to prevent a blind attacker from
                   1599:                 * inserting packets into a connection.
                   1600:                 *
                   1601:                 * RFC1323 tells us:
                   1602:                 *  - The timestamp on this packet must be greater than
                   1603:                 *    or equal to the last value echoed by the other
                   1604:                 *    endpoint.  The RFC says those will be discarded
                   1605:                 *    since it is a dup that has already been acked.
                   1606:                 *    This gives us a lowerbound on the timestamp.
                   1607:                 *        timestamp >= other last echoed timestamp
                   1608:                 *  - The timestamp will be less than or equal to
                   1609:                 *    the last timestamp plus the time between the
                   1610:                 *    last packet and now.  The RFC defines the max
                   1611:                 *    clock rate as 1ms.  We will allow clocks to be
                   1612:                 *    up to 10% fast and will allow a total difference
                   1613:                 *    or 30 seconds due to a route change.  And this
                   1614:                 *    gives us an upperbound on the timestamp.
                   1615:                 *        timestamp <= last timestamp + max ticks
                   1616:                 *    We have to be careful here.  Windows will send an
                   1617:                 *    initial timestamp of zero and then initialize it
                   1618:                 *    to a random value after the 3whs; presumably to
                   1619:                 *    avoid a DoS by having to call an expensive RNG
                   1620:                 *    during a SYN flood.  Proof MS has at least one
                   1621:                 *    good security geek.
                   1622:                 *
                   1623:                 *  - The TCP timestamp option must also echo the other
                   1624:                 *    endpoints timestamp.  The timestamp echoed is the
                   1625:                 *    one carried on the earliest unacknowledged segment
                   1626:                 *    on the left edge of the sequence window.  The RFC
                   1627:                 *    states that the host will reject any echoed
                   1628:                 *    timestamps that were larger than any ever sent.
                   1629:                 *    This gives us an upperbound on the TS echo.
                   1630:                 *        tescr <= largest_tsval
                   1631:                 *  - The lowerbound on the TS echo is a little more
                   1632:                 *    tricky to determine.  The other endpoint's echoed
                   1633:                 *    values will not decrease.  But there may be
                   1634:                 *    network conditions that re-order packets and
                   1635:                 *    cause our view of them to decrease.  For now the
                   1636:                 *    only lowerbound we can safely determine is that
                   1637:                 *    the TS echo will never be less than the original
                   1638:                 *    TS.  XXX There is probably a better lowerbound.
                   1639:                 *    Remove TS_MAX_CONN with better lowerbound check.
                   1640:                 *        tescr >= other original TS
                   1641:                 *
                   1642:                 * It is also important to note that the fastest
                   1643:                 * timestamp clock of 1ms will wrap its 32bit space in
                   1644:                 * 24 days.  So we just disable TS checking after 24
                   1645:                 * days of idle time.  We actually must use a 12d
                   1646:                 * connection limit until we can come up with a better
                   1647:                 * lowerbound to the TS echo check.
                   1648:                 */
                   1649:                struct timeval delta_ts;
                   1650:                int ts_fudge;
                   1651:
                   1652:
                   1653:                /*
                   1654:                 * PFTM_TS_DIFF is how many seconds of leeway to allow
                   1655:                 * a host's timestamp.  This can happen if the previous
                   1656:                 * packet got delayed in transit for much longer than
                   1657:                 * this packet.
                   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:                /* Calculate max ticks since the last timestamp */
                   1664: #define TS_MAXFREQ     1100            /* RFC max TS freq of 1Khz + 10% skew */
                   1665: #define TS_MICROSECS   1000000         /* microseconds per second */
                   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:                        /* Bad RFC1323 implementation or an insertion attack.
                   1678:                         *
                   1679:                         * - Solaris 2.6 and 2.7 are known to send another ACK
                   1680:                         *   after the FIN,FIN|ACK,ACK closing that carries
                   1681:                         *   an old timestamp.
                   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:                /* XXX I'd really like to require tsecr but it's optional */
                   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:                /* Didn't send a timestamp.  Timestamps aren't really useful
                   1717:                 * when:
                   1718:                 *  - connection opening or closing (often not even sent).
                   1719:                 *    but we must not let an attacker to put a FIN on a
                   1720:                 *    data packet to sneak it through our ESTABLISHED check.
                   1721:                 *  - on a TCP reset.  RFC suggests not even looking at TS.
                   1722:                 *  - on an empty ACK.  The TS will not be echoed so it will
                   1723:                 *    probably not help keep the RTT calculation in sync and
                   1724:                 *    there isn't as much danger when the sequence numbers
                   1725:                 *    got wrapped.  So some stacks don't include TS on empty
                   1726:                 *    ACKs :-(
                   1727:                 *
                   1728:                 * To minimize the disruption to mostly RFC1323 conformant
                   1729:                 * stacks, we will only require timestamps on data packets.
                   1730:                 *
                   1731:                 * And what do ya know, we cannot require timestamps on data
                   1732:                 * packets.  There appear to be devices that do legitimate
                   1733:                 * TCP connection hijacking.  There are HTTP devices that allow
                   1734:                 * a 3whs (with timestamps) and then buffer the HTTP request.
                   1735:                 * If the intermediate device has the HTTP response cache, it
                   1736:                 * will spoof the response but not bother timestamping its
                   1737:                 * packets.  So we can look for the presence of a timestamp in
                   1738:                 * the first data packet and if there, require it in all future
                   1739:                 * packets.
                   1740:                 */
                   1741:
                   1742:                if (pd->p_len > 0 && (src->scrub->pfss_flags & PFSS_DATA_TS)) {
                   1743:                        /*
                   1744:                         * Hey!  Someone tried to sneak a packet in.  Or the
                   1745:                         * stack changed its RFC1323 behavior?!?!
                   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:         * We will note if a host sends his data packets with or without
                   1762:         * timestamps.  And require all data packets to contain a timestamp
                   1763:         * if the first does.  PAWS implicitly requires that all data packets be
                   1764:         * timestamped.  But I think there are middle-man devices that hijack
                   1765:         * TCP streams immediately after the 3whs and don't timestamp their
                   1766:         * packets (seen in a WWW accelerator or cache).
                   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:                                /* Don't warn if other host rejected RFC1323 */
                   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:         * Update PAWS values
                   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:                                /* tsval0 MUST be the lowest timestamp */
                   1807:                                src->scrub->pfss_tsval0 = tsval;
                   1808:                        }
                   1809:
                   1810:                        /* Only fully initialized after a TS gets echoed */
                   1811:                        if ((src->scrub->pfss_flags & PFSS_PAWS) == 0)
                   1812:                                src->scrub->pfss_flags |= PFSS_PAWS;
                   1813:                }
                   1814:        }
                   1815:
                   1816:        /* I have a dream....  TCP segment reassembly.... */
                   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: }

CVSweb