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