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_nb.h"
35 #include "ripd/rip_debug.h"
36 #include "ripd/rip_interface.h"
37 
38 /*
39  * XPath: /frr-ripd:ripd/instance
40  */
ripd_instance_create(struct nb_cb_create_args * args)41 int ripd_instance_create(struct nb_cb_create_args *args)
42 {
43 	struct rip *rip;
44 	struct vrf *vrf;
45 	const char *vrf_name;
46 	int socket;
47 
48 	vrf_name = yang_dnode_get_string(args->dnode, "./vrf");
49 	vrf = vrf_lookup_by_name(vrf_name);
50 
51 	/*
52 	 * Try to create a RIP socket only if the VRF is enabled, otherwise
53 	 * create a disabled RIP instance and wait for the VRF to be enabled.
54 	 */
55 	switch (args->event) {
56 	case NB_EV_VALIDATE:
57 		break;
58 	case NB_EV_PREPARE:
59 		if (!vrf || !vrf_is_enabled(vrf))
60 			break;
61 
62 		socket = rip_create_socket(vrf);
63 		if (socket < 0)
64 			return NB_ERR_RESOURCE;
65 		args->resource->fd = socket;
66 		break;
67 	case NB_EV_ABORT:
68 		if (!vrf || !vrf_is_enabled(vrf))
69 			break;
70 
71 		socket = args->resource->fd;
72 		close(socket);
73 		break;
74 	case NB_EV_APPLY:
75 		if (vrf && vrf_is_enabled(vrf))
76 			socket = args->resource->fd;
77 		else
78 			socket = -1;
79 
80 		rip = rip_create(vrf_name, vrf, socket);
81 		nb_running_set_entry(args->dnode, rip);
82 		break;
83 	}
84 
85 	return NB_OK;
86 }
87 
ripd_instance_destroy(struct nb_cb_destroy_args * args)88 int ripd_instance_destroy(struct nb_cb_destroy_args *args)
89 {
90 	struct rip *rip;
91 
92 	if (args->event != NB_EV_APPLY)
93 		return NB_OK;
94 
95 	rip = nb_running_unset_entry(args->dnode);
96 	rip_clean(rip);
97 
98 	return NB_OK;
99 }
100 
101 /*
102  * XPath: /frr-ripd:ripd/instance/allow-ecmp
103  */
ripd_instance_allow_ecmp_modify(struct nb_cb_modify_args * args)104 int ripd_instance_allow_ecmp_modify(struct nb_cb_modify_args *args)
105 {
106 	struct rip *rip;
107 
108 	if (args->event != NB_EV_APPLY)
109 		return NB_OK;
110 
111 	rip = nb_running_get_entry(args->dnode, NULL, true);
112 	rip->ecmp = yang_dnode_get_bool(args->dnode, NULL);
113 	if (!rip->ecmp)
114 		rip_ecmp_disable(rip);
115 
116 	return NB_OK;
117 }
118 
119 /*
120  * XPath: /frr-ripd:ripd/instance/default-information-originate
121  */
ripd_instance_default_information_originate_modify(struct nb_cb_modify_args * args)122 int ripd_instance_default_information_originate_modify(
123 	struct nb_cb_modify_args *args)
124 {
125 	struct rip *rip;
126 	bool default_information;
127 	struct prefix_ipv4 p;
128 
129 	if (args->event != NB_EV_APPLY)
130 		return NB_OK;
131 
132 	rip = nb_running_get_entry(args->dnode, NULL, true);
133 	default_information = yang_dnode_get_bool(args->dnode, NULL);
134 
135 	memset(&p, 0, sizeof(struct prefix_ipv4));
136 	p.family = AF_INET;
137 	if (default_information) {
138 		struct nexthop nh;
139 
140 		memset(&nh, 0, sizeof(nh));
141 		nh.type = NEXTHOP_TYPE_IPV4;
142 		rip_redistribute_add(rip, ZEBRA_ROUTE_RIP, RIP_ROUTE_DEFAULT,
143 				     &p, &nh, 0, 0, 0);
144 	} else {
145 		rip_redistribute_delete(rip, ZEBRA_ROUTE_RIP, RIP_ROUTE_DEFAULT,
146 					&p, 0);
147 	}
148 
149 	return NB_OK;
150 }
151 
152 /*
153  * XPath: /frr-ripd:ripd/instance/default-metric
154  */
ripd_instance_default_metric_modify(struct nb_cb_modify_args * args)155 int ripd_instance_default_metric_modify(struct nb_cb_modify_args *args)
156 {
157 	struct rip *rip;
158 
159 	if (args->event != NB_EV_APPLY)
160 		return NB_OK;
161 
162 	rip = nb_running_get_entry(args->dnode, NULL, true);
163 	rip->default_metric = yang_dnode_get_uint8(args->dnode, NULL);
164 	/* rip_update_default_metric (); */
165 
166 	return NB_OK;
167 }
168 
169 /*
170  * XPath: /frr-ripd:ripd/instance/distance/default
171  */
ripd_instance_distance_default_modify(struct nb_cb_modify_args * args)172 int ripd_instance_distance_default_modify(struct nb_cb_modify_args *args)
173 {
174 	struct rip *rip;
175 
176 	if (args->event != NB_EV_APPLY)
177 		return NB_OK;
178 
179 	rip = nb_running_get_entry(args->dnode, NULL, true);
180 	rip->distance = yang_dnode_get_uint8(args->dnode, NULL);
181 
182 	return NB_OK;
183 }
184 
185 /*
186  * XPath: /frr-ripd:ripd/instance/distance/source
187  */
ripd_instance_distance_source_create(struct nb_cb_create_args * args)188 int ripd_instance_distance_source_create(struct nb_cb_create_args *args)
189 {
190 	struct rip *rip;
191 	struct prefix_ipv4 prefix;
192 	struct route_node *rn;
193 
194 	if (args->event != NB_EV_APPLY)
195 		return NB_OK;
196 
197 	yang_dnode_get_ipv4p(&prefix, args->dnode, "./prefix");
198 	apply_mask_ipv4(&prefix);
199 
200 	/* Get RIP distance node. */
201 	rip = nb_running_get_entry(args->dnode, NULL, true);
202 	rn = route_node_get(rip->distance_table, (struct prefix *)&prefix);
203 	rn->info = rip_distance_new();
204 	nb_running_set_entry(args->dnode, rn);
205 
206 	return NB_OK;
207 }
208 
ripd_instance_distance_source_destroy(struct nb_cb_destroy_args * args)209 int ripd_instance_distance_source_destroy(struct nb_cb_destroy_args *args)
210 {
211 	struct route_node *rn;
212 	struct rip_distance *rdistance;
213 
214 	if (args->event != NB_EV_APPLY)
215 		return NB_OK;
216 
217 	rn = nb_running_unset_entry(args->dnode);
218 	rdistance = rn->info;
219 	rip_distance_free(rdistance);
220 	rn->info = NULL;
221 	route_unlock_node(rn);
222 
223 	return NB_OK;
224 }
225 
226 /*
227  * XPath: /frr-ripd:ripd/instance/distance/source/distance
228  */
ripd_instance_distance_source_distance_modify(struct nb_cb_modify_args * args)229 int ripd_instance_distance_source_distance_modify(
230 	struct nb_cb_modify_args *args)
231 {
232 	struct route_node *rn;
233 	uint8_t distance;
234 	struct rip_distance *rdistance;
235 
236 	if (args->event != NB_EV_APPLY)
237 		return NB_OK;
238 
239 	/* Set distance value. */
240 	rn = nb_running_get_entry(args->dnode, NULL, true);
241 	distance = yang_dnode_get_uint8(args->dnode, NULL);
242 	rdistance = rn->info;
243 	rdistance->distance = distance;
244 
245 	return NB_OK;
246 }
247 
248 /*
249  * XPath: /frr-ripd:ripd/instance/distance/source/access-list
250  */
ripd_instance_distance_source_access_list_modify(struct nb_cb_modify_args * args)251 int ripd_instance_distance_source_access_list_modify(
252 	struct nb_cb_modify_args *args)
253 {
254 	const char *acl_name;
255 	struct route_node *rn;
256 	struct rip_distance *rdistance;
257 
258 	if (args->event != NB_EV_APPLY)
259 		return NB_OK;
260 
261 	acl_name = yang_dnode_get_string(args->dnode, NULL);
262 
263 	/* Set access-list */
264 	rn = nb_running_get_entry(args->dnode, NULL, true);
265 	rdistance = rn->info;
266 	if (rdistance->access_list)
267 		free(rdistance->access_list);
268 	rdistance->access_list = strdup(acl_name);
269 
270 	return NB_OK;
271 }
272 
ripd_instance_distance_source_access_list_destroy(struct nb_cb_destroy_args * args)273 int ripd_instance_distance_source_access_list_destroy(
274 	struct nb_cb_destroy_args *args)
275 {
276 	struct route_node *rn;
277 	struct rip_distance *rdistance;
278 
279 	if (args->event != NB_EV_APPLY)
280 		return NB_OK;
281 
282 	/* Reset access-list configuration. */
283 	rn = nb_running_get_entry(args->dnode, NULL, true);
284 	rdistance = rn->info;
285 	free(rdistance->access_list);
286 	rdistance->access_list = NULL;
287 
288 	return NB_OK;
289 }
290 
291 /*
292  * XPath: /frr-ripd:ripd/instance/explicit-neighbor
293  */
ripd_instance_explicit_neighbor_create(struct nb_cb_create_args * args)294 int ripd_instance_explicit_neighbor_create(struct nb_cb_create_args *args)
295 {
296 	struct rip *rip;
297 	struct prefix_ipv4 p;
298 
299 	if (args->event != NB_EV_APPLY)
300 		return NB_OK;
301 
302 	rip = nb_running_get_entry(args->dnode, NULL, true);
303 	p.family = AF_INET;
304 	p.prefixlen = IPV4_MAX_BITLEN;
305 	yang_dnode_get_ipv4(&p.prefix, args->dnode, NULL);
306 
307 	return rip_neighbor_add(rip, &p);
308 }
309 
ripd_instance_explicit_neighbor_destroy(struct nb_cb_destroy_args * args)310 int ripd_instance_explicit_neighbor_destroy(struct nb_cb_destroy_args *args)
311 {
312 	struct rip *rip;
313 	struct prefix_ipv4 p;
314 
315 	if (args->event != NB_EV_APPLY)
316 		return NB_OK;
317 
318 	rip = nb_running_get_entry(args->dnode, NULL, true);
319 	p.family = AF_INET;
320 	p.prefixlen = IPV4_MAX_BITLEN;
321 	yang_dnode_get_ipv4(&p.prefix, args->dnode, NULL);
322 
323 	return rip_neighbor_delete(rip, &p);
324 }
325 
326 /*
327  * XPath: /frr-ripd:ripd/instance/network
328  */
ripd_instance_network_create(struct nb_cb_create_args * args)329 int ripd_instance_network_create(struct nb_cb_create_args *args)
330 {
331 	struct rip *rip;
332 	struct prefix p;
333 
334 	if (args->event != NB_EV_APPLY)
335 		return NB_OK;
336 
337 	rip = nb_running_get_entry(args->dnode, NULL, true);
338 	yang_dnode_get_ipv4p(&p, args->dnode, NULL);
339 	apply_mask_ipv4((struct prefix_ipv4 *)&p);
340 
341 	return rip_enable_network_add(rip, &p);
342 }
343 
ripd_instance_network_destroy(struct nb_cb_destroy_args * args)344 int ripd_instance_network_destroy(struct nb_cb_destroy_args *args)
345 {
346 	struct rip *rip;
347 	struct prefix p;
348 
349 	if (args->event != NB_EV_APPLY)
350 		return NB_OK;
351 
352 	rip = nb_running_get_entry(args->dnode, NULL, true);
353 	yang_dnode_get_ipv4p(&p, args->dnode, NULL);
354 	apply_mask_ipv4((struct prefix_ipv4 *)&p);
355 
356 	return rip_enable_network_delete(rip, &p);
357 }
358 
359 /*
360  * XPath: /frr-ripd:ripd/instance/interface
361  */
ripd_instance_interface_create(struct nb_cb_create_args * args)362 int ripd_instance_interface_create(struct nb_cb_create_args *args)
363 {
364 	struct rip *rip;
365 	const char *ifname;
366 
367 	if (args->event != NB_EV_APPLY)
368 		return NB_OK;
369 
370 	rip = nb_running_get_entry(args->dnode, NULL, true);
371 	ifname = yang_dnode_get_string(args->dnode, NULL);
372 
373 	return rip_enable_if_add(rip, ifname);
374 }
375 
ripd_instance_interface_destroy(struct nb_cb_destroy_args * args)376 int ripd_instance_interface_destroy(struct nb_cb_destroy_args *args)
377 {
378 	struct rip *rip;
379 	const char *ifname;
380 
381 	if (args->event != NB_EV_APPLY)
382 		return NB_OK;
383 
384 	rip = nb_running_get_entry(args->dnode, NULL, true);
385 	ifname = yang_dnode_get_string(args->dnode, NULL);
386 
387 	return rip_enable_if_delete(rip, ifname);
388 }
389 
390 /*
391  * XPath: /frr-ripd:ripd/instance/offset-list
392  */
ripd_instance_offset_list_create(struct nb_cb_create_args * args)393 int ripd_instance_offset_list_create(struct nb_cb_create_args *args)
394 {
395 	struct rip *rip;
396 	const char *ifname;
397 	struct rip_offset_list *offset;
398 
399 	if (args->event != NB_EV_APPLY)
400 		return NB_OK;
401 
402 	rip = nb_running_get_entry(args->dnode, NULL, true);
403 	ifname = yang_dnode_get_string(args->dnode, "./interface");
404 
405 	offset = rip_offset_list_new(rip, ifname);
406 	nb_running_set_entry(args->dnode, offset);
407 
408 	return NB_OK;
409 }
410 
ripd_instance_offset_list_destroy(struct nb_cb_destroy_args * args)411 int ripd_instance_offset_list_destroy(struct nb_cb_destroy_args *args)
412 {
413 	int direct;
414 	struct rip_offset_list *offset;
415 
416 	if (args->event != NB_EV_APPLY)
417 		return NB_OK;
418 
419 	direct = yang_dnode_get_enum(args->dnode, "./direction");
420 
421 	offset = nb_running_unset_entry(args->dnode);
422 	if (offset->direct[direct].alist_name) {
423 		free(offset->direct[direct].alist_name);
424 		offset->direct[direct].alist_name = NULL;
425 	}
426 	if (offset->direct[RIP_OFFSET_LIST_IN].alist_name == NULL
427 	    && offset->direct[RIP_OFFSET_LIST_OUT].alist_name == NULL)
428 		offset_list_del(offset);
429 
430 	return NB_OK;
431 }
432 
433 /*
434  * XPath: /frr-ripd:ripd/instance/offset-list/access-list
435  */
ripd_instance_offset_list_access_list_modify(struct nb_cb_modify_args * args)436 int ripd_instance_offset_list_access_list_modify(struct nb_cb_modify_args *args)
437 {
438 	int direct;
439 	struct rip_offset_list *offset;
440 	const char *alist_name;
441 
442 	if (args->event != NB_EV_APPLY)
443 		return NB_OK;
444 
445 	direct = yang_dnode_get_enum(args->dnode, "../direction");
446 	alist_name = yang_dnode_get_string(args->dnode, NULL);
447 
448 	offset = nb_running_get_entry(args->dnode, NULL, true);
449 	if (offset->direct[direct].alist_name)
450 		free(offset->direct[direct].alist_name);
451 	offset->direct[direct].alist_name = strdup(alist_name);
452 
453 	return NB_OK;
454 }
455 
456 /*
457  * XPath: /frr-ripd:ripd/instance/offset-list/metric
458  */
ripd_instance_offset_list_metric_modify(struct nb_cb_modify_args * args)459 int ripd_instance_offset_list_metric_modify(struct nb_cb_modify_args *args)
460 {
461 	int direct;
462 	uint8_t metric;
463 	struct rip_offset_list *offset;
464 
465 	if (args->event != NB_EV_APPLY)
466 		return NB_OK;
467 
468 	direct = yang_dnode_get_enum(args->dnode, "../direction");
469 	metric = yang_dnode_get_uint8(args->dnode, NULL);
470 
471 	offset = nb_running_get_entry(args->dnode, NULL, true);
472 	offset->direct[direct].metric = metric;
473 
474 	return NB_OK;
475 }
476 
477 /*
478  * XPath: /frr-ripd:ripd/instance/passive-default
479  */
ripd_instance_passive_default_modify(struct nb_cb_modify_args * args)480 int ripd_instance_passive_default_modify(struct nb_cb_modify_args *args)
481 {
482 	struct rip *rip;
483 
484 	if (args->event != NB_EV_APPLY)
485 		return NB_OK;
486 
487 	rip = nb_running_get_entry(args->dnode, NULL, true);
488 	rip->passive_default = yang_dnode_get_bool(args->dnode, NULL);
489 	rip_passive_nondefault_clean(rip);
490 
491 	return NB_OK;
492 }
493 
494 /*
495  * XPath: /frr-ripd:ripd/instance/passive-interface
496  */
ripd_instance_passive_interface_create(struct nb_cb_create_args * args)497 int ripd_instance_passive_interface_create(struct nb_cb_create_args *args)
498 {
499 	struct rip *rip;
500 	const char *ifname;
501 
502 	if (args->event != NB_EV_APPLY)
503 		return NB_OK;
504 
505 	rip = nb_running_get_entry(args->dnode, NULL, true);
506 	ifname = yang_dnode_get_string(args->dnode, NULL);
507 
508 	return rip_passive_nondefault_set(rip, ifname);
509 }
510 
ripd_instance_passive_interface_destroy(struct nb_cb_destroy_args * args)511 int ripd_instance_passive_interface_destroy(struct nb_cb_destroy_args *args)
512 {
513 	struct rip *rip;
514 	const char *ifname;
515 
516 	if (args->event != NB_EV_APPLY)
517 		return NB_OK;
518 
519 	rip = nb_running_get_entry(args->dnode, NULL, true);
520 	ifname = yang_dnode_get_string(args->dnode, NULL);
521 
522 	return rip_passive_nondefault_unset(rip, ifname);
523 }
524 
525 /*
526  * XPath: /frr-ripd:ripd/instance/non-passive-interface
527  */
ripd_instance_non_passive_interface_create(struct nb_cb_create_args * args)528 int ripd_instance_non_passive_interface_create(struct nb_cb_create_args *args)
529 {
530 	struct rip *rip;
531 	const char *ifname;
532 
533 	if (args->event != NB_EV_APPLY)
534 		return NB_OK;
535 
536 	rip = nb_running_get_entry(args->dnode, NULL, true);
537 	ifname = yang_dnode_get_string(args->dnode, NULL);
538 
539 	return rip_passive_nondefault_unset(rip, ifname);
540 }
541 
ripd_instance_non_passive_interface_destroy(struct nb_cb_destroy_args * args)542 int ripd_instance_non_passive_interface_destroy(struct nb_cb_destroy_args *args)
543 {
544 	struct rip *rip;
545 	const char *ifname;
546 
547 	if (args->event != NB_EV_APPLY)
548 		return NB_OK;
549 
550 	rip = nb_running_get_entry(args->dnode, NULL, true);
551 	ifname = yang_dnode_get_string(args->dnode, NULL);
552 
553 	return rip_passive_nondefault_set(rip, ifname);
554 }
555 
556 /*
557  * XPath: /frr-ripd:ripd/instance/redistribute
558  */
ripd_instance_redistribute_create(struct nb_cb_create_args * args)559 int ripd_instance_redistribute_create(struct nb_cb_create_args *args)
560 {
561 	struct rip *rip;
562 	int type;
563 
564 	if (args->event != NB_EV_APPLY)
565 		return NB_OK;
566 
567 	rip = nb_running_get_entry(args->dnode, NULL, true);
568 	type = yang_dnode_get_enum(args->dnode, "./protocol");
569 
570 	rip->redist[type].enabled = true;
571 
572 	return NB_OK;
573 }
574 
ripd_instance_redistribute_destroy(struct nb_cb_destroy_args * args)575 int ripd_instance_redistribute_destroy(struct nb_cb_destroy_args *args)
576 {
577 	struct rip *rip;
578 	int type;
579 
580 	if (args->event != NB_EV_APPLY)
581 		return NB_OK;
582 
583 	rip = nb_running_get_entry(args->dnode, NULL, true);
584 	type = yang_dnode_get_enum(args->dnode, "./protocol");
585 
586 	rip->redist[type].enabled = false;
587 	if (rip->redist[type].route_map.name) {
588 		free(rip->redist[type].route_map.name);
589 		rip->redist[type].route_map.name = NULL;
590 		rip->redist[type].route_map.map = NULL;
591 	}
592 	rip->redist[type].metric_config = false;
593 	rip->redist[type].metric = 0;
594 
595 	if (rip->enabled)
596 		rip_redistribute_conf_delete(rip, type);
597 
598 	return NB_OK;
599 }
600 
ripd_instance_redistribute_apply_finish(struct nb_cb_apply_finish_args * args)601 void ripd_instance_redistribute_apply_finish(
602 	struct nb_cb_apply_finish_args *args)
603 {
604 	struct rip *rip;
605 	int type;
606 
607 	rip = nb_running_get_entry(args->dnode, NULL, true);
608 	type = yang_dnode_get_enum(args->dnode, "./protocol");
609 
610 	if (rip->enabled)
611 		rip_redistribute_conf_update(rip, type);
612 }
613 
614 /*
615  * XPath: /frr-ripd:ripd/instance/redistribute/route-map
616  */
ripd_instance_redistribute_route_map_modify(struct nb_cb_modify_args * args)617 int ripd_instance_redistribute_route_map_modify(struct nb_cb_modify_args *args)
618 {
619 	struct rip *rip;
620 	int type;
621 	const char *rmap_name;
622 
623 	if (args->event != NB_EV_APPLY)
624 		return NB_OK;
625 
626 	rip = nb_running_get_entry(args->dnode, NULL, true);
627 	type = yang_dnode_get_enum(args->dnode, "../protocol");
628 	rmap_name = yang_dnode_get_string(args->dnode, NULL);
629 
630 	if (rip->redist[type].route_map.name)
631 		free(rip->redist[type].route_map.name);
632 	rip->redist[type].route_map.name = strdup(rmap_name);
633 	rip->redist[type].route_map.map = route_map_lookup_by_name(rmap_name);
634 
635 	return NB_OK;
636 }
637 
ripd_instance_redistribute_route_map_destroy(struct nb_cb_destroy_args * args)638 int ripd_instance_redistribute_route_map_destroy(
639 	struct nb_cb_destroy_args *args)
640 {
641 	struct rip *rip;
642 	int type;
643 
644 	if (args->event != NB_EV_APPLY)
645 		return NB_OK;
646 
647 	rip = nb_running_get_entry(args->dnode, NULL, true);
648 	type = yang_dnode_get_enum(args->dnode, "../protocol");
649 
650 	free(rip->redist[type].route_map.name);
651 	rip->redist[type].route_map.name = NULL;
652 	rip->redist[type].route_map.map = NULL;
653 
654 	return NB_OK;
655 }
656 
657 /*
658  * XPath: /frr-ripd:ripd/instance/redistribute/metric
659  */
ripd_instance_redistribute_metric_modify(struct nb_cb_modify_args * args)660 int ripd_instance_redistribute_metric_modify(struct nb_cb_modify_args *args)
661 {
662 	struct rip *rip;
663 	int type;
664 	uint8_t metric;
665 
666 	if (args->event != NB_EV_APPLY)
667 		return NB_OK;
668 
669 	rip = nb_running_get_entry(args->dnode, NULL, true);
670 	type = yang_dnode_get_enum(args->dnode, "../protocol");
671 	metric = yang_dnode_get_uint8(args->dnode, NULL);
672 
673 	rip->redist[type].metric_config = true;
674 	rip->redist[type].metric = metric;
675 
676 	return NB_OK;
677 }
678 
ripd_instance_redistribute_metric_destroy(struct nb_cb_destroy_args * args)679 int ripd_instance_redistribute_metric_destroy(struct nb_cb_destroy_args *args)
680 {
681 	struct rip *rip;
682 	int type;
683 
684 	if (args->event != NB_EV_APPLY)
685 		return NB_OK;
686 
687 	rip = nb_running_get_entry(args->dnode, NULL, true);
688 	type = yang_dnode_get_enum(args->dnode, "../protocol");
689 
690 	rip->redist[type].metric_config = false;
691 	rip->redist[type].metric = 0;
692 
693 	return NB_OK;
694 }
695 
696 /*
697  * XPath: /frr-ripd:ripd/instance/static-route
698  */
ripd_instance_static_route_create(struct nb_cb_create_args * args)699 int ripd_instance_static_route_create(struct nb_cb_create_args *args)
700 {
701 	struct rip *rip;
702 	struct nexthop nh;
703 	struct prefix_ipv4 p;
704 
705 	if (args->event != NB_EV_APPLY)
706 		return NB_OK;
707 
708 	rip = nb_running_get_entry(args->dnode, NULL, true);
709 	yang_dnode_get_ipv4p(&p, args->dnode, NULL);
710 	apply_mask_ipv4(&p);
711 
712 	memset(&nh, 0, sizeof(nh));
713 	nh.type = NEXTHOP_TYPE_IPV4;
714 	rip_redistribute_add(rip, ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, &nh, 0,
715 			     0, 0);
716 
717 	return NB_OK;
718 }
719 
ripd_instance_static_route_destroy(struct nb_cb_destroy_args * args)720 int ripd_instance_static_route_destroy(struct nb_cb_destroy_args *args)
721 {
722 	struct rip *rip;
723 	struct prefix_ipv4 p;
724 
725 	if (args->event != NB_EV_APPLY)
726 		return NB_OK;
727 
728 	rip = nb_running_get_entry(args->dnode, NULL, true);
729 	yang_dnode_get_ipv4p(&p, args->dnode, NULL);
730 	apply_mask_ipv4(&p);
731 
732 	rip_redistribute_delete(rip, ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0);
733 
734 	return NB_OK;
735 }
736 
737 /*
738  * XPath: /frr-ripd:ripd/instance/timers/
739  */
ripd_instance_timers_apply_finish(struct nb_cb_apply_finish_args * args)740 void ripd_instance_timers_apply_finish(struct nb_cb_apply_finish_args *args)
741 {
742 	struct rip *rip;
743 
744 	rip = nb_running_get_entry(args->dnode, NULL, true);
745 
746 	/* Reset update timer thread. */
747 	rip_event(rip, RIP_UPDATE_EVENT, 0);
748 }
749 
750 /*
751  * XPath: /frr-ripd:ripd/instance/timers/flush-interval
752  */
ripd_instance_timers_flush_interval_modify(struct nb_cb_modify_args * args)753 int ripd_instance_timers_flush_interval_modify(struct nb_cb_modify_args *args)
754 {
755 	struct rip *rip;
756 
757 	if (args->event != NB_EV_APPLY)
758 		return NB_OK;
759 
760 	rip = nb_running_get_entry(args->dnode, NULL, true);
761 	rip->garbage_time = yang_dnode_get_uint32(args->dnode, NULL);
762 
763 	return NB_OK;
764 }
765 
766 /*
767  * XPath: /frr-ripd:ripd/instance/timers/holddown-interval
768  */
ripd_instance_timers_holddown_interval_modify(struct nb_cb_modify_args * args)769 int ripd_instance_timers_holddown_interval_modify(
770 	struct nb_cb_modify_args *args)
771 {
772 	struct rip *rip;
773 
774 	if (args->event != NB_EV_APPLY)
775 		return NB_OK;
776 
777 	rip = nb_running_get_entry(args->dnode, NULL, true);
778 	rip->timeout_time = yang_dnode_get_uint32(args->dnode, NULL);
779 
780 	return NB_OK;
781 }
782 
783 /*
784  * XPath: /frr-ripd:ripd/instance/timers/update-interval
785  */
ripd_instance_timers_update_interval_modify(struct nb_cb_modify_args * args)786 int ripd_instance_timers_update_interval_modify(struct nb_cb_modify_args *args)
787 {
788 	struct rip *rip;
789 
790 	if (args->event != NB_EV_APPLY)
791 		return NB_OK;
792 
793 	rip = nb_running_get_entry(args->dnode, NULL, true);
794 	rip->update_time = yang_dnode_get_uint32(args->dnode, NULL);
795 
796 	return NB_OK;
797 }
798 
799 /*
800  * XPath: /frr-ripd:ripd/instance/version/receive
801  */
ripd_instance_version_receive_modify(struct nb_cb_modify_args * args)802 int ripd_instance_version_receive_modify(struct nb_cb_modify_args *args)
803 {
804 	struct rip *rip;
805 
806 	if (args->event != NB_EV_APPLY)
807 		return NB_OK;
808 
809 	rip = nb_running_get_entry(args->dnode, NULL, true);
810 	rip->version_recv = yang_dnode_get_enum(args->dnode, NULL);
811 
812 	return NB_OK;
813 }
814 
815 /*
816  * XPath: /frr-ripd:ripd/instance/version/send
817  */
ripd_instance_version_send_modify(struct nb_cb_modify_args * args)818 int ripd_instance_version_send_modify(struct nb_cb_modify_args *args)
819 {
820 	struct rip *rip;
821 
822 	if (args->event != NB_EV_APPLY)
823 		return NB_OK;
824 
825 	rip = nb_running_get_entry(args->dnode, NULL, true);
826 	rip->version_send = yang_dnode_get_enum(args->dnode, NULL);
827 
828 	return NB_OK;
829 }
830 
831 /*
832  * XPath: /frr-interface:lib/interface/frr-ripd:rip/split-horizon
833  */
lib_interface_rip_split_horizon_modify(struct nb_cb_modify_args * args)834 int lib_interface_rip_split_horizon_modify(struct nb_cb_modify_args *args)
835 {
836 	struct interface *ifp;
837 	struct rip_interface *ri;
838 
839 	if (args->event != NB_EV_APPLY)
840 		return NB_OK;
841 
842 	ifp = nb_running_get_entry(args->dnode, NULL, true);
843 	ri = ifp->info;
844 	ri->split_horizon = yang_dnode_get_enum(args->dnode, NULL);
845 
846 	return NB_OK;
847 }
848 
849 /*
850  * XPath: /frr-interface:lib/interface/frr-ripd:rip/v2-broadcast
851  */
lib_interface_rip_v2_broadcast_modify(struct nb_cb_modify_args * args)852 int lib_interface_rip_v2_broadcast_modify(struct nb_cb_modify_args *args)
853 {
854 	struct interface *ifp;
855 	struct rip_interface *ri;
856 
857 	if (args->event != NB_EV_APPLY)
858 		return NB_OK;
859 
860 	ifp = nb_running_get_entry(args->dnode, NULL, true);
861 	ri = ifp->info;
862 	ri->v2_broadcast = yang_dnode_get_bool(args->dnode, NULL);
863 
864 	return NB_OK;
865 }
866 
867 /*
868  * XPath: /frr-interface:lib/interface/frr-ripd:rip/version-receive
869  */
lib_interface_rip_version_receive_modify(struct nb_cb_modify_args * args)870 int lib_interface_rip_version_receive_modify(struct nb_cb_modify_args *args)
871 {
872 	struct interface *ifp;
873 	struct rip_interface *ri;
874 
875 	if (args->event != NB_EV_APPLY)
876 		return NB_OK;
877 
878 	ifp = nb_running_get_entry(args->dnode, NULL, true);
879 	ri = ifp->info;
880 	ri->ri_receive = yang_dnode_get_enum(args->dnode, NULL);
881 
882 	return NB_OK;
883 }
884 
885 /*
886  * XPath: /frr-interface:lib/interface/frr-ripd:rip/version-send
887  */
lib_interface_rip_version_send_modify(struct nb_cb_modify_args * args)888 int lib_interface_rip_version_send_modify(struct nb_cb_modify_args *args)
889 {
890 	struct interface *ifp;
891 	struct rip_interface *ri;
892 
893 	if (args->event != NB_EV_APPLY)
894 		return NB_OK;
895 
896 	ifp = nb_running_get_entry(args->dnode, NULL, true);
897 	ri = ifp->info;
898 	ri->ri_send = yang_dnode_get_enum(args->dnode, NULL);
899 
900 	return NB_OK;
901 }
902 
903 /*
904  * XPath: /frr-interface:lib/interface/frr-ripd:rip/authentication-scheme/mode
905  */
lib_interface_rip_authentication_scheme_mode_modify(struct nb_cb_modify_args * args)906 int lib_interface_rip_authentication_scheme_mode_modify(
907 	struct nb_cb_modify_args *args)
908 {
909 	struct interface *ifp;
910 	struct rip_interface *ri;
911 
912 	if (args->event != NB_EV_APPLY)
913 		return NB_OK;
914 
915 	ifp = nb_running_get_entry(args->dnode, NULL, true);
916 	ri = ifp->info;
917 	ri->auth_type = yang_dnode_get_enum(args->dnode, NULL);
918 
919 	return NB_OK;
920 }
921 
922 /*
923  * XPath:
924  * /frr-interface:lib/interface/frr-ripd:rip/authentication-scheme/md5-auth-length
925  */
lib_interface_rip_authentication_scheme_md5_auth_length_modify(struct nb_cb_modify_args * args)926 int lib_interface_rip_authentication_scheme_md5_auth_length_modify(
927 	struct nb_cb_modify_args *args)
928 {
929 	struct interface *ifp;
930 	struct rip_interface *ri;
931 
932 	if (args->event != NB_EV_APPLY)
933 		return NB_OK;
934 
935 	ifp = nb_running_get_entry(args->dnode, NULL, true);
936 	ri = ifp->info;
937 	ri->md5_auth_len = yang_dnode_get_enum(args->dnode, NULL);
938 
939 	return NB_OK;
940 }
941 
lib_interface_rip_authentication_scheme_md5_auth_length_destroy(struct nb_cb_destroy_args * args)942 int lib_interface_rip_authentication_scheme_md5_auth_length_destroy(
943 	struct nb_cb_destroy_args *args)
944 {
945 	struct interface *ifp;
946 	struct rip_interface *ri;
947 
948 	if (args->event != NB_EV_APPLY)
949 		return NB_OK;
950 
951 	ifp = nb_running_get_entry(args->dnode, NULL, true);
952 	ri = ifp->info;
953 	ri->md5_auth_len = yang_get_default_enum(
954 		"%s/authentication-scheme/md5-auth-length", RIP_IFACE);
955 
956 	return NB_OK;
957 }
958 
959 /*
960  * XPath: /frr-interface:lib/interface/frr-ripd:rip/authentication-password
961  */
lib_interface_rip_authentication_password_modify(struct nb_cb_modify_args * args)962 int lib_interface_rip_authentication_password_modify(
963 	struct nb_cb_modify_args *args)
964 {
965 	struct interface *ifp;
966 	struct rip_interface *ri;
967 
968 	if (args->event != NB_EV_APPLY)
969 		return NB_OK;
970 
971 	ifp = nb_running_get_entry(args->dnode, NULL, true);
972 	ri = ifp->info;
973 	XFREE(MTYPE_RIP_INTERFACE_STRING, ri->auth_str);
974 	ri->auth_str = XSTRDUP(MTYPE_RIP_INTERFACE_STRING,
975 			       yang_dnode_get_string(args->dnode, NULL));
976 
977 	return NB_OK;
978 }
979 
lib_interface_rip_authentication_password_destroy(struct nb_cb_destroy_args * args)980 int lib_interface_rip_authentication_password_destroy(
981 	struct nb_cb_destroy_args *args)
982 {
983 	struct interface *ifp;
984 	struct rip_interface *ri;
985 
986 	if (args->event != NB_EV_APPLY)
987 		return NB_OK;
988 
989 	ifp = nb_running_get_entry(args->dnode, NULL, true);
990 	ri = ifp->info;
991 	XFREE(MTYPE_RIP_INTERFACE_STRING, ri->auth_str);
992 
993 	return NB_OK;
994 }
995 
996 /*
997  * XPath: /frr-interface:lib/interface/frr-ripd:rip/authentication-key-chain
998  */
lib_interface_rip_authentication_key_chain_modify(struct nb_cb_modify_args * args)999 int lib_interface_rip_authentication_key_chain_modify(
1000 	struct nb_cb_modify_args *args)
1001 {
1002 	struct interface *ifp;
1003 	struct rip_interface *ri;
1004 
1005 	if (args->event != NB_EV_APPLY)
1006 		return NB_OK;
1007 
1008 	ifp = nb_running_get_entry(args->dnode, NULL, true);
1009 	ri = ifp->info;
1010 	XFREE(MTYPE_RIP_INTERFACE_STRING, ri->key_chain);
1011 	ri->key_chain = XSTRDUP(MTYPE_RIP_INTERFACE_STRING,
1012 				yang_dnode_get_string(args->dnode, NULL));
1013 
1014 	return NB_OK;
1015 }
1016 
lib_interface_rip_authentication_key_chain_destroy(struct nb_cb_destroy_args * args)1017 int lib_interface_rip_authentication_key_chain_destroy(
1018 	struct nb_cb_destroy_args *args)
1019 {
1020 	struct interface *ifp;
1021 	struct rip_interface *ri;
1022 
1023 	if (args->event != NB_EV_APPLY)
1024 		return NB_OK;
1025 
1026 	ifp = nb_running_get_entry(args->dnode, NULL, true);
1027 	ri = ifp->info;
1028 	XFREE(MTYPE_RIP_INTERFACE_STRING, ri->key_chain);
1029 
1030 	return NB_OK;
1031 }
1032