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