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