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