Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/netpfil/pf/pf_ioctl.c
39536 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (c) 2001 Daniel Hartmeier
5
* Copyright (c) 2002,2003 Henning Brauer
6
* Copyright (c) 2012 Gleb Smirnoff <[email protected]>
7
* All rights reserved.
8
*
9
* Redistribution and use in source and binary forms, with or without
10
* modification, are permitted provided that the following conditions
11
* are met:
12
*
13
* - Redistributions of source code must retain the above copyright
14
* notice, this list of conditions and the following disclaimer.
15
* - Redistributions in binary form must reproduce the above
16
* copyright notice, this list of conditions and the following
17
* disclaimer in the documentation and/or other materials provided
18
* with the distribution.
19
*
20
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31
* POSSIBILITY OF SUCH DAMAGE.
32
*
33
* Effort sponsored in part by the Defense Advanced Research Projects
34
* Agency (DARPA) and Air Force Research Laboratory, Air Force
35
* Materiel Command, USAF, under agreement number F30602-01-2-0537.
36
*
37
* $OpenBSD: pf_ioctl.c,v 1.213 2009/02/15 21:46:12 mbalmer Exp $
38
*/
39
40
#include <sys/cdefs.h>
41
#include "opt_inet.h"
42
#include "opt_inet6.h"
43
#include "opt_bpf.h"
44
#include "opt_pf.h"
45
46
#include <sys/param.h>
47
#include <sys/_bitset.h>
48
#include <sys/bitset.h>
49
#include <sys/bus.h>
50
#include <sys/conf.h>
51
#include <sys/endian.h>
52
#include <sys/fcntl.h>
53
#include <sys/filio.h>
54
#include <sys/hash.h>
55
#include <sys/interrupt.h>
56
#include <sys/jail.h>
57
#include <sys/kernel.h>
58
#include <sys/kthread.h>
59
#include <sys/lock.h>
60
#include <sys/mbuf.h>
61
#include <sys/module.h>
62
#include <sys/nv.h>
63
#include <sys/proc.h>
64
#include <sys/sdt.h>
65
#include <sys/smp.h>
66
#include <sys/socket.h>
67
#include <sys/sysctl.h>
68
#include <sys/md5.h>
69
#include <sys/ucred.h>
70
71
#include <net/if.h>
72
#include <net/if_var.h>
73
#include <net/if_private.h>
74
#include <net/vnet.h>
75
#include <net/route.h>
76
#include <net/pfil.h>
77
#include <net/pfvar.h>
78
#include <net/if_pfsync.h>
79
#include <net/if_pflog.h>
80
81
#include <netinet/in.h>
82
#include <netinet/ip.h>
83
#include <netinet/ip_var.h>
84
#include <netinet6/ip6_var.h>
85
#include <netinet/ip_icmp.h>
86
#include <netpfil/pf/pf_nl.h>
87
#include <netpfil/pf/pf_nv.h>
88
89
#ifdef INET6
90
#include <netinet/ip6.h>
91
#endif /* INET6 */
92
93
#ifdef ALTQ
94
#include <net/altq/altq.h>
95
#endif
96
97
SDT_PROBE_DEFINE3(pf, ioctl, ioctl, error, "int", "int", "int");
98
SDT_PROBE_DEFINE3(pf, ioctl, function, error, "char *", "int", "int");
99
SDT_PROBE_DEFINE2(pf, ioctl, addrule, error, "int", "int");
100
SDT_PROBE_DEFINE2(pf, ioctl, nvchk, error, "int", "int");
101
102
static struct pf_kpool *pf_get_kpool(const char *, u_int32_t, u_int8_t,
103
u_int32_t, u_int8_t, u_int8_t, u_int8_t, int);
104
105
static void pf_mv_kpool(struct pf_kpalist *, struct pf_kpalist *);
106
static void pf_empty_kpool(struct pf_kpalist *);
107
static int pfioctl(struct cdev *, u_long, caddr_t, int,
108
struct thread *);
109
static int pf_begin_eth(uint32_t *, const char *);
110
static int pf_rollback_eth(uint32_t, const char *);
111
static int pf_commit_eth(uint32_t, const char *);
112
static void pf_free_eth_rule(struct pf_keth_rule *);
113
#ifdef ALTQ
114
static int pf_begin_altq(u_int32_t *);
115
static int pf_rollback_altq(u_int32_t);
116
static int pf_commit_altq(u_int32_t);
117
static int pf_enable_altq(struct pf_altq *);
118
static int pf_disable_altq(struct pf_altq *);
119
static void pf_qid_unref(uint16_t);
120
#endif /* ALTQ */
121
static int pf_begin_rules(u_int32_t *, int, const char *);
122
static int pf_rollback_rules(u_int32_t, int, char *);
123
static int pf_setup_pfsync_matching(struct pf_kruleset *);
124
static void pf_hash_rule_rolling(MD5_CTX *, struct pf_krule *);
125
static void pf_hash_rule(struct pf_krule *);
126
static void pf_hash_rule_addr(MD5_CTX *, struct pf_rule_addr *);
127
static int pf_commit_rules(u_int32_t, int, char *);
128
static int pf_addr_setup(struct pf_kruleset *,
129
struct pf_addr_wrap *, sa_family_t);
130
static void pf_src_node_copy(const struct pf_ksrc_node *,
131
struct pf_src_node *);
132
#ifdef ALTQ
133
static int pf_export_kaltq(struct pf_altq *,
134
struct pfioc_altq_v1 *, size_t);
135
static int pf_import_kaltq(struct pfioc_altq_v1 *,
136
struct pf_altq *, size_t);
137
#endif /* ALTQ */
138
139
VNET_DEFINE(struct pf_krule, pf_default_rule);
140
141
static __inline int pf_krule_compare(struct pf_krule *,
142
struct pf_krule *);
143
144
RB_GENERATE(pf_krule_global, pf_krule, entry_global, pf_krule_compare);
145
146
#ifdef ALTQ
147
VNET_DEFINE_STATIC(int, pf_altq_running);
148
#define V_pf_altq_running VNET(pf_altq_running)
149
#endif
150
151
#define TAGID_MAX 50000
152
struct pf_tagname {
153
TAILQ_ENTRY(pf_tagname) namehash_entries;
154
TAILQ_ENTRY(pf_tagname) taghash_entries;
155
char name[PF_TAG_NAME_SIZE];
156
uint16_t tag;
157
int ref;
158
};
159
160
struct pf_tagset {
161
TAILQ_HEAD(, pf_tagname) *namehash;
162
TAILQ_HEAD(, pf_tagname) *taghash;
163
unsigned int mask;
164
uint32_t seed;
165
BITSET_DEFINE(, TAGID_MAX) avail;
166
};
167
168
VNET_DEFINE(struct pf_tagset, pf_tags);
169
#define V_pf_tags VNET(pf_tags)
170
static unsigned int pf_rule_tag_hashsize;
171
#define PF_RULE_TAG_HASH_SIZE_DEFAULT 128
172
SYSCTL_UINT(_net_pf, OID_AUTO, rule_tag_hashsize, CTLFLAG_RDTUN,
173
&pf_rule_tag_hashsize, PF_RULE_TAG_HASH_SIZE_DEFAULT,
174
"Size of pf(4) rule tag hashtable");
175
176
#ifdef ALTQ
177
VNET_DEFINE(struct pf_tagset, pf_qids);
178
#define V_pf_qids VNET(pf_qids)
179
static unsigned int pf_queue_tag_hashsize;
180
#define PF_QUEUE_TAG_HASH_SIZE_DEFAULT 128
181
SYSCTL_UINT(_net_pf, OID_AUTO, queue_tag_hashsize, CTLFLAG_RDTUN,
182
&pf_queue_tag_hashsize, PF_QUEUE_TAG_HASH_SIZE_DEFAULT,
183
"Size of pf(4) queue tag hashtable");
184
#endif
185
VNET_DEFINE(uma_zone_t, pf_tag_z);
186
#define V_pf_tag_z VNET(pf_tag_z)
187
static MALLOC_DEFINE(M_PFALTQ, "pf_altq", "pf(4) altq configuration db");
188
static MALLOC_DEFINE(M_PFRULE, "pf_rule", "pf(4) rules");
189
MALLOC_DEFINE(M_PF, "pf", "pf(4)");
190
191
#if (PF_QNAME_SIZE != PF_TAG_NAME_SIZE)
192
#error PF_QNAME_SIZE must be equal to PF_TAG_NAME_SIZE
193
#endif
194
195
VNET_DEFINE_STATIC(bool, pf_filter_local) = false;
196
#define V_pf_filter_local VNET(pf_filter_local)
197
SYSCTL_BOOL(_net_pf, OID_AUTO, filter_local, CTLFLAG_VNET | CTLFLAG_RW,
198
&VNET_NAME(pf_filter_local), false,
199
"Enable filtering for packets delivered to local network stack");
200
201
#ifdef PF_DEFAULT_TO_DROP
202
VNET_DEFINE_STATIC(bool, default_to_drop) = true;
203
#else
204
VNET_DEFINE_STATIC(bool, default_to_drop);
205
#endif
206
#define V_default_to_drop VNET(default_to_drop)
207
SYSCTL_BOOL(_net_pf, OID_AUTO, default_to_drop, CTLFLAG_RDTUN | CTLFLAG_VNET,
208
&VNET_NAME(default_to_drop), false,
209
"Make the default rule drop all packets.");
210
211
static void pf_init_tagset(struct pf_tagset *, unsigned int *,
212
unsigned int);
213
static void pf_cleanup_tagset(struct pf_tagset *);
214
static uint16_t tagname2hashindex(const struct pf_tagset *, const char *);
215
static uint16_t tag2hashindex(const struct pf_tagset *, uint16_t);
216
static u_int16_t tagname2tag(struct pf_tagset *, const char *, bool);
217
static void tag_unref(struct pf_tagset *, u_int16_t);
218
219
struct cdev *pf_dev;
220
221
/*
222
* XXX - These are new and need to be checked when moveing to a new version
223
*/
224
static void pf_clear_all_states(void);
225
static int pf_killstates_row(struct pf_kstate_kill *,
226
struct pf_idhash *);
227
static int pf_killstates_nv(struct pfioc_nv *);
228
static int pf_clearstates_nv(struct pfioc_nv *);
229
static int pf_getstate(struct pfioc_nv *);
230
static int pf_getstatus(struct pfioc_nv *);
231
static int pf_clear_tables(void);
232
static void pf_kill_srcnodes(struct pfioc_src_node_kill *);
233
static int pf_keepcounters(struct pfioc_nv *);
234
static void pf_tbladdr_copyout(struct pf_addr_wrap *);
235
236
/*
237
* Wrapper functions for pfil(9) hooks
238
*/
239
static pfil_return_t pf_eth_check_in(struct mbuf **m, struct ifnet *ifp,
240
int flags, void *ruleset __unused, struct inpcb *inp);
241
static pfil_return_t pf_eth_check_out(struct mbuf **m, struct ifnet *ifp,
242
int flags, void *ruleset __unused, struct inpcb *inp);
243
#ifdef INET
244
static pfil_return_t pf_check_in(struct mbuf **m, struct ifnet *ifp,
245
int flags, void *ruleset __unused, struct inpcb *inp);
246
static pfil_return_t pf_check_out(struct mbuf **m, struct ifnet *ifp,
247
int flags, void *ruleset __unused, struct inpcb *inp);
248
#endif
249
#ifdef INET6
250
static pfil_return_t pf_check6_in(struct mbuf **m, struct ifnet *ifp,
251
int flags, void *ruleset __unused, struct inpcb *inp);
252
static pfil_return_t pf_check6_out(struct mbuf **m, struct ifnet *ifp,
253
int flags, void *ruleset __unused, struct inpcb *inp);
254
#endif
255
256
static void hook_pf_eth(void);
257
static void hook_pf(void);
258
static void dehook_pf_eth(void);
259
static void dehook_pf(void);
260
static int shutdown_pf(void);
261
static int pf_load(void);
262
static void pf_unload(void);
263
264
static struct cdevsw pf_cdevsw = {
265
.d_ioctl = pfioctl,
266
.d_name = PF_NAME,
267
.d_version = D_VERSION,
268
};
269
270
VNET_DEFINE_STATIC(bool, pf_pfil_hooked);
271
#define V_pf_pfil_hooked VNET(pf_pfil_hooked)
272
VNET_DEFINE_STATIC(bool, pf_pfil_eth_hooked);
273
#define V_pf_pfil_eth_hooked VNET(pf_pfil_eth_hooked)
274
275
/*
276
* We need a flag that is neither hooked nor running to know when
277
* the VNET is "valid". We primarily need this to control (global)
278
* external event, e.g., eventhandlers.
279
*/
280
VNET_DEFINE(int, pf_vnet_active);
281
#define V_pf_vnet_active VNET(pf_vnet_active)
282
283
int pf_end_threads;
284
struct proc *pf_purge_proc;
285
286
VNET_DEFINE(struct rmlock, pf_rules_lock);
287
VNET_DEFINE(struct rmlock, pf_tags_lock);
288
VNET_DEFINE_STATIC(struct sx, pf_ioctl_lock);
289
#define V_pf_ioctl_lock VNET(pf_ioctl_lock)
290
struct sx pf_end_lock;
291
292
/* pfsync */
293
VNET_DEFINE(pfsync_state_import_t *, pfsync_state_import_ptr);
294
VNET_DEFINE(pfsync_insert_state_t *, pfsync_insert_state_ptr);
295
VNET_DEFINE(pfsync_update_state_t *, pfsync_update_state_ptr);
296
VNET_DEFINE(pfsync_delete_state_t *, pfsync_delete_state_ptr);
297
VNET_DEFINE(pfsync_clear_states_t *, pfsync_clear_states_ptr);
298
VNET_DEFINE(pfsync_defer_t *, pfsync_defer_ptr);
299
VNET_DEFINE(pflow_export_state_t *, pflow_export_state_ptr);
300
pfsync_detach_ifnet_t *pfsync_detach_ifnet_ptr;
301
302
/* pflog */
303
pflog_packet_t *pflog_packet_ptr = NULL;
304
305
/*
306
* Copy a user-provided string, returning an error if truncation would occur.
307
* Avoid scanning past "sz" bytes in the source string since there's no
308
* guarantee that it's nul-terminated.
309
*/
310
static int
311
pf_user_strcpy(char *dst, const char *src, size_t sz)
312
{
313
if (strnlen(src, sz) == sz)
314
return (EINVAL);
315
(void)strlcpy(dst, src, sz);
316
return (0);
317
}
318
319
static void
320
pfattach_vnet(void)
321
{
322
u_int32_t *my_timeout = V_pf_default_rule.timeout;
323
324
bzero(&V_pf_status, sizeof(V_pf_status));
325
326
pf_initialize();
327
pfr_initialize();
328
pfi_initialize_vnet();
329
pf_normalize_init();
330
pf_syncookies_init();
331
332
V_pf_limits[PF_LIMIT_STATES].limit = PFSTATE_HIWAT;
333
V_pf_limits[PF_LIMIT_SRC_NODES].limit = PFSNODE_HIWAT;
334
V_pf_limits[PF_LIMIT_ANCHORS].limit = PF_ANCHOR_HIWAT;
335
V_pf_limits[PF_LIMIT_ETH_ANCHORS].limit = PF_ANCHOR_HIWAT;
336
337
RB_INIT(&V_pf_anchors);
338
pf_init_kruleset(&pf_main_ruleset);
339
340
pf_init_keth(V_pf_keth);
341
342
/* default rule should never be garbage collected */
343
V_pf_default_rule.entries.tqe_prev = &V_pf_default_rule.entries.tqe_next;
344
V_pf_default_rule.action = V_default_to_drop ? PF_DROP : PF_PASS;
345
V_pf_default_rule.nr = (uint32_t)-1;
346
V_pf_default_rule.rtableid = -1;
347
348
pf_counter_u64_init(&V_pf_default_rule.evaluations, M_WAITOK);
349
for (int i = 0; i < 2; i++) {
350
pf_counter_u64_init(&V_pf_default_rule.packets[i], M_WAITOK);
351
pf_counter_u64_init(&V_pf_default_rule.bytes[i], M_WAITOK);
352
}
353
V_pf_default_rule.states_cur = counter_u64_alloc(M_WAITOK);
354
V_pf_default_rule.states_tot = counter_u64_alloc(M_WAITOK);
355
for (pf_sn_types_t sn_type = 0; sn_type<PF_SN_MAX; sn_type++)
356
V_pf_default_rule.src_nodes[sn_type] = counter_u64_alloc(M_WAITOK);
357
358
V_pf_default_rule.timestamp = uma_zalloc_pcpu(pf_timestamp_pcpu_zone,
359
M_WAITOK | M_ZERO);
360
361
#ifdef PF_WANT_32_TO_64_COUNTER
362
V_pf_kifmarker = malloc(sizeof(*V_pf_kifmarker), PFI_MTYPE, M_WAITOK | M_ZERO);
363
V_pf_rulemarker = malloc(sizeof(*V_pf_rulemarker), M_PFRULE, M_WAITOK | M_ZERO);
364
PF_RULES_WLOCK();
365
LIST_INSERT_HEAD(&V_pf_allkiflist, V_pf_kifmarker, pfik_allkiflist);
366
LIST_INSERT_HEAD(&V_pf_allrulelist, &V_pf_default_rule, allrulelist);
367
V_pf_allrulecount++;
368
LIST_INSERT_HEAD(&V_pf_allrulelist, V_pf_rulemarker, allrulelist);
369
PF_RULES_WUNLOCK();
370
#endif
371
372
/* initialize default timeouts */
373
my_timeout[PFTM_TCP_FIRST_PACKET] = PFTM_TCP_FIRST_PACKET_VAL;
374
my_timeout[PFTM_TCP_OPENING] = PFTM_TCP_OPENING_VAL;
375
my_timeout[PFTM_TCP_ESTABLISHED] = PFTM_TCP_ESTABLISHED_VAL;
376
my_timeout[PFTM_TCP_CLOSING] = PFTM_TCP_CLOSING_VAL;
377
my_timeout[PFTM_TCP_FIN_WAIT] = PFTM_TCP_FIN_WAIT_VAL;
378
my_timeout[PFTM_TCP_CLOSED] = PFTM_TCP_CLOSED_VAL;
379
my_timeout[PFTM_SCTP_FIRST_PACKET] = PFTM_TCP_FIRST_PACKET_VAL;
380
my_timeout[PFTM_SCTP_OPENING] = PFTM_TCP_OPENING_VAL;
381
my_timeout[PFTM_SCTP_ESTABLISHED] = PFTM_TCP_ESTABLISHED_VAL;
382
my_timeout[PFTM_SCTP_CLOSING] = PFTM_TCP_CLOSING_VAL;
383
my_timeout[PFTM_SCTP_CLOSED] = PFTM_TCP_CLOSED_VAL;
384
my_timeout[PFTM_UDP_FIRST_PACKET] = PFTM_UDP_FIRST_PACKET_VAL;
385
my_timeout[PFTM_UDP_SINGLE] = PFTM_UDP_SINGLE_VAL;
386
my_timeout[PFTM_UDP_MULTIPLE] = PFTM_UDP_MULTIPLE_VAL;
387
my_timeout[PFTM_ICMP_FIRST_PACKET] = PFTM_ICMP_FIRST_PACKET_VAL;
388
my_timeout[PFTM_ICMP_ERROR_REPLY] = PFTM_ICMP_ERROR_REPLY_VAL;
389
my_timeout[PFTM_OTHER_FIRST_PACKET] = PFTM_OTHER_FIRST_PACKET_VAL;
390
my_timeout[PFTM_OTHER_SINGLE] = PFTM_OTHER_SINGLE_VAL;
391
my_timeout[PFTM_OTHER_MULTIPLE] = PFTM_OTHER_MULTIPLE_VAL;
392
my_timeout[PFTM_FRAG] = PFTM_FRAG_VAL;
393
my_timeout[PFTM_INTERVAL] = PFTM_INTERVAL_VAL;
394
my_timeout[PFTM_SRC_NODE] = PFTM_SRC_NODE_VAL;
395
my_timeout[PFTM_TS_DIFF] = PFTM_TS_DIFF_VAL;
396
my_timeout[PFTM_ADAPTIVE_START] = PFSTATE_ADAPT_START;
397
my_timeout[PFTM_ADAPTIVE_END] = PFSTATE_ADAPT_END;
398
399
V_pf_status.debug = PF_DEBUG_URGENT;
400
/*
401
* XXX This is different than in OpenBSD where reassembly is enabled by
402
* defult. In FreeBSD we expect people to still use scrub rules and
403
* switch to the new syntax later. Only when they switch they must
404
* explicitly enable reassemle. We could change the default once the
405
* scrub rule functionality is hopefully removed some day in future.
406
*/
407
V_pf_status.reass = 0;
408
409
V_pf_pfil_hooked = false;
410
V_pf_pfil_eth_hooked = false;
411
412
/* XXX do our best to avoid a conflict */
413
V_pf_status.hostid = arc4random();
414
415
for (int i = 0; i < PFRES_MAX; i++)
416
V_pf_status.counters[i] = counter_u64_alloc(M_WAITOK);
417
for (int i = 0; i < KLCNT_MAX; i++)
418
V_pf_status.lcounters[i] = counter_u64_alloc(M_WAITOK);
419
for (int i = 0; i < FCNT_MAX; i++)
420
pf_counter_u64_init(&V_pf_status.fcounters[i], M_WAITOK);
421
for (int i = 0; i < SCNT_MAX; i++)
422
V_pf_status.scounters[i] = counter_u64_alloc(M_WAITOK);
423
for (int i = 0; i < NCNT_MAX; i++)
424
V_pf_status.ncounters[i] = counter_u64_alloc(M_WAITOK);
425
426
if (swi_add(&V_pf_swi_ie, "pf send", pf_intr, curvnet, SWI_NET,
427
INTR_MPSAFE, &V_pf_swi_cookie) != 0)
428
/* XXXGL: leaked all above. */
429
return;
430
}
431
432
static struct pf_kpool *
433
pf_get_kpool(const char *anchor, u_int32_t ticket, u_int8_t rule_action,
434
u_int32_t rule_number, u_int8_t r_last, u_int8_t active,
435
u_int8_t check_ticket, int which)
436
{
437
struct pf_kruleset *ruleset;
438
struct pf_krule *rule;
439
int rs_num;
440
441
MPASS(which == PF_RDR || which == PF_NAT || which == PF_RT);
442
443
ruleset = pf_find_kruleset(anchor);
444
if (ruleset == NULL)
445
return (NULL);
446
rs_num = pf_get_ruleset_number(rule_action);
447
if (rs_num >= PF_RULESET_MAX)
448
return (NULL);
449
if (active) {
450
if (check_ticket && ticket !=
451
ruleset->rules[rs_num].active.ticket)
452
return (NULL);
453
if (r_last)
454
rule = TAILQ_LAST(ruleset->rules[rs_num].active.ptr,
455
pf_krulequeue);
456
else
457
rule = TAILQ_FIRST(ruleset->rules[rs_num].active.ptr);
458
} else {
459
if (check_ticket && ticket !=
460
ruleset->rules[rs_num].inactive.ticket)
461
return (NULL);
462
if (r_last)
463
rule = TAILQ_LAST(ruleset->rules[rs_num].inactive.ptr,
464
pf_krulequeue);
465
else
466
rule = TAILQ_FIRST(ruleset->rules[rs_num].inactive.ptr);
467
}
468
if (!r_last) {
469
while ((rule != NULL) && (rule->nr != rule_number))
470
rule = TAILQ_NEXT(rule, entries);
471
}
472
if (rule == NULL)
473
return (NULL);
474
475
switch (which) {
476
case PF_RDR:
477
return (&rule->rdr);
478
case PF_NAT:
479
return (&rule->nat);
480
case PF_RT:
481
return (&rule->route);
482
default:
483
panic("Unknow pool type %d", which);
484
}
485
}
486
487
static void
488
pf_mv_kpool(struct pf_kpalist *poola, struct pf_kpalist *poolb)
489
{
490
struct pf_kpooladdr *mv_pool_pa;
491
492
while ((mv_pool_pa = TAILQ_FIRST(poola)) != NULL) {
493
TAILQ_REMOVE(poola, mv_pool_pa, entries);
494
TAILQ_INSERT_TAIL(poolb, mv_pool_pa, entries);
495
}
496
}
497
498
static void
499
pf_empty_kpool(struct pf_kpalist *poola)
500
{
501
struct pf_kpooladdr *pa;
502
503
while ((pa = TAILQ_FIRST(poola)) != NULL) {
504
switch (pa->addr.type) {
505
case PF_ADDR_DYNIFTL:
506
pfi_dynaddr_remove(pa->addr.p.dyn);
507
break;
508
case PF_ADDR_TABLE:
509
/* XXX: this could be unfinished pooladdr on pabuf */
510
if (pa->addr.p.tbl != NULL)
511
pfr_detach_table(pa->addr.p.tbl);
512
break;
513
}
514
if (pa->kif)
515
pfi_kkif_unref(pa->kif);
516
TAILQ_REMOVE(poola, pa, entries);
517
free(pa, M_PFRULE);
518
}
519
}
520
521
static void
522
pf_unlink_rule_locked(struct pf_krulequeue *rulequeue, struct pf_krule *rule)
523
{
524
525
PF_RULES_WASSERT();
526
PF_UNLNKDRULES_ASSERT();
527
528
TAILQ_REMOVE(rulequeue, rule, entries);
529
530
rule->rule_ref |= PFRULE_REFS;
531
TAILQ_INSERT_TAIL(&V_pf_unlinked_rules, rule, entries);
532
}
533
534
static void
535
pf_unlink_rule(struct pf_krulequeue *rulequeue, struct pf_krule *rule)
536
{
537
538
PF_RULES_WASSERT();
539
540
PF_UNLNKDRULES_LOCK();
541
pf_unlink_rule_locked(rulequeue, rule);
542
PF_UNLNKDRULES_UNLOCK();
543
}
544
545
static void
546
pf_free_eth_rule(struct pf_keth_rule *rule)
547
{
548
PF_RULES_WASSERT();
549
550
if (rule == NULL)
551
return;
552
553
if (rule->tag)
554
tag_unref(&V_pf_tags, rule->tag);
555
if (rule->match_tag)
556
tag_unref(&V_pf_tags, rule->match_tag);
557
#ifdef ALTQ
558
pf_qid_unref(rule->qid);
559
#endif
560
561
if (rule->bridge_to)
562
pfi_kkif_unref(rule->bridge_to);
563
if (rule->kif)
564
pfi_kkif_unref(rule->kif);
565
566
if (rule->ipsrc.addr.type == PF_ADDR_TABLE)
567
pfr_detach_table(rule->ipsrc.addr.p.tbl);
568
if (rule->ipdst.addr.type == PF_ADDR_TABLE)
569
pfr_detach_table(rule->ipdst.addr.p.tbl);
570
571
counter_u64_free(rule->evaluations);
572
for (int i = 0; i < 2; i++) {
573
counter_u64_free(rule->packets[i]);
574
counter_u64_free(rule->bytes[i]);
575
}
576
uma_zfree_pcpu(pf_timestamp_pcpu_zone, rule->timestamp);
577
pf_keth_anchor_remove(rule);
578
579
free(rule, M_PFRULE);
580
}
581
582
void
583
pf_free_rule(struct pf_krule *rule)
584
{
585
586
PF_RULES_WASSERT();
587
PF_CONFIG_ASSERT();
588
589
if (rule->tag)
590
tag_unref(&V_pf_tags, rule->tag);
591
if (rule->match_tag)
592
tag_unref(&V_pf_tags, rule->match_tag);
593
#ifdef ALTQ
594
if (rule->pqid != rule->qid)
595
pf_qid_unref(rule->pqid);
596
pf_qid_unref(rule->qid);
597
#endif
598
switch (rule->src.addr.type) {
599
case PF_ADDR_DYNIFTL:
600
pfi_dynaddr_remove(rule->src.addr.p.dyn);
601
break;
602
case PF_ADDR_TABLE:
603
pfr_detach_table(rule->src.addr.p.tbl);
604
break;
605
}
606
switch (rule->dst.addr.type) {
607
case PF_ADDR_DYNIFTL:
608
pfi_dynaddr_remove(rule->dst.addr.p.dyn);
609
break;
610
case PF_ADDR_TABLE:
611
pfr_detach_table(rule->dst.addr.p.tbl);
612
break;
613
}
614
if (rule->overload_tbl)
615
pfr_detach_table(rule->overload_tbl);
616
if (rule->kif)
617
pfi_kkif_unref(rule->kif);
618
if (rule->rcv_kif)
619
pfi_kkif_unref(rule->rcv_kif);
620
pf_remove_kanchor(rule);
621
pf_empty_kpool(&rule->rdr.list);
622
pf_empty_kpool(&rule->nat.list);
623
pf_empty_kpool(&rule->route.list);
624
625
pf_krule_free(rule);
626
}
627
628
static void
629
pf_init_tagset(struct pf_tagset *ts, unsigned int *tunable_size,
630
unsigned int default_size)
631
{
632
unsigned int i;
633
unsigned int hashsize;
634
635
if (*tunable_size == 0 || !powerof2(*tunable_size))
636
*tunable_size = default_size;
637
638
hashsize = *tunable_size;
639
ts->namehash = mallocarray(hashsize, sizeof(*ts->namehash), M_PFHASH,
640
M_WAITOK);
641
ts->taghash = mallocarray(hashsize, sizeof(*ts->taghash), M_PFHASH,
642
M_WAITOK);
643
ts->mask = hashsize - 1;
644
ts->seed = arc4random();
645
for (i = 0; i < hashsize; i++) {
646
TAILQ_INIT(&ts->namehash[i]);
647
TAILQ_INIT(&ts->taghash[i]);
648
}
649
BIT_FILL(TAGID_MAX, &ts->avail);
650
}
651
652
static void
653
pf_cleanup_tagset(struct pf_tagset *ts)
654
{
655
unsigned int i;
656
unsigned int hashsize;
657
struct pf_tagname *t, *tmp;
658
659
/*
660
* Only need to clean up one of the hashes as each tag is hashed
661
* into each table.
662
*/
663
hashsize = ts->mask + 1;
664
for (i = 0; i < hashsize; i++)
665
TAILQ_FOREACH_SAFE(t, &ts->namehash[i], namehash_entries, tmp)
666
uma_zfree(V_pf_tag_z, t);
667
668
free(ts->namehash, M_PFHASH);
669
free(ts->taghash, M_PFHASH);
670
}
671
672
static uint16_t
673
tagname2hashindex(const struct pf_tagset *ts, const char *tagname)
674
{
675
size_t len;
676
677
len = strnlen(tagname, PF_TAG_NAME_SIZE - 1);
678
return (murmur3_32_hash(tagname, len, ts->seed) & ts->mask);
679
}
680
681
static uint16_t
682
tag2hashindex(const struct pf_tagset *ts, uint16_t tag)
683
{
684
685
return (tag & ts->mask);
686
}
687
688
static u_int16_t
689
tagname2tag(struct pf_tagset *ts, const char *tagname, bool add_new)
690
{
691
struct pf_tagname *tag;
692
u_int32_t index;
693
u_int16_t new_tagid;
694
695
PF_TAGS_RLOCK_TRACKER;
696
697
PF_TAGS_RLOCK();
698
699
index = tagname2hashindex(ts, tagname);
700
TAILQ_FOREACH(tag, &ts->namehash[index], namehash_entries)
701
if (strcmp(tagname, tag->name) == 0) {
702
tag->ref++;
703
new_tagid = tag->tag;
704
PF_TAGS_RUNLOCK();
705
return (new_tagid);
706
}
707
708
/*
709
* When used for pfsync with queues we must not create new entries.
710
* Pf tags can be created just fine by this function, but queues
711
* require additional configuration. If they are missing on the target
712
* system we just ignore them
713
*/
714
if (add_new == false) {
715
printf("%s: Not creating a new tag\n", __func__);
716
PF_TAGS_RUNLOCK();
717
return (0);
718
}
719
720
/*
721
* If a new entry must be created do it under a write lock.
722
* But first search again, somebody could have created the tag
723
* between unlocking the read lock and locking the write lock.
724
*/
725
PF_TAGS_RUNLOCK();
726
PF_TAGS_WLOCK();
727
TAILQ_FOREACH(tag, &ts->namehash[index], namehash_entries)
728
if (strcmp(tagname, tag->name) == 0) {
729
tag->ref++;
730
new_tagid = tag->tag;
731
PF_TAGS_WUNLOCK();
732
return (new_tagid);
733
}
734
735
/*
736
* new entry
737
*
738
* to avoid fragmentation, we do a linear search from the beginning
739
* and take the first free slot we find.
740
*/
741
new_tagid = BIT_FFS(TAGID_MAX, &ts->avail);
742
/*
743
* Tags are 1-based, with valid tags in the range [1..TAGID_MAX].
744
* BIT_FFS() returns a 1-based bit number, with 0 indicating no bits
745
* set. It may also return a bit number greater than TAGID_MAX due
746
* to rounding of the number of bits in the vector up to a multiple
747
* of the vector word size at declaration/allocation time.
748
*/
749
if ((new_tagid == 0) || (new_tagid > TAGID_MAX)) {
750
PF_TAGS_WUNLOCK();
751
return (0);
752
}
753
754
/* Mark the tag as in use. Bits are 0-based for BIT_CLR() */
755
BIT_CLR(TAGID_MAX, new_tagid - 1, &ts->avail);
756
757
/* allocate and fill new struct pf_tagname */
758
tag = uma_zalloc(V_pf_tag_z, M_NOWAIT);
759
if (tag == NULL) {
760
PF_TAGS_WUNLOCK();
761
return (0);
762
}
763
strlcpy(tag->name, tagname, sizeof(tag->name));
764
tag->tag = new_tagid;
765
tag->ref = 1;
766
767
/* Insert into namehash */
768
TAILQ_INSERT_TAIL(&ts->namehash[index], tag, namehash_entries);
769
770
/* Insert into taghash */
771
index = tag2hashindex(ts, new_tagid);
772
TAILQ_INSERT_TAIL(&ts->taghash[index], tag, taghash_entries);
773
774
PF_TAGS_WUNLOCK();
775
return (new_tagid);
776
}
777
778
static char *
779
tag2tagname(struct pf_tagset *ts, u_int16_t tag)
780
{
781
struct pf_tagname *t;
782
uint16_t index;
783
784
PF_TAGS_RLOCK_TRACKER;
785
786
PF_TAGS_RLOCK();
787
788
index = tag2hashindex(ts, tag);
789
TAILQ_FOREACH(t, &ts->taghash[index], taghash_entries)
790
if (tag == t->tag) {
791
PF_TAGS_RUNLOCK();
792
return (t->name);
793
}
794
795
PF_TAGS_RUNLOCK();
796
return (NULL);
797
}
798
799
static void
800
tag_unref(struct pf_tagset *ts, u_int16_t tag)
801
{
802
struct pf_tagname *t;
803
uint16_t index;
804
805
PF_TAGS_WLOCK();
806
807
index = tag2hashindex(ts, tag);
808
TAILQ_FOREACH(t, &ts->taghash[index], taghash_entries)
809
if (tag == t->tag) {
810
if (--t->ref == 0) {
811
TAILQ_REMOVE(&ts->taghash[index], t,
812
taghash_entries);
813
index = tagname2hashindex(ts, t->name);
814
TAILQ_REMOVE(&ts->namehash[index], t,
815
namehash_entries);
816
/* Bits are 0-based for BIT_SET() */
817
BIT_SET(TAGID_MAX, tag - 1, &ts->avail);
818
uma_zfree(V_pf_tag_z, t);
819
}
820
break;
821
}
822
823
PF_TAGS_WUNLOCK();
824
}
825
826
uint16_t
827
pf_tagname2tag(const char *tagname)
828
{
829
return (tagname2tag(&V_pf_tags, tagname, true));
830
}
831
832
static const char *
833
pf_tag2tagname(uint16_t tag)
834
{
835
return (tag2tagname(&V_pf_tags, tag));
836
}
837
838
static int
839
pf_begin_eth(uint32_t *ticket, const char *anchor)
840
{
841
struct pf_keth_rule *rule, *tmp;
842
struct pf_keth_ruleset *rs;
843
844
PF_RULES_WASSERT();
845
846
rs = pf_find_or_create_keth_ruleset(anchor);
847
if (rs == NULL)
848
return (EINVAL);
849
850
/* Purge old inactive rules. */
851
TAILQ_FOREACH_SAFE(rule, rs->inactive.rules, entries,
852
tmp) {
853
TAILQ_REMOVE(rs->inactive.rules, rule,
854
entries);
855
pf_free_eth_rule(rule);
856
}
857
858
*ticket = ++rs->inactive.ticket;
859
rs->inactive.open = 1;
860
861
return (0);
862
}
863
864
static int
865
pf_rollback_eth(uint32_t ticket, const char *anchor)
866
{
867
struct pf_keth_rule *rule, *tmp;
868
struct pf_keth_ruleset *rs;
869
870
PF_RULES_WASSERT();
871
872
rs = pf_find_keth_ruleset(anchor);
873
if (rs == NULL)
874
return (EINVAL);
875
876
if (!rs->inactive.open ||
877
ticket != rs->inactive.ticket)
878
return (0);
879
880
/* Purge old inactive rules. */
881
TAILQ_FOREACH_SAFE(rule, rs->inactive.rules, entries,
882
tmp) {
883
TAILQ_REMOVE(rs->inactive.rules, rule, entries);
884
pf_free_eth_rule(rule);
885
}
886
887
rs->inactive.open = 0;
888
889
pf_remove_if_empty_keth_ruleset(rs);
890
891
return (0);
892
}
893
894
#define PF_SET_SKIP_STEPS(i) \
895
do { \
896
while (head[i] != cur) { \
897
head[i]->skip[i].ptr = cur; \
898
head[i] = TAILQ_NEXT(head[i], entries); \
899
} \
900
} while (0)
901
902
static void
903
pf_eth_calc_skip_steps(struct pf_keth_ruleq *rules)
904
{
905
struct pf_keth_rule *cur, *prev, *head[PFE_SKIP_COUNT];
906
int i;
907
908
cur = TAILQ_FIRST(rules);
909
prev = cur;
910
for (i = 0; i < PFE_SKIP_COUNT; ++i)
911
head[i] = cur;
912
while (cur != NULL) {
913
if (cur->kif != prev->kif || cur->ifnot != prev->ifnot)
914
PF_SET_SKIP_STEPS(PFE_SKIP_IFP);
915
if (cur->direction != prev->direction)
916
PF_SET_SKIP_STEPS(PFE_SKIP_DIR);
917
if (cur->proto != prev->proto)
918
PF_SET_SKIP_STEPS(PFE_SKIP_PROTO);
919
if (memcmp(&cur->src, &prev->src, sizeof(cur->src)) != 0)
920
PF_SET_SKIP_STEPS(PFE_SKIP_SRC_ADDR);
921
if (memcmp(&cur->dst, &prev->dst, sizeof(cur->dst)) != 0)
922
PF_SET_SKIP_STEPS(PFE_SKIP_DST_ADDR);
923
if (cur->ipsrc.neg != prev->ipsrc.neg ||
924
pf_addr_wrap_neq(&cur->ipsrc.addr, &prev->ipsrc.addr))
925
PF_SET_SKIP_STEPS(PFE_SKIP_SRC_IP_ADDR);
926
if (cur->ipdst.neg != prev->ipdst.neg ||
927
pf_addr_wrap_neq(&cur->ipdst.addr, &prev->ipdst.addr))
928
PF_SET_SKIP_STEPS(PFE_SKIP_DST_IP_ADDR);
929
930
prev = cur;
931
cur = TAILQ_NEXT(cur, entries);
932
}
933
for (i = 0; i < PFE_SKIP_COUNT; ++i)
934
PF_SET_SKIP_STEPS(i);
935
}
936
937
static int
938
pf_commit_eth(uint32_t ticket, const char *anchor)
939
{
940
struct pf_keth_ruleq *rules;
941
struct pf_keth_ruleset *rs;
942
943
rs = pf_find_keth_ruleset(anchor);
944
if (rs == NULL) {
945
return (EINVAL);
946
}
947
948
if (!rs->inactive.open ||
949
ticket != rs->inactive.ticket)
950
return (EBUSY);
951
952
PF_RULES_WASSERT();
953
954
pf_eth_calc_skip_steps(rs->inactive.rules);
955
956
rules = rs->active.rules;
957
atomic_store_ptr(&rs->active.rules, rs->inactive.rules);
958
rs->inactive.rules = rules;
959
rs->inactive.ticket = rs->active.ticket;
960
961
return (pf_rollback_eth(rs->inactive.ticket,
962
rs->anchor ? rs->anchor->path : ""));
963
}
964
965
#ifdef ALTQ
966
uint16_t
967
pf_qname2qid(const char *qname, bool add_new)
968
{
969
return (tagname2tag(&V_pf_qids, qname, add_new));
970
}
971
972
static const char *
973
pf_qid2qname(uint16_t qid)
974
{
975
return (tag2tagname(&V_pf_qids, qid));
976
}
977
978
static void
979
pf_qid_unref(uint16_t qid)
980
{
981
tag_unref(&V_pf_qids, qid);
982
}
983
984
static int
985
pf_begin_altq(u_int32_t *ticket)
986
{
987
struct pf_altq *altq, *tmp;
988
int error = 0;
989
990
PF_RULES_WASSERT();
991
992
/* Purge the old altq lists */
993
TAILQ_FOREACH_SAFE(altq, V_pf_altq_ifs_inactive, entries, tmp) {
994
if ((altq->local_flags & PFALTQ_FLAG_IF_REMOVED) == 0) {
995
/* detach and destroy the discipline */
996
error = altq_remove(altq);
997
}
998
free(altq, M_PFALTQ);
999
}
1000
TAILQ_INIT(V_pf_altq_ifs_inactive);
1001
TAILQ_FOREACH_SAFE(altq, V_pf_altqs_inactive, entries, tmp) {
1002
pf_qid_unref(altq->qid);
1003
free(altq, M_PFALTQ);
1004
}
1005
TAILQ_INIT(V_pf_altqs_inactive);
1006
if (error)
1007
return (error);
1008
*ticket = ++V_ticket_altqs_inactive;
1009
V_altqs_inactive_open = 1;
1010
return (0);
1011
}
1012
1013
static int
1014
pf_rollback_altq(u_int32_t ticket)
1015
{
1016
struct pf_altq *altq, *tmp;
1017
int error = 0;
1018
1019
PF_RULES_WASSERT();
1020
1021
if (!V_altqs_inactive_open || ticket != V_ticket_altqs_inactive)
1022
return (0);
1023
/* Purge the old altq lists */
1024
TAILQ_FOREACH_SAFE(altq, V_pf_altq_ifs_inactive, entries, tmp) {
1025
if ((altq->local_flags & PFALTQ_FLAG_IF_REMOVED) == 0) {
1026
/* detach and destroy the discipline */
1027
error = altq_remove(altq);
1028
}
1029
free(altq, M_PFALTQ);
1030
}
1031
TAILQ_INIT(V_pf_altq_ifs_inactive);
1032
TAILQ_FOREACH_SAFE(altq, V_pf_altqs_inactive, entries, tmp) {
1033
pf_qid_unref(altq->qid);
1034
free(altq, M_PFALTQ);
1035
}
1036
TAILQ_INIT(V_pf_altqs_inactive);
1037
V_altqs_inactive_open = 0;
1038
return (error);
1039
}
1040
1041
static int
1042
pf_commit_altq(u_int32_t ticket)
1043
{
1044
struct pf_altqqueue *old_altqs, *old_altq_ifs;
1045
struct pf_altq *altq, *tmp;
1046
int err, error = 0;
1047
1048
PF_RULES_WASSERT();
1049
1050
if (!V_altqs_inactive_open || ticket != V_ticket_altqs_inactive)
1051
return (EBUSY);
1052
1053
/* swap altqs, keep the old. */
1054
old_altqs = V_pf_altqs_active;
1055
old_altq_ifs = V_pf_altq_ifs_active;
1056
V_pf_altqs_active = V_pf_altqs_inactive;
1057
V_pf_altq_ifs_active = V_pf_altq_ifs_inactive;
1058
V_pf_altqs_inactive = old_altqs;
1059
V_pf_altq_ifs_inactive = old_altq_ifs;
1060
V_ticket_altqs_active = V_ticket_altqs_inactive;
1061
1062
/* Attach new disciplines */
1063
TAILQ_FOREACH(altq, V_pf_altq_ifs_active, entries) {
1064
if ((altq->local_flags & PFALTQ_FLAG_IF_REMOVED) == 0) {
1065
/* attach the discipline */
1066
error = altq_pfattach(altq);
1067
if (error == 0 && V_pf_altq_running)
1068
error = pf_enable_altq(altq);
1069
if (error != 0)
1070
return (error);
1071
}
1072
}
1073
1074
/* Purge the old altq lists */
1075
TAILQ_FOREACH_SAFE(altq, V_pf_altq_ifs_inactive, entries, tmp) {
1076
if ((altq->local_flags & PFALTQ_FLAG_IF_REMOVED) == 0) {
1077
/* detach and destroy the discipline */
1078
if (V_pf_altq_running)
1079
error = pf_disable_altq(altq);
1080
err = altq_pfdetach(altq);
1081
if (err != 0 && error == 0)
1082
error = err;
1083
err = altq_remove(altq);
1084
if (err != 0 && error == 0)
1085
error = err;
1086
}
1087
free(altq, M_PFALTQ);
1088
}
1089
TAILQ_INIT(V_pf_altq_ifs_inactive);
1090
TAILQ_FOREACH_SAFE(altq, V_pf_altqs_inactive, entries, tmp) {
1091
pf_qid_unref(altq->qid);
1092
free(altq, M_PFALTQ);
1093
}
1094
TAILQ_INIT(V_pf_altqs_inactive);
1095
1096
V_altqs_inactive_open = 0;
1097
return (error);
1098
}
1099
1100
static int
1101
pf_enable_altq(struct pf_altq *altq)
1102
{
1103
struct ifnet *ifp;
1104
struct tb_profile tb;
1105
int error = 0;
1106
1107
if ((ifp = ifunit(altq->ifname)) == NULL)
1108
return (EINVAL);
1109
1110
if (ifp->if_snd.altq_type != ALTQT_NONE)
1111
error = altq_enable(&ifp->if_snd);
1112
1113
/* set tokenbucket regulator */
1114
if (error == 0 && ifp != NULL && ALTQ_IS_ENABLED(&ifp->if_snd)) {
1115
tb.rate = altq->ifbandwidth;
1116
tb.depth = altq->tbrsize;
1117
error = tbr_set(&ifp->if_snd, &tb);
1118
}
1119
1120
return (error);
1121
}
1122
1123
static int
1124
pf_disable_altq(struct pf_altq *altq)
1125
{
1126
struct ifnet *ifp;
1127
struct tb_profile tb;
1128
int error;
1129
1130
if ((ifp = ifunit(altq->ifname)) == NULL)
1131
return (EINVAL);
1132
1133
/*
1134
* when the discipline is no longer referenced, it was overridden
1135
* by a new one. if so, just return.
1136
*/
1137
if (altq->altq_disc != ifp->if_snd.altq_disc)
1138
return (0);
1139
1140
error = altq_disable(&ifp->if_snd);
1141
1142
if (error == 0) {
1143
/* clear tokenbucket regulator */
1144
tb.rate = 0;
1145
error = tbr_set(&ifp->if_snd, &tb);
1146
}
1147
1148
return (error);
1149
}
1150
1151
static int
1152
pf_altq_ifnet_event_add(struct ifnet *ifp, int remove, u_int32_t ticket,
1153
struct pf_altq *altq)
1154
{
1155
struct ifnet *ifp1;
1156
int error = 0;
1157
1158
/* Deactivate the interface in question */
1159
altq->local_flags &= ~PFALTQ_FLAG_IF_REMOVED;
1160
if ((ifp1 = ifunit(altq->ifname)) == NULL ||
1161
(remove && ifp1 == ifp)) {
1162
altq->local_flags |= PFALTQ_FLAG_IF_REMOVED;
1163
} else {
1164
error = altq_add(ifp1, altq);
1165
1166
if (ticket != V_ticket_altqs_inactive)
1167
error = EBUSY;
1168
1169
if (error)
1170
free(altq, M_PFALTQ);
1171
}
1172
1173
return (error);
1174
}
1175
1176
void
1177
pf_altq_ifnet_event(struct ifnet *ifp, int remove)
1178
{
1179
struct pf_altq *a1, *a2, *a3;
1180
u_int32_t ticket;
1181
int error = 0;
1182
1183
/*
1184
* No need to re-evaluate the configuration for events on interfaces
1185
* that do not support ALTQ, as it's not possible for such
1186
* interfaces to be part of the configuration.
1187
*/
1188
if (!ALTQ_IS_READY(&ifp->if_snd))
1189
return;
1190
1191
/* Interrupt userland queue modifications */
1192
if (V_altqs_inactive_open)
1193
pf_rollback_altq(V_ticket_altqs_inactive);
1194
1195
/* Start new altq ruleset */
1196
if (pf_begin_altq(&ticket))
1197
return;
1198
1199
/* Copy the current active set */
1200
TAILQ_FOREACH(a1, V_pf_altq_ifs_active, entries) {
1201
a2 = malloc(sizeof(*a2), M_PFALTQ, M_NOWAIT);
1202
if (a2 == NULL) {
1203
error = ENOMEM;
1204
break;
1205
}
1206
bcopy(a1, a2, sizeof(struct pf_altq));
1207
1208
error = pf_altq_ifnet_event_add(ifp, remove, ticket, a2);
1209
if (error)
1210
break;
1211
1212
TAILQ_INSERT_TAIL(V_pf_altq_ifs_inactive, a2, entries);
1213
}
1214
if (error)
1215
goto out;
1216
TAILQ_FOREACH(a1, V_pf_altqs_active, entries) {
1217
a2 = malloc(sizeof(*a2), M_PFALTQ, M_NOWAIT);
1218
if (a2 == NULL) {
1219
error = ENOMEM;
1220
break;
1221
}
1222
bcopy(a1, a2, sizeof(struct pf_altq));
1223
1224
if ((a2->qid = pf_qname2qid(a2->qname, true)) == 0) {
1225
error = EBUSY;
1226
free(a2, M_PFALTQ);
1227
break;
1228
}
1229
a2->altq_disc = NULL;
1230
TAILQ_FOREACH(a3, V_pf_altq_ifs_inactive, entries) {
1231
if (strncmp(a3->ifname, a2->ifname,
1232
IFNAMSIZ) == 0) {
1233
a2->altq_disc = a3->altq_disc;
1234
break;
1235
}
1236
}
1237
error = pf_altq_ifnet_event_add(ifp, remove, ticket, a2);
1238
if (error)
1239
break;
1240
1241
TAILQ_INSERT_TAIL(V_pf_altqs_inactive, a2, entries);
1242
}
1243
1244
out:
1245
if (error != 0)
1246
pf_rollback_altq(ticket);
1247
else
1248
pf_commit_altq(ticket);
1249
}
1250
#endif /* ALTQ */
1251
1252
static struct pf_krule_global *
1253
pf_rule_tree_alloc(int flags)
1254
{
1255
struct pf_krule_global *tree;
1256
1257
tree = malloc(sizeof(struct pf_krule_global), M_PF, flags);
1258
if (tree == NULL)
1259
return (NULL);
1260
RB_INIT(tree);
1261
return (tree);
1262
}
1263
1264
void
1265
pf_rule_tree_free(struct pf_krule_global *tree)
1266
{
1267
1268
free(tree, M_PF);
1269
}
1270
1271
static int
1272
pf_begin_rules(u_int32_t *ticket, int rs_num, const char *anchor)
1273
{
1274
struct pf_krule_global *tree;
1275
struct pf_kruleset *rs;
1276
struct pf_krule *rule;
1277
1278
PF_RULES_WASSERT();
1279
1280
if (rs_num < 0 || rs_num >= PF_RULESET_MAX)
1281
return (EINVAL);
1282
tree = pf_rule_tree_alloc(M_NOWAIT);
1283
if (tree == NULL)
1284
return (ENOMEM);
1285
rs = pf_find_or_create_kruleset(anchor);
1286
if (rs == NULL) {
1287
pf_rule_tree_free(tree);
1288
return (EINVAL);
1289
}
1290
pf_rule_tree_free(rs->rules[rs_num].inactive.tree);
1291
rs->rules[rs_num].inactive.tree = tree;
1292
1293
while ((rule = TAILQ_FIRST(rs->rules[rs_num].inactive.ptr)) != NULL) {
1294
pf_unlink_rule(rs->rules[rs_num].inactive.ptr, rule);
1295
rs->rules[rs_num].inactive.rcount--;
1296
}
1297
*ticket = ++rs->rules[rs_num].inactive.ticket;
1298
rs->rules[rs_num].inactive.open = 1;
1299
return (0);
1300
}
1301
1302
static int
1303
pf_rollback_rules(u_int32_t ticket, int rs_num, char *anchor)
1304
{
1305
struct pf_kruleset *rs;
1306
struct pf_krule *rule;
1307
1308
PF_RULES_WASSERT();
1309
1310
if (rs_num < 0 || rs_num >= PF_RULESET_MAX)
1311
return (EINVAL);
1312
rs = pf_find_kruleset(anchor);
1313
if (rs == NULL || !rs->rules[rs_num].inactive.open ||
1314
rs->rules[rs_num].inactive.ticket != ticket)
1315
return (0);
1316
while ((rule = TAILQ_FIRST(rs->rules[rs_num].inactive.ptr)) != NULL) {
1317
pf_unlink_rule(rs->rules[rs_num].inactive.ptr, rule);
1318
rs->rules[rs_num].inactive.rcount--;
1319
}
1320
rs->rules[rs_num].inactive.open = 0;
1321
return (0);
1322
}
1323
1324
#define PF_MD5_UPD(st, elm) \
1325
MD5Update(ctx, (u_int8_t *) &(st)->elm, sizeof((st)->elm))
1326
1327
#define PF_MD5_UPD_STR(st, elm) \
1328
MD5Update(ctx, (u_int8_t *) (st)->elm, strlen((st)->elm))
1329
1330
#define PF_MD5_UPD_HTONL(st, elm, stor) do { \
1331
(stor) = htonl((st)->elm); \
1332
MD5Update(ctx, (u_int8_t *) &(stor), sizeof(u_int32_t));\
1333
} while (0)
1334
1335
#define PF_MD5_UPD_HTONS(st, elm, stor) do { \
1336
(stor) = htons((st)->elm); \
1337
MD5Update(ctx, (u_int8_t *) &(stor), sizeof(u_int16_t));\
1338
} while (0)
1339
1340
static void
1341
pf_hash_rule_addr(MD5_CTX *ctx, struct pf_rule_addr *pfr)
1342
{
1343
PF_MD5_UPD(pfr, addr.type);
1344
switch (pfr->addr.type) {
1345
case PF_ADDR_DYNIFTL:
1346
PF_MD5_UPD(pfr, addr.v.ifname);
1347
PF_MD5_UPD(pfr, addr.iflags);
1348
break;
1349
case PF_ADDR_TABLE:
1350
if (strncmp(pfr->addr.v.tblname, PF_OPTIMIZER_TABLE_PFX,
1351
strlen(PF_OPTIMIZER_TABLE_PFX)))
1352
PF_MD5_UPD(pfr, addr.v.tblname);
1353
break;
1354
case PF_ADDR_ADDRMASK:
1355
/* XXX ignore af? */
1356
PF_MD5_UPD(pfr, addr.v.a.addr.addr32);
1357
PF_MD5_UPD(pfr, addr.v.a.mask.addr32);
1358
break;
1359
}
1360
1361
PF_MD5_UPD(pfr, port[0]);
1362
PF_MD5_UPD(pfr, port[1]);
1363
PF_MD5_UPD(pfr, neg);
1364
PF_MD5_UPD(pfr, port_op);
1365
}
1366
1367
static void
1368
pf_hash_rule_rolling(MD5_CTX *ctx, struct pf_krule *rule)
1369
{
1370
u_int16_t x;
1371
u_int32_t y;
1372
1373
pf_hash_rule_addr(ctx, &rule->src);
1374
pf_hash_rule_addr(ctx, &rule->dst);
1375
for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++)
1376
PF_MD5_UPD_STR(rule, label[i]);
1377
PF_MD5_UPD_STR(rule, ifname);
1378
PF_MD5_UPD_STR(rule, rcv_ifname);
1379
PF_MD5_UPD_STR(rule, match_tagname);
1380
PF_MD5_UPD_HTONS(rule, match_tag, x); /* dup? */
1381
PF_MD5_UPD_HTONL(rule, os_fingerprint, y);
1382
PF_MD5_UPD_HTONL(rule, prob, y);
1383
PF_MD5_UPD_HTONL(rule, uid.uid[0], y);
1384
PF_MD5_UPD_HTONL(rule, uid.uid[1], y);
1385
PF_MD5_UPD(rule, uid.op);
1386
PF_MD5_UPD_HTONL(rule, gid.gid[0], y);
1387
PF_MD5_UPD_HTONL(rule, gid.gid[1], y);
1388
PF_MD5_UPD(rule, gid.op);
1389
PF_MD5_UPD_HTONL(rule, rule_flag, y);
1390
PF_MD5_UPD(rule, action);
1391
PF_MD5_UPD(rule, direction);
1392
PF_MD5_UPD(rule, af);
1393
PF_MD5_UPD(rule, quick);
1394
PF_MD5_UPD(rule, ifnot);
1395
PF_MD5_UPD(rule, rcvifnot);
1396
PF_MD5_UPD(rule, match_tag_not);
1397
PF_MD5_UPD(rule, natpass);
1398
PF_MD5_UPD(rule, keep_state);
1399
PF_MD5_UPD(rule, proto);
1400
PF_MD5_UPD(rule, type);
1401
PF_MD5_UPD(rule, code);
1402
PF_MD5_UPD(rule, flags);
1403
PF_MD5_UPD(rule, flagset);
1404
PF_MD5_UPD(rule, allow_opts);
1405
PF_MD5_UPD(rule, rt);
1406
PF_MD5_UPD(rule, tos);
1407
PF_MD5_UPD(rule, scrub_flags);
1408
PF_MD5_UPD(rule, min_ttl);
1409
PF_MD5_UPD(rule, set_tos);
1410
if (rule->anchor != NULL)
1411
PF_MD5_UPD_STR(rule, anchor->path);
1412
}
1413
1414
static void
1415
pf_hash_rule(struct pf_krule *rule)
1416
{
1417
MD5_CTX ctx;
1418
1419
MD5Init(&ctx);
1420
pf_hash_rule_rolling(&ctx, rule);
1421
MD5Final(rule->md5sum, &ctx);
1422
}
1423
1424
static int
1425
pf_krule_compare(struct pf_krule *a, struct pf_krule *b)
1426
{
1427
1428
return (memcmp(a->md5sum, b->md5sum, PF_MD5_DIGEST_LENGTH));
1429
}
1430
1431
static int
1432
pf_commit_rules(u_int32_t ticket, int rs_num, char *anchor)
1433
{
1434
struct pf_kruleset *rs;
1435
struct pf_krule *rule, *old_rule;
1436
struct pf_krulequeue *old_rules;
1437
struct pf_krule_global *old_tree;
1438
int error;
1439
u_int32_t old_rcount;
1440
1441
PF_RULES_WASSERT();
1442
1443
if (rs_num < 0 || rs_num >= PF_RULESET_MAX)
1444
return (EINVAL);
1445
rs = pf_find_kruleset(anchor);
1446
if (rs == NULL || !rs->rules[rs_num].inactive.open ||
1447
ticket != rs->rules[rs_num].inactive.ticket)
1448
return (EBUSY);
1449
1450
/* Calculate checksum for the main ruleset */
1451
if (rs == &pf_main_ruleset) {
1452
error = pf_setup_pfsync_matching(rs);
1453
if (error != 0)
1454
return (error);
1455
}
1456
1457
/* Swap rules, keep the old. */
1458
old_rules = rs->rules[rs_num].active.ptr;
1459
old_rcount = rs->rules[rs_num].active.rcount;
1460
old_tree = rs->rules[rs_num].active.tree;
1461
1462
rs->rules[rs_num].active.ptr =
1463
rs->rules[rs_num].inactive.ptr;
1464
rs->rules[rs_num].active.tree =
1465
rs->rules[rs_num].inactive.tree;
1466
rs->rules[rs_num].active.rcount =
1467
rs->rules[rs_num].inactive.rcount;
1468
1469
/* Attempt to preserve counter information. */
1470
if (V_pf_status.keep_counters && old_tree != NULL) {
1471
TAILQ_FOREACH(rule, rs->rules[rs_num].active.ptr,
1472
entries) {
1473
old_rule = RB_FIND(pf_krule_global, old_tree, rule);
1474
if (old_rule == NULL) {
1475
continue;
1476
}
1477
pf_counter_u64_critical_enter();
1478
pf_counter_u64_rollup_protected(&rule->evaluations,
1479
pf_counter_u64_fetch(&old_rule->evaluations));
1480
pf_counter_u64_rollup_protected(&rule->packets[0],
1481
pf_counter_u64_fetch(&old_rule->packets[0]));
1482
pf_counter_u64_rollup_protected(&rule->packets[1],
1483
pf_counter_u64_fetch(&old_rule->packets[1]));
1484
pf_counter_u64_rollup_protected(&rule->bytes[0],
1485
pf_counter_u64_fetch(&old_rule->bytes[0]));
1486
pf_counter_u64_rollup_protected(&rule->bytes[1],
1487
pf_counter_u64_fetch(&old_rule->bytes[1]));
1488
pf_counter_u64_critical_exit();
1489
}
1490
}
1491
1492
rs->rules[rs_num].inactive.ptr = old_rules;
1493
rs->rules[rs_num].inactive.tree = NULL; /* important for pf_ioctl_addrule */
1494
rs->rules[rs_num].inactive.rcount = old_rcount;
1495
1496
rs->rules[rs_num].active.ticket =
1497
rs->rules[rs_num].inactive.ticket;
1498
pf_calc_skip_steps(rs->rules[rs_num].active.ptr);
1499
1500
/* Purge the old rule list. */
1501
PF_UNLNKDRULES_LOCK();
1502
while ((rule = TAILQ_FIRST(old_rules)) != NULL)
1503
pf_unlink_rule_locked(old_rules, rule);
1504
PF_UNLNKDRULES_UNLOCK();
1505
rs->rules[rs_num].inactive.rcount = 0;
1506
rs->rules[rs_num].inactive.open = 0;
1507
pf_remove_if_empty_kruleset(rs);
1508
pf_rule_tree_free(old_tree);
1509
1510
return (0);
1511
}
1512
1513
static int
1514
pf_setup_pfsync_matching(struct pf_kruleset *rs)
1515
{
1516
MD5_CTX ctx;
1517
struct pf_krule *rule;
1518
int rs_cnt;
1519
u_int8_t digest[PF_MD5_DIGEST_LENGTH];
1520
1521
MD5Init(&ctx);
1522
for (rs_cnt = 0; rs_cnt < PF_RULESET_MAX; rs_cnt++) {
1523
/* XXX PF_RULESET_SCRUB as well? */
1524
if (rs_cnt == PF_RULESET_SCRUB)
1525
continue;
1526
1527
if (rs->rules[rs_cnt].inactive.rcount) {
1528
TAILQ_FOREACH(rule, rs->rules[rs_cnt].inactive.ptr,
1529
entries) {
1530
pf_hash_rule_rolling(&ctx, rule);
1531
}
1532
}
1533
}
1534
1535
MD5Final(digest, &ctx);
1536
memcpy(V_pf_status.pf_chksum, digest, sizeof(V_pf_status.pf_chksum));
1537
return (0);
1538
}
1539
1540
static int
1541
pf_eth_addr_setup(struct pf_keth_ruleset *ruleset, struct pf_addr_wrap *addr)
1542
{
1543
int error = 0;
1544
1545
switch (addr->type) {
1546
case PF_ADDR_TABLE:
1547
addr->p.tbl = pfr_eth_attach_table(ruleset, addr->v.tblname);
1548
if (addr->p.tbl == NULL)
1549
error = ENOMEM;
1550
break;
1551
default:
1552
error = EINVAL;
1553
}
1554
1555
return (error);
1556
}
1557
1558
static int
1559
pf_addr_setup(struct pf_kruleset *ruleset, struct pf_addr_wrap *addr,
1560
sa_family_t af)
1561
{
1562
int error = 0;
1563
1564
switch (addr->type) {
1565
case PF_ADDR_TABLE:
1566
addr->p.tbl = pfr_attach_table(ruleset, addr->v.tblname);
1567
if (addr->p.tbl == NULL)
1568
error = ENOMEM;
1569
break;
1570
case PF_ADDR_DYNIFTL:
1571
error = pfi_dynaddr_setup(addr, af);
1572
break;
1573
}
1574
1575
return (error);
1576
}
1577
1578
void
1579
pf_addr_copyout(struct pf_addr_wrap *addr)
1580
{
1581
1582
switch (addr->type) {
1583
case PF_ADDR_DYNIFTL:
1584
pfi_dynaddr_copyout(addr);
1585
break;
1586
case PF_ADDR_TABLE:
1587
pf_tbladdr_copyout(addr);
1588
break;
1589
}
1590
}
1591
1592
static void
1593
pf_src_node_copy(const struct pf_ksrc_node *in, struct pf_src_node *out)
1594
{
1595
int secs = time_uptime;
1596
1597
bzero(out, sizeof(struct pf_src_node));
1598
1599
bcopy(&in->addr, &out->addr, sizeof(struct pf_addr));
1600
bcopy(&in->raddr, &out->raddr, sizeof(struct pf_addr));
1601
1602
if (in->rule != NULL)
1603
out->rule.nr = in->rule->nr;
1604
1605
for (int i = 0; i < 2; i++) {
1606
out->bytes[i] = counter_u64_fetch(in->bytes[i]);
1607
out->packets[i] = counter_u64_fetch(in->packets[i]);
1608
}
1609
1610
out->states = in->states;
1611
out->conn = in->conn;
1612
out->af = in->af;
1613
out->ruletype = in->ruletype;
1614
1615
out->creation = secs - in->creation;
1616
if (out->expire > secs)
1617
out->expire -= secs;
1618
else
1619
out->expire = 0;
1620
1621
/* Adjust the connection rate estimate. */
1622
out->conn_rate.limit = in->conn_rate.limit;
1623
out->conn_rate.seconds = in->conn_rate.seconds;
1624
/* If there's no limit there's no counter_rate. */
1625
if (in->conn_rate.cr != NULL)
1626
out->conn_rate.count = counter_rate_get(in->conn_rate.cr);
1627
}
1628
1629
#ifdef ALTQ
1630
/*
1631
* Handle export of struct pf_kaltq to user binaries that may be using any
1632
* version of struct pf_altq.
1633
*/
1634
static int
1635
pf_export_kaltq(struct pf_altq *q, struct pfioc_altq_v1 *pa, size_t ioc_size)
1636
{
1637
u_int32_t version;
1638
1639
if (ioc_size == sizeof(struct pfioc_altq_v0))
1640
version = 0;
1641
else
1642
version = pa->version;
1643
1644
if (version > PFIOC_ALTQ_VERSION)
1645
return (EINVAL);
1646
1647
#define ASSIGN(x) exported_q->x = q->x
1648
#define COPY(x) \
1649
bcopy(&q->x, &exported_q->x, min(sizeof(q->x), sizeof(exported_q->x)))
1650
#define SATU16(x) (u_int32_t)uqmin((x), USHRT_MAX)
1651
#define SATU32(x) (u_int32_t)uqmin((x), UINT_MAX)
1652
1653
switch (version) {
1654
case 0: {
1655
struct pf_altq_v0 *exported_q =
1656
&((struct pfioc_altq_v0 *)pa)->altq;
1657
1658
COPY(ifname);
1659
1660
ASSIGN(scheduler);
1661
ASSIGN(tbrsize);
1662
exported_q->tbrsize = SATU16(q->tbrsize);
1663
exported_q->ifbandwidth = SATU32(q->ifbandwidth);
1664
1665
COPY(qname);
1666
COPY(parent);
1667
ASSIGN(parent_qid);
1668
exported_q->bandwidth = SATU32(q->bandwidth);
1669
ASSIGN(priority);
1670
ASSIGN(local_flags);
1671
1672
ASSIGN(qlimit);
1673
ASSIGN(flags);
1674
1675
if (q->scheduler == ALTQT_HFSC) {
1676
#define ASSIGN_OPT(x) exported_q->pq_u.hfsc_opts.x = q->pq_u.hfsc_opts.x
1677
#define ASSIGN_OPT_SATU32(x) exported_q->pq_u.hfsc_opts.x = \
1678
SATU32(q->pq_u.hfsc_opts.x)
1679
1680
ASSIGN_OPT_SATU32(rtsc_m1);
1681
ASSIGN_OPT(rtsc_d);
1682
ASSIGN_OPT_SATU32(rtsc_m2);
1683
1684
ASSIGN_OPT_SATU32(lssc_m1);
1685
ASSIGN_OPT(lssc_d);
1686
ASSIGN_OPT_SATU32(lssc_m2);
1687
1688
ASSIGN_OPT_SATU32(ulsc_m1);
1689
ASSIGN_OPT(ulsc_d);
1690
ASSIGN_OPT_SATU32(ulsc_m2);
1691
1692
ASSIGN_OPT(flags);
1693
1694
#undef ASSIGN_OPT
1695
#undef ASSIGN_OPT_SATU32
1696
} else
1697
COPY(pq_u);
1698
1699
ASSIGN(qid);
1700
break;
1701
}
1702
case 1: {
1703
struct pf_altq_v1 *exported_q =
1704
&((struct pfioc_altq_v1 *)pa)->altq;
1705
1706
COPY(ifname);
1707
1708
ASSIGN(scheduler);
1709
ASSIGN(tbrsize);
1710
ASSIGN(ifbandwidth);
1711
1712
COPY(qname);
1713
COPY(parent);
1714
ASSIGN(parent_qid);
1715
ASSIGN(bandwidth);
1716
ASSIGN(priority);
1717
ASSIGN(local_flags);
1718
1719
ASSIGN(qlimit);
1720
ASSIGN(flags);
1721
COPY(pq_u);
1722
1723
ASSIGN(qid);
1724
break;
1725
}
1726
default:
1727
panic("%s: unhandled struct pfioc_altq version", __func__);
1728
break;
1729
}
1730
1731
#undef ASSIGN
1732
#undef COPY
1733
#undef SATU16
1734
#undef SATU32
1735
1736
return (0);
1737
}
1738
1739
/*
1740
* Handle import to struct pf_kaltq of struct pf_altq from user binaries
1741
* that may be using any version of it.
1742
*/
1743
static int
1744
pf_import_kaltq(struct pfioc_altq_v1 *pa, struct pf_altq *q, size_t ioc_size)
1745
{
1746
u_int32_t version;
1747
1748
if (ioc_size == sizeof(struct pfioc_altq_v0))
1749
version = 0;
1750
else
1751
version = pa->version;
1752
1753
if (version > PFIOC_ALTQ_VERSION)
1754
return (EINVAL);
1755
1756
#define ASSIGN(x) q->x = imported_q->x
1757
#define COPY(x) \
1758
bcopy(&imported_q->x, &q->x, min(sizeof(imported_q->x), sizeof(q->x)))
1759
1760
switch (version) {
1761
case 0: {
1762
struct pf_altq_v0 *imported_q =
1763
&((struct pfioc_altq_v0 *)pa)->altq;
1764
1765
COPY(ifname);
1766
1767
ASSIGN(scheduler);
1768
ASSIGN(tbrsize); /* 16-bit -> 32-bit */
1769
ASSIGN(ifbandwidth); /* 32-bit -> 64-bit */
1770
1771
COPY(qname);
1772
COPY(parent);
1773
ASSIGN(parent_qid);
1774
ASSIGN(bandwidth); /* 32-bit -> 64-bit */
1775
ASSIGN(priority);
1776
ASSIGN(local_flags);
1777
1778
ASSIGN(qlimit);
1779
ASSIGN(flags);
1780
1781
if (imported_q->scheduler == ALTQT_HFSC) {
1782
#define ASSIGN_OPT(x) q->pq_u.hfsc_opts.x = imported_q->pq_u.hfsc_opts.x
1783
1784
/*
1785
* The m1 and m2 parameters are being copied from
1786
* 32-bit to 64-bit.
1787
*/
1788
ASSIGN_OPT(rtsc_m1);
1789
ASSIGN_OPT(rtsc_d);
1790
ASSIGN_OPT(rtsc_m2);
1791
1792
ASSIGN_OPT(lssc_m1);
1793
ASSIGN_OPT(lssc_d);
1794
ASSIGN_OPT(lssc_m2);
1795
1796
ASSIGN_OPT(ulsc_m1);
1797
ASSIGN_OPT(ulsc_d);
1798
ASSIGN_OPT(ulsc_m2);
1799
1800
ASSIGN_OPT(flags);
1801
1802
#undef ASSIGN_OPT
1803
} else
1804
COPY(pq_u);
1805
1806
ASSIGN(qid);
1807
break;
1808
}
1809
case 1: {
1810
struct pf_altq_v1 *imported_q =
1811
&((struct pfioc_altq_v1 *)pa)->altq;
1812
1813
COPY(ifname);
1814
1815
ASSIGN(scheduler);
1816
ASSIGN(tbrsize);
1817
ASSIGN(ifbandwidth);
1818
1819
COPY(qname);
1820
COPY(parent);
1821
ASSIGN(parent_qid);
1822
ASSIGN(bandwidth);
1823
ASSIGN(priority);
1824
ASSIGN(local_flags);
1825
1826
ASSIGN(qlimit);
1827
ASSIGN(flags);
1828
COPY(pq_u);
1829
1830
ASSIGN(qid);
1831
break;
1832
}
1833
default:
1834
panic("%s: unhandled struct pfioc_altq version", __func__);
1835
break;
1836
}
1837
1838
#undef ASSIGN
1839
#undef COPY
1840
1841
return (0);
1842
}
1843
1844
static struct pf_altq *
1845
pf_altq_get_nth_active(u_int32_t n)
1846
{
1847
struct pf_altq *altq;
1848
u_int32_t nr;
1849
1850
nr = 0;
1851
TAILQ_FOREACH(altq, V_pf_altq_ifs_active, entries) {
1852
if (nr == n)
1853
return (altq);
1854
nr++;
1855
}
1856
1857
TAILQ_FOREACH(altq, V_pf_altqs_active, entries) {
1858
if (nr == n)
1859
return (altq);
1860
nr++;
1861
}
1862
1863
return (NULL);
1864
}
1865
#endif /* ALTQ */
1866
1867
struct pf_krule *
1868
pf_krule_alloc(void)
1869
{
1870
struct pf_krule *rule;
1871
1872
rule = malloc(sizeof(struct pf_krule), M_PFRULE, M_WAITOK | M_ZERO);
1873
mtx_init(&rule->nat.mtx, "pf_krule_nat_pool", NULL, MTX_DEF);
1874
mtx_init(&rule->rdr.mtx, "pf_krule_rdr_pool", NULL, MTX_DEF);
1875
mtx_init(&rule->route.mtx, "pf_krule_route_pool", NULL, MTX_DEF);
1876
rule->timestamp = uma_zalloc_pcpu(pf_timestamp_pcpu_zone,
1877
M_WAITOK | M_ZERO);
1878
return (rule);
1879
}
1880
1881
void
1882
pf_krule_free(struct pf_krule *rule)
1883
{
1884
#ifdef PF_WANT_32_TO_64_COUNTER
1885
bool wowned;
1886
#endif
1887
1888
if (rule == NULL)
1889
return;
1890
1891
#ifdef PF_WANT_32_TO_64_COUNTER
1892
if (rule->allrulelinked) {
1893
wowned = PF_RULES_WOWNED();
1894
if (!wowned)
1895
PF_RULES_WLOCK();
1896
LIST_REMOVE(rule, allrulelist);
1897
V_pf_allrulecount--;
1898
if (!wowned)
1899
PF_RULES_WUNLOCK();
1900
}
1901
#endif
1902
1903
pf_counter_u64_deinit(&rule->evaluations);
1904
for (int i = 0; i < 2; i++) {
1905
pf_counter_u64_deinit(&rule->packets[i]);
1906
pf_counter_u64_deinit(&rule->bytes[i]);
1907
}
1908
counter_u64_free(rule->states_cur);
1909
counter_u64_free(rule->states_tot);
1910
for (pf_sn_types_t sn_type=0; sn_type<PF_SN_MAX; sn_type++)
1911
counter_u64_free(rule->src_nodes[sn_type]);
1912
uma_zfree_pcpu(pf_timestamp_pcpu_zone, rule->timestamp);
1913
1914
mtx_destroy(&rule->nat.mtx);
1915
mtx_destroy(&rule->rdr.mtx);
1916
mtx_destroy(&rule->route.mtx);
1917
free(rule, M_PFRULE);
1918
}
1919
1920
void
1921
pf_krule_clear_counters(struct pf_krule *rule)
1922
{
1923
pf_counter_u64_zero(&rule->evaluations);
1924
for (int i = 0; i < 2; i++) {
1925
pf_counter_u64_zero(&rule->packets[i]);
1926
pf_counter_u64_zero(&rule->bytes[i]);
1927
}
1928
counter_u64_zero(rule->states_tot);
1929
}
1930
1931
static void
1932
pf_kpooladdr_to_pooladdr(const struct pf_kpooladdr *kpool,
1933
struct pf_pooladdr *pool)
1934
{
1935
1936
bzero(pool, sizeof(*pool));
1937
bcopy(&kpool->addr, &pool->addr, sizeof(pool->addr));
1938
strlcpy(pool->ifname, kpool->ifname, sizeof(pool->ifname));
1939
}
1940
1941
static int
1942
pf_pooladdr_to_kpooladdr(const struct pf_pooladdr *pool,
1943
struct pf_kpooladdr *kpool)
1944
{
1945
int ret;
1946
1947
bzero(kpool, sizeof(*kpool));
1948
bcopy(&pool->addr, &kpool->addr, sizeof(kpool->addr));
1949
ret = pf_user_strcpy(kpool->ifname, pool->ifname,
1950
sizeof(kpool->ifname));
1951
return (ret);
1952
}
1953
1954
static void
1955
pf_pool_to_kpool(const struct pf_pool *pool, struct pf_kpool *kpool)
1956
{
1957
_Static_assert(sizeof(pool->key) == sizeof(kpool->key), "");
1958
_Static_assert(sizeof(pool->counter) == sizeof(kpool->counter), "");
1959
1960
bcopy(&pool->key, &kpool->key, sizeof(kpool->key));
1961
bcopy(&pool->counter, &kpool->counter, sizeof(kpool->counter));
1962
1963
kpool->tblidx = pool->tblidx;
1964
kpool->proxy_port[0] = pool->proxy_port[0];
1965
kpool->proxy_port[1] = pool->proxy_port[1];
1966
kpool->opts = pool->opts;
1967
}
1968
1969
static int
1970
pf_rule_to_krule(const struct pf_rule *rule, struct pf_krule *krule)
1971
{
1972
int ret;
1973
1974
#ifndef INET
1975
if (rule->af == AF_INET) {
1976
return (EAFNOSUPPORT);
1977
}
1978
#endif /* INET */
1979
#ifndef INET6
1980
if (rule->af == AF_INET6) {
1981
return (EAFNOSUPPORT);
1982
}
1983
#endif /* INET6 */
1984
1985
ret = pf_check_rule_addr(&rule->src);
1986
if (ret != 0)
1987
return (ret);
1988
ret = pf_check_rule_addr(&rule->dst);
1989
if (ret != 0)
1990
return (ret);
1991
1992
bcopy(&rule->src, &krule->src, sizeof(rule->src));
1993
bcopy(&rule->dst, &krule->dst, sizeof(rule->dst));
1994
1995
ret = pf_user_strcpy(krule->label[0], rule->label, sizeof(rule->label));
1996
if (ret != 0)
1997
return (ret);
1998
ret = pf_user_strcpy(krule->ifname, rule->ifname, sizeof(rule->ifname));
1999
if (ret != 0)
2000
return (ret);
2001
ret = pf_user_strcpy(krule->qname, rule->qname, sizeof(rule->qname));
2002
if (ret != 0)
2003
return (ret);
2004
ret = pf_user_strcpy(krule->pqname, rule->pqname, sizeof(rule->pqname));
2005
if (ret != 0)
2006
return (ret);
2007
ret = pf_user_strcpy(krule->tagname, rule->tagname,
2008
sizeof(rule->tagname));
2009
if (ret != 0)
2010
return (ret);
2011
ret = pf_user_strcpy(krule->match_tagname, rule->match_tagname,
2012
sizeof(rule->match_tagname));
2013
if (ret != 0)
2014
return (ret);
2015
ret = pf_user_strcpy(krule->overload_tblname, rule->overload_tblname,
2016
sizeof(rule->overload_tblname));
2017
if (ret != 0)
2018
return (ret);
2019
2020
pf_pool_to_kpool(&rule->rpool, &krule->rdr);
2021
2022
/* Don't allow userspace to set evaluations, packets or bytes. */
2023
/* kif, anchor, overload_tbl are not copied over. */
2024
2025
krule->os_fingerprint = rule->os_fingerprint;
2026
2027
krule->rtableid = rule->rtableid;
2028
/* pf_rule->timeout is smaller than pf_krule->timeout */
2029
bcopy(rule->timeout, krule->timeout, sizeof(rule->timeout));
2030
krule->max_states = rule->max_states;
2031
krule->max_src_nodes = rule->max_src_nodes;
2032
krule->max_src_states = rule->max_src_states;
2033
krule->max_src_conn = rule->max_src_conn;
2034
krule->max_src_conn_rate.limit = rule->max_src_conn_rate.limit;
2035
krule->max_src_conn_rate.seconds = rule->max_src_conn_rate.seconds;
2036
krule->qid = rule->qid;
2037
krule->pqid = rule->pqid;
2038
krule->nr = rule->nr;
2039
krule->prob = rule->prob;
2040
krule->cuid = rule->cuid;
2041
krule->cpid = rule->cpid;
2042
2043
krule->return_icmp = rule->return_icmp;
2044
krule->return_icmp6 = rule->return_icmp6;
2045
krule->max_mss = rule->max_mss;
2046
krule->tag = rule->tag;
2047
krule->match_tag = rule->match_tag;
2048
krule->scrub_flags = rule->scrub_flags;
2049
2050
bcopy(&rule->uid, &krule->uid, sizeof(krule->uid));
2051
bcopy(&rule->gid, &krule->gid, sizeof(krule->gid));
2052
2053
krule->rule_flag = rule->rule_flag;
2054
krule->action = rule->action;
2055
krule->direction = rule->direction;
2056
krule->log = rule->log;
2057
krule->logif = rule->logif;
2058
krule->quick = rule->quick;
2059
krule->ifnot = rule->ifnot;
2060
krule->match_tag_not = rule->match_tag_not;
2061
krule->natpass = rule->natpass;
2062
2063
krule->keep_state = rule->keep_state;
2064
krule->af = rule->af;
2065
krule->proto = rule->proto;
2066
krule->type = rule->type;
2067
krule->code = rule->code;
2068
krule->flags = rule->flags;
2069
krule->flagset = rule->flagset;
2070
krule->min_ttl = rule->min_ttl;
2071
krule->allow_opts = rule->allow_opts;
2072
krule->rt = rule->rt;
2073
krule->return_ttl = rule->return_ttl;
2074
krule->tos = rule->tos;
2075
krule->set_tos = rule->set_tos;
2076
2077
krule->flush = rule->flush;
2078
krule->prio = rule->prio;
2079
krule->set_prio[0] = rule->set_prio[0];
2080
krule->set_prio[1] = rule->set_prio[1];
2081
2082
bcopy(&rule->divert, &krule->divert, sizeof(krule->divert));
2083
2084
return (0);
2085
}
2086
2087
int
2088
pf_ioctl_getrules(struct pfioc_rule *pr)
2089
{
2090
struct pf_kruleset *ruleset;
2091
struct pf_krule *tail;
2092
int rs_num;
2093
2094
PF_RULES_WLOCK();
2095
ruleset = pf_find_kruleset(pr->anchor);
2096
if (ruleset == NULL) {
2097
PF_RULES_WUNLOCK();
2098
return (EINVAL);
2099
}
2100
rs_num = pf_get_ruleset_number(pr->rule.action);
2101
if (rs_num >= PF_RULESET_MAX) {
2102
PF_RULES_WUNLOCK();
2103
return (EINVAL);
2104
}
2105
tail = TAILQ_LAST(ruleset->rules[rs_num].active.ptr,
2106
pf_krulequeue);
2107
if (tail)
2108
pr->nr = tail->nr + 1;
2109
else
2110
pr->nr = 0;
2111
pr->ticket = ruleset->rules[rs_num].active.ticket;
2112
PF_RULES_WUNLOCK();
2113
2114
return (0);
2115
}
2116
2117
static int
2118
pf_rule_checkaf(struct pf_krule *r)
2119
{
2120
switch (r->af) {
2121
case 0:
2122
if (r->rule_flag & PFRULE_AFTO)
2123
return (EPFNOSUPPORT);
2124
break;
2125
case AF_INET:
2126
if ((r->rule_flag & PFRULE_AFTO) && r->naf != AF_INET6)
2127
return (EPFNOSUPPORT);
2128
break;
2129
#ifdef INET6
2130
case AF_INET6:
2131
if ((r->rule_flag & PFRULE_AFTO) && r->naf != AF_INET)
2132
return (EPFNOSUPPORT);
2133
break;
2134
#endif /* INET6 */
2135
default:
2136
return (EPFNOSUPPORT);
2137
}
2138
2139
if ((r->rule_flag & PFRULE_AFTO) == 0 && r->naf != 0)
2140
return (EPFNOSUPPORT);
2141
2142
return (0);
2143
}
2144
2145
static int
2146
pf_validate_range(uint8_t op, uint16_t port[2])
2147
{
2148
uint16_t a = ntohs(port[0]);
2149
uint16_t b = ntohs(port[1]);
2150
2151
if ((op == PF_OP_RRG && a > b) || /* 34:12, i.e. none */
2152
(op == PF_OP_IRG && a >= b) || /* 34><12, i.e. none */
2153
(op == PF_OP_XRG && a > b)) /* 34<>22, i.e. all */
2154
return 1;
2155
return 0;
2156
}
2157
2158
int
2159
pf_ioctl_addrule(struct pf_krule *rule, uint32_t ticket,
2160
uint32_t pool_ticket, const char *anchor, const char *anchor_call,
2161
uid_t uid, pid_t pid)
2162
{
2163
struct pf_kruleset *ruleset;
2164
struct pf_krule *tail;
2165
struct pf_kpooladdr *pa;
2166
struct pfi_kkif *kif = NULL, *rcv_kif = NULL;
2167
int rs_num;
2168
int error = 0;
2169
2170
#define ERROUT(x) ERROUT_FUNCTION(errout, x)
2171
#define ERROUT_UNLOCKED(x) ERROUT_FUNCTION(errout_unlocked, x)
2172
2173
if ((rule->return_icmp >> 8) > ICMP_MAXTYPE)
2174
ERROUT_UNLOCKED(EINVAL);
2175
2176
if ((error = pf_rule_checkaf(rule)))
2177
ERROUT_UNLOCKED(error);
2178
if (pf_validate_range(rule->src.port_op, rule->src.port))
2179
ERROUT_UNLOCKED(EINVAL);
2180
if (pf_validate_range(rule->dst.port_op, rule->dst.port))
2181
ERROUT_UNLOCKED(EINVAL);
2182
2183
if (rule->ifname[0])
2184
kif = pf_kkif_create(M_WAITOK);
2185
if (rule->rcv_ifname[0])
2186
rcv_kif = pf_kkif_create(M_WAITOK);
2187
pf_counter_u64_init(&rule->evaluations, M_WAITOK);
2188
for (int i = 0; i < 2; i++) {
2189
pf_counter_u64_init(&rule->packets[i], M_WAITOK);
2190
pf_counter_u64_init(&rule->bytes[i], M_WAITOK);
2191
}
2192
rule->states_cur = counter_u64_alloc(M_WAITOK);
2193
rule->states_tot = counter_u64_alloc(M_WAITOK);
2194
for (pf_sn_types_t sn_type=0; sn_type<PF_SN_MAX; sn_type++)
2195
rule->src_nodes[sn_type] = counter_u64_alloc(M_WAITOK);
2196
rule->cuid = uid;
2197
rule->cpid = pid;
2198
TAILQ_INIT(&rule->rdr.list);
2199
TAILQ_INIT(&rule->nat.list);
2200
TAILQ_INIT(&rule->route.list);
2201
2202
PF_CONFIG_LOCK();
2203
PF_RULES_WLOCK();
2204
#ifdef PF_WANT_32_TO_64_COUNTER
2205
LIST_INSERT_HEAD(&V_pf_allrulelist, rule, allrulelist);
2206
MPASS(!rule->allrulelinked);
2207
rule->allrulelinked = true;
2208
V_pf_allrulecount++;
2209
#endif
2210
ruleset = pf_find_kruleset(anchor);
2211
if (ruleset == NULL)
2212
ERROUT(EINVAL);
2213
rs_num = pf_get_ruleset_number(rule->action);
2214
if (rs_num >= PF_RULESET_MAX)
2215
ERROUT(EINVAL);
2216
if (ticket != ruleset->rules[rs_num].inactive.ticket) {
2217
DPFPRINTF(PF_DEBUG_MISC,
2218
"ticket: %d != [%d]%d", ticket, rs_num,
2219
ruleset->rules[rs_num].inactive.ticket);
2220
ERROUT(EBUSY);
2221
}
2222
if (pool_ticket != V_ticket_pabuf) {
2223
DPFPRINTF(PF_DEBUG_MISC,
2224
"pool_ticket: %d != %d", pool_ticket,
2225
V_ticket_pabuf);
2226
ERROUT(EBUSY);
2227
}
2228
/*
2229
* XXXMJG hack: there is no mechanism to ensure they started the
2230
* transaction. Ticket checked above may happen to match by accident,
2231
* even if nobody called DIOCXBEGIN, let alone this process.
2232
* Partially work around it by checking if the RB tree got allocated,
2233
* see pf_begin_rules.
2234
*/
2235
if (ruleset->rules[rs_num].inactive.tree == NULL) {
2236
ERROUT(EINVAL);
2237
}
2238
2239
tail = TAILQ_LAST(ruleset->rules[rs_num].inactive.ptr,
2240
pf_krulequeue);
2241
if (tail)
2242
rule->nr = tail->nr + 1;
2243
else
2244
rule->nr = 0;
2245
if (rule->ifname[0]) {
2246
rule->kif = pfi_kkif_attach(kif, rule->ifname);
2247
kif = NULL;
2248
pfi_kkif_ref(rule->kif);
2249
} else
2250
rule->kif = NULL;
2251
2252
if (rule->rcv_ifname[0]) {
2253
rule->rcv_kif = pfi_kkif_attach(rcv_kif, rule->rcv_ifname);
2254
rcv_kif = NULL;
2255
pfi_kkif_ref(rule->rcv_kif);
2256
} else
2257
rule->rcv_kif = NULL;
2258
2259
if (rule->rtableid > 0 && rule->rtableid >= rt_numfibs)
2260
ERROUT(EBUSY);
2261
#ifdef ALTQ
2262
/* set queue IDs */
2263
if (rule->qname[0] != 0) {
2264
if ((rule->qid = pf_qname2qid(rule->qname, true)) == 0)
2265
ERROUT(EBUSY);
2266
else if (rule->pqname[0] != 0) {
2267
if ((rule->pqid =
2268
pf_qname2qid(rule->pqname, true)) == 0)
2269
ERROUT(EBUSY);
2270
} else
2271
rule->pqid = rule->qid;
2272
}
2273
#endif
2274
if (rule->tagname[0])
2275
if ((rule->tag = pf_tagname2tag(rule->tagname)) == 0)
2276
ERROUT(EBUSY);
2277
if (rule->match_tagname[0])
2278
if ((rule->match_tag =
2279
pf_tagname2tag(rule->match_tagname)) == 0)
2280
ERROUT(EBUSY);
2281
if (rule->rt && !rule->direction)
2282
ERROUT(EINVAL);
2283
if (!rule->log)
2284
rule->logif = 0;
2285
if (! pf_init_threshold(&rule->pktrate, rule->pktrate.limit,
2286
rule->pktrate.seconds))
2287
ERROUT(ENOMEM);
2288
if (pf_addr_setup(ruleset, &rule->src.addr, rule->af))
2289
ERROUT(ENOMEM);
2290
if (pf_addr_setup(ruleset, &rule->dst.addr, rule->af))
2291
ERROUT(ENOMEM);
2292
if (pf_kanchor_setup(rule, ruleset, anchor_call))
2293
ERROUT(EINVAL);
2294
if (rule->scrub_flags & PFSTATE_SETPRIO &&
2295
(rule->set_prio[0] > PF_PRIO_MAX ||
2296
rule->set_prio[1] > PF_PRIO_MAX))
2297
ERROUT(EINVAL);
2298
for (int i = 0; i < 3; i++) {
2299
TAILQ_FOREACH(pa, &V_pf_pabuf[i], entries)
2300
if (pa->addr.type == PF_ADDR_TABLE) {
2301
pa->addr.p.tbl = pfr_attach_table(ruleset,
2302
pa->addr.v.tblname);
2303
if (pa->addr.p.tbl == NULL)
2304
ERROUT(ENOMEM);
2305
}
2306
}
2307
2308
rule->overload_tbl = NULL;
2309
if (rule->overload_tblname[0]) {
2310
if ((rule->overload_tbl = pfr_attach_table(ruleset,
2311
rule->overload_tblname)) == NULL)
2312
ERROUT(EINVAL);
2313
else
2314
rule->overload_tbl->pfrkt_flags |=
2315
PFR_TFLAG_ACTIVE;
2316
}
2317
2318
pf_mv_kpool(&V_pf_pabuf[0], &rule->nat.list);
2319
2320
/*
2321
* Old version of pfctl provide route redirection pools in single
2322
* common redirection pool rdr. New versions use rdr only for
2323
* rdr-to rules.
2324
*/
2325
if (rule->rt > PF_NOPFROUTE && TAILQ_EMPTY(&V_pf_pabuf[2])) {
2326
pf_mv_kpool(&V_pf_pabuf[1], &rule->route.list);
2327
} else {
2328
pf_mv_kpool(&V_pf_pabuf[1], &rule->rdr.list);
2329
pf_mv_kpool(&V_pf_pabuf[2], &rule->route.list);
2330
}
2331
2332
if (((rule->action == PF_NAT) || (rule->action == PF_RDR) ||
2333
(rule->action == PF_BINAT)) && rule->anchor == NULL &&
2334
TAILQ_FIRST(&rule->rdr.list) == NULL) {
2335
ERROUT(EINVAL);
2336
}
2337
2338
if (rule->rt > PF_NOPFROUTE && (TAILQ_FIRST(&rule->route.list) == NULL)) {
2339
ERROUT(EINVAL);
2340
}
2341
2342
if (rule->action == PF_PASS && (rule->rdr.opts & PF_POOL_STICKYADDR ||
2343
rule->nat.opts & PF_POOL_STICKYADDR) && !rule->keep_state) {
2344
ERROUT(EINVAL);
2345
}
2346
2347
MPASS(error == 0);
2348
2349
rule->nat.cur = TAILQ_FIRST(&rule->nat.list);
2350
rule->rdr.cur = TAILQ_FIRST(&rule->rdr.list);
2351
rule->route.cur = TAILQ_FIRST(&rule->route.list);
2352
rule->route.ipv6_nexthop_af = AF_INET6;
2353
TAILQ_INSERT_TAIL(ruleset->rules[rs_num].inactive.ptr,
2354
rule, entries);
2355
ruleset->rules[rs_num].inactive.rcount++;
2356
2357
PF_RULES_WUNLOCK();
2358
pf_hash_rule(rule);
2359
if (RB_INSERT(pf_krule_global, ruleset->rules[rs_num].inactive.tree, rule) != NULL) {
2360
PF_RULES_WLOCK();
2361
TAILQ_REMOVE(ruleset->rules[rs_num].inactive.ptr, rule, entries);
2362
ruleset->rules[rs_num].inactive.rcount--;
2363
pf_free_rule(rule);
2364
rule = NULL;
2365
ERROUT(EEXIST);
2366
}
2367
PF_CONFIG_UNLOCK();
2368
2369
return (0);
2370
2371
#undef ERROUT
2372
#undef ERROUT_UNLOCKED
2373
errout:
2374
PF_RULES_WUNLOCK();
2375
PF_CONFIG_UNLOCK();
2376
errout_unlocked:
2377
pf_kkif_free(rcv_kif);
2378
pf_kkif_free(kif);
2379
pf_krule_free(rule);
2380
return (error);
2381
}
2382
2383
static bool
2384
pf_label_match(const struct pf_krule *rule, const char *label)
2385
{
2386
int i = 0;
2387
2388
while (*rule->label[i]) {
2389
if (strcmp(rule->label[i], label) == 0)
2390
return (true);
2391
i++;
2392
}
2393
2394
return (false);
2395
}
2396
2397
static unsigned int
2398
pf_kill_matching_state(struct pf_state_key_cmp *key, int dir)
2399
{
2400
struct pf_kstate *s;
2401
int more = 0;
2402
2403
s = pf_find_state_all(key, dir, &more);
2404
if (s == NULL)
2405
return (0);
2406
2407
if (more) {
2408
PF_STATE_UNLOCK(s);
2409
return (0);
2410
}
2411
2412
pf_remove_state(s);
2413
return (1);
2414
}
2415
2416
static int
2417
pf_killstates_row(struct pf_kstate_kill *psk, struct pf_idhash *ih)
2418
{
2419
struct pf_kstate *s;
2420
struct pf_state_key *sk;
2421
struct pf_addr *srcaddr, *dstaddr;
2422
struct pf_state_key_cmp match_key;
2423
int idx, killed = 0;
2424
unsigned int dir;
2425
u_int16_t srcport, dstport;
2426
struct pfi_kkif *kif;
2427
2428
relock_DIOCKILLSTATES:
2429
PF_HASHROW_LOCK(ih);
2430
LIST_FOREACH(s, &ih->states, entry) {
2431
/* For floating states look at the original kif. */
2432
kif = s->kif == V_pfi_all ? s->orig_kif : s->kif;
2433
2434
sk = s->key[psk->psk_nat ? PF_SK_STACK : PF_SK_WIRE];
2435
if (s->direction == PF_OUT) {
2436
srcaddr = &sk->addr[1];
2437
dstaddr = &sk->addr[0];
2438
srcport = sk->port[1];
2439
dstport = sk->port[0];
2440
} else {
2441
srcaddr = &sk->addr[0];
2442
dstaddr = &sk->addr[1];
2443
srcport = sk->port[0];
2444
dstport = sk->port[1];
2445
}
2446
2447
if (psk->psk_af && sk->af != psk->psk_af)
2448
continue;
2449
2450
if (psk->psk_proto && psk->psk_proto != sk->proto)
2451
continue;
2452
2453
if (! pf_match_addr(psk->psk_src.neg,
2454
&psk->psk_src.addr.v.a.addr,
2455
&psk->psk_src.addr.v.a.mask, srcaddr, sk->af))
2456
continue;
2457
2458
if (! pf_match_addr(psk->psk_dst.neg,
2459
&psk->psk_dst.addr.v.a.addr,
2460
&psk->psk_dst.addr.v.a.mask, dstaddr, sk->af))
2461
continue;
2462
2463
if (! pf_match_addr(psk->psk_rt_addr.neg,
2464
&psk->psk_rt_addr.addr.v.a.addr,
2465
&psk->psk_rt_addr.addr.v.a.mask,
2466
&s->act.rt_addr, sk->af))
2467
continue;
2468
2469
if (psk->psk_src.port_op != 0 &&
2470
! pf_match_port(psk->psk_src.port_op,
2471
psk->psk_src.port[0], psk->psk_src.port[1], srcport))
2472
continue;
2473
2474
if (psk->psk_dst.port_op != 0 &&
2475
! pf_match_port(psk->psk_dst.port_op,
2476
psk->psk_dst.port[0], psk->psk_dst.port[1], dstport))
2477
continue;
2478
2479
if (psk->psk_label[0] &&
2480
! pf_label_match(s->rule, psk->psk_label))
2481
continue;
2482
2483
if (psk->psk_ifname[0] && strcmp(psk->psk_ifname,
2484
kif->pfik_name))
2485
continue;
2486
2487
if (psk->psk_kill_match) {
2488
/* Create the key to find matching states, with lock
2489
* held. */
2490
2491
bzero(&match_key, sizeof(match_key));
2492
2493
if (s->direction == PF_OUT) {
2494
dir = PF_IN;
2495
idx = psk->psk_nat ? PF_SK_WIRE : PF_SK_STACK;
2496
} else {
2497
dir = PF_OUT;
2498
idx = psk->psk_nat ? PF_SK_STACK : PF_SK_WIRE;
2499
}
2500
2501
match_key.af = s->key[idx]->af;
2502
match_key.proto = s->key[idx]->proto;
2503
pf_addrcpy(&match_key.addr[0],
2504
&s->key[idx]->addr[1], match_key.af);
2505
match_key.port[0] = s->key[idx]->port[1];
2506
pf_addrcpy(&match_key.addr[1],
2507
&s->key[idx]->addr[0], match_key.af);
2508
match_key.port[1] = s->key[idx]->port[0];
2509
}
2510
2511
pf_remove_state(s);
2512
killed++;
2513
2514
if (psk->psk_kill_match)
2515
killed += pf_kill_matching_state(&match_key, dir);
2516
2517
goto relock_DIOCKILLSTATES;
2518
}
2519
PF_HASHROW_UNLOCK(ih);
2520
2521
return (killed);
2522
}
2523
2524
void
2525
unhandled_af(int af)
2526
{
2527
panic("unhandled af %d", af);
2528
}
2529
2530
int
2531
pf_start(void)
2532
{
2533
int error = 0;
2534
2535
sx_xlock(&V_pf_ioctl_lock);
2536
if (V_pf_status.running)
2537
error = EEXIST;
2538
else {
2539
hook_pf();
2540
if (! TAILQ_EMPTY(V_pf_keth->active.rules))
2541
hook_pf_eth();
2542
V_pf_status.running = 1;
2543
V_pf_status.since = time_uptime;
2544
new_unrhdr64(&V_pf_stateid, time_second);
2545
2546
DPFPRINTF(PF_DEBUG_MISC, "pf: started");
2547
}
2548
sx_xunlock(&V_pf_ioctl_lock);
2549
2550
return (error);
2551
}
2552
2553
int
2554
pf_stop(void)
2555
{
2556
int error = 0;
2557
2558
sx_xlock(&V_pf_ioctl_lock);
2559
if (!V_pf_status.running)
2560
error = ENOENT;
2561
else {
2562
V_pf_status.running = 0;
2563
dehook_pf();
2564
dehook_pf_eth();
2565
V_pf_status.since = time_uptime;
2566
DPFPRINTF(PF_DEBUG_MISC, "pf: stopped");
2567
}
2568
sx_xunlock(&V_pf_ioctl_lock);
2569
2570
return (error);
2571
}
2572
2573
void
2574
pf_ioctl_clear_status(void)
2575
{
2576
PF_RULES_WLOCK();
2577
for (int i = 0; i < PFRES_MAX; i++)
2578
counter_u64_zero(V_pf_status.counters[i]);
2579
for (int i = 0; i < FCNT_MAX; i++)
2580
pf_counter_u64_zero(&V_pf_status.fcounters[i]);
2581
for (int i = 0; i < SCNT_MAX; i++)
2582
counter_u64_zero(V_pf_status.scounters[i]);
2583
for (int i = 0; i < NCNT_MAX; i++)
2584
counter_u64_zero(V_pf_status.ncounters[i]);
2585
for (int i = 0; i < KLCNT_MAX; i++)
2586
counter_u64_zero(V_pf_status.lcounters[i]);
2587
V_pf_status.since = time_uptime;
2588
if (*V_pf_status.ifname)
2589
pfi_update_status(V_pf_status.ifname, NULL);
2590
PF_RULES_WUNLOCK();
2591
}
2592
2593
int
2594
pf_ioctl_set_timeout(int timeout, int seconds, int *prev_seconds)
2595
{
2596
uint32_t old;
2597
2598
if (timeout < 0 || timeout >= PFTM_MAX ||
2599
seconds < 0)
2600
return (EINVAL);
2601
2602
PF_RULES_WLOCK();
2603
old = V_pf_default_rule.timeout[timeout];
2604
if (timeout == PFTM_INTERVAL && seconds == 0)
2605
seconds = 1;
2606
V_pf_default_rule.timeout[timeout] = seconds;
2607
if (timeout == PFTM_INTERVAL && seconds < old)
2608
wakeup(pf_purge_thread);
2609
2610
if (prev_seconds != NULL)
2611
*prev_seconds = old;
2612
2613
PF_RULES_WUNLOCK();
2614
2615
return (0);
2616
}
2617
2618
int
2619
pf_ioctl_get_timeout(int timeout, int *seconds)
2620
{
2621
PF_RULES_RLOCK_TRACKER;
2622
2623
if (timeout < 0 || timeout >= PFTM_MAX)
2624
return (EINVAL);
2625
2626
PF_RULES_RLOCK();
2627
*seconds = V_pf_default_rule.timeout[timeout];
2628
PF_RULES_RUNLOCK();
2629
2630
return (0);
2631
}
2632
2633
int
2634
pf_ioctl_set_limit(int index, unsigned int limit, unsigned int *old_limit)
2635
{
2636
2637
PF_RULES_WLOCK();
2638
if (index < 0 || index >= PF_LIMIT_MAX ||
2639
V_pf_limits[index].zone == NULL) {
2640
PF_RULES_WUNLOCK();
2641
return (EINVAL);
2642
}
2643
uma_zone_set_max(V_pf_limits[index].zone,
2644
limit == 0 ? INT_MAX : limit);
2645
if (old_limit != NULL)
2646
*old_limit = V_pf_limits[index].limit;
2647
V_pf_limits[index].limit = limit;
2648
PF_RULES_WUNLOCK();
2649
2650
return (0);
2651
}
2652
2653
int
2654
pf_ioctl_get_limit(int index, unsigned int *limit)
2655
{
2656
PF_RULES_RLOCK_TRACKER;
2657
2658
if (index < 0 || index >= PF_LIMIT_MAX)
2659
return (EINVAL);
2660
2661
PF_RULES_RLOCK();
2662
*limit = V_pf_limits[index].limit;
2663
PF_RULES_RUNLOCK();
2664
2665
return (0);
2666
}
2667
2668
int
2669
pf_ioctl_begin_addrs(uint32_t *ticket)
2670
{
2671
PF_RULES_WLOCK();
2672
pf_empty_kpool(&V_pf_pabuf[0]);
2673
pf_empty_kpool(&V_pf_pabuf[1]);
2674
pf_empty_kpool(&V_pf_pabuf[2]);
2675
*ticket = ++V_ticket_pabuf;
2676
PF_RULES_WUNLOCK();
2677
2678
return (0);
2679
}
2680
2681
int
2682
pf_ioctl_add_addr(struct pf_nl_pooladdr *pp)
2683
{
2684
struct pf_kpooladdr *pa = NULL;
2685
struct pfi_kkif *kif = NULL;
2686
int error;
2687
2688
if (pp->which != PF_RDR && pp->which != PF_NAT &&
2689
pp->which != PF_RT)
2690
return (EINVAL);
2691
2692
switch (pp->af) {
2693
#ifdef INET
2694
case AF_INET:
2695
/* FALLTHROUGH */
2696
#endif /* INET */
2697
#ifdef INET6
2698
case AF_INET6:
2699
/* FALLTHROUGH */
2700
#endif /* INET6 */
2701
case AF_UNSPEC:
2702
break;
2703
default:
2704
return (EAFNOSUPPORT);
2705
}
2706
2707
if (pp->addr.addr.type != PF_ADDR_ADDRMASK &&
2708
pp->addr.addr.type != PF_ADDR_DYNIFTL &&
2709
pp->addr.addr.type != PF_ADDR_TABLE)
2710
return (EINVAL);
2711
2712
if (pp->addr.addr.p.dyn != NULL)
2713
return (EINVAL);
2714
2715
pa = malloc(sizeof(*pa), M_PFRULE, M_WAITOK);
2716
error = pf_pooladdr_to_kpooladdr(&pp->addr, pa);
2717
if (error != 0)
2718
goto out;
2719
if (pa->ifname[0])
2720
kif = pf_kkif_create(M_WAITOK);
2721
PF_RULES_WLOCK();
2722
if (pp->ticket != V_ticket_pabuf) {
2723
PF_RULES_WUNLOCK();
2724
if (pa->ifname[0])
2725
pf_kkif_free(kif);
2726
error = EBUSY;
2727
goto out;
2728
}
2729
if (pa->ifname[0]) {
2730
pa->kif = pfi_kkif_attach(kif, pa->ifname);
2731
kif = NULL;
2732
pfi_kkif_ref(pa->kif);
2733
} else
2734
pa->kif = NULL;
2735
if (pa->addr.type == PF_ADDR_DYNIFTL && ((error =
2736
pfi_dynaddr_setup(&pa->addr, pp->af)) != 0)) {
2737
if (pa->ifname[0])
2738
pfi_kkif_unref(pa->kif);
2739
PF_RULES_WUNLOCK();
2740
goto out;
2741
}
2742
pa->af = pp->af;
2743
switch (pp->which) {
2744
case PF_NAT:
2745
TAILQ_INSERT_TAIL(&V_pf_pabuf[0], pa, entries);
2746
break;
2747
case PF_RDR:
2748
TAILQ_INSERT_TAIL(&V_pf_pabuf[1], pa, entries);
2749
break;
2750
case PF_RT:
2751
TAILQ_INSERT_TAIL(&V_pf_pabuf[2], pa, entries);
2752
break;
2753
}
2754
PF_RULES_WUNLOCK();
2755
2756
return (0);
2757
2758
out:
2759
free(pa, M_PFRULE);
2760
return (error);
2761
}
2762
2763
int
2764
pf_ioctl_get_addrs(struct pf_nl_pooladdr *pp)
2765
{
2766
struct pf_kpool *pool;
2767
struct pf_kpooladdr *pa;
2768
2769
PF_RULES_RLOCK_TRACKER;
2770
2771
if (pp->which != PF_RDR && pp->which != PF_NAT &&
2772
pp->which != PF_RT)
2773
return (EINVAL);
2774
2775
pp->anchor[sizeof(pp->anchor) - 1] = 0;
2776
pp->nr = 0;
2777
2778
PF_RULES_RLOCK();
2779
pool = pf_get_kpool(pp->anchor, pp->ticket, pp->r_action,
2780
pp->r_num, 0, 1, 0, pp->which);
2781
if (pool == NULL) {
2782
PF_RULES_RUNLOCK();
2783
return (EBUSY);
2784
}
2785
TAILQ_FOREACH(pa, &pool->list, entries)
2786
pp->nr++;
2787
PF_RULES_RUNLOCK();
2788
2789
return (0);
2790
}
2791
2792
int
2793
pf_ioctl_get_addr(struct pf_nl_pooladdr *pp)
2794
{
2795
struct pf_kpool *pool;
2796
struct pf_kpooladdr *pa;
2797
u_int32_t nr = 0;
2798
2799
if (pp->which != PF_RDR && pp->which != PF_NAT &&
2800
pp->which != PF_RT)
2801
return (EINVAL);
2802
2803
PF_RULES_RLOCK_TRACKER;
2804
2805
pp->anchor[sizeof(pp->anchor) - 1] = '\0';
2806
2807
PF_RULES_RLOCK();
2808
pool = pf_get_kpool(pp->anchor, pp->ticket, pp->r_action,
2809
pp->r_num, 0, 1, 1, pp->which);
2810
if (pool == NULL) {
2811
PF_RULES_RUNLOCK();
2812
return (EBUSY);
2813
}
2814
pa = TAILQ_FIRST(&pool->list);
2815
while ((pa != NULL) && (nr < pp->nr)) {
2816
pa = TAILQ_NEXT(pa, entries);
2817
nr++;
2818
}
2819
if (pa == NULL) {
2820
PF_RULES_RUNLOCK();
2821
return (EBUSY);
2822
}
2823
pf_kpooladdr_to_pooladdr(pa, &pp->addr);
2824
pp->af = pa->af;
2825
pf_addr_copyout(&pp->addr.addr);
2826
PF_RULES_RUNLOCK();
2827
2828
return (0);
2829
}
2830
2831
int
2832
pf_ioctl_get_rulesets(struct pfioc_ruleset *pr)
2833
{
2834
struct pf_kruleset *ruleset;
2835
struct pf_kanchor *anchor;
2836
2837
PF_RULES_RLOCK_TRACKER;
2838
2839
pr->path[sizeof(pr->path) - 1] = '\0';
2840
2841
PF_RULES_RLOCK();
2842
if ((ruleset = pf_find_kruleset(pr->path)) == NULL) {
2843
PF_RULES_RUNLOCK();
2844
return (ENOENT);
2845
}
2846
pr->nr = 0;
2847
if (ruleset == &pf_main_ruleset) {
2848
/* XXX kludge for pf_main_ruleset */
2849
RB_FOREACH(anchor, pf_kanchor_global, &V_pf_anchors)
2850
if (anchor->parent == NULL)
2851
pr->nr++;
2852
} else {
2853
RB_FOREACH(anchor, pf_kanchor_node,
2854
&ruleset->anchor->children)
2855
pr->nr++;
2856
}
2857
PF_RULES_RUNLOCK();
2858
2859
return (0);
2860
}
2861
2862
int
2863
pf_ioctl_get_ruleset(struct pfioc_ruleset *pr)
2864
{
2865
struct pf_kruleset *ruleset;
2866
struct pf_kanchor *anchor;
2867
u_int32_t nr = 0;
2868
int error = 0;
2869
2870
PF_RULES_RLOCK_TRACKER;
2871
2872
PF_RULES_RLOCK();
2873
if ((ruleset = pf_find_kruleset(pr->path)) == NULL) {
2874
PF_RULES_RUNLOCK();
2875
return (ENOENT);
2876
}
2877
2878
pr->name[0] = '\0';
2879
if (ruleset == &pf_main_ruleset) {
2880
/* XXX kludge for pf_main_ruleset */
2881
RB_FOREACH(anchor, pf_kanchor_global, &V_pf_anchors)
2882
if (anchor->parent == NULL && nr++ == pr->nr) {
2883
strlcpy(pr->name, anchor->name,
2884
sizeof(pr->name));
2885
break;
2886
}
2887
} else {
2888
RB_FOREACH(anchor, pf_kanchor_node,
2889
&ruleset->anchor->children)
2890
if (nr++ == pr->nr) {
2891
strlcpy(pr->name, anchor->name,
2892
sizeof(pr->name));
2893
break;
2894
}
2895
}
2896
if (!pr->name[0])
2897
error = EBUSY;
2898
PF_RULES_RUNLOCK();
2899
2900
return (error);
2901
}
2902
2903
int
2904
pf_ioctl_natlook(struct pfioc_natlook *pnl)
2905
{
2906
struct pf_state_key *sk;
2907
struct pf_kstate *state;
2908
struct pf_state_key_cmp key;
2909
int m = 0, direction = pnl->direction;
2910
int sidx, didx;
2911
2912
/* NATLOOK src and dst are reversed, so reverse sidx/didx */
2913
sidx = (direction == PF_IN) ? 1 : 0;
2914
didx = (direction == PF_IN) ? 0 : 1;
2915
2916
if (!pnl->proto ||
2917
PF_AZERO(&pnl->saddr, pnl->af) ||
2918
PF_AZERO(&pnl->daddr, pnl->af) ||
2919
((pnl->proto == IPPROTO_TCP ||
2920
pnl->proto == IPPROTO_UDP) &&
2921
(!pnl->dport || !pnl->sport)))
2922
return (EINVAL);
2923
2924
switch (pnl->direction) {
2925
case PF_IN:
2926
case PF_OUT:
2927
case PF_INOUT:
2928
break;
2929
default:
2930
return (EINVAL);
2931
}
2932
2933
switch (pnl->af) {
2934
#ifdef INET
2935
case AF_INET:
2936
break;
2937
#endif /* INET */
2938
#ifdef INET6
2939
case AF_INET6:
2940
break;
2941
#endif /* INET6 */
2942
default:
2943
return (EAFNOSUPPORT);
2944
}
2945
2946
bzero(&key, sizeof(key));
2947
key.af = pnl->af;
2948
key.proto = pnl->proto;
2949
pf_addrcpy(&key.addr[sidx], &pnl->saddr, pnl->af);
2950
key.port[sidx] = pnl->sport;
2951
pf_addrcpy(&key.addr[didx], &pnl->daddr, pnl->af);
2952
key.port[didx] = pnl->dport;
2953
2954
state = pf_find_state_all(&key, direction, &m);
2955
if (state == NULL)
2956
return (ENOENT);
2957
2958
if (m > 1) {
2959
PF_STATE_UNLOCK(state);
2960
return (E2BIG); /* more than one state */
2961
}
2962
2963
sk = state->key[sidx];
2964
pf_addrcpy(&pnl->rsaddr,
2965
&sk->addr[sidx], sk->af);
2966
pnl->rsport = sk->port[sidx];
2967
pf_addrcpy(&pnl->rdaddr,
2968
&sk->addr[didx], sk->af);
2969
pnl->rdport = sk->port[didx];
2970
PF_STATE_UNLOCK(state);
2971
2972
return (0);
2973
}
2974
2975
static int
2976
pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td)
2977
{
2978
int error = 0;
2979
PF_RULES_RLOCK_TRACKER;
2980
2981
#define ERROUT_IOCTL(target, x) \
2982
do { \
2983
error = (x); \
2984
SDT_PROBE3(pf, ioctl, ioctl, error, cmd, error, __LINE__); \
2985
goto target; \
2986
} while (0)
2987
2988
2989
/* XXX keep in sync with switch() below */
2990
if (securelevel_gt(td->td_ucred, 2))
2991
switch (cmd) {
2992
case DIOCGETRULES:
2993
case DIOCGETRULENV:
2994
case DIOCGETADDRS:
2995
case DIOCGETADDR:
2996
case DIOCGETSTATE:
2997
case DIOCGETSTATENV:
2998
case DIOCSETSTATUSIF:
2999
case DIOCGETSTATUSNV:
3000
case DIOCCLRSTATUS:
3001
case DIOCNATLOOK:
3002
case DIOCSETDEBUG:
3003
#ifdef COMPAT_FREEBSD14
3004
case DIOCGETSTATES:
3005
case DIOCGETSTATESV2:
3006
#endif
3007
case DIOCGETTIMEOUT:
3008
case DIOCCLRRULECTRS:
3009
case DIOCGETLIMIT:
3010
case DIOCGETALTQSV0:
3011
case DIOCGETALTQSV1:
3012
case DIOCGETALTQV0:
3013
case DIOCGETALTQV1:
3014
case DIOCGETQSTATSV0:
3015
case DIOCGETQSTATSV1:
3016
case DIOCGETRULESETS:
3017
case DIOCGETRULESET:
3018
case DIOCRGETTABLES:
3019
case DIOCRGETTSTATS:
3020
case DIOCRCLRTSTATS:
3021
case DIOCRCLRADDRS:
3022
case DIOCRADDADDRS:
3023
case DIOCRDELADDRS:
3024
case DIOCRSETADDRS:
3025
case DIOCRGETADDRS:
3026
case DIOCRGETASTATS:
3027
case DIOCRCLRASTATS:
3028
case DIOCRTSTADDRS:
3029
case DIOCOSFPGET:
3030
case DIOCGETSRCNODES:
3031
case DIOCCLRSRCNODES:
3032
case DIOCGETSYNCOOKIES:
3033
case DIOCIGETIFACES:
3034
case DIOCGIFSPEEDV0:
3035
case DIOCGIFSPEEDV1:
3036
case DIOCSETIFFLAG:
3037
case DIOCCLRIFFLAG:
3038
case DIOCGETETHRULES:
3039
case DIOCGETETHRULE:
3040
case DIOCGETETHRULESETS:
3041
case DIOCGETETHRULESET:
3042
break;
3043
case DIOCRCLRTABLES:
3044
case DIOCRADDTABLES:
3045
case DIOCRDELTABLES:
3046
case DIOCRSETTFLAGS:
3047
if (((struct pfioc_table *)addr)->pfrio_flags &
3048
PFR_FLAG_DUMMY)
3049
break; /* dummy operation ok */
3050
return (EPERM);
3051
default:
3052
return (EPERM);
3053
}
3054
3055
if (!(flags & FWRITE))
3056
switch (cmd) {
3057
case DIOCGETRULES:
3058
case DIOCGETADDRS:
3059
case DIOCGETADDR:
3060
case DIOCGETSTATE:
3061
case DIOCGETSTATENV:
3062
case DIOCGETSTATUSNV:
3063
#ifdef COMPAT_FREEBSD14
3064
case DIOCGETSTATES:
3065
case DIOCGETSTATESV2:
3066
#endif
3067
case DIOCGETTIMEOUT:
3068
case DIOCGETLIMIT:
3069
case DIOCGETALTQSV0:
3070
case DIOCGETALTQSV1:
3071
case DIOCGETALTQV0:
3072
case DIOCGETALTQV1:
3073
case DIOCGETQSTATSV0:
3074
case DIOCGETQSTATSV1:
3075
case DIOCGETRULESETS:
3076
case DIOCGETRULESET:
3077
case DIOCNATLOOK:
3078
case DIOCRGETTABLES:
3079
case DIOCRGETTSTATS:
3080
case DIOCRGETADDRS:
3081
case DIOCRGETASTATS:
3082
case DIOCRTSTADDRS:
3083
case DIOCOSFPGET:
3084
case DIOCGETSRCNODES:
3085
case DIOCGETSYNCOOKIES:
3086
case DIOCIGETIFACES:
3087
case DIOCGIFSPEEDV1:
3088
case DIOCGIFSPEEDV0:
3089
case DIOCGETRULENV:
3090
case DIOCGETETHRULES:
3091
case DIOCGETETHRULE:
3092
case DIOCGETETHRULESETS:
3093
case DIOCGETETHRULESET:
3094
break;
3095
case DIOCRCLRTABLES:
3096
case DIOCRADDTABLES:
3097
case DIOCRDELTABLES:
3098
case DIOCRCLRTSTATS:
3099
case DIOCRCLRADDRS:
3100
case DIOCRADDADDRS:
3101
case DIOCRDELADDRS:
3102
case DIOCRSETADDRS:
3103
case DIOCRSETTFLAGS:
3104
if (((struct pfioc_table *)addr)->pfrio_flags &
3105
PFR_FLAG_DUMMY) {
3106
flags |= FWRITE; /* need write lock for dummy */
3107
break; /* dummy operation ok */
3108
}
3109
return (EACCES);
3110
default:
3111
return (EACCES);
3112
}
3113
3114
CURVNET_SET(TD_TO_VNET(td));
3115
3116
switch (cmd) {
3117
#ifdef COMPAT_FREEBSD14
3118
case DIOCSTART:
3119
error = pf_start();
3120
break;
3121
3122
case DIOCSTOP:
3123
error = pf_stop();
3124
break;
3125
#endif
3126
3127
case DIOCGETETHRULES: {
3128
struct pfioc_nv *nv = (struct pfioc_nv *)addr;
3129
nvlist_t *nvl;
3130
void *packed;
3131
struct pf_keth_rule *tail;
3132
struct pf_keth_ruleset *rs;
3133
u_int32_t ticket, nr;
3134
const char *anchor = "";
3135
3136
nvl = NULL;
3137
packed = NULL;
3138
3139
#define ERROUT(x) ERROUT_IOCTL(DIOCGETETHRULES_error, x)
3140
3141
if (nv->len > pf_ioctl_maxcount)
3142
ERROUT(ENOMEM);
3143
3144
/* Copy the request in */
3145
packed = malloc(nv->len, M_NVLIST, M_WAITOK);
3146
error = copyin(nv->data, packed, nv->len);
3147
if (error)
3148
ERROUT(error);
3149
3150
nvl = nvlist_unpack(packed, nv->len, 0);
3151
if (nvl == NULL)
3152
ERROUT(EBADMSG);
3153
3154
if (! nvlist_exists_string(nvl, "anchor"))
3155
ERROUT(EBADMSG);
3156
3157
anchor = nvlist_get_string(nvl, "anchor");
3158
3159
rs = pf_find_keth_ruleset(anchor);
3160
3161
nvlist_destroy(nvl);
3162
nvl = NULL;
3163
free(packed, M_NVLIST);
3164
packed = NULL;
3165
3166
if (rs == NULL)
3167
ERROUT(ENOENT);
3168
3169
/* Reply */
3170
nvl = nvlist_create(0);
3171
if (nvl == NULL)
3172
ERROUT(ENOMEM);
3173
3174
PF_RULES_RLOCK();
3175
3176
ticket = rs->active.ticket;
3177
tail = TAILQ_LAST(rs->active.rules, pf_keth_ruleq);
3178
if (tail)
3179
nr = tail->nr + 1;
3180
else
3181
nr = 0;
3182
3183
PF_RULES_RUNLOCK();
3184
3185
nvlist_add_number(nvl, "ticket", ticket);
3186
nvlist_add_number(nvl, "nr", nr);
3187
3188
packed = nvlist_pack(nvl, &nv->len);
3189
if (packed == NULL)
3190
ERROUT(ENOMEM);
3191
3192
if (nv->size == 0)
3193
ERROUT(0);
3194
else if (nv->size < nv->len)
3195
ERROUT(ENOSPC);
3196
3197
error = copyout(packed, nv->data, nv->len);
3198
3199
#undef ERROUT
3200
DIOCGETETHRULES_error:
3201
free(packed, M_NVLIST);
3202
nvlist_destroy(nvl);
3203
break;
3204
}
3205
3206
case DIOCGETETHRULE: {
3207
struct epoch_tracker et;
3208
struct pfioc_nv *nv = (struct pfioc_nv *)addr;
3209
nvlist_t *nvl = NULL;
3210
void *nvlpacked = NULL;
3211
struct pf_keth_rule *rule = NULL;
3212
struct pf_keth_ruleset *rs;
3213
u_int32_t ticket, nr;
3214
bool clear = false;
3215
const char *anchor;
3216
3217
#define ERROUT(x) ERROUT_IOCTL(DIOCGETETHRULE_error, x)
3218
3219
if (nv->len > pf_ioctl_maxcount)
3220
ERROUT(ENOMEM);
3221
3222
nvlpacked = malloc(nv->len, M_NVLIST, M_WAITOK);
3223
error = copyin(nv->data, nvlpacked, nv->len);
3224
if (error)
3225
ERROUT(error);
3226
3227
nvl = nvlist_unpack(nvlpacked, nv->len, 0);
3228
if (nvl == NULL)
3229
ERROUT(EBADMSG);
3230
if (! nvlist_exists_number(nvl, "ticket"))
3231
ERROUT(EBADMSG);
3232
ticket = nvlist_get_number(nvl, "ticket");
3233
if (! nvlist_exists_string(nvl, "anchor"))
3234
ERROUT(EBADMSG);
3235
anchor = nvlist_get_string(nvl, "anchor");
3236
3237
if (nvlist_exists_bool(nvl, "clear"))
3238
clear = nvlist_get_bool(nvl, "clear");
3239
3240
if (clear && !(flags & FWRITE))
3241
ERROUT(EACCES);
3242
3243
if (! nvlist_exists_number(nvl, "nr"))
3244
ERROUT(EBADMSG);
3245
nr = nvlist_get_number(nvl, "nr");
3246
3247
PF_RULES_RLOCK();
3248
rs = pf_find_keth_ruleset(anchor);
3249
if (rs == NULL) {
3250
PF_RULES_RUNLOCK();
3251
ERROUT(ENOENT);
3252
}
3253
if (ticket != rs->active.ticket) {
3254
PF_RULES_RUNLOCK();
3255
ERROUT(EBUSY);
3256
}
3257
3258
nvlist_destroy(nvl);
3259
nvl = NULL;
3260
free(nvlpacked, M_NVLIST);
3261
nvlpacked = NULL;
3262
3263
rule = TAILQ_FIRST(rs->active.rules);
3264
while ((rule != NULL) && (rule->nr != nr))
3265
rule = TAILQ_NEXT(rule, entries);
3266
if (rule == NULL) {
3267
PF_RULES_RUNLOCK();
3268
ERROUT(ENOENT);
3269
}
3270
/* Make sure rule can't go away. */
3271
NET_EPOCH_ENTER(et);
3272
PF_RULES_RUNLOCK();
3273
nvl = pf_keth_rule_to_nveth_rule(rule);
3274
if (pf_keth_anchor_nvcopyout(rs, rule, nvl)) {
3275
NET_EPOCH_EXIT(et);
3276
ERROUT(EBUSY);
3277
}
3278
NET_EPOCH_EXIT(et);
3279
if (nvl == NULL)
3280
ERROUT(ENOMEM);
3281
3282
nvlpacked = nvlist_pack(nvl, &nv->len);
3283
if (nvlpacked == NULL)
3284
ERROUT(ENOMEM);
3285
3286
if (nv->size == 0)
3287
ERROUT(0);
3288
else if (nv->size < nv->len)
3289
ERROUT(ENOSPC);
3290
3291
error = copyout(nvlpacked, nv->data, nv->len);
3292
if (error == 0 && clear) {
3293
counter_u64_zero(rule->evaluations);
3294
for (int i = 0; i < 2; i++) {
3295
counter_u64_zero(rule->packets[i]);
3296
counter_u64_zero(rule->bytes[i]);
3297
}
3298
}
3299
3300
#undef ERROUT
3301
DIOCGETETHRULE_error:
3302
free(nvlpacked, M_NVLIST);
3303
nvlist_destroy(nvl);
3304
break;
3305
}
3306
3307
case DIOCADDETHRULE: {
3308
struct pfioc_nv *nv = (struct pfioc_nv *)addr;
3309
nvlist_t *nvl = NULL;
3310
void *nvlpacked = NULL;
3311
struct pf_keth_rule *rule = NULL, *tail = NULL;
3312
struct pf_keth_ruleset *ruleset = NULL;
3313
struct pfi_kkif *kif = NULL, *bridge_to_kif = NULL;
3314
const char *anchor = "", *anchor_call = "";
3315
3316
#define ERROUT(x) ERROUT_IOCTL(DIOCADDETHRULE_error, x)
3317
3318
if (nv->len > pf_ioctl_maxcount)
3319
ERROUT(ENOMEM);
3320
3321
nvlpacked = malloc(nv->len, M_NVLIST, M_WAITOK);
3322
error = copyin(nv->data, nvlpacked, nv->len);
3323
if (error)
3324
ERROUT(error);
3325
3326
nvl = nvlist_unpack(nvlpacked, nv->len, 0);
3327
if (nvl == NULL)
3328
ERROUT(EBADMSG);
3329
3330
if (! nvlist_exists_number(nvl, "ticket"))
3331
ERROUT(EBADMSG);
3332
3333
if (nvlist_exists_string(nvl, "anchor"))
3334
anchor = nvlist_get_string(nvl, "anchor");
3335
if (nvlist_exists_string(nvl, "anchor_call"))
3336
anchor_call = nvlist_get_string(nvl, "anchor_call");
3337
3338
ruleset = pf_find_keth_ruleset(anchor);
3339
if (ruleset == NULL)
3340
ERROUT(EINVAL);
3341
3342
if (nvlist_get_number(nvl, "ticket") !=
3343
ruleset->inactive.ticket) {
3344
DPFPRINTF(PF_DEBUG_MISC,
3345
"ticket: %d != %d",
3346
(u_int32_t)nvlist_get_number(nvl, "ticket"),
3347
ruleset->inactive.ticket);
3348
ERROUT(EBUSY);
3349
}
3350
3351
rule = malloc(sizeof(*rule), M_PFRULE, M_WAITOK);
3352
rule->timestamp = NULL;
3353
3354
error = pf_nveth_rule_to_keth_rule(nvl, rule);
3355
if (error != 0)
3356
ERROUT(error);
3357
3358
if (rule->ifname[0])
3359
kif = pf_kkif_create(M_WAITOK);
3360
if (rule->bridge_to_name[0])
3361
bridge_to_kif = pf_kkif_create(M_WAITOK);
3362
rule->evaluations = counter_u64_alloc(M_WAITOK);
3363
for (int i = 0; i < 2; i++) {
3364
rule->packets[i] = counter_u64_alloc(M_WAITOK);
3365
rule->bytes[i] = counter_u64_alloc(M_WAITOK);
3366
}
3367
rule->timestamp = uma_zalloc_pcpu(pf_timestamp_pcpu_zone,
3368
M_WAITOK | M_ZERO);
3369
3370
PF_RULES_WLOCK();
3371
3372
if (rule->ifname[0]) {
3373
rule->kif = pfi_kkif_attach(kif, rule->ifname);
3374
pfi_kkif_ref(rule->kif);
3375
} else
3376
rule->kif = NULL;
3377
if (rule->bridge_to_name[0]) {
3378
rule->bridge_to = pfi_kkif_attach(bridge_to_kif,
3379
rule->bridge_to_name);
3380
pfi_kkif_ref(rule->bridge_to);
3381
} else
3382
rule->bridge_to = NULL;
3383
3384
#ifdef ALTQ
3385
/* set queue IDs */
3386
if (rule->qname[0] != 0) {
3387
if ((rule->qid = pf_qname2qid(rule->qname, true)) == 0)
3388
error = EBUSY;
3389
else
3390
rule->qid = rule->qid;
3391
}
3392
#endif
3393
if (rule->tagname[0])
3394
if ((rule->tag = pf_tagname2tag(rule->tagname)) == 0)
3395
error = EBUSY;
3396
if (rule->match_tagname[0])
3397
if ((rule->match_tag = pf_tagname2tag(
3398
rule->match_tagname)) == 0)
3399
error = EBUSY;
3400
3401
if (error == 0 && rule->ipdst.addr.type == PF_ADDR_TABLE)
3402
error = pf_eth_addr_setup(ruleset, &rule->ipdst.addr);
3403
if (error == 0 && rule->ipsrc.addr.type == PF_ADDR_TABLE)
3404
error = pf_eth_addr_setup(ruleset, &rule->ipsrc.addr);
3405
3406
if (error) {
3407
pf_free_eth_rule(rule);
3408
PF_RULES_WUNLOCK();
3409
ERROUT(error);
3410
}
3411
3412
if (pf_keth_anchor_setup(rule, ruleset, anchor_call)) {
3413
pf_free_eth_rule(rule);
3414
PF_RULES_WUNLOCK();
3415
ERROUT(EINVAL);
3416
}
3417
3418
tail = TAILQ_LAST(ruleset->inactive.rules, pf_keth_ruleq);
3419
if (tail)
3420
rule->nr = tail->nr + 1;
3421
else
3422
rule->nr = 0;
3423
3424
TAILQ_INSERT_TAIL(ruleset->inactive.rules, rule, entries);
3425
3426
PF_RULES_WUNLOCK();
3427
3428
#undef ERROUT
3429
DIOCADDETHRULE_error:
3430
nvlist_destroy(nvl);
3431
free(nvlpacked, M_NVLIST);
3432
break;
3433
}
3434
3435
case DIOCGETETHRULESETS: {
3436
struct epoch_tracker et;
3437
struct pfioc_nv *nv = (struct pfioc_nv *)addr;
3438
nvlist_t *nvl = NULL;
3439
void *nvlpacked = NULL;
3440
struct pf_keth_ruleset *ruleset;
3441
struct pf_keth_anchor *anchor;
3442
int nr = 0;
3443
3444
#define ERROUT(x) ERROUT_IOCTL(DIOCGETETHRULESETS_error, x)
3445
3446
if (nv->len > pf_ioctl_maxcount)
3447
ERROUT(ENOMEM);
3448
3449
nvlpacked = malloc(nv->len, M_NVLIST, M_WAITOK);
3450
error = copyin(nv->data, nvlpacked, nv->len);
3451
if (error)
3452
ERROUT(error);
3453
3454
nvl = nvlist_unpack(nvlpacked, nv->len, 0);
3455
if (nvl == NULL)
3456
ERROUT(EBADMSG);
3457
if (! nvlist_exists_string(nvl, "path"))
3458
ERROUT(EBADMSG);
3459
3460
NET_EPOCH_ENTER(et);
3461
3462
if ((ruleset = pf_find_keth_ruleset(
3463
nvlist_get_string(nvl, "path"))) == NULL) {
3464
NET_EPOCH_EXIT(et);
3465
ERROUT(ENOENT);
3466
}
3467
3468
if (ruleset->anchor == NULL) {
3469
RB_FOREACH(anchor, pf_keth_anchor_global, &V_pf_keth_anchors)
3470
if (anchor->parent == NULL)
3471
nr++;
3472
} else {
3473
RB_FOREACH(anchor, pf_keth_anchor_node,
3474
&ruleset->anchor->children)
3475
nr++;
3476
}
3477
3478
NET_EPOCH_EXIT(et);
3479
3480
nvlist_destroy(nvl);
3481
nvl = NULL;
3482
free(nvlpacked, M_NVLIST);
3483
nvlpacked = NULL;
3484
3485
nvl = nvlist_create(0);
3486
if (nvl == NULL)
3487
ERROUT(ENOMEM);
3488
3489
nvlist_add_number(nvl, "nr", nr);
3490
3491
nvlpacked = nvlist_pack(nvl, &nv->len);
3492
if (nvlpacked == NULL)
3493
ERROUT(ENOMEM);
3494
3495
if (nv->size == 0)
3496
ERROUT(0);
3497
else if (nv->size < nv->len)
3498
ERROUT(ENOSPC);
3499
3500
error = copyout(nvlpacked, nv->data, nv->len);
3501
3502
#undef ERROUT
3503
DIOCGETETHRULESETS_error:
3504
free(nvlpacked, M_NVLIST);
3505
nvlist_destroy(nvl);
3506
break;
3507
}
3508
3509
case DIOCGETETHRULESET: {
3510
struct epoch_tracker et;
3511
struct pfioc_nv *nv = (struct pfioc_nv *)addr;
3512
nvlist_t *nvl = NULL;
3513
void *nvlpacked = NULL;
3514
struct pf_keth_ruleset *ruleset;
3515
struct pf_keth_anchor *anchor;
3516
int nr = 0, req_nr = 0;
3517
bool found = false;
3518
3519
#define ERROUT(x) ERROUT_IOCTL(DIOCGETETHRULESET_error, x)
3520
3521
if (nv->len > pf_ioctl_maxcount)
3522
ERROUT(ENOMEM);
3523
3524
nvlpacked = malloc(nv->len, M_NVLIST, M_WAITOK);
3525
error = copyin(nv->data, nvlpacked, nv->len);
3526
if (error)
3527
ERROUT(error);
3528
3529
nvl = nvlist_unpack(nvlpacked, nv->len, 0);
3530
if (nvl == NULL)
3531
ERROUT(EBADMSG);
3532
if (! nvlist_exists_string(nvl, "path"))
3533
ERROUT(EBADMSG);
3534
if (! nvlist_exists_number(nvl, "nr"))
3535
ERROUT(EBADMSG);
3536
3537
req_nr = nvlist_get_number(nvl, "nr");
3538
3539
NET_EPOCH_ENTER(et);
3540
3541
if ((ruleset = pf_find_keth_ruleset(
3542
nvlist_get_string(nvl, "path"))) == NULL) {
3543
NET_EPOCH_EXIT(et);
3544
ERROUT(ENOENT);
3545
}
3546
3547
nvlist_destroy(nvl);
3548
nvl = NULL;
3549
free(nvlpacked, M_NVLIST);
3550
nvlpacked = NULL;
3551
3552
nvl = nvlist_create(0);
3553
if (nvl == NULL) {
3554
NET_EPOCH_EXIT(et);
3555
ERROUT(ENOMEM);
3556
}
3557
3558
if (ruleset->anchor == NULL) {
3559
RB_FOREACH(anchor, pf_keth_anchor_global,
3560
&V_pf_keth_anchors) {
3561
if (anchor->parent == NULL && nr++ == req_nr) {
3562
found = true;
3563
break;
3564
}
3565
}
3566
} else {
3567
RB_FOREACH(anchor, pf_keth_anchor_node,
3568
&ruleset->anchor->children) {
3569
if (nr++ == req_nr) {
3570
found = true;
3571
break;
3572
}
3573
}
3574
}
3575
3576
NET_EPOCH_EXIT(et);
3577
if (found) {
3578
nvlist_add_number(nvl, "nr", nr);
3579
nvlist_add_string(nvl, "name", anchor->name);
3580
if (ruleset->anchor)
3581
nvlist_add_string(nvl, "path",
3582
ruleset->anchor->path);
3583
else
3584
nvlist_add_string(nvl, "path", "");
3585
} else {
3586
ERROUT(EBUSY);
3587
}
3588
3589
nvlpacked = nvlist_pack(nvl, &nv->len);
3590
if (nvlpacked == NULL)
3591
ERROUT(ENOMEM);
3592
3593
if (nv->size == 0)
3594
ERROUT(0);
3595
else if (nv->size < nv->len)
3596
ERROUT(ENOSPC);
3597
3598
error = copyout(nvlpacked, nv->data, nv->len);
3599
3600
#undef ERROUT
3601
DIOCGETETHRULESET_error:
3602
free(nvlpacked, M_NVLIST);
3603
nvlist_destroy(nvl);
3604
break;
3605
}
3606
3607
case DIOCADDRULENV: {
3608
struct pfioc_nv *nv = (struct pfioc_nv *)addr;
3609
nvlist_t *nvl = NULL;
3610
void *nvlpacked = NULL;
3611
struct pf_krule *rule = NULL;
3612
const char *anchor = "", *anchor_call = "";
3613
uint32_t ticket = 0, pool_ticket = 0;
3614
3615
#define ERROUT(x) ERROUT_IOCTL(DIOCADDRULENV_error, x)
3616
3617
if (nv->len > pf_ioctl_maxcount)
3618
ERROUT(ENOMEM);
3619
3620
nvlpacked = malloc(nv->len, M_NVLIST, M_WAITOK);
3621
error = copyin(nv->data, nvlpacked, nv->len);
3622
if (error)
3623
ERROUT(error);
3624
3625
nvl = nvlist_unpack(nvlpacked, nv->len, 0);
3626
if (nvl == NULL)
3627
ERROUT(EBADMSG);
3628
3629
if (! nvlist_exists_number(nvl, "ticket"))
3630
ERROUT(EINVAL);
3631
ticket = nvlist_get_number(nvl, "ticket");
3632
3633
if (! nvlist_exists_number(nvl, "pool_ticket"))
3634
ERROUT(EINVAL);
3635
pool_ticket = nvlist_get_number(nvl, "pool_ticket");
3636
3637
if (! nvlist_exists_nvlist(nvl, "rule"))
3638
ERROUT(EINVAL);
3639
3640
rule = pf_krule_alloc();
3641
error = pf_nvrule_to_krule(nvlist_get_nvlist(nvl, "rule"),
3642
rule);
3643
if (error)
3644
ERROUT(error);
3645
3646
if (nvlist_exists_string(nvl, "anchor"))
3647
anchor = nvlist_get_string(nvl, "anchor");
3648
if (nvlist_exists_string(nvl, "anchor_call"))
3649
anchor_call = nvlist_get_string(nvl, "anchor_call");
3650
3651
if ((error = nvlist_error(nvl)))
3652
ERROUT(error);
3653
3654
/* Frees rule on error */
3655
error = pf_ioctl_addrule(rule, ticket, pool_ticket, anchor,
3656
anchor_call, td->td_ucred->cr_ruid,
3657
td->td_proc ? td->td_proc->p_pid : 0);
3658
3659
nvlist_destroy(nvl);
3660
free(nvlpacked, M_NVLIST);
3661
break;
3662
#undef ERROUT
3663
DIOCADDRULENV_error:
3664
pf_krule_free(rule);
3665
nvlist_destroy(nvl);
3666
free(nvlpacked, M_NVLIST);
3667
3668
break;
3669
}
3670
case DIOCADDRULE: {
3671
struct pfioc_rule *pr = (struct pfioc_rule *)addr;
3672
struct pf_krule *rule;
3673
3674
rule = pf_krule_alloc();
3675
error = pf_rule_to_krule(&pr->rule, rule);
3676
if (error != 0) {
3677
pf_krule_free(rule);
3678
goto fail;
3679
}
3680
3681
pr->anchor[sizeof(pr->anchor) - 1] = '\0';
3682
3683
/* Frees rule on error */
3684
error = pf_ioctl_addrule(rule, pr->ticket, pr->pool_ticket,
3685
pr->anchor, pr->anchor_call, td->td_ucred->cr_ruid,
3686
td->td_proc ? td->td_proc->p_pid : 0);
3687
break;
3688
}
3689
3690
case DIOCGETRULES: {
3691
struct pfioc_rule *pr = (struct pfioc_rule *)addr;
3692
3693
pr->anchor[sizeof(pr->anchor) - 1] = '\0';
3694
3695
error = pf_ioctl_getrules(pr);
3696
3697
break;
3698
}
3699
3700
case DIOCGETRULENV: {
3701
struct pfioc_nv *nv = (struct pfioc_nv *)addr;
3702
nvlist_t *nvrule = NULL;
3703
nvlist_t *nvl = NULL;
3704
struct pf_kruleset *ruleset;
3705
struct pf_krule *rule;
3706
void *nvlpacked = NULL;
3707
int rs_num, nr;
3708
bool clear_counter = false;
3709
3710
#define ERROUT(x) ERROUT_IOCTL(DIOCGETRULENV_error, x)
3711
3712
if (nv->len > pf_ioctl_maxcount)
3713
ERROUT(ENOMEM);
3714
3715
/* Copy the request in */
3716
nvlpacked = malloc(nv->len, M_NVLIST, M_WAITOK);
3717
error = copyin(nv->data, nvlpacked, nv->len);
3718
if (error)
3719
ERROUT(error);
3720
3721
nvl = nvlist_unpack(nvlpacked, nv->len, 0);
3722
if (nvl == NULL)
3723
ERROUT(EBADMSG);
3724
3725
if (! nvlist_exists_string(nvl, "anchor"))
3726
ERROUT(EBADMSG);
3727
if (! nvlist_exists_number(nvl, "ruleset"))
3728
ERROUT(EBADMSG);
3729
if (! nvlist_exists_number(nvl, "ticket"))
3730
ERROUT(EBADMSG);
3731
if (! nvlist_exists_number(nvl, "nr"))
3732
ERROUT(EBADMSG);
3733
3734
if (nvlist_exists_bool(nvl, "clear_counter"))
3735
clear_counter = nvlist_get_bool(nvl, "clear_counter");
3736
3737
if (clear_counter && !(flags & FWRITE))
3738
ERROUT(EACCES);
3739
3740
nr = nvlist_get_number(nvl, "nr");
3741
3742
PF_RULES_WLOCK();
3743
ruleset = pf_find_kruleset(nvlist_get_string(nvl, "anchor"));
3744
if (ruleset == NULL) {
3745
PF_RULES_WUNLOCK();
3746
ERROUT(ENOENT);
3747
}
3748
3749
rs_num = pf_get_ruleset_number(nvlist_get_number(nvl, "ruleset"));
3750
if (rs_num >= PF_RULESET_MAX) {
3751
PF_RULES_WUNLOCK();
3752
ERROUT(EINVAL);
3753
}
3754
3755
if (nvlist_get_number(nvl, "ticket") !=
3756
ruleset->rules[rs_num].active.ticket) {
3757
PF_RULES_WUNLOCK();
3758
ERROUT(EBUSY);
3759
}
3760
3761
if ((error = nvlist_error(nvl))) {
3762
PF_RULES_WUNLOCK();
3763
ERROUT(error);
3764
}
3765
3766
rule = TAILQ_FIRST(ruleset->rules[rs_num].active.ptr);
3767
while ((rule != NULL) && (rule->nr != nr))
3768
rule = TAILQ_NEXT(rule, entries);
3769
if (rule == NULL) {
3770
PF_RULES_WUNLOCK();
3771
ERROUT(EBUSY);
3772
}
3773
3774
nvrule = pf_krule_to_nvrule(rule);
3775
3776
nvlist_destroy(nvl);
3777
nvl = nvlist_create(0);
3778
if (nvl == NULL) {
3779
PF_RULES_WUNLOCK();
3780
ERROUT(ENOMEM);
3781
}
3782
nvlist_add_number(nvl, "nr", nr);
3783
nvlist_add_nvlist(nvl, "rule", nvrule);
3784
nvlist_destroy(nvrule);
3785
nvrule = NULL;
3786
if (pf_kanchor_nvcopyout(ruleset, rule, nvl)) {
3787
PF_RULES_WUNLOCK();
3788
ERROUT(EBUSY);
3789
}
3790
3791
free(nvlpacked, M_NVLIST);
3792
nvlpacked = nvlist_pack(nvl, &nv->len);
3793
if (nvlpacked == NULL) {
3794
PF_RULES_WUNLOCK();
3795
ERROUT(ENOMEM);
3796
}
3797
3798
if (nv->size == 0) {
3799
PF_RULES_WUNLOCK();
3800
ERROUT(0);
3801
}
3802
else if (nv->size < nv->len) {
3803
PF_RULES_WUNLOCK();
3804
ERROUT(ENOSPC);
3805
}
3806
3807
if (clear_counter)
3808
pf_krule_clear_counters(rule);
3809
3810
PF_RULES_WUNLOCK();
3811
3812
error = copyout(nvlpacked, nv->data, nv->len);
3813
3814
#undef ERROUT
3815
DIOCGETRULENV_error:
3816
free(nvlpacked, M_NVLIST);
3817
nvlist_destroy(nvrule);
3818
nvlist_destroy(nvl);
3819
3820
break;
3821
}
3822
3823
case DIOCCHANGERULE: {
3824
struct pfioc_rule *pcr = (struct pfioc_rule *)addr;
3825
struct pf_kruleset *ruleset;
3826
struct pf_krule *oldrule = NULL, *newrule = NULL;
3827
struct pfi_kkif *kif = NULL;
3828
struct pf_kpooladdr *pa;
3829
u_int32_t nr = 0;
3830
int rs_num;
3831
3832
pcr->anchor[sizeof(pcr->anchor) - 1] = '\0';
3833
3834
if (pcr->action < PF_CHANGE_ADD_HEAD ||
3835
pcr->action > PF_CHANGE_GET_TICKET) {
3836
error = EINVAL;
3837
goto fail;
3838
}
3839
if (pcr->rule.return_icmp >> 8 > ICMP_MAXTYPE) {
3840
error = EINVAL;
3841
goto fail;
3842
}
3843
3844
if (pcr->action != PF_CHANGE_REMOVE) {
3845
newrule = pf_krule_alloc();
3846
error = pf_rule_to_krule(&pcr->rule, newrule);
3847
if (error != 0) {
3848
pf_krule_free(newrule);
3849
goto fail;
3850
}
3851
3852
if ((error = pf_rule_checkaf(newrule))) {
3853
pf_krule_free(newrule);
3854
goto fail;
3855
}
3856
if (newrule->ifname[0])
3857
kif = pf_kkif_create(M_WAITOK);
3858
pf_counter_u64_init(&newrule->evaluations, M_WAITOK);
3859
for (int i = 0; i < 2; i++) {
3860
pf_counter_u64_init(&newrule->packets[i], M_WAITOK);
3861
pf_counter_u64_init(&newrule->bytes[i], M_WAITOK);
3862
}
3863
newrule->states_cur = counter_u64_alloc(M_WAITOK);
3864
newrule->states_tot = counter_u64_alloc(M_WAITOK);
3865
for (pf_sn_types_t sn_type=0; sn_type<PF_SN_MAX; sn_type++)
3866
newrule->src_nodes[sn_type] = counter_u64_alloc(M_WAITOK);
3867
newrule->cuid = td->td_ucred->cr_ruid;
3868
newrule->cpid = td->td_proc ? td->td_proc->p_pid : 0;
3869
TAILQ_INIT(&newrule->nat.list);
3870
TAILQ_INIT(&newrule->rdr.list);
3871
TAILQ_INIT(&newrule->route.list);
3872
}
3873
#define ERROUT(x) ERROUT_IOCTL(DIOCCHANGERULE_error, x)
3874
3875
PF_CONFIG_LOCK();
3876
PF_RULES_WLOCK();
3877
#ifdef PF_WANT_32_TO_64_COUNTER
3878
if (newrule != NULL) {
3879
LIST_INSERT_HEAD(&V_pf_allrulelist, newrule, allrulelist);
3880
newrule->allrulelinked = true;
3881
V_pf_allrulecount++;
3882
}
3883
#endif
3884
3885
if (!(pcr->action == PF_CHANGE_REMOVE ||
3886
pcr->action == PF_CHANGE_GET_TICKET) &&
3887
pcr->pool_ticket != V_ticket_pabuf)
3888
ERROUT(EBUSY);
3889
3890
ruleset = pf_find_kruleset(pcr->anchor);
3891
if (ruleset == NULL)
3892
ERROUT(EINVAL);
3893
3894
rs_num = pf_get_ruleset_number(pcr->rule.action);
3895
if (rs_num >= PF_RULESET_MAX)
3896
ERROUT(EINVAL);
3897
3898
/*
3899
* XXXMJG: there is no guarantee that the ruleset was
3900
* created by the usual route of calling DIOCXBEGIN.
3901
* As a result it is possible the rule tree will not
3902
* be allocated yet. Hack around it by doing it here.
3903
* Note it is fine to let the tree persist in case of
3904
* error as it will be freed down the road on future
3905
* updates (if need be).
3906
*/
3907
if (ruleset->rules[rs_num].active.tree == NULL) {
3908
ruleset->rules[rs_num].active.tree = pf_rule_tree_alloc(M_NOWAIT);
3909
if (ruleset->rules[rs_num].active.tree == NULL) {
3910
ERROUT(ENOMEM);
3911
}
3912
}
3913
3914
if (pcr->action == PF_CHANGE_GET_TICKET) {
3915
pcr->ticket = ++ruleset->rules[rs_num].active.ticket;
3916
ERROUT(0);
3917
} else if (pcr->ticket !=
3918
ruleset->rules[rs_num].active.ticket)
3919
ERROUT(EINVAL);
3920
3921
if (pcr->action != PF_CHANGE_REMOVE) {
3922
if (newrule->ifname[0]) {
3923
newrule->kif = pfi_kkif_attach(kif,
3924
newrule->ifname);
3925
kif = NULL;
3926
pfi_kkif_ref(newrule->kif);
3927
} else
3928
newrule->kif = NULL;
3929
3930
if (newrule->rtableid > 0 &&
3931
newrule->rtableid >= rt_numfibs)
3932
error = EBUSY;
3933
3934
#ifdef ALTQ
3935
/* set queue IDs */
3936
if (newrule->qname[0] != 0) {
3937
if ((newrule->qid =
3938
pf_qname2qid(newrule->qname, true)) == 0)
3939
error = EBUSY;
3940
else if (newrule->pqname[0] != 0) {
3941
if ((newrule->pqid =
3942
pf_qname2qid(newrule->pqname, true)) == 0)
3943
error = EBUSY;
3944
} else
3945
newrule->pqid = newrule->qid;
3946
}
3947
#endif /* ALTQ */
3948
if (newrule->tagname[0])
3949
if ((newrule->tag =
3950
pf_tagname2tag(newrule->tagname)) == 0)
3951
error = EBUSY;
3952
if (newrule->match_tagname[0])
3953
if ((newrule->match_tag = pf_tagname2tag(
3954
newrule->match_tagname)) == 0)
3955
error = EBUSY;
3956
if (newrule->rt && !newrule->direction)
3957
error = EINVAL;
3958
if (!newrule->log)
3959
newrule->logif = 0;
3960
if (pf_addr_setup(ruleset, &newrule->src.addr, newrule->af))
3961
error = ENOMEM;
3962
if (pf_addr_setup(ruleset, &newrule->dst.addr, newrule->af))
3963
error = ENOMEM;
3964
if (pf_kanchor_setup(newrule, ruleset, pcr->anchor_call))
3965
error = EINVAL;
3966
for (int i = 0; i < 3; i++) {
3967
TAILQ_FOREACH(pa, &V_pf_pabuf[i], entries)
3968
if (pa->addr.type == PF_ADDR_TABLE) {
3969
pa->addr.p.tbl =
3970
pfr_attach_table(ruleset,
3971
pa->addr.v.tblname);
3972
if (pa->addr.p.tbl == NULL)
3973
error = ENOMEM;
3974
}
3975
}
3976
3977
newrule->overload_tbl = NULL;
3978
if (newrule->overload_tblname[0]) {
3979
if ((newrule->overload_tbl = pfr_attach_table(
3980
ruleset, newrule->overload_tblname)) ==
3981
NULL)
3982
error = EINVAL;
3983
else
3984
newrule->overload_tbl->pfrkt_flags |=
3985
PFR_TFLAG_ACTIVE;
3986
}
3987
3988
pf_mv_kpool(&V_pf_pabuf[0], &newrule->nat.list);
3989
pf_mv_kpool(&V_pf_pabuf[1], &newrule->rdr.list);
3990
pf_mv_kpool(&V_pf_pabuf[2], &newrule->route.list);
3991
if (((((newrule->action == PF_NAT) ||
3992
(newrule->action == PF_RDR) ||
3993
(newrule->action == PF_BINAT) ||
3994
(newrule->rt > PF_NOPFROUTE)) &&
3995
!newrule->anchor)) &&
3996
(TAILQ_FIRST(&newrule->rdr.list) == NULL))
3997
error = EINVAL;
3998
3999
if (error) {
4000
pf_free_rule(newrule);
4001
PF_RULES_WUNLOCK();
4002
PF_CONFIG_UNLOCK();
4003
goto fail;
4004
}
4005
4006
newrule->nat.cur = TAILQ_FIRST(&newrule->nat.list);
4007
newrule->rdr.cur = TAILQ_FIRST(&newrule->rdr.list);
4008
}
4009
pf_empty_kpool(&V_pf_pabuf[0]);
4010
pf_empty_kpool(&V_pf_pabuf[1]);
4011
pf_empty_kpool(&V_pf_pabuf[2]);
4012
4013
if (pcr->action == PF_CHANGE_ADD_HEAD)
4014
oldrule = TAILQ_FIRST(
4015
ruleset->rules[rs_num].active.ptr);
4016
else if (pcr->action == PF_CHANGE_ADD_TAIL)
4017
oldrule = TAILQ_LAST(
4018
ruleset->rules[rs_num].active.ptr, pf_krulequeue);
4019
else {
4020
oldrule = TAILQ_FIRST(
4021
ruleset->rules[rs_num].active.ptr);
4022
while ((oldrule != NULL) && (oldrule->nr != pcr->nr))
4023
oldrule = TAILQ_NEXT(oldrule, entries);
4024
if (oldrule == NULL) {
4025
if (newrule != NULL)
4026
pf_free_rule(newrule);
4027
PF_RULES_WUNLOCK();
4028
PF_CONFIG_UNLOCK();
4029
error = EINVAL;
4030
goto fail;
4031
}
4032
}
4033
4034
if (pcr->action == PF_CHANGE_REMOVE) {
4035
pf_unlink_rule(ruleset->rules[rs_num].active.ptr,
4036
oldrule);
4037
RB_REMOVE(pf_krule_global,
4038
ruleset->rules[rs_num].active.tree, oldrule);
4039
ruleset->rules[rs_num].active.rcount--;
4040
} else {
4041
pf_hash_rule(newrule);
4042
if (RB_INSERT(pf_krule_global,
4043
ruleset->rules[rs_num].active.tree, newrule) != NULL) {
4044
pf_free_rule(newrule);
4045
PF_RULES_WUNLOCK();
4046
PF_CONFIG_UNLOCK();
4047
error = EEXIST;
4048
goto fail;
4049
}
4050
4051
if (oldrule == NULL)
4052
TAILQ_INSERT_TAIL(
4053
ruleset->rules[rs_num].active.ptr,
4054
newrule, entries);
4055
else if (pcr->action == PF_CHANGE_ADD_HEAD ||
4056
pcr->action == PF_CHANGE_ADD_BEFORE)
4057
TAILQ_INSERT_BEFORE(oldrule, newrule, entries);
4058
else
4059
TAILQ_INSERT_AFTER(
4060
ruleset->rules[rs_num].active.ptr,
4061
oldrule, newrule, entries);
4062
ruleset->rules[rs_num].active.rcount++;
4063
}
4064
4065
nr = 0;
4066
TAILQ_FOREACH(oldrule,
4067
ruleset->rules[rs_num].active.ptr, entries)
4068
oldrule->nr = nr++;
4069
4070
ruleset->rules[rs_num].active.ticket++;
4071
4072
pf_calc_skip_steps(ruleset->rules[rs_num].active.ptr);
4073
pf_remove_if_empty_kruleset(ruleset);
4074
4075
PF_RULES_WUNLOCK();
4076
PF_CONFIG_UNLOCK();
4077
break;
4078
4079
#undef ERROUT
4080
DIOCCHANGERULE_error:
4081
PF_RULES_WUNLOCK();
4082
PF_CONFIG_UNLOCK();
4083
pf_krule_free(newrule);
4084
pf_kkif_free(kif);
4085
break;
4086
}
4087
4088
case DIOCCLRSTATESNV: {
4089
error = pf_clearstates_nv((struct pfioc_nv *)addr);
4090
break;
4091
}
4092
4093
case DIOCKILLSTATESNV: {
4094
error = pf_killstates_nv((struct pfioc_nv *)addr);
4095
break;
4096
}
4097
4098
case DIOCADDSTATE: {
4099
struct pfioc_state *ps = (struct pfioc_state *)addr;
4100
struct pfsync_state_1301 *sp = &ps->state;
4101
4102
if (sp->timeout >= PFTM_MAX) {
4103
error = EINVAL;
4104
goto fail;
4105
}
4106
if (V_pfsync_state_import_ptr != NULL) {
4107
PF_RULES_RLOCK();
4108
error = V_pfsync_state_import_ptr(
4109
(union pfsync_state_union *)sp, PFSYNC_SI_IOCTL,
4110
PFSYNC_MSG_VERSION_1301);
4111
PF_RULES_RUNLOCK();
4112
} else
4113
error = EOPNOTSUPP;
4114
break;
4115
}
4116
4117
case DIOCGETSTATE: {
4118
struct pfioc_state *ps = (struct pfioc_state *)addr;
4119
struct pf_kstate *s;
4120
4121
s = pf_find_state_byid(ps->state.id, ps->state.creatorid);
4122
if (s == NULL) {
4123
error = ENOENT;
4124
goto fail;
4125
}
4126
4127
pfsync_state_export((union pfsync_state_union*)&ps->state,
4128
s, PFSYNC_MSG_VERSION_1301);
4129
PF_STATE_UNLOCK(s);
4130
break;
4131
}
4132
4133
case DIOCGETSTATENV: {
4134
error = pf_getstate((struct pfioc_nv *)addr);
4135
break;
4136
}
4137
4138
#ifdef COMPAT_FREEBSD14
4139
case DIOCGETSTATES: {
4140
struct pfioc_states *ps = (struct pfioc_states *)addr;
4141
struct pf_kstate *s;
4142
struct pfsync_state_1301 *pstore, *p;
4143
int i, nr;
4144
size_t slice_count = 16, count;
4145
void *out;
4146
4147
if (ps->ps_len <= 0) {
4148
nr = uma_zone_get_cur(V_pf_state_z);
4149
ps->ps_len = sizeof(struct pfsync_state_1301) * nr;
4150
break;
4151
}
4152
4153
out = ps->ps_states;
4154
pstore = mallocarray(slice_count,
4155
sizeof(struct pfsync_state_1301), M_PF, M_WAITOK | M_ZERO);
4156
nr = 0;
4157
4158
for (i = 0; i <= V_pf_hashmask; i++) {
4159
struct pf_idhash *ih = &V_pf_idhash[i];
4160
4161
DIOCGETSTATES_retry:
4162
p = pstore;
4163
4164
if (LIST_EMPTY(&ih->states))
4165
continue;
4166
4167
PF_HASHROW_LOCK(ih);
4168
count = 0;
4169
LIST_FOREACH(s, &ih->states, entry) {
4170
if (s->timeout == PFTM_UNLINKED)
4171
continue;
4172
count++;
4173
}
4174
4175
if (count > slice_count) {
4176
PF_HASHROW_UNLOCK(ih);
4177
free(pstore, M_PF);
4178
slice_count = count * 2;
4179
pstore = mallocarray(slice_count,
4180
sizeof(struct pfsync_state_1301), M_PF,
4181
M_WAITOK | M_ZERO);
4182
goto DIOCGETSTATES_retry;
4183
}
4184
4185
if ((nr+count) * sizeof(*p) > ps->ps_len) {
4186
PF_HASHROW_UNLOCK(ih);
4187
goto DIOCGETSTATES_full;
4188
}
4189
4190
LIST_FOREACH(s, &ih->states, entry) {
4191
if (s->timeout == PFTM_UNLINKED)
4192
continue;
4193
4194
pfsync_state_export((union pfsync_state_union*)p,
4195
s, PFSYNC_MSG_VERSION_1301);
4196
p++;
4197
nr++;
4198
}
4199
PF_HASHROW_UNLOCK(ih);
4200
error = copyout(pstore, out,
4201
sizeof(struct pfsync_state_1301) * count);
4202
if (error) {
4203
free(pstore, M_PF);
4204
goto fail;
4205
}
4206
out = ps->ps_states + nr;
4207
}
4208
DIOCGETSTATES_full:
4209
ps->ps_len = sizeof(struct pfsync_state_1301) * nr;
4210
free(pstore, M_PF);
4211
4212
break;
4213
}
4214
4215
case DIOCGETSTATESV2: {
4216
struct pfioc_states_v2 *ps = (struct pfioc_states_v2 *)addr;
4217
struct pf_kstate *s;
4218
struct pf_state_export *pstore, *p;
4219
int i, nr;
4220
size_t slice_count = 16, count;
4221
void *out;
4222
4223
if (ps->ps_req_version > PF_STATE_VERSION) {
4224
error = ENOTSUP;
4225
goto fail;
4226
}
4227
4228
if (ps->ps_len <= 0) {
4229
nr = uma_zone_get_cur(V_pf_state_z);
4230
ps->ps_len = sizeof(struct pf_state_export) * nr;
4231
break;
4232
}
4233
4234
out = ps->ps_states;
4235
pstore = mallocarray(slice_count,
4236
sizeof(struct pf_state_export), M_PF, M_WAITOK | M_ZERO);
4237
nr = 0;
4238
4239
for (i = 0; i <= V_pf_hashmask; i++) {
4240
struct pf_idhash *ih = &V_pf_idhash[i];
4241
4242
DIOCGETSTATESV2_retry:
4243
p = pstore;
4244
4245
if (LIST_EMPTY(&ih->states))
4246
continue;
4247
4248
PF_HASHROW_LOCK(ih);
4249
count = 0;
4250
LIST_FOREACH(s, &ih->states, entry) {
4251
if (s->timeout == PFTM_UNLINKED)
4252
continue;
4253
count++;
4254
}
4255
4256
if (count > slice_count) {
4257
PF_HASHROW_UNLOCK(ih);
4258
free(pstore, M_PF);
4259
slice_count = count * 2;
4260
pstore = mallocarray(slice_count,
4261
sizeof(struct pf_state_export), M_PF,
4262
M_WAITOK | M_ZERO);
4263
goto DIOCGETSTATESV2_retry;
4264
}
4265
4266
if ((nr+count) * sizeof(*p) > ps->ps_len) {
4267
PF_HASHROW_UNLOCK(ih);
4268
goto DIOCGETSTATESV2_full;
4269
}
4270
4271
LIST_FOREACH(s, &ih->states, entry) {
4272
if (s->timeout == PFTM_UNLINKED)
4273
continue;
4274
4275
pf_state_export(p, s);
4276
p++;
4277
nr++;
4278
}
4279
PF_HASHROW_UNLOCK(ih);
4280
error = copyout(pstore, out,
4281
sizeof(struct pf_state_export) * count);
4282
if (error) {
4283
free(pstore, M_PF);
4284
goto fail;
4285
}
4286
out = ps->ps_states + nr;
4287
}
4288
DIOCGETSTATESV2_full:
4289
ps->ps_len = nr * sizeof(struct pf_state_export);
4290
free(pstore, M_PF);
4291
4292
break;
4293
}
4294
#endif
4295
case DIOCGETSTATUSNV: {
4296
error = pf_getstatus((struct pfioc_nv *)addr);
4297
break;
4298
}
4299
4300
case DIOCSETSTATUSIF: {
4301
struct pfioc_if *pi = (struct pfioc_if *)addr;
4302
4303
if (pi->ifname[0] == 0) {
4304
bzero(V_pf_status.ifname, IFNAMSIZ);
4305
break;
4306
}
4307
PF_RULES_WLOCK();
4308
error = pf_user_strcpy(V_pf_status.ifname, pi->ifname, IFNAMSIZ);
4309
PF_RULES_WUNLOCK();
4310
break;
4311
}
4312
4313
case DIOCCLRSTATUS: {
4314
pf_ioctl_clear_status();
4315
break;
4316
}
4317
4318
case DIOCNATLOOK: {
4319
struct pfioc_natlook *pnl = (struct pfioc_natlook *)addr;
4320
4321
error = pf_ioctl_natlook(pnl);
4322
break;
4323
}
4324
4325
case DIOCSETTIMEOUT: {
4326
struct pfioc_tm *pt = (struct pfioc_tm *)addr;
4327
4328
error = pf_ioctl_set_timeout(pt->timeout, pt->seconds,
4329
&pt->seconds);
4330
break;
4331
}
4332
4333
case DIOCGETTIMEOUT: {
4334
struct pfioc_tm *pt = (struct pfioc_tm *)addr;
4335
4336
error = pf_ioctl_get_timeout(pt->timeout, &pt->seconds);
4337
break;
4338
}
4339
4340
case DIOCGETLIMIT: {
4341
struct pfioc_limit *pl = (struct pfioc_limit *)addr;
4342
4343
error = pf_ioctl_get_limit(pl->index, &pl->limit);
4344
break;
4345
}
4346
4347
case DIOCSETLIMIT: {
4348
struct pfioc_limit *pl = (struct pfioc_limit *)addr;
4349
unsigned int old_limit;
4350
4351
error = pf_ioctl_set_limit(pl->index, pl->limit, &old_limit);
4352
pl->limit = old_limit;
4353
break;
4354
}
4355
4356
case DIOCSETDEBUG: {
4357
u_int32_t *level = (u_int32_t *)addr;
4358
4359
PF_RULES_WLOCK();
4360
V_pf_status.debug = *level;
4361
PF_RULES_WUNLOCK();
4362
break;
4363
}
4364
4365
case DIOCCLRRULECTRS: {
4366
/* obsoleted by DIOCGETRULE with action=PF_GET_CLR_CNTR */
4367
struct pf_kruleset *ruleset = &pf_main_ruleset;
4368
struct pf_krule *rule;
4369
4370
PF_RULES_WLOCK();
4371
TAILQ_FOREACH(rule,
4372
ruleset->rules[PF_RULESET_FILTER].active.ptr, entries) {
4373
pf_counter_u64_zero(&rule->evaluations);
4374
for (int i = 0; i < 2; i++) {
4375
pf_counter_u64_zero(&rule->packets[i]);
4376
pf_counter_u64_zero(&rule->bytes[i]);
4377
}
4378
}
4379
PF_RULES_WUNLOCK();
4380
break;
4381
}
4382
4383
case DIOCGIFSPEEDV0:
4384
case DIOCGIFSPEEDV1: {
4385
struct pf_ifspeed_v1 *psp = (struct pf_ifspeed_v1 *)addr;
4386
struct pf_ifspeed_v1 ps;
4387
struct ifnet *ifp;
4388
4389
if (psp->ifname[0] == '\0') {
4390
error = EINVAL;
4391
goto fail;
4392
}
4393
4394
error = pf_user_strcpy(ps.ifname, psp->ifname, IFNAMSIZ);
4395
if (error != 0)
4396
goto fail;
4397
ifp = ifunit(ps.ifname);
4398
if (ifp != NULL) {
4399
psp->baudrate32 =
4400
(u_int32_t)uqmin(ifp->if_baudrate, UINT_MAX);
4401
if (cmd == DIOCGIFSPEEDV1)
4402
psp->baudrate = ifp->if_baudrate;
4403
} else {
4404
error = EINVAL;
4405
}
4406
break;
4407
}
4408
4409
#ifdef ALTQ
4410
case DIOCSTARTALTQ: {
4411
struct pf_altq *altq;
4412
4413
PF_RULES_WLOCK();
4414
/* enable all altq interfaces on active list */
4415
TAILQ_FOREACH(altq, V_pf_altq_ifs_active, entries) {
4416
if ((altq->local_flags & PFALTQ_FLAG_IF_REMOVED) == 0) {
4417
error = pf_enable_altq(altq);
4418
if (error != 0)
4419
break;
4420
}
4421
}
4422
if (error == 0)
4423
V_pf_altq_running = 1;
4424
PF_RULES_WUNLOCK();
4425
DPFPRINTF(PF_DEBUG_MISC, "altq: started");
4426
break;
4427
}
4428
4429
case DIOCSTOPALTQ: {
4430
struct pf_altq *altq;
4431
4432
PF_RULES_WLOCK();
4433
/* disable all altq interfaces on active list */
4434
TAILQ_FOREACH(altq, V_pf_altq_ifs_active, entries) {
4435
if ((altq->local_flags & PFALTQ_FLAG_IF_REMOVED) == 0) {
4436
error = pf_disable_altq(altq);
4437
if (error != 0)
4438
break;
4439
}
4440
}
4441
if (error == 0)
4442
V_pf_altq_running = 0;
4443
PF_RULES_WUNLOCK();
4444
DPFPRINTF(PF_DEBUG_MISC, "altq: stopped");
4445
break;
4446
}
4447
4448
case DIOCADDALTQV0:
4449
case DIOCADDALTQV1: {
4450
struct pfioc_altq_v1 *pa = (struct pfioc_altq_v1 *)addr;
4451
struct pf_altq *altq, *a;
4452
struct ifnet *ifp;
4453
4454
altq = malloc(sizeof(*altq), M_PFALTQ, M_WAITOK | M_ZERO);
4455
error = pf_import_kaltq(pa, altq, IOCPARM_LEN(cmd));
4456
if (error)
4457
goto fail;
4458
altq->local_flags = 0;
4459
4460
PF_RULES_WLOCK();
4461
if (pa->ticket != V_ticket_altqs_inactive) {
4462
PF_RULES_WUNLOCK();
4463
free(altq, M_PFALTQ);
4464
error = EBUSY;
4465
goto fail;
4466
}
4467
4468
/*
4469
* if this is for a queue, find the discipline and
4470
* copy the necessary fields
4471
*/
4472
if (altq->qname[0] != 0) {
4473
if ((altq->qid = pf_qname2qid(altq->qname, true)) == 0) {
4474
PF_RULES_WUNLOCK();
4475
error = EBUSY;
4476
free(altq, M_PFALTQ);
4477
goto fail;
4478
}
4479
altq->altq_disc = NULL;
4480
TAILQ_FOREACH(a, V_pf_altq_ifs_inactive, entries) {
4481
if (strncmp(a->ifname, altq->ifname,
4482
IFNAMSIZ) == 0) {
4483
altq->altq_disc = a->altq_disc;
4484
break;
4485
}
4486
}
4487
}
4488
4489
if ((ifp = ifunit(altq->ifname)) == NULL)
4490
altq->local_flags |= PFALTQ_FLAG_IF_REMOVED;
4491
else
4492
error = altq_add(ifp, altq);
4493
4494
if (error) {
4495
PF_RULES_WUNLOCK();
4496
free(altq, M_PFALTQ);
4497
goto fail;
4498
}
4499
4500
if (altq->qname[0] != 0)
4501
TAILQ_INSERT_TAIL(V_pf_altqs_inactive, altq, entries);
4502
else
4503
TAILQ_INSERT_TAIL(V_pf_altq_ifs_inactive, altq, entries);
4504
/* version error check done on import above */
4505
pf_export_kaltq(altq, pa, IOCPARM_LEN(cmd));
4506
PF_RULES_WUNLOCK();
4507
break;
4508
}
4509
4510
case DIOCGETALTQSV0:
4511
case DIOCGETALTQSV1: {
4512
struct pfioc_altq_v1 *pa = (struct pfioc_altq_v1 *)addr;
4513
struct pf_altq *altq;
4514
4515
PF_RULES_RLOCK();
4516
pa->nr = 0;
4517
TAILQ_FOREACH(altq, V_pf_altq_ifs_active, entries)
4518
pa->nr++;
4519
TAILQ_FOREACH(altq, V_pf_altqs_active, entries)
4520
pa->nr++;
4521
pa->ticket = V_ticket_altqs_active;
4522
PF_RULES_RUNLOCK();
4523
break;
4524
}
4525
4526
case DIOCGETALTQV0:
4527
case DIOCGETALTQV1: {
4528
struct pfioc_altq_v1 *pa = (struct pfioc_altq_v1 *)addr;
4529
struct pf_altq *altq;
4530
4531
PF_RULES_RLOCK();
4532
if (pa->ticket != V_ticket_altqs_active) {
4533
PF_RULES_RUNLOCK();
4534
error = EBUSY;
4535
goto fail;
4536
}
4537
altq = pf_altq_get_nth_active(pa->nr);
4538
if (altq == NULL) {
4539
PF_RULES_RUNLOCK();
4540
error = EBUSY;
4541
goto fail;
4542
}
4543
pf_export_kaltq(altq, pa, IOCPARM_LEN(cmd));
4544
PF_RULES_RUNLOCK();
4545
break;
4546
}
4547
4548
case DIOCCHANGEALTQV0:
4549
case DIOCCHANGEALTQV1:
4550
/* CHANGEALTQ not supported yet! */
4551
error = ENODEV;
4552
break;
4553
4554
case DIOCGETQSTATSV0:
4555
case DIOCGETQSTATSV1: {
4556
struct pfioc_qstats_v1 *pq = (struct pfioc_qstats_v1 *)addr;
4557
struct pf_altq *altq;
4558
int nbytes;
4559
u_int32_t version;
4560
4561
PF_RULES_RLOCK();
4562
if (pq->ticket != V_ticket_altqs_active) {
4563
PF_RULES_RUNLOCK();
4564
error = EBUSY;
4565
goto fail;
4566
}
4567
nbytes = pq->nbytes;
4568
altq = pf_altq_get_nth_active(pq->nr);
4569
if (altq == NULL) {
4570
PF_RULES_RUNLOCK();
4571
error = EBUSY;
4572
goto fail;
4573
}
4574
4575
if ((altq->local_flags & PFALTQ_FLAG_IF_REMOVED) != 0) {
4576
PF_RULES_RUNLOCK();
4577
error = ENXIO;
4578
goto fail;
4579
}
4580
PF_RULES_RUNLOCK();
4581
if (cmd == DIOCGETQSTATSV0)
4582
version = 0; /* DIOCGETQSTATSV0 means stats struct v0 */
4583
else
4584
version = pq->version;
4585
error = altq_getqstats(altq, pq->buf, &nbytes, version);
4586
if (error == 0) {
4587
pq->scheduler = altq->scheduler;
4588
pq->nbytes = nbytes;
4589
}
4590
break;
4591
}
4592
#endif /* ALTQ */
4593
4594
case DIOCBEGINADDRS: {
4595
struct pfioc_pooladdr *pp = (struct pfioc_pooladdr *)addr;
4596
4597
error = pf_ioctl_begin_addrs(&pp->ticket);
4598
break;
4599
}
4600
4601
case DIOCADDADDR: {
4602
struct pfioc_pooladdr *pp = (struct pfioc_pooladdr *)addr;
4603
struct pf_nl_pooladdr npp = {};
4604
4605
npp.which = PF_RDR;
4606
memcpy(&npp, pp, sizeof(*pp));
4607
error = pf_ioctl_add_addr(&npp);
4608
break;
4609
}
4610
4611
case DIOCGETADDRS: {
4612
struct pfioc_pooladdr *pp = (struct pfioc_pooladdr *)addr;
4613
struct pf_nl_pooladdr npp = {};
4614
4615
npp.which = PF_RDR;
4616
memcpy(&npp, pp, sizeof(*pp));
4617
error = pf_ioctl_get_addrs(&npp);
4618
memcpy(pp, &npp, sizeof(*pp));
4619
4620
break;
4621
}
4622
4623
case DIOCGETADDR: {
4624
struct pfioc_pooladdr *pp = (struct pfioc_pooladdr *)addr;
4625
struct pf_nl_pooladdr npp = {};
4626
4627
npp.which = PF_RDR;
4628
memcpy(&npp, pp, sizeof(*pp));
4629
error = pf_ioctl_get_addr(&npp);
4630
memcpy(pp, &npp, sizeof(*pp));
4631
4632
break;
4633
}
4634
4635
case DIOCCHANGEADDR: {
4636
struct pfioc_pooladdr *pca = (struct pfioc_pooladdr *)addr;
4637
struct pf_kpool *pool;
4638
struct pf_kpooladdr *oldpa = NULL, *newpa = NULL;
4639
struct pf_kruleset *ruleset;
4640
struct pfi_kkif *kif = NULL;
4641
4642
pca->anchor[sizeof(pca->anchor) - 1] = '\0';
4643
4644
if (pca->action < PF_CHANGE_ADD_HEAD ||
4645
pca->action > PF_CHANGE_REMOVE) {
4646
error = EINVAL;
4647
goto fail;
4648
}
4649
if (pca->addr.addr.type != PF_ADDR_ADDRMASK &&
4650
pca->addr.addr.type != PF_ADDR_DYNIFTL &&
4651
pca->addr.addr.type != PF_ADDR_TABLE) {
4652
error = EINVAL;
4653
goto fail;
4654
}
4655
if (pca->addr.addr.p.dyn != NULL) {
4656
error = EINVAL;
4657
goto fail;
4658
}
4659
4660
if (pca->action != PF_CHANGE_REMOVE) {
4661
#ifndef INET
4662
if (pca->af == AF_INET) {
4663
error = EAFNOSUPPORT;
4664
goto fail;
4665
}
4666
#endif /* INET */
4667
#ifndef INET6
4668
if (pca->af == AF_INET6) {
4669
error = EAFNOSUPPORT;
4670
goto fail;
4671
}
4672
#endif /* INET6 */
4673
newpa = malloc(sizeof(*newpa), M_PFRULE, M_WAITOK);
4674
bcopy(&pca->addr, newpa, sizeof(struct pf_pooladdr));
4675
if (newpa->ifname[0])
4676
kif = pf_kkif_create(M_WAITOK);
4677
newpa->kif = NULL;
4678
}
4679
#define ERROUT(x) ERROUT_IOCTL(DIOCCHANGEADDR_error, x)
4680
PF_RULES_WLOCK();
4681
ruleset = pf_find_kruleset(pca->anchor);
4682
if (ruleset == NULL)
4683
ERROUT(EBUSY);
4684
4685
pool = pf_get_kpool(pca->anchor, pca->ticket, pca->r_action,
4686
pca->r_num, pca->r_last, 1, 1, PF_RDR);
4687
if (pool == NULL)
4688
ERROUT(EBUSY);
4689
4690
if (pca->action != PF_CHANGE_REMOVE) {
4691
if (newpa->ifname[0]) {
4692
newpa->kif = pfi_kkif_attach(kif, newpa->ifname);
4693
pfi_kkif_ref(newpa->kif);
4694
kif = NULL;
4695
}
4696
4697
switch (newpa->addr.type) {
4698
case PF_ADDR_DYNIFTL:
4699
error = pfi_dynaddr_setup(&newpa->addr,
4700
pca->af);
4701
break;
4702
case PF_ADDR_TABLE:
4703
newpa->addr.p.tbl = pfr_attach_table(ruleset,
4704
newpa->addr.v.tblname);
4705
if (newpa->addr.p.tbl == NULL)
4706
error = ENOMEM;
4707
break;
4708
}
4709
if (error)
4710
goto DIOCCHANGEADDR_error;
4711
}
4712
4713
switch (pca->action) {
4714
case PF_CHANGE_ADD_HEAD:
4715
oldpa = TAILQ_FIRST(&pool->list);
4716
break;
4717
case PF_CHANGE_ADD_TAIL:
4718
oldpa = TAILQ_LAST(&pool->list, pf_kpalist);
4719
break;
4720
default:
4721
oldpa = TAILQ_FIRST(&pool->list);
4722
for (int i = 0; oldpa && i < pca->nr; i++)
4723
oldpa = TAILQ_NEXT(oldpa, entries);
4724
4725
if (oldpa == NULL)
4726
ERROUT(EINVAL);
4727
}
4728
4729
if (pca->action == PF_CHANGE_REMOVE) {
4730
TAILQ_REMOVE(&pool->list, oldpa, entries);
4731
switch (oldpa->addr.type) {
4732
case PF_ADDR_DYNIFTL:
4733
pfi_dynaddr_remove(oldpa->addr.p.dyn);
4734
break;
4735
case PF_ADDR_TABLE:
4736
pfr_detach_table(oldpa->addr.p.tbl);
4737
break;
4738
}
4739
if (oldpa->kif)
4740
pfi_kkif_unref(oldpa->kif);
4741
free(oldpa, M_PFRULE);
4742
} else {
4743
if (oldpa == NULL)
4744
TAILQ_INSERT_TAIL(&pool->list, newpa, entries);
4745
else if (pca->action == PF_CHANGE_ADD_HEAD ||
4746
pca->action == PF_CHANGE_ADD_BEFORE)
4747
TAILQ_INSERT_BEFORE(oldpa, newpa, entries);
4748
else
4749
TAILQ_INSERT_AFTER(&pool->list, oldpa,
4750
newpa, entries);
4751
}
4752
4753
pool->cur = TAILQ_FIRST(&pool->list);
4754
pf_addrcpy(&pool->counter, &pool->cur->addr.v.a.addr, pca->af);
4755
PF_RULES_WUNLOCK();
4756
break;
4757
4758
#undef ERROUT
4759
DIOCCHANGEADDR_error:
4760
if (newpa != NULL) {
4761
if (newpa->kif)
4762
pfi_kkif_unref(newpa->kif);
4763
free(newpa, M_PFRULE);
4764
}
4765
PF_RULES_WUNLOCK();
4766
pf_kkif_free(kif);
4767
break;
4768
}
4769
4770
case DIOCGETRULESETS: {
4771
struct pfioc_ruleset *pr = (struct pfioc_ruleset *)addr;
4772
4773
pr->path[sizeof(pr->path) - 1] = '\0';
4774
4775
error = pf_ioctl_get_rulesets(pr);
4776
break;
4777
}
4778
4779
case DIOCGETRULESET: {
4780
struct pfioc_ruleset *pr = (struct pfioc_ruleset *)addr;
4781
4782
pr->path[sizeof(pr->path) - 1] = '\0';
4783
4784
error = pf_ioctl_get_ruleset(pr);
4785
break;
4786
}
4787
4788
case DIOCRCLRTABLES: {
4789
struct pfioc_table *io = (struct pfioc_table *)addr;
4790
4791
if (io->pfrio_esize != 0) {
4792
error = ENODEV;
4793
goto fail;
4794
}
4795
PF_RULES_WLOCK();
4796
error = pfr_clr_tables(&io->pfrio_table, &io->pfrio_ndel,
4797
io->pfrio_flags | PFR_FLAG_USERIOCTL);
4798
PF_RULES_WUNLOCK();
4799
break;
4800
}
4801
4802
case DIOCRADDTABLES: {
4803
struct pfioc_table *io = (struct pfioc_table *)addr;
4804
struct pfr_table *pfrts;
4805
size_t totlen;
4806
4807
if (io->pfrio_esize != sizeof(struct pfr_table)) {
4808
error = ENODEV;
4809
goto fail;
4810
}
4811
4812
if (io->pfrio_size < 0 || io->pfrio_size > pf_ioctl_maxcount ||
4813
WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_table))) {
4814
error = ENOMEM;
4815
goto fail;
4816
}
4817
4818
totlen = io->pfrio_size * sizeof(struct pfr_table);
4819
pfrts = mallocarray(io->pfrio_size, sizeof(struct pfr_table),
4820
M_PF, M_WAITOK);
4821
error = copyin(io->pfrio_buffer, pfrts, totlen);
4822
if (error) {
4823
free(pfrts, M_PF);
4824
goto fail;
4825
}
4826
PF_RULES_WLOCK();
4827
error = pfr_add_tables(pfrts, io->pfrio_size,
4828
&io->pfrio_nadd, io->pfrio_flags | PFR_FLAG_USERIOCTL);
4829
PF_RULES_WUNLOCK();
4830
free(pfrts, M_PF);
4831
break;
4832
}
4833
4834
case DIOCRDELTABLES: {
4835
struct pfioc_table *io = (struct pfioc_table *)addr;
4836
struct pfr_table *pfrts;
4837
size_t totlen;
4838
4839
if (io->pfrio_esize != sizeof(struct pfr_table)) {
4840
error = ENODEV;
4841
goto fail;
4842
}
4843
4844
if (io->pfrio_size < 0 || io->pfrio_size > pf_ioctl_maxcount ||
4845
WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_table))) {
4846
error = ENOMEM;
4847
goto fail;
4848
}
4849
4850
totlen = io->pfrio_size * sizeof(struct pfr_table);
4851
pfrts = mallocarray(io->pfrio_size, sizeof(struct pfr_table),
4852
M_PF, M_WAITOK);
4853
error = copyin(io->pfrio_buffer, pfrts, totlen);
4854
if (error) {
4855
free(pfrts, M_PF);
4856
goto fail;
4857
}
4858
PF_RULES_WLOCK();
4859
error = pfr_del_tables(pfrts, io->pfrio_size,
4860
&io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL);
4861
PF_RULES_WUNLOCK();
4862
free(pfrts, M_PF);
4863
break;
4864
}
4865
4866
case DIOCRGETTABLES: {
4867
struct pfioc_table *io = (struct pfioc_table *)addr;
4868
struct pfr_table *pfrts;
4869
size_t totlen;
4870
int n;
4871
4872
if (io->pfrio_esize != sizeof(struct pfr_table)) {
4873
error = ENODEV;
4874
goto fail;
4875
}
4876
PF_RULES_RLOCK();
4877
n = pfr_table_count(&io->pfrio_table, io->pfrio_flags);
4878
if (n < 0) {
4879
PF_RULES_RUNLOCK();
4880
error = EINVAL;
4881
goto fail;
4882
}
4883
io->pfrio_size = min(io->pfrio_size, n);
4884
4885
totlen = io->pfrio_size * sizeof(struct pfr_table);
4886
4887
pfrts = mallocarray(io->pfrio_size, sizeof(struct pfr_table),
4888
M_PF, M_NOWAIT | M_ZERO);
4889
if (pfrts == NULL) {
4890
error = ENOMEM;
4891
PF_RULES_RUNLOCK();
4892
goto fail;
4893
}
4894
error = pfr_get_tables(&io->pfrio_table, pfrts,
4895
&io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
4896
PF_RULES_RUNLOCK();
4897
if (error == 0)
4898
error = copyout(pfrts, io->pfrio_buffer, totlen);
4899
free(pfrts, M_PF);
4900
break;
4901
}
4902
4903
case DIOCRGETTSTATS: {
4904
struct pfioc_table *io = (struct pfioc_table *)addr;
4905
struct pfr_tstats *pfrtstats;
4906
size_t totlen;
4907
int n;
4908
4909
if (io->pfrio_esize != sizeof(struct pfr_tstats)) {
4910
error = ENODEV;
4911
goto fail;
4912
}
4913
PF_TABLE_STATS_LOCK();
4914
PF_RULES_RLOCK();
4915
n = pfr_table_count(&io->pfrio_table, io->pfrio_flags);
4916
if (n < 0) {
4917
PF_RULES_RUNLOCK();
4918
PF_TABLE_STATS_UNLOCK();
4919
error = EINVAL;
4920
goto fail;
4921
}
4922
io->pfrio_size = min(io->pfrio_size, n);
4923
4924
totlen = io->pfrio_size * sizeof(struct pfr_tstats);
4925
pfrtstats = mallocarray(io->pfrio_size,
4926
sizeof(struct pfr_tstats), M_PF, M_NOWAIT | M_ZERO);
4927
if (pfrtstats == NULL) {
4928
error = ENOMEM;
4929
PF_RULES_RUNLOCK();
4930
PF_TABLE_STATS_UNLOCK();
4931
goto fail;
4932
}
4933
error = pfr_get_tstats(&io->pfrio_table, pfrtstats,
4934
&io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
4935
PF_RULES_RUNLOCK();
4936
PF_TABLE_STATS_UNLOCK();
4937
if (error == 0)
4938
error = copyout(pfrtstats, io->pfrio_buffer, totlen);
4939
free(pfrtstats, M_PF);
4940
break;
4941
}
4942
4943
case DIOCRCLRTSTATS: {
4944
struct pfioc_table *io = (struct pfioc_table *)addr;
4945
struct pfr_table *pfrts;
4946
size_t totlen;
4947
4948
if (io->pfrio_esize != sizeof(struct pfr_table)) {
4949
error = ENODEV;
4950
goto fail;
4951
}
4952
4953
if (io->pfrio_size < 0 || io->pfrio_size > pf_ioctl_maxcount ||
4954
WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_table))) {
4955
/* We used to count tables and use the minimum required
4956
* size, so we didn't fail on overly large requests.
4957
* Keep doing so. */
4958
io->pfrio_size = pf_ioctl_maxcount;
4959
goto fail;
4960
}
4961
4962
totlen = io->pfrio_size * sizeof(struct pfr_table);
4963
pfrts = mallocarray(io->pfrio_size, sizeof(struct pfr_table),
4964
M_PF, M_WAITOK);
4965
error = copyin(io->pfrio_buffer, pfrts, totlen);
4966
if (error) {
4967
free(pfrts, M_PF);
4968
goto fail;
4969
}
4970
4971
PF_TABLE_STATS_LOCK();
4972
PF_RULES_RLOCK();
4973
error = pfr_clr_tstats(pfrts, io->pfrio_size,
4974
&io->pfrio_nzero, io->pfrio_flags | PFR_FLAG_USERIOCTL);
4975
PF_RULES_RUNLOCK();
4976
PF_TABLE_STATS_UNLOCK();
4977
free(pfrts, M_PF);
4978
break;
4979
}
4980
4981
case DIOCRSETTFLAGS: {
4982
struct pfioc_table *io = (struct pfioc_table *)addr;
4983
struct pfr_table *pfrts;
4984
size_t totlen;
4985
int n;
4986
4987
if (io->pfrio_esize != sizeof(struct pfr_table)) {
4988
error = ENODEV;
4989
goto fail;
4990
}
4991
4992
PF_RULES_RLOCK();
4993
n = pfr_table_count(&io->pfrio_table, io->pfrio_flags);
4994
if (n < 0) {
4995
PF_RULES_RUNLOCK();
4996
error = EINVAL;
4997
goto fail;
4998
}
4999
5000
io->pfrio_size = min(io->pfrio_size, n);
5001
PF_RULES_RUNLOCK();
5002
5003
totlen = io->pfrio_size * sizeof(struct pfr_table);
5004
pfrts = mallocarray(io->pfrio_size, sizeof(struct pfr_table),
5005
M_PF, M_WAITOK);
5006
error = copyin(io->pfrio_buffer, pfrts, totlen);
5007
if (error) {
5008
free(pfrts, M_PF);
5009
goto fail;
5010
}
5011
PF_RULES_WLOCK();
5012
error = pfr_set_tflags(pfrts, io->pfrio_size,
5013
io->pfrio_setflag, io->pfrio_clrflag, &io->pfrio_nchange,
5014
&io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL);
5015
PF_RULES_WUNLOCK();
5016
free(pfrts, M_PF);
5017
break;
5018
}
5019
5020
case DIOCRCLRADDRS: {
5021
struct pfioc_table *io = (struct pfioc_table *)addr;
5022
5023
if (io->pfrio_esize != 0) {
5024
error = ENODEV;
5025
goto fail;
5026
}
5027
PF_RULES_WLOCK();
5028
error = pfr_clr_addrs(&io->pfrio_table, &io->pfrio_ndel,
5029
io->pfrio_flags | PFR_FLAG_USERIOCTL);
5030
PF_RULES_WUNLOCK();
5031
break;
5032
}
5033
5034
case DIOCRADDADDRS: {
5035
struct pfioc_table *io = (struct pfioc_table *)addr;
5036
struct pfr_addr *pfras;
5037
size_t totlen;
5038
5039
if (io->pfrio_esize != sizeof(struct pfr_addr)) {
5040
error = ENODEV;
5041
goto fail;
5042
}
5043
if (io->pfrio_size < 0 ||
5044
io->pfrio_size > pf_ioctl_maxcount ||
5045
WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_addr))) {
5046
error = EINVAL;
5047
goto fail;
5048
}
5049
totlen = io->pfrio_size * sizeof(struct pfr_addr);
5050
pfras = mallocarray(io->pfrio_size, sizeof(struct pfr_addr),
5051
M_PF, M_WAITOK);
5052
error = copyin(io->pfrio_buffer, pfras, totlen);
5053
if (error) {
5054
free(pfras, M_PF);
5055
goto fail;
5056
}
5057
PF_RULES_WLOCK();
5058
io->pfrio_nadd = 0;
5059
error = pfr_add_addrs(&io->pfrio_table, pfras,
5060
io->pfrio_size, &io->pfrio_nadd, io->pfrio_flags |
5061
PFR_FLAG_USERIOCTL);
5062
PF_RULES_WUNLOCK();
5063
if (error == 0 && io->pfrio_flags & PFR_FLAG_FEEDBACK)
5064
error = copyout(pfras, io->pfrio_buffer, totlen);
5065
free(pfras, M_PF);
5066
break;
5067
}
5068
5069
case DIOCRDELADDRS: {
5070
struct pfioc_table *io = (struct pfioc_table *)addr;
5071
struct pfr_addr *pfras;
5072
size_t totlen;
5073
5074
if (io->pfrio_esize != sizeof(struct pfr_addr)) {
5075
error = ENODEV;
5076
goto fail;
5077
}
5078
if (io->pfrio_size < 0 ||
5079
io->pfrio_size > pf_ioctl_maxcount ||
5080
WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_addr))) {
5081
error = EINVAL;
5082
goto fail;
5083
}
5084
totlen = io->pfrio_size * sizeof(struct pfr_addr);
5085
pfras = mallocarray(io->pfrio_size, sizeof(struct pfr_addr),
5086
M_PF, M_WAITOK);
5087
error = copyin(io->pfrio_buffer, pfras, totlen);
5088
if (error) {
5089
free(pfras, M_PF);
5090
goto fail;
5091
}
5092
PF_RULES_WLOCK();
5093
error = pfr_del_addrs(&io->pfrio_table, pfras,
5094
io->pfrio_size, &io->pfrio_ndel, io->pfrio_flags |
5095
PFR_FLAG_USERIOCTL);
5096
PF_RULES_WUNLOCK();
5097
if (error == 0 && io->pfrio_flags & PFR_FLAG_FEEDBACK)
5098
error = copyout(pfras, io->pfrio_buffer, totlen);
5099
free(pfras, M_PF);
5100
break;
5101
}
5102
5103
case DIOCRSETADDRS: {
5104
struct pfioc_table *io = (struct pfioc_table *)addr;
5105
struct pfr_addr *pfras;
5106
size_t totlen, count;
5107
5108
if (io->pfrio_esize != sizeof(struct pfr_addr)) {
5109
error = ENODEV;
5110
goto fail;
5111
}
5112
if (io->pfrio_size < 0 || io->pfrio_size2 < 0) {
5113
error = EINVAL;
5114
goto fail;
5115
}
5116
count = max(io->pfrio_size, io->pfrio_size2);
5117
if (count > pf_ioctl_maxcount ||
5118
WOULD_OVERFLOW(count, sizeof(struct pfr_addr))) {
5119
error = EINVAL;
5120
goto fail;
5121
}
5122
totlen = count * sizeof(struct pfr_addr);
5123
pfras = mallocarray(count, sizeof(struct pfr_addr), M_PF,
5124
M_WAITOK);
5125
error = copyin(io->pfrio_buffer, pfras, totlen);
5126
if (error) {
5127
free(pfras, M_PF);
5128
goto fail;
5129
}
5130
PF_RULES_WLOCK();
5131
error = pfr_set_addrs(&io->pfrio_table, pfras,
5132
io->pfrio_size, &io->pfrio_size2, &io->pfrio_nadd,
5133
&io->pfrio_ndel, &io->pfrio_nchange, io->pfrio_flags |
5134
PFR_FLAG_USERIOCTL, 0);
5135
PF_RULES_WUNLOCK();
5136
if (error == 0 && io->pfrio_flags & PFR_FLAG_FEEDBACK)
5137
error = copyout(pfras, io->pfrio_buffer, totlen);
5138
free(pfras, M_PF);
5139
break;
5140
}
5141
5142
case DIOCRGETADDRS: {
5143
struct pfioc_table *io = (struct pfioc_table *)addr;
5144
struct pfr_addr *pfras;
5145
size_t totlen;
5146
5147
if (io->pfrio_esize != sizeof(struct pfr_addr)) {
5148
error = ENODEV;
5149
goto fail;
5150
}
5151
if (io->pfrio_size < 0 ||
5152
io->pfrio_size > pf_ioctl_maxcount ||
5153
WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_addr))) {
5154
error = EINVAL;
5155
goto fail;
5156
}
5157
totlen = io->pfrio_size * sizeof(struct pfr_addr);
5158
pfras = mallocarray(io->pfrio_size, sizeof(struct pfr_addr),
5159
M_PF, M_WAITOK | M_ZERO);
5160
PF_RULES_RLOCK();
5161
error = pfr_get_addrs(&io->pfrio_table, pfras,
5162
&io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
5163
PF_RULES_RUNLOCK();
5164
if (error == 0)
5165
error = copyout(pfras, io->pfrio_buffer, totlen);
5166
free(pfras, M_PF);
5167
break;
5168
}
5169
5170
case DIOCRGETASTATS: {
5171
struct pfioc_table *io = (struct pfioc_table *)addr;
5172
struct pfr_astats *pfrastats;
5173
size_t totlen;
5174
5175
if (io->pfrio_esize != sizeof(struct pfr_astats)) {
5176
error = ENODEV;
5177
goto fail;
5178
}
5179
if (io->pfrio_size < 0 ||
5180
io->pfrio_size > pf_ioctl_maxcount ||
5181
WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_astats))) {
5182
error = EINVAL;
5183
goto fail;
5184
}
5185
totlen = io->pfrio_size * sizeof(struct pfr_astats);
5186
pfrastats = mallocarray(io->pfrio_size,
5187
sizeof(struct pfr_astats), M_PF, M_WAITOK | M_ZERO);
5188
PF_RULES_RLOCK();
5189
error = pfr_get_astats(&io->pfrio_table, pfrastats,
5190
&io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
5191
PF_RULES_RUNLOCK();
5192
if (error == 0)
5193
error = copyout(pfrastats, io->pfrio_buffer, totlen);
5194
free(pfrastats, M_PF);
5195
break;
5196
}
5197
5198
case DIOCRCLRASTATS: {
5199
struct pfioc_table *io = (struct pfioc_table *)addr;
5200
struct pfr_addr *pfras;
5201
size_t totlen;
5202
5203
if (io->pfrio_esize != sizeof(struct pfr_addr)) {
5204
error = ENODEV;
5205
goto fail;
5206
}
5207
if (io->pfrio_size < 0 ||
5208
io->pfrio_size > pf_ioctl_maxcount ||
5209
WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_addr))) {
5210
error = EINVAL;
5211
goto fail;
5212
}
5213
totlen = io->pfrio_size * sizeof(struct pfr_addr);
5214
pfras = mallocarray(io->pfrio_size, sizeof(struct pfr_addr),
5215
M_PF, M_WAITOK);
5216
error = copyin(io->pfrio_buffer, pfras, totlen);
5217
if (error) {
5218
free(pfras, M_PF);
5219
goto fail;
5220
}
5221
PF_RULES_WLOCK();
5222
error = pfr_clr_astats(&io->pfrio_table, pfras,
5223
io->pfrio_size, &io->pfrio_nzero, io->pfrio_flags |
5224
PFR_FLAG_USERIOCTL);
5225
PF_RULES_WUNLOCK();
5226
if (error == 0 && io->pfrio_flags & PFR_FLAG_FEEDBACK)
5227
error = copyout(pfras, io->pfrio_buffer, totlen);
5228
free(pfras, M_PF);
5229
break;
5230
}
5231
5232
case DIOCRTSTADDRS: {
5233
struct pfioc_table *io = (struct pfioc_table *)addr;
5234
struct pfr_addr *pfras;
5235
size_t totlen;
5236
5237
if (io->pfrio_esize != sizeof(struct pfr_addr)) {
5238
error = ENODEV;
5239
goto fail;
5240
}
5241
if (io->pfrio_size < 0 ||
5242
io->pfrio_size > pf_ioctl_maxcount ||
5243
WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_addr))) {
5244
error = EINVAL;
5245
goto fail;
5246
}
5247
totlen = io->pfrio_size * sizeof(struct pfr_addr);
5248
pfras = mallocarray(io->pfrio_size, sizeof(struct pfr_addr),
5249
M_PF, M_WAITOK);
5250
error = copyin(io->pfrio_buffer, pfras, totlen);
5251
if (error) {
5252
free(pfras, M_PF);
5253
goto fail;
5254
}
5255
PF_RULES_RLOCK();
5256
error = pfr_tst_addrs(&io->pfrio_table, pfras,
5257
io->pfrio_size, &io->pfrio_nmatch, io->pfrio_flags |
5258
PFR_FLAG_USERIOCTL);
5259
PF_RULES_RUNLOCK();
5260
if (error == 0)
5261
error = copyout(pfras, io->pfrio_buffer, totlen);
5262
free(pfras, M_PF);
5263
break;
5264
}
5265
5266
case DIOCRINADEFINE: {
5267
struct pfioc_table *io = (struct pfioc_table *)addr;
5268
struct pfr_addr *pfras;
5269
size_t totlen;
5270
5271
if (io->pfrio_esize != sizeof(struct pfr_addr)) {
5272
error = ENODEV;
5273
goto fail;
5274
}
5275
if (io->pfrio_size < 0 ||
5276
io->pfrio_size > pf_ioctl_maxcount ||
5277
WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_addr))) {
5278
error = EINVAL;
5279
goto fail;
5280
}
5281
totlen = io->pfrio_size * sizeof(struct pfr_addr);
5282
pfras = mallocarray(io->pfrio_size, sizeof(struct pfr_addr),
5283
M_PF, M_WAITOK);
5284
error = copyin(io->pfrio_buffer, pfras, totlen);
5285
if (error) {
5286
free(pfras, M_PF);
5287
goto fail;
5288
}
5289
PF_RULES_WLOCK();
5290
error = pfr_ina_define(&io->pfrio_table, pfras,
5291
io->pfrio_size, &io->pfrio_nadd, &io->pfrio_naddr,
5292
io->pfrio_ticket, io->pfrio_flags | PFR_FLAG_USERIOCTL);
5293
PF_RULES_WUNLOCK();
5294
free(pfras, M_PF);
5295
break;
5296
}
5297
5298
case DIOCOSFPADD: {
5299
struct pf_osfp_ioctl *io = (struct pf_osfp_ioctl *)addr;
5300
PF_RULES_WLOCK();
5301
error = pf_osfp_add(io);
5302
PF_RULES_WUNLOCK();
5303
break;
5304
}
5305
5306
case DIOCOSFPGET: {
5307
struct pf_osfp_ioctl *io = (struct pf_osfp_ioctl *)addr;
5308
PF_RULES_RLOCK();
5309
error = pf_osfp_get(io);
5310
PF_RULES_RUNLOCK();
5311
break;
5312
}
5313
5314
case DIOCXBEGIN: {
5315
struct pfioc_trans *io = (struct pfioc_trans *)addr;
5316
struct pfioc_trans_e *ioes, *ioe;
5317
size_t totlen;
5318
int i;
5319
5320
if (io->esize != sizeof(*ioe)) {
5321
error = ENODEV;
5322
goto fail;
5323
}
5324
if (io->size < 0 ||
5325
io->size > pf_ioctl_maxcount ||
5326
WOULD_OVERFLOW(io->size, sizeof(struct pfioc_trans_e))) {
5327
error = EINVAL;
5328
goto fail;
5329
}
5330
totlen = sizeof(struct pfioc_trans_e) * io->size;
5331
ioes = mallocarray(io->size, sizeof(struct pfioc_trans_e),
5332
M_PF, M_WAITOK);
5333
error = copyin(io->array, ioes, totlen);
5334
if (error) {
5335
free(ioes, M_PF);
5336
goto fail;
5337
}
5338
PF_RULES_WLOCK();
5339
for (i = 0, ioe = ioes; i < io->size; i++, ioe++) {
5340
ioe->anchor[sizeof(ioe->anchor) - 1] = '\0';
5341
switch (ioe->rs_num) {
5342
case PF_RULESET_ETH:
5343
if ((error = pf_begin_eth(&ioe->ticket, ioe->anchor))) {
5344
PF_RULES_WUNLOCK();
5345
free(ioes, M_PF);
5346
goto fail;
5347
}
5348
break;
5349
#ifdef ALTQ
5350
case PF_RULESET_ALTQ:
5351
if (ioe->anchor[0]) {
5352
PF_RULES_WUNLOCK();
5353
free(ioes, M_PF);
5354
error = EINVAL;
5355
goto fail;
5356
}
5357
if ((error = pf_begin_altq(&ioe->ticket))) {
5358
PF_RULES_WUNLOCK();
5359
free(ioes, M_PF);
5360
goto fail;
5361
}
5362
break;
5363
#endif /* ALTQ */
5364
case PF_RULESET_TABLE:
5365
{
5366
struct pfr_table table;
5367
5368
bzero(&table, sizeof(table));
5369
strlcpy(table.pfrt_anchor, ioe->anchor,
5370
sizeof(table.pfrt_anchor));
5371
if ((error = pfr_ina_begin(&table,
5372
&ioe->ticket, NULL, 0))) {
5373
PF_RULES_WUNLOCK();
5374
free(ioes, M_PF);
5375
goto fail;
5376
}
5377
break;
5378
}
5379
default:
5380
if ((error = pf_begin_rules(&ioe->ticket,
5381
ioe->rs_num, ioe->anchor))) {
5382
PF_RULES_WUNLOCK();
5383
free(ioes, M_PF);
5384
goto fail;
5385
}
5386
break;
5387
}
5388
}
5389
PF_RULES_WUNLOCK();
5390
error = copyout(ioes, io->array, totlen);
5391
free(ioes, M_PF);
5392
break;
5393
}
5394
5395
case DIOCXROLLBACK: {
5396
struct pfioc_trans *io = (struct pfioc_trans *)addr;
5397
struct pfioc_trans_e *ioe, *ioes;
5398
size_t totlen;
5399
int i;
5400
5401
if (io->esize != sizeof(*ioe)) {
5402
error = ENODEV;
5403
goto fail;
5404
}
5405
if (io->size < 0 ||
5406
io->size > pf_ioctl_maxcount ||
5407
WOULD_OVERFLOW(io->size, sizeof(struct pfioc_trans_e))) {
5408
error = EINVAL;
5409
goto fail;
5410
}
5411
totlen = sizeof(struct pfioc_trans_e) * io->size;
5412
ioes = mallocarray(io->size, sizeof(struct pfioc_trans_e),
5413
M_PF, M_WAITOK);
5414
error = copyin(io->array, ioes, totlen);
5415
if (error) {
5416
free(ioes, M_PF);
5417
goto fail;
5418
}
5419
PF_RULES_WLOCK();
5420
for (i = 0, ioe = ioes; i < io->size; i++, ioe++) {
5421
ioe->anchor[sizeof(ioe->anchor) - 1] = '\0';
5422
switch (ioe->rs_num) {
5423
case PF_RULESET_ETH:
5424
if ((error = pf_rollback_eth(ioe->ticket,
5425
ioe->anchor))) {
5426
PF_RULES_WUNLOCK();
5427
free(ioes, M_PF);
5428
goto fail; /* really bad */
5429
}
5430
break;
5431
#ifdef ALTQ
5432
case PF_RULESET_ALTQ:
5433
if (ioe->anchor[0]) {
5434
PF_RULES_WUNLOCK();
5435
free(ioes, M_PF);
5436
error = EINVAL;
5437
goto fail;
5438
}
5439
if ((error = pf_rollback_altq(ioe->ticket))) {
5440
PF_RULES_WUNLOCK();
5441
free(ioes, M_PF);
5442
goto fail; /* really bad */
5443
}
5444
break;
5445
#endif /* ALTQ */
5446
case PF_RULESET_TABLE:
5447
{
5448
struct pfr_table table;
5449
5450
bzero(&table, sizeof(table));
5451
strlcpy(table.pfrt_anchor, ioe->anchor,
5452
sizeof(table.pfrt_anchor));
5453
if ((error = pfr_ina_rollback(&table,
5454
ioe->ticket, NULL, 0))) {
5455
PF_RULES_WUNLOCK();
5456
free(ioes, M_PF);
5457
goto fail; /* really bad */
5458
}
5459
break;
5460
}
5461
default:
5462
if ((error = pf_rollback_rules(ioe->ticket,
5463
ioe->rs_num, ioe->anchor))) {
5464
PF_RULES_WUNLOCK();
5465
free(ioes, M_PF);
5466
goto fail; /* really bad */
5467
}
5468
break;
5469
}
5470
}
5471
PF_RULES_WUNLOCK();
5472
free(ioes, M_PF);
5473
break;
5474
}
5475
5476
case DIOCXCOMMIT: {
5477
struct pfioc_trans *io = (struct pfioc_trans *)addr;
5478
struct pfioc_trans_e *ioe, *ioes;
5479
struct pf_kruleset *rs;
5480
struct pf_keth_ruleset *ers;
5481
size_t totlen;
5482
int i;
5483
5484
if (io->esize != sizeof(*ioe)) {
5485
error = ENODEV;
5486
goto fail;
5487
}
5488
5489
if (io->size < 0 ||
5490
io->size > pf_ioctl_maxcount ||
5491
WOULD_OVERFLOW(io->size, sizeof(struct pfioc_trans_e))) {
5492
error = EINVAL;
5493
goto fail;
5494
}
5495
5496
totlen = sizeof(struct pfioc_trans_e) * io->size;
5497
ioes = mallocarray(io->size, sizeof(struct pfioc_trans_e),
5498
M_PF, M_WAITOK);
5499
error = copyin(io->array, ioes, totlen);
5500
if (error) {
5501
free(ioes, M_PF);
5502
goto fail;
5503
}
5504
PF_RULES_WLOCK();
5505
/* First makes sure everything will succeed. */
5506
for (i = 0, ioe = ioes; i < io->size; i++, ioe++) {
5507
ioe->anchor[sizeof(ioe->anchor) - 1] = '\0';
5508
switch (ioe->rs_num) {
5509
case PF_RULESET_ETH:
5510
ers = pf_find_keth_ruleset(ioe->anchor);
5511
if (ers == NULL || ioe->ticket == 0 ||
5512
ioe->ticket != ers->inactive.ticket) {
5513
PF_RULES_WUNLOCK();
5514
free(ioes, M_PF);
5515
error = EINVAL;
5516
goto fail;
5517
}
5518
break;
5519
#ifdef ALTQ
5520
case PF_RULESET_ALTQ:
5521
if (ioe->anchor[0]) {
5522
PF_RULES_WUNLOCK();
5523
free(ioes, M_PF);
5524
error = EINVAL;
5525
goto fail;
5526
}
5527
if (!V_altqs_inactive_open || ioe->ticket !=
5528
V_ticket_altqs_inactive) {
5529
PF_RULES_WUNLOCK();
5530
free(ioes, M_PF);
5531
error = EBUSY;
5532
goto fail;
5533
}
5534
break;
5535
#endif /* ALTQ */
5536
case PF_RULESET_TABLE:
5537
rs = pf_find_kruleset(ioe->anchor);
5538
if (rs == NULL || !rs->topen || ioe->ticket !=
5539
rs->tticket) {
5540
PF_RULES_WUNLOCK();
5541
free(ioes, M_PF);
5542
error = EBUSY;
5543
goto fail;
5544
}
5545
break;
5546
default:
5547
if (ioe->rs_num < 0 || ioe->rs_num >=
5548
PF_RULESET_MAX) {
5549
PF_RULES_WUNLOCK();
5550
free(ioes, M_PF);
5551
error = EINVAL;
5552
goto fail;
5553
}
5554
rs = pf_find_kruleset(ioe->anchor);
5555
if (rs == NULL ||
5556
!rs->rules[ioe->rs_num].inactive.open ||
5557
rs->rules[ioe->rs_num].inactive.ticket !=
5558
ioe->ticket) {
5559
PF_RULES_WUNLOCK();
5560
free(ioes, M_PF);
5561
error = EBUSY;
5562
goto fail;
5563
}
5564
break;
5565
}
5566
}
5567
/* Now do the commit - no errors should happen here. */
5568
for (i = 0, ioe = ioes; i < io->size; i++, ioe++) {
5569
switch (ioe->rs_num) {
5570
case PF_RULESET_ETH:
5571
if ((error = pf_commit_eth(ioe->ticket, ioe->anchor))) {
5572
PF_RULES_WUNLOCK();
5573
free(ioes, M_PF);
5574
goto fail; /* really bad */
5575
}
5576
break;
5577
#ifdef ALTQ
5578
case PF_RULESET_ALTQ:
5579
if ((error = pf_commit_altq(ioe->ticket))) {
5580
PF_RULES_WUNLOCK();
5581
free(ioes, M_PF);
5582
goto fail; /* really bad */
5583
}
5584
break;
5585
#endif /* ALTQ */
5586
case PF_RULESET_TABLE:
5587
{
5588
struct pfr_table table;
5589
5590
bzero(&table, sizeof(table));
5591
(void)strlcpy(table.pfrt_anchor, ioe->anchor,
5592
sizeof(table.pfrt_anchor));
5593
if ((error = pfr_ina_commit(&table,
5594
ioe->ticket, NULL, NULL, 0))) {
5595
PF_RULES_WUNLOCK();
5596
free(ioes, M_PF);
5597
goto fail; /* really bad */
5598
}
5599
break;
5600
}
5601
default:
5602
if ((error = pf_commit_rules(ioe->ticket,
5603
ioe->rs_num, ioe->anchor))) {
5604
PF_RULES_WUNLOCK();
5605
free(ioes, M_PF);
5606
goto fail; /* really bad */
5607
}
5608
break;
5609
}
5610
}
5611
PF_RULES_WUNLOCK();
5612
5613
/* Only hook into EtherNet taffic if we've got rules for it. */
5614
if (! TAILQ_EMPTY(V_pf_keth->active.rules))
5615
hook_pf_eth();
5616
else
5617
dehook_pf_eth();
5618
5619
free(ioes, M_PF);
5620
break;
5621
}
5622
5623
case DIOCGETSRCNODES: {
5624
struct pfioc_src_nodes *psn = (struct pfioc_src_nodes *)addr;
5625
struct pf_srchash *sh;
5626
struct pf_ksrc_node *n;
5627
struct pf_src_node *p, *pstore;
5628
uint32_t i, nr = 0;
5629
5630
for (i = 0, sh = V_pf_srchash; i <= V_pf_srchashmask;
5631
i++, sh++) {
5632
PF_HASHROW_LOCK(sh);
5633
LIST_FOREACH(n, &sh->nodes, entry)
5634
nr++;
5635
PF_HASHROW_UNLOCK(sh);
5636
}
5637
5638
psn->psn_len = min(psn->psn_len,
5639
sizeof(struct pf_src_node) * nr);
5640
5641
if (psn->psn_len == 0) {
5642
psn->psn_len = sizeof(struct pf_src_node) * nr;
5643
goto fail;
5644
}
5645
5646
nr = 0;
5647
5648
p = pstore = malloc(psn->psn_len, M_PF, M_WAITOK | M_ZERO);
5649
for (i = 0, sh = V_pf_srchash; i <= V_pf_srchashmask;
5650
i++, sh++) {
5651
PF_HASHROW_LOCK(sh);
5652
LIST_FOREACH(n, &sh->nodes, entry) {
5653
5654
if ((nr + 1) * sizeof(*p) > (unsigned)psn->psn_len)
5655
break;
5656
5657
pf_src_node_copy(n, p);
5658
5659
p++;
5660
nr++;
5661
}
5662
PF_HASHROW_UNLOCK(sh);
5663
}
5664
error = copyout(pstore, psn->psn_src_nodes,
5665
sizeof(struct pf_src_node) * nr);
5666
if (error) {
5667
free(pstore, M_PF);
5668
goto fail;
5669
}
5670
psn->psn_len = sizeof(struct pf_src_node) * nr;
5671
free(pstore, M_PF);
5672
break;
5673
}
5674
5675
case DIOCCLRSRCNODES: {
5676
pf_kill_srcnodes(NULL);
5677
break;
5678
}
5679
5680
case DIOCKILLSRCNODES:
5681
pf_kill_srcnodes((struct pfioc_src_node_kill *)addr);
5682
break;
5683
5684
#ifdef COMPAT_FREEBSD13
5685
case DIOCKEEPCOUNTERS_FREEBSD13:
5686
#endif
5687
case DIOCKEEPCOUNTERS:
5688
error = pf_keepcounters((struct pfioc_nv *)addr);
5689
break;
5690
5691
case DIOCGETSYNCOOKIES:
5692
error = pf_get_syncookies((struct pfioc_nv *)addr);
5693
break;
5694
5695
case DIOCSETSYNCOOKIES:
5696
error = pf_set_syncookies((struct pfioc_nv *)addr);
5697
break;
5698
5699
case DIOCSETHOSTID: {
5700
u_int32_t *hostid = (u_int32_t *)addr;
5701
5702
PF_RULES_WLOCK();
5703
if (*hostid == 0)
5704
V_pf_status.hostid = arc4random();
5705
else
5706
V_pf_status.hostid = *hostid;
5707
PF_RULES_WUNLOCK();
5708
break;
5709
}
5710
5711
case DIOCOSFPFLUSH:
5712
PF_RULES_WLOCK();
5713
pf_osfp_flush();
5714
PF_RULES_WUNLOCK();
5715
break;
5716
5717
case DIOCIGETIFACES: {
5718
struct pfioc_iface *io = (struct pfioc_iface *)addr;
5719
struct pfi_kif *ifstore;
5720
size_t bufsiz;
5721
5722
if (io->pfiio_esize != sizeof(struct pfi_kif)) {
5723
error = ENODEV;
5724
goto fail;
5725
}
5726
5727
if (io->pfiio_size < 0 ||
5728
io->pfiio_size > pf_ioctl_maxcount ||
5729
WOULD_OVERFLOW(io->pfiio_size, sizeof(struct pfi_kif))) {
5730
error = EINVAL;
5731
goto fail;
5732
}
5733
5734
io->pfiio_name[sizeof(io->pfiio_name) - 1] = '\0';
5735
5736
bufsiz = io->pfiio_size * sizeof(struct pfi_kif);
5737
ifstore = mallocarray(io->pfiio_size, sizeof(struct pfi_kif),
5738
M_PF, M_WAITOK | M_ZERO);
5739
5740
PF_RULES_RLOCK();
5741
pfi_get_ifaces(io->pfiio_name, ifstore, &io->pfiio_size);
5742
PF_RULES_RUNLOCK();
5743
error = copyout(ifstore, io->pfiio_buffer, bufsiz);
5744
free(ifstore, M_PF);
5745
break;
5746
}
5747
5748
case DIOCSETIFFLAG: {
5749
struct pfioc_iface *io = (struct pfioc_iface *)addr;
5750
5751
io->pfiio_name[sizeof(io->pfiio_name) - 1] = '\0';
5752
5753
PF_RULES_WLOCK();
5754
error = pfi_set_flags(io->pfiio_name, io->pfiio_flags);
5755
PF_RULES_WUNLOCK();
5756
break;
5757
}
5758
5759
case DIOCCLRIFFLAG: {
5760
struct pfioc_iface *io = (struct pfioc_iface *)addr;
5761
5762
io->pfiio_name[sizeof(io->pfiio_name) - 1] = '\0';
5763
5764
PF_RULES_WLOCK();
5765
error = pfi_clear_flags(io->pfiio_name, io->pfiio_flags);
5766
PF_RULES_WUNLOCK();
5767
break;
5768
}
5769
5770
case DIOCSETREASS: {
5771
u_int32_t *reass = (u_int32_t *)addr;
5772
5773
V_pf_status.reass = *reass & (PF_REASS_ENABLED|PF_REASS_NODF);
5774
/* Removal of DF flag without reassembly enabled is not a
5775
* valid combination. Disable reassembly in such case. */
5776
if (!(V_pf_status.reass & PF_REASS_ENABLED))
5777
V_pf_status.reass = 0;
5778
break;
5779
}
5780
5781
default:
5782
error = ENODEV;
5783
break;
5784
}
5785
fail:
5786
CURVNET_RESTORE();
5787
5788
#undef ERROUT_IOCTL
5789
5790
return (error);
5791
}
5792
5793
void
5794
pfsync_state_export(union pfsync_state_union *sp, struct pf_kstate *st, int msg_version)
5795
{
5796
const char *tagname;
5797
bzero(sp, sizeof(union pfsync_state_union));
5798
5799
/* copy from state key */
5800
sp->pfs_1301.key[PF_SK_WIRE].addr[0] = st->key[PF_SK_WIRE]->addr[0];
5801
sp->pfs_1301.key[PF_SK_WIRE].addr[1] = st->key[PF_SK_WIRE]->addr[1];
5802
sp->pfs_1301.key[PF_SK_WIRE].port[0] = st->key[PF_SK_WIRE]->port[0];
5803
sp->pfs_1301.key[PF_SK_WIRE].port[1] = st->key[PF_SK_WIRE]->port[1];
5804
sp->pfs_1301.key[PF_SK_STACK].addr[0] = st->key[PF_SK_STACK]->addr[0];
5805
sp->pfs_1301.key[PF_SK_STACK].addr[1] = st->key[PF_SK_STACK]->addr[1];
5806
sp->pfs_1301.key[PF_SK_STACK].port[0] = st->key[PF_SK_STACK]->port[0];
5807
sp->pfs_1301.key[PF_SK_STACK].port[1] = st->key[PF_SK_STACK]->port[1];
5808
5809
/* copy from state */
5810
strlcpy(sp->pfs_1301.ifname, st->kif->pfik_name, sizeof(sp->pfs_1301.ifname));
5811
bcopy(&st->act.rt_addr, &sp->pfs_1301.rt_addr, sizeof(sp->pfs_1301.rt_addr));
5812
sp->pfs_1301.creation = htonl(time_uptime - (st->creation / 1000));
5813
sp->pfs_1301.expire = pf_state_expires(st);
5814
if (sp->pfs_1301.expire <= time_uptime)
5815
sp->pfs_1301.expire = htonl(0);
5816
else
5817
sp->pfs_1301.expire = htonl(sp->pfs_1301.expire - time_uptime);
5818
5819
switch (msg_version) {
5820
case PFSYNC_MSG_VERSION_1301:
5821
sp->pfs_1301.state_flags = st->state_flags;
5822
sp->pfs_1301.direction = st->direction;
5823
sp->pfs_1301.log = st->act.log;
5824
sp->pfs_1301.timeout = st->timeout;
5825
sp->pfs_1301.proto = st->key[PF_SK_WIRE]->proto;
5826
sp->pfs_1301.af = st->key[PF_SK_WIRE]->af;
5827
/*
5828
* XXX Why do we bother pfsyncing source node information if source
5829
* nodes are not synced? Showing users that there is source tracking
5830
* when there is none seems useless.
5831
*/
5832
if (st->sns[PF_SN_LIMIT] != NULL)
5833
sp->pfs_1301.sync_flags |= PFSYNC_FLAG_SRCNODE;
5834
if (st->sns[PF_SN_NAT] != NULL || st->sns[PF_SN_ROUTE])
5835
sp->pfs_1301.sync_flags |= PFSYNC_FLAG_NATSRCNODE;
5836
break;
5837
case PFSYNC_MSG_VERSION_1400:
5838
sp->pfs_1400.state_flags = htons(st->state_flags);
5839
sp->pfs_1400.direction = st->direction;
5840
sp->pfs_1400.log = st->act.log;
5841
sp->pfs_1400.timeout = st->timeout;
5842
sp->pfs_1400.proto = st->key[PF_SK_WIRE]->proto;
5843
sp->pfs_1400.af = st->key[PF_SK_WIRE]->af;
5844
sp->pfs_1400.qid = htons(st->act.qid);
5845
sp->pfs_1400.pqid = htons(st->act.pqid);
5846
sp->pfs_1400.dnpipe = htons(st->act.dnpipe);
5847
sp->pfs_1400.dnrpipe = htons(st->act.dnrpipe);
5848
sp->pfs_1400.rtableid = htonl(st->act.rtableid);
5849
sp->pfs_1400.min_ttl = st->act.min_ttl;
5850
sp->pfs_1400.set_tos = st->act.set_tos;
5851
sp->pfs_1400.max_mss = htons(st->act.max_mss);
5852
sp->pfs_1400.set_prio[0] = st->act.set_prio[0];
5853
sp->pfs_1400.set_prio[1] = st->act.set_prio[1];
5854
sp->pfs_1400.rt = st->act.rt;
5855
if (st->act.rt_kif)
5856
strlcpy(sp->pfs_1400.rt_ifname,
5857
st->act.rt_kif->pfik_name,
5858
sizeof(sp->pfs_1400.rt_ifname));
5859
/*
5860
* XXX Why do we bother pfsyncing source node information if source
5861
* nodes are not synced? Showing users that there is source tracking
5862
* when there is none seems useless.
5863
*/
5864
if (st->sns[PF_SN_LIMIT] != NULL)
5865
sp->pfs_1400.sync_flags |= PFSYNC_FLAG_SRCNODE;
5866
if (st->sns[PF_SN_NAT] != NULL || st->sns[PF_SN_ROUTE])
5867
sp->pfs_1400.sync_flags |= PFSYNC_FLAG_NATSRCNODE;
5868
break;
5869
case PFSYNC_MSG_VERSION_1500:
5870
sp->pfs_1500.state_flags = htons(st->state_flags);
5871
sp->pfs_1500.direction = st->direction;
5872
sp->pfs_1500.log = st->act.log;
5873
sp->pfs_1500.timeout = st->timeout;
5874
sp->pfs_1500.wire_proto = st->key[PF_SK_WIRE]->proto;
5875
sp->pfs_1500.wire_af = st->key[PF_SK_WIRE]->af;
5876
sp->pfs_1500.stack_proto = st->key[PF_SK_STACK]->proto;
5877
sp->pfs_1500.stack_af = st->key[PF_SK_STACK]->af;
5878
sp->pfs_1500.qid = htons(st->act.qid);
5879
sp->pfs_1500.pqid = htons(st->act.pqid);
5880
sp->pfs_1500.dnpipe = htons(st->act.dnpipe);
5881
sp->pfs_1500.dnrpipe = htons(st->act.dnrpipe);
5882
sp->pfs_1500.rtableid = htonl(st->act.rtableid);
5883
sp->pfs_1500.min_ttl = st->act.min_ttl;
5884
sp->pfs_1500.set_tos = st->act.set_tos;
5885
sp->pfs_1500.max_mss = htons(st->act.max_mss);
5886
sp->pfs_1500.set_prio[0] = st->act.set_prio[0];
5887
sp->pfs_1500.set_prio[1] = st->act.set_prio[1];
5888
sp->pfs_1500.rt = st->act.rt;
5889
sp->pfs_1500.rt_af = st->act.rt_af;
5890
if (st->act.rt_kif)
5891
strlcpy(sp->pfs_1500.rt_ifname,
5892
st->act.rt_kif->pfik_name,
5893
sizeof(sp->pfs_1500.rt_ifname));
5894
strlcpy(sp->pfs_1500.orig_ifname,
5895
st->orig_kif->pfik_name,
5896
sizeof(sp->pfs_1500.orig_ifname));
5897
if ((tagname = pf_tag2tagname(st->tag)) != NULL)
5898
strlcpy(sp->pfs_1500.tagname, tagname,
5899
sizeof(sp->pfs_1500.tagname));
5900
break;
5901
default:
5902
panic("%s: Unsupported pfsync_msg_version %d",
5903
__func__, msg_version);
5904
}
5905
5906
sp->pfs_1301.id = st->id;
5907
sp->pfs_1301.creatorid = st->creatorid;
5908
pf_state_peer_hton(&st->src, &sp->pfs_1301.src);
5909
pf_state_peer_hton(&st->dst, &sp->pfs_1301.dst);
5910
5911
if (st->rule == NULL)
5912
sp->pfs_1301.rule = htonl(-1);
5913
else
5914
sp->pfs_1301.rule = htonl(st->rule->nr);
5915
if (st->anchor == NULL)
5916
sp->pfs_1301.anchor = htonl(-1);
5917
else
5918
sp->pfs_1301.anchor = htonl(st->anchor->nr);
5919
if (st->nat_rule == NULL)
5920
sp->pfs_1301.nat_rule = htonl(-1);
5921
else
5922
sp->pfs_1301.nat_rule = htonl(st->nat_rule->nr);
5923
5924
pf_state_counter_hton(st->packets[0], sp->pfs_1301.packets[0]);
5925
pf_state_counter_hton(st->packets[1], sp->pfs_1301.packets[1]);
5926
pf_state_counter_hton(st->bytes[0], sp->pfs_1301.bytes[0]);
5927
pf_state_counter_hton(st->bytes[1], sp->pfs_1301.bytes[1]);
5928
}
5929
5930
void
5931
pf_state_export(struct pf_state_export *sp, struct pf_kstate *st)
5932
{
5933
bzero(sp, sizeof(*sp));
5934
5935
sp->version = PF_STATE_VERSION;
5936
5937
/* copy from state key */
5938
sp->key[PF_SK_WIRE].addr[0] = st->key[PF_SK_WIRE]->addr[0];
5939
sp->key[PF_SK_WIRE].addr[1] = st->key[PF_SK_WIRE]->addr[1];
5940
sp->key[PF_SK_WIRE].port[0] = st->key[PF_SK_WIRE]->port[0];
5941
sp->key[PF_SK_WIRE].port[1] = st->key[PF_SK_WIRE]->port[1];
5942
sp->key[PF_SK_STACK].addr[0] = st->key[PF_SK_STACK]->addr[0];
5943
sp->key[PF_SK_STACK].addr[1] = st->key[PF_SK_STACK]->addr[1];
5944
sp->key[PF_SK_STACK].port[0] = st->key[PF_SK_STACK]->port[0];
5945
sp->key[PF_SK_STACK].port[1] = st->key[PF_SK_STACK]->port[1];
5946
sp->proto = st->key[PF_SK_WIRE]->proto;
5947
sp->af = st->key[PF_SK_WIRE]->af;
5948
5949
/* copy from state */
5950
strlcpy(sp->ifname, st->kif->pfik_name, sizeof(sp->ifname));
5951
strlcpy(sp->orig_ifname, st->orig_kif->pfik_name,
5952
sizeof(sp->orig_ifname));
5953
memcpy(&sp->rt_addr, &st->act.rt_addr, sizeof(sp->rt_addr));
5954
sp->creation = htonl(time_uptime - (st->creation / 1000));
5955
sp->expire = pf_state_expires(st);
5956
if (sp->expire <= time_uptime)
5957
sp->expire = htonl(0);
5958
else
5959
sp->expire = htonl(sp->expire - time_uptime);
5960
5961
sp->direction = st->direction;
5962
sp->log = st->act.log;
5963
sp->timeout = st->timeout;
5964
/* 8 bits for the old libpfctl, 16 bits for the new libpfctl */
5965
sp->state_flags_compat = st->state_flags;
5966
sp->state_flags = htons(st->state_flags);
5967
if (st->sns[PF_SN_LIMIT] != NULL)
5968
sp->sync_flags |= PFSYNC_FLAG_SRCNODE;
5969
if (st->sns[PF_SN_NAT] != NULL || st->sns[PF_SN_ROUTE] != NULL)
5970
sp->sync_flags |= PFSYNC_FLAG_NATSRCNODE;
5971
sp->id = st->id;
5972
sp->creatorid = st->creatorid;
5973
pf_state_peer_hton(&st->src, &sp->src);
5974
pf_state_peer_hton(&st->dst, &sp->dst);
5975
5976
if (st->rule == NULL)
5977
sp->rule = htonl(-1);
5978
else
5979
sp->rule = htonl(st->rule->nr);
5980
if (st->anchor == NULL)
5981
sp->anchor = htonl(-1);
5982
else
5983
sp->anchor = htonl(st->anchor->nr);
5984
if (st->nat_rule == NULL)
5985
sp->nat_rule = htonl(-1);
5986
else
5987
sp->nat_rule = htonl(st->nat_rule->nr);
5988
5989
sp->packets[0] = st->packets[0];
5990
sp->packets[1] = st->packets[1];
5991
sp->bytes[0] = st->bytes[0];
5992
sp->bytes[1] = st->bytes[1];
5993
5994
sp->qid = htons(st->act.qid);
5995
sp->pqid = htons(st->act.pqid);
5996
sp->dnpipe = htons(st->act.dnpipe);
5997
sp->dnrpipe = htons(st->act.dnrpipe);
5998
sp->rtableid = htonl(st->act.rtableid);
5999
sp->min_ttl = st->act.min_ttl;
6000
sp->set_tos = st->act.set_tos;
6001
sp->max_mss = htons(st->act.max_mss);
6002
sp->rt = st->act.rt;
6003
if (st->act.rt_kif)
6004
strlcpy(sp->rt_ifname, st->act.rt_kif->pfik_name,
6005
sizeof(sp->rt_ifname));
6006
sp->set_prio[0] = st->act.set_prio[0];
6007
sp->set_prio[1] = st->act.set_prio[1];
6008
6009
}
6010
6011
static void
6012
pf_tbladdr_copyout(struct pf_addr_wrap *aw)
6013
{
6014
struct pfr_ktable *kt;
6015
6016
KASSERT(aw->type == PF_ADDR_TABLE, ("%s: type %u", __func__, aw->type));
6017
6018
kt = aw->p.tbl;
6019
if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE) && kt->pfrkt_root != NULL)
6020
kt = kt->pfrkt_root;
6021
aw->p.tbl = NULL;
6022
aw->p.tblcnt = (kt->pfrkt_flags & PFR_TFLAG_ACTIVE) ?
6023
kt->pfrkt_cnt : -1;
6024
}
6025
6026
static int
6027
pf_add_status_counters(nvlist_t *nvl, const char *name, counter_u64_t *counters,
6028
size_t number, char **names)
6029
{
6030
nvlist_t *nvc;
6031
6032
nvc = nvlist_create(0);
6033
if (nvc == NULL)
6034
return (ENOMEM);
6035
6036
for (int i = 0; i < number; i++) {
6037
nvlist_append_number_array(nvc, "counters",
6038
counter_u64_fetch(counters[i]));
6039
nvlist_append_string_array(nvc, "names",
6040
names[i]);
6041
nvlist_append_number_array(nvc, "ids",
6042
i);
6043
}
6044
nvlist_add_nvlist(nvl, name, nvc);
6045
nvlist_destroy(nvc);
6046
6047
return (0);
6048
}
6049
6050
static int
6051
pf_getstatus(struct pfioc_nv *nv)
6052
{
6053
nvlist_t *nvl = NULL, *nvc = NULL;
6054
void *nvlpacked = NULL;
6055
int error;
6056
struct pf_status s;
6057
char *pf_reasons[PFRES_MAX+1] = PFRES_NAMES;
6058
char *pf_lcounter[KLCNT_MAX+1] = KLCNT_NAMES;
6059
char *pf_fcounter[FCNT_MAX+1] = FCNT_NAMES;
6060
time_t since;
6061
6062
PF_RULES_RLOCK_TRACKER;
6063
6064
#define ERROUT(x) ERROUT_FUNCTION(errout, x)
6065
6066
PF_RULES_RLOCK();
6067
6068
nvl = nvlist_create(0);
6069
if (nvl == NULL)
6070
ERROUT(ENOMEM);
6071
6072
since = time_second - (time_uptime - V_pf_status.since);
6073
6074
nvlist_add_bool(nvl, "running", V_pf_status.running);
6075
nvlist_add_number(nvl, "since", since);
6076
nvlist_add_number(nvl, "debug", V_pf_status.debug);
6077
nvlist_add_number(nvl, "hostid", V_pf_status.hostid);
6078
nvlist_add_number(nvl, "states", V_pf_status.states);
6079
nvlist_add_number(nvl, "src_nodes", V_pf_status.src_nodes);
6080
nvlist_add_number(nvl, "reass", V_pf_status.reass);
6081
nvlist_add_bool(nvl, "syncookies_active",
6082
V_pf_status.syncookies_active);
6083
nvlist_add_number(nvl, "halfopen_states", V_pf_status.states_halfopen);
6084
6085
/* counters */
6086
error = pf_add_status_counters(nvl, "counters", V_pf_status.counters,
6087
PFRES_MAX, pf_reasons);
6088
if (error != 0)
6089
ERROUT(error);
6090
6091
/* lcounters */
6092
error = pf_add_status_counters(nvl, "lcounters", V_pf_status.lcounters,
6093
KLCNT_MAX, pf_lcounter);
6094
if (error != 0)
6095
ERROUT(error);
6096
6097
/* fcounters */
6098
nvc = nvlist_create(0);
6099
if (nvc == NULL)
6100
ERROUT(ENOMEM);
6101
6102
for (int i = 0; i < FCNT_MAX; i++) {
6103
nvlist_append_number_array(nvc, "counters",
6104
pf_counter_u64_fetch(&V_pf_status.fcounters[i]));
6105
nvlist_append_string_array(nvc, "names",
6106
pf_fcounter[i]);
6107
nvlist_append_number_array(nvc, "ids",
6108
i);
6109
}
6110
nvlist_add_nvlist(nvl, "fcounters", nvc);
6111
nvlist_destroy(nvc);
6112
nvc = NULL;
6113
6114
/* scounters */
6115
error = pf_add_status_counters(nvl, "scounters", V_pf_status.scounters,
6116
SCNT_MAX, pf_fcounter);
6117
if (error != 0)
6118
ERROUT(error);
6119
6120
nvlist_add_string(nvl, "ifname", V_pf_status.ifname);
6121
nvlist_add_binary(nvl, "chksum", V_pf_status.pf_chksum,
6122
PF_MD5_DIGEST_LENGTH);
6123
6124
pfi_update_status(V_pf_status.ifname, &s);
6125
6126
/* pcounters / bcounters */
6127
for (int i = 0; i < 2; i++) {
6128
for (int j = 0; j < 2; j++) {
6129
for (int k = 0; k < 2; k++) {
6130
nvlist_append_number_array(nvl, "pcounters",
6131
s.pcounters[i][j][k]);
6132
}
6133
nvlist_append_number_array(nvl, "bcounters",
6134
s.bcounters[i][j]);
6135
}
6136
}
6137
6138
nvlpacked = nvlist_pack(nvl, &nv->len);
6139
if (nvlpacked == NULL)
6140
ERROUT(ENOMEM);
6141
6142
if (nv->size == 0)
6143
ERROUT(0);
6144
else if (nv->size < nv->len)
6145
ERROUT(ENOSPC);
6146
6147
PF_RULES_RUNLOCK();
6148
error = copyout(nvlpacked, nv->data, nv->len);
6149
goto done;
6150
6151
#undef ERROUT
6152
errout:
6153
PF_RULES_RUNLOCK();
6154
done:
6155
free(nvlpacked, M_NVLIST);
6156
nvlist_destroy(nvc);
6157
nvlist_destroy(nvl);
6158
6159
return (error);
6160
}
6161
6162
/*
6163
* XXX - Check for version mismatch!!!
6164
*/
6165
static void
6166
pf_clear_all_states(void)
6167
{
6168
struct epoch_tracker et;
6169
struct pf_kstate *s;
6170
u_int i;
6171
6172
NET_EPOCH_ENTER(et);
6173
for (i = 0; i <= V_pf_hashmask; i++) {
6174
struct pf_idhash *ih = &V_pf_idhash[i];
6175
relock:
6176
PF_HASHROW_LOCK(ih);
6177
LIST_FOREACH(s, &ih->states, entry) {
6178
s->timeout = PFTM_PURGE;
6179
/* Don't send out individual delete messages. */
6180
s->state_flags |= PFSTATE_NOSYNC;
6181
pf_remove_state(s);
6182
goto relock;
6183
}
6184
PF_HASHROW_UNLOCK(ih);
6185
}
6186
NET_EPOCH_EXIT(et);
6187
}
6188
6189
static int
6190
pf_clear_tables(void)
6191
{
6192
struct pfioc_table io;
6193
int error;
6194
6195
bzero(&io, sizeof(io));
6196
io.pfrio_flags |= PFR_FLAG_ALLRSETS;
6197
6198
error = pfr_clr_tables(&io.pfrio_table, &io.pfrio_ndel,
6199
io.pfrio_flags);
6200
6201
return (error);
6202
}
6203
6204
static void
6205
pf_kill_srcnodes(struct pfioc_src_node_kill *psnk)
6206
{
6207
struct pf_ksrc_node_list kill;
6208
u_int killed;
6209
6210
LIST_INIT(&kill);
6211
for (int i = 0; i <= V_pf_srchashmask; i++) {
6212
struct pf_srchash *sh = &V_pf_srchash[i];
6213
struct pf_ksrc_node *sn, *tmp;
6214
6215
PF_HASHROW_LOCK(sh);
6216
LIST_FOREACH_SAFE(sn, &sh->nodes, entry, tmp)
6217
if (psnk == NULL ||
6218
(pf_match_addr(psnk->psnk_src.neg,
6219
&psnk->psnk_src.addr.v.a.addr,
6220
&psnk->psnk_src.addr.v.a.mask,
6221
&sn->addr, sn->af) &&
6222
pf_match_addr(psnk->psnk_dst.neg,
6223
&psnk->psnk_dst.addr.v.a.addr,
6224
&psnk->psnk_dst.addr.v.a.mask,
6225
&sn->raddr, sn->af))) {
6226
pf_unlink_src_node(sn);
6227
LIST_INSERT_HEAD(&kill, sn, entry);
6228
sn->expire = 1;
6229
}
6230
PF_HASHROW_UNLOCK(sh);
6231
}
6232
6233
for (int i = 0; i <= V_pf_hashmask; i++) {
6234
struct pf_idhash *ih = &V_pf_idhash[i];
6235
struct pf_kstate *s;
6236
6237
PF_HASHROW_LOCK(ih);
6238
LIST_FOREACH(s, &ih->states, entry) {
6239
for(pf_sn_types_t sn_type=0; sn_type<PF_SN_MAX;
6240
sn_type++) {
6241
if (s->sns[sn_type] &&
6242
s->sns[sn_type]->expire == 1) {
6243
s->sns[sn_type] = NULL;
6244
}
6245
}
6246
}
6247
PF_HASHROW_UNLOCK(ih);
6248
}
6249
6250
killed = pf_free_src_nodes(&kill);
6251
6252
if (psnk != NULL)
6253
psnk->psnk_killed = killed;
6254
}
6255
6256
static int
6257
pf_keepcounters(struct pfioc_nv *nv)
6258
{
6259
nvlist_t *nvl = NULL;
6260
void *nvlpacked = NULL;
6261
int error = 0;
6262
6263
#define ERROUT(x) ERROUT_FUNCTION(on_error, x)
6264
6265
if (nv->len > pf_ioctl_maxcount)
6266
ERROUT(ENOMEM);
6267
6268
nvlpacked = malloc(nv->len, M_NVLIST, M_WAITOK);
6269
error = copyin(nv->data, nvlpacked, nv->len);
6270
if (error)
6271
ERROUT(error);
6272
6273
nvl = nvlist_unpack(nvlpacked, nv->len, 0);
6274
if (nvl == NULL)
6275
ERROUT(EBADMSG);
6276
6277
if (! nvlist_exists_bool(nvl, "keep_counters"))
6278
ERROUT(EBADMSG);
6279
6280
V_pf_status.keep_counters = nvlist_get_bool(nvl, "keep_counters");
6281
6282
on_error:
6283
nvlist_destroy(nvl);
6284
free(nvlpacked, M_NVLIST);
6285
return (error);
6286
}
6287
6288
unsigned int
6289
pf_clear_states(const struct pf_kstate_kill *kill)
6290
{
6291
struct pf_state_key_cmp match_key;
6292
struct pf_kstate *s;
6293
struct pfi_kkif *kif;
6294
int idx;
6295
unsigned int killed = 0, dir;
6296
6297
NET_EPOCH_ASSERT();
6298
6299
for (unsigned int i = 0; i <= V_pf_hashmask; i++) {
6300
struct pf_idhash *ih = &V_pf_idhash[i];
6301
6302
relock_DIOCCLRSTATES:
6303
PF_HASHROW_LOCK(ih);
6304
LIST_FOREACH(s, &ih->states, entry) {
6305
/* For floating states look at the original kif. */
6306
kif = s->kif == V_pfi_all ? s->orig_kif : s->kif;
6307
6308
if (kill->psk_ifname[0] &&
6309
strcmp(kill->psk_ifname,
6310
kif->pfik_name))
6311
continue;
6312
6313
if (kill->psk_kill_match) {
6314
bzero(&match_key, sizeof(match_key));
6315
6316
if (s->direction == PF_OUT) {
6317
dir = PF_IN;
6318
idx = PF_SK_STACK;
6319
} else {
6320
dir = PF_OUT;
6321
idx = PF_SK_WIRE;
6322
}
6323
6324
match_key.af = s->key[idx]->af;
6325
match_key.proto = s->key[idx]->proto;
6326
pf_addrcpy(&match_key.addr[0],
6327
&s->key[idx]->addr[1], match_key.af);
6328
match_key.port[0] = s->key[idx]->port[1];
6329
pf_addrcpy(&match_key.addr[1],
6330
&s->key[idx]->addr[0], match_key.af);
6331
match_key.port[1] = s->key[idx]->port[0];
6332
}
6333
6334
/*
6335
* Don't send out individual
6336
* delete messages.
6337
*/
6338
s->state_flags |= PFSTATE_NOSYNC;
6339
pf_remove_state(s);
6340
killed++;
6341
6342
if (kill->psk_kill_match)
6343
killed += pf_kill_matching_state(&match_key,
6344
dir);
6345
6346
goto relock_DIOCCLRSTATES;
6347
}
6348
PF_HASHROW_UNLOCK(ih);
6349
}
6350
6351
if (V_pfsync_clear_states_ptr != NULL)
6352
V_pfsync_clear_states_ptr(V_pf_status.hostid, kill->psk_ifname);
6353
6354
return (killed);
6355
}
6356
6357
void
6358
pf_killstates(struct pf_kstate_kill *kill, unsigned int *killed)
6359
{
6360
struct pf_kstate *s;
6361
6362
NET_EPOCH_ASSERT();
6363
if (kill->psk_pfcmp.id) {
6364
if (kill->psk_pfcmp.creatorid == 0)
6365
kill->psk_pfcmp.creatorid = V_pf_status.hostid;
6366
if ((s = pf_find_state_byid(kill->psk_pfcmp.id,
6367
kill->psk_pfcmp.creatorid))) {
6368
pf_remove_state(s);
6369
*killed = 1;
6370
}
6371
return;
6372
}
6373
6374
for (unsigned int i = 0; i <= V_pf_hashmask; i++)
6375
*killed += pf_killstates_row(kill, &V_pf_idhash[i]);
6376
}
6377
6378
static int
6379
pf_killstates_nv(struct pfioc_nv *nv)
6380
{
6381
struct pf_kstate_kill kill;
6382
struct epoch_tracker et;
6383
nvlist_t *nvl = NULL;
6384
void *nvlpacked = NULL;
6385
int error = 0;
6386
unsigned int killed = 0;
6387
6388
#define ERROUT(x) ERROUT_FUNCTION(on_error, x)
6389
6390
if (nv->len > pf_ioctl_maxcount)
6391
ERROUT(ENOMEM);
6392
6393
nvlpacked = malloc(nv->len, M_NVLIST, M_WAITOK);
6394
error = copyin(nv->data, nvlpacked, nv->len);
6395
if (error)
6396
ERROUT(error);
6397
6398
nvl = nvlist_unpack(nvlpacked, nv->len, 0);
6399
if (nvl == NULL)
6400
ERROUT(EBADMSG);
6401
6402
error = pf_nvstate_kill_to_kstate_kill(nvl, &kill);
6403
if (error)
6404
ERROUT(error);
6405
6406
NET_EPOCH_ENTER(et);
6407
pf_killstates(&kill, &killed);
6408
NET_EPOCH_EXIT(et);
6409
6410
free(nvlpacked, M_NVLIST);
6411
nvlpacked = NULL;
6412
nvlist_destroy(nvl);
6413
nvl = nvlist_create(0);
6414
if (nvl == NULL)
6415
ERROUT(ENOMEM);
6416
6417
nvlist_add_number(nvl, "killed", killed);
6418
6419
nvlpacked = nvlist_pack(nvl, &nv->len);
6420
if (nvlpacked == NULL)
6421
ERROUT(ENOMEM);
6422
6423
if (nv->size == 0)
6424
ERROUT(0);
6425
else if (nv->size < nv->len)
6426
ERROUT(ENOSPC);
6427
6428
error = copyout(nvlpacked, nv->data, nv->len);
6429
6430
on_error:
6431
nvlist_destroy(nvl);
6432
free(nvlpacked, M_NVLIST);
6433
return (error);
6434
}
6435
6436
static int
6437
pf_clearstates_nv(struct pfioc_nv *nv)
6438
{
6439
struct pf_kstate_kill kill;
6440
struct epoch_tracker et;
6441
nvlist_t *nvl = NULL;
6442
void *nvlpacked = NULL;
6443
int error = 0;
6444
unsigned int killed;
6445
6446
#define ERROUT(x) ERROUT_FUNCTION(on_error, x)
6447
6448
if (nv->len > pf_ioctl_maxcount)
6449
ERROUT(ENOMEM);
6450
6451
nvlpacked = malloc(nv->len, M_NVLIST, M_WAITOK);
6452
error = copyin(nv->data, nvlpacked, nv->len);
6453
if (error)
6454
ERROUT(error);
6455
6456
nvl = nvlist_unpack(nvlpacked, nv->len, 0);
6457
if (nvl == NULL)
6458
ERROUT(EBADMSG);
6459
6460
error = pf_nvstate_kill_to_kstate_kill(nvl, &kill);
6461
if (error)
6462
ERROUT(error);
6463
6464
NET_EPOCH_ENTER(et);
6465
killed = pf_clear_states(&kill);
6466
NET_EPOCH_EXIT(et);
6467
6468
free(nvlpacked, M_NVLIST);
6469
nvlpacked = NULL;
6470
nvlist_destroy(nvl);
6471
nvl = nvlist_create(0);
6472
if (nvl == NULL)
6473
ERROUT(ENOMEM);
6474
6475
nvlist_add_number(nvl, "killed", killed);
6476
6477
nvlpacked = nvlist_pack(nvl, &nv->len);
6478
if (nvlpacked == NULL)
6479
ERROUT(ENOMEM);
6480
6481
if (nv->size == 0)
6482
ERROUT(0);
6483
else if (nv->size < nv->len)
6484
ERROUT(ENOSPC);
6485
6486
error = copyout(nvlpacked, nv->data, nv->len);
6487
6488
#undef ERROUT
6489
on_error:
6490
nvlist_destroy(nvl);
6491
free(nvlpacked, M_NVLIST);
6492
return (error);
6493
}
6494
6495
static int
6496
pf_getstate(struct pfioc_nv *nv)
6497
{
6498
nvlist_t *nvl = NULL, *nvls;
6499
void *nvlpacked = NULL;
6500
struct pf_kstate *s = NULL;
6501
int error = 0;
6502
uint64_t id, creatorid;
6503
6504
#define ERROUT(x) ERROUT_FUNCTION(errout, x)
6505
6506
if (nv->len > pf_ioctl_maxcount)
6507
ERROUT(ENOMEM);
6508
6509
nvlpacked = malloc(nv->len, M_NVLIST, M_WAITOK);
6510
error = copyin(nv->data, nvlpacked, nv->len);
6511
if (error)
6512
ERROUT(error);
6513
6514
nvl = nvlist_unpack(nvlpacked, nv->len, 0);
6515
if (nvl == NULL)
6516
ERROUT(EBADMSG);
6517
6518
PFNV_CHK(pf_nvuint64(nvl, "id", &id));
6519
PFNV_CHK(pf_nvuint64(nvl, "creatorid", &creatorid));
6520
6521
s = pf_find_state_byid(id, creatorid);
6522
if (s == NULL)
6523
ERROUT(ENOENT);
6524
6525
free(nvlpacked, M_NVLIST);
6526
nvlpacked = NULL;
6527
nvlist_destroy(nvl);
6528
nvl = nvlist_create(0);
6529
if (nvl == NULL)
6530
ERROUT(ENOMEM);
6531
6532
nvls = pf_state_to_nvstate(s);
6533
if (nvls == NULL)
6534
ERROUT(ENOMEM);
6535
6536
nvlist_add_nvlist(nvl, "state", nvls);
6537
nvlist_destroy(nvls);
6538
6539
nvlpacked = nvlist_pack(nvl, &nv->len);
6540
if (nvlpacked == NULL)
6541
ERROUT(ENOMEM);
6542
6543
if (nv->size == 0)
6544
ERROUT(0);
6545
else if (nv->size < nv->len)
6546
ERROUT(ENOSPC);
6547
6548
error = copyout(nvlpacked, nv->data, nv->len);
6549
6550
#undef ERROUT
6551
errout:
6552
if (s != NULL)
6553
PF_STATE_UNLOCK(s);
6554
free(nvlpacked, M_NVLIST);
6555
nvlist_destroy(nvl);
6556
return (error);
6557
}
6558
6559
/*
6560
* XXX - Check for version mismatch!!!
6561
*/
6562
6563
/*
6564
* Duplicate pfctl -Fa operation to get rid of as much as we can.
6565
*/
6566
static int
6567
shutdown_pf(void)
6568
{
6569
int error = 0;
6570
u_int32_t t[5];
6571
char nn = '\0';
6572
struct pf_kanchor *anchor, *tmp_anchor;
6573
struct pf_keth_anchor *eth_anchor, *tmp_eth_anchor;
6574
int rs_num;
6575
6576
do {
6577
/* Unlink rules of all user defined anchors */
6578
RB_FOREACH_SAFE(anchor, pf_kanchor_global, &V_pf_anchors,
6579
tmp_anchor) {
6580
for (rs_num = 0; rs_num < PF_RULESET_MAX; ++rs_num) {
6581
if ((error = pf_begin_rules(&t[rs_num], rs_num,
6582
anchor->path)) != 0) {
6583
DPFPRINTF(PF_DEBUG_MISC, "%s: "
6584
"anchor.path=%s rs_num=%d",
6585
__func__, anchor->path, rs_num);
6586
goto error; /* XXX: rollback? */
6587
}
6588
}
6589
for (rs_num = 0; rs_num < PF_RULESET_MAX; ++rs_num) {
6590
error = pf_commit_rules(t[rs_num], rs_num,
6591
anchor->path);
6592
MPASS(error == 0);
6593
}
6594
}
6595
6596
/* Unlink rules of all user defined ether anchors */
6597
RB_FOREACH_SAFE(eth_anchor, pf_keth_anchor_global,
6598
&V_pf_keth_anchors, tmp_eth_anchor) {
6599
if ((error = pf_begin_eth(&t[0], eth_anchor->path))
6600
!= 0) {
6601
DPFPRINTF(PF_DEBUG_MISC, "%s: eth "
6602
"anchor.path=%s", __func__,
6603
eth_anchor->path);
6604
goto error;
6605
}
6606
error = pf_commit_eth(t[0], eth_anchor->path);
6607
MPASS(error == 0);
6608
}
6609
6610
if ((error = pf_begin_rules(&t[0], PF_RULESET_SCRUB, &nn))
6611
!= 0) {
6612
DPFPRINTF(PF_DEBUG_MISC, "%s: SCRUB", __func__);
6613
break;
6614
}
6615
if ((error = pf_begin_rules(&t[1], PF_RULESET_FILTER, &nn))
6616
!= 0) {
6617
DPFPRINTF(PF_DEBUG_MISC, "%s: FILTER", __func__);
6618
break; /* XXX: rollback? */
6619
}
6620
if ((error = pf_begin_rules(&t[2], PF_RULESET_NAT, &nn))
6621
!= 0) {
6622
DPFPRINTF(PF_DEBUG_MISC, "%s: NAT", __func__);
6623
break; /* XXX: rollback? */
6624
}
6625
if ((error = pf_begin_rules(&t[3], PF_RULESET_BINAT, &nn))
6626
!= 0) {
6627
DPFPRINTF(PF_DEBUG_MISC, "%s: BINAT", __func__);
6628
break; /* XXX: rollback? */
6629
}
6630
if ((error = pf_begin_rules(&t[4], PF_RULESET_RDR, &nn))
6631
!= 0) {
6632
DPFPRINTF(PF_DEBUG_MISC, "%s: RDR", __func__);
6633
break; /* XXX: rollback? */
6634
}
6635
6636
error = pf_commit_rules(t[0], PF_RULESET_SCRUB, &nn);
6637
MPASS(error == 0);
6638
error = pf_commit_rules(t[1], PF_RULESET_FILTER, &nn);
6639
MPASS(error == 0);
6640
error = pf_commit_rules(t[2], PF_RULESET_NAT, &nn);
6641
MPASS(error == 0);
6642
error = pf_commit_rules(t[3], PF_RULESET_BINAT, &nn);
6643
MPASS(error == 0);
6644
error = pf_commit_rules(t[4], PF_RULESET_RDR, &nn);
6645
MPASS(error == 0);
6646
6647
if ((error = pf_clear_tables()) != 0)
6648
break;
6649
6650
if ((error = pf_begin_eth(&t[0], &nn)) != 0) {
6651
DPFPRINTF(PF_DEBUG_MISC, "%s: eth", __func__);
6652
break;
6653
}
6654
error = pf_commit_eth(t[0], &nn);
6655
MPASS(error == 0);
6656
6657
#ifdef ALTQ
6658
if ((error = pf_begin_altq(&t[0])) != 0) {
6659
DPFPRINTF(PF_DEBUG_MISC, "%s: ALTQ", __func__);
6660
break;
6661
}
6662
pf_commit_altq(t[0]);
6663
#endif
6664
6665
pf_clear_all_states();
6666
6667
pf_kill_srcnodes(NULL);
6668
6669
for (int i = 0; i < PF_RULESET_MAX; i++) {
6670
pf_rule_tree_free(pf_main_ruleset.rules[i].active.tree);
6671
pf_rule_tree_free(pf_main_ruleset.rules[i].inactive.tree);
6672
}
6673
6674
/* status does not use malloced mem so no need to cleanup */
6675
/* fingerprints and interfaces have their own cleanup code */
6676
} while(0);
6677
6678
error:
6679
return (error);
6680
}
6681
6682
static pfil_return_t
6683
pf_check_return(int chk, struct mbuf **m)
6684
{
6685
6686
switch (chk) {
6687
case PF_PASS:
6688
if (*m == NULL)
6689
return (PFIL_CONSUMED);
6690
else
6691
return (PFIL_PASS);
6692
break;
6693
default:
6694
if (*m != NULL) {
6695
m_freem(*m);
6696
*m = NULL;
6697
}
6698
return (PFIL_DROPPED);
6699
}
6700
}
6701
6702
static pfil_return_t
6703
pf_eth_check_in(struct mbuf **m, struct ifnet *ifp, int flags,
6704
void *ruleset __unused, struct inpcb *inp)
6705
{
6706
int chk;
6707
6708
CURVNET_ASSERT_SET();
6709
6710
chk = pf_test_eth(PF_IN, flags, ifp, m, inp);
6711
6712
return (pf_check_return(chk, m));
6713
}
6714
6715
static pfil_return_t
6716
pf_eth_check_out(struct mbuf **m, struct ifnet *ifp, int flags,
6717
void *ruleset __unused, struct inpcb *inp)
6718
{
6719
int chk;
6720
6721
CURVNET_ASSERT_SET();
6722
6723
chk = pf_test_eth(PF_OUT, flags, ifp, m, inp);
6724
6725
return (pf_check_return(chk, m));
6726
}
6727
6728
#ifdef INET
6729
static pfil_return_t
6730
pf_check_in(struct mbuf **m, struct ifnet *ifp, int flags,
6731
void *ruleset __unused, struct inpcb *inp)
6732
{
6733
int chk;
6734
6735
CURVNET_ASSERT_SET();
6736
6737
chk = pf_test(AF_INET, PF_IN, flags, ifp, m, inp, NULL);
6738
6739
return (pf_check_return(chk, m));
6740
}
6741
6742
static pfil_return_t
6743
pf_check_out(struct mbuf **m, struct ifnet *ifp, int flags,
6744
void *ruleset __unused, struct inpcb *inp)
6745
{
6746
int chk;
6747
6748
CURVNET_ASSERT_SET();
6749
6750
chk = pf_test(AF_INET, PF_OUT, flags, ifp, m, inp, NULL);
6751
6752
return (pf_check_return(chk, m));
6753
}
6754
#endif
6755
6756
#ifdef INET6
6757
static pfil_return_t
6758
pf_check6_in(struct mbuf **m, struct ifnet *ifp, int flags,
6759
void *ruleset __unused, struct inpcb *inp)
6760
{
6761
int chk;
6762
6763
CURVNET_ASSERT_SET();
6764
6765
/*
6766
* In case of loopback traffic IPv6 uses the real interface in
6767
* order to support scoped addresses. In order to support stateful
6768
* filtering we have change this to lo0 as it is the case in IPv4.
6769
*/
6770
chk = pf_test(AF_INET6, PF_IN, flags, (*m)->m_flags & M_LOOP ? V_loif : ifp,
6771
m, inp, NULL);
6772
6773
return (pf_check_return(chk, m));
6774
}
6775
6776
static pfil_return_t
6777
pf_check6_out(struct mbuf **m, struct ifnet *ifp, int flags,
6778
void *ruleset __unused, struct inpcb *inp)
6779
{
6780
int chk;
6781
6782
CURVNET_ASSERT_SET();
6783
6784
chk = pf_test(AF_INET6, PF_OUT, flags, ifp, m, inp, NULL);
6785
6786
return (pf_check_return(chk, m));
6787
}
6788
#endif /* INET6 */
6789
6790
VNET_DEFINE_STATIC(pfil_hook_t, pf_eth_in_hook);
6791
VNET_DEFINE_STATIC(pfil_hook_t, pf_eth_out_hook);
6792
#define V_pf_eth_in_hook VNET(pf_eth_in_hook)
6793
#define V_pf_eth_out_hook VNET(pf_eth_out_hook)
6794
6795
#ifdef INET
6796
VNET_DEFINE_STATIC(pfil_hook_t, pf_ip4_in_hook);
6797
VNET_DEFINE_STATIC(pfil_hook_t, pf_ip4_out_hook);
6798
#define V_pf_ip4_in_hook VNET(pf_ip4_in_hook)
6799
#define V_pf_ip4_out_hook VNET(pf_ip4_out_hook)
6800
#endif
6801
#ifdef INET6
6802
VNET_DEFINE_STATIC(pfil_hook_t, pf_ip6_in_hook);
6803
VNET_DEFINE_STATIC(pfil_hook_t, pf_ip6_out_hook);
6804
#define V_pf_ip6_in_hook VNET(pf_ip6_in_hook)
6805
#define V_pf_ip6_out_hook VNET(pf_ip6_out_hook)
6806
#endif
6807
6808
static void
6809
hook_pf_eth(void)
6810
{
6811
struct pfil_hook_args pha = {
6812
.pa_version = PFIL_VERSION,
6813
.pa_modname = "pf",
6814
.pa_type = PFIL_TYPE_ETHERNET,
6815
};
6816
struct pfil_link_args pla = {
6817
.pa_version = PFIL_VERSION,
6818
};
6819
int ret __diagused;
6820
6821
if (atomic_load_bool(&V_pf_pfil_eth_hooked))
6822
return;
6823
6824
pha.pa_mbuf_chk = pf_eth_check_in;
6825
pha.pa_flags = PFIL_IN;
6826
pha.pa_rulname = "eth-in";
6827
V_pf_eth_in_hook = pfil_add_hook(&pha);
6828
pla.pa_flags = PFIL_IN | PFIL_HEADPTR | PFIL_HOOKPTR;
6829
pla.pa_head = V_link_pfil_head;
6830
pla.pa_hook = V_pf_eth_in_hook;
6831
ret = pfil_link(&pla);
6832
MPASS(ret == 0);
6833
pha.pa_mbuf_chk = pf_eth_check_out;
6834
pha.pa_flags = PFIL_OUT;
6835
pha.pa_rulname = "eth-out";
6836
V_pf_eth_out_hook = pfil_add_hook(&pha);
6837
pla.pa_flags = PFIL_OUT | PFIL_HEADPTR | PFIL_HOOKPTR;
6838
pla.pa_head = V_link_pfil_head;
6839
pla.pa_hook = V_pf_eth_out_hook;
6840
ret = pfil_link(&pla);
6841
MPASS(ret == 0);
6842
6843
atomic_store_bool(&V_pf_pfil_eth_hooked, true);
6844
}
6845
6846
static void
6847
hook_pf(void)
6848
{
6849
struct pfil_hook_args pha = {
6850
.pa_version = PFIL_VERSION,
6851
.pa_modname = "pf",
6852
};
6853
struct pfil_link_args pla = {
6854
.pa_version = PFIL_VERSION,
6855
};
6856
int ret __diagused;
6857
6858
if (atomic_load_bool(&V_pf_pfil_hooked))
6859
return;
6860
6861
#ifdef INET
6862
pha.pa_type = PFIL_TYPE_IP4;
6863
pha.pa_mbuf_chk = pf_check_in;
6864
pha.pa_flags = PFIL_IN;
6865
pha.pa_rulname = "default-in";
6866
V_pf_ip4_in_hook = pfil_add_hook(&pha);
6867
pla.pa_flags = PFIL_IN | PFIL_HEADPTR | PFIL_HOOKPTR;
6868
pla.pa_head = V_inet_pfil_head;
6869
pla.pa_hook = V_pf_ip4_in_hook;
6870
ret = pfil_link(&pla);
6871
MPASS(ret == 0);
6872
pha.pa_mbuf_chk = pf_check_out;
6873
pha.pa_flags = PFIL_OUT;
6874
pha.pa_rulname = "default-out";
6875
V_pf_ip4_out_hook = pfil_add_hook(&pha);
6876
pla.pa_flags = PFIL_OUT | PFIL_HEADPTR | PFIL_HOOKPTR;
6877
pla.pa_head = V_inet_pfil_head;
6878
pla.pa_hook = V_pf_ip4_out_hook;
6879
ret = pfil_link(&pla);
6880
MPASS(ret == 0);
6881
if (V_pf_filter_local) {
6882
pla.pa_flags = PFIL_OUT | PFIL_HEADPTR | PFIL_HOOKPTR;
6883
pla.pa_head = V_inet_local_pfil_head;
6884
pla.pa_hook = V_pf_ip4_out_hook;
6885
ret = pfil_link(&pla);
6886
MPASS(ret == 0);
6887
}
6888
#endif
6889
#ifdef INET6
6890
pha.pa_type = PFIL_TYPE_IP6;
6891
pha.pa_mbuf_chk = pf_check6_in;
6892
pha.pa_flags = PFIL_IN;
6893
pha.pa_rulname = "default-in6";
6894
V_pf_ip6_in_hook = pfil_add_hook(&pha);
6895
pla.pa_flags = PFIL_IN | PFIL_HEADPTR | PFIL_HOOKPTR;
6896
pla.pa_head = V_inet6_pfil_head;
6897
pla.pa_hook = V_pf_ip6_in_hook;
6898
ret = pfil_link(&pla);
6899
MPASS(ret == 0);
6900
pha.pa_mbuf_chk = pf_check6_out;
6901
pha.pa_rulname = "default-out6";
6902
pha.pa_flags = PFIL_OUT;
6903
V_pf_ip6_out_hook = pfil_add_hook(&pha);
6904
pla.pa_flags = PFIL_OUT | PFIL_HEADPTR | PFIL_HOOKPTR;
6905
pla.pa_head = V_inet6_pfil_head;
6906
pla.pa_hook = V_pf_ip6_out_hook;
6907
ret = pfil_link(&pla);
6908
MPASS(ret == 0);
6909
if (V_pf_filter_local) {
6910
pla.pa_flags = PFIL_OUT | PFIL_HEADPTR | PFIL_HOOKPTR;
6911
pla.pa_head = V_inet6_local_pfil_head;
6912
pla.pa_hook = V_pf_ip6_out_hook;
6913
ret = pfil_link(&pla);
6914
MPASS(ret == 0);
6915
}
6916
#endif
6917
6918
atomic_store_bool(&V_pf_pfil_hooked, true);
6919
}
6920
6921
static void
6922
dehook_pf_eth(void)
6923
{
6924
6925
if (!atomic_load_bool(&V_pf_pfil_eth_hooked))
6926
return;
6927
6928
pfil_remove_hook(V_pf_eth_in_hook);
6929
pfil_remove_hook(V_pf_eth_out_hook);
6930
6931
atomic_store_bool(&V_pf_pfil_eth_hooked, false);
6932
}
6933
6934
static void
6935
dehook_pf(void)
6936
{
6937
6938
if (!atomic_load_bool(&V_pf_pfil_hooked))
6939
return;
6940
6941
#ifdef INET
6942
pfil_remove_hook(V_pf_ip4_in_hook);
6943
pfil_remove_hook(V_pf_ip4_out_hook);
6944
#endif
6945
#ifdef INET6
6946
pfil_remove_hook(V_pf_ip6_in_hook);
6947
pfil_remove_hook(V_pf_ip6_out_hook);
6948
#endif
6949
6950
atomic_store_bool(&V_pf_pfil_hooked, false);
6951
}
6952
6953
static void
6954
pf_load_vnet(void)
6955
{
6956
V_pf_tag_z = uma_zcreate("pf tags", sizeof(struct pf_tagname),
6957
NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
6958
6959
rm_init_flags(&V_pf_rules_lock, "pf rulesets", RM_RECURSE);
6960
rm_init_flags(&V_pf_tags_lock, "pf tags and queues", RM_RECURSE);
6961
sx_init(&V_pf_ioctl_lock, "pf ioctl");
6962
6963
pf_init_tagset(&V_pf_tags, &pf_rule_tag_hashsize,
6964
PF_RULE_TAG_HASH_SIZE_DEFAULT);
6965
#ifdef ALTQ
6966
pf_init_tagset(&V_pf_qids, &pf_queue_tag_hashsize,
6967
PF_QUEUE_TAG_HASH_SIZE_DEFAULT);
6968
#endif
6969
6970
V_pf_keth = &V_pf_main_keth_anchor.ruleset;
6971
6972
pfattach_vnet();
6973
V_pf_vnet_active = 1;
6974
}
6975
6976
static int
6977
pf_load(void)
6978
{
6979
int error;
6980
6981
sx_init(&pf_end_lock, "pf end thread");
6982
6983
pf_mtag_initialize();
6984
6985
pf_dev = make_dev(&pf_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, PF_NAME);
6986
if (pf_dev == NULL)
6987
return (ENOMEM);
6988
6989
pf_end_threads = 0;
6990
error = kproc_create(pf_purge_thread, NULL, &pf_purge_proc, 0, 0, "pf purge");
6991
if (error != 0)
6992
return (error);
6993
6994
pfi_initialize();
6995
6996
return (0);
6997
}
6998
6999
static void
7000
pf_unload_vnet(void)
7001
{
7002
int ret __diagused;
7003
7004
V_pf_vnet_active = 0;
7005
V_pf_status.running = 0;
7006
dehook_pf();
7007
dehook_pf_eth();
7008
7009
PF_RULES_WLOCK();
7010
pf_syncookies_cleanup();
7011
shutdown_pf();
7012
PF_RULES_WUNLOCK();
7013
7014
ret = swi_remove(V_pf_swi_cookie);
7015
MPASS(ret == 0);
7016
ret = intr_event_destroy(V_pf_swi_ie);
7017
MPASS(ret == 0);
7018
7019
pf_unload_vnet_purge();
7020
7021
pf_normalize_cleanup();
7022
PF_RULES_WLOCK();
7023
pfi_cleanup_vnet();
7024
PF_RULES_WUNLOCK();
7025
pfr_cleanup();
7026
pf_osfp_flush();
7027
pf_cleanup();
7028
if (IS_DEFAULT_VNET(curvnet))
7029
pf_mtag_cleanup();
7030
7031
pf_cleanup_tagset(&V_pf_tags);
7032
#ifdef ALTQ
7033
pf_cleanup_tagset(&V_pf_qids);
7034
#endif
7035
uma_zdestroy(V_pf_tag_z);
7036
7037
#ifdef PF_WANT_32_TO_64_COUNTER
7038
PF_RULES_WLOCK();
7039
LIST_REMOVE(V_pf_kifmarker, pfik_allkiflist);
7040
7041
MPASS(LIST_EMPTY(&V_pf_allkiflist));
7042
MPASS(V_pf_allkifcount == 0);
7043
7044
LIST_REMOVE(&V_pf_default_rule, allrulelist);
7045
V_pf_allrulecount--;
7046
LIST_REMOVE(V_pf_rulemarker, allrulelist);
7047
7048
MPASS(LIST_EMPTY(&V_pf_allrulelist));
7049
MPASS(V_pf_allrulecount == 0);
7050
7051
PF_RULES_WUNLOCK();
7052
7053
free(V_pf_kifmarker, PFI_MTYPE);
7054
free(V_pf_rulemarker, M_PFRULE);
7055
#endif
7056
7057
/* Free counters last as we updated them during shutdown. */
7058
pf_counter_u64_deinit(&V_pf_default_rule.evaluations);
7059
for (int i = 0; i < 2; i++) {
7060
pf_counter_u64_deinit(&V_pf_default_rule.packets[i]);
7061
pf_counter_u64_deinit(&V_pf_default_rule.bytes[i]);
7062
}
7063
counter_u64_free(V_pf_default_rule.states_cur);
7064
counter_u64_free(V_pf_default_rule.states_tot);
7065
for (pf_sn_types_t sn_type=0; sn_type<PF_SN_MAX; sn_type++)
7066
counter_u64_free(V_pf_default_rule.src_nodes[sn_type]);
7067
uma_zfree_pcpu(pf_timestamp_pcpu_zone, V_pf_default_rule.timestamp);
7068
7069
for (int i = 0; i < PFRES_MAX; i++)
7070
counter_u64_free(V_pf_status.counters[i]);
7071
for (int i = 0; i < KLCNT_MAX; i++)
7072
counter_u64_free(V_pf_status.lcounters[i]);
7073
for (int i = 0; i < FCNT_MAX; i++)
7074
pf_counter_u64_deinit(&V_pf_status.fcounters[i]);
7075
for (int i = 0; i < SCNT_MAX; i++)
7076
counter_u64_free(V_pf_status.scounters[i]);
7077
for (int i = 0; i < NCNT_MAX; i++)
7078
counter_u64_free(V_pf_status.ncounters[i]);
7079
7080
rm_destroy(&V_pf_rules_lock);
7081
sx_destroy(&V_pf_ioctl_lock);
7082
}
7083
7084
static void
7085
pf_unload(void)
7086
{
7087
7088
sx_xlock(&pf_end_lock);
7089
pf_end_threads = 1;
7090
while (pf_end_threads < 2) {
7091
wakeup_one(pf_purge_thread);
7092
sx_sleep(pf_purge_proc, &pf_end_lock, 0, "pftmo", 0);
7093
}
7094
sx_xunlock(&pf_end_lock);
7095
7096
pf_nl_unregister();
7097
7098
if (pf_dev != NULL)
7099
destroy_dev(pf_dev);
7100
7101
pfi_cleanup();
7102
7103
sx_destroy(&pf_end_lock);
7104
}
7105
7106
static void
7107
vnet_pf_init(void *unused __unused)
7108
{
7109
7110
pf_load_vnet();
7111
}
7112
VNET_SYSINIT(vnet_pf_init, SI_SUB_PROTO_FIREWALL, SI_ORDER_THIRD,
7113
vnet_pf_init, NULL);
7114
7115
static void
7116
vnet_pf_uninit(const void *unused __unused)
7117
{
7118
7119
pf_unload_vnet();
7120
}
7121
SYSUNINIT(pf_unload, SI_SUB_PROTO_FIREWALL, SI_ORDER_SECOND, pf_unload, NULL);
7122
VNET_SYSUNINIT(vnet_pf_uninit, SI_SUB_PROTO_FIREWALL, SI_ORDER_THIRD,
7123
vnet_pf_uninit, NULL);
7124
7125
static int
7126
pf_modevent(module_t mod, int type, void *data)
7127
{
7128
int error = 0;
7129
7130
switch(type) {
7131
case MOD_LOAD:
7132
error = pf_load();
7133
pf_nl_register();
7134
break;
7135
case MOD_UNLOAD:
7136
/* Handled in SYSUNINIT(pf_unload) to ensure it's done after
7137
* the vnet_pf_uninit()s */
7138
break;
7139
default:
7140
error = EINVAL;
7141
break;
7142
}
7143
7144
return (error);
7145
}
7146
7147
static moduledata_t pf_mod = {
7148
"pf",
7149
pf_modevent,
7150
0
7151
};
7152
7153
DECLARE_MODULE(pf, pf_mod, SI_SUB_PROTO_FIREWALL, SI_ORDER_SECOND);
7154
MODULE_DEPEND(pf, netlink, 1, 1, 1);
7155
MODULE_DEPEND(pf, crypto, 1, 1, 1);
7156
MODULE_VERSION(pf, PF_MODVER);
7157
7158