diff options
Diffstat (limited to 'ospfd')
-rw-r--r-- | ospfd/.cvsignore | 14 | ||||
-rw-r--r-- | ospfd/ospf_abr.c | 49 | ||||
-rw-r--r-- | ospfd/ospf_asbr.c | 5 | ||||
-rw-r--r-- | ospfd/ospf_ase.c | 1 | ||||
-rw-r--r-- | ospfd/ospf_dump.c | 23 | ||||
-rw-r--r-- | ospfd/ospf_dump.h | 3 | ||||
-rw-r--r-- | ospfd/ospf_flood.c | 3 | ||||
-rw-r--r-- | ospfd/ospf_lsa.c | 19 | ||||
-rw-r--r-- | ospfd/ospf_lsa.h | 6 | ||||
-rw-r--r-- | ospfd/ospf_main.c | 46 | ||||
-rw-r--r-- | ospfd/ospf_network.c | 19 | ||||
-rw-r--r-- | ospfd/ospf_packet.c | 593 | ||||
-rw-r--r-- | ospfd/ospf_packet.h | 11 | ||||
-rw-r--r-- | ospfd/ospf_route.c | 59 | ||||
-rw-r--r-- | ospfd/ospf_spf.c | 19 | ||||
-rw-r--r-- | ospfd/ospf_vty.c | 59 | ||||
-rw-r--r-- | ospfd/ospf_zebra.c | 6 | ||||
-rw-r--r-- | ospfd/ospf_zebra.h | 2 | ||||
-rw-r--r-- | ospfd/ospfd.c | 2 | ||||
-rw-r--r-- | ospfd/ospfd.h | 4 |
20 files changed, 595 insertions, 348 deletions
diff --git a/ospfd/.cvsignore b/ospfd/.cvsignore deleted file mode 100644 index 6fce629e..00000000 --- a/ospfd/.cvsignore +++ /dev/null @@ -1,14 +0,0 @@ -Makefile -Makefile.in -*.o -ospfd -ospfd.conf -tags -TAGS -.deps -.nfs* -*.lo -*.la -*.libs -.arch-inventory -.arch-ids diff --git a/ospfd/ospf_abr.c b/ospfd/ospf_abr.c index 7a75194a..b7cc20dd 100644 --- a/ospfd/ospf_abr.c +++ b/ospfd/ospf_abr.c @@ -384,7 +384,7 @@ ospf_abr_nssa_am_elected (struct ospf_area *area) if (best == NULL) best = &lsa->data->id; else - if ( IPV4_ADDR_CMP (&best, &lsa->data->id) < 0) + if (IPV4_ADDR_CMP (&best->s_addr, &lsa->data->id.s_addr) < 0) best = &lsa->data->id; } @@ -395,7 +395,7 @@ ospf_abr_nssa_am_elected (struct ospf_area *area) if (best == NULL) return 1; - if ( IPV4_ADDR_CMP (&best, &area->ospf->router_id) < 0) + if (IPV4_ADDR_CMP (&best->s_addr, &area->ospf->router_id.s_addr) < 0) return 1; else return 0; @@ -613,15 +613,6 @@ set_metric (struct ospf_lsa *lsa, u_int32_t metric) memcpy(header->metric, mp, 3); } -static int -ospf_abr_check_nssa_range (struct prefix_ipv4 *p, u_int32_t cost, - struct ospf_area *area) -{ - /* The Type-7 is tested against the aggregated prefix and forwarded - for lsa installation and flooding */ - return 0; -} - /* ospf_abr_translate_nssa */ static int ospf_abr_translate_nssa (struct ospf_area *area, struct ospf_lsa *lsa) @@ -1577,42 +1568,6 @@ ospf_abr_send_nssa_aggregates (struct ospf *ospf) /* temporarily turned off */ } static void -ospf_abr_announce_nssa_defaults (struct ospf *ospf) /* By ABR-Translator */ -{ - struct listnode *node; - struct ospf_area *area; - - if (! IS_OSPF_ABR (ospf)) - return; - - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_abr_announce_stub_defaults(): Start"); - - for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area)) - { - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_abr_announce_nssa_defaults(): looking at area %s", - inet_ntoa (area->area_id)); - - if (area->external_routing != OSPF_AREA_NSSA) - continue; - - if (OSPF_IS_AREA_BACKBONE (area)) - continue; /* Sanity Check */ - - /* if (!TranslatorRole continue V 1.0 look for "always" conf */ - if (area->NSSATranslatorState) - { - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_abr_announce_nssa_defaults(): " - "announcing 0.0.0.0/0 to this nssa"); - /* ospf_abr_announce_nssa_asbr_to_as (&p, area->default_cost, area); */ - /*ospf_abr_announce_network_to_area (&p, area->default_cost, area);*/ - } - } -} - -static void ospf_abr_announce_stub_defaults (struct ospf *ospf) { struct listnode *node; diff --git a/ospfd/ospf_asbr.c b/ospfd/ospf_asbr.c index c39efee1..a23b4f2b 100644 --- a/ospfd/ospf_asbr.c +++ b/ospfd/ospf_asbr.c @@ -284,6 +284,9 @@ ospf_redistribute_withdraw (struct ospf *ospf, u_char type) continue; ospf_external_lsa_flush (ospf, type, &ei->p, ei->ifindex /*, ei->nexthop */); - ospf_external_info_delete (type, ei->p); + + ospf_external_info_free (ei); + route_unlock_node (rn); + rn->info = NULL; } } diff --git a/ospfd/ospf_ase.c b/ospfd/ospf_ase.c index 3c199311..6a72e31d 100644 --- a/ospfd/ospf_ase.c +++ b/ospfd/ospf_ase.c @@ -135,7 +135,6 @@ ospf_ase_complete_direct_routes (struct ospf_route *ro, struct in_addr nexthop) { struct listnode *node; struct ospf_path *op; - struct interface *ifp; for (ALL_LIST_ELEMENTS_RO (ro->paths, node, op)) if (op->nexthop.s_addr == 0) diff --git a/ospfd/ospf_dump.c b/ospfd/ospf_dump.c index e65b2e33..7e11e251 100644 --- a/ospfd/ospf_dump.c +++ b/ospfd/ospf_dump.c @@ -115,6 +115,16 @@ const struct message ospf_network_type_msg[] = }; const int ospf_network_type_msg_max = OSPF_IFTYPE_MAX; +/* AuType */ +const struct message ospf_auth_type_str[] = +{ + { OSPF_AUTH_NULL, "Null" }, + { OSPF_AUTH_SIMPLE, "Simple" }, + { OSPF_AUTH_CRYPTOGRAPHIC, "Cryptographic" }, +}; +const size_t ospf_auth_type_str_max = sizeof (ospf_auth_type_str) / + sizeof (ospf_auth_type_str[0]); + /* Configuration debug option variables. */ unsigned long conf_debug_ospf_packet[5] = {0, 0, 0, 0, 0}; unsigned long conf_debug_ospf_event = 0; @@ -657,18 +667,19 @@ static void ospf_header_dump (struct ospf_header *ospfh) { char buf[9]; + u_int16_t auth_type = ntohs (ospfh->auth_type); zlog_debug ("Header"); zlog_debug (" Version %d", ospfh->version); zlog_debug (" Type %d (%s)", ospfh->type, - ospf_packet_type_str[ospfh->type]); + LOOKUP (ospf_packet_type_str, ospfh->type)); zlog_debug (" Packet Len %d", ntohs (ospfh->length)); zlog_debug (" Router ID %s", inet_ntoa (ospfh->router_id)); zlog_debug (" Area ID %s", inet_ntoa (ospfh->area_id)); zlog_debug (" Checksum 0x%x", ntohs (ospfh->checksum)); - zlog_debug (" AuType %d", ntohs (ospfh->auth_type)); + zlog_debug (" AuType %s", LOOKUP (ospf_auth_type_str, auth_type)); - switch (ntohs (ospfh->auth_type)) + switch (auth_type) { case OSPF_AUTH_NULL: break; @@ -1457,7 +1468,7 @@ DEFUN (show_debugging_ospf, if (IS_DEBUG_OSPF_PACKET (i, SEND) && IS_DEBUG_OSPF_PACKET (i, RECV)) { vty_out (vty, " OSPF packet %s%s debugging is on%s", - ospf_packet_type_str[i + 1], + LOOKUP (ospf_packet_type_str, i + 1), IS_DEBUG_OSPF_PACKET (i, DETAIL) ? " detail" : "", VTY_NEWLINE); } @@ -1465,12 +1476,12 @@ DEFUN (show_debugging_ospf, { if (IS_DEBUG_OSPF_PACKET (i, SEND)) vty_out (vty, " OSPF packet %s send%s debugging is on%s", - ospf_packet_type_str[i + 1], + LOOKUP (ospf_packet_type_str, i + 1), IS_DEBUG_OSPF_PACKET (i, DETAIL) ? " detail" : "", VTY_NEWLINE); if (IS_DEBUG_OSPF_PACKET (i, RECV)) vty_out (vty, " OSPF packet %s receive%s debugging is on%s", - ospf_packet_type_str[i + 1], + LOOKUP (ospf_packet_type_str, i + 1), IS_DEBUG_OSPF_PACKET (i, DETAIL) ? " detail" : "", VTY_NEWLINE); } diff --git a/ospfd/ospf_dump.h b/ospfd/ospf_dump.h index fb813719..a2d5e8ba 100644 --- a/ospfd/ospf_dump.h +++ b/ospfd/ospf_dump.h @@ -121,8 +121,9 @@ extern unsigned long term_debug_ospf_zebra; extern unsigned long term_debug_ospf_nssa; /* Message Strings. */ -extern const char *ospf_packet_type_str[]; extern char *ospf_lsa_type_str[]; +extern const struct message ospf_auth_type_str[]; +extern const size_t ospf_auth_type_str_max; /* Prototypes. */ extern const char *ospf_area_name_string (struct ospf_area *); diff --git a/ospfd/ospf_flood.c b/ospfd/ospf_flood.c index 77f2e161..2ebae89a 100644 --- a/ospfd/ospf_flood.c +++ b/ospfd/ospf_flood.c @@ -319,7 +319,8 @@ ospf_flood (struct ospf *ospf, struct ospf_neighbor *nbr, procedure cannot overwrite the newly installed LSA until MinLSArrival seconds have elapsed. */ - new = ospf_lsa_install (ospf, nbr->oi, new); + if (! (new = ospf_lsa_install (ospf, nbr->oi, new))) + return -1; /* unknown LSA type or any other error condition */ /* Acknowledge the receipt of the LSA by sending a Link State Acknowledgment packet back out the receiving interface. */ diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c index 842df49c..d5959eb1 100644 --- a/ospfd/ospf_lsa.c +++ b/ospfd/ospf_lsa.c @@ -746,7 +746,7 @@ ospf_stub_router_timer (struct thread *t) return 0; } -inline static void +static void ospf_stub_router_check (struct ospf_area *area) { /* area must either be administratively configured to be stub @@ -1637,7 +1637,7 @@ ospf_external_lsa_new (struct ospf *ospf, if (ei == NULL) { if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - zlog_debug ("LSA[Type5]: External info is NULL, could not originated"); + zlog_debug ("LSA[Type5]: External info is NULL, can't originate"); return NULL; } @@ -2838,9 +2838,9 @@ ospf_maxage_lsa_remover (struct thread *thread) OSPF_TIMER_ON (ospf->t_maxage, ospf_maxage_lsa_remover, 0); /* Remove LSA from the LSDB */ - if (CHECK_FLAG (lsa->flags, OSPF_LSA_SELF)) + if (IS_LSA_SELF (lsa)) if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) - zlog_debug ("LSA[Type%d:%s]: LSA 0x%lx is self-oririnated: ", + zlog_debug ("LSA[Type%d:%s]: LSA 0x%lx is self-originated: ", lsa->data->type, inet_ntoa (lsa->data->id), (u_long)lsa); if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) @@ -3389,7 +3389,7 @@ ospf_lsa_is_self_originated (struct ospf *ospf, struct ospf_lsa *lsa) /* This LSA is already checked. */ if (CHECK_FLAG (lsa->flags, OSPF_LSA_SELF_CHECKED)) - return CHECK_FLAG (lsa->flags, OSPF_LSA_SELF); + return IS_LSA_SELF (lsa); /* Make sure LSA is self-checked. */ SET_FLAG (lsa->flags, OSPF_LSA_SELF_CHECKED); @@ -3414,11 +3414,11 @@ ospf_lsa_is_self_originated (struct ospf *ospf, struct ospf_lsa *lsa) { /* to make it easier later */ SET_FLAG (lsa->flags, OSPF_LSA_SELF); - return CHECK_FLAG (lsa->flags, OSPF_LSA_SELF); + return IS_LSA_SELF (lsa); } } - return CHECK_FLAG (lsa->flags, OSPF_LSA_SELF); + return IS_LSA_SELF (lsa); } /* Get unique Link State ID. */ @@ -3541,6 +3541,7 @@ ospf_lsa_refresh (struct ospf *ospf, struct ospf_lsa *lsa) struct external_info *ei; struct ospf_lsa *new = NULL; assert (CHECK_FLAG (lsa->flags, OSPF_LSA_SELF)); + assert (IS_LSA_SELF (lsa)); assert (lsa->lock > 0); switch (lsa->data->type) @@ -3589,7 +3590,7 @@ ospf_refresher_register_lsa (struct ospf *ospf, struct ospf_lsa *lsa) u_int16_t index, current_index; assert (lsa->lock > 0); - assert (CHECK_FLAG (lsa->flags, OSPF_LSA_SELF)); + assert (IS_LSA_SELF (lsa)); if (lsa->refresh_list < 0) { @@ -3632,7 +3633,7 @@ void ospf_refresher_unregister_lsa (struct ospf *ospf, struct ospf_lsa *lsa) { assert (lsa->lock > 0); - assert (CHECK_FLAG (lsa->flags, OSPF_LSA_SELF)); + assert (IS_LSA_SELF (lsa)); if (lsa->refresh_list >= 0) { struct list *refresh_list = ospf->lsa_refresh_queue.qs[lsa->refresh_list]; diff --git a/ospfd/ospf_lsa.h b/ospfd/ospf_lsa.h index 72e2f8a5..297cd984 100644 --- a/ospfd/ospf_lsa.h +++ b/ospfd/ospf_lsa.h @@ -49,6 +49,7 @@ #define OSPF_LSA_HEADER_SIZE 20U #define OSPF_ROUTER_LSA_LINK_SIZE 12U +#define OSPF_ROUTER_LSA_TOS_SIZE 4U #define OSPF_MAX_LSA_SIZE 1500U /* AS-external-LSA refresh method. */ @@ -152,6 +153,7 @@ struct router_lsa_link }; /* OSPF Router-LSAs structure. */ +#define OSPF_ROUTER_LSA_MIN_SIZE 16U /* w/1 link descriptor */ struct router_lsa { struct lsa_header header; @@ -169,6 +171,7 @@ struct router_lsa }; /* OSPF Network-LSAs structure. */ +#define OSPF_NETWORK_LSA_MIN_SIZE 8U /* w/1 router-ID */ struct network_lsa { struct lsa_header header; @@ -177,6 +180,7 @@ struct network_lsa }; /* OSPF Summary-LSAs structure. */ +#define OSPF_SUMMARY_LSA_MIN_SIZE 8U /* w/1 TOS metric block */ struct summary_lsa { struct lsa_header header; @@ -186,6 +190,7 @@ struct summary_lsa }; /* OSPF AS-external-LSAs structure. */ +#define OSPF_AS_EXTERNAL_LSA_MIN_SIZE 16U /* w/1 TOS forwarding block */ struct as_external_lsa { struct lsa_header header; @@ -274,6 +279,7 @@ extern struct in_addr ospf_get_ip_from_ifp (struct ospf_interface *); extern struct ospf_lsa *ospf_external_lsa_originate (struct ospf *, struct external_info *); extern int ospf_external_lsa_originate_timer (struct thread *); +extern int ospf_default_originate_timer (struct thread *); extern struct ospf_lsa *ospf_lsa_lookup (struct ospf_area *, u_int32_t, struct in_addr, struct in_addr); extern struct ospf_lsa *ospf_lsa_lookup_by_id (struct ospf_area *, diff --git a/ospfd/ospf_main.c b/ospfd/ospf_main.c index 8b9a3458..bad674b6 100644 --- a/ospfd/ospf_main.c +++ b/ospfd/ospf_main.c @@ -38,6 +38,7 @@ #include "memory.h" #include "privs.h" #include "sigevent.h" +#include "zclient.h" #include "ospfd/ospfd.h" #include "ospfd/ospf_interface.h" @@ -80,6 +81,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'}, { "dryrun", no_argument, NULL, 'C'}, { "help", no_argument, NULL, 'h'}, { "vty_addr", required_argument, NULL, 'A'}, @@ -116,6 +118,7 @@ Daemon which manages OSPF.\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\ @@ -191,30 +194,11 @@ main (int argc, char **argv) /* get program name */ progname = ((p = strrchr (argv[0], '/')) ? ++p : argv[0]); - /* Invoked by a priviledged user? -- endo. */ - if (geteuid () != 0) - { - errno = EPERM; - perror (progname); - exit (1); - } - - zlog_default = openzlog (progname, ZLOG_OSPF, - LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON); - - /* OSPF master init. */ - ospf_master_init (); - -#ifdef SUPPORT_OSPF_API - /* OSPF apiserver is disabled by default. */ - ospf_apiserver_enable = 0; -#endif /* SUPPORT_OSPF_API */ - while (1) { int opt; - opt = getopt_long (argc, argv, "df:i:hA:P:u:g:avC", longopts, 0); + opt = getopt_long (argc, argv, "df:i:z:hA:P:u:g:avC", longopts, 0); if (opt == EOF) break; @@ -235,6 +219,9 @@ main (int argc, char **argv) case 'i': pid_file = optarg; break; + case 'z': + zclient_serv_path_set (optarg); + break; case 'P': /* Deal with atoi() returning 0 on failure, and ospfd not listening on ospfd port... */ @@ -274,6 +261,25 @@ main (int argc, char **argv) } } + /* Invoked by a priviledged user? -- endo. */ + if (geteuid () != 0) + { + errno = EPERM; + perror (progname); + exit (1); + } + + zlog_default = openzlog (progname, ZLOG_OSPF, + LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON); + + /* OSPF master init. */ + ospf_master_init (); + +#ifdef SUPPORT_OSPF_API + /* OSPF apiserver is disabled by default. */ + ospf_apiserver_enable = 0; +#endif /* SUPPORT_OSPF_API */ + /* Initializations. */ master = om->master; diff --git a/ospfd/ospf_network.c b/ospfd/ospf_network.c index 1e2d44e6..3e326a8c 100644 --- a/ospfd/ospf_network.c +++ b/ospfd/ospf_network.c @@ -52,8 +52,8 @@ ospf_if_add_allspfrouters (struct ospf *top, struct prefix *p, { int ret; - ret = setsockopt_multicast_ipv4 (top->fd, IP_ADD_MEMBERSHIP, - p->u.prefix4, htonl (OSPF_ALLSPFROUTERS), + ret = setsockopt_ipv4_multicast (top->fd, IP_ADD_MEMBERSHIP, + htonl (OSPF_ALLSPFROUTERS), ifindex); if (ret < 0) zlog_warn ("can't setsockopt IP_ADD_MEMBERSHIP (fd %d, addr %s, " @@ -73,8 +73,8 @@ ospf_if_drop_allspfrouters (struct ospf *top, struct prefix *p, { int ret; - ret = setsockopt_multicast_ipv4 (top->fd, IP_DROP_MEMBERSHIP, - p->u.prefix4, htonl (OSPF_ALLSPFROUTERS), + ret = setsockopt_ipv4_multicast (top->fd, IP_DROP_MEMBERSHIP, + htonl (OSPF_ALLSPFROUTERS), ifindex); if (ret < 0) zlog_warn ("can't setsockopt IP_DROP_MEMBERSHIP (fd %d, addr %s, " @@ -94,8 +94,8 @@ ospf_if_add_alldrouters (struct ospf *top, struct prefix *p, unsigned int { int ret; - ret = setsockopt_multicast_ipv4 (top->fd, IP_ADD_MEMBERSHIP, - p->u.prefix4, htonl (OSPF_ALLDROUTERS), + ret = setsockopt_ipv4_multicast (top->fd, IP_ADD_MEMBERSHIP, + htonl (OSPF_ALLDROUTERS), ifindex); if (ret < 0) zlog_warn ("can't setsockopt IP_ADD_MEMBERSHIP (fd %d, addr %s, " @@ -115,8 +115,8 @@ ospf_if_drop_alldrouters (struct ospf *top, struct prefix *p, unsigned int { int ret; - ret = setsockopt_multicast_ipv4 (top->fd, IP_DROP_MEMBERSHIP, - p->u.prefix4, htonl (OSPF_ALLDROUTERS), + ret = setsockopt_ipv4_multicast (top->fd, IP_DROP_MEMBERSHIP, + htonl (OSPF_ALLDROUTERS), ifindex); if (ret < 0) zlog_warn ("can't setsockopt IP_DROP_MEMBERSHIP (fd %d, addr %s, " @@ -151,8 +151,7 @@ ospf_if_ipmulticast (struct ospf *top, struct prefix *p, unsigned int ifindex) zlog_warn ("can't setsockopt IP_MULTICAST_TTL(1) for fd %d: %s", top->fd, safe_strerror (errno)); - ret = setsockopt_multicast_ipv4 (top->fd, IP_MULTICAST_IF, - p->u.prefix4, 0, ifindex); + ret = setsockopt_ipv4_multicast_if (top->fd, ifindex); if (ret < 0) zlog_warn("can't setsockopt IP_MULTICAST_IF(fd %d, addr %s, " "ifindex %u): %s", diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c index be137d91..351fb210 100644 --- a/ospfd/ospf_packet.c +++ b/ospfd/ospf_packet.c @@ -50,16 +50,50 @@ #include "ospfd/ospf_dump.h" /* Packet Type String. */ -const char *ospf_packet_type_str[] = -{ - "unknown", - "Hello", - "Database Description", - "Link State Request", - "Link State Update", - "Link State Acknowledgment", +const struct message ospf_packet_type_str[] = +{ + { OSPF_MSG_HELLO, "Hello" }, + { OSPF_MSG_DB_DESC, "Database Description" }, + { OSPF_MSG_LS_REQ, "Link State Request" }, + { OSPF_MSG_LS_UPD, "Link State Update" }, + { OSPF_MSG_LS_ACK, "Link State Acknowledgment" }, +}; +const size_t ospf_packet_type_str_max = sizeof (ospf_packet_type_str) / + sizeof (ospf_packet_type_str[0]); + +/* Minimum (besides OSPF_HEADER_SIZE) lengths for OSPF packets of + particular types, offset is the "type" field of a packet. */ +static const u_int16_t ospf_packet_minlen[] = +{ + 0, + OSPF_HELLO_MIN_SIZE, + OSPF_DB_DESC_MIN_SIZE, + OSPF_LS_REQ_MIN_SIZE, + OSPF_LS_UPD_MIN_SIZE, + OSPF_LS_ACK_MIN_SIZE, +}; + +/* Minimum (besides OSPF_LSA_HEADER_SIZE) lengths for LSAs of particular + types, offset is the "LSA type" field. */ +static const u_int16_t ospf_lsa_minlen[] = +{ + 0, + OSPF_ROUTER_LSA_MIN_SIZE, + OSPF_NETWORK_LSA_MIN_SIZE, + OSPF_SUMMARY_LSA_MIN_SIZE, + OSPF_SUMMARY_LSA_MIN_SIZE, + OSPF_AS_EXTERNAL_LSA_MIN_SIZE, + 0, + OSPF_AS_EXTERNAL_LSA_MIN_SIZE, + 0, + 0, + 0, + 0, }; +/* for ospf_check_auth() */ +static int ospf_check_sum (struct ospf_header *); + /* OSPF authentication checking function */ static int ospf_auth_type (struct ospf_interface *oi) @@ -201,7 +235,7 @@ ospf_packet_add (struct ospf_interface *oi, struct ospf_packet *op) "destination %s) called with NULL obuf, ignoring " "(please report this bug)!\n", IF_NAME(oi), oi->state, LOOKUP (ospf_ism_state_msg, oi->state), - ospf_packet_type_str[stream_getc_from(op->s, 1)], + LOOKUP (ospf_packet_type_str, stream_getc_from(op->s, 1)), inet_ntoa (op->dst)); return; } @@ -222,7 +256,7 @@ ospf_packet_add_top (struct ospf_interface *oi, struct ospf_packet *op) "destination %s) called with NULL obuf, ignoring " "(please report this bug)!\n", IF_NAME(oi), oi->state, LOOKUP (ospf_ism_state_msg, oi->state), - ospf_packet_type_str[stream_getc_from(op->s, 1)], + LOOKUP (ospf_packet_type_str, stream_getc_from(op->s, 1)), inet_ntoa (op->dst)); return; } @@ -266,7 +300,7 @@ ospf_packet_dup (struct ospf_packet *op) } /* XXX inline */ -static inline unsigned int +static unsigned int ospf_packet_authspace (struct ospf_interface *oi) { int auth = 0; @@ -291,24 +325,14 @@ ospf_packet_max (struct ospf_interface *oi) static int -ospf_check_md5_digest (struct ospf_interface *oi, struct stream *s, - u_int16_t length) +ospf_check_md5_digest (struct ospf_interface *oi, struct ospf_header *ospfh) { - unsigned char *ibuf; MD5_CTX ctx; unsigned char digest[OSPF_AUTH_MD5_SIZE]; - unsigned char *pdigest; struct crypt_key *ck; - struct ospf_header *ospfh; struct ospf_neighbor *nbr; + u_int16_t length = ntohs (ospfh->length); - - ibuf = STREAM_PNT (s); - ospfh = (struct ospf_header *) ibuf; - - /* Get pointer to the end of the packet. */ - pdigest = ibuf + length; - /* Get secret key. */ ck = ospf_crypt_key_lookup (OSPF_IF_PARAM (oi, auth_crypt), ospfh->u.crypt.key_id); @@ -334,12 +358,12 @@ ospf_check_md5_digest (struct ospf_interface *oi, struct stream *s, /* Generate a digest for the ospf packet - their digest + our digest. */ memset(&ctx, 0, sizeof(ctx)); MD5Init(&ctx); - MD5Update(&ctx, ibuf, length); + MD5Update(&ctx, ospfh, length); MD5Update(&ctx, ck->auth_key, OSPF_AUTH_MD5_SIZE); MD5Final(digest, &ctx); /* compare the two */ - if (memcmp (pdigest, digest, OSPF_AUTH_MD5_SIZE)) + if (memcmp ((caddr_t)ospfh + length, digest, OSPF_AUTH_MD5_SIZE)) { zlog_warn ("interface %s: ospf_check_md5 checksum mismatch", IF_NAME (oi)); @@ -755,7 +779,7 @@ ospf_write (struct thread *thread) } zlog_debug ("%s sent to [%s] via [%s].", - ospf_packet_type_str[type], inet_ntoa (op->dst), + LOOKUP (ospf_packet_type_str, type), inet_ntoa (op->dst), IF_NAME (oi)); if (IS_DEBUG_OSPF_PACKET (type - 1, DETAIL)) @@ -801,7 +825,7 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh, { zlog_debug ("ospf_header[%s/%s]: selforiginated, " "dropping.", - ospf_packet_type_str[ospfh->type], + LOOKUP (ospf_packet_type_str, ospfh->type), inet_ntoa (iph->ip_src)); } return; @@ -1568,8 +1592,13 @@ ospf_ls_upd_list_lsa (struct ospf_neighbor *nbr, struct stream *s, sum = lsah->checksum; if (sum != ospf_lsa_checksum (lsah)) { - zlog_warn ("Link State Update: LSA checksum error %x, %x.", - sum, lsah->checksum); + /* (bug #685) more details in a one-line message make it possible + * to identify problem source on the one hand and to have a better + * chance to compress repeated messages in syslog on the other */ + zlog_warn ("Link State Update: LSA checksum error %x/%x, ID=%s from: nbr %s, router ID %s, adv router %s", + sum, lsah->checksum, inet_ntoa (lsah->id), + inet_ntoa (nbr->src), inet_ntoa (nbr->router_id), + inet_ntoa (lsah->adv_router)); continue; } @@ -2116,7 +2145,7 @@ ospf_recv_packet (int fd, struct interface **ifp, struct stream *ibuf) ip_len = iph->ip_len; -#if !defined(GNU_LINUX) && (OpenBSD < 200311) +#if !defined(GNU_LINUX) && (OpenBSD < 200311) && (__FreeBSD_version < 1000000) /* * Kernel network code touches incoming IP header parameters, * before protocol specific processing. @@ -2208,7 +2237,7 @@ ospf_associate_packet_vl (struct ospf *ospf, struct interface *ifp, return NULL; } -static inline int +static int ospf_check_area_id (struct ospf_interface *oi, struct ospf_header *ospfh) { /* Check match the Area ID of the receiving interface. */ @@ -2241,45 +2270,91 @@ ospf_check_network_mask (struct ospf_interface *oi, struct in_addr ip_src) return 0; } +/* Return 1, if the packet is properly authenticated and checksummed, + 0 otherwise. In particular, check that AuType header field is valid and + matches the locally configured AuType, and that D.5 requirements are met. */ static int -ospf_check_auth (struct ospf_interface *oi, struct stream *ibuf, - struct ospf_header *ospfh) +ospf_check_auth (struct ospf_interface *oi, struct ospf_header *ospfh) { - int ret = 0; struct crypt_key *ck; + u_int16_t iface_auth_type; + u_int16_t pkt_auth_type = ntohs (ospfh->auth_type); - switch (ntohs (ospfh->auth_type)) + switch (pkt_auth_type) + { + case OSPF_AUTH_NULL: /* RFC2328 D.5.1 */ + if (OSPF_AUTH_NULL != (iface_auth_type = ospf_auth_type (oi))) { - case OSPF_AUTH_NULL: - ret = 1; - break; - case OSPF_AUTH_SIMPLE: - if (!memcmp (OSPF_IF_PARAM (oi, auth_simple), ospfh->u.auth_data, OSPF_AUTH_SIMPLE_SIZE)) - ret = 1; - else - ret = 0; - break; - case OSPF_AUTH_CRYPTOGRAPHIC: - if ((ck = listgetdata (listtail(OSPF_IF_PARAM (oi,auth_crypt)))) == NULL) - { - ret = 0; - break; - } - - /* This is very basic, the digest processing is elsewhere */ - if (ospfh->u.crypt.auth_data_len == OSPF_AUTH_MD5_SIZE && - ospfh->u.crypt.key_id == ck->key_id && - ntohs (ospfh->length) + OSPF_AUTH_SIMPLE_SIZE <= stream_get_size (ibuf)) - ret = 1; - else - ret = 0; - break; - default: - ret = 0; - break; + if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV)) + zlog_warn ("interface %s: auth-type mismatch, local %s, rcvd Null", + IF_NAME (oi), LOOKUP (ospf_auth_type_str, iface_auth_type)); + return 0; } - - return ret; + if (! ospf_check_sum (ospfh)) + { + if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV)) + zlog_warn ("interface %s: Null auth OK, but checksum error, Router-ID %s", + IF_NAME (oi), inet_ntoa (ospfh->router_id)); + return 0; + } + return 1; + case OSPF_AUTH_SIMPLE: /* RFC2328 D.5.2 */ + if (OSPF_AUTH_SIMPLE != (iface_auth_type = ospf_auth_type (oi))) + { + if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV)) + zlog_warn ("interface %s: auth-type mismatch, local %s, rcvd Simple", + IF_NAME (oi), LOOKUP (ospf_auth_type_str, iface_auth_type)); + return 0; + } + if (memcmp (OSPF_IF_PARAM (oi, auth_simple), ospfh->u.auth_data, OSPF_AUTH_SIMPLE_SIZE)) + { + if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV)) + zlog_warn ("interface %s: Simple auth failed", IF_NAME (oi)); + return 0; + } + if (! ospf_check_sum (ospfh)) + { + if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV)) + zlog_warn ("interface %s: Simple auth OK, checksum error, Router-ID %s", + IF_NAME (oi), inet_ntoa (ospfh->router_id)); + return 0; + } + return 1; + case OSPF_AUTH_CRYPTOGRAPHIC: /* RFC2328 D.5.3 */ + if (OSPF_AUTH_CRYPTOGRAPHIC != (iface_auth_type = ospf_auth_type (oi))) + { + if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV)) + zlog_warn ("interface %s: auth-type mismatch, local %s, rcvd Cryptographic", + IF_NAME (oi), LOOKUP (ospf_auth_type_str, iface_auth_type)); + return 0; + } + if (ospfh->checksum) + { + if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV)) + zlog_warn ("interface %s: OSPF header checksum is not 0", IF_NAME (oi)); + return 0; + } + /* only MD5 crypto method can pass ospf_packet_examin() */ + if + ( + NULL == (ck = listgetdata (listtail(OSPF_IF_PARAM (oi,auth_crypt)))) || + ospfh->u.crypt.key_id != ck->key_id || + /* Condition above uses the last key ID on the list, which is + different from what ospf_crypt_key_lookup() does. A bug? */ + ! ospf_check_md5_digest (oi, ospfh) + ) + { + if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV)) + zlog_warn ("interface %s: MD5 auth failed", IF_NAME (oi)); + return 0; + } + return 1; + default: + if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV)) + zlog_warn ("interface %s: invalid packet auth-type (%02x)", + IF_NAME (oi), pkt_auth_type); + return 0; + } } static int @@ -2308,19 +2383,311 @@ ospf_check_sum (struct ospf_header *ospfh) return 1; } +/* Verify, that given link/TOS records are properly sized/aligned and match + Router-LSA "# links" and "# TOS" fields as specified in RFC2328 A.4.2. */ +static unsigned +ospf_router_lsa_links_examin +( + struct router_lsa_link * link, + u_int16_t linkbytes, + const u_int16_t num_links +) +{ + unsigned counted_links = 0, thislinklen; + + while (linkbytes) + { + thislinklen = OSPF_ROUTER_LSA_LINK_SIZE + 4 * link->m[0].tos_count; + if (thislinklen > linkbytes) + { + if (IS_DEBUG_OSPF_PACKET (0, RECV)) + zlog_debug ("%s: length error in link block #%u", __func__, counted_links); + return MSG_NG; + } + link = (struct router_lsa_link *)((caddr_t) link + thislinklen); + linkbytes -= thislinklen; + counted_links++; + } + if (counted_links != num_links) + { + if (IS_DEBUG_OSPF_PACKET (0, RECV)) + zlog_debug ("%s: %u link blocks declared, %u present", + __func__, num_links, counted_links); + return MSG_NG; + } + return MSG_OK; +} + +/* Verify, that the given LSA is properly sized/aligned (including type-specific + minimum length constraint). */ +static unsigned +ospf_lsa_examin (struct lsa_header * lsah, const u_int16_t lsalen, const u_char headeronly) +{ + unsigned ret; + struct router_lsa * rlsa; + if + ( + lsah->type < OSPF_MAX_LSA && + ospf_lsa_minlen[lsah->type] && + lsalen < OSPF_LSA_HEADER_SIZE + ospf_lsa_minlen[lsah->type] + ) + { + if (IS_DEBUG_OSPF_PACKET (0, RECV)) + zlog_debug ("%s: undersized (%u B) %s", + __func__, lsalen, LOOKUP (ospf_lsa_type_msg, lsah->type)); + return MSG_NG; + } + switch (lsah->type) + { + case OSPF_ROUTER_LSA: + /* RFC2328 A.4.2, LSA header + 4 bytes followed by N>=1 (12+)-byte link blocks */ + if (headeronly) + { + ret = (lsalen - OSPF_LSA_HEADER_SIZE - OSPF_ROUTER_LSA_MIN_SIZE) % 4 ? MSG_NG : MSG_OK; + break; + } + rlsa = (struct router_lsa *) lsah; + ret = ospf_router_lsa_links_examin + ( + (struct router_lsa_link *) rlsa->link, + lsalen - OSPF_LSA_HEADER_SIZE - 4, /* skip: basic header, "flags", 0, "# links" */ + ntohs (rlsa->links) /* 16 bits */ + ); + break; + case OSPF_AS_EXTERNAL_LSA: + /* RFC2328 A.4.5, LSA header + 4 bytes followed by N>=1 12-bytes long blocks */ + case OSPF_AS_NSSA_LSA: + /* RFC3101 C, idem */ + ret = (lsalen - OSPF_LSA_HEADER_SIZE - OSPF_AS_EXTERNAL_LSA_MIN_SIZE) % 12 ? MSG_NG : MSG_OK; + break; + /* Following LSA types are considered OK length-wise as soon as their minimum + * length constraint is met and length of the whole LSA is a multiple of 4 + * (basic LSA header size is already a multiple of 4). */ + case OSPF_NETWORK_LSA: + /* RFC2328 A.4.3, LSA header + 4 bytes followed by N>=1 router-IDs */ + case OSPF_SUMMARY_LSA: + case OSPF_ASBR_SUMMARY_LSA: + /* RFC2328 A.4.4, LSA header + 4 bytes followed by N>=1 4-bytes TOS blocks */ +#ifdef HAVE_OPAQUE_LSA + case OSPF_OPAQUE_LINK_LSA: + case OSPF_OPAQUE_AREA_LSA: + case OSPF_OPAQUE_AS_LSA: + /* RFC5250 A.2, "some number of octets (of application-specific + * data) padded to 32-bit alignment." This is considered equivalent + * to 4-byte alignment of all other LSA types, see OSPF-ALIGNMENT.txt + * file for the detailed analysis of this passage. */ +#endif + ret = lsalen % 4 ? MSG_NG : MSG_OK; + break; + default: + if (IS_DEBUG_OSPF_PACKET (0, RECV)) + zlog_debug ("%s: unsupported LSA type 0x%02x", __func__, lsah->type); + return MSG_NG; + } + if (ret != MSG_OK && IS_DEBUG_OSPF_PACKET (0, RECV)) + zlog_debug ("%s: alignment error in %s", + __func__, LOOKUP (ospf_lsa_type_msg, lsah->type)); + return ret; +} + +/* 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 +ospf_lsaseq_examin +( + struct 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 < OSPF_LSA_HEADER_SIZE) + { + if (IS_DEBUG_OSPF_PACKET (0, 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 = ntohs (lsah->length); + if (lsalen < OSPF_LSA_HEADER_SIZE) + { + if (IS_DEBUG_OSPF_PACKET (0, 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 ospf_lsa_examin() */ + if (MSG_OK != ospf_lsa_examin (lsah, lsalen, 1)) + { + if (IS_DEBUG_OSPF_PACKET (0, RECV)) + zlog_debug ("%s: malformed header-only LSA #%u", __func__, counted_lsas); + return MSG_NG; + } + lsah = (struct lsa_header *) ((caddr_t) lsah + OSPF_LSA_HEADER_SIZE); + length -= OSPF_LSA_HEADER_SIZE; + } + else + { + /* make sure the input buffer is deep enough before further checks */ + if (lsalen > length) + { + if (IS_DEBUG_OSPF_PACKET (0, RECV)) + zlog_debug ("%s: anomaly in LSA #%u: declared length is %u B, buffered length is %zu B", + __func__, counted_lsas, lsalen, length); + return MSG_NG; + } + if (MSG_OK != ospf_lsa_examin (lsah, lsalen, 0)) + { + if (IS_DEBUG_OSPF_PACKET (0, RECV)) + zlog_debug ("%s: malformed LSA #%u", __func__, counted_lsas); + return MSG_NG; + } + lsah = (struct lsa_header *) ((caddr_t) lsah + lsalen); + length -= lsalen; + } + counted_lsas++; + } + + if (declared_num_lsas && counted_lsas != declared_num_lsas) + { + if (IS_DEBUG_OSPF_PACKET (0, 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 +ospf_packet_examin (struct ospf_header * oh, const unsigned bytesonwire) +{ + u_int16_t bytesdeclared, bytesauth; + unsigned ret; + struct ospf_ls_update * lsupd; + + /* Length, 1st approximation. */ + if (bytesonwire < OSPF_HEADER_SIZE) + { + if (IS_DEBUG_OSPF_PACKET (0, RECV)) + zlog_debug ("%s: undersized (%u B) packet", __func__, bytesonwire); + return MSG_NG; + } + /* Now it is safe to access header fields. Performing length check, allow + * for possible extra bytes of crypto auth/padding, which are not counted + * in the OSPF header "length" field. */ + if (oh->version != OSPF_VERSION) + { + if (IS_DEBUG_OSPF_PACKET (0, RECV)) + zlog_debug ("%s: invalid (%u) protocol version", __func__, oh->version); + return MSG_NG; + } + bytesdeclared = ntohs (oh->length); + if (ntohs (oh->auth_type) != OSPF_AUTH_CRYPTOGRAPHIC) + bytesauth = 0; + else + { + if (oh->u.crypt.auth_data_len != OSPF_AUTH_MD5_SIZE) + { + if (IS_DEBUG_OSPF_PACKET (0, RECV)) + zlog_debug ("%s: unsupported crypto auth length (%u B)", + __func__, oh->u.crypt.auth_data_len); + return MSG_NG; + } + bytesauth = OSPF_AUTH_MD5_SIZE; + } + if (bytesdeclared + bytesauth > bytesonwire) + { + if (IS_DEBUG_OSPF_PACKET (0, RECV)) + zlog_debug ("%s: packet length error (%u real, %u+%u declared)", + __func__, bytesonwire, bytesdeclared, bytesauth); + return MSG_NG; + } + /* Length, 2nd approximation. The type-specific constraint is checked + against declared length, not amount of bytes on wire. */ + if + ( + oh->type >= OSPF_MSG_HELLO && + oh->type <= OSPF_MSG_LS_ACK && + bytesdeclared < OSPF_HEADER_SIZE + ospf_packet_minlen[oh->type] + ) + { + if (IS_DEBUG_OSPF_PACKET (0, RECV)) + zlog_debug ("%s: undersized (%u B) %s packet", __func__, + bytesdeclared, LOOKUP (ospf_packet_type_str, oh->type)); + return MSG_NG; + } + switch (oh->type) + { + case OSPF_MSG_HELLO: + /* RFC2328 A.3.2, packet header + OSPF_HELLO_MIN_SIZE bytes followed + by N>=0 router-IDs. */ + ret = (bytesdeclared - OSPF_HEADER_SIZE - OSPF_HELLO_MIN_SIZE) % 4 ? MSG_NG : MSG_OK; + break; + case OSPF_MSG_DB_DESC: + /* RFC2328 A.3.3, packet header + OSPF_DB_DESC_MIN_SIZE bytes followed + by N>=0 header-only LSAs. */ + ret = ospf_lsaseq_examin + ( + (struct lsa_header *) ((caddr_t) oh + OSPF_HEADER_SIZE + OSPF_DB_DESC_MIN_SIZE), + bytesdeclared - OSPF_HEADER_SIZE - OSPF_DB_DESC_MIN_SIZE, + 1, /* header-only LSAs */ + 0 + ); + break; + case OSPF_MSG_LS_REQ: + /* RFC2328 A.3.4, packet header followed by N>=0 12-bytes request blocks. */ + ret = (bytesdeclared - OSPF_HEADER_SIZE - OSPF_LS_REQ_MIN_SIZE) % + OSPF_LSA_KEY_SIZE ? MSG_NG : MSG_OK; + break; + case OSPF_MSG_LS_UPD: + /* RFC2328 A.3.5, packet header + OSPF_LS_UPD_MIN_SIZE bytes followed + by N>=0 full LSAs (with N declared beforehand). */ + lsupd = (struct ospf_ls_update *) ((caddr_t) oh + OSPF_HEADER_SIZE); + ret = ospf_lsaseq_examin + ( + (struct lsa_header *) ((caddr_t) lsupd + OSPF_LS_UPD_MIN_SIZE), + bytesdeclared - OSPF_HEADER_SIZE - OSPF_LS_UPD_MIN_SIZE, + 0, /* full LSAs */ + ntohl (lsupd->num_lsas) /* 32 bits */ + ); + break; + case OSPF_MSG_LS_ACK: + /* RFC2328 A.3.6, packet header followed by N>=0 header-only LSAs. */ + ret = ospf_lsaseq_examin + ( + (struct lsa_header *) ((caddr_t) oh + OSPF_HEADER_SIZE + OSPF_LS_ACK_MIN_SIZE), + bytesdeclared - OSPF_HEADER_SIZE - OSPF_LS_ACK_MIN_SIZE, + 1, /* header-only LSAs */ + 0 + ); + break; + default: + if (IS_DEBUG_OSPF_PACKET (0, RECV)) + zlog_debug ("%s: invalid packet type 0x%02x", __func__, oh->type); + return MSG_NG; + } + if (ret != MSG_OK && IS_DEBUG_OSPF_PACKET (0, RECV)) + zlog_debug ("%s: malformed %s packet", __func__, LOOKUP (ospf_packet_type_str, oh->type)); + return ret; +} + /* OSPF Header verification. */ static int ospf_verify_header (struct stream *ibuf, struct ospf_interface *oi, struct ip *iph, struct ospf_header *ospfh) { - /* check version. */ - if (ospfh->version != OSPF_VERSION) - { - zlog_warn ("interface %s: ospf_read version number mismatch.", - IF_NAME (oi)); - return -1; - } - /* Check Area ID. */ if (!ospf_check_area_id (oi, ospfh)) { @@ -2337,42 +2704,9 @@ ospf_verify_header (struct stream *ibuf, struct ospf_interface *oi, return -1; } - /* Check authentication. */ - if (ospf_auth_type (oi) != ntohs (ospfh->auth_type)) - { - zlog_warn ("interface %s: auth-type mismatch, local %d, rcvd %d", - IF_NAME (oi), ospf_auth_type (oi), ntohs (ospfh->auth_type)); - return -1; - } - - if (! ospf_check_auth (oi, ibuf, ospfh)) - { - zlog_warn ("interface %s: ospf_read authentication failed.", - IF_NAME (oi)); - return -1; - } - - /* if check sum is invalid, packet is discarded. */ - if (ntohs (ospfh->auth_type) != OSPF_AUTH_CRYPTOGRAPHIC) - { - if (! ospf_check_sum (ospfh)) - { - zlog_warn ("interface %s: ospf_read packet checksum error %s", - IF_NAME (oi), inet_ntoa (ospfh->router_id)); - return -1; - } - } - else - { - if (ospfh->checksum != 0) - return -1; - if (ospf_check_md5_digest (oi, ibuf, ntohs (ospfh->length)) == 0) - { - zlog_warn ("interface %s: ospf_read md5 authentication failed.", - IF_NAME (oi)); - return -1; - } - } + /* Check authentication. The function handles logging actions, where required. */ + if (! ospf_check_auth (oi, ospfh)) + return -1; return 0; } @@ -2396,10 +2730,10 @@ ospf_read (struct thread *thread) /* prepare for next packet. */ ospf->t_read = thread_add_read (master, ospf_read, ospf, ospf->fd); - /* read OSPF packet. */ stream_reset(ospf->ibuf); if (!(ibuf = ospf_recv_packet (ospf->fd, &ifp, ospf->ibuf))) return -1; + /* This raw packet is known to be at least as big as its IP header. */ /* Note that there should not be alignment problems with this assignment because this is at the beginning of the stream data buffer. */ @@ -2430,15 +2764,23 @@ ospf_read (struct thread *thread) return 0; } - /* Adjust size to message length. */ + /* Advance from IP header to OSPF header (iph->ip_hl has been verified + by ospf_recv_packet() to be correct). */ stream_forward_getp (ibuf, iph->ip_hl * 4); - - /* Get ospf packet header. */ + ospfh = (struct ospf_header *) STREAM_PNT (ibuf); + if (MSG_OK != ospf_packet_examin (ospfh, stream_get_endp (ibuf) - stream_get_getp (ibuf))) + return -1; + /* Now it is safe to access all fields of OSPF packet header. */ /* associate packet with ospf interface */ oi = ospf_if_lookup_recv_if (ospf, iph->ip_src, ifp); + /* ospf_verify_header() relies on a valid "oi" and thus can be called only + after the passive/backbone/other checks below are passed. These checks + in turn access the fields of unverified "ospfh" structure for their own + purposes and must remain very accurate in doing this. */ + /* If incoming interface is passive one, ignore it. */ if (oi && OSPF_IF_PASSIVE_STATUS (oi) == OSPF_IF_PASSIVE) { @@ -2529,6 +2871,17 @@ ospf_read (struct thread *thread) return 0; } + /* Verify more OSPF header fields. */ + ret = ospf_verify_header (ibuf, oi, iph, ospfh); + if (ret < 0) + { + if (IS_DEBUG_OSPF_PACKET (0, RECV)) + zlog_debug ("ospf_read[%s]: Header check failed, " + "dropping.", + inet_ntoa (iph->ip_src)); + return ret; + } + /* Show debug receiving packet. */ if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV)) { @@ -2539,7 +2892,7 @@ ospf_read (struct thread *thread) } zlog_debug ("%s received from [%s] via [%s]", - ospf_packet_type_str[ospfh->type], + LOOKUP (ospf_packet_type_str, ospfh->type), inet_ntoa (ospfh->router_id), IF_NAME (oi)); zlog_debug (" src [%s],", inet_ntoa (iph->ip_src)); zlog_debug (" dst [%s]", inet_ntoa (iph->ip_dst)); @@ -2548,20 +2901,6 @@ ospf_read (struct thread *thread) zlog_debug ("-----------------------------------------------------"); } - /* Some header verification. */ - ret = ospf_verify_header (ibuf, oi, iph, ospfh); - if (ret < 0) - { - if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV)) - { - zlog_debug ("ospf_read[%s/%s]: Header check failed, " - "dropping.", - ospf_packet_type_str[ospfh->type], - inet_ntoa (iph->ip_src)); - } - return ret; - } - stream_forward_getp (ibuf, OSPF_HEADER_SIZE); /* Adjust size to message length. */ diff --git a/ospfd/ospf_packet.h b/ospfd/ospf_packet.h index 9a472081..337686ad 100644 --- a/ospfd/ospf_packet.h +++ b/ospfd/ospf_packet.h @@ -46,6 +46,10 @@ #define OSPF_HELLO_REPLY_DELAY 1 +/* Return values of functions involved in packet verification, see ospf6d. */ +#define MSG_OK 0 +#define MSG_NG 1 + struct ospf_packet { struct ospf_packet *next; @@ -117,6 +121,10 @@ struct ospf_db_desc u_int32_t dd_seqnum; }; +struct ospf_ls_update +{ + u_int32_t num_lsas; +}; /* Macros. */ /* XXX Perhaps obsolete; function in ospf_packet.c */ @@ -163,4 +171,7 @@ extern int ospf_ls_ack_timer (struct thread *); extern int ospf_poll_timer (struct thread *); extern int ospf_hello_reply_timer (struct thread *); +extern const struct message ospf_packet_type_str[]; +extern const size_t ospf_packet_type_str_max; + #endif /* _ZEBRA_OSPF_PACKET_H */ diff --git a/ospfd/ospf_route.c b/ospfd/ospf_route.c index 267237b8..d2e5e1e7 100644 --- a/ospfd/ospf_route.c +++ b/ospfd/ospf_route.c @@ -272,61 +272,6 @@ ospf_route_install (struct ospf *ospf, struct route_table *rt) } } -static void -ospf_intra_route_add (struct route_table *rt, struct vertex *v, - struct ospf_area *area) -{ - struct route_node *rn; - struct ospf_route *or; - struct prefix_ipv4 p; - struct ospf_path *path; - struct vertex_parent *parent; - struct listnode *node, *nnode; - - p.family = AF_INET; - p.prefix = v->id; - if (v->type == OSPF_VERTEX_ROUTER) - p.prefixlen = IPV4_MAX_BITLEN; - else - { - struct network_lsa *lsa = (struct network_lsa *) v->lsa; - p.prefixlen = ip_masklen (lsa->mask); - } - apply_mask_ipv4 (&p); - - rn = route_node_get (rt, (struct prefix *) &p); - if (rn->info) - { - zlog_warn ("Same routing information exists for %s", inet_ntoa (v->id)); - route_unlock_node (rn); - return; - } - - or = ospf_route_new (); - - if (v->type == OSPF_VERTEX_NETWORK) - { - or->type = OSPF_DESTINATION_NETWORK; - - for (ALL_LIST_ELEMENTS (v->parents, node, nnode, parent)) - { - path = ospf_path_new (); - path->nexthop = parent->nexthop->router; - listnode_add (or->paths, path); - } - } - else - or->type = OSPF_DESTINATION_ROUTER; - - or->id = v->id; - or->u.std.area_id = area->area_id; - or->u.std.external_routing= area->external_routing; - or->path_type = OSPF_PATH_INTRA_AREA; - or->cost = v->distance; - - rn->info = or; -} - /* RFC2328 16.1. (4). For "router". */ void ospf_intra_add_router (struct route_table *rt, struct vertex *v, @@ -720,10 +665,6 @@ ospf_asbr_route_cmp (struct ospf *ospf, struct ospf_route *r1, r1_type = r1->path_type; r2_type = r2->path_type; - /* If RFC1583Compat flag is on -- all paths are equal. */ - if (CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE)) - return 0; - /* r1/r2 itself is backbone, and it's Inter-area path. */ if (OSPF_IS_AREA_ID_BACKBONE (r1->u.std.area_id)) r1_type = OSPF_PATH_INTER_AREA; diff --git a/ospfd/ospf_spf.c b/ospfd/ospf_spf.c index ca200222..d7f9ba27 100644 --- a/ospfd/ospf_spf.c +++ b/ospfd/ospf_spf.c @@ -356,9 +356,6 @@ ospf_lsa_has_link (struct lsa_header *w, struct lsa_header *v) return -1; } -#define ROUTER_LSA_MIN_SIZE 12 -#define ROUTER_LSA_TOS_SIZE 4 - /* Find the next link after prev_link from v to w. If prev_link is * NULL, return the first link from v to w. Ignore stub and virtual links; * these link types will never be returned. @@ -380,8 +377,8 @@ ospf_get_next_link (struct vertex *v, struct vertex *w, else { p = (u_char *) prev_link; - p += (ROUTER_LSA_MIN_SIZE + - (prev_link->m[0].tos_count * ROUTER_LSA_TOS_SIZE)); + p += (OSPF_ROUTER_LSA_LINK_SIZE + + (prev_link->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE)); } lim = ((u_char *) v->lsa) + ntohs (v->lsa->length); @@ -390,7 +387,7 @@ ospf_get_next_link (struct vertex *v, struct vertex *w, { l = (struct router_lsa_link *) p; - p += (ROUTER_LSA_MIN_SIZE + (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE)); + p += (OSPF_ROUTER_LSA_LINK_SIZE + (l->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE)); if (l->m[0].type != lsa_type) continue; @@ -755,8 +752,8 @@ ospf_spf_next (struct vertex *v, struct ospf_area *area, { l = (struct router_lsa_link *) p; - p += (ROUTER_LSA_MIN_SIZE + - (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE)); + p += (OSPF_ROUTER_LSA_LINK_SIZE + + (l->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE)); /* (a) If this is a link to a stub network, examine the next link in V's LSA. Links to stub networks will be @@ -989,8 +986,8 @@ ospf_spf_process_stubs (struct ospf_area *area, struct vertex *v, { l = (struct router_lsa_link *) p; - p += (ROUTER_LSA_MIN_SIZE + - (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE)); + p += (OSPF_ROUTER_LSA_LINK_SIZE + + (l->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE)); if (l->m[0].type == LSA_LINK_TYPE_STUB) ospf_intra_add_stub (rt, l, v, area, parent_is_root); @@ -1045,6 +1042,7 @@ ospf_rtrs_free (struct route_table *rtrs) route_table_finish (rtrs); } +#if 0 static void ospf_rtrs_print (struct route_table *rtrs) { @@ -1104,6 +1102,7 @@ ospf_rtrs_print (struct route_table *rtrs) zlog_debug ("ospf_rtrs_print() end"); } +#endif /* Calculating the shortest-path tree for an area. */ static void diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index 46e7ffa5..97c8e8d6 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -80,8 +80,11 @@ ospf_str2area_id (const char *str, struct in_addr *area_id, int *format) /* match "<0-4294967295>". */ else { + if (*str == '-') + return -1; + errno = 0; ret = strtoul (str, &endptr, 10); - if (*endptr != '\0' || (ret == ULONG_MAX && errno == ERANGE)) + if (*endptr != '\0' || errno || ret > UINT32_MAX) return -1; area_id->s_addr = htonl (ret); @@ -93,29 +96,6 @@ ospf_str2area_id (const char *str, struct in_addr *area_id, int *format) static int -str2distribute_source (const char *str, int *source) -{ - /* Sanity check. */ - if (str == NULL) - return 0; - - if (strncmp (str, "k", 1) == 0) - *source = ZEBRA_ROUTE_KERNEL; - else if (strncmp (str, "c", 1) == 0) - *source = ZEBRA_ROUTE_CONNECT; - else if (strncmp (str, "s", 1) == 0) - *source = ZEBRA_ROUTE_STATIC; - else if (strncmp (str, "r", 1) == 0) - *source = ZEBRA_ROUTE_RIP; - else if (strncmp (str, "b", 1) == 0) - *source = ZEBRA_ROUTE_BGP; - else - return 0; - - return 1; -} - -static int str2metric (const char *str, int *metric) { /* Sanity check. */ @@ -3761,7 +3741,7 @@ show_as_external_lsa_detail (struct vty *vty, struct ospf_lsa *lsa) return 0; } -/* N.B. This function currently seems to be unused. */ +#if 0 static int show_as_external_lsa_stdvty (struct ospf_lsa *lsa) { @@ -3785,6 +3765,7 @@ show_as_external_lsa_stdvty (struct ospf_lsa *lsa) return 0; } +#endif /* Show AS-NSSA-LSA detail information. */ static int @@ -5824,7 +5805,8 @@ DEFUN (ospf_redistribute_source_metric_type, int metric = -1; /* Get distribute source. */ - if (!str2distribute_source (argv[0], &source)) + source = proto_redistnum(AFI_IP, argv[0]); + if (source < 0 || source == ZEBRA_ROUTE_OSPF) return CMD_WARNING; /* Get metric value. */ @@ -5885,7 +5867,8 @@ DEFUN (ospf_redistribute_source_type_metric, int metric = -1; /* Get distribute source. */ - if (!str2distribute_source (argv[0], &source)) + source = proto_redistnum(AFI_IP, argv[0]); + if (source < 0 || source == ZEBRA_ROUTE_OSPF) return CMD_WARNING; /* Get metric value. */ @@ -5949,7 +5932,8 @@ DEFUN (ospf_redistribute_source_metric_routemap, int metric = -1; /* Get distribute source. */ - if (!str2distribute_source (argv[0], &source)) + source = proto_redistnum(AFI_IP, argv[0]); + if (source < 0 || source == ZEBRA_ROUTE_OSPF) return CMD_WARNING; /* Get metric value. */ @@ -5982,7 +5966,8 @@ DEFUN (ospf_redistribute_source_type_routemap, int type = -1; /* Get distribute source. */ - if (!str2distribute_source (argv[0], &source)) + source = proto_redistnum(AFI_IP, argv[0]); + if (source < 0 || source == ZEBRA_ROUTE_OSPF) return CMD_WARNING; /* Get metric value. */ @@ -6010,7 +5995,8 @@ DEFUN (ospf_redistribute_source_routemap, int source; /* Get distribute source. */ - if (!str2distribute_source (argv[0], &source)) + source = proto_redistnum(AFI_IP, argv[0]); + if (source < 0 || source == ZEBRA_ROUTE_OSPF) return CMD_WARNING; if (argc == 2) @@ -6031,7 +6017,8 @@ DEFUN (no_ospf_redistribute_source, struct ospf *ospf = vty->index; int source; - if (!str2distribute_source (argv[0], &source)) + source = proto_redistnum(AFI_IP, argv[0]); + if (source < 0 || source == ZEBRA_ROUTE_OSPF) return CMD_WARNING; ospf_routemap_unset (ospf, source); @@ -6050,7 +6037,8 @@ DEFUN (ospf_distribute_list_out, int source; /* Get distribute source. */ - if (!str2distribute_source (argv[1], &source)) + source = proto_redistnum(AFI_IP, argv[0]); + if (source < 0 || source == ZEBRA_ROUTE_OSPF) return CMD_WARNING; return ospf_distribute_list_out_set (ospf, source, argv[0]); @@ -6068,7 +6056,8 @@ DEFUN (no_ospf_distribute_list_out, struct ospf *ospf = vty->index; int source; - if (!str2distribute_source (argv[1], &source)) + source = proto_redistnum(AFI_IP, argv[0]); + if (source < 0 || source == ZEBRA_ROUTE_OSPF) return CMD_WARNING; return ospf_distribute_list_out_unset (ospf, source, argv[0]); @@ -7902,9 +7891,9 @@ config_write_ospf_distribute (struct vty *vty, struct ospf *ospf) { /* distribute-list print. */ for (type = 0; type < ZEBRA_ROUTE_MAX; type++) - if (ospf->dlist[type].name) + if (DISTRIBUTE_NAME (ospf, type)) vty_out (vty, " distribute-list %s out %s%s", - ospf->dlist[type].name, + DISTRIBUTE_NAME (ospf, type), zebra_route_string(type), VTY_NEWLINE); /* default-information print. */ diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c index 50ca85e1..f8d1cb7c 100644 --- a/ospfd/ospf_zebra.c +++ b/ospfd/ospf_zebra.c @@ -358,6 +358,7 @@ ospf_zebra_add (struct prefix_ipv4 *p, struct ospf_route *or) stream_putc (s, ZEBRA_ROUTE_OSPF); stream_putc (s, flags); stream_putc (s, message); + stream_putw (s, SAFI_UNICAST); /* Put prefix information. */ psize = PSIZE (p->prefixlen); @@ -427,6 +428,7 @@ ospf_zebra_delete (struct prefix_ipv4 *p, struct ospf_route *or) api.type = ZEBRA_ROUTE_OSPF; api.flags = 0; api.message = 0; + api.safi = SAFI_UNICAST; api.ifindex_num = 0; api.nexthop_num = 0; @@ -483,6 +485,7 @@ ospf_zebra_add_discard (struct prefix_ipv4 *p) api.type = ZEBRA_ROUTE_OSPF; api.flags = ZEBRA_FLAG_BLACKHOLE; api.message = 0; + api.safi = SAFI_UNICAST; SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); api.nexthop_num = 0; api.ifindex_num = 0; @@ -505,6 +508,7 @@ ospf_zebra_delete_discard (struct prefix_ipv4 *p) api.type = ZEBRA_ROUTE_OSPF; api.flags = ZEBRA_FLAG_BLACKHOLE; api.message = 0; + api.safi = SAFI_UNICAST; SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); api.nexthop_num = 0; api.ifindex_num = 0; @@ -670,7 +674,7 @@ ospf_external_lsa_originate_check (struct ospf *ospf, if (is_prefix_default (&ei->p)) if (ospf->default_originate == DEFAULT_ORIGINATE_NONE) { - zlog_info ("LSA[Type5:0.0.0.0]: Not originate AS-exntenal-LSA " + zlog_info ("LSA[Type5:0.0.0.0]: Not originate AS-external-LSA " "for default"); return 0; } diff --git a/ospfd/ospf_zebra.h b/ospfd/ospf_zebra.h index 3efd8958..fbb34442 100644 --- a/ospfd/ospf_zebra.h +++ b/ospfd/ospf_zebra.h @@ -50,8 +50,6 @@ extern void ospf_zebra_delete (struct prefix_ipv4 *, struct ospf_route *); extern void ospf_zebra_add_discard (struct prefix_ipv4 *); extern void ospf_zebra_delete_discard (struct prefix_ipv4 *); -extern int ospf_default_originate_timer (struct thread *); - extern int ospf_redistribute_check (struct ospf *, struct external_info *, int *); extern int ospf_distribute_check_connected (struct ospf *, diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c index 0188ffda..e8405136 100644 --- a/ospfd/ospfd.c +++ b/ospfd/ospfd.c @@ -1204,6 +1204,7 @@ ospf_area_nssa_translator_role_set (struct ospf *ospf, struct in_addr area_id, return 1; } +#if 0 /* XXX: unused? Leave for symmetry? */ static int ospf_area_nssa_translator_role_unset (struct ospf *ospf, @@ -1221,6 +1222,7 @@ ospf_area_nssa_translator_role_unset (struct ospf *ospf, return 1; } +#endif int ospf_area_export_list_set (struct ospf *ospf, diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h index 0e57c452..7a56d163 100644 --- a/ospfd/ospfd.h +++ b/ospfd/ospfd.h @@ -72,10 +72,6 @@ #define OSPF_ALLSPFROUTERS 0xe0000005 /* 224.0.0.5 */ #define OSPF_ALLDROUTERS 0xe0000006 /* 224.0.0.6 */ -/* XXX Where is this used? And why it was used only if compiled with - * NSSA support. */ -#define OSPF_LOOPer 0x7f000000 /* 127.0.0.0 */ - #define OSPF_AREA_BACKBONE 0x00000000 /* 0.0.0.0 */ /* OSPF Authentication Type. */ |