Annotation of embedaddon/quagga/ospf6d/ospf6_message.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 "memory.h"
! 25: #include "log.h"
! 26: #include "vty.h"
! 27: #include "command.h"
! 28: #include "thread.h"
! 29: #include "linklist.h"
! 30:
! 31: #include "ospf6_proto.h"
! 32: #include "ospf6_lsa.h"
! 33: #include "ospf6_lsdb.h"
! 34: #include "ospf6_network.h"
! 35: #include "ospf6_message.h"
! 36:
! 37: #include "ospf6_top.h"
! 38: #include "ospf6_area.h"
! 39: #include "ospf6_neighbor.h"
! 40: #include "ospf6_interface.h"
! 41:
! 42: /* for structures and macros ospf6_lsa_examin() needs */
! 43: #include "ospf6_abr.h"
! 44: #include "ospf6_asbr.h"
! 45: #include "ospf6_intra.h"
! 46:
! 47: #include "ospf6_flood.h"
! 48: #include "ospf6d.h"
! 49:
! 50: unsigned char conf_debug_ospf6_message[6] = {0x03, 0, 0, 0, 0, 0};
! 51: const char *ospf6_message_type_str[] =
! 52: { "Unknown", "Hello", "DbDesc", "LSReq", "LSUpdate", "LSAck" };
! 53:
! 54: /* Minimum (besides the standard OSPF packet header) lengths for OSPF
! 55: packets of particular types, offset is the "type" field. */
! 56: const u_int16_t ospf6_packet_minlen[OSPF6_MESSAGE_TYPE_ALL] =
! 57: {
! 58: 0,
! 59: OSPF6_HELLO_MIN_SIZE,
! 60: OSPF6_DB_DESC_MIN_SIZE,
! 61: OSPF6_LS_REQ_MIN_SIZE,
! 62: OSPF6_LS_UPD_MIN_SIZE,
! 63: OSPF6_LS_ACK_MIN_SIZE
! 64: };
! 65:
! 66: /* Minimum (besides the standard LSA header) lengths for LSAs of particular
! 67: types, offset is the "LSA function code" portion of "LSA type" field. */
! 68: const u_int16_t ospf6_lsa_minlen[OSPF6_LSTYPE_SIZE] =
! 69: {
! 70: 0,
! 71: /* 0x2001 */ OSPF6_ROUTER_LSA_MIN_SIZE,
! 72: /* 0x2002 */ OSPF6_NETWORK_LSA_MIN_SIZE,
! 73: /* 0x2003 */ OSPF6_INTER_PREFIX_LSA_MIN_SIZE,
! 74: /* 0x2004 */ OSPF6_INTER_ROUTER_LSA_FIX_SIZE,
! 75: /* 0x4005 */ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE,
! 76: /* 0x2006 */ 0,
! 77: /* 0x2007 */ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE,
! 78: /* 0x0008 */ OSPF6_LINK_LSA_MIN_SIZE,
! 79: /* 0x2009 */ OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
! 80: };
! 81:
! 82: /* print functions */
! 83:
! 84: static void
! 85: ospf6_header_print (struct ospf6_header *oh)
! 86: {
! 87: char router_id[16], area_id[16];
! 88: inet_ntop (AF_INET, &oh->router_id, router_id, sizeof (router_id));
! 89: inet_ntop (AF_INET, &oh->area_id, area_id, sizeof (area_id));
! 90:
! 91: zlog_debug (" OSPFv%d Type:%d Len:%hu Router-ID:%s",
! 92: oh->version, oh->type, ntohs (oh->length), router_id);
! 93: zlog_debug (" Area-ID:%s Cksum:%hx Instance-ID:%d",
! 94: area_id, ntohs (oh->checksum), oh->instance_id);
! 95: }
! 96:
! 97: void
! 98: ospf6_hello_print (struct ospf6_header *oh)
! 99: {
! 100: struct ospf6_hello *hello;
! 101: char options[16];
! 102: char drouter[16], bdrouter[16], neighbor[16];
! 103: char *p;
! 104:
! 105: ospf6_header_print (oh);
! 106: assert (oh->type == OSPF6_MESSAGE_TYPE_HELLO);
! 107:
! 108: hello = (struct ospf6_hello *)
! 109: ((caddr_t) oh + sizeof (struct ospf6_header));
! 110:
! 111: inet_ntop (AF_INET, &hello->drouter, drouter, sizeof (drouter));
! 112: inet_ntop (AF_INET, &hello->bdrouter, bdrouter, sizeof (bdrouter));
! 113: ospf6_options_printbuf (hello->options, options, sizeof (options));
! 114:
! 115: zlog_debug (" I/F-Id:%ld Priority:%d Option:%s",
! 116: (u_long) ntohl (hello->interface_id), hello->priority, options);
! 117: zlog_debug (" HelloInterval:%hu DeadInterval:%hu",
! 118: ntohs (hello->hello_interval), ntohs (hello->dead_interval));
! 119: zlog_debug (" DR:%s BDR:%s", drouter, bdrouter);
! 120:
! 121: for (p = (char *) ((caddr_t) hello + sizeof (struct ospf6_hello));
! 122: p + sizeof (u_int32_t) <= OSPF6_MESSAGE_END (oh);
! 123: p += sizeof (u_int32_t))
! 124: {
! 125: inet_ntop (AF_INET, (void *) p, neighbor, sizeof (neighbor));
! 126: zlog_debug (" Neighbor: %s", neighbor);
! 127: }
! 128:
! 129: if (p != OSPF6_MESSAGE_END (oh))
! 130: zlog_debug ("Trailing garbage exists");
! 131: }
! 132:
! 133: void
! 134: ospf6_dbdesc_print (struct ospf6_header *oh)
! 135: {
! 136: struct ospf6_dbdesc *dbdesc;
! 137: char options[16];
! 138: char *p;
! 139:
! 140: ospf6_header_print (oh);
! 141: assert (oh->type == OSPF6_MESSAGE_TYPE_DBDESC);
! 142:
! 143: dbdesc = (struct ospf6_dbdesc *)
! 144: ((caddr_t) oh + sizeof (struct ospf6_header));
! 145:
! 146: ospf6_options_printbuf (dbdesc->options, options, sizeof (options));
! 147:
! 148: zlog_debug (" MBZ: %#x Option: %s IfMTU: %hu",
! 149: dbdesc->reserved1, options, ntohs (dbdesc->ifmtu));
! 150: zlog_debug (" MBZ: %#x Bits: %s%s%s SeqNum: %#lx",
! 151: dbdesc->reserved2,
! 152: (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) ? "I" : "-"),
! 153: (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) ? "M" : "-"),
! 154: (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) ? "m" : "s"),
! 155: (u_long) ntohl (dbdesc->seqnum));
! 156:
! 157: for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
! 158: p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
! 159: p += sizeof (struct ospf6_lsa_header))
! 160: ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p);
! 161:
! 162: if (p != OSPF6_MESSAGE_END (oh))
! 163: zlog_debug ("Trailing garbage exists");
! 164: }
! 165:
! 166: void
! 167: ospf6_lsreq_print (struct ospf6_header *oh)
! 168: {
! 169: char id[16], adv_router[16];
! 170: char *p;
! 171:
! 172: ospf6_header_print (oh);
! 173: assert (oh->type == OSPF6_MESSAGE_TYPE_LSREQ);
! 174:
! 175: for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
! 176: p + sizeof (struct ospf6_lsreq_entry) <= OSPF6_MESSAGE_END (oh);
! 177: p += sizeof (struct ospf6_lsreq_entry))
! 178: {
! 179: struct ospf6_lsreq_entry *e = (struct ospf6_lsreq_entry *) p;
! 180: inet_ntop (AF_INET, &e->adv_router, adv_router, sizeof (adv_router));
! 181: inet_ntop (AF_INET, &e->id, id, sizeof (id));
! 182: zlog_debug (" [%s Id:%s Adv:%s]",
! 183: ospf6_lstype_name (e->type), id, adv_router);
! 184: }
! 185:
! 186: if (p != OSPF6_MESSAGE_END (oh))
! 187: zlog_debug ("Trailing garbage exists");
! 188: }
! 189:
! 190: void
! 191: ospf6_lsupdate_print (struct ospf6_header *oh)
! 192: {
! 193: struct ospf6_lsupdate *lsupdate;
! 194: u_long num;
! 195: char *p;
! 196:
! 197: ospf6_header_print (oh);
! 198: assert (oh->type == OSPF6_MESSAGE_TYPE_LSUPDATE);
! 199:
! 200: lsupdate = (struct ospf6_lsupdate *)
! 201: ((caddr_t) oh + sizeof (struct ospf6_header));
! 202:
! 203: num = ntohl (lsupdate->lsa_number);
! 204: zlog_debug (" Number of LSA: %ld", num);
! 205:
! 206: for (p = (char *) ((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
! 207: p < OSPF6_MESSAGE_END (oh) &&
! 208: p + OSPF6_LSA_SIZE (p) <= OSPF6_MESSAGE_END (oh);
! 209: p += OSPF6_LSA_SIZE (p))
! 210: {
! 211: ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p);
! 212: if (OSPF6_LSA_SIZE (p) < sizeof (struct ospf6_lsa_header))
! 213: {
! 214: zlog_debug (" Malformed LSA length, quit printing");
! 215: break;
! 216: }
! 217: }
! 218:
! 219: if (p != OSPF6_MESSAGE_END (oh))
! 220: {
! 221: char buf[32];
! 222:
! 223: int num = 0;
! 224: memset (buf, 0, sizeof (buf));
! 225:
! 226: zlog_debug (" Trailing garbage exists");
! 227: while (p < OSPF6_MESSAGE_END (oh))
! 228: {
! 229: snprintf (buf, sizeof (buf), "%s %2x", buf, *p++);
! 230: num++;
! 231: if (num == 8)
! 232: {
! 233: zlog_debug (" %s", buf);
! 234: memset (buf, 0, sizeof (buf));
! 235: num = 0;
! 236: }
! 237: }
! 238: if (num)
! 239: zlog_debug (" %s", buf);
! 240: }
! 241: }
! 242:
! 243: void
! 244: ospf6_lsack_print (struct ospf6_header *oh)
! 245: {
! 246: char *p;
! 247:
! 248: ospf6_header_print (oh);
! 249: assert (oh->type == OSPF6_MESSAGE_TYPE_LSACK);
! 250:
! 251: for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
! 252: p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
! 253: p += sizeof (struct ospf6_lsa_header))
! 254: ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p);
! 255:
! 256: if (p != OSPF6_MESSAGE_END (oh))
! 257: zlog_debug ("Trailing garbage exists");
! 258: }
! 259:
! 260: static void
! 261: ospf6_hello_recv (struct in6_addr *src, struct in6_addr *dst,
! 262: struct ospf6_interface *oi, struct ospf6_header *oh)
! 263: {
! 264: struct ospf6_hello *hello;
! 265: struct ospf6_neighbor *on;
! 266: char *p;
! 267: int twoway = 0;
! 268: int neighborchange = 0;
! 269: int backupseen = 0;
! 270:
! 271: hello = (struct ospf6_hello *)
! 272: ((caddr_t) oh + sizeof (struct ospf6_header));
! 273:
! 274: /* HelloInterval check */
! 275: if (ntohs (hello->hello_interval) != oi->hello_interval)
! 276: {
! 277: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 278: zlog_debug ("HelloInterval mismatch");
! 279: return;
! 280: }
! 281:
! 282: /* RouterDeadInterval check */
! 283: if (ntohs (hello->dead_interval) != oi->dead_interval)
! 284: {
! 285: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 286: zlog_debug ("RouterDeadInterval mismatch");
! 287: return;
! 288: }
! 289:
! 290: /* E-bit check */
! 291: if (OSPF6_OPT_ISSET (hello->options, OSPF6_OPT_E) !=
! 292: OSPF6_OPT_ISSET (oi->area->options, OSPF6_OPT_E))
! 293: {
! 294: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 295: zlog_debug ("E-bit mismatch");
! 296: return;
! 297: }
! 298:
! 299: /* Find neighbor, create if not exist */
! 300: on = ospf6_neighbor_lookup (oh->router_id, oi);
! 301: if (on == NULL)
! 302: {
! 303: on = ospf6_neighbor_create (oh->router_id, oi);
! 304: on->prev_drouter = on->drouter = hello->drouter;
! 305: on->prev_bdrouter = on->bdrouter = hello->bdrouter;
! 306: on->priority = hello->priority;
! 307: }
! 308:
! 309: /* always override neighbor's source address and ifindex */
! 310: on->ifindex = ntohl (hello->interface_id);
! 311: memcpy (&on->linklocal_addr, src, sizeof (struct in6_addr));
! 312:
! 313: /* TwoWay check */
! 314: for (p = (char *) ((caddr_t) hello + sizeof (struct ospf6_hello));
! 315: p + sizeof (u_int32_t) <= OSPF6_MESSAGE_END (oh);
! 316: p += sizeof (u_int32_t))
! 317: {
! 318: u_int32_t *router_id = (u_int32_t *) p;
! 319:
! 320: if (*router_id == oi->area->ospf6->router_id)
! 321: twoway++;
! 322: }
! 323:
! 324: if (p != OSPF6_MESSAGE_END (oh))
! 325: {
! 326: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 327: zlog_debug ("Trailing garbage ignored");
! 328: }
! 329:
! 330: /* RouterPriority check */
! 331: if (on->priority != hello->priority)
! 332: {
! 333: on->priority = hello->priority;
! 334: neighborchange++;
! 335: }
! 336:
! 337: /* DR check */
! 338: if (on->drouter != hello->drouter)
! 339: {
! 340: on->prev_drouter = on->drouter;
! 341: on->drouter = hello->drouter;
! 342: if (on->prev_drouter == on->router_id || on->drouter == on->router_id)
! 343: neighborchange++;
! 344: }
! 345:
! 346: /* BDR check */
! 347: if (on->bdrouter != hello->bdrouter)
! 348: {
! 349: on->prev_bdrouter = on->bdrouter;
! 350: on->bdrouter = hello->bdrouter;
! 351: if (on->prev_bdrouter == on->router_id || on->bdrouter == on->router_id)
! 352: neighborchange++;
! 353: }
! 354:
! 355: /* BackupSeen check */
! 356: if (oi->state == OSPF6_INTERFACE_WAITING)
! 357: {
! 358: if (hello->bdrouter == on->router_id)
! 359: backupseen++;
! 360: else if (hello->drouter == on->router_id && hello->bdrouter == htonl (0))
! 361: backupseen++;
! 362: }
! 363:
! 364: /* Execute neighbor events */
! 365: thread_execute (master, hello_received, on, 0);
! 366: if (twoway)
! 367: thread_execute (master, twoway_received, on, 0);
! 368: else
! 369: thread_execute (master, oneway_received, on, 0);
! 370:
! 371: /* Schedule interface events */
! 372: if (backupseen)
! 373: thread_add_event (master, backup_seen, oi, 0);
! 374: if (neighborchange)
! 375: thread_add_event (master, neighbor_change, oi, 0);
! 376: }
! 377:
! 378: static void
! 379: ospf6_dbdesc_recv_master (struct ospf6_header *oh,
! 380: struct ospf6_neighbor *on)
! 381: {
! 382: struct ospf6_dbdesc *dbdesc;
! 383: char *p;
! 384:
! 385: dbdesc = (struct ospf6_dbdesc *)
! 386: ((caddr_t) oh + sizeof (struct ospf6_header));
! 387:
! 388: if (on->state < OSPF6_NEIGHBOR_INIT)
! 389: {
! 390: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 391: zlog_debug ("Neighbor state less than Init, ignore");
! 392: return;
! 393: }
! 394:
! 395: switch (on->state)
! 396: {
! 397: case OSPF6_NEIGHBOR_TWOWAY:
! 398: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 399: zlog_debug ("Neighbor state is 2-Way, ignore");
! 400: return;
! 401:
! 402: case OSPF6_NEIGHBOR_INIT:
! 403: thread_execute (master, twoway_received, on, 0);
! 404: if (on->state != OSPF6_NEIGHBOR_EXSTART)
! 405: {
! 406: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 407: zlog_debug ("Neighbor state is not ExStart, ignore");
! 408: return;
! 409: }
! 410: /* else fall through to ExStart */
! 411:
! 412: case OSPF6_NEIGHBOR_EXSTART:
! 413: /* if neighbor obeys us as our slave, schedule negotiation_done
! 414: and process LSA Headers. Otherwise, ignore this message */
! 415: if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) &&
! 416: ! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) &&
! 417: ntohl (dbdesc->seqnum) == on->dbdesc_seqnum)
! 418: {
! 419: /* execute NegotiationDone */
! 420: thread_execute (master, negotiation_done, on, 0);
! 421:
! 422: /* Record neighbor options */
! 423: memcpy (on->options, dbdesc->options, sizeof (on->options));
! 424: }
! 425: else
! 426: {
! 427: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 428: zlog_debug ("Negotiation failed");
! 429: return;
! 430: }
! 431: /* fall through to exchange */
! 432:
! 433: case OSPF6_NEIGHBOR_EXCHANGE:
! 434: if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
! 435: {
! 436: /* Duplicated DatabaseDescription is dropped by master */
! 437: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 438: zlog_debug ("Duplicated dbdesc discarded by Master, ignore");
! 439: return;
! 440: }
! 441:
! 442: if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT))
! 443: {
! 444: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 445: zlog_debug ("Master/Slave bit mismatch");
! 446: thread_add_event (master, seqnumber_mismatch, on, 0);
! 447: return;
! 448: }
! 449:
! 450: if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT))
! 451: {
! 452: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 453: zlog_debug ("Initialize bit mismatch");
! 454: thread_add_event (master, seqnumber_mismatch, on, 0);
! 455: return;
! 456: }
! 457:
! 458: if (memcmp (on->options, dbdesc->options, sizeof (on->options)))
! 459: {
! 460: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 461: zlog_debug ("Option field mismatch");
! 462: thread_add_event (master, seqnumber_mismatch, on, 0);
! 463: return;
! 464: }
! 465:
! 466: if (ntohl (dbdesc->seqnum) != on->dbdesc_seqnum)
! 467: {
! 468: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 469: zlog_debug ("Sequence number mismatch (%#lx expected)",
! 470: (u_long) on->dbdesc_seqnum);
! 471: thread_add_event (master, seqnumber_mismatch, on, 0);
! 472: return;
! 473: }
! 474: break;
! 475:
! 476: case OSPF6_NEIGHBOR_LOADING:
! 477: case OSPF6_NEIGHBOR_FULL:
! 478: if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
! 479: {
! 480: /* Duplicated DatabaseDescription is dropped by master */
! 481: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 482: zlog_debug ("Duplicated dbdesc discarded by Master, ignore");
! 483: return;
! 484: }
! 485:
! 486: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 487: zlog_debug ("Not duplicate dbdesc in state %s",
! 488: ospf6_neighbor_state_str[on->state]);
! 489: thread_add_event (master, seqnumber_mismatch, on, 0);
! 490: return;
! 491:
! 492: default:
! 493: assert (0);
! 494: break;
! 495: }
! 496:
! 497: /* Process LSA headers */
! 498: for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
! 499: p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
! 500: p += sizeof (struct ospf6_lsa_header))
! 501: {
! 502: struct ospf6_lsa *his, *mine;
! 503: struct ospf6_lsdb *lsdb = NULL;
! 504:
! 505: his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
! 506:
! 507: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 508: zlog_debug ("%s", his->name);
! 509:
! 510: switch (OSPF6_LSA_SCOPE (his->header->type))
! 511: {
! 512: case OSPF6_SCOPE_LINKLOCAL:
! 513: lsdb = on->ospf6_if->lsdb;
! 514: break;
! 515: case OSPF6_SCOPE_AREA:
! 516: lsdb = on->ospf6_if->area->lsdb;
! 517: break;
! 518: case OSPF6_SCOPE_AS:
! 519: lsdb = on->ospf6_if->area->ospf6->lsdb;
! 520: break;
! 521: case OSPF6_SCOPE_RESERVED:
! 522: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 523: zlog_debug ("Ignoring LSA of reserved scope");
! 524: ospf6_lsa_delete (his);
! 525: continue;
! 526: break;
! 527: }
! 528:
! 529: if (ntohs (his->header->type) == OSPF6_LSTYPE_AS_EXTERNAL &&
! 530: IS_AREA_STUB (on->ospf6_if->area))
! 531: {
! 532: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 533: zlog_debug ("SeqNumMismatch (E-bit mismatch), discard");
! 534: ospf6_lsa_delete (his);
! 535: thread_add_event (master, seqnumber_mismatch, on, 0);
! 536: return;
! 537: }
! 538:
! 539: mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
! 540: his->header->adv_router, lsdb);
! 541: if (mine == NULL)
! 542: {
! 543: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 544: zlog_debug ("Add request (No database copy)");
! 545: ospf6_lsdb_add (his, on->request_list);
! 546: }
! 547: else if (ospf6_lsa_compare (his, mine) < 0)
! 548: {
! 549: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 550: zlog_debug ("Add request (Received MoreRecent)");
! 551: ospf6_lsdb_add (his, on->request_list);
! 552: }
! 553: else
! 554: {
! 555: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 556: zlog_debug ("Discard (Existing MoreRecent)");
! 557: ospf6_lsa_delete (his);
! 558: }
! 559: }
! 560:
! 561: if (p != OSPF6_MESSAGE_END (oh))
! 562: {
! 563: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 564: zlog_debug ("Trailing garbage ignored");
! 565: }
! 566:
! 567: /* Increment sequence number */
! 568: on->dbdesc_seqnum ++;
! 569:
! 570: /* schedule send lsreq */
! 571: if (on->thread_send_lsreq == NULL)
! 572: on->thread_send_lsreq =
! 573: thread_add_event (master, ospf6_lsreq_send, on, 0);
! 574:
! 575: THREAD_OFF (on->thread_send_dbdesc);
! 576:
! 577: /* More bit check */
! 578: if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) &&
! 579: ! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT))
! 580: thread_add_event (master, exchange_done, on, 0);
! 581: else
! 582: on->thread_send_dbdesc =
! 583: thread_add_event (master, ospf6_dbdesc_send_newone, on, 0);
! 584:
! 585: /* save last received dbdesc */
! 586: memcpy (&on->dbdesc_last, dbdesc, sizeof (struct ospf6_dbdesc));
! 587: }
! 588:
! 589: static void
! 590: ospf6_dbdesc_recv_slave (struct ospf6_header *oh,
! 591: struct ospf6_neighbor *on)
! 592: {
! 593: struct ospf6_dbdesc *dbdesc;
! 594: char *p;
! 595:
! 596: dbdesc = (struct ospf6_dbdesc *)
! 597: ((caddr_t) oh + sizeof (struct ospf6_header));
! 598:
! 599: if (on->state < OSPF6_NEIGHBOR_INIT)
! 600: {
! 601: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 602: zlog_debug ("Neighbor state less than Init, ignore");
! 603: return;
! 604: }
! 605:
! 606: switch (on->state)
! 607: {
! 608: case OSPF6_NEIGHBOR_TWOWAY:
! 609: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 610: zlog_debug ("Neighbor state is 2-Way, ignore");
! 611: return;
! 612:
! 613: case OSPF6_NEIGHBOR_INIT:
! 614: thread_execute (master, twoway_received, on, 0);
! 615: if (on->state != OSPF6_NEIGHBOR_EXSTART)
! 616: {
! 617: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 618: zlog_debug ("Neighbor state is not ExStart, ignore");
! 619: return;
! 620: }
! 621: /* else fall through to ExStart */
! 622:
! 623: case OSPF6_NEIGHBOR_EXSTART:
! 624: /* If the neighbor is Master, act as Slave. Schedule negotiation_done
! 625: and process LSA Headers. Otherwise, ignore this message */
! 626: if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) &&
! 627: CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) &&
! 628: CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) &&
! 629: ntohs (oh->length) == sizeof (struct ospf6_header) +
! 630: sizeof (struct ospf6_dbdesc))
! 631: {
! 632: /* set the master/slave bit to slave */
! 633: UNSET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT);
! 634:
! 635: /* set the DD sequence number to one specified by master */
! 636: on->dbdesc_seqnum = ntohl (dbdesc->seqnum);
! 637:
! 638: /* schedule NegotiationDone */
! 639: thread_execute (master, negotiation_done, on, 0);
! 640:
! 641: /* Record neighbor options */
! 642: memcpy (on->options, dbdesc->options, sizeof (on->options));
! 643: }
! 644: else
! 645: {
! 646: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 647: zlog_debug ("Negotiation failed");
! 648: return;
! 649: }
! 650: break;
! 651:
! 652: case OSPF6_NEIGHBOR_EXCHANGE:
! 653: if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
! 654: {
! 655: /* Duplicated DatabaseDescription causes slave to retransmit */
! 656: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 657: zlog_debug ("Duplicated dbdesc causes retransmit");
! 658: THREAD_OFF (on->thread_send_dbdesc);
! 659: on->thread_send_dbdesc =
! 660: thread_add_event (master, ospf6_dbdesc_send, on, 0);
! 661: return;
! 662: }
! 663:
! 664: if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT))
! 665: {
! 666: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 667: zlog_debug ("Master/Slave bit mismatch");
! 668: thread_add_event (master, seqnumber_mismatch, on, 0);
! 669: return;
! 670: }
! 671:
! 672: if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT))
! 673: {
! 674: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 675: zlog_debug ("Initialize bit mismatch");
! 676: thread_add_event (master, seqnumber_mismatch, on, 0);
! 677: return;
! 678: }
! 679:
! 680: if (memcmp (on->options, dbdesc->options, sizeof (on->options)))
! 681: {
! 682: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 683: zlog_debug ("Option field mismatch");
! 684: thread_add_event (master, seqnumber_mismatch, on, 0);
! 685: return;
! 686: }
! 687:
! 688: if (ntohl (dbdesc->seqnum) != on->dbdesc_seqnum + 1)
! 689: {
! 690: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 691: zlog_debug ("Sequence number mismatch (%#lx expected)",
! 692: (u_long) on->dbdesc_seqnum + 1);
! 693: thread_add_event (master, seqnumber_mismatch, on, 0);
! 694: return;
! 695: }
! 696: break;
! 697:
! 698: case OSPF6_NEIGHBOR_LOADING:
! 699: case OSPF6_NEIGHBOR_FULL:
! 700: if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
! 701: {
! 702: /* Duplicated DatabaseDescription causes slave to retransmit */
! 703: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 704: zlog_debug ("Duplicated dbdesc causes retransmit");
! 705: THREAD_OFF (on->thread_send_dbdesc);
! 706: on->thread_send_dbdesc =
! 707: thread_add_event (master, ospf6_dbdesc_send, on, 0);
! 708: return;
! 709: }
! 710:
! 711: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 712: zlog_debug ("Not duplicate dbdesc in state %s",
! 713: ospf6_neighbor_state_str[on->state]);
! 714: thread_add_event (master, seqnumber_mismatch, on, 0);
! 715: return;
! 716:
! 717: default:
! 718: assert (0);
! 719: break;
! 720: }
! 721:
! 722: /* Process LSA headers */
! 723: for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
! 724: p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
! 725: p += sizeof (struct ospf6_lsa_header))
! 726: {
! 727: struct ospf6_lsa *his, *mine;
! 728: struct ospf6_lsdb *lsdb = NULL;
! 729:
! 730: his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
! 731:
! 732: switch (OSPF6_LSA_SCOPE (his->header->type))
! 733: {
! 734: case OSPF6_SCOPE_LINKLOCAL:
! 735: lsdb = on->ospf6_if->lsdb;
! 736: break;
! 737: case OSPF6_SCOPE_AREA:
! 738: lsdb = on->ospf6_if->area->lsdb;
! 739: break;
! 740: case OSPF6_SCOPE_AS:
! 741: lsdb = on->ospf6_if->area->ospf6->lsdb;
! 742: break;
! 743: case OSPF6_SCOPE_RESERVED:
! 744: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 745: zlog_debug ("Ignoring LSA of reserved scope");
! 746: ospf6_lsa_delete (his);
! 747: continue;
! 748: break;
! 749: }
! 750:
! 751: if (OSPF6_LSA_SCOPE (his->header->type) == OSPF6_SCOPE_AS &&
! 752: IS_AREA_STUB (on->ospf6_if->area))
! 753: {
! 754: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 755: zlog_debug ("E-bit mismatch with LSA Headers");
! 756: ospf6_lsa_delete (his);
! 757: thread_add_event (master, seqnumber_mismatch, on, 0);
! 758: return;
! 759: }
! 760:
! 761: mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
! 762: his->header->adv_router, lsdb);
! 763: if (mine == NULL || ospf6_lsa_compare (his, mine) < 0)
! 764: {
! 765: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 766: zlog_debug ("Add request-list: %s", his->name);
! 767: ospf6_lsdb_add (his, on->request_list);
! 768: }
! 769: else
! 770: ospf6_lsa_delete (his);
! 771: }
! 772:
! 773: if (p != OSPF6_MESSAGE_END (oh))
! 774: {
! 775: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 776: zlog_debug ("Trailing garbage ignored");
! 777: }
! 778:
! 779: /* Set sequence number to Master's */
! 780: on->dbdesc_seqnum = ntohl (dbdesc->seqnum);
! 781:
! 782: /* schedule send lsreq */
! 783: if (on->thread_send_lsreq == NULL)
! 784: on->thread_send_lsreq =
! 785: thread_add_event (master, ospf6_lsreq_send, on, 0);
! 786:
! 787: THREAD_OFF (on->thread_send_dbdesc);
! 788: on->thread_send_dbdesc =
! 789: thread_add_event (master, ospf6_dbdesc_send_newone, on, 0);
! 790:
! 791: /* save last received dbdesc */
! 792: memcpy (&on->dbdesc_last, dbdesc, sizeof (struct ospf6_dbdesc));
! 793: }
! 794:
! 795: static void
! 796: ospf6_dbdesc_recv (struct in6_addr *src, struct in6_addr *dst,
! 797: struct ospf6_interface *oi, struct ospf6_header *oh)
! 798: {
! 799: struct ospf6_neighbor *on;
! 800: struct ospf6_dbdesc *dbdesc;
! 801:
! 802: on = ospf6_neighbor_lookup (oh->router_id, oi);
! 803: if (on == NULL)
! 804: {
! 805: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 806: zlog_debug ("Neighbor not found, ignore");
! 807: return;
! 808: }
! 809:
! 810: dbdesc = (struct ospf6_dbdesc *)
! 811: ((caddr_t) oh + sizeof (struct ospf6_header));
! 812:
! 813: /* Interface MTU check */
! 814: if (!oi->mtu_ignore && ntohs (dbdesc->ifmtu) != oi->ifmtu)
! 815: {
! 816: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 817: zlog_debug ("I/F MTU mismatch");
! 818: return;
! 819: }
! 820:
! 821: if (dbdesc->reserved1 || dbdesc->reserved2)
! 822: {
! 823: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 824: zlog_debug ("Non-0 reserved field in %s's DbDesc, correct",
! 825: on->name);
! 826: dbdesc->reserved1 = 0;
! 827: dbdesc->reserved2 = 0;
! 828: }
! 829:
! 830: if (ntohl (oh->router_id) < ntohl (ospf6->router_id))
! 831: ospf6_dbdesc_recv_master (oh, on);
! 832: else if (ntohl (ospf6->router_id) < ntohl (oh->router_id))
! 833: ospf6_dbdesc_recv_slave (oh, on);
! 834: else
! 835: {
! 836: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 837: zlog_debug ("Can't decide which is master, ignore");
! 838: }
! 839: }
! 840:
! 841: static void
! 842: ospf6_lsreq_recv (struct in6_addr *src, struct in6_addr *dst,
! 843: struct ospf6_interface *oi, struct ospf6_header *oh)
! 844: {
! 845: struct ospf6_neighbor *on;
! 846: char *p;
! 847: struct ospf6_lsreq_entry *e;
! 848: struct ospf6_lsdb *lsdb = NULL;
! 849: struct ospf6_lsa *lsa;
! 850:
! 851: on = ospf6_neighbor_lookup (oh->router_id, oi);
! 852: if (on == NULL)
! 853: {
! 854: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 855: zlog_debug ("Neighbor not found, ignore");
! 856: return;
! 857: }
! 858:
! 859: if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
! 860: on->state != OSPF6_NEIGHBOR_LOADING &&
! 861: on->state != OSPF6_NEIGHBOR_FULL)
! 862: {
! 863: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 864: zlog_debug ("Neighbor state less than Exchange, ignore");
! 865: return;
! 866: }
! 867:
! 868: /* Process each request */
! 869: for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
! 870: p + sizeof (struct ospf6_lsreq_entry) <= OSPF6_MESSAGE_END (oh);
! 871: p += sizeof (struct ospf6_lsreq_entry))
! 872: {
! 873: e = (struct ospf6_lsreq_entry *) p;
! 874:
! 875: switch (OSPF6_LSA_SCOPE (e->type))
! 876: {
! 877: case OSPF6_SCOPE_LINKLOCAL:
! 878: lsdb = on->ospf6_if->lsdb;
! 879: break;
! 880: case OSPF6_SCOPE_AREA:
! 881: lsdb = on->ospf6_if->area->lsdb;
! 882: break;
! 883: case OSPF6_SCOPE_AS:
! 884: lsdb = on->ospf6_if->area->ospf6->lsdb;
! 885: break;
! 886: default:
! 887: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 888: zlog_debug ("Ignoring LSA of reserved scope");
! 889: continue;
! 890: break;
! 891: }
! 892:
! 893: /* Find database copy */
! 894: lsa = ospf6_lsdb_lookup (e->type, e->id, e->adv_router, lsdb);
! 895: if (lsa == NULL)
! 896: {
! 897: char id[16], adv_router[16];
! 898: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 899: {
! 900: inet_ntop (AF_INET, &e->id, id, sizeof (id));
! 901: inet_ntop (AF_INET, &e->adv_router, adv_router,
! 902: sizeof (adv_router));
! 903: zlog_debug ("Can't find requested [%s Id:%s Adv:%s]",
! 904: ospf6_lstype_name (e->type), id, adv_router);
! 905: }
! 906: thread_add_event (master, bad_lsreq, on, 0);
! 907: return;
! 908: }
! 909:
! 910: ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->lsupdate_list);
! 911: }
! 912:
! 913: if (p != OSPF6_MESSAGE_END (oh))
! 914: {
! 915: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 916: zlog_debug ("Trailing garbage ignored");
! 917: }
! 918:
! 919: /* schedule send lsupdate */
! 920: THREAD_OFF (on->thread_send_lsupdate);
! 921: on->thread_send_lsupdate =
! 922: thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
! 923: }
! 924:
! 925: /* Verify, that the specified memory area contains exactly N valid IPv6
! 926: prefixes as specified by RFC5340, A.4.1. */
! 927: static unsigned
! 928: ospf6_prefixes_examin
! 929: (
! 930: struct ospf6_prefix *current, /* start of buffer */
! 931: unsigned length,
! 932: const u_int32_t req_num_pfxs /* always compared with the actual number of prefixes */
! 933: )
! 934: {
! 935: u_char requested_pfx_bytes;
! 936: u_int32_t real_num_pfxs = 0;
! 937:
! 938: while (length)
! 939: {
! 940: if (length < OSPF6_PREFIX_MIN_SIZE)
! 941: {
! 942: if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
! 943: zlog_debug ("%s: undersized IPv6 prefix header", __func__);
! 944: return MSG_NG;
! 945: }
! 946: /* safe to look deeper */
! 947: if (current->prefix_length > IPV6_MAX_BITLEN)
! 948: {
! 949: if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
! 950: zlog_debug ("%s: invalid PrefixLength (%u bits)", __func__, current->prefix_length);
! 951: return MSG_NG;
! 952: }
! 953: /* covers both fixed- and variable-sized fields */
! 954: requested_pfx_bytes = OSPF6_PREFIX_MIN_SIZE + OSPF6_PREFIX_SPACE (current->prefix_length);
! 955: if (requested_pfx_bytes > length)
! 956: {
! 957: if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
! 958: zlog_debug ("%s: undersized IPv6 prefix", __func__);
! 959: return MSG_NG;
! 960: }
! 961: /* next prefix */
! 962: length -= requested_pfx_bytes;
! 963: current = (struct ospf6_prefix *) ((caddr_t) current + requested_pfx_bytes);
! 964: real_num_pfxs++;
! 965: }
! 966: if (real_num_pfxs != req_num_pfxs)
! 967: {
! 968: if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
! 969: zlog_debug ("%s: IPv6 prefix number mismatch (%u required, %u real)",
! 970: __func__, req_num_pfxs, real_num_pfxs);
! 971: return MSG_NG;
! 972: }
! 973: return MSG_OK;
! 974: }
! 975:
! 976: /* Verify an LSA to have a valid length and dispatch further (where
! 977: appropriate) to check if the contents, including nested IPv6 prefixes,
! 978: is properly sized/aligned within the LSA. Note that this function gets
! 979: LSA type in network byte order, uses in host byte order and passes to
! 980: ospf6_lstype_name() in network byte order again. */
! 981: static unsigned
! 982: ospf6_lsa_examin (struct ospf6_lsa_header *lsah, const u_int16_t lsalen, const u_char headeronly)
! 983: {
! 984: struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
! 985: struct ospf6_as_external_lsa *as_external_lsa;
! 986: struct ospf6_link_lsa *link_lsa;
! 987: unsigned exp_length;
! 988: u_int8_t ltindex;
! 989: u_int16_t lsatype;
! 990:
! 991: /* In case an additional minimum length constraint is defined for current
! 992: LSA type, make sure that this constraint is met. */
! 993: lsatype = ntohs (lsah->type);
! 994: ltindex = lsatype & OSPF6_LSTYPE_FCODE_MASK;
! 995: if
! 996: (
! 997: ltindex < OSPF6_LSTYPE_SIZE &&
! 998: ospf6_lsa_minlen[ltindex] &&
! 999: lsalen < ospf6_lsa_minlen[ltindex] + OSPF6_LSA_HEADER_SIZE
! 1000: )
! 1001: {
! 1002: if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
! 1003: zlog_debug ("%s: undersized (%u B) LSA", __func__, lsalen);
! 1004: return MSG_NG;
! 1005: }
! 1006: switch (lsatype)
! 1007: {
! 1008: case OSPF6_LSTYPE_ROUTER:
! 1009: /* RFC5340 A.4.3, LSA header + OSPF6_ROUTER_LSA_MIN_SIZE bytes followed
! 1010: by N>=0 interface descriptions. */
! 1011: if ((lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_ROUTER_LSA_MIN_SIZE) % OSPF6_ROUTER_LSDESC_FIX_SIZE)
! 1012: {
! 1013: if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
! 1014: zlog_debug ("%s: interface description alignment error", __func__);
! 1015: return MSG_NG;
! 1016: }
! 1017: break;
! 1018: case OSPF6_LSTYPE_NETWORK:
! 1019: /* RFC5340 A.4.4, LSA header + OSPF6_NETWORK_LSA_MIN_SIZE bytes
! 1020: followed by N>=0 attached router descriptions. */
! 1021: if ((lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_NETWORK_LSA_MIN_SIZE) % OSPF6_NETWORK_LSDESC_FIX_SIZE)
! 1022: {
! 1023: if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
! 1024: zlog_debug ("%s: router description alignment error", __func__);
! 1025: return MSG_NG;
! 1026: }
! 1027: break;
! 1028: case OSPF6_LSTYPE_INTER_PREFIX:
! 1029: /* RFC5340 A.4.5, LSA header + OSPF6_INTER_PREFIX_LSA_MIN_SIZE bytes
! 1030: followed by 3-4 fields of a single IPv6 prefix. */
! 1031: if (headeronly)
! 1032: break;
! 1033: return ospf6_prefixes_examin
! 1034: (
! 1035: (struct ospf6_prefix *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE + OSPF6_INTER_PREFIX_LSA_MIN_SIZE),
! 1036: lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_INTER_PREFIX_LSA_MIN_SIZE,
! 1037: 1
! 1038: );
! 1039: case OSPF6_LSTYPE_INTER_ROUTER:
! 1040: /* RFC5340 A.4.6, fixed-size LSA. */
! 1041: if (lsalen > OSPF6_LSA_HEADER_SIZE + OSPF6_INTER_ROUTER_LSA_FIX_SIZE)
! 1042: {
! 1043: if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
! 1044: zlog_debug ("%s: oversized (%u B) LSA", __func__, lsalen);
! 1045: return MSG_NG;
! 1046: }
! 1047: break;
! 1048: case OSPF6_LSTYPE_AS_EXTERNAL: /* RFC5340 A.4.7, same as A.4.8. */
! 1049: case OSPF6_LSTYPE_TYPE_7:
! 1050: /* RFC5340 A.4.8, LSA header + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE bytes
! 1051: followed by 3-4 fields of IPv6 prefix and 3 conditional LSA fields:
! 1052: 16 bytes of forwarding address, 4 bytes of external route tag,
! 1053: 4 bytes of referenced link state ID. */
! 1054: if (headeronly)
! 1055: break;
! 1056: as_external_lsa = (struct ospf6_as_external_lsa *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE);
! 1057: exp_length = OSPF6_LSA_HEADER_SIZE + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE;
! 1058: /* To find out if the last optional field (Referenced Link State ID) is
! 1059: assumed in this LSA, we need to access fixed fields of the IPv6
! 1060: prefix before ospf6_prefix_examin() confirms its sizing. */
! 1061: if (exp_length + OSPF6_PREFIX_MIN_SIZE > lsalen)
! 1062: {
! 1063: if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
! 1064: zlog_debug ("%s: undersized (%u B) LSA header", __func__, lsalen);
! 1065: return MSG_NG;
! 1066: }
! 1067: /* forwarding address */
! 1068: if (CHECK_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F))
! 1069: exp_length += 16;
! 1070: /* external route tag */
! 1071: if (CHECK_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T))
! 1072: exp_length += 4;
! 1073: /* referenced link state ID */
! 1074: if (as_external_lsa->prefix.u._prefix_referenced_lstype)
! 1075: exp_length += 4;
! 1076: /* All the fixed-size fields (mandatory and optional) must fit. I.e.,
! 1077: this check does not include any IPv6 prefix fields. */
! 1078: if (exp_length > lsalen)
! 1079: {
! 1080: if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
! 1081: zlog_debug ("%s: undersized (%u B) LSA header", __func__, lsalen);
! 1082: return MSG_NG;
! 1083: }
! 1084: /* The last call completely covers the remainder (IPv6 prefix). */
! 1085: return ospf6_prefixes_examin
! 1086: (
! 1087: (struct ospf6_prefix *) ((caddr_t) as_external_lsa + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE),
! 1088: lsalen - exp_length,
! 1089: 1
! 1090: );
! 1091: case OSPF6_LSTYPE_LINK:
! 1092: /* RFC5340 A.4.9, LSA header + OSPF6_LINK_LSA_MIN_SIZE bytes followed
! 1093: by N>=0 IPv6 prefix blocks (with N declared beforehand). */
! 1094: if (headeronly)
! 1095: break;
! 1096: link_lsa = (struct ospf6_link_lsa *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE);
! 1097: return ospf6_prefixes_examin
! 1098: (
! 1099: (struct ospf6_prefix *) ((caddr_t) link_lsa + OSPF6_LINK_LSA_MIN_SIZE),
! 1100: lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_LINK_LSA_MIN_SIZE,
! 1101: ntohl (link_lsa->prefix_num) /* 32 bits */
! 1102: );
! 1103: case OSPF6_LSTYPE_INTRA_PREFIX:
! 1104: /* RFC5340 A.4.10, LSA header + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE bytes
! 1105: followed by N>=0 IPv6 prefixes (with N declared beforehand). */
! 1106: if (headeronly)
! 1107: break;
! 1108: intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE);
! 1109: return ospf6_prefixes_examin
! 1110: (
! 1111: (struct ospf6_prefix *) ((caddr_t) intra_prefix_lsa + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE),
! 1112: lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_INTRA_PREFIX_LSA_MIN_SIZE,
! 1113: ntohs (intra_prefix_lsa->prefix_num) /* 16 bits */
! 1114: );
! 1115: }
! 1116: /* No additional validation is possible for unknown LSA types, which are
! 1117: themselves valid in OPSFv3, hence the default decision is to accept. */
! 1118: return MSG_OK;
! 1119: }
! 1120:
! 1121: /* Verify if the provided input buffer is a valid sequence of LSAs. This
! 1122: includes verification of LSA blocks length/alignment and dispatching
! 1123: of deeper-level checks. */
! 1124: static unsigned
! 1125: ospf6_lsaseq_examin
! 1126: (
! 1127: struct ospf6_lsa_header *lsah, /* start of buffered data */
! 1128: size_t length,
! 1129: const u_char headeronly,
! 1130: /* When declared_num_lsas is not 0, compare it to the real number of LSAs
! 1131: and treat the difference as an error. */
! 1132: const u_int32_t declared_num_lsas
! 1133: )
! 1134: {
! 1135: u_int32_t counted_lsas = 0;
! 1136:
! 1137: while (length)
! 1138: {
! 1139: u_int16_t lsalen;
! 1140: if (length < OSPF6_LSA_HEADER_SIZE)
! 1141: {
! 1142: if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
! 1143: zlog_debug ("%s: undersized (%u B) trailing (#%u) LSA header",
! 1144: __func__, length, counted_lsas);
! 1145: return MSG_NG;
! 1146: }
! 1147: /* save on ntohs() calls here and in the LSA validator */
! 1148: lsalen = OSPF6_LSA_SIZE (lsah);
! 1149: if (lsalen < OSPF6_LSA_HEADER_SIZE)
! 1150: {
! 1151: if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
! 1152: zlog_debug ("%s: malformed LSA header #%u, declared length is %u B",
! 1153: __func__, counted_lsas, lsalen);
! 1154: return MSG_NG;
! 1155: }
! 1156: if (headeronly)
! 1157: {
! 1158: /* less checks here and in ospf6_lsa_examin() */
! 1159: if (MSG_OK != ospf6_lsa_examin (lsah, lsalen, 1))
! 1160: {
! 1161: if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
! 1162: zlog_debug ("%s: anomaly in header-only %s LSA #%u", __func__,
! 1163: ospf6_lstype_name (lsah->type), counted_lsas);
! 1164: return MSG_NG;
! 1165: }
! 1166: lsah = (struct ospf6_lsa_header *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE);
! 1167: length -= OSPF6_LSA_HEADER_SIZE;
! 1168: }
! 1169: else
! 1170: {
! 1171: /* make sure the input buffer is deep enough before further checks */
! 1172: if (lsalen > length)
! 1173: {
! 1174: if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
! 1175: zlog_debug ("%s: anomaly in %s LSA #%u: declared length is %u B, buffered length is %u B",
! 1176: __func__, ospf6_lstype_name (lsah->type), counted_lsas, lsalen, length);
! 1177: return MSG_NG;
! 1178: }
! 1179: if (MSG_OK != ospf6_lsa_examin (lsah, lsalen, 0))
! 1180: {
! 1181: if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
! 1182: zlog_debug ("%s: anomaly in %s LSA #%u", __func__,
! 1183: ospf6_lstype_name (lsah->type), counted_lsas);
! 1184: return MSG_NG;
! 1185: }
! 1186: lsah = (struct ospf6_lsa_header *) ((caddr_t) lsah + lsalen);
! 1187: length -= lsalen;
! 1188: }
! 1189: counted_lsas++;
! 1190: }
! 1191:
! 1192: if (declared_num_lsas && counted_lsas != declared_num_lsas)
! 1193: {
! 1194: if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
! 1195: zlog_debug ("%s: #LSAs declared (%u) does not match actual (%u)",
! 1196: __func__, declared_num_lsas, counted_lsas);
! 1197: return MSG_NG;
! 1198: }
! 1199: return MSG_OK;
! 1200: }
! 1201:
! 1202: /* Verify a complete OSPF packet for proper sizing/alignment. */
! 1203: static unsigned
! 1204: ospf6_packet_examin (struct ospf6_header *oh, const unsigned bytesonwire)
! 1205: {
! 1206: struct ospf6_lsupdate *lsupd;
! 1207: unsigned test;
! 1208:
! 1209: /* length, 1st approximation */
! 1210: if (bytesonwire < OSPF6_HEADER_SIZE)
! 1211: {
! 1212: if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
! 1213: zlog_debug ("%s: undersized (%u B) packet", __func__, bytesonwire);
! 1214: return MSG_NG;
! 1215: }
! 1216: /* Now it is safe to access header fields. */
! 1217: if (bytesonwire != ntohs (oh->length))
! 1218: {
! 1219: if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
! 1220: zlog_debug ("%s: packet length error (%u real, %u declared)",
! 1221: __func__, bytesonwire, ntohs (oh->length));
! 1222: return MSG_NG;
! 1223: }
! 1224: /* version check */
! 1225: if (oh->version != OSPFV3_VERSION)
! 1226: {
! 1227: if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
! 1228: zlog_debug ("%s: invalid (%u) protocol version", __func__, oh->version);
! 1229: return MSG_NG;
! 1230: }
! 1231: /* length, 2nd approximation */
! 1232: if
! 1233: (
! 1234: oh->type < OSPF6_MESSAGE_TYPE_ALL &&
! 1235: ospf6_packet_minlen[oh->type] &&
! 1236: bytesonwire < OSPF6_HEADER_SIZE + ospf6_packet_minlen[oh->type]
! 1237: )
! 1238: {
! 1239: if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
! 1240: zlog_debug ("%s: undersized (%u B) %s packet", __func__,
! 1241: bytesonwire, ospf6_message_type_str[oh->type]);
! 1242: return MSG_NG;
! 1243: }
! 1244: /* type-specific deeper validation */
! 1245: switch (oh->type)
! 1246: {
! 1247: case OSPF6_MESSAGE_TYPE_HELLO:
! 1248: /* RFC5340 A.3.2, packet header + OSPF6_HELLO_MIN_SIZE bytes followed
! 1249: by N>=0 router-IDs. */
! 1250: if (0 == (bytesonwire - OSPF6_HEADER_SIZE - OSPF6_HELLO_MIN_SIZE) % 4)
! 1251: return MSG_OK;
! 1252: if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
! 1253: zlog_debug ("%s: alignment error in %s packet",
! 1254: __func__, ospf6_message_type_str[oh->type]);
! 1255: return MSG_NG;
! 1256: case OSPF6_MESSAGE_TYPE_DBDESC:
! 1257: /* RFC5340 A.3.3, packet header + OSPF6_DB_DESC_MIN_SIZE bytes followed
! 1258: by N>=0 header-only LSAs. */
! 1259: test = ospf6_lsaseq_examin
! 1260: (
! 1261: (struct ospf6_lsa_header *) ((caddr_t) oh + OSPF6_HEADER_SIZE + OSPF6_DB_DESC_MIN_SIZE),
! 1262: bytesonwire - OSPF6_HEADER_SIZE - OSPF6_DB_DESC_MIN_SIZE,
! 1263: 1,
! 1264: 0
! 1265: );
! 1266: break;
! 1267: case OSPF6_MESSAGE_TYPE_LSREQ:
! 1268: /* RFC5340 A.3.4, packet header + N>=0 LS description blocks. */
! 1269: if (0 == (bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_REQ_MIN_SIZE) % OSPF6_LSREQ_LSDESC_FIX_SIZE)
! 1270: return MSG_OK;
! 1271: if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
! 1272: zlog_debug ("%s: alignment error in %s packet",
! 1273: __func__, ospf6_message_type_str[oh->type]);
! 1274: return MSG_NG;
! 1275: case OSPF6_MESSAGE_TYPE_LSUPDATE:
! 1276: /* RFC5340 A.3.5, packet header + OSPF6_LS_UPD_MIN_SIZE bytes followed
! 1277: by N>=0 full LSAs (with N declared beforehand). */
! 1278: lsupd = (struct ospf6_lsupdate *) ((caddr_t) oh + OSPF6_HEADER_SIZE);
! 1279: test = ospf6_lsaseq_examin
! 1280: (
! 1281: (struct ospf6_lsa_header *) ((caddr_t) lsupd + OSPF6_LS_UPD_MIN_SIZE),
! 1282: bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_UPD_MIN_SIZE,
! 1283: 0,
! 1284: ntohl (lsupd->lsa_number) /* 32 bits */
! 1285: );
! 1286: break;
! 1287: case OSPF6_MESSAGE_TYPE_LSACK:
! 1288: /* RFC5340 A.3.6, packet header + N>=0 header-only LSAs. */
! 1289: test = ospf6_lsaseq_examin
! 1290: (
! 1291: (struct ospf6_lsa_header *) ((caddr_t) oh + OSPF6_HEADER_SIZE + OSPF6_LS_ACK_MIN_SIZE),
! 1292: bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_ACK_MIN_SIZE,
! 1293: 1,
! 1294: 0
! 1295: );
! 1296: break;
! 1297: default:
! 1298: if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
! 1299: zlog_debug ("%s: invalid (%u) message type", __func__, oh->type);
! 1300: return MSG_NG;
! 1301: }
! 1302: if (test != MSG_OK && IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
! 1303: zlog_debug ("%s: anomaly in %s packet", __func__, ospf6_message_type_str[oh->type]);
! 1304: return test;
! 1305: }
! 1306:
! 1307: /* Verify particular fields of otherwise correct received OSPF packet to
! 1308: meet the requirements of RFC. */
! 1309: static int
! 1310: ospf6_rxpacket_examin (struct ospf6_interface *oi, struct ospf6_header *oh, const unsigned bytesonwire)
! 1311: {
! 1312: char buf[2][INET_ADDRSTRLEN];
! 1313:
! 1314: if (MSG_OK != ospf6_packet_examin (oh, bytesonwire))
! 1315: return MSG_NG;
! 1316:
! 1317: /* Area-ID check */
! 1318: if (oh->area_id != oi->area->area_id)
! 1319: {
! 1320: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 1321: {
! 1322: if (oh->area_id == BACKBONE_AREA_ID)
! 1323: zlog_debug ("%s: Message may be via Virtual Link: not supported", __func__);
! 1324: else
! 1325: zlog_debug
! 1326: (
! 1327: "%s: Area-ID mismatch (my %s, rcvd %s)", __func__,
! 1328: inet_ntop (AF_INET, &oi->area->area_id, buf[0], INET_ADDRSTRLEN),
! 1329: inet_ntop (AF_INET, &oh->area_id, buf[1], INET_ADDRSTRLEN)
! 1330: );
! 1331: }
! 1332: return MSG_NG;
! 1333: }
! 1334:
! 1335: /* Instance-ID check */
! 1336: if (oh->instance_id != oi->instance_id)
! 1337: {
! 1338: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 1339: zlog_debug ("%s: Instance-ID mismatch (my %u, rcvd %u)", __func__, oi->instance_id, oh->instance_id);
! 1340: return MSG_NG;
! 1341: }
! 1342:
! 1343: /* Router-ID check */
! 1344: if (oh->router_id == oi->area->ospf6->router_id)
! 1345: {
! 1346: zlog_warn ("%s: Duplicate Router-ID (%s)", __func__, inet_ntop (AF_INET, &oh->router_id, buf[0], INET_ADDRSTRLEN));
! 1347: return MSG_NG;
! 1348: }
! 1349: return MSG_OK;
! 1350: }
! 1351:
! 1352: static void
! 1353: ospf6_lsupdate_recv (struct in6_addr *src, struct in6_addr *dst,
! 1354: struct ospf6_interface *oi, struct ospf6_header *oh)
! 1355: {
! 1356: struct ospf6_neighbor *on;
! 1357: struct ospf6_lsupdate *lsupdate;
! 1358: unsigned long num;
! 1359: char *p;
! 1360:
! 1361: on = ospf6_neighbor_lookup (oh->router_id, oi);
! 1362: if (on == NULL)
! 1363: {
! 1364: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 1365: zlog_debug ("Neighbor not found, ignore");
! 1366: return;
! 1367: }
! 1368:
! 1369: if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
! 1370: on->state != OSPF6_NEIGHBOR_LOADING &&
! 1371: on->state != OSPF6_NEIGHBOR_FULL)
! 1372: {
! 1373: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 1374: zlog_debug ("Neighbor state less than Exchange, ignore");
! 1375: return;
! 1376: }
! 1377:
! 1378: lsupdate = (struct ospf6_lsupdate *)
! 1379: ((caddr_t) oh + sizeof (struct ospf6_header));
! 1380:
! 1381: num = ntohl (lsupdate->lsa_number);
! 1382:
! 1383: /* Process LSAs */
! 1384: for (p = (char *) ((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
! 1385: p < OSPF6_MESSAGE_END (oh) &&
! 1386: p + OSPF6_LSA_SIZE (p) <= OSPF6_MESSAGE_END (oh);
! 1387: p += OSPF6_LSA_SIZE (p))
! 1388: {
! 1389: if (num == 0)
! 1390: break;
! 1391: if (OSPF6_LSA_SIZE (p) < sizeof (struct ospf6_lsa_header))
! 1392: {
! 1393: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 1394: zlog_debug ("Malformed LSA length, quit processing");
! 1395: break;
! 1396: }
! 1397:
! 1398: ospf6_receive_lsa (on, (struct ospf6_lsa_header *) p);
! 1399: num--;
! 1400: }
! 1401:
! 1402: if (num != 0)
! 1403: {
! 1404: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 1405: zlog_debug ("Malformed LSA number or LSA length");
! 1406: }
! 1407: if (p != OSPF6_MESSAGE_END (oh))
! 1408: {
! 1409: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 1410: zlog_debug ("Trailing garbage ignored");
! 1411: }
! 1412:
! 1413: /* RFC2328 Section 10.9: When the neighbor responds to these requests
! 1414: with the proper Link State Update packet(s), the Link state request
! 1415: list is truncated and a new Link State Request packet is sent. */
! 1416: /* send new Link State Request packet if this LS Update packet
! 1417: can be recognized as a response to our previous LS Request */
! 1418: if (! IN6_IS_ADDR_MULTICAST (dst) &&
! 1419: (on->state == OSPF6_NEIGHBOR_EXCHANGE ||
! 1420: on->state == OSPF6_NEIGHBOR_LOADING))
! 1421: {
! 1422: THREAD_OFF (on->thread_send_lsreq);
! 1423: on->thread_send_lsreq =
! 1424: thread_add_event (master, ospf6_lsreq_send, on, 0);
! 1425: }
! 1426: }
! 1427:
! 1428: static void
! 1429: ospf6_lsack_recv (struct in6_addr *src, struct in6_addr *dst,
! 1430: struct ospf6_interface *oi, struct ospf6_header *oh)
! 1431: {
! 1432: struct ospf6_neighbor *on;
! 1433: char *p;
! 1434: struct ospf6_lsa *his, *mine;
! 1435: struct ospf6_lsdb *lsdb = NULL;
! 1436:
! 1437: assert (oh->type == OSPF6_MESSAGE_TYPE_LSACK);
! 1438:
! 1439: on = ospf6_neighbor_lookup (oh->router_id, oi);
! 1440: if (on == NULL)
! 1441: {
! 1442: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 1443: zlog_debug ("Neighbor not found, ignore");
! 1444: return;
! 1445: }
! 1446:
! 1447: if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
! 1448: on->state != OSPF6_NEIGHBOR_LOADING &&
! 1449: on->state != OSPF6_NEIGHBOR_FULL)
! 1450: {
! 1451: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 1452: zlog_debug ("Neighbor state less than Exchange, ignore");
! 1453: return;
! 1454: }
! 1455:
! 1456: for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
! 1457: p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
! 1458: p += sizeof (struct ospf6_lsa_header))
! 1459: {
! 1460: his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
! 1461:
! 1462: switch (OSPF6_LSA_SCOPE (his->header->type))
! 1463: {
! 1464: case OSPF6_SCOPE_LINKLOCAL:
! 1465: lsdb = on->ospf6_if->lsdb;
! 1466: break;
! 1467: case OSPF6_SCOPE_AREA:
! 1468: lsdb = on->ospf6_if->area->lsdb;
! 1469: break;
! 1470: case OSPF6_SCOPE_AS:
! 1471: lsdb = on->ospf6_if->area->ospf6->lsdb;
! 1472: break;
! 1473: case OSPF6_SCOPE_RESERVED:
! 1474: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 1475: zlog_debug ("Ignoring LSA of reserved scope");
! 1476: ospf6_lsa_delete (his);
! 1477: continue;
! 1478: break;
! 1479: }
! 1480:
! 1481: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 1482: zlog_debug ("%s acknowledged by %s", his->name, on->name);
! 1483:
! 1484: /* Find database copy */
! 1485: mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
! 1486: his->header->adv_router, lsdb);
! 1487: if (mine == NULL)
! 1488: {
! 1489: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 1490: zlog_debug ("No database copy");
! 1491: ospf6_lsa_delete (his);
! 1492: continue;
! 1493: }
! 1494:
! 1495: /* Check if the LSA is on his retrans-list */
! 1496: mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
! 1497: his->header->adv_router, on->retrans_list);
! 1498: if (mine == NULL)
! 1499: {
! 1500: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 1501: zlog_debug ("Not on %s's retrans-list", on->name);
! 1502: ospf6_lsa_delete (his);
! 1503: continue;
! 1504: }
! 1505:
! 1506: if (ospf6_lsa_compare (his, mine) != 0)
! 1507: {
! 1508: /* Log this questionable acknowledgement,
! 1509: and examine the next one. */
! 1510: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 1511: zlog_debug ("Questionable acknowledgement");
! 1512: ospf6_lsa_delete (his);
! 1513: continue;
! 1514: }
! 1515:
! 1516: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 1517: zlog_debug ("Acknowledged, remove from %s's retrans-list",
! 1518: on->name);
! 1519:
! 1520: ospf6_decrement_retrans_count (mine);
! 1521: if (OSPF6_LSA_IS_MAXAGE (mine))
! 1522: ospf6_maxage_remove (on->ospf6_if->area->ospf6);
! 1523: ospf6_lsdb_remove (mine, on->retrans_list);
! 1524: ospf6_lsa_delete (his);
! 1525: }
! 1526:
! 1527: if (p != OSPF6_MESSAGE_END (oh))
! 1528: {
! 1529: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 1530: zlog_debug ("Trailing garbage ignored");
! 1531: }
! 1532: }
! 1533:
! 1534: static u_char *recvbuf = NULL;
! 1535: static u_char *sendbuf = NULL;
! 1536: static unsigned int iobuflen = 0;
! 1537:
! 1538: int
! 1539: ospf6_iobuf_size (unsigned int size)
! 1540: {
! 1541: u_char *recvnew, *sendnew;
! 1542:
! 1543: if (size <= iobuflen)
! 1544: return iobuflen;
! 1545:
! 1546: recvnew = XMALLOC (MTYPE_OSPF6_MESSAGE, size);
! 1547: sendnew = XMALLOC (MTYPE_OSPF6_MESSAGE, size);
! 1548: if (recvnew == NULL || sendnew == NULL)
! 1549: {
! 1550: if (recvnew)
! 1551: XFREE (MTYPE_OSPF6_MESSAGE, recvnew);
! 1552: if (sendnew)
! 1553: XFREE (MTYPE_OSPF6_MESSAGE, sendnew);
! 1554: zlog_debug ("Could not allocate I/O buffer of size %d.", size);
! 1555: return iobuflen;
! 1556: }
! 1557:
! 1558: if (recvbuf)
! 1559: XFREE (MTYPE_OSPF6_MESSAGE, recvbuf);
! 1560: if (sendbuf)
! 1561: XFREE (MTYPE_OSPF6_MESSAGE, sendbuf);
! 1562: recvbuf = recvnew;
! 1563: sendbuf = sendnew;
! 1564: iobuflen = size;
! 1565:
! 1566: return iobuflen;
! 1567: }
! 1568:
! 1569: void
! 1570: ospf6_message_terminate (void)
! 1571: {
! 1572: if (recvbuf)
! 1573: {
! 1574: XFREE (MTYPE_OSPF6_MESSAGE, recvbuf);
! 1575: recvbuf = NULL;
! 1576: }
! 1577:
! 1578: if (sendbuf)
! 1579: {
! 1580: XFREE (MTYPE_OSPF6_MESSAGE, sendbuf);
! 1581: sendbuf = NULL;
! 1582: }
! 1583:
! 1584: iobuflen = 0;
! 1585: }
! 1586:
! 1587: int
! 1588: ospf6_receive (struct thread *thread)
! 1589: {
! 1590: int sockfd;
! 1591: unsigned int len;
! 1592: char srcname[64], dstname[64];
! 1593: struct in6_addr src, dst;
! 1594: unsigned int ifindex;
! 1595: struct iovec iovector[2];
! 1596: struct ospf6_interface *oi;
! 1597: struct ospf6_header *oh;
! 1598:
! 1599: /* add next read thread */
! 1600: sockfd = THREAD_FD (thread);
! 1601: thread_add_read (master, ospf6_receive, NULL, sockfd);
! 1602:
! 1603: /* initialize */
! 1604: memset (&src, 0, sizeof (src));
! 1605: memset (&dst, 0, sizeof (dst));
! 1606: ifindex = 0;
! 1607: memset (recvbuf, 0, iobuflen);
! 1608: iovector[0].iov_base = recvbuf;
! 1609: iovector[0].iov_len = iobuflen;
! 1610: iovector[1].iov_base = NULL;
! 1611: iovector[1].iov_len = 0;
! 1612:
! 1613: /* receive message */
! 1614: len = ospf6_recvmsg (&src, &dst, &ifindex, iovector);
! 1615: if (len > iobuflen)
! 1616: {
! 1617: zlog_err ("Excess message read");
! 1618: return 0;
! 1619: }
! 1620:
! 1621: oi = ospf6_interface_lookup_by_ifindex (ifindex);
! 1622: if (oi == NULL || oi->area == NULL)
! 1623: {
! 1624: zlog_debug ("Message received on disabled interface");
! 1625: return 0;
! 1626: }
! 1627: if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_PASSIVE))
! 1628: {
! 1629: if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
! 1630: zlog_debug ("%s: Ignore message on passive interface %s",
! 1631: __func__, oi->interface->name);
! 1632: return 0;
! 1633: }
! 1634:
! 1635: oh = (struct ospf6_header *) recvbuf;
! 1636: if (ospf6_rxpacket_examin (oi, oh, len) != MSG_OK)
! 1637: return 0;
! 1638:
! 1639: /* Being here means, that no sizing/alignment issues were detected in
! 1640: the input packet. This renders the additional checks performed below
! 1641: and also in the type-specific dispatching functions a dead code,
! 1642: which can be dismissed in a cleanup-focused review round later. */
! 1643:
! 1644: /* Log */
! 1645: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
! 1646: {
! 1647: inet_ntop (AF_INET6, &src, srcname, sizeof (srcname));
! 1648: inet_ntop (AF_INET6, &dst, dstname, sizeof (dstname));
! 1649: zlog_debug ("%s received on %s",
! 1650: OSPF6_MESSAGE_TYPE_NAME (oh->type), oi->interface->name);
! 1651: zlog_debug (" src: %s", srcname);
! 1652: zlog_debug (" dst: %s", dstname);
! 1653: if (len != ntohs (oh->length))
! 1654: zlog_debug ("Message length does not match actually received: %d", len);
! 1655:
! 1656: switch (oh->type)
! 1657: {
! 1658: case OSPF6_MESSAGE_TYPE_HELLO:
! 1659: ospf6_hello_print (oh);
! 1660: break;
! 1661: case OSPF6_MESSAGE_TYPE_DBDESC:
! 1662: ospf6_dbdesc_print (oh);
! 1663: break;
! 1664: case OSPF6_MESSAGE_TYPE_LSREQ:
! 1665: ospf6_lsreq_print (oh);
! 1666: break;
! 1667: case OSPF6_MESSAGE_TYPE_LSUPDATE:
! 1668: ospf6_lsupdate_print (oh);
! 1669: break;
! 1670: case OSPF6_MESSAGE_TYPE_LSACK:
! 1671: ospf6_lsack_print (oh);
! 1672: break;
! 1673: default:
! 1674: zlog_debug ("Unknown message");
! 1675: break;
! 1676: }
! 1677: }
! 1678:
! 1679: switch (oh->type)
! 1680: {
! 1681: case OSPF6_MESSAGE_TYPE_HELLO:
! 1682: ospf6_hello_recv (&src, &dst, oi, oh);
! 1683: break;
! 1684:
! 1685: case OSPF6_MESSAGE_TYPE_DBDESC:
! 1686: ospf6_dbdesc_recv (&src, &dst, oi, oh);
! 1687: break;
! 1688:
! 1689: case OSPF6_MESSAGE_TYPE_LSREQ:
! 1690: ospf6_lsreq_recv (&src, &dst, oi, oh);
! 1691: break;
! 1692:
! 1693: case OSPF6_MESSAGE_TYPE_LSUPDATE:
! 1694: ospf6_lsupdate_recv (&src, &dst, oi, oh);
! 1695: break;
! 1696:
! 1697: case OSPF6_MESSAGE_TYPE_LSACK:
! 1698: ospf6_lsack_recv (&src, &dst, oi, oh);
! 1699: break;
! 1700:
! 1701: default:
! 1702: if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
! 1703: zlog_debug ("Unknown message");
! 1704: break;
! 1705: }
! 1706:
! 1707: return 0;
! 1708: }
! 1709:
! 1710: static void
! 1711: ospf6_send (struct in6_addr *src, struct in6_addr *dst,
! 1712: struct ospf6_interface *oi, struct ospf6_header *oh)
! 1713: {
! 1714: int len;
! 1715: char srcname[64], dstname[64];
! 1716: struct iovec iovector[2];
! 1717:
! 1718: /* initialize */
! 1719: iovector[0].iov_base = (caddr_t) oh;
! 1720: iovector[0].iov_len = ntohs (oh->length);
! 1721: iovector[1].iov_base = NULL;
! 1722: iovector[1].iov_len = 0;
! 1723:
! 1724: /* fill OSPF header */
! 1725: oh->version = OSPFV3_VERSION;
! 1726: /* message type must be set before */
! 1727: /* message length must be set before */
! 1728: oh->router_id = oi->area->ospf6->router_id;
! 1729: oh->area_id = oi->area->area_id;
! 1730: /* checksum is calculated by kernel */
! 1731: oh->instance_id = oi->instance_id;
! 1732: oh->reserved = 0;
! 1733:
! 1734: /* Log */
! 1735: if (IS_OSPF6_DEBUG_MESSAGE (oh->type, SEND))
! 1736: {
! 1737: inet_ntop (AF_INET6, dst, dstname, sizeof (dstname));
! 1738: if (src)
! 1739: inet_ntop (AF_INET6, src, srcname, sizeof (srcname));
! 1740: else
! 1741: memset (srcname, 0, sizeof (srcname));
! 1742: zlog_debug ("%s send on %s",
! 1743: OSPF6_MESSAGE_TYPE_NAME (oh->type), oi->interface->name);
! 1744: zlog_debug (" src: %s", srcname);
! 1745: zlog_debug (" dst: %s", dstname);
! 1746:
! 1747: switch (oh->type)
! 1748: {
! 1749: case OSPF6_MESSAGE_TYPE_HELLO:
! 1750: ospf6_hello_print (oh);
! 1751: break;
! 1752: case OSPF6_MESSAGE_TYPE_DBDESC:
! 1753: ospf6_dbdesc_print (oh);
! 1754: break;
! 1755: case OSPF6_MESSAGE_TYPE_LSREQ:
! 1756: ospf6_lsreq_print (oh);
! 1757: break;
! 1758: case OSPF6_MESSAGE_TYPE_LSUPDATE:
! 1759: ospf6_lsupdate_print (oh);
! 1760: break;
! 1761: case OSPF6_MESSAGE_TYPE_LSACK:
! 1762: ospf6_lsack_print (oh);
! 1763: break;
! 1764: default:
! 1765: zlog_debug ("Unknown message");
! 1766: assert (0);
! 1767: break;
! 1768: }
! 1769: }
! 1770:
! 1771: /* send message */
! 1772: len = ospf6_sendmsg (src, dst, &oi->interface->ifindex, iovector);
! 1773: if (len != ntohs (oh->length))
! 1774: zlog_err ("Could not send entire message");
! 1775: }
! 1776:
! 1777: int
! 1778: ospf6_hello_send (struct thread *thread)
! 1779: {
! 1780: struct ospf6_interface *oi;
! 1781: struct ospf6_header *oh;
! 1782: struct ospf6_hello *hello;
! 1783: u_char *p;
! 1784: struct listnode *node, *nnode;
! 1785: struct ospf6_neighbor *on;
! 1786:
! 1787: oi = (struct ospf6_interface *) THREAD_ARG (thread);
! 1788: oi->thread_send_hello = (struct thread *) NULL;
! 1789:
! 1790: if (oi->state <= OSPF6_INTERFACE_DOWN)
! 1791: {
! 1792: if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_HELLO, SEND))
! 1793: zlog_debug ("Unable to send Hello on down interface %s",
! 1794: oi->interface->name);
! 1795: return 0;
! 1796: }
! 1797:
! 1798: /* set next thread */
! 1799: oi->thread_send_hello = thread_add_timer (master, ospf6_hello_send,
! 1800: oi, oi->hello_interval);
! 1801:
! 1802: memset (sendbuf, 0, iobuflen);
! 1803: oh = (struct ospf6_header *) sendbuf;
! 1804: hello = (struct ospf6_hello *)((caddr_t) oh + sizeof (struct ospf6_header));
! 1805:
! 1806: hello->interface_id = htonl (oi->interface->ifindex);
! 1807: hello->priority = oi->priority;
! 1808: hello->options[0] = oi->area->options[0];
! 1809: hello->options[1] = oi->area->options[1];
! 1810: hello->options[2] = oi->area->options[2];
! 1811: hello->hello_interval = htons (oi->hello_interval);
! 1812: hello->dead_interval = htons (oi->dead_interval);
! 1813: hello->drouter = oi->drouter;
! 1814: hello->bdrouter = oi->bdrouter;
! 1815:
! 1816: p = (u_char *)((caddr_t) hello + sizeof (struct ospf6_hello));
! 1817:
! 1818: for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on))
! 1819: {
! 1820: if (on->state < OSPF6_NEIGHBOR_INIT)
! 1821: continue;
! 1822:
! 1823: if (p - sendbuf + sizeof (u_int32_t) > oi->ifmtu)
! 1824: {
! 1825: if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_HELLO, SEND))
! 1826: zlog_debug ("sending Hello message: exceeds I/F MTU");
! 1827: break;
! 1828: }
! 1829:
! 1830: memcpy (p, &on->router_id, sizeof (u_int32_t));
! 1831: p += sizeof (u_int32_t);
! 1832: }
! 1833:
! 1834: oh->type = OSPF6_MESSAGE_TYPE_HELLO;
! 1835: oh->length = htons (p - sendbuf);
! 1836:
! 1837: ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
! 1838: return 0;
! 1839: }
! 1840:
! 1841: int
! 1842: ospf6_dbdesc_send (struct thread *thread)
! 1843: {
! 1844: struct ospf6_neighbor *on;
! 1845: struct ospf6_header *oh;
! 1846: struct ospf6_dbdesc *dbdesc;
! 1847: u_char *p;
! 1848: struct ospf6_lsa *lsa;
! 1849:
! 1850: on = (struct ospf6_neighbor *) THREAD_ARG (thread);
! 1851: on->thread_send_dbdesc = (struct thread *) NULL;
! 1852:
! 1853: if (on->state < OSPF6_NEIGHBOR_EXSTART)
! 1854: {
! 1855: if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_DBDESC, SEND))
! 1856: zlog_debug ("Quit to send DbDesc to neighbor %s state %s",
! 1857: on->name, ospf6_neighbor_state_str[on->state]);
! 1858: return 0;
! 1859: }
! 1860:
! 1861: /* set next thread if master */
! 1862: if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT))
! 1863: on->thread_send_dbdesc =
! 1864: thread_add_timer (master, ospf6_dbdesc_send, on,
! 1865: on->ospf6_if->rxmt_interval);
! 1866:
! 1867: memset (sendbuf, 0, iobuflen);
! 1868: oh = (struct ospf6_header *) sendbuf;
! 1869: dbdesc = (struct ospf6_dbdesc *)((caddr_t) oh +
! 1870: sizeof (struct ospf6_header));
! 1871:
! 1872: /* if this is initial one, initialize sequence number for DbDesc */
! 1873: if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT))
! 1874: {
! 1875: struct timeval tv;
! 1876: if (quagga_gettime (QUAGGA_CLK_MONOTONIC, &tv) < 0)
! 1877: tv.tv_sec = 1;
! 1878: on->dbdesc_seqnum = tv.tv_sec;
! 1879: }
! 1880:
! 1881: dbdesc->options[0] = on->ospf6_if->area->options[0];
! 1882: dbdesc->options[1] = on->ospf6_if->area->options[1];
! 1883: dbdesc->options[2] = on->ospf6_if->area->options[2];
! 1884: dbdesc->ifmtu = htons (on->ospf6_if->ifmtu);
! 1885: dbdesc->bits = on->dbdesc_bits;
! 1886: dbdesc->seqnum = htonl (on->dbdesc_seqnum);
! 1887:
! 1888: /* if this is not initial one, set LSA headers in dbdesc */
! 1889: p = (u_char *)((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
! 1890: if (! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT))
! 1891: {
! 1892: for (lsa = ospf6_lsdb_head (on->dbdesc_list); lsa;
! 1893: lsa = ospf6_lsdb_next (lsa))
! 1894: {
! 1895: ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
! 1896:
! 1897: /* MTU check */
! 1898: if (p - sendbuf + sizeof (struct ospf6_lsa_header) >
! 1899: on->ospf6_if->ifmtu)
! 1900: {
! 1901: ospf6_lsa_unlock (lsa);
! 1902: break;
! 1903: }
! 1904: memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
! 1905: p += sizeof (struct ospf6_lsa_header);
! 1906: }
! 1907: }
! 1908:
! 1909: oh->type = OSPF6_MESSAGE_TYPE_DBDESC;
! 1910: oh->length = htons (p - sendbuf);
! 1911:
! 1912: ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
! 1913: on->ospf6_if, oh);
! 1914: return 0;
! 1915: }
! 1916:
! 1917: int
! 1918: ospf6_dbdesc_send_newone (struct thread *thread)
! 1919: {
! 1920: struct ospf6_neighbor *on;
! 1921: struct ospf6_lsa *lsa;
! 1922: unsigned int size = 0;
! 1923:
! 1924: on = (struct ospf6_neighbor *) THREAD_ARG (thread);
! 1925: ospf6_lsdb_remove_all (on->dbdesc_list);
! 1926:
! 1927: /* move LSAs from summary_list to dbdesc_list (within neighbor structure)
! 1928: so that ospf6_send_dbdesc () can send those LSAs */
! 1929: size = sizeof (struct ospf6_lsa_header) + sizeof (struct ospf6_dbdesc);
! 1930: for (lsa = ospf6_lsdb_head (on->summary_list); lsa;
! 1931: lsa = ospf6_lsdb_next (lsa))
! 1932: {
! 1933: if (size + sizeof (struct ospf6_lsa_header) > on->ospf6_if->ifmtu)
! 1934: {
! 1935: ospf6_lsa_unlock (lsa);
! 1936: break;
! 1937: }
! 1938:
! 1939: ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->dbdesc_list);
! 1940: ospf6_lsdb_remove (lsa, on->summary_list);
! 1941: size += sizeof (struct ospf6_lsa_header);
! 1942: }
! 1943:
! 1944: if (on->summary_list->count == 0)
! 1945: UNSET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT);
! 1946:
! 1947: /* If slave, More bit check must be done here */
! 1948: if (! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT) && /* Slave */
! 1949: ! CHECK_FLAG (on->dbdesc_last.bits, OSPF6_DBDESC_MBIT) &&
! 1950: ! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT))
! 1951: thread_add_event (master, exchange_done, on, 0);
! 1952:
! 1953: thread_execute (master, ospf6_dbdesc_send, on, 0);
! 1954: return 0;
! 1955: }
! 1956:
! 1957: int
! 1958: ospf6_lsreq_send (struct thread *thread)
! 1959: {
! 1960: struct ospf6_neighbor *on;
! 1961: struct ospf6_header *oh;
! 1962: struct ospf6_lsreq_entry *e;
! 1963: u_char *p;
! 1964: struct ospf6_lsa *lsa;
! 1965:
! 1966: on = (struct ospf6_neighbor *) THREAD_ARG (thread);
! 1967: on->thread_send_lsreq = (struct thread *) NULL;
! 1968:
! 1969: /* LSReq will be sent only in ExStart or Loading */
! 1970: if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
! 1971: on->state != OSPF6_NEIGHBOR_LOADING)
! 1972: {
! 1973: if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSREQ, SEND))
! 1974: zlog_debug ("Quit to send LSReq to neighbor %s state %s",
! 1975: on->name, ospf6_neighbor_state_str[on->state]);
! 1976: return 0;
! 1977: }
! 1978:
! 1979: /* schedule loading_done if request list is empty */
! 1980: if (on->request_list->count == 0)
! 1981: {
! 1982: thread_add_event (master, loading_done, on, 0);
! 1983: return 0;
! 1984: }
! 1985:
! 1986: /* set next thread */
! 1987: on->thread_send_lsreq =
! 1988: thread_add_timer (master, ospf6_lsreq_send, on,
! 1989: on->ospf6_if->rxmt_interval);
! 1990:
! 1991: memset (sendbuf, 0, iobuflen);
! 1992: oh = (struct ospf6_header *) sendbuf;
! 1993:
! 1994: /* set Request entries in lsreq */
! 1995: p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
! 1996: for (lsa = ospf6_lsdb_head (on->request_list); lsa;
! 1997: lsa = ospf6_lsdb_next (lsa))
! 1998: {
! 1999: /* MTU check */
! 2000: if (p - sendbuf + sizeof (struct ospf6_lsreq_entry) > on->ospf6_if->ifmtu)
! 2001: {
! 2002: ospf6_lsa_unlock (lsa);
! 2003: break;
! 2004: }
! 2005:
! 2006: e = (struct ospf6_lsreq_entry *) p;
! 2007: e->type = lsa->header->type;
! 2008: e->id = lsa->header->id;
! 2009: e->adv_router = lsa->header->adv_router;
! 2010: p += sizeof (struct ospf6_lsreq_entry);
! 2011: }
! 2012:
! 2013: oh->type = OSPF6_MESSAGE_TYPE_LSREQ;
! 2014: oh->length = htons (p - sendbuf);
! 2015:
! 2016: ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
! 2017: on->ospf6_if, oh);
! 2018: return 0;
! 2019: }
! 2020:
! 2021: int
! 2022: ospf6_lsupdate_send_neighbor (struct thread *thread)
! 2023: {
! 2024: struct ospf6_neighbor *on;
! 2025: struct ospf6_header *oh;
! 2026: struct ospf6_lsupdate *lsupdate;
! 2027: u_char *p;
! 2028: int num;
! 2029: struct ospf6_lsa *lsa;
! 2030:
! 2031: on = (struct ospf6_neighbor *) THREAD_ARG (thread);
! 2032: on->thread_send_lsupdate = (struct thread *) NULL;
! 2033:
! 2034: if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
! 2035: zlog_debug ("LSUpdate to neighbor %s", on->name);
! 2036:
! 2037: if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
! 2038: {
! 2039: if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
! 2040: zlog_debug ("Quit to send (neighbor state %s)",
! 2041: ospf6_neighbor_state_str[on->state]);
! 2042: return 0;
! 2043: }
! 2044:
! 2045: /* if we have nothing to send, return */
! 2046: if (on->lsupdate_list->count == 0 &&
! 2047: on->retrans_list->count == 0)
! 2048: {
! 2049: if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
! 2050: zlog_debug ("Quit to send (nothing to send)");
! 2051: return 0;
! 2052: }
! 2053:
! 2054: memset (sendbuf, 0, iobuflen);
! 2055: oh = (struct ospf6_header *) sendbuf;
! 2056: lsupdate = (struct ospf6_lsupdate *)
! 2057: ((caddr_t) oh + sizeof (struct ospf6_header));
! 2058:
! 2059: p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
! 2060: num = 0;
! 2061:
! 2062: /* lsupdate_list lists those LSA which doesn't need to be
! 2063: retransmitted. remove those from the list */
! 2064: for (lsa = ospf6_lsdb_head (on->lsupdate_list); lsa;
! 2065: lsa = ospf6_lsdb_next (lsa))
! 2066: {
! 2067: /* MTU check */
! 2068: if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header))
! 2069: > on->ospf6_if->ifmtu)
! 2070: {
! 2071: ospf6_lsa_unlock (lsa);
! 2072: break;
! 2073: }
! 2074:
! 2075: ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
! 2076: memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
! 2077: p += OSPF6_LSA_SIZE (lsa->header);
! 2078: num++;
! 2079:
! 2080: assert (lsa->lock == 2);
! 2081: ospf6_lsdb_remove (lsa, on->lsupdate_list);
! 2082: }
! 2083:
! 2084: for (lsa = ospf6_lsdb_head (on->retrans_list); lsa;
! 2085: lsa = ospf6_lsdb_next (lsa))
! 2086: {
! 2087: /* MTU check */
! 2088: if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header))
! 2089: > on->ospf6_if->ifmtu)
! 2090: {
! 2091: ospf6_lsa_unlock (lsa);
! 2092: break;
! 2093: }
! 2094:
! 2095: ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
! 2096: memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
! 2097: p += OSPF6_LSA_SIZE (lsa->header);
! 2098: num++;
! 2099: }
! 2100:
! 2101: lsupdate->lsa_number = htonl (num);
! 2102:
! 2103: oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
! 2104: oh->length = htons (p - sendbuf);
! 2105:
! 2106: ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
! 2107: on->ospf6_if, oh);
! 2108:
! 2109: if (on->lsupdate_list->count != 0 ||
! 2110: on->retrans_list->count != 0)
! 2111: {
! 2112: if (on->lsupdate_list->count != 0)
! 2113: on->thread_send_lsupdate =
! 2114: thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
! 2115: else
! 2116: on->thread_send_lsupdate =
! 2117: thread_add_timer (master, ospf6_lsupdate_send_neighbor, on,
! 2118: on->ospf6_if->rxmt_interval);
! 2119: }
! 2120:
! 2121: return 0;
! 2122: }
! 2123:
! 2124: int
! 2125: ospf6_lsupdate_send_interface (struct thread *thread)
! 2126: {
! 2127: struct ospf6_interface *oi;
! 2128: struct ospf6_header *oh;
! 2129: struct ospf6_lsupdate *lsupdate;
! 2130: u_char *p;
! 2131: int num;
! 2132: struct ospf6_lsa *lsa;
! 2133:
! 2134: oi = (struct ospf6_interface *) THREAD_ARG (thread);
! 2135: oi->thread_send_lsupdate = (struct thread *) NULL;
! 2136:
! 2137: if (oi->state <= OSPF6_INTERFACE_WAITING)
! 2138: {
! 2139: if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
! 2140: zlog_debug ("Quit to send LSUpdate to interface %s state %s",
! 2141: oi->interface->name, ospf6_interface_state_str[oi->state]);
! 2142: return 0;
! 2143: }
! 2144:
! 2145: /* if we have nothing to send, return */
! 2146: if (oi->lsupdate_list->count == 0)
! 2147: return 0;
! 2148:
! 2149: memset (sendbuf, 0, iobuflen);
! 2150: oh = (struct ospf6_header *) sendbuf;
! 2151: lsupdate = (struct ospf6_lsupdate *)((caddr_t) oh +
! 2152: sizeof (struct ospf6_header));
! 2153:
! 2154: p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
! 2155: num = 0;
! 2156:
! 2157: for (lsa = ospf6_lsdb_head (oi->lsupdate_list); lsa;
! 2158: lsa = ospf6_lsdb_next (lsa))
! 2159: {
! 2160: /* MTU check */
! 2161: if ( (p - sendbuf + ((unsigned int)OSPF6_LSA_SIZE (lsa->header)))
! 2162: > oi->ifmtu)
! 2163: {
! 2164: ospf6_lsa_unlock (lsa);
! 2165: break;
! 2166: }
! 2167:
! 2168: ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
! 2169: memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
! 2170: p += OSPF6_LSA_SIZE (lsa->header);
! 2171: num++;
! 2172:
! 2173: assert (lsa->lock == 2);
! 2174: ospf6_lsdb_remove (lsa, oi->lsupdate_list);
! 2175: }
! 2176:
! 2177: lsupdate->lsa_number = htonl (num);
! 2178:
! 2179: oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
! 2180: oh->length = htons (p - sendbuf);
! 2181:
! 2182: if (oi->state == OSPF6_INTERFACE_DR ||
! 2183: oi->state == OSPF6_INTERFACE_BDR)
! 2184: ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
! 2185: else
! 2186: ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
! 2187:
! 2188: if (oi->lsupdate_list->count > 0)
! 2189: {
! 2190: oi->thread_send_lsupdate =
! 2191: thread_add_event (master, ospf6_lsupdate_send_interface, oi, 0);
! 2192: }
! 2193:
! 2194: return 0;
! 2195: }
! 2196:
! 2197: int
! 2198: ospf6_lsack_send_neighbor (struct thread *thread)
! 2199: {
! 2200: struct ospf6_neighbor *on;
! 2201: struct ospf6_header *oh;
! 2202: u_char *p;
! 2203: struct ospf6_lsa *lsa;
! 2204:
! 2205: on = (struct ospf6_neighbor *) THREAD_ARG (thread);
! 2206: on->thread_send_lsack = (struct thread *) NULL;
! 2207:
! 2208: if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
! 2209: {
! 2210: if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSACK, SEND))
! 2211: zlog_debug ("Quit to send LSAck to neighbor %s state %s",
! 2212: on->name, ospf6_neighbor_state_str[on->state]);
! 2213: return 0;
! 2214: }
! 2215:
! 2216: /* if we have nothing to send, return */
! 2217: if (on->lsack_list->count == 0)
! 2218: return 0;
! 2219:
! 2220: memset (sendbuf, 0, iobuflen);
! 2221: oh = (struct ospf6_header *) sendbuf;
! 2222:
! 2223: p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
! 2224:
! 2225: for (lsa = ospf6_lsdb_head (on->lsack_list); lsa;
! 2226: lsa = ospf6_lsdb_next (lsa))
! 2227: {
! 2228: /* MTU check */
! 2229: if (p - sendbuf + sizeof (struct ospf6_lsa_header) > on->ospf6_if->ifmtu)
! 2230: {
! 2231: /* if we run out of packet size/space here,
! 2232: better to try again soon. */
! 2233: THREAD_OFF (on->thread_send_lsack);
! 2234: on->thread_send_lsack =
! 2235: thread_add_event (master, ospf6_lsack_send_neighbor, on, 0);
! 2236:
! 2237: ospf6_lsa_unlock (lsa);
! 2238: break;
! 2239: }
! 2240:
! 2241: ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
! 2242: memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
! 2243: p += sizeof (struct ospf6_lsa_header);
! 2244:
! 2245: assert (lsa->lock == 2);
! 2246: ospf6_lsdb_remove (lsa, on->lsack_list);
! 2247: }
! 2248:
! 2249: oh->type = OSPF6_MESSAGE_TYPE_LSACK;
! 2250: oh->length = htons (p - sendbuf);
! 2251:
! 2252: ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
! 2253: on->ospf6_if, oh);
! 2254: return 0;
! 2255: }
! 2256:
! 2257: int
! 2258: ospf6_lsack_send_interface (struct thread *thread)
! 2259: {
! 2260: struct ospf6_interface *oi;
! 2261: struct ospf6_header *oh;
! 2262: u_char *p;
! 2263: struct ospf6_lsa *lsa;
! 2264:
! 2265: oi = (struct ospf6_interface *) THREAD_ARG (thread);
! 2266: oi->thread_send_lsack = (struct thread *) NULL;
! 2267:
! 2268: if (oi->state <= OSPF6_INTERFACE_WAITING)
! 2269: {
! 2270: if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSACK, SEND))
! 2271: zlog_debug ("Quit to send LSAck to interface %s state %s",
! 2272: oi->interface->name, ospf6_interface_state_str[oi->state]);
! 2273: return 0;
! 2274: }
! 2275:
! 2276: /* if we have nothing to send, return */
! 2277: if (oi->lsack_list->count == 0)
! 2278: return 0;
! 2279:
! 2280: memset (sendbuf, 0, iobuflen);
! 2281: oh = (struct ospf6_header *) sendbuf;
! 2282:
! 2283: p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
! 2284:
! 2285: for (lsa = ospf6_lsdb_head (oi->lsack_list); lsa;
! 2286: lsa = ospf6_lsdb_next (lsa))
! 2287: {
! 2288: /* MTU check */
! 2289: if (p - sendbuf + sizeof (struct ospf6_lsa_header) > oi->ifmtu)
! 2290: {
! 2291: /* if we run out of packet size/space here,
! 2292: better to try again soon. */
! 2293: THREAD_OFF (oi->thread_send_lsack);
! 2294: oi->thread_send_lsack =
! 2295: thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
! 2296:
! 2297: ospf6_lsa_unlock (lsa);
! 2298: break;
! 2299: }
! 2300:
! 2301: ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
! 2302: memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
! 2303: p += sizeof (struct ospf6_lsa_header);
! 2304:
! 2305: assert (lsa->lock == 2);
! 2306: ospf6_lsdb_remove (lsa, oi->lsack_list);
! 2307: }
! 2308:
! 2309: oh->type = OSPF6_MESSAGE_TYPE_LSACK;
! 2310: oh->length = htons (p - sendbuf);
! 2311:
! 2312: if (oi->state == OSPF6_INTERFACE_DR ||
! 2313: oi->state == OSPF6_INTERFACE_BDR)
! 2314: ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
! 2315: else
! 2316: ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
! 2317:
! 2318: if (oi->thread_send_lsack == NULL && oi->lsack_list->count > 0)
! 2319: {
! 2320: oi->thread_send_lsack =
! 2321: thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
! 2322: }
! 2323:
! 2324: return 0;
! 2325: }
! 2326:
! 2327:
! 2328: /* Commands */
! 2329: DEFUN (debug_ospf6_message,
! 2330: debug_ospf6_message_cmd,
! 2331: "debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all)",
! 2332: DEBUG_STR
! 2333: OSPF6_STR
! 2334: "Debug OSPFv3 message\n"
! 2335: "Debug Unknown message\n"
! 2336: "Debug Hello message\n"
! 2337: "Debug Database Description message\n"
! 2338: "Debug Link State Request message\n"
! 2339: "Debug Link State Update message\n"
! 2340: "Debug Link State Acknowledgement message\n"
! 2341: "Debug All message\n"
! 2342: )
! 2343: {
! 2344: unsigned char level = 0;
! 2345: int type = 0;
! 2346: int i;
! 2347:
! 2348: assert (argc > 0);
! 2349:
! 2350: /* check type */
! 2351: if (! strncmp (argv[0], "u", 1))
! 2352: type = OSPF6_MESSAGE_TYPE_UNKNOWN;
! 2353: else if (! strncmp (argv[0], "h", 1))
! 2354: type = OSPF6_MESSAGE_TYPE_HELLO;
! 2355: else if (! strncmp (argv[0], "d", 1))
! 2356: type = OSPF6_MESSAGE_TYPE_DBDESC;
! 2357: else if (! strncmp (argv[0], "lsr", 3))
! 2358: type = OSPF6_MESSAGE_TYPE_LSREQ;
! 2359: else if (! strncmp (argv[0], "lsu", 3))
! 2360: type = OSPF6_MESSAGE_TYPE_LSUPDATE;
! 2361: else if (! strncmp (argv[0], "lsa", 3))
! 2362: type = OSPF6_MESSAGE_TYPE_LSACK;
! 2363: else if (! strncmp (argv[0], "a", 1))
! 2364: type = OSPF6_MESSAGE_TYPE_ALL;
! 2365:
! 2366: if (argc == 1)
! 2367: level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
! 2368: else if (! strncmp (argv[1], "s", 1))
! 2369: level = OSPF6_DEBUG_MESSAGE_SEND;
! 2370: else if (! strncmp (argv[1], "r", 1))
! 2371: level = OSPF6_DEBUG_MESSAGE_RECV;
! 2372:
! 2373: if (type == OSPF6_MESSAGE_TYPE_ALL)
! 2374: {
! 2375: for (i = 0; i < 6; i++)
! 2376: OSPF6_DEBUG_MESSAGE_ON (i, level);
! 2377: }
! 2378: else
! 2379: OSPF6_DEBUG_MESSAGE_ON (type, level);
! 2380:
! 2381: return CMD_SUCCESS;
! 2382: }
! 2383:
! 2384: ALIAS (debug_ospf6_message,
! 2385: debug_ospf6_message_sendrecv_cmd,
! 2386: "debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all) (send|recv)",
! 2387: DEBUG_STR
! 2388: OSPF6_STR
! 2389: "Debug OSPFv3 message\n"
! 2390: "Debug Unknown message\n"
! 2391: "Debug Hello message\n"
! 2392: "Debug Database Description message\n"
! 2393: "Debug Link State Request message\n"
! 2394: "Debug Link State Update message\n"
! 2395: "Debug Link State Acknowledgement message\n"
! 2396: "Debug All message\n"
! 2397: "Debug only sending message\n"
! 2398: "Debug only receiving message\n"
! 2399: )
! 2400:
! 2401:
! 2402: DEFUN (no_debug_ospf6_message,
! 2403: no_debug_ospf6_message_cmd,
! 2404: "no debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all)",
! 2405: NO_STR
! 2406: DEBUG_STR
! 2407: OSPF6_STR
! 2408: "Debug OSPFv3 message\n"
! 2409: "Debug Unknown message\n"
! 2410: "Debug Hello message\n"
! 2411: "Debug Database Description message\n"
! 2412: "Debug Link State Request message\n"
! 2413: "Debug Link State Update message\n"
! 2414: "Debug Link State Acknowledgement message\n"
! 2415: "Debug All message\n"
! 2416: )
! 2417: {
! 2418: unsigned char level = 0;
! 2419: int type = 0;
! 2420: int i;
! 2421:
! 2422: assert (argc > 0);
! 2423:
! 2424: /* check type */
! 2425: if (! strncmp (argv[0], "u", 1))
! 2426: type = OSPF6_MESSAGE_TYPE_UNKNOWN;
! 2427: else if (! strncmp (argv[0], "h", 1))
! 2428: type = OSPF6_MESSAGE_TYPE_HELLO;
! 2429: else if (! strncmp (argv[0], "d", 1))
! 2430: type = OSPF6_MESSAGE_TYPE_DBDESC;
! 2431: else if (! strncmp (argv[0], "lsr", 3))
! 2432: type = OSPF6_MESSAGE_TYPE_LSREQ;
! 2433: else if (! strncmp (argv[0], "lsu", 3))
! 2434: type = OSPF6_MESSAGE_TYPE_LSUPDATE;
! 2435: else if (! strncmp (argv[0], "lsa", 3))
! 2436: type = OSPF6_MESSAGE_TYPE_LSACK;
! 2437: else if (! strncmp (argv[0], "a", 1))
! 2438: type = OSPF6_MESSAGE_TYPE_ALL;
! 2439:
! 2440: if (argc == 1)
! 2441: level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
! 2442: else if (! strncmp (argv[1], "s", 1))
! 2443: level = OSPF6_DEBUG_MESSAGE_SEND;
! 2444: else if (! strncmp (argv[1], "r", 1))
! 2445: level = OSPF6_DEBUG_MESSAGE_RECV;
! 2446:
! 2447: if (type == OSPF6_MESSAGE_TYPE_ALL)
! 2448: {
! 2449: for (i = 0; i < 6; i++)
! 2450: OSPF6_DEBUG_MESSAGE_OFF (i, level);
! 2451: }
! 2452: else
! 2453: OSPF6_DEBUG_MESSAGE_OFF (type, level);
! 2454:
! 2455: return CMD_SUCCESS;
! 2456: }
! 2457:
! 2458: ALIAS (no_debug_ospf6_message,
! 2459: no_debug_ospf6_message_sendrecv_cmd,
! 2460: "no debug ospf6 message "
! 2461: "(unknown|hello|dbdesc|lsreq|lsupdate|lsack|all) (send|recv)",
! 2462: NO_STR
! 2463: DEBUG_STR
! 2464: OSPF6_STR
! 2465: "Debug OSPFv3 message\n"
! 2466: "Debug Unknown message\n"
! 2467: "Debug Hello message\n"
! 2468: "Debug Database Description message\n"
! 2469: "Debug Link State Request message\n"
! 2470: "Debug Link State Update message\n"
! 2471: "Debug Link State Acknowledgement message\n"
! 2472: "Debug All message\n"
! 2473: "Debug only sending message\n"
! 2474: "Debug only receiving message\n"
! 2475: )
! 2476:
! 2477: int
! 2478: config_write_ospf6_debug_message (struct vty *vty)
! 2479: {
! 2480: const char *type_str[] = {"unknown", "hello", "dbdesc",
! 2481: "lsreq", "lsupdate", "lsack"};
! 2482: unsigned char s = 0, r = 0;
! 2483: int i;
! 2484:
! 2485: for (i = 0; i < 6; i++)
! 2486: {
! 2487: if (IS_OSPF6_DEBUG_MESSAGE (i, SEND))
! 2488: s |= 1 << i;
! 2489: if (IS_OSPF6_DEBUG_MESSAGE (i, RECV))
! 2490: r |= 1 << i;
! 2491: }
! 2492:
! 2493: if (s == 0x3f && r == 0x3f)
! 2494: {
! 2495: vty_out (vty, "debug ospf6 message all%s", VNL);
! 2496: return 0;
! 2497: }
! 2498:
! 2499: if (s == 0x3f && r == 0)
! 2500: {
! 2501: vty_out (vty, "debug ospf6 message all send%s", VNL);
! 2502: return 0;
! 2503: }
! 2504: else if (s == 0 && r == 0x3f)
! 2505: {
! 2506: vty_out (vty, "debug ospf6 message all recv%s", VNL);
! 2507: return 0;
! 2508: }
! 2509:
! 2510: /* Unknown message is logged by default */
! 2511: if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, SEND) &&
! 2512: ! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
! 2513: vty_out (vty, "no debug ospf6 message unknown%s", VNL);
! 2514: else if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, SEND))
! 2515: vty_out (vty, "no debug ospf6 message unknown send%s", VNL);
! 2516: else if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
! 2517: vty_out (vty, "no debug ospf6 message unknown recv%s", VNL);
! 2518:
! 2519: for (i = 1; i < 6; i++)
! 2520: {
! 2521: if (IS_OSPF6_DEBUG_MESSAGE (i, SEND) &&
! 2522: IS_OSPF6_DEBUG_MESSAGE (i, RECV))
! 2523: vty_out (vty, "debug ospf6 message %s%s", type_str[i], VNL);
! 2524: else if (IS_OSPF6_DEBUG_MESSAGE (i, SEND))
! 2525: vty_out (vty, "debug ospf6 message %s send%s", type_str[i],
! 2526: VNL);
! 2527: else if (IS_OSPF6_DEBUG_MESSAGE (i, RECV))
! 2528: vty_out (vty, "debug ospf6 message %s recv%s", type_str[i],
! 2529: VNL);
! 2530: }
! 2531:
! 2532: return 0;
! 2533: }
! 2534:
! 2535: void
! 2536: install_element_ospf6_debug_message (void)
! 2537: {
! 2538: install_element (ENABLE_NODE, &debug_ospf6_message_cmd);
! 2539: install_element (ENABLE_NODE, &no_debug_ospf6_message_cmd);
! 2540: install_element (ENABLE_NODE, &debug_ospf6_message_sendrecv_cmd);
! 2541: install_element (ENABLE_NODE, &no_debug_ospf6_message_sendrecv_cmd);
! 2542: install_element (CONFIG_NODE, &debug_ospf6_message_cmd);
! 2543: install_element (CONFIG_NODE, &no_debug_ospf6_message_cmd);
! 2544: install_element (CONFIG_NODE, &debug_ospf6_message_sendrecv_cmd);
! 2545: install_element (CONFIG_NODE, &no_debug_ospf6_message_sendrecv_cmd);
! 2546: }
! 2547:
! 2548:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>