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