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