]> git.proxmox.com Git - mirror_frr.git/blob - ripd/rip_interface.c
Merge pull request #13183 from Pdoijode/pdoijode/pim-json-changes
[mirror_frr.git] / ripd / rip_interface.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* Interface related function for RIP.
3 * Copyright (C) 1997, 98 Kunihiro Ishiguro <kunihiro@zebra.org>
4 */
5
6 #include <zebra.h>
7
8 #include "command.h"
9 #include "if.h"
10 #include "sockunion.h"
11 #include "prefix.h"
12 #include "memory.h"
13 #include "network.h"
14 #include "table.h"
15 #include "log.h"
16 #include "stream.h"
17 #include "frrevent.h"
18 #include "zclient.h"
19 #include "filter.h"
20 #include "sockopt.h"
21 #include "privs.h"
22 #include "lib_errors.h"
23 #include "northbound_cli.h"
24
25 #include "zebra/connected.h"
26
27 #include "ripd/ripd.h"
28 #include "ripd/rip_debug.h"
29 #include "ripd/rip_interface.h"
30
31 DEFINE_MTYPE_STATIC(RIPD, RIP_INTERFACE, "RIP interface");
32 DEFINE_MTYPE(RIPD, RIP_INTERFACE_STRING, "RIP Interface String");
33 DEFINE_HOOK(rip_ifaddr_add, (struct connected * ifc), (ifc));
34 DEFINE_HOOK(rip_ifaddr_del, (struct connected * ifc), (ifc));
35
36 /* static prototypes */
37 static void rip_enable_apply(struct interface *);
38 static void rip_passive_interface_apply(struct interface *);
39 static int rip_if_down(struct interface *ifp);
40 static int rip_enable_if_lookup(struct rip *rip, const char *ifname);
41 static int rip_enable_network_lookup2(struct connected *connected);
42 static void rip_enable_apply_all(struct rip *rip);
43
44 const struct message ri_version_msg[] = {{RI_RIP_VERSION_1, "1"},
45 {RI_RIP_VERSION_2, "2"},
46 {RI_RIP_VERSION_1_AND_2, "1 2"},
47 {RI_RIP_VERSION_NONE, "none"},
48 {0}};
49
50 /* Join to the RIP version 2 multicast group. */
51 static int ipv4_multicast_join(int sock, struct in_addr group,
52 struct in_addr ifa, ifindex_t ifindex)
53 {
54 int ret;
55
56 ret = setsockopt_ipv4_multicast(sock, IP_ADD_MEMBERSHIP, ifa,
57 group.s_addr, ifindex);
58
59 if (ret < 0)
60 zlog_info("can't setsockopt IP_ADD_MEMBERSHIP %s",
61 safe_strerror(errno));
62
63 return ret;
64 }
65
66 /* Leave from the RIP version 2 multicast group. */
67 static int ipv4_multicast_leave(int sock, struct in_addr group,
68 struct in_addr ifa, ifindex_t ifindex)
69 {
70 int ret;
71
72 ret = setsockopt_ipv4_multicast(sock, IP_DROP_MEMBERSHIP, ifa,
73 group.s_addr, ifindex);
74
75 if (ret < 0)
76 zlog_info("can't setsockopt IP_DROP_MEMBERSHIP");
77
78 return ret;
79 }
80
81 static void rip_interface_reset(struct rip_interface *);
82
83 /* Allocate new RIP's interface configuration. */
84 static struct rip_interface *rip_interface_new(void)
85 {
86 struct rip_interface *ri;
87
88 ri = XCALLOC(MTYPE_RIP_INTERFACE, sizeof(struct rip_interface));
89
90 rip_interface_reset(ri);
91
92 return ri;
93 }
94
95 void rip_interface_multicast_set(int sock, struct connected *connected)
96 {
97 struct in_addr addr;
98
99 assert(connected != NULL);
100
101 addr = CONNECTED_ID(connected)->u.prefix4;
102
103 if (setsockopt_ipv4_multicast_if(sock, addr, connected->ifp->ifindex)
104 < 0) {
105 zlog_warn(
106 "Can't setsockopt IP_MULTICAST_IF on fd %d to ifindex %d for interface %s",
107 sock, connected->ifp->ifindex, connected->ifp->name);
108 }
109
110 return;
111 }
112
113 /* Send RIP request packet to specified interface. */
114 static void rip_request_interface_send(struct interface *ifp, uint8_t version)
115 {
116 struct sockaddr_in to;
117
118 /* RIPv2 support multicast. */
119 if (version == RIPv2 && if_is_multicast(ifp)) {
120
121 if (IS_RIP_DEBUG_EVENT)
122 zlog_debug("multicast request on %s", ifp->name);
123
124 rip_request_send(NULL, ifp, version, NULL);
125 return;
126 }
127
128 /* RIPv1 and non multicast interface. */
129 if (if_is_pointopoint(ifp) || if_is_broadcast(ifp)) {
130 struct listnode *cnode, *cnnode;
131 struct connected *connected;
132
133 if (IS_RIP_DEBUG_EVENT)
134 zlog_debug("broadcast request to %s", ifp->name);
135
136 for (ALL_LIST_ELEMENTS(ifp->connected, cnode, cnnode,
137 connected)) {
138 if (connected->address->family != AF_INET)
139 continue;
140
141 memset(&to, 0, sizeof(struct sockaddr_in));
142 to.sin_port = htons(RIP_PORT_DEFAULT);
143 if (connected->destination)
144 /* use specified broadcast or peer
145 * destination addr */
146 to.sin_addr = connected->destination->u.prefix4;
147 else if (connected->address->prefixlen
148 < IPV4_MAX_BITLEN)
149 /* calculate the appropriate broadcast
150 * address */
151 to.sin_addr.s_addr = ipv4_broadcast_addr(
152 connected->address->u.prefix4.s_addr,
153 connected->address->prefixlen);
154 else
155 /* do not know where to send the packet
156 */
157 continue;
158
159 if (IS_RIP_DEBUG_EVENT)
160 zlog_debug("SEND request to %pI4",
161 &to.sin_addr);
162
163 rip_request_send(&to, ifp, version, connected);
164 }
165 }
166 }
167
168 /* This will be executed when interface goes up. */
169 static void rip_request_interface(struct interface *ifp)
170 {
171 struct rip_interface *ri;
172 int vsend;
173
174 /* In default ripd doesn't send RIP_REQUEST to the loopback interface.
175 */
176 if (if_is_loopback(ifp))
177 return;
178
179 /* If interface is down, don't send RIP packet. */
180 if (!if_is_operative(ifp))
181 return;
182
183 /* Fetch RIP interface information. */
184 ri = ifp->info;
185
186 /* If there is no version configuration in the interface,
187 use rip's version setting. */
188 vsend = ((ri->ri_send == RI_RIP_UNSPEC) ? ri->rip->version_send
189 : ri->ri_send);
190 if (vsend & RIPv1)
191 rip_request_interface_send(ifp, RIPv1);
192 if (vsend & RIPv2)
193 rip_request_interface_send(ifp, RIPv2);
194 }
195
196 /* Multicast packet receive socket. */
197 static int rip_multicast_join(struct interface *ifp, int sock)
198 {
199 struct listnode *cnode;
200 struct connected *ifc;
201
202 if (if_is_operative(ifp) && if_is_multicast(ifp)) {
203 if (IS_RIP_DEBUG_EVENT)
204 zlog_debug("multicast join at %s", ifp->name);
205
206 for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, ifc)) {
207 struct prefix_ipv4 *p;
208 struct in_addr group;
209
210 p = (struct prefix_ipv4 *)ifc->address;
211
212 if (p->family != AF_INET)
213 continue;
214
215 group.s_addr = htonl(INADDR_RIP_GROUP);
216 if (ipv4_multicast_join(sock, group, p->prefix,
217 ifp->ifindex)
218 < 0)
219 return -1;
220 else
221 return 0;
222 }
223 }
224 return 0;
225 }
226
227 /* Leave from multicast group. */
228 static void rip_multicast_leave(struct interface *ifp, int sock)
229 {
230 struct listnode *cnode;
231 struct connected *connected;
232
233 if (if_is_up(ifp) && if_is_multicast(ifp)) {
234 if (IS_RIP_DEBUG_EVENT)
235 zlog_debug("multicast leave from %s", ifp->name);
236
237 for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, connected)) {
238 struct prefix_ipv4 *p;
239 struct in_addr group;
240
241 p = (struct prefix_ipv4 *)connected->address;
242
243 if (p->family != AF_INET)
244 continue;
245
246 group.s_addr = htonl(INADDR_RIP_GROUP);
247 if (ipv4_multicast_leave(sock, group, p->prefix,
248 ifp->ifindex)
249 == 0)
250 return;
251 }
252 }
253 }
254
255 /* Is there and address on interface that I could use ? */
256 static int rip_if_ipv4_address_check(struct interface *ifp)
257 {
258 struct listnode *nn;
259 struct connected *connected;
260 int count = 0;
261
262 for (ALL_LIST_ELEMENTS_RO(ifp->connected, nn, connected)) {
263 struct prefix *p;
264
265 p = connected->address;
266
267 if (p->family == AF_INET)
268 count++;
269 }
270
271 return count;
272 }
273
274
275 /* Does this address belongs to me ? */
276 int if_check_address(struct rip *rip, struct in_addr addr)
277 {
278 struct interface *ifp;
279
280 FOR_ALL_INTERFACES (rip->vrf, ifp) {
281 struct listnode *cnode;
282 struct connected *connected;
283
284 for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, connected)) {
285 struct prefix_ipv4 *p;
286
287 p = (struct prefix_ipv4 *)connected->address;
288
289 if (p->family != AF_INET)
290 continue;
291
292 if (IPV4_ADDR_CMP(&p->prefix, &addr) == 0)
293 return 1;
294 }
295 }
296 return 0;
297 }
298
299 /* Interface link down message processing. */
300 static int rip_ifp_down(struct interface *ifp)
301 {
302 rip_interface_sync(ifp);
303 rip_if_down(ifp);
304
305 if (IS_RIP_DEBUG_ZEBRA)
306 zlog_debug(
307 "interface %s vrf %s(%u) index %d flags %llx metric %d mtu %d is down",
308 ifp->name, ifp->vrf->name, ifp->vrf->vrf_id,
309 ifp->ifindex, (unsigned long long)ifp->flags,
310 ifp->metric, ifp->mtu);
311
312 return 0;
313 }
314
315 /* Interface link up message processing */
316 static int rip_ifp_up(struct interface *ifp)
317 {
318 if (IS_RIP_DEBUG_ZEBRA)
319 zlog_debug(
320 "interface %s vrf %s(%u) index %d flags %#llx metric %d mtu %d is up",
321 ifp->name, ifp->vrf->name, ifp->vrf->vrf_id,
322 ifp->ifindex, (unsigned long long)ifp->flags,
323 ifp->metric, ifp->mtu);
324
325 rip_interface_sync(ifp);
326
327 /* Check if this interface is RIP enabled or not.*/
328 rip_enable_apply(ifp);
329
330 /* Check for a passive interface */
331 rip_passive_interface_apply(ifp);
332
333 /* Apply distribute list to the all interface. */
334 rip_distribute_update_interface(ifp);
335
336 return 0;
337 }
338
339 /* Interface addition message from zebra. */
340 static int rip_ifp_create(struct interface *ifp)
341 {
342 rip_interface_sync(ifp);
343
344 if (IS_RIP_DEBUG_ZEBRA)
345 zlog_debug(
346 "interface add %s vrf %s(%u) index %d flags %#llx metric %d mtu %d",
347 ifp->name, ifp->vrf->name, ifp->vrf->vrf_id,
348 ifp->ifindex, (unsigned long long)ifp->flags,
349 ifp->metric, ifp->mtu);
350
351 /* Check if this interface is RIP enabled or not.*/
352 rip_enable_apply(ifp);
353
354 /* Check for a passive interface */
355 rip_passive_interface_apply(ifp);
356
357 /* Apply distribute list to the all interface. */
358 rip_distribute_update_interface(ifp);
359
360 /* rip_request_neighbor_all (); */
361
362 /* Check interface routemap. */
363 rip_if_rmap_update_interface(ifp);
364
365 return 0;
366 }
367
368 static int rip_ifp_destroy(struct interface *ifp)
369 {
370 rip_interface_sync(ifp);
371 if (if_is_up(ifp)) {
372 rip_if_down(ifp);
373 }
374
375 if (IS_RIP_DEBUG_ZEBRA)
376 zlog_debug(
377 "interface delete %s vrf %s(%u) index %d flags %#llx metric %d mtu %d",
378 ifp->name, ifp->vrf->name, ifp->vrf->vrf_id,
379 ifp->ifindex, (unsigned long long)ifp->flags,
380 ifp->metric, ifp->mtu);
381
382 return 0;
383 }
384
385 /* VRF update for an interface. */
386 int rip_interface_vrf_update(ZAPI_CALLBACK_ARGS)
387 {
388 struct interface *ifp;
389 vrf_id_t new_vrf_id;
390
391 ifp = zebra_interface_vrf_update_read(zclient->ibuf, vrf_id,
392 &new_vrf_id);
393 if (!ifp)
394 return 0;
395
396 if (IS_RIP_DEBUG_ZEBRA) {
397 struct vrf *nvrf = vrf_lookup_by_id(new_vrf_id);
398
399 zlog_debug("interface %s VRF change vrf %s(%u) new vrf %s(%u)",
400 ifp->name, ifp->vrf->name, vrf_id, VRF_LOGNAME(nvrf),
401 new_vrf_id);
402 }
403
404 if_update_to_new_vrf(ifp, new_vrf_id);
405 rip_interface_sync(ifp);
406
407 return 0;
408 }
409
410 static void rip_interface_clean(struct rip_interface *ri)
411 {
412 ri->enable_network = 0;
413 ri->enable_interface = 0;
414 ri->running = 0;
415
416 EVENT_OFF(ri->t_wakeup);
417 }
418
419 void rip_interfaces_clean(struct rip *rip)
420 {
421 struct interface *ifp;
422
423 FOR_ALL_INTERFACES (rip->vrf, ifp)
424 rip_interface_clean(ifp->info);
425 }
426
427 static void rip_interface_reset(struct rip_interface *ri)
428 {
429 ri->auth_type = yang_get_default_enum("%s/authentication-scheme/mode",
430 RIP_IFACE);
431 ri->md5_auth_len = yang_get_default_enum(
432 "%s/authentication-scheme/md5-auth-length", RIP_IFACE);
433
434 /* Set default split-horizon behavior. If the interface is Frame
435 Relay or SMDS is enabled, the default value for split-horizon is
436 off. But currently Zebra does detect Frame Relay or SMDS
437 interface. So all interface is set to split horizon. */
438 ri->split_horizon =
439 yang_get_default_enum("%s/split-horizon", RIP_IFACE);
440
441 ri->ri_send = yang_get_default_enum("%s/version-send", RIP_IFACE);
442 ri->ri_receive = yang_get_default_enum("%s/version-receive", RIP_IFACE);
443 ri->v2_broadcast = yang_get_default_bool("%s/v2-broadcast", RIP_IFACE);
444
445 XFREE(MTYPE_RIP_INTERFACE_STRING, ri->auth_str);
446
447 XFREE(MTYPE_RIP_INTERFACE_STRING, ri->key_chain);
448
449 ri->list[RIP_FILTER_IN] = NULL;
450 ri->list[RIP_FILTER_OUT] = NULL;
451
452 ri->prefix[RIP_FILTER_IN] = NULL;
453 ri->prefix[RIP_FILTER_OUT] = NULL;
454
455 ri->recv_badpackets = 0;
456 ri->recv_badroutes = 0;
457 ri->sent_updates = 0;
458
459 ri->passive = 0;
460
461 rip_interface_clean(ri);
462 }
463
464 int rip_if_down(struct interface *ifp)
465 {
466 struct rip *rip;
467 struct route_node *rp;
468 struct rip_info *rinfo;
469 struct rip_interface *ri = NULL;
470 struct list *list = NULL;
471 struct listnode *listnode = NULL, *nextnode = NULL;
472
473 ri = ifp->info;
474
475 EVENT_OFF(ri->t_wakeup);
476
477 rip = ri->rip;
478 if (rip) {
479 for (rp = route_top(rip->table); rp; rp = route_next(rp))
480 if ((list = rp->info) != NULL)
481 for (ALL_LIST_ELEMENTS(list, listnode, nextnode,
482 rinfo))
483 if (rinfo->nh.ifindex == ifp->ifindex)
484 rip_ecmp_delete(rip, rinfo);
485
486 if (ri->running) {
487 if (IS_RIP_DEBUG_EVENT)
488 zlog_debug("turn off %s", ifp->name);
489
490 /* Leave from multicast group. */
491 rip_multicast_leave(ifp, rip->sock);
492
493 ri->running = 0;
494 }
495 }
496
497 return 0;
498 }
499
500 static void rip_apply_address_add(struct connected *ifc)
501 {
502 struct rip_interface *ri = ifc->ifp->info;
503 struct rip *rip = ri->rip;
504 struct prefix_ipv4 address;
505 struct nexthop nh;
506 struct prefix *p;
507
508 if (!rip)
509 return;
510
511 if (!if_is_up(ifc->ifp))
512 return;
513
514 p = ifc->address;
515
516 memset(&address, 0, sizeof(address));
517 memset(&nh, 0, sizeof(nh));
518
519 address.family = p->family;
520 address.prefix = p->u.prefix4;
521 address.prefixlen = p->prefixlen;
522 apply_mask_ipv4(&address);
523
524 nh.ifindex = ifc->ifp->ifindex;
525 nh.type = NEXTHOP_TYPE_IFINDEX;
526
527 /* Check if this interface is RIP enabled or not
528 or Check if this address's prefix is RIP enabled */
529 if ((rip_enable_if_lookup(rip, ifc->ifp->name) >= 0)
530 || (rip_enable_network_lookup2(ifc) >= 0))
531 rip_redistribute_add(rip, ZEBRA_ROUTE_CONNECT,
532 RIP_ROUTE_INTERFACE, &address, &nh, 0, 0,
533 0);
534 }
535
536 int rip_interface_address_add(ZAPI_CALLBACK_ARGS)
537 {
538 struct connected *ifc;
539 struct prefix *p;
540
541 ifc = zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD,
542 zclient->ibuf, vrf_id);
543
544 if (ifc == NULL)
545 return 0;
546
547 p = ifc->address;
548
549 if (p->family == AF_INET) {
550 if (IS_RIP_DEBUG_ZEBRA)
551 zlog_debug("connected address %pFX is added", p);
552
553 rip_enable_apply(ifc->ifp);
554 /* Check if this prefix needs to be redistributed */
555 rip_apply_address_add(ifc);
556
557 hook_call(rip_ifaddr_add, ifc);
558 }
559
560 return 0;
561 }
562
563 static void rip_apply_address_del(struct connected *ifc)
564 {
565 struct rip_interface *ri = ifc->ifp->info;
566 struct rip *rip = ri->rip;
567 struct prefix_ipv4 address;
568 struct prefix *p;
569
570 if (!rip)
571 return;
572
573 if (!if_is_up(ifc->ifp))
574 return;
575
576 p = ifc->address;
577
578 memset(&address, 0, sizeof(address));
579 address.family = p->family;
580 address.prefix = p->u.prefix4;
581 address.prefixlen = p->prefixlen;
582 apply_mask_ipv4(&address);
583
584 rip_redistribute_delete(rip, ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE,
585 &address, ifc->ifp->ifindex);
586 }
587
588 int rip_interface_address_delete(ZAPI_CALLBACK_ARGS)
589 {
590 struct connected *ifc;
591 struct prefix *p;
592
593 ifc = zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE,
594 zclient->ibuf, vrf_id);
595
596 if (ifc) {
597 p = ifc->address;
598 if (p->family == AF_INET) {
599 if (IS_RIP_DEBUG_ZEBRA)
600 zlog_debug("connected address %pFX is deleted",
601 p);
602
603 hook_call(rip_ifaddr_del, ifc);
604
605 /* Chech whether this prefix needs to be removed */
606 rip_apply_address_del(ifc);
607 }
608
609 connected_free(&ifc);
610 }
611
612 return 0;
613 }
614
615 /* Check interface is enabled by network statement. */
616 /* Check whether the interface has at least a connected prefix that
617 * is within the ripng_enable_network table. */
618 static int rip_enable_network_lookup_if(struct interface *ifp)
619 {
620 struct rip_interface *ri = ifp->info;
621 struct rip *rip = ri->rip;
622 struct listnode *node, *nnode;
623 struct connected *connected;
624 struct prefix_ipv4 address;
625
626 if (!rip)
627 return -1;
628
629 for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, connected)) {
630 struct prefix *p;
631 struct route_node *n;
632
633 p = connected->address;
634
635 if (p->family == AF_INET) {
636 address.family = AF_INET;
637 address.prefix = p->u.prefix4;
638 address.prefixlen = IPV4_MAX_BITLEN;
639
640 n = route_node_match(rip->enable_network,
641 (struct prefix *)&address);
642 if (n) {
643 route_unlock_node(n);
644 return 1;
645 }
646 }
647 }
648 return -1;
649 }
650
651 /* Check whether connected is within the ripng_enable_network table. */
652 static int rip_enable_network_lookup2(struct connected *connected)
653 {
654 struct rip_interface *ri = connected->ifp->info;
655 struct rip *rip = ri->rip;
656 struct prefix_ipv4 address;
657 struct prefix *p;
658
659 p = connected->address;
660
661 if (p->family == AF_INET) {
662 struct route_node *node;
663
664 address.family = p->family;
665 address.prefix = p->u.prefix4;
666 address.prefixlen = IPV4_MAX_BITLEN;
667
668 /* LPM on p->family, p->u.prefix4/IPV4_MAX_BITLEN within
669 * rip->enable_network */
670 node = route_node_match(rip->enable_network,
671 (struct prefix *)&address);
672
673 if (node) {
674 route_unlock_node(node);
675 return 1;
676 }
677 }
678
679 return -1;
680 }
681 /* Add RIP enable network. */
682 int rip_enable_network_add(struct rip *rip, struct prefix *p)
683 {
684 struct route_node *node;
685
686 node = route_node_get(rip->enable_network, p);
687
688 if (node->info) {
689 route_unlock_node(node);
690 return NB_ERR_INCONSISTENCY;
691 } else
692 node->info = (void *)1;
693
694 /* XXX: One should find a better solution than a generic one */
695 rip_enable_apply_all(rip);
696
697 return NB_OK;
698 }
699
700 /* Delete RIP enable network. */
701 int rip_enable_network_delete(struct rip *rip, struct prefix *p)
702 {
703 struct route_node *node;
704
705 node = route_node_lookup(rip->enable_network, p);
706 if (node) {
707 node->info = NULL;
708
709 /* Unlock info lock. */
710 route_unlock_node(node);
711
712 /* Unlock lookup lock. */
713 route_unlock_node(node);
714
715 /* XXX: One should find a better solution than a generic one */
716 rip_enable_apply_all(rip);
717
718 return NB_OK;
719 }
720
721 return NB_ERR_INCONSISTENCY;
722 }
723
724 /* Check interface is enabled by ifname statement. */
725 static int rip_enable_if_lookup(struct rip *rip, const char *ifname)
726 {
727 unsigned int i;
728 char *str;
729
730 if (!rip)
731 return -1;
732
733 for (i = 0; i < vector_active(rip->enable_interface); i++)
734 if ((str = vector_slot(rip->enable_interface, i)) != NULL)
735 if (strcmp(str, ifname) == 0)
736 return i;
737 return -1;
738 }
739
740 /* Add interface to rip_enable_if. */
741 int rip_enable_if_add(struct rip *rip, const char *ifname)
742 {
743 int ret;
744
745 ret = rip_enable_if_lookup(rip, ifname);
746 if (ret >= 0)
747 return NB_ERR_INCONSISTENCY;
748
749 vector_set(rip->enable_interface,
750 XSTRDUP(MTYPE_RIP_INTERFACE_STRING, ifname));
751
752 rip_enable_apply_all(rip); /* TODOVJ */
753
754 return NB_OK;
755 }
756
757 /* Delete interface from rip_enable_if. */
758 int rip_enable_if_delete(struct rip *rip, const char *ifname)
759 {
760 int index;
761 char *str;
762
763 index = rip_enable_if_lookup(rip, ifname);
764 if (index < 0)
765 return NB_ERR_INCONSISTENCY;
766
767 str = vector_slot(rip->enable_interface, index);
768 XFREE(MTYPE_RIP_INTERFACE_STRING, str);
769 vector_unset(rip->enable_interface, index);
770
771 rip_enable_apply_all(rip); /* TODOVJ */
772
773 return NB_OK;
774 }
775
776 /* Join to multicast group and send request to the interface. */
777 static void rip_interface_wakeup(struct event *t)
778 {
779 struct interface *ifp;
780 struct rip_interface *ri;
781
782 /* Get interface. */
783 ifp = EVENT_ARG(t);
784
785 ri = ifp->info;
786
787 /* Join to multicast group. */
788 if (rip_multicast_join(ifp, ri->rip->sock) < 0) {
789 flog_err_sys(EC_LIB_SOCKET,
790 "multicast join failed, interface %s not running",
791 ifp->name);
792 return;
793 }
794
795 /* Set running flag. */
796 ri->running = 1;
797
798 /* Send RIP request to the interface. */
799 rip_request_interface(ifp);
800 }
801
802 static void rip_connect_set(struct interface *ifp, int set)
803 {
804 struct rip_interface *ri = ifp->info;
805 struct rip *rip = ri->rip;
806 struct listnode *node, *nnode;
807 struct connected *connected;
808 struct prefix_ipv4 address;
809 struct nexthop nh;
810
811 memset(&nh, 0, sizeof(nh));
812
813 for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, connected)) {
814 struct prefix *p;
815 p = connected->address;
816
817 if (p->family != AF_INET)
818 continue;
819
820 address.family = AF_INET;
821 address.prefix = p->u.prefix4;
822 address.prefixlen = p->prefixlen;
823 apply_mask_ipv4(&address);
824
825 nh.ifindex = connected->ifp->ifindex;
826 nh.type = NEXTHOP_TYPE_IFINDEX;
827 if (set) {
828 /* Check once more whether this prefix is within a
829 * "network IF_OR_PREF" one */
830 if ((rip_enable_if_lookup(rip, connected->ifp->name)
831 >= 0)
832 || (rip_enable_network_lookup2(connected) >= 0))
833 rip_redistribute_add(rip, ZEBRA_ROUTE_CONNECT,
834 RIP_ROUTE_INTERFACE,
835 &address, &nh, 0, 0, 0);
836 } else {
837 rip_redistribute_delete(rip, ZEBRA_ROUTE_CONNECT,
838 RIP_ROUTE_INTERFACE, &address,
839 connected->ifp->ifindex);
840 if (rip_redistribute_check(rip, ZEBRA_ROUTE_CONNECT))
841 rip_redistribute_add(rip, ZEBRA_ROUTE_CONNECT,
842 RIP_ROUTE_REDISTRIBUTE,
843 &address, &nh, 0, 0, 0);
844 }
845 }
846 }
847
848 /* Update interface status. */
849 void rip_enable_apply(struct interface *ifp)
850 {
851 int ret;
852 struct rip_interface *ri = NULL;
853
854 /* Check interface. */
855 if (!if_is_operative(ifp))
856 return;
857
858 ri = ifp->info;
859
860 /* Check network configuration. */
861 ret = rip_enable_network_lookup_if(ifp);
862
863 /* If the interface is matched. */
864 if (ret > 0)
865 ri->enable_network = 1;
866 else
867 ri->enable_network = 0;
868
869 /* Check interface name configuration. */
870 ret = rip_enable_if_lookup(ri->rip, ifp->name);
871 if (ret >= 0)
872 ri->enable_interface = 1;
873 else
874 ri->enable_interface = 0;
875
876 /* any interface MUST have an IPv4 address */
877 if (!rip_if_ipv4_address_check(ifp)) {
878 ri->enable_network = 0;
879 ri->enable_interface = 0;
880 }
881
882 /* Update running status of the interface. */
883 if (ri->enable_network || ri->enable_interface) {
884 if (IS_RIP_DEBUG_EVENT)
885 zlog_debug("turn on %s", ifp->name);
886
887 /* Add interface wake up thread. */
888 event_add_timer(master, rip_interface_wakeup, ifp, 1,
889 &ri->t_wakeup);
890 rip_connect_set(ifp, 1);
891 } else if (ri->running) {
892 /* Might as well clean up the route table as well
893 * rip_if_down sets to 0 ri->running, and displays "turn
894 *off %s"
895 **/
896 rip_if_down(ifp);
897
898 rip_connect_set(ifp, 0);
899 }
900 }
901
902 /* Apply network configuration to all interface. */
903 static void rip_enable_apply_all(struct rip *rip)
904 {
905 struct interface *ifp;
906
907 /* Check each interface. */
908 FOR_ALL_INTERFACES (rip->vrf, ifp)
909 rip_enable_apply(ifp);
910 }
911
912 int rip_neighbor_lookup(struct rip *rip, struct sockaddr_in *from)
913 {
914 struct prefix_ipv4 p;
915 struct route_node *node;
916
917 memset(&p, 0, sizeof(p));
918 p.family = AF_INET;
919 p.prefix = from->sin_addr;
920 p.prefixlen = IPV4_MAX_BITLEN;
921
922 node = route_node_lookup(rip->neighbor, (struct prefix *)&p);
923 if (node) {
924 route_unlock_node(node);
925 return 1;
926 }
927 return 0;
928 }
929
930 /* Add new RIP neighbor to the neighbor tree. */
931 int rip_neighbor_add(struct rip *rip, struct prefix_ipv4 *p)
932 {
933 struct route_node *node;
934
935 node = route_node_get(rip->neighbor, (struct prefix *)p);
936
937 if (node->info)
938 return NB_ERR_INCONSISTENCY;
939
940 node->info = rip->neighbor;
941
942 return NB_OK;
943 }
944
945 /* Delete RIP neighbor from the neighbor tree. */
946 int rip_neighbor_delete(struct rip *rip, struct prefix_ipv4 *p)
947 {
948 struct route_node *node;
949
950 /* Lock for look up. */
951 node = route_node_lookup(rip->neighbor, (struct prefix *)p);
952 if (!node)
953 return NB_ERR_INCONSISTENCY;
954
955 node->info = NULL;
956
957 /* Unlock lookup lock. */
958 route_unlock_node(node);
959
960 /* Unlock real neighbor information lock. */
961 route_unlock_node(node);
962
963 return NB_OK;
964 }
965
966 /* Clear all network and neighbor configuration. */
967 void rip_clean_network(struct rip *rip)
968 {
969 unsigned int i;
970 char *str;
971 struct route_node *rn;
972
973 /* rip->enable_network. */
974 for (rn = route_top(rip->enable_network); rn; rn = route_next(rn))
975 if (rn->info) {
976 rn->info = NULL;
977 route_unlock_node(rn);
978 }
979
980 /* rip->enable_interface. */
981 for (i = 0; i < vector_active(rip->enable_interface); i++)
982 if ((str = vector_slot(rip->enable_interface, i)) != NULL) {
983 XFREE(MTYPE_RIP_INTERFACE_STRING, str);
984 vector_slot(rip->enable_interface, i) = NULL;
985 }
986 }
987
988 /* Utility function for looking up passive interface settings. */
989 static int rip_passive_nondefault_lookup(struct rip *rip, const char *ifname)
990 {
991 unsigned int i;
992 char *str;
993
994 for (i = 0; i < vector_active(rip->passive_nondefault); i++)
995 if ((str = vector_slot(rip->passive_nondefault, i)) != NULL)
996 if (strcmp(str, ifname) == 0)
997 return i;
998 return -1;
999 }
1000
1001 static void rip_passive_interface_apply(struct interface *ifp)
1002 {
1003 struct rip *rip;
1004 struct rip_interface *ri;
1005
1006 ri = ifp->info;
1007 rip = ri->rip;
1008 if (rip == NULL)
1009 return;
1010
1011 ri->passive = ((rip_passive_nondefault_lookup(rip, ifp->name) < 0)
1012 ? rip->passive_default
1013 : !rip->passive_default);
1014
1015 if (IS_RIP_DEBUG_ZEBRA)
1016 zlog_debug("interface %s: passive = %d", ifp->name,
1017 ri->passive);
1018 }
1019
1020 static void rip_passive_interface_apply_all(struct rip *rip)
1021 {
1022 struct interface *ifp;
1023
1024 FOR_ALL_INTERFACES (rip->vrf, ifp)
1025 rip_passive_interface_apply(ifp);
1026 }
1027
1028 /* Passive interface. */
1029 int rip_passive_nondefault_set(struct rip *rip, const char *ifname)
1030 {
1031 if (rip_passive_nondefault_lookup(rip, ifname) >= 0)
1032 /*
1033 * Don't return an error, this can happen after changing
1034 * 'passive-default'.
1035 */
1036 return NB_OK;
1037
1038 vector_set(rip->passive_nondefault,
1039 XSTRDUP(MTYPE_RIP_INTERFACE_STRING, ifname));
1040
1041 rip_passive_interface_apply_all(rip);
1042
1043 return NB_OK;
1044 }
1045
1046 int rip_passive_nondefault_unset(struct rip *rip, const char *ifname)
1047 {
1048 int i;
1049 char *str;
1050
1051 i = rip_passive_nondefault_lookup(rip, ifname);
1052 if (i < 0)
1053 /*
1054 * Don't return an error, this can happen after changing
1055 * 'passive-default'.
1056 */
1057 return NB_OK;
1058
1059 str = vector_slot(rip->passive_nondefault, i);
1060 XFREE(MTYPE_RIP_INTERFACE_STRING, str);
1061 vector_unset(rip->passive_nondefault, i);
1062
1063 rip_passive_interface_apply_all(rip);
1064
1065 return NB_OK;
1066 }
1067
1068 /* Free all configured RIP passive-interface settings. */
1069 void rip_passive_nondefault_clean(struct rip *rip)
1070 {
1071 unsigned int i;
1072 char *str;
1073
1074 for (i = 0; i < vector_active(rip->passive_nondefault); i++)
1075 if ((str = vector_slot(rip->passive_nondefault, i)) != NULL) {
1076 XFREE(MTYPE_RIP_INTERFACE_STRING, str);
1077 vector_slot(rip->passive_nondefault, i) = NULL;
1078 }
1079 rip_passive_interface_apply_all(rip);
1080 }
1081
1082 int rip_show_network_config(struct vty *vty, struct rip *rip)
1083 {
1084 unsigned int i;
1085 char *ifname;
1086 struct route_node *node;
1087
1088 /* Network type RIP enable interface statement. */
1089 for (node = route_top(rip->enable_network); node;
1090 node = route_next(node))
1091 if (node->info)
1092 vty_out(vty, " %pFX\n", &node->p);
1093
1094 /* Interface name RIP enable statement. */
1095 for (i = 0; i < vector_active(rip->enable_interface); i++)
1096 if ((ifname = vector_slot(rip->enable_interface, i)) != NULL)
1097 vty_out(vty, " %s\n", ifname);
1098
1099 /* RIP neighbors listing. */
1100 for (node = route_top(rip->neighbor); node; node = route_next(node))
1101 if (node->info)
1102 vty_out(vty, " %pI4\n", &node->p.u.prefix4);
1103
1104 return 0;
1105 }
1106
1107 void rip_interface_sync(struct interface *ifp)
1108 {
1109 struct rip_interface *ri;
1110
1111 ri = ifp->info;
1112 if (ri)
1113 ri->rip = ifp->vrf->info;
1114 }
1115
1116 /* Called when interface structure allocated. */
1117 static int rip_interface_new_hook(struct interface *ifp)
1118 {
1119 ifp->info = rip_interface_new();
1120 rip_interface_sync(ifp);
1121
1122 return 0;
1123 }
1124
1125 /* Called when interface structure deleted. */
1126 static int rip_interface_delete_hook(struct interface *ifp)
1127 {
1128 rip_interface_reset(ifp->info);
1129 XFREE(MTYPE_RIP_INTERFACE, ifp->info);
1130 return 0;
1131 }
1132
1133 /* Allocate and initialize interface vector. */
1134 void rip_if_init(void)
1135 {
1136 /* Default initial size of interface vector. */
1137 hook_register_prio(if_add, 0, rip_interface_new_hook);
1138 hook_register_prio(if_del, 0, rip_interface_delete_hook);
1139
1140 /* Install interface node. */
1141 if_cmd_init_default();
1142 if_zapi_callbacks(rip_ifp_create, rip_ifp_up,
1143 rip_ifp_down, rip_ifp_destroy);
1144 }