2023-02-08 13:17:09 +01:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
2002-12-13 21:15:29 +01:00
|
|
|
/*
|
2004-05-18 20:57:06 +02:00
|
|
|
* Copyright (C) 2003 Yasuhiro Ohara
|
2002-12-13 21:15:29 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <zebra.h>
|
|
|
|
|
|
|
|
/* Include other stuffs */
|
|
|
|
#include "log.h"
|
|
|
|
#include "linklist.h"
|
2004-09-01 23:36:14 +02:00
|
|
|
#include "vector.h"
|
|
|
|
#include "vty.h"
|
2002-12-13 21:15:29 +01:00
|
|
|
#include "command.h"
|
|
|
|
#include "memory.h"
|
2023-03-07 20:22:48 +01:00
|
|
|
#include "frrevent.h"
|
lib: improve fletcher checksum validation
OVERVIEW
The checksum used in OSPF (rfc2328) is specified in rc905 annex B. There is an
sample implementation in rfc1008 which forms the basis of the quagga
implementation. This algorithm works perfectly when generating a checksum;
however, validation is a bit problematic.
The following LSA (generated by a non-quagga implementation) is received by
quagga and marked with an invalid checksum; however, it passes both the rfc905
and rfc1008 validation checks.
static uint8_t lsa_10_121_233_29[] = {
0x0e, 0x10, 0x02, 0x03,
0x09, 0x00, 0x35, 0x40,
0x0a, 0x79, 0xe9, 0x1d,
0x80, 0x00, 0x00, 0x03,
0x00, 0x8a, 0x00, 0x1c,
0xff, 0xff, 0xff, 0xe0,
0x00, 0x00, 0x36, 0xb0
};
LS Type: Summary-LSA (IP network)
LS Age: 3600 seconds
Do Not Age: False
Options: 0x02 (E)
Link-State Advertisement Type: Summary-LSA (IP network) (3)
Link State ID: 9.0.53.64
Advertising Router: 10.121.233.29 (10.121.233.29)
LS Sequence Number: 0x80000003
LS Checksum: 0x008a
Length: 28
Netmask: 255.255.255.224
Metric: 14000
You'll note that one byte of the checksum is 0x00; quagga would calculate the
checksum as 0xff8a.
It can be argued that the sourcing implementation generates an incorrect
checksum; however, rfc905 indicates that, for 1's complement arithmetic, the
value 255 shall be regarded as 0, thus either values are valid.
EXPLANATION
The quagga ospfd and ospf6d implementations operate by copying the PDU's
existing checksum in a holding variable, calculating the checksum, and comparing
the resulting checksum to the original. As a note, this implementation has the
side effect of modifying the contents of the PDU.
Evaluation of both rfc905 and rfc1008 shows that checksum validation should
involve calculating the sum over the PDU and checking that both resulting C0 and
C1 values are zero. This behavior is enacted in the rfc1008 implementation by
calling encodecc with k = 0 (checksum offset); however, this functionality had
been omitted from the quagga implementation.
PATCH
This patch adds the ability to call the quagga's fletcher_checksum() with a
checksum offset value of 0xffff (aka FLETCHER_CHECKSUM_VALIDATE) which returns
the sum over the buffer (a value of 0 indicates a valid checksum). This is
similar to the mechanism in rfc1008 when called with k = 0. The patch also
introduces ospf_lsa_checksum_valid().
ospf6d had it's own implementation of the fletcher checksum in
ospf6_lsa_checksum(); it's the same algorithm as in fletcher_checksum(). This
patch removes the local implementation in favor of the library's as well as creates
and uses ospf6_lsa_checksum_valid().
quagga's ISIS implementation suffers from the same problem; however, I do not
have the facilities to validate a fix to ISIS, thus this change has been left to
the ISIS maintainers. The function iso_csum_verify() should be reduced to
running the fletcher checksum over the buffer using an offset of 0.
Signed-off-by: JR Rivers <jrrivers@cumulusnetworks.com>
Reviewed-by: Scott Feldman <sfeldma@cumulusnetworks.com>
Reviewed-by: Nolan Leake <nolan@cumulusnetworks.com>
Reviewed-by: Ayan Banerjee <ayan@cumulusnetworks.com>
Reviewed-by: Shrijeet Mukherjee <shm@cumulusnetworks.com>
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
2012-09-13 19:17:36 +02:00
|
|
|
#include "checksum.h"
|
2021-08-10 17:42:52 +02:00
|
|
|
#include "frrstr.h"
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
#include "ospf6_proto.h"
|
|
|
|
#include "ospf6_lsa.h"
|
|
|
|
#include "ospf6_lsdb.h"
|
|
|
|
#include "ospf6_message.h"
|
2021-02-10 08:28:52 +01:00
|
|
|
#include "ospf6_asbr.h"
|
|
|
|
#include "ospf6_zebra.h"
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
#include "ospf6_top.h"
|
|
|
|
#include "ospf6_area.h"
|
|
|
|
#include "ospf6_interface.h"
|
|
|
|
#include "ospf6_neighbor.h"
|
|
|
|
|
2004-05-18 20:57:06 +02:00
|
|
|
#include "ospf6_flood.h"
|
2004-08-04 22:02:13 +02:00
|
|
|
#include "ospf6d.h"
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2021-05-28 11:33:03 +02:00
|
|
|
#include "ospf6d/ospf6_lsa_clippy.c"
|
|
|
|
|
2021-03-22 19:31:56 +01:00
|
|
|
DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_LSA, "OSPF6 LSA");
|
|
|
|
DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_LSA_HEADER, "OSPF6 LSA header");
|
|
|
|
DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_LSA_SUMMARY, "OSPF6 LSA summary");
|
|
|
|
|
2024-07-18 04:56:14 +02:00
|
|
|
const uint8_t ospf6_lsa_min_size[OSPF6_LSTYPE_SIZE] = {
|
|
|
|
[OSPF6_LSTYPE_UNKNOWN] = 0,
|
|
|
|
[0x00ff & OSPF6_LSTYPE_ROUTER] = OSPF6_ROUTER_LSA_MIN_SIZE,
|
|
|
|
[0x00ff & OSPF6_LSTYPE_NETWORK] = OSPF6_NETWORK_LSA_MIN_SIZE,
|
|
|
|
[0x00ff & OSPF6_LSTYPE_INTER_PREFIX] = OSPF6_INTER_PREFIX_LSA_MIN_SIZE,
|
|
|
|
[0x00ff & OSPF6_LSTYPE_INTER_ROUTER] = OSPF6_INTER_ROUTER_LSA_FIX_SIZE,
|
|
|
|
[0x00ff & OSPF6_LSTYPE_AS_EXTERNAL] = OSPF6_AS_EXTERNAL_LSA_MIN_SIZE,
|
|
|
|
[0x00ff & OSPF6_LSTYPE_GROUP_MEMBERSHIP] = 0, /* Unused */
|
|
|
|
[0x00ff & OSPF6_LSTYPE_TYPE_7] = OSPF6_AS_EXTERNAL_LSA_MIN_SIZE,
|
|
|
|
[0x00ff & OSPF6_LSTYPE_LINK] = OSPF6_LINK_LSA_MIN_SIZE,
|
|
|
|
[0x00ff & OSPF6_LSTYPE_INTRA_PREFIX] = OSPF6_INTRA_PREFIX_LSA_MIN_SIZE,
|
|
|
|
[0x00ff & OSPF6_LSTYPE_GRACE_LSA] = 0
|
|
|
|
};
|
|
|
|
|
|
|
|
void *lsdesc_start_lsa_type(struct ospf6_lsa_header *header, int lsa_type)
|
|
|
|
{
|
|
|
|
uint8_t t = (0x00ff & lsa_type);
|
|
|
|
|
|
|
|
if (t == OSPF6_LSTYPE_UNKNOWN || t >= OSPF6_LSTYPE_SIZE) {
|
|
|
|
zlog_debug("Cannot get descriptor offset for unknown lsa type 0x%x",
|
|
|
|
t);
|
|
|
|
return ospf6_lsa_end(header);
|
|
|
|
}
|
|
|
|
return (char *)lsa_after_header(header) + ospf6_lsa_min_size[t];
|
|
|
|
}
|
|
|
|
|
|
|
|
void *lsdesc_start(struct ospf6_lsa_header *header)
|
|
|
|
{
|
|
|
|
return lsdesc_start_lsa_type(header, ntohs(header->type));
|
|
|
|
}
|
|
|
|
|
2021-11-06 16:35:33 +01:00
|
|
|
static struct ospf6_lsa_handler *lsa_handlers[OSPF6_LSTYPE_SIZE];
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2024-08-05 08:09:30 +02:00
|
|
|
void *nth_lsdesc(struct ospf6_lsa_header *header, int pos)
|
|
|
|
{
|
|
|
|
char *lsdesc = lsdesc_start(header);
|
|
|
|
char *lsa_end = ospf6_lsa_end(header);
|
|
|
|
char *nth;
|
|
|
|
int lsdesc_size;
|
|
|
|
|
|
|
|
if (ntohs(header->type) == OSPF6_LSTYPE_ROUTER)
|
|
|
|
lsdesc_size = OSPF6_ROUTER_LSDESC_FIX_SIZE;
|
|
|
|
else if (ntohs(header->type) == OSPF6_LSTYPE_NETWORK)
|
|
|
|
lsdesc_size = OSPF6_NETWORK_LSDESC_FIX_SIZE;
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
nth = lsdesc + (pos * lsdesc_size);
|
|
|
|
|
|
|
|
if (nth + lsdesc_size <= lsa_end)
|
|
|
|
return nth;
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2024-08-05 08:14:20 +02:00
|
|
|
void *nth_prefix(struct ospf6_lsa_header *header, int pos)
|
|
|
|
{
|
|
|
|
struct ospf6_prefix *prefix = lsdesc_start(header);
|
|
|
|
char *end = ospf6_lsa_end(header);
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
if (ntohs(header->type) != OSPF6_LSTYPE_LINK &&
|
|
|
|
ntohs(header->type) != OSPF6_LSTYPE_INTRA_PREFIX)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (pos == 0)
|
|
|
|
return prefix;
|
|
|
|
|
|
|
|
while ((char *)prefix < end &&
|
|
|
|
(char *)prefix + OSPF6_PREFIX_SIZE(prefix) <= end) {
|
|
|
|
if (i == pos)
|
|
|
|
return prefix;
|
|
|
|
i++;
|
|
|
|
prefix = OSPF6_PREFIX_NEXT(prefix);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2020-10-08 07:38:43 +02:00
|
|
|
struct ospf6 *ospf6_get_by_lsdb(struct ospf6_lsa *lsa)
|
|
|
|
{
|
|
|
|
struct ospf6 *ospf6 = NULL;
|
|
|
|
|
|
|
|
switch (OSPF6_LSA_SCOPE(lsa->header->type)) {
|
|
|
|
case OSPF6_SCOPE_LINKLOCAL:
|
|
|
|
ospf6 = OSPF6_INTERFACE(lsa->lsdb->data)->area->ospf6;
|
|
|
|
break;
|
|
|
|
case OSPF6_SCOPE_AREA:
|
|
|
|
ospf6 = OSPF6_AREA(lsa->lsdb->data)->ospf6;
|
|
|
|
break;
|
|
|
|
case OSPF6_SCOPE_AS:
|
|
|
|
ospf6 = OSPF6_PROCESS(lsa->lsdb->data);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
assert(0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return ospf6;
|
|
|
|
}
|
|
|
|
|
2020-12-04 06:54:40 +01:00
|
|
|
static int ospf6_unknown_lsa_show(struct vty *vty, struct ospf6_lsa *lsa,
|
|
|
|
json_object *json_obj, bool use_json)
|
2004-09-01 23:36:14 +02:00
|
|
|
{
|
2024-05-21 01:47:20 +02:00
|
|
|
char *start, *end, *current;
|
2004-09-01 23:36:14 +02:00
|
|
|
|
2024-07-19 05:04:05 +02:00
|
|
|
start = lsa_after_header(lsa->header);
|
2024-05-21 02:39:47 +02:00
|
|
|
end = ospf6_lsa_end(lsa->header);
|
2004-09-01 23:36:14 +02:00
|
|
|
|
2022-01-31 20:42:17 +01:00
|
|
|
if (use_json) {
|
|
|
|
json_object_string_add(json_obj, "lsaType", "unknown");
|
|
|
|
} else {
|
2020-12-04 06:54:40 +01:00
|
|
|
vty_out(vty, " Unknown contents:\n");
|
|
|
|
for (current = start; current < end; current++) {
|
|
|
|
if ((current - start) % 16 == 0)
|
|
|
|
vty_out(vty, "\n ");
|
|
|
|
else if ((current - start) % 4 == 0)
|
|
|
|
vty_out(vty, " ");
|
|
|
|
|
2021-08-10 17:42:52 +02:00
|
|
|
vty_out(vty, "%02x", *current);
|
2020-12-04 06:54:40 +01:00
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2020-12-04 06:54:40 +01:00
|
|
|
vty_out(vty, "\n\n");
|
2004-09-01 23:36:14 +02:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-10-08 18:20:12 +02:00
|
|
|
static struct ospf6_lsa_handler unknown_handler = {
|
|
|
|
.lh_type = OSPF6_LSTYPE_UNKNOWN,
|
|
|
|
.lh_name = "Unknown",
|
|
|
|
.lh_short_name = "Unk",
|
|
|
|
.lh_show = ospf6_unknown_lsa_show,
|
|
|
|
.lh_get_prefix_str = NULL,
|
|
|
|
.lh_debug = 0 /* No default debug */
|
|
|
|
};
|
2004-09-01 23:36:14 +02:00
|
|
|
|
2020-03-31 13:55:17 +02:00
|
|
|
void ospf6_install_lsa_handler(struct ospf6_lsa_handler *handler)
|
2004-09-01 23:36:14 +02:00
|
|
|
{
|
|
|
|
/* type in handler is host byte order */
|
2021-11-06 16:35:33 +01:00
|
|
|
unsigned int index = handler->lh_type & OSPF6_LSTYPE_FCODE_MASK;
|
|
|
|
|
|
|
|
assertf(index < array_size(lsa_handlers), "index=%x", index);
|
|
|
|
assertf(lsa_handlers[index] == NULL, "old=%s, new=%s",
|
|
|
|
lsa_handlers[index]->lh_name, handler->lh_name);
|
|
|
|
|
|
|
|
lsa_handlers[index] = handler;
|
2004-09-01 23:36:14 +02:00
|
|
|
}
|
|
|
|
|
2020-03-31 13:55:17 +02:00
|
|
|
struct ospf6_lsa_handler *ospf6_get_lsa_handler(uint16_t type)
|
2004-09-01 23:36:14 +02:00
|
|
|
{
|
2020-03-31 13:55:17 +02:00
|
|
|
struct ospf6_lsa_handler *handler = NULL;
|
2004-10-10 14:54:58 +02:00
|
|
|
unsigned int index = ntohs(type) & OSPF6_LSTYPE_FCODE_MASK;
|
2004-09-01 23:36:14 +02:00
|
|
|
|
2021-11-06 16:35:33 +01:00
|
|
|
if (index < array_size(lsa_handlers))
|
|
|
|
handler = lsa_handlers[index];
|
2004-09-01 23:36:14 +02:00
|
|
|
|
2004-11-25 21:54:46 +01:00
|
|
|
if (handler == NULL)
|
|
|
|
handler = &unknown_handler;
|
|
|
|
|
2004-09-01 23:36:14 +02:00
|
|
|
return handler;
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2018-03-27 21:13:34 +02:00
|
|
|
const char *ospf6_lstype_name(uint16_t type)
|
2004-05-18 20:57:06 +02:00
|
|
|
{
|
|
|
|
static char buf[8];
|
2017-10-08 18:20:12 +02:00
|
|
|
const struct ospf6_lsa_handler *handler;
|
2004-05-18 20:57:06 +02:00
|
|
|
|
2004-09-01 23:36:14 +02:00
|
|
|
handler = ospf6_get_lsa_handler(type);
|
|
|
|
if (handler && handler != &unknown_handler)
|
2017-10-08 18:20:12 +02:00
|
|
|
return handler->lh_name;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2004-05-18 20:57:06 +02:00
|
|
|
snprintf(buf, sizeof(buf), "0x%04hx", ntohs(type));
|
|
|
|
return buf;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2018-03-27 21:13:34 +02:00
|
|
|
const char *ospf6_lstype_short_name(uint16_t type)
|
2013-08-25 05:03:23 +02:00
|
|
|
{
|
|
|
|
static char buf[8];
|
2017-10-08 18:20:12 +02:00
|
|
|
const struct ospf6_lsa_handler *handler;
|
2013-08-25 05:03:23 +02:00
|
|
|
|
|
|
|
handler = ospf6_get_lsa_handler(type);
|
2021-02-23 18:07:28 +01:00
|
|
|
if (handler)
|
2017-10-08 18:20:12 +02:00
|
|
|
return handler->lh_short_name;
|
2013-08-25 05:03:23 +02:00
|
|
|
|
|
|
|
snprintf(buf, sizeof(buf), "0x%04hx", ntohs(type));
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
2018-03-27 21:13:34 +02:00
|
|
|
uint8_t ospf6_lstype_debug(uint16_t type)
|
2004-09-01 23:36:14 +02:00
|
|
|
{
|
2017-10-08 18:20:12 +02:00
|
|
|
const struct ospf6_lsa_handler *handler;
|
2004-09-01 23:36:14 +02:00
|
|
|
handler = ospf6_get_lsa_handler(type);
|
2018-09-04 12:55:19 +02:00
|
|
|
return handler->lh_debug;
|
2004-09-01 23:36:14 +02:00
|
|
|
}
|
|
|
|
|
2021-02-10 08:28:52 +01:00
|
|
|
int metric_type(struct ospf6 *ospf6, int type, uint8_t instance)
|
|
|
|
{
|
|
|
|
struct ospf6_redist *red;
|
|
|
|
|
|
|
|
red = ospf6_redist_lookup(ospf6, type, instance);
|
|
|
|
|
|
|
|
return ((!red || red->dmetric.type < 0) ? DEFAULT_METRIC_TYPE
|
|
|
|
: red->dmetric.type);
|
|
|
|
}
|
|
|
|
|
|
|
|
int metric_value(struct ospf6 *ospf6, int type, uint8_t instance)
|
|
|
|
{
|
|
|
|
struct ospf6_redist *red;
|
|
|
|
|
|
|
|
red = ospf6_redist_lookup(ospf6, type, instance);
|
|
|
|
if (!red || red->dmetric.value < 0) {
|
|
|
|
if (type == DEFAULT_ROUTE) {
|
|
|
|
if (ospf6->default_originate == DEFAULT_ORIGINATE_ZEBRA)
|
|
|
|
return DEFAULT_DEFAULT_ORIGINATE_METRIC;
|
|
|
|
else
|
|
|
|
return DEFAULT_DEFAULT_ALWAYS_METRIC;
|
|
|
|
} else
|
|
|
|
return DEFAULT_DEFAULT_METRIC;
|
|
|
|
}
|
|
|
|
|
|
|
|
return red->dmetric.value;
|
|
|
|
}
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* RFC2328: Section 13.2 */
|
2004-05-18 20:57:06 +02:00
|
|
|
int ospf6_lsa_is_differ(struct ospf6_lsa *lsa1, struct ospf6_lsa *lsa2)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2004-05-18 20:57:06 +02:00
|
|
|
int len;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2004-05-18 20:57:06 +02:00
|
|
|
assert(OSPF6_LSA_IS_SAME(lsa1, lsa2));
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2004-05-18 20:57:06 +02:00
|
|
|
/* XXX, Options ??? */
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
ospf6_lsa_age_current(lsa1);
|
|
|
|
ospf6_lsa_age_current(lsa2);
|
2013-10-23 02:42:18 +02:00
|
|
|
if (ntohs(lsa1->header->age) == OSPF_LSA_MAXAGE
|
|
|
|
&& ntohs(lsa2->header->age) != OSPF_LSA_MAXAGE)
|
2002-12-13 21:15:29 +01:00
|
|
|
return 1;
|
2013-10-23 02:42:18 +02:00
|
|
|
if (ntohs(lsa1->header->age) != OSPF_LSA_MAXAGE
|
|
|
|
&& ntohs(lsa2->header->age) == OSPF_LSA_MAXAGE)
|
2002-12-13 21:15:29 +01:00
|
|
|
return 1;
|
|
|
|
|
|
|
|
/* compare body */
|
2024-05-28 06:07:14 +02:00
|
|
|
if (ospf6_lsa_size(lsa1->header) != ospf6_lsa_size(lsa2->header))
|
2002-12-13 21:15:29 +01:00
|
|
|
return 1;
|
|
|
|
|
2024-05-28 06:07:14 +02:00
|
|
|
len = ospf6_lsa_size(lsa1->header) - sizeof(struct ospf6_lsa_header);
|
2004-05-18 20:57:06 +02:00
|
|
|
return memcmp(lsa1->header + 1, lsa2->header + 1, len);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2004-05-18 20:57:06 +02:00
|
|
|
int ospf6_lsa_is_changed(struct ospf6_lsa *lsa1, struct ospf6_lsa *lsa2)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2004-05-18 20:57:06 +02:00
|
|
|
int length;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2004-05-18 20:57:06 +02:00
|
|
|
if (OSPF6_LSA_IS_MAXAGE(lsa1) ^ OSPF6_LSA_IS_MAXAGE(lsa2))
|
|
|
|
return 1;
|
2024-05-28 06:07:14 +02:00
|
|
|
if (ospf6_lsa_size(lsa1->header) != ospf6_lsa_size(lsa2->header))
|
2004-05-18 20:57:06 +02:00
|
|
|
return 1;
|
2011-09-26 11:18:36 +02:00
|
|
|
/* Going beyond LSA headers to compare the payload only makes sense,
|
|
|
|
* when both LSAs aren't header-only. */
|
|
|
|
if (CHECK_FLAG(lsa1->flag, OSPF6_LSA_HEADERONLY)
|
|
|
|
!= CHECK_FLAG(lsa2->flag, OSPF6_LSA_HEADERONLY)) {
|
|
|
|
zlog_warn(
|
|
|
|
"%s: only one of two (%s, %s) LSAs compared is header-only",
|
|
|
|
__func__, lsa1->name, lsa2->name);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if (CHECK_FLAG(lsa1->flag, OSPF6_LSA_HEADERONLY))
|
|
|
|
return 0;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2024-05-28 06:07:14 +02:00
|
|
|
length = ospf6_lsa_size(lsa1->header) - sizeof(struct ospf6_lsa_header);
|
2011-09-26 11:18:36 +02:00
|
|
|
/* Once upper layer verifies LSAs received, length underrun should
|
|
|
|
* become a warning. */
|
|
|
|
if (length <= 0)
|
|
|
|
return 0;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2024-07-19 05:04:05 +02:00
|
|
|
return memcmp(lsa_after_header(lsa1->header),
|
|
|
|
lsa_after_header(lsa2->header), length);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ospf6 age functions */
|
2004-08-19 08:56:53 +02:00
|
|
|
/* calculate birth */
|
2018-01-17 19:55:46 +01:00
|
|
|
void ospf6_lsa_age_set(struct ospf6_lsa *lsa)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
|
|
|
struct timeval now;
|
|
|
|
|
|
|
|
assert(lsa && lsa->header);
|
|
|
|
|
2017-01-18 01:30:43 +01:00
|
|
|
monotime(&now);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
lsa->birth.tv_sec = now.tv_sec - ntohs(lsa->header->age);
|
|
|
|
lsa->birth.tv_usec = now.tv_usec;
|
2004-08-19 08:56:53 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* this function calculates current age from its birth,
|
|
|
|
then update age field of LSA header. return value is current age */
|
2018-03-27 21:13:34 +02:00
|
|
|
uint16_t ospf6_lsa_age_current(struct ospf6_lsa *lsa)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
|
|
|
struct timeval now;
|
2018-03-27 21:13:34 +02:00
|
|
|
uint32_t ulage;
|
|
|
|
uint16_t age;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
assert(lsa);
|
|
|
|
assert(lsa->header);
|
|
|
|
|
|
|
|
/* current time */
|
2017-01-18 01:30:43 +01:00
|
|
|
monotime(&now);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2013-10-23 02:42:18 +02:00
|
|
|
if (ntohs(lsa->header->age) >= OSPF_LSA_MAXAGE) {
|
2009-08-28 16:10:00 +02:00
|
|
|
/* ospf6_lsa_premature_aging () sets age to MAXAGE; when using
|
|
|
|
relative time, we cannot compare against lsa birth time, so
|
|
|
|
we catch this special case here. */
|
2013-10-23 02:42:18 +02:00
|
|
|
lsa->header->age = htons(OSPF_LSA_MAXAGE);
|
|
|
|
return OSPF_LSA_MAXAGE;
|
2009-07-16 18:20:37 +02:00
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
/* calculate age */
|
|
|
|
ulage = now.tv_sec - lsa->birth.tv_sec;
|
|
|
|
|
|
|
|
/* if over MAXAGE, set to it */
|
2013-10-23 02:42:18 +02:00
|
|
|
age = (ulage > OSPF_LSA_MAXAGE ? OSPF_LSA_MAXAGE : ulage);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
lsa->header->age = htons(age);
|
|
|
|
return age;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* update age field of LSA header with adding InfTransDelay */
|
2018-03-27 21:13:34 +02:00
|
|
|
void ospf6_lsa_age_update_to_send(struct ospf6_lsa *lsa, uint32_t transdelay)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
|
|
|
unsigned short age;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
age = ospf6_lsa_age_current(lsa) + transdelay;
|
2013-10-23 02:42:18 +02:00
|
|
|
if (age > OSPF_LSA_MAXAGE)
|
|
|
|
age = OSPF_LSA_MAXAGE;
|
2002-12-13 21:15:29 +01:00
|
|
|
lsa->header->age = htons(age);
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
void ospf6_lsa_premature_aging(struct ospf6_lsa *lsa)
|
|
|
|
{
|
|
|
|
/* log */
|
2004-09-01 23:36:14 +02:00
|
|
|
if (IS_OSPF6_DEBUG_LSA_TYPE(lsa->header->type))
|
2004-12-24 07:00:11 +01:00
|
|
|
zlog_debug("LSA: Premature aging: %s", lsa->name);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2022-12-25 16:26:52 +01:00
|
|
|
EVENT_OFF(lsa->expire);
|
|
|
|
EVENT_OFF(lsa->refresh);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2013-08-24 09:54:24 +02:00
|
|
|
/*
|
|
|
|
* We clear the LSA from the neighbor retx lists now because it
|
|
|
|
* will not get deleted later. Essentially, changing the age to
|
|
|
|
* MaxAge will prevent this LSA from being matched with its
|
|
|
|
* existing entries in the retx list thereby causing those entries
|
|
|
|
* to be silently replaced with its MaxAged version, but with ever
|
|
|
|
* increasing retx count causing this LSA to remain forever and
|
|
|
|
* for the MaxAge remover thread to be called forever too.
|
|
|
|
*
|
|
|
|
* The reason the previous entry silently disappears is that when
|
|
|
|
* entry is added to a neighbor's retx list, it replaces the existing
|
|
|
|
* entry. But since the ospf6_lsdb_add() routine is generic and not
|
|
|
|
* aware
|
|
|
|
* of the special semantics of retx count, the retx count is not
|
|
|
|
* decremented when its replaced. Attempting to add the incr and decr
|
|
|
|
* retx count routines as the hook_add and hook_remove for the retx
|
|
|
|
* lists
|
|
|
|
* have a problem because the hook_remove routine is called for MaxAge
|
|
|
|
* entries (as will be the case in a traditional LSDB, unlike in this
|
|
|
|
* case
|
|
|
|
* where an LSDB is used as an efficient tree structure to store all
|
|
|
|
* kinds
|
|
|
|
* of data) that are added instead of calling the hook_add routine.
|
|
|
|
*/
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2013-08-24 09:54:24 +02:00
|
|
|
ospf6_flood_clear(lsa);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2013-10-23 02:42:18 +02:00
|
|
|
lsa->header->age = htons(OSPF_LSA_MAXAGE);
|
2023-07-11 22:03:38 +02:00
|
|
|
event_execute(master, ospf6_lsa_expire, lsa, 0, NULL);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* check which is more recent. if a is more recent, return -1;
|
|
|
|
if the same, return 0; otherwise(b is more recent), return 1 */
|
2004-05-18 20:57:06 +02:00
|
|
|
int ospf6_lsa_compare(struct ospf6_lsa *a, struct ospf6_lsa *b)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2009-12-17 06:41:17 +01:00
|
|
|
int32_t seqnuma, seqnumb;
|
2018-03-27 21:13:34 +02:00
|
|
|
uint16_t cksuma, cksumb;
|
|
|
|
uint16_t agea, ageb;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
assert(a && a->header);
|
|
|
|
assert(b && b->header);
|
2004-05-18 20:57:06 +02:00
|
|
|
assert(OSPF6_LSA_IS_SAME(a, b));
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
seqnuma = (int32_t)ntohl(a->header->seqnum);
|
|
|
|
seqnumb = (int32_t)ntohl(b->header->seqnum);
|
|
|
|
|
|
|
|
/* compare by sequence number */
|
|
|
|
if (seqnuma > seqnumb)
|
|
|
|
return -1;
|
2009-12-07 10:33:20 +01:00
|
|
|
if (seqnuma < seqnumb)
|
2002-12-13 21:15:29 +01:00
|
|
|
return 1;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Checksum */
|
|
|
|
cksuma = ntohs(a->header->checksum);
|
|
|
|
cksumb = ntohs(b->header->checksum);
|
|
|
|
if (cksuma > cksumb)
|
|
|
|
return -1;
|
|
|
|
if (cksuma < cksumb)
|
|
|
|
return 0;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-05-18 20:57:06 +02:00
|
|
|
/* Update Age */
|
2002-12-13 21:15:29 +01:00
|
|
|
agea = ospf6_lsa_age_current(a);
|
|
|
|
ageb = ospf6_lsa_age_current(b);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-05-18 20:57:06 +02:00
|
|
|
/* MaxAge check */
|
2013-10-23 02:42:18 +02:00
|
|
|
if (agea == OSPF_LSA_MAXAGE && ageb != OSPF_LSA_MAXAGE)
|
2002-12-13 21:15:29 +01:00
|
|
|
return -1;
|
2013-10-23 02:42:18 +02:00
|
|
|
else if (agea != OSPF_LSA_MAXAGE && ageb == OSPF_LSA_MAXAGE)
|
2002-12-13 21:15:29 +01:00
|
|
|
return 1;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-05-18 20:57:06 +02:00
|
|
|
/* Age check */
|
2013-10-23 02:42:18 +02:00
|
|
|
if (agea > ageb && agea - ageb >= OSPF_LSA_MAXAGE_DIFF)
|
2002-12-13 21:15:29 +01:00
|
|
|
return 1;
|
2013-10-23 02:42:18 +02:00
|
|
|
else if (agea < ageb && ageb - agea >= OSPF_LSA_MAXAGE_DIFF)
|
2002-12-13 21:15:29 +01:00
|
|
|
return -1;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* neither recent */
|
|
|
|
return 0;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-05-18 20:57:06 +02:00
|
|
|
char *ospf6_lsa_printbuf(struct ospf6_lsa *lsa, char *buf, int size)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2004-05-18 20:57:06 +02:00
|
|
|
char id[16], adv_router[16];
|
|
|
|
inet_ntop(AF_INET, &lsa->header->id, id, sizeof(id));
|
|
|
|
inet_ntop(AF_INET, &lsa->header->adv_router, adv_router,
|
|
|
|
sizeof(adv_router));
|
|
|
|
snprintf(buf, size, "[%s Id:%s Adv:%s]",
|
2004-09-01 23:36:14 +02:00
|
|
|
ospf6_lstype_name(lsa->header->type), id, adv_router);
|
2004-05-18 20:57:06 +02:00
|
|
|
return buf;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-05-18 20:57:06 +02:00
|
|
|
void ospf6_lsa_header_print_raw(struct ospf6_lsa_header *header)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2004-05-18 20:57:06 +02:00
|
|
|
char id[16], adv_router[16];
|
|
|
|
inet_ntop(AF_INET, &header->id, id, sizeof(id));
|
|
|
|
inet_ntop(AF_INET, &header->adv_router, adv_router, sizeof(adv_router));
|
2004-12-24 07:00:11 +01:00
|
|
|
zlog_debug(" [%s Id:%s Adv:%s]", ospf6_lstype_name(header->type), id,
|
|
|
|
adv_router);
|
|
|
|
zlog_debug(" Age: %4hu SeqNum: %#08lx Cksum: %04hx Len: %d",
|
2018-03-27 21:13:34 +02:00
|
|
|
ntohs(header->age), (unsigned long)ntohl(header->seqnum),
|
2004-12-24 07:00:11 +01:00
|
|
|
ntohs(header->checksum), ntohs(header->length));
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-05-18 20:57:06 +02:00
|
|
|
void ospf6_lsa_header_print(struct ospf6_lsa *lsa)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2004-05-18 20:57:06 +02:00
|
|
|
ospf6_lsa_age_current(lsa);
|
|
|
|
ospf6_lsa_header_print_raw(lsa->header);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
void ospf6_lsa_show_summary_header(struct vty *vty)
|
|
|
|
{
|
2017-07-13 19:42:42 +02:00
|
|
|
vty_out(vty, "%-4s %-15s%-15s%4s %8s %30s\n", "Type", "LSId",
|
2002-12-13 21:15:29 +01:00
|
|
|
"AdvRouter", "Age", "SeqNum", "Payload");
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2020-12-04 06:54:40 +01:00
|
|
|
void ospf6_lsa_show_summary(struct vty *vty, struct ospf6_lsa *lsa,
|
|
|
|
json_object *json_array, bool use_json)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2004-05-18 20:57:06 +02:00
|
|
|
char adv_router[16], id[16];
|
2013-08-25 05:03:23 +02:00
|
|
|
int type;
|
2017-10-08 18:20:12 +02:00
|
|
|
const struct ospf6_lsa_handler *handler;
|
2020-12-04 06:54:40 +01:00
|
|
|
char buf[64];
|
2013-08-25 05:03:23 +02:00
|
|
|
int cnt = 0;
|
2020-12-04 06:54:40 +01:00
|
|
|
json_object *json_obj = NULL;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
assert(lsa);
|
|
|
|
assert(lsa->header);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
inet_ntop(AF_INET, &lsa->header->id, id, sizeof(id));
|
|
|
|
inet_ntop(AF_INET, &lsa->header->adv_router, adv_router,
|
|
|
|
sizeof(adv_router));
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2013-08-25 05:03:23 +02:00
|
|
|
type = ntohs(lsa->header->type);
|
|
|
|
handler = ospf6_get_lsa_handler(lsa->header->type);
|
2020-12-04 06:54:40 +01:00
|
|
|
|
|
|
|
if (use_json)
|
|
|
|
json_obj = json_object_new_object();
|
|
|
|
|
2021-02-23 18:07:28 +01:00
|
|
|
switch (type) {
|
|
|
|
case OSPF6_LSTYPE_INTER_PREFIX:
|
|
|
|
case OSPF6_LSTYPE_INTER_ROUTER:
|
|
|
|
case OSPF6_LSTYPE_AS_EXTERNAL:
|
2021-03-25 12:29:51 +01:00
|
|
|
case OSPF6_LSTYPE_TYPE_7:
|
2020-12-04 06:54:40 +01:00
|
|
|
if (use_json) {
|
|
|
|
json_object_string_add(
|
|
|
|
json_obj, "type",
|
|
|
|
ospf6_lstype_short_name(lsa->header->type));
|
|
|
|
json_object_string_add(json_obj, "lsId", id);
|
|
|
|
json_object_string_add(json_obj, "advRouter",
|
|
|
|
adv_router);
|
|
|
|
json_object_int_add(json_obj, "age",
|
|
|
|
ospf6_lsa_age_current(lsa));
|
|
|
|
json_object_int_add(
|
|
|
|
json_obj, "seqNum",
|
|
|
|
(unsigned long)ntohl(lsa->header->seqnum));
|
|
|
|
json_object_string_add(
|
|
|
|
json_obj, "payload",
|
|
|
|
handler->lh_get_prefix_str(lsa, buf,
|
|
|
|
sizeof(buf), 0));
|
|
|
|
json_object_array_add(json_array, json_obj);
|
|
|
|
} else
|
|
|
|
vty_out(vty, "%-4s %-15s%-15s%4hu %8lx %30s\n",
|
|
|
|
ospf6_lstype_short_name(lsa->header->type), id,
|
|
|
|
adv_router, ospf6_lsa_age_current(lsa),
|
|
|
|
(unsigned long)ntohl(lsa->header->seqnum),
|
|
|
|
handler->lh_get_prefix_str(lsa, buf,
|
|
|
|
sizeof(buf), 0));
|
2021-02-23 18:07:28 +01:00
|
|
|
break;
|
|
|
|
case OSPF6_LSTYPE_ROUTER:
|
|
|
|
case OSPF6_LSTYPE_NETWORK:
|
|
|
|
case OSPF6_LSTYPE_GROUP_MEMBERSHIP:
|
|
|
|
case OSPF6_LSTYPE_LINK:
|
|
|
|
case OSPF6_LSTYPE_INTRA_PREFIX:
|
2017-10-08 18:20:12 +02:00
|
|
|
while (handler->lh_get_prefix_str(lsa, buf, sizeof(buf), cnt)
|
2013-08-25 05:03:23 +02:00
|
|
|
!= NULL) {
|
2020-12-04 06:54:40 +01:00
|
|
|
if (use_json) {
|
|
|
|
json_object_string_add(
|
|
|
|
json_obj, "type",
|
|
|
|
ospf6_lstype_short_name(
|
|
|
|
lsa->header->type));
|
|
|
|
json_object_string_add(json_obj, "lsId", id);
|
|
|
|
json_object_string_add(json_obj, "advRouter",
|
|
|
|
adv_router);
|
|
|
|
json_object_int_add(json_obj, "age",
|
|
|
|
ospf6_lsa_age_current(lsa));
|
|
|
|
json_object_int_add(
|
|
|
|
json_obj, "seqNum",
|
|
|
|
(unsigned long)ntohl(
|
|
|
|
lsa->header->seqnum));
|
|
|
|
json_object_string_add(json_obj, "payload",
|
|
|
|
buf);
|
|
|
|
json_object_array_add(json_array, json_obj);
|
|
|
|
json_obj = json_object_new_object();
|
|
|
|
} else
|
|
|
|
vty_out(vty, "%-4s %-15s%-15s%4hu %8lx %30s\n",
|
|
|
|
ospf6_lstype_short_name(
|
|
|
|
lsa->header->type),
|
|
|
|
id, adv_router,
|
|
|
|
ospf6_lsa_age_current(lsa),
|
|
|
|
(unsigned long)ntohl(
|
|
|
|
lsa->header->seqnum),
|
|
|
|
buf);
|
2013-08-25 05:03:23 +02:00
|
|
|
cnt++;
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2020-12-04 06:54:40 +01:00
|
|
|
if (use_json)
|
|
|
|
json_object_free(json_obj);
|
2021-02-23 18:07:28 +01:00
|
|
|
break;
|
|
|
|
default:
|
2020-12-04 06:54:40 +01:00
|
|
|
if (use_json) {
|
|
|
|
json_object_string_add(
|
|
|
|
json_obj, "type",
|
|
|
|
ospf6_lstype_short_name(lsa->header->type));
|
|
|
|
json_object_string_add(json_obj, "lsId", id);
|
|
|
|
json_object_string_add(json_obj, "advRouter",
|
|
|
|
adv_router);
|
|
|
|
json_object_int_add(json_obj, "age",
|
|
|
|
ospf6_lsa_age_current(lsa));
|
|
|
|
json_object_int_add(
|
|
|
|
json_obj, "seqNum",
|
|
|
|
(unsigned long)ntohl(lsa->header->seqnum));
|
|
|
|
json_object_array_add(json_array, json_obj);
|
|
|
|
} else
|
|
|
|
vty_out(vty, "%-4s %-15s%-15s%4hu %8lx\n",
|
|
|
|
ospf6_lstype_short_name(lsa->header->type), id,
|
|
|
|
adv_router, ospf6_lsa_age_current(lsa),
|
|
|
|
(unsigned long)ntohl(lsa->header->seqnum));
|
2021-02-23 18:07:28 +01:00
|
|
|
break;
|
2013-08-25 05:03:23 +02:00
|
|
|
}
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2020-12-04 06:54:40 +01:00
|
|
|
void ospf6_lsa_show_dump(struct vty *vty, struct ospf6_lsa *lsa,
|
|
|
|
json_object *json_array, bool use_json)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2021-08-10 17:42:52 +02:00
|
|
|
uint8_t *start = NULL;
|
|
|
|
uint8_t *end = NULL;
|
|
|
|
uint8_t *current = NULL;
|
2002-12-13 21:15:29 +01:00
|
|
|
char byte[4];
|
2021-08-10 17:42:52 +02:00
|
|
|
char *header_str = NULL;
|
|
|
|
char adv_router[INET6_ADDRSTRLEN];
|
|
|
|
char id[INET6_ADDRSTRLEN];
|
|
|
|
json_object *json = NULL;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2018-03-27 21:13:34 +02:00
|
|
|
start = (uint8_t *)lsa->header;
|
2024-05-21 02:39:47 +02:00
|
|
|
end = (uint8_t *)ospf6_lsa_end(lsa->header);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2021-08-10 17:42:52 +02:00
|
|
|
if (use_json) {
|
|
|
|
json = json_object_new_object();
|
|
|
|
size_t header_str_sz = (2 * (end - start)) + 1;
|
2020-12-04 06:54:40 +01:00
|
|
|
|
2022-12-05 18:10:25 +01:00
|
|
|
header_str = XMALLOC(MTYPE_OSPF6_LSA_HEADER, header_str_sz);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2021-08-10 17:42:52 +02:00
|
|
|
inet_ntop(AF_INET, &lsa->header->id, id, sizeof(id));
|
|
|
|
inet_ntop(AF_INET, &lsa->header->adv_router, adv_router,
|
|
|
|
sizeof(adv_router));
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2021-08-10 17:42:52 +02:00
|
|
|
frrstr_hex(header_str, header_str_sz, start, end - start);
|
|
|
|
|
|
|
|
json_object_string_add(json, "linkStateId", id);
|
|
|
|
json_object_string_add(json, "advertisingRouter", adv_router);
|
|
|
|
json_object_string_add(json, "header", header_str);
|
|
|
|
json_object_array_add(json_array, json);
|
|
|
|
|
2022-12-05 18:10:25 +01:00
|
|
|
XFREE(MTYPE_OSPF6_LSA_HEADER, header_str);
|
2021-08-10 17:42:52 +02:00
|
|
|
} else {
|
|
|
|
vty_out(vty, "\n%s:\n", lsa->name);
|
|
|
|
|
|
|
|
for (current = start; current < end; current++) {
|
|
|
|
if ((current - start) % 16 == 0)
|
|
|
|
vty_out(vty, "\n ");
|
|
|
|
else if ((current - start) % 4 == 0)
|
|
|
|
vty_out(vty, " ");
|
|
|
|
|
|
|
|
snprintf(byte, sizeof(byte), "%02x", *current);
|
|
|
|
vty_out(vty, "%s", byte);
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2021-08-10 17:42:52 +02:00
|
|
|
vty_out(vty, "\n\n");
|
|
|
|
}
|
2020-12-04 06:54:40 +01:00
|
|
|
|
2004-08-15 07:52:07 +02:00
|
|
|
return;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2020-12-04 06:54:40 +01:00
|
|
|
void ospf6_lsa_show_internal(struct vty *vty, struct ospf6_lsa *lsa,
|
|
|
|
json_object *json_array, bool use_json)
|
2004-05-18 20:57:06 +02:00
|
|
|
{
|
|
|
|
char adv_router[64], id[64];
|
2020-12-04 06:54:40 +01:00
|
|
|
json_object *json_obj;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-05-18 20:57:06 +02:00
|
|
|
assert(lsa && lsa->header);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-05-18 20:57:06 +02:00
|
|
|
inet_ntop(AF_INET, &lsa->header->id, id, sizeof(id));
|
|
|
|
inet_ntop(AF_INET, &lsa->header->adv_router, adv_router,
|
|
|
|
sizeof(adv_router));
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2020-12-04 06:54:40 +01:00
|
|
|
if (use_json) {
|
|
|
|
json_obj = json_object_new_object();
|
|
|
|
json_object_int_add(json_obj, "age",
|
|
|
|
ospf6_lsa_age_current(lsa));
|
|
|
|
json_object_string_add(json_obj, "type",
|
|
|
|
ospf6_lstype_name(lsa->header->type));
|
|
|
|
json_object_string_add(json_obj, "linkStateId", id);
|
|
|
|
json_object_string_add(json_obj, "advertisingRouter",
|
|
|
|
adv_router);
|
|
|
|
json_object_int_add(json_obj, "lsSequenceNumber",
|
|
|
|
(unsigned long)ntohl(lsa->header->seqnum));
|
|
|
|
json_object_int_add(json_obj, "checksum",
|
|
|
|
ntohs(lsa->header->checksum));
|
|
|
|
json_object_int_add(json_obj, "length",
|
2024-05-28 06:07:14 +02:00
|
|
|
ospf6_lsa_size(lsa->header));
|
2020-12-04 06:54:40 +01:00
|
|
|
json_object_int_add(json_obj, "flag", lsa->flag);
|
|
|
|
json_object_int_add(json_obj, "lock", lsa->lock);
|
|
|
|
json_object_int_add(json_obj, "reTxCount", lsa->retrans_count);
|
|
|
|
|
|
|
|
/* Threads Data not added */
|
|
|
|
json_object_array_add(json_array, json_obj);
|
|
|
|
} else {
|
|
|
|
vty_out(vty, "\n");
|
|
|
|
vty_out(vty, "Age: %4hu Type: %s\n", ospf6_lsa_age_current(lsa),
|
|
|
|
ospf6_lstype_name(lsa->header->type));
|
|
|
|
vty_out(vty, "Link State ID: %s\n", id);
|
|
|
|
vty_out(vty, "Advertising Router: %s\n", adv_router);
|
|
|
|
vty_out(vty, "LS Sequence Number: %#010lx\n",
|
|
|
|
(unsigned long)ntohl(lsa->header->seqnum));
|
|
|
|
vty_out(vty, "CheckSum: %#06hx Length: %hu\n",
|
|
|
|
ntohs(lsa->header->checksum),
|
2024-05-28 06:07:14 +02:00
|
|
|
ospf6_lsa_size(lsa->header));
|
2020-12-04 06:54:40 +01:00
|
|
|
vty_out(vty, "Flag: %x \n", lsa->flag);
|
|
|
|
vty_out(vty, "Lock: %d \n", lsa->lock);
|
|
|
|
vty_out(vty, "ReTx Count: %d\n", lsa->retrans_count);
|
2021-05-31 15:27:51 +02:00
|
|
|
vty_out(vty, "Threads: Expire: %p, Refresh: %p\n", lsa->expire,
|
|
|
|
lsa->refresh);
|
2020-12-04 06:54:40 +01:00
|
|
|
vty_out(vty, "\n");
|
|
|
|
}
|
2004-08-15 07:52:07 +02:00
|
|
|
return;
|
2004-05-18 20:57:06 +02:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2020-12-04 06:54:40 +01:00
|
|
|
void ospf6_lsa_show(struct vty *vty, struct ospf6_lsa *lsa,
|
|
|
|
json_object *json_array, bool use_json)
|
2004-08-15 07:52:07 +02:00
|
|
|
{
|
|
|
|
char adv_router[64], id[64];
|
2017-10-08 18:20:12 +02:00
|
|
|
const struct ospf6_lsa_handler *handler;
|
2013-08-25 05:03:23 +02:00
|
|
|
struct timeval now, res;
|
2017-07-28 00:19:31 +02:00
|
|
|
char duration[64];
|
2020-12-04 06:54:40 +01:00
|
|
|
json_object *json_obj = NULL;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-08-15 07:52:07 +02:00
|
|
|
assert(lsa && lsa->header);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-08-15 07:52:07 +02:00
|
|
|
inet_ntop(AF_INET, &lsa->header->id, id, sizeof(id));
|
|
|
|
inet_ntop(AF_INET, &lsa->header->adv_router, adv_router,
|
|
|
|
sizeof(adv_router));
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-01-18 01:30:43 +01:00
|
|
|
monotime(&now);
|
2013-08-25 05:03:23 +02:00
|
|
|
timersub(&now, &lsa->installed, &res);
|
|
|
|
timerstring(&res, duration, sizeof(duration));
|
2020-12-04 06:54:40 +01:00
|
|
|
if (use_json) {
|
|
|
|
json_obj = json_object_new_object();
|
|
|
|
json_object_int_add(json_obj, "age",
|
|
|
|
ospf6_lsa_age_current(lsa));
|
|
|
|
json_object_string_add(json_obj, "type",
|
|
|
|
ospf6_lstype_name(lsa->header->type));
|
2021-06-14 08:41:10 +02:00
|
|
|
json_object_string_add(json_obj, "linkStateId", id);
|
2020-12-04 06:54:40 +01:00
|
|
|
json_object_string_add(json_obj, "advertisingRouter",
|
|
|
|
adv_router);
|
|
|
|
json_object_int_add(json_obj, "lsSequenceNumber",
|
|
|
|
(unsigned long)ntohl(lsa->header->seqnum));
|
2021-06-14 08:21:42 +02:00
|
|
|
json_object_int_add(json_obj, "checksum",
|
2020-12-04 06:54:40 +01:00
|
|
|
ntohs(lsa->header->checksum));
|
|
|
|
json_object_int_add(json_obj, "length",
|
|
|
|
ntohs(lsa->header->length));
|
|
|
|
json_object_string_add(json_obj, "duration", duration);
|
|
|
|
} else {
|
|
|
|
vty_out(vty, "Age: %4hu Type: %s\n", ospf6_lsa_age_current(lsa),
|
|
|
|
ospf6_lstype_name(lsa->header->type));
|
|
|
|
vty_out(vty, "Link State ID: %s\n", id);
|
|
|
|
vty_out(vty, "Advertising Router: %s\n", adv_router);
|
|
|
|
vty_out(vty, "LS Sequence Number: %#010lx\n",
|
|
|
|
(unsigned long)ntohl(lsa->header->seqnum));
|
|
|
|
vty_out(vty, "CheckSum: %#06hx Length: %hu\n",
|
|
|
|
ntohs(lsa->header->checksum),
|
|
|
|
ntohs(lsa->header->length));
|
|
|
|
vty_out(vty, "Duration: %s\n", duration);
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-09-01 23:36:14 +02:00
|
|
|
handler = ospf6_get_lsa_handler(lsa->header->type);
|
2017-10-08 18:20:12 +02:00
|
|
|
|
|
|
|
if (handler->lh_show != NULL)
|
2020-12-04 06:54:40 +01:00
|
|
|
handler->lh_show(vty, lsa, json_obj, use_json);
|
2017-10-08 18:20:12 +02:00
|
|
|
else {
|
|
|
|
assert(unknown_handler.lh_show != NULL);
|
2020-12-04 06:54:40 +01:00
|
|
|
unknown_handler.lh_show(vty, lsa, json_obj, use_json);
|
2017-10-08 18:20:12 +02:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2020-12-04 06:54:40 +01:00
|
|
|
if (use_json)
|
|
|
|
json_object_array_add(json_array, json_obj);
|
|
|
|
else
|
|
|
|
vty_out(vty, "\n");
|
2004-08-15 07:52:07 +02:00
|
|
|
}
|
|
|
|
|
2021-03-22 19:24:59 +01:00
|
|
|
struct ospf6_lsa *ospf6_lsa_alloc(size_t lsa_length)
|
|
|
|
{
|
2021-03-22 19:31:56 +01:00
|
|
|
struct ospf6_lsa *lsa;
|
|
|
|
|
2021-03-22 19:24:59 +01:00
|
|
|
lsa = XCALLOC(MTYPE_OSPF6_LSA, sizeof(struct ospf6_lsa));
|
|
|
|
lsa->header = XMALLOC(MTYPE_OSPF6_LSA_HEADER, lsa_length);
|
|
|
|
|
|
|
|
return lsa;
|
|
|
|
}
|
|
|
|
|
2004-08-15 07:52:07 +02:00
|
|
|
/* OSPFv3 LSA creation/deletion function */
|
2004-05-18 20:57:06 +02:00
|
|
|
struct ospf6_lsa *ospf6_lsa_create(struct ospf6_lsa_header *header)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
|
|
|
struct ospf6_lsa *lsa = NULL;
|
2018-03-27 21:13:34 +02:00
|
|
|
uint16_t lsa_size = 0;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2004-05-18 20:57:06 +02:00
|
|
|
/* size of the entire LSA */
|
2024-05-28 06:07:14 +02:00
|
|
|
lsa_size = ospf6_lsa_size(header); /* XXX vulnerable */
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2021-03-22 19:24:59 +01:00
|
|
|
lsa = ospf6_lsa_alloc(lsa_size);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2004-05-18 20:57:06 +02:00
|
|
|
/* copy LSA from original header */
|
2021-03-22 19:24:59 +01:00
|
|
|
memcpy(lsa->header, header, lsa_size);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
/* dump string */
|
2004-05-18 20:57:06 +02:00
|
|
|
ospf6_lsa_printbuf(lsa, lsa->name, sizeof(lsa->name));
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2004-08-19 08:56:53 +02:00
|
|
|
/* calculate birth of this lsa */
|
2002-12-13 21:15:29 +01:00
|
|
|
ospf6_lsa_age_set(lsa);
|
|
|
|
|
|
|
|
return lsa;
|
|
|
|
}
|
|
|
|
|
2004-05-18 20:57:06 +02:00
|
|
|
struct ospf6_lsa *ospf6_lsa_create_headeronly(struct ospf6_lsa_header *header)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
|
|
|
struct ospf6_lsa *lsa = NULL;
|
|
|
|
|
2021-03-22 19:24:59 +01:00
|
|
|
lsa = ospf6_lsa_alloc(sizeof(struct ospf6_lsa_header));
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2021-03-22 19:24:59 +01:00
|
|
|
memcpy(lsa->header, header, sizeof(struct ospf6_lsa_header));
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2004-08-15 07:52:07 +02:00
|
|
|
SET_FLAG(lsa->flag, OSPF6_LSA_HEADERONLY);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
/* dump string */
|
2004-05-18 20:57:06 +02:00
|
|
|
ospf6_lsa_printbuf(lsa, lsa->name, sizeof(lsa->name));
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2004-08-19 08:56:53 +02:00
|
|
|
/* calculate birth of this lsa */
|
2002-12-13 21:15:29 +01:00
|
|
|
ospf6_lsa_age_set(lsa);
|
|
|
|
|
|
|
|
return lsa;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ospf6_lsa_delete(struct ospf6_lsa *lsa)
|
|
|
|
{
|
2004-05-18 20:57:06 +02:00
|
|
|
assert(lsa->lock == 0);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
/* cancel threads */
|
2022-12-25 16:26:52 +01:00
|
|
|
EVENT_OFF(lsa->expire);
|
|
|
|
EVENT_OFF(lsa->refresh);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
/* do free */
|
2017-07-13 20:39:22 +02:00
|
|
|
XFREE(MTYPE_OSPF6_LSA_HEADER, lsa->header);
|
2004-05-18 20:57:06 +02:00
|
|
|
XFREE(MTYPE_OSPF6_LSA, lsa);
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2004-05-18 20:57:06 +02:00
|
|
|
struct ospf6_lsa *ospf6_lsa_copy(struct ospf6_lsa *lsa)
|
|
|
|
{
|
|
|
|
struct ospf6_lsa *copy = NULL;
|
|
|
|
|
|
|
|
ospf6_lsa_age_current(lsa);
|
2004-08-15 07:52:07 +02:00
|
|
|
if (CHECK_FLAG(lsa->flag, OSPF6_LSA_HEADERONLY))
|
2004-05-18 20:57:06 +02:00
|
|
|
copy = ospf6_lsa_create_headeronly(lsa->header);
|
2002-12-13 21:15:29 +01:00
|
|
|
else
|
2004-05-18 20:57:06 +02:00
|
|
|
copy = ospf6_lsa_create(lsa->header);
|
|
|
|
assert(copy->lock == 0);
|
|
|
|
|
2004-08-19 08:56:53 +02:00
|
|
|
copy->birth = lsa->birth;
|
2004-05-18 20:57:06 +02:00
|
|
|
copy->originated = lsa->originated;
|
2004-08-25 11:10:37 +02:00
|
|
|
copy->received = lsa->received;
|
|
|
|
copy->installed = lsa->installed;
|
2004-08-15 07:52:07 +02:00
|
|
|
copy->lsdb = lsa->lsdb;
|
2013-08-24 09:55:14 +02:00
|
|
|
copy->rn = NULL;
|
2004-05-18 20:57:06 +02:00
|
|
|
|
|
|
|
return copy;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2004-05-18 20:57:06 +02:00
|
|
|
/* increment reference counter of struct ospf6_lsa */
|
2020-10-11 17:13:33 +02:00
|
|
|
struct ospf6_lsa *ospf6_lsa_lock(struct ospf6_lsa *lsa)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
|
|
|
lsa->lock++;
|
2020-10-11 17:13:33 +02:00
|
|
|
return lsa;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2004-05-18 20:57:06 +02:00
|
|
|
/* decrement reference counter of struct ospf6_lsa */
|
2023-07-05 15:28:50 +02:00
|
|
|
void ospf6_lsa_unlock(struct ospf6_lsa **lsa)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
|
|
|
/* decrement reference counter */
|
2023-07-05 15:28:50 +02:00
|
|
|
assert((*lsa)->lock > 0);
|
|
|
|
(*lsa)->lock--;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2023-07-05 15:28:50 +02:00
|
|
|
if ((*lsa)->lock != 0)
|
|
|
|
return;
|
2004-05-18 20:57:06 +02:00
|
|
|
|
2023-07-05 15:28:50 +02:00
|
|
|
ospf6_lsa_delete(*lsa);
|
|
|
|
*lsa = NULL;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2004-05-18 20:57:06 +02:00
|
|
|
/* ospf6 lsa expiry */
|
2022-03-01 22:18:12 +01:00
|
|
|
void ospf6_lsa_expire(struct event *thread)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
|
|
|
struct ospf6_lsa *lsa;
|
2020-10-08 07:38:43 +02:00
|
|
|
struct ospf6 *ospf6;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2022-12-25 16:26:52 +01:00
|
|
|
lsa = (struct ospf6_lsa *)EVENT_ARG(thread);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2004-05-18 20:57:06 +02:00
|
|
|
assert(lsa && lsa->header);
|
|
|
|
assert(OSPF6_LSA_IS_MAXAGE(lsa));
|
|
|
|
assert(!lsa->refresh);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2022-03-01 22:18:12 +01:00
|
|
|
lsa->expire = (struct event *)NULL;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2004-09-01 23:36:14 +02:00
|
|
|
if (IS_OSPF6_DEBUG_LSA_TYPE(lsa->header->type)) {
|
2004-12-24 07:00:11 +01:00
|
|
|
zlog_debug("LSA Expire:");
|
2004-05-18 20:57:06 +02:00
|
|
|
ospf6_lsa_header_print(lsa);
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2004-08-15 07:52:07 +02:00
|
|
|
if (CHECK_FLAG(lsa->flag, OSPF6_LSA_HEADERONLY))
|
2022-02-23 01:04:25 +01:00
|
|
|
return; /* dbexchange will do something ... */
|
2020-10-08 07:38:43 +02:00
|
|
|
ospf6 = ospf6_get_by_lsdb(lsa);
|
2021-05-28 11:33:03 +02:00
|
|
|
assert(ospf6);
|
|
|
|
|
2004-05-18 20:57:06 +02:00
|
|
|
/* reinstall lsa */
|
2004-08-19 08:56:53 +02:00
|
|
|
ospf6_install_lsa(lsa);
|
2004-05-18 20:57:06 +02:00
|
|
|
|
2013-08-24 09:54:50 +02:00
|
|
|
/* reflood lsa */
|
|
|
|
ospf6_flood(NULL, lsa);
|
|
|
|
|
2004-05-18 20:57:06 +02:00
|
|
|
/* schedule maxage remover */
|
|
|
|
ospf6_maxage_remove(ospf6);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2022-03-01 22:18:12 +01:00
|
|
|
void ospf6_lsa_refresh(struct event *thread)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2004-08-15 07:52:07 +02:00
|
|
|
struct ospf6_lsa *old, *self, *new;
|
|
|
|
struct ospf6_lsdb *lsdb_self;
|
|
|
|
|
2022-12-25 16:26:52 +01:00
|
|
|
old = (struct ospf6_lsa *)EVENT_ARG(thread);
|
2004-08-15 07:52:07 +02:00
|
|
|
assert(old && old->header);
|
|
|
|
|
2022-03-01 22:18:12 +01:00
|
|
|
old->refresh = (struct event *)NULL;
|
2004-08-15 07:52:07 +02:00
|
|
|
|
|
|
|
lsdb_self = ospf6_get_scoped_lsdb_self(old);
|
|
|
|
self = ospf6_lsdb_lookup(old->header->type, old->header->id,
|
|
|
|
old->header->adv_router, lsdb_self);
|
|
|
|
if (self == NULL) {
|
|
|
|
if (IS_OSPF6_DEBUG_LSA_TYPE(old->header->type))
|
|
|
|
zlog_debug("Refresh: could not find self LSA, flush %s",
|
2004-12-24 07:00:11 +01:00
|
|
|
old->name);
|
2004-08-15 07:52:07 +02:00
|
|
|
ospf6_lsa_premature_aging(old);
|
2022-02-23 01:04:25 +01:00
|
|
|
return;
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2004-09-01 23:36:14 +02:00
|
|
|
/* Reset age, increment LS sequence number. */
|
2004-08-15 07:52:07 +02:00
|
|
|
self->header->age = htons(0);
|
|
|
|
self->header->seqnum =
|
|
|
|
ospf6_new_ls_seqnum(self->header->type, self->header->id,
|
|
|
|
self->header->adv_router, old->lsdb);
|
|
|
|
ospf6_lsa_checksum(self->header);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-08-15 07:52:07 +02:00
|
|
|
new = ospf6_lsa_create(self->header);
|
|
|
|
new->lsdb = old->lsdb;
|
2022-05-20 20:19:08 +02:00
|
|
|
event_add_timer(master, ospf6_lsa_refresh, new, OSPF_LS_REFRESH_TIME,
|
|
|
|
&new->refresh);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-08-15 07:52:07 +02:00
|
|
|
/* store it in the LSDB for self-originated LSAs */
|
|
|
|
ospf6_lsdb_add(ospf6_lsa_copy(new), lsdb_self);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-09-01 23:36:14 +02:00
|
|
|
if (IS_OSPF6_DEBUG_LSA_TYPE(new->header->type)) {
|
2004-12-24 07:00:11 +01:00
|
|
|
zlog_debug("LSA Refresh:");
|
2004-08-15 07:52:07 +02:00
|
|
|
ospf6_lsa_header_print(new);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2004-08-15 07:52:07 +02:00
|
|
|
ospf6_install_lsa(new);
|
2013-08-24 09:54:50 +02:00
|
|
|
ospf6_flood(NULL, new);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2020-10-08 07:38:43 +02:00
|
|
|
void ospf6_flush_self_originated_lsas_now(struct ospf6 *ospf6)
|
ospf6d: Handle Premature Aging of LSAs
RFC 2328 (14.1) Premature aging of LSAs from
routing domain :
When ospf6d is going away (router going down),
send MAXAGEd self originated LSAs to all
neighbors in routing domain to trigger
Premature aging to remove from resepective LSDBs.
Neighbor Router Reboot:
Upon receiving Self-originate MAXAGEd LSA, simply
discard, Current copy could be non maxaged latest.
For neighbor advertised LSA's (current copy in LSDB)
is set to MAXAGE but received new LSA with Non-MAXAGE
(with current age), discard the current MAXAGE LSA,
Send latest copy of LSA to neighbors and update the
LSDB with new LSA.
When a neighbor transition to FULL, trigger AS-External
LSAs update from external LSDB to new neighbor.
Testing:
R1 ---- DUT --- R5
| \
R2 R3
|
R4
Area 1: R5 and DUT
Area 0: DUT, R1, R2, R3
Area 2: R2 R4
Add IPv6 static routes at R5
Redistribute kernel routes at R5,
Validate routes at R4, redistributed via backbone
to area 2.
Stop n start frr.service at R5 and validated
MAXAGE LSAs then recent age LSAs in Database at DUT-R4.
Validated external routes installed DUT to R4.
Signed-off-by: Chirag Shah <chirag@cumulusnetworks.com>
2018-01-26 23:53:43 +01:00
|
|
|
{
|
2021-03-11 14:41:05 +01:00
|
|
|
struct listnode *node, *nnode;
|
ospf6d: Handle Premature Aging of LSAs
RFC 2328 (14.1) Premature aging of LSAs from
routing domain :
When ospf6d is going away (router going down),
send MAXAGEd self originated LSAs to all
neighbors in routing domain to trigger
Premature aging to remove from resepective LSDBs.
Neighbor Router Reboot:
Upon receiving Self-originate MAXAGEd LSA, simply
discard, Current copy could be non maxaged latest.
For neighbor advertised LSA's (current copy in LSDB)
is set to MAXAGE but received new LSA with Non-MAXAGE
(with current age), discard the current MAXAGE LSA,
Send latest copy of LSA to neighbors and update the
LSDB with new LSA.
When a neighbor transition to FULL, trigger AS-External
LSAs update from external LSDB to new neighbor.
Testing:
R1 ---- DUT --- R5
| \
R2 R3
|
R4
Area 1: R5 and DUT
Area 0: DUT, R1, R2, R3
Area 2: R2 R4
Add IPv6 static routes at R5
Redistribute kernel routes at R5,
Validate routes at R4, redistributed via backbone
to area 2.
Stop n start frr.service at R5 and validated
MAXAGE LSAs then recent age LSAs in Database at DUT-R4.
Validated external routes installed DUT to R4.
Signed-off-by: Chirag Shah <chirag@cumulusnetworks.com>
2018-01-26 23:53:43 +01:00
|
|
|
struct ospf6_area *oa;
|
|
|
|
struct ospf6_lsa *lsa;
|
|
|
|
const struct route_node *end = NULL;
|
|
|
|
uint32_t type, adv_router;
|
2021-03-11 14:41:05 +01:00
|
|
|
struct ospf6_interface *oi;
|
ospf6d: Handle Premature Aging of LSAs
RFC 2328 (14.1) Premature aging of LSAs from
routing domain :
When ospf6d is going away (router going down),
send MAXAGEd self originated LSAs to all
neighbors in routing domain to trigger
Premature aging to remove from resepective LSDBs.
Neighbor Router Reboot:
Upon receiving Self-originate MAXAGEd LSA, simply
discard, Current copy could be non maxaged latest.
For neighbor advertised LSA's (current copy in LSDB)
is set to MAXAGE but received new LSA with Non-MAXAGE
(with current age), discard the current MAXAGE LSA,
Send latest copy of LSA to neighbors and update the
LSDB with new LSA.
When a neighbor transition to FULL, trigger AS-External
LSAs update from external LSDB to new neighbor.
Testing:
R1 ---- DUT --- R5
| \
R2 R3
|
R4
Area 1: R5 and DUT
Area 0: DUT, R1, R2, R3
Area 2: R2 R4
Add IPv6 static routes at R5
Redistribute kernel routes at R5,
Validate routes at R4, redistributed via backbone
to area 2.
Stop n start frr.service at R5 and validated
MAXAGE LSAs then recent age LSAs in Database at DUT-R4.
Validated external routes installed DUT to R4.
Signed-off-by: Chirag Shah <chirag@cumulusnetworks.com>
2018-01-26 23:53:43 +01:00
|
|
|
|
|
|
|
ospf6->inst_shutdown = 1;
|
|
|
|
|
|
|
|
for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
|
|
|
|
end = ospf6_lsdb_head(oa->lsdb_self, 0, 0, ospf6->router_id,
|
|
|
|
&lsa);
|
|
|
|
while (lsa) {
|
|
|
|
/* RFC 2328 (14.1): Set MAXAGE */
|
|
|
|
lsa->header->age = htons(OSPF_LSA_MAXAGE);
|
|
|
|
/* Flood MAXAGE LSA*/
|
|
|
|
ospf6_flood(NULL, lsa);
|
|
|
|
|
|
|
|
lsa = ospf6_lsdb_next(end, lsa);
|
|
|
|
}
|
2021-03-11 14:41:05 +01:00
|
|
|
|
|
|
|
for (ALL_LIST_ELEMENTS(oa->if_list, node, nnode, oi)) {
|
|
|
|
end = ospf6_lsdb_head(oi->lsdb_self, 0, 0,
|
|
|
|
ospf6->router_id, &lsa);
|
|
|
|
while (lsa) {
|
|
|
|
/* RFC 2328 (14.1): Set MAXAGE */
|
|
|
|
lsa->header->age = htons(OSPF_LSA_MAXAGE);
|
|
|
|
/* Flood MAXAGE LSA*/
|
|
|
|
ospf6_flood(NULL, lsa);
|
|
|
|
|
|
|
|
lsa = ospf6_lsdb_next(end, lsa);
|
|
|
|
}
|
|
|
|
}
|
ospf6d: Handle Premature Aging of LSAs
RFC 2328 (14.1) Premature aging of LSAs from
routing domain :
When ospf6d is going away (router going down),
send MAXAGEd self originated LSAs to all
neighbors in routing domain to trigger
Premature aging to remove from resepective LSDBs.
Neighbor Router Reboot:
Upon receiving Self-originate MAXAGEd LSA, simply
discard, Current copy could be non maxaged latest.
For neighbor advertised LSA's (current copy in LSDB)
is set to MAXAGE but received new LSA with Non-MAXAGE
(with current age), discard the current MAXAGE LSA,
Send latest copy of LSA to neighbors and update the
LSDB with new LSA.
When a neighbor transition to FULL, trigger AS-External
LSAs update from external LSDB to new neighbor.
Testing:
R1 ---- DUT --- R5
| \
R2 R3
|
R4
Area 1: R5 and DUT
Area 0: DUT, R1, R2, R3
Area 2: R2 R4
Add IPv6 static routes at R5
Redistribute kernel routes at R5,
Validate routes at R4, redistributed via backbone
to area 2.
Stop n start frr.service at R5 and validated
MAXAGE LSAs then recent age LSAs in Database at DUT-R4.
Validated external routes installed DUT to R4.
Signed-off-by: Chirag Shah <chirag@cumulusnetworks.com>
2018-01-26 23:53:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
type = htons(OSPF6_LSTYPE_AS_EXTERNAL);
|
|
|
|
adv_router = ospf6->router_id;
|
|
|
|
for (ALL_LSDB_TYPED_ADVRTR(ospf6->lsdb, type, adv_router, lsa)) {
|
|
|
|
/* RFC 2328 (14.1): Set MAXAGE */
|
|
|
|
lsa->header->age = htons(OSPF_LSA_MAXAGE);
|
|
|
|
ospf6_flood(NULL, lsa);
|
|
|
|
}
|
|
|
|
}
|
2014-06-04 06:53:35 +02:00
|
|
|
|
lib: improve fletcher checksum validation
OVERVIEW
The checksum used in OSPF (rfc2328) is specified in rc905 annex B. There is an
sample implementation in rfc1008 which forms the basis of the quagga
implementation. This algorithm works perfectly when generating a checksum;
however, validation is a bit problematic.
The following LSA (generated by a non-quagga implementation) is received by
quagga and marked with an invalid checksum; however, it passes both the rfc905
and rfc1008 validation checks.
static uint8_t lsa_10_121_233_29[] = {
0x0e, 0x10, 0x02, 0x03,
0x09, 0x00, 0x35, 0x40,
0x0a, 0x79, 0xe9, 0x1d,
0x80, 0x00, 0x00, 0x03,
0x00, 0x8a, 0x00, 0x1c,
0xff, 0xff, 0xff, 0xe0,
0x00, 0x00, 0x36, 0xb0
};
LS Type: Summary-LSA (IP network)
LS Age: 3600 seconds
Do Not Age: False
Options: 0x02 (E)
Link-State Advertisement Type: Summary-LSA (IP network) (3)
Link State ID: 9.0.53.64
Advertising Router: 10.121.233.29 (10.121.233.29)
LS Sequence Number: 0x80000003
LS Checksum: 0x008a
Length: 28
Netmask: 255.255.255.224
Metric: 14000
You'll note that one byte of the checksum is 0x00; quagga would calculate the
checksum as 0xff8a.
It can be argued that the sourcing implementation generates an incorrect
checksum; however, rfc905 indicates that, for 1's complement arithmetic, the
value 255 shall be regarded as 0, thus either values are valid.
EXPLANATION
The quagga ospfd and ospf6d implementations operate by copying the PDU's
existing checksum in a holding variable, calculating the checksum, and comparing
the resulting checksum to the original. As a note, this implementation has the
side effect of modifying the contents of the PDU.
Evaluation of both rfc905 and rfc1008 shows that checksum validation should
involve calculating the sum over the PDU and checking that both resulting C0 and
C1 values are zero. This behavior is enacted in the rfc1008 implementation by
calling encodecc with k = 0 (checksum offset); however, this functionality had
been omitted from the quagga implementation.
PATCH
This patch adds the ability to call the quagga's fletcher_checksum() with a
checksum offset value of 0xffff (aka FLETCHER_CHECKSUM_VALIDATE) which returns
the sum over the buffer (a value of 0 indicates a valid checksum). This is
similar to the mechanism in rfc1008 when called with k = 0. The patch also
introduces ospf_lsa_checksum_valid().
ospf6d had it's own implementation of the fletcher checksum in
ospf6_lsa_checksum(); it's the same algorithm as in fletcher_checksum(). This
patch removes the local implementation in favor of the library's as well as creates
and uses ospf6_lsa_checksum_valid().
quagga's ISIS implementation suffers from the same problem; however, I do not
have the facilities to validate a fix to ISIS, thus this change has been left to
the ISIS maintainers. The function iso_csum_verify() should be reduced to
running the fletcher checksum over the buffer using an offset of 0.
Signed-off-by: JR Rivers <jrrivers@cumulusnetworks.com>
Reviewed-by: Scott Feldman <sfeldma@cumulusnetworks.com>
Reviewed-by: Nolan Leake <nolan@cumulusnetworks.com>
Reviewed-by: Ayan Banerjee <ayan@cumulusnetworks.com>
Reviewed-by: Shrijeet Mukherjee <shm@cumulusnetworks.com>
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
2012-09-13 19:17:36 +02:00
|
|
|
/* Fletcher Checksum -- Refer to RFC1008. */
|
2002-12-13 21:15:29 +01:00
|
|
|
|
lib: improve fletcher checksum validation
OVERVIEW
The checksum used in OSPF (rfc2328) is specified in rc905 annex B. There is an
sample implementation in rfc1008 which forms the basis of the quagga
implementation. This algorithm works perfectly when generating a checksum;
however, validation is a bit problematic.
The following LSA (generated by a non-quagga implementation) is received by
quagga and marked with an invalid checksum; however, it passes both the rfc905
and rfc1008 validation checks.
static uint8_t lsa_10_121_233_29[] = {
0x0e, 0x10, 0x02, 0x03,
0x09, 0x00, 0x35, 0x40,
0x0a, 0x79, 0xe9, 0x1d,
0x80, 0x00, 0x00, 0x03,
0x00, 0x8a, 0x00, 0x1c,
0xff, 0xff, 0xff, 0xe0,
0x00, 0x00, 0x36, 0xb0
};
LS Type: Summary-LSA (IP network)
LS Age: 3600 seconds
Do Not Age: False
Options: 0x02 (E)
Link-State Advertisement Type: Summary-LSA (IP network) (3)
Link State ID: 9.0.53.64
Advertising Router: 10.121.233.29 (10.121.233.29)
LS Sequence Number: 0x80000003
LS Checksum: 0x008a
Length: 28
Netmask: 255.255.255.224
Metric: 14000
You'll note that one byte of the checksum is 0x00; quagga would calculate the
checksum as 0xff8a.
It can be argued that the sourcing implementation generates an incorrect
checksum; however, rfc905 indicates that, for 1's complement arithmetic, the
value 255 shall be regarded as 0, thus either values are valid.
EXPLANATION
The quagga ospfd and ospf6d implementations operate by copying the PDU's
existing checksum in a holding variable, calculating the checksum, and comparing
the resulting checksum to the original. As a note, this implementation has the
side effect of modifying the contents of the PDU.
Evaluation of both rfc905 and rfc1008 shows that checksum validation should
involve calculating the sum over the PDU and checking that both resulting C0 and
C1 values are zero. This behavior is enacted in the rfc1008 implementation by
calling encodecc with k = 0 (checksum offset); however, this functionality had
been omitted from the quagga implementation.
PATCH
This patch adds the ability to call the quagga's fletcher_checksum() with a
checksum offset value of 0xffff (aka FLETCHER_CHECKSUM_VALIDATE) which returns
the sum over the buffer (a value of 0 indicates a valid checksum). This is
similar to the mechanism in rfc1008 when called with k = 0. The patch also
introduces ospf_lsa_checksum_valid().
ospf6d had it's own implementation of the fletcher checksum in
ospf6_lsa_checksum(); it's the same algorithm as in fletcher_checksum(). This
patch removes the local implementation in favor of the library's as well as creates
and uses ospf6_lsa_checksum_valid().
quagga's ISIS implementation suffers from the same problem; however, I do not
have the facilities to validate a fix to ISIS, thus this change has been left to
the ISIS maintainers. The function iso_csum_verify() should be reduced to
running the fletcher checksum over the buffer using an offset of 0.
Signed-off-by: JR Rivers <jrrivers@cumulusnetworks.com>
Reviewed-by: Scott Feldman <sfeldma@cumulusnetworks.com>
Reviewed-by: Nolan Leake <nolan@cumulusnetworks.com>
Reviewed-by: Ayan Banerjee <ayan@cumulusnetworks.com>
Reviewed-by: Shrijeet Mukherjee <shm@cumulusnetworks.com>
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
2012-09-13 19:17:36 +02:00
|
|
|
/* All the offsets are zero-based. The offsets in the RFC1008 are
|
|
|
|
one-based. */
|
2002-12-13 21:15:29 +01:00
|
|
|
unsigned short ospf6_lsa_checksum(struct ospf6_lsa_header *lsa_header)
|
|
|
|
{
|
2018-03-27 21:13:34 +02:00
|
|
|
uint8_t *buffer = (uint8_t *)&lsa_header->type;
|
|
|
|
int type_offset =
|
|
|
|
buffer - (uint8_t *)&lsa_header->age; /* should be 2 */
|
2002-12-13 21:15:29 +01:00
|
|
|
|
lib: improve fletcher checksum validation
OVERVIEW
The checksum used in OSPF (rfc2328) is specified in rc905 annex B. There is an
sample implementation in rfc1008 which forms the basis of the quagga
implementation. This algorithm works perfectly when generating a checksum;
however, validation is a bit problematic.
The following LSA (generated by a non-quagga implementation) is received by
quagga and marked with an invalid checksum; however, it passes both the rfc905
and rfc1008 validation checks.
static uint8_t lsa_10_121_233_29[] = {
0x0e, 0x10, 0x02, 0x03,
0x09, 0x00, 0x35, 0x40,
0x0a, 0x79, 0xe9, 0x1d,
0x80, 0x00, 0x00, 0x03,
0x00, 0x8a, 0x00, 0x1c,
0xff, 0xff, 0xff, 0xe0,
0x00, 0x00, 0x36, 0xb0
};
LS Type: Summary-LSA (IP network)
LS Age: 3600 seconds
Do Not Age: False
Options: 0x02 (E)
Link-State Advertisement Type: Summary-LSA (IP network) (3)
Link State ID: 9.0.53.64
Advertising Router: 10.121.233.29 (10.121.233.29)
LS Sequence Number: 0x80000003
LS Checksum: 0x008a
Length: 28
Netmask: 255.255.255.224
Metric: 14000
You'll note that one byte of the checksum is 0x00; quagga would calculate the
checksum as 0xff8a.
It can be argued that the sourcing implementation generates an incorrect
checksum; however, rfc905 indicates that, for 1's complement arithmetic, the
value 255 shall be regarded as 0, thus either values are valid.
EXPLANATION
The quagga ospfd and ospf6d implementations operate by copying the PDU's
existing checksum in a holding variable, calculating the checksum, and comparing
the resulting checksum to the original. As a note, this implementation has the
side effect of modifying the contents of the PDU.
Evaluation of both rfc905 and rfc1008 shows that checksum validation should
involve calculating the sum over the PDU and checking that both resulting C0 and
C1 values are zero. This behavior is enacted in the rfc1008 implementation by
calling encodecc with k = 0 (checksum offset); however, this functionality had
been omitted from the quagga implementation.
PATCH
This patch adds the ability to call the quagga's fletcher_checksum() with a
checksum offset value of 0xffff (aka FLETCHER_CHECKSUM_VALIDATE) which returns
the sum over the buffer (a value of 0 indicates a valid checksum). This is
similar to the mechanism in rfc1008 when called with k = 0. The patch also
introduces ospf_lsa_checksum_valid().
ospf6d had it's own implementation of the fletcher checksum in
ospf6_lsa_checksum(); it's the same algorithm as in fletcher_checksum(). This
patch removes the local implementation in favor of the library's as well as creates
and uses ospf6_lsa_checksum_valid().
quagga's ISIS implementation suffers from the same problem; however, I do not
have the facilities to validate a fix to ISIS, thus this change has been left to
the ISIS maintainers. The function iso_csum_verify() should be reduced to
running the fletcher checksum over the buffer using an offset of 0.
Signed-off-by: JR Rivers <jrrivers@cumulusnetworks.com>
Reviewed-by: Scott Feldman <sfeldma@cumulusnetworks.com>
Reviewed-by: Nolan Leake <nolan@cumulusnetworks.com>
Reviewed-by: Ayan Banerjee <ayan@cumulusnetworks.com>
Reviewed-by: Shrijeet Mukherjee <shm@cumulusnetworks.com>
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
2012-09-13 19:17:36 +02:00
|
|
|
/* Skip the AGE field */
|
2024-05-28 06:07:14 +02:00
|
|
|
uint16_t len = ospf6_lsa_size(lsa_header) - type_offset;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
lib: improve fletcher checksum validation
OVERVIEW
The checksum used in OSPF (rfc2328) is specified in rc905 annex B. There is an
sample implementation in rfc1008 which forms the basis of the quagga
implementation. This algorithm works perfectly when generating a checksum;
however, validation is a bit problematic.
The following LSA (generated by a non-quagga implementation) is received by
quagga and marked with an invalid checksum; however, it passes both the rfc905
and rfc1008 validation checks.
static uint8_t lsa_10_121_233_29[] = {
0x0e, 0x10, 0x02, 0x03,
0x09, 0x00, 0x35, 0x40,
0x0a, 0x79, 0xe9, 0x1d,
0x80, 0x00, 0x00, 0x03,
0x00, 0x8a, 0x00, 0x1c,
0xff, 0xff, 0xff, 0xe0,
0x00, 0x00, 0x36, 0xb0
};
LS Type: Summary-LSA (IP network)
LS Age: 3600 seconds
Do Not Age: False
Options: 0x02 (E)
Link-State Advertisement Type: Summary-LSA (IP network) (3)
Link State ID: 9.0.53.64
Advertising Router: 10.121.233.29 (10.121.233.29)
LS Sequence Number: 0x80000003
LS Checksum: 0x008a
Length: 28
Netmask: 255.255.255.224
Metric: 14000
You'll note that one byte of the checksum is 0x00; quagga would calculate the
checksum as 0xff8a.
It can be argued that the sourcing implementation generates an incorrect
checksum; however, rfc905 indicates that, for 1's complement arithmetic, the
value 255 shall be regarded as 0, thus either values are valid.
EXPLANATION
The quagga ospfd and ospf6d implementations operate by copying the PDU's
existing checksum in a holding variable, calculating the checksum, and comparing
the resulting checksum to the original. As a note, this implementation has the
side effect of modifying the contents of the PDU.
Evaluation of both rfc905 and rfc1008 shows that checksum validation should
involve calculating the sum over the PDU and checking that both resulting C0 and
C1 values are zero. This behavior is enacted in the rfc1008 implementation by
calling encodecc with k = 0 (checksum offset); however, this functionality had
been omitted from the quagga implementation.
PATCH
This patch adds the ability to call the quagga's fletcher_checksum() with a
checksum offset value of 0xffff (aka FLETCHER_CHECKSUM_VALIDATE) which returns
the sum over the buffer (a value of 0 indicates a valid checksum). This is
similar to the mechanism in rfc1008 when called with k = 0. The patch also
introduces ospf_lsa_checksum_valid().
ospf6d had it's own implementation of the fletcher checksum in
ospf6_lsa_checksum(); it's the same algorithm as in fletcher_checksum(). This
patch removes the local implementation in favor of the library's as well as creates
and uses ospf6_lsa_checksum_valid().
quagga's ISIS implementation suffers from the same problem; however, I do not
have the facilities to validate a fix to ISIS, thus this change has been left to
the ISIS maintainers. The function iso_csum_verify() should be reduced to
running the fletcher checksum over the buffer using an offset of 0.
Signed-off-by: JR Rivers <jrrivers@cumulusnetworks.com>
Reviewed-by: Scott Feldman <sfeldma@cumulusnetworks.com>
Reviewed-by: Nolan Leake <nolan@cumulusnetworks.com>
Reviewed-by: Ayan Banerjee <ayan@cumulusnetworks.com>
Reviewed-by: Shrijeet Mukherjee <shm@cumulusnetworks.com>
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
2012-09-13 19:17:36 +02:00
|
|
|
/* Checksum offset starts from "type" field, not the beginning of the
|
|
|
|
lsa_header struct. The offset is 14, rather than 16. */
|
2018-03-27 21:13:34 +02:00
|
|
|
int checksum_offset = (uint8_t *)&lsa_header->checksum - buffer;
|
lib: improve fletcher checksum validation
OVERVIEW
The checksum used in OSPF (rfc2328) is specified in rc905 annex B. There is an
sample implementation in rfc1008 which forms the basis of the quagga
implementation. This algorithm works perfectly when generating a checksum;
however, validation is a bit problematic.
The following LSA (generated by a non-quagga implementation) is received by
quagga and marked with an invalid checksum; however, it passes both the rfc905
and rfc1008 validation checks.
static uint8_t lsa_10_121_233_29[] = {
0x0e, 0x10, 0x02, 0x03,
0x09, 0x00, 0x35, 0x40,
0x0a, 0x79, 0xe9, 0x1d,
0x80, 0x00, 0x00, 0x03,
0x00, 0x8a, 0x00, 0x1c,
0xff, 0xff, 0xff, 0xe0,
0x00, 0x00, 0x36, 0xb0
};
LS Type: Summary-LSA (IP network)
LS Age: 3600 seconds
Do Not Age: False
Options: 0x02 (E)
Link-State Advertisement Type: Summary-LSA (IP network) (3)
Link State ID: 9.0.53.64
Advertising Router: 10.121.233.29 (10.121.233.29)
LS Sequence Number: 0x80000003
LS Checksum: 0x008a
Length: 28
Netmask: 255.255.255.224
Metric: 14000
You'll note that one byte of the checksum is 0x00; quagga would calculate the
checksum as 0xff8a.
It can be argued that the sourcing implementation generates an incorrect
checksum; however, rfc905 indicates that, for 1's complement arithmetic, the
value 255 shall be regarded as 0, thus either values are valid.
EXPLANATION
The quagga ospfd and ospf6d implementations operate by copying the PDU's
existing checksum in a holding variable, calculating the checksum, and comparing
the resulting checksum to the original. As a note, this implementation has the
side effect of modifying the contents of the PDU.
Evaluation of both rfc905 and rfc1008 shows that checksum validation should
involve calculating the sum over the PDU and checking that both resulting C0 and
C1 values are zero. This behavior is enacted in the rfc1008 implementation by
calling encodecc with k = 0 (checksum offset); however, this functionality had
been omitted from the quagga implementation.
PATCH
This patch adds the ability to call the quagga's fletcher_checksum() with a
checksum offset value of 0xffff (aka FLETCHER_CHECKSUM_VALIDATE) which returns
the sum over the buffer (a value of 0 indicates a valid checksum). This is
similar to the mechanism in rfc1008 when called with k = 0. The patch also
introduces ospf_lsa_checksum_valid().
ospf6d had it's own implementation of the fletcher checksum in
ospf6_lsa_checksum(); it's the same algorithm as in fletcher_checksum(). This
patch removes the local implementation in favor of the library's as well as creates
and uses ospf6_lsa_checksum_valid().
quagga's ISIS implementation suffers from the same problem; however, I do not
have the facilities to validate a fix to ISIS, thus this change has been left to
the ISIS maintainers. The function iso_csum_verify() should be reduced to
running the fletcher checksum over the buffer using an offset of 0.
Signed-off-by: JR Rivers <jrrivers@cumulusnetworks.com>
Reviewed-by: Scott Feldman <sfeldma@cumulusnetworks.com>
Reviewed-by: Nolan Leake <nolan@cumulusnetworks.com>
Reviewed-by: Ayan Banerjee <ayan@cumulusnetworks.com>
Reviewed-by: Shrijeet Mukherjee <shm@cumulusnetworks.com>
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
2012-09-13 19:17:36 +02:00
|
|
|
|
|
|
|
return (unsigned short)fletcher_checksum(buffer, len, checksum_offset);
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
lib: improve fletcher checksum validation
OVERVIEW
The checksum used in OSPF (rfc2328) is specified in rc905 annex B. There is an
sample implementation in rfc1008 which forms the basis of the quagga
implementation. This algorithm works perfectly when generating a checksum;
however, validation is a bit problematic.
The following LSA (generated by a non-quagga implementation) is received by
quagga and marked with an invalid checksum; however, it passes both the rfc905
and rfc1008 validation checks.
static uint8_t lsa_10_121_233_29[] = {
0x0e, 0x10, 0x02, 0x03,
0x09, 0x00, 0x35, 0x40,
0x0a, 0x79, 0xe9, 0x1d,
0x80, 0x00, 0x00, 0x03,
0x00, 0x8a, 0x00, 0x1c,
0xff, 0xff, 0xff, 0xe0,
0x00, 0x00, 0x36, 0xb0
};
LS Type: Summary-LSA (IP network)
LS Age: 3600 seconds
Do Not Age: False
Options: 0x02 (E)
Link-State Advertisement Type: Summary-LSA (IP network) (3)
Link State ID: 9.0.53.64
Advertising Router: 10.121.233.29 (10.121.233.29)
LS Sequence Number: 0x80000003
LS Checksum: 0x008a
Length: 28
Netmask: 255.255.255.224
Metric: 14000
You'll note that one byte of the checksum is 0x00; quagga would calculate the
checksum as 0xff8a.
It can be argued that the sourcing implementation generates an incorrect
checksum; however, rfc905 indicates that, for 1's complement arithmetic, the
value 255 shall be regarded as 0, thus either values are valid.
EXPLANATION
The quagga ospfd and ospf6d implementations operate by copying the PDU's
existing checksum in a holding variable, calculating the checksum, and comparing
the resulting checksum to the original. As a note, this implementation has the
side effect of modifying the contents of the PDU.
Evaluation of both rfc905 and rfc1008 shows that checksum validation should
involve calculating the sum over the PDU and checking that both resulting C0 and
C1 values are zero. This behavior is enacted in the rfc1008 implementation by
calling encodecc with k = 0 (checksum offset); however, this functionality had
been omitted from the quagga implementation.
PATCH
This patch adds the ability to call the quagga's fletcher_checksum() with a
checksum offset value of 0xffff (aka FLETCHER_CHECKSUM_VALIDATE) which returns
the sum over the buffer (a value of 0 indicates a valid checksum). This is
similar to the mechanism in rfc1008 when called with k = 0. The patch also
introduces ospf_lsa_checksum_valid().
ospf6d had it's own implementation of the fletcher checksum in
ospf6_lsa_checksum(); it's the same algorithm as in fletcher_checksum(). This
patch removes the local implementation in favor of the library's as well as creates
and uses ospf6_lsa_checksum_valid().
quagga's ISIS implementation suffers from the same problem; however, I do not
have the facilities to validate a fix to ISIS, thus this change has been left to
the ISIS maintainers. The function iso_csum_verify() should be reduced to
running the fletcher checksum over the buffer using an offset of 0.
Signed-off-by: JR Rivers <jrrivers@cumulusnetworks.com>
Reviewed-by: Scott Feldman <sfeldma@cumulusnetworks.com>
Reviewed-by: Nolan Leake <nolan@cumulusnetworks.com>
Reviewed-by: Ayan Banerjee <ayan@cumulusnetworks.com>
Reviewed-by: Shrijeet Mukherjee <shm@cumulusnetworks.com>
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
2012-09-13 19:17:36 +02:00
|
|
|
int ospf6_lsa_checksum_valid(struct ospf6_lsa_header *lsa_header)
|
|
|
|
{
|
2018-03-27 21:13:34 +02:00
|
|
|
uint8_t *buffer = (uint8_t *)&lsa_header->type;
|
|
|
|
int type_offset =
|
|
|
|
buffer - (uint8_t *)&lsa_header->age; /* should be 2 */
|
2002-12-13 21:15:29 +01:00
|
|
|
|
lib: improve fletcher checksum validation
OVERVIEW
The checksum used in OSPF (rfc2328) is specified in rc905 annex B. There is an
sample implementation in rfc1008 which forms the basis of the quagga
implementation. This algorithm works perfectly when generating a checksum;
however, validation is a bit problematic.
The following LSA (generated by a non-quagga implementation) is received by
quagga and marked with an invalid checksum; however, it passes both the rfc905
and rfc1008 validation checks.
static uint8_t lsa_10_121_233_29[] = {
0x0e, 0x10, 0x02, 0x03,
0x09, 0x00, 0x35, 0x40,
0x0a, 0x79, 0xe9, 0x1d,
0x80, 0x00, 0x00, 0x03,
0x00, 0x8a, 0x00, 0x1c,
0xff, 0xff, 0xff, 0xe0,
0x00, 0x00, 0x36, 0xb0
};
LS Type: Summary-LSA (IP network)
LS Age: 3600 seconds
Do Not Age: False
Options: 0x02 (E)
Link-State Advertisement Type: Summary-LSA (IP network) (3)
Link State ID: 9.0.53.64
Advertising Router: 10.121.233.29 (10.121.233.29)
LS Sequence Number: 0x80000003
LS Checksum: 0x008a
Length: 28
Netmask: 255.255.255.224
Metric: 14000
You'll note that one byte of the checksum is 0x00; quagga would calculate the
checksum as 0xff8a.
It can be argued that the sourcing implementation generates an incorrect
checksum; however, rfc905 indicates that, for 1's complement arithmetic, the
value 255 shall be regarded as 0, thus either values are valid.
EXPLANATION
The quagga ospfd and ospf6d implementations operate by copying the PDU's
existing checksum in a holding variable, calculating the checksum, and comparing
the resulting checksum to the original. As a note, this implementation has the
side effect of modifying the contents of the PDU.
Evaluation of both rfc905 and rfc1008 shows that checksum validation should
involve calculating the sum over the PDU and checking that both resulting C0 and
C1 values are zero. This behavior is enacted in the rfc1008 implementation by
calling encodecc with k = 0 (checksum offset); however, this functionality had
been omitted from the quagga implementation.
PATCH
This patch adds the ability to call the quagga's fletcher_checksum() with a
checksum offset value of 0xffff (aka FLETCHER_CHECKSUM_VALIDATE) which returns
the sum over the buffer (a value of 0 indicates a valid checksum). This is
similar to the mechanism in rfc1008 when called with k = 0. The patch also
introduces ospf_lsa_checksum_valid().
ospf6d had it's own implementation of the fletcher checksum in
ospf6_lsa_checksum(); it's the same algorithm as in fletcher_checksum(). This
patch removes the local implementation in favor of the library's as well as creates
and uses ospf6_lsa_checksum_valid().
quagga's ISIS implementation suffers from the same problem; however, I do not
have the facilities to validate a fix to ISIS, thus this change has been left to
the ISIS maintainers. The function iso_csum_verify() should be reduced to
running the fletcher checksum over the buffer using an offset of 0.
Signed-off-by: JR Rivers <jrrivers@cumulusnetworks.com>
Reviewed-by: Scott Feldman <sfeldma@cumulusnetworks.com>
Reviewed-by: Nolan Leake <nolan@cumulusnetworks.com>
Reviewed-by: Ayan Banerjee <ayan@cumulusnetworks.com>
Reviewed-by: Shrijeet Mukherjee <shm@cumulusnetworks.com>
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
2012-09-13 19:17:36 +02:00
|
|
|
/* Skip the AGE field */
|
2024-05-28 06:07:14 +02:00
|
|
|
uint16_t len = ospf6_lsa_size(lsa_header) - type_offset;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
lib: improve fletcher checksum validation
OVERVIEW
The checksum used in OSPF (rfc2328) is specified in rc905 annex B. There is an
sample implementation in rfc1008 which forms the basis of the quagga
implementation. This algorithm works perfectly when generating a checksum;
however, validation is a bit problematic.
The following LSA (generated by a non-quagga implementation) is received by
quagga and marked with an invalid checksum; however, it passes both the rfc905
and rfc1008 validation checks.
static uint8_t lsa_10_121_233_29[] = {
0x0e, 0x10, 0x02, 0x03,
0x09, 0x00, 0x35, 0x40,
0x0a, 0x79, 0xe9, 0x1d,
0x80, 0x00, 0x00, 0x03,
0x00, 0x8a, 0x00, 0x1c,
0xff, 0xff, 0xff, 0xe0,
0x00, 0x00, 0x36, 0xb0
};
LS Type: Summary-LSA (IP network)
LS Age: 3600 seconds
Do Not Age: False
Options: 0x02 (E)
Link-State Advertisement Type: Summary-LSA (IP network) (3)
Link State ID: 9.0.53.64
Advertising Router: 10.121.233.29 (10.121.233.29)
LS Sequence Number: 0x80000003
LS Checksum: 0x008a
Length: 28
Netmask: 255.255.255.224
Metric: 14000
You'll note that one byte of the checksum is 0x00; quagga would calculate the
checksum as 0xff8a.
It can be argued that the sourcing implementation generates an incorrect
checksum; however, rfc905 indicates that, for 1's complement arithmetic, the
value 255 shall be regarded as 0, thus either values are valid.
EXPLANATION
The quagga ospfd and ospf6d implementations operate by copying the PDU's
existing checksum in a holding variable, calculating the checksum, and comparing
the resulting checksum to the original. As a note, this implementation has the
side effect of modifying the contents of the PDU.
Evaluation of both rfc905 and rfc1008 shows that checksum validation should
involve calculating the sum over the PDU and checking that both resulting C0 and
C1 values are zero. This behavior is enacted in the rfc1008 implementation by
calling encodecc with k = 0 (checksum offset); however, this functionality had
been omitted from the quagga implementation.
PATCH
This patch adds the ability to call the quagga's fletcher_checksum() with a
checksum offset value of 0xffff (aka FLETCHER_CHECKSUM_VALIDATE) which returns
the sum over the buffer (a value of 0 indicates a valid checksum). This is
similar to the mechanism in rfc1008 when called with k = 0. The patch also
introduces ospf_lsa_checksum_valid().
ospf6d had it's own implementation of the fletcher checksum in
ospf6_lsa_checksum(); it's the same algorithm as in fletcher_checksum(). This
patch removes the local implementation in favor of the library's as well as creates
and uses ospf6_lsa_checksum_valid().
quagga's ISIS implementation suffers from the same problem; however, I do not
have the facilities to validate a fix to ISIS, thus this change has been left to
the ISIS maintainers. The function iso_csum_verify() should be reduced to
running the fletcher checksum over the buffer using an offset of 0.
Signed-off-by: JR Rivers <jrrivers@cumulusnetworks.com>
Reviewed-by: Scott Feldman <sfeldma@cumulusnetworks.com>
Reviewed-by: Nolan Leake <nolan@cumulusnetworks.com>
Reviewed-by: Ayan Banerjee <ayan@cumulusnetworks.com>
Reviewed-by: Shrijeet Mukherjee <shm@cumulusnetworks.com>
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
2012-09-13 19:17:36 +02:00
|
|
|
return (fletcher_checksum(buffer, len, FLETCHER_CHECKSUM_VALIDATE)
|
|
|
|
== 0);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2008-08-15 14:45:30 +02:00
|
|
|
void ospf6_lsa_init(void)
|
2004-08-15 07:52:07 +02:00
|
|
|
{
|
|
|
|
ospf6_install_lsa_handler(&unknown_handler);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2010-11-10 22:01:41 +01:00
|
|
|
void ospf6_lsa_terminate(void)
|
|
|
|
{
|
|
|
|
}
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2017-10-08 18:20:12 +02:00
|
|
|
static char *ospf6_lsa_handler_name(const struct ospf6_lsa_handler *h)
|
2004-09-01 23:36:14 +02:00
|
|
|
{
|
|
|
|
static char buf[64];
|
2004-10-10 14:54:58 +02:00
|
|
|
unsigned int i;
|
2017-10-08 18:20:12 +02:00
|
|
|
unsigned int size = strlen(h->lh_name);
|
2004-09-01 23:36:14 +02:00
|
|
|
|
2017-10-08 18:20:12 +02:00
|
|
|
if (!strcmp(h->lh_name, "unknown")
|
|
|
|
&& h->lh_type != OSPF6_LSTYPE_UNKNOWN) {
|
|
|
|
snprintf(buf, sizeof(buf), "%#04hx", h->lh_type);
|
2004-09-01 23:36:14 +02:00
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < MIN(size, sizeof(buf)); i++) {
|
2017-10-08 18:20:12 +02:00
|
|
|
if (!islower((unsigned char)h->lh_name[i]))
|
|
|
|
buf[i] = tolower((unsigned char)h->lh_name[i]);
|
2004-09-01 23:36:14 +02:00
|
|
|
else
|
2017-10-08 18:20:12 +02:00
|
|
|
buf[i] = h->lh_name[i];
|
2004-09-01 23:36:14 +02:00
|
|
|
}
|
|
|
|
buf[size] = '\0';
|
|
|
|
return buf;
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2021-11-06 16:35:33 +01:00
|
|
|
void ospf6_lsa_debug_set_all(bool val)
|
2021-06-02 09:08:40 +02:00
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
struct ospf6_lsa_handler *handler = NULL;
|
|
|
|
|
2021-11-06 16:35:33 +01:00
|
|
|
for (i = 0; i < array_size(lsa_handlers); i++) {
|
|
|
|
handler = lsa_handlers[i];
|
2021-06-02 09:08:40 +02:00
|
|
|
if (handler == NULL)
|
|
|
|
continue;
|
2021-11-06 16:35:33 +01:00
|
|
|
if (val)
|
2021-06-02 09:08:40 +02:00
|
|
|
SET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_ALL);
|
|
|
|
else
|
|
|
|
UNSET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_ALL);
|
|
|
|
}
|
2021-11-06 16:35:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
DEFPY (debug_ospf6_lsa_all,
|
|
|
|
debug_ospf6_lsa_all_cmd,
|
|
|
|
"[no$no] debug ospf6 lsa all",
|
|
|
|
NO_STR
|
|
|
|
DEBUG_STR
|
|
|
|
OSPF6_STR
|
|
|
|
"Debug Link State Advertisements (LSAs)\n"
|
|
|
|
"Display for all types of LSAs\n")
|
|
|
|
{
|
|
|
|
ospf6_lsa_debug_set_all(!no);
|
2021-06-02 09:08:40 +02:00
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2021-05-28 11:33:03 +02:00
|
|
|
DEFPY (debug_ospf6_lsa_aggregation,
|
|
|
|
debug_ospf6_lsa_aggregation_cmd,
|
|
|
|
"[no] debug ospf6 lsa aggregation",
|
|
|
|
NO_STR
|
|
|
|
DEBUG_STR
|
|
|
|
OSPF6_STR
|
|
|
|
"Debug Link State Advertisements (LSAs)\n"
|
|
|
|
"External LSA Aggregation\n")
|
|
|
|
{
|
|
|
|
|
|
|
|
struct ospf6_lsa_handler *handler;
|
|
|
|
|
|
|
|
handler = ospf6_get_lsa_handler(OSPF6_LSTYPE_AS_EXTERNAL);
|
|
|
|
if (handler == NULL)
|
|
|
|
return CMD_WARNING_CONFIG_FAILED;
|
|
|
|
|
|
|
|
if (no)
|
|
|
|
UNSET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_AGGR);
|
|
|
|
else
|
|
|
|
SET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_AGGR);
|
|
|
|
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2004-09-01 23:36:14 +02:00
|
|
|
DEFUN (debug_ospf6_lsa_type,
|
|
|
|
debug_ospf6_lsa_hex_cmd,
|
2021-10-06 02:25:55 +02:00
|
|
|
"debug ospf6 lsa <router|network|inter-prefix|inter-router|as-external|nssa|link|intra-prefix|unknown> [<originate|examine|flooding>]",
|
2004-05-18 20:57:06 +02:00
|
|
|
DEBUG_STR
|
|
|
|
OSPF6_STR
|
|
|
|
"Debug Link State Advertisements (LSAs)\n"
|
2016-11-30 00:07:11 +01:00
|
|
|
"Display Router LSAs\n"
|
|
|
|
"Display Network LSAs\n"
|
|
|
|
"Display Inter-Area-Prefix LSAs\n"
|
|
|
|
"Display Inter-Router LSAs\n"
|
|
|
|
"Display As-External LSAs\n"
|
2021-10-06 02:25:55 +02:00
|
|
|
"Display NSSA LSAs\n"
|
2016-11-30 00:07:11 +01:00
|
|
|
"Display Link LSAs\n"
|
|
|
|
"Display Intra-Area-Prefix LSAs\n"
|
|
|
|
"Display LSAs of unknown origin\n"
|
|
|
|
"Display details of LSAs\n"
|
|
|
|
"Dump LSAs\n"
|
|
|
|
"Display LSA's internal information\n")
|
2004-05-18 20:57:06 +02:00
|
|
|
{
|
2016-09-23 21:56:31 +02:00
|
|
|
int idx_lsa = 3;
|
2016-09-30 03:27:05 +02:00
|
|
|
int idx_type = 4;
|
2004-10-10 14:54:58 +02:00
|
|
|
unsigned int i;
|
2004-09-01 23:36:14 +02:00
|
|
|
struct ospf6_lsa_handler *handler = NULL;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2021-11-06 16:35:33 +01:00
|
|
|
for (i = 0; i < array_size(lsa_handlers); i++) {
|
|
|
|
handler = lsa_handlers[i];
|
2004-09-01 23:36:14 +02:00
|
|
|
if (handler == NULL)
|
|
|
|
continue;
|
2016-09-23 21:56:31 +02:00
|
|
|
if (strncmp(argv[idx_lsa]->arg, ospf6_lsa_handler_name(handler),
|
|
|
|
strlen(argv[idx_lsa]->arg))
|
|
|
|
== 0)
|
2004-09-01 23:36:14 +02:00
|
|
|
break;
|
2017-10-08 18:20:12 +02:00
|
|
|
if (!strcasecmp(argv[idx_lsa]->arg, handler->lh_name))
|
2004-09-01 23:36:14 +02:00
|
|
|
break;
|
|
|
|
handler = NULL;
|
2004-05-18 20:57:06 +02:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-09-01 23:36:14 +02:00
|
|
|
if (handler == NULL)
|
|
|
|
handler = &unknown_handler;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2016-09-30 03:27:05 +02:00
|
|
|
if (argc == 5) {
|
2017-06-26 20:15:19 +02:00
|
|
|
if (strmatch(argv[idx_type]->text, "originate"))
|
2018-09-04 12:55:19 +02:00
|
|
|
SET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_ORIGINATE);
|
2017-06-26 20:15:19 +02:00
|
|
|
else if (strmatch(argv[idx_type]->text, "examine"))
|
2018-09-04 12:55:19 +02:00
|
|
|
SET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_EXAMIN);
|
2017-06-26 20:15:19 +02:00
|
|
|
else if (strmatch(argv[idx_type]->text, "flooding"))
|
2018-09-04 12:55:19 +02:00
|
|
|
SET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_FLOOD);
|
2004-09-01 23:36:14 +02:00
|
|
|
} else
|
2018-09-04 12:55:19 +02:00
|
|
|
SET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-05-18 20:57:06 +02:00
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2004-09-01 23:36:14 +02:00
|
|
|
DEFUN (no_debug_ospf6_lsa_type,
|
|
|
|
no_debug_ospf6_lsa_hex_cmd,
|
2021-10-06 02:25:55 +02:00
|
|
|
"no debug ospf6 lsa <router|network|inter-prefix|inter-router|as-external|nssa|link|intra-prefix|unknown> [<originate|examine|flooding>]",
|
2004-05-18 20:57:06 +02:00
|
|
|
NO_STR
|
|
|
|
DEBUG_STR
|
|
|
|
OSPF6_STR
|
|
|
|
"Debug Link State Advertisements (LSAs)\n"
|
2016-11-05 00:03:03 +01:00
|
|
|
"Display Router LSAs\n"
|
|
|
|
"Display Network LSAs\n"
|
|
|
|
"Display Inter-Area-Prefix LSAs\n"
|
2016-11-30 00:07:11 +01:00
|
|
|
"Display Inter-Router LSAs\n"
|
2016-11-05 00:03:03 +01:00
|
|
|
"Display As-External LSAs\n"
|
2021-10-06 02:25:55 +02:00
|
|
|
"Display NSSA LSAs\n"
|
2016-11-05 00:03:03 +01:00
|
|
|
"Display Link LSAs\n"
|
|
|
|
"Display Intra-Area-Prefix LSAs\n"
|
2016-11-30 00:07:11 +01:00
|
|
|
"Display LSAs of unknown origin\n"
|
2016-11-05 00:03:03 +01:00
|
|
|
"Display details of LSAs\n"
|
|
|
|
"Dump LSAs\n"
|
|
|
|
"Display LSA's internal information\n")
|
2004-05-18 20:57:06 +02:00
|
|
|
{
|
2016-09-23 21:56:31 +02:00
|
|
|
int idx_lsa = 4;
|
2016-09-30 03:27:05 +02:00
|
|
|
int idx_type = 5;
|
2018-03-27 21:13:34 +02:00
|
|
|
unsigned int i;
|
2016-09-23 21:56:31 +02:00
|
|
|
struct ospf6_lsa_handler *handler = NULL;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2021-11-06 16:35:33 +01:00
|
|
|
for (i = 0; i < array_size(lsa_handlers); i++) {
|
|
|
|
handler = lsa_handlers[i];
|
2004-09-01 23:36:14 +02:00
|
|
|
if (handler == NULL)
|
|
|
|
continue;
|
|
|
|
if (strncmp(argv[idx_lsa]->arg, ospf6_lsa_handler_name(handler),
|
|
|
|
strlen(argv[idx_lsa]->arg))
|
2017-07-17 14:03:14 +02:00
|
|
|
== 0)
|
2017-07-13 19:42:42 +02:00
|
|
|
break;
|
2017-10-08 18:20:12 +02:00
|
|
|
if (!strcasecmp(argv[idx_lsa]->arg, handler->lh_name))
|
2004-09-01 23:36:14 +02:00
|
|
|
break;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2004-09-01 23:36:14 +02:00
|
|
|
if (handler == NULL)
|
|
|
|
return CMD_SUCCESS;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2016-09-30 03:27:05 +02:00
|
|
|
if (argc == 6) {
|
2017-06-26 20:15:19 +02:00
|
|
|
if (strmatch(argv[idx_type]->text, "originate"))
|
2018-09-04 12:55:19 +02:00
|
|
|
UNSET_FLAG(handler->lh_debug,
|
|
|
|
OSPF6_LSA_DEBUG_ORIGINATE);
|
2017-06-26 20:15:19 +02:00
|
|
|
if (strmatch(argv[idx_type]->text, "examine"))
|
2018-09-04 12:55:19 +02:00
|
|
|
UNSET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_EXAMIN);
|
2017-06-26 20:15:19 +02:00
|
|
|
if (strmatch(argv[idx_type]->text, "flooding"))
|
2018-09-04 12:55:19 +02:00
|
|
|
UNSET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_FLOOD);
|
2017-07-17 14:03:14 +02:00
|
|
|
} else
|
2018-09-04 12:55:19 +02:00
|
|
|
UNSET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-09-01 23:36:14 +02:00
|
|
|
return CMD_SUCCESS;
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
|
|
|
|
2008-08-15 14:45:30 +02:00
|
|
|
void install_element_ospf6_debug_lsa(void)
|
2017-07-17 14:03:14 +02:00
|
|
|
{
|
2021-06-02 09:08:40 +02:00
|
|
|
install_element(ENABLE_NODE, &debug_ospf6_lsa_all_cmd);
|
|
|
|
install_element(CONFIG_NODE, &debug_ospf6_lsa_all_cmd);
|
2004-09-01 23:36:14 +02:00
|
|
|
install_element(ENABLE_NODE, &debug_ospf6_lsa_hex_cmd);
|
|
|
|
install_element(ENABLE_NODE, &no_debug_ospf6_lsa_hex_cmd);
|
|
|
|
install_element(CONFIG_NODE, &debug_ospf6_lsa_hex_cmd);
|
|
|
|
install_element(CONFIG_NODE, &no_debug_ospf6_lsa_hex_cmd);
|
2021-05-28 11:33:03 +02:00
|
|
|
|
|
|
|
install_element(ENABLE_NODE, &debug_ospf6_lsa_aggregation_cmd);
|
|
|
|
install_element(CONFIG_NODE, &debug_ospf6_lsa_aggregation_cmd);
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
|
|
|
|
2004-09-01 23:36:14 +02:00
|
|
|
int config_write_ospf6_debug_lsa(struct vty *vty)
|
2017-07-17 14:03:14 +02:00
|
|
|
{
|
2018-03-27 21:13:34 +02:00
|
|
|
unsigned int i;
|
2017-10-08 18:20:12 +02:00
|
|
|
const struct ospf6_lsa_handler *handler;
|
2021-06-02 09:08:40 +02:00
|
|
|
bool debug_all = true;
|
|
|
|
|
2021-11-06 16:35:33 +01:00
|
|
|
for (i = 0; i < array_size(lsa_handlers); i++) {
|
|
|
|
handler = lsa_handlers[i];
|
2021-06-02 09:08:40 +02:00
|
|
|
if (handler == NULL)
|
|
|
|
continue;
|
|
|
|
if (CHECK_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_ALL)
|
|
|
|
< OSPF6_LSA_DEBUG_ALL) {
|
|
|
|
debug_all = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (debug_all) {
|
|
|
|
vty_out(vty, "debug ospf6 lsa all\n");
|
|
|
|
return 0;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2021-11-06 16:35:33 +01:00
|
|
|
for (i = 0; i < array_size(lsa_handlers); i++) {
|
|
|
|
handler = lsa_handlers[i];
|
2004-09-01 23:36:14 +02:00
|
|
|
if (handler == NULL)
|
|
|
|
continue;
|
2018-09-04 12:55:19 +02:00
|
|
|
if (CHECK_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG))
|
2017-07-13 19:42:42 +02:00
|
|
|
vty_out(vty, "debug ospf6 lsa %s\n",
|
|
|
|
ospf6_lsa_handler_name(handler));
|
2018-09-04 12:55:19 +02:00
|
|
|
if (CHECK_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_ORIGINATE))
|
2017-07-13 19:42:42 +02:00
|
|
|
vty_out(vty, "debug ospf6 lsa %s originate\n",
|
|
|
|
ospf6_lsa_handler_name(handler));
|
2018-09-04 12:55:19 +02:00
|
|
|
if (CHECK_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_EXAMIN))
|
2017-07-13 19:42:42 +02:00
|
|
|
vty_out(vty, "debug ospf6 lsa %s examine\n",
|
|
|
|
ospf6_lsa_handler_name(handler));
|
2018-09-04 12:55:19 +02:00
|
|
|
if (CHECK_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_FLOOD))
|
2017-07-13 19:42:42 +02:00
|
|
|
vty_out(vty, "debug ospf6 lsa %s flooding\n",
|
|
|
|
ospf6_lsa_handler_name(handler));
|
2021-05-28 11:33:03 +02:00
|
|
|
if (CHECK_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_AGGR))
|
|
|
|
vty_out(vty, "debug ospf6 lsa aggregation\n");
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2004-08-15 07:52:07 +02:00
|
|
|
return 0;
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|