]>
Commit | Line | Data |
---|---|---|
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 |
35 | static 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 | 51 | static 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 |
102 | log_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 | */ | |
115 | static 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 | */ | |
130 | static 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 |
136 | static 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 | ||
167 | bool 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 | ||
179 | static 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 | ||
219 | static 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 | ||
4470143b | 268 | /* |
375d157f | 269 | * XPath: /frr-filter:lib/access-list |
4470143b | 270 | */ |
375d157f | 271 | static int lib_access_list_create(struct nb_cb_create_args *args) |
4470143b | 272 | { |
375d157f | 273 | struct access_list *acl = NULL; |
4470143b | 274 | const char *acl_name; |
375d157f | 275 | int type; |
4470143b | 276 | |
fb8884f3 | 277 | if (args->event != NB_EV_APPLY) |
4470143b RZ |
278 | return NB_OK; |
279 | ||
375d157f RZ |
280 | type = yang_dnode_get_enum(args->dnode, "./type"); |
281 | acl_name = yang_dnode_get_string(args->dnode, "./name"); | |
282 | ||
283 | switch (type) { | |
284 | case YALT_IPV4: | |
285 | acl = access_list_get(AFI_IP, acl_name); | |
286 | break; | |
287 | case YALT_IPV6: | |
288 | acl = access_list_get(AFI_IP6, acl_name); | |
289 | break; | |
290 | case YALT_MAC: | |
291 | acl = access_list_get(AFI_L2VPN, acl_name); | |
292 | break; | |
293 | } | |
294 | ||
fb8884f3 | 295 | nb_running_set_entry(args->dnode, acl); |
4470143b RZ |
296 | |
297 | return NB_OK; | |
298 | } | |
299 | ||
375d157f | 300 | static int lib_access_list_destroy(struct nb_cb_destroy_args *args) |
4470143b RZ |
301 | { |
302 | struct access_master *am; | |
303 | struct access_list *acl; | |
304 | ||
fb8884f3 | 305 | if (args->event != NB_EV_APPLY) |
4470143b RZ |
306 | return NB_OK; |
307 | ||
fb8884f3 | 308 | acl = nb_running_unset_entry(args->dnode); |
4470143b RZ |
309 | am = acl->master; |
310 | if (am->delete_hook) | |
311 | am->delete_hook(acl); | |
312 | ||
313 | access_list_delete(acl); | |
314 | ||
315 | return NB_OK; | |
316 | } | |
317 | ||
318 | /* | |
375d157f | 319 | * XPath: /frr-filter:lib/access-list/remark |
4470143b | 320 | */ |
375d157f | 321 | static int lib_access_list_remark_modify(struct nb_cb_modify_args *args) |
4470143b RZ |
322 | { |
323 | struct access_list *acl; | |
324 | const char *remark; | |
325 | ||
fb8884f3 | 326 | if (args->event != NB_EV_APPLY) |
4470143b RZ |
327 | return NB_OK; |
328 | ||
fb8884f3 | 329 | acl = nb_running_get_entry(args->dnode, NULL, true); |
4470143b RZ |
330 | if (acl->remark) |
331 | XFREE(MTYPE_TMP, acl->remark); | |
332 | ||
fb8884f3 | 333 | remark = yang_dnode_get_string(args->dnode, NULL); |
4470143b RZ |
334 | acl->remark = XSTRDUP(MTYPE_TMP, remark); |
335 | ||
336 | return NB_OK; | |
337 | } | |
338 | ||
fb8884f3 | 339 | static int |
375d157f | 340 | lib_access_list_remark_destroy(struct nb_cb_destroy_args *args) |
4470143b RZ |
341 | { |
342 | struct access_list *acl; | |
343 | ||
fb8884f3 | 344 | if (args->event != NB_EV_APPLY) |
4470143b RZ |
345 | return NB_OK; |
346 | ||
fb8884f3 | 347 | acl = nb_running_get_entry(args->dnode, NULL, true); |
4470143b RZ |
348 | if (acl->remark) |
349 | XFREE(MTYPE_TMP, acl->remark); | |
350 | ||
4470143b RZ |
351 | return NB_OK; |
352 | } | |
353 | ||
375d157f | 354 | |
4470143b | 355 | /* |
375d157f | 356 | * XPath: /frr-filter:lib/access-list/entry |
4470143b | 357 | */ |
375d157f | 358 | static int lib_access_list_entry_create(struct nb_cb_create_args *args) |
4470143b | 359 | { |
4470143b RZ |
360 | struct access_list *acl; |
361 | struct filter *f; | |
4470143b | 362 | |
fb8884f3 | 363 | if (args->event != NB_EV_APPLY) |
4470143b RZ |
364 | return NB_OK; |
365 | ||
4470143b | 366 | f = filter_new(); |
fb8884f3 | 367 | f->seq = yang_dnode_get_uint32(args->dnode, "./sequence"); |
4470143b | 368 | |
fb8884f3 | 369 | acl = nb_running_get_entry(args->dnode, NULL, true); |
4470143b RZ |
370 | f->acl = acl; |
371 | access_list_filter_add(acl, f); | |
fb8884f3 | 372 | nb_running_set_entry(args->dnode, f); |
4470143b RZ |
373 | |
374 | return NB_OK; | |
375 | } | |
376 | ||
375d157f | 377 | static int lib_access_list_entry_destroy(struct nb_cb_destroy_args *args) |
4470143b RZ |
378 | { |
379 | struct access_list *acl; | |
380 | struct filter *f; | |
381 | ||
fb8884f3 | 382 | if (args->event != NB_EV_APPLY) |
4470143b RZ |
383 | return NB_OK; |
384 | ||
fb8884f3 | 385 | f = nb_running_unset_entry(args->dnode); |
4470143b RZ |
386 | acl = f->acl; |
387 | access_list_filter_delete(acl, f); | |
388 | ||
389 | return NB_OK; | |
390 | } | |
391 | ||
392 | /* | |
375d157f | 393 | * XPath: /frr-filter:lib/access-list/entry/action |
4470143b RZ |
394 | */ |
395 | static int | |
375d157f | 396 | lib_access_list_entry_action_modify(struct nb_cb_modify_args *args) |
4470143b RZ |
397 | { |
398 | const char *filter_type; | |
399 | struct filter *f; | |
400 | ||
fb8884f3 | 401 | if (args->event != NB_EV_APPLY) |
4470143b RZ |
402 | return NB_OK; |
403 | ||
fb8884f3 RZ |
404 | f = nb_running_get_entry(args->dnode, NULL, true); |
405 | filter_type = yang_dnode_get_string(args->dnode, NULL); | |
4470143b RZ |
406 | if (strcmp(filter_type, "permit") == 0) |
407 | f->type = FILTER_PERMIT; | |
408 | else | |
409 | f->type = FILTER_DENY; | |
410 | ||
1eb17c77 K |
411 | acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_ADDED); |
412 | ||
4470143b RZ |
413 | return NB_OK; |
414 | } | |
415 | ||
416 | /* | |
375d157f | 417 | * XPath: /frr-filter:lib/access-list/entry/ipv4-prefix |
4470143b RZ |
418 | */ |
419 | static int | |
375d157f | 420 | lib_access_list_entry_ipv4_prefix_modify(struct nb_cb_modify_args *args) |
4470143b | 421 | { |
375d157f | 422 | struct filter_zebra *fz; |
4470143b RZ |
423 | struct filter *f; |
424 | ||
f414129b RZ |
425 | /* Don't allow duplicated values. */ |
426 | if (args->event == NB_EV_VALIDATE) { | |
427 | if (acl_zebra_is_dup( | |
428 | args->dnode, | |
429 | yang_dnode_get_enum(args->dnode, "../../type"))) { | |
430 | snprintfrr(args->errmsg, args->errmsg_len, | |
431 | "duplicated access list value: %s", | |
432 | yang_dnode_get_string(args->dnode, NULL)); | |
433 | return NB_ERR_VALIDATION; | |
434 | } | |
435 | return NB_OK; | |
436 | } | |
437 | ||
fb8884f3 | 438 | if (args->event != NB_EV_APPLY) |
4470143b RZ |
439 | return NB_OK; |
440 | ||
fb8884f3 | 441 | f = nb_running_get_entry(args->dnode, NULL, true); |
375d157f RZ |
442 | f->cisco = 0; |
443 | fz = &f->u.zfilter; | |
444 | yang_dnode_get_prefix(&fz->prefix, args->dnode, NULL); | |
4470143b | 445 | |
1eb17c77 K |
446 | acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_ADDED); |
447 | ||
4470143b RZ |
448 | return NB_OK; |
449 | } | |
450 | ||
451 | static int | |
375d157f | 452 | lib_access_list_entry_ipv4_prefix_destroy(struct nb_cb_destroy_args *args) |
4470143b | 453 | { |
375d157f | 454 | struct filter_zebra *fz; |
4470143b RZ |
455 | struct filter *f; |
456 | ||
fb8884f3 | 457 | if (args->event != NB_EV_APPLY) |
4470143b RZ |
458 | return NB_OK; |
459 | ||
fb8884f3 | 460 | f = nb_running_get_entry(args->dnode, NULL, true); |
375d157f RZ |
461 | fz = &f->u.zfilter; |
462 | memset(&fz->prefix, 0, sizeof(fz->prefix)); | |
4470143b | 463 | |
1eb17c77 K |
464 | acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_DELETED); |
465 | ||
4470143b RZ |
466 | return NB_OK; |
467 | } | |
468 | ||
469 | /* | |
375d157f | 470 | * XPath: /frr-filter:lib/access-list/entry/ipv4-exact-match |
4470143b RZ |
471 | */ |
472 | static int | |
375d157f | 473 | lib_access_list_entry_ipv4_exact_match_modify(struct nb_cb_modify_args *args) |
4470143b | 474 | { |
375d157f | 475 | struct filter_zebra *fz; |
4470143b | 476 | struct filter *f; |
4470143b | 477 | |
f414129b RZ |
478 | /* Don't allow duplicated values. */ |
479 | if (args->event == NB_EV_VALIDATE) { | |
480 | if (acl_zebra_is_dup( | |
481 | args->dnode, | |
482 | yang_dnode_get_enum(args->dnode, "../../type"))) { | |
483 | snprintfrr(args->errmsg, args->errmsg_len, | |
484 | "duplicated access list value: %s", | |
485 | yang_dnode_get_string(args->dnode, NULL)); | |
486 | return NB_ERR_VALIDATION; | |
487 | } | |
488 | return NB_OK; | |
489 | } | |
490 | ||
fb8884f3 | 491 | if (args->event != NB_EV_APPLY) |
4470143b RZ |
492 | return NB_OK; |
493 | ||
fb8884f3 | 494 | f = nb_running_get_entry(args->dnode, NULL, true); |
375d157f RZ |
495 | fz = &f->u.zfilter; |
496 | fz->exact = yang_dnode_get_bool(args->dnode, NULL); | |
4470143b | 497 | |
1eb17c77 K |
498 | acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_ADDED); |
499 | ||
4470143b RZ |
500 | return NB_OK; |
501 | } | |
502 | ||
503 | static int | |
375d157f | 504 | lib_access_list_entry_ipv4_exact_match_destroy(struct nb_cb_destroy_args *args) |
4470143b | 505 | { |
375d157f | 506 | struct filter_zebra *fz; |
4470143b RZ |
507 | struct filter *f; |
508 | ||
fb8884f3 | 509 | if (args->event != NB_EV_APPLY) |
4470143b RZ |
510 | return NB_OK; |
511 | ||
fb8884f3 | 512 | f = nb_running_get_entry(args->dnode, NULL, true); |
375d157f RZ |
513 | fz = &f->u.zfilter; |
514 | fz->exact = 0; | |
4470143b | 515 | |
1eb17c77 K |
516 | acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_DELETED); |
517 | ||
4470143b RZ |
518 | return NB_OK; |
519 | } | |
520 | ||
521 | /* | |
375d157f | 522 | * XPath: /frr-filter:lib/access-list/entry/host |
4470143b | 523 | */ |
fb8884f3 | 524 | static int |
375d157f | 525 | lib_access_list_entry_host_modify(struct nb_cb_modify_args *args) |
4470143b RZ |
526 | { |
527 | struct filter_cisco *fc; | |
528 | struct filter *f; | |
529 | ||
f414129b RZ |
530 | /* Don't allow duplicated values. */ |
531 | if (args->event == NB_EV_VALIDATE) { | |
532 | if (acl_cisco_is_dup(args->dnode)) { | |
533 | snprintfrr(args->errmsg, args->errmsg_len, | |
534 | "duplicated access list value: %s", | |
535 | yang_dnode_get_string(args->dnode, NULL)); | |
536 | return NB_ERR_VALIDATION; | |
537 | } | |
538 | return NB_OK; | |
539 | } | |
540 | ||
fb8884f3 | 541 | if (args->event != NB_EV_APPLY) |
4470143b RZ |
542 | return NB_OK; |
543 | ||
fb8884f3 | 544 | f = nb_running_get_entry(args->dnode, NULL, true); |
375d157f | 545 | f->cisco = 1; |
4470143b | 546 | fc = &f->u.cfilter; |
375d157f | 547 | yang_dnode_get_ipv4(&fc->addr, args->dnode, NULL); |
0ed507dd | 548 | fc->addr_mask.s_addr = CISCO_BIN_HOST_WILDCARD_MASK; |
4470143b | 549 | |
1eb17c77 K |
550 | acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_ADDED); |
551 | ||
4470143b RZ |
552 | return NB_OK; |
553 | } | |
554 | ||
555 | static int | |
375d157f | 556 | lib_access_list_entry_host_destroy(struct nb_cb_destroy_args *args) |
4470143b RZ |
557 | { |
558 | struct filter_cisco *fc; | |
559 | struct filter *f; | |
560 | ||
fb8884f3 | 561 | if (args->event != NB_EV_APPLY) |
4470143b RZ |
562 | return NB_OK; |
563 | ||
fb8884f3 | 564 | f = nb_running_get_entry(args->dnode, NULL, true); |
4470143b | 565 | fc = &f->u.cfilter; |
0ed507dd | 566 | cisco_unset_addr_mask(&fc->addr, &fc->addr_mask); |
4470143b | 567 | |
1eb17c77 K |
568 | acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_DELETED); |
569 | ||
4470143b RZ |
570 | return NB_OK; |
571 | } | |
572 | ||
573 | /* | |
b1993be6 | 574 | * XPath: /frr-filter:lib/access-list/entry/network/address |
4470143b | 575 | */ |
375d157f | 576 | static int |
b1993be6 | 577 | lib_access_list_entry_network_address_modify(struct nb_cb_modify_args *args) |
4470143b RZ |
578 | { |
579 | struct filter_cisco *fc; | |
580 | struct filter *f; | |
581 | ||
f414129b RZ |
582 | /* Don't allow duplicated values. */ |
583 | if (args->event == NB_EV_VALIDATE) { | |
584 | if (acl_cisco_is_dup(args->dnode)) { | |
585 | snprintfrr(args->errmsg, args->errmsg_len, | |
586 | "duplicated access list value: %s", | |
587 | yang_dnode_get_string(args->dnode, NULL)); | |
588 | return NB_ERR_VALIDATION; | |
589 | } | |
590 | return NB_OK; | |
591 | } | |
592 | ||
fb8884f3 | 593 | if (args->event != NB_EV_APPLY) |
4470143b RZ |
594 | return NB_OK; |
595 | ||
fb8884f3 | 596 | f = nb_running_get_entry(args->dnode, NULL, true); |
375d157f | 597 | f->cisco = 1; |
4470143b | 598 | fc = &f->u.cfilter; |
b1993be6 | 599 | yang_dnode_get_ipv4(&fc->addr, args->dnode, NULL); |
4470143b | 600 | |
1eb17c77 K |
601 | acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_ADDED); |
602 | ||
4470143b RZ |
603 | return NB_OK; |
604 | } | |
605 | ||
b1993be6 RZ |
606 | /* |
607 | * XPath: /frr-filter:lib/access-list/entry/network/mask | |
608 | */ | |
375d157f | 609 | static int |
b1993be6 | 610 | lib_access_list_entry_network_mask_modify(struct nb_cb_modify_args *args) |
4470143b RZ |
611 | { |
612 | struct filter_cisco *fc; | |
613 | struct filter *f; | |
614 | ||
f414129b RZ |
615 | /* Don't allow duplicated values. */ |
616 | if (args->event == NB_EV_VALIDATE) { | |
617 | if (acl_cisco_is_dup(args->dnode)) { | |
618 | snprintfrr(args->errmsg, args->errmsg_len, | |
619 | "duplicated access list value: %s", | |
620 | yang_dnode_get_string(args->dnode, NULL)); | |
621 | return NB_ERR_VALIDATION; | |
622 | } | |
623 | return NB_OK; | |
624 | } | |
625 | ||
fb8884f3 | 626 | if (args->event != NB_EV_APPLY) |
4470143b RZ |
627 | return NB_OK; |
628 | ||
fb8884f3 | 629 | f = nb_running_get_entry(args->dnode, NULL, true); |
b1993be6 | 630 | f->cisco = 1; |
4470143b | 631 | fc = &f->u.cfilter; |
b1993be6 | 632 | yang_dnode_get_ipv4(&fc->addr_mask, args->dnode, NULL); |
4470143b | 633 | |
b1993be6 | 634 | acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_ADDED); |
1eb17c77 | 635 | |
4470143b RZ |
636 | return NB_OK; |
637 | } | |
638 | ||
639 | /* | |
375d157f | 640 | * XPath: /frr-filter:lib/access-list/entry/source-any |
4470143b | 641 | */ |
375d157f RZ |
642 | static int |
643 | lib_access_list_entry_source_any_create(struct nb_cb_create_args *args) | |
4470143b RZ |
644 | { |
645 | struct filter_cisco *fc; | |
646 | struct filter *f; | |
4470143b | 647 | |
f414129b RZ |
648 | /* Don't allow duplicated values. */ |
649 | if (args->event == NB_EV_VALIDATE) { | |
650 | if (acl_cisco_is_dup(args->dnode)) { | |
651 | snprintfrr(args->errmsg, args->errmsg_len, | |
652 | "duplicated access list value: %s", | |
653 | yang_dnode_get_string(args->dnode, NULL)); | |
654 | return NB_ERR_VALIDATION; | |
655 | } | |
656 | return NB_OK; | |
657 | } | |
658 | ||
fb8884f3 | 659 | if (args->event != NB_EV_APPLY) |
4470143b RZ |
660 | return NB_OK; |
661 | ||
fb8884f3 | 662 | f = nb_running_get_entry(args->dnode, NULL, true); |
375d157f | 663 | f->cisco = 1; |
4470143b | 664 | fc = &f->u.cfilter; |
375d157f | 665 | fc->addr.s_addr = INADDR_ANY; |
0ed507dd | 666 | fc->addr_mask.s_addr = CISCO_BIN_ANY_WILDCARD_MASK; |
4470143b | 667 | |
1eb17c77 K |
668 | acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_ADDED); |
669 | ||
4470143b RZ |
670 | return NB_OK; |
671 | } | |
672 | ||
375d157f RZ |
673 | static int |
674 | lib_access_list_entry_source_any_destroy(struct nb_cb_destroy_args *args) | |
4470143b RZ |
675 | { |
676 | struct filter_cisco *fc; | |
677 | struct filter *f; | |
678 | ||
fb8884f3 | 679 | if (args->event != NB_EV_APPLY) |
4470143b RZ |
680 | return NB_OK; |
681 | ||
fb8884f3 | 682 | f = nb_running_get_entry(args->dnode, NULL, true); |
4470143b | 683 | fc = &f->u.cfilter; |
0ed507dd | 684 | cisco_unset_addr_mask(&fc->addr, &fc->addr_mask); |
4470143b | 685 | |
1eb17c77 K |
686 | acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_DELETED); |
687 | ||
4470143b RZ |
688 | return NB_OK; |
689 | } | |
690 | ||
691 | /* | |
375d157f | 692 | * XPath: /frr-filter:lib/access-list/entry/destination-host |
4470143b | 693 | */ |
375d157f RZ |
694 | static int lib_access_list_entry_destination_host_modify( |
695 | struct nb_cb_modify_args *args) | |
4470143b RZ |
696 | { |
697 | struct filter_cisco *fc; | |
698 | struct filter *f; | |
699 | ||
f414129b RZ |
700 | /* Don't allow duplicated values. */ |
701 | if (args->event == NB_EV_VALIDATE) { | |
702 | if (acl_cisco_is_dup(args->dnode)) { | |
703 | snprintfrr(args->errmsg, args->errmsg_len, | |
704 | "duplicated access list value: %s", | |
705 | yang_dnode_get_string(args->dnode, NULL)); | |
706 | return NB_ERR_VALIDATION; | |
707 | } | |
708 | return NB_OK; | |
709 | } | |
710 | ||
fb8884f3 | 711 | if (args->event != NB_EV_APPLY) |
4470143b RZ |
712 | return NB_OK; |
713 | ||
fb8884f3 | 714 | f = nb_running_get_entry(args->dnode, NULL, true); |
4470143b | 715 | fc = &f->u.cfilter; |
375d157f RZ |
716 | fc->extended = 1; |
717 | yang_dnode_get_ipv4(&fc->mask, args->dnode, NULL); | |
0ed507dd | 718 | fc->mask_mask.s_addr = CISCO_BIN_HOST_WILDCARD_MASK; |
4470143b | 719 | |
1eb17c77 K |
720 | acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_ADDED); |
721 | ||
4470143b RZ |
722 | return NB_OK; |
723 | } | |
724 | ||
375d157f | 725 | static int lib_access_list_entry_destination_host_destroy( |
fb8884f3 | 726 | struct nb_cb_destroy_args *args) |
4470143b RZ |
727 | { |
728 | struct filter_cisco *fc; | |
729 | struct filter *f; | |
730 | ||
fb8884f3 | 731 | if (args->event != NB_EV_APPLY) |
4470143b RZ |
732 | return NB_OK; |
733 | ||
fb8884f3 | 734 | f = nb_running_get_entry(args->dnode, NULL, true); |
4470143b | 735 | fc = &f->u.cfilter; |
375d157f | 736 | fc->extended = 0; |
0ed507dd | 737 | cisco_unset_addr_mask(&fc->mask, &fc->mask_mask); |
4470143b | 738 | |
1eb17c77 K |
739 | acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_DELETED); |
740 | ||
4470143b RZ |
741 | return NB_OK; |
742 | } | |
743 | ||
744 | /* | |
b1993be6 | 745 | * XPath: /frr-filter:lib/access-list/entry/destination-network/address |
4470143b | 746 | */ |
b1993be6 | 747 | static int lib_access_list_entry_destination_network_address_modify( |
375d157f | 748 | struct nb_cb_modify_args *args) |
4470143b | 749 | { |
375d157f | 750 | struct filter_cisco *fc; |
4470143b RZ |
751 | struct filter *f; |
752 | ||
f414129b RZ |
753 | /* Don't allow duplicated values. */ |
754 | if (args->event == NB_EV_VALIDATE) { | |
755 | if (acl_cisco_is_dup(args->dnode)) { | |
756 | snprintfrr(args->errmsg, args->errmsg_len, | |
757 | "duplicated access list value: %s", | |
758 | yang_dnode_get_string(args->dnode, NULL)); | |
759 | return NB_ERR_VALIDATION; | |
760 | } | |
761 | return NB_OK; | |
762 | } | |
763 | ||
fb8884f3 | 764 | if (args->event != NB_EV_APPLY) |
4470143b RZ |
765 | return NB_OK; |
766 | ||
fb8884f3 | 767 | f = nb_running_get_entry(args->dnode, NULL, true); |
375d157f RZ |
768 | fc = &f->u.cfilter; |
769 | fc->extended = 1; | |
b1993be6 | 770 | yang_dnode_get_ipv4(&fc->mask, args->dnode, NULL); |
4470143b | 771 | |
1eb17c77 K |
772 | acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_ADDED); |
773 | ||
4470143b RZ |
774 | return NB_OK; |
775 | } | |
776 | ||
b1993be6 RZ |
777 | /* |
778 | * XPath: /frr-filter:lib/access-list/entry/destination-network/mask | |
779 | */ | |
780 | static int lib_access_list_entry_destination_network_mask_modify( | |
781 | struct nb_cb_modify_args *args) | |
4470143b | 782 | { |
375d157f | 783 | struct filter_cisco *fc; |
4470143b RZ |
784 | struct filter *f; |
785 | ||
f414129b RZ |
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 | ||
fb8884f3 | 797 | if (args->event != NB_EV_APPLY) |
4470143b RZ |
798 | return NB_OK; |
799 | ||
fb8884f3 | 800 | f = nb_running_get_entry(args->dnode, NULL, true); |
375d157f | 801 | fc = &f->u.cfilter; |
b1993be6 RZ |
802 | fc->extended = 1; |
803 | yang_dnode_get_ipv4(&fc->mask_mask, args->dnode, NULL); | |
4470143b | 804 | |
b1993be6 | 805 | acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_ADDED); |
1eb17c77 | 806 | |
4470143b RZ |
807 | return NB_OK; |
808 | } | |
809 | ||
810 | /* | |
375d157f | 811 | * XPath: /frr-filter:lib/access-list/entry/destination-any |
4470143b | 812 | */ |
375d157f RZ |
813 | static int lib_access_list_entry_destination_any_create( |
814 | struct nb_cb_create_args *args) | |
4470143b | 815 | { |
375d157f | 816 | struct filter_cisco *fc; |
4470143b RZ |
817 | struct filter *f; |
818 | ||
f414129b RZ |
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 | ||
fb8884f3 | 830 | if (args->event != NB_EV_APPLY) |
4470143b RZ |
831 | return NB_OK; |
832 | ||
fb8884f3 | 833 | f = nb_running_get_entry(args->dnode, NULL, true); |
375d157f RZ |
834 | fc = &f->u.cfilter; |
835 | fc->extended = 1; | |
836 | fc->mask.s_addr = INADDR_ANY; | |
0ed507dd | 837 | fc->mask_mask.s_addr = CISCO_BIN_ANY_WILDCARD_MASK; |
4470143b | 838 | |
1eb17c77 K |
839 | acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_ADDED); |
840 | ||
4470143b RZ |
841 | return NB_OK; |
842 | } | |
843 | ||
375d157f RZ |
844 | static int lib_access_list_entry_destination_any_destroy( |
845 | struct nb_cb_destroy_args *args) | |
4470143b | 846 | { |
375d157f | 847 | struct filter_cisco *fc; |
4470143b RZ |
848 | struct filter *f; |
849 | ||
fb8884f3 | 850 | if (args->event != NB_EV_APPLY) |
4470143b RZ |
851 | return NB_OK; |
852 | ||
fb8884f3 | 853 | f = nb_running_get_entry(args->dnode, NULL, true); |
375d157f RZ |
854 | fc = &f->u.cfilter; |
855 | fc->extended = 0; | |
0ed507dd | 856 | cisco_unset_addr_mask(&fc->mask, &fc->mask_mask); |
4470143b | 857 | |
1eb17c77 K |
858 | acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_DELETED); |
859 | ||
4470143b RZ |
860 | return NB_OK; |
861 | } | |
862 | ||
4470143b RZ |
863 | /* |
864 | * XPath: /frr-filter:lib/access-list/entry/any | |
865 | */ | |
fb8884f3 | 866 | static int lib_access_list_entry_any_create(struct nb_cb_create_args *args) |
4470143b RZ |
867 | { |
868 | struct filter_zebra *fz; | |
869 | struct filter *f; | |
870 | int type; | |
871 | ||
f414129b RZ |
872 | /* Don't allow duplicated values. */ |
873 | if (args->event == NB_EV_VALIDATE) { | |
874 | if (acl_zebra_is_dup( | |
875 | args->dnode, | |
876 | yang_dnode_get_enum(args->dnode, "../../type"))) { | |
877 | snprintfrr(args->errmsg, args->errmsg_len, | |
878 | "duplicated access list value: %s", | |
879 | yang_dnode_get_string(args->dnode, NULL)); | |
880 | return NB_ERR_VALIDATION; | |
881 | } | |
882 | return NB_OK; | |
883 | } | |
884 | ||
fb8884f3 | 885 | if (args->event != NB_EV_APPLY) |
4470143b RZ |
886 | return NB_OK; |
887 | ||
fb8884f3 | 888 | f = nb_running_get_entry(args->dnode, NULL, true); |
375d157f | 889 | f->cisco = 0; |
4470143b RZ |
890 | fz = &f->u.zfilter; |
891 | memset(&fz->prefix, 0, sizeof(fz->prefix)); | |
892 | ||
fb8884f3 | 893 | type = yang_dnode_get_enum(args->dnode, "../../type"); |
4470143b | 894 | switch (type) { |
be96651c | 895 | case YALT_IPV4: |
4470143b RZ |
896 | fz->prefix.family = AF_INET; |
897 | break; | |
be96651c | 898 | case YALT_IPV6: |
4470143b RZ |
899 | fz->prefix.family = AF_INET6; |
900 | break; | |
be96651c | 901 | case YALT_MAC: |
4470143b RZ |
902 | fz->prefix.family = AF_ETHERNET; |
903 | break; | |
904 | } | |
905 | ||
1eb17c77 K |
906 | acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_ADDED); |
907 | ||
4470143b RZ |
908 | return NB_OK; |
909 | } | |
910 | ||
fb8884f3 | 911 | static int lib_access_list_entry_any_destroy(struct nb_cb_destroy_args *args) |
4470143b RZ |
912 | { |
913 | struct filter_zebra *fz; | |
914 | struct filter *f; | |
915 | ||
fb8884f3 | 916 | if (args->event != NB_EV_APPLY) |
4470143b RZ |
917 | return NB_OK; |
918 | ||
fb8884f3 | 919 | f = nb_running_get_entry(args->dnode, NULL, true); |
4470143b RZ |
920 | fz = &f->u.zfilter; |
921 | fz->prefix.family = 0; | |
922 | ||
1eb17c77 K |
923 | acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_DELETED); |
924 | ||
4470143b RZ |
925 | return NB_OK; |
926 | } | |
927 | ||
928 | /* | |
929 | * XPath: /frr-filter:lib/prefix-list | |
930 | */ | |
fb8884f3 | 931 | static int lib_prefix_list_create(struct nb_cb_create_args *args) |
4470143b | 932 | { |
ff94358e | 933 | struct prefix_list *pl = NULL; |
4470143b RZ |
934 | const char *name; |
935 | int type; | |
936 | ||
fb8884f3 | 937 | if (args->event != NB_EV_APPLY) |
4470143b RZ |
938 | return NB_OK; |
939 | ||
fb8884f3 RZ |
940 | type = yang_dnode_get_enum(args->dnode, "./type"); |
941 | name = yang_dnode_get_string(args->dnode, "./name"); | |
4470143b RZ |
942 | switch (type) { |
943 | case 0: /* ipv4 */ | |
944 | pl = prefix_list_get(AFI_IP, 0, name); | |
945 | break; | |
946 | case 1: /* ipv6 */ | |
947 | pl = prefix_list_get(AFI_IP6, 0, name); | |
948 | break; | |
949 | } | |
950 | ||
fb8884f3 | 951 | nb_running_set_entry(args->dnode, pl); |
4470143b RZ |
952 | |
953 | return NB_OK; | |
954 | } | |
955 | ||
fb8884f3 | 956 | static int lib_prefix_list_destroy(struct nb_cb_destroy_args *args) |
4470143b RZ |
957 | { |
958 | struct prefix_list *pl; | |
959 | ||
fb8884f3 | 960 | if (args->event != NB_EV_APPLY) |
4470143b RZ |
961 | return NB_OK; |
962 | ||
fb8884f3 | 963 | pl = nb_running_unset_entry(args->dnode); |
4470143b RZ |
964 | prefix_list_delete(pl); |
965 | ||
966 | return NB_OK; | |
967 | } | |
968 | ||
969 | /* | |
cc82bcc1 | 970 | * XPath: /frr-filter:lib/prefix-list/remark |
4470143b | 971 | */ |
cc82bcc1 | 972 | static int lib_prefix_list_remark_modify(struct nb_cb_modify_args *args) |
4470143b RZ |
973 | { |
974 | struct prefix_list *pl; | |
975 | const char *remark; | |
976 | ||
fb8884f3 | 977 | if (args->event != NB_EV_APPLY) |
4470143b RZ |
978 | return NB_OK; |
979 | ||
fb8884f3 | 980 | pl = nb_running_get_entry(args->dnode, NULL, true); |
4470143b RZ |
981 | if (pl->desc) |
982 | XFREE(MTYPE_TMP, pl->desc); | |
983 | ||
fb8884f3 | 984 | remark = yang_dnode_get_string(args->dnode, NULL); |
4470143b RZ |
985 | pl->desc = XSTRDUP(MTYPE_TMP, remark); |
986 | ||
987 | return NB_OK; | |
988 | } | |
989 | ||
cc82bcc1 | 990 | static int lib_prefix_list_remark_destroy(struct nb_cb_destroy_args *args) |
4470143b RZ |
991 | { |
992 | struct prefix_list *pl; | |
993 | ||
fb8884f3 | 994 | if (args->event != NB_EV_APPLY) |
4470143b RZ |
995 | return NB_OK; |
996 | ||
fb8884f3 | 997 | pl = nb_running_get_entry(args->dnode, NULL, true); |
4470143b RZ |
998 | if (pl->desc) |
999 | XFREE(MTYPE_TMP, pl->desc); | |
1000 | ||
4470143b RZ |
1001 | return NB_OK; |
1002 | } | |
1003 | ||
1004 | /* | |
1005 | * XPath: /frr-filter:lib/prefix-list/entry | |
1006 | */ | |
fb8884f3 | 1007 | static int lib_prefix_list_entry_create(struct nb_cb_create_args *args) |
4470143b RZ |
1008 | { |
1009 | struct prefix_list_entry *ple; | |
1010 | struct prefix_list *pl; | |
4470143b | 1011 | |
fb8884f3 | 1012 | if (args->event != NB_EV_APPLY) |
4470143b RZ |
1013 | return NB_OK; |
1014 | ||
fb8884f3 | 1015 | pl = nb_running_get_entry(args->dnode, NULL, true); |
4470143b RZ |
1016 | ple = prefix_list_entry_new(); |
1017 | ple->pl = pl; | |
cc82bcc1 | 1018 | ple->seq = yang_dnode_get_uint32(args->dnode, "./sequence"); |
81b50422 | 1019 | prefix_list_entry_set_empty(ple); |
a7b28218 | 1020 | nb_running_set_entry(args->dnode, ple); |
4470143b RZ |
1021 | |
1022 | return NB_OK; | |
1023 | } | |
1024 | ||
fb8884f3 | 1025 | static int lib_prefix_list_entry_destroy(struct nb_cb_destroy_args *args) |
4470143b RZ |
1026 | { |
1027 | struct prefix_list_entry *ple; | |
1028 | ||
fb8884f3 | 1029 | if (args->event != NB_EV_APPLY) |
4470143b RZ |
1030 | return NB_OK; |
1031 | ||
fb8884f3 | 1032 | ple = nb_running_unset_entry(args->dnode); |
a7b28218 | 1033 | if (ple->installed) |
81b50422 | 1034 | prefix_list_entry_delete2(ple); |
a7b28218 RZ |
1035 | else |
1036 | prefix_list_entry_free(ple); | |
4470143b RZ |
1037 | |
1038 | return NB_OK; | |
1039 | } | |
1040 | ||
1041 | /* | |
1042 | * XPath: /frr-filter:lib/prefix-list/entry/action | |
1043 | */ | |
fb8884f3 | 1044 | static int lib_prefix_list_entry_action_modify(struct nb_cb_modify_args *args) |
4470143b RZ |
1045 | { |
1046 | struct prefix_list_entry *ple; | |
be96651c | 1047 | int action_type; |
4470143b | 1048 | |
fb8884f3 | 1049 | if (args->event != NB_EV_APPLY) |
4470143b RZ |
1050 | return NB_OK; |
1051 | ||
fb8884f3 | 1052 | ple = nb_running_get_entry(args->dnode, NULL, true); |
a7b28218 RZ |
1053 | |
1054 | /* Start prefix entry update procedure. */ | |
1055 | prefix_list_entry_update_start(ple); | |
1056 | ||
be96651c RZ |
1057 | action_type = yang_dnode_get_enum(args->dnode, NULL); |
1058 | if (action_type == YPLA_PERMIT) | |
4470143b RZ |
1059 | ple->type = PREFIX_PERMIT; |
1060 | else | |
1061 | ple->type = PREFIX_DENY; | |
1062 | ||
a7b28218 RZ |
1063 | /* Finish prefix entry update procedure. */ |
1064 | prefix_list_entry_update_finish(ple); | |
1065 | ||
4470143b RZ |
1066 | return NB_OK; |
1067 | } | |
1068 | ||
1069 | /* | |
1070 | * XPath: /frr-filter:lib/prefix-list/entry/ipv4-prefix | |
1071 | */ | |
1072 | static int | |
fb8884f3 | 1073 | lib_prefix_list_entry_ipv4_prefix_modify(struct nb_cb_modify_args *args) |
4470143b RZ |
1074 | { |
1075 | struct prefix_list_entry *ple; | |
cf4472c4 RZ |
1076 | struct prefix p; |
1077 | ||
1078 | if (args->event == NB_EV_VALIDATE) { | |
1079 | /* | |
1080 | * TODO: validate prefix_entry_dup_check() passes. | |
1081 | * | |
1082 | * This needs to be implemented using YANG lyd_node | |
1083 | * navigation, because the `priv` data structures are not | |
1084 | * available at `NB_EV_VALIDATE` phase. An easier | |
1085 | * alternative would be mark `ipvx-prefix` as unique | |
1086 | * (see RFC 7950, Section 7.8.3. The list "unique" Statement). | |
1087 | */ | |
1088 | return NB_OK; | |
1089 | } | |
4470143b | 1090 | |
fb8884f3 | 1091 | if (args->event != NB_EV_APPLY) |
4470143b RZ |
1092 | return NB_OK; |
1093 | ||
fb8884f3 | 1094 | ple = nb_running_get_entry(args->dnode, NULL, true); |
a7b28218 RZ |
1095 | |
1096 | /* Start prefix entry update procedure. */ | |
1097 | prefix_list_entry_update_start(ple); | |
1098 | ||
fb8884f3 | 1099 | yang_dnode_get_prefix(&ple->prefix, args->dnode, NULL); |
4470143b | 1100 | |
cf4472c4 RZ |
1101 | /* Apply mask and correct original address if necessary. */ |
1102 | prefix_copy(&p, &ple->prefix); | |
1103 | apply_mask(&p); | |
1104 | if (!prefix_same(&ple->prefix, &p)) { | |
1105 | zlog_info("%s: bad network %pFX correcting it to %pFX", | |
1106 | __func__, &ple->prefix, &p); | |
1107 | prefix_copy(&ple->prefix, &p); | |
1108 | } | |
1109 | ||
1110 | ||
a7b28218 RZ |
1111 | /* Finish prefix entry update procedure. */ |
1112 | prefix_list_entry_update_finish(ple); | |
1113 | ||
4470143b RZ |
1114 | return NB_OK; |
1115 | } | |
1116 | ||
1117 | static int | |
fb8884f3 | 1118 | lib_prefix_list_entry_ipv4_prefix_destroy(struct nb_cb_destroy_args *args) |
4470143b RZ |
1119 | { |
1120 | struct prefix_list_entry *ple; | |
1121 | ||
fb8884f3 | 1122 | if (args->event != NB_EV_APPLY) |
4470143b RZ |
1123 | return NB_OK; |
1124 | ||
fb8884f3 | 1125 | ple = nb_running_get_entry(args->dnode, NULL, true); |
a7b28218 RZ |
1126 | |
1127 | /* Start prefix entry update procedure. */ | |
1128 | prefix_list_entry_update_start(ple); | |
1129 | ||
4470143b | 1130 | memset(&ple->prefix, 0, sizeof(ple->prefix)); |
4470143b | 1131 | |
a7b28218 RZ |
1132 | /* Finish prefix entry update procedure. */ |
1133 | prefix_list_entry_update_finish(ple); | |
1134 | ||
4470143b RZ |
1135 | return NB_OK; |
1136 | } | |
1137 | ||
1138 | /* | |
1139 | * XPath: /frr-filter:lib/prefix-list/entry/ipv4-prefix-length-greater-or-equal | |
1140 | */ | |
1141 | static int lib_prefix_list_entry_ipv4_prefix_length_greater_or_equal_modify( | |
fb8884f3 | 1142 | struct nb_cb_modify_args *args) |
4470143b RZ |
1143 | { |
1144 | struct prefix_list_entry *ple; | |
1145 | ||
4362a768 | 1146 | if (args->event == NB_EV_VALIDATE && |
8bc38cbd | 1147 | prefix_list_length_validate(args) != NB_OK) |
4362a768 RZ |
1148 | return NB_ERR_VALIDATION; |
1149 | ||
fb8884f3 | 1150 | if (args->event != NB_EV_APPLY) |
4470143b RZ |
1151 | return NB_OK; |
1152 | ||
fb8884f3 | 1153 | ple = nb_running_get_entry(args->dnode, NULL, true); |
a7b28218 RZ |
1154 | |
1155 | /* Start prefix entry update procedure. */ | |
1156 | prefix_list_entry_update_start(ple); | |
1157 | ||
fb8884f3 | 1158 | ple->ge = yang_dnode_get_uint8(args->dnode, NULL); |
4470143b | 1159 | |
a7b28218 RZ |
1160 | /* Finish prefix entry update procedure. */ |
1161 | prefix_list_entry_update_finish(ple); | |
1162 | ||
4470143b RZ |
1163 | return NB_OK; |
1164 | } | |
1165 | ||
1166 | static int lib_prefix_list_entry_ipv4_prefix_length_greater_or_equal_destroy( | |
fb8884f3 | 1167 | struct nb_cb_destroy_args *args) |
4470143b RZ |
1168 | { |
1169 | struct prefix_list_entry *ple; | |
1170 | ||
fb8884f3 | 1171 | if (args->event != NB_EV_APPLY) |
4470143b RZ |
1172 | return NB_OK; |
1173 | ||
fb8884f3 | 1174 | ple = nb_running_get_entry(args->dnode, NULL, true); |
a7b28218 RZ |
1175 | |
1176 | /* Start prefix entry update procedure. */ | |
1177 | prefix_list_entry_update_start(ple); | |
1178 | ||
4470143b RZ |
1179 | ple->ge = 0; |
1180 | ||
a7b28218 RZ |
1181 | /* Finish prefix entry update procedure. */ |
1182 | prefix_list_entry_update_finish(ple); | |
1183 | ||
4470143b RZ |
1184 | return NB_OK; |
1185 | } | |
1186 | ||
1187 | /* | |
1188 | * XPath: /frr-filter:lib/prefix-list/entry/ipv4-prefix-length-lesser-or-equal | |
1189 | */ | |
1190 | static int lib_prefix_list_entry_ipv4_prefix_length_lesser_or_equal_modify( | |
fb8884f3 | 1191 | struct nb_cb_modify_args *args) |
4470143b RZ |
1192 | { |
1193 | struct prefix_list_entry *ple; | |
1194 | ||
4362a768 | 1195 | if (args->event == NB_EV_VALIDATE && |
8bc38cbd | 1196 | prefix_list_length_validate(args) != NB_OK) |
4362a768 RZ |
1197 | return NB_ERR_VALIDATION; |
1198 | ||
fb8884f3 | 1199 | if (args->event != NB_EV_APPLY) |
4470143b RZ |
1200 | return NB_OK; |
1201 | ||
fb8884f3 | 1202 | ple = nb_running_get_entry(args->dnode, NULL, true); |
a7b28218 RZ |
1203 | |
1204 | /* Start prefix entry update procedure. */ | |
1205 | prefix_list_entry_update_start(ple); | |
1206 | ||
fb8884f3 | 1207 | ple->le = yang_dnode_get_uint8(args->dnode, NULL); |
4470143b | 1208 | |
a7b28218 RZ |
1209 | /* Finish prefix entry update procedure. */ |
1210 | prefix_list_entry_update_finish(ple); | |
1211 | ||
4470143b RZ |
1212 | return NB_OK; |
1213 | } | |
1214 | ||
1215 | static int lib_prefix_list_entry_ipv4_prefix_length_lesser_or_equal_destroy( | |
fb8884f3 | 1216 | struct nb_cb_destroy_args *args) |
4470143b RZ |
1217 | { |
1218 | struct prefix_list_entry *ple; | |
1219 | ||
fb8884f3 | 1220 | if (args->event != NB_EV_APPLY) |
4470143b RZ |
1221 | return NB_OK; |
1222 | ||
fb8884f3 | 1223 | ple = nb_running_get_entry(args->dnode, NULL, true); |
a7b28218 RZ |
1224 | |
1225 | /* Start prefix entry update procedure. */ | |
1226 | prefix_list_entry_update_start(ple); | |
1227 | ||
4470143b RZ |
1228 | ple->le = 0; |
1229 | ||
a7b28218 RZ |
1230 | /* Finish prefix entry update procedure. */ |
1231 | prefix_list_entry_update_finish(ple); | |
1232 | ||
4470143b RZ |
1233 | return NB_OK; |
1234 | } | |
1235 | ||
4470143b RZ |
1236 | /* |
1237 | * XPath: /frr-filter:lib/prefix-list/entry/any | |
1238 | */ | |
fb8884f3 | 1239 | static int lib_prefix_list_entry_any_create(struct nb_cb_create_args *args) |
4470143b RZ |
1240 | { |
1241 | struct prefix_list_entry *ple; | |
81b50422 | 1242 | int type; |
4470143b | 1243 | |
fb8884f3 | 1244 | if (args->event != NB_EV_APPLY) |
4470143b RZ |
1245 | return NB_OK; |
1246 | ||
fb8884f3 | 1247 | ple = nb_running_get_entry(args->dnode, NULL, true); |
a7b28218 RZ |
1248 | |
1249 | /* Start prefix entry update procedure. */ | |
1250 | prefix_list_entry_update_start(ple); | |
1251 | ||
81b50422 RZ |
1252 | ple->any = true; |
1253 | ||
1254 | /* Fill prefix struct from scratch. */ | |
4470143b | 1255 | memset(&ple->prefix, 0, sizeof(ple->prefix)); |
81b50422 RZ |
1256 | |
1257 | type = yang_dnode_get_enum(args->dnode, "../../type"); | |
1258 | switch (type) { | |
be96651c | 1259 | case YPLT_IPV4: |
81b50422 RZ |
1260 | ple->prefix.family = AF_INET; |
1261 | ple->ge = 0; | |
1262 | ple->le = IPV4_MAX_BITLEN; | |
1263 | break; | |
be96651c | 1264 | case YPLT_IPV6: |
81b50422 RZ |
1265 | ple->prefix.family = AF_INET6; |
1266 | ple->ge = 0; | |
1267 | ple->le = IPV6_MAX_BITLEN; | |
1268 | break; | |
1269 | } | |
4470143b | 1270 | |
a7b28218 RZ |
1271 | /* Finish prefix entry update procedure. */ |
1272 | prefix_list_entry_update_finish(ple); | |
1273 | ||
4470143b RZ |
1274 | return NB_OK; |
1275 | } | |
1276 | ||
fb8884f3 | 1277 | static int lib_prefix_list_entry_any_destroy(struct nb_cb_destroy_args *args) |
4470143b RZ |
1278 | { |
1279 | struct prefix_list_entry *ple; | |
1280 | ||
fb8884f3 | 1281 | if (args->event != NB_EV_APPLY) |
4470143b RZ |
1282 | return NB_OK; |
1283 | ||
fb8884f3 | 1284 | ple = nb_running_get_entry(args->dnode, NULL, true); |
a7b28218 RZ |
1285 | |
1286 | /* Start prefix entry update procedure. */ | |
1287 | prefix_list_entry_update_start(ple); | |
1288 | ||
81b50422 | 1289 | prefix_list_entry_set_empty(ple); |
4470143b | 1290 | |
a7b28218 RZ |
1291 | /* Finish prefix entry update procedure. */ |
1292 | prefix_list_entry_update_finish(ple); | |
1293 | ||
4470143b RZ |
1294 | return NB_OK; |
1295 | } | |
1296 | ||
1297 | /* clang-format off */ | |
1298 | const struct frr_yang_module_info frr_filter_info = { | |
1299 | .name = "frr-filter", | |
1300 | .nodes = { | |
1301 | { | |
375d157f | 1302 | .xpath = "/frr-filter:lib/access-list", |
4470143b | 1303 | .cbs = { |
375d157f RZ |
1304 | .create = lib_access_list_create, |
1305 | .destroy = lib_access_list_destroy, | |
4470143b RZ |
1306 | } |
1307 | }, | |
1308 | { | |
375d157f | 1309 | .xpath = "/frr-filter:lib/access-list/remark", |
4470143b | 1310 | .cbs = { |
375d157f RZ |
1311 | .modify = lib_access_list_remark_modify, |
1312 | .destroy = lib_access_list_remark_destroy, | |
1313 | .cli_show = access_list_remark_show, | |
4470143b RZ |
1314 | } |
1315 | }, | |
1316 | { | |
375d157f | 1317 | .xpath = "/frr-filter:lib/access-list/entry", |
4470143b | 1318 | .cbs = { |
375d157f RZ |
1319 | .create = lib_access_list_entry_create, |
1320 | .destroy = lib_access_list_entry_destroy, | |
1321 | .cli_show = access_list_show, | |
4470143b RZ |
1322 | } |
1323 | }, | |
1324 | { | |
375d157f | 1325 | .xpath = "/frr-filter:lib/access-list/entry/action", |
4470143b | 1326 | .cbs = { |
375d157f | 1327 | .modify = lib_access_list_entry_action_modify, |
4470143b RZ |
1328 | } |
1329 | }, | |
1330 | { | |
375d157f | 1331 | .xpath = "/frr-filter:lib/access-list/entry/ipv4-prefix", |
4470143b | 1332 | .cbs = { |
375d157f RZ |
1333 | .modify = lib_access_list_entry_ipv4_prefix_modify, |
1334 | .destroy = lib_access_list_entry_ipv4_prefix_destroy, | |
4470143b RZ |
1335 | } |
1336 | }, | |
1337 | { | |
375d157f | 1338 | .xpath = "/frr-filter:lib/access-list/entry/ipv4-exact-match", |
4470143b | 1339 | .cbs = { |
375d157f RZ |
1340 | .modify = lib_access_list_entry_ipv4_exact_match_modify, |
1341 | .destroy = lib_access_list_entry_ipv4_exact_match_destroy, | |
4470143b RZ |
1342 | } |
1343 | }, | |
1344 | { | |
375d157f | 1345 | .xpath = "/frr-filter:lib/access-list/entry/host", |
4470143b | 1346 | .cbs = { |
375d157f RZ |
1347 | .modify = lib_access_list_entry_host_modify, |
1348 | .destroy = lib_access_list_entry_host_destroy, | |
4470143b RZ |
1349 | } |
1350 | }, | |
1351 | { | |
b1993be6 | 1352 | .xpath = "/frr-filter:lib/access-list/entry/network/address", |
4470143b | 1353 | .cbs = { |
b1993be6 RZ |
1354 | .modify = lib_access_list_entry_network_address_modify, |
1355 | } | |
1356 | }, | |
1357 | { | |
1358 | .xpath = "/frr-filter:lib/access-list/entry/network/mask", | |
1359 | .cbs = { | |
1360 | .modify = lib_access_list_entry_network_mask_modify, | |
4470143b RZ |
1361 | } |
1362 | }, | |
1363 | { | |
375d157f | 1364 | .xpath = "/frr-filter:lib/access-list/entry/source-any", |
4470143b | 1365 | .cbs = { |
375d157f RZ |
1366 | .create = lib_access_list_entry_source_any_create, |
1367 | .destroy = lib_access_list_entry_source_any_destroy, | |
4470143b RZ |
1368 | } |
1369 | }, | |
1370 | { | |
375d157f | 1371 | .xpath = "/frr-filter:lib/access-list/entry/destination-host", |
4470143b | 1372 | .cbs = { |
375d157f RZ |
1373 | .modify = lib_access_list_entry_destination_host_modify, |
1374 | .destroy = lib_access_list_entry_destination_host_destroy, | |
4470143b RZ |
1375 | } |
1376 | }, | |
1377 | { | |
b1993be6 RZ |
1378 | .xpath = "/frr-filter:lib/access-list/entry/destination-network/address", |
1379 | .cbs = { | |
1380 | .modify = lib_access_list_entry_destination_network_address_modify, | |
1381 | } | |
1382 | }, | |
1383 | { | |
1384 | .xpath = "/frr-filter:lib/access-list/entry/destination-network/mask", | |
4470143b | 1385 | .cbs = { |
b1993be6 | 1386 | .modify = lib_access_list_entry_destination_network_mask_modify, |
4470143b RZ |
1387 | } |
1388 | }, | |
1389 | { | |
375d157f | 1390 | .xpath = "/frr-filter:lib/access-list/entry/destination-any", |
4470143b | 1391 | .cbs = { |
375d157f RZ |
1392 | .create = lib_access_list_entry_destination_any_create, |
1393 | .destroy = lib_access_list_entry_destination_any_destroy, | |
4470143b RZ |
1394 | } |
1395 | }, | |
1396 | { | |
1397 | .xpath = "/frr-filter:lib/access-list/entry/ipv6-prefix", | |
1398 | .cbs = { | |
a247b2b7 RZ |
1399 | .modify = lib_access_list_entry_ipv4_prefix_modify, |
1400 | .destroy = lib_access_list_entry_ipv4_prefix_destroy, | |
4470143b RZ |
1401 | } |
1402 | }, | |
1403 | { | |
1404 | .xpath = "/frr-filter:lib/access-list/entry/ipv6-exact-match", | |
1405 | .cbs = { | |
a247b2b7 RZ |
1406 | .modify = lib_access_list_entry_ipv4_exact_match_modify, |
1407 | .destroy = lib_access_list_entry_ipv4_exact_match_destroy, | |
4470143b RZ |
1408 | } |
1409 | }, | |
1410 | { | |
1411 | .xpath = "/frr-filter:lib/access-list/entry/mac", | |
1412 | .cbs = { | |
a247b2b7 RZ |
1413 | .modify = lib_access_list_entry_ipv4_prefix_modify, |
1414 | .destroy = lib_access_list_entry_ipv4_prefix_destroy, | |
4470143b RZ |
1415 | } |
1416 | }, | |
1417 | { | |
1418 | .xpath = "/frr-filter:lib/access-list/entry/any", | |
1419 | .cbs = { | |
1420 | .create = lib_access_list_entry_any_create, | |
1421 | .destroy = lib_access_list_entry_any_destroy, | |
1422 | } | |
1423 | }, | |
1424 | { | |
1425 | .xpath = "/frr-filter:lib/prefix-list", | |
1426 | .cbs = { | |
1427 | .create = lib_prefix_list_create, | |
1428 | .destroy = lib_prefix_list_destroy, | |
1429 | } | |
1430 | }, | |
1431 | { | |
cc82bcc1 | 1432 | .xpath = "/frr-filter:lib/prefix-list/remark", |
4470143b | 1433 | .cbs = { |
cc82bcc1 RZ |
1434 | .modify = lib_prefix_list_remark_modify, |
1435 | .destroy = lib_prefix_list_remark_destroy, | |
1d3c4b66 | 1436 | .cli_show = prefix_list_remark_show, |
4470143b RZ |
1437 | } |
1438 | }, | |
1439 | { | |
1440 | .xpath = "/frr-filter:lib/prefix-list/entry", | |
1441 | .cbs = { | |
1442 | .create = lib_prefix_list_entry_create, | |
1443 | .destroy = lib_prefix_list_entry_destroy, | |
1d3c4b66 | 1444 | .cli_show = prefix_list_show, |
4470143b RZ |
1445 | } |
1446 | }, | |
1447 | { | |
1448 | .xpath = "/frr-filter:lib/prefix-list/entry/action", | |
1449 | .cbs = { | |
1450 | .modify = lib_prefix_list_entry_action_modify, | |
1451 | } | |
1452 | }, | |
1453 | { | |
1454 | .xpath = "/frr-filter:lib/prefix-list/entry/ipv4-prefix", | |
1455 | .cbs = { | |
1456 | .modify = lib_prefix_list_entry_ipv4_prefix_modify, | |
1457 | .destroy = lib_prefix_list_entry_ipv4_prefix_destroy, | |
1458 | } | |
1459 | }, | |
1460 | { | |
1461 | .xpath = "/frr-filter:lib/prefix-list/entry/ipv4-prefix-length-greater-or-equal", | |
1462 | .cbs = { | |
1463 | .modify = lib_prefix_list_entry_ipv4_prefix_length_greater_or_equal_modify, | |
1464 | .destroy = lib_prefix_list_entry_ipv4_prefix_length_greater_or_equal_destroy, | |
1465 | } | |
1466 | }, | |
1467 | { | |
1468 | .xpath = "/frr-filter:lib/prefix-list/entry/ipv4-prefix-length-lesser-or-equal", | |
1469 | .cbs = { | |
1470 | .modify = lib_prefix_list_entry_ipv4_prefix_length_lesser_or_equal_modify, | |
1471 | .destroy = lib_prefix_list_entry_ipv4_prefix_length_lesser_or_equal_destroy, | |
1472 | } | |
1473 | }, | |
1474 | { | |
1475 | .xpath = "/frr-filter:lib/prefix-list/entry/ipv6-prefix", | |
1476 | .cbs = { | |
a247b2b7 RZ |
1477 | .modify = lib_prefix_list_entry_ipv4_prefix_modify, |
1478 | .destroy = lib_prefix_list_entry_ipv4_prefix_destroy, | |
4470143b RZ |
1479 | } |
1480 | }, | |
1481 | { | |
1482 | .xpath = "/frr-filter:lib/prefix-list/entry/ipv6-prefix-length-greater-or-equal", | |
1483 | .cbs = { | |
a247b2b7 RZ |
1484 | .modify = lib_prefix_list_entry_ipv4_prefix_length_greater_or_equal_modify, |
1485 | .destroy = lib_prefix_list_entry_ipv4_prefix_length_greater_or_equal_destroy, | |
4470143b RZ |
1486 | } |
1487 | }, | |
1488 | { | |
1489 | .xpath = "/frr-filter:lib/prefix-list/entry/ipv6-prefix-length-lesser-or-equal", | |
1490 | .cbs = { | |
a247b2b7 RZ |
1491 | .modify = lib_prefix_list_entry_ipv4_prefix_length_lesser_or_equal_modify, |
1492 | .destroy = lib_prefix_list_entry_ipv4_prefix_length_lesser_or_equal_destroy, | |
4470143b RZ |
1493 | } |
1494 | }, | |
1495 | { | |
1496 | .xpath = "/frr-filter:lib/prefix-list/entry/any", | |
1497 | .cbs = { | |
1498 | .create = lib_prefix_list_entry_any_create, | |
1499 | .destroy = lib_prefix_list_entry_any_destroy, | |
1500 | } | |
1501 | }, | |
1502 | { | |
1503 | .xpath = NULL, | |
1504 | }, | |
1505 | } | |
1506 | }; |