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