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

Annotation of sys/net/pf.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: pf.c,v 1.552 2007/08/21 15:57:27 dhartmei Exp $ */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 2001 Daniel Hartmeier
        !             5:  * Copyright (c) 2002,2003 Henning Brauer
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * Redistribution and use in source and binary forms, with or without
        !             9:  * modification, are permitted provided that the following conditions
        !            10:  * are met:
        !            11:  *
        !            12:  *    - Redistributions of source code must retain the above copyright
        !            13:  *      notice, this list of conditions and the following disclaimer.
        !            14:  *    - Redistributions in binary form must reproduce the above
        !            15:  *      copyright notice, this list of conditions and the following
        !            16:  *      disclaimer in the documentation and/or other materials provided
        !            17:  *      with the distribution.
        !            18:  *
        !            19:  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
        !            20:  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
        !            21:  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
        !            22:  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
        !            23:  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
        !            24:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
        !            25:  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
        !            26:  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
        !            27:  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            28:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
        !            29:  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            30:  * POSSIBILITY OF SUCH DAMAGE.
        !            31:  *
        !            32:  * Effort sponsored in part by the Defense Advanced Research Projects
        !            33:  * Agency (DARPA) and Air Force Research Laboratory, Air Force
        !            34:  * Materiel Command, USAF, under agreement number F30602-01-2-0537.
        !            35:  *
        !            36:  */
        !            37:
        !            38: #include "bpfilter.h"
        !            39: #include "pflog.h"
        !            40: #include "pfsync.h"
        !            41:
        !            42: #include <sys/param.h>
        !            43: #include <sys/systm.h>
        !            44: #include <sys/mbuf.h>
        !            45: #include <sys/filio.h>
        !            46: #include <sys/socket.h>
        !            47: #include <sys/socketvar.h>
        !            48: #include <sys/kernel.h>
        !            49: #include <sys/time.h>
        !            50: #include <sys/pool.h>
        !            51: #include <sys/proc.h>
        !            52: #include <sys/rwlock.h>
        !            53:
        !            54: #include <net/if.h>
        !            55: #include <net/if_types.h>
        !            56: #include <net/bpf.h>
        !            57: #include <net/route.h>
        !            58: #include <net/radix_mpath.h>
        !            59:
        !            60: #include <netinet/in.h>
        !            61: #include <netinet/in_var.h>
        !            62: #include <netinet/in_systm.h>
        !            63: #include <netinet/ip.h>
        !            64: #include <netinet/ip_var.h>
        !            65: #include <netinet/tcp.h>
        !            66: #include <netinet/tcp_seq.h>
        !            67: #include <netinet/udp.h>
        !            68: #include <netinet/ip_icmp.h>
        !            69: #include <netinet/in_pcb.h>
        !            70: #include <netinet/tcp_timer.h>
        !            71: #include <netinet/tcp_var.h>
        !            72: #include <netinet/udp_var.h>
        !            73: #include <netinet/icmp_var.h>
        !            74: #include <netinet/if_ether.h>
        !            75:
        !            76: #include <dev/rndvar.h>
        !            77: #include <net/pfvar.h>
        !            78: #include <net/if_pflog.h>
        !            79:
        !            80: #if NPFSYNC > 0
        !            81: #include <net/if_pfsync.h>
        !            82: #endif /* NPFSYNC > 0 */
        !            83:
        !            84: #ifdef INET6
        !            85: #include <netinet/ip6.h>
        !            86: #include <netinet/in_pcb.h>
        !            87: #include <netinet/icmp6.h>
        !            88: #include <netinet6/nd6.h>
        !            89: #endif /* INET6 */
        !            90:
        !            91:
        !            92: #define DPFPRINTF(n, x)        if (pf_status.debug >= (n)) printf x
        !            93:
        !            94: /*
        !            95:  * Global variables
        !            96:  */
        !            97:
        !            98: /* state tables */
        !            99: struct pf_state_tree_lan_ext    pf_statetbl_lan_ext;
        !           100: struct pf_state_tree_ext_gwy    pf_statetbl_ext_gwy;
        !           101:
        !           102: struct pf_altqqueue     pf_altqs[2];
        !           103: struct pf_palist        pf_pabuf;
        !           104: struct pf_altqqueue    *pf_altqs_active;
        !           105: struct pf_altqqueue    *pf_altqs_inactive;
        !           106: struct pf_status        pf_status;
        !           107:
        !           108: u_int32_t               ticket_altqs_active;
        !           109: u_int32_t               ticket_altqs_inactive;
        !           110: int                     altqs_inactive_open;
        !           111: u_int32_t               ticket_pabuf;
        !           112:
        !           113: struct pf_anchor_stackframe {
        !           114:        struct pf_ruleset                       *rs;
        !           115:        struct pf_rule                          *r;
        !           116:        struct pf_anchor_node                   *parent;
        !           117:        struct pf_anchor                        *child;
        !           118: } pf_anchor_stack[64];
        !           119:
        !           120: struct pool             pf_src_tree_pl, pf_rule_pl, pf_pooladdr_pl;
        !           121: struct pool             pf_state_pl, pf_state_key_pl;
        !           122: struct pool             pf_altq_pl;
        !           123:
        !           124: void                    pf_print_host(struct pf_addr *, u_int16_t, u_int8_t);
        !           125:
        !           126: void                    pf_init_threshold(struct pf_threshold *, u_int32_t,
        !           127:                            u_int32_t);
        !           128: void                    pf_add_threshold(struct pf_threshold *);
        !           129: int                     pf_check_threshold(struct pf_threshold *);
        !           130:
        !           131: void                    pf_change_ap(struct pf_addr *, u_int16_t *,
        !           132:                            u_int16_t *, u_int16_t *, struct pf_addr *,
        !           133:                            u_int16_t, u_int8_t, sa_family_t);
        !           134: int                     pf_modulate_sack(struct mbuf *, int, struct pf_pdesc *,
        !           135:                            struct tcphdr *, struct pf_state_peer *);
        !           136: #ifdef INET6
        !           137: void                    pf_change_a6(struct pf_addr *, u_int16_t *,
        !           138:                            struct pf_addr *, u_int8_t);
        !           139: #endif /* INET6 */
        !           140: void                    pf_change_icmp(struct pf_addr *, u_int16_t *,
        !           141:                            struct pf_addr *, struct pf_addr *, u_int16_t,
        !           142:                            u_int16_t *, u_int16_t *, u_int16_t *,
        !           143:                            u_int16_t *, u_int8_t, sa_family_t);
        !           144: void                    pf_send_tcp(const struct pf_rule *, sa_family_t,
        !           145:                            const struct pf_addr *, const struct pf_addr *,
        !           146:                            u_int16_t, u_int16_t, u_int32_t, u_int32_t,
        !           147:                            u_int8_t, u_int16_t, u_int16_t, u_int8_t, int,
        !           148:                            u_int16_t, struct ether_header *, struct ifnet *);
        !           149: void                    pf_send_icmp(struct mbuf *, u_int8_t, u_int8_t,
        !           150:                            sa_family_t, struct pf_rule *);
        !           151: struct pf_rule         *pf_match_translation(struct pf_pdesc *, struct mbuf *,
        !           152:                            int, int, struct pfi_kif *,
        !           153:                            struct pf_addr *, u_int16_t, struct pf_addr *,
        !           154:                            u_int16_t, int);
        !           155: struct pf_rule         *pf_get_translation(struct pf_pdesc *, struct mbuf *,
        !           156:                            int, int, struct pfi_kif *, struct pf_src_node **,
        !           157:                            struct pf_addr *, u_int16_t,
        !           158:                            struct pf_addr *, u_int16_t,
        !           159:                            struct pf_addr *, u_int16_t *);
        !           160: void                    pf_attach_state(struct pf_state_key *,
        !           161:                            struct pf_state *, int);
        !           162: void                    pf_detach_state(struct pf_state *, int);
        !           163: int                     pf_test_rule(struct pf_rule **, struct pf_state **,
        !           164:                            int, struct pfi_kif *, struct mbuf *, int,
        !           165:                            void *, struct pf_pdesc *, struct pf_rule **,
        !           166:                            struct pf_ruleset **, struct ifqueue *);
        !           167: int                     pf_test_fragment(struct pf_rule **, int,
        !           168:                            struct pfi_kif *, struct mbuf *, void *,
        !           169:                            struct pf_pdesc *, struct pf_rule **,
        !           170:                            struct pf_ruleset **);
        !           171: int                     pf_test_state_tcp(struct pf_state **, int,
        !           172:                            struct pfi_kif *, struct mbuf *, int,
        !           173:                            void *, struct pf_pdesc *, u_short *);
        !           174: int                     pf_test_state_udp(struct pf_state **, int,
        !           175:                            struct pfi_kif *, struct mbuf *, int,
        !           176:                            void *, struct pf_pdesc *);
        !           177: int                     pf_test_state_icmp(struct pf_state **, int,
        !           178:                            struct pfi_kif *, struct mbuf *, int,
        !           179:                            void *, struct pf_pdesc *, u_short *);
        !           180: int                     pf_test_state_other(struct pf_state **, int,
        !           181:                            struct pfi_kif *, struct pf_pdesc *);
        !           182: int                     pf_match_tag(struct mbuf *, struct pf_rule *, int *);
        !           183: void                    pf_step_into_anchor(int *, struct pf_ruleset **, int,
        !           184:                            struct pf_rule **, struct pf_rule **,  int *);
        !           185: int                     pf_step_out_of_anchor(int *, struct pf_ruleset **,
        !           186:                             int, struct pf_rule **, struct pf_rule **,
        !           187:                             int *);
        !           188: void                    pf_hash(struct pf_addr *, struct pf_addr *,
        !           189:                            struct pf_poolhashkey *, sa_family_t);
        !           190: int                     pf_map_addr(u_int8_t, struct pf_rule *,
        !           191:                            struct pf_addr *, struct pf_addr *,
        !           192:                            struct pf_addr *, struct pf_src_node **);
        !           193: int                     pf_get_sport(sa_family_t, u_int8_t, struct pf_rule *,
        !           194:                            struct pf_addr *, struct pf_addr *, u_int16_t,
        !           195:                            struct pf_addr *, u_int16_t*, u_int16_t, u_int16_t,
        !           196:                            struct pf_src_node **);
        !           197: void                    pf_route(struct mbuf **, struct pf_rule *, int,
        !           198:                            struct ifnet *, struct pf_state *,
        !           199:                            struct pf_pdesc *);
        !           200: void                    pf_route6(struct mbuf **, struct pf_rule *, int,
        !           201:                            struct ifnet *, struct pf_state *,
        !           202:                            struct pf_pdesc *);
        !           203: int                     pf_socket_lookup(int, struct pf_pdesc *);
        !           204: u_int8_t                pf_get_wscale(struct mbuf *, int, u_int16_t,
        !           205:                            sa_family_t);
        !           206: u_int16_t               pf_get_mss(struct mbuf *, int, u_int16_t,
        !           207:                            sa_family_t);
        !           208: u_int16_t               pf_calc_mss(struct pf_addr *, sa_family_t,
        !           209:                                u_int16_t);
        !           210: void                    pf_set_rt_ifp(struct pf_state *,
        !           211:                            struct pf_addr *);
        !           212: int                     pf_check_proto_cksum(struct mbuf *, int, int,
        !           213:                            u_int8_t, sa_family_t);
        !           214: int                     pf_addr_wrap_neq(struct pf_addr_wrap *,
        !           215:                            struct pf_addr_wrap *);
        !           216: struct pf_state                *pf_find_state(struct pfi_kif *,
        !           217:                            struct pf_state_key_cmp *, u_int8_t);
        !           218: int                     pf_src_connlimit(struct pf_state **);
        !           219: void                    pf_stateins_err(const char *, struct pf_state *,
        !           220:                            struct pfi_kif *);
        !           221: int                     pf_check_congestion(struct ifqueue *);
        !           222:
        !           223: extern struct pool pfr_ktable_pl;
        !           224: extern struct pool pfr_kentry_pl;
        !           225:
        !           226: struct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX] = {
        !           227:        { &pf_state_pl, PFSTATE_HIWAT },
        !           228:        { &pf_src_tree_pl, PFSNODE_HIWAT },
        !           229:        { &pf_frent_pl, PFFRAG_FRENT_HIWAT },
        !           230:        { &pfr_ktable_pl, PFR_KTABLE_HIWAT },
        !           231:        { &pfr_kentry_pl, PFR_KENTRY_HIWAT }
        !           232: };
        !           233:
        !           234: #define STATE_LOOKUP()                                                 \
        !           235:        do {                                                            \
        !           236:                if (direction == PF_IN)                                 \
        !           237:                        *state = pf_find_state(kif, &key, PF_EXT_GWY);  \
        !           238:                else                                                    \
        !           239:                        *state = pf_find_state(kif, &key, PF_LAN_EXT);  \
        !           240:                if (*state == NULL || (*state)->timeout == PFTM_PURGE)  \
        !           241:                        return (PF_DROP);                               \
        !           242:                if (direction == PF_OUT &&                              \
        !           243:                    (((*state)->rule.ptr->rt == PF_ROUTETO &&           \
        !           244:                    (*state)->rule.ptr->direction == PF_OUT) ||         \
        !           245:                    ((*state)->rule.ptr->rt == PF_REPLYTO &&            \
        !           246:                    (*state)->rule.ptr->direction == PF_IN)) &&         \
        !           247:                    (*state)->rt_kif != NULL &&                         \
        !           248:                    (*state)->rt_kif != kif)                            \
        !           249:                        return (PF_PASS);                               \
        !           250:        } while (0)
        !           251:
        !           252: #define        STATE_TRANSLATE(sk) \
        !           253:        (sk)->lan.addr.addr32[0] != (sk)->gwy.addr.addr32[0] || \
        !           254:        ((sk)->af == AF_INET6 && \
        !           255:        ((sk)->lan.addr.addr32[1] != (sk)->gwy.addr.addr32[1] || \
        !           256:        (sk)->lan.addr.addr32[2] != (sk)->gwy.addr.addr32[2] || \
        !           257:        (sk)->lan.addr.addr32[3] != (sk)->gwy.addr.addr32[3])) || \
        !           258:        (sk)->lan.port != (sk)->gwy.port
        !           259:
        !           260: #define BOUND_IFACE(r, k) \
        !           261:        ((r)->rule_flag & PFRULE_IFBOUND) ? (k) : pfi_all
        !           262:
        !           263: #define STATE_INC_COUNTERS(s)                          \
        !           264:        do {                                            \
        !           265:                s->rule.ptr->states++;                  \
        !           266:                if (s->anchor.ptr != NULL)              \
        !           267:                        s->anchor.ptr->states++;        \
        !           268:                if (s->nat_rule.ptr != NULL)            \
        !           269:                        s->nat_rule.ptr->states++;      \
        !           270:        } while (0)
        !           271:
        !           272: #define STATE_DEC_COUNTERS(s)                          \
        !           273:        do {                                            \
        !           274:                if (s->nat_rule.ptr != NULL)            \
        !           275:                        s->nat_rule.ptr->states--;      \
        !           276:                if (s->anchor.ptr != NULL)              \
        !           277:                        s->anchor.ptr->states--;        \
        !           278:                s->rule.ptr->states--;                  \
        !           279:        } while (0)
        !           280:
        !           281: static __inline int pf_src_compare(struct pf_src_node *, struct pf_src_node *);
        !           282: static __inline int pf_state_compare_lan_ext(struct pf_state_key *,
        !           283:        struct pf_state_key *);
        !           284: static __inline int pf_state_compare_ext_gwy(struct pf_state_key *,
        !           285:        struct pf_state_key *);
        !           286: static __inline int pf_state_compare_id(struct pf_state *,
        !           287:        struct pf_state *);
        !           288:
        !           289: struct pf_src_tree tree_src_tracking;
        !           290:
        !           291: struct pf_state_tree_id tree_id;
        !           292: struct pf_state_queue state_list;
        !           293:
        !           294: RB_GENERATE(pf_src_tree, pf_src_node, entry, pf_src_compare);
        !           295: RB_GENERATE(pf_state_tree_lan_ext, pf_state_key,
        !           296:     entry_lan_ext, pf_state_compare_lan_ext);
        !           297: RB_GENERATE(pf_state_tree_ext_gwy, pf_state_key,
        !           298:     entry_ext_gwy, pf_state_compare_ext_gwy);
        !           299: RB_GENERATE(pf_state_tree_id, pf_state,
        !           300:     entry_id, pf_state_compare_id);
        !           301:
        !           302: #define        PF_DT_SKIP_LANEXT       0x01
        !           303: #define        PF_DT_SKIP_EXTGWY       0x02
        !           304:
        !           305: static __inline int
        !           306: pf_src_compare(struct pf_src_node *a, struct pf_src_node *b)
        !           307: {
        !           308:        int     diff;
        !           309:
        !           310:        if (a->rule.ptr > b->rule.ptr)
        !           311:                return (1);
        !           312:        if (a->rule.ptr < b->rule.ptr)
        !           313:                return (-1);
        !           314:        if ((diff = a->af - b->af) != 0)
        !           315:                return (diff);
        !           316:        switch (a->af) {
        !           317: #ifdef INET
        !           318:        case AF_INET:
        !           319:                if (a->addr.addr32[0] > b->addr.addr32[0])
        !           320:                        return (1);
        !           321:                if (a->addr.addr32[0] < b->addr.addr32[0])
        !           322:                        return (-1);
        !           323:                break;
        !           324: #endif /* INET */
        !           325: #ifdef INET6
        !           326:        case AF_INET6:
        !           327:                if (a->addr.addr32[3] > b->addr.addr32[3])
        !           328:                        return (1);
        !           329:                if (a->addr.addr32[3] < b->addr.addr32[3])
        !           330:                        return (-1);
        !           331:                if (a->addr.addr32[2] > b->addr.addr32[2])
        !           332:                        return (1);
        !           333:                if (a->addr.addr32[2] < b->addr.addr32[2])
        !           334:                        return (-1);
        !           335:                if (a->addr.addr32[1] > b->addr.addr32[1])
        !           336:                        return (1);
        !           337:                if (a->addr.addr32[1] < b->addr.addr32[1])
        !           338:                        return (-1);
        !           339:                if (a->addr.addr32[0] > b->addr.addr32[0])
        !           340:                        return (1);
        !           341:                if (a->addr.addr32[0] < b->addr.addr32[0])
        !           342:                        return (-1);
        !           343:                break;
        !           344: #endif /* INET6 */
        !           345:        }
        !           346:        return (0);
        !           347: }
        !           348:
        !           349: static __inline int
        !           350: pf_state_compare_lan_ext(struct pf_state_key *a, struct pf_state_key *b)
        !           351: {
        !           352:        int     diff;
        !           353:
        !           354:        if ((diff = a->proto - b->proto) != 0)
        !           355:                return (diff);
        !           356:        if ((diff = a->af - b->af) != 0)
        !           357:                return (diff);
        !           358:        switch (a->af) {
        !           359: #ifdef INET
        !           360:        case AF_INET:
        !           361:                if (a->lan.addr.addr32[0] > b->lan.addr.addr32[0])
        !           362:                        return (1);
        !           363:                if (a->lan.addr.addr32[0] < b->lan.addr.addr32[0])
        !           364:                        return (-1);
        !           365:                if (a->ext.addr.addr32[0] > b->ext.addr.addr32[0])
        !           366:                        return (1);
        !           367:                if (a->ext.addr.addr32[0] < b->ext.addr.addr32[0])
        !           368:                        return (-1);
        !           369:                break;
        !           370: #endif /* INET */
        !           371: #ifdef INET6
        !           372:        case AF_INET6:
        !           373:                if (a->lan.addr.addr32[3] > b->lan.addr.addr32[3])
        !           374:                        return (1);
        !           375:                if (a->lan.addr.addr32[3] < b->lan.addr.addr32[3])
        !           376:                        return (-1);
        !           377:                if (a->ext.addr.addr32[3] > b->ext.addr.addr32[3])
        !           378:                        return (1);
        !           379:                if (a->ext.addr.addr32[3] < b->ext.addr.addr32[3])
        !           380:                        return (-1);
        !           381:                if (a->lan.addr.addr32[2] > b->lan.addr.addr32[2])
        !           382:                        return (1);
        !           383:                if (a->lan.addr.addr32[2] < b->lan.addr.addr32[2])
        !           384:                        return (-1);
        !           385:                if (a->ext.addr.addr32[2] > b->ext.addr.addr32[2])
        !           386:                        return (1);
        !           387:                if (a->ext.addr.addr32[2] < b->ext.addr.addr32[2])
        !           388:                        return (-1);
        !           389:                if (a->lan.addr.addr32[1] > b->lan.addr.addr32[1])
        !           390:                        return (1);
        !           391:                if (a->lan.addr.addr32[1] < b->lan.addr.addr32[1])
        !           392:                        return (-1);
        !           393:                if (a->ext.addr.addr32[1] > b->ext.addr.addr32[1])
        !           394:                        return (1);
        !           395:                if (a->ext.addr.addr32[1] < b->ext.addr.addr32[1])
        !           396:                        return (-1);
        !           397:                if (a->lan.addr.addr32[0] > b->lan.addr.addr32[0])
        !           398:                        return (1);
        !           399:                if (a->lan.addr.addr32[0] < b->lan.addr.addr32[0])
        !           400:                        return (-1);
        !           401:                if (a->ext.addr.addr32[0] > b->ext.addr.addr32[0])
        !           402:                        return (1);
        !           403:                if (a->ext.addr.addr32[0] < b->ext.addr.addr32[0])
        !           404:                        return (-1);
        !           405:                break;
        !           406: #endif /* INET6 */
        !           407:        }
        !           408:
        !           409:        if ((diff = a->lan.port - b->lan.port) != 0)
        !           410:                return (diff);
        !           411:        if ((diff = a->ext.port - b->ext.port) != 0)
        !           412:                return (diff);
        !           413:
        !           414:        return (0);
        !           415: }
        !           416:
        !           417: static __inline int
        !           418: pf_state_compare_ext_gwy(struct pf_state_key *a, struct pf_state_key *b)
        !           419: {
        !           420:        int     diff;
        !           421:
        !           422:        if ((diff = a->proto - b->proto) != 0)
        !           423:                return (diff);
        !           424:        if ((diff = a->af - b->af) != 0)
        !           425:                return (diff);
        !           426:        switch (a->af) {
        !           427: #ifdef INET
        !           428:        case AF_INET:
        !           429:                if (a->ext.addr.addr32[0] > b->ext.addr.addr32[0])
        !           430:                        return (1);
        !           431:                if (a->ext.addr.addr32[0] < b->ext.addr.addr32[0])
        !           432:                        return (-1);
        !           433:                if (a->gwy.addr.addr32[0] > b->gwy.addr.addr32[0])
        !           434:                        return (1);
        !           435:                if (a->gwy.addr.addr32[0] < b->gwy.addr.addr32[0])
        !           436:                        return (-1);
        !           437:                break;
        !           438: #endif /* INET */
        !           439: #ifdef INET6
        !           440:        case AF_INET6:
        !           441:                if (a->ext.addr.addr32[3] > b->ext.addr.addr32[3])
        !           442:                        return (1);
        !           443:                if (a->ext.addr.addr32[3] < b->ext.addr.addr32[3])
        !           444:                        return (-1);
        !           445:                if (a->gwy.addr.addr32[3] > b->gwy.addr.addr32[3])
        !           446:                        return (1);
        !           447:                if (a->gwy.addr.addr32[3] < b->gwy.addr.addr32[3])
        !           448:                        return (-1);
        !           449:                if (a->ext.addr.addr32[2] > b->ext.addr.addr32[2])
        !           450:                        return (1);
        !           451:                if (a->ext.addr.addr32[2] < b->ext.addr.addr32[2])
        !           452:                        return (-1);
        !           453:                if (a->gwy.addr.addr32[2] > b->gwy.addr.addr32[2])
        !           454:                        return (1);
        !           455:                if (a->gwy.addr.addr32[2] < b->gwy.addr.addr32[2])
        !           456:                        return (-1);
        !           457:                if (a->ext.addr.addr32[1] > b->ext.addr.addr32[1])
        !           458:                        return (1);
        !           459:                if (a->ext.addr.addr32[1] < b->ext.addr.addr32[1])
        !           460:                        return (-1);
        !           461:                if (a->gwy.addr.addr32[1] > b->gwy.addr.addr32[1])
        !           462:                        return (1);
        !           463:                if (a->gwy.addr.addr32[1] < b->gwy.addr.addr32[1])
        !           464:                        return (-1);
        !           465:                if (a->ext.addr.addr32[0] > b->ext.addr.addr32[0])
        !           466:                        return (1);
        !           467:                if (a->ext.addr.addr32[0] < b->ext.addr.addr32[0])
        !           468:                        return (-1);
        !           469:                if (a->gwy.addr.addr32[0] > b->gwy.addr.addr32[0])
        !           470:                        return (1);
        !           471:                if (a->gwy.addr.addr32[0] < b->gwy.addr.addr32[0])
        !           472:                        return (-1);
        !           473:                break;
        !           474: #endif /* INET6 */
        !           475:        }
        !           476:
        !           477:        if ((diff = a->ext.port - b->ext.port) != 0)
        !           478:                return (diff);
        !           479:        if ((diff = a->gwy.port - b->gwy.port) != 0)
        !           480:                return (diff);
        !           481:
        !           482:        return (0);
        !           483: }
        !           484:
        !           485: static __inline int
        !           486: pf_state_compare_id(struct pf_state *a, struct pf_state *b)
        !           487: {
        !           488:        if (a->id > b->id)
        !           489:                return (1);
        !           490:        if (a->id < b->id)
        !           491:                return (-1);
        !           492:        if (a->creatorid > b->creatorid)
        !           493:                return (1);
        !           494:        if (a->creatorid < b->creatorid)
        !           495:                return (-1);
        !           496:
        !           497:        return (0);
        !           498: }
        !           499:
        !           500: #ifdef INET6
        !           501: void
        !           502: pf_addrcpy(struct pf_addr *dst, struct pf_addr *src, sa_family_t af)
        !           503: {
        !           504:        switch (af) {
        !           505: #ifdef INET
        !           506:        case AF_INET:
        !           507:                dst->addr32[0] = src->addr32[0];
        !           508:                break;
        !           509: #endif /* INET */
        !           510:        case AF_INET6:
        !           511:                dst->addr32[0] = src->addr32[0];
        !           512:                dst->addr32[1] = src->addr32[1];
        !           513:                dst->addr32[2] = src->addr32[2];
        !           514:                dst->addr32[3] = src->addr32[3];
        !           515:                break;
        !           516:        }
        !           517: }
        !           518: #endif /* INET6 */
        !           519:
        !           520: struct pf_state *
        !           521: pf_find_state_byid(struct pf_state_cmp *key)
        !           522: {
        !           523:        pf_status.fcounters[FCNT_STATE_SEARCH]++;
        !           524:
        !           525:        return (RB_FIND(pf_state_tree_id, &tree_id, (struct pf_state *)key));
        !           526: }
        !           527:
        !           528: struct pf_state *
        !           529: pf_find_state(struct pfi_kif *kif, struct pf_state_key_cmp *key, u_int8_t tree)
        !           530: {
        !           531:        struct pf_state_key     *sk;
        !           532:        struct pf_state         *s;
        !           533:
        !           534:        pf_status.fcounters[FCNT_STATE_SEARCH]++;
        !           535:
        !           536:        switch (tree) {
        !           537:        case PF_LAN_EXT:
        !           538:                sk = RB_FIND(pf_state_tree_lan_ext, &pf_statetbl_lan_ext,
        !           539:                    (struct pf_state_key *)key);
        !           540:                break;
        !           541:        case PF_EXT_GWY:
        !           542:                sk = RB_FIND(pf_state_tree_ext_gwy, &pf_statetbl_ext_gwy,
        !           543:                    (struct pf_state_key *)key);
        !           544:                break;
        !           545:        default:
        !           546:                panic("pf_find_state");
        !           547:        }
        !           548:
        !           549:        /* list is sorted, if-bound states before floating ones */
        !           550:        if (sk != NULL)
        !           551:                TAILQ_FOREACH(s, &sk->states, next)
        !           552:                        if (s->kif == pfi_all || s->kif == kif)
        !           553:                                return (s);
        !           554:
        !           555:        return (NULL);
        !           556: }
        !           557:
        !           558: struct pf_state *
        !           559: pf_find_state_all(struct pf_state_key_cmp *key, u_int8_t tree, int *more)
        !           560: {
        !           561:        struct pf_state_key     *sk;
        !           562:        struct pf_state         *s, *ret = NULL;
        !           563:
        !           564:        pf_status.fcounters[FCNT_STATE_SEARCH]++;
        !           565:
        !           566:        switch (tree) {
        !           567:        case PF_LAN_EXT:
        !           568:                sk = RB_FIND(pf_state_tree_lan_ext,
        !           569:                    &pf_statetbl_lan_ext, (struct pf_state_key *)key);
        !           570:                break;
        !           571:        case PF_EXT_GWY:
        !           572:                sk = RB_FIND(pf_state_tree_ext_gwy,
        !           573:                    &pf_statetbl_ext_gwy, (struct pf_state_key *)key);
        !           574:                break;
        !           575:        default:
        !           576:                panic("pf_find_state_all");
        !           577:        }
        !           578:
        !           579:        if (sk != NULL) {
        !           580:                ret = TAILQ_FIRST(&sk->states);
        !           581:                if (more == NULL)
        !           582:                        return (ret);
        !           583:
        !           584:                TAILQ_FOREACH(s, &sk->states, next)
        !           585:                        (*more)++;
        !           586:        }
        !           587:
        !           588:        return (ret);
        !           589: }
        !           590:
        !           591: void
        !           592: pf_init_threshold(struct pf_threshold *threshold,
        !           593:     u_int32_t limit, u_int32_t seconds)
        !           594: {
        !           595:        threshold->limit = limit * PF_THRESHOLD_MULT;
        !           596:        threshold->seconds = seconds;
        !           597:        threshold->count = 0;
        !           598:        threshold->last = time_second;
        !           599: }
        !           600:
        !           601: void
        !           602: pf_add_threshold(struct pf_threshold *threshold)
        !           603: {
        !           604:        u_int32_t t = time_second, diff = t - threshold->last;
        !           605:
        !           606:        if (diff >= threshold->seconds)
        !           607:                threshold->count = 0;
        !           608:        else
        !           609:                threshold->count -= threshold->count * diff /
        !           610:                    threshold->seconds;
        !           611:        threshold->count += PF_THRESHOLD_MULT;
        !           612:        threshold->last = t;
        !           613: }
        !           614:
        !           615: int
        !           616: pf_check_threshold(struct pf_threshold *threshold)
        !           617: {
        !           618:        return (threshold->count > threshold->limit);
        !           619: }
        !           620:
        !           621: int
        !           622: pf_src_connlimit(struct pf_state **state)
        !           623: {
        !           624:        int bad = 0;
        !           625:
        !           626:        (*state)->src_node->conn++;
        !           627:        (*state)->src.tcp_est = 1;
        !           628:        pf_add_threshold(&(*state)->src_node->conn_rate);
        !           629:
        !           630:        if ((*state)->rule.ptr->max_src_conn &&
        !           631:            (*state)->rule.ptr->max_src_conn <
        !           632:            (*state)->src_node->conn) {
        !           633:                pf_status.lcounters[LCNT_SRCCONN]++;
        !           634:                bad++;
        !           635:        }
        !           636:
        !           637:        if ((*state)->rule.ptr->max_src_conn_rate.limit &&
        !           638:            pf_check_threshold(&(*state)->src_node->conn_rate)) {
        !           639:                pf_status.lcounters[LCNT_SRCCONNRATE]++;
        !           640:                bad++;
        !           641:        }
        !           642:
        !           643:        if (!bad)
        !           644:                return (0);
        !           645:
        !           646:        if ((*state)->rule.ptr->overload_tbl) {
        !           647:                struct pfr_addr p;
        !           648:                u_int32_t       killed = 0;
        !           649:
        !           650:                pf_status.lcounters[LCNT_OVERLOAD_TABLE]++;
        !           651:                if (pf_status.debug >= PF_DEBUG_MISC) {
        !           652:                        printf("pf_src_connlimit: blocking address ");
        !           653:                        pf_print_host(&(*state)->src_node->addr, 0,
        !           654:                            (*state)->state_key->af);
        !           655:                }
        !           656:
        !           657:                bzero(&p, sizeof(p));
        !           658:                p.pfra_af = (*state)->state_key->af;
        !           659:                switch ((*state)->state_key->af) {
        !           660: #ifdef INET
        !           661:                case AF_INET:
        !           662:                        p.pfra_net = 32;
        !           663:                        p.pfra_ip4addr = (*state)->src_node->addr.v4;
        !           664:                        break;
        !           665: #endif /* INET */
        !           666: #ifdef INET6
        !           667:                case AF_INET6:
        !           668:                        p.pfra_net = 128;
        !           669:                        p.pfra_ip6addr = (*state)->src_node->addr.v6;
        !           670:                        break;
        !           671: #endif /* INET6 */
        !           672:                }
        !           673:
        !           674:                pfr_insert_kentry((*state)->rule.ptr->overload_tbl,
        !           675:                    &p, time_second);
        !           676:
        !           677:                /* kill existing states if that's required. */
        !           678:                if ((*state)->rule.ptr->flush) {
        !           679:                        struct pf_state_key *sk;
        !           680:                        struct pf_state *st;
        !           681:
        !           682:                        pf_status.lcounters[LCNT_OVERLOAD_FLUSH]++;
        !           683:                        RB_FOREACH(st, pf_state_tree_id, &tree_id) {
        !           684:                                sk = st->state_key;
        !           685:                                /*
        !           686:                                 * Kill states from this source.  (Only those
        !           687:                                 * from the same rule if PF_FLUSH_GLOBAL is not
        !           688:                                 * set)
        !           689:                                 */
        !           690:                                if (sk->af ==
        !           691:                                    (*state)->state_key->af &&
        !           692:                                    (((*state)->state_key->direction ==
        !           693:                                        PF_OUT &&
        !           694:                                    PF_AEQ(&(*state)->src_node->addr,
        !           695:                                        &sk->lan.addr, sk->af)) ||
        !           696:                                    ((*state)->state_key->direction == PF_IN &&
        !           697:                                    PF_AEQ(&(*state)->src_node->addr,
        !           698:                                        &sk->ext.addr, sk->af))) &&
        !           699:                                    ((*state)->rule.ptr->flush &
        !           700:                                    PF_FLUSH_GLOBAL ||
        !           701:                                    (*state)->rule.ptr == st->rule.ptr)) {
        !           702:                                        st->timeout = PFTM_PURGE;
        !           703:                                        st->src.state = st->dst.state =
        !           704:                                            TCPS_CLOSED;
        !           705:                                        killed++;
        !           706:                                }
        !           707:                        }
        !           708:                        if (pf_status.debug >= PF_DEBUG_MISC)
        !           709:                                printf(", %u states killed", killed);
        !           710:                }
        !           711:                if (pf_status.debug >= PF_DEBUG_MISC)
        !           712:                        printf("\n");
        !           713:        }
        !           714:
        !           715:        /* kill this state */
        !           716:        (*state)->timeout = PFTM_PURGE;
        !           717:        (*state)->src.state = (*state)->dst.state = TCPS_CLOSED;
        !           718:        return (1);
        !           719: }
        !           720:
        !           721: int
        !           722: pf_insert_src_node(struct pf_src_node **sn, struct pf_rule *rule,
        !           723:     struct pf_addr *src, sa_family_t af)
        !           724: {
        !           725:        struct pf_src_node      k;
        !           726:
        !           727:        if (*sn == NULL) {
        !           728:                k.af = af;
        !           729:                PF_ACPY(&k.addr, src, af);
        !           730:                if (rule->rule_flag & PFRULE_RULESRCTRACK ||
        !           731:                    rule->rpool.opts & PF_POOL_STICKYADDR)
        !           732:                        k.rule.ptr = rule;
        !           733:                else
        !           734:                        k.rule.ptr = NULL;
        !           735:                pf_status.scounters[SCNT_SRC_NODE_SEARCH]++;
        !           736:                *sn = RB_FIND(pf_src_tree, &tree_src_tracking, &k);
        !           737:        }
        !           738:        if (*sn == NULL) {
        !           739:                if (!rule->max_src_nodes ||
        !           740:                    rule->src_nodes < rule->max_src_nodes)
        !           741:                        (*sn) = pool_get(&pf_src_tree_pl, PR_NOWAIT);
        !           742:                else
        !           743:                        pf_status.lcounters[LCNT_SRCNODES]++;
        !           744:                if ((*sn) == NULL)
        !           745:                        return (-1);
        !           746:                bzero(*sn, sizeof(struct pf_src_node));
        !           747:
        !           748:                pf_init_threshold(&(*sn)->conn_rate,
        !           749:                    rule->max_src_conn_rate.limit,
        !           750:                    rule->max_src_conn_rate.seconds);
        !           751:
        !           752:                (*sn)->af = af;
        !           753:                if (rule->rule_flag & PFRULE_RULESRCTRACK ||
        !           754:                    rule->rpool.opts & PF_POOL_STICKYADDR)
        !           755:                        (*sn)->rule.ptr = rule;
        !           756:                else
        !           757:                        (*sn)->rule.ptr = NULL;
        !           758:                PF_ACPY(&(*sn)->addr, src, af);
        !           759:                if (RB_INSERT(pf_src_tree,
        !           760:                    &tree_src_tracking, *sn) != NULL) {
        !           761:                        if (pf_status.debug >= PF_DEBUG_MISC) {
        !           762:                                printf("pf: src_tree insert failed: ");
        !           763:                                pf_print_host(&(*sn)->addr, 0, af);
        !           764:                                printf("\n");
        !           765:                        }
        !           766:                        pool_put(&pf_src_tree_pl, *sn);
        !           767:                        return (-1);
        !           768:                }
        !           769:                (*sn)->creation = time_second;
        !           770:                (*sn)->ruletype = rule->action;
        !           771:                if ((*sn)->rule.ptr != NULL)
        !           772:                        (*sn)->rule.ptr->src_nodes++;
        !           773:                pf_status.scounters[SCNT_SRC_NODE_INSERT]++;
        !           774:                pf_status.src_nodes++;
        !           775:        } else {
        !           776:                if (rule->max_src_states &&
        !           777:                    (*sn)->states >= rule->max_src_states) {
        !           778:                        pf_status.lcounters[LCNT_SRCSTATES]++;
        !           779:                        return (-1);
        !           780:                }
        !           781:        }
        !           782:        return (0);
        !           783: }
        !           784:
        !           785: void
        !           786: pf_stateins_err(const char *tree, struct pf_state *s, struct pfi_kif *kif)
        !           787: {
        !           788:        struct pf_state_key     *sk = s->state_key;
        !           789:
        !           790:        if (pf_status.debug >= PF_DEBUG_MISC) {
        !           791:                printf("pf: state insert failed: %s %s", tree, kif->pfik_name);
        !           792:                printf(" lan: ");
        !           793:                pf_print_host(&sk->lan.addr, sk->lan.port,
        !           794:                    sk->af);
        !           795:                printf(" gwy: ");
        !           796:                pf_print_host(&sk->gwy.addr, sk->gwy.port,
        !           797:                    sk->af);
        !           798:                printf(" ext: ");
        !           799:                pf_print_host(&sk->ext.addr, sk->ext.port,
        !           800:                    sk->af);
        !           801:                if (s->sync_flags & PFSTATE_FROMSYNC)
        !           802:                        printf(" (from sync)");
        !           803:                printf("\n");
        !           804:        }
        !           805: }
        !           806:
        !           807: int
        !           808: pf_insert_state(struct pfi_kif *kif, struct pf_state *s)
        !           809: {
        !           810:        struct pf_state_key     *cur;
        !           811:        struct pf_state         *sp;
        !           812:
        !           813:        KASSERT(s->state_key != NULL);
        !           814:        s->kif = kif;
        !           815:
        !           816:        if ((cur = RB_INSERT(pf_state_tree_lan_ext, &pf_statetbl_lan_ext,
        !           817:            s->state_key)) != NULL) {
        !           818:                /* key exists. check for same kif, if none, add to key */
        !           819:                TAILQ_FOREACH(sp, &cur->states, next)
        !           820:                        if (sp->kif == kif) {   /* collision! */
        !           821:                                pf_stateins_err("tree_lan_ext", s, kif);
        !           822:                                return (-1);
        !           823:                        }
        !           824:                pf_detach_state(s, PF_DT_SKIP_LANEXT|PF_DT_SKIP_EXTGWY);
        !           825:                pf_attach_state(cur, s, kif == pfi_all ? 1 : 0);
        !           826:        }
        !           827:
        !           828:        /* if cur != NULL, we already found a state key and attached to it */
        !           829:        if (cur == NULL && (cur = RB_INSERT(pf_state_tree_ext_gwy,
        !           830:            &pf_statetbl_ext_gwy, s->state_key)) != NULL) {
        !           831:                /* must not happen. we must have found the sk above! */
        !           832:                pf_stateins_err("tree_ext_gwy", s, kif);
        !           833:                pf_detach_state(s, PF_DT_SKIP_EXTGWY);
        !           834:                return (-1);
        !           835:        }
        !           836:
        !           837:        if (s->id == 0 && s->creatorid == 0) {
        !           838:                s->id = htobe64(pf_status.stateid++);
        !           839:                s->creatorid = pf_status.hostid;
        !           840:        }
        !           841:        if (RB_INSERT(pf_state_tree_id, &tree_id, s) != NULL) {
        !           842:                if (pf_status.debug >= PF_DEBUG_MISC) {
        !           843:                        printf("pf: state insert failed: "
        !           844:                            "id: %016llx creatorid: %08x",
        !           845:                            betoh64(s->id), ntohl(s->creatorid));
        !           846:                        if (s->sync_flags & PFSTATE_FROMSYNC)
        !           847:                                printf(" (from sync)");
        !           848:                        printf("\n");
        !           849:                }
        !           850:                pf_detach_state(s, 0);
        !           851:                return (-1);
        !           852:        }
        !           853:        TAILQ_INSERT_TAIL(&state_list, s, entry_list);
        !           854:        pf_status.fcounters[FCNT_STATE_INSERT]++;
        !           855:        pf_status.states++;
        !           856:        pfi_kif_ref(kif, PFI_KIF_REF_STATE);
        !           857: #if NPFSYNC
        !           858:        pfsync_insert_state(s);
        !           859: #endif
        !           860:        return (0);
        !           861: }
        !           862:
        !           863: void
        !           864: pf_purge_thread(void *v)
        !           865: {
        !           866:        int nloops = 0, s;
        !           867:
        !           868:        for (;;) {
        !           869:                tsleep(pf_purge_thread, PWAIT, "pftm", 1 * hz);
        !           870:
        !           871:                s = splsoftnet();
        !           872:
        !           873:                /* process a fraction of the state table every second */
        !           874:                pf_purge_expired_states(1 + (pf_status.states
        !           875:                    / pf_default_rule.timeout[PFTM_INTERVAL]));
        !           876:
        !           877:                /* purge other expired types every PFTM_INTERVAL seconds */
        !           878:                if (++nloops >= pf_default_rule.timeout[PFTM_INTERVAL]) {
        !           879:                        pf_purge_expired_fragments();
        !           880:                        pf_purge_expired_src_nodes(0);
        !           881:                        nloops = 0;
        !           882:                }
        !           883:
        !           884:                splx(s);
        !           885:        }
        !           886: }
        !           887:
        !           888: u_int32_t
        !           889: pf_state_expires(const struct pf_state *state)
        !           890: {
        !           891:        u_int32_t       timeout;
        !           892:        u_int32_t       start;
        !           893:        u_int32_t       end;
        !           894:        u_int32_t       states;
        !           895:
        !           896:        /* handle all PFTM_* > PFTM_MAX here */
        !           897:        if (state->timeout == PFTM_PURGE)
        !           898:                return (time_second);
        !           899:        if (state->timeout == PFTM_UNTIL_PACKET)
        !           900:                return (0);
        !           901:        KASSERT(state->timeout != PFTM_UNLINKED);
        !           902:        KASSERT(state->timeout < PFTM_MAX);
        !           903:        timeout = state->rule.ptr->timeout[state->timeout];
        !           904:        if (!timeout)
        !           905:                timeout = pf_default_rule.timeout[state->timeout];
        !           906:        start = state->rule.ptr->timeout[PFTM_ADAPTIVE_START];
        !           907:        if (start) {
        !           908:                end = state->rule.ptr->timeout[PFTM_ADAPTIVE_END];
        !           909:                states = state->rule.ptr->states;
        !           910:        } else {
        !           911:                start = pf_default_rule.timeout[PFTM_ADAPTIVE_START];
        !           912:                end = pf_default_rule.timeout[PFTM_ADAPTIVE_END];
        !           913:                states = pf_status.states;
        !           914:        }
        !           915:        if (end && states > start && start < end) {
        !           916:                if (states < end)
        !           917:                        return (state->expire + timeout * (end - states) /
        !           918:                            (end - start));
        !           919:                else
        !           920:                        return (time_second);
        !           921:        }
        !           922:        return (state->expire + timeout);
        !           923: }
        !           924:
        !           925: void
        !           926: pf_purge_expired_src_nodes(int waslocked)
        !           927: {
        !           928:         struct pf_src_node             *cur, *next;
        !           929:         int                             locked = waslocked;
        !           930:
        !           931:         for (cur = RB_MIN(pf_src_tree, &tree_src_tracking); cur; cur = next) {
        !           932:                 next = RB_NEXT(pf_src_tree, &tree_src_tracking, cur);
        !           933:
        !           934:                 if (cur->states <= 0 && cur->expire <= time_second) {
        !           935:                         if (! locked) {
        !           936:                                 rw_enter_write(&pf_consistency_lock);
        !           937:                                 next = RB_NEXT(pf_src_tree,
        !           938:                                     &tree_src_tracking, cur);
        !           939:                                 locked = 1;
        !           940:                         }
        !           941:                         if (cur->rule.ptr != NULL) {
        !           942:                                 cur->rule.ptr->src_nodes--;
        !           943:                                 if (cur->rule.ptr->states <= 0 &&
        !           944:                                     cur->rule.ptr->max_src_nodes <= 0)
        !           945:                                         pf_rm_rule(NULL, cur->rule.ptr);
        !           946:                         }
        !           947:                         RB_REMOVE(pf_src_tree, &tree_src_tracking, cur);
        !           948:                         pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
        !           949:                         pf_status.src_nodes--;
        !           950:                         pool_put(&pf_src_tree_pl, cur);
        !           951:                 }
        !           952:         }
        !           953:
        !           954:         if (locked && !waslocked)
        !           955:                rw_exit_write(&pf_consistency_lock);
        !           956: }
        !           957:
        !           958: void
        !           959: pf_src_tree_remove_state(struct pf_state *s)
        !           960: {
        !           961:        u_int32_t timeout;
        !           962:
        !           963:        if (s->src_node != NULL) {
        !           964:                if (s->state_key->proto == IPPROTO_TCP) {
        !           965:                        if (s->src.tcp_est)
        !           966:                                --s->src_node->conn;
        !           967:                }
        !           968:                if (--s->src_node->states <= 0) {
        !           969:                        timeout = s->rule.ptr->timeout[PFTM_SRC_NODE];
        !           970:                        if (!timeout)
        !           971:                                timeout =
        !           972:                                    pf_default_rule.timeout[PFTM_SRC_NODE];
        !           973:                        s->src_node->expire = time_second + timeout;
        !           974:                }
        !           975:        }
        !           976:        if (s->nat_src_node != s->src_node && s->nat_src_node != NULL) {
        !           977:                if (--s->nat_src_node->states <= 0) {
        !           978:                        timeout = s->rule.ptr->timeout[PFTM_SRC_NODE];
        !           979:                        if (!timeout)
        !           980:                                timeout =
        !           981:                                    pf_default_rule.timeout[PFTM_SRC_NODE];
        !           982:                        s->nat_src_node->expire = time_second + timeout;
        !           983:                }
        !           984:        }
        !           985:        s->src_node = s->nat_src_node = NULL;
        !           986: }
        !           987:
        !           988: /* callers should be at splsoftnet */
        !           989: void
        !           990: pf_unlink_state(struct pf_state *cur)
        !           991: {
        !           992:        if (cur->src.state == PF_TCPS_PROXY_DST) {
        !           993:                pf_send_tcp(cur->rule.ptr, cur->state_key->af,
        !           994:                    &cur->state_key->ext.addr, &cur->state_key->lan.addr,
        !           995:                    cur->state_key->ext.port, cur->state_key->lan.port,
        !           996:                    cur->src.seqhi, cur->src.seqlo + 1,
        !           997:                    TH_RST|TH_ACK, 0, 0, 0, 1, cur->tag, NULL, NULL);
        !           998:        }
        !           999:        RB_REMOVE(pf_state_tree_id, &tree_id, cur);
        !          1000: #if NPFSYNC
        !          1001:        if (cur->creatorid == pf_status.hostid)
        !          1002:                pfsync_delete_state(cur);
        !          1003: #endif
        !          1004:        cur->timeout = PFTM_UNLINKED;
        !          1005:        pf_src_tree_remove_state(cur);
        !          1006:        pf_detach_state(cur, 0);
        !          1007: }
        !          1008:
        !          1009: /* callers should be at splsoftnet and hold the
        !          1010:  * write_lock on pf_consistency_lock */
        !          1011: void
        !          1012: pf_free_state(struct pf_state *cur)
        !          1013: {
        !          1014: #if NPFSYNC
        !          1015:        if (pfsyncif != NULL &&
        !          1016:            (pfsyncif->sc_bulk_send_next == cur ||
        !          1017:            pfsyncif->sc_bulk_terminator == cur))
        !          1018:                return;
        !          1019: #endif
        !          1020:        KASSERT(cur->timeout == PFTM_UNLINKED);
        !          1021:        if (--cur->rule.ptr->states <= 0 &&
        !          1022:            cur->rule.ptr->src_nodes <= 0)
        !          1023:                pf_rm_rule(NULL, cur->rule.ptr);
        !          1024:        if (cur->nat_rule.ptr != NULL)
        !          1025:                if (--cur->nat_rule.ptr->states <= 0 &&
        !          1026:                        cur->nat_rule.ptr->src_nodes <= 0)
        !          1027:                        pf_rm_rule(NULL, cur->nat_rule.ptr);
        !          1028:        if (cur->anchor.ptr != NULL)
        !          1029:                if (--cur->anchor.ptr->states <= 0)
        !          1030:                        pf_rm_rule(NULL, cur->anchor.ptr);
        !          1031:        pf_normalize_tcp_cleanup(cur);
        !          1032:        pfi_kif_unref(cur->kif, PFI_KIF_REF_STATE);
        !          1033:        TAILQ_REMOVE(&state_list, cur, entry_list);
        !          1034:        if (cur->tag)
        !          1035:                pf_tag_unref(cur->tag);
        !          1036:        pool_put(&pf_state_pl, cur);
        !          1037:        pf_status.fcounters[FCNT_STATE_REMOVALS]++;
        !          1038:        pf_status.states--;
        !          1039: }
        !          1040:
        !          1041: void
        !          1042: pf_purge_expired_states(u_int32_t maxcheck)
        !          1043: {
        !          1044:        static struct pf_state  *cur = NULL;
        !          1045:        struct pf_state         *next;
        !          1046:        int                      locked = 0;
        !          1047:
        !          1048:        while (maxcheck--) {
        !          1049:                /* wrap to start of list when we hit the end */
        !          1050:                if (cur == NULL) {
        !          1051:                        cur = TAILQ_FIRST(&state_list);
        !          1052:                        if (cur == NULL)
        !          1053:                                break;  /* list empty */
        !          1054:                }
        !          1055:
        !          1056:                /* get next state, as cur may get deleted */
        !          1057:                next = TAILQ_NEXT(cur, entry_list);
        !          1058:
        !          1059:                if (cur->timeout == PFTM_UNLINKED) {
        !          1060:                        /* free unlinked state */
        !          1061:                        if (! locked) {
        !          1062:                                rw_enter_write(&pf_consistency_lock);
        !          1063:                                locked = 1;
        !          1064:                        }
        !          1065:                        pf_free_state(cur);
        !          1066:                } else if (pf_state_expires(cur) <= time_second) {
        !          1067:                        /* unlink and free expired state */
        !          1068:                        pf_unlink_state(cur);
        !          1069:                        if (! locked) {
        !          1070:                                rw_enter_write(&pf_consistency_lock);
        !          1071:                                locked = 1;
        !          1072:                        }
        !          1073:                        pf_free_state(cur);
        !          1074:                }
        !          1075:                cur = next;
        !          1076:        }
        !          1077:
        !          1078:        if (locked)
        !          1079:                rw_exit_write(&pf_consistency_lock);
        !          1080: }
        !          1081:
        !          1082: int
        !          1083: pf_tbladdr_setup(struct pf_ruleset *rs, struct pf_addr_wrap *aw)
        !          1084: {
        !          1085:        if (aw->type != PF_ADDR_TABLE)
        !          1086:                return (0);
        !          1087:        if ((aw->p.tbl = pfr_attach_table(rs, aw->v.tblname)) == NULL)
        !          1088:                return (1);
        !          1089:        return (0);
        !          1090: }
        !          1091:
        !          1092: void
        !          1093: pf_tbladdr_remove(struct pf_addr_wrap *aw)
        !          1094: {
        !          1095:        if (aw->type != PF_ADDR_TABLE || aw->p.tbl == NULL)
        !          1096:                return;
        !          1097:        pfr_detach_table(aw->p.tbl);
        !          1098:        aw->p.tbl = NULL;
        !          1099: }
        !          1100:
        !          1101: void
        !          1102: pf_tbladdr_copyout(struct pf_addr_wrap *aw)
        !          1103: {
        !          1104:        struct pfr_ktable *kt = aw->p.tbl;
        !          1105:
        !          1106:        if (aw->type != PF_ADDR_TABLE || kt == NULL)
        !          1107:                return;
        !          1108:        if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE) && kt->pfrkt_root != NULL)
        !          1109:                kt = kt->pfrkt_root;
        !          1110:        aw->p.tbl = NULL;
        !          1111:        aw->p.tblcnt = (kt->pfrkt_flags & PFR_TFLAG_ACTIVE) ?
        !          1112:                kt->pfrkt_cnt : -1;
        !          1113: }
        !          1114:
        !          1115: void
        !          1116: pf_print_host(struct pf_addr *addr, u_int16_t p, sa_family_t af)
        !          1117: {
        !          1118:        switch (af) {
        !          1119: #ifdef INET
        !          1120:        case AF_INET: {
        !          1121:                u_int32_t a = ntohl(addr->addr32[0]);
        !          1122:                printf("%u.%u.%u.%u", (a>>24)&255, (a>>16)&255,
        !          1123:                    (a>>8)&255, a&255);
        !          1124:                if (p) {
        !          1125:                        p = ntohs(p);
        !          1126:                        printf(":%u", p);
        !          1127:                }
        !          1128:                break;
        !          1129:        }
        !          1130: #endif /* INET */
        !          1131: #ifdef INET6
        !          1132:        case AF_INET6: {
        !          1133:                u_int16_t b;
        !          1134:                u_int8_t i, curstart = 255, curend = 0,
        !          1135:                    maxstart = 0, maxend = 0;
        !          1136:                for (i = 0; i < 8; i++) {
        !          1137:                        if (!addr->addr16[i]) {
        !          1138:                                if (curstart == 255)
        !          1139:                                        curstart = i;
        !          1140:                                else
        !          1141:                                        curend = i;
        !          1142:                        } else {
        !          1143:                                if (curstart) {
        !          1144:                                        if ((curend - curstart) >
        !          1145:                                            (maxend - maxstart)) {
        !          1146:                                                maxstart = curstart;
        !          1147:                                                maxend = curend;
        !          1148:                                                curstart = 255;
        !          1149:                                        }
        !          1150:                                }
        !          1151:                        }
        !          1152:                }
        !          1153:                for (i = 0; i < 8; i++) {
        !          1154:                        if (i >= maxstart && i <= maxend) {
        !          1155:                                if (maxend != 7) {
        !          1156:                                        if (i == maxstart)
        !          1157:                                                printf(":");
        !          1158:                                } else {
        !          1159:                                        if (i == maxend)
        !          1160:                                                printf(":");
        !          1161:                                }
        !          1162:                        } else {
        !          1163:                                b = ntohs(addr->addr16[i]);
        !          1164:                                printf("%x", b);
        !          1165:                                if (i < 7)
        !          1166:                                        printf(":");
        !          1167:                        }
        !          1168:                }
        !          1169:                if (p) {
        !          1170:                        p = ntohs(p);
        !          1171:                        printf("[%u]", p);
        !          1172:                }
        !          1173:                break;
        !          1174:        }
        !          1175: #endif /* INET6 */
        !          1176:        }
        !          1177: }
        !          1178:
        !          1179: void
        !          1180: pf_print_state(struct pf_state *s)
        !          1181: {
        !          1182:        struct pf_state_key *sk = s->state_key;
        !          1183:        switch (sk->proto) {
        !          1184:        case IPPROTO_TCP:
        !          1185:                printf("TCP ");
        !          1186:                break;
        !          1187:        case IPPROTO_UDP:
        !          1188:                printf("UDP ");
        !          1189:                break;
        !          1190:        case IPPROTO_ICMP:
        !          1191:                printf("ICMP ");
        !          1192:                break;
        !          1193:        case IPPROTO_ICMPV6:
        !          1194:                printf("ICMPV6 ");
        !          1195:                break;
        !          1196:        default:
        !          1197:                printf("%u ", sk->proto);
        !          1198:                break;
        !          1199:        }
        !          1200:        pf_print_host(&sk->lan.addr, sk->lan.port, sk->af);
        !          1201:        printf(" ");
        !          1202:        pf_print_host(&sk->gwy.addr, sk->gwy.port, sk->af);
        !          1203:        printf(" ");
        !          1204:        pf_print_host(&sk->ext.addr, sk->ext.port, sk->af);
        !          1205:        printf(" [lo=%u high=%u win=%u modulator=%u", s->src.seqlo,
        !          1206:            s->src.seqhi, s->src.max_win, s->src.seqdiff);
        !          1207:        if (s->src.wscale && s->dst.wscale)
        !          1208:                printf(" wscale=%u", s->src.wscale & PF_WSCALE_MASK);
        !          1209:        printf("]");
        !          1210:        printf(" [lo=%u high=%u win=%u modulator=%u", s->dst.seqlo,
        !          1211:            s->dst.seqhi, s->dst.max_win, s->dst.seqdiff);
        !          1212:        if (s->src.wscale && s->dst.wscale)
        !          1213:                printf(" wscale=%u", s->dst.wscale & PF_WSCALE_MASK);
        !          1214:        printf("]");
        !          1215:        printf(" %u:%u", s->src.state, s->dst.state);
        !          1216: }
        !          1217:
        !          1218: void
        !          1219: pf_print_flags(u_int8_t f)
        !          1220: {
        !          1221:        if (f)
        !          1222:                printf(" ");
        !          1223:        if (f & TH_FIN)
        !          1224:                printf("F");
        !          1225:        if (f & TH_SYN)
        !          1226:                printf("S");
        !          1227:        if (f & TH_RST)
        !          1228:                printf("R");
        !          1229:        if (f & TH_PUSH)
        !          1230:                printf("P");
        !          1231:        if (f & TH_ACK)
        !          1232:                printf("A");
        !          1233:        if (f & TH_URG)
        !          1234:                printf("U");
        !          1235:        if (f & TH_ECE)
        !          1236:                printf("E");
        !          1237:        if (f & TH_CWR)
        !          1238:                printf("W");
        !          1239: }
        !          1240:
        !          1241: #define        PF_SET_SKIP_STEPS(i)                                    \
        !          1242:        do {                                                    \
        !          1243:                while (head[i] != cur) {                        \
        !          1244:                        head[i]->skip[i].ptr = cur;             \
        !          1245:                        head[i] = TAILQ_NEXT(head[i], entries); \
        !          1246:                }                                               \
        !          1247:        } while (0)
        !          1248:
        !          1249: void
        !          1250: pf_calc_skip_steps(struct pf_rulequeue *rules)
        !          1251: {
        !          1252:        struct pf_rule *cur, *prev, *head[PF_SKIP_COUNT];
        !          1253:        int i;
        !          1254:
        !          1255:        cur = TAILQ_FIRST(rules);
        !          1256:        prev = cur;
        !          1257:        for (i = 0; i < PF_SKIP_COUNT; ++i)
        !          1258:                head[i] = cur;
        !          1259:        while (cur != NULL) {
        !          1260:
        !          1261:                if (cur->kif != prev->kif || cur->ifnot != prev->ifnot)
        !          1262:                        PF_SET_SKIP_STEPS(PF_SKIP_IFP);
        !          1263:                if (cur->direction != prev->direction)
        !          1264:                        PF_SET_SKIP_STEPS(PF_SKIP_DIR);
        !          1265:                if (cur->af != prev->af)
        !          1266:                        PF_SET_SKIP_STEPS(PF_SKIP_AF);
        !          1267:                if (cur->proto != prev->proto)
        !          1268:                        PF_SET_SKIP_STEPS(PF_SKIP_PROTO);
        !          1269:                if (cur->src.neg != prev->src.neg ||
        !          1270:                    pf_addr_wrap_neq(&cur->src.addr, &prev->src.addr))
        !          1271:                        PF_SET_SKIP_STEPS(PF_SKIP_SRC_ADDR);
        !          1272:                if (cur->src.port[0] != prev->src.port[0] ||
        !          1273:                    cur->src.port[1] != prev->src.port[1] ||
        !          1274:                    cur->src.port_op != prev->src.port_op)
        !          1275:                        PF_SET_SKIP_STEPS(PF_SKIP_SRC_PORT);
        !          1276:                if (cur->dst.neg != prev->dst.neg ||
        !          1277:                    pf_addr_wrap_neq(&cur->dst.addr, &prev->dst.addr))
        !          1278:                        PF_SET_SKIP_STEPS(PF_SKIP_DST_ADDR);
        !          1279:                if (cur->dst.port[0] != prev->dst.port[0] ||
        !          1280:                    cur->dst.port[1] != prev->dst.port[1] ||
        !          1281:                    cur->dst.port_op != prev->dst.port_op)
        !          1282:                        PF_SET_SKIP_STEPS(PF_SKIP_DST_PORT);
        !          1283:
        !          1284:                prev = cur;
        !          1285:                cur = TAILQ_NEXT(cur, entries);
        !          1286:        }
        !          1287:        for (i = 0; i < PF_SKIP_COUNT; ++i)
        !          1288:                PF_SET_SKIP_STEPS(i);
        !          1289: }
        !          1290:
        !          1291: int
        !          1292: pf_addr_wrap_neq(struct pf_addr_wrap *aw1, struct pf_addr_wrap *aw2)
        !          1293: {
        !          1294:        if (aw1->type != aw2->type)
        !          1295:                return (1);
        !          1296:        switch (aw1->type) {
        !          1297:        case PF_ADDR_ADDRMASK:
        !          1298:                if (PF_ANEQ(&aw1->v.a.addr, &aw2->v.a.addr, 0))
        !          1299:                        return (1);
        !          1300:                if (PF_ANEQ(&aw1->v.a.mask, &aw2->v.a.mask, 0))
        !          1301:                        return (1);
        !          1302:                return (0);
        !          1303:        case PF_ADDR_DYNIFTL:
        !          1304:                return (aw1->p.dyn->pfid_kt != aw2->p.dyn->pfid_kt);
        !          1305:        case PF_ADDR_NOROUTE:
        !          1306:        case PF_ADDR_URPFFAILED:
        !          1307:                return (0);
        !          1308:        case PF_ADDR_TABLE:
        !          1309:                return (aw1->p.tbl != aw2->p.tbl);
        !          1310:        case PF_ADDR_RTLABEL:
        !          1311:                return (aw1->v.rtlabel != aw2->v.rtlabel);
        !          1312:        default:
        !          1313:                printf("invalid address type: %d\n", aw1->type);
        !          1314:                return (1);
        !          1315:        }
        !          1316: }
        !          1317:
        !          1318: u_int16_t
        !          1319: pf_cksum_fixup(u_int16_t cksum, u_int16_t old, u_int16_t new, u_int8_t udp)
        !          1320: {
        !          1321:        u_int32_t       l;
        !          1322:
        !          1323:        if (udp && !cksum)
        !          1324:                return (0x0000);
        !          1325:        l = cksum + old - new;
        !          1326:        l = (l >> 16) + (l & 65535);
        !          1327:        l = l & 65535;
        !          1328:        if (udp && !l)
        !          1329:                return (0xFFFF);
        !          1330:        return (l);
        !          1331: }
        !          1332:
        !          1333: void
        !          1334: pf_change_ap(struct pf_addr *a, u_int16_t *p, u_int16_t *ic, u_int16_t *pc,
        !          1335:     struct pf_addr *an, u_int16_t pn, u_int8_t u, sa_family_t af)
        !          1336: {
        !          1337:        struct pf_addr  ao;
        !          1338:        u_int16_t       po = *p;
        !          1339:
        !          1340:        PF_ACPY(&ao, a, af);
        !          1341:        PF_ACPY(a, an, af);
        !          1342:
        !          1343:        *p = pn;
        !          1344:
        !          1345:        switch (af) {
        !          1346: #ifdef INET
        !          1347:        case AF_INET:
        !          1348:                *ic = pf_cksum_fixup(pf_cksum_fixup(*ic,
        !          1349:                    ao.addr16[0], an->addr16[0], 0),
        !          1350:                    ao.addr16[1], an->addr16[1], 0);
        !          1351:                *p = pn;
        !          1352:                *pc = pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(*pc,
        !          1353:                    ao.addr16[0], an->addr16[0], u),
        !          1354:                    ao.addr16[1], an->addr16[1], u),
        !          1355:                    po, pn, u);
        !          1356:                break;
        !          1357: #endif /* INET */
        !          1358: #ifdef INET6
        !          1359:        case AF_INET6:
        !          1360:                *pc = pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
        !          1361:                    pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
        !          1362:                    pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(*pc,
        !          1363:                    ao.addr16[0], an->addr16[0], u),
        !          1364:                    ao.addr16[1], an->addr16[1], u),
        !          1365:                    ao.addr16[2], an->addr16[2], u),
        !          1366:                    ao.addr16[3], an->addr16[3], u),
        !          1367:                    ao.addr16[4], an->addr16[4], u),
        !          1368:                    ao.addr16[5], an->addr16[5], u),
        !          1369:                    ao.addr16[6], an->addr16[6], u),
        !          1370:                    ao.addr16[7], an->addr16[7], u),
        !          1371:                    po, pn, u);
        !          1372:                break;
        !          1373: #endif /* INET6 */
        !          1374:        }
        !          1375: }
        !          1376:
        !          1377:
        !          1378: /* Changes a u_int32_t.  Uses a void * so there are no align restrictions */
        !          1379: void
        !          1380: pf_change_a(void *a, u_int16_t *c, u_int32_t an, u_int8_t u)
        !          1381: {
        !          1382:        u_int32_t       ao;
        !          1383:
        !          1384:        memcpy(&ao, a, sizeof(ao));
        !          1385:        memcpy(a, &an, sizeof(u_int32_t));
        !          1386:        *c = pf_cksum_fixup(pf_cksum_fixup(*c, ao / 65536, an / 65536, u),
        !          1387:            ao % 65536, an % 65536, u);
        !          1388: }
        !          1389:
        !          1390: #ifdef INET6
        !          1391: void
        !          1392: pf_change_a6(struct pf_addr *a, u_int16_t *c, struct pf_addr *an, u_int8_t u)
        !          1393: {
        !          1394:        struct pf_addr  ao;
        !          1395:
        !          1396:        PF_ACPY(&ao, a, AF_INET6);
        !          1397:        PF_ACPY(a, an, AF_INET6);
        !          1398:
        !          1399:        *c = pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
        !          1400:            pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
        !          1401:            pf_cksum_fixup(pf_cksum_fixup(*c,
        !          1402:            ao.addr16[0], an->addr16[0], u),
        !          1403:            ao.addr16[1], an->addr16[1], u),
        !          1404:            ao.addr16[2], an->addr16[2], u),
        !          1405:            ao.addr16[3], an->addr16[3], u),
        !          1406:            ao.addr16[4], an->addr16[4], u),
        !          1407:            ao.addr16[5], an->addr16[5], u),
        !          1408:            ao.addr16[6], an->addr16[6], u),
        !          1409:            ao.addr16[7], an->addr16[7], u);
        !          1410: }
        !          1411: #endif /* INET6 */
        !          1412:
        !          1413: void
        !          1414: pf_change_icmp(struct pf_addr *ia, u_int16_t *ip, struct pf_addr *oa,
        !          1415:     struct pf_addr *na, u_int16_t np, u_int16_t *pc, u_int16_t *h2c,
        !          1416:     u_int16_t *ic, u_int16_t *hc, u_int8_t u, sa_family_t af)
        !          1417: {
        !          1418:        struct pf_addr  oia, ooa;
        !          1419:
        !          1420:        PF_ACPY(&oia, ia, af);
        !          1421:        PF_ACPY(&ooa, oa, af);
        !          1422:
        !          1423:        /* Change inner protocol port, fix inner protocol checksum. */
        !          1424:        if (ip != NULL) {
        !          1425:                u_int16_t       oip = *ip;
        !          1426:                u_int32_t       opc;
        !          1427:
        !          1428:                if (pc != NULL)
        !          1429:                        opc = *pc;
        !          1430:                *ip = np;
        !          1431:                if (pc != NULL)
        !          1432:                        *pc = pf_cksum_fixup(*pc, oip, *ip, u);
        !          1433:                *ic = pf_cksum_fixup(*ic, oip, *ip, 0);
        !          1434:                if (pc != NULL)
        !          1435:                        *ic = pf_cksum_fixup(*ic, opc, *pc, 0);
        !          1436:        }
        !          1437:        /* Change inner ip address, fix inner ip and icmp checksums. */
        !          1438:        PF_ACPY(ia, na, af);
        !          1439:        switch (af) {
        !          1440: #ifdef INET
        !          1441:        case AF_INET: {
        !          1442:                u_int32_t        oh2c = *h2c;
        !          1443:
        !          1444:                *h2c = pf_cksum_fixup(pf_cksum_fixup(*h2c,
        !          1445:                    oia.addr16[0], ia->addr16[0], 0),
        !          1446:                    oia.addr16[1], ia->addr16[1], 0);
        !          1447:                *ic = pf_cksum_fixup(pf_cksum_fixup(*ic,
        !          1448:                    oia.addr16[0], ia->addr16[0], 0),
        !          1449:                    oia.addr16[1], ia->addr16[1], 0);
        !          1450:                *ic = pf_cksum_fixup(*ic, oh2c, *h2c, 0);
        !          1451:                break;
        !          1452:        }
        !          1453: #endif /* INET */
        !          1454: #ifdef INET6
        !          1455:        case AF_INET6:
        !          1456:                *ic = pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
        !          1457:                    pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
        !          1458:                    pf_cksum_fixup(pf_cksum_fixup(*ic,
        !          1459:                    oia.addr16[0], ia->addr16[0], u),
        !          1460:                    oia.addr16[1], ia->addr16[1], u),
        !          1461:                    oia.addr16[2], ia->addr16[2], u),
        !          1462:                    oia.addr16[3], ia->addr16[3], u),
        !          1463:                    oia.addr16[4], ia->addr16[4], u),
        !          1464:                    oia.addr16[5], ia->addr16[5], u),
        !          1465:                    oia.addr16[6], ia->addr16[6], u),
        !          1466:                    oia.addr16[7], ia->addr16[7], u);
        !          1467:                break;
        !          1468: #endif /* INET6 */
        !          1469:        }
        !          1470:        /* Change outer ip address, fix outer ip or icmpv6 checksum. */
        !          1471:        PF_ACPY(oa, na, af);
        !          1472:        switch (af) {
        !          1473: #ifdef INET
        !          1474:        case AF_INET:
        !          1475:                *hc = pf_cksum_fixup(pf_cksum_fixup(*hc,
        !          1476:                    ooa.addr16[0], oa->addr16[0], 0),
        !          1477:                    ooa.addr16[1], oa->addr16[1], 0);
        !          1478:                break;
        !          1479: #endif /* INET */
        !          1480: #ifdef INET6
        !          1481:        case AF_INET6:
        !          1482:                *ic = pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
        !          1483:                    pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
        !          1484:                    pf_cksum_fixup(pf_cksum_fixup(*ic,
        !          1485:                    ooa.addr16[0], oa->addr16[0], u),
        !          1486:                    ooa.addr16[1], oa->addr16[1], u),
        !          1487:                    ooa.addr16[2], oa->addr16[2], u),
        !          1488:                    ooa.addr16[3], oa->addr16[3], u),
        !          1489:                    ooa.addr16[4], oa->addr16[4], u),
        !          1490:                    ooa.addr16[5], oa->addr16[5], u),
        !          1491:                    ooa.addr16[6], oa->addr16[6], u),
        !          1492:                    ooa.addr16[7], oa->addr16[7], u);
        !          1493:                break;
        !          1494: #endif /* INET6 */
        !          1495:        }
        !          1496: }
        !          1497:
        !          1498:
        !          1499: /*
        !          1500:  * Need to modulate the sequence numbers in the TCP SACK option
        !          1501:  * (credits to Krzysztof Pfaff for report and patch)
        !          1502:  */
        !          1503: int
        !          1504: pf_modulate_sack(struct mbuf *m, int off, struct pf_pdesc *pd,
        !          1505:     struct tcphdr *th, struct pf_state_peer *dst)
        !          1506: {
        !          1507:        int hlen = (th->th_off << 2) - sizeof(*th), thoptlen = hlen;
        !          1508:        u_int8_t opts[MAX_TCPOPTLEN], *opt = opts;
        !          1509:        int copyback = 0, i, olen;
        !          1510:        struct sackblk sack;
        !          1511:
        !          1512: #define TCPOLEN_SACKLEN        (TCPOLEN_SACK + 2)
        !          1513:        if (hlen < TCPOLEN_SACKLEN ||
        !          1514:            !pf_pull_hdr(m, off + sizeof(*th), opts, hlen, NULL, NULL, pd->af))
        !          1515:                return 0;
        !          1516:
        !          1517:        while (hlen >= TCPOLEN_SACKLEN) {
        !          1518:                olen = opt[1];
        !          1519:                switch (*opt) {
        !          1520:                case TCPOPT_EOL:        /* FALLTHROUGH */
        !          1521:                case TCPOPT_NOP:
        !          1522:                        opt++;
        !          1523:                        hlen--;
        !          1524:                        break;
        !          1525:                case TCPOPT_SACK:
        !          1526:                        if (olen > hlen)
        !          1527:                                olen = hlen;
        !          1528:                        if (olen >= TCPOLEN_SACKLEN) {
        !          1529:                                for (i = 2; i + TCPOLEN_SACK <= olen;
        !          1530:                                    i += TCPOLEN_SACK) {
        !          1531:                                        memcpy(&sack, &opt[i], sizeof(sack));
        !          1532:                                        pf_change_a(&sack.start, &th->th_sum,
        !          1533:                                            htonl(ntohl(sack.start) -
        !          1534:                                            dst->seqdiff), 0);
        !          1535:                                        pf_change_a(&sack.end, &th->th_sum,
        !          1536:                                            htonl(ntohl(sack.end) -
        !          1537:                                            dst->seqdiff), 0);
        !          1538:                                        memcpy(&opt[i], &sack, sizeof(sack));
        !          1539:                                }
        !          1540:                                copyback = 1;
        !          1541:                        }
        !          1542:                        /* FALLTHROUGH */
        !          1543:                default:
        !          1544:                        if (olen < 2)
        !          1545:                                olen = 2;
        !          1546:                        hlen -= olen;
        !          1547:                        opt += olen;
        !          1548:                }
        !          1549:        }
        !          1550:
        !          1551:        if (copyback)
        !          1552:                m_copyback(m, off + sizeof(*th), thoptlen, opts);
        !          1553:        return (copyback);
        !          1554: }
        !          1555:
        !          1556: void
        !          1557: pf_send_tcp(const struct pf_rule *r, sa_family_t af,
        !          1558:     const struct pf_addr *saddr, const struct pf_addr *daddr,
        !          1559:     u_int16_t sport, u_int16_t dport, u_int32_t seq, u_int32_t ack,
        !          1560:     u_int8_t flags, u_int16_t win, u_int16_t mss, u_int8_t ttl, int tag,
        !          1561:     u_int16_t rtag, struct ether_header *eh, struct ifnet *ifp)
        !          1562: {
        !          1563:        struct mbuf     *m;
        !          1564:        int              len, tlen;
        !          1565: #ifdef INET
        !          1566:        struct ip       *h;
        !          1567: #endif /* INET */
        !          1568: #ifdef INET6
        !          1569:        struct ip6_hdr  *h6;
        !          1570: #endif /* INET6 */
        !          1571:        struct tcphdr   *th;
        !          1572:        char            *opt;
        !          1573:
        !          1574:        /* maximum segment size tcp option */
        !          1575:        tlen = sizeof(struct tcphdr);
        !          1576:        if (mss)
        !          1577:                tlen += 4;
        !          1578:
        !          1579:        switch (af) {
        !          1580: #ifdef INET
        !          1581:        case AF_INET:
        !          1582:                len = sizeof(struct ip) + tlen;
        !          1583:                break;
        !          1584: #endif /* INET */
        !          1585: #ifdef INET6
        !          1586:        case AF_INET6:
        !          1587:                len = sizeof(struct ip6_hdr) + tlen;
        !          1588:                break;
        !          1589: #endif /* INET6 */
        !          1590:        }
        !          1591:
        !          1592:        /* create outgoing mbuf */
        !          1593:        m = m_gethdr(M_DONTWAIT, MT_HEADER);
        !          1594:        if (m == NULL)
        !          1595:                return;
        !          1596:        if (tag)
        !          1597:                m->m_pkthdr.pf.flags |= PF_TAG_GENERATED;
        !          1598:        m->m_pkthdr.pf.tag = rtag;
        !          1599:
        !          1600:        if (r != NULL && r->rtableid >= 0)
        !          1601:                m->m_pkthdr.pf.rtableid = m->m_pkthdr.pf.rtableid;
        !          1602:
        !          1603: #ifdef ALTQ
        !          1604:        if (r != NULL && r->qid) {
        !          1605:                m->m_pkthdr.pf.qid = r->qid;
        !          1606:                /* add hints for ecn */
        !          1607:                m->m_pkthdr.pf.hdr = mtod(m, struct ip *);
        !          1608:        }
        !          1609: #endif /* ALTQ */
        !          1610:        m->m_data += max_linkhdr;
        !          1611:        m->m_pkthdr.len = m->m_len = len;
        !          1612:        m->m_pkthdr.rcvif = NULL;
        !          1613:        bzero(m->m_data, len);
        !          1614:        switch (af) {
        !          1615: #ifdef INET
        !          1616:        case AF_INET:
        !          1617:                h = mtod(m, struct ip *);
        !          1618:
        !          1619:                /* IP header fields included in the TCP checksum */
        !          1620:                h->ip_p = IPPROTO_TCP;
        !          1621:                h->ip_len = htons(tlen);
        !          1622:                h->ip_src.s_addr = saddr->v4.s_addr;
        !          1623:                h->ip_dst.s_addr = daddr->v4.s_addr;
        !          1624:
        !          1625:                th = (struct tcphdr *)((caddr_t)h + sizeof(struct ip));
        !          1626:                break;
        !          1627: #endif /* INET */
        !          1628: #ifdef INET6
        !          1629:        case AF_INET6:
        !          1630:                h6 = mtod(m, struct ip6_hdr *);
        !          1631:
        !          1632:                /* IP header fields included in the TCP checksum */
        !          1633:                h6->ip6_nxt = IPPROTO_TCP;
        !          1634:                h6->ip6_plen = htons(tlen);
        !          1635:                memcpy(&h6->ip6_src, &saddr->v6, sizeof(struct in6_addr));
        !          1636:                memcpy(&h6->ip6_dst, &daddr->v6, sizeof(struct in6_addr));
        !          1637:
        !          1638:                th = (struct tcphdr *)((caddr_t)h6 + sizeof(struct ip6_hdr));
        !          1639:                break;
        !          1640: #endif /* INET6 */
        !          1641:        }
        !          1642:
        !          1643:        /* TCP header */
        !          1644:        th->th_sport = sport;
        !          1645:        th->th_dport = dport;
        !          1646:        th->th_seq = htonl(seq);
        !          1647:        th->th_ack = htonl(ack);
        !          1648:        th->th_off = tlen >> 2;
        !          1649:        th->th_flags = flags;
        !          1650:        th->th_win = htons(win);
        !          1651:
        !          1652:        if (mss) {
        !          1653:                opt = (char *)(th + 1);
        !          1654:                opt[0] = TCPOPT_MAXSEG;
        !          1655:                opt[1] = 4;
        !          1656:                HTONS(mss);
        !          1657:                bcopy((caddr_t)&mss, (caddr_t)(opt + 2), 2);
        !          1658:        }
        !          1659:
        !          1660:        switch (af) {
        !          1661: #ifdef INET
        !          1662:        case AF_INET:
        !          1663:                /* TCP checksum */
        !          1664:                th->th_sum = in_cksum(m, len);
        !          1665:
        !          1666:                /* Finish the IP header */
        !          1667:                h->ip_v = 4;
        !          1668:                h->ip_hl = sizeof(*h) >> 2;
        !          1669:                h->ip_tos = IPTOS_LOWDELAY;
        !          1670:                h->ip_len = htons(len);
        !          1671:                h->ip_off = htons(ip_mtudisc ? IP_DF : 0);
        !          1672:                h->ip_ttl = ttl ? ttl : ip_defttl;
        !          1673:                h->ip_sum = 0;
        !          1674:                if (eh == NULL) {
        !          1675:                        ip_output(m, (void *)NULL, (void *)NULL, 0,
        !          1676:                            (void *)NULL, (void *)NULL);
        !          1677:                } else {
        !          1678:                        struct route             ro;
        !          1679:                        struct rtentry           rt;
        !          1680:                        struct ether_header     *e = (void *)ro.ro_dst.sa_data;
        !          1681:
        !          1682:                        if (ifp == NULL) {
        !          1683:                                m_freem(m);
        !          1684:                                return;
        !          1685:                        }
        !          1686:                        rt.rt_ifp = ifp;
        !          1687:                        ro.ro_rt = &rt;
        !          1688:                        ro.ro_dst.sa_len = sizeof(ro.ro_dst);
        !          1689:                        ro.ro_dst.sa_family = pseudo_AF_HDRCMPLT;
        !          1690:                        bcopy(eh->ether_dhost, e->ether_shost, ETHER_ADDR_LEN);
        !          1691:                        bcopy(eh->ether_shost, e->ether_dhost, ETHER_ADDR_LEN);
        !          1692:                        e->ether_type = eh->ether_type;
        !          1693:                        ip_output(m, (void *)NULL, &ro, IP_ROUTETOETHER,
        !          1694:                            (void *)NULL, (void *)NULL);
        !          1695:                }
        !          1696:                break;
        !          1697: #endif /* INET */
        !          1698: #ifdef INET6
        !          1699:        case AF_INET6:
        !          1700:                /* TCP checksum */
        !          1701:                th->th_sum = in6_cksum(m, IPPROTO_TCP,
        !          1702:                    sizeof(struct ip6_hdr), tlen);
        !          1703:
        !          1704:                h6->ip6_vfc |= IPV6_VERSION;
        !          1705:                h6->ip6_hlim = IPV6_DEFHLIM;
        !          1706:
        !          1707:                ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL);
        !          1708:                break;
        !          1709: #endif /* INET6 */
        !          1710:        }
        !          1711: }
        !          1712:
        !          1713: void
        !          1714: pf_send_icmp(struct mbuf *m, u_int8_t type, u_int8_t code, sa_family_t af,
        !          1715:     struct pf_rule *r)
        !          1716: {
        !          1717:        struct mbuf     *m0;
        !          1718:
        !          1719:        m0 = m_copy(m, 0, M_COPYALL);
        !          1720:        m0->m_pkthdr.pf.flags |= PF_TAG_GENERATED;
        !          1721:
        !          1722:        if (r->rtableid >= 0)
        !          1723:                m0->m_pkthdr.pf.rtableid = r->rtableid;
        !          1724:
        !          1725: #ifdef ALTQ
        !          1726:        if (r->qid) {
        !          1727:                m0->m_pkthdr.pf.qid = r->qid;
        !          1728:                /* add hints for ecn */
        !          1729:                m0->m_pkthdr.pf.hdr = mtod(m0, struct ip *);
        !          1730:        }
        !          1731: #endif /* ALTQ */
        !          1732:
        !          1733:        switch (af) {
        !          1734: #ifdef INET
        !          1735:        case AF_INET:
        !          1736:                icmp_error(m0, type, code, 0, 0);
        !          1737:                break;
        !          1738: #endif /* INET */
        !          1739: #ifdef INET6
        !          1740:        case AF_INET6:
        !          1741:                icmp6_error(m0, type, code, 0);
        !          1742:                break;
        !          1743: #endif /* INET6 */
        !          1744:        }
        !          1745: }
        !          1746:
        !          1747: /*
        !          1748:  * Return 1 if the addresses a and b match (with mask m), otherwise return 0.
        !          1749:  * If n is 0, they match if they are equal. If n is != 0, they match if they
        !          1750:  * are different.
        !          1751:  */
        !          1752: int
        !          1753: pf_match_addr(u_int8_t n, struct pf_addr *a, struct pf_addr *m,
        !          1754:     struct pf_addr *b, sa_family_t af)
        !          1755: {
        !          1756:        int     match = 0;
        !          1757:
        !          1758:        switch (af) {
        !          1759: #ifdef INET
        !          1760:        case AF_INET:
        !          1761:                if ((a->addr32[0] & m->addr32[0]) ==
        !          1762:                    (b->addr32[0] & m->addr32[0]))
        !          1763:                        match++;
        !          1764:                break;
        !          1765: #endif /* INET */
        !          1766: #ifdef INET6
        !          1767:        case AF_INET6:
        !          1768:                if (((a->addr32[0] & m->addr32[0]) ==
        !          1769:                     (b->addr32[0] & m->addr32[0])) &&
        !          1770:                    ((a->addr32[1] & m->addr32[1]) ==
        !          1771:                     (b->addr32[1] & m->addr32[1])) &&
        !          1772:                    ((a->addr32[2] & m->addr32[2]) ==
        !          1773:                     (b->addr32[2] & m->addr32[2])) &&
        !          1774:                    ((a->addr32[3] & m->addr32[3]) ==
        !          1775:                     (b->addr32[3] & m->addr32[3])))
        !          1776:                        match++;
        !          1777:                break;
        !          1778: #endif /* INET6 */
        !          1779:        }
        !          1780:        if (match) {
        !          1781:                if (n)
        !          1782:                        return (0);
        !          1783:                else
        !          1784:                        return (1);
        !          1785:        } else {
        !          1786:                if (n)
        !          1787:                        return (1);
        !          1788:                else
        !          1789:                        return (0);
        !          1790:        }
        !          1791: }
        !          1792:
        !          1793: int
        !          1794: pf_match(u_int8_t op, u_int32_t a1, u_int32_t a2, u_int32_t p)
        !          1795: {
        !          1796:        switch (op) {
        !          1797:        case PF_OP_IRG:
        !          1798:                return ((p > a1) && (p < a2));
        !          1799:        case PF_OP_XRG:
        !          1800:                return ((p < a1) || (p > a2));
        !          1801:        case PF_OP_RRG:
        !          1802:                return ((p >= a1) && (p <= a2));
        !          1803:        case PF_OP_EQ:
        !          1804:                return (p == a1);
        !          1805:        case PF_OP_NE:
        !          1806:                return (p != a1);
        !          1807:        case PF_OP_LT:
        !          1808:                return (p < a1);
        !          1809:        case PF_OP_LE:
        !          1810:                return (p <= a1);
        !          1811:        case PF_OP_GT:
        !          1812:                return (p > a1);
        !          1813:        case PF_OP_GE:
        !          1814:                return (p >= a1);
        !          1815:        }
        !          1816:        return (0); /* never reached */
        !          1817: }
        !          1818:
        !          1819: int
        !          1820: pf_match_port(u_int8_t op, u_int16_t a1, u_int16_t a2, u_int16_t p)
        !          1821: {
        !          1822:        NTOHS(a1);
        !          1823:        NTOHS(a2);
        !          1824:        NTOHS(p);
        !          1825:        return (pf_match(op, a1, a2, p));
        !          1826: }
        !          1827:
        !          1828: int
        !          1829: pf_match_uid(u_int8_t op, uid_t a1, uid_t a2, uid_t u)
        !          1830: {
        !          1831:        if (u == UID_MAX && op != PF_OP_EQ && op != PF_OP_NE)
        !          1832:                return (0);
        !          1833:        return (pf_match(op, a1, a2, u));
        !          1834: }
        !          1835:
        !          1836: int
        !          1837: pf_match_gid(u_int8_t op, gid_t a1, gid_t a2, gid_t g)
        !          1838: {
        !          1839:        if (g == GID_MAX && op != PF_OP_EQ && op != PF_OP_NE)
        !          1840:                return (0);
        !          1841:        return (pf_match(op, a1, a2, g));
        !          1842: }
        !          1843:
        !          1844: int
        !          1845: pf_match_tag(struct mbuf *m, struct pf_rule *r, int *tag)
        !          1846: {
        !          1847:        if (*tag == -1)
        !          1848:                *tag = m->m_pkthdr.pf.tag;
        !          1849:
        !          1850:        return ((!r->match_tag_not && r->match_tag == *tag) ||
        !          1851:            (r->match_tag_not && r->match_tag != *tag));
        !          1852: }
        !          1853:
        !          1854: int
        !          1855: pf_tag_packet(struct mbuf *m, int tag, int rtableid)
        !          1856: {
        !          1857:        if (tag <= 0 && rtableid < 0)
        !          1858:                return (0);
        !          1859:
        !          1860:        if (tag > 0)
        !          1861:                m->m_pkthdr.pf.tag = tag;
        !          1862:        if (rtableid >= 0)
        !          1863:                m->m_pkthdr.pf.rtableid = rtableid;
        !          1864:
        !          1865:        return (0);
        !          1866: }
        !          1867:
        !          1868: void
        !          1869: pf_step_into_anchor(int *depth, struct pf_ruleset **rs, int n,
        !          1870:     struct pf_rule **r, struct pf_rule **a,  int *match)
        !          1871: {
        !          1872:        struct pf_anchor_stackframe     *f;
        !          1873:
        !          1874:        (*r)->anchor->match = 0;
        !          1875:        if (match)
        !          1876:                *match = 0;
        !          1877:        if (*depth >= sizeof(pf_anchor_stack) /
        !          1878:            sizeof(pf_anchor_stack[0])) {
        !          1879:                printf("pf_step_into_anchor: stack overflow\n");
        !          1880:                *r = TAILQ_NEXT(*r, entries);
        !          1881:                return;
        !          1882:        } else if (*depth == 0 && a != NULL)
        !          1883:                *a = *r;
        !          1884:        f = pf_anchor_stack + (*depth)++;
        !          1885:        f->rs = *rs;
        !          1886:        f->r = *r;
        !          1887:        if ((*r)->anchor_wildcard) {
        !          1888:                f->parent = &(*r)->anchor->children;
        !          1889:                if ((f->child = RB_MIN(pf_anchor_node, f->parent)) ==
        !          1890:                    NULL) {
        !          1891:                        *r = NULL;
        !          1892:                        return;
        !          1893:                }
        !          1894:                *rs = &f->child->ruleset;
        !          1895:        } else {
        !          1896:                f->parent = NULL;
        !          1897:                f->child = NULL;
        !          1898:                *rs = &(*r)->anchor->ruleset;
        !          1899:        }
        !          1900:        *r = TAILQ_FIRST((*rs)->rules[n].active.ptr);
        !          1901: }
        !          1902:
        !          1903: int
        !          1904: pf_step_out_of_anchor(int *depth, struct pf_ruleset **rs, int n,
        !          1905:     struct pf_rule **r, struct pf_rule **a, int *match)
        !          1906: {
        !          1907:        struct pf_anchor_stackframe     *f;
        !          1908:        int quick = 0;
        !          1909:
        !          1910:        do {
        !          1911:                if (*depth <= 0)
        !          1912:                        break;
        !          1913:                f = pf_anchor_stack + *depth - 1;
        !          1914:                if (f->parent != NULL && f->child != NULL) {
        !          1915:                        if (f->child->match ||
        !          1916:                            (match != NULL && *match)) {
        !          1917:                                f->r->anchor->match = 1;
        !          1918:                                *match = 0;
        !          1919:                        }
        !          1920:                        f->child = RB_NEXT(pf_anchor_node, f->parent, f->child);
        !          1921:                        if (f->child != NULL) {
        !          1922:                                *rs = &f->child->ruleset;
        !          1923:                                *r = TAILQ_FIRST((*rs)->rules[n].active.ptr);
        !          1924:                                if (*r == NULL)
        !          1925:                                        continue;
        !          1926:                                else
        !          1927:                                        break;
        !          1928:                        }
        !          1929:                }
        !          1930:                (*depth)--;
        !          1931:                if (*depth == 0 && a != NULL)
        !          1932:                        *a = NULL;
        !          1933:                *rs = f->rs;
        !          1934:                if (f->r->anchor->match || (match  != NULL && *match))
        !          1935:                        quick = f->r->quick;
        !          1936:                *r = TAILQ_NEXT(f->r, entries);
        !          1937:        } while (*r == NULL);
        !          1938:
        !          1939:        return (quick);
        !          1940: }
        !          1941:
        !          1942: #ifdef INET6
        !          1943: void
        !          1944: pf_poolmask(struct pf_addr *naddr, struct pf_addr *raddr,
        !          1945:     struct pf_addr *rmask, struct pf_addr *saddr, sa_family_t af)
        !          1946: {
        !          1947:        switch (af) {
        !          1948: #ifdef INET
        !          1949:        case AF_INET:
        !          1950:                naddr->addr32[0] = (raddr->addr32[0] & rmask->addr32[0]) |
        !          1951:                ((rmask->addr32[0] ^ 0xffffffff ) & saddr->addr32[0]);
        !          1952:                break;
        !          1953: #endif /* INET */
        !          1954:        case AF_INET6:
        !          1955:                naddr->addr32[0] = (raddr->addr32[0] & rmask->addr32[0]) |
        !          1956:                ((rmask->addr32[0] ^ 0xffffffff ) & saddr->addr32[0]);
        !          1957:                naddr->addr32[1] = (raddr->addr32[1] & rmask->addr32[1]) |
        !          1958:                ((rmask->addr32[1] ^ 0xffffffff ) & saddr->addr32[1]);
        !          1959:                naddr->addr32[2] = (raddr->addr32[2] & rmask->addr32[2]) |
        !          1960:                ((rmask->addr32[2] ^ 0xffffffff ) & saddr->addr32[2]);
        !          1961:                naddr->addr32[3] = (raddr->addr32[3] & rmask->addr32[3]) |
        !          1962:                ((rmask->addr32[3] ^ 0xffffffff ) & saddr->addr32[3]);
        !          1963:                break;
        !          1964:        }
        !          1965: }
        !          1966:
        !          1967: void
        !          1968: pf_addr_inc(struct pf_addr *addr, sa_family_t af)
        !          1969: {
        !          1970:        switch (af) {
        !          1971: #ifdef INET
        !          1972:        case AF_INET:
        !          1973:                addr->addr32[0] = htonl(ntohl(addr->addr32[0]) + 1);
        !          1974:                break;
        !          1975: #endif /* INET */
        !          1976:        case AF_INET6:
        !          1977:                if (addr->addr32[3] == 0xffffffff) {
        !          1978:                        addr->addr32[3] = 0;
        !          1979:                        if (addr->addr32[2] == 0xffffffff) {
        !          1980:                                addr->addr32[2] = 0;
        !          1981:                                if (addr->addr32[1] == 0xffffffff) {
        !          1982:                                        addr->addr32[1] = 0;
        !          1983:                                        addr->addr32[0] =
        !          1984:                                            htonl(ntohl(addr->addr32[0]) + 1);
        !          1985:                                } else
        !          1986:                                        addr->addr32[1] =
        !          1987:                                            htonl(ntohl(addr->addr32[1]) + 1);
        !          1988:                        } else
        !          1989:                                addr->addr32[2] =
        !          1990:                                    htonl(ntohl(addr->addr32[2]) + 1);
        !          1991:                } else
        !          1992:                        addr->addr32[3] =
        !          1993:                            htonl(ntohl(addr->addr32[3]) + 1);
        !          1994:                break;
        !          1995:        }
        !          1996: }
        !          1997: #endif /* INET6 */
        !          1998:
        !          1999: #define mix(a,b,c) \
        !          2000:        do {                                    \
        !          2001:                a -= b; a -= c; a ^= (c >> 13); \
        !          2002:                b -= c; b -= a; b ^= (a << 8);  \
        !          2003:                c -= a; c -= b; c ^= (b >> 13); \
        !          2004:                a -= b; a -= c; a ^= (c >> 12); \
        !          2005:                b -= c; b -= a; b ^= (a << 16); \
        !          2006:                c -= a; c -= b; c ^= (b >> 5);  \
        !          2007:                a -= b; a -= c; a ^= (c >> 3);  \
        !          2008:                b -= c; b -= a; b ^= (a << 10); \
        !          2009:                c -= a; c -= b; c ^= (b >> 15); \
        !          2010:        } while (0)
        !          2011:
        !          2012: /*
        !          2013:  * hash function based on bridge_hash in if_bridge.c
        !          2014:  */
        !          2015: void
        !          2016: pf_hash(struct pf_addr *inaddr, struct pf_addr *hash,
        !          2017:     struct pf_poolhashkey *key, sa_family_t af)
        !          2018: {
        !          2019:        u_int32_t       a = 0x9e3779b9, b = 0x9e3779b9, c = key->key32[0];
        !          2020:
        !          2021:        switch (af) {
        !          2022: #ifdef INET
        !          2023:        case AF_INET:
        !          2024:                a += inaddr->addr32[0];
        !          2025:                b += key->key32[1];
        !          2026:                mix(a, b, c);
        !          2027:                hash->addr32[0] = c + key->key32[2];
        !          2028:                break;
        !          2029: #endif /* INET */
        !          2030: #ifdef INET6
        !          2031:        case AF_INET6:
        !          2032:                a += inaddr->addr32[0];
        !          2033:                b += inaddr->addr32[2];
        !          2034:                mix(a, b, c);
        !          2035:                hash->addr32[0] = c;
        !          2036:                a += inaddr->addr32[1];
        !          2037:                b += inaddr->addr32[3];
        !          2038:                c += key->key32[1];
        !          2039:                mix(a, b, c);
        !          2040:                hash->addr32[1] = c;
        !          2041:                a += inaddr->addr32[2];
        !          2042:                b += inaddr->addr32[1];
        !          2043:                c += key->key32[2];
        !          2044:                mix(a, b, c);
        !          2045:                hash->addr32[2] = c;
        !          2046:                a += inaddr->addr32[3];
        !          2047:                b += inaddr->addr32[0];
        !          2048:                c += key->key32[3];
        !          2049:                mix(a, b, c);
        !          2050:                hash->addr32[3] = c;
        !          2051:                break;
        !          2052: #endif /* INET6 */
        !          2053:        }
        !          2054: }
        !          2055:
        !          2056: int
        !          2057: pf_map_addr(sa_family_t af, struct pf_rule *r, struct pf_addr *saddr,
        !          2058:     struct pf_addr *naddr, struct pf_addr *init_addr, struct pf_src_node **sn)
        !          2059: {
        !          2060:        unsigned char            hash[16];
        !          2061:        struct pf_pool          *rpool = &r->rpool;
        !          2062:        struct pf_addr          *raddr = &rpool->cur->addr.v.a.addr;
        !          2063:        struct pf_addr          *rmask = &rpool->cur->addr.v.a.mask;
        !          2064:        struct pf_pooladdr      *acur = rpool->cur;
        !          2065:        struct pf_src_node       k;
        !          2066:
        !          2067:        if (*sn == NULL && r->rpool.opts & PF_POOL_STICKYADDR &&
        !          2068:            (r->rpool.opts & PF_POOL_TYPEMASK) != PF_POOL_NONE) {
        !          2069:                k.af = af;
        !          2070:                PF_ACPY(&k.addr, saddr, af);
        !          2071:                if (r->rule_flag & PFRULE_RULESRCTRACK ||
        !          2072:                    r->rpool.opts & PF_POOL_STICKYADDR)
        !          2073:                        k.rule.ptr = r;
        !          2074:                else
        !          2075:                        k.rule.ptr = NULL;
        !          2076:                pf_status.scounters[SCNT_SRC_NODE_SEARCH]++;
        !          2077:                *sn = RB_FIND(pf_src_tree, &tree_src_tracking, &k);
        !          2078:                if (*sn != NULL && !PF_AZERO(&(*sn)->raddr, af)) {
        !          2079:                        PF_ACPY(naddr, &(*sn)->raddr, af);
        !          2080:                        if (pf_status.debug >= PF_DEBUG_MISC) {
        !          2081:                                printf("pf_map_addr: src tracking maps ");
        !          2082:                                pf_print_host(&k.addr, 0, af);
        !          2083:                                printf(" to ");
        !          2084:                                pf_print_host(naddr, 0, af);
        !          2085:                                printf("\n");
        !          2086:                        }
        !          2087:                        return (0);
        !          2088:                }
        !          2089:        }
        !          2090:
        !          2091:        if (rpool->cur->addr.type == PF_ADDR_NOROUTE)
        !          2092:                return (1);
        !          2093:        if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) {
        !          2094:                switch (af) {
        !          2095: #ifdef INET
        !          2096:                case AF_INET:
        !          2097:                        if (rpool->cur->addr.p.dyn->pfid_acnt4 < 1 &&
        !          2098:                            (rpool->opts & PF_POOL_TYPEMASK) !=
        !          2099:                            PF_POOL_ROUNDROBIN)
        !          2100:                                return (1);
        !          2101:                         raddr = &rpool->cur->addr.p.dyn->pfid_addr4;
        !          2102:                         rmask = &rpool->cur->addr.p.dyn->pfid_mask4;
        !          2103:                        break;
        !          2104: #endif /* INET */
        !          2105: #ifdef INET6
        !          2106:                case AF_INET6:
        !          2107:                        if (rpool->cur->addr.p.dyn->pfid_acnt6 < 1 &&
        !          2108:                            (rpool->opts & PF_POOL_TYPEMASK) !=
        !          2109:                            PF_POOL_ROUNDROBIN)
        !          2110:                                return (1);
        !          2111:                        raddr = &rpool->cur->addr.p.dyn->pfid_addr6;
        !          2112:                        rmask = &rpool->cur->addr.p.dyn->pfid_mask6;
        !          2113:                        break;
        !          2114: #endif /* INET6 */
        !          2115:                }
        !          2116:        } else if (rpool->cur->addr.type == PF_ADDR_TABLE) {
        !          2117:                if ((rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_ROUNDROBIN)
        !          2118:                        return (1); /* unsupported */
        !          2119:        } else {
        !          2120:                raddr = &rpool->cur->addr.v.a.addr;
        !          2121:                rmask = &rpool->cur->addr.v.a.mask;
        !          2122:        }
        !          2123:
        !          2124:        switch (rpool->opts & PF_POOL_TYPEMASK) {
        !          2125:        case PF_POOL_NONE:
        !          2126:                PF_ACPY(naddr, raddr, af);
        !          2127:                break;
        !          2128:        case PF_POOL_BITMASK:
        !          2129:                PF_POOLMASK(naddr, raddr, rmask, saddr, af);
        !          2130:                break;
        !          2131:        case PF_POOL_RANDOM:
        !          2132:                if (init_addr != NULL && PF_AZERO(init_addr, af)) {
        !          2133:                        switch (af) {
        !          2134: #ifdef INET
        !          2135:                        case AF_INET:
        !          2136:                                rpool->counter.addr32[0] = htonl(arc4random());
        !          2137:                                break;
        !          2138: #endif /* INET */
        !          2139: #ifdef INET6
        !          2140:                        case AF_INET6:
        !          2141:                                if (rmask->addr32[3] != 0xffffffff)
        !          2142:                                        rpool->counter.addr32[3] =
        !          2143:                                            htonl(arc4random());
        !          2144:                                else
        !          2145:                                        break;
        !          2146:                                if (rmask->addr32[2] != 0xffffffff)
        !          2147:                                        rpool->counter.addr32[2] =
        !          2148:                                            htonl(arc4random());
        !          2149:                                else
        !          2150:                                        break;
        !          2151:                                if (rmask->addr32[1] != 0xffffffff)
        !          2152:                                        rpool->counter.addr32[1] =
        !          2153:                                            htonl(arc4random());
        !          2154:                                else
        !          2155:                                        break;
        !          2156:                                if (rmask->addr32[0] != 0xffffffff)
        !          2157:                                        rpool->counter.addr32[0] =
        !          2158:                                            htonl(arc4random());
        !          2159:                                break;
        !          2160: #endif /* INET6 */
        !          2161:                        }
        !          2162:                        PF_POOLMASK(naddr, raddr, rmask, &rpool->counter, af);
        !          2163:                        PF_ACPY(init_addr, naddr, af);
        !          2164:
        !          2165:                } else {
        !          2166:                        PF_AINC(&rpool->counter, af);
        !          2167:                        PF_POOLMASK(naddr, raddr, rmask, &rpool->counter, af);
        !          2168:                }
        !          2169:                break;
        !          2170:        case PF_POOL_SRCHASH:
        !          2171:                pf_hash(saddr, (struct pf_addr *)&hash, &rpool->key, af);
        !          2172:                PF_POOLMASK(naddr, raddr, rmask, (struct pf_addr *)&hash, af);
        !          2173:                break;
        !          2174:        case PF_POOL_ROUNDROBIN:
        !          2175:                if (rpool->cur->addr.type == PF_ADDR_TABLE) {
        !          2176:                        if (!pfr_pool_get(rpool->cur->addr.p.tbl,
        !          2177:                            &rpool->tblidx, &rpool->counter,
        !          2178:                            &raddr, &rmask, af))
        !          2179:                                goto get_addr;
        !          2180:                } else if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) {
        !          2181:                        if (!pfr_pool_get(rpool->cur->addr.p.dyn->pfid_kt,
        !          2182:                            &rpool->tblidx, &rpool->counter,
        !          2183:                            &raddr, &rmask, af))
        !          2184:                                goto get_addr;
        !          2185:                } else if (pf_match_addr(0, raddr, rmask, &rpool->counter, af))
        !          2186:                        goto get_addr;
        !          2187:
        !          2188:        try_next:
        !          2189:                if ((rpool->cur = TAILQ_NEXT(rpool->cur, entries)) == NULL)
        !          2190:                        rpool->cur = TAILQ_FIRST(&rpool->list);
        !          2191:                if (rpool->cur->addr.type == PF_ADDR_TABLE) {
        !          2192:                        rpool->tblidx = -1;
        !          2193:                        if (pfr_pool_get(rpool->cur->addr.p.tbl,
        !          2194:                            &rpool->tblidx, &rpool->counter,
        !          2195:                            &raddr, &rmask, af)) {
        !          2196:                                /* table contains no address of type 'af' */
        !          2197:                                if (rpool->cur != acur)
        !          2198:                                        goto try_next;
        !          2199:                                return (1);
        !          2200:                        }
        !          2201:                } else if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) {
        !          2202:                        rpool->tblidx = -1;
        !          2203:                        if (pfr_pool_get(rpool->cur->addr.p.dyn->pfid_kt,
        !          2204:                            &rpool->tblidx, &rpool->counter,
        !          2205:                            &raddr, &rmask, af)) {
        !          2206:                                /* table contains no address of type 'af' */
        !          2207:                                if (rpool->cur != acur)
        !          2208:                                        goto try_next;
        !          2209:                                return (1);
        !          2210:                        }
        !          2211:                } else {
        !          2212:                        raddr = &rpool->cur->addr.v.a.addr;
        !          2213:                        rmask = &rpool->cur->addr.v.a.mask;
        !          2214:                        PF_ACPY(&rpool->counter, raddr, af);
        !          2215:                }
        !          2216:
        !          2217:        get_addr:
        !          2218:                PF_ACPY(naddr, &rpool->counter, af);
        !          2219:                if (init_addr != NULL && PF_AZERO(init_addr, af))
        !          2220:                        PF_ACPY(init_addr, naddr, af);
        !          2221:                PF_AINC(&rpool->counter, af);
        !          2222:                break;
        !          2223:        }
        !          2224:        if (*sn != NULL)
        !          2225:                PF_ACPY(&(*sn)->raddr, naddr, af);
        !          2226:
        !          2227:        if (pf_status.debug >= PF_DEBUG_MISC &&
        !          2228:            (rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_NONE) {
        !          2229:                printf("pf_map_addr: selected address ");
        !          2230:                pf_print_host(naddr, 0, af);
        !          2231:                printf("\n");
        !          2232:        }
        !          2233:
        !          2234:        return (0);
        !          2235: }
        !          2236:
        !          2237: int
        !          2238: pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r,
        !          2239:     struct pf_addr *saddr, struct pf_addr *daddr, u_int16_t dport,
        !          2240:     struct pf_addr *naddr, u_int16_t *nport, u_int16_t low, u_int16_t high,
        !          2241:     struct pf_src_node **sn)
        !          2242: {
        !          2243:        struct pf_state_key_cmp key;
        !          2244:        struct pf_addr          init_addr;
        !          2245:        u_int16_t               cut;
        !          2246:
        !          2247:        bzero(&init_addr, sizeof(init_addr));
        !          2248:        if (pf_map_addr(af, r, saddr, naddr, &init_addr, sn))
        !          2249:                return (1);
        !          2250:
        !          2251:        if (proto == IPPROTO_ICMP) {
        !          2252:                low = 1;
        !          2253:                high = 65535;
        !          2254:        }
        !          2255:
        !          2256:        do {
        !          2257:                key.af = af;
        !          2258:                key.proto = proto;
        !          2259:                PF_ACPY(&key.ext.addr, daddr, key.af);
        !          2260:                PF_ACPY(&key.gwy.addr, naddr, key.af);
        !          2261:                key.ext.port = dport;
        !          2262:
        !          2263:                /*
        !          2264:                 * port search; start random, step;
        !          2265:                 * similar 2 portloop in in_pcbbind
        !          2266:                 */
        !          2267:                if (!(proto == IPPROTO_TCP || proto == IPPROTO_UDP ||
        !          2268:                    proto == IPPROTO_ICMP)) {
        !          2269:                        key.gwy.port = dport;
        !          2270:                        if (pf_find_state_all(&key, PF_EXT_GWY, NULL) == NULL)
        !          2271:                                return (0);
        !          2272:                } else if (low == 0 && high == 0) {
        !          2273:                        key.gwy.port = *nport;
        !          2274:                        if (pf_find_state_all(&key, PF_EXT_GWY, NULL) == NULL)
        !          2275:                                return (0);
        !          2276:                } else if (low == high) {
        !          2277:                        key.gwy.port = htons(low);
        !          2278:                        if (pf_find_state_all(&key, PF_EXT_GWY, NULL) == NULL) {
        !          2279:                                *nport = htons(low);
        !          2280:                                return (0);
        !          2281:                        }
        !          2282:                } else {
        !          2283:                        u_int16_t tmp;
        !          2284:
        !          2285:                        if (low > high) {
        !          2286:                                tmp = low;
        !          2287:                                low = high;
        !          2288:                                high = tmp;
        !          2289:                        }
        !          2290:                        /* low < high */
        !          2291:                        cut = htonl(arc4random()) % (1 + high - low) + low;
        !          2292:                        /* low <= cut <= high */
        !          2293:                        for (tmp = cut; tmp <= high; ++(tmp)) {
        !          2294:                                key.gwy.port = htons(tmp);
        !          2295:                                if (pf_find_state_all(&key, PF_EXT_GWY, NULL) ==
        !          2296:                                    NULL) {
        !          2297:                                        *nport = htons(tmp);
        !          2298:                                        return (0);
        !          2299:                                }
        !          2300:                        }
        !          2301:                        for (tmp = cut - 1; tmp >= low; --(tmp)) {
        !          2302:                                key.gwy.port = htons(tmp);
        !          2303:                                if (pf_find_state_all(&key, PF_EXT_GWY, NULL) ==
        !          2304:                                    NULL) {
        !          2305:                                        *nport = htons(tmp);
        !          2306:                                        return (0);
        !          2307:                                }
        !          2308:                        }
        !          2309:                }
        !          2310:
        !          2311:                switch (r->rpool.opts & PF_POOL_TYPEMASK) {
        !          2312:                case PF_POOL_RANDOM:
        !          2313:                case PF_POOL_ROUNDROBIN:
        !          2314:                        if (pf_map_addr(af, r, saddr, naddr, &init_addr, sn))
        !          2315:                                return (1);
        !          2316:                        break;
        !          2317:                case PF_POOL_NONE:
        !          2318:                case PF_POOL_SRCHASH:
        !          2319:                case PF_POOL_BITMASK:
        !          2320:                default:
        !          2321:                        return (1);
        !          2322:                }
        !          2323:        } while (! PF_AEQ(&init_addr, naddr, af) );
        !          2324:
        !          2325:        return (1);                                     /* none available */
        !          2326: }
        !          2327:
        !          2328: struct pf_rule *
        !          2329: pf_match_translation(struct pf_pdesc *pd, struct mbuf *m, int off,
        !          2330:     int direction, struct pfi_kif *kif, struct pf_addr *saddr, u_int16_t sport,
        !          2331:     struct pf_addr *daddr, u_int16_t dport, int rs_num)
        !          2332: {
        !          2333:        struct pf_rule          *r, *rm = NULL;
        !          2334:        struct pf_ruleset       *ruleset = NULL;
        !          2335:        int                      tag = -1;
        !          2336:        int                      rtableid = -1;
        !          2337:        int                      asd = 0;
        !          2338:
        !          2339:        r = TAILQ_FIRST(pf_main_ruleset.rules[rs_num].active.ptr);
        !          2340:        while (r && rm == NULL) {
        !          2341:                struct pf_rule_addr     *src = NULL, *dst = NULL;
        !          2342:                struct pf_addr_wrap     *xdst = NULL;
        !          2343:
        !          2344:                if (r->action == PF_BINAT && direction == PF_IN) {
        !          2345:                        src = &r->dst;
        !          2346:                        if (r->rpool.cur != NULL)
        !          2347:                                xdst = &r->rpool.cur->addr;
        !          2348:                } else {
        !          2349:                        src = &r->src;
        !          2350:                        dst = &r->dst;
        !          2351:                }
        !          2352:
        !          2353:                r->evaluations++;
        !          2354:                if (pfi_kif_match(r->kif, kif) == r->ifnot)
        !          2355:                        r = r->skip[PF_SKIP_IFP].ptr;
        !          2356:                else if (r->direction && r->direction != direction)
        !          2357:                        r = r->skip[PF_SKIP_DIR].ptr;
        !          2358:                else if (r->af && r->af != pd->af)
        !          2359:                        r = r->skip[PF_SKIP_AF].ptr;
        !          2360:                else if (r->proto && r->proto != pd->proto)
        !          2361:                        r = r->skip[PF_SKIP_PROTO].ptr;
        !          2362:                else if (PF_MISMATCHAW(&src->addr, saddr, pd->af,
        !          2363:                    src->neg, kif))
        !          2364:                        r = r->skip[src == &r->src ? PF_SKIP_SRC_ADDR :
        !          2365:                            PF_SKIP_DST_ADDR].ptr;
        !          2366:                else if (src->port_op && !pf_match_port(src->port_op,
        !          2367:                    src->port[0], src->port[1], sport))
        !          2368:                        r = r->skip[src == &r->src ? PF_SKIP_SRC_PORT :
        !          2369:                            PF_SKIP_DST_PORT].ptr;
        !          2370:                else if (dst != NULL &&
        !          2371:                    PF_MISMATCHAW(&dst->addr, daddr, pd->af, dst->neg, NULL))
        !          2372:                        r = r->skip[PF_SKIP_DST_ADDR].ptr;
        !          2373:                else if (xdst != NULL && PF_MISMATCHAW(xdst, daddr, pd->af,
        !          2374:                    0, NULL))
        !          2375:                        r = TAILQ_NEXT(r, entries);
        !          2376:                else if (dst != NULL && dst->port_op &&
        !          2377:                    !pf_match_port(dst->port_op, dst->port[0],
        !          2378:                    dst->port[1], dport))
        !          2379:                        r = r->skip[PF_SKIP_DST_PORT].ptr;
        !          2380:                else if (r->match_tag && !pf_match_tag(m, r, &tag))
        !          2381:                        r = TAILQ_NEXT(r, entries);
        !          2382:                else if (r->os_fingerprint != PF_OSFP_ANY && (pd->proto !=
        !          2383:                    IPPROTO_TCP || !pf_osfp_match(pf_osfp_fingerprint(pd, m,
        !          2384:                    off, pd->hdr.tcp), r->os_fingerprint)))
        !          2385:                        r = TAILQ_NEXT(r, entries);
        !          2386:                else {
        !          2387:                        if (r->tag)
        !          2388:                                tag = r->tag;
        !          2389:                        if (r->rtableid >= 0)
        !          2390:                                rtableid = r->rtableid;
        !          2391:                        if (r->anchor == NULL) {
        !          2392:                                rm = r;
        !          2393:                        } else
        !          2394:                                pf_step_into_anchor(&asd, &ruleset, rs_num,
        !          2395:                                    &r, NULL, NULL);
        !          2396:                }
        !          2397:                if (r == NULL)
        !          2398:                        pf_step_out_of_anchor(&asd, &ruleset, rs_num, &r,
        !          2399:                            NULL, NULL);
        !          2400:        }
        !          2401:        if (pf_tag_packet(m, tag, rtableid))
        !          2402:                return (NULL);
        !          2403:        if (rm != NULL && (rm->action == PF_NONAT ||
        !          2404:            rm->action == PF_NORDR || rm->action == PF_NOBINAT))
        !          2405:                return (NULL);
        !          2406:        return (rm);
        !          2407: }
        !          2408:
        !          2409: struct pf_rule *
        !          2410: pf_get_translation(struct pf_pdesc *pd, struct mbuf *m, int off, int direction,
        !          2411:     struct pfi_kif *kif, struct pf_src_node **sn,
        !          2412:     struct pf_addr *saddr, u_int16_t sport,
        !          2413:     struct pf_addr *daddr, u_int16_t dport,
        !          2414:     struct pf_addr *naddr, u_int16_t *nport)
        !          2415: {
        !          2416:        struct pf_rule  *r = NULL;
        !          2417:
        !          2418:        if (direction == PF_OUT) {
        !          2419:                r = pf_match_translation(pd, m, off, direction, kif, saddr,
        !          2420:                    sport, daddr, dport, PF_RULESET_BINAT);
        !          2421:                if (r == NULL)
        !          2422:                        r = pf_match_translation(pd, m, off, direction, kif,
        !          2423:                            saddr, sport, daddr, dport, PF_RULESET_NAT);
        !          2424:        } else {
        !          2425:                r = pf_match_translation(pd, m, off, direction, kif, saddr,
        !          2426:                    sport, daddr, dport, PF_RULESET_RDR);
        !          2427:                if (r == NULL)
        !          2428:                        r = pf_match_translation(pd, m, off, direction, kif,
        !          2429:                            saddr, sport, daddr, dport, PF_RULESET_BINAT);
        !          2430:        }
        !          2431:
        !          2432:        if (r != NULL) {
        !          2433:                switch (r->action) {
        !          2434:                case PF_NONAT:
        !          2435:                case PF_NOBINAT:
        !          2436:                case PF_NORDR:
        !          2437:                        return (NULL);
        !          2438:                case PF_NAT:
        !          2439:                        if (pf_get_sport(pd->af, pd->proto, r, saddr,
        !          2440:                            daddr, dport, naddr, nport, r->rpool.proxy_port[0],
        !          2441:                            r->rpool.proxy_port[1], sn)) {
        !          2442:                                DPFPRINTF(PF_DEBUG_MISC,
        !          2443:                                    ("pf: NAT proxy port allocation "
        !          2444:                                    "(%u-%u) failed\n",
        !          2445:                                    r->rpool.proxy_port[0],
        !          2446:                                    r->rpool.proxy_port[1]));
        !          2447:                                return (NULL);
        !          2448:                        }
        !          2449:                        break;
        !          2450:                case PF_BINAT:
        !          2451:                        switch (direction) {
        !          2452:                        case PF_OUT:
        !          2453:                                if (r->rpool.cur->addr.type == PF_ADDR_DYNIFTL){
        !          2454:                                        switch (pd->af) {
        !          2455: #ifdef INET
        !          2456:                                        case AF_INET:
        !          2457:                                                if (r->rpool.cur->addr.p.dyn->
        !          2458:                                                    pfid_acnt4 < 1)
        !          2459:                                                        return (NULL);
        !          2460:                                                PF_POOLMASK(naddr,
        !          2461:                                                    &r->rpool.cur->addr.p.dyn->
        !          2462:                                                    pfid_addr4,
        !          2463:                                                    &r->rpool.cur->addr.p.dyn->
        !          2464:                                                    pfid_mask4,
        !          2465:                                                    saddr, AF_INET);
        !          2466:                                                break;
        !          2467: #endif /* INET */
        !          2468: #ifdef INET6
        !          2469:                                        case AF_INET6:
        !          2470:                                                if (r->rpool.cur->addr.p.dyn->
        !          2471:                                                    pfid_acnt6 < 1)
        !          2472:                                                        return (NULL);
        !          2473:                                                PF_POOLMASK(naddr,
        !          2474:                                                    &r->rpool.cur->addr.p.dyn->
        !          2475:                                                    pfid_addr6,
        !          2476:                                                    &r->rpool.cur->addr.p.dyn->
        !          2477:                                                    pfid_mask6,
        !          2478:                                                    saddr, AF_INET6);
        !          2479:                                                break;
        !          2480: #endif /* INET6 */
        !          2481:                                        }
        !          2482:                                } else
        !          2483:                                        PF_POOLMASK(naddr,
        !          2484:                                            &r->rpool.cur->addr.v.a.addr,
        !          2485:                                            &r->rpool.cur->addr.v.a.mask,
        !          2486:                                            saddr, pd->af);
        !          2487:                                break;
        !          2488:                        case PF_IN:
        !          2489:                                if (r->src.addr.type == PF_ADDR_DYNIFTL) {
        !          2490:                                        switch (pd->af) {
        !          2491: #ifdef INET
        !          2492:                                        case AF_INET:
        !          2493:                                                if (r->src.addr.p.dyn->
        !          2494:                                                    pfid_acnt4 < 1)
        !          2495:                                                        return (NULL);
        !          2496:                                                PF_POOLMASK(naddr,
        !          2497:                                                    &r->src.addr.p.dyn->
        !          2498:                                                    pfid_addr4,
        !          2499:                                                    &r->src.addr.p.dyn->
        !          2500:                                                    pfid_mask4,
        !          2501:                                                    daddr, AF_INET);
        !          2502:                                                break;
        !          2503: #endif /* INET */
        !          2504: #ifdef INET6
        !          2505:                                        case AF_INET6:
        !          2506:                                                if (r->src.addr.p.dyn->
        !          2507:                                                    pfid_acnt6 < 1)
        !          2508:                                                        return (NULL);
        !          2509:                                                PF_POOLMASK(naddr,
        !          2510:                                                    &r->src.addr.p.dyn->
        !          2511:                                                    pfid_addr6,
        !          2512:                                                    &r->src.addr.p.dyn->
        !          2513:                                                    pfid_mask6,
        !          2514:                                                    daddr, AF_INET6);
        !          2515:                                                break;
        !          2516: #endif /* INET6 */
        !          2517:                                        }
        !          2518:                                } else
        !          2519:                                        PF_POOLMASK(naddr,
        !          2520:                                            &r->src.addr.v.a.addr,
        !          2521:                                            &r->src.addr.v.a.mask, daddr,
        !          2522:                                            pd->af);
        !          2523:                                break;
        !          2524:                        }
        !          2525:                        break;
        !          2526:                case PF_RDR: {
        !          2527:                        if (pf_map_addr(pd->af, r, saddr, naddr, NULL, sn))
        !          2528:                                return (NULL);
        !          2529:                        if ((r->rpool.opts & PF_POOL_TYPEMASK) ==
        !          2530:                            PF_POOL_BITMASK)
        !          2531:                                PF_POOLMASK(naddr, naddr,
        !          2532:                                    &r->rpool.cur->addr.v.a.mask, daddr,
        !          2533:                                    pd->af);
        !          2534:
        !          2535:                        if (r->rpool.proxy_port[1]) {
        !          2536:                                u_int32_t       tmp_nport;
        !          2537:
        !          2538:                                tmp_nport = ((ntohs(dport) -
        !          2539:                                    ntohs(r->dst.port[0])) %
        !          2540:                                    (r->rpool.proxy_port[1] -
        !          2541:                                    r->rpool.proxy_port[0] + 1)) +
        !          2542:                                    r->rpool.proxy_port[0];
        !          2543:
        !          2544:                                /* wrap around if necessary */
        !          2545:                                if (tmp_nport > 65535)
        !          2546:                                        tmp_nport -= 65535;
        !          2547:                                *nport = htons((u_int16_t)tmp_nport);
        !          2548:                        } else if (r->rpool.proxy_port[0])
        !          2549:                                *nport = htons(r->rpool.proxy_port[0]);
        !          2550:                        break;
        !          2551:                }
        !          2552:                default:
        !          2553:                        return (NULL);
        !          2554:                }
        !          2555:        }
        !          2556:
        !          2557:        return (r);
        !          2558: }
        !          2559:
        !          2560: int
        !          2561: pf_socket_lookup(int direction, struct pf_pdesc *pd)
        !          2562: {
        !          2563:        struct pf_addr          *saddr, *daddr;
        !          2564:        u_int16_t                sport, dport;
        !          2565:        struct inpcbtable       *tb;
        !          2566:        struct inpcb            *inp;
        !          2567:
        !          2568:        if (pd == NULL)
        !          2569:                return (-1);
        !          2570:        pd->lookup.uid = UID_MAX;
        !          2571:        pd->lookup.gid = GID_MAX;
        !          2572:        pd->lookup.pid = NO_PID;
        !          2573:        switch (pd->proto) {
        !          2574:        case IPPROTO_TCP:
        !          2575:                if (pd->hdr.tcp == NULL)
        !          2576:                        return (-1);
        !          2577:                sport = pd->hdr.tcp->th_sport;
        !          2578:                dport = pd->hdr.tcp->th_dport;
        !          2579:                tb = &tcbtable;
        !          2580:                break;
        !          2581:        case IPPROTO_UDP:
        !          2582:                if (pd->hdr.udp == NULL)
        !          2583:                        return (-1);
        !          2584:                sport = pd->hdr.udp->uh_sport;
        !          2585:                dport = pd->hdr.udp->uh_dport;
        !          2586:                tb = &udbtable;
        !          2587:                break;
        !          2588:        default:
        !          2589:                return (-1);
        !          2590:        }
        !          2591:        if (direction == PF_IN) {
        !          2592:                saddr = pd->src;
        !          2593:                daddr = pd->dst;
        !          2594:        } else {
        !          2595:                u_int16_t       p;
        !          2596:
        !          2597:                p = sport;
        !          2598:                sport = dport;
        !          2599:                dport = p;
        !          2600:                saddr = pd->dst;
        !          2601:                daddr = pd->src;
        !          2602:        }
        !          2603:        switch (pd->af) {
        !          2604: #ifdef INET
        !          2605:        case AF_INET:
        !          2606:                inp = in_pcbhashlookup(tb, saddr->v4, sport, daddr->v4, dport);
        !          2607:                if (inp == NULL) {
        !          2608:                        inp = in_pcblookup_listen(tb, daddr->v4, dport, 0);
        !          2609:                        if (inp == NULL)
        !          2610:                                return (-1);
        !          2611:                }
        !          2612:                break;
        !          2613: #endif /* INET */
        !          2614: #ifdef INET6
        !          2615:        case AF_INET6:
        !          2616:                inp = in6_pcbhashlookup(tb, &saddr->v6, sport, &daddr->v6,
        !          2617:                    dport);
        !          2618:                if (inp == NULL) {
        !          2619:                        inp = in6_pcblookup_listen(tb, &daddr->v6, dport, 0);
        !          2620:                        if (inp == NULL)
        !          2621:                                return (-1);
        !          2622:                }
        !          2623:                break;
        !          2624: #endif /* INET6 */
        !          2625:
        !          2626:        default:
        !          2627:                return (-1);
        !          2628:        }
        !          2629:        pd->lookup.uid = inp->inp_socket->so_euid;
        !          2630:        pd->lookup.gid = inp->inp_socket->so_egid;
        !          2631:        pd->lookup.pid = inp->inp_socket->so_cpid;
        !          2632:        return (1);
        !          2633: }
        !          2634:
        !          2635: u_int8_t
        !          2636: pf_get_wscale(struct mbuf *m, int off, u_int16_t th_off, sa_family_t af)
        !          2637: {
        !          2638:        int              hlen;
        !          2639:        u_int8_t         hdr[60];
        !          2640:        u_int8_t        *opt, optlen;
        !          2641:        u_int8_t         wscale = 0;
        !          2642:
        !          2643:        hlen = th_off << 2;             /* hlen <= sizeof(hdr) */
        !          2644:        if (hlen <= sizeof(struct tcphdr))
        !          2645:                return (0);
        !          2646:        if (!pf_pull_hdr(m, off, hdr, hlen, NULL, NULL, af))
        !          2647:                return (0);
        !          2648:        opt = hdr + sizeof(struct tcphdr);
        !          2649:        hlen -= sizeof(struct tcphdr);
        !          2650:        while (hlen >= 3) {
        !          2651:                switch (*opt) {
        !          2652:                case TCPOPT_EOL:
        !          2653:                case TCPOPT_NOP:
        !          2654:                        ++opt;
        !          2655:                        --hlen;
        !          2656:                        break;
        !          2657:                case TCPOPT_WINDOW:
        !          2658:                        wscale = opt[2];
        !          2659:                        if (wscale > TCP_MAX_WINSHIFT)
        !          2660:                                wscale = TCP_MAX_WINSHIFT;
        !          2661:                        wscale |= PF_WSCALE_FLAG;
        !          2662:                        /* FALLTHROUGH */
        !          2663:                default:
        !          2664:                        optlen = opt[1];
        !          2665:                        if (optlen < 2)
        !          2666:                                optlen = 2;
        !          2667:                        hlen -= optlen;
        !          2668:                        opt += optlen;
        !          2669:                        break;
        !          2670:                }
        !          2671:        }
        !          2672:        return (wscale);
        !          2673: }
        !          2674:
        !          2675: u_int16_t
        !          2676: pf_get_mss(struct mbuf *m, int off, u_int16_t th_off, sa_family_t af)
        !          2677: {
        !          2678:        int              hlen;
        !          2679:        u_int8_t         hdr[60];
        !          2680:        u_int8_t        *opt, optlen;
        !          2681:        u_int16_t        mss = tcp_mssdflt;
        !          2682:
        !          2683:        hlen = th_off << 2;     /* hlen <= sizeof(hdr) */
        !          2684:        if (hlen <= sizeof(struct tcphdr))
        !          2685:                return (0);
        !          2686:        if (!pf_pull_hdr(m, off, hdr, hlen, NULL, NULL, af))
        !          2687:                return (0);
        !          2688:        opt = hdr + sizeof(struct tcphdr);
        !          2689:        hlen -= sizeof(struct tcphdr);
        !          2690:        while (hlen >= TCPOLEN_MAXSEG) {
        !          2691:                switch (*opt) {
        !          2692:                case TCPOPT_EOL:
        !          2693:                case TCPOPT_NOP:
        !          2694:                        ++opt;
        !          2695:                        --hlen;
        !          2696:                        break;
        !          2697:                case TCPOPT_MAXSEG:
        !          2698:                        bcopy((caddr_t)(opt + 2), (caddr_t)&mss, 2);
        !          2699:                        NTOHS(mss);
        !          2700:                        /* FALLTHROUGH */
        !          2701:                default:
        !          2702:                        optlen = opt[1];
        !          2703:                        if (optlen < 2)
        !          2704:                                optlen = 2;
        !          2705:                        hlen -= optlen;
        !          2706:                        opt += optlen;
        !          2707:                        break;
        !          2708:                }
        !          2709:        }
        !          2710:        return (mss);
        !          2711: }
        !          2712:
        !          2713: u_int16_t
        !          2714: pf_calc_mss(struct pf_addr *addr, sa_family_t af, u_int16_t offer)
        !          2715: {
        !          2716: #ifdef INET
        !          2717:        struct sockaddr_in      *dst;
        !          2718:        struct route             ro;
        !          2719: #endif /* INET */
        !          2720: #ifdef INET6
        !          2721:        struct sockaddr_in6     *dst6;
        !          2722:        struct route_in6         ro6;
        !          2723: #endif /* INET6 */
        !          2724:        struct rtentry          *rt = NULL;
        !          2725:        int                      hlen;
        !          2726:        u_int16_t                mss = tcp_mssdflt;
        !          2727:
        !          2728:        switch (af) {
        !          2729: #ifdef INET
        !          2730:        case AF_INET:
        !          2731:                hlen = sizeof(struct ip);
        !          2732:                bzero(&ro, sizeof(ro));
        !          2733:                dst = (struct sockaddr_in *)&ro.ro_dst;
        !          2734:                dst->sin_family = AF_INET;
        !          2735:                dst->sin_len = sizeof(*dst);
        !          2736:                dst->sin_addr = addr->v4;
        !          2737:                rtalloc_noclone(&ro, NO_CLONING);
        !          2738:                rt = ro.ro_rt;
        !          2739:                break;
        !          2740: #endif /* INET */
        !          2741: #ifdef INET6
        !          2742:        case AF_INET6:
        !          2743:                hlen = sizeof(struct ip6_hdr);
        !          2744:                bzero(&ro6, sizeof(ro6));
        !          2745:                dst6 = (struct sockaddr_in6 *)&ro6.ro_dst;
        !          2746:                dst6->sin6_family = AF_INET6;
        !          2747:                dst6->sin6_len = sizeof(*dst6);
        !          2748:                dst6->sin6_addr = addr->v6;
        !          2749:                rtalloc_noclone((struct route *)&ro6, NO_CLONING);
        !          2750:                rt = ro6.ro_rt;
        !          2751:                break;
        !          2752: #endif /* INET6 */
        !          2753:        }
        !          2754:
        !          2755:        if (rt && rt->rt_ifp) {
        !          2756:                mss = rt->rt_ifp->if_mtu - hlen - sizeof(struct tcphdr);
        !          2757:                mss = max(tcp_mssdflt, mss);
        !          2758:                RTFREE(rt);
        !          2759:        }
        !          2760:        mss = min(mss, offer);
        !          2761:        mss = max(mss, 64);             /* sanity - at least max opt space */
        !          2762:        return (mss);
        !          2763: }
        !          2764:
        !          2765: void
        !          2766: pf_set_rt_ifp(struct pf_state *s, struct pf_addr *saddr)
        !          2767: {
        !          2768:        struct pf_rule *r = s->rule.ptr;
        !          2769:
        !          2770:        s->rt_kif = NULL;
        !          2771:        if (!r->rt || r->rt == PF_FASTROUTE)
        !          2772:                return;
        !          2773:        switch (s->state_key->af) {
        !          2774: #ifdef INET
        !          2775:        case AF_INET:
        !          2776:                pf_map_addr(AF_INET, r, saddr, &s->rt_addr, NULL,
        !          2777:                    &s->nat_src_node);
        !          2778:                s->rt_kif = r->rpool.cur->kif;
        !          2779:                break;
        !          2780: #endif /* INET */
        !          2781: #ifdef INET6
        !          2782:        case AF_INET6:
        !          2783:                pf_map_addr(AF_INET6, r, saddr, &s->rt_addr, NULL,
        !          2784:                    &s->nat_src_node);
        !          2785:                s->rt_kif = r->rpool.cur->kif;
        !          2786:                break;
        !          2787: #endif /* INET6 */
        !          2788:        }
        !          2789: }
        !          2790:
        !          2791: void
        !          2792: pf_attach_state(struct pf_state_key *sk, struct pf_state *s, int tail)
        !          2793: {
        !          2794:        s->state_key = sk;
        !          2795:        sk->refcnt++;
        !          2796:
        !          2797:        /* list is sorted, if-bound states before floating */
        !          2798:        if (tail)
        !          2799:                TAILQ_INSERT_TAIL(&sk->states, s, next);
        !          2800:        else
        !          2801:                TAILQ_INSERT_HEAD(&sk->states, s, next);
        !          2802: }
        !          2803:
        !          2804: void
        !          2805: pf_detach_state(struct pf_state *s, int flags)
        !          2806: {
        !          2807:        struct pf_state_key     *sk = s->state_key;
        !          2808:
        !          2809:        if (sk == NULL)
        !          2810:                return;
        !          2811:
        !          2812:        s->state_key = NULL;
        !          2813:        TAILQ_REMOVE(&sk->states, s, next);
        !          2814:        if (--sk->refcnt == 0) {
        !          2815:                if (!(flags & PF_DT_SKIP_EXTGWY))
        !          2816:                        RB_REMOVE(pf_state_tree_ext_gwy,
        !          2817:                            &pf_statetbl_ext_gwy, sk);
        !          2818:                if (!(flags & PF_DT_SKIP_LANEXT))
        !          2819:                        RB_REMOVE(pf_state_tree_lan_ext,
        !          2820:                            &pf_statetbl_lan_ext, sk);
        !          2821:                pool_put(&pf_state_key_pl, sk);
        !          2822:        }
        !          2823: }
        !          2824:
        !          2825: struct pf_state_key *
        !          2826: pf_alloc_state_key(struct pf_state *s)
        !          2827: {
        !          2828:        struct pf_state_key     *sk;
        !          2829:
        !          2830:        if ((sk = pool_get(&pf_state_key_pl, PR_NOWAIT)) == NULL)
        !          2831:                return (NULL);
        !          2832:        bzero(sk, sizeof(*sk));
        !          2833:        TAILQ_INIT(&sk->states);
        !          2834:        pf_attach_state(sk, s, 0);
        !          2835:
        !          2836:        return (sk);
        !          2837: }
        !          2838:
        !          2839: int
        !          2840: pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction,
        !          2841:     struct pfi_kif *kif, struct mbuf *m, int off, void *h,
        !          2842:     struct pf_pdesc *pd, struct pf_rule **am, struct pf_ruleset **rsm,
        !          2843:     struct ifqueue *ifq)
        !          2844: {
        !          2845:        struct pf_rule          *nr = NULL;
        !          2846:        struct pf_addr          *saddr = pd->src, *daddr = pd->dst;
        !          2847:        u_int16_t                bport, nport = 0;
        !          2848:        sa_family_t              af = pd->af;
        !          2849:        struct pf_rule          *r, *a = NULL;
        !          2850:        struct pf_ruleset       *ruleset = NULL;
        !          2851:        struct pf_src_node      *nsn = NULL;
        !          2852:        struct tcphdr           *th = pd->hdr.tcp;
        !          2853:        u_short                  reason;
        !          2854:        int                      rewrite = 0, hdrlen = 0;
        !          2855:        int                      tag = -1, rtableid = -1;
        !          2856:        int                      asd = 0;
        !          2857:        int                      match = 0;
        !          2858:        int                      state_icmp = 0;
        !          2859:        u_int16_t                mss = tcp_mssdflt;
        !          2860:        u_int16_t                sport, dport;
        !          2861:        u_int8_t                 icmptype = 0, icmpcode = 0;
        !          2862:
        !          2863:        if (direction == PF_IN && pf_check_congestion(ifq)) {
        !          2864:                REASON_SET(&reason, PFRES_CONGEST);
        !          2865:                return (PF_DROP);
        !          2866:        }
        !          2867:
        !          2868:        sport = dport = hdrlen = 0;
        !          2869:
        !          2870:        switch (pd->proto) {
        !          2871:        case IPPROTO_TCP:
        !          2872:                sport = th->th_sport;
        !          2873:                dport = th->th_dport;
        !          2874:                hdrlen = sizeof(*th);
        !          2875:                break;
        !          2876:        case IPPROTO_UDP:
        !          2877:                sport = pd->hdr.udp->uh_sport;
        !          2878:                dport = pd->hdr.udp->uh_dport;
        !          2879:                hdrlen = sizeof(*pd->hdr.udp);
        !          2880:                break;
        !          2881: #ifdef INET
        !          2882:        case IPPROTO_ICMP:
        !          2883:                if (pd->af != AF_INET)
        !          2884:                        break;
        !          2885:                sport = dport = pd->hdr.icmp->icmp_id;
        !          2886:                icmptype = pd->hdr.icmp->icmp_type;
        !          2887:                icmpcode = pd->hdr.icmp->icmp_code;
        !          2888:
        !          2889:                if (icmptype == ICMP_UNREACH ||
        !          2890:                    icmptype == ICMP_SOURCEQUENCH ||
        !          2891:                    icmptype == ICMP_REDIRECT ||
        !          2892:                    icmptype == ICMP_TIMXCEED ||
        !          2893:                    icmptype == ICMP_PARAMPROB)
        !          2894:                        state_icmp++;
        !          2895:                break;
        !          2896: #endif /* INET */
        !          2897: #ifdef INET6
        !          2898:        case IPPROTO_ICMPV6:
        !          2899:                if (pd->af != AF_INET6)
        !          2900:                        break;
        !          2901:                sport = dport = pd->hdr.icmp6->icmp6_id;
        !          2902:                hdrlen = sizeof(*pd->hdr.icmp6);
        !          2903:                icmptype = pd->hdr.icmp6->icmp6_type;
        !          2904:                icmpcode = pd->hdr.icmp6->icmp6_code;
        !          2905:
        !          2906:                if (icmptype == ICMP6_DST_UNREACH ||
        !          2907:                    icmptype == ICMP6_PACKET_TOO_BIG ||
        !          2908:                    icmptype == ICMP6_TIME_EXCEEDED ||
        !          2909:                    icmptype == ICMP6_PARAM_PROB)
        !          2910:                        state_icmp++;
        !          2911:                break;
        !          2912: #endif /* INET6 */
        !          2913:        }
        !          2914:
        !          2915:        r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_FILTER].active.ptr);
        !          2916:
        !          2917:        if (direction == PF_OUT) {
        !          2918:                bport = nport = sport;
        !          2919:                /* check outgoing packet for BINAT/NAT */
        !          2920:                if ((nr = pf_get_translation(pd, m, off, PF_OUT, kif, &nsn,
        !          2921:                    saddr, sport, daddr, dport, &pd->naddr, &nport)) != NULL) {
        !          2922:                        PF_ACPY(&pd->baddr, saddr, af);
        !          2923:                        switch (pd->proto) {
        !          2924:                        case IPPROTO_TCP:
        !          2925:                                pf_change_ap(saddr, &th->th_sport, pd->ip_sum,
        !          2926:                                    &th->th_sum, &pd->naddr, nport, 0, af);
        !          2927:                                sport = th->th_sport;
        !          2928:                                rewrite++;
        !          2929:                                break;
        !          2930:                        case IPPROTO_UDP:
        !          2931:                                pf_change_ap(saddr, &pd->hdr.udp->uh_sport,
        !          2932:                                    pd->ip_sum, &pd->hdr.udp->uh_sum,
        !          2933:                                    &pd->naddr, nport, 1, af);
        !          2934:                                sport = pd->hdr.udp->uh_sport;
        !          2935:                                rewrite++;
        !          2936:                                break;
        !          2937: #ifdef INET
        !          2938:                        case IPPROTO_ICMP:
        !          2939:                                pf_change_a(&saddr->v4.s_addr, pd->ip_sum,
        !          2940:                                    pd->naddr.v4.s_addr, 0);
        !          2941:                                pd->hdr.icmp->icmp_cksum = pf_cksum_fixup(
        !          2942:                                    pd->hdr.icmp->icmp_cksum, sport, nport, 0);
        !          2943:                                pd->hdr.icmp->icmp_id = nport;
        !          2944:                                m_copyback(m, off, ICMP_MINLEN, pd->hdr.icmp);
        !          2945:                                break;
        !          2946: #endif /* INET */
        !          2947: #ifdef INET6
        !          2948:                        case IPPROTO_ICMPV6:
        !          2949:                                pf_change_a6(saddr, &pd->hdr.icmp6->icmp6_cksum,
        !          2950:                                    &pd->naddr, 0);
        !          2951:                                rewrite++;
        !          2952:                                break;
        !          2953: #endif /* INET */
        !          2954:                        default:
        !          2955:                                switch (af) {
        !          2956: #ifdef INET
        !          2957:                                case AF_INET:
        !          2958:                                        pf_change_a(&saddr->v4.s_addr,
        !          2959:                                            pd->ip_sum, pd->naddr.v4.s_addr, 0);
        !          2960:                                        break;
        !          2961: #endif /* INET */
        !          2962: #ifdef INET6
        !          2963:                                case AF_INET6:
        !          2964:                                        PF_ACPY(saddr, &pd->naddr, af);
        !          2965:                                        break;
        !          2966: #endif /* INET */
        !          2967:                                }
        !          2968:                                break;
        !          2969:                        }
        !          2970:
        !          2971:                        if (nr->natpass)
        !          2972:                                r = NULL;
        !          2973:                        pd->nat_rule = nr;
        !          2974:                }
        !          2975:        } else {
        !          2976:                bport = nport = dport;
        !          2977:                /* check incoming packet for BINAT/RDR */
        !          2978:                if ((nr = pf_get_translation(pd, m, off, PF_IN, kif, &nsn,
        !          2979:                    saddr, sport, daddr, dport, &pd->naddr, &nport)) != NULL) {
        !          2980:                        PF_ACPY(&pd->baddr, daddr, af);
        !          2981:                        switch (pd->proto) {
        !          2982:                        case IPPROTO_TCP:
        !          2983:                                pf_change_ap(daddr, &th->th_dport, pd->ip_sum,
        !          2984:                                    &th->th_sum, &pd->naddr, nport, 0, af);
        !          2985:                                dport = th->th_dport;
        !          2986:                                rewrite++;
        !          2987:                                break;
        !          2988:                        case IPPROTO_UDP:
        !          2989:                                pf_change_ap(daddr, &pd->hdr.udp->uh_dport,
        !          2990:                                    pd->ip_sum, &pd->hdr.udp->uh_sum,
        !          2991:                                    &pd->naddr, nport, 1, af);
        !          2992:                                dport = pd->hdr.udp->uh_dport;
        !          2993:                                rewrite++;
        !          2994:                                break;
        !          2995: #ifdef INET
        !          2996:                        case IPPROTO_ICMP:
        !          2997:                                pf_change_a(&daddr->v4.s_addr, pd->ip_sum,
        !          2998:                                    pd->naddr.v4.s_addr, 0);
        !          2999:                                break;
        !          3000: #endif /* INET */
        !          3001: #ifdef INET6
        !          3002:                        case IPPROTO_ICMPV6:
        !          3003:                                pf_change_a6(daddr, &pd->hdr.icmp6->icmp6_cksum,
        !          3004:                                    &pd->naddr, 0);
        !          3005:                                rewrite++;
        !          3006:                                break;
        !          3007: #endif /* INET6 */
        !          3008:                        default:
        !          3009:                                switch (af) {
        !          3010: #ifdef INET
        !          3011:                                case AF_INET:
        !          3012:                                        pf_change_a(&daddr->v4.s_addr,
        !          3013:                                            pd->ip_sum, pd->naddr.v4.s_addr, 0);
        !          3014:                                        break;
        !          3015: #endif /* INET */
        !          3016: #ifdef INET6
        !          3017:                                case AF_INET6:
        !          3018:                                        PF_ACPY(daddr, &pd->naddr, af);
        !          3019:                                        break;
        !          3020: #endif /* INET */
        !          3021:                                }
        !          3022:                                break;
        !          3023:                        }
        !          3024:
        !          3025:                        if (nr->natpass)
        !          3026:                                r = NULL;
        !          3027:                        pd->nat_rule = nr;
        !          3028:                }
        !          3029:        }
        !          3030:
        !          3031:        while (r != NULL) {
        !          3032:                r->evaluations++;
        !          3033:                if (pfi_kif_match(r->kif, kif) == r->ifnot)
        !          3034:                        r = r->skip[PF_SKIP_IFP].ptr;
        !          3035:                else if (r->direction && r->direction != direction)
        !          3036:                        r = r->skip[PF_SKIP_DIR].ptr;
        !          3037:                else if (r->af && r->af != af)
        !          3038:                        r = r->skip[PF_SKIP_AF].ptr;
        !          3039:                else if (r->proto && r->proto != pd->proto)
        !          3040:                        r = r->skip[PF_SKIP_PROTO].ptr;
        !          3041:                else if (PF_MISMATCHAW(&r->src.addr, saddr, af,
        !          3042:                    r->src.neg, kif))
        !          3043:                        r = r->skip[PF_SKIP_SRC_ADDR].ptr;
        !          3044:                /* tcp/udp only. port_op always 0 in other cases */
        !          3045:                else if (r->src.port_op && !pf_match_port(r->src.port_op,
        !          3046:                    r->src.port[0], r->src.port[1], sport))
        !          3047:                        r = r->skip[PF_SKIP_SRC_PORT].ptr;
        !          3048:                else if (PF_MISMATCHAW(&r->dst.addr, daddr, af,
        !          3049:                    r->dst.neg, NULL))
        !          3050:                        r = r->skip[PF_SKIP_DST_ADDR].ptr;
        !          3051:                /* tcp/udp only. port_op always 0 in other cases */
        !          3052:                else if (r->dst.port_op && !pf_match_port(r->dst.port_op,
        !          3053:                    r->dst.port[0], r->dst.port[1], dport))
        !          3054:                        r = r->skip[PF_SKIP_DST_PORT].ptr;
        !          3055:                /* icmp only. type always 0 in other cases */
        !          3056:                else if (r->type && r->type != icmptype + 1)
        !          3057:                        r = TAILQ_NEXT(r, entries);
        !          3058:                /* icmp only. type always 0 in other cases */
        !          3059:                else if (r->code && r->code != icmpcode + 1)
        !          3060:                        r = TAILQ_NEXT(r, entries);
        !          3061:                else if (r->tos && !(r->tos == pd->tos))
        !          3062:                        r = TAILQ_NEXT(r, entries);
        !          3063:                else if (r->rule_flag & PFRULE_FRAGMENT)
        !          3064:                        r = TAILQ_NEXT(r, entries);
        !          3065:                else if (pd->proto == IPPROTO_TCP &&
        !          3066:                    (r->flagset & th->th_flags) != r->flags)
        !          3067:                        r = TAILQ_NEXT(r, entries);
        !          3068:                /* tcp/udp only. uid.op always 0 in other cases */
        !          3069:                else if (r->uid.op && (pd->lookup.done || (pd->lookup.done =
        !          3070:                    pf_socket_lookup(direction, pd), 1)) &&
        !          3071:                    !pf_match_uid(r->uid.op, r->uid.uid[0], r->uid.uid[1],
        !          3072:                    pd->lookup.uid))
        !          3073:                        r = TAILQ_NEXT(r, entries);
        !          3074:                /* tcp/udp only. gid.op always 0 in other cases */
        !          3075:                else if (r->gid.op && (pd->lookup.done || (pd->lookup.done =
        !          3076:                    pf_socket_lookup(direction, pd), 1)) &&
        !          3077:                    !pf_match_gid(r->gid.op, r->gid.gid[0], r->gid.gid[1],
        !          3078:                    pd->lookup.gid))
        !          3079:                        r = TAILQ_NEXT(r, entries);
        !          3080:                else if (r->prob && r->prob <= arc4random())
        !          3081:                        r = TAILQ_NEXT(r, entries);
        !          3082:                else if (r->match_tag && !pf_match_tag(m, r, &tag))
        !          3083:                        r = TAILQ_NEXT(r, entries);
        !          3084:                else if (r->os_fingerprint != PF_OSFP_ANY &&
        !          3085:                    (pd->proto != IPPROTO_TCP || !pf_osfp_match(
        !          3086:                    pf_osfp_fingerprint(pd, m, off, th),
        !          3087:                    r->os_fingerprint)))
        !          3088:                        r = TAILQ_NEXT(r, entries);
        !          3089:                else {
        !          3090:                        if (r->tag)
        !          3091:                                tag = r->tag;
        !          3092:                        if (r->rtableid >= 0)
        !          3093:                                rtableid = r->rtableid;
        !          3094:                        if (r->anchor == NULL) {
        !          3095:                                match = 1;
        !          3096:                                *rm = r;
        !          3097:                                *am = a;
        !          3098:                                *rsm = ruleset;
        !          3099:                                if ((*rm)->quick)
        !          3100:                                        break;
        !          3101:                                r = TAILQ_NEXT(r, entries);
        !          3102:                        } else
        !          3103:                                pf_step_into_anchor(&asd, &ruleset,
        !          3104:                                    PF_RULESET_FILTER, &r, &a, &match);
        !          3105:                }
        !          3106:                if (r == NULL && pf_step_out_of_anchor(&asd, &ruleset,
        !          3107:                    PF_RULESET_FILTER, &r, &a, &match))
        !          3108:                        break;
        !          3109:        }
        !          3110:        r = *rm;
        !          3111:        a = *am;
        !          3112:        ruleset = *rsm;
        !          3113:
        !          3114:        REASON_SET(&reason, PFRES_MATCH);
        !          3115:
        !          3116:        if (r->log || (nr != NULL && nr->log)) {
        !          3117:                if (rewrite)
        !          3118:                        m_copyback(m, off, hdrlen, pd->hdr.any);
        !          3119:                PFLOG_PACKET(kif, h, m, af, direction, reason, r->log ? r : nr,
        !          3120:                    a, ruleset, pd);
        !          3121:        }
        !          3122:
        !          3123:        if ((r->action == PF_DROP) &&
        !          3124:            ((r->rule_flag & PFRULE_RETURNRST) ||
        !          3125:            (r->rule_flag & PFRULE_RETURNICMP) ||
        !          3126:            (r->rule_flag & PFRULE_RETURN))) {
        !          3127:                /* undo NAT changes, if they have taken place */
        !          3128:                if (nr != NULL) {
        !          3129:                        if (direction == PF_OUT) {
        !          3130:                                switch (pd->proto) {
        !          3131:                                case IPPROTO_TCP:
        !          3132:                                        pf_change_ap(saddr, &th->th_sport,
        !          3133:                                            pd->ip_sum, &th->th_sum,
        !          3134:                                            &pd->baddr, bport, 0, af);
        !          3135:                                        sport = th->th_sport;
        !          3136:                                        rewrite++;
        !          3137:                                        break;
        !          3138:                                case IPPROTO_UDP:
        !          3139:                                        pf_change_ap(saddr,
        !          3140:                                            &pd->hdr.udp->uh_sport, pd->ip_sum,
        !          3141:                                            &pd->hdr.udp->uh_sum, &pd->baddr,
        !          3142:                                            bport, 1, af);
        !          3143:                                        sport = pd->hdr.udp->uh_sport;
        !          3144:                                        rewrite++;
        !          3145:                                        break;
        !          3146:                                case IPPROTO_ICMP:
        !          3147: #ifdef INET6
        !          3148:                                case IPPROTO_ICMPV6:
        !          3149: #endif
        !          3150:                                        /* nothing! */
        !          3151:                                        break;
        !          3152:                                default:
        !          3153:                                        switch (af) {
        !          3154:                                        case AF_INET:
        !          3155:                                                pf_change_a(&saddr->v4.s_addr,
        !          3156:                                                    pd->ip_sum,
        !          3157:                                                    pd->baddr.v4.s_addr, 0);
        !          3158:                                                break;
        !          3159:                                        case AF_INET6:
        !          3160:                                                PF_ACPY(saddr, &pd->baddr, af);
        !          3161:                                                break;
        !          3162:                                        }
        !          3163:                                }
        !          3164:                        } else {
        !          3165:                                switch (pd->proto) {
        !          3166:                                case IPPROTO_TCP:
        !          3167:                                        pf_change_ap(daddr, &th->th_dport,
        !          3168:                                            pd->ip_sum, &th->th_sum,
        !          3169:                                            &pd->baddr, bport, 0, af);
        !          3170:                                        dport = th->th_dport;
        !          3171:                                        rewrite++;
        !          3172:                                        break;
        !          3173:                                case IPPROTO_UDP:
        !          3174:                                        pf_change_ap(daddr,
        !          3175:                                            &pd->hdr.udp->uh_dport, pd->ip_sum,
        !          3176:                                            &pd->hdr.udp->uh_sum, &pd->baddr,
        !          3177:                                            bport, 1, af);
        !          3178:                                        dport = pd->hdr.udp->uh_dport;
        !          3179:                                        rewrite++;
        !          3180:                                        break;
        !          3181:                                case IPPROTO_ICMP:
        !          3182: #ifdef INET6
        !          3183:                                case IPPROTO_ICMPV6:
        !          3184: #endif
        !          3185:                                        /* nothing! */
        !          3186:                                        break;
        !          3187:                                default:
        !          3188:                                        switch (af) {
        !          3189:                                        case AF_INET:
        !          3190:                                                pf_change_a(&daddr->v4.s_addr,
        !          3191:                                                    pd->ip_sum,
        !          3192:                                                    pd->baddr.v4.s_addr, 0);
        !          3193:                                                break;
        !          3194:                                        case AF_INET6:
        !          3195:                                                PF_ACPY(daddr, &pd->baddr, af);
        !          3196:                                                break;
        !          3197:                                        }
        !          3198:                                }
        !          3199:                        }
        !          3200:                }
        !          3201:                if (pd->proto == IPPROTO_TCP &&
        !          3202:                    ((r->rule_flag & PFRULE_RETURNRST) ||
        !          3203:                    (r->rule_flag & PFRULE_RETURN)) &&
        !          3204:                    !(th->th_flags & TH_RST)) {
        !          3205:                        u_int32_t        ack = ntohl(th->th_seq) + pd->p_len;
        !          3206:                        struct ip       *h = mtod(m, struct ip *);
        !          3207:
        !          3208:                        if (pf_check_proto_cksum(m, off,
        !          3209:                            ntohs(h->ip_len) - off, IPPROTO_TCP, AF_INET))
        !          3210:                                REASON_SET(&reason, PFRES_PROTCKSUM);
        !          3211:                        else {
        !          3212:                                if (th->th_flags & TH_SYN)
        !          3213:                                        ack++;
        !          3214:                                if (th->th_flags & TH_FIN)
        !          3215:                                        ack++;
        !          3216:                                pf_send_tcp(r, af, pd->dst,
        !          3217:                                    pd->src, th->th_dport, th->th_sport,
        !          3218:                                    ntohl(th->th_ack), ack, TH_RST|TH_ACK, 0, 0,
        !          3219:                                    r->return_ttl, 1, 0, pd->eh, kif->pfik_ifp);
        !          3220:                        }
        !          3221:                } else if ((af == AF_INET) && r->return_icmp)
        !          3222:                        pf_send_icmp(m, r->return_icmp >> 8,
        !          3223:                            r->return_icmp & 255, af, r);
        !          3224:                else if ((af == AF_INET6) && r->return_icmp6)
        !          3225:                        pf_send_icmp(m, r->return_icmp6 >> 8,
        !          3226:                            r->return_icmp6 & 255, af, r);
        !          3227:        }
        !          3228:
        !          3229:        if (r->action == PF_DROP)
        !          3230:                return (PF_DROP);
        !          3231:
        !          3232:        if (pf_tag_packet(m, tag, rtableid)) {
        !          3233:                REASON_SET(&reason, PFRES_MEMORY);
        !          3234:                return (PF_DROP);
        !          3235:        }
        !          3236:
        !          3237:        if (!state_icmp && (r->keep_state || nr != NULL ||
        !          3238:            (pd->flags & PFDESC_TCP_NORM))) {
        !          3239:                /* create new state */
        !          3240:                u_int16_t        len;
        !          3241:                struct pf_state *s = NULL;
        !          3242:                struct pf_state_key *sk = NULL;
        !          3243:                struct pf_src_node *sn = NULL;
        !          3244:
        !          3245:                /* check maximums */
        !          3246:                if (r->max_states && (r->states >= r->max_states)) {
        !          3247:                        pf_status.lcounters[LCNT_STATES]++;
        !          3248:                        REASON_SET(&reason, PFRES_MAXSTATES);
        !          3249:                        goto cleanup;
        !          3250:                }
        !          3251:                /* src node for filter rule */
        !          3252:                if ((r->rule_flag & PFRULE_SRCTRACK ||
        !          3253:                    r->rpool.opts & PF_POOL_STICKYADDR) &&
        !          3254:                    pf_insert_src_node(&sn, r, saddr, af) != 0) {
        !          3255:                        REASON_SET(&reason, PFRES_SRCLIMIT);
        !          3256:                        goto cleanup;
        !          3257:                }
        !          3258:                /* src node for translation rule */
        !          3259:                if (nr != NULL && (nr->rpool.opts & PF_POOL_STICKYADDR) &&
        !          3260:                    ((direction == PF_OUT &&
        !          3261:                    pf_insert_src_node(&nsn, nr, &pd->baddr, af) != 0) ||
        !          3262:                    (pf_insert_src_node(&nsn, nr, saddr, af) != 0))) {
        !          3263:                        REASON_SET(&reason, PFRES_SRCLIMIT);
        !          3264:                        goto cleanup;
        !          3265:                }
        !          3266:                s = pool_get(&pf_state_pl, PR_NOWAIT);
        !          3267:                if (s == NULL) {
        !          3268:                        REASON_SET(&reason, PFRES_MEMORY);
        !          3269: cleanup:
        !          3270:                        if (sn != NULL && sn->states == 0 && sn->expire == 0) {
        !          3271:                                RB_REMOVE(pf_src_tree, &tree_src_tracking, sn);
        !          3272:                                pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
        !          3273:                                pf_status.src_nodes--;
        !          3274:                                pool_put(&pf_src_tree_pl, sn);
        !          3275:                        }
        !          3276:                        if (nsn != sn && nsn != NULL && nsn->states == 0 &&
        !          3277:                            nsn->expire == 0) {
        !          3278:                                RB_REMOVE(pf_src_tree, &tree_src_tracking, nsn);
        !          3279:                                pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
        !          3280:                                pf_status.src_nodes--;
        !          3281:                                pool_put(&pf_src_tree_pl, nsn);
        !          3282:                        }
        !          3283:                        if (sk != NULL) {
        !          3284:                                pool_put(&pf_state_key_pl, sk);
        !          3285:                        }
        !          3286:                        return (PF_DROP);
        !          3287:                }
        !          3288:                bzero(s, sizeof(*s));
        !          3289:                s->rule.ptr = r;
        !          3290:                s->nat_rule.ptr = nr;
        !          3291:                s->anchor.ptr = a;
        !          3292:                STATE_INC_COUNTERS(s);
        !          3293:                s->allow_opts = r->allow_opts;
        !          3294:                s->log = r->log & PF_LOG_ALL;
        !          3295:                if (nr != NULL)
        !          3296:                        s->log |= nr->log & PF_LOG_ALL;
        !          3297:                switch (pd->proto) {
        !          3298:                case IPPROTO_TCP:
        !          3299:                        len = pd->tot_len - off - (th->th_off << 2);
        !          3300:                        s->src.seqlo = ntohl(th->th_seq);
        !          3301:                        s->src.seqhi = s->src.seqlo + len + 1;
        !          3302:                        if ((th->th_flags & (TH_SYN|TH_ACK)) ==
        !          3303:                        TH_SYN && r->keep_state == PF_STATE_MODULATE) {
        !          3304:                                /* Generate sequence number modulator */
        !          3305:                                while ((s->src.seqdiff =
        !          3306:                                    tcp_rndiss_next() - s->src.seqlo) == 0)
        !          3307:                                        ;
        !          3308:                                pf_change_a(&th->th_seq, &th->th_sum,
        !          3309:                                    htonl(s->src.seqlo + s->src.seqdiff), 0);
        !          3310:                                rewrite = 1;
        !          3311:                        } else
        !          3312:                                s->src.seqdiff = 0;
        !          3313:                        if (th->th_flags & TH_SYN) {
        !          3314:                                s->src.seqhi++;
        !          3315:                                s->src.wscale = pf_get_wscale(m, off,
        !          3316:                                    th->th_off, af);
        !          3317:                        }
        !          3318:                        s->src.max_win = MAX(ntohs(th->th_win), 1);
        !          3319:                        if (s->src.wscale & PF_WSCALE_MASK) {
        !          3320:                                /* Remove scale factor from initial window */
        !          3321:                                int win = s->src.max_win;
        !          3322:                                win += 1 << (s->src.wscale & PF_WSCALE_MASK);
        !          3323:                                s->src.max_win = (win - 1) >>
        !          3324:                                    (s->src.wscale & PF_WSCALE_MASK);
        !          3325:                        }
        !          3326:                        if (th->th_flags & TH_FIN)
        !          3327:                                s->src.seqhi++;
        !          3328:                        s->dst.seqhi = 1;
        !          3329:                        s->dst.max_win = 1;
        !          3330:                        s->src.state = TCPS_SYN_SENT;
        !          3331:                        s->dst.state = TCPS_CLOSED;
        !          3332:                        s->timeout = PFTM_TCP_FIRST_PACKET;
        !          3333:                        break;
        !          3334:                case IPPROTO_UDP:
        !          3335:                        s->src.state = PFUDPS_SINGLE;
        !          3336:                        s->dst.state = PFUDPS_NO_TRAFFIC;
        !          3337:                        s->timeout = PFTM_UDP_FIRST_PACKET;
        !          3338:                        break;
        !          3339:                case IPPROTO_ICMP:
        !          3340: #ifdef INET6
        !          3341:                case IPPROTO_ICMPV6:
        !          3342: #endif
        !          3343:                        s->timeout = PFTM_ICMP_FIRST_PACKET;
        !          3344:                        break;
        !          3345:                default:
        !          3346:                        s->src.state = PFOTHERS_SINGLE;
        !          3347:                        s->dst.state = PFOTHERS_NO_TRAFFIC;
        !          3348:                        s->timeout = PFTM_OTHER_FIRST_PACKET;
        !          3349:                }
        !          3350:
        !          3351:                s->creation = time_second;
        !          3352:                s->expire = time_second;
        !          3353:
        !          3354:                if (sn != NULL) {
        !          3355:                        s->src_node = sn;
        !          3356:                        s->src_node->states++;
        !          3357:                }
        !          3358:                if (nsn != NULL) {
        !          3359:                        PF_ACPY(&nsn->raddr, &pd->naddr, af);
        !          3360:                        s->nat_src_node = nsn;
        !          3361:                        s->nat_src_node->states++;
        !          3362:                }
        !          3363:                if (pd->proto == IPPROTO_TCP) {
        !          3364:                        if ((pd->flags & PFDESC_TCP_NORM) &&
        !          3365:                            pf_normalize_tcp_init(m, off, pd, th, &s->src,
        !          3366:                            &s->dst)) {
        !          3367:                                REASON_SET(&reason, PFRES_MEMORY);
        !          3368:                                pf_src_tree_remove_state(s);
        !          3369:                                STATE_DEC_COUNTERS(s);
        !          3370:                                pool_put(&pf_state_pl, s);
        !          3371:                                return (PF_DROP);
        !          3372:                        }
        !          3373:                        if ((pd->flags & PFDESC_TCP_NORM) && s->src.scrub &&
        !          3374:                            pf_normalize_tcp_stateful(m, off, pd, &reason,
        !          3375:                            th, s, &s->src, &s->dst, &rewrite)) {
        !          3376:                                /* This really shouldn't happen!!! */
        !          3377:                                DPFPRINTF(PF_DEBUG_URGENT,
        !          3378:                                    ("pf_normalize_tcp_stateful failed on "
        !          3379:                                    "first pkt"));
        !          3380:                                pf_normalize_tcp_cleanup(s);
        !          3381:                                pf_src_tree_remove_state(s);
        !          3382:                                STATE_DEC_COUNTERS(s);
        !          3383:                                pool_put(&pf_state_pl, s);
        !          3384:                                return (PF_DROP);
        !          3385:                        }
        !          3386:                }
        !          3387:
        !          3388:                if ((sk = pf_alloc_state_key(s)) == NULL) {
        !          3389:                        REASON_SET(&reason, PFRES_MEMORY);
        !          3390:                        goto cleanup;
        !          3391:                }
        !          3392:
        !          3393:                sk->proto = pd->proto;
        !          3394:                sk->direction = direction;
        !          3395:                sk->af = af;
        !          3396:                if (direction == PF_OUT) {
        !          3397:                        PF_ACPY(&sk->gwy.addr, saddr, af);
        !          3398:                        PF_ACPY(&sk->ext.addr, daddr, af);
        !          3399:                        switch (pd->proto) {
        !          3400:                        case IPPROTO_ICMP:
        !          3401: #ifdef INET6
        !          3402:                        case IPPROTO_ICMPV6:
        !          3403: #endif
        !          3404:                                sk->gwy.port = nport;
        !          3405:                                sk->ext.port = 0;
        !          3406:                                break;
        !          3407:                        default:
        !          3408:                                sk->gwy.port = sport;
        !          3409:                                sk->ext.port = dport;
        !          3410:                        }
        !          3411:                        if (nr != NULL) {
        !          3412:                                PF_ACPY(&sk->lan.addr, &pd->baddr, af);
        !          3413:                                sk->lan.port = bport;
        !          3414:                        } else {
        !          3415:                                PF_ACPY(&sk->lan.addr, &sk->gwy.addr, af);
        !          3416:                                sk->lan.port = sk->gwy.port;
        !          3417:                        }
        !          3418:                } else {
        !          3419:                        PF_ACPY(&sk->lan.addr, daddr, af);
        !          3420:                        PF_ACPY(&sk->ext.addr, saddr, af);
        !          3421:                        switch (pd->proto) {
        !          3422:                        case IPPROTO_ICMP:
        !          3423: #ifdef INET6
        !          3424:                        case IPPROTO_ICMPV6:
        !          3425: #endif
        !          3426:                                sk->lan.port = nport;
        !          3427:                                sk->ext.port = 0;
        !          3428:                                break;
        !          3429:                        default:
        !          3430:                                sk->lan.port = dport;
        !          3431:                                sk->ext.port = sport;
        !          3432:                        }
        !          3433:                        if (nr != NULL) {
        !          3434:                                PF_ACPY(&sk->gwy.addr, &pd->baddr, af);
        !          3435:                                sk->gwy.port = bport;
        !          3436:                        } else {
        !          3437:                                PF_ACPY(&sk->gwy.addr, &sk->lan.addr, af);
        !          3438:                                sk->gwy.port = sk->lan.port;
        !          3439:                        }
        !          3440:                }
        !          3441:
        !          3442:                pf_set_rt_ifp(s, saddr);        /* needs s->state_key set */
        !          3443:
        !          3444:                if (pf_insert_state(BOUND_IFACE(r, kif), s)) {
        !          3445:                        if (pd->proto == IPPROTO_TCP)
        !          3446:                                pf_normalize_tcp_cleanup(s);
        !          3447:                        REASON_SET(&reason, PFRES_STATEINS);
        !          3448:                        pf_src_tree_remove_state(s);
        !          3449:                        STATE_DEC_COUNTERS(s);
        !          3450:                        pool_put(&pf_state_pl, s);
        !          3451:                        return (PF_DROP);
        !          3452:                } else
        !          3453:                        *sm = s;
        !          3454:                if (tag > 0) {
        !          3455:                        pf_tag_ref(tag);
        !          3456:                        s->tag = tag;
        !          3457:                }
        !          3458:                if (pd->proto == IPPROTO_TCP &&
        !          3459:                    (th->th_flags & (TH_SYN|TH_ACK)) == TH_SYN &&
        !          3460:                    r->keep_state == PF_STATE_SYNPROXY) {
        !          3461:                        s->src.state = PF_TCPS_PROXY_SRC;
        !          3462:                        if (nr != NULL) {
        !          3463:                                if (direction == PF_OUT) {
        !          3464:                                        pf_change_ap(saddr, &th->th_sport,
        !          3465:                                            pd->ip_sum, &th->th_sum, &pd->baddr,
        !          3466:                                            bport, 0, af);
        !          3467:                                        sport = th->th_sport;
        !          3468:                                } else {
        !          3469:                                        pf_change_ap(daddr, &th->th_dport,
        !          3470:                                            pd->ip_sum, &th->th_sum, &pd->baddr,
        !          3471:                                            bport, 0, af);
        !          3472:                                        sport = th->th_dport;
        !          3473:                                }
        !          3474:                        }
        !          3475:                        s->src.seqhi = htonl(arc4random());
        !          3476:                        /* Find mss option */
        !          3477:                        mss = pf_get_mss(m, off, th->th_off, af);
        !          3478:                        mss = pf_calc_mss(saddr, af, mss);
        !          3479:                        mss = pf_calc_mss(daddr, af, mss);
        !          3480:                        s->src.mss = mss;
        !          3481:                        pf_send_tcp(r, af, daddr, saddr, th->th_dport,
        !          3482:                            th->th_sport, s->src.seqhi, ntohl(th->th_seq) + 1,
        !          3483:                            TH_SYN|TH_ACK, 0, s->src.mss, 0, 1, 0, NULL, NULL);
        !          3484:                        REASON_SET(&reason, PFRES_SYNPROXY);
        !          3485:                        return (PF_SYNPROXY_DROP);
        !          3486:                }
        !          3487:        }
        !          3488:
        !          3489:        /* copy back packet headers if we performed NAT operations */
        !          3490:        if (rewrite)
        !          3491:                m_copyback(m, off, hdrlen, pd->hdr.any);
        !          3492:
        !          3493:        return (PF_PASS);
        !          3494: }
        !          3495:
        !          3496: int
        !          3497: pf_test_fragment(struct pf_rule **rm, int direction, struct pfi_kif *kif,
        !          3498:     struct mbuf *m, void *h, struct pf_pdesc *pd, struct pf_rule **am,
        !          3499:     struct pf_ruleset **rsm)
        !          3500: {
        !          3501:        struct pf_rule          *r, *a = NULL;
        !          3502:        struct pf_ruleset       *ruleset = NULL;
        !          3503:        sa_family_t              af = pd->af;
        !          3504:        u_short                  reason;
        !          3505:        int                      tag = -1;
        !          3506:        int                      asd = 0;
        !          3507:        int                      match = 0;
        !          3508:
        !          3509:        r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_FILTER].active.ptr);
        !          3510:        while (r != NULL) {
        !          3511:                r->evaluations++;
        !          3512:                if (pfi_kif_match(r->kif, kif) == r->ifnot)
        !          3513:                        r = r->skip[PF_SKIP_IFP].ptr;
        !          3514:                else if (r->direction && r->direction != direction)
        !          3515:                        r = r->skip[PF_SKIP_DIR].ptr;
        !          3516:                else if (r->af && r->af != af)
        !          3517:                        r = r->skip[PF_SKIP_AF].ptr;
        !          3518:                else if (r->proto && r->proto != pd->proto)
        !          3519:                        r = r->skip[PF_SKIP_PROTO].ptr;
        !          3520:                else if (PF_MISMATCHAW(&r->src.addr, pd->src, af,
        !          3521:                    r->src.neg, kif))
        !          3522:                        r = r->skip[PF_SKIP_SRC_ADDR].ptr;
        !          3523:                else if (PF_MISMATCHAW(&r->dst.addr, pd->dst, af,
        !          3524:                    r->dst.neg, NULL))
        !          3525:                        r = r->skip[PF_SKIP_DST_ADDR].ptr;
        !          3526:                else if (r->tos && !(r->tos == pd->tos))
        !          3527:                        r = TAILQ_NEXT(r, entries);
        !          3528:                else if (r->src.port_op || r->dst.port_op ||
        !          3529:                    r->flagset || r->type || r->code ||
        !          3530:                    r->os_fingerprint != PF_OSFP_ANY)
        !          3531:                        r = TAILQ_NEXT(r, entries);
        !          3532:                else if (r->prob && r->prob <= arc4random())
        !          3533:                        r = TAILQ_NEXT(r, entries);
        !          3534:                else if (r->match_tag && !pf_match_tag(m, r, &tag))
        !          3535:                        r = TAILQ_NEXT(r, entries);
        !          3536:                else {
        !          3537:                        if (r->anchor == NULL) {
        !          3538:                                match = 1;
        !          3539:                                *rm = r;
        !          3540:                                *am = a;
        !          3541:                                *rsm = ruleset;
        !          3542:                                if ((*rm)->quick)
        !          3543:                                        break;
        !          3544:                                r = TAILQ_NEXT(r, entries);
        !          3545:                        } else
        !          3546:                                pf_step_into_anchor(&asd, &ruleset,
        !          3547:                                    PF_RULESET_FILTER, &r, &a, &match);
        !          3548:                }
        !          3549:                if (r == NULL && pf_step_out_of_anchor(&asd, &ruleset,
        !          3550:                    PF_RULESET_FILTER, &r, &a, &match))
        !          3551:                        break;
        !          3552:        }
        !          3553:        r = *rm;
        !          3554:        a = *am;
        !          3555:        ruleset = *rsm;
        !          3556:
        !          3557:        REASON_SET(&reason, PFRES_MATCH);
        !          3558:
        !          3559:        if (r->log)
        !          3560:                PFLOG_PACKET(kif, h, m, af, direction, reason, r, a, ruleset,
        !          3561:                    pd);
        !          3562:
        !          3563:        if (r->action != PF_PASS)
        !          3564:                return (PF_DROP);
        !          3565:
        !          3566:        if (pf_tag_packet(m, tag, -1)) {
        !          3567:                REASON_SET(&reason, PFRES_MEMORY);
        !          3568:                return (PF_DROP);
        !          3569:        }
        !          3570:
        !          3571:        return (PF_PASS);
        !          3572: }
        !          3573:
        !          3574: int
        !          3575: pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif,
        !          3576:     struct mbuf *m, int off, void *h, struct pf_pdesc *pd,
        !          3577:     u_short *reason)
        !          3578: {
        !          3579:        struct pf_state_key_cmp  key;
        !          3580:        struct tcphdr           *th = pd->hdr.tcp;
        !          3581:        u_int16_t                win = ntohs(th->th_win);
        !          3582:        u_int32_t                ack, end, seq, orig_seq;
        !          3583:        u_int8_t                 sws, dws;
        !          3584:        int                      ackskew;
        !          3585:        int                      copyback = 0;
        !          3586:        struct pf_state_peer    *src, *dst;
        !          3587:
        !          3588:        key.af = pd->af;
        !          3589:        key.proto = IPPROTO_TCP;
        !          3590:        if (direction == PF_IN) {
        !          3591:                PF_ACPY(&key.ext.addr, pd->src, key.af);
        !          3592:                PF_ACPY(&key.gwy.addr, pd->dst, key.af);
        !          3593:                key.ext.port = th->th_sport;
        !          3594:                key.gwy.port = th->th_dport;
        !          3595:        } else {
        !          3596:                PF_ACPY(&key.lan.addr, pd->src, key.af);
        !          3597:                PF_ACPY(&key.ext.addr, pd->dst, key.af);
        !          3598:                key.lan.port = th->th_sport;
        !          3599:                key.ext.port = th->th_dport;
        !          3600:        }
        !          3601:
        !          3602:        STATE_LOOKUP();
        !          3603:
        !          3604:        if (direction == (*state)->state_key->direction) {
        !          3605:                src = &(*state)->src;
        !          3606:                dst = &(*state)->dst;
        !          3607:        } else {
        !          3608:                src = &(*state)->dst;
        !          3609:                dst = &(*state)->src;
        !          3610:        }
        !          3611:
        !          3612:        if ((*state)->src.state == PF_TCPS_PROXY_SRC) {
        !          3613:                if (direction != (*state)->state_key->direction) {
        !          3614:                        REASON_SET(reason, PFRES_SYNPROXY);
        !          3615:                        return (PF_SYNPROXY_DROP);
        !          3616:                }
        !          3617:                if (th->th_flags & TH_SYN) {
        !          3618:                        if (ntohl(th->th_seq) != (*state)->src.seqlo) {
        !          3619:                                REASON_SET(reason, PFRES_SYNPROXY);
        !          3620:                                return (PF_DROP);
        !          3621:                        }
        !          3622:                        pf_send_tcp((*state)->rule.ptr, pd->af, pd->dst,
        !          3623:                            pd->src, th->th_dport, th->th_sport,
        !          3624:                            (*state)->src.seqhi, ntohl(th->th_seq) + 1,
        !          3625:                            TH_SYN|TH_ACK, 0, (*state)->src.mss, 0, 1,
        !          3626:                            0, NULL, NULL);
        !          3627:                        REASON_SET(reason, PFRES_SYNPROXY);
        !          3628:                        return (PF_SYNPROXY_DROP);
        !          3629:                } else if (!(th->th_flags & TH_ACK) ||
        !          3630:                    (ntohl(th->th_ack) != (*state)->src.seqhi + 1) ||
        !          3631:                    (ntohl(th->th_seq) != (*state)->src.seqlo + 1)) {
        !          3632:                        REASON_SET(reason, PFRES_SYNPROXY);
        !          3633:                        return (PF_DROP);
        !          3634:                } else if ((*state)->src_node != NULL &&
        !          3635:                    pf_src_connlimit(state)) {
        !          3636:                        REASON_SET(reason, PFRES_SRCLIMIT);
        !          3637:                        return (PF_DROP);
        !          3638:                } else
        !          3639:                        (*state)->src.state = PF_TCPS_PROXY_DST;
        !          3640:        }
        !          3641:        if ((*state)->src.state == PF_TCPS_PROXY_DST) {
        !          3642:                struct pf_state_host *src, *dst;
        !          3643:
        !          3644:                if (direction == PF_OUT) {
        !          3645:                        src = &(*state)->state_key->gwy;
        !          3646:                        dst = &(*state)->state_key->ext;
        !          3647:                } else {
        !          3648:                        src = &(*state)->state_key->ext;
        !          3649:                        dst = &(*state)->state_key->lan;
        !          3650:                }
        !          3651:                if (direction == (*state)->state_key->direction) {
        !          3652:                        if (((th->th_flags & (TH_SYN|TH_ACK)) != TH_ACK) ||
        !          3653:                            (ntohl(th->th_ack) != (*state)->src.seqhi + 1) ||
        !          3654:                            (ntohl(th->th_seq) != (*state)->src.seqlo + 1)) {
        !          3655:                                REASON_SET(reason, PFRES_SYNPROXY);
        !          3656:                                return (PF_DROP);
        !          3657:                        }
        !          3658:                        (*state)->src.max_win = MAX(ntohs(th->th_win), 1);
        !          3659:                        if ((*state)->dst.seqhi == 1)
        !          3660:                                (*state)->dst.seqhi = htonl(arc4random());
        !          3661:                        pf_send_tcp((*state)->rule.ptr, pd->af, &src->addr,
        !          3662:                            &dst->addr, src->port, dst->port,
        !          3663:                            (*state)->dst.seqhi, 0, TH_SYN, 0,
        !          3664:                            (*state)->src.mss, 0, 0, (*state)->tag, NULL, NULL);
        !          3665:                        REASON_SET(reason, PFRES_SYNPROXY);
        !          3666:                        return (PF_SYNPROXY_DROP);
        !          3667:                } else if (((th->th_flags & (TH_SYN|TH_ACK)) !=
        !          3668:                    (TH_SYN|TH_ACK)) ||
        !          3669:                    (ntohl(th->th_ack) != (*state)->dst.seqhi + 1)) {
        !          3670:                        REASON_SET(reason, PFRES_SYNPROXY);
        !          3671:                        return (PF_DROP);
        !          3672:                } else {
        !          3673:                        (*state)->dst.max_win = MAX(ntohs(th->th_win), 1);
        !          3674:                        (*state)->dst.seqlo = ntohl(th->th_seq);
        !          3675:                        pf_send_tcp((*state)->rule.ptr, pd->af, pd->dst,
        !          3676:                            pd->src, th->th_dport, th->th_sport,
        !          3677:                            ntohl(th->th_ack), ntohl(th->th_seq) + 1,
        !          3678:                            TH_ACK, (*state)->src.max_win, 0, 0, 0,
        !          3679:                            (*state)->tag, NULL, NULL);
        !          3680:                        pf_send_tcp((*state)->rule.ptr, pd->af, &src->addr,
        !          3681:                            &dst->addr, src->port, dst->port,
        !          3682:                            (*state)->src.seqhi + 1, (*state)->src.seqlo + 1,
        !          3683:                            TH_ACK, (*state)->dst.max_win, 0, 0, 1,
        !          3684:                            0, NULL, NULL);
        !          3685:                        (*state)->src.seqdiff = (*state)->dst.seqhi -
        !          3686:                            (*state)->src.seqlo;
        !          3687:                        (*state)->dst.seqdiff = (*state)->src.seqhi -
        !          3688:                            (*state)->dst.seqlo;
        !          3689:                        (*state)->src.seqhi = (*state)->src.seqlo +
        !          3690:                            (*state)->dst.max_win;
        !          3691:                        (*state)->dst.seqhi = (*state)->dst.seqlo +
        !          3692:                            (*state)->src.max_win;
        !          3693:                        (*state)->src.wscale = (*state)->dst.wscale = 0;
        !          3694:                        (*state)->src.state = (*state)->dst.state =
        !          3695:                            TCPS_ESTABLISHED;
        !          3696:                        REASON_SET(reason, PFRES_SYNPROXY);
        !          3697:                        return (PF_SYNPROXY_DROP);
        !          3698:                }
        !          3699:        }
        !          3700:
        !          3701:        if (src->wscale && dst->wscale && !(th->th_flags & TH_SYN)) {
        !          3702:                sws = src->wscale & PF_WSCALE_MASK;
        !          3703:                dws = dst->wscale & PF_WSCALE_MASK;
        !          3704:        } else
        !          3705:                sws = dws = 0;
        !          3706:
        !          3707:        /*
        !          3708:         * Sequence tracking algorithm from Guido van Rooij's paper:
        !          3709:         *   http://www.madison-gurkha.com/publications/tcp_filtering/
        !          3710:         *      tcp_filtering.ps
        !          3711:         */
        !          3712:
        !          3713:        orig_seq = seq = ntohl(th->th_seq);
        !          3714:        if (src->seqlo == 0) {
        !          3715:                /* First packet from this end. Set its state */
        !          3716:
        !          3717:                if ((pd->flags & PFDESC_TCP_NORM || dst->scrub) &&
        !          3718:                    src->scrub == NULL) {
        !          3719:                        if (pf_normalize_tcp_init(m, off, pd, th, src, dst)) {
        !          3720:                                REASON_SET(reason, PFRES_MEMORY);
        !          3721:                                return (PF_DROP);
        !          3722:                        }
        !          3723:                }
        !          3724:
        !          3725:                /* Deferred generation of sequence number modulator */
        !          3726:                if (dst->seqdiff && !src->seqdiff) {
        !          3727:                        while ((src->seqdiff = tcp_rndiss_next() - seq) == 0)
        !          3728:                                ;
        !          3729:                        ack = ntohl(th->th_ack) - dst->seqdiff;
        !          3730:                        pf_change_a(&th->th_seq, &th->th_sum, htonl(seq +
        !          3731:                            src->seqdiff), 0);
        !          3732:                        pf_change_a(&th->th_ack, &th->th_sum, htonl(ack), 0);
        !          3733:                        copyback = 1;
        !          3734:                } else {
        !          3735:                        ack = ntohl(th->th_ack);
        !          3736:                }
        !          3737:
        !          3738:                end = seq + pd->p_len;
        !          3739:                if (th->th_flags & TH_SYN) {
        !          3740:                        end++;
        !          3741:                        if (dst->wscale & PF_WSCALE_FLAG) {
        !          3742:                                src->wscale = pf_get_wscale(m, off, th->th_off,
        !          3743:                                    pd->af);
        !          3744:                                if (src->wscale & PF_WSCALE_FLAG) {
        !          3745:                                        /* Remove scale factor from initial
        !          3746:                                         * window */
        !          3747:                                        sws = src->wscale & PF_WSCALE_MASK;
        !          3748:                                        win = ((u_int32_t)win + (1 << sws) - 1)
        !          3749:                                            >> sws;
        !          3750:                                        dws = dst->wscale & PF_WSCALE_MASK;
        !          3751:                                } else {
        !          3752:                                        /* fixup other window */
        !          3753:                                        dst->max_win <<= dst->wscale &
        !          3754:                                            PF_WSCALE_MASK;
        !          3755:                                        /* in case of a retrans SYN|ACK */
        !          3756:                                        dst->wscale = 0;
        !          3757:                                }
        !          3758:                        }
        !          3759:                }
        !          3760:                if (th->th_flags & TH_FIN)
        !          3761:                        end++;
        !          3762:
        !          3763:                src->seqlo = seq;
        !          3764:                if (src->state < TCPS_SYN_SENT)
        !          3765:                        src->state = TCPS_SYN_SENT;
        !          3766:
        !          3767:                /*
        !          3768:                 * May need to slide the window (seqhi may have been set by
        !          3769:                 * the crappy stack check or if we picked up the connection
        !          3770:                 * after establishment)
        !          3771:                 */
        !          3772:                if (src->seqhi == 1 ||
        !          3773:                    SEQ_GEQ(end + MAX(1, dst->max_win << dws), src->seqhi))
        !          3774:                        src->seqhi = end + MAX(1, dst->max_win << dws);
        !          3775:                if (win > src->max_win)
        !          3776:                        src->max_win = win;
        !          3777:
        !          3778:        } else {
        !          3779:                ack = ntohl(th->th_ack) - dst->seqdiff;
        !          3780:                if (src->seqdiff) {
        !          3781:                        /* Modulate sequence numbers */
        !          3782:                        pf_change_a(&th->th_seq, &th->th_sum, htonl(seq +
        !          3783:                            src->seqdiff), 0);
        !          3784:                        pf_change_a(&th->th_ack, &th->th_sum, htonl(ack), 0);
        !          3785:                        copyback = 1;
        !          3786:                }
        !          3787:                end = seq + pd->p_len;
        !          3788:                if (th->th_flags & TH_SYN)
        !          3789:                        end++;
        !          3790:                if (th->th_flags & TH_FIN)
        !          3791:                        end++;
        !          3792:        }
        !          3793:
        !          3794:        if ((th->th_flags & TH_ACK) == 0) {
        !          3795:                /* Let it pass through the ack skew check */
        !          3796:                ack = dst->seqlo;
        !          3797:        } else if ((ack == 0 &&
        !          3798:            (th->th_flags & (TH_ACK|TH_RST)) == (TH_ACK|TH_RST)) ||
        !          3799:            /* broken tcp stacks do not set ack */
        !          3800:            (dst->state < TCPS_SYN_SENT)) {
        !          3801:                /*
        !          3802:                 * Many stacks (ours included) will set the ACK number in an
        !          3803:                 * FIN|ACK if the SYN times out -- no sequence to ACK.
        !          3804:                 */
        !          3805:                ack = dst->seqlo;
        !          3806:        }
        !          3807:
        !          3808:        if (seq == end) {
        !          3809:                /* Ease sequencing restrictions on no data packets */
        !          3810:                seq = src->seqlo;
        !          3811:                end = seq;
        !          3812:        }
        !          3813:
        !          3814:        ackskew = dst->seqlo - ack;
        !          3815:
        !          3816:
        !          3817:        /*
        !          3818:         * Need to demodulate the sequence numbers in any TCP SACK options
        !          3819:         * (Selective ACK). We could optionally validate the SACK values
        !          3820:         * against the current ACK window, either forwards or backwards, but
        !          3821:         * I'm not confident that SACK has been implemented properly
        !          3822:         * everywhere. It wouldn't surprise me if several stacks accidently
        !          3823:         * SACK too far backwards of previously ACKed data. There really aren't
        !          3824:         * any security implications of bad SACKing unless the target stack
        !          3825:         * doesn't validate the option length correctly. Someone trying to
        !          3826:         * spoof into a TCP connection won't bother blindly sending SACK
        !          3827:         * options anyway.
        !          3828:         */
        !          3829:        if (dst->seqdiff && (th->th_off << 2) > sizeof(struct tcphdr)) {
        !          3830:                if (pf_modulate_sack(m, off, pd, th, dst))
        !          3831:                        copyback = 1;
        !          3832:        }
        !          3833:
        !          3834:
        !          3835: #define MAXACKWINDOW (0xffff + 1500)   /* 1500 is an arbitrary fudge factor */
        !          3836:        if (SEQ_GEQ(src->seqhi, end) &&
        !          3837:            /* Last octet inside other's window space */
        !          3838:            SEQ_GEQ(seq, src->seqlo - (dst->max_win << dws)) &&
        !          3839:            /* Retrans: not more than one window back */
        !          3840:            (ackskew >= -MAXACKWINDOW) &&
        !          3841:            /* Acking not more than one reassembled fragment backwards */
        !          3842:            (ackskew <= (MAXACKWINDOW << sws)) &&
        !          3843:            /* Acking not more than one window forward */
        !          3844:            ((th->th_flags & TH_RST) == 0 || orig_seq == src->seqlo ||
        !          3845:            (orig_seq == src->seqlo + 1) || (pd->flags & PFDESC_IP_REAS) == 0)) {
        !          3846:            /* Require an exact/+1 sequence match on resets when possible */
        !          3847:
        !          3848:                if (dst->scrub || src->scrub) {
        !          3849:                        if (pf_normalize_tcp_stateful(m, off, pd, reason, th,
        !          3850:                            *state, src, dst, &copyback))
        !          3851:                                return (PF_DROP);
        !          3852:                }
        !          3853:
        !          3854:                /* update max window */
        !          3855:                if (src->max_win < win)
        !          3856:                        src->max_win = win;
        !          3857:                /* synchronize sequencing */
        !          3858:                if (SEQ_GT(end, src->seqlo))
        !          3859:                        src->seqlo = end;
        !          3860:                /* slide the window of what the other end can send */
        !          3861:                if (SEQ_GEQ(ack + (win << sws), dst->seqhi))
        !          3862:                        dst->seqhi = ack + MAX((win << sws), 1);
        !          3863:
        !          3864:
        !          3865:                /* update states */
        !          3866:                if (th->th_flags & TH_SYN)
        !          3867:                        if (src->state < TCPS_SYN_SENT)
        !          3868:                                src->state = TCPS_SYN_SENT;
        !          3869:                if (th->th_flags & TH_FIN)
        !          3870:                        if (src->state < TCPS_CLOSING)
        !          3871:                                src->state = TCPS_CLOSING;
        !          3872:                if (th->th_flags & TH_ACK) {
        !          3873:                        if (dst->state == TCPS_SYN_SENT) {
        !          3874:                                dst->state = TCPS_ESTABLISHED;
        !          3875:                                if (src->state == TCPS_ESTABLISHED &&
        !          3876:                                    (*state)->src_node != NULL &&
        !          3877:                                    pf_src_connlimit(state)) {
        !          3878:                                        REASON_SET(reason, PFRES_SRCLIMIT);
        !          3879:                                        return (PF_DROP);
        !          3880:                                }
        !          3881:                        } else if (dst->state == TCPS_CLOSING)
        !          3882:                                dst->state = TCPS_FIN_WAIT_2;
        !          3883:                }
        !          3884:                if (th->th_flags & TH_RST)
        !          3885:                        src->state = dst->state = TCPS_TIME_WAIT;
        !          3886:
        !          3887:                /* update expire time */
        !          3888:                (*state)->expire = time_second;
        !          3889:                if (src->state >= TCPS_FIN_WAIT_2 &&
        !          3890:                    dst->state >= TCPS_FIN_WAIT_2)
        !          3891:                        (*state)->timeout = PFTM_TCP_CLOSED;
        !          3892:                else if (src->state >= TCPS_CLOSING &&
        !          3893:                    dst->state >= TCPS_CLOSING)
        !          3894:                        (*state)->timeout = PFTM_TCP_FIN_WAIT;
        !          3895:                else if (src->state < TCPS_ESTABLISHED ||
        !          3896:                    dst->state < TCPS_ESTABLISHED)
        !          3897:                        (*state)->timeout = PFTM_TCP_OPENING;
        !          3898:                else if (src->state >= TCPS_CLOSING ||
        !          3899:                    dst->state >= TCPS_CLOSING)
        !          3900:                        (*state)->timeout = PFTM_TCP_CLOSING;
        !          3901:                else
        !          3902:                        (*state)->timeout = PFTM_TCP_ESTABLISHED;
        !          3903:
        !          3904:                /* Fall through to PASS packet */
        !          3905:
        !          3906:        } else if ((dst->state < TCPS_SYN_SENT ||
        !          3907:                dst->state >= TCPS_FIN_WAIT_2 ||
        !          3908:                src->state >= TCPS_FIN_WAIT_2) &&
        !          3909:            SEQ_GEQ(src->seqhi + MAXACKWINDOW, end) &&
        !          3910:            /* Within a window forward of the originating packet */
        !          3911:            SEQ_GEQ(seq, src->seqlo - MAXACKWINDOW)) {
        !          3912:            /* Within a window backward of the originating packet */
        !          3913:
        !          3914:                /*
        !          3915:                 * This currently handles three situations:
        !          3916:                 *  1) Stupid stacks will shotgun SYNs before their peer
        !          3917:                 *     replies.
        !          3918:                 *  2) When PF catches an already established stream (the
        !          3919:                 *     firewall rebooted, the state table was flushed, routes
        !          3920:                 *     changed...)
        !          3921:                 *  3) Packets get funky immediately after the connection
        !          3922:                 *     closes (this should catch Solaris spurious ACK|FINs
        !          3923:                 *     that web servers like to spew after a close)
        !          3924:                 *
        !          3925:                 * This must be a little more careful than the above code
        !          3926:                 * since packet floods will also be caught here. We don't
        !          3927:                 * update the TTL here to mitigate the damage of a packet
        !          3928:                 * flood and so the same code can handle awkward establishment
        !          3929:                 * and a loosened connection close.
        !          3930:                 * In the establishment case, a correct peer response will
        !          3931:                 * validate the connection, go through the normal state code
        !          3932:                 * and keep updating the state TTL.
        !          3933:                 */
        !          3934:
        !          3935:                if (pf_status.debug >= PF_DEBUG_MISC) {
        !          3936:                        printf("pf: loose state match: ");
        !          3937:                        pf_print_state(*state);
        !          3938:                        pf_print_flags(th->th_flags);
        !          3939:                        printf(" seq=%u (%u) ack=%u len=%u ackskew=%d "
        !          3940:                            "pkts=%llu:%llu\n", seq, orig_seq, ack, pd->p_len,
        !          3941:                            ackskew, (*state)->packets[0],
        !          3942:                            (*state)->packets[1]);
        !          3943:                }
        !          3944:
        !          3945:                if (dst->scrub || src->scrub) {
        !          3946:                        if (pf_normalize_tcp_stateful(m, off, pd, reason, th,
        !          3947:                            *state, src, dst, &copyback))
        !          3948:                                return (PF_DROP);
        !          3949:                }
        !          3950:
        !          3951:                /* update max window */
        !          3952:                if (src->max_win < win)
        !          3953:                        src->max_win = win;
        !          3954:                /* synchronize sequencing */
        !          3955:                if (SEQ_GT(end, src->seqlo))
        !          3956:                        src->seqlo = end;
        !          3957:                /* slide the window of what the other end can send */
        !          3958:                if (SEQ_GEQ(ack + (win << sws), dst->seqhi))
        !          3959:                        dst->seqhi = ack + MAX((win << sws), 1);
        !          3960:
        !          3961:                /*
        !          3962:                 * Cannot set dst->seqhi here since this could be a shotgunned
        !          3963:                 * SYN and not an already established connection.
        !          3964:                 */
        !          3965:
        !          3966:                if (th->th_flags & TH_FIN)
        !          3967:                        if (src->state < TCPS_CLOSING)
        !          3968:                                src->state = TCPS_CLOSING;
        !          3969:                if (th->th_flags & TH_RST)
        !          3970:                        src->state = dst->state = TCPS_TIME_WAIT;
        !          3971:
        !          3972:                /* Fall through to PASS packet */
        !          3973:
        !          3974:        } else {
        !          3975:                if ((*state)->dst.state == TCPS_SYN_SENT &&
        !          3976:                    (*state)->src.state == TCPS_SYN_SENT) {
        !          3977:                        /* Send RST for state mismatches during handshake */
        !          3978:                        if (!(th->th_flags & TH_RST))
        !          3979:                                pf_send_tcp((*state)->rule.ptr, pd->af,
        !          3980:                                    pd->dst, pd->src, th->th_dport,
        !          3981:                                    th->th_sport, ntohl(th->th_ack), 0,
        !          3982:                                    TH_RST, 0, 0,
        !          3983:                                    (*state)->rule.ptr->return_ttl, 1, 0,
        !          3984:                                    pd->eh, kif->pfik_ifp);
        !          3985:                        src->seqlo = 0;
        !          3986:                        src->seqhi = 1;
        !          3987:                        src->max_win = 1;
        !          3988:                } else if (pf_status.debug >= PF_DEBUG_MISC) {
        !          3989:                        printf("pf: BAD state: ");
        !          3990:                        pf_print_state(*state);
        !          3991:                        pf_print_flags(th->th_flags);
        !          3992:                        printf(" seq=%u (%u) ack=%u len=%u ackskew=%d "
        !          3993:                            "pkts=%llu:%llu dir=%s,%s\n",
        !          3994:                            seq, orig_seq, ack, pd->p_len, ackskew,
        !          3995:                            (*state)->packets[0], (*state)->packets[1],
        !          3996:                            direction == PF_IN ? "in" : "out",
        !          3997:                            direction == (*state)->state_key->direction ?
        !          3998:                                "fwd" : "rev");
        !          3999:                        printf("pf: State failure on: %c %c %c %c | %c %c\n",
        !          4000:                            SEQ_GEQ(src->seqhi, end) ? ' ' : '1',
        !          4001:                            SEQ_GEQ(seq, src->seqlo - (dst->max_win << dws)) ?
        !          4002:                            ' ': '2',
        !          4003:                            (ackskew >= -MAXACKWINDOW) ? ' ' : '3',
        !          4004:                            (ackskew <= (MAXACKWINDOW << sws)) ? ' ' : '4',
        !          4005:                            SEQ_GEQ(src->seqhi + MAXACKWINDOW, end) ?' ' :'5',
        !          4006:                            SEQ_GEQ(seq, src->seqlo - MAXACKWINDOW) ?' ' :'6');
        !          4007:                }
        !          4008:                REASON_SET(reason, PFRES_BADSTATE);
        !          4009:                return (PF_DROP);
        !          4010:        }
        !          4011:
        !          4012:        /* Any packets which have gotten here are to be passed */
        !          4013:
        !          4014:        /* translate source/destination address, if necessary */
        !          4015:        if (STATE_TRANSLATE((*state)->state_key)) {
        !          4016:                if (direction == PF_OUT)
        !          4017:                        pf_change_ap(pd->src, &th->th_sport, pd->ip_sum,
        !          4018:                            &th->th_sum, &(*state)->state_key->gwy.addr,
        !          4019:                            (*state)->state_key->gwy.port, 0, pd->af);
        !          4020:                else
        !          4021:                        pf_change_ap(pd->dst, &th->th_dport, pd->ip_sum,
        !          4022:                            &th->th_sum, &(*state)->state_key->lan.addr,
        !          4023:                            (*state)->state_key->lan.port, 0, pd->af);
        !          4024:                m_copyback(m, off, sizeof(*th), th);
        !          4025:        } else if (copyback) {
        !          4026:                /* Copyback sequence modulation or stateful scrub changes */
        !          4027:                m_copyback(m, off, sizeof(*th), th);
        !          4028:        }
        !          4029:
        !          4030:        return (PF_PASS);
        !          4031: }
        !          4032:
        !          4033: int
        !          4034: pf_test_state_udp(struct pf_state **state, int direction, struct pfi_kif *kif,
        !          4035:     struct mbuf *m, int off, void *h, struct pf_pdesc *pd)
        !          4036: {
        !          4037:        struct pf_state_peer    *src, *dst;
        !          4038:        struct pf_state_key_cmp  key;
        !          4039:        struct udphdr           *uh = pd->hdr.udp;
        !          4040:
        !          4041:        key.af = pd->af;
        !          4042:        key.proto = IPPROTO_UDP;
        !          4043:        if (direction == PF_IN) {
        !          4044:                PF_ACPY(&key.ext.addr, pd->src, key.af);
        !          4045:                PF_ACPY(&key.gwy.addr, pd->dst, key.af);
        !          4046:                key.ext.port = uh->uh_sport;
        !          4047:                key.gwy.port = uh->uh_dport;
        !          4048:        } else {
        !          4049:                PF_ACPY(&key.lan.addr, pd->src, key.af);
        !          4050:                PF_ACPY(&key.ext.addr, pd->dst, key.af);
        !          4051:                key.lan.port = uh->uh_sport;
        !          4052:                key.ext.port = uh->uh_dport;
        !          4053:        }
        !          4054:
        !          4055:        STATE_LOOKUP();
        !          4056:
        !          4057:        if (direction == (*state)->state_key->direction) {
        !          4058:                src = &(*state)->src;
        !          4059:                dst = &(*state)->dst;
        !          4060:        } else {
        !          4061:                src = &(*state)->dst;
        !          4062:                dst = &(*state)->src;
        !          4063:        }
        !          4064:
        !          4065:        /* update states */
        !          4066:        if (src->state < PFUDPS_SINGLE)
        !          4067:                src->state = PFUDPS_SINGLE;
        !          4068:        if (dst->state == PFUDPS_SINGLE)
        !          4069:                dst->state = PFUDPS_MULTIPLE;
        !          4070:
        !          4071:        /* update expire time */
        !          4072:        (*state)->expire = time_second;
        !          4073:        if (src->state == PFUDPS_MULTIPLE && dst->state == PFUDPS_MULTIPLE)
        !          4074:                (*state)->timeout = PFTM_UDP_MULTIPLE;
        !          4075:        else
        !          4076:                (*state)->timeout = PFTM_UDP_SINGLE;
        !          4077:
        !          4078:        /* translate source/destination address, if necessary */
        !          4079:        if (STATE_TRANSLATE((*state)->state_key)) {
        !          4080:                if (direction == PF_OUT)
        !          4081:                        pf_change_ap(pd->src, &uh->uh_sport, pd->ip_sum,
        !          4082:                            &uh->uh_sum, &(*state)->state_key->gwy.addr,
        !          4083:                            (*state)->state_key->gwy.port, 1, pd->af);
        !          4084:                else
        !          4085:                        pf_change_ap(pd->dst, &uh->uh_dport, pd->ip_sum,
        !          4086:                            &uh->uh_sum, &(*state)->state_key->lan.addr,
        !          4087:                            (*state)->state_key->lan.port, 1, pd->af);
        !          4088:                m_copyback(m, off, sizeof(*uh), uh);
        !          4089:        }
        !          4090:
        !          4091:        return (PF_PASS);
        !          4092: }
        !          4093:
        !          4094: int
        !          4095: pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
        !          4096:     struct mbuf *m, int off, void *h, struct pf_pdesc *pd, u_short *reason)
        !          4097: {
        !          4098:        struct pf_addr  *saddr = pd->src, *daddr = pd->dst;
        !          4099:        u_int16_t        icmpid, *icmpsum;
        !          4100:        u_int8_t         icmptype;
        !          4101:        int              state_icmp = 0;
        !          4102:        struct pf_state_key_cmp key;
        !          4103:
        !          4104:        switch (pd->proto) {
        !          4105: #ifdef INET
        !          4106:        case IPPROTO_ICMP:
        !          4107:                icmptype = pd->hdr.icmp->icmp_type;
        !          4108:                icmpid = pd->hdr.icmp->icmp_id;
        !          4109:                icmpsum = &pd->hdr.icmp->icmp_cksum;
        !          4110:
        !          4111:                if (icmptype == ICMP_UNREACH ||
        !          4112:                    icmptype == ICMP_SOURCEQUENCH ||
        !          4113:                    icmptype == ICMP_REDIRECT ||
        !          4114:                    icmptype == ICMP_TIMXCEED ||
        !          4115:                    icmptype == ICMP_PARAMPROB)
        !          4116:                        state_icmp++;
        !          4117:                break;
        !          4118: #endif /* INET */
        !          4119: #ifdef INET6
        !          4120:        case IPPROTO_ICMPV6:
        !          4121:                icmptype = pd->hdr.icmp6->icmp6_type;
        !          4122:                icmpid = pd->hdr.icmp6->icmp6_id;
        !          4123:                icmpsum = &pd->hdr.icmp6->icmp6_cksum;
        !          4124:
        !          4125:                if (icmptype == ICMP6_DST_UNREACH ||
        !          4126:                    icmptype == ICMP6_PACKET_TOO_BIG ||
        !          4127:                    icmptype == ICMP6_TIME_EXCEEDED ||
        !          4128:                    icmptype == ICMP6_PARAM_PROB)
        !          4129:                        state_icmp++;
        !          4130:                break;
        !          4131: #endif /* INET6 */
        !          4132:        }
        !          4133:
        !          4134:        if (!state_icmp) {
        !          4135:
        !          4136:                /*
        !          4137:                 * ICMP query/reply message not related to a TCP/UDP packet.
        !          4138:                 * Search for an ICMP state.
        !          4139:                 */
        !          4140:                key.af = pd->af;
        !          4141:                key.proto = pd->proto;
        !          4142:                if (direction == PF_IN) {
        !          4143:                        PF_ACPY(&key.ext.addr, pd->src, key.af);
        !          4144:                        PF_ACPY(&key.gwy.addr, pd->dst, key.af);
        !          4145:                        key.ext.port = 0;
        !          4146:                        key.gwy.port = icmpid;
        !          4147:                } else {
        !          4148:                        PF_ACPY(&key.lan.addr, pd->src, key.af);
        !          4149:                        PF_ACPY(&key.ext.addr, pd->dst, key.af);
        !          4150:                        key.lan.port = icmpid;
        !          4151:                        key.ext.port = 0;
        !          4152:                }
        !          4153:
        !          4154:                STATE_LOOKUP();
        !          4155:
        !          4156:                (*state)->expire = time_second;
        !          4157:                (*state)->timeout = PFTM_ICMP_ERROR_REPLY;
        !          4158:
        !          4159:                /* translate source/destination address, if necessary */
        !          4160:                if (STATE_TRANSLATE((*state)->state_key)) {
        !          4161:                        if (direction == PF_OUT) {
        !          4162:                                switch (pd->af) {
        !          4163: #ifdef INET
        !          4164:                                case AF_INET:
        !          4165:                                        pf_change_a(&saddr->v4.s_addr,
        !          4166:                                            pd->ip_sum,
        !          4167:                                            (*state)->state_key->gwy.addr.v4.s_addr, 0);
        !          4168:                                        pd->hdr.icmp->icmp_cksum =
        !          4169:                                            pf_cksum_fixup(
        !          4170:                                            pd->hdr.icmp->icmp_cksum, icmpid,
        !          4171:                                            (*state)->state_key->gwy.port, 0);
        !          4172:                                        pd->hdr.icmp->icmp_id =
        !          4173:                                            (*state)->state_key->gwy.port;
        !          4174:                                        m_copyback(m, off, ICMP_MINLEN,
        !          4175:                                            pd->hdr.icmp);
        !          4176:                                        break;
        !          4177: #endif /* INET */
        !          4178: #ifdef INET6
        !          4179:                                case AF_INET6:
        !          4180:                                        pf_change_a6(saddr,
        !          4181:                                            &pd->hdr.icmp6->icmp6_cksum,
        !          4182:                                            &(*state)->state_key->gwy.addr, 0);
        !          4183:                                        m_copyback(m, off,
        !          4184:                                            sizeof(struct icmp6_hdr),
        !          4185:                                            pd->hdr.icmp6);
        !          4186:                                        break;
        !          4187: #endif /* INET6 */
        !          4188:                                }
        !          4189:                        } else {
        !          4190:                                switch (pd->af) {
        !          4191: #ifdef INET
        !          4192:                                case AF_INET:
        !          4193:                                        pf_change_a(&daddr->v4.s_addr,
        !          4194:                                            pd->ip_sum,
        !          4195:                                            (*state)->state_key->lan.addr.v4.s_addr, 0);
        !          4196:                                        pd->hdr.icmp->icmp_cksum =
        !          4197:                                            pf_cksum_fixup(
        !          4198:                                            pd->hdr.icmp->icmp_cksum, icmpid,
        !          4199:                                            (*state)->state_key->lan.port, 0);
        !          4200:                                        pd->hdr.icmp->icmp_id =
        !          4201:                                            (*state)->state_key->lan.port;
        !          4202:                                        m_copyback(m, off, ICMP_MINLEN,
        !          4203:                                            pd->hdr.icmp);
        !          4204:                                        break;
        !          4205: #endif /* INET */
        !          4206: #ifdef INET6
        !          4207:                                case AF_INET6:
        !          4208:                                        pf_change_a6(daddr,
        !          4209:                                            &pd->hdr.icmp6->icmp6_cksum,
        !          4210:                                            &(*state)->state_key->lan.addr, 0);
        !          4211:                                        m_copyback(m, off,
        !          4212:                                            sizeof(struct icmp6_hdr),
        !          4213:                                            pd->hdr.icmp6);
        !          4214:                                        break;
        !          4215: #endif /* INET6 */
        !          4216:                                }
        !          4217:                        }
        !          4218:                }
        !          4219:
        !          4220:                return (PF_PASS);
        !          4221:
        !          4222:        } else {
        !          4223:                /*
        !          4224:                 * ICMP error message in response to a TCP/UDP packet.
        !          4225:                 * Extract the inner TCP/UDP header and search for that state.
        !          4226:                 */
        !          4227:
        !          4228:                struct pf_pdesc pd2;
        !          4229: #ifdef INET
        !          4230:                struct ip       h2;
        !          4231: #endif /* INET */
        !          4232: #ifdef INET6
        !          4233:                struct ip6_hdr  h2_6;
        !          4234:                int             terminal = 0;
        !          4235: #endif /* INET6 */
        !          4236:                int             ipoff2;
        !          4237:                int             off2;
        !          4238:
        !          4239:                pd2.af = pd->af;
        !          4240:                switch (pd->af) {
        !          4241: #ifdef INET
        !          4242:                case AF_INET:
        !          4243:                        /* offset of h2 in mbuf chain */
        !          4244:                        ipoff2 = off + ICMP_MINLEN;
        !          4245:
        !          4246:                        if (!pf_pull_hdr(m, ipoff2, &h2, sizeof(h2),
        !          4247:                            NULL, reason, pd2.af)) {
        !          4248:                                DPFPRINTF(PF_DEBUG_MISC,
        !          4249:                                    ("pf: ICMP error message too short "
        !          4250:                                    "(ip)\n"));
        !          4251:                                return (PF_DROP);
        !          4252:                        }
        !          4253:                        /*
        !          4254:                         * ICMP error messages don't refer to non-first
        !          4255:                         * fragments
        !          4256:                         */
        !          4257:                        if (h2.ip_off & htons(IP_OFFMASK)) {
        !          4258:                                REASON_SET(reason, PFRES_FRAG);
        !          4259:                                return (PF_DROP);
        !          4260:                        }
        !          4261:
        !          4262:                        /* offset of protocol header that follows h2 */
        !          4263:                        off2 = ipoff2 + (h2.ip_hl << 2);
        !          4264:
        !          4265:                        pd2.proto = h2.ip_p;
        !          4266:                        pd2.src = (struct pf_addr *)&h2.ip_src;
        !          4267:                        pd2.dst = (struct pf_addr *)&h2.ip_dst;
        !          4268:                        pd2.ip_sum = &h2.ip_sum;
        !          4269:                        break;
        !          4270: #endif /* INET */
        !          4271: #ifdef INET6
        !          4272:                case AF_INET6:
        !          4273:                        ipoff2 = off + sizeof(struct icmp6_hdr);
        !          4274:
        !          4275:                        if (!pf_pull_hdr(m, ipoff2, &h2_6, sizeof(h2_6),
        !          4276:                            NULL, reason, pd2.af)) {
        !          4277:                                DPFPRINTF(PF_DEBUG_MISC,
        !          4278:                                    ("pf: ICMP error message too short "
        !          4279:                                    "(ip6)\n"));
        !          4280:                                return (PF_DROP);
        !          4281:                        }
        !          4282:                        pd2.proto = h2_6.ip6_nxt;
        !          4283:                        pd2.src = (struct pf_addr *)&h2_6.ip6_src;
        !          4284:                        pd2.dst = (struct pf_addr *)&h2_6.ip6_dst;
        !          4285:                        pd2.ip_sum = NULL;
        !          4286:                        off2 = ipoff2 + sizeof(h2_6);
        !          4287:                        do {
        !          4288:                                switch (pd2.proto) {
        !          4289:                                case IPPROTO_FRAGMENT:
        !          4290:                                        /*
        !          4291:                                         * ICMPv6 error messages for
        !          4292:                                         * non-first fragments
        !          4293:                                         */
        !          4294:                                        REASON_SET(reason, PFRES_FRAG);
        !          4295:                                        return (PF_DROP);
        !          4296:                                case IPPROTO_AH:
        !          4297:                                case IPPROTO_HOPOPTS:
        !          4298:                                case IPPROTO_ROUTING:
        !          4299:                                case IPPROTO_DSTOPTS: {
        !          4300:                                        /* get next header and header length */
        !          4301:                                        struct ip6_ext opt6;
        !          4302:
        !          4303:                                        if (!pf_pull_hdr(m, off2, &opt6,
        !          4304:                                            sizeof(opt6), NULL, reason,
        !          4305:                                            pd2.af)) {
        !          4306:                                                DPFPRINTF(PF_DEBUG_MISC,
        !          4307:                                                    ("pf: ICMPv6 short opt\n"));
        !          4308:                                                return (PF_DROP);
        !          4309:                                        }
        !          4310:                                        if (pd2.proto == IPPROTO_AH)
        !          4311:                                                off2 += (opt6.ip6e_len + 2) * 4;
        !          4312:                                        else
        !          4313:                                                off2 += (opt6.ip6e_len + 1) * 8;
        !          4314:                                        pd2.proto = opt6.ip6e_nxt;
        !          4315:                                        /* goto the next header */
        !          4316:                                        break;
        !          4317:                                }
        !          4318:                                default:
        !          4319:                                        terminal++;
        !          4320:                                        break;
        !          4321:                                }
        !          4322:                        } while (!terminal);
        !          4323:                        break;
        !          4324: #endif /* INET6 */
        !          4325:                }
        !          4326:
        !          4327:                switch (pd2.proto) {
        !          4328:                case IPPROTO_TCP: {
        !          4329:                        struct tcphdr            th;
        !          4330:                        u_int32_t                seq;
        !          4331:                        struct pf_state_peer    *src, *dst;
        !          4332:                        u_int8_t                 dws;
        !          4333:                        int                      copyback = 0;
        !          4334:
        !          4335:                        /*
        !          4336:                         * Only the first 8 bytes of the TCP header can be
        !          4337:                         * expected. Don't access any TCP header fields after
        !          4338:                         * th_seq, an ackskew test is not possible.
        !          4339:                         */
        !          4340:                        if (!pf_pull_hdr(m, off2, &th, 8, NULL, reason,
        !          4341:                            pd2.af)) {
        !          4342:                                DPFPRINTF(PF_DEBUG_MISC,
        !          4343:                                    ("pf: ICMP error message too short "
        !          4344:                                    "(tcp)\n"));
        !          4345:                                return (PF_DROP);
        !          4346:                        }
        !          4347:
        !          4348:                        key.af = pd2.af;
        !          4349:                        key.proto = IPPROTO_TCP;
        !          4350:                        if (direction == PF_IN) {
        !          4351:                                PF_ACPY(&key.ext.addr, pd2.dst, key.af);
        !          4352:                                PF_ACPY(&key.gwy.addr, pd2.src, key.af);
        !          4353:                                key.ext.port = th.th_dport;
        !          4354:                                key.gwy.port = th.th_sport;
        !          4355:                        } else {
        !          4356:                                PF_ACPY(&key.lan.addr, pd2.dst, key.af);
        !          4357:                                PF_ACPY(&key.ext.addr, pd2.src, key.af);
        !          4358:                                key.lan.port = th.th_dport;
        !          4359:                                key.ext.port = th.th_sport;
        !          4360:                        }
        !          4361:
        !          4362:                        STATE_LOOKUP();
        !          4363:
        !          4364:                        if (direction == (*state)->state_key->direction) {
        !          4365:                                src = &(*state)->dst;
        !          4366:                                dst = &(*state)->src;
        !          4367:                        } else {
        !          4368:                                src = &(*state)->src;
        !          4369:                                dst = &(*state)->dst;
        !          4370:                        }
        !          4371:
        !          4372:                        if (src->wscale && dst->wscale)
        !          4373:                                dws = dst->wscale & PF_WSCALE_MASK;
        !          4374:                        else
        !          4375:                                dws = 0;
        !          4376:
        !          4377:                        /* Demodulate sequence number */
        !          4378:                        seq = ntohl(th.th_seq) - src->seqdiff;
        !          4379:                        if (src->seqdiff) {
        !          4380:                                pf_change_a(&th.th_seq, icmpsum,
        !          4381:                                    htonl(seq), 0);
        !          4382:                                copyback = 1;
        !          4383:                        }
        !          4384:
        !          4385:                        if (!SEQ_GEQ(src->seqhi, seq) ||
        !          4386:                            !SEQ_GEQ(seq, src->seqlo - (dst->max_win << dws))) {
        !          4387:                                if (pf_status.debug >= PF_DEBUG_MISC) {
        !          4388:                                        printf("pf: BAD ICMP %d:%d ",
        !          4389:                                            icmptype, pd->hdr.icmp->icmp_code);
        !          4390:                                        pf_print_host(pd->src, 0, pd->af);
        !          4391:                                        printf(" -> ");
        !          4392:                                        pf_print_host(pd->dst, 0, pd->af);
        !          4393:                                        printf(" state: ");
        !          4394:                                        pf_print_state(*state);
        !          4395:                                        printf(" seq=%u\n", seq);
        !          4396:                                }
        !          4397:                                REASON_SET(reason, PFRES_BADSTATE);
        !          4398:                                return (PF_DROP);
        !          4399:                        }
        !          4400:
        !          4401:                        if (STATE_TRANSLATE((*state)->state_key)) {
        !          4402:                                if (direction == PF_IN) {
        !          4403:                                        pf_change_icmp(pd2.src, &th.th_sport,
        !          4404:                                            daddr, &(*state)->state_key->lan.addr,
        !          4405:                                            (*state)->state_key->lan.port, NULL,
        !          4406:                                            pd2.ip_sum, icmpsum,
        !          4407:                                            pd->ip_sum, 0, pd2.af);
        !          4408:                                } else {
        !          4409:                                        pf_change_icmp(pd2.dst, &th.th_dport,
        !          4410:                                            saddr, &(*state)->state_key->gwy.addr,
        !          4411:                                            (*state)->state_key->gwy.port, NULL,
        !          4412:                                            pd2.ip_sum, icmpsum,
        !          4413:                                            pd->ip_sum, 0, pd2.af);
        !          4414:                                }
        !          4415:                                copyback = 1;
        !          4416:                        }
        !          4417:
        !          4418:                        if (copyback) {
        !          4419:                                switch (pd2.af) {
        !          4420: #ifdef INET
        !          4421:                                case AF_INET:
        !          4422:                                        m_copyback(m, off, ICMP_MINLEN,
        !          4423:                                            pd->hdr.icmp);
        !          4424:                                        m_copyback(m, ipoff2, sizeof(h2),
        !          4425:                                            &h2);
        !          4426:                                        break;
        !          4427: #endif /* INET */
        !          4428: #ifdef INET6
        !          4429:                                case AF_INET6:
        !          4430:                                        m_copyback(m, off,
        !          4431:                                            sizeof(struct icmp6_hdr),
        !          4432:                                            pd->hdr.icmp6);
        !          4433:                                        m_copyback(m, ipoff2, sizeof(h2_6),
        !          4434:                                            &h2_6);
        !          4435:                                        break;
        !          4436: #endif /* INET6 */
        !          4437:                                }
        !          4438:                                m_copyback(m, off2, 8, &th);
        !          4439:                        }
        !          4440:
        !          4441:                        return (PF_PASS);
        !          4442:                        break;
        !          4443:                }
        !          4444:                case IPPROTO_UDP: {
        !          4445:                        struct udphdr           uh;
        !          4446:
        !          4447:                        if (!pf_pull_hdr(m, off2, &uh, sizeof(uh),
        !          4448:                            NULL, reason, pd2.af)) {
        !          4449:                                DPFPRINTF(PF_DEBUG_MISC,
        !          4450:                                    ("pf: ICMP error message too short "
        !          4451:                                    "(udp)\n"));
        !          4452:                                return (PF_DROP);
        !          4453:                        }
        !          4454:
        !          4455:                        key.af = pd2.af;
        !          4456:                        key.proto = IPPROTO_UDP;
        !          4457:                        if (direction == PF_IN) {
        !          4458:                                PF_ACPY(&key.ext.addr, pd2.dst, key.af);
        !          4459:                                PF_ACPY(&key.gwy.addr, pd2.src, key.af);
        !          4460:                                key.ext.port = uh.uh_dport;
        !          4461:                                key.gwy.port = uh.uh_sport;
        !          4462:                        } else {
        !          4463:                                PF_ACPY(&key.lan.addr, pd2.dst, key.af);
        !          4464:                                PF_ACPY(&key.ext.addr, pd2.src, key.af);
        !          4465:                                key.lan.port = uh.uh_dport;
        !          4466:                                key.ext.port = uh.uh_sport;
        !          4467:                        }
        !          4468:
        !          4469:                        STATE_LOOKUP();
        !          4470:
        !          4471:                        if (STATE_TRANSLATE((*state)->state_key)) {
        !          4472:                                if (direction == PF_IN) {
        !          4473:                                        pf_change_icmp(pd2.src, &uh.uh_sport,
        !          4474:                                            daddr,
        !          4475:                                            &(*state)->state_key->lan.addr,
        !          4476:                                            (*state)->state_key->lan.port,
        !          4477:                                            &uh.uh_sum,
        !          4478:                                            pd2.ip_sum, icmpsum,
        !          4479:                                            pd->ip_sum, 1, pd2.af);
        !          4480:                                } else {
        !          4481:                                        pf_change_icmp(pd2.dst, &uh.uh_dport,
        !          4482:                                            saddr,
        !          4483:                                            &(*state)->state_key->gwy.addr,
        !          4484:                                            (*state)->state_key->gwy.port, &uh.uh_sum,
        !          4485:                                            pd2.ip_sum, icmpsum,
        !          4486:                                            pd->ip_sum, 1, pd2.af);
        !          4487:                                }
        !          4488:                                switch (pd2.af) {
        !          4489: #ifdef INET
        !          4490:                                case AF_INET:
        !          4491:                                        m_copyback(m, off, ICMP_MINLEN,
        !          4492:                                            pd->hdr.icmp);
        !          4493:                                        m_copyback(m, ipoff2, sizeof(h2), &h2);
        !          4494:                                        break;
        !          4495: #endif /* INET */
        !          4496: #ifdef INET6
        !          4497:                                case AF_INET6:
        !          4498:                                        m_copyback(m, off,
        !          4499:                                            sizeof(struct icmp6_hdr),
        !          4500:                                            pd->hdr.icmp6);
        !          4501:                                        m_copyback(m, ipoff2, sizeof(h2_6),
        !          4502:                                            &h2_6);
        !          4503:                                        break;
        !          4504: #endif /* INET6 */
        !          4505:                                }
        !          4506:                                m_copyback(m, off2, sizeof(uh), &uh);
        !          4507:                        }
        !          4508:
        !          4509:                        return (PF_PASS);
        !          4510:                        break;
        !          4511:                }
        !          4512: #ifdef INET
        !          4513:                case IPPROTO_ICMP: {
        !          4514:                        struct icmp             iih;
        !          4515:
        !          4516:                        if (!pf_pull_hdr(m, off2, &iih, ICMP_MINLEN,
        !          4517:                            NULL, reason, pd2.af)) {
        !          4518:                                DPFPRINTF(PF_DEBUG_MISC,
        !          4519:                                    ("pf: ICMP error message too short i"
        !          4520:                                    "(icmp)\n"));
        !          4521:                                return (PF_DROP);
        !          4522:                        }
        !          4523:
        !          4524:                        key.af = pd2.af;
        !          4525:                        key.proto = IPPROTO_ICMP;
        !          4526:                        if (direction == PF_IN) {
        !          4527:                                PF_ACPY(&key.ext.addr, pd2.dst, key.af);
        !          4528:                                PF_ACPY(&key.gwy.addr, pd2.src, key.af);
        !          4529:                                key.ext.port = 0;
        !          4530:                                key.gwy.port = iih.icmp_id;
        !          4531:                        } else {
        !          4532:                                PF_ACPY(&key.lan.addr, pd2.dst, key.af);
        !          4533:                                PF_ACPY(&key.ext.addr, pd2.src, key.af);
        !          4534:                                key.lan.port = iih.icmp_id;
        !          4535:                                key.ext.port = 0;
        !          4536:                        }
        !          4537:
        !          4538:                        STATE_LOOKUP();
        !          4539:
        !          4540:                        if (STATE_TRANSLATE((*state)->state_key)) {
        !          4541:                                if (direction == PF_IN) {
        !          4542:                                        pf_change_icmp(pd2.src, &iih.icmp_id,
        !          4543:                                            daddr,
        !          4544:                                            &(*state)->state_key->lan.addr,
        !          4545:                                            (*state)->state_key->lan.port, NULL,
        !          4546:                                            pd2.ip_sum, icmpsum,
        !          4547:                                            pd->ip_sum, 0, AF_INET);
        !          4548:                                } else {
        !          4549:                                        pf_change_icmp(pd2.dst, &iih.icmp_id,
        !          4550:                                            saddr,
        !          4551:                                            &(*state)->state_key->gwy.addr,
        !          4552:                                            (*state)->state_key->gwy.port, NULL,
        !          4553:                                            pd2.ip_sum, icmpsum,
        !          4554:                                            pd->ip_sum, 0, AF_INET);
        !          4555:                                }
        !          4556:                                m_copyback(m, off, ICMP_MINLEN, pd->hdr.icmp);
        !          4557:                                m_copyback(m, ipoff2, sizeof(h2), &h2);
        !          4558:                                m_copyback(m, off2, ICMP_MINLEN, &iih);
        !          4559:                        }
        !          4560:
        !          4561:                        return (PF_PASS);
        !          4562:                        break;
        !          4563:                }
        !          4564: #endif /* INET */
        !          4565: #ifdef INET6
        !          4566:                case IPPROTO_ICMPV6: {
        !          4567:                        struct icmp6_hdr        iih;
        !          4568:
        !          4569:                        if (!pf_pull_hdr(m, off2, &iih,
        !          4570:                            sizeof(struct icmp6_hdr), NULL, reason, pd2.af)) {
        !          4571:                                DPFPRINTF(PF_DEBUG_MISC,
        !          4572:                                    ("pf: ICMP error message too short "
        !          4573:                                    "(icmp6)\n"));
        !          4574:                                return (PF_DROP);
        !          4575:                        }
        !          4576:
        !          4577:                        key.af = pd2.af;
        !          4578:                        key.proto = IPPROTO_ICMPV6;
        !          4579:                        if (direction == PF_IN) {
        !          4580:                                PF_ACPY(&key.ext.addr, pd2.dst, key.af);
        !          4581:                                PF_ACPY(&key.gwy.addr, pd2.src, key.af);
        !          4582:                                key.ext.port = 0;
        !          4583:                                key.gwy.port = iih.icmp6_id;
        !          4584:                        } else {
        !          4585:                                PF_ACPY(&key.lan.addr, pd2.dst, key.af);
        !          4586:                                PF_ACPY(&key.ext.addr, pd2.src, key.af);
        !          4587:                                key.lan.port = iih.icmp6_id;
        !          4588:                                key.ext.port = 0;
        !          4589:                        }
        !          4590:
        !          4591:                        STATE_LOOKUP();
        !          4592:
        !          4593:                        if (STATE_TRANSLATE((*state)->state_key)) {
        !          4594:                                if (direction == PF_IN) {
        !          4595:                                        pf_change_icmp(pd2.src, &iih.icmp6_id,
        !          4596:                                            daddr,
        !          4597:                                            &(*state)->state_key->lan.addr,
        !          4598:                                            (*state)->state_key->lan.port, NULL,
        !          4599:                                            pd2.ip_sum, icmpsum,
        !          4600:                                            pd->ip_sum, 0, AF_INET6);
        !          4601:                                } else {
        !          4602:                                        pf_change_icmp(pd2.dst, &iih.icmp6_id,
        !          4603:                                            saddr, &(*state)->state_key->gwy.addr,
        !          4604:                                            (*state)->state_key->gwy.port, NULL,
        !          4605:                                            pd2.ip_sum, icmpsum,
        !          4606:                                            pd->ip_sum, 0, AF_INET6);
        !          4607:                                }
        !          4608:                                m_copyback(m, off, sizeof(struct icmp6_hdr),
        !          4609:                                    pd->hdr.icmp6);
        !          4610:                                m_copyback(m, ipoff2, sizeof(h2_6), &h2_6);
        !          4611:                                m_copyback(m, off2, sizeof(struct icmp6_hdr),
        !          4612:                                    &iih);
        !          4613:                        }
        !          4614:
        !          4615:                        return (PF_PASS);
        !          4616:                        break;
        !          4617:                }
        !          4618: #endif /* INET6 */
        !          4619:                default: {
        !          4620:                        key.af = pd2.af;
        !          4621:                        key.proto = pd2.proto;
        !          4622:                        if (direction == PF_IN) {
        !          4623:                                PF_ACPY(&key.ext.addr, pd2.dst, key.af);
        !          4624:                                PF_ACPY(&key.gwy.addr, pd2.src, key.af);
        !          4625:                                key.ext.port = 0;
        !          4626:                                key.gwy.port = 0;
        !          4627:                        } else {
        !          4628:                                PF_ACPY(&key.lan.addr, pd2.dst, key.af);
        !          4629:                                PF_ACPY(&key.ext.addr, pd2.src, key.af);
        !          4630:                                key.lan.port = 0;
        !          4631:                                key.ext.port = 0;
        !          4632:                        }
        !          4633:
        !          4634:                        STATE_LOOKUP();
        !          4635:
        !          4636:                        if (STATE_TRANSLATE((*state)->state_key)) {
        !          4637:                                if (direction == PF_IN) {
        !          4638:                                        pf_change_icmp(pd2.src, NULL,
        !          4639:                                            daddr,
        !          4640:                                            &(*state)->state_key->lan.addr,
        !          4641:                                            0, NULL,
        !          4642:                                            pd2.ip_sum, icmpsum,
        !          4643:                                            pd->ip_sum, 0, pd2.af);
        !          4644:                                } else {
        !          4645:                                        pf_change_icmp(pd2.dst, NULL,
        !          4646:                                            saddr,
        !          4647:                                            &(*state)->state_key->gwy.addr,
        !          4648:                                            0, NULL,
        !          4649:                                            pd2.ip_sum, icmpsum,
        !          4650:                                            pd->ip_sum, 0, pd2.af);
        !          4651:                                }
        !          4652:                                switch (pd2.af) {
        !          4653: #ifdef INET
        !          4654:                                case AF_INET:
        !          4655:                                        m_copyback(m, off, ICMP_MINLEN,
        !          4656:                                            pd->hdr.icmp);
        !          4657:                                        m_copyback(m, ipoff2, sizeof(h2), &h2);
        !          4658:                                        break;
        !          4659: #endif /* INET */
        !          4660: #ifdef INET6
        !          4661:                                case AF_INET6:
        !          4662:                                        m_copyback(m, off,
        !          4663:                                            sizeof(struct icmp6_hdr),
        !          4664:                                            pd->hdr.icmp6);
        !          4665:                                        m_copyback(m, ipoff2, sizeof(h2_6),
        !          4666:                                            &h2_6);
        !          4667:                                        break;
        !          4668: #endif /* INET6 */
        !          4669:                                }
        !          4670:                        }
        !          4671:
        !          4672:                        return (PF_PASS);
        !          4673:                        break;
        !          4674:                }
        !          4675:                }
        !          4676:        }
        !          4677: }
        !          4678:
        !          4679: int
        !          4680: pf_test_state_other(struct pf_state **state, int direction, struct pfi_kif *kif,
        !          4681:     struct pf_pdesc *pd)
        !          4682: {
        !          4683:        struct pf_state_peer    *src, *dst;
        !          4684:        struct pf_state_key_cmp  key;
        !          4685:
        !          4686:        key.af = pd->af;
        !          4687:        key.proto = pd->proto;
        !          4688:        if (direction == PF_IN) {
        !          4689:                PF_ACPY(&key.ext.addr, pd->src, key.af);
        !          4690:                PF_ACPY(&key.gwy.addr, pd->dst, key.af);
        !          4691:                key.ext.port = 0;
        !          4692:                key.gwy.port = 0;
        !          4693:        } else {
        !          4694:                PF_ACPY(&key.lan.addr, pd->src, key.af);
        !          4695:                PF_ACPY(&key.ext.addr, pd->dst, key.af);
        !          4696:                key.lan.port = 0;
        !          4697:                key.ext.port = 0;
        !          4698:        }
        !          4699:
        !          4700:        STATE_LOOKUP();
        !          4701:
        !          4702:        if (direction == (*state)->state_key->direction) {
        !          4703:                src = &(*state)->src;
        !          4704:                dst = &(*state)->dst;
        !          4705:        } else {
        !          4706:                src = &(*state)->dst;
        !          4707:                dst = &(*state)->src;
        !          4708:        }
        !          4709:
        !          4710:        /* update states */
        !          4711:        if (src->state < PFOTHERS_SINGLE)
        !          4712:                src->state = PFOTHERS_SINGLE;
        !          4713:        if (dst->state == PFOTHERS_SINGLE)
        !          4714:                dst->state = PFOTHERS_MULTIPLE;
        !          4715:
        !          4716:        /* update expire time */
        !          4717:        (*state)->expire = time_second;
        !          4718:        if (src->state == PFOTHERS_MULTIPLE && dst->state == PFOTHERS_MULTIPLE)
        !          4719:                (*state)->timeout = PFTM_OTHER_MULTIPLE;
        !          4720:        else
        !          4721:                (*state)->timeout = PFTM_OTHER_SINGLE;
        !          4722:
        !          4723:        /* translate source/destination address, if necessary */
        !          4724:        if (STATE_TRANSLATE((*state)->state_key)) {
        !          4725:                if (direction == PF_OUT)
        !          4726:                        switch (pd->af) {
        !          4727: #ifdef INET
        !          4728:                        case AF_INET:
        !          4729:                                pf_change_a(&pd->src->v4.s_addr,
        !          4730:                                    pd->ip_sum,
        !          4731:                                    (*state)->state_key->gwy.addr.v4.s_addr,
        !          4732:                                    0);
        !          4733:                                break;
        !          4734: #endif /* INET */
        !          4735: #ifdef INET6
        !          4736:                        case AF_INET6:
        !          4737:                                PF_ACPY(pd->src,
        !          4738:                                    &(*state)->state_key->gwy.addr, pd->af);
        !          4739:                                break;
        !          4740: #endif /* INET6 */
        !          4741:                        }
        !          4742:                else
        !          4743:                        switch (pd->af) {
        !          4744: #ifdef INET
        !          4745:                        case AF_INET:
        !          4746:                                pf_change_a(&pd->dst->v4.s_addr,
        !          4747:                                    pd->ip_sum,
        !          4748:                                    (*state)->state_key->lan.addr.v4.s_addr,
        !          4749:                                    0);
        !          4750:                                break;
        !          4751: #endif /* INET */
        !          4752: #ifdef INET6
        !          4753:                        case AF_INET6:
        !          4754:                                PF_ACPY(pd->dst,
        !          4755:                                    &(*state)->state_key->lan.addr, pd->af);
        !          4756:                                break;
        !          4757: #endif /* INET6 */
        !          4758:                        }
        !          4759:        }
        !          4760:
        !          4761:        return (PF_PASS);
        !          4762: }
        !          4763:
        !          4764: /*
        !          4765:  * ipoff and off are measured from the start of the mbuf chain.
        !          4766:  * h must be at "ipoff" on the mbuf chain.
        !          4767:  */
        !          4768: void *
        !          4769: pf_pull_hdr(struct mbuf *m, int off, void *p, int len,
        !          4770:     u_short *actionp, u_short *reasonp, sa_family_t af)
        !          4771: {
        !          4772:        switch (af) {
        !          4773: #ifdef INET
        !          4774:        case AF_INET: {
        !          4775:                struct ip       *h = mtod(m, struct ip *);
        !          4776:                u_int16_t        fragoff = (ntohs(h->ip_off) & IP_OFFMASK) << 3;
        !          4777:
        !          4778:                if (fragoff) {
        !          4779:                        if (fragoff >= len)
        !          4780:                                ACTION_SET(actionp, PF_PASS);
        !          4781:                        else {
        !          4782:                                ACTION_SET(actionp, PF_DROP);
        !          4783:                                REASON_SET(reasonp, PFRES_FRAG);
        !          4784:                        }
        !          4785:                        return (NULL);
        !          4786:                }
        !          4787:                if (m->m_pkthdr.len < off + len ||
        !          4788:                    ntohs(h->ip_len) < off + len) {
        !          4789:                        ACTION_SET(actionp, PF_DROP);
        !          4790:                        REASON_SET(reasonp, PFRES_SHORT);
        !          4791:                        return (NULL);
        !          4792:                }
        !          4793:                break;
        !          4794:        }
        !          4795: #endif /* INET */
        !          4796: #ifdef INET6
        !          4797:        case AF_INET6: {
        !          4798:                struct ip6_hdr  *h = mtod(m, struct ip6_hdr *);
        !          4799:
        !          4800:                if (m->m_pkthdr.len < off + len ||
        !          4801:                    (ntohs(h->ip6_plen) + sizeof(struct ip6_hdr)) <
        !          4802:                    (unsigned)(off + len)) {
        !          4803:                        ACTION_SET(actionp, PF_DROP);
        !          4804:                        REASON_SET(reasonp, PFRES_SHORT);
        !          4805:                        return (NULL);
        !          4806:                }
        !          4807:                break;
        !          4808:        }
        !          4809: #endif /* INET6 */
        !          4810:        }
        !          4811:        m_copydata(m, off, len, p);
        !          4812:        return (p);
        !          4813: }
        !          4814:
        !          4815: int
        !          4816: pf_routable(struct pf_addr *addr, sa_family_t af, struct pfi_kif *kif)
        !          4817: {
        !          4818:        struct sockaddr_in      *dst;
        !          4819:        int                      ret = 1;
        !          4820:        int                      check_mpath;
        !          4821:        extern int               ipmultipath;
        !          4822: #ifdef INET6
        !          4823:        extern int               ip6_multipath;
        !          4824:        struct sockaddr_in6     *dst6;
        !          4825:        struct route_in6         ro;
        !          4826: #else
        !          4827:        struct route             ro;
        !          4828: #endif
        !          4829:        struct radix_node       *rn;
        !          4830:        struct rtentry          *rt;
        !          4831:        struct ifnet            *ifp;
        !          4832:
        !          4833:        check_mpath = 0;
        !          4834:        bzero(&ro, sizeof(ro));
        !          4835:        switch (af) {
        !          4836:        case AF_INET:
        !          4837:                dst = satosin(&ro.ro_dst);
        !          4838:                dst->sin_family = AF_INET;
        !          4839:                dst->sin_len = sizeof(*dst);
        !          4840:                dst->sin_addr = addr->v4;
        !          4841:                if (ipmultipath)
        !          4842:                        check_mpath = 1;
        !          4843:                break;
        !          4844: #ifdef INET6
        !          4845:        case AF_INET6:
        !          4846:                dst6 = (struct sockaddr_in6 *)&ro.ro_dst;
        !          4847:                dst6->sin6_family = AF_INET6;
        !          4848:                dst6->sin6_len = sizeof(*dst6);
        !          4849:                dst6->sin6_addr = addr->v6;
        !          4850:                if (ip6_multipath)
        !          4851:                        check_mpath = 1;
        !          4852:                break;
        !          4853: #endif /* INET6 */
        !          4854:        default:
        !          4855:                return (0);
        !          4856:        }
        !          4857:
        !          4858:        /* Skip checks for ipsec interfaces */
        !          4859:        if (kif != NULL && kif->pfik_ifp->if_type == IFT_ENC)
        !          4860:                goto out;
        !          4861:
        !          4862:        rtalloc_noclone((struct route *)&ro, NO_CLONING);
        !          4863:
        !          4864:        if (ro.ro_rt != NULL) {
        !          4865:                /* No interface given, this is a no-route check */
        !          4866:                if (kif == NULL)
        !          4867:                        goto out;
        !          4868:
        !          4869:                if (kif->pfik_ifp == NULL) {
        !          4870:                        ret = 0;
        !          4871:                        goto out;
        !          4872:                }
        !          4873:
        !          4874:                /* Perform uRPF check if passed input interface */
        !          4875:                ret = 0;
        !          4876:                rn = (struct radix_node *)ro.ro_rt;
        !          4877:                do {
        !          4878:                        rt = (struct rtentry *)rn;
        !          4879:                        if (rt->rt_ifp->if_type == IFT_CARP)
        !          4880:                                ifp = rt->rt_ifp->if_carpdev;
        !          4881:                        else
        !          4882:                                ifp = rt->rt_ifp;
        !          4883:
        !          4884:                        if (kif->pfik_ifp == ifp)
        !          4885:                                ret = 1;
        !          4886:                        rn = rn_mpath_next(rn);
        !          4887:                } while (check_mpath == 1 && rn != NULL && ret == 0);
        !          4888:        } else
        !          4889:                ret = 0;
        !          4890: out:
        !          4891:        if (ro.ro_rt != NULL)
        !          4892:                RTFREE(ro.ro_rt);
        !          4893:        return (ret);
        !          4894: }
        !          4895:
        !          4896: int
        !          4897: pf_rtlabel_match(struct pf_addr *addr, sa_family_t af, struct pf_addr_wrap *aw)
        !          4898: {
        !          4899:        struct sockaddr_in      *dst;
        !          4900: #ifdef INET6
        !          4901:        struct sockaddr_in6     *dst6;
        !          4902:        struct route_in6         ro;
        !          4903: #else
        !          4904:        struct route             ro;
        !          4905: #endif
        !          4906:        int                      ret = 0;
        !          4907:
        !          4908:        bzero(&ro, sizeof(ro));
        !          4909:        switch (af) {
        !          4910:        case AF_INET:
        !          4911:                dst = satosin(&ro.ro_dst);
        !          4912:                dst->sin_family = AF_INET;
        !          4913:                dst->sin_len = sizeof(*dst);
        !          4914:                dst->sin_addr = addr->v4;
        !          4915:                break;
        !          4916: #ifdef INET6
        !          4917:        case AF_INET6:
        !          4918:                dst6 = (struct sockaddr_in6 *)&ro.ro_dst;
        !          4919:                dst6->sin6_family = AF_INET6;
        !          4920:                dst6->sin6_len = sizeof(*dst6);
        !          4921:                dst6->sin6_addr = addr->v6;
        !          4922:                break;
        !          4923: #endif /* INET6 */
        !          4924:        default:
        !          4925:                return (0);
        !          4926:        }
        !          4927:
        !          4928:        rtalloc_noclone((struct route *)&ro, NO_CLONING);
        !          4929:
        !          4930:        if (ro.ro_rt != NULL) {
        !          4931:                if (ro.ro_rt->rt_labelid == aw->v.rtlabel)
        !          4932:                        ret = 1;
        !          4933:                RTFREE(ro.ro_rt);
        !          4934:        }
        !          4935:
        !          4936:        return (ret);
        !          4937: }
        !          4938:
        !          4939: #ifdef INET
        !          4940: void
        !          4941: pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
        !          4942:     struct pf_state *s, struct pf_pdesc *pd)
        !          4943: {
        !          4944:        struct mbuf             *m0, *m1;
        !          4945:        struct route             iproute;
        !          4946:        struct route            *ro = NULL;
        !          4947:        struct sockaddr_in      *dst;
        !          4948:        struct ip               *ip;
        !          4949:        struct ifnet            *ifp = NULL;
        !          4950:        struct pf_addr           naddr;
        !          4951:        struct pf_src_node      *sn = NULL;
        !          4952:        int                      error = 0;
        !          4953: #ifdef IPSEC
        !          4954:        struct m_tag            *mtag;
        !          4955: #endif /* IPSEC */
        !          4956:
        !          4957:        if (m == NULL || *m == NULL || r == NULL ||
        !          4958:            (dir != PF_IN && dir != PF_OUT) || oifp == NULL)
        !          4959:                panic("pf_route: invalid parameters");
        !          4960:
        !          4961:        if ((*m)->m_pkthdr.pf.routed++ > 3) {
        !          4962:                m0 = *m;
        !          4963:                *m = NULL;
        !          4964:                goto bad;
        !          4965:        }
        !          4966:
        !          4967:        if (r->rt == PF_DUPTO) {
        !          4968:                if ((m0 = m_copym2(*m, 0, M_COPYALL, M_NOWAIT)) == NULL)
        !          4969:                        return;
        !          4970:        } else {
        !          4971:                if ((r->rt == PF_REPLYTO) == (r->direction == dir))
        !          4972:                        return;
        !          4973:                m0 = *m;
        !          4974:        }
        !          4975:
        !          4976:        if (m0->m_len < sizeof(struct ip)) {
        !          4977:                DPFPRINTF(PF_DEBUG_URGENT,
        !          4978:                    ("pf_route: m0->m_len < sizeof(struct ip)\n"));
        !          4979:                goto bad;
        !          4980:        }
        !          4981:
        !          4982:        ip = mtod(m0, struct ip *);
        !          4983:
        !          4984:        ro = &iproute;
        !          4985:        bzero((caddr_t)ro, sizeof(*ro));
        !          4986:        dst = satosin(&ro->ro_dst);
        !          4987:        dst->sin_family = AF_INET;
        !          4988:        dst->sin_len = sizeof(*dst);
        !          4989:        dst->sin_addr = ip->ip_dst;
        !          4990:
        !          4991:        if (r->rt == PF_FASTROUTE) {
        !          4992:                rtalloc(ro);
        !          4993:                if (ro->ro_rt == 0) {
        !          4994:                        ipstat.ips_noroute++;
        !          4995:                        goto bad;
        !          4996:                }
        !          4997:
        !          4998:                ifp = ro->ro_rt->rt_ifp;
        !          4999:                ro->ro_rt->rt_use++;
        !          5000:
        !          5001:                if (ro->ro_rt->rt_flags & RTF_GATEWAY)
        !          5002:                        dst = satosin(ro->ro_rt->rt_gateway);
        !          5003:        } else {
        !          5004:                if (TAILQ_EMPTY(&r->rpool.list)) {
        !          5005:                        DPFPRINTF(PF_DEBUG_URGENT,
        !          5006:                            ("pf_route: TAILQ_EMPTY(&r->rpool.list)\n"));
        !          5007:                        goto bad;
        !          5008:                }
        !          5009:                if (s == NULL) {
        !          5010:                        pf_map_addr(AF_INET, r, (struct pf_addr *)&ip->ip_src,
        !          5011:                            &naddr, NULL, &sn);
        !          5012:                        if (!PF_AZERO(&naddr, AF_INET))
        !          5013:                                dst->sin_addr.s_addr = naddr.v4.s_addr;
        !          5014:                        ifp = r->rpool.cur->kif ?
        !          5015:                            r->rpool.cur->kif->pfik_ifp : NULL;
        !          5016:                } else {
        !          5017:                        if (!PF_AZERO(&s->rt_addr, AF_INET))
        !          5018:                                dst->sin_addr.s_addr =
        !          5019:                                    s->rt_addr.v4.s_addr;
        !          5020:                        ifp = s->rt_kif ? s->rt_kif->pfik_ifp : NULL;
        !          5021:                }
        !          5022:        }
        !          5023:        if (ifp == NULL)
        !          5024:                goto bad;
        !          5025:
        !          5026:        if (oifp != ifp) {
        !          5027:                if (pf_test(PF_OUT, ifp, &m0, NULL) != PF_PASS)
        !          5028:                        goto bad;
        !          5029:                else if (m0 == NULL)
        !          5030:                        goto done;
        !          5031:                if (m0->m_len < sizeof(struct ip)) {
        !          5032:                        DPFPRINTF(PF_DEBUG_URGENT,
        !          5033:                            ("pf_route: m0->m_len < sizeof(struct ip)\n"));
        !          5034:                        goto bad;
        !          5035:                }
        !          5036:                ip = mtod(m0, struct ip *);
        !          5037:        }
        !          5038:
        !          5039:        /* Copied from ip_output. */
        !          5040: #ifdef IPSEC
        !          5041:        /*
        !          5042:         * If deferred crypto processing is needed, check that the
        !          5043:         * interface supports it.
        !          5044:         */
        !          5045:        if ((mtag = m_tag_find(m0, PACKET_TAG_IPSEC_OUT_CRYPTO_NEEDED, NULL))
        !          5046:            != NULL && (ifp->if_capabilities & IFCAP_IPSEC) == 0) {
        !          5047:                /* Notify IPsec to do its own crypto. */
        !          5048:                ipsp_skipcrypto_unmark((struct tdb_ident *)(mtag + 1));
        !          5049:                goto bad;
        !          5050:        }
        !          5051: #endif /* IPSEC */
        !          5052:
        !          5053:        /* Catch routing changes wrt. hardware checksumming for TCP or UDP. */
        !          5054:        if (m0->m_pkthdr.csum_flags & M_TCPV4_CSUM_OUT) {
        !          5055:                if (!(ifp->if_capabilities & IFCAP_CSUM_TCPv4) ||
        !          5056:                    ifp->if_bridge != NULL) {
        !          5057:                        in_delayed_cksum(m0);
        !          5058:                        m0->m_pkthdr.csum_flags &= ~M_TCPV4_CSUM_OUT; /* Clear */
        !          5059:                }
        !          5060:        } else if (m0->m_pkthdr.csum_flags & M_UDPV4_CSUM_OUT) {
        !          5061:                if (!(ifp->if_capabilities & IFCAP_CSUM_UDPv4) ||
        !          5062:                    ifp->if_bridge != NULL) {
        !          5063:                        in_delayed_cksum(m0);
        !          5064:                        m0->m_pkthdr.csum_flags &= ~M_UDPV4_CSUM_OUT; /* Clear */
        !          5065:                }
        !          5066:        }
        !          5067:
        !          5068:        if (ntohs(ip->ip_len) <= ifp->if_mtu) {
        !          5069:                if ((ifp->if_capabilities & IFCAP_CSUM_IPv4) &&
        !          5070:                    ifp->if_bridge == NULL) {
        !          5071:                        m0->m_pkthdr.csum_flags |= M_IPV4_CSUM_OUT;
        !          5072:                        ipstat.ips_outhwcsum++;
        !          5073:                } else {
        !          5074:                        ip->ip_sum = 0;
        !          5075:                        ip->ip_sum = in_cksum(m0, ip->ip_hl << 2);
        !          5076:                }
        !          5077:                /* Update relevant hardware checksum stats for TCP/UDP */
        !          5078:                if (m0->m_pkthdr.csum_flags & M_TCPV4_CSUM_OUT)
        !          5079:                        tcpstat.tcps_outhwcsum++;
        !          5080:                else if (m0->m_pkthdr.csum_flags & M_UDPV4_CSUM_OUT)
        !          5081:                        udpstat.udps_outhwcsum++;
        !          5082:                error = (*ifp->if_output)(ifp, m0, sintosa(dst), NULL);
        !          5083:                goto done;
        !          5084:        }
        !          5085:
        !          5086:        /*
        !          5087:         * Too large for interface; fragment if possible.
        !          5088:         * Must be able to put at least 8 bytes per fragment.
        !          5089:         */
        !          5090:        if (ip->ip_off & htons(IP_DF)) {
        !          5091:                ipstat.ips_cantfrag++;
        !          5092:                if (r->rt != PF_DUPTO) {
        !          5093:                        icmp_error(m0, ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG, 0,
        !          5094:                            ifp->if_mtu);
        !          5095:                        goto done;
        !          5096:                } else
        !          5097:                        goto bad;
        !          5098:        }
        !          5099:
        !          5100:        m1 = m0;
        !          5101:        error = ip_fragment(m0, ifp, ifp->if_mtu);
        !          5102:        if (error) {
        !          5103:                m0 = NULL;
        !          5104:                goto bad;
        !          5105:        }
        !          5106:
        !          5107:        for (m0 = m1; m0; m0 = m1) {
        !          5108:                m1 = m0->m_nextpkt;
        !          5109:                m0->m_nextpkt = 0;
        !          5110:                if (error == 0)
        !          5111:                        error = (*ifp->if_output)(ifp, m0, sintosa(dst),
        !          5112:                            NULL);
        !          5113:                else
        !          5114:                        m_freem(m0);
        !          5115:        }
        !          5116:
        !          5117:        if (error == 0)
        !          5118:                ipstat.ips_fragmented++;
        !          5119:
        !          5120: done:
        !          5121:        if (r->rt != PF_DUPTO)
        !          5122:                *m = NULL;
        !          5123:        if (ro == &iproute && ro->ro_rt)
        !          5124:                RTFREE(ro->ro_rt);
        !          5125:        return;
        !          5126:
        !          5127: bad:
        !          5128:        m_freem(m0);
        !          5129:        goto done;
        !          5130: }
        !          5131: #endif /* INET */
        !          5132:
        !          5133: #ifdef INET6
        !          5134: void
        !          5135: pf_route6(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
        !          5136:     struct pf_state *s, struct pf_pdesc *pd)
        !          5137: {
        !          5138:        struct mbuf             *m0;
        !          5139:        struct route_in6         ip6route;
        !          5140:        struct route_in6        *ro;
        !          5141:        struct sockaddr_in6     *dst;
        !          5142:        struct ip6_hdr          *ip6;
        !          5143:        struct ifnet            *ifp = NULL;
        !          5144:        struct pf_addr           naddr;
        !          5145:        struct pf_src_node      *sn = NULL;
        !          5146:        int                      error = 0;
        !          5147:
        !          5148:        if (m == NULL || *m == NULL || r == NULL ||
        !          5149:            (dir != PF_IN && dir != PF_OUT) || oifp == NULL)
        !          5150:                panic("pf_route6: invalid parameters");
        !          5151:
        !          5152:        if ((*m)->m_pkthdr.pf.routed++ > 3) {
        !          5153:                m0 = *m;
        !          5154:                *m = NULL;
        !          5155:                goto bad;
        !          5156:        }
        !          5157:
        !          5158:        if (r->rt == PF_DUPTO) {
        !          5159:                if ((m0 = m_copym2(*m, 0, M_COPYALL, M_NOWAIT)) == NULL)
        !          5160:                        return;
        !          5161:        } else {
        !          5162:                if ((r->rt == PF_REPLYTO) == (r->direction == dir))
        !          5163:                        return;
        !          5164:                m0 = *m;
        !          5165:        }
        !          5166:
        !          5167:        if (m0->m_len < sizeof(struct ip6_hdr)) {
        !          5168:                DPFPRINTF(PF_DEBUG_URGENT,
        !          5169:                    ("pf_route6: m0->m_len < sizeof(struct ip6_hdr)\n"));
        !          5170:                goto bad;
        !          5171:        }
        !          5172:        ip6 = mtod(m0, struct ip6_hdr *);
        !          5173:
        !          5174:        ro = &ip6route;
        !          5175:        bzero((caddr_t)ro, sizeof(*ro));
        !          5176:        dst = (struct sockaddr_in6 *)&ro->ro_dst;
        !          5177:        dst->sin6_family = AF_INET6;
        !          5178:        dst->sin6_len = sizeof(*dst);
        !          5179:        dst->sin6_addr = ip6->ip6_dst;
        !          5180:
        !          5181:        /* Cheat. XXX why only in the v6 case??? */
        !          5182:        if (r->rt == PF_FASTROUTE) {
        !          5183:                m0->m_pkthdr.pf.flags |= PF_TAG_GENERATED;
        !          5184:                ip6_output(m0, NULL, NULL, 0, NULL, NULL, NULL);
        !          5185:                return;
        !          5186:        }
        !          5187:
        !          5188:        if (TAILQ_EMPTY(&r->rpool.list)) {
        !          5189:                DPFPRINTF(PF_DEBUG_URGENT,
        !          5190:                    ("pf_route6: TAILQ_EMPTY(&r->rpool.list)\n"));
        !          5191:                goto bad;
        !          5192:        }
        !          5193:        if (s == NULL) {
        !          5194:                pf_map_addr(AF_INET6, r, (struct pf_addr *)&ip6->ip6_src,
        !          5195:                    &naddr, NULL, &sn);
        !          5196:                if (!PF_AZERO(&naddr, AF_INET6))
        !          5197:                        PF_ACPY((struct pf_addr *)&dst->sin6_addr,
        !          5198:                            &naddr, AF_INET6);
        !          5199:                ifp = r->rpool.cur->kif ? r->rpool.cur->kif->pfik_ifp : NULL;
        !          5200:        } else {
        !          5201:                if (!PF_AZERO(&s->rt_addr, AF_INET6))
        !          5202:                        PF_ACPY((struct pf_addr *)&dst->sin6_addr,
        !          5203:                            &s->rt_addr, AF_INET6);
        !          5204:                ifp = s->rt_kif ? s->rt_kif->pfik_ifp : NULL;
        !          5205:        }
        !          5206:        if (ifp == NULL)
        !          5207:                goto bad;
        !          5208:
        !          5209:        if (oifp != ifp) {
        !          5210:                if (pf_test6(PF_OUT, ifp, &m0, NULL) != PF_PASS)
        !          5211:                        goto bad;
        !          5212:                else if (m0 == NULL)
        !          5213:                        goto done;
        !          5214:                if (m0->m_len < sizeof(struct ip6_hdr)) {
        !          5215:                        DPFPRINTF(PF_DEBUG_URGENT,
        !          5216:                            ("pf_route6: m0->m_len < sizeof(struct ip6_hdr)\n"));
        !          5217:                        goto bad;
        !          5218:                }
        !          5219:                ip6 = mtod(m0, struct ip6_hdr *);
        !          5220:        }
        !          5221:
        !          5222:        /*
        !          5223:         * If the packet is too large for the outgoing interface,
        !          5224:         * send back an icmp6 error.
        !          5225:         */
        !          5226:        if (IN6_IS_SCOPE_EMBED(&dst->sin6_addr))
        !          5227:                dst->sin6_addr.s6_addr16[1] = htons(ifp->if_index);
        !          5228:        if ((u_long)m0->m_pkthdr.len <= ifp->if_mtu) {
        !          5229:                error = nd6_output(ifp, ifp, m0, dst, NULL);
        !          5230:        } else {
        !          5231:                in6_ifstat_inc(ifp, ifs6_in_toobig);
        !          5232:                if (r->rt != PF_DUPTO)
        !          5233:                        icmp6_error(m0, ICMP6_PACKET_TOO_BIG, 0, ifp->if_mtu);
        !          5234:                else
        !          5235:                        goto bad;
        !          5236:        }
        !          5237:
        !          5238: done:
        !          5239:        if (r->rt != PF_DUPTO)
        !          5240:                *m = NULL;
        !          5241:        return;
        !          5242:
        !          5243: bad:
        !          5244:        m_freem(m0);
        !          5245:        goto done;
        !          5246: }
        !          5247: #endif /* INET6 */
        !          5248:
        !          5249:
        !          5250: /*
        !          5251:  * check protocol (tcp/udp/icmp/icmp6) checksum and set mbuf flag
        !          5252:  *   off is the offset where the protocol header starts
        !          5253:  *   len is the total length of protocol header plus payload
        !          5254:  * returns 0 when the checksum is valid, otherwise returns 1.
        !          5255:  */
        !          5256: int
        !          5257: pf_check_proto_cksum(struct mbuf *m, int off, int len, u_int8_t p,
        !          5258:     sa_family_t af)
        !          5259: {
        !          5260:        u_int16_t flag_ok, flag_bad;
        !          5261:        u_int16_t sum;
        !          5262:
        !          5263:        switch (p) {
        !          5264:        case IPPROTO_TCP:
        !          5265:                flag_ok = M_TCP_CSUM_IN_OK;
        !          5266:                flag_bad = M_TCP_CSUM_IN_BAD;
        !          5267:                break;
        !          5268:        case IPPROTO_UDP:
        !          5269:                flag_ok = M_UDP_CSUM_IN_OK;
        !          5270:                flag_bad = M_UDP_CSUM_IN_BAD;
        !          5271:                break;
        !          5272:        case IPPROTO_ICMP:
        !          5273: #ifdef INET6
        !          5274:        case IPPROTO_ICMPV6:
        !          5275: #endif /* INET6 */
        !          5276:                flag_ok = flag_bad = 0;
        !          5277:                break;
        !          5278:        default:
        !          5279:                return (1);
        !          5280:        }
        !          5281:        if (m->m_pkthdr.csum_flags & flag_ok)
        !          5282:                return (0);
        !          5283:        if (m->m_pkthdr.csum_flags & flag_bad)
        !          5284:                return (1);
        !          5285:        if (off < sizeof(struct ip) || len < sizeof(struct udphdr))
        !          5286:                return (1);
        !          5287:        if (m->m_pkthdr.len < off + len)
        !          5288:                return (1);
        !          5289:        switch (af) {
        !          5290: #ifdef INET
        !          5291:        case AF_INET:
        !          5292:                if (p == IPPROTO_ICMP) {
        !          5293:                        if (m->m_len < off)
        !          5294:                                return (1);
        !          5295:                        m->m_data += off;
        !          5296:                        m->m_len -= off;
        !          5297:                        sum = in_cksum(m, len);
        !          5298:                        m->m_data -= off;
        !          5299:                        m->m_len += off;
        !          5300:                } else {
        !          5301:                        if (m->m_len < sizeof(struct ip))
        !          5302:                                return (1);
        !          5303:                        sum = in4_cksum(m, p, off, len);
        !          5304:                }
        !          5305:                break;
        !          5306: #endif /* INET */
        !          5307: #ifdef INET6
        !          5308:        case AF_INET6:
        !          5309:                if (m->m_len < sizeof(struct ip6_hdr))
        !          5310:                        return (1);
        !          5311:                sum = in6_cksum(m, p, off, len);
        !          5312:                break;
        !          5313: #endif /* INET6 */
        !          5314:        default:
        !          5315:                return (1);
        !          5316:        }
        !          5317:        if (sum) {
        !          5318:                m->m_pkthdr.csum_flags |= flag_bad;
        !          5319:                switch (p) {
        !          5320:                case IPPROTO_TCP:
        !          5321:                        tcpstat.tcps_rcvbadsum++;
        !          5322:                        break;
        !          5323:                case IPPROTO_UDP:
        !          5324:                        udpstat.udps_badsum++;
        !          5325:                        break;
        !          5326:                case IPPROTO_ICMP:
        !          5327:                        icmpstat.icps_checksum++;
        !          5328:                        break;
        !          5329: #ifdef INET6
        !          5330:                case IPPROTO_ICMPV6:
        !          5331:                        icmp6stat.icp6s_checksum++;
        !          5332:                        break;
        !          5333: #endif /* INET6 */
        !          5334:                }
        !          5335:                return (1);
        !          5336:        }
        !          5337:        m->m_pkthdr.csum_flags |= flag_ok;
        !          5338:        return (0);
        !          5339: }
        !          5340:
        !          5341: #ifdef INET
        !          5342: int
        !          5343: pf_test(int dir, struct ifnet *ifp, struct mbuf **m0,
        !          5344:     struct ether_header *eh)
        !          5345: {
        !          5346:        struct pfi_kif          *kif;
        !          5347:        u_short                  action, reason = 0, log = 0;
        !          5348:        struct mbuf             *m = *m0;
        !          5349:        struct ip               *h;
        !          5350:        struct pf_rule          *a = NULL, *r = &pf_default_rule, *tr, *nr;
        !          5351:        struct pf_state         *s = NULL;
        !          5352:        struct pf_state_key     *sk = NULL;
        !          5353:        struct pf_ruleset       *ruleset = NULL;
        !          5354:        struct pf_pdesc          pd;
        !          5355:        int                      off, dirndx, pqid = 0;
        !          5356:
        !          5357:        if (!pf_status.running)
        !          5358:                return (PF_PASS);
        !          5359:
        !          5360:        memset(&pd, 0, sizeof(pd));
        !          5361:        if (ifp->if_type == IFT_CARP && ifp->if_carpdev)
        !          5362:                kif = (struct pfi_kif *)ifp->if_carpdev->if_pf_kif;
        !          5363:        else
        !          5364:                kif = (struct pfi_kif *)ifp->if_pf_kif;
        !          5365:
        !          5366:        if (kif == NULL) {
        !          5367:                DPFPRINTF(PF_DEBUG_URGENT,
        !          5368:                    ("pf_test: kif == NULL, if_xname %s\n", ifp->if_xname));
        !          5369:                return (PF_DROP);
        !          5370:        }
        !          5371:        if (kif->pfik_flags & PFI_IFLAG_SKIP)
        !          5372:                return (PF_PASS);
        !          5373:
        !          5374: #ifdef DIAGNOSTIC
        !          5375:        if ((m->m_flags & M_PKTHDR) == 0)
        !          5376:                panic("non-M_PKTHDR is passed to pf_test");
        !          5377: #endif /* DIAGNOSTIC */
        !          5378:
        !          5379:        if (m->m_pkthdr.len < (int)sizeof(*h)) {
        !          5380:                action = PF_DROP;
        !          5381:                REASON_SET(&reason, PFRES_SHORT);
        !          5382:                log = 1;
        !          5383:                goto done;
        !          5384:        }
        !          5385:
        !          5386:        if (m->m_pkthdr.pf.flags & PF_TAG_GENERATED)
        !          5387:                return (PF_PASS);
        !          5388:
        !          5389:        /* We do IP header normalization and packet reassembly here */
        !          5390:        if (pf_normalize_ip(m0, dir, kif, &reason, &pd) != PF_PASS) {
        !          5391:                action = PF_DROP;
        !          5392:                goto done;
        !          5393:        }
        !          5394:        m = *m0;        /* pf_normalize messes with m0 */
        !          5395:        h = mtod(m, struct ip *);
        !          5396:
        !          5397:        off = h->ip_hl << 2;
        !          5398:        if (off < (int)sizeof(*h)) {
        !          5399:                action = PF_DROP;
        !          5400:                REASON_SET(&reason, PFRES_SHORT);
        !          5401:                log = 1;
        !          5402:                goto done;
        !          5403:        }
        !          5404:
        !          5405:        pd.src = (struct pf_addr *)&h->ip_src;
        !          5406:        pd.dst = (struct pf_addr *)&h->ip_dst;
        !          5407:        PF_ACPY(&pd.baddr, dir == PF_OUT ? pd.src : pd.dst, AF_INET);
        !          5408:        pd.ip_sum = &h->ip_sum;
        !          5409:        pd.proto = h->ip_p;
        !          5410:        pd.af = AF_INET;
        !          5411:        pd.tos = h->ip_tos;
        !          5412:        pd.tot_len = ntohs(h->ip_len);
        !          5413:        pd.eh = eh;
        !          5414:
        !          5415:        /* handle fragments that didn't get reassembled by normalization */
        !          5416:        if (h->ip_off & htons(IP_MF | IP_OFFMASK)) {
        !          5417:                action = pf_test_fragment(&r, dir, kif, m, h,
        !          5418:                    &pd, &a, &ruleset);
        !          5419:                goto done;
        !          5420:        }
        !          5421:
        !          5422:        switch (h->ip_p) {
        !          5423:
        !          5424:        case IPPROTO_TCP: {
        !          5425:                struct tcphdr   th;
        !          5426:
        !          5427:                pd.hdr.tcp = &th;
        !          5428:                if (!pf_pull_hdr(m, off, &th, sizeof(th),
        !          5429:                    &action, &reason, AF_INET)) {
        !          5430:                        log = action != PF_PASS;
        !          5431:                        goto done;
        !          5432:                }
        !          5433:                pd.p_len = pd.tot_len - off - (th.th_off << 2);
        !          5434:                if ((th.th_flags & TH_ACK) && pd.p_len == 0)
        !          5435:                        pqid = 1;
        !          5436:                action = pf_normalize_tcp(dir, kif, m, 0, off, h, &pd);
        !          5437:                if (action == PF_DROP)
        !          5438:                        goto done;
        !          5439:                action = pf_test_state_tcp(&s, dir, kif, m, off, h, &pd,
        !          5440:                    &reason);
        !          5441:                if (action == PF_PASS) {
        !          5442: #if NPFSYNC
        !          5443:                        pfsync_update_state(s);
        !          5444: #endif /* NPFSYNC */
        !          5445:                        r = s->rule.ptr;
        !          5446:                        a = s->anchor.ptr;
        !          5447:                        log = s->log;
        !          5448:                } else if (s == NULL)
        !          5449:                        action = pf_test_rule(&r, &s, dir, kif,
        !          5450:                            m, off, h, &pd, &a, &ruleset, &ipintrq);
        !          5451:                break;
        !          5452:        }
        !          5453:
        !          5454:        case IPPROTO_UDP: {
        !          5455:                struct udphdr   uh;
        !          5456:
        !          5457:                pd.hdr.udp = &uh;
        !          5458:                if (!pf_pull_hdr(m, off, &uh, sizeof(uh),
        !          5459:                    &action, &reason, AF_INET)) {
        !          5460:                        log = action != PF_PASS;
        !          5461:                        goto done;
        !          5462:                }
        !          5463:                if (uh.uh_dport == 0 ||
        !          5464:                    ntohs(uh.uh_ulen) > m->m_pkthdr.len - off ||
        !          5465:                    ntohs(uh.uh_ulen) < sizeof(struct udphdr)) {
        !          5466:                        action = PF_DROP;
        !          5467:                        REASON_SET(&reason, PFRES_SHORT);
        !          5468:                        goto done;
        !          5469:                }
        !          5470:                action = pf_test_state_udp(&s, dir, kif, m, off, h, &pd);
        !          5471:                if (action == PF_PASS) {
        !          5472: #if NPFSYNC
        !          5473:                        pfsync_update_state(s);
        !          5474: #endif /* NPFSYNC */
        !          5475:                        r = s->rule.ptr;
        !          5476:                        a = s->anchor.ptr;
        !          5477:                        log = s->log;
        !          5478:                } else if (s == NULL)
        !          5479:                        action = pf_test_rule(&r, &s, dir, kif,
        !          5480:                            m, off, h, &pd, &a, &ruleset, &ipintrq);
        !          5481:                break;
        !          5482:        }
        !          5483:
        !          5484:        case IPPROTO_ICMP: {
        !          5485:                struct icmp     ih;
        !          5486:
        !          5487:                pd.hdr.icmp = &ih;
        !          5488:                if (!pf_pull_hdr(m, off, &ih, ICMP_MINLEN,
        !          5489:                    &action, &reason, AF_INET)) {
        !          5490:                        log = action != PF_PASS;
        !          5491:                        goto done;
        !          5492:                }
        !          5493:                action = pf_test_state_icmp(&s, dir, kif, m, off, h, &pd,
        !          5494:                    &reason);
        !          5495:                if (action == PF_PASS) {
        !          5496: #if NPFSYNC
        !          5497:                        pfsync_update_state(s);
        !          5498: #endif /* NPFSYNC */
        !          5499:                        r = s->rule.ptr;
        !          5500:                        a = s->anchor.ptr;
        !          5501:                        log = s->log;
        !          5502:                } else if (s == NULL)
        !          5503:                        action = pf_test_rule(&r, &s, dir, kif,
        !          5504:                            m, off, h, &pd, &a, &ruleset, &ipintrq);
        !          5505:                break;
        !          5506:        }
        !          5507:
        !          5508:        default:
        !          5509:                action = pf_test_state_other(&s, dir, kif, &pd);
        !          5510:                if (action == PF_PASS) {
        !          5511: #if NPFSYNC
        !          5512:                        pfsync_update_state(s);
        !          5513: #endif /* NPFSYNC */
        !          5514:                        r = s->rule.ptr;
        !          5515:                        a = s->anchor.ptr;
        !          5516:                        log = s->log;
        !          5517:                } else if (s == NULL)
        !          5518:                        action = pf_test_rule(&r, &s, dir, kif, m, off, h,
        !          5519:                            &pd, &a, &ruleset, &ipintrq);
        !          5520:                break;
        !          5521:        }
        !          5522:
        !          5523: done:
        !          5524:        if (action == PF_PASS && h->ip_hl > 5 &&
        !          5525:            !((s && s->allow_opts) || r->allow_opts)) {
        !          5526:                action = PF_DROP;
        !          5527:                REASON_SET(&reason, PFRES_IPOPTIONS);
        !          5528:                log = 1;
        !          5529:                DPFPRINTF(PF_DEBUG_MISC,
        !          5530:                    ("pf: dropping packet with ip options\n"));
        !          5531:        }
        !          5532:
        !          5533:        if ((s && s->tag) || r->rtableid)
        !          5534:                pf_tag_packet(m, s ? s->tag : 0, r->rtableid);
        !          5535:
        !          5536: #ifdef ALTQ
        !          5537:        if (action == PF_PASS && r->qid) {
        !          5538:                if (pqid || (pd.tos & IPTOS_LOWDELAY))
        !          5539:                        m->m_pkthdr.pf.qid = r->pqid;
        !          5540:                else
        !          5541:                        m->m_pkthdr.pf.qid = r->qid;
        !          5542:                /* add hints for ecn */
        !          5543:                m->m_pkthdr.pf.hdr = h;
        !          5544:        }
        !          5545: #endif /* ALTQ */
        !          5546:
        !          5547:        /*
        !          5548:         * connections redirected to loopback should not match sockets
        !          5549:         * bound specifically to loopback due to security implications,
        !          5550:         * see tcp_input() and in_pcblookup_listen().
        !          5551:         */
        !          5552:        if (dir == PF_IN && action == PF_PASS && (pd.proto == IPPROTO_TCP ||
        !          5553:            pd.proto == IPPROTO_UDP) && s != NULL && s->nat_rule.ptr != NULL &&
        !          5554:            (s->nat_rule.ptr->action == PF_RDR ||
        !          5555:            s->nat_rule.ptr->action == PF_BINAT) &&
        !          5556:            (ntohl(pd.dst->v4.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET)
        !          5557:                m->m_pkthdr.pf.flags |= PF_TAG_TRANSLATE_LOCALHOST;
        !          5558:
        !          5559:        if (log) {
        !          5560:                struct pf_rule *lr;
        !          5561:
        !          5562:                if (s != NULL && s->nat_rule.ptr != NULL &&
        !          5563:                    s->nat_rule.ptr->log & PF_LOG_ALL)
        !          5564:                        lr = s->nat_rule.ptr;
        !          5565:                else
        !          5566:                        lr = r;
        !          5567:                PFLOG_PACKET(kif, h, m, AF_INET, dir, reason, lr, a, ruleset,
        !          5568:                    &pd);
        !          5569:        }
        !          5570:
        !          5571:        kif->pfik_bytes[0][dir == PF_OUT][action != PF_PASS] += pd.tot_len;
        !          5572:        kif->pfik_packets[0][dir == PF_OUT][action != PF_PASS]++;
        !          5573:
        !          5574:        if (action == PF_PASS || r->action == PF_DROP) {
        !          5575:                dirndx = (dir == PF_OUT);
        !          5576:                r->packets[dirndx]++;
        !          5577:                r->bytes[dirndx] += pd.tot_len;
        !          5578:                if (a != NULL) {
        !          5579:                        a->packets[dirndx]++;
        !          5580:                        a->bytes[dirndx] += pd.tot_len;
        !          5581:                }
        !          5582:                if (s != NULL) {
        !          5583:                        sk = s->state_key;
        !          5584:                        if (s->nat_rule.ptr != NULL) {
        !          5585:                                s->nat_rule.ptr->packets[dirndx]++;
        !          5586:                                s->nat_rule.ptr->bytes[dirndx] += pd.tot_len;
        !          5587:                        }
        !          5588:                        if (s->src_node != NULL) {
        !          5589:                                s->src_node->packets[dirndx]++;
        !          5590:                                s->src_node->bytes[dirndx] += pd.tot_len;
        !          5591:                        }
        !          5592:                        if (s->nat_src_node != NULL) {
        !          5593:                                s->nat_src_node->packets[dirndx]++;
        !          5594:                                s->nat_src_node->bytes[dirndx] += pd.tot_len;
        !          5595:                        }
        !          5596:                        dirndx = (dir == sk->direction) ? 0 : 1;
        !          5597:                        s->packets[dirndx]++;
        !          5598:                        s->bytes[dirndx] += pd.tot_len;
        !          5599:                }
        !          5600:                tr = r;
        !          5601:                nr = (s != NULL) ? s->nat_rule.ptr : pd.nat_rule;
        !          5602:                if (nr != NULL) {
        !          5603:                        struct pf_addr *x;
        !          5604:                        /*
        !          5605:                         * XXX: we need to make sure that the addresses
        !          5606:                         * passed to pfr_update_stats() are the same than
        !          5607:                         * the addresses used during matching (pfr_match)
        !          5608:                         */
        !          5609:                        if (r == &pf_default_rule) {
        !          5610:                                tr = nr;
        !          5611:                                x = (sk == NULL || sk->direction == dir) ?
        !          5612:                                    &pd.baddr : &pd.naddr;
        !          5613:                        } else
        !          5614:                                x = (sk == NULL || sk->direction == dir) ?
        !          5615:                                    &pd.naddr : &pd.baddr;
        !          5616:                        if (x == &pd.baddr || s == NULL) {
        !          5617:                                /* we need to change the address */
        !          5618:                                if (dir == PF_OUT)
        !          5619:                                        pd.src = x;
        !          5620:                                else
        !          5621:                                        pd.dst = x;
        !          5622:                        }
        !          5623:                }
        !          5624:                if (tr->src.addr.type == PF_ADDR_TABLE)
        !          5625:                        pfr_update_stats(tr->src.addr.p.tbl, (sk == NULL ||
        !          5626:                            sk->direction == dir) ?
        !          5627:                            pd.src : pd.dst, pd.af,
        !          5628:                            pd.tot_len, dir == PF_OUT, r->action == PF_PASS,
        !          5629:                            tr->src.neg);
        !          5630:                if (tr->dst.addr.type == PF_ADDR_TABLE)
        !          5631:                        pfr_update_stats(tr->dst.addr.p.tbl, (sk == NULL ||
        !          5632:                            sk->direction == dir) ? pd.dst : pd.src, pd.af,
        !          5633:                            pd.tot_len, dir == PF_OUT, r->action == PF_PASS,
        !          5634:                            tr->dst.neg);
        !          5635:        }
        !          5636:
        !          5637:
        !          5638:        if (action == PF_SYNPROXY_DROP) {
        !          5639:                m_freem(*m0);
        !          5640:                *m0 = NULL;
        !          5641:                action = PF_PASS;
        !          5642:        } else if (r->rt)
        !          5643:                /* pf_route can free the mbuf causing *m0 to become NULL */
        !          5644:                pf_route(m0, r, dir, kif->pfik_ifp, s, &pd);
        !          5645:
        !          5646:        return (action);
        !          5647: }
        !          5648: #endif /* INET */
        !          5649:
        !          5650: #ifdef INET6
        !          5651: int
        !          5652: pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0,
        !          5653:     struct ether_header *eh)
        !          5654: {
        !          5655:        struct pfi_kif          *kif;
        !          5656:        u_short                  action, reason = 0, log = 0;
        !          5657:        struct mbuf             *m = *m0, *n = NULL;
        !          5658:        struct ip6_hdr          *h;
        !          5659:        struct pf_rule          *a = NULL, *r = &pf_default_rule, *tr, *nr;
        !          5660:        struct pf_state         *s = NULL;
        !          5661:        struct pf_state_key     *sk = NULL;
        !          5662:        struct pf_ruleset       *ruleset = NULL;
        !          5663:        struct pf_pdesc          pd;
        !          5664:        int                      off, terminal = 0, dirndx, rh_cnt = 0;
        !          5665:
        !          5666:        if (!pf_status.running)
        !          5667:                return (PF_PASS);
        !          5668:
        !          5669:        memset(&pd, 0, sizeof(pd));
        !          5670:        if (ifp->if_type == IFT_CARP && ifp->if_carpdev)
        !          5671:                kif = (struct pfi_kif *)ifp->if_carpdev->if_pf_kif;
        !          5672:        else
        !          5673:                kif = (struct pfi_kif *)ifp->if_pf_kif;
        !          5674:
        !          5675:        if (kif == NULL) {
        !          5676:                DPFPRINTF(PF_DEBUG_URGENT,
        !          5677:                    ("pf_test6: kif == NULL, if_xname %s\n", ifp->if_xname));
        !          5678:                return (PF_DROP);
        !          5679:        }
        !          5680:        if (kif->pfik_flags & PFI_IFLAG_SKIP)
        !          5681:                return (PF_PASS);
        !          5682:
        !          5683: #ifdef DIAGNOSTIC
        !          5684:        if ((m->m_flags & M_PKTHDR) == 0)
        !          5685:                panic("non-M_PKTHDR is passed to pf_test6");
        !          5686: #endif /* DIAGNOSTIC */
        !          5687:
        !          5688:        if (m->m_pkthdr.len < (int)sizeof(*h)) {
        !          5689:                action = PF_DROP;
        !          5690:                REASON_SET(&reason, PFRES_SHORT);
        !          5691:                log = 1;
        !          5692:                goto done;
        !          5693:        }
        !          5694:
        !          5695:        if (m->m_pkthdr.pf.flags & PF_TAG_GENERATED)
        !          5696:                return (PF_PASS);
        !          5697:
        !          5698:        /* We do IP header normalization and packet reassembly here */
        !          5699:        if (pf_normalize_ip6(m0, dir, kif, &reason, &pd) != PF_PASS) {
        !          5700:                action = PF_DROP;
        !          5701:                goto done;
        !          5702:        }
        !          5703:        m = *m0;        /* pf_normalize messes with m0 */
        !          5704:        h = mtod(m, struct ip6_hdr *);
        !          5705:
        !          5706: #if 1
        !          5707:        /*
        !          5708:         * we do not support jumbogram yet.  if we keep going, zero ip6_plen
        !          5709:         * will do something bad, so drop the packet for now.
        !          5710:         */
        !          5711:        if (htons(h->ip6_plen) == 0) {
        !          5712:                action = PF_DROP;
        !          5713:                REASON_SET(&reason, PFRES_NORM);        /*XXX*/
        !          5714:                goto done;
        !          5715:        }
        !          5716: #endif
        !          5717:
        !          5718:        pd.src = (struct pf_addr *)&h->ip6_src;
        !          5719:        pd.dst = (struct pf_addr *)&h->ip6_dst;
        !          5720:        PF_ACPY(&pd.baddr, dir == PF_OUT ? pd.src : pd.dst, AF_INET6);
        !          5721:        pd.ip_sum = NULL;
        !          5722:        pd.af = AF_INET6;
        !          5723:        pd.tos = 0;
        !          5724:        pd.tot_len = ntohs(h->ip6_plen) + sizeof(struct ip6_hdr);
        !          5725:        pd.eh = eh;
        !          5726:
        !          5727:        off = ((caddr_t)h - m->m_data) + sizeof(struct ip6_hdr);
        !          5728:        pd.proto = h->ip6_nxt;
        !          5729:        do {
        !          5730:                switch (pd.proto) {
        !          5731:                case IPPROTO_FRAGMENT:
        !          5732:                        action = pf_test_fragment(&r, dir, kif, m, h,
        !          5733:                            &pd, &a, &ruleset);
        !          5734:                        if (action == PF_DROP)
        !          5735:                                REASON_SET(&reason, PFRES_FRAG);
        !          5736:                        goto done;
        !          5737:                case IPPROTO_ROUTING: {
        !          5738:                        struct ip6_rthdr rthdr;
        !          5739:
        !          5740:                        if (rh_cnt++) {
        !          5741:                                DPFPRINTF(PF_DEBUG_MISC,
        !          5742:                                    ("pf: IPv6 more than one rthdr\n"));
        !          5743:                                action = PF_DROP;
        !          5744:                                REASON_SET(&reason, PFRES_IPOPTIONS);
        !          5745:                                log = 1;
        !          5746:                                goto done;
        !          5747:                        }
        !          5748:                        if (!pf_pull_hdr(m, off, &rthdr, sizeof(rthdr), NULL,
        !          5749:                            &reason, pd.af)) {
        !          5750:                                DPFPRINTF(PF_DEBUG_MISC,
        !          5751:                                    ("pf: IPv6 short rthdr\n"));
        !          5752:                                action = PF_DROP;
        !          5753:                                REASON_SET(&reason, PFRES_SHORT);
        !          5754:                                log = 1;
        !          5755:                                goto done;
        !          5756:                        }
        !          5757:                        if (rthdr.ip6r_type == IPV6_RTHDR_TYPE_0) {
        !          5758:                                DPFPRINTF(PF_DEBUG_MISC,
        !          5759:                                    ("pf: IPv6 rthdr0\n"));
        !          5760:                                action = PF_DROP;
        !          5761:                                REASON_SET(&reason, PFRES_IPOPTIONS);
        !          5762:                                log = 1;
        !          5763:                                goto done;
        !          5764:                        }
        !          5765:                        /* FALLTHROUGH */
        !          5766:                }
        !          5767:                case IPPROTO_AH:
        !          5768:                case IPPROTO_HOPOPTS:
        !          5769:                case IPPROTO_DSTOPTS: {
        !          5770:                        /* get next header and header length */
        !          5771:                        struct ip6_ext  opt6;
        !          5772:
        !          5773:                        if (!pf_pull_hdr(m, off, &opt6, sizeof(opt6),
        !          5774:                            NULL, &reason, pd.af)) {
        !          5775:                                DPFPRINTF(PF_DEBUG_MISC,
        !          5776:                                    ("pf: IPv6 short opt\n"));
        !          5777:                                action = PF_DROP;
        !          5778:                                log = 1;
        !          5779:                                goto done;
        !          5780:                        }
        !          5781:                        if (pd.proto == IPPROTO_AH)
        !          5782:                                off += (opt6.ip6e_len + 2) * 4;
        !          5783:                        else
        !          5784:                                off += (opt6.ip6e_len + 1) * 8;
        !          5785:                        pd.proto = opt6.ip6e_nxt;
        !          5786:                        /* goto the next header */
        !          5787:                        break;
        !          5788:                }
        !          5789:                default:
        !          5790:                        terminal++;
        !          5791:                        break;
        !          5792:                }
        !          5793:        } while (!terminal);
        !          5794:
        !          5795:        /* if there's no routing header, use unmodified mbuf for checksumming */
        !          5796:        if (!n)
        !          5797:                n = m;
        !          5798:
        !          5799:        switch (pd.proto) {
        !          5800:
        !          5801:        case IPPROTO_TCP: {
        !          5802:                struct tcphdr   th;
        !          5803:
        !          5804:                pd.hdr.tcp = &th;
        !          5805:                if (!pf_pull_hdr(m, off, &th, sizeof(th),
        !          5806:                    &action, &reason, AF_INET6)) {
        !          5807:                        log = action != PF_PASS;
        !          5808:                        goto done;
        !          5809:                }
        !          5810:                pd.p_len = pd.tot_len - off - (th.th_off << 2);
        !          5811:                action = pf_normalize_tcp(dir, kif, m, 0, off, h, &pd);
        !          5812:                if (action == PF_DROP)
        !          5813:                        goto done;
        !          5814:                action = pf_test_state_tcp(&s, dir, kif, m, off, h, &pd,
        !          5815:                    &reason);
        !          5816:                if (action == PF_PASS) {
        !          5817: #if NPFSYNC
        !          5818:                        pfsync_update_state(s);
        !          5819: #endif /* NPFSYNC */
        !          5820:                        r = s->rule.ptr;
        !          5821:                        a = s->anchor.ptr;
        !          5822:                        log = s->log;
        !          5823:                } else if (s == NULL)
        !          5824:                        action = pf_test_rule(&r, &s, dir, kif,
        !          5825:                            m, off, h, &pd, &a, &ruleset, &ip6intrq);
        !          5826:                break;
        !          5827:        }
        !          5828:
        !          5829:        case IPPROTO_UDP: {
        !          5830:                struct udphdr   uh;
        !          5831:
        !          5832:                pd.hdr.udp = &uh;
        !          5833:                if (!pf_pull_hdr(m, off, &uh, sizeof(uh),
        !          5834:                    &action, &reason, AF_INET6)) {
        !          5835:                        log = action != PF_PASS;
        !          5836:                        goto done;
        !          5837:                }
        !          5838:                if (uh.uh_dport == 0 ||
        !          5839:                    ntohs(uh.uh_ulen) > m->m_pkthdr.len - off ||
        !          5840:                    ntohs(uh.uh_ulen) < sizeof(struct udphdr)) {
        !          5841:                        action = PF_DROP;
        !          5842:                        REASON_SET(&reason, PFRES_SHORT);
        !          5843:                        goto done;
        !          5844:                }
        !          5845:                action = pf_test_state_udp(&s, dir, kif, m, off, h, &pd);
        !          5846:                if (action == PF_PASS) {
        !          5847: #if NPFSYNC
        !          5848:                        pfsync_update_state(s);
        !          5849: #endif /* NPFSYNC */
        !          5850:                        r = s->rule.ptr;
        !          5851:                        a = s->anchor.ptr;
        !          5852:                        log = s->log;
        !          5853:                } else if (s == NULL)
        !          5854:                        action = pf_test_rule(&r, &s, dir, kif,
        !          5855:                            m, off, h, &pd, &a, &ruleset, &ip6intrq);
        !          5856:                break;
        !          5857:        }
        !          5858:
        !          5859:        case IPPROTO_ICMPV6: {
        !          5860:                struct icmp6_hdr        ih;
        !          5861:
        !          5862:                pd.hdr.icmp6 = &ih;
        !          5863:                if (!pf_pull_hdr(m, off, &ih, sizeof(ih),
        !          5864:                    &action, &reason, AF_INET6)) {
        !          5865:                        log = action != PF_PASS;
        !          5866:                        goto done;
        !          5867:                }
        !          5868:                action = pf_test_state_icmp(&s, dir, kif,
        !          5869:                    m, off, h, &pd, &reason);
        !          5870:                if (action == PF_PASS) {
        !          5871: #if NPFSYNC
        !          5872:                        pfsync_update_state(s);
        !          5873: #endif /* NPFSYNC */
        !          5874:                        r = s->rule.ptr;
        !          5875:                        a = s->anchor.ptr;
        !          5876:                        log = s->log;
        !          5877:                } else if (s == NULL)
        !          5878:                        action = pf_test_rule(&r, &s, dir, kif,
        !          5879:                            m, off, h, &pd, &a, &ruleset, &ip6intrq);
        !          5880:                break;
        !          5881:        }
        !          5882:
        !          5883:        default:
        !          5884:                action = pf_test_state_other(&s, dir, kif, &pd);
        !          5885:                if (action == PF_PASS) {
        !          5886: #if NPFSYNC
        !          5887:                        pfsync_update_state(s);
        !          5888: #endif /* NPFSYNC */
        !          5889:                        r = s->rule.ptr;
        !          5890:                        a = s->anchor.ptr;
        !          5891:                        log = s->log;
        !          5892:                } else if (s == NULL)
        !          5893:                        action = pf_test_rule(&r, &s, dir, kif, m, off, h,
        !          5894:                            &pd, &a, &ruleset, &ip6intrq);
        !          5895:                break;
        !          5896:        }
        !          5897:
        !          5898: done:
        !          5899:        if (n != m) {
        !          5900:                m_freem(n);
        !          5901:                n = NULL;
        !          5902:        }
        !          5903:
        !          5904:        /* handle dangerous IPv6 extension headers. */
        !          5905:        if (action == PF_PASS && rh_cnt &&
        !          5906:            !((s && s->allow_opts) || r->allow_opts)) {
        !          5907:                action = PF_DROP;
        !          5908:                REASON_SET(&reason, PFRES_IPOPTIONS);
        !          5909:                log = 1;
        !          5910:                DPFPRINTF(PF_DEBUG_MISC,
        !          5911:                    ("pf: dropping packet with dangerous v6 headers\n"));
        !          5912:        }
        !          5913:
        !          5914:        if ((s && s->tag) || r->rtableid)
        !          5915:                pf_tag_packet(m, s ? s->tag : 0, r->rtableid);
        !          5916:
        !          5917: #ifdef ALTQ
        !          5918:        if (action == PF_PASS && r->qid) {
        !          5919:                if (pd.tos & IPTOS_LOWDELAY)
        !          5920:                        m->m_pkthdr.pf.qid = r->pqid;
        !          5921:                else
        !          5922:                        m->m_pkthdr.pf.qid = r->qid;
        !          5923:                /* add hints for ecn */
        !          5924:                m->m_pkthdr.pf.hdr = h;
        !          5925:        }
        !          5926: #endif /* ALTQ */
        !          5927:
        !          5928:        if (dir == PF_IN && action == PF_PASS && (pd.proto == IPPROTO_TCP ||
        !          5929:            pd.proto == IPPROTO_UDP) && s != NULL && s->nat_rule.ptr != NULL &&
        !          5930:            (s->nat_rule.ptr->action == PF_RDR ||
        !          5931:            s->nat_rule.ptr->action == PF_BINAT) &&
        !          5932:            IN6_IS_ADDR_LOOPBACK(&pd.dst->v6))
        !          5933:                m->m_pkthdr.pf.flags |= PF_TAG_TRANSLATE_LOCALHOST;
        !          5934:
        !          5935:        if (log) {
        !          5936:                struct pf_rule *lr;
        !          5937:
        !          5938:                if (s != NULL && s->nat_rule.ptr != NULL &&
        !          5939:                    s->nat_rule.ptr->log & PF_LOG_ALL)
        !          5940:                        lr = s->nat_rule.ptr;
        !          5941:                else
        !          5942:                        lr = r;
        !          5943:                PFLOG_PACKET(kif, h, m, AF_INET6, dir, reason, lr, a, ruleset,
        !          5944:                    &pd);
        !          5945:        }
        !          5946:
        !          5947:        kif->pfik_bytes[1][dir == PF_OUT][action != PF_PASS] += pd.tot_len;
        !          5948:        kif->pfik_packets[1][dir == PF_OUT][action != PF_PASS]++;
        !          5949:
        !          5950:        if (action == PF_PASS || r->action == PF_DROP) {
        !          5951:                dirndx = (dir == PF_OUT);
        !          5952:                r->packets[dirndx]++;
        !          5953:                r->bytes[dirndx] += pd.tot_len;
        !          5954:                if (a != NULL) {
        !          5955:                        a->packets[dirndx]++;
        !          5956:                        a->bytes[dirndx] += pd.tot_len;
        !          5957:                }
        !          5958:                if (s != NULL) {
        !          5959:                        sk = s->state_key;
        !          5960:                        if (s->nat_rule.ptr != NULL) {
        !          5961:                                s->nat_rule.ptr->packets[dirndx]++;
        !          5962:                                s->nat_rule.ptr->bytes[dirndx] += pd.tot_len;
        !          5963:                        }
        !          5964:                        if (s->src_node != NULL) {
        !          5965:                                s->src_node->packets[dirndx]++;
        !          5966:                                s->src_node->bytes[dirndx] += pd.tot_len;
        !          5967:                        }
        !          5968:                        if (s->nat_src_node != NULL) {
        !          5969:                                s->nat_src_node->packets[dirndx]++;
        !          5970:                                s->nat_src_node->bytes[dirndx] += pd.tot_len;
        !          5971:                        }
        !          5972:                        dirndx = (dir == sk->direction) ? 0 : 1;
        !          5973:                        s->packets[dirndx]++;
        !          5974:                        s->bytes[dirndx] += pd.tot_len;
        !          5975:                }
        !          5976:                tr = r;
        !          5977:                nr = (s != NULL) ? s->nat_rule.ptr : pd.nat_rule;
        !          5978:                if (nr != NULL) {
        !          5979:                        struct pf_addr *x;
        !          5980:                        /*
        !          5981:                         * XXX: we need to make sure that the addresses
        !          5982:                         * passed to pfr_update_stats() are the same than
        !          5983:                         * the addresses used during matching (pfr_match)
        !          5984:                         */
        !          5985:                        if (r == &pf_default_rule) {
        !          5986:                                tr = nr;
        !          5987:                                x = (s == NULL || sk->direction == dir) ?
        !          5988:                                    &pd.baddr : &pd.naddr;
        !          5989:                        } else {
        !          5990:                                x = (s == NULL || sk->direction == dir) ?
        !          5991:                                    &pd.naddr : &pd.baddr;
        !          5992:                        }
        !          5993:                        if (x == &pd.baddr || s == NULL) {
        !          5994:                                if (dir == PF_OUT)
        !          5995:                                        pd.src = x;
        !          5996:                                else
        !          5997:                                        pd.dst = x;
        !          5998:                        }
        !          5999:                }
        !          6000:                if (tr->src.addr.type == PF_ADDR_TABLE)
        !          6001:                        pfr_update_stats(tr->src.addr.p.tbl, (sk == NULL ||
        !          6002:                            sk->direction == dir) ? pd.src : pd.dst, pd.af,
        !          6003:                            pd.tot_len, dir == PF_OUT, r->action == PF_PASS,
        !          6004:                            tr->src.neg);
        !          6005:                if (tr->dst.addr.type == PF_ADDR_TABLE)
        !          6006:                        pfr_update_stats(tr->dst.addr.p.tbl, (sk == NULL ||
        !          6007:                            sk->direction == dir) ? pd.dst : pd.src, pd.af,
        !          6008:                            pd.tot_len, dir == PF_OUT, r->action == PF_PASS,
        !          6009:                            tr->dst.neg);
        !          6010:        }
        !          6011:
        !          6012:
        !          6013:        if (action == PF_SYNPROXY_DROP) {
        !          6014:                m_freem(*m0);
        !          6015:                *m0 = NULL;
        !          6016:                action = PF_PASS;
        !          6017:        } else if (r->rt)
        !          6018:                /* pf_route6 can free the mbuf causing *m0 to become NULL */
        !          6019:                pf_route6(m0, r, dir, kif->pfik_ifp, s, &pd);
        !          6020:
        !          6021:        return (action);
        !          6022: }
        !          6023: #endif /* INET6 */
        !          6024:
        !          6025: int
        !          6026: pf_check_congestion(struct ifqueue *ifq)
        !          6027: {
        !          6028:        if (ifq->ifq_congestion)
        !          6029:                return (1);
        !          6030:        else
        !          6031:                return (0);
        !          6032: }

CVSweb