Annotation of embedaddon/quagga/ospf6d/ospf6_lsa.c, revision 1.1.1.3
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",
1.1.1.3 ! misho 78: "Unk",
1.1 misho 79: ospf6_unknown_lsa_show,
1.1.1.3 ! misho 80: NULL,
1.1 misho 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:
1.1.1.3 ! misho 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:
1.1 misho 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);
1.1.1.3 ! misho 158: if (ntohs (lsa1->header->age) == OSPF_LSA_MAXAGE &&
! 159: ntohs (lsa2->header->age) != OSPF_LSA_MAXAGE)
1.1 misho 160: return 1;
1.1.1.3 ! misho 161: if (ntohs (lsa1->header->age) != OSPF_LSA_MAXAGE &&
! 162: ntohs (lsa2->header->age) == OSPF_LSA_MAXAGE)
1.1 misho 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:
1.1.1.3 ! misho 237: if (ntohs (lsa->header->age) >= OSPF_LSA_MAXAGE)
1.1 misho 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. */
1.1.1.3 ! misho 242: lsa->header->age = htons (OSPF_LSA_MAXAGE);
! 243: return OSPF_LSA_MAXAGE;
1.1 misho 244: }
245: /* calculate age */
246: ulage = now.tv_sec - lsa->birth.tv_sec;
247:
248: /* if over MAXAGE, set to it */
1.1.1.3 ! misho 249: age = (ulage > OSPF_LSA_MAXAGE ? OSPF_LSA_MAXAGE : ulage);
1.1 misho 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;
1.1.1.3 ! misho 262: if (age > OSPF_LSA_MAXAGE)
! 263: age = OSPF_LSA_MAXAGE;
1.1 misho 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:
1.1.1.3 ! misho 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);
1.1 misho 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: {
1.1.1.3 ! misho 309: int32_t seqnuma, seqnumb;
1.1 misho 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:
1.1.1.3 ! misho 317: seqnuma = (int32_t) ntohl (a->header->seqnum);
! 318: seqnumb = (int32_t) ntohl (b->header->seqnum);
1.1 misho 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 */
1.1.1.3 ! misho 339: if (agea == OSPF_LSA_MAXAGE && ageb != OSPF_LSA_MAXAGE)
1.1 misho 340: return -1;
1.1.1.3 ! misho 341: else if (agea != OSPF_LSA_MAXAGE && ageb == OSPF_LSA_MAXAGE)
1.1 misho 342: return 1;
343:
344: /* Age check */
1.1.1.3 ! misho 345: if (agea > ageb && agea - ageb >= OSPF_LSA_MAXAGE_DIFF)
1.1 misho 346: return 1;
1.1.1.3 ! misho 347: else if (agea < ageb && ageb - agea >= OSPF_LSA_MAXAGE_DIFF)
1.1 misho 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: {
1.1.1.3 ! misho 390: vty_out (vty, "%-4s %-15s%-15s%4s %8s %30s%s",
1.1 misho 391: "Type", "LSId", "AdvRouter", "Age", "SeqNum",
1.1.1.3 ! misho 392: "Payload", VNL);
1.1 misho 393: }
394:
395: void
396: ospf6_lsa_show_summary (struct vty *vty, struct ospf6_lsa *lsa)
397: {
398: char adv_router[16], id[16];
1.1.1.3 ! misho 399: int type;
! 400: struct ospf6_lsa_handler *handler;
! 401: char buf[64], tmpbuf[80];
! 402: int cnt = 0;
1.1 misho 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:
1.1.1.3 ! misho 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: }
1.1 misho 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);
1.1.1.3 ! misho 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);
1.1 misho 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;
1.1.1.3 ! misho 507: struct timeval now, res;
! 508: char duration[16];
1.1 misho 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:
1.1.1.3 ! misho 516: quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
! 517: timersub (&now, &lsa->installed, &res);
! 518: timerstring (&res, duration, sizeof (duration));
! 519:
1.1 misho 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);
1.1.1.3 ! misho 529: vty_out (vty, "Duration: %s%s", duration, VNL);
1.1 misho 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;
1.1.1.3 ! misho 634: copy->rn = NULL;
1.1 misho 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:
1.1.1.3 ! misho 661:
1.1 misho 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:
1.1.1.3 ! misho 688: /* reflood lsa */
! 689: ospf6_flood (NULL, lsa);
! 690:
1.1 misho 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,
1.1.1.3 ! misho 730: OSPF_LS_REFRESH_TIME);
1.1 misho 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);
1.1.1.3 ! misho 742: ospf6_flood (NULL, new);
1.1 misho 743:
744: return 0;
745: }
746:
1.1.1.3 ! misho 747:
1.1 misho 748:
1.1.1.2 misho 749: /* Fletcher Checksum -- Refer to RFC1008. */
1.1 misho 750:
1.1.1.2 misho 751: /* All the offsets are zero-based. The offsets in the RFC1008 are
752: one-based. */
1.1 misho 753: unsigned short
754: ospf6_lsa_checksum (struct ospf6_lsa_header *lsa_header)
755: {
1.1.1.2 misho 756: u_char *buffer = (u_char *) &lsa_header->type;
757: int type_offset = buffer - (u_char *) &lsa_header->age; /* should be 2 */
1.1 misho 758:
1.1.1.2 misho 759: /* Skip the AGE field */
760: u_int16_t len = ntohs(lsa_header->length) - type_offset;
1.1 misho 761:
1.1.1.2 misho 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);
1.1 misho 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: }
1.1.1.3 ! misho 793:
1.1 misho 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:
1.1.1.3 ! misho 801: if (!strcmp(h->name, "unknown") &&
1.1 misho 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: {
1.1.1.3 ! misho 810: if (! islower ((unsigned char)h->name[i]))
! 811: buf[i] = tolower ((unsigned char)h->name[i]);
1.1 misho 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,
1.1.1.3 ! misho 821: "debug ospf6 lsa (router|network|inter-prefix|inter-router|as-ext|grp-mbr|type7|link|intra-prefix|unknown)",
1.1 misho 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;
1.1.1.3 ! misho 838: if (strncmp (argv[0], ospf6_lsa_handler_name(handler), strlen(argv[0])) == 0)
1.1 misho 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);
1.1.1.3 ! misho 852: if (! strcmp (argv[1], "examine"))
1.1 misho 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:
1.1.1.3 ! misho 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:
1.1 misho 872: DEFUN (no_debug_ospf6_lsa_type,
873: no_debug_ospf6_lsa_hex_cmd,
1.1.1.3 ! misho 874: "no debug ospf6 lsa (router|network|inter-prefix|inter-router|as-ext|grp-mbr|type7|link|intra-prefix|unknown)",
1.1 misho 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;
1.1.1.3 ! misho 892: if (strncmp (argv[0], ospf6_lsa_handler_name(handler), strlen(argv[0])) == 0)
1.1 misho 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);
1.1.1.3 ! misho 905: if (! strcmp (argv[1], "examine"))
1.1 misho 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:
1.1.1.3 ! misho 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: )
1.1 misho 925:
926: void
927: install_element_ospf6_debug_lsa (void)
928: {
929: install_element (ENABLE_NODE, &debug_ospf6_lsa_hex_cmd);
1.1.1.3 ! misho 930: install_element (ENABLE_NODE, &debug_ospf6_lsa_hex_detail_cmd);
1.1 misho 931: install_element (ENABLE_NODE, &no_debug_ospf6_lsa_hex_cmd);
1.1.1.3 ! misho 932: install_element (ENABLE_NODE, &no_debug_ospf6_lsa_hex_detail_cmd);
1.1 misho 933: install_element (CONFIG_NODE, &debug_ospf6_lsa_hex_cmd);
1.1.1.3 ! misho 934: install_element (CONFIG_NODE, &debug_ospf6_lsa_hex_detail_cmd);
1.1 misho 935: install_element (CONFIG_NODE, &no_debug_ospf6_lsa_hex_cmd);
1.1.1.3 ! misho 936: install_element (CONFIG_NODE, &no_debug_ospf6_lsa_hex_detail_cmd);
1.1 misho 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))
1.1.1.3 ! misho 957: vty_out (vty, "debug ospf6 lsa %s examine%s",
1.1 misho 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>