]> git.proxmox.com Git - mirror_frr.git/blob - ospf6d/ospf6_lsa.c
SVN revisions 916-920 from Zebra. ABR support is almost done.
[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
17 * along with GNU Zebra; see the file COPYING. If not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 */
21
22 #include <zebra.h>
23
24 /* Include other stuffs */
25 #include "log.h"
26 #include "linklist.h"
27 #include "command.h"
28 #include "memory.h"
29 #include "thread.h"
30
31 #include "ospf6_proto.h"
32 #include "ospf6_lsa.h"
33 #include "ospf6_lsdb.h"
34 #include "ospf6_message.h"
35
36 #include "ospf6_top.h"
37 #include "ospf6_area.h"
38 #include "ospf6_interface.h"
39 #include "ospf6_neighbor.h"
40
41 #include "ospf6_flood.h"
42 #include "ospf6d.h"
43
44 unsigned char conf_debug_ospf6_lsa = 0;
45
46 struct ospf6_lsa_handler *ospf6_lsa_handler[OSPF6_LSTYPE_SIZE];
47
48 char *ospf6_lstype_str[OSPF6_LSTYPE_SIZE] =
49 {"Unknown", "Router", "Network", "Inter-Prefix", "Inter-Router",
50 "AS-External", "Group-Membership", "Type-7", "Link", "Intra-Prefix"};
51
52 char *
53 ospf6_lstype_name (u_int16_t type)
54 {
55 static char buf[8];
56 int index = OSPF6_LSTYPE_INDEX (type);
57
58 if (ospf6_lsa_handler[index])
59 return ospf6_lsa_handler[index]->name;
60
61 snprintf (buf, sizeof (buf), "0x%04hx", ntohs (type));
62 return buf;
63 }
64
65 /* RFC2328: Section 13.2 */
66 int
67 ospf6_lsa_is_differ (struct ospf6_lsa *lsa1,
68 struct ospf6_lsa *lsa2)
69 {
70 int len;
71
72 assert (OSPF6_LSA_IS_SAME (lsa1, lsa2));
73
74 /* XXX, Options ??? */
75
76 ospf6_lsa_age_current (lsa1);
77 ospf6_lsa_age_current (lsa2);
78 if (ntohs (lsa1->header->age) == MAXAGE &&
79 ntohs (lsa2->header->age) != MAXAGE)
80 return 1;
81 if (ntohs (lsa1->header->age) != MAXAGE &&
82 ntohs (lsa2->header->age) == MAXAGE)
83 return 1;
84
85 /* compare body */
86 if (ntohs (lsa1->header->length) != ntohs (lsa2->header->length))
87 return 1;
88
89 len = ntohs (lsa1->header->length) - sizeof (struct ospf6_lsa_header);
90 return memcmp (lsa1->header + 1, lsa2->header + 1, len);
91 }
92
93 int
94 ospf6_lsa_is_changed (struct ospf6_lsa *lsa1,
95 struct ospf6_lsa *lsa2)
96 {
97 int length;
98
99 if (OSPF6_LSA_IS_MAXAGE (lsa1) ^ OSPF6_LSA_IS_MAXAGE (lsa2))
100 return 1;
101 if (ntohs (lsa1->header->length) != ntohs (lsa2->header->length))
102 return 1;
103
104 length = OSPF6_LSA_SIZE (lsa1->header) - sizeof (struct ospf6_lsa_header);
105 assert (length > 0);
106
107 return memcmp (OSPF6_LSA_HEADER_END (lsa1->header),
108 OSPF6_LSA_HEADER_END (lsa2->header), length);
109 }
110
111 /* ospf6 age functions */
112 /* calculate birth and set expire timer */
113 static void
114 ospf6_lsa_age_set (struct ospf6_lsa *lsa)
115 {
116 struct timeval now;
117
118 assert (lsa && lsa->header);
119
120 if (gettimeofday (&now, (struct timezone *)NULL) < 0)
121 zlog_warn ("LSA: gettimeofday failed, may fail LSA AGEs: %s",
122 strerror (errno));
123
124 lsa->birth.tv_sec = now.tv_sec - ntohs (lsa->header->age);
125 lsa->birth.tv_usec = now.tv_usec;
126 if (ntohs (lsa->header->age) != MAXAGE)
127 lsa->expire = thread_add_timer (master, ospf6_lsa_expire, lsa,
128 MAXAGE + lsa->birth.tv_sec - now.tv_sec);
129 else
130 lsa->expire = NULL;
131 return;
132 }
133
134 /* this function calculates current age from its birth,
135 then update age field of LSA header. return value is current age */
136 u_int16_t
137 ospf6_lsa_age_current (struct ospf6_lsa *lsa)
138 {
139 struct timeval now;
140 u_int32_t ulage;
141 u_int16_t age;
142
143 assert (lsa);
144 assert (lsa->header);
145
146 /* current time */
147 if (gettimeofday (&now, (struct timezone *)NULL) < 0)
148 zlog_warn ("LSA: gettimeofday failed, may fail LSA AGEs: %s",
149 strerror (errno));
150
151 /* calculate age */
152 ulage = now.tv_sec - lsa->birth.tv_sec;
153
154 /* if over MAXAGE, set to it */
155 age = (ulage > MAXAGE ? MAXAGE : ulage);
156
157 lsa->header->age = htons (age);
158 return age;
159 }
160
161 /* update age field of LSA header with adding InfTransDelay */
162 void
163 ospf6_lsa_age_update_to_send (struct ospf6_lsa *lsa, u_int32_t transdelay)
164 {
165 unsigned short age;
166
167 age = ospf6_lsa_age_current (lsa) + transdelay;
168 if (age > MAXAGE)
169 age = MAXAGE;
170 lsa->header->age = htons (age);
171 }
172
173 void
174 ospf6_lsa_premature_aging (struct ospf6_lsa *lsa)
175 {
176 /* log */
177 if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
178 zlog_info ("LSA: Premature aging: %s", lsa->name);
179
180 THREAD_OFF (lsa->expire);
181 THREAD_OFF (lsa->refresh);
182
183 memset (&lsa->birth, 0, sizeof (struct timeval));
184 thread_execute (master, ospf6_lsa_expire, lsa, 0);
185 }
186
187 /* check which is more recent. if a is more recent, return -1;
188 if the same, return 0; otherwise(b is more recent), return 1 */
189 int
190 ospf6_lsa_compare (struct ospf6_lsa *a, struct ospf6_lsa *b)
191 {
192 signed long seqnuma, seqnumb;
193 u_int16_t cksuma, cksumb;
194 u_int16_t agea, ageb;
195
196 assert (a && a->header);
197 assert (b && b->header);
198 assert (OSPF6_LSA_IS_SAME (a, b));
199
200 seqnuma = ((signed long) ntohl (a->header->seqnum))
201 - (signed long) INITIAL_SEQUENCE_NUMBER;
202 seqnumb = ((signed long) ntohl (b->header->seqnum))
203 - (signed long) INITIAL_SEQUENCE_NUMBER;
204
205 /* compare by sequence number */
206 /* XXX, LS sequence number wrapping */
207 if (seqnuma > seqnumb)
208 return -1;
209 else if (seqnuma < seqnumb)
210 return 1;
211
212 /* Checksum */
213 cksuma = ntohs (a->header->checksum);
214 cksumb = ntohs (b->header->checksum);
215 if (cksuma > cksumb)
216 return -1;
217 if (cksuma < cksumb)
218 return 0;
219
220 /* Update Age */
221 agea = ospf6_lsa_age_current (a);
222 ageb = ospf6_lsa_age_current (b);
223
224 /* MaxAge check */
225 if (agea == MAXAGE && ageb != MAXAGE)
226 return -1;
227 else if (agea != MAXAGE && ageb == MAXAGE)
228 return 1;
229
230 /* Age check */
231 if (agea > ageb && agea - ageb >= MAX_AGE_DIFF)
232 return 1;
233 else if (agea < ageb && ageb - agea >= MAX_AGE_DIFF)
234 return -1;
235
236 /* neither recent */
237 return 0;
238 }
239
240 char *
241 ospf6_lsa_printbuf (struct ospf6_lsa *lsa, char *buf, int size)
242 {
243 char id[16], adv_router[16];
244 inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id));
245 inet_ntop (AF_INET, &lsa->header->adv_router, adv_router,
246 sizeof (adv_router));
247 snprintf (buf, size, "[%s Id:%s Adv:%s]",
248 OSPF6_LSTYPE_NAME (lsa->header->type), id, adv_router);
249 return buf;
250 }
251
252 void
253 ospf6_lsa_header_print_raw (struct ospf6_lsa_header *header)
254 {
255 char id[16], adv_router[16];
256 inet_ntop (AF_INET, &header->id, id, sizeof (id));
257 inet_ntop (AF_INET, &header->adv_router, adv_router,
258 sizeof (adv_router));
259 zlog_info (" [%s Id:%s Adv:%s]",
260 OSPF6_LSTYPE_NAME (header->type), id, adv_router);
261 zlog_info (" Age: %4hu SeqNum: %#08lx Cksum: %04hx Len: %d",
262 ntohs (header->age), (u_long) ntohl (header->seqnum),
263 ntohs (header->checksum), ntohs (header->length));
264 }
265
266 void
267 ospf6_lsa_header_print (struct ospf6_lsa *lsa)
268 {
269 ospf6_lsa_age_current (lsa);
270 ospf6_lsa_header_print_raw (lsa->header);
271 }
272
273 void
274 ospf6_lsa_show_summary_header (struct vty *vty)
275 {
276 vty_out (vty, "%-12s %-15s %-15s %4s %8s %4s %4s %-8s%s",
277 "Type", "LSId", "AdvRouter", "Age", "SeqNum",
278 "Cksm", "Len", "Duration", VNL);
279 }
280
281 void
282 ospf6_lsa_show_summary (struct vty *vty, struct ospf6_lsa *lsa)
283 {
284 char adv_router[16], id[16];
285 struct timeval now, res;
286 char duration[16];
287
288 assert (lsa);
289 assert (lsa->header);
290
291 inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id));
292 inet_ntop (AF_INET, &lsa->header->adv_router, adv_router,
293 sizeof (adv_router));
294
295 gettimeofday (&now, NULL);
296 timersub (&now, &lsa->installed, &res);
297 timerstring (&res, duration, sizeof (duration));
298
299 vty_out (vty, "%-12s %-15s %-15s %4hu %8lx %04hx %4hu %8s%s",
300 OSPF6_LSTYPE_NAME (lsa->header->type),
301 id, adv_router, ospf6_lsa_age_current (lsa),
302 (u_long) ntohl (lsa->header->seqnum),
303 ntohs (lsa->header->checksum), ntohs (lsa->header->length),
304 duration, VNL);
305 }
306
307 void
308 ospf6_lsa_show_dump (struct vty *vty, struct ospf6_lsa *lsa)
309 {
310 u_char *start, *end, *current;
311 char byte[4];
312
313 start = (char *) lsa->header;
314 end = (char *) lsa->header + ntohs (lsa->header->length);
315
316 vty_out (vty, "%s", VNL);
317 vty_out (vty, "%s:%s", lsa->name, VNL);
318
319 for (current = start; current < end; current ++)
320 {
321 if ((current - start) % 16 == 0)
322 vty_out (vty, "%s ", VNL);
323 else if ((current - start) % 4 == 0)
324 vty_out (vty, " ");
325
326 snprintf (byte, sizeof (byte), "%02x", *current);
327 vty_out (vty, "%s", byte);
328 }
329
330 vty_out (vty, "%s%s", VNL, VNL);
331 return;
332 }
333
334 void
335 ospf6_lsa_show_internal (struct vty *vty, struct ospf6_lsa *lsa)
336 {
337 char adv_router[64], id[64];
338
339 assert (lsa && lsa->header);
340
341 inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id));
342 inet_ntop (AF_INET, &lsa->header->adv_router,
343 adv_router, sizeof (adv_router));
344
345 vty_out (vty, "%s", VNL);
346 vty_out (vty, "Age: %4hu Type: %s%s", ospf6_lsa_age_current (lsa),
347 OSPF6_LSTYPE_NAME (lsa->header->type), VNL);
348 vty_out (vty, "Link State ID: %s%s", id, VNL);
349 vty_out (vty, "Advertising Router: %s%s", adv_router, VNL);
350 vty_out (vty, "LS Sequence Number: %#010lx%s",
351 (u_long) ntohl (lsa->header->seqnum), VNL);
352 vty_out (vty, "CheckSum: %#06hx Length: %hu%s",
353 ntohs (lsa->header->checksum),
354 ntohs (lsa->header->length), VNL);
355 vty_out (vty, " Prev: %p This: %p Next: %p%s",
356 lsa->prev, lsa, lsa->next, VNL);
357 vty_out (vty, "%s", VNL);
358 return;
359 }
360
361 void
362 ospf6_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
363 {
364 char adv_router[64], id[64];
365 int index;
366
367 assert (lsa && lsa->header);
368
369 inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id));
370 inet_ntop (AF_INET, &lsa->header->adv_router,
371 adv_router, sizeof (adv_router));
372
373 vty_out (vty, "Age: %4hu Type: %s%s", ospf6_lsa_age_current (lsa),
374 OSPF6_LSTYPE_NAME (lsa->header->type), VNL);
375 vty_out (vty, "Link State ID: %s%s", id, VNL);
376 vty_out (vty, "Advertising Router: %s%s", adv_router, VNL);
377 vty_out (vty, "LS Sequence Number: %#010lx%s",
378 (u_long) ntohl (lsa->header->seqnum), VNL);
379 vty_out (vty, "CheckSum: %#06hx Length: %hu%s",
380 ntohs (lsa->header->checksum),
381 ntohs (lsa->header->length), VNL);
382
383 index = OSPF6_LSTYPE_INDEX (lsa->header->type);
384 if (ospf6_lsa_handler[index]->show)
385 (*ospf6_lsa_handler[index]->show) (vty, lsa);
386 else
387 {
388 ospf6_lsa_show_dump (vty, lsa);
389 vty_out (vty, "%sUnknown LSA type ...%s", VNL, VNL);
390 }
391
392 vty_out (vty, "%s", VNL);
393 }
394
395 /* OSPFv3 LSA creation/deletion function */
396 struct ospf6_lsa *
397 ospf6_lsa_create (struct ospf6_lsa_header *header)
398 {
399 struct ospf6_lsa *lsa = NULL;
400 struct ospf6_lsa_header *new_header = NULL;
401 u_int16_t lsa_size = 0;
402
403 /* size of the entire LSA */
404 lsa_size = ntohs (header->length); /* XXX vulnerable */
405
406 /* allocate memory for this LSA */
407 new_header = (struct ospf6_lsa_header *)
408 XMALLOC (MTYPE_OSPF6_LSA, lsa_size);
409
410 /* copy LSA from original header */
411 memcpy (new_header, header, lsa_size);
412
413 /* LSA information structure */
414 /* allocate memory */
415 lsa = (struct ospf6_lsa *)
416 XMALLOC (MTYPE_OSPF6_LSA, sizeof (struct ospf6_lsa));
417 memset (lsa, 0, sizeof (struct ospf6_lsa));
418
419 lsa->header = (struct ospf6_lsa_header *) new_header;
420
421 /* dump string */
422 ospf6_lsa_printbuf (lsa, lsa->name, sizeof (lsa->name));
423
424 /* calculate birth, expire and refresh of this lsa */
425 ospf6_lsa_age_set (lsa);
426
427 if (IS_OSPF6_DEBUG_LSA (MEMORY))
428 zlog_info ("Create LSA Memory: %s (%p/%p)",
429 lsa->name, lsa, lsa->header);
430
431 return lsa;
432 }
433
434 struct ospf6_lsa *
435 ospf6_lsa_create_headeronly (struct ospf6_lsa_header *header)
436 {
437 struct ospf6_lsa *lsa = NULL;
438 struct ospf6_lsa_header *new_header = NULL;
439
440 /* allocate memory for this LSA */
441 new_header = (struct ospf6_lsa_header *)
442 XMALLOC (MTYPE_OSPF6_LSA, sizeof (struct ospf6_lsa_header));
443
444 /* copy LSA from original header */
445 memcpy (new_header, header, sizeof (struct ospf6_lsa_header));
446
447 /* LSA information structure */
448 /* allocate memory */
449 lsa = (struct ospf6_lsa *)
450 XMALLOC (MTYPE_OSPF6_LSA, sizeof (struct ospf6_lsa));
451 memset (lsa, 0, sizeof (struct ospf6_lsa));
452
453 lsa->header = (struct ospf6_lsa_header *) new_header;
454 SET_FLAG (lsa->flag, OSPF6_LSA_HEADERONLY);
455
456 /* dump string */
457 ospf6_lsa_printbuf (lsa, lsa->name, sizeof (lsa->name));
458
459 /* calculate birth, expire and refresh of this lsa */
460 ospf6_lsa_age_set (lsa);
461
462 if (IS_OSPF6_DEBUG_LSA (MEMORY))
463 zlog_info ("Create LSA (Header-only) Memory: %s (%p/%p)",
464 lsa->name, lsa, lsa->header);
465
466 return lsa;
467 }
468
469 void
470 ospf6_lsa_delete (struct ospf6_lsa *lsa)
471 {
472 assert (lsa->lock == 0);
473
474 /* cancel threads */
475 THREAD_OFF (lsa->expire);
476 THREAD_OFF (lsa->refresh);
477
478 if (IS_OSPF6_DEBUG_LSA (MEMORY))
479 zlog_info ("Delete LSA %s Memory: %s (%p/%p)",
480 (CHECK_FLAG (lsa->flag, OSPF6_LSA_HEADERONLY) ?
481 "(Header-only) " : ""), lsa->name, lsa, lsa->header);
482
483 /* do free */
484 XFREE (MTYPE_OSPF6_LSA, lsa->header);
485 XFREE (MTYPE_OSPF6_LSA, lsa);
486 }
487
488 struct ospf6_lsa *
489 ospf6_lsa_copy (struct ospf6_lsa *lsa)
490 {
491 struct ospf6_lsa *copy = NULL;
492
493 if (IS_OSPF6_DEBUG_LSA (MEMORY))
494 zlog_info ("Create LSA Copy from %s", lsa->name);
495
496 ospf6_lsa_age_current (lsa);
497 if (CHECK_FLAG (lsa->flag, OSPF6_LSA_HEADERONLY))
498 copy = ospf6_lsa_create_headeronly (lsa->header);
499 else
500 copy = ospf6_lsa_create (lsa->header);
501 assert (copy->lock == 0);
502
503 copy->installed = lsa->installed;
504 copy->originated = lsa->originated;
505 copy->lsdb = lsa->lsdb;
506
507 return copy;
508 }
509
510 /* increment reference counter of struct ospf6_lsa */
511 void
512 ospf6_lsa_lock (struct ospf6_lsa *lsa)
513 {
514 lsa->lock++;
515 return;
516 }
517
518 /* decrement reference counter of struct ospf6_lsa */
519 void
520 ospf6_lsa_unlock (struct ospf6_lsa *lsa)
521 {
522 /* decrement reference counter */
523 assert (lsa->lock > 0);
524 lsa->lock--;
525
526 if (lsa->lock != 0)
527 return;
528
529 ospf6_lsa_delete (lsa);
530 }
531
532 \f
533 /* ospf6 lsa expiry */
534 int
535 ospf6_lsa_expire (struct thread *thread)
536 {
537 struct ospf6_lsa *lsa;
538
539 lsa = (struct ospf6_lsa *) THREAD_ARG (thread);
540
541 assert (lsa && lsa->header);
542 assert (OSPF6_LSA_IS_MAXAGE (lsa));
543 assert (! lsa->refresh);
544
545 lsa->expire = (struct thread *) NULL;
546
547 if (IS_OSPF6_DEBUG_LSA (TIMER))
548 {
549 zlog_info ("LSA Expire:");
550 ospf6_lsa_header_print (lsa);
551 }
552
553 if (CHECK_FLAG (lsa->flag, OSPF6_LSA_HEADERONLY))
554 return 0; /* dbexchange will do something ... */
555
556 /* reflood lsa */
557 ospf6_flood (NULL, lsa);
558
559 /* reinstall lsa */
560 if (IS_OSPF6_DEBUG_LSA (DATABASE))
561 zlog_info ("Reinstall MaxAge %s", lsa->name);
562 ospf6_lsdb_add (lsa, lsa->lsdb);
563
564 /* schedule maxage remover */
565 ospf6_maxage_remove (ospf6);
566
567 return 0;
568 }
569
570 int
571 ospf6_lsa_refresh (struct thread *thread)
572 {
573 struct ospf6_lsa *old, *self, *new;
574 struct ospf6_lsdb *lsdb_self;
575
576 assert (thread);
577 old = (struct ospf6_lsa *) THREAD_ARG (thread);
578 assert (old && old->header);
579
580 old->refresh = (struct thread *) NULL;
581
582 lsdb_self = ospf6_get_scoped_lsdb_self (old);
583 self = ospf6_lsdb_lookup (old->header->type, old->header->id,
584 old->header->adv_router, lsdb_self);
585 if (self == NULL)
586 {
587 ospf6_lsa_premature_aging (old);
588 return 0;
589 }
590
591 /* Reset age, increment LS sequence number. */
592 self->header->age = htons (0);
593 self->header->seqnum =
594 ospf6_new_ls_seqnum (self->header->type, self->header->id,
595 self->header->adv_router, old->lsdb);
596 ospf6_lsa_checksum (self->header);
597
598 new = ospf6_lsa_create (self->header);
599 new->lsdb = old->lsdb;
600 new->refresh = thread_add_timer (master, ospf6_lsa_refresh, new,
601 LS_REFRESH_TIME);
602
603 /* store it in the LSDB for self-originated LSAs */
604 ospf6_lsdb_add (ospf6_lsa_copy (new), lsdb_self);
605
606 if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
607 {
608 zlog_info ("LSA Refresh:");
609 ospf6_lsa_header_print (new);
610 }
611
612 ospf6_flood_clear (old);
613 ospf6_flood (NULL, new);
614 ospf6_install_lsa (new);
615
616 return 0;
617 }
618
619 \f
620
621 /* enhanced Fletcher checksum algorithm, RFC1008 7.2 */
622 #define MODX 4102
623 #define LSA_CHECKSUM_OFFSET 15
624
625 unsigned short
626 ospf6_lsa_checksum (struct ospf6_lsa_header *lsa_header)
627 {
628 u_char *sp, *ep, *p, *q;
629 int c0 = 0, c1 = 0;
630 int x, y;
631 u_int16_t length;
632
633 lsa_header->checksum = 0;
634 length = ntohs (lsa_header->length) - 2;
635 sp = (char *) &lsa_header->type;
636
637 for (ep = sp + length; sp < ep; sp = q)
638 {
639 q = sp + MODX;
640 if (q > ep)
641 q = ep;
642 for (p = sp; p < q; p++)
643 {
644 c0 += *p;
645 c1 += c0;
646 }
647 c0 %= 255;
648 c1 %= 255;
649 }
650
651 /* r = (c1 << 8) + c0; */
652 x = ((length - LSA_CHECKSUM_OFFSET) * c0 - c1) % 255;
653 if (x <= 0)
654 x += 255;
655 y = 510 - c0 - x;
656 if (y > 255)
657 y -= 255;
658
659 lsa_header->checksum = htons ((x << 8) + y);
660
661 return (lsa_header->checksum);
662 }
663
664 int
665 ospf6_unknown_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
666 {
667 u_char *start, *end, *current;
668 char byte[4];
669
670 start = (char *) lsa->header + sizeof (struct ospf6_lsa_header);
671 end = (char *) lsa->header + ntohs (lsa->header->length);
672
673 vty_out (vty, " Unknown contents:%s", VNL);
674 for (current = start; current < end; current ++)
675 {
676 if ((current - start) % 16 == 0)
677 vty_out (vty, "%s ", VNL);
678 else if ((current - start) % 4 == 0)
679 vty_out (vty, " ");
680
681 snprintf (byte, sizeof (byte), "%02x", *current);
682 vty_out (vty, "%s", byte);
683 }
684
685 vty_out (vty, "%s%s", VNL, VNL);
686 return 0;
687 }
688
689 void
690 ospf6_install_lsa_handler (struct ospf6_lsa_handler *handler)
691 {
692 /* might need to adjust dynamic array length ... */
693 int index = OSPF6_LSTYPE_INDEX (htons (handler->type));
694 ospf6_lsa_handler[index] = handler;
695 }
696
697 struct ospf6_lsa_handler unknown_handler =
698 {
699 OSPF6_LSTYPE_UNKNOWN,
700 "Unknown",
701 ospf6_unknown_lsa_show
702 };
703
704 void
705 ospf6_lsa_init ()
706 {
707 memset (ospf6_lsa_handler, 0, sizeof (ospf6_lsa_handler));
708 ospf6_install_lsa_handler (&unknown_handler);
709 }
710
711 \f
712
713 DEFUN (debug_ospf6_lsa_sendrecv,
714 debug_ospf6_lsa_sendrecv_cmd,
715 "debug ospf6 lsa (send|recv|originate|timer|database|memory|all)",
716 DEBUG_STR
717 OSPF6_STR
718 "Debug Link State Advertisements (LSAs)\n"
719 "Debug Sending LSAs\n"
720 "Debug Receiving LSAs\n"
721 "Debug Originating LSAs\n"
722 "Debug Timer Event of LSAs\n"
723 "Debug LSA Database\n"
724 "Debug Memory of LSAs\n"
725 "Debug LSAs all\n"
726 )
727 {
728 unsigned char level = 0;
729
730 if (argc)
731 {
732 if (! strncmp (argv[0], "s", 1))
733 level = OSPF6_DEBUG_LSA_SEND;
734 else if (! strncmp (argv[0], "r", 1))
735 level = OSPF6_DEBUG_LSA_RECV;
736 else if (! strncmp (argv[0], "o", 1))
737 level = OSPF6_DEBUG_LSA_ORIGINATE;
738 else if (! strncmp (argv[0], "t", 1))
739 level = OSPF6_DEBUG_LSA_TIMER;
740 else if (! strncmp (argv[0], "d", 1))
741 level = OSPF6_DEBUG_LSA_DATABASE;
742 else if (! strncmp (argv[0], "m", 1))
743 level = OSPF6_DEBUG_LSA_MEMORY;
744 else if (! strncmp (argv[0], "a", 1))
745 {
746 level = OSPF6_DEBUG_LSA_SEND | OSPF6_DEBUG_LSA_RECV |
747 OSPF6_DEBUG_LSA_ORIGINATE | OSPF6_DEBUG_LSA_TIMER |
748 OSPF6_DEBUG_LSA_DATABASE | OSPF6_DEBUG_LSA_MEMORY;
749 }
750 }
751 else
752 {
753 level = OSPF6_DEBUG_LSA_SEND | OSPF6_DEBUG_LSA_RECV |
754 OSPF6_DEBUG_LSA_ORIGINATE | OSPF6_DEBUG_LSA_TIMER;
755 }
756
757 OSPF6_DEBUG_LSA_ON (level);
758 return CMD_SUCCESS;
759 }
760
761 ALIAS (debug_ospf6_lsa_sendrecv,
762 debug_ospf6_lsa_cmd,
763 "debug ospf6 lsa",
764 NO_STR
765 DEBUG_STR
766 OSPF6_STR
767 "Debug Link State Advertisements (LSAs)\n"
768 );
769
770 DEFUN (no_debug_ospf6_lsa_sendrecv,
771 no_debug_ospf6_lsa_sendrecv_cmd,
772 "no debug ospf6 lsa (send|recv|originate|timer|database|memory|all)",
773 NO_STR
774 DEBUG_STR
775 OSPF6_STR
776 "Debug Link State Advertisements (LSAs)\n"
777 "Debug Sending LSAs\n"
778 "Debug Receiving LSAs\n"
779 "Debug Originating LSAs\n"
780 "Debug Timer Event of LSAs\n"
781 "Debug LSA Database\n"
782 "Debug Memory of LSAs\n"
783 "Debug LSAs all\n"
784 )
785 {
786 unsigned char level = 0;
787
788 if (argc)
789 {
790 if (! strncmp (argv[0], "s", 1))
791 level = OSPF6_DEBUG_LSA_SEND;
792 else if (! strncmp (argv[0], "r", 1))
793 level = OSPF6_DEBUG_LSA_RECV;
794 else if (! strncmp (argv[0], "o", 1))
795 level = OSPF6_DEBUG_LSA_ORIGINATE;
796 else if (! strncmp (argv[0], "t", 1))
797 level = OSPF6_DEBUG_LSA_TIMER;
798 else if (! strncmp (argv[0], "d", 1))
799 level = OSPF6_DEBUG_LSA_DATABASE;
800 else if (! strncmp (argv[0], "m", 1))
801 level = OSPF6_DEBUG_LSA_MEMORY;
802 else if (! strncmp (argv[0], "a", 1))
803 {
804 level = OSPF6_DEBUG_LSA_SEND | OSPF6_DEBUG_LSA_RECV |
805 OSPF6_DEBUG_LSA_ORIGINATE | OSPF6_DEBUG_LSA_TIMER |
806 OSPF6_DEBUG_LSA_DATABASE | OSPF6_DEBUG_LSA_MEMORY;
807 }
808 }
809 else
810 {
811 level = OSPF6_DEBUG_LSA_SEND | OSPF6_DEBUG_LSA_RECV |
812 OSPF6_DEBUG_LSA_ORIGINATE | OSPF6_DEBUG_LSA_TIMER;
813 }
814
815 OSPF6_DEBUG_LSA_OFF (level);
816 return CMD_SUCCESS;
817 }
818
819 ALIAS (no_debug_ospf6_lsa_sendrecv,
820 no_debug_ospf6_lsa_cmd,
821 "no debug ospf6 lsa",
822 NO_STR
823 DEBUG_STR
824 OSPF6_STR
825 "Debug Link State Advertisements (LSAs)\n"
826 );
827
828 int
829 config_write_ospf6_debug_lsa (struct vty *vty)
830 {
831 if (conf_debug_ospf6_lsa == OSPF6_DEBUG_LSA_ALL)
832 vty_out (vty, "debug ospf6 lsa all%s", VNL);
833 else
834 {
835 if (conf_debug_ospf6_lsa == OSPF6_DEBUG_LSA_DEFAULT)
836 vty_out (vty, "debug ospf6 lsa%s", VNL);
837 else
838 {
839 if (IS_OSPF6_DEBUG_LSA (SEND))
840 vty_out (vty, "debug ospf6 lsa send%s", VNL);
841 if (IS_OSPF6_DEBUG_LSA (RECV))
842 vty_out (vty, "debug ospf6 lsa recv%s", VNL);
843 if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
844 vty_out (vty, "debug ospf6 lsa originate%s", VNL);
845 if (IS_OSPF6_DEBUG_LSA (TIMER))
846 vty_out (vty, "debug ospf6 lsa timer%s", VNL);
847 }
848
849 if (IS_OSPF6_DEBUG_LSA (DATABASE))
850 vty_out (vty, "debug ospf6 lsa database%s", VNL);
851 if (IS_OSPF6_DEBUG_LSA (MEMORY))
852 vty_out (vty, "debug ospf6 lsa memory%s", VNL);
853 }
854
855 return 0;
856 }
857
858 void
859 install_element_ospf6_debug_lsa ()
860 {
861 install_element (ENABLE_NODE, &debug_ospf6_lsa_cmd);
862 install_element (ENABLE_NODE, &debug_ospf6_lsa_sendrecv_cmd);
863 install_element (ENABLE_NODE, &no_debug_ospf6_lsa_cmd);
864 install_element (ENABLE_NODE, &no_debug_ospf6_lsa_sendrecv_cmd);
865 install_element (CONFIG_NODE, &debug_ospf6_lsa_cmd);
866 install_element (CONFIG_NODE, &debug_ospf6_lsa_sendrecv_cmd);
867 install_element (CONFIG_NODE, &no_debug_ospf6_lsa_cmd);
868 install_element (CONFIG_NODE, &no_debug_ospf6_lsa_sendrecv_cmd);
869 }
870
871