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