]> git.proxmox.com Git - mirror_frr.git/blame - ripd/rip_interface.c
topotests: use new OSPFv3 interface area syntax
[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
718e3744 314/* Inteface 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
5434aac4
DS
320 if (IS_RIP_DEBUG_ZEBRA) {
321 struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
322
d62a17ae 323 zlog_debug(
5434aac4
DS
324 "interface %s vrf %s(%u) index %d flags %llx metric %d mtu %d is down",
325 ifp->name, VRF_LOGNAME(vrf), ifp->vrf_id, ifp->ifindex,
ae7b826a 326 (unsigned long long)ifp->flags, ifp->metric, ifp->mtu);
5434aac4 327 }
d62a17ae 328
329 return 0;
718e3744 330}
331
332/* Inteface link up message processing */
ddbf3e60 333static int rip_ifp_up(struct interface *ifp)
718e3744 334{
5434aac4
DS
335 if (IS_RIP_DEBUG_ZEBRA) {
336 struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
337
d62a17ae 338 zlog_debug(
5434aac4
DS
339 "interface %s vrf %s(%u) index %d flags %#llx metric %d mtu %d is up",
340 ifp->name, VRF_LOGNAME(vrf), ifp->vrf_id, ifp->ifindex,
ae7b826a 341 (unsigned long long)ifp->flags, ifp->metric, ifp->mtu);
5434aac4 342 }
ae7b826a
RW
343
344 rip_interface_sync(ifp);
718e3744 345
d62a17ae 346 /* Check if this interface is RIP enabled or not.*/
347 rip_enable_apply(ifp);
718e3744 348
d62a17ae 349 /* Check for a passive interface */
350 rip_passive_interface_apply(ifp);
718e3744 351
d62a17ae 352 /* Apply distribute list to the all interface. */
353 rip_distribute_update_interface(ifp);
718e3744 354
d62a17ae 355 return 0;
718e3744 356}
357
358/* Inteface addition message from zebra. */
ef7bd2a3 359static int rip_ifp_create(struct interface *ifp)
718e3744 360{
ae7b826a 361 rip_interface_sync(ifp);
718e3744 362
5434aac4
DS
363 if (IS_RIP_DEBUG_ZEBRA) {
364 struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
d62a17ae 365 zlog_debug(
5434aac4
DS
366 "interface add %s vrf %s(%u) index %d flags %#llx metric %d mtu %d",
367 ifp->name, VRF_LOGNAME(vrf), ifp->vrf_id, ifp->ifindex,
ae7b826a 368 (unsigned long long)ifp->flags, ifp->metric, ifp->mtu);
5434aac4 369 }
718e3744 370
d62a17ae 371 /* Check if this interface is RIP enabled or not.*/
372 rip_enable_apply(ifp);
718e3744 373
d62a17ae 374 /* Check for a passive interface */
375 rip_passive_interface_apply(ifp);
718e3744 376
d62a17ae 377 /* Apply distribute list to the all interface. */
378 rip_distribute_update_interface(ifp);
718e3744 379
d62a17ae 380 /* rip_request_neighbor_all (); */
16705130 381
d62a17ae 382 /* Check interface routemap. */
383 rip_if_rmap_update_interface(ifp);
384
385 return 0;
718e3744 386}
387
3c3c3252 388static int rip_ifp_destroy(struct interface *ifp)
718e3744 389{
5434aac4
DS
390 struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
391
ae7b826a 392 rip_interface_sync(ifp);
d62a17ae 393 if (if_is_up(ifp)) {
394 rip_if_down(ifp);
395 }
718e3744 396
13c5f95e
DS
397 if (IS_RIP_DEBUG_ZEBRA)
398 zlog_debug(
399 "interface delete %s vrf %s(%u) index %d flags %#llx metric %d mtu %d",
400 ifp->name, VRF_LOGNAME(vrf), ifp->vrf_id, ifp->ifindex,
401 (unsigned long long)ifp->flags, ifp->metric, ifp->mtu);
718e3744 402
d62a17ae 403 return 0;
718e3744 404}
405
ae7b826a 406/* VRF update for an interface. */
121f9dee 407int rip_interface_vrf_update(ZAPI_CALLBACK_ARGS)
ae7b826a
RW
408{
409 struct interface *ifp;
410 vrf_id_t new_vrf_id;
411
412 ifp = zebra_interface_vrf_update_read(zclient->ibuf, vrf_id,
413 &new_vrf_id);
414 if (!ifp)
415 return 0;
416
5434aac4
DS
417 if (IS_RIP_DEBUG_ZEBRA) {
418 struct vrf *vrf = vrf_lookup_by_id(vrf_id);
419 struct vrf *nvrf = vrf_lookup_by_id(new_vrf_id);
420
421 zlog_debug("interface %s VRF change vrf %s(%u) new vrf %s(%u)",
422 ifp->name, VRF_LOGNAME(vrf), vrf_id,
423 VRF_LOGNAME(nvrf), new_vrf_id);
424 }
ae7b826a 425
a36898e7 426 if_update_to_new_vrf(ifp, new_vrf_id);
ae7b826a
RW
427 rip_interface_sync(ifp);
428
429 return 0;
430}
431
d62a17ae 432static void rip_interface_clean(struct rip_interface *ri)
4305dfd1 433{
d62a17ae 434 ri->enable_network = 0;
435 ri->enable_interface = 0;
436 ri->running = 0;
718e3744 437
b3d6bc6e 438 thread_cancel(&ri->t_wakeup);
4305dfd1 439}
718e3744 440
045c5389 441void rip_interfaces_clean(struct rip *rip)
718e3744 442{
d62a17ae 443 struct interface *ifp;
718e3744 444
ae7b826a 445 FOR_ALL_INTERFACES (rip->vrf, ifp)
d62a17ae 446 rip_interface_clean(ifp->info);
1dec2166 447}
718e3744 448
d62a17ae 449static void rip_interface_reset(struct rip_interface *ri)
4305dfd1 450{
94b117b2
RW
451 ri->auth_type = yang_get_default_enum("%s/authentication-scheme/mode",
452 RIP_IFACE);
453 ri->md5_auth_len = yang_get_default_enum(
454 "%s/authentication-scheme/md5-auth-length", RIP_IFACE);
718e3744 455
d62a17ae 456 /* Set default split-horizon behavior. If the interface is Frame
457 Relay or SMDS is enabled, the default value for split-horizon is
458 off. But currently Zebra does detect Frame Relay or SMDS
459 interface. So all interface is set to split horizon. */
94b117b2
RW
460 ri->split_horizon =
461 yang_get_default_enum("%s/split-horizon", RIP_IFACE);
718e3744 462
94b117b2
RW
463 ri->ri_send = yang_get_default_enum("%s/version-send", RIP_IFACE);
464 ri->ri_receive = yang_get_default_enum("%s/version-receive", RIP_IFACE);
465 ri->v2_broadcast = yang_get_default_bool("%s/v2-broadcast", RIP_IFACE);
f90310cf 466
0a22ddfb 467 XFREE(MTYPE_RIP_INTERFACE_STRING, ri->auth_str);
03c20031 468
0a22ddfb 469 XFREE(MTYPE_RIP_INTERFACE_STRING, ri->key_chain);
03c20031 470
d62a17ae 471 ri->list[RIP_FILTER_IN] = NULL;
472 ri->list[RIP_FILTER_OUT] = NULL;
718e3744 473
d62a17ae 474 ri->prefix[RIP_FILTER_IN] = NULL;
475 ri->prefix[RIP_FILTER_OUT] = NULL;
718e3744 476
d62a17ae 477 ri->recv_badpackets = 0;
478 ri->recv_badroutes = 0;
479 ri->sent_updates = 0;
4305dfd1 480
d62a17ae 481 ri->passive = 0;
718e3744 482
d62a17ae 483 rip_interface_clean(ri);
4305dfd1 484}
718e3744 485
d62a17ae 486int rip_if_down(struct interface *ifp)
718e3744 487{
045c5389 488 struct rip *rip;
d62a17ae 489 struct route_node *rp;
490 struct rip_info *rinfo;
491 struct rip_interface *ri = NULL;
492 struct list *list = NULL;
493 struct listnode *listnode = NULL, *nextnode = NULL;
045c5389
RW
494
495 ri = ifp->info;
8f0c2688
IR
496
497 THREAD_OFF(ri->t_wakeup);
498
045c5389 499 rip = ri->rip;
d62a17ae 500 if (rip) {
501 for (rp = route_top(rip->table); rp; rp = route_next(rp))
502 if ((list = rp->info) != NULL)
503 for (ALL_LIST_ELEMENTS(list, listnode, nextnode,
504 rinfo))
dd127197 505 if (rinfo->nh.ifindex == ifp->ifindex)
045c5389 506 rip_ecmp_delete(rip, rinfo);
d62a17ae 507
508 if (ri->running) {
509 if (IS_RIP_DEBUG_EVENT)
510 zlog_debug("turn off %s", ifp->name);
511
512 /* Leave from multicast group. */
513 rip_multicast_leave(ifp, rip->sock);
514
515 ri->running = 0;
516 }
517 }
518
519 return 0;
718e3744 520}
521
d62a17ae 522static void rip_apply_address_add(struct connected *ifc)
dc63bfd4 523{
045c5389
RW
524 struct rip_interface *ri = ifc->ifp->info;
525 struct rip *rip = ri->rip;
d62a17ae 526 struct prefix_ipv4 address;
3f5682c8 527 struct nexthop nh;
d62a17ae 528 struct prefix *p;
16705130 529
d62a17ae 530 if (!rip)
531 return;
16705130 532
d62a17ae 533 if (!if_is_up(ifc->ifp))
534 return;
16705130 535
d62a17ae 536 p = ifc->address;
16705130 537
d62a17ae 538 memset(&address, 0, sizeof(address));
3f5682c8
DS
539 memset(&nh, 0, sizeof(nh));
540
d62a17ae 541 address.family = p->family;
542 address.prefix = p->u.prefix4;
543 address.prefixlen = p->prefixlen;
544 apply_mask_ipv4(&address);
16705130 545
3f5682c8
DS
546 nh.ifindex = ifc->ifp->ifindex;
547 nh.type = NEXTHOP_TYPE_IFINDEX;
548
d62a17ae 549 /* Check if this interface is RIP enabled or not
550 or Check if this address's prefix is RIP enabled */
045c5389 551 if ((rip_enable_if_lookup(rip, ifc->ifp->name) >= 0)
d62a17ae 552 || (rip_enable_network_lookup2(ifc) >= 0))
045c5389
RW
553 rip_redistribute_add(rip, ZEBRA_ROUTE_CONNECT,
554 RIP_ROUTE_INTERFACE, &address, &nh, 0, 0,
555 0);
16705130 556}
557
121f9dee 558int rip_interface_address_add(ZAPI_CALLBACK_ARGS)
718e3744 559{
d62a17ae 560 struct connected *ifc;
561 struct prefix *p;
718e3744 562
d62a17ae 563 ifc = zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD,
564 zclient->ibuf, vrf_id);
718e3744 565
d62a17ae 566 if (ifc == NULL)
567 return 0;
718e3744 568
d62a17ae 569 p = ifc->address;
718e3744 570
d62a17ae 571 if (p->family == AF_INET) {
572 if (IS_RIP_DEBUG_ZEBRA)
f42238f8 573 zlog_debug("connected address %pFX is added", p);
16705130 574
d62a17ae 575 rip_enable_apply(ifc->ifp);
576 /* Check if this prefix needs to be redistributed */
577 rip_apply_address_add(ifc);
718e3744 578
d62a17ae 579 hook_call(rip_ifaddr_add, ifc);
580 }
718e3744 581
d62a17ae 582 return 0;
718e3744 583}
584
d62a17ae 585static void rip_apply_address_del(struct connected *ifc)
586{
045c5389
RW
587 struct rip_interface *ri = ifc->ifp->info;
588 struct rip *rip = ri->rip;
d62a17ae 589 struct prefix_ipv4 address;
590 struct prefix *p;
16705130 591
d62a17ae 592 if (!rip)
593 return;
16705130 594
d62a17ae 595 if (!if_is_up(ifc->ifp))
596 return;
16705130 597
d62a17ae 598 p = ifc->address;
16705130 599
d62a17ae 600 memset(&address, 0, sizeof(address));
601 address.family = p->family;
602 address.prefix = p->u.prefix4;
603 address.prefixlen = p->prefixlen;
604 apply_mask_ipv4(&address);
16705130 605
045c5389 606 rip_redistribute_delete(rip, ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE,
d62a17ae 607 &address, ifc->ifp->ifindex);
16705130 608}
609
121f9dee 610int rip_interface_address_delete(ZAPI_CALLBACK_ARGS)
718e3744 611{
d62a17ae 612 struct connected *ifc;
613 struct prefix *p;
718e3744 614
d62a17ae 615 ifc = zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE,
616 zclient->ibuf, vrf_id);
718e3744 617
d62a17ae 618 if (ifc) {
619 p = ifc->address;
620 if (p->family == AF_INET) {
621 if (IS_RIP_DEBUG_ZEBRA)
f42238f8
DS
622 zlog_debug("connected address %pFX is deleted",
623 p);
16705130 624
d62a17ae 625 hook_call(rip_ifaddr_del, ifc);
718e3744 626
d62a17ae 627 /* Chech wether this prefix needs to be removed */
628 rip_apply_address_del(ifc);
629 }
718e3744 630
721c0857 631 connected_free(&ifc);
d62a17ae 632 }
718e3744 633
d62a17ae 634 return 0;
718e3744 635}
6b0655a2 636
718e3744 637/* Check interface is enabled by network statement. */
16705130 638/* Check wether the interface has at least a connected prefix that
639 * is within the ripng_enable_network table. */
d62a17ae 640static int rip_enable_network_lookup_if(struct interface *ifp)
641{
045c5389
RW
642 struct rip_interface *ri = ifp->info;
643 struct rip *rip = ri->rip;
d62a17ae 644 struct listnode *node, *nnode;
645 struct connected *connected;
646 struct prefix_ipv4 address;
647
1205fdc4
RW
648 if (!rip)
649 return -1;
650
d62a17ae 651 for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, connected)) {
652 struct prefix *p;
dc7204b7 653 struct route_node *n;
d62a17ae 654
655 p = connected->address;
656
657 if (p->family == AF_INET) {
658 address.family = AF_INET;
659 address.prefix = p->u.prefix4;
660 address.prefixlen = IPV4_MAX_BITLEN;
661
1205fdc4 662 n = route_node_match(rip->enable_network,
dc7204b7
A
663 (struct prefix *)&address);
664 if (n) {
665 route_unlock_node(n);
d62a17ae 666 return 1;
667 }
668 }
669 }
670 return -1;
718e3744 671}
672
16705130 673/* Check wether connected is within the ripng_enable_network table. */
045c5389 674static int rip_enable_network_lookup2(struct connected *connected)
16705130 675{
045c5389
RW
676 struct rip_interface *ri = connected->ifp->info;
677 struct rip *rip = ri->rip;
d62a17ae 678 struct prefix_ipv4 address;
679 struct prefix *p;
16705130 680
d62a17ae 681 p = connected->address;
16705130 682
d62a17ae 683 if (p->family == AF_INET) {
684 struct route_node *node;
16705130 685
d62a17ae 686 address.family = p->family;
687 address.prefix = p->u.prefix4;
688 address.prefixlen = IPV4_MAX_BITLEN;
16705130 689
d62a17ae 690 /* LPM on p->family, p->u.prefix4/IPV4_MAX_BITLEN within
1205fdc4
RW
691 * rip->enable_network */
692 node = route_node_match(rip->enable_network,
d62a17ae 693 (struct prefix *)&address);
16705130 694
d62a17ae 695 if (node) {
696 route_unlock_node(node);
697 return 1;
698 }
699 }
16705130 700
d62a17ae 701 return -1;
16705130 702}
718e3744 703/* Add RIP enable network. */
045c5389 704int rip_enable_network_add(struct rip *rip, struct prefix *p)
718e3744 705{
d62a17ae 706 struct route_node *node;
718e3744 707
1205fdc4 708 node = route_node_get(rip->enable_network, p);
718e3744 709
d62a17ae 710 if (node->info) {
711 route_unlock_node(node);
3d7a1be8 712 return NB_ERR_INCONSISTENCY;
d62a17ae 713 } else
714 node->info = (void *)1;
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;
718e3744 720}
721
722/* Delete RIP enable network. */
045c5389 723int rip_enable_network_delete(struct rip *rip, struct prefix *p)
718e3744 724{
d62a17ae 725 struct route_node *node;
718e3744 726
1205fdc4 727 node = route_node_lookup(rip->enable_network, p);
d62a17ae 728 if (node) {
729 node->info = NULL;
718e3744 730
d62a17ae 731 /* Unlock info lock. */
732 route_unlock_node(node);
718e3744 733
d62a17ae 734 /* Unlock lookup lock. */
735 route_unlock_node(node);
718e3744 736
d62a17ae 737 /* XXX: One should find a better solution than a generic one */
045c5389 738 rip_enable_apply_all(rip);
16705130 739
3d7a1be8 740 return NB_OK;
d62a17ae 741 }
3d7a1be8
RW
742
743 return NB_ERR_INCONSISTENCY;
718e3744 744}
745
746/* Check interface is enabled by ifname statement. */
045c5389 747static int rip_enable_if_lookup(struct rip *rip, const char *ifname)
718e3744 748{
d62a17ae 749 unsigned int i;
750 char *str;
718e3744 751
ca046902
RW
752 if (!rip)
753 return -1;
754
755 for (i = 0; i < vector_active(rip->enable_interface); i++)
756 if ((str = vector_slot(rip->enable_interface, i)) != NULL)
d62a17ae 757 if (strcmp(str, ifname) == 0)
758 return i;
759 return -1;
718e3744 760}
761
762/* Add interface to rip_enable_if. */
045c5389 763int rip_enable_if_add(struct rip *rip, const char *ifname)
718e3744 764{
d62a17ae 765 int ret;
718e3744 766
045c5389 767 ret = rip_enable_if_lookup(rip, ifname);
d62a17ae 768 if (ret >= 0)
3d7a1be8 769 return NB_ERR_INCONSISTENCY;
718e3744 770
ca046902 771 vector_set(rip->enable_interface,
03c20031 772 XSTRDUP(MTYPE_RIP_INTERFACE_STRING, ifname));
718e3744 773
045c5389 774 rip_enable_apply_all(rip); /* TODOVJ */
16705130 775
3d7a1be8 776 return NB_OK;
718e3744 777}
778
779/* Delete interface from rip_enable_if. */
045c5389 780int rip_enable_if_delete(struct rip *rip, const char *ifname)
718e3744 781{
d62a17ae 782 int index;
783 char *str;
718e3744 784
045c5389 785 index = rip_enable_if_lookup(rip, ifname);
d62a17ae 786 if (index < 0)
3d7a1be8 787 return NB_ERR_INCONSISTENCY;
718e3744 788
ca046902 789 str = vector_slot(rip->enable_interface, index);
03c20031 790 XFREE(MTYPE_RIP_INTERFACE_STRING, str);
ca046902 791 vector_unset(rip->enable_interface, index);
718e3744 792
045c5389 793 rip_enable_apply_all(rip); /* TODOVJ */
16705130 794
3d7a1be8 795 return NB_OK;
718e3744 796}
797
798/* Join to multicast group and send request to the interface. */
d62a17ae 799static int rip_interface_wakeup(struct thread *t)
718e3744 800{
d62a17ae 801 struct interface *ifp;
802 struct rip_interface *ri;
718e3744 803
d62a17ae 804 /* Get interface. */
805 ifp = THREAD_ARG(t);
718e3744 806
d62a17ae 807 ri = ifp->info;
808 ri->t_wakeup = NULL;
718e3744 809
d62a17ae 810 /* Join to multicast group. */
045c5389 811 if (rip_multicast_join(ifp, ri->rip->sock) < 0) {
450971aa 812 flog_err_sys(EC_LIB_SOCKET,
09c866e3
QY
813 "multicast join failed, interface %s not running",
814 ifp->name);
d62a17ae 815 return 0;
816 }
718e3744 817
d62a17ae 818 /* Set running flag. */
819 ri->running = 1;
820
821 /* Send RIP request to the interface. */
822 rip_request_interface(ifp);
823
824 return 0;
825}
826
827static void rip_connect_set(struct interface *ifp, int set)
828{
045c5389
RW
829 struct rip_interface *ri = ifp->info;
830 struct rip *rip = ri->rip;
d62a17ae 831 struct listnode *node, *nnode;
832 struct connected *connected;
833 struct prefix_ipv4 address;
3f5682c8
DS
834 struct nexthop nh;
835
836 memset(&nh, 0, sizeof(nh));
d62a17ae 837
838 for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, connected)) {
839 struct prefix *p;
840 p = connected->address;
841
842 if (p->family != AF_INET)
843 continue;
844
845 address.family = AF_INET;
846 address.prefix = p->u.prefix4;
847 address.prefixlen = p->prefixlen;
848 apply_mask_ipv4(&address);
849
3f5682c8
DS
850 nh.ifindex = connected->ifp->ifindex;
851 nh.type = NEXTHOP_TYPE_IFINDEX;
d62a17ae 852 if (set) {
853 /* Check once more wether this prefix is within a
854 * "network IF_OR_PREF" one */
045c5389
RW
855 if ((rip_enable_if_lookup(rip, connected->ifp->name)
856 >= 0)
d62a17ae 857 || (rip_enable_network_lookup2(connected) >= 0))
045c5389 858 rip_redistribute_add(rip, ZEBRA_ROUTE_CONNECT,
996c9314
LB
859 RIP_ROUTE_INTERFACE,
860 &address, &nh, 0, 0, 0);
d62a17ae 861 } else {
045c5389 862 rip_redistribute_delete(rip, ZEBRA_ROUTE_CONNECT,
d62a17ae 863 RIP_ROUTE_INTERFACE, &address,
864 connected->ifp->ifindex);
045c5389
RW
865 if (rip_redistribute_check(rip, ZEBRA_ROUTE_CONNECT))
866 rip_redistribute_add(rip, ZEBRA_ROUTE_CONNECT,
996c9314
LB
867 RIP_ROUTE_REDISTRIBUTE,
868 &address, &nh, 0, 0, 0);
d62a17ae 869 }
870 }
718e3744 871}
872
873/* Update interface status. */
d62a17ae 874void rip_enable_apply(struct interface *ifp)
718e3744 875{
d62a17ae 876 int ret;
877 struct rip_interface *ri = NULL;
718e3744 878
d62a17ae 879 /* Check interface. */
880 if (!if_is_operative(ifp))
881 return;
718e3744 882
d62a17ae 883 ri = ifp->info;
884
885 /* Check network configuration. */
886 ret = rip_enable_network_lookup_if(ifp);
887
888 /* If the interface is matched. */
889 if (ret > 0)
890 ri->enable_network = 1;
891 else
892 ri->enable_network = 0;
893
894 /* Check interface name configuration. */
045c5389 895 ret = rip_enable_if_lookup(ri->rip, ifp->name);
d62a17ae 896 if (ret >= 0)
897 ri->enable_interface = 1;
898 else
899 ri->enable_interface = 0;
718e3744 900
d62a17ae 901 /* any interface MUST have an IPv4 address */
902 if (!rip_if_ipv4_address_check(ifp)) {
903 ri->enable_network = 0;
904 ri->enable_interface = 0;
718e3744 905 }
718e3744 906
d62a17ae 907 /* Update running status of the interface. */
908 if (ri->enable_network || ri->enable_interface) {
2e37ad7f
RW
909 if (IS_RIP_DEBUG_EVENT)
910 zlog_debug("turn on %s", ifp->name);
911
912 /* Add interface wake up thread. */
913 thread_add_timer(master, rip_interface_wakeup, ifp, 1,
914 &ri->t_wakeup);
915 rip_connect_set(ifp, 1);
916 } else if (ri->running) {
917 /* Might as well clean up the route table as well
918 * rip_if_down sets to 0 ri->running, and displays "turn
919 *off %s"
920 **/
921 rip_if_down(ifp);
d62a17ae 922
2e37ad7f 923 rip_connect_set(ifp, 0);
718e3744 924 }
718e3744 925}
926
927/* Apply network configuration to all interface. */
045c5389 928static void rip_enable_apply_all(struct rip *rip)
718e3744 929{
d62a17ae 930 struct interface *ifp;
718e3744 931
d62a17ae 932 /* Check each interface. */
ae7b826a 933 FOR_ALL_INTERFACES (rip->vrf, ifp)
d62a17ae 934 rip_enable_apply(ifp);
718e3744 935}
936
045c5389 937int rip_neighbor_lookup(struct rip *rip, struct sockaddr_in *from)
718e3744 938{
d62a17ae 939 struct prefix_ipv4 p;
940 struct route_node *node;
718e3744 941
d62a17ae 942 memset(&p, 0, sizeof(struct prefix_ipv4));
943 p.family = AF_INET;
944 p.prefix = from->sin_addr;
945 p.prefixlen = IPV4_MAX_BITLEN;
718e3744 946
d62a17ae 947 node = route_node_lookup(rip->neighbor, (struct prefix *)&p);
948 if (node) {
949 route_unlock_node(node);
950 return 1;
951 }
952 return 0;
718e3744 953}
954
955/* Add new RIP neighbor to the neighbor tree. */
045c5389 956int rip_neighbor_add(struct rip *rip, struct prefix_ipv4 *p)
718e3744 957{
d62a17ae 958 struct route_node *node;
718e3744 959
d62a17ae 960 node = route_node_get(rip->neighbor, (struct prefix *)p);
718e3744 961
d62a17ae 962 if (node->info)
f0ab22fb 963 return NB_ERR_INCONSISTENCY;
718e3744 964
d62a17ae 965 node->info = rip->neighbor;
718e3744 966
f0ab22fb 967 return NB_OK;
718e3744 968}
969
970/* Delete RIP neighbor from the neighbor tree. */
045c5389 971int rip_neighbor_delete(struct rip *rip, struct prefix_ipv4 *p)
718e3744 972{
d62a17ae 973 struct route_node *node;
718e3744 974
d62a17ae 975 /* Lock for look up. */
976 node = route_node_lookup(rip->neighbor, (struct prefix *)p);
977 if (!node)
f0ab22fb 978 return NB_ERR_INCONSISTENCY;
718e3744 979
d62a17ae 980 node->info = NULL;
718e3744 981
d62a17ae 982 /* Unlock lookup lock. */
983 route_unlock_node(node);
718e3744 984
d62a17ae 985 /* Unlock real neighbor information lock. */
986 route_unlock_node(node);
987
f0ab22fb 988 return NB_OK;
718e3744 989}
990
991/* Clear all network and neighbor configuration. */
045c5389 992void rip_clean_network(struct rip *rip)
d62a17ae 993{
994 unsigned int i;
995 char *str;
996 struct route_node *rn;
997
1205fdc4
RW
998 /* rip->enable_network. */
999 for (rn = route_top(rip->enable_network); rn; rn = route_next(rn))
d62a17ae 1000 if (rn->info) {
1001 rn->info = NULL;
1002 route_unlock_node(rn);
1003 }
1004
ca046902
RW
1005 /* rip->enable_interface. */
1006 for (i = 0; i < vector_active(rip->enable_interface); i++)
1007 if ((str = vector_slot(rip->enable_interface, i)) != NULL) {
03c20031 1008 XFREE(MTYPE_RIP_INTERFACE_STRING, str);
ca046902 1009 vector_slot(rip->enable_interface, i) = NULL;
d62a17ae 1010 }
718e3744 1011}
6b0655a2 1012
718e3744 1013/* Utility function for looking up passive interface settings. */
045c5389 1014static int rip_passive_nondefault_lookup(struct rip *rip, const char *ifname)
718e3744 1015{
d62a17ae 1016 unsigned int i;
1017 char *str;
718e3744 1018
5a29c0d5
RW
1019 for (i = 0; i < vector_active(rip->passive_nondefault); i++)
1020 if ((str = vector_slot(rip->passive_nondefault, i)) != NULL)
d62a17ae 1021 if (strcmp(str, ifname) == 0)
1022 return i;
1023 return -1;
718e3744 1024}
1025
045c5389 1026static void rip_passive_interface_apply(struct interface *ifp)
718e3744 1027{
045c5389 1028 struct rip *rip;
d62a17ae 1029 struct rip_interface *ri;
718e3744 1030
045c5389
RW
1031 ri = ifp->info;
1032 rip = ri->rip;
44f2f852
RW
1033 if (rip == NULL)
1034 return;
1035
045c5389 1036 ri->passive = ((rip_passive_nondefault_lookup(rip, ifp->name) < 0)
44f2f852
RW
1037 ? rip->passive_default
1038 : !rip->passive_default);
4aaff3f8 1039
d62a17ae 1040 if (IS_RIP_DEBUG_ZEBRA)
1041 zlog_debug("interface %s: passive = %d", ifp->name,
1042 ri->passive);
718e3744 1043}
1044
045c5389 1045static void rip_passive_interface_apply_all(struct rip *rip)
718e3744 1046{
d62a17ae 1047 struct interface *ifp;
718e3744 1048
ae7b826a 1049 FOR_ALL_INTERFACES (rip->vrf, ifp)
d62a17ae 1050 rip_passive_interface_apply(ifp);
718e3744 1051}
1052
1053/* Passive interface. */
045c5389 1054int rip_passive_nondefault_set(struct rip *rip, const char *ifname)
718e3744 1055{
045c5389 1056 if (rip_passive_nondefault_lookup(rip, ifname) >= 0)
44f2f852
RW
1057 /*
1058 * Don't return an error, this can happen after changing
1059 * 'passive-default'.
1060 */
1061 return NB_OK;
718e3744 1062
5a29c0d5 1063 vector_set(rip->passive_nondefault,
03c20031 1064 XSTRDUP(MTYPE_RIP_INTERFACE_STRING, ifname));
718e3744 1065
045c5389 1066 rip_passive_interface_apply_all(rip);
718e3744 1067
44f2f852 1068 return NB_OK;
718e3744 1069}
1070
045c5389 1071int rip_passive_nondefault_unset(struct rip *rip, const char *ifname)
718e3744 1072{
d62a17ae 1073 int i;
1074 char *str;
718e3744 1075
045c5389 1076 i = rip_passive_nondefault_lookup(rip, ifname);
d62a17ae 1077 if (i < 0)
44f2f852
RW
1078 /*
1079 * Don't return an error, this can happen after changing
1080 * 'passive-default'.
1081 */
1082 return NB_OK;
718e3744 1083
5a29c0d5 1084 str = vector_slot(rip->passive_nondefault, i);
03c20031 1085 XFREE(MTYPE_RIP_INTERFACE_STRING, str);
5a29c0d5 1086 vector_unset(rip->passive_nondefault, i);
718e3744 1087
045c5389 1088 rip_passive_interface_apply_all(rip);
718e3744 1089
44f2f852 1090 return NB_OK;
718e3744 1091}
1092
1093/* Free all configured RIP passive-interface settings. */
045c5389 1094void rip_passive_nondefault_clean(struct rip *rip)
718e3744 1095{
d62a17ae 1096 unsigned int i;
1097 char *str;
718e3744 1098
5a29c0d5
RW
1099 for (i = 0; i < vector_active(rip->passive_nondefault); i++)
1100 if ((str = vector_slot(rip->passive_nondefault, i)) != NULL) {
03c20031 1101 XFREE(MTYPE_RIP_INTERFACE_STRING, str);
5a29c0d5 1102 vector_slot(rip->passive_nondefault, i) = NULL;
d62a17ae 1103 }
045c5389 1104 rip_passive_interface_apply_all(rip);
718e3744 1105}
6b0655a2 1106
718e3744 1107/* Write rip configuration of each interface. */
d62a17ae 1108static int rip_interface_config_write(struct vty *vty)
1109{
ae7b826a 1110 struct vrf *vrf;
94b117b2 1111 int write = 0;
d62a17ae 1112
ae7b826a
RW
1113 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
1114 struct interface *ifp;
d62a17ae 1115
ae7b826a
RW
1116 FOR_ALL_INTERFACES (vrf, ifp) {
1117 struct lyd_node *dnode;
1118
3bb513c3 1119 dnode = yang_dnode_getf(
ae7b826a
RW
1120 running_config->dnode,
1121 "/frr-interface:lib/interface[name='%s'][vrf='%s']",
1122 ifp->name, vrf->name);
1123 if (dnode == NULL)
1124 continue;
d62a17ae 1125
ae7b826a
RW
1126 write = 1;
1127 nb_cli_show_dnode_cmds(vty, dnode, false);
1128 }
d62a17ae 1129 }
94b117b2
RW
1130
1131 return write;
d62a17ae 1132}
1133
045c5389 1134int rip_show_network_config(struct vty *vty, struct rip *rip)
d62a17ae 1135{
1136 unsigned int i;
1137 char *ifname;
1138 struct route_node *node;
1139
1140 /* Network type RIP enable interface statement. */
1205fdc4 1141 for (node = route_top(rip->enable_network); node;
d62a17ae 1142 node = route_next(node))
1143 if (node->info)
53bb7f9b 1144 vty_out(vty, " %pFX\n", &node->p);
d62a17ae 1145
1146 /* Interface name RIP enable statement. */
ca046902
RW
1147 for (i = 0; i < vector_active(rip->enable_interface); i++)
1148 if ((ifname = vector_slot(rip->enable_interface, i)) != NULL)
44f2f852 1149 vty_out(vty, " %s\n", ifname);
d62a17ae 1150
1151 /* RIP neighbors listing. */
1152 for (node = route_top(rip->neighbor); node; node = route_next(node))
1153 if (node->info)
53bb7f9b 1154 vty_out(vty, " %pI4\n", &node->p.u.prefix4);
718e3744 1155
d62a17ae 1156 return 0;
1157}
1158
ae7b826a
RW
1159void rip_interface_sync(struct interface *ifp)
1160{
1161 struct vrf *vrf;
1162
a36898e7 1163 vrf = vrf_lookup_by_id(ifp->vrf_id);
ae7b826a
RW
1164 if (vrf) {
1165 struct rip_interface *ri;
1166
1167 ri = ifp->info;
1168 if (ri)
1169 ri->rip = vrf->info;
1170 }
1171}
1172
718e3744 1173/* Called when interface structure allocated. */
d62a17ae 1174static int rip_interface_new_hook(struct interface *ifp)
718e3744 1175{
d62a17ae 1176 ifp->info = rip_interface_new();
ae7b826a
RW
1177 rip_interface_sync(ifp);
1178
d62a17ae 1179 return 0;
718e3744 1180}
1181
1182/* Called when interface structure deleted. */
d62a17ae 1183static int rip_interface_delete_hook(struct interface *ifp)
718e3744 1184{
72010aca 1185 rip_interface_reset(ifp->info);
d62a17ae 1186 XFREE(MTYPE_RIP_INTERFACE, ifp->info);
d62a17ae 1187 return 0;
718e3744 1188}
1189
1190/* Allocate and initialize interface vector. */
d62a17ae 1191void rip_if_init(void)
718e3744 1192{
d62a17ae 1193 /* Default initial size of interface vector. */
ce19a04a
DL
1194 hook_register_prio(if_add, 0, rip_interface_new_hook);
1195 hook_register_prio(if_del, 0, rip_interface_delete_hook);
d62a17ae 1196
d62a17ae 1197 /* Install interface node. */
9da01b0b 1198 if_cmd_init(rip_interface_config_write);
138c5a74
DS
1199 if_zapi_callbacks(rip_ifp_create, rip_ifp_up,
1200 rip_ifp_down, rip_ifp_destroy);
718e3744 1201}