summaryrefslogtreecommitdiff
path: root/ospfd
diff options
context:
space:
mode:
authorAvneesh Sachdev <avneesh@opensourcerouting.org>2012-04-09 00:25:15 -0700
committerAvneesh Sachdev <avneesh@opensourcerouting.org>2012-04-09 00:25:15 -0700
commit3cf6c2b4e43f44a977d218c96c26250654ae333e (patch)
treee017cde2015fbf3ef6c250327428d7c6152aa8f7 /ospfd
parent01d7ff0a2166a422c56bd26f04fc22832a9e690b (diff)
parente96b312150d8e376c1ef463793d1929eca3618d5 (diff)
Merge branch 'quagga' into google-bgp-multipath
Conflicts: bgpd/bgp_route.c
Diffstat (limited to 'ospfd')
-rw-r--r--ospfd/.cvsignore14
-rw-r--r--ospfd/ospf_abr.c49
-rw-r--r--ospfd/ospf_asbr.c5
-rw-r--r--ospfd/ospf_ase.c1
-rw-r--r--ospfd/ospf_dump.c23
-rw-r--r--ospfd/ospf_dump.h3
-rw-r--r--ospfd/ospf_flood.c3
-rw-r--r--ospfd/ospf_lsa.c19
-rw-r--r--ospfd/ospf_lsa.h6
-rw-r--r--ospfd/ospf_main.c46
-rw-r--r--ospfd/ospf_network.c19
-rw-r--r--ospfd/ospf_packet.c593
-rw-r--r--ospfd/ospf_packet.h11
-rw-r--r--ospfd/ospf_route.c59
-rw-r--r--ospfd/ospf_spf.c19
-rw-r--r--ospfd/ospf_vty.c59
-rw-r--r--ospfd/ospf_zebra.c6
-rw-r--r--ospfd/ospf_zebra.h2
-rw-r--r--ospfd/ospfd.c2
-rw-r--r--ospfd/ospfd.h4
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. */