source: rtems-libbsd/freebsd/sys/contrib/pf/net/pf.c @ 2017a6d

55-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since 2017a6d was 2017a6d, checked in by Sebastian Huber <sebastian.huber@…>, on 04/07/16 at 07:48:12

Directly use <sys/time.h> provided by Newlib

  • Property mode set to 100644
File size: 185.7 KB
Line 
1#include <machine/rtems-bsd-kernel-space.h>
2
3/*      $OpenBSD: pf.c,v 1.634 2009/02/27 12:37:45 henning Exp $ */
4
5/*
6 * Copyright (c) 2001 Daniel Hartmeier
7 * Copyright (c) 2002 - 2008 Henning Brauer
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 *
14 *    - Redistributions of source code must retain the above copyright
15 *      notice, this list of conditions and the following disclaimer.
16 *    - Redistributions in binary form must reproduce the above
17 *      copyright notice, this list of conditions and the following
18 *      disclaimer in the documentation and/or other materials provided
19 *      with the distribution.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 *
34 * Effort sponsored in part by the Defense Advanced Research Projects
35 * Agency (DARPA) and Air Force Research Laboratory, Air Force
36 * Materiel Command, USAF, under agreement number F30602-01-2-0537.
37 *
38 */
39
40#ifdef __FreeBSD__
41#include <rtems/bsd/local/opt_inet.h>
42#include <rtems/bsd/local/opt_inet6.h>
43
44#include <sys/cdefs.h>
45__FBSDID("$FreeBSD$");
46#endif
47
48#ifdef __FreeBSD__
49#include <rtems/bsd/local/opt_bpf.h>
50#include <rtems/bsd/local/opt_pf.h>
51
52#define NPFSYNC         1
53
54#ifdef DEV_PFLOW
55#define NPFLOW          DEV_PFLOW
56#else
57#define NPFLOW          0
58#endif
59
60#else
61#include "bpfilter.h"
62#include "pflog.h"
63#include "pfsync.h"
64#include "pflow.h"
65#endif
66
67#include <rtems/bsd/sys/param.h>
68#include <sys/systm.h>
69#include <sys/mbuf.h>
70#include <sys/filio.h>
71#include <sys/socket.h>
72#include <sys/socketvar.h>
73#include <sys/kernel.h>
74#include <sys/time.h>
75#ifdef __FreeBSD__
76#include <sys/random.h>
77#include <sys/sysctl.h>
78#include <sys/endian.h>
79#define betoh64         be64toh
80#else
81#include <sys/pool.h>
82#endif
83#include <sys/proc.h>
84#ifdef __FreeBSD__
85#include <sys/kthread.h>
86#include <rtems/bsd/sys/lock.h>
87#include <sys/sx.h>
88#else
89#include <sys/rwlock.h>
90#endif
91
92#ifdef __FreeBSD__
93#include <sys/md5.h>
94#else
95#include <crypto/md5.h>
96#endif
97
98#include <net/if.h>
99#include <net/if_types.h>
100#include <net/bpf.h>
101#include <net/route.h>
102#ifdef __FreeBSD__
103#ifdef RADIX_MPATH
104#include <net/radix_mpath.h>
105#endif
106#else
107#include <net/radix_mpath.h>
108#endif
109
110#include <netinet/in.h>
111#include <netinet/in_var.h>
112#include <netinet/in_systm.h>
113#include <netinet/ip.h>
114#include <netinet/ip_var.h>
115#include <netinet/tcp.h>
116#include <netinet/tcp_seq.h>
117#include <netinet/udp.h>
118#include <netinet/ip_icmp.h>
119#include <netinet/in_pcb.h>
120#include <netinet/tcp_timer.h>
121#include <netinet/tcp_var.h>
122#include <netinet/udp_var.h>
123#include <netinet/icmp_var.h>
124#include <netinet/if_ether.h>
125#ifdef __FreeBSD__
126#include <netinet/ip_fw.h>
127#include <netpfil/ipfw/ip_fw_private.h> /* XXX: only for DIR_IN/DIR_OUT */
128#endif
129
130#ifndef __FreeBSD__
131#include <dev/rndvar.h>
132#endif
133#include <net/pfvar.h>
134#include <net/if_pflog.h>
135#include <net/if_pflow.h>
136#include <net/if_pfsync.h>
137
138#ifdef INET6
139#include <netinet/ip6.h>
140#include <netinet/in_pcb.h>
141#include <netinet/icmp6.h>
142#include <netinet6/nd6.h>
143#ifdef __FreeBSD__
144#include <netinet6/ip6_var.h>
145#include <netinet6/in6_pcb.h>
146#endif
147#endif /* INET6 */
148
149#ifdef __FreeBSD__
150#include <machine/in_cksum.h>
151#include <sys/limits.h>
152#include <sys/ucred.h>
153#include <security/mac/mac_framework.h>
154
155extern int ip_optcopy(struct ip *, struct ip *);
156#endif
157
158#ifdef __FreeBSD__
159#define DPFPRINTF(n, x) if (V_pf_status.debug >= (n)) printf x
160#else
161#define DPFPRINTF(n, x) if (pf_status.debug >= (n)) printf x
162#endif
163
164/*
165 * Global variables
166 */
167
168/* state tables */
169#ifdef __FreeBSD__
170VNET_DEFINE(struct pf_state_tree,        pf_statetbl);
171
172VNET_DEFINE(struct pf_altqqueue,         pf_altqs[2]);
173VNET_DEFINE(struct pf_palist,            pf_pabuf);
174VNET_DEFINE(struct pf_altqqueue *,       pf_altqs_active);
175VNET_DEFINE(struct pf_altqqueue *,       pf_altqs_inactive);
176VNET_DEFINE(struct pf_status,            pf_status);
177
178VNET_DEFINE(u_int32_t,                   ticket_altqs_active);
179VNET_DEFINE(u_int32_t,                   ticket_altqs_inactive);
180VNET_DEFINE(int,                         altqs_inactive_open);
181VNET_DEFINE(u_int32_t,                   ticket_pabuf);
182
183VNET_DEFINE(MD5_CTX,                     pf_tcp_secret_ctx);
184#define V_pf_tcp_secret_ctx              VNET(pf_tcp_secret_ctx)
185VNET_DEFINE(u_char,                      pf_tcp_secret[16]);
186#define V_pf_tcp_secret                  VNET(pf_tcp_secret)
187VNET_DEFINE(int,                         pf_tcp_secret_init);
188#define V_pf_tcp_secret_init             VNET(pf_tcp_secret_init)
189VNET_DEFINE(int,                         pf_tcp_iss_off);
190#define V_pf_tcp_iss_off                 VNET(pf_tcp_iss_off)
191
192struct pf_anchor_stackframe {
193        struct pf_ruleset               *rs;
194        struct pf_rule                  *r;
195        struct pf_anchor_node           *parent;
196        struct pf_anchor                *child;
197};
198VNET_DEFINE(struct pf_anchor_stackframe, pf_anchor_stack[64]);
199#define V_pf_anchor_stack                VNET(pf_anchor_stack)
200
201VNET_DEFINE(uma_zone_t,  pf_src_tree_pl);
202VNET_DEFINE(uma_zone_t,  pf_rule_pl);
203VNET_DEFINE(uma_zone_t,  pf_pooladdr_pl);
204VNET_DEFINE(uma_zone_t,  pf_state_pl);
205VNET_DEFINE(uma_zone_t,  pf_state_key_pl);
206VNET_DEFINE(uma_zone_t,  pf_state_item_pl);
207VNET_DEFINE(uma_zone_t,  pf_altq_pl);
208#else
209struct pf_state_tree     pf_statetbl;
210
211struct pf_altqqueue      pf_altqs[2];
212struct pf_palist         pf_pabuf;
213struct pf_altqqueue     *pf_altqs_active;
214struct pf_altqqueue     *pf_altqs_inactive;
215struct pf_status         pf_status;
216
217u_int32_t                ticket_altqs_active;
218u_int32_t                ticket_altqs_inactive;
219int                      altqs_inactive_open;
220u_int32_t                ticket_pabuf;
221
222MD5_CTX                  pf_tcp_secret_ctx;
223u_char                   pf_tcp_secret[16];
224int                      pf_tcp_secret_init;
225int                      pf_tcp_iss_off;
226
227struct pf_anchor_stackframe {
228        struct pf_ruleset                       *rs;
229        struct pf_rule                          *r;
230        struct pf_anchor_node                   *parent;
231        struct pf_anchor                        *child;
232} pf_anchor_stack[64];
233
234struct pool              pf_src_tree_pl, pf_rule_pl, pf_pooladdr_pl;
235struct pool              pf_state_pl, pf_state_key_pl, pf_state_item_pl;
236struct pool              pf_altq_pl;
237#endif
238
239void                     pf_init_threshold(struct pf_threshold *, u_int32_t,
240                            u_int32_t);
241void                     pf_add_threshold(struct pf_threshold *);
242int                      pf_check_threshold(struct pf_threshold *);
243
244void                     pf_change_ap(struct pf_addr *, u_int16_t *,
245                            u_int16_t *, u_int16_t *, struct pf_addr *,
246                            u_int16_t, u_int8_t, sa_family_t);
247int                      pf_modulate_sack(struct mbuf *, int, struct pf_pdesc *,
248                            struct tcphdr *, struct pf_state_peer *);
249#ifdef INET6
250void                     pf_change_a6(struct pf_addr *, u_int16_t *,
251                            struct pf_addr *, u_int8_t);
252#endif /* INET6 */
253void                     pf_change_icmp(struct pf_addr *, u_int16_t *,
254                            struct pf_addr *, struct pf_addr *, u_int16_t,
255                            u_int16_t *, u_int16_t *, u_int16_t *,
256                            u_int16_t *, u_int8_t, sa_family_t);
257#ifdef __FreeBSD__
258void                     pf_send_tcp(struct mbuf *,
259                            const struct pf_rule *, sa_family_t,
260#else
261void                     pf_send_tcp(const struct pf_rule *, sa_family_t,
262#endif
263                            const struct pf_addr *, const struct pf_addr *,
264                            u_int16_t, u_int16_t, u_int32_t, u_int32_t,
265                            u_int8_t, u_int16_t, u_int16_t, u_int8_t, int,
266                            u_int16_t, struct ether_header *, struct ifnet *);
267static void              pf_send_icmp(struct mbuf *, u_int8_t, u_int8_t,
268                            sa_family_t, struct pf_rule *);
269void                     pf_detach_state(struct pf_state *);
270void                     pf_state_key_detach(struct pf_state *, int);
271u_int32_t                pf_tcp_iss(struct pf_pdesc *);
272int                      pf_test_rule(struct pf_rule **, struct pf_state **,
273                            int, struct pfi_kif *, struct mbuf *, int,
274                            void *, struct pf_pdesc *, struct pf_rule **,
275#ifdef __FreeBSD__
276                            struct pf_ruleset **, struct ifqueue *,
277                            struct inpcb *);
278#else
279                            struct pf_ruleset **, struct ifqueue *);
280#endif
281static __inline int      pf_create_state(struct pf_rule *, struct pf_rule *,
282                            struct pf_rule *, struct pf_pdesc *,
283                            struct pf_src_node *, struct pf_state_key *,
284                            struct pf_state_key *, struct pf_state_key *,
285                            struct pf_state_key *, struct mbuf *, int,
286                            u_int16_t, u_int16_t, int *, struct pfi_kif *,
287                            struct pf_state **, int, u_int16_t, u_int16_t,
288                            int);
289int                      pf_test_fragment(struct pf_rule **, int,
290                            struct pfi_kif *, struct mbuf *, void *,
291                            struct pf_pdesc *, struct pf_rule **,
292                            struct pf_ruleset **);
293int                      pf_tcp_track_full(struct pf_state_peer *,
294                            struct pf_state_peer *, struct pf_state **,
295                            struct pfi_kif *, struct mbuf *, int,
296                            struct pf_pdesc *, u_short *, int *);
297int                     pf_tcp_track_sloppy(struct pf_state_peer *,
298                            struct pf_state_peer *, struct pf_state **,
299                            struct pf_pdesc *, u_short *);
300int                      pf_test_state_tcp(struct pf_state **, int,
301                            struct pfi_kif *, struct mbuf *, int,
302                            void *, struct pf_pdesc *, u_short *);
303int                      pf_test_state_udp(struct pf_state **, int,
304                            struct pfi_kif *, struct mbuf *, int,
305                            void *, struct pf_pdesc *);
306int                      pf_test_state_icmp(struct pf_state **, int,
307                            struct pfi_kif *, struct mbuf *, int,
308                            void *, struct pf_pdesc *, u_short *);
309int                      pf_test_state_other(struct pf_state **, int,
310                            struct pfi_kif *, struct mbuf *, struct pf_pdesc *);
311void                     pf_route(struct mbuf **, struct pf_rule *, int,
312                            struct ifnet *, struct pf_state *,
313                            struct pf_pdesc *);
314void                     pf_route6(struct mbuf **, struct pf_rule *, int,
315                            struct ifnet *, struct pf_state *,
316                            struct pf_pdesc *);
317#ifndef __FreeBSD__
318int                      pf_socket_lookup(int, struct pf_pdesc *);
319#endif
320u_int8_t                 pf_get_wscale(struct mbuf *, int, u_int16_t,
321                            sa_family_t);
322u_int16_t                pf_get_mss(struct mbuf *, int, u_int16_t,
323                            sa_family_t);
324u_int16_t                pf_calc_mss(struct pf_addr *, sa_family_t,
325                                int, u_int16_t);
326void                     pf_set_rt_ifp(struct pf_state *,
327                            struct pf_addr *);
328int                      pf_check_proto_cksum(struct mbuf *, int, int,
329                            u_int8_t, sa_family_t);
330#ifndef __FreeBSD__
331struct pf_divert        *pf_get_divert(struct mbuf *);
332#endif
333void                     pf_print_state_parts(struct pf_state *,
334                            struct pf_state_key *, struct pf_state_key *);
335int                      pf_addr_wrap_neq(struct pf_addr_wrap *,
336                            struct pf_addr_wrap *);
337int                      pf_compare_state_keys(struct pf_state_key *,
338                            struct pf_state_key *, struct pfi_kif *, u_int);
339#ifdef __FreeBSD__
340struct pf_state         *pf_find_state(struct pfi_kif *,
341                            struct pf_state_key_cmp *, u_int, struct mbuf *,
342                            struct pf_mtag *);
343#else
344struct pf_state         *pf_find_state(struct pfi_kif *,
345                            struct pf_state_key_cmp *, u_int, struct mbuf *);
346#endif
347int                      pf_src_connlimit(struct pf_state **);
348int                      pf_check_congestion(struct ifqueue *);
349
350#ifdef __FreeBSD__
351int in4_cksum(struct mbuf *m, u_int8_t nxt, int off, int len);
352
353VNET_DECLARE(int, pf_end_threads);
354
355VNET_DEFINE(struct pf_pool_limit, pf_pool_limits[PF_LIMIT_MAX]);
356#else
357extern struct pool pfr_ktable_pl;
358extern struct pool pfr_kentry_pl;
359
360struct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX] = {
361        { &pf_state_pl, PFSTATE_HIWAT },
362        { &pf_src_tree_pl, PFSNODE_HIWAT },
363        { &pf_frent_pl, PFFRAG_FRENT_HIWAT },
364        { &pfr_ktable_pl, PFR_KTABLE_HIWAT },
365        { &pfr_kentry_pl, PFR_KENTRY_HIWAT }
366};
367#endif
368
369#ifdef __FreeBSD__
370#define PPACKET_LOOPED()                                                \
371        (pd->pf_mtag->flags & PF_PACKET_LOOPED)
372
373#define PACKET_LOOPED()                                                 \
374        (pd.pf_mtag->flags & PF_PACKET_LOOPED)
375
376#define STATE_LOOKUP(i, k, d, s, m, pt)                                 \
377        do {                                                            \
378                s = pf_find_state(i, k, d, m, pt);                      \
379                if (s == NULL || (s)->timeout == PFTM_PURGE)            \
380                        return (PF_DROP);                               \
381                if (PPACKET_LOOPED())                                   \
382                        return (PF_PASS);                               \
383                if (d == PF_OUT &&                                      \
384                    (((s)->rule.ptr->rt == PF_ROUTETO &&                \
385                    (s)->rule.ptr->direction == PF_OUT) ||              \
386                    ((s)->rule.ptr->rt == PF_REPLYTO &&                 \
387                    (s)->rule.ptr->direction == PF_IN)) &&              \
388                    (s)->rt_kif != NULL &&                              \
389                    (s)->rt_kif != i)                                   \
390                        return (PF_PASS);                               \
391        } while (0)
392#else
393#define STATE_LOOKUP(i, k, d, s, m)                                     \
394        do {                                                            \
395                s = pf_find_state(i, k, d, m);                          \
396                if (s == NULL || (s)->timeout == PFTM_PURGE)            \
397                        return (PF_DROP);                               \
398                if (d == PF_OUT &&                                      \
399                    (((s)->rule.ptr->rt == PF_ROUTETO &&                \
400                    (s)->rule.ptr->direction == PF_OUT) ||              \
401                    ((s)->rule.ptr->rt == PF_REPLYTO &&                 \
402                    (s)->rule.ptr->direction == PF_IN)) &&              \
403                    (s)->rt_kif != NULL &&                              \
404                    (s)->rt_kif != i)                                   \
405                        return (PF_PASS);                               \
406        } while (0)
407#endif
408
409#ifdef __FreeBSD__
410#define BOUND_IFACE(r, k) \
411        ((r)->rule_flag & PFRULE_IFBOUND) ? (k) : V_pfi_all
412#else
413#define BOUND_IFACE(r, k) \
414        ((r)->rule_flag & PFRULE_IFBOUND) ? (k) : pfi_all
415#endif
416
417#define STATE_INC_COUNTERS(s)                           \
418        do {                                            \
419                s->rule.ptr->states_cur++;              \
420                s->rule.ptr->states_tot++;              \
421                if (s->anchor.ptr != NULL) {            \
422                        s->anchor.ptr->states_cur++;    \
423                        s->anchor.ptr->states_tot++;    \
424                }                                       \
425                if (s->nat_rule.ptr != NULL) {          \
426                        s->nat_rule.ptr->states_cur++;  \
427                        s->nat_rule.ptr->states_tot++;  \
428                }                                       \
429        } while (0)
430
431#define STATE_DEC_COUNTERS(s)                           \
432        do {                                            \
433                if (s->nat_rule.ptr != NULL)            \
434                        s->nat_rule.ptr->states_cur--;  \
435                if (s->anchor.ptr != NULL)              \
436                        s->anchor.ptr->states_cur--;    \
437                s->rule.ptr->states_cur--;              \
438        } while (0)
439
440static __inline int pf_src_compare(struct pf_src_node *, struct pf_src_node *);
441static __inline int pf_state_compare_key(struct pf_state_key *,
442        struct pf_state_key *);
443static __inline int pf_state_compare_id(struct pf_state *,
444        struct pf_state *);
445
446#ifdef __FreeBSD__
447VNET_DEFINE(struct pf_src_tree,          tree_src_tracking);
448
449VNET_DEFINE(struct pf_state_tree_id,     tree_id);
450VNET_DEFINE(struct pf_state_queue,       state_list);
451#else
452struct pf_src_tree tree_src_tracking;
453
454struct pf_state_tree_id tree_id;
455struct pf_state_queue state_list;
456#endif
457
458RB_GENERATE(pf_src_tree, pf_src_node, entry, pf_src_compare);
459RB_GENERATE(pf_state_tree, pf_state_key, entry, pf_state_compare_key);
460RB_GENERATE(pf_state_tree_id, pf_state,
461    entry_id, pf_state_compare_id);
462
463static __inline int
464pf_src_compare(struct pf_src_node *a, struct pf_src_node *b)
465{
466        int     diff;
467
468        if (a->rule.ptr > b->rule.ptr)
469                return (1);
470        if (a->rule.ptr < b->rule.ptr)
471                return (-1);
472        if ((diff = a->af - b->af) != 0)
473                return (diff);
474        switch (a->af) {
475#ifdef INET
476        case AF_INET:
477                if (a->addr.addr32[0] > b->addr.addr32[0])
478                        return (1);
479                if (a->addr.addr32[0] < b->addr.addr32[0])
480                        return (-1);
481                break;
482#endif /* INET */
483#ifdef INET6
484        case AF_INET6:
485                if (a->addr.addr32[3] > b->addr.addr32[3])
486                        return (1);
487                if (a->addr.addr32[3] < b->addr.addr32[3])
488                        return (-1);
489                if (a->addr.addr32[2] > b->addr.addr32[2])
490                        return (1);
491                if (a->addr.addr32[2] < b->addr.addr32[2])
492                        return (-1);
493                if (a->addr.addr32[1] > b->addr.addr32[1])
494                        return (1);
495                if (a->addr.addr32[1] < b->addr.addr32[1])
496                        return (-1);
497                if (a->addr.addr32[0] > b->addr.addr32[0])
498                        return (1);
499                if (a->addr.addr32[0] < b->addr.addr32[0])
500                        return (-1);
501                break;
502#endif /* INET6 */
503        }
504        return (0);
505}
506
507#ifdef INET6
508void
509pf_addrcpy(struct pf_addr *dst, struct pf_addr *src, sa_family_t af)
510{
511        switch (af) {
512#ifdef INET
513        case AF_INET:
514                dst->addr32[0] = src->addr32[0];
515                break;
516#endif /* INET */
517        case AF_INET6:
518                dst->addr32[0] = src->addr32[0];
519                dst->addr32[1] = src->addr32[1];
520                dst->addr32[2] = src->addr32[2];
521                dst->addr32[3] = src->addr32[3];
522                break;
523        }
524}
525#endif /* INET6 */
526
527void
528pf_init_threshold(struct pf_threshold *threshold,
529    u_int32_t limit, u_int32_t seconds)
530{
531        threshold->limit = limit * PF_THRESHOLD_MULT;
532        threshold->seconds = seconds;
533        threshold->count = 0;
534        threshold->last = time_second;
535}
536
537void
538pf_add_threshold(struct pf_threshold *threshold)
539{
540        u_int32_t t = time_second, diff = t - threshold->last;
541
542        if (diff >= threshold->seconds)
543                threshold->count = 0;
544        else
545                threshold->count -= threshold->count * diff /
546                    threshold->seconds;
547        threshold->count += PF_THRESHOLD_MULT;
548        threshold->last = t;
549}
550
551int
552pf_check_threshold(struct pf_threshold *threshold)
553{
554        return (threshold->count > threshold->limit);
555}
556
557int
558pf_src_connlimit(struct pf_state **state)
559{
560        int bad = 0;
561
562        (*state)->src_node->conn++;
563        (*state)->src.tcp_est = 1;
564        pf_add_threshold(&(*state)->src_node->conn_rate);
565
566        if ((*state)->rule.ptr->max_src_conn &&
567            (*state)->rule.ptr->max_src_conn <
568            (*state)->src_node->conn) {
569#ifdef __FreeBSD__
570                V_pf_status.lcounters[LCNT_SRCCONN]++;
571#else
572                pf_status.lcounters[LCNT_SRCCONN]++;
573#endif
574                bad++;
575        }
576
577        if ((*state)->rule.ptr->max_src_conn_rate.limit &&
578            pf_check_threshold(&(*state)->src_node->conn_rate)) {
579#ifdef __FreeBSD__
580                V_pf_status.lcounters[LCNT_SRCCONNRATE]++;
581#else
582                pf_status.lcounters[LCNT_SRCCONNRATE]++;
583#endif
584                bad++;
585        }
586
587        if (!bad)
588                return (0);
589
590        if ((*state)->rule.ptr->overload_tbl) {
591                struct pfr_addr p;
592                u_int32_t       killed = 0;
593
594#ifdef __FreeBSD__
595                V_pf_status.lcounters[LCNT_OVERLOAD_TABLE]++;
596                if (V_pf_status.debug >= PF_DEBUG_MISC) {
597#else
598                pf_status.lcounters[LCNT_OVERLOAD_TABLE]++;
599                if (pf_status.debug >= PF_DEBUG_MISC) {
600#endif
601                        printf("pf_src_connlimit: blocking address ");
602                        pf_print_host(&(*state)->src_node->addr, 0,
603                            (*state)->key[PF_SK_WIRE]->af);
604                }
605
606                bzero(&p, sizeof(p));
607                p.pfra_af = (*state)->key[PF_SK_WIRE]->af;
608                switch ((*state)->key[PF_SK_WIRE]->af) {
609#ifdef INET
610                case AF_INET:
611                        p.pfra_net = 32;
612                        p.pfra_ip4addr = (*state)->src_node->addr.v4;
613                        break;
614#endif /* INET */
615#ifdef INET6
616                case AF_INET6:
617                        p.pfra_net = 128;
618                        p.pfra_ip6addr = (*state)->src_node->addr.v6;
619                        break;
620#endif /* INET6 */
621                }
622
623                pfr_insert_kentry((*state)->rule.ptr->overload_tbl,
624                    &p, time_second);
625
626                /* kill existing states if that's required. */
627                if ((*state)->rule.ptr->flush) {
628                        struct pf_state_key *sk;
629                        struct pf_state *st;
630
631#ifdef __FreeBSD__
632                        V_pf_status.lcounters[LCNT_OVERLOAD_FLUSH]++;
633                        RB_FOREACH(st, pf_state_tree_id, &V_tree_id) {
634#else
635                        pf_status.lcounters[LCNT_OVERLOAD_FLUSH]++;
636                        RB_FOREACH(st, pf_state_tree_id, &tree_id) {
637#endif
638                                sk = st->key[PF_SK_WIRE];
639                                /*
640                                 * Kill states from this source.  (Only those
641                                 * from the same rule if PF_FLUSH_GLOBAL is not
642                                 * set)
643                                 */
644                                if (sk->af ==
645                                    (*state)->key[PF_SK_WIRE]->af &&
646                                    (((*state)->direction == PF_OUT &&
647                                    PF_AEQ(&(*state)->src_node->addr,
648                                        &sk->addr[1], sk->af)) ||
649                                    ((*state)->direction == PF_IN &&
650                                    PF_AEQ(&(*state)->src_node->addr,
651                                        &sk->addr[0], sk->af))) &&
652                                    ((*state)->rule.ptr->flush &
653                                    PF_FLUSH_GLOBAL ||
654                                    (*state)->rule.ptr == st->rule.ptr)) {
655                                        st->timeout = PFTM_PURGE;
656                                        st->src.state = st->dst.state =
657                                            TCPS_CLOSED;
658                                        killed++;
659                                }
660                        }
661#ifdef __FreeBSD__
662                        if (V_pf_status.debug >= PF_DEBUG_MISC)
663#else
664                        if (pf_status.debug >= PF_DEBUG_MISC)
665#endif
666                                printf(", %u states killed", killed);
667                }
668#ifdef __FreeBSD__
669                if (V_pf_status.debug >= PF_DEBUG_MISC)
670#else
671                if (pf_status.debug >= PF_DEBUG_MISC)
672#endif
673                        printf("\n");
674        }
675
676        /* kill this state */
677        (*state)->timeout = PFTM_PURGE;
678        (*state)->src.state = (*state)->dst.state = TCPS_CLOSED;
679        return (1);
680}
681
682int
683pf_insert_src_node(struct pf_src_node **sn, struct pf_rule *rule,
684    struct pf_addr *src, sa_family_t af)
685{
686        struct pf_src_node      k;
687
688        if (*sn == NULL) {
689                k.af = af;
690                PF_ACPY(&k.addr, src, af);
691                if (rule->rule_flag & PFRULE_RULESRCTRACK ||
692                    rule->rpool.opts & PF_POOL_STICKYADDR)
693                        k.rule.ptr = rule;
694                else
695                        k.rule.ptr = NULL;
696#ifdef __FreeBSD__
697                V_pf_status.scounters[SCNT_SRC_NODE_SEARCH]++;
698                *sn = RB_FIND(pf_src_tree, &V_tree_src_tracking, &k);
699#else
700                pf_status.scounters[SCNT_SRC_NODE_SEARCH]++;
701                *sn = RB_FIND(pf_src_tree, &tree_src_tracking, &k);
702#endif
703        }
704        if (*sn == NULL) {
705                if (!rule->max_src_nodes ||
706                    rule->src_nodes < rule->max_src_nodes)
707#ifdef __FreeBSD__
708                        (*sn) = pool_get(&V_pf_src_tree_pl, PR_NOWAIT | PR_ZERO);
709#else
710                        (*sn) = pool_get(&pf_src_tree_pl, PR_NOWAIT | PR_ZERO);
711#endif
712                else
713#ifdef __FreeBSD__
714                        V_pf_status.lcounters[LCNT_SRCNODES]++;
715#else
716                        pf_status.lcounters[LCNT_SRCNODES]++;
717#endif
718                if ((*sn) == NULL)
719                        return (-1);
720
721                pf_init_threshold(&(*sn)->conn_rate,
722                    rule->max_src_conn_rate.limit,
723                    rule->max_src_conn_rate.seconds);
724
725                (*sn)->af = af;
726                if (rule->rule_flag & PFRULE_RULESRCTRACK ||
727                    rule->rpool.opts & PF_POOL_STICKYADDR)
728                        (*sn)->rule.ptr = rule;
729                else
730                        (*sn)->rule.ptr = NULL;
731                PF_ACPY(&(*sn)->addr, src, af);
732                if (RB_INSERT(pf_src_tree,
733#ifdef __FreeBSD__
734                    &V_tree_src_tracking, *sn) != NULL) {
735                        if (V_pf_status.debug >= PF_DEBUG_MISC) {
736#else
737                    &tree_src_tracking, *sn) != NULL) {
738                        if (pf_status.debug >= PF_DEBUG_MISC) {
739#endif
740                                printf("pf: src_tree insert failed: ");
741                                pf_print_host(&(*sn)->addr, 0, af);
742                                printf("\n");
743                        }
744#ifdef __FreeBSD__
745                        pool_put(&V_pf_src_tree_pl, *sn);
746#else
747                        pool_put(&pf_src_tree_pl, *sn);
748#endif
749                        return (-1);
750                }
751                (*sn)->creation = time_second;
752                (*sn)->ruletype = rule->action;
753                if ((*sn)->rule.ptr != NULL)
754                        (*sn)->rule.ptr->src_nodes++;
755#ifdef __FreeBSD__
756                V_pf_status.scounters[SCNT_SRC_NODE_INSERT]++;
757                V_pf_status.src_nodes++;
758#else
759                pf_status.scounters[SCNT_SRC_NODE_INSERT]++;
760                pf_status.src_nodes++;
761#endif
762        } else {
763                if (rule->max_src_states &&
764                    (*sn)->states >= rule->max_src_states) {
765#ifdef __FreeBSD__
766                        V_pf_status.lcounters[LCNT_SRCSTATES]++;
767#else
768                        pf_status.lcounters[LCNT_SRCSTATES]++;
769#endif
770                        return (-1);
771                }
772        }
773        return (0);
774}
775
776/* state table stuff */
777
778static __inline int
779pf_state_compare_key(struct pf_state_key *a, struct pf_state_key *b)
780{
781        int     diff;
782
783        if ((diff = a->proto - b->proto) != 0)
784                return (diff);
785        if ((diff = a->af - b->af) != 0)
786                return (diff);
787        switch (a->af) {
788#ifdef INET
789        case AF_INET:
790                if (a->addr[0].addr32[0] > b->addr[0].addr32[0])
791                        return (1);
792                if (a->addr[0].addr32[0] < b->addr[0].addr32[0])
793                        return (-1);
794                if (a->addr[1].addr32[0] > b->addr[1].addr32[0])
795                        return (1);
796                if (a->addr[1].addr32[0] < b->addr[1].addr32[0])
797                        return (-1);
798                break;
799#endif /* INET */
800#ifdef INET6
801        case AF_INET6:
802                if (a->addr[0].addr32[3] > b->addr[0].addr32[3])
803                        return (1);
804                if (a->addr[0].addr32[3] < b->addr[0].addr32[3])
805                        return (-1);
806                if (a->addr[1].addr32[3] > b->addr[1].addr32[3])
807                        return (1);
808                if (a->addr[1].addr32[3] < b->addr[1].addr32[3])
809                        return (-1);
810                if (a->addr[0].addr32[2] > b->addr[0].addr32[2])
811                        return (1);
812                if (a->addr[0].addr32[2] < b->addr[0].addr32[2])
813                        return (-1);
814                if (a->addr[1].addr32[2] > b->addr[1].addr32[2])
815                        return (1);
816                if (a->addr[1].addr32[2] < b->addr[1].addr32[2])
817                        return (-1);
818                if (a->addr[0].addr32[1] > b->addr[0].addr32[1])
819                        return (1);
820                if (a->addr[0].addr32[1] < b->addr[0].addr32[1])
821                        return (-1);
822                if (a->addr[1].addr32[1] > b->addr[1].addr32[1])
823                        return (1);
824                if (a->addr[1].addr32[1] < b->addr[1].addr32[1])
825                        return (-1);
826                if (a->addr[0].addr32[0] > b->addr[0].addr32[0])
827                        return (1);
828                if (a->addr[0].addr32[0] < b->addr[0].addr32[0])
829                        return (-1);
830                if (a->addr[1].addr32[0] > b->addr[1].addr32[0])
831                        return (1);
832                if (a->addr[1].addr32[0] < b->addr[1].addr32[0])
833                        return (-1);
834                break;
835#endif /* INET6 */
836        }
837
838        if ((diff = a->port[0] - b->port[0]) != 0)
839                return (diff);
840        if ((diff = a->port[1] - b->port[1]) != 0)
841                return (diff);
842
843        return (0);
844}
845
846static __inline int
847pf_state_compare_id(struct pf_state *a, struct pf_state *b)
848{
849        if (a->id > b->id)
850                return (1);
851        if (a->id < b->id)
852                return (-1);
853        if (a->creatorid > b->creatorid)
854                return (1);
855        if (a->creatorid < b->creatorid)
856                return (-1);
857
858        return (0);
859}
860
861int
862pf_state_key_attach(struct pf_state_key *sk, struct pf_state *s, int idx)
863{
864        struct pf_state_item    *si;
865        struct pf_state_key     *cur;
866        struct pf_state         *olds = NULL;
867
868#ifdef __FreeBSD__
869        KASSERT(s->key[idx] == NULL, ("%s: key is null!", __FUNCTION__));
870#else
871        KASSERT(s->key[idx] == NULL);   /* XXX handle this? */
872#endif
873
874#ifdef __FreeBSD__
875        if ((cur = RB_INSERT(pf_state_tree, &V_pf_statetbl, sk)) != NULL) {
876#else
877        if ((cur = RB_INSERT(pf_state_tree, &pf_statetbl, sk)) != NULL) {
878#endif
879                /* key exists. check for same kif, if none, add to key */
880                TAILQ_FOREACH(si, &cur->states, entry)
881                        if (si->s->kif == s->kif &&
882                            si->s->direction == s->direction) {
883                                if (sk->proto == IPPROTO_TCP &&
884                                    si->s->src.state >= TCPS_FIN_WAIT_2 &&
885                                    si->s->dst.state >= TCPS_FIN_WAIT_2) {
886                                        si->s->src.state = si->s->dst.state =
887                                            TCPS_CLOSED;
888                                        /* unlink late or sks can go away */
889                                        olds = si->s;
890                                } else {
891#ifdef __FreeBSD__
892                                        if (V_pf_status.debug >= PF_DEBUG_MISC) {
893#else
894                                        if (pf_status.debug >= PF_DEBUG_MISC) {
895#endif
896                                                printf("pf: %s key attach "
897                                                    "failed on %s: ",
898                                                    (idx == PF_SK_WIRE) ?
899                                                    "wire" : "stack",
900                                                    s->kif->pfik_name);
901                                                pf_print_state_parts(s,
902                                                    (idx == PF_SK_WIRE) ?
903                                                    sk : NULL,
904                                                    (idx == PF_SK_STACK) ?
905                                                    sk : NULL);
906                                                printf(", existing: ");
907                                                pf_print_state_parts(si->s,
908                                                    (idx == PF_SK_WIRE) ?
909                                                    sk : NULL,
910                                                    (idx == PF_SK_STACK) ?
911                                                    sk : NULL);
912                                                printf("\n");
913                                        }
914#ifdef __FreeBSD__
915                                        pool_put(&V_pf_state_key_pl, sk);
916#else
917                                        pool_put(&pf_state_key_pl, sk);
918#endif
919                                        return (-1);    /* collision! */
920                                }
921                        }
922#ifdef __FreeBSD__
923                pool_put(&V_pf_state_key_pl, sk);
924#else
925                pool_put(&pf_state_key_pl, sk);
926#endif
927                s->key[idx] = cur;
928        } else
929                s->key[idx] = sk;
930
931#ifdef __FreeBSD__
932        if ((si = pool_get(&V_pf_state_item_pl, PR_NOWAIT)) == NULL) {
933#else
934        if ((si = pool_get(&pf_state_item_pl, PR_NOWAIT)) == NULL) {
935#endif
936                pf_state_key_detach(s, idx);
937                return (-1);
938        }
939        si->s = s;
940
941        /* list is sorted, if-bound states before floating */
942#ifdef __FreeBSD__
943        if (s->kif == V_pfi_all)
944#else
945        if (s->kif == pfi_all)
946#endif
947                TAILQ_INSERT_TAIL(&s->key[idx]->states, si, entry);
948        else
949                TAILQ_INSERT_HEAD(&s->key[idx]->states, si, entry);
950
951        if (olds)
952                pf_unlink_state(olds);
953
954        return (0);
955}
956
957void
958pf_detach_state(struct pf_state *s)
959{
960        if (s->key[PF_SK_WIRE] == s->key[PF_SK_STACK])
961                s->key[PF_SK_WIRE] = NULL;
962
963        if (s->key[PF_SK_STACK] != NULL)
964                pf_state_key_detach(s, PF_SK_STACK);
965
966        if (s->key[PF_SK_WIRE] != NULL)
967                pf_state_key_detach(s, PF_SK_WIRE);
968}
969
970void
971pf_state_key_detach(struct pf_state *s, int idx)
972{
973        struct pf_state_item    *si;
974
975        si = TAILQ_FIRST(&s->key[idx]->states);
976        while (si && si->s != s)
977            si = TAILQ_NEXT(si, entry);
978
979        if (si) {
980                TAILQ_REMOVE(&s->key[idx]->states, si, entry);
981#ifdef __FreeBSD__
982                pool_put(&V_pf_state_item_pl, si);
983#else
984                pool_put(&pf_state_item_pl, si);
985#endif
986        }
987
988        if (TAILQ_EMPTY(&s->key[idx]->states)) {
989#ifdef __FreeBSD__
990                RB_REMOVE(pf_state_tree, &V_pf_statetbl, s->key[idx]);
991#else
992                RB_REMOVE(pf_state_tree, &pf_statetbl, s->key[idx]);
993#endif
994                if (s->key[idx]->reverse)
995                        s->key[idx]->reverse->reverse = NULL;
996#ifdef __FreeBSD__
997        /* XXX: implement this */
998#else
999                if (s->key[idx]->inp)
1000                        s->key[idx]->inp->inp_pf_sk = NULL;
1001#endif
1002#ifdef __FreeBSD__
1003                pool_put(&V_pf_state_key_pl, s->key[idx]);
1004#else
1005                pool_put(&pf_state_key_pl, s->key[idx]);
1006#endif
1007        }
1008        s->key[idx] = NULL;
1009}
1010
1011struct pf_state_key *
1012pf_alloc_state_key(int pool_flags)
1013{
1014        struct pf_state_key     *sk;
1015
1016#ifdef __FreeBSD__
1017        if ((sk = pool_get(&V_pf_state_key_pl, pool_flags)) == NULL)
1018#else
1019        if ((sk = pool_get(&pf_state_key_pl, pool_flags)) == NULL)
1020#endif
1021                return (NULL);
1022        TAILQ_INIT(&sk->states);
1023
1024        return (sk);
1025}
1026
1027int
1028pf_state_key_setup(struct pf_pdesc *pd, struct pf_rule *nr,
1029        struct pf_state_key **skw, struct pf_state_key **sks,
1030        struct pf_state_key **skp, struct pf_state_key **nkp,
1031        struct pf_addr *saddr, struct pf_addr *daddr,
1032        u_int16_t sport, u_int16_t dport)
1033{
1034#ifdef __FreeBSD__
1035        KASSERT((*skp == NULL && *nkp == NULL),
1036                ("%s: skp == NULL && nkp == NULL", __FUNCTION__));
1037#else
1038        KASSERT((*skp == NULL && *nkp == NULL));
1039#endif
1040
1041        if ((*skp = pf_alloc_state_key(PR_NOWAIT | PR_ZERO)) == NULL)
1042                return (ENOMEM);
1043
1044        PF_ACPY(&(*skp)->addr[pd->sidx], saddr, pd->af);
1045        PF_ACPY(&(*skp)->addr[pd->didx], daddr, pd->af);
1046        (*skp)->port[pd->sidx] = sport;
1047        (*skp)->port[pd->didx] = dport;
1048        (*skp)->proto = pd->proto;
1049        (*skp)->af = pd->af;
1050
1051        if (nr != NULL) {
1052                if ((*nkp = pf_alloc_state_key(PR_NOWAIT | PR_ZERO)) == NULL)
1053                        return (ENOMEM); /* caller must handle cleanup */
1054
1055                /* XXX maybe just bcopy and TAILQ_INIT(&(*nkp)->states) */
1056                PF_ACPY(&(*nkp)->addr[0], &(*skp)->addr[0], pd->af);
1057                PF_ACPY(&(*nkp)->addr[1], &(*skp)->addr[1], pd->af);
1058                (*nkp)->port[0] = (*skp)->port[0];
1059                (*nkp)->port[1] = (*skp)->port[1];
1060                (*nkp)->proto = pd->proto;
1061                (*nkp)->af = pd->af;
1062        } else
1063                *nkp = *skp;
1064
1065        if (pd->dir == PF_IN) {
1066                *skw = *skp;
1067                *sks = *nkp;
1068        } else {
1069                *sks = *skp;
1070                *skw = *nkp;
1071        }
1072        return (0);
1073}
1074
1075
1076int
1077pf_state_insert(struct pfi_kif *kif, struct pf_state_key *skw,
1078    struct pf_state_key *sks, struct pf_state *s)
1079{
1080#ifndef __FreeBSD__
1081        splassert(IPL_SOFTNET);
1082#endif
1083
1084        s->kif = kif;
1085
1086        if (skw == sks) {
1087                if (pf_state_key_attach(skw, s, PF_SK_WIRE))
1088                        return (-1);
1089                s->key[PF_SK_STACK] = s->key[PF_SK_WIRE];
1090        } else {
1091                if (pf_state_key_attach(skw, s, PF_SK_WIRE)) {
1092#ifdef __FreeBSD__
1093                        pool_put(&V_pf_state_key_pl, sks);
1094#else
1095                        pool_put(&pf_state_key_pl, sks);
1096#endif
1097                        return (-1);
1098                }
1099                if (pf_state_key_attach(sks, s, PF_SK_STACK)) {
1100                        pf_state_key_detach(s, PF_SK_WIRE);
1101                        return (-1);
1102                }
1103        }
1104
1105        if (s->id == 0 && s->creatorid == 0) {
1106#ifdef __FreeBSD__
1107                s->id = htobe64(V_pf_status.stateid++);
1108                s->creatorid = V_pf_status.hostid;
1109#else
1110                s->id = htobe64(pf_status.stateid++);
1111                s->creatorid = pf_status.hostid;
1112#endif
1113        }
1114#ifdef __FreeBSD__
1115        if (RB_INSERT(pf_state_tree_id, &V_tree_id, s) != NULL) {
1116                if (V_pf_status.debug >= PF_DEBUG_MISC) {
1117#else
1118        if (RB_INSERT(pf_state_tree_id, &tree_id, s) != NULL) {
1119                if (pf_status.debug >= PF_DEBUG_MISC) {
1120#endif
1121                        printf("pf: state insert failed: "
1122                            "id: %016llx creatorid: %08x",
1123#ifdef __FreeBSD__
1124                            (unsigned long long)betoh64(s->id), ntohl(s->creatorid));
1125#else
1126                            betoh64(s->id), ntohl(s->creatorid));
1127#endif
1128                        printf("\n");
1129                }
1130                pf_detach_state(s);
1131                return (-1);
1132        }
1133#ifdef __FreeBSD__
1134        TAILQ_INSERT_TAIL(&V_state_list, s, entry_list);
1135        V_pf_status.fcounters[FCNT_STATE_INSERT]++;
1136        V_pf_status.states++;
1137#else
1138        TAILQ_INSERT_TAIL(&state_list, s, entry_list);
1139        pf_status.fcounters[FCNT_STATE_INSERT]++;
1140        pf_status.states++;
1141#endif
1142        pfi_kif_ref(kif, PFI_KIF_REF_STATE);
1143#if NPFSYNC > 0
1144#ifdef __FreeBSD__
1145        if (pfsync_insert_state_ptr != NULL)
1146                pfsync_insert_state_ptr(s);
1147#else
1148        pfsync_insert_state(s);
1149#endif
1150#endif
1151        return (0);
1152}
1153
1154struct pf_state *
1155pf_find_state_byid(struct pf_state_cmp *key)
1156{
1157#ifdef __FreeBSD__
1158        V_pf_status.fcounters[FCNT_STATE_SEARCH]++;
1159
1160        return (RB_FIND(pf_state_tree_id, &V_tree_id, (struct pf_state *)key));
1161#else
1162        pf_status.fcounters[FCNT_STATE_SEARCH]++;
1163
1164        return (RB_FIND(pf_state_tree_id, &tree_id, (struct pf_state *)key));
1165#endif
1166}
1167
1168/* XXX debug function, intended to be removed one day */
1169int
1170pf_compare_state_keys(struct pf_state_key *a, struct pf_state_key *b,
1171    struct pfi_kif *kif, u_int dir)
1172{
1173        /* a (from hdr) and b (new) must be exact opposites of each other */
1174        if (a->af == b->af && a->proto == b->proto &&
1175            PF_AEQ(&a->addr[0], &b->addr[1], a->af) &&
1176            PF_AEQ(&a->addr[1], &b->addr[0], a->af) &&
1177            a->port[0] == b->port[1] &&
1178            a->port[1] == b->port[0])
1179                return (0);
1180        else {
1181                /* mismatch. must not happen. */
1182                printf("pf: state key linking mismatch! dir=%s, "
1183                    "if=%s, stored af=%u, a0: ",
1184                    dir == PF_OUT ? "OUT" : "IN", kif->pfik_name, a->af);
1185                pf_print_host(&a->addr[0], a->port[0], a->af);
1186                printf(", a1: ");
1187                pf_print_host(&a->addr[1], a->port[1], a->af);
1188                printf(", proto=%u", a->proto);
1189                printf(", found af=%u, a0: ", b->af);
1190                pf_print_host(&b->addr[0], b->port[0], b->af);
1191                printf(", a1: ");
1192                pf_print_host(&b->addr[1], b->port[1], b->af);
1193                printf(", proto=%u", b->proto);
1194                printf(".\n");
1195                return (-1);
1196        }
1197}
1198
1199struct pf_state *
1200#ifdef __FreeBSD__
1201pf_find_state(struct pfi_kif *kif, struct pf_state_key_cmp *key, u_int dir,
1202    struct mbuf *m, struct pf_mtag *pftag)
1203#else
1204pf_find_state(struct pfi_kif *kif, struct pf_state_key_cmp *key, u_int dir,
1205    struct mbuf *m)
1206#endif
1207{
1208        struct pf_state_key     *sk;
1209        struct pf_state_item    *si;
1210
1211#ifdef __FreeBSD__
1212        V_pf_status.fcounters[FCNT_STATE_SEARCH]++;
1213#else
1214        pf_status.fcounters[FCNT_STATE_SEARCH]++;
1215#endif
1216
1217#ifdef __FreeBSD__
1218        if (dir == PF_OUT && pftag->statekey &&
1219            ((struct pf_state_key *)pftag->statekey)->reverse)
1220                sk = ((struct pf_state_key *)pftag->statekey)->reverse;
1221        else {
1222#ifdef __FreeBSD__
1223                if ((sk = RB_FIND(pf_state_tree, &V_pf_statetbl,
1224#else
1225                if ((sk = RB_FIND(pf_state_tree, &pf_statetbl,
1226#endif
1227                    (struct pf_state_key *)key)) == NULL)
1228                        return (NULL);
1229                if (dir == PF_OUT && pftag->statekey &&
1230                    pf_compare_state_keys(pftag->statekey, sk,
1231                    kif, dir) == 0) {
1232                        ((struct pf_state_key *)
1233                            pftag->statekey)->reverse = sk;
1234                        sk->reverse = pftag->statekey;
1235                }
1236        }
1237#else
1238        if (dir == PF_OUT && m->m_pkthdr.pf.statekey &&
1239            ((struct pf_state_key *)m->m_pkthdr.pf.statekey)->reverse)
1240                sk = ((struct pf_state_key *)m->m_pkthdr.pf.statekey)->reverse;
1241        else {
1242#ifdef __FreeBSD__
1243                if ((sk = RB_FIND(pf_state_tree, &V_pf_statetbl,
1244#else
1245                if ((sk = RB_FIND(pf_state_tree, &pf_statetbl,
1246#endif
1247                    (struct pf_state_key *)key)) == NULL)
1248                        return (NULL);
1249                if (dir == PF_OUT && m->m_pkthdr.pf.statekey &&
1250                    pf_compare_state_keys(m->m_pkthdr.pf.statekey, sk,
1251                    kif, dir) == 0) {
1252                        ((struct pf_state_key *)
1253                            m->m_pkthdr.pf.statekey)->reverse = sk;
1254                        sk->reverse = m->m_pkthdr.pf.statekey;
1255                }
1256        }
1257#endif
1258
1259        if (dir == PF_OUT)
1260#ifdef __FreeBSD__
1261                pftag->statekey = NULL;
1262#else
1263                m->m_pkthdr.pf.statekey = NULL;
1264#endif
1265
1266        /* list is sorted, if-bound states before floating ones */
1267        TAILQ_FOREACH(si, &sk->states, entry)
1268#ifdef __FreeBSD__
1269                if ((si->s->kif == V_pfi_all || si->s->kif == kif) &&
1270#else
1271                if ((si->s->kif == pfi_all || si->s->kif == kif) &&
1272#endif
1273                    sk == (dir == PF_IN ? si->s->key[PF_SK_WIRE] :
1274                    si->s->key[PF_SK_STACK]))
1275                        return (si->s);
1276
1277        return (NULL);
1278}
1279
1280struct pf_state *
1281pf_find_state_all(struct pf_state_key_cmp *key, u_int dir, int *more)
1282{
1283        struct pf_state_key     *sk;
1284        struct pf_state_item    *si, *ret = NULL;
1285
1286#ifdef __FreeBSD__
1287        V_pf_status.fcounters[FCNT_STATE_SEARCH]++;
1288#else
1289        pf_status.fcounters[FCNT_STATE_SEARCH]++;
1290#endif
1291
1292#ifdef __FreeBSD__
1293        sk = RB_FIND(pf_state_tree, &V_pf_statetbl, (struct pf_state_key *)key);
1294#else
1295        sk = RB_FIND(pf_state_tree, &pf_statetbl, (struct pf_state_key *)key);
1296#endif
1297        if (sk != NULL) {
1298                TAILQ_FOREACH(si, &sk->states, entry)
1299                        if (dir == PF_INOUT ||
1300                            (sk == (dir == PF_IN ? si->s->key[PF_SK_WIRE] :
1301                            si->s->key[PF_SK_STACK]))) {
1302                                if (more == NULL)
1303                                        return (si->s);
1304
1305                                if (ret)
1306                                        (*more)++;
1307                                else
1308                                        ret = si;
1309                        }
1310        }
1311        return (ret ? ret->s : NULL);
1312}
1313
1314/* END state table stuff */
1315
1316
1317void
1318pf_purge_thread(void *v)
1319{
1320        int nloops = 0, s;
1321#ifdef __FreeBSD__
1322        int locked;
1323#endif
1324
1325        CURVNET_SET((struct vnet *)v);
1326
1327        for (;;) {
1328                tsleep(pf_purge_thread, PWAIT, "pftm", 1 * hz);
1329
1330#ifdef __FreeBSD__
1331                sx_slock(&V_pf_consistency_lock);
1332                PF_LOCK();
1333                locked = 0;
1334
1335                if (V_pf_end_threads) {
1336                        PF_UNLOCK();
1337                        sx_sunlock(&V_pf_consistency_lock);
1338                        sx_xlock(&V_pf_consistency_lock);
1339                        PF_LOCK();
1340
1341                        pf_purge_expired_states(V_pf_status.states, 1);
1342                        pf_purge_expired_fragments();
1343                        pf_purge_expired_src_nodes(1);
1344                        V_pf_end_threads++;
1345
1346                        sx_xunlock(&V_pf_consistency_lock);
1347                        PF_UNLOCK();
1348                        wakeup(pf_purge_thread);
1349                        kproc_exit(0);
1350                }
1351#endif
1352                s = splsoftnet();
1353
1354                /* process a fraction of the state table every second */
1355#ifdef __FreeBSD__
1356                if (!pf_purge_expired_states(1 + (V_pf_status.states /
1357                    V_pf_default_rule.timeout[PFTM_INTERVAL]), 0)) {
1358                        PF_UNLOCK();
1359                        sx_sunlock(&V_pf_consistency_lock);
1360                        sx_xlock(&V_pf_consistency_lock);
1361                        PF_LOCK();
1362                        locked = 1;
1363
1364                        pf_purge_expired_states(1 + (V_pf_status.states /
1365                            V_pf_default_rule.timeout[PFTM_INTERVAL]), 1);
1366                }
1367#else
1368                pf_purge_expired_states(1 + (pf_status.states
1369                    / pf_default_rule.timeout[PFTM_INTERVAL]));
1370#endif
1371
1372                /* purge other expired types every PFTM_INTERVAL seconds */
1373#ifdef __FreeBSD__
1374                if (++nloops >= V_pf_default_rule.timeout[PFTM_INTERVAL]) {
1375#else
1376                if (++nloops >= pf_default_rule.timeout[PFTM_INTERVAL]) {
1377#endif
1378                        pf_purge_expired_fragments();
1379                        pf_purge_expired_src_nodes(0);
1380                        nloops = 0;
1381                }
1382
1383                splx(s);
1384#ifdef __FreeBSD__
1385                PF_UNLOCK();
1386                if (locked)
1387                        sx_xunlock(&V_pf_consistency_lock);
1388                else
1389                        sx_sunlock(&V_pf_consistency_lock);
1390#endif
1391        }
1392        CURVNET_RESTORE();
1393}
1394
1395u_int32_t
1396pf_state_expires(const struct pf_state *state)
1397{
1398        u_int32_t       timeout;
1399        u_int32_t       start;
1400        u_int32_t       end;
1401        u_int32_t       states;
1402
1403        /* handle all PFTM_* > PFTM_MAX here */
1404        if (state->timeout == PFTM_PURGE)
1405                return (time_second);
1406        if (state->timeout == PFTM_UNTIL_PACKET)
1407                return (0);
1408#ifdef __FreeBSD__
1409        KASSERT(state->timeout != PFTM_UNLINKED,
1410            ("pf_state_expires: timeout == PFTM_UNLINKED"));
1411        KASSERT((state->timeout < PFTM_MAX),
1412            ("pf_state_expires: timeout > PFTM_MAX"));
1413#else
1414        KASSERT(state->timeout != PFTM_UNLINKED);
1415        KASSERT(state->timeout < PFTM_MAX);
1416#endif
1417        timeout = state->rule.ptr->timeout[state->timeout];
1418        if (!timeout)
1419#ifdef __FreeBSD__
1420                timeout = V_pf_default_rule.timeout[state->timeout];
1421#else
1422                timeout = pf_default_rule.timeout[state->timeout];
1423#endif
1424        start = state->rule.ptr->timeout[PFTM_ADAPTIVE_START];
1425        if (start) {
1426                end = state->rule.ptr->timeout[PFTM_ADAPTIVE_END];
1427                states = state->rule.ptr->states_cur;
1428        } else {
1429#ifdef __FreeBSD__
1430                start = V_pf_default_rule.timeout[PFTM_ADAPTIVE_START];
1431                end = V_pf_default_rule.timeout[PFTM_ADAPTIVE_END];
1432                states = V_pf_status.states;
1433#else
1434                start = pf_default_rule.timeout[PFTM_ADAPTIVE_START];
1435                end = pf_default_rule.timeout[PFTM_ADAPTIVE_END];
1436                states = pf_status.states;
1437#endif
1438        }
1439        if (end && states > start && start < end) {
1440                if (states < end)
1441                        return (state->expire + timeout * (end - states) /
1442                            (end - start));
1443                else
1444                        return (time_second);
1445        }
1446        return (state->expire + timeout);
1447}
1448
1449#ifdef __FreeBSD__
1450int
1451pf_purge_expired_src_nodes(int waslocked)
1452#else
1453void
1454pf_purge_expired_src_nodes(int waslocked)
1455#endif
1456{
1457        struct pf_src_node              *cur, *next;
1458        int                              locked = waslocked;
1459
1460#ifdef __FreeBSD__
1461        for (cur = RB_MIN(pf_src_tree, &V_tree_src_tracking); cur; cur = next) {
1462        next = RB_NEXT(pf_src_tree, &V_tree_src_tracking, cur);
1463#else
1464        for (cur = RB_MIN(pf_src_tree, &tree_src_tracking); cur; cur = next) {
1465        next = RB_NEXT(pf_src_tree, &tree_src_tracking, cur);
1466#endif
1467
1468                if (cur->states <= 0 && cur->expire <= time_second) {
1469                        if (! locked) {
1470#ifdef __FreeBSD__
1471                                if (!sx_try_upgrade(&V_pf_consistency_lock))
1472                                        return (0);
1473#else
1474                                rw_enter_write(&pf_consistency_lock);
1475#endif
1476                                next = RB_NEXT(pf_src_tree,
1477#ifdef __FreeBSD__
1478                                    &V_tree_src_tracking, cur);
1479#else
1480                                    &tree_src_tracking, cur);
1481#endif
1482                                locked = 1;
1483                        }
1484                        if (cur->rule.ptr != NULL) {
1485                                cur->rule.ptr->src_nodes--;
1486                                if (cur->rule.ptr->states_cur <= 0 &&
1487                                    cur->rule.ptr->max_src_nodes <= 0)
1488                                        pf_rm_rule(NULL, cur->rule.ptr);
1489                        }
1490#ifdef __FreeBSD__
1491                        RB_REMOVE(pf_src_tree, &V_tree_src_tracking, cur);
1492                        V_pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
1493                        V_pf_status.src_nodes--;
1494                        pool_put(&V_pf_src_tree_pl, cur);
1495#else
1496                        RB_REMOVE(pf_src_tree, &tree_src_tracking, cur);
1497                        pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
1498                        pf_status.src_nodes--;
1499                        pool_put(&pf_src_tree_pl, cur);
1500#endif
1501                }
1502        }
1503
1504        if (locked && !waslocked)
1505#ifdef __FreeBSD__
1506        {
1507                sx_downgrade(&V_pf_consistency_lock);
1508        }
1509        return (1);
1510#else
1511                rw_exit_write(&pf_consistency_lock);
1512#endif
1513}
1514
1515void
1516pf_src_tree_remove_state(struct pf_state *s)
1517{
1518        u_int32_t timeout;
1519
1520        if (s->src_node != NULL) {
1521                if (s->src.tcp_est)
1522                        --s->src_node->conn;
1523                if (--s->src_node->states <= 0) {
1524                        timeout = s->rule.ptr->timeout[PFTM_SRC_NODE];
1525                        if (!timeout)
1526                                timeout =
1527#ifdef __FreeBSD__
1528                                    V_pf_default_rule.timeout[PFTM_SRC_NODE];
1529#else
1530                                    pf_default_rule.timeout[PFTM_SRC_NODE];
1531#endif
1532                        s->src_node->expire = time_second + timeout;
1533                }
1534        }
1535        if (s->nat_src_node != s->src_node && s->nat_src_node != NULL) {
1536                if (--s->nat_src_node->states <= 0) {
1537                        timeout = s->rule.ptr->timeout[PFTM_SRC_NODE];
1538                        if (!timeout)
1539                                timeout =
1540#ifdef __FreeBSD__
1541                                    V_pf_default_rule.timeout[PFTM_SRC_NODE];
1542#else
1543                                    pf_default_rule.timeout[PFTM_SRC_NODE];
1544#endif
1545                        s->nat_src_node->expire = time_second + timeout;
1546                }
1547        }
1548        s->src_node = s->nat_src_node = NULL;
1549}
1550
1551/* callers should be at splsoftnet */
1552void
1553pf_unlink_state(struct pf_state *cur)
1554{
1555#ifdef __FreeBSD__
1556        if (cur->local_flags & PFSTATE_EXPIRING)
1557                return;
1558        cur->local_flags |= PFSTATE_EXPIRING;
1559#else
1560        splassert(IPL_SOFTNET);
1561#endif
1562
1563        if (cur->src.state == PF_TCPS_PROXY_DST) {
1564                /* XXX wire key the right one? */
1565#ifdef __FreeBSD__
1566                pf_send_tcp(NULL, cur->rule.ptr, cur->key[PF_SK_WIRE]->af,
1567#else
1568                pf_send_tcp(cur->rule.ptr, cur->key[PF_SK_WIRE]->af,
1569#endif
1570                    &cur->key[PF_SK_WIRE]->addr[1],
1571                    &cur->key[PF_SK_WIRE]->addr[0],
1572                    cur->key[PF_SK_WIRE]->port[1],
1573                    cur->key[PF_SK_WIRE]->port[0],
1574                    cur->src.seqhi, cur->src.seqlo + 1,
1575                    TH_RST|TH_ACK, 0, 0, 0, 1, cur->tag, NULL, NULL);
1576        }
1577#ifdef __FreeBSD__
1578        RB_REMOVE(pf_state_tree_id, &V_tree_id, cur);
1579#else
1580        RB_REMOVE(pf_state_tree_id, &tree_id, cur);
1581#endif
1582#if NPFLOW > 0
1583        if (cur->state_flags & PFSTATE_PFLOW)
1584#ifdef __FreeBSD__
1585                if (export_pflow_ptr != NULL)
1586                        export_pflow_ptr(cur);
1587#else
1588                export_pflow(cur);
1589#endif
1590#endif
1591#if NPFSYNC > 0
1592#ifdef __FreeBSD__
1593        if (pfsync_delete_state_ptr != NULL)
1594                pfsync_delete_state_ptr(cur);
1595#else
1596        pfsync_delete_state(cur);
1597#endif
1598#endif
1599        cur->timeout = PFTM_UNLINKED;
1600        pf_src_tree_remove_state(cur);
1601        pf_detach_state(cur);
1602}
1603
1604/* callers should be at splsoftnet and hold the
1605 * write_lock on pf_consistency_lock */
1606void
1607pf_free_state(struct pf_state *cur)
1608{
1609#ifndef __FreeBSD__
1610        splassert(IPL_SOFTNET);
1611#endif
1612
1613#if NPFSYNC > 0
1614#ifdef __FreeBSD__
1615        if (pfsync_state_in_use_ptr != NULL &&
1616                pfsync_state_in_use_ptr(cur))
1617#else
1618        if (pfsync_state_in_use(cur))
1619#endif
1620                return;
1621#endif
1622#ifdef __FreeBSD__
1623        KASSERT(cur->timeout == PFTM_UNLINKED,
1624            ("pf_free_state: cur->timeout != PFTM_UNLINKED"));
1625#else
1626        KASSERT(cur->timeout == PFTM_UNLINKED);
1627#endif
1628        if (--cur->rule.ptr->states_cur <= 0 &&
1629            cur->rule.ptr->src_nodes <= 0)
1630                pf_rm_rule(NULL, cur->rule.ptr);
1631        if (cur->nat_rule.ptr != NULL)
1632                if (--cur->nat_rule.ptr->states_cur <= 0 &&
1633                        cur->nat_rule.ptr->src_nodes <= 0)
1634                        pf_rm_rule(NULL, cur->nat_rule.ptr);
1635        if (cur->anchor.ptr != NULL)
1636                if (--cur->anchor.ptr->states_cur <= 0)
1637                        pf_rm_rule(NULL, cur->anchor.ptr);
1638        pf_normalize_tcp_cleanup(cur);
1639        pfi_kif_unref(cur->kif, PFI_KIF_REF_STATE);
1640#ifdef __FreeBSD__
1641        TAILQ_REMOVE(&V_state_list, cur, entry_list);
1642#else
1643        TAILQ_REMOVE(&state_list, cur, entry_list);
1644#endif
1645        if (cur->tag)
1646                pf_tag_unref(cur->tag);
1647#ifdef __FreeBSD__
1648        pool_put(&V_pf_state_pl, cur);
1649        V_pf_status.fcounters[FCNT_STATE_REMOVALS]++;
1650        V_pf_status.states--;
1651#else
1652        pool_put(&pf_state_pl, cur);
1653        pf_status.fcounters[FCNT_STATE_REMOVALS]++;
1654        pf_status.states--;
1655#endif
1656}
1657
1658#ifdef __FreeBSD__
1659int
1660pf_purge_expired_states(u_int32_t maxcheck, int waslocked)
1661#else
1662void
1663pf_purge_expired_states(u_int32_t maxcheck)
1664#endif
1665{
1666        static struct pf_state  *cur = NULL;
1667        struct pf_state         *next;
1668#ifdef __FreeBSD__
1669        int                      locked = waslocked;
1670#else
1671        int                      locked = 0;
1672#endif
1673
1674        while (maxcheck--) {
1675                /* wrap to start of list when we hit the end */
1676                if (cur == NULL) {
1677#ifdef __FreeBSD__
1678                        cur = TAILQ_FIRST(&V_state_list);
1679#else
1680                        cur = TAILQ_FIRST(&state_list);
1681#endif
1682                        if (cur == NULL)
1683                                break;  /* list empty */
1684                }
1685
1686                /* get next state, as cur may get deleted */
1687                next = TAILQ_NEXT(cur, entry_list);
1688
1689                if (cur->timeout == PFTM_UNLINKED) {
1690                        /* free unlinked state */
1691                        if (! locked) {
1692#ifdef __FreeBSD__
1693                                if (!sx_try_upgrade(&V_pf_consistency_lock))
1694                                        return (0);
1695#else
1696                                rw_enter_write(&pf_consistency_lock);
1697#endif
1698                                locked = 1;
1699                        }
1700                        pf_free_state(cur);
1701                } else if (pf_state_expires(cur) <= time_second) {
1702                        /* unlink and free expired state */
1703                        pf_unlink_state(cur);
1704                        if (! locked) {
1705#ifdef __FreeBSD__
1706                                if (!sx_try_upgrade(&V_pf_consistency_lock))
1707                                        return (0);
1708#else
1709                                rw_enter_write(&pf_consistency_lock);
1710#endif
1711                                locked = 1;
1712                        }
1713                        pf_free_state(cur);
1714                }
1715                cur = next;
1716        }
1717
1718#ifdef __FreeBSD__
1719        if (!waslocked && locked)
1720                sx_downgrade(&V_pf_consistency_lock);
1721
1722        return (1);
1723#else
1724        if (locked)
1725                rw_exit_write(&pf_consistency_lock);
1726#endif
1727}
1728
1729int
1730pf_tbladdr_setup(struct pf_ruleset *rs, struct pf_addr_wrap *aw)
1731{
1732        if (aw->type != PF_ADDR_TABLE)
1733                return (0);
1734        if ((aw->p.tbl = pfr_attach_table(rs, aw->v.tblname, 1)) == NULL)
1735                return (1);
1736        return (0);
1737}
1738
1739void
1740pf_tbladdr_remove(struct pf_addr_wrap *aw)
1741{
1742        if (aw->type != PF_ADDR_TABLE || aw->p.tbl == NULL)
1743                return;
1744        pfr_detach_table(aw->p.tbl);
1745        aw->p.tbl = NULL;
1746}
1747
1748void
1749pf_tbladdr_copyout(struct pf_addr_wrap *aw)
1750{
1751        struct pfr_ktable *kt = aw->p.tbl;
1752
1753        if (aw->type != PF_ADDR_TABLE || kt == NULL)
1754                return;
1755        if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE) && kt->pfrkt_root != NULL)
1756                kt = kt->pfrkt_root;
1757        aw->p.tbl = NULL;
1758        aw->p.tblcnt = (kt->pfrkt_flags & PFR_TFLAG_ACTIVE) ?
1759                kt->pfrkt_cnt : -1;
1760}
1761
1762void
1763pf_print_host(struct pf_addr *addr, u_int16_t p, sa_family_t af)
1764{
1765        switch (af) {
1766#ifdef INET
1767        case AF_INET: {
1768                u_int32_t a = ntohl(addr->addr32[0]);
1769                printf("%u.%u.%u.%u", (a>>24)&255, (a>>16)&255,
1770                    (a>>8)&255, a&255);
1771                if (p) {
1772                        p = ntohs(p);
1773                        printf(":%u", p);
1774                }
1775                break;
1776        }
1777#endif /* INET */
1778#ifdef INET6
1779        case AF_INET6: {
1780                u_int16_t b;
1781                u_int8_t i, curstart, curend, maxstart, maxend;
1782                curstart = curend = maxstart = maxend = 255;
1783                for (i = 0; i < 8; i++) {
1784                        if (!addr->addr16[i]) {
1785                                if (curstart == 255)
1786                                        curstart = i;
1787                                curend = i;
1788                        } else {
1789                                if ((curend - curstart) >
1790                                    (maxend - maxstart)) {
1791                                        maxstart = curstart;
1792                                        maxend = curend;
1793                                }
1794                                curstart = curend = 255;
1795                        }
1796                }
1797                if ((curend - curstart) >
1798                    (maxend - maxstart)) {
1799                        maxstart = curstart;
1800                        maxend = curend;
1801                }
1802                for (i = 0; i < 8; i++) {
1803                        if (i >= maxstart && i <= maxend) {
1804                                if (i == 0)
1805                                        printf(":");
1806                                if (i == maxend)
1807                                        printf(":");
1808                        } else {
1809                                b = ntohs(addr->addr16[i]);
1810                                printf("%x", b);
1811                                if (i < 7)
1812                                        printf(":");
1813                        }
1814                }
1815                if (p) {
1816                        p = ntohs(p);
1817                        printf("[%u]", p);
1818                }
1819                break;
1820        }
1821#endif /* INET6 */
1822        }
1823}
1824
1825void
1826pf_print_state(struct pf_state *s)
1827{
1828        pf_print_state_parts(s, NULL, NULL);
1829}
1830
1831void
1832pf_print_state_parts(struct pf_state *s,
1833    struct pf_state_key *skwp, struct pf_state_key *sksp)
1834{
1835        struct pf_state_key *skw, *sks;
1836        u_int8_t proto, dir;
1837
1838        /* Do our best to fill these, but they're skipped if NULL */
1839        skw = skwp ? skwp : (s ? s->key[PF_SK_WIRE] : NULL);
1840        sks = sksp ? sksp : (s ? s->key[PF_SK_STACK] : NULL);
1841        proto = skw ? skw->proto : (sks ? sks->proto : 0);
1842        dir = s ? s->direction : 0;
1843
1844        switch (proto) {
1845        case IPPROTO_IPV4:
1846                printf("IPv4");
1847                break;
1848        case IPPROTO_IPV6:
1849                printf("IPv6");
1850                break;
1851        case IPPROTO_TCP:
1852                printf("TCP");
1853                break;
1854        case IPPROTO_UDP:
1855                printf("UDP");
1856                break;
1857        case IPPROTO_ICMP:
1858                printf("ICMP");
1859                break;
1860        case IPPROTO_ICMPV6:
1861                printf("ICMPv6");
1862                break;
1863        default:
1864                printf("%u", skw->proto);
1865                break;
1866        }
1867        switch (dir) {
1868        case PF_IN:
1869                printf(" in");
1870                break;
1871        case PF_OUT:
1872                printf(" out");
1873                break;
1874        }
1875        if (skw) {
1876                printf(" wire: ");
1877                pf_print_host(&skw->addr[0], skw->port[0], skw->af);
1878                printf(" ");
1879                pf_print_host(&skw->addr[1], skw->port[1], skw->af);
1880        }
1881        if (sks) {
1882                printf(" stack: ");
1883                if (sks != skw) {
1884                        pf_print_host(&sks->addr[0], sks->port[0], sks->af);
1885                        printf(" ");
1886                        pf_print_host(&sks->addr[1], sks->port[1], sks->af);
1887                } else
1888                        printf("-");
1889        }
1890        if (s) {
1891                if (proto == IPPROTO_TCP) {
1892                        printf(" [lo=%u high=%u win=%u modulator=%u",
1893                            s->src.seqlo, s->src.seqhi,
1894                            s->src.max_win, s->src.seqdiff);
1895                        if (s->src.wscale && s->dst.wscale)
1896                                printf(" wscale=%u",
1897                                    s->src.wscale & PF_WSCALE_MASK);
1898                        printf("]");
1899                        printf(" [lo=%u high=%u win=%u modulator=%u",
1900                            s->dst.seqlo, s->dst.seqhi,
1901                            s->dst.max_win, s->dst.seqdiff);
1902                        if (s->src.wscale && s->dst.wscale)
1903                                printf(" wscale=%u",
1904                                s->dst.wscale & PF_WSCALE_MASK);
1905                        printf("]");
1906                }
1907                printf(" %u:%u", s->src.state, s->dst.state);
1908        }
1909}
1910
1911void
1912pf_print_flags(u_int8_t f)
1913{
1914        if (f)
1915                printf(" ");
1916        if (f & TH_FIN)
1917                printf("F");
1918        if (f & TH_SYN)
1919                printf("S");
1920        if (f & TH_RST)
1921                printf("R");
1922        if (f & TH_PUSH)
1923                printf("P");
1924        if (f & TH_ACK)
1925                printf("A");
1926        if (f & TH_URG)
1927                printf("U");
1928        if (f & TH_ECE)
1929                printf("E");
1930        if (f & TH_CWR)
1931                printf("W");
1932}
1933
1934#define PF_SET_SKIP_STEPS(i)                                    \
1935        do {                                                    \
1936                while (head[i] != cur) {                        \
1937                        head[i]->skip[i].ptr = cur;             \
1938                        head[i] = TAILQ_NEXT(head[i], entries); \
1939                }                                               \
1940        } while (0)
1941
1942void
1943pf_calc_skip_steps(struct pf_rulequeue *rules)
1944{
1945        struct pf_rule *cur, *prev, *head[PF_SKIP_COUNT];
1946        int i;
1947
1948        cur = TAILQ_FIRST(rules);
1949        prev = cur;
1950        for (i = 0; i < PF_SKIP_COUNT; ++i)
1951                head[i] = cur;
1952        while (cur != NULL) {
1953
1954                if (cur->kif != prev->kif || cur->ifnot != prev->ifnot)
1955                        PF_SET_SKIP_STEPS(PF_SKIP_IFP);
1956                if (cur->direction != prev->direction)
1957                        PF_SET_SKIP_STEPS(PF_SKIP_DIR);
1958                if (cur->af != prev->af)
1959                        PF_SET_SKIP_STEPS(PF_SKIP_AF);
1960                if (cur->proto != prev->proto)
1961                        PF_SET_SKIP_STEPS(PF_SKIP_PROTO);
1962                if (cur->src.neg != prev->src.neg ||
1963                    pf_addr_wrap_neq(&cur->src.addr, &prev->src.addr))
1964                        PF_SET_SKIP_STEPS(PF_SKIP_SRC_ADDR);
1965                if (cur->src.port[0] != prev->src.port[0] ||
1966                    cur->src.port[1] != prev->src.port[1] ||
1967                    cur->src.port_op != prev->src.port_op)
1968                        PF_SET_SKIP_STEPS(PF_SKIP_SRC_PORT);
1969                if (cur->dst.neg != prev->dst.neg ||
1970                    pf_addr_wrap_neq(&cur->dst.addr, &prev->dst.addr))
1971                        PF_SET_SKIP_STEPS(PF_SKIP_DST_ADDR);
1972                if (cur->dst.port[0] != prev->dst.port[0] ||
1973                    cur->dst.port[1] != prev->dst.port[1] ||
1974                    cur->dst.port_op != prev->dst.port_op)
1975                        PF_SET_SKIP_STEPS(PF_SKIP_DST_PORT);
1976
1977                prev = cur;
1978                cur = TAILQ_NEXT(cur, entries);
1979        }
1980        for (i = 0; i < PF_SKIP_COUNT; ++i)
1981                PF_SET_SKIP_STEPS(i);
1982}
1983
1984int
1985pf_addr_wrap_neq(struct pf_addr_wrap *aw1, struct pf_addr_wrap *aw2)
1986{
1987        if (aw1->type != aw2->type)
1988                return (1);
1989        switch (aw1->type) {
1990        case PF_ADDR_ADDRMASK:
1991        case PF_ADDR_RANGE:
1992                if (PF_ANEQ(&aw1->v.a.addr, &aw2->v.a.addr, 0))
1993                        return (1);
1994                if (PF_ANEQ(&aw1->v.a.mask, &aw2->v.a.mask, 0))
1995                        return (1);
1996                return (0);
1997        case PF_ADDR_DYNIFTL:
1998                return (aw1->p.dyn->pfid_kt != aw2->p.dyn->pfid_kt);
1999        case PF_ADDR_NOROUTE:
2000        case PF_ADDR_URPFFAILED:
2001                return (0);
2002        case PF_ADDR_TABLE:
2003                return (aw1->p.tbl != aw2->p.tbl);
2004        case PF_ADDR_RTLABEL:
2005                return (aw1->v.rtlabel != aw2->v.rtlabel);
2006        default:
2007                printf("invalid address type: %d\n", aw1->type);
2008                return (1);
2009        }
2010}
2011
2012u_int16_t
2013pf_cksum_fixup(u_int16_t cksum, u_int16_t old, u_int16_t new, u_int8_t udp)
2014{
2015        u_int32_t       l;
2016
2017        if (udp && !cksum)
2018                return (0x0000);
2019        l = cksum + old - new;
2020        l = (l >> 16) + (l & 65535);
2021        l = l & 65535;
2022        if (udp && !l)
2023                return (0xFFFF);
2024        return (l);
2025}
2026
2027void
2028pf_change_ap(struct pf_addr *a, u_int16_t *p, u_int16_t *ic, u_int16_t *pc,
2029    struct pf_addr *an, u_int16_t pn, u_int8_t u, sa_family_t af)
2030{
2031        struct pf_addr  ao;
2032        u_int16_t       po = *p;
2033
2034        PF_ACPY(&ao, a, af);
2035        PF_ACPY(a, an, af);
2036
2037        *p = pn;
2038
2039        switch (af) {
2040#ifdef INET
2041        case AF_INET:
2042                *ic = pf_cksum_fixup(pf_cksum_fixup(*ic,
2043                    ao.addr16[0], an->addr16[0], 0),
2044                    ao.addr16[1], an->addr16[1], 0);
2045                *p = pn;
2046                *pc = pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(*pc,
2047                    ao.addr16[0], an->addr16[0], u),
2048                    ao.addr16[1], an->addr16[1], u),
2049                    po, pn, u);
2050                break;
2051#endif /* INET */
2052#ifdef INET6
2053        case AF_INET6:
2054                *pc = pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
2055                    pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
2056                    pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(*pc,
2057                    ao.addr16[0], an->addr16[0], u),
2058                    ao.addr16[1], an->addr16[1], u),
2059                    ao.addr16[2], an->addr16[2], u),
2060                    ao.addr16[3], an->addr16[3], u),
2061                    ao.addr16[4], an->addr16[4], u),
2062                    ao.addr16[5], an->addr16[5], u),
2063                    ao.addr16[6], an->addr16[6], u),
2064                    ao.addr16[7], an->addr16[7], u),
2065                    po, pn, u);
2066                break;
2067#endif /* INET6 */
2068        }
2069}
2070
2071
2072/* Changes a u_int32_t.  Uses a void * so there are no align restrictions */
2073void
2074pf_change_a(void *a, u_int16_t *c, u_int32_t an, u_int8_t u)
2075{
2076        u_int32_t       ao;
2077
2078        memcpy(&ao, a, sizeof(ao));
2079        memcpy(a, &an, sizeof(u_int32_t));
2080        *c = pf_cksum_fixup(pf_cksum_fixup(*c, ao / 65536, an / 65536, u),
2081            ao % 65536, an % 65536, u);
2082}
2083
2084#ifdef INET6
2085void
2086pf_change_a6(struct pf_addr *a, u_int16_t *c, struct pf_addr *an, u_int8_t u)
2087{
2088        struct pf_addr  ao;
2089
2090        PF_ACPY(&ao, a, AF_INET6);
2091        PF_ACPY(a, an, AF_INET6);
2092
2093        *c = pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
2094            pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
2095            pf_cksum_fixup(pf_cksum_fixup(*c,
2096            ao.addr16[0], an->addr16[0], u),
2097            ao.addr16[1], an->addr16[1], u),
2098            ao.addr16[2], an->addr16[2], u),
2099            ao.addr16[3], an->addr16[3], u),
2100            ao.addr16[4], an->addr16[4], u),
2101            ao.addr16[5], an->addr16[5], u),
2102            ao.addr16[6], an->addr16[6], u),
2103            ao.addr16[7], an->addr16[7], u);
2104}
2105#endif /* INET6 */
2106
2107void
2108pf_change_icmp(struct pf_addr *ia, u_int16_t *ip, struct pf_addr *oa,
2109    struct pf_addr *na, u_int16_t np, u_int16_t *pc, u_int16_t *h2c,
2110    u_int16_t *ic, u_int16_t *hc, u_int8_t u, sa_family_t af)
2111{
2112        struct pf_addr  oia, ooa;
2113
2114        PF_ACPY(&oia, ia, af);
2115        if (oa)
2116                PF_ACPY(&ooa, oa, af);
2117
2118        /* Change inner protocol port, fix inner protocol checksum. */
2119        if (ip != NULL) {
2120                u_int16_t       oip = *ip;
2121                u_int32_t       opc;
2122
2123                if (pc != NULL)
2124                        opc = *pc;
2125                *ip = np;
2126                if (pc != NULL)
2127                        *pc = pf_cksum_fixup(*pc, oip, *ip, u);
2128                *ic = pf_cksum_fixup(*ic, oip, *ip, 0);
2129                if (pc != NULL)
2130                        *ic = pf_cksum_fixup(*ic, opc, *pc, 0);
2131        }
2132        /* Change inner ip address, fix inner ip and icmp checksums. */
2133        PF_ACPY(ia, na, af);
2134        switch (af) {
2135#ifdef INET
2136        case AF_INET: {
2137                u_int32_t        oh2c = *h2c;
2138
2139                *h2c = pf_cksum_fixup(pf_cksum_fixup(*h2c,
2140                    oia.addr16[0], ia->addr16[0], 0),
2141                    oia.addr16[1], ia->addr16[1], 0);
2142                *ic = pf_cksum_fixup(pf_cksum_fixup(*ic,
2143                    oia.addr16[0], ia->addr16[0], 0),
2144                    oia.addr16[1], ia->addr16[1], 0);
2145                *ic = pf_cksum_fixup(*ic, oh2c, *h2c, 0);
2146                break;
2147        }
2148#endif /* INET */
2149#ifdef INET6
2150        case AF_INET6:
2151                *ic = pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
2152                    pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
2153                    pf_cksum_fixup(pf_cksum_fixup(*ic,
2154                    oia.addr16[0], ia->addr16[0], u),
2155                    oia.addr16[1], ia->addr16[1], u),
2156                    oia.addr16[2], ia->addr16[2], u),
2157                    oia.addr16[3], ia->addr16[3], u),
2158                    oia.addr16[4], ia->addr16[4], u),
2159                    oia.addr16[5], ia->addr16[5], u),
2160                    oia.addr16[6], ia->addr16[6], u),
2161                    oia.addr16[7], ia->addr16[7], u);
2162                break;
2163#endif /* INET6 */
2164        }
2165        /* Outer ip address, fix outer ip or icmpv6 checksum, if necessary. */
2166        if (oa) {
2167                PF_ACPY(oa, na, af);
2168                switch (af) {
2169#ifdef INET
2170                case AF_INET:
2171                        *hc = pf_cksum_fixup(pf_cksum_fixup(*hc,
2172                            ooa.addr16[0], oa->addr16[0], 0),
2173                            ooa.addr16[1], oa->addr16[1], 0);
2174                        break;
2175#endif /* INET */
2176#ifdef INET6
2177                case AF_INET6:
2178                        *ic = pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
2179                            pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
2180                            pf_cksum_fixup(pf_cksum_fixup(*ic,
2181                            ooa.addr16[0], oa->addr16[0], u),
2182                            ooa.addr16[1], oa->addr16[1], u),
2183                            ooa.addr16[2], oa->addr16[2], u),
2184                            ooa.addr16[3], oa->addr16[3], u),
2185                            ooa.addr16[4], oa->addr16[4], u),
2186                            ooa.addr16[5], oa->addr16[5], u),
2187                            ooa.addr16[6], oa->addr16[6], u),
2188                            ooa.addr16[7], oa->addr16[7], u);
2189                        break;
2190#endif /* INET6 */
2191                }
2192        }
2193}
2194
2195
2196/*
2197 * Need to modulate the sequence numbers in the TCP SACK option
2198 * (credits to Krzysztof Pfaff for report and patch)
2199 */
2200int
2201pf_modulate_sack(struct mbuf *m, int off, struct pf_pdesc *pd,
2202    struct tcphdr *th, struct pf_state_peer *dst)
2203{
2204        int hlen = (th->th_off << 2) - sizeof(*th), thoptlen = hlen;
2205#ifdef __FreeBSD__
2206        u_int8_t opts[TCP_MAXOLEN], *opt = opts;
2207#else
2208        u_int8_t opts[MAX_TCPOPTLEN], *opt = opts;
2209#endif
2210        int copyback = 0, i, olen;
2211        struct sackblk sack;
2212
2213#define TCPOLEN_SACKLEN (TCPOLEN_SACK + 2)
2214        if (hlen < TCPOLEN_SACKLEN ||
2215            !pf_pull_hdr(m, off + sizeof(*th), opts, hlen, NULL, NULL, pd->af))
2216                return 0;
2217
2218        while (hlen >= TCPOLEN_SACKLEN) {
2219                olen = opt[1];
2220                switch (*opt) {
2221                case TCPOPT_EOL:        /* FALLTHROUGH */
2222                case TCPOPT_NOP:
2223                        opt++;
2224                        hlen--;
2225                        break;
2226                case TCPOPT_SACK:
2227                        if (olen > hlen)
2228                                olen = hlen;
2229                        if (olen >= TCPOLEN_SACKLEN) {
2230                                for (i = 2; i + TCPOLEN_SACK <= olen;
2231                                    i += TCPOLEN_SACK) {
2232                                        memcpy(&sack, &opt[i], sizeof(sack));
2233                                        pf_change_a(&sack.start, &th->th_sum,
2234                                            htonl(ntohl(sack.start) -
2235                                            dst->seqdiff), 0);
2236                                        pf_change_a(&sack.end, &th->th_sum,
2237                                            htonl(ntohl(sack.end) -
2238                                            dst->seqdiff), 0);
2239                                        memcpy(&opt[i], &sack, sizeof(sack));
2240                                }
2241                                copyback = 1;
2242                        }
2243                        /* FALLTHROUGH */
2244                default:
2245                        if (olen < 2)
2246                                olen = 2;
2247                        hlen -= olen;
2248                        opt += olen;
2249                }
2250        }
2251
2252        if (copyback)
2253#ifdef __FreeBSD__
2254                m_copyback(m, off + sizeof(*th), thoptlen, (caddr_t)opts);
2255#else
2256                m_copyback(m, off + sizeof(*th), thoptlen, opts);
2257#endif
2258        return (copyback);
2259}
2260
2261void
2262#ifdef __FreeBSD__
2263pf_send_tcp(struct mbuf *replyto, const struct pf_rule *r, sa_family_t af,
2264#else
2265pf_send_tcp(const struct pf_rule *r, sa_family_t af,
2266#endif
2267    const struct pf_addr *saddr, const struct pf_addr *daddr,
2268    u_int16_t sport, u_int16_t dport, u_int32_t seq, u_int32_t ack,
2269    u_int8_t flags, u_int16_t win, u_int16_t mss, u_int8_t ttl, int tag,
2270    u_int16_t rtag, struct ether_header *eh, struct ifnet *ifp)
2271{
2272        struct mbuf     *m;
2273        int              len, tlen;
2274#ifdef INET
2275        struct ip       *h;
2276#endif /* INET */
2277#ifdef INET6
2278        struct ip6_hdr  *h6;
2279#endif /* INET6 */
2280        struct tcphdr   *th;
2281        char            *opt;
2282#ifdef __FreeBSD__
2283        struct pf_mtag  *pf_mtag;
2284
2285        KASSERT(
2286#ifdef INET
2287            af == AF_INET
2288#else
2289            0
2290#endif
2291            ||
2292#ifdef INET6
2293            af == AF_INET6
2294#else
2295            0
2296#endif
2297            , ("Unsupported AF %d", af));
2298        len = 0;
2299        th = NULL;
2300#ifdef INET
2301        h = NULL;
2302#endif
2303#ifdef INET6
2304        h6 = NULL;
2305#endif
2306#endif /* __FreeBSD__ */
2307
2308        /* maximum segment size tcp option */
2309        tlen = sizeof(struct tcphdr);
2310        if (mss)
2311                tlen += 4;
2312
2313        switch (af) {
2314#ifdef INET
2315        case AF_INET:
2316                len = sizeof(struct ip) + tlen;
2317                break;
2318#endif /* INET */
2319#ifdef INET6
2320        case AF_INET6:
2321                len = sizeof(struct ip6_hdr) + tlen;
2322                break;
2323#endif /* INET6 */
2324        }
2325
2326        /* create outgoing mbuf */
2327        m = m_gethdr(M_DONTWAIT, MT_HEADER);
2328        if (m == NULL)
2329                return;
2330#ifdef __FreeBSD__
2331#ifdef MAC
2332        mac_netinet_firewall_send(m);
2333#endif
2334        if ((pf_mtag = pf_get_mtag(m)) == NULL) {
2335                m_freem(m);
2336                return;
2337        }
2338#endif
2339        if (tag)
2340#ifdef __FreeBSD__
2341                m->m_flags |= M_SKIP_FIREWALL;
2342        pf_mtag->tag = rtag;
2343#else
2344                m->m_pkthdr.pf.flags |= PF_TAG_GENERATED;
2345        m->m_pkthdr.pf.tag = rtag;
2346#endif
2347
2348        if (r != NULL && r->rtableid >= 0)
2349#ifdef __FreeBSD__
2350        {
2351                M_SETFIB(m, r->rtableid);
2352                pf_mtag->rtableid = r->rtableid;
2353#else
2354                m->m_pkthdr.pf.rtableid = r->rtableid;
2355#endif
2356#ifdef __FreeBSD__
2357        }
2358#endif
2359
2360#ifdef ALTQ
2361        if (r != NULL && r->qid) {
2362#ifdef __FreeBSD__
2363                pf_mtag->qid = r->qid;
2364
2365                /* add hints for ecn */
2366                pf_mtag->hdr = mtod(m, struct ip *);
2367#else
2368                m->m_pkthdr.pf.qid = r->qid;
2369                /* add hints for ecn */
2370                m->m_pkthdr.pf.hdr = mtod(m, struct ip *);
2371#endif
2372        }
2373#endif /* ALTQ */
2374        m->m_data += max_linkhdr;
2375        m->m_pkthdr.len = m->m_len = len;
2376        m->m_pkthdr.rcvif = NULL;
2377        bzero(m->m_data, len);
2378        switch (af) {
2379#ifdef INET
2380        case AF_INET:
2381                h = mtod(m, struct ip *);
2382
2383                /* IP header fields included in the TCP checksum */
2384                h->ip_p = IPPROTO_TCP;
2385                h->ip_len = htons(tlen);
2386                h->ip_src.s_addr = saddr->v4.s_addr;
2387                h->ip_dst.s_addr = daddr->v4.s_addr;
2388
2389                th = (struct tcphdr *)((caddr_t)h + sizeof(struct ip));
2390                break;
2391#endif /* INET */
2392#ifdef INET6
2393        case AF_INET6:
2394                h6 = mtod(m, struct ip6_hdr *);
2395
2396                /* IP header fields included in the TCP checksum */
2397                h6->ip6_nxt = IPPROTO_TCP;
2398                h6->ip6_plen = htons(tlen);
2399                memcpy(&h6->ip6_src, &saddr->v6, sizeof(struct in6_addr));
2400                memcpy(&h6->ip6_dst, &daddr->v6, sizeof(struct in6_addr));
2401
2402                th = (struct tcphdr *)((caddr_t)h6 + sizeof(struct ip6_hdr));
2403                break;
2404#endif /* INET6 */
2405        }
2406
2407        /* TCP header */
2408        th->th_sport = sport;
2409        th->th_dport = dport;
2410        th->th_seq = htonl(seq);
2411        th->th_ack = htonl(ack);
2412        th->th_off = tlen >> 2;
2413        th->th_flags = flags;
2414        th->th_win = htons(win);
2415
2416        if (mss) {
2417                opt = (char *)(th + 1);
2418                opt[0] = TCPOPT_MAXSEG;
2419                opt[1] = 4;
2420                HTONS(mss);
2421                bcopy((caddr_t)&mss, (caddr_t)(opt + 2), 2);
2422        }
2423
2424        switch (af) {
2425#ifdef INET
2426        case AF_INET:
2427                /* TCP checksum */
2428                th->th_sum = in_cksum(m, len);
2429
2430                /* Finish the IP header */
2431                h->ip_v = 4;
2432                h->ip_hl = sizeof(*h) >> 2;
2433                h->ip_tos = IPTOS_LOWDELAY;
2434#ifdef __FreeBSD__
2435                h->ip_off = V_path_mtu_discovery ? IP_DF : 0;
2436                h->ip_len = len;
2437                h->ip_ttl = ttl ? ttl : V_ip_defttl;
2438#else
2439                h->ip_len = htons(len);
2440                h->ip_off = htons(ip_mtudisc ? IP_DF : 0);
2441                h->ip_ttl = ttl ? ttl : ip_defttl;
2442#endif
2443                h->ip_sum = 0;
2444                if (eh == NULL) {
2445#ifdef __FreeBSD__
2446                PF_UNLOCK();
2447                ip_output(m, (void *)NULL, (void *)NULL, 0,
2448                    (void *)NULL, (void *)NULL);
2449                PF_LOCK();
2450#else /* ! __FreeBSD__ */
2451                        ip_output(m, (void *)NULL, (void *)NULL, 0,
2452                            (void *)NULL, (void *)NULL);
2453#endif
2454                } else {
2455                        struct route             ro;
2456                        struct rtentry           rt;
2457                        struct ether_header     *e = (void *)ro.ro_dst.sa_data;
2458
2459                        if (ifp == NULL) {
2460                                m_freem(m);
2461                                return;
2462                        }
2463                        rt.rt_ifp = ifp;
2464                        ro.ro_rt = &rt;
2465                        ro.ro_dst.sa_len = sizeof(ro.ro_dst);
2466                        ro.ro_dst.sa_family = pseudo_AF_HDRCMPLT;
2467                        bcopy(eh->ether_dhost, e->ether_shost, ETHER_ADDR_LEN);
2468                        bcopy(eh->ether_shost, e->ether_dhost, ETHER_ADDR_LEN);
2469                        e->ether_type = eh->ether_type;
2470#ifdef __FreeBSD__
2471                        PF_UNLOCK();
2472                        /* XXX_IMPORT: later */
2473                        ip_output(m, (void *)NULL, &ro, 0,
2474                            (void *)NULL, (void *)NULL);
2475                        PF_LOCK();
2476#else /* ! __FreeBSD__ */
2477                        ip_output(m, (void *)NULL, &ro, IP_ROUTETOETHER,
2478                            (void *)NULL, (void *)NULL);
2479#endif
2480                }
2481                break;
2482#endif /* INET */
2483#ifdef INET6
2484        case AF_INET6:
2485                /* TCP checksum */
2486                th->th_sum = in6_cksum(m, IPPROTO_TCP,
2487                    sizeof(struct ip6_hdr), tlen);
2488
2489                h6->ip6_vfc |= IPV6_VERSION;
2490                h6->ip6_hlim = IPV6_DEFHLIM;
2491
2492#ifdef __FreeBSD__
2493                PF_UNLOCK();
2494                ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL);
2495                PF_LOCK();
2496#else
2497                ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL);
2498#endif
2499                break;
2500#endif /* INET6 */
2501        }
2502}
2503
2504static void
2505pf_send_icmp(struct mbuf *m, u_int8_t type, u_int8_t code, sa_family_t af,
2506    struct pf_rule *r)
2507{
2508        struct mbuf     *m0;
2509#ifdef __FreeBSD__
2510#ifdef INET
2511        struct ip *ip;
2512#endif
2513        struct pf_mtag *pf_mtag;
2514#endif
2515
2516#ifdef __FreeBSD__
2517        m0 = m_copypacket(m, M_DONTWAIT);
2518        if (m0 == NULL)
2519                return;
2520#else
2521        if ((m0 = m_copy(m, 0, M_COPYALL)) == NULL)
2522                return;
2523#endif
2524
2525#ifdef __FreeBSD__
2526        if ((pf_mtag = pf_get_mtag(m0)) == NULL)
2527                return;
2528        /* XXX: revisit */
2529        m0->m_flags |= M_SKIP_FIREWALL;
2530#else
2531        m0->m_pkthdr.pf.flags |= PF_TAG_GENERATED;
2532#endif
2533
2534        if (r->rtableid >= 0)
2535#ifdef __FreeBSD__
2536        {
2537                M_SETFIB(m0, r->rtableid);
2538                pf_mtag->rtableid = r->rtableid;
2539#else
2540                m0->m_pkthdr.pf.rtableid = r->rtableid;
2541#endif
2542#ifdef __FreeBSD__
2543        }
2544#endif
2545
2546#ifdef ALTQ
2547        if (r->qid) {
2548#ifdef __FreeBSD__
2549                pf_mtag->qid = r->qid;
2550                /* add hints for ecn */
2551                pf_mtag->hdr = mtod(m0, struct ip *);
2552#else
2553                m0->m_pkthdr.pf.qid = r->qid;
2554                /* add hints for ecn */
2555                m0->m_pkthdr.pf.hdr = mtod(m0, struct ip *);
2556#endif
2557        }
2558#endif /* ALTQ */
2559
2560        switch (af) {
2561#ifdef INET
2562        case AF_INET:
2563#ifdef __FreeBSD__
2564                /* icmp_error() expects host byte ordering */
2565                ip = mtod(m0, struct ip *);
2566                NTOHS(ip->ip_len);
2567                NTOHS(ip->ip_off);
2568                PF_UNLOCK();
2569                icmp_error(m0, type, code, 0, 0);
2570                PF_LOCK();
2571#else
2572                icmp_error(m0, type, code, 0, 0);
2573#endif
2574                break;
2575#endif /* INET */
2576#ifdef INET6
2577        case AF_INET6:
2578#ifdef __FreeBSD__
2579                PF_UNLOCK();
2580#endif
2581                icmp6_error(m0, type, code, 0);
2582#ifdef __FreeBSD__
2583                PF_LOCK();
2584#endif
2585                break;
2586#endif /* INET6 */
2587        }
2588}
2589
2590/*
2591 * Return 1 if the addresses a and b match (with mask m), otherwise return 0.
2592 * If n is 0, they match if they are equal. If n is != 0, they match if they
2593 * are different.
2594 */
2595int
2596pf_match_addr(u_int8_t n, struct pf_addr *a, struct pf_addr *m,
2597    struct pf_addr *b, sa_family_t af)
2598{
2599        int     match = 0;
2600
2601        switch (af) {
2602#ifdef INET
2603        case AF_INET:
2604                if ((a->addr32[0] & m->addr32[0]) ==
2605                    (b->addr32[0] & m->addr32[0]))
2606                        match++;
2607                break;
2608#endif /* INET */
2609#ifdef INET6
2610        case AF_INET6:
2611                if (((a->addr32[0] & m->addr32[0]) ==
2612                     (b->addr32[0] & m->addr32[0])) &&
2613                    ((a->addr32[1] & m->addr32[1]) ==
2614                     (b->addr32[1] & m->addr32[1])) &&
2615                    ((a->addr32[2] & m->addr32[2]) ==
2616                     (b->addr32[2] & m->addr32[2])) &&
2617                    ((a->addr32[3] & m->addr32[3]) ==
2618                     (b->addr32[3] & m->addr32[3])))
2619                        match++;
2620                break;
2621#endif /* INET6 */
2622        }
2623        if (match) {
2624                if (n)
2625                        return (0);
2626                else
2627                        return (1);
2628        } else {
2629                if (n)
2630                        return (1);
2631                else
2632                        return (0);
2633        }
2634}
2635
2636/*
2637 * Return 1 if b <= a <= e, otherwise return 0.
2638 */
2639int
2640pf_match_addr_range(struct pf_addr *b, struct pf_addr *e,
2641    struct pf_addr *a, sa_family_t af)
2642{
2643        switch (af) {
2644#ifdef INET
2645        case AF_INET:
2646                if ((a->addr32[0] < b->addr32[0]) ||
2647                    (a->addr32[0] > e->addr32[0]))
2648                        return (0);
2649                break;
2650#endif /* INET */
2651#ifdef INET6
2652        case AF_INET6: {
2653                int     i;
2654
2655                /* check a >= b */
2656                for (i = 0; i < 4; ++i)
2657                        if (a->addr32[i] > b->addr32[i])
2658                                break;
2659                        else if (a->addr32[i] < b->addr32[i])
2660                                return (0);
2661                /* check a <= e */
2662                for (i = 0; i < 4; ++i)
2663                        if (a->addr32[i] < e->addr32[i])
2664                                break;
2665                        else if (a->addr32[i] > e->addr32[i])
2666                                return (0);
2667                break;
2668        }
2669#endif /* INET6 */
2670        }
2671        return (1);
2672}
2673
2674int
2675pf_match(u_int8_t op, u_int32_t a1, u_int32_t a2, u_int32_t p)
2676{
2677        switch (op) {
2678        case PF_OP_IRG:
2679                return ((p > a1) && (p < a2));
2680        case PF_OP_XRG:
2681                return ((p < a1) || (p > a2));
2682        case PF_OP_RRG:
2683                return ((p >= a1) && (p <= a2));
2684        case PF_OP_EQ:
2685                return (p == a1);
2686        case PF_OP_NE:
2687                return (p != a1);
2688        case PF_OP_LT:
2689                return (p < a1);
2690        case PF_OP_LE:
2691                return (p <= a1);
2692        case PF_OP_GT:
2693                return (p > a1);
2694        case PF_OP_GE:
2695                return (p >= a1);
2696        }
2697        return (0); /* never reached */
2698}
2699
2700int
2701pf_match_port(u_int8_t op, u_int16_t a1, u_int16_t a2, u_int16_t p)
2702{
2703        NTOHS(a1);
2704        NTOHS(a2);
2705        NTOHS(p);
2706        return (pf_match(op, a1, a2, p));
2707}
2708
2709int
2710pf_match_uid(u_int8_t op, uid_t a1, uid_t a2, uid_t u)
2711{
2712        if (u == UID_MAX && op != PF_OP_EQ && op != PF_OP_NE)
2713                return (0);
2714        return (pf_match(op, a1, a2, u));
2715}
2716
2717int
2718pf_match_gid(u_int8_t op, gid_t a1, gid_t a2, gid_t g)
2719{
2720        if (g == GID_MAX && op != PF_OP_EQ && op != PF_OP_NE)
2721                return (0);
2722        return (pf_match(op, a1, a2, g));
2723}
2724
2725int
2726#ifdef __FreeBSD__
2727pf_match_tag(struct mbuf *m, struct pf_rule *r, int *tag,
2728    struct pf_mtag *pf_mtag)
2729#else
2730pf_match_tag(struct mbuf *m, struct pf_rule *r, int *tag)
2731#endif
2732{
2733        if (*tag == -1)
2734#ifdef __FreeBSD__
2735                *tag = pf_mtag->tag;
2736#else
2737                *tag = m->m_pkthdr.pf.tag;
2738#endif
2739
2740        return ((!r->match_tag_not && r->match_tag == *tag) ||
2741            (r->match_tag_not && r->match_tag != *tag));
2742}
2743
2744int
2745#ifdef __FreeBSD__
2746pf_tag_packet(struct mbuf *m, int tag, int rtableid,
2747    struct pf_mtag *pf_mtag)
2748#else
2749pf_tag_packet(struct mbuf *m, int tag, int rtableid)
2750#endif
2751{
2752        if (tag <= 0 && rtableid < 0)
2753                return (0);
2754
2755        if (tag > 0)
2756#ifdef __FreeBSD__
2757                pf_mtag->tag = tag;
2758#else
2759                m->m_pkthdr.pf.tag = tag;
2760#endif
2761        if (rtableid >= 0)
2762#ifdef __FreeBSD__
2763        {
2764                M_SETFIB(m, rtableid);
2765        }
2766#else
2767                m->m_pkthdr.pf.rtableid = rtableid;
2768#endif
2769
2770        return (0);
2771}
2772
2773void
2774pf_step_into_anchor(int *depth, struct pf_ruleset **rs, int n,
2775    struct pf_rule **r, struct pf_rule **a, int *match)
2776{
2777        struct pf_anchor_stackframe     *f;
2778
2779        (*r)->anchor->match = 0;
2780        if (match)
2781                *match = 0;
2782#ifdef __FreeBSD__
2783        if (*depth >= sizeof(V_pf_anchor_stack) /
2784            sizeof(V_pf_anchor_stack[0])) {
2785#else
2786        if (*depth >= sizeof(pf_anchor_stack) /
2787            sizeof(pf_anchor_stack[0])) {
2788#endif
2789                printf("pf_step_into_anchor: stack overflow\n");
2790                *r = TAILQ_NEXT(*r, entries);
2791                return;
2792        } else if (*depth == 0 && a != NULL)
2793                *a = *r;
2794#ifdef __FreeBSD__
2795        f = V_pf_anchor_stack + (*depth)++;
2796#else
2797        f = pf_anchor_stack + (*depth)++;
2798#endif
2799        f->rs = *rs;
2800        f->r = *r;
2801        if ((*r)->anchor_wildcard) {
2802                f->parent = &(*r)->anchor->children;
2803                if ((f->child = RB_MIN(pf_anchor_node, f->parent)) ==
2804                    NULL) {
2805                        *r = NULL;
2806                        return;
2807                }
2808                *rs = &f->child->ruleset;
2809        } else {
2810                f->parent = NULL;
2811                f->child = NULL;
2812                *rs = &(*r)->anchor->ruleset;
2813        }
2814        *r = TAILQ_FIRST((*rs)->rules[n].active.ptr);
2815}
2816
2817int
2818pf_step_out_of_anchor(int *depth, struct pf_ruleset **rs, int n,
2819    struct pf_rule **r, struct pf_rule **a, int *match)
2820{
2821        struct pf_anchor_stackframe     *f;
2822        int quick = 0;
2823
2824        do {
2825                if (*depth <= 0)
2826                        break;
2827#ifdef __FreeBSD__
2828                f = V_pf_anchor_stack + *depth - 1;
2829#else
2830                f = pf_anchor_stack + *depth - 1;
2831#endif
2832                if (f->parent != NULL && f->child != NULL) {
2833                        if (f->child->match ||
2834                            (match != NULL && *match)) {
2835                                f->r->anchor->match = 1;
2836                                *match = 0;
2837                        }
2838                        f->child = RB_NEXT(pf_anchor_node, f->parent, f->child);
2839                        if (f->child != NULL) {
2840                                *rs = &f->child->ruleset;
2841                                *r = TAILQ_FIRST((*rs)->rules[n].active.ptr);
2842                                if (*r == NULL)
2843                                        continue;
2844                                else
2845                                        break;
2846                        }
2847                }
2848                (*depth)--;
2849                if (*depth == 0 && a != NULL)
2850                        *a = NULL;
2851                *rs = f->rs;
2852                if (f->r->anchor->match || (match != NULL && *match))
2853                        quick = f->r->quick;
2854                *r = TAILQ_NEXT(f->r, entries);
2855        } while (*r == NULL);
2856
2857        return (quick);
2858}
2859
2860#ifdef INET6
2861void
2862pf_poolmask(struct pf_addr *naddr, struct pf_addr *raddr,
2863    struct pf_addr *rmask, struct pf_addr *saddr, sa_family_t af)
2864{
2865        switch (af) {
2866#ifdef INET
2867        case AF_INET:
2868                naddr->addr32[0] = (raddr->addr32[0] & rmask->addr32[0]) |
2869                ((rmask->addr32[0] ^ 0xffffffff ) & saddr->addr32[0]);
2870                break;
2871#endif /* INET */
2872        case AF_INET6:
2873                naddr->addr32[0] = (raddr->addr32[0] & rmask->addr32[0]) |
2874                ((rmask->addr32[0] ^ 0xffffffff ) & saddr->addr32[0]);
2875                naddr->addr32[1] = (raddr->addr32[1] & rmask->addr32[1]) |
2876                ((rmask->addr32[1] ^ 0xffffffff ) & saddr->addr32[1]);
2877                naddr->addr32[2] = (raddr->addr32[2] & rmask->addr32[2]) |
2878                ((rmask->addr32[2] ^ 0xffffffff ) & saddr->addr32[2]);
2879                naddr->addr32[3] = (raddr->addr32[3] & rmask->addr32[3]) |
2880                ((rmask->addr32[3] ^ 0xffffffff ) & saddr->addr32[3]);
2881                break;
2882        }
2883}
2884
2885void
2886pf_addr_inc(struct pf_addr *addr, sa_family_t af)
2887{
2888        switch (af) {
2889#ifdef INET
2890        case AF_INET:
2891                addr->addr32[0] = htonl(ntohl(addr->addr32[0]) + 1);
2892                break;
2893#endif /* INET */
2894        case AF_INET6:
2895                if (addr->addr32[3] == 0xffffffff) {
2896                        addr->addr32[3] = 0;
2897                        if (addr->addr32[2] == 0xffffffff) {
2898                                addr->addr32[2] = 0;
2899                                if (addr->addr32[1] == 0xffffffff) {
2900                                        addr->addr32[1] = 0;
2901                                        addr->addr32[0] =
2902                                            htonl(ntohl(addr->addr32[0]) + 1);
2903                                } else
2904                                        addr->addr32[1] =
2905                                            htonl(ntohl(addr->addr32[1]) + 1);
2906                        } else
2907                                addr->addr32[2] =
2908                                    htonl(ntohl(addr->addr32[2]) + 1);
2909                } else
2910                        addr->addr32[3] =
2911                            htonl(ntohl(addr->addr32[3]) + 1);
2912                break;
2913        }
2914}
2915#endif /* INET6 */
2916
2917int
2918#ifdef __FreeBSD__
2919pf_socket_lookup(int direction, struct pf_pdesc *pd, struct inpcb *inp_arg)
2920#else
2921pf_socket_lookup(int direction, struct pf_pdesc *pd)
2922#endif
2923{
2924        struct pf_addr          *saddr, *daddr;
2925        u_int16_t                sport, dport;
2926#ifdef __FreeBSD__
2927        struct inpcbinfo        *pi;
2928#else
2929        struct inpcbtable       *tb;
2930#endif
2931        struct inpcb            *inp;
2932
2933        if (pd == NULL)
2934                return (-1);
2935        pd->lookup.uid = UID_MAX;
2936        pd->lookup.gid = GID_MAX;
2937        pd->lookup.pid = NO_PID;
2938
2939#ifdef __FreeBSD__
2940        if (inp_arg != NULL) {
2941                INP_LOCK_ASSERT(inp_arg);
2942#ifndef __rtems__
2943                pd->lookup.uid = inp_arg->inp_cred->cr_uid;
2944                pd->lookup.gid = inp_arg->inp_cred->cr_groups[0];
2945#else /* __rtems__ */
2946                pd->lookup.uid = BSD_DEFAULT_UID;
2947                pd->lookup.gid = BSD_DEFAULT_GID;
2948#endif /* __rtems__ */
2949                return (1);
2950        }
2951#endif
2952
2953        switch (pd->proto) {
2954        case IPPROTO_TCP:
2955                if (pd->hdr.tcp == NULL)
2956                        return (-1);
2957                sport = pd->hdr.tcp->th_sport;
2958                dport = pd->hdr.tcp->th_dport;
2959#ifdef __FreeBSD__
2960                pi = &V_tcbinfo;
2961#else
2962                tb = &tcbtable;
2963#endif
2964                break;
2965        case IPPROTO_UDP:
2966                if (pd->hdr.udp == NULL)
2967                        return (-1);
2968                sport = pd->hdr.udp->uh_sport;
2969                dport = pd->hdr.udp->uh_dport;
2970#ifdef __FreeBSD__
2971                pi = &V_udbinfo;
2972#else
2973                tb = &udbtable;
2974#endif
2975                break;
2976        default:
2977                return (-1);
2978        }
2979        if (direction == PF_IN) {
2980                saddr = pd->src;
2981                daddr = pd->dst;
2982        } else {
2983                u_int16_t       p;
2984
2985                p = sport;
2986                sport = dport;
2987                dport = p;
2988                saddr = pd->dst;
2989                daddr = pd->src;
2990        }
2991        switch (pd->af) {
2992#ifdef INET
2993        case AF_INET:
2994#ifdef __FreeBSD__
2995                /*
2996                 * XXXRW: would be nice if we had an mbuf here so that we
2997                 * could use in_pcblookup_mbuf().
2998                 */
2999                inp = in_pcblookup(pi, saddr->v4, sport, daddr->v4,
3000                        dport, INPLOOKUP_RLOCKPCB, NULL);
3001                if (inp == NULL) {
3002                        inp = in_pcblookup(pi, saddr->v4, sport,
3003                           daddr->v4, dport, INPLOOKUP_WILDCARD |
3004                           INPLOOKUP_RLOCKPCB, NULL);
3005                        if (inp == NULL)
3006                                return (-1);
3007                }
3008#else
3009                inp = in_pcbhashlookup(tb, saddr->v4, sport, daddr->v4, dport);
3010                if (inp == NULL) {
3011                        inp = in_pcblookup_listen(tb, daddr->v4, dport, 0,
3012                            NULL);
3013                        if (inp == NULL)
3014                                return (-1);
3015                }
3016#endif
3017                break;
3018#endif /* INET */
3019#ifdef INET6
3020        case AF_INET6:
3021#ifdef __FreeBSD__
3022                /*
3023                 * XXXRW: would be nice if we had an mbuf here so that we
3024                 * could use in6_pcblookup_mbuf().
3025                 */
3026                inp = in6_pcblookup(pi, &saddr->v6, sport,
3027                        &daddr->v6, dport, INPLOOKUP_RLOCKPCB, NULL);
3028                if (inp == NULL) {
3029                        inp = in6_pcblookup(pi, &saddr->v6, sport,
3030                            &daddr->v6, dport, INPLOOKUP_WILDCARD |
3031                            INPLOOKUP_RLOCKPCB, NULL);
3032                        if (inp == NULL)
3033                                return (-1);
3034                }
3035#else
3036                inp = in6_pcbhashlookup(tb, &saddr->v6, sport, &daddr->v6,
3037                    dport);
3038                if (inp == NULL) {
3039                        inp = in6_pcblookup_listen(tb, &daddr->v6, dport, 0,
3040                            NULL);
3041                        if (inp == NULL)
3042                                return (-1);
3043                }
3044#endif
3045                break;
3046#endif /* INET6 */
3047
3048        default:
3049                return (-1);
3050        }
3051#ifdef __FreeBSD__
3052        INP_RLOCK_ASSERT(inp);
3053#ifndef __rtems__
3054        pd->lookup.uid = inp->inp_cred->cr_uid;
3055        pd->lookup.gid = inp->inp_cred->cr_groups[0];
3056#else /* __rtems__ */
3057        pd->lookup.uid = BSD_DEFAULT_UID;
3058        pd->lookup.gid = BSD_DEFAULT_GID;
3059#endif /* __rtems__ */
3060        INP_RUNLOCK(inp);
3061#else
3062        pd->lookup.uid = inp->inp_socket->so_euid;
3063        pd->lookup.gid = inp->inp_socket->so_egid;
3064        pd->lookup.pid = inp->inp_socket->so_cpid;
3065#endif
3066        return (1);
3067}
3068
3069u_int8_t
3070pf_get_wscale(struct mbuf *m, int off, u_int16_t th_off, sa_family_t af)
3071{
3072        int              hlen;
3073        u_int8_t         hdr[60];
3074        u_int8_t        *opt, optlen;
3075        u_int8_t         wscale = 0;
3076
3077        hlen = th_off << 2;             /* hlen <= sizeof(hdr) */
3078        if (hlen <= sizeof(struct tcphdr))
3079                return (0);
3080        if (!pf_pull_hdr(m, off, hdr, hlen, NULL, NULL, af))
3081                return (0);
3082        opt = hdr + sizeof(struct tcphdr);
3083        hlen -= sizeof(struct tcphdr);
3084        while (hlen >= 3) {
3085                switch (*opt) {
3086                case TCPOPT_EOL:
3087                case TCPOPT_NOP:
3088                        ++opt;
3089                        --hlen;
3090                        break;
3091                case TCPOPT_WINDOW:
3092                        wscale = opt[2];
3093                        if (wscale > TCP_MAX_WINSHIFT)
3094                                wscale = TCP_MAX_WINSHIFT;
3095                        wscale |= PF_WSCALE_FLAG;
3096                        /* FALLTHROUGH */
3097                default:
3098                        optlen = opt[1];
3099                        if (optlen < 2)
3100                                optlen = 2;
3101                        hlen -= optlen;
3102                        opt += optlen;
3103                        break;
3104                }
3105        }
3106        return (wscale);
3107}
3108
3109u_int16_t
3110pf_get_mss(struct mbuf *m, int off, u_int16_t th_off, sa_family_t af)
3111{
3112        int              hlen;
3113        u_int8_t         hdr[60];
3114        u_int8_t        *opt, optlen;
3115#ifdef __FreeBSD__
3116        u_int16_t        mss = V_tcp_mssdflt;
3117#else
3118        u_int16_t        mss = tcp_mssdflt;
3119#endif
3120
3121        hlen = th_off << 2;     /* hlen <= sizeof(hdr) */
3122        if (hlen <= sizeof(struct tcphdr))
3123                return (0);
3124        if (!pf_pull_hdr(m, off, hdr, hlen, NULL, NULL, af))
3125                return (0);
3126        opt = hdr + sizeof(struct tcphdr);
3127        hlen -= sizeof(struct tcphdr);
3128        while (hlen >= TCPOLEN_MAXSEG) {
3129                switch (*opt) {
3130                case TCPOPT_EOL:
3131                case TCPOPT_NOP:
3132                        ++opt;
3133                        --hlen;
3134                        break;
3135                case TCPOPT_MAXSEG:
3136                        bcopy((caddr_t)(opt + 2), (caddr_t)&mss, 2);
3137                        NTOHS(mss);
3138                        /* FALLTHROUGH */
3139                default:
3140                        optlen = opt[1];
3141                        if (optlen < 2)
3142                                optlen = 2;
3143                        hlen -= optlen;
3144                        opt += optlen;
3145                        break;
3146                }
3147        }
3148        return (mss);
3149}
3150
3151u_int16_t
3152pf_calc_mss(struct pf_addr *addr, sa_family_t af, int rtableid, u_int16_t offer)
3153{
3154#ifdef INET
3155        struct sockaddr_in      *dst;
3156        struct route             ro;
3157#endif /* INET */
3158#ifdef INET6
3159        struct sockaddr_in6     *dst6;
3160        struct route_in6         ro6;
3161#endif /* INET6 */
3162        struct rtentry          *rt = NULL;
3163#ifdef __FreeBSD__
3164        int                      hlen = 0;
3165        u_int16_t                mss = V_tcp_mssdflt;
3166#else
3167        int                      hlen;
3168        u_int16_t                mss = tcp_mssdflt;
3169#endif
3170
3171        switch (af) {
3172#ifdef INET
3173        case AF_INET:
3174                hlen = sizeof(struct ip);
3175                bzero(&ro, sizeof(ro));
3176                dst = (struct sockaddr_in *)&ro.ro_dst;
3177                dst->sin_family = AF_INET;
3178                dst->sin_len = sizeof(*dst);
3179                dst->sin_addr = addr->v4;
3180#ifdef __FreeBSD__
3181                in_rtalloc_ign(&ro, 0, rtableid);
3182#else /* ! __FreeBSD__ */
3183                rtalloc_noclone(&ro, NO_CLONING);
3184#endif
3185                rt = ro.ro_rt;
3186                break;
3187#endif /* INET */
3188#ifdef INET6
3189        case AF_INET6:
3190                hlen = sizeof(struct ip6_hdr);
3191                bzero(&ro6, sizeof(ro6));
3192                dst6 = (struct sockaddr_in6 *)&ro6.ro_dst;
3193                dst6->sin6_family = AF_INET6;
3194                dst6->sin6_len = sizeof(*dst6);
3195                dst6->sin6_addr = addr->v6;
3196#ifdef __FreeBSD__
3197                in6_rtalloc_ign(&ro6, 0, rtableid);
3198#else /* ! __FreeBSD__ */
3199                rtalloc_noclone((struct route *)&ro6, NO_CLONING);
3200#endif
3201                rt = ro6.ro_rt;
3202                break;
3203#endif /* INET6 */
3204        }
3205
3206        if (rt && rt->rt_ifp) {
3207                mss = rt->rt_ifp->if_mtu - hlen - sizeof(struct tcphdr);
3208#ifdef __FreeBSD__
3209                mss = max(V_tcp_mssdflt, mss);
3210#else
3211                mss = max(tcp_mssdflt, mss);
3212#endif
3213                RTFREE(rt);
3214        }
3215        mss = min(mss, offer);
3216        mss = max(mss, 64);             /* sanity - at least max opt space */
3217        return (mss);
3218}
3219
3220void
3221pf_set_rt_ifp(struct pf_state *s, struct pf_addr *saddr)
3222{
3223        struct pf_rule *r = s->rule.ptr;
3224        struct pf_src_node *sn = NULL;
3225
3226        s->rt_kif = NULL;
3227        if (!r->rt || r->rt == PF_FASTROUTE)
3228                return;
3229        switch (s->key[PF_SK_WIRE]->af) {
3230#ifdef INET
3231        case AF_INET:
3232                pf_map_addr(AF_INET, r, saddr, &s->rt_addr, NULL, &sn);
3233                s->rt_kif = r->rpool.cur->kif;
3234                break;
3235#endif /* INET */
3236#ifdef INET6
3237        case AF_INET6:
3238                pf_map_addr(AF_INET6, r, saddr, &s->rt_addr, NULL, &sn);
3239                s->rt_kif = r->rpool.cur->kif;
3240                break;
3241#endif /* INET6 */
3242        }
3243}
3244
3245u_int32_t
3246pf_tcp_iss(struct pf_pdesc *pd)
3247{
3248        MD5_CTX ctx;
3249        u_int32_t digest[4];
3250
3251#ifdef __FreeBSD__
3252        if (V_pf_tcp_secret_init == 0) {
3253                read_random(&V_pf_tcp_secret, sizeof(V_pf_tcp_secret));
3254                MD5Init(&V_pf_tcp_secret_ctx);
3255                MD5Update(&V_pf_tcp_secret_ctx, V_pf_tcp_secret,
3256                    sizeof(V_pf_tcp_secret));
3257                V_pf_tcp_secret_init = 1;
3258        }
3259
3260        ctx = V_pf_tcp_secret_ctx;
3261#else
3262        if (pf_tcp_secret_init == 0) {
3263                arc4random_buf(pf_tcp_secret, sizeof(pf_tcp_secret));
3264                MD5Init(&pf_tcp_secret_ctx);
3265                MD5Update(&pf_tcp_secret_ctx, pf_tcp_secret,
3266                    sizeof(pf_tcp_secret));
3267                pf_tcp_secret_init = 1;
3268        }
3269
3270        ctx = pf_tcp_secret_ctx;
3271#endif
3272
3273        MD5Update(&ctx, (char *)&pd->hdr.tcp->th_sport, sizeof(u_short));
3274        MD5Update(&ctx, (char *)&pd->hdr.tcp->th_dport, sizeof(u_short));
3275        if (pd->af == AF_INET6) {
3276                MD5Update(&ctx, (char *)&pd->src->v6, sizeof(struct in6_addr));
3277                MD5Update(&ctx, (char *)&pd->dst->v6, sizeof(struct in6_addr));
3278        } else {
3279                MD5Update(&ctx, (char *)&pd->src->v4, sizeof(struct in_addr));
3280                MD5Update(&ctx, (char *)&pd->dst->v4, sizeof(struct in_addr));
3281        }
3282        MD5Final((u_char *)digest, &ctx);
3283#ifdef __FreeBSD__
3284        V_pf_tcp_iss_off += 4096;
3285#define ISN_RANDOM_INCREMENT (4096 - 1)
3286        return (digest[0] + (arc4random() & ISN_RANDOM_INCREMENT) +
3287            V_pf_tcp_iss_off);
3288#undef  ISN_RANDOM_INCREMENT
3289#else
3290        pf_tcp_iss_off += 4096;
3291        return (digest[0] + tcp_iss + pf_tcp_iss_off);
3292#endif
3293}
3294
3295int
3296pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction,
3297    struct pfi_kif *kif, struct mbuf *m, int off, void *h,
3298    struct pf_pdesc *pd, struct pf_rule **am, struct pf_ruleset **rsm,
3299#ifdef __FreeBSD__
3300    struct ifqueue *ifq, struct inpcb *inp)
3301#else
3302    struct ifqueue *ifq)
3303#endif
3304{
3305        struct pf_rule          *nr = NULL;
3306        struct pf_addr          *saddr = pd->src, *daddr = pd->dst;
3307        sa_family_t              af = pd->af;
3308        struct pf_rule          *r, *a = NULL;
3309        struct pf_ruleset       *ruleset = NULL;
3310        struct pf_src_node      *nsn = NULL;
3311        struct tcphdr           *th = pd->hdr.tcp;
3312        struct pf_state_key     *skw = NULL, *sks = NULL;
3313        struct pf_state_key     *sk = NULL, *nk = NULL;
3314        u_short                  reason;
3315        int                      rewrite = 0, hdrlen = 0;
3316        int                      tag = -1, rtableid = -1;
3317        int                      asd = 0;
3318        int                      match = 0;
3319        int                      state_icmp = 0;
3320#ifdef __FreeBSD__
3321        u_int16_t                sport = 0, dport = 0;
3322        u_int16_t                bproto_sum = 0, bip_sum = 0;
3323#else
3324        u_int16_t                sport, dport;
3325        u_int16_t                bproto_sum = 0, bip_sum;
3326#endif
3327        u_int8_t                 icmptype = 0, icmpcode = 0;
3328
3329
3330        if (direction == PF_IN && pf_check_congestion(ifq)) {
3331                REASON_SET(&reason, PFRES_CONGEST);
3332                return (PF_DROP);
3333        }
3334
3335#ifdef __FreeBSD__
3336        if (inp != NULL)
3337                pd->lookup.done = pf_socket_lookup(direction, pd, inp);
3338        else if (V_debug_pfugidhack) {
3339                PF_UNLOCK();
3340                DPFPRINTF(PF_DEBUG_MISC, ("pf: unlocked lookup\n"));
3341                    pd->lookup.done = pf_socket_lookup(direction, pd, inp);
3342                PF_LOCK();
3343        }
3344#endif
3345
3346        switch (pd->proto) {
3347        case IPPROTO_TCP:
3348                sport = th->th_sport;
3349                dport = th->th_dport;
3350                hdrlen = sizeof(*th);
3351                break;
3352        case IPPROTO_UDP:
3353                sport = pd->hdr.udp->uh_sport;
3354                dport = pd->hdr.udp->uh_dport;
3355                hdrlen = sizeof(*pd->hdr.udp);
3356                break;
3357#ifdef INET
3358        case IPPROTO_ICMP:
3359                if (pd->af != AF_INET)
3360                        break;
3361                sport = dport = pd->hdr.icmp->icmp_id;
3362                hdrlen = sizeof(*pd->hdr.icmp);
3363                icmptype = pd->hdr.icmp->icmp_type;
3364                icmpcode = pd->hdr.icmp->icmp_code;
3365
3366                if (icmptype == ICMP_UNREACH ||
3367                    icmptype == ICMP_SOURCEQUENCH ||
3368                    icmptype == ICMP_REDIRECT ||
3369                    icmptype == ICMP_TIMXCEED ||
3370                    icmptype == ICMP_PARAMPROB)
3371                        state_icmp++;
3372                break;
3373#endif /* INET */
3374#ifdef INET6
3375        case IPPROTO_ICMPV6:
3376                if (af != AF_INET6)
3377                        break;
3378                sport = dport = pd->hdr.icmp6->icmp6_id;
3379                hdrlen = sizeof(*pd->hdr.icmp6);
3380                icmptype = pd->hdr.icmp6->icmp6_type;
3381                icmpcode = pd->hdr.icmp6->icmp6_code;
3382
3383                if (icmptype == ICMP6_DST_UNREACH ||
3384                    icmptype == ICMP6_PACKET_TOO_BIG ||
3385                    icmptype == ICMP6_TIME_EXCEEDED ||
3386                    icmptype == ICMP6_PARAM_PROB)
3387                        state_icmp++;
3388                break;
3389#endif /* INET6 */
3390        default:
3391                sport = dport = hdrlen = 0;
3392                break;
3393        }
3394
3395        r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_FILTER].active.ptr);
3396
3397        /* check packet for BINAT/NAT/RDR */
3398        if ((nr = pf_get_translation(pd, m, off, direction, kif, &nsn,
3399            &skw, &sks, &sk, &nk, saddr, daddr, sport, dport)) != NULL) {
3400                if (nk == NULL || sk == NULL) {
3401                        REASON_SET(&reason, PFRES_MEMORY);
3402                        goto cleanup;
3403                }
3404
3405                if (pd->ip_sum)
3406                        bip_sum = *pd->ip_sum;
3407
3408                switch (pd->proto) {
3409                case IPPROTO_TCP:
3410                        bproto_sum = th->th_sum;
3411                        pd->proto_sum = &th->th_sum;
3412
3413                        if (PF_ANEQ(saddr, &nk->addr[pd->sidx], af) ||
3414                            nk->port[pd->sidx] != sport) {
3415                                pf_change_ap(saddr, &th->th_sport, pd->ip_sum,
3416                                    &th->th_sum, &nk->addr[pd->sidx],
3417                                    nk->port[pd->sidx], 0, af);
3418                                pd->sport = &th->th_sport;
3419                                sport = th->th_sport;
3420                        }
3421
3422                        if (PF_ANEQ(daddr, &nk->addr[pd->didx], af) ||
3423                            nk->port[pd->didx] != dport) {
3424                                pf_change_ap(daddr, &th->th_dport, pd->ip_sum,
3425                                    &th->th_sum, &nk->addr[pd->didx],
3426                                    nk->port[pd->didx], 0, af);
3427                                dport = th->th_dport;
3428                                pd->dport = &th->th_dport;
3429                        }
3430                        rewrite++;
3431                        break;
3432                case IPPROTO_UDP:
3433                        bproto_sum = pd->hdr.udp->uh_sum;
3434                        pd->proto_sum = &pd->hdr.udp->uh_sum;
3435
3436                        if (PF_ANEQ(saddr, &nk->addr[pd->sidx], af) ||
3437                            nk->port[pd->sidx] != sport) {
3438                                pf_change_ap(saddr, &pd->hdr.udp->uh_sport,
3439                                    pd->ip_sum, &pd->hdr.udp->uh_sum,
3440                                    &nk->addr[pd->sidx],
3441                                    nk->port[pd->sidx], 1, af);
3442                                sport = pd->hdr.udp->uh_sport;
3443                                pd->sport = &pd->hdr.udp->uh_sport;
3444                        }
3445
3446                        if (PF_ANEQ(daddr, &nk->addr[pd->didx], af) ||
3447                            nk->port[pd->didx] != dport) {
3448                                pf_change_ap(daddr, &pd->hdr.udp->uh_dport,
3449                                    pd->ip_sum, &pd->hdr.udp->uh_sum,
3450                                    &nk->addr[pd->didx],
3451                                    nk->port[pd->didx], 1, af);
3452                                dport = pd->hdr.udp->uh_dport;
3453                                pd->dport = &pd->hdr.udp->uh_dport;
3454                        }
3455                        rewrite++;
3456                        break;
3457#ifdef INET
3458                case IPPROTO_ICMP:
3459                        nk->port[0] = nk->port[1];
3460                        if (PF_ANEQ(saddr, &nk->addr[pd->sidx], AF_INET))
3461                                pf_change_a(&saddr->v4.s_addr, pd->ip_sum,
3462                                    nk->addr[pd->sidx].v4.s_addr, 0);
3463
3464                        if (PF_ANEQ(daddr, &nk->addr[pd->didx], AF_INET))
3465                                pf_change_a(&daddr->v4.s_addr, pd->ip_sum,
3466                                    nk->addr[pd->didx].v4.s_addr, 0);
3467
3468                        if (nk->port[1] != pd->hdr.icmp->icmp_id) {
3469                                pd->hdr.icmp->icmp_cksum = pf_cksum_fixup(
3470                                    pd->hdr.icmp->icmp_cksum, sport,
3471                                    nk->port[1], 0);
3472                                pd->hdr.icmp->icmp_id = nk->port[1];
3473                                pd->sport = &pd->hdr.icmp->icmp_id;
3474                        }
3475                        m_copyback(m, off, ICMP_MINLEN, (caddr_t)pd->hdr.icmp);
3476                        break;
3477#endif /* INET */
3478#ifdef INET6
3479                case IPPROTO_ICMPV6:
3480                        nk->port[0] = nk->port[1];
3481                        if (PF_ANEQ(saddr, &nk->addr[pd->sidx], AF_INET6))
3482                                pf_change_a6(saddr, &pd->hdr.icmp6->icmp6_cksum,
3483                                    &nk->addr[pd->sidx], 0);
3484
3485                        if (PF_ANEQ(daddr, &nk->addr[pd->didx], AF_INET6))
3486                                pf_change_a6(daddr, &pd->hdr.icmp6->icmp6_cksum,
3487                                    &nk->addr[pd->didx], 0);
3488                        rewrite++;
3489                        break;
3490#endif /* INET */
3491                default:
3492                        switch (af) {
3493#ifdef INET
3494                        case AF_INET:
3495                                if (PF_ANEQ(saddr,
3496                                    &nk->addr[pd->sidx], AF_INET))
3497                                        pf_change_a(&saddr->v4.s_addr,
3498                                            pd->ip_sum,
3499                                            nk->addr[pd->sidx].v4.s_addr, 0);
3500
3501                                if (PF_ANEQ(daddr,
3502                                    &nk->addr[pd->didx], AF_INET))
3503                                        pf_change_a(&daddr->v4.s_addr,
3504                                            pd->ip_sum,
3505                                            nk->addr[pd->didx].v4.s_addr, 0);
3506                                break;
3507#endif /* INET */
3508#ifdef INET6
3509                        case AF_INET6:
3510                                if (PF_ANEQ(saddr,
3511                                    &nk->addr[pd->sidx], AF_INET6))
3512                                        PF_ACPY(saddr, &nk->addr[pd->sidx], af);
3513
3514                                if (PF_ANEQ(daddr,
3515                                    &nk->addr[pd->didx], AF_INET6))
3516                                        PF_ACPY(saddr, &nk->addr[pd->didx], af);
3517                                break;
3518#endif /* INET */
3519                        }
3520                        break;
3521                }
3522                if (nr->natpass)
3523                        r = NULL;
3524                pd->nat_rule = nr;
3525        }
3526
3527        while (r != NULL) {
3528                r->evaluations++;
3529                if (pfi_kif_match(r->kif, kif) == r->ifnot)
3530                        r = r->skip[PF_SKIP_IFP].ptr;
3531                else if (r->direction && r->direction != direction)
3532                        r = r->skip[PF_SKIP_DIR].ptr;
3533                else if (r->af && r->af != af)
3534                        r = r->skip[PF_SKIP_AF].ptr;
3535                else if (r->proto && r->proto != pd->proto)
3536                        r = r->skip[PF_SKIP_PROTO].ptr;
3537                else if (PF_MISMATCHAW(&r->src.addr, saddr, af,
3538                    r->src.neg, kif, M_GETFIB(m)))
3539                        r = r->skip[PF_SKIP_SRC_ADDR].ptr;
3540                /* tcp/udp only. port_op always 0 in other cases */
3541                else if (r->src.port_op && !pf_match_port(r->src.port_op,
3542                    r->src.port[0], r->src.port[1], sport))
3543                        r = r->skip[PF_SKIP_SRC_PORT].ptr;
3544                else if (PF_MISMATCHAW(&r->dst.addr, daddr, af,
3545                    r->dst.neg, NULL, M_GETFIB(m)))
3546                        r = r->skip[PF_SKIP_DST_ADDR].ptr;
3547                /* tcp/udp only. port_op always 0 in other cases */
3548                else if (r->dst.port_op && !pf_match_port(r->dst.port_op,
3549                    r->dst.port[0], r->dst.port[1], dport))
3550                        r = r->skip[PF_SKIP_DST_PORT].ptr;
3551                /* icmp only. type always 0 in other cases */
3552                else if (r->type && r->type != icmptype + 1)
3553                        r = TAILQ_NEXT(r, entries);
3554                /* icmp only. type always 0 in other cases */
3555                else if (r->code && r->code != icmpcode + 1)
3556                        r = TAILQ_NEXT(r, entries);
3557                else if (r->tos && !(r->tos == pd->tos))
3558                        r = TAILQ_NEXT(r, entries);
3559                else if (r->rule_flag & PFRULE_FRAGMENT)
3560                        r = TAILQ_NEXT(r, entries);
3561                else if (pd->proto == IPPROTO_TCP &&
3562                    (r->flagset & th->th_flags) != r->flags)
3563                        r = TAILQ_NEXT(r, entries);
3564                /* tcp/udp only. uid.op always 0 in other cases */
3565                else if (r->uid.op && (pd->lookup.done || (pd->lookup.done =
3566#ifdef __FreeBSD__
3567                    pf_socket_lookup(direction, pd, inp), 1)) &&
3568#else
3569                    pf_socket_lookup(direction, pd), 1)) &&
3570#endif
3571                    !pf_match_uid(r->uid.op, r->uid.uid[0], r->uid.uid[1],
3572                    pd->lookup.uid))
3573                        r = TAILQ_NEXT(r, entries);
3574                /* tcp/udp only. gid.op always 0 in other cases */
3575                else if (r->gid.op && (pd->lookup.done || (pd->lookup.done =
3576#ifdef __FreeBSD__
3577                    pf_socket_lookup(direction, pd, inp), 1)) &&
3578#else
3579                    pf_socket_lookup(direction, pd), 1)) &&
3580#endif
3581                    !pf_match_gid(r->gid.op, r->gid.gid[0], r->gid.gid[1],
3582                    pd->lookup.gid))
3583                        r = TAILQ_NEXT(r, entries);
3584                else if (r->prob &&
3585#ifdef __FreeBSD__
3586                    r->prob <= arc4random())
3587#else
3588                    r->prob <= arc4random_uniform(UINT_MAX - 1) + 1)
3589#endif
3590                        r = TAILQ_NEXT(r, entries);
3591#ifdef __FreeBSD__
3592                else if (r->match_tag && !pf_match_tag(m, r, &tag, pd->pf_mtag))
3593#else
3594                else if (r->match_tag && !pf_match_tag(m, r, &tag))
3595#endif
3596                        r = TAILQ_NEXT(r, entries);
3597                else if (r->os_fingerprint != PF_OSFP_ANY &&
3598                    (pd->proto != IPPROTO_TCP || !pf_osfp_match(
3599                    pf_osfp_fingerprint(pd, m, off, th),
3600                    r->os_fingerprint)))
3601                        r = TAILQ_NEXT(r, entries);
3602                else {
3603                        if (r->tag)
3604                                tag = r->tag;
3605                        if (r->rtableid >= 0)
3606                                rtableid = r->rtableid;
3607                        if (r->anchor == NULL) {
3608                                match = 1;
3609                                *rm = r;
3610                                *am = a;
3611                                *rsm = ruleset;
3612                                if ((*rm)->quick)
3613                                        break;
3614                                r = TAILQ_NEXT(r, entries);
3615                        } else
3616                                pf_step_into_anchor(&asd, &ruleset,
3617                                    PF_RULESET_FILTER, &r, &a, &match);
3618                }
3619                if (r == NULL && pf_step_out_of_anchor(&asd, &ruleset,
3620                    PF_RULESET_FILTER, &r, &a, &match))
3621                        break;
3622        }
3623        r = *rm;
3624        a = *am;
3625        ruleset = *rsm;
3626
3627        REASON_SET(&reason, PFRES_MATCH);
3628
3629        if (r->log || (nr != NULL && nr->log)) {
3630                if (rewrite)
3631                        m_copyback(m, off, hdrlen, pd->hdr.any);
3632                PFLOG_PACKET(kif, h, m, af, direction, reason, r->log ? r : nr,
3633                    a, ruleset, pd);
3634        }
3635
3636        if ((r->action == PF_DROP) &&
3637            ((r->rule_flag & PFRULE_RETURNRST) ||
3638            (r->rule_flag & PFRULE_RETURNICMP) ||
3639            (r->rule_flag & PFRULE_RETURN))) {
3640                /* undo NAT changes, if they have taken place */
3641                if (nr != NULL) {
3642                        PF_ACPY(saddr, &sk->addr[pd->sidx], af);
3643                        PF_ACPY(daddr, &sk->addr[pd->didx], af);
3644                        if (pd->sport)
3645                                *pd->sport = sk->port[pd->sidx];
3646                        if (pd->dport)
3647                                *pd->dport = sk->port[pd->didx];
3648                        if (pd->proto_sum)
3649                                *pd->proto_sum = bproto_sum;
3650                        if (pd->ip_sum)
3651                                *pd->ip_sum = bip_sum;
3652                        m_copyback(m, off, hdrlen, pd->hdr.any);
3653                }
3654                if (pd->proto == IPPROTO_TCP &&
3655                    ((r->rule_flag & PFRULE_RETURNRST) ||
3656                    (r->rule_flag & PFRULE_RETURN)) &&
3657                    !(th->th_flags & TH_RST)) {
3658                        u_int32_t        ack = ntohl(th->th_seq) + pd->p_len;
3659                        int              len = 0;
3660#ifdef INET
3661                        struct ip       *h4;
3662#endif
3663#ifdef INET6
3664                        struct ip6_hdr  *h6;
3665#endif
3666
3667                        switch (af) {
3668#ifdef INET
3669                        case AF_INET:
3670                                h4 = mtod(m, struct ip *);
3671                                len = ntohs(h4->ip_len) - off;
3672                                break;
3673#endif
3674#ifdef INET6
3675                        case AF_INET6:
3676                                h6 = mtod(m, struct ip6_hdr *);
3677                                len = ntohs(h6->ip6_plen) - (off - sizeof(*h6));
3678                                break;
3679#endif
3680                        }
3681
3682                        if (pf_check_proto_cksum(m, off, len, IPPROTO_TCP, af))
3683                                REASON_SET(&reason, PFRES_PROTCKSUM);
3684                        else {
3685                                if (th->th_flags & TH_SYN)
3686                                        ack++;
3687                                if (th->th_flags & TH_FIN)
3688                                        ack++;
3689#ifdef __FreeBSD__
3690                                pf_send_tcp(m, r, af, pd->dst,
3691#else
3692                                pf_send_tcp(r, af, pd->dst,
3693#endif
3694                                    pd->src, th->th_dport, th->th_sport,
3695                                    ntohl(th->th_ack), ack, TH_RST|TH_ACK, 0, 0,
3696                                    r->return_ttl, 1, 0, pd->eh, kif->pfik_ifp);
3697                        }
3698                } else if (pd->proto != IPPROTO_ICMP && af == AF_INET &&
3699                    r->return_icmp)
3700                        pf_send_icmp(m, r->return_icmp >> 8,
3701                            r->return_icmp & 255, af, r);
3702                else if (pd->proto != IPPROTO_ICMPV6 && af == AF_INET6 &&
3703                    r->return_icmp6)
3704                        pf_send_icmp(m, r->return_icmp6 >> 8,
3705                            r->return_icmp6 & 255, af, r);
3706        }
3707
3708        if (r->action == PF_DROP)
3709                goto cleanup;
3710
3711#ifdef __FreeBSD__
3712        if (pf_tag_packet(m, tag, rtableid, pd->pf_mtag)) {
3713#else
3714        if (pf_tag_packet(m, tag, rtableid)) {
3715#endif
3716                REASON_SET(&reason, PFRES_MEMORY);
3717                goto cleanup;
3718        }
3719
3720        if (!state_icmp && (r->keep_state || nr != NULL ||
3721            (pd->flags & PFDESC_TCP_NORM))) {
3722                int action;
3723                action = pf_create_state(r, nr, a, pd, nsn, skw, sks, nk, sk, m,
3724                    off, sport, dport, &rewrite, kif, sm, tag, bproto_sum,
3725                    bip_sum, hdrlen);
3726                if (action != PF_PASS)
3727                        return (action);
3728        } else {
3729#ifdef __FreeBSD__
3730                if (sk != NULL)
3731                        pool_put(&V_pf_state_key_pl, sk);
3732                if (nk != NULL)
3733                        pool_put(&V_pf_state_key_pl, nk);
3734#else
3735                if (sk != NULL)
3736                        pool_put(&pf_state_key_pl, sk);
3737                if (nk != NULL)
3738                        pool_put(&pf_state_key_pl, nk);
3739#endif
3740        }
3741
3742        /* copy back packet headers if we performed NAT operations */
3743        if (rewrite)
3744                m_copyback(m, off, hdrlen, pd->hdr.any);
3745
3746#if NPFSYNC > 0
3747        if (*sm != NULL && !ISSET((*sm)->state_flags, PFSTATE_NOSYNC) &&
3748#ifdef __FreeBSD__
3749            direction == PF_OUT && pfsync_up_ptr != NULL && pfsync_up_ptr()) {
3750#else
3751            direction == PF_OUT && pfsync_up()) {
3752#endif
3753                /*
3754                 * We want the state created, but we dont
3755                 * want to send this in case a partner
3756                 * firewall has to know about it to allow
3757                 * replies through it.
3758                 */
3759#ifdef __FreeBSD__
3760                if (pfsync_defer_ptr != NULL &&
3761                        pfsync_defer_ptr(*sm, m))
3762#else
3763                if (pfsync_defer(*sm, m))
3764#endif
3765                        return (PF_DEFER);
3766        }
3767#endif
3768
3769        return (PF_PASS);
3770
3771cleanup:
3772#ifdef __FreeBSD__
3773        if (sk != NULL)
3774                pool_put(&V_pf_state_key_pl, sk);
3775        if (nk != NULL)
3776                pool_put(&V_pf_state_key_pl, nk);
3777#else
3778        if (sk != NULL)
3779                pool_put(&pf_state_key_pl, sk);
3780        if (nk != NULL)
3781                pool_put(&pf_state_key_pl, nk);
3782#endif
3783        return (PF_DROP);
3784}
3785
3786static __inline int
3787pf_create_state(struct pf_rule *r, struct pf_rule *nr, struct pf_rule *a,
3788    struct pf_pdesc *pd, struct pf_src_node *nsn, struct pf_state_key *skw,
3789    struct pf_state_key *sks, struct pf_state_key *nk, struct pf_state_key *sk,
3790    struct mbuf *m, int off, u_int16_t sport, u_int16_t dport, int *rewrite,
3791    struct pfi_kif *kif, struct pf_state **sm, int tag, u_int16_t bproto_sum,
3792    u_int16_t bip_sum, int hdrlen)
3793{
3794        struct pf_state         *s = NULL;
3795        struct pf_src_node      *sn = NULL;
3796        struct tcphdr           *th = pd->hdr.tcp;
3797#ifdef __FreeBSD__
3798        u_int16_t                mss = V_tcp_mssdflt;
3799#else
3800        u_int16_t                mss = tcp_mssdflt;
3801#endif
3802        u_short                  reason;
3803
3804        /* check maximums */
3805        if (r->max_states && (r->states_cur >= r->max_states)) {
3806#ifdef __FreeBSD__
3807                V_pf_status.lcounters[LCNT_STATES]++;
3808#else
3809                pf_status.lcounters[LCNT_STATES]++;
3810#endif
3811                REASON_SET(&reason, PFRES_MAXSTATES);
3812                return (PF_DROP);
3813        }
3814        /* src node for filter rule */
3815        if ((r->rule_flag & PFRULE_SRCTRACK ||
3816            r->rpool.opts & PF_POOL_STICKYADDR) &&
3817            pf_insert_src_node(&sn, r, pd->src, pd->af) != 0) {
3818                REASON_SET(&reason, PFRES_SRCLIMIT);
3819                goto csfailed;
3820        }
3821        /* src node for translation rule */
3822        if (nr != NULL && (nr->rpool.opts & PF_POOL_STICKYADDR) &&
3823            pf_insert_src_node(&nsn, nr, &sk->addr[pd->sidx], pd->af)) {
3824                REASON_SET(&reason, PFRES_SRCLIMIT);
3825                goto csfailed;
3826        }
3827#ifdef __FreeBSD__
3828        s = pool_get(&V_pf_state_pl, PR_NOWAIT | PR_ZERO);
3829#else
3830        s = pool_get(&pf_state_pl, PR_NOWAIT | PR_ZERO);
3831#endif
3832        if (s == NULL) {
3833                REASON_SET(&reason, PFRES_MEMORY);
3834                goto csfailed;
3835        }
3836        s->rule.ptr = r;
3837        s->nat_rule.ptr = nr;
3838        s->anchor.ptr = a;
3839        STATE_INC_COUNTERS(s);
3840        if (r->allow_opts)
3841                s->state_flags |= PFSTATE_ALLOWOPTS;
3842        if (r->rule_flag & PFRULE_STATESLOPPY)
3843                s->state_flags |= PFSTATE_SLOPPY;
3844        if (r->rule_flag & PFRULE_PFLOW)
3845                s->state_flags |= PFSTATE_PFLOW;
3846        s->log = r->log & PF_LOG_ALL;
3847        s->sync_state = PFSYNC_S_NONE;
3848        if (nr != NULL)
3849                s->log |= nr->log & PF_LOG_ALL;
3850        switch (pd->proto) {
3851        case IPPROTO_TCP:
3852                s->src.seqlo = ntohl(th->th_seq);
3853                s->src.seqhi = s->src.seqlo + pd->p_len + 1;
3854                if ((th->th_flags & (TH_SYN|TH_ACK)) == TH_SYN &&
3855                    r->keep_state == PF_STATE_MODULATE) {
3856                        /* Generate sequence number modulator */
3857                        if ((s->src.seqdiff = pf_tcp_iss(pd) - s->src.seqlo) ==
3858                            0)
3859                                s->src.seqdiff = 1;
3860                        pf_change_a(&th->th_seq, &th->th_sum,
3861                            htonl(s->src.seqlo + s->src.seqdiff), 0);
3862                        *rewrite = 1;
3863                } else
3864                        s->src.seqdiff = 0;
3865                if (th->th_flags & TH_SYN) {
3866                        s->src.seqhi++;
3867                        s->src.wscale = pf_get_wscale(m, off,
3868                            th->th_off, pd->af);
3869                }
3870                s->src.max_win = MAX(ntohs(th->th_win), 1);
3871                if (s->src.wscale & PF_WSCALE_MASK) {
3872                        /* Remove scale factor from initial window */
3873                        int win = s->src.max_win;
3874                        win += 1 << (s->src.wscale & PF_WSCALE_MASK);
3875                        s->src.max_win = (win - 1) >>
3876                            (s->src.wscale & PF_WSCALE_MASK);
3877                }
3878                if (th->th_flags & TH_FIN)
3879                        s->src.seqhi++;
3880                s->dst.seqhi = 1;
3881                s->dst.max_win = 1;
3882                s->src.state = TCPS_SYN_SENT;
3883                s->dst.state = TCPS_CLOSED;
3884                s->timeout = PFTM_TCP_FIRST_PACKET;
3885                break;
3886        case IPPROTO_UDP:
3887                s->src.state = PFUDPS_SINGLE;
3888                s->dst.state = PFUDPS_NO_TRAFFIC;
3889                s->timeout = PFTM_UDP_FIRST_PACKET;
3890                break;
3891        case IPPROTO_ICMP:
3892#ifdef INET6
3893        case IPPROTO_ICMPV6:
3894#endif
3895                s->timeout = PFTM_ICMP_FIRST_PACKET;
3896                break;
3897        default:
3898                s->src.state = PFOTHERS_SINGLE;
3899                s->dst.state = PFOTHERS_NO_TRAFFIC;
3900                s->timeout = PFTM_OTHER_FIRST_PACKET;
3901        }
3902
3903        s->creation = time_second;
3904        s->expire = time_second;
3905
3906        if (sn != NULL) {
3907                s->src_node = sn;
3908                s->src_node->states++;
3909        }
3910        if (nsn != NULL) {
3911                /* XXX We only modify one side for now. */
3912                PF_ACPY(&nsn->raddr, &nk->addr[1], pd->af);
3913                s->nat_src_node = nsn;
3914                s->nat_src_node->states++;
3915        }
3916        if (pd->proto == IPPROTO_TCP) {
3917                if ((pd->flags & PFDESC_TCP_NORM) && pf_normalize_tcp_init(m,
3918                    off, pd, th, &s->src, &s->dst)) {
3919                        REASON_SET(&reason, PFRES_MEMORY);
3920                        pf_src_tree_remove_state(s);
3921                        STATE_DEC_COUNTERS(s);
3922#ifdef __FreeBSD__
3923                        pool_put(&V_pf_state_pl, s);
3924#else
3925                        pool_put(&pf_state_pl, s);
3926#endif
3927                        return (PF_DROP);
3928                }
3929                if ((pd->flags & PFDESC_TCP_NORM) && s->src.scrub &&
3930                    pf_normalize_tcp_stateful(m, off, pd, &reason, th, s,
3931                    &s->src, &s->dst, rewrite)) {
3932                        /* This really shouldn't happen!!! */
3933                        DPFPRINTF(PF_DEBUG_URGENT,
3934                            ("pf_normalize_tcp_stateful failed on first pkt"));
3935                        pf_normalize_tcp_cleanup(s);
3936                        pf_src_tree_remove_state(s);
3937                        STATE_DEC_COUNTERS(s);
3938#ifdef __FreeBSD__
3939                        pool_put(&V_pf_state_pl, s);
3940#else
3941                        pool_put(&pf_state_pl, s);
3942#endif
3943                        return (PF_DROP);
3944                }
3945        }
3946        s->direction = pd->dir;
3947
3948        if (sk == NULL && pf_state_key_setup(pd, nr, &skw, &sks, &sk, &nk,
3949            pd->src, pd->dst, sport, dport))
3950                goto csfailed;
3951
3952        if (pf_state_insert(BOUND_IFACE(r, kif), skw, sks, s)) {
3953                if (pd->proto == IPPROTO_TCP)
3954                        pf_normalize_tcp_cleanup(s);
3955                REASON_SET(&reason, PFRES_STATEINS);
3956                pf_src_tree_remove_state(s);
3957                STATE_DEC_COUNTERS(s);
3958#ifdef __FreeBSD__
3959                pool_put(&V_pf_state_pl, s);
3960#else
3961                pool_put(&pf_state_pl, s);
3962#endif
3963                return (PF_DROP);
3964        } else
3965                *sm = s;
3966
3967        pf_set_rt_ifp(s, pd->src);      /* needs s->state_key set */
3968        if (tag > 0) {
3969                pf_tag_ref(tag);
3970                s->tag = tag;
3971        }
3972        if (pd->proto == IPPROTO_TCP && (th->th_flags & (TH_SYN|TH_ACK)) ==
3973            TH_SYN && r->keep_state == PF_STATE_SYNPROXY) {
3974                s->src.state = PF_TCPS_PROXY_SRC;
3975                /* undo NAT changes, if they have taken place */
3976                if (nr != NULL) {
3977                        struct pf_state_key *skt = s->key[PF_SK_WIRE];
3978                        if (pd->dir == PF_OUT)
3979                                skt = s->key[PF_SK_STACK];
3980                        PF_ACPY(pd->src, &skt->addr[pd->sidx], pd->af);
3981                        PF_ACPY(pd->dst, &skt->addr[pd->didx], pd->af);
3982                        if (pd->sport)
3983                                *pd->sport = skt->port[pd->sidx];
3984                        if (pd->dport)
3985                                *pd->dport = skt->port[pd->didx];
3986                        if (pd->proto_sum)
3987                                *pd->proto_sum = bproto_sum;
3988                        if (pd->ip_sum)
3989                                *pd->ip_sum = bip_sum;
3990                        m_copyback(m, off, hdrlen, pd->hdr.any);
3991                }
3992                s->src.seqhi = htonl(arc4random());
3993                /* Find mss option */
3994                int rtid = M_GETFIB(m);
3995                mss = pf_get_mss(m, off, th->th_off, pd->af);
3996                mss = pf_calc_mss(pd->src, pd->af, rtid, mss);
3997                mss = pf_calc_mss(pd->dst, pd->af, rtid, mss);
3998                s->src.mss = mss;
3999#ifdef __FreeBSD__
4000                pf_send_tcp(NULL, r, pd->af, pd->dst, pd->src, th->th_dport,
4001#else
4002                pf_send_tcp(r, pd->af, pd->dst, pd->src, th->th_dport,
4003#endif
4004                    th->th_sport, s->src.seqhi, ntohl(th->th_seq) + 1,
4005                    TH_SYN|TH_ACK, 0, s->src.mss, 0, 1, 0, NULL, NULL);
4006                REASON_SET(&reason, PFRES_SYNPROXY);
4007                return (PF_SYNPROXY_DROP);
4008        }
4009
4010        return (PF_PASS);
4011
4012csfailed:
4013#ifdef __FreeBSD__
4014        if (sk != NULL)
4015                pool_put(&V_pf_state_key_pl, sk);
4016        if (nk != NULL)
4017                pool_put(&V_pf_state_key_pl, nk);
4018#else
4019        if (sk != NULL)
4020                pool_put(&pf_state_key_pl, sk);
4021        if (nk != NULL)
4022                pool_put(&pf_state_key_pl, nk);
4023#endif
4024
4025        if (sn != NULL && sn->states == 0 && sn->expire == 0) {
4026#ifdef __FreeBSD__
4027                RB_REMOVE(pf_src_tree, &V_tree_src_tracking, sn);
4028                V_pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
4029                V_pf_status.src_nodes--;
4030                pool_put(&V_pf_src_tree_pl, sn);
4031#else
4032                RB_REMOVE(pf_src_tree, &tree_src_tracking, sn);
4033                pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
4034                pf_status.src_nodes--;
4035                pool_put(&pf_src_tree_pl, sn);
4036#endif
4037        }
4038        if (nsn != sn && nsn != NULL && nsn->states == 0 && nsn->expire == 0) {
4039#ifdef __FreeBSD__
4040                RB_REMOVE(pf_src_tree, &V_tree_src_tracking, nsn);
4041                V_pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
4042                V_pf_status.src_nodes--;
4043                pool_put(&V_pf_src_tree_pl, nsn);
4044#else
4045                RB_REMOVE(pf_src_tree, &tree_src_tracking, nsn);
4046                pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
4047                pf_status.src_nodes--;
4048                pool_put(&pf_src_tree_pl, nsn);
4049#endif
4050        }
4051        return (PF_DROP);
4052}
4053
4054int
4055pf_test_fragment(struct pf_rule **rm, int direction, struct pfi_kif *kif,
4056    struct mbuf *m, void *h, struct pf_pdesc *pd, struct pf_rule **am,
4057    struct pf_ruleset **rsm)
4058{
4059        struct pf_rule          *r, *a = NULL;
4060        struct pf_ruleset       *ruleset = NULL;
4061        sa_family_t              af = pd->af;
4062        u_short                  reason;
4063        int                      tag = -1;
4064        int                      asd = 0;
4065        int                      match = 0;
4066
4067        r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_FILTER].active.ptr);
4068        while (r != NULL) {
4069                r->evaluations++;
4070                if (pfi_kif_match(r->kif, kif) == r->ifnot)
4071                        r = r->skip[PF_SKIP_IFP].ptr;
4072                else if (r->direction && r->direction != direction)
4073                        r = r->skip[PF_SKIP_DIR].ptr;
4074                else if (r->af && r->af != af)
4075                        r = r->skip[PF_SKIP_AF].ptr;
4076                else if (r->proto && r->proto != pd->proto)
4077                        r = r->skip[PF_SKIP_PROTO].ptr;
4078                else if (PF_MISMATCHAW(&r->src.addr, pd->src, af,
4079                    r->src.neg, kif, M_GETFIB(m)))
4080                        r = r->skip[PF_SKIP_SRC_ADDR].ptr;
4081                else if (PF_MISMATCHAW(&r->dst.addr, pd->dst, af,
4082                    r->dst.neg, NULL, M_GETFIB(m)))
4083                        r = r->skip[PF_SKIP_DST_ADDR].ptr;
4084                else if (r->tos && !(r->tos == pd->tos))
4085                        r = TAILQ_NEXT(r, entries);
4086                else if (r->os_fingerprint != PF_OSFP_ANY)
4087                        r = TAILQ_NEXT(r, entries);
4088                else if (pd->proto == IPPROTO_UDP &&
4089                    (r->src.port_op || r->dst.port_op))
4090                        r = TAILQ_NEXT(r, entries);
4091                else if (pd->proto == IPPROTO_TCP &&
4092                    (r->src.port_op || r->dst.port_op || r->flagset))
4093                        r = TAILQ_NEXT(r, entries);
4094                else if ((pd->proto == IPPROTO_ICMP ||
4095                    pd->proto == IPPROTO_ICMPV6) &&
4096                    (r->type || r->code))
4097                        r = TAILQ_NEXT(r, entries);
4098                else if (r->prob && r->prob <=
4099                    (arc4random() % (UINT_MAX - 1) + 1))
4100                        r = TAILQ_NEXT(r, entries);
4101#ifdef __FreeBSD__
4102                else if (r->match_tag && !pf_match_tag(m, r, &tag, pd->pf_mtag))
4103#else
4104                else if (r->match_tag && !pf_match_tag(m, r, &tag))
4105#endif
4106                        r = TAILQ_NEXT(r, entries);
4107                else {
4108                        if (r->anchor == NULL) {
4109                                match = 1;
4110                                *rm = r;
4111                                *am = a;
4112                                *rsm = ruleset;
4113                                if ((*rm)->quick)
4114                                        break;
4115                                r = TAILQ_NEXT(r, entries);
4116                        } else
4117                                pf_step_into_anchor(&asd, &ruleset,
4118                                    PF_RULESET_FILTER, &r, &a, &match);
4119                }
4120                if (r == NULL && pf_step_out_of_anchor(&asd, &ruleset,
4121                    PF_RULESET_FILTER, &r, &a, &match))
4122                        break;
4123        }
4124        r = *rm;
4125        a = *am;
4126        ruleset = *rsm;
4127
4128        REASON_SET(&reason, PFRES_MATCH);
4129
4130        if (r->log)
4131                PFLOG_PACKET(kif, h, m, af, direction, reason, r, a, ruleset,
4132                    pd);
4133
4134        if (r->action != PF_PASS)
4135                return (PF_DROP);
4136
4137#ifdef __FreeBSD__
4138        if (pf_tag_packet(m, tag, -1, pd->pf_mtag)) {
4139#else
4140        if (pf_tag_packet(m, tag, -1)) {
4141#endif
4142                REASON_SET(&reason, PFRES_MEMORY);
4143                return (PF_DROP);
4144        }
4145
4146        return (PF_PASS);
4147}
4148
4149int
4150pf_tcp_track_full(struct pf_state_peer *src, struct pf_state_peer *dst,
4151        struct pf_state **state, struct pfi_kif *kif, struct mbuf *m, int off,
4152        struct pf_pdesc *pd, u_short *reason, int *copyback)
4153{
4154        struct tcphdr           *th = pd->hdr.tcp;
4155        u_int16_t                win = ntohs(th->th_win);
4156        u_int32_t                ack, end, seq, orig_seq;
4157        u_int8_t                 sws, dws;
4158        int                      ackskew;
4159
4160        if (src->wscale && dst->wscale && !(th->th_flags & TH_SYN)) {
4161                sws = src->wscale & PF_WSCALE_MASK;
4162                dws = dst->wscale & PF_WSCALE_MASK;
4163        } else
4164                sws = dws = 0;
4165
4166        /*
4167         * Sequence tracking algorithm from Guido van Rooij's paper:
4168         *   http://www.madison-gurkha.com/publications/tcp_filtering/
4169         *      tcp_filtering.ps
4170         */
4171
4172        orig_seq = seq = ntohl(th->th_seq);
4173        if (src->seqlo == 0) {
4174                /* First packet from this end. Set its state */
4175
4176                if ((pd->flags & PFDESC_TCP_NORM || dst->scrub) &&
4177                    src->scrub == NULL) {
4178                        if (pf_normalize_tcp_init(m, off, pd, th, src, dst)) {
4179                                REASON_SET(reason, PFRES_MEMORY);
4180                                return (PF_DROP);
4181                        }
4182                }
4183
4184                /* Deferred generation of sequence number modulator */
4185                if (dst->seqdiff && !src->seqdiff) {
4186                        /* use random iss for the TCP server */
4187                        while ((src->seqdiff = arc4random() - seq) == 0)
4188                                ;
4189                        ack = ntohl(th->th_ack) - dst->seqdiff;
4190                        pf_change_a(&th->th_seq, &th->th_sum, htonl(seq +
4191                            src->seqdiff), 0);
4192                        pf_change_a(&th->th_ack, &th->th_sum, htonl(ack), 0);
4193                        *copyback = 1;
4194                } else {
4195                        ack = ntohl(th->th_ack);
4196                }
4197
4198                end = seq + pd->p_len;
4199                if (th->th_flags & TH_SYN) {
4200                        end++;
4201                        if (dst->wscale & PF_WSCALE_FLAG) {
4202                                src->wscale = pf_get_wscale(m, off, th->th_off,
4203                                    pd->af);
4204                                if (src->wscale & PF_WSCALE_FLAG) {
4205                                        /* Remove scale factor from initial
4206                                         * window */
4207                                        sws = src->wscale & PF_WSCALE_MASK;
4208                                        win = ((u_int32_t)win + (1 << sws) - 1)
4209                                            >> sws;
4210                                        dws = dst->wscale & PF_WSCALE_MASK;
4211                                } else {
4212                                        /* fixup other window */
4213                                        dst->max_win <<= dst->wscale &
4214                                            PF_WSCALE_MASK;
4215                                        /* in case of a retrans SYN|ACK */
4216                                        dst->wscale = 0;
4217                                }
4218                        }
4219                }
4220                if (th->th_flags & TH_FIN)
4221                        end++;
4222
4223                src->seqlo = seq;
4224                if (src->state < TCPS_SYN_SENT)
4225                        src->state = TCPS_SYN_SENT;
4226
4227                /*
4228                 * May need to slide the window (seqhi may have been set by
4229                 * the crappy stack check or if we picked up the connection
4230                 * after establishment)
4231                 */
4232                if (src->seqhi == 1 ||
4233                    SEQ_GEQ(end + MAX(1, dst->max_win << dws), src->seqhi))
4234                        src->seqhi = end + MAX(1, dst->max_win << dws);
4235                if (win > src->max_win)
4236                        src->max_win = win;
4237
4238        } else {
4239                ack = ntohl(th->th_ack) - dst->seqdiff;
4240                if (src->seqdiff) {
4241                        /* Modulate sequence numbers */
4242                        pf_change_a(&th->th_seq, &th->th_sum, htonl(seq +
4243                            src->seqdiff), 0);
4244                        pf_change_a(&th->th_ack, &th->th_sum, htonl(ack), 0);
4245                        *copyback = 1;
4246                }
4247                end = seq + pd->p_len;
4248                if (th->th_flags & TH_SYN)
4249                        end++;
4250                if (th->th_flags & TH_FIN)
4251                        end++;
4252        }
4253
4254        if ((th->th_flags & TH_ACK) == 0) {
4255                /* Let it pass through the ack skew check */
4256                ack = dst->seqlo;
4257        } else if ((ack == 0 &&
4258            (th->th_flags & (TH_ACK|TH_RST)) == (TH_ACK|TH_RST)) ||
4259            /* broken tcp stacks do not set ack */
4260            (dst->state < TCPS_SYN_SENT)) {
4261                /*
4262                 * Many stacks (ours included) will set the ACK number in an
4263                 * FIN|ACK if the SYN times out -- no sequence to ACK.
4264                 */
4265                ack = dst->seqlo;
4266        }
4267
4268        if (seq == end) {
4269                /* Ease sequencing restrictions on no data packets */
4270                seq = src->seqlo;
4271                end = seq;
4272        }
4273
4274        ackskew = dst->seqlo - ack;
4275
4276
4277        /*
4278         * Need to demodulate the sequence numbers in any TCP SACK options
4279         * (Selective ACK). We could optionally validate the SACK values
4280         * against the current ACK window, either forwards or backwards, but
4281         * I'm not confident that SACK has been implemented properly
4282         * everywhere. It wouldn't surprise me if several stacks accidently
4283         * SACK too far backwards of previously ACKed data. There really aren't
4284         * any security implications of bad SACKing unless the target stack
4285         * doesn't validate the option length correctly. Someone trying to
4286         * spoof into a TCP connection won't bother blindly sending SACK
4287         * options anyway.
4288         */
4289        if (dst->seqdiff && (th->th_off << 2) > sizeof(struct tcphdr)) {
4290                if (pf_modulate_sack(m, off, pd, th, dst))
4291                        *copyback = 1;
4292        }
4293
4294
4295#define MAXACKWINDOW (0xffff + 1500)    /* 1500 is an arbitrary fudge factor */
4296        if (SEQ_GEQ(src->seqhi, end) &&
4297            /* Last octet inside other's window space */
4298            SEQ_GEQ(seq, src->seqlo - (dst->max_win << dws)) &&
4299            /* Retrans: not more than one window back */
4300            (ackskew >= -MAXACKWINDOW) &&
4301            /* Acking not more than one reassembled fragment backwards */
4302            (ackskew <= (MAXACKWINDOW << sws)) &&
4303            /* Acking not more than one window forward */
4304            ((th->th_flags & TH_RST) == 0 || orig_seq == src->seqlo ||
4305            (orig_seq == src->seqlo + 1) || (orig_seq + 1 == src->seqlo) ||
4306            (pd->flags & PFDESC_IP_REAS) == 0)) {
4307            /* Require an exact/+1 sequence match on resets when possible */
4308
4309                if (dst->scrub || src->scrub) {
4310                        if (pf_normalize_tcp_stateful(m, off, pd, reason, th,
4311                            *state, src, dst, copyback))
4312                                return (PF_DROP);
4313                }
4314
4315                /* update max window */
4316                if (src->max_win < win)
4317                        src->max_win = win;
4318                /* synchronize sequencing */
4319                if (SEQ_GT(end, src->seqlo))
4320                        src->seqlo = end;
4321                /* slide the window of what the other end can send */
4322                if (SEQ_GEQ(ack + (win << sws), dst->seqhi))
4323                        dst->seqhi = ack + MAX((win << sws), 1);
4324
4325
4326                /* update states */
4327                if (th->th_flags & TH_SYN)
4328                        if (src->state < TCPS_SYN_SENT)
4329                                src->state = TCPS_SYN_SENT;
4330                if (th->th_flags & TH_FIN)
4331                        if (src->state < TCPS_CLOSING)
4332                                src->state = TCPS_CLOSING;
4333                if (th->th_flags & TH_ACK) {
4334                        if (dst->state == TCPS_SYN_SENT) {
4335                                dst->state = TCPS_ESTABLISHED;
4336                                if (src->state == TCPS_ESTABLISHED &&
4337                                    (*state)->src_node != NULL &&
4338                                    pf_src_connlimit(state)) {
4339                                        REASON_SET(reason, PFRES_SRCLIMIT);
4340                                        return (PF_DROP);
4341                                }
4342                        } else if (dst->state == TCPS_CLOSING)
4343                                dst->state = TCPS_FIN_WAIT_2;
4344                }
4345                if (th->th_flags & TH_RST)
4346                        src->state = dst->state = TCPS_TIME_WAIT;
4347
4348                /* update expire time */
4349                (*state)->expire = time_second;
4350                if (src->state >= TCPS_FIN_WAIT_2 &&
4351                    dst->state >= TCPS_FIN_WAIT_2)
4352                        (*state)->timeout = PFTM_TCP_CLOSED;
4353                else if (src->state >= TCPS_CLOSING &&
4354                    dst->state >= TCPS_CLOSING)
4355                        (*state)->timeout = PFTM_TCP_FIN_WAIT;
4356                else if (src->state < TCPS_ESTABLISHED ||
4357                    dst->state < TCPS_ESTABLISHED)
4358                        (*state)->timeout = PFTM_TCP_OPENING;
4359                else if (src->state >= TCPS_CLOSING ||
4360                    dst->state >= TCPS_CLOSING)
4361                        (*state)->timeout = PFTM_TCP_CLOSING;
4362                else
4363                        (*state)->timeout = PFTM_TCP_ESTABLISHED;
4364
4365                /* Fall through to PASS packet */
4366
4367        } else if ((dst->state < TCPS_SYN_SENT ||
4368                dst->state >= TCPS_FIN_WAIT_2 ||
4369                src->state >= TCPS_FIN_WAIT_2) &&
4370            SEQ_GEQ(src->seqhi + MAXACKWINDOW, end) &&
4371            /* Within a window forward of the originating packet */
4372            SEQ_GEQ(seq, src->seqlo - MAXACKWINDOW)) {
4373            /* Within a window backward of the originating packet */
4374
4375                /*
4376                 * This currently handles three situations:
4377                 *  1) Stupid stacks will shotgun SYNs before their peer
4378                 *     replies.
4379                 *  2) When PF catches an already established stream (the
4380                 *     firewall rebooted, the state table was flushed, routes
4381                 *     changed...)
4382                 *  3) Packets get funky immediately after the connection
4383                 *     closes (this should catch Solaris spurious ACK|FINs
4384                 *     that web servers like to spew after a close)
4385                 *
4386                 * This must be a little more careful than the above code
4387                 * since packet floods will also be caught here. We don't
4388                 * update the TTL here to mitigate the damage of a packet
4389                 * flood and so the same code can handle awkward establishment
4390                 * and a loosened connection close.
4391                 * In the establishment case, a correct peer response will
4392                 * validate the connection, go through the normal state code
4393                 * and keep updating the state TTL.
4394                 */
4395
4396#ifdef __FreeBSD__
4397                if (V_pf_status.debug >= PF_DEBUG_MISC) {
4398#else
4399                if (pf_status.debug >= PF_DEBUG_MISC) {
4400#endif
4401                        printf("pf: loose state match: ");
4402                        pf_print_state(*state);
4403                        pf_print_flags(th->th_flags);
4404                        printf(" seq=%u (%u) ack=%u len=%u ackskew=%d "
4405                            "pkts=%llu:%llu dir=%s,%s\n", seq, orig_seq, ack,
4406#ifdef __FreeBSD__
4407                            pd->p_len, ackskew, (unsigned long long)(*state)->packets[0],
4408                            (unsigned long long)(*state)->packets[1],
4409#else
4410                            pd->p_len, ackskew, (*state)->packets[0],
4411                            (*state)->packets[1],
4412#endif
4413                            pd->dir == PF_IN ? "in" : "out",
4414                            pd->dir == (*state)->direction ? "fwd" : "rev");
4415                }
4416
4417                if (dst->scrub || src->scrub) {
4418                        if (pf_normalize_tcp_stateful(m, off, pd, reason, th,
4419                            *state, src, dst, copyback))
4420                                return (PF_DROP);
4421                }
4422
4423                /* update max window */
4424                if (src->max_win < win)
4425                        src->max_win = win;
4426                /* synchronize sequencing */
4427                if (SEQ_GT(end, src->seqlo))
4428                        src->seqlo = end;
4429                /* slide the window of what the other end can send */
4430                if (SEQ_GEQ(ack + (win << sws), dst->seqhi))
4431                        dst->seqhi = ack + MAX((win << sws), 1);
4432
4433                /*
4434                 * Cannot set dst->seqhi here since this could be a shotgunned
4435                 * SYN and not an already established connection.
4436                 */
4437
4438                if (th->th_flags & TH_FIN)
4439                        if (src->state < TCPS_CLOSING)
4440                                src->state = TCPS_CLOSING;
4441                if (th->th_flags & TH_RST)
4442                        src->state = dst->state = TCPS_TIME_WAIT;
4443
4444                /* Fall through to PASS packet */
4445
4446        } else {
4447                if ((*state)->dst.state == TCPS_SYN_SENT &&
4448                    (*state)->src.state == TCPS_SYN_SENT) {
4449                        /* Send RST for state mismatches during handshake */
4450                        if (!(th->th_flags & TH_RST))
4451#ifdef __FreeBSD__
4452                                pf_send_tcp(NULL, (*state)->rule.ptr, pd->af,
4453#else
4454                                pf_send_tcp((*state)->rule.ptr, pd->af,
4455#endif
4456                                    pd->dst, pd->src, th->th_dport,
4457                                    th->th_sport, ntohl(th->th_ack), 0,
4458                                    TH_RST, 0, 0,
4459                                    (*state)->rule.ptr->return_ttl, 1, 0,
4460                                    pd->eh, kif->pfik_ifp);
4461                        src->seqlo = 0;
4462                        src->seqhi = 1;
4463                        src->max_win = 1;
4464#ifdef __FreeBSD__
4465                } else if (V_pf_status.debug >= PF_DEBUG_MISC) {
4466#else
4467                } else if (pf_status.debug >= PF_DEBUG_MISC) {
4468#endif
4469                        printf("pf: BAD state: ");
4470                        pf_print_state(*state);
4471                        pf_print_flags(th->th_flags);
4472                        printf(" seq=%u (%u) ack=%u len=%u ackskew=%d "
4473                            "pkts=%llu:%llu dir=%s,%s\n",
4474                            seq, orig_seq, ack, pd->p_len, ackskew,
4475#ifdef __FreeBSD__
4476                            (unsigned long long)(*state)->packets[0],
4477                            (unsigned long long)(*state)->packets[1],
4478#else
4479                            (*state)->packets[0], (*state)->packets[1],
4480#endif
4481                            pd->dir == PF_IN ? "in" : "out",
4482                            pd->dir == (*state)->direction ? "fwd" : "rev");
4483                        printf("pf: State failure on: %c %c %c %c | %c %c\n",
4484                            SEQ_GEQ(src->seqhi, end) ? ' ' : '1',
4485                            SEQ_GEQ(seq, src->seqlo - (dst->max_win << dws)) ?
4486                            ' ': '2',
4487                            (ackskew >= -MAXACKWINDOW) ? ' ' : '3',
4488                            (ackskew <= (MAXACKWINDOW << sws)) ? ' ' : '4',
4489                            SEQ_GEQ(src->seqhi + MAXACKWINDOW, end) ?' ' :'5',
4490                            SEQ_GEQ(seq, src->seqlo - MAXACKWINDOW) ?' ' :'6');
4491                }
4492                REASON_SET(reason, PFRES_BADSTATE);
4493                return (PF_DROP);
4494        }
4495
4496        return (PF_PASS);
4497}
4498
4499int
4500pf_tcp_track_sloppy(struct pf_state_peer *src, struct pf_state_peer *dst,
4501        struct pf_state **state, struct pf_pdesc *pd, u_short *reason)
4502{
4503        struct tcphdr           *th = pd->hdr.tcp;
4504
4505        if (th->th_flags & TH_SYN)
4506                if (src->state < TCPS_SYN_SENT)
4507                        src->state = TCPS_SYN_SENT;
4508        if (th->th_flags & TH_FIN)
4509                if (src->state < TCPS_CLOSING)
4510                        src->state = TCPS_CLOSING;
4511        if (th->th_flags & TH_ACK) {
4512                if (dst->state == TCPS_SYN_SENT) {
4513                        dst->state = TCPS_ESTABLISHED;
4514                        if (src->state == TCPS_ESTABLISHED &&
4515                            (*state)->src_node != NULL &&
4516                            pf_src_connlimit(state)) {
4517                                REASON_SET(reason, PFRES_SRCLIMIT);
4518                                return (PF_DROP);
4519                        }
4520                } else if (dst->state == TCPS_CLOSING) {
4521                        dst->state = TCPS_FIN_WAIT_2;
4522                } else if (src->state == TCPS_SYN_SENT &&
4523                    dst->state < TCPS_SYN_SENT) {
4524                        /*
4525                         * Handle a special sloppy case where we only see one
4526                         * half of the connection. If there is a ACK after
4527                         * the initial SYN without ever seeing a packet from
4528                         * the destination, set the connection to established.
4529                         */
4530                        dst->state = src->state = TCPS_ESTABLISHED;
4531                        if ((*state)->src_node != NULL &&
4532                            pf_src_connlimit(state)) {
4533                                REASON_SET(reason, PFRES_SRCLIMIT);
4534                                return (PF_DROP);
4535                        }
4536                } else if (src->state == TCPS_CLOSING &&
4537                    dst->state == TCPS_ESTABLISHED &&
4538                    dst->seqlo == 0) {
4539                        /*
4540                         * Handle the closing of half connections where we
4541                         * don't see the full bidirectional FIN/ACK+ACK
4542                         * handshake.
4543                         */
4544                        dst->state = TCPS_CLOSING;
4545                }
4546        }
4547        if (th->th_flags & TH_RST)
4548                src->state = dst->state = TCPS_TIME_WAIT;
4549
4550        /* update expire time */
4551        (*state)->expire = time_second;
4552        if (src->state >= TCPS_FIN_WAIT_2 &&
4553            dst->state >= TCPS_FIN_WAIT_2)
4554                (*state)->timeout = PFTM_TCP_CLOSED;
4555        else if (src->state >= TCPS_CLOSING &&
4556            dst->state >= TCPS_CLOSING)
4557                (*state)->timeout = PFTM_TCP_FIN_WAIT;
4558        else if (src->state < TCPS_ESTABLISHED ||
4559            dst->state < TCPS_ESTABLISHED)
4560                (*state)->timeout = PFTM_TCP_OPENING;
4561        else if (src->state >= TCPS_CLOSING ||
4562            dst->state >= TCPS_CLOSING)
4563                (*state)->timeout = PFTM_TCP_CLOSING;
4564        else
4565                (*state)->timeout = PFTM_TCP_ESTABLISHED;
4566
4567        return (PF_PASS);
4568}
4569
4570int
4571pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif,
4572    struct mbuf *m, int off, void *h, struct pf_pdesc *pd,
4573    u_short *reason)
4574{
4575        struct pf_state_key_cmp  key;
4576        struct tcphdr           *th = pd->hdr.tcp;
4577        int                      copyback = 0;
4578        struct pf_state_peer    *src, *dst;
4579        struct pf_state_key     *sk;
4580
4581        key.af = pd->af;
4582        key.proto = IPPROTO_TCP;
4583        if (direction == PF_IN) {       /* wire side, straight */
4584                PF_ACPY(&key.addr[0], pd->src, key.af);
4585                PF_ACPY(&key.addr[1], pd->dst, key.af);
4586                key.port[0] = th->th_sport;
4587                key.port[1] = th->th_dport;
4588        } else {                        /* stack side, reverse */
4589                PF_ACPY(&key.addr[1], pd->src, key.af);
4590                PF_ACPY(&key.addr[0], pd->dst, key.af);
4591                key.port[1] = th->th_sport;
4592                key.port[0] = th->th_dport;
4593        }
4594
4595#ifdef __FreeBSD__
4596        STATE_LOOKUP(kif, &key, direction, *state, m, pd->pf_mtag);
4597#else
4598        STATE_LOOKUP(kif, &key, direction, *state, m);
4599#endif
4600
4601        if (direction == (*state)->direction) {
4602                src = &(*state)->src;
4603                dst = &(*state)->dst;
4604        } else {
4605                src = &(*state)->dst;
4606                dst = &(*state)->src;
4607        }
4608
4609        sk = (*state)->key[pd->didx];
4610
4611        if ((*state)->src.state == PF_TCPS_PROXY_SRC) {
4612                if (direction != (*state)->direction) {
4613                        REASON_SET(reason, PFRES_SYNPROXY);
4614                        return (PF_SYNPROXY_DROP);
4615                }
4616                if (th->th_flags & TH_SYN) {
4617                        if (ntohl(th->th_seq) != (*state)->src.seqlo) {
4618                                REASON_SET(reason, PFRES_SYNPROXY);
4619                                return (PF_DROP);
4620                        }
4621#ifdef __FreeBSD__
4622                        pf_send_tcp(NULL, (*state)->rule.ptr, pd->af, pd->dst,
4623#else
4624                        pf_send_tcp((*state)->rule.ptr, pd->af, pd->dst,
4625#endif
4626                            pd->src, th->th_dport, th->th_sport,
4627                            (*state)->src.seqhi, ntohl(th->th_seq) + 1,
4628                            TH_SYN|TH_ACK, 0, (*state)->src.mss, 0, 1,
4629                            0, NULL, NULL);
4630                        REASON_SET(reason, PFRES_SYNPROXY);
4631                        return (PF_SYNPROXY_DROP);
4632                } else if (!(th->th_flags & TH_ACK) ||
4633                    (ntohl(th->th_ack) != (*state)->src.seqhi + 1) ||
4634                    (ntohl(th->th_seq) != (*state)->src.seqlo + 1)) {
4635                        REASON_SET(reason, PFRES_SYNPROXY);
4636                        return (PF_DROP);
4637                } else if ((*state)->src_node != NULL &&
4638                    pf_src_connlimit(state)) {
4639                        REASON_SET(reason, PFRES_SRCLIMIT);
4640                        return (PF_DROP);
4641                } else
4642                        (*state)->src.state = PF_TCPS_PROXY_DST;
4643        }
4644        if ((*state)->src.state == PF_TCPS_PROXY_DST) {
4645                if (direction == (*state)->direction) {
4646                        if (((th->th_flags & (TH_SYN|TH_ACK)) != TH_ACK) ||
4647                            (ntohl(th->th_ack) != (*state)->src.seqhi + 1) ||
4648                            (ntohl(th->th_seq) != (*state)->src.seqlo + 1)) {
4649                                REASON_SET(reason, PFRES_SYNPROXY);
4650                                return (PF_DROP);
4651                        }
4652                        (*state)->src.max_win = MAX(ntohs(th->th_win), 1);
4653                        if ((*state)->dst.seqhi == 1)
4654                                (*state)->dst.seqhi = htonl(arc4random());
4655#ifdef __FreeBSD__
4656                        pf_send_tcp(NULL, (*state)->rule.ptr, pd->af,
4657#else
4658                        pf_send_tcp((*state)->rule.ptr, pd->af,
4659#endif
4660                            &sk->addr[pd->sidx], &sk->addr[pd->didx],
4661                            sk->port[pd->sidx], sk->port[pd->didx],
4662                            (*state)->dst.seqhi, 0, TH_SYN, 0,
4663                            (*state)->src.mss, 0, 0, (*state)->tag, NULL, NULL);
4664                        REASON_SET(reason, PFRES_SYNPROXY);
4665                        return (PF_SYNPROXY_DROP);
4666                } else if (((th->th_flags & (TH_SYN|TH_ACK)) !=
4667                    (TH_SYN|TH_ACK)) ||
4668                    (ntohl(th->th_ack) != (*state)->dst.seqhi + 1)) {
4669                        REASON_SET(reason, PFRES_SYNPROXY);
4670                        return (PF_DROP);
4671                } else {
4672                        (*state)->dst.max_win = MAX(ntohs(th->th_win), 1);
4673                        (*state)->dst.seqlo = ntohl(th->th_seq);
4674#ifdef __FreeBSD__
4675                        pf_send_tcp(NULL, (*state)->rule.ptr, pd->af, pd->dst,
4676#else
4677                        pf_send_tcp((*state)->rule.ptr, pd->af, pd->dst,
4678#endif
4679                            pd->src, th->th_dport, th->th_sport,
4680                            ntohl(th->th_ack), ntohl(th->th_seq) + 1,
4681                            TH_ACK, (*state)->src.max_win, 0, 0, 0,
4682                            (*state)->tag, NULL, NULL);
4683#ifdef __FreeBSD__
4684                        pf_send_tcp(NULL, (*state)->rule.ptr, pd->af,
4685#else
4686                        pf_send_tcp((*state)->rule.ptr, pd->af,
4687#endif
4688                            &sk->addr[pd->sidx], &sk->addr[pd->didx],
4689                            sk->port[pd->sidx], sk->port[pd->didx],
4690                            (*state)->src.seqhi + 1, (*state)->src.seqlo + 1,
4691                            TH_ACK, (*state)->dst.max_win, 0, 0, 1,
4692                            0, NULL, NULL);
4693                        (*state)->src.seqdiff = (*state)->dst.seqhi -
4694                            (*state)->src.seqlo;
4695                        (*state)->dst.seqdiff = (*state)->src.seqhi -
4696                            (*state)->dst.seqlo;
4697                        (*state)->src.seqhi = (*state)->src.seqlo +
4698                            (*state)->dst.max_win;
4699                        (*state)->dst.seqhi = (*state)->dst.seqlo +
4700                            (*state)->src.max_win;
4701                        (*state)->src.wscale = (*state)->dst.wscale = 0;
4702                        (*state)->src.state = (*state)->dst.state =
4703                            TCPS_ESTABLISHED;
4704                        REASON_SET(reason, PFRES_SYNPROXY);
4705                        return (PF_SYNPROXY_DROP);
4706                }
4707        }
4708
4709        if (((th->th_flags & (TH_SYN|TH_ACK)) == TH_SYN) &&
4710            dst->state >= TCPS_FIN_WAIT_2 &&
4711            src->state >= TCPS_FIN_WAIT_2) {
4712#ifdef __FreeBSD__
4713                if (V_pf_status.debug >= PF_DEBUG_MISC) {
4714#else
4715                if (pf_status.debug >= PF_DEBUG_MISC) {
4716#endif
4717                        printf("pf: state reuse ");
4718                        pf_print_state(*state);
4719                        pf_print_flags(th->th_flags);
4720                        printf("\n");
4721                }
4722                /* XXX make sure it's the same direction ?? */
4723                (*state)->src.state = (*state)->dst.state = TCPS_CLOSED;
4724                pf_unlink_state(*state);
4725                *state = NULL;
4726                return (PF_DROP);
4727        }
4728
4729        if ((*state)->state_flags & PFSTATE_SLOPPY) {
4730                if (pf_tcp_track_sloppy(src, dst, state, pd, reason) == PF_DROP)
4731                        return (PF_DROP);
4732        } else {
4733                if (pf_tcp_track_full(src, dst, state, kif, m, off, pd, reason,
4734                    &copyback) == PF_DROP)
4735                        return (PF_DROP);
4736        }
4737
4738        /* translate source/destination address, if necessary */
4739        if ((*state)->key[PF_SK_WIRE] != (*state)->key[PF_SK_STACK]) {
4740                struct pf_state_key *nk = (*state)->key[pd->didx];
4741
4742                if (PF_ANEQ(pd->src, &nk->addr[pd->sidx], pd->af) ||
4743                    nk->port[pd->sidx] != th->th_sport)
4744                        pf_change_ap(pd->src, &th->th_sport, pd->ip_sum,
4745                            &th->th_sum, &nk->addr[pd->sidx],
4746                            nk->port[pd->sidx], 0, pd->af);
4747
4748                if (PF_ANEQ(pd->dst, &nk->addr[pd->didx], pd->af) ||
4749                    nk->port[pd->didx] != th->th_dport)
4750                        pf_change_ap(pd->dst, &th->th_dport, pd->ip_sum,
4751                            &th->th_sum, &nk->addr[pd->didx],
4752                            nk->port[pd->didx], 0, pd->af);
4753                copyback = 1;
4754        }
4755
4756        /* Copyback sequence modulation or stateful scrub changes if needed */
4757        if (copyback)
4758#ifdef __FreeBSD__
4759                m_copyback(m, off, sizeof(*th), (caddr_t)th);
4760#else
4761                m_copyback(m, off, sizeof(*th), th);
4762#endif
4763
4764        return (PF_PASS);
4765}
4766
4767int
4768pf_test_state_udp(struct pf_state **state, int direction, struct pfi_kif *kif,
4769    struct mbuf *m, int off, void *h, struct pf_pdesc *pd)
4770{
4771        struct pf_state_peer    *src, *dst;
4772        struct pf_state_key_cmp  key;
4773        struct udphdr           *uh = pd->hdr.udp;
4774
4775        key.af = pd->af;
4776        key.proto = IPPROTO_UDP;
4777        if (direction == PF_IN) {       /* wire side, straight */
4778                PF_ACPY(&key.addr[0], pd->src, key.af);
4779                PF_ACPY(&key.addr[1], pd->dst, key.af);
4780                key.port[0] = uh->uh_sport;
4781                key.port[1] = uh->uh_dport;
4782        } else {                        /* stack side, reverse */
4783                PF_ACPY(&key.addr[1], pd->src, key.af);
4784                PF_ACPY(&key.addr[0], pd->dst, key.af);
4785                key.port[1] = uh->uh_sport;
4786                key.port[0] = uh->uh_dport;
4787        }
4788
4789#ifdef __FreeBSD__
4790        STATE_LOOKUP(kif, &key, direction, *state, m, pd->pf_mtag);
4791#else
4792        STATE_LOOKUP(kif, &key, direction, *state, m);
4793#endif
4794
4795        if (direction == (*state)->direction) {
4796                src = &(*state)->src;
4797                dst = &(*state)->dst;
4798        } else {
4799                src = &(*state)->dst;
4800                dst = &(*state)->src;
4801        }
4802
4803        /* update states */
4804        if (src->state < PFUDPS_SINGLE)
4805                src->state = PFUDPS_SINGLE;
4806        if (dst->state == PFUDPS_SINGLE)
4807                dst->state = PFUDPS_MULTIPLE;
4808
4809        /* update expire time */
4810        (*state)->expire = time_second;
4811        if (src->state == PFUDPS_MULTIPLE && dst->state == PFUDPS_MULTIPLE)
4812                (*state)->timeout = PFTM_UDP_MULTIPLE;
4813        else
4814                (*state)->timeout = PFTM_UDP_SINGLE;
4815
4816        /* translate source/destination address, if necessary */
4817        if ((*state)->key[PF_SK_WIRE] != (*state)->key[PF_SK_STACK]) {
4818                struct pf_state_key *nk = (*state)->key[pd->didx];
4819
4820                if (PF_ANEQ(pd->src, &nk->addr[pd->sidx], pd->af) ||
4821                    nk->port[pd->sidx] != uh->uh_sport)
4822                        pf_change_ap(pd->src, &uh->uh_sport, pd->ip_sum,
4823                            &uh->uh_sum, &nk->addr[pd->sidx],
4824                            nk->port[pd->sidx], 1, pd->af);
4825
4826                if (PF_ANEQ(pd->dst, &nk->addr[pd->didx], pd->af) ||
4827                    nk->port[pd->didx] != uh->uh_dport)
4828                        pf_change_ap(pd->dst, &uh->uh_dport, pd->ip_sum,
4829                            &uh->uh_sum, &nk->addr[pd->didx],
4830                            nk->port[pd->didx], 1, pd->af);
4831#ifdef __FreeBSD__
4832                m_copyback(m, off, sizeof(*uh), (caddr_t)uh);
4833#else
4834                m_copyback(m, off, sizeof(*uh), uh);
4835#endif
4836        }
4837
4838        return (PF_PASS);
4839}
4840
4841int
4842pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
4843    struct mbuf *m, int off, void *h, struct pf_pdesc *pd, u_short *reason)
4844{
4845        struct pf_addr  *saddr = pd->src, *daddr = pd->dst;
4846#ifdef __FreeBSD__
4847        u_int16_t        icmpid = 0, *icmpsum;
4848#else
4849        u_int16_t        icmpid, *icmpsum;
4850#endif
4851        u_int8_t         icmptype;
4852        int              state_icmp = 0;
4853        struct pf_state_key_cmp key;
4854
4855        switch (pd->proto) {
4856#ifdef INET
4857        case IPPROTO_ICMP:
4858                icmptype = pd->hdr.icmp->icmp_type;
4859                icmpid = pd->hdr.icmp->icmp_id;
4860                icmpsum = &pd->hdr.icmp->icmp_cksum;
4861
4862                if (icmptype == ICMP_UNREACH ||
4863                    icmptype == ICMP_SOURCEQUENCH ||
4864                    icmptype == ICMP_REDIRECT ||
4865                    icmptype == ICMP_TIMXCEED ||
4866                    icmptype == ICMP_PARAMPROB)
4867                        state_icmp++;
4868                break;
4869#endif /* INET */
4870#ifdef INET6
4871        case IPPROTO_ICMPV6:
4872                icmptype = pd->hdr.icmp6->icmp6_type;
4873                icmpid = pd->hdr.icmp6->icmp6_id;
4874                icmpsum = &pd->hdr.icmp6->icmp6_cksum;
4875
4876                if (icmptype == ICMP6_DST_UNREACH ||
4877                    icmptype == ICMP6_PACKET_TOO_BIG ||
4878                    icmptype == ICMP6_TIME_EXCEEDED ||
4879                    icmptype == ICMP6_PARAM_PROB)
4880                        state_icmp++;
4881                break;
4882#endif /* INET6 */
4883        }
4884
4885        if (!state_icmp) {
4886
4887                /*
4888                 * ICMP query/reply message not related to a TCP/UDP packet.
4889                 * Search for an ICMP state.
4890                 */
4891                key.af = pd->af;
4892                key.proto = pd->proto;
4893                key.port[0] = key.port[1] = icmpid;
4894                if (direction == PF_IN) {       /* wire side, straight */
4895                        PF_ACPY(&key.addr[0], pd->src, key.af);
4896                        PF_ACPY(&key.addr[1], pd->dst, key.af);
4897                } else {                        /* stack side, reverse */
4898                        PF_ACPY(&key.addr[1], pd->src, key.af);
4899                        PF_ACPY(&key.addr[0], pd->dst, key.af);
4900                }
4901
4902#ifdef __FreeBSD__
4903                STATE_LOOKUP(kif, &key, direction, *state, m, pd->pf_mtag);
4904#else
4905                STATE_LOOKUP(kif, &key, direction, *state, m);
4906#endif
4907
4908                (*state)->expire = time_second;
4909                (*state)->timeout = PFTM_ICMP_ERROR_REPLY;
4910
4911                /* translate source/destination address, if necessary */
4912                if ((*state)->key[PF_SK_WIRE] != (*state)->key[PF_SK_STACK]) {
4913                        struct pf_state_key *nk = (*state)->key[pd->didx];
4914
4915                        switch (pd->af) {
4916#ifdef INET
4917                        case AF_INET:
4918                                if (PF_ANEQ(pd->src,
4919                                    &nk->addr[pd->sidx], AF_INET))
4920                                        pf_change_a(&saddr->v4.s_addr,
4921                                            pd->ip_sum,
4922                                            nk->addr[pd->sidx].v4.s_addr, 0);
4923
4924                                if (PF_ANEQ(pd->dst, &nk->addr[pd->didx],
4925                                    AF_INET))
4926                                        pf_change_a(&daddr->v4.s_addr,
4927                                            pd->ip_sum,
4928                                            nk->addr[pd->didx].v4.s_addr, 0);
4929
4930                                if (nk->port[0] !=
4931                                    pd->hdr.icmp->icmp_id) {
4932                                        pd->hdr.icmp->icmp_cksum =
4933                                            pf_cksum_fixup(
4934                                            pd->hdr.icmp->icmp_cksum, icmpid,
4935                                            nk->port[pd->sidx], 0);
4936                                        pd->hdr.icmp->icmp_id =
4937                                            nk->port[pd->sidx];
4938                                }
4939
4940                                m_copyback(m, off, ICMP_MINLEN,
4941#ifdef __FreeBSD__
4942                                    (caddr_t)
4943#endif
4944                                    pd->hdr.icmp);
4945                                break;
4946#endif /* INET */
4947#ifdef INET6
4948                        case AF_INET6:
4949                                if (PF_ANEQ(pd->src,
4950                                    &nk->addr[pd->sidx], AF_INET6))
4951                                        pf_change_a6(saddr,
4952                                            &pd->hdr.icmp6->icmp6_cksum,
4953                                            &nk->addr[pd->sidx], 0);
4954
4955                                if (PF_ANEQ(pd->dst,
4956                                    &nk->addr[pd->didx], AF_INET6))
4957                                        pf_change_a6(daddr,
4958                                            &pd->hdr.icmp6->icmp6_cksum,
4959                                            &nk->addr[pd->didx], 0);
4960
4961                                m_copyback(m, off,
4962                                    sizeof(struct icmp6_hdr),
4963#ifdef __FreeBSD__
4964                                    (caddr_t)
4965#endif
4966                                    pd->hdr.icmp6);
4967                                break;
4968#endif /* INET6 */
4969                        }
4970                }
4971                return (PF_PASS);
4972
4973        } else {
4974                /*
4975                 * ICMP error message in response to a TCP/UDP packet.
4976                 * Extract the inner TCP/UDP header and search for that state.
4977                 */
4978
4979                struct pf_pdesc pd2;
4980#ifdef __FreeBSD__
4981                bzero(&pd2, sizeof pd2);
4982#endif
4983#ifdef INET
4984                struct ip       h2;
4985#endif /* INET */
4986#ifdef INET6
4987                struct ip6_hdr  h2_6;
4988                int             terminal = 0;
4989#endif /* INET6 */
4990#ifdef __FreeBSD__
4991                int             ipoff2 = 0;
4992                int             off2 = 0;
4993#else
4994                int             ipoff2;
4995                int             off2;
4996#endif
4997
4998                pd2.af = pd->af;
4999                /* Payload packet is from the opposite direction. */
5000                pd2.sidx = (direction == PF_IN) ? 1 : 0;
5001                pd2.didx = (direction == PF_IN) ? 0 : 1;
5002                switch (pd->af) {
5003#ifdef INET
5004                case AF_INET:
5005                        /* offset of h2 in mbuf chain */
5006                        ipoff2 = off + ICMP_MINLEN;
5007
5008                        if (!pf_pull_hdr(m, ipoff2, &h2, sizeof(h2),
5009                            NULL, reason, pd2.af)) {
5010                                DPFPRINTF(PF_DEBUG_MISC,
5011                                    ("pf: ICMP error message too short "
5012                                    "(ip)\n"));
5013                                return (PF_DROP);
5014                        }
5015                        /*
5016                         * ICMP error messages don't refer to non-first
5017                         * fragments
5018                         */
5019                        if (h2.ip_off & htons(IP_OFFMASK)) {
5020                                REASON_SET(reason, PFRES_FRAG);
5021                                return (PF_DROP);
5022                        }
5023
5024                        /* offset of protocol header that follows h2 */
5025                        off2 = ipoff2 + (h2.ip_hl << 2);
5026
5027                        pd2.proto = h2.ip_p;
5028                        pd2.src = (struct pf_addr *)&h2.ip_src;
5029                        pd2.dst = (struct pf_addr *)&h2.ip_dst;
5030                        pd2.ip_sum = &h2.ip_sum;
5031                        break;
5032#endif /* INET */
5033#ifdef INET6
5034                case AF_INET6:
5035                        ipoff2 = off + sizeof(struct icmp6_hdr);
5036
5037                        if (!pf_pull_hdr(m, ipoff2, &h2_6, sizeof(h2_6),
5038                            NULL, reason, pd2.af)) {
5039                                DPFPRINTF(PF_DEBUG_MISC,
5040                                    ("pf: ICMP error message too short "
5041                                    "(ip6)\n"));
5042                                return (PF_DROP);
5043                        }
5044                        pd2.proto = h2_6.ip6_nxt;
5045                        pd2.src = (struct pf_addr *)&h2_6.ip6_src;
5046                        pd2.dst = (struct pf_addr *)&h2_6.ip6_dst;
5047                        pd2.ip_sum = NULL;
5048                        off2 = ipoff2 + sizeof(h2_6);
5049                        do {
5050                                switch (pd2.proto) {
5051                                case IPPROTO_FRAGMENT:
5052                                        /*
5053                                         * ICMPv6 error messages for
5054                                         * non-first fragments
5055                                         */
5056                                        REASON_SET(reason, PFRES_FRAG);
5057                                        return (PF_DROP);
5058                                case IPPROTO_AH:
5059                                case IPPROTO_HOPOPTS:
5060                                case IPPROTO_ROUTING:
5061                                case IPPROTO_DSTOPTS: {
5062                                        /* get next header and header length */
5063                                        struct ip6_ext opt6;
5064
5065                                        if (!pf_pull_hdr(m, off2, &opt6,
5066                                            sizeof(opt6), NULL, reason,
5067                                            pd2.af)) {
5068                                                DPFPRINTF(PF_DEBUG_MISC,
5069                                                    ("pf: ICMPv6 short opt\n"));
5070                                                return (PF_DROP);
5071                                        }
5072                                        if (pd2.proto == IPPROTO_AH)
5073                                                off2 += (opt6.ip6e_len + 2) * 4;
5074                                        else
5075                                                off2 += (opt6.ip6e_len + 1) * 8;
5076                                        pd2.proto = opt6.ip6e_nxt;
5077                                        /* goto the next header */
5078                                        break;
5079                                }
5080                                default:
5081                                        terminal++;
5082                                        break;
5083                                }
5084                        } while (!terminal);
5085                        break;
5086#endif /* INET6 */
5087                }
5088
5089                switch (pd2.proto) {
5090                case IPPROTO_TCP: {
5091                        struct tcphdr            th;
5092                        u_int32_t                seq;
5093                        struct pf_state_peer    *src, *dst;
5094                        u_int8_t                 dws;
5095                        int                      copyback = 0;
5096
5097                        /*
5098                         * Only the first 8 bytes of the TCP header can be
5099                         * expected. Don't access any TCP header fields after
5100                         * th_seq, an ackskew test is not possible.
5101                         */
5102                        if (!pf_pull_hdr(m, off2, &th, 8, NULL, reason,
5103                            pd2.af)) {
5104                                DPFPRINTF(PF_DEBUG_MISC,
5105                                    ("pf: ICMP error message too short "
5106                                    "(tcp)\n"));
5107                                return (PF_DROP);
5108                        }
5109
5110                        key.af = pd2.af;
5111                        key.proto = IPPROTO_TCP;
5112                        PF_ACPY(&key.addr[pd2.sidx], pd2.src, key.af);
5113                        PF_ACPY(&key.addr[pd2.didx], pd2.dst, key.af);
5114                        key.port[pd2.sidx] = th.th_sport;
5115                        key.port[pd2.didx] = th.th_dport;
5116
5117#ifdef __FreeBSD__
5118                        STATE_LOOKUP(kif, &key, direction, *state, m, pd->pf_mtag);
5119#else
5120                        STATE_LOOKUP(kif, &key, direction, *state, m);
5121#endif
5122
5123                        if (direction == (*state)->direction) {
5124                                src = &(*state)->dst;
5125                                dst = &(*state)->src;
5126                        } else {
5127                                src = &(*state)->src;
5128                                dst = &(*state)->dst;
5129                        }
5130
5131                        if (src->wscale && dst->wscale)
5132                                dws = dst->wscale & PF_WSCALE_MASK;
5133                        else
5134                                dws = 0;
5135
5136                        /* Demodulate sequence number */
5137                        seq = ntohl(th.th_seq) - src->seqdiff;
5138                        if (src->seqdiff) {
5139                                pf_change_a(&th.th_seq, icmpsum,
5140                                    htonl(seq), 0);
5141                                copyback = 1;
5142                        }
5143
5144                        if (!((*state)->state_flags & PFSTATE_SLOPPY) &&
5145                            (!SEQ_GEQ(src->seqhi, seq) ||
5146                            !SEQ_GEQ(seq, src->seqlo - (dst->max_win << dws)))) {
5147#ifdef __FreeBSD__
5148                                if (V_pf_status.debug >= PF_DEBUG_MISC) {
5149#else
5150                                if (pf_status.debug >= PF_DEBUG_MISC) {
5151#endif
5152                                        printf("pf: BAD ICMP %d:%d ",
5153                                            icmptype, pd->hdr.icmp->icmp_code);
5154                                        pf_print_host(pd->src, 0, pd->af);
5155                                        printf(" -> ");
5156                                        pf_print_host(pd->dst, 0, pd->af);
5157                                        printf(" state: ");
5158                                        pf_print_state(*state);
5159                                        printf(" seq=%u\n", seq);
5160                                }
5161                                REASON_SET(reason, PFRES_BADSTATE);
5162                                return (PF_DROP);
5163                        } else {
5164#ifdef __FreeBSD__
5165                                if (V_pf_status.debug >= PF_DEBUG_MISC) {
5166#else
5167                                if (pf_status.debug >= PF_DEBUG_MISC) {
5168#endif
5169                                        printf("pf: OK ICMP %d:%d ",
5170                                            icmptype, pd->hdr.icmp->icmp_code);
5171                                        pf_print_host(pd->src, 0, pd->af);
5172                                        printf(" -> ");
5173                                        pf_print_host(pd->dst, 0, pd->af);
5174                                        printf(" state: ");
5175                                        pf_print_state(*state);
5176                                        printf(" seq=%u\n", seq);
5177                                }
5178                        }
5179
5180                        /* translate source/destination address, if necessary */
5181                        if ((*state)->key[PF_SK_WIRE] !=
5182                            (*state)->key[PF_SK_STACK]) {
5183                                struct pf_state_key *nk =
5184                                    (*state)->key[pd->didx];
5185
5186                                if (PF_ANEQ(pd2.src,
5187                                    &nk->addr[pd2.sidx], pd2.af) ||
5188                                    nk->port[pd2.sidx] != th.th_sport)
5189                                        pf_change_icmp(pd2.src, &th.th_sport,
5190                                            daddr, &nk->addr[pd2.sidx],
5191                                            nk->port[pd2.sidx], NULL,
5192                                            pd2.ip_sum, icmpsum,
5193                                            pd->ip_sum, 0, pd2.af);
5194
5195                                if (PF_ANEQ(pd2.dst,
5196                                    &nk->addr[pd2.didx], pd2.af) ||
5197                                    nk->port[pd2.didx] != th.th_dport)
5198                                        pf_change_icmp(pd2.dst, &th.th_dport,
5199                                            NULL, /* XXX Inbound NAT? */
5200                                            &nk->addr[pd2.didx],
5201                                            nk->port[pd2.didx], NULL,
5202                                            pd2.ip_sum, icmpsum,
5203                                            pd->ip_sum, 0, pd2.af);
5204                                copyback = 1;
5205                        }
5206
5207                        if (copyback) {
5208                                switch (pd2.af) {
5209#ifdef INET
5210                                case AF_INET:
5211                                        m_copyback(m, off, ICMP_MINLEN,
5212#ifdef __FreeBSD__
5213                                            (caddr_t)
5214#endif
5215                                            pd->hdr.icmp);
5216                                        m_copyback(m, ipoff2, sizeof(h2),
5217#ifdef __FreeBSD__
5218                                            (caddr_t)
5219#endif
5220                                            &h2);
5221                                        break;
5222#endif /* INET */
5223#ifdef INET6
5224                                case AF_INET6:
5225                                        m_copyback(m, off,
5226                                            sizeof(struct icmp6_hdr),
5227#ifdef __FreeBSD__
5228                                            (caddr_t)
5229#endif
5230                                            pd->hdr.icmp6);
5231                                        m_copyback(m, ipoff2, sizeof(h2_6),
5232#ifdef __FreeBSD__
5233                                            (caddr_t)
5234#endif
5235                                            &h2_6);
5236                                        break;
5237#endif /* INET6 */
5238                                }
5239#ifdef __FreeBSD__
5240                                m_copyback(m, off2, 8, (caddr_t)&th);
5241#else
5242                                m_copyback(m, off2, 8, &th);
5243#endif
5244                        }
5245
5246                        return (PF_PASS);
5247                        break;
5248                }
5249                case IPPROTO_UDP: {
5250                        struct udphdr           uh;
5251
5252                        if (!pf_pull_hdr(m, off2, &uh, sizeof(uh),
5253                            NULL, reason, pd2.af)) {
5254                                DPFPRINTF(PF_DEBUG_MISC,
5255                                    ("pf: ICMP error message too short "
5256                                    "(udp)\n"));
5257                                return (PF_DROP);
5258                        }
5259
5260                        key.af = pd2.af;
5261                        key.proto = IPPROTO_UDP;
5262                        PF_ACPY(&key.addr[pd2.sidx], pd2.src, key.af);
5263                        PF_ACPY(&key.addr[pd2.didx], pd2.dst, key.af);
5264                        key.port[pd2.sidx] = uh.uh_sport;
5265                        key.port[pd2.didx] = uh.uh_dport;
5266
5267#ifdef __FreeBSD__
5268                        STATE_LOOKUP(kif, &key, direction, *state, m, pd->pf_mtag);
5269#else
5270                        STATE_LOOKUP(kif, &key, direction, *state, m);
5271#endif
5272
5273                        /* translate source/destination address, if necessary */
5274                        if ((*state)->key[PF_SK_WIRE] !=
5275                            (*state)->key[PF_SK_STACK]) {
5276                                struct pf_state_key *nk =
5277                                    (*state)->key[pd->didx];
5278
5279                                if (PF_ANEQ(pd2.src,
5280                                    &nk->addr[pd2.sidx], pd2.af) ||
5281                                    nk->port[pd2.sidx] != uh.uh_sport)
5282                                        pf_change_icmp(pd2.src, &uh.uh_sport,
5283                                            daddr, &nk->addr[pd2.sidx],
5284                                            nk->port[pd2.sidx], &uh.uh_sum,
5285                                            pd2.ip_sum, icmpsum,
5286                                            pd->ip_sum, 1, pd2.af);
5287
5288                                if (PF_ANEQ(pd2.dst,
5289                                    &nk->addr[pd2.didx], pd2.af) ||
5290                                    nk->port[pd2.didx] != uh.uh_dport)
5291                                        pf_change_icmp(pd2.dst, &uh.uh_dport,
5292                                            NULL, /* XXX Inbound NAT? */
5293                                            &nk->addr[pd2.didx],
5294                                            nk->port[pd2.didx], &uh.uh_sum,
5295                                            pd2.ip_sum, icmpsum,
5296                                            pd->ip_sum, 1, pd2.af);
5297
5298                                switch (pd2.af) {
5299#ifdef INET
5300                                case AF_INET:
5301                                        m_copyback(m, off, ICMP_MINLEN,
5302#ifdef __FreeBSD__
5303                                            (caddr_t)
5304#endif
5305                                            pd->hdr.icmp);
5306#ifdef __FreeBSD__
5307                                        m_copyback(m, ipoff2, sizeof(h2), (caddr_t)&h2);
5308#else
5309                                        m_copyback(m, ipoff2, sizeof(h2), &h2);
5310#endif
5311                                        break;
5312#endif /* INET */
5313#ifdef INET6
5314                                case AF_INET6:
5315                                        m_copyback(m, off,
5316                                            sizeof(struct icmp6_hdr),
5317#ifdef __FreeBSD__
5318                                            (caddr_t)
5319#endif
5320                                            pd->hdr.icmp6);
5321                                        m_copyback(m, ipoff2, sizeof(h2_6),
5322#ifdef __FreeBSD__
5323                                            (caddr_t)
5324#endif
5325                                            &h2_6);
5326                                        break;
5327#endif /* INET6 */
5328                                }
5329#ifdef __FreeBSD__
5330                                m_copyback(m, off2, sizeof(uh), (caddr_t)&uh);
5331#else
5332                                m_copyback(m, off2, sizeof(uh), &uh);
5333#endif
5334                        }
5335                        return (PF_PASS);
5336                        break;
5337                }
5338#ifdef INET
5339                case IPPROTO_ICMP: {
5340                        struct icmp             iih;
5341
5342                        if (!pf_pull_hdr(m, off2, &iih, ICMP_MINLEN,
5343                            NULL, reason, pd2.af)) {
5344                                DPFPRINTF(PF_DEBUG_MISC,
5345                                    ("pf: ICMP error message too short i"
5346                                    "(icmp)\n"));
5347                                return (PF_DROP);
5348                        }
5349
5350                        key.af = pd2.af;
5351                        key.proto = IPPROTO_ICMP;
5352                        PF_ACPY(&key.addr[pd2.sidx], pd2.src, key.af);
5353                        PF_ACPY(&key.addr[pd2.didx], pd2.dst, key.af);
5354                        key.port[0] = key.port[1] = iih.icmp_id;
5355
5356#ifdef __FreeBSD__
5357                        STATE_LOOKUP(kif, &key, direction, *state, m, pd->pf_mtag);
5358#else
5359                        STATE_LOOKUP(kif, &key, direction, *state, m);
5360#endif
5361
5362                        /* translate source/destination address, if necessary */
5363                        if ((*state)->key[PF_SK_WIRE] !=
5364                            (*state)->key[PF_SK_STACK]) {
5365                                struct pf_state_key *nk =
5366                                    (*state)->key[pd->didx];
5367
5368                                if (PF_ANEQ(pd2.src,
5369                                    &nk->addr[pd2.sidx], pd2.af) ||
5370                                    nk->port[pd2.sidx] != iih.icmp_id)
5371                                        pf_change_icmp(pd2.src, &iih.icmp_id,
5372                                            daddr, &nk->addr[pd2.sidx],
5373                                            nk->port[pd2.sidx], NULL,
5374                                            pd2.ip_sum, icmpsum,
5375                                            pd->ip_sum, 0, AF_INET);
5376
5377                                if (PF_ANEQ(pd2.dst,
5378                                    &nk->addr[pd2.didx], pd2.af) ||
5379                                    nk->port[pd2.didx] != iih.icmp_id)
5380                                        pf_change_icmp(pd2.dst, &iih.icmp_id,
5381                                            NULL, /* XXX Inbound NAT? */
5382                                            &nk->addr[pd2.didx],
5383                                            nk->port[pd2.didx], NULL,
5384                                            pd2.ip_sum, icmpsum,
5385                                            pd->ip_sum, 0, AF_INET);
5386
5387#ifdef __FreeBSD__
5388                                m_copyback(m, off, ICMP_MINLEN, (caddr_t)pd->hdr.icmp);
5389                                m_copyback(m, ipoff2, sizeof(h2), (caddr_t)&h2);
5390                                m_copyback(m, off2, ICMP_MINLEN, (caddr_t)&iih);
5391#else
5392                                m_copyback(m, off, ICMP_MINLEN, pd->hdr.icmp);
5393                                m_copyback(m, ipoff2, sizeof(h2), &h2);
5394                                m_copyback(m, off2, ICMP_MINLEN, &iih);
5395#endif
5396                        }
5397                        return (PF_PASS);
5398                        break;
5399                }
5400#endif /* INET */
5401#ifdef INET6
5402                case IPPROTO_ICMPV6: {
5403                        struct icmp6_hdr        iih;
5404
5405                        if (!pf_pull_hdr(m, off2, &iih,
5406                            sizeof(struct icmp6_hdr), NULL, reason, pd2.af)) {
5407                                DPFPRINTF(PF_DEBUG_MISC,
5408                                    ("pf: ICMP error message too short "
5409                                    "(icmp6)\n"));
5410                                return (PF_DROP);
5411                        }
5412
5413                        key.af = pd2.af;
5414                        key.proto = IPPROTO_ICMPV6;
5415                        PF_ACPY(&key.addr[pd2.sidx], pd2.src, key.af);
5416                        PF_ACPY(&key.addr[pd2.didx], pd2.dst, key.af);
5417                        key.port[0] = key.port[1] = iih.icmp6_id;
5418
5419#ifdef __FreeBSD__
5420                        STATE_LOOKUP(kif, &key, direction, *state, m, pd->pf_mtag);
5421#else
5422                        STATE_LOOKUP(kif, &key, direction, *state, m);
5423#endif
5424
5425                        /* translate source/destination address, if necessary */
5426                        if ((*state)->key[PF_SK_WIRE] !=
5427                            (*state)->key[PF_SK_STACK]) {
5428                                struct pf_state_key *nk =
5429                                    (*state)->key[pd->didx];
5430
5431                                if (PF_ANEQ(pd2.src,
5432                                    &nk->addr[pd2.sidx], pd2.af) ||
5433                                    nk->port[pd2.sidx] != iih.icmp6_id)
5434                                        pf_change_icmp(pd2.src, &iih.icmp6_id,
5435                                            daddr, &nk->addr[pd2.sidx],
5436                                            nk->port[pd2.sidx], NULL,
5437                                            pd2.ip_sum, icmpsum,
5438                                            pd->ip_sum, 0, AF_INET6);
5439
5440                                if (PF_ANEQ(pd2.dst,
5441                                    &nk->addr[pd2.didx], pd2.af) ||
5442                                    nk->port[pd2.didx] != iih.icmp6_id)
5443                                        pf_change_icmp(pd2.dst, &iih.icmp6_id,
5444                                            NULL, /* XXX Inbound NAT? */
5445                                            &nk->addr[pd2.didx],
5446                                            nk->port[pd2.didx], NULL,
5447                                            pd2.ip_sum, icmpsum,
5448                                            pd->ip_sum, 0, AF_INET6);
5449
5450#ifdef __FreeBSD__
5451                                m_copyback(m, off, sizeof(struct icmp6_hdr),
5452                                    (caddr_t)pd->hdr.icmp6);
5453                                m_copyback(m, ipoff2, sizeof(h2_6), (caddr_t)&h2_6);
5454                                m_copyback(m, off2, sizeof(struct icmp6_hdr),
5455                                    (caddr_t)&iih);
5456#else
5457                                m_copyback(m, off, sizeof(struct icmp6_hdr),
5458                                    pd->hdr.icmp6);
5459                                m_copyback(m, ipoff2, sizeof(h2_6), &h2_6);
5460                                m_copyback(m, off2, sizeof(struct icmp6_hdr),
5461                                    &iih);
5462#endif
5463                        }
5464                        return (PF_PASS);
5465                        break;
5466                }
5467#endif /* INET6 */
5468                default: {
5469                        key.af = pd2.af;
5470                        key.proto = pd2.proto;
5471                        PF_ACPY(&key.addr[pd2.sidx], pd2.src, key.af);
5472                        PF_ACPY(&key.addr[pd2.didx], pd2.dst, key.af);
5473                        key.port[0] = key.port[1] = 0;
5474
5475#ifdef __FreeBSD__
5476                        STATE_LOOKUP(kif, &key, direction, *state, m, pd->pf_mtag);
5477#else
5478                        STATE_LOOKUP(kif, &key, direction, *state, m);
5479#endif
5480
5481                        /* translate source/destination address, if necessary */
5482                        if ((*state)->key[PF_SK_WIRE] !=
5483                            (*state)->key[PF_SK_STACK]) {
5484                                struct pf_state_key *nk =
5485                                    (*state)->key[pd->didx];
5486
5487                                if (PF_ANEQ(pd2.src,
5488                                    &nk->addr[pd2.sidx], pd2.af))
5489                                        pf_change_icmp(pd2.src, NULL, daddr,
5490                                            &nk->addr[pd2.sidx], 0, NULL,
5491                                            pd2.ip_sum, icmpsum,
5492                                            pd->ip_sum, 0, pd2.af);
5493
5494                                if (PF_ANEQ(pd2.dst,
5495                                    &nk->addr[pd2.didx], pd2.af))
5496                                        pf_change_icmp(pd2.src, NULL,
5497                                            NULL, /* XXX Inbound NAT? */
5498                                            &nk->addr[pd2.didx], 0, NULL,
5499                                            pd2.ip_sum, icmpsum,
5500                                            pd->ip_sum, 0, pd2.af);
5501
5502                                switch (pd2.af) {
5503#ifdef INET
5504                                case AF_INET:
5505#ifdef __FreeBSD__
5506                                        m_copyback(m, off, ICMP_MINLEN,
5507                                            (caddr_t)pd->hdr.icmp);
5508                                        m_copyback(m, ipoff2, sizeof(h2), (caddr_t)&h2);
5509#else
5510                                        m_copyback(m, off, ICMP_MINLEN,
5511                                            pd->hdr.icmp);
5512                                        m_copyback(m, ipoff2, sizeof(h2), &h2);
5513#endif
5514                                        break;
5515#endif /* INET */
5516#ifdef INET6
5517                                case AF_INET6:
5518                                        m_copyback(m, off,
5519                                            sizeof(struct icmp6_hdr),
5520#ifdef __FreeBSD__
5521                                            (caddr_t)
5522#endif
5523                                            pd->hdr.icmp6);
5524                                        m_copyback(m, ipoff2, sizeof(h2_6),
5525#ifdef __FreeBSD__
5526                                            (caddr_t)
5527#endif
5528                                            &h2_6);
5529                                        break;
5530#endif /* INET6 */
5531                                }
5532                        }
5533                        return (PF_PASS);
5534                        break;
5535                }
5536                }
5537        }
5538}
5539
5540int
5541pf_test_state_other(struct pf_state **state, int direction, struct pfi_kif *kif,
5542    struct mbuf *m, struct pf_pdesc *pd)
5543{
5544        struct pf_state_peer    *src, *dst;
5545        struct pf_state_key_cmp  key;
5546
5547        key.af = pd->af;
5548        key.proto = pd->proto;
5549        if (direction == PF_IN) {
5550                PF_ACPY(&key.addr[0], pd->src, key.af);
5551                PF_ACPY(&key.addr[1], pd->dst, key.af);
5552                key.port[0] = key.port[1] = 0;
5553        } else {
5554                PF_ACPY(&key.addr[1], pd->src, key.af);
5555                PF_ACPY(&key.addr[0], pd->dst, key.af);
5556                key.port[1] = key.port[0] = 0;
5557        }
5558
5559#ifdef __FreeBSD__
5560        STATE_LOOKUP(kif, &key, direction, *state, m, pd->pf_mtag);
5561#else
5562        STATE_LOOKUP(kif, &key, direction, *state, m);
5563#endif
5564
5565        if (direction == (*state)->direction) {
5566                src = &(*state)->src;
5567                dst = &(*state)->dst;
5568        } else {
5569                src = &(*state)->dst;
5570                dst = &(*state)->src;
5571        }
5572
5573        /* update states */
5574        if (src->state < PFOTHERS_SINGLE)
5575                src->state = PFOTHERS_SINGLE;
5576        if (dst->state == PFOTHERS_SINGLE)
5577                dst->state = PFOTHERS_MULTIPLE;
5578
5579        /* update expire time */
5580        (*state)->expire = time_second;
5581        if (src->state == PFOTHERS_MULTIPLE && dst->state == PFOTHERS_MULTIPLE)
5582                (*state)->timeout = PFTM_OTHER_MULTIPLE;
5583        else
5584                (*state)->timeout = PFTM_OTHER_SINGLE;
5585
5586        /* translate source/destination address, if necessary */
5587        if ((*state)->key[PF_SK_WIRE] != (*state)->key[PF_SK_STACK]) {
5588                struct pf_state_key *nk = (*state)->key[pd->didx];
5589
5590#ifdef __FreeBSD__
5591                KASSERT(nk, ("%s: nk is null", __FUNCTION__));
5592                KASSERT(pd, ("%s: pd is null", __FUNCTION__));
5593                KASSERT(pd->src, ("%s: pd->src is null", __FUNCTION__));
5594                KASSERT(pd->dst, ("%s: pd->dst is null", __FUNCTION__));
5595#else
5596                KASSERT(nk);
5597                KASSERT(pd);
5598                KASSERT(pd->src);
5599                KASSERT(pd->dst);
5600#endif
5601                switch (pd->af) {
5602#ifdef INET
5603                case AF_INET:
5604                        if (PF_ANEQ(pd->src, &nk->addr[pd->sidx], AF_INET))
5605                                pf_change_a(&pd->src->v4.s_addr,
5606                                    pd->ip_sum,
5607                                    nk->addr[pd->sidx].v4.s_addr,
5608                                    0);
5609
5610
5611                        if (PF_ANEQ(pd->dst, &nk->addr[pd->didx], AF_INET))
5612                                pf_change_a(&pd->dst->v4.s_addr,
5613                                    pd->ip_sum,
5614                                    nk->addr[pd->didx].v4.s_addr,
5615                                    0);
5616
5617                                break;
5618#endif /* INET */
5619#ifdef INET6
5620                case AF_INET6:
5621                        if (PF_ANEQ(pd->src, &nk->addr[pd->sidx], AF_INET))
5622                                PF_ACPY(pd->src, &nk->addr[pd->sidx], pd->af);
5623
5624                        if (PF_ANEQ(pd->dst, &nk->addr[pd->didx], AF_INET))
5625                                PF_ACPY(pd->dst, &nk->addr[pd->didx], pd->af);
5626#endif /* INET6 */
5627                }
5628        }
5629        return (PF_PASS);
5630}
5631
5632/*
5633 * ipoff and off are measured from the start of the mbuf chain.
5634 * h must be at "ipoff" on the mbuf chain.
5635 */
5636void *
5637pf_pull_hdr(struct mbuf *m, int off, void *p, int len,
5638    u_short *actionp, u_short *reasonp, sa_family_t af)
5639{
5640        switch (af) {
5641#ifdef INET
5642        case AF_INET: {
5643                struct ip       *h = mtod(m, struct ip *);
5644                u_int16_t        fragoff = (ntohs(h->ip_off) & IP_OFFMASK) << 3;
5645
5646                if (fragoff) {
5647                        if (fragoff >= len)
5648                                ACTION_SET(actionp, PF_PASS);
5649                        else {
5650                                ACTION_SET(actionp, PF_DROP);
5651                                REASON_SET(reasonp, PFRES_FRAG);
5652                        }
5653                        return (NULL);
5654                }
5655                if (m->m_pkthdr.len < off + len ||
5656                    ntohs(h->ip_len) < off + len) {
5657                        ACTION_SET(actionp, PF_DROP);
5658                        REASON_SET(reasonp, PFRES_SHORT);
5659                        return (NULL);
5660                }
5661                break;
5662        }
5663#endif /* INET */
5664#ifdef INET6
5665        case AF_INET6: {
5666                struct ip6_hdr  *h = mtod(m, struct ip6_hdr *);
5667
5668                if (m->m_pkthdr.len < off + len ||
5669                    (ntohs(h->ip6_plen) + sizeof(struct ip6_hdr)) <
5670                    (unsigned)(off + len)) {
5671                        ACTION_SET(actionp, PF_DROP);
5672                        REASON_SET(reasonp, PFRES_SHORT);
5673                        return (NULL);
5674                }
5675                break;
5676        }
5677#endif /* INET6 */
5678        }
5679        m_copydata(m, off, len, p);
5680        return (p);
5681}
5682
5683int
5684pf_routable(struct pf_addr *addr, sa_family_t af, struct pfi_kif *kif,
5685    int rtableid)
5686{
5687#ifdef __FreeBSD__
5688#ifdef RADIX_MPATH
5689        struct radix_node_head  *rnh;
5690#endif
5691#endif
5692        struct sockaddr_in      *dst;
5693        int                      ret = 1;
5694        int                      check_mpath;
5695#ifndef __FreeBSD__
5696        extern int               ipmultipath;
5697#endif
5698#ifdef INET6
5699#ifndef __FreeBSD__
5700        extern int               ip6_multipath;
5701#endif
5702        struct sockaddr_in6     *dst6;
5703        struct route_in6         ro;
5704#else
5705        struct route             ro;
5706#endif
5707        struct radix_node       *rn;
5708        struct rtentry          *rt;
5709        struct ifnet            *ifp;
5710
5711        check_mpath = 0;
5712#ifdef __FreeBSD__
5713#ifdef RADIX_MPATH
5714        /* XXX: stick to table 0 for now */
5715        rnh = rt_tables_get_rnh(0, af);
5716        if (rnh != NULL && rn_mpath_capable(rnh))
5717                check_mpath = 1;
5718#endif
5719#endif
5720        bzero(&ro, sizeof(ro));
5721        switch (af) {
5722        case AF_INET:
5723                dst = satosin(&ro.ro_dst);
5724                dst->sin_family = AF_INET;
5725                dst->sin_len = sizeof(*dst);
5726                dst->sin_addr = addr->v4;
5727#ifndef __FreeBSD__
5728                if (ipmultipath)
5729                        check_mpath = 1;
5730#endif
5731                break;
5732#ifdef INET6
5733        case AF_INET6:
5734                /*
5735                 * Skip check for addresses with embedded interface scope,
5736                 * as they would always match anyway.
5737                 */
5738                if (IN6_IS_SCOPE_EMBED(&addr->v6))
5739                        goto out;
5740                dst6 = (struct sockaddr_in6 *)&ro.ro_dst;
5741                dst6->sin6_family = AF_INET6;
5742                dst6->sin6_len = sizeof(*dst6);
5743                dst6->sin6_addr = addr->v6;
5744#ifndef __FreeBSD__
5745                if (ip6_multipath)
5746                        check_mpath = 1;
5747#endif
5748                break;
5749#endif /* INET6 */
5750        default:
5751                return (0);
5752        }
5753
5754        /* Skip checks for ipsec interfaces */
5755        if (kif != NULL && kif->pfik_ifp->if_type == IFT_ENC)
5756                goto out;
5757
5758#ifdef __FreeBSD__
5759        switch (af) {
5760#ifdef INET6
5761        case AF_INET6:
5762                in6_rtalloc_ign(&ro, 0, rtableid);
5763                break;
5764#endif
5765#ifdef INET
5766        case AF_INET:
5767                in_rtalloc_ign((struct route *)&ro, 0, rtableid);
5768                break;
5769#endif
5770        default:
5771                rtalloc_ign((struct route *)&ro, 0);    /* No/default FIB. */
5772                break;
5773        }
5774#else /* ! __FreeBSD__ */
5775        rtalloc_noclone((struct route *)&ro, NO_CLONING);
5776#endif
5777
5778        if (ro.ro_rt != NULL) {
5779                /* No interface given, this is a no-route check */
5780                if (kif == NULL)
5781                        goto out;
5782
5783                if (kif->pfik_ifp == NULL) {
5784                        ret = 0;
5785                        goto out;
5786                }
5787
5788                /* Perform uRPF check if passed input interface */
5789                ret = 0;
5790                rn = (struct radix_node *)ro.ro_rt;
5791                do {
5792                        rt = (struct rtentry *)rn;
5793#ifndef __FreeBSD__ /* CARPDEV */
5794                        if (rt->rt_ifp->if_type == IFT_CARP)
5795                                ifp = rt->rt_ifp->if_carpdev;
5796                        else
5797#endif
5798                                ifp = rt->rt_ifp;
5799
5800                        if (kif->pfik_ifp == ifp)
5801                                ret = 1;
5802#ifdef __FreeBSD__
5803#ifdef RADIX_MPATH
5804                        rn = rn_mpath_next(rn);
5805#endif
5806#else
5807                        rn = rn_mpath_next(rn, 0);
5808#endif
5809                } while (check_mpath == 1 && rn != NULL && ret == 0);
5810        } else
5811                ret = 0;
5812out:
5813        if (ro.ro_rt != NULL)
5814                RTFREE(ro.ro_rt);
5815        return (ret);
5816}
5817
5818int
5819pf_rtlabel_match(struct pf_addr *addr, sa_family_t af, struct pf_addr_wrap *aw,
5820    int rtableid)
5821{
5822        struct sockaddr_in      *dst;
5823#ifdef INET6
5824        struct sockaddr_in6     *dst6;
5825        struct route_in6         ro;
5826#else
5827        struct route             ro;
5828#endif
5829        int                      ret = 0;
5830
5831        bzero(&ro, sizeof(ro));
5832        switch (af) {
5833        case AF_INET:
5834                dst = satosin(&ro.ro_dst);
5835                dst->sin_family = AF_INET;
5836                dst->sin_len = sizeof(*dst);
5837                dst->sin_addr = addr->v4;
5838                break;
5839#ifdef INET6
5840        case AF_INET6:
5841                dst6 = (struct sockaddr_in6 *)&ro.ro_dst;
5842                dst6->sin6_family = AF_INET6;
5843                dst6->sin6_len = sizeof(*dst6);
5844                dst6->sin6_addr = addr->v6;
5845                break;
5846#endif /* INET6 */
5847        default:
5848                return (0);
5849        }
5850
5851#ifdef __FreeBSD__
5852        switch (af) {
5853#ifdef INET6
5854        case AF_INET6:
5855                in6_rtalloc_ign(&ro, 0, rtableid);
5856                break;
5857#endif
5858#ifdef INET
5859        case AF_INET:
5860                in_rtalloc_ign((struct route *)&ro, 0, rtableid);
5861                break;
5862#endif
5863        default:
5864                rtalloc_ign((struct route *)&ro, 0);
5865                break;
5866        }
5867#else /* ! __FreeBSD__ */
5868        rtalloc_noclone((struct route *)&ro, NO_CLONING);
5869#endif
5870
5871        if (ro.ro_rt != NULL) {
5872#ifdef __FreeBSD__
5873                /* XXX_IMPORT: later */
5874#else
5875                if (ro.ro_rt->rt_labelid == aw->v.rtlabel)
5876                        ret = 1;
5877#endif
5878                RTFREE(ro.ro_rt);
5879        }
5880
5881        return (ret);
5882}
5883
5884#ifdef INET
5885void
5886pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
5887    struct pf_state *s, struct pf_pdesc *pd)
5888{
5889        struct mbuf             *m0, *m1;
5890        struct route             iproute;
5891        struct route            *ro = NULL;
5892        struct sockaddr_in      *dst;
5893        struct ip               *ip;
5894        struct ifnet            *ifp = NULL;
5895        struct pf_addr           naddr;
5896        struct pf_src_node      *sn = NULL;
5897        int                      error = 0;
5898#ifdef __FreeBSD__
5899        int sw_csum;
5900#endif
5901#ifdef IPSEC
5902        struct m_tag            *mtag;
5903#endif /* IPSEC */
5904
5905        if (m == NULL || *m == NULL || r == NULL ||
5906            (dir != PF_IN && dir != PF_OUT) || oifp == NULL)
5907                panic("pf_route: invalid parameters");
5908
5909#ifdef __FreeBSD__
5910        if (pd->pf_mtag->routed++ > 3) {
5911#else
5912        if ((*m)->m_pkthdr.pf.routed++ > 3) {
5913#endif
5914                m0 = *m;
5915                *m = NULL;
5916                goto bad;
5917        }
5918
5919        if (r->rt == PF_DUPTO) {
5920#ifdef __FreeBSD__
5921                if ((m0 = m_dup(*m, M_DONTWAIT)) == NULL)
5922#else
5923                if ((m0 = m_copym2(*m, 0, M_COPYALL, M_NOWAIT)) == NULL)
5924#endif
5925                        return;
5926        } else {
5927                if ((r->rt == PF_REPLYTO) == (r->direction == dir))
5928                        return;
5929                m0 = *m;
5930        }
5931
5932        if (m0->m_len < sizeof(struct ip)) {
5933                DPFPRINTF(PF_DEBUG_URGENT,
5934                    ("pf_route: m0->m_len < sizeof(struct ip)\n"));
5935                goto bad;
5936        }
5937
5938        ip = mtod(m0, struct ip *);
5939
5940        ro = &iproute;
5941        bzero((caddr_t)ro, sizeof(*ro));
5942        dst = satosin(&ro->ro_dst);
5943        dst->sin_family = AF_INET;
5944        dst->sin_len = sizeof(*dst);
5945        dst->sin_addr = ip->ip_dst;
5946
5947        if (r->rt == PF_FASTROUTE) {
5948#ifdef __FreeBSD__
5949                in_rtalloc_ign(ro, 0, M_GETFIB(m0));
5950#else
5951                rtalloc(ro);
5952#endif
5953                if (ro->ro_rt == 0) {
5954#ifdef __FreeBSD__
5955                        KMOD_IPSTAT_INC(ips_noroute);
5956#else
5957                        ipstat.ips_noroute++;
5958#endif
5959                        goto bad;
5960                }
5961
5962                ifp = ro->ro_rt->rt_ifp;
5963                ro->ro_rt->rt_use++;
5964
5965                if (ro->ro_rt->rt_flags & RTF_GATEWAY)
5966                        dst = satosin(ro->ro_rt->rt_gateway);
5967        } else {
5968                if (TAILQ_EMPTY(&r->rpool.list)) {
5969                        DPFPRINTF(PF_DEBUG_URGENT,
5970                            ("pf_route: TAILQ_EMPTY(&r->rpool.list)\n"));
5971                        goto bad;
5972                }
5973                if (s == NULL) {
5974                        pf_map_addr(AF_INET, r, (struct pf_addr *)&ip->ip_src,
5975                            &naddr, NULL, &sn);
5976                        if (!PF_AZERO(&naddr, AF_INET))
5977                                dst->sin_addr.s_addr = naddr.v4.s_addr;
5978                        ifp = r->rpool.cur->kif ?
5979                            r->rpool.cur->kif->pfik_ifp : NULL;
5980                } else {
5981                        if (!PF_AZERO(&s->rt_addr, AF_INET))
5982                                dst->sin_addr.s_addr =
5983                                    s->rt_addr.v4.s_addr;
5984                        ifp = s->rt_kif ? s->rt_kif->pfik_ifp : NULL;
5985                }
5986        }
5987        if (ifp == NULL)
5988                goto bad;
5989
5990        if (oifp != ifp) {
5991#ifdef __FreeBSD__
5992                PF_UNLOCK();
5993                if (pf_test(PF_OUT, ifp, &m0, NULL, NULL) != PF_PASS) {
5994                        PF_LOCK();
5995                        goto bad;
5996                } else if (m0 == NULL) {
5997                        PF_LOCK();
5998                        goto done;
5999                }
6000                PF_LOCK();
6001#else
6002                if (pf_test(PF_OUT, ifp, &m0, NULL) != PF_PASS)
6003                        goto bad;
6004                else if (m0 == NULL)
6005                        goto done;
6006#endif
6007                if (m0->m_len < sizeof(struct ip)) {
6008                        DPFPRINTF(PF_DEBUG_URGENT,
6009                            ("pf_route: m0->m_len < sizeof(struct ip)\n"));
6010                        goto bad;
6011                }
6012                ip = mtod(m0, struct ip *);
6013        }
6014
6015#ifdef __FreeBSD__
6016        /* Copied from FreeBSD 5.1-CURRENT ip_output. */
6017        m0->m_pkthdr.csum_flags |= CSUM_IP;
6018        sw_csum = m0->m_pkthdr.csum_flags & ~ifp->if_hwassist;
6019        if (sw_csum & CSUM_DELAY_DATA) {
6020                /*
6021                 * XXX: in_delayed_cksum assumes HBO for ip->ip_len (at least)
6022                 */
6023                NTOHS(ip->ip_len);
6024                NTOHS(ip->ip_off);      /* XXX: needed? */
6025                in_delayed_cksum(m0);
6026                HTONS(ip->ip_len);
6027                HTONS(ip->ip_off);
6028                sw_csum &= ~CSUM_DELAY_DATA;
6029        }
6030        m0->m_pkthdr.csum_flags &= ifp->if_hwassist;
6031
6032        if (ntohs(ip->ip_len) <= ifp->if_mtu ||
6033            (ifp->if_hwassist & CSUM_FRAGMENT &&
6034            ((ip->ip_off & htons(IP_DF)) == 0))) {
6035                /*
6036                 * ip->ip_len = htons(ip->ip_len);
6037                 * ip->ip_off = htons(ip->ip_off);
6038                 */
6039                ip->ip_sum = 0;
6040                if (sw_csum & CSUM_DELAY_IP) {
6041                        /* From KAME */
6042                        if (ip->ip_v == IPVERSION &&
6043                            (ip->ip_hl << 2) == sizeof(*ip)) {
6044                                ip->ip_sum = in_cksum_hdr(ip);
6045                        } else {
6046                                ip->ip_sum = in_cksum(m0, ip->ip_hl << 2);
6047                        }
6048                }
6049                PF_UNLOCK();
6050                error = (*ifp->if_output)(ifp, m0, sintosa(dst), ro);
6051                PF_LOCK();
6052                goto done;
6053        }
6054#else
6055        /* Copied from ip_output. */
6056#ifdef IPSEC
6057        /*
6058         * If deferred crypto processing is needed, check that the
6059         * interface supports it.
6060         */
6061        if ((mtag = m_tag_find(m0, PACKET_TAG_IPSEC_OUT_CRYPTO_NEEDED, NULL))
6062            != NULL && (ifp->if_capabilities & IFCAP_IPSEC) == 0) {
6063                /* Notify IPsec to do its own crypto. */
6064                ipsp_skipcrypto_unmark((struct tdb_ident *)(mtag + 1));
6065                goto bad;
6066        }
6067#endif /* IPSEC */
6068
6069        /* Catch routing changes wrt. hardware checksumming for TCP or UDP. */
6070        if (m0->m_pkthdr.csum_flags & M_TCPV4_CSUM_OUT) {
6071                if (!(ifp->if_capabilities & IFCAP_CSUM_TCPv4) ||
6072                    ifp->if_bridge != NULL) {
6073                        in_delayed_cksum(m0);
6074                        m0->m_pkthdr.csum_flags &= ~M_TCPV4_CSUM_OUT; /* Clr */
6075                }
6076        } else if (m0->m_pkthdr.csum_flags & M_UDPV4_CSUM_OUT) {
6077                if (!(ifp->if_capabilities & IFCAP_CSUM_UDPv4) ||
6078                    ifp->if_bridge != NULL) {
6079                        in_delayed_cksum(m0);
6080                        m0->m_pkthdr.csum_flags &= ~M_UDPV4_CSUM_OUT; /* Clr */
6081                }
6082        }
6083
6084        if (ntohs(ip->ip_len) <= ifp->if_mtu) {
6085                ip->ip_sum = 0;
6086                if ((ifp->if_capabilities & IFCAP_CSUM_IPv4) &&
6087                    ifp->if_bridge == NULL) {
6088                        m0->m_pkthdr.csum_flags |= M_IPV4_CSUM_OUT;
6089#ifdef __FreeBSD__
6090                        KMOD_IPSTAT_INC(ips_outhwcsum);
6091#else
6092                        ipstat.ips_outhwcsum++;
6093#endif
6094                } else
6095                        ip->ip_sum = in_cksum(m0, ip->ip_hl << 2);
6096                /* Update relevant hardware checksum stats for TCP/UDP */
6097                if (m0->m_pkthdr.csum_flags & M_TCPV4_CSUM_OUT)
6098                        KMOD_TCPSTAT_INC(tcps_outhwcsum);
6099                else if (m0->m_pkthdr.csum_flags & M_UDPV4_CSUM_OUT)
6100                        KMOD_UDPSTAT_INC(udps_outhwcsum);
6101                error = (*ifp->if_output)(ifp, m0, sintosa(dst), NULL);
6102                goto done;
6103        }
6104#endif
6105
6106        /*
6107         * Too large for interface; fragment if possible.
6108         * Must be able to put at least 8 bytes per fragment.
6109         */
6110        if (ip->ip_off & htons(IP_DF)) {
6111#ifdef __FreeBSD__
6112                KMOD_IPSTAT_INC(ips_cantfrag);
6113#else
6114                ipstat.ips_cantfrag++;
6115#endif
6116                if (r->rt != PF_DUPTO) {
6117#ifdef __FreeBSD__
6118                        /* icmp_error() expects host byte ordering */
6119                        NTOHS(ip->ip_len);
6120                        NTOHS(ip->ip_off);
6121                        PF_UNLOCK();
6122                        icmp_error(m0, ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG, 0,
6123                            ifp->if_mtu);
6124                        PF_LOCK();
6125#else
6126                        icmp_error(m0, ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG, 0,
6127                            ifp->if_mtu);
6128#endif
6129                        goto done;
6130                } else
6131                        goto bad;
6132        }
6133
6134        m1 = m0;
6135#ifdef __FreeBSD__
6136        /*
6137         * XXX: is cheaper + less error prone than own function
6138         */
6139        NTOHS(ip->ip_len);
6140        NTOHS(ip->ip_off);
6141        error = ip_fragment(ip, &m0, ifp->if_mtu, ifp->if_hwassist, sw_csum);
6142#else
6143        error = ip_fragment(m0, ifp, ifp->if_mtu);
6144#endif
6145        if (error) {
6146#ifndef __FreeBSD__    /* ip_fragment does not do m_freem() on FreeBSD */
6147                m0 = NULL;
6148#endif
6149                goto bad;
6150        }
6151
6152        for (m0 = m1; m0; m0 = m1) {
6153                m1 = m0->m_nextpkt;
6154                m0->m_nextpkt = 0;
6155#ifdef __FreeBSD__
6156                if (error == 0) {
6157                        PF_UNLOCK();
6158                        error = (*ifp->if_output)(ifp, m0, sintosa(dst),
6159                            NULL);
6160                        PF_LOCK();
6161                } else
6162#else
6163                if (error == 0)
6164                        error = (*ifp->if_output)(ifp, m0, sintosa(dst),
6165                            NULL);
6166                else
6167#endif
6168                        m_freem(m0);
6169        }
6170
6171        if (error == 0)
6172#ifdef __FreeBSD__
6173                KMOD_IPSTAT_INC(ips_fragmented);
6174#else
6175                ipstat.ips_fragmented++;
6176#endif
6177
6178done:
6179        if (r->rt != PF_DUPTO)
6180                *m = NULL;
6181        if (ro == &iproute && ro->ro_rt)
6182                RTFREE(ro->ro_rt);
6183        return;
6184
6185bad:
6186        m_freem(m0);
6187        goto done;
6188}
6189#endif /* INET */
6190
6191#ifdef INET6
6192void
6193pf_route6(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
6194    struct pf_state *s, struct pf_pdesc *pd)
6195{
6196        struct mbuf             *m0;
6197        struct route_in6         ip6route;
6198        struct route_in6        *ro;
6199        struct sockaddr_in6     *dst;
6200        struct ip6_hdr          *ip6;
6201        struct ifnet            *ifp = NULL;
6202        struct pf_addr           naddr;
6203        struct pf_src_node      *sn = NULL;
6204
6205        if (m == NULL || *m == NULL || r == NULL ||
6206            (dir != PF_IN && dir != PF_OUT) || oifp == NULL)
6207                panic("pf_route6: invalid parameters");
6208
6209#ifdef __FreeBSD__
6210        if (pd->pf_mtag->routed++ > 3) {
6211#else
6212        if ((*m)->m_pkthdr.pf.routed++ > 3) {
6213#endif
6214                m0 = *m;
6215                *m = NULL;
6216                goto bad;
6217        }
6218
6219        if (r->rt == PF_DUPTO) {
6220#ifdef __FreeBSD__
6221                if ((m0 = m_dup(*m, M_DONTWAIT)) == NULL)
6222#else
6223                if ((m0 = m_copym2(*m, 0, M_COPYALL, M_NOWAIT)) == NULL)
6224#endif
6225                        return;
6226        } else {
6227                if ((r->rt == PF_REPLYTO) == (r->direction == dir))
6228                        return;
6229                m0 = *m;
6230        }
6231
6232        if (m0->m_len < sizeof(struct ip6_hdr)) {
6233                DPFPRINTF(PF_DEBUG_URGENT,
6234                    ("pf_route6: m0->m_len < sizeof(struct ip6_hdr)\n"));
6235                goto bad;
6236        }
6237        ip6 = mtod(m0, struct ip6_hdr *);
6238
6239        ro = &ip6route;
6240        bzero((caddr_t)ro, sizeof(*ro));
6241        dst = (struct sockaddr_in6 *)&ro->ro_dst;
6242        dst->sin6_family = AF_INET6;
6243        dst->sin6_len = sizeof(*dst);
6244        dst->sin6_addr = ip6->ip6_dst;
6245
6246        /* Cheat. XXX why only in the v6 case??? */
6247        if (r->rt == PF_FASTROUTE) {
6248#ifdef __FreeBSD__
6249                m0->m_flags |= M_SKIP_FIREWALL;
6250                PF_UNLOCK();
6251                ip6_output(m0, NULL, NULL, 0, NULL, NULL, NULL);
6252#else
6253                m0->m_pkthdr.pf.flags |= PF_TAG_GENERATED;
6254                ip6_output(m0, NULL, NULL, 0, NULL, NULL, NULL);
6255#endif
6256                return;
6257        }
6258
6259        if (TAILQ_EMPTY(&r->rpool.list)) {
6260                DPFPRINTF(PF_DEBUG_URGENT,
6261                    ("pf_route6: TAILQ_EMPTY(&r->rpool.list)\n"));
6262                goto bad;
6263        }
6264        if (s == NULL) {
6265                pf_map_addr(AF_INET6, r, (struct pf_addr *)&ip6->ip6_src,
6266                    &naddr, NULL, &sn);
6267                if (!PF_AZERO(&naddr, AF_INET6))
6268                        PF_ACPY((struct pf_addr *)&dst->sin6_addr,
6269                            &naddr, AF_INET6);
6270                ifp = r->rpool.cur->kif ? r->rpool.cur->kif->pfik_ifp : NULL;
6271        } else {
6272                if (!PF_AZERO(&s->rt_addr, AF_INET6))
6273                        PF_ACPY((struct pf_addr *)&dst->sin6_addr,
6274                            &s->rt_addr, AF_INET6);
6275                ifp = s->rt_kif ? s->rt_kif->pfik_ifp : NULL;
6276        }
6277        if (ifp == NULL)
6278                goto bad;
6279
6280        if (oifp != ifp) {
6281#ifdef __FreeBSD__
6282                PF_UNLOCK();
6283                if (pf_test6(PF_OUT, ifp, &m0, NULL, NULL) != PF_PASS) {
6284                        PF_LOCK();
6285                        goto bad;
6286                } else if (m0 == NULL) {
6287                        PF_LOCK();
6288                        goto done;
6289                }
6290                PF_LOCK();
6291#else
6292                if (pf_test6(PF_OUT, ifp, &m0, NULL) != PF_PASS)
6293                        goto bad;
6294                else if (m0 == NULL)
6295                        goto done;
6296#endif
6297                if (m0->m_len < sizeof(struct ip6_hdr)) {
6298                        DPFPRINTF(PF_DEBUG_URGENT,
6299                            ("pf_route6: m0->m_len < sizeof(struct ip6_hdr)\n"));
6300                        goto bad;
6301                }
6302                ip6 = mtod(m0, struct ip6_hdr *);
6303        }
6304
6305        /*
6306         * If the packet is too large for the outgoing interface,
6307         * send back an icmp6 error.
6308         */
6309        if (IN6_IS_SCOPE_EMBED(&dst->sin6_addr))
6310                dst->sin6_addr.s6_addr16[1] = htons(ifp->if_index);
6311        if ((u_long)m0->m_pkthdr.len <= ifp->if_mtu) {
6312#ifdef __FreeBSD__
6313                PF_UNLOCK();
6314#endif
6315                nd6_output(ifp, ifp, m0, dst, NULL);
6316#ifdef __FreeBSD__
6317                PF_LOCK();
6318#endif
6319        } else {
6320                in6_ifstat_inc(ifp, ifs6_in_toobig);
6321#ifdef __FreeBSD__
6322                if (r->rt != PF_DUPTO) {
6323                        PF_UNLOCK();
6324                        icmp6_error(m0, ICMP6_PACKET_TOO_BIG, 0, ifp->if_mtu);
6325                        PF_LOCK();
6326                } else
6327#else
6328                if (r->rt != PF_DUPTO)
6329                        icmp6_error(m0, ICMP6_PACKET_TOO_BIG, 0, ifp->if_mtu);
6330                else
6331#endif
6332                        goto bad;
6333        }
6334
6335done:
6336        if (r->rt != PF_DUPTO)
6337                *m = NULL;
6338        return;
6339
6340bad:
6341        m_freem(m0);
6342        goto done;
6343}
6344#endif /* INET6 */
6345
6346#ifdef __FreeBSD__
6347/*
6348 * FreeBSD supports cksum offloads for the following drivers.
6349 *  em(4), fxp(4), ixgb(4), lge(4), ndis(4), nge(4), re(4),
6350 *   ti(4), txp(4), xl(4)
6351 *
6352 * CSUM_DATA_VALID | CSUM_PSEUDO_HDR :
6353 *  network driver performed cksum including pseudo header, need to verify
6354 *   csum_data
6355 * CSUM_DATA_VALID :
6356 *  network driver performed cksum, needs to additional pseudo header
6357 *  cksum computation with partial csum_data(i.e. lack of H/W support for
6358 *  pseudo header, for instance hme(4), sk(4) and possibly gem(4))
6359 *
6360 * After validating the cksum of packet, set both flag CSUM_DATA_VALID and
6361 * CSUM_PSEUDO_HDR in order to avoid recomputation of the cksum in upper
6362 * TCP/UDP layer.
6363 * Also, set csum_data to 0xffff to force cksum validation.
6364 */
6365int
6366pf_check_proto_cksum(struct mbuf *m, int off, int len, u_int8_t p, sa_family_t af)
6367{
6368        u_int16_t sum = 0;
6369        int hw_assist = 0;
6370        struct ip *ip;
6371
6372        if (off < sizeof(struct ip) || len < sizeof(struct udphdr))
6373                return (1);
6374        if (m->m_pkthdr.len < off + len)
6375                return (1);
6376
6377        switch (p) {
6378        case IPPROTO_TCP:
6379                if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID) {
6380                        if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR) {
6381                                sum = m->m_pkthdr.csum_data;
6382                        } else {
6383                                ip = mtod(m, struct ip *);
6384                                sum = in_pseudo(ip->ip_src.s_addr,
6385                                ip->ip_dst.s_addr, htonl((u_short)len +
6386                                m->m_pkthdr.csum_data + IPPROTO_TCP));
6387                        }
6388                        sum ^= 0xffff;
6389                        ++hw_assist;
6390                }
6391                break;
6392        case IPPROTO_UDP:
6393                if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID) {
6394                        if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR) {
6395                                sum = m->m_pkthdr.csum_data;
6396                        } else {
6397                                ip = mtod(m, struct ip *);
6398                                sum = in_pseudo(ip->ip_src.s_addr,
6399                                ip->ip_dst.s_addr, htonl((u_short)len +
6400                                m->m_pkthdr.csum_data + IPPROTO_UDP));
6401                        }
6402                        sum ^= 0xffff;
6403                        ++hw_assist;
6404                }
6405                break;
6406        case IPPROTO_ICMP:
6407#ifdef INET6
6408        case IPPROTO_ICMPV6:
6409#endif /* INET6 */
6410                break;
6411        default:
6412                return (1);
6413        }
6414
6415        if (!hw_assist) {
6416                switch (af) {
6417                case AF_INET:
6418                        if (p == IPPROTO_ICMP) {
6419                                if (m->m_len < off)
6420                                        return (1);
6421                                m->m_data += off;
6422                                m->m_len -= off;
6423                                sum = in_cksum(m, len);
6424                                m->m_data -= off;
6425                                m->m_len += off;
6426                        } else {
6427                                if (m->m_len < sizeof(struct ip))
6428                                        return (1);
6429                                sum = in4_cksum(m, p, off, len);
6430                        }
6431                        break;
6432#ifdef INET6
6433                case AF_INET6:
6434                        if (m->m_len < sizeof(struct ip6_hdr))
6435                                return (1);
6436                        sum = in6_cksum(m, p, off, len);
6437                        break;
6438#endif /* INET6 */
6439                default:
6440                        return (1);
6441                }
6442        }
6443        if (sum) {
6444                switch (p) {
6445                case IPPROTO_TCP:
6446                    {
6447                        KMOD_TCPSTAT_INC(tcps_rcvbadsum);
6448                        break;
6449                    }
6450                case IPPROTO_UDP:
6451                    {
6452                        KMOD_UDPSTAT_INC(udps_badsum);
6453                        break;
6454                    }
6455#ifdef INET
6456                case IPPROTO_ICMP:
6457                    {
6458                        KMOD_ICMPSTAT_INC(icps_checksum);
6459                        break;
6460                    }
6461#endif
6462#ifdef INET6
6463                case IPPROTO_ICMPV6:
6464                    {
6465                        KMOD_ICMP6STAT_INC(icp6s_checksum);
6466                        break;
6467                    }
6468#endif /* INET6 */
6469                }
6470                return (1);
6471        } else {
6472                if (p == IPPROTO_TCP || p == IPPROTO_UDP) {
6473                        m->m_pkthdr.csum_flags |=
6474                            (CSUM_DATA_VALID | CSUM_PSEUDO_HDR);
6475                        m->m_pkthdr.csum_data = 0xffff;
6476                }
6477        }
6478        return (0);
6479}
6480#else /* !__FreeBSD__ */
6481
6482/*
6483 * check protocol (tcp/udp/icmp/icmp6) checksum and set mbuf flag
6484 *   off is the offset where the protocol header starts
6485 *   len is the total length of protocol header plus payload
6486 * returns 0 when the checksum is valid, otherwise returns 1.
6487 */
6488int
6489pf_check_proto_cksum(struct mbuf *m, int off, int len, u_int8_t p,
6490    sa_family_t af)
6491{
6492        u_int16_t flag_ok, flag_bad;
6493        u_int16_t sum;
6494
6495        switch (p) {
6496        case IPPROTO_TCP:
6497                flag_ok = M_TCP_CSUM_IN_OK;
6498                flag_bad = M_TCP_CSUM_IN_BAD;
6499                break;
6500        case IPPROTO_UDP:
6501                flag_ok = M_UDP_CSUM_IN_OK;
6502                flag_bad = M_UDP_CSUM_IN_BAD;
6503                break;
6504        case IPPROTO_ICMP:
6505#ifdef INET6
6506        case IPPROTO_ICMPV6:
6507#endif /* INET6 */
6508                flag_ok = flag_bad = 0;
6509                break;
6510        default:
6511                return (1);
6512        }
6513        if (m->m_pkthdr.csum_flags & flag_ok)
6514                return (0);
6515        if (m->m_pkthdr.csum_flags & flag_bad)
6516                return (1);
6517        if (off < sizeof(struct ip) || len < sizeof(struct udphdr))
6518                return (1);
6519        if (m->m_pkthdr.len < off + len)
6520                return (1);
6521        switch (af) {
6522#ifdef INET
6523        case AF_INET:
6524                if (p == IPPROTO_ICMP) {
6525                        if (m->m_len < off)
6526                                return (1);
6527                        m->m_data += off;
6528                        m->m_len -= off;
6529                        sum = in_cksum(m, len);
6530                        m->m_data -= off;
6531                        m->m_len += off;
6532                } else {
6533                        if (m->m_len < sizeof(struct ip))
6534                                return (1);
6535                        sum = in4_cksum(m, p, off, len);
6536                }
6537                break;
6538#endif /* INET */
6539#ifdef INET6
6540        case AF_INET6:
6541                if (m->m_len < sizeof(struct ip6_hdr))
6542                        return (1);
6543                sum = in6_cksum(m, p, off, len);
6544                break;
6545#endif /* INET6 */
6546        default:
6547                return (1);
6548        }
6549        if (sum) {
6550                m->m_pkthdr.csum_flags |= flag_bad;
6551                switch (p) {
6552                case IPPROTO_TCP:
6553                        KMOD_TCPSTAT_INC(tcps_rcvbadsum);
6554                        break;
6555                case IPPROTO_UDP:
6556                        KMOD_UDPSTAT_INC(udps_badsum);
6557                        break;
6558#ifdef INET
6559                case IPPROTO_ICMP:
6560                        KMOD_ICMPSTAT_INC(icps_checksum);
6561                        break;
6562#endif
6563#ifdef INET6
6564                case IPPROTO_ICMPV6:
6565                        KMOD_ICMP6STAT_INC(icp6s_checksum);
6566                        break;
6567#endif /* INET6 */
6568                }
6569                return (1);
6570        }
6571        m->m_pkthdr.csum_flags |= flag_ok;
6572        return (0);
6573}
6574#endif
6575
6576#ifndef __FreeBSD__
6577struct pf_divert *
6578pf_find_divert(struct mbuf *m)
6579{
6580        struct m_tag    *mtag;
6581
6582        if ((mtag = m_tag_find(m, PACKET_TAG_PF_DIVERT, NULL)) == NULL)
6583                return (NULL);
6584
6585        return ((struct pf_divert *)(mtag + 1));
6586}
6587
6588struct pf_divert *
6589pf_get_divert(struct mbuf *m)
6590{
6591        struct m_tag    *mtag;
6592
6593        if ((mtag = m_tag_find(m, PACKET_TAG_PF_DIVERT, NULL)) == NULL) {
6594                mtag = m_tag_get(PACKET_TAG_PF_DIVERT, sizeof(struct pf_divert),
6595                    M_NOWAIT);
6596                if (mtag == NULL)
6597                        return (NULL);
6598                bzero(mtag + 1, sizeof(struct pf_divert));
6599                m_tag_prepend(m, mtag);
6600        }
6601
6602        return ((struct pf_divert *)(mtag + 1));
6603}
6604#endif
6605
6606#ifdef INET
6607int
6608#ifdef __FreeBSD__
6609pf_test(int dir, struct ifnet *ifp, struct mbuf **m0,
6610    struct ether_header *eh, struct inpcb *inp)
6611#else
6612pf_test(int dir, struct ifnet *ifp, struct mbuf **m0,
6613    struct ether_header *eh)
6614#endif
6615{
6616        struct pfi_kif          *kif;
6617        u_short                  action, reason = 0, log = 0;
6618        struct mbuf             *m = *m0;
6619#ifdef __FreeBSD__
6620        struct ip               *h = NULL;
6621        struct m_tag            *ipfwtag;
6622        struct pf_rule          *a = NULL, *r = &V_pf_default_rule, *tr, *nr;
6623#else
6624        struct ip               *h;
6625        struct pf_rule          *a = NULL, *r = &pf_default_rule, *tr, *nr;
6626#endif
6627        struct pf_state         *s = NULL;
6628        struct pf_ruleset       *ruleset = NULL;
6629        struct pf_pdesc          pd;
6630        int                      off, dirndx, pqid = 0;
6631
6632#ifdef __FreeBSD__
6633        PF_LOCK();
6634        if (!V_pf_status.running)
6635        {
6636                PF_UNLOCK();
6637                return (PF_PASS);
6638        }
6639#else
6640        if (!pf_status.running)
6641                return (PF_PASS);
6642#endif
6643
6644        memset(&pd, 0, sizeof(pd));
6645#ifdef __FreeBSD__
6646        if ((pd.pf_mtag = pf_get_mtag(m)) == NULL) {
6647                PF_UNLOCK();
6648                DPFPRINTF(PF_DEBUG_URGENT,
6649                    ("pf_test: pf_get_mtag returned NULL\n"));
6650                return (PF_DROP);
6651        }
6652#endif
6653#ifndef __FreeBSD__
6654        if (ifp->if_type == IFT_CARP && ifp->if_carpdev)
6655                kif = (struct pfi_kif *)ifp->if_carpdev->if_pf_kif;
6656        else
6657#endif
6658                kif = (struct pfi_kif *)ifp->if_pf_kif;
6659
6660        if (kif == NULL) {
6661#ifdef __FreeBSD__
6662                PF_UNLOCK();
6663#endif
6664                DPFPRINTF(PF_DEBUG_URGENT,
6665                    ("pf_test: kif == NULL, if_xname %s\n", ifp->if_xname));
6666                return (PF_DROP);
6667        }
6668        if (kif->pfik_flags & PFI_IFLAG_SKIP)
6669#ifdef __FreeBSD__
6670        {
6671                PF_UNLOCK();
6672#endif
6673                return (PF_PASS);
6674#ifdef __FreeBSD__
6675        }
6676#endif
6677
6678#ifdef __FreeBSD__
6679        M_ASSERTPKTHDR(m);
6680#else
6681#ifdef DIAGNOSTIC
6682        if ((m->m_flags & M_PKTHDR) == 0)
6683                panic("non-M_PKTHDR is passed to pf_test");
6684#endif /* DIAGNOSTIC */
6685#endif
6686
6687        if (m->m_pkthdr.len < (int)sizeof(*h)) {
6688                action = PF_DROP;
6689                REASON_SET(&reason, PFRES_SHORT);
6690                log = 1;
6691                goto done;
6692        }
6693
6694#ifdef __FreeBSD__
6695        if (m->m_flags & M_SKIP_FIREWALL) {
6696                PF_UNLOCK();
6697                return (PF_PASS);
6698        }
6699#else
6700        if (m->m_pkthdr.pf.flags & PF_TAG_GENERATED)
6701                return (PF_PASS);
6702#endif
6703       
6704#ifdef __FreeBSD__
6705        if (ip_divert_ptr != NULL &&
6706            ((ipfwtag = m_tag_locate(m, MTAG_IPFW_RULE, 0, NULL)) != NULL)) {
6707                struct ipfw_rule_ref *rr = (struct ipfw_rule_ref *)(ipfwtag+1);
6708                if (rr->info & IPFW_IS_DIVERT && rr->rulenum == 0) {
6709                        pd.pf_mtag->flags |= PF_PACKET_LOOPED;
6710                        m_tag_delete(m, ipfwtag);
6711                }
6712                if (pd.pf_mtag->flags & PF_FASTFWD_OURS_PRESENT) {
6713                        m->m_flags |= M_FASTFWD_OURS;
6714                        pd.pf_mtag->flags &= ~PF_FASTFWD_OURS_PRESENT;
6715                }
6716        } else
6717#endif
6718        /* We do IP header normalization and packet reassembly here */
6719        if (pf_normalize_ip(m0, dir, kif, &reason, &pd) != PF_PASS) {
6720                action = PF_DROP;
6721                goto done;
6722        }
6723        m = *m0;        /* pf_normalize messes with m0 */
6724        h = mtod(m, struct ip *);
6725
6726        off = h->ip_hl << 2;
6727        if (off < (int)sizeof(*h)) {
6728                action = PF_DROP;
6729                REASON_SET(&reason, PFRES_SHORT);
6730                log = 1;
6731                goto done;
6732        }
6733
6734        pd.src = (struct pf_addr *)&h->ip_src;
6735        pd.dst = (struct pf_addr *)&h->ip_dst;
6736        pd.sport = pd.dport = NULL;
6737        pd.ip_sum = &h->ip_sum;
6738        pd.proto_sum = NULL;
6739        pd.proto = h->ip_p;
6740        pd.dir = dir;
6741        pd.sidx = (dir == PF_IN) ? 0 : 1;
6742        pd.didx = (dir == PF_IN) ? 1 : 0;
6743        pd.af = AF_INET;
6744        pd.tos = h->ip_tos;
6745        pd.tot_len = ntohs(h->ip_len);
6746        pd.eh = eh;
6747
6748        /* handle fragments that didn't get reassembled by normalization */
6749        if (h->ip_off & htons(IP_MF | IP_OFFMASK)) {
6750                action = pf_test_fragment(&r, dir, kif, m, h,
6751                    &pd, &a, &ruleset);
6752                goto done;
6753        }
6754
6755        switch (h->ip_p) {
6756
6757        case IPPROTO_TCP: {
6758                struct tcphdr   th;
6759
6760                pd.hdr.tcp = &th;
6761                if (!pf_pull_hdr(m, off, &th, sizeof(th),
6762                    &action, &reason, AF_INET)) {
6763                        log = action != PF_PASS;
6764                        goto done;
6765                }
6766                pd.p_len = pd.tot_len - off - (th.th_off << 2);
6767                if ((th.th_flags & TH_ACK) && pd.p_len == 0)
6768                        pqid = 1;
6769                action = pf_normalize_tcp(dir, kif, m, 0, off, h, &pd);
6770                if (action == PF_DROP)
6771                        goto done;
6772                action = pf_test_state_tcp(&s, dir, kif, m, off, h, &pd,
6773                    &reason);
6774                if (action == PF_PASS) {
6775#if NPFSYNC > 0
6776#ifdef __FreeBSD__
6777                        if (pfsync_update_state_ptr != NULL)
6778                                pfsync_update_state_ptr(s);
6779#else
6780                        pfsync_update_state(s);
6781#endif
6782#endif /* NPFSYNC */
6783                        r = s->rule.ptr;
6784                        a = s->anchor.ptr;
6785                        log = s->log;
6786                } else if (s == NULL)
6787#ifdef __FreeBSD__
6788                        action = pf_test_rule(&r, &s, dir, kif,
6789                            m, off, h, &pd, &a, &ruleset, NULL, inp);
6790#else
6791                        action = pf_test_rule(&r, &s, dir, kif,
6792                            m, off, h, &pd, &a, &ruleset, &ipintrq);
6793#endif
6794                break;
6795        }
6796
6797        case IPPROTO_UDP: {
6798                struct udphdr   uh;
6799
6800                pd.hdr.udp = &uh;
6801                if (!pf_pull_hdr(m, off, &uh, sizeof(uh),
6802                    &action, &reason, AF_INET)) {
6803                        log = action != PF_PASS;
6804                        goto done;
6805                }
6806                if (uh.uh_dport == 0 ||
6807                    ntohs(uh.uh_ulen) > m->m_pkthdr.len - off ||
6808                    ntohs(uh.uh_ulen) < sizeof(struct udphdr)) {
6809                        action = PF_DROP;
6810                        REASON_SET(&reason, PFRES_SHORT);
6811                        goto done;
6812                }
6813                action = pf_test_state_udp(&s, dir, kif, m, off, h, &pd);
6814                if (action == PF_PASS) {
6815#if NPFSYNC > 0
6816#ifdef __FreeBSD__
6817                        if (pfsync_update_state_ptr != NULL)
6818                                pfsync_update_state_ptr(s);
6819#else
6820                        pfsync_update_state(s);
6821#endif
6822#endif /* NPFSYNC */
6823                        r = s->rule.ptr;
6824                        a = s->anchor.ptr;
6825                        log = s->log;
6826                } else if (s == NULL)
6827#ifdef __FreeBSD__
6828                        action = pf_test_rule(&r, &s, dir, kif,
6829                            m, off, h, &pd, &a, &ruleset, NULL, inp);
6830#else
6831                        action = pf_test_rule(&r, &s, dir, kif,
6832                            m, off, h, &pd, &a, &ruleset, &ipintrq);
6833#endif
6834                break;
6835        }
6836
6837        case IPPROTO_ICMP: {
6838                struct icmp     ih;
6839
6840                pd.hdr.icmp = &ih;
6841                if (!pf_pull_hdr(m, off, &ih, ICMP_MINLEN,
6842                    &action, &reason, AF_INET)) {
6843                        log = action != PF_PASS;
6844                        goto done;
6845                }
6846                action = pf_test_state_icmp(&s, dir, kif, m, off, h, &pd,
6847                    &reason);
6848                if (action == PF_PASS) {
6849#if NPFSYNC > 0
6850#ifdef __FreeBSD__
6851                        if (pfsync_update_state_ptr != NULL)
6852                                pfsync_update_state_ptr(s);
6853#else
6854                        pfsync_update_state(s);
6855#endif
6856#endif /* NPFSYNC */
6857                        r = s->rule.ptr;
6858                        a = s->anchor.ptr;
6859                        log = s->log;
6860                } else if (s == NULL)
6861#ifdef __FreeBSD__
6862                        action = pf_test_rule(&r, &s, dir, kif,
6863                            m, off, h, &pd, &a, &ruleset, NULL, inp);
6864#else
6865                        action = pf_test_rule(&r, &s, dir, kif,
6866                            m, off, h, &pd, &a, &ruleset, &ipintrq);
6867#endif
6868                break;
6869        }
6870
6871#ifdef INET6
6872        case IPPROTO_ICMPV6: {
6873                action = PF_DROP;
6874                DPFPRINTF(PF_DEBUG_MISC,
6875                    ("pf: dropping IPv4 packet with ICMPv6 payload\n"));
6876                goto done;
6877        }
6878#endif
6879
6880        default:
6881                action = pf_test_state_other(&s, dir, kif, m, &pd);
6882                if (action == PF_PASS) {
6883#if NPFSYNC > 0
6884#ifdef __FreeBSD__
6885                        if (pfsync_update_state_ptr != NULL)
6886                                pfsync_update_state_ptr(s);
6887#else
6888                        pfsync_update_state(s);
6889#endif
6890#endif /* NPFSYNC */
6891                        r = s->rule.ptr;
6892                        a = s->anchor.ptr;
6893                        log = s->log;
6894                } else if (s == NULL)
6895#ifdef __FreeBSD__
6896                        action = pf_test_rule(&r, &s, dir, kif, m, off, h,
6897                            &pd, &a, &ruleset, NULL, inp);
6898#else
6899                        action = pf_test_rule(&r, &s, dir, kif, m, off, h,
6900                            &pd, &a, &ruleset, &ipintrq);
6901#endif
6902                break;
6903        }
6904
6905done:
6906        if (action == PF_PASS && h->ip_hl > 5 &&
6907            !((s && s->state_flags & PFSTATE_ALLOWOPTS) || r->allow_opts)) {
6908                action = PF_DROP;
6909                REASON_SET(&reason, PFRES_IPOPTIONS);
6910                log = 1;
6911                DPFPRINTF(PF_DEBUG_MISC,
6912                    ("pf: dropping packet with ip options\n"));
6913        }
6914
6915        if ((s && s->tag) || r->rtableid >= 0)
6916#ifdef __FreeBSD__
6917                pf_tag_packet(m, s ? s->tag : 0, r->rtableid, pd.pf_mtag);
6918#else
6919                pf_tag_packet(m, s ? s->tag : 0, r->rtableid);
6920#endif
6921
6922        if (dir == PF_IN && s && s->key[PF_SK_STACK])
6923#ifdef __FreeBSD__
6924                pd.pf_mtag->statekey = s->key[PF_SK_STACK];
6925#else
6926                m->m_pkthdr.pf.statekey = s->key[PF_SK_STACK];
6927#endif
6928
6929#ifdef ALTQ
6930        if (action == PF_PASS && r->qid) {
6931#ifdef __FreeBSD__
6932                if (pqid || (pd.tos & IPTOS_LOWDELAY))
6933                        pd.pf_mtag->qid = r->pqid;
6934                else
6935                        pd.pf_mtag->qid = r->qid;
6936                /* add hints for ecn */
6937                pd.pf_mtag->hdr = h;
6938
6939#else
6940                if (pqid || (pd.tos & IPTOS_LOWDELAY))
6941                        m->m_pkthdr.pf.qid = r->pqid;
6942                else
6943                        m->m_pkthdr.pf.qid = r->qid;
6944                /* add hints for ecn */
6945                m->m_pkthdr.pf.hdr = h;
6946#endif
6947        }
6948#endif /* ALTQ */
6949
6950        /*
6951         * connections redirected to loopback should not match sockets
6952         * bound specifically to loopback due to security implications,
6953         * see tcp_input() and in_pcblookup_listen().
6954         */
6955        if (dir == PF_IN && action == PF_PASS && (pd.proto == IPPROTO_TCP ||
6956            pd.proto == IPPROTO_UDP) && s != NULL && s->nat_rule.ptr != NULL &&
6957            (s->nat_rule.ptr->action == PF_RDR ||
6958            s->nat_rule.ptr->action == PF_BINAT) &&
6959            (ntohl(pd.dst->v4.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET)
6960#ifdef __FreeBSD__
6961                m->m_flags |= M_SKIP_FIREWALL;
6962#else
6963                m->m_pkthdr.pf.flags |= PF_TAG_TRANSLATE_LOCALHOST;
6964#endif
6965
6966#ifdef __FreeBSD__
6967        if (action == PF_PASS && r->divert.port &&
6968            ip_divert_ptr != NULL && !PACKET_LOOPED()) {
6969
6970                ipfwtag = m_tag_alloc(MTAG_IPFW_RULE, 0,
6971                                sizeof(struct ipfw_rule_ref), M_NOWAIT | M_ZERO);
6972                if (ipfwtag != NULL) {
6973                        ((struct ipfw_rule_ref *)(ipfwtag+1))->info =
6974                            ntohs(r->divert.port);
6975                        ((struct ipfw_rule_ref *)(ipfwtag+1))->rulenum = dir;
6976
6977                        m_tag_prepend(m, ipfwtag);
6978
6979                        PF_UNLOCK();
6980
6981                        if (m->m_flags & M_FASTFWD_OURS) {
6982                                pd.pf_mtag->flags |= PF_FASTFWD_OURS_PRESENT;
6983                                m->m_flags &= ~M_FASTFWD_OURS;
6984                        }
6985
6986                        ip_divert_ptr(*m0,
6987                                dir ==  PF_IN ? DIR_IN : DIR_OUT);
6988                        *m0 = NULL;
6989                        return (action);
6990                } else {
6991                        /* XXX: ipfw has the same behaviour! */
6992                        action = PF_DROP;
6993                        REASON_SET(&reason, PFRES_MEMORY);
6994                        log = 1;
6995                        DPFPRINTF(PF_DEBUG_MISC,
6996                            ("pf: failed to allocate divert tag\n"));
6997                }
6998        }
6999#else
7000        if (dir == PF_IN && action == PF_PASS && r->divert.port) {
7001                struct pf_divert *divert;
7002
7003                if ((divert = pf_get_divert(m))) {
7004                        m->m_pkthdr.pf.flags |= PF_TAG_DIVERTED;
7005                        divert->port = r->divert.port;
7006                        divert->addr.ipv4 = r->divert.addr.v4;
7007                }
7008        }
7009#endif
7010
7011        if (log) {
7012                struct pf_rule *lr;
7013
7014                if (s != NULL && s->nat_rule.ptr != NULL &&
7015                    s->nat_rule.ptr->log & PF_LOG_ALL)
7016                        lr = s->nat_rule.ptr;
7017                else
7018                        lr = r;
7019                PFLOG_PACKET(kif, h, m, AF_INET, dir, reason, lr, a, ruleset,
7020                    &pd);
7021        }
7022
7023        kif->pfik_bytes[0][dir == PF_OUT][action != PF_PASS] += pd.tot_len;
7024        kif->pfik_packets[0][dir == PF_OUT][action != PF_PASS]++;
7025
7026        if (action == PF_PASS || r->action == PF_DROP) {
7027                dirndx = (dir == PF_OUT);
7028                r->packets[dirndx]++;
7029                r->bytes[dirndx] += pd.tot_len;
7030                if (a != NULL) {
7031                        a->packets[dirndx]++;
7032                        a->bytes[dirndx] += pd.tot_len;
7033                }
7034                if (s != NULL) {
7035                        if (s->nat_rule.ptr != NULL) {
7036                                s->nat_rule.ptr->packets[dirndx]++;
7037                                s->nat_rule.ptr->bytes[dirndx] += pd.tot_len;
7038                        }
7039                        if (s->src_node != NULL) {
7040                                s->src_node->packets[dirndx]++;
7041                                s->src_node->bytes[dirndx] += pd.tot_len;
7042                        }
7043                        if (s->nat_src_node != NULL) {
7044                                s->nat_src_node->packets[dirndx]++;
7045                                s->nat_src_node->bytes[dirndx] += pd.tot_len;
7046                        }
7047                        dirndx = (dir == s->direction) ? 0 : 1;
7048                        s->packets[dirndx]++;
7049                        s->bytes[dirndx] += pd.tot_len;
7050                }
7051                tr = r;
7052                nr = (s != NULL) ? s->nat_rule.ptr : pd.nat_rule;
7053#ifdef __FreeBSD__
7054                if (nr != NULL && r == &V_pf_default_rule)
7055#else
7056                if (nr != NULL && r == &pf_default_rule)
7057#endif
7058                        tr = nr;
7059                if (tr->src.addr.type == PF_ADDR_TABLE)
7060                        pfr_update_stats(tr->src.addr.p.tbl,
7061                            (s == NULL) ? pd.src :
7062                            &s->key[(s->direction == PF_IN)]->
7063                                addr[(s->direction == PF_OUT)],
7064                            pd.af, pd.tot_len, dir == PF_OUT,
7065                            r->action == PF_PASS, tr->src.neg);
7066                if (tr->dst.addr.type == PF_ADDR_TABLE)
7067                        pfr_update_stats(tr->dst.addr.p.tbl,
7068                            (s == NULL) ? pd.dst :
7069                            &s->key[(s->direction == PF_IN)]->
7070                                addr[(s->direction == PF_IN)],
7071                            pd.af, pd.tot_len, dir == PF_OUT,
7072                            r->action == PF_PASS, tr->dst.neg);
7073        }
7074
7075        switch (action) {
7076        case PF_SYNPROXY_DROP:
7077                m_freem(*m0);
7078        case PF_DEFER:
7079                *m0 = NULL;
7080                action = PF_PASS;
7081                break;
7082        default:
7083                /* pf_route can free the mbuf causing *m0 to become NULL */
7084                if (r->rt)
7085                        pf_route(m0, r, dir, kif->pfik_ifp, s, &pd);
7086                break;
7087        }
7088#ifdef __FreeBSD__
7089        PF_UNLOCK();
7090#endif
7091        return (action);
7092}
7093#endif /* INET */
7094
7095#ifdef INET6
7096int
7097#ifdef __FreeBSD__
7098pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0,
7099    struct ether_header *eh, struct inpcb *inp)
7100#else
7101pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0,
7102    struct ether_header *eh)
7103#endif
7104{
7105        struct pfi_kif          *kif;
7106        u_short                  action, reason = 0, log = 0;
7107        struct mbuf             *m = *m0, *n = NULL;
7108#ifdef __FreeBSD__
7109        struct ip6_hdr          *h = NULL;
7110        struct pf_rule          *a = NULL, *r = &V_pf_default_rule, *tr, *nr;
7111#else
7112        struct ip6_hdr          *h;
7113        struct pf_rule          *a = NULL, *r = &pf_default_rule, *tr, *nr;
7114#endif
7115        struct pf_state         *s = NULL;
7116        struct pf_ruleset       *ruleset = NULL;
7117        struct pf_pdesc          pd;
7118        int                      off, terminal = 0, dirndx, rh_cnt = 0;
7119
7120#ifdef __FreeBSD__
7121        PF_LOCK();
7122        if (!V_pf_status.running) {
7123                PF_UNLOCK();
7124                return (PF_PASS);
7125        }
7126#else
7127        if (!pf_status.running)
7128                return (PF_PASS);
7129#endif
7130
7131        memset(&pd, 0, sizeof(pd));
7132#ifdef __FreeBSD__
7133        if ((pd.pf_mtag = pf_get_mtag(m)) == NULL) {
7134                PF_UNLOCK();
7135                DPFPRINTF(PF_DEBUG_URGENT,
7136                    ("pf_test: pf_get_mtag returned NULL\n"));
7137                return (PF_DROP);
7138        }
7139#endif
7140#ifndef __FreeBSD__
7141        if (ifp->if_type == IFT_CARP && ifp->if_carpdev)
7142                kif = (struct pfi_kif *)ifp->if_carpdev->if_pf_kif;
7143        else
7144#endif
7145                kif = (struct pfi_kif *)ifp->if_pf_kif;
7146
7147        if (kif == NULL) {
7148#ifdef __FreeBSD__
7149                PF_UNLOCK();
7150#endif
7151                DPFPRINTF(PF_DEBUG_URGENT,
7152                    ("pf_test6: kif == NULL, if_xname %s\n", ifp->if_xname));
7153                return (PF_DROP);
7154        }
7155        if (kif->pfik_flags & PFI_IFLAG_SKIP)
7156#ifdef __FreeBSD__
7157        {
7158                PF_UNLOCK();
7159#endif
7160                return (PF_PASS);
7161#ifdef __FreeBSD__
7162        }
7163#endif
7164
7165#ifdef __FreeBSD__
7166        M_ASSERTPKTHDR(m);
7167#else
7168#ifdef DIAGNOSTIC
7169        if ((m->m_flags & M_PKTHDR) == 0)
7170                panic("non-M_PKTHDR is passed to pf_test6");
7171#endif /* DIAGNOSTIC */
7172#endif
7173
7174        if (m->m_pkthdr.len < (int)sizeof(*h)) {
7175                action = PF_DROP;
7176                REASON_SET(&reason, PFRES_SHORT);
7177                log = 1;
7178                goto done;
7179        }
7180
7181#ifdef __FreeBSD__
7182        if (pd.pf_mtag->flags & PF_TAG_GENERATED) {
7183                PF_UNLOCK();
7184#else
7185        if (m->m_pkthdr.pf.flags & PF_TAG_GENERATED)
7186#endif
7187                return (PF_PASS);
7188#ifdef __FreeBSD__
7189        }
7190#endif
7191
7192        /* We do IP header normalization and packet reassembly here */
7193        if (pf_normalize_ip6(m0, dir, kif, &reason, &pd) != PF_PASS) {
7194                action = PF_DROP;
7195                goto done;
7196        }
7197        m = *m0;        /* pf_normalize messes with m0 */
7198        h = mtod(m, struct ip6_hdr *);
7199
7200#if 1
7201        /*
7202         * we do not support jumbogram yet.  if we keep going, zero ip6_plen
7203         * will do something bad, so drop the packet for now.
7204         */
7205        if (htons(h->ip6_plen) == 0) {
7206                action = PF_DROP;
7207                REASON_SET(&reason, PFRES_NORM);        /*XXX*/
7208                goto done;
7209        }
7210#endif
7211
7212        pd.src = (struct pf_addr *)&h->ip6_src;
7213        pd.dst = (struct pf_addr *)&h->ip6_dst;
7214        pd.sport = pd.dport = NULL;
7215        pd.ip_sum = NULL;
7216        pd.proto_sum = NULL;
7217        pd.dir = dir;
7218        pd.sidx = (dir == PF_IN) ? 0 : 1;
7219        pd.didx = (dir == PF_IN) ? 1 : 0;
7220        pd.af = AF_INET6;
7221        pd.tos = 0;
7222        pd.tot_len = ntohs(h->ip6_plen) + sizeof(struct ip6_hdr);
7223        pd.eh = eh;
7224
7225        off = ((caddr_t)h - m->m_data) + sizeof(struct ip6_hdr);
7226        pd.proto = h->ip6_nxt;
7227        do {
7228                switch (pd.proto) {
7229                case IPPROTO_FRAGMENT:
7230                        action = pf_test_fragment(&r, dir, kif, m, h,
7231                            &pd, &a, &ruleset);
7232                        if (action == PF_DROP)
7233                                REASON_SET(&reason, PFRES_FRAG);
7234                        goto done;
7235                case IPPROTO_ROUTING: {
7236                        struct ip6_rthdr rthdr;
7237
7238                        if (rh_cnt++) {
7239                                DPFPRINTF(PF_DEBUG_MISC,
7240                                    ("pf: IPv6 more than one rthdr\n"));
7241                                action = PF_DROP;
7242                                REASON_SET(&reason, PFRES_IPOPTIONS);
7243                                log = 1;
7244                                goto done;
7245                        }
7246                        if (!pf_pull_hdr(m, off, &rthdr, sizeof(rthdr), NULL,
7247                            &reason, pd.af)) {
7248                                DPFPRINTF(PF_DEBUG_MISC,
7249                                    ("pf: IPv6 short rthdr\n"));
7250                                action = PF_DROP;
7251                                REASON_SET(&reason, PFRES_SHORT);
7252                                log = 1;
7253                                goto done;
7254                        }
7255                        if (rthdr.ip6r_type == IPV6_RTHDR_TYPE_0) {
7256                                DPFPRINTF(PF_DEBUG_MISC,
7257                                    ("pf: IPv6 rthdr0\n"));
7258                                action = PF_DROP;
7259                                REASON_SET(&reason, PFRES_IPOPTIONS);
7260                                log = 1;
7261                                goto done;
7262                        }
7263                        /* FALLTHROUGH */
7264                }
7265                case IPPROTO_AH:
7266                case IPPROTO_HOPOPTS:
7267                case IPPROTO_DSTOPTS: {
7268                        /* get next header and header length */
7269                        struct ip6_ext  opt6;
7270
7271                        if (!pf_pull_hdr(m, off, &opt6, sizeof(opt6),
7272                            NULL, &reason, pd.af)) {
7273                                DPFPRINTF(PF_DEBUG_MISC,
7274                                    ("pf: IPv6 short opt\n"));
7275                                action = PF_DROP;
7276                                log = 1;
7277                                goto done;
7278                        }
7279                        if (pd.proto == IPPROTO_AH)
7280                                off += (opt6.ip6e_len + 2) * 4;
7281                        else
7282                                off += (opt6.ip6e_len + 1) * 8;
7283                        pd.proto = opt6.ip6e_nxt;
7284                        /* goto the next header */
7285                        break;
7286                }
7287                default:
7288                        terminal++;
7289                        break;
7290                }
7291        } while (!terminal);
7292
7293        /* if there's no routing header, use unmodified mbuf for checksumming */
7294        if (!n)
7295                n = m;
7296
7297        switch (pd.proto) {
7298
7299        case IPPROTO_TCP: {
7300                struct tcphdr   th;
7301
7302                pd.hdr.tcp = &th;
7303                if (!pf_pull_hdr(m, off, &th, sizeof(th),
7304                    &action, &reason, AF_INET6)) {
7305                        log = action != PF_PASS;
7306                        goto done;
7307                }
7308                pd.p_len = pd.tot_len - off - (th.th_off << 2);
7309                action = pf_normalize_tcp(dir, kif, m, 0, off, h, &pd);
7310                if (action == PF_DROP)
7311                        goto done;
7312                action = pf_test_state_tcp(&s, dir, kif, m, off, h, &pd,
7313                    &reason);
7314                if (action == PF_PASS) {
7315#if NPFSYNC > 0
7316#ifdef __FreeBSD__
7317                        if (pfsync_update_state_ptr != NULL)
7318                                pfsync_update_state_ptr(s);
7319#else
7320                        pfsync_update_state(s);
7321#endif
7322#endif /* NPFSYNC */
7323                        r = s->rule.ptr;
7324                        a = s->anchor.ptr;
7325                        log = s->log;
7326                } else if (s == NULL)
7327#ifdef __FreeBSD__
7328                        action = pf_test_rule(&r, &s, dir, kif,
7329                            m, off, h, &pd, &a, &ruleset, NULL, inp);
7330#else
7331                        action = pf_test_rule(&r, &s, dir, kif,
7332                            m, off, h, &pd, &a, &ruleset, &ip6intrq);
7333#endif
7334                break;
7335        }
7336
7337        case IPPROTO_UDP: {
7338                struct udphdr   uh;
7339
7340                pd.hdr.udp = &uh;
7341                if (!pf_pull_hdr(m, off, &uh, sizeof(uh),
7342                    &action, &reason, AF_INET6)) {
7343                        log = action != PF_PASS;
7344                        goto done;
7345                }
7346                if (uh.uh_dport == 0 ||
7347                    ntohs(uh.uh_ulen) > m->m_pkthdr.len - off ||
7348                    ntohs(uh.uh_ulen) < sizeof(struct udphdr)) {
7349                        action = PF_DROP;
7350                        REASON_SET(&reason, PFRES_SHORT);
7351                        goto done;
7352                }
7353                action = pf_test_state_udp(&s, dir, kif, m, off, h, &pd);
7354                if (action == PF_PASS) {
7355#if NPFSYNC > 0
7356#ifdef __FreeBSD__
7357                        if (pfsync_update_state_ptr != NULL)
7358                                pfsync_update_state_ptr(s);
7359#else
7360                        pfsync_update_state(s);
7361#endif
7362#endif /* NPFSYNC */
7363                        r = s->rule.ptr;
7364                        a = s->anchor.ptr;
7365                        log = s->log;
7366                } else if (s == NULL)
7367#ifdef __FreeBSD__
7368                        action = pf_test_rule(&r, &s, dir, kif,
7369                            m, off, h, &pd, &a, &ruleset, NULL, inp);
7370#else
7371                        action = pf_test_rule(&r, &s, dir, kif,
7372                            m, off, h, &pd, &a, &ruleset, &ip6intrq);
7373#endif
7374                break;
7375        }
7376
7377        case IPPROTO_ICMP: {
7378                action = PF_DROP;
7379                DPFPRINTF(PF_DEBUG_MISC,
7380                    ("pf: dropping IPv6 packet with ICMPv4 payload\n"));
7381                goto done;
7382        }
7383
7384        case IPPROTO_ICMPV6: {
7385                struct icmp6_hdr        ih;
7386
7387                pd.hdr.icmp6 = &ih;
7388                if (!pf_pull_hdr(m, off, &ih, sizeof(ih),
7389                    &action, &reason, AF_INET6)) {
7390                        log = action != PF_PASS;
7391                        goto done;
7392                }
7393                action = pf_test_state_icmp(&s, dir, kif,
7394                    m, off, h, &pd, &reason);
7395                if (action == PF_PASS) {
7396#if NPFSYNC > 0
7397#ifdef __FreeBSD__
7398                        if (pfsync_update_state_ptr != NULL)
7399                                pfsync_update_state_ptr(s);
7400#else
7401                        pfsync_update_state(s);
7402#endif
7403#endif /* NPFSYNC */
7404                        r = s->rule.ptr;
7405                        a = s->anchor.ptr;
7406                        log = s->log;
7407                } else if (s == NULL)
7408#ifdef __FreeBSD__
7409                        action = pf_test_rule(&r, &s, dir, kif,
7410                            m, off, h, &pd, &a, &ruleset, NULL, inp);
7411#else
7412                        action = pf_test_rule(&r, &s, dir, kif,
7413                            m, off, h, &pd, &a, &ruleset, &ip6intrq);
7414#endif
7415                break;
7416        }
7417
7418        default:
7419                action = pf_test_state_other(&s, dir, kif, m, &pd);
7420                if (action == PF_PASS) {
7421#if NPFSYNC > 0
7422#ifdef __FreeBSD__
7423                        if (pfsync_update_state_ptr != NULL)
7424                                pfsync_update_state_ptr(s);
7425#else
7426                        pfsync_update_state(s);
7427#endif
7428#endif /* NPFSYNC */
7429                        r = s->rule.ptr;
7430                        a = s->anchor.ptr;
7431                        log = s->log;
7432                } else if (s == NULL)
7433#ifdef __FreeBSD__
7434                        action = pf_test_rule(&r, &s, dir, kif, m, off, h,
7435                            &pd, &a, &ruleset, NULL, inp);
7436#else
7437                        action = pf_test_rule(&r, &s, dir, kif, m, off, h,
7438                            &pd, &a, &ruleset, &ip6intrq);
7439#endif
7440                break;
7441        }
7442
7443done:
7444        if (n != m) {
7445                m_freem(n);
7446                n = NULL;
7447        }
7448
7449        /* handle dangerous IPv6 extension headers. */
7450        if (action == PF_PASS && rh_cnt &&
7451            !((s && s->state_flags & PFSTATE_ALLOWOPTS) || r->allow_opts)) {
7452                action = PF_DROP;
7453                REASON_SET(&reason, PFRES_IPOPTIONS);
7454                log = 1;
7455                DPFPRINTF(PF_DEBUG_MISC,
7456                    ("pf: dropping packet with dangerous v6 headers\n"));
7457        }
7458
7459        if ((s && s->tag) || r->rtableid >= 0)
7460#ifdef __FreeBSD__
7461                pf_tag_packet(m, s ? s->tag : 0, r->rtableid, pd.pf_mtag);
7462#else
7463                pf_tag_packet(m, s ? s->tag : 0, r->rtableid);
7464#endif
7465
7466        if (dir == PF_IN && s && s->key[PF_SK_STACK])
7467#ifdef __FreeBSD__
7468                pd.pf_mtag->statekey = s->key[PF_SK_STACK];
7469#else
7470                m->m_pkthdr.pf.statekey = s->key[PF_SK_STACK];
7471#endif
7472
7473#ifdef ALTQ
7474        if (action == PF_PASS && r->qid) {
7475#ifdef __FreeBSD__
7476                if (pd.tos & IPTOS_LOWDELAY)
7477                        pd.pf_mtag->qid = r->pqid;
7478                else
7479                        pd.pf_mtag->qid = r->qid;
7480                /* add hints for ecn */
7481                pd.pf_mtag->hdr = h;
7482#else
7483                if (pd.tos & IPTOS_LOWDELAY)
7484                        m->m_pkthdr.pf.qid = r->pqid;
7485                else
7486                        m->m_pkthdr.pf.qid = r->qid;
7487                /* add hints for ecn */
7488                m->m_pkthdr.pf.hdr = h;
7489#endif
7490        }
7491#endif /* ALTQ */
7492
7493        if (dir == PF_IN && action == PF_PASS && (pd.proto == IPPROTO_TCP ||
7494            pd.proto == IPPROTO_UDP) && s != NULL && s->nat_rule.ptr != NULL &&
7495            (s->nat_rule.ptr->action == PF_RDR ||
7496            s->nat_rule.ptr->action == PF_BINAT) &&
7497            IN6_IS_ADDR_LOOPBACK(&pd.dst->v6))
7498#ifdef __FreeBSD__
7499                m->m_flags |= M_SKIP_FIREWALL;
7500#else
7501                m->m_pkthdr.pf.flags |= PF_TAG_TRANSLATE_LOCALHOST;
7502#endif
7503
7504#ifdef __FreeBSD__
7505        /* XXX: Anybody working on it?! */
7506        if (r->divert.port)
7507                printf("pf: divert(9) is not supported for IPv6\n");
7508#else
7509        if (dir == PF_IN && action == PF_PASS && r->divert.port) {
7510                struct pf_divert *divert;
7511
7512                if ((divert = pf_get_divert(m))) {
7513                        m->m_pkthdr.pf.flags |= PF_TAG_DIVERTED;
7514                        divert->port = r->divert.port;
7515                        divert->addr.ipv6 = r->divert.addr.v6;
7516                }
7517        }
7518#endif
7519
7520        if (log) {
7521                struct pf_rule *lr;
7522
7523                if (s != NULL && s->nat_rule.ptr != NULL &&
7524                    s->nat_rule.ptr->log & PF_LOG_ALL)
7525                        lr = s->nat_rule.ptr;
7526                else
7527                        lr = r;
7528                PFLOG_PACKET(kif, h, m, AF_INET6, dir, reason, lr, a, ruleset,
7529                    &pd);
7530        }
7531
7532        kif->pfik_bytes[1][dir == PF_OUT][action != PF_PASS] += pd.tot_len;
7533        kif->pfik_packets[1][dir == PF_OUT][action != PF_PASS]++;
7534
7535        if (action == PF_PASS || r->action == PF_DROP) {
7536                dirndx = (dir == PF_OUT);
7537                r->packets[dirndx]++;
7538                r->bytes[dirndx] += pd.tot_len;
7539                if (a != NULL) {
7540                        a->packets[dirndx]++;
7541                        a->bytes[dirndx] += pd.tot_len;
7542                }
7543                if (s != NULL) {
7544                        if (s->nat_rule.ptr != NULL) {
7545                                s->nat_rule.ptr->packets[dirndx]++;
7546                                s->nat_rule.ptr->bytes[dirndx] += pd.tot_len;
7547                        }
7548                        if (s->src_node != NULL) {
7549                                s->src_node->packets[dirndx]++;
7550                                s->src_node->bytes[dirndx] += pd.tot_len;
7551                        }
7552                        if (s->nat_src_node != NULL) {
7553                                s->nat_src_node->packets[dirndx]++;
7554                                s->nat_src_node->bytes[dirndx] += pd.tot_len;
7555                        }
7556                        dirndx = (dir == s->direction) ? 0 : 1;
7557                        s->packets[dirndx]++;
7558                        s->bytes[dirndx] += pd.tot_len;
7559                }
7560                tr = r;
7561                nr = (s != NULL) ? s->nat_rule.ptr : pd.nat_rule;
7562#ifdef __FreeBSD__
7563                if (nr != NULL && r == &V_pf_default_rule)
7564#else
7565                if (nr != NULL && r == &pf_default_rule)
7566#endif
7567                        tr = nr;
7568                if (tr->src.addr.type == PF_ADDR_TABLE)
7569                        pfr_update_stats(tr->src.addr.p.tbl,
7570                            (s == NULL) ? pd.src :
7571                            &s->key[(s->direction == PF_IN)]->addr[0],
7572                            pd.af, pd.tot_len, dir == PF_OUT,
7573                            r->action == PF_PASS, tr->src.neg);
7574                if (tr->dst.addr.type == PF_ADDR_TABLE)
7575                        pfr_update_stats(tr->dst.addr.p.tbl,
7576                            (s == NULL) ? pd.dst :
7577                            &s->key[(s->direction == PF_IN)]->addr[1],
7578                            pd.af, pd.tot_len, dir == PF_OUT,
7579                            r->action == PF_PASS, tr->dst.neg);
7580        }
7581
7582        switch (action) {
7583        case PF_SYNPROXY_DROP:
7584                m_freem(*m0);
7585        case PF_DEFER:
7586                *m0 = NULL;
7587                action = PF_PASS;
7588                break;
7589        default:
7590                /* pf_route6 can free the mbuf causing *m0 to become NULL */
7591                if (r->rt)
7592                        pf_route6(m0, r, dir, kif->pfik_ifp, s, &pd);
7593                break;
7594        }
7595
7596#ifdef __FreeBSD__
7597        PF_UNLOCK();
7598#endif
7599        return (action);
7600}
7601#endif /* INET6 */
7602
7603int
7604pf_check_congestion(struct ifqueue *ifq)
7605{
7606#ifdef __FreeBSD__
7607        /* XXX_IMPORT: later */
7608        return (0);
7609#else
7610        if (ifq->ifq_congestion)
7611                return (1);
7612        else
7613                return (0);
7614#endif
7615}
7616
7617/*
7618 * must be called whenever any addressing information such as
7619 * address, port, protocol has changed
7620 */
7621void
7622pf_pkt_addr_changed(struct mbuf *m)
7623{
7624#ifdef __FreeBSD__
7625        struct pf_mtag  *pf_tag;
7626
7627        if ((pf_tag = pf_find_mtag(m)) != NULL)
7628                pf_tag->statekey = NULL;
7629#else
7630        m->m_pkthdr.pf.statekey = NULL;
7631#endif
7632}
Note: See TracBrowser for help on using the repository browser.