From 718e3744195351130f4ce7dbe0613f4b3e23df93 Mon Sep 17 00:00:00 2001 From: paul Date: Fri, 13 Dec 2002 20:15:29 +0000 Subject: Initial revision --- ospf6d/ospf6d.c | 826 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 826 insertions(+) create mode 100644 ospf6d/ospf6d.c (limited to 'ospf6d/ospf6d.c') diff --git a/ospf6d/ospf6d.c b/ospf6d/ospf6d.c new file mode 100644 index 00000000..dbe7a88f --- /dev/null +++ b/ospf6d/ospf6d.c @@ -0,0 +1,826 @@ +/* + * Copyright (C) 1999 Yasuhiro Ohara + * + * This file is part of GNU Zebra. + * + * GNU Zebra is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * GNU Zebra is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Zebra; see the file COPYING. If not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "ospf6d.h" + +#include "ospf6_damp.h" + +/* global ospf6d variable */ +int ospf6_sock; +list iflist; +list nexthoplist = NULL; +struct sockaddr_in6 allspfrouters6; +struct sockaddr_in6 alldrouters6; +char *recent_reason; /* set by ospf6_lsa_check_recent () */ +int proctitle_mode = 0; + +char ospf6_daemon_version[] = OSPF6_DAEMON_VERSION; + + +#define TIMER_SEC_MICRO 1000000 + +void +ospf6_timeval_sub (const struct timeval *t1, const struct timeval *t2, + struct timeval *result) +{ + long usec, movedown = 0; + + if (t1->tv_sec < t2->tv_sec || + (t1->tv_sec == t2->tv_sec && t1->tv_usec < t2->tv_usec)) + { + result->tv_sec = 0; + result->tv_usec = 0; + return; + } + + if (t1->tv_usec < t2->tv_usec) + { + usec = t1->tv_usec + TIMER_SEC_MICRO; + movedown++; + } + else + usec = t1->tv_usec; + result->tv_usec = usec - t2->tv_usec; + + result->tv_sec = t1->tv_sec - t2->tv_sec - movedown; +} + +void +ospf6_timeval_div (const struct timeval *t1, u_int by, + struct timeval *result) +{ + long movedown; + + if (by == 0) + { + result->tv_sec = 0; + result->tv_usec = 0; + return; + } + + movedown = t1->tv_sec % by; + result->tv_sec = t1->tv_sec / by; + result->tv_usec = (t1->tv_usec + movedown * TIMER_SEC_MICRO) / by; +} + +void +ospf6_timeval_decode (const struct timeval *t, long *dayp, long *hourp, + long *minp, long *secp, long *msecp, long *usecp) +{ + long day, hour, min, sec, msec, usec, left; + + left = t->tv_sec; + day = left / 86400; left -= day * 86400; + hour = left / 3600; left -= hour * 3600; + min = left / 60; left -= min * 60; + sec = left; + left = t->tv_usec; + msec = left / 1000; left -= msec * 1000; + usec = left; + + if (dayp) *dayp = day; + if (hourp) *hourp = hour; + if (minp) *minp = min; + if (secp) *secp = sec; + if (msecp) *msecp = msec; + if (usecp) *usecp = usec; +} + +void +ospf6_timeval_string (struct timeval *tv, char *buf, int size) +{ + char days[16], hours[16], mins[16], secs[16], msecs[16], usecs[16]; + long day, hour, min, sec, msec, usec; + + ospf6_timeval_decode (tv, &day, &hour, &min, &sec, &msec, &usec); + snprintf (days, sizeof (days), "%ld days ", day); + snprintf (hours, sizeof (hours), "%ld hours ", hour); + snprintf (mins, sizeof (mins), "%ld mins ", min); + snprintf (secs, sizeof (secs), "%ld secs ", sec); + snprintf (msecs, sizeof (msecs), "%ld msecs ", msec); + snprintf (usecs, sizeof (usecs), "%ld usecs ", usec); + + snprintf (buf, size, "%s%s%s%s%s%s", + (day ? days : ""), (hour ? hours : ""), + (min ? mins : ""), (sec ? secs : ""), + (msec ? msecs : ""), (usec ? usecs : "")); +} + +void +ospf6_timeval_string_summary (struct timeval *tv, char *buf, int size) +{ + char days[16], hours[16], mins[16], secs[16], msecs[16], usecs[16]; + long day, hour, min, sec, msec, usec; + + ospf6_timeval_decode (tv, &day, &hour, &min, &sec, &msec, &usec); + snprintf (days, sizeof (days), "%02ldd", day); + snprintf (hours, sizeof (hours), "%ldh", hour); + snprintf (mins, sizeof (mins), "%ldm", min); + snprintf (secs, sizeof (secs), "%lds", sec); + snprintf (msecs, sizeof (msecs), "%ldms", msec); + snprintf (usecs, sizeof (usecs), "%ldus", usec); + + snprintf (buf, size, "%s%02ld:%02ld:%02ld", + (day ? days : ""), hour, min, sec); +} + +/* foreach function */ +void +ospf6_count_state (void *arg, int val, void *obj) +{ + int *count = (int *) arg; + u_char state = val; + struct ospf6_neighbor *nei = (struct ospf6_neighbor *) obj; + + if (nei->state == state) + (*count)++; +} + +/* VTY commands. */ +DEFUN (reload, + reload_cmd, + "reload", + "Reloads\n") +{ + extern void _reload (); + _reload (); + return CMD_SUCCESS; +} + +DEFUN (garbage_collection, + garbage_collection_cmd, + "ipv6 ospf6 garbage collect", + IPV6_STR + OSPF6_STR + "garbage collection by hand\n" + "Remove Maxages if possible and recalculate routes\n") +{ + ospf6_maxage_remover (); +#if 0 + ospf6_route_calculation_schedule (); +#endif + return CMD_SUCCESS; +} + +/* Show version. */ +DEFUN (show_version_ospf6, + show_version_ospf6_cmd, + "show version ospf6", + SHOW_STR + "Displays ospf6d version\n") +{ + vty_out (vty, "Zebra OSPF6d Version: %s%s", + ospf6_daemon_version, VTY_NEWLINE); + + return CMD_SUCCESS; +} + +/* start ospf6 */ +DEFUN (router_ospf6, + router_ospf6_cmd, + "router ospf6", + OSPF6_ROUTER_STR + OSPF6_STR) +{ + if (ospf6 == NULL) + ospf6_start (); + + /* set current ospf point. */ + vty->node = OSPF6_NODE; + vty->index = ospf6; + + return CMD_SUCCESS; +} + +/* stop ospf6 */ +DEFUN (no_router_ospf6, + no_router_ospf6_cmd, + "no router ospf6", + NO_STR + OSPF6_ROUTER_STR) +{ + if (!ospf6) + vty_out (vty, "OSPFv3 is not running%s", VTY_NEWLINE); + else + ospf6_stop (); + + /* return to config node . */ + vty->node = CONFIG_NODE; + vty->index = NULL; + + return CMD_SUCCESS; +} + +/* show top level structures */ +DEFUN (show_ipv6_ospf6, + show_ipv6_ospf6_cmd, + "show ipv6 ospf6", + SHOW_STR + IP6_STR + OSPF6_STR) +{ + OSPF6_CMD_CHECK_RUNNING (); + + ospf6_show (vty); + return CMD_SUCCESS; +} + +DEFUN (show_ipv6_ospf6_nexthoplist, + show_ipv6_ospf6_nexthoplist_cmd, + "show ipv6 ospf6 nexthop-list", + SHOW_STR + IP6_STR + OSPF6_STR + "List of nexthop\n") +{ +#if 0 + listnode i; + struct ospf6_nexthop *nh; + char buf[128]; + for (i = listhead (nexthoplist); i; nextnode (i)) + { + nh = (struct ospf6_nexthop *) getdata (i); + nexthop_str (nh, buf, sizeof (buf)); + vty_out (vty, "%s%s", buf, + VTY_NEWLINE); + } +#endif + return CMD_SUCCESS; +} + +DEFUN (show_ipv6_ospf6_statistics, + show_ipv6_ospf6_statistics_cmd, + "show ipv6 ospf6 statistics", + SHOW_STR + IP6_STR + OSPF6_STR + "Statistics\n") +{ + OSPF6_CMD_CHECK_RUNNING (); + + ospf6_statistics_show (vty, ospf6); + return CMD_SUCCESS; +} + +/* change Router_ID commands. */ +DEFUN (router_id, + router_id_cmd, + "router-id ROUTER_ID", + "Configure ospf Router-ID.\n" + V4NOTATION_STR) +{ + int ret; + u_int32_t router_id; + + ret = inet_pton (AF_INET, argv[0], &router_id); + if (!ret) + { + vty_out (vty, "malformed ospf router identifier%s", VTY_NEWLINE); + vty_out (vty, "%s", VTY_NEWLINE); + return CMD_WARNING; + } + + if (IS_OSPF6_DUMP_CONFIG) + zlog_info ("CONFIG: router-id %s", argv[0]); + ospf6->router_id = router_id; + + return CMD_SUCCESS; +} + +int +ospf6_interface_bind_area (struct vty *vty, + char *if_name, char *area_name, + char *plist_name, int passive) +{ + struct interface *ifp; + struct ospf6_interface *o6i; + struct ospf6_area *o6a; + u_int32_t area_id; + + /* find/create ospf6 interface */ + ifp = if_get_by_name (if_name); + o6i = (struct ospf6_interface *) ifp->info; + if (! o6i) + o6i = ospf6_interface_create (ifp); + + /* parse Area-ID */ + if (inet_pton (AF_INET, area_name, &area_id) != 1) + { + vty_out (vty, "Invalid Area-ID: %s%s", area_name, VTY_NEWLINE); + return CMD_ERR_AMBIGUOUS; + } + + /* find/create ospf6 area */ + o6a = ospf6_area_lookup (area_id, ospf6); + if (!o6a) + { + o6a = ospf6_area_create (area_id); + o6a->ospf6 = ospf6; + listnode_add (ospf6->area_list, o6a); + } + + if (o6i->area) + { + if (o6i->area != o6a) + { + vty_out (vty, "Aready attached to area %s%s", + o6i->area->str, VTY_NEWLINE); + return CMD_ERR_NOTHING_TODO; + } + } + else + { + listnode_add (o6a->if_list, o6i); + o6i->area = o6a; + } + + /* prefix-list name */ + if (plist_name) + { + if (o6i->plist_name) + XFREE (MTYPE_PREFIX_LIST_STR, o6i->plist_name); + o6i->plist_name = XSTRDUP (MTYPE_PREFIX_LIST_STR, plist_name); + } + else + { + if (o6i->plist_name) + XFREE (MTYPE_PREFIX_LIST_STR, o6i->plist_name); + o6i->plist_name = NULL; + } + + if (passive) + { + listnode node; + struct ospf6_neighbor *o6n; + + SET_FLAG (o6i->flag, OSPF6_INTERFACE_FLAG_PASSIVE); + if (o6i->thread_send_hello) + { + thread_cancel (o6i->thread_send_hello); + o6i->thread_send_hello = (struct thread *) NULL; + } + + for (node = listhead (o6i->neighbor_list); node; nextnode (node)) + { + o6n = getdata (node); + if (o6n->inactivity_timer) + thread_cancel (o6n->inactivity_timer); + thread_execute (master, inactivity_timer, o6n, 0); + } + } + else + { + UNSET_FLAG (o6i->flag, OSPF6_INTERFACE_FLAG_PASSIVE); + if (o6i->thread_send_hello == NULL) + thread_add_event (master, ospf6_send_hello, o6i, 0); + } + + /* enable I/F if it's not enabled still */ + if (! ospf6_interface_is_enabled (o6i->interface->ifindex)) + thread_add_event (master, interface_up, o6i, 0); + else + CALL_FOREACH_LSA_HOOK (hook_interface, hook_change, o6i); + + CALL_CHANGE_HOOK (&interface_hook, o6i); + return CMD_SUCCESS; +} + +DEFUN (interface_area_plist, + interface_area_plist_cmd, + "interface IFNAME area A.B.C.D prefix-list WORD", + "Enable routing on an IPv6 interface\n" + IFNAME_STR + "Set the OSPF6 area ID\n" + "OSPF6 area ID in IPv4 address notation\n" + OSPF6_PREFIX_LIST_STR + "IPv6 prefix-list name\n" + ) +{ + if (IS_OSPF6_DUMP_CONFIG) + zlog_info ("CONFIG: interface %s area %s prefix-list %s", + argv[0], argv[1], argv[2]); + + return ospf6_interface_bind_area (vty, argv[0], argv[1], argv[2], 0); +} + +DEFUN (interface_area_plist_passive, + interface_area_plist_passive_cmd, + "interface IFNAME area A.B.C.D prefix-list WORD passive", + "Enable routing on an IPv6 interface\n" + IFNAME_STR + "Set the OSPF6 area ID\n" + "OSPF6 area ID in IPv4 address notation\n" + OSPF6_PREFIX_LIST_STR + "IPv6 prefix-list name\n" + "IPv6 prefix-list name\n" + OSPF6_PASSIVE_STR + ) +{ + if (IS_OSPF6_DUMP_CONFIG) + zlog_info ("CONFIG: interface %s area %s prefix-list %s passive", + argv[0], argv[1], argv[2]); + + return ospf6_interface_bind_area (vty, argv[0], argv[1], argv[2], 1); +} + +DEFUN (interface_area, + interface_area_cmd, + "interface IFNAME area A.B.C.D", + "Enable routing on an IPv6 interface\n" + IFNAME_STR + "Set the OSPF6 area ID\n" + "OSPF6 area ID in IPv4 address notation\n" + ) +{ + struct interface *ifp; + struct ospf6_interface *o6i; + int passive; + char *plist_name; + + if (IS_OSPF6_DUMP_CONFIG) + zlog_info ("CONFIG: interface %s area %s", + argv[0], argv[1]); + + ifp = if_get_by_name (argv[0]); + o6i = (struct ospf6_interface *) ifp->info; + if (o6i) + { + passive = CHECK_FLAG (o6i->flag, OSPF6_INTERFACE_FLAG_PASSIVE); + plist_name = o6i->plist_name; + } + else + { + passive = 0; + plist_name = NULL; + } + + return ospf6_interface_bind_area (vty, argv[0], argv[1], + plist_name, passive); +} + +DEFUN (interface_area_passive, + interface_area_passive_cmd, + "interface IFNAME area A.B.C.D passive", + "Enable routing on an IPv6 interface\n" + IFNAME_STR + "Set the OSPF6 area ID\n" + "OSPF6 area ID in IPv4 address notation\n" + OSPF6_PASSIVE_STR + ) +{ + if (IS_OSPF6_DUMP_CONFIG) + zlog_info ("CONFIG: interface %s area %s passive", + argv[0], argv[1]); + + return ospf6_interface_bind_area (vty, argv[0], argv[1], NULL, 1); +} + +DEFUN (no_interface_area, + no_interface_area_cmd, + "no interface IFNAME area A.B.C.D", + NO_STR + "Disable routing on an IPv6 interface\n" + IFNAME_STR) +{ + struct interface *ifp; + struct ospf6_interface *o6i; + struct ospf6 *o6; + u_int32_t area_id; + + o6 = (struct ospf6 *) vty->index; + + ifp = if_lookup_by_name (argv[0]); + if (!ifp) + return CMD_ERR_NO_MATCH; + + o6i = (struct ospf6_interface *) ifp->info; + if (!o6i) + return CMD_SUCCESS; + + /* parse Area-ID */ + if (inet_pton (AF_INET, argv[1], &area_id) != 1) + { + vty_out (vty, "Invalid Area-ID: %s%s", argv[1], VTY_NEWLINE); + return CMD_ERR_AMBIGUOUS; + } + + if (o6i->area->area_id != area_id) + { + vty_out (vty, "Wrong Area-ID: %s aready attached to area %s%s", + o6i->interface->name, o6i->area->str, VTY_NEWLINE); + return CMD_ERR_NOTHING_TODO; + } + + if (o6i->area) + thread_execute (master, interface_down, o6i, 0); + + listnode_delete (o6i->area->if_list, o6i); + o6i->area = (struct ospf6_area *) NULL; + + return CMD_SUCCESS; +} + +DEFUN (area_range, + area_range_cmd, + "area A.B.C.D range X:X::X:X/M", + "OSPFv3 area parameters\n" + "OSPFv3 area ID in IPv4 address format\n" + "Summarize routes matching address/mask (border routers only)\n" + "IPv6 address range\n") +{ + struct ospf6 *o6; + struct ospf6_area *o6a; + u_int32_t area_id; + int ret; + + o6 = (struct ospf6 *) vty->index; + inet_pton (AF_INET, argv[0], &area_id); + o6a = ospf6_area_lookup (area_id, o6); + if (! o6a) + { + vty_out (vty, "No such area%s", VTY_NEWLINE); + return CMD_ERR_NO_MATCH; + } + + ret = str2prefix_ipv6 (argv[1], &o6a->area_range); + if (ret <= 0) + { + vty_out (vty, "Malformed IPv6 address%s", VTY_NEWLINE); + return CMD_WARNING; + } + + return CMD_SUCCESS; +} + +DEFUN (passive_interface, + passive_interface_cmd, + "passive-interface IFNAME", + OSPF6_PASSIVE_STR + IFNAME_STR) +{ + struct interface *ifp; + struct ospf6_interface *o6i; + + ifp = if_get_by_name (argv[0]); + if (ifp->info) + o6i = (struct ospf6_interface *) ifp->info; + else + o6i = ospf6_interface_create (ifp); + + SET_FLAG (o6i->flag, OSPF6_INTERFACE_FLAG_PASSIVE); + + if (o6i->thread_send_hello) + { + thread_cancel (o6i->thread_send_hello); + o6i->thread_send_hello = (struct thread *) NULL; + } + + return CMD_SUCCESS; +} + +DEFUN (no_passive_interface, + no_passive_interface_cmd, + "no passive-interface IFNAME", + NO_STR + OSPF6_PASSIVE_STR + IFNAME_STR) +{ + struct interface *ifp; + struct ospf6_interface *o6i; + + ifp = if_lookup_by_name (argv[0]); + if (! ifp) + return CMD_ERR_NO_MATCH; + + o6i = (struct ospf6_interface *) ifp->info; + UNSET_FLAG (o6i->flag, OSPF6_INTERFACE_FLAG_PASSIVE); + if (o6i->thread_send_hello == NULL) + thread_add_event (master, ospf6_send_hello, o6i, 0); + + return CMD_SUCCESS; +} + +#ifdef HAVE_SETPROCTITLE +extern int _argc; +extern char **_argv; + +DEFUN (set_proctitle, + set_proctitle_cmd, + "set proctitle (version|normal|none)", + "Set command\n" + "Process title\n" + "Version information\n" + "Normal command-line options\n" + "Just program name\n") +{ + int i; + char buf[64], tmp[64]; + + if (strncmp (argv[0], "v", 1) == 0) + { + proctitle_mode = 1; + setproctitle ("%s Zebra: %s", OSPF6_DAEMON_VERSION, ZEBRA_VERSION); + } + else if (strncmp (argv[0], "nor", 3) == 0) + { + proctitle_mode = 0; + memset (tmp, 0, sizeof (tmp)); + memset (buf, 0, sizeof (buf)); + for (i = 0; i < _argc; i++) + { + snprintf (buf, sizeof (buf), "%s%s ", tmp, _argv[i]); + memcpy (&tmp, &buf, sizeof (tmp)); + } + setproctitle (buf); + } + else if (strncmp (argv[0], "non", 3) == 0) + { + proctitle_mode = -1; + setproctitle (NULL); + } + else + return CMD_ERR_NO_MATCH; + + return CMD_SUCCESS; +} +#endif /* HAVE_SETPROCTITLE */ + +/* OSPF configuration write function. */ +int +ospf6_config_write (struct vty *vty) +{ + listnode j, k; + char buf[64]; + struct ospf6_area *area; + struct ospf6_interface *o6i; + + if (proctitle_mode == 1) + vty_out (vty, "set proctitle version%s", VTY_NEWLINE); + else if (proctitle_mode == -1) + vty_out (vty, "set proctitle none%s", VTY_NEWLINE); + + vty_out (vty, "!%s", VTY_NEWLINE); + + if (! ospf6) + return 0; + + /* OSPFv6 configuration. */ + if (!ospf6) + return CMD_SUCCESS; + + inet_ntop (AF_INET, &ospf6->router_id, buf, sizeof (buf)); + vty_out (vty, "router ospf6%s", VTY_NEWLINE); + vty_out (vty, " router-id %s%s", buf, VTY_NEWLINE); + + ospf6_redistribute_config_write (vty); + ospf6_damp_config_write (vty); + + for (j = listhead (ospf6->area_list); j; nextnode (j)) + { + area = (struct ospf6_area *)getdata (j); + for (k = listhead (area->if_list); k; nextnode (k)) + { + o6i = (struct ospf6_interface *) getdata (k); + vty_out (vty, " interface %s area %s%s", + o6i->interface->name, area->str, VTY_NEWLINE); + } + } + vty_out (vty, "!%s", VTY_NEWLINE); + return 0; +} + +/* OSPF6 node structure. */ +struct cmd_node ospf6_node = +{ + OSPF6_NODE, + "%s(config-ospf6)# ", +}; + +/* Install ospf related commands. */ +void +ospf6_init () +{ + /* Install ospf6 top node. */ + install_node (&ospf6_node, ospf6_config_write); + + install_element (VIEW_NODE, &show_ipv6_ospf6_cmd); + install_element (VIEW_NODE, &show_version_ospf6_cmd); + install_element (ENABLE_NODE, &show_ipv6_ospf6_cmd); + install_element (ENABLE_NODE, &show_version_ospf6_cmd); + install_element (ENABLE_NODE, &reload_cmd); + install_element (CONFIG_NODE, &router_ospf6_cmd); + install_element (CONFIG_NODE, &interface_cmd); +#ifdef OSPF6_STATISTICS + install_element (VIEW_NODE, &show_ipv6_ospf6_statistics_cmd); + install_element (ENABLE_NODE, &show_ipv6_ospf6_statistics_cmd); +#endif /* OSPF6_STATISTICS */ +#ifdef OSPF6_GARBAGE_COLLECT + install_element (ENABLE_NODE, &garbage_collection_cmd); +#endif /* OSPF6_GARBAGE_COLLECT */ +#ifdef HAVE_SETPROCTITLE + install_element (CONFIG_NODE, &set_proctitle_cmd); +#endif /* HAVE_SETPROCTITLE */ + + install_default (OSPF6_NODE); + install_element (OSPF6_NODE, &router_id_cmd); + install_element (OSPF6_NODE, &interface_area_cmd); + install_element (OSPF6_NODE, &interface_area_passive_cmd); + install_element (OSPF6_NODE, &interface_area_plist_cmd); + install_element (OSPF6_NODE, &interface_area_plist_passive_cmd); + install_element (OSPF6_NODE, &no_interface_area_cmd); + install_element (OSPF6_NODE, &passive_interface_cmd); + install_element (OSPF6_NODE, &no_passive_interface_cmd); + install_element (OSPF6_NODE, &area_range_cmd); + + /* Make empty list of top list. */ + if_init (); + + /* Install access list */ + access_list_init (); + + /* Install prefix list */ + prefix_list_init (); + + ospf6_dump_init (); + +#ifdef HAVE_OSPF6_DAMP + ospf6_damp_init (); +#endif /*HAVE_OSPF6_DAMP*/ + + ospf6_hook_init (); + ospf6_lsa_init (); + + ospf6_top_init (); + ospf6_area_init (); + ospf6_interface_init (); + ospf6_neighbor_init (); + ospf6_zebra_init (); + + ospf6_routemap_init (); + ospf6_lsdb_init (); + + ospf6_spf_init (); + + ospf6_intra_init (); + ospf6_abr_init (); + ospf6_asbr_init (); +} + +void +ospf6_terminate () +{ + /* stop ospf6 */ + ospf6_stop (); + + /* log */ + zlog (NULL, LOG_INFO, "OSPF6d terminated"); +} + +void +ospf6_maxage_remover () +{ +#if 0 + if (IS_OSPF6_DUMP_LSDB) + zlog_info ("MaxAge Remover"); +#endif + + ospf6_top_schedule_maxage_remover (NULL, 0, ospf6); + (*ospf6->foreach_area) (ospf6, NULL, 0, + ospf6_area_schedule_maxage_remover); + (*ospf6->foreach_if) (ospf6, NULL, 0, + ospf6_interface_schedule_maxage_remover); +} + + + +void * +ospf6_lsa_get_scope (u_int16_t type, struct ospf6_interface *o6i) +{ + if (OSPF6_LSA_IS_SCOPE_LINKLOCAL (ntohs (type))) + return o6i; + else if (OSPF6_LSA_IS_SCOPE_AREA (ntohs (type))) + return o6i->area; + else if (OSPF6_LSA_IS_SCOPE_AS (ntohs (type))) + return o6i->area->ospf6; + else + return NULL; +} + -- cgit v1.2.1