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
pf_nvbool(const nvlist_t * nvl,const char * name,bool * val)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
pf_nvbinary(const nvlist_t * nvl,const char * name,void * data,size_t expected_size)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
pf_nvint(const nvlist_t * nvl,const char * name,int * val)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
pf_nvstring(const nvlist_t * nvl,const char * name,char * str,size_t maxlen)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
pf_nvaddr_to_addr(const nvlist_t * nvl,struct pf_addr * paddr)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 *
pf_addr_to_nvaddr(const struct pf_addr * paddr)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
pf_nvmape_to_mape(const nvlist_t * nvl,struct pf_mape_portset * mape)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 *
pf_mape_to_nvmape(const struct pf_mape_portset * mape)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
pf_nvpool_to_pool(const nvlist_t * nvl,struct pf_kpool * kpool)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 *
pf_pool_to_nvpool(const struct pf_kpool * pool)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
pf_nvaddr_wrap_to_addr_wrap(const nvlist_t * nvl,struct pf_addr_wrap * addr)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 *
pf_addr_wrap_to_nvaddr_wrap(const struct pf_addr_wrap * addr)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
pf_validate_op(uint8_t op)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
pf_nvrule_addr_to_rule_addr(const nvlist_t * nvl,struct pf_rule_addr * addr)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 *
pf_rule_addr_to_nvrule_addr(const struct pf_rule_addr * addr)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
pf_nvrule_uid_to_rule_uid(const nvlist_t * nvl,struct pf_rule_uid * uid)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 *
pf_rule_uid_to_nvrule_uid(const struct pf_rule_uid * uid)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
pf_nvrule_gid_to_rule_gid(const nvlist_t * nvl,struct pf_rule_gid * gid)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
pf_check_rule_addr(const struct pf_rule_addr * addr)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
pf_nvrule_to_krule(const nvlist_t * nvl,struct pf_krule * rule)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 *
pf_divert_to_nvdivert(const struct pf_krule * rule)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 *
pf_krule_to_nvrule(struct pf_krule * rule)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
pf_nvstate_cmp_to_state_cmp(const nvlist_t * nvl,struct pf_state_cmp * cmp)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
pf_nvstate_kill_to_kstate_kill(const nvlist_t * nvl,struct pf_kstate_kill * kill)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 *
pf_state_key_to_nvstate_key(const struct pf_state_key * key)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 *
pf_state_peer_to_nvstate_peer(const struct pf_state_peer * peer)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 *
pf_state_to_nvstate(const struct pf_kstate * s)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
pf_nveth_rule_addr_to_keth_rule_addr(const nvlist_t * nvl,struct pf_keth_rule_addr * krule)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*
pf_keth_rule_addr_to_nveth_rule_addr(const struct pf_keth_rule_addr * krule)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*
pf_keth_rule_to_nveth_rule(const struct pf_keth_rule * krule)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
pf_nveth_rule_to_keth_rule(const nvlist_t * nvl,struct pf_keth_rule * krule)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