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