Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/netpfil/pf/pf_nv.c
39481 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (c) 2021 Rubicon Communications, LLC (Netgate)
5
*
6
* Redistribution and use in source and binary forms, with or without
7
* modification, are permitted provided that the following conditions
8
* are met:
9
* 1. Redistributions of source code must retain the above copyright
10
* notice, this list of conditions and the following disclaimer.
11
* 2. Redistributions in binary form must reproduce the above copyright
12
* notice, this list of conditions and the following disclaimer in the
13
* documentation and/or other materials provided with the distribution.
14
*
15
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
* SUCH DAMAGE.
26
*
27
*/
28
#include <sys/cdefs.h>
29
#include "opt_inet.h"
30
#include "opt_inet6.h"
31
32
#include <sys/param.h>
33
#include <sys/errno.h>
34
#include <sys/limits.h>
35
#include <sys/queue.h>
36
#include <sys/systm.h>
37
38
#include <netpfil/pf/pf_nv.h>
39
40
#define PF_NV_IMPL_UINT(fnname, type, max) \
41
int \
42
pf_nv ## fnname ## _opt(const nvlist_t *nvl, const char *name, \
43
type *val, type dflt) \
44
{ \
45
uint64_t raw; \
46
if (! nvlist_exists_number(nvl, name)) { \
47
*val = dflt; \
48
return (0); \
49
} \
50
raw = nvlist_get_number(nvl, name); \
51
if (raw > max) \
52
return (ERANGE); \
53
*val = (type)raw; \
54
return (0); \
55
} \
56
int \
57
pf_nv ## fnname(const nvlist_t *nvl, const char *name, type *val) \
58
{ \
59
uint64_t raw; \
60
if (! nvlist_exists_number(nvl, name)) \
61
return (EINVAL); \
62
raw = nvlist_get_number(nvl, name); \
63
if (raw > max) \
64
return (ERANGE); \
65
*val = (type)raw; \
66
return (0); \
67
} \
68
int \
69
pf_nv ## fnname ## _array(const nvlist_t *nvl, const char *name, \
70
type *array, size_t maxelems, size_t *nelems) \
71
{ \
72
const uint64_t *n; \
73
size_t nitems; \
74
bzero(array, sizeof(type) * maxelems); \
75
if (! nvlist_exists_number_array(nvl, name)) \
76
return (EINVAL); \
77
n = nvlist_get_number_array(nvl, name, &nitems); \
78
if (nitems > maxelems) \
79
return (E2BIG); \
80
if (nelems != NULL) \
81
*nelems = nitems; \
82
for (size_t i = 0; i < nitems; i++) { \
83
if (n[i] > max) \
84
return (ERANGE); \
85
array[i] = (type)n[i]; \
86
} \
87
return (0); \
88
} \
89
void \
90
pf_ ## fnname ## _array_nv(nvlist_t *nvl, const char *name, \
91
const type *numbers, size_t count) \
92
{ \
93
uint64_t tmp; \
94
for (size_t i = 0; i < count; i++) { \
95
tmp = numbers[i]; \
96
nvlist_append_number_array(nvl, name, tmp); \
97
} \
98
}
99
100
int
101
pf_nvbool(const nvlist_t *nvl, const char *name, bool *val)
102
{
103
if (! nvlist_exists_bool(nvl, name))
104
return (EINVAL);
105
106
*val = nvlist_get_bool(nvl, name);
107
108
return (0);
109
}
110
111
int
112
pf_nvbinary(const nvlist_t *nvl, const char *name, void *data,
113
size_t expected_size)
114
{
115
const uint8_t *nvdata;
116
size_t len;
117
118
bzero(data, expected_size);
119
120
if (! nvlist_exists_binary(nvl, name))
121
return (EINVAL);
122
123
nvdata = (const uint8_t *)nvlist_get_binary(nvl, name, &len);
124
if (len > expected_size)
125
return (EINVAL);
126
127
memcpy(data, nvdata, len);
128
129
return (0);
130
}
131
132
PF_NV_IMPL_UINT(uint8, uint8_t, UINT8_MAX);
133
PF_NV_IMPL_UINT(uint16, uint16_t, UINT16_MAX);
134
PF_NV_IMPL_UINT(uint32, uint32_t, UINT32_MAX);
135
PF_NV_IMPL_UINT(uint64, uint64_t, UINT64_MAX);
136
137
int
138
pf_nvint(const nvlist_t *nvl, const char *name, int *val)
139
{
140
int64_t raw;
141
142
if (! nvlist_exists_number(nvl, name))
143
return (EINVAL);
144
145
raw = nvlist_get_number(nvl, name);
146
if (raw > INT_MAX || raw < INT_MIN)
147
return (ERANGE);
148
149
*val = (int)raw;
150
151
return (0);
152
}
153
154
int
155
pf_nvstring(const nvlist_t *nvl, const char *name, char *str, size_t maxlen)
156
{
157
int ret;
158
159
if (! nvlist_exists_string(nvl, name))
160
return (EINVAL);
161
162
ret = strlcpy(str, nvlist_get_string(nvl, name), maxlen);
163
if (ret >= maxlen)
164
return (EINVAL);
165
166
return (0);
167
}
168
169
static int
170
pf_nvaddr_to_addr(const nvlist_t *nvl, struct pf_addr *paddr)
171
{
172
return (pf_nvbinary(nvl, "addr", paddr, sizeof(*paddr)));
173
}
174
175
static nvlist_t *
176
pf_addr_to_nvaddr(const struct pf_addr *paddr)
177
{
178
nvlist_t *nvl;
179
180
nvl = nvlist_create(0);
181
if (nvl == NULL)
182
return (NULL);
183
184
nvlist_add_binary(nvl, "addr", paddr, sizeof(*paddr));
185
186
return (nvl);
187
}
188
189
static int
190
pf_nvmape_to_mape(const nvlist_t *nvl, struct pf_mape_portset *mape)
191
{
192
int error = 0;
193
194
bzero(mape, sizeof(*mape));
195
PFNV_CHK(pf_nvuint8(nvl, "offset", &mape->offset));
196
PFNV_CHK(pf_nvuint8(nvl, "psidlen", &mape->psidlen));
197
PFNV_CHK(pf_nvuint16(nvl, "psid", &mape->psid));
198
199
errout:
200
return (error);
201
}
202
203
static nvlist_t *
204
pf_mape_to_nvmape(const struct pf_mape_portset *mape)
205
{
206
nvlist_t *nvl;
207
208
nvl = nvlist_create(0);
209
if (nvl == NULL)
210
return (NULL);
211
212
nvlist_add_number(nvl, "offset", mape->offset);
213
nvlist_add_number(nvl, "psidlen", mape->psidlen);
214
nvlist_add_number(nvl, "psid", mape->psid);
215
216
return (nvl);
217
}
218
219
static int
220
pf_nvpool_to_pool(const nvlist_t *nvl, struct pf_kpool *kpool)
221
{
222
int error = 0;
223
224
PFNV_CHK(pf_nvbinary(nvl, "key", &kpool->key, sizeof(kpool->key)));
225
226
if (nvlist_exists_nvlist(nvl, "counter")) {
227
PFNV_CHK(pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "counter"),
228
&kpool->counter));
229
}
230
231
PFNV_CHK(pf_nvint(nvl, "tblidx", &kpool->tblidx));
232
PFNV_CHK(pf_nvuint16_array(nvl, "proxy_port", kpool->proxy_port, 2,
233
NULL));
234
PFNV_CHK(pf_nvuint8(nvl, "opts", &kpool->opts));
235
236
if (nvlist_exists_nvlist(nvl, "mape")) {
237
PFNV_CHK(pf_nvmape_to_mape(nvlist_get_nvlist(nvl, "mape"),
238
&kpool->mape));
239
}
240
241
errout:
242
return (error);
243
}
244
245
static nvlist_t *
246
pf_pool_to_nvpool(const struct pf_kpool *pool)
247
{
248
nvlist_t *nvl;
249
nvlist_t *tmp;
250
251
nvl = nvlist_create(0);
252
if (nvl == NULL)
253
return (NULL);
254
255
nvlist_add_binary(nvl, "key", &pool->key, sizeof(pool->key));
256
tmp = pf_addr_to_nvaddr(&pool->counter);
257
if (tmp == NULL)
258
goto error;
259
nvlist_add_nvlist(nvl, "counter", tmp);
260
nvlist_destroy(tmp);
261
262
nvlist_add_number(nvl, "tblidx", pool->tblidx);
263
pf_uint16_array_nv(nvl, "proxy_port", pool->proxy_port, 2);
264
nvlist_add_number(nvl, "opts", pool->opts);
265
266
tmp = pf_mape_to_nvmape(&pool->mape);
267
if (tmp == NULL)
268
goto error;
269
nvlist_add_nvlist(nvl, "mape", tmp);
270
nvlist_destroy(tmp);
271
272
return (nvl);
273
274
error:
275
nvlist_destroy(nvl);
276
return (NULL);
277
}
278
279
static int
280
pf_nvaddr_wrap_to_addr_wrap(const nvlist_t *nvl, struct pf_addr_wrap *addr)
281
{
282
int error = 0;
283
284
bzero(addr, sizeof(*addr));
285
286
PFNV_CHK(pf_nvuint8(nvl, "type", &addr->type));
287
PFNV_CHK(pf_nvuint8(nvl, "iflags", &addr->iflags));
288
if (addr->type == PF_ADDR_DYNIFTL)
289
PFNV_CHK(pf_nvstring(nvl, "ifname", addr->v.ifname,
290
sizeof(addr->v.ifname)));
291
if (addr->type == PF_ADDR_TABLE)
292
PFNV_CHK(pf_nvstring(nvl, "tblname", addr->v.tblname,
293
sizeof(addr->v.tblname)));
294
295
if (! nvlist_exists_nvlist(nvl, "addr"))
296
return (EINVAL);
297
PFNV_CHK(pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "addr"),
298
&addr->v.a.addr));
299
300
if (! nvlist_exists_nvlist(nvl, "mask"))
301
return (EINVAL);
302
PFNV_CHK(pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "mask"),
303
&addr->v.a.mask));
304
305
switch (addr->type) {
306
case PF_ADDR_DYNIFTL:
307
case PF_ADDR_TABLE:
308
case PF_ADDR_RANGE:
309
case PF_ADDR_ADDRMASK:
310
case PF_ADDR_NOROUTE:
311
case PF_ADDR_URPFFAILED:
312
break;
313
default:
314
return (EINVAL);
315
}
316
317
errout:
318
return (error);
319
}
320
321
static nvlist_t *
322
pf_addr_wrap_to_nvaddr_wrap(const struct pf_addr_wrap *addr)
323
{
324
nvlist_t *nvl;
325
nvlist_t *tmp;
326
uint64_t num;
327
struct pfr_ktable *kt;
328
329
nvl = nvlist_create(0);
330
if (nvl == NULL)
331
return (NULL);
332
333
nvlist_add_number(nvl, "type", addr->type);
334
nvlist_add_number(nvl, "iflags", addr->iflags);
335
if (addr->type == PF_ADDR_DYNIFTL) {
336
nvlist_add_string(nvl, "ifname", addr->v.ifname);
337
num = 0;
338
if (addr->p.dyn != NULL)
339
num = addr->p.dyn->pfid_acnt4 +
340
addr->p.dyn->pfid_acnt6;
341
nvlist_add_number(nvl, "dyncnt", num);
342
}
343
if (addr->type == PF_ADDR_TABLE) {
344
nvlist_add_string(nvl, "tblname", addr->v.tblname);
345
num = -1;
346
kt = addr->p.tbl;
347
if ((kt->pfrkt_flags & PFR_TFLAG_ACTIVE) &&
348
kt->pfrkt_root != NULL)
349
kt = kt->pfrkt_root;
350
if (kt->pfrkt_flags & PFR_TFLAG_ACTIVE)
351
num = kt->pfrkt_cnt;
352
nvlist_add_number(nvl, "tblcnt", num);
353
}
354
355
tmp = pf_addr_to_nvaddr(&addr->v.a.addr);
356
if (tmp == NULL)
357
goto error;
358
nvlist_add_nvlist(nvl, "addr", tmp);
359
nvlist_destroy(tmp);
360
tmp = pf_addr_to_nvaddr(&addr->v.a.mask);
361
if (tmp == NULL)
362
goto error;
363
nvlist_add_nvlist(nvl, "mask", tmp);
364
nvlist_destroy(tmp);
365
366
return (nvl);
367
368
error:
369
nvlist_destroy(nvl);
370
return (NULL);
371
}
372
373
static int
374
pf_validate_op(uint8_t op)
375
{
376
switch (op) {
377
case PF_OP_NONE:
378
case PF_OP_IRG:
379
case PF_OP_EQ:
380
case PF_OP_NE:
381
case PF_OP_LT:
382
case PF_OP_LE:
383
case PF_OP_GT:
384
case PF_OP_GE:
385
case PF_OP_XRG:
386
case PF_OP_RRG:
387
break;
388
default:
389
return (EINVAL);
390
}
391
392
return (0);
393
}
394
395
static int
396
pf_nvrule_addr_to_rule_addr(const nvlist_t *nvl, struct pf_rule_addr *addr)
397
{
398
int error = 0;
399
400
if (! nvlist_exists_nvlist(nvl, "addr"))
401
return (EINVAL);
402
403
PFNV_CHK(pf_nvaddr_wrap_to_addr_wrap(nvlist_get_nvlist(nvl, "addr"),
404
&addr->addr));
405
PFNV_CHK(pf_nvuint16_array(nvl, "port", addr->port, 2, NULL));
406
PFNV_CHK(pf_nvuint8(nvl, "neg", &addr->neg));
407
PFNV_CHK(pf_nvuint8(nvl, "port_op", &addr->port_op));
408
409
PFNV_CHK(pf_validate_op(addr->port_op));
410
411
errout:
412
return (error);
413
}
414
415
static nvlist_t *
416
pf_rule_addr_to_nvrule_addr(const struct pf_rule_addr *addr)
417
{
418
nvlist_t *nvl;
419
nvlist_t *tmp;
420
421
nvl = nvlist_create(0);
422
if (nvl == NULL)
423
return (NULL);
424
425
tmp = pf_addr_wrap_to_nvaddr_wrap(&addr->addr);
426
if (tmp == NULL)
427
goto error;
428
nvlist_add_nvlist(nvl, "addr", tmp);
429
nvlist_destroy(tmp);
430
pf_uint16_array_nv(nvl, "port", addr->port, 2);
431
nvlist_add_number(nvl, "neg", addr->neg);
432
nvlist_add_number(nvl, "port_op", addr->port_op);
433
434
return (nvl);
435
436
error:
437
nvlist_destroy(nvl);
438
return (NULL);
439
}
440
441
static int
442
pf_nvrule_uid_to_rule_uid(const nvlist_t *nvl, struct pf_rule_uid *uid)
443
{
444
int error = 0;
445
446
bzero(uid, sizeof(*uid));
447
448
PFNV_CHK(pf_nvuint32_array(nvl, "uid", uid->uid, 2, NULL));
449
PFNV_CHK(pf_nvuint8(nvl, "op", &uid->op));
450
451
PFNV_CHK(pf_validate_op(uid->op));
452
453
errout:
454
return (error);
455
}
456
457
static nvlist_t *
458
pf_rule_uid_to_nvrule_uid(const struct pf_rule_uid *uid)
459
{
460
nvlist_t *nvl;
461
462
nvl = nvlist_create(0);
463
if (nvl == NULL)
464
return (NULL);
465
466
pf_uint32_array_nv(nvl, "uid", uid->uid, 2);
467
nvlist_add_number(nvl, "op", uid->op);
468
469
return (nvl);
470
}
471
472
static int
473
pf_nvrule_gid_to_rule_gid(const nvlist_t *nvl, struct pf_rule_gid *gid)
474
{
475
/* Cheat a little. These stucts are the same, other than the name of
476
* the first field. */
477
return (pf_nvrule_uid_to_rule_uid(nvl, (struct pf_rule_uid *)gid));
478
}
479
480
int
481
pf_check_rule_addr(const struct pf_rule_addr *addr)
482
{
483
484
switch (addr->addr.type) {
485
case PF_ADDR_ADDRMASK:
486
case PF_ADDR_NOROUTE:
487
case PF_ADDR_DYNIFTL:
488
case PF_ADDR_TABLE:
489
case PF_ADDR_URPFFAILED:
490
case PF_ADDR_RANGE:
491
break;
492
default:
493
return (EINVAL);
494
}
495
496
if (addr->addr.p.dyn != NULL) {
497
return (EINVAL);
498
}
499
500
return (0);
501
}
502
503
504
int
505
pf_nvrule_to_krule(const nvlist_t *nvl, struct pf_krule *rule)
506
{
507
int error = 0;
508
uint8_t tmp;
509
510
#define ERROUT(x) ERROUT_FUNCTION(errout, x)
511
512
PFNV_CHK(pf_nvuint32(nvl, "nr", &rule->nr));
513
514
if (! nvlist_exists_nvlist(nvl, "src"))
515
ERROUT(EINVAL);
516
517
error = pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "src"),
518
&rule->src);
519
if (error != 0)
520
ERROUT(error);
521
522
if (! nvlist_exists_nvlist(nvl, "dst"))
523
ERROUT(EINVAL);
524
525
PFNV_CHK(pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "dst"),
526
&rule->dst));
527
528
if (nvlist_exists_string(nvl, "label")) {
529
PFNV_CHK(pf_nvstring(nvl, "label", rule->label[0],
530
sizeof(rule->label[0])));
531
} else if (nvlist_exists_string_array(nvl, "labels")) {
532
const char *const *strs;
533
size_t items;
534
int ret;
535
536
strs = nvlist_get_string_array(nvl, "labels", &items);
537
if (items > PF_RULE_MAX_LABEL_COUNT)
538
ERROUT(E2BIG);
539
540
for (size_t i = 0; i < items; i++) {
541
ret = strlcpy(rule->label[i], strs[i],
542
sizeof(rule->label[0]));
543
if (ret >= sizeof(rule->label[0]))
544
ERROUT(E2BIG);
545
}
546
}
547
548
PFNV_CHK(pf_nvuint32_opt(nvl, "ridentifier", &rule->ridentifier, 0));
549
PFNV_CHK(pf_nvstring(nvl, "ifname", rule->ifname,
550
sizeof(rule->ifname)));
551
PFNV_CHK(pf_nvstring(nvl, "qname", rule->qname, sizeof(rule->qname)));
552
PFNV_CHK(pf_nvstring(nvl, "pqname", rule->pqname,
553
sizeof(rule->pqname)));
554
PFNV_CHK(pf_nvstring(nvl, "tagname", rule->tagname,
555
sizeof(rule->tagname)));
556
PFNV_CHK(pf_nvuint16_opt(nvl, "dnpipe", &rule->dnpipe, 0));
557
PFNV_CHK(pf_nvuint16_opt(nvl, "dnrpipe", &rule->dnrpipe, 0));
558
PFNV_CHK(pf_nvuint32_opt(nvl, "dnflags", &rule->free_flags, 0));
559
PFNV_CHK(pf_nvstring(nvl, "match_tagname", rule->match_tagname,
560
sizeof(rule->match_tagname)));
561
PFNV_CHK(pf_nvstring(nvl, "overload_tblname", rule->overload_tblname,
562
sizeof(rule->overload_tblname)));
563
564
if (! nvlist_exists_nvlist(nvl, "rpool"))
565
ERROUT(EINVAL);
566
PFNV_CHK(pf_nvpool_to_pool(nvlist_get_nvlist(nvl, "rpool"),
567
&rule->rdr));
568
569
PFNV_CHK(pf_nvuint32(nvl, "os_fingerprint", &rule->os_fingerprint));
570
571
PFNV_CHK(pf_nvint(nvl, "rtableid", &rule->rtableid));
572
PFNV_CHK(pf_nvuint32_array(nvl, "timeout", rule->timeout, PFTM_MAX, NULL));
573
PFNV_CHK(pf_nvuint32(nvl, "max_states", &rule->max_states));
574
PFNV_CHK(pf_nvuint32(nvl, "max_src_nodes", &rule->max_src_nodes));
575
PFNV_CHK(pf_nvuint32(nvl, "max_src_states", &rule->max_src_states));
576
PFNV_CHK(pf_nvuint32(nvl, "max_src_conn", &rule->max_src_conn));
577
PFNV_CHK(pf_nvuint32(nvl, "max_src_conn_rate.limit",
578
&rule->max_src_conn_rate.limit));
579
PFNV_CHK(pf_nvuint32(nvl, "max_src_conn_rate.seconds",
580
&rule->max_src_conn_rate.seconds));
581
PFNV_CHK(pf_nvuint32(nvl, "prob", &rule->prob));
582
PFNV_CHK(pf_nvuint32(nvl, "cuid", &rule->cuid));
583
PFNV_CHK(pf_nvuint32(nvl, "cpid", &rule->cpid));
584
585
PFNV_CHK(pf_nvuint16(nvl, "return_icmp", &rule->return_icmp));
586
PFNV_CHK(pf_nvuint16(nvl, "return_icmp6", &rule->return_icmp6));
587
588
PFNV_CHK(pf_nvuint16(nvl, "max_mss", &rule->max_mss));
589
PFNV_CHK(pf_nvuint16(nvl, "scrub_flags", &rule->scrub_flags));
590
591
if (! nvlist_exists_nvlist(nvl, "uid"))
592
ERROUT(EINVAL);
593
PFNV_CHK(pf_nvrule_uid_to_rule_uid(nvlist_get_nvlist(nvl, "uid"),
594
&rule->uid));
595
596
if (! nvlist_exists_nvlist(nvl, "gid"))
597
ERROUT(EINVAL);
598
PFNV_CHK(pf_nvrule_gid_to_rule_gid(nvlist_get_nvlist(nvl, "gid"),
599
&rule->gid));
600
601
PFNV_CHK(pf_nvuint32(nvl, "rule_flag", &rule->rule_flag));
602
PFNV_CHK(pf_nvuint8(nvl, "action", &rule->action));
603
PFNV_CHK(pf_nvuint8(nvl, "direction", &rule->direction));
604
PFNV_CHK(pf_nvuint8(nvl, "log", &rule->log));
605
PFNV_CHK(pf_nvuint8(nvl, "logif", &rule->logif));
606
PFNV_CHK(pf_nvuint8(nvl, "quick", &rule->quick));
607
PFNV_CHK(pf_nvuint8(nvl, "ifnot", &rule->ifnot));
608
PFNV_CHK(pf_nvuint8(nvl, "match_tag_not", &rule->match_tag_not));
609
PFNV_CHK(pf_nvuint8(nvl, "natpass", &rule->natpass));
610
611
PFNV_CHK(pf_nvuint8(nvl, "keep_state", &rule->keep_state));
612
PFNV_CHK(pf_nvuint8(nvl, "af", &rule->af));
613
PFNV_CHK(pf_nvuint8(nvl, "proto", &rule->proto));
614
PFNV_CHK(pf_nvuint8(nvl, "type", &tmp));
615
rule->type = tmp;
616
PFNV_CHK(pf_nvuint8(nvl, "code", &tmp));
617
rule->code = tmp;
618
PFNV_CHK(pf_nvuint8(nvl, "flags", &rule->flags));
619
PFNV_CHK(pf_nvuint8(nvl, "flagset", &rule->flagset));
620
PFNV_CHK(pf_nvuint8(nvl, "min_ttl", &rule->min_ttl));
621
PFNV_CHK(pf_nvuint8(nvl, "allow_opts", &rule->allow_opts));
622
PFNV_CHK(pf_nvuint8(nvl, "rt", &rule->rt));
623
PFNV_CHK(pf_nvuint8(nvl, "return_ttl", &rule->return_ttl));
624
PFNV_CHK(pf_nvuint8(nvl, "tos", &rule->tos));
625
PFNV_CHK(pf_nvuint8(nvl, "set_tos", &rule->set_tos));
626
627
PFNV_CHK(pf_nvuint8(nvl, "flush", &rule->flush));
628
PFNV_CHK(pf_nvuint8(nvl, "prio", &rule->prio));
629
630
PFNV_CHK(pf_nvuint8_array(nvl, "set_prio", rule->set_prio, 2, NULL));
631
632
if (nvlist_exists_nvlist(nvl, "divert")) {
633
const nvlist_t *nvldivert = nvlist_get_nvlist(nvl, "divert");
634
635
if (! nvlist_exists_nvlist(nvldivert, "addr"))
636
ERROUT(EINVAL);
637
PFNV_CHK(pf_nvaddr_to_addr(nvlist_get_nvlist(nvldivert, "addr"),
638
&rule->divert.addr));
639
PFNV_CHK(pf_nvuint16(nvldivert, "port", &rule->divert.port));
640
}
641
642
/* Validation */
643
#ifndef INET
644
if (rule->af == AF_INET)
645
ERROUT(EAFNOSUPPORT);
646
#endif /* INET */
647
#ifndef INET6
648
if (rule->af == AF_INET6)
649
ERROUT(EAFNOSUPPORT);
650
#endif /* INET6 */
651
652
PFNV_CHK(pf_check_rule_addr(&rule->src));
653
PFNV_CHK(pf_check_rule_addr(&rule->dst));
654
655
return (0);
656
657
#undef ERROUT
658
errout:
659
return (error);
660
}
661
662
static nvlist_t *
663
pf_divert_to_nvdivert(const struct pf_krule *rule)
664
{
665
nvlist_t *nvl;
666
nvlist_t *tmp;
667
668
nvl = nvlist_create(0);
669
if (nvl == NULL)
670
return (NULL);
671
672
tmp = pf_addr_to_nvaddr(&rule->divert.addr);
673
if (tmp == NULL)
674
goto error;
675
nvlist_add_nvlist(nvl, "addr", tmp);
676
nvlist_destroy(tmp);
677
nvlist_add_number(nvl, "port", rule->divert.port);
678
679
return (nvl);
680
681
error:
682
nvlist_destroy(nvl);
683
return (NULL);
684
}
685
686
nvlist_t *
687
pf_krule_to_nvrule(struct pf_krule *rule)
688
{
689
nvlist_t *nvl, *tmp;
690
u_int64_t src_nodes_total = 0;
691
692
nvl = nvlist_create(0);
693
if (nvl == NULL)
694
return (nvl);
695
696
nvlist_add_number(nvl, "nr", rule->nr);
697
tmp = pf_rule_addr_to_nvrule_addr(&rule->src);
698
if (tmp == NULL)
699
goto error;
700
nvlist_add_nvlist(nvl, "src", tmp);
701
nvlist_destroy(tmp);
702
tmp = pf_rule_addr_to_nvrule_addr(&rule->dst);
703
if (tmp == NULL)
704
goto error;
705
nvlist_add_nvlist(nvl, "dst", tmp);
706
nvlist_destroy(tmp);
707
708
for (int i = 0; i < PF_SKIP_COUNT; i++) {
709
nvlist_append_number_array(nvl, "skip",
710
rule->skip[i] ? rule->skip[i]->nr : -1);
711
}
712
713
for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++) {
714
nvlist_append_string_array(nvl, "labels", rule->label[i]);
715
}
716
nvlist_add_string(nvl, "label", rule->label[0]);
717
nvlist_add_number(nvl, "ridentifier", rule->ridentifier);
718
nvlist_add_string(nvl, "ifname", rule->ifname);
719
nvlist_add_string(nvl, "qname", rule->qname);
720
nvlist_add_string(nvl, "pqname", rule->pqname);
721
nvlist_add_number(nvl, "dnpipe", rule->dnpipe);
722
nvlist_add_number(nvl, "dnrpipe", rule->dnrpipe);
723
nvlist_add_number(nvl, "dnflags", rule->free_flags);
724
nvlist_add_string(nvl, "tagname", rule->tagname);
725
nvlist_add_string(nvl, "match_tagname", rule->match_tagname);
726
nvlist_add_string(nvl, "overload_tblname", rule->overload_tblname);
727
728
tmp = pf_pool_to_nvpool(&rule->rdr);
729
if (tmp == NULL)
730
goto error;
731
nvlist_add_nvlist(nvl, "rpool", tmp);
732
nvlist_destroy(tmp);
733
734
nvlist_add_number(nvl, "evaluations",
735
pf_counter_u64_fetch(&rule->evaluations));
736
for (int i = 0; i < 2; i++) {
737
nvlist_append_number_array(nvl, "packets",
738
pf_counter_u64_fetch(&rule->packets[i]));
739
nvlist_append_number_array(nvl, "bytes",
740
pf_counter_u64_fetch(&rule->bytes[i]));
741
}
742
nvlist_add_number(nvl, "timestamp", pf_get_timestamp(rule));
743
744
nvlist_add_number(nvl, "os_fingerprint", rule->os_fingerprint);
745
746
nvlist_add_number(nvl, "rtableid", rule->rtableid);
747
pf_uint32_array_nv(nvl, "timeout", rule->timeout, PFTM_MAX);
748
nvlist_add_number(nvl, "max_states", rule->max_states);
749
nvlist_add_number(nvl, "max_src_nodes", rule->max_src_nodes);
750
nvlist_add_number(nvl, "max_src_states", rule->max_src_states);
751
nvlist_add_number(nvl, "max_src_conn", rule->max_src_conn);
752
nvlist_add_number(nvl, "max_src_conn_rate.limit",
753
rule->max_src_conn_rate.limit);
754
nvlist_add_number(nvl, "max_src_conn_rate.seconds",
755
rule->max_src_conn_rate.seconds);
756
nvlist_add_number(nvl, "qid", rule->qid);
757
nvlist_add_number(nvl, "pqid", rule->pqid);
758
nvlist_add_number(nvl, "prob", rule->prob);
759
nvlist_add_number(nvl, "cuid", rule->cuid);
760
nvlist_add_number(nvl, "cpid", rule->cpid);
761
762
nvlist_add_number(nvl, "states_cur",
763
counter_u64_fetch(rule->states_cur));
764
nvlist_add_number(nvl, "states_tot",
765
counter_u64_fetch(rule->states_tot));
766
for (pf_sn_types_t sn_type=0; sn_type<PF_SN_MAX; sn_type++)
767
src_nodes_total += counter_u64_fetch(rule->src_nodes[sn_type]);
768
nvlist_add_number(nvl, "src_nodes", src_nodes_total);
769
770
nvlist_add_number(nvl, "return_icmp", rule->return_icmp);
771
nvlist_add_number(nvl, "return_icmp6", rule->return_icmp6);
772
773
nvlist_add_number(nvl, "max_mss", rule->max_mss);
774
nvlist_add_number(nvl, "scrub_flags", rule->scrub_flags);
775
776
tmp = pf_rule_uid_to_nvrule_uid(&rule->uid);
777
if (tmp == NULL)
778
goto error;
779
nvlist_add_nvlist(nvl, "uid", tmp);
780
nvlist_destroy(tmp);
781
tmp = pf_rule_uid_to_nvrule_uid((const struct pf_rule_uid *)&rule->gid);
782
if (tmp == NULL)
783
goto error;
784
nvlist_add_nvlist(nvl, "gid", tmp);
785
nvlist_destroy(tmp);
786
787
nvlist_add_number(nvl, "rule_flag", rule->rule_flag);
788
nvlist_add_number(nvl, "action", rule->action);
789
nvlist_add_number(nvl, "direction", rule->direction);
790
nvlist_add_number(nvl, "log", rule->log);
791
nvlist_add_number(nvl, "logif", rule->logif);
792
nvlist_add_number(nvl, "quick", rule->quick);
793
nvlist_add_number(nvl, "ifnot", rule->ifnot);
794
nvlist_add_number(nvl, "match_tag_not", rule->match_tag_not);
795
nvlist_add_number(nvl, "natpass", rule->natpass);
796
797
nvlist_add_number(nvl, "keep_state", rule->keep_state);
798
nvlist_add_number(nvl, "af", rule->af);
799
nvlist_add_number(nvl, "proto", rule->proto);
800
nvlist_add_number(nvl, "type", rule->type);
801
nvlist_add_number(nvl, "code", rule->code);
802
nvlist_add_number(nvl, "flags", rule->flags);
803
nvlist_add_number(nvl, "flagset", rule->flagset);
804
nvlist_add_number(nvl, "min_ttl", rule->min_ttl);
805
nvlist_add_number(nvl, "allow_opts", rule->allow_opts);
806
nvlist_add_number(nvl, "rt", rule->rt);
807
nvlist_add_number(nvl, "return_ttl", rule->return_ttl);
808
nvlist_add_number(nvl, "tos", rule->tos);
809
nvlist_add_number(nvl, "set_tos", rule->set_tos);
810
nvlist_add_number(nvl, "anchor_relative", rule->anchor_relative);
811
nvlist_add_number(nvl, "anchor_wildcard", rule->anchor_wildcard);
812
813
nvlist_add_number(nvl, "flush", rule->flush);
814
nvlist_add_number(nvl, "prio", rule->prio);
815
816
pf_uint8_array_nv(nvl, "set_prio", rule->set_prio, 2);
817
818
tmp = pf_divert_to_nvdivert(rule);
819
if (tmp == NULL)
820
goto error;
821
nvlist_add_nvlist(nvl, "divert", tmp);
822
nvlist_destroy(tmp);
823
824
return (nvl);
825
826
error:
827
nvlist_destroy(nvl);
828
return (NULL);
829
}
830
831
static int
832
pf_nvstate_cmp_to_state_cmp(const nvlist_t *nvl, struct pf_state_cmp *cmp)
833
{
834
int error = 0;
835
836
bzero(cmp, sizeof(*cmp));
837
838
PFNV_CHK(pf_nvuint64(nvl, "id", &cmp->id));
839
PFNV_CHK(pf_nvuint32(nvl, "creatorid", &cmp->creatorid));
840
PFNV_CHK(pf_nvuint8(nvl, "direction", &cmp->direction));
841
842
errout:
843
return (error);
844
}
845
846
int
847
pf_nvstate_kill_to_kstate_kill(const nvlist_t *nvl,
848
struct pf_kstate_kill *kill)
849
{
850
int error = 0;
851
852
bzero(kill, sizeof(*kill));
853
854
if (! nvlist_exists_nvlist(nvl, "cmp"))
855
return (EINVAL);
856
857
PFNV_CHK(pf_nvstate_cmp_to_state_cmp(nvlist_get_nvlist(nvl, "cmp"),
858
&kill->psk_pfcmp));
859
PFNV_CHK(pf_nvuint8(nvl, "af", &kill->psk_af));
860
PFNV_CHK(pf_nvint(nvl, "proto", &kill->psk_proto));
861
862
if (! nvlist_exists_nvlist(nvl, "src"))
863
return (EINVAL);
864
PFNV_CHK(pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "src"),
865
&kill->psk_src));
866
if (! nvlist_exists_nvlist(nvl, "dst"))
867
return (EINVAL);
868
PFNV_CHK(pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "dst"),
869
&kill->psk_dst));
870
if (nvlist_exists_nvlist(nvl, "rt_addr")) {
871
PFNV_CHK(pf_nvrule_addr_to_rule_addr(
872
nvlist_get_nvlist(nvl, "rt_addr"), &kill->psk_rt_addr));
873
}
874
875
PFNV_CHK(pf_nvstring(nvl, "ifname", kill->psk_ifname,
876
sizeof(kill->psk_ifname)));
877
PFNV_CHK(pf_nvstring(nvl, "label", kill->psk_label,
878
sizeof(kill->psk_label)));
879
PFNV_CHK(pf_nvbool(nvl, "kill_match", &kill->psk_kill_match));
880
881
if (nvlist_exists_bool(nvl, "nat"))
882
PFNV_CHK(pf_nvbool(nvl, "nat", &kill->psk_nat));
883
884
errout:
885
return (error);
886
}
887
888
static nvlist_t *
889
pf_state_key_to_nvstate_key(const struct pf_state_key *key)
890
{
891
nvlist_t *nvl, *tmp;
892
893
nvl = nvlist_create(0);
894
if (nvl == NULL)
895
return (NULL);
896
897
for (int i = 0; i < 2; i++) {
898
tmp = pf_addr_to_nvaddr(&key->addr[i]);
899
if (tmp == NULL)
900
goto errout;
901
nvlist_append_nvlist_array(nvl, "addr", tmp);
902
nvlist_destroy(tmp);
903
nvlist_append_number_array(nvl, "port", key->port[i]);
904
}
905
nvlist_add_number(nvl, "af", key->af);
906
nvlist_add_number(nvl, "proto", key->proto);
907
908
return (nvl);
909
910
errout:
911
nvlist_destroy(nvl);
912
return (NULL);
913
}
914
915
static nvlist_t *
916
pf_state_peer_to_nvstate_peer(const struct pf_state_peer *peer)
917
{
918
nvlist_t *nvl;
919
920
nvl = nvlist_create(0);
921
if (nvl == NULL)
922
return (NULL);
923
924
nvlist_add_number(nvl, "seqlo", peer->seqlo);
925
nvlist_add_number(nvl, "seqhi", peer->seqhi);
926
nvlist_add_number(nvl, "seqdiff", peer->seqdiff);
927
nvlist_add_number(nvl, "state", peer->state);
928
nvlist_add_number(nvl, "wscale", peer->wscale);
929
930
return (nvl);
931
}
932
933
nvlist_t *
934
pf_state_to_nvstate(const struct pf_kstate *s)
935
{
936
nvlist_t *nvl, *tmp;
937
uint32_t expire, flags = 0;
938
939
nvl = nvlist_create(0);
940
if (nvl == NULL)
941
return (NULL);
942
943
nvlist_add_number(nvl, "id", s->id);
944
nvlist_add_string(nvl, "ifname", s->kif->pfik_name);
945
nvlist_add_string(nvl, "orig_ifname", s->orig_kif->pfik_name);
946
947
tmp = pf_state_key_to_nvstate_key(s->key[PF_SK_STACK]);
948
if (tmp == NULL)
949
goto errout;
950
nvlist_add_nvlist(nvl, "stack_key", tmp);
951
nvlist_destroy(tmp);
952
953
tmp = pf_state_key_to_nvstate_key(s->key[PF_SK_WIRE]);
954
if (tmp == NULL)
955
goto errout;
956
nvlist_add_nvlist(nvl, "wire_key", tmp);
957
nvlist_destroy(tmp);
958
959
tmp = pf_state_peer_to_nvstate_peer(&s->src);
960
if (tmp == NULL)
961
goto errout;
962
nvlist_add_nvlist(nvl, "src", tmp);
963
nvlist_destroy(tmp);
964
965
tmp = pf_state_peer_to_nvstate_peer(&s->dst);
966
if (tmp == NULL)
967
goto errout;
968
nvlist_add_nvlist(nvl, "dst", tmp);
969
nvlist_destroy(tmp);
970
971
tmp = pf_addr_to_nvaddr(&s->act.rt_addr);
972
if (tmp == NULL)
973
goto errout;
974
nvlist_add_nvlist(nvl, "rt_addr", tmp);
975
nvlist_destroy(tmp);
976
977
nvlist_add_number(nvl, "rule", s->rule ? s->rule->nr : -1);
978
nvlist_add_number(nvl, "anchor",
979
s->anchor ? s->anchor->nr : -1);
980
nvlist_add_number(nvl, "nat_rule",
981
s->nat_rule ? s->nat_rule->nr : -1);
982
nvlist_add_number(nvl, "creation", s->creation / 1000);
983
984
expire = pf_state_expires(s);
985
if (expire <= time_uptime)
986
expire = 0;
987
else
988
expire = expire - time_uptime;
989
nvlist_add_number(nvl, "expire", expire);
990
991
for (int i = 0; i < 2; i++) {
992
nvlist_append_number_array(nvl, "packets",
993
s->packets[i]);
994
nvlist_append_number_array(nvl, "bytes",
995
s->bytes[i]);
996
}
997
998
nvlist_add_number(nvl, "creatorid", s->creatorid);
999
nvlist_add_number(nvl, "direction", s->direction);
1000
nvlist_add_number(nvl, "state_flags", s->state_flags);
1001
if (s->sns[PF_SN_LIMIT] != NULL)
1002
flags |= PFSYNC_FLAG_SRCNODE;
1003
if (s->sns[PF_SN_NAT] != NULL || s->sns[PF_SN_ROUTE])
1004
flags |= PFSYNC_FLAG_NATSRCNODE;
1005
nvlist_add_number(nvl, "sync_flags", flags);
1006
1007
return (nvl);
1008
1009
errout:
1010
nvlist_destroy(nvl);
1011
return (NULL);
1012
}
1013
1014
static int
1015
pf_nveth_rule_addr_to_keth_rule_addr(const nvlist_t *nvl,
1016
struct pf_keth_rule_addr *krule)
1017
{
1018
static const u_int8_t EMPTY_MAC[ETHER_ADDR_LEN] = { 0 };
1019
int error = 0;
1020
1021
PFNV_CHK(pf_nvbinary(nvl, "addr", &krule->addr, sizeof(krule->addr)));
1022
PFNV_CHK(pf_nvbool(nvl, "neg", &krule->neg));
1023
if (nvlist_exists_binary(nvl, "mask"))
1024
PFNV_CHK(pf_nvbinary(nvl, "mask", &krule->mask,
1025
sizeof(krule->mask)));
1026
1027
/* To make checks for 'is this address set?' easier. */
1028
if (memcmp(krule->addr, EMPTY_MAC, ETHER_ADDR_LEN) != 0)
1029
krule->isset = 1;
1030
1031
errout:
1032
return (error);
1033
}
1034
1035
static nvlist_t*
1036
pf_keth_rule_addr_to_nveth_rule_addr(const struct pf_keth_rule_addr *krule)
1037
{
1038
nvlist_t *nvl;
1039
1040
nvl = nvlist_create(0);
1041
if (nvl == NULL)
1042
return (NULL);
1043
1044
nvlist_add_binary(nvl, "addr", &krule->addr, sizeof(krule->addr));
1045
nvlist_add_binary(nvl, "mask", &krule->mask, sizeof(krule->mask));
1046
nvlist_add_bool(nvl, "neg", krule->neg);
1047
1048
return (nvl);
1049
}
1050
1051
nvlist_t*
1052
pf_keth_rule_to_nveth_rule(const struct pf_keth_rule *krule)
1053
{
1054
nvlist_t *nvl, *addr;
1055
1056
nvl = nvlist_create(0);
1057
if (nvl == NULL)
1058
return (NULL);
1059
1060
for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++) {
1061
nvlist_append_string_array(nvl, "labels", krule->label[i]);
1062
}
1063
nvlist_add_number(nvl, "ridentifier", krule->ridentifier);
1064
1065
nvlist_add_number(nvl, "nr", krule->nr);
1066
nvlist_add_bool(nvl, "quick", krule->quick);
1067
nvlist_add_string(nvl, "ifname", krule->ifname);
1068
nvlist_add_bool(nvl, "ifnot", krule->ifnot);
1069
nvlist_add_number(nvl, "direction", krule->direction);
1070
nvlist_add_number(nvl, "proto", krule->proto);
1071
nvlist_add_string(nvl, "match_tagname", krule->match_tagname);
1072
nvlist_add_number(nvl, "match_tag", krule->match_tag);
1073
nvlist_add_bool(nvl, "match_tag_not", krule->match_tag_not);
1074
1075
addr = pf_keth_rule_addr_to_nveth_rule_addr(&krule->src);
1076
if (addr == NULL) {
1077
nvlist_destroy(nvl);
1078
return (NULL);
1079
}
1080
nvlist_add_nvlist(nvl, "src", addr);
1081
nvlist_destroy(addr);
1082
1083
addr = pf_keth_rule_addr_to_nveth_rule_addr(&krule->dst);
1084
if (addr == NULL) {
1085
nvlist_destroy(nvl);
1086
return (NULL);
1087
}
1088
nvlist_add_nvlist(nvl, "dst", addr);
1089
nvlist_destroy(addr);
1090
1091
addr = pf_rule_addr_to_nvrule_addr(&krule->ipsrc);
1092
if (addr == NULL) {
1093
nvlist_destroy(nvl);
1094
return (NULL);
1095
}
1096
nvlist_add_nvlist(nvl, "ipsrc", addr);
1097
nvlist_destroy(addr);
1098
1099
addr = pf_rule_addr_to_nvrule_addr(&krule->ipdst);
1100
if (addr == NULL) {
1101
nvlist_destroy(nvl);
1102
return (NULL);
1103
}
1104
nvlist_add_nvlist(nvl, "ipdst", addr);
1105
nvlist_destroy(addr);
1106
1107
nvlist_add_number(nvl, "evaluations",
1108
counter_u64_fetch(krule->evaluations));
1109
nvlist_add_number(nvl, "packets-in",
1110
counter_u64_fetch(krule->packets[0]));
1111
nvlist_add_number(nvl, "packets-out",
1112
counter_u64_fetch(krule->packets[1]));
1113
nvlist_add_number(nvl, "bytes-in",
1114
counter_u64_fetch(krule->bytes[0]));
1115
nvlist_add_number(nvl, "bytes-out",
1116
counter_u64_fetch(krule->bytes[1]));
1117
1118
nvlist_add_number(nvl, "timestamp", pf_get_timestamp(krule));
1119
nvlist_add_string(nvl, "qname", krule->qname);
1120
nvlist_add_string(nvl, "tagname", krule->tagname);
1121
1122
nvlist_add_number(nvl, "dnpipe", krule->dnpipe);
1123
nvlist_add_number(nvl, "dnflags", krule->dnflags);
1124
1125
nvlist_add_number(nvl, "anchor_relative", krule->anchor_relative);
1126
nvlist_add_number(nvl, "anchor_wildcard", krule->anchor_wildcard);
1127
1128
nvlist_add_string(nvl, "bridge_to", krule->bridge_to_name);
1129
nvlist_add_number(nvl, "action", krule->action);
1130
1131
return (nvl);
1132
}
1133
1134
int
1135
pf_nveth_rule_to_keth_rule(const nvlist_t *nvl,
1136
struct pf_keth_rule *krule)
1137
{
1138
int error = 0;
1139
1140
#define ERROUT(x) ERROUT_FUNCTION(errout, x)
1141
1142
bzero(krule, sizeof(*krule));
1143
1144
if (nvlist_exists_string_array(nvl, "labels")) {
1145
const char *const *strs;
1146
size_t items;
1147
int ret;
1148
1149
strs = nvlist_get_string_array(nvl, "labels", &items);
1150
if (items > PF_RULE_MAX_LABEL_COUNT)
1151
ERROUT(E2BIG);
1152
1153
for (size_t i = 0; i < items; i++) {
1154
ret = strlcpy(krule->label[i], strs[i],
1155
sizeof(krule->label[0]));
1156
if (ret >= sizeof(krule->label[0]))
1157
ERROUT(E2BIG);
1158
}
1159
}
1160
1161
PFNV_CHK(pf_nvuint32_opt(nvl, "ridentifier", &krule->ridentifier, 0));
1162
1163
PFNV_CHK(pf_nvuint32(nvl, "nr", &krule->nr));
1164
PFNV_CHK(pf_nvbool(nvl, "quick", &krule->quick));
1165
PFNV_CHK(pf_nvstring(nvl, "ifname", krule->ifname,
1166
sizeof(krule->ifname)));
1167
PFNV_CHK(pf_nvbool(nvl, "ifnot", &krule->ifnot));
1168
PFNV_CHK(pf_nvuint8(nvl, "direction", &krule->direction));
1169
PFNV_CHK(pf_nvuint16(nvl, "proto", &krule->proto));
1170
1171
if (nvlist_exists_nvlist(nvl, "src")) {
1172
error = pf_nveth_rule_addr_to_keth_rule_addr(
1173
nvlist_get_nvlist(nvl, "src"), &krule->src);
1174
if (error)
1175
return (error);
1176
}
1177
if (nvlist_exists_nvlist(nvl, "dst")) {
1178
error = pf_nveth_rule_addr_to_keth_rule_addr(
1179
nvlist_get_nvlist(nvl, "dst"), &krule->dst);
1180
if (error)
1181
return (error);
1182
}
1183
1184
if (nvlist_exists_nvlist(nvl, "ipsrc")) {
1185
error = pf_nvrule_addr_to_rule_addr(
1186
nvlist_get_nvlist(nvl, "ipsrc"), &krule->ipsrc);
1187
if (error != 0)
1188
return (error);
1189
1190
if (krule->ipsrc.addr.type != PF_ADDR_ADDRMASK &&
1191
krule->ipsrc.addr.type != PF_ADDR_TABLE)
1192
return (EINVAL);
1193
}
1194
1195
if (nvlist_exists_nvlist(nvl, "ipdst")) {
1196
error = pf_nvrule_addr_to_rule_addr(
1197
nvlist_get_nvlist(nvl, "ipdst"), &krule->ipdst);
1198
if (error != 0)
1199
return (error);
1200
1201
if (krule->ipdst.addr.type != PF_ADDR_ADDRMASK &&
1202
krule->ipdst.addr.type != PF_ADDR_TABLE)
1203
return (EINVAL);
1204
}
1205
1206
if (nvlist_exists_string(nvl, "match_tagname")) {
1207
PFNV_CHK(pf_nvstring(nvl, "match_tagname", krule->match_tagname,
1208
sizeof(krule->match_tagname)));
1209
PFNV_CHK(pf_nvbool(nvl, "match_tag_not", &krule->match_tag_not));
1210
}
1211
1212
PFNV_CHK(pf_nvstring(nvl, "qname", krule->qname, sizeof(krule->qname)));
1213
PFNV_CHK(pf_nvstring(nvl, "tagname", krule->tagname,
1214
sizeof(krule->tagname)));
1215
1216
PFNV_CHK(pf_nvuint16_opt(nvl, "dnpipe", &krule->dnpipe, 0));
1217
PFNV_CHK(pf_nvuint32_opt(nvl, "dnflags", &krule->dnflags, 0));
1218
PFNV_CHK(pf_nvstring(nvl, "bridge_to", krule->bridge_to_name,
1219
sizeof(krule->bridge_to_name)));
1220
1221
PFNV_CHK(pf_nvuint8(nvl, "action", &krule->action));
1222
1223
if (krule->action != PF_PASS && krule->action != PF_DROP &&
1224
krule->action != PF_MATCH)
1225
return (EBADMSG);
1226
1227
#undef ERROUT
1228
errout:
1229
return (error);
1230
}
1231
1232