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