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