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