]> git.proxmox.com Git - mirror_frr.git/blame - ripd/rip_interface.c
Merge pull request #13254 from manojvn/remove_startupjson_doc
[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;
718e3744 460
d62a17ae 461 rip_interface_clean(ri);
4305dfd1 462}
718e3744 463
d62a17ae 464int rip_if_down(struct interface *ifp)
718e3744 465{
045c5389 466 struct rip *rip;
d62a17ae 467 struct route_node *rp;
468 struct rip_info *rinfo;
469 struct rip_interface *ri = NULL;
470 struct list *list = NULL;
471 struct listnode *listnode = NULL, *nextnode = NULL;
045c5389
RW
472
473 ri = ifp->info;
8f0c2688 474
e16d030c 475 EVENT_OFF(ri->t_wakeup);
8f0c2688 476
045c5389 477 rip = ri->rip;
d62a17ae 478 if (rip) {
479 for (rp = route_top(rip->table); rp; rp = route_next(rp))
480 if ((list = rp->info) != NULL)
481 for (ALL_LIST_ELEMENTS(list, listnode, nextnode,
482 rinfo))
dd127197 483 if (rinfo->nh.ifindex == ifp->ifindex)
045c5389 484 rip_ecmp_delete(rip, rinfo);
d62a17ae 485
486 if (ri->running) {
487 if (IS_RIP_DEBUG_EVENT)
488 zlog_debug("turn off %s", ifp->name);
489
490 /* Leave from multicast group. */
491 rip_multicast_leave(ifp, rip->sock);
492
493 ri->running = 0;
494 }
495 }
496
497 return 0;
718e3744 498}
499
d62a17ae 500static void rip_apply_address_add(struct connected *ifc)
dc63bfd4 501{
045c5389
RW
502 struct rip_interface *ri = ifc->ifp->info;
503 struct rip *rip = ri->rip;
d62a17ae 504 struct prefix_ipv4 address;
3f5682c8 505 struct nexthop nh;
d62a17ae 506 struct prefix *p;
16705130 507
d62a17ae 508 if (!rip)
509 return;
16705130 510
d62a17ae 511 if (!if_is_up(ifc->ifp))
512 return;
16705130 513
d62a17ae 514 p = ifc->address;
16705130 515
d62a17ae 516 memset(&address, 0, sizeof(address));
3f5682c8
DS
517 memset(&nh, 0, sizeof(nh));
518
d62a17ae 519 address.family = p->family;
520 address.prefix = p->u.prefix4;
521 address.prefixlen = p->prefixlen;
522 apply_mask_ipv4(&address);
16705130 523
3f5682c8
DS
524 nh.ifindex = ifc->ifp->ifindex;
525 nh.type = NEXTHOP_TYPE_IFINDEX;
526
d62a17ae 527 /* Check if this interface is RIP enabled or not
528 or Check if this address's prefix is RIP enabled */
045c5389 529 if ((rip_enable_if_lookup(rip, ifc->ifp->name) >= 0)
d62a17ae 530 || (rip_enable_network_lookup2(ifc) >= 0))
045c5389
RW
531 rip_redistribute_add(rip, ZEBRA_ROUTE_CONNECT,
532 RIP_ROUTE_INTERFACE, &address, &nh, 0, 0,
533 0);
16705130 534}
535
121f9dee 536int rip_interface_address_add(ZAPI_CALLBACK_ARGS)
718e3744 537{
d62a17ae 538 struct connected *ifc;
539 struct prefix *p;
718e3744 540
d62a17ae 541 ifc = zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD,
542 zclient->ibuf, vrf_id);
718e3744 543
d62a17ae 544 if (ifc == NULL)
545 return 0;
718e3744 546
d62a17ae 547 p = ifc->address;
718e3744 548
d62a17ae 549 if (p->family == AF_INET) {
550 if (IS_RIP_DEBUG_ZEBRA)
f42238f8 551 zlog_debug("connected address %pFX is added", p);
16705130 552
d62a17ae 553 rip_enable_apply(ifc->ifp);
554 /* Check if this prefix needs to be redistributed */
555 rip_apply_address_add(ifc);
718e3744 556
d62a17ae 557 hook_call(rip_ifaddr_add, ifc);
558 }
718e3744 559
d62a17ae 560 return 0;
718e3744 561}
562
d62a17ae 563static void rip_apply_address_del(struct connected *ifc)
564{
045c5389
RW
565 struct rip_interface *ri = ifc->ifp->info;
566 struct rip *rip = ri->rip;
d62a17ae 567 struct prefix_ipv4 address;
568 struct prefix *p;
16705130 569
d62a17ae 570 if (!rip)
571 return;
16705130 572
d62a17ae 573 if (!if_is_up(ifc->ifp))
574 return;
16705130 575
d62a17ae 576 p = ifc->address;
16705130 577
d62a17ae 578 memset(&address, 0, sizeof(address));
579 address.family = p->family;
580 address.prefix = p->u.prefix4;
581 address.prefixlen = p->prefixlen;
582 apply_mask_ipv4(&address);
16705130 583
045c5389 584 rip_redistribute_delete(rip, ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE,
d62a17ae 585 &address, ifc->ifp->ifindex);
16705130 586}
587
121f9dee 588int rip_interface_address_delete(ZAPI_CALLBACK_ARGS)
718e3744 589{
d62a17ae 590 struct connected *ifc;
591 struct prefix *p;
718e3744 592
d62a17ae 593 ifc = zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE,
594 zclient->ibuf, vrf_id);
718e3744 595
d62a17ae 596 if (ifc) {
597 p = ifc->address;
598 if (p->family == AF_INET) {
599 if (IS_RIP_DEBUG_ZEBRA)
f42238f8
DS
600 zlog_debug("connected address %pFX is deleted",
601 p);
16705130 602
d62a17ae 603 hook_call(rip_ifaddr_del, ifc);
718e3744 604
f89c0aed 605 /* Chech whether this prefix needs to be removed */
d62a17ae 606 rip_apply_address_del(ifc);
607 }
718e3744 608
721c0857 609 connected_free(&ifc);
d62a17ae 610 }
718e3744 611
d62a17ae 612 return 0;
718e3744 613}
6b0655a2 614
718e3744 615/* Check interface is enabled by network statement. */
f89c0aed 616/* Check whether the interface has at least a connected prefix that
16705130 617 * is within the ripng_enable_network table. */
d62a17ae 618static int rip_enable_network_lookup_if(struct interface *ifp)
619{
045c5389
RW
620 struct rip_interface *ri = ifp->info;
621 struct rip *rip = ri->rip;
d62a17ae 622 struct listnode *node, *nnode;
623 struct connected *connected;
624 struct prefix_ipv4 address;
625
1205fdc4
RW
626 if (!rip)
627 return -1;
628
d62a17ae 629 for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, connected)) {
630 struct prefix *p;
dc7204b7 631 struct route_node *n;
d62a17ae 632
633 p = connected->address;
634
635 if (p->family == AF_INET) {
636 address.family = AF_INET;
637 address.prefix = p->u.prefix4;
638 address.prefixlen = IPV4_MAX_BITLEN;
639
1205fdc4 640 n = route_node_match(rip->enable_network,
dc7204b7
A
641 (struct prefix *)&address);
642 if (n) {
643 route_unlock_node(n);
d62a17ae 644 return 1;
645 }
646 }
647 }
648 return -1;
718e3744 649}
650
f89c0aed 651/* Check whether connected is within the ripng_enable_network table. */
045c5389 652static int rip_enable_network_lookup2(struct connected *connected)
16705130 653{
045c5389
RW
654 struct rip_interface *ri = connected->ifp->info;
655 struct rip *rip = ri->rip;
d62a17ae 656 struct prefix_ipv4 address;
657 struct prefix *p;
16705130 658
d62a17ae 659 p = connected->address;
16705130 660
d62a17ae 661 if (p->family == AF_INET) {
662 struct route_node *node;
16705130 663
d62a17ae 664 address.family = p->family;
665 address.prefix = p->u.prefix4;
666 address.prefixlen = IPV4_MAX_BITLEN;
16705130 667
d62a17ae 668 /* LPM on p->family, p->u.prefix4/IPV4_MAX_BITLEN within
1205fdc4
RW
669 * rip->enable_network */
670 node = route_node_match(rip->enable_network,
d62a17ae 671 (struct prefix *)&address);
16705130 672
d62a17ae 673 if (node) {
674 route_unlock_node(node);
675 return 1;
676 }
677 }
16705130 678
d62a17ae 679 return -1;
16705130 680}
718e3744 681/* Add RIP enable network. */
045c5389 682int rip_enable_network_add(struct rip *rip, struct prefix *p)
718e3744 683{
d62a17ae 684 struct route_node *node;
718e3744 685
1205fdc4 686 node = route_node_get(rip->enable_network, p);
718e3744 687
d62a17ae 688 if (node->info) {
689 route_unlock_node(node);
3d7a1be8 690 return NB_ERR_INCONSISTENCY;
d62a17ae 691 } else
692 node->info = (void *)1;
718e3744 693
d62a17ae 694 /* XXX: One should find a better solution than a generic one */
045c5389 695 rip_enable_apply_all(rip);
16705130 696
3d7a1be8 697 return NB_OK;
718e3744 698}
699
700/* Delete RIP enable network. */
045c5389 701int rip_enable_network_delete(struct rip *rip, struct prefix *p)
718e3744 702{
d62a17ae 703 struct route_node *node;
718e3744 704
1205fdc4 705 node = route_node_lookup(rip->enable_network, p);
d62a17ae 706 if (node) {
707 node->info = NULL;
718e3744 708
d62a17ae 709 /* Unlock info lock. */
710 route_unlock_node(node);
718e3744 711
d62a17ae 712 /* Unlock lookup lock. */
713 route_unlock_node(node);
718e3744 714
d62a17ae 715 /* XXX: One should find a better solution than a generic one */
045c5389 716 rip_enable_apply_all(rip);
16705130 717
3d7a1be8 718 return NB_OK;
d62a17ae 719 }
3d7a1be8
RW
720
721 return NB_ERR_INCONSISTENCY;
718e3744 722}
723
724/* Check interface is enabled by ifname statement. */
045c5389 725static int rip_enable_if_lookup(struct rip *rip, const char *ifname)
718e3744 726{
d62a17ae 727 unsigned int i;
728 char *str;
718e3744 729
ca046902
RW
730 if (!rip)
731 return -1;
732
733 for (i = 0; i < vector_active(rip->enable_interface); i++)
734 if ((str = vector_slot(rip->enable_interface, i)) != NULL)
d62a17ae 735 if (strcmp(str, ifname) == 0)
736 return i;
737 return -1;
718e3744 738}
739
740/* Add interface to rip_enable_if. */
045c5389 741int rip_enable_if_add(struct rip *rip, const char *ifname)
718e3744 742{
d62a17ae 743 int ret;
718e3744 744
045c5389 745 ret = rip_enable_if_lookup(rip, ifname);
d62a17ae 746 if (ret >= 0)
3d7a1be8 747 return NB_ERR_INCONSISTENCY;
718e3744 748
ca046902 749 vector_set(rip->enable_interface,
03c20031 750 XSTRDUP(MTYPE_RIP_INTERFACE_STRING, ifname));
718e3744 751
045c5389 752 rip_enable_apply_all(rip); /* TODOVJ */
16705130 753
3d7a1be8 754 return NB_OK;
718e3744 755}
756
757/* Delete interface from rip_enable_if. */
045c5389 758int rip_enable_if_delete(struct rip *rip, const char *ifname)
718e3744 759{
d62a17ae 760 int index;
761 char *str;
718e3744 762
045c5389 763 index = rip_enable_if_lookup(rip, ifname);
d62a17ae 764 if (index < 0)
3d7a1be8 765 return NB_ERR_INCONSISTENCY;
718e3744 766
ca046902 767 str = vector_slot(rip->enable_interface, index);
03c20031 768 XFREE(MTYPE_RIP_INTERFACE_STRING, str);
ca046902 769 vector_unset(rip->enable_interface, index);
718e3744 770
045c5389 771 rip_enable_apply_all(rip); /* TODOVJ */
16705130 772
3d7a1be8 773 return NB_OK;
718e3744 774}
775
776/* Join to multicast group and send request to the interface. */
e6685141 777static void rip_interface_wakeup(struct event *t)
718e3744 778{
d62a17ae 779 struct interface *ifp;
780 struct rip_interface *ri;
718e3744 781
d62a17ae 782 /* Get interface. */
e16d030c 783 ifp = EVENT_ARG(t);
718e3744 784
d62a17ae 785 ri = ifp->info;
718e3744 786
d62a17ae 787 /* Join to multicast group. */
045c5389 788 if (rip_multicast_join(ifp, ri->rip->sock) < 0) {
450971aa 789 flog_err_sys(EC_LIB_SOCKET,
09c866e3
QY
790 "multicast join failed, interface %s not running",
791 ifp->name);
cc9f21da 792 return;
d62a17ae 793 }
718e3744 794
d62a17ae 795 /* Set running flag. */
796 ri->running = 1;
797
798 /* Send RIP request to the interface. */
799 rip_request_interface(ifp);
d62a17ae 800}
801
802static void rip_connect_set(struct interface *ifp, int set)
803{
045c5389
RW
804 struct rip_interface *ri = ifp->info;
805 struct rip *rip = ri->rip;
d62a17ae 806 struct listnode *node, *nnode;
807 struct connected *connected;
808 struct prefix_ipv4 address;
3f5682c8
DS
809 struct nexthop nh;
810
811 memset(&nh, 0, sizeof(nh));
d62a17ae 812
813 for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, connected)) {
814 struct prefix *p;
815 p = connected->address;
816
817 if (p->family != AF_INET)
818 continue;
819
820 address.family = AF_INET;
821 address.prefix = p->u.prefix4;
822 address.prefixlen = p->prefixlen;
823 apply_mask_ipv4(&address);
824
3f5682c8
DS
825 nh.ifindex = connected->ifp->ifindex;
826 nh.type = NEXTHOP_TYPE_IFINDEX;
d62a17ae 827 if (set) {
f89c0aed 828 /* Check once more whether this prefix is within a
d62a17ae 829 * "network IF_OR_PREF" one */
045c5389
RW
830 if ((rip_enable_if_lookup(rip, connected->ifp->name)
831 >= 0)
d62a17ae 832 || (rip_enable_network_lookup2(connected) >= 0))
045c5389 833 rip_redistribute_add(rip, ZEBRA_ROUTE_CONNECT,
996c9314
LB
834 RIP_ROUTE_INTERFACE,
835 &address, &nh, 0, 0, 0);
d62a17ae 836 } else {
045c5389 837 rip_redistribute_delete(rip, ZEBRA_ROUTE_CONNECT,
d62a17ae 838 RIP_ROUTE_INTERFACE, &address,
839 connected->ifp->ifindex);
045c5389
RW
840 if (rip_redistribute_check(rip, ZEBRA_ROUTE_CONNECT))
841 rip_redistribute_add(rip, ZEBRA_ROUTE_CONNECT,
996c9314
LB
842 RIP_ROUTE_REDISTRIBUTE,
843 &address, &nh, 0, 0, 0);
d62a17ae 844 }
845 }
718e3744 846}
847
848/* Update interface status. */
d62a17ae 849void rip_enable_apply(struct interface *ifp)
718e3744 850{
d62a17ae 851 int ret;
852 struct rip_interface *ri = NULL;
718e3744 853
d62a17ae 854 /* Check interface. */
855 if (!if_is_operative(ifp))
856 return;
718e3744 857
d62a17ae 858 ri = ifp->info;
859
860 /* Check network configuration. */
861 ret = rip_enable_network_lookup_if(ifp);
862
863 /* If the interface is matched. */
864 if (ret > 0)
865 ri->enable_network = 1;
866 else
867 ri->enable_network = 0;
868
869 /* Check interface name configuration. */
045c5389 870 ret = rip_enable_if_lookup(ri->rip, ifp->name);
d62a17ae 871 if (ret >= 0)
872 ri->enable_interface = 1;
873 else
874 ri->enable_interface = 0;
718e3744 875
d62a17ae 876 /* any interface MUST have an IPv4 address */
877 if (!rip_if_ipv4_address_check(ifp)) {
878 ri->enable_network = 0;
879 ri->enable_interface = 0;
718e3744 880 }
718e3744 881
d62a17ae 882 /* Update running status of the interface. */
883 if (ri->enable_network || ri->enable_interface) {
2e37ad7f
RW
884 if (IS_RIP_DEBUG_EVENT)
885 zlog_debug("turn on %s", ifp->name);
886
887 /* Add interface wake up thread. */
907a2395
DS
888 event_add_timer(master, rip_interface_wakeup, ifp, 1,
889 &ri->t_wakeup);
2e37ad7f
RW
890 rip_connect_set(ifp, 1);
891 } else if (ri->running) {
892 /* Might as well clean up the route table as well
893 * rip_if_down sets to 0 ri->running, and displays "turn
894 *off %s"
895 **/
896 rip_if_down(ifp);
d62a17ae 897
2e37ad7f 898 rip_connect_set(ifp, 0);
718e3744 899 }
718e3744 900}
901
902/* Apply network configuration to all interface. */
045c5389 903static void rip_enable_apply_all(struct rip *rip)
718e3744 904{
d62a17ae 905 struct interface *ifp;
718e3744 906
d62a17ae 907 /* Check each interface. */
ae7b826a 908 FOR_ALL_INTERFACES (rip->vrf, ifp)
d62a17ae 909 rip_enable_apply(ifp);
718e3744 910}
911
045c5389 912int rip_neighbor_lookup(struct rip *rip, struct sockaddr_in *from)
718e3744 913{
d62a17ae 914 struct prefix_ipv4 p;
915 struct route_node *node;
718e3744 916
6006b807 917 memset(&p, 0, sizeof(p));
d62a17ae 918 p.family = AF_INET;
919 p.prefix = from->sin_addr;
920 p.prefixlen = IPV4_MAX_BITLEN;
718e3744 921
d62a17ae 922 node = route_node_lookup(rip->neighbor, (struct prefix *)&p);
923 if (node) {
924 route_unlock_node(node);
925 return 1;
926 }
927 return 0;
718e3744 928}
929
930/* Add new RIP neighbor to the neighbor tree. */
045c5389 931int rip_neighbor_add(struct rip *rip, struct prefix_ipv4 *p)
718e3744 932{
d62a17ae 933 struct route_node *node;
718e3744 934
d62a17ae 935 node = route_node_get(rip->neighbor, (struct prefix *)p);
718e3744 936
d62a17ae 937 if (node->info)
f0ab22fb 938 return NB_ERR_INCONSISTENCY;
718e3744 939
d62a17ae 940 node->info = rip->neighbor;
718e3744 941
f0ab22fb 942 return NB_OK;
718e3744 943}
944
945/* Delete RIP neighbor from the neighbor tree. */
045c5389 946int rip_neighbor_delete(struct rip *rip, struct prefix_ipv4 *p)
718e3744 947{
d62a17ae 948 struct route_node *node;
718e3744 949
d62a17ae 950 /* Lock for look up. */
951 node = route_node_lookup(rip->neighbor, (struct prefix *)p);
952 if (!node)
f0ab22fb 953 return NB_ERR_INCONSISTENCY;
718e3744 954
d62a17ae 955 node->info = NULL;
718e3744 956
d62a17ae 957 /* Unlock lookup lock. */
958 route_unlock_node(node);
718e3744 959
d62a17ae 960 /* Unlock real neighbor information lock. */
961 route_unlock_node(node);
962
f0ab22fb 963 return NB_OK;
718e3744 964}
965
966/* Clear all network and neighbor configuration. */
045c5389 967void rip_clean_network(struct rip *rip)
d62a17ae 968{
969 unsigned int i;
970 char *str;
971 struct route_node *rn;
972
1205fdc4
RW
973 /* rip->enable_network. */
974 for (rn = route_top(rip->enable_network); rn; rn = route_next(rn))
d62a17ae 975 if (rn->info) {
976 rn->info = NULL;
977 route_unlock_node(rn);
978 }
979
ca046902
RW
980 /* rip->enable_interface. */
981 for (i = 0; i < vector_active(rip->enable_interface); i++)
982 if ((str = vector_slot(rip->enable_interface, i)) != NULL) {
03c20031 983 XFREE(MTYPE_RIP_INTERFACE_STRING, str);
ca046902 984 vector_slot(rip->enable_interface, i) = NULL;
d62a17ae 985 }
718e3744 986}
6b0655a2 987
718e3744 988/* Utility function for looking up passive interface settings. */
045c5389 989static int rip_passive_nondefault_lookup(struct rip *rip, const char *ifname)
718e3744 990{
d62a17ae 991 unsigned int i;
992 char *str;
718e3744 993
5a29c0d5
RW
994 for (i = 0; i < vector_active(rip->passive_nondefault); i++)
995 if ((str = vector_slot(rip->passive_nondefault, i)) != NULL)
d62a17ae 996 if (strcmp(str, ifname) == 0)
997 return i;
998 return -1;
718e3744 999}
1000
045c5389 1001static void rip_passive_interface_apply(struct interface *ifp)
718e3744 1002{
045c5389 1003 struct rip *rip;
d62a17ae 1004 struct rip_interface *ri;
718e3744 1005
045c5389
RW
1006 ri = ifp->info;
1007 rip = ri->rip;
44f2f852
RW
1008 if (rip == NULL)
1009 return;
1010
045c5389 1011 ri->passive = ((rip_passive_nondefault_lookup(rip, ifp->name) < 0)
44f2f852
RW
1012 ? rip->passive_default
1013 : !rip->passive_default);
4aaff3f8 1014
d62a17ae 1015 if (IS_RIP_DEBUG_ZEBRA)
1016 zlog_debug("interface %s: passive = %d", ifp->name,
1017 ri->passive);
718e3744 1018}
1019
045c5389 1020static void rip_passive_interface_apply_all(struct rip *rip)
718e3744 1021{
d62a17ae 1022 struct interface *ifp;
718e3744 1023
ae7b826a 1024 FOR_ALL_INTERFACES (rip->vrf, ifp)
d62a17ae 1025 rip_passive_interface_apply(ifp);
718e3744 1026}
1027
1028/* Passive interface. */
045c5389 1029int rip_passive_nondefault_set(struct rip *rip, const char *ifname)
718e3744 1030{
045c5389 1031 if (rip_passive_nondefault_lookup(rip, ifname) >= 0)
44f2f852
RW
1032 /*
1033 * Don't return an error, this can happen after changing
1034 * 'passive-default'.
1035 */
1036 return NB_OK;
718e3744 1037
5a29c0d5 1038 vector_set(rip->passive_nondefault,
03c20031 1039 XSTRDUP(MTYPE_RIP_INTERFACE_STRING, ifname));
718e3744 1040
045c5389 1041 rip_passive_interface_apply_all(rip);
718e3744 1042
44f2f852 1043 return NB_OK;
718e3744 1044}
1045
045c5389 1046int rip_passive_nondefault_unset(struct rip *rip, const char *ifname)
718e3744 1047{
d62a17ae 1048 int i;
1049 char *str;
718e3744 1050
045c5389 1051 i = rip_passive_nondefault_lookup(rip, ifname);
d62a17ae 1052 if (i < 0)
44f2f852
RW
1053 /*
1054 * Don't return an error, this can happen after changing
1055 * 'passive-default'.
1056 */
1057 return NB_OK;
718e3744 1058
5a29c0d5 1059 str = vector_slot(rip->passive_nondefault, i);
03c20031 1060 XFREE(MTYPE_RIP_INTERFACE_STRING, str);
5a29c0d5 1061 vector_unset(rip->passive_nondefault, i);
718e3744 1062
045c5389 1063 rip_passive_interface_apply_all(rip);
718e3744 1064
44f2f852 1065 return NB_OK;
718e3744 1066}
1067
1068/* Free all configured RIP passive-interface settings. */
045c5389 1069void rip_passive_nondefault_clean(struct rip *rip)
718e3744 1070{
d62a17ae 1071 unsigned int i;
1072 char *str;
718e3744 1073
5a29c0d5
RW
1074 for (i = 0; i < vector_active(rip->passive_nondefault); i++)
1075 if ((str = vector_slot(rip->passive_nondefault, i)) != NULL) {
03c20031 1076 XFREE(MTYPE_RIP_INTERFACE_STRING, str);
5a29c0d5 1077 vector_slot(rip->passive_nondefault, i) = NULL;
d62a17ae 1078 }
045c5389 1079 rip_passive_interface_apply_all(rip);
718e3744 1080}
6b0655a2 1081
045c5389 1082int rip_show_network_config(struct vty *vty, struct rip *rip)
d62a17ae 1083{
1084 unsigned int i;
1085 char *ifname;
1086 struct route_node *node;
1087
1088 /* Network type RIP enable interface statement. */
1205fdc4 1089 for (node = route_top(rip->enable_network); node;
d62a17ae 1090 node = route_next(node))
1091 if (node->info)
53bb7f9b 1092 vty_out(vty, " %pFX\n", &node->p);
d62a17ae 1093
1094 /* Interface name RIP enable statement. */
ca046902
RW
1095 for (i = 0; i < vector_active(rip->enable_interface); i++)
1096 if ((ifname = vector_slot(rip->enable_interface, i)) != NULL)
44f2f852 1097 vty_out(vty, " %s\n", ifname);
d62a17ae 1098
1099 /* RIP neighbors listing. */
1100 for (node = route_top(rip->neighbor); node; node = route_next(node))
1101 if (node->info)
53bb7f9b 1102 vty_out(vty, " %pI4\n", &node->p.u.prefix4);
718e3744 1103
d62a17ae 1104 return 0;
1105}
1106
ae7b826a
RW
1107void rip_interface_sync(struct interface *ifp)
1108{
096f7609 1109 struct rip_interface *ri;
ae7b826a 1110
096f7609
IR
1111 ri = ifp->info;
1112 if (ri)
1113 ri->rip = ifp->vrf->info;
ae7b826a
RW
1114}
1115
718e3744 1116/* Called when interface structure allocated. */
d62a17ae 1117static int rip_interface_new_hook(struct interface *ifp)
718e3744 1118{
d62a17ae 1119 ifp->info = rip_interface_new();
ae7b826a
RW
1120 rip_interface_sync(ifp);
1121
d62a17ae 1122 return 0;
718e3744 1123}
1124
1125/* Called when interface structure deleted. */
d62a17ae 1126static int rip_interface_delete_hook(struct interface *ifp)
718e3744 1127{
72010aca 1128 rip_interface_reset(ifp->info);
d62a17ae 1129 XFREE(MTYPE_RIP_INTERFACE, ifp->info);
d62a17ae 1130 return 0;
718e3744 1131}
1132
1133/* Allocate and initialize interface vector. */
d62a17ae 1134void rip_if_init(void)
718e3744 1135{
d62a17ae 1136 /* Default initial size of interface vector. */
ce19a04a
DL
1137 hook_register_prio(if_add, 0, rip_interface_new_hook);
1138 hook_register_prio(if_del, 0, rip_interface_delete_hook);
d62a17ae 1139
d62a17ae 1140 /* Install interface node. */
104fd767 1141 if_cmd_init_default();
138c5a74
DS
1142 if_zapi_callbacks(rip_ifp_create, rip_ifp_up,
1143 rip_ifp_down, rip_ifp_destroy);
718e3744 1144}