blob: 52a1fe2409038d45ad3442c5614d150105b8cdd8 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/*
2 * Interface related function for RIPng.
3 * Copyright (C) 1998 Kunihiro Ishiguro
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with GNU Zebra; see the file COPYING. If not, write to the Free
19 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 * 02111-1307, USA.
21 */
22
23#include <zebra.h>
24
25#include "linklist.h"
26#include "if.h"
27#include "prefix.h"
28#include "memory.h"
29#include "network.h"
30#include "filter.h"
31#include "log.h"
32#include "stream.h"
33#include "zclient.h"
34#include "command.h"
35#include "table.h"
36#include "thread.h"
gdt4d4653a2004-07-01 19:26:33 +000037#include "privs.h"
paul718e3742002-12-13 20:15:29 +000038
39#include "ripngd/ripngd.h"
40#include "ripngd/ripng_debug.h"
41
42/* If RFC2133 definition is used. */
43#ifndef IPV6_JOIN_GROUP
44#define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
45#endif
46#ifndef IPV6_LEAVE_GROUP
47#define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
48#endif
49
gdt4d4653a2004-07-01 19:26:33 +000050extern struct zebra_privs_t ripngd_privs;
51
paul718e3742002-12-13 20:15:29 +000052/* Static utility function. */
53static void ripng_enable_apply (struct interface *);
54static void ripng_passive_interface_apply (struct interface *);
hasso98b718a2004-10-11 12:57:57 +000055int ripng_enable_if_lookup (const char *ifname);
hassoa94434b2003-05-25 17:10:12 +000056int ripng_enable_network_lookup2 (struct connected *connected);
57void ripng_enable_apply_all ();
paul718e3742002-12-13 20:15:29 +000058
59/* Join to the all rip routers multicast group. */
60int
61ripng_multicast_join (struct interface *ifp)
62{
63 int ret;
64 struct ipv6_mreq mreq;
ajs656b4ee2005-01-30 18:08:12 +000065 int save_errno;
paul718e3742002-12-13 20:15:29 +000066
hassoa94434b2003-05-25 17:10:12 +000067 if (if_is_up (ifp) && if_is_multicast (ifp)) {
68 memset (&mreq, 0, sizeof (mreq));
69 inet_pton(AF_INET6, RIPNG_GROUP, &mreq.ipv6mr_multiaddr);
70 mreq.ipv6mr_interface = ifp->ifindex;
paul718e3742002-12-13 20:15:29 +000071
gdt4d4653a2004-07-01 19:26:33 +000072 /*
73 * NetBSD 1.6.2 requires root to join groups on gif(4).
74 * While this is bogus, privs are available and easy to use
75 * for this call as a workaround.
76 */
77 if (ripngd_privs.change (ZPRIVS_RAISE))
78 zlog_err ("ripng_multicast_join: could not raise privs");
79
hassoa94434b2003-05-25 17:10:12 +000080 ret = setsockopt (ripng->sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
81 (char *) &mreq, sizeof (mreq));
ajs656b4ee2005-01-30 18:08:12 +000082 save_errno = errno;
gdtddf1c262004-01-04 01:02:55 +000083
gdt4d4653a2004-07-01 19:26:33 +000084 if (ripngd_privs.change (ZPRIVS_LOWER))
85 zlog_err ("ripng_multicast_join: could not lower privs");
86
ajs656b4ee2005-01-30 18:08:12 +000087 if (ret < 0 && save_errno == EADDRINUSE)
gdtddf1c262004-01-04 01:02:55 +000088 {
89 /*
90 * Group is already joined. This occurs due to sloppy group
91 * management, in particular declining to leave the group on
92 * an interface that has just gone down.
93 */
94 zlog_warn ("ripng join on %s EADDRINUSE (ignoring)\n", ifp->name);
95 return 0; /* not an error */
96 }
97
hassoa94434b2003-05-25 17:10:12 +000098 if (ret < 0)
ajs656b4ee2005-01-30 18:08:12 +000099 zlog_warn ("can't setsockopt IPV6_JOIN_GROUP: %s",
100 safe_strerror (save_errno));
paul718e3742002-12-13 20:15:29 +0000101
hassoa94434b2003-05-25 17:10:12 +0000102 if (IS_RIPNG_DEBUG_EVENT)
ajs2e23ab22004-12-08 19:46:50 +0000103 zlog_debug ("RIPng %s join to all-rip-routers multicast group", ifp->name);
paul718e3742002-12-13 20:15:29 +0000104
hassoa94434b2003-05-25 17:10:12 +0000105 if (ret < 0)
106 return -1;
107 }
108 return 0;
paul718e3742002-12-13 20:15:29 +0000109}
110
111/* Leave from the all rip routers multicast group. */
112int
113ripng_multicast_leave (struct interface *ifp)
114{
115 int ret;
116 struct ipv6_mreq mreq;
117
hassoa94434b2003-05-25 17:10:12 +0000118 if (if_is_up (ifp) && if_is_multicast (ifp)) {
119 memset (&mreq, 0, sizeof (mreq));
120 inet_pton(AF_INET6, RIPNG_GROUP, &mreq.ipv6mr_multiaddr);
121 mreq.ipv6mr_interface = ifp->ifindex;
paul718e3742002-12-13 20:15:29 +0000122
hassoa94434b2003-05-25 17:10:12 +0000123 ret = setsockopt (ripng->sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
124 (char *) &mreq, sizeof (mreq));
125 if (ret < 0)
ajs6099b3b2004-11-20 02:06:59 +0000126 zlog_warn ("can't setsockopt IPV6_LEAVE_GROUP: %s\n", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000127
hassoa94434b2003-05-25 17:10:12 +0000128 if (IS_RIPNG_DEBUG_EVENT)
ajs2e23ab22004-12-08 19:46:50 +0000129 zlog_debug ("RIPng %s leave from all-rip-routers multicast group",
hassoa94434b2003-05-25 17:10:12 +0000130 ifp->name);
paul718e3742002-12-13 20:15:29 +0000131
hassoa94434b2003-05-25 17:10:12 +0000132 if (ret < 0)
133 return -1;
134 }
135
136 return 0;
137}
138
139/* How many link local IPv6 address could be used on the interface ? */
140int
141ripng_if_ipv6_lladdress_check (struct interface *ifp)
142{
143 struct listnode *nn;
144 struct connected *connected;
145 int count = 0;
146
paul1eb8ef22005-04-07 07:30:20 +0000147 for (ALL_LIST_ELEMENTS_RO (ifp->connected, nn, connected))
148 {
hassoa94434b2003-05-25 17:10:12 +0000149 struct prefix *p;
150 p = connected->address;
151
152 if ((p->family == AF_INET6) &&
153 IN6_IS_ADDR_LINKLOCAL (&p->u.prefix6))
154 count++;
155 }
156
157 return count;
paul718e3742002-12-13 20:15:29 +0000158}
159
160/* Check max mtu size. */
hasso98b718a2004-10-11 12:57:57 +0000161unsigned int
paul718e3742002-12-13 20:15:29 +0000162ripng_check_max_mtu ()
163{
hasso52dc7ee2004-09-23 19:18:23 +0000164 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000165 struct interface *ifp;
hasso98b718a2004-10-11 12:57:57 +0000166 unsigned int mtu;
paul718e3742002-12-13 20:15:29 +0000167
168 mtu = 0;
paul1eb8ef22005-04-07 07:30:20 +0000169 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
170 if (mtu < ifp->mtu6)
171 mtu = ifp->mtu6;
172
paul718e3742002-12-13 20:15:29 +0000173 return mtu;
174}
175
176int
177ripng_if_down (struct interface *ifp)
178{
179 struct route_node *rp;
180 struct ripng_info *rinfo;
181 struct ripng_interface *ri;
182
hassoa94434b2003-05-25 17:10:12 +0000183 if (ripng)
paul718e3742002-12-13 20:15:29 +0000184 {
185 for (rp = route_top (ripng->table); rp; rp = route_next (rp))
186 if ((rinfo = rp->info) != NULL)
187 {
188 /* Routes got through this interface. */
189 if (rinfo->ifindex == ifp->ifindex
190 && rinfo->type == ZEBRA_ROUTE_RIPNG
191 && rinfo->sub_type == RIPNG_ROUTE_RTE)
192 {
193 ripng_zebra_ipv6_delete ((struct prefix_ipv6 *) &rp->p,
194 &rinfo->nexthop,
195 rinfo->ifindex);
196
hassoa94434b2003-05-25 17:10:12 +0000197 ripng_redistribute_delete (rinfo->type, rinfo->sub_type,
198 (struct prefix_ipv6 *)&rp->p,
199 rinfo->ifindex);
paul718e3742002-12-13 20:15:29 +0000200 }
201 else
202 {
hassoa94434b2003-05-25 17:10:12 +0000203 /* All redistributed routes got through this interface,
204 * but the static and system ones are kept. */
205 if ((rinfo->ifindex == ifp->ifindex) &&
206 (rinfo->type != ZEBRA_ROUTE_STATIC) &&
207 (rinfo->type != ZEBRA_ROUTE_SYSTEM))
paul718e3742002-12-13 20:15:29 +0000208 ripng_redistribute_delete (rinfo->type, rinfo->sub_type,
209 (struct prefix_ipv6 *) &rp->p,
210 rinfo->ifindex);
211 }
212 }
213 }
214
215 ri = ifp->info;
216
hassoa94434b2003-05-25 17:10:12 +0000217 if (ri->running)
paul718e3742002-12-13 20:15:29 +0000218 {
219 if (IS_RIPNG_DEBUG_EVENT)
ajs2e23ab22004-12-08 19:46:50 +0000220 zlog_debug ("turn off %s", ifp->name);
paul718e3742002-12-13 20:15:29 +0000221
222 /* Leave from multicast group. */
223 ripng_multicast_leave (ifp);
224
225 ri->running = 0;
226 }
227
228 return 0;
229}
230
231/* Inteface link up message processing. */
232int
233ripng_interface_up (int command, struct zclient *zclient, zebra_size_t length)
234{
235 struct stream *s;
236 struct interface *ifp;
237
238 /* zebra_interface_state_read() updates interface structure in iflist. */
239 s = zclient->ibuf;
240 ifp = zebra_interface_state_read (s);
241
242 if (ifp == NULL)
243 return 0;
244
245 if (IS_RIPNG_DEBUG_ZEBRA)
ajs2e23ab22004-12-08 19:46:50 +0000246 zlog_debug ("interface up %s index %d flags %ld metric %d mtu %d",
hasso1203e1c2004-07-23 21:34:27 +0000247 ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu6);
paul718e3742002-12-13 20:15:29 +0000248
249 /* Check if this interface is RIPng enabled or not. */
250 ripng_enable_apply (ifp);
251
252 /* Check for a passive interface. */
253 ripng_passive_interface_apply (ifp);
254
255 /* Apply distribute list to the all interface. */
256 ripng_distribute_update_interface (ifp);
257
258 return 0;
259}
260
261/* Inteface link down message processing. */
262int
263ripng_interface_down (int command, struct zclient *zclient,
264 zebra_size_t length)
265{
266 struct stream *s;
267 struct interface *ifp;
268
269 /* zebra_interface_state_read() updates interface structure in iflist. */
270 s = zclient->ibuf;
271 ifp = zebra_interface_state_read (s);
272
273 if (ifp == NULL)
274 return 0;
275
276 ripng_if_down (ifp);
277
278 if (IS_RIPNG_DEBUG_ZEBRA)
ajs2e23ab22004-12-08 19:46:50 +0000279 zlog_debug ("interface down %s index %d flags %ld metric %d mtu %d",
hasso1203e1c2004-07-23 21:34:27 +0000280 ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu6);
paul718e3742002-12-13 20:15:29 +0000281
282 return 0;
283}
284
285/* Inteface addition message from zebra. */
286int
287ripng_interface_add (int command, struct zclient *zclient, zebra_size_t length)
288{
289 struct interface *ifp;
290
291 ifp = zebra_interface_add_read (zclient->ibuf);
292
293 if (IS_RIPNG_DEBUG_ZEBRA)
ajs2e23ab22004-12-08 19:46:50 +0000294 zlog_debug ("RIPng interface add %s index %d flags %ld metric %d mtu %d",
hasso1203e1c2004-07-23 21:34:27 +0000295 ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu6);
paul718e3742002-12-13 20:15:29 +0000296
297 /* Check is this interface is RIP enabled or not.*/
298 ripng_enable_apply (ifp);
299
300 /* Apply distribute list to the interface. */
301 ripng_distribute_update_interface (ifp);
302
303 /* Check interface routemap. */
304 ripng_if_rmap_update_interface (ifp);
305
306 return 0;
307}
308
309int
310ripng_interface_delete (int command, struct zclient *zclient,
311 zebra_size_t length)
312{
hassoa94434b2003-05-25 17:10:12 +0000313 struct interface *ifp;
314 struct stream *s;
315
316 s = zclient->ibuf;
317 /* zebra_interface_state_read() updates interface structure in iflist */
318 ifp = zebra_interface_state_read(s);
319
320 if (ifp == NULL)
321 return 0;
322
323 if (if_is_up (ifp)) {
324 ripng_if_down(ifp);
325 }
326
327 zlog_info("interface delete %s index %d flags %ld metric %d mtu %d",
hasso1203e1c2004-07-23 21:34:27 +0000328 ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu6);
hassoa94434b2003-05-25 17:10:12 +0000329
330 /* To support pseudo interface do not free interface structure. */
331 /* if_delete(ifp); */
ajsd2fc8892005-04-02 18:38:43 +0000332 ifp->ifindex = IFINDEX_INTERNAL;
hassoa94434b2003-05-25 17:10:12 +0000333
paul718e3742002-12-13 20:15:29 +0000334 return 0;
335}
336
hassoa94434b2003-05-25 17:10:12 +0000337void
338ripng_interface_clean ()
339{
paul1eb8ef22005-04-07 07:30:20 +0000340 struct listnode *node, *nnode;
hassoa94434b2003-05-25 17:10:12 +0000341 struct interface *ifp;
342 struct ripng_interface *ri;
343
paul1eb8ef22005-04-07 07:30:20 +0000344 for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
hassoa94434b2003-05-25 17:10:12 +0000345 {
hassoa94434b2003-05-25 17:10:12 +0000346 ri = ifp->info;
347
348 ri->enable_network = 0;
349 ri->enable_interface = 0;
350 ri->running = 0;
351
352 if (ri->t_wakeup)
353 {
354 thread_cancel (ri->t_wakeup);
355 ri->t_wakeup = NULL;
356 }
357 }
358}
359
360void
361ripng_interface_reset () {
hasso52dc7ee2004-09-23 19:18:23 +0000362 struct listnode *node;
hassoa94434b2003-05-25 17:10:12 +0000363 struct interface *ifp;
364 struct ripng_interface *ri;
365
paul1eb8ef22005-04-07 07:30:20 +0000366 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
hassoa94434b2003-05-25 17:10:12 +0000367 {
hassoa94434b2003-05-25 17:10:12 +0000368 ri = ifp->info;
369
370 ri->enable_network = 0;
371 ri->enable_interface = 0;
372 ri->running = 0;
373
374 ri->split_horizon = RIPNG_NO_SPLIT_HORIZON;
375 ri->split_horizon_default = RIPNG_NO_SPLIT_HORIZON;
376
377 ri->list[RIPNG_FILTER_IN] = NULL;
378 ri->list[RIPNG_FILTER_OUT] = NULL;
379
380 ri->prefix[RIPNG_FILTER_IN] = NULL;
381 ri->prefix[RIPNG_FILTER_OUT] = NULL;
382
383 if (ri->t_wakeup)
384 {
385 thread_cancel (ri->t_wakeup);
386 ri->t_wakeup = NULL;
387 }
388
389 ri->passive = 0;
390 }
391}
392
393static void
394ripng_apply_address_add (struct connected *ifc) {
395 struct prefix_ipv6 address;
396 struct prefix *p;
397
398 if (!ripng)
399 return;
400
401 if (! if_is_up(ifc->ifp))
402 return;
403
404 p = ifc->address;
405
406 memset (&address, 0, sizeof (address));
407 address.family = p->family;
408 address.prefix = p->u.prefix6;
409 address.prefixlen = p->prefixlen;
410 apply_mask_ipv6(&address);
411
412 /* Check if this interface is RIP enabled or not
413 or Check if this address's prefix is RIP enabled */
414 if ((ripng_enable_if_lookup(ifc->ifp->name) >= 0) ||
415 (ripng_enable_network_lookup2(ifc) >= 0))
416 ripng_redistribute_add(ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_INTERFACE,
417 &address, ifc->ifp->ifindex, NULL);
418
419}
420
paul718e3742002-12-13 20:15:29 +0000421int
422ripng_interface_address_add (int command, struct zclient *zclient,
423 zebra_size_t length)
424{
425 struct connected *c;
426 struct prefix *p;
paul718e3742002-12-13 20:15:29 +0000427
paul0a589352004-05-08 11:48:26 +0000428 c = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_ADD,
429 zclient->ibuf);
paul718e3742002-12-13 20:15:29 +0000430
431 if (c == NULL)
432 return 0;
433
434 p = c->address;
435
436 if (p->family == AF_INET6)
437 {
438 if (IS_RIPNG_DEBUG_ZEBRA)
ajs2e23ab22004-12-08 19:46:50 +0000439 zlog_debug ("RIPng connected address %s/%d add",
hasso3a2ce6a2005-04-08 01:30:51 +0000440 inet6_ntoa(p->u.prefix6),
paul718e3742002-12-13 20:15:29 +0000441 p->prefixlen);
442
hassoa94434b2003-05-25 17:10:12 +0000443 /* Check is this prefix needs to be redistributed. */
444 ripng_apply_address_add(c);
445
446 /* Let's try once again whether the interface could be activated */
447 if (c->ifp) {
448 struct ripng_interface *ri = c->ifp->info;
449
450 if (!ri->running) {
451 /* Check if this interface is RIP enabled or not.*/
452 ripng_enable_apply (c->ifp);
453
454 /* Apply distribute list to the interface. */
455 ripng_distribute_update_interface (c->ifp);
456
457 /* Check interface routemap. */
458 ripng_if_rmap_update_interface (c->ifp);
459 }
460 }
461
paul718e3742002-12-13 20:15:29 +0000462 }
463
464 return 0;
465}
466
hassoa94434b2003-05-25 17:10:12 +0000467static void
468ripng_apply_address_del (struct connected *ifc) {
469 struct prefix_ipv6 address;
470 struct prefix *p;
471
472 if (!ripng)
473 return;
474
475 if (! if_is_up(ifc->ifp))
476 return;
477
478 p = ifc->address;
479
480 memset (&address, 0, sizeof (address));
481 address.family = p->family;
482 address.prefix = p->u.prefix6;
483 address.prefixlen = p->prefixlen;
484 apply_mask_ipv6(&address);
485
486 ripng_redistribute_delete(ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_INTERFACE,
487 &address, ifc->ifp->ifindex);
488}
489
paul718e3742002-12-13 20:15:29 +0000490int
491ripng_interface_address_delete (int command, struct zclient *zclient,
492 zebra_size_t length)
493{
494 struct connected *ifc;
495 struct prefix *p;
496 char buf[INET6_ADDRSTRLEN];
497
paul0a589352004-05-08 11:48:26 +0000498 ifc = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_DELETE,
499 zclient->ibuf);
paul718e3742002-12-13 20:15:29 +0000500
501 if (ifc)
502 {
503 p = ifc->address;
504
505 if (p->family == AF_INET6)
506 {
507 if (IS_RIPNG_DEBUG_ZEBRA)
ajs2e23ab22004-12-08 19:46:50 +0000508 zlog_debug ("RIPng connected address %s/%d delete",
paul718e3742002-12-13 20:15:29 +0000509 inet_ntop (AF_INET6, &p->u.prefix6, buf,
510 INET6_ADDRSTRLEN),
511 p->prefixlen);
512
hassoa94434b2003-05-25 17:10:12 +0000513 /* Check wether this prefix needs to be removed. */
514 ripng_apply_address_del(ifc);
paul718e3742002-12-13 20:15:29 +0000515 }
516 connected_free (ifc);
517 }
518
519 return 0;
520}
521
522/* RIPng enable interface vector. */
523vector ripng_enable_if;
524
525/* RIPng enable network table. */
526struct route_table *ripng_enable_network;
527
528/* Lookup RIPng enable network. */
hassoa94434b2003-05-25 17:10:12 +0000529/* Check wether the interface has at least a connected prefix that
530 * is within the ripng_enable_network table. */
paul718e3742002-12-13 20:15:29 +0000531int
hassoa94434b2003-05-25 17:10:12 +0000532ripng_enable_network_lookup_if (struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000533{
paul1eb8ef22005-04-07 07:30:20 +0000534 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000535 struct connected *connected;
hassoa94434b2003-05-25 17:10:12 +0000536 struct prefix_ipv6 address;
paul718e3742002-12-13 20:15:29 +0000537
paul1eb8ef22005-04-07 07:30:20 +0000538 for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected))
539 {
540 struct prefix *p;
541 struct route_node *node;
paul718e3742002-12-13 20:15:29 +0000542
paul1eb8ef22005-04-07 07:30:20 +0000543 p = connected->address;
paul718e3742002-12-13 20:15:29 +0000544
paul1eb8ef22005-04-07 07:30:20 +0000545 if (p->family == AF_INET6)
546 {
547 address.family = AF_INET6;
548 address.prefix = p->u.prefix6;
549 address.prefixlen = IPV6_MAX_BITLEN;
hassoa94434b2003-05-25 17:10:12 +0000550
paul1eb8ef22005-04-07 07:30:20 +0000551 node = route_node_match (ripng_enable_network,
552 (struct prefix *)&address);
553 if (node)
554 {
555 route_unlock_node (node);
556 return 1;
557 }
558 }
559 }
paul718e3742002-12-13 20:15:29 +0000560 return -1;
561}
562
hassoa94434b2003-05-25 17:10:12 +0000563/* Check wether connected is within the ripng_enable_network table. */
564int
565ripng_enable_network_lookup2 (struct connected *connected)
566{
567 struct prefix_ipv6 address;
568 struct prefix *p;
569
570 p = connected->address;
571
572 if (p->family == AF_INET6) {
573 struct route_node *node;
574
575 address.family = p->family;
576 address.prefix = p->u.prefix6;
577 address.prefixlen = IPV6_MAX_BITLEN;
578
579 /* LPM on p->family, p->u.prefix6/IPV6_MAX_BITLEN within ripng_enable_network */
580 node = route_node_match (ripng_enable_network,
581 (struct prefix *)&address);
582
583 if (node) {
584 route_unlock_node (node);
585 return 1;
586 }
587 }
588
589 return -1;
590}
591
paul718e3742002-12-13 20:15:29 +0000592/* Add RIPng enable network. */
593int
594ripng_enable_network_add (struct prefix *p)
595{
596 struct route_node *node;
597
598 node = route_node_get (ripng_enable_network, p);
599
600 if (node->info)
601 {
602 route_unlock_node (node);
603 return -1;
604 }
605 else
hasso7a1d5832004-10-08 06:32:23 +0000606 node->info = (char *) "enabled";
paul718e3742002-12-13 20:15:29 +0000607
hassoa94434b2003-05-25 17:10:12 +0000608 /* XXX: One should find a better solution than a generic one */
609 ripng_enable_apply_all();
610
paul718e3742002-12-13 20:15:29 +0000611 return 1;
612}
613
614/* Delete RIPng enable network. */
615int
616ripng_enable_network_delete (struct prefix *p)
617{
618 struct route_node *node;
619
620 node = route_node_lookup (ripng_enable_network, p);
621 if (node)
622 {
623 node->info = NULL;
624
625 /* Unlock info lock. */
626 route_unlock_node (node);
627
628 /* Unlock lookup lock. */
629 route_unlock_node (node);
630
631 return 1;
632 }
633 return -1;
634}
635
636/* Lookup function. */
637int
hasso98b718a2004-10-11 12:57:57 +0000638ripng_enable_if_lookup (const char *ifname)
paul718e3742002-12-13 20:15:29 +0000639{
hasso7a1d5832004-10-08 06:32:23 +0000640 unsigned int i;
paul718e3742002-12-13 20:15:29 +0000641 char *str;
642
paul55468c82005-03-14 20:19:01 +0000643 for (i = 0; i < vector_active (ripng_enable_if); i++)
paul718e3742002-12-13 20:15:29 +0000644 if ((str = vector_slot (ripng_enable_if, i)) != NULL)
645 if (strcmp (str, ifname) == 0)
646 return i;
647 return -1;
648}
649
650/* Add interface to ripng_enable_if. */
651int
hasso98b718a2004-10-11 12:57:57 +0000652ripng_enable_if_add (const char *ifname)
paul718e3742002-12-13 20:15:29 +0000653{
654 int ret;
655
656 ret = ripng_enable_if_lookup (ifname);
657 if (ret >= 0)
658 return -1;
659
660 vector_set (ripng_enable_if, strdup (ifname));
661
hassoa94434b2003-05-25 17:10:12 +0000662 ripng_enable_apply_all();
663
paul718e3742002-12-13 20:15:29 +0000664 return 1;
665}
666
667/* Delete interface from ripng_enable_if. */
668int
hasso98b718a2004-10-11 12:57:57 +0000669ripng_enable_if_delete (const char *ifname)
paul718e3742002-12-13 20:15:29 +0000670{
671 int index;
672 char *str;
673
674 index = ripng_enable_if_lookup (ifname);
675 if (index < 0)
676 return -1;
677
678 str = vector_slot (ripng_enable_if, index);
679 free (str);
680 vector_unset (ripng_enable_if, index);
681
hassoa94434b2003-05-25 17:10:12 +0000682 ripng_enable_apply_all();
683
paul718e3742002-12-13 20:15:29 +0000684 return 1;
685}
686
687/* Wake up interface. */
688int
689ripng_interface_wakeup (struct thread *t)
690{
691 struct interface *ifp;
692 struct ripng_interface *ri;
693
694 /* Get interface. */
695 ifp = THREAD_ARG (t);
696
697 ri = ifp->info;
698 ri->t_wakeup = NULL;
699
700 /* Join to multicast group. */
hassoa94434b2003-05-25 17:10:12 +0000701 if (ripng_multicast_join (ifp) < 0) {
702 zlog_err ("multicast join failed, interface %s not running", ifp->name);
703 return 0;
704 }
705
706 /* Set running flag. */
707 ri->running = 1;
paul718e3742002-12-13 20:15:29 +0000708
709 /* Send RIP request to the interface. */
710 ripng_request (ifp);
711
712 return 0;
713}
714
hassoa94434b2003-05-25 17:10:12 +0000715int ripng_redistribute_check (int);
716
717void
718ripng_connect_set (struct interface *ifp, int set)
719{
paul1eb8ef22005-04-07 07:30:20 +0000720 struct listnode *node, *nnode;
hassoa94434b2003-05-25 17:10:12 +0000721 struct connected *connected;
722 struct prefix_ipv6 address;
723
paul1eb8ef22005-04-07 07:30:20 +0000724 for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, connected))
725 {
hassoa94434b2003-05-25 17:10:12 +0000726 struct prefix *p;
727 p = connected->address;
728
729 if (p->family != AF_INET6)
730 continue;
731
732 address.family = AF_INET6;
733 address.prefix = p->u.prefix6;
734 address.prefixlen = p->prefixlen;
735 apply_mask_ipv6 (&address);
736
737 if (set) {
738 /* Check once more wether this prefix is within a "network IF_OR_PREF" one */
739 if ((ripng_enable_if_lookup(connected->ifp->name) >= 0) ||
740 (ripng_enable_network_lookup2(connected) >= 0))
741 ripng_redistribute_add (ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_INTERFACE,
742 &address, connected->ifp->ifindex, NULL);
743 } else {
744 ripng_redistribute_delete (ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_INTERFACE,
745 &address, connected->ifp->ifindex);
746 if (ripng_redistribute_check (ZEBRA_ROUTE_CONNECT))
747 ripng_redistribute_add (ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_REDISTRIBUTE,
748 &address, connected->ifp->ifindex, NULL);
749 }
750 }
751}
752
paul718e3742002-12-13 20:15:29 +0000753/* Check RIPng is enabed on this interface. */
754void
755ripng_enable_apply (struct interface *ifp)
756{
757 int ret;
758 struct ripng_interface *ri = NULL;
759
760 /* Check interface. */
paul718e3742002-12-13 20:15:29 +0000761 if (! if_is_up (ifp))
762 return;
763
764 ri = ifp->info;
765
hassoa94434b2003-05-25 17:10:12 +0000766 /* Is this interface a candidate for RIPng ? */
767 ret = ripng_enable_network_lookup_if (ifp);
paul718e3742002-12-13 20:15:29 +0000768
769 /* If the interface is matched. */
770 if (ret > 0)
771 ri->enable_network = 1;
772 else
773 ri->enable_network = 0;
774
775 /* Check interface name configuration. */
776 ret = ripng_enable_if_lookup (ifp->name);
777 if (ret >= 0)
778 ri->enable_interface = 1;
779 else
780 ri->enable_interface = 0;
781
hassoa94434b2003-05-25 17:10:12 +0000782 /* any candidate interface MUST have a link-local IPv6 address */
783 if ((! ripng_if_ipv6_lladdress_check (ifp)) &&
784 (ri->enable_network || ri->enable_interface)) {
785 ri->enable_network = 0;
786 ri->enable_interface = 0;
787 zlog_warn("Interface %s does not have any link-local address",
788 ifp->name);
789 }
790
paul718e3742002-12-13 20:15:29 +0000791 /* Update running status of the interface. */
792 if (ri->enable_network || ri->enable_interface)
793 {
paul718e3742002-12-13 20:15:29 +0000794 {
795 if (IS_RIPNG_DEBUG_EVENT)
ajs2e23ab22004-12-08 19:46:50 +0000796 zlog_debug ("RIPng turn on %s", ifp->name);
paul718e3742002-12-13 20:15:29 +0000797
798 /* Add interface wake up thread. */
799 if (! ri->t_wakeup)
800 ri->t_wakeup = thread_add_timer (master, ripng_interface_wakeup,
801 ifp, 1);
paul718e3742002-12-13 20:15:29 +0000802
hassoa94434b2003-05-25 17:10:12 +0000803 ripng_connect_set (ifp, 1);
paul718e3742002-12-13 20:15:29 +0000804 }
805 }
806 else
807 {
808 if (ri->running)
809 {
hassoa94434b2003-05-25 17:10:12 +0000810 /* Might as well clean up the route table as well
811 * ripng_if_down sets to 0 ri->running, and displays "turn off %s"
812 **/
813 ripng_if_down(ifp);
paul718e3742002-12-13 20:15:29 +0000814
hassoa94434b2003-05-25 17:10:12 +0000815 ripng_connect_set (ifp, 0);
paul718e3742002-12-13 20:15:29 +0000816 }
817 }
818}
819
820/* Set distribute list to all interfaces. */
hassoa94434b2003-05-25 17:10:12 +0000821void
paul718e3742002-12-13 20:15:29 +0000822ripng_enable_apply_all ()
823{
824 struct interface *ifp;
hasso52dc7ee2004-09-23 19:18:23 +0000825 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000826
paul1eb8ef22005-04-07 07:30:20 +0000827 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
828 ripng_enable_apply (ifp);
paul718e3742002-12-13 20:15:29 +0000829}
830
hassoa94434b2003-05-25 17:10:12 +0000831/* Clear all network and neighbor configuration */
832void
833ripng_clean_network ()
834{
hasso7a1d5832004-10-08 06:32:23 +0000835 unsigned int i;
hassoa94434b2003-05-25 17:10:12 +0000836 char *str;
837 struct route_node *rn;
838
839 /* ripng_enable_network */
840 for (rn = route_top (ripng_enable_network); rn; rn = route_next (rn))
841 if (rn->info) {
842 rn->info = NULL;
843 route_unlock_node(rn);
844 }
845
846 /* ripng_enable_if */
paul55468c82005-03-14 20:19:01 +0000847 for (i = 0; i < vector_active (ripng_enable_if); i++)
hassoa94434b2003-05-25 17:10:12 +0000848 if ((str = vector_slot (ripng_enable_if, i)) != NULL) {
849 free (str);
850 vector_slot (ripng_enable_if, i) = NULL;
851 }
852}
853
paul718e3742002-12-13 20:15:29 +0000854/* Vector to store passive-interface name. */
855vector Vripng_passive_interface;
856
857/* Utility function for looking up passive interface settings. */
858int
hasso98b718a2004-10-11 12:57:57 +0000859ripng_passive_interface_lookup (const char *ifname)
paul718e3742002-12-13 20:15:29 +0000860{
hasso7a1d5832004-10-08 06:32:23 +0000861 unsigned int i;
paul718e3742002-12-13 20:15:29 +0000862 char *str;
863
paul55468c82005-03-14 20:19:01 +0000864 for (i = 0; i < vector_active (Vripng_passive_interface); i++)
paul718e3742002-12-13 20:15:29 +0000865 if ((str = vector_slot (Vripng_passive_interface, i)) != NULL)
866 if (strcmp (str, ifname) == 0)
867 return i;
868 return -1;
869}
870
871void
872ripng_passive_interface_apply (struct interface *ifp)
873{
874 int ret;
875 struct ripng_interface *ri;
876
877 ri = ifp->info;
878
879 ret = ripng_passive_interface_lookup (ifp->name);
880 if (ret < 0)
881 ri->passive = 0;
882 else
883 ri->passive = 1;
884}
885
886void
887ripng_passive_interface_apply_all (void)
888{
889 struct interface *ifp;
hasso52dc7ee2004-09-23 19:18:23 +0000890 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000891
paul1eb8ef22005-04-07 07:30:20 +0000892 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
893 ripng_passive_interface_apply (ifp);
paul718e3742002-12-13 20:15:29 +0000894}
895
896/* Passive interface. */
897int
hasso98b718a2004-10-11 12:57:57 +0000898ripng_passive_interface_set (struct vty *vty, const char *ifname)
paul718e3742002-12-13 20:15:29 +0000899{
900 if (ripng_passive_interface_lookup (ifname) >= 0)
901 return CMD_WARNING;
902
903 vector_set (Vripng_passive_interface, strdup (ifname));
904
905 ripng_passive_interface_apply_all ();
906
907 return CMD_SUCCESS;
908}
909
910int
hasso98b718a2004-10-11 12:57:57 +0000911ripng_passive_interface_unset (struct vty *vty, const char *ifname)
paul718e3742002-12-13 20:15:29 +0000912{
913 int i;
914 char *str;
915
916 i = ripng_passive_interface_lookup (ifname);
917 if (i < 0)
918 return CMD_WARNING;
919
920 str = vector_slot (Vripng_passive_interface, i);
921 free (str);
922 vector_unset (Vripng_passive_interface, i);
923
924 ripng_passive_interface_apply_all ();
925
926 return CMD_SUCCESS;
927}
928
929/* Free all configured RIP passive-interface settings. */
930void
931ripng_passive_interface_clean (void)
932{
hasso7a1d5832004-10-08 06:32:23 +0000933 unsigned int i;
paul718e3742002-12-13 20:15:29 +0000934 char *str;
935
paul55468c82005-03-14 20:19:01 +0000936 for (i = 0; i < vector_active (Vripng_passive_interface); i++)
paul718e3742002-12-13 20:15:29 +0000937 if ((str = vector_slot (Vripng_passive_interface, i)) != NULL)
938 {
939 free (str);
940 vector_slot (Vripng_passive_interface, i) = NULL;
941 }
942 ripng_passive_interface_apply_all ();
943}
944
945/* Write RIPng enable network and interface to the vty. */
946int
hassoa94434b2003-05-25 17:10:12 +0000947ripng_network_write (struct vty *vty, int config_mode)
paul718e3742002-12-13 20:15:29 +0000948{
hasso7a1d5832004-10-08 06:32:23 +0000949 unsigned int i;
hasso98b718a2004-10-11 12:57:57 +0000950 const char *ifname;
paul718e3742002-12-13 20:15:29 +0000951 struct route_node *node;
952 char buf[BUFSIZ];
953
954 /* Write enable network. */
955 for (node = route_top (ripng_enable_network); node; node = route_next (node))
956 if (node->info)
957 {
958 struct prefix *p = &node->p;
hassoa94434b2003-05-25 17:10:12 +0000959 vty_out (vty, "%s%s/%d%s",
960 config_mode ? " network " : " ",
paul718e3742002-12-13 20:15:29 +0000961 inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ),
962 p->prefixlen,
963 VTY_NEWLINE);
964
965 }
966
967 /* Write enable interface. */
paul55468c82005-03-14 20:19:01 +0000968 for (i = 0; i < vector_active (ripng_enable_if); i++)
hassoa94434b2003-05-25 17:10:12 +0000969 if ((ifname = vector_slot (ripng_enable_if, i)) != NULL)
970 vty_out (vty, "%s%s%s",
971 config_mode ? " network " : " ",
972 ifname,
paul718e3742002-12-13 20:15:29 +0000973 VTY_NEWLINE);
974
975 /* Write passive interface. */
hassoa94434b2003-05-25 17:10:12 +0000976 if (config_mode)
paul55468c82005-03-14 20:19:01 +0000977 for (i = 0; i < vector_active (Vripng_passive_interface); i++)
hassoa94434b2003-05-25 17:10:12 +0000978 if ((ifname = vector_slot (Vripng_passive_interface, i)) != NULL)
979 vty_out (vty, " passive-interface %s%s", ifname, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000980
981 return 0;
982}
983
984/* RIPng enable on specified interface or matched network. */
985DEFUN (ripng_network,
986 ripng_network_cmd,
987 "network IF_OR_ADDR",
988 "RIPng enable on specified interface or network.\n"
989 "Interface or address")
990{
991 int ret;
992 struct prefix p;
993
994 ret = str2prefix (argv[0], &p);
995
996 /* Given string is IPv6 network or interface name. */
997 if (ret)
998 ret = ripng_enable_network_add (&p);
999 else
1000 ret = ripng_enable_if_add (argv[0]);
1001
1002 if (ret < 0)
1003 {
1004 vty_out (vty, "There is same network configuration %s%s", argv[0],
1005 VTY_NEWLINE);
1006 return CMD_WARNING;
1007 }
1008
paul718e3742002-12-13 20:15:29 +00001009 return CMD_SUCCESS;
1010}
1011
1012/* RIPng enable on specified interface or matched network. */
1013DEFUN (no_ripng_network,
1014 no_ripng_network_cmd,
1015 "no network IF_OR_ADDR",
1016 NO_STR
1017 "RIPng enable on specified interface or network.\n"
1018 "Interface or address")
1019{
1020 int ret;
1021 struct prefix p;
1022
1023 ret = str2prefix (argv[0], &p);
1024
1025 /* Given string is interface name. */
1026 if (ret)
1027 ret = ripng_enable_network_delete (&p);
1028 else
1029 ret = ripng_enable_if_delete (argv[0]);
1030
1031 if (ret < 0)
1032 {
1033 vty_out (vty, "can't find network %s%s", argv[0],
1034 VTY_NEWLINE);
1035 return CMD_WARNING;
1036 }
1037
paul718e3742002-12-13 20:15:29 +00001038 return CMD_SUCCESS;
1039}
1040
hassoa94434b2003-05-25 17:10:12 +00001041DEFUN (ipv6_ripng_split_horizon,
1042 ipv6_ripng_split_horizon_cmd,
1043 "ipv6 ripng split-horizon",
1044 IPV6_STR
1045 "Routing Information Protocol\n"
1046 "Perform split horizon\n")
1047{
1048 struct interface *ifp;
1049 struct ripng_interface *ri;
1050
1051 ifp = vty->index;
1052 ri = ifp->info;
1053
1054 ri->split_horizon = RIPNG_SPLIT_HORIZON;
1055 return CMD_SUCCESS;
1056}
1057
1058DEFUN (ipv6_ripng_split_horizon_poisoned_reverse,
1059 ipv6_ripng_split_horizon_poisoned_reverse_cmd,
1060 "ipv6 ripng split-horizon poisoned-reverse",
1061 IPV6_STR
1062 "Routing Information Protocol\n"
1063 "Perform split horizon\n"
1064 "With poisoned-reverse\n")
1065{
1066 struct interface *ifp;
1067 struct ripng_interface *ri;
1068
1069 ifp = vty->index;
1070 ri = ifp->info;
1071
1072 ri->split_horizon = RIPNG_SPLIT_HORIZON_POISONED_REVERSE;
1073 return CMD_SUCCESS;
1074}
1075
1076DEFUN (no_ipv6_ripng_split_horizon,
1077 no_ipv6_ripng_split_horizon_cmd,
1078 "no ipv6 ripng split-horizon",
1079 NO_STR
1080 IPV6_STR
1081 "Routing Information Protocol\n"
1082 "Perform split horizon\n")
1083{
1084 struct interface *ifp;
1085 struct ripng_interface *ri;
1086
1087 ifp = vty->index;
1088 ri = ifp->info;
1089
1090 ri->split_horizon = RIPNG_NO_SPLIT_HORIZON;
1091 return CMD_SUCCESS;
1092}
1093
1094ALIAS (no_ipv6_ripng_split_horizon,
1095 no_ipv6_ripng_split_horizon_poisoned_reverse_cmd,
1096 "no ipv6 ripng split-horizon poisoned-reverse",
1097 NO_STR
1098 IPV6_STR
1099 "Routing Information Protocol\n"
1100 "Perform split horizon\n"
1101 "With poisoned-reverse\n")
1102
paul718e3742002-12-13 20:15:29 +00001103DEFUN (ripng_passive_interface,
1104 ripng_passive_interface_cmd,
1105 "passive-interface IFNAME",
1106 "Suppress routing updates on an interface\n"
1107 "Interface name\n")
1108{
1109 return ripng_passive_interface_set (vty, argv[0]);
1110}
1111
1112DEFUN (no_ripng_passive_interface,
1113 no_ripng_passive_interface_cmd,
1114 "no passive-interface IFNAME",
1115 NO_STR
1116 "Suppress routing updates on an interface\n"
1117 "Interface name\n")
1118{
1119 return ripng_passive_interface_unset (vty, argv[0]);
1120}
1121
1122struct ripng_interface *
1123ri_new ()
1124{
1125 struct ripng_interface *ri;
1126 ri = XCALLOC (MTYPE_IF, sizeof (struct ripng_interface));
hassoa94434b2003-05-25 17:10:12 +00001127
1128 /* Set default split-horizon behavior. If the interface is Frame
1129 Relay or SMDS is enabled, the default value for split-horizon is
1130 off. But currently Zebra does detect Frame Relay or SMDS
1131 interface. So all interface is set to split horizon. */
1132 ri->split_horizon_default = RIPNG_SPLIT_HORIZON;
1133 ri->split_horizon = ri->split_horizon_default;
1134
paul718e3742002-12-13 20:15:29 +00001135 return ri;
1136}
1137
1138int
1139ripng_if_new_hook (struct interface *ifp)
1140{
1141 ifp->info = ri_new ();
1142 return 0;
1143}
1144
hassoa94434b2003-05-25 17:10:12 +00001145/* Called when interface structure deleted. */
1146int
1147ripng_if_delete_hook (struct interface *ifp)
1148{
1149 XFREE (MTYPE_IF, ifp->info);
1150 ifp->info = NULL;
1151 return 0;
1152}
1153
paul718e3742002-12-13 20:15:29 +00001154/* Configuration write function for ripngd. */
1155int
1156interface_config_write (struct vty *vty)
1157{
hasso52dc7ee2004-09-23 19:18:23 +00001158 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001159 struct interface *ifp;
1160 struct ripng_interface *ri;
1161 int write = 0;
1162
paul1eb8ef22005-04-07 07:30:20 +00001163 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
paul718e3742002-12-13 20:15:29 +00001164 {
paul718e3742002-12-13 20:15:29 +00001165 ri = ifp->info;
1166
hassoa94434b2003-05-25 17:10:12 +00001167 /* Do not display the interface if there is no
1168 * configuration about it.
1169 **/
1170 if ((!ifp->desc) &&
1171 (ri->split_horizon == ri->split_horizon_default))
1172 continue;
1173
paul718e3742002-12-13 20:15:29 +00001174 vty_out (vty, "interface %s%s", ifp->name,
1175 VTY_NEWLINE);
1176 if (ifp->desc)
1177 vty_out (vty, " description %s%s", ifp->desc,
1178 VTY_NEWLINE);
1179
hassoa94434b2003-05-25 17:10:12 +00001180 /* Split horizon. */
1181 if (ri->split_horizon != ri->split_horizon_default)
1182 {
1183 switch (ri->split_horizon) {
1184 case RIPNG_SPLIT_HORIZON:
1185 vty_out (vty, " ipv6 ripng split-horizon%s", VTY_NEWLINE);
1186 break;
1187 case RIPNG_SPLIT_HORIZON_POISONED_REVERSE:
1188 vty_out (vty, " ipv6 ripng split-horizon poisoned-reverse%s",
1189 VTY_NEWLINE);
1190 break;
1191 case RIPNG_NO_SPLIT_HORIZON:
1192 default:
1193 vty_out (vty, " no ipv6 ripng split-horizon%s", VTY_NEWLINE);
1194 break;
1195 }
1196 }
1197
paul718e3742002-12-13 20:15:29 +00001198 vty_out (vty, "!%s", VTY_NEWLINE);
1199
1200 write++;
1201 }
1202 return write;
1203}
1204
1205/* ripngd's interface node. */
1206struct cmd_node interface_node =
1207{
1208 INTERFACE_NODE,
1209 "%s(config-if)# ",
hassoa94434b2003-05-25 17:10:12 +00001210 1 /* VTYSH */
paul718e3742002-12-13 20:15:29 +00001211};
1212
1213/* Initialization of interface. */
1214void
1215ripng_if_init ()
1216{
1217 /* Interface initialize. */
1218 iflist = list_new ();
1219 if_add_hook (IF_NEW_HOOK, ripng_if_new_hook);
hassoa94434b2003-05-25 17:10:12 +00001220 if_add_hook (IF_DELETE_HOOK, ripng_if_delete_hook);
paul718e3742002-12-13 20:15:29 +00001221
1222 /* RIPng enable network init. */
1223 ripng_enable_network = route_table_init ();
1224
1225 /* RIPng enable interface init. */
1226 ripng_enable_if = vector_init (1);
1227
1228 /* RIPng passive interface. */
1229 Vripng_passive_interface = vector_init (1);
1230
1231 /* Install interface node. */
1232 install_node (&interface_node, interface_config_write);
hassoa94434b2003-05-25 17:10:12 +00001233
1234 /* Install commands. */
paul718e3742002-12-13 20:15:29 +00001235 install_element (CONFIG_NODE, &interface_cmd);
paul32d24632003-05-23 09:25:20 +00001236 install_element (CONFIG_NODE, &no_interface_cmd);
hassoa94434b2003-05-25 17:10:12 +00001237 install_default (INTERFACE_NODE);
paul718e3742002-12-13 20:15:29 +00001238 install_element (INTERFACE_NODE, &interface_desc_cmd);
1239 install_element (INTERFACE_NODE, &no_interface_desc_cmd);
1240
1241 install_element (RIPNG_NODE, &ripng_network_cmd);
1242 install_element (RIPNG_NODE, &no_ripng_network_cmd);
1243 install_element (RIPNG_NODE, &ripng_passive_interface_cmd);
1244 install_element (RIPNG_NODE, &no_ripng_passive_interface_cmd);
hassoa94434b2003-05-25 17:10:12 +00001245
1246 install_element (INTERFACE_NODE, &ipv6_ripng_split_horizon_cmd);
1247 install_element (INTERFACE_NODE, &ipv6_ripng_split_horizon_poisoned_reverse_cmd);
1248 install_element (INTERFACE_NODE, &no_ipv6_ripng_split_horizon_cmd);
1249 install_element (INTERFACE_NODE, &no_ipv6_ripng_split_horizon_poisoned_reverse_cmd);
paul718e3742002-12-13 20:15:29 +00001250}