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