blob: 477bfd7fdd23778c75ad4515a7046d09ccb5fbba [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
147 for (nn = listhead (ifp->connected); nn; nextnode (nn))
148 if ((connected = getdata (nn)) != NULL) {
149 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;
169 for (node = listhead (iflist); node; nextnode (node))
170 {
171 ifp = getdata (node);
hasso1203e1c2004-07-23 21:34:27 +0000172 if (mtu < ifp->mtu6)
173 mtu = ifp->mtu6;
paul718e3742002-12-13 20:15:29 +0000174 }
175 return mtu;
176}
177
178int
179ripng_if_down (struct interface *ifp)
180{
181 struct route_node *rp;
182 struct ripng_info *rinfo;
183 struct ripng_interface *ri;
184
hassoa94434b2003-05-25 17:10:12 +0000185 if (ripng)
paul718e3742002-12-13 20:15:29 +0000186 {
187 for (rp = route_top (ripng->table); rp; rp = route_next (rp))
188 if ((rinfo = rp->info) != NULL)
189 {
190 /* Routes got through this interface. */
191 if (rinfo->ifindex == ifp->ifindex
192 && rinfo->type == ZEBRA_ROUTE_RIPNG
193 && rinfo->sub_type == RIPNG_ROUTE_RTE)
194 {
195 ripng_zebra_ipv6_delete ((struct prefix_ipv6 *) &rp->p,
196 &rinfo->nexthop,
197 rinfo->ifindex);
198
hassoa94434b2003-05-25 17:10:12 +0000199 ripng_redistribute_delete (rinfo->type, rinfo->sub_type,
200 (struct prefix_ipv6 *)&rp->p,
201 rinfo->ifindex);
paul718e3742002-12-13 20:15:29 +0000202 }
203 else
204 {
hassoa94434b2003-05-25 17:10:12 +0000205 /* All redistributed routes got through this interface,
206 * but the static and system ones are kept. */
207 if ((rinfo->ifindex == ifp->ifindex) &&
208 (rinfo->type != ZEBRA_ROUTE_STATIC) &&
209 (rinfo->type != ZEBRA_ROUTE_SYSTEM))
paul718e3742002-12-13 20:15:29 +0000210 ripng_redistribute_delete (rinfo->type, rinfo->sub_type,
211 (struct prefix_ipv6 *) &rp->p,
212 rinfo->ifindex);
213 }
214 }
215 }
216
217 ri = ifp->info;
218
hassoa94434b2003-05-25 17:10:12 +0000219 if (ri->running)
paul718e3742002-12-13 20:15:29 +0000220 {
221 if (IS_RIPNG_DEBUG_EVENT)
ajs2e23ab22004-12-08 19:46:50 +0000222 zlog_debug ("turn off %s", ifp->name);
paul718e3742002-12-13 20:15:29 +0000223
224 /* Leave from multicast group. */
225 ripng_multicast_leave (ifp);
226
227 ri->running = 0;
228 }
229
230 return 0;
231}
232
233/* Inteface link up message processing. */
234int
235ripng_interface_up (int command, struct zclient *zclient, zebra_size_t length)
236{
237 struct stream *s;
238 struct interface *ifp;
239
240 /* zebra_interface_state_read() updates interface structure in iflist. */
241 s = zclient->ibuf;
242 ifp = zebra_interface_state_read (s);
243
244 if (ifp == NULL)
245 return 0;
246
247 if (IS_RIPNG_DEBUG_ZEBRA)
ajs2e23ab22004-12-08 19:46:50 +0000248 zlog_debug ("interface up %s index %d flags %ld metric %d mtu %d",
hasso1203e1c2004-07-23 21:34:27 +0000249 ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu6);
paul718e3742002-12-13 20:15:29 +0000250
251 /* Check if this interface is RIPng enabled or not. */
252 ripng_enable_apply (ifp);
253
254 /* Check for a passive interface. */
255 ripng_passive_interface_apply (ifp);
256
257 /* Apply distribute list to the all interface. */
258 ripng_distribute_update_interface (ifp);
259
260 return 0;
261}
262
263/* Inteface link down message processing. */
264int
265ripng_interface_down (int command, struct zclient *zclient,
266 zebra_size_t length)
267{
268 struct stream *s;
269 struct interface *ifp;
270
271 /* zebra_interface_state_read() updates interface structure in iflist. */
272 s = zclient->ibuf;
273 ifp = zebra_interface_state_read (s);
274
275 if (ifp == NULL)
276 return 0;
277
278 ripng_if_down (ifp);
279
280 if (IS_RIPNG_DEBUG_ZEBRA)
ajs2e23ab22004-12-08 19:46:50 +0000281 zlog_debug ("interface down %s index %d flags %ld metric %d mtu %d",
hasso1203e1c2004-07-23 21:34:27 +0000282 ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu6);
paul718e3742002-12-13 20:15:29 +0000283
284 return 0;
285}
286
287/* Inteface addition message from zebra. */
288int
289ripng_interface_add (int command, struct zclient *zclient, zebra_size_t length)
290{
291 struct interface *ifp;
292
293 ifp = zebra_interface_add_read (zclient->ibuf);
294
295 if (IS_RIPNG_DEBUG_ZEBRA)
ajs2e23ab22004-12-08 19:46:50 +0000296 zlog_debug ("RIPng interface add %s index %d flags %ld metric %d mtu %d",
hasso1203e1c2004-07-23 21:34:27 +0000297 ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu6);
paul718e3742002-12-13 20:15:29 +0000298
299 /* Check is this interface is RIP enabled or not.*/
300 ripng_enable_apply (ifp);
301
302 /* Apply distribute list to the interface. */
303 ripng_distribute_update_interface (ifp);
304
305 /* Check interface routemap. */
306 ripng_if_rmap_update_interface (ifp);
307
308 return 0;
309}
310
311int
312ripng_interface_delete (int command, struct zclient *zclient,
313 zebra_size_t length)
314{
hassoa94434b2003-05-25 17:10:12 +0000315 struct interface *ifp;
316 struct stream *s;
317
318 s = zclient->ibuf;
319 /* zebra_interface_state_read() updates interface structure in iflist */
320 ifp = zebra_interface_state_read(s);
321
322 if (ifp == NULL)
323 return 0;
324
325 if (if_is_up (ifp)) {
326 ripng_if_down(ifp);
327 }
328
329 zlog_info("interface delete %s index %d flags %ld metric %d mtu %d",
hasso1203e1c2004-07-23 21:34:27 +0000330 ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu6);
hassoa94434b2003-05-25 17:10:12 +0000331
332 /* To support pseudo interface do not free interface structure. */
333 /* if_delete(ifp); */
ajsd2fc8892005-04-02 18:38:43 +0000334 ifp->ifindex = IFINDEX_INTERNAL;
hassoa94434b2003-05-25 17:10:12 +0000335
paul718e3742002-12-13 20:15:29 +0000336 return 0;
337}
338
hassoa94434b2003-05-25 17:10:12 +0000339void
340ripng_interface_clean ()
341{
hasso52dc7ee2004-09-23 19:18:23 +0000342 struct listnode *node;
hassoa94434b2003-05-25 17:10:12 +0000343 struct interface *ifp;
344 struct ripng_interface *ri;
345
346 for (node = listhead (iflist); node; nextnode (node))
347 {
348 ifp = getdata (node);
349 ri = ifp->info;
350
351 ri->enable_network = 0;
352 ri->enable_interface = 0;
353 ri->running = 0;
354
355 if (ri->t_wakeup)
356 {
357 thread_cancel (ri->t_wakeup);
358 ri->t_wakeup = NULL;
359 }
360 }
361}
362
363void
364ripng_interface_reset () {
hasso52dc7ee2004-09-23 19:18:23 +0000365 struct listnode *node;
hassoa94434b2003-05-25 17:10:12 +0000366 struct interface *ifp;
367 struct ripng_interface *ri;
368
369 for (node = listhead (iflist); node; nextnode (node))
370 {
371 ifp = getdata (node);
372 ri = ifp->info;
373
374 ri->enable_network = 0;
375 ri->enable_interface = 0;
376 ri->running = 0;
377
378 ri->split_horizon = RIPNG_NO_SPLIT_HORIZON;
379 ri->split_horizon_default = RIPNG_NO_SPLIT_HORIZON;
380
381 ri->list[RIPNG_FILTER_IN] = NULL;
382 ri->list[RIPNG_FILTER_OUT] = NULL;
383
384 ri->prefix[RIPNG_FILTER_IN] = NULL;
385 ri->prefix[RIPNG_FILTER_OUT] = NULL;
386
387 if (ri->t_wakeup)
388 {
389 thread_cancel (ri->t_wakeup);
390 ri->t_wakeup = NULL;
391 }
392
393 ri->passive = 0;
394 }
395}
396
397static void
398ripng_apply_address_add (struct connected *ifc) {
399 struct prefix_ipv6 address;
400 struct prefix *p;
401
402 if (!ripng)
403 return;
404
405 if (! if_is_up(ifc->ifp))
406 return;
407
408 p = ifc->address;
409
410 memset (&address, 0, sizeof (address));
411 address.family = p->family;
412 address.prefix = p->u.prefix6;
413 address.prefixlen = p->prefixlen;
414 apply_mask_ipv6(&address);
415
416 /* Check if this interface is RIP enabled or not
417 or Check if this address's prefix is RIP enabled */
418 if ((ripng_enable_if_lookup(ifc->ifp->name) >= 0) ||
419 (ripng_enable_network_lookup2(ifc) >= 0))
420 ripng_redistribute_add(ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_INTERFACE,
421 &address, ifc->ifp->ifindex, NULL);
422
423}
424
paul718e3742002-12-13 20:15:29 +0000425int
426ripng_interface_address_add (int command, struct zclient *zclient,
427 zebra_size_t length)
428{
429 struct connected *c;
430 struct prefix *p;
paul718e3742002-12-13 20:15:29 +0000431
paul0a589352004-05-08 11:48:26 +0000432 c = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_ADD,
433 zclient->ibuf);
paul718e3742002-12-13 20:15:29 +0000434
435 if (c == NULL)
436 return 0;
437
438 p = c->address;
439
440 if (p->family == AF_INET6)
441 {
442 if (IS_RIPNG_DEBUG_ZEBRA)
ajs2e23ab22004-12-08 19:46:50 +0000443 zlog_debug ("RIPng connected address %s/%d add",
hassoa94434b2003-05-25 17:10:12 +0000444 inet6_ntop(&p->u.prefix6),
paul718e3742002-12-13 20:15:29 +0000445 p->prefixlen);
446
hassoa94434b2003-05-25 17:10:12 +0000447 /* Check is this prefix needs to be redistributed. */
448 ripng_apply_address_add(c);
449
450 /* Let's try once again whether the interface could be activated */
451 if (c->ifp) {
452 struct ripng_interface *ri = c->ifp->info;
453
454 if (!ri->running) {
455 /* Check if this interface is RIP enabled or not.*/
456 ripng_enable_apply (c->ifp);
457
458 /* Apply distribute list to the interface. */
459 ripng_distribute_update_interface (c->ifp);
460
461 /* Check interface routemap. */
462 ripng_if_rmap_update_interface (c->ifp);
463 }
464 }
465
paul718e3742002-12-13 20:15:29 +0000466 }
467
468 return 0;
469}
470
hassoa94434b2003-05-25 17:10:12 +0000471static void
472ripng_apply_address_del (struct connected *ifc) {
473 struct prefix_ipv6 address;
474 struct prefix *p;
475
476 if (!ripng)
477 return;
478
479 if (! if_is_up(ifc->ifp))
480 return;
481
482 p = ifc->address;
483
484 memset (&address, 0, sizeof (address));
485 address.family = p->family;
486 address.prefix = p->u.prefix6;
487 address.prefixlen = p->prefixlen;
488 apply_mask_ipv6(&address);
489
490 ripng_redistribute_delete(ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_INTERFACE,
491 &address, ifc->ifp->ifindex);
492}
493
paul718e3742002-12-13 20:15:29 +0000494int
495ripng_interface_address_delete (int command, struct zclient *zclient,
496 zebra_size_t length)
497{
498 struct connected *ifc;
499 struct prefix *p;
500 char buf[INET6_ADDRSTRLEN];
501
paul0a589352004-05-08 11:48:26 +0000502 ifc = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_DELETE,
503 zclient->ibuf);
paul718e3742002-12-13 20:15:29 +0000504
505 if (ifc)
506 {
507 p = ifc->address;
508
509 if (p->family == AF_INET6)
510 {
511 if (IS_RIPNG_DEBUG_ZEBRA)
ajs2e23ab22004-12-08 19:46:50 +0000512 zlog_debug ("RIPng connected address %s/%d delete",
paul718e3742002-12-13 20:15:29 +0000513 inet_ntop (AF_INET6, &p->u.prefix6, buf,
514 INET6_ADDRSTRLEN),
515 p->prefixlen);
516
hassoa94434b2003-05-25 17:10:12 +0000517 /* Check wether this prefix needs to be removed. */
518 ripng_apply_address_del(ifc);
paul718e3742002-12-13 20:15:29 +0000519 }
520 connected_free (ifc);
521 }
522
523 return 0;
524}
525
526/* RIPng enable interface vector. */
527vector ripng_enable_if;
528
529/* RIPng enable network table. */
530struct route_table *ripng_enable_network;
531
532/* Lookup RIPng enable network. */
hassoa94434b2003-05-25 17:10:12 +0000533/* Check wether the interface has at least a connected prefix that
534 * is within the ripng_enable_network table. */
paul718e3742002-12-13 20:15:29 +0000535int
hassoa94434b2003-05-25 17:10:12 +0000536ripng_enable_network_lookup_if (struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000537{
hasso52dc7ee2004-09-23 19:18:23 +0000538 struct listnode *listnode;
paul718e3742002-12-13 20:15:29 +0000539 struct connected *connected;
hassoa94434b2003-05-25 17:10:12 +0000540 struct prefix_ipv6 address;
paul718e3742002-12-13 20:15:29 +0000541
542 for (listnode = listhead (ifp->connected); listnode; nextnode (listnode))
543 if ((connected = getdata (listnode)) != NULL)
544 {
545 struct prefix *p;
546 struct route_node *node;
547
548 p = connected->address;
549
550 if (p->family == AF_INET6)
551 {
hassoa94434b2003-05-25 17:10:12 +0000552 address.family = AF_INET6;
553 address.prefix = p->u.prefix6;
554 address.prefixlen = IPV6_MAX_BITLEN;
555
556 node = route_node_match (ripng_enable_network,
557 (struct prefix *)&address);
paul718e3742002-12-13 20:15:29 +0000558 if (node)
559 {
560 route_unlock_node (node);
561 return 1;
562 }
563 }
564 }
565 return -1;
566}
567
hassoa94434b2003-05-25 17:10:12 +0000568/* Check wether connected is within the ripng_enable_network table. */
569int
570ripng_enable_network_lookup2 (struct connected *connected)
571{
572 struct prefix_ipv6 address;
573 struct prefix *p;
574
575 p = connected->address;
576
577 if (p->family == AF_INET6) {
578 struct route_node *node;
579
580 address.family = p->family;
581 address.prefix = p->u.prefix6;
582 address.prefixlen = IPV6_MAX_BITLEN;
583
584 /* LPM on p->family, p->u.prefix6/IPV6_MAX_BITLEN within ripng_enable_network */
585 node = route_node_match (ripng_enable_network,
586 (struct prefix *)&address);
587
588 if (node) {
589 route_unlock_node (node);
590 return 1;
591 }
592 }
593
594 return -1;
595}
596
paul718e3742002-12-13 20:15:29 +0000597/* Add RIPng enable network. */
598int
599ripng_enable_network_add (struct prefix *p)
600{
601 struct route_node *node;
602
603 node = route_node_get (ripng_enable_network, p);
604
605 if (node->info)
606 {
607 route_unlock_node (node);
608 return -1;
609 }
610 else
hasso7a1d5832004-10-08 06:32:23 +0000611 node->info = (char *) "enabled";
paul718e3742002-12-13 20:15:29 +0000612
hassoa94434b2003-05-25 17:10:12 +0000613 /* XXX: One should find a better solution than a generic one */
614 ripng_enable_apply_all();
615
paul718e3742002-12-13 20:15:29 +0000616 return 1;
617}
618
619/* Delete RIPng enable network. */
620int
621ripng_enable_network_delete (struct prefix *p)
622{
623 struct route_node *node;
624
625 node = route_node_lookup (ripng_enable_network, p);
626 if (node)
627 {
628 node->info = NULL;
629
630 /* Unlock info lock. */
631 route_unlock_node (node);
632
633 /* Unlock lookup lock. */
634 route_unlock_node (node);
635
636 return 1;
637 }
638 return -1;
639}
640
641/* Lookup function. */
642int
hasso98b718a2004-10-11 12:57:57 +0000643ripng_enable_if_lookup (const char *ifname)
paul718e3742002-12-13 20:15:29 +0000644{
hasso7a1d5832004-10-08 06:32:23 +0000645 unsigned int i;
paul718e3742002-12-13 20:15:29 +0000646 char *str;
647
paul55468c82005-03-14 20:19:01 +0000648 for (i = 0; i < vector_active (ripng_enable_if); i++)
paul718e3742002-12-13 20:15:29 +0000649 if ((str = vector_slot (ripng_enable_if, i)) != NULL)
650 if (strcmp (str, ifname) == 0)
651 return i;
652 return -1;
653}
654
655/* Add interface to ripng_enable_if. */
656int
hasso98b718a2004-10-11 12:57:57 +0000657ripng_enable_if_add (const char *ifname)
paul718e3742002-12-13 20:15:29 +0000658{
659 int ret;
660
661 ret = ripng_enable_if_lookup (ifname);
662 if (ret >= 0)
663 return -1;
664
665 vector_set (ripng_enable_if, strdup (ifname));
666
hassoa94434b2003-05-25 17:10:12 +0000667 ripng_enable_apply_all();
668
paul718e3742002-12-13 20:15:29 +0000669 return 1;
670}
671
672/* Delete interface from ripng_enable_if. */
673int
hasso98b718a2004-10-11 12:57:57 +0000674ripng_enable_if_delete (const char *ifname)
paul718e3742002-12-13 20:15:29 +0000675{
676 int index;
677 char *str;
678
679 index = ripng_enable_if_lookup (ifname);
680 if (index < 0)
681 return -1;
682
683 str = vector_slot (ripng_enable_if, index);
684 free (str);
685 vector_unset (ripng_enable_if, index);
686
hassoa94434b2003-05-25 17:10:12 +0000687 ripng_enable_apply_all();
688
paul718e3742002-12-13 20:15:29 +0000689 return 1;
690}
691
692/* Wake up interface. */
693int
694ripng_interface_wakeup (struct thread *t)
695{
696 struct interface *ifp;
697 struct ripng_interface *ri;
698
699 /* Get interface. */
700 ifp = THREAD_ARG (t);
701
702 ri = ifp->info;
703 ri->t_wakeup = NULL;
704
705 /* Join to multicast group. */
hassoa94434b2003-05-25 17:10:12 +0000706 if (ripng_multicast_join (ifp) < 0) {
707 zlog_err ("multicast join failed, interface %s not running", ifp->name);
708 return 0;
709 }
710
711 /* Set running flag. */
712 ri->running = 1;
paul718e3742002-12-13 20:15:29 +0000713
714 /* Send RIP request to the interface. */
715 ripng_request (ifp);
716
717 return 0;
718}
719
hassoa94434b2003-05-25 17:10:12 +0000720int ripng_redistribute_check (int);
721
722void
723ripng_connect_set (struct interface *ifp, int set)
724{
725 struct listnode *nn;
726 struct connected *connected;
727 struct prefix_ipv6 address;
728
729 for (nn = listhead (ifp->connected); nn; nextnode (nn))
730 if ((connected = getdata (nn)) != NULL) {
731 struct prefix *p;
732 p = connected->address;
733
734 if (p->family != AF_INET6)
735 continue;
736
737 address.family = AF_INET6;
738 address.prefix = p->u.prefix6;
739 address.prefixlen = p->prefixlen;
740 apply_mask_ipv6 (&address);
741
742 if (set) {
743 /* Check once more wether this prefix is within a "network IF_OR_PREF" one */
744 if ((ripng_enable_if_lookup(connected->ifp->name) >= 0) ||
745 (ripng_enable_network_lookup2(connected) >= 0))
746 ripng_redistribute_add (ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_INTERFACE,
747 &address, connected->ifp->ifindex, NULL);
748 } else {
749 ripng_redistribute_delete (ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_INTERFACE,
750 &address, connected->ifp->ifindex);
751 if (ripng_redistribute_check (ZEBRA_ROUTE_CONNECT))
752 ripng_redistribute_add (ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_REDISTRIBUTE,
753 &address, connected->ifp->ifindex, NULL);
754 }
755 }
756}
757
paul718e3742002-12-13 20:15:29 +0000758/* Check RIPng is enabed on this interface. */
759void
760ripng_enable_apply (struct interface *ifp)
761{
762 int ret;
763 struct ripng_interface *ri = NULL;
764
765 /* Check interface. */
paul718e3742002-12-13 20:15:29 +0000766 if (! if_is_up (ifp))
767 return;
768
769 ri = ifp->info;
770
hassoa94434b2003-05-25 17:10:12 +0000771 /* Is this interface a candidate for RIPng ? */
772 ret = ripng_enable_network_lookup_if (ifp);
paul718e3742002-12-13 20:15:29 +0000773
774 /* If the interface is matched. */
775 if (ret > 0)
776 ri->enable_network = 1;
777 else
778 ri->enable_network = 0;
779
780 /* Check interface name configuration. */
781 ret = ripng_enable_if_lookup (ifp->name);
782 if (ret >= 0)
783 ri->enable_interface = 1;
784 else
785 ri->enable_interface = 0;
786
hassoa94434b2003-05-25 17:10:12 +0000787 /* any candidate interface MUST have a link-local IPv6 address */
788 if ((! ripng_if_ipv6_lladdress_check (ifp)) &&
789 (ri->enable_network || ri->enable_interface)) {
790 ri->enable_network = 0;
791 ri->enable_interface = 0;
792 zlog_warn("Interface %s does not have any link-local address",
793 ifp->name);
794 }
795
paul718e3742002-12-13 20:15:29 +0000796 /* Update running status of the interface. */
797 if (ri->enable_network || ri->enable_interface)
798 {
paul718e3742002-12-13 20:15:29 +0000799 {
800 if (IS_RIPNG_DEBUG_EVENT)
ajs2e23ab22004-12-08 19:46:50 +0000801 zlog_debug ("RIPng turn on %s", ifp->name);
paul718e3742002-12-13 20:15:29 +0000802
803 /* Add interface wake up thread. */
804 if (! ri->t_wakeup)
805 ri->t_wakeup = thread_add_timer (master, ripng_interface_wakeup,
806 ifp, 1);
paul718e3742002-12-13 20:15:29 +0000807
hassoa94434b2003-05-25 17:10:12 +0000808 ripng_connect_set (ifp, 1);
paul718e3742002-12-13 20:15:29 +0000809 }
810 }
811 else
812 {
813 if (ri->running)
814 {
hassoa94434b2003-05-25 17:10:12 +0000815 /* Might as well clean up the route table as well
816 * ripng_if_down sets to 0 ri->running, and displays "turn off %s"
817 **/
818 ripng_if_down(ifp);
paul718e3742002-12-13 20:15:29 +0000819
hassoa94434b2003-05-25 17:10:12 +0000820 ripng_connect_set (ifp, 0);
paul718e3742002-12-13 20:15:29 +0000821 }
822 }
823}
824
825/* Set distribute list to all interfaces. */
hassoa94434b2003-05-25 17:10:12 +0000826void
paul718e3742002-12-13 20:15:29 +0000827ripng_enable_apply_all ()
828{
829 struct interface *ifp;
hasso52dc7ee2004-09-23 19:18:23 +0000830 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000831
832 for (node = listhead (iflist); node; nextnode (node))
833 {
834 ifp = getdata (node);
835 ripng_enable_apply (ifp);
836 }
837}
838
hassoa94434b2003-05-25 17:10:12 +0000839/* Clear all network and neighbor configuration */
840void
841ripng_clean_network ()
842{
hasso7a1d5832004-10-08 06:32:23 +0000843 unsigned int i;
hassoa94434b2003-05-25 17:10:12 +0000844 char *str;
845 struct route_node *rn;
846
847 /* ripng_enable_network */
848 for (rn = route_top (ripng_enable_network); rn; rn = route_next (rn))
849 if (rn->info) {
850 rn->info = NULL;
851 route_unlock_node(rn);
852 }
853
854 /* ripng_enable_if */
paul55468c82005-03-14 20:19:01 +0000855 for (i = 0; i < vector_active (ripng_enable_if); i++)
hassoa94434b2003-05-25 17:10:12 +0000856 if ((str = vector_slot (ripng_enable_if, i)) != NULL) {
857 free (str);
858 vector_slot (ripng_enable_if, i) = NULL;
859 }
860}
861
paul718e3742002-12-13 20:15:29 +0000862/* Vector to store passive-interface name. */
863vector Vripng_passive_interface;
864
865/* Utility function for looking up passive interface settings. */
866int
hasso98b718a2004-10-11 12:57:57 +0000867ripng_passive_interface_lookup (const char *ifname)
paul718e3742002-12-13 20:15:29 +0000868{
hasso7a1d5832004-10-08 06:32:23 +0000869 unsigned int i;
paul718e3742002-12-13 20:15:29 +0000870 char *str;
871
paul55468c82005-03-14 20:19:01 +0000872 for (i = 0; i < vector_active (Vripng_passive_interface); i++)
paul718e3742002-12-13 20:15:29 +0000873 if ((str = vector_slot (Vripng_passive_interface, i)) != NULL)
874 if (strcmp (str, ifname) == 0)
875 return i;
876 return -1;
877}
878
879void
880ripng_passive_interface_apply (struct interface *ifp)
881{
882 int ret;
883 struct ripng_interface *ri;
884
885 ri = ifp->info;
886
887 ret = ripng_passive_interface_lookup (ifp->name);
888 if (ret < 0)
889 ri->passive = 0;
890 else
891 ri->passive = 1;
892}
893
894void
895ripng_passive_interface_apply_all (void)
896{
897 struct interface *ifp;
hasso52dc7ee2004-09-23 19:18:23 +0000898 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000899
900 for (node = listhead (iflist); node; nextnode (node))
901 {
902 ifp = getdata (node);
903 ripng_passive_interface_apply (ifp);
904 }
905}
906
907/* Passive interface. */
908int
hasso98b718a2004-10-11 12:57:57 +0000909ripng_passive_interface_set (struct vty *vty, const char *ifname)
paul718e3742002-12-13 20:15:29 +0000910{
911 if (ripng_passive_interface_lookup (ifname) >= 0)
912 return CMD_WARNING;
913
914 vector_set (Vripng_passive_interface, strdup (ifname));
915
916 ripng_passive_interface_apply_all ();
917
918 return CMD_SUCCESS;
919}
920
921int
hasso98b718a2004-10-11 12:57:57 +0000922ripng_passive_interface_unset (struct vty *vty, const char *ifname)
paul718e3742002-12-13 20:15:29 +0000923{
924 int i;
925 char *str;
926
927 i = ripng_passive_interface_lookup (ifname);
928 if (i < 0)
929 return CMD_WARNING;
930
931 str = vector_slot (Vripng_passive_interface, i);
932 free (str);
933 vector_unset (Vripng_passive_interface, i);
934
935 ripng_passive_interface_apply_all ();
936
937 return CMD_SUCCESS;
938}
939
940/* Free all configured RIP passive-interface settings. */
941void
942ripng_passive_interface_clean (void)
943{
hasso7a1d5832004-10-08 06:32:23 +0000944 unsigned int i;
paul718e3742002-12-13 20:15:29 +0000945 char *str;
946
paul55468c82005-03-14 20:19:01 +0000947 for (i = 0; i < vector_active (Vripng_passive_interface); i++)
paul718e3742002-12-13 20:15:29 +0000948 if ((str = vector_slot (Vripng_passive_interface, i)) != NULL)
949 {
950 free (str);
951 vector_slot (Vripng_passive_interface, i) = NULL;
952 }
953 ripng_passive_interface_apply_all ();
954}
955
956/* Write RIPng enable network and interface to the vty. */
957int
hassoa94434b2003-05-25 17:10:12 +0000958ripng_network_write (struct vty *vty, int config_mode)
paul718e3742002-12-13 20:15:29 +0000959{
hasso7a1d5832004-10-08 06:32:23 +0000960 unsigned int i;
hasso98b718a2004-10-11 12:57:57 +0000961 const char *ifname;
paul718e3742002-12-13 20:15:29 +0000962 struct route_node *node;
963 char buf[BUFSIZ];
964
965 /* Write enable network. */
966 for (node = route_top (ripng_enable_network); node; node = route_next (node))
967 if (node->info)
968 {
969 struct prefix *p = &node->p;
hassoa94434b2003-05-25 17:10:12 +0000970 vty_out (vty, "%s%s/%d%s",
971 config_mode ? " network " : " ",
paul718e3742002-12-13 20:15:29 +0000972 inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ),
973 p->prefixlen,
974 VTY_NEWLINE);
975
976 }
977
978 /* Write enable interface. */
paul55468c82005-03-14 20:19:01 +0000979 for (i = 0; i < vector_active (ripng_enable_if); i++)
hassoa94434b2003-05-25 17:10:12 +0000980 if ((ifname = vector_slot (ripng_enable_if, i)) != NULL)
981 vty_out (vty, "%s%s%s",
982 config_mode ? " network " : " ",
983 ifname,
paul718e3742002-12-13 20:15:29 +0000984 VTY_NEWLINE);
985
986 /* Write passive interface. */
hassoa94434b2003-05-25 17:10:12 +0000987 if (config_mode)
paul55468c82005-03-14 20:19:01 +0000988 for (i = 0; i < vector_active (Vripng_passive_interface); i++)
hassoa94434b2003-05-25 17:10:12 +0000989 if ((ifname = vector_slot (Vripng_passive_interface, i)) != NULL)
990 vty_out (vty, " passive-interface %s%s", ifname, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000991
992 return 0;
993}
994
995/* RIPng enable on specified interface or matched network. */
996DEFUN (ripng_network,
997 ripng_network_cmd,
998 "network IF_OR_ADDR",
999 "RIPng enable on specified interface or network.\n"
1000 "Interface or address")
1001{
1002 int ret;
1003 struct prefix p;
1004
1005 ret = str2prefix (argv[0], &p);
1006
1007 /* Given string is IPv6 network or interface name. */
1008 if (ret)
1009 ret = ripng_enable_network_add (&p);
1010 else
1011 ret = ripng_enable_if_add (argv[0]);
1012
1013 if (ret < 0)
1014 {
1015 vty_out (vty, "There is same network configuration %s%s", argv[0],
1016 VTY_NEWLINE);
1017 return CMD_WARNING;
1018 }
1019
paul718e3742002-12-13 20:15:29 +00001020 return CMD_SUCCESS;
1021}
1022
1023/* RIPng enable on specified interface or matched network. */
1024DEFUN (no_ripng_network,
1025 no_ripng_network_cmd,
1026 "no network IF_OR_ADDR",
1027 NO_STR
1028 "RIPng enable on specified interface or network.\n"
1029 "Interface or address")
1030{
1031 int ret;
1032 struct prefix p;
1033
1034 ret = str2prefix (argv[0], &p);
1035
1036 /* Given string is interface name. */
1037 if (ret)
1038 ret = ripng_enable_network_delete (&p);
1039 else
1040 ret = ripng_enable_if_delete (argv[0]);
1041
1042 if (ret < 0)
1043 {
1044 vty_out (vty, "can't find network %s%s", argv[0],
1045 VTY_NEWLINE);
1046 return CMD_WARNING;
1047 }
1048
paul718e3742002-12-13 20:15:29 +00001049 return CMD_SUCCESS;
1050}
1051
hassoa94434b2003-05-25 17:10:12 +00001052DEFUN (ipv6_ripng_split_horizon,
1053 ipv6_ripng_split_horizon_cmd,
1054 "ipv6 ripng split-horizon",
1055 IPV6_STR
1056 "Routing Information Protocol\n"
1057 "Perform split horizon\n")
1058{
1059 struct interface *ifp;
1060 struct ripng_interface *ri;
1061
1062 ifp = vty->index;
1063 ri = ifp->info;
1064
1065 ri->split_horizon = RIPNG_SPLIT_HORIZON;
1066 return CMD_SUCCESS;
1067}
1068
1069DEFUN (ipv6_ripng_split_horizon_poisoned_reverse,
1070 ipv6_ripng_split_horizon_poisoned_reverse_cmd,
1071 "ipv6 ripng split-horizon poisoned-reverse",
1072 IPV6_STR
1073 "Routing Information Protocol\n"
1074 "Perform split horizon\n"
1075 "With poisoned-reverse\n")
1076{
1077 struct interface *ifp;
1078 struct ripng_interface *ri;
1079
1080 ifp = vty->index;
1081 ri = ifp->info;
1082
1083 ri->split_horizon = RIPNG_SPLIT_HORIZON_POISONED_REVERSE;
1084 return CMD_SUCCESS;
1085}
1086
1087DEFUN (no_ipv6_ripng_split_horizon,
1088 no_ipv6_ripng_split_horizon_cmd,
1089 "no ipv6 ripng split-horizon",
1090 NO_STR
1091 IPV6_STR
1092 "Routing Information Protocol\n"
1093 "Perform split horizon\n")
1094{
1095 struct interface *ifp;
1096 struct ripng_interface *ri;
1097
1098 ifp = vty->index;
1099 ri = ifp->info;
1100
1101 ri->split_horizon = RIPNG_NO_SPLIT_HORIZON;
1102 return CMD_SUCCESS;
1103}
1104
1105ALIAS (no_ipv6_ripng_split_horizon,
1106 no_ipv6_ripng_split_horizon_poisoned_reverse_cmd,
1107 "no ipv6 ripng split-horizon poisoned-reverse",
1108 NO_STR
1109 IPV6_STR
1110 "Routing Information Protocol\n"
1111 "Perform split horizon\n"
1112 "With poisoned-reverse\n")
1113
paul718e3742002-12-13 20:15:29 +00001114DEFUN (ripng_passive_interface,
1115 ripng_passive_interface_cmd,
1116 "passive-interface IFNAME",
1117 "Suppress routing updates on an interface\n"
1118 "Interface name\n")
1119{
1120 return ripng_passive_interface_set (vty, argv[0]);
1121}
1122
1123DEFUN (no_ripng_passive_interface,
1124 no_ripng_passive_interface_cmd,
1125 "no passive-interface IFNAME",
1126 NO_STR
1127 "Suppress routing updates on an interface\n"
1128 "Interface name\n")
1129{
1130 return ripng_passive_interface_unset (vty, argv[0]);
1131}
1132
1133struct ripng_interface *
1134ri_new ()
1135{
1136 struct ripng_interface *ri;
1137 ri = XCALLOC (MTYPE_IF, sizeof (struct ripng_interface));
hassoa94434b2003-05-25 17:10:12 +00001138
1139 /* Set default split-horizon behavior. If the interface is Frame
1140 Relay or SMDS is enabled, the default value for split-horizon is
1141 off. But currently Zebra does detect Frame Relay or SMDS
1142 interface. So all interface is set to split horizon. */
1143 ri->split_horizon_default = RIPNG_SPLIT_HORIZON;
1144 ri->split_horizon = ri->split_horizon_default;
1145
paul718e3742002-12-13 20:15:29 +00001146 return ri;
1147}
1148
1149int
1150ripng_if_new_hook (struct interface *ifp)
1151{
1152 ifp->info = ri_new ();
1153 return 0;
1154}
1155
hassoa94434b2003-05-25 17:10:12 +00001156/* Called when interface structure deleted. */
1157int
1158ripng_if_delete_hook (struct interface *ifp)
1159{
1160 XFREE (MTYPE_IF, ifp->info);
1161 ifp->info = NULL;
1162 return 0;
1163}
1164
paul718e3742002-12-13 20:15:29 +00001165/* Configuration write function for ripngd. */
1166int
1167interface_config_write (struct vty *vty)
1168{
hasso52dc7ee2004-09-23 19:18:23 +00001169 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001170 struct interface *ifp;
1171 struct ripng_interface *ri;
1172 int write = 0;
1173
1174 for (node = listhead (iflist); node; nextnode (node))
1175 {
1176 ifp = getdata (node);
1177 ri = ifp->info;
1178
hassoa94434b2003-05-25 17:10:12 +00001179 /* Do not display the interface if there is no
1180 * configuration about it.
1181 **/
1182 if ((!ifp->desc) &&
1183 (ri->split_horizon == ri->split_horizon_default))
1184 continue;
1185
paul718e3742002-12-13 20:15:29 +00001186 vty_out (vty, "interface %s%s", ifp->name,
1187 VTY_NEWLINE);
1188 if (ifp->desc)
1189 vty_out (vty, " description %s%s", ifp->desc,
1190 VTY_NEWLINE);
1191
hassoa94434b2003-05-25 17:10:12 +00001192 /* Split horizon. */
1193 if (ri->split_horizon != ri->split_horizon_default)
1194 {
1195 switch (ri->split_horizon) {
1196 case RIPNG_SPLIT_HORIZON:
1197 vty_out (vty, " ipv6 ripng split-horizon%s", VTY_NEWLINE);
1198 break;
1199 case RIPNG_SPLIT_HORIZON_POISONED_REVERSE:
1200 vty_out (vty, " ipv6 ripng split-horizon poisoned-reverse%s",
1201 VTY_NEWLINE);
1202 break;
1203 case RIPNG_NO_SPLIT_HORIZON:
1204 default:
1205 vty_out (vty, " no ipv6 ripng split-horizon%s", VTY_NEWLINE);
1206 break;
1207 }
1208 }
1209
paul718e3742002-12-13 20:15:29 +00001210 vty_out (vty, "!%s", VTY_NEWLINE);
1211
1212 write++;
1213 }
1214 return write;
1215}
1216
1217/* ripngd's interface node. */
1218struct cmd_node interface_node =
1219{
1220 INTERFACE_NODE,
1221 "%s(config-if)# ",
hassoa94434b2003-05-25 17:10:12 +00001222 1 /* VTYSH */
paul718e3742002-12-13 20:15:29 +00001223};
1224
1225/* Initialization of interface. */
1226void
1227ripng_if_init ()
1228{
1229 /* Interface initialize. */
1230 iflist = list_new ();
1231 if_add_hook (IF_NEW_HOOK, ripng_if_new_hook);
hassoa94434b2003-05-25 17:10:12 +00001232 if_add_hook (IF_DELETE_HOOK, ripng_if_delete_hook);
paul718e3742002-12-13 20:15:29 +00001233
1234 /* RIPng enable network init. */
1235 ripng_enable_network = route_table_init ();
1236
1237 /* RIPng enable interface init. */
1238 ripng_enable_if = vector_init (1);
1239
1240 /* RIPng passive interface. */
1241 Vripng_passive_interface = vector_init (1);
1242
1243 /* Install interface node. */
1244 install_node (&interface_node, interface_config_write);
hassoa94434b2003-05-25 17:10:12 +00001245
1246 /* Install commands. */
paul718e3742002-12-13 20:15:29 +00001247 install_element (CONFIG_NODE, &interface_cmd);
paul32d24632003-05-23 09:25:20 +00001248 install_element (CONFIG_NODE, &no_interface_cmd);
hassoa94434b2003-05-25 17:10:12 +00001249 install_default (INTERFACE_NODE);
paul718e3742002-12-13 20:15:29 +00001250 install_element (INTERFACE_NODE, &interface_desc_cmd);
1251 install_element (INTERFACE_NODE, &no_interface_desc_cmd);
1252
1253 install_element (RIPNG_NODE, &ripng_network_cmd);
1254 install_element (RIPNG_NODE, &no_ripng_network_cmd);
1255 install_element (RIPNG_NODE, &ripng_passive_interface_cmd);
1256 install_element (RIPNG_NODE, &no_ripng_passive_interface_cmd);
hassoa94434b2003-05-25 17:10:12 +00001257
1258 install_element (INTERFACE_NODE, &ipv6_ripng_split_horizon_cmd);
1259 install_element (INTERFACE_NODE, &ipv6_ripng_split_horizon_poisoned_reverse_cmd);
1260 install_element (INTERFACE_NODE, &no_ipv6_ripng_split_horizon_cmd);
1261 install_element (INTERFACE_NODE, &no_ipv6_ripng_split_horizon_poisoned_reverse_cmd);
paul718e3742002-12-13 20:15:29 +00001262}