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