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