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