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