]> git.proxmox.com Git - mirror_frr.git/blob - ripd/rip_interface.c
*: Add infrastructure to support zapi interface callbacks
[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 int rip_interface_down(ZAPI_CALLBACK_ARGS)
350 {
351 struct interface *ifp;
352 struct stream *s;
353
354 s = zclient->ibuf;
355
356 /* zebra_interface_state_read() updates interface structure in
357 iflist. */
358 ifp = zebra_interface_state_read(s, vrf_id);
359
360 if (ifp == NULL)
361 return 0;
362
363 rip_interface_sync(ifp);
364 rip_if_down(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 down",
369 ifp->name, ifp->vrf_id, ifp->ifindex,
370 (unsigned long long)ifp->flags, ifp->metric, ifp->mtu);
371
372 return 0;
373 }
374
375 /* Inteface link up message processing */
376 int rip_interface_up(ZAPI_CALLBACK_ARGS)
377 {
378 struct interface *ifp;
379
380 /* zebra_interface_state_read () updates interface structure in
381 iflist. */
382 ifp = zebra_interface_state_read(zclient->ibuf, vrf_id);
383
384 if (ifp == NULL)
385 return 0;
386
387 if (IS_RIP_DEBUG_ZEBRA)
388 zlog_debug(
389 "interface %s vrf %u index %d flags %#llx metric %d mtu %d is up",
390 ifp->name, ifp->vrf_id, ifp->ifindex,
391 (unsigned long long)ifp->flags, ifp->metric, ifp->mtu);
392
393 rip_interface_sync(ifp);
394
395 /* Check if this interface is RIP enabled or not.*/
396 rip_enable_apply(ifp);
397
398 /* Check for a passive interface */
399 rip_passive_interface_apply(ifp);
400
401 /* Apply distribute list to the all interface. */
402 rip_distribute_update_interface(ifp);
403
404 return 0;
405 }
406
407 /* Inteface addition message from zebra. */
408 int rip_interface_add(ZAPI_CALLBACK_ARGS)
409 {
410 struct interface *ifp;
411
412 ifp = zebra_interface_add_read(zclient->ibuf, vrf_id);
413 rip_interface_sync(ifp);
414
415 if (IS_RIP_DEBUG_ZEBRA)
416 zlog_debug(
417 "interface add %s vrf %u index %d flags %#llx metric %d mtu %d",
418 ifp->name, ifp->vrf_id, ifp->ifindex,
419 (unsigned long long)ifp->flags, ifp->metric, ifp->mtu);
420
421 /* Check if this interface is RIP enabled or not.*/
422 rip_enable_apply(ifp);
423
424 /* Check for a passive interface */
425 rip_passive_interface_apply(ifp);
426
427 /* Apply distribute list to the all interface. */
428 rip_distribute_update_interface(ifp);
429
430 /* rip_request_neighbor_all (); */
431
432 /* Check interface routemap. */
433 rip_if_rmap_update_interface(ifp);
434
435 return 0;
436 }
437
438 int rip_interface_delete(ZAPI_CALLBACK_ARGS)
439 {
440 struct interface *ifp;
441 struct stream *s;
442
443
444 s = zclient->ibuf;
445 /* zebra_interface_state_read() updates interface structure in iflist */
446 ifp = zebra_interface_state_read(s, vrf_id);
447
448 if (ifp == NULL)
449 return 0;
450
451 rip_interface_sync(ifp);
452 if (if_is_up(ifp)) {
453 rip_if_down(ifp);
454 }
455
456 zlog_info(
457 "interface delete %s vrf %u index %d flags %#llx metric %d mtu %d",
458 ifp->name, ifp->vrf_id, ifp->ifindex,
459 (unsigned long long)ifp->flags, ifp->metric, ifp->mtu);
460
461 /* To support pseudo interface do not free interface structure. */
462 /* if_delete(ifp); */
463 if_set_index(ifp, IFINDEX_INTERNAL);
464
465 return 0;
466 }
467
468 /* VRF update for an interface. */
469 int rip_interface_vrf_update(ZAPI_CALLBACK_ARGS)
470 {
471 struct interface *ifp;
472 vrf_id_t new_vrf_id;
473
474 ifp = zebra_interface_vrf_update_read(zclient->ibuf, vrf_id,
475 &new_vrf_id);
476 if (!ifp)
477 return 0;
478
479 if (IS_RIP_DEBUG_ZEBRA)
480 zlog_debug("interface %s VRF change vrf_id %u new vrf id %u",
481 ifp->name, vrf_id, new_vrf_id);
482
483 if_update_to_new_vrf(ifp, new_vrf_id);
484 rip_interface_sync(ifp);
485
486 return 0;
487 }
488
489 static void rip_interface_clean(struct rip_interface *ri)
490 {
491 ri->enable_network = 0;
492 ri->enable_interface = 0;
493 ri->running = 0;
494
495 if (ri->t_wakeup) {
496 thread_cancel(ri->t_wakeup);
497 ri->t_wakeup = NULL;
498 }
499 }
500
501 void rip_interfaces_clean(struct rip *rip)
502 {
503 struct interface *ifp;
504
505 FOR_ALL_INTERFACES (rip->vrf, ifp)
506 rip_interface_clean(ifp->info);
507 }
508
509 static void rip_interface_reset(struct rip_interface *ri)
510 {
511 ri->auth_type = yang_get_default_enum("%s/authentication-scheme/mode",
512 RIP_IFACE);
513 ri->md5_auth_len = yang_get_default_enum(
514 "%s/authentication-scheme/md5-auth-length", RIP_IFACE);
515
516 /* Set default split-horizon behavior. If the interface is Frame
517 Relay or SMDS is enabled, the default value for split-horizon is
518 off. But currently Zebra does detect Frame Relay or SMDS
519 interface. So all interface is set to split horizon. */
520 ri->split_horizon =
521 yang_get_default_enum("%s/split-horizon", RIP_IFACE);
522
523 ri->ri_send = yang_get_default_enum("%s/version-send", RIP_IFACE);
524 ri->ri_receive = yang_get_default_enum("%s/version-receive", RIP_IFACE);
525 ri->v2_broadcast = yang_get_default_bool("%s/v2-broadcast", RIP_IFACE);
526
527 XFREE(MTYPE_RIP_INTERFACE_STRING, ri->auth_str);
528
529 XFREE(MTYPE_RIP_INTERFACE_STRING, ri->key_chain);
530
531 ri->list[RIP_FILTER_IN] = NULL;
532 ri->list[RIP_FILTER_OUT] = NULL;
533
534 ri->prefix[RIP_FILTER_IN] = NULL;
535 ri->prefix[RIP_FILTER_OUT] = NULL;
536
537 ri->recv_badpackets = 0;
538 ri->recv_badroutes = 0;
539 ri->sent_updates = 0;
540
541 ri->passive = 0;
542
543 rip_interface_clean(ri);
544 }
545
546 int rip_if_down(struct interface *ifp)
547 {
548 struct rip *rip;
549 struct route_node *rp;
550 struct rip_info *rinfo;
551 struct rip_interface *ri = NULL;
552 struct list *list = NULL;
553 struct listnode *listnode = NULL, *nextnode = NULL;
554
555 ri = ifp->info;
556 rip = ri->rip;
557 if (rip) {
558 for (rp = route_top(rip->table); rp; rp = route_next(rp))
559 if ((list = rp->info) != NULL)
560 for (ALL_LIST_ELEMENTS(list, listnode, nextnode,
561 rinfo))
562 if (rinfo->nh.ifindex == ifp->ifindex)
563 rip_ecmp_delete(rip, rinfo);
564
565 if (ri->running) {
566 if (IS_RIP_DEBUG_EVENT)
567 zlog_debug("turn off %s", ifp->name);
568
569 /* Leave from multicast group. */
570 rip_multicast_leave(ifp, rip->sock);
571
572 ri->running = 0;
573 }
574 }
575
576 return 0;
577 }
578
579 static void rip_apply_address_add(struct connected *ifc)
580 {
581 struct rip_interface *ri = ifc->ifp->info;
582 struct rip *rip = ri->rip;
583 struct prefix_ipv4 address;
584 struct nexthop nh;
585 struct prefix *p;
586
587 if (!rip)
588 return;
589
590 if (!if_is_up(ifc->ifp))
591 return;
592
593 p = ifc->address;
594
595 memset(&address, 0, sizeof(address));
596 memset(&nh, 0, sizeof(nh));
597
598 address.family = p->family;
599 address.prefix = p->u.prefix4;
600 address.prefixlen = p->prefixlen;
601 apply_mask_ipv4(&address);
602
603 nh.ifindex = ifc->ifp->ifindex;
604 nh.type = NEXTHOP_TYPE_IFINDEX;
605
606 /* Check if this interface is RIP enabled or not
607 or Check if this address's prefix is RIP enabled */
608 if ((rip_enable_if_lookup(rip, ifc->ifp->name) >= 0)
609 || (rip_enable_network_lookup2(ifc) >= 0))
610 rip_redistribute_add(rip, ZEBRA_ROUTE_CONNECT,
611 RIP_ROUTE_INTERFACE, &address, &nh, 0, 0,
612 0);
613 }
614
615 int rip_interface_address_add(ZAPI_CALLBACK_ARGS)
616 {
617 struct connected *ifc;
618 struct prefix *p;
619
620 ifc = zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD,
621 zclient->ibuf, vrf_id);
622
623 if (ifc == NULL)
624 return 0;
625
626 p = ifc->address;
627
628 if (p->family == AF_INET) {
629 if (IS_RIP_DEBUG_ZEBRA)
630 zlog_debug("connected address %s/%d is added",
631 inet_ntoa(p->u.prefix4), p->prefixlen);
632
633 rip_enable_apply(ifc->ifp);
634 /* Check if this prefix needs to be redistributed */
635 rip_apply_address_add(ifc);
636
637 hook_call(rip_ifaddr_add, ifc);
638 }
639
640 return 0;
641 }
642
643 static void rip_apply_address_del(struct connected *ifc)
644 {
645 struct rip_interface *ri = ifc->ifp->info;
646 struct rip *rip = ri->rip;
647 struct prefix_ipv4 address;
648 struct prefix *p;
649
650 if (!rip)
651 return;
652
653 if (!if_is_up(ifc->ifp))
654 return;
655
656 p = ifc->address;
657
658 memset(&address, 0, sizeof(address));
659 address.family = p->family;
660 address.prefix = p->u.prefix4;
661 address.prefixlen = p->prefixlen;
662 apply_mask_ipv4(&address);
663
664 rip_redistribute_delete(rip, ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE,
665 &address, ifc->ifp->ifindex);
666 }
667
668 int rip_interface_address_delete(ZAPI_CALLBACK_ARGS)
669 {
670 struct connected *ifc;
671 struct prefix *p;
672
673 ifc = zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE,
674 zclient->ibuf, vrf_id);
675
676 if (ifc) {
677 p = ifc->address;
678 if (p->family == AF_INET) {
679 if (IS_RIP_DEBUG_ZEBRA)
680 zlog_debug("connected address %s/%d is deleted",
681 inet_ntoa(p->u.prefix4),
682 p->prefixlen);
683
684 hook_call(rip_ifaddr_del, ifc);
685
686 /* Chech wether this prefix needs to be removed */
687 rip_apply_address_del(ifc);
688 }
689
690 connected_free(ifc);
691 }
692
693 return 0;
694 }
695
696 /* Check interface is enabled by network statement. */
697 /* Check wether the interface has at least a connected prefix that
698 * is within the ripng_enable_network table. */
699 static int rip_enable_network_lookup_if(struct interface *ifp)
700 {
701 struct rip_interface *ri = ifp->info;
702 struct rip *rip = ri->rip;
703 struct listnode *node, *nnode;
704 struct connected *connected;
705 struct prefix_ipv4 address;
706
707 if (!rip)
708 return -1;
709
710 for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, connected)) {
711 struct prefix *p;
712 struct route_node *n;
713
714 p = connected->address;
715
716 if (p->family == AF_INET) {
717 address.family = AF_INET;
718 address.prefix = p->u.prefix4;
719 address.prefixlen = IPV4_MAX_BITLEN;
720
721 n = route_node_match(rip->enable_network,
722 (struct prefix *)&address);
723 if (n) {
724 route_unlock_node(n);
725 return 1;
726 }
727 }
728 }
729 return -1;
730 }
731
732 /* Check wether connected is within the ripng_enable_network table. */
733 static int rip_enable_network_lookup2(struct connected *connected)
734 {
735 struct rip_interface *ri = connected->ifp->info;
736 struct rip *rip = ri->rip;
737 struct prefix_ipv4 address;
738 struct prefix *p;
739
740 p = connected->address;
741
742 if (p->family == AF_INET) {
743 struct route_node *node;
744
745 address.family = p->family;
746 address.prefix = p->u.prefix4;
747 address.prefixlen = IPV4_MAX_BITLEN;
748
749 /* LPM on p->family, p->u.prefix4/IPV4_MAX_BITLEN within
750 * rip->enable_network */
751 node = route_node_match(rip->enable_network,
752 (struct prefix *)&address);
753
754 if (node) {
755 route_unlock_node(node);
756 return 1;
757 }
758 }
759
760 return -1;
761 }
762 /* Add RIP enable network. */
763 int rip_enable_network_add(struct rip *rip, struct prefix *p)
764 {
765 struct route_node *node;
766
767 node = route_node_get(rip->enable_network, p);
768
769 if (node->info) {
770 route_unlock_node(node);
771 return NB_ERR_INCONSISTENCY;
772 } else
773 node->info = (void *)1;
774
775 /* XXX: One should find a better solution than a generic one */
776 rip_enable_apply_all(rip);
777
778 return NB_OK;
779 }
780
781 /* Delete RIP enable network. */
782 int rip_enable_network_delete(struct rip *rip, struct prefix *p)
783 {
784 struct route_node *node;
785
786 node = route_node_lookup(rip->enable_network, p);
787 if (node) {
788 node->info = NULL;
789
790 /* Unlock info lock. */
791 route_unlock_node(node);
792
793 /* Unlock lookup lock. */
794 route_unlock_node(node);
795
796 /* XXX: One should find a better solution than a generic one */
797 rip_enable_apply_all(rip);
798
799 return NB_OK;
800 }
801
802 return NB_ERR_INCONSISTENCY;
803 }
804
805 /* Check interface is enabled by ifname statement. */
806 static int rip_enable_if_lookup(struct rip *rip, const char *ifname)
807 {
808 unsigned int i;
809 char *str;
810
811 if (!rip)
812 return -1;
813
814 for (i = 0; i < vector_active(rip->enable_interface); i++)
815 if ((str = vector_slot(rip->enable_interface, i)) != NULL)
816 if (strcmp(str, ifname) == 0)
817 return i;
818 return -1;
819 }
820
821 /* Add interface to rip_enable_if. */
822 int rip_enable_if_add(struct rip *rip, const char *ifname)
823 {
824 int ret;
825
826 ret = rip_enable_if_lookup(rip, ifname);
827 if (ret >= 0)
828 return NB_ERR_INCONSISTENCY;
829
830 vector_set(rip->enable_interface,
831 XSTRDUP(MTYPE_RIP_INTERFACE_STRING, ifname));
832
833 rip_enable_apply_all(rip); /* TODOVJ */
834
835 return NB_OK;
836 }
837
838 /* Delete interface from rip_enable_if. */
839 int rip_enable_if_delete(struct rip *rip, const char *ifname)
840 {
841 int index;
842 char *str;
843
844 index = rip_enable_if_lookup(rip, ifname);
845 if (index < 0)
846 return NB_ERR_INCONSISTENCY;
847
848 str = vector_slot(rip->enable_interface, index);
849 XFREE(MTYPE_RIP_INTERFACE_STRING, str);
850 vector_unset(rip->enable_interface, index);
851
852 rip_enable_apply_all(rip); /* TODOVJ */
853
854 return NB_OK;
855 }
856
857 /* Join to multicast group and send request to the interface. */
858 static int rip_interface_wakeup(struct thread *t)
859 {
860 struct interface *ifp;
861 struct rip_interface *ri;
862
863 /* Get interface. */
864 ifp = THREAD_ARG(t);
865
866 ri = ifp->info;
867 ri->t_wakeup = NULL;
868
869 /* Join to multicast group. */
870 if (rip_multicast_join(ifp, ri->rip->sock) < 0) {
871 flog_err_sys(EC_LIB_SOCKET,
872 "multicast join failed, interface %s not running",
873 ifp->name);
874 return 0;
875 }
876
877 /* Set running flag. */
878 ri->running = 1;
879
880 /* Send RIP request to the interface. */
881 rip_request_interface(ifp);
882
883 return 0;
884 }
885
886 static void rip_connect_set(struct interface *ifp, int set)
887 {
888 struct rip_interface *ri = ifp->info;
889 struct rip *rip = ri->rip;
890 struct listnode *node, *nnode;
891 struct connected *connected;
892 struct prefix_ipv4 address;
893 struct nexthop nh;
894
895 memset(&nh, 0, sizeof(nh));
896
897 for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, connected)) {
898 struct prefix *p;
899 p = connected->address;
900
901 if (p->family != AF_INET)
902 continue;
903
904 address.family = AF_INET;
905 address.prefix = p->u.prefix4;
906 address.prefixlen = p->prefixlen;
907 apply_mask_ipv4(&address);
908
909 nh.ifindex = connected->ifp->ifindex;
910 nh.type = NEXTHOP_TYPE_IFINDEX;
911 if (set) {
912 /* Check once more wether this prefix is within a
913 * "network IF_OR_PREF" one */
914 if ((rip_enable_if_lookup(rip, connected->ifp->name)
915 >= 0)
916 || (rip_enable_network_lookup2(connected) >= 0))
917 rip_redistribute_add(rip, ZEBRA_ROUTE_CONNECT,
918 RIP_ROUTE_INTERFACE,
919 &address, &nh, 0, 0, 0);
920 } else {
921 rip_redistribute_delete(rip, ZEBRA_ROUTE_CONNECT,
922 RIP_ROUTE_INTERFACE, &address,
923 connected->ifp->ifindex);
924 if (rip_redistribute_check(rip, ZEBRA_ROUTE_CONNECT))
925 rip_redistribute_add(rip, ZEBRA_ROUTE_CONNECT,
926 RIP_ROUTE_REDISTRIBUTE,
927 &address, &nh, 0, 0, 0);
928 }
929 }
930 }
931
932 /* Update interface status. */
933 void rip_enable_apply(struct interface *ifp)
934 {
935 int ret;
936 struct rip_interface *ri = NULL;
937
938 /* Check interface. */
939 if (!if_is_operative(ifp))
940 return;
941
942 ri = ifp->info;
943
944 /* Check network configuration. */
945 ret = rip_enable_network_lookup_if(ifp);
946
947 /* If the interface is matched. */
948 if (ret > 0)
949 ri->enable_network = 1;
950 else
951 ri->enable_network = 0;
952
953 /* Check interface name configuration. */
954 ret = rip_enable_if_lookup(ri->rip, ifp->name);
955 if (ret >= 0)
956 ri->enable_interface = 1;
957 else
958 ri->enable_interface = 0;
959
960 /* any interface MUST have an IPv4 address */
961 if (!rip_if_ipv4_address_check(ifp)) {
962 ri->enable_network = 0;
963 ri->enable_interface = 0;
964 }
965
966 /* Update running status of the interface. */
967 if (ri->enable_network || ri->enable_interface) {
968 if (IS_RIP_DEBUG_EVENT)
969 zlog_debug("turn on %s", ifp->name);
970
971 /* Add interface wake up thread. */
972 thread_add_timer(master, rip_interface_wakeup, ifp, 1,
973 &ri->t_wakeup);
974 rip_connect_set(ifp, 1);
975 } else if (ri->running) {
976 /* Might as well clean up the route table as well
977 * rip_if_down sets to 0 ri->running, and displays "turn
978 *off %s"
979 **/
980 rip_if_down(ifp);
981
982 rip_connect_set(ifp, 0);
983 }
984 }
985
986 /* Apply network configuration to all interface. */
987 static void rip_enable_apply_all(struct rip *rip)
988 {
989 struct interface *ifp;
990
991 /* Check each interface. */
992 FOR_ALL_INTERFACES (rip->vrf, ifp)
993 rip_enable_apply(ifp);
994 }
995
996 int rip_neighbor_lookup(struct rip *rip, struct sockaddr_in *from)
997 {
998 struct prefix_ipv4 p;
999 struct route_node *node;
1000
1001 memset(&p, 0, sizeof(struct prefix_ipv4));
1002 p.family = AF_INET;
1003 p.prefix = from->sin_addr;
1004 p.prefixlen = IPV4_MAX_BITLEN;
1005
1006 node = route_node_lookup(rip->neighbor, (struct prefix *)&p);
1007 if (node) {
1008 route_unlock_node(node);
1009 return 1;
1010 }
1011 return 0;
1012 }
1013
1014 /* Add new RIP neighbor to the neighbor tree. */
1015 int rip_neighbor_add(struct rip *rip, struct prefix_ipv4 *p)
1016 {
1017 struct route_node *node;
1018
1019 node = route_node_get(rip->neighbor, (struct prefix *)p);
1020
1021 if (node->info)
1022 return NB_ERR_INCONSISTENCY;
1023
1024 node->info = rip->neighbor;
1025
1026 return NB_OK;
1027 }
1028
1029 /* Delete RIP neighbor from the neighbor tree. */
1030 int rip_neighbor_delete(struct rip *rip, struct prefix_ipv4 *p)
1031 {
1032 struct route_node *node;
1033
1034 /* Lock for look up. */
1035 node = route_node_lookup(rip->neighbor, (struct prefix *)p);
1036 if (!node)
1037 return NB_ERR_INCONSISTENCY;
1038
1039 node->info = NULL;
1040
1041 /* Unlock lookup lock. */
1042 route_unlock_node(node);
1043
1044 /* Unlock real neighbor information lock. */
1045 route_unlock_node(node);
1046
1047 return NB_OK;
1048 }
1049
1050 /* Clear all network and neighbor configuration. */
1051 void rip_clean_network(struct rip *rip)
1052 {
1053 unsigned int i;
1054 char *str;
1055 struct route_node *rn;
1056
1057 /* rip->enable_network. */
1058 for (rn = route_top(rip->enable_network); rn; rn = route_next(rn))
1059 if (rn->info) {
1060 rn->info = NULL;
1061 route_unlock_node(rn);
1062 }
1063
1064 /* rip->enable_interface. */
1065 for (i = 0; i < vector_active(rip->enable_interface); i++)
1066 if ((str = vector_slot(rip->enable_interface, i)) != NULL) {
1067 XFREE(MTYPE_RIP_INTERFACE_STRING, str);
1068 vector_slot(rip->enable_interface, i) = NULL;
1069 }
1070 }
1071
1072 /* Utility function for looking up passive interface settings. */
1073 static int rip_passive_nondefault_lookup(struct rip *rip, const char *ifname)
1074 {
1075 unsigned int i;
1076 char *str;
1077
1078 for (i = 0; i < vector_active(rip->passive_nondefault); i++)
1079 if ((str = vector_slot(rip->passive_nondefault, i)) != NULL)
1080 if (strcmp(str, ifname) == 0)
1081 return i;
1082 return -1;
1083 }
1084
1085 static void rip_passive_interface_apply(struct interface *ifp)
1086 {
1087 struct rip *rip;
1088 struct rip_interface *ri;
1089
1090 ri = ifp->info;
1091 rip = ri->rip;
1092 if (rip == NULL)
1093 return;
1094
1095 ri->passive = ((rip_passive_nondefault_lookup(rip, ifp->name) < 0)
1096 ? rip->passive_default
1097 : !rip->passive_default);
1098
1099 if (IS_RIP_DEBUG_ZEBRA)
1100 zlog_debug("interface %s: passive = %d", ifp->name,
1101 ri->passive);
1102 }
1103
1104 static void rip_passive_interface_apply_all(struct rip *rip)
1105 {
1106 struct interface *ifp;
1107
1108 FOR_ALL_INTERFACES (rip->vrf, ifp)
1109 rip_passive_interface_apply(ifp);
1110 }
1111
1112 /* Passive interface. */
1113 int rip_passive_nondefault_set(struct rip *rip, const char *ifname)
1114 {
1115 if (rip_passive_nondefault_lookup(rip, ifname) >= 0)
1116 /*
1117 * Don't return an error, this can happen after changing
1118 * 'passive-default'.
1119 */
1120 return NB_OK;
1121
1122 vector_set(rip->passive_nondefault,
1123 XSTRDUP(MTYPE_RIP_INTERFACE_STRING, ifname));
1124
1125 rip_passive_interface_apply_all(rip);
1126
1127 return NB_OK;
1128 }
1129
1130 int rip_passive_nondefault_unset(struct rip *rip, const char *ifname)
1131 {
1132 int i;
1133 char *str;
1134
1135 i = rip_passive_nondefault_lookup(rip, ifname);
1136 if (i < 0)
1137 /*
1138 * Don't return an error, this can happen after changing
1139 * 'passive-default'.
1140 */
1141 return NB_OK;
1142
1143 str = vector_slot(rip->passive_nondefault, i);
1144 XFREE(MTYPE_RIP_INTERFACE_STRING, str);
1145 vector_unset(rip->passive_nondefault, i);
1146
1147 rip_passive_interface_apply_all(rip);
1148
1149 return NB_OK;
1150 }
1151
1152 /* Free all configured RIP passive-interface settings. */
1153 void rip_passive_nondefault_clean(struct rip *rip)
1154 {
1155 unsigned int i;
1156 char *str;
1157
1158 for (i = 0; i < vector_active(rip->passive_nondefault); i++)
1159 if ((str = vector_slot(rip->passive_nondefault, i)) != NULL) {
1160 XFREE(MTYPE_RIP_INTERFACE_STRING, str);
1161 vector_slot(rip->passive_nondefault, i) = NULL;
1162 }
1163 rip_passive_interface_apply_all(rip);
1164 }
1165
1166 /* Write rip configuration of each interface. */
1167 static int rip_interface_config_write(struct vty *vty)
1168 {
1169 struct vrf *vrf;
1170 int write = 0;
1171
1172 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
1173 struct interface *ifp;
1174
1175 FOR_ALL_INTERFACES (vrf, ifp) {
1176 struct lyd_node *dnode;
1177
1178 dnode = yang_dnode_get(
1179 running_config->dnode,
1180 "/frr-interface:lib/interface[name='%s'][vrf='%s']",
1181 ifp->name, vrf->name);
1182 if (dnode == NULL)
1183 continue;
1184
1185 write = 1;
1186 nb_cli_show_dnode_cmds(vty, dnode, false);
1187 }
1188 }
1189
1190 return write;
1191 }
1192
1193 int rip_show_network_config(struct vty *vty, struct rip *rip)
1194 {
1195 unsigned int i;
1196 char *ifname;
1197 struct route_node *node;
1198
1199 /* Network type RIP enable interface statement. */
1200 for (node = route_top(rip->enable_network); node;
1201 node = route_next(node))
1202 if (node->info)
1203 vty_out(vty, " %s/%u\n",
1204 inet_ntoa(node->p.u.prefix4),
1205 node->p.prefixlen);
1206
1207 /* Interface name RIP enable statement. */
1208 for (i = 0; i < vector_active(rip->enable_interface); i++)
1209 if ((ifname = vector_slot(rip->enable_interface, i)) != NULL)
1210 vty_out(vty, " %s\n", ifname);
1211
1212 /* RIP neighbors listing. */
1213 for (node = route_top(rip->neighbor); node; node = route_next(node))
1214 if (node->info)
1215 vty_out(vty, " %s\n", inet_ntoa(node->p.u.prefix4));
1216
1217 return 0;
1218 }
1219
1220 static struct cmd_node interface_node = {
1221 INTERFACE_NODE, "%s(config-if)# ", 1,
1222 };
1223
1224 void rip_interface_sync(struct interface *ifp)
1225 {
1226 struct vrf *vrf;
1227
1228 vrf = vrf_lookup_by_id(ifp->vrf_id);
1229 if (vrf) {
1230 struct rip_interface *ri;
1231
1232 ri = ifp->info;
1233 if (ri)
1234 ri->rip = vrf->info;
1235 }
1236 }
1237
1238 /* Called when interface structure allocated. */
1239 static int rip_interface_new_hook(struct interface *ifp)
1240 {
1241 ifp->info = rip_interface_new();
1242 rip_interface_sync(ifp);
1243
1244 return 0;
1245 }
1246
1247 /* Called when interface structure deleted. */
1248 static int rip_interface_delete_hook(struct interface *ifp)
1249 {
1250 rip_interface_reset(ifp->info);
1251 XFREE(MTYPE_RIP_INTERFACE, ifp->info);
1252 ifp->info = NULL;
1253 return 0;
1254 }
1255
1256 static int rip_ifp_create(struct interface *ifp)
1257 {
1258 return 0;
1259 }
1260
1261 static int rip_ifp_up(struct interface *ifp)
1262 {
1263 return 0;
1264 }
1265
1266 static int rip_ifp_down(struct interface *ifp)
1267 {
1268 return 0;
1269 }
1270
1271 static int rip_ifp_destroy(struct interface *ifp)
1272 {
1273 return 0;
1274 }
1275
1276 /* Allocate and initialize interface vector. */
1277 void rip_if_init(void)
1278 {
1279 /* Default initial size of interface vector. */
1280 hook_register_prio(if_add, 0, rip_interface_new_hook);
1281 hook_register_prio(if_del, 0, rip_interface_delete_hook);
1282
1283 /* Install interface node. */
1284 install_node(&interface_node, rip_interface_config_write);
1285 if_cmd_init();
1286 if_zapi_callbacks(rip_ifp_create, rip_ifp_up,
1287 rip_ifp_down, rip_ifp_destroy);
1288 }