1 /* $OpenBSD: lsupdate.c,v 1.49 2021/01/19 09:25:53 claudio Exp $ */ 2 3 /* 4 * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org> 5 * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org> 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #include <sys/types.h> 21 #include <sys/socket.h> 22 #include <netinet/in.h> 23 #include <arpa/inet.h> 24 25 #include <stdlib.h> 26 #include <string.h> 27 #include <siphash.h> 28 29 #include "ospf.h" 30 #include "ospfd.h" 31 #include "log.h" 32 #include "ospfe.h" 33 #include "rde.h" 34 35 struct ibuf *prepare_ls_update(struct iface *); 36 int add_ls_update(struct ibuf *, struct iface *, void *, u_int16_t, 37 u_int16_t); 38 int send_ls_update(struct ibuf *, struct iface *, struct in_addr, u_int32_t); 39 40 void ls_retrans_list_insert(struct nbr *, struct lsa_entry *); 41 void ls_retrans_list_remove(struct nbr *, struct lsa_entry *); 42 43 /* link state update packet handling */ 44 int 45 lsa_flood(struct iface *iface, struct nbr *originator, struct lsa_hdr *lsa_hdr, 46 void *data) 47 { 48 struct nbr *nbr; 49 struct lsa_entry *le = NULL; 50 int queued = 0, dont_ack = 0; 51 int r; 52 53 LIST_FOREACH(nbr, &iface->nbr_list, entry) { 54 if (nbr == iface->self) 55 continue; 56 if (!(nbr->state & NBR_STA_FLOOD)) 57 continue; 58 59 if (iface->state & IF_STA_DROTHER && !queued) 60 while ((le = ls_retrans_list_get(iface->self, lsa_hdr))) 61 ls_retrans_list_free(iface->self, le); 62 63 while ((le = ls_retrans_list_get(nbr, lsa_hdr))) 64 ls_retrans_list_free(nbr, le); 65 66 if (!(nbr->state & NBR_STA_FULL) && 67 (le = ls_req_list_get(nbr, lsa_hdr)) != NULL) { 68 r = lsa_newer(lsa_hdr, le->le_lsa); 69 if (r > 0) { 70 /* to flood LSA is newer than requested */ 71 ls_req_list_free(nbr, le); 72 /* new needs to be flooded */ 73 } else if (r < 0) { 74 /* to flood LSA is older than requested */ 75 continue; 76 } else { 77 /* LSA are equal */ 78 ls_req_list_free(nbr, le); 79 continue; 80 } 81 } 82 83 if (nbr == originator) { 84 dont_ack++; 85 continue; 86 } 87 88 /* non DR or BDR router keep all lsa in one retrans list */ 89 if (iface->state & IF_STA_DROTHER) { 90 if (!queued) 91 ls_retrans_list_add(iface->self, data, 92 iface->rxmt_interval, 0); 93 queued = 1; 94 } else { 95 ls_retrans_list_add(nbr, data, iface->rxmt_interval, 0); 96 queued = 1; 97 } 98 } 99 100 if (!queued) 101 return (0); 102 103 if (iface == originator->iface && iface->self != originator) { 104 if (iface->dr == originator || iface->bdr == originator) 105 return (0); 106 if (iface->state & IF_STA_BACKUP) 107 return (0); 108 dont_ack++; 109 } 110 111 /* 112 * initial flood needs to be queued separately, timeout is zero 113 * and oneshot has to be set because the retransimssion queues 114 * are already loaded. 115 */ 116 switch (iface->type) { 117 case IF_TYPE_POINTOPOINT: 118 case IF_TYPE_BROADCAST: 119 ls_retrans_list_add(iface->self, data, 0, 1); 120 break; 121 case IF_TYPE_NBMA: 122 case IF_TYPE_POINTOMULTIPOINT: 123 case IF_TYPE_VIRTUALLINK: 124 LIST_FOREACH(nbr, &iface->nbr_list, entry) { 125 if (nbr == iface->self) 126 continue; 127 if (!(nbr->state & NBR_STA_FLOOD)) 128 continue; 129 if (!TAILQ_EMPTY(&nbr->ls_retrans_list)) { 130 le = TAILQ_LAST(&nbr->ls_retrans_list, 131 lsa_head); 132 if (lsa_hdr->type != le->le_lsa->type || 133 lsa_hdr->ls_id != le->le_lsa->ls_id || 134 lsa_hdr->adv_rtr != le->le_lsa->adv_rtr) 135 continue; 136 } 137 ls_retrans_list_add(nbr, data, 0, 1); 138 } 139 break; 140 default: 141 fatalx("lsa_flood: unknown interface type"); 142 } 143 144 return (dont_ack == 2); 145 } 146 147 struct ibuf * 148 prepare_ls_update(struct iface *iface) 149 { 150 struct ibuf *buf; 151 152 if ((buf = ibuf_dynamic(iface->mtu - sizeof(struct ip), 153 IP_MAXPACKET - sizeof(struct ip))) == NULL) 154 fatal("prepare_ls_update"); 155 156 /* OSPF header */ 157 if (gen_ospf_hdr(buf, iface, PACKET_TYPE_LS_UPDATE)) 158 goto fail; 159 160 /* reserve space for number of lsa field */ 161 if (ibuf_reserve(buf, sizeof(u_int32_t)) == NULL) 162 goto fail; 163 164 return (buf); 165 fail: 166 log_warn("prepare_ls_update"); 167 ibuf_free(buf); 168 return (NULL); 169 } 170 171 int 172 add_ls_update(struct ibuf *buf, struct iface *iface, void *data, u_int16_t len, 173 u_int16_t older) 174 { 175 size_t ageoff; 176 u_int16_t age; 177 178 if ((size_t)iface->mtu < sizeof(struct ip) + sizeof(struct ospf_hdr) + 179 sizeof(u_int32_t) + ibuf_size(buf) + len + MD5_DIGEST_LENGTH) { 180 /* start new packet unless this is the first LSA to pack */ 181 if (ibuf_size(buf) > sizeof(struct ospf_hdr) + 182 sizeof(u_int32_t)) 183 return (0); 184 } 185 186 ageoff = ibuf_size(buf); 187 if (ibuf_add(buf, data, len)) { 188 log_warn("add_ls_update"); 189 return (0); 190 } 191 192 /* age LSA before sending it out */ 193 memcpy(&age, data, sizeof(age)); 194 age = ntohs(age); 195 if ((age += older + iface->transmit_delay) >= MAX_AGE) 196 age = MAX_AGE; 197 age = htons(age); 198 memcpy(ibuf_seek(buf, ageoff, sizeof(age)), &age, sizeof(age)); 199 200 return (1); 201 } 202 203 204 205 int 206 send_ls_update(struct ibuf *buf, struct iface *iface, struct in_addr addr, 207 u_int32_t nlsa) 208 { 209 struct sockaddr_in dst; 210 211 nlsa = htonl(nlsa); 212 memcpy(ibuf_seek(buf, sizeof(struct ospf_hdr), sizeof(nlsa)), 213 &nlsa, sizeof(nlsa)); 214 /* update authentication and calculate checksum */ 215 if (auth_gen(buf, iface)) 216 goto fail; 217 218 /* set destination */ 219 dst.sin_family = AF_INET; 220 dst.sin_len = sizeof(struct sockaddr_in); 221 dst.sin_addr.s_addr = addr.s_addr; 222 223 if (send_packet(iface, buf, &dst) == -1) 224 goto fail; 225 226 ibuf_free(buf); 227 return (0); 228 fail: 229 log_warn("%s", __func__); 230 ibuf_free(buf); 231 return (-1); 232 } 233 234 void 235 recv_ls_update(struct nbr *nbr, char *buf, u_int16_t len) 236 { 237 struct lsa_hdr lsa; 238 u_int32_t nlsa; 239 240 if (len < sizeof(nlsa)) { 241 log_warnx("recv_ls_update: bad packet size, neighbor ID %s", 242 inet_ntoa(nbr->id)); 243 return; 244 } 245 memcpy(&nlsa, buf, sizeof(nlsa)); 246 nlsa = ntohl(nlsa); 247 buf += sizeof(nlsa); 248 len -= sizeof(nlsa); 249 250 switch (nbr->state) { 251 case NBR_STA_DOWN: 252 case NBR_STA_ATTEMPT: 253 case NBR_STA_INIT: 254 case NBR_STA_2_WAY: 255 case NBR_STA_XSTRT: 256 case NBR_STA_SNAP: 257 log_debug("recv_ls_update: packet ignored in state %s, " 258 "neighbor ID %s", nbr_state_name(nbr->state), 259 inet_ntoa(nbr->id)); 260 break; 261 case NBR_STA_XCHNG: 262 case NBR_STA_LOAD: 263 case NBR_STA_FULL: 264 for (; nlsa > 0 && len > 0; nlsa--) { 265 if (len < sizeof(lsa)) { 266 log_warnx("recv_ls_update: bad packet size, " 267 "neighbor ID %s", inet_ntoa(nbr->id)); 268 return; 269 } 270 memcpy(&lsa, buf, sizeof(lsa)); 271 if (len < ntohs(lsa.len)) { 272 log_warnx("recv_ls_update: bad packet size, " 273 "neighbor ID %s", inet_ntoa(nbr->id)); 274 return; 275 } 276 ospfe_imsg_compose_rde(IMSG_LS_UPD, nbr->peerid, 0, 277 buf, ntohs(lsa.len)); 278 buf += ntohs(lsa.len); 279 len -= ntohs(lsa.len); 280 } 281 if (nlsa > 0 || len > 0) { 282 log_warnx("recv_ls_update: bad packet size, " 283 "neighbor ID %s", inet_ntoa(nbr->id)); 284 return; 285 } 286 break; 287 default: 288 fatalx("recv_ls_update: unknown neighbor state"); 289 } 290 } 291 292 /* link state retransmit list */ 293 void 294 ls_retrans_list_add(struct nbr *nbr, struct lsa_hdr *lsa, 295 unsigned short timeout, unsigned short oneshot) 296 { 297 struct timeval tv; 298 struct lsa_entry *le; 299 struct lsa_ref *ref; 300 301 if ((ref = lsa_cache_get(lsa)) == NULL) 302 fatalx("King Bula sez: somebody forgot to lsa_cache_add"); 303 304 if ((le = calloc(1, sizeof(*le))) == NULL) 305 fatal("ls_retrans_list_add"); 306 307 le->le_ref = ref; 308 le->le_when = timeout; 309 le->le_oneshot = oneshot; 310 311 ls_retrans_list_insert(nbr, le); 312 313 if (!evtimer_pending(&nbr->ls_retrans_timer, NULL)) { 314 timerclear(&tv); 315 tv.tv_sec = TAILQ_FIRST(&nbr->ls_retrans_list)->le_when; 316 317 if (evtimer_add(&nbr->ls_retrans_timer, &tv) == -1) 318 fatal("ls_retrans_list_add"); 319 } 320 } 321 322 int 323 ls_retrans_list_del(struct nbr *nbr, struct lsa_hdr *lsa_hdr) 324 { 325 struct lsa_entry *le; 326 327 if ((le = ls_retrans_list_get(nbr, lsa_hdr)) == NULL) 328 return (-1); 329 /* 330 * Compare LSA with the Ack by comparing not only the seq_num and 331 * checksum but also the age field. Since we only care about MAX_AGE 332 * vs. non-MAX_AGE LSA, a simple >= comparison is good enough. This 333 * ensures that a LSA withdrawal is not acked by a previous update. 334 */ 335 if (lsa_hdr->seq_num == le->le_ref->hdr.seq_num && 336 lsa_hdr->ls_chksum == le->le_ref->hdr.ls_chksum && 337 ntohs(lsa_hdr->age) >= ntohs(le->le_ref->hdr.age)) { 338 ls_retrans_list_free(nbr, le); 339 return (0); 340 } 341 342 return (-1); 343 } 344 345 struct lsa_entry * 346 ls_retrans_list_get(struct nbr *nbr, struct lsa_hdr *lsa_hdr) 347 { 348 struct lsa_entry *le; 349 350 TAILQ_FOREACH(le, &nbr->ls_retrans_list, entry) { 351 if ((lsa_hdr->type == le->le_ref->hdr.type) && 352 (lsa_hdr->ls_id == le->le_ref->hdr.ls_id) && 353 (lsa_hdr->adv_rtr == le->le_ref->hdr.adv_rtr)) 354 return (le); 355 } 356 return (NULL); 357 } 358 359 void 360 ls_retrans_list_insert(struct nbr *nbr, struct lsa_entry *new) 361 { 362 struct lsa_entry *le; 363 unsigned short when = new->le_when; 364 365 TAILQ_FOREACH(le, &nbr->ls_retrans_list, entry) { 366 if (when < le->le_when) { 367 new->le_when = when; 368 TAILQ_INSERT_BEFORE(le, new, entry); 369 nbr->ls_ret_cnt++; 370 return; 371 } 372 when -= le->le_when; 373 } 374 new->le_when = when; 375 TAILQ_INSERT_TAIL(&nbr->ls_retrans_list, new, entry); 376 nbr->ls_ret_cnt++; 377 } 378 379 void 380 ls_retrans_list_remove(struct nbr *nbr, struct lsa_entry *le) 381 { 382 struct timeval tv; 383 struct lsa_entry *next = TAILQ_NEXT(le, entry); 384 int reset = 0; 385 386 /* adjust timeout of next entry */ 387 if (next) 388 next->le_when += le->le_when; 389 390 if (TAILQ_FIRST(&nbr->ls_retrans_list) == le && 391 evtimer_pending(&nbr->ls_retrans_timer, NULL)) 392 reset = 1; 393 394 TAILQ_REMOVE(&nbr->ls_retrans_list, le, entry); 395 nbr->ls_ret_cnt--; 396 397 if (reset && TAILQ_FIRST(&nbr->ls_retrans_list)) { 398 if (evtimer_del(&nbr->ls_retrans_timer) == -1) 399 fatal("ls_retrans_list_remove"); 400 401 timerclear(&tv); 402 tv.tv_sec = TAILQ_FIRST(&nbr->ls_retrans_list)->le_when; 403 404 if (evtimer_add(&nbr->ls_retrans_timer, &tv) == -1) 405 fatal("ls_retrans_list_remove"); 406 } 407 } 408 409 void 410 ls_retrans_list_free(struct nbr *nbr, struct lsa_entry *le) 411 { 412 ls_retrans_list_remove(nbr, le); 413 414 lsa_cache_put(le->le_ref, nbr); 415 free(le); 416 } 417 418 void 419 ls_retrans_list_clr(struct nbr *nbr) 420 { 421 struct lsa_entry *le; 422 423 while ((le = TAILQ_FIRST(&nbr->ls_retrans_list)) != NULL) 424 ls_retrans_list_free(nbr, le); 425 426 nbr->ls_ret_cnt = 0; 427 } 428 429 /* ARGSUSED */ 430 void 431 ls_retrans_timer(int fd, short event, void *bula) 432 { 433 struct timeval tv; 434 struct timespec tp; 435 struct in_addr addr; 436 struct nbr *nbr = bula; 437 struct lsa_entry *le; 438 struct ibuf *buf; 439 time_t now; 440 int d; 441 u_int32_t nlsa = 0; 442 443 if ((le = TAILQ_FIRST(&nbr->ls_retrans_list)) != NULL) 444 le->le_when = 0; /* timer fired */ 445 else 446 return; /* queue empty, nothing to do */ 447 448 clock_gettime(CLOCK_MONOTONIC, &tp); 449 now = tp.tv_sec; 450 451 if (nbr->iface->self == nbr) { 452 /* 453 * oneshot needs to be set for lsa queued for flooding, 454 * if oneshot is not set then the lsa needs to be converted 455 * because the router switched lately to DR or BDR 456 */ 457 if (le->le_oneshot && nbr->iface->state & IF_STA_DRORBDR) 458 inet_aton(AllSPFRouters, &addr); 459 else if (nbr->iface->state & IF_STA_DRORBDR) { 460 /* 461 * old retransmission needs to be converted into 462 * flood by rerunning the lsa_flood. 463 */ 464 lsa_flood(nbr->iface, nbr, &le->le_ref->hdr, 465 le->le_ref->data); 466 ls_retrans_list_free(nbr, le); 467 /* ls_retrans_list_free retriggers the timer */ 468 return; 469 } else if (nbr->iface->type == IF_TYPE_POINTOPOINT) 470 memcpy(&addr, &nbr->addr, sizeof(addr)); 471 else 472 inet_aton(AllDRouters, &addr); 473 } else 474 memcpy(&addr, &nbr->addr, sizeof(addr)); 475 476 if ((buf = prepare_ls_update(nbr->iface)) == NULL) { 477 le->le_when = 1; 478 goto done; 479 } 480 481 while ((le = TAILQ_FIRST(&nbr->ls_retrans_list)) != NULL && 482 le->le_when == 0) { 483 d = now - le->le_ref->stamp; 484 if (d < 0) 485 d = 0; 486 else if (d > MAX_AGE) 487 d = MAX_AGE; 488 489 if (add_ls_update(buf, nbr->iface, le->le_ref->data, 490 le->le_ref->len, d) == 0) { 491 if (nlsa == 0) { 492 /* something bad happened retry later */ 493 log_warnx("ls_retrans_timer: sending LS update " 494 "to neighbor ID %s failed", 495 inet_ntoa(nbr->id)); 496 TAILQ_REMOVE(&nbr->ls_retrans_list, le, entry); 497 nbr->ls_ret_cnt--; 498 le->le_when = nbr->iface->rxmt_interval; 499 ls_retrans_list_insert(nbr, le); 500 } 501 break; 502 } 503 nlsa++; 504 if (le->le_oneshot) 505 ls_retrans_list_free(nbr, le); 506 else { 507 TAILQ_REMOVE(&nbr->ls_retrans_list, le, entry); 508 nbr->ls_ret_cnt--; 509 le->le_when = nbr->iface->rxmt_interval; 510 ls_retrans_list_insert(nbr, le); 511 } 512 } 513 if (nlsa) 514 send_ls_update(buf, nbr->iface, addr, nlsa); 515 else 516 ibuf_free(buf); 517 518 done: 519 if ((le = TAILQ_FIRST(&nbr->ls_retrans_list)) != NULL) { 520 timerclear(&tv); 521 tv.tv_sec = le->le_when; 522 523 if (evtimer_add(&nbr->ls_retrans_timer, &tv) == -1) 524 fatal("ls_retrans_timer"); 525 } 526 } 527 528 LIST_HEAD(lsa_cache_head, lsa_ref); 529 530 struct lsa_cache { 531 struct lsa_cache_head *hashtbl; 532 u_int32_t hashmask; 533 } lsacache; 534 535 SIPHASH_KEY lsacachekey; 536 537 struct lsa_ref *lsa_cache_look(struct lsa_hdr *); 538 539 void 540 lsa_cache_init(u_int32_t hashsize) 541 { 542 u_int32_t hs, i; 543 544 for (hs = 1; hs < hashsize; hs <<= 1) 545 ; 546 lsacache.hashtbl = calloc(hs, sizeof(struct lsa_cache_head)); 547 if (lsacache.hashtbl == NULL) 548 fatal("lsa_cache_init"); 549 550 for (i = 0; i < hs; i++) 551 LIST_INIT(&lsacache.hashtbl[i]); 552 arc4random_buf(&lsacachekey, sizeof(lsacachekey)); 553 554 lsacache.hashmask = hs - 1; 555 } 556 557 static uint32_t 558 lsa_hash_hdr(const struct lsa_hdr *hdr) 559 { 560 return SipHash24(&lsacachekey, hdr, sizeof(*hdr)); 561 } 562 563 struct lsa_ref * 564 lsa_cache_add(void *data, u_int16_t len) 565 { 566 struct lsa_cache_head *head; 567 struct lsa_ref *ref, *old; 568 struct timespec tp; 569 570 if ((ref = calloc(1, sizeof(*ref))) == NULL) 571 fatal("lsa_cache_add"); 572 memcpy(&ref->hdr, data, sizeof(ref->hdr)); 573 574 if ((old = lsa_cache_look(&ref->hdr))) { 575 free(ref); 576 old->refcnt++; 577 return (old); 578 } 579 580 if ((ref->data = malloc(len)) == NULL) 581 fatal("lsa_cache_add"); 582 memcpy(ref->data, data, len); 583 584 clock_gettime(CLOCK_MONOTONIC, &tp); 585 ref->stamp = tp.tv_sec; 586 ref->len = len; 587 ref->refcnt = 1; 588 589 head = &lsacache.hashtbl[lsa_hash_hdr(&ref->hdr) & lsacache.hashmask]; 590 LIST_INSERT_HEAD(head, ref, entry); 591 return (ref); 592 } 593 594 struct lsa_ref * 595 lsa_cache_get(struct lsa_hdr *lsa_hdr) 596 { 597 struct lsa_ref *ref; 598 599 ref = lsa_cache_look(lsa_hdr); 600 if (ref) 601 ref->refcnt++; 602 603 return (ref); 604 } 605 606 void 607 lsa_cache_put(struct lsa_ref *ref, struct nbr *nbr) 608 { 609 if (--ref->refcnt > 0) 610 return; 611 612 if (ntohs(ref->hdr.age) >= MAX_AGE) 613 ospfe_imsg_compose_rde(IMSG_LS_MAXAGE, nbr->peerid, 0, 614 ref->data, sizeof(struct lsa_hdr)); 615 616 free(ref->data); 617 LIST_REMOVE(ref, entry); 618 free(ref); 619 } 620 621 struct lsa_ref * 622 lsa_cache_look(struct lsa_hdr *lsa_hdr) 623 { 624 struct lsa_cache_head *head; 625 struct lsa_ref *ref; 626 627 head = &lsacache.hashtbl[lsa_hash_hdr(lsa_hdr) & lsacache.hashmask]; 628 629 LIST_FOREACH(ref, head, entry) { 630 if (memcmp(&ref->hdr, lsa_hdr, sizeof(*lsa_hdr)) == 0) 631 /* found match */ 632 return (ref); 633 } 634 635 return (NULL); 636 } 637