Annotation of embedaddon/quagga/ospf6d/ospf6_lsa.c, revision 1.1.1.2
1.1 misho 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 "vector.h"
28: #include "vty.h"
29: #include "command.h"
30: #include "memory.h"
31: #include "thread.h"
1.1.1.2 ! misho 32: #include "checksum.h"
1.1 misho 33:
34: #include "ospf6_proto.h"
35: #include "ospf6_lsa.h"
36: #include "ospf6_lsdb.h"
37: #include "ospf6_message.h"
38:
39: #include "ospf6_top.h"
40: #include "ospf6_area.h"
41: #include "ospf6_interface.h"
42: #include "ospf6_neighbor.h"
43:
44: #include "ospf6_flood.h"
45: #include "ospf6d.h"
46:
47: vector ospf6_lsa_handler_vector;
48:
49: static int
50: ospf6_unknown_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
51: {
52: u_char *start, *end, *current;
53: char byte[4];
54:
55: start = (u_char *) lsa->header + sizeof (struct ospf6_lsa_header);
56: end = (u_char *) lsa->header + ntohs (lsa->header->length);
57:
58: vty_out (vty, " Unknown contents:%s", VNL);
59: for (current = start; current < end; current ++)
60: {
61: if ((current - start) % 16 == 0)
62: vty_out (vty, "%s ", VNL);
63: else if ((current - start) % 4 == 0)
64: vty_out (vty, " ");
65:
66: snprintf (byte, sizeof (byte), "%02x", *current);
67: vty_out (vty, "%s", byte);
68: }
69:
70: vty_out (vty, "%s%s", VNL, VNL);
71: return 0;
72: }
73:
74: struct ospf6_lsa_handler unknown_handler =
75: {
76: OSPF6_LSTYPE_UNKNOWN,
77: "Unknown",
78: ospf6_unknown_lsa_show,
79: OSPF6_LSA_DEBUG,
80: };
81:
82: void
83: ospf6_install_lsa_handler (struct ospf6_lsa_handler *handler)
84: {
85: /* type in handler is host byte order */
86: int index = handler->type & OSPF6_LSTYPE_FCODE_MASK;
87: vector_set_index (ospf6_lsa_handler_vector, index, handler);
88: }
89:
90: struct ospf6_lsa_handler *
91: ospf6_get_lsa_handler (u_int16_t type)
92: {
93: struct ospf6_lsa_handler *handler = NULL;
94: unsigned int index = ntohs (type) & OSPF6_LSTYPE_FCODE_MASK;
95:
96: if (index >= vector_active (ospf6_lsa_handler_vector))
97: handler = &unknown_handler;
98: else
99: handler = vector_slot (ospf6_lsa_handler_vector, index);
100:
101: if (handler == NULL)
102: handler = &unknown_handler;
103:
104: return handler;
105: }
106:
107: const char *
108: ospf6_lstype_name (u_int16_t type)
109: {
110: static char buf[8];
111: struct ospf6_lsa_handler *handler;
112:
113: handler = ospf6_get_lsa_handler (type);
114: if (handler && handler != &unknown_handler)
115: return handler->name;
116:
117: snprintf (buf, sizeof (buf), "0x%04hx", ntohs (type));
118: return buf;
119: }
120:
121: u_char
122: ospf6_lstype_debug (u_int16_t type)
123: {
124: struct ospf6_lsa_handler *handler;
125: handler = ospf6_get_lsa_handler (type);
126: return handler->debug;
127: }
128:
129: /* RFC2328: Section 13.2 */
130: int
131: ospf6_lsa_is_differ (struct ospf6_lsa *lsa1,
132: struct ospf6_lsa *lsa2)
133: {
134: int len;
135:
136: assert (OSPF6_LSA_IS_SAME (lsa1, lsa2));
137:
138: /* XXX, Options ??? */
139:
140: ospf6_lsa_age_current (lsa1);
141: ospf6_lsa_age_current (lsa2);
142: if (ntohs (lsa1->header->age) == MAXAGE &&
143: ntohs (lsa2->header->age) != MAXAGE)
144: return 1;
145: if (ntohs (lsa1->header->age) != MAXAGE &&
146: ntohs (lsa2->header->age) == MAXAGE)
147: return 1;
148:
149: /* compare body */
150: if (ntohs (lsa1->header->length) != ntohs (lsa2->header->length))
151: return 1;
152:
153: len = ntohs (lsa1->header->length) - sizeof (struct ospf6_lsa_header);
154: return memcmp (lsa1->header + 1, lsa2->header + 1, len);
155: }
156:
157: int
158: ospf6_lsa_is_changed (struct ospf6_lsa *lsa1,
159: struct ospf6_lsa *lsa2)
160: {
161: int length;
162:
163: if (OSPF6_LSA_IS_MAXAGE (lsa1) ^ OSPF6_LSA_IS_MAXAGE (lsa2))
164: return 1;
165: if (ntohs (lsa1->header->length) != ntohs (lsa2->header->length))
166: return 1;
167: /* Going beyond LSA headers to compare the payload only makes sense, when both LSAs aren't header-only. */
168: if (CHECK_FLAG (lsa1->flag, OSPF6_LSA_HEADERONLY) != CHECK_FLAG (lsa2->flag, OSPF6_LSA_HEADERONLY))
169: {
170: zlog_warn ("%s: only one of two (%s, %s) LSAs compared is header-only", __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 become a warning. */
178: if (length <= 0)
179: return 0;
180:
181: return memcmp (OSPF6_LSA_HEADER_END (lsa1->header),
182: OSPF6_LSA_HEADER_END (lsa2->header), length);
183: }
184:
185: /* ospf6 age functions */
186: /* calculate birth */
187: static void
188: ospf6_lsa_age_set (struct ospf6_lsa *lsa)
189: {
190: struct timeval now;
191:
192: assert (lsa && lsa->header);
193:
194: if (quagga_gettime (QUAGGA_CLK_MONOTONIC, &now) < 0)
195: zlog_warn ("LSA: quagga_gettime failed, may fail LSA AGEs: %s",
196: safe_strerror (errno));
197:
198: lsa->birth.tv_sec = now.tv_sec - ntohs (lsa->header->age);
199: lsa->birth.tv_usec = now.tv_usec;
200:
201: return;
202: }
203:
204: /* this function calculates current age from its birth,
205: then update age field of LSA header. return value is current age */
206: u_int16_t
207: ospf6_lsa_age_current (struct ospf6_lsa *lsa)
208: {
209: struct timeval now;
210: u_int32_t ulage;
211: u_int16_t age;
212:
213: assert (lsa);
214: assert (lsa->header);
215:
216: /* current time */
217: if (quagga_gettime (QUAGGA_CLK_MONOTONIC, &now) < 0)
218: zlog_warn ("LSA: quagga_gettime failed, may fail LSA AGEs: %s",
219: safe_strerror (errno));
220:
221: if (ntohs (lsa->header->age) >= MAXAGE)
222: {
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 (MAXAGE);
227: return 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 > MAXAGE ? 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
241: ospf6_lsa_age_update_to_send (struct ospf6_lsa *lsa, u_int32_t transdelay)
242: {
243: unsigned short age;
244:
245: age = ospf6_lsa_age_current (lsa) + transdelay;
246: if (age > MAXAGE)
247: age = MAXAGE;
248: lsa->header->age = htons (age);
249: }
250:
251: void
252: ospf6_lsa_premature_aging (struct ospf6_lsa *lsa)
253: {
254: /* log */
255: if (IS_OSPF6_DEBUG_LSA_TYPE (lsa->header->type))
256: zlog_debug ("LSA: Premature aging: %s", lsa->name);
257:
258: THREAD_OFF (lsa->expire);
259: THREAD_OFF (lsa->refresh);
260:
261: lsa->header->age = htons (MAXAGE);
262: thread_execute (master, ospf6_lsa_expire, lsa, 0);
263: }
264:
265: /* check which is more recent. if a is more recent, return -1;
266: if the same, return 0; otherwise(b is more recent), return 1 */
267: int
268: ospf6_lsa_compare (struct ospf6_lsa *a, struct ospf6_lsa *b)
269: {
270: int seqnuma, seqnumb;
271: u_int16_t cksuma, cksumb;
272: u_int16_t agea, ageb;
273:
274: assert (a && a->header);
275: assert (b && b->header);
276: assert (OSPF6_LSA_IS_SAME (a, b));
277:
278: seqnuma = (int) ntohl (a->header->seqnum);
279: seqnumb = (int) ntohl (b->header->seqnum);
280:
281: /* compare by sequence number */
282: if (seqnuma > seqnumb)
283: return -1;
284: if (seqnuma < seqnumb)
285: return 1;
286:
287: /* Checksum */
288: cksuma = ntohs (a->header->checksum);
289: cksumb = ntohs (b->header->checksum);
290: if (cksuma > cksumb)
291: return -1;
292: if (cksuma < cksumb)
293: return 0;
294:
295: /* Update Age */
296: agea = ospf6_lsa_age_current (a);
297: ageb = ospf6_lsa_age_current (b);
298:
299: /* MaxAge check */
300: if (agea == MAXAGE && ageb != MAXAGE)
301: return -1;
302: else if (agea != MAXAGE && ageb == MAXAGE)
303: return 1;
304:
305: /* Age check */
306: if (agea > ageb && agea - ageb >= MAX_AGE_DIFF)
307: return 1;
308: else if (agea < ageb && ageb - agea >= MAX_AGE_DIFF)
309: return -1;
310:
311: /* neither recent */
312: return 0;
313: }
314:
315: char *
316: ospf6_lsa_printbuf (struct ospf6_lsa *lsa, char *buf, int size)
317: {
318: char id[16], adv_router[16];
319: inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id));
320: inet_ntop (AF_INET, &lsa->header->adv_router, adv_router,
321: sizeof (adv_router));
322: snprintf (buf, size, "[%s Id:%s Adv:%s]",
323: ospf6_lstype_name (lsa->header->type), id, adv_router);
324: return buf;
325: }
326:
327: void
328: ospf6_lsa_header_print_raw (struct ospf6_lsa_header *header)
329: {
330: char id[16], adv_router[16];
331: inet_ntop (AF_INET, &header->id, id, sizeof (id));
332: inet_ntop (AF_INET, &header->adv_router, adv_router,
333: sizeof (adv_router));
334: zlog_debug (" [%s Id:%s Adv:%s]",
335: ospf6_lstype_name (header->type), id, adv_router);
336: zlog_debug (" Age: %4hu SeqNum: %#08lx Cksum: %04hx Len: %d",
337: ntohs (header->age), (u_long) ntohl (header->seqnum),
338: ntohs (header->checksum), ntohs (header->length));
339: }
340:
341: void
342: ospf6_lsa_header_print (struct ospf6_lsa *lsa)
343: {
344: ospf6_lsa_age_current (lsa);
345: ospf6_lsa_header_print_raw (lsa->header);
346: }
347:
348: void
349: ospf6_lsa_show_summary_header (struct vty *vty)
350: {
351: vty_out (vty, "%-12s %-15s %-15s %4s %8s %4s %4s %-8s%s",
352: "Type", "LSId", "AdvRouter", "Age", "SeqNum",
353: "Cksm", "Len", "Duration", VNL);
354: }
355:
356: void
357: ospf6_lsa_show_summary (struct vty *vty, struct ospf6_lsa *lsa)
358: {
359: char adv_router[16], id[16];
360: struct timeval now, res;
361: char duration[16];
362:
363: assert (lsa);
364: assert (lsa->header);
365:
366: inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id));
367: inet_ntop (AF_INET, &lsa->header->adv_router, adv_router,
368: sizeof (adv_router));
369:
370: quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
371: timersub (&now, &lsa->installed, &res);
372: timerstring (&res, duration, sizeof (duration));
373:
374: vty_out (vty, "%-12s %-15s %-15s %4hu %8lx %04hx %4hu %8s%s",
375: ospf6_lstype_name (lsa->header->type),
376: id, adv_router, ospf6_lsa_age_current (lsa),
377: (u_long) ntohl (lsa->header->seqnum),
378: ntohs (lsa->header->checksum), ntohs (lsa->header->length),
379: duration, VNL);
380: }
381:
382: void
383: ospf6_lsa_show_dump (struct vty *vty, struct ospf6_lsa *lsa)
384: {
385: u_char *start, *end, *current;
386: char byte[4];
387:
388: start = (u_char *) lsa->header;
389: end = (u_char *) lsa->header + ntohs (lsa->header->length);
390:
391: vty_out (vty, "%s", VNL);
392: vty_out (vty, "%s:%s", lsa->name, VNL);
393:
394: for (current = start; current < end; current ++)
395: {
396: if ((current - start) % 16 == 0)
397: vty_out (vty, "%s ", VNL);
398: else if ((current - start) % 4 == 0)
399: vty_out (vty, " ");
400:
401: snprintf (byte, sizeof (byte), "%02x", *current);
402: vty_out (vty, "%s", byte);
403: }
404:
405: vty_out (vty, "%s%s", VNL, VNL);
406: return;
407: }
408:
409: void
410: ospf6_lsa_show_internal (struct vty *vty, struct ospf6_lsa *lsa)
411: {
412: char adv_router[64], id[64];
413:
414: assert (lsa && lsa->header);
415:
416: inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id));
417: inet_ntop (AF_INET, &lsa->header->adv_router,
418: adv_router, sizeof (adv_router));
419:
420: vty_out (vty, "%s", VNL);
421: vty_out (vty, "Age: %4hu Type: %s%s", ospf6_lsa_age_current (lsa),
422: ospf6_lstype_name (lsa->header->type), VNL);
423: vty_out (vty, "Link State ID: %s%s", id, VNL);
424: vty_out (vty, "Advertising Router: %s%s", adv_router, VNL);
425: vty_out (vty, "LS Sequence Number: %#010lx%s",
426: (u_long) ntohl (lsa->header->seqnum), VNL);
427: vty_out (vty, "CheckSum: %#06hx Length: %hu%s",
428: ntohs (lsa->header->checksum),
429: ntohs (lsa->header->length), VNL);
430: vty_out (vty, " Prev: %p This: %p Next: %p%s",
431: lsa->prev, lsa, lsa->next, VNL);
432: vty_out (vty, "%s", VNL);
433: return;
434: }
435:
436: void
437: ospf6_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
438: {
439: char adv_router[64], id[64];
440: struct ospf6_lsa_handler *handler;
441:
442: assert (lsa && lsa->header);
443:
444: inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id));
445: inet_ntop (AF_INET, &lsa->header->adv_router,
446: adv_router, sizeof (adv_router));
447:
448: vty_out (vty, "Age: %4hu Type: %s%s", ospf6_lsa_age_current (lsa),
449: ospf6_lstype_name (lsa->header->type), VNL);
450: vty_out (vty, "Link State ID: %s%s", id, VNL);
451: vty_out (vty, "Advertising Router: %s%s", adv_router, VNL);
452: vty_out (vty, "LS Sequence Number: %#010lx%s",
453: (u_long) ntohl (lsa->header->seqnum), VNL);
454: vty_out (vty, "CheckSum: %#06hx Length: %hu%s",
455: ntohs (lsa->header->checksum),
456: ntohs (lsa->header->length), VNL);
457:
458: handler = ospf6_get_lsa_handler (lsa->header->type);
459: if (handler->show == NULL)
460: handler = &unknown_handler;
461: (*handler->show) (vty, lsa);
462:
463: vty_out (vty, "%s", VNL);
464: }
465:
466: /* OSPFv3 LSA creation/deletion function */
467: struct ospf6_lsa *
468: ospf6_lsa_create (struct ospf6_lsa_header *header)
469: {
470: struct ospf6_lsa *lsa = NULL;
471: struct ospf6_lsa_header *new_header = NULL;
472: u_int16_t lsa_size = 0;
473:
474: /* size of the entire LSA */
475: lsa_size = ntohs (header->length); /* XXX vulnerable */
476:
477: /* allocate memory for this LSA */
478: new_header = (struct ospf6_lsa_header *)
479: XMALLOC (MTYPE_OSPF6_LSA, lsa_size);
480:
481: /* copy LSA from original header */
482: memcpy (new_header, header, lsa_size);
483:
484: /* LSA information structure */
485: /* allocate memory */
486: lsa = (struct ospf6_lsa *)
487: XCALLOC (MTYPE_OSPF6_LSA, sizeof (struct ospf6_lsa));
488:
489: lsa->header = (struct ospf6_lsa_header *) new_header;
490:
491: /* dump string */
492: ospf6_lsa_printbuf (lsa, lsa->name, sizeof (lsa->name));
493:
494: /* calculate birth of this lsa */
495: ospf6_lsa_age_set (lsa);
496:
497: return lsa;
498: }
499:
500: struct ospf6_lsa *
501: ospf6_lsa_create_headeronly (struct ospf6_lsa_header *header)
502: {
503: struct ospf6_lsa *lsa = NULL;
504: struct ospf6_lsa_header *new_header = NULL;
505:
506: /* allocate memory for this LSA */
507: new_header = (struct ospf6_lsa_header *)
508: XMALLOC (MTYPE_OSPF6_LSA, sizeof (struct ospf6_lsa_header));
509:
510: /* copy LSA from original header */
511: memcpy (new_header, header, sizeof (struct ospf6_lsa_header));
512:
513: /* LSA information structure */
514: /* allocate memory */
515: lsa = (struct ospf6_lsa *)
516: XCALLOC (MTYPE_OSPF6_LSA, sizeof (struct ospf6_lsa));
517:
518: lsa->header = (struct ospf6_lsa_header *) new_header;
519: SET_FLAG (lsa->flag, OSPF6_LSA_HEADERONLY);
520:
521: /* dump string */
522: ospf6_lsa_printbuf (lsa, lsa->name, sizeof (lsa->name));
523:
524: /* calculate birth of this lsa */
525: ospf6_lsa_age_set (lsa);
526:
527: return lsa;
528: }
529:
530: void
531: ospf6_lsa_delete (struct ospf6_lsa *lsa)
532: {
533: assert (lsa->lock == 0);
534:
535: /* cancel threads */
536: THREAD_OFF (lsa->expire);
537: THREAD_OFF (lsa->refresh);
538:
539: /* do free */
540: XFREE (MTYPE_OSPF6_LSA, lsa->header);
541: XFREE (MTYPE_OSPF6_LSA, lsa);
542: }
543:
544: struct ospf6_lsa *
545: ospf6_lsa_copy (struct ospf6_lsa *lsa)
546: {
547: struct ospf6_lsa *copy = NULL;
548:
549: ospf6_lsa_age_current (lsa);
550: if (CHECK_FLAG (lsa->flag, OSPF6_LSA_HEADERONLY))
551: copy = ospf6_lsa_create_headeronly (lsa->header);
552: else
553: copy = ospf6_lsa_create (lsa->header);
554: assert (copy->lock == 0);
555:
556: copy->birth = lsa->birth;
557: copy->originated = lsa->originated;
558: copy->received = lsa->received;
559: copy->installed = lsa->installed;
560: copy->lsdb = lsa->lsdb;
561:
562: return copy;
563: }
564:
565: /* increment reference counter of struct ospf6_lsa */
566: void
567: ospf6_lsa_lock (struct ospf6_lsa *lsa)
568: {
569: lsa->lock++;
570: return;
571: }
572:
573: /* decrement reference counter of struct ospf6_lsa */
574: void
575: ospf6_lsa_unlock (struct ospf6_lsa *lsa)
576: {
577: /* decrement reference counter */
578: assert (lsa->lock > 0);
579: lsa->lock--;
580:
581: if (lsa->lock != 0)
582: return;
583:
584: ospf6_lsa_delete (lsa);
585: }
586:
587:
588: /* ospf6 lsa expiry */
589: int
590: ospf6_lsa_expire (struct thread *thread)
591: {
592: struct ospf6_lsa *lsa;
593:
594: lsa = (struct ospf6_lsa *) THREAD_ARG (thread);
595:
596: assert (lsa && lsa->header);
597: assert (OSPF6_LSA_IS_MAXAGE (lsa));
598: assert (! lsa->refresh);
599:
600: lsa->expire = (struct thread *) NULL;
601:
602: if (IS_OSPF6_DEBUG_LSA_TYPE (lsa->header->type))
603: {
604: zlog_debug ("LSA Expire:");
605: ospf6_lsa_header_print (lsa);
606: }
607:
608: if (CHECK_FLAG (lsa->flag, OSPF6_LSA_HEADERONLY))
609: return 0; /* dbexchange will do something ... */
610:
611: /* reflood lsa */
612: ospf6_flood (NULL, lsa);
613:
614: /* reinstall lsa */
615: ospf6_install_lsa (lsa);
616:
617: /* schedule maxage remover */
618: ospf6_maxage_remove (ospf6);
619:
620: return 0;
621: }
622:
623: int
624: ospf6_lsa_refresh (struct thread *thread)
625: {
626: struct ospf6_lsa *old, *self, *new;
627: struct ospf6_lsdb *lsdb_self;
628:
629: assert (thread);
630: old = (struct ospf6_lsa *) THREAD_ARG (thread);
631: assert (old && old->header);
632:
633: old->refresh = (struct thread *) NULL;
634:
635: lsdb_self = ospf6_get_scoped_lsdb_self (old);
636: self = ospf6_lsdb_lookup (old->header->type, old->header->id,
637: old->header->adv_router, lsdb_self);
638: if (self == NULL)
639: {
640: if (IS_OSPF6_DEBUG_LSA_TYPE (old->header->type))
641: zlog_debug ("Refresh: could not find self LSA, flush %s", old->name);
642: ospf6_lsa_premature_aging (old);
643: return 0;
644: }
645:
646: /* Reset age, increment LS sequence number. */
647: self->header->age = htons (0);
648: self->header->seqnum =
649: ospf6_new_ls_seqnum (self->header->type, self->header->id,
650: self->header->adv_router, old->lsdb);
651: ospf6_lsa_checksum (self->header);
652:
653: new = ospf6_lsa_create (self->header);
654: new->lsdb = old->lsdb;
655: new->refresh = thread_add_timer (master, ospf6_lsa_refresh, new,
656: LS_REFRESH_TIME);
657:
658: /* store it in the LSDB for self-originated LSAs */
659: ospf6_lsdb_add (ospf6_lsa_copy (new), lsdb_self);
660:
661: if (IS_OSPF6_DEBUG_LSA_TYPE (new->header->type))
662: {
663: zlog_debug ("LSA Refresh:");
664: ospf6_lsa_header_print (new);
665: }
666:
667: ospf6_flood_clear (old);
668: ospf6_flood (NULL, new);
669: ospf6_install_lsa (new);
670:
671: return 0;
672: }
673:
674:
675:
1.1.1.2 ! misho 676: /* Fletcher Checksum -- Refer to RFC1008. */
1.1 misho 677:
1.1.1.2 ! misho 678: /* All the offsets are zero-based. The offsets in the RFC1008 are
! 679: one-based. */
1.1 misho 680: unsigned short
681: ospf6_lsa_checksum (struct ospf6_lsa_header *lsa_header)
682: {
1.1.1.2 ! misho 683: u_char *buffer = (u_char *) &lsa_header->type;
! 684: int type_offset = buffer - (u_char *) &lsa_header->age; /* should be 2 */
1.1 misho 685:
1.1.1.2 ! misho 686: /* Skip the AGE field */
! 687: u_int16_t len = ntohs(lsa_header->length) - type_offset;
1.1 misho 688:
1.1.1.2 ! misho 689: /* Checksum offset starts from "type" field, not the beginning of the
! 690: lsa_header struct. The offset is 14, rather than 16. */
! 691: int checksum_offset = (u_char *) &lsa_header->checksum - buffer;
! 692:
! 693: return (unsigned short)fletcher_checksum(buffer, len, checksum_offset);
! 694: }
! 695:
! 696: int
! 697: ospf6_lsa_checksum_valid (struct ospf6_lsa_header *lsa_header)
! 698: {
! 699: u_char *buffer = (u_char *) &lsa_header->type;
! 700: int type_offset = buffer - (u_char *) &lsa_header->age; /* should be 2 */
! 701:
! 702: /* Skip the AGE field */
! 703: u_int16_t len = ntohs(lsa_header->length) - type_offset;
! 704:
! 705: return (fletcher_checksum(buffer, len, FLETCHER_CHECKSUM_VALIDATE) == 0);
1.1 misho 706: }
707:
708: void
709: ospf6_lsa_init (void)
710: {
711: ospf6_lsa_handler_vector = vector_init (0);
712: ospf6_install_lsa_handler (&unknown_handler);
713: }
714:
715: void
716: ospf6_lsa_terminate (void)
717: {
718: vector_free (ospf6_lsa_handler_vector);
719: }
720:
721: static char *
722: ospf6_lsa_handler_name (struct ospf6_lsa_handler *h)
723: {
724: static char buf[64];
725: unsigned int i;
726: unsigned int size = strlen (h->name);
727:
728: if (!strcmp(h->name, "Unknown") &&
729: h->type != OSPF6_LSTYPE_UNKNOWN)
730: {
731: snprintf (buf, sizeof (buf), "%#04hx", h->type);
732: return buf;
733: }
734:
735: for (i = 0; i < MIN (size, sizeof (buf)); i++)
736: {
737: if (! islower (h->name[i]))
738: buf[i] = tolower (h->name[i]);
739: else
740: buf[i] = h->name[i];
741: }
742: buf[size] = '\0';
743: return buf;
744: }
745:
746: DEFUN (debug_ospf6_lsa_type,
747: debug_ospf6_lsa_hex_cmd,
748: "debug ospf6 lsa XXXX/0xXXXX",
749: DEBUG_STR
750: OSPF6_STR
751: "Debug Link State Advertisements (LSAs)\n"
752: "Specify LS type as Hexadecimal\n"
753: )
754: {
755: unsigned int i;
756: struct ospf6_lsa_handler *handler = NULL;
757: unsigned long val;
758: char *endptr = NULL;
759: u_int16_t type = 0;
760:
761: assert (argc);
762:
763: if ((strlen (argv[0]) == 6 && ! strncmp (argv[0], "0x", 2)) ||
764: (strlen (argv[0]) == 4))
765: {
766: val = strtoul (argv[0], &endptr, 16);
767: if (*endptr == '\0')
768: type = val;
769: }
770:
771: for (i = 0; i < vector_active (ospf6_lsa_handler_vector); i++)
772: {
773: handler = vector_slot (ospf6_lsa_handler_vector, i);
774: if (handler == NULL)
775: continue;
776: if (type && handler->type == type)
777: break;
778: if (! strcasecmp (argv[0], handler->name))
779: break;
780: handler = NULL;
781: }
782:
783: if (type && handler == NULL)
784: {
785: handler = (struct ospf6_lsa_handler *)
786: malloc (sizeof (struct ospf6_lsa_handler));
787: memset (handler, 0, sizeof (struct ospf6_lsa_handler));
788: handler->type = type;
789: handler->name = "Unknown";
790: handler->show = ospf6_unknown_lsa_show;
791: vector_set_index (ospf6_lsa_handler_vector,
792: handler->type & OSPF6_LSTYPE_FCODE_MASK, handler);
793: }
794:
795: if (handler == NULL)
796: handler = &unknown_handler;
797:
798: if (argc >= 2)
799: {
800: if (! strcmp (argv[1], "originate"))
801: SET_FLAG (handler->debug, OSPF6_LSA_DEBUG_ORIGINATE);
802: if (! strcmp (argv[1], "examin"))
803: SET_FLAG (handler->debug, OSPF6_LSA_DEBUG_EXAMIN);
804: if (! strcmp (argv[1], "flooding"))
805: SET_FLAG (handler->debug, OSPF6_LSA_DEBUG_FLOOD);
806: }
807: else
808: SET_FLAG (handler->debug, OSPF6_LSA_DEBUG);
809:
810: return CMD_SUCCESS;
811: }
812:
813: DEFUN (no_debug_ospf6_lsa_type,
814: no_debug_ospf6_lsa_hex_cmd,
815: "no debug ospf6 lsa XXXX/0xXXXX",
816: NO_STR
817: DEBUG_STR
818: OSPF6_STR
819: "Debug Link State Advertisements (LSAs)\n"
820: "Specify LS type as Hexadecimal\n"
821: )
822: {
823: u_int i;
824: struct ospf6_lsa_handler *handler = NULL;
825: unsigned long val;
826: char *endptr = NULL;
827: u_int16_t type = 0;
828:
829: assert (argc);
830:
831: if ((strlen (argv[0]) == 6 && ! strncmp (argv[0], "0x", 2)) ||
832: (strlen (argv[0]) == 4))
833: {
834: val = strtoul (argv[0], &endptr, 16);
835: if (*endptr == '\0')
836: type = val;
837: }
838:
839: for (i = 0; i < vector_active (ospf6_lsa_handler_vector); i++)
840: {
841: handler = vector_slot (ospf6_lsa_handler_vector, i);
842: if (handler == NULL)
843: continue;
844: if (type && handler->type == type)
845: break;
846: if (! strcasecmp (argv[0], handler->name))
847: break;
848: }
849:
850: if (handler == NULL)
851: return CMD_SUCCESS;
852:
853: if (argc >= 2)
854: {
855: if (! strcmp (argv[1], "originate"))
856: UNSET_FLAG (handler->debug, OSPF6_LSA_DEBUG_ORIGINATE);
857: if (! strcmp (argv[1], "examin"))
858: UNSET_FLAG (handler->debug, OSPF6_LSA_DEBUG_EXAMIN);
859: if (! strcmp (argv[1], "flooding"))
860: UNSET_FLAG (handler->debug, OSPF6_LSA_DEBUG_FLOOD);
861: }
862: else
863: UNSET_FLAG (handler->debug, OSPF6_LSA_DEBUG);
864:
865: if (handler->debug == 0 &&
866: !strcmp(handler->name, "Unknown") && type != OSPF6_LSTYPE_UNKNOWN)
867: {
868: free (handler);
869: vector_slot (ospf6_lsa_handler_vector, i) = NULL;
870: }
871:
872: return CMD_SUCCESS;
873: }
874:
875: struct cmd_element debug_ospf6_lsa_type_cmd;
876: struct cmd_element debug_ospf6_lsa_type_detail_cmd;
877: struct cmd_element no_debug_ospf6_lsa_type_cmd;
878: struct cmd_element no_debug_ospf6_lsa_type_detail_cmd;
879:
880: void
881: install_element_ospf6_debug_lsa (void)
882: {
883: u_int i;
884: struct ospf6_lsa_handler *handler;
885: #define STRSIZE 256
886: #define DOCSIZE 1024
887: static char strbuf[STRSIZE];
888: static char docbuf[DOCSIZE];
889: static char detail_strbuf[STRSIZE];
890: static char detail_docbuf[DOCSIZE];
891: char *str, *no_str;
892: char *doc, *no_doc;
893:
894: strbuf[0] = '\0';
895: no_str = &strbuf[strlen (strbuf)];
896: strncat (strbuf, "no ", STRSIZE - strlen (strbuf));
897: str = &strbuf[strlen (strbuf)];
898:
899: strncat (strbuf, "debug ospf6 lsa (", STRSIZE - strlen (strbuf));
900: for (i = 0; i < vector_active (ospf6_lsa_handler_vector); i++)
901: {
902: handler = vector_slot (ospf6_lsa_handler_vector, i);
903: if (handler == NULL)
904: continue;
905: strncat (strbuf, ospf6_lsa_handler_name (handler),
906: STRSIZE - strlen (strbuf));
907: strncat (strbuf, "|", STRSIZE - strlen (strbuf));
908: }
909: strbuf[strlen (strbuf) - 1] = ')';
910: strbuf[strlen (strbuf)] = '\0';
911:
912: docbuf[0] = '\0';
913: no_doc = &docbuf[strlen (docbuf)];
914: strncat (docbuf, NO_STR, DOCSIZE - strlen (docbuf));
915: doc = &docbuf[strlen (docbuf)];
916:
917: strncat (docbuf, DEBUG_STR, DOCSIZE - strlen (docbuf));
918: strncat (docbuf, OSPF6_STR, DOCSIZE - strlen (docbuf));
919: strncat (docbuf, "Debug Link State Advertisements (LSAs)\n",
920: DOCSIZE - strlen (docbuf));
921:
922: for (i = 0; i < vector_active (ospf6_lsa_handler_vector); i++)
923: {
924: handler = vector_slot (ospf6_lsa_handler_vector, i);
925: if (handler == NULL)
926: continue;
927: strncat (docbuf, "Debug ", DOCSIZE - strlen (docbuf));
928: strncat (docbuf, handler->name, DOCSIZE - strlen (docbuf));
929: strncat (docbuf, "-LSA\n", DOCSIZE - strlen (docbuf));
930: }
931: docbuf[strlen (docbuf)] = '\0';
932:
933: debug_ospf6_lsa_type_cmd.string = str;
934: debug_ospf6_lsa_type_cmd.func = debug_ospf6_lsa_type;
935: debug_ospf6_lsa_type_cmd.doc = doc;
936:
937: no_debug_ospf6_lsa_type_cmd.string = no_str;
938: no_debug_ospf6_lsa_type_cmd.func = no_debug_ospf6_lsa_type;
939: no_debug_ospf6_lsa_type_cmd.doc = no_doc;
940:
941: strncpy (detail_strbuf, strbuf, STRSIZE);
942: strncat (detail_strbuf, " (originate|examin|flooding)",
943: STRSIZE - strlen (detail_strbuf));
944: detail_strbuf[strlen (detail_strbuf)] = '\0';
945: no_str = &detail_strbuf[0];
946: str = &detail_strbuf[strlen ("no ")];
947:
948: strncpy (detail_docbuf, docbuf, DOCSIZE);
949: strncat (detail_docbuf, "Debug Originating LSA\n",
950: DOCSIZE - strlen (detail_docbuf));
951: strncat (detail_docbuf, "Debug Examining LSA\n",
952: DOCSIZE - strlen (detail_docbuf));
953: strncat (detail_docbuf, "Debug Flooding LSA\n",
954: DOCSIZE - strlen (detail_docbuf));
955: detail_docbuf[strlen (detail_docbuf)] = '\0';
956: no_doc = &detail_docbuf[0];
957: doc = &detail_docbuf[strlen (NO_STR)];
958:
959: debug_ospf6_lsa_type_detail_cmd.string = str;
960: debug_ospf6_lsa_type_detail_cmd.func = debug_ospf6_lsa_type;
961: debug_ospf6_lsa_type_detail_cmd.doc = doc;
962:
963: no_debug_ospf6_lsa_type_detail_cmd.string = no_str;
964: no_debug_ospf6_lsa_type_detail_cmd.func = no_debug_ospf6_lsa_type;
965: no_debug_ospf6_lsa_type_detail_cmd.doc = no_doc;
966:
967: install_element (ENABLE_NODE, &debug_ospf6_lsa_hex_cmd);
968: install_element (ENABLE_NODE, &debug_ospf6_lsa_type_cmd);
969: install_element (ENABLE_NODE, &debug_ospf6_lsa_type_detail_cmd);
970: install_element (ENABLE_NODE, &no_debug_ospf6_lsa_hex_cmd);
971: install_element (ENABLE_NODE, &no_debug_ospf6_lsa_type_cmd);
972: install_element (ENABLE_NODE, &no_debug_ospf6_lsa_type_detail_cmd);
973: install_element (CONFIG_NODE, &debug_ospf6_lsa_hex_cmd);
974: install_element (CONFIG_NODE, &debug_ospf6_lsa_type_cmd);
975: install_element (CONFIG_NODE, &debug_ospf6_lsa_type_detail_cmd);
976: install_element (CONFIG_NODE, &no_debug_ospf6_lsa_hex_cmd);
977: install_element (CONFIG_NODE, &no_debug_ospf6_lsa_type_cmd);
978: install_element (CONFIG_NODE, &no_debug_ospf6_lsa_type_detail_cmd);
979: }
980:
981: int
982: config_write_ospf6_debug_lsa (struct vty *vty)
983: {
984: u_int i;
985: struct ospf6_lsa_handler *handler;
986:
987: for (i = 0; i < vector_active (ospf6_lsa_handler_vector); i++)
988: {
989: handler = vector_slot (ospf6_lsa_handler_vector, i);
990: if (handler == NULL)
991: continue;
992: if (CHECK_FLAG (handler->debug, OSPF6_LSA_DEBUG))
993: vty_out (vty, "debug ospf6 lsa %s%s",
994: ospf6_lsa_handler_name (handler), VNL);
995: if (CHECK_FLAG (handler->debug, OSPF6_LSA_DEBUG_ORIGINATE))
996: vty_out (vty, "debug ospf6 lsa %s originate%s",
997: ospf6_lsa_handler_name (handler), VNL);
998: if (CHECK_FLAG (handler->debug, OSPF6_LSA_DEBUG_EXAMIN))
999: vty_out (vty, "debug ospf6 lsa %s examin%s",
1000: ospf6_lsa_handler_name (handler), VNL);
1001: if (CHECK_FLAG (handler->debug, OSPF6_LSA_DEBUG_FLOOD))
1002: vty_out (vty, "debug ospf6 lsa %s flooding%s",
1003: ospf6_lsa_handler_name (handler), VNL);
1004: }
1005:
1006: return 0;
1007: }
1008:
1009:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>