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