1 /* $OpenBSD: rde_lsdb.c,v 1.42 2009/01/07 21:16:36 claudio Exp $ */ 2 3 /* 4 * Copyright (c) 2004, 2005 Claudio Jeker <claudio@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/types.h> 20 #include <sys/tree.h> 21 #include <stdlib.h> 22 #include <string.h> 23 #include <unistd.h> 24 25 #include "ospf.h" 26 #include "ospfd.h" 27 #include "rde.h" 28 #include "log.h" 29 30 struct vertex *vertex_get(struct lsa *, struct rde_nbr *); 31 32 int lsa_router_check(struct lsa *, u_int16_t); 33 void lsa_timeout(int, short, void *); 34 void lsa_refresh(struct vertex *); 35 int lsa_equal(struct lsa *, struct lsa *); 36 37 RB_GENERATE(lsa_tree, vertex, entry, lsa_compare) 38 39 void 40 lsa_init(struct lsa_tree *t) 41 { 42 RB_INIT(t); 43 } 44 45 int 46 lsa_compare(struct vertex *a, struct vertex *b) 47 { 48 if (a->type < b->type) 49 return (-1); 50 if (a->type > b->type) 51 return (1); 52 if (a->ls_id < b->ls_id) 53 return (-1); 54 if (a->ls_id > b->ls_id) 55 return (1); 56 if (a->adv_rtr < b->adv_rtr) 57 return (-1); 58 if (a->adv_rtr > b->adv_rtr) 59 return (1); 60 return (0); 61 } 62 63 64 struct vertex * 65 vertex_get(struct lsa *lsa, struct rde_nbr *nbr) 66 { 67 struct vertex *v; 68 struct timespec tp; 69 70 if ((v = calloc(1, sizeof(struct vertex))) == NULL) 71 fatal(NULL); 72 TAILQ_INIT(&v->nexthop); 73 v->area = nbr->area; 74 v->peerid = nbr->peerid; 75 v->lsa = lsa; 76 clock_gettime(CLOCK_MONOTONIC, &tp); 77 v->changed = v->stamp = tp.tv_sec; 78 v->cost = LS_INFINITY; 79 v->ls_id = ntohl(lsa->hdr.ls_id); 80 v->adv_rtr = ntohl(lsa->hdr.adv_rtr); 81 v->type = lsa->hdr.type; 82 83 if (!nbr->self) 84 v->flooded = 1; /* XXX fix me */ 85 v->self = nbr->self; 86 87 evtimer_set(&v->ev, lsa_timeout, v); 88 89 return (v); 90 } 91 92 void 93 vertex_free(struct vertex *v) 94 { 95 if (v->type == LSA_TYPE_EXTERNAL) 96 RB_REMOVE(lsa_tree, &asext_tree, v); 97 else 98 RB_REMOVE(lsa_tree, &v->area->lsa_tree, v); 99 100 (void)evtimer_del(&v->ev); 101 free(v->lsa); 102 free(v); 103 } 104 105 /* returns -1 if a is older, 1 if newer and 0 if equal to b */ 106 int 107 lsa_newer(struct lsa_hdr *a, struct lsa_hdr *b) 108 { 109 int32_t a32, b32; 110 u_int16_t a16, b16; 111 int i; 112 113 if (a == NULL) 114 return (-1); 115 if (b == NULL) 116 return (1); 117 118 /* 119 * The sequence number is defined as signed 32-bit integer, 120 * no idea how IETF came up with such a stupid idea. 121 */ 122 a32 = (int32_t)ntohl(a->seq_num); 123 b32 = (int32_t)ntohl(b->seq_num); 124 125 if (a32 > b32) 126 return (1); 127 if (a32 < b32) 128 return (-1); 129 130 a16 = ntohs(a->ls_chksum); 131 b16 = ntohs(b->ls_chksum); 132 133 if (a16 > b16) 134 return (1); 135 if (a16 < b16) 136 return (-1); 137 138 a16 = ntohs(a->age); 139 b16 = ntohs(b->age); 140 141 if (a16 >= MAX_AGE && b16 >= MAX_AGE) 142 return (0); 143 if (b16 >= MAX_AGE) 144 return (-1); 145 if (a16 >= MAX_AGE) 146 return (1); 147 148 i = b16 - a16; 149 if (abs(i) > MAX_AGE_DIFF) 150 return (i > 0 ? 1 : -1); 151 152 return (0); 153 } 154 155 int 156 lsa_check(struct rde_nbr *nbr, struct lsa *lsa, u_int16_t len) 157 { 158 struct area *area = nbr->area; 159 u_int32_t metric; 160 161 if (len < sizeof(lsa->hdr)) { 162 log_warnx("lsa_check: bad packet size"); 163 return (0); 164 } 165 if (ntohs(lsa->hdr.len) != len) { 166 log_warnx("lsa_check: bad packet size"); 167 return (0); 168 } 169 170 if (iso_cksum(lsa, len, 0)) { 171 log_warnx("lsa_check: bad packet checksum"); 172 return (0); 173 } 174 175 /* invalid ages */ 176 if ((ntohs(lsa->hdr.age) < 1 && !nbr->self) || 177 ntohs(lsa->hdr.age) > MAX_AGE) { 178 log_warnx("lsa_check: bad age"); 179 return (0); 180 } 181 182 /* invalid sequence number */ 183 if (ntohl(lsa->hdr.seq_num) == RESV_SEQ_NUM) { 184 log_warnx("ls_check: bad seq num"); 185 return (0); 186 } 187 188 switch (lsa->hdr.type) { 189 case LSA_TYPE_ROUTER: 190 if (!lsa_router_check(lsa, len)) 191 return (0); 192 break; 193 case LSA_TYPE_NETWORK: 194 if ((len % sizeof(u_int32_t)) || 195 len < sizeof(lsa->hdr) + sizeof(u_int32_t)) { 196 log_warnx("lsa_check: bad LSA network packet"); 197 return (0); 198 } 199 break; 200 case LSA_TYPE_SUM_NETWORK: 201 case LSA_TYPE_SUM_ROUTER: 202 if ((len % sizeof(u_int32_t)) || 203 len < sizeof(lsa->hdr) + sizeof(lsa->data.sum)) { 204 log_warnx("lsa_check: bad LSA summary packet"); 205 return (0); 206 } 207 metric = ntohl(lsa->data.sum.metric); 208 if (metric & ~LSA_METRIC_MASK) { 209 log_warnx("lsa_check: bad LSA summary metric"); 210 return (0); 211 } 212 break; 213 case LSA_TYPE_EXTERNAL: 214 if ((len % (3 * sizeof(u_int32_t))) || 215 len < sizeof(lsa->hdr) + sizeof(lsa->data.asext)) { 216 log_warnx("lsa_check: bad LSA as-external packet"); 217 return (0); 218 } 219 metric = ntohl(lsa->data.asext.metric); 220 if (metric & ~(LSA_METRIC_MASK | LSA_ASEXT_E_FLAG)) { 221 log_warnx("lsa_check: bad LSA as-external metric"); 222 return (0); 223 } 224 /* AS-external-LSA are silently discarded in stub areas */ 225 if (area->stub) 226 return (0); 227 break; 228 default: 229 log_warnx("lsa_check: unknown type %u", lsa->hdr.type); 230 return (0); 231 } 232 233 /* MaxAge handling */ 234 if (lsa->hdr.age == htons(MAX_AGE) && !nbr->self && lsa_find(area, 235 lsa->hdr.type, lsa->hdr.ls_id, lsa->hdr.adv_rtr) == NULL && 236 !rde_nbr_loading(area)) { 237 /* 238 * if no neighbor in state Exchange or Loading 239 * ack LSA but don't add it. Needs to be a direct ack. 240 */ 241 rde_imsg_compose_ospfe(IMSG_LS_ACK, nbr->peerid, 0, &lsa->hdr, 242 sizeof(struct lsa_hdr)); 243 return (0); 244 } 245 246 return (1); 247 } 248 249 int 250 lsa_router_check(struct lsa *lsa, u_int16_t len) 251 { 252 struct lsa_rtr_link *rtr_link; 253 char *buf = (char *)lsa; 254 u_int16_t i, off, nlinks; 255 256 off = sizeof(lsa->hdr) + sizeof(struct lsa_rtr); 257 if (off > len) { 258 log_warnx("lsa_check: invalid LSA router packet"); 259 return (0); 260 } 261 262 nlinks = ntohs(lsa->data.rtr.nlinks); 263 for (i = 0; i < nlinks; i++) { 264 rtr_link = (struct lsa_rtr_link *)(buf + off); 265 off += sizeof(struct lsa_rtr_link); 266 if (off > len) { 267 log_warnx("lsa_check: invalid LSA router packet"); 268 return (0); 269 } 270 off += rtr_link->num_tos * sizeof(u_int32_t); 271 if (off > len) { 272 log_warnx("lsa_check: invalid LSA router packet"); 273 return (0); 274 } 275 } 276 277 if (i != nlinks) { 278 log_warnx("lsa_check: invalid LSA router packet"); 279 return (0); 280 } 281 return (1); 282 } 283 284 int 285 lsa_self(struct rde_nbr *nbr, struct lsa *new, struct vertex *v) 286 { 287 struct iface *iface; 288 struct lsa *dummy; 289 290 if (nbr->self) 291 return (0); 292 293 if (rde_router_id() == new->hdr.adv_rtr) 294 goto self; 295 296 if (new->hdr.type == LSA_TYPE_NETWORK) 297 LIST_FOREACH(iface, &nbr->area->iface_list, entry) 298 if (iface->addr.s_addr == new->hdr.ls_id) 299 goto self; 300 301 return (0); 302 303 self: 304 if (v == NULL) { 305 /* 306 * LSA is no longer announced, remove by premature aging. 307 * The problem is that new may not be altered so a copy 308 * needs to be added to the LSA DB first. 309 */ 310 if ((dummy = malloc(ntohs(new->hdr.len))) == NULL) 311 fatal("lsa_self"); 312 memcpy(dummy, new, ntohs(new->hdr.len)); 313 dummy->hdr.age = htons(MAX_AGE); 314 /* 315 * The clue is that by using the remote nbr as originator 316 * the dummy LSA will be reflooded via the default timeout 317 * handler. 318 */ 319 (void)lsa_add(rde_nbr_self(nbr->area), dummy); 320 return (1); 321 } 322 323 /* 324 * LSA is still originated, just reflood it. But we need to create 325 * a new instance by setting the LSA sequence number equal to the 326 * one of new and calling lsa_refresh(). Flooding will be done by the 327 * caller. 328 */ 329 v->lsa->hdr.seq_num = new->hdr.seq_num; 330 lsa_refresh(v); 331 return (1); 332 } 333 334 int 335 lsa_add(struct rde_nbr *nbr, struct lsa *lsa) 336 { 337 struct lsa_tree *tree; 338 struct vertex *new, *old; 339 struct timeval tv, now, res; 340 341 if (lsa->hdr.type == LSA_TYPE_EXTERNAL) 342 tree = &asext_tree; 343 else 344 tree = &nbr->area->lsa_tree; 345 346 new = vertex_get(lsa, nbr); 347 old = RB_INSERT(lsa_tree, tree, new); 348 349 if (old != NULL) { 350 if (old->deleted && evtimer_pending(&old->ev, &tv)) { 351 /* new update added before hold time expired */ 352 gettimeofday(&now, NULL); 353 timersub(&tv, &now, &res); 354 355 /* remove old LSA and insert new LSA with delay */ 356 vertex_free(old); 357 RB_INSERT(lsa_tree, tree, new); 358 new->deleted = 1; 359 360 if (evtimer_add(&new->ev, &res) != 0) 361 fatal("lsa_add"); 362 return (1); 363 } 364 if (!lsa_equal(new->lsa, old->lsa)) { 365 if (lsa->hdr.type != LSA_TYPE_EXTERNAL) 366 nbr->area->dirty = 1; 367 start_spf_timer(); 368 } 369 vertex_free(old); 370 RB_INSERT(lsa_tree, tree, new); 371 } else { 372 if (lsa->hdr.type != LSA_TYPE_EXTERNAL) 373 nbr->area->dirty = 1; 374 start_spf_timer(); 375 } 376 377 /* timeout handling either MAX_AGE or LS_REFRESH_TIME */ 378 timerclear(&tv); 379 380 if (nbr->self && ntohs(new->lsa->hdr.age) == DEFAULT_AGE) 381 tv.tv_sec = LS_REFRESH_TIME; 382 else 383 tv.tv_sec = MAX_AGE - ntohs(new->lsa->hdr.age); 384 385 if (evtimer_add(&new->ev, &tv) != 0) 386 fatal("lsa_add"); 387 return (0); 388 } 389 390 void 391 lsa_del(struct rde_nbr *nbr, struct lsa_hdr *lsa) 392 { 393 struct vertex *v; 394 struct timeval tv; 395 396 v = lsa_find(nbr->area, lsa->type, lsa->ls_id, lsa->adv_rtr); 397 if (v == NULL) 398 return; 399 400 v->deleted = 1; 401 /* hold time to make sure that a new lsa is not added premature */ 402 timerclear(&tv); 403 tv.tv_sec = MIN_LS_INTERVAL; 404 if (evtimer_add(&v->ev, &tv) == -1) 405 fatal("lsa_del"); 406 } 407 408 void 409 lsa_age(struct vertex *v) 410 { 411 struct timespec tp; 412 time_t now; 413 int d; 414 u_int16_t age; 415 416 clock_gettime(CLOCK_MONOTONIC, &tp); 417 now = tp.tv_sec; 418 419 d = now - v->stamp; 420 /* set stamp so that at least new calls work */ 421 v->stamp = now; 422 423 if (d < 0) { 424 log_warnx("lsa_age: time went backwards"); 425 return; 426 } 427 428 age = ntohs(v->lsa->hdr.age); 429 if (age + d > MAX_AGE) 430 age = MAX_AGE; 431 else 432 age += d; 433 434 v->lsa->hdr.age = htons(age); 435 } 436 437 struct vertex * 438 lsa_find(struct area *area, u_int8_t type, u_int32_t ls_id, u_int32_t adv_rtr) 439 { 440 struct vertex key; 441 struct vertex *v; 442 struct lsa_tree *tree; 443 444 key.ls_id = ntohl(ls_id); 445 key.adv_rtr = ntohl(adv_rtr); 446 key.type = type; 447 448 if (type == LSA_TYPE_EXTERNAL) 449 tree = &asext_tree; 450 else 451 tree = &area->lsa_tree; 452 453 v = RB_FIND(lsa_tree, tree, &key); 454 455 /* LSA that are deleted are not findable */ 456 if (v && v->deleted) 457 return (NULL); 458 459 if (v) 460 lsa_age(v); 461 462 return (v); 463 } 464 465 struct vertex * 466 lsa_find_net(struct area *area, u_int32_t ls_id) 467 { 468 struct lsa_tree *tree = &area->lsa_tree; 469 struct vertex *v; 470 471 /* XXX speed me up */ 472 RB_FOREACH(v, lsa_tree, tree) { 473 if (v->lsa->hdr.type == LSA_TYPE_NETWORK && 474 v->lsa->hdr.ls_id == ls_id) { 475 /* LSA that are deleted are not findable */ 476 if (v->deleted) 477 return (NULL); 478 lsa_age(v); 479 return (v); 480 } 481 } 482 483 return (NULL); 484 } 485 486 u_int16_t 487 lsa_num_links(struct vertex *v) 488 { 489 switch (v->type) { 490 case LSA_TYPE_ROUTER: 491 return (ntohs(v->lsa->data.rtr.nlinks)); 492 case LSA_TYPE_NETWORK: 493 return ((ntohs(v->lsa->hdr.len) - sizeof(struct lsa_hdr) 494 - sizeof(u_int32_t)) / sizeof(struct lsa_net_link)); 495 default: 496 fatalx("lsa_num_links: invalid LSA type"); 497 } 498 499 return (0); 500 } 501 502 void 503 lsa_snap(struct area *area, u_int32_t peerid) 504 { 505 struct lsa_tree *tree = &area->lsa_tree; 506 struct vertex *v; 507 508 do { 509 RB_FOREACH(v, lsa_tree, tree) { 510 if (v->deleted) 511 continue; 512 lsa_age(v); 513 if (ntohs(v->lsa->hdr.age) >= MAX_AGE) 514 rde_imsg_compose_ospfe(IMSG_LS_UPD, peerid, 515 0, &v->lsa->hdr, ntohs(v->lsa->hdr.len)); 516 else 517 rde_imsg_compose_ospfe(IMSG_DB_SNAPSHOT, peerid, 518 0, &v->lsa->hdr, sizeof(struct lsa_hdr)); 519 } 520 if (tree != &area->lsa_tree || area->stub) 521 break; 522 tree = &asext_tree; 523 } while (1); 524 } 525 526 void 527 lsa_dump(struct lsa_tree *tree, int imsg_type, pid_t pid) 528 { 529 struct vertex *v; 530 531 RB_FOREACH(v, lsa_tree, tree) { 532 if (v->deleted) 533 continue; 534 lsa_age(v); 535 switch (imsg_type) { 536 case IMSG_CTL_SHOW_DATABASE: 537 rde_imsg_compose_ospfe(IMSG_CTL_SHOW_DATABASE, 0, pid, 538 &v->lsa->hdr, ntohs(v->lsa->hdr.len)); 539 continue; 540 case IMSG_CTL_SHOW_DB_SELF: 541 if (v->lsa->hdr.adv_rtr == rde_router_id()) 542 break; 543 continue; 544 case IMSG_CTL_SHOW_DB_EXT: 545 if (v->type == LSA_TYPE_EXTERNAL) 546 break; 547 continue; 548 case IMSG_CTL_SHOW_DB_NET: 549 if (v->type == LSA_TYPE_NETWORK) 550 break; 551 continue; 552 case IMSG_CTL_SHOW_DB_RTR: 553 if (v->type == LSA_TYPE_ROUTER) 554 break; 555 continue; 556 case IMSG_CTL_SHOW_DB_SUM: 557 if (v->type == LSA_TYPE_SUM_NETWORK) 558 break; 559 continue; 560 case IMSG_CTL_SHOW_DB_ASBR: 561 if (v->type == LSA_TYPE_SUM_ROUTER) 562 break; 563 continue; 564 default: 565 log_warnx("lsa_dump: unknown imsg type"); 566 return; 567 } 568 rde_imsg_compose_ospfe(imsg_type, 0, pid, &v->lsa->hdr, 569 ntohs(v->lsa->hdr.len)); 570 } 571 } 572 573 /* ARGSUSED */ 574 void 575 lsa_timeout(int fd, short event, void *bula) 576 { 577 struct vertex *v = bula; 578 struct timeval tv; 579 580 lsa_age(v); 581 582 if (v->deleted) { 583 if (ntohs(v->lsa->hdr.age) >= MAX_AGE) { 584 vertex_free(v); 585 } else { 586 v->deleted = 0; 587 588 /* schedule recalculation of the RIB */ 589 if (v->lsa->hdr.type != LSA_TYPE_EXTERNAL) 590 v->area->dirty = 1; 591 start_spf_timer(); 592 593 rde_imsg_compose_ospfe(IMSG_LS_FLOOD, v->peerid, 0, 594 v->lsa, ntohs(v->lsa->hdr.len)); 595 596 /* timeout handling either MAX_AGE or LS_REFRESH_TIME */ 597 timerclear(&tv); 598 if (v->self) 599 tv.tv_sec = LS_REFRESH_TIME; 600 else 601 tv.tv_sec = MAX_AGE - ntohs(v->lsa->hdr.age); 602 603 if (evtimer_add(&v->ev, &tv) != 0) 604 fatal("lsa_timeout"); 605 } 606 return; 607 } 608 609 if (v->self && ntohs(v->lsa->hdr.age) < MAX_AGE) 610 lsa_refresh(v); 611 612 rde_imsg_compose_ospfe(IMSG_LS_FLOOD, v->peerid, 0, 613 v->lsa, ntohs(v->lsa->hdr.len)); 614 } 615 616 void 617 lsa_refresh(struct vertex *v) 618 { 619 struct timeval tv; 620 struct timespec tp; 621 u_int32_t seqnum; 622 u_int16_t len; 623 624 /* refresh LSA by increasing sequence number by one */ 625 v->lsa->hdr.age = htons(DEFAULT_AGE); 626 seqnum = ntohl(v->lsa->hdr.seq_num); 627 if (seqnum++ == MAX_SEQ_NUM) 628 /* XXX fix me */ 629 fatalx("sequence number wrapping"); 630 v->lsa->hdr.seq_num = htonl(seqnum); 631 632 /* recalculate checksum */ 633 len = ntohs(v->lsa->hdr.len); 634 v->lsa->hdr.ls_chksum = 0; 635 v->lsa->hdr.ls_chksum = htons(iso_cksum(v->lsa, len, LS_CKSUM_OFFSET)); 636 637 clock_gettime(CLOCK_MONOTONIC, &tp); 638 v->changed = v->stamp = tp.tv_sec; 639 640 timerclear(&tv); 641 tv.tv_sec = LS_REFRESH_TIME; 642 if (evtimer_add(&v->ev, &tv) == -1) 643 fatal("lsa_refresh"); 644 } 645 646 void 647 lsa_merge(struct rde_nbr *nbr, struct lsa *lsa, struct vertex *v) 648 { 649 struct timeval tv; 650 struct timespec tp; 651 time_t now; 652 u_int16_t len; 653 654 if (v == NULL) { 655 if (lsa_add(nbr, lsa)) 656 /* delayed update */ 657 return; 658 rde_imsg_compose_ospfe(IMSG_LS_FLOOD, nbr->peerid, 0, 659 lsa, ntohs(lsa->hdr.len)); 660 return; 661 } 662 663 /* set the seq_num to the current one. lsa_refresh() will do the ++ */ 664 lsa->hdr.seq_num = v->lsa->hdr.seq_num; 665 /* recalculate checksum */ 666 len = ntohs(lsa->hdr.len); 667 lsa->hdr.ls_chksum = 0; 668 lsa->hdr.ls_chksum = htons(iso_cksum(lsa, len, LS_CKSUM_OFFSET)); 669 670 /* compare LSA most header fields are equal so don't check them */ 671 if (lsa_equal(lsa, v->lsa)) { 672 free(lsa); 673 return; 674 } 675 676 /* overwrite the lsa all other fields are unaffected */ 677 free(v->lsa); 678 v->lsa = lsa; 679 start_spf_timer(); 680 if (v->type != LSA_TYPE_EXTERNAL) 681 nbr->area->dirty = 1; 682 683 /* set correct timeout for reflooding the LSA */ 684 clock_gettime(CLOCK_MONOTONIC, &tp); 685 now = tp.tv_sec; 686 timerclear(&tv); 687 if (v->changed + MIN_LS_INTERVAL >= now) 688 tv.tv_sec = MIN_LS_INTERVAL; 689 if (evtimer_add(&v->ev, &tv) == -1) 690 fatal("lsa_merge"); 691 } 692 693 void 694 lsa_remove_invalid_sums(struct area *area) 695 { 696 struct lsa_tree *tree = &area->lsa_tree; 697 struct vertex *v, *nv; 698 699 /* XXX speed me up */ 700 for (v = RB_MIN(lsa_tree, tree); v != NULL; v = nv) { 701 nv = RB_NEXT(lsa_tree, tree, v); 702 if ((v->type == LSA_TYPE_SUM_NETWORK || 703 v->type == LSA_TYPE_SUM_ROUTER) && 704 v->self && v->cost == LS_INFINITY && 705 v->deleted == 0) { 706 /* 707 * age the lsa and call lsa_timeout() which will 708 * actually remove it from the database. 709 */ 710 v->lsa->hdr.age = htons(MAX_AGE); 711 lsa_timeout(0, 0, v); 712 } 713 } 714 } 715 716 void 717 lsa_generate_stub_sums(struct area *area) 718 { 719 struct rt_node rn; 720 struct redistribute *r; 721 struct vertex *v; 722 struct lsa *lsa; 723 struct area *back; 724 725 if (!area->stub) 726 return; 727 728 back = rde_backbone_area(); 729 if (!back || !back->active) 730 return; 731 732 SIMPLEQ_FOREACH(r, &area->redist_list, entry) { 733 bzero(&rn, sizeof(rn)); 734 if (r->type == REDIST_DEFAULT) { 735 /* setup fake rt_node */ 736 rn.prefixlen = 0; 737 rn.prefix.s_addr = INADDR_ANY; 738 rn.cost = r->metric & LSA_METRIC_MASK; 739 740 /* update lsa but only if it was changed */ 741 v = lsa_find(area, LSA_TYPE_SUM_NETWORK, 742 rn.prefix.s_addr, rde_router_id()); 743 lsa = orig_sum_lsa(&rn, area, LSA_TYPE_SUM_NETWORK, 0); 744 lsa_merge(rde_nbr_self(area), lsa, v); 745 746 if (v == NULL) 747 v = lsa_find(area, LSA_TYPE_SUM_NETWORK, 748 rn.prefix.s_addr, rde_router_id()); 749 750 /* 751 * suppressed/deleted routes are not found in the 752 * second lsa_find 753 */ 754 if (v) 755 v->cost = rn.cost; 756 return; 757 } else if (r->type == (REDIST_DEFAULT | REDIST_NO)) 758 return; 759 } 760 } 761 762 int 763 lsa_equal(struct lsa *a, struct lsa *b) 764 { 765 /* 766 * compare LSA that already have same type, adv_rtr and ls_id 767 * so not all header need to be compared 768 */ 769 if (a == NULL || b == NULL) 770 return (0); 771 if (a->hdr.len != b->hdr.len) 772 return (0); 773 if (a->hdr.opts != b->hdr.opts) 774 return (0); 775 /* LSA with age MAX_AGE are never equal */ 776 if (a->hdr.age == htons(MAX_AGE) || b->hdr.age == htons(MAX_AGE)) 777 return (0); 778 if (memcmp(&a->data, &b->data, ntohs(a->hdr.len) - 779 sizeof(struct lsa_hdr))) 780 return (0); 781 782 return (1); 783 } 784 785