]> git.saurik.com Git - apple/xnu.git/blame - bsd/net/pf.c
xnu-6153.11.26.tar.gz
[apple/xnu.git] / bsd / net / pf.c
CommitLineData
a39ff7e2 1/*
cb323159 2 * Copyright (c) 2007-2019 Apple Inc. All rights reserved.
b0d623f7
A
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
d1ecb069 29/* $apfw: git commit 6602420f2f101b74305cd78f7cd9e0c8fdedae97 $ */
b0d623f7
A
30/* $OpenBSD: pf.c,v 1.567 2008/02/20 23:40:13 henning Exp $ */
31
32/*
33 * Copyright (c) 2001 Daniel Hartmeier
3e170ce0
A
34 * Copyright (c) 2002 - 2013 Henning Brauer
35 * NAT64 - Copyright (c) 2010 Viagenie Inc. (http://www.viagenie.ca)
b0d623f7
A
36 * All rights reserved.
37 *
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
40 * are met:
41 *
42 * - Redistributions of source code must retain the above copyright
43 * notice, this list of conditions and the following disclaimer.
44 * - Redistributions in binary form must reproduce the above
45 * copyright notice, this list of conditions and the following
46 * disclaimer in the documentation and/or other materials provided
47 * with the distribution.
48 *
49 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
50 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
51 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
52 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
53 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
54 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
55 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
56 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
57 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
58 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
59 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
60 * POSSIBILITY OF SUCH DAMAGE.
61 *
62 * Effort sponsored in part by the Defense Advanced Research Projects
63 * Agency (DARPA) and Air Force Research Laboratory, Air Force
64 * Materiel Command, USAF, under agreement number F30602-01-2-0537.
65 *
66 */
67
68#include <machine/endian.h>
69#include <sys/param.h>
70#include <sys/systm.h>
b0d623f7
A
71#include <sys/filio.h>
72#include <sys/socket.h>
73#include <sys/socketvar.h>
74#include <sys/kernel.h>
75#include <sys/time.h>
76#include <sys/proc.h>
77#include <sys/random.h>
78#include <sys/mcache.h>
39236c6e 79#include <sys/protosw.h>
b0d623f7
A
80
81#include <libkern/crypto/md5.h>
82#include <libkern/libkern.h>
83
84#include <mach/thread_act.h>
85
86#include <net/if.h>
87#include <net/if_types.h>
88#include <net/bpf.h>
89#include <net/route.h>
39236c6e 90#include <net/dlil.h>
b0d623f7
A
91
92#include <netinet/in.h>
93#include <netinet/in_var.h>
94#include <netinet/in_systm.h>
95#include <netinet/ip.h>
96#include <netinet/ip_var.h>
97#include <netinet/tcp.h>
98#include <netinet/tcp_seq.h>
99#include <netinet/udp.h>
100#include <netinet/ip_icmp.h>
101#include <netinet/in_pcb.h>
102#include <netinet/tcp_timer.h>
103#include <netinet/tcp_var.h>
104#include <netinet/tcp_fsm.h>
105#include <netinet/udp_var.h>
106#include <netinet/icmp_var.h>
107#include <net/if_ether.h>
108#include <net/ethernet.h>
316670eb 109#include <net/flowhash.h>
d9a64523 110#include <net/nat464_utils.h>
b0d623f7
A
111#include <net/pfvar.h>
112#include <net/if_pflog.h>
113
114#if NPFSYNC
115#include <net/if_pfsync.h>
116#endif /* NPFSYNC */
117
118#if INET6
119#include <netinet/ip6.h>
120#include <netinet6/in6_pcb.h>
121#include <netinet6/ip6_var.h>
122#include <netinet/icmp6.h>
123#include <netinet6/nd6.h>
124#endif /* INET6 */
125
316670eb
A
126#if DUMMYNET
127#include <netinet/ip_dummynet.h>
128#endif /* DUMMYNET */
b0d623f7 129
39236c6e 130/*
39037602 131 * For RandomULong(), to get a 32 bits random value
39236c6e
A
132 * Note that random() returns a 31 bits value, see rdar://11159750
133 */
134#include <dev/random/randomdev.h>
135
0a7de745 136#define DPFPRINTF(n, x) (pf_status.debug >= (n) ? printf x : ((void)0))
b0d623f7
A
137
138/*
139 * On Mac OS X, the rtableid value is treated as the interface scope
140 * value that is equivalent to the interface index used for scoped
141 * routing. A valid scope value is anything but IFSCOPE_NONE (0),
142 * as per definition of ifindex which is a positive, non-zero number.
143 * The other BSDs treat a negative rtableid value as invalid, hence
144 * the test against INT_MAX to handle userland apps which initialize
145 * the field with a negative number.
146 */
0a7de745 147#define PF_RTABLEID_IS_VALID(r) \
b0d623f7
A
148 ((r) > IFSCOPE_NONE && (r) <= INT_MAX)
149
150/*
151 * Global variables
152 */
0a7de745
A
153decl_lck_mtx_data(, pf_lock_data);
154decl_lck_rw_data(, pf_perim_lock_data);
316670eb
A
155lck_mtx_t *pf_lock = &pf_lock_data;
156lck_rw_t *pf_perim_lock = &pf_perim_lock_data;
b0d623f7
A
157
158/* state tables */
0a7de745
A
159struct pf_state_tree_lan_ext pf_statetbl_lan_ext;
160struct pf_state_tree_ext_gwy pf_statetbl_ext_gwy;
b0d623f7 161
0a7de745
A
162struct pf_palist pf_pabuf;
163struct pf_status pf_status;
b0d623f7 164
0a7de745 165u_int32_t ticket_pabuf;
b0d623f7 166
0a7de745
A
167static MD5_CTX pf_tcp_secret_ctx;
168static u_char pf_tcp_secret[16];
169static int pf_tcp_secret_init;
170static int pf_tcp_iss_off;
b0d623f7
A
171
172static struct pf_anchor_stackframe {
0a7de745
A
173 struct pf_ruleset *rs;
174 struct pf_rule *r;
175 struct pf_anchor_node *parent;
176 struct pf_anchor *child;
b0d623f7
A
177} pf_anchor_stack[64];
178
0a7de745
A
179struct pool pf_src_tree_pl, pf_rule_pl, pf_pooladdr_pl;
180struct pool pf_state_pl, pf_state_key_pl;
b0d623f7 181
b0d623f7
A
182typedef void (*hook_fn_t)(void *);
183
184struct hook_desc {
185 TAILQ_ENTRY(hook_desc) hd_list;
186 hook_fn_t hd_fn;
187 void *hd_arg;
188};
189
0a7de745
A
190#define HOOK_REMOVE 0x01
191#define HOOK_FREE 0x02
192#define HOOK_ABORT 0x04
b0d623f7 193
0a7de745
A
194static void *hook_establish(struct hook_desc_head *, int,
195 hook_fn_t, void *);
196static void hook_runloop(struct hook_desc_head *, int flags);
b0d623f7 197
0a7de745
A
198struct pool pf_app_state_pl;
199static void pf_print_addr(struct pf_addr *addr, sa_family_t af);
200static void pf_print_sk_host(struct pf_state_host *, u_int8_t, int,
201 u_int8_t);
b0d623f7 202
0a7de745 203static void pf_print_host(struct pf_addr *, u_int16_t, u_int8_t);
b0d623f7 204
0a7de745
A
205static void pf_init_threshold(struct pf_threshold *, u_int32_t,
206 u_int32_t);
207static void pf_add_threshold(struct pf_threshold *);
208static int pf_check_threshold(struct pf_threshold *);
b0d623f7 209
0a7de745
A
210static void pf_change_ap(int, pbuf_t *, struct pf_addr *,
211 u_int16_t *, u_int16_t *, u_int16_t *,
212 struct pf_addr *, u_int16_t, u_int8_t, sa_family_t,
213 sa_family_t, int);
214static int pf_modulate_sack(pbuf_t *, int, struct pf_pdesc *,
215 struct tcphdr *, struct pf_state_peer *);
b0d623f7 216#if INET6
0a7de745
A
217static void pf_change_a6(struct pf_addr *, u_int16_t *,
218 struct pf_addr *, u_int8_t);
219void pf_change_addr(struct pf_addr *a, u_int16_t *c,
220 struct pf_addr *an, u_int8_t u,
221 sa_family_t af, sa_family_t afn);
b0d623f7 222#endif /* INET6 */
0a7de745
A
223static void pf_change_icmp(struct pf_addr *, u_int16_t *,
224 struct pf_addr *, struct pf_addr *, u_int16_t,
225 u_int16_t *, u_int16_t *, u_int16_t *,
226 u_int16_t *, u_int8_t, sa_family_t);
227static void pf_send_tcp(const struct pf_rule *, sa_family_t,
228 const struct pf_addr *, const struct pf_addr *,
229 u_int16_t, u_int16_t, u_int32_t, u_int32_t,
230 u_int8_t, u_int16_t, u_int16_t, u_int8_t, int,
231 u_int16_t, struct ether_header *, struct ifnet *);
232static void pf_send_icmp(pbuf_t *, u_int8_t, u_int8_t,
233 sa_family_t, struct pf_rule *);
234static struct pf_rule *pf_match_translation(struct pf_pdesc *, pbuf_t *,
235 int, int, struct pfi_kif *, struct pf_addr *,
236 union pf_state_xport *, struct pf_addr *,
237 union pf_state_xport *, int);
238static struct pf_rule *pf_get_translation_aux(struct pf_pdesc *,
239 pbuf_t *, int, int, struct pfi_kif *,
240 struct pf_src_node **, struct pf_addr *,
241 union pf_state_xport *, struct pf_addr *,
242 union pf_state_xport *, union pf_state_xport *
243 );
244static void pf_attach_state(struct pf_state_key *,
245 struct pf_state *, int);
246static void pf_detach_state(struct pf_state *, int);
247static u_int32_t pf_tcp_iss(struct pf_pdesc *);
248static int pf_test_rule(struct pf_rule **, struct pf_state **,
249 int, struct pfi_kif *, pbuf_t *, int,
250 void *, struct pf_pdesc *, struct pf_rule **,
251 struct pf_ruleset **, struct ifqueue *);
316670eb 252#if DUMMYNET
0a7de745
A
253static int pf_test_dummynet(struct pf_rule **, int,
254 struct pfi_kif *, pbuf_t **,
255 struct pf_pdesc *, struct ip_fw_args *);
316670eb 256#endif /* DUMMYNET */
0a7de745
A
257static int pf_test_fragment(struct pf_rule **, int,
258 struct pfi_kif *, pbuf_t *, void *,
259 struct pf_pdesc *, struct pf_rule **,
260 struct pf_ruleset **);
261static int pf_test_state_tcp(struct pf_state **, int,
262 struct pfi_kif *, pbuf_t *, int,
263 void *, struct pf_pdesc *, u_short *);
264static int pf_test_state_udp(struct pf_state **, int,
265 struct pfi_kif *, pbuf_t *, int,
266 void *, struct pf_pdesc *, u_short *);
267static int pf_test_state_icmp(struct pf_state **, int,
268 struct pfi_kif *, pbuf_t *, int,
269 void *, struct pf_pdesc *, u_short *);
270static int pf_test_state_other(struct pf_state **, int,
271 struct pfi_kif *, struct pf_pdesc *);
272static int pf_match_tag(struct pf_rule *,
273 struct pf_mtag *, int *);
274static void pf_hash(struct pf_addr *, struct pf_addr *,
275 struct pf_poolhashkey *, sa_family_t);
276static int pf_map_addr(u_int8_t, struct pf_rule *,
277 struct pf_addr *, struct pf_addr *,
278 struct pf_addr *, struct pf_src_node **);
279static int pf_get_sport(struct pf_pdesc *, struct pfi_kif *,
280 struct pf_rule *, struct pf_addr *,
281 union pf_state_xport *, struct pf_addr *,
282 union pf_state_xport *, struct pf_addr *,
283 union pf_state_xport *, struct pf_src_node **
284 );
285static void pf_route(pbuf_t **, struct pf_rule *, int,
286 struct ifnet *, struct pf_state *,
287 struct pf_pdesc *);
b0d623f7 288#if INET6
0a7de745
A
289static void pf_route6(pbuf_t **, struct pf_rule *, int,
290 struct ifnet *, struct pf_state *,
291 struct pf_pdesc *);
b0d623f7 292#endif /* INET6 */
0a7de745
A
293static u_int8_t pf_get_wscale(pbuf_t *, int, u_int16_t,
294 sa_family_t);
295static u_int16_t pf_get_mss(pbuf_t *, int, u_int16_t,
296 sa_family_t);
297static u_int16_t pf_calc_mss(struct pf_addr *, sa_family_t,
298 u_int16_t);
299static void pf_set_rt_ifp(struct pf_state *,
300 struct pf_addr *, sa_family_t af);
301static int pf_check_proto_cksum(pbuf_t *, int, int,
302 u_int8_t, sa_family_t);
303static int pf_addr_wrap_neq(struct pf_addr_wrap *,
304 struct pf_addr_wrap *);
305static struct pf_state *pf_find_state(struct pfi_kif *,
306 struct pf_state_key_cmp *, u_int);
307static int pf_src_connlimit(struct pf_state **);
308static void pf_stateins_err(const char *, struct pf_state *,
309 struct pfi_kif *);
310static int pf_check_congestion(struct ifqueue *);
b0d623f7 311
b0d623f7
A
312#if 0
313static const char *pf_pptp_ctrl_type_name(u_int16_t code);
314#endif
0a7de745
A
315static void pf_pptp_handler(struct pf_state *, int, int,
316 struct pf_pdesc *, struct pfi_kif *);
317static void pf_pptp_unlink(struct pf_state *);
318static void pf_grev1_unlink(struct pf_state *);
319static int pf_test_state_grev1(struct pf_state **, int,
320 struct pfi_kif *, int, struct pf_pdesc *);
321static int pf_ike_compare(struct pf_app_state *,
322 struct pf_app_state *);
323static int pf_test_state_esp(struct pf_state **, int,
324 struct pfi_kif *, int, struct pf_pdesc *);
b0d623f7
A
325
326extern struct pool pfr_ktable_pl;
327extern struct pool pfr_kentry_pl;
328extern int path_mtu_discovery;
329
330struct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX] = {
cb323159
A
331 { .pp = &pf_state_pl, .limit = PFSTATE_HIWAT },
332 { .pp = &pf_app_state_pl, .limit = PFAPPSTATE_HIWAT },
333 { .pp = &pf_src_tree_pl, .limit = PFSNODE_HIWAT },
334 { .pp = &pf_frent_pl, .limit = PFFRAG_FRENT_HIWAT },
335 { .pp = &pfr_ktable_pl, .limit = PFR_KTABLE_HIWAT },
336 { .pp = &pfr_kentry_pl, .limit = PFR_KENTRY_HIWAT },
b0d623f7
A
337};
338
5ba3f43e
A
339void *
340pf_lazy_makewritable(struct pf_pdesc *pd, pbuf_t *pbuf, int len)
b0d623f7 341{
5ba3f43e
A
342 void *p;
343
0a7de745
A
344 if (pd->lmw < 0) {
345 return NULL;
346 }
b0d623f7 347
5ba3f43e 348 VERIFY(pbuf == pd->mp);
b0d623f7 349
5ba3f43e 350 p = pbuf->pb_data;
b0d623f7 351 if (len > pd->lmw) {
0a7de745 352 if ((p = pbuf_ensure_writable(pbuf, len)) == NULL) {
b0d623f7 353 len = -1;
0a7de745 354 }
b0d623f7 355 pd->lmw = len;
5ba3f43e
A
356 if (len >= 0) {
357 pd->pf_mtag = pf_find_mtag_pbuf(pbuf);
b0d623f7
A
358
359 switch (pd->af) {
360 case AF_INET: {
5ba3f43e
A
361 struct ip *h = p;
362 pd->src = (struct pf_addr *)(uintptr_t)&h->ip_src;
363 pd->dst = (struct pf_addr *)(uintptr_t)&h->ip_dst;
b0d623f7
A
364 pd->ip_sum = &h->ip_sum;
365 break;
366 }
367#if INET6
368 case AF_INET6: {
5ba3f43e
A
369 struct ip6_hdr *h = p;
370 pd->src = (struct pf_addr *)(uintptr_t)&h->ip6_src;
371 pd->dst = (struct pf_addr *)(uintptr_t)&h->ip6_dst;
b0d623f7
A
372 break;
373 }
374#endif /* INET6 */
375 }
376 }
377 }
378
0a7de745 379 return len < 0 ? NULL : p;
b0d623f7
A
380}
381
382static const int *
383pf_state_lookup_aux(struct pf_state **state, struct pfi_kif *kif,
0a7de745 384 int direction, int *action)
b0d623f7
A
385{
386 if (*state == NULL || (*state)->timeout == PFTM_PURGE) {
387 *action = PF_DROP;
0a7de745 388 return action;
b0d623f7
A
389 }
390
391 if (direction == PF_OUT &&
392 (((*state)->rule.ptr->rt == PF_ROUTETO &&
393 (*state)->rule.ptr->direction == PF_OUT) ||
394 ((*state)->rule.ptr->rt == PF_REPLYTO &&
395 (*state)->rule.ptr->direction == PF_IN)) &&
396 (*state)->rt_kif != NULL && (*state)->rt_kif != kif) {
397 *action = PF_PASS;
0a7de745 398 return action;
b0d623f7
A
399 }
400
0a7de745 401 return 0;
b0d623f7
A
402}
403
0a7de745
A
404#define STATE_LOOKUP() \
405 do { \
406 int action; \
407 *state = pf_find_state(kif, &key, direction); \
408 if (*state != NULL && pd != NULL && \
409 !(pd->pktflags & PKTF_FLOW_ID)) { \
410 pd->flowsrc = (*state)->state_key->flowsrc; \
411 pd->flowhash = (*state)->state_key->flowhash; \
412 if (pd->flowhash != 0) { \
413 pd->pktflags |= PKTF_FLOW_ID; \
414 pd->pktflags &= ~PKTF_FLOW_ADV; \
415 } \
416 } \
417 if (pf_state_lookup_aux(state, kif, direction, &action)) \
418 return (action); \
b0d623f7
A
419 } while (0)
420
0a7de745
A
421#define STATE_ADDR_TRANSLATE(sk) \
422 (sk)->lan.addr.addr32[0] != (sk)->gwy.addr.addr32[0] || \
423 ((sk)->af_lan == AF_INET6 && \
424 ((sk)->lan.addr.addr32[1] != (sk)->gwy.addr.addr32[1] || \
425 (sk)->lan.addr.addr32[2] != (sk)->gwy.addr.addr32[2] || \
b0d623f7
A
426 (sk)->lan.addr.addr32[3] != (sk)->gwy.addr.addr32[3]))
427
0a7de745
A
428#define STATE_TRANSLATE(sk) \
429 ((sk)->af_lan != (sk)->af_gwy || \
430 STATE_ADDR_TRANSLATE(sk) || \
b0d623f7
A
431 (sk)->lan.xport.port != (sk)->gwy.xport.port)
432
0a7de745
A
433#define STATE_GRE_TRANSLATE(sk) \
434 (STATE_ADDR_TRANSLATE(sk) || \
b0d623f7
A
435 (sk)->lan.xport.call_id != (sk)->gwy.xport.call_id)
436
b0d623f7
A
437#define BOUND_IFACE(r, k) \
438 ((r)->rule_flag & PFRULE_IFBOUND) ? (k) : pfi_all
439
0a7de745
A
440#define STATE_INC_COUNTERS(s) \
441 do { \
442 s->rule.ptr->states++; \
443 VERIFY(s->rule.ptr->states != 0); \
444 if (s->anchor.ptr != NULL) { \
445 s->anchor.ptr->states++; \
446 VERIFY(s->anchor.ptr->states != 0); \
447 } \
448 if (s->nat_rule.ptr != NULL) { \
449 s->nat_rule.ptr->states++; \
450 VERIFY(s->nat_rule.ptr->states != 0); \
451 } \
b0d623f7
A
452 } while (0)
453
0a7de745
A
454#define STATE_DEC_COUNTERS(s) \
455 do { \
456 if (s->nat_rule.ptr != NULL) { \
457 VERIFY(s->nat_rule.ptr->states > 0); \
458 s->nat_rule.ptr->states--; \
459 } \
460 if (s->anchor.ptr != NULL) { \
461 VERIFY(s->anchor.ptr->states > 0); \
462 s->anchor.ptr->states--; \
463 } \
464 VERIFY(s->rule.ptr->states > 0); \
465 s->rule.ptr->states--; \
b0d623f7
A
466 } while (0)
467
468static __inline int pf_src_compare(struct pf_src_node *, struct pf_src_node *);
469static __inline int pf_state_compare_lan_ext(struct pf_state_key *,
0a7de745 470 struct pf_state_key *);
b0d623f7 471static __inline int pf_state_compare_ext_gwy(struct pf_state_key *,
0a7de745 472 struct pf_state_key *);
b0d623f7 473static __inline int pf_state_compare_id(struct pf_state *,
0a7de745 474 struct pf_state *);
b0d623f7
A
475
476struct pf_src_tree tree_src_tracking;
477
478struct pf_state_tree_id tree_id;
479struct pf_state_queue state_list;
480
481RB_GENERATE(pf_src_tree, pf_src_node, entry, pf_src_compare);
482RB_GENERATE(pf_state_tree_lan_ext, pf_state_key,
483 entry_lan_ext, pf_state_compare_lan_ext);
484RB_GENERATE(pf_state_tree_ext_gwy, pf_state_key,
485 entry_ext_gwy, pf_state_compare_ext_gwy);
486RB_GENERATE(pf_state_tree_id, pf_state,
487 entry_id, pf_state_compare_id);
488
0a7de745
A
489#define PF_DT_SKIP_LANEXT 0x01
490#define PF_DT_SKIP_EXTGWY 0x02
b0d623f7 491
b7266188
A
492static const u_int16_t PF_PPTP_PORT = 1723;
493static const u_int32_t PF_PPTP_MAGIC_NUMBER = 0x1A2B3C4D;
b0d623f7
A
494
495struct pf_pptp_hdr {
0a7de745
A
496 u_int16_t length;
497 u_int16_t type;
498 u_int32_t magic;
b0d623f7
A
499};
500
501struct pf_pptp_ctrl_hdr {
0a7de745
A
502 u_int16_t type;
503 u_int16_t reserved_0;
b0d623f7
A
504};
505
506struct pf_pptp_ctrl_generic {
0a7de745 507 u_int16_t data[0];
b0d623f7
A
508};
509
0a7de745 510#define PF_PPTP_CTRL_TYPE_START_REQ 1
b0d623f7 511struct pf_pptp_ctrl_start_req {
0a7de745
A
512 u_int16_t protocol_version;
513 u_int16_t reserved_1;
514 u_int32_t framing_capabilities;
515 u_int32_t bearer_capabilities;
516 u_int16_t maximum_channels;
517 u_int16_t firmware_revision;
518 u_int8_t host_name[64];
519 u_int8_t vendor_string[64];
b0d623f7
A
520};
521
0a7de745 522#define PF_PPTP_CTRL_TYPE_START_RPY 2
b0d623f7 523struct pf_pptp_ctrl_start_rpy {
0a7de745
A
524 u_int16_t protocol_version;
525 u_int8_t result_code;
526 u_int8_t error_code;
527 u_int32_t framing_capabilities;
528 u_int32_t bearer_capabilities;
529 u_int16_t maximum_channels;
530 u_int16_t firmware_revision;
531 u_int8_t host_name[64];
532 u_int8_t vendor_string[64];
b0d623f7
A
533};
534
0a7de745 535#define PF_PPTP_CTRL_TYPE_STOP_REQ 3
b0d623f7 536struct pf_pptp_ctrl_stop_req {
0a7de745
A
537 u_int8_t reason;
538 u_int8_t reserved_1;
539 u_int16_t reserved_2;
b0d623f7
A
540};
541
0a7de745 542#define PF_PPTP_CTRL_TYPE_STOP_RPY 4
b0d623f7 543struct pf_pptp_ctrl_stop_rpy {
0a7de745
A
544 u_int8_t reason;
545 u_int8_t error_code;
546 u_int16_t reserved_1;
b0d623f7
A
547};
548
0a7de745 549#define PF_PPTP_CTRL_TYPE_ECHO_REQ 5
b0d623f7 550struct pf_pptp_ctrl_echo_req {
0a7de745 551 u_int32_t identifier;
b0d623f7
A
552};
553
0a7de745 554#define PF_PPTP_CTRL_TYPE_ECHO_RPY 6
b0d623f7 555struct pf_pptp_ctrl_echo_rpy {
0a7de745
A
556 u_int32_t identifier;
557 u_int8_t result_code;
558 u_int8_t error_code;
559 u_int16_t reserved_1;
b0d623f7
A
560};
561
0a7de745 562#define PF_PPTP_CTRL_TYPE_CALL_OUT_REQ 7
b0d623f7 563struct pf_pptp_ctrl_call_out_req {
0a7de745
A
564 u_int16_t call_id;
565 u_int16_t call_sernum;
566 u_int32_t min_bps;
567 u_int32_t bearer_type;
568 u_int32_t framing_type;
569 u_int16_t rxwindow_size;
570 u_int16_t proc_delay;
571 u_int8_t phone_num[64];
572 u_int8_t sub_addr[64];
b0d623f7
A
573};
574
0a7de745 575#define PF_PPTP_CTRL_TYPE_CALL_OUT_RPY 8
b0d623f7 576struct pf_pptp_ctrl_call_out_rpy {
0a7de745
A
577 u_int16_t call_id;
578 u_int16_t peer_call_id;
579 u_int8_t result_code;
580 u_int8_t error_code;
581 u_int16_t cause_code;
582 u_int32_t connect_speed;
583 u_int16_t rxwindow_size;
584 u_int16_t proc_delay;
585 u_int32_t phy_channel_id;
b0d623f7
A
586};
587
0a7de745 588#define PF_PPTP_CTRL_TYPE_CALL_IN_1ST 9
b0d623f7 589struct pf_pptp_ctrl_call_in_1st {
0a7de745
A
590 u_int16_t call_id;
591 u_int16_t call_sernum;
592 u_int32_t bearer_type;
593 u_int32_t phy_channel_id;
594 u_int16_t dialed_number_len;
595 u_int16_t dialing_number_len;
596 u_int8_t dialed_num[64];
597 u_int8_t dialing_num[64];
598 u_int8_t sub_addr[64];
b0d623f7
A
599};
600
0a7de745 601#define PF_PPTP_CTRL_TYPE_CALL_IN_2ND 10
b0d623f7 602struct pf_pptp_ctrl_call_in_2nd {
0a7de745
A
603 u_int16_t call_id;
604 u_int16_t peer_call_id;
605 u_int8_t result_code;
606 u_int8_t error_code;
607 u_int16_t rxwindow_size;
608 u_int16_t txdelay;
609 u_int16_t reserved_1;
b0d623f7
A
610};
611
0a7de745 612#define PF_PPTP_CTRL_TYPE_CALL_IN_3RD 11
b0d623f7 613struct pf_pptp_ctrl_call_in_3rd {
0a7de745
A
614 u_int16_t call_id;
615 u_int16_t reserved_1;
616 u_int32_t connect_speed;
617 u_int16_t rxwindow_size;
618 u_int16_t txdelay;
619 u_int32_t framing_type;
b0d623f7
A
620};
621
0a7de745 622#define PF_PPTP_CTRL_TYPE_CALL_CLR 12
b0d623f7 623struct pf_pptp_ctrl_call_clr {
0a7de745
A
624 u_int16_t call_id;
625 u_int16_t reserved_1;
b0d623f7
A
626};
627
0a7de745 628#define PF_PPTP_CTRL_TYPE_CALL_DISC 13
b0d623f7 629struct pf_pptp_ctrl_call_disc {
0a7de745
A
630 u_int16_t call_id;
631 u_int8_t result_code;
632 u_int8_t error_code;
633 u_int16_t cause_code;
634 u_int16_t reserved_1;
635 u_int8_t statistics[128];
b0d623f7
A
636};
637
0a7de745 638#define PF_PPTP_CTRL_TYPE_ERROR 14
b0d623f7 639struct pf_pptp_ctrl_error {
0a7de745
A
640 u_int16_t peer_call_id;
641 u_int16_t reserved_1;
642 u_int32_t crc_errors;
643 u_int32_t fr_errors;
644 u_int32_t hw_errors;
645 u_int32_t buf_errors;
646 u_int32_t tim_errors;
647 u_int32_t align_errors;
b0d623f7
A
648};
649
0a7de745 650#define PF_PPTP_CTRL_TYPE_SET_LINKINFO 15
b0d623f7 651struct pf_pptp_ctrl_set_linkinfo {
0a7de745
A
652 u_int16_t peer_call_id;
653 u_int16_t reserved_1;
654 u_int32_t tx_accm;
655 u_int32_t rx_accm;
b0d623f7
A
656};
657
658#if 0
0a7de745
A
659static const char *
660pf_pptp_ctrl_type_name(u_int16_t code)
b0d623f7
A
661{
662 code = ntohs(code);
663
664 if (code < PF_PPTP_CTRL_TYPE_START_REQ ||
665 code > PF_PPTP_CTRL_TYPE_SET_LINKINFO) {
666 static char reserved[] = "reserved-00";
667
668 sprintf(&reserved[9], "%02x", code);
0a7de745 669 return reserved;
b0d623f7
A
670 } else {
671 static const char *name[] = {
672 "start_req", "start_rpy", "stop_req", "stop_rpy",
673 "echo_req", "echo_rpy", "call_out_req", "call_out_rpy",
674 "call_in_1st", "call_in_2nd", "call_in_3rd",
675 "call_clr", "call_disc", "error", "set_linkinfo"
676 };
677
0a7de745 678 return name[code - 1];
b0d623f7
A
679 }
680};
681#endif
682
683static const size_t PF_PPTP_CTRL_MSG_MINSIZE =
0a7de745 684 sizeof(struct pf_pptp_hdr) + sizeof(struct pf_pptp_ctrl_hdr);
b0d623f7
A
685
686union pf_pptp_ctrl_msg_union {
0a7de745
A
687 struct pf_pptp_ctrl_start_req start_req;
688 struct pf_pptp_ctrl_start_rpy start_rpy;
689 struct pf_pptp_ctrl_stop_req stop_req;
690 struct pf_pptp_ctrl_stop_rpy stop_rpy;
691 struct pf_pptp_ctrl_echo_req echo_req;
692 struct pf_pptp_ctrl_echo_rpy echo_rpy;
693 struct pf_pptp_ctrl_call_out_req call_out_req;
694 struct pf_pptp_ctrl_call_out_rpy call_out_rpy;
695 struct pf_pptp_ctrl_call_in_1st call_in_1st;
696 struct pf_pptp_ctrl_call_in_2nd call_in_2nd;
697 struct pf_pptp_ctrl_call_in_3rd call_in_3rd;
698 struct pf_pptp_ctrl_call_clr call_clr;
699 struct pf_pptp_ctrl_call_disc call_disc;
700 struct pf_pptp_ctrl_error error;
701 struct pf_pptp_ctrl_set_linkinfo set_linkinfo;
702 u_int8_t data[0];
b0d623f7
A
703};
704
705struct pf_pptp_ctrl_msg {
0a7de745
A
706 struct pf_pptp_hdr hdr;
707 struct pf_pptp_ctrl_hdr ctrl;
708 union pf_pptp_ctrl_msg_union msg;
b0d623f7
A
709};
710
0a7de745
A
711#define PF_GRE_FLAG_CHECKSUM_PRESENT 0x8000
712#define PF_GRE_FLAG_VERSION_MASK 0x0007
713#define PF_GRE_PPP_ETHERTYPE 0x880B
b0d623f7
A
714
715struct pf_grev1_hdr {
716 u_int16_t flags;
717 u_int16_t protocol_type;
718 u_int16_t payload_length;
719 u_int16_t call_id;
720 /*
0a7de745
A
721 * u_int32_t seqno;
722 * u_int32_t ackno;
723 */
b0d623f7
A
724};
725
b7266188 726static const u_int16_t PF_IKE_PORT = 500;
b0d623f7
A
727
728struct pf_ike_hdr {
729 u_int64_t initiator_cookie, responder_cookie;
730 u_int8_t next_payload, version, exchange_type, flags;
731 u_int32_t message_id, length;
732};
733
0a7de745
A
734#define PF_IKE_PACKET_MINSIZE (sizeof (struct pf_ike_hdr))
735
736#define PF_IKEv1_EXCHTYPE_BASE 1
737#define PF_IKEv1_EXCHTYPE_ID_PROTECT 2
738#define PF_IKEv1_EXCHTYPE_AUTH_ONLY 3
739#define PF_IKEv1_EXCHTYPE_AGGRESSIVE 4
740#define PF_IKEv1_EXCHTYPE_INFORMATIONAL 5
741#define PF_IKEv2_EXCHTYPE_SA_INIT 34
742#define PF_IKEv2_EXCHTYPE_AUTH 35
743#define PF_IKEv2_EXCHTYPE_CREATE_CHILD_SA 36
744#define PF_IKEv2_EXCHTYPE_INFORMATIONAL 37
745
746#define PF_IKEv1_FLAG_E 0x01
747#define PF_IKEv1_FLAG_C 0x02
748#define PF_IKEv1_FLAG_A 0x04
749#define PF_IKEv2_FLAG_I 0x08
750#define PF_IKEv2_FLAG_V 0x10
751#define PF_IKEv2_FLAG_R 0x20
b0d623f7
A
752
753struct pf_esp_hdr {
754 u_int32_t spi;
755 u_int32_t seqno;
756 u_int8_t payload[];
757};
b0d623f7
A
758
759static __inline int
3e170ce0 760pf_addr_compare(struct pf_addr *a, struct pf_addr *b, sa_family_t af)
b0d623f7 761{
3e170ce0
A
762 switch (af) {
763#ifdef INET
b0d623f7 764 case AF_INET:
0a7de745
A
765 if (a->addr32[0] > b->addr32[0]) {
766 return 1;
767 }
768 if (a->addr32[0] < b->addr32[0]) {
769 return -1;
770 }
b0d623f7
A
771 break;
772#endif /* INET */
3e170ce0 773#ifdef INET6
b0d623f7 774 case AF_INET6:
0a7de745
A
775 if (a->addr32[3] > b->addr32[3]) {
776 return 1;
777 }
778 if (a->addr32[3] < b->addr32[3]) {
779 return -1;
780 }
781 if (a->addr32[2] > b->addr32[2]) {
782 return 1;
783 }
784 if (a->addr32[2] < b->addr32[2]) {
785 return -1;
786 }
787 if (a->addr32[1] > b->addr32[1]) {
788 return 1;
789 }
790 if (a->addr32[1] < b->addr32[1]) {
791 return -1;
792 }
793 if (a->addr32[0] > b->addr32[0]) {
794 return 1;
795 }
796 if (a->addr32[0] < b->addr32[0]) {
797 return -1;
798 }
b0d623f7
A
799 break;
800#endif /* INET6 */
801 }
0a7de745 802 return 0;
b0d623f7
A
803}
804
3e170ce0
A
805static __inline int
806pf_src_compare(struct pf_src_node *a, struct pf_src_node *b)
807{
0a7de745
A
808 int diff;
809
810 if (a->rule.ptr > b->rule.ptr) {
811 return 1;
812 }
813 if (a->rule.ptr < b->rule.ptr) {
814 return -1;
815 }
816 if ((diff = a->af - b->af) != 0) {
817 return diff;
818 }
819 if ((diff = pf_addr_compare(&a->addr, &b->addr, a->af)) != 0) {
820 return diff;
821 }
822 return 0;
3e170ce0
A
823}
824
b0d623f7
A
825static __inline int
826pf_state_compare_lan_ext(struct pf_state_key *a, struct pf_state_key *b)
827{
0a7de745
A
828 int diff;
829 int extfilter;
b0d623f7 830
0a7de745
A
831 if ((diff = a->proto - b->proto) != 0) {
832 return diff;
833 }
834 if ((diff = a->af_lan - b->af_lan) != 0) {
835 return diff;
836 }
b0d623f7 837
b0d623f7
A
838 extfilter = PF_EXTFILTER_APD;
839
840 switch (a->proto) {
841 case IPPROTO_ICMP:
842 case IPPROTO_ICMPV6:
0a7de745
A
843 if ((diff = a->lan.xport.port - b->lan.xport.port) != 0) {
844 return diff;
845 }
b0d623f7
A
846 break;
847
848 case IPPROTO_TCP:
0a7de745
A
849 if ((diff = a->lan.xport.port - b->lan.xport.port) != 0) {
850 return diff;
851 }
852 if ((diff = a->ext_lan.xport.port - b->ext_lan.xport.port) != 0) {
853 return diff;
854 }
b0d623f7
A
855 break;
856
857 case IPPROTO_UDP:
0a7de745
A
858 if ((diff = a->proto_variant - b->proto_variant)) {
859 return diff;
860 }
b0d623f7 861 extfilter = a->proto_variant;
0a7de745
A
862 if ((diff = a->lan.xport.port - b->lan.xport.port) != 0) {
863 return diff;
864 }
b0d623f7 865 if ((extfilter < PF_EXTFILTER_AD) &&
0a7de745
A
866 (diff = a->ext_lan.xport.port - b->ext_lan.xport.port) != 0) {
867 return diff;
868 }
b0d623f7
A
869 break;
870
871 case IPPROTO_GRE:
872 if (a->proto_variant == PF_GRE_PPTP_VARIANT &&
873 a->proto_variant == b->proto_variant) {
3e170ce0 874 if (!!(diff = a->ext_lan.xport.call_id -
0a7de745
A
875 b->ext_lan.xport.call_id)) {
876 return diff;
877 }
b0d623f7
A
878 }
879 break;
880
881 case IPPROTO_ESP:
0a7de745
A
882 if (!!(diff = a->ext_lan.xport.spi - b->ext_lan.xport.spi)) {
883 return diff;
884 }
b0d623f7
A
885 break;
886
887 default:
888 break;
889 }
b0d623f7 890
3e170ce0 891 switch (a->af_lan) {
b0d623f7
A
892#if INET
893 case AF_INET:
3e170ce0 894 if ((diff = pf_addr_compare(&a->lan.addr, &b->lan.addr,
0a7de745
A
895 a->af_lan)) != 0) {
896 return diff;
897 }
3e170ce0 898
b0d623f7 899 if (extfilter < PF_EXTFILTER_EI) {
3e170ce0 900 if ((diff = pf_addr_compare(&a->ext_lan.addr,
0a7de745
A
901 &b->ext_lan.addr,
902 a->af_lan)) != 0) {
903 return diff;
904 }
b0d623f7 905 }
b0d623f7
A
906 break;
907#endif /* INET */
908#if INET6
909 case AF_INET6:
3e170ce0 910 if ((diff = pf_addr_compare(&a->lan.addr, &b->lan.addr,
0a7de745
A
911 a->af_lan)) != 0) {
912 return diff;
913 }
3e170ce0 914
b0d623f7 915 if (extfilter < PF_EXTFILTER_EI ||
3e170ce0
A
916 !PF_AZERO(&b->ext_lan.addr, AF_INET6)) {
917 if ((diff = pf_addr_compare(&a->ext_lan.addr,
0a7de745
A
918 &b->ext_lan.addr,
919 a->af_lan)) != 0) {
920 return diff;
921 }
b0d623f7 922 }
b0d623f7
A
923 break;
924#endif /* INET6 */
925 }
926
b0d623f7
A
927 if (a->app_state && b->app_state) {
928 if (a->app_state->compare_lan_ext &&
929 b->app_state->compare_lan_ext) {
930 diff = (const char *)b->app_state->compare_lan_ext -
931 (const char *)a->app_state->compare_lan_ext;
0a7de745
A
932 if (diff != 0) {
933 return diff;
934 }
b0d623f7
A
935 diff = a->app_state->compare_lan_ext(a->app_state,
936 b->app_state);
0a7de745
A
937 if (diff != 0) {
938 return diff;
939 }
b0d623f7
A
940 }
941 }
b0d623f7 942
0a7de745 943 return 0;
b0d623f7
A
944}
945
946static __inline int
947pf_state_compare_ext_gwy(struct pf_state_key *a, struct pf_state_key *b)
948{
0a7de745
A
949 int diff;
950 int extfilter;
b0d623f7 951
0a7de745
A
952 if ((diff = a->proto - b->proto) != 0) {
953 return diff;
954 }
b0d623f7 955
0a7de745
A
956 if ((diff = a->af_gwy - b->af_gwy) != 0) {
957 return diff;
958 }
b0d623f7 959
b0d623f7
A
960 extfilter = PF_EXTFILTER_APD;
961
962 switch (a->proto) {
963 case IPPROTO_ICMP:
964 case IPPROTO_ICMPV6:
0a7de745
A
965 if ((diff = a->gwy.xport.port - b->gwy.xport.port) != 0) {
966 return diff;
967 }
b0d623f7
A
968 break;
969
970 case IPPROTO_TCP:
0a7de745
A
971 if ((diff = a->ext_gwy.xport.port - b->ext_gwy.xport.port) != 0) {
972 return diff;
973 }
974 if ((diff = a->gwy.xport.port - b->gwy.xport.port) != 0) {
975 return diff;
976 }
b0d623f7
A
977 break;
978
979 case IPPROTO_UDP:
0a7de745
A
980 if ((diff = a->proto_variant - b->proto_variant)) {
981 return diff;
982 }
b0d623f7 983 extfilter = a->proto_variant;
0a7de745
A
984 if ((diff = a->gwy.xport.port - b->gwy.xport.port) != 0) {
985 return diff;
986 }
b0d623f7 987 if ((extfilter < PF_EXTFILTER_AD) &&
0a7de745
A
988 (diff = a->ext_gwy.xport.port - b->ext_gwy.xport.port) != 0) {
989 return diff;
990 }
b0d623f7
A
991 break;
992
993 case IPPROTO_GRE:
994 if (a->proto_variant == PF_GRE_PPTP_VARIANT &&
995 a->proto_variant == b->proto_variant) {
996 if (!!(diff = a->gwy.xport.call_id -
0a7de745
A
997 b->gwy.xport.call_id)) {
998 return diff;
999 }
b0d623f7
A
1000 }
1001 break;
1002
1003 case IPPROTO_ESP:
0a7de745
A
1004 if (!!(diff = a->gwy.xport.spi - b->gwy.xport.spi)) {
1005 return diff;
1006 }
b0d623f7
A
1007 break;
1008
1009 default:
1010 break;
1011 }
b0d623f7 1012
3e170ce0 1013 switch (a->af_gwy) {
b0d623f7
A
1014#if INET
1015 case AF_INET:
3e170ce0 1016 if ((diff = pf_addr_compare(&a->gwy.addr, &b->gwy.addr,
0a7de745
A
1017 a->af_gwy)) != 0) {
1018 return diff;
1019 }
3e170ce0 1020
b0d623f7 1021 if (extfilter < PF_EXTFILTER_EI) {
3e170ce0 1022 if ((diff = pf_addr_compare(&a->ext_gwy.addr, &b->ext_gwy.addr,
0a7de745
A
1023 a->af_gwy)) != 0) {
1024 return diff;
1025 }
b0d623f7 1026 }
b0d623f7
A
1027 break;
1028#endif /* INET */
1029#if INET6
1030 case AF_INET6:
3e170ce0 1031 if ((diff = pf_addr_compare(&a->gwy.addr, &b->gwy.addr,
0a7de745
A
1032 a->af_gwy)) != 0) {
1033 return diff;
1034 }
3e170ce0 1035
b0d623f7 1036 if (extfilter < PF_EXTFILTER_EI ||
3e170ce0
A
1037 !PF_AZERO(&b->ext_gwy.addr, AF_INET6)) {
1038 if ((diff = pf_addr_compare(&a->ext_gwy.addr, &b->ext_gwy.addr,
0a7de745
A
1039 a->af_gwy)) != 0) {
1040 return diff;
1041 }
b0d623f7 1042 }
b0d623f7
A
1043 break;
1044#endif /* INET6 */
1045 }
1046
b0d623f7
A
1047 if (a->app_state && b->app_state) {
1048 if (a->app_state->compare_ext_gwy &&
1049 b->app_state->compare_ext_gwy) {
1050 diff = (const char *)b->app_state->compare_ext_gwy -
1051 (const char *)a->app_state->compare_ext_gwy;
0a7de745
A
1052 if (diff != 0) {
1053 return diff;
1054 }
b0d623f7
A
1055 diff = a->app_state->compare_ext_gwy(a->app_state,
1056 b->app_state);
0a7de745
A
1057 if (diff != 0) {
1058 return diff;
1059 }
b0d623f7
A
1060 }
1061 }
b0d623f7 1062
0a7de745 1063 return 0;
b0d623f7
A
1064}
1065
1066static __inline int
1067pf_state_compare_id(struct pf_state *a, struct pf_state *b)
1068{
0a7de745
A
1069 if (a->id > b->id) {
1070 return 1;
1071 }
1072 if (a->id < b->id) {
1073 return -1;
1074 }
1075 if (a->creatorid > b->creatorid) {
1076 return 1;
1077 }
1078 if (a->creatorid < b->creatorid) {
1079 return -1;
1080 }
1081
1082 return 0;
b0d623f7
A
1083}
1084
1085#if INET6
1086void
1087pf_addrcpy(struct pf_addr *dst, struct pf_addr *src, sa_family_t af)
1088{
1089 switch (af) {
1090#if INET
1091 case AF_INET:
1092 dst->addr32[0] = src->addr32[0];
1093 break;
1094#endif /* INET */
1095 case AF_INET6:
1096 dst->addr32[0] = src->addr32[0];
1097 dst->addr32[1] = src->addr32[1];
1098 dst->addr32[2] = src->addr32[2];
1099 dst->addr32[3] = src->addr32[3];
1100 break;
1101 }
1102}
1103#endif /* INET6 */
1104
1105struct pf_state *
1106pf_find_state_byid(struct pf_state_cmp *key)
1107{
1108 pf_status.fcounters[FCNT_STATE_SEARCH]++;
1109
0a7de745
A
1110 return RB_FIND(pf_state_tree_id, &tree_id,
1111 (struct pf_state *)(void *)key);
b0d623f7
A
1112}
1113
1114static struct pf_state *
1115pf_find_state(struct pfi_kif *kif, struct pf_state_key_cmp *key, u_int dir)
1116{
0a7de745
A
1117 struct pf_state_key *sk = NULL;
1118 struct pf_state *s;
b0d623f7
A
1119
1120 pf_status.fcounters[FCNT_STATE_SEARCH]++;
1121
1122 switch (dir) {
1123 case PF_OUT:
1124 sk = RB_FIND(pf_state_tree_lan_ext, &pf_statetbl_lan_ext,
1125 (struct pf_state_key *)key);
1126 break;
1127 case PF_IN:
1128 sk = RB_FIND(pf_state_tree_ext_gwy, &pf_statetbl_ext_gwy,
1129 (struct pf_state_key *)key);
3e170ce0
A
1130 /*
1131 * NAT64 is done only on input, for packets coming in from
1132 * from the LAN side, need to lookup the lan_ext tree.
1133 */
1134 if (sk == NULL) {
1135 sk = RB_FIND(pf_state_tree_lan_ext,
0a7de745
A
1136 &pf_statetbl_lan_ext,
1137 (struct pf_state_key *)key);
1138 if (sk && sk->af_lan == sk->af_gwy) {
3e170ce0 1139 sk = NULL;
0a7de745 1140 }
3e170ce0 1141 }
b0d623f7
A
1142 break;
1143 default:
1144 panic("pf_find_state");
1145 }
1146
1147 /* list is sorted, if-bound states before floating ones */
0a7de745 1148 if (sk != NULL) {
b0d623f7 1149 TAILQ_FOREACH(s, &sk->states, next)
0a7de745
A
1150 if (s->kif == pfi_all || s->kif == kif) {
1151 return s;
1152 }
1153 }
b0d623f7 1154
0a7de745 1155 return NULL;
b0d623f7
A
1156}
1157
1158struct pf_state *
1159pf_find_state_all(struct pf_state_key_cmp *key, u_int dir, int *more)
1160{
0a7de745
A
1161 struct pf_state_key *sk = NULL;
1162 struct pf_state *s, *ret = NULL;
b0d623f7
A
1163
1164 pf_status.fcounters[FCNT_STATE_SEARCH]++;
1165
1166 switch (dir) {
1167 case PF_OUT:
1168 sk = RB_FIND(pf_state_tree_lan_ext,
1169 &pf_statetbl_lan_ext, (struct pf_state_key *)key);
1170 break;
1171 case PF_IN:
1172 sk = RB_FIND(pf_state_tree_ext_gwy,
1173 &pf_statetbl_ext_gwy, (struct pf_state_key *)key);
3e170ce0
A
1174 /*
1175 * NAT64 is done only on input, for packets coming in from
1176 * from the LAN side, need to lookup the lan_ext tree.
1177 */
1178 if ((sk == NULL) && pf_nat64_configured) {
1179 sk = RB_FIND(pf_state_tree_lan_ext,
0a7de745
A
1180 &pf_statetbl_lan_ext,
1181 (struct pf_state_key *)key);
1182 if (sk && sk->af_lan == sk->af_gwy) {
3e170ce0 1183 sk = NULL;
0a7de745 1184 }
3e170ce0 1185 }
b0d623f7
A
1186 break;
1187 default:
1188 panic("pf_find_state_all");
1189 }
1190
1191 if (sk != NULL) {
1192 ret = TAILQ_FIRST(&sk->states);
0a7de745
A
1193 if (more == NULL) {
1194 return ret;
1195 }
b0d623f7
A
1196
1197 TAILQ_FOREACH(s, &sk->states, next)
0a7de745 1198 (*more)++;
b0d623f7
A
1199 }
1200
0a7de745 1201 return ret;
b0d623f7
A
1202}
1203
1204static void
1205pf_init_threshold(struct pf_threshold *threshold,
1206 u_int32_t limit, u_int32_t seconds)
1207{
1208 threshold->limit = limit * PF_THRESHOLD_MULT;
1209 threshold->seconds = seconds;
1210 threshold->count = 0;
1211 threshold->last = pf_time_second();
1212}
1213
1214static void
1215pf_add_threshold(struct pf_threshold *threshold)
1216{
1217 u_int32_t t = pf_time_second(), diff = t - threshold->last;
1218
0a7de745 1219 if (diff >= threshold->seconds) {
b0d623f7 1220 threshold->count = 0;
0a7de745 1221 } else {
b0d623f7
A
1222 threshold->count -= threshold->count * diff /
1223 threshold->seconds;
0a7de745 1224 }
b0d623f7
A
1225 threshold->count += PF_THRESHOLD_MULT;
1226 threshold->last = t;
1227}
1228
1229static int
1230pf_check_threshold(struct pf_threshold *threshold)
1231{
0a7de745 1232 return threshold->count > threshold->limit;
b0d623f7
A
1233}
1234
1235static int
1236pf_src_connlimit(struct pf_state **state)
1237{
1238 int bad = 0;
b0d623f7 1239 (*state)->src_node->conn++;
b7266188 1240 VERIFY((*state)->src_node->conn != 0);
b0d623f7
A
1241 (*state)->src.tcp_est = 1;
1242 pf_add_threshold(&(*state)->src_node->conn_rate);
1243
1244 if ((*state)->rule.ptr->max_src_conn &&
1245 (*state)->rule.ptr->max_src_conn <
1246 (*state)->src_node->conn) {
1247 pf_status.lcounters[LCNT_SRCCONN]++;
1248 bad++;
1249 }
1250
1251 if ((*state)->rule.ptr->max_src_conn_rate.limit &&
1252 pf_check_threshold(&(*state)->src_node->conn_rate)) {
1253 pf_status.lcounters[LCNT_SRCCONNRATE]++;
1254 bad++;
1255 }
1256
0a7de745
A
1257 if (!bad) {
1258 return 0;
1259 }
b0d623f7
A
1260
1261 if ((*state)->rule.ptr->overload_tbl) {
1262 struct pfr_addr p;
0a7de745 1263 u_int32_t killed = 0;
b0d623f7
A
1264
1265 pf_status.lcounters[LCNT_OVERLOAD_TABLE]++;
1266 if (pf_status.debug >= PF_DEBUG_MISC) {
1267 printf("pf_src_connlimit: blocking address ");
1268 pf_print_host(&(*state)->src_node->addr, 0,
0a7de745 1269 (*state)->state_key->af_lan);
b0d623f7
A
1270 }
1271
0a7de745 1272 bzero(&p, sizeof(p));
3e170ce0
A
1273 p.pfra_af = (*state)->state_key->af_lan;
1274 switch ((*state)->state_key->af_lan) {
b0d623f7
A
1275#if INET
1276 case AF_INET:
1277 p.pfra_net = 32;
5ba3f43e 1278 p.pfra_ip4addr = (*state)->src_node->addr.v4addr;
b0d623f7
A
1279 break;
1280#endif /* INET */
1281#if INET6
1282 case AF_INET6:
1283 p.pfra_net = 128;
5ba3f43e 1284 p.pfra_ip6addr = (*state)->src_node->addr.v6addr;
b0d623f7
A
1285 break;
1286#endif /* INET6 */
1287 }
1288
1289 pfr_insert_kentry((*state)->rule.ptr->overload_tbl,
d1ecb069 1290 &p, pf_calendar_time_second());
b0d623f7
A
1291
1292 /* kill existing states if that's required. */
1293 if ((*state)->rule.ptr->flush) {
1294 struct pf_state_key *sk;
1295 struct pf_state *st;
1296
1297 pf_status.lcounters[LCNT_OVERLOAD_FLUSH]++;
1298 RB_FOREACH(st, pf_state_tree_id, &tree_id) {
1299 sk = st->state_key;
1300 /*
1301 * Kill states from this source. (Only those
1302 * from the same rule if PF_FLUSH_GLOBAL is not
1303 * set)
1304 */
3e170ce0
A
1305 if (sk->af_lan ==
1306 (*state)->state_key->af_lan &&
b0d623f7 1307 (((*state)->state_key->direction ==
0a7de745 1308 PF_OUT &&
b0d623f7 1309 PF_AEQ(&(*state)->src_node->addr,
0a7de745 1310 &sk->lan.addr, sk->af_lan)) ||
b0d623f7
A
1311 ((*state)->state_key->direction == PF_IN &&
1312 PF_AEQ(&(*state)->src_node->addr,
0a7de745 1313 &sk->ext_lan.addr, sk->af_lan))) &&
b0d623f7
A
1314 ((*state)->rule.ptr->flush &
1315 PF_FLUSH_GLOBAL ||
1316 (*state)->rule.ptr == st->rule.ptr)) {
1317 st->timeout = PFTM_PURGE;
1318 st->src.state = st->dst.state =
1319 TCPS_CLOSED;
1320 killed++;
1321 }
1322 }
0a7de745 1323 if (pf_status.debug >= PF_DEBUG_MISC) {
b0d623f7 1324 printf(", %u states killed", killed);
0a7de745 1325 }
b0d623f7 1326 }
0a7de745 1327 if (pf_status.debug >= PF_DEBUG_MISC) {
b0d623f7 1328 printf("\n");
0a7de745 1329 }
b0d623f7
A
1330 }
1331
1332 /* kill this state */
1333 (*state)->timeout = PFTM_PURGE;
1334 (*state)->src.state = (*state)->dst.state = TCPS_CLOSED;
0a7de745 1335 return 1;
b0d623f7
A
1336}
1337
1338int
1339pf_insert_src_node(struct pf_src_node **sn, struct pf_rule *rule,
1340 struct pf_addr *src, sa_family_t af)
1341{
0a7de745 1342 struct pf_src_node k;
b0d623f7
A
1343
1344 if (*sn == NULL) {
1345 k.af = af;
1346 PF_ACPY(&k.addr, src, af);
1347 if (rule->rule_flag & PFRULE_RULESRCTRACK ||
0a7de745 1348 rule->rpool.opts & PF_POOL_STICKYADDR) {
b0d623f7 1349 k.rule.ptr = rule;
0a7de745 1350 } else {
b0d623f7 1351 k.rule.ptr = NULL;
0a7de745 1352 }
b0d623f7
A
1353 pf_status.scounters[SCNT_SRC_NODE_SEARCH]++;
1354 *sn = RB_FIND(pf_src_tree, &tree_src_tracking, &k);
1355 }
1356 if (*sn == NULL) {
1357 if (!rule->max_src_nodes ||
0a7de745 1358 rule->src_nodes < rule->max_src_nodes) {
b0d623f7 1359 (*sn) = pool_get(&pf_src_tree_pl, PR_WAITOK);
0a7de745 1360 } else {
b0d623f7 1361 pf_status.lcounters[LCNT_SRCNODES]++;
0a7de745
A
1362 }
1363 if ((*sn) == NULL) {
1364 return -1;
1365 }
1366 bzero(*sn, sizeof(struct pf_src_node));
b0d623f7
A
1367
1368 pf_init_threshold(&(*sn)->conn_rate,
1369 rule->max_src_conn_rate.limit,
1370 rule->max_src_conn_rate.seconds);
1371
1372 (*sn)->af = af;
1373 if (rule->rule_flag & PFRULE_RULESRCTRACK ||
0a7de745 1374 rule->rpool.opts & PF_POOL_STICKYADDR) {
b0d623f7 1375 (*sn)->rule.ptr = rule;
0a7de745 1376 } else {
b0d623f7 1377 (*sn)->rule.ptr = NULL;
0a7de745 1378 }
b0d623f7
A
1379 PF_ACPY(&(*sn)->addr, src, af);
1380 if (RB_INSERT(pf_src_tree,
1381 &tree_src_tracking, *sn) != NULL) {
1382 if (pf_status.debug >= PF_DEBUG_MISC) {
1383 printf("pf: src_tree insert failed: ");
1384 pf_print_host(&(*sn)->addr, 0, af);
1385 printf("\n");
1386 }
1387 pool_put(&pf_src_tree_pl, *sn);
0a7de745 1388 return -1;
b0d623f7
A
1389 }
1390 (*sn)->creation = pf_time_second();
1391 (*sn)->ruletype = rule->action;
0a7de745 1392 if ((*sn)->rule.ptr != NULL) {
b0d623f7 1393 (*sn)->rule.ptr->src_nodes++;
0a7de745 1394 }
b0d623f7
A
1395 pf_status.scounters[SCNT_SRC_NODE_INSERT]++;
1396 pf_status.src_nodes++;
1397 } else {
1398 if (rule->max_src_states &&
1399 (*sn)->states >= rule->max_src_states) {
1400 pf_status.lcounters[LCNT_SRCSTATES]++;
0a7de745 1401 return -1;
b0d623f7
A
1402 }
1403 }
0a7de745 1404 return 0;
b0d623f7
A
1405}
1406
1407static void
1408pf_stateins_err(const char *tree, struct pf_state *s, struct pfi_kif *kif)
1409{
0a7de745 1410 struct pf_state_key *sk = s->state_key;
b0d623f7
A
1411
1412 if (pf_status.debug >= PF_DEBUG_MISC) {
b0d623f7
A
1413 printf("pf: state insert failed: %s %s ", tree, kif->pfik_name);
1414 switch (sk->proto) {
1415 case IPPROTO_TCP:
1416 printf("TCP");
1417 break;
1418 case IPPROTO_UDP:
1419 printf("UDP");
1420 break;
1421 case IPPROTO_ICMP:
1422 printf("ICMP4");
1423 break;
1424 case IPPROTO_ICMPV6:
1425 printf("ICMP6");
1426 break;
1427 default:
1428 printf("PROTO=%u", sk->proto);
1429 break;
1430 }
1431 printf(" lan: ");
3e170ce0 1432 pf_print_sk_host(&sk->lan, sk->af_lan, sk->proto,
b0d623f7
A
1433 sk->proto_variant);
1434 printf(" gwy: ");
3e170ce0
A
1435 pf_print_sk_host(&sk->gwy, sk->af_gwy, sk->proto,
1436 sk->proto_variant);
1437 printf(" ext_lan: ");
1438 pf_print_sk_host(&sk->ext_lan, sk->af_lan, sk->proto,
b0d623f7 1439 sk->proto_variant);
3e170ce0
A
1440 printf(" ext_gwy: ");
1441 pf_print_sk_host(&sk->ext_gwy, sk->af_gwy, sk->proto,
b0d623f7 1442 sk->proto_variant);
0a7de745 1443 if (s->sync_flags & PFSTATE_FROMSYNC) {
b0d623f7 1444 printf(" (from sync)");
0a7de745 1445 }
b0d623f7
A
1446 printf("\n");
1447 }
1448}
1449
1450int
1451pf_insert_state(struct pfi_kif *kif, struct pf_state *s)
1452{
0a7de745
A
1453 struct pf_state_key *cur;
1454 struct pf_state *sp;
b0d623f7
A
1455
1456 VERIFY(s->state_key != NULL);
1457 s->kif = kif;
1458
1459 if ((cur = RB_INSERT(pf_state_tree_lan_ext, &pf_statetbl_lan_ext,
1460 s->state_key)) != NULL) {
1461 /* key exists. check for same kif, if none, add to key */
1462 TAILQ_FOREACH(sp, &cur->states, next)
0a7de745
A
1463 if (sp->kif == kif) { /* collision! */
1464 pf_stateins_err("tree_lan_ext", s, kif);
1465 pf_detach_state(s,
1466 PF_DT_SKIP_LANEXT | PF_DT_SKIP_EXTGWY);
1467 return -1;
1468 }
1469 pf_detach_state(s, PF_DT_SKIP_LANEXT | PF_DT_SKIP_EXTGWY);
b0d623f7
A
1470 pf_attach_state(cur, s, kif == pfi_all ? 1 : 0);
1471 }
1472
1473 /* if cur != NULL, we already found a state key and attached to it */
1474 if (cur == NULL && (cur = RB_INSERT(pf_state_tree_ext_gwy,
1475 &pf_statetbl_ext_gwy, s->state_key)) != NULL) {
1476 /* must not happen. we must have found the sk above! */
1477 pf_stateins_err("tree_ext_gwy", s, kif);
1478 pf_detach_state(s, PF_DT_SKIP_EXTGWY);
0a7de745 1479 return -1;
b0d623f7
A
1480 }
1481
1482 if (s->id == 0 && s->creatorid == 0) {
1483 s->id = htobe64(pf_status.stateid++);
1484 s->creatorid = pf_status.hostid;
1485 }
1486 if (RB_INSERT(pf_state_tree_id, &tree_id, s) != NULL) {
1487 if (pf_status.debug >= PF_DEBUG_MISC) {
1488 printf("pf: state insert failed: "
1489 "id: %016llx creatorid: %08x",
1490 be64toh(s->id), ntohl(s->creatorid));
0a7de745 1491 if (s->sync_flags & PFSTATE_FROMSYNC) {
b0d623f7 1492 printf(" (from sync)");
0a7de745 1493 }
b0d623f7
A
1494 printf("\n");
1495 }
1496 pf_detach_state(s, 0);
0a7de745 1497 return -1;
b0d623f7
A
1498 }
1499 TAILQ_INSERT_TAIL(&state_list, s, entry_list);
1500 pf_status.fcounters[FCNT_STATE_INSERT]++;
1501 pf_status.states++;
b7266188 1502 VERIFY(pf_status.states != 0);
b0d623f7
A
1503 pfi_kif_ref(kif, PFI_KIF_REF_STATE);
1504#if NPFSYNC
1505 pfsync_insert_state(s);
1506#endif
0a7de745 1507 return 0;
b0d623f7
A
1508}
1509
316670eb
A
1510static int
1511pf_purge_thread_cont(int err)
b0d623f7 1512{
316670eb
A
1513#pragma unused(err)
1514 static u_int32_t nloops = 0;
0a7de745 1515 int t = 1; /* 1 second */
316670eb 1516
39236c6e
A
1517 /*
1518 * Update coarse-grained networking timestamp (in sec.); the idea
1519 * is to piggy-back on the periodic timeout callout to update
1520 * the counter returnable via net_uptime().
1521 */
1522 net_update_uptime();
1523
316670eb
A
1524 lck_rw_lock_shared(pf_perim_lock);
1525 lck_mtx_lock(pf_lock);
1526
1527 /* purge everything if not running */
1528 if (!pf_status.running) {
1529 pf_purge_expired_states(pf_status.states);
1530 pf_purge_expired_fragments();
1531 pf_purge_expired_src_nodes();
1532
1533 /* terminate thread (we don't currently do this) */
1534 if (pf_purge_thread == NULL) {
1535 lck_mtx_unlock(pf_lock);
1536 lck_rw_done(pf_perim_lock);
1537
1538 thread_deallocate(current_thread());
1539 thread_terminate(current_thread());
1540 /* NOTREACHED */
0a7de745 1541 return 0;
316670eb
A
1542 } else {
1543 /* if there's nothing left, sleep w/o timeout */
1544 if (pf_status.states == 0 &&
1545 pf_normalize_isempty() &&
1546 RB_EMPTY(&tree_src_tracking)) {
1547 nloops = 0;
1548 t = 0;
b0d623f7 1549 }
316670eb 1550 goto done;
b0d623f7 1551 }
316670eb 1552 }
b0d623f7 1553
316670eb
A
1554 /* process a fraction of the state table every second */
1555 pf_purge_expired_states(1 + (pf_status.states
1556 / pf_default_rule.timeout[PFTM_INTERVAL]));
b0d623f7 1557
316670eb
A
1558 /* purge other expired types every PFTM_INTERVAL seconds */
1559 if (++nloops >= pf_default_rule.timeout[PFTM_INTERVAL]) {
1560 pf_purge_expired_fragments();
1561 pf_purge_expired_src_nodes();
1562 nloops = 0;
b0d623f7 1563 }
316670eb
A
1564done:
1565 lck_mtx_unlock(pf_lock);
1566 lck_rw_done(pf_perim_lock);
1567
1568 (void) tsleep0(pf_purge_thread_fn, PWAIT, "pf_purge_cont",
1569 t * hz, pf_purge_thread_cont);
1570 /* NOTREACHED */
1571 VERIFY(0);
1572
0a7de745 1573 return 0;
316670eb
A
1574}
1575
1576void
1577pf_purge_thread_fn(void *v, wait_result_t w)
1578{
1579#pragma unused(v, w)
1580 (void) tsleep0(pf_purge_thread_fn, PWAIT, "pf_purge", 0,
1581 pf_purge_thread_cont);
1582 /*
1583 * tsleep0() shouldn't have returned as PCATCH was not set;
1584 * therefore assert in this case.
1585 */
1586 VERIFY(0);
b0d623f7
A
1587}
1588
1589u_int64_t
1590pf_state_expires(const struct pf_state *state)
1591{
0a7de745
A
1592 u_int32_t t;
1593 u_int32_t start;
1594 u_int32_t end;
1595 u_int32_t states;
b0d623f7 1596
5ba3f43e 1597 LCK_MTX_ASSERT(pf_lock, LCK_MTX_ASSERT_OWNED);
b0d623f7
A
1598
1599 /* handle all PFTM_* > PFTM_MAX here */
0a7de745
A
1600 if (state->timeout == PFTM_PURGE) {
1601 return pf_time_second();
1602 }
fe8ab488 1603
b0d623f7
A
1604 VERIFY(state->timeout != PFTM_UNLINKED);
1605 VERIFY(state->timeout < PFTM_MAX);
1606 t = state->rule.ptr->timeout[state->timeout];
0a7de745 1607 if (!t) {
b0d623f7 1608 t = pf_default_rule.timeout[state->timeout];
0a7de745 1609 }
b0d623f7
A
1610 start = state->rule.ptr->timeout[PFTM_ADAPTIVE_START];
1611 if (start) {
1612 end = state->rule.ptr->timeout[PFTM_ADAPTIVE_END];
1613 states = state->rule.ptr->states;
1614 } else {
1615 start = pf_default_rule.timeout[PFTM_ADAPTIVE_START];
1616 end = pf_default_rule.timeout[PFTM_ADAPTIVE_END];
1617 states = pf_status.states;
1618 }
1619 if (end && states > start && start < end) {
0a7de745
A
1620 if (states < end) {
1621 return state->expire + t * (end - states) /
1622 (end - start);
1623 } else {
1624 return pf_time_second();
1625 }
b0d623f7 1626 }
0a7de745 1627 return state->expire + t;
b0d623f7
A
1628}
1629
1630void
1631pf_purge_expired_src_nodes(void)
1632{
0a7de745 1633 struct pf_src_node *cur, *next;
b0d623f7 1634
5ba3f43e 1635 LCK_MTX_ASSERT(pf_lock, LCK_MTX_ASSERT_OWNED);
b0d623f7
A
1636
1637 for (cur = RB_MIN(pf_src_tree, &tree_src_tracking); cur; cur = next) {
1638 next = RB_NEXT(pf_src_tree, &tree_src_tracking, cur);
1639
1640 if (cur->states <= 0 && cur->expire <= pf_time_second()) {
1641 if (cur->rule.ptr != NULL) {
1642 cur->rule.ptr->src_nodes--;
1643 if (cur->rule.ptr->states <= 0 &&
0a7de745 1644 cur->rule.ptr->max_src_nodes <= 0) {
b0d623f7 1645 pf_rm_rule(NULL, cur->rule.ptr);
0a7de745 1646 }
b0d623f7
A
1647 }
1648 RB_REMOVE(pf_src_tree, &tree_src_tracking, cur);
1649 pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
1650 pf_status.src_nodes--;
1651 pool_put(&pf_src_tree_pl, cur);
1652 }
1653 }
1654}
1655
1656void
1657pf_src_tree_remove_state(struct pf_state *s)
1658{
1659 u_int32_t t;
1660
5ba3f43e 1661 LCK_MTX_ASSERT(pf_lock, LCK_MTX_ASSERT_OWNED);
b0d623f7
A
1662
1663 if (s->src_node != NULL) {
b7266188
A
1664 if (s->src.tcp_est) {
1665 VERIFY(s->src_node->conn > 0);
b0d623f7 1666 --s->src_node->conn;
b7266188
A
1667 }
1668 VERIFY(s->src_node->states > 0);
b0d623f7
A
1669 if (--s->src_node->states <= 0) {
1670 t = s->rule.ptr->timeout[PFTM_SRC_NODE];
0a7de745 1671 if (!t) {
b0d623f7 1672 t = pf_default_rule.timeout[PFTM_SRC_NODE];
0a7de745 1673 }
b0d623f7
A
1674 s->src_node->expire = pf_time_second() + t;
1675 }
1676 }
1677 if (s->nat_src_node != s->src_node && s->nat_src_node != NULL) {
b7266188 1678 VERIFY(s->nat_src_node->states > 0);
b0d623f7
A
1679 if (--s->nat_src_node->states <= 0) {
1680 t = s->rule.ptr->timeout[PFTM_SRC_NODE];
0a7de745 1681 if (!t) {
b0d623f7 1682 t = pf_default_rule.timeout[PFTM_SRC_NODE];
0a7de745 1683 }
b0d623f7
A
1684 s->nat_src_node->expire = pf_time_second() + t;
1685 }
1686 }
1687 s->src_node = s->nat_src_node = NULL;
1688}
1689
1690void
1691pf_unlink_state(struct pf_state *cur)
1692{
5ba3f43e 1693 LCK_MTX_ASSERT(pf_lock, LCK_MTX_ASSERT_OWNED);
b0d623f7 1694
b0d623f7 1695 if (cur->src.state == PF_TCPS_PROXY_DST) {
3e170ce0
A
1696 pf_send_tcp(cur->rule.ptr, cur->state_key->af_lan,
1697 &cur->state_key->ext_lan.addr, &cur->state_key->lan.addr,
1698 cur->state_key->ext_lan.xport.port,
b0d623f7
A
1699 cur->state_key->lan.xport.port,
1700 cur->src.seqhi, cur->src.seqlo + 1,
0a7de745 1701 TH_RST | TH_ACK, 0, 0, 0, 1, cur->tag, NULL, NULL);
b0d623f7
A
1702 }
1703
0a7de745 1704 hook_runloop(&cur->unlink_hooks, HOOK_REMOVE | HOOK_FREE);
b0d623f7
A
1705 RB_REMOVE(pf_state_tree_id, &tree_id, cur);
1706#if NPFSYNC
0a7de745 1707 if (cur->creatorid == pf_status.hostid) {
b0d623f7 1708 pfsync_delete_state(cur);
0a7de745 1709 }
b0d623f7
A
1710#endif
1711 cur->timeout = PFTM_UNLINKED;
1712 pf_src_tree_remove_state(cur);
1713 pf_detach_state(cur, 0);
1714}
1715
1716/* callers should be at splpf and hold the
1717 * write_lock on pf_consistency_lock */
1718void
1719pf_free_state(struct pf_state *cur)
1720{
5ba3f43e 1721 LCK_MTX_ASSERT(pf_lock, LCK_MTX_ASSERT_OWNED);
b0d623f7
A
1722#if NPFSYNC
1723 if (pfsyncif != NULL &&
1724 (pfsyncif->sc_bulk_send_next == cur ||
0a7de745 1725 pfsyncif->sc_bulk_terminator == cur)) {
b0d623f7 1726 return;
0a7de745 1727 }
b0d623f7
A
1728#endif
1729 VERIFY(cur->timeout == PFTM_UNLINKED);
b7266188 1730 VERIFY(cur->rule.ptr->states > 0);
b0d623f7 1731 if (--cur->rule.ptr->states <= 0 &&
0a7de745 1732 cur->rule.ptr->src_nodes <= 0) {
b0d623f7 1733 pf_rm_rule(NULL, cur->rule.ptr);
0a7de745 1734 }
b7266188
A
1735 if (cur->nat_rule.ptr != NULL) {
1736 VERIFY(cur->nat_rule.ptr->states > 0);
b0d623f7 1737 if (--cur->nat_rule.ptr->states <= 0 &&
0a7de745 1738 cur->nat_rule.ptr->src_nodes <= 0) {
b0d623f7 1739 pf_rm_rule(NULL, cur->nat_rule.ptr);
0a7de745 1740 }
b7266188
A
1741 }
1742 if (cur->anchor.ptr != NULL) {
1743 VERIFY(cur->anchor.ptr->states > 0);
0a7de745 1744 if (--cur->anchor.ptr->states <= 0) {
b0d623f7 1745 pf_rm_rule(NULL, cur->anchor.ptr);
0a7de745 1746 }
b7266188 1747 }
b0d623f7
A
1748 pf_normalize_tcp_cleanup(cur);
1749 pfi_kif_unref(cur->kif, PFI_KIF_REF_STATE);
1750 TAILQ_REMOVE(&state_list, cur, entry_list);
0a7de745 1751 if (cur->tag) {
b0d623f7 1752 pf_tag_unref(cur->tag);
0a7de745 1753 }
b0d623f7
A
1754 pool_put(&pf_state_pl, cur);
1755 pf_status.fcounters[FCNT_STATE_REMOVALS]++;
b7266188 1756 VERIFY(pf_status.states > 0);
b0d623f7
A
1757 pf_status.states--;
1758}
1759
1760void
1761pf_purge_expired_states(u_int32_t maxcheck)
1762{
0a7de745
A
1763 static struct pf_state *cur = NULL;
1764 struct pf_state *next;
b0d623f7 1765
5ba3f43e 1766 LCK_MTX_ASSERT(pf_lock, LCK_MTX_ASSERT_OWNED);
b0d623f7
A
1767
1768 while (maxcheck--) {
1769 /* wrap to start of list when we hit the end */
1770 if (cur == NULL) {
1771 cur = TAILQ_FIRST(&state_list);
0a7de745
A
1772 if (cur == NULL) {
1773 break; /* list empty */
1774 }
b0d623f7
A
1775 }
1776
1777 /* get next state, as cur may get deleted */
1778 next = TAILQ_NEXT(cur, entry_list);
1779
1780 if (cur->timeout == PFTM_UNLINKED) {
1781 pf_free_state(cur);
1782 } else if (pf_state_expires(cur) <= pf_time_second()) {
1783 /* unlink and free expired state */
1784 pf_unlink_state(cur);
1785 pf_free_state(cur);
1786 }
1787 cur = next;
1788 }
1789}
1790
1791int
1792pf_tbladdr_setup(struct pf_ruleset *rs, struct pf_addr_wrap *aw)
1793{
5ba3f43e 1794 LCK_MTX_ASSERT(pf_lock, LCK_MTX_ASSERT_OWNED);
b0d623f7 1795
0a7de745
A
1796 if (aw->type != PF_ADDR_TABLE) {
1797 return 0;
1798 }
1799 if ((aw->p.tbl = pfr_attach_table(rs, aw->v.tblname)) == NULL) {
1800 return 1;
1801 }
1802 return 0;
b0d623f7
A
1803}
1804
1805void
1806pf_tbladdr_remove(struct pf_addr_wrap *aw)
1807{
5ba3f43e 1808 LCK_MTX_ASSERT(pf_lock, LCK_MTX_ASSERT_OWNED);
b0d623f7 1809
0a7de745 1810 if (aw->type != PF_ADDR_TABLE || aw->p.tbl == NULL) {
b0d623f7 1811 return;
0a7de745 1812 }
b0d623f7
A
1813 pfr_detach_table(aw->p.tbl);
1814 aw->p.tbl = NULL;
1815}
1816
1817void
1818pf_tbladdr_copyout(struct pf_addr_wrap *aw)
1819{
1820 struct pfr_ktable *kt = aw->p.tbl;
1821
5ba3f43e 1822 LCK_MTX_ASSERT(pf_lock, LCK_MTX_ASSERT_OWNED);
b0d623f7 1823
0a7de745 1824 if (aw->type != PF_ADDR_TABLE || kt == NULL) {
b0d623f7 1825 return;
0a7de745
A
1826 }
1827 if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE) && kt->pfrkt_root != NULL) {
b0d623f7 1828 kt = kt->pfrkt_root;
0a7de745 1829 }
b0d623f7
A
1830 aw->p.tbl = NULL;
1831 aw->p.tblcnt = (kt->pfrkt_flags & PFR_TFLAG_ACTIVE) ?
1832 kt->pfrkt_cnt : -1;
1833}
1834
b0d623f7
A
1835static void
1836pf_print_addr(struct pf_addr *addr, sa_family_t af)
1837{
1838 switch (af) {
1839#if INET
1840 case AF_INET: {
1841 u_int32_t a = ntohl(addr->addr32[0]);
0a7de745
A
1842 printf("%u.%u.%u.%u", (a >> 24) & 255, (a >> 16) & 255,
1843 (a >> 8) & 255, a & 255);
b0d623f7
A
1844 break;
1845 }
1846#endif /* INET */
1847#if INET6
1848 case AF_INET6: {
1849 u_int16_t b;
1850 u_int8_t i, curstart = 255, curend = 0,
1851 maxstart = 0, maxend = 0;
1852 for (i = 0; i < 8; i++) {
1853 if (!addr->addr16[i]) {
0a7de745 1854 if (curstart == 255) {
b0d623f7 1855 curstart = i;
0a7de745 1856 } else {
b0d623f7 1857 curend = i;
0a7de745 1858 }
b0d623f7
A
1859 } else {
1860 if (curstart) {
1861 if ((curend - curstart) >
1862 (maxend - maxstart)) {
1863 maxstart = curstart;
1864 maxend = curend;
1865 curstart = 255;
1866 }
1867 }
1868 }
1869 }
1870 for (i = 0; i < 8; i++) {
1871 if (i >= maxstart && i <= maxend) {
1872 if (maxend != 7) {
0a7de745 1873 if (i == maxstart) {
b0d623f7 1874 printf(":");
0a7de745 1875 }
b0d623f7 1876 } else {
0a7de745 1877 if (i == maxend) {
b0d623f7 1878 printf(":");
0a7de745 1879 }
b0d623f7
A
1880 }
1881 } else {
1882 b = ntohs(addr->addr16[i]);
1883 printf("%x", b);
0a7de745 1884 if (i < 7) {
b0d623f7 1885 printf(":");
0a7de745 1886 }
b0d623f7
A
1887 }
1888 }
1889 break;
1890 }
1891#endif /* INET6 */
1892 }
1893}
1894
1895static void
1896pf_print_sk_host(struct pf_state_host *sh, sa_family_t af, int proto,
0a7de745 1897 u_int8_t proto_variant)
b0d623f7
A
1898{
1899 pf_print_addr(&sh->addr, af);
1900
1901 switch (proto) {
1902 case IPPROTO_ESP:
0a7de745 1903 if (sh->xport.spi) {
b0d623f7 1904 printf("[%08x]", ntohl(sh->xport.spi));
0a7de745 1905 }
b0d623f7
A
1906 break;
1907
1908 case IPPROTO_GRE:
0a7de745 1909 if (proto_variant == PF_GRE_PPTP_VARIANT) {
b0d623f7 1910 printf("[%u]", ntohs(sh->xport.call_id));
0a7de745 1911 }
b0d623f7
A
1912 break;
1913
1914 case IPPROTO_TCP:
1915 case IPPROTO_UDP:
1916 printf("[%u]", ntohs(sh->xport.port));
1917 break;
1918
1919 default:
1920 break;
1921 }
1922}
b0d623f7
A
1923
1924static void
1925pf_print_host(struct pf_addr *addr, u_int16_t p, sa_family_t af)
1926{
b0d623f7 1927 pf_print_addr(addr, af);
0a7de745 1928 if (p) {
b0d623f7 1929 printf("[%u]", ntohs(p));
0a7de745 1930 }
b0d623f7
A
1931}
1932
1933void
1934pf_print_state(struct pf_state *s)
1935{
1936 struct pf_state_key *sk = s->state_key;
1937 switch (sk->proto) {
b0d623f7
A
1938 case IPPROTO_ESP:
1939 printf("ESP ");
1940 break;
1941 case IPPROTO_GRE:
1942 printf("GRE%u ", sk->proto_variant);
1943 break;
b0d623f7
A
1944 case IPPROTO_TCP:
1945 printf("TCP ");
1946 break;
1947 case IPPROTO_UDP:
1948 printf("UDP ");
1949 break;
1950 case IPPROTO_ICMP:
1951 printf("ICMP ");
1952 break;
1953 case IPPROTO_ICMPV6:
1954 printf("ICMPV6 ");
1955 break;
1956 default:
1957 printf("%u ", sk->proto);
1958 break;
1959 }
3e170ce0
A
1960 pf_print_sk_host(&sk->lan, sk->af_lan, sk->proto, sk->proto_variant);
1961 printf(" ");
1962 pf_print_sk_host(&sk->gwy, sk->af_gwy, sk->proto, sk->proto_variant);
b0d623f7 1963 printf(" ");
3e170ce0 1964 pf_print_sk_host(&sk->ext_lan, sk->af_lan, sk->proto,
0a7de745 1965 sk->proto_variant);
b0d623f7 1966 printf(" ");
3e170ce0 1967 pf_print_sk_host(&sk->ext_gwy, sk->af_gwy, sk->proto,
0a7de745 1968 sk->proto_variant);
b0d623f7
A
1969 printf(" [lo=%u high=%u win=%u modulator=%u", s->src.seqlo,
1970 s->src.seqhi, s->src.max_win, s->src.seqdiff);
0a7de745 1971 if (s->src.wscale && s->dst.wscale) {
b0d623f7 1972 printf(" wscale=%u", s->src.wscale & PF_WSCALE_MASK);
0a7de745 1973 }
b0d623f7
A
1974 printf("]");
1975 printf(" [lo=%u high=%u win=%u modulator=%u", s->dst.seqlo,
1976 s->dst.seqhi, s->dst.max_win, s->dst.seqdiff);
0a7de745 1977 if (s->src.wscale && s->dst.wscale) {
b0d623f7 1978 printf(" wscale=%u", s->dst.wscale & PF_WSCALE_MASK);
0a7de745 1979 }
b0d623f7
A
1980 printf("]");
1981 printf(" %u:%u", s->src.state, s->dst.state);
1982}
1983
1984void
1985pf_print_flags(u_int8_t f)
1986{
0a7de745 1987 if (f) {
b0d623f7 1988 printf(" ");
0a7de745
A
1989 }
1990 if (f & TH_FIN) {
b0d623f7 1991 printf("F");
0a7de745
A
1992 }
1993 if (f & TH_SYN) {
b0d623f7 1994 printf("S");
0a7de745
A
1995 }
1996 if (f & TH_RST) {
b0d623f7 1997 printf("R");
0a7de745
A
1998 }
1999 if (f & TH_PUSH) {
b0d623f7 2000 printf("P");
0a7de745
A
2001 }
2002 if (f & TH_ACK) {
b0d623f7 2003 printf("A");
0a7de745
A
2004 }
2005 if (f & TH_URG) {
b0d623f7 2006 printf("U");
0a7de745
A
2007 }
2008 if (f & TH_ECE) {
b0d623f7 2009 printf("E");
0a7de745
A
2010 }
2011 if (f & TH_CWR) {
b0d623f7 2012 printf("W");
0a7de745 2013 }
b0d623f7
A
2014}
2015
0a7de745
A
2016#define PF_SET_SKIP_STEPS(i) \
2017 do { \
2018 while (head[i] != cur) { \
2019 head[i]->skip[i].ptr = cur; \
2020 head[i] = TAILQ_NEXT(head[i], entries); \
2021 } \
b0d623f7
A
2022 } while (0)
2023
2024void
2025pf_calc_skip_steps(struct pf_rulequeue *rules)
2026{
2027 struct pf_rule *cur, *prev, *head[PF_SKIP_COUNT];
2028 int i;
2029
2030 cur = TAILQ_FIRST(rules);
2031 prev = cur;
0a7de745 2032 for (i = 0; i < PF_SKIP_COUNT; ++i) {
b0d623f7 2033 head[i] = cur;
0a7de745 2034 }
b0d623f7 2035 while (cur != NULL) {
0a7de745 2036 if (cur->kif != prev->kif || cur->ifnot != prev->ifnot) {
b0d623f7 2037 PF_SET_SKIP_STEPS(PF_SKIP_IFP);
0a7de745
A
2038 }
2039 if (cur->direction != prev->direction) {
b0d623f7 2040 PF_SET_SKIP_STEPS(PF_SKIP_DIR);
0a7de745
A
2041 }
2042 if (cur->af != prev->af) {
b0d623f7 2043 PF_SET_SKIP_STEPS(PF_SKIP_AF);
0a7de745
A
2044 }
2045 if (cur->proto != prev->proto) {
b0d623f7 2046 PF_SET_SKIP_STEPS(PF_SKIP_PROTO);
0a7de745 2047 }
b0d623f7 2048 if (cur->src.neg != prev->src.neg ||
0a7de745 2049 pf_addr_wrap_neq(&cur->src.addr, &prev->src.addr)) {
b0d623f7 2050 PF_SET_SKIP_STEPS(PF_SKIP_SRC_ADDR);
0a7de745 2051 }
b0d623f7
A
2052 {
2053 union pf_rule_xport *cx = &cur->src.xport;
2054 union pf_rule_xport *px = &prev->src.xport;
2055
2056 switch (cur->proto) {
2057 case IPPROTO_GRE:
2058 case IPPROTO_ESP:
2059 PF_SET_SKIP_STEPS(PF_SKIP_SRC_PORT);
2060 break;
2061 default:
2062 if (prev->proto == IPPROTO_GRE ||
2063 prev->proto == IPPROTO_ESP ||
2064 cx->range.op != px->range.op ||
2065 cx->range.port[0] != px->range.port[0] ||
0a7de745 2066 cx->range.port[1] != px->range.port[1]) {
b0d623f7 2067 PF_SET_SKIP_STEPS(PF_SKIP_SRC_PORT);
0a7de745 2068 }
b0d623f7
A
2069 break;
2070 }
2071 }
b0d623f7 2072 if (cur->dst.neg != prev->dst.neg ||
0a7de745 2073 pf_addr_wrap_neq(&cur->dst.addr, &prev->dst.addr)) {
b0d623f7 2074 PF_SET_SKIP_STEPS(PF_SKIP_DST_ADDR);
0a7de745 2075 }
b0d623f7
A
2076 {
2077 union pf_rule_xport *cx = &cur->dst.xport;
2078 union pf_rule_xport *px = &prev->dst.xport;
2079
2080 switch (cur->proto) {
2081 case IPPROTO_GRE:
2082 if (cur->proto != prev->proto ||
0a7de745 2083 cx->call_id != px->call_id) {
b0d623f7 2084 PF_SET_SKIP_STEPS(PF_SKIP_DST_PORT);
0a7de745 2085 }
b0d623f7
A
2086 break;
2087 case IPPROTO_ESP:
2088 if (cur->proto != prev->proto ||
0a7de745 2089 cx->spi != px->spi) {
b0d623f7 2090 PF_SET_SKIP_STEPS(PF_SKIP_DST_PORT);
0a7de745 2091 }
b0d623f7
A
2092 break;
2093 default:
2094 if (prev->proto == IPPROTO_GRE ||
2095 prev->proto == IPPROTO_ESP ||
2096 cx->range.op != px->range.op ||
2097 cx->range.port[0] != px->range.port[0] ||
0a7de745 2098 cx->range.port[1] != px->range.port[1]) {
b0d623f7 2099 PF_SET_SKIP_STEPS(PF_SKIP_DST_PORT);
0a7de745 2100 }
b0d623f7
A
2101 break;
2102 }
2103 }
b0d623f7
A
2104
2105 prev = cur;
2106 cur = TAILQ_NEXT(cur, entries);
2107 }
0a7de745 2108 for (i = 0; i < PF_SKIP_COUNT; ++i) {
b0d623f7 2109 PF_SET_SKIP_STEPS(i);
0a7de745 2110 }
b0d623f7
A
2111}
2112
316670eb
A
2113u_int32_t
2114pf_calc_state_key_flowhash(struct pf_state_key *sk)
2115{
2116 struct pf_flowhash_key fh __attribute__((aligned(8)));
39236c6e 2117 uint32_t flowhash = 0;
316670eb 2118
0a7de745 2119 bzero(&fh, sizeof(fh));
3e170ce0 2120 if (PF_ALEQ(&sk->lan.addr, &sk->ext_lan.addr, sk->af_lan)) {
0a7de745
A
2121 bcopy(&sk->lan.addr, &fh.ap1.addr, sizeof(fh.ap1.addr));
2122 bcopy(&sk->ext_lan.addr, &fh.ap2.addr, sizeof(fh.ap2.addr));
316670eb 2123 } else {
0a7de745
A
2124 bcopy(&sk->ext_lan.addr, &fh.ap1.addr, sizeof(fh.ap1.addr));
2125 bcopy(&sk->lan.addr, &fh.ap2.addr, sizeof(fh.ap2.addr));
316670eb 2126 }
3e170ce0 2127 if (sk->lan.xport.spi <= sk->ext_lan.xport.spi) {
316670eb 2128 fh.ap1.xport.spi = sk->lan.xport.spi;
3e170ce0 2129 fh.ap2.xport.spi = sk->ext_lan.xport.spi;
316670eb 2130 } else {
3e170ce0 2131 fh.ap1.xport.spi = sk->ext_lan.xport.spi;
316670eb
A
2132 fh.ap2.xport.spi = sk->lan.xport.spi;
2133 }
3e170ce0 2134 fh.af = sk->af_lan;
316670eb
A
2135 fh.proto = sk->proto;
2136
39236c6e 2137try_again:
0a7de745 2138 flowhash = net_flowhash(&fh, sizeof(fh), pf_hash_seed);
39236c6e
A
2139 if (flowhash == 0) {
2140 /* try to get a non-zero flowhash */
2141 pf_hash_seed = RandomULong();
2142 goto try_again;
2143 }
2144
0a7de745 2145 return flowhash;
316670eb
A
2146}
2147
b0d623f7
A
2148static int
2149pf_addr_wrap_neq(struct pf_addr_wrap *aw1, struct pf_addr_wrap *aw2)
2150{
0a7de745
A
2151 if (aw1->type != aw2->type) {
2152 return 1;
2153 }
b0d623f7
A
2154 switch (aw1->type) {
2155 case PF_ADDR_ADDRMASK:
2156 case PF_ADDR_RANGE:
0a7de745
A
2157 if (PF_ANEQ(&aw1->v.a.addr, &aw2->v.a.addr, 0)) {
2158 return 1;
2159 }
2160 if (PF_ANEQ(&aw1->v.a.mask, &aw2->v.a.mask, 0)) {
2161 return 1;
2162 }
2163 return 0;
b0d623f7 2164 case PF_ADDR_DYNIFTL:
0a7de745
A
2165 return aw1->p.dyn == NULL || aw2->p.dyn == NULL ||
2166 aw1->p.dyn->pfid_kt != aw2->p.dyn->pfid_kt;
b0d623f7
A
2167 case PF_ADDR_NOROUTE:
2168 case PF_ADDR_URPFFAILED:
0a7de745 2169 return 0;
b0d623f7 2170 case PF_ADDR_TABLE:
0a7de745 2171 return aw1->p.tbl != aw2->p.tbl;
b0d623f7 2172 case PF_ADDR_RTLABEL:
0a7de745 2173 return aw1->v.rtlabel != aw2->v.rtlabel;
b0d623f7
A
2174 default:
2175 printf("invalid address type: %d\n", aw1->type);
0a7de745 2176 return 1;
b0d623f7
A
2177 }
2178}
2179
2180u_int16_t
2181pf_cksum_fixup(u_int16_t cksum, u_int16_t old, u_int16_t new, u_int8_t udp)
2182{
0a7de745 2183 return nat464_cksum_fixup(cksum, old, new, udp);
b0d623f7
A
2184}
2185
3e170ce0
A
2186/*
2187 * change ip address & port
2188 * dir : packet direction
2189 * a : address to be changed
2190 * p : port to be changed
2191 * ic : ip header checksum
2192 * pc : protocol checksum
2193 * an : new ip address
2194 * pn : new port
2195 * u : should be 1 if UDP packet else 0
2196 * af : address family of the packet
2197 * afn : address family of the new address
2198 * ua : should be 1 if ip address needs to be updated in the packet else
2199 * only the checksum is recalculated & updated.
2200 */
b0d623f7 2201static void
5ba3f43e 2202pf_change_ap(int dir, pbuf_t *pbuf, struct pf_addr *a, u_int16_t *p,
b0d623f7 2203 u_int16_t *ic, u_int16_t *pc, struct pf_addr *an, u_int16_t pn,
3e170ce0 2204 u_int8_t u, sa_family_t af, sa_family_t afn, int ua)
b0d623f7 2205{
0a7de745
A
2206 struct pf_addr ao;
2207 u_int16_t po = *p;
b0d623f7
A
2208
2209 PF_ACPY(&ao, a, af);
0a7de745 2210 if (ua) {
3e170ce0 2211 PF_ACPY(a, an, afn);
0a7de745 2212 }
b0d623f7
A
2213
2214 *p = pn;
2215
2216 switch (af) {
2217#if INET
2218 case AF_INET:
3e170ce0
A
2219 switch (afn) {
2220 case AF_INET:
2221 *ic = pf_cksum_fixup(pf_cksum_fixup(*ic,
0a7de745
A
2222 ao.addr16[0], an->addr16[0], 0),
2223 ao.addr16[1], an->addr16[1], 0);
3e170ce0 2224 *p = pn;
d9a64523
A
2225 /*
2226 * If the packet is originated from an ALG on the NAT gateway
2227 * (source address is loopback or local), in which case the
2228 * TCP/UDP checksum field contains the pseudo header checksum
2229 * that's not yet complemented.
2230 * In that case we do not need to fixup the checksum for port
2231 * translation as the pseudo header checksum doesn't include ports.
2232 *
2233 * A packet generated locally will have UDP/TCP CSUM flag
2234 * set (gets set in protocol output).
2235 *
2236 * It should be noted that the fixup doesn't do anything if the
2237 * checksum is 0.
2238 */
5ba3f43e 2239 if (dir == PF_OUT && pbuf != NULL &&
d9a64523
A
2240 (*pbuf->pb_csum_flags & (CSUM_TCP | CSUM_UDP))) {
2241 /* Pseudo-header checksum does not include ports */
3e170ce0 2242 *pc = ~pf_cksum_fixup(pf_cksum_fixup(~*pc,
0a7de745
A
2243 ao.addr16[0], an->addr16[0], u),
2244 ao.addr16[1], an->addr16[1], u);
3e170ce0
A
2245 } else {
2246 *pc =
0a7de745
A
2247 pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
2248 *pc, ao.addr16[0], an->addr16[0], u),
2249 ao.addr16[1], an->addr16[1], u),
2250 po, pn, u);
3e170ce0
A
2251 }
2252 break;
2253#ifdef INET6
2254 case AF_INET6:
2255 *p = pn;
2256 *pc = pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
0a7de745
A
2257 pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
2258
2259 pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(*pc,
2260 ao.addr16[0], an->addr16[0], u),
2261 ao.addr16[1], an->addr16[1], u),
2262 0, an->addr16[2], u),
2263 0, an->addr16[3], u),
2264 0, an->addr16[4], u),
2265 0, an->addr16[5], u),
2266 0, an->addr16[6], u),
2267 0, an->addr16[7], u),
b0d623f7 2268 po, pn, u);
3e170ce0
A
2269 break;
2270#endif /* INET6 */
b0d623f7
A
2271 }
2272 break;
2273#endif /* INET */
2274#if INET6
2275 case AF_INET6:
3e170ce0
A
2276 switch (afn) {
2277 case AF_INET6:
0a7de745
A
2278 /*
2279 * If the packet is originated from an ALG on the NAT gateway
2280 * (source address is loopback or local), in which case the
2281 * TCP/UDP checksum field contains the pseudo header checksum
2282 * that's not yet complemented.
2283 * A packet generated locally
2284 * will have UDP/TCP CSUM flag set (gets set in protocol
2285 * output).
2286 */
5ba3f43e
A
2287 if (dir == PF_OUT && pbuf != NULL &&
2288 (*pbuf->pb_csum_flags & (CSUM_TCPIPV6 |
0a7de745
A
2289 CSUM_UDPIPV6))) {
2290 /* Pseudo-header checksum does not include ports */
3e170ce0 2291 *pc =
0a7de745
A
2292 ~pf_cksum_fixup(pf_cksum_fixup(
2293 pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
2294 pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
2295 ~*pc,
2296 ao.addr16[0], an->addr16[0], u),
2297 ao.addr16[1], an->addr16[1], u),
2298 ao.addr16[2], an->addr16[2], u),
2299 ao.addr16[3], an->addr16[3], u),
2300 ao.addr16[4], an->addr16[4], u),
2301 ao.addr16[5], an->addr16[5], u),
2302 ao.addr16[6], an->addr16[6], u),
2303 ao.addr16[7], an->addr16[7], u);
3e170ce0
A
2304 } else {
2305 *pc =
0a7de745
A
2306 pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
2307 pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
2308 pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
2309 *pc,
2310 ao.addr16[0], an->addr16[0], u),
2311 ao.addr16[1], an->addr16[1], u),
2312 ao.addr16[2], an->addr16[2], u),
2313 ao.addr16[3], an->addr16[3], u),
2314 ao.addr16[4], an->addr16[4], u),
2315 ao.addr16[5], an->addr16[5], u),
2316 ao.addr16[6], an->addr16[6], u),
2317 ao.addr16[7], an->addr16[7], u),
2318 po, pn, u);
3e170ce0
A
2319 }
2320 break;
2321#ifdef INET
2322 case AF_INET:
6d2010ae 2323 *pc = pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
0a7de745
A
2324 pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
2325 pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(*pc,
2326 ao.addr16[0], an->addr16[0], u),
2327 ao.addr16[1], an->addr16[1], u),
2328 ao.addr16[2], 0, u),
2329 ao.addr16[3], 0, u),
2330 ao.addr16[4], 0, u),
2331 ao.addr16[5], 0, u),
2332 ao.addr16[6], 0, u),
2333 ao.addr16[7], 0, u),
3e170ce0
A
2334 po, pn, u);
2335 break;
2336#endif /* INET */
6d2010ae 2337 }
b0d623f7
A
2338 break;
2339#endif /* INET6 */
2340 }
2341}
2342
2343
2344/* Changes a u_int32_t. Uses a void * so there are no align restrictions */
2345void
2346pf_change_a(void *a, u_int16_t *c, u_int32_t an, u_int8_t u)
2347{
0a7de745 2348 u_int32_t ao;
b0d623f7 2349
0a7de745
A
2350 memcpy(&ao, a, sizeof(ao));
2351 memcpy(a, &an, sizeof(u_int32_t));
b0d623f7
A
2352 *c = pf_cksum_fixup(pf_cksum_fixup(*c, ao / 65536, an / 65536, u),
2353 ao % 65536, an % 65536, u);
2354}
2355
2356#if INET6
2357static void
2358pf_change_a6(struct pf_addr *a, u_int16_t *c, struct pf_addr *an, u_int8_t u)
2359{
0a7de745 2360 struct pf_addr ao;
b0d623f7
A
2361
2362 PF_ACPY(&ao, a, AF_INET6);
2363 PF_ACPY(a, an, AF_INET6);
2364
2365 *c = pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
0a7de745
A
2366 pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
2367 pf_cksum_fixup(pf_cksum_fixup(*c,
2368 ao.addr16[0], an->addr16[0], u),
2369 ao.addr16[1], an->addr16[1], u),
2370 ao.addr16[2], an->addr16[2], u),
2371 ao.addr16[3], an->addr16[3], u),
2372 ao.addr16[4], an->addr16[4], u),
2373 ao.addr16[5], an->addr16[5], u),
b0d623f7
A
2374 ao.addr16[6], an->addr16[6], u),
2375 ao.addr16[7], an->addr16[7], u);
2376}
3e170ce0
A
2377
2378void
2379pf_change_addr(struct pf_addr *a, u_int16_t *c, struct pf_addr *an, u_int8_t u,
0a7de745 2380 sa_family_t af, sa_family_t afn)
3e170ce0 2381{
0a7de745 2382 struct pf_addr ao;
3e170ce0 2383
cb323159
A
2384 if (af != afn) {
2385 PF_ACPY(&ao, a, af);
2386 PF_ACPY(a, an, afn);
2387 }
3e170ce0
A
2388
2389 switch (af) {
2390 case AF_INET:
2391 switch (afn) {
2392 case AF_INET:
5ba3f43e 2393 pf_change_a(a, c, an->v4addr.s_addr, u);
3e170ce0
A
2394 break;
2395 case AF_INET6:
2396 *c = pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
0a7de745
A
2397 pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
2398 pf_cksum_fixup(pf_cksum_fixup(*c,
2399 ao.addr16[0], an->addr16[0], u),
2400 ao.addr16[1], an->addr16[1], u),
2401 0, an->addr16[2], u),
2402 0, an->addr16[3], u),
2403 0, an->addr16[4], u),
2404 0, an->addr16[5], u),
2405 0, an->addr16[6], u),
2406 0, an->addr16[7], u);
3e170ce0
A
2407 break;
2408 }
2409 break;
2410 case AF_INET6:
2411 switch (afn) {
2412 case AF_INET:
2413 *c = pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
0a7de745
A
2414 pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
2415 pf_cksum_fixup(pf_cksum_fixup(*c,
2416 ao.addr16[0], an->addr16[0], u),
2417 ao.addr16[1], an->addr16[1], u),
2418 ao.addr16[2], 0, u),
2419 ao.addr16[3], 0, u),
2420 ao.addr16[4], 0, u),
2421 ao.addr16[5], 0, u),
2422 ao.addr16[6], 0, u),
2423 ao.addr16[7], 0, u);
3e170ce0
A
2424 break;
2425 case AF_INET6:
2426 pf_change_a6(a, c, an, u);
2427 break;
2428 }
2429 break;
2430 }
2431}
2432
b0d623f7
A
2433#endif /* INET6 */
2434
2435static void
2436pf_change_icmp(struct pf_addr *ia, u_int16_t *ip, struct pf_addr *oa,
2437 struct pf_addr *na, u_int16_t np, u_int16_t *pc, u_int16_t *h2c,
2438 u_int16_t *ic, u_int16_t *hc, u_int8_t u, sa_family_t af)
2439{
0a7de745 2440 struct pf_addr oia, ooa;
b0d623f7
A
2441
2442 PF_ACPY(&oia, ia, af);
2443 PF_ACPY(&ooa, oa, af);
2444
2445 /* Change inner protocol port, fix inner protocol checksum. */
2446 if (ip != NULL) {
0a7de745
A
2447 u_int16_t oip = *ip;
2448 u_int32_t opc = 0;
b0d623f7 2449
0a7de745 2450 if (pc != NULL) {
b0d623f7 2451 opc = *pc;
0a7de745 2452 }
b0d623f7 2453 *ip = np;
0a7de745 2454 if (pc != NULL) {
b0d623f7 2455 *pc = pf_cksum_fixup(*pc, oip, *ip, u);
0a7de745 2456 }
b0d623f7 2457 *ic = pf_cksum_fixup(*ic, oip, *ip, 0);
0a7de745 2458 if (pc != NULL) {
b0d623f7 2459 *ic = pf_cksum_fixup(*ic, opc, *pc, 0);
0a7de745 2460 }
b0d623f7
A
2461 }
2462 /* Change inner ip address, fix inner ip and icmp checksums. */
2463 PF_ACPY(ia, na, af);
2464 switch (af) {
2465#if INET
2466 case AF_INET: {
0a7de745 2467 u_int32_t oh2c = *h2c;
b0d623f7
A
2468
2469 *h2c = pf_cksum_fixup(pf_cksum_fixup(*h2c,
2470 oia.addr16[0], ia->addr16[0], 0),
2471 oia.addr16[1], ia->addr16[1], 0);
2472 *ic = pf_cksum_fixup(pf_cksum_fixup(*ic,
2473 oia.addr16[0], ia->addr16[0], 0),
2474 oia.addr16[1], ia->addr16[1], 0);
2475 *ic = pf_cksum_fixup(*ic, oh2c, *h2c, 0);
2476 break;
2477 }
2478#endif /* INET */
2479#if INET6
2480 case AF_INET6:
2481 *ic = pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
0a7de745
A
2482 pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
2483 pf_cksum_fixup(pf_cksum_fixup(*ic,
2484 oia.addr16[0], ia->addr16[0], u),
2485 oia.addr16[1], ia->addr16[1], u),
2486 oia.addr16[2], ia->addr16[2], u),
2487 oia.addr16[3], ia->addr16[3], u),
2488 oia.addr16[4], ia->addr16[4], u),
2489 oia.addr16[5], ia->addr16[5], u),
b0d623f7
A
2490 oia.addr16[6], ia->addr16[6], u),
2491 oia.addr16[7], ia->addr16[7], u);
2492 break;
2493#endif /* INET6 */
2494 }
2495 /* Change outer ip address, fix outer ip or icmpv6 checksum. */
2496 PF_ACPY(oa, na, af);
2497 switch (af) {
2498#if INET
2499 case AF_INET:
2500 *hc = pf_cksum_fixup(pf_cksum_fixup(*hc,
2501 ooa.addr16[0], oa->addr16[0], 0),
2502 ooa.addr16[1], oa->addr16[1], 0);
2503 break;
2504#endif /* INET */
2505#if INET6
2506 case AF_INET6:
2507 *ic = pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
0a7de745
A
2508 pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
2509 pf_cksum_fixup(pf_cksum_fixup(*ic,
2510 ooa.addr16[0], oa->addr16[0], u),
2511 ooa.addr16[1], oa->addr16[1], u),
2512 ooa.addr16[2], oa->addr16[2], u),
2513 ooa.addr16[3], oa->addr16[3], u),
2514 ooa.addr16[4], oa->addr16[4], u),
2515 ooa.addr16[5], oa->addr16[5], u),
b0d623f7
A
2516 ooa.addr16[6], oa->addr16[6], u),
2517 ooa.addr16[7], oa->addr16[7], u);
2518 break;
2519#endif /* INET6 */
2520 }
2521}
2522
2523
2524/*
2525 * Need to modulate the sequence numbers in the TCP SACK option
2526 * (credits to Krzysztof Pfaff for report and patch)
2527 */
2528static int
5ba3f43e 2529pf_modulate_sack(pbuf_t *pbuf, int off, struct pf_pdesc *pd,
b0d623f7
A
2530 struct tcphdr *th, struct pf_state_peer *dst)
2531{
0a7de745 2532 int hlen = (th->th_off << 2) - sizeof(*th), thoptlen = hlen;
b0d623f7
A
2533 u_int8_t opts[MAX_TCPOPTLEN], *opt = opts;
2534 int copyback = 0, i, olen;
2535 struct sackblk sack;
2536
0a7de745 2537#define TCPOLEN_SACKLEN (TCPOLEN_SACK + 2)
b0d623f7 2538 if (hlen < TCPOLEN_SACKLEN ||
0a7de745
A
2539 !pf_pull_hdr(pbuf, off + sizeof(*th), opts, hlen, NULL, NULL, pd->af)) {
2540 return 0;
2541 }
b0d623f7
A
2542
2543 while (hlen >= TCPOLEN_SACKLEN) {
2544 olen = opt[1];
2545 switch (*opt) {
0a7de745 2546 case TCPOPT_EOL: /* FALLTHROUGH */
b0d623f7
A
2547 case TCPOPT_NOP:
2548 opt++;
2549 hlen--;
2550 break;
2551 case TCPOPT_SACK:
0a7de745 2552 if (olen > hlen) {
b0d623f7 2553 olen = hlen;
0a7de745 2554 }
b0d623f7
A
2555 if (olen >= TCPOLEN_SACKLEN) {
2556 for (i = 2; i + TCPOLEN_SACK <= olen;
2557 i += TCPOLEN_SACK) {
0a7de745 2558 memcpy(&sack, &opt[i], sizeof(sack));
b0d623f7
A
2559 pf_change_a(&sack.start, &th->th_sum,
2560 htonl(ntohl(sack.start) -
2561 dst->seqdiff), 0);
2562 pf_change_a(&sack.end, &th->th_sum,
2563 htonl(ntohl(sack.end) -
2564 dst->seqdiff), 0);
0a7de745 2565 memcpy(&opt[i], &sack, sizeof(sack));
b0d623f7 2566 }
0a7de745 2567 copyback = off + sizeof(*th) + thoptlen;
b0d623f7 2568 }
0a7de745 2569 /* FALLTHROUGH */
b0d623f7 2570 default:
0a7de745 2571 if (olen < 2) {
b0d623f7 2572 olen = 2;
0a7de745 2573 }
b0d623f7
A
2574 hlen -= olen;
2575 opt += olen;
2576 }
2577 }
2578
b0d623f7 2579 if (copyback) {
0a7de745
A
2580 if (pf_lazy_makewritable(pd, pbuf, copyback) == NULL) {
2581 return -1;
2582 }
2583 pbuf_copy_back(pbuf, off + sizeof(*th), thoptlen, opts);
b0d623f7 2584 }
0a7de745 2585 return copyback;
b0d623f7
A
2586}
2587
5ba3f43e
A
2588/*
2589 * XXX
2590 *
2591 * The following functions (pf_send_tcp and pf_send_icmp) are somewhat
2592 * special in that they originate "spurious" packets rather than
2593 * filter/NAT existing packets. As such, they're not a great fit for
2594 * the 'pbuf' shim, which assumes the underlying packet buffers are
2595 * allocated elsewhere.
2596 *
2597 * Since these functions are rarely used, we'll carry on allocating mbufs
2598 * and passing them to the IP stack for eventual routing.
2599 */
b0d623f7
A
2600static void
2601pf_send_tcp(const struct pf_rule *r, sa_family_t af,
2602 const struct pf_addr *saddr, const struct pf_addr *daddr,
2603 u_int16_t sport, u_int16_t dport, u_int32_t seq, u_int32_t ack,
2604 u_int8_t flags, u_int16_t win, u_int16_t mss, u_int8_t ttl, int tag,
2605 u_int16_t rtag, struct ether_header *eh, struct ifnet *ifp)
2606{
2607#pragma unused(eh, ifp)
0a7de745
A
2608 struct mbuf *m;
2609 int len, tlen;
b0d623f7 2610#if INET
0a7de745 2611 struct ip *h = NULL;
b0d623f7
A
2612#endif /* INET */
2613#if INET6
0a7de745 2614 struct ip6_hdr *h6 = NULL;
b0d623f7 2615#endif /* INET6 */
0a7de745
A
2616 struct tcphdr *th = NULL;
2617 char *opt;
2618 struct pf_mtag *pf_mtag;
b0d623f7
A
2619
2620 /* maximum segment size tcp option */
0a7de745
A
2621 tlen = sizeof(struct tcphdr);
2622 if (mss) {
b0d623f7 2623 tlen += 4;
0a7de745 2624 }
b0d623f7
A
2625
2626 switch (af) {
2627#if INET
2628 case AF_INET:
0a7de745 2629 len = sizeof(struct ip) + tlen;
b0d623f7
A
2630 break;
2631#endif /* INET */
2632#if INET6
2633 case AF_INET6:
0a7de745 2634 len = sizeof(struct ip6_hdr) + tlen;
b0d623f7
A
2635 break;
2636#endif /* INET6 */
2637 default:
2638 panic("pf_send_tcp: not AF_INET or AF_INET6!");
2639 return;
2640 }
2641
2642 /* create outgoing mbuf */
2643 m = m_gethdr(M_DONTWAIT, MT_HEADER);
0a7de745 2644 if (m == NULL) {
b0d623f7 2645 return;
0a7de745 2646 }
b0d623f7 2647
0a7de745 2648 if ((pf_mtag = pf_get_mtag(m)) == NULL) {
b0d623f7 2649 return;
0a7de745 2650 }
b0d623f7 2651
0a7de745 2652 if (tag) {
316670eb 2653 pf_mtag->pftag_flags |= PF_TAG_GENERATED;
0a7de745 2654 }
316670eb 2655 pf_mtag->pftag_tag = rtag;
b0d623f7 2656
0a7de745 2657 if (r != NULL && PF_RTABLEID_IS_VALID(r->rtableid)) {
316670eb 2658 pf_mtag->pftag_rtableid = r->rtableid;
0a7de745 2659 }
b0d623f7 2660
39236c6e 2661#if PF_ECN
316670eb
A
2662 /* add hints for ecn */
2663 pf_mtag->pftag_hdr = mtod(m, struct ip *);
2664 /* record address family */
2665 pf_mtag->pftag_flags &= ~(PF_TAG_HDR_INET | PF_TAG_HDR_INET6);
2666 switch (af) {
2667#if INET
2668 case AF_INET:
2669 pf_mtag->pftag_flags |= PF_TAG_HDR_INET;
2670 break;
2671#endif /* INET */
2672#if INET6
2673 case AF_INET6:
2674 pf_mtag->pftag_flags |= PF_TAG_HDR_INET6;
2675 break;
2676#endif /* INET6 */
b0d623f7 2677 }
39236c6e
A
2678#endif /* PF_ECN */
2679
316670eb 2680 /* indicate this is TCP */
39236c6e 2681 m->m_pkthdr.pkt_proto = IPPROTO_TCP;
316670eb
A
2682
2683 /* Make sure headers are 32-bit aligned */
b0d623f7
A
2684 m->m_data += max_linkhdr;
2685 m->m_pkthdr.len = m->m_len = len;
2686 m->m_pkthdr.rcvif = NULL;
2687 bzero(m->m_data, len);
2688 switch (af) {
2689#if INET
2690 case AF_INET:
2691 h = mtod(m, struct ip *);
2692
2693 /* IP header fields included in the TCP checksum */
2694 h->ip_p = IPPROTO_TCP;
2695 h->ip_len = htons(tlen);
5ba3f43e
A
2696 h->ip_src.s_addr = saddr->v4addr.s_addr;
2697 h->ip_dst.s_addr = daddr->v4addr.s_addr;
b0d623f7 2698
0a7de745 2699 th = (struct tcphdr *)(void *)((caddr_t)h + sizeof(struct ip));
b0d623f7
A
2700 break;
2701#endif /* INET */
2702#if INET6
2703 case AF_INET6:
2704 h6 = mtod(m, struct ip6_hdr *);
2705
2706 /* IP header fields included in the TCP checksum */
2707 h6->ip6_nxt = IPPROTO_TCP;
2708 h6->ip6_plen = htons(tlen);
0a7de745
A
2709 memcpy(&h6->ip6_src, &saddr->v6addr, sizeof(struct in6_addr));
2710 memcpy(&h6->ip6_dst, &daddr->v6addr, sizeof(struct in6_addr));
b0d623f7 2711
316670eb 2712 th = (struct tcphdr *)(void *)
0a7de745 2713 ((caddr_t)h6 + sizeof(struct ip6_hdr));
b0d623f7
A
2714 break;
2715#endif /* INET6 */
2716 }
2717
2718 /* TCP header */
2719 th->th_sport = sport;
2720 th->th_dport = dport;
2721 th->th_seq = htonl(seq);
2722 th->th_ack = htonl(ack);
2723 th->th_off = tlen >> 2;
2724 th->th_flags = flags;
2725 th->th_win = htons(win);
2726
2727 if (mss) {
2728 opt = (char *)(th + 1);
2729 opt[0] = TCPOPT_MAXSEG;
2730 opt[1] = 4;
2731#if BYTE_ORDER != BIG_ENDIAN
2732 HTONS(mss);
2733#endif
2734 bcopy((caddr_t)&mss, (caddr_t)(opt + 2), 2);
2735 }
2736
2737 switch (af) {
2738#if INET
2739 case AF_INET: {
2740 struct route ro;
2741
2742 /* TCP checksum */
2743 th->th_sum = in_cksum(m, len);
2744
2745 /* Finish the IP header */
2746 h->ip_v = 4;
0a7de745 2747 h->ip_hl = sizeof(*h) >> 2;
b0d623f7
A
2748 h->ip_tos = IPTOS_LOWDELAY;
2749 /*
2750 * ip_output() expects ip_len and ip_off to be in host order.
2751 */
2752 h->ip_len = len;
2753 h->ip_off = (path_mtu_discovery ? IP_DF : 0);
2754 h->ip_ttl = ttl ? ttl : ip_defttl;
2755 h->ip_sum = 0;
2756
0a7de745 2757 bzero(&ro, sizeof(ro));
b0d623f7 2758 ip_output(m, NULL, &ro, 0, NULL, NULL);
39236c6e 2759 ROUTE_RELEASE(&ro);
b0d623f7
A
2760 break;
2761 }
2762#endif /* INET */
2763#if INET6
2764 case AF_INET6: {
2765 struct route_in6 ro6;
2766
2767 /* TCP checksum */
2768 th->th_sum = in6_cksum(m, IPPROTO_TCP,
0a7de745 2769 sizeof(struct ip6_hdr), tlen);
b0d623f7
A
2770
2771 h6->ip6_vfc |= IPV6_VERSION;
2772 h6->ip6_hlim = IPV6_DEFHLIM;
2773
0a7de745 2774 bzero(&ro6, sizeof(ro6));
6d2010ae 2775 ip6_output(m, NULL, &ro6, 0, NULL, NULL, NULL);
39236c6e 2776 ROUTE_RELEASE(&ro6);
b0d623f7
A
2777 break;
2778 }
2779#endif /* INET6 */
2780 }
2781}
2782
2783static void
5ba3f43e 2784pf_send_icmp(pbuf_t *pbuf, u_int8_t type, u_int8_t code, sa_family_t af,
b0d623f7
A
2785 struct pf_rule *r)
2786{
0a7de745
A
2787 struct mbuf *m0;
2788 struct pf_mtag *pf_mtag;
b0d623f7 2789
5ba3f43e 2790 m0 = pbuf_clone_to_mbuf(pbuf);
0a7de745 2791 if (m0 == NULL) {
b0d623f7 2792 return;
0a7de745 2793 }
b0d623f7 2794
0a7de745 2795 if ((pf_mtag = pf_get_mtag(m0)) == NULL) {
b0d623f7 2796 return;
0a7de745 2797 }
b0d623f7 2798
316670eb 2799 pf_mtag->pftag_flags |= PF_TAG_GENERATED;
b0d623f7 2800
0a7de745 2801 if (PF_RTABLEID_IS_VALID(r->rtableid)) {
316670eb 2802 pf_mtag->pftag_rtableid = r->rtableid;
0a7de745 2803 }
316670eb 2804
39236c6e 2805#if PF_ECN
316670eb
A
2806 /* add hints for ecn */
2807 pf_mtag->pftag_hdr = mtod(m0, struct ip *);
2808 /* record address family */
39236c6e 2809 pf_mtag->pftag_flags &= ~(PF_TAG_HDR_INET | PF_TAG_HDR_INET6);
316670eb
A
2810 switch (af) {
2811#if INET
2812 case AF_INET:
2813 pf_mtag->pftag_flags |= PF_TAG_HDR_INET;
39236c6e 2814 m0->m_pkthdr.pkt_proto = IPPROTO_ICMP;
316670eb
A
2815 break;
2816#endif /* INET */
2817#if INET6
2818 case AF_INET6:
2819 pf_mtag->pftag_flags |= PF_TAG_HDR_INET6;
39236c6e 2820 m0->m_pkthdr.pkt_proto = IPPROTO_ICMPV6;
316670eb
A
2821 break;
2822#endif /* INET6 */
b0d623f7 2823 }
39236c6e 2824#endif /* PF_ECN */
316670eb 2825
b0d623f7
A
2826 switch (af) {
2827#if INET
2828 case AF_INET:
2829 icmp_error(m0, type, code, 0, 0);
2830 break;
2831#endif /* INET */
2832#if INET6
2833 case AF_INET6:
2834 icmp6_error(m0, type, code, 0);
2835 break;
2836#endif /* INET6 */
2837 }
2838}
2839
2840/*
2841 * Return 1 if the addresses a and b match (with mask m), otherwise return 0.
2842 * If n is 0, they match if they are equal. If n is != 0, they match if they
2843 * are different.
2844 */
2845int
2846pf_match_addr(u_int8_t n, struct pf_addr *a, struct pf_addr *m,
2847 struct pf_addr *b, sa_family_t af)
2848{
0a7de745 2849 int match = 0;
b0d623f7
A
2850
2851 switch (af) {
2852#if INET
2853 case AF_INET:
2854 if ((a->addr32[0] & m->addr32[0]) ==
0a7de745 2855 (b->addr32[0] & m->addr32[0])) {
b0d623f7 2856 match++;
0a7de745 2857 }
b0d623f7
A
2858 break;
2859#endif /* INET */
2860#if INET6
2861 case AF_INET6:
2862 if (((a->addr32[0] & m->addr32[0]) ==
0a7de745 2863 (b->addr32[0] & m->addr32[0])) &&
b0d623f7 2864 ((a->addr32[1] & m->addr32[1]) ==
0a7de745 2865 (b->addr32[1] & m->addr32[1])) &&
b0d623f7 2866 ((a->addr32[2] & m->addr32[2]) ==
0a7de745 2867 (b->addr32[2] & m->addr32[2])) &&
b0d623f7 2868 ((a->addr32[3] & m->addr32[3]) ==
0a7de745 2869 (b->addr32[3] & m->addr32[3]))) {
b0d623f7 2870 match++;
0a7de745 2871 }
b0d623f7
A
2872 break;
2873#endif /* INET6 */
2874 }
2875 if (match) {
0a7de745
A
2876 if (n) {
2877 return 0;
2878 } else {
2879 return 1;
2880 }
b0d623f7 2881 } else {
0a7de745
A
2882 if (n) {
2883 return 1;
2884 } else {
2885 return 0;
2886 }
b0d623f7
A
2887 }
2888}
2889
2890/*
2891 * Return 1 if b <= a <= e, otherwise return 0.
2892 */
2893int
2894pf_match_addr_range(struct pf_addr *b, struct pf_addr *e,
2895 struct pf_addr *a, sa_family_t af)
2896{
2897 switch (af) {
2898#if INET
2899 case AF_INET:
2900 if ((a->addr32[0] < b->addr32[0]) ||
0a7de745
A
2901 (a->addr32[0] > e->addr32[0])) {
2902 return 0;
2903 }
b0d623f7
A
2904 break;
2905#endif /* INET */
2906#if INET6
2907 case AF_INET6: {
0a7de745 2908 int i;
b0d623f7
A
2909
2910 /* check a >= b */
0a7de745
A
2911 for (i = 0; i < 4; ++i) {
2912 if (a->addr32[i] > b->addr32[i]) {
b0d623f7 2913 break;
0a7de745
A
2914 } else if (a->addr32[i] < b->addr32[i]) {
2915 return 0;
2916 }
2917 }
b0d623f7 2918 /* check a <= e */
0a7de745
A
2919 for (i = 0; i < 4; ++i) {
2920 if (a->addr32[i] < e->addr32[i]) {
b0d623f7 2921 break;
0a7de745
A
2922 } else if (a->addr32[i] > e->addr32[i]) {
2923 return 0;
2924 }
2925 }
b0d623f7
A
2926 break;
2927 }
2928#endif /* INET6 */
2929 }
0a7de745 2930 return 1;
b0d623f7
A
2931}
2932
2933int
2934pf_match(u_int8_t op, u_int32_t a1, u_int32_t a2, u_int32_t p)
2935{
2936 switch (op) {
2937 case PF_OP_IRG:
0a7de745 2938 return (p > a1) && (p < a2);
b0d623f7 2939 case PF_OP_XRG:
0a7de745 2940 return (p < a1) || (p > a2);
b0d623f7 2941 case PF_OP_RRG:
0a7de745 2942 return (p >= a1) && (p <= a2);
b0d623f7 2943 case PF_OP_EQ:
0a7de745 2944 return p == a1;
b0d623f7 2945 case PF_OP_NE:
0a7de745 2946 return p != a1;
b0d623f7 2947 case PF_OP_LT:
0a7de745 2948 return p < a1;
b0d623f7 2949 case PF_OP_LE:
0a7de745 2950 return p <= a1;
b0d623f7 2951 case PF_OP_GT:
0a7de745 2952 return p > a1;
b0d623f7 2953 case PF_OP_GE:
0a7de745 2954 return p >= a1;
b0d623f7 2955 }
0a7de745 2956 return 0; /* never reached */
b0d623f7
A
2957}
2958
2959int
2960pf_match_port(u_int8_t op, u_int16_t a1, u_int16_t a2, u_int16_t p)
2961{
2962#if BYTE_ORDER != BIG_ENDIAN
2963 NTOHS(a1);
2964 NTOHS(a2);
2965 NTOHS(p);
2966#endif
0a7de745 2967 return pf_match(op, a1, a2, p);
b0d623f7
A
2968}
2969
b0d623f7
A
2970int
2971pf_match_xport(u_int8_t proto, u_int8_t proto_variant, union pf_rule_xport *rx,
2972 union pf_state_xport *sx)
2973{
2974 int d = !0;
2975
2976 if (sx) {
2977 switch (proto) {
2978 case IPPROTO_GRE:
0a7de745 2979 if (proto_variant == PF_GRE_PPTP_VARIANT) {
b0d623f7 2980 d = (rx->call_id == sx->call_id);
0a7de745 2981 }
b0d623f7
A
2982 break;
2983
2984 case IPPROTO_ESP:
2985 d = (rx->spi == sx->spi);
2986 break;
2987
2988 case IPPROTO_TCP:
2989 case IPPROTO_UDP:
2990 case IPPROTO_ICMP:
2991 case IPPROTO_ICMPV6:
0a7de745 2992 if (rx->range.op) {
b0d623f7
A
2993 d = pf_match_port(rx->range.op,
2994 rx->range.port[0], rx->range.port[1],
2995 sx->port);
0a7de745 2996 }
b0d623f7
A
2997 break;
2998
2999 default:
3000 break;
3001 }
3002 }
3003
0a7de745 3004 return d;
b0d623f7 3005}
b0d623f7
A
3006
3007int
3008pf_match_uid(u_int8_t op, uid_t a1, uid_t a2, uid_t u)
3009{
0a7de745
A
3010 if (u == UID_MAX && op != PF_OP_EQ && op != PF_OP_NE) {
3011 return 0;
3012 }
3013 return pf_match(op, a1, a2, u);
b0d623f7
A
3014}
3015
3016int
3017pf_match_gid(u_int8_t op, gid_t a1, gid_t a2, gid_t g)
3018{
0a7de745
A
3019 if (g == GID_MAX && op != PF_OP_EQ && op != PF_OP_NE) {
3020 return 0;
3021 }
3022 return pf_match(op, a1, a2, g);
b0d623f7
A
3023}
3024
3025static int
5ba3f43e 3026pf_match_tag(struct pf_rule *r, struct pf_mtag *pf_mtag,
b0d623f7
A
3027 int *tag)
3028{
0a7de745 3029 if (*tag == -1) {
316670eb 3030 *tag = pf_mtag->pftag_tag;
0a7de745 3031 }
b0d623f7 3032
0a7de745
A
3033 return (!r->match_tag_not && r->match_tag == *tag) ||
3034 (r->match_tag_not && r->match_tag != *tag);
b0d623f7
A
3035}
3036
3037int
5ba3f43e 3038pf_tag_packet(pbuf_t *pbuf, struct pf_mtag *pf_mtag, int tag,
316670eb 3039 unsigned int rtableid, struct pf_pdesc *pd)
b0d623f7 3040{
39236c6e 3041 if (tag <= 0 && !PF_RTABLEID_IS_VALID(rtableid) &&
0a7de745
A
3042 (pd == NULL || !(pd->pktflags & PKTF_FLOW_ID))) {
3043 return 0;
3044 }
b0d623f7 3045
0a7de745
A
3046 if (pf_mtag == NULL && (pf_mtag = pf_get_mtag_pbuf(pbuf)) == NULL) {
3047 return 1;
3048 }
b0d623f7 3049
0a7de745 3050 if (tag > 0) {
316670eb 3051 pf_mtag->pftag_tag = tag;
0a7de745
A
3052 }
3053 if (PF_RTABLEID_IS_VALID(rtableid)) {
316670eb 3054 pf_mtag->pftag_rtableid = rtableid;
0a7de745 3055 }
39236c6e 3056 if (pd != NULL && (pd->pktflags & PKTF_FLOW_ID)) {
5ba3f43e
A
3057 *pbuf->pb_flowsrc = pd->flowsrc;
3058 *pbuf->pb_flowid = pd->flowhash;
3059 *pbuf->pb_flags |= pd->pktflags;
3060 *pbuf->pb_proto = pd->proto;
316670eb 3061 }
b0d623f7 3062
0a7de745 3063 return 0;
b0d623f7
A
3064}
3065
13f56ec4 3066void
b0d623f7 3067pf_step_into_anchor(int *depth, struct pf_ruleset **rs, int n,
0a7de745 3068 struct pf_rule **r, struct pf_rule **a, int *match)
b0d623f7 3069{
0a7de745 3070 struct pf_anchor_stackframe *f;
b0d623f7
A
3071
3072 (*r)->anchor->match = 0;
0a7de745 3073 if (match) {
b0d623f7 3074 *match = 0;
0a7de745
A
3075 }
3076 if (*depth >= (int)sizeof(pf_anchor_stack) /
3077 (int)sizeof(pf_anchor_stack[0])) {
b0d623f7
A
3078 printf("pf_step_into_anchor: stack overflow\n");
3079 *r = TAILQ_NEXT(*r, entries);
3080 return;
0a7de745 3081 } else if (*depth == 0 && a != NULL) {
b0d623f7 3082 *a = *r;
0a7de745 3083 }
b0d623f7
A
3084 f = pf_anchor_stack + (*depth)++;
3085 f->rs = *rs;
3086 f->r = *r;
3087 if ((*r)->anchor_wildcard) {
3088 f->parent = &(*r)->anchor->children;
3089 if ((f->child = RB_MIN(pf_anchor_node, f->parent)) ==
3090 NULL) {
3091 *r = NULL;
3092 return;
3093 }
3094 *rs = &f->child->ruleset;
3095 } else {
3096 f->parent = NULL;
3097 f->child = NULL;
3098 *rs = &(*r)->anchor->ruleset;
3099 }
3100 *r = TAILQ_FIRST((*rs)->rules[n].active.ptr);
3101}
3102
13f56ec4 3103int
b0d623f7
A
3104pf_step_out_of_anchor(int *depth, struct pf_ruleset **rs, int n,
3105 struct pf_rule **r, struct pf_rule **a, int *match)
3106{
0a7de745 3107 struct pf_anchor_stackframe *f;
b0d623f7
A
3108 int quick = 0;
3109
3110 do {
0a7de745 3111 if (*depth <= 0) {
b0d623f7 3112 break;
0a7de745 3113 }
b0d623f7
A
3114 f = pf_anchor_stack + *depth - 1;
3115 if (f->parent != NULL && f->child != NULL) {
3116 if (f->child->match ||
3117 (match != NULL && *match)) {
3118 f->r->anchor->match = 1;
0a7de745 3119 if (match) {
a39ff7e2 3120 *match = 0;
0a7de745 3121 }
b0d623f7
A
3122 }
3123 f->child = RB_NEXT(pf_anchor_node, f->parent, f->child);
3124 if (f->child != NULL) {
3125 *rs = &f->child->ruleset;
3126 *r = TAILQ_FIRST((*rs)->rules[n].active.ptr);
0a7de745 3127 if (*r == NULL) {
b0d623f7 3128 continue;
0a7de745 3129 } else {
b0d623f7 3130 break;
0a7de745 3131 }
b0d623f7
A
3132 }
3133 }
3134 (*depth)--;
0a7de745 3135 if (*depth == 0 && a != NULL) {
b0d623f7 3136 *a = NULL;
0a7de745 3137 }
b0d623f7 3138 *rs = f->rs;
0a7de745 3139 if (f->r->anchor->match || (match != NULL && *match)) {
b0d623f7 3140 quick = f->r->quick;
0a7de745 3141 }
b0d623f7
A
3142 *r = TAILQ_NEXT(f->r, entries);
3143 } while (*r == NULL);
3144
0a7de745 3145 return quick;
b0d623f7
A
3146}
3147
3148#if INET6
3149void
3150pf_poolmask(struct pf_addr *naddr, struct pf_addr *raddr,
3151 struct pf_addr *rmask, struct pf_addr *saddr, sa_family_t af)
3152{
3153 switch (af) {
3154#if INET
3155 case AF_INET:
3156 naddr->addr32[0] = (raddr->addr32[0] & rmask->addr32[0]) |
3157 ((rmask->addr32[0] ^ 0xffffffff) & saddr->addr32[0]);
3158 break;
3159#endif /* INET */
3160 case AF_INET6:
3161 naddr->addr32[0] = (raddr->addr32[0] & rmask->addr32[0]) |
3162 ((rmask->addr32[0] ^ 0xffffffff) & saddr->addr32[0]);
3163 naddr->addr32[1] = (raddr->addr32[1] & rmask->addr32[1]) |
3164 ((rmask->addr32[1] ^ 0xffffffff) & saddr->addr32[1]);
3165 naddr->addr32[2] = (raddr->addr32[2] & rmask->addr32[2]) |
3166 ((rmask->addr32[2] ^ 0xffffffff) & saddr->addr32[2]);
3167 naddr->addr32[3] = (raddr->addr32[3] & rmask->addr32[3]) |
3168 ((rmask->addr32[3] ^ 0xffffffff) & saddr->addr32[3]);
3169 break;
3170 }
3171}
3172
3173void
3174pf_addr_inc(struct pf_addr *addr, sa_family_t af)
3175{
3176 switch (af) {
3177#if INET
3178 case AF_INET:
3179 addr->addr32[0] = htonl(ntohl(addr->addr32[0]) + 1);
3180 break;
3181#endif /* INET */
3182 case AF_INET6:
3183 if (addr->addr32[3] == 0xffffffff) {
3184 addr->addr32[3] = 0;
3185 if (addr->addr32[2] == 0xffffffff) {
3186 addr->addr32[2] = 0;
3187 if (addr->addr32[1] == 0xffffffff) {
3188 addr->addr32[1] = 0;
3189 addr->addr32[0] =
3190 htonl(ntohl(addr->addr32[0]) + 1);
0a7de745 3191 } else {
b0d623f7
A
3192 addr->addr32[1] =
3193 htonl(ntohl(addr->addr32[1]) + 1);
0a7de745
A
3194 }
3195 } else {
b0d623f7
A
3196 addr->addr32[2] =
3197 htonl(ntohl(addr->addr32[2]) + 1);
0a7de745
A
3198 }
3199 } else {
b0d623f7
A
3200 addr->addr32[3] =
3201 htonl(ntohl(addr->addr32[3]) + 1);
0a7de745 3202 }
b0d623f7
A
3203 break;
3204 }
3205}
3206#endif /* INET6 */
3207
3208#define mix(a, b, c) \
0a7de745
A
3209 do { \
3210 a -= b; a -= c; a ^= (c >> 13); \
3211 b -= c; b -= a; b ^= (a << 8); \
3212 c -= a; c -= b; c ^= (b >> 13); \
3213 a -= b; a -= c; a ^= (c >> 12); \
3214 b -= c; b -= a; b ^= (a << 16); \
3215 c -= a; c -= b; c ^= (b >> 5); \
3216 a -= b; a -= c; a ^= (c >> 3); \
3217 b -= c; b -= a; b ^= (a << 10); \
3218 c -= a; c -= b; c ^= (b >> 15); \
b0d623f7
A
3219 } while (0)
3220
3221/*
3222 * hash function based on bridge_hash in if_bridge.c
3223 */
3224static void
3225pf_hash(struct pf_addr *inaddr, struct pf_addr *hash,
3226 struct pf_poolhashkey *key, sa_family_t af)
3227{
0a7de745 3228 u_int32_t a = 0x9e3779b9, b = 0x9e3779b9, c = key->key32[0];
b0d623f7
A
3229
3230 switch (af) {
3231#if INET
3232 case AF_INET:
3233 a += inaddr->addr32[0];
3234 b += key->key32[1];
3235 mix(a, b, c);
3236 hash->addr32[0] = c + key->key32[2];
3237 break;
3238#endif /* INET */
3239#if INET6
3240 case AF_INET6:
3241 a += inaddr->addr32[0];
3242 b += inaddr->addr32[2];
3243 mix(a, b, c);
3244 hash->addr32[0] = c;
3245 a += inaddr->addr32[1];
3246 b += inaddr->addr32[3];
3247 c += key->key32[1];
3248 mix(a, b, c);
3249 hash->addr32[1] = c;
3250 a += inaddr->addr32[2];
3251 b += inaddr->addr32[1];
3252 c += key->key32[2];
3253 mix(a, b, c);
3254 hash->addr32[2] = c;
3255 a += inaddr->addr32[3];
3256 b += inaddr->addr32[0];
3257 c += key->key32[3];
3258 mix(a, b, c);
3259 hash->addr32[3] = c;
3260 break;
3261#endif /* INET6 */
3262 }
3263}
3264
3265static int
3266pf_map_addr(sa_family_t af, struct pf_rule *r, struct pf_addr *saddr,
3267 struct pf_addr *naddr, struct pf_addr *init_addr, struct pf_src_node **sn)
3268{
0a7de745
A
3269 unsigned char hash[16];
3270 struct pf_pool *rpool = &r->rpool;
3271 struct pf_addr *raddr = &rpool->cur->addr.v.a.addr;
3272 struct pf_addr *rmask = &rpool->cur->addr.v.a.mask;
3273 struct pf_pooladdr *acur = rpool->cur;
3274 struct pf_src_node k;
b0d623f7
A
3275
3276 if (*sn == NULL && r->rpool.opts & PF_POOL_STICKYADDR &&
3277 (r->rpool.opts & PF_POOL_TYPEMASK) != PF_POOL_NONE) {
3278 k.af = af;
3279 PF_ACPY(&k.addr, saddr, af);
3280 if (r->rule_flag & PFRULE_RULESRCTRACK ||
0a7de745 3281 r->rpool.opts & PF_POOL_STICKYADDR) {
b0d623f7 3282 k.rule.ptr = r;
0a7de745 3283 } else {
b0d623f7 3284 k.rule.ptr = NULL;
0a7de745 3285 }
b0d623f7
A
3286 pf_status.scounters[SCNT_SRC_NODE_SEARCH]++;
3287 *sn = RB_FIND(pf_src_tree, &tree_src_tracking, &k);
3e170ce0
A
3288 if (*sn != NULL && !PF_AZERO(&(*sn)->raddr, rpool->af)) {
3289 PF_ACPY(naddr, &(*sn)->raddr, rpool->af);
b0d623f7
A
3290 if (pf_status.debug >= PF_DEBUG_MISC) {
3291 printf("pf_map_addr: src tracking maps ");
3292 pf_print_host(&k.addr, 0, af);
3293 printf(" to ");
3e170ce0 3294 pf_print_host(naddr, 0, rpool->af);
b0d623f7
A
3295 printf("\n");
3296 }
0a7de745 3297 return 0;
b0d623f7
A
3298 }
3299 }
3300
0a7de745
A
3301 if (rpool->cur->addr.type == PF_ADDR_NOROUTE) {
3302 return 1;
3303 }
b0d623f7 3304 if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) {
0a7de745
A
3305 if (rpool->cur->addr.p.dyn == NULL) {
3306 return 1;
3307 }
3e170ce0 3308 switch (rpool->af) {
b0d623f7
A
3309#if INET
3310 case AF_INET:
3311 if (rpool->cur->addr.p.dyn->pfid_acnt4 < 1 &&
3312 (rpool->opts & PF_POOL_TYPEMASK) !=
0a7de745
A
3313 PF_POOL_ROUNDROBIN) {
3314 return 1;
3315 }
b0d623f7
A
3316 raddr = &rpool->cur->addr.p.dyn->pfid_addr4;
3317 rmask = &rpool->cur->addr.p.dyn->pfid_mask4;
3318 break;
3319#endif /* INET */
3320#if INET6
3321 case AF_INET6:
3322 if (rpool->cur->addr.p.dyn->pfid_acnt6 < 1 &&
3323 (rpool->opts & PF_POOL_TYPEMASK) !=
0a7de745
A
3324 PF_POOL_ROUNDROBIN) {
3325 return 1;
3326 }
b0d623f7
A
3327 raddr = &rpool->cur->addr.p.dyn->pfid_addr6;
3328 rmask = &rpool->cur->addr.p.dyn->pfid_mask6;
3329 break;
3330#endif /* INET6 */
3331 }
3332 } else if (rpool->cur->addr.type == PF_ADDR_TABLE) {
0a7de745
A
3333 if ((rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_ROUNDROBIN) {
3334 return 1; /* unsupported */
3335 }
b0d623f7
A
3336 } else {
3337 raddr = &rpool->cur->addr.v.a.addr;
3338 rmask = &rpool->cur->addr.v.a.mask;
3339 }
3340
3341 switch (rpool->opts & PF_POOL_TYPEMASK) {
3342 case PF_POOL_NONE:
3e170ce0 3343 PF_ACPY(naddr, raddr, rpool->af);
b0d623f7
A
3344 break;
3345 case PF_POOL_BITMASK:
3e170ce0 3346 ASSERT(af == rpool->af);
b0d623f7
A
3347 PF_POOLMASK(naddr, raddr, rmask, saddr, af);
3348 break;
3349 case PF_POOL_RANDOM:
3e170ce0 3350 if (init_addr != NULL && PF_AZERO(init_addr, rpool->af)) {
b0d623f7
A
3351 switch (af) {
3352#if INET
3353 case AF_INET:
3354 rpool->counter.addr32[0] = htonl(random());
3355 break;
3356#endif /* INET */
3357#if INET6
3358 case AF_INET6:
0a7de745 3359 if (rmask->addr32[3] != 0xffffffff) {
b0d623f7 3360 rpool->counter.addr32[3] =
39236c6e 3361 RandomULong();
0a7de745 3362 } else {
b0d623f7 3363 break;
0a7de745
A
3364 }
3365 if (rmask->addr32[2] != 0xffffffff) {
b0d623f7 3366 rpool->counter.addr32[2] =
39236c6e 3367 RandomULong();
0a7de745 3368 } else {
b0d623f7 3369 break;
0a7de745
A
3370 }
3371 if (rmask->addr32[1] != 0xffffffff) {
b0d623f7 3372 rpool->counter.addr32[1] =
39236c6e 3373 RandomULong();
0a7de745 3374 } else {
b0d623f7 3375 break;
0a7de745
A
3376 }
3377 if (rmask->addr32[0] != 0xffffffff) {
b0d623f7 3378 rpool->counter.addr32[0] =
39236c6e 3379 RandomULong();
0a7de745 3380 }
b0d623f7
A
3381 break;
3382#endif /* INET6 */
3383 }
3e170ce0 3384 PF_POOLMASK(naddr, raddr, rmask, &rpool->counter,
0a7de745 3385 rpool->af);
3e170ce0 3386 PF_ACPY(init_addr, naddr, rpool->af);
b0d623f7 3387 } else {
3e170ce0
A
3388 PF_AINC(&rpool->counter, rpool->af);
3389 PF_POOLMASK(naddr, raddr, rmask, &rpool->counter,
0a7de745 3390 rpool->af);
b0d623f7
A
3391 }
3392 break;
3393 case PF_POOL_SRCHASH:
3e170ce0
A
3394 ASSERT(af == rpool->af);
3395 PF_POOLMASK(naddr, raddr, rmask, saddr, af);
316670eb
A
3396 pf_hash(saddr, (struct pf_addr *)(void *)&hash,
3397 &rpool->key, af);
3398 PF_POOLMASK(naddr, raddr, rmask,
3399 (struct pf_addr *)(void *)&hash, af);
b0d623f7
A
3400 break;
3401 case PF_POOL_ROUNDROBIN:
3402 if (rpool->cur->addr.type == PF_ADDR_TABLE) {
3403 if (!pfr_pool_get(rpool->cur->addr.p.tbl,
3404 &rpool->tblidx, &rpool->counter,
0a7de745 3405 &raddr, &rmask, rpool->af)) {
b0d623f7 3406 goto get_addr;
0a7de745 3407 }
b0d623f7 3408 } else if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) {
39236c6e
A
3409 if (rpool->cur->addr.p.dyn != NULL &&
3410 !pfr_pool_get(rpool->cur->addr.p.dyn->pfid_kt,
b0d623f7 3411 &rpool->tblidx, &rpool->counter,
0a7de745 3412 &raddr, &rmask, af)) {
b0d623f7 3413 goto get_addr;
0a7de745 3414 }
3e170ce0 3415 } else if (pf_match_addr(0, raddr, rmask, &rpool->counter,
0a7de745 3416 rpool->af)) {
b0d623f7 3417 goto get_addr;
0a7de745 3418 }
b0d623f7 3419
0a7de745
A
3420try_next:
3421 if ((rpool->cur = TAILQ_NEXT(rpool->cur, entries)) == NULL) {
b0d623f7 3422 rpool->cur = TAILQ_FIRST(&rpool->list);
0a7de745 3423 }
b0d623f7
A
3424 if (rpool->cur->addr.type == PF_ADDR_TABLE) {
3425 rpool->tblidx = -1;
3426 if (pfr_pool_get(rpool->cur->addr.p.tbl,
3427 &rpool->tblidx, &rpool->counter,
3e170ce0
A
3428 &raddr, &rmask, rpool->af)) {
3429 /* table contains no address of type
3430 * 'rpool->af' */
0a7de745 3431 if (rpool->cur != acur) {
b0d623f7 3432 goto try_next;
0a7de745
A
3433 }
3434 return 1;
b0d623f7
A
3435 }
3436 } else if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) {
3437 rpool->tblidx = -1;
0a7de745
A
3438 if (rpool->cur->addr.p.dyn == NULL) {
3439 return 1;
3440 }
b0d623f7
A
3441 if (pfr_pool_get(rpool->cur->addr.p.dyn->pfid_kt,
3442 &rpool->tblidx, &rpool->counter,
3e170ce0
A
3443 &raddr, &rmask, rpool->af)) {
3444 /* table contains no address of type
3445 * 'rpool->af' */
0a7de745 3446 if (rpool->cur != acur) {
b0d623f7 3447 goto try_next;
0a7de745
A
3448 }
3449 return 1;
b0d623f7
A
3450 }
3451 } else {
3452 raddr = &rpool->cur->addr.v.a.addr;
3453 rmask = &rpool->cur->addr.v.a.mask;
3e170ce0 3454 PF_ACPY(&rpool->counter, raddr, rpool->af);
b0d623f7
A
3455 }
3456
0a7de745 3457get_addr:
3e170ce0 3458 PF_ACPY(naddr, &rpool->counter, rpool->af);
0a7de745 3459 if (init_addr != NULL && PF_AZERO(init_addr, rpool->af)) {
3e170ce0 3460 PF_ACPY(init_addr, naddr, rpool->af);
0a7de745 3461 }
3e170ce0 3462 PF_AINC(&rpool->counter, rpool->af);
b0d623f7
A
3463 break;
3464 }
0a7de745 3465 if (*sn != NULL) {
3e170ce0 3466 PF_ACPY(&(*sn)->raddr, naddr, rpool->af);
0a7de745 3467 }
b0d623f7
A
3468
3469 if (pf_status.debug >= PF_DEBUG_MISC &&
3470 (rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_NONE) {
3471 printf("pf_map_addr: selected address ");
3e170ce0 3472 pf_print_host(naddr, 0, rpool->af);
b0d623f7
A
3473 printf("\n");
3474 }
3475
0a7de745 3476 return 0;
b0d623f7
A
3477}
3478
b0d623f7
A
3479static int
3480pf_get_sport(struct pf_pdesc *pd, struct pfi_kif *kif, struct pf_rule *r,
3481 struct pf_addr *saddr, union pf_state_xport *sxport, struct pf_addr *daddr,
3482 union pf_state_xport *dxport, struct pf_addr *naddr,
5ba3f43e
A
3483 union pf_state_xport *nxport, struct pf_src_node **sn
3484 )
b0d623f7
A
3485{
3486#pragma unused(kif)
0a7de745
A
3487 struct pf_state_key_cmp key;
3488 struct pf_addr init_addr;
b0d623f7
A
3489 unsigned int cut;
3490 sa_family_t af = pd->af;
3491 u_int8_t proto = pd->proto;
b7266188
A
3492 unsigned int low = r->rpool.proxy_port[0];
3493 unsigned int high = r->rpool.proxy_port[1];
b0d623f7 3494
0a7de745
A
3495 bzero(&init_addr, sizeof(init_addr));
3496 if (pf_map_addr(af, r, saddr, naddr, &init_addr, sn)) {
3497 return 1;
3498 }
b0d623f7
A
3499
3500 if (proto == IPPROTO_ICMP) {
3501 low = 1;
3502 high = 65535;
3503 }
3504
0a7de745
A
3505 if (!nxport) {
3506 return 0; /* No output necessary. */
3507 }
b0d623f7
A
3508 /*--- Special mapping rules for UDP ---*/
3509 if (proto == IPPROTO_UDP) {
b0d623f7 3510 /*--- Never float IKE source port ---*/
b7266188 3511 if (ntohs(sxport->port) == PF_IKE_PORT) {
b0d623f7 3512 nxport->port = sxport->port;
0a7de745 3513 return 0;
b0d623f7
A
3514 }
3515
3516 /*--- Apply exterior mapping options ---*/
3517 if (r->extmap > PF_EXTMAP_APD) {
3518 struct pf_state *s;
3519
3520 TAILQ_FOREACH(s, &state_list, entry_list) {
3521 struct pf_state_key *sk = s->state_key;
0a7de745 3522 if (!sk) {
b0d623f7 3523 continue;
0a7de745
A
3524 }
3525 if (s->nat_rule.ptr != r) {
b0d623f7 3526 continue;
0a7de745 3527 }
3e170ce0 3528 if (sk->proto != IPPROTO_UDP ||
0a7de745 3529 sk->af_lan != af) {
b0d623f7 3530 continue;
0a7de745
A
3531 }
3532 if (sk->lan.xport.port != sxport->port) {
b0d623f7 3533 continue;
0a7de745
A
3534 }
3535 if (PF_ANEQ(&sk->lan.addr, saddr, af)) {
b0d623f7 3536 continue;
0a7de745 3537 }
b0d623f7 3538 if (r->extmap < PF_EXTMAP_EI &&
0a7de745 3539 PF_ANEQ(&sk->ext_lan.addr, daddr, af)) {
b0d623f7 3540 continue;
0a7de745 3541 }
b0d623f7
A
3542
3543 nxport->port = sk->gwy.xport.port;
0a7de745 3544 return 0;
b0d623f7
A
3545 }
3546 }
b7266188
A
3547 } else if (proto == IPPROTO_TCP) {
3548 struct pf_state* s;
3549 /*
3550 * APPLE MODIFICATION: <rdar://problem/6546358>
3551 * Fix allows....NAT to use a single binding for TCP session
3552 * with same source IP and source port
3553 */
3554 TAILQ_FOREACH(s, &state_list, entry_list) {
3555 struct pf_state_key* sk = s->state_key;
0a7de745 3556 if (!sk) {
b7266188 3557 continue;
0a7de745
A
3558 }
3559 if (s->nat_rule.ptr != r) {
b7266188 3560 continue;
0a7de745
A
3561 }
3562 if (sk->proto != IPPROTO_TCP || sk->af_lan != af) {
3563 continue;
3564 }
3565 if (sk->lan.xport.port != sxport->port) {
b7266188 3566 continue;
0a7de745
A
3567 }
3568 if (!(PF_AEQ(&sk->lan.addr, saddr, af))) {
b7266188 3569 continue;
0a7de745 3570 }
b7266188 3571 nxport->port = sk->gwy.xport.port;
0a7de745 3572 return 0;
b7266188 3573 }
b0d623f7 3574 }
b0d623f7 3575 do {
3e170ce0 3576 key.af_gwy = af;
b0d623f7 3577 key.proto = proto;
3e170ce0
A
3578 PF_ACPY(&key.ext_gwy.addr, daddr, key.af_gwy);
3579 PF_ACPY(&key.gwy.addr, naddr, key.af_gwy);
b0d623f7 3580 switch (proto) {
0a7de745
A
3581 case IPPROTO_UDP:
3582 key.proto_variant = r->extfilter;
3583 break;
3584 default:
3585 key.proto_variant = 0;
3586 break;
b0d623f7 3587 }
0a7de745 3588 if (dxport) {
3e170ce0 3589 key.ext_gwy.xport = *dxport;
0a7de745 3590 } else {
3e170ce0 3591 memset(&key.ext_gwy.xport, 0,
0a7de745
A
3592 sizeof(key.ext_gwy.xport));
3593 }
b0d623f7
A
3594 /*
3595 * port search; start random, step;
3596 * similar 2 portloop in in_pcbbind
3597 */
3598 if (!(proto == IPPROTO_TCP || proto == IPPROTO_UDP ||
3599 proto == IPPROTO_ICMP)) {
0a7de745 3600 if (dxport) {
b0d623f7 3601 key.gwy.xport = *dxport;
0a7de745 3602 } else {
b0d623f7 3603 memset(&key.gwy.xport, 0,
0a7de745
A
3604 sizeof(key.gwy.xport));
3605 }
3606 if (pf_find_state_all(&key, PF_IN, NULL) == NULL) {
3607 return 0;
3608 }
b0d623f7 3609 } else if (low == 0 && high == 0) {
b0d623f7 3610 key.gwy.xport = *nxport;
5ba3f43e
A
3611 if (pf_find_state_all(&key, PF_IN, NULL) == NULL
3612 ) {
0a7de745 3613 return 0;
5ba3f43e 3614 }
b0d623f7 3615 } else if (low == high) {
b0d623f7 3616 key.gwy.xport.port = htons(low);
5ba3f43e
A
3617 if (pf_find_state_all(&key, PF_IN, NULL) == NULL
3618 ) {
b0d623f7 3619 nxport->port = htons(low);
0a7de745 3620 return 0;
b0d623f7 3621 }
b0d623f7 3622 } else {
b0d623f7 3623 unsigned int tmp;
b0d623f7
A
3624 if (low > high) {
3625 tmp = low;
3626 low = high;
3627 high = tmp;
3628 }
3629 /* low < high */
3630 cut = htonl(random()) % (1 + high - low) + low;
3631 /* low <= cut <= high */
3632 for (tmp = cut; tmp <= high; ++(tmp)) {
b0d623f7 3633 key.gwy.xport.port = htons(tmp);
5ba3f43e 3634 if (pf_find_state_all(&key, PF_IN, NULL) == NULL
0a7de745 3635 ) {
b0d623f7 3636 nxport->port = htons(tmp);
0a7de745 3637 return 0;
b0d623f7 3638 }
b0d623f7
A
3639 }
3640 for (tmp = cut - 1; tmp >= low; --(tmp)) {
b0d623f7 3641 key.gwy.xport.port = htons(tmp);
5ba3f43e 3642 if (pf_find_state_all(&key, PF_IN, NULL) == NULL
0a7de745 3643 ) {
b0d623f7 3644 nxport->port = htons(tmp);
0a7de745 3645 return 0;
b0d623f7 3646 }
b0d623f7
A
3647 }
3648 }
3649
3650 switch (r->rpool.opts & PF_POOL_TYPEMASK) {
3651 case PF_POOL_RANDOM:
3652 case PF_POOL_ROUNDROBIN:
0a7de745
A
3653 if (pf_map_addr(af, r, saddr, naddr, &init_addr, sn)) {
3654 return 1;
3655 }
b0d623f7
A
3656 break;
3657 case PF_POOL_NONE:
3658 case PF_POOL_SRCHASH:
3659 case PF_POOL_BITMASK:
3660 default:
0a7de745 3661 return 1;
b0d623f7
A
3662 }
3663 } while (!PF_AEQ(&init_addr, naddr, af));
3664
0a7de745 3665 return 1; /* none available */
b0d623f7
A
3666}
3667
b0d623f7 3668static struct pf_rule *
5ba3f43e 3669pf_match_translation(struct pf_pdesc *pd, pbuf_t *pbuf, int off,
b0d623f7
A
3670 int direction, struct pfi_kif *kif, struct pf_addr *saddr,
3671 union pf_state_xport *sxport, struct pf_addr *daddr,
3672 union pf_state_xport *dxport, int rs_num)
b0d623f7 3673{
0a7de745
A
3674 struct pf_rule *r, *rm = NULL;
3675 struct pf_ruleset *ruleset = NULL;
3676 int tag = -1;
3677 unsigned int rtableid = IFSCOPE_NONE;
3678 int asd = 0;
b0d623f7
A
3679
3680 r = TAILQ_FIRST(pf_main_ruleset.rules[rs_num].active.ptr);
3681 while (r && rm == NULL) {
0a7de745
A
3682 struct pf_rule_addr *src = NULL, *dst = NULL;
3683 struct pf_addr_wrap *xdst = NULL;
3684 struct pf_addr_wrap *xsrc = NULL;
3685 union pf_rule_xport rdrxport;
b0d623f7
A
3686
3687 if (r->action == PF_BINAT && direction == PF_IN) {
3688 src = &r->dst;
0a7de745 3689 if (r->rpool.cur != NULL) {
b0d623f7 3690 xdst = &r->rpool.cur->addr;
0a7de745 3691 }
b0d623f7
A
3692 } else if (r->action == PF_RDR && direction == PF_OUT) {
3693 dst = &r->src;
3694 src = &r->dst;
d1ecb069
A
3695 if (r->rpool.cur != NULL) {
3696 rdrxport.range.op = PF_OP_EQ;
3697 rdrxport.range.port[0] =
3698 htons(r->rpool.proxy_port[0]);
b0d623f7 3699 xsrc = &r->rpool.cur->addr;
d1ecb069 3700 }
b0d623f7
A
3701 } else {
3702 src = &r->src;
3703 dst = &r->dst;
3704 }
3705
3706 r->evaluations++;
0a7de745 3707 if (pfi_kif_match(r->kif, kif) == r->ifnot) {
b0d623f7 3708 r = r->skip[PF_SKIP_IFP].ptr;
0a7de745 3709 } else if (r->direction && r->direction != direction) {
b0d623f7 3710 r = r->skip[PF_SKIP_DIR].ptr;
0a7de745 3711 } else if (r->af && r->af != pd->af) {
b0d623f7 3712 r = r->skip[PF_SKIP_AF].ptr;
0a7de745 3713 } else if (r->proto && r->proto != pd->proto) {
b0d623f7 3714 r = r->skip[PF_SKIP_PROTO].ptr;
0a7de745 3715 } else if (xsrc && PF_MISMATCHAW(xsrc, saddr, pd->af, 0, NULL)) {
b0d623f7 3716 r = TAILQ_NEXT(r, entries);
0a7de745
A
3717 } else if (!xsrc && PF_MISMATCHAW(&src->addr, saddr, pd->af,
3718 src->neg, kif)) {
d1ecb069 3719 r = TAILQ_NEXT(r, entries);
0a7de745 3720 } else if (xsrc && (!rdrxport.range.port[0] ||
d1ecb069 3721 !pf_match_xport(r->proto, r->proto_variant, &rdrxport,
0a7de745 3722 sxport))) {
d1ecb069 3723 r = TAILQ_NEXT(r, entries);
0a7de745
A
3724 } else if (!xsrc && !pf_match_xport(r->proto,
3725 r->proto_variant, &src->xport, sxport)) {
b0d623f7
A
3726 r = r->skip[src == &r->src ? PF_SKIP_SRC_PORT :
3727 PF_SKIP_DST_PORT].ptr;
0a7de745
A
3728 } else if (dst != NULL &&
3729 PF_MISMATCHAW(&dst->addr, daddr, pd->af, dst->neg, NULL)) {
b0d623f7 3730 r = r->skip[PF_SKIP_DST_ADDR].ptr;
0a7de745
A
3731 } else if (xdst != NULL && PF_MISMATCHAW(xdst, daddr, pd->af,
3732 0, NULL)) {
b0d623f7 3733 r = TAILQ_NEXT(r, entries);
0a7de745
A
3734 } else if (dst && !pf_match_xport(r->proto, r->proto_variant,
3735 &dst->xport, dxport)) {
b0d623f7 3736 r = r->skip[PF_SKIP_DST_PORT].ptr;
0a7de745 3737 } else if (r->match_tag && !pf_match_tag(r, pd->pf_mtag, &tag)) {
b0d623f7 3738 r = TAILQ_NEXT(r, entries);
0a7de745 3739 } else if (r->os_fingerprint != PF_OSFP_ANY && (pd->proto !=
5ba3f43e 3740 IPPROTO_TCP || !pf_osfp_match(pf_osfp_fingerprint(pd, pbuf,
0a7de745 3741 off, pd->hdr.tcp), r->os_fingerprint))) {
b0d623f7 3742 r = TAILQ_NEXT(r, entries);
0a7de745
A
3743 } else {
3744 if (r->tag) {
b0d623f7 3745 tag = r->tag;
0a7de745
A
3746 }
3747 if (PF_RTABLEID_IS_VALID(r->rtableid)) {
b0d623f7 3748 rtableid = r->rtableid;
0a7de745 3749 }
b0d623f7
A
3750 if (r->anchor == NULL) {
3751 rm = r;
0a7de745 3752 } else {
b0d623f7
A
3753 pf_step_into_anchor(&asd, &ruleset, rs_num,
3754 &r, NULL, NULL);
0a7de745 3755 }
b0d623f7 3756 }
0a7de745 3757 if (r == NULL) {
b0d623f7
A
3758 pf_step_out_of_anchor(&asd, &ruleset, rs_num, &r,
3759 NULL, NULL);
0a7de745
A
3760 }
3761 }
3762 if (pf_tag_packet(pbuf, pd->pf_mtag, tag, rtableid, NULL)) {
3763 return NULL;
b0d623f7 3764 }
b0d623f7 3765 if (rm != NULL && (rm->action == PF_NONAT ||
3e170ce0 3766 rm->action == PF_NORDR || rm->action == PF_NOBINAT ||
0a7de745
A
3767 rm->action == PF_NONAT64)) {
3768 return NULL;
3769 }
3770 return rm;
b0d623f7
A
3771}
3772
39037602 3773/*
3e170ce0
A
3774 * Get address translation information for NAT/BINAT/RDR
3775 * pd : pf packet descriptor
5ba3f43e 3776 * pbuf : pbuf holding the packet
3e170ce0
A
3777 * off : offset to protocol header
3778 * direction : direction of packet
3779 * kif : pf interface info obtained from the packet's recv interface
3780 * sn : source node pointer (output)
3781 * saddr : packet source address
3782 * sxport : packet source port
3783 * daddr : packet destination address
3784 * dxport : packet destination port
3785 * nsxport : translated source port (output)
3786 *
3787 * Translated source & destination address are updated in pd->nsaddr &
3788 * pd->ndaddr
3789 */
b0d623f7 3790static struct pf_rule *
5ba3f43e 3791pf_get_translation_aux(struct pf_pdesc *pd, pbuf_t *pbuf, int off,
b0d623f7
A
3792 int direction, struct pfi_kif *kif, struct pf_src_node **sn,
3793 struct pf_addr *saddr, union pf_state_xport *sxport, struct pf_addr *daddr,
5ba3f43e
A
3794 union pf_state_xport *dxport, union pf_state_xport *nsxport
3795 )
b0d623f7 3796{
0a7de745 3797 struct pf_rule *r = NULL;
3e170ce0 3798 pd->naf = pd->af;
b0d623f7 3799
b0d623f7 3800 if (direction == PF_OUT) {
5ba3f43e 3801 r = pf_match_translation(pd, pbuf, off, direction, kif, saddr,
b0d623f7 3802 sxport, daddr, dxport, PF_RULESET_BINAT);
0a7de745 3803 if (r == NULL) {
5ba3f43e 3804 r = pf_match_translation(pd, pbuf, off, direction, kif,
b0d623f7 3805 saddr, sxport, daddr, dxport, PF_RULESET_RDR);
0a7de745
A
3806 }
3807 if (r == NULL) {
5ba3f43e 3808 r = pf_match_translation(pd, pbuf, off, direction, kif,
b0d623f7 3809 saddr, sxport, daddr, dxport, PF_RULESET_NAT);
0a7de745 3810 }
b0d623f7 3811 } else {
5ba3f43e 3812 r = pf_match_translation(pd, pbuf, off, direction, kif, saddr,
b0d623f7 3813 sxport, daddr, dxport, PF_RULESET_RDR);
0a7de745 3814 if (r == NULL) {
5ba3f43e 3815 r = pf_match_translation(pd, pbuf, off, direction, kif,
b0d623f7 3816 saddr, sxport, daddr, dxport, PF_RULESET_BINAT);
0a7de745 3817 }
b0d623f7 3818 }
b0d623f7
A
3819
3820 if (r != NULL) {
3e170ce0
A
3821 struct pf_addr *nsaddr = &pd->naddr;
3822 struct pf_addr *ndaddr = &pd->ndaddr;
3823
3824 *nsaddr = *saddr;
3825 *ndaddr = *daddr;
3826
b0d623f7
A
3827 switch (r->action) {
3828 case PF_NONAT:
3e170ce0 3829 case PF_NONAT64:
b0d623f7
A
3830 case PF_NOBINAT:
3831 case PF_NORDR:
0a7de745 3832 return NULL;
b0d623f7 3833 case PF_NAT:
3e170ce0
A
3834 case PF_NAT64:
3835 /*
3836 * we do NAT64 on incoming path and we call ip_input
3837 * which asserts receive interface to be not NULL.
3838 * The below check is to prevent NAT64 action on any
3839 * packet generated by local entity using synthesized
3840 * IPv6 address.
3841 */
0a7de745
A
3842 if ((r->action == PF_NAT64) && (direction == PF_OUT)) {
3843 return NULL;
3844 }
3e170ce0 3845
b0d623f7 3846 if (pf_get_sport(pd, kif, r, saddr, sxport, daddr,
5ba3f43e 3847 dxport, nsaddr, nsxport, sn
0a7de745 3848 )) {
b0d623f7
A
3849 DPFPRINTF(PF_DEBUG_MISC,
3850 ("pf: NAT proxy port allocation "
3851 "(%u-%u) failed\n",
3852 r->rpool.proxy_port[0],
3853 r->rpool.proxy_port[1]));
0a7de745 3854 return NULL;
b0d623f7 3855 }
3e170ce0
A
3856 /*
3857 * For NAT64 the destination IPv4 address is derived
3858 * from the last 32 bits of synthesized IPv6 address
3859 */
3860 if (r->action == PF_NAT64) {
5ba3f43e 3861 ndaddr->v4addr.s_addr = daddr->addr32[3];
3e170ce0
A
3862 pd->naf = AF_INET;
3863 }
b0d623f7
A
3864 break;
3865 case PF_BINAT:
3866 switch (direction) {
3867 case PF_OUT:
3868 if (r->rpool.cur->addr.type ==
3869 PF_ADDR_DYNIFTL) {
0a7de745
A
3870 if (r->rpool.cur->addr.p.dyn == NULL) {
3871 return NULL;
3872 }
b0d623f7
A
3873 switch (pd->af) {
3874#if INET
3875 case AF_INET:
3876 if (r->rpool.cur->addr.p.dyn->
0a7de745
A
3877 pfid_acnt4 < 1) {
3878 return NULL;
3879 }
3e170ce0 3880 PF_POOLMASK(nsaddr,
b0d623f7
A
3881 &r->rpool.cur->addr.p.dyn->
3882 pfid_addr4,
3883 &r->rpool.cur->addr.p.dyn->
3884 pfid_mask4,
3885 saddr, AF_INET);
3886 break;
3887#endif /* INET */
3888#if INET6
3889 case AF_INET6:
3890 if (r->rpool.cur->addr.p.dyn->
0a7de745
A
3891 pfid_acnt6 < 1) {
3892 return NULL;
3893 }
3e170ce0 3894 PF_POOLMASK(nsaddr,
b0d623f7
A
3895 &r->rpool.cur->addr.p.dyn->
3896 pfid_addr6,
3897 &r->rpool.cur->addr.p.dyn->
3898 pfid_mask6,
3899 saddr, AF_INET6);
3900 break;
3901#endif /* INET6 */
3902 }
3903 } else {
3e170ce0 3904 PF_POOLMASK(nsaddr,
b0d623f7
A
3905 &r->rpool.cur->addr.v.a.addr,
3906 &r->rpool.cur->addr.v.a.mask,
3907 saddr, pd->af);
3908 }
3909 break;
3910 case PF_IN:
3911 if (r->src.addr.type == PF_ADDR_DYNIFTL) {
0a7de745
A
3912 if (r->src.addr.p.dyn == NULL) {
3913 return NULL;
3914 }
b0d623f7
A
3915 switch (pd->af) {
3916#if INET
3917 case AF_INET:
3918 if (r->src.addr.p.dyn->
0a7de745
A
3919 pfid_acnt4 < 1) {
3920 return NULL;
3921 }
3e170ce0 3922 PF_POOLMASK(ndaddr,
b0d623f7
A
3923 &r->src.addr.p.dyn->
3924 pfid_addr4,
3925 &r->src.addr.p.dyn->
3926 pfid_mask4,
3927 daddr, AF_INET);
3928 break;
3929#endif /* INET */
3930#if INET6
3931 case AF_INET6:
3932 if (r->src.addr.p.dyn->
0a7de745
A
3933 pfid_acnt6 < 1) {
3934 return NULL;
3935 }
3e170ce0 3936 PF_POOLMASK(ndaddr,
b0d623f7
A
3937 &r->src.addr.p.dyn->
3938 pfid_addr6,
3939 &r->src.addr.p.dyn->
3940 pfid_mask6,
3941 daddr, AF_INET6);
3942 break;
3943#endif /* INET6 */
3944 }
0a7de745 3945 } else {
3e170ce0 3946 PF_POOLMASK(ndaddr,
b0d623f7
A
3947 &r->src.addr.v.a.addr,
3948 &r->src.addr.v.a.mask, daddr,
3949 pd->af);
0a7de745 3950 }
b0d623f7
A
3951 break;
3952 }
3953 break;
3954 case PF_RDR: {
b0d623f7
A
3955 switch (direction) {
3956 case PF_OUT:
3957 if (r->dst.addr.type == PF_ADDR_DYNIFTL) {
0a7de745
A
3958 if (r->dst.addr.p.dyn == NULL) {
3959 return NULL;
3960 }
b0d623f7
A
3961 switch (pd->af) {
3962#if INET
3963 case AF_INET:
3964 if (r->dst.addr.p.dyn->
0a7de745
A
3965 pfid_acnt4 < 1) {
3966 return NULL;
3967 }
3e170ce0 3968 PF_POOLMASK(nsaddr,
b0d623f7
A
3969 &r->dst.addr.p.dyn->
3970 pfid_addr4,
3971 &r->dst.addr.p.dyn->
3972 pfid_mask4,
3973 daddr, AF_INET);
3974 break;
3975#endif /* INET */
3976#if INET6
3977 case AF_INET6:
3978 if (r->dst.addr.p.dyn->
0a7de745
A
3979 pfid_acnt6 < 1) {
3980 return NULL;
3981 }
3e170ce0 3982 PF_POOLMASK(nsaddr,
b0d623f7
A
3983 &r->dst.addr.p.dyn->
3984 pfid_addr6,
3985 &r->dst.addr.p.dyn->
3986 pfid_mask6,
3987 daddr, AF_INET6);
3988 break;
3989#endif /* INET6 */
3990 }
3991 } else {
3e170ce0 3992 PF_POOLMASK(nsaddr,
b0d623f7
A
3993 &r->dst.addr.v.a.addr,
3994 &r->dst.addr.v.a.mask,
3995 daddr, pd->af);
3996 }
0a7de745 3997 if (nsxport && r->dst.xport.range.port[0]) {
3e170ce0 3998 nsxport->port =
d1ecb069 3999 r->dst.xport.range.port[0];
0a7de745 4000 }
b0d623f7
A
4001 break;
4002 case PF_IN:
4003 if (pf_map_addr(pd->af, r, saddr,
0a7de745
A
4004 ndaddr, NULL, sn)) {
4005 return NULL;
4006 }
b0d623f7 4007 if ((r->rpool.opts & PF_POOL_TYPEMASK) ==
0a7de745 4008 PF_POOL_BITMASK) {
3e170ce0 4009 PF_POOLMASK(ndaddr, ndaddr,
b0d623f7
A
4010 &r->rpool.cur->addr.v.a.mask, daddr,
4011 pd->af);
0a7de745 4012 }
b0d623f7 4013
3e170ce0 4014 if (nsxport && dxport) {
b0d623f7 4015 if (r->rpool.proxy_port[1]) {
0a7de745 4016 u_int32_t tmp_nport;
b0d623f7
A
4017
4018 tmp_nport =
4019 ((ntohs(dxport->port) -
4020 ntohs(r->dst.xport.range.
4021 port[0])) %
4022 (r->rpool.proxy_port[1] -
4023 r->rpool.proxy_port[0] +
4024 1)) + r->rpool.proxy_port[0];
4025
4026 /* wrap around if necessary */
0a7de745 4027 if (tmp_nport > 65535) {
b0d623f7 4028 tmp_nport -= 65535;
0a7de745 4029 }
3e170ce0 4030 nsxport->port =
b0d623f7
A
4031 htons((u_int16_t)tmp_nport);
4032 } else if (r->rpool.proxy_port[0]) {
3e170ce0 4033 nsxport->port = htons(r->rpool.
b0d623f7
A
4034 proxy_port[0]);
4035 }
4036 }
4037 break;
4038 }
b0d623f7
A
4039 break;
4040 }
4041 default:
0a7de745 4042 return NULL;
b0d623f7
A
4043 }
4044 }
4045
0a7de745 4046 return r;
b0d623f7
A
4047}
4048
4049int
4050pf_socket_lookup(int direction, struct pf_pdesc *pd)
4051{
0a7de745
A
4052 struct pf_addr *saddr, *daddr;
4053 u_int16_t sport, dport;
4054 struct inpcbinfo *pi;
4055 int inp = 0;
b0d623f7 4056
0a7de745
A
4057 if (pd == NULL) {
4058 return -1;
4059 }
b0d623f7
A
4060 pd->lookup.uid = UID_MAX;
4061 pd->lookup.gid = GID_MAX;
4062 pd->lookup.pid = NO_PID;
4063
4064 switch (pd->proto) {
4065 case IPPROTO_TCP:
0a7de745
A
4066 if (pd->hdr.tcp == NULL) {
4067 return -1;
4068 }
b0d623f7
A
4069 sport = pd->hdr.tcp->th_sport;
4070 dport = pd->hdr.tcp->th_dport;
4071 pi = &tcbinfo;
4072 break;
4073 case IPPROTO_UDP:
0a7de745
A
4074 if (pd->hdr.udp == NULL) {
4075 return -1;
4076 }
b0d623f7
A
4077 sport = pd->hdr.udp->uh_sport;
4078 dport = pd->hdr.udp->uh_dport;
4079 pi = &udbinfo;
4080 break;
4081 default:
0a7de745 4082 return -1;
b0d623f7
A
4083 }
4084 if (direction == PF_IN) {
4085 saddr = pd->src;
4086 daddr = pd->dst;
4087 } else {
0a7de745 4088 u_int16_t p;
b0d623f7
A
4089
4090 p = sport;
4091 sport = dport;
4092 dport = p;
4093 saddr = pd->dst;
4094 daddr = pd->src;
4095 }
4096 switch (pd->af) {
4097#if INET
4098 case AF_INET:
5ba3f43e 4099 inp = in_pcblookup_hash_exists(pi, saddr->v4addr, sport, daddr->v4addr, dport,
6d2010ae 4100 0, &pd->lookup.uid, &pd->lookup.gid, NULL);
b7266188 4101#if INET6
6d2010ae 4102 if (inp == 0) {
b7266188
A
4103 struct in6_addr s6, d6;
4104
0a7de745 4105 memset(&s6, 0, sizeof(s6));
b7266188 4106 s6.s6_addr16[5] = htons(0xffff);
5ba3f43e 4107 memcpy(&s6.s6_addr32[3], &saddr->v4addr,
0a7de745 4108 sizeof(saddr->v4addr));
b7266188 4109
0a7de745 4110 memset(&d6, 0, sizeof(d6));
b7266188 4111 d6.s6_addr16[5] = htons(0xffff);
5ba3f43e 4112 memcpy(&d6.s6_addr32[3], &daddr->v4addr,
0a7de745 4113 sizeof(daddr->v4addr));
b7266188 4114
6d2010ae
A
4115 inp = in6_pcblookup_hash_exists(pi, &s6, sport,
4116 &d6, dport, 0, &pd->lookup.uid, &pd->lookup.gid, NULL);
4117 if (inp == 0) {
5ba3f43e
A
4118 inp = in_pcblookup_hash_exists(pi, saddr->v4addr, sport,
4119 daddr->v4addr, dport, INPLOOKUP_WILDCARD, &pd->lookup.uid, &pd->lookup.gid, NULL);
6d2010ae
A
4120 if (inp == 0) {
4121 inp = in6_pcblookup_hash_exists(pi, &s6, sport,
b7266188 4122 &d6, dport, INPLOOKUP_WILDCARD,
6d2010ae 4123 &pd->lookup.uid, &pd->lookup.gid, NULL);
0a7de745
A
4124 if (inp == 0) {
4125 return -1;
4126 }
b7266188
A
4127 }
4128 }
4129 }
4130#else
6d2010ae 4131 if (inp == 0) {
5ba3f43e
A
4132 inp = in_pcblookup_hash_exists(pi, saddr->v4addr, sport,
4133 daddr->v4addr, dport, INPLOOKUP_WILDCARD,
6d2010ae 4134 &pd->lookup.uid, &pd->lookup.gid, NULL);
0a7de745
A
4135 if (inp == 0) {
4136 return -1;
4137 }
b0d623f7 4138 }
b7266188 4139#endif /* !INET6 */
b0d623f7
A
4140 break;
4141#endif /* INET */
4142#if INET6
4143 case AF_INET6:
5ba3f43e 4144 inp = in6_pcblookup_hash_exists(pi, &saddr->v6addr, sport, &daddr->v6addr,
6d2010ae
A
4145 dport, 0, &pd->lookup.uid, &pd->lookup.gid, NULL);
4146 if (inp == 0) {
5ba3f43e
A
4147 inp = in6_pcblookup_hash_exists(pi, &saddr->v6addr, sport,
4148 &daddr->v6addr, dport, INPLOOKUP_WILDCARD,
6d2010ae 4149 &pd->lookup.uid, &pd->lookup.gid, NULL);
0a7de745
A
4150 if (inp == 0) {
4151 return -1;
4152 }
b0d623f7
A
4153 }
4154 break;
4155#endif /* INET6 */
39037602 4156
b0d623f7 4157 default:
0a7de745 4158 return -1;
b0d623f7
A
4159 }
4160
0a7de745 4161 return 1;
b0d623f7
A
4162}
4163
4164static u_int8_t
5ba3f43e 4165pf_get_wscale(pbuf_t *pbuf, int off, u_int16_t th_off, sa_family_t af)
b0d623f7 4166{
0a7de745
A
4167 int hlen;
4168 u_int8_t hdr[60];
4169 u_int8_t *opt, optlen;
4170 u_int8_t wscale = 0;
4171
4172 hlen = th_off << 2; /* hlen <= sizeof (hdr) */
4173 if (hlen <= (int)sizeof(struct tcphdr)) {
4174 return 0;
4175 }
4176 if (!pf_pull_hdr(pbuf, off, hdr, hlen, NULL, NULL, af)) {
4177 return 0;
4178 }
4179 opt = hdr + sizeof(struct tcphdr);
4180 hlen -= sizeof(struct tcphdr);
b0d623f7
A
4181 while (hlen >= 3) {
4182 switch (*opt) {
4183 case TCPOPT_EOL:
4184 case TCPOPT_NOP:
4185 ++opt;
4186 --hlen;
4187 break;
4188 case TCPOPT_WINDOW:
4189 wscale = opt[2];
0a7de745 4190 if (wscale > TCP_MAX_WINSHIFT) {
b0d623f7 4191 wscale = TCP_MAX_WINSHIFT;
0a7de745 4192 }
b0d623f7 4193 wscale |= PF_WSCALE_FLAG;
0a7de745 4194 /* FALLTHROUGH */
b0d623f7
A
4195 default:
4196 optlen = opt[1];
0a7de745 4197 if (optlen < 2) {
b0d623f7 4198 optlen = 2;
0a7de745 4199 }
b0d623f7
A
4200 hlen -= optlen;
4201 opt += optlen;
4202 break;
4203 }
4204 }
0a7de745 4205 return wscale;
b0d623f7
A
4206}
4207
4208static u_int16_t
5ba3f43e 4209pf_get_mss(pbuf_t *pbuf, int off, u_int16_t th_off, sa_family_t af)
b0d623f7 4210{
0a7de745
A
4211 int hlen;
4212 u_int8_t hdr[60];
4213 u_int8_t *opt, optlen;
4214 u_int16_t mss = tcp_mssdflt;
4215
4216 hlen = th_off << 2; /* hlen <= sizeof (hdr) */
4217 if (hlen <= (int)sizeof(struct tcphdr)) {
4218 return 0;
4219 }
4220 if (!pf_pull_hdr(pbuf, off, hdr, hlen, NULL, NULL, af)) {
4221 return 0;
4222 }
4223 opt = hdr + sizeof(struct tcphdr);
4224 hlen -= sizeof(struct tcphdr);
b0d623f7
A
4225 while (hlen >= TCPOLEN_MAXSEG) {
4226 switch (*opt) {
4227 case TCPOPT_EOL:
4228 case TCPOPT_NOP:
4229 ++opt;
4230 --hlen;
4231 break;
4232 case TCPOPT_MAXSEG:
4233 bcopy((caddr_t)(opt + 2), (caddr_t)&mss, 2);
4234#if BYTE_ORDER != BIG_ENDIAN
4235 NTOHS(mss);
4236#endif
0a7de745 4237 /* FALLTHROUGH */
b0d623f7
A
4238 default:
4239 optlen = opt[1];
0a7de745 4240 if (optlen < 2) {
b0d623f7 4241 optlen = 2;
0a7de745 4242 }
b0d623f7
A
4243 hlen -= optlen;
4244 opt += optlen;
4245 break;
4246 }
4247 }
0a7de745 4248 return mss;
b0d623f7
A
4249}
4250
4251static u_int16_t
4252pf_calc_mss(struct pf_addr *addr, sa_family_t af, u_int16_t offer)
4253{
4254#if INET
0a7de745
A
4255 struct sockaddr_in *dst;
4256 struct route ro;
b0d623f7
A
4257#endif /* INET */
4258#if INET6
0a7de745
A
4259 struct sockaddr_in6 *dst6;
4260 struct route_in6 ro6;
b0d623f7 4261#endif /* INET6 */
0a7de745
A
4262 struct rtentry *rt = NULL;
4263 int hlen;
4264 u_int16_t mss = tcp_mssdflt;
b0d623f7
A
4265
4266 switch (af) {
4267#if INET
4268 case AF_INET:
0a7de745
A
4269 hlen = sizeof(struct ip);
4270 bzero(&ro, sizeof(ro));
316670eb 4271 dst = (struct sockaddr_in *)(void *)&ro.ro_dst;
b0d623f7 4272 dst->sin_family = AF_INET;
0a7de745 4273 dst->sin_len = sizeof(*dst);
5ba3f43e 4274 dst->sin_addr = addr->v4addr;
b0d623f7
A
4275 rtalloc(&ro);
4276 rt = ro.ro_rt;
4277 break;
4278#endif /* INET */
4279#if INET6
4280 case AF_INET6:
0a7de745
A
4281 hlen = sizeof(struct ip6_hdr);
4282 bzero(&ro6, sizeof(ro6));
316670eb 4283 dst6 = (struct sockaddr_in6 *)(void *)&ro6.ro_dst;
b0d623f7 4284 dst6->sin6_family = AF_INET6;
0a7de745 4285 dst6->sin6_len = sizeof(*dst6);
5ba3f43e 4286 dst6->sin6_addr = addr->v6addr;
b0d623f7
A
4287 rtalloc((struct route *)&ro);
4288 rt = ro6.ro_rt;
4289 break;
4290#endif /* INET6 */
4291 default:
4292 panic("pf_calc_mss: not AF_INET or AF_INET6!");
0a7de745 4293 return 0;
b0d623f7
A
4294 }
4295
4296 if (rt && rt->rt_ifp) {
0a7de745 4297 /* This is relevant only for PF SYN Proxy */
d9a64523
A
4298 int interface_mtu = rt->rt_ifp->if_mtu;
4299
4300 if (af == AF_INET &&
4301 INTF_ADJUST_MTU_FOR_CLAT46(rt->rt_ifp)) {
4302 interface_mtu = IN6_LINKMTU(rt->rt_ifp);
4303 /* Further adjust the size for CLAT46 expansion */
4304 interface_mtu -= CLAT46_HDR_EXPANSION_OVERHD;
4305 }
0a7de745 4306 mss = interface_mtu - hlen - sizeof(struct tcphdr);
b0d623f7 4307 mss = max(tcp_mssdflt, mss);
39236c6e 4308 rtfree(rt);
b0d623f7
A
4309 }
4310 mss = min(mss, offer);
0a7de745
A
4311 mss = max(mss, 64); /* sanity - at least max opt space */
4312 return mss;
b0d623f7
A
4313}
4314
4315static void
3e170ce0 4316pf_set_rt_ifp(struct pf_state *s, struct pf_addr *saddr, sa_family_t af)
b0d623f7
A
4317{
4318 struct pf_rule *r = s->rule.ptr;
4319
4320 s->rt_kif = NULL;
3e170ce0 4321
0a7de745 4322 if (!r->rt || r->rt == PF_FASTROUTE) {
b0d623f7 4323 return;
0a7de745 4324 }
3e170ce0
A
4325 if ((af == AF_INET) || (af == AF_INET6)) {
4326 pf_map_addr(af, r, saddr, &s->rt_addr, NULL,
b0d623f7
A
4327 &s->nat_src_node);
4328 s->rt_kif = r->rpool.cur->kif;
b0d623f7 4329 }
3e170ce0
A
4330
4331 return;
b0d623f7
A
4332}
4333
4334static void
4335pf_attach_state(struct pf_state_key *sk, struct pf_state *s, int tail)
4336{
4337 s->state_key = sk;
4338 sk->refcnt++;
4339
4340 /* list is sorted, if-bound states before floating */
0a7de745 4341 if (tail) {
b0d623f7 4342 TAILQ_INSERT_TAIL(&sk->states, s, next);
0a7de745 4343 } else {
b0d623f7 4344 TAILQ_INSERT_HEAD(&sk->states, s, next);
0a7de745 4345 }
b0d623f7
A
4346}
4347
4348static void
4349pf_detach_state(struct pf_state *s, int flags)
4350{
0a7de745 4351 struct pf_state_key *sk = s->state_key;
b0d623f7 4352
0a7de745 4353 if (sk == NULL) {
b0d623f7 4354 return;
0a7de745 4355 }
b0d623f7
A
4356
4357 s->state_key = NULL;
4358 TAILQ_REMOVE(&sk->states, s, next);
4359 if (--sk->refcnt == 0) {
0a7de745 4360 if (!(flags & PF_DT_SKIP_EXTGWY)) {
b0d623f7
A
4361 RB_REMOVE(pf_state_tree_ext_gwy,
4362 &pf_statetbl_ext_gwy, sk);
0a7de745
A
4363 }
4364 if (!(flags & PF_DT_SKIP_LANEXT)) {
b0d623f7
A
4365 RB_REMOVE(pf_state_tree_lan_ext,
4366 &pf_statetbl_lan_ext, sk);
0a7de745
A
4367 }
4368 if (sk->app_state) {
b0d623f7 4369 pool_put(&pf_app_state_pl, sk->app_state);
0a7de745 4370 }
b0d623f7
A
4371 pool_put(&pf_state_key_pl, sk);
4372 }
4373}
4374
4375struct pf_state_key *
316670eb 4376pf_alloc_state_key(struct pf_state *s, struct pf_state_key *psk)
b0d623f7 4377{
0a7de745 4378 struct pf_state_key *sk;
b0d623f7 4379
0a7de745
A
4380 if ((sk = pool_get(&pf_state_key_pl, PR_WAITOK)) == NULL) {
4381 return NULL;
4382 }
4383 bzero(sk, sizeof(*sk));
b0d623f7
A
4384 TAILQ_INIT(&sk->states);
4385 pf_attach_state(sk, s, 0);
4386
316670eb
A
4387 /* initialize state key from psk, if provided */
4388 if (psk != NULL) {
0a7de745
A
4389 bcopy(&psk->lan, &sk->lan, sizeof(sk->lan));
4390 bcopy(&psk->gwy, &sk->gwy, sizeof(sk->gwy));
4391 bcopy(&psk->ext_lan, &sk->ext_lan, sizeof(sk->ext_lan));
4392 bcopy(&psk->ext_gwy, &sk->ext_gwy, sizeof(sk->ext_gwy));
3e170ce0
A
4393 sk->af_lan = psk->af_lan;
4394 sk->af_gwy = psk->af_gwy;
316670eb
A
4395 sk->proto = psk->proto;
4396 sk->direction = psk->direction;
4397 sk->proto_variant = psk->proto_variant;
4398 VERIFY(psk->app_state == NULL);
39236c6e 4399 sk->flowsrc = psk->flowsrc;
316670eb
A
4400 sk->flowhash = psk->flowhash;
4401 /* don't touch tree entries, states and refcnt on sk */
4402 }
4403
0a7de745 4404 return sk;
b0d623f7
A
4405}
4406
4407static u_int32_t
4408pf_tcp_iss(struct pf_pdesc *pd)
4409{
4410 MD5_CTX ctx;
4411 u_int32_t digest[4];
4412
4413 if (pf_tcp_secret_init == 0) {
0a7de745 4414 read_frandom(pf_tcp_secret, sizeof(pf_tcp_secret));
b0d623f7
A
4415 MD5Init(&pf_tcp_secret_ctx);
4416 MD5Update(&pf_tcp_secret_ctx, pf_tcp_secret,
0a7de745 4417 sizeof(pf_tcp_secret));
b0d623f7
A
4418 pf_tcp_secret_init = 1;
4419 }
4420 ctx = pf_tcp_secret_ctx;
4421
0a7de745
A
4422 MD5Update(&ctx, (char *)&pd->hdr.tcp->th_sport, sizeof(u_short));
4423 MD5Update(&ctx, (char *)&pd->hdr.tcp->th_dport, sizeof(u_short));
b0d623f7 4424 if (pd->af == AF_INET6) {
0a7de745
A
4425 MD5Update(&ctx, (char *)&pd->src->v6addr, sizeof(struct in6_addr));
4426 MD5Update(&ctx, (char *)&pd->dst->v6addr, sizeof(struct in6_addr));
b0d623f7 4427 } else {
0a7de745
A
4428 MD5Update(&ctx, (char *)&pd->src->v4addr, sizeof(struct in_addr));
4429 MD5Update(&ctx, (char *)&pd->dst->v4addr, sizeof(struct in_addr));
b0d623f7
A
4430 }
4431 MD5Final((u_char *)digest, &ctx);
4432 pf_tcp_iss_off += 4096;
0a7de745 4433 return digest[0] + random() + pf_tcp_iss_off;
b0d623f7
A
4434}
4435
3e170ce0
A
4436/*
4437 * This routine is called to perform address family translation on the
5ba3f43e 4438 * inner IP header (that may come as payload) of an ICMP(v4addr/6) error
3e170ce0
A
4439 * response.
4440 */
4441static int
5ba3f43e 4442pf_change_icmp_af(pbuf_t *pbuf, int off,
0a7de745
A
4443 struct pf_pdesc *pd, struct pf_pdesc *pd2, struct pf_addr *src,
4444 struct pf_addr *dst, sa_family_t af, sa_family_t naf)
3e170ce0 4445{
0a7de745
A
4446 struct ip *ip4 = NULL;
4447 struct ip6_hdr *ip6 = NULL;
4448 void *hdr;
4449 int hlen, olen;
3e170ce0
A
4450
4451 if (af == naf || (af != AF_INET && af != AF_INET6) ||
0a7de745
A
4452 (naf != AF_INET && naf != AF_INET6)) {
4453 return -1;
4454 }
3e170ce0 4455
3e170ce0
A
4456 /* old header */
4457 olen = pd2->off - off;
4458 /* new header */
4459 hlen = naf == AF_INET ? sizeof(*ip4) : sizeof(*ip6);
4460
5ba3f43e
A
4461 /* Modify the pbuf to accommodate the new header */
4462 hdr = pbuf_resize_segment(pbuf, off, olen, hlen);
0a7de745
A
4463 if (hdr == NULL) {
4464 return -1;
4465 }
3e170ce0
A
4466
4467 /* translate inner ip/ip6 header */
4468 switch (naf) {
4469 case AF_INET:
5ba3f43e 4470 ip4 = hdr;
3e170ce0
A
4471 bzero(ip4, sizeof(*ip4));
4472 ip4->ip_v = IPVERSION;
4473 ip4->ip_hl = sizeof(*ip4) >> 2;
4474 ip4->ip_len = htons(sizeof(*ip4) + pd2->tot_len - olen);
5ba3f43e 4475 ip4->ip_id = rfc6864 ? 0 : htons(ip_randomid());
3e170ce0
A
4476 ip4->ip_off = htons(IP_DF);
4477 ip4->ip_ttl = pd2->ttl;
0a7de745 4478 if (pd2->proto == IPPROTO_ICMPV6) {
3e170ce0 4479 ip4->ip_p = IPPROTO_ICMP;
0a7de745 4480 } else {
3e170ce0 4481 ip4->ip_p = pd2->proto;
0a7de745 4482 }
5ba3f43e
A
4483 ip4->ip_src = src->v4addr;
4484 ip4->ip_dst = dst->v4addr;
4485 ip4->ip_sum = pbuf_inet_cksum(pbuf, 0, 0, ip4->ip_hl << 2);
3e170ce0
A
4486 break;
4487 case AF_INET6:
5ba3f43e 4488 ip6 = hdr;
3e170ce0
A
4489 bzero(ip6, sizeof(*ip6));
4490 ip6->ip6_vfc = IPV6_VERSION;
4491 ip6->ip6_plen = htons(pd2->tot_len - olen);
0a7de745 4492 if (pd2->proto == IPPROTO_ICMP) {
3e170ce0 4493 ip6->ip6_nxt = IPPROTO_ICMPV6;
0a7de745 4494 } else {
3e170ce0 4495 ip6->ip6_nxt = pd2->proto;
0a7de745
A
4496 }
4497 if (!pd2->ttl || pd2->ttl > IPV6_DEFHLIM) {
3e170ce0 4498 ip6->ip6_hlim = IPV6_DEFHLIM;
0a7de745 4499 } else {
3e170ce0 4500 ip6->ip6_hlim = pd2->ttl;
0a7de745 4501 }
5ba3f43e
A
4502 ip6->ip6_src = src->v6addr;
4503 ip6->ip6_dst = dst->v6addr;
3e170ce0
A
4504 break;
4505 }
4506
4507 /* adjust payload offset and total packet length */
4508 pd2->off += hlen - olen;
4509 pd->tot_len += hlen - olen;
4510
0a7de745 4511 return 0;
3e170ce0
A
4512}
4513
0a7de745
A
4514#define PTR_IP(field) ((int32_t)offsetof(struct ip, field))
4515#define PTR_IP6(field) ((int32_t)offsetof(struct ip6_hdr, field))
3e170ce0
A
4516
4517static int
4518pf_translate_icmp_af(int af, void *arg)
4519{
0a7de745
A
4520 struct icmp *icmp4;
4521 struct icmp6_hdr *icmp6;
4522 u_int32_t mtu;
4523 int32_t ptr = -1;
4524 u_int8_t type;
4525 u_int8_t code;
3e170ce0
A
4526
4527 switch (af) {
4528 case AF_INET:
4529 icmp6 = arg;
4530 type = icmp6->icmp6_type;
4531 code = icmp6->icmp6_code;
4532 mtu = ntohl(icmp6->icmp6_mtu);
4533
4534 switch (type) {
4535 case ICMP6_ECHO_REQUEST:
4536 type = ICMP_ECHO;
4537 break;
4538 case ICMP6_ECHO_REPLY:
4539 type = ICMP_ECHOREPLY;
4540 break;
4541 case ICMP6_DST_UNREACH:
4542 type = ICMP_UNREACH;
4543 switch (code) {
4544 case ICMP6_DST_UNREACH_NOROUTE:
4545 case ICMP6_DST_UNREACH_BEYONDSCOPE:
4546 case ICMP6_DST_UNREACH_ADDR:
4547 code = ICMP_UNREACH_HOST;
4548 break;
4549 case ICMP6_DST_UNREACH_ADMIN:
4550 code = ICMP_UNREACH_HOST_PROHIB;
4551 break;
4552 case ICMP6_DST_UNREACH_NOPORT:
4553 code = ICMP_UNREACH_PORT;
4554 break;
4555 default:
0a7de745 4556 return -1;
3e170ce0
A
4557 }
4558 break;
4559 case ICMP6_PACKET_TOO_BIG:
4560 type = ICMP_UNREACH;
4561 code = ICMP_UNREACH_NEEDFRAG;
4562 mtu -= 20;
4563 break;
4564 case ICMP6_TIME_EXCEEDED:
4565 type = ICMP_TIMXCEED;
4566 break;
4567 case ICMP6_PARAM_PROB:
4568 switch (code) {
4569 case ICMP6_PARAMPROB_HEADER:
4570 type = ICMP_PARAMPROB;
4571 code = ICMP_PARAMPROB_ERRATPTR;
4572 ptr = ntohl(icmp6->icmp6_pptr);
4573
0a7de745 4574 if (ptr == PTR_IP6(ip6_vfc)) {
3e170ce0 4575 ; /* preserve */
0a7de745 4576 } else if (ptr == PTR_IP6(ip6_vfc) + 1) {
3e170ce0 4577 ptr = PTR_IP(ip_tos);
0a7de745
A
4578 } else if (ptr == PTR_IP6(ip6_plen) ||
4579 ptr == PTR_IP6(ip6_plen) + 1) {
3e170ce0 4580 ptr = PTR_IP(ip_len);
0a7de745 4581 } else if (ptr == PTR_IP6(ip6_nxt)) {
3e170ce0 4582 ptr = PTR_IP(ip_p);
0a7de745 4583 } else if (ptr == PTR_IP6(ip6_hlim)) {
3e170ce0 4584 ptr = PTR_IP(ip_ttl);
0a7de745
A
4585 } else if (ptr >= PTR_IP6(ip6_src) &&
4586 ptr < PTR_IP6(ip6_dst)) {
3e170ce0 4587 ptr = PTR_IP(ip_src);
0a7de745
A
4588 } else if (ptr >= PTR_IP6(ip6_dst) &&
4589 ptr < (int32_t)sizeof(struct ip6_hdr)) {
3e170ce0 4590 ptr = PTR_IP(ip_dst);
0a7de745
A
4591 } else {
4592 return -1;
3e170ce0
A
4593 }
4594 break;
4595 case ICMP6_PARAMPROB_NEXTHEADER:
4596 type = ICMP_UNREACH;
4597 code = ICMP_UNREACH_PROTOCOL;
4598 break;
4599 default:
0a7de745 4600 return -1;
3e170ce0
A
4601 }
4602 break;
4603 default:
0a7de745 4604 return -1;
3e170ce0
A
4605 }
4606 icmp6->icmp6_type = type;
4607 icmp6->icmp6_code = code;
4608 /* aligns well with a icmpv4 nextmtu */
4609 icmp6->icmp6_mtu = htonl(mtu);
4610 /* icmpv4 pptr is a one most significant byte */
0a7de745 4611 if (ptr >= 0) {
3e170ce0 4612 icmp6->icmp6_pptr = htonl(ptr << 24);
0a7de745 4613 }
3e170ce0
A
4614 break;
4615
4616 case AF_INET6:
4617 icmp4 = arg;
4618 type = icmp4->icmp_type;
4619 code = icmp4->icmp_code;
4620 mtu = ntohs(icmp4->icmp_nextmtu);
4621
4622 switch (type) {
4623 case ICMP_ECHO:
4624 type = ICMP6_ECHO_REQUEST;
4625 break;
4626 case ICMP_ECHOREPLY:
4627 type = ICMP6_ECHO_REPLY;
4628 break;
4629 case ICMP_UNREACH:
4630 type = ICMP6_DST_UNREACH;
4631 switch (code) {
4632 case ICMP_UNREACH_NET:
4633 case ICMP_UNREACH_HOST:
4634 case ICMP_UNREACH_NET_UNKNOWN:
4635 case ICMP_UNREACH_HOST_UNKNOWN:
4636 case ICMP_UNREACH_ISOLATED:
4637 case ICMP_UNREACH_TOSNET:
4638 case ICMP_UNREACH_TOSHOST:
4639 code = ICMP6_DST_UNREACH_NOROUTE;
4640 break;
4641 case ICMP_UNREACH_PORT:
4642 code = ICMP6_DST_UNREACH_NOPORT;
4643 break;
4644 case ICMP_UNREACH_NET_PROHIB:
4645 case ICMP_UNREACH_HOST_PROHIB:
4646 case ICMP_UNREACH_FILTER_PROHIB:
4647 case ICMP_UNREACH_PRECEDENCE_CUTOFF:
4648 code = ICMP6_DST_UNREACH_ADMIN;
4649 break;
4650 case ICMP_UNREACH_PROTOCOL:
4651 type = ICMP6_PARAM_PROB;
4652 code = ICMP6_PARAMPROB_NEXTHEADER;
4653 ptr = offsetof(struct ip6_hdr, ip6_nxt);
4654 break;
4655 case ICMP_UNREACH_NEEDFRAG:
4656 type = ICMP6_PACKET_TOO_BIG;
4657 code = 0;
4658 mtu += 20;
4659 break;
4660 default:
0a7de745 4661 return -1;
3e170ce0
A
4662 }
4663 break;
4664 case ICMP_TIMXCEED:
4665 type = ICMP6_TIME_EXCEEDED;
4666 break;
4667 case ICMP_PARAMPROB:
4668 type = ICMP6_PARAM_PROB;
4669 switch (code) {
4670 case ICMP_PARAMPROB_ERRATPTR:
4671 code = ICMP6_PARAMPROB_HEADER;
4672 break;
4673 case ICMP_PARAMPROB_LENGTH:
4674 code = ICMP6_PARAMPROB_HEADER;
4675 break;
4676 default:
0a7de745 4677 return -1;
3e170ce0
A
4678 }
4679
4680 ptr = icmp4->icmp_pptr;
0a7de745 4681 if (ptr == 0 || ptr == PTR_IP(ip_tos)) {
3e170ce0 4682 ; /* preserve */
0a7de745
A
4683 } else if (ptr == PTR_IP(ip_len) ||
4684 ptr == PTR_IP(ip_len) + 1) {
3e170ce0 4685 ptr = PTR_IP6(ip6_plen);
0a7de745 4686 } else if (ptr == PTR_IP(ip_ttl)) {
3e170ce0 4687 ptr = PTR_IP6(ip6_hlim);
0a7de745 4688 } else if (ptr == PTR_IP(ip_p)) {
3e170ce0 4689 ptr = PTR_IP6(ip6_nxt);
0a7de745
A
4690 } else if (ptr >= PTR_IP(ip_src) &&
4691 ptr < PTR_IP(ip_dst)) {
3e170ce0 4692 ptr = PTR_IP6(ip6_src);
0a7de745
A
4693 } else if (ptr >= PTR_IP(ip_dst) &&
4694 ptr < (int32_t)sizeof(struct ip)) {
3e170ce0 4695 ptr = PTR_IP6(ip6_dst);
0a7de745
A
4696 } else {
4697 return -1;
3e170ce0
A
4698 }
4699 break;
4700 default:
0a7de745 4701 return -1;
3e170ce0
A
4702 }
4703 icmp4->icmp_type = type;
4704 icmp4->icmp_code = code;
4705 icmp4->icmp_nextmtu = htons(mtu);
0a7de745 4706 if (ptr >= 0) {
3e170ce0 4707 icmp4->icmp_void = htonl(ptr);
0a7de745 4708 }
3e170ce0
A
4709 break;
4710 }
4711
0a7de745 4712 return 0;
3e170ce0
A
4713}
4714
5ba3f43e 4715/* Note: frees pbuf if PF_NAT64 is returned */
3e170ce0 4716static int
5ba3f43e 4717pf_nat64_ipv6(pbuf_t *pbuf, int off, struct pf_pdesc *pd)
3e170ce0 4718{
0a7de745 4719 struct ip *ip4;
5ba3f43e 4720 struct mbuf *m;
3e170ce0
A
4721
4722 /*
4723 * ip_input asserts for rcvif to be not NULL
4724 * That may not be true for two corner cases
4725 * 1. If for some reason a local app sends DNS
4726 * AAAA query to local host
4727 * 2. If IPv6 stack in kernel internally generates a
4728 * message destined for a synthesized IPv6 end-point.
4729 */
0a7de745
A
4730 if (pbuf->pb_ifp == NULL) {
4731 return PF_DROP;
4732 }
3e170ce0 4733
5ba3f43e 4734 ip4 = (struct ip *)pbuf_resize_segment(pbuf, 0, off, sizeof(*ip4));
0a7de745
A
4735 if (ip4 == NULL) {
4736 return PF_DROP;
4737 }
3e170ce0 4738
3e170ce0
A
4739 ip4->ip_v = 4;
4740 ip4->ip_hl = 5;
4741 ip4->ip_tos = pd->tos & htonl(0x0ff00000);
4742 ip4->ip_len = htons(sizeof(*ip4) + (pd->tot_len - off));
d9a64523
A
4743 ip4->ip_id = 0;
4744 ip4->ip_off = htons(IP_DF);
4745 ip4->ip_ttl = pd->ttl;
4746 ip4->ip_p = pd->proto;
3e170ce0 4747 ip4->ip_sum = 0;
5ba3f43e
A
4748 ip4->ip_src = pd->naddr.v4addr;
4749 ip4->ip_dst = pd->ndaddr.v4addr;
4750 ip4->ip_sum = pbuf_inet_cksum(pbuf, 0, 0, ip4->ip_hl << 2);
3e170ce0
A
4751
4752 /* recalculate icmp checksums */
4753 if (pd->proto == IPPROTO_ICMP) {
3e170ce0 4754 struct icmp *icmp;
5ba3f43e 4755 int hlen = sizeof(*ip4);
3e170ce0 4756
5ba3f43e
A
4757 icmp = (struct icmp *)pbuf_contig_segment(pbuf, hlen,
4758 ICMP_MINLEN);
0a7de745
A
4759 if (icmp == NULL) {
4760 return PF_DROP;
4761 }
3e170ce0 4762
3e170ce0 4763 icmp->icmp_cksum = 0;
5ba3f43e 4764 icmp->icmp_cksum = pbuf_inet_cksum(pbuf, 0, hlen,
0a7de745 4765 ntohs(ip4->ip_len) - hlen);
3e170ce0
A
4766 }
4767
0a7de745 4768 if ((m = pbuf_to_mbuf(pbuf, TRUE)) != NULL) {
5ba3f43e 4769 ip_input(m);
0a7de745 4770 }
5ba3f43e 4771
0a7de745 4772 return PF_NAT64;
3e170ce0
A
4773}
4774
4775static int
5ba3f43e 4776pf_nat64_ipv4(pbuf_t *pbuf, int off, struct pf_pdesc *pd)
3e170ce0 4777{
0a7de745 4778 struct ip6_hdr *ip6;
5ba3f43e 4779 struct mbuf *m;
3e170ce0 4780
0a7de745
A
4781 if (pbuf->pb_ifp == NULL) {
4782 return PF_DROP;
4783 }
3e170ce0 4784
5ba3f43e 4785 ip6 = (struct ip6_hdr *)pbuf_resize_segment(pbuf, 0, off, sizeof(*ip6));
0a7de745
A
4786 if (ip6 == NULL) {
4787 return PF_DROP;
4788 }
3e170ce0 4789
3e170ce0
A
4790 ip6->ip6_vfc = htonl((6 << 28) | (pd->tos << 20));
4791 ip6->ip6_plen = htons(pd->tot_len - off);
4792 ip6->ip6_nxt = pd->proto;
4793 ip6->ip6_hlim = pd->ttl;
5ba3f43e
A
4794 ip6->ip6_src = pd->naddr.v6addr;
4795 ip6->ip6_dst = pd->ndaddr.v6addr;
3e170ce0
A
4796
4797 /* recalculate icmp6 checksums */
4798 if (pd->proto == IPPROTO_ICMPV6) {
3e170ce0 4799 struct icmp6_hdr *icmp6;
5ba3f43e 4800 int hlen = sizeof(*ip6);
3e170ce0 4801
5ba3f43e
A
4802 icmp6 = (struct icmp6_hdr *)pbuf_contig_segment(pbuf, hlen,
4803 sizeof(*icmp6));
0a7de745
A
4804 if (icmp6 == NULL) {
4805 return PF_DROP;
4806 }
3e170ce0 4807
3e170ce0 4808 icmp6->icmp6_cksum = 0;
5ba3f43e 4809 icmp6->icmp6_cksum = pbuf_inet6_cksum(pbuf,
0a7de745
A
4810 IPPROTO_ICMPV6, hlen,
4811 ntohs(ip6->ip6_plen));
39037602 4812 } else if (pd->proto == IPPROTO_UDP) {
39037602 4813 struct udphdr *uh;
5ba3f43e
A
4814 int hlen = sizeof(*ip6);
4815
4816 uh = (struct udphdr *)pbuf_contig_segment(pbuf, hlen,
4817 sizeof(*uh));
0a7de745
A
4818 if (uh == NULL) {
4819 return PF_DROP;
4820 }
5ba3f43e 4821
0a7de745 4822 if (uh->uh_sum == 0) {
5ba3f43e 4823 uh->uh_sum = pbuf_inet6_cksum(pbuf, IPPROTO_UDP,
0a7de745
A
4824 hlen, ntohs(ip6->ip6_plen));
4825 }
3e170ce0 4826 }
39037602 4827
0a7de745 4828 if ((m = pbuf_to_mbuf(pbuf, TRUE)) != NULL) {
5ba3f43e 4829 ip6_input(m);
0a7de745 4830 }
5ba3f43e 4831
0a7de745 4832 return PF_NAT64;
3e170ce0
A
4833}
4834
b0d623f7
A
4835static int
4836pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction,
5ba3f43e 4837 struct pfi_kif *kif, pbuf_t *pbuf, int off, void *h,
b0d623f7
A
4838 struct pf_pdesc *pd, struct pf_rule **am, struct pf_ruleset **rsm,
4839 struct ifqueue *ifq)
4840{
4841#pragma unused(h)
0a7de745
A
4842 struct pf_rule *nr = NULL;
4843 struct pf_addr *saddr = pd->src, *daddr = pd->dst;
4844 sa_family_t af = pd->af;
4845 struct pf_rule *r, *a = NULL;
4846 struct pf_ruleset *ruleset = NULL;
4847 struct pf_src_node *nsn = NULL;
4848 struct tcphdr *th = pd->hdr.tcp;
4849 struct udphdr *uh = pd->hdr.udp;
4850 u_short reason;
4851 int rewrite = 0, hdrlen = 0;
4852 int tag = -1;
4853 unsigned int rtableid = IFSCOPE_NONE;
4854 int asd = 0;
4855 int match = 0;
4856 int state_icmp = 0;
4857 u_int16_t mss = tcp_mssdflt;
4858 u_int8_t icmptype = 0, icmpcode = 0;
4859
4860 struct pf_grev1_hdr *grev1 = pd->hdr.grev1;
3e170ce0 4861 union pf_state_xport bxport, bdxport, nxport, sxport, dxport;
0a7de745 4862 struct pf_state_key psk;
b0d623f7 4863
5ba3f43e 4864 LCK_MTX_ASSERT(pf_lock, LCK_MTX_ASSERT_OWNED);
b0d623f7
A
4865
4866 if (direction == PF_IN && pf_check_congestion(ifq)) {
4867 REASON_SET(&reason, PFRES_CONGEST);
0a7de745 4868 return PF_DROP;
b0d623f7
A
4869 }
4870
b0d623f7
A
4871 hdrlen = 0;
4872 sxport.spi = 0;
4873 dxport.spi = 0;
4874 nxport.spi = 0;
b0d623f7
A
4875
4876 switch (pd->proto) {
4877 case IPPROTO_TCP:
b0d623f7
A
4878 sxport.port = th->th_sport;
4879 dxport.port = th->th_dport;
0a7de745 4880 hdrlen = sizeof(*th);
b0d623f7
A
4881 break;
4882 case IPPROTO_UDP:
3e170ce0
A
4883 sxport.port = uh->uh_sport;
4884 dxport.port = uh->uh_dport;
0a7de745 4885 hdrlen = sizeof(*uh);
b0d623f7
A
4886 break;
4887#if INET
4888 case IPPROTO_ICMP:
0a7de745 4889 if (pd->af != AF_INET) {
b0d623f7 4890 break;
0a7de745 4891 }
b0d623f7
A
4892 sxport.port = dxport.port = pd->hdr.icmp->icmp_id;
4893 hdrlen = ICMP_MINLEN;
b0d623f7
A
4894 icmptype = pd->hdr.icmp->icmp_type;
4895 icmpcode = pd->hdr.icmp->icmp_code;
4896
0a7de745 4897 if (ICMP_ERRORTYPE(icmptype)) {
b0d623f7 4898 state_icmp++;
0a7de745 4899 }
b0d623f7
A
4900 break;
4901#endif /* INET */
4902#if INET6
4903 case IPPROTO_ICMPV6:
0a7de745 4904 if (pd->af != AF_INET6) {
b0d623f7 4905 break;
0a7de745 4906 }
b0d623f7 4907 sxport.port = dxport.port = pd->hdr.icmp6->icmp6_id;
0a7de745 4908 hdrlen = sizeof(*pd->hdr.icmp6);
b0d623f7
A
4909 icmptype = pd->hdr.icmp6->icmp6_type;
4910 icmpcode = pd->hdr.icmp6->icmp6_code;
4911
0a7de745 4912 if (ICMP6_ERRORTYPE(icmptype)) {
b0d623f7 4913 state_icmp++;
0a7de745 4914 }
b0d623f7
A
4915 break;
4916#endif /* INET6 */
b0d623f7
A
4917 case IPPROTO_GRE:
4918 if (pd->proto_variant == PF_GRE_PPTP_VARIANT) {
4919 sxport.call_id = dxport.call_id =
4920 pd->hdr.grev1->call_id;
0a7de745 4921 hdrlen = sizeof(*pd->hdr.grev1);
b0d623f7
A
4922 }
4923 break;
4924 case IPPROTO_ESP:
4925 sxport.spi = 0;
4926 dxport.spi = pd->hdr.esp->spi;
0a7de745 4927 hdrlen = sizeof(*pd->hdr.esp);
b0d623f7 4928 break;
b0d623f7
A
4929 }
4930
4931 r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_FILTER].active.ptr);
4932
3e170ce0
A
4933 bxport = sxport;
4934 bdxport = dxport;
4935
0a7de745 4936 if (direction == PF_OUT) {
3e170ce0 4937 nxport = sxport;
0a7de745 4938 } else {
3e170ce0 4939 nxport = dxport;
0a7de745 4940 }
3e170ce0
A
4941
4942 /* check packet for BINAT/NAT/RDR */
5ba3f43e 4943 if ((nr = pf_get_translation_aux(pd, pbuf, off, direction, kif, &nsn,
0a7de745
A
4944 saddr, &sxport, daddr, &dxport, &nxport
4945 )) != NULL) {
3e170ce0
A
4946 int ua;
4947 u_int16_t dport;
4948
0a7de745 4949 if (pd->af != pd->naf) {
3e170ce0 4950 ua = 0;
0a7de745 4951 } else {
3e170ce0 4952 ua = 1;
0a7de745 4953 }
3e170ce0
A
4954
4955 PF_ACPY(&pd->baddr, saddr, af);
4956 PF_ACPY(&pd->bdaddr, daddr, af);
4957
4958 switch (pd->proto) {
4959 case IPPROTO_TCP:
4960 if (pd->af != pd->naf ||
4961 PF_ANEQ(saddr, &pd->naddr, pd->af)) {
b0d623f7 4962 pf_change_ap(direction, pd->mp, saddr,
0a7de745
A
4963 &th->th_sport, pd->ip_sum, &th->th_sum,
4964 &pd->naddr, nxport.port, 0, af,
4965 pd->naf, ua);
b0d623f7 4966 sxport.port = th->th_sport;
3e170ce0
A
4967 }
4968
4969 if (pd->af != pd->naf ||
4970 PF_ANEQ(daddr, &pd->ndaddr, pd->af) ||
4971 (nr && (nr->action == PF_RDR) &&
0a7de745
A
4972 (th->th_dport != nxport.port))) {
4973 if (nr && nr->action == PF_RDR) {
3e170ce0 4974 dport = nxport.port;
0a7de745 4975 } else {
3e170ce0 4976 dport = th->th_dport;
0a7de745 4977 }
3e170ce0 4978 pf_change_ap(direction, pd->mp, daddr,
0a7de745
A
4979 &th->th_dport, pd->ip_sum,
4980 &th->th_sum, &pd->ndaddr,
4981 dport, 0, af, pd->naf, ua);
3e170ce0
A
4982 dxport.port = th->th_dport;
4983 }
4984 rewrite++;
4985 break;
4986
4987 case IPPROTO_UDP:
4988 if (pd->af != pd->naf ||
4989 PF_ANEQ(saddr, &pd->naddr, pd->af)) {
b0d623f7 4990 pf_change_ap(direction, pd->mp, saddr,
0a7de745
A
4991 &uh->uh_sport, pd->ip_sum,
4992 &uh->uh_sum, &pd->naddr,
4993 nxport.port, 1, af, pd->naf, ua);
3e170ce0
A
4994 sxport.port = uh->uh_sport;
4995 }
4996
4997 if (pd->af != pd->naf ||
4998 PF_ANEQ(daddr, &pd->ndaddr, pd->af) ||
4999 (nr && (nr->action == PF_RDR) &&
0a7de745
A
5000 (uh->uh_dport != nxport.port))) {
5001 if (nr && nr->action == PF_RDR) {
3e170ce0 5002 dport = nxport.port;
0a7de745 5003 } else {
3e170ce0 5004 dport = uh->uh_dport;
0a7de745 5005 }
3e170ce0 5006 pf_change_ap(direction, pd->mp, daddr,
0a7de745
A
5007 &uh->uh_dport, pd->ip_sum,
5008 &uh->uh_sum, &pd->ndaddr,
5009 dport, 0, af, pd->naf, ua);
3e170ce0
A
5010 dxport.port = uh->uh_dport;
5011 }
5012 rewrite++;
5013 break;
b0d623f7 5014#if INET
3e170ce0 5015 case IPPROTO_ICMP:
0a7de745 5016 if (pd->af != AF_INET) {
b0d623f7 5017 break;
0a7de745 5018 }
3e170ce0
A
5019 /*
5020 * TODO:
5021 * pd->af != pd->naf not handled yet here and would be
5022 * needed for NAT46 needed to support XLAT.
5023 * Will cross the bridge when it comes.
5024 */
5025 if (PF_ANEQ(saddr, &pd->naddr, pd->af)) {
5ba3f43e 5026 pf_change_a(&saddr->v4addr.s_addr, pd->ip_sum,
0a7de745 5027 pd->naddr.v4addr.s_addr, 0);
3e170ce0 5028 pd->hdr.icmp->icmp_cksum = pf_cksum_fixup(
0a7de745
A
5029 pd->hdr.icmp->icmp_cksum, sxport.port,
5030 nxport.port, 0);
3e170ce0
A
5031 pd->hdr.icmp->icmp_id = nxport.port;
5032 }
5033
5034 if (PF_ANEQ(daddr, &pd->ndaddr, pd->af)) {
5ba3f43e 5035 pf_change_a(&daddr->v4addr.s_addr, pd->ip_sum,
0a7de745 5036 pd->ndaddr.v4addr.s_addr, 0);
3e170ce0
A
5037 }
5038 ++rewrite;
5039 break;
b0d623f7
A
5040#endif /* INET */
5041#if INET6
3e170ce0 5042 case IPPROTO_ICMPV6:
0a7de745 5043 if (pd->af != AF_INET6) {
b0d623f7 5044 break;
0a7de745 5045 }
3e170ce0
A
5046
5047 if (pd->af != pd->naf ||
5048 PF_ANEQ(saddr, &pd->naddr, pd->af)) {
5049 pf_change_addr(saddr,
0a7de745
A
5050 &pd->hdr.icmp6->icmp6_cksum,
5051 &pd->naddr, 0, pd->af, pd->naf);
b0d623f7
A
5052 }
5053
3e170ce0
A
5054 if (pd->af != pd->naf ||
5055 PF_ANEQ(daddr, &pd->ndaddr, pd->af)) {
5056 pf_change_addr(daddr,
0a7de745
A
5057 &pd->hdr.icmp6->icmp6_cksum,
5058 &pd->ndaddr, 0, pd->af, pd->naf);
3e170ce0
A
5059 }
5060
5061 if (pd->af != pd->naf) {
5062 if (pf_translate_icmp_af(AF_INET,
0a7de745
A
5063 pd->hdr.icmp6)) {
5064 return PF_DROP;
5065 }
3e170ce0
A
5066 pd->proto = IPPROTO_ICMP;
5067 }
5068 rewrite++;
5069 break;
5070#endif /* INET */
5071 case IPPROTO_GRE:
5072 if ((direction == PF_IN) &&
0a7de745
A
5073 (pd->proto_variant == PF_GRE_PPTP_VARIANT)) {
5074 grev1->call_id = nxport.call_id;
5075 }
3e170ce0
A
5076
5077 switch (pd->af) {
b0d623f7 5078#if INET
3e170ce0
A
5079 case AF_INET:
5080 if (PF_ANEQ(saddr, &pd->naddr, pd->af)) {
5ba3f43e 5081 pf_change_a(&saddr->v4addr.s_addr,
0a7de745
A
5082 pd->ip_sum,
5083 pd->naddr.v4addr.s_addr, 0);
3e170ce0
A
5084 }
5085 if (PF_ANEQ(daddr, &pd->ndaddr, pd->af)) {
5ba3f43e 5086 pf_change_a(&daddr->v4addr.s_addr,
0a7de745
A
5087 pd->ip_sum,
5088 pd->ndaddr.v4addr.s_addr, 0);
316670eb 5089 }
b0d623f7
A
5090 break;
5091#endif /* INET */
5092#if INET6
3e170ce0 5093 case AF_INET6:
0a7de745 5094 if (PF_ANEQ(saddr, &pd->naddr, pd->af)) {
3e170ce0 5095 PF_ACPY(saddr, &pd->naddr, AF_INET6);
0a7de745
A
5096 }
5097 if (PF_ANEQ(daddr, &pd->ndaddr, pd->af)) {
3e170ce0 5098 PF_ACPY(daddr, &pd->ndaddr, AF_INET6);
0a7de745 5099 }
b0d623f7
A
5100 break;
5101#endif /* INET6 */
3e170ce0
A
5102 }
5103 ++rewrite;
5104 break;
5105 case IPPROTO_ESP:
0a7de745 5106 if (direction == PF_OUT) {
3e170ce0 5107 bxport.spi = 0;
0a7de745 5108 }
b0d623f7 5109
3e170ce0 5110 switch (pd->af) {
b0d623f7 5111#if INET
3e170ce0
A
5112 case AF_INET:
5113 if (PF_ANEQ(saddr, &pd->naddr, pd->af)) {
5ba3f43e 5114 pf_change_a(&saddr->v4addr.s_addr,
0a7de745 5115 pd->ip_sum, pd->naddr.v4addr.s_addr, 0);
3e170ce0
A
5116 }
5117 if (PF_ANEQ(daddr, &pd->ndaddr, pd->af)) {
5ba3f43e 5118 pf_change_a(&daddr->v4addr.s_addr,
0a7de745
A
5119 pd->ip_sum,
5120 pd->ndaddr.v4addr.s_addr, 0);
b0d623f7 5121 }
b0d623f7 5122 break;
b0d623f7
A
5123#endif /* INET */
5124#if INET6
3e170ce0 5125 case AF_INET6:
0a7de745 5126 if (PF_ANEQ(saddr, &pd->naddr, pd->af)) {
3e170ce0 5127 PF_ACPY(saddr, &pd->naddr, AF_INET6);
0a7de745
A
5128 }
5129 if (PF_ANEQ(daddr, &pd->ndaddr, pd->af)) {
3e170ce0 5130 PF_ACPY(daddr, &pd->ndaddr, AF_INET6);
0a7de745 5131 }
3e170ce0 5132 break;
b0d623f7 5133#endif /* INET6 */
3e170ce0
A
5134 }
5135 break;
5136 default:
5137 switch (pd->af) {
5138#if INET
5139 case AF_INET:
5140 if ((pd->naf != AF_INET) ||
5141 (PF_ANEQ(saddr, &pd->naddr, pd->af))) {
5142 pf_change_addr(saddr, pd->ip_sum,
0a7de745 5143 &pd->naddr, 0, af, pd->naf);
3e170ce0
A
5144 }
5145
5146 if ((pd->naf != AF_INET) ||
5147 (PF_ANEQ(daddr, &pd->ndaddr, pd->af))) {
5148 pf_change_addr(daddr, pd->ip_sum,
0a7de745 5149 &pd->ndaddr, 0, af, pd->naf);
b0d623f7
A
5150 }
5151 break;
b0d623f7
A
5152#endif /* INET */
5153#if INET6
3e170ce0 5154 case AF_INET6:
0a7de745 5155 if (PF_ANEQ(saddr, &pd->naddr, pd->af)) {
3e170ce0 5156 PF_ACPY(saddr, &pd->naddr, af);
0a7de745
A
5157 }
5158 if (PF_ANEQ(daddr, &pd->ndaddr, pd->af)) {
3e170ce0 5159 PF_ACPY(daddr, &pd->ndaddr, af);
0a7de745 5160 }
b0d623f7 5161 break;
3e170ce0 5162#endif /* INET */
b0d623f7 5163 }
3e170ce0 5164 break;
b0d623f7 5165 }
3e170ce0 5166
0a7de745 5167 if (nr->natpass) {
3e170ce0 5168 r = NULL;
0a7de745 5169 }
3e170ce0
A
5170 pd->nat_rule = nr;
5171 pd->af = pd->naf;
5ba3f43e 5172 } else {
b0d623f7
A
5173 }
5174
0a7de745 5175 if (nr && nr->tag > 0) {
b0d623f7 5176 tag = nr->tag;
0a7de745 5177 }
b0d623f7
A
5178
5179 while (r != NULL) {
5180 r->evaluations++;
0a7de745 5181 if (pfi_kif_match(r->kif, kif) == r->ifnot) {
b0d623f7 5182 r = r->skip[PF_SKIP_IFP].ptr;
0a7de745 5183 } else if (r->direction && r->direction != direction) {
b0d623f7 5184 r = r->skip[PF_SKIP_DIR].ptr;
0a7de745 5185 } else if (r->af && r->af != pd->af) {
b0d623f7 5186 r = r->skip[PF_SKIP_AF].ptr;
0a7de745 5187 } else if (r->proto && r->proto != pd->proto) {
b0d623f7 5188 r = r->skip[PF_SKIP_PROTO].ptr;
0a7de745
A
5189 } else if (PF_MISMATCHAW(&r->src.addr, saddr, pd->af,
5190 r->src.neg, kif)) {
b0d623f7 5191 r = r->skip[PF_SKIP_SRC_ADDR].ptr;
0a7de745 5192 }
b0d623f7 5193 /* tcp/udp only. port_op always 0 in other cases */
b0d623f7
A
5194 else if (r->proto == pd->proto &&
5195 (r->proto == IPPROTO_TCP || r->proto == IPPROTO_UDP) &&
5196 r->src.xport.range.op &&
5197 !pf_match_port(r->src.xport.range.op,
5198 r->src.xport.range.port[0], r->src.xport.range.port[1],
0a7de745 5199 th->th_sport)) {
b0d623f7 5200 r = r->skip[PF_SKIP_SRC_PORT].ptr;
0a7de745
A
5201 } else if (PF_MISMATCHAW(&r->dst.addr, daddr, pd->af,
5202 r->dst.neg, NULL)) {
b0d623f7 5203 r = r->skip[PF_SKIP_DST_ADDR].ptr;
0a7de745 5204 }
b0d623f7 5205 /* tcp/udp only. port_op always 0 in other cases */
b0d623f7
A
5206 else if (r->proto == pd->proto &&
5207 (r->proto == IPPROTO_TCP || r->proto == IPPROTO_UDP) &&
5208 r->dst.xport.range.op &&
5209 !pf_match_port(r->dst.xport.range.op,
5210 r->dst.xport.range.port[0], r->dst.xport.range.port[1],
0a7de745 5211 th->th_dport)) {
b0d623f7 5212 r = r->skip[PF_SKIP_DST_PORT].ptr;
0a7de745 5213 }
b0d623f7 5214 /* icmp only. type always 0 in other cases */
0a7de745 5215 else if (r->type && r->type != icmptype + 1) {
b0d623f7 5216 r = TAILQ_NEXT(r, entries);
0a7de745 5217 }
b0d623f7 5218 /* icmp only. type always 0 in other cases */
0a7de745 5219 else if (r->code && r->code != icmpcode + 1) {
b0d623f7 5220 r = TAILQ_NEXT(r, entries);
0a7de745
A
5221 } else if ((r->rule_flag & PFRULE_TOS) && r->tos &&
5222 !(r->tos & pd->tos)) {
316670eb 5223 r = TAILQ_NEXT(r, entries);
0a7de745
A
5224 } else if ((r->rule_flag & PFRULE_DSCP) && r->tos &&
5225 !(r->tos & (pd->tos & DSCP_MASK))) {
316670eb 5226 r = TAILQ_NEXT(r, entries);
0a7de745
A
5227 } else if ((r->rule_flag & PFRULE_SC) && r->tos &&
5228 ((r->tos & SCIDX_MASK) != pd->sc)) {
b0d623f7 5229 r = TAILQ_NEXT(r, entries);
0a7de745 5230 } else if (r->rule_flag & PFRULE_FRAGMENT) {
b0d623f7 5231 r = TAILQ_NEXT(r, entries);
0a7de745
A
5232 } else if (pd->proto == IPPROTO_TCP &&
5233 (r->flagset & th->th_flags) != r->flags) {
b0d623f7 5234 r = TAILQ_NEXT(r, entries);
0a7de745 5235 }
b0d623f7 5236 /* tcp/udp only. uid.op always 0 in other cases */
39037602
A
5237 else if (r->uid.op && (pd->lookup.done || ((void)(pd->lookup.done =
5238 pf_socket_lookup(direction, pd)), 1)) &&
b0d623f7 5239 !pf_match_uid(r->uid.op, r->uid.uid[0], r->uid.uid[1],
0a7de745 5240 pd->lookup.uid)) {
b0d623f7 5241 r = TAILQ_NEXT(r, entries);
0a7de745 5242 }
b0d623f7 5243 /* tcp/udp only. gid.op always 0 in other cases */
39037602
A
5244 else if (r->gid.op && (pd->lookup.done || ((void)(pd->lookup.done =
5245 pf_socket_lookup(direction, pd)), 1)) &&
b0d623f7 5246 !pf_match_gid(r->gid.op, r->gid.gid[0], r->gid.gid[1],
0a7de745 5247 pd->lookup.gid)) {
b0d623f7 5248 r = TAILQ_NEXT(r, entries);
0a7de745 5249 } else if (r->prob && r->prob <= (RandomULong() % (UINT_MAX - 1) + 1)) {
b0d623f7 5250 r = TAILQ_NEXT(r, entries);
0a7de745 5251 } else if (r->match_tag && !pf_match_tag(r, pd->pf_mtag, &tag)) {
b0d623f7 5252 r = TAILQ_NEXT(r, entries);
0a7de745 5253 } else if (r->os_fingerprint != PF_OSFP_ANY &&
b0d623f7 5254 (pd->proto != IPPROTO_TCP || !pf_osfp_match(
0a7de745
A
5255 pf_osfp_fingerprint(pd, pbuf, off, th),
5256 r->os_fingerprint))) {
b0d623f7 5257 r = TAILQ_NEXT(r, entries);
0a7de745
A
5258 } else {
5259 if (r->tag) {
b0d623f7 5260 tag = r->tag;
0a7de745
A
5261 }
5262 if (PF_RTABLEID_IS_VALID(r->rtableid)) {
b0d623f7 5263 rtableid = r->rtableid;
0a7de745 5264 }
b0d623f7
A
5265 if (r->anchor == NULL) {
5266 match = 1;
5267 *rm = r;
5268 *am = a;
5269 *rsm = ruleset;
0a7de745 5270 if ((*rm)->quick) {
b0d623f7 5271 break;
0a7de745 5272 }
b0d623f7 5273 r = TAILQ_NEXT(r, entries);
0a7de745 5274 } else {
b0d623f7
A
5275 pf_step_into_anchor(&asd, &ruleset,
5276 PF_RULESET_FILTER, &r, &a, &match);
0a7de745 5277 }
b0d623f7
A
5278 }
5279 if (r == NULL && pf_step_out_of_anchor(&asd, &ruleset,
0a7de745 5280 PF_RULESET_FILTER, &r, &a, &match)) {
b0d623f7 5281 break;
0a7de745 5282 }
b0d623f7
A
5283 }
5284 r = *rm;
5285 a = *am;
5286 ruleset = *rsm;
5287
5288 REASON_SET(&reason, PFRES_MATCH);
5289
5290 if (r->log || (nr != NULL && nr->log)) {
b0d623f7 5291 if (rewrite > 0) {
0a7de745 5292 if (rewrite < off + hdrlen) {
b0d623f7 5293 rewrite = off + hdrlen;
0a7de745 5294 }
b0d623f7 5295
5ba3f43e 5296 if (pf_lazy_makewritable(pd, pbuf, rewrite) == NULL) {
b0d623f7 5297 REASON_SET(&reason, PFRES_MEMORY);
0a7de745 5298 return PF_DROP;
b0d623f7
A
5299 }
5300
5ba3f43e 5301 pbuf_copy_back(pbuf, off, hdrlen, pd->hdr.any);
b0d623f7 5302 }
5ba3f43e 5303 PFLOG_PACKET(kif, h, pbuf, pd->af, direction, reason,
0a7de745 5304 r->log ? r : nr, a, ruleset, pd);
b0d623f7
A
5305 }
5306
5307 if ((r->action == PF_DROP) &&
5308 ((r->rule_flag & PFRULE_RETURNRST) ||
5309 (r->rule_flag & PFRULE_RETURNICMP) ||
5310 (r->rule_flag & PFRULE_RETURN))) {
5311 /* undo NAT changes, if they have taken place */
3e170ce0
A
5312 /* XXX For NAT64 we are not reverting the changes */
5313 if (nr != NULL && nr->action != PF_NAT64) {
b0d623f7 5314 if (direction == PF_OUT) {
3e170ce0 5315 pd->af = af;
b0d623f7
A
5316 switch (pd->proto) {
5317 case IPPROTO_TCP:
b0d623f7
A
5318 pf_change_ap(direction, pd->mp, saddr,
5319 &th->th_sport, pd->ip_sum,
5320 &th->th_sum, &pd->baddr,
3e170ce0 5321 bxport.port, 0, af, pd->af, 1);
b0d623f7 5322 sxport.port = th->th_sport;
b0d623f7
A
5323 rewrite++;
5324 break;
5325 case IPPROTO_UDP:
b0d623f7
A
5326 pf_change_ap(direction, pd->mp, saddr,
5327 &pd->hdr.udp->uh_sport, pd->ip_sum,
5328 &pd->hdr.udp->uh_sum, &pd->baddr,
3e170ce0 5329 bxport.port, 1, af, pd->af, 1);
b0d623f7 5330 sxport.port = pd->hdr.udp->uh_sport;
b0d623f7
A
5331 rewrite++;
5332 break;
5333 case IPPROTO_ICMP:
5334#if INET6
5335 case IPPROTO_ICMPV6:
5336#endif
5337 /* nothing! */
5338 break;
b0d623f7
A
5339 case IPPROTO_GRE:
5340 PF_ACPY(&pd->baddr, saddr, af);
5341 ++rewrite;
5342 switch (af) {
5343#if INET
5344 case AF_INET:
5ba3f43e 5345 pf_change_a(&saddr->v4addr.s_addr,
b0d623f7 5346 pd->ip_sum,
5ba3f43e 5347 pd->baddr.v4addr.s_addr, 0);
b0d623f7
A
5348 break;
5349#endif /* INET */
5350#if INET6
5351 case AF_INET6:
5352 PF_ACPY(saddr, &pd->baddr,
5353 AF_INET6);
5354 break;
5355#endif /* INET6 */
5356 }
5357 break;
5358 case IPPROTO_ESP:
5359 PF_ACPY(&pd->baddr, saddr, af);
5360 switch (af) {
5361#if INET
5362 case AF_INET:
5ba3f43e 5363 pf_change_a(&saddr->v4addr.s_addr,
b0d623f7 5364 pd->ip_sum,
5ba3f43e 5365 pd->baddr.v4addr.s_addr, 0);
b0d623f7
A
5366 break;
5367#endif /* INET */
5368#if INET6
5369 case AF_INET6:
5370 PF_ACPY(saddr, &pd->baddr,
5371 AF_INET6);
5372 break;
5373#endif /* INET6 */
5374 }
5375 break;
b0d623f7
A
5376 default:
5377 switch (af) {
5378 case AF_INET:
5ba3f43e 5379 pf_change_a(&saddr->v4addr.s_addr,
b0d623f7 5380 pd->ip_sum,
5ba3f43e 5381 pd->baddr.v4addr.s_addr, 0);
b0d623f7
A
5382 break;
5383 case AF_INET6:
5384 PF_ACPY(saddr, &pd->baddr, af);
5385 break;
5386 }
5387 }
5388 } else {
5389 switch (pd->proto) {
5390 case IPPROTO_TCP:
b0d623f7
A
5391 pf_change_ap(direction, pd->mp, daddr,
5392 &th->th_dport, pd->ip_sum,
3e170ce0
A
5393 &th->th_sum, &pd->bdaddr,
5394 bdxport.port, 0, af, pd->af, 1);
b0d623f7 5395 dxport.port = th->th_dport;
b0d623f7
A
5396 rewrite++;
5397 break;
5398 case IPPROTO_UDP:
b0d623f7
A
5399 pf_change_ap(direction, pd->mp, daddr,
5400 &pd->hdr.udp->uh_dport, pd->ip_sum,
3e170ce0
A
5401 &pd->hdr.udp->uh_sum, &pd->bdaddr,
5402 bdxport.port, 1, af, pd->af, 1);
b0d623f7 5403 dxport.port = pd->hdr.udp->uh_dport;
b0d623f7
A
5404 rewrite++;
5405 break;
5406 case IPPROTO_ICMP:
5407#if INET6
5408 case IPPROTO_ICMPV6:
5409#endif
5410 /* nothing! */
5411 break;
b0d623f7
A
5412 case IPPROTO_GRE:
5413 if (pd->proto_variant ==
0a7de745 5414 PF_GRE_PPTP_VARIANT) {
3e170ce0 5415 grev1->call_id =
0a7de745
A
5416 bdxport.call_id;
5417 }
b0d623f7
A
5418 ++rewrite;
5419 switch (af) {
5420#if INET
5421 case AF_INET:
5ba3f43e 5422 pf_change_a(&daddr->v4addr.s_addr,
b0d623f7 5423 pd->ip_sum,
5ba3f43e 5424 pd->bdaddr.v4addr.s_addr, 0);
b0d623f7
A
5425 break;
5426#endif /* INET */
5427#if INET6
5428 case AF_INET6:
3e170ce0 5429 PF_ACPY(daddr, &pd->bdaddr,
b0d623f7
A
5430 AF_INET6);
5431 break;
5432#endif /* INET6 */
5433 }
5434 break;
5435 case IPPROTO_ESP:
5436 switch (af) {
5437#if INET
5438 case AF_INET:
5ba3f43e 5439 pf_change_a(&daddr->v4addr.s_addr,
b0d623f7 5440 pd->ip_sum,
5ba3f43e 5441 pd->bdaddr.v4addr.s_addr, 0);
b0d623f7
A
5442 break;
5443#endif /* INET */
5444#if INET6
5445 case AF_INET6:
3e170ce0 5446 PF_ACPY(daddr, &pd->bdaddr,
b0d623f7
A
5447 AF_INET6);
5448 break;
5449#endif /* INET6 */
5450 }
5451 break;
b0d623f7
A
5452 default:
5453 switch (af) {
5454 case AF_INET:
5ba3f43e 5455 pf_change_a(&daddr->v4addr.s_addr,
b0d623f7 5456 pd->ip_sum,
5ba3f43e 5457 pd->bdaddr.v4addr.s_addr, 0);
b0d623f7
A
5458 break;
5459#if INET6
5460 case AF_INET6:
3e170ce0 5461 PF_ACPY(daddr, &pd->bdaddr, af);
b0d623f7
A
5462 break;
5463#endif /* INET6 */
5464 }
5465 }
5466 }
5467 }
5468 if (pd->proto == IPPROTO_TCP &&
5469 ((r->rule_flag & PFRULE_RETURNRST) ||
5470 (r->rule_flag & PFRULE_RETURN)) &&
5471 !(th->th_flags & TH_RST)) {
0a7de745
A
5472 u_int32_t ack = ntohl(th->th_seq) + pd->p_len;
5473 int len = 0;
5474 struct ip *h4;
b0d623f7 5475#if INET6
0a7de745 5476 struct ip6_hdr *h6;
b0d623f7
A
5477#endif /* INET6 */
5478
3e170ce0 5479 switch (pd->af) {
b0d623f7 5480 case AF_INET:
5ba3f43e 5481 h4 = pbuf->pb_data;
b0d623f7
A
5482 len = ntohs(h4->ip_len) - off;
5483 break;
5484#if INET6
5485 case AF_INET6:
5ba3f43e 5486 h6 = pbuf->pb_data;
b0d623f7 5487 len = ntohs(h6->ip6_plen) -
0a7de745 5488 (off - sizeof(*h6));
b0d623f7
A
5489 break;
5490#endif /* INET6 */
5491 }
5492
5ba3f43e 5493 if (pf_check_proto_cksum(pbuf, off, len, IPPROTO_TCP,
0a7de745 5494 pd->af)) {
b0d623f7 5495 REASON_SET(&reason, PFRES_PROTCKSUM);
0a7de745
A
5496 } else {
5497 if (th->th_flags & TH_SYN) {
b0d623f7 5498 ack++;
0a7de745
A
5499 }
5500 if (th->th_flags & TH_FIN) {
b0d623f7 5501 ack++;
0a7de745 5502 }
3e170ce0 5503 pf_send_tcp(r, pd->af, pd->dst,
b0d623f7 5504 pd->src, th->th_dport, th->th_sport,
0a7de745 5505 ntohl(th->th_ack), ack, TH_RST | TH_ACK, 0, 0,
b0d623f7
A
5506 r->return_ttl, 1, 0, pd->eh, kif->pfik_ifp);
5507 }
3e170ce0 5508 } else if (pd->proto != IPPROTO_ICMP && pd->af == AF_INET &&
b0d623f7 5509 pd->proto != IPPROTO_ESP && pd->proto != IPPROTO_AH &&
0a7de745 5510 r->return_icmp) {
5ba3f43e 5511 pf_send_icmp(pbuf, r->return_icmp >> 8,
3e170ce0 5512 r->return_icmp & 255, pd->af, r);
0a7de745 5513 } else if (pd->proto != IPPROTO_ICMPV6 && af == AF_INET6 &&
b0d623f7 5514 pd->proto != IPPROTO_ESP && pd->proto != IPPROTO_AH &&
0a7de745 5515 r->return_icmp6) {
5ba3f43e 5516 pf_send_icmp(pbuf, r->return_icmp6 >> 8,
3e170ce0 5517 r->return_icmp6 & 255, pd->af, r);
0a7de745 5518 }
b0d623f7
A
5519 }
5520
5ba3f43e 5521 if (r->action == PF_DROP) {
0a7de745 5522 return PF_DROP;
5ba3f43e 5523 }
b0d623f7 5524
316670eb 5525 /* prepare state key, for flowhash and/or the state (if created) */
0a7de745 5526 bzero(&psk, sizeof(psk));
316670eb
A
5527 psk.proto = pd->proto;
5528 psk.direction = direction;
316670eb
A
5529 if (pd->proto == IPPROTO_UDP) {
5530 if (ntohs(pd->hdr.udp->uh_sport) == PF_IKE_PORT &&
5531 ntohs(pd->hdr.udp->uh_dport) == PF_IKE_PORT) {
5532 psk.proto_variant = PF_EXTFILTER_APD;
5533 } else {
5534 psk.proto_variant = nr ? nr->extfilter : r->extfilter;
0a7de745 5535 if (psk.proto_variant < PF_EXTFILTER_APD) {
316670eb 5536 psk.proto_variant = PF_EXTFILTER_APD;
0a7de745 5537 }
316670eb
A
5538 }
5539 } else if (pd->proto == IPPROTO_GRE) {
5540 psk.proto_variant = pd->proto_variant;
5541 }
5542 if (direction == PF_OUT) {
3e170ce0 5543 psk.af_gwy = af;
316670eb 5544 PF_ACPY(&psk.gwy.addr, saddr, af);
3e170ce0 5545 PF_ACPY(&psk.ext_gwy.addr, daddr, af);
316670eb 5546 switch (pd->proto) {
316670eb
A
5547 case IPPROTO_ESP:
5548 psk.gwy.xport.spi = 0;
3e170ce0 5549 psk.ext_gwy.xport.spi = pd->hdr.esp->spi;
316670eb
A
5550 break;
5551 case IPPROTO_ICMP:
5552#if INET6
5553 case IPPROTO_ICMPV6:
5554#endif
3e170ce0
A
5555 /*
5556 * NAT64 requires protocol translation between ICMPv4
5557 * and ICMPv6. TCP and UDP do not require protocol
5558 * translation. To avoid adding complexity just to
5ba3f43e 5559 * handle ICMP(v4addr/v6addr), we always lookup for
3e170ce0
A
5560 * proto = IPPROTO_ICMP on both LAN and WAN side
5561 */
5562 psk.proto = IPPROTO_ICMP;
316670eb 5563 psk.gwy.xport.port = nxport.port;
3e170ce0 5564 psk.ext_gwy.xport.spi = 0;
316670eb
A
5565 break;
5566 default:
5567 psk.gwy.xport = sxport;
3e170ce0 5568 psk.ext_gwy.xport = dxport;
316670eb
A
5569 break;
5570 }
3e170ce0 5571 psk.af_lan = af;
316670eb
A
5572 if (nr != NULL) {
5573 PF_ACPY(&psk.lan.addr, &pd->baddr, af);
5574 psk.lan.xport = bxport;
3e170ce0
A
5575 PF_ACPY(&psk.ext_lan.addr, &pd->bdaddr, af);
5576 psk.ext_lan.xport = bdxport;
316670eb
A
5577 } else {
5578 PF_ACPY(&psk.lan.addr, &psk.gwy.addr, af);
5579 psk.lan.xport = psk.gwy.xport;
3e170ce0
A
5580 PF_ACPY(&psk.ext_lan.addr, &psk.ext_gwy.addr, af);
5581 psk.ext_lan.xport = psk.ext_gwy.xport;
316670eb
A
5582 }
5583 } else {
3e170ce0
A
5584 psk.af_lan = af;
5585 if (nr && nr->action == PF_NAT64) {
5586 PF_ACPY(&psk.lan.addr, &pd->baddr, af);
5587 PF_ACPY(&psk.ext_lan.addr, &pd->bdaddr, af);
5588 } else {
5589 PF_ACPY(&psk.lan.addr, daddr, af);
5590 PF_ACPY(&psk.ext_lan.addr, saddr, af);
5591 }
316670eb
A
5592 switch (pd->proto) {
5593 case IPPROTO_ICMP:
5594#if INET6
5595 case IPPROTO_ICMPV6:
5596#endif
3e170ce0
A
5597 /*
5598 * NAT64 requires protocol translation between ICMPv4
5599 * and ICMPv6. TCP and UDP do not require protocol
5600 * translation. To avoid adding complexity just to
5ba3f43e 5601 * handle ICMP(v4addr/v6addr), we always lookup for
3e170ce0
A
5602 * proto = IPPROTO_ICMP on both LAN and WAN side
5603 */
5604 psk.proto = IPPROTO_ICMP;
5605 if (nr && nr->action == PF_NAT64) {
5606 psk.lan.xport = bxport;
5607 psk.ext_lan.xport = bxport;
5608 } else {
5609 psk.lan.xport = nxport;
5610 psk.ext_lan.xport.spi = 0;
5611 }
316670eb
A
5612 break;
5613 case IPPROTO_ESP:
3e170ce0 5614 psk.ext_lan.xport.spi = 0;
316670eb
A
5615 psk.lan.xport.spi = pd->hdr.esp->spi;
5616 break;
5617 default:
3e170ce0
A
5618 if (nr != NULL) {
5619 if (nr->action == PF_NAT64) {
5620 psk.lan.xport = bxport;
5621 psk.ext_lan.xport = bdxport;
5622 } else {
5623 psk.lan.xport = dxport;
5624 psk.ext_lan.xport = sxport;
5625 }
5626 } else {
5627 psk.lan.xport = dxport;
5628 psk.ext_lan.xport = sxport;
5629 }
316670eb
A
5630 break;
5631 }
3e170ce0 5632 psk.af_gwy = pd->naf;
316670eb 5633 if (nr != NULL) {
3e170ce0
A
5634 if (nr->action == PF_NAT64) {
5635 PF_ACPY(&psk.gwy.addr, &pd->naddr, pd->naf);
5636 PF_ACPY(&psk.ext_gwy.addr, &pd->ndaddr,
0a7de745 5637 pd->naf);
3e170ce0
A
5638 if ((pd->proto == IPPROTO_ICMPV6) ||
5639 (pd->proto == IPPROTO_ICMP)) {
5640 psk.gwy.xport = nxport;
5641 psk.ext_gwy.xport = nxport;
5642 } else {
5643 psk.gwy.xport = sxport;
5644 psk.ext_gwy.xport = dxport;
5645 }
5646 } else {
5647 PF_ACPY(&psk.gwy.addr, &pd->bdaddr, af);
5648 psk.gwy.xport = bdxport;
5649 PF_ACPY(&psk.ext_gwy.addr, saddr, af);
5650 psk.ext_gwy.xport = sxport;
5651 }
316670eb
A
5652 } else {
5653 PF_ACPY(&psk.gwy.addr, &psk.lan.addr, af);
5654 psk.gwy.xport = psk.lan.xport;
3e170ce0
A
5655 PF_ACPY(&psk.ext_gwy.addr, &psk.ext_lan.addr, af);
5656 psk.ext_gwy.xport = psk.ext_lan.xport;
316670eb
A
5657 }
5658 }
39236c6e
A
5659 if (pd->pktflags & PKTF_FLOW_ID) {
5660 /* flow hash was already computed outside of PF */
5661 psk.flowsrc = pd->flowsrc;
316670eb
A
5662 psk.flowhash = pd->flowhash;
5663 } else {
39236c6e
A
5664 /* compute flow hash and store it in state key */
5665 psk.flowsrc = FLOWSRC_PF;
316670eb 5666 psk.flowhash = pf_calc_state_key_flowhash(&psk);
39236c6e 5667 pd->flowsrc = psk.flowsrc;
316670eb 5668 pd->flowhash = psk.flowhash;
39236c6e
A
5669 pd->pktflags |= PKTF_FLOW_ID;
5670 pd->pktflags &= ~PKTF_FLOW_ADV;
316670eb
A
5671 }
5672
5ba3f43e 5673 if (pf_tag_packet(pbuf, pd->pf_mtag, tag, rtableid, pd)) {
b0d623f7 5674 REASON_SET(&reason, PFRES_MEMORY);
0a7de745 5675 return PF_DROP;
b0d623f7
A
5676 }
5677
5678 if (!state_icmp && (r->keep_state || nr != NULL ||
5679 (pd->flags & PFDESC_TCP_NORM))) {
5680 /* create new state */
0a7de745 5681 struct pf_state *s = NULL;
b0d623f7
A
5682 struct pf_state_key *sk = NULL;
5683 struct pf_src_node *sn = NULL;
b0d623f7
A
5684 struct pf_ike_hdr ike;
5685
5686 if (pd->proto == IPPROTO_UDP) {
5ba3f43e 5687 size_t plen = pbuf->pb_packet_len - off - sizeof(*uh);
b0d623f7 5688
b7266188
A
5689 if (ntohs(uh->uh_sport) == PF_IKE_PORT &&
5690 ntohs(uh->uh_dport) == PF_IKE_PORT &&
b0d623f7 5691 plen >= PF_IKE_PACKET_MINSIZE) {
0a7de745 5692 if (plen > PF_IKE_PACKET_MINSIZE) {
b0d623f7 5693 plen = PF_IKE_PACKET_MINSIZE;
0a7de745
A
5694 }
5695 pbuf_copy_data(pbuf, off + sizeof(*uh), plen,
5ba3f43e 5696 &ike);
b0d623f7
A
5697 }
5698 }
5699
5700 if (nr != NULL && pd->proto == IPPROTO_ESP &&
5701 direction == PF_OUT) {
0a7de745 5702 struct pf_state_key_cmp sk0;
b0d623f7
A
5703 struct pf_state *s0;
5704
5705 /*
5706 * <jhw@apple.com>
5707 * This squelches state creation if the external
5708 * address matches an existing incomplete state with a
5709 * different internal address. Only one 'blocking'
5710 * partial state is allowed for each external address.
5711 */
0a7de745 5712 memset(&sk0, 0, sizeof(sk0));
3e170ce0 5713 sk0.af_gwy = pd->af;
b0d623f7 5714 sk0.proto = IPPROTO_ESP;
3e170ce0
A
5715 PF_ACPY(&sk0.gwy.addr, saddr, sk0.af_gwy);
5716 PF_ACPY(&sk0.ext_gwy.addr, daddr, sk0.af_gwy);
b0d623f7
A
5717 s0 = pf_find_state(kif, &sk0, PF_IN);
5718
5719 if (s0 && PF_ANEQ(&s0->state_key->lan.addr,
5720 pd->src, pd->af)) {
5721 nsn = 0;
5722 goto cleanup;
5723 }
5724 }
b0d623f7
A
5725
5726 /* check maximums */
5727 if (r->max_states && (r->states >= r->max_states)) {
5728 pf_status.lcounters[LCNT_STATES]++;
5729 REASON_SET(&reason, PFRES_MAXSTATES);
5730 goto cleanup;
5731 }
5732 /* src node for filter rule */
5733 if ((r->rule_flag & PFRULE_SRCTRACK ||
5734 r->rpool.opts & PF_POOL_STICKYADDR) &&
5735 pf_insert_src_node(&sn, r, saddr, af) != 0) {
5736 REASON_SET(&reason, PFRES_SRCLIMIT);
5737 goto cleanup;
5738 }
5739 /* src node for translation rule */
5740 if (nr != NULL && (nr->rpool.opts & PF_POOL_STICKYADDR) &&
5741 ((direction == PF_OUT &&
b0d623f7 5742 nr->action != PF_RDR &&
b0d623f7
A
5743 pf_insert_src_node(&nsn, nr, &pd->baddr, af) != 0) ||
5744 (pf_insert_src_node(&nsn, nr, saddr, af) != 0))) {
5745 REASON_SET(&reason, PFRES_SRCLIMIT);
5746 goto cleanup;
5747 }
5748 s = pool_get(&pf_state_pl, PR_WAITOK);
5749 if (s == NULL) {
5750 REASON_SET(&reason, PFRES_MEMORY);
5751cleanup:
5752 if (sn != NULL && sn->states == 0 && sn->expire == 0) {
5753 RB_REMOVE(pf_src_tree, &tree_src_tracking, sn);
5754 pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
5755 pf_status.src_nodes--;
5756 pool_put(&pf_src_tree_pl, sn);
5757 }
5758 if (nsn != sn && nsn != NULL && nsn->states == 0 &&
5759 nsn->expire == 0) {
5760 RB_REMOVE(pf_src_tree, &tree_src_tracking, nsn);
5761 pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
5762 pf_status.src_nodes--;
5763 pool_put(&pf_src_tree_pl, nsn);
5764 }
5765 if (sk != NULL) {
0a7de745 5766 if (sk->app_state) {
b0d623f7
A
5767 pool_put(&pf_app_state_pl,
5768 sk->app_state);
0a7de745 5769 }
b0d623f7
A
5770 pool_put(&pf_state_key_pl, sk);
5771 }
0a7de745 5772 return PF_DROP;
b0d623f7 5773 }
0a7de745 5774 bzero(s, sizeof(*s));
b0d623f7 5775 TAILQ_INIT(&s->unlink_hooks);
b0d623f7
A
5776 s->rule.ptr = r;
5777 s->nat_rule.ptr = nr;
d1ecb069 5778 s->anchor.ptr = a;
b0d623f7
A
5779 STATE_INC_COUNTERS(s);
5780 s->allow_opts = r->allow_opts;
5781 s->log = r->log & PF_LOG_ALL;
0a7de745 5782 if (nr != NULL) {
b0d623f7 5783 s->log |= nr->log & PF_LOG_ALL;
0a7de745 5784 }
b0d623f7
A
5785 switch (pd->proto) {
5786 case IPPROTO_TCP:
5787 s->src.seqlo = ntohl(th->th_seq);
5788 s->src.seqhi = s->src.seqlo + pd->p_len + 1;
0a7de745 5789 if ((th->th_flags & (TH_SYN | TH_ACK)) ==
b0d623f7
A
5790 TH_SYN && r->keep_state == PF_STATE_MODULATE) {
5791 /* Generate sequence number modulator */
5792 if ((s->src.seqdiff = pf_tcp_iss(pd) -
0a7de745 5793 s->src.seqlo) == 0) {
b0d623f7 5794 s->src.seqdiff = 1;
0a7de745 5795 }
b0d623f7
A
5796 pf_change_a(&th->th_seq, &th->th_sum,
5797 htonl(s->src.seqlo + s->src.seqdiff), 0);
0a7de745
A
5798 rewrite = off + sizeof(*th);
5799 } else {
b0d623f7 5800 s->src.seqdiff = 0;
0a7de745 5801 }
b0d623f7
A
5802 if (th->th_flags & TH_SYN) {
5803 s->src.seqhi++;
5ba3f43e 5804 s->src.wscale = pf_get_wscale(pbuf, off,
b0d623f7
A
5805 th->th_off, af);
5806 }
5807 s->src.max_win = MAX(ntohs(th->th_win), 1);
5808 if (s->src.wscale & PF_WSCALE_MASK) {
5809 /* Remove scale factor from initial window */
5810 int win = s->src.max_win;
5811 win += 1 << (s->src.wscale & PF_WSCALE_MASK);
5812 s->src.max_win = (win - 1) >>
5813 (s->src.wscale & PF_WSCALE_MASK);
5814 }
0a7de745 5815 if (th->th_flags & TH_FIN) {
b0d623f7 5816 s->src.seqhi++;
0a7de745 5817 }
b0d623f7
A
5818 s->dst.seqhi = 1;
5819 s->dst.max_win = 1;
5820 s->src.state = TCPS_SYN_SENT;
5821 s->dst.state = TCPS_CLOSED;
5822 s->timeout = PFTM_TCP_FIRST_PACKET;
5823 break;
5824 case IPPROTO_UDP:
5825 s->src.state = PFUDPS_SINGLE;
5826 s->dst.state = PFUDPS_NO_TRAFFIC;
5827 s->timeout = PFTM_UDP_FIRST_PACKET;
5828 break;
5829 case IPPROTO_ICMP:
5830#if INET6
5831 case IPPROTO_ICMPV6:
5832#endif
5833 s->timeout = PFTM_ICMP_FIRST_PACKET;
5834 break;
b0d623f7
A
5835 case IPPROTO_GRE:
5836 s->src.state = PFGRE1S_INITIATING;
5837 s->dst.state = PFGRE1S_NO_TRAFFIC;
5838 s->timeout = PFTM_GREv1_INITIATING;
5839 break;
5840 case IPPROTO_ESP:
5841 s->src.state = PFESPS_INITIATING;
5842 s->dst.state = PFESPS_NO_TRAFFIC;
5843 s->timeout = PFTM_ESP_FIRST_PACKET;
5844 break;
b0d623f7
A
5845 default:
5846 s->src.state = PFOTHERS_SINGLE;
5847 s->dst.state = PFOTHERS_NO_TRAFFIC;
5848 s->timeout = PFTM_OTHER_FIRST_PACKET;
5849 }
5850
5851 s->creation = pf_time_second();
5852 s->expire = pf_time_second();
5853
5854 if (sn != NULL) {
5855 s->src_node = sn;
5856 s->src_node->states++;
b7266188 5857 VERIFY(s->src_node->states != 0);
b0d623f7
A
5858 }
5859 if (nsn != NULL) {
5860 PF_ACPY(&nsn->raddr, &pd->naddr, af);
5861 s->nat_src_node = nsn;
5862 s->nat_src_node->states++;
b7266188 5863 VERIFY(s->nat_src_node->states != 0);
b0d623f7
A
5864 }
5865 if (pd->proto == IPPROTO_TCP) {
5866 if ((pd->flags & PFDESC_TCP_NORM) &&
5ba3f43e 5867 pf_normalize_tcp_init(pbuf, off, pd, th, &s->src,
b0d623f7
A
5868 &s->dst)) {
5869 REASON_SET(&reason, PFRES_MEMORY);
5870 pf_src_tree_remove_state(s);
5871 STATE_DEC_COUNTERS(s);
5872 pool_put(&pf_state_pl, s);
0a7de745 5873 return PF_DROP;
b0d623f7
A
5874 }
5875 if ((pd->flags & PFDESC_TCP_NORM) && s->src.scrub &&
5ba3f43e 5876 pf_normalize_tcp_stateful(pbuf, off, pd, &reason,
b0d623f7
A
5877 th, s, &s->src, &s->dst, &rewrite)) {
5878 /* This really shouldn't happen!!! */
5879 DPFPRINTF(PF_DEBUG_URGENT,
5880 ("pf_normalize_tcp_stateful failed on "
5881 "first pkt"));
5882 pf_normalize_tcp_cleanup(s);
5883 pf_src_tree_remove_state(s);
5884 STATE_DEC_COUNTERS(s);
5885 pool_put(&pf_state_pl, s);
0a7de745 5886 return PF_DROP;
b0d623f7
A
5887 }
5888 }
5889
316670eb
A
5890 /* allocate state key and import values from psk */
5891 if ((sk = pf_alloc_state_key(s, &psk)) == NULL) {
b0d623f7 5892 REASON_SET(&reason, PFRES_MEMORY);
5ba3f43e
A
5893 /*
5894 * XXXSCW: This will leak the freshly-allocated
5895 * state structure 's'. Although it should
5896 * eventually be aged-out and removed.
5897 */
b0d623f7
A
5898 goto cleanup;
5899 }
5900
0a7de745 5901 pf_set_rt_ifp(s, saddr, af); /* needs s->state_key set */
b0d623f7 5902
5ba3f43e 5903 pbuf = pd->mp; // XXXSCW: Why?
b0d623f7
A
5904
5905 if (sk->app_state == 0) {
5906 switch (pd->proto) {
5907 case IPPROTO_TCP: {
5908 u_int16_t dport = (direction == PF_OUT) ?
3e170ce0 5909 sk->ext_gwy.xport.port : sk->gwy.xport.port;
b0d623f7 5910
b7266188
A
5911 if (nr != NULL &&
5912 ntohs(dport) == PF_PPTP_PORT) {
b0d623f7
A
5913 struct pf_app_state *as;
5914
5915 as = pool_get(&pf_app_state_pl,
5916 PR_WAITOK);
5917 if (!as) {
5918 REASON_SET(&reason,
5919 PFRES_MEMORY);
5920 goto cleanup;
5921 }
5922
0a7de745 5923 bzero(as, sizeof(*as));
b0d623f7
A
5924 as->handler = pf_pptp_handler;
5925 as->compare_lan_ext = 0;
5926 as->compare_ext_gwy = 0;
5927 as->u.pptp.grev1_state = 0;
5928 sk->app_state = as;
5929 (void) hook_establish(&s->unlink_hooks,
5930 0, (hook_fn_t) pf_pptp_unlink, s);
5931 }
5932 break;
5933 }
5934
5935 case IPPROTO_UDP: {
b7266188
A
5936 if (nr != NULL &&
5937 ntohs(uh->uh_sport) == PF_IKE_PORT &&
5938 ntohs(uh->uh_dport) == PF_IKE_PORT) {
b0d623f7
A
5939 struct pf_app_state *as;
5940
5941 as = pool_get(&pf_app_state_pl,
5942 PR_WAITOK);
5943 if (!as) {
5944 REASON_SET(&reason,
5945 PFRES_MEMORY);
5946 goto cleanup;
5947 }
5948
0a7de745 5949 bzero(as, sizeof(*as));
b0d623f7
A
5950 as->compare_lan_ext = pf_ike_compare;
5951 as->compare_ext_gwy = pf_ike_compare;
5952 as->u.ike.cookie = ike.initiator_cookie;
5953 sk->app_state = as;
5954 }
5955 break;
5956 }
5957
5958 default:
5959 break;
5960 }
5961 }
b0d623f7
A
5962
5963 if (pf_insert_state(BOUND_IFACE(r, kif), s)) {
0a7de745 5964 if (pd->proto == IPPROTO_TCP) {
b0d623f7 5965 pf_normalize_tcp_cleanup(s);
0a7de745 5966 }
b0d623f7
A
5967 REASON_SET(&reason, PFRES_STATEINS);
5968 pf_src_tree_remove_state(s);
5969 STATE_DEC_COUNTERS(s);
5970 pool_put(&pf_state_pl, s);
0a7de745 5971 return PF_DROP;
5ba3f43e 5972 } else {
b0d623f7 5973 *sm = s;
5ba3f43e 5974 }
b0d623f7
A
5975 if (tag > 0) {
5976 pf_tag_ref(tag);
5977 s->tag = tag;
5978 }
5979 if (pd->proto == IPPROTO_TCP &&
0a7de745 5980 (th->th_flags & (TH_SYN | TH_ACK)) == TH_SYN &&
b0d623f7 5981 r->keep_state == PF_STATE_SYNPROXY) {
3e170ce0 5982 int ua = (sk->af_lan == sk->af_gwy) ? 1 : 0;
b0d623f7
A
5983 s->src.state = PF_TCPS_PROXY_SRC;
5984 if (nr != NULL) {
b0d623f7
A
5985 if (direction == PF_OUT) {
5986 pf_change_ap(direction, pd->mp, saddr,
5987 &th->th_sport, pd->ip_sum,
5988 &th->th_sum, &pd->baddr,
3e170ce0 5989 bxport.port, 0, af, pd->af, ua);
b0d623f7
A
5990 sxport.port = th->th_sport;
5991 } else {
5992 pf_change_ap(direction, pd->mp, daddr,
5993 &th->th_dport, pd->ip_sum,
5994 &th->th_sum, &pd->baddr,
3e170ce0 5995 bxport.port, 0, af, pd->af, ua);
b0d623f7
A
5996 sxport.port = th->th_dport;
5997 }
b0d623f7
A
5998 }
5999 s->src.seqhi = htonl(random());
6000 /* Find mss option */
5ba3f43e 6001 mss = pf_get_mss(pbuf, off, th->th_off, af);
b0d623f7
A
6002 mss = pf_calc_mss(saddr, af, mss);
6003 mss = pf_calc_mss(daddr, af, mss);
6004 s->src.mss = mss;
6005 pf_send_tcp(r, af, daddr, saddr, th->th_dport,
6006 th->th_sport, s->src.seqhi, ntohl(th->th_seq) + 1,
0a7de745 6007 TH_SYN | TH_ACK, 0, s->src.mss, 0, 1, 0, NULL, NULL);
b0d623f7 6008 REASON_SET(&reason, PFRES_SYNPROXY);
0a7de745 6009 return PF_SYNPROXY_DROP;
b0d623f7
A
6010 }
6011
b0d623f7
A
6012 if (sk->app_state && sk->app_state->handler) {
6013 int offx = off;
6014
6015 switch (pd->proto) {
6016 case IPPROTO_TCP:
6017 offx += th->th_off << 2;
6018 break;
6019 case IPPROTO_UDP:
6020 offx += pd->hdr.udp->uh_ulen << 2;
6021 break;
6022 default:
6023 /* ALG handlers only apply to TCP and UDP rules */
6024 break;
6025 }
6026
6027 if (offx > off) {
6028 sk->app_state->handler(s, direction, offx,
6029 pd, kif);
6030 if (pd->lmw < 0) {
6031 REASON_SET(&reason, PFRES_MEMORY);
0a7de745 6032 return PF_DROP;
b0d623f7 6033 }
0a7de745 6034 pbuf = pd->mp; // XXXSCW: Why?
b0d623f7
A
6035 }
6036 }
b0d623f7
A
6037 }
6038
6039 /* copy back packet headers if we performed NAT operations */
b0d623f7 6040 if (rewrite) {
0a7de745 6041 if (rewrite < off + hdrlen) {
b0d623f7 6042 rewrite = off + hdrlen;
0a7de745 6043 }
b0d623f7 6044
5ba3f43e 6045 if (pf_lazy_makewritable(pd, pd->mp, rewrite) == NULL) {
b0d623f7 6046 REASON_SET(&reason, PFRES_MEMORY);
0a7de745 6047 return PF_DROP;
b0d623f7
A
6048 }
6049
5ba3f43e 6050 pbuf_copy_back(pbuf, off, hdrlen, pd->hdr.any);
0a7de745 6051 if (af == AF_INET6 && pd->naf == AF_INET) {
5ba3f43e 6052 return pf_nat64_ipv6(pbuf, off, pd);
0a7de745 6053 } else if (af == AF_INET && pd->naf == AF_INET6) {
5ba3f43e 6054 return pf_nat64_ipv4(pbuf, off, pd);
0a7de745 6055 }
b0d623f7 6056 }
b0d623f7 6057
0a7de745 6058 return PF_PASS;
b0d623f7
A
6059}
6060
5ba3f43e
A
6061boolean_t is_nlc_enabled_glb = FALSE;
6062
6063static inline boolean_t
6064pf_is_dummynet_enabled(void)
6065{
6066#if DUMMYNET
0a7de745
A
6067 if (__probable(!PF_IS_ENABLED)) {
6068 return FALSE;
6069 }
5ba3f43e 6070
0a7de745
A
6071 if (__probable(!DUMMYNET_LOADED)) {
6072 return FALSE;
6073 }
5ba3f43e
A
6074
6075 if (__probable(TAILQ_EMPTY(pf_main_ruleset.
0a7de745
A
6076 rules[PF_RULESET_DUMMYNET].active.ptr))) {
6077 return FALSE;
6078 }
5ba3f43e 6079
0a7de745 6080 return TRUE;
5ba3f43e 6081#else
0a7de745 6082 return FALSE;
5ba3f43e
A
6083#endif /* DUMMYNET */
6084}
6085
316670eb
A
6086#if DUMMYNET
6087/*
39037602 6088 * When pf_test_dummynet() returns PF_PASS, the rule matching parameter "rm"
316670eb 6089 * remains unchanged, meaning the packet did not match a dummynet rule.
39037602
A
6090 * when the packet does match a dummynet rule, pf_test_dummynet() returns
6091 * PF_PASS and zero out the mbuf rule as the packet is effectively siphoned
316670eb
A
6092 * out by dummynet.
6093 */
6094static int
39037602 6095pf_test_dummynet(struct pf_rule **rm, int direction, struct pfi_kif *kif,
5ba3f43e 6096 pbuf_t **pbuf0, struct pf_pdesc *pd, struct ip_fw_args *fwa)
316670eb 6097{
0a7de745
A
6098 pbuf_t *pbuf = *pbuf0;
6099 struct pf_rule *am = NULL;
6100 struct pf_ruleset *rsm = NULL;
6101 struct pf_addr *saddr = pd->src, *daddr = pd->dst;
6102 sa_family_t af = pd->af;
6103 struct pf_rule *r, *a = NULL;
6104 struct pf_ruleset *ruleset = NULL;
6105 struct tcphdr *th = pd->hdr.tcp;
6106 u_short reason;
6107 int hdrlen = 0;
6108 int tag = -1;
6109 unsigned int rtableid = IFSCOPE_NONE;
6110 int asd = 0;
6111 int match = 0;
6112 u_int8_t icmptype = 0, icmpcode = 0;
6113 struct ip_fw_args dnflow;
6114 struct pf_rule *prev_matching_rule = fwa ? fwa->fwa_pf_rule : NULL;
6115 int found_prev_rule = (prev_matching_rule) ? 0 : 1;
316670eb 6116
5ba3f43e 6117 LCK_MTX_ASSERT(pf_lock, LCK_MTX_ASSERT_OWNED);
316670eb 6118
0a7de745
A
6119 if (!pf_is_dummynet_enabled()) {
6120 return PF_PASS;
6121 }
39037602 6122
316670eb
A
6123 bzero(&dnflow, sizeof(dnflow));
6124
6125 hdrlen = 0;
316670eb
A
6126
6127 /* Fragments don't gave protocol headers */
0a7de745 6128 if (!(pd->flags & PFDESC_IP_FRAG)) {
316670eb
A
6129 switch (pd->proto) {
6130 case IPPROTO_TCP:
6131 dnflow.fwa_id.flags = pd->hdr.tcp->th_flags;
4b17d6b6
A
6132 dnflow.fwa_id.dst_port = ntohs(pd->hdr.tcp->th_dport);
6133 dnflow.fwa_id.src_port = ntohs(pd->hdr.tcp->th_sport);
0a7de745 6134 hdrlen = sizeof(*th);
316670eb
A
6135 break;
6136 case IPPROTO_UDP:
4b17d6b6
A
6137 dnflow.fwa_id.dst_port = ntohs(pd->hdr.udp->uh_dport);
6138 dnflow.fwa_id.src_port = ntohs(pd->hdr.udp->uh_sport);
0a7de745 6139 hdrlen = sizeof(*pd->hdr.udp);
316670eb
A
6140 break;
6141#if INET
6142 case IPPROTO_ICMP:
0a7de745 6143 if (af != AF_INET) {
316670eb 6144 break;
0a7de745 6145 }
316670eb
A
6146 hdrlen = ICMP_MINLEN;
6147 icmptype = pd->hdr.icmp->icmp_type;
6148 icmpcode = pd->hdr.icmp->icmp_code;
6149 break;
6150#endif /* INET */
6151#if INET6
6152 case IPPROTO_ICMPV6:
0a7de745 6153 if (af != AF_INET6) {
316670eb 6154 break;
0a7de745
A
6155 }
6156 hdrlen = sizeof(*pd->hdr.icmp6);
316670eb
A
6157 icmptype = pd->hdr.icmp6->icmp6_type;
6158 icmpcode = pd->hdr.icmp6->icmp6_code;
6159 break;
6160#endif /* INET6 */
6161 case IPPROTO_GRE:
0a7de745
A
6162 if (pd->proto_variant == PF_GRE_PPTP_VARIANT) {
6163 hdrlen = sizeof(*pd->hdr.grev1);
6164 }
316670eb
A
6165 break;
6166 case IPPROTO_ESP:
0a7de745 6167 hdrlen = sizeof(*pd->hdr.esp);
316670eb
A
6168 break;
6169 }
0a7de745 6170 }
316670eb
A
6171
6172 r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_DUMMYNET].active.ptr);
6173
6174 while (r != NULL) {
6175 r->evaluations++;
0a7de745 6176 if (pfi_kif_match(r->kif, kif) == r->ifnot) {
316670eb 6177 r = r->skip[PF_SKIP_IFP].ptr;
0a7de745 6178 } else if (r->direction && r->direction != direction) {
316670eb 6179 r = r->skip[PF_SKIP_DIR].ptr;
0a7de745 6180 } else if (r->af && r->af != af) {
316670eb 6181 r = r->skip[PF_SKIP_AF].ptr;
0a7de745 6182 } else if (r->proto && r->proto != pd->proto) {
316670eb 6183 r = r->skip[PF_SKIP_PROTO].ptr;
0a7de745
A
6184 } else if (PF_MISMATCHAW(&r->src.addr, saddr, af,
6185 r->src.neg, kif)) {
316670eb 6186 r = r->skip[PF_SKIP_SRC_ADDR].ptr;
0a7de745 6187 }
316670eb 6188 /* tcp/udp only. port_op always 0 in other cases */
39037602 6189 else if (r->proto == pd->proto &&
316670eb
A
6190 (r->proto == IPPROTO_TCP || r->proto == IPPROTO_UDP) &&
6191 ((pd->flags & PFDESC_IP_FRAG) ||
6192 ((r->src.xport.range.op &&
6193 !pf_match_port(r->src.xport.range.op,
6194 r->src.xport.range.port[0], r->src.xport.range.port[1],
0a7de745 6195 th->th_sport))))) {
316670eb 6196 r = r->skip[PF_SKIP_SRC_PORT].ptr;
0a7de745
A
6197 } else if (PF_MISMATCHAW(&r->dst.addr, daddr, af,
6198 r->dst.neg, NULL)) {
316670eb 6199 r = r->skip[PF_SKIP_DST_ADDR].ptr;
0a7de745 6200 }
316670eb
A
6201 /* tcp/udp only. port_op always 0 in other cases */
6202 else if (r->proto == pd->proto &&
6203 (r->proto == IPPROTO_TCP || r->proto == IPPROTO_UDP) &&
6204 r->dst.xport.range.op &&
6205 ((pd->flags & PFDESC_IP_FRAG) ||
6206 !pf_match_port(r->dst.xport.range.op,
6207 r->dst.xport.range.port[0], r->dst.xport.range.port[1],
0a7de745 6208 th->th_dport))) {
316670eb 6209 r = r->skip[PF_SKIP_DST_PORT].ptr;
0a7de745 6210 }
316670eb 6211 /* icmp only. type always 0 in other cases */
39037602 6212 else if (r->type &&
0a7de745
A
6213 ((pd->flags & PFDESC_IP_FRAG) ||
6214 r->type != icmptype + 1)) {
316670eb 6215 r = TAILQ_NEXT(r, entries);
0a7de745 6216 }
316670eb 6217 /* icmp only. type always 0 in other cases */
39037602 6218 else if (r->code &&
0a7de745
A
6219 ((pd->flags & PFDESC_IP_FRAG) ||
6220 r->code != icmpcode + 1)) {
316670eb 6221 r = TAILQ_NEXT(r, entries);
0a7de745 6222 } else if (r->tos && !(r->tos == pd->tos)) {
316670eb 6223 r = TAILQ_NEXT(r, entries);
0a7de745 6224 } else if (r->rule_flag & PFRULE_FRAGMENT) {
316670eb 6225 r = TAILQ_NEXT(r, entries);
0a7de745 6226 } else if (pd->proto == IPPROTO_TCP &&
316670eb 6227 ((pd->flags & PFDESC_IP_FRAG) ||
0a7de745 6228 (r->flagset & th->th_flags) != r->flags)) {
316670eb 6229 r = TAILQ_NEXT(r, entries);
0a7de745 6230 } else if (r->prob && r->prob <= (RandomULong() % (UINT_MAX - 1) + 1)) {
39236c6e 6231 r = TAILQ_NEXT(r, entries);
0a7de745 6232 } else if (r->match_tag && !pf_match_tag(r, pd->pf_mtag, &tag)) {
316670eb 6233 r = TAILQ_NEXT(r, entries);
0a7de745 6234 } else {
39037602
A
6235 /*
6236 * Need to go past the previous dummynet matching rule
316670eb
A
6237 */
6238 if (r->anchor == NULL) {
6239 if (found_prev_rule) {
0a7de745 6240 if (r->tag) {
316670eb 6241 tag = r->tag;
0a7de745
A
6242 }
6243 if (PF_RTABLEID_IS_VALID(r->rtableid)) {
316670eb 6244 rtableid = r->rtableid;
0a7de745 6245 }
316670eb
A
6246 match = 1;
6247 *rm = r;
6248 am = a;
6249 rsm = ruleset;
0a7de745 6250 if ((*rm)->quick) {
316670eb 6251 break;
0a7de745 6252 }
316670eb
A
6253 } else if (r == prev_matching_rule) {
6254 found_prev_rule = 1;
6255 }
6256 r = TAILQ_NEXT(r, entries);
6257 } else {
6258 pf_step_into_anchor(&asd, &ruleset,
6259 PF_RULESET_DUMMYNET, &r, &a, &match);
6260 }
6261 }
6262 if (r == NULL && pf_step_out_of_anchor(&asd, &ruleset,
0a7de745 6263 PF_RULESET_DUMMYNET, &r, &a, &match)) {
316670eb 6264 break;
0a7de745 6265 }
316670eb
A
6266 }
6267 r = *rm;
6268 a = am;
6269 ruleset = rsm;
6270
0a7de745
A
6271 if (!match) {
6272 return PF_PASS;
6273 }
316670eb
A
6274
6275 REASON_SET(&reason, PFRES_DUMMYNET);
6276
6277 if (r->log) {
5ba3f43e 6278 PFLOG_PACKET(kif, h, pbuf, af, direction, reason, r,
316670eb
A
6279 a, ruleset, pd);
6280 }
6281
6282 if (r->action == PF_NODUMMYNET) {
6283 int dirndx = (direction == PF_OUT);
39037602 6284
316670eb
A
6285 r->packets[dirndx]++;
6286 r->bytes[dirndx] += pd->tot_len;
6287
0a7de745 6288 return PF_PASS;
316670eb 6289 }
5ba3f43e 6290 if (pf_tag_packet(pbuf, pd->pf_mtag, tag, rtableid, pd)) {
316670eb
A
6291 REASON_SET(&reason, PFRES_MEMORY);
6292
0a7de745 6293 return PF_DROP;
316670eb
A
6294 }
6295
6296 if (r->dnpipe && ip_dn_io_ptr != NULL) {
5ba3f43e 6297 struct mbuf *m;
316670eb 6298 int dirndx = (direction == PF_OUT);
39037602 6299
316670eb
A
6300 r->packets[dirndx]++;
6301 r->bytes[dirndx] += pd->tot_len;
39037602 6302
316670eb
A
6303 dnflow.fwa_cookie = r->dnpipe;
6304 dnflow.fwa_pf_rule = r;
316670eb
A
6305 dnflow.fwa_id.proto = pd->proto;
6306 dnflow.fwa_flags = r->dntype;
4b17d6b6 6307 switch (af) {
0a7de745
A
6308 case AF_INET:
6309 dnflow.fwa_id.addr_type = 4;
6310 dnflow.fwa_id.src_ip = ntohl(saddr->v4addr.s_addr);
6311 dnflow.fwa_id.dst_ip = ntohl(daddr->v4addr.s_addr);
6312 break;
6313 case AF_INET6:
6314 dnflow.fwa_id.addr_type = 6;
6315 dnflow.fwa_id.src_ip6 = saddr->v6addr;
6316 dnflow.fwa_id.dst_ip6 = saddr->v6addr;
6317 break;
6318 }
4b17d6b6 6319
316670eb
A
6320 if (fwa != NULL) {
6321 dnflow.fwa_oif = fwa->fwa_oif;
6322 dnflow.fwa_oflags = fwa->fwa_oflags;
6323 /*
39037602
A
6324 * Note that fwa_ro, fwa_dst and fwa_ipoa are
6325 * actually in a union so the following does work
316670eb
A
6326 * for both IPv4 and IPv6
6327 */
6328 dnflow.fwa_ro = fwa->fwa_ro;
6329 dnflow.fwa_dst = fwa->fwa_dst;
6330 dnflow.fwa_ipoa = fwa->fwa_ipoa;
6331 dnflow.fwa_ro6_pmtu = fwa->fwa_ro6_pmtu;
6332 dnflow.fwa_origifp = fwa->fwa_origifp;
6333 dnflow.fwa_mtu = fwa->fwa_mtu;
316670eb
A
6334 dnflow.fwa_unfragpartlen = fwa->fwa_unfragpartlen;
6335 dnflow.fwa_exthdrs = fwa->fwa_exthdrs;
6336 }
39037602 6337
316670eb 6338 if (af == AF_INET) {
5ba3f43e 6339 struct ip *iphdr = pbuf->pb_data;
316670eb
A
6340 NTOHS(iphdr->ip_len);
6341 NTOHS(iphdr->ip_off);
6342 }
3e170ce0 6343 /*
39037602 6344 * Don't need to unlock pf_lock as NET_THREAD_HELD_PF
316670eb
A
6345 * allows for recursive behavior
6346 */
5ba3f43e
A
6347 m = pbuf_to_mbuf(pbuf, TRUE);
6348 if (m != NULL) {
6349 ip_dn_io_ptr(m,
6350 dnflow.fwa_cookie, (af == AF_INET) ?
0a7de745
A
6351 ((direction == PF_IN) ? DN_TO_IP_IN : DN_TO_IP_OUT) :
6352 ((direction == PF_IN) ? DN_TO_IP6_IN : DN_TO_IP6_OUT),
5ba3f43e
A
6353 &dnflow, DN_CLIENT_PF);
6354 }
39037602 6355
316670eb 6356 /*
39037602 6357 * The packet is siphoned out by dummynet so return a NULL
5ba3f43e 6358 * pbuf so the caller can still return success.
316670eb 6359 */
5ba3f43e 6360 *pbuf0 = NULL;
39037602 6361
0a7de745 6362 return PF_PASS;
316670eb
A
6363 }
6364
0a7de745 6365 return PF_PASS;
316670eb
A
6366}
6367#endif /* DUMMYNET */
6368
b0d623f7
A
6369static int
6370pf_test_fragment(struct pf_rule **rm, int direction, struct pfi_kif *kif,
5ba3f43e 6371 pbuf_t *pbuf, void *h, struct pf_pdesc *pd, struct pf_rule **am,
b0d623f7
A
6372 struct pf_ruleset **rsm)
6373{
6374#pragma unused(h)
0a7de745
A
6375 struct pf_rule *r, *a = NULL;
6376 struct pf_ruleset *ruleset = NULL;
6377 sa_family_t af = pd->af;
6378 u_short reason;
6379 int tag = -1;
6380 int asd = 0;
6381 int match = 0;
b0d623f7
A
6382
6383 r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_FILTER].active.ptr);
6384 while (r != NULL) {
6385 r->evaluations++;
0a7de745 6386 if (pfi_kif_match(r->kif, kif) == r->ifnot) {
b0d623f7 6387 r = r->skip[PF_SKIP_IFP].ptr;
0a7de745 6388 } else if (r->direction && r->direction != direction) {
b0d623f7 6389 r = r->skip[PF_SKIP_DIR].ptr;
0a7de745 6390 } else if (r->af && r->af != af) {
b0d623f7 6391 r = r->skip[PF_SKIP_AF].ptr;
0a7de745 6392 } else if (r->proto && r->proto != pd->proto) {
b0d623f7 6393 r = r->skip[PF_SKIP_PROTO].ptr;
0a7de745
A
6394 } else if (PF_MISMATCHAW(&r->src.addr, pd->src, af,
6395 r->src.neg, kif)) {
b0d623f7 6396 r = r->skip[PF_SKIP_SRC_ADDR].ptr;
0a7de745
A
6397 } else if (PF_MISMATCHAW(&r->dst.addr, pd->dst, af,
6398 r->dst.neg, NULL)) {
b0d623f7 6399 r = r->skip[PF_SKIP_DST_ADDR].ptr;
0a7de745
A
6400 } else if ((r->rule_flag & PFRULE_TOS) && r->tos &&
6401 !(r->tos & pd->tos)) {
316670eb 6402 r = TAILQ_NEXT(r, entries);
0a7de745
A
6403 } else if ((r->rule_flag & PFRULE_DSCP) && r->tos &&
6404 !(r->tos & (pd->tos & DSCP_MASK))) {
316670eb 6405 r = TAILQ_NEXT(r, entries);
0a7de745
A
6406 } else if ((r->rule_flag & PFRULE_SC) && r->tos &&
6407 ((r->tos & SCIDX_MASK) != pd->sc)) {
b0d623f7 6408 r = TAILQ_NEXT(r, entries);
0a7de745 6409 } else if (r->os_fingerprint != PF_OSFP_ANY) {
b0d623f7 6410 r = TAILQ_NEXT(r, entries);
0a7de745
A
6411 } else if (pd->proto == IPPROTO_UDP &&
6412 (r->src.xport.range.op || r->dst.xport.range.op)) {
b0d623f7 6413 r = TAILQ_NEXT(r, entries);
0a7de745 6414 } else if (pd->proto == IPPROTO_TCP &&
b0d623f7 6415 (r->src.xport.range.op || r->dst.xport.range.op ||
0a7de745 6416 r->flagset)) {
b0d623f7 6417 r = TAILQ_NEXT(r, entries);
0a7de745 6418 } else if ((pd->proto == IPPROTO_ICMP ||
b0d623f7 6419 pd->proto == IPPROTO_ICMPV6) &&
0a7de745 6420 (r->type || r->code)) {
b0d623f7 6421 r = TAILQ_NEXT(r, entries);
0a7de745 6422 } else if (r->prob && r->prob <= (RandomULong() % (UINT_MAX - 1) + 1)) {
b0d623f7 6423 r = TAILQ_NEXT(r, entries);
0a7de745 6424 } else if (r->match_tag && !pf_match_tag(r, pd->pf_mtag, &tag)) {
b0d623f7 6425 r = TAILQ_NEXT(r, entries);
0a7de745 6426 } else {
b0d623f7
A
6427 if (r->anchor == NULL) {
6428 match = 1;
6429 *rm = r;
6430 *am = a;
6431 *rsm = ruleset;
0a7de745 6432 if ((*rm)->quick) {
b0d623f7 6433 break;
0a7de745 6434 }
b0d623f7 6435 r = TAILQ_NEXT(r, entries);
0a7de745 6436 } else {
b0d623f7
A
6437 pf_step_into_anchor(&asd, &ruleset,
6438 PF_RULESET_FILTER, &r, &a, &match);
0a7de745 6439 }
b0d623f7
A
6440 }
6441 if (r == NULL && pf_step_out_of_anchor(&asd, &ruleset,
0a7de745 6442 PF_RULESET_FILTER, &r, &a, &match)) {
b0d623f7 6443 break;
0a7de745 6444 }
b0d623f7
A
6445 }
6446 r = *rm;
6447 a = *am;
6448 ruleset = *rsm;
6449
6450 REASON_SET(&reason, PFRES_MATCH);
6451
0a7de745 6452 if (r->log) {
5ba3f43e 6453 PFLOG_PACKET(kif, h, pbuf, af, direction, reason, r, a, ruleset,
b0d623f7 6454 pd);
0a7de745 6455 }
b0d623f7 6456
0a7de745
A
6457 if (r->action != PF_PASS) {
6458 return PF_DROP;
6459 }
b0d623f7 6460
5ba3f43e 6461 if (pf_tag_packet(pbuf, pd->pf_mtag, tag, -1, NULL)) {
b0d623f7 6462 REASON_SET(&reason, PFRES_MEMORY);
0a7de745 6463 return PF_DROP;
b0d623f7
A
6464 }
6465
0a7de745 6466 return PF_PASS;
b0d623f7
A
6467}
6468
b0d623f7
A
6469static void
6470pf_pptp_handler(struct pf_state *s, int direction, int off,
6471 struct pf_pdesc *pd, struct pfi_kif *kif)
6472{
6473#pragma unused(direction)
6474 struct tcphdr *th;
d1ecb069 6475 struct pf_pptp_state *pptps;
b0d623f7 6476 struct pf_pptp_ctrl_msg cm;
39037602 6477 size_t plen, tlen;
b0d623f7
A
6478 struct pf_state *gs;
6479 u_int16_t ct;
6480 u_int16_t *pac_call_id;
6481 u_int16_t *pns_call_id;
6482 u_int16_t *spoof_call_id;
6483 u_int8_t *pac_state;
6484 u_int8_t *pns_state;
6485 enum { PF_PPTP_PASS, PF_PPTP_INSERT_GRE, PF_PPTP_REMOVE_GRE } op;
5ba3f43e 6486 pbuf_t *pbuf;
b0d623f7
A
6487 struct pf_state_key *sk;
6488 struct pf_state_key *gsk;
d1ecb069
A
6489 struct pf_app_state *gas;
6490
6491 sk = s->state_key;
6492 pptps = &sk->app_state->u.pptp;
6493 gs = pptps->grev1_state;
6494
0a7de745 6495 if (gs) {
d1ecb069 6496 gs->expire = pf_time_second();
0a7de745 6497 }
b0d623f7 6498
5ba3f43e 6499 pbuf = pd->mp;
0a7de745
A
6500 plen = min(sizeof(cm), pbuf->pb_packet_len - off);
6501 if (plen < PF_PPTP_CTRL_MSG_MINSIZE) {
b0d623f7 6502 return;
0a7de745 6503 }
39037602 6504 tlen = plen - PF_PPTP_CTRL_MSG_MINSIZE;
5ba3f43e 6505 pbuf_copy_data(pbuf, off, plen, &cm);
b0d623f7 6506
0a7de745 6507 if (ntohl(cm.hdr.magic) != PF_PPTP_MAGIC_NUMBER) {
b0d623f7 6508 return;
0a7de745
A
6509 }
6510 if (ntohs(cm.hdr.type) != 1) {
b0d623f7 6511 return;
0a7de745 6512 }
b0d623f7 6513
0a7de745
A
6514#define TYPE_LEN_CHECK(_type, _name) \
6515 case PF_PPTP_CTRL_TYPE_##_type: \
6516 if (tlen < sizeof(struct pf_pptp_ctrl_##_name)) \
6517 return; \
6518 break;
39037602
A
6519
6520 switch (cm.ctrl.type) {
0a7de745
A
6521 TYPE_LEN_CHECK(START_REQ, start_req);
6522 TYPE_LEN_CHECK(START_RPY, start_rpy);
6523 TYPE_LEN_CHECK(STOP_REQ, stop_req);
6524 TYPE_LEN_CHECK(STOP_RPY, stop_rpy);
6525 TYPE_LEN_CHECK(ECHO_REQ, echo_req);
6526 TYPE_LEN_CHECK(ECHO_RPY, echo_rpy);
6527 TYPE_LEN_CHECK(CALL_OUT_REQ, call_out_req);
6528 TYPE_LEN_CHECK(CALL_OUT_RPY, call_out_rpy);
6529 TYPE_LEN_CHECK(CALL_IN_1ST, call_in_1st);
6530 TYPE_LEN_CHECK(CALL_IN_2ND, call_in_2nd);
6531 TYPE_LEN_CHECK(CALL_IN_3RD, call_in_3rd);
6532 TYPE_LEN_CHECK(CALL_CLR, call_clr);
6533 TYPE_LEN_CHECK(CALL_DISC, call_disc);
6534 TYPE_LEN_CHECK(ERROR, error);
6535 TYPE_LEN_CHECK(SET_LINKINFO, set_linkinfo);
39037602
A
6536 default:
6537 return;
6538 }
6539#undef TYPE_LEN_CHECK
6540
b0d623f7
A
6541 if (!gs) {
6542 gs = pool_get(&pf_state_pl, PR_WAITOK);
0a7de745 6543 if (!gs) {
b0d623f7 6544 return;
0a7de745 6545 }
b0d623f7 6546
0a7de745 6547 memcpy(gs, s, sizeof(*gs));
b0d623f7 6548
0a7de745
A
6549 memset(&gs->entry_id, 0, sizeof(gs->entry_id));
6550 memset(&gs->entry_list, 0, sizeof(gs->entry_list));
b0d623f7
A
6551
6552 TAILQ_INIT(&gs->unlink_hooks);
6553 gs->rt_kif = NULL;
6554 gs->creation = 0;
6555 gs->pfsync_time = 0;
6556 gs->packets[0] = gs->packets[1] = 0;
6557 gs->bytes[0] = gs->bytes[1] = 0;
6558 gs->timeout = PFTM_UNLINKED;
6559 gs->id = gs->creatorid = 0;
6560 gs->src.state = gs->dst.state = PFGRE1S_NO_TRAFFIC;
6561 gs->src.scrub = gs->dst.scrub = 0;
6562
d1ecb069
A
6563 gas = pool_get(&pf_app_state_pl, PR_NOWAIT);
6564 if (!gas) {
6565 pool_put(&pf_state_pl, gs);
6566 return;
6567 }
6568
316670eb 6569 gsk = pf_alloc_state_key(gs, NULL);
b0d623f7 6570 if (!gsk) {
d1ecb069 6571 pool_put(&pf_app_state_pl, gas);
b0d623f7
A
6572 pool_put(&pf_state_pl, gs);
6573 return;
6574 }
6575
0a7de745
A
6576 memcpy(&gsk->lan, &sk->lan, sizeof(gsk->lan));
6577 memcpy(&gsk->gwy, &sk->gwy, sizeof(gsk->gwy));
6578 memcpy(&gsk->ext_lan, &sk->ext_lan, sizeof(gsk->ext_lan));
6579 memcpy(&gsk->ext_gwy, &sk->ext_gwy, sizeof(gsk->ext_gwy));
3e170ce0
A
6580 gsk->af_lan = sk->af_lan;
6581 gsk->af_gwy = sk->af_gwy;
b0d623f7
A
6582 gsk->proto = IPPROTO_GRE;
6583 gsk->proto_variant = PF_GRE_PPTP_VARIANT;
d1ecb069 6584 gsk->app_state = gas;
b0d623f7
A
6585 gsk->lan.xport.call_id = 0;
6586 gsk->gwy.xport.call_id = 0;
3e170ce0
A
6587 gsk->ext_lan.xport.call_id = 0;
6588 gsk->ext_gwy.xport.call_id = 0;
39236c6e 6589 gsk->flowsrc = FLOWSRC_PF;
316670eb 6590 gsk->flowhash = pf_calc_state_key_flowhash(gsk);
0a7de745 6591 memset(gas, 0, sizeof(*gas));
d1ecb069 6592 gas->u.grev1.pptp_state = s;
b7266188 6593 STATE_INC_COUNTERS(gs);
d1ecb069
A
6594 pptps->grev1_state = gs;
6595 (void) hook_establish(&gs->unlink_hooks, 0,
6596 (hook_fn_t) pf_grev1_unlink, gs);
b0d623f7
A
6597 } else {
6598 gsk = gs->state_key;
6599 }
6600
6601 switch (sk->direction) {
6602 case PF_IN:
3e170ce0 6603 pns_call_id = &gsk->ext_lan.xport.call_id;
b0d623f7
A
6604 pns_state = &gs->dst.state;
6605 pac_call_id = &gsk->lan.xport.call_id;
6606 pac_state = &gs->src.state;
6607 break;
6608
6609 case PF_OUT:
6610 pns_call_id = &gsk->lan.xport.call_id;
6611 pns_state = &gs->src.state;
3e170ce0 6612 pac_call_id = &gsk->ext_lan.xport.call_id;
b0d623f7
A
6613 pac_state = &gs->dst.state;
6614 break;
6615
6616 default:
6617 DPFPRINTF(PF_DEBUG_URGENT,
6618 ("pf_pptp_handler: bad directional!\n"));
6619 return;
6620 }
6621
6622 spoof_call_id = 0;
6623 op = PF_PPTP_PASS;
6624
6625 ct = ntohs(cm.ctrl.type);
6626
6627 switch (ct) {
6628 case PF_PPTP_CTRL_TYPE_CALL_OUT_REQ:
6629 *pns_call_id = cm.msg.call_out_req.call_id;
6630 *pns_state = PFGRE1S_INITIATING;
0a7de745 6631 if (s->nat_rule.ptr && pns_call_id == &gsk->lan.xport.call_id) {
b0d623f7 6632 spoof_call_id = &cm.msg.call_out_req.call_id;
0a7de745 6633 }
b0d623f7
A
6634 break;
6635
6636 case PF_PPTP_CTRL_TYPE_CALL_OUT_RPY:
6637 *pac_call_id = cm.msg.call_out_rpy.call_id;
0a7de745 6638 if (s->nat_rule.ptr) {
b0d623f7
A
6639 spoof_call_id =
6640 (pac_call_id == &gsk->lan.xport.call_id) ?
6641 &cm.msg.call_out_rpy.call_id :
6642 &cm.msg.call_out_rpy.peer_call_id;
0a7de745 6643 }
b0d623f7
A
6644 if (gs->timeout == PFTM_UNLINKED) {
6645 *pac_state = PFGRE1S_INITIATING;
6646 op = PF_PPTP_INSERT_GRE;
6647 }
6648 break;
6649
6650 case PF_PPTP_CTRL_TYPE_CALL_IN_1ST:
6651 *pns_call_id = cm.msg.call_in_1st.call_id;
6652 *pns_state = PFGRE1S_INITIATING;
0a7de745 6653 if (s->nat_rule.ptr && pns_call_id == &gsk->lan.xport.call_id) {
b0d623f7 6654 spoof_call_id = &cm.msg.call_in_1st.call_id;
0a7de745 6655 }
b0d623f7
A
6656 break;
6657
6658 case PF_PPTP_CTRL_TYPE_CALL_IN_2ND:
6659 *pac_call_id = cm.msg.call_in_2nd.call_id;
6660 *pac_state = PFGRE1S_INITIATING;
0a7de745 6661 if (s->nat_rule.ptr) {
b0d623f7
A
6662 spoof_call_id =
6663 (pac_call_id == &gsk->lan.xport.call_id) ?
6664 &cm.msg.call_in_2nd.call_id :
6665 &cm.msg.call_in_2nd.peer_call_id;
0a7de745 6666 }
b0d623f7
A
6667 break;
6668
6669 case PF_PPTP_CTRL_TYPE_CALL_IN_3RD:
0a7de745 6670 if (s->nat_rule.ptr && pns_call_id == &gsk->lan.xport.call_id) {
b0d623f7 6671 spoof_call_id = &cm.msg.call_in_3rd.call_id;
0a7de745 6672 }
b0d623f7
A
6673 if (cm.msg.call_in_3rd.call_id != *pns_call_id) {
6674 break;
6675 }
0a7de745 6676 if (gs->timeout == PFTM_UNLINKED) {
b0d623f7 6677 op = PF_PPTP_INSERT_GRE;
0a7de745 6678 }
b0d623f7
A
6679 break;
6680
6681 case PF_PPTP_CTRL_TYPE_CALL_CLR:
0a7de745 6682 if (cm.msg.call_clr.call_id != *pns_call_id) {
b0d623f7 6683 op = PF_PPTP_REMOVE_GRE;
0a7de745 6684 }
b0d623f7
A
6685 break;
6686
6687 case PF_PPTP_CTRL_TYPE_CALL_DISC:
0a7de745 6688 if (cm.msg.call_clr.call_id != *pac_call_id) {
b0d623f7 6689 op = PF_PPTP_REMOVE_GRE;
0a7de745 6690 }
b0d623f7
A
6691 break;
6692
6693 case PF_PPTP_CTRL_TYPE_ERROR:
0a7de745 6694 if (s->nat_rule.ptr && pns_call_id == &gsk->lan.xport.call_id) {
b0d623f7 6695 spoof_call_id = &cm.msg.error.peer_call_id;
0a7de745 6696 }
b0d623f7
A
6697 break;
6698
6699 case PF_PPTP_CTRL_TYPE_SET_LINKINFO:
0a7de745 6700 if (s->nat_rule.ptr && pac_call_id == &gsk->lan.xport.call_id) {
b0d623f7 6701 spoof_call_id = &cm.msg.set_linkinfo.peer_call_id;
0a7de745 6702 }
b0d623f7
A
6703 break;
6704
6705 default:
6706 op = PF_PPTP_PASS;
6707 break;
6708 }
6709
6710 if (!gsk->gwy.xport.call_id && gsk->lan.xport.call_id) {
6711 gsk->gwy.xport.call_id = gsk->lan.xport.call_id;
6712 if (spoof_call_id) {
6713 u_int16_t call_id = 0;
6714 int n = 0;
6715 struct pf_state_key_cmp key;
6716
3e170ce0 6717 key.af_gwy = gsk->af_gwy;
b0d623f7
A
6718 key.proto = IPPROTO_GRE;
6719 key.proto_variant = PF_GRE_PPTP_VARIANT;
3e170ce0
A
6720 PF_ACPY(&key.gwy.addr, &gsk->gwy.addr, key.af_gwy);
6721 PF_ACPY(&key.ext_gwy.addr, &gsk->ext_gwy.addr, key.af_gwy);
b0d623f7 6722 key.gwy.xport.call_id = gsk->gwy.xport.call_id;
3e170ce0 6723 key.ext_gwy.xport.call_id = gsk->ext_gwy.xport.call_id;
b0d623f7
A
6724 do {
6725 call_id = htonl(random());
6726 } while (!call_id);
6727
6728 while (pf_find_state_all(&key, PF_IN, 0)) {
6729 call_id = ntohs(call_id);
6730 --call_id;
0a7de745
A
6731 if (--call_id == 0) {
6732 call_id = 0xffff;
6733 }
b0d623f7
A
6734 call_id = htons(call_id);
6735
6736 key.gwy.xport.call_id = call_id;
6737
6738 if (++n > 65535) {
6739 DPFPRINTF(PF_DEBUG_URGENT,
6740 ("pf_pptp_handler: failed to spoof "
6741 "call id\n"));
6742 key.gwy.xport.call_id = 0;
6743 break;
6744 }
6745 }
6746
6747 gsk->gwy.xport.call_id = call_id;
6748 }
6749 }
6750
6751 th = pd->hdr.tcp;
6752
6753 if (spoof_call_id && gsk->lan.xport.call_id != gsk->gwy.xport.call_id) {
6754 if (*spoof_call_id == gsk->gwy.xport.call_id) {
6755 *spoof_call_id = gsk->lan.xport.call_id;
6756 th->th_sum = pf_cksum_fixup(th->th_sum,
6757 gsk->gwy.xport.call_id, gsk->lan.xport.call_id, 0);
6758 } else {
6759 *spoof_call_id = gsk->gwy.xport.call_id;
6760 th->th_sum = pf_cksum_fixup(th->th_sum,
6761 gsk->lan.xport.call_id, gsk->gwy.xport.call_id, 0);
6762 }
6763
5ba3f43e 6764 if (pf_lazy_makewritable(pd, pbuf, off + plen) == NULL) {
d1ecb069 6765 pptps->grev1_state = NULL;
b7266188
A
6766 STATE_DEC_COUNTERS(gs);
6767 pool_put(&pf_state_pl, gs);
b0d623f7 6768 return;
b7266188 6769 }
5ba3f43e 6770 pbuf_copy_back(pbuf, off, plen, &cm);
b0d623f7
A
6771 }
6772
6773 switch (op) {
6774 case PF_PPTP_REMOVE_GRE:
6775 gs->timeout = PFTM_PURGE;
6776 gs->src.state = gs->dst.state = PFGRE1S_NO_TRAFFIC;
6777 gsk->lan.xport.call_id = 0;
6778 gsk->gwy.xport.call_id = 0;
3e170ce0
A
6779 gsk->ext_lan.xport.call_id = 0;
6780 gsk->ext_gwy.xport.call_id = 0;
b0d623f7
A
6781 gs->id = gs->creatorid = 0;
6782 break;
6783
6784 case PF_PPTP_INSERT_GRE:
6785 gs->creation = pf_time_second();
6786 gs->expire = pf_time_second();
d1ecb069 6787 gs->timeout = PFTM_TCP_ESTABLISHED;
b7266188
A
6788 if (gs->src_node != NULL) {
6789 ++gs->src_node->states;
6790 VERIFY(gs->src_node->states != 0);
6791 }
6792 if (gs->nat_src_node != NULL) {
6793 ++gs->nat_src_node->states;
6794 VERIFY(gs->nat_src_node->states != 0);
6795 }
3e170ce0 6796 pf_set_rt_ifp(gs, &sk->lan.addr, sk->af_lan);
b0d623f7 6797 if (pf_insert_state(BOUND_IFACE(s->rule.ptr, kif), gs)) {
b0d623f7
A
6798 /*
6799 * <jhw@apple.com>
6800 * FIX ME: insertion can fail when multiple PNS
6801 * behind the same NAT open calls to the same PAC
6802 * simultaneously because spoofed call ID numbers
6803 * are chosen before states are inserted. This is
6804 * hard to fix and happens infrequently enough that
6805 * users will normally try again and this ALG will
6806 * succeed. Failures are expected to be rare enough
6807 * that fixing this is a low priority.
6808 */
d1ecb069 6809 pptps->grev1_state = NULL;
0a7de745 6810 pd->lmw = -1; /* Force PF_DROP on PFRES_MEMORY */
b0d623f7
A
6811 pf_src_tree_remove_state(gs);
6812 STATE_DEC_COUNTERS(gs);
6813 pool_put(&pf_state_pl, gs);
6814 DPFPRINTF(PF_DEBUG_URGENT, ("pf_pptp_handler: error "
6815 "inserting GREv1 state.\n"));
6816 }
6817 break;
6818
6819 default:
6820 break;
6821 }
6822}
6823
6824static void
6825pf_pptp_unlink(struct pf_state *s)
6826{
6827 struct pf_app_state *as = s->state_key->app_state;
d1ecb069
A
6828 struct pf_state *grev1s = as->u.pptp.grev1_state;
6829
6830 if (grev1s) {
6831 struct pf_app_state *gas = grev1s->state_key->app_state;
b0d623f7 6832
0a7de745 6833 if (grev1s->timeout < PFTM_MAX) {
d1ecb069 6834 grev1s->timeout = PFTM_PURGE;
0a7de745 6835 }
d1ecb069
A
6836 gas->u.grev1.pptp_state = NULL;
6837 as->u.pptp.grev1_state = NULL;
6838 }
6839}
6840
6841static void
6842pf_grev1_unlink(struct pf_state *s)
6843{
6844 struct pf_app_state *as = s->state_key->app_state;
6845 struct pf_state *pptps = as->u.grev1.pptp_state;
6846
6847 if (pptps) {
6848 struct pf_app_state *pas = pptps->state_key->app_state;
6849
6850 pas->u.pptp.grev1_state = NULL;
6851 as->u.grev1.pptp_state = NULL;
b0d623f7
A
6852 }
6853}
6854
6855static int
6856pf_ike_compare(struct pf_app_state *a, struct pf_app_state *b)
6857{
6858 int64_t d = a->u.ike.cookie - b->u.ike.cookie;
0a7de745 6859 return (d > 0) ? 1 : ((d < 0) ? -1 : 0);
b0d623f7 6860}
b0d623f7 6861
3e170ce0 6862static int
5ba3f43e 6863pf_do_nat64(struct pf_state_key *sk, struct pf_pdesc *pd, pbuf_t *pbuf,
0a7de745 6864 int off)
3e170ce0
A
6865{
6866 if (pd->af == AF_INET) {
6867 if (pd->af != sk->af_lan) {
6868 pd->ndaddr = sk->lan.addr;
6869 pd->naddr = sk->ext_lan.addr;
6870 } else {
6871 pd->naddr = sk->gwy.addr;
6872 pd->ndaddr = sk->ext_gwy.addr;
6873 }
0a7de745
A
6874 return pf_nat64_ipv4(pbuf, off, pd);
6875 } else if (pd->af == AF_INET6) {
3e170ce0
A
6876 if (pd->af != sk->af_lan) {
6877 pd->ndaddr = sk->lan.addr;
6878 pd->naddr = sk->ext_lan.addr;
0a7de745
A
6879 } else {
6880 pd->naddr = sk->gwy.addr;
6881 pd->ndaddr = sk->ext_gwy.addr;
6882 }
6883 return pf_nat64_ipv6(pbuf, off, pd);
3e170ce0 6884 }
0a7de745 6885 return PF_DROP;
3e170ce0
A
6886}
6887
b0d623f7
A
6888static int
6889pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif,
5ba3f43e 6890 pbuf_t *pbuf, int off, void *h, struct pf_pdesc *pd,
b0d623f7
A
6891 u_short *reason)
6892{
6893#pragma unused(h)
0a7de745
A
6894 struct pf_state_key_cmp key;
6895 struct tcphdr *th = pd->hdr.tcp;
6896 u_int16_t win = ntohs(th->th_win);
6897 u_int32_t ack, end, seq, orig_seq;
6898 u_int8_t sws, dws;
6899 int ackskew;
6900 int copyback = 0;
6901 struct pf_state_peer *src, *dst;
6902 struct pf_state_key *sk;
b0d623f7 6903
b0d623f7 6904 key.app_state = 0;
b0d623f7 6905 key.proto = IPPROTO_TCP;
3e170ce0
A
6906 key.af_lan = key.af_gwy = pd->af;
6907
6908 /*
6909 * For NAT64 the first time rule search and state creation
6910 * is done on the incoming side only.
6911 * Once the state gets created, NAT64's LAN side (ipv6) will
6912 * not be able to find the state in ext-gwy tree as that normally
6913 * is intended to be looked up for incoming traffic from the
6914 * WAN side.
6915 * Therefore to handle NAT64 case we init keys here for both
6916 * lan-ext as well as ext-gwy trees.
6917 * In the state lookup we attempt a lookup on both trees if
6918 * first one does not return any result and return a match if
6919 * the match state's was created by NAT64 rule.
6920 */
6921 PF_ACPY(&key.ext_gwy.addr, pd->src, key.af_gwy);
6922 PF_ACPY(&key.gwy.addr, pd->dst, key.af_gwy);
6923 key.ext_gwy.xport.port = th->th_sport;
6924 key.gwy.xport.port = th->th_dport;
6925
6926 PF_ACPY(&key.lan.addr, pd->src, key.af_lan);
6927 PF_ACPY(&key.ext_lan.addr, pd->dst, key.af_lan);
6928 key.lan.xport.port = th->th_sport;
6929 key.ext_lan.xport.port = th->th_dport;
b0d623f7
A
6930
6931 STATE_LOOKUP();
6932
3e170ce0
A
6933 sk = (*state)->state_key;
6934 /*
6935 * In case of NAT64 the translation is first applied on the LAN
6936 * side. Therefore for stack's address family comparison
6937 * we use sk->af_lan.
6938 */
6939 if ((direction == sk->direction) && (pd->af == sk->af_lan)) {
b0d623f7
A
6940 src = &(*state)->src;
6941 dst = &(*state)->dst;
6942 } else {
6943 src = &(*state)->dst;
6944 dst = &(*state)->src;
6945 }
6946
3e170ce0
A
6947 if (src->state == PF_TCPS_PROXY_SRC) {
6948 if (direction != sk->direction) {
b0d623f7 6949 REASON_SET(reason, PFRES_SYNPROXY);
0a7de745 6950 return PF_SYNPROXY_DROP;
b0d623f7
A
6951 }
6952 if (th->th_flags & TH_SYN) {
3e170ce0 6953 if (ntohl(th->th_seq) != src->seqlo) {
b0d623f7 6954 REASON_SET(reason, PFRES_SYNPROXY);
0a7de745 6955 return PF_DROP;
b0d623f7
A
6956 }
6957 pf_send_tcp((*state)->rule.ptr, pd->af, pd->dst,
6958 pd->src, th->th_dport, th->th_sport,
3e170ce0 6959 src->seqhi, ntohl(th->th_seq) + 1,
0a7de745 6960 TH_SYN | TH_ACK, 0, src->mss, 0, 1,
b0d623f7
A
6961 0, NULL, NULL);
6962 REASON_SET(reason, PFRES_SYNPROXY);
0a7de745 6963 return PF_SYNPROXY_DROP;
b0d623f7 6964 } else if (!(th->th_flags & TH_ACK) ||
3e170ce0
A
6965 (ntohl(th->th_ack) != src->seqhi + 1) ||
6966 (ntohl(th->th_seq) != src->seqlo + 1)) {
b0d623f7 6967 REASON_SET(reason, PFRES_SYNPROXY);
0a7de745 6968 return PF_DROP;
b0d623f7
A
6969 } else if ((*state)->src_node != NULL &&
6970 pf_src_connlimit(state)) {
6971 REASON_SET(reason, PFRES_SRCLIMIT);
0a7de745
A
6972 return PF_DROP;
6973 } else {
3e170ce0 6974 src->state = PF_TCPS_PROXY_DST;
0a7de745 6975 }
b0d623f7 6976 }
3e170ce0 6977 if (src->state == PF_TCPS_PROXY_DST) {
b0d623f7
A
6978 struct pf_state_host *psrc, *pdst;
6979
6980 if (direction == PF_OUT) {
3e170ce0
A
6981 psrc = &sk->gwy;
6982 pdst = &sk->ext_gwy;
b0d623f7 6983 } else {
3e170ce0
A
6984 psrc = &sk->ext_lan;
6985 pdst = &sk->lan;
b0d623f7 6986 }
3e170ce0 6987 if (direction == sk->direction) {
0a7de745 6988 if (((th->th_flags & (TH_SYN | TH_ACK)) != TH_ACK) ||
3e170ce0
A
6989 (ntohl(th->th_ack) != src->seqhi + 1) ||
6990 (ntohl(th->th_seq) != src->seqlo + 1)) {
b0d623f7 6991 REASON_SET(reason, PFRES_SYNPROXY);
0a7de745 6992 return PF_DROP;
b0d623f7 6993 }
3e170ce0 6994 src->max_win = MAX(ntohs(th->th_win), 1);
0a7de745 6995 if (dst->seqhi == 1) {
3e170ce0 6996 dst->seqhi = htonl(random());
0a7de745 6997 }
b0d623f7 6998 pf_send_tcp((*state)->rule.ptr, pd->af, &psrc->addr,
b0d623f7 6999 &pdst->addr, psrc->xport.port, pdst->xport.port,
3e170ce0
A
7000 dst->seqhi, 0, TH_SYN, 0,
7001 src->mss, 0, 0, (*state)->tag, NULL, NULL);
b0d623f7 7002 REASON_SET(reason, PFRES_SYNPROXY);
0a7de745
A
7003 return PF_SYNPROXY_DROP;
7004 } else if (((th->th_flags & (TH_SYN | TH_ACK)) !=
7005 (TH_SYN | TH_ACK)) ||
3e170ce0 7006 (ntohl(th->th_ack) != dst->seqhi + 1)) {
b0d623f7 7007 REASON_SET(reason, PFRES_SYNPROXY);
0a7de745 7008 return PF_DROP;
b0d623f7 7009 } else {
3e170ce0
A
7010 dst->max_win = MAX(ntohs(th->th_win), 1);
7011 dst->seqlo = ntohl(th->th_seq);
b0d623f7
A
7012 pf_send_tcp((*state)->rule.ptr, pd->af, pd->dst,
7013 pd->src, th->th_dport, th->th_sport,
7014 ntohl(th->th_ack), ntohl(th->th_seq) + 1,
3e170ce0 7015 TH_ACK, src->max_win, 0, 0, 0,
b0d623f7
A
7016 (*state)->tag, NULL, NULL);
7017 pf_send_tcp((*state)->rule.ptr, pd->af, &psrc->addr,
b0d623f7 7018 &pdst->addr, psrc->xport.port, pdst->xport.port,
3e170ce0
A
7019 src->seqhi + 1, src->seqlo + 1,
7020 TH_ACK, dst->max_win, 0, 0, 1,
b0d623f7 7021 0, NULL, NULL);
3e170ce0
A
7022 src->seqdiff = dst->seqhi -
7023 src->seqlo;
7024 dst->seqdiff = src->seqhi -
7025 dst->seqlo;
7026 src->seqhi = src->seqlo +
7027 dst->max_win;
7028 dst->seqhi = dst->seqlo +
7029 src->max_win;
7030 src->wscale = dst->wscale = 0;
7031 src->state = dst->state =
b0d623f7
A
7032 TCPS_ESTABLISHED;
7033 REASON_SET(reason, PFRES_SYNPROXY);
0a7de745 7034 return PF_SYNPROXY_DROP;
b0d623f7
A
7035 }
7036 }
7037
0a7de745 7038 if (((th->th_flags & (TH_SYN | TH_ACK)) == TH_SYN) &&
b0d623f7
A
7039 dst->state >= TCPS_FIN_WAIT_2 &&
7040 src->state >= TCPS_FIN_WAIT_2) {
7041 if (pf_status.debug >= PF_DEBUG_MISC) {
7042 printf("pf: state reuse ");
7043 pf_print_state(*state);
7044 pf_print_flags(th->th_flags);
7045 printf("\n");
7046 }
7047 /* XXX make sure it's the same direction ?? */
3e170ce0 7048 src->state = dst->state = TCPS_CLOSED;
b0d623f7
A
7049 pf_unlink_state(*state);
7050 *state = NULL;
0a7de745 7051 return PF_DROP;
b0d623f7
A
7052 }
7053
39236c6e
A
7054 if ((th->th_flags & TH_SYN) == 0) {
7055 sws = (src->wscale & PF_WSCALE_FLAG) ?
7056 (src->wscale & PF_WSCALE_MASK) : TCP_MAX_WINSHIFT;
7057 dws = (dst->wscale & PF_WSCALE_FLAG) ?
7058 (dst->wscale & PF_WSCALE_MASK) : TCP_MAX_WINSHIFT;
0a7de745 7059 } else {
b0d623f7 7060 sws = dws = 0;
0a7de745 7061 }
b0d623f7
A
7062
7063 /*
7064 * Sequence tracking algorithm from Guido van Rooij's paper:
7065 * http://www.madison-gurkha.com/publications/tcp_filtering/
7066 * tcp_filtering.ps
7067 */
7068
7069 orig_seq = seq = ntohl(th->th_seq);
7070 if (src->seqlo == 0) {
7071 /* First packet from this end. Set its state */
7072
7073 if ((pd->flags & PFDESC_TCP_NORM || dst->scrub) &&
7074 src->scrub == NULL) {
5ba3f43e 7075 if (pf_normalize_tcp_init(pbuf, off, pd, th, src, dst)) {
b0d623f7 7076 REASON_SET(reason, PFRES_MEMORY);
0a7de745 7077 return PF_DROP;
b0d623f7
A
7078 }
7079 }
7080
7081 /* Deferred generation of sequence number modulator */
7082 if (dst->seqdiff && !src->seqdiff) {
7083 /* use random iss for the TCP server */
0a7de745 7084 while ((src->seqdiff = random() - seq) == 0) {
b0d623f7 7085 ;
0a7de745 7086 }
b0d623f7
A
7087 ack = ntohl(th->th_ack) - dst->seqdiff;
7088 pf_change_a(&th->th_seq, &th->th_sum, htonl(seq +
7089 src->seqdiff), 0);
7090 pf_change_a(&th->th_ack, &th->th_sum, htonl(ack), 0);
0a7de745 7091 copyback = off + sizeof(*th);
b0d623f7
A
7092 } else {
7093 ack = ntohl(th->th_ack);
7094 }
7095
7096 end = seq + pd->p_len;
7097 if (th->th_flags & TH_SYN) {
7098 end++;
7099 if (dst->wscale & PF_WSCALE_FLAG) {
5ba3f43e
A
7100 src->wscale = pf_get_wscale(pbuf, off,
7101 th->th_off, pd->af);
b0d623f7
A
7102 if (src->wscale & PF_WSCALE_FLAG) {
7103 /*
7104 * Remove scale factor from initial
7105 * window
7106 */
7107 sws = src->wscale & PF_WSCALE_MASK;
7108 win = ((u_int32_t)win + (1 << sws) - 1)
7109 >> sws;
7110 dws = dst->wscale & PF_WSCALE_MASK;
7111 } else {
b7266188 7112 /*
b7266188
A
7113 * Window scale negotiation has failed,
7114 * therefore we must restore the window
7115 * scale in the state record that we
7116 * optimistically removed in
7117 * pf_test_rule(). Care is required to
7118 * prevent arithmetic overflow from
7119 * zeroing the window when it's
316670eb 7120 * truncated down to 16-bits.
b7266188 7121 */
d1ecb069
A
7122 u_int32_t max_win = dst->max_win;
7123 max_win <<=
7124 dst->wscale & PF_WSCALE_MASK;
7125 dst->max_win = MIN(0xffff, max_win);
b0d623f7
A
7126 /* in case of a retrans SYN|ACK */
7127 dst->wscale = 0;
7128 }
7129 }
7130 }
0a7de745 7131 if (th->th_flags & TH_FIN) {
b0d623f7 7132 end++;
0a7de745 7133 }
b0d623f7
A
7134
7135 src->seqlo = seq;
0a7de745 7136 if (src->state < TCPS_SYN_SENT) {
b0d623f7 7137 src->state = TCPS_SYN_SENT;
0a7de745 7138 }
b0d623f7
A
7139
7140 /*
7141 * May need to slide the window (seqhi may have been set by
7142 * the crappy stack check or if we picked up the connection
7143 * after establishment)
7144 */
b7266188
A
7145 if (src->seqhi == 1 ||
7146 SEQ_GEQ(end + MAX(1, (u_int32_t)dst->max_win << dws),
0a7de745 7147 src->seqhi)) {
b7266188 7148 src->seqhi = end + MAX(1, (u_int32_t)dst->max_win << dws);
0a7de745
A
7149 }
7150 if (win > src->max_win) {
b0d623f7 7151 src->max_win = win;
0a7de745 7152 }
b0d623f7
A
7153 } else {
7154 ack = ntohl(th->th_ack) - dst->seqdiff;
7155 if (src->seqdiff) {
7156 /* Modulate sequence numbers */
7157 pf_change_a(&th->th_seq, &th->th_sum, htonl(seq +
7158 src->seqdiff), 0);
7159 pf_change_a(&th->th_ack, &th->th_sum, htonl(ack), 0);
0a7de745 7160 copyback = off + sizeof(*th);
b0d623f7
A
7161 }
7162 end = seq + pd->p_len;
0a7de745 7163 if (th->th_flags & TH_SYN) {
b0d623f7 7164 end++;
0a7de745
A
7165 }
7166 if (th->th_flags & TH_FIN) {
b0d623f7 7167 end++;
0a7de745 7168 }
b0d623f7
A
7169 }
7170
7171 if ((th->th_flags & TH_ACK) == 0) {
7172 /* Let it pass through the ack skew check */
7173 ack = dst->seqlo;
7174 } else if ((ack == 0 &&
0a7de745 7175 (th->th_flags & (TH_ACK | TH_RST)) == (TH_ACK | TH_RST)) ||
b0d623f7
A
7176 /* broken tcp stacks do not set ack */
7177 (dst->state < TCPS_SYN_SENT)) {
7178 /*
7179 * Many stacks (ours included) will set the ACK number in an
7180 * FIN|ACK if the SYN times out -- no sequence to ACK.
7181 */
7182 ack = dst->seqlo;
7183 }
7184
7185 if (seq == end) {
7186 /* Ease sequencing restrictions on no data packets */
7187 seq = src->seqlo;
7188 end = seq;
7189 }
7190
7191 ackskew = dst->seqlo - ack;
7192
7193
7194 /*
7195 * Need to demodulate the sequence numbers in any TCP SACK options
7196 * (Selective ACK). We could optionally validate the SACK values
7197 * against the current ACK window, either forwards or backwards, but
7198 * I'm not confident that SACK has been implemented properly
7199 * everywhere. It wouldn't surprise me if several stacks accidently
7200 * SACK too far backwards of previously ACKed data. There really aren't
7201 * any security implications of bad SACKing unless the target stack
7202 * doesn't validate the option length correctly. Someone trying to
7203 * spoof into a TCP connection won't bother blindly sending SACK
7204 * options anyway.
7205 */
0a7de745 7206 if (dst->seqdiff && (th->th_off << 2) > (int)sizeof(struct tcphdr)) {
5ba3f43e 7207 copyback = pf_modulate_sack(pbuf, off, pd, th, dst);
b0d623f7
A
7208 if (copyback == -1) {
7209 REASON_SET(reason, PFRES_MEMORY);
0a7de745 7210 return PF_DROP;
b0d623f7
A
7211 }
7212
0a7de745 7213 pbuf = pd->mp; // XXXSCW: Why?
b0d623f7
A
7214 }
7215
7216
0a7de745 7217#define MAXACKWINDOW (0xffff + 1500) /* 1500 is an arbitrary fudge factor */
b0d623f7
A
7218 if (SEQ_GEQ(src->seqhi, end) &&
7219 /* Last octet inside other's window space */
b7266188 7220 SEQ_GEQ(seq, src->seqlo - ((u_int32_t)dst->max_win << dws)) &&
b0d623f7
A
7221 /* Retrans: not more than one window back */
7222 (ackskew >= -MAXACKWINDOW) &&
7223 /* Acking not more than one reassembled fragment backwards */
7224 (ackskew <= (MAXACKWINDOW << sws)) &&
7225 /* Acking not more than one window forward */
7226 ((th->th_flags & TH_RST) == 0 || orig_seq == src->seqlo ||
7227 (orig_seq == src->seqlo + 1) || (orig_seq + 1 == src->seqlo) ||
7228 (pd->flags & PFDESC_IP_REAS) == 0)) {
0a7de745 7229 /* Require an exact/+1 sequence match on resets when possible */
b0d623f7
A
7230
7231 if (dst->scrub || src->scrub) {
5ba3f43e 7232 if (pf_normalize_tcp_stateful(pbuf, off, pd, reason, th,
0a7de745
A
7233 *state, src, dst, &copyback)) {
7234 return PF_DROP;
7235 }
b0d623f7 7236
0a7de745 7237 pbuf = pd->mp; // XXXSCW: Why?
b0d623f7
A
7238 }
7239
7240 /* update max window */
0a7de745 7241 if (src->max_win < win) {
b0d623f7 7242 src->max_win = win;
0a7de745 7243 }
b0d623f7 7244 /* synchronize sequencing */
0a7de745 7245 if (SEQ_GT(end, src->seqlo)) {
b0d623f7 7246 src->seqlo = end;
0a7de745 7247 }
b0d623f7 7248 /* slide the window of what the other end can send */
0a7de745 7249 if (SEQ_GEQ(ack + ((u_int32_t)win << sws), dst->seqhi)) {
b7266188 7250 dst->seqhi = ack + MAX(((u_int32_t)win << sws), 1);
0a7de745 7251 }
b0d623f7
A
7252
7253 /* update states */
0a7de745
A
7254 if (th->th_flags & TH_SYN) {
7255 if (src->state < TCPS_SYN_SENT) {
b0d623f7 7256 src->state = TCPS_SYN_SENT;
0a7de745
A
7257 }
7258 }
7259 if (th->th_flags & TH_FIN) {
7260 if (src->state < TCPS_CLOSING) {
b0d623f7 7261 src->state = TCPS_CLOSING;
0a7de745
A
7262 }
7263 }
b0d623f7
A
7264 if (th->th_flags & TH_ACK) {
7265 if (dst->state == TCPS_SYN_SENT) {
7266 dst->state = TCPS_ESTABLISHED;
7267 if (src->state == TCPS_ESTABLISHED &&
7268 (*state)->src_node != NULL &&
7269 pf_src_connlimit(state)) {
7270 REASON_SET(reason, PFRES_SRCLIMIT);
0a7de745 7271 return PF_DROP;
b0d623f7 7272 }
0a7de745 7273 } else if (dst->state == TCPS_CLOSING) {
b0d623f7 7274 dst->state = TCPS_FIN_WAIT_2;
0a7de745 7275 }
b0d623f7 7276 }
0a7de745 7277 if (th->th_flags & TH_RST) {
b0d623f7 7278 src->state = dst->state = TCPS_TIME_WAIT;
0a7de745 7279 }
b0d623f7
A
7280
7281 /* update expire time */
7282 (*state)->expire = pf_time_second();
7283 if (src->state >= TCPS_FIN_WAIT_2 &&
0a7de745 7284 dst->state >= TCPS_FIN_WAIT_2) {
b0d623f7 7285 (*state)->timeout = PFTM_TCP_CLOSED;
0a7de745
A
7286 } else if (src->state >= TCPS_CLOSING &&
7287 dst->state >= TCPS_CLOSING) {
b0d623f7 7288 (*state)->timeout = PFTM_TCP_FIN_WAIT;
0a7de745
A
7289 } else if (src->state < TCPS_ESTABLISHED ||
7290 dst->state < TCPS_ESTABLISHED) {
b0d623f7 7291 (*state)->timeout = PFTM_TCP_OPENING;
0a7de745
A
7292 } else if (src->state >= TCPS_CLOSING ||
7293 dst->state >= TCPS_CLOSING) {
b0d623f7 7294 (*state)->timeout = PFTM_TCP_CLOSING;
0a7de745 7295 } else {
b0d623f7 7296 (*state)->timeout = PFTM_TCP_ESTABLISHED;
0a7de745 7297 }
b0d623f7
A
7298
7299 /* Fall through to PASS packet */
b0d623f7
A
7300 } else if ((dst->state < TCPS_SYN_SENT ||
7301 dst->state >= TCPS_FIN_WAIT_2 || src->state >= TCPS_FIN_WAIT_2) &&
7302 SEQ_GEQ(src->seqhi + MAXACKWINDOW, end) &&
7303 /* Within a window forward of the originating packet */
7304 SEQ_GEQ(seq, src->seqlo - MAXACKWINDOW)) {
0a7de745 7305 /* Within a window backward of the originating packet */
b0d623f7
A
7306
7307 /*
7308 * This currently handles three situations:
7309 * 1) Stupid stacks will shotgun SYNs before their peer
7310 * replies.
7311 * 2) When PF catches an already established stream (the
7312 * firewall rebooted, the state table was flushed, routes
7313 * changed...)
7314 * 3) Packets get funky immediately after the connection
7315 * closes (this should catch Solaris spurious ACK|FINs
7316 * that web servers like to spew after a close)
7317 *
7318 * This must be a little more careful than the above code
7319 * since packet floods will also be caught here. We don't
7320 * update the TTL here to mitigate the damage of a packet
7321 * flood and so the same code can handle awkward establishment
7322 * and a loosened connection close.
7323 * In the establishment case, a correct peer response will
7324 * validate the connection, go through the normal state code
7325 * and keep updating the state TTL.
7326 */
7327
7328 if (pf_status.debug >= PF_DEBUG_MISC) {
7329 printf("pf: loose state match: ");
7330 pf_print_state(*state);
7331 pf_print_flags(th->th_flags);
7332 printf(" seq=%u (%u) ack=%u len=%u ackskew=%d "
7333 "pkts=%llu:%llu dir=%s,%s\n", seq, orig_seq, ack,
7334 pd->p_len, ackskew, (*state)->packets[0],
7335 (*state)->packets[1],
7336 direction == PF_IN ? "in" : "out",
3e170ce0 7337 direction == sk->direction ?
b0d623f7
A
7338 "fwd" : "rev");
7339 }
7340
7341 if (dst->scrub || src->scrub) {
5ba3f43e 7342 if (pf_normalize_tcp_stateful(pbuf, off, pd, reason, th,
0a7de745
A
7343 *state, src, dst, &copyback)) {
7344 return PF_DROP;
7345 }
7346 pbuf = pd->mp; // XXXSCW: Why?
b0d623f7
A
7347 }
7348
7349 /* update max window */
0a7de745 7350 if (src->max_win < win) {
b0d623f7 7351 src->max_win = win;
0a7de745 7352 }
b0d623f7 7353 /* synchronize sequencing */
0a7de745 7354 if (SEQ_GT(end, src->seqlo)) {
b0d623f7 7355 src->seqlo = end;
0a7de745 7356 }
b0d623f7 7357 /* slide the window of what the other end can send */
0a7de745 7358 if (SEQ_GEQ(ack + ((u_int32_t)win << sws), dst->seqhi)) {
b7266188 7359 dst->seqhi = ack + MAX(((u_int32_t)win << sws), 1);
0a7de745 7360 }
b0d623f7
A
7361
7362 /*
7363 * Cannot set dst->seqhi here since this could be a shotgunned
7364 * SYN and not an already established connection.
7365 */
7366
0a7de745
A
7367 if (th->th_flags & TH_FIN) {
7368 if (src->state < TCPS_CLOSING) {
b0d623f7 7369 src->state = TCPS_CLOSING;
0a7de745
A
7370 }
7371 }
7372 if (th->th_flags & TH_RST) {
b0d623f7 7373 src->state = dst->state = TCPS_TIME_WAIT;
0a7de745 7374 }
b0d623f7
A
7375
7376 /* Fall through to PASS packet */
b0d623f7 7377 } else {
3e170ce0
A
7378 if (dst->state == TCPS_SYN_SENT &&
7379 src->state == TCPS_SYN_SENT) {
b0d623f7 7380 /* Send RST for state mismatches during handshake */
0a7de745 7381 if (!(th->th_flags & TH_RST)) {
b0d623f7
A
7382 pf_send_tcp((*state)->rule.ptr, pd->af,
7383 pd->dst, pd->src, th->th_dport,
7384 th->th_sport, ntohl(th->th_ack), 0,
7385 TH_RST, 0, 0,
7386 (*state)->rule.ptr->return_ttl, 1, 0,
7387 pd->eh, kif->pfik_ifp);
0a7de745 7388 }
b0d623f7
A
7389 src->seqlo = 0;
7390 src->seqhi = 1;
7391 src->max_win = 1;
7392 } else if (pf_status.debug >= PF_DEBUG_MISC) {
7393 printf("pf: BAD state: ");
7394 pf_print_state(*state);
7395 pf_print_flags(th->th_flags);
39236c6e
A
7396 printf("\n seq=%u (%u) ack=%u len=%u ackskew=%d "
7397 "sws=%u dws=%u pkts=%llu:%llu dir=%s,%s\n",
b0d623f7 7398 seq, orig_seq, ack, pd->p_len, ackskew,
39236c6e 7399 (unsigned int)sws, (unsigned int)dws,
b0d623f7
A
7400 (*state)->packets[0], (*state)->packets[1],
7401 direction == PF_IN ? "in" : "out",
3e170ce0 7402 direction == sk->direction ?
b0d623f7
A
7403 "fwd" : "rev");
7404 printf("pf: State failure on: %c %c %c %c | %c %c\n",
7405 SEQ_GEQ(src->seqhi, end) ? ' ' : '1',
b7266188
A
7406 SEQ_GEQ(seq,
7407 src->seqlo - ((u_int32_t)dst->max_win << dws)) ?
b0d623f7
A
7408 ' ': '2',
7409 (ackskew >= -MAXACKWINDOW) ? ' ' : '3',
7410 (ackskew <= (MAXACKWINDOW << sws)) ? ' ' : '4',
7411 SEQ_GEQ(src->seqhi + MAXACKWINDOW, end) ?' ' :'5',
7412 SEQ_GEQ(seq, src->seqlo - MAXACKWINDOW) ?' ' :'6');
7413 }
7414 REASON_SET(reason, PFRES_BADSTATE);
0a7de745 7415 return PF_DROP;
b0d623f7
A
7416 }
7417
7418 /* Any packets which have gotten here are to be passed */
7419
3e170ce0
A
7420 if (sk->app_state &&
7421 sk->app_state->handler) {
7422 sk->app_state->handler(*state, direction,
b0d623f7
A
7423 off + (th->th_off << 2), pd, kif);
7424 if (pd->lmw < 0) {
7425 REASON_SET(reason, PFRES_MEMORY);
0a7de745 7426 return PF_DROP;
b0d623f7 7427 }
0a7de745 7428 pbuf = pd->mp; // XXXSCW: Why?
b0d623f7
A
7429 }
7430
7431 /* translate source/destination address, if necessary */
3e170ce0
A
7432 if (STATE_TRANSLATE(sk)) {
7433 pd->naf = (pd->af == sk->af_lan) ? sk->af_gwy : sk->af_lan;
7434
7435 if (direction == PF_OUT) {
b0d623f7 7436 pf_change_ap(direction, pd->mp, pd->src, &th->th_sport,
0a7de745
A
7437 pd->ip_sum, &th->th_sum, &sk->gwy.addr,
7438 sk->gwy.xport.port, 0, pd->af, pd->naf, 1);
3e170ce0
A
7439 } else {
7440 if (pd->af != pd->naf) {
7441 if (pd->af == sk->af_gwy) {
7442 pf_change_ap(direction, pd->mp, pd->dst,
0a7de745
A
7443 &th->th_dport, pd->ip_sum,
7444 &th->th_sum, &sk->lan.addr,
7445 sk->lan.xport.port, 0,
7446 pd->af, pd->naf, 0);
3e170ce0
A
7447
7448 pf_change_ap(direction, pd->mp, pd->src,
0a7de745
A
7449 &th->th_sport, pd->ip_sum,
7450 &th->th_sum, &sk->ext_lan.addr,
7451 th->th_sport, 0, pd->af,
7452 pd->naf, 0);
3e170ce0
A
7453 } else {
7454 pf_change_ap(direction, pd->mp, pd->dst,
0a7de745
A
7455 &th->th_dport, pd->ip_sum,
7456 &th->th_sum, &sk->ext_gwy.addr,
7457 th->th_dport, 0, pd->af,
7458 pd->naf, 0);
3e170ce0
A
7459
7460 pf_change_ap(direction, pd->mp, pd->src,
0a7de745
A
7461 &th->th_sport, pd->ip_sum,
7462 &th->th_sum, &sk->gwy.addr,
7463 sk->gwy.xport.port, 0, pd->af,
7464 pd->naf, 0);
3e170ce0
A
7465 }
7466 } else {
7467 pf_change_ap(direction, pd->mp, pd->dst,
0a7de745
A
7468 &th->th_dport, pd->ip_sum,
7469 &th->th_sum, &sk->lan.addr,
7470 sk->lan.xport.port, 0, pd->af,
7471 pd->naf, 1);
3e170ce0
A
7472 }
7473 }
7474
0a7de745 7475 copyback = off + sizeof(*th);
b0d623f7
A
7476 }
7477
7478 if (copyback) {
5ba3f43e 7479 if (pf_lazy_makewritable(pd, pbuf, copyback) == NULL) {
b0d623f7 7480 REASON_SET(reason, PFRES_MEMORY);
0a7de745 7481 return PF_DROP;
b0d623f7
A
7482 }
7483
7484 /* Copyback sequence modulation or stateful scrub changes */
0a7de745 7485 pbuf_copy_back(pbuf, off, sizeof(*th), th);
b0d623f7 7486
0a7de745
A
7487 if (sk->af_lan != sk->af_gwy) {
7488 return pf_do_nat64(sk, pd, pbuf, off);
7489 }
3e170ce0 7490 }
0a7de745 7491 return PF_PASS;
b0d623f7
A
7492}
7493
7494static int
7495pf_test_state_udp(struct pf_state **state, int direction, struct pfi_kif *kif,
5ba3f43e 7496 pbuf_t *pbuf, int off, void *h, struct pf_pdesc *pd, u_short *reason)
b0d623f7
A
7497{
7498#pragma unused(h)
0a7de745
A
7499 struct pf_state_peer *src, *dst;
7500 struct pf_state_key_cmp key;
7501 struct pf_state_key *sk;
7502 struct udphdr *uh = pd->hdr.udp;
b0d623f7 7503 struct pf_app_state as;
3e170ce0 7504 int action, extfilter;
b0d623f7
A
7505 key.app_state = 0;
7506 key.proto_variant = PF_EXTFILTER_APD;
b0d623f7 7507
b0d623f7 7508 key.proto = IPPROTO_UDP;
3e170ce0
A
7509 key.af_lan = key.af_gwy = pd->af;
7510
7511 /*
7512 * For NAT64 the first time rule search and state creation
7513 * is done on the incoming side only.
7514 * Once the state gets created, NAT64's LAN side (ipv6) will
7515 * not be able to find the state in ext-gwy tree as that normally
7516 * is intended to be looked up for incoming traffic from the
7517 * WAN side.
7518 * Therefore to handle NAT64 case we init keys here for both
7519 * lan-ext as well as ext-gwy trees.
7520 * In the state lookup we attempt a lookup on both trees if
7521 * first one does not return any result and return a match if
7522 * the match state's was created by NAT64 rule.
7523 */
7524 PF_ACPY(&key.ext_gwy.addr, pd->src, key.af_gwy);
7525 PF_ACPY(&key.gwy.addr, pd->dst, key.af_gwy);
7526 key.ext_gwy.xport.port = uh->uh_sport;
7527 key.gwy.xport.port = uh->uh_dport;
7528
7529 PF_ACPY(&key.lan.addr, pd->src, key.af_lan);
7530 PF_ACPY(&key.ext_lan.addr, pd->dst, key.af_lan);
7531 key.lan.xport.port = uh->uh_sport;
7532 key.ext_lan.xport.port = uh->uh_dport;
b0d623f7 7533
b7266188
A
7534 if (ntohs(uh->uh_sport) == PF_IKE_PORT &&
7535 ntohs(uh->uh_dport) == PF_IKE_PORT) {
b0d623f7 7536 struct pf_ike_hdr ike;
0a7de745 7537 size_t plen = pbuf->pb_packet_len - off - sizeof(*uh);
b0d623f7
A
7538 if (plen < PF_IKE_PACKET_MINSIZE) {
7539 DPFPRINTF(PF_DEBUG_MISC,
7540 ("pf: IKE message too small.\n"));
0a7de745 7541 return PF_DROP;
b0d623f7
A
7542 }
7543
0a7de745
A
7544 if (plen > sizeof(ike)) {
7545 plen = sizeof(ike);
7546 }
7547 pbuf_copy_data(pbuf, off + sizeof(*uh), plen, &ike);
b0d623f7
A
7548
7549 if (ike.initiator_cookie) {
7550 key.app_state = &as;
7551 as.compare_lan_ext = pf_ike_compare;
7552 as.compare_ext_gwy = pf_ike_compare;
7553 as.u.ike.cookie = ike.initiator_cookie;
7554 } else {
7555 /*
7556 * <http://tools.ietf.org/html/\
7557 * draft-ietf-ipsec-nat-t-ike-01>
7558 * Support non-standard NAT-T implementations that
7559 * push the ESP packet over the top of the IKE packet.
7560 * Do not drop packet.
7561 */
7562 DPFPRINTF(PF_DEBUG_MISC,
7563 ("pf: IKE initiator cookie = 0.\n"));
7564 }
7565 }
7566
3e170ce0 7567 *state = pf_find_state(kif, &key, direction);
b0d623f7
A
7568
7569 if (!key.app_state && *state == 0) {
7570 key.proto_variant = PF_EXTFILTER_AD;
3e170ce0 7571 *state = pf_find_state(kif, &key, direction);
b0d623f7
A
7572 }
7573
7574 if (!key.app_state && *state == 0) {
7575 key.proto_variant = PF_EXTFILTER_EI;
3e170ce0 7576 *state = pf_find_state(kif, &key, direction);
b0d623f7
A
7577 }
7578
39236c6e
A
7579 /* similar to STATE_LOOKUP() */
7580 if (*state != NULL && pd != NULL && !(pd->pktflags & PKTF_FLOW_ID)) {
7581 pd->flowsrc = (*state)->state_key->flowsrc;
316670eb 7582 pd->flowhash = (*state)->state_key->flowhash;
39236c6e
A
7583 if (pd->flowhash != 0) {
7584 pd->pktflags |= PKTF_FLOW_ID;
7585 pd->pktflags &= ~PKTF_FLOW_ADV;
7586 }
7587 }
316670eb 7588
0a7de745
A
7589 if (pf_state_lookup_aux(state, kif, direction, &action)) {
7590 return action;
7591 }
b0d623f7 7592
3e170ce0
A
7593 sk = (*state)->state_key;
7594
7595 /*
7596 * In case of NAT64 the translation is first applied on the LAN
7597 * side. Therefore for stack's address family comparison
7598 * we use sk->af_lan.
7599 */
7600 if ((direction == sk->direction) && (pd->af == sk->af_lan)) {
b0d623f7
A
7601 src = &(*state)->src;
7602 dst = &(*state)->dst;
7603 } else {
7604 src = &(*state)->dst;
7605 dst = &(*state)->src;
7606 }
7607
7608 /* update states */
0a7de745 7609 if (src->state < PFUDPS_SINGLE) {
b0d623f7 7610 src->state = PFUDPS_SINGLE;
0a7de745
A
7611 }
7612 if (dst->state == PFUDPS_SINGLE) {
b0d623f7 7613 dst->state = PFUDPS_MULTIPLE;
0a7de745 7614 }
b0d623f7
A
7615
7616 /* update expire time */
7617 (*state)->expire = pf_time_second();
0a7de745 7618 if (src->state == PFUDPS_MULTIPLE && dst->state == PFUDPS_MULTIPLE) {
b0d623f7 7619 (*state)->timeout = PFTM_UDP_MULTIPLE;
0a7de745 7620 } else {
b0d623f7 7621 (*state)->timeout = PFTM_UDP_SINGLE;
0a7de745 7622 }
b0d623f7 7623
3e170ce0 7624 extfilter = sk->proto_variant;
b0d623f7 7625 if (extfilter > PF_EXTFILTER_APD) {
3e170ce0
A
7626 if (direction == PF_OUT) {
7627 sk->ext_lan.xport.port = key.ext_lan.xport.port;
0a7de745 7628 if (extfilter > PF_EXTFILTER_AD) {
3e170ce0 7629 PF_ACPY(&sk->ext_lan.addr, &key.ext_lan.addr,
0a7de745
A
7630 key.af_lan);
7631 }
3e170ce0
A
7632 } else {
7633 sk->ext_gwy.xport.port = key.ext_gwy.xport.port;
0a7de745 7634 if (extfilter > PF_EXTFILTER_AD) {
3e170ce0 7635 PF_ACPY(&sk->ext_gwy.addr, &key.ext_gwy.addr,
0a7de745
A
7636 key.af_gwy);
7637 }
3e170ce0 7638 }
b0d623f7
A
7639 }
7640
3e170ce0
A
7641 if (sk->app_state && sk->app_state->handler) {
7642 sk->app_state->handler(*state, direction, off + uh->uh_ulen,
0a7de745 7643 pd, kif);
b7266188
A
7644 if (pd->lmw < 0) {
7645 REASON_SET(reason, PFRES_MEMORY);
0a7de745 7646 return PF_DROP;
b7266188 7647 }
0a7de745 7648 pbuf = pd->mp; // XXXSCW: Why?
b0d623f7 7649 }
b0d623f7
A
7650
7651 /* translate source/destination address, if necessary */
3e170ce0 7652 if (STATE_TRANSLATE(sk)) {
0a7de745 7653 if (pf_lazy_makewritable(pd, pbuf, off + sizeof(*uh)) == NULL) {
d1ecb069 7654 REASON_SET(reason, PFRES_MEMORY);
0a7de745 7655 return PF_DROP;
d1ecb069 7656 }
b0d623f7 7657
3e170ce0
A
7658 pd->naf = (pd->af == sk->af_lan) ? sk->af_gwy : sk->af_lan;
7659
7660 if (direction == PF_OUT) {
b0d623f7 7661 pf_change_ap(direction, pd->mp, pd->src, &uh->uh_sport,
0a7de745
A
7662 pd->ip_sum, &uh->uh_sum, &sk->gwy.addr,
7663 sk->gwy.xport.port, 1, pd->af, pd->naf, 1);
3e170ce0
A
7664 } else {
7665 if (pd->af != pd->naf) {
3e170ce0
A
7666 if (pd->af == sk->af_gwy) {
7667 pf_change_ap(direction, pd->mp, pd->dst,
0a7de745
A
7668 &uh->uh_dport, pd->ip_sum,
7669 &uh->uh_sum, &sk->lan.addr,
7670 sk->lan.xport.port, 1,
7671 pd->af, pd->naf, 0);
3e170ce0
A
7672
7673 pf_change_ap(direction, pd->mp, pd->src,
0a7de745
A
7674 &uh->uh_sport, pd->ip_sum,
7675 &uh->uh_sum, &sk->ext_lan.addr,
7676 uh->uh_sport, 1, pd->af,
7677 pd->naf, 0);
3e170ce0
A
7678 } else {
7679 pf_change_ap(direction, pd->mp, pd->dst,
0a7de745
A
7680 &uh->uh_dport, pd->ip_sum,
7681 &uh->uh_sum, &sk->ext_gwy.addr,
7682 uh->uh_dport, 1, pd->af,
7683 pd->naf, 0);
3e170ce0
A
7684
7685 pf_change_ap(direction, pd->mp, pd->src,
0a7de745
A
7686 &uh->uh_sport, pd->ip_sum,
7687 &uh->uh_sum, &sk->gwy.addr,
7688 sk->gwy.xport.port, 1, pd->af,
7689 pd->naf, 0);
3e170ce0
A
7690 }
7691 } else {
7692 pf_change_ap(direction, pd->mp, pd->dst,
0a7de745
A
7693 &uh->uh_dport, pd->ip_sum,
7694 &uh->uh_sum, &sk->lan.addr,
7695 sk->lan.xport.port, 1,
7696 pd->af, pd->naf, 1);
3e170ce0
A
7697 }
7698 }
7699
0a7de745
A
7700 pbuf_copy_back(pbuf, off, sizeof(*uh), uh);
7701 if (sk->af_lan != sk->af_gwy) {
7702 return pf_do_nat64(sk, pd, pbuf, off);
7703 }
b0d623f7 7704 }
0a7de745 7705 return PF_PASS;
b0d623f7
A
7706}
7707
7708static int
7709pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
5ba3f43e 7710 pbuf_t *pbuf, int off, void *h, struct pf_pdesc *pd, u_short *reason)
b0d623f7
A
7711{
7712#pragma unused(h)
0a7de745
A
7713 struct pf_addr *saddr = pd->src, *daddr = pd->dst;
7714 struct in_addr srcv4_inaddr = saddr->v4addr;
7715 u_int16_t icmpid = 0, *icmpsum = NULL;
7716 u_int8_t icmptype = 0;
7717 int state_icmp = 0;
b0d623f7 7718 struct pf_state_key_cmp key;
0a7de745 7719 struct pf_state_key *sk;
b0d623f7 7720
b0d623f7
A
7721 struct pf_app_state as;
7722 key.app_state = 0;
b0d623f7 7723
3e170ce0
A
7724 pd->off = off;
7725
b0d623f7
A
7726 switch (pd->proto) {
7727#if INET
7728 case IPPROTO_ICMP:
7729 icmptype = pd->hdr.icmp->icmp_type;
7730 icmpid = pd->hdr.icmp->icmp_id;
7731 icmpsum = &pd->hdr.icmp->icmp_cksum;
7732
0a7de745 7733 if (ICMP_ERRORTYPE(icmptype)) {
b0d623f7 7734 state_icmp++;
0a7de745 7735 }
b0d623f7
A
7736 break;
7737#endif /* INET */
7738#if INET6
7739 case IPPROTO_ICMPV6:
7740 icmptype = pd->hdr.icmp6->icmp6_type;
7741 icmpid = pd->hdr.icmp6->icmp6_id;
7742 icmpsum = &pd->hdr.icmp6->icmp6_cksum;
7743
0a7de745 7744 if (ICMP6_ERRORTYPE(icmptype)) {
b0d623f7 7745 state_icmp++;
0a7de745 7746 }
b0d623f7
A
7747 break;
7748#endif /* INET6 */
7749 }
7750
7751 if (!state_icmp) {
b0d623f7
A
7752 /*
7753 * ICMP query/reply message not related to a TCP/UDP packet.
7754 * Search for an ICMP state.
7755 */
3e170ce0
A
7756 /*
7757 * NAT64 requires protocol translation between ICMPv4
7758 * and ICMPv6. TCP and UDP do not require protocol
7759 * translation. To avoid adding complexity just to
5ba3f43e 7760 * handle ICMP(v4addr/v6addr), we always lookup for
3e170ce0
A
7761 * proto = IPPROTO_ICMP on both LAN and WAN side
7762 */
7763 key.proto = IPPROTO_ICMP;
7764 key.af_lan = key.af_gwy = pd->af;
7765
7766 PF_ACPY(&key.ext_gwy.addr, pd->src, key.af_gwy);
7767 PF_ACPY(&key.gwy.addr, pd->dst, key.af_gwy);
7768 key.ext_gwy.xport.port = 0;
7769 key.gwy.xport.port = icmpid;
7770
7771 PF_ACPY(&key.lan.addr, pd->src, key.af_lan);
7772 PF_ACPY(&key.ext_lan.addr, pd->dst, key.af_lan);
7773 key.lan.xport.port = icmpid;
7774 key.ext_lan.xport.port = 0;
b0d623f7
A
7775
7776 STATE_LOOKUP();
7777
3e170ce0 7778 sk = (*state)->state_key;
b0d623f7
A
7779 (*state)->expire = pf_time_second();
7780 (*state)->timeout = PFTM_ICMP_ERROR_REPLY;
7781
7782 /* translate source/destination address, if necessary */
3e170ce0
A
7783 if (STATE_TRANSLATE(sk)) {
7784 pd->naf = (pd->af == sk->af_lan) ?
0a7de745 7785 sk->af_gwy : sk->af_lan;
b0d623f7
A
7786 if (direction == PF_OUT) {
7787 switch (pd->af) {
7788#if INET
7789 case AF_INET:
5ba3f43e 7790 pf_change_a(&saddr->v4addr.s_addr,
b0d623f7 7791 pd->ip_sum,
5ba3f43e 7792 sk->gwy.addr.v4addr.s_addr, 0);
b0d623f7
A
7793 pd->hdr.icmp->icmp_cksum =
7794 pf_cksum_fixup(
0a7de745
A
7795 pd->hdr.icmp->icmp_cksum, icmpid,
7796 sk->gwy.xport.port, 0);
b0d623f7 7797 pd->hdr.icmp->icmp_id =
0a7de745 7798 sk->gwy.xport.port;
5ba3f43e 7799 if (pf_lazy_makewritable(pd, pbuf,
0a7de745
A
7800 off + ICMP_MINLEN) == NULL) {
7801 return PF_DROP;
7802 }
5ba3f43e 7803 pbuf_copy_back(pbuf, off, ICMP_MINLEN,
b0d623f7
A
7804 pd->hdr.icmp);
7805 break;
7806#endif /* INET */
7807#if INET6
7808 case AF_INET6:
7809 pf_change_a6(saddr,
7810 &pd->hdr.icmp6->icmp6_cksum,
3e170ce0 7811 &sk->gwy.addr, 0);
cb323159 7812 if (pf_lazy_makewritable(pd, pbuf,
0a7de745
A
7813 off + sizeof(struct icmp6_hdr)) ==
7814 NULL) {
7815 return PF_DROP;
7816 }
5ba3f43e 7817 pbuf_copy_back(pbuf, off,
0a7de745 7818 sizeof(struct icmp6_hdr),
b0d623f7
A
7819 pd->hdr.icmp6);
7820 break;
7821#endif /* INET6 */
7822 }
7823 } else {
7824 switch (pd->af) {
7825#if INET
7826 case AF_INET:
3e170ce0
A
7827 if (pd->naf != AF_INET) {
7828 if (pf_translate_icmp_af(
0a7de745
A
7829 AF_INET6, pd->hdr.icmp)) {
7830 return PF_DROP;
7831 }
3e170ce0
A
7832
7833 pd->proto = IPPROTO_ICMPV6;
3e170ce0 7834 } else {
5ba3f43e 7835 pf_change_a(&daddr->v4addr.s_addr,
0a7de745
A
7836 pd->ip_sum,
7837 sk->lan.addr.v4addr.s_addr, 0);
3e170ce0
A
7838
7839 pd->hdr.icmp->icmp_cksum =
0a7de745
A
7840 pf_cksum_fixup(
7841 pd->hdr.icmp->icmp_cksum,
7842 icmpid, sk->lan.xport.port, 0);
3e170ce0
A
7843
7844 pd->hdr.icmp->icmp_id =
0a7de745 7845 sk->lan.xport.port;
3e170ce0
A
7846 }
7847
5ba3f43e 7848 if (pf_lazy_makewritable(pd, pbuf,
0a7de745
A
7849 off + ICMP_MINLEN) == NULL) {
7850 return PF_DROP;
7851 }
5ba3f43e 7852 pbuf_copy_back(pbuf, off, ICMP_MINLEN,
0a7de745
A
7853 pd->hdr.icmp);
7854 if (sk->af_lan != sk->af_gwy) {
7855 return pf_do_nat64(sk, pd,
7856 pbuf, off);
7857 }
b0d623f7
A
7858 break;
7859#endif /* INET */
7860#if INET6
7861 case AF_INET6:
3e170ce0
A
7862 if (pd->naf != AF_INET6) {
7863 if (pf_translate_icmp_af(
0a7de745
A
7864 AF_INET, pd->hdr.icmp6)) {
7865 return PF_DROP;
7866 }
3e170ce0
A
7867
7868 pd->proto = IPPROTO_ICMP;
7869 } else {
7870 pf_change_a6(daddr,
0a7de745
A
7871 &pd->hdr.icmp6->icmp6_cksum,
7872 &sk->lan.addr, 0);
3e170ce0 7873 }
5ba3f43e 7874 if (pf_lazy_makewritable(pd, pbuf,
0a7de745
A
7875 off + sizeof(struct icmp6_hdr)) ==
7876 NULL) {
7877 return PF_DROP;
7878 }
5ba3f43e 7879 pbuf_copy_back(pbuf, off,
0a7de745
A
7880 sizeof(struct icmp6_hdr),
7881 pd->hdr.icmp6);
7882 if (sk->af_lan != sk->af_gwy) {
7883 return pf_do_nat64(sk, pd,
7884 pbuf, off);
7885 }
b0d623f7
A
7886 break;
7887#endif /* INET6 */
7888 }
7889 }
7890 }
7891
0a7de745 7892 return PF_PASS;
b0d623f7
A
7893 } else {
7894 /*
7895 * ICMP error message in response to a TCP/UDP packet.
7896 * Extract the inner TCP/UDP header and search for that state.
7897 */
0a7de745 7898 struct pf_pdesc pd2; /* For inner (original) header */
b0d623f7 7899#if INET
0a7de745 7900 struct ip h2;
b0d623f7
A
7901#endif /* INET */
7902#if INET6
0a7de745
A
7903 struct ip6_hdr h2_6;
7904 int terminal = 0;
b0d623f7 7905#endif /* INET6 */
0a7de745
A
7906 int ipoff2 = 0;
7907 int off2 = 0;
b0d623f7 7908
0a7de745 7909 memset(&pd2, 0, sizeof(pd2));
b0d623f7
A
7910
7911 pd2.af = pd->af;
7912 switch (pd->af) {
7913#if INET
7914 case AF_INET:
7915 /* offset of h2 in mbuf chain */
7916 ipoff2 = off + ICMP_MINLEN;
7917
0a7de745 7918 if (!pf_pull_hdr(pbuf, ipoff2, &h2, sizeof(h2),
b0d623f7
A
7919 NULL, reason, pd2.af)) {
7920 DPFPRINTF(PF_DEBUG_MISC,
7921 ("pf: ICMP error message too short "
7922 "(ip)\n"));
0a7de745 7923 return PF_DROP;
b0d623f7
A
7924 }
7925 /*
7926 * ICMP error messages don't refer to non-first
7927 * fragments
7928 */
7929 if (h2.ip_off & htons(IP_OFFMASK)) {
7930 REASON_SET(reason, PFRES_FRAG);
0a7de745 7931 return PF_DROP;
b0d623f7
A
7932 }
7933
7934 /* offset of protocol header that follows h2 */
7935 off2 = ipoff2 + (h2.ip_hl << 2);
3e170ce0
A
7936 /* TODO */
7937 pd2.off = ipoff2 + (h2.ip_hl << 2);
b0d623f7
A
7938
7939 pd2.proto = h2.ip_p;
7940 pd2.src = (struct pf_addr *)&h2.ip_src;
7941 pd2.dst = (struct pf_addr *)&h2.ip_dst;
7942 pd2.ip_sum = &h2.ip_sum;
7943 break;
7944#endif /* INET */
7945#if INET6
7946 case AF_INET6:
0a7de745 7947 ipoff2 = off + sizeof(struct icmp6_hdr);
b0d623f7 7948
0a7de745 7949 if (!pf_pull_hdr(pbuf, ipoff2, &h2_6, sizeof(h2_6),
b0d623f7
A
7950 NULL, reason, pd2.af)) {
7951 DPFPRINTF(PF_DEBUG_MISC,
7952 ("pf: ICMP error message too short "
7953 "(ip6)\n"));
0a7de745 7954 return PF_DROP;
b0d623f7
A
7955 }
7956 pd2.proto = h2_6.ip6_nxt;
5ba3f43e
A
7957 pd2.src = (struct pf_addr *)(uintptr_t)&h2_6.ip6_src;
7958 pd2.dst = (struct pf_addr *)(uintptr_t)&h2_6.ip6_dst;
b0d623f7 7959 pd2.ip_sum = NULL;
0a7de745 7960 off2 = ipoff2 + sizeof(h2_6);
b0d623f7
A
7961 do {
7962 switch (pd2.proto) {
7963 case IPPROTO_FRAGMENT:
7964 /*
7965 * ICMPv6 error messages for
7966 * non-first fragments
7967 */
7968 REASON_SET(reason, PFRES_FRAG);
0a7de745 7969 return PF_DROP;
b0d623f7
A
7970 case IPPROTO_AH:
7971 case IPPROTO_HOPOPTS:
7972 case IPPROTO_ROUTING:
7973 case IPPROTO_DSTOPTS: {
7974 /* get next header and header length */
7975 struct ip6_ext opt6;
7976
5ba3f43e 7977 if (!pf_pull_hdr(pbuf, off2, &opt6,
0a7de745 7978 sizeof(opt6), NULL, reason,
b0d623f7
A
7979 pd2.af)) {
7980 DPFPRINTF(PF_DEBUG_MISC,
7981 ("pf: ICMPv6 short opt\n"));
0a7de745 7982 return PF_DROP;
b0d623f7 7983 }
0a7de745 7984 if (pd2.proto == IPPROTO_AH) {
b0d623f7 7985 off2 += (opt6.ip6e_len + 2) * 4;
0a7de745 7986 } else {
b0d623f7 7987 off2 += (opt6.ip6e_len + 1) * 8;
0a7de745 7988 }
b0d623f7
A
7989 pd2.proto = opt6.ip6e_nxt;
7990 /* goto the next header */
7991 break;
7992 }
7993 default:
7994 terminal++;
7995 break;
7996 }
7997 } while (!terminal);
3e170ce0
A
7998 /* TODO */
7999 pd2.off = ipoff2;
b0d623f7
A
8000 break;
8001#endif /* INET6 */
8002 }
8003
8004 switch (pd2.proto) {
8005 case IPPROTO_TCP: {
0a7de745
A
8006 struct tcphdr th;
8007 u_int32_t seq;
8008 struct pf_state_peer *src, *dst;
8009 u_int8_t dws;
8010 int copyback = 0;
b0d623f7
A
8011
8012 /*
8013 * Only the first 8 bytes of the TCP header can be
8014 * expected. Don't access any TCP header fields after
8015 * th_seq, an ackskew test is not possible.
8016 */
5ba3f43e 8017 if (!pf_pull_hdr(pbuf, off2, &th, 8, NULL, reason,
b0d623f7
A
8018 pd2.af)) {
8019 DPFPRINTF(PF_DEBUG_MISC,
8020 ("pf: ICMP error message too short "
8021 "(tcp)\n"));
0a7de745 8022 return PF_DROP;
b0d623f7
A
8023 }
8024
b0d623f7 8025 key.proto = IPPROTO_TCP;
3e170ce0
A
8026 key.af_gwy = pd2.af;
8027 PF_ACPY(&key.ext_gwy.addr, pd2.dst, key.af_gwy);
8028 PF_ACPY(&key.gwy.addr, pd2.src, key.af_gwy);
8029 key.ext_gwy.xport.port = th.th_dport;
8030 key.gwy.xport.port = th.th_sport;
8031
8032 key.af_lan = pd2.af;
8033 PF_ACPY(&key.lan.addr, pd2.dst, key.af_lan);
8034 PF_ACPY(&key.ext_lan.addr, pd2.src, key.af_lan);
8035 key.lan.xport.port = th.th_dport;
8036 key.ext_lan.xport.port = th.th_sport;
b0d623f7
A
8037
8038 STATE_LOOKUP();
8039
3e170ce0
A
8040 sk = (*state)->state_key;
8041 if ((direction == sk->direction) &&
8042 ((sk->af_lan == sk->af_gwy) ||
0a7de745 8043 (pd2.af == sk->af_lan))) {
b0d623f7
A
8044 src = &(*state)->dst;
8045 dst = &(*state)->src;
8046 } else {
8047 src = &(*state)->src;
8048 dst = &(*state)->dst;
8049 }
8050
0a7de745 8051 if (src->wscale && (dst->wscale & PF_WSCALE_FLAG)) {
b0d623f7 8052 dws = dst->wscale & PF_WSCALE_MASK;
0a7de745 8053 } else {
39236c6e 8054 dws = TCP_MAX_WINSHIFT;
0a7de745 8055 }
b0d623f7
A
8056
8057 /* Demodulate sequence number */
8058 seq = ntohl(th.th_seq) - src->seqdiff;
8059 if (src->seqdiff) {
8060 pf_change_a(&th.th_seq, icmpsum,
8061 htonl(seq), 0);
8062 copyback = 1;
8063 }
8064
8065 if (!SEQ_GEQ(src->seqhi, seq) ||
b7266188
A
8066 !SEQ_GEQ(seq,
8067 src->seqlo - ((u_int32_t)dst->max_win << dws))) {
b0d623f7
A
8068 if (pf_status.debug >= PF_DEBUG_MISC) {
8069 printf("pf: BAD ICMP %d:%d ",
8070 icmptype, pd->hdr.icmp->icmp_code);
8071 pf_print_host(pd->src, 0, pd->af);
8072 printf(" -> ");
8073 pf_print_host(pd->dst, 0, pd->af);
8074 printf(" state: ");
8075 pf_print_state(*state);
8076 printf(" seq=%u\n", seq);
8077 }
8078 REASON_SET(reason, PFRES_BADSTATE);
0a7de745 8079 return PF_DROP;
b0d623f7
A
8080 }
8081
3e170ce0 8082 pd->naf = pd2.naf = (pd2.af == sk->af_lan) ?
0a7de745 8083 sk->af_gwy : sk->af_lan;
3e170ce0
A
8084
8085 if (STATE_TRANSLATE(sk)) {
8086 /* NAT64 case */
8087 if (sk->af_lan != sk->af_gwy) {
8088 struct pf_state_host *saddr2, *daddr2;
8089
8090 if (pd2.naf == sk->af_lan) {
8091 saddr2 = &sk->lan;
8092 daddr2 = &sk->ext_lan;
8093 } else {
8094 saddr2 = &sk->ext_gwy;
8095 daddr2 = &sk->gwy;
8096 }
8097
8098 /* translate ICMP message types and codes */
8099 if (pf_translate_icmp_af(pd->naf,
0a7de745
A
8100 pd->hdr.icmp)) {
8101 return PF_DROP;
8102 }
5ba3f43e
A
8103
8104 if (pf_lazy_makewritable(pd, pbuf,
0a7de745
A
8105 off2 + 8) == NULL) {
8106 return PF_DROP;
8107 }
3e170ce0 8108
5ba3f43e 8109 pbuf_copy_back(pbuf, pd->off,
0a7de745
A
8110 sizeof(struct icmp6_hdr),
8111 pd->hdr.icmp6);
3e170ce0
A
8112
8113 /*
8114 * translate inner ip header within the
8115 * ICMP message
8116 */
5ba3f43e 8117 if (pf_change_icmp_af(pbuf, ipoff2, pd,
3e170ce0 8118 &pd2, &saddr2->addr, &daddr2->addr,
0a7de745
A
8119 pd->af, pd->naf)) {
8120 return PF_DROP;
8121 }
3e170ce0 8122
0a7de745 8123 if (pd->naf == AF_INET) {
3e170ce0 8124 pd->proto = IPPROTO_ICMP;
0a7de745 8125 } else {
3e170ce0 8126 pd->proto = IPPROTO_ICMPV6;
0a7de745 8127 }
3e170ce0
A
8128
8129 /*
8130 * translate inner tcp header within
8131 * the ICMP message
8132 */
8133 pf_change_ap(direction, NULL, pd2.src,
0a7de745
A
8134 &th.th_sport, pd2.ip_sum,
8135 &th.th_sum, &daddr2->addr,
8136 saddr2->xport.port, 0, pd2.af,
8137 pd2.naf, 0);
3e170ce0
A
8138
8139 pf_change_ap(direction, NULL, pd2.dst,
0a7de745
A
8140 &th.th_dport, pd2.ip_sum,
8141 &th.th_sum, &saddr2->addr,
8142 daddr2->xport.port, 0, pd2.af,
8143 pd2.naf, 0);
3e170ce0 8144
5ba3f43e 8145 pbuf_copy_back(pbuf, pd2.off, 8, &th);
3e170ce0
A
8146
8147 /* translate outer ip header */
8148 PF_ACPY(&pd->naddr, &daddr2->addr,
0a7de745 8149 pd->naf);
3e170ce0 8150 PF_ACPY(&pd->ndaddr, &saddr2->addr,
0a7de745 8151 pd->naf);
3e170ce0
A
8152 if (pd->af == AF_INET) {
8153 memcpy(&pd->naddr.addr32[3],
8154 &srcv4_inaddr,
8155 sizeof(pd->naddr.addr32[3]));
0a7de745
A
8156 return pf_nat64_ipv4(pbuf, off,
8157 pd);
3e170ce0 8158 } else {
0a7de745
A
8159 return pf_nat64_ipv6(pbuf, off,
8160 pd);
3e170ce0
A
8161 }
8162 }
b0d623f7
A
8163 if (direction == PF_IN) {
8164 pf_change_icmp(pd2.src, &th.th_sport,
3e170ce0
A
8165 daddr, &sk->lan.addr,
8166 sk->lan.xport.port, NULL,
b0d623f7
A
8167 pd2.ip_sum, icmpsum,
8168 pd->ip_sum, 0, pd2.af);
8169 } else {
8170 pf_change_icmp(pd2.dst, &th.th_dport,
3e170ce0
A
8171 saddr, &sk->gwy.addr,
8172 sk->gwy.xport.port, NULL,
b0d623f7
A
8173 pd2.ip_sum, icmpsum,
8174 pd->ip_sum, 0, pd2.af);
8175 }
8176 copyback = 1;
8177 }
8178
8179 if (copyback) {
5ba3f43e 8180 if (pf_lazy_makewritable(pd, pbuf, off2 + 8) ==
0a7de745
A
8181 NULL) {
8182 return PF_DROP;
8183 }
b0d623f7
A
8184 switch (pd2.af) {
8185#if INET
8186 case AF_INET:
5ba3f43e 8187 pbuf_copy_back(pbuf, off, ICMP_MINLEN,
b0d623f7 8188 pd->hdr.icmp);
5ba3f43e 8189 pbuf_copy_back(pbuf, ipoff2, sizeof(h2),
b0d623f7
A
8190 &h2);
8191 break;
8192#endif /* INET */
8193#if INET6
8194 case AF_INET6:
5ba3f43e 8195 pbuf_copy_back(pbuf, off,
0a7de745 8196 sizeof(struct icmp6_hdr),
b0d623f7 8197 pd->hdr.icmp6);
5ba3f43e 8198 pbuf_copy_back(pbuf, ipoff2,
0a7de745 8199 sizeof(h2_6), &h2_6);
b0d623f7
A
8200 break;
8201#endif /* INET6 */
8202 }
5ba3f43e 8203 pbuf_copy_back(pbuf, off2, 8, &th);
b0d623f7
A
8204 }
8205
0a7de745 8206 return PF_PASS;
b0d623f7
A
8207 }
8208 case IPPROTO_UDP: {
3e170ce0 8209 struct udphdr uh;
b0d623f7 8210 int dx, action;
0a7de745 8211 if (!pf_pull_hdr(pbuf, off2, &uh, sizeof(uh),
b0d623f7
A
8212 NULL, reason, pd2.af)) {
8213 DPFPRINTF(PF_DEBUG_MISC,
8214 ("pf: ICMP error message too short "
8215 "(udp)\n"));
0a7de745 8216 return PF_DROP;
b0d623f7
A
8217 }
8218
3e170ce0
A
8219 key.af_gwy = pd2.af;
8220 PF_ACPY(&key.ext_gwy.addr, pd2.dst, key.af_gwy);
8221 PF_ACPY(&key.gwy.addr, pd2.src, key.af_gwy);
8222 key.ext_gwy.xport.port = uh.uh_dport;
8223 key.gwy.xport.port = uh.uh_sport;
b0d623f7 8224
3e170ce0
A
8225 key.af_lan = pd2.af;
8226 PF_ACPY(&key.lan.addr, pd2.dst, key.af_lan);
8227 PF_ACPY(&key.ext_lan.addr, pd2.src, key.af_lan);
8228 key.lan.xport.port = uh.uh_dport;
8229 key.ext_lan.xport.port = uh.uh_sport;
8230
8231 key.proto = IPPROTO_UDP;
b0d623f7 8232 key.proto_variant = PF_EXTFILTER_APD;
3e170ce0 8233 dx = direction;
b0d623f7 8234
b7266188
A
8235 if (ntohs(uh.uh_sport) == PF_IKE_PORT &&
8236 ntohs(uh.uh_dport) == PF_IKE_PORT) {
b0d623f7 8237 struct pf_ike_hdr ike;
5ba3f43e 8238 size_t plen = pbuf->pb_packet_len - off2 -
0a7de745 8239 sizeof(uh);
b0d623f7
A
8240 if (direction == PF_IN &&
8241 plen < 8 /* PF_IKE_PACKET_MINSIZE */) {
8242 DPFPRINTF(PF_DEBUG_MISC, ("pf: "
8243 "ICMP error, embedded IKE message "
8244 "too small.\n"));
0a7de745 8245 return PF_DROP;
b0d623f7
A
8246 }
8247
0a7de745
A
8248 if (plen > sizeof(ike)) {
8249 plen = sizeof(ike);
8250 }
8251 pbuf_copy_data(pbuf, off + sizeof(uh), plen,
5ba3f43e 8252 &ike);
b0d623f7
A
8253
8254 key.app_state = &as;
8255 as.compare_lan_ext = pf_ike_compare;
8256 as.compare_ext_gwy = pf_ike_compare;
8257 as.u.ike.cookie = ike.initiator_cookie;
8258 }
8259
8260 *state = pf_find_state(kif, &key, dx);
8261
8262 if (key.app_state && *state == 0) {
8263 key.app_state = 0;
8264 *state = pf_find_state(kif, &key, dx);
8265 }
8266
8267 if (*state == 0) {
8268 key.proto_variant = PF_EXTFILTER_AD;
8269 *state = pf_find_state(kif, &key, dx);
8270 }
8271
8272 if (*state == 0) {
8273 key.proto_variant = PF_EXTFILTER_EI;
8274 *state = pf_find_state(kif, &key, dx);
8275 }
8276
39236c6e 8277 /* similar to STATE_LOOKUP() */
316670eb 8278 if (*state != NULL && pd != NULL &&
39236c6e
A
8279 !(pd->pktflags & PKTF_FLOW_ID)) {
8280 pd->flowsrc = (*state)->state_key->flowsrc;
316670eb 8281 pd->flowhash = (*state)->state_key->flowhash;
39236c6e
A
8282 if (pd->flowhash != 0) {
8283 pd->pktflags |= PKTF_FLOW_ID;
8284 pd->pktflags &= ~PKTF_FLOW_ADV;
8285 }
8286 }
316670eb 8287
0a7de745
A
8288 if (pf_state_lookup_aux(state, kif, direction, &action)) {
8289 return action;
8290 }
b0d623f7 8291
3e170ce0
A
8292 sk = (*state)->state_key;
8293 pd->naf = pd2.naf = (pd2.af == sk->af_lan) ?
0a7de745 8294 sk->af_gwy : sk->af_lan;
3e170ce0
A
8295
8296 if (STATE_TRANSLATE(sk)) {
8297 /* NAT64 case */
8298 if (sk->af_lan != sk->af_gwy) {
8299 struct pf_state_host *saddr2, *daddr2;
8300
8301 if (pd2.naf == sk->af_lan) {
8302 saddr2 = &sk->lan;
8303 daddr2 = &sk->ext_lan;
8304 } else {
8305 saddr2 = &sk->ext_gwy;
8306 daddr2 = &sk->gwy;
8307 }
8308
8309 /* translate ICMP message */
8310 if (pf_translate_icmp_af(pd->naf,
0a7de745
A
8311 pd->hdr.icmp)) {
8312 return PF_DROP;
8313 }
5ba3f43e 8314 if (pf_lazy_makewritable(pd, pbuf,
0a7de745
A
8315 off2 + 8) == NULL) {
8316 return PF_DROP;
8317 }
3e170ce0 8318
5ba3f43e 8319 pbuf_copy_back(pbuf, pd->off,
0a7de745
A
8320 sizeof(struct icmp6_hdr),
8321 pd->hdr.icmp6);
3e170ce0
A
8322
8323 /*
8324 * translate inner ip header within the
8325 * ICMP message
8326 */
5ba3f43e 8327 if (pf_change_icmp_af(pbuf, ipoff2, pd,
3e170ce0 8328 &pd2, &saddr2->addr, &daddr2->addr,
0a7de745
A
8329 pd->af, pd->naf)) {
8330 return PF_DROP;
8331 }
3e170ce0 8332
0a7de745 8333 if (pd->naf == AF_INET) {
3e170ce0 8334 pd->proto = IPPROTO_ICMP;
0a7de745 8335 } else {
3e170ce0 8336 pd->proto = IPPROTO_ICMPV6;
0a7de745 8337 }
3e170ce0
A
8338
8339 /*
8340 * translate inner udp header within
8341 * the ICMP message
8342 */
8343 pf_change_ap(direction, NULL, pd2.src,
0a7de745
A
8344 &uh.uh_sport, pd2.ip_sum,
8345 &uh.uh_sum, &daddr2->addr,
8346 saddr2->xport.port, 0, pd2.af,
8347 pd2.naf, 0);
3e170ce0
A
8348
8349 pf_change_ap(direction, NULL, pd2.dst,
0a7de745
A
8350 &uh.uh_dport, pd2.ip_sum,
8351 &uh.uh_sum, &saddr2->addr,
8352 daddr2->xport.port, 0, pd2.af,
8353 pd2.naf, 0);
3e170ce0 8354
5ba3f43e
A
8355 pbuf_copy_back(pbuf, pd2.off,
8356 sizeof(uh), &uh);
3e170ce0
A
8357
8358 /* translate outer ip header */
8359 PF_ACPY(&pd->naddr, &daddr2->addr,
0a7de745 8360 pd->naf);
3e170ce0 8361 PF_ACPY(&pd->ndaddr, &saddr2->addr,
0a7de745 8362 pd->naf);
3e170ce0
A
8363 if (pd->af == AF_INET) {
8364 memcpy(&pd->naddr.addr32[3],
8365 &srcv4_inaddr,
8366 sizeof(pd->naddr.addr32[3]));
0a7de745
A
8367 return pf_nat64_ipv4(pbuf, off,
8368 pd);
3e170ce0 8369 } else {
0a7de745
A
8370 return pf_nat64_ipv6(pbuf, off,
8371 pd);
3e170ce0
A
8372 }
8373 }
b0d623f7
A
8374 if (direction == PF_IN) {
8375 pf_change_icmp(pd2.src, &uh.uh_sport,
3e170ce0
A
8376 daddr, &sk->lan.addr,
8377 sk->lan.xport.port, &uh.uh_sum,
b0d623f7
A
8378 pd2.ip_sum, icmpsum,
8379 pd->ip_sum, 1, pd2.af);
8380 } else {
8381 pf_change_icmp(pd2.dst, &uh.uh_dport,
3e170ce0
A
8382 saddr, &sk->gwy.addr,
8383 sk->gwy.xport.port, &uh.uh_sum,
b0d623f7
A
8384 pd2.ip_sum, icmpsum,
8385 pd->ip_sum, 1, pd2.af);
8386 }
5ba3f43e 8387 if (pf_lazy_makewritable(pd, pbuf,
0a7de745
A
8388 off2 + sizeof(uh)) == NULL) {
8389 return PF_DROP;
8390 }
b0d623f7
A
8391 switch (pd2.af) {
8392#if INET
8393 case AF_INET:
5ba3f43e 8394 pbuf_copy_back(pbuf, off, ICMP_MINLEN,
b0d623f7 8395 pd->hdr.icmp);
5ba3f43e 8396 pbuf_copy_back(pbuf, ipoff2,
0a7de745 8397 sizeof(h2), &h2);
b0d623f7
A
8398 break;
8399#endif /* INET */
8400#if INET6
8401 case AF_INET6:
5ba3f43e 8402 pbuf_copy_back(pbuf, off,
0a7de745 8403 sizeof(struct icmp6_hdr),
b0d623f7 8404 pd->hdr.icmp6);
5ba3f43e 8405 pbuf_copy_back(pbuf, ipoff2,
0a7de745 8406 sizeof(h2_6), &h2_6);
b0d623f7
A
8407 break;
8408#endif /* INET6 */
8409 }
0a7de745 8410 pbuf_copy_back(pbuf, off2, sizeof(uh), &uh);
b0d623f7
A
8411 }
8412
0a7de745 8413 return PF_PASS;
b0d623f7
A
8414 }
8415#if INET
8416 case IPPROTO_ICMP: {
0a7de745 8417 struct icmp iih;
b0d623f7 8418
5ba3f43e 8419 if (!pf_pull_hdr(pbuf, off2, &iih, ICMP_MINLEN,
b0d623f7
A
8420 NULL, reason, pd2.af)) {
8421 DPFPRINTF(PF_DEBUG_MISC,
8422 ("pf: ICMP error message too short i"
8423 "(icmp)\n"));
0a7de745 8424 return PF_DROP;
b0d623f7
A
8425 }
8426
b0d623f7 8427 key.proto = IPPROTO_ICMP;
0a7de745 8428 if (direction == PF_IN) {
3e170ce0
A
8429 key.af_gwy = pd2.af;
8430 PF_ACPY(&key.ext_gwy.addr, pd2.dst, key.af_gwy);
8431 PF_ACPY(&key.gwy.addr, pd2.src, key.af_gwy);
8432 key.ext_gwy.xport.port = 0;
b0d623f7 8433 key.gwy.xport.port = iih.icmp_id;
b0d623f7 8434 } else {
3e170ce0
A
8435 key.af_lan = pd2.af;
8436 PF_ACPY(&key.lan.addr, pd2.dst, key.af_lan);
8437 PF_ACPY(&key.ext_lan.addr, pd2.src, key.af_lan);
b0d623f7 8438 key.lan.xport.port = iih.icmp_id;
3e170ce0 8439 key.ext_lan.xport.port = 0;
b0d623f7
A
8440 }
8441
8442 STATE_LOOKUP();
8443
3e170ce0
A
8444 sk = (*state)->state_key;
8445 if (STATE_TRANSLATE(sk)) {
b0d623f7
A
8446 if (direction == PF_IN) {
8447 pf_change_icmp(pd2.src, &iih.icmp_id,
3e170ce0
A
8448 daddr, &sk->lan.addr,
8449 sk->lan.xport.port, NULL,
b0d623f7
A
8450 pd2.ip_sum, icmpsum,
8451 pd->ip_sum, 0, AF_INET);
8452 } else {
8453 pf_change_icmp(pd2.dst, &iih.icmp_id,
3e170ce0
A
8454 saddr, &sk->gwy.addr,
8455 sk->gwy.xport.port, NULL,
b0d623f7
A
8456 pd2.ip_sum, icmpsum,
8457 pd->ip_sum, 0, AF_INET);
8458 }
5ba3f43e 8459 if (pf_lazy_makewritable(pd, pbuf,
0a7de745
A
8460 off2 + ICMP_MINLEN) == NULL) {
8461 return PF_DROP;
8462 }
5ba3f43e
A
8463 pbuf_copy_back(pbuf, off, ICMP_MINLEN,
8464 pd->hdr.icmp);
0a7de745 8465 pbuf_copy_back(pbuf, ipoff2, sizeof(h2), &h2);
5ba3f43e 8466 pbuf_copy_back(pbuf, off2, ICMP_MINLEN, &iih);
b0d623f7
A
8467 }
8468
0a7de745 8469 return PF_PASS;
b0d623f7
A
8470 }
8471#endif /* INET */
8472#if INET6
8473 case IPPROTO_ICMPV6: {
0a7de745 8474 struct icmp6_hdr iih;
b0d623f7 8475
5ba3f43e 8476 if (!pf_pull_hdr(pbuf, off2, &iih,
0a7de745 8477 sizeof(struct icmp6_hdr), NULL, reason, pd2.af)) {
b0d623f7
A
8478 DPFPRINTF(PF_DEBUG_MISC,
8479 ("pf: ICMP error message too short "
8480 "(icmp6)\n"));
0a7de745 8481 return PF_DROP;
b0d623f7
A
8482 }
8483
b0d623f7 8484 key.proto = IPPROTO_ICMPV6;
0a7de745 8485 if (direction == PF_IN) {
3e170ce0
A
8486 key.af_gwy = pd2.af;
8487 PF_ACPY(&key.ext_gwy.addr, pd2.dst, key.af_gwy);
8488 PF_ACPY(&key.gwy.addr, pd2.src, key.af_gwy);
8489 key.ext_gwy.xport.port = 0;
b0d623f7 8490 key.gwy.xport.port = iih.icmp6_id;
b0d623f7 8491 } else {
3e170ce0
A
8492 key.af_lan = pd2.af;
8493 PF_ACPY(&key.lan.addr, pd2.dst, key.af_lan);
8494 PF_ACPY(&key.ext_lan.addr, pd2.src, key.af_lan);
b0d623f7 8495 key.lan.xport.port = iih.icmp6_id;
3e170ce0 8496 key.ext_lan.xport.port = 0;
b0d623f7
A
8497 }
8498
8499 STATE_LOOKUP();
8500
3e170ce0
A
8501 sk = (*state)->state_key;
8502 if (STATE_TRANSLATE(sk)) {
b0d623f7
A
8503 if (direction == PF_IN) {
8504 pf_change_icmp(pd2.src, &iih.icmp6_id,
3e170ce0
A
8505 daddr, &sk->lan.addr,
8506 sk->lan.xport.port, NULL,
b0d623f7
A
8507 pd2.ip_sum, icmpsum,
8508 pd->ip_sum, 0, AF_INET6);
8509 } else {
8510 pf_change_icmp(pd2.dst, &iih.icmp6_id,
3e170ce0
A
8511 saddr, &sk->gwy.addr,
8512 sk->gwy.xport.port, NULL,
b0d623f7
A
8513 pd2.ip_sum, icmpsum,
8514 pd->ip_sum, 0, AF_INET6);
8515 }
5ba3f43e 8516 if (pf_lazy_makewritable(pd, pbuf, off2 +
0a7de745
A
8517 sizeof(struct icmp6_hdr)) == NULL) {
8518 return PF_DROP;
8519 }
5ba3f43e 8520 pbuf_copy_back(pbuf, off,
0a7de745
A
8521 sizeof(struct icmp6_hdr), pd->hdr.icmp6);
8522 pbuf_copy_back(pbuf, ipoff2, sizeof(h2_6),
5ba3f43e
A
8523 &h2_6);
8524 pbuf_copy_back(pbuf, off2,
0a7de745 8525 sizeof(struct icmp6_hdr), &iih);
b0d623f7
A
8526 }
8527
0a7de745 8528 return PF_PASS;
b0d623f7
A
8529 }
8530#endif /* INET6 */
8531 default: {
b0d623f7 8532 key.proto = pd2.proto;
0a7de745 8533 if (direction == PF_IN) {
3e170ce0
A
8534 key.af_gwy = pd2.af;
8535 PF_ACPY(&key.ext_gwy.addr, pd2.dst, key.af_gwy);
8536 PF_ACPY(&key.gwy.addr, pd2.src, key.af_gwy);
8537 key.ext_gwy.xport.port = 0;
b0d623f7 8538 key.gwy.xport.port = 0;
b0d623f7 8539 } else {
3e170ce0
A
8540 key.af_lan = pd2.af;
8541 PF_ACPY(&key.lan.addr, pd2.dst, key.af_lan);
8542 PF_ACPY(&key.ext_lan.addr, pd2.src, key.af_lan);
b0d623f7 8543 key.lan.xport.port = 0;
3e170ce0 8544 key.ext_lan.xport.port = 0;
b0d623f7
A
8545 }
8546
8547 STATE_LOOKUP();
8548
3e170ce0
A
8549 sk = (*state)->state_key;
8550 if (STATE_TRANSLATE(sk)) {
b0d623f7 8551 if (direction == PF_IN) {
3e170ce0 8552 pf_change_icmp(pd2.src, NULL, daddr,
0a7de745
A
8553 &sk->lan.addr, 0, NULL,
8554 pd2.ip_sum, icmpsum,
8555 pd->ip_sum, 0, pd2.af);
b0d623f7 8556 } else {
3e170ce0 8557 pf_change_icmp(pd2.dst, NULL, saddr,
0a7de745
A
8558 &sk->gwy.addr, 0, NULL,
8559 pd2.ip_sum, icmpsum,
8560 pd->ip_sum, 0, pd2.af);
b0d623f7
A
8561 }
8562 switch (pd2.af) {
8563#if INET
8564 case AF_INET:
5ba3f43e 8565 if (pf_lazy_makewritable(pd, pbuf,
0a7de745
A
8566 ipoff2 + sizeof(h2)) == NULL) {
8567 return PF_DROP;
8568 }
5ba3f43e
A
8569 /*
8570 * <XXXSCW>
8571 * Xnu was missing the following...
8572 */
8573 pbuf_copy_back(pbuf, off, ICMP_MINLEN,
8574 pd->hdr.icmp);
8575 pbuf_copy_back(pbuf, ipoff2,
8576 sizeof(h2), &h2);
8577 break;
8578 /*
8579 * </XXXSCW>
8580 */
b0d623f7
A
8581#endif /* INET */
8582#if INET6
8583 case AF_INET6:
5ba3f43e 8584 if (pf_lazy_makewritable(pd, pbuf,
0a7de745
A
8585 ipoff2 + sizeof(h2_6)) == NULL) {
8586 return PF_DROP;
8587 }
5ba3f43e 8588 pbuf_copy_back(pbuf, off,
0a7de745 8589 sizeof(struct icmp6_hdr),
5ba3f43e
A
8590 pd->hdr.icmp6);
8591 pbuf_copy_back(pbuf, ipoff2,
0a7de745 8592 sizeof(h2_6), &h2_6);
b0d623f7
A
8593 break;
8594#endif /* INET6 */
8595 }
8596 }
8597
0a7de745 8598 return PF_PASS;
b0d623f7
A
8599 }
8600 }
8601 }
8602}
8603
b0d623f7
A
8604static int
8605pf_test_state_grev1(struct pf_state **state, int direction,
8606 struct pfi_kif *kif, int off, struct pf_pdesc *pd)
8607{
8608 struct pf_state_peer *src;
8609 struct pf_state_peer *dst;
8610 struct pf_state_key_cmp key;
8611 struct pf_grev1_hdr *grev1 = pd->hdr.grev1;
b0d623f7 8612
b0d623f7 8613 key.app_state = 0;
b0d623f7
A
8614 key.proto = IPPROTO_GRE;
8615 key.proto_variant = PF_GRE_PPTP_VARIANT;
0a7de745 8616 if (direction == PF_IN) {
3e170ce0
A
8617 key.af_gwy = pd->af;
8618 PF_ACPY(&key.ext_gwy.addr, pd->src, key.af_gwy);
8619 PF_ACPY(&key.gwy.addr, pd->dst, key.af_gwy);
b0d623f7
A
8620 key.gwy.xport.call_id = grev1->call_id;
8621 } else {
3e170ce0
A
8622 key.af_lan = pd->af;
8623 PF_ACPY(&key.lan.addr, pd->src, key.af_lan);
8624 PF_ACPY(&key.ext_lan.addr, pd->dst, key.af_lan);
8625 key.ext_lan.xport.call_id = grev1->call_id;
b0d623f7
A
8626 }
8627
8628 STATE_LOOKUP();
8629
8630 if (direction == (*state)->state_key->direction) {
8631 src = &(*state)->src;
8632 dst = &(*state)->dst;
8633 } else {
8634 src = &(*state)->dst;
8635 dst = &(*state)->src;
8636 }
8637
8638 /* update states */
0a7de745 8639 if (src->state < PFGRE1S_INITIATING) {
b0d623f7 8640 src->state = PFGRE1S_INITIATING;
0a7de745 8641 }
b0d623f7
A
8642
8643 /* update expire time */
8644 (*state)->expire = pf_time_second();
8645 if (src->state >= PFGRE1S_INITIATING &&
8646 dst->state >= PFGRE1S_INITIATING) {
0a7de745 8647 if ((*state)->timeout != PFTM_TCP_ESTABLISHED) {
d1ecb069 8648 (*state)->timeout = PFTM_GREv1_ESTABLISHED;
0a7de745 8649 }
b0d623f7
A
8650 src->state = PFGRE1S_ESTABLISHED;
8651 dst->state = PFGRE1S_ESTABLISHED;
8652 } else {
8653 (*state)->timeout = PFTM_GREv1_INITIATING;
8654 }
d1ecb069 8655
0a7de745 8656 if ((*state)->state_key->app_state) {
d1ecb069
A
8657 (*state)->state_key->app_state->u.grev1.pptp_state->expire =
8658 pf_time_second();
0a7de745 8659 }
d1ecb069 8660
b0d623f7
A
8661 /* translate source/destination address, if necessary */
8662 if (STATE_GRE_TRANSLATE((*state)->state_key)) {
8663 if (direction == PF_OUT) {
8664 switch (pd->af) {
8665#if INET
8666 case AF_INET:
5ba3f43e 8667 pf_change_a(&pd->src->v4addr.s_addr,
b0d623f7 8668 pd->ip_sum,
5ba3f43e 8669 (*state)->state_key->gwy.addr.v4addr.s_addr, 0);
b0d623f7
A
8670 break;
8671#endif /* INET */
8672#if INET6
8673 case AF_INET6:
8674 PF_ACPY(pd->src, &(*state)->state_key->gwy.addr,
8675 pd->af);
8676 break;
8677#endif /* INET6 */
8678 }
8679 } else {
8680 grev1->call_id = (*state)->state_key->lan.xport.call_id;
8681
8682 switch (pd->af) {
8683#if INET
8684 case AF_INET:
5ba3f43e 8685 pf_change_a(&pd->dst->v4addr.s_addr,
b0d623f7 8686 pd->ip_sum,
5ba3f43e 8687 (*state)->state_key->lan.addr.v4addr.s_addr, 0);
b0d623f7
A
8688 break;
8689#endif /* INET */
8690#if INET6
8691 case AF_INET6:
8692 PF_ACPY(pd->dst, &(*state)->state_key->lan.addr,
8693 pd->af);
8694 break;
8695#endif /* INET6 */
8696 }
8697 }
8698
0a7de745
A
8699 if (pf_lazy_makewritable(pd, pd->mp, off + sizeof(*grev1)) ==
8700 NULL) {
8701 return PF_DROP;
8702 }
8703 pbuf_copy_back(pd->mp, off, sizeof(*grev1), grev1);
b0d623f7
A
8704 }
8705
0a7de745 8706 return PF_PASS;
b0d623f7
A
8707}
8708
316670eb 8709static int
b0d623f7
A
8710pf_test_state_esp(struct pf_state **state, int direction, struct pfi_kif *kif,
8711 int off, struct pf_pdesc *pd)
8712{
8713#pragma unused(off)
8714 struct pf_state_peer *src;
8715 struct pf_state_peer *dst;
8716 struct pf_state_key_cmp key;
8717 struct pf_esp_hdr *esp = pd->hdr.esp;
8718 int action;
8719
0a7de745 8720 memset(&key, 0, sizeof(key));
b0d623f7 8721 key.proto = IPPROTO_ESP;
0a7de745 8722 if (direction == PF_IN) {
3e170ce0
A
8723 key.af_gwy = pd->af;
8724 PF_ACPY(&key.ext_gwy.addr, pd->src, key.af_gwy);
8725 PF_ACPY(&key.gwy.addr, pd->dst, key.af_gwy);
b0d623f7
A
8726 key.gwy.xport.spi = esp->spi;
8727 } else {
3e170ce0
A
8728 key.af_lan = pd->af;
8729 PF_ACPY(&key.lan.addr, pd->src, key.af_lan);
8730 PF_ACPY(&key.ext_lan.addr, pd->dst, key.af_lan);
8731 key.ext_lan.xport.spi = esp->spi;
b0d623f7
A
8732 }
8733
8734 *state = pf_find_state(kif, &key, direction);
8735
8736 if (*state == 0) {
8737 struct pf_state *s;
8738
8739 /*
8740 * <jhw@apple.com>
8741 * No matching state. Look for a blocking state. If we find
8742 * one, then use that state and move it so that it's keyed to
8743 * the SPI in the current packet.
8744 */
8745 if (direction == PF_IN) {
8746 key.gwy.xport.spi = 0;
8747
8748 s = pf_find_state(kif, &key, direction);
8749 if (s) {
8750 struct pf_state_key *sk = s->state_key;
8751
8752 RB_REMOVE(pf_state_tree_ext_gwy,
8753 &pf_statetbl_ext_gwy, sk);
8754 sk->lan.xport.spi = sk->gwy.xport.spi =
8755 esp->spi;
8756
8757 if (RB_INSERT(pf_state_tree_ext_gwy,
0a7de745 8758 &pf_statetbl_ext_gwy, sk)) {
b0d623f7 8759 pf_detach_state(s, PF_DT_SKIP_EXTGWY);
0a7de745 8760 } else {
b0d623f7 8761 *state = s;
0a7de745 8762 }
b0d623f7
A
8763 }
8764 } else {
3e170ce0 8765 key.ext_lan.xport.spi = 0;
b0d623f7
A
8766
8767 s = pf_find_state(kif, &key, direction);
8768 if (s) {
8769 struct pf_state_key *sk = s->state_key;
8770
8771 RB_REMOVE(pf_state_tree_lan_ext,
8772 &pf_statetbl_lan_ext, sk);
3e170ce0 8773 sk->ext_lan.xport.spi = esp->spi;
b0d623f7
A
8774
8775 if (RB_INSERT(pf_state_tree_lan_ext,
0a7de745 8776 &pf_statetbl_lan_ext, sk)) {
b0d623f7 8777 pf_detach_state(s, PF_DT_SKIP_LANEXT);
0a7de745 8778 } else {
b0d623f7 8779 *state = s;
0a7de745 8780 }
b0d623f7
A
8781 }
8782 }
8783
8784 if (s) {
8785 if (*state == 0) {
8786#if NPFSYNC
0a7de745 8787 if (s->creatorid == pf_status.hostid) {
b0d623f7 8788 pfsync_delete_state(s);
0a7de745 8789 }
b0d623f7
A
8790#endif
8791 s->timeout = PFTM_UNLINKED;
8792 hook_runloop(&s->unlink_hooks,
0a7de745 8793 HOOK_REMOVE | HOOK_FREE);
b0d623f7
A
8794 pf_src_tree_remove_state(s);
8795 pf_free_state(s);
0a7de745 8796 return PF_DROP;
b0d623f7
A
8797 }
8798 }
8799 }
8800
39236c6e
A
8801 /* similar to STATE_LOOKUP() */
8802 if (*state != NULL && pd != NULL && !(pd->pktflags & PKTF_FLOW_ID)) {
8803 pd->flowsrc = (*state)->state_key->flowsrc;
316670eb 8804 pd->flowhash = (*state)->state_key->flowhash;
39236c6e
A
8805 if (pd->flowhash != 0) {
8806 pd->pktflags |= PKTF_FLOW_ID;
8807 pd->pktflags &= ~PKTF_FLOW_ADV;
8808 }
316670eb
A
8809 }
8810
0a7de745
A
8811 if (pf_state_lookup_aux(state, kif, direction, &action)) {
8812 return action;
8813 }
b0d623f7
A
8814
8815 if (direction == (*state)->state_key->direction) {
8816 src = &(*state)->src;
8817 dst = &(*state)->dst;
8818 } else {
8819 src = &(*state)->dst;
8820 dst = &(*state)->src;
8821 }
8822
8823 /* update states */
0a7de745 8824 if (src->state < PFESPS_INITIATING) {
b0d623f7 8825 src->state = PFESPS_INITIATING;
0a7de745 8826 }
b0d623f7
A
8827
8828 /* update expire time */
8829 (*state)->expire = pf_time_second();
8830 if (src->state >= PFESPS_INITIATING &&
8831 dst->state >= PFESPS_INITIATING) {
8832 (*state)->timeout = PFTM_ESP_ESTABLISHED;
8833 src->state = PFESPS_ESTABLISHED;
8834 dst->state = PFESPS_ESTABLISHED;
8835 } else {
8836 (*state)->timeout = PFTM_ESP_INITIATING;
8837 }
8838 /* translate source/destination address, if necessary */
8839 if (STATE_ADDR_TRANSLATE((*state)->state_key)) {
8840 if (direction == PF_OUT) {
8841 switch (pd->af) {
8842#if INET
8843 case AF_INET:
5ba3f43e 8844 pf_change_a(&pd->src->v4addr.s_addr,
b0d623f7 8845 pd->ip_sum,
5ba3f43e 8846 (*state)->state_key->gwy.addr.v4addr.s_addr, 0);
b0d623f7
A
8847 break;
8848#endif /* INET */
8849#if INET6
8850 case AF_INET6:
8851 PF_ACPY(pd->src, &(*state)->state_key->gwy.addr,
8852 pd->af);
8853 break;
8854#endif /* INET6 */
8855 }
8856 } else {
8857 switch (pd->af) {
8858#if INET
8859 case AF_INET:
5ba3f43e 8860 pf_change_a(&pd->dst->v4addr.s_addr,
b0d623f7 8861 pd->ip_sum,
5ba3f43e 8862 (*state)->state_key->lan.addr.v4addr.s_addr, 0);
b0d623f7
A
8863 break;
8864#endif /* INET */
8865#if INET6
8866 case AF_INET6:
8867 PF_ACPY(pd->dst, &(*state)->state_key->lan.addr,
8868 pd->af);
8869 break;
8870#endif /* INET6 */
8871 }
8872 }
8873 }
8874
0a7de745 8875 return PF_PASS;
b0d623f7 8876}
b0d623f7
A
8877
8878static int
8879pf_test_state_other(struct pf_state **state, int direction, struct pfi_kif *kif,
8880 struct pf_pdesc *pd)
8881{
0a7de745
A
8882 struct pf_state_peer *src, *dst;
8883 struct pf_state_key_cmp key;
b0d623f7 8884
b0d623f7 8885 key.app_state = 0;
b0d623f7 8886 key.proto = pd->proto;
0a7de745 8887 if (direction == PF_IN) {
3e170ce0
A
8888 key.af_gwy = pd->af;
8889 PF_ACPY(&key.ext_gwy.addr, pd->src, key.af_gwy);
8890 PF_ACPY(&key.gwy.addr, pd->dst, key.af_gwy);
8891 key.ext_gwy.xport.port = 0;
b0d623f7 8892 key.gwy.xport.port = 0;
b0d623f7 8893 } else {
3e170ce0
A
8894 key.af_lan = pd->af;
8895 PF_ACPY(&key.lan.addr, pd->src, key.af_lan);
8896 PF_ACPY(&key.ext_lan.addr, pd->dst, key.af_lan);
b0d623f7 8897 key.lan.xport.port = 0;
3e170ce0 8898 key.ext_lan.xport.port = 0;
b0d623f7
A
8899 }
8900
8901 STATE_LOOKUP();
8902
8903 if (direction == (*state)->state_key->direction) {
8904 src = &(*state)->src;
8905 dst = &(*state)->dst;
8906 } else {
8907 src = &(*state)->dst;
8908 dst = &(*state)->src;
8909 }
8910
8911 /* update states */
0a7de745 8912 if (src->state < PFOTHERS_SINGLE) {
b0d623f7 8913 src->state = PFOTHERS_SINGLE;
0a7de745
A
8914 }
8915 if (dst->state == PFOTHERS_SINGLE) {
b0d623f7 8916 dst->state = PFOTHERS_MULTIPLE;
0a7de745 8917 }
b0d623f7
A
8918
8919 /* update expire time */
8920 (*state)->expire = pf_time_second();
0a7de745 8921 if (src->state == PFOTHERS_MULTIPLE && dst->state == PFOTHERS_MULTIPLE) {
b0d623f7 8922 (*state)->timeout = PFTM_OTHER_MULTIPLE;
0a7de745 8923 } else {
b0d623f7 8924 (*state)->timeout = PFTM_OTHER_SINGLE;
0a7de745 8925 }
b0d623f7
A
8926
8927 /* translate source/destination address, if necessary */
b0d623f7 8928 if (STATE_ADDR_TRANSLATE((*state)->state_key)) {
b0d623f7
A
8929 if (direction == PF_OUT) {
8930 switch (pd->af) {
8931#if INET
8932 case AF_INET:
5ba3f43e 8933 pf_change_a(&pd->src->v4addr.s_addr,
b0d623f7 8934 pd->ip_sum,
5ba3f43e 8935 (*state)->state_key->gwy.addr.v4addr.s_addr,
b0d623f7
A
8936 0);
8937 break;
8938#endif /* INET */
8939#if INET6
8940 case AF_INET6:
8941 PF_ACPY(pd->src,
8942 &(*state)->state_key->gwy.addr, pd->af);
8943 break;
8944#endif /* INET6 */
8945 }
8946 } else {
8947 switch (pd->af) {
8948#if INET
8949 case AF_INET:
5ba3f43e 8950 pf_change_a(&pd->dst->v4addr.s_addr,
b0d623f7 8951 pd->ip_sum,
5ba3f43e 8952 (*state)->state_key->lan.addr.v4addr.s_addr,
b0d623f7
A
8953 0);
8954 break;
8955#endif /* INET */
8956#if INET6
8957 case AF_INET6:
8958 PF_ACPY(pd->dst,
8959 &(*state)->state_key->lan.addr, pd->af);
8960 break;
8961#endif /* INET6 */
8962 }
8963 }
8964 }
8965
0a7de745 8966 return PF_PASS;
b0d623f7
A
8967}
8968
8969/*
8970 * ipoff and off are measured from the start of the mbuf chain.
8971 * h must be at "ipoff" on the mbuf chain.
8972 */
8973void *
5ba3f43e 8974pf_pull_hdr(pbuf_t *pbuf, int off, void *p, int len,
b0d623f7
A
8975 u_short *actionp, u_short *reasonp, sa_family_t af)
8976{
8977 switch (af) {
8978#if INET
8979 case AF_INET: {
0a7de745
A
8980 struct ip *h = pbuf->pb_data;
8981 u_int16_t fragoff = (ntohs(h->ip_off) & IP_OFFMASK) << 3;
b0d623f7
A
8982
8983 if (fragoff) {
8984 if (fragoff >= len) {
8985 ACTION_SET(actionp, PF_PASS);
8986 } else {
8987 ACTION_SET(actionp, PF_DROP);
8988 REASON_SET(reasonp, PFRES_FRAG);
8989 }
0a7de745 8990 return NULL;
b0d623f7 8991 }
5ba3f43e 8992 if (pbuf->pb_packet_len < (unsigned)(off + len) ||
b0d623f7
A
8993 ntohs(h->ip_len) < off + len) {
8994 ACTION_SET(actionp, PF_DROP);
8995 REASON_SET(reasonp, PFRES_SHORT);
0a7de745 8996 return NULL;
b0d623f7
A
8997 }
8998 break;
8999 }
9000#endif /* INET */
9001#if INET6
9002 case AF_INET6: {
0a7de745 9003 struct ip6_hdr *h = pbuf->pb_data;
b0d623f7 9004
5ba3f43e 9005 if (pbuf->pb_packet_len < (unsigned)(off + len) ||
0a7de745 9006 (ntohs(h->ip6_plen) + sizeof(struct ip6_hdr)) <
b0d623f7
A
9007 (unsigned)(off + len)) {
9008 ACTION_SET(actionp, PF_DROP);
9009 REASON_SET(reasonp, PFRES_SHORT);
0a7de745 9010 return NULL;
b0d623f7
A
9011 }
9012 break;
9013 }
9014#endif /* INET6 */
9015 }
5ba3f43e 9016 pbuf_copy_data(pbuf, off, len, p);
0a7de745 9017 return p;
b0d623f7
A
9018}
9019
9020int
9021pf_routable(struct pf_addr *addr, sa_family_t af, struct pfi_kif *kif)
9022{
9023#pragma unused(kif)
0a7de745
A
9024 struct sockaddr_in *dst;
9025 int ret = 1;
b0d623f7 9026#if INET6
0a7de745
A
9027 struct sockaddr_in6 *dst6;
9028 struct route_in6 ro;
b0d623f7 9029#else
0a7de745 9030 struct route ro;
b0d623f7
A
9031#endif
9032
0a7de745 9033 bzero(&ro, sizeof(ro));
b0d623f7
A
9034 switch (af) {
9035 case AF_INET:
9036 dst = satosin(&ro.ro_dst);
9037 dst->sin_family = AF_INET;
0a7de745 9038 dst->sin_len = sizeof(*dst);
5ba3f43e 9039 dst->sin_addr = addr->v4addr;
b0d623f7
A
9040 break;
9041#if INET6
9042 case AF_INET6:
9043 dst6 = (struct sockaddr_in6 *)&ro.ro_dst;
9044 dst6->sin6_family = AF_INET6;
0a7de745 9045 dst6->sin6_len = sizeof(*dst6);
5ba3f43e 9046 dst6->sin6_addr = addr->v6addr;
b0d623f7
A
9047 break;
9048#endif /* INET6 */
9049 default:
0a7de745 9050 return 0;
b0d623f7
A
9051 }
9052
9053 /* XXX: IFT_ENC is not currently used by anything*/
9054 /* Skip checks for ipsec interfaces */
0a7de745 9055 if (kif != NULL && kif->pfik_ifp->if_type == IFT_ENC) {
b0d623f7 9056 goto out;
0a7de745 9057 }
b0d623f7 9058
39236c6e 9059 /* XXX: what is the point of this? */
b0d623f7
A
9060 rtalloc((struct route *)&ro);
9061
9062out:
39236c6e 9063 ROUTE_RELEASE(&ro);
0a7de745 9064 return ret;
b0d623f7
A
9065}
9066
9067int
9068pf_rtlabel_match(struct pf_addr *addr, sa_family_t af, struct pf_addr_wrap *aw)
9069{
9070#pragma unused(aw)
0a7de745 9071 struct sockaddr_in *dst;
b0d623f7 9072#if INET6
0a7de745
A
9073 struct sockaddr_in6 *dst6;
9074 struct route_in6 ro;
b0d623f7 9075#else
0a7de745 9076 struct route ro;
b0d623f7 9077#endif
0a7de745 9078 int ret = 0;
b0d623f7 9079
0a7de745 9080 bzero(&ro, sizeof(ro));
b0d623f7
A
9081 switch (af) {
9082 case AF_INET:
9083 dst = satosin(&ro.ro_dst);
9084 dst->sin_family = AF_INET;
0a7de745 9085 dst->sin_len = sizeof(*dst);
5ba3f43e 9086 dst->sin_addr = addr->v4addr;
b0d623f7
A
9087 break;
9088#if INET6
9089 case AF_INET6:
9090 dst6 = (struct sockaddr_in6 *)&ro.ro_dst;
9091 dst6->sin6_family = AF_INET6;
0a7de745 9092 dst6->sin6_len = sizeof(*dst6);
5ba3f43e 9093 dst6->sin6_addr = addr->v6addr;
b0d623f7
A
9094 break;
9095#endif /* INET6 */
9096 default:
0a7de745 9097 return 0;
b0d623f7
A
9098 }
9099
39236c6e 9100 /* XXX: what is the point of this? */
b0d623f7
A
9101 rtalloc((struct route *)&ro);
9102
39236c6e 9103 ROUTE_RELEASE(&ro);
b0d623f7 9104
0a7de745 9105 return ret;
b0d623f7
A
9106}
9107
9108#if INET
9109static void
5ba3f43e 9110pf_route(pbuf_t **pbufp, struct pf_rule *r, int dir, struct ifnet *oifp,
b0d623f7
A
9111 struct pf_state *s, struct pf_pdesc *pd)
9112{
9113#pragma unused(pd)
0a7de745
A
9114 struct mbuf *m0, *m1;
9115 struct route iproute;
9116 struct route *ro = &iproute;
9117 struct sockaddr_in *dst;
9118 struct ip *ip;
9119 struct ifnet *ifp = NULL;
9120 struct pf_addr naddr;
9121 struct pf_src_node *sn = NULL;
9122 int error = 0;
9123 uint32_t sw_csum;
9124 int interface_mtu = 0;
9125 bzero(&iproute, sizeof(iproute));
b0d623f7 9126
5ba3f43e 9127 if (pbufp == NULL || !pbuf_is_valid(*pbufp) || r == NULL ||
0a7de745 9128 (dir != PF_IN && dir != PF_OUT) || oifp == NULL) {
b0d623f7 9129 panic("pf_route: invalid parameters");
0a7de745 9130 }
b0d623f7 9131
316670eb 9132 if (pd->pf_mtag->pftag_routed++ > 3) {
5ba3f43e
A
9133 pbuf_destroy(*pbufp);
9134 *pbufp = NULL;
9135 m0 = NULL;
b0d623f7
A
9136 goto bad;
9137 }
9138
5ba3f43e
A
9139 /*
9140 * Since this is something of an edge case and may involve the
9141 * host stack (for routing, at least for now), we convert the
9142 * incoming pbuf into an mbuf.
9143 */
0a7de745 9144 if (r->rt == PF_DUPTO) {
5ba3f43e 9145 m0 = pbuf_clone_to_mbuf(*pbufp);
0a7de745 9146 } else if ((r->rt == PF_REPLYTO) == (r->direction == dir)) {
5ba3f43e 9147 return;
0a7de745 9148 } else {
5ba3f43e
A
9149 /* We're going to consume this packet */
9150 m0 = pbuf_to_mbuf(*pbufp, TRUE);
9151 *pbufp = NULL;
b0d623f7
A
9152 }
9153
0a7de745 9154 if (m0 == NULL) {
5ba3f43e 9155 goto bad;
0a7de745 9156 }
5ba3f43e
A
9157
9158 /* We now have the packet in an mbuf (m0) */
9159
0a7de745 9160 if (m0->m_len < (int)sizeof(struct ip)) {
b0d623f7 9161 DPFPRINTF(PF_DEBUG_URGENT,
5ba3f43e 9162 ("pf_route: packet length < sizeof (struct ip)\n"));
b0d623f7
A
9163 goto bad;
9164 }
9165
9166 ip = mtod(m0, struct ip *);
9167
316670eb 9168 dst = satosin((void *)&ro->ro_dst);
b0d623f7 9169 dst->sin_family = AF_INET;
0a7de745 9170 dst->sin_len = sizeof(*dst);
b0d623f7
A
9171 dst->sin_addr = ip->ip_dst;
9172
9173 if (r->rt == PF_FASTROUTE) {
9174 rtalloc(ro);
39236c6e 9175 if (ro->ro_rt == NULL) {
b0d623f7
A
9176 ipstat.ips_noroute++;
9177 goto bad;
9178 }
9179
9180 ifp = ro->ro_rt->rt_ifp;
6d2010ae 9181 RT_LOCK(ro->ro_rt);
b0d623f7
A
9182 ro->ro_rt->rt_use++;
9183
0a7de745 9184 if (ro->ro_rt->rt_flags & RTF_GATEWAY) {
316670eb 9185 dst = satosin((void *)ro->ro_rt->rt_gateway);
0a7de745 9186 }
6d2010ae 9187 RT_UNLOCK(ro->ro_rt);
b0d623f7
A
9188 } else {
9189 if (TAILQ_EMPTY(&r->rpool.list)) {
9190 DPFPRINTF(PF_DEBUG_URGENT,
9191 ("pf_route: TAILQ_EMPTY(&r->rpool.list)\n"));
9192 goto bad;
9193 }
9194 if (s == NULL) {
9195 pf_map_addr(AF_INET, r, (struct pf_addr *)&ip->ip_src,
9196 &naddr, NULL, &sn);
0a7de745 9197 if (!PF_AZERO(&naddr, AF_INET)) {
5ba3f43e 9198 dst->sin_addr.s_addr = naddr.v4addr.s_addr;
0a7de745 9199 }
b0d623f7
A
9200 ifp = r->rpool.cur->kif ?
9201 r->rpool.cur->kif->pfik_ifp : NULL;
9202 } else {
0a7de745 9203 if (!PF_AZERO(&s->rt_addr, AF_INET)) {
b0d623f7 9204 dst->sin_addr.s_addr =
5ba3f43e 9205 s->rt_addr.v4addr.s_addr;
0a7de745 9206 }
b0d623f7
A
9207 ifp = s->rt_kif ? s->rt_kif->pfik_ifp : NULL;
9208 }
9209 }
0a7de745 9210 if (ifp == NULL) {
b0d623f7 9211 goto bad;
0a7de745 9212 }
b0d623f7
A
9213
9214 if (oifp != ifp) {
0a7de745 9215 if (pf_test_mbuf(PF_OUT, ifp, &m0, NULL, NULL) != PF_PASS) {
b0d623f7 9216 goto bad;
0a7de745 9217 } else if (m0 == NULL) {
b0d623f7 9218 goto done;
0a7de745
A
9219 }
9220 if (m0->m_len < (int)sizeof(struct ip)) {
b0d623f7 9221 DPFPRINTF(PF_DEBUG_URGENT,
5ba3f43e 9222 ("pf_route: packet length < sizeof (struct ip)\n"));
b0d623f7
A
9223 goto bad;
9224 }
9225 ip = mtod(m0, struct ip *);
9226 }
9227
b0d623f7 9228 /* Catch routing changes wrt. hardware checksumming for TCP or UDP. */
39236c6e
A
9229 ip_output_checksum(ifp, m0, ((ip->ip_hl) << 2), ntohs(ip->ip_len),
9230 &sw_csum);
b0d623f7 9231
d9a64523
A
9232 interface_mtu = ifp->if_mtu;
9233
9234 if (INTF_ADJUST_MTU_FOR_CLAT46(ifp)) {
9235 interface_mtu = IN6_LINKMTU(ifp);
9236 /* Further adjust the size for CLAT46 expansion */
9237 interface_mtu -= CLAT46_HDR_EXPANSION_OVERHD;
9238 }
9239
9240 if (ntohs(ip->ip_len) <= interface_mtu || TSO_IPV4_OK(ifp, m0) ||
39236c6e
A
9241 (!(ip->ip_off & htons(IP_DF)) &&
9242 (ifp->if_hwassist & CSUM_FRAGMENT))) {
b0d623f7 9243 ip->ip_sum = 0;
39236c6e 9244 if (sw_csum & CSUM_DELAY_IP) {
b0d623f7 9245 ip->ip_sum = in_cksum(m0, ip->ip_hl << 2);
39236c6e
A
9246 sw_csum &= ~CSUM_DELAY_IP;
9247 m0->m_pkthdr.csum_flags &= ~CSUM_DELAY_IP;
9248 }
316670eb 9249 error = ifnet_output(ifp, PF_INET, m0, ro->ro_rt, sintosa(dst));
b0d623f7
A
9250 goto done;
9251 }
9252
9253 /*
9254 * Too large for interface; fragment if possible.
9255 * Must be able to put at least 8 bytes per fragment.
39236c6e 9256 * Balk when DF bit is set or the interface didn't support TSO.
b0d623f7 9257 */
39236c6e
A
9258 if ((ip->ip_off & htons(IP_DF)) ||
9259 (m0->m_pkthdr.csum_flags & CSUM_TSO_IPV4)) {
b0d623f7
A
9260 ipstat.ips_cantfrag++;
9261 if (r->rt != PF_DUPTO) {
9262 icmp_error(m0, ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG, 0,
d9a64523 9263 interface_mtu);
b0d623f7 9264 goto done;
0a7de745 9265 } else {
b0d623f7 9266 goto bad;
0a7de745 9267 }
b0d623f7
A
9268 }
9269
9270 m1 = m0;
6d2010ae
A
9271
9272 /* PR-8933605: send ip_len,ip_off to ip_fragment in host byte order */
316670eb 9273#if BYTE_ORDER != BIG_ENDIAN
6d2010ae
A
9274 NTOHS(ip->ip_off);
9275 NTOHS(ip->ip_len);
9276#endif
d9a64523 9277 error = ip_fragment(m0, ifp, interface_mtu, sw_csum);
316670eb 9278
b0d623f7
A
9279 if (error) {
9280 m0 = NULL;
9281 goto bad;
9282 }
9283
9284 for (m0 = m1; m0; m0 = m1) {
9285 m1 = m0->m_nextpkt;
9286 m0->m_nextpkt = 0;
0a7de745 9287 if (error == 0) {
316670eb 9288 error = ifnet_output(ifp, PF_INET, m0, ro->ro_rt,
b0d623f7 9289 sintosa(dst));
0a7de745 9290 } else {
b0d623f7 9291 m_freem(m0);
0a7de745 9292 }
b0d623f7
A
9293 }
9294
0a7de745 9295 if (error == 0) {
b0d623f7 9296 ipstat.ips_fragmented++;
0a7de745 9297 }
b0d623f7
A
9298
9299done:
39236c6e 9300 ROUTE_RELEASE(&iproute);
b0d623f7
A
9301 return;
9302
9303bad:
0a7de745 9304 if (m0) {
5ba3f43e 9305 m_freem(m0);
0a7de745 9306 }
b0d623f7
A
9307 goto done;
9308}
9309#endif /* INET */
9310
9311#if INET6
9312static void
5ba3f43e 9313pf_route6(pbuf_t **pbufp, struct pf_rule *r, int dir, struct ifnet *oifp,
b0d623f7
A
9314 struct pf_state *s, struct pf_pdesc *pd)
9315{
9316#pragma unused(pd)
0a7de745
A
9317 struct mbuf *m0;
9318 struct route_in6 ip6route;
9319 struct route_in6 *ro;
9320 struct sockaddr_in6 *dst;
9321 struct ip6_hdr *ip6;
9322 struct ifnet *ifp = NULL;
9323 struct pf_addr naddr;
9324 struct pf_src_node *sn = NULL;
9325 int error = 0;
cb323159 9326 struct pf_mtag *pf_mtag;
b0d623f7 9327
5ba3f43e 9328 if (pbufp == NULL || !pbuf_is_valid(*pbufp) || r == NULL ||
0a7de745 9329 (dir != PF_IN && dir != PF_OUT) || oifp == NULL) {
b0d623f7 9330 panic("pf_route6: invalid parameters");
0a7de745 9331 }
b0d623f7 9332
316670eb 9333 if (pd->pf_mtag->pftag_routed++ > 3) {
5ba3f43e
A
9334 pbuf_destroy(*pbufp);
9335 *pbufp = NULL;
9336 m0 = NULL;
b0d623f7
A
9337 goto bad;
9338 }
9339
5ba3f43e
A
9340 /*
9341 * Since this is something of an edge case and may involve the
9342 * host stack (for routing, at least for now), we convert the
9343 * incoming pbuf into an mbuf.
9344 */
b0d623f7 9345 if (r->rt == PF_DUPTO) {
5ba3f43e 9346 m0 = pbuf_clone_to_mbuf(*pbufp);
0a7de745 9347 } else if ((r->rt == PF_REPLYTO) == (r->direction == dir)) {
5ba3f43e 9348 return;
0a7de745 9349 } else {
5ba3f43e
A
9350 /* We're about to consume this packet */
9351 m0 = pbuf_to_mbuf(*pbufp, TRUE);
9352 *pbufp = NULL;
b0d623f7
A
9353 }
9354
0a7de745 9355 if (m0 == NULL) {
5ba3f43e 9356 goto bad;
0a7de745 9357 }
5ba3f43e 9358
0a7de745 9359 if (m0->m_len < (int)sizeof(struct ip6_hdr)) {
b0d623f7
A
9360 DPFPRINTF(PF_DEBUG_URGENT,
9361 ("pf_route6: m0->m_len < sizeof (struct ip6_hdr)\n"));
9362 goto bad;
9363 }
9364 ip6 = mtod(m0, struct ip6_hdr *);
9365
9366 ro = &ip6route;
0a7de745 9367 bzero((caddr_t)ro, sizeof(*ro));
b0d623f7
A
9368 dst = (struct sockaddr_in6 *)&ro->ro_dst;
9369 dst->sin6_family = AF_INET6;
0a7de745 9370 dst->sin6_len = sizeof(*dst);
b0d623f7
A
9371 dst->sin6_addr = ip6->ip6_dst;
9372
5ba3f43e 9373 /* Cheat. XXX why only in the v6addr case??? */
b0d623f7 9374 if (r->rt == PF_FASTROUTE) {
cb323159
A
9375 pf_mtag = pf_get_mtag(m0);
9376 ASSERT(pf_mtag != NULL);
316670eb 9377 pf_mtag->pftag_flags |= PF_TAG_GENERATED;
6d2010ae 9378 ip6_output(m0, NULL, NULL, 0, NULL, NULL, NULL);
b0d623f7
A
9379 return;
9380 }
9381
9382 if (TAILQ_EMPTY(&r->rpool.list)) {
9383 DPFPRINTF(PF_DEBUG_URGENT,
9384 ("pf_route6: TAILQ_EMPTY(&r->rpool.list)\n"));
9385 goto bad;
9386 }
9387 if (s == NULL) {
5ba3f43e 9388 pf_map_addr(AF_INET6, r, (struct pf_addr *)(uintptr_t)&ip6->ip6_src,
b0d623f7 9389 &naddr, NULL, &sn);
0a7de745 9390 if (!PF_AZERO(&naddr, AF_INET6)) {
b0d623f7
A
9391 PF_ACPY((struct pf_addr *)&dst->sin6_addr,
9392 &naddr, AF_INET6);
0a7de745 9393 }
b0d623f7
A
9394 ifp = r->rpool.cur->kif ? r->rpool.cur->kif->pfik_ifp : NULL;
9395 } else {
0a7de745 9396 if (!PF_AZERO(&s->rt_addr, AF_INET6)) {
b0d623f7
A
9397 PF_ACPY((struct pf_addr *)&dst->sin6_addr,
9398 &s->rt_addr, AF_INET6);
0a7de745 9399 }
b0d623f7
A
9400 ifp = s->rt_kif ? s->rt_kif->pfik_ifp : NULL;
9401 }
0a7de745 9402 if (ifp == NULL) {
b0d623f7 9403 goto bad;
0a7de745 9404 }
b0d623f7
A
9405
9406 if (oifp != ifp) {
0a7de745 9407 if (pf_test6_mbuf(PF_OUT, ifp, &m0, NULL, NULL) != PF_PASS) {
b0d623f7 9408 goto bad;
0a7de745 9409 } else if (m0 == NULL) {
b0d623f7 9410 goto done;
0a7de745
A
9411 }
9412 if (m0->m_len < (int)sizeof(struct ip6_hdr)) {
b0d623f7
A
9413 DPFPRINTF(PF_DEBUG_URGENT, ("pf_route6: m0->m_len "
9414 "< sizeof (struct ip6_hdr)\n"));
9415 goto bad;
9416 }
cb323159
A
9417 pf_mtag = pf_get_mtag(m0);
9418 /*
9419 * send refragmented packets.
9420 */
9421 if ((pf_mtag->pftag_flags & PF_TAG_REFRAGMENTED) != 0) {
9422 pf_mtag->pftag_flags &= ~PF_TAG_REFRAGMENTED;
9423 /*
9424 * nd6_output() frees packet chain in both success and
9425 * failure cases.
9426 */
9427 error = nd6_output(ifp, ifp, m0, dst, NULL, NULL);
9428 m0 = NULL;
9429 if (error) {
9430 DPFPRINTF(PF_DEBUG_URGENT, ("pf_route6:"
9431 "dropped refragmented packet\n"));
9432 }
9433 goto done;
9434 }
b0d623f7
A
9435 ip6 = mtod(m0, struct ip6_hdr *);
9436 }
9437
9438 /*
9439 * If the packet is too large for the outgoing interface,
9440 * send back an icmp6 error.
9441 */
0a7de745 9442 if (IN6_IS_SCOPE_EMBED(&dst->sin6_addr)) {
b0d623f7 9443 dst->sin6_addr.s6_addr16[1] = htons(ifp->if_index);
0a7de745 9444 }
b0d623f7 9445 if ((unsigned)m0->m_pkthdr.len <= ifp->if_mtu) {
316670eb 9446 error = nd6_output(ifp, ifp, m0, dst, NULL, NULL);
b0d623f7
A
9447 } else {
9448 in6_ifstat_inc(ifp, ifs6_in_toobig);
0a7de745 9449 if (r->rt != PF_DUPTO) {
b0d623f7 9450 icmp6_error(m0, ICMP6_PACKET_TOO_BIG, 0, ifp->if_mtu);
0a7de745 9451 } else {
b0d623f7 9452 goto bad;
0a7de745 9453 }
b0d623f7
A
9454 }
9455
9456done:
b0d623f7
A
9457 return;
9458
9459bad:
0a7de745 9460 if (m0) {
5ba3f43e 9461 m_freem(m0);
cb323159 9462 m0 = NULL;
0a7de745 9463 }
b0d623f7
A
9464 goto done;
9465}
9466#endif /* INET6 */
9467
9468
9469/*
9470 * check protocol (tcp/udp/icmp/icmp6) checksum and set mbuf flag
9471 * off is the offset where the protocol header starts
9472 * len is the total length of protocol header plus payload
9473 * returns 0 when the checksum is valid, otherwise returns 1.
9474 */
9475static int
5ba3f43e 9476pf_check_proto_cksum(pbuf_t *pbuf, int off, int len, u_int8_t p,
b0d623f7
A
9477 sa_family_t af)
9478{
9479 u_int16_t sum;
9480
9481 switch (p) {
9482 case IPPROTO_TCP:
9483 case IPPROTO_UDP:
9484 /*
9485 * Optimize for the common case; if the hardware calculated
9486 * value doesn't include pseudo-header checksum, or if it
9487 * is partially-computed (only 16-bit summation), do it in
9488 * software below.
9489 */
5ba3f43e 9490 if ((*pbuf->pb_csum_flags &
39236c6e
A
9491 (CSUM_DATA_VALID | CSUM_PSEUDO_HDR)) ==
9492 (CSUM_DATA_VALID | CSUM_PSEUDO_HDR) &&
5ba3f43e 9493 (*pbuf->pb_csum_data ^ 0xffff) == 0) {
0a7de745 9494 return 0;
b0d623f7
A
9495 }
9496 break;
9497 case IPPROTO_ICMP:
9498#if INET6
9499 case IPPROTO_ICMPV6:
9500#endif /* INET6 */
9501 break;
9502 default:
0a7de745
A
9503 return 1;
9504 }
9505 if (off < (int)sizeof(struct ip) || len < (int)sizeof(struct udphdr)) {
9506 return 1;
9507 }
9508 if (pbuf->pb_packet_len < (unsigned)(off + len)) {
9509 return 1;
b0d623f7 9510 }
b0d623f7
A
9511 switch (af) {
9512#if INET
9513 case AF_INET:
9514 if (p == IPPROTO_ICMP) {
5ba3f43e 9515#if 0
0a7de745
A
9516 if (m->m_len < off) {
9517 return 1;
9518 }
b0d623f7
A
9519 m->m_data += off;
9520 m->m_len -= off;
9521 sum = in_cksum(m, len);
9522 m->m_data -= off;
9523 m->m_len += off;
5ba3f43e 9524#else
0a7de745
A
9525 if (pbuf->pb_contig_len < (unsigned)off) {
9526 return 1;
9527 }
5ba3f43e
A
9528 sum = pbuf_inet_cksum(pbuf, 0, off, len);
9529#endif
b0d623f7 9530 } else {
0a7de745
A
9531 if (pbuf->pb_contig_len < (int)sizeof(struct ip)) {
9532 return 1;
9533 }
5ba3f43e 9534 sum = pbuf_inet_cksum(pbuf, p, off, len);
b0d623f7
A
9535 }
9536 break;
9537#endif /* INET */
9538#if INET6
9539 case AF_INET6:
0a7de745
A
9540 if (pbuf->pb_contig_len < (int)sizeof(struct ip6_hdr)) {
9541 return 1;
9542 }
5ba3f43e 9543 sum = pbuf_inet6_cksum(pbuf, p, off, len);
b0d623f7
A
9544 break;
9545#endif /* INET6 */
9546 default:
0a7de745 9547 return 1;
b0d623f7
A
9548 }
9549 if (sum) {
9550 switch (p) {
9551 case IPPROTO_TCP:
9552 tcpstat.tcps_rcvbadsum++;
9553 break;
9554 case IPPROTO_UDP:
9555 udpstat.udps_badsum++;
9556 break;
9557 case IPPROTO_ICMP:
9558 icmpstat.icps_checksum++;
9559 break;
9560#if INET6
9561 case IPPROTO_ICMPV6:
9562 icmp6stat.icp6s_checksum++;
9563 break;
9564#endif /* INET6 */
9565 }
0a7de745 9566 return 1;
b0d623f7 9567 }
0a7de745 9568 return 0;
b0d623f7
A
9569}
9570
9571#if INET
0a7de745
A
9572#define PF_APPLE_UPDATE_PDESC_IPv4() \
9573 do { \
9574 if (pbuf && pd.mp && pbuf != pd.mp) { \
9575 pbuf = pd.mp; \
9576 h = pbuf->pb_data; \
9577 pd.pf_mtag = pf_get_mtag_pbuf(pbuf); \
9578 } \
b0d623f7 9579 } while (0)
b0d623f7
A
9580
9581int
5ba3f43e
A
9582pf_test_mbuf(int dir, struct ifnet *ifp, struct mbuf **m0,
9583 struct ether_header *eh, struct ip_fw_args *fwa)
9584{
9585 pbuf_t pbuf_store, *pbuf;
9586 int rv;
9587
9588 pbuf_init_mbuf(&pbuf_store, *m0, (*m0)->m_pkthdr.rcvif);
9589 pbuf = &pbuf_store;
9590
9591 rv = pf_test(dir, ifp, &pbuf, eh, fwa);
9592
9593 if (pbuf_is_valid(pbuf)) {
9594 *m0 = pbuf->pb_mbuf;
9595 pbuf->pb_mbuf = NULL;
9596 pbuf_destroy(pbuf);
0a7de745 9597 } else {
5ba3f43e 9598 *m0 = NULL;
0a7de745 9599 }
5ba3f43e 9600
0a7de745 9601 return rv;
5ba3f43e
A
9602}
9603
9604int
9605pf_test(int dir, struct ifnet *ifp, pbuf_t **pbufp,
316670eb 9606 struct ether_header *eh, struct ip_fw_args *fwa)
b0d623f7 9607{
316670eb
A
9608#if !DUMMYNET
9609#pragma unused(fwa)
9610#endif
0a7de745
A
9611 struct pfi_kif *kif;
9612 u_short action = PF_PASS, reason = 0, log = 0;
9613 pbuf_t *pbuf = *pbufp;
9614 struct ip *h = 0;
9615 struct pf_rule *a = NULL, *r = &pf_default_rule, *tr, *nr;
9616 struct pf_state *s = NULL;
9617 struct pf_state_key *sk = NULL;
9618 struct pf_ruleset *ruleset = NULL;
9619 struct pf_pdesc pd;
9620 int off, dirndx, pqid = 0;
b0d623f7 9621
5ba3f43e 9622 LCK_MTX_ASSERT(pf_lock, LCK_MTX_ASSERT_OWNED);
b0d623f7 9623
0a7de745
A
9624 if (!pf_status.running) {
9625 return PF_PASS;
9626 }
b0d623f7 9627
0a7de745 9628 memset(&pd, 0, sizeof(pd));
b0d623f7 9629
5ba3f43e 9630 if ((pd.pf_mtag = pf_get_mtag_pbuf(pbuf)) == NULL) {
b0d623f7 9631 DPFPRINTF(PF_DEBUG_URGENT,
5ba3f43e 9632 ("pf_test: pf_get_mtag_pbuf returned NULL\n"));
0a7de745 9633 return PF_DROP;
b0d623f7
A
9634 }
9635
0a7de745
A
9636 if (pd.pf_mtag->pftag_flags & PF_TAG_GENERATED) {
9637 return PF_PASS;
9638 }
b0d623f7
A
9639
9640 kif = (struct pfi_kif *)ifp->if_pf_kif;
9641
9642 if (kif == NULL) {
9643 DPFPRINTF(PF_DEBUG_URGENT,
9644 ("pf_test: kif == NULL, if_name %s\n", ifp->if_name));
0a7de745
A
9645 return PF_DROP;
9646 }
9647 if (kif->pfik_flags & PFI_IFLAG_SKIP) {
9648 return PF_PASS;
b0d623f7 9649 }
b0d623f7 9650
cb323159
A
9651 if (pbuf->pb_packet_len < (int)sizeof(*h)) {
9652 REASON_SET(&reason, PFRES_SHORT);
9653 return PF_DROP;
9654 }
9655
316670eb 9656 /* initialize enough of pd for the done label */
5ba3f43e
A
9657 h = pbuf->pb_data;
9658 pd.mp = pbuf;
316670eb 9659 pd.lmw = 0;
5ba3f43e 9660 pd.pf_mtag = pf_get_mtag_pbuf(pbuf);
316670eb
A
9661 pd.src = (struct pf_addr *)&h->ip_src;
9662 pd.dst = (struct pf_addr *)&h->ip_dst;
3e170ce0
A
9663 PF_ACPY(&pd.baddr, pd.src, AF_INET);
9664 PF_ACPY(&pd.bdaddr, pd.dst, AF_INET);
316670eb
A
9665 pd.ip_sum = &h->ip_sum;
9666 pd.proto = h->ip_p;
9667 pd.proto_variant = 0;
9668 pd.af = AF_INET;
9669 pd.tos = h->ip_tos;
3e170ce0 9670 pd.ttl = h->ip_ttl;
316670eb
A
9671 pd.tot_len = ntohs(h->ip_len);
9672 pd.eh = eh;
9673
316670eb 9674#if DUMMYNET
0a7de745 9675 if (fwa != NULL && fwa->fwa_pf_rule != NULL) {
316670eb 9676 goto nonormalize;
0a7de745 9677 }
316670eb
A
9678#endif /* DUMMYNET */
9679
b0d623f7 9680 /* We do IP header normalization and packet reassembly here */
5ba3f43e 9681 action = pf_normalize_ip(pbuf, dir, kif, &reason, &pd);
316670eb 9682 if (action != PF_PASS || pd.lmw < 0) {
b0d623f7
A
9683 action = PF_DROP;
9684 goto done;
9685 }
316670eb
A
9686
9687#if DUMMYNET
9688nonormalize:
9689#endif /* DUMMYNET */
5ba3f43e
A
9690 /* pf_normalize can mess with pb_data */
9691 h = pbuf->pb_data;
b0d623f7
A
9692
9693 off = h->ip_hl << 2;
0a7de745 9694 if (off < (int)sizeof(*h)) {
b0d623f7
A
9695 action = PF_DROP;
9696 REASON_SET(&reason, PFRES_SHORT);
9697 log = 1;
9698 goto done;
9699 }
9700
9701 pd.src = (struct pf_addr *)&h->ip_src;
9702 pd.dst = (struct pf_addr *)&h->ip_dst;
3e170ce0
A
9703 PF_ACPY(&pd.baddr, pd.src, AF_INET);
9704 PF_ACPY(&pd.bdaddr, pd.dst, AF_INET);
b0d623f7
A
9705 pd.ip_sum = &h->ip_sum;
9706 pd.proto = h->ip_p;
b0d623f7 9707 pd.proto_variant = 0;
5ba3f43e 9708 pd.mp = pbuf;
b0d623f7 9709 pd.lmw = 0;
5ba3f43e 9710 pd.pf_mtag = pf_get_mtag_pbuf(pbuf);
b0d623f7
A
9711 pd.af = AF_INET;
9712 pd.tos = h->ip_tos;
3e170ce0 9713 pd.ttl = h->ip_ttl;
5ba3f43e 9714 pd.sc = MBUF_SCIDX(pbuf_get_service_class(pbuf));
b0d623f7
A
9715 pd.tot_len = ntohs(h->ip_len);
9716 pd.eh = eh;
39236c6e 9717
5ba3f43e
A
9718 if (*pbuf->pb_flags & PKTF_FLOW_ID) {
9719 pd.flowsrc = *pbuf->pb_flowsrc;
9720 pd.flowhash = *pbuf->pb_flowid;
9721 pd.pktflags = *pbuf->pb_flags & PKTF_FLOW_MASK;
316670eb 9722 }
b0d623f7
A
9723
9724 /* handle fragments that didn't get reassembled by normalization */
9725 if (h->ip_off & htons(IP_MF | IP_OFFMASK)) {
316670eb
A
9726 pd.flags |= PFDESC_IP_FRAG;
9727#if DUMMYNET
9728 /* Traffic goes through dummynet first */
5ba3f43e
A
9729 action = pf_test_dummynet(&r, dir, kif, &pbuf, &pd, fwa);
9730 if (action == PF_DROP || pbuf == NULL) {
9731 *pbufp = NULL;
0a7de745 9732 return action;
316670eb
A
9733 }
9734#endif /* DUMMYNET */
5ba3f43e 9735 action = pf_test_fragment(&r, dir, kif, pbuf, h,
b0d623f7
A
9736 &pd, &a, &ruleset);
9737 goto done;
9738 }
9739
9740 switch (h->ip_p) {
b0d623f7 9741 case IPPROTO_TCP: {
0a7de745 9742 struct tcphdr th;
b0d623f7 9743 pd.hdr.tcp = &th;
0a7de745 9744 if (!pf_pull_hdr(pbuf, off, &th, sizeof(th),
b0d623f7
A
9745 &action, &reason, AF_INET)) {
9746 log = action != PF_PASS;
9747 goto done;
9748 }
9749 pd.p_len = pd.tot_len - off - (th.th_off << 2);
0a7de745 9750 if ((th.th_flags & TH_ACK) && pd.p_len == 0) {
b0d623f7 9751 pqid = 1;
0a7de745 9752 }
316670eb
A
9753#if DUMMYNET
9754 /* Traffic goes through dummynet first */
5ba3f43e
A
9755 action = pf_test_dummynet(&r, dir, kif, &pbuf, &pd, fwa);
9756 if (action == PF_DROP || pbuf == NULL) {
9757 *pbufp = NULL;
0a7de745 9758 return action;
316670eb
A
9759 }
9760#endif /* DUMMYNET */
5ba3f43e 9761 action = pf_normalize_tcp(dir, kif, pbuf, 0, off, h, &pd);
0a7de745 9762 if (pd.lmw < 0) {
b0d623f7 9763 goto done;
0a7de745 9764 }
b0d623f7 9765 PF_APPLE_UPDATE_PDESC_IPv4();
0a7de745 9766 if (action == PF_DROP) {
b7266188 9767 goto done;
0a7de745 9768 }
5ba3f43e 9769 action = pf_test_state_tcp(&s, dir, kif, pbuf, off, h, &pd,
b0d623f7 9770 &reason);
0a7de745 9771 if (action == PF_NAT64) {
3e170ce0 9772 goto done;
0a7de745
A
9773 }
9774 if (pd.lmw < 0) {
b0d623f7 9775 goto done;
0a7de745 9776 }
b0d623f7 9777 PF_APPLE_UPDATE_PDESC_IPv4();
b0d623f7
A
9778 if (action == PF_PASS) {
9779#if NPFSYNC
9780 pfsync_update_state(s);
9781#endif /* NPFSYNC */
9782 r = s->rule.ptr;
9783 a = s->anchor.ptr;
9784 log = s->log;
0a7de745 9785 } else if (s == NULL) {
b0d623f7 9786 action = pf_test_rule(&r, &s, dir, kif,
5ba3f43e 9787 pbuf, off, h, &pd, &a, &ruleset, NULL);
0a7de745 9788 }
b0d623f7
A
9789 break;
9790 }
9791
9792 case IPPROTO_UDP: {
0a7de745 9793 struct udphdr uh;
b0d623f7
A
9794
9795 pd.hdr.udp = &uh;
0a7de745 9796 if (!pf_pull_hdr(pbuf, off, &uh, sizeof(uh),
b0d623f7
A
9797 &action, &reason, AF_INET)) {
9798 log = action != PF_PASS;
9799 goto done;
9800 }
9801 if (uh.uh_dport == 0 ||
5ba3f43e 9802 ntohs(uh.uh_ulen) > pbuf->pb_packet_len - off ||
0a7de745 9803 ntohs(uh.uh_ulen) < sizeof(struct udphdr)) {
b0d623f7
A
9804 action = PF_DROP;
9805 REASON_SET(&reason, PFRES_SHORT);
9806 goto done;
9807 }
316670eb
A
9808#if DUMMYNET
9809 /* Traffic goes through dummynet first */
5ba3f43e
A
9810 action = pf_test_dummynet(&r, dir, kif, &pbuf, &pd, fwa);
9811 if (action == PF_DROP || pbuf == NULL) {
9812 *pbufp = NULL;
0a7de745 9813 return action;
316670eb
A
9814 }
9815#endif /* DUMMYNET */
5ba3f43e 9816 action = pf_test_state_udp(&s, dir, kif, pbuf, off, h, &pd,
b7266188 9817 &reason);
0a7de745 9818 if (action == PF_NAT64) {
3e170ce0 9819 goto done;
0a7de745
A
9820 }
9821 if (pd.lmw < 0) {
b0d623f7 9822 goto done;
0a7de745 9823 }
b0d623f7 9824 PF_APPLE_UPDATE_PDESC_IPv4();
b0d623f7
A
9825 if (action == PF_PASS) {
9826#if NPFSYNC
9827 pfsync_update_state(s);
9828#endif /* NPFSYNC */
9829 r = s->rule.ptr;
9830 a = s->anchor.ptr;
9831 log = s->log;
0a7de745 9832 } else if (s == NULL) {
b0d623f7 9833 action = pf_test_rule(&r, &s, dir, kif,
5ba3f43e 9834 pbuf, off, h, &pd, &a, &ruleset, NULL);
0a7de745 9835 }
b0d623f7
A
9836 break;
9837 }
9838
9839 case IPPROTO_ICMP: {
0a7de745 9840 struct icmp ih;
b0d623f7
A
9841
9842 pd.hdr.icmp = &ih;
5ba3f43e 9843 if (!pf_pull_hdr(pbuf, off, &ih, ICMP_MINLEN,
b0d623f7
A
9844 &action, &reason, AF_INET)) {
9845 log = action != PF_PASS;
9846 goto done;
9847 }
316670eb
A
9848#if DUMMYNET
9849 /* Traffic goes through dummynet first */
5ba3f43e
A
9850 action = pf_test_dummynet(&r, dir, kif, &pbuf, &pd, fwa);
9851 if (action == PF_DROP || pbuf == NULL) {
9852 *pbufp = NULL;
0a7de745 9853 return action;
316670eb
A
9854 }
9855#endif /* DUMMYNET */
5ba3f43e 9856 action = pf_test_state_icmp(&s, dir, kif, pbuf, off, h, &pd,
b0d623f7 9857 &reason);
0a7de745 9858 if (action == PF_NAT64) {
3e170ce0 9859 goto done;
0a7de745
A
9860 }
9861 if (pd.lmw < 0) {
b0d623f7 9862 goto done;
0a7de745 9863 }
b0d623f7 9864 PF_APPLE_UPDATE_PDESC_IPv4();
b0d623f7
A
9865 if (action == PF_PASS) {
9866#if NPFSYNC
9867 pfsync_update_state(s);
9868#endif /* NPFSYNC */
9869 r = s->rule.ptr;
9870 a = s->anchor.ptr;
9871 log = s->log;
0a7de745 9872 } else if (s == NULL) {
b0d623f7 9873 action = pf_test_rule(&r, &s, dir, kif,
5ba3f43e 9874 pbuf, off, h, &pd, &a, &ruleset, NULL);
0a7de745 9875 }
b0d623f7
A
9876 break;
9877 }
9878
b0d623f7 9879 case IPPROTO_ESP: {
0a7de745 9880 struct pf_esp_hdr esp;
b0d623f7
A
9881
9882 pd.hdr.esp = &esp;
0a7de745 9883 if (!pf_pull_hdr(pbuf, off, &esp, sizeof(esp), &action, &reason,
b0d623f7
A
9884 AF_INET)) {
9885 log = action != PF_PASS;
9886 goto done;
9887 }
316670eb
A
9888#if DUMMYNET
9889 /* Traffic goes through dummynet first */
5ba3f43e
A
9890 action = pf_test_dummynet(&r, dir, kif, &pbuf, &pd, fwa);
9891 if (action == PF_DROP || pbuf == NULL) {
9892 *pbufp = NULL;
0a7de745 9893 return action;
316670eb
A
9894 }
9895#endif /* DUMMYNET */
b0d623f7 9896 action = pf_test_state_esp(&s, dir, kif, off, &pd);
0a7de745 9897 if (pd.lmw < 0) {
b0d623f7 9898 goto done;
0a7de745 9899 }
b0d623f7
A
9900 PF_APPLE_UPDATE_PDESC_IPv4();
9901 if (action == PF_PASS) {
9902#if NPFSYNC
9903 pfsync_update_state(s);
9904#endif /* NPFSYNC */
9905 r = s->rule.ptr;
9906 a = s->anchor.ptr;
9907 log = s->log;
0a7de745 9908 } else if (s == NULL) {
b0d623f7 9909 action = pf_test_rule(&r, &s, dir, kif,
5ba3f43e 9910 pbuf, off, h, &pd, &a, &ruleset, NULL);
0a7de745 9911 }
b0d623f7
A
9912 break;
9913 }
9914
9915 case IPPROTO_GRE: {
0a7de745 9916 struct pf_grev1_hdr grev1;
b0d623f7 9917 pd.hdr.grev1 = &grev1;
0a7de745 9918 if (!pf_pull_hdr(pbuf, off, &grev1, sizeof(grev1), &action,
b0d623f7
A
9919 &reason, AF_INET)) {
9920 log = (action != PF_PASS);
9921 goto done;
9922 }
316670eb
A
9923#if DUMMYNET
9924 /* Traffic goes through dummynet first */
5ba3f43e
A
9925 action = pf_test_dummynet(&r, dir, kif, &pbuf, &pd, fwa);
9926 if (action == PF_DROP || pbuf == NULL) {
9927 *pbufp = NULL;
0a7de745 9928 return action;
316670eb
A
9929 }
9930#endif /* DUMMYNET */
b0d623f7
A
9931 if ((ntohs(grev1.flags) & PF_GRE_FLAG_VERSION_MASK) == 1 &&
9932 ntohs(grev1.protocol_type) == PF_GRE_PPP_ETHERTYPE) {
9933 if (ntohs(grev1.payload_length) >
5ba3f43e 9934 pbuf->pb_packet_len - off) {
b0d623f7
A
9935 action = PF_DROP;
9936 REASON_SET(&reason, PFRES_SHORT);
9937 goto done;
9938 }
9939 pd.proto_variant = PF_GRE_PPTP_VARIANT;
9940 action = pf_test_state_grev1(&s, dir, kif, off, &pd);
0a7de745
A
9941 if (pd.lmw < 0) {
9942 goto done;
9943 }
b0d623f7
A
9944 PF_APPLE_UPDATE_PDESC_IPv4();
9945 if (action == PF_PASS) {
9946#if NPFSYNC
9947 pfsync_update_state(s);
9948#endif /* NPFSYNC */
9949 r = s->rule.ptr;
9950 a = s->anchor.ptr;
9951 log = s->log;
9952 break;
9953 } else if (s == NULL) {
5ba3f43e
A
9954 action = pf_test_rule(&r, &s, dir, kif, pbuf,
9955 off, h, &pd, &a, &ruleset, NULL);
0a7de745 9956 if (action == PF_PASS) {
b0d623f7 9957 break;
0a7de745 9958 }
b0d623f7
A
9959 }
9960 }
9961
9962 /* not GREv1/PPTP, so treat as ordinary GRE... */
9963 }
b0d623f7
A
9964
9965 default:
316670eb
A
9966#if DUMMYNET
9967 /* Traffic goes through dummynet first */
5ba3f43e
A
9968 action = pf_test_dummynet(&r, dir, kif, &pbuf, &pd, fwa);
9969 if (action == PF_DROP || pbuf == NULL) {
9970 *pbufp = NULL;
0a7de745 9971 return action;
316670eb
A
9972 }
9973#endif /* DUMMYNET */
b0d623f7 9974 action = pf_test_state_other(&s, dir, kif, &pd);
0a7de745 9975 if (pd.lmw < 0) {
b0d623f7 9976 goto done;
0a7de745 9977 }
b0d623f7 9978 PF_APPLE_UPDATE_PDESC_IPv4();
b0d623f7
A
9979 if (action == PF_PASS) {
9980#if NPFSYNC
9981 pfsync_update_state(s);
9982#endif /* NPFSYNC */
9983 r = s->rule.ptr;
9984 a = s->anchor.ptr;
9985 log = s->log;
0a7de745 9986 } else if (s == NULL) {
5ba3f43e 9987 action = pf_test_rule(&r, &s, dir, kif, pbuf, off, h,
39236c6e 9988 &pd, &a, &ruleset, NULL);
0a7de745 9989 }
b0d623f7
A
9990 break;
9991 }
9992
9993done:
3e170ce0 9994 if (action == PF_NAT64) {
5ba3f43e 9995 *pbufp = NULL;
0a7de745 9996 return action;
3e170ce0
A
9997 }
9998
5ba3f43e 9999 *pbufp = pd.mp;
b0d623f7
A
10000 PF_APPLE_UPDATE_PDESC_IPv4();
10001
490019cf
A
10002 if (action != PF_DROP) {
10003 if (action == PF_PASS && h->ip_hl > 5 &&
10004 !((s && s->allow_opts) || r->allow_opts)) {
10005 action = PF_DROP;
10006 REASON_SET(&reason, PFRES_IPOPTIONS);
10007 log = 1;
10008 DPFPRINTF(PF_DEBUG_MISC,
10009 ("pf: dropping packet with ip options [hlen=%u]\n",
10010 (unsigned int) h->ip_hl));
10011 }
b0d623f7 10012
490019cf 10013 if ((s && s->tag) || PF_RTABLEID_IS_VALID(r->rtableid) ||
0a7de745 10014 (pd.pktflags & PKTF_FLOW_ID)) {
5ba3f43e 10015 (void) pf_tag_packet(pbuf, pd.pf_mtag, s ? s->tag : 0,
490019cf 10016 r->rtableid, &pd);
0a7de745 10017 }
b0d623f7 10018
490019cf 10019 if (action == PF_PASS) {
39236c6e 10020#if PF_ECN
490019cf
A
10021 /* add hints for ecn */
10022 pd.pf_mtag->pftag_hdr = h;
10023 /* record address family */
10024 pd.pf_mtag->pftag_flags &= ~PF_TAG_HDR_INET6;
10025 pd.pf_mtag->pftag_flags |= PF_TAG_HDR_INET;
39236c6e 10026#endif /* PF_ECN */
490019cf 10027 /* record protocol */
5ba3f43e 10028 *pbuf->pb_proto = pd.proto;
b0d623f7 10029
490019cf
A
10030 /*
10031 * connections redirected to loopback should not match sockets
10032 * bound specifically to loopback due to security implications,
10033 * see tcp_input() and in_pcblookup_listen().
10034 */
10035 if (dir == PF_IN && (pd.proto == IPPROTO_TCP ||
0a7de745
A
10036 pd.proto == IPPROTO_UDP) && s != NULL &&
10037 s->nat_rule.ptr != NULL &&
10038 (s->nat_rule.ptr->action == PF_RDR ||
10039 s->nat_rule.ptr->action == PF_BINAT) &&
10040 (ntohl(pd.dst->v4addr.s_addr) >> IN_CLASSA_NSHIFT)
10041 == IN_LOOPBACKNET) {
490019cf 10042 pd.pf_mtag->pftag_flags |= PF_TAG_TRANSLATE_LOCALHOST;
0a7de745 10043 }
490019cf
A
10044 }
10045 }
b0d623f7
A
10046
10047 if (log) {
10048 struct pf_rule *lr;
10049
10050 if (s != NULL && s->nat_rule.ptr != NULL &&
0a7de745 10051 s->nat_rule.ptr->log & PF_LOG_ALL) {
b0d623f7 10052 lr = s->nat_rule.ptr;
0a7de745 10053 } else {
b0d623f7 10054 lr = r;
0a7de745 10055 }
5ba3f43e 10056 PFLOG_PACKET(kif, h, pbuf, AF_INET, dir, reason, lr, a, ruleset,
b0d623f7
A
10057 &pd);
10058 }
10059
10060 kif->pfik_bytes[0][dir == PF_OUT][action != PF_PASS] += pd.tot_len;
10061 kif->pfik_packets[0][dir == PF_OUT][action != PF_PASS]++;
10062
10063 if (action == PF_PASS || r->action == PF_DROP) {
10064 dirndx = (dir == PF_OUT);
10065 r->packets[dirndx]++;
10066 r->bytes[dirndx] += pd.tot_len;
10067 if (a != NULL) {
10068 a->packets[dirndx]++;
10069 a->bytes[dirndx] += pd.tot_len;
10070 }
10071 if (s != NULL) {
10072 sk = s->state_key;
10073 if (s->nat_rule.ptr != NULL) {
10074 s->nat_rule.ptr->packets[dirndx]++;
10075 s->nat_rule.ptr->bytes[dirndx] += pd.tot_len;
10076 }
10077 if (s->src_node != NULL) {
10078 s->src_node->packets[dirndx]++;
10079 s->src_node->bytes[dirndx] += pd.tot_len;
10080 }
10081 if (s->nat_src_node != NULL) {
10082 s->nat_src_node->packets[dirndx]++;
10083 s->nat_src_node->bytes[dirndx] += pd.tot_len;
10084 }
10085 dirndx = (dir == sk->direction) ? 0 : 1;
10086 s->packets[dirndx]++;
10087 s->bytes[dirndx] += pd.tot_len;
10088 }
10089 tr = r;
10090 nr = (s != NULL) ? s->nat_rule.ptr : pd.nat_rule;
10091 if (nr != NULL) {
10092 struct pf_addr *x;
10093 /*
10094 * XXX: we need to make sure that the addresses
10095 * passed to pfr_update_stats() are the same than
10096 * the addresses used during matching (pfr_match)
10097 */
10098 if (r == &pf_default_rule) {
10099 tr = nr;
10100 x = (sk == NULL || sk->direction == dir) ?
10101 &pd.baddr : &pd.naddr;
0a7de745 10102 } else {
b0d623f7
A
10103 x = (sk == NULL || sk->direction == dir) ?
10104 &pd.naddr : &pd.baddr;
0a7de745 10105 }
b0d623f7
A
10106 if (x == &pd.baddr || s == NULL) {
10107 /* we need to change the address */
0a7de745 10108 if (dir == PF_OUT) {
b0d623f7 10109 pd.src = x;
0a7de745 10110 } else {
b0d623f7 10111 pd.dst = x;
0a7de745 10112 }
b0d623f7
A
10113 }
10114 }
0a7de745 10115 if (tr->src.addr.type == PF_ADDR_TABLE) {
b0d623f7
A
10116 pfr_update_stats(tr->src.addr.p.tbl, (sk == NULL ||
10117 sk->direction == dir) ?
10118 pd.src : pd.dst, pd.af,
10119 pd.tot_len, dir == PF_OUT, r->action == PF_PASS,
10120 tr->src.neg);
0a7de745
A
10121 }
10122 if (tr->dst.addr.type == PF_ADDR_TABLE) {
b0d623f7
A
10123 pfr_update_stats(tr->dst.addr.p.tbl, (sk == NULL ||
10124 sk->direction == dir) ? pd.dst : pd.src, pd.af,
10125 pd.tot_len, dir == PF_OUT, r->action == PF_PASS,
10126 tr->dst.neg);
0a7de745 10127 }
b0d623f7
A
10128 }
10129
5ba3f43e 10130 VERIFY(pbuf == NULL || pd.mp == NULL || pd.mp == pbuf);
b7266188 10131
5ba3f43e 10132 if (*pbufp) {
b0d623f7 10133 if (pd.lmw < 0) {
b7266188
A
10134 REASON_SET(&reason, PFRES_MEMORY);
10135 action = PF_DROP;
10136 }
10137
10138 if (action == PF_DROP) {
5ba3f43e
A
10139 pbuf_destroy(*pbufp);
10140 *pbufp = NULL;
0a7de745 10141 return PF_DROP;
b0d623f7
A
10142 }
10143
5ba3f43e 10144 *pbufp = pbuf;
b0d623f7 10145 }
b0d623f7
A
10146
10147 if (action == PF_SYNPROXY_DROP) {
5ba3f43e
A
10148 pbuf_destroy(*pbufp);
10149 *pbufp = NULL;
b0d623f7 10150 action = PF_PASS;
0a7de745 10151 } else if (r->rt) {
5ba3f43e
A
10152 /* pf_route can free the pbuf causing *pbufp to become NULL */
10153 pf_route(pbufp, r, dir, kif->pfik_ifp, s, &pd);
0a7de745 10154 }
b0d623f7 10155
0a7de745 10156 return action;
b0d623f7
A
10157}
10158#endif /* INET */
10159
10160#if INET6
0a7de745
A
10161#define PF_APPLE_UPDATE_PDESC_IPv6() \
10162 do { \
10163 if (pbuf && pd.mp && pbuf != pd.mp) { \
10164 pbuf = pd.mp; \
10165 } \
10166 h = pbuf->pb_data; \
b0d623f7 10167 } while (0)
b0d623f7
A
10168
10169int
5ba3f43e
A
10170pf_test6_mbuf(int dir, struct ifnet *ifp, struct mbuf **m0,
10171 struct ether_header *eh, struct ip_fw_args *fwa)
10172{
10173 pbuf_t pbuf_store, *pbuf;
10174 int rv;
10175
10176 pbuf_init_mbuf(&pbuf_store, *m0, (*m0)->m_pkthdr.rcvif);
10177 pbuf = &pbuf_store;
10178
10179 rv = pf_test6(dir, ifp, &pbuf, eh, fwa);
10180
10181 if (pbuf_is_valid(pbuf)) {
10182 *m0 = pbuf->pb_mbuf;
10183 pbuf->pb_mbuf = NULL;
10184 pbuf_destroy(pbuf);
0a7de745 10185 } else {
5ba3f43e 10186 *m0 = NULL;
0a7de745 10187 }
5ba3f43e 10188
0a7de745 10189 return rv;
5ba3f43e
A
10190}
10191
10192int
10193pf_test6(int dir, struct ifnet *ifp, pbuf_t **pbufp,
316670eb 10194 struct ether_header *eh, struct ip_fw_args *fwa)
b0d623f7 10195{
316670eb
A
10196#if !DUMMYNET
10197#pragma unused(fwa)
10198#endif
0a7de745
A
10199 struct pfi_kif *kif;
10200 u_short action = PF_PASS, reason = 0, log = 0;
10201 pbuf_t *pbuf = *pbufp;
10202 struct ip6_hdr *h;
10203 struct pf_rule *a = NULL, *r = &pf_default_rule, *tr, *nr;
10204 struct pf_state *s = NULL;
10205 struct pf_state_key *sk = NULL;
10206 struct pf_ruleset *ruleset = NULL;
10207 struct pf_pdesc pd;
10208 int off, terminal = 0, dirndx, rh_cnt = 0;
10209 u_int8_t nxt;
cb323159 10210 boolean_t fwd = FALSE;
b0d623f7 10211
5ba3f43e 10212 LCK_MTX_ASSERT(pf_lock, LCK_MTX_ASSERT_OWNED);
b0d623f7 10213
cb323159
A
10214 ASSERT(ifp != NULL);
10215 if ((dir == PF_OUT) && (pbuf->pb_ifp) && (ifp != pbuf->pb_ifp)) {
10216 fwd = TRUE;
10217 }
10218
0a7de745
A
10219 if (!pf_status.running) {
10220 return PF_PASS;
10221 }
b0d623f7 10222
0a7de745 10223 memset(&pd, 0, sizeof(pd));
b0d623f7 10224
5ba3f43e 10225 if ((pd.pf_mtag = pf_get_mtag_pbuf(pbuf)) == NULL) {
b0d623f7 10226 DPFPRINTF(PF_DEBUG_URGENT,
5ba3f43e 10227 ("pf_test6: pf_get_mtag_pbuf returned NULL\n"));
0a7de745 10228 return PF_DROP;
b0d623f7
A
10229 }
10230
0a7de745
A
10231 if (pd.pf_mtag->pftag_flags & PF_TAG_GENERATED) {
10232 return PF_PASS;
10233 }
b0d623f7
A
10234
10235 kif = (struct pfi_kif *)ifp->if_pf_kif;
10236
10237 if (kif == NULL) {
10238 DPFPRINTF(PF_DEBUG_URGENT,
10239 ("pf_test6: kif == NULL, if_name %s\n", ifp->if_name));
0a7de745
A
10240 return PF_DROP;
10241 }
10242 if (kif->pfik_flags & PFI_IFLAG_SKIP) {
10243 return PF_PASS;
b0d623f7 10244 }
b0d623f7 10245
cb323159
A
10246 if (pbuf->pb_packet_len < (int)sizeof(*h)) {
10247 REASON_SET(&reason, PFRES_SHORT);
10248 return PF_DROP;
10249 }
b0d623f7 10250
cb323159 10251 h = pbuf->pb_data;
316670eb 10252 nxt = h->ip6_nxt;
5ba3f43e
A
10253 off = ((caddr_t)h - (caddr_t)pbuf->pb_data) + sizeof(struct ip6_hdr);
10254 pd.mp = pbuf;
316670eb 10255 pd.lmw = 0;
5ba3f43e
A
10256 pd.pf_mtag = pf_get_mtag_pbuf(pbuf);
10257 pd.src = (struct pf_addr *)(uintptr_t)&h->ip6_src;
10258 pd.dst = (struct pf_addr *)(uintptr_t)&h->ip6_dst;
3e170ce0
A
10259 PF_ACPY(&pd.baddr, pd.src, AF_INET6);
10260 PF_ACPY(&pd.bdaddr, pd.dst, AF_INET6);
316670eb
A
10261 pd.ip_sum = NULL;
10262 pd.af = AF_INET6;
10263 pd.proto = nxt;
10264 pd.proto_variant = 0;
10265 pd.tos = 0;
3e170ce0 10266 pd.ttl = h->ip6_hlim;
5ba3f43e 10267 pd.sc = MBUF_SCIDX(pbuf_get_service_class(pbuf));
316670eb
A
10268 pd.tot_len = ntohs(h->ip6_plen) + sizeof(struct ip6_hdr);
10269 pd.eh = eh;
10270
5ba3f43e
A
10271 if (*pbuf->pb_flags & PKTF_FLOW_ID) {
10272 pd.flowsrc = *pbuf->pb_flowsrc;
10273 pd.flowhash = *pbuf->pb_flowid;
10274 pd.pktflags = (*pbuf->pb_flags & PKTF_FLOW_MASK);
316670eb
A
10275 }
10276
316670eb 10277#if DUMMYNET
0a7de745 10278 if (fwa != NULL && fwa->fwa_pf_rule != NULL) {
316670eb 10279 goto nonormalize;
0a7de745 10280 }
316670eb
A
10281#endif /* DUMMYNET */
10282
b0d623f7 10283 /* We do IP header normalization and packet reassembly here */
5ba3f43e 10284 action = pf_normalize_ip6(pbuf, dir, kif, &reason, &pd);
316670eb 10285 if (action != PF_PASS || pd.lmw < 0) {
b0d623f7
A
10286 action = PF_DROP;
10287 goto done;
10288 }
316670eb
A
10289
10290#if DUMMYNET
10291nonormalize:
10292#endif /* DUMMYNET */
5ba3f43e 10293 h = pbuf->pb_data;
b0d623f7
A
10294
10295#if 1
10296 /*
10297 * we do not support jumbogram yet. if we keep going, zero ip6_plen
10298 * will do something bad, so drop the packet for now.
10299 */
10300 if (htons(h->ip6_plen) == 0) {
10301 action = PF_DROP;
0a7de745 10302 REASON_SET(&reason, PFRES_NORM); /*XXX*/
b0d623f7
A
10303 goto done;
10304 }
10305#endif
5ba3f43e
A
10306 pd.src = (struct pf_addr *)(uintptr_t)&h->ip6_src;
10307 pd.dst = (struct pf_addr *)(uintptr_t)&h->ip6_dst;
3e170ce0
A
10308 PF_ACPY(&pd.baddr, pd.src, AF_INET6);
10309 PF_ACPY(&pd.bdaddr, pd.dst, AF_INET6);
b0d623f7
A
10310 pd.ip_sum = NULL;
10311 pd.af = AF_INET6;
10312 pd.tos = 0;
3e170ce0 10313 pd.ttl = h->ip6_hlim;
0a7de745 10314 pd.tot_len = ntohs(h->ip6_plen) + sizeof(struct ip6_hdr);
b0d623f7
A
10315 pd.eh = eh;
10316
0a7de745 10317 off = ((caddr_t)h - (caddr_t)pbuf->pb_data) + sizeof(struct ip6_hdr);
b0d623f7 10318 pd.proto = h->ip6_nxt;
b0d623f7 10319 pd.proto_variant = 0;
5ba3f43e 10320 pd.mp = pbuf;
b0d623f7 10321 pd.lmw = 0;
5ba3f43e 10322 pd.pf_mtag = pf_get_mtag_pbuf(pbuf);
b0d623f7 10323
316670eb 10324 do {
cb323159 10325 switch (pd.proto) {
316670eb
A
10326 case IPPROTO_FRAGMENT: {
10327 struct ip6_frag ip6f;
39236c6e 10328
316670eb 10329 pd.flags |= PFDESC_IP_FRAG;
5ba3f43e 10330 if (!pf_pull_hdr(pbuf, off, &ip6f, sizeof ip6f, NULL,
b0d623f7
A
10331 &reason, pd.af)) {
10332 DPFPRINTF(PF_DEBUG_MISC,
316670eb 10333 ("pf: IPv6 short fragment header\n"));
b0d623f7
A
10334 action = PF_DROP;
10335 REASON_SET(&reason, PFRES_SHORT);
10336 log = 1;
10337 goto done;
10338 }
cb323159 10339 pd.proto = ip6f.ip6f_nxt;
316670eb
A
10340#if DUMMYNET
10341 /* Traffic goes through dummynet first */
5ba3f43e
A
10342 action = pf_test_dummynet(&r, dir, kif, &pbuf, &pd,
10343 fwa);
10344 if (action == PF_DROP || pbuf == NULL) {
10345 *pbufp = NULL;
0a7de745 10346 return action;
316670eb
A
10347 }
10348#endif /* DUMMYNET */
5ba3f43e
A
10349 action = pf_test_fragment(&r, dir, kif, pbuf, h, &pd,
10350 &a, &ruleset);
316670eb
A
10351 if (action == PF_DROP) {
10352 REASON_SET(&reason, PFRES_FRAG);
b0d623f7 10353 log = 1;
b0d623f7 10354 }
316670eb 10355 goto done;
b0d623f7 10356 }
316670eb
A
10357 case IPPROTO_ROUTING:
10358 ++rh_cnt;
0a7de745 10359 /* FALL THROUGH */
316670eb 10360
b0d623f7
A
10361 case IPPROTO_AH:
10362 case IPPROTO_HOPOPTS:
10363 case IPPROTO_DSTOPTS: {
10364 /* get next header and header length */
0a7de745 10365 struct ip6_ext opt6;
b0d623f7 10366
5ba3f43e 10367 if (!pf_pull_hdr(pbuf, off, &opt6, sizeof(opt6),
b0d623f7
A
10368 NULL, &reason, pd.af)) {
10369 DPFPRINTF(PF_DEBUG_MISC,
10370 ("pf: IPv6 short opt\n"));
10371 action = PF_DROP;
10372 log = 1;
10373 goto done;
10374 }
0a7de745 10375 if (pd.proto == IPPROTO_AH) {
b0d623f7 10376 off += (opt6.ip6e_len + 2) * 4;
0a7de745 10377 } else {
b0d623f7 10378 off += (opt6.ip6e_len + 1) * 8;
0a7de745 10379 }
cb323159 10380 pd.proto = opt6.ip6e_nxt;
b0d623f7
A
10381 /* goto the next header */
10382 break;
10383 }
10384 default:
10385 terminal++;
10386 break;
10387 }
10388 } while (!terminal);
10389
b0d623f7
A
10390
10391 switch (pd.proto) {
b0d623f7 10392 case IPPROTO_TCP: {
0a7de745 10393 struct tcphdr th;
b0d623f7
A
10394
10395 pd.hdr.tcp = &th;
0a7de745 10396 if (!pf_pull_hdr(pbuf, off, &th, sizeof(th),
b0d623f7
A
10397 &action, &reason, AF_INET6)) {
10398 log = action != PF_PASS;
10399 goto done;
10400 }
10401 pd.p_len = pd.tot_len - off - (th.th_off << 2);
316670eb
A
10402#if DUMMYNET
10403 /* Traffic goes through dummynet first */
5ba3f43e
A
10404 action = pf_test_dummynet(&r, dir, kif, &pbuf, &pd, fwa);
10405 if (action == PF_DROP || pbuf == NULL) {
10406 *pbufp = NULL;
0a7de745 10407 return action;
316670eb
A
10408 }
10409#endif /* DUMMYNET */
5ba3f43e 10410 action = pf_normalize_tcp(dir, kif, pbuf, 0, off, h, &pd);
0a7de745 10411 if (pd.lmw < 0) {
b0d623f7 10412 goto done;
0a7de745 10413 }
b0d623f7 10414 PF_APPLE_UPDATE_PDESC_IPv6();
0a7de745 10415 if (action == PF_DROP) {
b7266188 10416 goto done;
0a7de745 10417 }
5ba3f43e 10418 action = pf_test_state_tcp(&s, dir, kif, pbuf, off, h, &pd,
b0d623f7 10419 &reason);
0a7de745 10420 if (action == PF_NAT64) {
3e170ce0 10421 goto done;
0a7de745
A
10422 }
10423 if (pd.lmw < 0) {
b0d623f7 10424 goto done;
0a7de745 10425 }
b0d623f7 10426 PF_APPLE_UPDATE_PDESC_IPv6();
b0d623f7
A
10427 if (action == PF_PASS) {
10428#if NPFSYNC
10429 pfsync_update_state(s);
10430#endif /* NPFSYNC */
10431 r = s->rule.ptr;
10432 a = s->anchor.ptr;
10433 log = s->log;
0a7de745 10434 } else if (s == NULL) {
b0d623f7 10435 action = pf_test_rule(&r, &s, dir, kif,
5ba3f43e 10436 pbuf, off, h, &pd, &a, &ruleset, NULL);
0a7de745 10437 }
b0d623f7
A
10438 break;
10439 }
10440
10441 case IPPROTO_UDP: {
0a7de745 10442 struct udphdr uh;
b0d623f7
A
10443
10444 pd.hdr.udp = &uh;
0a7de745 10445 if (!pf_pull_hdr(pbuf, off, &uh, sizeof(uh),
b0d623f7
A
10446 &action, &reason, AF_INET6)) {
10447 log = action != PF_PASS;
10448 goto done;
10449 }
10450 if (uh.uh_dport == 0 ||
5ba3f43e 10451 ntohs(uh.uh_ulen) > pbuf->pb_packet_len - off ||
0a7de745 10452 ntohs(uh.uh_ulen) < sizeof(struct udphdr)) {
b0d623f7
A
10453 action = PF_DROP;
10454 REASON_SET(&reason, PFRES_SHORT);
10455 goto done;
10456 }
316670eb
A
10457#if DUMMYNET
10458 /* Traffic goes through dummynet first */
5ba3f43e
A
10459 action = pf_test_dummynet(&r, dir, kif, &pbuf, &pd, fwa);
10460 if (action == PF_DROP || pbuf == NULL) {
10461 *pbufp = NULL;
0a7de745 10462 return action;
316670eb
A
10463 }
10464#endif /* DUMMYNET */
5ba3f43e 10465 action = pf_test_state_udp(&s, dir, kif, pbuf, off, h, &pd,
b7266188 10466 &reason);
0a7de745 10467 if (action == PF_NAT64) {
3e170ce0 10468 goto done;
0a7de745
A
10469 }
10470 if (pd.lmw < 0) {
b0d623f7 10471 goto done;
0a7de745 10472 }
b0d623f7 10473 PF_APPLE_UPDATE_PDESC_IPv6();
b0d623f7
A
10474 if (action == PF_PASS) {
10475#if NPFSYNC
10476 pfsync_update_state(s);
10477#endif /* NPFSYNC */
10478 r = s->rule.ptr;
10479 a = s->anchor.ptr;
10480 log = s->log;
0a7de745 10481 } else if (s == NULL) {
b0d623f7 10482 action = pf_test_rule(&r, &s, dir, kif,
5ba3f43e 10483 pbuf, off, h, &pd, &a, &ruleset, NULL);
0a7de745 10484 }
b0d623f7
A
10485 break;
10486 }
10487
10488 case IPPROTO_ICMPV6: {
0a7de745 10489 struct icmp6_hdr ih;
b0d623f7
A
10490
10491 pd.hdr.icmp6 = &ih;
0a7de745 10492 if (!pf_pull_hdr(pbuf, off, &ih, sizeof(ih),
b0d623f7
A
10493 &action, &reason, AF_INET6)) {
10494 log = action != PF_PASS;
10495 goto done;
10496 }
316670eb
A
10497#if DUMMYNET
10498 /* Traffic goes through dummynet first */
5ba3f43e
A
10499 action = pf_test_dummynet(&r, dir, kif, &pbuf, &pd, fwa);
10500 if (action == PF_DROP || pbuf == NULL) {
10501 *pbufp = NULL;
0a7de745 10502 return action;
316670eb
A
10503 }
10504#endif /* DUMMYNET */
b0d623f7 10505 action = pf_test_state_icmp(&s, dir, kif,
5ba3f43e 10506 pbuf, off, h, &pd, &reason);
0a7de745 10507 if (action == PF_NAT64) {
3e170ce0 10508 goto done;
0a7de745
A
10509 }
10510 if (pd.lmw < 0) {
b0d623f7 10511 goto done;
0a7de745 10512 }
b0d623f7 10513 PF_APPLE_UPDATE_PDESC_IPv6();
b0d623f7
A
10514 if (action == PF_PASS) {
10515#if NPFSYNC
10516 pfsync_update_state(s);
10517#endif /* NPFSYNC */
10518 r = s->rule.ptr;
10519 a = s->anchor.ptr;
10520 log = s->log;
0a7de745 10521 } else if (s == NULL) {
b0d623f7 10522 action = pf_test_rule(&r, &s, dir, kif,
5ba3f43e 10523 pbuf, off, h, &pd, &a, &ruleset, NULL);
0a7de745 10524 }
b0d623f7
A
10525 break;
10526 }
10527
b0d623f7 10528 case IPPROTO_ESP: {
0a7de745 10529 struct pf_esp_hdr esp;
b0d623f7
A
10530
10531 pd.hdr.esp = &esp;
0a7de745 10532 if (!pf_pull_hdr(pbuf, off, &esp, sizeof(esp), &action,
5ba3f43e 10533 &reason, AF_INET6)) {
b0d623f7
A
10534 log = action != PF_PASS;
10535 goto done;
10536 }
316670eb
A
10537#if DUMMYNET
10538 /* Traffic goes through dummynet first */
5ba3f43e
A
10539 action = pf_test_dummynet(&r, dir, kif, &pbuf, &pd, fwa);
10540 if (action == PF_DROP || pbuf == NULL) {
10541 *pbufp = NULL;
0a7de745 10542 return action;
316670eb
A
10543 }
10544#endif /* DUMMYNET */
b0d623f7 10545 action = pf_test_state_esp(&s, dir, kif, off, &pd);
0a7de745 10546 if (pd.lmw < 0) {
b0d623f7 10547 goto done;
0a7de745 10548 }
b0d623f7
A
10549 PF_APPLE_UPDATE_PDESC_IPv6();
10550 if (action == PF_PASS) {
10551#if NPFSYNC
10552 pfsync_update_state(s);
10553#endif /* NPFSYNC */
10554 r = s->rule.ptr;
10555 a = s->anchor.ptr;
10556 log = s->log;
0a7de745 10557 } else if (s == NULL) {
b0d623f7 10558 action = pf_test_rule(&r, &s, dir, kif,
5ba3f43e 10559 pbuf, off, h, &pd, &a, &ruleset, NULL);
0a7de745 10560 }
b0d623f7
A
10561 break;
10562 }
10563
10564 case IPPROTO_GRE: {
0a7de745 10565 struct pf_grev1_hdr grev1;
b0d623f7
A
10566
10567 pd.hdr.grev1 = &grev1;
0a7de745 10568 if (!pf_pull_hdr(pbuf, off, &grev1, sizeof(grev1), &action,
b0d623f7
A
10569 &reason, AF_INET6)) {
10570 log = (action != PF_PASS);
10571 goto done;
10572 }
316670eb
A
10573#if DUMMYNET
10574 /* Traffic goes through dummynet first */
5ba3f43e
A
10575 action = pf_test_dummynet(&r, dir, kif, &pbuf, &pd, fwa);
10576 if (action == PF_DROP || pbuf == NULL) {
10577 *pbufp = NULL;
0a7de745 10578 return action;
316670eb
A
10579 }
10580#endif /* DUMMYNET */
b0d623f7
A
10581 if ((ntohs(grev1.flags) & PF_GRE_FLAG_VERSION_MASK) == 1 &&
10582 ntohs(grev1.protocol_type) == PF_GRE_PPP_ETHERTYPE) {
10583 if (ntohs(grev1.payload_length) >
5ba3f43e 10584 pbuf->pb_packet_len - off) {
b0d623f7
A
10585 action = PF_DROP;
10586 REASON_SET(&reason, PFRES_SHORT);
10587 goto done;
10588 }
10589 action = pf_test_state_grev1(&s, dir, kif, off, &pd);
0a7de745 10590 if (pd.lmw < 0) {
b0d623f7 10591 goto done;
0a7de745 10592 }
b0d623f7
A
10593 PF_APPLE_UPDATE_PDESC_IPv6();
10594 if (action == PF_PASS) {
10595#if NPFSYNC
10596 pfsync_update_state(s);
10597#endif /* NPFSYNC */
10598 r = s->rule.ptr;
10599 a = s->anchor.ptr;
10600 log = s->log;
10601 break;
10602 } else if (s == NULL) {
5ba3f43e
A
10603 action = pf_test_rule(&r, &s, dir, kif, pbuf,
10604 off, h, &pd, &a, &ruleset, NULL);
0a7de745 10605 if (action == PF_PASS) {
b0d623f7 10606 break;
0a7de745 10607 }
b0d623f7
A
10608 }
10609 }
10610
10611 /* not GREv1/PPTP, so treat as ordinary GRE... */
10612 }
b0d623f7
A
10613
10614 default:
316670eb
A
10615#if DUMMYNET
10616 /* Traffic goes through dummynet first */
5ba3f43e
A
10617 action = pf_test_dummynet(&r, dir, kif, &pbuf, &pd, fwa);
10618 if (action == PF_DROP || pbuf == NULL) {
10619 *pbufp = NULL;
0a7de745 10620 return action;
316670eb
A
10621 }
10622#endif /* DUMMYNET */
b0d623f7 10623 action = pf_test_state_other(&s, dir, kif, &pd);
0a7de745 10624 if (pd.lmw < 0) {
b0d623f7 10625 goto done;
0a7de745 10626 }
b0d623f7 10627 PF_APPLE_UPDATE_PDESC_IPv6();
b0d623f7
A
10628 if (action == PF_PASS) {
10629#if NPFSYNC
10630 pfsync_update_state(s);
10631#endif /* NPFSYNC */
10632 r = s->rule.ptr;
10633 a = s->anchor.ptr;
10634 log = s->log;
0a7de745 10635 } else if (s == NULL) {
5ba3f43e 10636 action = pf_test_rule(&r, &s, dir, kif, pbuf, off, h,
39236c6e 10637 &pd, &a, &ruleset, NULL);
0a7de745 10638 }
b0d623f7
A
10639 break;
10640 }
10641
10642done:
3e170ce0 10643 if (action == PF_NAT64) {
5ba3f43e 10644 *pbufp = NULL;
0a7de745 10645 return action;
3e170ce0
A
10646 }
10647
5ba3f43e 10648 *pbufp = pd.mp;
b0d623f7
A
10649 PF_APPLE_UPDATE_PDESC_IPv6();
10650
b0d623f7 10651 /* handle dangerous IPv6 extension headers. */
490019cf
A
10652 if (action != PF_DROP) {
10653 if (action == PF_PASS && rh_cnt &&
10654 !((s && s->allow_opts) || r->allow_opts)) {
10655 action = PF_DROP;
10656 REASON_SET(&reason, PFRES_IPOPTIONS);
10657 log = 1;
10658 DPFPRINTF(PF_DEBUG_MISC,
5ba3f43e 10659 ("pf: dropping packet with dangerous v6addr headers\n"));
490019cf 10660 }
b0d623f7 10661
490019cf 10662 if ((s && s->tag) || PF_RTABLEID_IS_VALID(r->rtableid) ||
0a7de745 10663 (pd.pktflags & PKTF_FLOW_ID)) {
5ba3f43e 10664 (void) pf_tag_packet(pbuf, pd.pf_mtag, s ? s->tag : 0,
490019cf 10665 r->rtableid, &pd);
0a7de745 10666 }
b0d623f7 10667
490019cf 10668 if (action == PF_PASS) {
39236c6e 10669#if PF_ECN
490019cf
A
10670 /* add hints for ecn */
10671 pd.pf_mtag->pftag_hdr = h;
10672 /* record address family */
10673 pd.pf_mtag->pftag_flags &= ~PF_TAG_HDR_INET;
10674 pd.pf_mtag->pftag_flags |= PF_TAG_HDR_INET6;
39236c6e 10675#endif /* PF_ECN */
490019cf 10676 /* record protocol */
5ba3f43e 10677 *pbuf->pb_proto = pd.proto;
490019cf
A
10678 if (dir == PF_IN && (pd.proto == IPPROTO_TCP ||
10679 pd.proto == IPPROTO_UDP) && s != NULL &&
10680 s->nat_rule.ptr != NULL &&
10681 (s->nat_rule.ptr->action == PF_RDR ||
0a7de745
A
10682 s->nat_rule.ptr->action == PF_BINAT) &&
10683 IN6_IS_ADDR_LOOPBACK(&pd.dst->v6addr)) {
490019cf 10684 pd.pf_mtag->pftag_flags |= PF_TAG_TRANSLATE_LOCALHOST;
0a7de745 10685 }
490019cf 10686 }
b0d623f7 10687 }
b0d623f7 10688
b0d623f7
A
10689
10690 if (log) {
10691 struct pf_rule *lr;
10692
10693 if (s != NULL && s->nat_rule.ptr != NULL &&
0a7de745 10694 s->nat_rule.ptr->log & PF_LOG_ALL) {
b0d623f7 10695 lr = s->nat_rule.ptr;
0a7de745 10696 } else {
b0d623f7 10697 lr = r;
0a7de745 10698 }
5ba3f43e 10699 PFLOG_PACKET(kif, h, pbuf, AF_INET6, dir, reason, lr, a, ruleset,
b0d623f7
A
10700 &pd);
10701 }
10702
10703 kif->pfik_bytes[1][dir == PF_OUT][action != PF_PASS] += pd.tot_len;
10704 kif->pfik_packets[1][dir == PF_OUT][action != PF_PASS]++;
10705
10706 if (action == PF_PASS || r->action == PF_DROP) {
10707 dirndx = (dir == PF_OUT);
10708 r->packets[dirndx]++;
10709 r->bytes[dirndx] += pd.tot_len;
10710 if (a != NULL) {
10711 a->packets[dirndx]++;
10712 a->bytes[dirndx] += pd.tot_len;
10713 }
10714 if (s != NULL) {
10715 sk = s->state_key;
10716 if (s->nat_rule.ptr != NULL) {
10717 s->nat_rule.ptr->packets[dirndx]++;
10718 s->nat_rule.ptr->bytes[dirndx] += pd.tot_len;
10719 }
10720 if (s->src_node != NULL) {
10721 s->src_node->packets[dirndx]++;
10722 s->src_node->bytes[dirndx] += pd.tot_len;
10723 }
10724 if (s->nat_src_node != NULL) {
10725 s->nat_src_node->packets[dirndx]++;
10726 s->nat_src_node->bytes[dirndx] += pd.tot_len;
10727 }
10728 dirndx = (dir == sk->direction) ? 0 : 1;
10729 s->packets[dirndx]++;
10730 s->bytes[dirndx] += pd.tot_len;
10731 }
10732 tr = r;
10733 nr = (s != NULL) ? s->nat_rule.ptr : pd.nat_rule;
10734 if (nr != NULL) {
10735 struct pf_addr *x;
10736 /*
10737 * XXX: we need to make sure that the addresses
10738 * passed to pfr_update_stats() are the same than
10739 * the addresses used during matching (pfr_match)
10740 */
10741 if (r == &pf_default_rule) {
10742 tr = nr;
10743 x = (s == NULL || sk->direction == dir) ?
10744 &pd.baddr : &pd.naddr;
10745 } else {
10746 x = (s == NULL || sk->direction == dir) ?
10747 &pd.naddr : &pd.baddr;
10748 }
10749 if (x == &pd.baddr || s == NULL) {
0a7de745 10750 if (dir == PF_OUT) {
b0d623f7 10751 pd.src = x;
0a7de745 10752 } else {
b0d623f7 10753 pd.dst = x;
0a7de745 10754 }
b0d623f7
A
10755 }
10756 }
0a7de745 10757 if (tr->src.addr.type == PF_ADDR_TABLE) {
b0d623f7
A
10758 pfr_update_stats(tr->src.addr.p.tbl, (sk == NULL ||
10759 sk->direction == dir) ? pd.src : pd.dst, pd.af,
10760 pd.tot_len, dir == PF_OUT, r->action == PF_PASS,
10761 tr->src.neg);
0a7de745
A
10762 }
10763 if (tr->dst.addr.type == PF_ADDR_TABLE) {
b0d623f7
A
10764 pfr_update_stats(tr->dst.addr.p.tbl, (sk == NULL ||
10765 sk->direction == dir) ? pd.dst : pd.src, pd.af,
10766 pd.tot_len, dir == PF_OUT, r->action == PF_PASS,
10767 tr->dst.neg);
0a7de745 10768 }
b0d623f7
A
10769 }
10770
10771#if 0
10772 if (action == PF_SYNPROXY_DROP) {
10773 m_freem(*m0);
10774 *m0 = NULL;
10775 action = PF_PASS;
0a7de745 10776 } else if (r->rt) {
b0d623f7
A
10777 /* pf_route6 can free the mbuf causing *m0 to become NULL */
10778 pf_route6(m0, r, dir, kif->pfik_ifp, s, &pd);
0a7de745 10779 }
b0d623f7 10780#else
5ba3f43e 10781 VERIFY(pbuf == NULL || pd.mp == NULL || pd.mp == pbuf);
b7266188 10782
5ba3f43e 10783 if (*pbufp) {
b0d623f7 10784 if (pd.lmw < 0) {
b7266188
A
10785 REASON_SET(&reason, PFRES_MEMORY);
10786 action = PF_DROP;
10787 }
10788
10789 if (action == PF_DROP) {
5ba3f43e
A
10790 pbuf_destroy(*pbufp);
10791 *pbufp = NULL;
0a7de745 10792 return PF_DROP;
b0d623f7
A
10793 }
10794
5ba3f43e 10795 *pbufp = pbuf;
b0d623f7
A
10796 }
10797
10798 if (action == PF_SYNPROXY_DROP) {
5ba3f43e
A
10799 pbuf_destroy(*pbufp);
10800 *pbufp = NULL;
b0d623f7
A
10801 action = PF_PASS;
10802 } else if (r->rt) {
cb323159 10803 /* pf_route6 can free the mbuf causing *pbufp to become NULL */
5ba3f43e 10804 pf_route6(pbufp, r, dir, kif->pfik_ifp, s, &pd);
b0d623f7 10805 }
316670eb 10806#endif /* 0 */
b0d623f7 10807
cb323159
A
10808 /* if reassembled packet passed, create new fragments */
10809 struct pf_fragment_tag *ftag = NULL;
10810 if ((action == PF_PASS) && (*pbufp != NULL) && (fwd) &&
10811 ((ftag = pf_find_fragment_tag_pbuf(*pbufp)) != NULL)) {
10812 action = pf_refragment6(ifp, pbufp, ftag);
10813 }
0a7de745 10814 return action;
b0d623f7
A
10815}
10816#endif /* INET6 */
10817
10818static int
10819pf_check_congestion(struct ifqueue *ifq)
10820{
10821#pragma unused(ifq)
0a7de745 10822 return 0;
b0d623f7
A
10823}
10824
10825void
10826pool_init(struct pool *pp, size_t size, unsigned int align, unsigned int ioff,
10827 int flags, const char *wchan, void *palloc)
10828{
10829#pragma unused(align, ioff, flags, palloc)
0a7de745 10830 bzero(pp, sizeof(*pp));
b0d623f7
A
10831 pp->pool_zone = zinit(size, 1024 * size, PAGE_SIZE, wchan);
10832 if (pp->pool_zone != NULL) {
10833 zone_change(pp->pool_zone, Z_EXPAND, TRUE);
6d2010ae 10834 zone_change(pp->pool_zone, Z_CALLERACCT, FALSE);
b0d623f7
A
10835 pp->pool_hiwat = pp->pool_limit = (unsigned int)-1;
10836 pp->pool_name = wchan;
10837 }
10838}
10839
10840/* Zones cannot be currently destroyed */
10841void
10842pool_destroy(struct pool *pp)
10843{
10844#pragma unused(pp)
10845}
10846
10847void
10848pool_sethiwat(struct pool *pp, int n)
10849{
0a7de745 10850 pp->pool_hiwat = n; /* Currently unused */
b0d623f7
A
10851}
10852
10853void
10854pool_sethardlimit(struct pool *pp, int n, const char *warnmess, int ratecap)
10855{
10856#pragma unused(warnmess, ratecap)
10857 pp->pool_limit = n;
10858}
10859
10860void *
10861pool_get(struct pool *pp, int flags)
10862{
10863 void *buf;
10864
5ba3f43e 10865 LCK_MTX_ASSERT(pf_lock, LCK_MTX_ASSERT_OWNED);
b0d623f7
A
10866
10867 if (pp->pool_count > pp->pool_limit) {
10868 DPFPRINTF(PF_DEBUG_NOISY,
10869 ("pf: pool %s hard limit reached (%d)\n",
10870 pp->pool_name != NULL ? pp->pool_name : "unknown",
10871 pp->pool_limit));
10872 pp->pool_fails++;
0a7de745 10873 return NULL;
b0d623f7
A
10874 }
10875
10876 buf = zalloc_canblock(pp->pool_zone, (flags & (PR_NOWAIT | PR_WAITOK)));
10877 if (buf != NULL) {
10878 pp->pool_count++;
10879 VERIFY(pp->pool_count != 0);
10880 }
0a7de745 10881 return buf;
b0d623f7
A
10882}
10883
10884void
10885pool_put(struct pool *pp, void *v)
10886{
5ba3f43e 10887 LCK_MTX_ASSERT(pf_lock, LCK_MTX_ASSERT_OWNED);
b0d623f7
A
10888
10889 zfree(pp->pool_zone, v);
10890 VERIFY(pp->pool_count != 0);
10891 pp->pool_count--;
10892}
10893
5ba3f43e
A
10894struct pf_mtag *
10895pf_find_mtag_pbuf(pbuf_t *pbuf)
10896{
0a7de745 10897 return pbuf->pb_pftag;
5ba3f43e
A
10898}
10899
b0d623f7
A
10900struct pf_mtag *
10901pf_find_mtag(struct mbuf *m)
10902{
0a7de745 10903 return m_pftag(m);
b0d623f7
A
10904}
10905
10906struct pf_mtag *
10907pf_get_mtag(struct mbuf *m)
10908{
0a7de745 10909 return pf_find_mtag(m);
b0d623f7
A
10910}
10911
5ba3f43e
A
10912struct pf_mtag *
10913pf_get_mtag_pbuf(pbuf_t *pbuf)
10914{
0a7de745 10915 return pf_find_mtag_pbuf(pbuf);
5ba3f43e
A
10916}
10917
cb323159
A
10918struct pf_fragment_tag *
10919pf_copy_fragment_tag(struct mbuf *m, struct pf_fragment_tag *ftag, int how)
10920{
10921 struct m_tag *tag;
10922 struct pf_mtag *pftag = pf_find_mtag(m);
10923
10924 tag = m_tag_create(KERNEL_MODULE_TAG_ID, KERNEL_TAG_TYPE_PF_REASS,
10925 sizeof(*ftag), how, m);
10926 if (tag == NULL) {
10927 return NULL;
10928 } else {
10929 m_tag_prepend(m, tag);
10930 tag = tag + 1;
10931 }
10932 bcopy(ftag, tag, sizeof(*ftag));
10933 pftag->pftag_flags |= PF_TAG_REASSEMBLED;
10934 return (struct pf_fragment_tag *)tag;
10935}
10936
10937struct pf_fragment_tag *
10938pf_find_fragment_tag(struct mbuf *m)
10939{
10940 struct m_tag *tag;
10941 struct pf_fragment_tag *ftag;
10942 struct pf_mtag *pftag = pf_find_mtag(m);
10943
10944 tag = m_tag_locate(m, KERNEL_MODULE_TAG_ID, KERNEL_TAG_TYPE_PF_REASS,
10945 NULL);
10946 VERIFY((tag == NULL) || (pftag->pftag_flags & PF_TAG_REASSEMBLED));
10947 if (tag != NULL) {
10948 tag = tag + 1;
10949 }
10950 ftag = (struct pf_fragment_tag *)tag;
10951 return ftag;
10952}
10953
10954struct pf_fragment_tag *
10955pf_find_fragment_tag_pbuf(pbuf_t *pbuf)
10956{
10957 struct pf_mtag *mtag = pf_find_mtag_pbuf(pbuf);
10958
10959 return (mtag->pftag_flags & PF_TAG_REASSEMBLED) ?
10960 pbuf->pb_pf_fragtag : NULL;
10961}
10962
b0d623f7
A
10963uint64_t
10964pf_time_second(void)
10965{
10966 struct timeval t;
10967
b7266188 10968 microuptime(&t);
0a7de745 10969 return t.tv_sec;
b7266188
A
10970}
10971
10972uint64_t
10973pf_calendar_time_second(void)
10974{
10975 struct timeval t;
10976
39236c6e 10977 getmicrotime(&t);
0a7de745 10978 return t.tv_sec;
b0d623f7
A
10979}
10980
10981static void *
10982hook_establish(struct hook_desc_head *head, int tail, hook_fn_t fn, void *arg)
10983{
10984 struct hook_desc *hd;
10985
10986 hd = _MALLOC(sizeof(*hd), M_DEVBUF, M_WAITOK);
0a7de745
A
10987 if (hd == NULL) {
10988 return NULL;
10989 }
b0d623f7
A
10990
10991 hd->hd_fn = fn;
10992 hd->hd_arg = arg;
0a7de745 10993 if (tail) {
b0d623f7 10994 TAILQ_INSERT_TAIL(head, hd, hd_list);
0a7de745 10995 } else {
b0d623f7 10996 TAILQ_INSERT_HEAD(head, hd, hd_list);
0a7de745 10997 }
b0d623f7 10998
0a7de745 10999 return hd;
b0d623f7
A
11000}
11001
11002static void
11003hook_runloop(struct hook_desc_head *head, int flags)
11004{
11005 struct hook_desc *hd;
11006
11007 if (!(flags & HOOK_REMOVE)) {
0a7de745 11008 if (!(flags & HOOK_ABORT)) {
b0d623f7 11009 TAILQ_FOREACH(hd, head, hd_list)
0a7de745
A
11010 hd->hd_fn(hd->hd_arg);
11011 }
b0d623f7
A
11012 } else {
11013 while (!!(hd = TAILQ_FIRST(head))) {
11014 TAILQ_REMOVE(head, hd, hd_list);
0a7de745 11015 if (!(flags & HOOK_ABORT)) {
b0d623f7 11016 hd->hd_fn(hd->hd_arg);
0a7de745
A
11017 }
11018 if (flags & HOOK_FREE) {
b0d623f7 11019 _FREE(hd, M_DEVBUF);
0a7de745 11020 }
b0d623f7
A
11021 }
11022 }
11023}