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