1*aca3beaaSApple OSS Distributions /*
2*aca3beaaSApple OSS Distributions * Copyright (c) 2007-2021 Apple Inc. All rights reserved.
3*aca3beaaSApple OSS Distributions *
4*aca3beaaSApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*aca3beaaSApple OSS Distributions *
6*aca3beaaSApple OSS Distributions * This file contains Original Code and/or Modifications of Original Code
7*aca3beaaSApple OSS Distributions * as defined in and that are subject to the Apple Public Source License
8*aca3beaaSApple OSS Distributions * Version 2.0 (the 'License'). You may not use this file except in
9*aca3beaaSApple OSS Distributions * compliance with the License. The rights granted to you under the License
10*aca3beaaSApple OSS Distributions * may not be used to create, or enable the creation or redistribution of,
11*aca3beaaSApple OSS Distributions * unlawful or unlicensed copies of an Apple operating system, or to
12*aca3beaaSApple OSS Distributions * circumvent, violate, or enable the circumvention or violation of, any
13*aca3beaaSApple OSS Distributions * terms of an Apple operating system software license agreement.
14*aca3beaaSApple OSS Distributions *
15*aca3beaaSApple OSS Distributions * Please obtain a copy of the License at
16*aca3beaaSApple OSS Distributions * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*aca3beaaSApple OSS Distributions *
18*aca3beaaSApple OSS Distributions * The Original Code and all software distributed under the License are
19*aca3beaaSApple OSS Distributions * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*aca3beaaSApple OSS Distributions * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*aca3beaaSApple OSS Distributions * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*aca3beaaSApple OSS Distributions * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*aca3beaaSApple OSS Distributions * Please see the License for the specific language governing rights and
24*aca3beaaSApple OSS Distributions * limitations under the License.
25*aca3beaaSApple OSS Distributions *
26*aca3beaaSApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*aca3beaaSApple OSS Distributions */
28*aca3beaaSApple OSS Distributions
29*aca3beaaSApple OSS Distributions /* $apfw: pf_if.c,v 1.4 2008/08/27 00:01:32 jhw Exp $ */
30*aca3beaaSApple OSS Distributions /* $OpenBSD: pf_if.c,v 1.46 2006/12/13 09:01:59 itojun Exp $ */
31*aca3beaaSApple OSS Distributions
32*aca3beaaSApple OSS Distributions /*
33*aca3beaaSApple OSS Distributions * Copyright 2005 Henning Brauer <[email protected]>
34*aca3beaaSApple OSS Distributions * Copyright 2005 Ryan McBride <[email protected]>
35*aca3beaaSApple OSS Distributions * Copyright (c) 2001 Daniel Hartmeier
36*aca3beaaSApple OSS Distributions * Copyright (c) 2003 Cedric Berger
37*aca3beaaSApple OSS Distributions * All rights reserved.
38*aca3beaaSApple OSS Distributions *
39*aca3beaaSApple OSS Distributions * Redistribution and use in source and binary forms, with or without
40*aca3beaaSApple OSS Distributions * modification, are permitted provided that the following conditions
41*aca3beaaSApple OSS Distributions * are met:
42*aca3beaaSApple OSS Distributions *
43*aca3beaaSApple OSS Distributions * - Redistributions of source code must retain the above copyright
44*aca3beaaSApple OSS Distributions * notice, this list of conditions and the following disclaimer.
45*aca3beaaSApple OSS Distributions * - Redistributions in binary form must reproduce the above
46*aca3beaaSApple OSS Distributions * copyright notice, this list of conditions and the following
47*aca3beaaSApple OSS Distributions * disclaimer in the documentation and/or other materials provided
48*aca3beaaSApple OSS Distributions * with the distribution.
49*aca3beaaSApple OSS Distributions *
50*aca3beaaSApple OSS Distributions * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
51*aca3beaaSApple OSS Distributions * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
52*aca3beaaSApple OSS Distributions * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
53*aca3beaaSApple OSS Distributions * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
54*aca3beaaSApple OSS Distributions * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
55*aca3beaaSApple OSS Distributions * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
56*aca3beaaSApple OSS Distributions * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
57*aca3beaaSApple OSS Distributions * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
58*aca3beaaSApple OSS Distributions * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
59*aca3beaaSApple OSS Distributions * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
60*aca3beaaSApple OSS Distributions * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
61*aca3beaaSApple OSS Distributions * POSSIBILITY OF SUCH DAMAGE.
62*aca3beaaSApple OSS Distributions */
63*aca3beaaSApple OSS Distributions
64*aca3beaaSApple OSS Distributions #include <sys/param.h>
65*aca3beaaSApple OSS Distributions #include <sys/systm.h>
66*aca3beaaSApple OSS Distributions #include <sys/mbuf.h>
67*aca3beaaSApple OSS Distributions #include <sys/filio.h>
68*aca3beaaSApple OSS Distributions #include <sys/socket.h>
69*aca3beaaSApple OSS Distributions #include <sys/socketvar.h>
70*aca3beaaSApple OSS Distributions #include <sys/kernel.h>
71*aca3beaaSApple OSS Distributions #include <sys/time.h>
72*aca3beaaSApple OSS Distributions #include <sys/malloc.h>
73*aca3beaaSApple OSS Distributions
74*aca3beaaSApple OSS Distributions #include <net/if.h>
75*aca3beaaSApple OSS Distributions #include <net/if_types.h>
76*aca3beaaSApple OSS Distributions #include <net/if_var.h>
77*aca3beaaSApple OSS Distributions
78*aca3beaaSApple OSS Distributions #include <netinet/in.h>
79*aca3beaaSApple OSS Distributions #include <netinet/in_var.h>
80*aca3beaaSApple OSS Distributions #include <netinet/in_systm.h>
81*aca3beaaSApple OSS Distributions #include <netinet/ip.h>
82*aca3beaaSApple OSS Distributions #include <netinet/ip_var.h>
83*aca3beaaSApple OSS Distributions
84*aca3beaaSApple OSS Distributions #include <netinet/ip6.h>
85*aca3beaaSApple OSS Distributions
86*aca3beaaSApple OSS Distributions #include <net/pfvar.h>
87*aca3beaaSApple OSS Distributions
88*aca3beaaSApple OSS Distributions struct pfi_kif *pfi_all = NULL;
89*aca3beaaSApple OSS Distributions
90*aca3beaaSApple OSS Distributions static struct pool pfi_addr_pl;
91*aca3beaaSApple OSS Distributions static struct pfi_ifhead pfi_ifs;
92*aca3beaaSApple OSS Distributions static u_int32_t pfi_update = 1;
93*aca3beaaSApple OSS Distributions static struct pfr_addr *pfi_buffer;
94*aca3beaaSApple OSS Distributions static int pfi_buffer_cnt;
95*aca3beaaSApple OSS Distributions static int pfi_buffer_max;
96*aca3beaaSApple OSS Distributions
97*aca3beaaSApple OSS Distributions __private_extern__ void pfi_kifaddr_update(void *);
98*aca3beaaSApple OSS Distributions
99*aca3beaaSApple OSS Distributions static void pfi_kif_update(struct pfi_kif *);
100*aca3beaaSApple OSS Distributions static void pfi_dynaddr_update(struct pfi_dynaddr *dyn);
101*aca3beaaSApple OSS Distributions static void pfi_table_update(struct pfr_ktable *, struct pfi_kif *, uint8_t, int);
102*aca3beaaSApple OSS Distributions static void pfi_instance_add(struct ifnet *, uint8_t, int);
103*aca3beaaSApple OSS Distributions static void pfi_address_add(struct sockaddr *, uint8_t, uint8_t);
104*aca3beaaSApple OSS Distributions static int pfi_if_compare(struct pfi_kif *, struct pfi_kif *);
105*aca3beaaSApple OSS Distributions static int pfi_skip_if(const char *, struct pfi_kif *);
106*aca3beaaSApple OSS Distributions static uint8_t pfi_unmask(void *);
107*aca3beaaSApple OSS Distributions
108*aca3beaaSApple OSS Distributions RB_PROTOTYPE_SC(static, pfi_ifhead, pfi_kif, pfik_tree, pfi_if_compare);
109*aca3beaaSApple OSS Distributions RB_GENERATE(pfi_ifhead, pfi_kif, pfik_tree, pfi_if_compare);
110*aca3beaaSApple OSS Distributions
111*aca3beaaSApple OSS Distributions #define PFI_BUFFER_MAX 0x10000
112*aca3beaaSApple OSS Distributions
113*aca3beaaSApple OSS Distributions #define IFG_ALL "ALL"
114*aca3beaaSApple OSS Distributions
115*aca3beaaSApple OSS Distributions void
pfi_initialize(void)116*aca3beaaSApple OSS Distributions pfi_initialize(void)
117*aca3beaaSApple OSS Distributions {
118*aca3beaaSApple OSS Distributions if (pfi_all != NULL) { /* already initialized */
119*aca3beaaSApple OSS Distributions return;
120*aca3beaaSApple OSS Distributions }
121*aca3beaaSApple OSS Distributions
122*aca3beaaSApple OSS Distributions pool_init(&pfi_addr_pl, sizeof(struct pfi_dynaddr), 0, 0, 0,
123*aca3beaaSApple OSS Distributions "pfiaddrpl", NULL);
124*aca3beaaSApple OSS Distributions pfi_buffer_max = 64;
125*aca3beaaSApple OSS Distributions pfi_buffer = (struct pfr_addr *)kalloc_data(pfi_buffer_max * sizeof(*pfi_buffer),
126*aca3beaaSApple OSS Distributions Z_WAITOK);
127*aca3beaaSApple OSS Distributions
128*aca3beaaSApple OSS Distributions if ((pfi_all = pfi_kif_get(IFG_ALL)) == NULL) {
129*aca3beaaSApple OSS Distributions panic("pfi_kif_get for pfi_all failed");
130*aca3beaaSApple OSS Distributions }
131*aca3beaaSApple OSS Distributions }
132*aca3beaaSApple OSS Distributions
133*aca3beaaSApple OSS Distributions #if 0
134*aca3beaaSApple OSS Distributions void
135*aca3beaaSApple OSS Distributions pfi_destroy(void)
136*aca3beaaSApple OSS Distributions {
137*aca3beaaSApple OSS Distributions pool_destroy(&pfi_addr_pl);
138*aca3beaaSApple OSS Distributions kfree_data(pfi_buffer, pfi_buffer_max * sizeof(*pfi_buffer));
139*aca3beaaSApple OSS Distributions }
140*aca3beaaSApple OSS Distributions #endif
141*aca3beaaSApple OSS Distributions
142*aca3beaaSApple OSS Distributions struct pfi_kif *
pfi_kif_get(const char * kif_name)143*aca3beaaSApple OSS Distributions pfi_kif_get(const char *kif_name)
144*aca3beaaSApple OSS Distributions {
145*aca3beaaSApple OSS Distributions struct pfi_kif *kif;
146*aca3beaaSApple OSS Distributions struct pfi_kif s;
147*aca3beaaSApple OSS Distributions
148*aca3beaaSApple OSS Distributions bzero(&s.pfik_name, sizeof(s.pfik_name));
149*aca3beaaSApple OSS Distributions strlcpy(s.pfik_name, kif_name, sizeof(s.pfik_name));
150*aca3beaaSApple OSS Distributions kif = RB_FIND(pfi_ifhead, &pfi_ifs, &s);
151*aca3beaaSApple OSS Distributions if (kif != NULL) {
152*aca3beaaSApple OSS Distributions return kif;
153*aca3beaaSApple OSS Distributions }
154*aca3beaaSApple OSS Distributions
155*aca3beaaSApple OSS Distributions /* create new one */
156*aca3beaaSApple OSS Distributions if ((kif = kalloc_type(struct pfi_kif, Z_WAITOK | Z_ZERO)) == NULL) {
157*aca3beaaSApple OSS Distributions return NULL;
158*aca3beaaSApple OSS Distributions }
159*aca3beaaSApple OSS Distributions
160*aca3beaaSApple OSS Distributions strlcpy(kif->pfik_name, kif_name, sizeof(kif->pfik_name));
161*aca3beaaSApple OSS Distributions kif->pfik_tzero = pf_calendar_time_second();
162*aca3beaaSApple OSS Distributions TAILQ_INIT(&kif->pfik_dynaddrs);
163*aca3beaaSApple OSS Distributions
164*aca3beaaSApple OSS Distributions RB_INSERT(pfi_ifhead, &pfi_ifs, kif);
165*aca3beaaSApple OSS Distributions return kif;
166*aca3beaaSApple OSS Distributions }
167*aca3beaaSApple OSS Distributions
168*aca3beaaSApple OSS Distributions void
pfi_kif_ref(struct pfi_kif * kif,enum pfi_kif_refs what)169*aca3beaaSApple OSS Distributions pfi_kif_ref(struct pfi_kif *kif, enum pfi_kif_refs what)
170*aca3beaaSApple OSS Distributions {
171*aca3beaaSApple OSS Distributions switch (what) {
172*aca3beaaSApple OSS Distributions case PFI_KIF_REF_RULE:
173*aca3beaaSApple OSS Distributions kif->pfik_rules++;
174*aca3beaaSApple OSS Distributions break;
175*aca3beaaSApple OSS Distributions case PFI_KIF_REF_STATE:
176*aca3beaaSApple OSS Distributions kif->pfik_states++;
177*aca3beaaSApple OSS Distributions break;
178*aca3beaaSApple OSS Distributions default:
179*aca3beaaSApple OSS Distributions panic("pfi_kif_ref with unknown type");
180*aca3beaaSApple OSS Distributions }
181*aca3beaaSApple OSS Distributions }
182*aca3beaaSApple OSS Distributions
183*aca3beaaSApple OSS Distributions void
pfi_kif_unref(struct pfi_kif * kif,enum pfi_kif_refs what)184*aca3beaaSApple OSS Distributions pfi_kif_unref(struct pfi_kif *kif, enum pfi_kif_refs what)
185*aca3beaaSApple OSS Distributions {
186*aca3beaaSApple OSS Distributions if (kif == NULL) {
187*aca3beaaSApple OSS Distributions return;
188*aca3beaaSApple OSS Distributions }
189*aca3beaaSApple OSS Distributions
190*aca3beaaSApple OSS Distributions switch (what) {
191*aca3beaaSApple OSS Distributions case PFI_KIF_REF_NONE:
192*aca3beaaSApple OSS Distributions break;
193*aca3beaaSApple OSS Distributions case PFI_KIF_REF_RULE:
194*aca3beaaSApple OSS Distributions if (kif->pfik_rules <= 0) {
195*aca3beaaSApple OSS Distributions printf("pfi_kif_unref: rules refcount <= 0\n");
196*aca3beaaSApple OSS Distributions return;
197*aca3beaaSApple OSS Distributions }
198*aca3beaaSApple OSS Distributions kif->pfik_rules--;
199*aca3beaaSApple OSS Distributions break;
200*aca3beaaSApple OSS Distributions case PFI_KIF_REF_STATE:
201*aca3beaaSApple OSS Distributions if (kif->pfik_states <= 0) {
202*aca3beaaSApple OSS Distributions printf("pfi_kif_unref: state refcount <= 0\n");
203*aca3beaaSApple OSS Distributions return;
204*aca3beaaSApple OSS Distributions }
205*aca3beaaSApple OSS Distributions kif->pfik_states--;
206*aca3beaaSApple OSS Distributions break;
207*aca3beaaSApple OSS Distributions default:
208*aca3beaaSApple OSS Distributions panic("pfi_kif_unref with unknown type");
209*aca3beaaSApple OSS Distributions }
210*aca3beaaSApple OSS Distributions
211*aca3beaaSApple OSS Distributions if (kif->pfik_ifp != NULL || kif == pfi_all) {
212*aca3beaaSApple OSS Distributions return;
213*aca3beaaSApple OSS Distributions }
214*aca3beaaSApple OSS Distributions
215*aca3beaaSApple OSS Distributions if (kif->pfik_rules || kif->pfik_states) {
216*aca3beaaSApple OSS Distributions return;
217*aca3beaaSApple OSS Distributions }
218*aca3beaaSApple OSS Distributions
219*aca3beaaSApple OSS Distributions RB_REMOVE(pfi_ifhead, &pfi_ifs, kif);
220*aca3beaaSApple OSS Distributions kfree_type(struct pfi_kif, kif);
221*aca3beaaSApple OSS Distributions }
222*aca3beaaSApple OSS Distributions
223*aca3beaaSApple OSS Distributions int
pfi_kif_match(struct pfi_kif * rule_kif,struct pfi_kif * packet_kif)224*aca3beaaSApple OSS Distributions pfi_kif_match(struct pfi_kif *rule_kif, struct pfi_kif *packet_kif)
225*aca3beaaSApple OSS Distributions {
226*aca3beaaSApple OSS Distributions if (rule_kif == NULL || rule_kif == packet_kif) {
227*aca3beaaSApple OSS Distributions return 1;
228*aca3beaaSApple OSS Distributions }
229*aca3beaaSApple OSS Distributions
230*aca3beaaSApple OSS Distributions return 0;
231*aca3beaaSApple OSS Distributions }
232*aca3beaaSApple OSS Distributions
233*aca3beaaSApple OSS Distributions void
pfi_attach_ifnet(struct ifnet * ifp)234*aca3beaaSApple OSS Distributions pfi_attach_ifnet(struct ifnet *ifp)
235*aca3beaaSApple OSS Distributions {
236*aca3beaaSApple OSS Distributions struct pfi_kif *kif;
237*aca3beaaSApple OSS Distributions
238*aca3beaaSApple OSS Distributions LCK_MTX_ASSERT(&pf_lock, LCK_MTX_ASSERT_OWNED);
239*aca3beaaSApple OSS Distributions
240*aca3beaaSApple OSS Distributions pfi_update++;
241*aca3beaaSApple OSS Distributions if ((kif = pfi_kif_get(if_name(ifp))) == NULL) {
242*aca3beaaSApple OSS Distributions panic("pfi_kif_get failed");
243*aca3beaaSApple OSS Distributions }
244*aca3beaaSApple OSS Distributions
245*aca3beaaSApple OSS Distributions ifnet_lock_exclusive(ifp);
246*aca3beaaSApple OSS Distributions kif->pfik_ifp = ifp;
247*aca3beaaSApple OSS Distributions ifp->if_pf_kif = kif;
248*aca3beaaSApple OSS Distributions ifnet_lock_done(ifp);
249*aca3beaaSApple OSS Distributions
250*aca3beaaSApple OSS Distributions pfi_kif_update(kif);
251*aca3beaaSApple OSS Distributions }
252*aca3beaaSApple OSS Distributions
253*aca3beaaSApple OSS Distributions /*
254*aca3beaaSApple OSS Distributions * Caller holds ifnet lock as writer (exclusive);
255*aca3beaaSApple OSS Distributions */
256*aca3beaaSApple OSS Distributions void
pfi_detach_ifnet(struct ifnet * ifp)257*aca3beaaSApple OSS Distributions pfi_detach_ifnet(struct ifnet *ifp)
258*aca3beaaSApple OSS Distributions {
259*aca3beaaSApple OSS Distributions struct pfi_kif *kif;
260*aca3beaaSApple OSS Distributions
261*aca3beaaSApple OSS Distributions LCK_MTX_ASSERT(&pf_lock, LCK_MTX_ASSERT_OWNED);
262*aca3beaaSApple OSS Distributions
263*aca3beaaSApple OSS Distributions if ((kif = (struct pfi_kif *)ifp->if_pf_kif) == NULL) {
264*aca3beaaSApple OSS Distributions return;
265*aca3beaaSApple OSS Distributions }
266*aca3beaaSApple OSS Distributions
267*aca3beaaSApple OSS Distributions pfi_update++;
268*aca3beaaSApple OSS Distributions pfi_kif_update(kif);
269*aca3beaaSApple OSS Distributions
270*aca3beaaSApple OSS Distributions ifnet_lock_exclusive(ifp);
271*aca3beaaSApple OSS Distributions kif->pfik_ifp = NULL;
272*aca3beaaSApple OSS Distributions ifp->if_pf_kif = NULL;
273*aca3beaaSApple OSS Distributions ifnet_lock_done(ifp);
274*aca3beaaSApple OSS Distributions
275*aca3beaaSApple OSS Distributions pfi_kif_unref(kif, PFI_KIF_REF_NONE);
276*aca3beaaSApple OSS Distributions }
277*aca3beaaSApple OSS Distributions
278*aca3beaaSApple OSS Distributions int
pfi_match_addr(struct pfi_dynaddr * dyn,struct pf_addr * a,sa_family_t af)279*aca3beaaSApple OSS Distributions pfi_match_addr(struct pfi_dynaddr *dyn, struct pf_addr *a, sa_family_t af)
280*aca3beaaSApple OSS Distributions {
281*aca3beaaSApple OSS Distributions switch (af) {
282*aca3beaaSApple OSS Distributions #if INET
283*aca3beaaSApple OSS Distributions case AF_INET:
284*aca3beaaSApple OSS Distributions switch (dyn->pfid_acnt4) {
285*aca3beaaSApple OSS Distributions case 0:
286*aca3beaaSApple OSS Distributions return 0;
287*aca3beaaSApple OSS Distributions case 1:
288*aca3beaaSApple OSS Distributions return PF_MATCHA(0, &dyn->pfid_addr4,
289*aca3beaaSApple OSS Distributions &dyn->pfid_mask4, a, AF_INET);
290*aca3beaaSApple OSS Distributions default:
291*aca3beaaSApple OSS Distributions return pfr_match_addr(dyn->pfid_kt, a, AF_INET);
292*aca3beaaSApple OSS Distributions }
293*aca3beaaSApple OSS Distributions #endif /* INET */
294*aca3beaaSApple OSS Distributions case AF_INET6:
295*aca3beaaSApple OSS Distributions switch (dyn->pfid_acnt6) {
296*aca3beaaSApple OSS Distributions case 0:
297*aca3beaaSApple OSS Distributions return 0;
298*aca3beaaSApple OSS Distributions case 1:
299*aca3beaaSApple OSS Distributions return PF_MATCHA(0, &dyn->pfid_addr6,
300*aca3beaaSApple OSS Distributions &dyn->pfid_mask6, a, AF_INET6);
301*aca3beaaSApple OSS Distributions default:
302*aca3beaaSApple OSS Distributions return pfr_match_addr(dyn->pfid_kt, a, AF_INET6);
303*aca3beaaSApple OSS Distributions }
304*aca3beaaSApple OSS Distributions default:
305*aca3beaaSApple OSS Distributions return 0;
306*aca3beaaSApple OSS Distributions }
307*aca3beaaSApple OSS Distributions }
308*aca3beaaSApple OSS Distributions
309*aca3beaaSApple OSS Distributions int
pfi_dynaddr_setup(struct pf_addr_wrap * aw,sa_family_t af)310*aca3beaaSApple OSS Distributions pfi_dynaddr_setup(struct pf_addr_wrap *aw, sa_family_t af)
311*aca3beaaSApple OSS Distributions {
312*aca3beaaSApple OSS Distributions struct pfi_dynaddr *dyn;
313*aca3beaaSApple OSS Distributions char tblname[PF_TABLE_NAME_SIZE];
314*aca3beaaSApple OSS Distributions struct pf_ruleset *ruleset = NULL;
315*aca3beaaSApple OSS Distributions int rv = 0;
316*aca3beaaSApple OSS Distributions
317*aca3beaaSApple OSS Distributions LCK_MTX_ASSERT(&pf_lock, LCK_MTX_ASSERT_OWNED);
318*aca3beaaSApple OSS Distributions
319*aca3beaaSApple OSS Distributions if (aw->type != PF_ADDR_DYNIFTL) {
320*aca3beaaSApple OSS Distributions return 0;
321*aca3beaaSApple OSS Distributions }
322*aca3beaaSApple OSS Distributions if ((dyn = pool_get(&pfi_addr_pl, PR_WAITOK)) == NULL) {
323*aca3beaaSApple OSS Distributions return 1;
324*aca3beaaSApple OSS Distributions }
325*aca3beaaSApple OSS Distributions bzero(dyn, sizeof(*dyn));
326*aca3beaaSApple OSS Distributions
327*aca3beaaSApple OSS Distributions if (strcmp(aw->v.ifname, "self") == 0) {
328*aca3beaaSApple OSS Distributions dyn->pfid_kif = pfi_kif_get(IFG_ALL);
329*aca3beaaSApple OSS Distributions } else {
330*aca3beaaSApple OSS Distributions dyn->pfid_kif = pfi_kif_get(aw->v.ifname);
331*aca3beaaSApple OSS Distributions }
332*aca3beaaSApple OSS Distributions if (dyn->pfid_kif == NULL) {
333*aca3beaaSApple OSS Distributions rv = 1;
334*aca3beaaSApple OSS Distributions goto _bad;
335*aca3beaaSApple OSS Distributions }
336*aca3beaaSApple OSS Distributions pfi_kif_ref(dyn->pfid_kif, PFI_KIF_REF_RULE);
337*aca3beaaSApple OSS Distributions
338*aca3beaaSApple OSS Distributions dyn->pfid_net = pfi_unmask(&aw->v.a.mask);
339*aca3beaaSApple OSS Distributions if (af == AF_INET && dyn->pfid_net == 32) {
340*aca3beaaSApple OSS Distributions dyn->pfid_net = 128;
341*aca3beaaSApple OSS Distributions }
342*aca3beaaSApple OSS Distributions strlcpy(tblname, aw->v.ifname, sizeof(tblname));
343*aca3beaaSApple OSS Distributions if (aw->iflags & PFI_AFLAG_NETWORK) {
344*aca3beaaSApple OSS Distributions strlcat(tblname, ":network", sizeof(tblname));
345*aca3beaaSApple OSS Distributions }
346*aca3beaaSApple OSS Distributions if (aw->iflags & PFI_AFLAG_BROADCAST) {
347*aca3beaaSApple OSS Distributions strlcat(tblname, ":broadcast", sizeof(tblname));
348*aca3beaaSApple OSS Distributions }
349*aca3beaaSApple OSS Distributions if (aw->iflags & PFI_AFLAG_PEER) {
350*aca3beaaSApple OSS Distributions strlcat(tblname, ":peer", sizeof(tblname));
351*aca3beaaSApple OSS Distributions }
352*aca3beaaSApple OSS Distributions if (aw->iflags & PFI_AFLAG_NOALIAS) {
353*aca3beaaSApple OSS Distributions strlcat(tblname, ":0", sizeof(tblname));
354*aca3beaaSApple OSS Distributions }
355*aca3beaaSApple OSS Distributions if (dyn->pfid_net != 128) {
356*aca3beaaSApple OSS Distributions snprintf(tblname + strlen(tblname),
357*aca3beaaSApple OSS Distributions sizeof(tblname) - strlen(tblname), "/%d", dyn->pfid_net);
358*aca3beaaSApple OSS Distributions }
359*aca3beaaSApple OSS Distributions if ((ruleset = pf_find_or_create_ruleset(PF_RESERVED_ANCHOR)) == NULL) {
360*aca3beaaSApple OSS Distributions rv = 1;
361*aca3beaaSApple OSS Distributions goto _bad;
362*aca3beaaSApple OSS Distributions }
363*aca3beaaSApple OSS Distributions
364*aca3beaaSApple OSS Distributions if ((dyn->pfid_kt = pfr_attach_table(ruleset, tblname)) == NULL) {
365*aca3beaaSApple OSS Distributions rv = 1;
366*aca3beaaSApple OSS Distributions goto _bad;
367*aca3beaaSApple OSS Distributions }
368*aca3beaaSApple OSS Distributions
369*aca3beaaSApple OSS Distributions dyn->pfid_kt->pfrkt_flags |= PFR_TFLAG_ACTIVE;
370*aca3beaaSApple OSS Distributions dyn->pfid_iflags = aw->iflags;
371*aca3beaaSApple OSS Distributions dyn->pfid_af = af;
372*aca3beaaSApple OSS Distributions
373*aca3beaaSApple OSS Distributions TAILQ_INSERT_TAIL(&dyn->pfid_kif->pfik_dynaddrs, dyn, entry);
374*aca3beaaSApple OSS Distributions aw->p.dyn = dyn;
375*aca3beaaSApple OSS Distributions pfi_kif_update(dyn->pfid_kif);
376*aca3beaaSApple OSS Distributions return 0;
377*aca3beaaSApple OSS Distributions
378*aca3beaaSApple OSS Distributions _bad:
379*aca3beaaSApple OSS Distributions if (dyn->pfid_kt != NULL) {
380*aca3beaaSApple OSS Distributions pfr_detach_table(dyn->pfid_kt);
381*aca3beaaSApple OSS Distributions }
382*aca3beaaSApple OSS Distributions if (ruleset != NULL) {
383*aca3beaaSApple OSS Distributions pf_release_ruleset(ruleset);
384*aca3beaaSApple OSS Distributions }
385*aca3beaaSApple OSS Distributions if (dyn->pfid_kif != NULL) {
386*aca3beaaSApple OSS Distributions pfi_kif_unref(dyn->pfid_kif, PFI_KIF_REF_RULE);
387*aca3beaaSApple OSS Distributions }
388*aca3beaaSApple OSS Distributions pool_put(&pfi_addr_pl, dyn);
389*aca3beaaSApple OSS Distributions return rv;
390*aca3beaaSApple OSS Distributions }
391*aca3beaaSApple OSS Distributions
392*aca3beaaSApple OSS Distributions void
pfi_kif_update(struct pfi_kif * kif)393*aca3beaaSApple OSS Distributions pfi_kif_update(struct pfi_kif *kif)
394*aca3beaaSApple OSS Distributions {
395*aca3beaaSApple OSS Distributions struct pfi_dynaddr *p;
396*aca3beaaSApple OSS Distributions
397*aca3beaaSApple OSS Distributions LCK_MTX_ASSERT(&pf_lock, LCK_MTX_ASSERT_OWNED);
398*aca3beaaSApple OSS Distributions
399*aca3beaaSApple OSS Distributions /* update all dynaddr */
400*aca3beaaSApple OSS Distributions TAILQ_FOREACH(p, &kif->pfik_dynaddrs, entry)
401*aca3beaaSApple OSS Distributions pfi_dynaddr_update(p);
402*aca3beaaSApple OSS Distributions }
403*aca3beaaSApple OSS Distributions
404*aca3beaaSApple OSS Distributions void
pfi_dynaddr_update(struct pfi_dynaddr * dyn)405*aca3beaaSApple OSS Distributions pfi_dynaddr_update(struct pfi_dynaddr *dyn)
406*aca3beaaSApple OSS Distributions {
407*aca3beaaSApple OSS Distributions struct pfi_kif *kif;
408*aca3beaaSApple OSS Distributions struct pfr_ktable *kt;
409*aca3beaaSApple OSS Distributions
410*aca3beaaSApple OSS Distributions if (dyn == NULL || dyn->pfid_kif == NULL || dyn->pfid_kt == NULL) {
411*aca3beaaSApple OSS Distributions panic("pfi_dynaddr_update");
412*aca3beaaSApple OSS Distributions }
413*aca3beaaSApple OSS Distributions
414*aca3beaaSApple OSS Distributions kif = dyn->pfid_kif;
415*aca3beaaSApple OSS Distributions kt = dyn->pfid_kt;
416*aca3beaaSApple OSS Distributions
417*aca3beaaSApple OSS Distributions if (kt->pfrkt_larg != pfi_update) {
418*aca3beaaSApple OSS Distributions /* this table needs to be brought up-to-date */
419*aca3beaaSApple OSS Distributions pfi_table_update(kt, kif, dyn->pfid_net, dyn->pfid_iflags);
420*aca3beaaSApple OSS Distributions kt->pfrkt_larg = pfi_update;
421*aca3beaaSApple OSS Distributions }
422*aca3beaaSApple OSS Distributions pfr_dynaddr_update(kt, dyn);
423*aca3beaaSApple OSS Distributions }
424*aca3beaaSApple OSS Distributions
425*aca3beaaSApple OSS Distributions void
pfi_table_update(struct pfr_ktable * kt,struct pfi_kif * kif,uint8_t net,int flags)426*aca3beaaSApple OSS Distributions pfi_table_update(struct pfr_ktable *kt, struct pfi_kif *kif, uint8_t net, int flags)
427*aca3beaaSApple OSS Distributions {
428*aca3beaaSApple OSS Distributions int e, size2 = 0;
429*aca3beaaSApple OSS Distributions
430*aca3beaaSApple OSS Distributions pfi_buffer_cnt = 0;
431*aca3beaaSApple OSS Distributions
432*aca3beaaSApple OSS Distributions if (kif->pfik_ifp != NULL) {
433*aca3beaaSApple OSS Distributions pfi_instance_add(kif->pfik_ifp, net, flags);
434*aca3beaaSApple OSS Distributions }
435*aca3beaaSApple OSS Distributions
436*aca3beaaSApple OSS Distributions if ((e = pfr_set_addrs(&kt->pfrkt_t, CAST_USER_ADDR_T(pfi_buffer),
437*aca3beaaSApple OSS Distributions pfi_buffer_cnt, &size2, NULL, NULL, NULL, 0, PFR_TFLAG_ALLMASK))) {
438*aca3beaaSApple OSS Distributions printf("pfi_table_update: cannot set %d new addresses "
439*aca3beaaSApple OSS Distributions "into table %s: %d\n", pfi_buffer_cnt, kt->pfrkt_name, e);
440*aca3beaaSApple OSS Distributions }
441*aca3beaaSApple OSS Distributions }
442*aca3beaaSApple OSS Distributions
443*aca3beaaSApple OSS Distributions void
pfi_instance_add(struct ifnet * ifp,uint8_t net,int flags)444*aca3beaaSApple OSS Distributions pfi_instance_add(struct ifnet *ifp, uint8_t net, int flags)
445*aca3beaaSApple OSS Distributions {
446*aca3beaaSApple OSS Distributions struct ifaddr *ia;
447*aca3beaaSApple OSS Distributions int got4 = 0, got6 = 0;
448*aca3beaaSApple OSS Distributions uint8_t net2, af;
449*aca3beaaSApple OSS Distributions
450*aca3beaaSApple OSS Distributions if (ifp == NULL) {
451*aca3beaaSApple OSS Distributions return;
452*aca3beaaSApple OSS Distributions }
453*aca3beaaSApple OSS Distributions ifnet_lock_shared(ifp);
454*aca3beaaSApple OSS Distributions TAILQ_FOREACH(ia, &ifp->if_addrhead, ifa_link) {
455*aca3beaaSApple OSS Distributions IFA_LOCK(ia);
456*aca3beaaSApple OSS Distributions if (ia->ifa_addr == NULL) {
457*aca3beaaSApple OSS Distributions IFA_UNLOCK(ia);
458*aca3beaaSApple OSS Distributions continue;
459*aca3beaaSApple OSS Distributions }
460*aca3beaaSApple OSS Distributions af = ia->ifa_addr->sa_family;
461*aca3beaaSApple OSS Distributions if (af != AF_INET && af != AF_INET6) {
462*aca3beaaSApple OSS Distributions IFA_UNLOCK(ia);
463*aca3beaaSApple OSS Distributions continue;
464*aca3beaaSApple OSS Distributions }
465*aca3beaaSApple OSS Distributions if ((flags & PFI_AFLAG_BROADCAST) && af == AF_INET6) {
466*aca3beaaSApple OSS Distributions IFA_UNLOCK(ia);
467*aca3beaaSApple OSS Distributions continue;
468*aca3beaaSApple OSS Distributions }
469*aca3beaaSApple OSS Distributions if ((flags & PFI_AFLAG_BROADCAST) &&
470*aca3beaaSApple OSS Distributions !(ifp->if_flags & IFF_BROADCAST)) {
471*aca3beaaSApple OSS Distributions IFA_UNLOCK(ia);
472*aca3beaaSApple OSS Distributions continue;
473*aca3beaaSApple OSS Distributions }
474*aca3beaaSApple OSS Distributions if ((flags & PFI_AFLAG_PEER) &&
475*aca3beaaSApple OSS Distributions !(ifp->if_flags & IFF_POINTOPOINT)) {
476*aca3beaaSApple OSS Distributions IFA_UNLOCK(ia);
477*aca3beaaSApple OSS Distributions continue;
478*aca3beaaSApple OSS Distributions }
479*aca3beaaSApple OSS Distributions if ((af == AF_INET6) &&
480*aca3beaaSApple OSS Distributions IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)
481*aca3beaaSApple OSS Distributions (void *)ia->ifa_addr)->sin6_addr)) {
482*aca3beaaSApple OSS Distributions IFA_UNLOCK(ia);
483*aca3beaaSApple OSS Distributions continue;
484*aca3beaaSApple OSS Distributions }
485*aca3beaaSApple OSS Distributions if ((af == AF_INET6) &&
486*aca3beaaSApple OSS Distributions (((struct in6_ifaddr *)ia)->ia6_flags &
487*aca3beaaSApple OSS Distributions (IN6_IFF_ANYCAST | IN6_IFF_NOTREADY | IN6_IFF_DETACHED |
488*aca3beaaSApple OSS Distributions IN6_IFF_CLAT46 | IN6_IFF_TEMPORARY | IN6_IFF_DEPRECATED))) {
489*aca3beaaSApple OSS Distributions IFA_UNLOCK(ia);
490*aca3beaaSApple OSS Distributions continue;
491*aca3beaaSApple OSS Distributions }
492*aca3beaaSApple OSS Distributions if (flags & PFI_AFLAG_NOALIAS) {
493*aca3beaaSApple OSS Distributions if (af == AF_INET && got4) {
494*aca3beaaSApple OSS Distributions IFA_UNLOCK(ia);
495*aca3beaaSApple OSS Distributions continue;
496*aca3beaaSApple OSS Distributions }
497*aca3beaaSApple OSS Distributions if (af == AF_INET6 && got6) {
498*aca3beaaSApple OSS Distributions IFA_UNLOCK(ia);
499*aca3beaaSApple OSS Distributions continue;
500*aca3beaaSApple OSS Distributions }
501*aca3beaaSApple OSS Distributions }
502*aca3beaaSApple OSS Distributions if (af == AF_INET) {
503*aca3beaaSApple OSS Distributions got4 = 1;
504*aca3beaaSApple OSS Distributions } else if (af == AF_INET6) {
505*aca3beaaSApple OSS Distributions got6 = 1;
506*aca3beaaSApple OSS Distributions }
507*aca3beaaSApple OSS Distributions net2 = net;
508*aca3beaaSApple OSS Distributions if (net2 == 128 && (flags & PFI_AFLAG_NETWORK)) {
509*aca3beaaSApple OSS Distributions if (af == AF_INET) {
510*aca3beaaSApple OSS Distributions net2 = pfi_unmask(&((struct sockaddr_in *)
511*aca3beaaSApple OSS Distributions (void *)ia->ifa_netmask)->sin_addr);
512*aca3beaaSApple OSS Distributions } else if (af == AF_INET6) {
513*aca3beaaSApple OSS Distributions net2 = pfi_unmask(&((struct sockaddr_in6 *)
514*aca3beaaSApple OSS Distributions (void *)ia->ifa_netmask)->sin6_addr);
515*aca3beaaSApple OSS Distributions }
516*aca3beaaSApple OSS Distributions }
517*aca3beaaSApple OSS Distributions if (af == AF_INET && net2 > 32) {
518*aca3beaaSApple OSS Distributions net2 = 32;
519*aca3beaaSApple OSS Distributions }
520*aca3beaaSApple OSS Distributions if (flags & PFI_AFLAG_BROADCAST) {
521*aca3beaaSApple OSS Distributions pfi_address_add(ia->ifa_broadaddr, af, net2);
522*aca3beaaSApple OSS Distributions } else if (flags & PFI_AFLAG_PEER) {
523*aca3beaaSApple OSS Distributions pfi_address_add(ia->ifa_dstaddr, af, net2);
524*aca3beaaSApple OSS Distributions } else {
525*aca3beaaSApple OSS Distributions pfi_address_add(ia->ifa_addr, af, net2);
526*aca3beaaSApple OSS Distributions }
527*aca3beaaSApple OSS Distributions IFA_UNLOCK(ia);
528*aca3beaaSApple OSS Distributions }
529*aca3beaaSApple OSS Distributions ifnet_lock_done(ifp);
530*aca3beaaSApple OSS Distributions }
531*aca3beaaSApple OSS Distributions
532*aca3beaaSApple OSS Distributions void
pfi_address_add(struct sockaddr * sa,uint8_t af,uint8_t net)533*aca3beaaSApple OSS Distributions pfi_address_add(struct sockaddr *sa, uint8_t af, uint8_t net)
534*aca3beaaSApple OSS Distributions {
535*aca3beaaSApple OSS Distributions struct pfr_addr *p;
536*aca3beaaSApple OSS Distributions int i;
537*aca3beaaSApple OSS Distributions
538*aca3beaaSApple OSS Distributions if (pfi_buffer_cnt >= pfi_buffer_max) {
539*aca3beaaSApple OSS Distributions int new_max = pfi_buffer_max * 2;
540*aca3beaaSApple OSS Distributions
541*aca3beaaSApple OSS Distributions if (new_max > PFI_BUFFER_MAX) {
542*aca3beaaSApple OSS Distributions printf("pfi_address_add: address buffer full (%d/%d)\n",
543*aca3beaaSApple OSS Distributions pfi_buffer_cnt, PFI_BUFFER_MAX);
544*aca3beaaSApple OSS Distributions return;
545*aca3beaaSApple OSS Distributions }
546*aca3beaaSApple OSS Distributions p = (struct pfr_addr *)kalloc_data(new_max * sizeof(*pfi_buffer),
547*aca3beaaSApple OSS Distributions Z_WAITOK);
548*aca3beaaSApple OSS Distributions if (p == NULL) {
549*aca3beaaSApple OSS Distributions printf("pfi_address_add: no memory to grow buffer "
550*aca3beaaSApple OSS Distributions "(%d/%d)\n", pfi_buffer_cnt, PFI_BUFFER_MAX);
551*aca3beaaSApple OSS Distributions return;
552*aca3beaaSApple OSS Distributions }
553*aca3beaaSApple OSS Distributions memcpy(p, pfi_buffer, pfi_buffer_max * sizeof(*pfi_buffer));
554*aca3beaaSApple OSS Distributions /* no need to zero buffer */
555*aca3beaaSApple OSS Distributions kfree_data(pfi_buffer, pfi_buffer_max * sizeof(*pfi_buffer));
556*aca3beaaSApple OSS Distributions pfi_buffer = p;
557*aca3beaaSApple OSS Distributions pfi_buffer_max = new_max;
558*aca3beaaSApple OSS Distributions }
559*aca3beaaSApple OSS Distributions if (af == AF_INET && net > 32) {
560*aca3beaaSApple OSS Distributions net = 128;
561*aca3beaaSApple OSS Distributions }
562*aca3beaaSApple OSS Distributions p = pfi_buffer + pfi_buffer_cnt++;
563*aca3beaaSApple OSS Distributions bzero(p, sizeof(*p));
564*aca3beaaSApple OSS Distributions p->pfra_af = af;
565*aca3beaaSApple OSS Distributions p->pfra_net = net;
566*aca3beaaSApple OSS Distributions if (af == AF_INET) {
567*aca3beaaSApple OSS Distributions p->pfra_ip4addr = ((struct sockaddr_in *)(void *)sa)->sin_addr;
568*aca3beaaSApple OSS Distributions } else if (af == AF_INET6) {
569*aca3beaaSApple OSS Distributions p->pfra_ip6addr =
570*aca3beaaSApple OSS Distributions ((struct sockaddr_in6 *)(void *)sa)->sin6_addr;
571*aca3beaaSApple OSS Distributions if (IN6_IS_SCOPE_EMBED(&p->pfra_ip6addr)) {
572*aca3beaaSApple OSS Distributions p->pfra_ip6addr.s6_addr16[1] = 0;
573*aca3beaaSApple OSS Distributions }
574*aca3beaaSApple OSS Distributions }
575*aca3beaaSApple OSS Distributions /* mask network address bits */
576*aca3beaaSApple OSS Distributions if (net < 128) {
577*aca3beaaSApple OSS Distributions ((caddr_t)p)[p->pfra_net / 8] &= ~(0xFF >> (p->pfra_net % 8));
578*aca3beaaSApple OSS Distributions }
579*aca3beaaSApple OSS Distributions for (i = (p->pfra_net + 7) / 8; i < (int)sizeof(p->pfra_u); i++) {
580*aca3beaaSApple OSS Distributions ((caddr_t)p)[i] = 0;
581*aca3beaaSApple OSS Distributions }
582*aca3beaaSApple OSS Distributions }
583*aca3beaaSApple OSS Distributions
584*aca3beaaSApple OSS Distributions void
pfi_dynaddr_remove(struct pf_addr_wrap * aw)585*aca3beaaSApple OSS Distributions pfi_dynaddr_remove(struct pf_addr_wrap *aw)
586*aca3beaaSApple OSS Distributions {
587*aca3beaaSApple OSS Distributions if (aw->type != PF_ADDR_DYNIFTL || aw->p.dyn == NULL ||
588*aca3beaaSApple OSS Distributions aw->p.dyn->pfid_kif == NULL || aw->p.dyn->pfid_kt == NULL) {
589*aca3beaaSApple OSS Distributions return;
590*aca3beaaSApple OSS Distributions }
591*aca3beaaSApple OSS Distributions
592*aca3beaaSApple OSS Distributions TAILQ_REMOVE(&aw->p.dyn->pfid_kif->pfik_dynaddrs, aw->p.dyn, entry);
593*aca3beaaSApple OSS Distributions pfi_kif_unref(aw->p.dyn->pfid_kif, PFI_KIF_REF_RULE);
594*aca3beaaSApple OSS Distributions aw->p.dyn->pfid_kif = NULL;
595*aca3beaaSApple OSS Distributions pfr_detach_table(aw->p.dyn->pfid_kt);
596*aca3beaaSApple OSS Distributions aw->p.dyn->pfid_kt = NULL;
597*aca3beaaSApple OSS Distributions pool_put(&pfi_addr_pl, aw->p.dyn);
598*aca3beaaSApple OSS Distributions aw->p.dyn = NULL;
599*aca3beaaSApple OSS Distributions }
600*aca3beaaSApple OSS Distributions
601*aca3beaaSApple OSS Distributions void
pfi_dynaddr_copyout(struct pf_addr_wrap * aw)602*aca3beaaSApple OSS Distributions pfi_dynaddr_copyout(struct pf_addr_wrap *aw)
603*aca3beaaSApple OSS Distributions {
604*aca3beaaSApple OSS Distributions if (aw->type != PF_ADDR_DYNIFTL || aw->p.dyn == NULL ||
605*aca3beaaSApple OSS Distributions aw->p.dyn->pfid_kif == NULL) {
606*aca3beaaSApple OSS Distributions return;
607*aca3beaaSApple OSS Distributions }
608*aca3beaaSApple OSS Distributions aw->p.dyncnt = aw->p.dyn->pfid_acnt4 + aw->p.dyn->pfid_acnt6;
609*aca3beaaSApple OSS Distributions }
610*aca3beaaSApple OSS Distributions
611*aca3beaaSApple OSS Distributions void
pfi_kifaddr_update(void * v)612*aca3beaaSApple OSS Distributions pfi_kifaddr_update(void *v)
613*aca3beaaSApple OSS Distributions {
614*aca3beaaSApple OSS Distributions struct pfi_kif *kif = (struct pfi_kif *)v;
615*aca3beaaSApple OSS Distributions
616*aca3beaaSApple OSS Distributions LCK_MTX_ASSERT(&pf_lock, LCK_MTX_ASSERT_OWNED);
617*aca3beaaSApple OSS Distributions
618*aca3beaaSApple OSS Distributions pfi_update++;
619*aca3beaaSApple OSS Distributions pfi_kif_update(kif);
620*aca3beaaSApple OSS Distributions }
621*aca3beaaSApple OSS Distributions
622*aca3beaaSApple OSS Distributions int
pfi_if_compare(struct pfi_kif * p,struct pfi_kif * q)623*aca3beaaSApple OSS Distributions pfi_if_compare(struct pfi_kif *p, struct pfi_kif *q)
624*aca3beaaSApple OSS Distributions {
625*aca3beaaSApple OSS Distributions return strncmp(p->pfik_name, q->pfik_name, IFNAMSIZ - 1);
626*aca3beaaSApple OSS Distributions }
627*aca3beaaSApple OSS Distributions
628*aca3beaaSApple OSS Distributions void
pfi_update_status(const char * name,struct pf_status * pfs)629*aca3beaaSApple OSS Distributions pfi_update_status(const char *name, struct pf_status *pfs)
630*aca3beaaSApple OSS Distributions {
631*aca3beaaSApple OSS Distributions struct pfi_kif *p;
632*aca3beaaSApple OSS Distributions struct pfi_kif key;
633*aca3beaaSApple OSS Distributions int i, j, k;
634*aca3beaaSApple OSS Distributions
635*aca3beaaSApple OSS Distributions LCK_MTX_ASSERT(&pf_lock, LCK_MTX_ASSERT_OWNED);
636*aca3beaaSApple OSS Distributions
637*aca3beaaSApple OSS Distributions bzero(&key.pfik_name, sizeof(key.pfik_name));
638*aca3beaaSApple OSS Distributions strlcpy(key.pfik_name, name, sizeof(key.pfik_name));
639*aca3beaaSApple OSS Distributions p = RB_FIND(pfi_ifhead, &pfi_ifs, &key);
640*aca3beaaSApple OSS Distributions if (p == NULL) {
641*aca3beaaSApple OSS Distributions return;
642*aca3beaaSApple OSS Distributions }
643*aca3beaaSApple OSS Distributions
644*aca3beaaSApple OSS Distributions if (pfs != NULL) {
645*aca3beaaSApple OSS Distributions bzero(pfs->pcounters, sizeof(pfs->pcounters));
646*aca3beaaSApple OSS Distributions bzero(pfs->bcounters, sizeof(pfs->bcounters));
647*aca3beaaSApple OSS Distributions for (i = 0; i < 2; i++) {
648*aca3beaaSApple OSS Distributions for (j = 0; j < 2; j++) {
649*aca3beaaSApple OSS Distributions for (k = 0; k < 2; k++) {
650*aca3beaaSApple OSS Distributions pfs->pcounters[i][j][k] +=
651*aca3beaaSApple OSS Distributions p->pfik_packets[i][j][k];
652*aca3beaaSApple OSS Distributions pfs->bcounters[i][j] +=
653*aca3beaaSApple OSS Distributions p->pfik_bytes[i][j][k];
654*aca3beaaSApple OSS Distributions }
655*aca3beaaSApple OSS Distributions }
656*aca3beaaSApple OSS Distributions }
657*aca3beaaSApple OSS Distributions } else {
658*aca3beaaSApple OSS Distributions /* just clear statistics */
659*aca3beaaSApple OSS Distributions bzero(p->pfik_packets, sizeof(p->pfik_packets));
660*aca3beaaSApple OSS Distributions bzero(p->pfik_bytes, sizeof(p->pfik_bytes));
661*aca3beaaSApple OSS Distributions p->pfik_tzero = pf_calendar_time_second();
662*aca3beaaSApple OSS Distributions }
663*aca3beaaSApple OSS Distributions }
664*aca3beaaSApple OSS Distributions
665*aca3beaaSApple OSS Distributions int
pfi_get_ifaces(const char * name,user_addr_t buf,int * size)666*aca3beaaSApple OSS Distributions pfi_get_ifaces(const char *name, user_addr_t buf, int *size)
667*aca3beaaSApple OSS Distributions {
668*aca3beaaSApple OSS Distributions struct pfi_kif *p, *nextp;
669*aca3beaaSApple OSS Distributions int n = 0;
670*aca3beaaSApple OSS Distributions
671*aca3beaaSApple OSS Distributions LCK_MTX_ASSERT(&pf_lock, LCK_MTX_ASSERT_OWNED);
672*aca3beaaSApple OSS Distributions
673*aca3beaaSApple OSS Distributions for (p = RB_MIN(pfi_ifhead, &pfi_ifs); p; p = nextp) {
674*aca3beaaSApple OSS Distributions nextp = RB_NEXT(pfi_ifhead, &pfi_ifs, p);
675*aca3beaaSApple OSS Distributions if (pfi_skip_if(name, p)) {
676*aca3beaaSApple OSS Distributions continue;
677*aca3beaaSApple OSS Distributions }
678*aca3beaaSApple OSS Distributions if (*size > n++) {
679*aca3beaaSApple OSS Distributions struct pfi_uif u;
680*aca3beaaSApple OSS Distributions
681*aca3beaaSApple OSS Distributions if (!p->pfik_tzero) {
682*aca3beaaSApple OSS Distributions p->pfik_tzero = pf_calendar_time_second();
683*aca3beaaSApple OSS Distributions }
684*aca3beaaSApple OSS Distributions pfi_kif_ref(p, PFI_KIF_REF_RULE);
685*aca3beaaSApple OSS Distributions
686*aca3beaaSApple OSS Distributions /* return the user space version of pfi_kif */
687*aca3beaaSApple OSS Distributions bzero(&u, sizeof(u));
688*aca3beaaSApple OSS Distributions bcopy(p->pfik_name, &u.pfik_name, sizeof(u.pfik_name));
689*aca3beaaSApple OSS Distributions bcopy(p->pfik_packets, &u.pfik_packets,
690*aca3beaaSApple OSS Distributions sizeof(u.pfik_packets));
691*aca3beaaSApple OSS Distributions bcopy(p->pfik_bytes, &u.pfik_bytes,
692*aca3beaaSApple OSS Distributions sizeof(u.pfik_bytes));
693*aca3beaaSApple OSS Distributions u.pfik_tzero = p->pfik_tzero;
694*aca3beaaSApple OSS Distributions u.pfik_flags = p->pfik_flags;
695*aca3beaaSApple OSS Distributions u.pfik_states = p->pfik_states;
696*aca3beaaSApple OSS Distributions u.pfik_rules = p->pfik_rules;
697*aca3beaaSApple OSS Distributions
698*aca3beaaSApple OSS Distributions if (copyout(&u, buf, sizeof(u))) {
699*aca3beaaSApple OSS Distributions pfi_kif_unref(p, PFI_KIF_REF_RULE);
700*aca3beaaSApple OSS Distributions return EFAULT;
701*aca3beaaSApple OSS Distributions }
702*aca3beaaSApple OSS Distributions buf += sizeof(u);
703*aca3beaaSApple OSS Distributions nextp = RB_NEXT(pfi_ifhead, &pfi_ifs, p);
704*aca3beaaSApple OSS Distributions pfi_kif_unref(p, PFI_KIF_REF_RULE);
705*aca3beaaSApple OSS Distributions }
706*aca3beaaSApple OSS Distributions }
707*aca3beaaSApple OSS Distributions *size = n;
708*aca3beaaSApple OSS Distributions return 0;
709*aca3beaaSApple OSS Distributions }
710*aca3beaaSApple OSS Distributions
711*aca3beaaSApple OSS Distributions int
pfi_skip_if(const char * filter,struct pfi_kif * p)712*aca3beaaSApple OSS Distributions pfi_skip_if(const char *filter, struct pfi_kif *p)
713*aca3beaaSApple OSS Distributions {
714*aca3beaaSApple OSS Distributions size_t n;
715*aca3beaaSApple OSS Distributions
716*aca3beaaSApple OSS Distributions if (filter == NULL || !*filter) {
717*aca3beaaSApple OSS Distributions return 0;
718*aca3beaaSApple OSS Distributions }
719*aca3beaaSApple OSS Distributions if (strcmp(p->pfik_name, filter) == 0) {
720*aca3beaaSApple OSS Distributions return 0; /* exact match */
721*aca3beaaSApple OSS Distributions }
722*aca3beaaSApple OSS Distributions n = strlen(filter);
723*aca3beaaSApple OSS Distributions if (n < 1 || n >= IFNAMSIZ) {
724*aca3beaaSApple OSS Distributions return 1; /* sanity check */
725*aca3beaaSApple OSS Distributions }
726*aca3beaaSApple OSS Distributions if (filter[n - 1] >= '0' && filter[n - 1] <= '9') {
727*aca3beaaSApple OSS Distributions return 1; /* only do exact match in that case */
728*aca3beaaSApple OSS Distributions }
729*aca3beaaSApple OSS Distributions if (strncmp(p->pfik_name, filter, n)) {
730*aca3beaaSApple OSS Distributions return 1; /* prefix doesn't match */
731*aca3beaaSApple OSS Distributions }
732*aca3beaaSApple OSS Distributions return p->pfik_name[n] < '0' || p->pfik_name[n] > '9';
733*aca3beaaSApple OSS Distributions }
734*aca3beaaSApple OSS Distributions
735*aca3beaaSApple OSS Distributions int
pfi_set_flags(const char * name,int flags)736*aca3beaaSApple OSS Distributions pfi_set_flags(const char *name, int flags)
737*aca3beaaSApple OSS Distributions {
738*aca3beaaSApple OSS Distributions struct pfi_kif *p;
739*aca3beaaSApple OSS Distributions
740*aca3beaaSApple OSS Distributions LCK_MTX_ASSERT(&pf_lock, LCK_MTX_ASSERT_OWNED);
741*aca3beaaSApple OSS Distributions
742*aca3beaaSApple OSS Distributions RB_FOREACH(p, pfi_ifhead, &pfi_ifs) {
743*aca3beaaSApple OSS Distributions if (pfi_skip_if(name, p)) {
744*aca3beaaSApple OSS Distributions continue;
745*aca3beaaSApple OSS Distributions }
746*aca3beaaSApple OSS Distributions p->pfik_flags |= flags;
747*aca3beaaSApple OSS Distributions }
748*aca3beaaSApple OSS Distributions return 0;
749*aca3beaaSApple OSS Distributions }
750*aca3beaaSApple OSS Distributions
751*aca3beaaSApple OSS Distributions int
pfi_clear_flags(const char * name,int flags)752*aca3beaaSApple OSS Distributions pfi_clear_flags(const char *name, int flags)
753*aca3beaaSApple OSS Distributions {
754*aca3beaaSApple OSS Distributions struct pfi_kif *p;
755*aca3beaaSApple OSS Distributions
756*aca3beaaSApple OSS Distributions LCK_MTX_ASSERT(&pf_lock, LCK_MTX_ASSERT_OWNED);
757*aca3beaaSApple OSS Distributions
758*aca3beaaSApple OSS Distributions RB_FOREACH(p, pfi_ifhead, &pfi_ifs) {
759*aca3beaaSApple OSS Distributions if (pfi_skip_if(name, p)) {
760*aca3beaaSApple OSS Distributions continue;
761*aca3beaaSApple OSS Distributions }
762*aca3beaaSApple OSS Distributions p->pfik_flags &= ~flags;
763*aca3beaaSApple OSS Distributions }
764*aca3beaaSApple OSS Distributions return 0;
765*aca3beaaSApple OSS Distributions }
766*aca3beaaSApple OSS Distributions
767*aca3beaaSApple OSS Distributions /* from pf_print_state.c */
768*aca3beaaSApple OSS Distributions uint8_t
pfi_unmask(void * addr)769*aca3beaaSApple OSS Distributions pfi_unmask(void *addr)
770*aca3beaaSApple OSS Distributions {
771*aca3beaaSApple OSS Distributions struct pf_addr *m = addr;
772*aca3beaaSApple OSS Distributions int i = 31, j = 0, b = 0;
773*aca3beaaSApple OSS Distributions u_int32_t tmp;
774*aca3beaaSApple OSS Distributions
775*aca3beaaSApple OSS Distributions while (j < 4 && m->addr32[j] == 0xffffffff) {
776*aca3beaaSApple OSS Distributions b += 32;
777*aca3beaaSApple OSS Distributions j++;
778*aca3beaaSApple OSS Distributions }
779*aca3beaaSApple OSS Distributions if (j < 4) {
780*aca3beaaSApple OSS Distributions tmp = ntohl(m->addr32[j]);
781*aca3beaaSApple OSS Distributions for (i = 31; tmp & (1 << i); --i) {
782*aca3beaaSApple OSS Distributions b++;
783*aca3beaaSApple OSS Distributions }
784*aca3beaaSApple OSS Distributions }
785*aca3beaaSApple OSS Distributions VERIFY(b >= 0 && b <= UINT8_MAX);
786*aca3beaaSApple OSS Distributions return (uint8_t)b;
787*aca3beaaSApple OSS Distributions }
788