1/* 2 * LSA function 3 * Copyright (C) 1999 Yasuhiro Ohara 4 * 5 * This file is part of GNU Zebra. 6 * 7 * GNU Zebra is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License as published by the 9 * Free Software Foundation; either version 2, or (at your option) any 10 * later version. 11 * 12 * GNU Zebra is distributed in the hope that it will be useful, but 13 * WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with GNU Zebra; see the file COPYING. If not, write to the 19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 20 * Boston, MA 02111-1307, USA. 21 */ 22 23#include <zebra.h> 24 25/* Include other stuffs */ 26#include "version.h" 27#include "log.h" 28#include "getopt.h" 29#include "linklist.h" 30#include "thread.h" 31#include "command.h" 32#include "memory.h" 33#include "sockunion.h" 34#include "if.h" 35#include "prefix.h" 36#include "stream.h" 37#include "thread.h" 38#include "filter.h" 39#include "zclient.h" 40#include "table.h" 41#include "plist.h" 42 43#include "ospf6_proto.h" 44#include "ospf6_prefix.h" 45#include "ospf6_lsa.h" 46#include "ospf6_lsdb.h" 47#include "ospf6_message.h" 48#include "ospf6_dump.h" 49 50#include "ospf6_top.h" 51#include "ospf6_area.h" 52#include "ospf6_interface.h" 53#include "ospf6_neighbor.h" 54#include "ospf6_redistribute.h" 55#include "ospf6_ism.h" 56#include "ospf6_nsm.h" 57#include "ospf6_dbex.h" 58 59#define HEADER_DEPENDENCY 60#include "ospf6d.h" 61#undef HEADER_DEPENDENCY 62 63/* test LSAs identity */ 64static int 65ospf6_lsa_issame (struct ospf6_lsa_header__ *lsh1, 66 struct ospf6_lsa_header__ *lsh2) 67{ 68 assert (lsh1 && lsh2); 69 70 if (lsh1->adv_router != lsh2->adv_router) 71 return 0; 72 73 if (lsh1->id != lsh2->id) 74 return 0; 75 76 if (lsh1->type != lsh2->type) 77 return 0; 78 79 return 1; 80} 81 82/* RFC2328: Section 13.2 */ 83int 84ospf6_lsa_differ (struct ospf6_lsa *lsa1, 85 struct ospf6_lsa *lsa2) 86{ 87 int diff, cmplen; 88 89 if (! ospf6_lsa_issame (lsa1->header, lsa2->header)) 90 return 1; 91 92 /* check Options field */ 93 /* xxx */ 94 95 ospf6_lsa_age_current (lsa1); 96 ospf6_lsa_age_current (lsa2); 97 if (ntohs (lsa1->header->age) == MAXAGE && 98 ntohs (lsa2->header->age) != MAXAGE) 99 return 1; 100 if (ntohs (lsa1->header->age) != MAXAGE && 101 ntohs (lsa2->header->age) == MAXAGE) 102 return 1; 103 104 /* compare body */ 105 if (ntohs (lsa1->header->length) != ntohs (lsa2->header->length)) 106 return 1; 107 108 cmplen = ntohs (lsa1->header->length) - sizeof (struct ospf6_lsa_header); 109 diff = memcmp (lsa1->header + 1, lsa2->header + 1, cmplen); 110 111 return diff; 112} 113 114int 115ospf6_lsa_match (u_int16_t type, u_int32_t id, u_int32_t adv_router, 116 struct ospf6_lsa_header *lsh) 117{ 118 if (lsh->advrtr != adv_router) 119 return 0; 120 121 if (lsh->ls_id != id) 122 return 0; 123 124 if (lsh->type != type) 125 return 0; 126 127 return 1; 128} 129 130/* ospf6 age functions */ 131/* calculate birth and set expire timer */ 132static void 133ospf6_lsa_age_set (struct ospf6_lsa *lsa) 134{ 135 struct timeval now; 136 137 assert (lsa && lsa->header); 138 139 if (gettimeofday (&now, (struct timezone *)NULL) < 0) 140 zlog_warn ("LSA: gettimeofday failed, may fail LSA AGEs: %s", 141 strerror (errno)); 142 143 lsa->birth.tv_sec = now.tv_sec - ntohs (lsa->header->age); 144 lsa->birth.tv_usec = now.tv_usec; 145 lsa->expire = thread_add_timer (master, ospf6_lsa_expire, lsa, 146 lsa->birth.tv_sec + MAXAGE - now.tv_sec); 147 return; 148} 149 150/* this function calculates current age from its birth, 151 then update age field of LSA header. return value is current age */ 152u_int16_t 153ospf6_lsa_age_current (struct ospf6_lsa *lsa) 154{ 155 struct timeval now; 156 u_int32_t ulage; 157 u_int16_t age; 158 159 assert (lsa); 160 assert (lsa->header); 161 162 /* current time */ 163 if (gettimeofday (&now, (struct timezone *)NULL) < 0) 164 zlog_warn ("LSA: gettimeofday failed, may fail ages: %s", 165 strerror (errno)); 166 167 /* calculate age */ 168 ulage = now.tv_sec - lsa->birth.tv_sec; 169 170 /* if over MAXAGE, set to it */ 171 if (ulage > MAXAGE) 172 age = MAXAGE; 173 else 174 age = ulage; 175 176 lsa->header->age = htons (age); 177 return age; 178} 179 180/* update age field of LSA header with adding InfTransDelay */ 181void 182ospf6_lsa_age_update_to_send (struct ospf6_lsa *lsa, u_int32_t transdelay) 183{ 184 unsigned short age; 185 186 age = ospf6_lsa_age_current (lsa) + transdelay; 187 if (age > MAXAGE) 188 age = MAXAGE; 189 lsa->header->age = htons (age); 190 return; 191} 192 193void 194ospf6_lsa_premature_aging (struct ospf6_lsa *lsa) 195{ 196 /* log */ 197 if (IS_OSPF6_DUMP_LSA) 198 zlog_info ("LSA: Premature aging: %s", lsa->str); 199 200 if (lsa->expire) 201 thread_cancel (lsa->expire); 202 lsa->expire = (struct thread *) NULL; 203 if (lsa->refresh) 204 thread_cancel (lsa->refresh); 205 lsa->refresh = (struct thread *) NULL; 206 207 memset (&lsa->birth, 0, sizeof (struct timeval)); 208 thread_execute (master, ospf6_lsa_expire, lsa, 0); 209} 210 211/* check which is more recent. if a is more recent, return -1; 212 if the same, return 0; otherwise(b is more recent), return 1 */ 213int 214ospf6_lsa_check_recent (struct ospf6_lsa *a, struct ospf6_lsa *b) 215{ 216 signed long seqnuma, seqnumb; 217 u_int16_t cksuma, cksumb; 218 u_int16_t agea, ageb; 219 220 assert (a && a->header); 221 assert (b && b->header); 222 assert (ospf6_lsa_issame (a->header, b->header)); 223 224 seqnuma = ((signed long) ntohl (a->header->seqnum)) 225 - (signed long) INITIAL_SEQUENCE_NUMBER; 226 seqnumb = ((signed long) ntohl (b->header->seqnum)) 227 - (signed long) INITIAL_SEQUENCE_NUMBER; 228 229 /* compare by sequence number */ 230 /* xxx, care about LS sequence number wrapping */ 231 recent_reason = "seqnum"; 232 if (seqnuma > seqnumb) 233 return -1; 234 else if (seqnuma < seqnumb) 235 return 1; 236 237 /* Checksum */ 238 cksuma = ntohs (a->header->checksum); 239 cksumb = ntohs (b->header->checksum); 240 if (cksuma > cksumb) 241 return -1; 242 if (cksuma < cksumb) 243 return 0; 244 245 /* Age check */ 246 agea = ospf6_lsa_age_current (a); 247 ageb = ospf6_lsa_age_current (b); 248 249 /* MaxAge check */ 250 recent_reason = "max age"; 251 if (agea == OSPF6_LSA_MAXAGE && ageb != OSPF6_LSA_MAXAGE) 252 return -1; 253 else if (agea != OSPF6_LSA_MAXAGE && ageb == OSPF6_LSA_MAXAGE) 254 return 1; 255 256 recent_reason = "age differ"; 257 if (agea > ageb && agea - ageb >= OSPF6_LSA_MAXAGEDIFF) 258 return 1; 259 else if (agea < ageb && ageb - agea >= OSPF6_LSA_MAXAGEDIFF) 260 return -1; 261 262 /* neither recent */ 263 recent_reason = "the same instance"; 264 return 0; 265} 266 267int 268ospf6_lsa_lsd_num (struct ospf6_lsa_header *lsa_header) 269{ 270 int ldnum = 0; 271 u_int16_t len; 272 273 len = ntohs (lsa_header->length); 274 len -= sizeof (struct ospf6_lsa_header); 275 if (lsa_header->type == htons (OSPF6_LSA_TYPE_ROUTER)) 276 { 277 len -= sizeof (struct ospf6_router_lsa); 278 ldnum = len / sizeof (struct ospf6_router_lsd); 279 } 280 else /* (lsa_header->type == htons (OSPF6_LSA_TYPE_NETWORK)) */ 281 { 282 len -= sizeof (struct ospf6_network_lsa); 283 ldnum = len / sizeof (u_int32_t); 284 } 285 286 return ldnum; 287} 288 289void * 290ospf6_lsa_lsd_get (int index, struct ospf6_lsa_header *lsa_header) 291{ 292 void *p; 293 struct ospf6_router_lsa *router_lsa; 294 struct ospf6_router_lsd *router_lsd; 295 struct ospf6_network_lsa *network_lsa; 296 struct ospf6_network_lsd *network_lsd; 297 298 if (lsa_header->type == htons (OSPF6_LSA_TYPE_ROUTER)) 299 { 300 router_lsa = (struct ospf6_router_lsa *) (lsa_header + 1); 301 router_lsd = (struct ospf6_router_lsd *) (router_lsa + 1); 302 router_lsd += index; 303 p = (void *) router_lsd; 304 } 305 else if (lsa_header->type == htons (OSPF6_LSA_TYPE_NETWORK)) 306 { 307 network_lsa = (struct ospf6_network_lsa *) (lsa_header + 1); 308 network_lsd = (struct ospf6_network_lsd *) (network_lsa + 1); 309 network_lsd += index; 310 p = (void *) network_lsd; 311 } 312 else 313 { 314 p = (void *) NULL; 315 } 316 317 return p; 318} 319 320/* network_lsd <-> router_lsd */ 321static int 322ospf6_lsa_lsd_network_reference_match (struct ospf6_network_lsd *network_lsd1, 323 struct ospf6_lsa_header *lsa_header1, 324 struct ospf6_router_lsd *router_lsd2, 325 struct ospf6_lsa_header *lsa_header2) 326{ 327 if (network_lsd1->adv_router != lsa_header2->advrtr) 328 return 0; 329 if (router_lsd2->type != OSPF6_ROUTER_LSD_TYPE_TRANSIT_NETWORK) 330 return 0; 331 if (router_lsd2->neighbor_router_id != lsa_header1->advrtr) 332 return 0; 333 if (router_lsd2->neighbor_interface_id != lsa_header1->ls_id) 334 return 0; 335 return 1; 336} 337 338/* router_lsd <-> router_lsd */ 339static int 340ospf6_lsa_lsd_router_reference_match (struct ospf6_router_lsd *router_lsd1, 341 struct ospf6_lsa_header *lsa_header1, 342 struct ospf6_router_lsd *router_lsd2, 343 struct ospf6_lsa_header *lsa_header2) 344{ 345 if (router_lsd1->type != OSPF6_ROUTER_LSD_TYPE_POINTTOPOINT) 346 return 0; 347 if (router_lsd2->type != OSPF6_ROUTER_LSD_TYPE_POINTTOPOINT) 348 return 0; 349 if (router_lsd1->neighbor_router_id != lsa_header2->advrtr) 350 return 0; 351 if (router_lsd2->neighbor_router_id != lsa_header1->advrtr) 352 return 0; 353 if (router_lsd1->neighbor_interface_id != router_lsd2->interface_id) 354 return 0; 355 if (router_lsd2->neighbor_interface_id != router_lsd1->interface_id) 356 return 0; 357 return 1; 358} 359 360int 361ospf6_lsa_lsd_is_refer_ok (int index1, struct ospf6_lsa_header *lsa_header1, 362 int index2, struct ospf6_lsa_header *lsa_header2) 363{ 364 struct ospf6_router_lsd *r1, *r2; 365 struct ospf6_network_lsd *n; 366 367 r1 = (struct ospf6_router_lsd *) NULL; 368 r2 = (struct ospf6_router_lsd *) NULL; 369 n = (struct ospf6_network_lsd *) NULL; 370 if (lsa_header1->type == htons (OSPF6_LSA_TYPE_ROUTER)) 371 r1 = (struct ospf6_router_lsd *) ospf6_lsa_lsd_get (index1, lsa_header1); 372 else 373 n = (struct ospf6_network_lsd *) ospf6_lsa_lsd_get (index1, lsa_header1); 374 375 if (lsa_header2->type == htons (OSPF6_LSA_TYPE_ROUTER)) 376 r2 = (struct ospf6_router_lsd *) ospf6_lsa_lsd_get (index2, lsa_header2); 377 else 378 n = (struct ospf6_network_lsd *) ospf6_lsa_lsd_get (index2, lsa_header2); 379 380 if (r1 && r2) 381 return ospf6_lsa_lsd_router_reference_match (r1, lsa_header1, 382 r2, lsa_header2); 383 else if (r1 && n) 384 return ospf6_lsa_lsd_network_reference_match (n, lsa_header2, 385 r1, lsa_header1); 386 else if (n && r2) 387 return ospf6_lsa_lsd_network_reference_match (n, lsa_header1, 388 r2, lsa_header2); 389 return 0; 390} 391 392void 393ospf6_lsa_show (struct vty *vty, struct ospf6_lsa *lsa) 394{ 395 char adv_router[64], id[64], type[32]; 396 397 assert (lsa); 398 assert (lsa->header); 399 400 ospf6_lsa_type_string (lsa->header->type, type, sizeof (type)); 401 inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id)); 402 inet_ntop (AF_INET, &lsa->header->adv_router, 403 adv_router, sizeof (adv_router)); 404 405 vty_out (vty, "%s", VTY_NEWLINE); 406 vty_out (vty, "Age: %4hu Type: %s%s", ospf6_lsa_age_current (lsa), 407 type, VTY_NEWLINE); 408 vty_out (vty, "Link State ID: %s%s", id, VTY_NEWLINE); 409 vty_out (vty, "Advertising Router: %s%s", adv_router, VTY_NEWLINE); 410 vty_out (vty, "LS Sequence Number: %#lx%s", (u_long)ntohl (lsa->header->seqnum), 411 VTY_NEWLINE); 412 vty_out (vty, "CheckSum: %#hx Length: %hu%s", ntohs (lsa->header->checksum), 413 ntohs (lsa->header->length), VTY_NEWLINE); 414 415 { 416 struct ospf6_lsa_slot *slot; 417 slot = ospf6_lsa_slot_get (lsa->header->type); 418 if (slot) 419 { 420 (*slot->func_show) (vty, lsa); 421 vty_out (vty, "%s", VTY_NEWLINE); 422 return; 423 } 424 } 425 426 vty_out (vty, "%sUnknown LSA type ...%s", VTY_NEWLINE, VTY_NEWLINE); 427} 428 429void 430ospf6_lsa_show_summary_header (struct vty *vty) 431{ 432 vty_out (vty, "%-12s %-15s %-15s %4s %8s %4s %4s %-8s%s", 433 "Type", "LSId", "AdvRouter", "Age", "SeqNum", 434 "Cksm", "Len", "Duration", VTY_NEWLINE); 435} 436 437void 438ospf6_lsa_show_summary (struct vty *vty, struct ospf6_lsa *lsa) 439{ 440 char adv_router[16], id[16], type[16]; 441 struct timeval now, res; 442 char duration[16]; 443 444 assert (lsa); 445 assert (lsa->header); 446 447 memset (type, 0, sizeof (type)); 448 ospf6_lsa_type_string (lsa->header->type, type, 13); 449 inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id)); 450 inet_ntop (AF_INET, &lsa->header->adv_router, adv_router, 451 sizeof (adv_router)); 452 453 gettimeofday (&now, NULL); 454 ospf6_timeval_sub (&now, &lsa->installed, &res); 455 ospf6_timeval_string_summary (&res, duration, sizeof (duration)); 456 457 vty_out (vty, "%-12s %-15s %-15s %4hu %8lx %04hx %4hu %8s%s", 458 type, id, adv_router, ospf6_lsa_age_current (lsa), 459 (u_long) ntohl (lsa->header->seqnum), 460 ntohs (lsa->header->checksum), ntohs (lsa->header->length), 461 duration, VTY_NEWLINE); 462} 463 464void 465ospf6_lsa_show_dump (struct vty *vty, struct ospf6_lsa *lsa) 466{ 467 u_char *start, *end, *current; 468 char byte[4]; 469 470 start = (char *) lsa->header; 471 end = (char *) lsa->header + ntohs (lsa->header->length); 472 473 vty_out (vty, "%s", VTY_NEWLINE); 474 vty_out (vty, "%s:%s", lsa->str, VTY_NEWLINE); 475 476 for (current = start; current < end; current ++) 477 { 478 if ((current - start) % 16 == 0) 479 vty_out (vty, "%s ", VTY_NEWLINE); 480 else if ((current - start) % 4 == 0) 481 vty_out (vty, " "); 482 483 snprintf (byte, sizeof (byte), "%02x", *current); 484 vty_out (vty, "%s", byte); 485 } 486 487 vty_out (vty, "%s%s", VTY_NEWLINE, VTY_NEWLINE); 488} 489 490/* OSPFv3 LSA creation/deletion function */ 491 492/* calculate LS sequence number for my new LSA. 493 return value is network byte order */ 494static signed long 495ospf6_lsa_seqnum_new (u_int16_t type, u_int32_t id, u_int32_t adv_router, 496 void *scope) 497{ 498 struct ospf6_lsa *lsa; 499 signed long seqnum; 500 501 /* get current database copy */ 502 lsa = ospf6_lsdb_lookup (type, id, adv_router, scope); 503 504 /* if current database copy not found, return InitialSequenceNumber */ 505 if (!lsa) 506 seqnum = INITIAL_SEQUENCE_NUMBER; 507 else 508 seqnum = (signed long) ntohl (lsa->header->seqnum) + 1; 509 510 return (htonl (seqnum)); 511} 512 513#if 0 514static void 515ospf6_lsa_header_set (u_int16_t type, u_int32_t ls_id, u_int32_t advrtr, 516 struct ospf6_lsa_header *lsa_header, int bodysize) 517{ 518 /* fill LSA header */ 519 lsa_header->age = 0; 520 lsa_header->type = type; 521 lsa_header->ls_id = ls_id; 522 lsa_header->advrtr = advrtr; 523 lsa_header->seqnum = 524 ospf6_lsa_seqnum_new (lsa_header->type, lsa_header->ls_id, 525 lsa_header->advrtr); 526 lsa_header->length = htons (sizeof (struct ospf6_lsa_header) + bodysize); 527 528 /* LSA checksum */ 529 ospf6_lsa_checksum (lsa_header); 530} 531#endif /*0*/ 532 533struct ospf6_lsa * 534ospf6_lsa_create (struct ospf6_lsa_header *source) 535{ 536 struct ospf6_lsa *lsa = NULL; 537 struct ospf6_lsa_header *lsa_header = NULL; 538 u_int16_t lsa_size = 0; 539 char buf_router[16], buf_id[16], typebuf[32]; 540 541 /* whole length of this LSA */ 542 lsa_size = ntohs (source->length); 543 544 /* allocate memory for this LSA */ 545 lsa_header = (struct ospf6_lsa_header *) 546 XMALLOC (MTYPE_OSPF6_LSA, lsa_size); 547 if (! lsa_header) 548 { 549 zlog_err ("Can't allocate memory for LSA Header"); 550 return (struct ospf6_lsa *) NULL; 551 } 552 memset (lsa_header, 0, lsa_size); 553 554 /* copy LSA from source */ 555 memcpy (lsa_header, source, lsa_size); 556 557 /* LSA information structure */ 558 /* allocate memory */ 559 lsa = (struct ospf6_lsa *) 560 XMALLOC (MTYPE_OSPF6_LSA, sizeof (struct ospf6_lsa)); 561 memset (lsa, 0, sizeof (struct ospf6_lsa)); 562 563 lsa->lsa_hdr = (struct ospf6_lsa_hdr *) lsa_header; 564 lsa->header = (struct ospf6_lsa_header__ *) lsa_header; 565 566 lsa->summary = 0; /* this is not LSA summary */ 567 568 /* dump string */ 569 inet_ntop (AF_INET, &lsa->header->id, buf_id, sizeof (buf_id)); 570 inet_ntop (AF_INET, &lsa->header->adv_router, buf_router, 571 sizeof (buf_router)); 572 snprintf (lsa->str, sizeof (lsa->str), "[%s ID=%s Adv=%s]", 573 ospf6_lsa_type_string (lsa_header->type, typebuf, 574 sizeof (typebuf)), 575 buf_id, buf_router); 576 577 /* calculate birth, expire and refresh of this lsa */ 578 ospf6_lsa_age_set (lsa); 579 580#ifdef DEBUG 581 if (IS_OSPF6_DUMP_LSA) 582 zlog_info ("Create: %s (%p/%p)", lsa->str, lsa, lsa->header); 583#endif /*DEBUG*/ 584 585 return lsa; 586} 587 588struct ospf6_lsa * 589ospf6_lsa_summary_create (struct ospf6_lsa_header__ *source) 590{ 591 struct ospf6_lsa *lsa = NULL; 592 struct ospf6_lsa_header *lsa_header = NULL; 593 u_int16_t lsa_size = 0; 594 char buf_router[16], buf_id[16], typebuf[16]; 595 596 /* LSA summary contains LSA Header only */ 597 lsa_size = sizeof (struct ospf6_lsa_header); 598 599 /* allocate memory for this LSA */ 600 lsa_header = (struct ospf6_lsa_header *) 601 XMALLOC (MTYPE_OSPF6_LSA_SUMMARY, lsa_size); 602 memset (lsa_header, 0, lsa_size); 603 604 /* copy LSA from source */ 605 memcpy (lsa_header, source, lsa_size); 606 607 /* LSA information structure */ 608 /* allocate memory */ 609 lsa = (struct ospf6_lsa *) 610 XMALLOC (MTYPE_OSPF6_LSA_SUMMARY, sizeof (struct ospf6_lsa)); 611 memset (lsa, 0, sizeof (struct ospf6_lsa)); 612 613 lsa->lsa_hdr = (struct ospf6_lsa_hdr *) lsa_header; 614 lsa->header = (struct ospf6_lsa_header__ *) lsa_header; 615 lsa->summary = 1; /* this is LSA summary */ 616 617 /* dump string */ 618 inet_ntop (AF_INET, &lsa->header->id, buf_id, sizeof (buf_id)); 619 inet_ntop (AF_INET, &lsa->header->adv_router, buf_router, 620 sizeof (buf_router)); 621 snprintf (lsa->str, sizeof (lsa->str), "[%s Summary ID=%s Adv=%s]", 622 ospf6_lsa_type_string (lsa->header->type, typebuf, 623 sizeof (typebuf)), 624 buf_id, buf_router); 625 626 /* calculate birth, expire and refresh of this lsa */ 627 ospf6_lsa_age_set (lsa); 628 629#ifdef DEBUG 630 if (IS_OSPF6_DUMP_LSA) 631 zlog_info ("Create: %s (%p/%p)", lsa->str, lsa, lsa->header); 632#endif /*DEBUG*/ 633 634 return lsa; 635} 636 637void 638ospf6_lsa_delete (struct ospf6_lsa *lsa) 639{ 640 /* just to make sure */ 641 if (lsa->lock != 0) 642 { 643 zlog_err ("Can't delete %s: lock: %ld", lsa->str, lsa->lock); 644 return; 645 } 646 647 /* cancel threads */ 648 if (lsa->expire) 649 thread_cancel (lsa->expire); 650 lsa->expire = (struct thread *) NULL; 651 if (lsa->refresh) 652 thread_cancel (lsa->refresh); 653 lsa->refresh = (struct thread *) NULL; 654 655#ifdef DEBUG 656 if (IS_OSPF6_DUMP_LSA) 657 zlog_info ("Delete %s (%p/%p)", lsa->str, lsa, lsa->header); 658#endif /*DEBUG*/ 659 660 /* do free */ 661 if (lsa->summary) 662 XFREE (MTYPE_OSPF6_LSA_SUMMARY, lsa->header); 663 else 664 XFREE (MTYPE_OSPF6_LSA, lsa->header); 665 lsa->header = NULL; 666 667 if (lsa->summary) 668 XFREE (MTYPE_OSPF6_LSA_SUMMARY, lsa); 669 else 670 XFREE (MTYPE_OSPF6_LSA, lsa); 671} 672 673/* increment reference counter of struct ospf6_lsa */ 674void 675ospf6_lsa_lock (struct ospf6_lsa *lsa) 676{ 677 lsa->lock++; 678 return; 679} 680 681/* decrement reference counter of struct ospf6_lsa */ 682void 683ospf6_lsa_unlock (struct ospf6_lsa *lsa) 684{ 685 /* decrement reference counter */ 686 if (lsa->lock > 0) 687 lsa->lock--; 688 else 689 zlog_warn ("Can't unlock %s: already no lock", lsa->str); 690 691 if (lsa->lock == 0) 692 ospf6_lsa_delete (lsa); 693} 694 695/* check necessity to update LSA: 696 returns 1 if it's necessary to reoriginate */ 697static int 698ospf6_lsa_is_really_reoriginate (struct ospf6_lsa *new) 699{ 700 struct ospf6_lsa *old; 701 int diff; 702 703 /* find previous LSA */ 704 old = ospf6_lsdb_lookup (new->header->type, new->header->id, 705 new->header->adv_router, new->scope); 706 if (! old) 707 return 1; 708 709 /* Check if this is refresh */ 710 if (CHECK_FLAG (old->flag, OSPF6_LSA_FLAG_REFRESH)) 711 { 712 zlog_warn ("LSA: reoriginate: %s: Refresh", new->str); 713 return 1; 714 } 715 716 /* Are these contents different ? */ 717 diff = ospf6_lsa_differ (new, old); 718 719 if (diff) 720 return 1; 721 722 if (IS_OSPF6_DUMP_LSA) 723 zlog_info ("LSA: Suppress updating %s", new->str); 724 return 0; 725} 726 727void 728ospf6_lsa_originate (u_int16_t type, u_int32_t id, u_int32_t adv_router, 729 char *data, int data_len, void *scope) 730{ 731 char buffer[MAXLSASIZE]; 732 struct ospf6_lsa_header *lsa_header; 733 struct ospf6_lsa *lsa; 734 735 assert (data_len <= sizeof (buffer) - sizeof (struct ospf6_lsa_header)); 736 737 lsa_header = (struct ospf6_lsa_header *) buffer; 738 739 /* Copy LSA Body */ 740 memcpy (buffer + sizeof (struct ospf6_lsa_header), data, data_len); 741 742 /* Fill LSA Header */ 743 lsa_header->age = 0; 744 lsa_header->type = type; 745 lsa_header->ls_id = id; 746 lsa_header->advrtr = adv_router; 747 lsa_header->seqnum = 748 ospf6_lsa_seqnum_new (lsa_header->type, lsa_header->ls_id, 749 lsa_header->advrtr, scope); 750 lsa_header->length = htons (sizeof (struct ospf6_lsa_header) + data_len); 751 752 /* LSA checksum */ 753 ospf6_lsa_checksum (lsa_header); 754 755 /* create LSA */ 756 lsa = ospf6_lsa_create ((struct ospf6_lsa_header *) buffer); 757 lsa->refresh = thread_add_timer (master, ospf6_lsa_refresh, lsa, 758 OSPF6_LS_REFRESH_TIME); 759 lsa->scope = scope; 760 761 if (ospf6_lsa_is_really_reoriginate (lsa)) 762 { 763 ospf6_dbex_remove_from_all_retrans_list (lsa); 764 ospf6_dbex_flood (lsa, NULL); 765 ospf6_lsdb_install (lsa); 766 } 767 else 768 ospf6_lsa_delete (lsa); 769} 770 771 772/* ospf6_lsa expired */ 773int 774ospf6_lsa_expire (struct thread *thread) 775{ 776 struct ospf6_lsa *lsa; 777 struct ospf6_lsdb *lsdb = NULL; 778 779 lsa = (struct ospf6_lsa *) THREAD_ARG (thread); 780 assert (lsa && lsa->lsa_hdr); 781 782 /* assertion */ 783 assert (IS_LSA_MAXAGE (lsa)); 784 assert (!lsa->refresh); 785 786 lsa->expire = (struct thread *) NULL; 787 788 /* log */ 789 if (IS_OSPF6_DUMP_LSA) 790 zlog_info ("LSA: Expire: %s", lsa->str); 791 792 if (!lsa->summary) 793 { 794 /* reflood lsa */ 795 ospf6_dbex_flood (lsa, NULL); 796 797 /* get scoped lsdb, call remove hook */ 798 if (OSPF6_LSA_IS_SCOPE_LINKLOCAL (ntohs (lsa->header->type))) 799 lsdb = ((struct ospf6_interface *) lsa->scope)->lsdb; 800 else if (OSPF6_LSA_IS_SCOPE_AREA (ntohs (lsa->header->type))) 801 lsdb = ((struct ospf6_area *) lsa->scope)->lsdb; 802 else if (OSPF6_LSA_IS_SCOPE_AS (ntohs (lsa->header->type))) 803 lsdb = ((struct ospf6 *) lsa->scope)->lsdb; 804 else 805 assert (0); 806 807#if 0 808 if (lsdb->hook) 809 (*lsdb->hook) (lsa, NULL); 810#else /*0*/ 811 CALL_REMOVE_HOOK (&database_hook, lsa); 812#endif /*0*/ 813 814 /* do not free LSA, and do nothing about lslists. 815 wait event (ospf6_lsdb_check_maxage) */ 816 } 817 818 return 0; 819} 820 821int 822ospf6_lsa_refresh (struct thread *thread) 823{ 824 struct ospf6_lsa *lsa; 825 struct ospf6_lsa_slot *slot; 826 827 assert (thread); 828 lsa = (struct ospf6_lsa *) THREAD_ARG (thread); 829 assert (lsa && lsa->lsa_hdr); 830 831 /* this will be used later as flag to decide really originate */ 832 lsa->refresh = (struct thread *) NULL; 833 SET_FLAG (lsa->flag, OSPF6_LSA_FLAG_REFRESH); 834 835 /* log */ 836 if (IS_OSPF6_DUMP_LSA) 837 zlog_info ("LSA Refresh: %s", lsa->str); 838 839 slot = ospf6_lsa_slot_get (lsa->header->type); 840 if (slot) 841 { 842 zlog_info ("LSA Refresh: %s", slot->name); 843 (*slot->func_refresh) (lsa); 844 return 0; 845 } 846 847 zlog_warn ("Can't Refresh LSA: Unknown type: %#x", 848 ntohs (lsa->header->type)); 849 return 1; 850} 851 852 853 854/* enhanced Fletcher checksum algorithm, RFC1008 7.2 */ 855#define MODX 4102 856#define LSA_CHECKSUM_OFFSET 15 857 858unsigned short 859ospf6_lsa_checksum (struct ospf6_lsa_header *lsa_header) 860{ 861 u_char *sp, *ep, *p, *q; 862 int c0 = 0, c1 = 0; 863 int x, y; 864 u_int16_t length; 865 866 lsa_header->checksum = 0; 867 length = ntohs (lsa_header->length) - 2; 868 sp = (char *) &lsa_header->type; 869 870 for (ep = sp + length; sp < ep; sp = q) 871 { 872 q = sp + MODX; 873 if (q > ep) 874 q = ep; 875 for (p = sp; p < q; p++) 876 { 877 c0 += *p; 878 c1 += c0; 879 } 880 c0 %= 255; 881 c1 %= 255; 882 } 883 884 /* r = (c1 << 8) + c0; */ 885 x = ((length - LSA_CHECKSUM_OFFSET) * c0 - c1) % 255; 886 if (x <= 0) 887 x += 255; 888 y = 510 - c0 - x; 889 if (y > 255) 890 y -= 255; 891 892 lsa_header->checksum = htons ((x << 8) + y); 893 894 return (lsa_header->checksum); 895} 896 897int 898ospf6_lsa_is_known_type (struct ospf6_lsa_header *lsa_header) 899{ 900 struct ospf6_lsa_slot *slot; 901 902 slot = ospf6_lsa_slot_get (lsa_header->type); 903 if (slot) 904 return 1; 905 return 0; 906} 907 908struct ospf6_lsa_slot *slot_head = NULL; 909 910struct ospf6_lsa_slot * 911ospf6_lsa_slot_get (u_int16_t type) 912{ 913 struct ospf6_lsa_slot *slot; 914 915 for (slot = slot_head; slot; slot = slot->next) 916 { 917 if (slot->type == type) 918 return slot; 919 } 920 921 return NULL; 922} 923 924int 925ospf6_lsa_slot_register (struct ospf6_lsa_slot *src) 926{ 927 struct ospf6_lsa_slot *new, *slot; 928 929 slot = ospf6_lsa_slot_get (src->type); 930 if (slot) 931 { 932 if (IS_OSPF6_DUMP_LSA) 933 zlog_info ("LSA: Slot register: already exists: %#x %s", 934 slot->type, slot->name); 935 return -1; 936 } 937 938 new = (struct ospf6_lsa_slot *) 939 XMALLOC (MTYPE_OSPF6_LSA, sizeof (struct ospf6_lsa_slot)); 940 if (! new) 941 { 942 zlog_err ("Can't allocate memory for LSA slot: %s", strerror (errno)); 943 return -1; 944 } 945 memset (new, 0, sizeof (struct ospf6_lsa_slot)); 946 memcpy (new, src, sizeof (struct ospf6_lsa_slot)); 947 948 if (IS_OSPF6_DUMP_LSA) 949 zlog_info ("LSA: Slot register: %#x %s", slot->type, slot->name); 950 951 if (slot_head == NULL) 952 { 953 new->prev = NULL; 954 new->next = NULL; 955 slot_head = new; 956 return 0; 957 } 958 959 slot = slot_head; 960 while (slot->next) 961 slot = slot->next; 962 963 slot->next = new; 964 new->prev = slot; 965 966 return 0; 967} 968 969int 970ospf6_lsa_slot_unregister (u_int16_t type) 971{ 972 struct ospf6_lsa_slot *slot; 973 974 slot = ospf6_lsa_slot_get (type); 975 if (slot == NULL) 976 { 977 if (IS_OSPF6_DUMP_LSA) 978 zlog_info ("Registering LSA slot: no such slot: %#x", type); 979 return -1; 980 } 981 982 if (IS_OSPF6_DUMP_LSA) 983 zlog_info ("Unregistering LSA Slot: %#x %s", slot->type, slot->name); 984 985 if (slot->prev) 986 slot->prev->next = slot->next; 987 if (slot->next) 988 slot->next->prev = slot->prev; 989 990 if (slot_head == slot) 991 slot_head = slot->next; 992 993 XFREE (MTYPE_OSPF6_LSA, slot); 994 return 0; 995} 996 997char * 998ospf6_lsa_type_string (u_int16_t type, char *buf, int bufsize) 999{ 1000 struct ospf6_lsa_slot *slot; 1001 1002 slot = ospf6_lsa_slot_get (type); 1003 if (slot) 1004 snprintf (buf, bufsize, "%s", slot->name); 1005 else 1006 snprintf (buf, bufsize, "Type=0x%04x", ntohs (type)); 1007 1008 return buf; 1009} 1010 1011 1012/*******************/ 1013/* LSA Origination */ 1014/*******************/ 1015 1016#define CONTINUE_IF_ADDRESS_LINKLOCAL(addr)\ 1017 if (IN6_IS_ADDR_LINKLOCAL (&(addr)->u.prefix6))\ 1018 {\ 1019 char buf[64];\ 1020 prefix2str (addr, buf, sizeof (buf));\ 1021 if (IS_OSPF6_DUMP_LSA)\ 1022 zlog_info (" Filter out Linklocal: %s", buf);\ 1023 continue;\ 1024 } 1025 1026#define CONTINUE_IF_ADDRESS_UNSPECIFIED(addr)\ 1027 if (IN6_IS_ADDR_UNSPECIFIED (&(addr)->u.prefix6))\ 1028 {\ 1029 char buf[64];\ 1030 prefix2str (addr, buf, sizeof (buf));\ 1031 if (IS_OSPF6_DUMP_LSA)\ 1032 zlog_info (" Filter out Unspecified: %s", buf);\ 1033 continue;\ 1034 } 1035 1036#define CONTINUE_IF_ADDRESS_LOOPBACK(addr)\ 1037 if (IN6_IS_ADDR_LOOPBACK (&(addr)->u.prefix6))\ 1038 {\ 1039 char buf[64];\ 1040 prefix2str (addr, buf, sizeof (buf));\ 1041 if (IS_OSPF6_DUMP_LSA)\ 1042 zlog_info (" Filter out Loopback: %s", buf);\ 1043 continue;\ 1044 } 1045 1046#define CONTINUE_IF_ADDRESS_V4COMPAT(addr)\ 1047 if (IN6_IS_ADDR_V4COMPAT (&(addr)->u.prefix6))\ 1048 {\ 1049 char buf[64];\ 1050 prefix2str (addr, buf, sizeof (buf));\ 1051 if (IS_OSPF6_DUMP_LSA)\ 1052 zlog_info (" Filter out V4Compat: %s", buf);\ 1053 continue;\ 1054 } 1055 1056#define CONTINUE_IF_ADDRESS_V4MAPPED(addr)\ 1057 if (IN6_IS_ADDR_V4MAPPED (&(addr)->u.prefix6))\ 1058 {\ 1059 char buf[64];\ 1060 prefix2str (addr, buf, sizeof (buf));\ 1061 if (IS_OSPF6_DUMP_LSA)\ 1062 zlog_info (" Filter out V4Mapped: %s", buf);\ 1063 continue;\ 1064 } 1065 1066/******************************/ 1067/* RFC2740 3.4.3.1 Router-LSA */ 1068/******************************/ 1069 1070char * 1071ospf6_lsa_router_bits_string (u_char router_bits, char *buf, int size) 1072{ 1073 char w, v, e, b; 1074 1075 w = (router_bits & OSPF6_ROUTER_LSA_BIT_W ? 'W' : '-'); 1076 v = (router_bits & OSPF6_ROUTER_LSA_BIT_V ? 'V' : '-'); 1077 e = (router_bits & OSPF6_ROUTER_LSA_BIT_E ? 'E' : '-'); 1078 b = (router_bits & OSPF6_ROUTER_LSA_BIT_B ? 'B' : '-'); 1079 snprintf (buf, size, "----%c%c%c%c", w, v, e, b); 1080 return buf; 1081} 1082 1083int 1084ospf6_lsa_router_show (struct vty *vty, struct ospf6_lsa *lsa) 1085{ 1086 char *start, *end, *current; 1087 char buf[32], name[32], bits[32], options[32]; 1088 struct ospf6_router_lsa *router_lsa; 1089 struct ospf6_router_lsd *lsdesc; 1090 1091 assert (lsa->header); 1092 1093 router_lsa = (struct ospf6_router_lsa *) 1094 ((char *) lsa->header + sizeof (struct ospf6_lsa_header)); 1095 1096 ospf6_lsa_router_bits_string (router_lsa->bits, bits, sizeof (bits)); 1097 ospf6_options_string (router_lsa->options, options, sizeof (options)); 1098 vty_out (vty, " Bits: %s Options: %s%s", bits, options, VTY_NEWLINE); 1099 1100 start = (char *) router_lsa + sizeof (struct ospf6_router_lsa); 1101 end = (char *) lsa->header + ntohs (lsa->header->length); 1102 for (current = start; current + sizeof (struct ospf6_router_lsd) <= end; 1103 current += sizeof (struct ospf6_router_lsd)) 1104 { 1105 lsdesc = (struct ospf6_router_lsd *) current; 1106 1107 if (lsdesc->type == OSPF6_ROUTER_LSD_TYPE_POINTTOPOINT) 1108 snprintf (name, sizeof (name), "Point-To-Point"); 1109 else if (lsdesc->type == OSPF6_ROUTER_LSD_TYPE_TRANSIT_NETWORK) 1110 snprintf (name, sizeof (name), "Transit-Network"); 1111 else if (lsdesc->type == OSPF6_ROUTER_LSD_TYPE_STUB_NETWORK) 1112 snprintf (name, sizeof (name), "Stub-Network"); 1113 else if (lsdesc->type == OSPF6_ROUTER_LSD_TYPE_VIRTUAL_LINK) 1114 snprintf (name, sizeof (name), "Virtual-Link"); 1115 else 1116 snprintf (name, sizeof (name), "Unknown (%#x)", lsdesc->type); 1117 1118 vty_out (vty, " Type: %s Metric: %d%s", 1119 name, ntohs (lsdesc->metric), VTY_NEWLINE); 1120 vty_out (vty, " Interface ID: %s%s", 1121 inet_ntop (AF_INET, &lsdesc->interface_id, 1122 buf, sizeof (buf)), VTY_NEWLINE); 1123 vty_out (vty, " Neighbor Interface ID: %s%s", 1124 inet_ntop (AF_INET, &lsdesc->neighbor_interface_id, 1125 buf, sizeof (buf)), VTY_NEWLINE); 1126 vty_out (vty, " Neighbor Router ID: %s%s", 1127 inet_ntop (AF_INET, &lsdesc->neighbor_router_id, 1128 buf, sizeof (buf)), VTY_NEWLINE); 1129 } 1130 return 0; 1131} 1132 1133void 1134ospf6_lsa_router_update (u_int32_t area_id) 1135{ 1136 char buffer [MAXLSASIZE]; 1137 u_int16_t size; 1138 struct ospf6_lsa *old; 1139 struct ospf6_area *o6a; 1140 int count; 1141 1142 struct ospf6_router_lsa *router_lsa; 1143 struct ospf6_router_lsd *router_lsd; 1144 listnode i; 1145 struct ospf6_interface *o6i; 1146 struct ospf6_neighbor *o6n = NULL; 1147 1148 o6a = ospf6_area_lookup (area_id, ospf6); 1149 if (! o6a) 1150 { 1151 inet_ntop (AF_INET, &area_id, buffer, sizeof (buffer)); 1152 if (IS_OSPF6_DUMP_LSA) 1153 zlog_warn ("Update Router-LSA: No such area: %s", buffer); 1154 return; 1155 } 1156 1157 if (IS_OSPF6_DUMP_LSA) 1158 zlog_info ("Update Router-LSA: for Area %s", o6a->str); 1159 1160 /* find previous LSA */ 1161 /* xxx, there may be multiple Router-LSAs */ 1162 old = ospf6_lsdb_lookup (htons (OSPF6_LSA_TYPE_ROUTER), 1163 htonl (0), o6a->ospf6->router_id, o6a); 1164 1165 size = sizeof (struct ospf6_router_lsa); 1166 memset (buffer, 0, sizeof (buffer)); 1167 router_lsa = (struct ospf6_router_lsa *) buffer; 1168 1169 OSPF6_OPT_CLEAR_ALL (router_lsa->options); 1170 OSPF6_OPT_SET (router_lsa->options, OSPF6_OPT_V6); 1171 OSPF6_OPT_SET (router_lsa->options, OSPF6_OPT_E); 1172 OSPF6_OPT_CLEAR (router_lsa->options, OSPF6_OPT_MC); 1173 OSPF6_OPT_CLEAR (router_lsa->options, OSPF6_OPT_N); 1174 OSPF6_OPT_SET (router_lsa->options, OSPF6_OPT_R); 1175 OSPF6_OPT_CLEAR (router_lsa->options, OSPF6_OPT_DC); 1176 1177 OSPF6_ROUTER_LSA_CLEAR_ALL_BITS (router_lsa); 1178 OSPF6_ROUTER_LSA_CLEAR (router_lsa, OSPF6_ROUTER_LSA_BIT_B); 1179 1180 if (ospf6_is_asbr (o6a->ospf6)) 1181 OSPF6_ROUTER_LSA_SET (router_lsa, OSPF6_ROUTER_LSA_BIT_E); 1182 else 1183 OSPF6_ROUTER_LSA_CLEAR (router_lsa, OSPF6_ROUTER_LSA_BIT_E); 1184 1185 OSPF6_ROUTER_LSA_CLEAR (router_lsa, OSPF6_ROUTER_LSA_BIT_V); 1186 OSPF6_ROUTER_LSA_CLEAR (router_lsa, OSPF6_ROUTER_LSA_BIT_W); 1187 1188 /* describe links for each interfaces */ 1189 router_lsd = (struct ospf6_router_lsd *) (router_lsa + 1); 1190 for (i = listhead (o6a->if_list); i; nextnode (i)) 1191 { 1192 o6i = (struct ospf6_interface *) getdata (i); 1193 assert (o6i); 1194 1195 /* Interfaces in state Down or Loopback are not described */ 1196 if (o6i->state == IFS_DOWN || o6i->state == IFS_LOOPBACK) 1197 continue; 1198 1199 /* Nor are interfaces without any full adjacencies described */ 1200 count = 0; 1201 o6i->foreach_nei (o6i, &count, NBS_FULL, ospf6_count_state); 1202 if (count == 0) 1203 continue; 1204 1205 /* Point-to-Point interfaces */ 1206 if (if_is_pointopoint (o6i->interface)) 1207 { 1208 if (listcount (o6i->neighbor_list) == 0) 1209 continue; 1210 1211 if (listcount (o6i->neighbor_list) != 1) 1212 zlog_warn ("LSA: Multiple neighbors on PoinToPoint: %s", 1213 o6i->interface->name); 1214 1215 o6n = (struct ospf6_neighbor *) 1216 getdata (listhead (o6i->neighbor_list)); 1217 assert (o6n); 1218 1219 router_lsd->type = OSPF6_ROUTER_LSD_TYPE_POINTTOPOINT; 1220 router_lsd->metric = htons (o6i->cost); 1221 router_lsd->interface_id = htonl (o6i->if_id); 1222 router_lsd->neighbor_interface_id = htonl (o6n->ifid); 1223 router_lsd->neighbor_router_id = o6n->router_id; 1224 1225 size += sizeof (struct ospf6_router_lsd); 1226 router_lsd ++; 1227 1228 continue; 1229 } 1230 1231 /* Broadcast and NBMA interfaces */ 1232 if (if_is_broadcast (o6i->interface)) 1233 { 1234 /* If this router is not DR, 1235 and If this router not fully adjacent with DR, 1236 this interface is not transit yet: ignore. */ 1237 if (o6i->state != IFS_DR) 1238 { 1239 o6n = ospf6_neighbor_lookup (o6i->dr, o6i); /* find DR */ 1240 if (o6n == NULL || o6n->state != NBS_FULL) 1241 continue; 1242 } 1243 else 1244 { 1245 count = 0; 1246 o6i->foreach_nei (o6i, &count, NBS_FULL, ospf6_count_state); 1247 if (count == 0) 1248 continue; 1249 } 1250 1251 router_lsd->type = OSPF6_ROUTER_LSD_TYPE_TRANSIT_NETWORK; 1252 router_lsd->metric = htons (o6i->cost); 1253 router_lsd->interface_id = htonl (o6i->if_id); 1254 if (o6i->state != IFS_DR) 1255 { 1256 router_lsd->neighbor_interface_id = htonl (o6n->ifid); 1257 router_lsd->neighbor_router_id = o6n->router_id; 1258 } 1259 else 1260 { 1261 router_lsd->neighbor_interface_id = htonl (o6i->if_id); 1262 router_lsd->neighbor_router_id = o6i->area->ospf6->router_id; 1263 } 1264 1265 size += sizeof (struct ospf6_router_lsd); 1266 router_lsd ++; 1267 1268 continue; 1269 } 1270 1271 /* Virtual links */ 1272 /* xxx */ 1273 /* Point-to-Multipoint interfaces */ 1274 /* xxx */ 1275 } 1276 1277 ospf6_lsa_originate (htons (OSPF6_LSA_TYPE_ROUTER), 1278 htonl (0), o6a->ospf6->router_id, 1279 (char *) router_lsa, size, o6a); 1280} 1281 1282int 1283ospf6_lsa_router_hook_neighbor (void *neighbor) 1284{ 1285 struct ospf6_neighbor *o6n = neighbor; 1286 if (o6n->ospf6_interface->area) 1287 ospf6_lsa_router_update (o6n->ospf6_interface->area->area_id); 1288 return 0; 1289} 1290 1291int 1292ospf6_lsa_router_hook_interface (void *interface) 1293{ 1294 struct ospf6_interface *o6i = interface; 1295 if (o6i->area) 1296 ospf6_lsa_router_update (o6i->area->area_id); 1297 return 0; 1298} 1299 1300int 1301ospf6_lsa_router_hook_area (void *area) 1302{ 1303 struct ospf6_area *o6a = area; 1304 ospf6_lsa_router_update (o6a->area_id); 1305 return 0; 1306} 1307 1308int 1309ospf6_lsa_router_hook_top (void *ospf6) 1310{ 1311 struct ospf6 *o6 = ospf6; 1312 struct ospf6_area *o6a; 1313 listnode node; 1314 1315 for (node = listhead (o6->area_list); node; nextnode (node)) 1316 { 1317 o6a = getdata (node); 1318 ospf6_lsa_router_update (o6a->area_id); 1319 } 1320 return 0; 1321} 1322 1323int 1324ospf6_lsa_router_refresh (void *old) 1325{ 1326 struct ospf6_lsa *lsa = old; 1327 struct ospf6_area *o6a; 1328 1329 o6a = lsa->scope; 1330 ospf6_lsa_router_update (o6a->area_id); 1331 return 0; 1332} 1333 1334void 1335ospf6_lsa_slot_register_router () 1336{ 1337 struct ospf6_lsa_slot slot; 1338 struct ospf6_hook hook; 1339 1340 memset (&slot, 0, sizeof (struct ospf6_lsa_slot)); 1341 slot.type = htons (OSPF6_LSA_TYPE_ROUTER); 1342 slot.name = "Router"; 1343 slot.func_show = ospf6_lsa_router_show; 1344 slot.func_refresh = ospf6_lsa_router_refresh; 1345 ospf6_lsa_slot_register (&slot); 1346 1347 ospf6_lsdb_hook[OSPF6_LSA_TYPE_ROUTER & OSPF6_LSTYPE_CODE_MASK].hook = 1348 ospf6_spf_database_hook; 1349 1350 memset (&hook, 0, sizeof (hook)); 1351 hook.name = "OriginateRouter"; 1352 hook.hook_change = ospf6_lsa_router_hook_neighbor; 1353 ospf6_hook_register (&hook, &neighbor_hook); 1354 1355 memset (&hook, 0, sizeof (hook)); 1356 hook.name = "OriginateRouter"; 1357 hook.hook_change = ospf6_lsa_router_hook_interface; 1358 ospf6_hook_register (&hook, &interface_hook); 1359 1360 memset (&hook, 0, sizeof (hook)); 1361 hook.name = "OriginateRouter"; 1362 hook.hook_change = ospf6_lsa_router_hook_area; 1363 ospf6_hook_register (&hook, &area_hook); 1364 1365 memset (&hook, 0, sizeof (hook)); 1366 hook.name = "OriginateRouter"; 1367 hook.hook_change = ospf6_lsa_router_hook_top; 1368 ospf6_hook_register (&hook, &top_hook); 1369} 1370 1371/*******************************/ 1372/* RFC2740 3.4.3.2 Network-LSA */ 1373/*******************************/ 1374 1375int 1376ospf6_lsa_network_show (struct vty *vty, struct ospf6_lsa *lsa) 1377{ 1378 char *start, *end, *current; 1379 struct ospf6_network_lsa *network_lsa; 1380 u_int32_t *router_id; 1381 char buf[128], options[32]; 1382 1383 assert (lsa->header); 1384 network_lsa = (struct ospf6_network_lsa *) (lsa->header + 1); 1385 router_id = (u_int32_t *)(network_lsa + 1); 1386 1387 ospf6_options_string (network_lsa->options, options, sizeof (options)); 1388 vty_out (vty, " Options: %s%s", options, VTY_NEWLINE); 1389 1390 start = (char *) network_lsa + sizeof (struct ospf6_network_lsa); 1391 end = (char *) lsa->header + ntohs (lsa->header->length); 1392 for (current = start; current + sizeof (u_int32_t) <= end; 1393 current += sizeof (u_int32_t)) 1394 { 1395 router_id = (u_int32_t *) current; 1396 inet_ntop (AF_INET, router_id, buf, sizeof (buf)); 1397 vty_out (vty, " Attached Router: %s%s", buf, VTY_NEWLINE); 1398 } 1399 return 0; 1400} 1401 1402void 1403ospf6_lsa_network_update (char *ifname) 1404{ 1405 char buffer [MAXLSASIZE]; 1406 u_int16_t size; 1407 struct ospf6_lsa *old; 1408 struct interface *ifp; 1409 struct ospf6_interface *o6i; 1410 int count; 1411 1412 struct ospf6_network_lsa *network_lsa; 1413 struct ospf6_neighbor *o6n; 1414 u_int32_t *router_id; 1415 listnode node; 1416 1417 ifp = if_lookup_by_name (ifname); 1418 if (! ifp) 1419 { 1420 if (IS_OSPF6_DUMP_LSA) 1421 zlog_warn ("Update Network: No such Interface: %s", ifname); 1422 return; 1423 } 1424 1425 o6i = (struct ospf6_interface *) ifp->info; 1426 if (! o6i || ! o6i->area) 1427 { 1428 if (IS_OSPF6_DUMP_LSA) 1429 zlog_warn ("Update Network: Interface not enabled: %s", ifname); 1430 return; 1431 } 1432 1433 /* find previous LSA */ 1434 old = ospf6_lsdb_lookup (htons (OSPF6_LSA_TYPE_NETWORK), 1435 htonl (o6i->if_id), 1436 o6i->area->ospf6->router_id, o6i->area); 1437 1438 /* Don't originate Network-LSA if not DR */ 1439 if (o6i->state != IFS_DR) 1440 { 1441 if (IS_OSPF6_DUMP_LSA) 1442 zlog_info ("Update Network: Interface %s is not DR", 1443 o6i->interface->name); 1444 if (old) 1445 ospf6_lsa_premature_aging (old); 1446 return; 1447 } 1448 1449 /* If none of neighbor is adjacent to us */ 1450 count = 0; 1451 o6i->foreach_nei (o6i, &count, NBS_FULL, ospf6_count_state); 1452 if (count == 0) 1453 { 1454 if (IS_OSPF6_DUMP_LSA) 1455 zlog_info ("Update Network: Interface %s is Stub", 1456 o6i->interface->name); 1457 if (old) 1458 ospf6_lsa_premature_aging (old); 1459 return; 1460 } 1461 1462 if (IS_OSPF6_DUMP_LSA) 1463 zlog_info ("Update Network: Interface %s", o6i->interface->name); 1464 1465 /* prepare buffer */ 1466 memset (buffer, 0, sizeof (buffer)); 1467 size = sizeof (struct ospf6_network_lsa); 1468 network_lsa = (struct ospf6_network_lsa *) buffer; 1469 router_id = (u_int32_t *)(network_lsa + 1); 1470 1471 /* set fields of myself */ 1472 *router_id++ = o6i->area->ospf6->router_id; 1473 size += sizeof (u_int32_t); 1474 network_lsa->options[0] |= o6i->area->options[0]; 1475 network_lsa->options[1] |= o6i->area->options[1]; 1476 network_lsa->options[2] |= o6i->area->options[2]; 1477 1478 /* Walk through neighbors */ 1479 for (node = listhead (o6i->neighbor_list); node; nextnode (node)) 1480 { 1481 o6n = (struct ospf6_neighbor *) getdata (node); 1482 1483 if (o6n->state != NBS_FULL) 1484 continue; 1485 1486 /* set this neighbor's Router-ID to LSA */ 1487 *router_id++ = o6n->router_id; 1488 size += sizeof (u_int32_t); 1489 1490 /* options field is logical OR */ 1491 network_lsa->options[0] |= o6n->options[0]; 1492 network_lsa->options[1] |= o6n->options[1]; 1493 network_lsa->options[2] |= o6n->options[2]; 1494 } 1495 1496 ospf6_lsa_originate (htons (OSPF6_LSA_TYPE_NETWORK), 1497 htonl (o6i->if_id), o6i->area->ospf6->router_id, 1498 (char *) network_lsa, size, o6i->area); 1499} 1500 1501int 1502ospf6_lsa_network_hook_neighbor (void *neighbor) 1503{ 1504 struct ospf6_neighbor *o6n = neighbor; 1505 ospf6_lsa_network_update (o6n->ospf6_interface->interface->name); 1506 return 0; 1507} 1508 1509int 1510ospf6_lsa_network_hook_interface (void *interface) 1511{ 1512 struct ospf6_interface *o6i = interface; 1513 if (o6i->area) 1514 ospf6_lsa_network_update (o6i->interface->name); 1515 return 0; 1516} 1517 1518int 1519ospf6_lsa_network_refresh (void *old) 1520{ 1521 struct ospf6_lsa *lsa = old; 1522 struct interface *ifp; 1523 1524 ifp = if_lookup_by_index (ntohl (lsa->header->id)); 1525 if (! ifp) 1526 ospf6_lsa_premature_aging (old); 1527 else 1528 ospf6_lsa_network_update (ifp->name); 1529 1530 return 0; 1531} 1532 1533void 1534ospf6_lsa_slot_register_network () 1535{ 1536 struct ospf6_lsa_slot slot; 1537 struct ospf6_hook hook; 1538 1539 memset (&slot, 0, sizeof (struct ospf6_lsa_slot)); 1540 slot.type = htons (OSPF6_LSA_TYPE_NETWORK); 1541 slot.name = "Network"; 1542 slot.func_show = ospf6_lsa_network_show; 1543 slot.func_refresh = ospf6_lsa_network_refresh; 1544 ospf6_lsa_slot_register (&slot); 1545 1546 ospf6_lsdb_hook[OSPF6_LSA_TYPE_NETWORK & OSPF6_LSTYPE_CODE_MASK].hook = 1547 ospf6_spf_database_hook; 1548 1549 memset (&hook, 0, sizeof (hook)); 1550 hook.name = "OriginateNetwork"; 1551 hook.hook_change = ospf6_lsa_network_hook_neighbor; 1552 ospf6_hook_register (&hook, &neighbor_hook); 1553 1554 memset (&hook, 0, sizeof (hook)); 1555 hook.name = "OriginateNetwork"; 1556 hook.hook_change = ospf6_lsa_network_hook_interface; 1557 ospf6_hook_register (&hook, &interface_hook); 1558} 1559 1560/****************************/ 1561/* RFC2740 3.4.3.6 Link-LSA */ 1562/****************************/ 1563 1564int 1565ospf6_lsa_link_show (struct vty *vty, struct ospf6_lsa *lsa) 1566{ 1567 char *start, *end, *current; 1568 struct ospf6_link_lsa *link_lsa; 1569 int prefixnum; 1570 struct ospf6_prefix *prefix; 1571 char buf[128]; 1572 struct in6_addr in6; 1573 1574 assert (lsa->header); 1575 1576 link_lsa = (struct ospf6_link_lsa *) (lsa->header + 1); 1577 prefixnum = ntohl (link_lsa->llsa_prefix_num); 1578 1579 inet_ntop (AF_INET6, (void *)&link_lsa->llsa_linklocal, buf, sizeof (buf)); 1580 vty_out (vty, " LinkLocal Address: %s%s", buf, VTY_NEWLINE); 1581 vty_out (vty, " Number of Prefix: %d%s", prefixnum, VTY_NEWLINE); 1582 1583 start = (char *) link_lsa + sizeof (struct ospf6_link_lsa); 1584 end = (char *) lsa->header + ntohs (lsa->header->length); 1585 for (current = start; current < end; current += OSPF6_PREFIX_SIZE (prefix)) 1586 { 1587 prefix = (struct ospf6_prefix *) current; 1588 if (current + OSPF6_PREFIX_SIZE (prefix) > end) 1589 { 1590 vty_out (vty, " Trailing %d byte garbage ... Malformed%s", 1591 end - current, VTY_NEWLINE); 1592 return -1; 1593 } 1594 1595 ospf6_prefix_options_str (prefix->prefix_options, buf, sizeof (buf)); 1596 vty_out (vty, " Prefix Options: %s%s", buf, VTY_NEWLINE); 1597 ospf6_prefix_in6_addr (prefix, &in6); 1598 inet_ntop (AF_INET6, &in6, buf, sizeof (buf)); 1599 vty_out (vty, " Prefix: %s/%d%s", 1600 buf, prefix->prefix_length, VTY_NEWLINE); 1601 } 1602 1603 return 0; 1604} 1605 1606 1607void 1608ospf6_lsa_link_update (char *ifname) 1609{ 1610 char *cp, buffer [MAXLSASIZE], buf[32]; 1611 u_int16_t size; 1612 struct ospf6_lsa *old; 1613 struct interface *ifp; 1614 struct ospf6_interface *o6i; 1615 1616 struct ospf6_link_lsa *link_lsa; 1617 struct ospf6_prefix *p; 1618 list prefix_connected; 1619 listnode node; 1620 struct connected *c; 1621 1622 ifp = if_lookup_by_name (ifname); 1623 if (! ifp) 1624 { 1625 if (IS_OSPF6_DUMP_LSA) 1626 zlog_info ("Update Link: No such Interface: %s", ifname); 1627 return; 1628 } 1629 1630 o6i = (struct ospf6_interface *) ifp->info; 1631 if (! o6i || ! o6i->area) 1632 { 1633 if (IS_OSPF6_DUMP_LSA) 1634 zlog_info ("Update Link: Interface not enabled: %s", ifname); 1635 return; 1636 } 1637 1638#if 0 1639 /* Link-LSA is on Broadcast or NBMA */ 1640 if (! if_is_broadcast (o6i->interface) /* && ! NBMA xxx */) 1641 { 1642 return; 1643 } 1644#endif /*0*/ 1645 1646 /* find previous LSA */ 1647 old = ospf6_lsdb_lookup (htons (OSPF6_LSA_TYPE_LINK), htonl (o6i->if_id), 1648 ospf6->router_id, o6i->area); 1649 1650 /* can't make Link-LSA if linklocal address not set */ 1651 if (! o6i->lladdr) 1652 { 1653 if (IS_OSPF6_DUMP_LSA) 1654 zlog_warn ("Update Link: No Linklocal Address: %s", 1655 o6i->interface->name); 1656 if (old) 1657 ospf6_lsa_premature_aging (old); 1658 return; 1659 } 1660 1661 if (IS_OSPF6_DUMP_LSA) 1662 zlog_info ("Update Link: Interface %s", o6i->interface->name); 1663 1664 if (! ospf6_interface_is_enabled (o6i->interface->ifindex)) 1665 { 1666 if (IS_OSPF6_DUMP_LSA) 1667 zlog_info (" Interface %s not enabled", o6i->interface->name); 1668 if (old) 1669 ospf6_lsa_premature_aging (old); 1670 return; 1671 } 1672 1673 /* check connected prefix */ 1674 prefix_connected = list_new (); 1675 for (node = listhead (o6i->interface->connected); node; nextnode (node)) 1676 { 1677 c = (struct connected *) getdata (node); 1678 1679 /* filter prefix not IPv6 */ 1680 if (c->address->family != AF_INET6) 1681 continue; 1682 1683 /* for log */ 1684 prefix2str (c->address, buf, sizeof (buf)); 1685 1686 CONTINUE_IF_ADDRESS_LINKLOCAL (c->address); 1687 CONTINUE_IF_ADDRESS_UNSPECIFIED (c->address); 1688 CONTINUE_IF_ADDRESS_LOOPBACK (c->address); 1689 CONTINUE_IF_ADDRESS_V4COMPAT (c->address); 1690 CONTINUE_IF_ADDRESS_V4MAPPED (c->address); 1691 1692 /* filter prefix specified by configuration */ 1693 if (o6i->plist_name) 1694 { 1695 struct prefix_list *plist; 1696 enum prefix_list_type result = PREFIX_PERMIT; 1697 1698 plist = prefix_list_lookup (AFI_IP6, o6i->plist_name); 1699 if (plist) 1700 result = prefix_list_apply (plist, c->address); 1701 else if (IS_OSPF6_DUMP_LSA) 1702 zlog_warn ("Update Intra-Prefix (Stub): " 1703 "Prefix list \"%s\" not found", o6i->plist_name); 1704 1705 if (result == PREFIX_DENY) 1706 { 1707 if (IS_OSPF6_DUMP_LSA) 1708 zlog_info (" Filter out Prefix-list %s: %s", 1709 o6i->plist_name, buf); 1710 continue; 1711 } 1712 } 1713 1714 if (IS_OSPF6_DUMP_LSA) 1715 zlog_info (" Advertise %s", buf); 1716 1717 /* hold prefix in list. duplicate is filtered in ospf6_prefix_add() */ 1718 p = ospf6_prefix_create (0, 0, (struct prefix_ipv6 *) c->address); 1719 ospf6_prefix_add (prefix_connected, p); 1720 } 1721 1722 /* Note: even if no prefix configured, still we have to create Link-LSA 1723 for next-hop resolution */ 1724 1725 memset (buffer, 0, sizeof (buffer)); 1726 size = sizeof (struct ospf6_link_lsa); 1727 link_lsa = (struct ospf6_link_lsa *) buffer; 1728 1729 /* fill Link LSA and calculate size */ 1730 link_lsa->llsa_rtr_pri = o6i->priority; 1731 link_lsa->llsa_options[0] = o6i->area->options[0]; 1732 link_lsa->llsa_options[1] = o6i->area->options[1]; 1733 link_lsa->llsa_options[2] = o6i->area->options[2]; 1734 1735 /* linklocal address */ 1736 memcpy (&link_lsa->llsa_linklocal, o6i->lladdr, sizeof (struct in6_addr)); 1737 1738#ifdef KAME /* clear ifindex */ 1739 if (link_lsa->llsa_linklocal.s6_addr[3] & 0x0f) 1740 link_lsa->llsa_linklocal.s6_addr[3] &= ~((char)0x0f); 1741#endif /* KAME */ 1742 1743 link_lsa->llsa_prefix_num = htonl (listcount (prefix_connected)); 1744 cp = (char *)(link_lsa + 1); 1745 for (node = listhead (prefix_connected); node; nextnode (node)) 1746 { 1747 p = (struct ospf6_prefix *) getdata (node); 1748 size += OSPF6_PREFIX_SIZE (p); 1749 memcpy (cp, p, OSPF6_PREFIX_SIZE (p)); 1750 cp += OSPF6_PREFIX_SIZE (p); 1751 } 1752 1753 for (node = listhead (prefix_connected); node; nextnode (node)) 1754 { 1755 p = (struct ospf6_prefix *) getdata (node); 1756 ospf6_prefix_delete (p); 1757 } 1758 list_delete (prefix_connected); 1759 1760 ospf6_lsa_originate (htons (OSPF6_LSA_TYPE_LINK), 1761 htonl (o6i->if_id), o6i->area->ospf6->router_id, 1762 (char *) link_lsa, size, o6i); 1763} 1764 1765int 1766ospf6_lsa_link_hook_interface (void *interface) 1767{ 1768 struct ospf6_interface *o6i = interface; 1769 if (o6i->area) 1770 ospf6_lsa_link_update (o6i->interface->name); 1771 return 0; 1772} 1773 1774int 1775ospf6_lsa_link_refresh (void *old) 1776{ 1777 struct ospf6_lsa *lsa = old; 1778 struct interface *ifp; 1779 1780 ifp = if_lookup_by_index (ntohl (lsa->header->id)); 1781 if (! ifp) 1782 ospf6_lsa_premature_aging (old); 1783 else 1784 ospf6_lsa_link_update (ifp->name); 1785 1786 return 0; 1787} 1788 1789void 1790ospf6_lsa_slot_register_link () 1791{ 1792 struct ospf6_lsa_slot slot; 1793 1794 memset (&slot, 0, sizeof (struct ospf6_lsa_slot)); 1795 slot.type = htons (OSPF6_LSA_TYPE_LINK); 1796 slot.name = "Link"; 1797 slot.func_show = ospf6_lsa_link_show; 1798 slot.func_refresh = ospf6_lsa_link_refresh; 1799 slot.hook_interface.name = "OriginateLink"; 1800 slot.hook_interface.hook_change = ospf6_lsa_link_hook_interface; 1801 ospf6_lsa_slot_register (&slot); 1802 1803 /* 1804 * Link LSA handling will be shift in ospf6_intra.c 1805 * Currently, only database hook only moved to ospf6_intra.c 1806 */ 1807#if 0 1808 ospf6_lsdb_hook[OSPF6_LSA_TYPE_LINK & OSPF6_LSTYPE_CODE_MASK].hook = 1809 ospf6_spf_database_hook; 1810#endif /*0*/ 1811} 1812 1813int 1814ospf6_lsa_add_hook (void *data) 1815{ 1816 struct ospf6_lsa *lsa = data; 1817 struct ospf6_lsa_slot *sp; 1818 1819 sp = ospf6_lsa_slot_get (lsa->header->type); 1820 if (sp) 1821 { 1822 CALL_CHANGE_HOOK (&sp->database_hook, lsa); 1823 } 1824 else 1825 zlog_warn ("Unknown LSA added to database: %s", lsa->str); 1826 return 0; 1827} 1828 1829int 1830ospf6_lsa_change_hook (void *data) 1831{ 1832 struct ospf6_lsa *lsa = data; 1833 struct ospf6_lsa_slot *sp; 1834 1835 sp = ospf6_lsa_slot_get (lsa->header->type); 1836 if (sp) 1837 { 1838 CALL_CHANGE_HOOK (&sp->database_hook, lsa); 1839 } 1840 else 1841 zlog_warn ("Unknown LSA changed in database: %s", lsa->str); 1842 return 0; 1843} 1844 1845int 1846ospf6_lsa_remove_hook (void *data) 1847{ 1848 struct ospf6_lsa *lsa = data; 1849 struct ospf6_lsa_slot *sp; 1850 1851 sp = ospf6_lsa_slot_get (lsa->header->type); 1852 if (sp) 1853 { 1854 CALL_REMOVE_HOOK (&sp->database_hook, lsa); 1855 } 1856 else 1857 zlog_warn ("Unknown LSA removed from database: %s", lsa->str); 1858 return 0; 1859} 1860 1861/* Initialize LSA slots */ 1862void 1863ospf6_lsa_init () 1864{ 1865 struct ospf6_hook hook; 1866 1867 slot_head = NULL; 1868 ospf6_lsa_slot_register_router (); 1869 ospf6_lsa_slot_register_network (); 1870 ospf6_lsa_slot_register_link (); 1871#if 0 1872 ospf6_lsa_slot_register_intra_prefix (); 1873 ospf6_lsa_slot_register_as_external (); 1874#endif /*0*/ 1875 1876 hook.name = "LSADatabaseHook"; 1877 hook.hook_add = ospf6_lsa_add_hook; 1878 hook.hook_change = ospf6_lsa_change_hook; 1879 hook.hook_remove = ospf6_lsa_remove_hook; 1880 ospf6_hook_register (&hook, &database_hook); 1881} 1882 1883