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 3 : DEFINE_MTYPE_STATIC(RIPD, RIP_INTERFACE, "RIP interface");
47 3 : DEFINE_MTYPE(RIPD, RIP_INTERFACE_STRING, "RIP Interface String");
48 16 : DEFINE_HOOK(rip_ifaddr_add, (struct connected * ifc), (ifc));
49 0 : 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 1 : static int ipv4_multicast_join(int sock, struct in_addr group,
67 : struct in_addr ifa, ifindex_t ifindex)
68 : {
69 1 : int ret;
70 :
71 1 : ret = setsockopt_ipv4_multicast(sock, IP_ADD_MEMBERSHIP, ifa,
72 : group.s_addr, ifindex);
73 :
74 1 : if (ret < 0)
75 0 : zlog_info("can't setsockopt IP_ADD_MEMBERSHIP %s",
76 : safe_strerror(errno));
77 :
78 1 : 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 8 : static struct rip_interface *rip_interface_new(void)
100 : {
101 8 : struct rip_interface *ri;
102 :
103 8 : ri = XCALLOC(MTYPE_RIP_INTERFACE, sizeof(struct rip_interface));
104 :
105 8 : rip_interface_reset(ri);
106 :
107 8 : return ri;
108 : }
109 :
110 1 : void rip_interface_multicast_set(int sock, struct connected *connected)
111 : {
112 1 : struct in_addr addr;
113 :
114 1 : assert(connected != NULL);
115 :
116 1 : addr = CONNECTED_ID(connected)->u.prefix4;
117 :
118 1 : 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 1 : return;
126 : }
127 :
128 : /* Send RIP request packet to specified interface. */
129 1 : static void rip_request_interface_send(struct interface *ifp, uint8_t version)
130 : {
131 1 : struct sockaddr_in to;
132 :
133 : /* RIPv2 support multicast. */
134 1 : if (version == RIPv2 && if_is_multicast(ifp)) {
135 :
136 1 : if (IS_RIP_DEBUG_EVENT)
137 1 : zlog_debug("multicast request on %s", ifp->name);
138 :
139 1 : rip_request_send(NULL, ifp, version, NULL);
140 1 : 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 1 : static void rip_request_interface(struct interface *ifp)
185 : {
186 1 : struct rip_interface *ri;
187 1 : int vsend;
188 :
189 : /* In default ripd doesn't send RIP_REQUEST to the loopback interface.
190 : */
191 1 : if (if_is_loopback(ifp))
192 : return;
193 :
194 : /* If interface is down, don't send RIP packet. */
195 1 : if (!if_is_operative(ifp))
196 : return;
197 :
198 : /* Fetch RIP interface information. */
199 1 : ri = ifp->info;
200 :
201 : /* If there is no version configuration in the interface,
202 : use rip's version setting. */
203 3 : vsend = ((ri->ri_send == RI_RIP_UNSPEC) ? ri->rip->version_send
204 1 : : ri->ri_send);
205 1 : if (vsend & RIPv1)
206 0 : rip_request_interface_send(ifp, RIPv1);
207 1 : if (vsend & RIPv2)
208 1 : rip_request_interface_send(ifp, RIPv2);
209 : }
210 :
211 : /* Multicast packet receive socket. */
212 1 : static int rip_multicast_join(struct interface *ifp, int sock)
213 : {
214 1 : struct listnode *cnode;
215 1 : struct connected *ifc;
216 :
217 1 : if (if_is_operative(ifp) && if_is_multicast(ifp)) {
218 1 : if (IS_RIP_DEBUG_EVENT)
219 1 : zlog_debug("multicast join at %s", ifp->name);
220 :
221 2 : for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, ifc)) {
222 1 : struct prefix_ipv4 *p;
223 1 : struct in_addr group;
224 :
225 1 : p = (struct prefix_ipv4 *)ifc->address;
226 :
227 1 : if (p->family != AF_INET)
228 0 : continue;
229 :
230 1 : group.s_addr = htonl(INADDR_RIP_GROUP);
231 1 : if (ipv4_multicast_join(sock, group, p->prefix,
232 : ifp->ifindex)
233 : < 0)
234 1 : return -1;
235 : else
236 1 : 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 46 : static int rip_if_ipv4_address_check(struct interface *ifp)
272 : {
273 46 : struct listnode *nn;
274 46 : struct connected *connected;
275 46 : int count = 0;
276 :
277 136 : for (ALL_LIST_ELEMENTS_RO(ifp->connected, nn, connected)) {
278 44 : struct prefix *p;
279 :
280 44 : p = connected->address;
281 :
282 44 : if (p->family == AF_INET)
283 38 : count++;
284 : }
285 :
286 46 : return count;
287 : }
288 :
289 :
290 : /* Does this address belongs to me ? */
291 0 : int if_check_address(struct rip *rip, struct in_addr addr)
292 : {
293 0 : struct interface *ifp;
294 :
295 0 : FOR_ALL_INTERFACES (rip->vrf, ifp) {
296 0 : struct listnode *cnode;
297 0 : struct connected *connected;
298 :
299 0 : for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, connected)) {
300 0 : struct prefix_ipv4 *p;
301 :
302 0 : p = (struct prefix_ipv4 *)connected->address;
303 :
304 0 : if (p->family != AF_INET)
305 0 : continue;
306 :
307 0 : 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 0 : static int rip_ifp_down(struct interface *ifp)
316 : {
317 0 : rip_interface_sync(ifp);
318 0 : rip_if_down(ifp);
319 :
320 0 : 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 0 : return 0;
328 : }
329 :
330 : /* Interface link up message processing */
331 14 : static int rip_ifp_up(struct interface *ifp)
332 : {
333 14 : 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 28 : rip_interface_sync(ifp);
341 :
342 : /* Check if this interface is RIP enabled or not.*/
343 14 : rip_enable_apply(ifp);
344 :
345 : /* Check for a passive interface */
346 14 : rip_passive_interface_apply(ifp);
347 :
348 : /* Apply distribute list to the all interface. */
349 14 : rip_distribute_update_interface(ifp);
350 :
351 14 : return 0;
352 : }
353 :
354 : /* Interface addition message from zebra. */
355 16 : static int rip_ifp_create(struct interface *ifp)
356 : {
357 32 : rip_interface_sync(ifp);
358 :
359 16 : 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 16 : rip_enable_apply(ifp);
368 :
369 : /* Check for a passive interface */
370 16 : rip_passive_interface_apply(ifp);
371 :
372 : /* Apply distribute list to the all interface. */
373 16 : rip_distribute_update_interface(ifp);
374 :
375 : /* rip_request_neighbor_all (); */
376 :
377 : /* Check interface routemap. */
378 16 : rip_if_rmap_update_interface(ifp);
379 :
380 16 : 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 16 : static void rip_interface_clean(struct rip_interface *ri)
426 : {
427 16 : ri->enable_network = 0;
428 16 : ri->enable_interface = 0;
429 16 : ri->running = 0;
430 :
431 16 : THREAD_OFF(ri->t_wakeup);
432 16 : }
433 :
434 1 : void rip_interfaces_clean(struct rip *rip)
435 : {
436 1 : struct interface *ifp;
437 :
438 1 : FOR_ALL_INTERFACES (rip->vrf, ifp)
439 0 : rip_interface_clean(ifp->info);
440 1 : }
441 :
442 16 : static void rip_interface_reset(struct rip_interface *ri)
443 : {
444 16 : ri->auth_type = yang_get_default_enum("%s/authentication-scheme/mode",
445 : RIP_IFACE);
446 16 : 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 32 : ri->split_horizon =
454 16 : yang_get_default_enum("%s/split-horizon", RIP_IFACE);
455 :
456 16 : ri->ri_send = yang_get_default_enum("%s/version-send", RIP_IFACE);
457 16 : ri->ri_receive = yang_get_default_enum("%s/version-receive", RIP_IFACE);
458 16 : ri->v2_broadcast = yang_get_default_bool("%s/v2-broadcast", RIP_IFACE);
459 :
460 16 : XFREE(MTYPE_RIP_INTERFACE_STRING, ri->auth_str);
461 :
462 16 : XFREE(MTYPE_RIP_INTERFACE_STRING, ri->key_chain);
463 :
464 16 : ri->list[RIP_FILTER_IN] = NULL;
465 16 : ri->list[RIP_FILTER_OUT] = NULL;
466 :
467 16 : ri->prefix[RIP_FILTER_IN] = NULL;
468 16 : ri->prefix[RIP_FILTER_OUT] = NULL;
469 :
470 16 : ri->recv_badpackets = 0;
471 16 : ri->recv_badroutes = 0;
472 16 : ri->sent_updates = 0;
473 :
474 16 : ri->passive = 0;
475 :
476 16 : rip_interface_clean(ri);
477 16 : }
478 :
479 0 : int rip_if_down(struct interface *ifp)
480 : {
481 0 : struct rip *rip;
482 0 : struct route_node *rp;
483 0 : struct rip_info *rinfo;
484 0 : struct rip_interface *ri = NULL;
485 0 : struct list *list = NULL;
486 0 : struct listnode *listnode = NULL, *nextnode = NULL;
487 :
488 0 : ri = ifp->info;
489 :
490 0 : THREAD_OFF(ri->t_wakeup);
491 :
492 0 : rip = ri->rip;
493 0 : if (rip) {
494 0 : for (rp = route_top(rip->table); rp; rp = route_next(rp))
495 0 : if ((list = rp->info) != NULL)
496 0 : for (ALL_LIST_ELEMENTS(list, listnode, nextnode,
497 : rinfo))
498 0 : if (rinfo->nh.ifindex == ifp->ifindex)
499 0 : rip_ecmp_delete(rip, rinfo);
500 :
501 0 : 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 0 : return 0;
513 : }
514 :
515 16 : static void rip_apply_address_add(struct connected *ifc)
516 : {
517 16 : struct rip_interface *ri = ifc->ifp->info;
518 16 : struct rip *rip = ri->rip;
519 16 : struct prefix_ipv4 address;
520 16 : struct nexthop nh;
521 16 : struct prefix *p;
522 :
523 16 : if (!rip)
524 0 : return;
525 :
526 16 : if (!if_is_up(ifc->ifp))
527 : return;
528 :
529 16 : p = ifc->address;
530 :
531 16 : memset(&address, 0, sizeof(address));
532 16 : memset(&nh, 0, sizeof(nh));
533 :
534 16 : address.family = p->family;
535 16 : address.prefix = p->u.prefix4;
536 16 : address.prefixlen = p->prefixlen;
537 16 : apply_mask_ipv4(&address);
538 :
539 16 : nh.ifindex = ifc->ifp->ifindex;
540 16 : 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 16 : if ((rip_enable_if_lookup(rip, ifc->ifp->name) >= 0)
545 16 : || (rip_enable_network_lookup2(ifc) >= 0))
546 2 : rip_redistribute_add(rip, ZEBRA_ROUTE_CONNECT,
547 : RIP_ROUTE_INTERFACE, &address, &nh, 0, 0,
548 : 0);
549 : }
550 :
551 27 : int rip_interface_address_add(ZAPI_CALLBACK_ARGS)
552 : {
553 27 : struct connected *ifc;
554 27 : struct prefix *p;
555 :
556 27 : ifc = zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD,
557 : zclient->ibuf, vrf_id);
558 :
559 27 : if (ifc == NULL)
560 : return 0;
561 :
562 27 : p = ifc->address;
563 :
564 27 : if (p->family == AF_INET) {
565 16 : if (IS_RIP_DEBUG_ZEBRA)
566 16 : zlog_debug("connected address %pFX is added", p);
567 :
568 16 : rip_enable_apply(ifc->ifp);
569 : /* Check if this prefix needs to be redistributed */
570 16 : rip_apply_address_add(ifc);
571 :
572 16 : hook_call(rip_ifaddr_add, ifc);
573 : }
574 :
575 : return 0;
576 : }
577 :
578 0 : static void rip_apply_address_del(struct connected *ifc)
579 : {
580 0 : struct rip_interface *ri = ifc->ifp->info;
581 0 : struct rip *rip = ri->rip;
582 0 : struct prefix_ipv4 address;
583 0 : struct prefix *p;
584 :
585 0 : if (!rip)
586 0 : return;
587 :
588 0 : if (!if_is_up(ifc->ifp))
589 : return;
590 :
591 0 : p = ifc->address;
592 :
593 0 : memset(&address, 0, sizeof(address));
594 0 : address.family = p->family;
595 0 : address.prefix = p->u.prefix4;
596 0 : address.prefixlen = p->prefixlen;
597 0 : apply_mask_ipv4(&address);
598 :
599 0 : rip_redistribute_delete(rip, ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE,
600 0 : &address, ifc->ifp->ifindex);
601 : }
602 :
603 0 : int rip_interface_address_delete(ZAPI_CALLBACK_ARGS)
604 : {
605 0 : struct connected *ifc;
606 0 : struct prefix *p;
607 :
608 0 : ifc = zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE,
609 : zclient->ibuf, vrf_id);
610 :
611 0 : if (ifc) {
612 0 : p = ifc->address;
613 0 : if (p->family == AF_INET) {
614 0 : if (IS_RIP_DEBUG_ZEBRA)
615 0 : zlog_debug("connected address %pFX is deleted",
616 : p);
617 :
618 0 : hook_call(rip_ifaddr_del, ifc);
619 :
620 : /* Chech whether this prefix needs to be removed */
621 0 : rip_apply_address_del(ifc);
622 : }
623 :
624 0 : connected_free(&ifc);
625 : }
626 :
627 0 : 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 46 : static int rip_enable_network_lookup_if(struct interface *ifp)
634 : {
635 46 : struct rip_interface *ri = ifp->info;
636 46 : struct rip *rip = ri->rip;
637 46 : struct listnode *node, *nnode;
638 46 : struct connected *connected;
639 46 : struct prefix_ipv4 address;
640 :
641 46 : if (!rip)
642 : return -1;
643 :
644 131 : for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, connected)) {
645 44 : struct prefix *p;
646 44 : struct route_node *n;
647 :
648 44 : p = connected->address;
649 :
650 44 : if (p->family == AF_INET) {
651 38 : address.family = AF_INET;
652 38 : address.prefix = p->u.prefix4;
653 38 : address.prefixlen = IPV4_MAX_BITLEN;
654 :
655 38 : n = route_node_match(rip->enable_network,
656 : (struct prefix *)&address);
657 38 : if (n) {
658 5 : route_unlock_node(n);
659 5 : return 1;
660 : }
661 : }
662 : }
663 : return -1;
664 : }
665 :
666 : /* Check whether connected is within the ripng_enable_network table. */
667 21 : static int rip_enable_network_lookup2(struct connected *connected)
668 : {
669 21 : struct rip_interface *ri = connected->ifp->info;
670 21 : struct rip *rip = ri->rip;
671 21 : struct prefix_ipv4 address;
672 21 : struct prefix *p;
673 :
674 21 : p = connected->address;
675 :
676 21 : if (p->family == AF_INET) {
677 21 : struct route_node *node;
678 :
679 21 : address.family = p->family;
680 21 : address.prefix = p->u.prefix4;
681 21 : address.prefixlen = IPV4_MAX_BITLEN;
682 :
683 : /* LPM on p->family, p->u.prefix4/IPV4_MAX_BITLEN within
684 : * rip->enable_network */
685 21 : node = route_node_match(rip->enable_network,
686 : (struct prefix *)&address);
687 :
688 21 : if (node) {
689 7 : route_unlock_node(node);
690 7 : return 1;
691 : }
692 : }
693 :
694 : return -1;
695 : }
696 : /* Add RIP enable network. */
697 1 : int rip_enable_network_add(struct rip *rip, struct prefix *p)
698 : {
699 1 : struct route_node *node;
700 :
701 1 : node = route_node_get(rip->enable_network, p);
702 :
703 1 : if (node->info) {
704 0 : route_unlock_node(node);
705 0 : return NB_ERR_INCONSISTENCY;
706 : } else
707 1 : node->info = (void *)1;
708 :
709 : /* XXX: One should find a better solution than a generic one */
710 1 : rip_enable_apply_all(rip);
711 :
712 1 : 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 67 : static int rip_enable_if_lookup(struct rip *rip, const char *ifname)
741 : {
742 67 : unsigned int i;
743 67 : char *str;
744 :
745 67 : if (!rip)
746 : return -1;
747 :
748 67 : for (i = 0; i < vector_active(rip->enable_interface); i++)
749 0 : if ((str = vector_slot(rip->enable_interface, i)) != NULL)
750 0 : if (strcmp(str, ifname) == 0)
751 0 : return i;
752 : return -1;
753 : }
754 :
755 : /* Add interface to rip_enable_if. */
756 0 : int rip_enable_if_add(struct rip *rip, const char *ifname)
757 : {
758 0 : int ret;
759 :
760 0 : ret = rip_enable_if_lookup(rip, ifname);
761 0 : if (ret >= 0)
762 : return NB_ERR_INCONSISTENCY;
763 :
764 0 : vector_set(rip->enable_interface,
765 : XSTRDUP(MTYPE_RIP_INTERFACE_STRING, ifname));
766 :
767 0 : rip_enable_apply_all(rip); /* TODOVJ */
768 :
769 0 : 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 1 : static void rip_interface_wakeup(struct thread *t)
793 : {
794 1 : struct interface *ifp;
795 1 : struct rip_interface *ri;
796 :
797 : /* Get interface. */
798 1 : ifp = THREAD_ARG(t);
799 :
800 1 : ri = ifp->info;
801 :
802 : /* Join to multicast group. */
803 1 : 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 1 : ri->running = 1;
812 :
813 : /* Send RIP request to the interface. */
814 1 : rip_request_interface(ifp);
815 : }
816 :
817 5 : static void rip_connect_set(struct interface *ifp, int set)
818 : {
819 5 : struct rip_interface *ri = ifp->info;
820 5 : struct rip *rip = ri->rip;
821 5 : struct listnode *node, *nnode;
822 5 : struct connected *connected;
823 5 : struct prefix_ipv4 address;
824 5 : struct nexthop nh;
825 :
826 5 : memset(&nh, 0, sizeof(nh));
827 :
828 15 : for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, connected)) {
829 5 : struct prefix *p;
830 5 : p = connected->address;
831 :
832 5 : if (p->family != AF_INET)
833 0 : continue;
834 :
835 5 : address.family = AF_INET;
836 5 : address.prefix = p->u.prefix4;
837 5 : address.prefixlen = p->prefixlen;
838 5 : apply_mask_ipv4(&address);
839 :
840 5 : nh.ifindex = connected->ifp->ifindex;
841 5 : nh.type = NEXTHOP_TYPE_IFINDEX;
842 5 : if (set) {
843 : /* Check once more whether this prefix is within a
844 : * "network IF_OR_PREF" one */
845 5 : if ((rip_enable_if_lookup(rip, connected->ifp->name)
846 : >= 0)
847 5 : || (rip_enable_network_lookup2(connected) >= 0))
848 5 : 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 5 : }
862 :
863 : /* Update interface status. */
864 46 : void rip_enable_apply(struct interface *ifp)
865 : {
866 46 : int ret;
867 46 : struct rip_interface *ri = NULL;
868 :
869 : /* Check interface. */
870 46 : if (!if_is_operative(ifp))
871 : return;
872 :
873 46 : ri = ifp->info;
874 :
875 : /* Check network configuration. */
876 46 : ret = rip_enable_network_lookup_if(ifp);
877 :
878 : /* If the interface is matched. */
879 46 : if (ret > 0)
880 5 : ri->enable_network = 1;
881 : else
882 41 : ri->enable_network = 0;
883 :
884 : /* Check interface name configuration. */
885 46 : ret = rip_enable_if_lookup(ri->rip, ifp->name);
886 46 : if (ret >= 0)
887 0 : ri->enable_interface = 1;
888 : else
889 46 : ri->enable_interface = 0;
890 :
891 : /* any interface MUST have an IPv4 address */
892 46 : if (!rip_if_ipv4_address_check(ifp)) {
893 8 : ri->enable_network = 0;
894 8 : ri->enable_interface = 0;
895 : }
896 :
897 : /* Update running status of the interface. */
898 46 : if (ri->enable_network || ri->enable_interface) {
899 5 : if (IS_RIP_DEBUG_EVENT)
900 5 : zlog_debug("turn on %s", ifp->name);
901 :
902 : /* Add interface wake up thread. */
903 5 : thread_add_timer(master, rip_interface_wakeup, ifp, 1,
904 : &ri->t_wakeup);
905 5 : rip_connect_set(ifp, 1);
906 41 : } 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 1 : static void rip_enable_apply_all(struct rip *rip)
919 : {
920 1 : struct interface *ifp;
921 :
922 : /* Check each interface. */
923 2 : FOR_ALL_INTERFACES (rip->vrf, ifp)
924 0 : rip_enable_apply(ifp);
925 1 : }
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 1 : void rip_clean_network(struct rip *rip)
983 : {
984 1 : unsigned int i;
985 1 : char *str;
986 1 : struct route_node *rn;
987 :
988 : /* rip->enable_network. */
989 2 : for (rn = route_top(rip->enable_network); rn; rn = route_next(rn))
990 1 : if (rn->info) {
991 1 : rn->info = NULL;
992 1 : route_unlock_node(rn);
993 : }
994 :
995 : /* rip->enable_interface. */
996 1 : for (i = 0; i < vector_active(rip->enable_interface); i++)
997 0 : if ((str = vector_slot(rip->enable_interface, i)) != NULL) {
998 0 : XFREE(MTYPE_RIP_INTERFACE_STRING, str);
999 0 : vector_slot(rip->enable_interface, i) = NULL;
1000 : }
1001 1 : }
1002 :
1003 : /* Utility function for looking up passive interface settings. */
1004 30 : static int rip_passive_nondefault_lookup(struct rip *rip, const char *ifname)
1005 : {
1006 30 : unsigned int i;
1007 30 : char *str;
1008 :
1009 30 : for (i = 0; i < vector_active(rip->passive_nondefault); i++)
1010 0 : if ((str = vector_slot(rip->passive_nondefault, i)) != NULL)
1011 0 : if (strcmp(str, ifname) == 0)
1012 0 : return i;
1013 : return -1;
1014 : }
1015 :
1016 30 : static void rip_passive_interface_apply(struct interface *ifp)
1017 : {
1018 30 : struct rip *rip;
1019 30 : struct rip_interface *ri;
1020 :
1021 30 : ri = ifp->info;
1022 30 : rip = ri->rip;
1023 30 : if (rip == NULL)
1024 : return;
1025 :
1026 30 : ri->passive = ((rip_passive_nondefault_lookup(rip, ifp->name) < 0)
1027 30 : ? rip->passive_default
1028 30 : : !rip->passive_default);
1029 :
1030 30 : if (IS_RIP_DEBUG_ZEBRA)
1031 30 : zlog_debug("interface %s: passive = %d", ifp->name,
1032 : ri->passive);
1033 : }
1034 :
1035 1 : static void rip_passive_interface_apply_all(struct rip *rip)
1036 : {
1037 1 : struct interface *ifp;
1038 :
1039 1 : FOR_ALL_INTERFACES (rip->vrf, ifp)
1040 0 : rip_passive_interface_apply(ifp);
1041 1 : }
1042 :
1043 : /* Passive interface. */
1044 0 : int rip_passive_nondefault_set(struct rip *rip, const char *ifname)
1045 : {
1046 0 : 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 0 : vector_set(rip->passive_nondefault,
1054 : XSTRDUP(MTYPE_RIP_INTERFACE_STRING, ifname));
1055 :
1056 0 : rip_passive_interface_apply_all(rip);
1057 :
1058 0 : 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 1 : void rip_passive_nondefault_clean(struct rip *rip)
1085 : {
1086 1 : unsigned int i;
1087 1 : char *str;
1088 :
1089 1 : for (i = 0; i < vector_active(rip->passive_nondefault); i++)
1090 0 : if ((str = vector_slot(rip->passive_nondefault, i)) != NULL) {
1091 0 : XFREE(MTYPE_RIP_INTERFACE_STRING, str);
1092 0 : vector_slot(rip->passive_nondefault, i) = NULL;
1093 : }
1094 1 : rip_passive_interface_apply_all(rip);
1095 1 : }
1096 :
1097 1 : int rip_show_network_config(struct vty *vty, struct rip *rip)
1098 : {
1099 1 : unsigned int i;
1100 1 : char *ifname;
1101 1 : struct route_node *node;
1102 :
1103 : /* Network type RIP enable interface statement. */
1104 2 : for (node = route_top(rip->enable_network); node;
1105 1 : node = route_next(node))
1106 1 : if (node->info)
1107 1 : vty_out(vty, " %pFX\n", &node->p);
1108 :
1109 : /* Interface name RIP enable statement. */
1110 1 : for (i = 0; i < vector_active(rip->enable_interface); i++)
1111 0 : if ((ifname = vector_slot(rip->enable_interface, i)) != NULL)
1112 0 : vty_out(vty, " %s\n", ifname);
1113 :
1114 : /* RIP neighbors listing. */
1115 1 : 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 1 : return 0;
1120 : }
1121 :
1122 46 : void rip_interface_sync(struct interface *ifp)
1123 : {
1124 46 : struct rip_interface *ri;
1125 :
1126 46 : ri = ifp->info;
1127 38 : if (ri)
1128 46 : ri->rip = ifp->vrf->info;
1129 8 : }
1130 :
1131 : /* Called when interface structure allocated. */
1132 8 : static int rip_interface_new_hook(struct interface *ifp)
1133 : {
1134 8 : ifp->info = rip_interface_new();
1135 8 : rip_interface_sync(ifp);
1136 :
1137 8 : return 0;
1138 : }
1139 :
1140 : /* Called when interface structure deleted. */
1141 8 : static int rip_interface_delete_hook(struct interface *ifp)
1142 : {
1143 8 : rip_interface_reset(ifp->info);
1144 8 : XFREE(MTYPE_RIP_INTERFACE, ifp->info);
1145 8 : return 0;
1146 : }
1147 :
1148 : /* Allocate and initialize interface vector. */
1149 1 : void rip_if_init(void)
1150 : {
1151 : /* Default initial size of interface vector. */
1152 1 : hook_register_prio(if_add, 0, rip_interface_new_hook);
1153 1 : hook_register_prio(if_del, 0, rip_interface_delete_hook);
1154 :
1155 : /* Install interface node. */
1156 1 : if_cmd_init_default();
1157 1 : if_zapi_callbacks(rip_ifp_create, rip_ifp_up,
1158 : rip_ifp_down, rip_ifp_destroy);
1159 1 : }
|