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
38 #include "ripngd/ripngd.h"
39 #include "ripngd/ripng_debug.h"
41 /* If RFC2133 definition is used. */
42 #ifndef IPV6_JOIN_GROUP
43 #define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
45 #ifndef IPV6_LEAVE_GROUP
46 #define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
49 /* Static utility function. */
50 static void ripng_enable_apply (struct interface
*);
51 static void ripng_passive_interface_apply (struct interface
*);
53 /* Join to the all rip routers multicast group. */
55 ripng_multicast_join (struct interface
*ifp
)
58 struct ipv6_mreq mreq
;
60 memset (&mreq
, 0, sizeof (mreq
));
61 inet_pton(AF_INET6
, RIPNG_GROUP
, &mreq
.ipv6mr_multiaddr
);
62 mreq
.ipv6mr_interface
= ifp
->ifindex
;
64 ret
= setsockopt (ripng
->sock
, IPPROTO_IPV6
, IPV6_JOIN_GROUP
,
65 (char *) &mreq
, sizeof (mreq
));
67 zlog_warn ("can't setsockopt IPV6_JOIN_GROUP: %s", strerror (errno
));
69 if (IS_RIPNG_DEBUG_EVENT
)
70 zlog_info ("RIPng %s join to all-rip-routers multicast group", ifp
->name
);
75 /* Leave from the all rip routers multicast group. */
77 ripng_multicast_leave (struct interface
*ifp
)
80 struct ipv6_mreq mreq
;
82 memset (&mreq
, 0, sizeof (mreq
));
83 inet_pton(AF_INET6
, RIPNG_GROUP
, &mreq
.ipv6mr_multiaddr
);
84 mreq
.ipv6mr_interface
= ifp
->ifindex
;
86 ret
= setsockopt (ripng
->sock
, IPPROTO_IPV6
, IPV6_LEAVE_GROUP
,
87 (char *) &mreq
, sizeof (mreq
));
89 zlog_warn ("can't setsockopt IPV6_LEAVE_GROUP: %s\n", strerror (errno
));
91 if (IS_RIPNG_DEBUG_EVENT
)
92 zlog_info ("RIPng %s leave from all-rip-routers multicast group",
98 /* Check max mtu size. */
100 ripng_check_max_mtu ()
103 struct interface
*ifp
;
107 for (node
= listhead (iflist
); node
; nextnode (node
))
109 ifp
= getdata (node
);
117 ripng_if_down (struct interface
*ifp
)
119 struct route_node
*rp
;
120 struct ripng_info
*rinfo
;
121 struct ripng_interface
*ri
;
125 for (rp
= route_top (ripng
->table
); rp
; rp
= route_next (rp
))
126 if ((rinfo
= rp
->info
) != NULL
)
128 /* Routes got through this interface. */
129 if (rinfo
->ifindex
== ifp
->ifindex
130 && rinfo
->type
== ZEBRA_ROUTE_RIPNG
131 && rinfo
->sub_type
== RIPNG_ROUTE_RTE
)
133 ripng_zebra_ipv6_delete ((struct prefix_ipv6
*) &rp
->p
,
137 RIPNG_TIMER_OFF (rinfo
->t_timeout
);
138 RIPNG_TIMER_OFF (rinfo
->t_garbage_collect
);
141 route_unlock_node (rp
);
143 ripng_info_free (rinfo
);
147 /* All redistributed routes got through this interface. */
148 if (rinfo
->ifindex
== ifp
->ifindex
)
149 ripng_redistribute_delete (rinfo
->type
, rinfo
->sub_type
,
150 (struct prefix_ipv6
*) &rp
->p
,
158 if (ripng
&& ri
->running
)
160 if (IS_RIPNG_DEBUG_EVENT
)
161 zlog_info ("turn off %s", ifp
->name
);
163 /* Leave from multicast group. */
164 ripng_multicast_leave (ifp
);
172 /* Inteface link up message processing. */
174 ripng_interface_up (int command
, struct zclient
*zclient
, zebra_size_t length
)
177 struct interface
*ifp
;
179 /* zebra_interface_state_read() updates interface structure in iflist. */
181 ifp
= zebra_interface_state_read (s
);
186 if (IS_RIPNG_DEBUG_ZEBRA
)
187 zlog_info ("interface up %s index %d flags %ld metric %d mtu %d",
188 ifp
->name
, ifp
->ifindex
, ifp
->flags
, ifp
->metric
, ifp
->mtu
);
190 /* Check if this interface is RIPng enabled or not. */
191 ripng_enable_apply (ifp
);
193 /* Check for a passive interface. */
194 ripng_passive_interface_apply (ifp
);
196 /* Apply distribute list to the all interface. */
197 ripng_distribute_update_interface (ifp
);
202 /* Inteface link down message processing. */
204 ripng_interface_down (int command
, struct zclient
*zclient
,
208 struct interface
*ifp
;
210 /* zebra_interface_state_read() updates interface structure in iflist. */
212 ifp
= zebra_interface_state_read (s
);
219 if (IS_RIPNG_DEBUG_ZEBRA
)
220 zlog_info ("interface down %s index %d flags %ld metric %d mtu %d",
221 ifp
->name
, ifp
->ifindex
, ifp
->flags
, ifp
->metric
, ifp
->mtu
);
226 /* Inteface addition message from zebra. */
228 ripng_interface_add (int command
, struct zclient
*zclient
, zebra_size_t length
)
230 struct interface
*ifp
;
232 ifp
= zebra_interface_add_read (zclient
->ibuf
);
234 if (IS_RIPNG_DEBUG_ZEBRA
)
235 zlog_info ("RIPng interface add %s index %d flags %ld metric %d mtu %d",
236 ifp
->name
, ifp
->ifindex
, ifp
->flags
, ifp
->metric
, ifp
->mtu
);
238 /* Check is this interface is RIP enabled or not.*/
239 ripng_enable_apply (ifp
);
241 /* Apply distribute list to the interface. */
242 ripng_distribute_update_interface (ifp
);
244 /* Check interface routemap. */
245 ripng_if_rmap_update_interface (ifp
);
251 ripng_interface_delete (int command
, struct zclient
*zclient
,
258 ripng_interface_address_add (int command
, struct zclient
*zclient
,
263 char buf
[INET6_ADDRSTRLEN
];
265 c
= zebra_interface_address_add_read (zclient
->ibuf
);
272 if (p
->family
== AF_INET6
)
274 if (IS_RIPNG_DEBUG_ZEBRA
)
275 zlog_info ("RIPng connected address %s/%d add",
276 inet_ntop (AF_INET6
, &p
->u
.prefix6
, buf
, INET6_ADDRSTRLEN
),
279 /* Check is this interface is RIP enabled or not.*/
280 ripng_enable_apply (c
->ifp
);
287 ripng_interface_address_delete (int command
, struct zclient
*zclient
,
290 struct connected
*ifc
;
292 char buf
[INET6_ADDRSTRLEN
];
294 ifc
= zebra_interface_address_delete_read (zclient
->ibuf
);
300 if (p
->family
== AF_INET6
)
302 if (IS_RIPNG_DEBUG_ZEBRA
)
303 zlog_info ("RIPng connected address %s/%d delete",
304 inet_ntop (AF_INET6
, &p
->u
.prefix6
, buf
,
308 /* Check is this interface is RIP enabled or not.*/
309 ripng_enable_apply (ifc
->ifp
);
311 connected_free (ifc
);
317 /* RIPng enable interface vector. */
318 vector ripng_enable_if
;
320 /* RIPng enable network table. */
321 struct route_table
*ripng_enable_network
;
323 /* Lookup RIPng enable network. */
325 ripng_enable_network_lookup (struct interface
*ifp
)
328 struct connected
*connected
;
330 for (listnode
= listhead (ifp
->connected
); listnode
; nextnode (listnode
))
331 if ((connected
= getdata (listnode
)) != NULL
)
334 struct route_node
*node
;
336 p
= connected
->address
;
338 if (p
->family
== AF_INET6
)
340 node
= route_node_match (ripng_enable_network
, p
);
343 route_unlock_node (node
);
351 /* Add RIPng enable network. */
353 ripng_enable_network_add (struct prefix
*p
)
355 struct route_node
*node
;
357 node
= route_node_get (ripng_enable_network
, p
);
361 route_unlock_node (node
);
365 node
->info
= "enabled";
370 /* Delete RIPng enable network. */
372 ripng_enable_network_delete (struct prefix
*p
)
374 struct route_node
*node
;
376 node
= route_node_lookup (ripng_enable_network
, p
);
381 /* Unlock info lock. */
382 route_unlock_node (node
);
384 /* Unlock lookup lock. */
385 route_unlock_node (node
);
392 /* Lookup function. */
394 ripng_enable_if_lookup (char *ifname
)
399 for (i
= 0; i
< vector_max (ripng_enable_if
); i
++)
400 if ((str
= vector_slot (ripng_enable_if
, i
)) != NULL
)
401 if (strcmp (str
, ifname
) == 0)
406 /* Add interface to ripng_enable_if. */
408 ripng_enable_if_add (char *ifname
)
412 ret
= ripng_enable_if_lookup (ifname
);
416 vector_set (ripng_enable_if
, strdup (ifname
));
421 /* Delete interface from ripng_enable_if. */
423 ripng_enable_if_delete (char *ifname
)
428 index
= ripng_enable_if_lookup (ifname
);
432 str
= vector_slot (ripng_enable_if
, index
);
434 vector_unset (ripng_enable_if
, index
);
439 /* Wake up interface. */
441 ripng_interface_wakeup (struct thread
*t
)
443 struct interface
*ifp
;
444 struct ripng_interface
*ri
;
447 ifp
= THREAD_ARG (t
);
452 /* Join to multicast group. */
453 ripng_multicast_join (ifp
);
455 /* Send RIP request to the interface. */
461 /* Check RIPng is enabed on this interface. */
463 ripng_enable_apply (struct interface
*ifp
)
466 struct ripng_interface
*ri
= NULL
;
468 /* Check interface. */
469 if (if_is_loopback (ifp
))
472 if (! if_is_up (ifp
))
477 /* Check network configuration. */
478 ret
= ripng_enable_network_lookup (ifp
);
480 /* If the interface is matched. */
482 ri
->enable_network
= 1;
484 ri
->enable_network
= 0;
486 /* Check interface name configuration. */
487 ret
= ripng_enable_if_lookup (ifp
->name
);
489 ri
->enable_interface
= 1;
491 ri
->enable_interface
= 0;
493 /* Update running status of the interface. */
494 if (ri
->enable_network
|| ri
->enable_interface
)
498 if (IS_RIPNG_DEBUG_EVENT
)
499 zlog_info ("RIPng turn on %s", ifp
->name
);
501 /* Add interface wake up thread. */
503 ri
->t_wakeup
= thread_add_timer (master
, ripng_interface_wakeup
,
506 /* Join to multicast group. */
507 ripng_multicast_join (ifp
);
509 /* Send RIP request to the interface. */
520 if (IS_RIPNG_DEBUG_EVENT
)
521 zlog_info ("RIPng turn off %s", ifp
->name
);
523 /* Leave from multicast group. */
524 ripng_multicast_leave (ifp
);
531 /* Set distribute list to all interfaces. */
533 ripng_enable_apply_all ()
535 struct interface
*ifp
;
538 for (node
= listhead (iflist
); node
; nextnode (node
))
540 ifp
= getdata (node
);
541 ripng_enable_apply (ifp
);
545 /* Vector to store passive-interface name. */
546 vector Vripng_passive_interface
;
548 /* Utility function for looking up passive interface settings. */
550 ripng_passive_interface_lookup (char *ifname
)
555 for (i
= 0; i
< vector_max (Vripng_passive_interface
); i
++)
556 if ((str
= vector_slot (Vripng_passive_interface
, i
)) != NULL
)
557 if (strcmp (str
, ifname
) == 0)
563 ripng_passive_interface_apply (struct interface
*ifp
)
566 struct ripng_interface
*ri
;
570 ret
= ripng_passive_interface_lookup (ifp
->name
);
578 ripng_passive_interface_apply_all (void)
580 struct interface
*ifp
;
583 for (node
= listhead (iflist
); node
; nextnode (node
))
585 ifp
= getdata (node
);
586 ripng_passive_interface_apply (ifp
);
590 /* Passive interface. */
592 ripng_passive_interface_set (struct vty
*vty
, char *ifname
)
594 if (ripng_passive_interface_lookup (ifname
) >= 0)
597 vector_set (Vripng_passive_interface
, strdup (ifname
));
599 ripng_passive_interface_apply_all ();
605 ripng_passive_interface_unset (struct vty
*vty
, char *ifname
)
610 i
= ripng_passive_interface_lookup (ifname
);
614 str
= vector_slot (Vripng_passive_interface
, i
);
616 vector_unset (Vripng_passive_interface
, i
);
618 ripng_passive_interface_apply_all ();
623 /* Free all configured RIP passive-interface settings. */
625 ripng_passive_interface_clean (void)
630 for (i
= 0; i
< vector_max (Vripng_passive_interface
); i
++)
631 if ((str
= vector_slot (Vripng_passive_interface
, i
)) != NULL
)
634 vector_slot (Vripng_passive_interface
, i
) = NULL
;
636 ripng_passive_interface_apply_all ();
639 /* Write RIPng enable network and interface to the vty. */
641 ripng_network_write (struct vty
*vty
)
646 struct route_node
*node
;
649 /* Write enable network. */
650 for (node
= route_top (ripng_enable_network
); node
; node
= route_next (node
))
653 struct prefix
*p
= &node
->p
;
654 vty_out (vty
, " network %s/%d%s",
655 inet_ntop (p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
661 /* Write enable interface. */
662 for (i
= 0; i
< vector_max (ripng_enable_if
); i
++)
663 if ((str
= vector_slot (ripng_enable_if
, i
)) != NULL
)
664 vty_out (vty
, " network %s%s", str
,
667 /* Write passive interface. */
668 for (i
= 0; i
< vector_max (Vripng_passive_interface
); i
++)
669 if ((ifname
= vector_slot (Vripng_passive_interface
, i
)) != NULL
)
670 vty_out (vty
, " passive-interface %s%s", ifname
, VTY_NEWLINE
);
675 /* RIPng enable on specified interface or matched network. */
676 DEFUN (ripng_network
,
678 "network IF_OR_ADDR",
679 "RIPng enable on specified interface or network.\n"
680 "Interface or address")
685 ret
= str2prefix (argv
[0], &p
);
687 /* Given string is IPv6 network or interface name. */
689 ret
= ripng_enable_network_add (&p
);
691 ret
= ripng_enable_if_add (argv
[0]);
695 vty_out (vty
, "There is same network configuration %s%s", argv
[0],
700 ripng_enable_apply_all ();
705 /* RIPng enable on specified interface or matched network. */
706 DEFUN (no_ripng_network
,
707 no_ripng_network_cmd
,
708 "no network IF_OR_ADDR",
710 "RIPng enable on specified interface or network.\n"
711 "Interface or address")
716 ret
= str2prefix (argv
[0], &p
);
718 /* Given string is interface name. */
720 ret
= ripng_enable_network_delete (&p
);
722 ret
= ripng_enable_if_delete (argv
[0]);
726 vty_out (vty
, "can't find network %s%s", argv
[0],
731 ripng_enable_apply_all ();
736 DEFUN (ripng_passive_interface
,
737 ripng_passive_interface_cmd
,
738 "passive-interface IFNAME",
739 "Suppress routing updates on an interface\n"
742 return ripng_passive_interface_set (vty
, argv
[0]);
745 DEFUN (no_ripng_passive_interface
,
746 no_ripng_passive_interface_cmd
,
747 "no passive-interface IFNAME",
749 "Suppress routing updates on an interface\n"
752 return ripng_passive_interface_unset (vty
, argv
[0]);
755 struct ripng_interface
*
758 struct ripng_interface
*ri
;
759 ri
= XCALLOC (MTYPE_IF
, sizeof (struct ripng_interface
));
764 ripng_if_new_hook (struct interface
*ifp
)
766 ifp
->info
= ri_new ();
770 /* Configuration write function for ripngd. */
772 interface_config_write (struct vty
*vty
)
775 struct interface
*ifp
;
776 struct ripng_interface
*ri
;
779 for (node
= listhead (iflist
); node
; nextnode (node
))
781 ifp
= getdata (node
);
784 vty_out (vty
, "interface %s%s", ifp
->name
,
787 vty_out (vty
, " description %s%s", ifp
->desc
,
790 vty_out (vty
, "!%s", VTY_NEWLINE
);
797 /* ripngd's interface node. */
798 struct cmd_node interface_node
=
804 /* Initialization of interface. */
808 /* Interface initialize. */
809 iflist
= list_new ();
810 if_add_hook (IF_NEW_HOOK
, ripng_if_new_hook
);
812 /* RIPng enable network init. */
813 ripng_enable_network
= route_table_init ();
815 /* RIPng enable interface init. */
816 ripng_enable_if
= vector_init (1);
818 /* RIPng passive interface. */
819 Vripng_passive_interface
= vector_init (1);
821 /* Install interface node. */
822 install_node (&interface_node
, interface_config_write
);
824 install_element (CONFIG_NODE
, &interface_cmd
);
825 install_element (INTERFACE_NODE
, &config_end_cmd
);
826 install_element (INTERFACE_NODE
, &config_exit_cmd
);
827 install_element (INTERFACE_NODE
, &config_help_cmd
);
828 install_element (INTERFACE_NODE
, &interface_desc_cmd
);
829 install_element (INTERFACE_NODE
, &no_interface_desc_cmd
);
831 install_element (RIPNG_NODE
, &ripng_network_cmd
);
832 install_element (RIPNG_NODE
, &no_ripng_network_cmd
);
833 install_element (RIPNG_NODE
, &ripng_passive_interface_cmd
);
834 install_element (RIPNG_NODE
, &no_ripng_passive_interface_cmd
);