]> git.proxmox.com Git - mirror_frr.git/blob - lib/filter_nb.c
Merge pull request #12798 from donaldsharp/rib_match_multicast
[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 static bool plist_is_dup_nb(const struct lyd_node *dnode)
460 {
461 const struct lyd_node *entry_dnode =
462 yang_dnode_get_parent(dnode, "entry");
463 struct plist_dup_args pda = {};
464
465 /* Initialize. */
466 pda.pda_type = yang_dnode_get_string(entry_dnode, "../type");
467 pda.pda_name = yang_dnode_get_string(entry_dnode, "../name");
468 pda.pda_action = yang_dnode_get_string(entry_dnode, "action");
469 pda.pda_entry_dnode = entry_dnode;
470
471 plist_dnode_to_prefix(entry_dnode, &pda.any, &pda.prefix, &pda.ge,
472 &pda.le);
473
474 return plist_is_dup(entry_dnode, &pda);
475 }
476
477 /*
478 * XPath: /frr-filter:lib/access-list
479 */
480 static int lib_access_list_create(struct nb_cb_create_args *args)
481 {
482 struct access_list *acl = NULL;
483 const char *acl_name;
484 int type;
485
486 if (args->event != NB_EV_APPLY)
487 return NB_OK;
488
489 type = yang_dnode_get_enum(args->dnode, "./type");
490 acl_name = yang_dnode_get_string(args->dnode, "./name");
491
492 switch (type) {
493 case YALT_IPV4:
494 acl = access_list_get(AFI_IP, acl_name);
495 break;
496 case YALT_IPV6:
497 acl = access_list_get(AFI_IP6, acl_name);
498 break;
499 case YALT_MAC:
500 acl = access_list_get(AFI_L2VPN, acl_name);
501 break;
502 }
503
504 nb_running_set_entry(args->dnode, acl);
505
506 return NB_OK;
507 }
508
509 static int lib_access_list_destroy(struct nb_cb_destroy_args *args)
510 {
511 struct access_list *acl;
512
513 if (args->event != NB_EV_APPLY)
514 return NB_OK;
515
516 acl = nb_running_unset_entry(args->dnode);
517 access_list_delete(acl);
518
519 return NB_OK;
520 }
521
522 /*
523 * XPath: /frr-filter:lib/access-list/remark
524 */
525 static int lib_access_list_remark_modify(struct nb_cb_modify_args *args)
526 {
527 struct access_list *acl;
528 const char *remark;
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 remark = yang_dnode_get_string(args->dnode, NULL);
538 acl->remark = XSTRDUP(MTYPE_TMP, remark);
539
540 return NB_OK;
541 }
542
543 static int
544 lib_access_list_remark_destroy(struct nb_cb_destroy_args *args)
545 {
546 struct access_list *acl;
547
548 if (args->event != NB_EV_APPLY)
549 return NB_OK;
550
551 acl = nb_running_get_entry(args->dnode, NULL, true);
552 if (acl->remark)
553 XFREE(MTYPE_TMP, acl->remark);
554
555 return NB_OK;
556 }
557
558
559 /*
560 * XPath: /frr-filter:lib/access-list/entry
561 */
562 static int lib_access_list_entry_create(struct nb_cb_create_args *args)
563 {
564 struct access_list *acl;
565 struct filter *f;
566
567 if (args->event != NB_EV_APPLY)
568 return NB_OK;
569
570 f = filter_new();
571 f->seq = yang_dnode_get_uint32(args->dnode, "./sequence");
572
573 acl = nb_running_get_entry(args->dnode, NULL, true);
574 f->acl = acl;
575 access_list_filter_add(acl, f);
576 nb_running_set_entry(args->dnode, f);
577
578 return NB_OK;
579 }
580
581 static int lib_access_list_entry_destroy(struct nb_cb_destroy_args *args)
582 {
583 struct access_list *acl;
584 struct filter *f;
585
586 if (args->event != NB_EV_APPLY)
587 return NB_OK;
588
589 f = nb_running_unset_entry(args->dnode);
590 acl = f->acl;
591 access_list_filter_delete(acl, f);
592
593 return NB_OK;
594 }
595
596 /*
597 * XPath: /frr-filter:lib/access-list/entry/action
598 */
599 static int
600 lib_access_list_entry_action_modify(struct nb_cb_modify_args *args)
601 {
602 const char *filter_type;
603 struct filter *f;
604
605 if (args->event != NB_EV_APPLY)
606 return NB_OK;
607
608 f = nb_running_get_entry(args->dnode, NULL, true);
609 filter_type = yang_dnode_get_string(args->dnode, NULL);
610 if (strcmp(filter_type, "permit") == 0)
611 f->type = FILTER_PERMIT;
612 else
613 f->type = FILTER_DENY;
614
615 acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_ADDED);
616
617 return NB_OK;
618 }
619
620 /*
621 * XPath: /frr-filter:lib/access-list/entry/ipv4-prefix
622 */
623 static int
624 lib_access_list_entry_ipv4_prefix_modify(struct nb_cb_modify_args *args)
625 {
626 struct filter_zebra *fz;
627 struct filter *f;
628
629 /* Don't allow duplicated values. */
630 if (args->event == NB_EV_VALIDATE) {
631 if (acl_zebra_is_dup(
632 args->dnode,
633 yang_dnode_get_enum(args->dnode, "../../type"))) {
634 snprintfrr(args->errmsg, args->errmsg_len,
635 "duplicated access list value: %s",
636 yang_dnode_get_string(args->dnode, NULL));
637 return NB_ERR_VALIDATION;
638 }
639 return NB_OK;
640 }
641
642 if (args->event != NB_EV_APPLY)
643 return NB_OK;
644
645 f = nb_running_get_entry(args->dnode, NULL, true);
646 f->cisco = 0;
647 fz = &f->u.zfilter;
648 yang_dnode_get_prefix(&fz->prefix, args->dnode, NULL);
649
650 acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_ADDED);
651
652 return NB_OK;
653 }
654
655 static int
656 lib_access_list_entry_ipv4_prefix_destroy(struct nb_cb_destroy_args *args)
657 {
658 struct filter_zebra *fz;
659 struct filter *f;
660
661 if (args->event != NB_EV_APPLY)
662 return NB_OK;
663
664 f = nb_running_get_entry(args->dnode, NULL, true);
665 fz = &f->u.zfilter;
666 memset(&fz->prefix, 0, sizeof(fz->prefix));
667
668 acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_DELETED);
669
670 return NB_OK;
671 }
672
673 /*
674 * XPath: /frr-filter:lib/access-list/entry/ipv4-exact-match
675 */
676 static int
677 lib_access_list_entry_ipv4_exact_match_modify(struct nb_cb_modify_args *args)
678 {
679 struct filter_zebra *fz;
680 struct filter *f;
681
682 /* Don't allow duplicated values. */
683 if (args->event == NB_EV_VALIDATE) {
684 if (acl_zebra_is_dup(
685 args->dnode,
686 yang_dnode_get_enum(args->dnode, "../../type"))) {
687 snprintfrr(args->errmsg, args->errmsg_len,
688 "duplicated access list value: %s",
689 yang_dnode_get_string(args->dnode, NULL));
690 return NB_ERR_VALIDATION;
691 }
692 return NB_OK;
693 }
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 = yang_dnode_get_bool(args->dnode, NULL);
701
702 acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_ADDED);
703
704 return NB_OK;
705 }
706
707 static int
708 lib_access_list_entry_ipv4_exact_match_destroy(struct nb_cb_destroy_args *args)
709 {
710 struct filter_zebra *fz;
711 struct filter *f;
712
713 if (args->event != NB_EV_APPLY)
714 return NB_OK;
715
716 f = nb_running_get_entry(args->dnode, NULL, true);
717 fz = &f->u.zfilter;
718 fz->exact = 0;
719
720 acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_DELETED);
721
722 return NB_OK;
723 }
724
725 /*
726 * XPath: /frr-filter:lib/access-list/entry/host
727 */
728 static int
729 lib_access_list_entry_host_modify(struct nb_cb_modify_args *args)
730 {
731 struct filter_cisco *fc;
732 struct filter *f;
733
734 /* Don't allow duplicated values. */
735 if (args->event == NB_EV_VALIDATE) {
736 if (acl_cisco_is_dup(args->dnode)) {
737 snprintfrr(args->errmsg, args->errmsg_len,
738 "duplicated access list value: %s",
739 yang_dnode_get_string(args->dnode, NULL));
740 return NB_ERR_VALIDATION;
741 }
742 return NB_OK;
743 }
744
745 if (args->event != NB_EV_APPLY)
746 return NB_OK;
747
748 f = nb_running_get_entry(args->dnode, NULL, true);
749 f->cisco = 1;
750 fc = &f->u.cfilter;
751 yang_dnode_get_ipv4(&fc->addr, args->dnode, NULL);
752 fc->addr_mask.s_addr = CISCO_BIN_HOST_WILDCARD_MASK;
753
754 acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_ADDED);
755
756 return NB_OK;
757 }
758
759 static int
760 lib_access_list_entry_host_destroy(struct nb_cb_destroy_args *args)
761 {
762 struct filter_cisco *fc;
763 struct filter *f;
764
765 if (args->event != NB_EV_APPLY)
766 return NB_OK;
767
768 f = nb_running_get_entry(args->dnode, NULL, true);
769 fc = &f->u.cfilter;
770 cisco_unset_addr_mask(&fc->addr, &fc->addr_mask);
771
772 acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_DELETED);
773
774 return NB_OK;
775 }
776
777 /*
778 * XPath: /frr-filter:lib/access-list/entry/network/address
779 */
780 static int
781 lib_access_list_entry_network_address_modify(struct nb_cb_modify_args *args)
782 {
783 struct filter_cisco *fc;
784 struct filter *f;
785
786 /* Don't allow duplicated values. */
787 if (args->event == NB_EV_VALIDATE) {
788 if (acl_cisco_is_dup(args->dnode)) {
789 snprintfrr(args->errmsg, args->errmsg_len,
790 "duplicated access list value: %s",
791 yang_dnode_get_string(args->dnode, NULL));
792 return NB_ERR_VALIDATION;
793 }
794 return NB_OK;
795 }
796
797 if (args->event != NB_EV_APPLY)
798 return NB_OK;
799
800 f = nb_running_get_entry(args->dnode, NULL, true);
801 f->cisco = 1;
802 fc = &f->u.cfilter;
803 yang_dnode_get_ipv4(&fc->addr, args->dnode, NULL);
804
805 acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_ADDED);
806
807 return NB_OK;
808 }
809
810 /*
811 * XPath: /frr-filter:lib/access-list/entry/network/mask
812 */
813 static int
814 lib_access_list_entry_network_mask_modify(struct nb_cb_modify_args *args)
815 {
816 struct filter_cisco *fc;
817 struct filter *f;
818
819 /* Don't allow duplicated values. */
820 if (args->event == NB_EV_VALIDATE) {
821 if (acl_cisco_is_dup(args->dnode)) {
822 snprintfrr(args->errmsg, args->errmsg_len,
823 "duplicated access list value: %s",
824 yang_dnode_get_string(args->dnode, NULL));
825 return NB_ERR_VALIDATION;
826 }
827 return NB_OK;
828 }
829
830 if (args->event != NB_EV_APPLY)
831 return NB_OK;
832
833 f = nb_running_get_entry(args->dnode, NULL, true);
834 f->cisco = 1;
835 fc = &f->u.cfilter;
836 yang_dnode_get_ipv4(&fc->addr_mask, args->dnode, NULL);
837
838 acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_ADDED);
839
840 return NB_OK;
841 }
842
843 /*
844 * XPath: /frr-filter:lib/access-list/entry/source-any
845 */
846 static int
847 lib_access_list_entry_source_any_create(struct nb_cb_create_args *args)
848 {
849 struct filter_cisco *fc;
850 struct filter *f;
851
852 /* Don't allow duplicated values. */
853 if (args->event == NB_EV_VALIDATE) {
854 if (acl_cisco_is_dup(args->dnode)) {
855 snprintfrr(args->errmsg, args->errmsg_len,
856 "duplicated access list value: %s",
857 yang_dnode_get_string(args->dnode, NULL));
858 return NB_ERR_VALIDATION;
859 }
860 return NB_OK;
861 }
862
863 if (args->event != NB_EV_APPLY)
864 return NB_OK;
865
866 f = nb_running_get_entry(args->dnode, NULL, true);
867 f->cisco = 1;
868 fc = &f->u.cfilter;
869 fc->addr.s_addr = INADDR_ANY;
870 fc->addr_mask.s_addr = CISCO_BIN_ANY_WILDCARD_MASK;
871
872 acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_ADDED);
873
874 return NB_OK;
875 }
876
877 static int
878 lib_access_list_entry_source_any_destroy(struct nb_cb_destroy_args *args)
879 {
880 struct filter_cisco *fc;
881 struct filter *f;
882
883 if (args->event != NB_EV_APPLY)
884 return NB_OK;
885
886 f = nb_running_get_entry(args->dnode, NULL, true);
887 fc = &f->u.cfilter;
888 cisco_unset_addr_mask(&fc->addr, &fc->addr_mask);
889
890 acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_DELETED);
891
892 return NB_OK;
893 }
894
895 /*
896 * XPath: /frr-filter:lib/access-list/entry/destination-host
897 */
898 static int lib_access_list_entry_destination_host_modify(
899 struct nb_cb_modify_args *args)
900 {
901 struct filter_cisco *fc;
902 struct filter *f;
903
904 /* Don't allow duplicated values. */
905 if (args->event == NB_EV_VALIDATE) {
906 if (acl_cisco_is_dup(args->dnode)) {
907 snprintfrr(args->errmsg, args->errmsg_len,
908 "duplicated access list value: %s",
909 yang_dnode_get_string(args->dnode, NULL));
910 return NB_ERR_VALIDATION;
911 }
912 return NB_OK;
913 }
914
915 if (args->event != NB_EV_APPLY)
916 return NB_OK;
917
918 f = nb_running_get_entry(args->dnode, NULL, true);
919 fc = &f->u.cfilter;
920 fc->extended = 1;
921 yang_dnode_get_ipv4(&fc->mask, args->dnode, NULL);
922 fc->mask_mask.s_addr = CISCO_BIN_HOST_WILDCARD_MASK;
923
924 acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_ADDED);
925
926 return NB_OK;
927 }
928
929 static int lib_access_list_entry_destination_host_destroy(
930 struct nb_cb_destroy_args *args)
931 {
932 struct filter_cisco *fc;
933 struct filter *f;
934
935 if (args->event != NB_EV_APPLY)
936 return NB_OK;
937
938 f = nb_running_get_entry(args->dnode, NULL, true);
939 fc = &f->u.cfilter;
940 fc->extended = 0;
941 cisco_unset_addr_mask(&fc->mask, &fc->mask_mask);
942
943 acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_DELETED);
944
945 return NB_OK;
946 }
947
948 /*
949 * XPath: /frr-filter:lib/access-list/entry/destination-network/address
950 */
951 static int lib_access_list_entry_destination_network_address_modify(
952 struct nb_cb_modify_args *args)
953 {
954 struct filter_cisco *fc;
955 struct filter *f;
956
957 /* Don't allow duplicated values. */
958 if (args->event == NB_EV_VALIDATE) {
959 if (acl_cisco_is_dup(args->dnode)) {
960 snprintfrr(args->errmsg, args->errmsg_len,
961 "duplicated access list value: %s",
962 yang_dnode_get_string(args->dnode, NULL));
963 return NB_ERR_VALIDATION;
964 }
965 return NB_OK;
966 }
967
968 if (args->event != NB_EV_APPLY)
969 return NB_OK;
970
971 f = nb_running_get_entry(args->dnode, NULL, true);
972 fc = &f->u.cfilter;
973 fc->extended = 1;
974 yang_dnode_get_ipv4(&fc->mask, args->dnode, NULL);
975
976 acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_ADDED);
977
978 return NB_OK;
979 }
980
981 /*
982 * XPath: /frr-filter:lib/access-list/entry/destination-network/mask
983 */
984 static int lib_access_list_entry_destination_network_mask_modify(
985 struct nb_cb_modify_args *args)
986 {
987 struct filter_cisco *fc;
988 struct filter *f;
989
990 /* Don't allow duplicated values. */
991 if (args->event == NB_EV_VALIDATE) {
992 if (acl_cisco_is_dup(args->dnode)) {
993 snprintfrr(args->errmsg, args->errmsg_len,
994 "duplicated access list value: %s",
995 yang_dnode_get_string(args->dnode, NULL));
996 return NB_ERR_VALIDATION;
997 }
998 return NB_OK;
999 }
1000
1001 if (args->event != NB_EV_APPLY)
1002 return NB_OK;
1003
1004 f = nb_running_get_entry(args->dnode, NULL, true);
1005 fc = &f->u.cfilter;
1006 fc->extended = 1;
1007 yang_dnode_get_ipv4(&fc->mask_mask, args->dnode, NULL);
1008
1009 acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_ADDED);
1010
1011 return NB_OK;
1012 }
1013
1014 /*
1015 * XPath: /frr-filter:lib/access-list/entry/destination-any
1016 */
1017 static int lib_access_list_entry_destination_any_create(
1018 struct nb_cb_create_args *args)
1019 {
1020 struct filter_cisco *fc;
1021 struct filter *f;
1022
1023 /* Don't allow duplicated values. */
1024 if (args->event == NB_EV_VALIDATE) {
1025 if (acl_cisco_is_dup(args->dnode)) {
1026 snprintfrr(args->errmsg, args->errmsg_len,
1027 "duplicated access list value: %s",
1028 yang_dnode_get_string(args->dnode, NULL));
1029 return NB_ERR_VALIDATION;
1030 }
1031 return NB_OK;
1032 }
1033
1034 if (args->event != NB_EV_APPLY)
1035 return NB_OK;
1036
1037 f = nb_running_get_entry(args->dnode, NULL, true);
1038 fc = &f->u.cfilter;
1039 fc->extended = 1;
1040 fc->mask.s_addr = INADDR_ANY;
1041 fc->mask_mask.s_addr = CISCO_BIN_ANY_WILDCARD_MASK;
1042
1043 acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_ADDED);
1044
1045 return NB_OK;
1046 }
1047
1048 static int lib_access_list_entry_destination_any_destroy(
1049 struct nb_cb_destroy_args *args)
1050 {
1051 struct filter_cisco *fc;
1052 struct filter *f;
1053
1054 if (args->event != NB_EV_APPLY)
1055 return NB_OK;
1056
1057 f = nb_running_get_entry(args->dnode, NULL, true);
1058 fc = &f->u.cfilter;
1059 fc->extended = 0;
1060 cisco_unset_addr_mask(&fc->mask, &fc->mask_mask);
1061
1062 acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_DELETED);
1063
1064 return NB_OK;
1065 }
1066
1067 /*
1068 * XPath: /frr-filter:lib/access-list/entry/any
1069 */
1070 static int lib_access_list_entry_any_create(struct nb_cb_create_args *args)
1071 {
1072 struct filter_zebra *fz;
1073 struct filter *f;
1074 int type;
1075
1076 /* Don't allow duplicated values. */
1077 if (args->event == NB_EV_VALIDATE) {
1078 if (acl_zebra_is_dup(
1079 args->dnode,
1080 yang_dnode_get_enum(args->dnode, "../../type"))) {
1081 snprintfrr(args->errmsg, args->errmsg_len,
1082 "duplicated access list value: %s",
1083 yang_dnode_get_string(args->dnode, NULL));
1084 return NB_ERR_VALIDATION;
1085 }
1086 return NB_OK;
1087 }
1088
1089 if (args->event != NB_EV_APPLY)
1090 return NB_OK;
1091
1092 f = nb_running_get_entry(args->dnode, NULL, true);
1093 f->cisco = 0;
1094 fz = &f->u.zfilter;
1095 memset(&fz->prefix, 0, sizeof(fz->prefix));
1096
1097 type = yang_dnode_get_enum(args->dnode, "../../type");
1098 switch (type) {
1099 case YALT_IPV4:
1100 fz->prefix.family = AF_INET;
1101 break;
1102 case YALT_IPV6:
1103 fz->prefix.family = AF_INET6;
1104 break;
1105 case YALT_MAC:
1106 fz->prefix.family = AF_ETHERNET;
1107 break;
1108 }
1109
1110 acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_ADDED);
1111
1112 return NB_OK;
1113 }
1114
1115 static int lib_access_list_entry_any_destroy(struct nb_cb_destroy_args *args)
1116 {
1117 struct filter_zebra *fz;
1118 struct filter *f;
1119
1120 if (args->event != NB_EV_APPLY)
1121 return NB_OK;
1122
1123 f = nb_running_get_entry(args->dnode, NULL, true);
1124 fz = &f->u.zfilter;
1125 fz->prefix.family = AF_UNSPEC;
1126
1127 acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_DELETED);
1128
1129 return NB_OK;
1130 }
1131
1132 /*
1133 * XPath: /frr-filter:lib/prefix-list
1134 */
1135 static int lib_prefix_list_create(struct nb_cb_create_args *args)
1136 {
1137 struct prefix_list *pl = NULL;
1138 const char *name;
1139 int type;
1140
1141 if (args->event != NB_EV_APPLY)
1142 return NB_OK;
1143
1144 type = yang_dnode_get_enum(args->dnode, "./type");
1145 name = yang_dnode_get_string(args->dnode, "./name");
1146 switch (type) {
1147 case 0: /* ipv4 */
1148 pl = prefix_list_get(AFI_IP, 0, name);
1149 break;
1150 case 1: /* ipv6 */
1151 pl = prefix_list_get(AFI_IP6, 0, name);
1152 break;
1153 }
1154
1155 nb_running_set_entry(args->dnode, pl);
1156
1157 return NB_OK;
1158 }
1159
1160 static int lib_prefix_list_destroy(struct nb_cb_destroy_args *args)
1161 {
1162 struct prefix_list *pl;
1163
1164 if (args->event != NB_EV_APPLY)
1165 return NB_OK;
1166
1167 pl = nb_running_unset_entry(args->dnode);
1168 prefix_list_delete(pl);
1169
1170 return NB_OK;
1171 }
1172
1173 /*
1174 * XPath: /frr-filter:lib/prefix-list/remark
1175 */
1176 static int lib_prefix_list_remark_modify(struct nb_cb_modify_args *args)
1177 {
1178 struct prefix_list *pl;
1179 const char *remark;
1180
1181 if (args->event != NB_EV_APPLY)
1182 return NB_OK;
1183
1184 pl = nb_running_get_entry(args->dnode, NULL, true);
1185 if (pl->desc)
1186 XFREE(MTYPE_TMP, pl->desc);
1187
1188 remark = yang_dnode_get_string(args->dnode, NULL);
1189 pl->desc = XSTRDUP(MTYPE_TMP, remark);
1190
1191 return NB_OK;
1192 }
1193
1194 static int lib_prefix_list_remark_destroy(struct nb_cb_destroy_args *args)
1195 {
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 if (pl->desc)
1203 XFREE(MTYPE_TMP, pl->desc);
1204
1205 return NB_OK;
1206 }
1207
1208 /*
1209 * XPath: /frr-filter:lib/prefix-list/entry
1210 */
1211 static int lib_prefix_list_entry_create(struct nb_cb_create_args *args)
1212 {
1213 struct prefix_list_entry *ple;
1214 struct prefix_list *pl;
1215
1216 if (args->event != NB_EV_APPLY)
1217 return NB_OK;
1218
1219 pl = nb_running_get_entry(args->dnode, NULL, true);
1220 ple = prefix_list_entry_new();
1221 ple->pl = pl;
1222 ple->seq = yang_dnode_get_uint32(args->dnode, "./sequence");
1223 prefix_list_entry_set_empty(ple);
1224 nb_running_set_entry(args->dnode, ple);
1225
1226 return NB_OK;
1227 }
1228
1229 static int lib_prefix_list_entry_destroy(struct nb_cb_destroy_args *args)
1230 {
1231 struct prefix_list_entry *ple;
1232
1233 if (args->event != NB_EV_APPLY)
1234 return NB_OK;
1235
1236 ple = nb_running_unset_entry(args->dnode);
1237 if (ple->installed)
1238 prefix_list_entry_delete2(ple);
1239 else
1240 prefix_list_entry_free(ple);
1241
1242 return NB_OK;
1243 }
1244
1245 /*
1246 * XPath: /frr-filter:lib/prefix-list/entry/action
1247 */
1248 static int lib_prefix_list_entry_action_modify(struct nb_cb_modify_args *args)
1249 {
1250 struct prefix_list_entry *ple;
1251 int action_type;
1252
1253 if (args->event != NB_EV_APPLY)
1254 return NB_OK;
1255
1256 ple = nb_running_get_entry(args->dnode, NULL, true);
1257
1258 /* Start prefix entry update procedure. */
1259 prefix_list_entry_update_start(ple);
1260
1261 action_type = yang_dnode_get_enum(args->dnode, NULL);
1262 if (action_type == YPLA_PERMIT)
1263 ple->type = PREFIX_PERMIT;
1264 else
1265 ple->type = PREFIX_DENY;
1266
1267 /* Finish prefix entry update procedure. */
1268 prefix_list_entry_update_finish(ple);
1269
1270 return NB_OK;
1271 }
1272
1273 static int lib_prefix_list_entry_prefix_modify(struct nb_cb_modify_args *args)
1274 {
1275 struct prefix_list_entry *ple;
1276 struct prefix p;
1277
1278 if (args->event != NB_EV_APPLY)
1279 return NB_OK;
1280
1281 ple = nb_running_get_entry(args->dnode, NULL, true);
1282
1283 /* Start prefix entry update procedure. */
1284 prefix_list_entry_update_start(ple);
1285
1286 yang_dnode_get_prefix(&ple->prefix, args->dnode, NULL);
1287
1288 /* Apply mask and correct original address if necessary. */
1289 prefix_copy(&p, &ple->prefix);
1290 apply_mask(&p);
1291 if (!prefix_same(&ple->prefix, &p)) {
1292 zlog_info("%s: bad network %pFX correcting it to %pFX",
1293 __func__, &ple->prefix, &p);
1294 prefix_copy(&ple->prefix, &p);
1295 }
1296
1297
1298 /* Finish prefix entry update procedure. */
1299 prefix_list_entry_update_finish(ple);
1300
1301 return NB_OK;
1302 }
1303
1304 static int lib_prefix_list_entry_prefix_destroy(struct nb_cb_destroy_args *args)
1305 {
1306 struct prefix_list_entry *ple;
1307
1308 if (args->event != NB_EV_APPLY)
1309 return NB_OK;
1310
1311 ple = nb_running_get_entry(args->dnode, NULL, true);
1312
1313 /* Start prefix entry update procedure. */
1314 prefix_list_entry_update_start(ple);
1315
1316 memset(&ple->prefix, 0, sizeof(ple->prefix));
1317
1318 /* Finish prefix entry update procedure. */
1319 prefix_list_entry_update_finish(ple);
1320
1321 return NB_OK;
1322 }
1323
1324 /*
1325 * XPath: /frr-filter:lib/prefix-list/entry/ipv4-prefix
1326 */
1327 static int
1328 lib_prefix_list_entry_ipv4_prefix_modify(struct nb_cb_modify_args *args)
1329 {
1330 if (args->event == NB_EV_VALIDATE) {
1331 const struct lyd_node *plist_dnode =
1332 yang_dnode_get_parent(args->dnode, "prefix-list");
1333
1334 if (plist_is_dup_nb(args->dnode)) {
1335 snprintf(args->errmsg, args->errmsg_len,
1336 "duplicated prefix list value: %s",
1337 yang_dnode_get_string(args->dnode, NULL));
1338 return NB_ERR_VALIDATION;
1339 }
1340
1341 return prefix_list_nb_validate_v4_af_type(
1342 plist_dnode, args->errmsg, args->errmsg_len);
1343 }
1344
1345 return lib_prefix_list_entry_prefix_modify(args);
1346 }
1347
1348 static int
1349 lib_prefix_list_entry_ipv4_prefix_destroy(struct nb_cb_destroy_args *args)
1350 {
1351
1352 if (args->event != NB_EV_APPLY)
1353 return NB_OK;
1354
1355 return lib_prefix_list_entry_prefix_destroy(args);
1356 }
1357
1358 /*
1359 * XPath: /frr-filter:lib/prefix-list/entry/ipv6-prefix
1360 */
1361 static int
1362 lib_prefix_list_entry_ipv6_prefix_modify(struct nb_cb_modify_args *args)
1363 {
1364
1365 if (args->event == NB_EV_VALIDATE) {
1366 const struct lyd_node *plist_dnode =
1367 yang_dnode_get_parent(args->dnode, "prefix-list");
1368
1369 if (plist_is_dup_nb(args->dnode)) {
1370 snprintf(args->errmsg, args->errmsg_len,
1371 "duplicated prefix list value: %s",
1372 yang_dnode_get_string(args->dnode, NULL));
1373 return NB_ERR_VALIDATION;
1374 }
1375
1376 return prefix_list_nb_validate_v6_af_type(
1377 plist_dnode, args->errmsg, args->errmsg_len);
1378 }
1379
1380 return lib_prefix_list_entry_prefix_modify(args);
1381 }
1382
1383 static int
1384 lib_prefix_list_entry_ipv6_prefix_destroy(struct nb_cb_destroy_args *args)
1385 {
1386
1387 if (args->event != NB_EV_APPLY)
1388 return NB_OK;
1389
1390 return lib_prefix_list_entry_prefix_destroy(args);
1391 }
1392
1393 /*
1394 * XPath: /frr-filter:lib/prefix-list/entry/ipv4-prefix-length-greater-or-equal
1395 */
1396 static int lib_prefix_list_entry_ipv4_prefix_length_greater_or_equal_modify(
1397 struct nb_cb_modify_args *args)
1398 {
1399 if (args->event == NB_EV_VALIDATE
1400 && prefix_list_length_validate(args) != NB_OK)
1401 return NB_ERR_VALIDATION;
1402
1403 if (args->event == NB_EV_VALIDATE) {
1404 const struct lyd_node *plist_dnode =
1405 yang_dnode_get_parent(args->dnode, "prefix-list");
1406
1407 if (plist_is_dup_nb(args->dnode)) {
1408 snprintf(args->errmsg, args->errmsg_len,
1409 "duplicated prefix list value: %s",
1410 yang_dnode_get_string(args->dnode, NULL));
1411 return NB_ERR_VALIDATION;
1412 }
1413
1414 return prefix_list_nb_validate_v4_af_type(
1415 plist_dnode, args->errmsg, args->errmsg_len);
1416 }
1417
1418 return lib_prefix_list_entry_prefix_length_greater_or_equal_modify(
1419 args);
1420 }
1421
1422 static int lib_prefix_list_entry_ipv4_prefix_length_greater_or_equal_destroy(
1423 struct nb_cb_destroy_args *args)
1424 {
1425 if (args->event == NB_EV_VALIDATE) {
1426 const struct lyd_node *plist_dnode =
1427 yang_dnode_get_parent(args->dnode, "prefix-list");
1428
1429 return prefix_list_nb_validate_v4_af_type(
1430 plist_dnode, args->errmsg, args->errmsg_len);
1431 }
1432
1433 return lib_prefix_list_entry_prefix_length_greater_or_equal_destroy(
1434 args);
1435 }
1436
1437 /*
1438 * XPath: /frr-filter:lib/prefix-list/entry/ipv4-prefix-length-lesser-or-equal
1439 */
1440 static int lib_prefix_list_entry_ipv4_prefix_length_lesser_or_equal_modify(
1441 struct nb_cb_modify_args *args)
1442 {
1443 if (args->event == NB_EV_VALIDATE
1444 && prefix_list_length_validate(args) != NB_OK)
1445 return NB_ERR_VALIDATION;
1446
1447 if (args->event == NB_EV_VALIDATE) {
1448 const struct lyd_node *plist_dnode =
1449 yang_dnode_get_parent(args->dnode, "prefix-list");
1450
1451 if (plist_is_dup_nb(args->dnode)) {
1452 snprintf(args->errmsg, args->errmsg_len,
1453 "duplicated prefix list value: %s",
1454 yang_dnode_get_string(args->dnode, NULL));
1455 return NB_ERR_VALIDATION;
1456 }
1457
1458 return prefix_list_nb_validate_v4_af_type(
1459 plist_dnode, args->errmsg, args->errmsg_len);
1460 }
1461
1462 return lib_prefix_list_entry_prefix_length_lesser_or_equal_modify(
1463 args);
1464 }
1465
1466 static int lib_prefix_list_entry_ipv4_prefix_length_lesser_or_equal_destroy(
1467 struct nb_cb_destroy_args *args)
1468 {
1469 if (args->event == NB_EV_VALIDATE) {
1470 const struct lyd_node *plist_dnode =
1471 yang_dnode_get_parent(args->dnode, "prefix-list");
1472
1473 return prefix_list_nb_validate_v4_af_type(
1474 plist_dnode, args->errmsg, args->errmsg_len);
1475 }
1476
1477 return lib_prefix_list_entry_prefix_length_lesser_or_equal_destroy(
1478 args);
1479 }
1480
1481 /*
1482 * XPath: /frr-filter:lib/prefix-list/entry/ipv6-prefix-length-greater-or-equal
1483 */
1484 static int lib_prefix_list_entry_ipv6_prefix_length_greater_or_equal_modify(
1485 struct nb_cb_modify_args *args)
1486 {
1487 if (args->event == NB_EV_VALIDATE
1488 && prefix_list_length_validate(args) != NB_OK)
1489 return NB_ERR_VALIDATION;
1490
1491 if (args->event == NB_EV_VALIDATE) {
1492 const struct lyd_node *plist_dnode =
1493 yang_dnode_get_parent(args->dnode, "prefix-list");
1494
1495 if (plist_is_dup_nb(args->dnode)) {
1496 snprintf(args->errmsg, args->errmsg_len,
1497 "duplicated prefix list value: %s",
1498 yang_dnode_get_string(args->dnode, NULL));
1499 return NB_ERR_VALIDATION;
1500 }
1501
1502 return prefix_list_nb_validate_v6_af_type(
1503 plist_dnode, args->errmsg, args->errmsg_len);
1504 }
1505
1506 return lib_prefix_list_entry_prefix_length_greater_or_equal_modify(
1507 args);
1508 }
1509
1510 static int lib_prefix_list_entry_ipv6_prefix_length_greater_or_equal_destroy(
1511 struct nb_cb_destroy_args *args)
1512 {
1513 if (args->event == NB_EV_VALIDATE) {
1514 const struct lyd_node *plist_dnode =
1515 yang_dnode_get_parent(args->dnode, "prefix-list");
1516
1517 return prefix_list_nb_validate_v6_af_type(
1518 plist_dnode, args->errmsg, args->errmsg_len);
1519 }
1520
1521 return lib_prefix_list_entry_prefix_length_greater_or_equal_destroy(
1522 args);
1523 }
1524
1525 /*
1526 * XPath: /frr-filter:lib/prefix-list/entry/ipv6-prefix-length-lesser-or-equal
1527 */
1528 static int lib_prefix_list_entry_ipv6_prefix_length_lesser_or_equal_modify(
1529 struct nb_cb_modify_args *args)
1530 {
1531 if (args->event == NB_EV_VALIDATE
1532 && prefix_list_length_validate(args) != NB_OK)
1533 return NB_ERR_VALIDATION;
1534
1535 if (args->event == NB_EV_VALIDATE) {
1536 const struct lyd_node *plist_dnode =
1537 yang_dnode_get_parent(args->dnode, "prefix-list");
1538
1539 if (plist_is_dup_nb(args->dnode)) {
1540 snprintf(args->errmsg, args->errmsg_len,
1541 "duplicated prefix list value: %s",
1542 yang_dnode_get_string(args->dnode, NULL));
1543 return NB_ERR_VALIDATION;
1544 }
1545
1546 return prefix_list_nb_validate_v6_af_type(
1547 plist_dnode, args->errmsg, args->errmsg_len);
1548 }
1549
1550 return lib_prefix_list_entry_prefix_length_lesser_or_equal_modify(
1551 args);
1552 }
1553
1554 static int lib_prefix_list_entry_ipv6_prefix_length_lesser_or_equal_destroy(
1555 struct nb_cb_destroy_args *args)
1556 {
1557 if (args->event == NB_EV_VALIDATE) {
1558 const struct lyd_node *plist_dnode =
1559 yang_dnode_get_parent(args->dnode, "prefix-list");
1560
1561 return prefix_list_nb_validate_v6_af_type(
1562 plist_dnode, args->errmsg, args->errmsg_len);
1563 }
1564
1565 return lib_prefix_list_entry_prefix_length_lesser_or_equal_destroy(
1566 args);
1567 }
1568
1569 /*
1570 * XPath: /frr-filter:lib/prefix-list/entry/any
1571 */
1572 static int lib_prefix_list_entry_any_create(struct nb_cb_create_args *args)
1573 {
1574 struct prefix_list_entry *ple;
1575 int type;
1576
1577 if (args->event == NB_EV_VALIDATE) {
1578 if (plist_is_dup_nb(args->dnode)) {
1579 snprintf(args->errmsg, args->errmsg_len,
1580 "duplicated prefix list value: %s",
1581 yang_dnode_get_string(args->dnode, NULL));
1582 return NB_ERR_VALIDATION;
1583 }
1584
1585 return NB_OK;
1586 }
1587
1588 if (args->event != NB_EV_APPLY)
1589 return NB_OK;
1590
1591 ple = nb_running_get_entry(args->dnode, NULL, true);
1592
1593 /* Start prefix entry update procedure. */
1594 prefix_list_entry_update_start(ple);
1595
1596 ple->any = true;
1597
1598 /* Fill prefix struct from scratch. */
1599 memset(&ple->prefix, 0, sizeof(ple->prefix));
1600
1601 type = yang_dnode_get_enum(args->dnode, "../../type");
1602 switch (type) {
1603 case YPLT_IPV4:
1604 ple->prefix.family = AF_INET;
1605 ple->ge = 0;
1606 ple->le = IPV4_MAX_BITLEN;
1607 break;
1608 case YPLT_IPV6:
1609 ple->prefix.family = AF_INET6;
1610 ple->ge = 0;
1611 ple->le = IPV6_MAX_BITLEN;
1612 break;
1613 }
1614
1615 /* Finish prefix entry update procedure. */
1616 prefix_list_entry_update_finish(ple);
1617
1618 return NB_OK;
1619 }
1620
1621 static int lib_prefix_list_entry_any_destroy(struct nb_cb_destroy_args *args)
1622 {
1623 struct prefix_list_entry *ple;
1624
1625 if (args->event != NB_EV_APPLY)
1626 return NB_OK;
1627
1628 ple = nb_running_get_entry(args->dnode, NULL, true);
1629
1630 /* Start prefix entry update procedure. */
1631 prefix_list_entry_update_start(ple);
1632
1633 prefix_list_entry_set_empty(ple);
1634
1635 /* Finish prefix entry update procedure. */
1636 prefix_list_entry_update_finish(ple);
1637
1638 return NB_OK;
1639 }
1640
1641 /* clang-format off */
1642 const struct frr_yang_module_info frr_filter_info = {
1643 .name = "frr-filter",
1644 .nodes = {
1645 {
1646 .xpath = "/frr-filter:lib/access-list",
1647 .cbs = {
1648 .create = lib_access_list_create,
1649 .destroy = lib_access_list_destroy,
1650 }
1651 },
1652 {
1653 .xpath = "/frr-filter:lib/access-list/remark",
1654 .cbs = {
1655 .modify = lib_access_list_remark_modify,
1656 .destroy = lib_access_list_remark_destroy,
1657 .cli_show = access_list_remark_show,
1658 }
1659 },
1660 {
1661 .xpath = "/frr-filter:lib/access-list/entry",
1662 .cbs = {
1663 .create = lib_access_list_entry_create,
1664 .destroy = lib_access_list_entry_destroy,
1665 .cli_cmp = access_list_cmp,
1666 .cli_show = access_list_show,
1667 }
1668 },
1669 {
1670 .xpath = "/frr-filter:lib/access-list/entry/action",
1671 .cbs = {
1672 .modify = lib_access_list_entry_action_modify,
1673 }
1674 },
1675 {
1676 .xpath = "/frr-filter:lib/access-list/entry/ipv4-prefix",
1677 .cbs = {
1678 .modify = lib_access_list_entry_ipv4_prefix_modify,
1679 .destroy = lib_access_list_entry_ipv4_prefix_destroy,
1680 }
1681 },
1682 {
1683 .xpath = "/frr-filter:lib/access-list/entry/ipv4-exact-match",
1684 .cbs = {
1685 .modify = lib_access_list_entry_ipv4_exact_match_modify,
1686 .destroy = lib_access_list_entry_ipv4_exact_match_destroy,
1687 }
1688 },
1689 {
1690 .xpath = "/frr-filter:lib/access-list/entry/host",
1691 .cbs = {
1692 .modify = lib_access_list_entry_host_modify,
1693 .destroy = lib_access_list_entry_host_destroy,
1694 }
1695 },
1696 {
1697 .xpath = "/frr-filter:lib/access-list/entry/network/address",
1698 .cbs = {
1699 .modify = lib_access_list_entry_network_address_modify,
1700 }
1701 },
1702 {
1703 .xpath = "/frr-filter:lib/access-list/entry/network/mask",
1704 .cbs = {
1705 .modify = lib_access_list_entry_network_mask_modify,
1706 }
1707 },
1708 {
1709 .xpath = "/frr-filter:lib/access-list/entry/source-any",
1710 .cbs = {
1711 .create = lib_access_list_entry_source_any_create,
1712 .destroy = lib_access_list_entry_source_any_destroy,
1713 }
1714 },
1715 {
1716 .xpath = "/frr-filter:lib/access-list/entry/destination-host",
1717 .cbs = {
1718 .modify = lib_access_list_entry_destination_host_modify,
1719 .destroy = lib_access_list_entry_destination_host_destroy,
1720 }
1721 },
1722 {
1723 .xpath = "/frr-filter:lib/access-list/entry/destination-network/address",
1724 .cbs = {
1725 .modify = lib_access_list_entry_destination_network_address_modify,
1726 }
1727 },
1728 {
1729 .xpath = "/frr-filter:lib/access-list/entry/destination-network/mask",
1730 .cbs = {
1731 .modify = lib_access_list_entry_destination_network_mask_modify,
1732 }
1733 },
1734 {
1735 .xpath = "/frr-filter:lib/access-list/entry/destination-any",
1736 .cbs = {
1737 .create = lib_access_list_entry_destination_any_create,
1738 .destroy = lib_access_list_entry_destination_any_destroy,
1739 }
1740 },
1741 {
1742 .xpath = "/frr-filter:lib/access-list/entry/ipv6-prefix",
1743 .cbs = {
1744 .modify = lib_access_list_entry_ipv4_prefix_modify,
1745 .destroy = lib_access_list_entry_ipv4_prefix_destroy,
1746 }
1747 },
1748 {
1749 .xpath = "/frr-filter:lib/access-list/entry/ipv6-exact-match",
1750 .cbs = {
1751 .modify = lib_access_list_entry_ipv4_exact_match_modify,
1752 .destroy = lib_access_list_entry_ipv4_exact_match_destroy,
1753 }
1754 },
1755 {
1756 .xpath = "/frr-filter:lib/access-list/entry/mac",
1757 .cbs = {
1758 .modify = lib_access_list_entry_ipv4_prefix_modify,
1759 .destroy = lib_access_list_entry_ipv4_prefix_destroy,
1760 }
1761 },
1762 {
1763 .xpath = "/frr-filter:lib/access-list/entry/any",
1764 .cbs = {
1765 .create = lib_access_list_entry_any_create,
1766 .destroy = lib_access_list_entry_any_destroy,
1767 }
1768 },
1769 {
1770 .xpath = "/frr-filter:lib/prefix-list",
1771 .cbs = {
1772 .create = lib_prefix_list_create,
1773 .destroy = lib_prefix_list_destroy,
1774 }
1775 },
1776 {
1777 .xpath = "/frr-filter:lib/prefix-list/remark",
1778 .cbs = {
1779 .modify = lib_prefix_list_remark_modify,
1780 .destroy = lib_prefix_list_remark_destroy,
1781 .cli_show = prefix_list_remark_show,
1782 }
1783 },
1784 {
1785 .xpath = "/frr-filter:lib/prefix-list/entry",
1786 .cbs = {
1787 .create = lib_prefix_list_entry_create,
1788 .destroy = lib_prefix_list_entry_destroy,
1789 .cli_cmp = prefix_list_cmp,
1790 .cli_show = prefix_list_show,
1791 }
1792 },
1793 {
1794 .xpath = "/frr-filter:lib/prefix-list/entry/action",
1795 .cbs = {
1796 .modify = lib_prefix_list_entry_action_modify,
1797 }
1798 },
1799 {
1800 .xpath = "/frr-filter:lib/prefix-list/entry/ipv4-prefix",
1801 .cbs = {
1802 .modify = lib_prefix_list_entry_ipv4_prefix_modify,
1803 .destroy = lib_prefix_list_entry_ipv4_prefix_destroy,
1804 }
1805 },
1806 {
1807 .xpath = "/frr-filter:lib/prefix-list/entry/ipv4-prefix-length-greater-or-equal",
1808 .cbs = {
1809 .modify = lib_prefix_list_entry_ipv4_prefix_length_greater_or_equal_modify,
1810 .destroy = lib_prefix_list_entry_ipv4_prefix_length_greater_or_equal_destroy,
1811 }
1812 },
1813 {
1814 .xpath = "/frr-filter:lib/prefix-list/entry/ipv4-prefix-length-lesser-or-equal",
1815 .cbs = {
1816 .modify = lib_prefix_list_entry_ipv4_prefix_length_lesser_or_equal_modify,
1817 .destroy = lib_prefix_list_entry_ipv4_prefix_length_lesser_or_equal_destroy,
1818 }
1819 },
1820 {
1821 .xpath = "/frr-filter:lib/prefix-list/entry/ipv6-prefix",
1822 .cbs = {
1823 .modify = lib_prefix_list_entry_ipv6_prefix_modify,
1824 .destroy = lib_prefix_list_entry_ipv6_prefix_destroy,
1825 }
1826 },
1827 {
1828 .xpath = "/frr-filter:lib/prefix-list/entry/ipv6-prefix-length-greater-or-equal",
1829 .cbs = {
1830 .modify = lib_prefix_list_entry_ipv6_prefix_length_greater_or_equal_modify,
1831 .destroy = lib_prefix_list_entry_ipv6_prefix_length_greater_or_equal_destroy,
1832 }
1833 },
1834 {
1835 .xpath = "/frr-filter:lib/prefix-list/entry/ipv6-prefix-length-lesser-or-equal",
1836 .cbs = {
1837 .modify = lib_prefix_list_entry_ipv6_prefix_length_lesser_or_equal_modify,
1838 .destroy = lib_prefix_list_entry_ipv6_prefix_length_lesser_or_equal_destroy,
1839 }
1840 },
1841 {
1842 .xpath = "/frr-filter:lib/prefix-list/entry/any",
1843 .cbs = {
1844 .create = lib_prefix_list_entry_any_create,
1845 .destroy = lib_prefix_list_entry_any_destroy,
1846 }
1847 },
1848 {
1849 .xpath = NULL,
1850 },
1851 }
1852 };