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