2 * Interface related function for RIPng.
3 * Copyright (C) 1998 Kunihiro Ishiguro
5 * This file is part of GNU Zebra.
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
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.
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
39 #include "ripngd/ripngd.h"
40 #include "ripngd/ripng_debug.h"
42 /* If RFC2133 definition is used. */
43 #ifndef IPV6_JOIN_GROUP
44 #define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
46 #ifndef IPV6_LEAVE_GROUP
47 #define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
50 extern struct zebra_privs_t ripngd_privs
;
52 /* Static utility function. */
53 static void ripng_enable_apply (struct interface
*);
54 static void ripng_passive_interface_apply (struct interface
*);
55 static int ripng_enable_if_lookup (const char *);
56 static int ripng_enable_network_lookup2 (struct connected
*);
57 static void ripng_enable_apply_all (void);
59 /* Join to the all rip routers multicast group. */
61 ripng_multicast_join (struct interface
*ifp
)
64 struct ipv6_mreq mreq
;
67 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
;
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.
77 if (ripngd_privs
.change (ZPRIVS_RAISE
))
78 zlog_err ("ripng_multicast_join: could not raise privs");
80 ret
= setsockopt (ripng
->sock
, IPPROTO_IPV6
, IPV6_JOIN_GROUP
,
81 (char *) &mreq
, sizeof (mreq
));
84 if (ripngd_privs
.change (ZPRIVS_LOWER
))
85 zlog_err ("ripng_multicast_join: could not lower privs");
87 if (ret
< 0 && save_errno
== EADDRINUSE
)
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.
94 zlog_warn ("ripng join on %s EADDRINUSE (ignoring)\n", ifp
->name
);
95 return 0; /* not an error */
99 zlog_warn ("can't setsockopt IPV6_JOIN_GROUP: %s",
100 safe_strerror (save_errno
));
102 if (IS_RIPNG_DEBUG_EVENT
)
103 zlog_debug ("RIPng %s join to all-rip-routers multicast group", ifp
->name
);
111 /* Leave from the all rip routers multicast group. */
113 ripng_multicast_leave (struct interface
*ifp
)
116 struct ipv6_mreq mreq
;
118 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
;
123 ret
= setsockopt (ripng
->sock
, IPPROTO_IPV6
, IPV6_LEAVE_GROUP
,
124 (char *) &mreq
, sizeof (mreq
));
126 zlog_warn ("can't setsockopt IPV6_LEAVE_GROUP: %s\n", safe_strerror (errno
));
128 if (IS_RIPNG_DEBUG_EVENT
)
129 zlog_debug ("RIPng %s leave from all-rip-routers multicast group",
139 /* How many link local IPv6 address could be used on the interface ? */
141 ripng_if_ipv6_lladdress_check (struct interface
*ifp
)
144 struct connected
*connected
;
147 for (ALL_LIST_ELEMENTS_RO (ifp
->connected
, nn
, connected
))
150 p
= connected
->address
;
152 if ((p
->family
== AF_INET6
) &&
153 IN6_IS_ADDR_LINKLOCAL (&p
->u
.prefix6
))
161 ripng_if_down (struct interface
*ifp
)
163 struct route_node
*rp
;
164 struct ripng_info
*rinfo
;
165 struct ripng_interface
*ri
;
169 for (rp
= route_top (ripng
->table
); rp
; rp
= route_next (rp
))
170 if ((rinfo
= rp
->info
) != NULL
)
172 /* Routes got through this interface. */
173 if (rinfo
->ifindex
== ifp
->ifindex
174 && rinfo
->type
== ZEBRA_ROUTE_RIPNG
175 && rinfo
->sub_type
== RIPNG_ROUTE_RTE
)
177 ripng_zebra_ipv6_delete ((struct prefix_ipv6
*) &rp
->p
,
181 ripng_redistribute_delete (rinfo
->type
, rinfo
->sub_type
,
182 (struct prefix_ipv6
*)&rp
->p
,
187 /* All redistributed routes got through this interface,
188 * but the static and system ones are kept. */
189 if ((rinfo
->ifindex
== ifp
->ifindex
) &&
190 (rinfo
->type
!= ZEBRA_ROUTE_STATIC
) &&
191 (rinfo
->type
!= ZEBRA_ROUTE_SYSTEM
))
192 ripng_redistribute_delete (rinfo
->type
, rinfo
->sub_type
,
193 (struct prefix_ipv6
*) &rp
->p
,
203 if (IS_RIPNG_DEBUG_EVENT
)
204 zlog_debug ("turn off %s", ifp
->name
);
206 /* Leave from multicast group. */
207 ripng_multicast_leave (ifp
);
215 /* Inteface link up message processing. */
217 ripng_interface_up (int command
, struct zclient
*zclient
, zebra_size_t length
)
220 struct interface
*ifp
;
222 /* zebra_interface_state_read() updates interface structure in iflist. */
224 ifp
= zebra_interface_state_read (s
);
229 if (IS_RIPNG_DEBUG_ZEBRA
)
230 zlog_debug ("interface up %s index %d flags %llx metric %d mtu %d",
231 ifp
->name
, ifp
->ifindex
, (unsigned long long)ifp
->flags
,
232 ifp
->metric
, ifp
->mtu6
);
234 /* Check if this interface is RIPng enabled or not. */
235 ripng_enable_apply (ifp
);
237 /* Check for a passive interface. */
238 ripng_passive_interface_apply (ifp
);
240 /* Apply distribute list to the all interface. */
241 ripng_distribute_update_interface (ifp
);
246 /* Inteface link down message processing. */
248 ripng_interface_down (int command
, struct zclient
*zclient
,
252 struct interface
*ifp
;
254 /* zebra_interface_state_read() updates interface structure in iflist. */
256 ifp
= zebra_interface_state_read (s
);
263 if (IS_RIPNG_DEBUG_ZEBRA
)
264 zlog_debug ("interface down %s index %d flags %#llx metric %d mtu %d",
265 ifp
->name
, ifp
->ifindex
,
266 (unsigned long long) ifp
->flags
, ifp
->metric
, ifp
->mtu6
);
271 /* Inteface addition message from zebra. */
273 ripng_interface_add (int command
, struct zclient
*zclient
, zebra_size_t length
)
275 struct interface
*ifp
;
277 ifp
= zebra_interface_add_read (zclient
->ibuf
);
279 if (IS_RIPNG_DEBUG_ZEBRA
)
280 zlog_debug ("RIPng interface add %s index %d flags %#llx metric %d mtu %d",
281 ifp
->name
, ifp
->ifindex
, (unsigned long long) ifp
->flags
,
282 ifp
->metric
, ifp
->mtu6
);
284 /* Check is this interface is RIP enabled or not.*/
285 ripng_enable_apply (ifp
);
287 /* Apply distribute list to the interface. */
288 ripng_distribute_update_interface (ifp
);
290 /* Check interface routemap. */
291 ripng_if_rmap_update_interface (ifp
);
297 ripng_interface_delete (int command
, struct zclient
*zclient
,
300 struct interface
*ifp
;
304 /* zebra_interface_state_read() updates interface structure in iflist */
305 ifp
= zebra_interface_state_read(s
);
310 if (if_is_up (ifp
)) {
314 zlog_info("interface delete %s index %d flags %#llx metric %d mtu %d",
315 ifp
->name
, ifp
->ifindex
, (unsigned long long) ifp
->flags
,
316 ifp
->metric
, ifp
->mtu6
);
318 /* To support pseudo interface do not free interface structure. */
319 /* if_delete(ifp); */
320 ifp
->ifindex
= IFINDEX_INTERNAL
;
326 ripng_interface_clean (void)
328 struct listnode
*node
, *nnode
;
329 struct interface
*ifp
;
330 struct ripng_interface
*ri
;
332 for (ALL_LIST_ELEMENTS (iflist
, node
, nnode
, ifp
))
336 ri
->enable_network
= 0;
337 ri
->enable_interface
= 0;
342 thread_cancel (ri
->t_wakeup
);
349 ripng_interface_reset (void)
351 struct listnode
*node
;
352 struct interface
*ifp
;
353 struct ripng_interface
*ri
;
355 for (ALL_LIST_ELEMENTS_RO (iflist
, node
, ifp
))
359 ri
->enable_network
= 0;
360 ri
->enable_interface
= 0;
363 ri
->split_horizon
= RIPNG_NO_SPLIT_HORIZON
;
364 ri
->split_horizon_default
= RIPNG_NO_SPLIT_HORIZON
;
366 ri
->list
[RIPNG_FILTER_IN
] = NULL
;
367 ri
->list
[RIPNG_FILTER_OUT
] = NULL
;
369 ri
->prefix
[RIPNG_FILTER_IN
] = NULL
;
370 ri
->prefix
[RIPNG_FILTER_OUT
] = NULL
;
374 thread_cancel (ri
->t_wakeup
);
383 ripng_apply_address_add (struct connected
*ifc
) {
384 struct prefix_ipv6 address
;
390 if (! if_is_up(ifc
->ifp
))
395 memset (&address
, 0, sizeof (address
));
396 address
.family
= p
->family
;
397 address
.prefix
= p
->u
.prefix6
;
398 address
.prefixlen
= p
->prefixlen
;
399 apply_mask_ipv6(&address
);
401 /* Check if this interface is RIP enabled or not
402 or Check if this address's prefix is RIP enabled */
403 if ((ripng_enable_if_lookup(ifc
->ifp
->name
) >= 0) ||
404 (ripng_enable_network_lookup2(ifc
) >= 0))
405 ripng_redistribute_add(ZEBRA_ROUTE_CONNECT
, RIPNG_ROUTE_INTERFACE
,
406 &address
, ifc
->ifp
->ifindex
, NULL
);
411 ripng_interface_address_add (int command
, struct zclient
*zclient
,
417 c
= zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_ADD
,
425 if (p
->family
== AF_INET6
)
427 struct ripng_interface
*ri
= c
->ifp
->info
;
429 if (IS_RIPNG_DEBUG_ZEBRA
)
430 zlog_debug ("RIPng connected address %s/%d add",
431 inet6_ntoa(p
->u
.prefix6
),
434 /* Check is this prefix needs to be redistributed. */
435 ripng_apply_address_add(c
);
437 /* Let's try once again whether the interface could be activated */
439 /* Check if this interface is RIP enabled or not.*/
440 ripng_enable_apply (c
->ifp
);
442 /* Apply distribute list to the interface. */
443 ripng_distribute_update_interface (c
->ifp
);
445 /* Check interface routemap. */
446 ripng_if_rmap_update_interface (c
->ifp
);
455 ripng_apply_address_del (struct connected
*ifc
) {
456 struct prefix_ipv6 address
;
462 if (! if_is_up(ifc
->ifp
))
467 memset (&address
, 0, sizeof (address
));
468 address
.family
= p
->family
;
469 address
.prefix
= p
->u
.prefix6
;
470 address
.prefixlen
= p
->prefixlen
;
471 apply_mask_ipv6(&address
);
473 ripng_redistribute_delete(ZEBRA_ROUTE_CONNECT
, RIPNG_ROUTE_INTERFACE
,
474 &address
, ifc
->ifp
->ifindex
);
478 ripng_interface_address_delete (int command
, struct zclient
*zclient
,
481 struct connected
*ifc
;
483 char buf
[INET6_ADDRSTRLEN
];
485 ifc
= zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_DELETE
,
492 if (p
->family
== AF_INET6
)
494 if (IS_RIPNG_DEBUG_ZEBRA
)
495 zlog_debug ("RIPng connected address %s/%d delete",
496 inet_ntop (AF_INET6
, &p
->u
.prefix6
, buf
,
500 /* Check wether this prefix needs to be removed. */
501 ripng_apply_address_del(ifc
);
503 connected_free (ifc
);
509 /* RIPng enable interface vector. */
510 vector ripng_enable_if
;
512 /* RIPng enable network table. */
513 struct route_table
*ripng_enable_network
;
515 /* Lookup RIPng enable network. */
516 /* Check wether the interface has at least a connected prefix that
517 * is within the ripng_enable_network table. */
519 ripng_enable_network_lookup_if (struct interface
*ifp
)
521 struct listnode
*node
;
522 struct connected
*connected
;
523 struct prefix_ipv6 address
;
525 for (ALL_LIST_ELEMENTS_RO (ifp
->connected
, node
, connected
))
528 struct route_node
*node
;
530 p
= connected
->address
;
532 if (p
->family
== AF_INET6
)
534 address
.family
= AF_INET6
;
535 address
.prefix
= p
->u
.prefix6
;
536 address
.prefixlen
= IPV6_MAX_BITLEN
;
538 node
= route_node_match (ripng_enable_network
,
539 (struct prefix
*)&address
);
542 route_unlock_node (node
);
550 /* Check wether connected is within the ripng_enable_network table. */
552 ripng_enable_network_lookup2 (struct connected
*connected
)
554 struct prefix_ipv6 address
;
557 p
= connected
->address
;
559 if (p
->family
== AF_INET6
) {
560 struct route_node
*node
;
562 address
.family
= p
->family
;
563 address
.prefix
= p
->u
.prefix6
;
564 address
.prefixlen
= IPV6_MAX_BITLEN
;
566 /* LPM on p->family, p->u.prefix6/IPV6_MAX_BITLEN within ripng_enable_network */
567 node
= route_node_match (ripng_enable_network
,
568 (struct prefix
*)&address
);
571 route_unlock_node (node
);
579 /* Add RIPng enable network. */
581 ripng_enable_network_add (struct prefix
*p
)
583 struct route_node
*node
;
585 node
= route_node_get (ripng_enable_network
, p
);
589 route_unlock_node (node
);
593 node
->info
= (char *) "enabled";
595 /* XXX: One should find a better solution than a generic one */
596 ripng_enable_apply_all();
601 /* Delete RIPng enable network. */
603 ripng_enable_network_delete (struct prefix
*p
)
605 struct route_node
*node
;
607 node
= route_node_lookup (ripng_enable_network
, p
);
612 /* Unlock info lock. */
613 route_unlock_node (node
);
615 /* Unlock lookup lock. */
616 route_unlock_node (node
);
623 /* Lookup function. */
625 ripng_enable_if_lookup (const char *ifname
)
630 for (i
= 0; i
< vector_active (ripng_enable_if
); i
++)
631 if ((str
= vector_slot (ripng_enable_if
, i
)) != NULL
)
632 if (strcmp (str
, ifname
) == 0)
637 /* Add interface to ripng_enable_if. */
639 ripng_enable_if_add (const char *ifname
)
643 ret
= ripng_enable_if_lookup (ifname
);
647 vector_set (ripng_enable_if
, strdup (ifname
));
649 ripng_enable_apply_all();
654 /* Delete interface from ripng_enable_if. */
656 ripng_enable_if_delete (const char *ifname
)
661 index
= ripng_enable_if_lookup (ifname
);
665 str
= vector_slot (ripng_enable_if
, index
);
667 vector_unset (ripng_enable_if
, index
);
669 ripng_enable_apply_all();
674 /* Wake up interface. */
676 ripng_interface_wakeup (struct thread
*t
)
678 struct interface
*ifp
;
679 struct ripng_interface
*ri
;
682 ifp
= THREAD_ARG (t
);
687 /* Join to multicast group. */
688 if (ripng_multicast_join (ifp
) < 0) {
689 zlog_err ("multicast join failed, interface %s not running", ifp
->name
);
693 /* Set running flag. */
696 /* Send RIP request to the interface. */
703 ripng_connect_set (struct interface
*ifp
, int set
)
705 struct listnode
*node
, *nnode
;
706 struct connected
*connected
;
707 struct prefix_ipv6 address
;
709 for (ALL_LIST_ELEMENTS (ifp
->connected
, node
, nnode
, connected
))
712 p
= connected
->address
;
714 if (p
->family
!= AF_INET6
)
717 address
.family
= AF_INET6
;
718 address
.prefix
= p
->u
.prefix6
;
719 address
.prefixlen
= p
->prefixlen
;
720 apply_mask_ipv6 (&address
);
723 /* Check once more wether this prefix is within a "network IF_OR_PREF" one */
724 if ((ripng_enable_if_lookup(connected
->ifp
->name
) >= 0) ||
725 (ripng_enable_network_lookup2(connected
) >= 0))
726 ripng_redistribute_add (ZEBRA_ROUTE_CONNECT
, RIPNG_ROUTE_INTERFACE
,
727 &address
, connected
->ifp
->ifindex
, NULL
);
729 ripng_redistribute_delete (ZEBRA_ROUTE_CONNECT
, RIPNG_ROUTE_INTERFACE
,
730 &address
, connected
->ifp
->ifindex
);
731 if (ripng_redistribute_check (ZEBRA_ROUTE_CONNECT
))
732 ripng_redistribute_add (ZEBRA_ROUTE_CONNECT
, RIPNG_ROUTE_REDISTRIBUTE
,
733 &address
, connected
->ifp
->ifindex
, NULL
);
738 /* Check RIPng is enabed on this interface. */
740 ripng_enable_apply (struct interface
*ifp
)
743 struct ripng_interface
*ri
= NULL
;
745 /* Check interface. */
746 if (! if_is_up (ifp
))
751 /* Is this interface a candidate for RIPng ? */
752 ret
= ripng_enable_network_lookup_if (ifp
);
754 /* If the interface is matched. */
756 ri
->enable_network
= 1;
758 ri
->enable_network
= 0;
760 /* Check interface name configuration. */
761 ret
= ripng_enable_if_lookup (ifp
->name
);
763 ri
->enable_interface
= 1;
765 ri
->enable_interface
= 0;
767 /* any candidate interface MUST have a link-local IPv6 address */
768 if ((! ripng_if_ipv6_lladdress_check (ifp
)) &&
769 (ri
->enable_network
|| ri
->enable_interface
)) {
770 ri
->enable_network
= 0;
771 ri
->enable_interface
= 0;
772 zlog_warn("Interface %s does not have any link-local address",
776 /* Update running status of the interface. */
777 if (ri
->enable_network
|| ri
->enable_interface
)
780 if (IS_RIPNG_DEBUG_EVENT
)
781 zlog_debug ("RIPng turn on %s", ifp
->name
);
783 /* Add interface wake up thread. */
785 ri
->t_wakeup
= thread_add_timer (master
, ripng_interface_wakeup
,
788 ripng_connect_set (ifp
, 1);
795 /* Might as well clean up the route table as well
796 * ripng_if_down sets to 0 ri->running, and displays "turn off %s"
800 ripng_connect_set (ifp
, 0);
805 /* Set distribute list to all interfaces. */
807 ripng_enable_apply_all (void)
809 struct interface
*ifp
;
810 struct listnode
*node
;
812 for (ALL_LIST_ELEMENTS_RO (iflist
, node
, ifp
))
813 ripng_enable_apply (ifp
);
816 /* Clear all network and neighbor configuration */
818 ripng_clean_network ()
822 struct route_node
*rn
;
824 /* ripng_enable_network */
825 for (rn
= route_top (ripng_enable_network
); rn
; rn
= route_next (rn
))
828 route_unlock_node(rn
);
831 /* ripng_enable_if */
832 for (i
= 0; i
< vector_active (ripng_enable_if
); i
++)
833 if ((str
= vector_slot (ripng_enable_if
, i
)) != NULL
) {
835 vector_slot (ripng_enable_if
, i
) = NULL
;
839 /* Vector to store passive-interface name. */
840 vector Vripng_passive_interface
;
842 /* Utility function for looking up passive interface settings. */
844 ripng_passive_interface_lookup (const char *ifname
)
849 for (i
= 0; i
< vector_active (Vripng_passive_interface
); i
++)
850 if ((str
= vector_slot (Vripng_passive_interface
, i
)) != NULL
)
851 if (strcmp (str
, ifname
) == 0)
857 ripng_passive_interface_apply (struct interface
*ifp
)
860 struct ripng_interface
*ri
;
864 ret
= ripng_passive_interface_lookup (ifp
->name
);
872 ripng_passive_interface_apply_all (void)
874 struct interface
*ifp
;
875 struct listnode
*node
;
877 for (ALL_LIST_ELEMENTS_RO (iflist
, node
, ifp
))
878 ripng_passive_interface_apply (ifp
);
881 /* Passive interface. */
883 ripng_passive_interface_set (struct vty
*vty
, const char *ifname
)
885 if (ripng_passive_interface_lookup (ifname
) >= 0)
888 vector_set (Vripng_passive_interface
, strdup (ifname
));
890 ripng_passive_interface_apply_all ();
896 ripng_passive_interface_unset (struct vty
*vty
, const char *ifname
)
901 i
= ripng_passive_interface_lookup (ifname
);
905 str
= vector_slot (Vripng_passive_interface
, i
);
907 vector_unset (Vripng_passive_interface
, i
);
909 ripng_passive_interface_apply_all ();
914 /* Free all configured RIP passive-interface settings. */
916 ripng_passive_interface_clean (void)
921 for (i
= 0; i
< vector_active (Vripng_passive_interface
); i
++)
922 if ((str
= vector_slot (Vripng_passive_interface
, i
)) != NULL
)
925 vector_slot (Vripng_passive_interface
, i
) = NULL
;
927 ripng_passive_interface_apply_all ();
930 /* Write RIPng enable network and interface to the vty. */
932 ripng_network_write (struct vty
*vty
, int config_mode
)
936 struct route_node
*node
;
939 /* Write enable network. */
940 for (node
= route_top (ripng_enable_network
); node
; node
= route_next (node
))
943 struct prefix
*p
= &node
->p
;
944 vty_out (vty
, "%s%s/%d%s",
945 config_mode
? " network " : " ",
946 inet_ntop (p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
952 /* Write enable interface. */
953 for (i
= 0; i
< vector_active (ripng_enable_if
); i
++)
954 if ((ifname
= vector_slot (ripng_enable_if
, i
)) != NULL
)
955 vty_out (vty
, "%s%s%s",
956 config_mode
? " network " : " ",
960 /* Write passive interface. */
962 for (i
= 0; i
< vector_active (Vripng_passive_interface
); i
++)
963 if ((ifname
= vector_slot (Vripng_passive_interface
, i
)) != NULL
)
964 vty_out (vty
, " passive-interface %s%s", ifname
, VTY_NEWLINE
);
969 /* RIPng enable on specified interface or matched network. */
970 DEFUN (ripng_network
,
972 "network IF_OR_ADDR",
973 "RIPng enable on specified interface or network.\n"
974 "Interface or address")
979 ret
= str2prefix (argv
[0], &p
);
981 /* Given string is IPv6 network or interface name. */
983 ret
= ripng_enable_network_add (&p
);
985 ret
= ripng_enable_if_add (argv
[0]);
989 vty_out (vty
, "There is same network configuration %s%s", argv
[0],
997 /* RIPng enable on specified interface or matched network. */
998 DEFUN (no_ripng_network
,
999 no_ripng_network_cmd
,
1000 "no network IF_OR_ADDR",
1002 "RIPng enable on specified interface or network.\n"
1003 "Interface or address")
1008 ret
= str2prefix (argv
[0], &p
);
1010 /* Given string is interface name. */
1012 ret
= ripng_enable_network_delete (&p
);
1014 ret
= ripng_enable_if_delete (argv
[0]);
1018 vty_out (vty
, "can't find network %s%s", argv
[0],
1026 DEFUN (ipv6_ripng_split_horizon
,
1027 ipv6_ripng_split_horizon_cmd
,
1028 "ipv6 ripng split-horizon",
1030 "Routing Information Protocol\n"
1031 "Perform split horizon\n")
1033 struct interface
*ifp
;
1034 struct ripng_interface
*ri
;
1039 ri
->split_horizon
= RIPNG_SPLIT_HORIZON
;
1043 DEFUN (ipv6_ripng_split_horizon_poisoned_reverse
,
1044 ipv6_ripng_split_horizon_poisoned_reverse_cmd
,
1045 "ipv6 ripng split-horizon poisoned-reverse",
1047 "Routing Information Protocol\n"
1048 "Perform split horizon\n"
1049 "With poisoned-reverse\n")
1051 struct interface
*ifp
;
1052 struct ripng_interface
*ri
;
1057 ri
->split_horizon
= RIPNG_SPLIT_HORIZON_POISONED_REVERSE
;
1061 DEFUN (no_ipv6_ripng_split_horizon
,
1062 no_ipv6_ripng_split_horizon_cmd
,
1063 "no ipv6 ripng split-horizon",
1066 "Routing Information Protocol\n"
1067 "Perform split horizon\n")
1069 struct interface
*ifp
;
1070 struct ripng_interface
*ri
;
1075 ri
->split_horizon
= RIPNG_NO_SPLIT_HORIZON
;
1079 ALIAS (no_ipv6_ripng_split_horizon
,
1080 no_ipv6_ripng_split_horizon_poisoned_reverse_cmd
,
1081 "no ipv6 ripng split-horizon poisoned-reverse",
1084 "Routing Information Protocol\n"
1085 "Perform split horizon\n"
1086 "With poisoned-reverse\n")
1088 DEFUN (ripng_passive_interface
,
1089 ripng_passive_interface_cmd
,
1090 "passive-interface IFNAME",
1091 "Suppress routing updates on an interface\n"
1094 return ripng_passive_interface_set (vty
, argv
[0]);
1097 DEFUN (no_ripng_passive_interface
,
1098 no_ripng_passive_interface_cmd
,
1099 "no passive-interface IFNAME",
1101 "Suppress routing updates on an interface\n"
1104 return ripng_passive_interface_unset (vty
, argv
[0]);
1107 static struct ripng_interface
*
1110 struct ripng_interface
*ri
;
1111 ri
= XCALLOC (MTYPE_IF
, sizeof (struct ripng_interface
));
1113 /* Set default split-horizon behavior. If the interface is Frame
1114 Relay or SMDS is enabled, the default value for split-horizon is
1115 off. But currently Zebra does detect Frame Relay or SMDS
1116 interface. So all interface is set to split horizon. */
1117 ri
->split_horizon_default
= RIPNG_SPLIT_HORIZON
;
1118 ri
->split_horizon
= ri
->split_horizon_default
;
1124 ripng_if_new_hook (struct interface
*ifp
)
1126 ifp
->info
= ri_new ();
1130 /* Called when interface structure deleted. */
1132 ripng_if_delete_hook (struct interface
*ifp
)
1134 XFREE (MTYPE_IF
, ifp
->info
);
1139 /* Configuration write function for ripngd. */
1141 interface_config_write (struct vty
*vty
)
1143 struct listnode
*node
;
1144 struct interface
*ifp
;
1145 struct ripng_interface
*ri
;
1148 for (ALL_LIST_ELEMENTS_RO (iflist
, node
, ifp
))
1152 /* Do not display the interface if there is no
1153 * configuration about it.
1156 (ri
->split_horizon
== ri
->split_horizon_default
))
1159 vty_out (vty
, "interface %s%s", ifp
->name
,
1162 vty_out (vty
, " description %s%s", ifp
->desc
,
1165 /* Split horizon. */
1166 if (ri
->split_horizon
!= ri
->split_horizon_default
)
1168 switch (ri
->split_horizon
) {
1169 case RIPNG_SPLIT_HORIZON
:
1170 vty_out (vty
, " ipv6 ripng split-horizon%s", VTY_NEWLINE
);
1172 case RIPNG_SPLIT_HORIZON_POISONED_REVERSE
:
1173 vty_out (vty
, " ipv6 ripng split-horizon poisoned-reverse%s",
1176 case RIPNG_NO_SPLIT_HORIZON
:
1178 vty_out (vty
, " no ipv6 ripng split-horizon%s", VTY_NEWLINE
);
1183 vty_out (vty
, "!%s", VTY_NEWLINE
);
1190 /* ripngd's interface node. */
1191 static struct cmd_node interface_node
=
1198 /* Initialization of interface. */
1202 /* Interface initialize. */
1203 iflist
= list_new ();
1204 if_add_hook (IF_NEW_HOOK
, ripng_if_new_hook
);
1205 if_add_hook (IF_DELETE_HOOK
, ripng_if_delete_hook
);
1207 /* RIPng enable network init. */
1208 ripng_enable_network
= route_table_init ();
1210 /* RIPng enable interface init. */
1211 ripng_enable_if
= vector_init (1);
1213 /* RIPng passive interface. */
1214 Vripng_passive_interface
= vector_init (1);
1216 /* Install interface node. */
1217 install_node (&interface_node
, interface_config_write
);
1219 /* Install commands. */
1220 install_element (CONFIG_NODE
, &interface_cmd
);
1221 install_element (CONFIG_NODE
, &no_interface_cmd
);
1222 install_default (INTERFACE_NODE
);
1223 install_element (INTERFACE_NODE
, &interface_desc_cmd
);
1224 install_element (INTERFACE_NODE
, &no_interface_desc_cmd
);
1226 install_element (RIPNG_NODE
, &ripng_network_cmd
);
1227 install_element (RIPNG_NODE
, &no_ripng_network_cmd
);
1228 install_element (RIPNG_NODE
, &ripng_passive_interface_cmd
);
1229 install_element (RIPNG_NODE
, &no_ripng_passive_interface_cmd
);
1231 install_element (INTERFACE_NODE
, &ipv6_ripng_split_horizon_cmd
);
1232 install_element (INTERFACE_NODE
, &ipv6_ripng_split_horizon_poisoned_reverse_cmd
);
1233 install_element (INTERFACE_NODE
, &no_ipv6_ripng_split_horizon_cmd
);
1234 install_element (INTERFACE_NODE
, &no_ipv6_ripng_split_horizon_poisoned_reverse_cmd
);