summaryrefslogtreecommitdiff
path: root/ospf6d
diff options
context:
space:
mode:
Diffstat (limited to 'ospf6d')
-rw-r--r--ospf6d/.cvsignore15
-rw-r--r--ospf6d/ospf6_abr.c6
-rw-r--r--ospf6d/ospf6_abr.h5
-rw-r--r--ospf6d/ospf6_area.c28
-rw-r--r--ospf6d/ospf6_asbr.c164
-rw-r--r--ospf6d/ospf6_asbr.h10
-rw-r--r--ospf6d/ospf6_interface.c75
-rw-r--r--ospf6d/ospf6_interface.h9
-rw-r--r--ospf6d/ospf6_intra.h6
-rw-r--r--ospf6d/ospf6_lsa.c12
-rw-r--r--ospf6d/ospf6_lsa.h2
-rw-r--r--ospf6d/ospf6_main.c22
-rw-r--r--ospf6d/ospf6_message.c695
-rw-r--r--ospf6d/ospf6_message.h14
-rw-r--r--ospf6d/ospf6_network.c91
-rw-r--r--ospf6d/ospf6_network.h6
-rw-r--r--ospf6d/ospf6_proto.c9
-rw-r--r--ospf6d/ospf6_proto.h1
-rw-r--r--ospf6d/ospf6_route.h1
-rw-r--r--ospf6d/ospf6_spf.c7
-rw-r--r--ospf6d/ospf6_top.c16
-rw-r--r--ospf6d/ospf6_zebra.c1
-rw-r--r--ospf6d/ospf6d.c9
-rw-r--r--ospf6d/ospf6d.h3
24 files changed, 812 insertions, 395 deletions
diff --git a/ospf6d/.cvsignore b/ospf6d/.cvsignore
deleted file mode 100644
index 522397a1..00000000
--- a/ospf6d/.cvsignore
+++ /dev/null
@@ -1,15 +0,0 @@
-Makefile.in
-Makefile
-*.o
-*.patch
-ospf6d
-ospf6d.conf
-tags
-TAGS
-.deps
-.nfs*
-*.lo
-*.la
-*.libs
-.arch-inventory
-.arch-ids
diff --git a/ospf6d/ospf6_abr.c b/ospf6d/ospf6_abr.c
index d38ef21a..c3a63fe6 100644
--- a/ospf6d/ospf6_abr.c
+++ b/ospf6d/ospf6_abr.c
@@ -555,7 +555,8 @@ ospf6_abr_examin_summary (struct ospf6_lsa *lsa, struct ospf6_area *oa)
prefix.family = AF_INET6;
prefix.prefixlen = prefix_lsa->prefix.prefix_length;
ospf6_prefix_in6_addr (&prefix.u.prefix6, &prefix_lsa->prefix);
- prefix2str (&prefix, buf, sizeof (buf));
+ if (is_debug)
+ prefix2str (&prefix, buf, sizeof (buf));
table = oa->ospf6->route_table;
type = OSPF6_DEST_TYPE_NETWORK;
prefix_options = prefix_lsa->prefix.prefix_options;
@@ -574,7 +575,8 @@ ospf6_abr_examin_summary (struct ospf6_lsa *lsa, struct ospf6_area *oa)
router_lsa = (struct ospf6_inter_router_lsa *)
OSPF6_LSA_HEADER_END (lsa->header);
ospf6_linkstate_prefix (router_lsa->router_id, htonl (0), &prefix);
- inet_ntop (AF_INET, &router_lsa->router_id, buf, sizeof (buf));
+ if (is_debug)
+ inet_ntop (AF_INET, &router_lsa->router_id, buf, sizeof (buf));
table = oa->ospf6->brouter_table;
type = OSPF6_DEST_TYPE_ROUTER;
options[0] = router_lsa->options[0];
diff --git a/ospf6d/ospf6_abr.h b/ospf6d/ospf6_abr.h
index 5d00c474..816f5964 100644
--- a/ospf6d/ospf6_abr.h
+++ b/ospf6d/ospf6_abr.h
@@ -22,6 +22,9 @@
#ifndef OSPF6_ABR_H
#define OSPF6_ABR_H
+/* for struct ospf6_route */
+#include "ospf6_route.h"
+
/* Debug option */
extern unsigned char conf_debug_ospf6_abr;
#define OSPF6_DEBUG_ABR_ON() \
@@ -32,6 +35,7 @@ extern unsigned char conf_debug_ospf6_abr;
(conf_debug_ospf6_abr)
/* Inter-Area-Prefix-LSA */
+#define OSPF6_INTER_PREFIX_LSA_MIN_SIZE 4U /* w/o IPv6 prefix */
struct ospf6_inter_prefix_lsa
{
u_int32_t metric;
@@ -39,6 +43,7 @@ struct ospf6_inter_prefix_lsa
};
/* Inter-Area-Router-LSA */
+#define OSPF6_INTER_ROUTER_LSA_FIX_SIZE 12U
struct ospf6_inter_router_lsa
{
u_char mbz;
diff --git a/ospf6d/ospf6_area.c b/ospf6d/ospf6_area.c
index f4b327e4..9934e6b9 100644
--- a/ospf6d/ospf6_area.c
+++ b/ospf6d/ospf6_area.c
@@ -420,6 +420,18 @@ ospf6_area_config_write (struct vty *vty)
prefix2str (&range->prefix, buf, sizeof (buf));
vty_out (vty, " area %s range %s%s", oa->name, buf, VNL);
}
+ if (PREFIX_NAME_IN (oa))
+ vty_out (vty, " area %s filter-list prefix %s in%s",
+ oa->name, PREFIX_NAME_IN (oa), VNL);
+ if (PREFIX_NAME_OUT (oa))
+ vty_out (vty, " area %s filter-list prefix %s out%s",
+ oa->name, PREFIX_NAME_OUT (oa), VNL);
+ if (IMPORT_NAME (oa))
+ vty_out (vty, " area %s import-list %s%s",
+ oa->name, IMPORT_NAME (oa), VNL);
+ if (EXPORT_NAME (oa))
+ vty_out (vty, " area %s export-list %s%s",
+ oa->name, EXPORT_NAME (oa), VNL);
}
}
@@ -441,14 +453,14 @@ DEFUN (area_filter_list,
argc--;
argv++;
- plist = prefix_list_lookup (AFI_IP6, argv[1]);
- if (strncmp (argv[2], "in", 2) == 0)
+ plist = prefix_list_lookup (AFI_IP6, argv[0]);
+ if (strncmp (argv[1], "in", 2) == 0)
{
PREFIX_LIST_IN (area) = plist;
if (PREFIX_NAME_IN (area))
free (PREFIX_NAME_IN (area));
- PREFIX_NAME_IN (area) = strdup (argv[1]);
+ PREFIX_NAME_IN (area) = strdup (argv[0]);
ospf6_abr_reimport (area);
}
else
@@ -457,7 +469,7 @@ DEFUN (area_filter_list,
if (PREFIX_NAME_OUT (area))
free (PREFIX_NAME_OUT (area));
- PREFIX_NAME_OUT (area) = strdup (argv[1]);
+ PREFIX_NAME_OUT (area) = strdup (argv[0]);
ospf6_abr_enable_area (area);
}
@@ -483,11 +495,11 @@ DEFUN (no_area_filter_list,
argc--;
argv++;
- plist = prefix_list_lookup (AFI_IP6, argv[1]);
- if (strncmp (argv[2], "in", 2) == 0)
+ plist = prefix_list_lookup (AFI_IP6, argv[0]);
+ if (strncmp (argv[1], "in", 2) == 0)
{
if (PREFIX_NAME_IN (area))
- if (strcmp (PREFIX_NAME_IN (area), argv[1]) != 0)
+ if (strcmp (PREFIX_NAME_IN (area), argv[0]) != 0)
return CMD_SUCCESS;
PREFIX_LIST_IN (area) = NULL;
@@ -500,7 +512,7 @@ DEFUN (no_area_filter_list,
else
{
if (PREFIX_NAME_OUT (area))
- if (strcmp (PREFIX_NAME_OUT (area), argv[1]) != 0)
+ if (strcmp (PREFIX_NAME_OUT (area), argv[0]) != 0)
return CMD_SUCCESS;
PREFIX_LIST_OUT (area) = NULL;
diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c
index 3efaab44..ae0a286d 100644
--- a/ospf6d/ospf6_asbr.c
+++ b/ospf6d/ospf6_asbr.c
@@ -447,6 +447,7 @@ ospf6_asbr_redistribute_add (int type, int ifindex, struct prefix *prefix,
memset (&troute, 0, sizeof (troute));
memset (&tinfo, 0, sizeof (tinfo));
troute.route_option = &tinfo;
+ tinfo.ifindex = ifindex;
ret = route_map_apply (ospf6->rmap[type].map, prefix,
RMAP_OSPF6, &troute);
@@ -616,27 +617,16 @@ ospf6_asbr_redistribute_remove (int type, int ifindex, struct prefix *prefix)
DEFUN (ospf6_redistribute,
ospf6_redistribute_cmd,
- "redistribute (static|kernel|connected|ripng|bgp)",
+ "redistribute " QUAGGA_REDIST_STR_OSPF6D,
"Redistribute\n"
- "Static route\n"
- "Kernel route\n"
- "Connected route\n"
- "RIPng route\n"
- "BGP route\n"
+ QUAGGA_REDIST_HELP_STR_OSPF6D
)
{
- int type = 0;
-
- if (strncmp (argv[0], "sta", 3) == 0)
- type = ZEBRA_ROUTE_STATIC;
- else if (strncmp (argv[0], "ker", 3) == 0)
- type = ZEBRA_ROUTE_KERNEL;
- else if (strncmp (argv[0], "con", 3) == 0)
- type = ZEBRA_ROUTE_CONNECT;
- else if (strncmp (argv[0], "rip", 3) == 0)
- type = ZEBRA_ROUTE_RIPNG;
- else if (strncmp (argv[0], "bgp", 3) == 0)
- type = ZEBRA_ROUTE_BGP;
+ int type;
+
+ type = proto_redistnum(AFI_IP6, argv[0]);
+ if (type < 0 || type == ZEBRA_ROUTE_OSPF6)
+ return CMD_WARNING;
ospf6_asbr_redistribute_unset (type);
ospf6_asbr_routemap_unset (type);
@@ -646,29 +636,18 @@ DEFUN (ospf6_redistribute,
DEFUN (ospf6_redistribute_routemap,
ospf6_redistribute_routemap_cmd,
- "redistribute (static|kernel|connected|ripng|bgp) route-map WORD",
+ "redistribute " QUAGGA_REDIST_STR_OSPF6D " route-map WORD",
"Redistribute\n"
- "Static routes\n"
- "Kernel route\n"
- "Connected route\n"
- "RIPng route\n"
- "BGP route\n"
+ QUAGGA_REDIST_HELP_STR_OSPF6D
"Route map reference\n"
"Route map name\n"
)
{
- int type = 0;
-
- if (strncmp (argv[0], "sta", 3) == 0)
- type = ZEBRA_ROUTE_STATIC;
- else if (strncmp (argv[0], "ker", 3) == 0)
- type = ZEBRA_ROUTE_KERNEL;
- else if (strncmp (argv[0], "con", 3) == 0)
- type = ZEBRA_ROUTE_CONNECT;
- else if (strncmp (argv[0], "rip", 3) == 0)
- type = ZEBRA_ROUTE_RIPNG;
- else if (strncmp (argv[0], "bgp", 3) == 0)
- type = ZEBRA_ROUTE_BGP;
+ int type;
+
+ type = proto_redistnum(AFI_IP6, argv[0]);
+ if (type < 0 || type == ZEBRA_ROUTE_OSPF6)
+ return CMD_WARNING;
ospf6_asbr_redistribute_unset (type);
ospf6_asbr_routemap_set (type, argv[1]);
@@ -678,28 +657,17 @@ DEFUN (ospf6_redistribute_routemap,
DEFUN (no_ospf6_redistribute,
no_ospf6_redistribute_cmd,
- "no redistribute (static|kernel|connected|ripng|bgp)",
+ "no redistribute " QUAGGA_REDIST_STR_OSPF6D,
NO_STR
"Redistribute\n"
- "Static route\n"
- "Kernel route\n"
- "Connected route\n"
- "RIPng route\n"
- "BGP route\n"
+ QUAGGA_REDIST_HELP_STR_OSPF6D
)
{
- int type = 0;
-
- if (strncmp (argv[0], "sta", 3) == 0)
- type = ZEBRA_ROUTE_STATIC;
- else if (strncmp (argv[0], "ker", 3) == 0)
- type = ZEBRA_ROUTE_KERNEL;
- else if (strncmp (argv[0], "con", 3) == 0)
- type = ZEBRA_ROUTE_CONNECT;
- else if (strncmp (argv[0], "rip", 3) == 0)
- type = ZEBRA_ROUTE_RIPNG;
- else if (strncmp (argv[0], "bgp", 3) == 0)
- type = ZEBRA_ROUTE_BGP;
+ int type;
+
+ type = proto_redistnum(AFI_IP6, argv[0]);
+ if (type < 0 || type == ZEBRA_ROUTE_OSPF6)
+ return CMD_WARNING;
ospf6_asbr_redistribute_unset (type);
ospf6_asbr_routemap_unset (type);
@@ -813,6 +781,54 @@ ospf6_routemap_rule_match_address_prefixlist_cmd =
ospf6_routemap_rule_match_address_prefixlist_free,
};
+/* `match interface IFNAME' */
+/* Match function should return 1 if match is success else return
+ zero. */
+static route_map_result_t
+ospf6_routemap_rule_match_interface (void *rule, struct prefix *prefix,
+ route_map_object_t type, void *object)
+{
+ struct interface *ifp;
+ struct ospf6_external_info *ei;
+
+ if (type == RMAP_OSPF6)
+ {
+ ei = ((struct ospf6_route *) object)->route_option;
+ ifp = if_lookup_by_name ((char *)rule);
+
+ if (ifp != NULL
+ && ei->ifindex == ifp->ifindex)
+ return RMAP_MATCH;
+ }
+
+ return RMAP_NOMATCH;
+}
+
+/* Route map `interface' match statement. `arg' should be
+ interface name. */
+static void *
+ospf6_routemap_rule_match_interface_compile (const char *arg)
+{
+ return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
+}
+
+/* Free route map's compiled `interface' value. */
+static void
+ospf6_routemap_rule_match_interface_free (void *rule)
+{
+ XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Route map commands for interface matching. */
+struct route_map_rule_cmd
+ospf6_routemap_rule_match_interface_cmd =
+{
+ "interface",
+ ospf6_routemap_rule_match_interface,
+ ospf6_routemap_rule_match_interface_compile,
+ ospf6_routemap_rule_match_interface_free
+};
+
static route_map_result_t
ospf6_routemap_rule_set_metric_type (void *rule, struct prefix *prefix,
route_map_object_t type, void *object)
@@ -990,6 +1006,39 @@ DEFUN (ospf6_routemap_no_match_address_prefixlist,
return route_map_command_status (vty, ret);
}
+/* "match interface" */
+DEFUN (ospf6_routemap_match_interface,
+ ospf6_routemap_match_interface_cmd,
+ "match interface WORD",
+ MATCH_STR
+ "Match first hop interface of route\n"
+ "Interface name\n")
+{
+ return route_map_add_match ((struct route_map_index *) vty->index,
+ "interface", argv[0]);
+}
+
+/* "no match interface WORD" */
+DEFUN (ospf6_routemap_no_match_interface,
+ ospf6_routemap_no_match_interface_cmd,
+ "no match interface",
+ MATCH_STR
+ NO_STR
+ "Match first hop interface of route\n")
+{
+ int ret = route_map_delete_match ((struct route_map_index *) vty->index,
+ "interface", (argc == 0) ? NULL : argv[0]);
+ return route_map_command_status (vty, ret);
+}
+
+ALIAS (ospf6_routemap_no_match_interface,
+ ospf6_routemap_no_match_interface_val_cmd,
+ "no match interface WORD",
+ MATCH_STR
+ NO_STR
+ "Match first hop interface of route\n"
+ "Interface name\n")
+
/* add "set metric-type" */
DEFUN (ospf6_routemap_set_metric_type,
ospf6_routemap_set_metric_type_cmd,
@@ -1082,6 +1131,8 @@ ospf6_routemap_init (void)
route_map_delete_hook (ospf6_asbr_routemap_update);
route_map_install_match (&ospf6_routemap_rule_match_address_prefixlist_cmd);
+ route_map_install_match (&ospf6_routemap_rule_match_interface_cmd);
+
route_map_install_set (&ospf6_routemap_rule_set_metric_type_cmd);
route_map_install_set (&ospf6_routemap_rule_set_metric_cmd);
route_map_install_set (&ospf6_routemap_rule_set_forwarding_cmd);
@@ -1090,6 +1141,11 @@ ospf6_routemap_init (void)
install_element (RMAP_NODE, &ospf6_routemap_match_address_prefixlist_cmd);
install_element (RMAP_NODE, &ospf6_routemap_no_match_address_prefixlist_cmd);
+ /* Match interface */
+ install_element (RMAP_NODE, &ospf6_routemap_match_interface_cmd);
+ install_element (RMAP_NODE, &ospf6_routemap_no_match_interface_cmd);
+ install_element (RMAP_NODE, &ospf6_routemap_no_match_interface_val_cmd);
+
/* ASE Metric Type (e.g. Type-1/Type-2) */
install_element (RMAP_NODE, &ospf6_routemap_set_metric_type_cmd);
install_element (RMAP_NODE, &ospf6_routemap_no_set_metric_type_cmd);
diff --git a/ospf6d/ospf6_asbr.h b/ospf6d/ospf6_asbr.h
index 6deb93ef..72e49143 100644
--- a/ospf6d/ospf6_asbr.h
+++ b/ospf6d/ospf6_asbr.h
@@ -22,6 +22,13 @@
#ifndef OSPF6_ASBR_H
#define OSPF6_ASBR_H
+/* for struct ospf6_prefix */
+#include "ospf6_proto.h"
+/* for struct ospf6_lsa */
+#include "ospf6_lsa.h"
+/* for struct ospf6_route */
+#include "ospf6_route.h"
+
/* Debug option */
extern unsigned char conf_debug_ospf6_asbr;
#define OSPF6_DEBUG_ASBR_ON() \
@@ -41,9 +48,12 @@ struct ospf6_external_info
struct in6_addr forwarding;
/* u_int32_t tag; */
+
+ unsigned int ifindex;
};
/* AS-External-LSA */
+#define OSPF6_AS_EXTERNAL_LSA_MIN_SIZE 4U /* w/o IPv6 prefix */
struct ospf6_as_external_lsa
{
u_int32_t bits_metric;
diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c
index 236baf17..71aa6859 100644
--- a/ospf6d/ospf6_interface.c
+++ b/ospf6d/ospf6_interface.c
@@ -108,14 +108,14 @@ ospf6_interface_create (struct interface *ifp)
oi->neighbor_list = list_new ();
oi->neighbor_list->cmp = ospf6_neighbor_cmp;
oi->linklocal_addr = (struct in6_addr *) NULL;
- oi->instance_id = 0;
- oi->transdelay = 1;
- oi->priority = 1;
-
- oi->hello_interval = 10;
- oi->dead_interval = 40;
- oi->rxmt_interval = 5;
- oi->cost = 1;
+ oi->instance_id = OSPF6_INTERFACE_INSTANCE_ID;
+ oi->transdelay = OSPF6_INTERFACE_TRANSDELAY;
+ oi->priority = OSPF6_INTERFACE_PRIORITY;
+
+ oi->hello_interval = OSPF6_INTERFACE_HELLO_INTERVAL;
+ oi->dead_interval = OSPF6_INTERFACE_DEAD_INTERVAL;
+ oi->rxmt_interval = OSPF6_INTERFACE_RXMT_INTERVAL;
+ oi->cost = OSPF6_INTERFACE_COST;
oi->state = OSPF6_INTERFACE_DOWN;
oi->flag = 0;
oi->mtu_ignore = 0;
@@ -399,12 +399,12 @@ ospf6_interface_state_change (u_char next_state, struct ospf6_interface *oi)
prev_state == OSPF6_INTERFACE_BDR) &&
(next_state != OSPF6_INTERFACE_DR &&
next_state != OSPF6_INTERFACE_BDR))
- ospf6_leave_alldrouters (oi->interface->ifindex);
+ ospf6_sso (oi->interface->ifindex, &alldrouters6, IPV6_LEAVE_GROUP);
if ((prev_state != OSPF6_INTERFACE_DR &&
prev_state != OSPF6_INTERFACE_BDR) &&
(next_state == OSPF6_INTERFACE_DR ||
next_state == OSPF6_INTERFACE_BDR))
- ospf6_join_alldrouters (oi->interface->ifindex);
+ ospf6_sso (oi->interface->ifindex, &alldrouters6, IPV6_JOIN_GROUP);
OSPF6_ROUTER_LSA_SCHEDULE (oi->area);
if (next_state == OSPF6_INTERFACE_DOWN)
@@ -612,7 +612,7 @@ interface_up (struct thread *thread)
}
/* Join AllSPFRouters */
- ospf6_join_allspfrouters (oi->interface->ifindex);
+ ospf6_sso (oi->interface->ifindex, &allspfrouters6, IPV6_JOIN_GROUP);
/* Update interface route */
ospf6_interface_connected_route_update (oi->interface);
@@ -707,7 +707,7 @@ interface_down (struct thread *thread)
/* Leave AllSPFRouters */
if (oi->state > OSPF6_INTERFACE_DOWN)
- ospf6_leave_allspfrouters (oi->interface->ifindex);
+ ospf6_sso (oi->interface->ifindex, &allspfrouters6, IPV6_LEAVE_GROUP);
ospf6_interface_state_change (OSPF6_INTERFACE_DOWN, oi);
@@ -929,7 +929,7 @@ ALIAS (show_ipv6_ospf6_interface_ifname_prefix,
"Display connected prefixes to advertise\n"
OSPF6_ROUTE_ADDRESS_STR
OSPF6_ROUTE_PREFIX_STR
- "Dispaly details of the prefixes\n"
+ "Display details of the prefixes\n"
)
ALIAS (show_ipv6_ospf6_interface_ifname_prefix,
@@ -943,7 +943,7 @@ ALIAS (show_ipv6_ospf6_interface_ifname_prefix,
"Display connected prefixes to advertise\n"
OSPF6_ROUTE_PREFIX_STR
OSPF6_ROUTE_MATCH_STR
- "Dispaly details of the prefixes\n"
+ "Display details of the prefixes\n"
)
DEFUN (show_ipv6_ospf6_interface_prefix,
@@ -982,7 +982,7 @@ ALIAS (show_ipv6_ospf6_interface_prefix,
"Display connected prefixes to advertise\n"
OSPF6_ROUTE_ADDRESS_STR
OSPF6_ROUTE_PREFIX_STR
- "Dispaly details of the prefixes\n"
+ "Display details of the prefixes\n"
)
ALIAS (show_ipv6_ospf6_interface_prefix,
@@ -995,7 +995,7 @@ ALIAS (show_ipv6_ospf6_interface_prefix,
"Display connected prefixes to advertise\n"
OSPF6_ROUTE_PREFIX_STR
OSPF6_ROUTE_MATCH_STR
- "Dispaly details of the prefixes\n"
+ "Display details of the prefixes\n"
)
@@ -1522,23 +1522,36 @@ config_write_ospf6_interface (struct vty *vty)
if (ifp->desc)
vty_out (vty, " description %s%s", ifp->desc, VNL);
-
if (ifp->mtu6 != oi->ifmtu)
vty_out (vty, " ipv6 ospf6 ifmtu %d%s", oi->ifmtu, VNL);
- vty_out (vty, " ipv6 ospf6 cost %d%s",
- oi->cost, VNL);
- vty_out (vty, " ipv6 ospf6 hello-interval %d%s",
- oi->hello_interval, VNL);
- vty_out (vty, " ipv6 ospf6 dead-interval %d%s",
- oi->dead_interval, VNL);
- vty_out (vty, " ipv6 ospf6 retransmit-interval %d%s",
- oi->rxmt_interval, VNL);
- vty_out (vty, " ipv6 ospf6 priority %d%s",
- oi->priority, VNL);
- vty_out (vty, " ipv6 ospf6 transmit-delay %d%s",
- oi->transdelay, VNL);
- vty_out (vty, " ipv6 ospf6 instance-id %d%s",
- oi->instance_id, VNL);
+
+ if (oi->cost != OSPF6_INTERFACE_COST)
+ vty_out (vty, " ipv6 ospf6 cost %d%s",
+ oi->cost, VNL);
+
+ if (oi->hello_interval != OSPF6_INTERFACE_HELLO_INTERVAL)
+ vty_out (vty, " ipv6 ospf6 hello-interval %d%s",
+ oi->hello_interval, VNL);
+
+ if (oi->dead_interval != OSPF6_INTERFACE_DEAD_INTERVAL)
+ vty_out (vty, " ipv6 ospf6 dead-interval %d%s",
+ oi->dead_interval, VNL);
+
+ if (oi->rxmt_interval != OSPF6_INTERFACE_RXMT_INTERVAL)
+ vty_out (vty, " ipv6 ospf6 retransmit-interval %d%s",
+ oi->rxmt_interval, VNL);
+
+ if (oi->priority != OSPF6_INTERFACE_PRIORITY)
+ vty_out (vty, " ipv6 ospf6 priority %d%s",
+ oi->priority, VNL);
+
+ if (oi->transdelay != OSPF6_INTERFACE_TRANSDELAY)
+ vty_out (vty, " ipv6 ospf6 transmit-delay %d%s",
+ oi->transdelay, VNL);
+
+ if (oi->instance_id != OSPF6_INTERFACE_INSTANCE_ID)
+ vty_out (vty, " ipv6 ospf6 instance-id %d%s",
+ oi->instance_id, VNL);
if (oi->plist_name)
vty_out (vty, " ipv6 ospf6 advertise prefix-list %s%s",
diff --git a/ospf6d/ospf6_interface.h b/ospf6d/ospf6_interface.h
index cf758c07..2d1ff34d 100644
--- a/ospf6d/ospf6_interface.h
+++ b/ospf6d/ospf6_interface.h
@@ -124,6 +124,15 @@ extern const char *ospf6_interface_state_str[];
#define OSPF6_INTERFACE_DISABLE 0x01
#define OSPF6_INTERFACE_PASSIVE 0x02
+/* default values */
+#define OSPF6_INTERFACE_HELLO_INTERVAL 10
+#define OSPF6_INTERFACE_DEAD_INTERVAL 40
+#define OSPF6_INTERFACE_RXMT_INTERVAL 5
+#define OSPF6_INTERFACE_COST 1
+#define OSPF6_INTERFACE_PRIORITY 1
+#define OSPF6_INTERFACE_TRANSDELAY 1
+#define OSPF6_INTERFACE_INSTANCE_ID 0
+
/* Function Prototypes */
diff --git a/ospf6d/ospf6_intra.h b/ospf6d/ospf6_intra.h
index 31643fd8..3810174e 100644
--- a/ospf6d/ospf6_intra.h
+++ b/ospf6d/ospf6_intra.h
@@ -69,6 +69,7 @@ extern u_int32_t conf_debug_ospf6_brouter_specific_area_id;
conf_debug_ospf6_brouter_specific_area_id == (area_id))
/* Router-LSA */
+#define OSPF6_ROUTER_LSA_MIN_SIZE 4U
struct ospf6_router_lsa
{
u_char bits;
@@ -77,6 +78,7 @@ struct ospf6_router_lsa
};
/* Link State Description in Router-LSA */
+#define OSPF6_ROUTER_LSDESC_FIX_SIZE 16U
struct ospf6_router_lsdesc
{
u_char type;
@@ -105,6 +107,7 @@ struct ospf6_router_lsdesc
(((struct ospf6_router_lsdesc *)(x))->neighbor_router_id)
/* Network-LSA */
+#define OSPF6_NETWORK_LSA_MIN_SIZE 4U
struct ospf6_network_lsa
{
u_char reserved;
@@ -113,6 +116,7 @@ struct ospf6_network_lsa
};
/* Link State Description in Router-LSA */
+#define OSPF6_NETWORK_LSDESC_FIX_SIZE 4U
struct ospf6_network_lsdesc
{
u_int32_t router_id;
@@ -121,6 +125,7 @@ struct ospf6_network_lsdesc
(((struct ospf6_network_lsdesc *)(x))->router_id)
/* Link-LSA */
+#define OSPF6_LINK_LSA_MIN_SIZE 24U /* w/o 1st IPv6 prefix */
struct ospf6_link_lsa
{
u_char priority;
@@ -131,6 +136,7 @@ struct ospf6_link_lsa
};
/* Intra-Area-Prefix-LSA */
+#define OSPF6_INTRA_PREFIX_LSA_MIN_SIZE 12U /* w/o 1st IPv6 prefix */
struct ospf6_intra_prefix_lsa
{
u_int16_t prefix_num;
diff --git a/ospf6d/ospf6_lsa.c b/ospf6d/ospf6_lsa.c
index 588b9462..e65752d8 100644
--- a/ospf6d/ospf6_lsa.c
+++ b/ospf6d/ospf6_lsa.c
@@ -163,9 +163,19 @@ ospf6_lsa_is_changed (struct ospf6_lsa *lsa1,
return 1;
if (ntohs (lsa1->header->length) != ntohs (lsa2->header->length))
return 1;
+ /* Going beyond LSA headers to compare the payload only makes sense, when both LSAs aren't header-only. */
+ if (CHECK_FLAG (lsa1->flag, OSPF6_LSA_HEADERONLY) != CHECK_FLAG (lsa2->flag, OSPF6_LSA_HEADERONLY))
+ {
+ zlog_warn ("%s: only one of two (%s, %s) LSAs compared is header-only", __func__, lsa1->name, lsa2->name);
+ return 1;
+ }
+ if (CHECK_FLAG (lsa1->flag, OSPF6_LSA_HEADERONLY))
+ return 0;
length = OSPF6_LSA_SIZE (lsa1->header) - sizeof (struct ospf6_lsa_header);
- assert (length > 0);
+ /* Once upper layer verifies LSAs received, length underrun should become a warning. */
+ if (length <= 0)
+ return 0;
return memcmp (OSPF6_LSA_HEADER_END (lsa1->header),
OSPF6_LSA_HEADER_END (lsa2->header), length);
diff --git a/ospf6d/ospf6_lsa.h b/ospf6d/ospf6_lsa.h
index c1093cab..7d93f5cb 100644
--- a/ospf6d/ospf6_lsa.h
+++ b/ospf6d/ospf6_lsa.h
@@ -79,6 +79,7 @@
(ntohs (type) & OSPF6_LSTYPE_SCOPE_MASK)
/* LSA Header */
+#define OSPF6_LSA_HEADER_SIZE 20U
struct ospf6_lsa_header
{
u_int16_t age; /* LS age */
@@ -244,7 +245,6 @@ extern struct ospf6_lsa_handler *ospf6_get_lsa_handler (u_int16_t type);
extern void ospf6_lsa_init (void);
extern void ospf6_lsa_terminate (void);
-extern void ospf6_lsa_cmd_init (void);
extern int config_write_ospf6_debug_lsa (struct vty *vty);
extern void install_element_ospf6_debug_lsa (void);
diff --git a/ospf6d/ospf6_main.c b/ospf6d/ospf6_main.c
index 800fae4b..d3ef0a6a 100644
--- a/ospf6d/ospf6_main.c
+++ b/ospf6d/ospf6_main.c
@@ -34,8 +34,13 @@
#include "plist.h"
#include "privs.h"
#include "sigevent.h"
+#include "zclient.h"
#include "ospf6d.h"
+#include "ospf6_top.h"
+#include "ospf6_message.h"
+#include "ospf6_asbr.h"
+#include "ospf6_lsa.h"
/* Default configuration file name for ospf6d. */
#define OSPF6_DEFAULT_CONFIG "ospf6d.conf"
@@ -72,6 +77,7 @@ struct option longopts[] =
{ "daemon", no_argument, NULL, 'd'},
{ "config_file", required_argument, NULL, 'f'},
{ "pid_file", required_argument, NULL, 'i'},
+ { "socket", required_argument, NULL, 'z'},
{ "vty_addr", required_argument, NULL, 'A'},
{ "vty_port", required_argument, NULL, 'P'},
{ "user", required_argument, NULL, 'u'},
@@ -110,6 +116,7 @@ Daemon which manages OSPF version 3.\n\n\
-d, --daemon Runs in daemon mode\n\
-f, --config_file Set configuration file name\n\
-i, --pid_file Set process identifier file name\n\
+-z, --socket Set path of zebra socket\n\
-A, --vty_addr Set vty's bind address\n\
-P, --vty_port Set vty's port number\n\
-u, --user User to run as\n\
@@ -124,7 +131,7 @@ Report bugs to zebra@zebra.org\n", progname);
exit (status);
}
-static void
+static void __attribute__ ((noreturn))
ospf6_exit (int status)
{
extern struct ospf6 *ospf6;
@@ -173,6 +180,7 @@ static void
sigterm (void)
{
zlog_notice ("Terminating on signal SIGTERM");
+ ospf6_clean();
ospf6_exit (0);
}
@@ -226,7 +234,7 @@ main (int argc, char *argv[], char *envp[])
/* Command line argument treatment. */
while (1)
{
- opt = getopt_long (argc, argv, "df:i:hp:A:P:u:g:vC", longopts, 0);
+ opt = getopt_long (argc, argv, "df:i:z:hp:A:P:u:g:vC", longopts, 0);
if (opt == EOF)
break;
@@ -247,6 +255,9 @@ main (int argc, char *argv[], char *envp[])
case 'i':
pid_file = optarg;
break;
+ case 'z':
+ zclient_serv_path_set (optarg);
+ break;
case 'P':
/* Deal with atoi() returning 0 on failure, and ospf6d not
listening on ospf6d port... */
@@ -281,6 +292,13 @@ main (int argc, char *argv[], char *envp[])
}
}
+ if (geteuid () != 0)
+ {
+ errno = EPERM;
+ perror (progname);
+ exit (1);
+ }
+
/* thread master */
master = thread_master_create ();
diff --git a/ospf6d/ospf6_message.c b/ospf6d/ospf6_message.c
index 51933b76..01d61263 100644
--- a/ospf6d/ospf6_message.c
+++ b/ospf6d/ospf6_message.c
@@ -39,12 +39,55 @@
#include "ospf6_neighbor.h"
#include "ospf6_interface.h"
+/* for structures and macros ospf6_lsa_examin() needs */
+#include "ospf6_abr.h"
+#include "ospf6_asbr.h"
+#include "ospf6_intra.h"
+
#include "ospf6_flood.h"
#include "ospf6d.h"
+#include <netinet/ip6.h>
+
unsigned char conf_debug_ospf6_message[6] = {0x03, 0, 0, 0, 0, 0};
-const char *ospf6_message_type_str[] =
- { "Unknown", "Hello", "DbDesc", "LSReq", "LSUpdate", "LSAck" };
+static const struct message ospf6_message_type_str [] =
+{
+ { OSPF6_MESSAGE_TYPE_HELLO, "Hello" },
+ { OSPF6_MESSAGE_TYPE_DBDESC, "DbDesc" },
+ { OSPF6_MESSAGE_TYPE_LSREQ, "LSReq" },
+ { OSPF6_MESSAGE_TYPE_LSUPDATE, "LSUpdate" },
+ { OSPF6_MESSAGE_TYPE_LSACK, "LSAck" },
+};
+static const size_t ospf6_message_type_str_max =
+ sizeof (ospf6_message_type_str) / sizeof (ospf6_message_type_str[0]);
+
+/* Minimum (besides the standard OSPF packet header) lengths for OSPF
+ packets of particular types, offset is the "type" field. */
+const u_int16_t ospf6_packet_minlen[OSPF6_MESSAGE_TYPE_ALL] =
+{
+ 0,
+ OSPF6_HELLO_MIN_SIZE,
+ OSPF6_DB_DESC_MIN_SIZE,
+ OSPF6_LS_REQ_MIN_SIZE,
+ OSPF6_LS_UPD_MIN_SIZE,
+ OSPF6_LS_ACK_MIN_SIZE
+};
+
+/* Minimum (besides the standard LSA header) lengths for LSAs of particular
+ types, offset is the "LSA function code" portion of "LSA type" field. */
+const u_int16_t ospf6_lsa_minlen[OSPF6_LSTYPE_SIZE] =
+{
+ 0,
+ /* 0x2001 */ OSPF6_ROUTER_LSA_MIN_SIZE,
+ /* 0x2002 */ OSPF6_NETWORK_LSA_MIN_SIZE,
+ /* 0x2003 */ OSPF6_INTER_PREFIX_LSA_MIN_SIZE,
+ /* 0x2004 */ OSPF6_INTER_ROUTER_LSA_FIX_SIZE,
+ /* 0x4005 */ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE,
+ /* 0x2006 */ 0,
+ /* 0x2007 */ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE,
+ /* 0x0008 */ OSPF6_LINK_LSA_MIN_SIZE,
+ /* 0x2009 */ OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
+};
/* print functions */
@@ -93,8 +136,7 @@ ospf6_hello_print (struct ospf6_header *oh)
zlog_debug (" Neighbor: %s", neighbor);
}
- if (p != OSPF6_MESSAGE_END (oh))
- zlog_debug ("Trailing garbage exists");
+ assert (p == OSPF6_MESSAGE_END (oh));
}
void
@@ -126,8 +168,7 @@ ospf6_dbdesc_print (struct ospf6_header *oh)
p += sizeof (struct ospf6_lsa_header))
ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p);
- if (p != OSPF6_MESSAGE_END (oh))
- zlog_debug ("Trailing garbage exists");
+ assert (p == OSPF6_MESSAGE_END (oh));
}
void
@@ -150,8 +191,7 @@ ospf6_lsreq_print (struct ospf6_header *oh)
ospf6_lstype_name (e->type), id, adv_router);
}
- if (p != OSPF6_MESSAGE_END (oh))
- zlog_debug ("Trailing garbage exists");
+ assert (p == OSPF6_MESSAGE_END (oh));
}
void
@@ -176,35 +216,9 @@ ospf6_lsupdate_print (struct ospf6_header *oh)
p += OSPF6_LSA_SIZE (p))
{
ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p);
- if (OSPF6_LSA_SIZE (p) < sizeof (struct ospf6_lsa_header))
- {
- zlog_debug (" Malformed LSA length, quit printing");
- break;
- }
}
- if (p != OSPF6_MESSAGE_END (oh))
- {
- char buf[32];
-
- int num = 0;
- memset (buf, 0, sizeof (buf));
-
- zlog_debug (" Trailing garbage exists");
- while (p < OSPF6_MESSAGE_END (oh))
- {
- snprintf (buf, sizeof (buf), "%s %2x", buf, *p++);
- num++;
- if (num == 8)
- {
- zlog_debug (" %s", buf);
- memset (buf, 0, sizeof (buf));
- num = 0;
- }
- }
- if (num)
- zlog_debug (" %s", buf);
- }
+ assert (p == OSPF6_MESSAGE_END (oh));
}
void
@@ -220,56 +234,7 @@ ospf6_lsack_print (struct ospf6_header *oh)
p += sizeof (struct ospf6_lsa_header))
ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p);
- if (p != OSPF6_MESSAGE_END (oh))
- zlog_debug ("Trailing garbage exists");
-}
-
-/* Receive function */
-#define MSG_OK 0
-#define MSG_NG 1
-static int
-ospf6_header_examin (struct in6_addr *src, struct in6_addr *dst,
- struct ospf6_interface *oi, struct ospf6_header *oh)
-{
- u_char type;
- type = OSPF6_MESSAGE_TYPE_CANONICAL (oh->type);
-
- /* version check */
- if (oh->version != OSPFV3_VERSION)
- {
- if (IS_OSPF6_DEBUG_MESSAGE (type, RECV))
- zlog_debug ("Message with unknown version");
- return MSG_NG;
- }
-
- /* Area-ID check */
- if (oh->area_id != oi->area->area_id)
- {
- if (oh->area_id == BACKBONE_AREA_ID)
- {
- if (IS_OSPF6_DEBUG_MESSAGE (type, RECV))
- zlog_debug ("Message may be via Virtual Link: not supported");
- return MSG_NG;
- }
-
- if (IS_OSPF6_DEBUG_MESSAGE (type, RECV))
- zlog_debug ("Area-ID mismatch");
- return MSG_NG;
- }
-
- /* Instance-ID check */
- if (oh->instance_id != oi->instance_id)
- {
- if (IS_OSPF6_DEBUG_MESSAGE (type, RECV))
- zlog_debug ("Instance-ID mismatch");
- return MSG_NG;
- }
-
- /* Router-ID check */
- if (oh->router_id == oi->area->ospf6->router_id)
- zlog_warn ("Detect duplicate Router-ID");
-
- return MSG_OK;
+ assert (p == OSPF6_MESSAGE_END (oh));
}
static void
@@ -283,9 +248,6 @@ ospf6_hello_recv (struct in6_addr *src, struct in6_addr *dst,
int neighborchange = 0;
int backupseen = 0;
- if (ospf6_header_examin (src, dst, oi, oh) != MSG_OK)
- return;
-
hello = (struct ospf6_hello *)
((caddr_t) oh + sizeof (struct ospf6_header));
@@ -339,11 +301,7 @@ ospf6_hello_recv (struct in6_addr *src, struct in6_addr *dst,
twoway++;
}
- if (p != OSPF6_MESSAGE_END (oh))
- {
- if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
- zlog_debug ("Trailing garbage ignored");
- }
+ assert (p == OSPF6_MESSAGE_END (oh));
/* RouterPriority check */
if (on->priority != hello->priority)
@@ -576,11 +534,7 @@ ospf6_dbdesc_recv_master (struct ospf6_header *oh,
}
}
- if (p != OSPF6_MESSAGE_END (oh))
- {
- if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
- zlog_debug ("Trailing garbage ignored");
- }
+ assert (p == OSPF6_MESSAGE_END (oh));
/* Increment sequence number */
on->dbdesc_seqnum ++;
@@ -788,11 +742,7 @@ ospf6_dbdesc_recv_slave (struct ospf6_header *oh,
ospf6_lsa_delete (his);
}
- if (p != OSPF6_MESSAGE_END (oh))
- {
- if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
- zlog_debug ("Trailing garbage ignored");
- }
+ assert (p == OSPF6_MESSAGE_END (oh));
/* Set sequence number to Master's */
on->dbdesc_seqnum = ntohl (dbdesc->seqnum);
@@ -817,9 +767,6 @@ ospf6_dbdesc_recv (struct in6_addr *src, struct in6_addr *dst,
struct ospf6_neighbor *on;
struct ospf6_dbdesc *dbdesc;
- if (ospf6_header_examin (src, dst, oi, oh) != MSG_OK)
- return;
-
on = ospf6_neighbor_lookup (oh->router_id, oi);
if (on == NULL)
{
@@ -869,9 +816,6 @@ ospf6_lsreq_recv (struct in6_addr *src, struct in6_addr *dst,
struct ospf6_lsdb *lsdb = NULL;
struct ospf6_lsa *lsa;
- if (ospf6_header_examin (src, dst, oi, oh) != MSG_OK)
- return;
-
on = ospf6_neighbor_lookup (oh->router_id, oi);
if (on == NULL)
{
@@ -934,11 +878,7 @@ ospf6_lsreq_recv (struct in6_addr *src, struct in6_addr *dst,
ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->lsupdate_list);
}
- if (p != OSPF6_MESSAGE_END (oh))
- {
- if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
- zlog_debug ("Trailing garbage ignored");
- }
+ assert (p == OSPF6_MESSAGE_END (oh));
/* schedule send lsupdate */
THREAD_OFF (on->thread_send_lsupdate);
@@ -946,18 +886,441 @@ ospf6_lsreq_recv (struct in6_addr *src, struct in6_addr *dst,
thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
}
+/* Verify, that the specified memory area contains exactly N valid IPv6
+ prefixes as specified by RFC5340, A.4.1. */
+static unsigned
+ospf6_prefixes_examin
+(
+ struct ospf6_prefix *current, /* start of buffer */
+ unsigned length,
+ const u_int32_t req_num_pfxs /* always compared with the actual number of prefixes */
+)
+{
+ u_char requested_pfx_bytes;
+ u_int32_t real_num_pfxs = 0;
+
+ while (length)
+ {
+ if (length < OSPF6_PREFIX_MIN_SIZE)
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
+ zlog_debug ("%s: undersized IPv6 prefix header", __func__);
+ return MSG_NG;
+ }
+ /* safe to look deeper */
+ if (current->prefix_length > IPV6_MAX_BITLEN)
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
+ zlog_debug ("%s: invalid PrefixLength (%u bits)", __func__, current->prefix_length);
+ return MSG_NG;
+ }
+ /* covers both fixed- and variable-sized fields */
+ requested_pfx_bytes = OSPF6_PREFIX_MIN_SIZE + OSPF6_PREFIX_SPACE (current->prefix_length);
+ if (requested_pfx_bytes > length)
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
+ zlog_debug ("%s: undersized IPv6 prefix", __func__);
+ return MSG_NG;
+ }
+ /* next prefix */
+ length -= requested_pfx_bytes;
+ current = (struct ospf6_prefix *) ((caddr_t) current + requested_pfx_bytes);
+ real_num_pfxs++;
+ }
+ if (real_num_pfxs != req_num_pfxs)
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
+ zlog_debug ("%s: IPv6 prefix number mismatch (%u required, %u real)",
+ __func__, req_num_pfxs, real_num_pfxs);
+ return MSG_NG;
+ }
+ return MSG_OK;
+}
+
+/* Verify an LSA to have a valid length and dispatch further (where
+ appropriate) to check if the contents, including nested IPv6 prefixes,
+ is properly sized/aligned within the LSA. Note that this function gets
+ LSA type in network byte order, uses in host byte order and passes to
+ ospf6_lstype_name() in network byte order again. */
+static unsigned
+ospf6_lsa_examin (struct ospf6_lsa_header *lsah, const u_int16_t lsalen, const u_char headeronly)
+{
+ struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
+ struct ospf6_as_external_lsa *as_external_lsa;
+ struct ospf6_link_lsa *link_lsa;
+ unsigned exp_length;
+ u_int8_t ltindex;
+ u_int16_t lsatype;
+
+ /* In case an additional minimum length constraint is defined for current
+ LSA type, make sure that this constraint is met. */
+ lsatype = ntohs (lsah->type);
+ ltindex = lsatype & OSPF6_LSTYPE_FCODE_MASK;
+ if
+ (
+ ltindex < OSPF6_LSTYPE_SIZE &&
+ ospf6_lsa_minlen[ltindex] &&
+ lsalen < ospf6_lsa_minlen[ltindex] + OSPF6_LSA_HEADER_SIZE
+ )
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
+ zlog_debug ("%s: undersized (%u B) LSA", __func__, lsalen);
+ return MSG_NG;
+ }
+ switch (lsatype)
+ {
+ case OSPF6_LSTYPE_ROUTER:
+ /* RFC5340 A.4.3, LSA header + OSPF6_ROUTER_LSA_MIN_SIZE bytes followed
+ by N>=0 interface descriptions. */
+ if ((lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_ROUTER_LSA_MIN_SIZE) % OSPF6_ROUTER_LSDESC_FIX_SIZE)
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
+ zlog_debug ("%s: interface description alignment error", __func__);
+ return MSG_NG;
+ }
+ break;
+ case OSPF6_LSTYPE_NETWORK:
+ /* RFC5340 A.4.4, LSA header + OSPF6_NETWORK_LSA_MIN_SIZE bytes
+ followed by N>=0 attached router descriptions. */
+ if ((lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_NETWORK_LSA_MIN_SIZE) % OSPF6_NETWORK_LSDESC_FIX_SIZE)
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
+ zlog_debug ("%s: router description alignment error", __func__);
+ return MSG_NG;
+ }
+ break;
+ case OSPF6_LSTYPE_INTER_PREFIX:
+ /* RFC5340 A.4.5, LSA header + OSPF6_INTER_PREFIX_LSA_MIN_SIZE bytes
+ followed by 3-4 fields of a single IPv6 prefix. */
+ if (headeronly)
+ break;
+ return ospf6_prefixes_examin
+ (
+ (struct ospf6_prefix *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE + OSPF6_INTER_PREFIX_LSA_MIN_SIZE),
+ lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_INTER_PREFIX_LSA_MIN_SIZE,
+ 1
+ );
+ case OSPF6_LSTYPE_INTER_ROUTER:
+ /* RFC5340 A.4.6, fixed-size LSA. */
+ if (lsalen > OSPF6_LSA_HEADER_SIZE + OSPF6_INTER_ROUTER_LSA_FIX_SIZE)
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
+ zlog_debug ("%s: oversized (%u B) LSA", __func__, lsalen);
+ return MSG_NG;
+ }
+ break;
+ case OSPF6_LSTYPE_AS_EXTERNAL: /* RFC5340 A.4.7, same as A.4.8. */
+ case OSPF6_LSTYPE_TYPE_7:
+ /* RFC5340 A.4.8, LSA header + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE bytes
+ followed by 3-4 fields of IPv6 prefix and 3 conditional LSA fields:
+ 16 bytes of forwarding address, 4 bytes of external route tag,
+ 4 bytes of referenced link state ID. */
+ if (headeronly)
+ break;
+ as_external_lsa = (struct ospf6_as_external_lsa *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE);
+ exp_length = OSPF6_LSA_HEADER_SIZE + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE;
+ /* To find out if the last optional field (Referenced Link State ID) is
+ assumed in this LSA, we need to access fixed fields of the IPv6
+ prefix before ospf6_prefix_examin() confirms its sizing. */
+ if (exp_length + OSPF6_PREFIX_MIN_SIZE > lsalen)
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
+ zlog_debug ("%s: undersized (%u B) LSA header", __func__, lsalen);
+ return MSG_NG;
+ }
+ /* forwarding address */
+ if (CHECK_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F))
+ exp_length += 16;
+ /* external route tag */
+ if (CHECK_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T))
+ exp_length += 4;
+ /* referenced link state ID */
+ if (as_external_lsa->prefix.u._prefix_referenced_lstype)
+ exp_length += 4;
+ /* All the fixed-size fields (mandatory and optional) must fit. I.e.,
+ this check does not include any IPv6 prefix fields. */
+ if (exp_length > lsalen)
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
+ zlog_debug ("%s: undersized (%u B) LSA header", __func__, lsalen);
+ return MSG_NG;
+ }
+ /* The last call completely covers the remainder (IPv6 prefix). */
+ return ospf6_prefixes_examin
+ (
+ (struct ospf6_prefix *) ((caddr_t) as_external_lsa + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE),
+ lsalen - exp_length,
+ 1
+ );
+ case OSPF6_LSTYPE_LINK:
+ /* RFC5340 A.4.9, LSA header + OSPF6_LINK_LSA_MIN_SIZE bytes followed
+ by N>=0 IPv6 prefix blocks (with N declared beforehand). */
+ if (headeronly)
+ break;
+ link_lsa = (struct ospf6_link_lsa *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE);
+ return ospf6_prefixes_examin
+ (
+ (struct ospf6_prefix *) ((caddr_t) link_lsa + OSPF6_LINK_LSA_MIN_SIZE),
+ lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_LINK_LSA_MIN_SIZE,
+ ntohl (link_lsa->prefix_num) /* 32 bits */
+ );
+ case OSPF6_LSTYPE_INTRA_PREFIX:
+ /* RFC5340 A.4.10, LSA header + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE bytes
+ followed by N>=0 IPv6 prefixes (with N declared beforehand). */
+ if (headeronly)
+ break;
+ intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE);
+ return ospf6_prefixes_examin
+ (
+ (struct ospf6_prefix *) ((caddr_t) intra_prefix_lsa + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE),
+ lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_INTRA_PREFIX_LSA_MIN_SIZE,
+ ntohs (intra_prefix_lsa->prefix_num) /* 16 bits */
+ );
+ }
+ /* No additional validation is possible for unknown LSA types, which are
+ themselves valid in OPSFv3, hence the default decision is to accept. */
+ return MSG_OK;
+}
+
+/* Verify if the provided input buffer is a valid sequence of LSAs. This
+ includes verification of LSA blocks length/alignment and dispatching
+ of deeper-level checks. */
+static unsigned
+ospf6_lsaseq_examin
+(
+ struct ospf6_lsa_header *lsah, /* start of buffered data */
+ size_t length,
+ const u_char headeronly,
+ /* When declared_num_lsas is not 0, compare it to the real number of LSAs
+ and treat the difference as an error. */
+ const u_int32_t declared_num_lsas
+)
+{
+ u_int32_t counted_lsas = 0;
+
+ while (length)
+ {
+ u_int16_t lsalen;
+ if (length < OSPF6_LSA_HEADER_SIZE)
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
+ zlog_debug ("%s: undersized (%zu B) trailing (#%u) LSA header",
+ __func__, length, counted_lsas);
+ return MSG_NG;
+ }
+ /* save on ntohs() calls here and in the LSA validator */
+ lsalen = OSPF6_LSA_SIZE (lsah);
+ if (lsalen < OSPF6_LSA_HEADER_SIZE)
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
+ zlog_debug ("%s: malformed LSA header #%u, declared length is %u B",
+ __func__, counted_lsas, lsalen);
+ return MSG_NG;
+ }
+ if (headeronly)
+ {
+ /* less checks here and in ospf6_lsa_examin() */
+ if (MSG_OK != ospf6_lsa_examin (lsah, lsalen, 1))
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
+ zlog_debug ("%s: anomaly in header-only %s LSA #%u", __func__,
+ ospf6_lstype_name (lsah->type), counted_lsas);
+ return MSG_NG;
+ }
+ lsah = (struct ospf6_lsa_header *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE);
+ length -= OSPF6_LSA_HEADER_SIZE;
+ }
+ else
+ {
+ /* make sure the input buffer is deep enough before further checks */
+ if (lsalen > length)
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
+ zlog_debug ("%s: anomaly in %s LSA #%u: declared length is %u B, buffered length is %zu B",
+ __func__, ospf6_lstype_name (lsah->type), counted_lsas, lsalen, length);
+ return MSG_NG;
+ }
+ if (MSG_OK != ospf6_lsa_examin (lsah, lsalen, 0))
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
+ zlog_debug ("%s: anomaly in %s LSA #%u", __func__,
+ ospf6_lstype_name (lsah->type), counted_lsas);
+ return MSG_NG;
+ }
+ lsah = (struct ospf6_lsa_header *) ((caddr_t) lsah + lsalen);
+ length -= lsalen;
+ }
+ counted_lsas++;
+ }
+
+ if (declared_num_lsas && counted_lsas != declared_num_lsas)
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
+ zlog_debug ("%s: #LSAs declared (%u) does not match actual (%u)",
+ __func__, declared_num_lsas, counted_lsas);
+ return MSG_NG;
+ }
+ return MSG_OK;
+}
+
+/* Verify a complete OSPF packet for proper sizing/alignment. */
+static unsigned
+ospf6_packet_examin (struct ospf6_header *oh, const unsigned bytesonwire)
+{
+ struct ospf6_lsupdate *lsupd;
+ unsigned test;
+
+ /* length, 1st approximation */
+ if (bytesonwire < OSPF6_HEADER_SIZE)
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
+ zlog_debug ("%s: undersized (%u B) packet", __func__, bytesonwire);
+ return MSG_NG;
+ }
+ /* Now it is safe to access header fields. */
+ if (bytesonwire != ntohs (oh->length))
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
+ zlog_debug ("%s: packet length error (%u real, %u declared)",
+ __func__, bytesonwire, ntohs (oh->length));
+ return MSG_NG;
+ }
+ /* version check */
+ if (oh->version != OSPFV3_VERSION)
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
+ zlog_debug ("%s: invalid (%u) protocol version", __func__, oh->version);
+ return MSG_NG;
+ }
+ /* length, 2nd approximation */
+ if
+ (
+ oh->type < OSPF6_MESSAGE_TYPE_ALL &&
+ ospf6_packet_minlen[oh->type] &&
+ bytesonwire < OSPF6_HEADER_SIZE + ospf6_packet_minlen[oh->type]
+ )
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
+ zlog_debug ("%s: undersized (%u B) %s packet", __func__,
+ bytesonwire, LOOKUP (ospf6_message_type_str, oh->type));
+ return MSG_NG;
+ }
+ /* type-specific deeper validation */
+ switch (oh->type)
+ {
+ case OSPF6_MESSAGE_TYPE_HELLO:
+ /* RFC5340 A.3.2, packet header + OSPF6_HELLO_MIN_SIZE bytes followed
+ by N>=0 router-IDs. */
+ if (0 == (bytesonwire - OSPF6_HEADER_SIZE - OSPF6_HELLO_MIN_SIZE) % 4)
+ return MSG_OK;
+ if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
+ zlog_debug ("%s: alignment error in %s packet",
+ __func__, LOOKUP (ospf6_message_type_str, oh->type));
+ return MSG_NG;
+ case OSPF6_MESSAGE_TYPE_DBDESC:
+ /* RFC5340 A.3.3, packet header + OSPF6_DB_DESC_MIN_SIZE bytes followed
+ by N>=0 header-only LSAs. */
+ test = ospf6_lsaseq_examin
+ (
+ (struct ospf6_lsa_header *) ((caddr_t) oh + OSPF6_HEADER_SIZE + OSPF6_DB_DESC_MIN_SIZE),
+ bytesonwire - OSPF6_HEADER_SIZE - OSPF6_DB_DESC_MIN_SIZE,
+ 1,
+ 0
+ );
+ break;
+ case OSPF6_MESSAGE_TYPE_LSREQ:
+ /* RFC5340 A.3.4, packet header + N>=0 LS description blocks. */
+ if (0 == (bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_REQ_MIN_SIZE) % OSPF6_LSREQ_LSDESC_FIX_SIZE)
+ return MSG_OK;
+ if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
+ zlog_debug ("%s: alignment error in %s packet",
+ __func__, LOOKUP (ospf6_message_type_str, oh->type));
+ return MSG_NG;
+ case OSPF6_MESSAGE_TYPE_LSUPDATE:
+ /* RFC5340 A.3.5, packet header + OSPF6_LS_UPD_MIN_SIZE bytes followed
+ by N>=0 full LSAs (with N declared beforehand). */
+ lsupd = (struct ospf6_lsupdate *) ((caddr_t) oh + OSPF6_HEADER_SIZE);
+ test = ospf6_lsaseq_examin
+ (
+ (struct ospf6_lsa_header *) ((caddr_t) lsupd + OSPF6_LS_UPD_MIN_SIZE),
+ bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_UPD_MIN_SIZE,
+ 0,
+ ntohl (lsupd->lsa_number) /* 32 bits */
+ );
+ break;
+ case OSPF6_MESSAGE_TYPE_LSACK:
+ /* RFC5340 A.3.6, packet header + N>=0 header-only LSAs. */
+ test = ospf6_lsaseq_examin
+ (
+ (struct ospf6_lsa_header *) ((caddr_t) oh + OSPF6_HEADER_SIZE + OSPF6_LS_ACK_MIN_SIZE),
+ bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_ACK_MIN_SIZE,
+ 1,
+ 0
+ );
+ break;
+ default:
+ if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
+ zlog_debug ("%s: invalid (%u) message type", __func__, oh->type);
+ return MSG_NG;
+ }
+ if (test != MSG_OK && IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
+ zlog_debug ("%s: anomaly in %s packet", __func__, LOOKUP (ospf6_message_type_str, oh->type));
+ return test;
+}
+
+/* Verify particular fields of otherwise correct received OSPF packet to
+ meet the requirements of RFC. */
+static int
+ospf6_rxpacket_examin (struct ospf6_interface *oi, struct ospf6_header *oh, const unsigned bytesonwire)
+{
+ char buf[2][INET_ADDRSTRLEN];
+
+ if (MSG_OK != ospf6_packet_examin (oh, bytesonwire))
+ return MSG_NG;
+
+ /* Area-ID check */
+ if (oh->area_id != oi->area->area_id)
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ {
+ if (oh->area_id == BACKBONE_AREA_ID)
+ zlog_debug ("%s: Message may be via Virtual Link: not supported", __func__);
+ else
+ zlog_debug
+ (
+ "%s: Area-ID mismatch (my %s, rcvd %s)", __func__,
+ inet_ntop (AF_INET, &oi->area->area_id, buf[0], INET_ADDRSTRLEN),
+ inet_ntop (AF_INET, &oh->area_id, buf[1], INET_ADDRSTRLEN)
+ );
+ }
+ return MSG_NG;
+ }
+
+ /* Instance-ID check */
+ if (oh->instance_id != oi->instance_id)
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_debug ("%s: Instance-ID mismatch (my %u, rcvd %u)", __func__, oi->instance_id, oh->instance_id);
+ return MSG_NG;
+ }
+
+ /* Router-ID check */
+ if (oh->router_id == oi->area->ospf6->router_id)
+ {
+ zlog_warn ("%s: Duplicate Router-ID (%s)", __func__, inet_ntop (AF_INET, &oh->router_id, buf[0], INET_ADDRSTRLEN));
+ return MSG_NG;
+ }
+ return MSG_OK;
+}
+
static void
ospf6_lsupdate_recv (struct in6_addr *src, struct in6_addr *dst,
struct ospf6_interface *oi, struct ospf6_header *oh)
{
struct ospf6_neighbor *on;
struct ospf6_lsupdate *lsupdate;
- unsigned long num;
char *p;
- if (ospf6_header_examin (src, dst, oi, oh) != MSG_OK)
- return;
-
on = ospf6_neighbor_lookup (oh->router_id, oi);
if (on == NULL)
{
@@ -978,37 +1341,16 @@ ospf6_lsupdate_recv (struct in6_addr *src, struct in6_addr *dst,
lsupdate = (struct ospf6_lsupdate *)
((caddr_t) oh + sizeof (struct ospf6_header));
- num = ntohl (lsupdate->lsa_number);
-
/* Process LSAs */
for (p = (char *) ((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
p < OSPF6_MESSAGE_END (oh) &&
p + OSPF6_LSA_SIZE (p) <= OSPF6_MESSAGE_END (oh);
p += OSPF6_LSA_SIZE (p))
{
- if (num == 0)
- break;
- if (OSPF6_LSA_SIZE (p) < sizeof (struct ospf6_lsa_header))
- {
- if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
- zlog_debug ("Malformed LSA length, quit processing");
- break;
- }
-
ospf6_receive_lsa (on, (struct ospf6_lsa_header *) p);
- num--;
}
- if (num != 0)
- {
- if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
- zlog_debug ("Malformed LSA number or LSA length");
- }
- if (p != OSPF6_MESSAGE_END (oh))
- {
- if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
- zlog_debug ("Trailing garbage ignored");
- }
+ assert (p == OSPF6_MESSAGE_END (oh));
/* RFC2328 Section 10.9: When the neighbor responds to these requests
with the proper Link State Update packet(s), the Link state request
@@ -1035,8 +1377,6 @@ ospf6_lsack_recv (struct in6_addr *src, struct in6_addr *dst,
struct ospf6_lsdb *lsdb = NULL;
assert (oh->type == OSPF6_MESSAGE_TYPE_LSACK);
- if (ospf6_header_examin (src, dst, oi, oh) != MSG_OK)
- return;
on = ospf6_neighbor_lookup (oh->router_id, oi);
if (on == NULL)
@@ -1126,11 +1466,7 @@ ospf6_lsack_recv (struct in6_addr *src, struct in6_addr *dst,
ospf6_lsa_delete (his);
}
- if (p != OSPF6_MESSAGE_END (oh))
- {
- if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
- zlog_debug ("Trailing garbage ignored");
- }
+ assert (p == OSPF6_MESSAGE_END (oh));
}
static u_char *recvbuf = NULL;
@@ -1219,11 +1555,6 @@ ospf6_receive (struct thread *thread)
zlog_err ("Excess message read");
return 0;
}
- else if (len < sizeof (struct ospf6_header))
- {
- zlog_err ("Deficient message read");
- return 0;
- }
oi = ospf6_interface_lookup_by_ifindex (ifindex);
if (oi == NULL || oi->area == NULL)
@@ -1231,8 +1562,22 @@ ospf6_receive (struct thread *thread)
zlog_debug ("Message received on disabled interface");
return 0;
}
+ if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_PASSIVE))
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
+ zlog_debug ("%s: Ignore message on passive interface %s",
+ __func__, oi->interface->name);
+ return 0;
+ }
oh = (struct ospf6_header *) recvbuf;
+ if (ospf6_rxpacket_examin (oi, oh, len) != MSG_OK)
+ return 0;
+
+ /* Being here means, that no sizing/alignment issues were detected in
+ the input packet. This renders the additional checks performed below
+ and also in the type-specific dispatching functions a dead code,
+ which can be dismissed in a cleanup-focused review round later. */
/* Log */
if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
@@ -1240,11 +1585,9 @@ ospf6_receive (struct thread *thread)
inet_ntop (AF_INET6, &src, srcname, sizeof (srcname));
inet_ntop (AF_INET6, &dst, dstname, sizeof (dstname));
zlog_debug ("%s received on %s",
- OSPF6_MESSAGE_TYPE_NAME (oh->type), oi->interface->name);
+ LOOKUP (ospf6_message_type_str, oh->type), oi->interface->name);
zlog_debug (" src: %s", srcname);
zlog_debug (" dst: %s", dstname);
- if (len != ntohs (oh->length))
- zlog_debug ("Message length does not match actually received: %d", len);
switch (oh->type)
{
@@ -1264,19 +1607,10 @@ ospf6_receive (struct thread *thread)
ospf6_lsack_print (oh);
break;
default:
- zlog_debug ("Unknown message");
- break;
+ assert (0);
}
}
- if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_PASSIVE))
- {
- if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
- zlog_debug ("Ignore message on passive interface %s",
- oi->interface->name);
- return 0;
- }
-
switch (oh->type)
{
case OSPF6_MESSAGE_TYPE_HELLO:
@@ -1300,9 +1634,7 @@ ospf6_receive (struct thread *thread)
break;
default:
- if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
- zlog_debug ("Unknown message");
- break;
+ assert (0);
}
return 0;
@@ -1341,7 +1673,7 @@ ospf6_send (struct in6_addr *src, struct in6_addr *dst,
else
memset (srcname, 0, sizeof (srcname));
zlog_debug ("%s send on %s",
- OSPF6_MESSAGE_TYPE_NAME (oh->type), oi->interface->name);
+ LOOKUP (ospf6_message_type_str, oh->type), oi->interface->name);
zlog_debug (" src: %s", srcname);
zlog_debug (" dst: %s", dstname);
@@ -1375,6 +1707,13 @@ ospf6_send (struct in6_addr *src, struct in6_addr *dst,
zlog_err ("Could not send entire message");
}
+static uint32_t
+ospf6_packet_max(struct ospf6_interface *oi)
+{
+ assert (oi->ifmtu > sizeof (struct ip6_hdr));
+ return oi->ifmtu - (sizeof (struct ip6_hdr));
+}
+
int
ospf6_hello_send (struct thread *thread)
{
@@ -1421,7 +1760,7 @@ ospf6_hello_send (struct thread *thread)
if (on->state < OSPF6_NEIGHBOR_INIT)
continue;
- if (p - sendbuf + sizeof (u_int32_t) > oi->ifmtu)
+ if (p - sendbuf + sizeof (u_int32_t) > ospf6_packet_max(oi))
{
if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_HELLO, SEND))
zlog_debug ("sending Hello message: exceeds I/F MTU");
@@ -1497,7 +1836,7 @@ ospf6_dbdesc_send (struct thread *thread)
/* MTU check */
if (p - sendbuf + sizeof (struct ospf6_lsa_header) >
- on->ospf6_if->ifmtu)
+ ospf6_packet_max(on->ospf6_if))
{
ospf6_lsa_unlock (lsa);
break;
@@ -1531,7 +1870,7 @@ ospf6_dbdesc_send_newone (struct thread *thread)
for (lsa = ospf6_lsdb_head (on->summary_list); lsa;
lsa = ospf6_lsdb_next (lsa))
{
- if (size + sizeof (struct ospf6_lsa_header) > on->ospf6_if->ifmtu)
+ if (size + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(on->ospf6_if))
{
ospf6_lsa_unlock (lsa);
break;
@@ -1598,7 +1937,7 @@ ospf6_lsreq_send (struct thread *thread)
lsa = ospf6_lsdb_next (lsa))
{
/* MTU check */
- if (p - sendbuf + sizeof (struct ospf6_lsreq_entry) > on->ospf6_if->ifmtu)
+ if (p - sendbuf + sizeof (struct ospf6_lsreq_entry) > ospf6_packet_max(on->ospf6_if))
{
ospf6_lsa_unlock (lsa);
break;
@@ -1667,7 +2006,7 @@ ospf6_lsupdate_send_neighbor (struct thread *thread)
{
/* MTU check */
if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header))
- > on->ospf6_if->ifmtu)
+ > ospf6_packet_max(on->ospf6_if))
{
ospf6_lsa_unlock (lsa);
break;
@@ -1687,7 +2026,7 @@ ospf6_lsupdate_send_neighbor (struct thread *thread)
{
/* MTU check */
if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header))
- > on->ospf6_if->ifmtu)
+ > ospf6_packet_max(on->ospf6_if))
{
ospf6_lsa_unlock (lsa);
break;
@@ -1760,7 +2099,7 @@ ospf6_lsupdate_send_interface (struct thread *thread)
{
/* MTU check */
if ( (p - sendbuf + ((unsigned int)OSPF6_LSA_SIZE (lsa->header)))
- > oi->ifmtu)
+ > ospf6_packet_max(oi))
{
ospf6_lsa_unlock (lsa);
break;
@@ -1827,7 +2166,7 @@ ospf6_lsack_send_neighbor (struct thread *thread)
lsa = ospf6_lsdb_next (lsa))
{
/* MTU check */
- if (p - sendbuf + sizeof (struct ospf6_lsa_header) > on->ospf6_if->ifmtu)
+ if (p - sendbuf + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(on->ospf6_if))
{
/* if we run out of packet size/space here,
better to try again soon. */
@@ -1887,7 +2226,7 @@ ospf6_lsack_send_interface (struct thread *thread)
lsa = ospf6_lsdb_next (lsa))
{
/* MTU check */
- if (p - sendbuf + sizeof (struct ospf6_lsa_header) > oi->ifmtu)
+ if (p - sendbuf + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(oi))
{
/* if we run out of packet size/space here,
better to try again soon. */
diff --git a/ospf6d/ospf6_message.h b/ospf6d/ospf6_message.h
index c72f0af4..b085a967 100644
--- a/ospf6d/ospf6_message.h
+++ b/ospf6d/ospf6_message.h
@@ -44,14 +44,8 @@ extern unsigned char conf_debug_ospf6_message[];
#define OSPF6_MESSAGE_TYPE_LSACK 0x5 /* Flooding acknowledgment */
#define OSPF6_MESSAGE_TYPE_ALL 0x6 /* For debug option */
-#define OSPF6_MESSAGE_TYPE_CANONICAL(T) \
- ((T) > OSPF6_MESSAGE_TYPE_LSACK ? OSPF6_MESSAGE_TYPE_UNKNOWN : (T))
-
-extern const char *ospf6_message_type_str[];
-#define OSPF6_MESSAGE_TYPE_NAME(T) \
- (ospf6_message_type_str[ OSPF6_MESSAGE_TYPE_CANONICAL (T) ])
-
/* OSPFv3 packet header */
+#define OSPF6_HEADER_SIZE 16U
struct ospf6_header
{
u_char version;
@@ -67,6 +61,7 @@ struct ospf6_header
#define OSPF6_MESSAGE_END(H) ((caddr_t) (H) + ntohs ((H)->length))
/* Hello */
+#define OSPF6_HELLO_MIN_SIZE 20U
struct ospf6_hello
{
u_int32_t interface_id;
@@ -80,6 +75,7 @@ struct ospf6_hello
};
/* Database Description */
+#define OSPF6_DB_DESC_MIN_SIZE 12U
struct ospf6_dbdesc
{
u_char reserved1;
@@ -96,7 +92,9 @@ struct ospf6_dbdesc
#define OSPF6_DBDESC_IBIT (0x04) /* initial bit */
/* Link State Request */
+#define OSPF6_LS_REQ_MIN_SIZE 0U
/* It is just a sequence of entries below */
+#define OSPF6_LSREQ_LSDESC_FIX_SIZE 12U
struct ospf6_lsreq_entry
{
u_int16_t reserved; /* Must Be Zero */
@@ -106,6 +104,7 @@ struct ospf6_lsreq_entry
};
/* Link State Update */
+#define OSPF6_LS_UPD_MIN_SIZE 4U
struct ospf6_lsupdate
{
u_int32_t lsa_number;
@@ -113,6 +112,7 @@ struct ospf6_lsupdate
};
/* Link State Acknowledgement */
+#define OSPF6_LS_ACK_MIN_SIZE 0U
/* It is just a sequence of LSA Headers */
/* Function definition */
diff --git a/ospf6d/ospf6_network.c b/ospf6d/ospf6_network.c
index 96b82af3..e5a1436c 100644
--- a/ospf6d/ospf6_network.c
+++ b/ospf6d/ospf6_network.c
@@ -64,6 +64,14 @@ ospf6_set_pktinfo (void)
}
void
+ospf6_set_transport_class (void)
+{
+#ifdef IPTOS_PREC_INTERNETCONTROL
+ setsockopt_ipv6_tclass (ospf6_sock, IPTOS_PREC_INTERNETCONTROL);
+#endif
+}
+
+void
ospf6_set_checksum (void)
{
int offset = 12;
@@ -102,6 +110,7 @@ ospf6_serv_sock (void)
#endif /*1*/
ospf6_reset_mcastloop ();
ospf6_set_pktinfo ();
+ ospf6_set_transport_class ();
ospf6_set_checksum ();
/* setup global in6_addr, allspf6 and alldr6 for later use */
@@ -111,86 +120,22 @@ ospf6_serv_sock (void)
return 0;
}
+/* ospf6 set socket option */
void
-ospf6_join_allspfrouters (u_int ifindex)
+ospf6_sso (u_int ifindex, struct in6_addr *group, int option)
{
struct ipv6_mreq mreq6;
- int retval;
+ int ret;
assert (ifindex);
mreq6.ipv6mr_interface = ifindex;
- memcpy (&mreq6.ipv6mr_multiaddr, &allspfrouters6,
- sizeof (struct in6_addr));
+ memcpy (&mreq6.ipv6mr_multiaddr, group, sizeof (struct in6_addr));
- retval = setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
- &mreq6, sizeof (mreq6));
-
- if (retval < 0)
- zlog_err ("Network: Join AllSPFRouters on ifindex %d failed: %s",
- ifindex, safe_strerror (errno));
-#if 0
- else
- zlog_debug ("Network: Join AllSPFRouters on ifindex %d", ifindex);
-#endif
-}
-
-void
-ospf6_leave_allspfrouters (u_int ifindex)
-{
- struct ipv6_mreq mreq6;
-
- assert (ifindex);
- mreq6.ipv6mr_interface = ifindex;
- memcpy (&mreq6.ipv6mr_multiaddr, &allspfrouters6,
- sizeof (struct in6_addr));
-
- if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
- &mreq6, sizeof (mreq6)) < 0)
- zlog_warn ("Network: Leave AllSPFRouters on ifindex %d Failed: %s",
- ifindex, safe_strerror (errno));
-#if 0
- else
- zlog_debug ("Network: Leave AllSPFRouters on ifindex %d", ifindex);
-#endif
-}
-
-void
-ospf6_join_alldrouters (u_int ifindex)
-{
- struct ipv6_mreq mreq6;
-
- assert (ifindex);
- mreq6.ipv6mr_interface = ifindex;
- memcpy (&mreq6.ipv6mr_multiaddr, &alldrouters6,
- sizeof (struct in6_addr));
-
- if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
- &mreq6, sizeof (mreq6)) < 0)
- zlog_warn ("Network: Join AllDRouters on ifindex %d Failed: %s",
- ifindex, safe_strerror (errno));
-#if 0
- else
- zlog_debug ("Network: Join AllDRouters on ifindex %d", ifindex);
-#endif
-}
-
-void
-ospf6_leave_alldrouters (u_int ifindex)
-{
- struct ipv6_mreq mreq6;
-
- assert (ifindex);
- mreq6.ipv6mr_interface = ifindex;
- memcpy (&mreq6.ipv6mr_multiaddr, &alldrouters6,
- sizeof (struct in6_addr));
-
- if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
- &mreq6, sizeof (mreq6)) < 0)
- zlog_warn ("Network: Leave AllDRouters on ifindex %d Failed", ifindex);
-#if 0
- else
- zlog_debug ("Network: Leave AllDRouters on ifindex %d", ifindex);
-#endif
+ ret = setsockopt (ospf6_sock, IPPROTO_IPV6, option,
+ &mreq6, sizeof (mreq6));
+ if (ret < 0)
+ zlog_err ("Network: setsockopt (%d) on ifindex %d failed: %s",
+ option, ifindex, safe_strerror (errno));
}
static int
diff --git a/ospf6d/ospf6_network.h b/ospf6d/ospf6_network.h
index fd8758e8..0526b3e1 100644
--- a/ospf6d/ospf6_network.h
+++ b/ospf6d/ospf6_network.h
@@ -35,11 +35,7 @@ extern void ospf6_set_pktinfo (void);
extern void ospf6_set_checksum (void);
extern int ospf6_serv_sock (void);
-
-extern void ospf6_join_allspfrouters (u_int);
-extern void ospf6_leave_allspfrouters (u_int);
-extern void ospf6_join_alldrouters (u_int);
-extern void ospf6_leave_alldrouters (u_int);
+extern void ospf6_sso (u_int ifindex, struct in6_addr *group, int option);
extern int ospf6_sendmsg (struct in6_addr *, struct in6_addr *,
unsigned int *, struct iovec *);
diff --git a/ospf6d/ospf6_proto.c b/ospf6d/ospf6_proto.c
index c792aa45..d011601f 100644
--- a/ospf6d/ospf6_proto.c
+++ b/ospf6d/ospf6_proto.c
@@ -42,11 +42,10 @@ ospf6_prefix_apply_mask (struct ospf6_prefix *op)
return;
}
- if (index == 16)
- return;
-
- pnt[index] &= mask;
- index ++;
+ /* nonzero mask means no check for this byte because if it contains
+ * prefix bits it must be there for us to write */
+ if (mask)
+ pnt[index++] &= mask;
while (index < OSPF6_PREFIX_SPACE (op->prefix_length))
pnt[index++] = 0;
diff --git a/ospf6d/ospf6_proto.h b/ospf6d/ospf6_proto.h
index a8c1b1a0..64625004 100644
--- a/ospf6d/ospf6_proto.h
+++ b/ospf6d/ospf6_proto.h
@@ -73,6 +73,7 @@
#define OSPF6_OPT_V6 (1 << 0) /* IPv6 forwarding Capability */
/* OSPF6 Prefix */
+#define OSPF6_PREFIX_MIN_SIZE 4U /* .length == 0 */
struct ospf6_prefix
{
u_int8_t prefix_length;
diff --git a/ospf6d/ospf6_route.h b/ospf6d/ospf6_route.h
index 8dcc877f..b384824c 100644
--- a/ospf6d/ospf6_route.h
+++ b/ospf6d/ospf6_route.h
@@ -300,6 +300,7 @@ extern void ospf6_brouter_show (struct vty *vty, struct ospf6_route *route);
extern int config_write_ospf6_debug_route (struct vty *vty);
extern void install_element_ospf6_debug_route (void);
extern void ospf6_route_init (void);
+extern void ospf6_clean (void);
#endif /* OSPF6_ROUTE_H */
diff --git a/ospf6d/ospf6_spf.c b/ospf6d/ospf6_spf.c
index cb549618..a4a5b721 100644
--- a/ospf6d/ospf6_spf.c
+++ b/ospf6d/ospf6_spf.c
@@ -282,8 +282,7 @@ ospf6_spf_install (struct ospf6_vertex *v,
{
struct ospf6_route *route;
int i, j;
- struct ospf6_vertex *prev, *w;
- struct listnode *node, *nnode;
+ struct ospf6_vertex *prev;
if (IS_OSPF6_DEBUG_SPF (PROCESS))
zlog_debug ("SPF install %s hops %d cost %d",
@@ -392,6 +391,8 @@ ospf6_spf_calculation (u_int32_t router_id,
caddr_t lsdesc;
struct ospf6_lsa *lsa;
+ ospf6_spf_table_finish (result_table);
+
/* Install the calculating router itself as the root of the SPF tree */
/* construct root vertex */
lsa = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_ROUTER), htonl (0),
@@ -403,8 +404,6 @@ ospf6_spf_calculation (u_int32_t router_id,
candidate_list = pqueue_create ();
candidate_list->cmp = ospf6_vertex_cmp;
- ospf6_spf_table_finish (result_table);
-
root = ospf6_vertex_create (lsa);
root->area = oa;
root->cost = 0;
diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c
index 2b65be82..df856b4c 100644
--- a/ospf6d/ospf6_top.c
+++ b/ospf6d/ospf6_top.c
@@ -594,10 +594,10 @@ ALIAS (show_ipv6_ospf6_route,
IP6_STR
OSPF6_STR
ROUTE_STR
- "Dispaly Intra-Area routes\n"
- "Dispaly Inter-Area routes\n"
- "Dispaly Type-1 External routes\n"
- "Dispaly Type-2 External routes\n"
+ "Display Intra-Area routes\n"
+ "Display Inter-Area routes\n"
+ "Display Type-1 External routes\n"
+ "Display Type-2 External routes\n"
)
DEFUN (show_ipv6_ospf6_route_type_detail,
@@ -607,10 +607,10 @@ DEFUN (show_ipv6_ospf6_route_type_detail,
IP6_STR
OSPF6_STR
ROUTE_STR
- "Dispaly Intra-Area routes\n"
- "Dispaly Inter-Area routes\n"
- "Dispaly Type-1 External routes\n"
- "Dispaly Type-2 External routes\n"
+ "Display Intra-Area routes\n"
+ "Display Inter-Area routes\n"
+ "Display Type-1 External routes\n"
+ "Display Type-2 External routes\n"
"Detailed information\n"
)
{
diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c
index 881771a7..f09e9d22 100644
--- a/ospf6d/ospf6_zebra.c
+++ b/ospf6d/ospf6_zebra.c
@@ -451,6 +451,7 @@ ospf6_zebra_route_update (int type, struct ospf6_route *request)
api.type = ZEBRA_ROUTE_OSPF6;
api.flags = 0;
api.message = 0;
+ api.safi = SAFI_UNICAST;
SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
api.nexthop_num = nhcount;
api.nexthop = nexthops;
diff --git a/ospf6d/ospf6d.c b/ospf6d/ospf6d.c
index bb091d4f..3fdbda18 100644
--- a/ospf6d/ospf6d.c
+++ b/ospf6d/ospf6d.c
@@ -1889,4 +1889,11 @@ ospf6_init (void)
thread_add_read (master, ospf6_receive, NULL, ospf6_sock);
}
-
+void
+ospf6_clean (void)
+{
+ if (ospf6->route_table)
+ ospf6_route_remove_all (ospf6->route_table);
+ if (ospf6->brouter_table)
+ ospf6_route_remove_all (ospf6->brouter_table);
+}
diff --git a/ospf6d/ospf6d.h b/ospf6d/ospf6d.h
index b6f1b737..2ac6300e 100644
--- a/ospf6d/ospf6d.h
+++ b/ospf6d/ospf6d.h
@@ -49,6 +49,9 @@ extern struct thread_master *master;
#endif /* IPV6_DROP_MEMBERSHIP */
#endif /* ! IPV6_LEAVE_GROUP */
+#define MSG_OK 0
+#define MSG_NG 1
+
/* cast macro: XXX - these *must* die, ick ick. */
#define OSPF6_PROCESS(x) ((struct ospf6 *) (x))
#define OSPF6_AREA(x) ((struct ospf6_area *) (x))