diff options
Diffstat (limited to 'ospf6d')
| -rw-r--r-- | ospf6d/.cvsignore | 15 | ||||
| -rw-r--r-- | ospf6d/ospf6_abr.c | 6 | ||||
| -rw-r--r-- | ospf6d/ospf6_abr.h | 5 | ||||
| -rw-r--r-- | ospf6d/ospf6_area.c | 28 | ||||
| -rw-r--r-- | ospf6d/ospf6_asbr.c | 164 | ||||
| -rw-r--r-- | ospf6d/ospf6_asbr.h | 10 | ||||
| -rw-r--r-- | ospf6d/ospf6_interface.c | 75 | ||||
| -rw-r--r-- | ospf6d/ospf6_interface.h | 9 | ||||
| -rw-r--r-- | ospf6d/ospf6_intra.h | 6 | ||||
| -rw-r--r-- | ospf6d/ospf6_lsa.c | 12 | ||||
| -rw-r--r-- | ospf6d/ospf6_lsa.h | 2 | ||||
| -rw-r--r-- | ospf6d/ospf6_main.c | 22 | ||||
| -rw-r--r-- | ospf6d/ospf6_message.c | 695 | ||||
| -rw-r--r-- | ospf6d/ospf6_message.h | 14 | ||||
| -rw-r--r-- | ospf6d/ospf6_network.c | 91 | ||||
| -rw-r--r-- | ospf6d/ospf6_network.h | 6 | ||||
| -rw-r--r-- | ospf6d/ospf6_proto.c | 9 | ||||
| -rw-r--r-- | ospf6d/ospf6_proto.h | 1 | ||||
| -rw-r--r-- | ospf6d/ospf6_route.h | 1 | ||||
| -rw-r--r-- | ospf6d/ospf6_spf.c | 7 | ||||
| -rw-r--r-- | ospf6d/ospf6_top.c | 16 | ||||
| -rw-r--r-- | ospf6d/ospf6_zebra.c | 1 | ||||
| -rw-r--r-- | ospf6d/ospf6d.c | 9 | ||||
| -rw-r--r-- | ospf6d/ospf6d.h | 3 | 
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)) | 
