]> git.proxmox.com Git - mirror_frr.git/blob - lib/filter_nb.c
Merge pull request #12797 from jvidalallende/ubi8_minimal_dockerfile
[mirror_frr.git] / lib / filter_nb.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * FRR filter northbound implementation.
4 *
5 * Copyright (C) 2019 Network Device Education Foundation, Inc. ("NetDEF")
6 * Rafael Zalamena
7 */
8
9 #include "zebra.h"
10
11 #include "lib/northbound.h"
12 #include "lib/prefix.h"
13 #include "lib/printfrr.h"
14
15 #include "lib/filter.h"
16 #include "lib/plist.h"
17 #include "lib/plist_int.h"
18 #include "lib/routemap.h"
19
20 /* Helper function. */
21 static void acl_notify_route_map(struct access_list *acl, int route_map_event)
22 {
23 switch (route_map_event) {
24 case RMAP_EVENT_FILTER_ADDED:
25 if (acl->master->add_hook)
26 (*acl->master->add_hook)(acl);
27 break;
28 case RMAP_EVENT_FILTER_DELETED:
29 if (acl->master->delete_hook)
30 (*acl->master->delete_hook)(acl);
31 break;
32 }
33
34 route_map_notify_dependencies(acl->name, route_map_event);
35 }
36
37 static enum nb_error prefix_list_length_validate(struct nb_cb_modify_args *args)
38 {
39 int type = yang_dnode_get_enum(args->dnode, "../../type");
40 const char *xpath_le = NULL, *xpath_ge = NULL;
41 struct prefix p;
42 uint8_t le, ge;
43
44 if (type == YPLT_IPV4) {
45 yang_dnode_get_prefix(&p, args->dnode, "../ipv4-prefix");
46 xpath_le = "../ipv4-prefix-length-lesser-or-equal";
47 xpath_ge = "../ipv4-prefix-length-greater-or-equal";
48 } else {
49 yang_dnode_get_prefix(&p, args->dnode, "../ipv6-prefix");
50 xpath_le = "../ipv6-prefix-length-lesser-or-equal";
51 xpath_ge = "../ipv6-prefix-length-greater-or-equal";
52 }
53
54 /*
55 * Check rule:
56 * prefix length <= le.
57 */
58 if (yang_dnode_exists(args->dnode, xpath_le)) {
59 le = yang_dnode_get_uint8(args->dnode, "%s", xpath_le);
60 if (p.prefixlen > le)
61 goto log_and_fail;
62 }
63
64 /*
65 * Check rule:
66 * prefix length <= ge.
67 */
68 if (yang_dnode_exists(args->dnode, xpath_ge)) {
69 ge = yang_dnode_get_uint8(args->dnode, "%s", xpath_ge);
70 if (p.prefixlen > ge)
71 goto log_and_fail;
72 }
73
74 /*
75 * Check rule:
76 * ge <= le.
77 */
78 if (yang_dnode_exists(args->dnode, xpath_le)
79 && yang_dnode_exists(args->dnode, xpath_ge)) {
80 le = yang_dnode_get_uint8(args->dnode, "%s", xpath_le);
81 ge = yang_dnode_get_uint8(args->dnode, "%s", xpath_ge);
82 if (ge > le)
83 goto log_and_fail;
84 }
85
86 return NB_OK;
87
88 log_and_fail:
89 snprintfrr(
90 args->errmsg, args->errmsg_len,
91 "Invalid prefix range for %pFX: Make sure that mask length <= ge <= le",
92 &p);
93 return NB_ERR_VALIDATION;
94 }
95
96 /**
97 * Sets prefix list entry to blank value.
98 *
99 * \param[out] ple prefix list entry to modify.
100 */
101 static void prefix_list_entry_set_empty(struct prefix_list_entry *ple)
102 {
103 ple->any = false;
104 memset(&ple->prefix, 0, sizeof(ple->prefix));
105 ple->ge = 0;
106 ple->le = 0;
107 }
108
109 static int
110 prefix_list_nb_validate_v4_af_type(const struct lyd_node *plist_dnode,
111 char *errmsg, size_t errmsg_len)
112 {
113 int af_type;
114
115 af_type = yang_dnode_get_enum(plist_dnode, "./type");
116 if (af_type != YPLT_IPV4) {
117 snprintf(errmsg, errmsg_len,
118 "prefix-list type %u is mismatched.", af_type);
119 return NB_ERR_VALIDATION;
120 }
121
122 return NB_OK;
123 }
124
125 static int
126 prefix_list_nb_validate_v6_af_type(const struct lyd_node *plist_dnode,
127 char *errmsg, size_t errmsg_len)
128 {
129 int af_type;
130
131 af_type = yang_dnode_get_enum(plist_dnode, "./type");
132 if (af_type != YPLT_IPV6) {
133 snprintf(errmsg, errmsg_len,
134 "prefix-list type %u is mismatched.", af_type);
135 return NB_ERR_VALIDATION;
136 }
137
138 return NB_OK;
139 }
140
141 static int lib_prefix_list_entry_prefix_length_greater_or_equal_modify(
142 struct nb_cb_modify_args *args)
143 {
144 struct prefix_list_entry *ple;
145
146 if (args->event != NB_EV_APPLY)
147 return NB_OK;
148
149 ple = nb_running_get_entry(args->dnode, NULL, true);
150
151 /* Start prefix entry update procedure. */
152 prefix_list_entry_update_start(ple);
153
154 ple->ge = yang_dnode_get_uint8(args->dnode, NULL);
155
156 /* Finish prefix entry update procedure. */
157 prefix_list_entry_update_finish(ple);
158
159 return NB_OK;
160 }
161
162 static int lib_prefix_list_entry_prefix_length_lesser_or_equal_modify(
163 struct nb_cb_modify_args *args)
164 {
165 struct prefix_list_entry *ple;
166
167 if (args->event != NB_EV_APPLY)
168 return NB_OK;
169
170 ple = nb_running_get_entry(args->dnode, NULL, true);
171
172 /* Start prefix entry update procedure. */
173 prefix_list_entry_update_start(ple);
174
175 ple->le = yang_dnode_get_uint8(args->dnode, NULL);
176
177 /* Finish prefix entry update procedure. */
178 prefix_list_entry_update_finish(ple);
179
180 return NB_OK;
181 }
182
183 static int lib_prefix_list_entry_prefix_length_greater_or_equal_destroy(
184 struct nb_cb_destroy_args *args)
185 {
186 struct prefix_list_entry *ple;
187
188 if (args->event != NB_EV_APPLY)
189 return NB_OK;
190
191 ple = nb_running_get_entry(args->dnode, NULL, true);
192
193 /* Start prefix entry update procedure. */
194 prefix_list_entry_update_start(ple);
195
196 ple->ge = 0;
197
198 /* Finish prefix entry update procedure. */
199 prefix_list_entry_update_finish(ple);
200
201 return NB_OK;
202 }
203
204 static int lib_prefix_list_entry_prefix_length_lesser_or_equal_destroy(
205 struct nb_cb_destroy_args *args)
206 {
207 struct prefix_list_entry *ple;
208
209 if (args->event != NB_EV_APPLY)
210 return NB_OK;
211
212 ple = nb_running_get_entry(args->dnode, NULL, true);
213
214 /* Start prefix entry update procedure. */
215 prefix_list_entry_update_start(ple);
216
217 ple->le = 0;
218
219 /* Finish prefix entry update procedure. */
220 prefix_list_entry_update_finish(ple);
221
222 return NB_OK;
223 }
224
225 /**
226 * Unsets the cisco style rule for addresses so it becomes disabled (the
227 * equivalent of setting: `0.0.0.0/32`).
228 *
229 * \param addr address part.
230 * \param mask mask part.
231 */
232 static void cisco_unset_addr_mask(struct in_addr *addr, struct in_addr *mask)
233 {
234 addr->s_addr = INADDR_ANY;
235 mask->s_addr = CISCO_BIN_HOST_WILDCARD_MASK;
236 }
237
238 static int _acl_is_dup(const struct lyd_node *dnode, void *arg)
239 {
240 struct acl_dup_args *ada = arg;
241 int idx;
242
243 /* This entry is the caller, so skip it. */
244 if (ada->ada_entry_dnode
245 && ada->ada_entry_dnode == dnode)
246 return YANG_ITER_CONTINUE;
247
248 if (strcmp(yang_dnode_get_string(dnode, "action"), ada->ada_action))
249 return YANG_ITER_CONTINUE;
250
251 /* Check if all values match. */
252 for (idx = 0; idx < ADA_MAX_VALUES; idx++) {
253 /* No more values. */
254 if (ada->ada_xpath[idx] == NULL)
255 break;
256
257 /* Not same type, just skip it. */
258 if (!yang_dnode_exists(dnode, ada->ada_xpath[idx]))
259 return YANG_ITER_CONTINUE;
260
261 /* Check if different value. */
262 if (strcmp(yang_dnode_get_string(dnode, "%s",
263 ada->ada_xpath[idx]),
264 ada->ada_value[idx]))
265 return YANG_ITER_CONTINUE;
266 }
267
268 ada->ada_found = true;
269 ada->ada_seq = yang_dnode_get_uint32(dnode, "sequence");
270
271 return YANG_ITER_STOP;
272 }
273
274 bool acl_is_dup(const struct lyd_node *dnode, struct acl_dup_args *ada)
275 {
276 ada->ada_found = false;
277
278 yang_dnode_iterate(
279 _acl_is_dup, ada, dnode,
280 "/frr-filter:lib/access-list[type='%s'][name='%s']/entry",
281 ada->ada_type, ada->ada_name);
282
283 return ada->ada_found;
284 }
285
286 static bool acl_cisco_is_dup(const struct lyd_node *dnode)
287 {
288 const struct lyd_node *entry_dnode =
289 yang_dnode_get_parent(dnode, "entry");
290 struct acl_dup_args ada = {};
291 int idx = 0, arg_idx = 0;
292 static const char *cisco_entries[] = {
293 "./host",
294 "./network/address",
295 "./network/mask",
296 "./source-any",
297 "./destination-host",
298 "./destination-network/address",
299 "./destination-network/mask",
300 "./destination-any",
301 NULL
302 };
303
304 /* Initialize. */
305 ada.ada_type = "ipv4";
306 ada.ada_name = yang_dnode_get_string(entry_dnode, "../name");
307 ada.ada_action = yang_dnode_get_string(entry_dnode, "action");
308 ada.ada_entry_dnode = entry_dnode;
309
310 /* Load all values/XPaths. */
311 while (cisco_entries[idx] != NULL) {
312 if (!yang_dnode_exists(entry_dnode, cisco_entries[idx])) {
313 idx++;
314 continue;
315 }
316
317 ada.ada_xpath[arg_idx] = cisco_entries[idx];
318 ada.ada_value[arg_idx] = yang_dnode_get_string(
319 entry_dnode, "%s", cisco_entries[idx]);
320 arg_idx++;
321 idx++;
322 }
323
324 return acl_is_dup(entry_dnode, &ada);
325 }
326
327 static bool acl_zebra_is_dup(const struct lyd_node *dnode,
328 enum yang_access_list_type type)
329 {
330 const struct lyd_node *entry_dnode =
331 yang_dnode_get_parent(dnode, "entry");
332 struct acl_dup_args ada = {};
333 int idx = 0, arg_idx = 0;
334 static const char *zebra_entries[] = {
335 "./ipv4-prefix",
336 "./ipv4-exact-match",
337 "./ipv6-prefix",
338 "./ipv6-exact-match",
339 "./mac",
340 "./any",
341 NULL
342 };
343
344 /* Initialize. */
345 switch (type) {
346 case YALT_IPV4:
347 ada.ada_type = "ipv4";
348 break;
349 case YALT_IPV6:
350 ada.ada_type = "ipv6";
351 break;
352 case YALT_MAC:
353 ada.ada_type = "mac";
354 break;
355 }
356 ada.ada_name = yang_dnode_get_string(entry_dnode, "../name");
357 ada.ada_action = yang_dnode_get_string(entry_dnode, "action");
358 ada.ada_entry_dnode = entry_dnode;
359
360 /* Load all values/XPaths. */
361 while (zebra_entries[idx] != NULL) {
362 if (!yang_dnode_exists(entry_dnode, zebra_entries[idx])) {
363 idx++;
364 continue;
365 }
366
367 ada.ada_xpath[arg_idx] = zebra_entries[idx];
368 ada.ada_value[arg_idx] = yang_dnode_get_string(
369 entry_dnode, "%s", zebra_entries[idx]);
370 arg_idx++;
371 idx++;
372 }
373
374 return acl_is_dup(entry_dnode, &ada);
375 }
376
377 static void plist_dnode_to_prefix(const struct lyd_node *dnode, bool *any,
378 struct prefix *p, int *ge, int *le)
379 {
380 *any = false;
381 *ge = 0;
382 *le = 0;
383
384 if (yang_dnode_exists(dnode, "./any")) {
385 *any = true;
386 return;
387 }
388
389 switch (yang_dnode_get_enum(dnode, "../type")) {
390 case YPLT_IPV4:
391 yang_dnode_get_prefix(p, dnode, "./ipv4-prefix");
392 if (yang_dnode_exists(dnode,
393 "./ipv4-prefix-length-greater-or-equal"))
394 *ge = yang_dnode_get_uint8(
395 dnode, "./ipv4-prefix-length-greater-or-equal");
396 if (yang_dnode_exists(dnode,
397 "./ipv4-prefix-length-lesser-or-equal"))
398 *le = yang_dnode_get_uint8(
399 dnode, "./ipv4-prefix-length-lesser-or-equal");
400 break;
401 case YPLT_IPV6:
402 yang_dnode_get_prefix(p, dnode, "./ipv6-prefix");
403 if (yang_dnode_exists(dnode,
404 "./ipv6-prefix-length-greater-or-equal"))
405 *ge = yang_dnode_get_uint8(
406 dnode, "./ipv6-prefix-length-greater-or-equal");
407 if (yang_dnode_exists(dnode,
408 "./ipv6-prefix-length-lesser-or-equal"))
409 *le = yang_dnode_get_uint8(
410 dnode, "./ipv6-prefix-length-lesser-or-equal");
411 break;
412 }
413 }
414
415 static int _plist_is_dup(const struct lyd_node *dnode, void *arg)
416 {
417 struct plist_dup_args *pda = arg;
418 struct prefix p = {};
419 int ge, le;
420 bool any;
421
422 /* This entry is the caller, so skip it. */
423 if (pda->pda_entry_dnode
424 && pda->pda_entry_dnode == dnode)
425 return YANG_ITER_CONTINUE;
426
427 if (strcmp(yang_dnode_get_string(dnode, "action"), pda->pda_action))
428 return YANG_ITER_CONTINUE;
429
430 plist_dnode_to_prefix(dnode, &any, &p, &ge, &le);
431
432 if (pda->any) {
433 if (!any)
434 return YANG_ITER_CONTINUE;
435 } else {
436 if (!prefix_same(&pda->prefix, &p) || pda->ge != ge
437 || pda->le != le)
438 return YANG_ITER_CONTINUE;
439 }
440
441 pda->pda_found = true;
442 pda->pda_seq = yang_dnode_get_uint32(dnode, "sequence");
443
444 return YANG_ITER_STOP;
445 }
446
447 bool plist_is_dup(const struct lyd_node *dnode, struct plist_dup_args *pda)
448 {
449 pda->pda_found = false;
450
451 yang_dnode_iterate(
452 _plist_is_dup, pda, dnode,
453 "/frr-filter:lib/prefix-list[type='%s'][name='%s']/entry",
454 pda->pda_type, pda->pda_name);
455
456 return pda->pda_found;
457 }
458
459 /*
460 * XPath: /frr-filter:lib/access-list
461 */
462 static int lib_access_list_create(struct nb_cb_create_args *args)
463 {
464 struct access_list *acl = NULL;
465 const char *acl_name;
466 int type;
467
468 if (args->event != NB_EV_APPLY)
469 return NB_OK;
470
471 type = yang_dnode_get_enum(args->dnode, "./type");
472 acl_name = yang_dnode_get_string(args->dnode, "./name");
473
474 switch (type) {
475 case YALT_IPV4:
476 acl = access_list_get(AFI_IP, acl_name);
477 break;
478 case YALT_IPV6:
479 acl = access_list_get(AFI_IP6, acl_name);
480 break;
481 case YALT_MAC:
482 acl = access_list_get(AFI_L2VPN, acl_name);
483 break;
484 }
485
486 nb_running_set_entry(args->dnode, acl);
487
488 return NB_OK;
489 }
490
491 static int lib_access_list_destroy(struct nb_cb_destroy_args *args)
492 {
493 struct access_list *acl;
494
495 if (args->event != NB_EV_APPLY)
496 return NB_OK;
497
498 acl = nb_running_unset_entry(args->dnode);
499 access_list_delete(acl);
500
501 return NB_OK;
502 }
503
504 /*
505 * XPath: /frr-filter:lib/access-list/remark
506 */
507 static int lib_access_list_remark_modify(struct nb_cb_modify_args *args)
508 {
509 struct access_list *acl;
510 const char *remark;
511
512 if (args->event != NB_EV_APPLY)
513 return NB_OK;
514
515 acl = nb_running_get_entry(args->dnode, NULL, true);
516 if (acl->remark)
517 XFREE(MTYPE_TMP, acl->remark);
518
519 remark = yang_dnode_get_string(args->dnode, NULL);
520 acl->remark = XSTRDUP(MTYPE_TMP, remark);
521
522 return NB_OK;
523 }
524
525 static int
526 lib_access_list_remark_destroy(struct nb_cb_destroy_args *args)
527 {
528 struct access_list *acl;
529
530 if (args->event != NB_EV_APPLY)
531 return NB_OK;
532
533 acl = nb_running_get_entry(args->dnode, NULL, true);
534 if (acl->remark)
535 XFREE(MTYPE_TMP, acl->remark);
536
537 return NB_OK;
538 }
539
540
541 /*
542 * XPath: /frr-filter:lib/access-list/entry
543 */
544 static int lib_access_list_entry_create(struct nb_cb_create_args *args)
545 {
546 struct access_list *acl;
547 struct filter *f;
548
549 if (args->event != NB_EV_APPLY)
550 return NB_OK;
551
552 f = filter_new();
553 f->seq = yang_dnode_get_uint32(args->dnode, "./sequence");
554
555 acl = nb_running_get_entry(args->dnode, NULL, true);
556 f->acl = acl;
557 access_list_filter_add(acl, f);
558 nb_running_set_entry(args->dnode, f);
559
560 return NB_OK;
561 }
562
563 static int lib_access_list_entry_destroy(struct nb_cb_destroy_args *args)
564 {
565 struct access_list *acl;
566 struct filter *f;
567
568 if (args->event != NB_EV_APPLY)
569 return NB_OK;
570
571 f = nb_running_unset_entry(args->dnode);
572 acl = f->acl;
573 access_list_filter_delete(acl, f);
574
575 return NB_OK;
576 }
577
578 /*
579 * XPath: /frr-filter:lib/access-list/entry/action
580 */
581 static int
582 lib_access_list_entry_action_modify(struct nb_cb_modify_args *args)
583 {
584 const char *filter_type;
585 struct filter *f;
586
587 if (args->event != NB_EV_APPLY)
588 return NB_OK;
589
590 f = nb_running_get_entry(args->dnode, NULL, true);
591 filter_type = yang_dnode_get_string(args->dnode, NULL);
592 if (strcmp(filter_type, "permit") == 0)
593 f->type = FILTER_PERMIT;
594 else
595 f->type = FILTER_DENY;
596
597 acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_ADDED);
598
599 return NB_OK;
600 }
601
602 /*
603 * XPath: /frr-filter:lib/access-list/entry/ipv4-prefix
604 */
605 static int
606 lib_access_list_entry_ipv4_prefix_modify(struct nb_cb_modify_args *args)
607 {
608 struct filter_zebra *fz;
609 struct filter *f;
610
611 /* Don't allow duplicated values. */
612 if (args->event == NB_EV_VALIDATE) {
613 if (acl_zebra_is_dup(
614 args->dnode,
615 yang_dnode_get_enum(args->dnode, "../../type"))) {
616 snprintfrr(args->errmsg, args->errmsg_len,
617 "duplicated access list value: %s",
618 yang_dnode_get_string(args->dnode, NULL));
619 return NB_ERR_VALIDATION;
620 }
621 return NB_OK;
622 }
623
624 if (args->event != NB_EV_APPLY)
625 return NB_OK;
626
627 f = nb_running_get_entry(args->dnode, NULL, true);
628 f->cisco = 0;
629 fz = &f->u.zfilter;
630 yang_dnode_get_prefix(&fz->prefix, args->dnode, NULL);
631
632 acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_ADDED);
633
634 return NB_OK;
635 }
636
637 static int
638 lib_access_list_entry_ipv4_prefix_destroy(struct nb_cb_destroy_args *args)
639 {
640 struct filter_zebra *fz;
641 struct filter *f;
642
643 if (args->event != NB_EV_APPLY)
644 return NB_OK;
645
646 f = nb_running_get_entry(args->dnode, NULL, true);
647 fz = &f->u.zfilter;
648 memset(&fz->prefix, 0, sizeof(fz->prefix));
649
650 acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_DELETED);
651
652 return NB_OK;
653 }
654
655 /*
656 * XPath: /frr-filter:lib/access-list/entry/ipv4-exact-match
657 */
658 static int
659 lib_access_list_entry_ipv4_exact_match_modify(struct nb_cb_modify_args *args)
660 {
661 struct filter_zebra *fz;
662 struct filter *f;
663
664 /* Don't allow duplicated values. */
665 if (args->event == NB_EV_VALIDATE) {
666 if (acl_zebra_is_dup(
667 args->dnode,
668 yang_dnode_get_enum(args->dnode, "../../type"))) {
669 snprintfrr(args->errmsg, args->errmsg_len,
670 "duplicated access list value: %s",
671 yang_dnode_get_string(args->dnode, NULL));
672 return NB_ERR_VALIDATION;
673 }
674 return NB_OK;
675 }
676
677 if (args->event != NB_EV_APPLY)
678 return NB_OK;
679
680 f = nb_running_get_entry(args->dnode, NULL, true);
681 fz = &f->u.zfilter;
682 fz->exact = yang_dnode_get_bool(args->dnode, NULL);
683
684 acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_ADDED);
685
686 return NB_OK;
687 }
688
689 static int
690 lib_access_list_entry_ipv4_exact_match_destroy(struct nb_cb_destroy_args *args)
691 {
692 struct filter_zebra *fz;
693 struct filter *f;
694
695 if (args->event != NB_EV_APPLY)
696 return NB_OK;
697
698 f = nb_running_get_entry(args->dnode, NULL, true);
699 fz = &f->u.zfilter;
700 fz->exact = 0;
701
702 acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_DELETED);
703
704 return NB_OK;
705 }
706
707 /*
708 * XPath: /frr-filter:lib/access-list/entry/host
709 */
710 static int
711 lib_access_list_entry_host_modify(struct nb_cb_modify_args *args)
712 {
713 struct filter_cisco *fc;
714 struct filter *f;
715
716 /* Don't allow duplicated values. */
717 if (args->event == NB_EV_VALIDATE) {
718 if (acl_cisco_is_dup(args->dnode)) {
719 snprintfrr(args->errmsg, args->errmsg_len,
720 "duplicated access list value: %s",
721 yang_dnode_get_string(args->dnode, NULL));
722 return NB_ERR_VALIDATION;
723 }
724 return NB_OK;
725 }
726
727 if (args->event != NB_EV_APPLY)
728 return NB_OK;
729
730 f = nb_running_get_entry(args->dnode, NULL, true);
731 f->cisco = 1;
732 fc = &f->u.cfilter;
733 yang_dnode_get_ipv4(&fc->addr, args->dnode, NULL);
734 fc->addr_mask.s_addr = CISCO_BIN_HOST_WILDCARD_MASK;
735
736 acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_ADDED);
737
738 return NB_OK;
739 }
740
741 static int
742 lib_access_list_entry_host_destroy(struct nb_cb_destroy_args *args)
743 {
744 struct filter_cisco *fc;
745 struct filter *f;
746
747 if (args->event != NB_EV_APPLY)
748 return NB_OK;
749
750 f = nb_running_get_entry(args->dnode, NULL, true);
751 fc = &f->u.cfilter;
752 cisco_unset_addr_mask(&fc->addr, &fc->addr_mask);
753
754 acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_DELETED);
755
756 return NB_OK;
757 }
758
759 /*
760 * XPath: /frr-filter:lib/access-list/entry/network/address
761 */
762 static int
763 lib_access_list_entry_network_address_modify(struct nb_cb_modify_args *args)
764 {
765 struct filter_cisco *fc;
766 struct filter *f;
767
768 /* Don't allow duplicated values. */
769 if (args->event == NB_EV_VALIDATE) {
770 if (acl_cisco_is_dup(args->dnode)) {
771 snprintfrr(args->errmsg, args->errmsg_len,
772 "duplicated access list value: %s",
773 yang_dnode_get_string(args->dnode, NULL));
774 return NB_ERR_VALIDATION;
775 }
776 return NB_OK;
777 }
778
779 if (args->event != NB_EV_APPLY)
780 return NB_OK;
781
782 f = nb_running_get_entry(args->dnode, NULL, true);
783 f->cisco = 1;
784 fc = &f->u.cfilter;
785 yang_dnode_get_ipv4(&fc->addr, args->dnode, NULL);
786
787 acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_ADDED);
788
789 return NB_OK;
790 }
791
792 /*
793 * XPath: /frr-filter:lib/access-list/entry/network/mask
794 */
795 static int
796 lib_access_list_entry_network_mask_modify(struct nb_cb_modify_args *args)
797 {
798 struct filter_cisco *fc;
799 struct filter *f;
800
801 /* Don't allow duplicated values. */
802 if (args->event == NB_EV_VALIDATE) {
803 if (acl_cisco_is_dup(args->dnode)) {
804 snprintfrr(args->errmsg, args->errmsg_len,
805 "duplicated access list value: %s",
806 yang_dnode_get_string(args->dnode, NULL));
807 return NB_ERR_VALIDATION;
808 }
809 return NB_OK;
810 }
811
812 if (args->event != NB_EV_APPLY)
813 return NB_OK;
814
815 f = nb_running_get_entry(args->dnode, NULL, true);
816 f->cisco = 1;
817 fc = &f->u.cfilter;
818 yang_dnode_get_ipv4(&fc->addr_mask, args->dnode, NULL);
819
820 acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_ADDED);
821
822 return NB_OK;
823 }
824
825 /*
826 * XPath: /frr-filter:lib/access-list/entry/source-any
827 */
828 static int
829 lib_access_list_entry_source_any_create(struct nb_cb_create_args *args)
830 {
831 struct filter_cisco *fc;
832 struct filter *f;
833
834 /* Don't allow duplicated values. */
835 if (args->event == NB_EV_VALIDATE) {
836 if (acl_cisco_is_dup(args->dnode)) {
837 snprintfrr(args->errmsg, args->errmsg_len,
838 "duplicated access list value: %s",
839 yang_dnode_get_string(args->dnode, NULL));
840 return NB_ERR_VALIDATION;
841 }
842 return NB_OK;
843 }
844
845 if (args->event != NB_EV_APPLY)
846 return NB_OK;
847
848 f = nb_running_get_entry(args->dnode, NULL, true);
849 f->cisco = 1;
850 fc = &f->u.cfilter;
851 fc->addr.s_addr = INADDR_ANY;
852 fc->addr_mask.s_addr = CISCO_BIN_ANY_WILDCARD_MASK;
853
854 acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_ADDED);
855
856 return NB_OK;
857 }
858
859 static int
860 lib_access_list_entry_source_any_destroy(struct nb_cb_destroy_args *args)
861 {
862 struct filter_cisco *fc;
863 struct filter *f;
864
865 if (args->event != NB_EV_APPLY)
866 return NB_OK;
867
868 f = nb_running_get_entry(args->dnode, NULL, true);
869 fc = &f->u.cfilter;
870 cisco_unset_addr_mask(&fc->addr, &fc->addr_mask);
871
872 acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_DELETED);
873
874 return NB_OK;
875 }
876
877 /*
878 * XPath: /frr-filter:lib/access-list/entry/destination-host
879 */
880 static int lib_access_list_entry_destination_host_modify(
881 struct nb_cb_modify_args *args)
882 {
883 struct filter_cisco *fc;
884 struct filter *f;
885
886 /* Don't allow duplicated values. */
887 if (args->event == NB_EV_VALIDATE) {
888 if (acl_cisco_is_dup(args->dnode)) {
889 snprintfrr(args->errmsg, args->errmsg_len,
890 "duplicated access list value: %s",
891 yang_dnode_get_string(args->dnode, NULL));
892 return NB_ERR_VALIDATION;
893 }
894 return NB_OK;
895 }
896
897 if (args->event != NB_EV_APPLY)
898 return NB_OK;
899
900 f = nb_running_get_entry(args->dnode, NULL, true);
901 fc = &f->u.cfilter;
902 fc->extended = 1;
903 yang_dnode_get_ipv4(&fc->mask, args->dnode, NULL);
904 fc->mask_mask.s_addr = CISCO_BIN_HOST_WILDCARD_MASK;
905
906 acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_ADDED);
907
908 return NB_OK;
909 }
910
911 static int lib_access_list_entry_destination_host_destroy(
912 struct nb_cb_destroy_args *args)
913 {
914 struct filter_cisco *fc;
915 struct filter *f;
916
917 if (args->event != NB_EV_APPLY)
918 return NB_OK;
919
920 f = nb_running_get_entry(args->dnode, NULL, true);
921 fc = &f->u.cfilter;
922 fc->extended = 0;
923 cisco_unset_addr_mask(&fc->mask, &fc->mask_mask);
924
925 acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_DELETED);
926
927 return NB_OK;
928 }
929
930 /*
931 * XPath: /frr-filter:lib/access-list/entry/destination-network/address
932 */
933 static int lib_access_list_entry_destination_network_address_modify(
934 struct nb_cb_modify_args *args)
935 {
936 struct filter_cisco *fc;
937 struct filter *f;
938
939 /* Don't allow duplicated values. */
940 if (args->event == NB_EV_VALIDATE) {
941 if (acl_cisco_is_dup(args->dnode)) {
942 snprintfrr(args->errmsg, args->errmsg_len,
943 "duplicated access list value: %s",
944 yang_dnode_get_string(args->dnode, NULL));
945 return NB_ERR_VALIDATION;
946 }
947 return NB_OK;
948 }
949
950 if (args->event != NB_EV_APPLY)
951 return NB_OK;
952
953 f = nb_running_get_entry(args->dnode, NULL, true);
954 fc = &f->u.cfilter;
955 fc->extended = 1;
956 yang_dnode_get_ipv4(&fc->mask, args->dnode, NULL);
957
958 acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_ADDED);
959
960 return NB_OK;
961 }
962
963 /*
964 * XPath: /frr-filter:lib/access-list/entry/destination-network/mask
965 */
966 static int lib_access_list_entry_destination_network_mask_modify(
967 struct nb_cb_modify_args *args)
968 {
969 struct filter_cisco *fc;
970 struct filter *f;
971
972 /* Don't allow duplicated values. */
973 if (args->event == NB_EV_VALIDATE) {
974 if (acl_cisco_is_dup(args->dnode)) {
975 snprintfrr(args->errmsg, args->errmsg_len,
976 "duplicated access list value: %s",
977 yang_dnode_get_string(args->dnode, NULL));
978 return NB_ERR_VALIDATION;
979 }
980 return NB_OK;
981 }
982
983 if (args->event != NB_EV_APPLY)
984 return NB_OK;
985
986 f = nb_running_get_entry(args->dnode, NULL, true);
987 fc = &f->u.cfilter;
988 fc->extended = 1;
989 yang_dnode_get_ipv4(&fc->mask_mask, args->dnode, NULL);
990
991 acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_ADDED);
992
993 return NB_OK;
994 }
995
996 /*
997 * XPath: /frr-filter:lib/access-list/entry/destination-any
998 */
999 static int lib_access_list_entry_destination_any_create(
1000 struct nb_cb_create_args *args)
1001 {
1002 struct filter_cisco *fc;
1003 struct filter *f;
1004
1005 /* Don't allow duplicated values. */
1006 if (args->event == NB_EV_VALIDATE) {
1007 if (acl_cisco_is_dup(args->dnode)) {
1008 snprintfrr(args->errmsg, args->errmsg_len,
1009 "duplicated access list value: %s",
1010 yang_dnode_get_string(args->dnode, NULL));
1011 return NB_ERR_VALIDATION;
1012 }
1013 return NB_OK;
1014 }
1015
1016 if (args->event != NB_EV_APPLY)
1017 return NB_OK;
1018
1019 f = nb_running_get_entry(args->dnode, NULL, true);
1020 fc = &f->u.cfilter;
1021 fc->extended = 1;
1022 fc->mask.s_addr = INADDR_ANY;
1023 fc->mask_mask.s_addr = CISCO_BIN_ANY_WILDCARD_MASK;
1024
1025 acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_ADDED);
1026
1027 return NB_OK;
1028 }
1029
1030 static int lib_access_list_entry_destination_any_destroy(
1031 struct nb_cb_destroy_args *args)
1032 {
1033 struct filter_cisco *fc;
1034 struct filter *f;
1035
1036 if (args->event != NB_EV_APPLY)
1037 return NB_OK;
1038
1039 f = nb_running_get_entry(args->dnode, NULL, true);
1040 fc = &f->u.cfilter;
1041 fc->extended = 0;
1042 cisco_unset_addr_mask(&fc->mask, &fc->mask_mask);
1043
1044 acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_DELETED);
1045
1046 return NB_OK;
1047 }
1048
1049 /*
1050 * XPath: /frr-filter:lib/access-list/entry/any
1051 */
1052 static int lib_access_list_entry_any_create(struct nb_cb_create_args *args)
1053 {
1054 struct filter_zebra *fz;
1055 struct filter *f;
1056 int type;
1057
1058 /* Don't allow duplicated values. */
1059 if (args->event == NB_EV_VALIDATE) {
1060 if (acl_zebra_is_dup(
1061 args->dnode,
1062 yang_dnode_get_enum(args->dnode, "../../type"))) {
1063 snprintfrr(args->errmsg, args->errmsg_len,
1064 "duplicated access list value: %s",
1065 yang_dnode_get_string(args->dnode, NULL));
1066 return NB_ERR_VALIDATION;
1067 }
1068 return NB_OK;
1069 }
1070
1071 if (args->event != NB_EV_APPLY)
1072 return NB_OK;
1073
1074 f = nb_running_get_entry(args->dnode, NULL, true);
1075 f->cisco = 0;
1076 fz = &f->u.zfilter;
1077 memset(&fz->prefix, 0, sizeof(fz->prefix));
1078
1079 type = yang_dnode_get_enum(args->dnode, "../../type");
1080 switch (type) {
1081 case YALT_IPV4:
1082 fz->prefix.family = AF_INET;
1083 break;
1084 case YALT_IPV6:
1085 fz->prefix.family = AF_INET6;
1086 break;
1087 case YALT_MAC:
1088 fz->prefix.family = AF_ETHERNET;
1089 break;
1090 }
1091
1092 acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_ADDED);
1093
1094 return NB_OK;
1095 }
1096
1097 static int lib_access_list_entry_any_destroy(struct nb_cb_destroy_args *args)
1098 {
1099 struct filter_zebra *fz;
1100 struct filter *f;
1101
1102 if (args->event != NB_EV_APPLY)
1103 return NB_OK;
1104
1105 f = nb_running_get_entry(args->dnode, NULL, true);
1106 fz = &f->u.zfilter;
1107 fz->prefix.family = AF_UNSPEC;
1108
1109 acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_DELETED);
1110
1111 return NB_OK;
1112 }
1113
1114 /*
1115 * XPath: /frr-filter:lib/prefix-list
1116 */
1117 static int lib_prefix_list_create(struct nb_cb_create_args *args)
1118 {
1119 struct prefix_list *pl = NULL;
1120 const char *name;
1121 int type;
1122
1123 if (args->event != NB_EV_APPLY)
1124 return NB_OK;
1125
1126 type = yang_dnode_get_enum(args->dnode, "./type");
1127 name = yang_dnode_get_string(args->dnode, "./name");
1128 switch (type) {
1129 case 0: /* ipv4 */
1130 pl = prefix_list_get(AFI_IP, 0, name);
1131 break;
1132 case 1: /* ipv6 */
1133 pl = prefix_list_get(AFI_IP6, 0, name);
1134 break;
1135 }
1136
1137 nb_running_set_entry(args->dnode, pl);
1138
1139 return NB_OK;
1140 }
1141
1142 static int lib_prefix_list_destroy(struct nb_cb_destroy_args *args)
1143 {
1144 struct prefix_list *pl;
1145
1146 if (args->event != NB_EV_APPLY)
1147 return NB_OK;
1148
1149 pl = nb_running_unset_entry(args->dnode);
1150 prefix_list_delete(pl);
1151
1152 return NB_OK;
1153 }
1154
1155 /*
1156 * XPath: /frr-filter:lib/prefix-list/remark
1157 */
1158 static int lib_prefix_list_remark_modify(struct nb_cb_modify_args *args)
1159 {
1160 struct prefix_list *pl;
1161 const char *remark;
1162
1163 if (args->event != NB_EV_APPLY)
1164 return NB_OK;
1165
1166 pl = nb_running_get_entry(args->dnode, NULL, true);
1167 if (pl->desc)
1168 XFREE(MTYPE_TMP, pl->desc);
1169
1170 remark = yang_dnode_get_string(args->dnode, NULL);
1171 pl->desc = XSTRDUP(MTYPE_TMP, remark);
1172
1173 return NB_OK;
1174 }
1175
1176 static int lib_prefix_list_remark_destroy(struct nb_cb_destroy_args *args)
1177 {
1178 struct prefix_list *pl;
1179
1180 if (args->event != NB_EV_APPLY)
1181 return NB_OK;
1182
1183 pl = nb_running_get_entry(args->dnode, NULL, true);
1184 if (pl->desc)
1185 XFREE(MTYPE_TMP, pl->desc);
1186
1187 return NB_OK;
1188 }
1189
1190 /*
1191 * XPath: /frr-filter:lib/prefix-list/entry
1192 */
1193 static int lib_prefix_list_entry_create(struct nb_cb_create_args *args)
1194 {
1195 struct prefix_list_entry *ple;
1196 struct prefix_list *pl;
1197
1198 if (args->event != NB_EV_APPLY)
1199 return NB_OK;
1200
1201 pl = nb_running_get_entry(args->dnode, NULL, true);
1202 ple = prefix_list_entry_new();
1203 ple->pl = pl;
1204 ple->seq = yang_dnode_get_uint32(args->dnode, "./sequence");
1205 prefix_list_entry_set_empty(ple);
1206 nb_running_set_entry(args->dnode, ple);
1207
1208 return NB_OK;
1209 }
1210
1211 static int lib_prefix_list_entry_destroy(struct nb_cb_destroy_args *args)
1212 {
1213 struct prefix_list_entry *ple;
1214
1215 if (args->event != NB_EV_APPLY)
1216 return NB_OK;
1217
1218 ple = nb_running_unset_entry(args->dnode);
1219 if (ple->installed)
1220 prefix_list_entry_delete2(ple);
1221 else
1222 prefix_list_entry_free(ple);
1223
1224 return NB_OK;
1225 }
1226
1227 /*
1228 * XPath: /frr-filter:lib/prefix-list/entry/action
1229 */
1230 static int lib_prefix_list_entry_action_modify(struct nb_cb_modify_args *args)
1231 {
1232 struct prefix_list_entry *ple;
1233 int action_type;
1234
1235 if (args->event != NB_EV_APPLY)
1236 return NB_OK;
1237
1238 ple = nb_running_get_entry(args->dnode, NULL, true);
1239
1240 /* Start prefix entry update procedure. */
1241 prefix_list_entry_update_start(ple);
1242
1243 action_type = yang_dnode_get_enum(args->dnode, NULL);
1244 if (action_type == YPLA_PERMIT)
1245 ple->type = PREFIX_PERMIT;
1246 else
1247 ple->type = PREFIX_DENY;
1248
1249 /* Finish prefix entry update procedure. */
1250 prefix_list_entry_update_finish(ple);
1251
1252 return NB_OK;
1253 }
1254
1255 static int lib_prefix_list_entry_prefix_modify(struct nb_cb_modify_args *args)
1256 {
1257 struct prefix_list_entry *ple;
1258 struct prefix p;
1259
1260 if (args->event != NB_EV_APPLY)
1261 return NB_OK;
1262
1263 ple = nb_running_get_entry(args->dnode, NULL, true);
1264
1265 /* Start prefix entry update procedure. */
1266 prefix_list_entry_update_start(ple);
1267
1268 yang_dnode_get_prefix(&ple->prefix, args->dnode, NULL);
1269
1270 /* Apply mask and correct original address if necessary. */
1271 prefix_copy(&p, &ple->prefix);
1272 apply_mask(&p);
1273 if (!prefix_same(&ple->prefix, &p)) {
1274 zlog_info("%s: bad network %pFX correcting it to %pFX",
1275 __func__, &ple->prefix, &p);
1276 prefix_copy(&ple->prefix, &p);
1277 }
1278
1279
1280 /* Finish prefix entry update procedure. */
1281 prefix_list_entry_update_finish(ple);
1282
1283 return NB_OK;
1284 }
1285
1286 static int lib_prefix_list_entry_prefix_destroy(struct nb_cb_destroy_args *args)
1287 {
1288 struct prefix_list_entry *ple;
1289
1290 if (args->event != NB_EV_APPLY)
1291 return NB_OK;
1292
1293 ple = nb_running_get_entry(args->dnode, NULL, true);
1294
1295 /* Start prefix entry update procedure. */
1296 prefix_list_entry_update_start(ple);
1297
1298 memset(&ple->prefix, 0, sizeof(ple->prefix));
1299
1300 /* Finish prefix entry update procedure. */
1301 prefix_list_entry_update_finish(ple);
1302
1303 return NB_OK;
1304 }
1305
1306 /*
1307 * XPath: /frr-filter:lib/prefix-list/entry/ipv4-prefix
1308 */
1309 static int
1310 lib_prefix_list_entry_ipv4_prefix_modify(struct nb_cb_modify_args *args)
1311 {
1312 if (args->event == NB_EV_VALIDATE) {
1313 const struct lyd_node *plist_dnode =
1314 yang_dnode_get_parent(args->dnode, "prefix-list");
1315
1316 return prefix_list_nb_validate_v4_af_type(
1317 plist_dnode, args->errmsg, args->errmsg_len);
1318 }
1319
1320 return lib_prefix_list_entry_prefix_modify(args);
1321 }
1322
1323 static int
1324 lib_prefix_list_entry_ipv4_prefix_destroy(struct nb_cb_destroy_args *args)
1325 {
1326
1327 if (args->event != NB_EV_APPLY)
1328 return NB_OK;
1329
1330 return lib_prefix_list_entry_prefix_destroy(args);
1331 }
1332
1333 /*
1334 * XPath: /frr-filter:lib/prefix-list/entry/ipv6-prefix
1335 */
1336 static int
1337 lib_prefix_list_entry_ipv6_prefix_modify(struct nb_cb_modify_args *args)
1338 {
1339
1340 if (args->event == NB_EV_VALIDATE) {
1341 const struct lyd_node *plist_dnode =
1342 yang_dnode_get_parent(args->dnode, "prefix-list");
1343
1344 return prefix_list_nb_validate_v6_af_type(
1345 plist_dnode, args->errmsg, args->errmsg_len);
1346 }
1347
1348 return lib_prefix_list_entry_prefix_modify(args);
1349 }
1350
1351 static int
1352 lib_prefix_list_entry_ipv6_prefix_destroy(struct nb_cb_destroy_args *args)
1353 {
1354
1355 if (args->event != NB_EV_APPLY)
1356 return NB_OK;
1357
1358 return lib_prefix_list_entry_prefix_destroy(args);
1359 }
1360
1361 /*
1362 * XPath: /frr-filter:lib/prefix-list/entry/ipv4-prefix-length-greater-or-equal
1363 */
1364 static int lib_prefix_list_entry_ipv4_prefix_length_greater_or_equal_modify(
1365 struct nb_cb_modify_args *args)
1366 {
1367 if (args->event == NB_EV_VALIDATE
1368 && prefix_list_length_validate(args) != NB_OK)
1369 return NB_ERR_VALIDATION;
1370
1371 if (args->event == NB_EV_VALIDATE) {
1372 const struct lyd_node *plist_dnode =
1373 yang_dnode_get_parent(args->dnode, "prefix-list");
1374
1375 return prefix_list_nb_validate_v4_af_type(
1376 plist_dnode, args->errmsg, args->errmsg_len);
1377 }
1378
1379 return lib_prefix_list_entry_prefix_length_greater_or_equal_modify(
1380 args);
1381 }
1382
1383 static int lib_prefix_list_entry_ipv4_prefix_length_greater_or_equal_destroy(
1384 struct nb_cb_destroy_args *args)
1385 {
1386 if (args->event == NB_EV_VALIDATE) {
1387 const struct lyd_node *plist_dnode =
1388 yang_dnode_get_parent(args->dnode, "prefix-list");
1389
1390 return prefix_list_nb_validate_v4_af_type(
1391 plist_dnode, args->errmsg, args->errmsg_len);
1392 }
1393
1394 return lib_prefix_list_entry_prefix_length_greater_or_equal_destroy(
1395 args);
1396 }
1397
1398 /*
1399 * XPath: /frr-filter:lib/prefix-list/entry/ipv4-prefix-length-lesser-or-equal
1400 */
1401 static int lib_prefix_list_entry_ipv4_prefix_length_lesser_or_equal_modify(
1402 struct nb_cb_modify_args *args)
1403 {
1404 if (args->event == NB_EV_VALIDATE
1405 && prefix_list_length_validate(args) != NB_OK)
1406 return NB_ERR_VALIDATION;
1407
1408 if (args->event == NB_EV_VALIDATE) {
1409 const struct lyd_node *plist_dnode =
1410 yang_dnode_get_parent(args->dnode, "prefix-list");
1411
1412 return prefix_list_nb_validate_v4_af_type(
1413 plist_dnode, args->errmsg, args->errmsg_len);
1414 }
1415
1416 return lib_prefix_list_entry_prefix_length_lesser_or_equal_modify(
1417 args);
1418 }
1419
1420 static int lib_prefix_list_entry_ipv4_prefix_length_lesser_or_equal_destroy(
1421 struct nb_cb_destroy_args *args)
1422 {
1423 if (args->event == NB_EV_VALIDATE) {
1424 const struct lyd_node *plist_dnode =
1425 yang_dnode_get_parent(args->dnode, "prefix-list");
1426
1427 return prefix_list_nb_validate_v4_af_type(
1428 plist_dnode, args->errmsg, args->errmsg_len);
1429 }
1430
1431 return lib_prefix_list_entry_prefix_length_lesser_or_equal_destroy(
1432 args);
1433 }
1434
1435 /*
1436 * XPath: /frr-filter:lib/prefix-list/entry/ipv6-prefix-length-greater-or-equal
1437 */
1438 static int lib_prefix_list_entry_ipv6_prefix_length_greater_or_equal_modify(
1439 struct nb_cb_modify_args *args)
1440 {
1441 if (args->event == NB_EV_VALIDATE
1442 && prefix_list_length_validate(args) != NB_OK)
1443 return NB_ERR_VALIDATION;
1444
1445 if (args->event == NB_EV_VALIDATE) {
1446 const struct lyd_node *plist_dnode =
1447 yang_dnode_get_parent(args->dnode, "prefix-list");
1448
1449 return prefix_list_nb_validate_v6_af_type(
1450 plist_dnode, args->errmsg, args->errmsg_len);
1451 }
1452
1453 return lib_prefix_list_entry_prefix_length_greater_or_equal_modify(
1454 args);
1455 }
1456
1457 static int lib_prefix_list_entry_ipv6_prefix_length_greater_or_equal_destroy(
1458 struct nb_cb_destroy_args *args)
1459 {
1460 if (args->event == NB_EV_VALIDATE) {
1461 const struct lyd_node *plist_dnode =
1462 yang_dnode_get_parent(args->dnode, "prefix-list");
1463
1464 return prefix_list_nb_validate_v6_af_type(
1465 plist_dnode, args->errmsg, args->errmsg_len);
1466 }
1467
1468 return lib_prefix_list_entry_prefix_length_greater_or_equal_destroy(
1469 args);
1470 }
1471
1472 /*
1473 * XPath: /frr-filter:lib/prefix-list/entry/ipv6-prefix-length-lesser-or-equal
1474 */
1475 static int lib_prefix_list_entry_ipv6_prefix_length_lesser_or_equal_modify(
1476 struct nb_cb_modify_args *args)
1477 {
1478 if (args->event == NB_EV_VALIDATE
1479 && prefix_list_length_validate(args) != NB_OK)
1480 return NB_ERR_VALIDATION;
1481
1482 if (args->event == NB_EV_VALIDATE) {
1483 const struct lyd_node *plist_dnode =
1484 yang_dnode_get_parent(args->dnode, "prefix-list");
1485
1486 return prefix_list_nb_validate_v6_af_type(
1487 plist_dnode, args->errmsg, args->errmsg_len);
1488 }
1489
1490 return lib_prefix_list_entry_prefix_length_lesser_or_equal_modify(
1491 args);
1492 }
1493
1494 static int lib_prefix_list_entry_ipv6_prefix_length_lesser_or_equal_destroy(
1495 struct nb_cb_destroy_args *args)
1496 {
1497 if (args->event == NB_EV_VALIDATE) {
1498 const struct lyd_node *plist_dnode =
1499 yang_dnode_get_parent(args->dnode, "prefix-list");
1500
1501 return prefix_list_nb_validate_v6_af_type(
1502 plist_dnode, args->errmsg, args->errmsg_len);
1503 }
1504
1505 return lib_prefix_list_entry_prefix_length_lesser_or_equal_destroy(
1506 args);
1507 }
1508
1509 /*
1510 * XPath: /frr-filter:lib/prefix-list/entry/any
1511 */
1512 static int lib_prefix_list_entry_any_create(struct nb_cb_create_args *args)
1513 {
1514 struct prefix_list_entry *ple;
1515 int type;
1516
1517 /*
1518 * If we have gotten to this point, it's legal
1519 */
1520 if (args->event == NB_EV_VALIDATE)
1521 return NB_OK;
1522
1523 if (args->event != NB_EV_APPLY)
1524 return NB_OK;
1525
1526 ple = nb_running_get_entry(args->dnode, NULL, true);
1527
1528 /* Start prefix entry update procedure. */
1529 prefix_list_entry_update_start(ple);
1530
1531 ple->any = true;
1532
1533 /* Fill prefix struct from scratch. */
1534 memset(&ple->prefix, 0, sizeof(ple->prefix));
1535
1536 type = yang_dnode_get_enum(args->dnode, "../../type");
1537 switch (type) {
1538 case YPLT_IPV4:
1539 ple->prefix.family = AF_INET;
1540 ple->ge = 0;
1541 ple->le = IPV4_MAX_BITLEN;
1542 break;
1543 case YPLT_IPV6:
1544 ple->prefix.family = AF_INET6;
1545 ple->ge = 0;
1546 ple->le = IPV6_MAX_BITLEN;
1547 break;
1548 }
1549
1550 /* Finish prefix entry update procedure. */
1551 prefix_list_entry_update_finish(ple);
1552
1553 return NB_OK;
1554 }
1555
1556 static int lib_prefix_list_entry_any_destroy(struct nb_cb_destroy_args *args)
1557 {
1558 struct prefix_list_entry *ple;
1559
1560 if (args->event != NB_EV_APPLY)
1561 return NB_OK;
1562
1563 ple = nb_running_get_entry(args->dnode, NULL, true);
1564
1565 /* Start prefix entry update procedure. */
1566 prefix_list_entry_update_start(ple);
1567
1568 ple->any = false;
1569
1570 /* Finish prefix entry update procedure. */
1571 prefix_list_entry_update_finish(ple);
1572
1573 return NB_OK;
1574 }
1575
1576 /* clang-format off */
1577 const struct frr_yang_module_info frr_filter_info = {
1578 .name = "frr-filter",
1579 .nodes = {
1580 {
1581 .xpath = "/frr-filter:lib/access-list",
1582 .cbs = {
1583 .create = lib_access_list_create,
1584 .destroy = lib_access_list_destroy,
1585 }
1586 },
1587 {
1588 .xpath = "/frr-filter:lib/access-list/remark",
1589 .cbs = {
1590 .modify = lib_access_list_remark_modify,
1591 .destroy = lib_access_list_remark_destroy,
1592 .cli_show = access_list_remark_show,
1593 }
1594 },
1595 {
1596 .xpath = "/frr-filter:lib/access-list/entry",
1597 .cbs = {
1598 .create = lib_access_list_entry_create,
1599 .destroy = lib_access_list_entry_destroy,
1600 .cli_cmp = access_list_cmp,
1601 .cli_show = access_list_show,
1602 }
1603 },
1604 {
1605 .xpath = "/frr-filter:lib/access-list/entry/action",
1606 .cbs = {
1607 .modify = lib_access_list_entry_action_modify,
1608 }
1609 },
1610 {
1611 .xpath = "/frr-filter:lib/access-list/entry/ipv4-prefix",
1612 .cbs = {
1613 .modify = lib_access_list_entry_ipv4_prefix_modify,
1614 .destroy = lib_access_list_entry_ipv4_prefix_destroy,
1615 }
1616 },
1617 {
1618 .xpath = "/frr-filter:lib/access-list/entry/ipv4-exact-match",
1619 .cbs = {
1620 .modify = lib_access_list_entry_ipv4_exact_match_modify,
1621 .destroy = lib_access_list_entry_ipv4_exact_match_destroy,
1622 }
1623 },
1624 {
1625 .xpath = "/frr-filter:lib/access-list/entry/host",
1626 .cbs = {
1627 .modify = lib_access_list_entry_host_modify,
1628 .destroy = lib_access_list_entry_host_destroy,
1629 }
1630 },
1631 {
1632 .xpath = "/frr-filter:lib/access-list/entry/network/address",
1633 .cbs = {
1634 .modify = lib_access_list_entry_network_address_modify,
1635 }
1636 },
1637 {
1638 .xpath = "/frr-filter:lib/access-list/entry/network/mask",
1639 .cbs = {
1640 .modify = lib_access_list_entry_network_mask_modify,
1641 }
1642 },
1643 {
1644 .xpath = "/frr-filter:lib/access-list/entry/source-any",
1645 .cbs = {
1646 .create = lib_access_list_entry_source_any_create,
1647 .destroy = lib_access_list_entry_source_any_destroy,
1648 }
1649 },
1650 {
1651 .xpath = "/frr-filter:lib/access-list/entry/destination-host",
1652 .cbs = {
1653 .modify = lib_access_list_entry_destination_host_modify,
1654 .destroy = lib_access_list_entry_destination_host_destroy,
1655 }
1656 },
1657 {
1658 .xpath = "/frr-filter:lib/access-list/entry/destination-network/address",
1659 .cbs = {
1660 .modify = lib_access_list_entry_destination_network_address_modify,
1661 }
1662 },
1663 {
1664 .xpath = "/frr-filter:lib/access-list/entry/destination-network/mask",
1665 .cbs = {
1666 .modify = lib_access_list_entry_destination_network_mask_modify,
1667 }
1668 },
1669 {
1670 .xpath = "/frr-filter:lib/access-list/entry/destination-any",
1671 .cbs = {
1672 .create = lib_access_list_entry_destination_any_create,
1673 .destroy = lib_access_list_entry_destination_any_destroy,
1674 }
1675 },
1676 {
1677 .xpath = "/frr-filter:lib/access-list/entry/ipv6-prefix",
1678 .cbs = {
1679 .modify = lib_access_list_entry_ipv4_prefix_modify,
1680 .destroy = lib_access_list_entry_ipv4_prefix_destroy,
1681 }
1682 },
1683 {
1684 .xpath = "/frr-filter:lib/access-list/entry/ipv6-exact-match",
1685 .cbs = {
1686 .modify = lib_access_list_entry_ipv4_exact_match_modify,
1687 .destroy = lib_access_list_entry_ipv4_exact_match_destroy,
1688 }
1689 },
1690 {
1691 .xpath = "/frr-filter:lib/access-list/entry/mac",
1692 .cbs = {
1693 .modify = lib_access_list_entry_ipv4_prefix_modify,
1694 .destroy = lib_access_list_entry_ipv4_prefix_destroy,
1695 }
1696 },
1697 {
1698 .xpath = "/frr-filter:lib/access-list/entry/any",
1699 .cbs = {
1700 .create = lib_access_list_entry_any_create,
1701 .destroy = lib_access_list_entry_any_destroy,
1702 }
1703 },
1704 {
1705 .xpath = "/frr-filter:lib/prefix-list",
1706 .cbs = {
1707 .create = lib_prefix_list_create,
1708 .destroy = lib_prefix_list_destroy,
1709 }
1710 },
1711 {
1712 .xpath = "/frr-filter:lib/prefix-list/remark",
1713 .cbs = {
1714 .modify = lib_prefix_list_remark_modify,
1715 .destroy = lib_prefix_list_remark_destroy,
1716 .cli_show = prefix_list_remark_show,
1717 }
1718 },
1719 {
1720 .xpath = "/frr-filter:lib/prefix-list/entry",
1721 .cbs = {
1722 .create = lib_prefix_list_entry_create,
1723 .destroy = lib_prefix_list_entry_destroy,
1724 .cli_cmp = prefix_list_cmp,
1725 .cli_show = prefix_list_show,
1726 }
1727 },
1728 {
1729 .xpath = "/frr-filter:lib/prefix-list/entry/action",
1730 .cbs = {
1731 .modify = lib_prefix_list_entry_action_modify,
1732 }
1733 },
1734 {
1735 .xpath = "/frr-filter:lib/prefix-list/entry/ipv4-prefix",
1736 .cbs = {
1737 .modify = lib_prefix_list_entry_ipv4_prefix_modify,
1738 .destroy = lib_prefix_list_entry_ipv4_prefix_destroy,
1739 }
1740 },
1741 {
1742 .xpath = "/frr-filter:lib/prefix-list/entry/ipv4-prefix-length-greater-or-equal",
1743 .cbs = {
1744 .modify = lib_prefix_list_entry_ipv4_prefix_length_greater_or_equal_modify,
1745 .destroy = lib_prefix_list_entry_ipv4_prefix_length_greater_or_equal_destroy,
1746 }
1747 },
1748 {
1749 .xpath = "/frr-filter:lib/prefix-list/entry/ipv4-prefix-length-lesser-or-equal",
1750 .cbs = {
1751 .modify = lib_prefix_list_entry_ipv4_prefix_length_lesser_or_equal_modify,
1752 .destroy = lib_prefix_list_entry_ipv4_prefix_length_lesser_or_equal_destroy,
1753 }
1754 },
1755 {
1756 .xpath = "/frr-filter:lib/prefix-list/entry/ipv6-prefix",
1757 .cbs = {
1758 .modify = lib_prefix_list_entry_ipv6_prefix_modify,
1759 .destroy = lib_prefix_list_entry_ipv6_prefix_destroy,
1760 }
1761 },
1762 {
1763 .xpath = "/frr-filter:lib/prefix-list/entry/ipv6-prefix-length-greater-or-equal",
1764 .cbs = {
1765 .modify = lib_prefix_list_entry_ipv6_prefix_length_greater_or_equal_modify,
1766 .destroy = lib_prefix_list_entry_ipv6_prefix_length_greater_or_equal_destroy,
1767 }
1768 },
1769 {
1770 .xpath = "/frr-filter:lib/prefix-list/entry/ipv6-prefix-length-lesser-or-equal",
1771 .cbs = {
1772 .modify = lib_prefix_list_entry_ipv6_prefix_length_lesser_or_equal_modify,
1773 .destroy = lib_prefix_list_entry_ipv6_prefix_length_lesser_or_equal_destroy,
1774 }
1775 },
1776 {
1777 .xpath = "/frr-filter:lib/prefix-list/entry/any",
1778 .cbs = {
1779 .create = lib_prefix_list_entry_any_create,
1780 .destroy = lib_prefix_list_entry_any_destroy,
1781 }
1782 },
1783 {
1784 .xpath = NULL,
1785 },
1786 }
1787 };