]> git.proxmox.com Git - mirror_frr.git/blob - ripd/rip_northbound.c
staticd: Do not ready prefix for printing till it's decoded
[mirror_frr.git] / ripd / rip_northbound.c
1 /*
2 * Copyright (C) 1997, 1998, 1999 Kunihiro Ishiguro <kunihiro@zebra.org>
3 * Copyright (C) 2018 NetDEF, Inc.
4 * Renato Westphal
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2 of the License, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include <zebra.h>
22
23 #include "if.h"
24 #include "vrf.h"
25 #include "log.h"
26 #include "prefix.h"
27 #include "table.h"
28 #include "command.h"
29 #include "routemap.h"
30 #include "northbound.h"
31 #include "libfrr.h"
32
33 #include "ripd/ripd.h"
34 #include "ripd/rip_cli.h"
35
36 /*
37 * XPath: /frr-ripd:ripd/instance
38 */
39 static int ripd_instance_create(enum nb_event event,
40 const struct lyd_node *dnode,
41 union nb_resource *resource)
42 {
43 int socket;
44
45 switch (event) {
46 case NB_EV_VALIDATE:
47 break;
48 case NB_EV_PREPARE:
49 socket = rip_create_socket();
50 if (socket < 0)
51 return NB_ERR_RESOURCE;
52 resource->fd = socket;
53 break;
54 case NB_EV_ABORT:
55 socket = resource->fd;
56 close(socket);
57 break;
58 case NB_EV_APPLY:
59 socket = resource->fd;
60 rip_create(socket);
61 break;
62 }
63
64 return NB_OK;
65 }
66
67 static int ripd_instance_delete(enum nb_event event,
68 const struct lyd_node *dnode)
69 {
70 if (event != NB_EV_APPLY)
71 return NB_OK;
72
73 rip_clean();
74
75 return NB_OK;
76 }
77
78 /*
79 * XPath: /frr-ripd:ripd/instance/allow-ecmp
80 */
81 static int ripd_instance_allow_ecmp_modify(enum nb_event event,
82 const struct lyd_node *dnode,
83 union nb_resource *resource)
84 {
85 if (event != NB_EV_APPLY)
86 return NB_OK;
87
88 rip->ecmp = yang_dnode_get_bool(dnode, NULL);
89 if (!rip->ecmp)
90 rip_ecmp_disable();
91
92 return NB_OK;
93 }
94
95 /*
96 * XPath: /frr-ripd:ripd/instance/default-information-originate
97 */
98 static int
99 ripd_instance_default_information_originate_modify(enum nb_event event,
100 const struct lyd_node *dnode,
101 union nb_resource *resource)
102 {
103 bool default_information;
104 struct prefix_ipv4 p;
105
106 if (event != NB_EV_APPLY)
107 return NB_OK;
108
109 default_information = yang_dnode_get_bool(dnode, NULL);
110
111 memset(&p, 0, sizeof(struct prefix_ipv4));
112 p.family = AF_INET;
113 if (default_information) {
114 struct nexthop nh;
115
116 memset(&nh, 0, sizeof(nh));
117 nh.type = NEXTHOP_TYPE_IPV4;
118 rip_redistribute_add(ZEBRA_ROUTE_RIP, RIP_ROUTE_DEFAULT, &p,
119 &nh, 0, 0, 0);
120 } else {
121 rip_redistribute_delete(ZEBRA_ROUTE_RIP, RIP_ROUTE_DEFAULT, &p,
122 0);
123 }
124
125 return NB_OK;
126 }
127
128 /*
129 * XPath: /frr-ripd:ripd/instance/default-metric
130 */
131 static int ripd_instance_default_metric_modify(enum nb_event event,
132 const struct lyd_node *dnode,
133 union nb_resource *resource)
134 {
135 if (event != NB_EV_APPLY)
136 return NB_OK;
137
138 rip->default_metric = yang_dnode_get_uint8(dnode, NULL);
139 /* rip_update_default_metric (); */
140
141 return NB_OK;
142 }
143
144 /*
145 * XPath: /frr-ripd:ripd/instance/distance/default
146 */
147 static int ripd_instance_distance_default_modify(enum nb_event event,
148 const struct lyd_node *dnode,
149 union nb_resource *resource)
150 {
151 if (event != NB_EV_APPLY)
152 return NB_OK;
153
154 rip->distance = yang_dnode_get_uint8(dnode, NULL);
155
156 return NB_OK;
157 }
158
159 /*
160 * XPath: /frr-ripd:ripd/instance/distance/source
161 */
162 static int ripd_instance_distance_source_create(enum nb_event event,
163 const struct lyd_node *dnode,
164 union nb_resource *resource)
165 {
166 struct prefix_ipv4 prefix;
167 struct route_node *rn;
168
169 if (event != NB_EV_APPLY)
170 return NB_OK;
171
172 yang_dnode_get_ipv4p(&prefix, dnode, "./prefix");
173 apply_mask_ipv4(&prefix);
174
175 /* Get RIP distance node. */
176 rn = route_node_get(rip_distance_table, (struct prefix *)&prefix);
177 rn->info = rip_distance_new();
178 yang_dnode_set_entry(dnode, rn);
179
180 return NB_OK;
181 }
182
183 static int ripd_instance_distance_source_delete(enum nb_event event,
184 const struct lyd_node *dnode)
185 {
186 struct route_node *rn;
187 struct rip_distance *rdistance;
188
189 if (event != NB_EV_APPLY)
190 return NB_OK;
191
192 rn = yang_dnode_get_entry(dnode, true);
193 rdistance = rn->info;
194 if (rdistance->access_list)
195 free(rdistance->access_list);
196 rip_distance_free(rdistance);
197
198 rn->info = NULL;
199 route_unlock_node(rn);
200
201 return NB_OK;
202 }
203
204 /*
205 * XPath: /frr-ripd:ripd/instance/distance/source/distance
206 */
207 static int
208 ripd_instance_distance_source_distance_modify(enum nb_event event,
209 const struct lyd_node *dnode,
210 union nb_resource *resource)
211 {
212 struct route_node *rn;
213 uint8_t distance;
214 struct rip_distance *rdistance;
215
216 if (event != NB_EV_APPLY)
217 return NB_OK;
218
219 /* Set distance value. */
220 rn = yang_dnode_get_entry(dnode, true);
221 distance = yang_dnode_get_uint8(dnode, NULL);
222 rdistance = rn->info;
223 rdistance->distance = distance;
224
225 return NB_OK;
226 }
227
228 /*
229 * XPath: /frr-ripd:ripd/instance/distance/source/access-list
230 */
231 static int
232 ripd_instance_distance_source_access_list_modify(enum nb_event event,
233 const struct lyd_node *dnode,
234 union nb_resource *resource)
235 {
236 const char *acl_name;
237 struct route_node *rn;
238 struct rip_distance *rdistance;
239
240 if (event != NB_EV_APPLY)
241 return NB_OK;
242
243 acl_name = yang_dnode_get_string(dnode, NULL);
244
245 /* Set access-list */
246 rn = yang_dnode_get_entry(dnode, true);
247 rdistance = rn->info;
248 if (rdistance->access_list)
249 free(rdistance->access_list);
250 rdistance->access_list = strdup(acl_name);
251
252 return NB_OK;
253 }
254
255 static int
256 ripd_instance_distance_source_access_list_delete(enum nb_event event,
257 const struct lyd_node *dnode)
258 {
259 struct route_node *rn;
260 struct rip_distance *rdistance;
261
262 if (event != NB_EV_APPLY)
263 return NB_OK;
264
265 /* Reset access-list configuration. */
266 rn = yang_dnode_get_entry(dnode, true);
267 rdistance = rn->info;
268 free(rdistance->access_list);
269 rdistance->access_list = NULL;
270
271 return NB_OK;
272 }
273
274 /*
275 * XPath: /frr-ripd:ripd/instance/explicit-neighbor
276 */
277 static int ripd_instance_explicit_neighbor_create(enum nb_event event,
278 const struct lyd_node *dnode,
279 union nb_resource *resource)
280 {
281 struct prefix_ipv4 p;
282
283 if (event != NB_EV_APPLY)
284 return NB_OK;
285
286 p.family = AF_INET;
287 p.prefixlen = IPV4_MAX_BITLEN;
288 yang_dnode_get_ipv4(&p.prefix, dnode, NULL);
289
290 return rip_neighbor_add(&p);
291 }
292
293 static int ripd_instance_explicit_neighbor_delete(enum nb_event event,
294 const struct lyd_node *dnode)
295 {
296 struct prefix_ipv4 p;
297
298 if (event != NB_EV_APPLY)
299 return NB_OK;
300
301 p.family = AF_INET;
302 p.prefixlen = IPV4_MAX_BITLEN;
303 yang_dnode_get_ipv4(&p.prefix, dnode, NULL);
304
305 return rip_neighbor_delete(&p);
306 }
307
308 /*
309 * XPath: /frr-ripd:ripd/instance/network
310 */
311 static int ripd_instance_network_create(enum nb_event event,
312 const struct lyd_node *dnode,
313 union nb_resource *resource)
314 {
315 struct prefix p;
316
317 if (event != NB_EV_APPLY)
318 return NB_OK;
319
320 yang_dnode_get_ipv4p(&p, dnode, NULL);
321 apply_mask_ipv4((struct prefix_ipv4 *)&p);
322
323 return rip_enable_network_add(&p);
324 }
325
326 static int ripd_instance_network_delete(enum nb_event event,
327 const struct lyd_node *dnode)
328 {
329 struct prefix p;
330
331 if (event != NB_EV_APPLY)
332 return NB_OK;
333
334 yang_dnode_get_ipv4p(&p, dnode, NULL);
335 apply_mask_ipv4((struct prefix_ipv4 *)&p);
336
337 return rip_enable_network_delete(&p);
338 }
339
340 /*
341 * XPath: /frr-ripd:ripd/instance/interface
342 */
343 static int ripd_instance_interface_create(enum nb_event event,
344 const struct lyd_node *dnode,
345 union nb_resource *resource)
346 {
347 const char *ifname;
348
349 if (event != NB_EV_APPLY)
350 return NB_OK;
351
352 ifname = yang_dnode_get_string(dnode, NULL);
353
354 return rip_enable_if_add(ifname);
355 }
356
357 static int ripd_instance_interface_delete(enum nb_event event,
358 const struct lyd_node *dnode)
359 {
360 const char *ifname;
361
362 if (event != NB_EV_APPLY)
363 return NB_OK;
364
365 ifname = yang_dnode_get_string(dnode, NULL);
366
367 return rip_enable_if_delete(ifname);
368 }
369
370 /*
371 * XPath: /frr-ripd:ripd/instance/offset-list
372 */
373 static int ripd_instance_offset_list_create(enum nb_event event,
374 const struct lyd_node *dnode,
375 union nb_resource *resource)
376 {
377 const char *ifname;
378 struct rip_offset_list *offset;
379
380 if (event != NB_EV_APPLY)
381 return NB_OK;
382
383 ifname = yang_dnode_get_string(dnode, "./interface");
384
385 offset = rip_offset_list_new(ifname);
386 yang_dnode_set_entry(dnode, offset);
387
388 return NB_OK;
389 }
390
391 static int ripd_instance_offset_list_delete(enum nb_event event,
392 const struct lyd_node *dnode)
393 {
394 int direct;
395 struct rip_offset_list *offset;
396
397 if (event != NB_EV_APPLY)
398 return NB_OK;
399
400 direct = yang_dnode_get_enum(dnode, "./direction");
401
402 offset = yang_dnode_get_entry(dnode, true);
403 if (offset->direct[direct].alist_name) {
404 free(offset->direct[direct].alist_name);
405 offset->direct[direct].alist_name = NULL;
406 }
407 if (offset->direct[RIP_OFFSET_LIST_IN].alist_name == NULL
408 && offset->direct[RIP_OFFSET_LIST_OUT].alist_name == NULL)
409 offset_list_del(offset);
410
411 return NB_OK;
412 }
413
414 /*
415 * XPath: /frr-ripd:ripd/instance/offset-list/access-list
416 */
417 static int
418 ripd_instance_offset_list_access_list_modify(enum nb_event event,
419 const struct lyd_node *dnode,
420 union nb_resource *resource)
421 {
422 int direct;
423 struct rip_offset_list *offset;
424 const char *alist_name;
425
426 if (event != NB_EV_APPLY)
427 return NB_OK;
428
429 direct = yang_dnode_get_enum(dnode, "../direction");
430 alist_name = yang_dnode_get_string(dnode, NULL);
431
432 offset = yang_dnode_get_entry(dnode, true);
433 if (offset->direct[direct].alist_name)
434 free(offset->direct[direct].alist_name);
435 offset->direct[direct].alist_name = strdup(alist_name);
436
437 return NB_OK;
438 }
439
440 /*
441 * XPath: /frr-ripd:ripd/instance/offset-list/metric
442 */
443 static int ripd_instance_offset_list_metric_modify(enum nb_event event,
444 const struct lyd_node *dnode,
445 union nb_resource *resource)
446 {
447 int direct;
448 uint8_t metric;
449 struct rip_offset_list *offset;
450
451 if (event != NB_EV_APPLY)
452 return NB_OK;
453
454 direct = yang_dnode_get_enum(dnode, "../direction");
455 metric = yang_dnode_get_uint8(dnode, NULL);
456
457 offset = yang_dnode_get_entry(dnode, true);
458 offset->direct[direct].metric = metric;
459
460 return NB_OK;
461 }
462
463 /*
464 * XPath: /frr-ripd:ripd/instance/passive-default
465 */
466 static int ripd_instance_passive_default_modify(enum nb_event event,
467 const struct lyd_node *dnode,
468 union nb_resource *resource)
469 {
470 if (event != NB_EV_APPLY)
471 return NB_OK;
472
473 rip->passive_default = yang_dnode_get_bool(dnode, NULL);
474 rip_passive_nondefault_clean();
475
476 return NB_OK;
477 }
478
479 /*
480 * XPath: /frr-ripd:ripd/instance/passive-interface
481 */
482 static int ripd_instance_passive_interface_create(enum nb_event event,
483 const struct lyd_node *dnode,
484 union nb_resource *resource)
485 {
486 const char *ifname;
487
488 if (event != NB_EV_APPLY)
489 return NB_OK;
490
491 ifname = yang_dnode_get_string(dnode, NULL);
492
493 return rip_passive_nondefault_set(ifname);
494 }
495
496 static int ripd_instance_passive_interface_delete(enum nb_event event,
497 const struct lyd_node *dnode)
498 {
499 const char *ifname;
500
501 if (event != NB_EV_APPLY)
502 return NB_OK;
503
504 ifname = yang_dnode_get_string(dnode, NULL);
505
506 return rip_passive_nondefault_unset(ifname);
507 }
508
509 /*
510 * XPath: /frr-ripd:ripd/instance/non-passive-interface
511 */
512 static int
513 ripd_instance_non_passive_interface_create(enum nb_event event,
514 const struct lyd_node *dnode,
515 union nb_resource *resource)
516 {
517 const char *ifname;
518
519 if (event != NB_EV_APPLY)
520 return NB_OK;
521
522 ifname = yang_dnode_get_string(dnode, NULL);
523
524 return rip_passive_nondefault_unset(ifname);
525 }
526
527 static int
528 ripd_instance_non_passive_interface_delete(enum nb_event event,
529 const struct lyd_node *dnode)
530 {
531 const char *ifname;
532
533 if (event != NB_EV_APPLY)
534 return NB_OK;
535
536 ifname = yang_dnode_get_string(dnode, NULL);
537
538 return rip_passive_nondefault_set(ifname);
539 }
540
541 /*
542 * XPath: /frr-ripd:ripd/instance/redistribute
543 */
544 static int ripd_instance_redistribute_create(enum nb_event event,
545 const struct lyd_node *dnode,
546 union nb_resource *resource)
547 {
548 return NB_OK;
549 }
550
551 static int ripd_instance_redistribute_delete(enum nb_event event,
552 const struct lyd_node *dnode)
553 {
554 int type;
555
556 if (event != NB_EV_APPLY)
557 return NB_OK;
558
559 type = yang_dnode_get_enum(dnode, "./protocol");
560
561 rip_redistribute_conf_delete(type);
562
563 return NB_OK;
564 }
565
566 static void
567 ripd_instance_redistribute_apply_finish(const struct lyd_node *dnode)
568 {
569 int type;
570
571 type = yang_dnode_get_enum(dnode, "./protocol");
572 rip_redistribute_conf_update(type);
573 }
574
575 /*
576 * XPath: /frr-ripd:ripd/instance/redistribute/route-map
577 */
578 static int
579 ripd_instance_redistribute_route_map_modify(enum nb_event event,
580 const struct lyd_node *dnode,
581 union nb_resource *resource)
582 {
583 int type;
584 const char *rmap_name;
585
586 if (event != NB_EV_APPLY)
587 return NB_OK;
588
589 type = yang_dnode_get_enum(dnode, "../protocol");
590 rmap_name = yang_dnode_get_string(dnode, NULL);
591
592 if (rip->route_map[type].name)
593 free(rip->route_map[type].name);
594 rip->route_map[type].name = strdup(rmap_name);
595 rip->route_map[type].map = route_map_lookup_by_name(rmap_name);
596
597 return NB_OK;
598 }
599
600 static int
601 ripd_instance_redistribute_route_map_delete(enum nb_event event,
602 const struct lyd_node *dnode)
603 {
604 int type;
605
606 if (event != NB_EV_APPLY)
607 return NB_OK;
608
609 type = yang_dnode_get_enum(dnode, "../protocol");
610
611 free(rip->route_map[type].name);
612 rip->route_map[type].name = NULL;
613 rip->route_map[type].map = NULL;
614
615 return NB_OK;
616 }
617
618 /*
619 * XPath: /frr-ripd:ripd/instance/redistribute/metric
620 */
621 static int
622 ripd_instance_redistribute_metric_modify(enum nb_event event,
623 const struct lyd_node *dnode,
624 union nb_resource *resource)
625 {
626 int type;
627 uint8_t metric;
628
629 if (event != NB_EV_APPLY)
630 return NB_OK;
631
632 type = yang_dnode_get_enum(dnode, "../protocol");
633 metric = yang_dnode_get_uint8(dnode, NULL);
634
635 rip->route_map[type].metric_config = true;
636 rip->route_map[type].metric = metric;
637
638 return NB_OK;
639 }
640
641 static int
642 ripd_instance_redistribute_metric_delete(enum nb_event event,
643 const struct lyd_node *dnode)
644 {
645 int type;
646
647 if (event != NB_EV_APPLY)
648 return NB_OK;
649
650 type = yang_dnode_get_enum(dnode, "../protocol");
651
652 rip->route_map[type].metric_config = false;
653 rip->route_map[type].metric = 0;
654
655 return NB_OK;
656 }
657
658 /*
659 * XPath: /frr-ripd:ripd/instance/static-route
660 */
661 static int ripd_instance_static_route_create(enum nb_event event,
662 const struct lyd_node *dnode,
663 union nb_resource *resource)
664 {
665 struct nexthop nh;
666 struct prefix_ipv4 p;
667
668 if (event != NB_EV_APPLY)
669 return NB_OK;
670
671 yang_dnode_get_ipv4p(&p, dnode, NULL);
672 apply_mask_ipv4(&p);
673
674 memset(&nh, 0, sizeof(nh));
675 nh.type = NEXTHOP_TYPE_IPV4;
676 rip_redistribute_add(ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, &nh, 0, 0,
677 0);
678
679 return NB_OK;
680 }
681
682 static int ripd_instance_static_route_delete(enum nb_event event,
683 const struct lyd_node *dnode)
684 {
685 struct prefix_ipv4 p;
686
687 if (event != NB_EV_APPLY)
688 return NB_OK;
689
690 yang_dnode_get_ipv4p(&p, dnode, NULL);
691 apply_mask_ipv4(&p);
692
693 rip_redistribute_delete(ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0);
694
695 return NB_OK;
696 }
697
698 /*
699 * XPath: /frr-ripd:ripd/instance/timers/
700 */
701 static void ripd_instance_timers_apply_finish(const struct lyd_node *dnode)
702 {
703 /* Reset update timer thread. */
704 rip_event(RIP_UPDATE_EVENT, 0);
705 }
706
707 /*
708 * XPath: /frr-ripd:ripd/instance/timers/flush-interval
709 */
710 static int
711 ripd_instance_timers_flush_interval_modify(enum nb_event event,
712 const struct lyd_node *dnode,
713 union nb_resource *resource)
714 {
715 if (event != NB_EV_APPLY)
716 return NB_OK;
717
718 rip->garbage_time = yang_dnode_get_uint32(dnode, NULL);
719
720 return NB_OK;
721 }
722
723 /*
724 * XPath: /frr-ripd:ripd/instance/timers/holddown-interval
725 */
726 static int
727 ripd_instance_timers_holddown_interval_modify(enum nb_event event,
728 const struct lyd_node *dnode,
729 union nb_resource *resource)
730 {
731 if (event != NB_EV_APPLY)
732 return NB_OK;
733
734 rip->timeout_time = yang_dnode_get_uint32(dnode, NULL);
735
736 return NB_OK;
737 }
738
739 /*
740 * XPath: /frr-ripd:ripd/instance/timers/update-interval
741 */
742 static int
743 ripd_instance_timers_update_interval_modify(enum nb_event event,
744 const struct lyd_node *dnode,
745 union nb_resource *resource)
746 {
747 if (event != NB_EV_APPLY)
748 return NB_OK;
749
750 rip->update_time = yang_dnode_get_uint32(dnode, NULL);
751
752 return NB_OK;
753 }
754
755 /*
756 * XPath: /frr-ripd:ripd/instance/version/receive
757 */
758 static int ripd_instance_version_receive_modify(enum nb_event event,
759 const struct lyd_node *dnode,
760 union nb_resource *resource)
761 {
762 if (event != NB_EV_APPLY)
763 return NB_OK;
764
765 rip->version_recv = yang_dnode_get_enum(dnode, NULL);
766
767 return NB_OK;
768 }
769
770 /*
771 * XPath: /frr-ripd:ripd/instance/version/send
772 */
773 static int ripd_instance_version_send_modify(enum nb_event event,
774 const struct lyd_node *dnode,
775 union nb_resource *resource)
776 {
777 if (event != NB_EV_APPLY)
778 return NB_OK;
779
780 rip->version_send = yang_dnode_get_enum(dnode, NULL);
781
782 return NB_OK;
783 }
784
785 /*
786 * XPath: /frr-interface:lib/interface/frr-ripd:rip/split-horizon
787 */
788 static int lib_interface_rip_split_horizon_modify(enum nb_event event,
789 const struct lyd_node *dnode,
790 union nb_resource *resource)
791 {
792 struct interface *ifp;
793 struct rip_interface *ri;
794
795 if (event != NB_EV_APPLY)
796 return NB_OK;
797
798 ifp = yang_dnode_get_entry(dnode, true);
799 ri = ifp->info;
800 ri->split_horizon = yang_dnode_get_enum(dnode, NULL);
801
802 return NB_OK;
803 }
804
805 /*
806 * XPath: /frr-interface:lib/interface/frr-ripd:rip/v2-broadcast
807 */
808 static int lib_interface_rip_v2_broadcast_modify(enum nb_event event,
809 const struct lyd_node *dnode,
810 union nb_resource *resource)
811 {
812 struct interface *ifp;
813 struct rip_interface *ri;
814
815 if (event != NB_EV_APPLY)
816 return NB_OK;
817
818 ifp = yang_dnode_get_entry(dnode, true);
819 ri = ifp->info;
820 ri->v2_broadcast = yang_dnode_get_bool(dnode, NULL);
821
822 return NB_OK;
823 }
824
825 /*
826 * XPath: /frr-interface:lib/interface/frr-ripd:rip/version-receive
827 */
828 static int
829 lib_interface_rip_version_receive_modify(enum nb_event event,
830 const struct lyd_node *dnode,
831 union nb_resource *resource)
832 {
833 struct interface *ifp;
834 struct rip_interface *ri;
835
836 if (event != NB_EV_APPLY)
837 return NB_OK;
838
839 ifp = yang_dnode_get_entry(dnode, true);
840 ri = ifp->info;
841 ri->ri_receive = yang_dnode_get_enum(dnode, NULL);
842
843 return NB_OK;
844 }
845
846 /*
847 * XPath: /frr-interface:lib/interface/frr-ripd:rip/version-send
848 */
849 static int lib_interface_rip_version_send_modify(enum nb_event event,
850 const struct lyd_node *dnode,
851 union nb_resource *resource)
852 {
853 struct interface *ifp;
854 struct rip_interface *ri;
855
856 if (event != NB_EV_APPLY)
857 return NB_OK;
858
859 ifp = yang_dnode_get_entry(dnode, true);
860 ri = ifp->info;
861 ri->ri_send = yang_dnode_get_enum(dnode, NULL);
862
863 return NB_OK;
864 }
865
866 /*
867 * XPath: /frr-interface:lib/interface/frr-ripd:rip/authentication-scheme/mode
868 */
869 static int lib_interface_rip_authentication_scheme_mode_modify(
870 enum nb_event event, const struct lyd_node *dnode,
871 union nb_resource *resource)
872 {
873 struct interface *ifp;
874 struct rip_interface *ri;
875
876 if (event != NB_EV_APPLY)
877 return NB_OK;
878
879 ifp = yang_dnode_get_entry(dnode, true);
880 ri = ifp->info;
881 ri->auth_type = yang_dnode_get_enum(dnode, NULL);
882
883 return NB_OK;
884 }
885
886 /*
887 * XPath:
888 * /frr-interface:lib/interface/frr-ripd:rip/authentication-scheme/md5-auth-length
889 */
890 static int lib_interface_rip_authentication_scheme_md5_auth_length_modify(
891 enum nb_event event, const struct lyd_node *dnode,
892 union nb_resource *resource)
893 {
894 struct interface *ifp;
895 struct rip_interface *ri;
896
897 if (event != NB_EV_APPLY)
898 return NB_OK;
899
900 ifp = yang_dnode_get_entry(dnode, true);
901 ri = ifp->info;
902 ri->md5_auth_len = yang_dnode_get_enum(dnode, NULL);
903
904 return NB_OK;
905 }
906
907 static int lib_interface_rip_authentication_scheme_md5_auth_length_delete(
908 enum nb_event event, const struct lyd_node *dnode)
909 {
910 struct interface *ifp;
911 struct rip_interface *ri;
912
913 if (event != NB_EV_APPLY)
914 return NB_OK;
915
916 ifp = yang_dnode_get_entry(dnode, true);
917 ri = ifp->info;
918 ri->md5_auth_len = yang_get_default_enum(
919 "%s/authentication-scheme/md5-auth-length", RIP_IFACE);
920
921 return NB_OK;
922 }
923
924 /*
925 * XPath: /frr-interface:lib/interface/frr-ripd:rip/authentication-password
926 */
927 static int
928 lib_interface_rip_authentication_password_modify(enum nb_event event,
929 const struct lyd_node *dnode,
930 union nb_resource *resource)
931 {
932 struct interface *ifp;
933 struct rip_interface *ri;
934
935 if (event != NB_EV_APPLY)
936 return NB_OK;
937
938 ifp = yang_dnode_get_entry(dnode, true);
939 ri = ifp->info;
940 if (ri->auth_str)
941 XFREE(MTYPE_RIP_INTERFACE_STRING, ri->auth_str);
942 ri->auth_str = XSTRDUP(MTYPE_RIP_INTERFACE_STRING,
943 yang_dnode_get_string(dnode, NULL));
944
945 return NB_OK;
946 }
947
948 static int
949 lib_interface_rip_authentication_password_delete(enum nb_event event,
950 const struct lyd_node *dnode)
951 {
952 struct interface *ifp;
953 struct rip_interface *ri;
954
955 if (event != NB_EV_APPLY)
956 return NB_OK;
957
958 ifp = yang_dnode_get_entry(dnode, true);
959 ri = ifp->info;
960 XFREE(MTYPE_RIP_INTERFACE_STRING, ri->auth_str);
961
962 return NB_OK;
963 }
964
965 /*
966 * XPath: /frr-interface:lib/interface/frr-ripd:rip/authentication-key-chain
967 */
968 static int
969 lib_interface_rip_authentication_key_chain_modify(enum nb_event event,
970 const struct lyd_node *dnode,
971 union nb_resource *resource)
972 {
973 struct interface *ifp;
974 struct rip_interface *ri;
975
976 if (event != NB_EV_APPLY)
977 return NB_OK;
978
979 ifp = yang_dnode_get_entry(dnode, true);
980 ri = ifp->info;
981 if (ri->key_chain)
982 XFREE(MTYPE_RIP_INTERFACE_STRING, ri->key_chain);
983 ri->key_chain = XSTRDUP(MTYPE_RIP_INTERFACE_STRING,
984 yang_dnode_get_string(dnode, NULL));
985
986 return NB_OK;
987 }
988
989 static int
990 lib_interface_rip_authentication_key_chain_delete(enum nb_event event,
991 const struct lyd_node *dnode)
992 {
993 struct interface *ifp;
994 struct rip_interface *ri;
995
996 if (event != NB_EV_APPLY)
997 return NB_OK;
998
999 ifp = yang_dnode_get_entry(dnode, true);
1000 ri = ifp->info;
1001 XFREE(MTYPE_RIP_INTERFACE_STRING, ri->key_chain);
1002
1003 return NB_OK;
1004 }
1005
1006 /*
1007 * XPath: /frr-ripd:ripd/state/neighbors/neighbor
1008 */
1009 static const void *
1010 ripd_state_neighbors_neighbor_get_next(const void *parent_list_entry,
1011 const void *list_entry)
1012 {
1013 struct listnode *node;
1014
1015 if (list_entry == NULL)
1016 node = listhead(peer_list);
1017 else
1018 node = listnextnode((struct listnode *)list_entry);
1019
1020 return node;
1021 }
1022
1023 static int ripd_state_neighbors_neighbor_get_keys(const void *list_entry,
1024 struct yang_list_keys *keys)
1025 {
1026 const struct listnode *node = list_entry;
1027 const struct rip_peer *peer = listgetdata(node);
1028
1029 keys->num = 1;
1030 (void)inet_ntop(AF_INET, &peer->addr, keys->key[0],
1031 sizeof(keys->key[0]));
1032
1033 return NB_OK;
1034 }
1035
1036 static const void *
1037 ripd_state_neighbors_neighbor_lookup_entry(const void *parent_list_entry,
1038 const struct yang_list_keys *keys)
1039 {
1040 struct in_addr address;
1041 struct rip_peer *peer;
1042 struct listnode *node;
1043
1044 yang_str2ipv4(keys->key[0], &address);
1045
1046 for (ALL_LIST_ELEMENTS_RO(peer_list, node, peer)) {
1047 if (IPV4_ADDR_SAME(&peer->addr, &address))
1048 return node;
1049 }
1050
1051 return NULL;
1052 }
1053
1054 /*
1055 * XPath: /frr-ripd:ripd/state/neighbors/neighbor/address
1056 */
1057 static struct yang_data *
1058 ripd_state_neighbors_neighbor_address_get_elem(const char *xpath,
1059 const void *list_entry)
1060 {
1061 const struct listnode *node = list_entry;
1062 const struct rip_peer *peer = listgetdata(node);
1063
1064 return yang_data_new_ipv4(xpath, &peer->addr);
1065 }
1066
1067 /*
1068 * XPath: /frr-ripd:ripd/state/neighbors/neighbor/last-update
1069 */
1070 static struct yang_data *
1071 ripd_state_neighbors_neighbor_last_update_get_elem(const char *xpath,
1072 const void *list_entry)
1073 {
1074 /* TODO: yang:date-and-time is tricky */
1075 return NULL;
1076 }
1077
1078 /*
1079 * XPath: /frr-ripd:ripd/state/neighbors/neighbor/bad-packets-rcvd
1080 */
1081 static struct yang_data *
1082 ripd_state_neighbors_neighbor_bad_packets_rcvd_get_elem(const char *xpath,
1083 const void *list_entry)
1084 {
1085 const struct listnode *node = list_entry;
1086 const struct rip_peer *peer = listgetdata(node);
1087
1088 return yang_data_new_uint32(xpath, peer->recv_badpackets);
1089 }
1090
1091 /*
1092 * XPath: /frr-ripd:ripd/state/neighbors/neighbor/bad-routes-rcvd
1093 */
1094 static struct yang_data *
1095 ripd_state_neighbors_neighbor_bad_routes_rcvd_get_elem(const char *xpath,
1096 const void *list_entry)
1097 {
1098 const struct listnode *node = list_entry;
1099 const struct rip_peer *peer = listgetdata(node);
1100
1101 return yang_data_new_uint32(xpath, peer->recv_badroutes);
1102 }
1103
1104 /*
1105 * XPath: /frr-ripd:ripd/state/routes/route
1106 */
1107 static const void *
1108 ripd_state_routes_route_get_next(const void *parent_list_entry,
1109 const void *list_entry)
1110 {
1111 struct route_node *rn;
1112
1113 if (rip == NULL)
1114 return NULL;
1115
1116 if (list_entry == NULL)
1117 rn = route_top(rip->table);
1118 else
1119 rn = route_next((struct route_node *)list_entry);
1120 while (rn && rn->info == NULL)
1121 rn = route_next(rn);
1122
1123 return rn;
1124 }
1125
1126 static int ripd_state_routes_route_get_keys(const void *list_entry,
1127 struct yang_list_keys *keys)
1128 {
1129 const struct route_node *rn = list_entry;
1130
1131 keys->num = 1;
1132 (void)prefix2str(&rn->p, keys->key[0], sizeof(keys->key[0]));
1133
1134 return NB_OK;
1135 }
1136
1137 static const void *
1138 ripd_state_routes_route_lookup_entry(const void *parent_list_entry,
1139 const struct yang_list_keys *keys)
1140 {
1141 struct prefix prefix;
1142 struct route_node *rn;
1143
1144 yang_str2ipv4p(keys->key[0], &prefix);
1145
1146 rn = route_node_lookup(rip->table, &prefix);
1147 if (!rn || !rn->info)
1148 return NULL;
1149
1150 route_unlock_node(rn);
1151
1152 return rn;
1153 }
1154
1155 /*
1156 * XPath: /frr-ripd:ripd/state/routes/route/prefix
1157 */
1158 static struct yang_data *
1159 ripd_state_routes_route_prefix_get_elem(const char *xpath,
1160 const void *list_entry)
1161 {
1162 const struct route_node *rn = list_entry;
1163 const struct rip_info *rinfo = listnode_head(rn->info);
1164
1165 return yang_data_new_ipv4p(xpath, &rinfo->rp->p);
1166 }
1167
1168 /*
1169 * XPath: /frr-ripd:ripd/state/routes/route/next-hop
1170 */
1171 static struct yang_data *
1172 ripd_state_routes_route_next_hop_get_elem(const char *xpath,
1173 const void *list_entry)
1174 {
1175 const struct route_node *rn = list_entry;
1176 const struct rip_info *rinfo = listnode_head(rn->info);
1177
1178 switch (rinfo->nh.type) {
1179 case NEXTHOP_TYPE_IPV4:
1180 case NEXTHOP_TYPE_IPV4_IFINDEX:
1181 return yang_data_new_ipv4(xpath, &rinfo->nh.gate.ipv4);
1182 default:
1183 return NULL;
1184 }
1185 }
1186
1187 /*
1188 * XPath: /frr-ripd:ripd/state/routes/route/interface
1189 */
1190 static struct yang_data *
1191 ripd_state_routes_route_interface_get_elem(const char *xpath,
1192 const void *list_entry)
1193 {
1194 const struct route_node *rn = list_entry;
1195 const struct rip_info *rinfo = listnode_head(rn->info);
1196
1197 switch (rinfo->nh.type) {
1198 case NEXTHOP_TYPE_IFINDEX:
1199 case NEXTHOP_TYPE_IPV4_IFINDEX:
1200 return yang_data_new_string(
1201 xpath, ifindex2ifname(rinfo->nh.ifindex, VRF_DEFAULT));
1202 default:
1203 return NULL;
1204 }
1205 }
1206
1207 /*
1208 * XPath: /frr-ripd:ripd/state/routes/route/metric
1209 */
1210 static struct yang_data *
1211 ripd_state_routes_route_metric_get_elem(const char *xpath,
1212 const void *list_entry)
1213 {
1214 const struct route_node *rn = list_entry;
1215 const struct rip_info *rinfo = listnode_head(rn->info);
1216
1217 return yang_data_new_uint8(xpath, rinfo->metric);
1218 }
1219
1220 /*
1221 * XPath: /frr-ripd:clear-rip-route
1222 */
1223 static int clear_rip_route_rpc(const char *xpath, const struct list *input,
1224 struct list *output)
1225 {
1226 struct route_node *rp;
1227 struct rip_info *rinfo;
1228 struct list *list;
1229 struct listnode *listnode;
1230
1231 /* Clear received RIP routes */
1232 for (rp = route_top(rip->table); rp; rp = route_next(rp)) {
1233 list = rp->info;
1234 if (!list)
1235 continue;
1236
1237 for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) {
1238 if (!rip_route_rte(rinfo))
1239 continue;
1240
1241 if (CHECK_FLAG(rinfo->flags, RIP_RTF_FIB))
1242 rip_zebra_ipv4_delete(rp);
1243 break;
1244 }
1245
1246 if (rinfo) {
1247 RIP_TIMER_OFF(rinfo->t_timeout);
1248 RIP_TIMER_OFF(rinfo->t_garbage_collect);
1249 listnode_delete(list, rinfo);
1250 rip_info_free(rinfo);
1251 }
1252
1253 if (list_isempty(list)) {
1254 list_delete(&list);
1255 rp->info = NULL;
1256 route_unlock_node(rp);
1257 }
1258 }
1259
1260 return NB_OK;
1261 }
1262
1263 /*
1264 * XPath: /frr-ripd:authentication-type-failure
1265 */
1266 void ripd_notif_send_auth_type_failure(const char *ifname)
1267 {
1268 const char *xpath = "/frr-ripd:authentication-type-failure";
1269 struct list *arguments;
1270 char xpath_arg[XPATH_MAXLEN];
1271 struct yang_data *data;
1272
1273 arguments = yang_data_list_new();
1274
1275 snprintf(xpath_arg, sizeof(xpath_arg), "%s/interface-name", xpath);
1276 data = yang_data_new_string(xpath_arg, ifname);
1277 listnode_add(arguments, data);
1278
1279 nb_notification_send(xpath, arguments);
1280 }
1281
1282 /*
1283 * XPath: /frr-ripd:authentication-failure
1284 */
1285 void ripd_notif_send_auth_failure(const char *ifname)
1286 {
1287 const char *xpath = "/frr-ripd:authentication-failure";
1288 struct list *arguments;
1289 char xpath_arg[XPATH_MAXLEN];
1290 struct yang_data *data;
1291
1292 arguments = yang_data_list_new();
1293
1294 snprintf(xpath_arg, sizeof(xpath_arg), "%s/interface-name", xpath);
1295 data = yang_data_new_string(xpath_arg, ifname);
1296 listnode_add(arguments, data);
1297
1298 nb_notification_send(xpath, arguments);
1299 }
1300
1301 /* clang-format off */
1302 const struct frr_yang_module_info frr_ripd_info = {
1303 .name = "frr-ripd",
1304 .nodes = {
1305 {
1306 .xpath = "/frr-ripd:ripd/instance",
1307 .cbs.create = ripd_instance_create,
1308 .cbs.delete = ripd_instance_delete,
1309 .cbs.cli_show = cli_show_router_rip,
1310 },
1311 {
1312 .xpath = "/frr-ripd:ripd/instance/allow-ecmp",
1313 .cbs.modify = ripd_instance_allow_ecmp_modify,
1314 .cbs.cli_show = cli_show_rip_allow_ecmp,
1315 },
1316 {
1317 .xpath = "/frr-ripd:ripd/instance/default-information-originate",
1318 .cbs.modify = ripd_instance_default_information_originate_modify,
1319 .cbs.cli_show = cli_show_rip_default_information_originate,
1320 },
1321 {
1322 .xpath = "/frr-ripd:ripd/instance/default-metric",
1323 .cbs.modify = ripd_instance_default_metric_modify,
1324 .cbs.cli_show = cli_show_rip_default_metric,
1325 },
1326 {
1327 .xpath = "/frr-ripd:ripd/instance/distance/default",
1328 .cbs.modify = ripd_instance_distance_default_modify,
1329 .cbs.cli_show = cli_show_rip_distance,
1330 },
1331 {
1332 .xpath = "/frr-ripd:ripd/instance/distance/source",
1333 .cbs.create = ripd_instance_distance_source_create,
1334 .cbs.delete = ripd_instance_distance_source_delete,
1335 .cbs.cli_show = cli_show_rip_distance_source,
1336 },
1337 {
1338 .xpath = "/frr-ripd:ripd/instance/distance/source/distance",
1339 .cbs.modify = ripd_instance_distance_source_distance_modify,
1340 },
1341 {
1342 .xpath = "/frr-ripd:ripd/instance/distance/source/access-list",
1343 .cbs.modify = ripd_instance_distance_source_access_list_modify,
1344 .cbs.delete = ripd_instance_distance_source_access_list_delete,
1345 },
1346 {
1347 .xpath = "/frr-ripd:ripd/instance/explicit-neighbor",
1348 .cbs.create = ripd_instance_explicit_neighbor_create,
1349 .cbs.delete = ripd_instance_explicit_neighbor_delete,
1350 .cbs.cli_show = cli_show_rip_neighbor,
1351 },
1352 {
1353 .xpath = "/frr-ripd:ripd/instance/network",
1354 .cbs.create = ripd_instance_network_create,
1355 .cbs.delete = ripd_instance_network_delete,
1356 .cbs.cli_show = cli_show_rip_network_prefix,
1357 },
1358 {
1359 .xpath = "/frr-ripd:ripd/instance/interface",
1360 .cbs.create = ripd_instance_interface_create,
1361 .cbs.delete = ripd_instance_interface_delete,
1362 .cbs.cli_show = cli_show_rip_network_interface,
1363 },
1364 {
1365 .xpath = "/frr-ripd:ripd/instance/offset-list",
1366 .cbs.create = ripd_instance_offset_list_create,
1367 .cbs.delete = ripd_instance_offset_list_delete,
1368 .cbs.cli_show = cli_show_rip_offset_list,
1369 },
1370 {
1371 .xpath = "/frr-ripd:ripd/instance/offset-list/access-list",
1372 .cbs.modify = ripd_instance_offset_list_access_list_modify,
1373 },
1374 {
1375 .xpath = "/frr-ripd:ripd/instance/offset-list/metric",
1376 .cbs.modify = ripd_instance_offset_list_metric_modify,
1377 },
1378 {
1379 .xpath = "/frr-ripd:ripd/instance/passive-default",
1380 .cbs.modify = ripd_instance_passive_default_modify,
1381 .cbs.cli_show = cli_show_rip_passive_default,
1382 },
1383 {
1384 .xpath = "/frr-ripd:ripd/instance/passive-interface",
1385 .cbs.create = ripd_instance_passive_interface_create,
1386 .cbs.delete = ripd_instance_passive_interface_delete,
1387 .cbs.cli_show = cli_show_rip_passive_interface,
1388 },
1389 {
1390 .xpath = "/frr-ripd:ripd/instance/non-passive-interface",
1391 .cbs.create = ripd_instance_non_passive_interface_create,
1392 .cbs.delete = ripd_instance_non_passive_interface_delete,
1393 .cbs.cli_show = cli_show_rip_non_passive_interface,
1394 },
1395 {
1396 .xpath = "/frr-ripd:ripd/instance/redistribute",
1397 .cbs.create = ripd_instance_redistribute_create,
1398 .cbs.delete = ripd_instance_redistribute_delete,
1399 .cbs.apply_finish = ripd_instance_redistribute_apply_finish,
1400 .cbs.cli_show = cli_show_rip_redistribute,
1401 },
1402 {
1403 .xpath = "/frr-ripd:ripd/instance/redistribute/route-map",
1404 .cbs.modify = ripd_instance_redistribute_route_map_modify,
1405 .cbs.delete = ripd_instance_redistribute_route_map_delete,
1406 },
1407 {
1408 .xpath = "/frr-ripd:ripd/instance/redistribute/metric",
1409 .cbs.modify = ripd_instance_redistribute_metric_modify,
1410 .cbs.delete = ripd_instance_redistribute_metric_delete,
1411 },
1412 {
1413 .xpath = "/frr-ripd:ripd/instance/static-route",
1414 .cbs.create = ripd_instance_static_route_create,
1415 .cbs.delete = ripd_instance_static_route_delete,
1416 .cbs.cli_show = cli_show_rip_route,
1417 },
1418 {
1419 .xpath = "/frr-ripd:ripd/instance/timers",
1420 .cbs.apply_finish = ripd_instance_timers_apply_finish,
1421 .cbs.cli_show = cli_show_rip_timers,
1422 },
1423 {
1424 .xpath = "/frr-ripd:ripd/instance/timers/flush-interval",
1425 .cbs.modify = ripd_instance_timers_flush_interval_modify,
1426 },
1427 {
1428 .xpath = "/frr-ripd:ripd/instance/timers/holddown-interval",
1429 .cbs.modify = ripd_instance_timers_holddown_interval_modify,
1430 },
1431 {
1432 .xpath = "/frr-ripd:ripd/instance/timers/update-interval",
1433 .cbs.modify = ripd_instance_timers_update_interval_modify,
1434 },
1435 {
1436 .xpath = "/frr-ripd:ripd/instance/version",
1437 .cbs.cli_show = cli_show_rip_version,
1438 },
1439 {
1440 .xpath = "/frr-ripd:ripd/instance/version/receive",
1441 .cbs.modify = ripd_instance_version_receive_modify,
1442 },
1443 {
1444 .xpath = "/frr-ripd:ripd/instance/version/send",
1445 .cbs.modify = ripd_instance_version_send_modify,
1446 },
1447 {
1448 .xpath = "/frr-interface:lib/interface/frr-ripd:rip/split-horizon",
1449 .cbs.modify = lib_interface_rip_split_horizon_modify,
1450 .cbs.cli_show = cli_show_ip_rip_split_horizon,
1451 },
1452 {
1453 .xpath = "/frr-interface:lib/interface/frr-ripd:rip/v2-broadcast",
1454 .cbs.modify = lib_interface_rip_v2_broadcast_modify,
1455 .cbs.cli_show = cli_show_ip_rip_v2_broadcast,
1456 },
1457 {
1458 .xpath = "/frr-interface:lib/interface/frr-ripd:rip/version-receive",
1459 .cbs.modify = lib_interface_rip_version_receive_modify,
1460 .cbs.cli_show = cli_show_ip_rip_receive_version,
1461 },
1462 {
1463 .xpath = "/frr-interface:lib/interface/frr-ripd:rip/version-send",
1464 .cbs.modify = lib_interface_rip_version_send_modify,
1465 .cbs.cli_show = cli_show_ip_rip_send_version,
1466 },
1467 {
1468 .xpath = "/frr-interface:lib/interface/frr-ripd:rip/authentication-scheme",
1469 .cbs.cli_show = cli_show_ip_rip_authentication_scheme,
1470 },
1471 {
1472 .xpath = "/frr-interface:lib/interface/frr-ripd:rip/authentication-scheme/mode",
1473 .cbs.modify = lib_interface_rip_authentication_scheme_mode_modify,
1474 },
1475 {
1476 .xpath = "/frr-interface:lib/interface/frr-ripd:rip/authentication-scheme/md5-auth-length",
1477 .cbs.modify = lib_interface_rip_authentication_scheme_md5_auth_length_modify,
1478 .cbs.delete = lib_interface_rip_authentication_scheme_md5_auth_length_delete,
1479 },
1480 {
1481 .xpath = "/frr-interface:lib/interface/frr-ripd:rip/authentication-password",
1482 .cbs.modify = lib_interface_rip_authentication_password_modify,
1483 .cbs.delete = lib_interface_rip_authentication_password_delete,
1484 .cbs.cli_show = cli_show_ip_rip_authentication_string,
1485 },
1486 {
1487 .xpath = "/frr-interface:lib/interface/frr-ripd:rip/authentication-key-chain",
1488 .cbs.modify = lib_interface_rip_authentication_key_chain_modify,
1489 .cbs.delete = lib_interface_rip_authentication_key_chain_delete,
1490 .cbs.cli_show = cli_show_ip_rip_authentication_key_chain,
1491 },
1492 {
1493 .xpath = "/frr-ripd:ripd/state/neighbors/neighbor",
1494 .cbs.get_next = ripd_state_neighbors_neighbor_get_next,
1495 .cbs.get_keys = ripd_state_neighbors_neighbor_get_keys,
1496 .cbs.lookup_entry = ripd_state_neighbors_neighbor_lookup_entry,
1497 },
1498 {
1499 .xpath = "/frr-ripd:ripd/state/neighbors/neighbor/address",
1500 .cbs.get_elem = ripd_state_neighbors_neighbor_address_get_elem,
1501 },
1502 {
1503 .xpath = "/frr-ripd:ripd/state/neighbors/neighbor/last-update",
1504 .cbs.get_elem = ripd_state_neighbors_neighbor_last_update_get_elem,
1505 },
1506 {
1507 .xpath = "/frr-ripd:ripd/state/neighbors/neighbor/bad-packets-rcvd",
1508 .cbs.get_elem = ripd_state_neighbors_neighbor_bad_packets_rcvd_get_elem,
1509 },
1510 {
1511 .xpath = "/frr-ripd:ripd/state/neighbors/neighbor/bad-routes-rcvd",
1512 .cbs.get_elem = ripd_state_neighbors_neighbor_bad_routes_rcvd_get_elem,
1513 },
1514 {
1515 .xpath = "/frr-ripd:ripd/state/routes/route",
1516 .cbs.get_next = ripd_state_routes_route_get_next,
1517 .cbs.get_keys = ripd_state_routes_route_get_keys,
1518 .cbs.lookup_entry = ripd_state_routes_route_lookup_entry,
1519 },
1520 {
1521 .xpath = "/frr-ripd:ripd/state/routes/route/prefix",
1522 .cbs.get_elem = ripd_state_routes_route_prefix_get_elem,
1523 },
1524 {
1525 .xpath = "/frr-ripd:ripd/state/routes/route/next-hop",
1526 .cbs.get_elem = ripd_state_routes_route_next_hop_get_elem,
1527 },
1528 {
1529 .xpath = "/frr-ripd:ripd/state/routes/route/interface",
1530 .cbs.get_elem = ripd_state_routes_route_interface_get_elem,
1531 },
1532 {
1533 .xpath = "/frr-ripd:ripd/state/routes/route/metric",
1534 .cbs.get_elem = ripd_state_routes_route_metric_get_elem,
1535 },
1536 {
1537 .xpath = "/frr-ripd:clear-rip-route",
1538 .cbs.rpc = clear_rip_route_rpc,
1539 },
1540 {
1541 .xpath = NULL,
1542 },
1543 }
1544 };