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