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