]> git.proxmox.com Git - mirror_frr.git/blame - ospf6d/ospf6_lsa.c
Merge pull request #10447 from ton31337/fix/json_with_whitespaces
[mirror_frr.git] / ospf6d / ospf6_lsa.c
CommitLineData
718e3744 1/*
508e53e2 2 * Copyright (C) 2003 Yasuhiro Ohara
718e3744 3 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
896014f4
DL
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
718e3744 19 */
20
21#include <zebra.h>
22
23/* Include other stuffs */
718e3744 24#include "log.h"
718e3744 25#include "linklist.h"
1e05838a 26#include "vector.h"
27#include "vty.h"
718e3744 28#include "command.h"
29#include "memory.h"
718e3744 30#include "thread.h"
d8a4e42b 31#include "checksum.h"
6ddb368d 32#include "frrstr.h"
718e3744 33
34#include "ospf6_proto.h"
718e3744 35#include "ospf6_lsa.h"
36#include "ospf6_lsdb.h"
37#include "ospf6_message.h"
c4122b55
YR
38#include "ospf6_asbr.h"
39#include "ospf6_zebra.h"
718e3744 40
41#include "ospf6_top.h"
42#include "ospf6_area.h"
43#include "ospf6_interface.h"
44#include "ospf6_neighbor.h"
718e3744 45
508e53e2 46#include "ospf6_flood.h"
049207c3 47#include "ospf6d.h"
718e3744 48
4dc43886
MR
49#ifndef VTYSH_EXTRACT_PL
50#include "ospf6d/ospf6_lsa_clippy.c"
51#endif
52
30043e4c
DL
53DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_LSA, "OSPF6 LSA");
54DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_LSA_HEADER, "OSPF6 LSA header");
55DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_LSA_SUMMARY, "OSPF6 LSA summary");
56
067967b8 57static struct ospf6_lsa_handler *lsa_handlers[OSPF6_LSTYPE_SIZE];
718e3744 58
beadc736 59struct ospf6 *ospf6_get_by_lsdb(struct ospf6_lsa *lsa)
60{
61 struct ospf6 *ospf6 = NULL;
62
63 switch (OSPF6_LSA_SCOPE(lsa->header->type)) {
64 case OSPF6_SCOPE_LINKLOCAL:
65 ospf6 = OSPF6_INTERFACE(lsa->lsdb->data)->area->ospf6;
66 break;
67 case OSPF6_SCOPE_AREA:
68 ospf6 = OSPF6_AREA(lsa->lsdb->data)->ospf6;
69 break;
70 case OSPF6_SCOPE_AS:
71 ospf6 = OSPF6_PROCESS(lsa->lsdb->data);
72 break;
73 default:
74 assert(0);
75 break;
76 }
77 return ospf6;
78}
79
e4bacbaa
YR
80static int ospf6_unknown_lsa_show(struct vty *vty, struct ospf6_lsa *lsa,
81 json_object *json_obj, bool use_json)
1e05838a 82{
d7c0a89a 83 uint8_t *start, *end, *current;
1e05838a 84
d7c0a89a
QY
85 start = (uint8_t *)lsa->header + sizeof(struct ospf6_lsa_header);
86 end = (uint8_t *)lsa->header + ntohs(lsa->header->length);
1e05838a 87
77a2f8e5
DA
88#if CONFDATE > 20230131
89CPP_NOTICE("Remove JSON object commands with keys starting with capital")
90#endif
91 if (use_json) {
e4bacbaa 92 json_object_string_add(json_obj, "LsaType", "unknown");
77a2f8e5
DA
93 json_object_string_add(json_obj, "lsaType", "unknown");
94 } else {
e4bacbaa
YR
95 vty_out(vty, " Unknown contents:\n");
96 for (current = start; current < end; current++) {
97 if ((current - start) % 16 == 0)
98 vty_out(vty, "\n ");
99 else if ((current - start) % 4 == 0)
100 vty_out(vty, " ");
101
6ddb368d 102 vty_out(vty, "%02x", *current);
e4bacbaa 103 }
718e3744 104
e4bacbaa 105 vty_out(vty, "\n\n");
d62a17ae 106 }
d62a17ae 107 return 0;
1e05838a 108}
109
3981b5c7
VJ
110static struct ospf6_lsa_handler unknown_handler = {
111 .lh_type = OSPF6_LSTYPE_UNKNOWN,
112 .lh_name = "Unknown",
113 .lh_short_name = "Unk",
114 .lh_show = ospf6_unknown_lsa_show,
115 .lh_get_prefix_str = NULL,
116 .lh_debug = 0 /* No default debug */
117};
1e05838a 118
4062abfa 119void ospf6_install_lsa_handler(struct ospf6_lsa_handler *handler)
1e05838a 120{
d62a17ae 121 /* type in handler is host byte order */
067967b8
DL
122 unsigned int index = handler->lh_type & OSPF6_LSTYPE_FCODE_MASK;
123
124 assertf(index < array_size(lsa_handlers), "index=%x", index);
125 assertf(lsa_handlers[index] == NULL, "old=%s, new=%s",
126 lsa_handlers[index]->lh_name, handler->lh_name);
127
128 lsa_handlers[index] = handler;
1e05838a 129}
130
4062abfa 131struct ospf6_lsa_handler *ospf6_get_lsa_handler(uint16_t type)
1e05838a 132{
4062abfa 133 struct ospf6_lsa_handler *handler = NULL;
d62a17ae 134 unsigned int index = ntohs(type) & OSPF6_LSTYPE_FCODE_MASK;
1e05838a 135
067967b8
DL
136 if (index < array_size(lsa_handlers))
137 handler = lsa_handlers[index];
1e05838a 138
d62a17ae 139 if (handler == NULL)
140 handler = &unknown_handler;
2680aa2b 141
d62a17ae 142 return handler;
1e05838a 143}
718e3744 144
d7c0a89a 145const char *ospf6_lstype_name(uint16_t type)
508e53e2 146{
d62a17ae 147 static char buf[8];
3981b5c7 148 const struct ospf6_lsa_handler *handler;
508e53e2 149
d62a17ae 150 handler = ospf6_get_lsa_handler(type);
151 if (handler && handler != &unknown_handler)
3981b5c7 152 return handler->lh_name;
718e3744 153
d62a17ae 154 snprintf(buf, sizeof(buf), "0x%04hx", ntohs(type));
155 return buf;
718e3744 156}
157
d7c0a89a 158const char *ospf6_lstype_short_name(uint16_t type)
e68a6767 159{
d62a17ae 160 static char buf[8];
3981b5c7 161 const struct ospf6_lsa_handler *handler;
e68a6767 162
d62a17ae 163 handler = ospf6_get_lsa_handler(type);
3e67830c 164 if (handler)
3981b5c7 165 return handler->lh_short_name;
e68a6767 166
d62a17ae 167 snprintf(buf, sizeof(buf), "0x%04hx", ntohs(type));
168 return buf;
e68a6767
DD
169}
170
d7c0a89a 171uint8_t ospf6_lstype_debug(uint16_t type)
1e05838a 172{
3981b5c7 173 const struct ospf6_lsa_handler *handler;
d62a17ae 174 handler = ospf6_get_lsa_handler(type);
01db90cd 175 return handler->lh_debug;
1e05838a 176}
177
c4122b55
YR
178int metric_type(struct ospf6 *ospf6, int type, uint8_t instance)
179{
180 struct ospf6_redist *red;
181
182 red = ospf6_redist_lookup(ospf6, type, instance);
183
184 return ((!red || red->dmetric.type < 0) ? DEFAULT_METRIC_TYPE
185 : red->dmetric.type);
186}
187
188int metric_value(struct ospf6 *ospf6, int type, uint8_t instance)
189{
190 struct ospf6_redist *red;
191
192 red = ospf6_redist_lookup(ospf6, type, instance);
193 if (!red || red->dmetric.value < 0) {
194 if (type == DEFAULT_ROUTE) {
195 if (ospf6->default_originate == DEFAULT_ORIGINATE_ZEBRA)
196 return DEFAULT_DEFAULT_ORIGINATE_METRIC;
197 else
198 return DEFAULT_DEFAULT_ALWAYS_METRIC;
199 } else
200 return DEFAULT_DEFAULT_METRIC;
201 }
202
203 return red->dmetric.value;
204}
205
718e3744 206/* RFC2328: Section 13.2 */
d62a17ae 207int ospf6_lsa_is_differ(struct ospf6_lsa *lsa1, struct ospf6_lsa *lsa2)
718e3744 208{
d62a17ae 209 int len;
718e3744 210
d62a17ae 211 assert(OSPF6_LSA_IS_SAME(lsa1, lsa2));
718e3744 212
d62a17ae 213 /* XXX, Options ??? */
718e3744 214
d62a17ae 215 ospf6_lsa_age_current(lsa1);
216 ospf6_lsa_age_current(lsa2);
217 if (ntohs(lsa1->header->age) == OSPF_LSA_MAXAGE
218 && ntohs(lsa2->header->age) != OSPF_LSA_MAXAGE)
219 return 1;
220 if (ntohs(lsa1->header->age) != OSPF_LSA_MAXAGE
221 && ntohs(lsa2->header->age) == OSPF_LSA_MAXAGE)
222 return 1;
718e3744 223
d62a17ae 224 /* compare body */
225 if (ntohs(lsa1->header->length) != ntohs(lsa2->header->length))
226 return 1;
718e3744 227
d62a17ae 228 len = ntohs(lsa1->header->length) - sizeof(struct ospf6_lsa_header);
229 return memcmp(lsa1->header + 1, lsa2->header + 1, len);
718e3744 230}
231
d62a17ae 232int ospf6_lsa_is_changed(struct ospf6_lsa *lsa1, struct ospf6_lsa *lsa2)
718e3744 233{
d62a17ae 234 int length;
718e3744 235
d62a17ae 236 if (OSPF6_LSA_IS_MAXAGE(lsa1) ^ OSPF6_LSA_IS_MAXAGE(lsa2))
237 return 1;
238 if (ntohs(lsa1->header->length) != ntohs(lsa2->header->length))
239 return 1;
240 /* Going beyond LSA headers to compare the payload only makes sense,
241 * when both LSAs aren't header-only. */
242 if (CHECK_FLAG(lsa1->flag, OSPF6_LSA_HEADERONLY)
243 != CHECK_FLAG(lsa2->flag, OSPF6_LSA_HEADERONLY)) {
244 zlog_warn(
245 "%s: only one of two (%s, %s) LSAs compared is header-only",
246 __func__, lsa1->name, lsa2->name);
247 return 1;
248 }
249 if (CHECK_FLAG(lsa1->flag, OSPF6_LSA_HEADERONLY))
250 return 0;
718e3744 251
d62a17ae 252 length = OSPF6_LSA_SIZE(lsa1->header) - sizeof(struct ospf6_lsa_header);
253 /* Once upper layer verifies LSAs received, length underrun should
254 * become a warning. */
255 if (length <= 0)
256 return 0;
718e3744 257
d62a17ae 258 return memcmp(OSPF6_LSA_HEADER_END(lsa1->header),
259 OSPF6_LSA_HEADER_END(lsa2->header), length);
718e3744 260}
261
262/* ospf6 age functions */
3b68735f 263/* calculate birth */
da086a3b 264void ospf6_lsa_age_set(struct ospf6_lsa *lsa)
718e3744 265{
d62a17ae 266 struct timeval now;
718e3744 267
d62a17ae 268 assert(lsa && lsa->header);
718e3744 269
d62a17ae 270 monotime(&now);
718e3744 271
d62a17ae 272 lsa->birth.tv_sec = now.tv_sec - ntohs(lsa->header->age);
273 lsa->birth.tv_usec = now.tv_usec;
3b68735f 274
d62a17ae 275 return;
718e3744 276}
277
278/* this function calculates current age from its birth,
279 then update age field of LSA header. return value is current age */
d7c0a89a 280uint16_t ospf6_lsa_age_current(struct ospf6_lsa *lsa)
718e3744 281{
d62a17ae 282 struct timeval now;
d7c0a89a
QY
283 uint32_t ulage;
284 uint16_t age;
718e3744 285
d62a17ae 286 assert(lsa);
287 assert(lsa->header);
718e3744 288
d62a17ae 289 /* current time */
290 monotime(&now);
718e3744 291
d62a17ae 292 if (ntohs(lsa->header->age) >= OSPF_LSA_MAXAGE) {
293 /* ospf6_lsa_premature_aging () sets age to MAXAGE; when using
294 relative time, we cannot compare against lsa birth time, so
295 we catch this special case here. */
296 lsa->header->age = htons(OSPF_LSA_MAXAGE);
297 return OSPF_LSA_MAXAGE;
298 }
299 /* calculate age */
300 ulage = now.tv_sec - lsa->birth.tv_sec;
718e3744 301
d62a17ae 302 /* if over MAXAGE, set to it */
303 age = (ulage > OSPF_LSA_MAXAGE ? OSPF_LSA_MAXAGE : ulage);
718e3744 304
d62a17ae 305 lsa->header->age = htons(age);
306 return age;
718e3744 307}
308
309/* update age field of LSA header with adding InfTransDelay */
d7c0a89a 310void ospf6_lsa_age_update_to_send(struct ospf6_lsa *lsa, uint32_t transdelay)
d62a17ae 311{
312 unsigned short age;
313
314 age = ospf6_lsa_age_current(lsa) + transdelay;
315 if (age > OSPF_LSA_MAXAGE)
316 age = OSPF_LSA_MAXAGE;
317 lsa->header->age = htons(age);
318}
319
320void ospf6_lsa_premature_aging(struct ospf6_lsa *lsa)
321{
322 /* log */
323 if (IS_OSPF6_DEBUG_LSA_TYPE(lsa->header->type))
324 zlog_debug("LSA: Premature aging: %s", lsa->name);
325
326 THREAD_OFF(lsa->expire);
327 THREAD_OFF(lsa->refresh);
328
329 /*
330 * We clear the LSA from the neighbor retx lists now because it
331 * will not get deleted later. Essentially, changing the age to
332 * MaxAge will prevent this LSA from being matched with its
333 * existing entries in the retx list thereby causing those entries
334 * to be silently replaced with its MaxAged version, but with ever
335 * increasing retx count causing this LSA to remain forever and
336 * for the MaxAge remover thread to be called forever too.
337 *
338 * The reason the previous entry silently disappears is that when
339 * entry is added to a neighbor's retx list, it replaces the existing
340 * entry. But since the ospf6_lsdb_add() routine is generic and not
341 * aware
342 * of the special semantics of retx count, the retx count is not
343 * decremented when its replaced. Attempting to add the incr and decr
344 * retx count routines as the hook_add and hook_remove for the retx
345 * lists
346 * have a problem because the hook_remove routine is called for MaxAge
347 * entries (as will be the case in a traditional LSDB, unlike in this
348 * case
349 * where an LSDB is used as an efficient tree structure to store all
350 * kinds
351 * of data) that are added instead of calling the hook_add routine.
352 */
353
354 ospf6_flood_clear(lsa);
355
356 lsa->header->age = htons(OSPF_LSA_MAXAGE);
357 thread_execute(master, ospf6_lsa_expire, lsa, 0);
718e3744 358}
359
360/* check which is more recent. if a is more recent, return -1;
361 if the same, return 0; otherwise(b is more recent), return 1 */
d62a17ae 362int ospf6_lsa_compare(struct ospf6_lsa *a, struct ospf6_lsa *b)
718e3744 363{
d62a17ae 364 int32_t seqnuma, seqnumb;
d7c0a89a
QY
365 uint16_t cksuma, cksumb;
366 uint16_t agea, ageb;
d62a17ae 367
368 assert(a && a->header);
369 assert(b && b->header);
370 assert(OSPF6_LSA_IS_SAME(a, b));
718e3744 371
d62a17ae 372 seqnuma = (int32_t)ntohl(a->header->seqnum);
373 seqnumb = (int32_t)ntohl(b->header->seqnum);
718e3744 374
d62a17ae 375 /* compare by sequence number */
376 if (seqnuma > seqnumb)
377 return -1;
378 if (seqnuma < seqnumb)
379 return 1;
380
381 /* Checksum */
382 cksuma = ntohs(a->header->checksum);
383 cksumb = ntohs(b->header->checksum);
384 if (cksuma > cksumb)
385 return -1;
386 if (cksuma < cksumb)
387 return 0;
388
389 /* Update Age */
390 agea = ospf6_lsa_age_current(a);
391 ageb = ospf6_lsa_age_current(b);
392
393 /* MaxAge check */
394 if (agea == OSPF_LSA_MAXAGE && ageb != OSPF_LSA_MAXAGE)
395 return -1;
396 else if (agea != OSPF_LSA_MAXAGE && ageb == OSPF_LSA_MAXAGE)
397 return 1;
398
399 /* Age check */
400 if (agea > ageb && agea - ageb >= OSPF_LSA_MAXAGE_DIFF)
401 return 1;
402 else if (agea < ageb && ageb - agea >= OSPF_LSA_MAXAGE_DIFF)
403 return -1;
404
405 /* neither recent */
406 return 0;
407}
408
409char *ospf6_lsa_printbuf(struct ospf6_lsa *lsa, char *buf, int size)
410{
411 char id[16], adv_router[16];
412 inet_ntop(AF_INET, &lsa->header->id, id, sizeof(id));
413 inet_ntop(AF_INET, &lsa->header->adv_router, adv_router,
414 sizeof(adv_router));
415 snprintf(buf, size, "[%s Id:%s Adv:%s]",
416 ospf6_lstype_name(lsa->header->type), id, adv_router);
417 return buf;
418}
419
420void ospf6_lsa_header_print_raw(struct ospf6_lsa_header *header)
421{
422 char id[16], adv_router[16];
423 inet_ntop(AF_INET, &header->id, id, sizeof(id));
424 inet_ntop(AF_INET, &header->adv_router, adv_router, sizeof(adv_router));
425 zlog_debug(" [%s Id:%s Adv:%s]", ospf6_lstype_name(header->type), id,
426 adv_router);
427 zlog_debug(" Age: %4hu SeqNum: %#08lx Cksum: %04hx Len: %d",
d7c0a89a 428 ntohs(header->age), (unsigned long)ntohl(header->seqnum),
d62a17ae 429 ntohs(header->checksum), ntohs(header->length));
430}
431
432void ospf6_lsa_header_print(struct ospf6_lsa *lsa)
433{
434 ospf6_lsa_age_current(lsa);
435 ospf6_lsa_header_print_raw(lsa->header);
436}
437
438void ospf6_lsa_show_summary_header(struct vty *vty)
439{
440 vty_out(vty, "%-4s %-15s%-15s%4s %8s %30s\n", "Type", "LSId",
441 "AdvRouter", "Age", "SeqNum", "Payload");
442}
443
e4bacbaa
YR
444void ospf6_lsa_show_summary(struct vty *vty, struct ospf6_lsa *lsa,
445 json_object *json_array, bool use_json)
d62a17ae 446{
447 char adv_router[16], id[16];
448 int type;
3981b5c7 449 const struct ospf6_lsa_handler *handler;
e4bacbaa 450 char buf[64];
d62a17ae 451 int cnt = 0;
e4bacbaa 452 json_object *json_obj = NULL;
d62a17ae 453
454 assert(lsa);
455 assert(lsa->header);
456
457 inet_ntop(AF_INET, &lsa->header->id, id, sizeof(id));
458 inet_ntop(AF_INET, &lsa->header->adv_router, adv_router,
459 sizeof(adv_router));
460
461 type = ntohs(lsa->header->type);
462 handler = ospf6_get_lsa_handler(lsa->header->type);
e4bacbaa
YR
463
464 if (use_json)
465 json_obj = json_object_new_object();
466
3e67830c 467 switch (type) {
468 case OSPF6_LSTYPE_INTER_PREFIX:
469 case OSPF6_LSTYPE_INTER_ROUTER:
470 case OSPF6_LSTYPE_AS_EXTERNAL:
ad500b22 471 case OSPF6_LSTYPE_TYPE_7:
e4bacbaa
YR
472 if (use_json) {
473 json_object_string_add(
474 json_obj, "type",
475 ospf6_lstype_short_name(lsa->header->type));
476 json_object_string_add(json_obj, "lsId", id);
477 json_object_string_add(json_obj, "advRouter",
478 adv_router);
479 json_object_int_add(json_obj, "age",
480 ospf6_lsa_age_current(lsa));
481 json_object_int_add(
482 json_obj, "seqNum",
483 (unsigned long)ntohl(lsa->header->seqnum));
484 json_object_string_add(
485 json_obj, "payload",
486 handler->lh_get_prefix_str(lsa, buf,
487 sizeof(buf), 0));
488 json_object_array_add(json_array, json_obj);
489 } else
490 vty_out(vty, "%-4s %-15s%-15s%4hu %8lx %30s\n",
491 ospf6_lstype_short_name(lsa->header->type), id,
492 adv_router, ospf6_lsa_age_current(lsa),
493 (unsigned long)ntohl(lsa->header->seqnum),
494 handler->lh_get_prefix_str(lsa, buf,
495 sizeof(buf), 0));
3e67830c 496 break;
497 case OSPF6_LSTYPE_ROUTER:
498 case OSPF6_LSTYPE_NETWORK:
499 case OSPF6_LSTYPE_GROUP_MEMBERSHIP:
3e67830c 500 case OSPF6_LSTYPE_LINK:
501 case OSPF6_LSTYPE_INTRA_PREFIX:
3981b5c7 502 while (handler->lh_get_prefix_str(lsa, buf, sizeof(buf), cnt)
d62a17ae 503 != NULL) {
e4bacbaa
YR
504 if (use_json) {
505 json_object_string_add(
506 json_obj, "type",
507 ospf6_lstype_short_name(
508 lsa->header->type));
509 json_object_string_add(json_obj, "lsId", id);
510 json_object_string_add(json_obj, "advRouter",
511 adv_router);
512 json_object_int_add(json_obj, "age",
513 ospf6_lsa_age_current(lsa));
514 json_object_int_add(
515 json_obj, "seqNum",
516 (unsigned long)ntohl(
517 lsa->header->seqnum));
518 json_object_string_add(json_obj, "payload",
519 buf);
520 json_object_array_add(json_array, json_obj);
521 json_obj = json_object_new_object();
522 } else
523 vty_out(vty, "%-4s %-15s%-15s%4hu %8lx %30s\n",
524 ospf6_lstype_short_name(
525 lsa->header->type),
526 id, adv_router,
527 ospf6_lsa_age_current(lsa),
528 (unsigned long)ntohl(
529 lsa->header->seqnum),
530 buf);
d62a17ae 531 cnt++;
532 }
e4bacbaa
YR
533 if (use_json)
534 json_object_free(json_obj);
3e67830c 535 break;
536 default:
e4bacbaa
YR
537 if (use_json) {
538 json_object_string_add(
539 json_obj, "type",
540 ospf6_lstype_short_name(lsa->header->type));
541 json_object_string_add(json_obj, "lsId", id);
542 json_object_string_add(json_obj, "advRouter",
543 adv_router);
544 json_object_int_add(json_obj, "age",
545 ospf6_lsa_age_current(lsa));
546 json_object_int_add(
547 json_obj, "seqNum",
548 (unsigned long)ntohl(lsa->header->seqnum));
549 json_object_array_add(json_array, json_obj);
550 } else
551 vty_out(vty, "%-4s %-15s%-15s%4hu %8lx\n",
552 ospf6_lstype_short_name(lsa->header->type), id,
553 adv_router, ospf6_lsa_age_current(lsa),
554 (unsigned long)ntohl(lsa->header->seqnum));
3e67830c 555 break;
e68a6767 556 }
d62a17ae 557}
558
e4bacbaa
YR
559void ospf6_lsa_show_dump(struct vty *vty, struct ospf6_lsa *lsa,
560 json_object *json_array, bool use_json)
d62a17ae 561{
6ddb368d
QY
562 uint8_t *start = NULL;
563 uint8_t *end = NULL;
564 uint8_t *current = NULL;
d62a17ae 565 char byte[4];
6ddb368d
QY
566 char *header_str = NULL;
567 char adv_router[INET6_ADDRSTRLEN];
568 char id[INET6_ADDRSTRLEN];
569 json_object *json = NULL;
d62a17ae 570
d7c0a89a
QY
571 start = (uint8_t *)lsa->header;
572 end = (uint8_t *)lsa->header + ntohs(lsa->header->length);
d62a17ae 573
6ddb368d
QY
574 if (use_json) {
575 json = json_object_new_object();
576 size_t header_str_sz = (2 * (end - start)) + 1;
e4bacbaa 577
6ddb368d 578 header_str = XMALLOC(MTYPE_TMP, header_str_sz);
d62a17ae 579
6ddb368d
QY
580 inet_ntop(AF_INET, &lsa->header->id, id, sizeof(id));
581 inet_ntop(AF_INET, &lsa->header->adv_router, adv_router,
582 sizeof(adv_router));
d62a17ae 583
6ddb368d
QY
584 frrstr_hex(header_str, header_str_sz, start, end - start);
585
586 json_object_string_add(json, "linkStateId", id);
587 json_object_string_add(json, "advertisingRouter", adv_router);
588 json_object_string_add(json, "header", header_str);
589 json_object_array_add(json_array, json);
590
591 XFREE(MTYPE_TMP, header_str);
592 } else {
593 vty_out(vty, "\n%s:\n", lsa->name);
594
595 for (current = start; current < end; current++) {
596 if ((current - start) % 16 == 0)
597 vty_out(vty, "\n ");
598 else if ((current - start) % 4 == 0)
599 vty_out(vty, " ");
600
601 snprintf(byte, sizeof(byte), "%02x", *current);
602 vty_out(vty, "%s", byte);
603 }
d62a17ae 604
6ddb368d
QY
605 vty_out(vty, "\n\n");
606 }
e4bacbaa 607
d62a17ae 608 return;
609}
610
e4bacbaa
YR
611void ospf6_lsa_show_internal(struct vty *vty, struct ospf6_lsa *lsa,
612 json_object *json_array, bool use_json)
d62a17ae 613{
614 char adv_router[64], id[64];
e4bacbaa 615 json_object *json_obj;
d62a17ae 616
617 assert(lsa && lsa->header);
618
619 inet_ntop(AF_INET, &lsa->header->id, id, sizeof(id));
620 inet_ntop(AF_INET, &lsa->header->adv_router, adv_router,
621 sizeof(adv_router));
622
e4bacbaa
YR
623 if (use_json) {
624 json_obj = json_object_new_object();
625 json_object_int_add(json_obj, "age",
626 ospf6_lsa_age_current(lsa));
627 json_object_string_add(json_obj, "type",
628 ospf6_lstype_name(lsa->header->type));
629 json_object_string_add(json_obj, "linkStateId", id);
630 json_object_string_add(json_obj, "advertisingRouter",
631 adv_router);
632 json_object_int_add(json_obj, "lsSequenceNumber",
633 (unsigned long)ntohl(lsa->header->seqnum));
634 json_object_int_add(json_obj, "checksum",
635 ntohs(lsa->header->checksum));
636 json_object_int_add(json_obj, "length",
637 ntohs(lsa->header->length));
638 json_object_int_add(json_obj, "flag", lsa->flag);
639 json_object_int_add(json_obj, "lock", lsa->lock);
640 json_object_int_add(json_obj, "reTxCount", lsa->retrans_count);
641
642 /* Threads Data not added */
643 json_object_array_add(json_array, json_obj);
644 } else {
645 vty_out(vty, "\n");
646 vty_out(vty, "Age: %4hu Type: %s\n", ospf6_lsa_age_current(lsa),
647 ospf6_lstype_name(lsa->header->type));
648 vty_out(vty, "Link State ID: %s\n", id);
649 vty_out(vty, "Advertising Router: %s\n", adv_router);
650 vty_out(vty, "LS Sequence Number: %#010lx\n",
651 (unsigned long)ntohl(lsa->header->seqnum));
652 vty_out(vty, "CheckSum: %#06hx Length: %hu\n",
653 ntohs(lsa->header->checksum),
654 ntohs(lsa->header->length));
655 vty_out(vty, "Flag: %x \n", lsa->flag);
656 vty_out(vty, "Lock: %d \n", lsa->lock);
657 vty_out(vty, "ReTx Count: %d\n", lsa->retrans_count);
461d106d
RW
658 vty_out(vty, "Threads: Expire: %p, Refresh: %p\n", lsa->expire,
659 lsa->refresh);
e4bacbaa
YR
660 vty_out(vty, "\n");
661 }
d62a17ae 662 return;
663}
664
e4bacbaa
YR
665void ospf6_lsa_show(struct vty *vty, struct ospf6_lsa *lsa,
666 json_object *json_array, bool use_json)
d62a17ae 667{
668 char adv_router[64], id[64];
3981b5c7 669 const struct ospf6_lsa_handler *handler;
d62a17ae 670 struct timeval now, res;
68bfcc05 671 char duration[64];
e4bacbaa 672 json_object *json_obj = NULL;
d62a17ae 673
674 assert(lsa && lsa->header);
675
676 inet_ntop(AF_INET, &lsa->header->id, id, sizeof(id));
677 inet_ntop(AF_INET, &lsa->header->adv_router, adv_router,
678 sizeof(adv_router));
679
680 monotime(&now);
681 timersub(&now, &lsa->installed, &res);
682 timerstring(&res, duration, sizeof(duration));
e4bacbaa
YR
683 if (use_json) {
684 json_obj = json_object_new_object();
685 json_object_int_add(json_obj, "age",
686 ospf6_lsa_age_current(lsa));
687 json_object_string_add(json_obj, "type",
688 ospf6_lstype_name(lsa->header->type));
2804f2d2 689 json_object_string_add(json_obj, "linkStateId", id);
e4bacbaa
YR
690 json_object_string_add(json_obj, "advertisingRouter",
691 adv_router);
692 json_object_int_add(json_obj, "lsSequenceNumber",
693 (unsigned long)ntohl(lsa->header->seqnum));
d6265808 694 json_object_int_add(json_obj, "checksum",
e4bacbaa
YR
695 ntohs(lsa->header->checksum));
696 json_object_int_add(json_obj, "length",
697 ntohs(lsa->header->length));
698 json_object_string_add(json_obj, "duration", duration);
699 } else {
700 vty_out(vty, "Age: %4hu Type: %s\n", ospf6_lsa_age_current(lsa),
701 ospf6_lstype_name(lsa->header->type));
702 vty_out(vty, "Link State ID: %s\n", id);
703 vty_out(vty, "Advertising Router: %s\n", adv_router);
704 vty_out(vty, "LS Sequence Number: %#010lx\n",
705 (unsigned long)ntohl(lsa->header->seqnum));
706 vty_out(vty, "CheckSum: %#06hx Length: %hu\n",
707 ntohs(lsa->header->checksum),
708 ntohs(lsa->header->length));
709 vty_out(vty, "Duration: %s\n", duration);
710 }
d62a17ae 711
712 handler = ospf6_get_lsa_handler(lsa->header->type);
3981b5c7
VJ
713
714 if (handler->lh_show != NULL)
e4bacbaa 715 handler->lh_show(vty, lsa, json_obj, use_json);
3981b5c7
VJ
716 else {
717 assert(unknown_handler.lh_show != NULL);
e4bacbaa 718 unknown_handler.lh_show(vty, lsa, json_obj, use_json);
3981b5c7 719 }
d62a17ae 720
e4bacbaa
YR
721 if (use_json)
722 json_object_array_add(json_array, json_obj);
723 else
724 vty_out(vty, "\n");
6452df09 725}
726
771e1fbe
DL
727struct ospf6_lsa *ospf6_lsa_alloc(size_t lsa_length)
728{
30043e4c
DL
729 struct ospf6_lsa *lsa;
730
771e1fbe
DL
731 lsa = XCALLOC(MTYPE_OSPF6_LSA, sizeof(struct ospf6_lsa));
732 lsa->header = XMALLOC(MTYPE_OSPF6_LSA_HEADER, lsa_length);
733
734 return lsa;
735}
736
6452df09 737/* OSPFv3 LSA creation/deletion function */
d62a17ae 738struct ospf6_lsa *ospf6_lsa_create(struct ospf6_lsa_header *header)
718e3744 739{
d62a17ae 740 struct ospf6_lsa *lsa = NULL;
d7c0a89a 741 uint16_t lsa_size = 0;
718e3744 742
d62a17ae 743 /* size of the entire LSA */
744 lsa_size = ntohs(header->length); /* XXX vulnerable */
718e3744 745
771e1fbe 746 lsa = ospf6_lsa_alloc(lsa_size);
718e3744 747
d62a17ae 748 /* copy LSA from original header */
771e1fbe 749 memcpy(lsa->header, header, lsa_size);
718e3744 750
d62a17ae 751 /* dump string */
752 ospf6_lsa_printbuf(lsa, lsa->name, sizeof(lsa->name));
718e3744 753
d62a17ae 754 /* calculate birth of this lsa */
755 ospf6_lsa_age_set(lsa);
718e3744 756
d62a17ae 757 return lsa;
718e3744 758}
759
d62a17ae 760struct ospf6_lsa *ospf6_lsa_create_headeronly(struct ospf6_lsa_header *header)
718e3744 761{
d62a17ae 762 struct ospf6_lsa *lsa = NULL;
718e3744 763
771e1fbe 764 lsa = ospf6_lsa_alloc(sizeof(struct ospf6_lsa_header));
718e3744 765
771e1fbe 766 memcpy(lsa->header, header, sizeof(struct ospf6_lsa_header));
718e3744 767
d62a17ae 768 SET_FLAG(lsa->flag, OSPF6_LSA_HEADERONLY);
718e3744 769
d62a17ae 770 /* dump string */
771 ospf6_lsa_printbuf(lsa, lsa->name, sizeof(lsa->name));
718e3744 772
d62a17ae 773 /* calculate birth of this lsa */
774 ospf6_lsa_age_set(lsa);
718e3744 775
d62a17ae 776 return lsa;
718e3744 777}
778
d62a17ae 779void ospf6_lsa_delete(struct ospf6_lsa *lsa)
718e3744 780{
d62a17ae 781 assert(lsa->lock == 0);
718e3744 782
d62a17ae 783 /* cancel threads */
784 THREAD_OFF(lsa->expire);
785 THREAD_OFF(lsa->refresh);
718e3744 786
d62a17ae 787 /* do free */
d107621d 788 XFREE(MTYPE_OSPF6_LSA_HEADER, lsa->header);
d62a17ae 789 XFREE(MTYPE_OSPF6_LSA, lsa);
508e53e2 790}
718e3744 791
d62a17ae 792struct ospf6_lsa *ospf6_lsa_copy(struct ospf6_lsa *lsa)
508e53e2 793{
d62a17ae 794 struct ospf6_lsa *copy = NULL;
508e53e2 795
d62a17ae 796 ospf6_lsa_age_current(lsa);
797 if (CHECK_FLAG(lsa->flag, OSPF6_LSA_HEADERONLY))
798 copy = ospf6_lsa_create_headeronly(lsa->header);
799 else
800 copy = ospf6_lsa_create(lsa->header);
801 assert(copy->lock == 0);
508e53e2 802
d62a17ae 803 copy->birth = lsa->birth;
804 copy->originated = lsa->originated;
805 copy->received = lsa->received;
806 copy->installed = lsa->installed;
807 copy->lsdb = lsa->lsdb;
808 copy->rn = NULL;
508e53e2 809
d62a17ae 810 return copy;
718e3744 811}
812
508e53e2 813/* increment reference counter of struct ospf6_lsa */
62270cc3 814struct ospf6_lsa *ospf6_lsa_lock(struct ospf6_lsa *lsa)
718e3744 815{
d62a17ae 816 lsa->lock++;
62270cc3 817 return lsa;
718e3744 818}
819
508e53e2 820/* decrement reference counter of struct ospf6_lsa */
744ba569 821struct ospf6_lsa *ospf6_lsa_unlock(struct ospf6_lsa *lsa)
718e3744 822{
d62a17ae 823 /* decrement reference counter */
824 assert(lsa->lock > 0);
825 lsa->lock--;
718e3744 826
d62a17ae 827 if (lsa->lock != 0)
744ba569 828 return lsa;
508e53e2 829
d62a17ae 830 ospf6_lsa_delete(lsa);
744ba569 831 return NULL;
718e3744 832}
833
6b0655a2 834
508e53e2 835/* ospf6 lsa expiry */
cc9f21da 836void ospf6_lsa_expire(struct thread *thread)
718e3744 837{
d62a17ae 838 struct ospf6_lsa *lsa;
beadc736 839 struct ospf6 *ospf6;
718e3744 840
d62a17ae 841 lsa = (struct ospf6_lsa *)THREAD_ARG(thread);
718e3744 842
d62a17ae 843 assert(lsa && lsa->header);
844 assert(OSPF6_LSA_IS_MAXAGE(lsa));
845 assert(!lsa->refresh);
718e3744 846
d62a17ae 847 lsa->expire = (struct thread *)NULL;
718e3744 848
d62a17ae 849 if (IS_OSPF6_DEBUG_LSA_TYPE(lsa->header->type)) {
850 zlog_debug("LSA Expire:");
851 ospf6_lsa_header_print(lsa);
852 }
718e3744 853
d62a17ae 854 if (CHECK_FLAG(lsa->flag, OSPF6_LSA_HEADERONLY))
cc9f21da 855 return; /* dbexchange will do something ... */
beadc736 856 ospf6 = ospf6_get_by_lsdb(lsa);
4dc43886
MR
857 assert(ospf6);
858
d62a17ae 859 /* reinstall lsa */
860 ospf6_install_lsa(lsa);
508e53e2 861
d62a17ae 862 /* reflood lsa */
863 ospf6_flood(NULL, lsa);
bf986da7 864
d62a17ae 865 /* schedule maxage remover */
866 ospf6_maxage_remove(ospf6);
718e3744 867}
868
cc9f21da 869void ospf6_lsa_refresh(struct thread *thread)
718e3744 870{
d62a17ae 871 struct ospf6_lsa *old, *self, *new;
872 struct ospf6_lsdb *lsdb_self;
6452df09 873
d62a17ae 874 old = (struct ospf6_lsa *)THREAD_ARG(thread);
875 assert(old && old->header);
6452df09 876
d62a17ae 877 old->refresh = (struct thread *)NULL;
6452df09 878
d62a17ae 879 lsdb_self = ospf6_get_scoped_lsdb_self(old);
880 self = ospf6_lsdb_lookup(old->header->type, old->header->id,
881 old->header->adv_router, lsdb_self);
882 if (self == NULL) {
883 if (IS_OSPF6_DEBUG_LSA_TYPE(old->header->type))
884 zlog_debug("Refresh: could not find self LSA, flush %s",
885 old->name);
886 ospf6_lsa_premature_aging(old);
cc9f21da 887 return;
d62a17ae 888 }
718e3744 889
d62a17ae 890 /* Reset age, increment LS sequence number. */
891 self->header->age = htons(0);
892 self->header->seqnum =
893 ospf6_new_ls_seqnum(self->header->type, self->header->id,
894 self->header->adv_router, old->lsdb);
895 ospf6_lsa_checksum(self->header);
896
897 new = ospf6_lsa_create(self->header);
898 new->lsdb = old->lsdb;
d62a17ae 899 thread_add_timer(master, ospf6_lsa_refresh, new, OSPF_LS_REFRESH_TIME,
900 &new->refresh);
901
902 /* store it in the LSDB for self-originated LSAs */
903 ospf6_lsdb_add(ospf6_lsa_copy(new), lsdb_self);
904
905 if (IS_OSPF6_DEBUG_LSA_TYPE(new->header->type)) {
906 zlog_debug("LSA Refresh:");
907 ospf6_lsa_header_print(new);
908 }
718e3744 909
d62a17ae 910 ospf6_install_lsa(new);
911 ospf6_flood(NULL, new);
718e3744 912}
913
beadc736 914void ospf6_flush_self_originated_lsas_now(struct ospf6 *ospf6)
76249532 915{
e161c2dc 916 struct listnode *node, *nnode;
76249532
CS
917 struct ospf6_area *oa;
918 struct ospf6_lsa *lsa;
919 const struct route_node *end = NULL;
920 uint32_t type, adv_router;
e161c2dc 921 struct ospf6_interface *oi;
76249532
CS
922
923 ospf6->inst_shutdown = 1;
924
925 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
996c9314
LB
926 end = ospf6_lsdb_head(oa->lsdb_self, 0, 0, ospf6->router_id,
927 &lsa);
76249532
CS
928 while (lsa) {
929 /* RFC 2328 (14.1): Set MAXAGE */
930 lsa->header->age = htons(OSPF_LSA_MAXAGE);
931 /* Flood MAXAGE LSA*/
932 ospf6_flood(NULL, lsa);
933
934 lsa = ospf6_lsdb_next(end, lsa);
935 }
e161c2dc
YR
936
937 for (ALL_LIST_ELEMENTS(oa->if_list, node, nnode, oi)) {
938 end = ospf6_lsdb_head(oi->lsdb_self, 0, 0,
939 ospf6->router_id, &lsa);
940 while (lsa) {
941 /* RFC 2328 (14.1): Set MAXAGE */
942 lsa->header->age = htons(OSPF_LSA_MAXAGE);
943 /* Flood MAXAGE LSA*/
944 ospf6_flood(NULL, lsa);
945
946 lsa = ospf6_lsdb_next(end, lsa);
947 }
948 }
76249532
CS
949 }
950
951 type = htons(OSPF6_LSTYPE_AS_EXTERNAL);
952 adv_router = ospf6->router_id;
953 for (ALL_LSDB_TYPED_ADVRTR(ospf6->lsdb, type, adv_router, lsa)) {
954 /* RFC 2328 (14.1): Set MAXAGE */
955 lsa->header->age = htons(OSPF_LSA_MAXAGE);
956 ospf6_flood(NULL, lsa);
957 }
958}
6b0655a2 959
d8a4e42b 960/* Fletcher Checksum -- Refer to RFC1008. */
718e3744 961
d8a4e42b
JR
962/* All the offsets are zero-based. The offsets in the RFC1008 are
963 one-based. */
d62a17ae 964unsigned short ospf6_lsa_checksum(struct ospf6_lsa_header *lsa_header)
718e3744 965{
d7c0a89a
QY
966 uint8_t *buffer = (uint8_t *)&lsa_header->type;
967 int type_offset =
968 buffer - (uint8_t *)&lsa_header->age; /* should be 2 */
718e3744 969
d62a17ae 970 /* Skip the AGE field */
d7c0a89a 971 uint16_t len = ntohs(lsa_header->length) - type_offset;
718e3744 972
d62a17ae 973 /* Checksum offset starts from "type" field, not the beginning of the
974 lsa_header struct. The offset is 14, rather than 16. */
d7c0a89a 975 int checksum_offset = (uint8_t *)&lsa_header->checksum - buffer;
d8a4e42b 976
d62a17ae 977 return (unsigned short)fletcher_checksum(buffer, len, checksum_offset);
d8a4e42b 978}
718e3744 979
d62a17ae 980int ospf6_lsa_checksum_valid(struct ospf6_lsa_header *lsa_header)
d8a4e42b 981{
d7c0a89a
QY
982 uint8_t *buffer = (uint8_t *)&lsa_header->type;
983 int type_offset =
984 buffer - (uint8_t *)&lsa_header->age; /* should be 2 */
718e3744 985
d62a17ae 986 /* Skip the AGE field */
d7c0a89a 987 uint16_t len = ntohs(lsa_header->length) - type_offset;
718e3744 988
d62a17ae 989 return (fletcher_checksum(buffer, len, FLETCHER_CHECKSUM_VALIDATE)
990 == 0);
718e3744 991}
992
d62a17ae 993void ospf6_lsa_init(void)
6452df09 994{
d62a17ae 995 ospf6_install_lsa_handler(&unknown_handler);
718e3744 996}
997
d62a17ae 998void ospf6_lsa_terminate(void)
ae2254aa 999{
ae2254aa 1000}
6b0655a2 1001
3981b5c7 1002static char *ospf6_lsa_handler_name(const struct ospf6_lsa_handler *h)
1e05838a 1003{
d62a17ae 1004 static char buf[64];
1005 unsigned int i;
3981b5c7 1006 unsigned int size = strlen(h->lh_name);
1e05838a 1007
996c9314
LB
1008 if (!strcmp(h->lh_name, "unknown")
1009 && h->lh_type != OSPF6_LSTYPE_UNKNOWN) {
3981b5c7 1010 snprintf(buf, sizeof(buf), "%#04hx", h->lh_type);
d62a17ae 1011 return buf;
1012 }
1e05838a 1013
d62a17ae 1014 for (i = 0; i < MIN(size, sizeof(buf)); i++) {
3981b5c7
VJ
1015 if (!islower((unsigned char)h->lh_name[i]))
1016 buf[i] = tolower((unsigned char)h->lh_name[i]);
d62a17ae 1017 else
3981b5c7 1018 buf[i] = h->lh_name[i];
d62a17ae 1019 }
1020 buf[size] = '\0';
1021 return buf;
1e05838a 1022}
718e3744 1023
067967b8 1024void ospf6_lsa_debug_set_all(bool val)
d5cb3508
YR
1025{
1026 unsigned int i;
1027 struct ospf6_lsa_handler *handler = NULL;
1028
067967b8
DL
1029 for (i = 0; i < array_size(lsa_handlers); i++) {
1030 handler = lsa_handlers[i];
d5cb3508
YR
1031 if (handler == NULL)
1032 continue;
067967b8 1033 if (val)
d5cb3508
YR
1034 SET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_ALL);
1035 else
1036 UNSET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_ALL);
1037 }
067967b8
DL
1038}
1039
1040DEFPY (debug_ospf6_lsa_all,
1041 debug_ospf6_lsa_all_cmd,
1042 "[no$no] debug ospf6 lsa all",
1043 NO_STR
1044 DEBUG_STR
1045 OSPF6_STR
1046 "Debug Link State Advertisements (LSAs)\n"
1047 "Display for all types of LSAs\n")
1048{
1049 ospf6_lsa_debug_set_all(!no);
d5cb3508
YR
1050 return CMD_SUCCESS;
1051}
1052
4dc43886
MR
1053DEFPY (debug_ospf6_lsa_aggregation,
1054 debug_ospf6_lsa_aggregation_cmd,
1055 "[no] debug ospf6 lsa aggregation",
1056 NO_STR
1057 DEBUG_STR
1058 OSPF6_STR
1059 "Debug Link State Advertisements (LSAs)\n"
1060 "External LSA Aggregation\n")
1061{
1062
1063 struct ospf6_lsa_handler *handler;
1064
1065 handler = ospf6_get_lsa_handler(OSPF6_LSTYPE_AS_EXTERNAL);
1066 if (handler == NULL)
1067 return CMD_WARNING_CONFIG_FAILED;
1068
1069 if (no)
1070 UNSET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_AGGR);
1071 else
1072 SET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_AGGR);
1073
1074 return CMD_SUCCESS;
1075}
1076
1e05838a 1077DEFUN (debug_ospf6_lsa_type,
1078 debug_ospf6_lsa_hex_cmd,
576e8424 1079 "debug ospf6 lsa <router|network|inter-prefix|inter-router|as-external|nssa|link|intra-prefix|unknown> [<originate|examine|flooding>]",
508e53e2 1080 DEBUG_STR
1081 OSPF6_STR
1082 "Debug Link State Advertisements (LSAs)\n"
3a2d747c
QY
1083 "Display Router LSAs\n"
1084 "Display Network LSAs\n"
1085 "Display Inter-Area-Prefix LSAs\n"
1086 "Display Inter-Router LSAs\n"
1087 "Display As-External LSAs\n"
576e8424 1088 "Display NSSA LSAs\n"
3a2d747c
QY
1089 "Display Link LSAs\n"
1090 "Display Intra-Area-Prefix LSAs\n"
1091 "Display LSAs of unknown origin\n"
1092 "Display details of LSAs\n"
1093 "Dump LSAs\n"
1094 "Display LSA's internal information\n")
508e53e2 1095{
d62a17ae 1096 int idx_lsa = 3;
1097 int idx_type = 4;
1098 unsigned int i;
1099 struct ospf6_lsa_handler *handler = NULL;
1100
067967b8
DL
1101 for (i = 0; i < array_size(lsa_handlers); i++) {
1102 handler = lsa_handlers[i];
d62a17ae 1103 if (handler == NULL)
1104 continue;
1105 if (strncmp(argv[idx_lsa]->arg, ospf6_lsa_handler_name(handler),
1106 strlen(argv[idx_lsa]->arg))
1107 == 0)
1108 break;
3981b5c7 1109 if (!strcasecmp(argv[idx_lsa]->arg, handler->lh_name))
d62a17ae 1110 break;
1111 handler = NULL;
1112 }
1113
1114 if (handler == NULL)
1115 handler = &unknown_handler;
1116
1117 if (argc == 5) {
1118 if (strmatch(argv[idx_type]->text, "originate"))
01db90cd 1119 SET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_ORIGINATE);
d62a17ae 1120 else if (strmatch(argv[idx_type]->text, "examine"))
01db90cd 1121 SET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_EXAMIN);
d62a17ae 1122 else if (strmatch(argv[idx_type]->text, "flooding"))
01db90cd 1123 SET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_FLOOD);
d62a17ae 1124 } else
01db90cd 1125 SET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG);
d62a17ae 1126
1127 return CMD_SUCCESS;
508e53e2 1128}
1129
1e05838a 1130DEFUN (no_debug_ospf6_lsa_type,
1131 no_debug_ospf6_lsa_hex_cmd,
576e8424 1132 "no debug ospf6 lsa <router|network|inter-prefix|inter-router|as-external|nssa|link|intra-prefix|unknown> [<originate|examine|flooding>]",
508e53e2 1133 NO_STR
1134 DEBUG_STR
1135 OSPF6_STR
1136 "Debug Link State Advertisements (LSAs)\n"
16cedbb0
QY
1137 "Display Router LSAs\n"
1138 "Display Network LSAs\n"
1139 "Display Inter-Area-Prefix LSAs\n"
3a2d747c 1140 "Display Inter-Router LSAs\n"
16cedbb0 1141 "Display As-External LSAs\n"
576e8424 1142 "Display NSSA LSAs\n"
16cedbb0
QY
1143 "Display Link LSAs\n"
1144 "Display Intra-Area-Prefix LSAs\n"
3a2d747c 1145 "Display LSAs of unknown origin\n"
16cedbb0
QY
1146 "Display details of LSAs\n"
1147 "Dump LSAs\n"
1148 "Display LSA's internal information\n")
508e53e2 1149{
d62a17ae 1150 int idx_lsa = 4;
1151 int idx_type = 5;
d7c0a89a 1152 unsigned int i;
d62a17ae 1153 struct ospf6_lsa_handler *handler = NULL;
1154
067967b8
DL
1155 for (i = 0; i < array_size(lsa_handlers); i++) {
1156 handler = lsa_handlers[i];
d62a17ae 1157 if (handler == NULL)
1158 continue;
1159 if (strncmp(argv[idx_lsa]->arg, ospf6_lsa_handler_name(handler),
1160 strlen(argv[idx_lsa]->arg))
1161 == 0)
1162 break;
3981b5c7 1163 if (!strcasecmp(argv[idx_lsa]->arg, handler->lh_name))
d62a17ae 1164 break;
1165 }
718e3744 1166
d62a17ae 1167 if (handler == NULL)
1168 return CMD_SUCCESS;
1169
1170 if (argc == 6) {
1171 if (strmatch(argv[idx_type]->text, "originate"))
01db90cd
DL
1172 UNSET_FLAG(handler->lh_debug,
1173 OSPF6_LSA_DEBUG_ORIGINATE);
d62a17ae 1174 if (strmatch(argv[idx_type]->text, "examine"))
01db90cd 1175 UNSET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_EXAMIN);
d62a17ae 1176 if (strmatch(argv[idx_type]->text, "flooding"))
01db90cd 1177 UNSET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_FLOOD);
d62a17ae 1178 } else
01db90cd 1179 UNSET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG);
d62a17ae 1180
1181 return CMD_SUCCESS;
1182}
1183
1184void install_element_ospf6_debug_lsa(void)
1185{
d5cb3508
YR
1186 install_element(ENABLE_NODE, &debug_ospf6_lsa_all_cmd);
1187 install_element(CONFIG_NODE, &debug_ospf6_lsa_all_cmd);
d62a17ae 1188 install_element(ENABLE_NODE, &debug_ospf6_lsa_hex_cmd);
1189 install_element(ENABLE_NODE, &no_debug_ospf6_lsa_hex_cmd);
1190 install_element(CONFIG_NODE, &debug_ospf6_lsa_hex_cmd);
1191 install_element(CONFIG_NODE, &no_debug_ospf6_lsa_hex_cmd);
4dc43886
MR
1192
1193 install_element(ENABLE_NODE, &debug_ospf6_lsa_aggregation_cmd);
1194 install_element(CONFIG_NODE, &debug_ospf6_lsa_aggregation_cmd);
d62a17ae 1195}
1196
1197int config_write_ospf6_debug_lsa(struct vty *vty)
1198{
d7c0a89a 1199 unsigned int i;
3981b5c7 1200 const struct ospf6_lsa_handler *handler;
d5cb3508
YR
1201 bool debug_all = true;
1202
067967b8
DL
1203 for (i = 0; i < array_size(lsa_handlers); i++) {
1204 handler = lsa_handlers[i];
d5cb3508
YR
1205 if (handler == NULL)
1206 continue;
1207 if (CHECK_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_ALL)
1208 < OSPF6_LSA_DEBUG_ALL) {
1209 debug_all = false;
1210 break;
1211 }
1212 }
1213
1214 if (debug_all) {
1215 vty_out(vty, "debug ospf6 lsa all\n");
1216 return 0;
1217 }
d62a17ae 1218
067967b8
DL
1219 for (i = 0; i < array_size(lsa_handlers); i++) {
1220 handler = lsa_handlers[i];
d62a17ae 1221 if (handler == NULL)
1222 continue;
01db90cd 1223 if (CHECK_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG))
d62a17ae 1224 vty_out(vty, "debug ospf6 lsa %s\n",
1225 ospf6_lsa_handler_name(handler));
01db90cd 1226 if (CHECK_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_ORIGINATE))
d62a17ae 1227 vty_out(vty, "debug ospf6 lsa %s originate\n",
1228 ospf6_lsa_handler_name(handler));
01db90cd 1229 if (CHECK_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_EXAMIN))
d62a17ae 1230 vty_out(vty, "debug ospf6 lsa %s examine\n",
1231 ospf6_lsa_handler_name(handler));
01db90cd 1232 if (CHECK_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_FLOOD))
d62a17ae 1233 vty_out(vty, "debug ospf6 lsa %s flooding\n",
1234 ospf6_lsa_handler_name(handler));
4dc43886
MR
1235 if (CHECK_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_AGGR))
1236 vty_out(vty, "debug ospf6 lsa aggregation\n");
d62a17ae 1237 }
718e3744 1238
d62a17ae 1239 return 0;
1240}