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 along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
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_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_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
;
166 struct list
*list
= NULL
;
167 struct listnode
*listnode
= NULL
, *nextnode
= NULL
;
170 for (rp
= route_top (ripng
->table
); rp
; rp
= route_next (rp
))
171 if ((list
= rp
->info
) != NULL
)
172 for (ALL_LIST_ELEMENTS (list
, listnode
, nextnode
, rinfo
))
173 if (rinfo
->ifindex
== ifp
->ifindex
)
174 ripng_ecmp_delete (rinfo
);
180 if (IS_RIPNG_DEBUG_EVENT
)
181 zlog_debug ("turn off %s", ifp
->name
);
183 /* Leave from multicast group. */
184 ripng_multicast_leave (ifp
);
192 /* Inteface link up message processing. */
194 ripng_interface_up (int command
, struct zclient
*zclient
, zebra_size_t length
,
198 struct interface
*ifp
;
200 /* zebra_interface_state_read() updates interface structure in iflist. */
202 ifp
= zebra_interface_state_read (s
, vrf_id
);
207 if (IS_RIPNG_DEBUG_ZEBRA
)
208 zlog_debug ("interface up %s index %d flags %llx metric %d mtu %d",
209 ifp
->name
, ifp
->ifindex
, (unsigned long long)ifp
->flags
,
210 ifp
->metric
, ifp
->mtu6
);
212 /* Check if this interface is RIPng enabled or not. */
213 ripng_enable_apply (ifp
);
215 /* Check for a passive interface. */
216 ripng_passive_interface_apply (ifp
);
218 /* Apply distribute list to the all interface. */
219 ripng_distribute_update_interface (ifp
);
224 /* Inteface link down message processing. */
226 ripng_interface_down (int command
, struct zclient
*zclient
,
227 zebra_size_t length
, vrf_id_t vrf_id
)
230 struct interface
*ifp
;
232 /* zebra_interface_state_read() updates interface structure in iflist. */
234 ifp
= zebra_interface_state_read (s
, vrf_id
);
241 if (IS_RIPNG_DEBUG_ZEBRA
)
242 zlog_debug ("interface down %s index %d flags %#llx metric %d mtu %d",
243 ifp
->name
, ifp
->ifindex
,
244 (unsigned long long) ifp
->flags
, ifp
->metric
, ifp
->mtu6
);
249 /* Inteface addition message from zebra. */
251 ripng_interface_add (int command
, struct zclient
*zclient
, zebra_size_t length
,
254 struct interface
*ifp
;
256 ifp
= zebra_interface_add_read (zclient
->ibuf
, vrf_id
);
258 if (IS_RIPNG_DEBUG_ZEBRA
)
259 zlog_debug ("RIPng interface add %s index %d flags %#llx metric %d mtu %d",
260 ifp
->name
, ifp
->ifindex
, (unsigned long long) ifp
->flags
,
261 ifp
->metric
, ifp
->mtu6
);
263 /* Check is this interface is RIP enabled or not.*/
264 ripng_enable_apply (ifp
);
266 /* Apply distribute list to the interface. */
267 ripng_distribute_update_interface (ifp
);
269 /* Check interface routemap. */
270 ripng_if_rmap_update_interface (ifp
);
276 ripng_interface_delete (int command
, struct zclient
*zclient
,
277 zebra_size_t length
, vrf_id_t vrf_id
)
279 struct interface
*ifp
;
283 /* zebra_interface_state_read() updates interface structure in iflist */
284 ifp
= zebra_interface_state_read (s
, vrf_id
);
289 if (if_is_up (ifp
)) {
293 zlog_info("interface delete %s index %d flags %#llx metric %d mtu %d",
294 ifp
->name
, ifp
->ifindex
, (unsigned long long) ifp
->flags
,
295 ifp
->metric
, ifp
->mtu6
);
297 /* To support pseudo interface do not free interface structure. */
298 /* if_delete(ifp); */
299 ifp
->ifindex
= IFINDEX_DELETED
;
305 ripng_interface_clean (void)
307 struct listnode
*node
, *nnode
;
308 struct interface
*ifp
;
309 struct ripng_interface
*ri
;
311 for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT
), node
, nnode
, ifp
))
315 ri
->enable_network
= 0;
316 ri
->enable_interface
= 0;
321 thread_cancel (ri
->t_wakeup
);
328 ripng_interface_reset (void)
330 struct listnode
*node
;
331 struct interface
*ifp
;
332 struct ripng_interface
*ri
;
334 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT
), node
, ifp
))
338 ri
->enable_network
= 0;
339 ri
->enable_interface
= 0;
342 ri
->split_horizon
= RIPNG_NO_SPLIT_HORIZON
;
343 ri
->split_horizon_default
= RIPNG_NO_SPLIT_HORIZON
;
345 ri
->list
[RIPNG_FILTER_IN
] = NULL
;
346 ri
->list
[RIPNG_FILTER_OUT
] = NULL
;
348 ri
->prefix
[RIPNG_FILTER_IN
] = NULL
;
349 ri
->prefix
[RIPNG_FILTER_OUT
] = NULL
;
353 thread_cancel (ri
->t_wakeup
);
362 ripng_apply_address_add (struct connected
*ifc
) {
363 struct prefix_ipv6 address
;
369 if (! if_is_up(ifc
->ifp
))
374 memset (&address
, 0, sizeof (address
));
375 address
.family
= p
->family
;
376 address
.prefix
= p
->u
.prefix6
;
377 address
.prefixlen
= p
->prefixlen
;
378 apply_mask_ipv6(&address
);
380 /* Check if this interface is RIP enabled or not
381 or Check if this address's prefix is RIP enabled */
382 if ((ripng_enable_if_lookup(ifc
->ifp
->name
) >= 0) ||
383 (ripng_enable_network_lookup2(ifc
) >= 0))
384 ripng_redistribute_add(ZEBRA_ROUTE_CONNECT
, RIPNG_ROUTE_INTERFACE
,
385 &address
, ifc
->ifp
->ifindex
, NULL
, 0);
390 ripng_interface_address_add (int command
, struct zclient
*zclient
,
391 zebra_size_t length
, vrf_id_t vrf_id
)
396 c
= zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_ADD
,
397 zclient
->ibuf
, vrf_id
);
404 if (p
->family
== AF_INET6
)
406 struct ripng_interface
*ri
= c
->ifp
->info
;
408 if (IS_RIPNG_DEBUG_ZEBRA
)
409 zlog_debug ("RIPng connected address %s/%d add",
410 inet6_ntoa(p
->u
.prefix6
),
413 /* Check is this prefix needs to be redistributed. */
414 ripng_apply_address_add(c
);
416 /* Let's try once again whether the interface could be activated */
418 /* Check if this interface is RIP enabled or not.*/
419 ripng_enable_apply (c
->ifp
);
421 /* Apply distribute list to the interface. */
422 ripng_distribute_update_interface (c
->ifp
);
424 /* Check interface routemap. */
425 ripng_if_rmap_update_interface (c
->ifp
);
434 ripng_apply_address_del (struct connected
*ifc
) {
435 struct prefix_ipv6 address
;
441 if (! if_is_up(ifc
->ifp
))
446 memset (&address
, 0, sizeof (address
));
447 address
.family
= p
->family
;
448 address
.prefix
= p
->u
.prefix6
;
449 address
.prefixlen
= p
->prefixlen
;
450 apply_mask_ipv6(&address
);
452 ripng_redistribute_delete(ZEBRA_ROUTE_CONNECT
, RIPNG_ROUTE_INTERFACE
,
453 &address
, ifc
->ifp
->ifindex
);
457 ripng_interface_address_delete (int command
, struct zclient
*zclient
,
458 zebra_size_t length
, vrf_id_t vrf_id
)
460 struct connected
*ifc
;
462 char buf
[INET6_ADDRSTRLEN
];
464 ifc
= zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_DELETE
,
465 zclient
->ibuf
, vrf_id
);
471 if (p
->family
== AF_INET6
)
473 if (IS_RIPNG_DEBUG_ZEBRA
)
474 zlog_debug ("RIPng connected address %s/%d delete",
475 inet_ntop (AF_INET6
, &p
->u
.prefix6
, buf
,
479 /* Check wether this prefix needs to be removed. */
480 ripng_apply_address_del(ifc
);
482 connected_free (ifc
);
488 /* RIPng enable interface vector. */
489 vector ripng_enable_if
;
491 /* RIPng enable network table. */
492 struct route_table
*ripng_enable_network
;
494 /* Lookup RIPng enable network. */
495 /* Check wether the interface has at least a connected prefix that
496 * is within the ripng_enable_network table. */
498 ripng_enable_network_lookup_if (struct interface
*ifp
)
500 struct listnode
*node
;
501 struct connected
*connected
;
502 struct prefix_ipv6 address
;
504 for (ALL_LIST_ELEMENTS_RO (ifp
->connected
, node
, connected
))
507 struct route_node
*node
;
509 p
= connected
->address
;
511 if (p
->family
== AF_INET6
)
513 address
.family
= AF_INET6
;
514 address
.prefix
= p
->u
.prefix6
;
515 address
.prefixlen
= IPV6_MAX_BITLEN
;
517 node
= route_node_match (ripng_enable_network
,
518 (struct prefix
*)&address
);
521 route_unlock_node (node
);
529 /* Check wether connected is within the ripng_enable_network table. */
531 ripng_enable_network_lookup2 (struct connected
*connected
)
533 struct prefix_ipv6 address
;
536 p
= connected
->address
;
538 if (p
->family
== AF_INET6
) {
539 struct route_node
*node
;
541 address
.family
= p
->family
;
542 address
.prefix
= p
->u
.prefix6
;
543 address
.prefixlen
= IPV6_MAX_BITLEN
;
545 /* LPM on p->family, p->u.prefix6/IPV6_MAX_BITLEN within ripng_enable_network */
546 node
= route_node_match (ripng_enable_network
,
547 (struct prefix
*)&address
);
550 route_unlock_node (node
);
558 /* Add RIPng enable network. */
560 ripng_enable_network_add (struct prefix
*p
)
562 struct route_node
*node
;
564 node
= route_node_get (ripng_enable_network
, p
);
568 route_unlock_node (node
);
572 node
->info
= (void *)1;
574 /* XXX: One should find a better solution than a generic one */
575 ripng_enable_apply_all();
580 /* Delete RIPng enable network. */
582 ripng_enable_network_delete (struct prefix
*p
)
584 struct route_node
*node
;
586 node
= route_node_lookup (ripng_enable_network
, p
);
591 /* Unlock info lock. */
592 route_unlock_node (node
);
594 /* Unlock lookup lock. */
595 route_unlock_node (node
);
602 /* Lookup function. */
604 ripng_enable_if_lookup (const char *ifname
)
609 for (i
= 0; i
< vector_active (ripng_enable_if
); i
++)
610 if ((str
= vector_slot (ripng_enable_if
, i
)) != NULL
)
611 if (strcmp (str
, ifname
) == 0)
616 /* Add interface to ripng_enable_if. */
618 ripng_enable_if_add (const char *ifname
)
622 ret
= ripng_enable_if_lookup (ifname
);
626 vector_set (ripng_enable_if
, strdup (ifname
));
628 ripng_enable_apply_all();
633 /* Delete interface from ripng_enable_if. */
635 ripng_enable_if_delete (const char *ifname
)
640 index
= ripng_enable_if_lookup (ifname
);
644 str
= vector_slot (ripng_enable_if
, index
);
646 vector_unset (ripng_enable_if
, index
);
648 ripng_enable_apply_all();
653 /* Wake up interface. */
655 ripng_interface_wakeup (struct thread
*t
)
657 struct interface
*ifp
;
658 struct ripng_interface
*ri
;
661 ifp
= THREAD_ARG (t
);
666 /* Join to multicast group. */
667 if (ripng_multicast_join (ifp
) < 0) {
668 zlog_err ("multicast join failed, interface %s not running", ifp
->name
);
672 /* Set running flag. */
675 /* Send RIP request to the interface. */
682 ripng_connect_set (struct interface
*ifp
, int set
)
684 struct listnode
*node
, *nnode
;
685 struct connected
*connected
;
686 struct prefix_ipv6 address
;
688 for (ALL_LIST_ELEMENTS (ifp
->connected
, node
, nnode
, connected
))
691 p
= connected
->address
;
693 if (p
->family
!= AF_INET6
)
696 address
.family
= AF_INET6
;
697 address
.prefix
= p
->u
.prefix6
;
698 address
.prefixlen
= p
->prefixlen
;
699 apply_mask_ipv6 (&address
);
702 /* Check once more wether this prefix is within a "network IF_OR_PREF" one */
703 if ((ripng_enable_if_lookup(connected
->ifp
->name
) >= 0) ||
704 (ripng_enable_network_lookup2(connected
) >= 0))
705 ripng_redistribute_add (ZEBRA_ROUTE_CONNECT
, RIPNG_ROUTE_INTERFACE
,
706 &address
, connected
->ifp
->ifindex
, NULL
, 0);
708 ripng_redistribute_delete (ZEBRA_ROUTE_CONNECT
, RIPNG_ROUTE_INTERFACE
,
709 &address
, connected
->ifp
->ifindex
);
710 if (ripng_redistribute_check (ZEBRA_ROUTE_CONNECT
))
711 ripng_redistribute_add (ZEBRA_ROUTE_CONNECT
, RIPNG_ROUTE_REDISTRIBUTE
,
712 &address
, connected
->ifp
->ifindex
, NULL
, 0);
717 /* Check RIPng is enabed on this interface. */
719 ripng_enable_apply (struct interface
*ifp
)
722 struct ripng_interface
*ri
= NULL
;
724 /* Check interface. */
725 if (! if_is_up (ifp
))
730 /* Is this interface a candidate for RIPng ? */
731 ret
= ripng_enable_network_lookup_if (ifp
);
733 /* If the interface is matched. */
735 ri
->enable_network
= 1;
737 ri
->enable_network
= 0;
739 /* Check interface name configuration. */
740 ret
= ripng_enable_if_lookup (ifp
->name
);
742 ri
->enable_interface
= 1;
744 ri
->enable_interface
= 0;
746 /* any candidate interface MUST have a link-local IPv6 address */
747 if ((! ripng_if_ipv6_lladdress_check (ifp
)) &&
748 (ri
->enable_network
|| ri
->enable_interface
)) {
749 ri
->enable_network
= 0;
750 ri
->enable_interface
= 0;
751 zlog_warn("Interface %s does not have any link-local address",
755 /* Update running status of the interface. */
756 if (ri
->enable_network
|| ri
->enable_interface
)
759 if (IS_RIPNG_DEBUG_EVENT
)
760 zlog_debug ("RIPng turn on %s", ifp
->name
);
762 /* Add interface wake up thread. */
763 thread_add_timer(master
, ripng_interface_wakeup
, ifp
, 1,
766 ripng_connect_set (ifp
, 1);
773 /* Might as well clean up the route table as well
774 * ripng_if_down sets to 0 ri->running, and displays "turn off %s"
778 ripng_connect_set (ifp
, 0);
783 /* Set distribute list to all interfaces. */
785 ripng_enable_apply_all (void)
787 struct interface
*ifp
;
788 struct listnode
*node
;
790 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT
), node
, ifp
))
791 ripng_enable_apply (ifp
);
794 /* Clear all network and neighbor configuration */
796 ripng_clean_network ()
800 struct route_node
*rn
;
802 /* ripng_enable_network */
803 for (rn
= route_top (ripng_enable_network
); rn
; rn
= route_next (rn
))
806 route_unlock_node(rn
);
809 /* ripng_enable_if */
810 for (i
= 0; i
< vector_active (ripng_enable_if
); i
++)
811 if ((str
= vector_slot (ripng_enable_if
, i
)) != NULL
) {
813 vector_slot (ripng_enable_if
, i
) = NULL
;
817 /* Vector to store passive-interface name. */
818 vector Vripng_passive_interface
;
820 /* Utility function for looking up passive interface settings. */
822 ripng_passive_interface_lookup (const char *ifname
)
827 for (i
= 0; i
< vector_active (Vripng_passive_interface
); i
++)
828 if ((str
= vector_slot (Vripng_passive_interface
, i
)) != NULL
)
829 if (strcmp (str
, ifname
) == 0)
835 ripng_passive_interface_apply (struct interface
*ifp
)
838 struct ripng_interface
*ri
;
842 ret
= ripng_passive_interface_lookup (ifp
->name
);
850 ripng_passive_interface_apply_all (void)
852 struct interface
*ifp
;
853 struct listnode
*node
;
855 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT
), node
, ifp
))
856 ripng_passive_interface_apply (ifp
);
859 /* Passive interface. */
861 ripng_passive_interface_set (struct vty
*vty
, const char *ifname
)
863 if (ripng_passive_interface_lookup (ifname
) >= 0)
866 vector_set (Vripng_passive_interface
, strdup (ifname
));
868 ripng_passive_interface_apply_all ();
874 ripng_passive_interface_unset (struct vty
*vty
, const char *ifname
)
879 i
= ripng_passive_interface_lookup (ifname
);
883 str
= vector_slot (Vripng_passive_interface
, i
);
885 vector_unset (Vripng_passive_interface
, i
);
887 ripng_passive_interface_apply_all ();
892 /* Free all configured RIP passive-interface settings. */
894 ripng_passive_interface_clean (void)
899 for (i
= 0; i
< vector_active (Vripng_passive_interface
); i
++)
900 if ((str
= vector_slot (Vripng_passive_interface
, i
)) != NULL
)
903 vector_slot (Vripng_passive_interface
, i
) = NULL
;
905 ripng_passive_interface_apply_all ();
908 /* Write RIPng enable network and interface to the vty. */
910 ripng_network_write (struct vty
*vty
, int config_mode
)
914 struct route_node
*node
;
917 /* Write enable network. */
918 for (node
= route_top (ripng_enable_network
); node
; node
= route_next (node
))
921 struct prefix
*p
= &node
->p
;
922 vty_out (vty
, "%s%s/%d%s",
923 config_mode
? " network " : " ",
924 inet_ntop (p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
930 /* Write enable interface. */
931 for (i
= 0; i
< vector_active (ripng_enable_if
); i
++)
932 if ((ifname
= vector_slot (ripng_enable_if
, i
)) != NULL
)
933 vty_out (vty
, "%s%s%s",
934 config_mode
? " network " : " ",
938 /* Write passive interface. */
940 for (i
= 0; i
< vector_active (Vripng_passive_interface
); i
++)
941 if ((ifname
= vector_slot (Vripng_passive_interface
, i
)) != NULL
)
942 vty_out (vty
, " passive-interface %s%s", ifname
, VTY_NEWLINE
);
947 /* RIPng enable on specified interface or matched network. */
948 DEFUN (ripng_network
,
950 "network IF_OR_ADDR",
951 "RIPng enable on specified interface or network.\n"
952 "Interface or address")
954 int idx_if_or_addr
= 1;
958 ret
= str2prefix (argv
[idx_if_or_addr
]->arg
, &p
);
960 /* Given string is IPv6 network or interface name. */
962 ret
= ripng_enable_network_add (&p
);
964 ret
= ripng_enable_if_add (argv
[idx_if_or_addr
]->arg
);
968 vty_out (vty
, "There is same network configuration %s%s", argv
[idx_if_or_addr
]->arg
,
976 /* RIPng enable on specified interface or matched network. */
977 DEFUN (no_ripng_network
,
978 no_ripng_network_cmd
,
979 "no network IF_OR_ADDR",
981 "RIPng enable on specified interface or network.\n"
982 "Interface or address")
984 int idx_if_or_addr
= 2;
988 ret
= str2prefix (argv
[idx_if_or_addr
]->arg
, &p
);
990 /* Given string is interface name. */
992 ret
= ripng_enable_network_delete (&p
);
994 ret
= ripng_enable_if_delete (argv
[idx_if_or_addr
]->arg
);
998 vty_out (vty
, "can't find network %s%s", argv
[idx_if_or_addr
]->arg
,
1006 DEFUN (ipv6_ripng_split_horizon
,
1007 ipv6_ripng_split_horizon_cmd
,
1008 "ipv6 ripng split-horizon",
1010 "Routing Information Protocol\n"
1011 "Perform split horizon\n")
1013 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1014 struct ripng_interface
*ri
;
1018 ri
->split_horizon
= RIPNG_SPLIT_HORIZON
;
1022 DEFUN (ipv6_ripng_split_horizon_poisoned_reverse
,
1023 ipv6_ripng_split_horizon_poisoned_reverse_cmd
,
1024 "ipv6 ripng split-horizon poisoned-reverse",
1026 "Routing Information Protocol\n"
1027 "Perform split horizon\n"
1028 "With poisoned-reverse\n")
1030 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1031 struct ripng_interface
*ri
;
1035 ri
->split_horizon
= RIPNG_SPLIT_HORIZON_POISONED_REVERSE
;
1039 DEFUN (no_ipv6_ripng_split_horizon
,
1040 no_ipv6_ripng_split_horizon_cmd
,
1041 "no ipv6 ripng split-horizon [poisoned-reverse]",
1044 "Routing Information Protocol\n"
1045 "Perform split horizon\n"
1046 "With poisoned-reverse\n")
1048 VTY_DECLVAR_CONTEXT(interface
, ifp
);
1049 struct ripng_interface
*ri
;
1053 ri
->split_horizon
= RIPNG_NO_SPLIT_HORIZON
;
1057 DEFUN (ripng_passive_interface
,
1058 ripng_passive_interface_cmd
,
1059 "passive-interface IFNAME",
1060 "Suppress routing updates on an interface\n"
1064 return ripng_passive_interface_set (vty
, argv
[idx_ifname
]->arg
);
1067 DEFUN (no_ripng_passive_interface
,
1068 no_ripng_passive_interface_cmd
,
1069 "no passive-interface IFNAME",
1071 "Suppress routing updates on an interface\n"
1075 return ripng_passive_interface_unset (vty
, argv
[idx_ifname
]->arg
);
1078 static struct ripng_interface
*
1081 struct ripng_interface
*ri
;
1082 ri
= XCALLOC (MTYPE_IF
, sizeof (struct ripng_interface
));
1084 /* Set default split-horizon behavior. If the interface is Frame
1085 Relay or SMDS is enabled, the default value for split-horizon is
1086 off. But currently Zebra does detect Frame Relay or SMDS
1087 interface. So all interface is set to split horizon. */
1088 ri
->split_horizon_default
= RIPNG_SPLIT_HORIZON
;
1089 ri
->split_horizon
= ri
->split_horizon_default
;
1095 ripng_if_new_hook (struct interface
*ifp
)
1097 ifp
->info
= ri_new ();
1101 /* Called when interface structure deleted. */
1103 ripng_if_delete_hook (struct interface
*ifp
)
1105 XFREE (MTYPE_IF
, ifp
->info
);
1110 /* Configuration write function for ripngd. */
1112 interface_config_write (struct vty
*vty
)
1114 struct listnode
*node
;
1115 struct interface
*ifp
;
1116 struct ripng_interface
*ri
;
1119 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT
), node
, ifp
))
1123 /* Do not display the interface if there is no
1124 * configuration about it.
1127 (ri
->split_horizon
== ri
->split_horizon_default
))
1130 vty_out (vty
, "interface %s%s", ifp
->name
,
1133 vty_out (vty
, " description %s%s", ifp
->desc
,
1136 /* Split horizon. */
1137 if (ri
->split_horizon
!= ri
->split_horizon_default
)
1139 switch (ri
->split_horizon
) {
1140 case RIPNG_SPLIT_HORIZON
:
1141 vty_out (vty
, " ipv6 ripng split-horizon%s", VTY_NEWLINE
);
1143 case RIPNG_SPLIT_HORIZON_POISONED_REVERSE
:
1144 vty_out (vty
, " ipv6 ripng split-horizon poisoned-reverse%s",
1147 case RIPNG_NO_SPLIT_HORIZON
:
1149 vty_out (vty
, " no ipv6 ripng split-horizon%s", VTY_NEWLINE
);
1154 vty_out (vty
, "!%s", VTY_NEWLINE
);
1161 /* ripngd's interface node. */
1162 static struct cmd_node interface_node
=
1169 /* Initialization of interface. */
1173 /* Interface initialize. */
1174 if_add_hook (IF_NEW_HOOK
, ripng_if_new_hook
);
1175 if_add_hook (IF_DELETE_HOOK
, ripng_if_delete_hook
);
1177 /* RIPng enable network init. */
1178 ripng_enable_network
= route_table_init ();
1180 /* RIPng enable interface init. */
1181 ripng_enable_if
= vector_init (1);
1183 /* RIPng passive interface. */
1184 Vripng_passive_interface
= vector_init (1);
1186 /* Install interface node. */
1187 install_node (&interface_node
, interface_config_write
);
1190 install_element (RIPNG_NODE
, &ripng_network_cmd
);
1191 install_element (RIPNG_NODE
, &no_ripng_network_cmd
);
1192 install_element (RIPNG_NODE
, &ripng_passive_interface_cmd
);
1193 install_element (RIPNG_NODE
, &no_ripng_passive_interface_cmd
);
1195 install_element (INTERFACE_NODE
, &ipv6_ripng_split_horizon_cmd
);
1196 install_element (INTERFACE_NODE
, &ipv6_ripng_split_horizon_poisoned_reverse_cmd
);
1197 install_element (INTERFACE_NODE
, &no_ipv6_ripng_split_horizon_cmd
);