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