]> git.proxmox.com Git - mirror_frr.git/blob - ospf6d/ospf6_lsa.c
Merge pull request #805 from Orange-OpenSource/master
[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[16];
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, lsa_size);
513
514 /* copy LSA from original header */
515 memcpy(new_header, header, lsa_size);
516
517 /* LSA information structure */
518 /* allocate memory */
519 lsa = (struct ospf6_lsa *)XCALLOC(MTYPE_OSPF6_LSA,
520 sizeof(struct ospf6_lsa));
521
522 lsa->header = (struct ospf6_lsa_header *)new_header;
523
524 /* dump string */
525 ospf6_lsa_printbuf(lsa, lsa->name, sizeof(lsa->name));
526
527 /* calculate birth of this lsa */
528 ospf6_lsa_age_set(lsa);
529
530 return lsa;
531 }
532
533 struct ospf6_lsa *ospf6_lsa_create_headeronly(struct ospf6_lsa_header *header)
534 {
535 struct ospf6_lsa *lsa = NULL;
536 struct ospf6_lsa_header *new_header = NULL;
537
538 /* allocate memory for this LSA */
539 new_header = (struct ospf6_lsa_header *)XMALLOC(
540 MTYPE_OSPF6_LSA, sizeof(struct ospf6_lsa_header));
541
542 /* copy LSA from original header */
543 memcpy(new_header, header, sizeof(struct ospf6_lsa_header));
544
545 /* LSA information structure */
546 /* allocate memory */
547 lsa = (struct ospf6_lsa *)XCALLOC(MTYPE_OSPF6_LSA,
548 sizeof(struct ospf6_lsa));
549
550 lsa->header = (struct ospf6_lsa_header *)new_header;
551 SET_FLAG(lsa->flag, OSPF6_LSA_HEADERONLY);
552
553 /* dump string */
554 ospf6_lsa_printbuf(lsa, lsa->name, sizeof(lsa->name));
555
556 /* calculate birth of this lsa */
557 ospf6_lsa_age_set(lsa);
558
559 return lsa;
560 }
561
562 void ospf6_lsa_delete(struct ospf6_lsa *lsa)
563 {
564 assert(lsa->lock == 0);
565
566 /* cancel threads */
567 THREAD_OFF(lsa->expire);
568 THREAD_OFF(lsa->refresh);
569
570 /* do free */
571 XFREE(MTYPE_OSPF6_LSA, lsa->header);
572 XFREE(MTYPE_OSPF6_LSA, lsa);
573 }
574
575 struct ospf6_lsa *ospf6_lsa_copy(struct ospf6_lsa *lsa)
576 {
577 struct ospf6_lsa *copy = NULL;
578
579 ospf6_lsa_age_current(lsa);
580 if (CHECK_FLAG(lsa->flag, OSPF6_LSA_HEADERONLY))
581 copy = ospf6_lsa_create_headeronly(lsa->header);
582 else
583 copy = ospf6_lsa_create(lsa->header);
584 assert(copy->lock == 0);
585
586 copy->birth = lsa->birth;
587 copy->originated = lsa->originated;
588 copy->received = lsa->received;
589 copy->installed = lsa->installed;
590 copy->lsdb = lsa->lsdb;
591 copy->rn = NULL;
592
593 return copy;
594 }
595
596 /* increment reference counter of struct ospf6_lsa */
597 void ospf6_lsa_lock(struct ospf6_lsa *lsa)
598 {
599 lsa->lock++;
600 return;
601 }
602
603 /* decrement reference counter of struct ospf6_lsa */
604 void ospf6_lsa_unlock(struct ospf6_lsa *lsa)
605 {
606 /* decrement reference counter */
607 assert(lsa->lock > 0);
608 lsa->lock--;
609
610 if (lsa->lock != 0)
611 return;
612
613 ospf6_lsa_delete(lsa);
614 }
615
616
617 /* ospf6 lsa expiry */
618 int ospf6_lsa_expire(struct thread *thread)
619 {
620 struct ospf6_lsa *lsa;
621
622 lsa = (struct ospf6_lsa *)THREAD_ARG(thread);
623
624 assert(lsa && lsa->header);
625 assert(OSPF6_LSA_IS_MAXAGE(lsa));
626 assert(!lsa->refresh);
627
628 lsa->expire = (struct thread *)NULL;
629
630 if (IS_OSPF6_DEBUG_LSA_TYPE(lsa->header->type)) {
631 zlog_debug("LSA Expire:");
632 ospf6_lsa_header_print(lsa);
633 }
634
635 if (CHECK_FLAG(lsa->flag, OSPF6_LSA_HEADERONLY))
636 return 0; /* dbexchange will do something ... */
637
638 /* reinstall lsa */
639 ospf6_install_lsa(lsa);
640
641 /* reflood lsa */
642 ospf6_flood(NULL, lsa);
643
644 /* schedule maxage remover */
645 ospf6_maxage_remove(ospf6);
646
647 return 0;
648 }
649
650 int ospf6_lsa_refresh(struct thread *thread)
651 {
652 struct ospf6_lsa *old, *self, *new;
653 struct ospf6_lsdb *lsdb_self;
654
655 old = (struct ospf6_lsa *)THREAD_ARG(thread);
656 assert(old && old->header);
657
658 old->refresh = (struct thread *)NULL;
659
660 lsdb_self = ospf6_get_scoped_lsdb_self(old);
661 self = ospf6_lsdb_lookup(old->header->type, old->header->id,
662 old->header->adv_router, lsdb_self);
663 if (self == NULL) {
664 if (IS_OSPF6_DEBUG_LSA_TYPE(old->header->type))
665 zlog_debug("Refresh: could not find self LSA, flush %s",
666 old->name);
667 ospf6_lsa_premature_aging(old);
668 return 0;
669 }
670
671 /* Reset age, increment LS sequence number. */
672 self->header->age = htons(0);
673 self->header->seqnum =
674 ospf6_new_ls_seqnum(self->header->type, self->header->id,
675 self->header->adv_router, old->lsdb);
676 ospf6_lsa_checksum(self->header);
677
678 new = ospf6_lsa_create(self->header);
679 new->lsdb = old->lsdb;
680 new->refresh = NULL;
681 thread_add_timer(master, ospf6_lsa_refresh, new, OSPF_LS_REFRESH_TIME,
682 &new->refresh);
683
684 /* store it in the LSDB for self-originated LSAs */
685 ospf6_lsdb_add(ospf6_lsa_copy(new), lsdb_self);
686
687 if (IS_OSPF6_DEBUG_LSA_TYPE(new->header->type)) {
688 zlog_debug("LSA Refresh:");
689 ospf6_lsa_header_print(new);
690 }
691
692 ospf6_install_lsa(new);
693 ospf6_flood(NULL, new);
694
695 return 0;
696 }
697
698
699 /* Fletcher Checksum -- Refer to RFC1008. */
700
701 /* All the offsets are zero-based. The offsets in the RFC1008 are
702 one-based. */
703 unsigned short ospf6_lsa_checksum(struct ospf6_lsa_header *lsa_header)
704 {
705 u_char *buffer = (u_char *)&lsa_header->type;
706 int type_offset = buffer - (u_char *)&lsa_header->age; /* should be 2 */
707
708 /* Skip the AGE field */
709 u_int16_t len = ntohs(lsa_header->length) - type_offset;
710
711 /* Checksum offset starts from "type" field, not the beginning of the
712 lsa_header struct. The offset is 14, rather than 16. */
713 int checksum_offset = (u_char *)&lsa_header->checksum - buffer;
714
715 return (unsigned short)fletcher_checksum(buffer, len, checksum_offset);
716 }
717
718 int ospf6_lsa_checksum_valid(struct ospf6_lsa_header *lsa_header)
719 {
720 u_char *buffer = (u_char *)&lsa_header->type;
721 int type_offset = buffer - (u_char *)&lsa_header->age; /* should be 2 */
722
723 /* Skip the AGE field */
724 u_int16_t len = ntohs(lsa_header->length) - type_offset;
725
726 return (fletcher_checksum(buffer, len, FLETCHER_CHECKSUM_VALIDATE)
727 == 0);
728 }
729
730 void ospf6_lsa_init(void)
731 {
732 ospf6_lsa_handler_vector = vector_init(0);
733 ospf6_install_lsa_handler(&unknown_handler);
734 }
735
736 void ospf6_lsa_terminate(void)
737 {
738 vector_free(ospf6_lsa_handler_vector);
739 }
740
741 static char *ospf6_lsa_handler_name(struct ospf6_lsa_handler *h)
742 {
743 static char buf[64];
744 unsigned int i;
745 unsigned int size = strlen(h->name);
746
747 if (!strcmp(h->name, "unknown") && h->type != OSPF6_LSTYPE_UNKNOWN) {
748 snprintf(buf, sizeof(buf), "%#04hx", h->type);
749 return buf;
750 }
751
752 for (i = 0; i < MIN(size, sizeof(buf)); i++) {
753 if (!islower((unsigned char)h->name[i]))
754 buf[i] = tolower((unsigned char)h->name[i]);
755 else
756 buf[i] = h->name[i];
757 }
758 buf[size] = '\0';
759 return buf;
760 }
761
762 DEFUN (debug_ospf6_lsa_type,
763 debug_ospf6_lsa_hex_cmd,
764 "debug ospf6 lsa <router|network|inter-prefix|inter-router|as-external|link|intra-prefix|unknown> [<originate|examine|flooding>]",
765 DEBUG_STR
766 OSPF6_STR
767 "Debug Link State Advertisements (LSAs)\n"
768 "Display Router LSAs\n"
769 "Display Network LSAs\n"
770 "Display Inter-Area-Prefix LSAs\n"
771 "Display Inter-Router LSAs\n"
772 "Display As-External LSAs\n"
773 "Display Link LSAs\n"
774 "Display Intra-Area-Prefix LSAs\n"
775 "Display LSAs of unknown origin\n"
776 "Display details of LSAs\n"
777 "Dump LSAs\n"
778 "Display LSA's internal information\n")
779 {
780 int idx_lsa = 3;
781 int idx_type = 4;
782 unsigned int i;
783 struct ospf6_lsa_handler *handler = NULL;
784
785 for (i = 0; i < vector_active(ospf6_lsa_handler_vector); i++) {
786 handler = vector_slot(ospf6_lsa_handler_vector, i);
787 if (handler == NULL)
788 continue;
789 if (strncmp(argv[idx_lsa]->arg, ospf6_lsa_handler_name(handler),
790 strlen(argv[idx_lsa]->arg))
791 == 0)
792 break;
793 if (!strcasecmp(argv[idx_lsa]->arg, handler->name))
794 break;
795 handler = NULL;
796 }
797
798 if (handler == NULL)
799 handler = &unknown_handler;
800
801 if (argc == 5) {
802 if (strmatch(argv[idx_type]->text, "originate"))
803 SET_FLAG(handler->debug, OSPF6_LSA_DEBUG_ORIGINATE);
804 else if (strmatch(argv[idx_type]->text, "examine"))
805 SET_FLAG(handler->debug, OSPF6_LSA_DEBUG_EXAMIN);
806 else if (strmatch(argv[idx_type]->text, "flooding"))
807 SET_FLAG(handler->debug, OSPF6_LSA_DEBUG_FLOOD);
808 } else
809 SET_FLAG(handler->debug, OSPF6_LSA_DEBUG);
810
811 return CMD_SUCCESS;
812 }
813
814 DEFUN (no_debug_ospf6_lsa_type,
815 no_debug_ospf6_lsa_hex_cmd,
816 "no debug ospf6 lsa <router|network|inter-prefix|inter-router|as-external|link|intra-prefix|unknown> [<originate|examine|flooding>]",
817 NO_STR
818 DEBUG_STR
819 OSPF6_STR
820 "Debug Link State Advertisements (LSAs)\n"
821 "Display Router LSAs\n"
822 "Display Network LSAs\n"
823 "Display Inter-Area-Prefix LSAs\n"
824 "Display Inter-Router LSAs\n"
825 "Display As-External LSAs\n"
826 "Display Link LSAs\n"
827 "Display Intra-Area-Prefix LSAs\n"
828 "Display LSAs of unknown origin\n"
829 "Display details of LSAs\n"
830 "Dump LSAs\n"
831 "Display LSA's internal information\n")
832 {
833 int idx_lsa = 4;
834 int idx_type = 5;
835 u_int i;
836 struct ospf6_lsa_handler *handler = NULL;
837
838 for (i = 0; i < vector_active(ospf6_lsa_handler_vector); i++) {
839 handler = vector_slot(ospf6_lsa_handler_vector, i);
840 if (handler == NULL)
841 continue;
842 if (strncmp(argv[idx_lsa]->arg, ospf6_lsa_handler_name(handler),
843 strlen(argv[idx_lsa]->arg))
844 == 0)
845 break;
846 if (!strcasecmp(argv[idx_lsa]->arg, handler->name))
847 break;
848 }
849
850 if (handler == NULL)
851 return CMD_SUCCESS;
852
853 if (argc == 6) {
854 if (strmatch(argv[idx_type]->text, "originate"))
855 UNSET_FLAG(handler->debug, OSPF6_LSA_DEBUG_ORIGINATE);
856 if (strmatch(argv[idx_type]->text, "examine"))
857 UNSET_FLAG(handler->debug, OSPF6_LSA_DEBUG_EXAMIN);
858 if (strmatch(argv[idx_type]->text, "flooding"))
859 UNSET_FLAG(handler->debug, OSPF6_LSA_DEBUG_FLOOD);
860 } else
861 UNSET_FLAG(handler->debug, OSPF6_LSA_DEBUG);
862
863 return CMD_SUCCESS;
864 }
865
866 void install_element_ospf6_debug_lsa(void)
867 {
868 install_element(ENABLE_NODE, &debug_ospf6_lsa_hex_cmd);
869 install_element(ENABLE_NODE, &no_debug_ospf6_lsa_hex_cmd);
870 install_element(CONFIG_NODE, &debug_ospf6_lsa_hex_cmd);
871 install_element(CONFIG_NODE, &no_debug_ospf6_lsa_hex_cmd);
872 }
873
874 int config_write_ospf6_debug_lsa(struct vty *vty)
875 {
876 u_int i;
877 struct ospf6_lsa_handler *handler;
878
879 for (i = 0; i < vector_active(ospf6_lsa_handler_vector); i++) {
880 handler = vector_slot(ospf6_lsa_handler_vector, i);
881 if (handler == NULL)
882 continue;
883 if (CHECK_FLAG(handler->debug, OSPF6_LSA_DEBUG))
884 vty_out(vty, "debug ospf6 lsa %s\n",
885 ospf6_lsa_handler_name(handler));
886 if (CHECK_FLAG(handler->debug, OSPF6_LSA_DEBUG_ORIGINATE))
887 vty_out(vty, "debug ospf6 lsa %s originate\n",
888 ospf6_lsa_handler_name(handler));
889 if (CHECK_FLAG(handler->debug, OSPF6_LSA_DEBUG_EXAMIN))
890 vty_out(vty, "debug ospf6 lsa %s examine\n",
891 ospf6_lsa_handler_name(handler));
892 if (CHECK_FLAG(handler->debug, OSPF6_LSA_DEBUG_FLOOD))
893 vty_out(vty, "debug ospf6 lsa %s flooding\n",
894 ospf6_lsa_handler_name(handler));
895 }
896
897 return 0;
898 }