]> git.proxmox.com Git - mirror_frr.git/blob - ripd/rip_interface.c
Merge pull request #13354 from zmw12306/parse_request_subtlv
[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 XFREE(MTYPE_TMP, ri->bfd.profile);
461
462 rip_interface_clean(ri);
463 }
464
465 int rip_if_down(struct interface *ifp)
466 {
467 struct rip *rip;
468 struct route_node *rp;
469 struct rip_info *rinfo;
470 struct rip_interface *ri = NULL;
471 struct list *list = NULL;
472 struct listnode *listnode = NULL, *nextnode = NULL;
473
474 ri = ifp->info;
475
476 EVENT_OFF(ri->t_wakeup);
477
478 rip = ri->rip;
479 if (rip) {
480 for (rp = route_top(rip->table); rp; rp = route_next(rp))
481 if ((list = rp->info) != NULL)
482 for (ALL_LIST_ELEMENTS(list, listnode, nextnode,
483 rinfo))
484 if (rinfo->nh.ifindex == ifp->ifindex)
485 rip_ecmp_delete(rip, rinfo);
486
487 if (ri->running) {
488 if (IS_RIP_DEBUG_EVENT)
489 zlog_debug("turn off %s", ifp->name);
490
491 /* Leave from multicast group. */
492 rip_multicast_leave(ifp, rip->sock);
493
494 ri->running = 0;
495 }
496 }
497
498 return 0;
499 }
500
501 static void rip_apply_address_add(struct connected *ifc)
502 {
503 struct rip_interface *ri = ifc->ifp->info;
504 struct rip *rip = ri->rip;
505 struct prefix_ipv4 address;
506 struct nexthop nh;
507 struct prefix *p;
508
509 if (!rip)
510 return;
511
512 if (!if_is_up(ifc->ifp))
513 return;
514
515 p = ifc->address;
516
517 memset(&address, 0, sizeof(address));
518 memset(&nh, 0, sizeof(nh));
519
520 address.family = p->family;
521 address.prefix = p->u.prefix4;
522 address.prefixlen = p->prefixlen;
523 apply_mask_ipv4(&address);
524
525 nh.ifindex = ifc->ifp->ifindex;
526 nh.type = NEXTHOP_TYPE_IFINDEX;
527
528 /* Check if this interface is RIP enabled or not
529 or Check if this address's prefix is RIP enabled */
530 if ((rip_enable_if_lookup(rip, ifc->ifp->name) >= 0)
531 || (rip_enable_network_lookup2(ifc) >= 0))
532 rip_redistribute_add(rip, ZEBRA_ROUTE_CONNECT,
533 RIP_ROUTE_INTERFACE, &address, &nh, 0, 0,
534 0);
535 }
536
537 int rip_interface_address_add(ZAPI_CALLBACK_ARGS)
538 {
539 struct connected *ifc;
540 struct prefix *p;
541
542 ifc = zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD,
543 zclient->ibuf, vrf_id);
544
545 if (ifc == NULL)
546 return 0;
547
548 p = ifc->address;
549
550 if (p->family == AF_INET) {
551 if (IS_RIP_DEBUG_ZEBRA)
552 zlog_debug("connected address %pFX is added", p);
553
554 rip_enable_apply(ifc->ifp);
555 /* Check if this prefix needs to be redistributed */
556 rip_apply_address_add(ifc);
557
558 hook_call(rip_ifaddr_add, ifc);
559 }
560
561 return 0;
562 }
563
564 static void rip_apply_address_del(struct connected *ifc)
565 {
566 struct rip_interface *ri = ifc->ifp->info;
567 struct rip *rip = ri->rip;
568 struct prefix_ipv4 address;
569 struct prefix *p;
570
571 if (!rip)
572 return;
573
574 if (!if_is_up(ifc->ifp))
575 return;
576
577 p = ifc->address;
578
579 memset(&address, 0, sizeof(address));
580 address.family = p->family;
581 address.prefix = p->u.prefix4;
582 address.prefixlen = p->prefixlen;
583 apply_mask_ipv4(&address);
584
585 rip_redistribute_delete(rip, ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE,
586 &address, ifc->ifp->ifindex);
587 }
588
589 int rip_interface_address_delete(ZAPI_CALLBACK_ARGS)
590 {
591 struct connected *ifc;
592 struct prefix *p;
593
594 ifc = zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE,
595 zclient->ibuf, vrf_id);
596
597 if (ifc) {
598 p = ifc->address;
599 if (p->family == AF_INET) {
600 if (IS_RIP_DEBUG_ZEBRA)
601 zlog_debug("connected address %pFX is deleted",
602 p);
603
604 hook_call(rip_ifaddr_del, ifc);
605
606 /* Chech whether this prefix needs to be removed */
607 rip_apply_address_del(ifc);
608 }
609
610 connected_free(&ifc);
611 }
612
613 return 0;
614 }
615
616 /* Check interface is enabled by network statement. */
617 /* Check whether the interface has at least a connected prefix that
618 * is within the ripng_enable_network table. */
619 static int rip_enable_network_lookup_if(struct interface *ifp)
620 {
621 struct rip_interface *ri = ifp->info;
622 struct rip *rip = ri->rip;
623 struct listnode *node, *nnode;
624 struct connected *connected;
625 struct prefix_ipv4 address;
626
627 if (!rip)
628 return -1;
629
630 for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, connected)) {
631 struct prefix *p;
632 struct route_node *n;
633
634 p = connected->address;
635
636 if (p->family == AF_INET) {
637 address.family = AF_INET;
638 address.prefix = p->u.prefix4;
639 address.prefixlen = IPV4_MAX_BITLEN;
640
641 n = route_node_match(rip->enable_network,
642 (struct prefix *)&address);
643 if (n) {
644 route_unlock_node(n);
645 return 1;
646 }
647 }
648 }
649 return -1;
650 }
651
652 /* Check whether connected is within the ripng_enable_network table. */
653 static int rip_enable_network_lookup2(struct connected *connected)
654 {
655 struct rip_interface *ri = connected->ifp->info;
656 struct rip *rip = ri->rip;
657 struct prefix_ipv4 address;
658 struct prefix *p;
659
660 p = connected->address;
661
662 if (p->family == AF_INET) {
663 struct route_node *node;
664
665 address.family = p->family;
666 address.prefix = p->u.prefix4;
667 address.prefixlen = IPV4_MAX_BITLEN;
668
669 /* LPM on p->family, p->u.prefix4/IPV4_MAX_BITLEN within
670 * rip->enable_network */
671 node = route_node_match(rip->enable_network,
672 (struct prefix *)&address);
673
674 if (node) {
675 route_unlock_node(node);
676 return 1;
677 }
678 }
679
680 return -1;
681 }
682 /* Add RIP enable network. */
683 int rip_enable_network_add(struct rip *rip, struct prefix *p)
684 {
685 struct route_node *node;
686
687 node = route_node_get(rip->enable_network, p);
688
689 if (node->info) {
690 route_unlock_node(node);
691 return NB_ERR_INCONSISTENCY;
692 } else
693 node->info = (void *)1;
694
695 /* XXX: One should find a better solution than a generic one */
696 rip_enable_apply_all(rip);
697
698 return NB_OK;
699 }
700
701 /* Delete RIP enable network. */
702 int rip_enable_network_delete(struct rip *rip, struct prefix *p)
703 {
704 struct route_node *node;
705
706 node = route_node_lookup(rip->enable_network, p);
707 if (node) {
708 node->info = NULL;
709
710 /* Unlock info lock. */
711 route_unlock_node(node);
712
713 /* Unlock lookup lock. */
714 route_unlock_node(node);
715
716 /* XXX: One should find a better solution than a generic one */
717 rip_enable_apply_all(rip);
718
719 return NB_OK;
720 }
721
722 return NB_ERR_INCONSISTENCY;
723 }
724
725 /* Check interface is enabled by ifname statement. */
726 static int rip_enable_if_lookup(struct rip *rip, const char *ifname)
727 {
728 unsigned int i;
729 char *str;
730
731 if (!rip)
732 return -1;
733
734 for (i = 0; i < vector_active(rip->enable_interface); i++)
735 if ((str = vector_slot(rip->enable_interface, i)) != NULL)
736 if (strcmp(str, ifname) == 0)
737 return i;
738 return -1;
739 }
740
741 /* Add interface to rip_enable_if. */
742 int rip_enable_if_add(struct rip *rip, const char *ifname)
743 {
744 int ret;
745
746 ret = rip_enable_if_lookup(rip, ifname);
747 if (ret >= 0)
748 return NB_ERR_INCONSISTENCY;
749
750 vector_set(rip->enable_interface,
751 XSTRDUP(MTYPE_RIP_INTERFACE_STRING, ifname));
752
753 rip_enable_apply_all(rip); /* TODOVJ */
754
755 return NB_OK;
756 }
757
758 /* Delete interface from rip_enable_if. */
759 int rip_enable_if_delete(struct rip *rip, const char *ifname)
760 {
761 int index;
762 char *str;
763
764 index = rip_enable_if_lookup(rip, ifname);
765 if (index < 0)
766 return NB_ERR_INCONSISTENCY;
767
768 str = vector_slot(rip->enable_interface, index);
769 XFREE(MTYPE_RIP_INTERFACE_STRING, str);
770 vector_unset(rip->enable_interface, index);
771
772 rip_enable_apply_all(rip); /* TODOVJ */
773
774 return NB_OK;
775 }
776
777 /* Join to multicast group and send request to the interface. */
778 static void rip_interface_wakeup(struct event *t)
779 {
780 struct interface *ifp;
781 struct rip_interface *ri;
782
783 /* Get interface. */
784 ifp = EVENT_ARG(t);
785
786 ri = ifp->info;
787
788 /* Join to multicast group. */
789 if (rip_multicast_join(ifp, ri->rip->sock) < 0) {
790 flog_err_sys(EC_LIB_SOCKET,
791 "multicast join failed, interface %s not running",
792 ifp->name);
793 return;
794 }
795
796 /* Set running flag. */
797 ri->running = 1;
798
799 /* Send RIP request to the interface. */
800 rip_request_interface(ifp);
801 }
802
803 static void rip_connect_set(struct interface *ifp, int set)
804 {
805 struct rip_interface *ri = ifp->info;
806 struct rip *rip = ri->rip;
807 struct listnode *node, *nnode;
808 struct connected *connected;
809 struct prefix_ipv4 address;
810 struct nexthop nh;
811
812 memset(&nh, 0, sizeof(nh));
813
814 for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, connected)) {
815 struct prefix *p;
816 p = connected->address;
817
818 if (p->family != AF_INET)
819 continue;
820
821 address.family = AF_INET;
822 address.prefix = p->u.prefix4;
823 address.prefixlen = p->prefixlen;
824 apply_mask_ipv4(&address);
825
826 nh.ifindex = connected->ifp->ifindex;
827 nh.type = NEXTHOP_TYPE_IFINDEX;
828 if (set) {
829 /* Check once more whether this prefix is within a
830 * "network IF_OR_PREF" one */
831 if ((rip_enable_if_lookup(rip, connected->ifp->name)
832 >= 0)
833 || (rip_enable_network_lookup2(connected) >= 0))
834 rip_redistribute_add(rip, ZEBRA_ROUTE_CONNECT,
835 RIP_ROUTE_INTERFACE,
836 &address, &nh, 0, 0, 0);
837 } else {
838 rip_redistribute_delete(rip, ZEBRA_ROUTE_CONNECT,
839 RIP_ROUTE_INTERFACE, &address,
840 connected->ifp->ifindex);
841 if (rip_redistribute_check(rip, ZEBRA_ROUTE_CONNECT))
842 rip_redistribute_add(rip, ZEBRA_ROUTE_CONNECT,
843 RIP_ROUTE_REDISTRIBUTE,
844 &address, &nh, 0, 0, 0);
845 }
846 }
847 }
848
849 /* Update interface status. */
850 void rip_enable_apply(struct interface *ifp)
851 {
852 int ret;
853 struct rip_interface *ri = NULL;
854
855 /* Check interface. */
856 if (!if_is_operative(ifp))
857 return;
858
859 ri = ifp->info;
860
861 /* Check network configuration. */
862 ret = rip_enable_network_lookup_if(ifp);
863
864 /* If the interface is matched. */
865 if (ret > 0)
866 ri->enable_network = 1;
867 else
868 ri->enable_network = 0;
869
870 /* Check interface name configuration. */
871 ret = rip_enable_if_lookup(ri->rip, ifp->name);
872 if (ret >= 0)
873 ri->enable_interface = 1;
874 else
875 ri->enable_interface = 0;
876
877 /* any interface MUST have an IPv4 address */
878 if (!rip_if_ipv4_address_check(ifp)) {
879 ri->enable_network = 0;
880 ri->enable_interface = 0;
881 }
882
883 /* Update running status of the interface. */
884 if (ri->enable_network || ri->enable_interface) {
885 if (IS_RIP_DEBUG_EVENT)
886 zlog_debug("turn on %s", ifp->name);
887
888 /* Add interface wake up thread. */
889 event_add_timer(master, rip_interface_wakeup, ifp, 1,
890 &ri->t_wakeup);
891 rip_connect_set(ifp, 1);
892 } else if (ri->running) {
893 /* Might as well clean up the route table as well
894 * rip_if_down sets to 0 ri->running, and displays "turn
895 *off %s"
896 **/
897 rip_if_down(ifp);
898
899 rip_connect_set(ifp, 0);
900 }
901 }
902
903 /* Apply network configuration to all interface. */
904 static void rip_enable_apply_all(struct rip *rip)
905 {
906 struct interface *ifp;
907
908 /* Check each interface. */
909 FOR_ALL_INTERFACES (rip->vrf, ifp)
910 rip_enable_apply(ifp);
911 }
912
913 int rip_neighbor_lookup(struct rip *rip, struct sockaddr_in *from)
914 {
915 struct prefix_ipv4 p;
916 struct route_node *node;
917
918 memset(&p, 0, sizeof(p));
919 p.family = AF_INET;
920 p.prefix = from->sin_addr;
921 p.prefixlen = IPV4_MAX_BITLEN;
922
923 node = route_node_lookup(rip->neighbor, (struct prefix *)&p);
924 if (node) {
925 route_unlock_node(node);
926 return 1;
927 }
928 return 0;
929 }
930
931 /* Add new RIP neighbor to the neighbor tree. */
932 int rip_neighbor_add(struct rip *rip, struct prefix_ipv4 *p)
933 {
934 struct route_node *node;
935
936 node = route_node_get(rip->neighbor, (struct prefix *)p);
937
938 if (node->info)
939 return NB_ERR_INCONSISTENCY;
940
941 node->info = rip->neighbor;
942
943 return NB_OK;
944 }
945
946 /* Delete RIP neighbor from the neighbor tree. */
947 int rip_neighbor_delete(struct rip *rip, struct prefix_ipv4 *p)
948 {
949 struct route_node *node;
950
951 /* Lock for look up. */
952 node = route_node_lookup(rip->neighbor, (struct prefix *)p);
953 if (!node)
954 return NB_ERR_INCONSISTENCY;
955
956 node->info = NULL;
957
958 /* Unlock lookup lock. */
959 route_unlock_node(node);
960
961 /* Unlock real neighbor information lock. */
962 route_unlock_node(node);
963
964 return NB_OK;
965 }
966
967 /* Clear all network and neighbor configuration. */
968 void rip_clean_network(struct rip *rip)
969 {
970 unsigned int i;
971 char *str;
972 struct route_node *rn;
973
974 /* rip->enable_network. */
975 for (rn = route_top(rip->enable_network); rn; rn = route_next(rn))
976 if (rn->info) {
977 rn->info = NULL;
978 route_unlock_node(rn);
979 }
980
981 /* rip->enable_interface. */
982 for (i = 0; i < vector_active(rip->enable_interface); i++)
983 if ((str = vector_slot(rip->enable_interface, i)) != NULL) {
984 XFREE(MTYPE_RIP_INTERFACE_STRING, str);
985 vector_slot(rip->enable_interface, i) = NULL;
986 }
987 }
988
989 /* Utility function for looking up passive interface settings. */
990 static int rip_passive_nondefault_lookup(struct rip *rip, const char *ifname)
991 {
992 unsigned int i;
993 char *str;
994
995 for (i = 0; i < vector_active(rip->passive_nondefault); i++)
996 if ((str = vector_slot(rip->passive_nondefault, i)) != NULL)
997 if (strcmp(str, ifname) == 0)
998 return i;
999 return -1;
1000 }
1001
1002 static void rip_passive_interface_apply(struct interface *ifp)
1003 {
1004 struct rip *rip;
1005 struct rip_interface *ri;
1006
1007 ri = ifp->info;
1008 rip = ri->rip;
1009 if (rip == NULL)
1010 return;
1011
1012 ri->passive = ((rip_passive_nondefault_lookup(rip, ifp->name) < 0)
1013 ? rip->passive_default
1014 : !rip->passive_default);
1015
1016 if (IS_RIP_DEBUG_ZEBRA)
1017 zlog_debug("interface %s: passive = %d", ifp->name,
1018 ri->passive);
1019 }
1020
1021 static void rip_passive_interface_apply_all(struct rip *rip)
1022 {
1023 struct interface *ifp;
1024
1025 FOR_ALL_INTERFACES (rip->vrf, ifp)
1026 rip_passive_interface_apply(ifp);
1027 }
1028
1029 /* Passive interface. */
1030 int rip_passive_nondefault_set(struct rip *rip, const char *ifname)
1031 {
1032 if (rip_passive_nondefault_lookup(rip, ifname) >= 0)
1033 /*
1034 * Don't return an error, this can happen after changing
1035 * 'passive-default'.
1036 */
1037 return NB_OK;
1038
1039 vector_set(rip->passive_nondefault,
1040 XSTRDUP(MTYPE_RIP_INTERFACE_STRING, ifname));
1041
1042 rip_passive_interface_apply_all(rip);
1043
1044 return NB_OK;
1045 }
1046
1047 int rip_passive_nondefault_unset(struct rip *rip, const char *ifname)
1048 {
1049 int i;
1050 char *str;
1051
1052 i = rip_passive_nondefault_lookup(rip, ifname);
1053 if (i < 0)
1054 /*
1055 * Don't return an error, this can happen after changing
1056 * 'passive-default'.
1057 */
1058 return NB_OK;
1059
1060 str = vector_slot(rip->passive_nondefault, i);
1061 XFREE(MTYPE_RIP_INTERFACE_STRING, str);
1062 vector_unset(rip->passive_nondefault, i);
1063
1064 rip_passive_interface_apply_all(rip);
1065
1066 return NB_OK;
1067 }
1068
1069 /* Free all configured RIP passive-interface settings. */
1070 void rip_passive_nondefault_clean(struct rip *rip)
1071 {
1072 unsigned int i;
1073 char *str;
1074
1075 for (i = 0; i < vector_active(rip->passive_nondefault); i++)
1076 if ((str = vector_slot(rip->passive_nondefault, i)) != NULL) {
1077 XFREE(MTYPE_RIP_INTERFACE_STRING, str);
1078 vector_slot(rip->passive_nondefault, i) = NULL;
1079 }
1080 rip_passive_interface_apply_all(rip);
1081 }
1082
1083 int rip_show_network_config(struct vty *vty, struct rip *rip)
1084 {
1085 unsigned int i;
1086 char *ifname;
1087 struct route_node *node;
1088
1089 /* Network type RIP enable interface statement. */
1090 for (node = route_top(rip->enable_network); node;
1091 node = route_next(node))
1092 if (node->info)
1093 vty_out(vty, " %pFX\n", &node->p);
1094
1095 /* Interface name RIP enable statement. */
1096 for (i = 0; i < vector_active(rip->enable_interface); i++)
1097 if ((ifname = vector_slot(rip->enable_interface, i)) != NULL)
1098 vty_out(vty, " %s\n", ifname);
1099
1100 /* RIP neighbors listing. */
1101 for (node = route_top(rip->neighbor); node; node = route_next(node))
1102 if (node->info)
1103 vty_out(vty, " %pI4\n", &node->p.u.prefix4);
1104
1105 return 0;
1106 }
1107
1108 void rip_interface_sync(struct interface *ifp)
1109 {
1110 struct rip_interface *ri;
1111
1112 ri = ifp->info;
1113 ri->ifp = ifp;
1114 if (ri)
1115 ri->rip = ifp->vrf->info;
1116 }
1117
1118 /* Called when interface structure allocated. */
1119 static int rip_interface_new_hook(struct interface *ifp)
1120 {
1121 ifp->info = rip_interface_new();
1122 rip_interface_sync(ifp);
1123
1124 return 0;
1125 }
1126
1127 /* Called when interface structure deleted. */
1128 static int rip_interface_delete_hook(struct interface *ifp)
1129 {
1130 rip_interface_reset(ifp->info);
1131 XFREE(MTYPE_RIP_INTERFACE, ifp->info);
1132 return 0;
1133 }
1134
1135 /* Allocate and initialize interface vector. */
1136 void rip_if_init(void)
1137 {
1138 /* Default initial size of interface vector. */
1139 hook_register_prio(if_add, 0, rip_interface_new_hook);
1140 hook_register_prio(if_del, 0, rip_interface_delete_hook);
1141
1142 /* Install interface node. */
1143 if_cmd_init_default();
1144 if_zapi_callbacks(rip_ifp_create, rip_ifp_up,
1145 rip_ifp_down, rip_ifp_destroy);
1146 }