Return to lsupd.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / bird2 / proto / ospf |
1.1 ! misho 1: /* ! 2: * BIRD -- OSPF ! 3: * ! 4: * (c) 2000--2004 Ondrej Filip <feela@network.cz> ! 5: * (c) 2009--2014 Ondrej Zajicek <santiago@crfreenet.org> ! 6: * (c) 2009--2014 CZ.NIC z.s.p.o. ! 7: * ! 8: * Can be freely distributed and used under the terms of the GNU GPL. ! 9: */ ! 10: ! 11: #include "ospf.h" ! 12: ! 13: ! 14: /* ! 15: struct ospf_lsupd_packet ! 16: { ! 17: struct ospf_packet hdr; ! 18: // union ospf_auth auth; ! 19: ! 20: u32 lsa_count; ! 21: void lsas[]; ! 22: }; ! 23: */ ! 24: ! 25: ! 26: void ! 27: ospf_dump_lsahdr(struct ospf_proto *p, struct ospf_lsa_header *lsa_n) ! 28: { ! 29: struct ospf_lsa_header lsa; ! 30: u32 lsa_etype; ! 31: ! 32: lsa_ntoh_hdr(lsa_n, &lsa); ! 33: lsa_etype = lsa_get_etype(&lsa, p); ! 34: ! 35: log(L_TRACE "%s: LSA Type: %04x, Id: %R, Rt: %R, Seq: %08x, Age: %u, Sum: %04x", ! 36: p->p.name, lsa_etype, lsa.id, lsa.rt, lsa.sn, lsa.age, lsa.checksum); ! 37: } ! 38: ! 39: void ! 40: ospf_dump_common(struct ospf_proto *p, struct ospf_packet *pkt) ! 41: { ! 42: log(L_TRACE "%s: length %d", p->p.name, ntohs(pkt->length)); ! 43: log(L_TRACE "%s: router %R", p->p.name, ntohl(pkt->routerid)); ! 44: } ! 45: ! 46: static inline uint ! 47: ospf_lsupd_hdrlen(struct ospf_proto *p) ! 48: { ! 49: return ospf_pkt_hdrlen(p) + 4; /* + u32 lsa count field */ ! 50: } ! 51: ! 52: static inline u32 ! 53: ospf_lsupd_get_lsa_count(struct ospf_packet *pkt, uint hdrlen) ! 54: { ! 55: u32 *c = ((void *) pkt) + hdrlen - 4; ! 56: return ntohl(*c); ! 57: } ! 58: ! 59: static inline void ! 60: ospf_lsupd_set_lsa_count(struct ospf_packet *pkt, uint hdrlen, u32 val) ! 61: { ! 62: u32 *c = ((void *) pkt) + hdrlen - 4; ! 63: *c = htonl(val); ! 64: } ! 65: ! 66: static inline void ! 67: ospf_lsupd_body(struct ospf_proto *p, struct ospf_packet *pkt, ! 68: uint *offset, uint *lsa_count) ! 69: { ! 70: uint hlen = ospf_lsupd_hdrlen(p); ! 71: *offset = hlen; ! 72: *lsa_count = ospf_lsupd_get_lsa_count(pkt, hlen); ! 73: } ! 74: ! 75: static void ! 76: ospf_dump_lsupd(struct ospf_proto *p, struct ospf_packet *pkt) ! 77: { ! 78: uint offset, plen, i, lsa_count, lsa_len; ! 79: ! 80: ASSERT(pkt->type == LSUPD_P); ! 81: ospf_dump_common(p, pkt); ! 82: ! 83: plen = ntohs(pkt->length); ! 84: ospf_lsupd_body(p, pkt, &offset, &lsa_count); ! 85: for (i = 0; i < lsa_count; i++) ! 86: { ! 87: if ((offset + sizeof(struct ospf_lsa_header)) > plen) ! 88: goto invalid; ! 89: ! 90: struct ospf_lsa_header *lsa = ((void *) pkt) + offset; ! 91: lsa_len = ntohs(lsa->length); ! 92: ! 93: if (((lsa_len % 4) != 0) || (lsa_len <= sizeof(struct ospf_lsa_header))) ! 94: goto invalid; ! 95: ! 96: ospf_dump_lsahdr(p, lsa); ! 97: offset += lsa_len; ! 98: } ! 99: return; ! 100: ! 101: invalid: ! 102: log(L_TRACE "%s: LSA invalid", p->p.name); ! 103: return; ! 104: } ! 105: ! 106: ! 107: static inline void ! 108: ospf_lsa_lsrq_down(struct top_hash_entry *req, struct ospf_neighbor *n) ! 109: { ! 110: if (req == n->lsrqi) ! 111: n->lsrqi = SNODE_NEXT(req); ! 112: ! 113: s_rem_node(SNODE req); ! 114: ospf_hash_delete(n->lsrqh, req); ! 115: ! 116: if (EMPTY_SLIST(n->lsrql)) ! 117: { ! 118: tm_stop(n->lsrq_timer); ! 119: ! 120: if (n->state == NEIGHBOR_LOADING) ! 121: ospf_neigh_sm(n, INM_LOADDONE); ! 122: } ! 123: } ! 124: ! 125: static inline void ! 126: ospf_lsa_lsrt_up(struct top_hash_entry *en, struct ospf_neighbor *n) ! 127: { ! 128: struct top_hash_entry *ret = ospf_hash_get_entry(n->lsrth, en); ! 129: ! 130: if (!SNODE_VALID(ret)) ! 131: { ! 132: en->ret_count++; ! 133: s_add_tail(&n->lsrtl, SNODE ret); ! 134: } ! 135: ! 136: ret->lsa = en->lsa; ! 137: ret->lsa_body = LSA_BODY_DUMMY; ! 138: ! 139: if (!tm_active(n->lsrt_timer)) ! 140: tm_start(n->lsrt_timer, n->ifa->rxmtint S); ! 141: } ! 142: ! 143: void ! 144: ospf_lsa_lsrt_down_(struct top_hash_entry *en, struct ospf_neighbor *n, struct top_hash_entry *ret) ! 145: { ! 146: if (en) ! 147: en->ret_count--; ! 148: ! 149: s_rem_node(SNODE ret); ! 150: ospf_hash_delete(n->lsrth, ret); ! 151: ! 152: if (EMPTY_SLIST(n->lsrtl)) ! 153: tm_stop(n->lsrt_timer); ! 154: } ! 155: ! 156: static inline int ! 157: ospf_lsa_lsrt_down(struct top_hash_entry *en, struct ospf_neighbor *n) ! 158: { ! 159: struct top_hash_entry *ret = ospf_hash_find_entry(n->lsrth, en); ! 160: ! 161: if (ret) ! 162: ospf_lsa_lsrt_down_(en, n, ret); ! 163: ! 164: return ret != NULL; ! 165: } ! 166: ! 167: void ! 168: ospf_add_flushed_to_lsrt(struct ospf_proto *p, struct ospf_neighbor *n) ! 169: { ! 170: struct top_hash_entry *en; ! 171: ! 172: WALK_SLIST(en, p->lsal) ! 173: if ((en->lsa.age == LSA_MAXAGE) && (en->lsa_body != NULL) && ! 174: lsa_flooding_allowed(en->lsa_type, en->domain, n->ifa) && ! 175: lsa_is_acceptable(en->lsa_type, n, p)) ! 176: ospf_lsa_lsrt_up(en, n); ! 177: ! 178: /* If we found any flushed LSA, we send them ASAP */ ! 179: if (tm_active(n->lsrt_timer)) ! 180: tm_start(n->lsrt_timer, 0); ! 181: } ! 182: ! 183: static int ospf_flood_lsupd(struct ospf_proto *p, struct top_hash_entry **lsa_list, uint lsa_count, uint lsa_min_count, struct ospf_iface *ifa); ! 184: ! 185: static void ! 186: ospf_enqueue_lsa(struct ospf_proto *p, struct top_hash_entry *en, struct ospf_iface *ifa) ! 187: { ! 188: /* Exception for local Grace-LSA, they are flooded synchronously */ ! 189: if ((en->lsa_type == LSA_T_GR) && (en->lsa.rt == p->router_id)) ! 190: { ! 191: ospf_flood_lsupd(p, &en, 1, 1, ifa); ! 192: return; ! 193: } ! 194: ! 195: if (ifa->flood_queue_used == ifa->flood_queue_size) ! 196: { ! 197: /* If we already have full queue, we send some packets */ ! 198: uint sent = ospf_flood_lsupd(p, ifa->flood_queue, ifa->flood_queue_used, ifa->flood_queue_used / 2, ifa); ! 199: uint i; ! 200: ! 201: for (i = 0; i < sent; i++) ! 202: ifa->flood_queue[i]->ret_count--; ! 203: ! 204: ifa->flood_queue_used -= sent; ! 205: memmove(ifa->flood_queue, ifa->flood_queue + sent, ifa->flood_queue_used * sizeof(void *)); ! 206: bzero(ifa->flood_queue + ifa->flood_queue_used, sent * sizeof(void *)); ! 207: } ! 208: ! 209: en->ret_count++; ! 210: ifa->flood_queue[ifa->flood_queue_used] = en; ! 211: ifa->flood_queue_used++; ! 212: ! 213: if (!ev_active(p->flood_event)) ! 214: ev_schedule(p->flood_event); ! 215: } ! 216: ! 217: void ! 218: ospf_flood_event(void *ptr) ! 219: { ! 220: struct ospf_proto *p = ptr; ! 221: struct ospf_iface *ifa; ! 222: int i, count; ! 223: ! 224: WALK_LIST(ifa, p->iface_list) ! 225: { ! 226: if (ifa->flood_queue_used == 0) ! 227: continue; ! 228: ! 229: count = ifa->flood_queue_used; ! 230: ospf_flood_lsupd(p, ifa->flood_queue, count, count, ifa); ! 231: ! 232: for (i = 0; i < count; i++) ! 233: ifa->flood_queue[i]->ret_count--; ! 234: ! 235: ifa->flood_queue_used = 0; ! 236: bzero(ifa->flood_queue, count * sizeof(void *)); ! 237: } ! 238: } ! 239: ! 240: ! 241: /** ! 242: * ospf_flood_lsa - send LSA to the neighbors ! 243: * @p: OSPF protocol instance ! 244: * @en: LSA entry ! 245: * @from: neighbor than sent this LSA (or NULL if LSA is local) ! 246: * ! 247: * return value - was the LSA flooded back? ! 248: */ ! 249: int ! 250: ospf_flood_lsa(struct ospf_proto *p, struct top_hash_entry *en, struct ospf_neighbor *from) ! 251: { ! 252: struct ospf_iface *ifa; ! 253: struct ospf_neighbor *n; ! 254: ! 255: /* RFC 2328 13.3 */ ! 256: ! 257: int back = 0; ! 258: WALK_LIST(ifa, p->iface_list) ! 259: { ! 260: if (ifa->stub) ! 261: continue; ! 262: ! 263: if (! lsa_flooding_allowed(en->lsa_type, en->domain, ifa)) ! 264: continue; ! 265: ! 266: DBG("Wanted to flood LSA: Type: %u, ID: %R, RT: %R, SN: 0x%x, Age %u\n", ! 267: hh->type, hh->id, hh->rt, hh->sn, hh->age); ! 268: ! 269: int used = 0; ! 270: WALK_LIST(n, ifa->neigh_list) ! 271: { ! 272: /* 13.3 (1a) */ ! 273: if (n->state < NEIGHBOR_EXCHANGE) ! 274: continue; ! 275: ! 276: /* 13.3 (1b) */ ! 277: if (n->state < NEIGHBOR_FULL) ! 278: { ! 279: struct top_hash_entry *req = ospf_hash_find_entry(n->lsrqh, en); ! 280: if (req != NULL) ! 281: { ! 282: int cmp = lsa_comp(&en->lsa, &req->lsa); ! 283: ! 284: /* If same or newer, remove LSA from the link state request list */ ! 285: if (cmp > CMP_OLDER) ! 286: ospf_lsa_lsrq_down(req, n); ! 287: ! 288: /* If older or same, skip processing of this neighbor */ ! 289: if (cmp < CMP_NEWER) ! 290: continue; ! 291: } ! 292: } ! 293: ! 294: /* 13.3 (1c) */ ! 295: if (n == from) ! 296: continue; ! 297: ! 298: /* Check whether optional LSAs are supported by neighbor */ ! 299: if (!lsa_is_acceptable(en->lsa_type, n, p)) ! 300: continue; ! 301: ! 302: /* 13.3 (1d) - add LSA to the link state retransmission list */ ! 303: ospf_lsa_lsrt_up(en, n); ! 304: ! 305: used = 1; ! 306: } ! 307: ! 308: /* 13.3 (2) */ ! 309: if (!used) ! 310: continue; ! 311: ! 312: if (from && (from->ifa == ifa)) ! 313: { ! 314: /* 13.3 (3) */ ! 315: if ((from->rid == ifa->drid) || (from->rid == ifa->bdrid)) ! 316: continue; ! 317: ! 318: /* 13.3 (4) */ ! 319: if (ifa->state == OSPF_IS_BACKUP) ! 320: continue; ! 321: ! 322: back = 1; ! 323: } ! 324: ! 325: /* 13.3 (5) - finally flood the packet */ ! 326: ospf_enqueue_lsa(p, en, ifa); ! 327: } ! 328: ! 329: return back; ! 330: } ! 331: ! 332: static uint ! 333: ospf_prepare_lsupd(struct ospf_proto *p, struct ospf_iface *ifa, ! 334: struct top_hash_entry **lsa_list, uint lsa_count) ! 335: { ! 336: struct ospf_packet *pkt; ! 337: uint hlen, pos, i, maxsize; ! 338: ! 339: pkt = ospf_tx_buffer(ifa); ! 340: hlen = ospf_lsupd_hdrlen(p); ! 341: maxsize = ospf_pkt_maxsize(ifa); ! 342: ! 343: ospf_pkt_fill_hdr(ifa, pkt, LSUPD_P); ! 344: pos = hlen; ! 345: ! 346: for (i = 0; i < lsa_count; i++) ! 347: { ! 348: struct top_hash_entry *en = lsa_list[i]; ! 349: uint len = en->lsa.length; ! 350: ! 351: if ((pos + len) > maxsize) ! 352: { ! 353: /* The packet if full, stop adding LSAs and sent it */ ! 354: if (i > 0) ! 355: break; ! 356: ! 357: /* LSA is larger than MTU, check buffer size */ ! 358: if (ospf_iface_assure_bufsize(ifa, pos + len) < 0) ! 359: { ! 360: /* Cannot fit in a tx buffer, skip that */ ! 361: log(L_ERR "%s: LSA too large to send on %s (Type: %04x, Id: %R, Rt: %R)", ! 362: p->p.name, ifa->ifname, en->lsa_type, en->lsa.id, en->lsa.rt); ! 363: break; ! 364: } ! 365: ! 366: /* TX buffer could be reallocated */ ! 367: pkt = ospf_tx_buffer(ifa); ! 368: } ! 369: ! 370: struct ospf_lsa_header *buf = ((void *) pkt) + pos; ! 371: lsa_hton_hdr(&en->lsa, buf); ! 372: lsa_hton_body(en->lsa_body, ((void *) buf) + sizeof(struct ospf_lsa_header), ! 373: len - sizeof(struct ospf_lsa_header)); ! 374: buf->age = htons(MIN(en->lsa.age + ifa->inftransdelay, LSA_MAXAGE)); ! 375: ! 376: pos += len; ! 377: } ! 378: ! 379: ospf_lsupd_set_lsa_count(pkt, hlen, i); ! 380: pkt->length = htons(pos); ! 381: ! 382: return i; ! 383: } ! 384: ! 385: ! 386: static int ! 387: ospf_flood_lsupd(struct ospf_proto *p, struct top_hash_entry **lsa_list, uint lsa_count, uint lsa_min_count, struct ospf_iface *ifa) ! 388: { ! 389: uint i, c; ! 390: ! 391: for (i = 0; i < lsa_min_count; i += c) ! 392: { ! 393: c = ospf_prepare_lsupd(p, ifa, lsa_list + i, lsa_count - i); ! 394: ! 395: if (!c) /* Too large LSA */ ! 396: { i++; continue; } ! 397: ! 398: OSPF_PACKET(ospf_dump_lsupd, ospf_tx_buffer(ifa), ! 399: "LSUPD packet flooded via %s", ifa->ifname); ! 400: ! 401: if (ifa->type == OSPF_IT_BCAST) ! 402: { ! 403: if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP)) ! 404: ospf_send_to_all(ifa); ! 405: else ! 406: ospf_send_to_des(ifa); ! 407: } ! 408: else ! 409: ospf_send_to_agt(ifa, NEIGHBOR_EXCHANGE); ! 410: } ! 411: ! 412: return i; ! 413: } ! 414: ! 415: int ! 416: ospf_send_lsupd(struct ospf_proto *p, struct top_hash_entry **lsa_list, uint lsa_count, struct ospf_neighbor *n) ! 417: { ! 418: struct ospf_iface *ifa = n->ifa; ! 419: uint i, c; ! 420: ! 421: for (i = 0; i < lsa_count; i += c) ! 422: { ! 423: c = ospf_prepare_lsupd(p, ifa, lsa_list + i, lsa_count - i); ! 424: ! 425: if (!c) /* Too large LSA */ ! 426: { i++; continue; } ! 427: ! 428: OSPF_PACKET(ospf_dump_lsupd, ospf_tx_buffer(ifa), ! 429: "LSUPD packet sent to nbr %R on %s", n->rid, ifa->ifname); ! 430: ! 431: ospf_send_to(ifa, n->ip); ! 432: } ! 433: ! 434: return i; ! 435: } ! 436: ! 437: void ! 438: ospf_rxmt_lsupd(struct ospf_proto *p, struct ospf_neighbor *n) ! 439: { ! 440: uint max = 2 * n->ifa->flood_queue_size; ! 441: struct top_hash_entry *entries[max]; ! 442: struct top_hash_entry *ret, *nxt, *en; ! 443: uint i = 0; ! 444: ! 445: /* ASSERT((n->state >= NEIGHBOR_EXCHANGE) && !EMPTY_SLIST(n->lsrtl)); */ ! 446: ! 447: WALK_SLIST_DELSAFE(ret, nxt, n->lsrtl) ! 448: { ! 449: if (i == max) ! 450: break; ! 451: ! 452: en = ospf_hash_find_entry(p->gr, ret); ! 453: if (!en) ! 454: { ! 455: /* Probably flushed LSA, this should not happen */ ! 456: log(L_WARN "%s: LSA disappeared (Type: %04x, Id: %R, Rt: %R)", ! 457: p->p.name, ret->lsa_type, ret->lsa.id, ret->lsa.rt); ! 458: ! 459: s_rem_node(SNODE ret); ! 460: ospf_hash_delete(n->lsrth, ret); ! 461: ! 462: continue; ! 463: } ! 464: ! 465: entries[i] = en; ! 466: i++; ! 467: } ! 468: ! 469: ospf_send_lsupd(p, entries, i, n); ! 470: } ! 471: ! 472: ! 473: static inline int ! 474: ospf_addr_is_local(struct ospf_proto *p, struct ospf_area *oa, ip_addr ip) ! 475: { ! 476: struct ospf_iface *ifa; ! 477: WALK_LIST(ifa, p->iface_list) ! 478: if ((ifa->oa == oa) && ifa->addr && ipa_equal(ifa->addr->ip, ip)) ! 479: return 1; ! 480: ! 481: return 0; ! 482: } ! 483: ! 484: void ! 485: ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa, ! 486: struct ospf_neighbor *n) ! 487: { ! 488: struct ospf_proto *p = ifa->oa->po; ! 489: const char *err_dsc = NULL; ! 490: uint plen, err_val = 0; ! 491: ! 492: /* RFC 2328 13. */ ! 493: ! 494: plen = ntohs(pkt->length); ! 495: if (plen < ospf_lsupd_hdrlen(p)) ! 496: { ! 497: LOG_PKT("Bad LSUPD packet from nbr %R on %s - %s (%u)", n->rid, ifa->ifname, "too short", plen); ! 498: return; ! 499: } ! 500: ! 501: OSPF_PACKET(ospf_dump_lsupd, pkt, "LSUPD packet received from nbr %R on %s", n->rid, ifa->ifname); ! 502: ! 503: if (n->state < NEIGHBOR_EXCHANGE) ! 504: { ! 505: OSPF_TRACE(D_PACKETS, "LSUPD packet ignored - lesser state than Exchange"); ! 506: return; ! 507: } ! 508: ! 509: ospf_neigh_sm(n, INM_HELLOREC); /* Questionable */ ! 510: ! 511: uint offset, i, lsa_count; ! 512: ospf_lsupd_body(p, pkt, &offset, &lsa_count); ! 513: ! 514: for (i = 0; i < lsa_count; i++) ! 515: { ! 516: struct ospf_lsa_header lsa, *lsa_n; ! 517: struct top_hash_entry *en; ! 518: u32 lsa_len, lsa_type, lsa_domain; ! 519: ! 520: if ((offset + sizeof(struct ospf_lsa_header)) > plen) ! 521: DROP("too short", plen); ! 522: ! 523: /* LSA header in network order */ ! 524: lsa_n = ((void *) pkt) + offset; ! 525: lsa_len = ntohs(lsa_n->length); ! 526: offset += lsa_len; ! 527: ! 528: if (offset > plen) ! 529: DROP("too short", plen); ! 530: ! 531: if (((lsa_len % 4) != 0) || (lsa_len <= sizeof(struct ospf_lsa_header))) ! 532: DROP("invalid LSA length", lsa_len); ! 533: ! 534: /* LSA header in host order */ ! 535: lsa_ntoh_hdr(lsa_n, &lsa); ! 536: lsa_get_type_domain(&lsa, ifa, &lsa_type, &lsa_domain); ! 537: ! 538: DBG("Update Type: %04x, Id: %R, Rt: %R, Sn: 0x%08x, Age: %u, Sum: %u\n", ! 539: lsa_type, lsa.id, lsa.rt, lsa.sn, lsa.age, lsa.checksum); ! 540: ! 541: /* RFC 2328 13. (1) - verify LSA checksum */ ! 542: if ((lsa_n->checksum == 0) || !lsa_verify_checksum(lsa_n, lsa_len)) ! 543: SKIP("invalid checksum"); ! 544: ! 545: /* RFC 2328 13. (2) */ ! 546: if (!lsa_type) ! 547: SKIP("unknown type"); ! 548: ! 549: /* RFC 5340 4.5.1 (2) and RFC 2328 13. (3) */ ! 550: if (!oa_is_ext(ifa->oa) && (LSA_SCOPE(lsa_type) == LSA_SCOPE_AS)) ! 551: SKIP("AS scope in stub area"); ! 552: ! 553: /* Errata 3746 to RFC 2328 - rt-summary-LSAs forbidden in stub areas */ ! 554: if (!oa_is_ext(ifa->oa) && (lsa_type == LSA_T_SUM_RT)) ! 555: SKIP("rt-summary-LSA in stub area"); ! 556: ! 557: /* RFC 5340 4.5.1 (3) */ ! 558: if (LSA_SCOPE(lsa_type) == LSA_SCOPE_RES) ! 559: SKIP("invalid scope"); ! 560: ! 561: /* Find local copy of LSA in link state database */ ! 562: en = ospf_hash_find(p->gr, lsa_domain, lsa.id, lsa.rt, lsa_type); ! 563: ! 564: #ifdef LOCAL_DEBUG ! 565: if (en) ! 566: DBG("I have Type: %04x, Id: %R, Rt: %R, Sn: 0x%08x, Age: %u, Sum: %u\n", ! 567: en->lsa_type, en->lsa.id, en->lsa.rt, en->lsa.sn, en->lsa.age, en->lsa.checksum); ! 568: #endif ! 569: ! 570: /* 13. (4) - ignore maxage LSA if i have no local copy */ ! 571: if ((lsa.age == LSA_MAXAGE) && !en && (p->padj == 0)) ! 572: { ! 573: /* 13.5. - schedule ACKs (tbl 19, case 5) */ ! 574: ospf_enqueue_lsack(n, lsa_n, ACKL_DIRECT); ! 575: continue; ! 576: } ! 577: ! 578: /* 13. (5) - received LSA is newer (or no local copy) */ ! 579: if (!en || (lsa_comp(&lsa, &en->lsa) == CMP_NEWER)) ! 580: { ! 581: /* 13. (5a) - enforce minimum time between updates for received LSAs */ ! 582: /* We also use this to ratelimit reactions to received self-originated LSAs */ ! 583: if (en && (lsa_inst_age(en) < MINLSARRIVAL)) ! 584: { ! 585: OSPF_TRACE(D_EVENTS, "Skipping LSA received in less that MinLSArrival"); ! 586: continue; ! 587: } ! 588: ! 589: /* Copy and validate LSA body */ ! 590: int blen = lsa.length - sizeof(struct ospf_lsa_header); ! 591: void *body = mb_alloc(p->p.pool, blen); ! 592: lsa_ntoh_body(lsa_n + 1, body, blen); ! 593: ! 594: if (lsa_validate(&lsa, lsa_type, ospf_is_v2(p), body) == 0) ! 595: { ! 596: mb_free(body); ! 597: SKIP("invalid body"); ! 598: } ! 599: ! 600: /* 13. (5f) - handle self-originated LSAs, see also 13.4. */ ! 601: if (!p->gr_recovery && ! 602: ((lsa.rt == p->router_id) || ! 603: (ospf_is_v2(p) && (lsa_type == LSA_T_NET) && ospf_addr_is_local(p, ifa->oa, ipa_from_u32(lsa.id))))) ! 604: { ! 605: OSPF_TRACE(D_EVENTS, "Received unexpected self-originated LSA"); ! 606: ospf_advance_lsa(p, en, &lsa, lsa_type, lsa_domain, body); ! 607: continue; ! 608: } ! 609: ! 610: /* 13. (5c) - remove old LSA from all retransmission lists ! 611: * ! 612: * We only need to remove it from the retransmission list of the neighbor ! 613: * that send us the new LSA. The old LSA is automatically replaced in ! 614: * retransmission lists by the new LSA. ! 615: */ ! 616: if (en) ! 617: ospf_lsa_lsrt_down(en, n); ! 618: ! 619: #if 0 ! 620: /* ! 621: * Old code for removing LSA from all retransmission lists. Must be done ! 622: * before (5b), otherwise it also removes the new entries from (5b). ! 623: */ ! 624: struct ospf_iface *ifi; ! 625: struct ospf_neighbor *ni; ! 626: ! 627: WALK_LIST(ifi, p->iface_list) ! 628: WALK_LIST(ni, ifi->neigh_list) ! 629: if (ni->state > NEIGHBOR_EXSTART) ! 630: ospf_lsa_lsrt_down(en, ni); ! 631: #endif ! 632: ! 633: /* 13. (5d) - install new LSA into database */ ! 634: en = ospf_install_lsa(p, &lsa, lsa_type, lsa_domain, body); ! 635: ! 636: /* RFC 5340 4.4.3 Events 6+7 - new Link LSA received */ ! 637: if (lsa_type == LSA_T_LINK) ! 638: ospf_notify_net_lsa(ifa); ! 639: ! 640: /* RFC 3623 3.1 - entering graceful restart helper mode */ ! 641: if (lsa_type == LSA_T_GR) ! 642: ospf_neigh_notify_grace_lsa(n, en); ! 643: ! 644: /* Link received pre-restart router LSA */ ! 645: if (p->gr_recovery && (lsa_type == LSA_T_RT) && (lsa.rt == p->router_id)) ! 646: ifa->oa->rt = en; ! 647: ! 648: /* 13. (5b) - flood new LSA */ ! 649: int flood_back = ospf_flood_lsa(p, en, n); ! 650: ! 651: /* 13.5. - schedule ACKs (tbl 19, cases 1+2) */ ! 652: if (! flood_back) ! 653: if ((ifa->state != OSPF_IS_BACKUP) || (n->rid == ifa->drid)) ! 654: ospf_enqueue_lsack(n, lsa_n, ACKL_DELAY); ! 655: ! 656: /* FIXME: remove LSA entry if it is LSA_MAXAGE and it is possible? */ ! 657: ! 658: continue; ! 659: } ! 660: ! 661: /* 13. (6) - received LSA is in Link state request list (but not newer) */ ! 662: if (ospf_hash_find_entry(n->lsrqh, en) != NULL) ! 663: DROP1("error in LSA database exchange"); ! 664: ! 665: /* 13. (7) - received LSA is same */ ! 666: if (lsa_comp(&lsa, &en->lsa) == CMP_SAME) ! 667: { ! 668: /* Duplicate LSA, treat as implicit ACK */ ! 669: int implicit_ack = ospf_lsa_lsrt_down(en, n); ! 670: ! 671: /* 13.5. - schedule ACKs (tbl 19, cases 3+4) */ ! 672: if (implicit_ack) ! 673: { ! 674: if ((ifa->state == OSPF_IS_BACKUP) && (n->rid == ifa->drid)) ! 675: ospf_enqueue_lsack(n, lsa_n, ACKL_DELAY); ! 676: } ! 677: else ! 678: ospf_enqueue_lsack(n, lsa_n, ACKL_DIRECT); ! 679: ! 680: continue; ! 681: } ! 682: ! 683: /* 13. (8) - received LSA is older */ ! 684: { ! 685: /* Seqnum is wrapping, wait until it is flushed */ ! 686: if ((en->lsa.age == LSA_MAXAGE) && (en->lsa.sn == LSA_MAXSEQNO)) ! 687: continue; ! 688: ! 689: /* Send newer local copy back to neighbor */ ! 690: /* FIXME - check for MinLSArrival ? */ ! 691: ospf_send_lsupd(p, &en, 1, n); ! 692: ! 693: continue; ! 694: } ! 695: ! 696: skip: ! 697: LOG_LSA1("Bad LSA (Type: %04x, Id: %R, Rt: %R) in LSUPD", lsa_type, lsa.id, lsa.rt); ! 698: LOG_LSA2(" received from nbr %R on %s - %s", n->rid, ifa->ifname, err_dsc); ! 699: } ! 700: ! 701: /* Send direct LSACKs */ ! 702: ospf_send_lsack(p, n, ACKL_DIRECT); ! 703: ! 704: /* Send enqueued LSAs immediately, do not wait for flood_event */ ! 705: if (ev_active(p->flood_event)) ! 706: { ! 707: ev_postpone(p->flood_event); ! 708: ospf_flood_event(p); ! 709: } ! 710: ! 711: /* ! 712: * During loading, we should ask for another batch of LSAs. This is only ! 713: * vaguely mentioned in RFC 2328. We send a new LSREQ if all requests sent in ! 714: * the last packet were already answered and/or removed from the LS request ! 715: * list and therefore lsrqi is pointing to the first node of the list. ! 716: */ ! 717: if (!EMPTY_SLIST(n->lsrql) && (n->lsrqi == SHEAD(n->lsrql))) ! 718: { ! 719: ospf_send_lsreq(p, n); ! 720: tm_start(n->lsrq_timer, n->ifa->rxmtint S); ! 721: } ! 722: ! 723: return; ! 724: ! 725: drop: ! 726: LOG_PKT("Bad LSUPD packet from nbr %R on %s - %s (%u)", ! 727: n->rid, ifa->ifname, err_dsc, err_val); ! 728: ! 729: /* Malformed LSUPD - there is no defined error event, we abuse BadLSReq */ ! 730: ospf_neigh_sm(n, INM_BADLSREQ); ! 731: return; ! 732: }