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