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