1/* 2 * Copyright (C) 1999 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 "ospf6d.h" 23 24/* check validity and put lsa in reqestlist if needed. */ 25/* returns -1 if SeqNumMismatch required. */ 26int 27ospf6_dbex_check_dbdesc_lsa_header (struct ospf6_lsa_header *lsa_header, 28 struct ospf6_neighbor *from) 29{ 30 struct ospf6_lsa *received = NULL; 31 struct ospf6_lsa *have = NULL; 32 33 received = ospf6_lsa_summary_create 34 ((struct ospf6_lsa_header__ *) lsa_header); 35 36 /* case when received is AS-External though neighbor belongs stub area */ 37 if (lsa_header->type == htons (OSPF6_LSA_TYPE_AS_EXTERNAL) && 38 ospf6_area_is_stub (from->ospf6_interface->area)) 39 { 40 zlog_err ("DbDesc %s receive from %s", from->str, received->str); 41 zlog_err (" E-bit mismatch: %s", received->str); 42 ospf6_lsa_delete (received); 43 return -1; 44 } 45 46 /* if already have newer database copy, check next LSA */ 47 have = ospf6_lsdb_lookup (lsa_header->type, lsa_header->ls_id, 48 lsa_header->advrtr, 49 ospf6_lsa_get_scope (lsa_header->type, 50 from->ospf6_interface)); 51 if (! have) 52 { 53 /* if we don't have database copy, add request */ 54 if (IS_OSPF6_DUMP_DBEX) 55 zlog_info ("Have no database copy, Request"); 56 ospf6_neighbor_request_add (received, from); 57 } 58 else if (have) 59 { 60 /* if database copy is less recent, add request */ 61 if (ospf6_lsa_check_recent (received, have) < 0) 62 { 63 if (IS_OSPF6_DUMP_DBEX) 64 zlog_info ("Database copy less recent, Request"); 65 ospf6_neighbor_request_add (received, from); 66 } 67 } 68 69 return 0; 70} 71 72/* Direct acknowledgement */ 73static void 74ospf6_dbex_acknowledge_direct (struct ospf6_lsa *lsa, 75 struct ospf6_neighbor *o6n) 76{ 77 struct iovec directack[MAXIOVLIST]; 78 assert (lsa); 79 80 if (IS_OSPF6_DUMP_DBEX) 81 zlog_info ("DBEX: [%s:%s] direct ack %s ", 82 o6n->str, o6n->ospf6_interface->interface->name, 83 lsa->str); 84 85 /* clear pointers to fragments of packet for direct acknowledgement */ 86 iov_clear (directack, MAXIOVLIST); 87 88 /* set pointer of LSA to send */ 89 OSPF6_MESSAGE_ATTACH (directack, lsa->header, 90 sizeof (struct ospf6_lsa_header)); 91 92 /* age update and add InfTransDelay */ 93 ospf6_lsa_age_update_to_send (lsa, o6n->ospf6_interface->transdelay); 94 95 /* send unicast packet to neighbor's ipaddress */ 96 ospf6_message_send (OSPF6_MESSAGE_TYPE_LSACK, directack, &o6n->hisaddr, 97 o6n->ospf6_interface->if_id); 98} 99 100/* Delayed acknowledgement */ 101void 102ospf6_dbex_acknowledge_delayed (struct ospf6_lsa *lsa, 103 struct ospf6_interface *o6i) 104{ 105 assert (o6i); 106 107 if (IS_OSPF6_DUMP_DBEX) 108 zlog_info ("DBEX: [%s] delayed ack %s", o6i->interface->name, lsa->str); 109 110 /* attach delayed acknowledge list */ 111 ospf6_lsa_age_current (lsa); 112 ospf6_interface_delayed_ack_add (lsa, o6i); 113 114 /* if not yet, schedule delayed acknowledge RxmtInterval later. 115 timers should be *less than* RxmtInterval 116 or needless retrans will ensue */ 117 if (o6i->thread_send_lsack_delayed == NULL) 118 o6i->thread_send_lsack_delayed 119 = thread_add_timer (master, ospf6_send_lsack_delayed, 120 o6i, o6i->rxmt_interval - 1); 121 122 return; 123} 124 125/* RFC2328 section 13 (4): 126 if MaxAge LSA and if we have no instance, and no neighbor 127 is in states Exchange or Loading */ 128/* returns 1 if match this case, else returns 0 */ 129static int 130ospf6_dbex_is_maxage_to_be_dropped (struct ospf6_lsa *received, 131 struct ospf6_neighbor *from) 132{ 133 int count; 134 135 if (! IS_LSA_MAXAGE (received)) 136 return 0; 137 138 if (ospf6_lsdb_lookup (received->header->type, received->header->id, 139 received->header->adv_router, 140 ospf6_lsa_get_scope (received->header->type, 141 from->ospf6_interface))) 142 return 0; 143 144 if (OSPF6_LSA_IS_SCOPE_LINKLOCAL (ntohs (received->header->type))) 145 { 146 count = 0; 147 (*from->ospf6_interface->foreach_nei) 148 (from->ospf6_interface, &count, NBS_EXCHANGE, ospf6_count_state); 149 (*from->ospf6_interface->foreach_nei) 150 (from->ospf6_interface, &count, NBS_LOADING, ospf6_count_state); 151 if (count) 152 return 0; 153 } 154 else if (OSPF6_LSA_IS_SCOPE_AREA (ntohs (received->header->type))) 155 { 156 count = 0; 157 (*from->ospf6_interface->area->foreach_nei) 158 (from->ospf6_interface->area, &count, NBS_EXCHANGE, ospf6_count_state); 159 (*from->ospf6_interface->area->foreach_nei) 160 (from->ospf6_interface->area, &count, NBS_LOADING, ospf6_count_state); 161 if (count) 162 return 0; 163 } 164 else if (OSPF6_LSA_IS_SCOPE_AS (ntohs (received->header->type))) 165 { 166 count = 0; 167 (*from->ospf6_interface->area->ospf6->foreach_nei) 168 (from->ospf6_interface->area->ospf6, &count, NBS_EXCHANGE, 169 ospf6_count_state); 170 (*from->ospf6_interface->area->ospf6->foreach_nei) 171 (from->ospf6_interface->area->ospf6, &count, NBS_LOADING, 172 ospf6_count_state); 173 if (count) 174 return 0; 175 } 176 177 return 1; 178} 179 180static void 181ospf6_dbex_remove_retrans (void *arg, int val, void *obj) 182{ 183 struct ospf6_lsa *rem; 184 struct ospf6_neighbor *nei = (struct ospf6_neighbor *) obj; 185 struct ospf6_lsa *lsa = (struct ospf6_lsa *) arg; 186 187 rem = ospf6_lsdb_lookup_lsdb (lsa->header->type, lsa->header->id, 188 lsa->header->adv_router, nei->retrans_list); 189 if (rem) 190 { 191 ospf6_neighbor_retrans_remove (rem, nei); 192 ospf6_maxage_remover (); 193 } 194} 195 196void 197ospf6_dbex_remove_from_all_retrans_list (struct ospf6_lsa *lsa) 198{ 199 struct ospf6_interface *o6i; 200 struct ospf6_area *o6a; 201 202 if (OSPF6_LSA_IS_SCOPE_LINKLOCAL (htons (lsa->header->type))) 203 { 204 o6i = lsa->scope; 205 (*o6i->foreach_nei) (o6i, lsa, 0, ospf6_dbex_remove_retrans); 206 } 207 else if (OSPF6_LSA_IS_SCOPE_AREA (htons (lsa->header->type))) 208 { 209 o6a = lsa->scope; 210 (*o6a->foreach_nei) (o6a, lsa, 0, ospf6_dbex_remove_retrans); 211 } 212 else if (OSPF6_LSA_IS_SCOPE_AS (htons (lsa->header->type))) 213 { 214 (*ospf6->foreach_nei) (ospf6, lsa, 0, ospf6_dbex_remove_retrans); 215 } 216} 217 218/* RFC2328 section 13 */ 219void 220ospf6_dbex_receive_lsa (struct ospf6_lsa_header *lsa_header, 221 struct ospf6_neighbor *from) 222{ 223 struct ospf6_lsa *received, *have, *rem; 224 struct timeval now; 225 int ismore_recent, acktype; 226 unsigned short cksum; 227 struct ospf6_lsa_slot *slot; 228 229 received = have = (struct ospf6_lsa *)NULL; 230 ismore_recent = -1; 231 recent_reason = "no instance"; 232 233 /* make lsa structure for received lsa */ 234 received = ospf6_lsa_create (lsa_header); 235 236 if (IS_OSPF6_DUMP_DBEX) 237 zlog_info ("Receive %s from %s", received->str, from->str); 238 239 /* set LSA scope */ 240 if (OSPF6_LSA_IS_SCOPE_LINKLOCAL (htons (lsa_header->type))) 241 received->scope = from->ospf6_interface; 242 else if (OSPF6_LSA_IS_SCOPE_AREA (htons (lsa_header->type))) 243 received->scope = from->ospf6_interface->area; 244 else if (OSPF6_LSA_IS_SCOPE_AS (htons (lsa_header->type))) 245 received->scope = from->ospf6_interface->area->ospf6; 246 247 /* (1) LSA Checksum */ 248 cksum = ntohs (lsa_header->checksum); 249 if (ntohs (ospf6_lsa_checksum (lsa_header)) != cksum) 250 { 251 zlog_warn ("DBEX: LSA cksum wrong: %s checksum %#hx should be %#hx", 252 received->str, cksum, ntohs (ospf6_lsa_checksum (lsa_header))); 253 ospf6_lsa_delete (received); 254 return; 255 } 256 257#if 0 258 /* (2) warn if unknown */ 259 if (! ospf6_lsa_is_known_type (lsa_header)) 260 zlog_warn ("[%s:%s] receive LSA unknown: %#x", 261 from->str, from->ospf6_interface->interface->name, 262 ntohs (lsa_header->type)); 263#endif /*0*/ 264 265 /* (3) Ebit Missmatch: AS-External-LSA */ 266 if (lsa_header->type == htons (OSPF6_LSA_TYPE_AS_EXTERNAL) && 267 ospf6_area_is_stub (from->ospf6_interface->area)) 268 { 269 zlog_err ("DBEX: [%s:%s] receive LSA E-bit mismatch: %s", 270 from->str, from->ospf6_interface->interface->name, 271 received->str); 272 ospf6_lsa_delete (received); 273 return; 274 } 275 276 /* (4) if MaxAge LSA and if we have no instance, and no neighbor 277 is in states Exchange or Loading */ 278 if (ospf6_dbex_is_maxage_to_be_dropped (received, from)) 279 { 280 /* log */ 281 if (IS_OSPF6_DUMP_DBEX) 282 zlog_info ("Drop MaxAge LSA: no instance, no neighbor " 283 "exchanging DB: %s", received->str); 284 285 /* a) Acknowledge back to neighbor (13.5) */ 286 /* Direct Acknowledgement */ 287 ospf6_dbex_acknowledge_direct (received, from); 288 289 /* b) Discard */ 290 ospf6_lsa_delete (received); 291 return; 292 } 293 294 /* (5) */ 295 /* lookup the same database copy in lsdb */ 296 have = ospf6_lsdb_lookup (lsa_header->type, lsa_header->ls_id, 297 lsa_header->advrtr, 298 ospf6_lsa_get_scope (lsa_header->type, 299 from->ospf6_interface)); 300 if (have) 301 { 302 ismore_recent = ospf6_lsa_check_recent (received, have); 303 if (ntohl (received->header->seqnum) == ntohl (have->header->seqnum)) 304 SET_FLAG (received->flag, OSPF6_LSA_FLAG_DUPLICATE); 305 } 306 307 /* if no database copy or received is more recent */ 308 if (!have || ismore_recent < 0) 309 { 310 /* in case we have no database copy */ 311 ismore_recent = -1; 312 313 /* (a) MinLSArrival check */ 314 gettimeofday (&now, (struct timezone *)NULL); 315 if (have && now.tv_sec - have->installed.tv_sec <= OSPF6_MIN_LS_ARRIVAL) 316 { 317 if (IS_OSPF6_DUMP_DBEX) 318 zlog_info ("DBEX: [%s:%s] received LSA too soon: %s", 319 from->str, from->ospf6_interface->interface->name, 320 received->str); 321 322 /* this will do free this lsa */ 323 ospf6_lsa_delete (received); 324 return; /* examin next lsa */ 325 } 326 327 /* (b) immediately flood */ 328 ospf6_dbex_flood (received, from); 329 330#if 0 331 /* Because New LSDB do not permit two LSA having the same identifier 332 exist in a LSDB list, above ospf6_dbex_flood() will remove 333 the old instance automatically. thus bellow is not needed. */ 334 /* (c) remove database copy from all neighbor's retranslist */ 335 if (have) 336 ospf6_dbex_remove_from_all_retrans_list (have); 337#endif 338 339 /* (d), installing lsdb, which may cause routing 340 table calculation (replacing database copy) */ 341 ospf6_lsdb_install (received); 342 343 /* (e) possibly acknowledge */ 344 acktype = ack_type (received, ismore_recent, from); 345 if (acktype == DIRECT_ACK) 346 { 347 ospf6_dbex_acknowledge_direct (received, from); 348 } 349 else if (acktype == DELAYED_ACK) 350 { 351 ospf6_dbex_acknowledge_delayed (received, from->ospf6_interface); 352 } 353 else 354 { 355 if (IS_OSPF6_DUMP_DBEX) 356 zlog_info ("DBEX: [%s:%s] don't ack %s", 357 from->str, from->ospf6_interface->interface->name, 358 received->str); 359 } 360 361 /* (f) */ 362 /* Self Originated LSA, section 13.4 */ 363 if (received->lsa_hdr->lsh_advrtr == ospf6->router_id 364 && have && ismore_recent < 0) 365 { 366 /* we're going to make new lsa or to flush this LSA. */ 367 if (IS_OSPF6_DUMP_DBEX) 368 zlog_info ("DBEX: Self-originated LSA %s from %s:%s", 369 received->str, from->str, 370 from->ospf6_interface->interface->name); 371 if (IS_OSPF6_DUMP_DBEX) 372 zlog_info ("DBEX: %s: Make new one/Flush", received->str); 373 374 SET_FLAG (received->flag, OSPF6_LSA_FLAG_REFRESH); 375 slot = ospf6_lsa_slot_get (received->header->type); 376 if (slot && slot->func_refresh) 377 { 378 (*slot->func_refresh) (received); 379 return; 380 } 381 382 zlog_warn ("Can't Refresh LSA: Unknown type: %#x, Flush", 383 ntohs (received->header->type)); 384 ospf6_lsa_premature_aging (received); 385 return; 386 } 387 } 388 else if (ospf6_lsdb_lookup_lsdb (received->header->type, 389 received->header->id, 390 received->header->adv_router, 391 from->request_list)) 392 /* (6) if there is instance on sending neighbor's request list */ 393 { 394 /* if no database copy, should go above state (5) */ 395 assert (have); 396 397 zlog_warn ("DBEX: [%s:%s] received LSA %s is not newer," 398 " and is on his requestlist: Generate BadLSReq", 399 from->str, from->ospf6_interface->interface->name, 400 received->str); 401 402 /* BadLSReq */ 403 thread_add_event (master, bad_lsreq, from, 0); 404 405 ospf6_lsa_delete (received); 406 } 407 else if (ismore_recent == 0) /* (7) if neither is more recent */ 408 { 409 /* (a) if on retranslist, Treat this LSA as an Ack: Implied Ack */ 410 rem = ospf6_lsdb_lookup_lsdb (received->header->type, 411 received->header->id, 412 received->header->adv_router, 413 from->retrans_list); 414 if (rem) 415 { 416 SET_FLAG (received->flag, OSPF6_LSA_FLAG_IMPLIEDACK); 417 ospf6_neighbor_retrans_remove (rem, from); 418 } 419 420 /* (b) possibly acknowledge */ 421 acktype = ack_type (received, ismore_recent, from); 422 if (acktype == DIRECT_ACK) 423 { 424 ospf6_dbex_acknowledge_direct (received, from); 425 } 426 else if (acktype == DELAYED_ACK) 427 { 428 ospf6_dbex_acknowledge_delayed (received, from->ospf6_interface); 429 } 430 else 431 { 432 if (IS_OSPF6_DUMP_DBEX) 433 zlog_info ("DBEX: [%s:%s] will no ack %s", 434 from->str, from->ospf6_interface->interface->name, 435 received->str); 436 } 437 ospf6_lsa_delete (received); 438 } 439 else /* (8) previous database copy is more recent */ 440 { 441 /* If Seqnumber Wrapping, simply discard 442 Otherwise, Send database copy of this LSA to this neighbor */ 443 if (! IS_LSA_MAXAGE (received) || 444 received->lsa_hdr->lsh_seqnum != MAX_SEQUENCE_NUMBER) 445 { 446 ospf6_send_lsupdate_direct (have, from); 447 } 448 ospf6_lsa_delete (received); 449 } 450} 451 452/* RFC2328: Table 19: Sending link state acknowledgements. */ 453int 454ack_type (struct ospf6_lsa *newp, int ismore_recent, 455 struct ospf6_neighbor *from) 456{ 457 struct ospf6_interface *ospf6_interface; 458 struct ospf6_neighbor *nbr; 459 listnode n, m; 460 461 assert (from && from->ospf6_interface); 462 ospf6_interface = from->ospf6_interface; 463 464 if (CHECK_FLAG (newp->flag, OSPF6_LSA_FLAG_FLOODBACK)) 465 { 466 return NO_ACK; 467 } 468 else if (ismore_recent < 0 && 469 ! CHECK_FLAG (newp->flag, OSPF6_LSA_FLAG_FLOODBACK)) 470 { 471 if (ospf6_interface->state == IFS_BDR) 472 { 473 if (ospf6_interface->dr == from->router_id) 474 { 475 return DELAYED_ACK; 476 } 477 else 478 { 479 return NO_ACK; 480 } 481 } 482 else 483 { 484 return DELAYED_ACK; 485 } 486 } 487 else if (CHECK_FLAG (newp->flag, OSPF6_LSA_FLAG_DUPLICATE) && 488 CHECK_FLAG (newp->flag, OSPF6_LSA_FLAG_IMPLIEDACK)) 489 { 490 if (ospf6_interface->state == IFS_BDR) 491 { 492 if (ospf6_interface->dr == from->router_id) 493 { 494 return DELAYED_ACK; 495 } 496 else 497 { 498 return NO_ACK; 499 } 500 } 501 else 502 { 503 return NO_ACK; 504 } 505 } 506 else if (CHECK_FLAG (newp->flag, OSPF6_LSA_FLAG_DUPLICATE) && 507 ! CHECK_FLAG (newp->flag, OSPF6_LSA_FLAG_IMPLIEDACK)) 508 { 509 return DIRECT_ACK; 510 } 511 else if (IS_LSA_MAXAGE (newp)) 512 { 513 if (! ospf6_lsdb_lookup (newp->header->type, newp->header->id, 514 newp->header->adv_router, 515 ospf6_lsa_get_scope (newp->header->type, 516 from->ospf6_interface))) 517 { 518 for (n = listhead (from->ospf6_interface->area->if_list); 519 n; nextnode (n)) 520 { 521 ospf6_interface = (struct ospf6_interface *) getdata (n); 522 for (m = listhead (ospf6_interface->neighbor_list); 523 m; nextnode (m)) 524 { 525 nbr = (struct ospf6_neighbor *) getdata (m); 526 if (nbr->state == NBS_EXCHANGE || nbr->state == NBS_LOADING) 527 { 528 return NO_ACK; 529 } 530 } 531 } 532 return DIRECT_ACK; 533 } 534 } 535 536 return NO_ACK; 537} 538 539static void 540ospf6_dbex_flood_linklocal (struct ospf6_lsa *lsa, struct ospf6_interface *o6i, 541 struct ospf6_neighbor *from) 542{ 543 struct ospf6_neighbor *o6n = (struct ospf6_neighbor *) NULL; 544 int ismore_recent, addretrans = 0; 545 listnode n; 546 struct ospf6_lsa *req; 547 548 /* (1) for each neighbor */ 549 for (n = listhead (o6i->neighbor_list); n; nextnode (n)) 550 { 551 o6n = (struct ospf6_neighbor *) getdata (n); 552 553 /* (a) */ 554 if (o6n->state < NBS_EXCHANGE) 555 continue; /* examin next neighbor */ 556 557 /* (b) */ 558 if (o6n->state == NBS_EXCHANGE 559 || o6n->state == NBS_LOADING) 560 { 561 req = ospf6_lsdb_lookup_lsdb (lsa->header->type, 562 lsa->header->id, 563 lsa->header->adv_router, 564 o6n->request_list); 565 if (req) 566 { 567 ismore_recent = ospf6_lsa_check_recent (lsa, req); 568 if (ismore_recent > 0) 569 { 570 continue; /* examin next neighbor */ 571 } 572 else if (ismore_recent == 0) 573 { 574 ospf6_neighbor_request_remove (req, o6n); 575 continue; /* examin next neighbor */ 576 } 577 else /* ismore_recent < 0 (the new LSA is more recent) */ 578 { 579 ospf6_neighbor_request_remove (req, o6n); 580 } 581 } 582 } 583 584 /* (c) */ 585 if (from && from->router_id == o6n->router_id) 586 continue; /* examin next neighbor */ 587 588 /* (d) add retranslist */ 589 if (IS_OSPF6_DUMP_DBEX) 590 zlog_info ("DBEX: schedule flooding [%s:%s]: %s", 591 o6n->str, o6n->ospf6_interface->interface->name, 592 lsa->str); 593 ospf6_neighbor_retrans_add (lsa, o6n); 594 addretrans++; 595 if (o6n->send_update == (struct thread *) NULL) 596 o6n->send_update = 597 thread_add_timer (master, ospf6_send_lsupdate_rxmt, o6n, 598 o6n->ospf6_interface->rxmt_interval); 599 } 600 601 /* (2) */ 602 if (addretrans == 0) 603 { 604 return; /* examin next interface */ 605 } 606 else if (from && from->ospf6_interface == o6i) 607 { 608 /* note occurence of floodback */ 609 SET_FLAG (lsa->flag, OSPF6_LSA_FLAG_FLOODBACK); 610 } 611 612 /* (3) */ 613 if (from && from->ospf6_interface == o6i) 614 { 615 /* if from DR or BDR, don't need to flood this interface */ 616 if (from->router_id == from->ospf6_interface->dr || 617 from->router_id == from->ospf6_interface->bdr) 618 return; /* examin next interface */ 619 } 620 621 /* (4) if I'm BDR, DR will flood this interface */ 622 if (from && from->ospf6_interface == o6i 623 && o6i->state == IFS_BDR) 624 return; /* examin next interface */ 625 626 if (IS_OSPF6_DUMP_DBEX) 627 zlog_info (" Flood to interface %s", o6i->interface->name); 628 629 /* (5) send LinkState Update */ 630 ospf6_send_lsupdate_flood (lsa, o6i); 631 632 return; 633} 634 635/* RFC2328 section 13.3 */ 636static void 637ospf6_dbex_flood_area (struct ospf6_lsa *lsa, struct ospf6_area *area, 638 struct ospf6_neighbor *from) 639{ 640 listnode n; 641 struct ospf6_interface *ospf6_interface; 642 643 assert (lsa && lsa->lsa_hdr && area); 644 645 /* for each eligible ospf_ifs */ 646 for (n = listhead (area->if_list); n; nextnode (n)) 647 { 648 ospf6_interface = (struct ospf6_interface *) getdata (n); 649 ospf6_dbex_flood_linklocal (lsa, ospf6_interface, from); 650 } 651} 652 653static void 654ospf6_dbex_flood_as (struct ospf6_lsa *lsa, struct ospf6 *ospf6, 655 struct ospf6_neighbor *from) 656{ 657 listnode n; 658 struct ospf6_area *o6a; 659 660 assert (lsa && lsa->lsa_hdr && ospf6); 661 662 /* for each attached area */ 663 for (n = listhead (ospf6->area_list); n; nextnode (n)) 664 { 665 o6a = (struct ospf6_area *) getdata (n); 666 ospf6_dbex_flood_area (lsa, o6a, from); 667 } 668} 669 670/* flood ospf6_lsa within appropriate scope */ 671void 672ospf6_dbex_flood (struct ospf6_lsa *lsa, struct ospf6_neighbor *from) 673{ 674 struct ospf6_area *o6a; 675 struct ospf6_interface *o6i; 676 struct ospf6 *o6; 677 struct ospf6_lsa_header *lsa_header; 678 679 lsa_header = (struct ospf6_lsa_header *) lsa->lsa_hdr; 680 681 if (IS_OSPF6_DUMP_DBEX) 682 zlog_info ("Flood: %s", lsa->str); 683 684 if (OSPF6_LSA_IS_SCOPE_LINKLOCAL (ntohs (lsa_header->type))) 685 { 686 o6i = (struct ospf6_interface *) lsa->scope; 687 assert (o6i); 688 689 ospf6_dbex_flood_linklocal (lsa, o6i, from); 690 } 691 else if (OSPF6_LSA_IS_SCOPE_AREA (ntohs (lsa_header->type))) 692 { 693 o6a = (struct ospf6_area *) lsa->scope; 694 assert (o6a); 695 696 ospf6_dbex_flood_area (lsa, o6a, from); 697 } 698 else if (OSPF6_LSA_IS_SCOPE_AS (ntohs (lsa_header->type))) 699 { 700 o6 = (struct ospf6 *) lsa->scope; 701 assert (o6); 702 703 ospf6_dbex_flood_as (lsa, o6, from); 704 } 705 else 706 { 707 zlog_warn ("Can't Flood %s: scope unknown", lsa->str); 708 } 709} 710 711 712