usbmodeswitch: Updated to v.1.2.6 from shibby's branch.
[tomato.git] / release / src / router / zebra / ripngd / ripng_interface.c
blob91554f914a241db9da6beead8fee03e38f3f8171
1 /*
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
10 * later version.
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
20 * 02111-1307, USA.
23 #include <zebra.h>
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"
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
44 #endif
45 #ifndef IPV6_LEAVE_GROUP
46 #define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
47 #endif
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. */
54 int
55 ripng_multicast_join (struct interface *ifp)
57 int ret;
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));
66 if (ret < 0)
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);
72 return ret;
75 /* Leave from the all rip routers multicast group. */
76 int
77 ripng_multicast_leave (struct interface *ifp)
79 int ret;
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));
88 if (ret < 0)
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",
93 ifp->name);
95 return ret;
98 /* Check max mtu size. */
99 int
100 ripng_check_max_mtu ()
102 listnode node;
103 struct interface *ifp;
104 int mtu;
106 mtu = 0;
107 for (node = listhead (iflist); node; nextnode (node))
109 ifp = getdata (node);
110 if (mtu < ifp->mtu)
111 mtu = ifp->mtu;
113 return mtu;
117 ripng_if_down (struct interface *ifp)
119 struct route_node *rp;
120 struct ripng_info *rinfo;
121 struct ripng_interface *ri;
123 if (ripng)
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,
134 &rinfo->nexthop,
135 rinfo->ifindex);
137 RIPNG_TIMER_OFF (rinfo->t_timeout);
138 RIPNG_TIMER_OFF (rinfo->t_garbage_collect);
140 rp->info = NULL;
141 route_unlock_node (rp);
143 ripng_info_free (rinfo);
145 else
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,
151 rinfo->ifindex);
156 ri = ifp->info;
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);
166 ri->running = 0;
169 return 0;
172 /* Inteface link up message processing. */
174 ripng_interface_up (int command, struct zclient *zclient, zebra_size_t length)
176 struct stream *s;
177 struct interface *ifp;
179 /* zebra_interface_state_read() updates interface structure in iflist. */
180 s = zclient->ibuf;
181 ifp = zebra_interface_state_read (s);
183 if (ifp == NULL)
184 return 0;
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);
199 return 0;
202 /* Inteface link down message processing. */
204 ripng_interface_down (int command, struct zclient *zclient,
205 zebra_size_t length)
207 struct stream *s;
208 struct interface *ifp;
210 /* zebra_interface_state_read() updates interface structure in iflist. */
211 s = zclient->ibuf;
212 ifp = zebra_interface_state_read (s);
214 if (ifp == NULL)
215 return 0;
217 ripng_if_down (ifp);
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);
223 return 0;
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);
247 return 0;
251 ripng_interface_delete (int command, struct zclient *zclient,
252 zebra_size_t length)
254 return 0;
258 ripng_interface_address_add (int command, struct zclient *zclient,
259 zebra_size_t length)
261 struct connected *c;
262 struct prefix *p;
263 char buf[INET6_ADDRSTRLEN];
265 c = zebra_interface_address_add_read (zclient->ibuf);
267 if (c == NULL)
268 return 0;
270 p = c->address;
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),
277 p->prefixlen);
279 /* Check is this interface is RIP enabled or not.*/
280 ripng_enable_apply (c->ifp);
283 return 0;
287 ripng_interface_address_delete (int command, struct zclient *zclient,
288 zebra_size_t length)
290 struct connected *ifc;
291 struct prefix *p;
292 char buf[INET6_ADDRSTRLEN];
294 ifc = zebra_interface_address_delete_read (zclient->ibuf);
296 if (ifc)
298 p = ifc->address;
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,
305 INET6_ADDRSTRLEN),
306 p->prefixlen);
308 /* Check is this interface is RIP enabled or not.*/
309 ripng_enable_apply (ifc->ifp);
311 connected_free (ifc);
314 return 0;
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)
327 listnode listnode;
328 struct connected *connected;
330 for (listnode = listhead (ifp->connected); listnode; nextnode (listnode))
331 if ((connected = getdata (listnode)) != NULL)
333 struct prefix *p;
334 struct route_node *node;
336 p = connected->address;
338 if (p->family == AF_INET6)
340 node = route_node_match (ripng_enable_network, p);
341 if (node)
343 route_unlock_node (node);
344 return 1;
348 return -1;
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);
359 if (node->info)
361 route_unlock_node (node);
362 return -1;
364 else
365 node->info = "enabled";
367 return 1;
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);
377 if (node)
379 node->info = NULL;
381 /* Unlock info lock. */
382 route_unlock_node (node);
384 /* Unlock lookup lock. */
385 route_unlock_node (node);
387 return 1;
389 return -1;
392 /* Lookup function. */
394 ripng_enable_if_lookup (char *ifname)
396 int i;
397 char *str;
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)
402 return i;
403 return -1;
406 /* Add interface to ripng_enable_if. */
408 ripng_enable_if_add (char *ifname)
410 int ret;
412 ret = ripng_enable_if_lookup (ifname);
413 if (ret >= 0)
414 return -1;
416 vector_set (ripng_enable_if, strdup (ifname));
418 return 1;
421 /* Delete interface from ripng_enable_if. */
423 ripng_enable_if_delete (char *ifname)
425 int index;
426 char *str;
428 index = ripng_enable_if_lookup (ifname);
429 if (index < 0)
430 return -1;
432 str = vector_slot (ripng_enable_if, index);
433 free (str);
434 vector_unset (ripng_enable_if, index);
436 return 1;
439 /* Wake up interface. */
441 ripng_interface_wakeup (struct thread *t)
443 struct interface *ifp;
444 struct ripng_interface *ri;
446 /* Get interface. */
447 ifp = THREAD_ARG (t);
449 ri = ifp->info;
450 ri->t_wakeup = NULL;
452 /* Join to multicast group. */
453 ripng_multicast_join (ifp);
455 /* Send RIP request to the interface. */
456 ripng_request (ifp);
458 return 0;
461 /* Check RIPng is enabed on this interface. */
462 void
463 ripng_enable_apply (struct interface *ifp)
465 int ret;
466 struct ripng_interface *ri = NULL;
468 /* Check interface. */
469 if (if_is_loopback (ifp))
470 return;
472 if (! if_is_up (ifp))
473 return;
475 ri = ifp->info;
477 /* Check network configuration. */
478 ret = ripng_enable_network_lookup (ifp);
480 /* If the interface is matched. */
481 if (ret > 0)
482 ri->enable_network = 1;
483 else
484 ri->enable_network = 0;
486 /* Check interface name configuration. */
487 ret = ripng_enable_if_lookup (ifp->name);
488 if (ret >= 0)
489 ri->enable_interface = 1;
490 else
491 ri->enable_interface = 0;
493 /* Update running status of the interface. */
494 if (ri->enable_network || ri->enable_interface)
496 if (! ri->running)
498 if (IS_RIPNG_DEBUG_EVENT)
499 zlog_info ("RIPng turn on %s", ifp->name);
501 /* Add interface wake up thread. */
502 if (! ri->t_wakeup)
503 ri->t_wakeup = thread_add_timer (master, ripng_interface_wakeup,
504 ifp, 1);
505 ri->running = 1;
508 else
510 if (ri->running)
512 if (IS_RIPNG_DEBUG_EVENT)
513 zlog_info ("RIPng turn off %s", ifp->name);
515 /* Leave from multicast group. */
516 ripng_multicast_leave (ifp);
518 ri->running = 0;
523 /* Set distribute list to all interfaces. */
524 static void
525 ripng_enable_apply_all ()
527 struct interface *ifp;
528 listnode node;
530 for (node = listhead (iflist); node; nextnode (node))
532 ifp = getdata (node);
533 ripng_enable_apply (ifp);
537 /* Vector to store passive-interface name. */
538 vector Vripng_passive_interface;
540 /* Utility function for looking up passive interface settings. */
542 ripng_passive_interface_lookup (char *ifname)
544 int i;
545 char *str;
547 for (i = 0; i < vector_max (Vripng_passive_interface); i++)
548 if ((str = vector_slot (Vripng_passive_interface, i)) != NULL)
549 if (strcmp (str, ifname) == 0)
550 return i;
551 return -1;
554 void
555 ripng_passive_interface_apply (struct interface *ifp)
557 int ret;
558 struct ripng_interface *ri;
560 ri = ifp->info;
562 ret = ripng_passive_interface_lookup (ifp->name);
563 if (ret < 0)
564 ri->passive = 0;
565 else
566 ri->passive = 1;
569 void
570 ripng_passive_interface_apply_all (void)
572 struct interface *ifp;
573 listnode node;
575 for (node = listhead (iflist); node; nextnode (node))
577 ifp = getdata (node);
578 ripng_passive_interface_apply (ifp);
582 /* Passive interface. */
584 ripng_passive_interface_set (struct vty *vty, char *ifname)
586 if (ripng_passive_interface_lookup (ifname) >= 0)
587 return CMD_WARNING;
589 vector_set (Vripng_passive_interface, strdup (ifname));
591 ripng_passive_interface_apply_all ();
593 return CMD_SUCCESS;
597 ripng_passive_interface_unset (struct vty *vty, char *ifname)
599 int i;
600 char *str;
602 i = ripng_passive_interface_lookup (ifname);
603 if (i < 0)
604 return CMD_WARNING;
606 str = vector_slot (Vripng_passive_interface, i);
607 free (str);
608 vector_unset (Vripng_passive_interface, i);
610 ripng_passive_interface_apply_all ();
612 return CMD_SUCCESS;
615 /* Free all configured RIP passive-interface settings. */
616 void
617 ripng_passive_interface_clean (void)
619 int i;
620 char *str;
622 for (i = 0; i < vector_max (Vripng_passive_interface); i++)
623 if ((str = vector_slot (Vripng_passive_interface, i)) != NULL)
625 free (str);
626 vector_slot (Vripng_passive_interface, i) = NULL;
628 ripng_passive_interface_apply_all ();
631 /* Write RIPng enable network and interface to the vty. */
633 ripng_network_write (struct vty *vty)
635 int i;
636 char *str;
637 char *ifname;
638 struct route_node *node;
639 char buf[BUFSIZ];
641 /* Write enable network. */
642 for (node = route_top (ripng_enable_network); node; node = route_next (node))
643 if (node->info)
645 struct prefix *p = &node->p;
646 vty_out (vty, " network %s/%d%s",
647 inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ),
648 p->prefixlen,
649 VTY_NEWLINE);
653 /* Write enable interface. */
654 for (i = 0; i < vector_max (ripng_enable_if); i++)
655 if ((str = vector_slot (ripng_enable_if, i)) != NULL)
656 vty_out (vty, " network %s%s", str,
657 VTY_NEWLINE);
659 /* Write passive interface. */
660 for (i = 0; i < vector_max (Vripng_passive_interface); i++)
661 if ((ifname = vector_slot (Vripng_passive_interface, i)) != NULL)
662 vty_out (vty, " passive-interface %s%s", ifname, VTY_NEWLINE);
664 return 0;
667 /* RIPng enable on specified interface or matched network. */
668 DEFUN (ripng_network,
669 ripng_network_cmd,
670 "network IF_OR_ADDR",
671 "RIPng enable on specified interface or network.\n"
672 "Interface or address")
674 int ret;
675 struct prefix p;
677 ret = str2prefix (argv[0], &p);
679 /* Given string is IPv6 network or interface name. */
680 if (ret)
681 ret = ripng_enable_network_add (&p);
682 else
683 ret = ripng_enable_if_add (argv[0]);
685 if (ret < 0)
687 vty_out (vty, "There is same network configuration %s%s", argv[0],
688 VTY_NEWLINE);
689 return CMD_WARNING;
692 ripng_enable_apply_all ();
694 return CMD_SUCCESS;
697 /* RIPng enable on specified interface or matched network. */
698 DEFUN (no_ripng_network,
699 no_ripng_network_cmd,
700 "no network IF_OR_ADDR",
701 NO_STR
702 "RIPng enable on specified interface or network.\n"
703 "Interface or address")
705 int ret;
706 struct prefix p;
708 ret = str2prefix (argv[0], &p);
710 /* Given string is interface name. */
711 if (ret)
712 ret = ripng_enable_network_delete (&p);
713 else
714 ret = ripng_enable_if_delete (argv[0]);
716 if (ret < 0)
718 vty_out (vty, "can't find network %s%s", argv[0],
719 VTY_NEWLINE);
720 return CMD_WARNING;
723 ripng_enable_apply_all ();
725 return CMD_SUCCESS;
728 DEFUN (ripng_passive_interface,
729 ripng_passive_interface_cmd,
730 "passive-interface IFNAME",
731 "Suppress routing updates on an interface\n"
732 "Interface name\n")
734 return ripng_passive_interface_set (vty, argv[0]);
737 DEFUN (no_ripng_passive_interface,
738 no_ripng_passive_interface_cmd,
739 "no passive-interface IFNAME",
740 NO_STR
741 "Suppress routing updates on an interface\n"
742 "Interface name\n")
744 return ripng_passive_interface_unset (vty, argv[0]);
747 struct ripng_interface *
748 ri_new ()
750 struct ripng_interface *ri;
751 ri = XCALLOC (MTYPE_IF, sizeof (struct ripng_interface));
752 return ri;
756 ripng_if_new_hook (struct interface *ifp)
758 ifp->info = ri_new ();
759 return 0;
762 /* Configuration write function for ripngd. */
764 interface_config_write (struct vty *vty)
766 listnode node;
767 struct interface *ifp;
768 struct ripng_interface *ri;
769 int write = 0;
771 for (node = listhead (iflist); node; nextnode (node))
773 ifp = getdata (node);
774 ri = ifp->info;
776 vty_out (vty, "interface %s%s", ifp->name,
777 VTY_NEWLINE);
778 if (ifp->desc)
779 vty_out (vty, " description %s%s", ifp->desc,
780 VTY_NEWLINE);
782 vty_out (vty, "!%s", VTY_NEWLINE);
784 write++;
786 return write;
789 /* ripngd's interface node. */
790 struct cmd_node interface_node =
792 INTERFACE_NODE,
793 "%s(config-if)# ",
796 /* Initialization of interface. */
797 void
798 ripng_if_init ()
800 /* Interface initialize. */
801 iflist = list_new ();
802 if_add_hook (IF_NEW_HOOK, ripng_if_new_hook);
804 /* RIPng enable network init. */
805 ripng_enable_network = route_table_init ();
807 /* RIPng enable interface init. */
808 ripng_enable_if = vector_init (1);
810 /* RIPng passive interface. */
811 Vripng_passive_interface = vector_init (1);
813 /* Install interface node. */
814 install_node (&interface_node, interface_config_write);
816 install_element (CONFIG_NODE, &interface_cmd);
817 install_element (INTERFACE_NODE, &config_end_cmd);
818 install_element (INTERFACE_NODE, &config_exit_cmd);
819 install_element (INTERFACE_NODE, &config_help_cmd);
820 install_element (INTERFACE_NODE, &interface_desc_cmd);
821 install_element (INTERFACE_NODE, &no_interface_desc_cmd);
823 install_element (RIPNG_NODE, &ripng_network_cmd);
824 install_element (RIPNG_NODE, &no_ripng_network_cmd);
825 install_element (RIPNG_NODE, &ripng_passive_interface_cmd);
826 install_element (RIPNG_NODE, &no_ripng_passive_interface_cmd);