1 /* $OpenBSD: neighbor.c,v 1.24 2011/03/12 01:57:13 claudio Exp $ */ 2 3 /* 4 * Copyright (c) 2009 Michele Marchetto <michele@openbsd.org> 5 * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org> 6 * Copyright (c) 2004, 2005, 2008 Esben Norby <norby@openbsd.org> 7 * 8 * Permission to use, copy, modify, and distribute this software for any 9 * purpose with or without fee is hereby granted, provided that the above 10 * copyright notice and this permission notice appear in all copies. 11 * 12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 19 */ 20 21 #include <sys/types.h> 22 #include <sys/ioctl.h> 23 #include <sys/time.h> 24 #include <sys/socket.h> 25 #include <netinet/in.h> 26 #include <arpa/inet.h> 27 #include <net/if.h> 28 29 #include <ctype.h> 30 #include <err.h> 31 #include <stdio.h> 32 #include <stdlib.h> 33 #include <string.h> 34 #include <event.h> 35 #include <unistd.h> 36 37 #include "ldpd.h" 38 #include "ldp.h" 39 #include "ldpe.h" 40 #include "control.h" 41 #include "log.h" 42 #include "lde.h" 43 44 int nbr_establish_connection(struct nbr *); 45 void nbr_send_labelmappings(struct nbr *); 46 int nbr_act_session_operational(struct nbr *); 47 48 static __inline int nbr_id_compare(struct nbr *, struct nbr *); 49 static __inline int nbr_addr_compare(struct nbr *, struct nbr *); 50 static __inline int nbr_pid_compare(struct nbr *, struct nbr *); 51 52 RB_HEAD(nbr_id_head, nbr); 53 RB_PROTOTYPE(nbr_id_head, nbr, id_tree, nbr_id_compare) 54 RB_GENERATE(nbr_id_head, nbr, id_tree, nbr_id_compare) 55 RB_HEAD(nbr_addr_head, nbr); 56 RB_PROTOTYPE(nbr_addr_head, nbr, addr_tree, nbr_addr_compare) 57 RB_GENERATE(nbr_addr_head, nbr, addr_tree, nbr_addr_compare) 58 RB_HEAD(nbr_pid_head, nbr); 59 RB_PROTOTYPE(nbr_pid_head, nbr, pid_tree, nbr_pid_compare) 60 RB_GENERATE(nbr_pid_head, nbr, pid_tree, nbr_pid_compare) 61 62 static __inline int 63 nbr_id_compare(struct nbr *a, struct nbr *b) 64 { 65 if (ntohl(a->id.s_addr) - ntohl(b->id.s_addr) == 0) 66 return (a->lspace - b->lspace); 67 return (ntohl(a->id.s_addr) - ntohl(b->id.s_addr)); 68 } 69 70 static __inline int 71 nbr_addr_compare(struct nbr *a, struct nbr *b) 72 { 73 return (ntohl(a->addr.s_addr) - ntohl(b->addr.s_addr)); 74 } 75 76 static __inline int 77 nbr_pid_compare(struct nbr *a, struct nbr *b) 78 { 79 return (a->peerid - b->peerid); 80 } 81 82 struct nbr_id_head nbrs_by_id = RB_INITIALIZER(&nbrs_by_id); 83 struct nbr_addr_head nbrs_by_addr = RB_INITIALIZER(&nbrs_by_addr); 84 struct nbr_pid_head nbrs_by_pid = RB_INITIALIZER(&nbrs_by_pid); 85 86 u_int32_t peercnt = NBR_CNTSTART; 87 88 extern struct ldpd_conf *leconf; 89 90 struct { 91 int state; 92 enum nbr_event event; 93 enum nbr_action action; 94 int new_state; 95 } nbr_fsm_tbl[] = { 96 /* current state event that happened action to take resulting state */ 97 /* Discovery States */ 98 {NBR_STA_DOWN, NBR_EVT_HELLO_RCVD, NBR_ACT_STRT_ITIMER, NBR_STA_PRESENT}, 99 {NBR_STA_SESSION, NBR_EVT_HELLO_RCVD, NBR_ACT_RST_ITIMER, 0}, 100 /* Passive Role */ 101 {NBR_STA_PRESENT, NBR_EVT_SESSION_UP, NBR_ACT_SESSION_EST, NBR_STA_INITIAL}, 102 {NBR_STA_INITIAL, NBR_EVT_INIT_RCVD, NBR_ACT_INIT_SEND, NBR_STA_OPENREC}, 103 {NBR_STA_OPENREC, NBR_EVT_KEEPALIVE_RCVD, NBR_ACT_STRT_KTIMER, NBR_STA_OPER}, 104 /* Active Role */ 105 {NBR_STA_PRESENT, NBR_EVT_INIT_SENT, NBR_ACT_NOTHING, NBR_STA_OPENSENT}, 106 {NBR_STA_OPENSENT, NBR_EVT_INIT_RCVD, NBR_ACT_KEEPALIVE_SEND, NBR_STA_OPER}, 107 /* Session Maintenance */ 108 {NBR_STA_OPER, NBR_EVT_PDU_RCVD, NBR_ACT_RST_KTIMEOUT, 0}, 109 /* Session Close */ 110 {NBR_STA_SESSION, NBR_EVT_CLOSE_SESSION, NBR_ACT_CLOSE_SESSION, NBR_STA_PRESENT}, 111 {NBR_STA_SESSION, NBR_EVT_DOWN, NBR_ACT_CLOSE_SESSION, }, 112 {-1, NBR_EVT_NOTHING, NBR_ACT_NOTHING, 0}, 113 }; 114 115 const char * const nbr_event_names[] = { 116 "NOTHING", 117 "HELLO RECEIVED", 118 "SESSION UP", 119 "SESSION CLOSE", 120 "INIT RECEIVED", 121 "KEEPALIVE RECEIVED", 122 "PDU RECEIVED", 123 "INIT SENT", 124 "DOWN" 125 }; 126 127 const char * const nbr_action_names[] = { 128 "NOTHING", 129 "START INACTIVITY TIMER", 130 "RESET INACTIVITY TIMER", 131 "RESET KEEPALIVE TIMEOUT", 132 "START KEEPALIVE TIMER", 133 "RESET KEEPALIVE TIMER", 134 "START NEIGHBOR SESSION", 135 "SEND INIT", 136 "SEND KEEPALIVE", 137 "CLOSE SESSION" 138 }; 139 140 int 141 nbr_fsm(struct nbr *nbr, enum nbr_event event) 142 { 143 struct timeval now; 144 int old_state; 145 int new_state = 0; 146 int i, ret = 0; 147 148 old_state = nbr->state; 149 for (i = 0; nbr_fsm_tbl[i].state != -1; i++) 150 if ((nbr_fsm_tbl[i].state & old_state) && 151 (nbr_fsm_tbl[i].event == event)) { 152 new_state = nbr_fsm_tbl[i].new_state; 153 break; 154 } 155 156 if (nbr_fsm_tbl[i].state == -1) { 157 /* event outside of the defined fsm, ignore it. */ 158 log_warnx("nbr_fsm: neighbor ID %s, " 159 "event %s not expected in state %s", 160 inet_ntoa(nbr->id), nbr_event_names[event], 161 nbr_state_name(old_state)); 162 return (0); 163 } 164 165 ret = 0; 166 167 switch (nbr_fsm_tbl[i].action) { 168 case NBR_ACT_RST_ITIMER: 169 case NBR_ACT_STRT_ITIMER: 170 nbr_start_itimer(nbr); 171 break; 172 case NBR_ACT_RST_KTIMEOUT: 173 nbr_start_ktimeout(nbr); 174 break; 175 case NBR_ACT_RST_KTIMER: 176 nbr_start_ktimer(nbr); 177 break; 178 case NBR_ACT_STRT_KTIMER: 179 nbr_act_session_operational(nbr); 180 nbr_start_ktimer(nbr); 181 nbr_start_ktimeout(nbr); 182 send_address(nbr, NULL); 183 nbr_send_labelmappings(nbr); 184 break; 185 case NBR_ACT_SESSION_EST: 186 ret = nbr_act_session_establish(nbr, 0); 187 break; 188 case NBR_ACT_INIT_SEND: 189 send_init(nbr); 190 send_keepalive(nbr); 191 break; 192 case NBR_ACT_KEEPALIVE_SEND: 193 nbr_act_session_operational(nbr); 194 nbr_start_ktimer(nbr); 195 nbr_start_ktimeout(nbr); 196 send_keepalive(nbr); 197 send_address(nbr, NULL); 198 nbr_send_labelmappings(nbr); 199 break; 200 case NBR_ACT_CLOSE_SESSION: 201 ldpe_imsg_compose_lde(IMSG_NEIGHBOR_DOWN, nbr->peerid, 0, 202 NULL, 0); 203 session_close(nbr); 204 nbr_start_idtimer(nbr); 205 break; 206 case NBR_ACT_NOTHING: 207 /* do nothing */ 208 break; 209 } 210 211 if (ret) { 212 log_warnx("nbr_fsm: error changing state for neighbor ID %s, " 213 "event %s, state %s", inet_ntoa(nbr->id), 214 nbr_event_names[event], nbr_state_name(old_state)); 215 return (-1); 216 } 217 218 if (new_state != 0) 219 nbr->state = new_state; 220 221 if (old_state != nbr->state) { 222 log_debug("nbr_fsm: event %s resulted in action %s and " 223 "changing state for neighbor ID %s from %s to %s", 224 nbr_event_names[event], 225 nbr_action_names[nbr_fsm_tbl[i].action], 226 inet_ntoa(nbr->id), nbr_state_name(old_state), 227 nbr_state_name(nbr->state)); 228 229 if (nbr->state == NBR_STA_OPER) { 230 gettimeofday(&now, NULL); 231 nbr->uptime = now.tv_sec; 232 } 233 } 234 235 return (ret); 236 } 237 238 struct nbr * 239 nbr_new(u_int32_t nbr_id, u_int16_t lspace, struct iface *iface, 240 struct in_addr a) 241 { 242 struct nbr *nbr; 243 244 if ((nbr = calloc(1, sizeof(*nbr))) == NULL) 245 fatal("nbr_new"); 246 if ((nbr->rbuf = calloc(1, sizeof(struct ibuf_read))) == NULL) 247 fatal("nbr_new"); 248 249 nbr->state = NBR_STA_DOWN; 250 nbr->id.s_addr = nbr_id; 251 nbr->lspace = lspace; 252 nbr->iface = iface; 253 nbr->addr = a; 254 255 /* get next unused peerid */ 256 while (nbr_find_peerid(++peercnt)) 257 ; 258 nbr->peerid = peercnt; 259 260 if (RB_INSERT(nbr_pid_head, &nbrs_by_pid, nbr) != NULL) 261 fatalx("nbr_new: RB_INSERT(nbrs_by_pid) failed"); 262 if (RB_INSERT(nbr_addr_head, &nbrs_by_addr, nbr) != NULL) 263 fatalx("nbr_new: RB_INSERT(nbrs_by_addr) failed"); 264 if (RB_INSERT(nbr_id_head, &nbrs_by_id, nbr) != NULL) 265 fatalx("nbr_new: RB_INSERT(nbrs_by_id) failed"); 266 267 TAILQ_INIT(&nbr->mapping_list); 268 TAILQ_INIT(&nbr->withdraw_list); 269 TAILQ_INIT(&nbr->request_list); 270 TAILQ_INIT(&nbr->release_list); 271 TAILQ_INIT(&nbr->abortreq_list); 272 273 /* set event structures */ 274 evtimer_set(&nbr->inactivity_timer, nbr_itimer, nbr); 275 evtimer_set(&nbr->keepalive_timeout, nbr_ktimeout, nbr); 276 evtimer_set(&nbr->keepalive_timer, nbr_ktimer, nbr); 277 evtimer_set(&nbr->initdelay_timer, nbr_idtimer, nbr); 278 279 return (nbr); 280 } 281 282 void 283 nbr_del(struct nbr *nbr) 284 { 285 session_close(nbr); 286 287 if (evtimer_pending(&nbr->inactivity_timer, NULL)) 288 evtimer_del(&nbr->inactivity_timer); 289 if (evtimer_pending(&nbr->keepalive_timer, NULL)) 290 evtimer_del(&nbr->keepalive_timer); 291 if (evtimer_pending(&nbr->keepalive_timeout, NULL)) 292 evtimer_del(&nbr->keepalive_timeout); 293 if (evtimer_pending(&nbr->initdelay_timer, NULL)) 294 evtimer_del(&nbr->initdelay_timer); 295 296 nbr_mapping_list_clr(nbr, &nbr->mapping_list); 297 298 RB_REMOVE(nbr_pid_head, &nbrs_by_pid, nbr); 299 RB_REMOVE(nbr_addr_head, &nbrs_by_addr, nbr); 300 RB_REMOVE(nbr_id_head, &nbrs_by_id, nbr); 301 302 free(nbr->rbuf); 303 free(nbr); 304 } 305 306 struct nbr * 307 nbr_find_peerid(u_int32_t peerid) 308 { 309 struct nbr n; 310 n.peerid = peerid; 311 return (RB_FIND(nbr_pid_head, &nbrs_by_pid, &n)); 312 } 313 314 struct nbr * 315 nbr_find_ip(u_int32_t addr) 316 { 317 struct nbr n; 318 n.addr.s_addr = addr; 319 return (RB_FIND(nbr_addr_head, &nbrs_by_addr, &n)); 320 } 321 322 struct nbr * 323 nbr_find_ldpid(u_int32_t rtr_id, u_int16_t lspace) 324 { 325 struct nbr n; 326 n.id.s_addr = rtr_id; 327 n.lspace = lspace; 328 return (RB_FIND(nbr_id_head, &nbrs_by_id, &n)); 329 } 330 331 /* timers */ 332 333 /* Inactivity timer: timeout based on hellos */ 334 /* ARGSUSED */ 335 void 336 nbr_itimer(int fd, short event, void *arg) 337 { 338 struct nbr *nbr = arg; 339 340 log_debug("nbr_itimer: neighbor ID %s peerid %lu", inet_ntoa(nbr->id), 341 nbr->peerid); 342 343 nbr_del(nbr); 344 } 345 346 void 347 nbr_start_itimer(struct nbr *nbr) 348 { 349 struct timeval tv; 350 351 timerclear(&tv); 352 tv.tv_sec = nbr->holdtime; 353 354 if (evtimer_add(&nbr->inactivity_timer, &tv) == -1) 355 fatal("nbr_start_itimer"); 356 } 357 358 void 359 nbr_stop_itimer(struct nbr *nbr) 360 { 361 if (evtimer_del(&nbr->inactivity_timer) == -1) 362 fatal("nbr_stop_itimer"); 363 } 364 365 /* Keepalive timer: timer to send keepalive message to neighbors */ 366 367 void 368 nbr_ktimer(int fd, short event, void *arg) 369 { 370 struct nbr *nbr = arg; 371 struct timeval tv; 372 373 send_keepalive(nbr); 374 375 timerclear(&tv); 376 tv.tv_sec = (time_t)(nbr->keepalive / KEEPALIVE_PER_PERIOD); 377 if (evtimer_add(&nbr->keepalive_timer, &tv) == -1) 378 fatal("nbr_ktimer"); 379 } 380 381 void 382 nbr_start_ktimer(struct nbr *nbr) 383 { 384 struct timeval tv; 385 386 timerclear(&tv); 387 388 /* XXX: just to be sure it will send three keepalives per period */ 389 tv.tv_sec = (time_t)(nbr->keepalive / KEEPALIVE_PER_PERIOD); 390 391 if (evtimer_add(&nbr->keepalive_timer, &tv) == -1) 392 fatal("nbr_start_ktimer"); 393 } 394 395 void 396 nbr_stop_ktimer(struct nbr *nbr) 397 { 398 if (evtimer_del(&nbr->keepalive_timer) == -1) 399 fatal("nbr_stop_ktimer"); 400 } 401 402 /* Keepalive timeout: if the nbr hasn't sent keepalive */ 403 404 void 405 nbr_ktimeout(int fd, short event, void *arg) 406 { 407 struct nbr *nbr = arg; 408 409 log_debug("nbr_ktimeout: neighbor ID %s peerid %lu", inet_ntoa(nbr->id), 410 nbr->peerid); 411 412 send_notification_nbr(nbr, S_KEEPALIVE_TMR, 0, 0); 413 /* XXX race, send_notification_nbr() has no chance to be sent */ 414 session_close(nbr); 415 } 416 417 void 418 nbr_start_ktimeout(struct nbr *nbr) 419 { 420 struct timeval tv; 421 422 timerclear(&tv); 423 tv.tv_sec = nbr->keepalive; 424 425 if (evtimer_add(&nbr->keepalive_timeout, &tv) == -1) 426 fatal("nbr_start_ktimeout"); 427 } 428 429 void 430 nbr_stop_ktimeout(struct nbr *nbr) 431 { 432 if (evtimer_del(&nbr->keepalive_timeout) == -1) 433 fatal("nbr_stop_ktimeout"); 434 } 435 436 /* Init delay timer: timer to retry to iniziatize session */ 437 438 void 439 nbr_idtimer(int fd, short event, void *arg) 440 { 441 struct nbr *nbr = arg; 442 443 if (ntohl(nbr->addr.s_addr) >= ntohl(nbr->iface->addr.s_addr)) 444 return; 445 446 log_debug("nbr_idtimer: neighbor ID %s peerid %lu", inet_ntoa(nbr->id), 447 nbr->peerid); 448 449 nbr_act_session_establish(nbr, 1); 450 } 451 452 void 453 nbr_start_idtimer(struct nbr *nbr) 454 { 455 struct timeval tv; 456 457 timerclear(&tv); 458 tv.tv_sec = INIT_DELAY_TMR; 459 460 if (evtimer_add(&nbr->initdelay_timer, &tv) == -1) 461 fatal("nbr_start_idtimer"); 462 } 463 464 void 465 nbr_stop_idtimer(struct nbr *nbr) 466 { 467 if (evtimer_del(&nbr->initdelay_timer) == -1) 468 fatal("nbr_stop_idtimer"); 469 } 470 471 int 472 nbr_pending_idtimer(struct nbr *nbr) 473 { 474 if (evtimer_pending(&nbr->initdelay_timer, NULL)) 475 return (1); 476 477 return (0); 478 } 479 480 int 481 nbr_establish_connection(struct nbr *nbr) 482 { 483 struct sockaddr_in in; 484 485 bzero(&in, sizeof(in)); 486 in.sin_family = AF_INET; 487 in.sin_port = htons(LDP_PORT); 488 in.sin_addr.s_addr = nbr->addr.s_addr; 489 490 nbr->fd = socket(AF_INET, SOCK_STREAM, 0); 491 if (nbr->fd == -1) { 492 log_debug("nbr_establish_connection: error while " 493 "creating socket"); 494 return (-1); 495 } 496 497 if (connect(nbr->fd, (struct sockaddr *)&in, sizeof(in)) == -1) { 498 log_debug("nbr_establish_connection: error while " 499 "connecting to %s", inet_ntoa(nbr->addr)); 500 nbr_start_idtimer(nbr); 501 close(nbr->fd); 502 return (-1); 503 } 504 505 return (0); 506 } 507 508 int 509 nbr_act_session_establish(struct nbr *nbr, int active) 510 { 511 if (active) { 512 if (nbr_establish_connection(nbr) < 0) 513 return (-1); 514 } 515 516 evbuf_init(&nbr->wbuf, nbr->fd, session_write, nbr); 517 event_set(&nbr->rev, nbr->fd, EV_READ | EV_PERSIST, session_read, nbr); 518 event_add(&nbr->rev, NULL); 519 520 if (active) { 521 send_init(nbr); 522 nbr_fsm(nbr, NBR_EVT_INIT_SENT); 523 } 524 525 return (0); 526 } 527 528 int 529 nbr_act_session_operational(struct nbr *nbr) 530 { 531 struct lde_nbr rn; 532 533 bzero(&rn, sizeof(rn)); 534 rn.id.s_addr = nbr->id.s_addr; 535 rn.lspace = nbr->lspace; 536 537 return (ldpe_imsg_compose_lde(IMSG_NEIGHBOR_UP, nbr->peerid, 0, &rn, 538 sizeof(rn))); 539 } 540 541 void 542 nbr_send_labelmappings(struct nbr *nbr) 543 { 544 if (leconf->mode & MODE_ADV_UNSOLICITED) { 545 ldpe_imsg_compose_lde(IMSG_LABEL_MAPPING_FULL, nbr->peerid, 0, 546 NULL, 0); 547 } 548 } 549 550 void 551 nbr_mapping_add(struct nbr *nbr, struct mapping_head *mh, struct map *map) 552 { 553 struct mapping_entry *me; 554 555 me = calloc(1, sizeof(*me)); 556 if (me == NULL) 557 fatal("nbr_mapping_add"); 558 me->map = *map; 559 560 TAILQ_INSERT_TAIL(mh, me, entry); 561 } 562 563 struct mapping_entry * 564 nbr_mapping_find(struct nbr *nbr, struct mapping_head *mh, struct map *map) 565 { 566 struct mapping_entry *me = NULL; 567 568 TAILQ_FOREACH(me, mh, entry) { 569 if (me->map.prefix.s_addr == map->prefix.s_addr && 570 me->map.prefixlen == map->prefixlen) 571 return (me); 572 } 573 574 return (NULL); 575 } 576 577 void 578 nbr_mapping_del(struct nbr *nbr, struct mapping_head *mh, struct map *map) 579 { 580 struct mapping_entry *me; 581 582 me = nbr_mapping_find(nbr, mh, map); 583 if (me == NULL) 584 return; 585 586 TAILQ_REMOVE(mh, me, entry); 587 free(me); 588 } 589 590 void 591 nbr_mapping_list_clr(struct nbr *nbr, struct mapping_head *mh) 592 { 593 struct mapping_entry *me; 594 595 while ((me = TAILQ_FIRST(mh)) != NULL) { 596 TAILQ_REMOVE(mh, me, entry); 597 free(me); 598 } 599 } 600 601 struct ctl_nbr * 602 nbr_to_ctl(struct nbr *nbr) 603 { 604 static struct ctl_nbr nctl; 605 struct timeval tv, now, res; 606 607 memcpy(nctl.name, nbr->iface->name, sizeof(nctl.name)); 608 memcpy(&nctl.id, &nbr->id, sizeof(nctl.id)); 609 memcpy(&nctl.addr, &nbr->addr, sizeof(nctl.addr)); 610 611 nctl.nbr_state = nbr->state; 612 nctl.iface_state = nbr->iface->state; 613 614 gettimeofday(&now, NULL); 615 if (evtimer_pending(&nbr->inactivity_timer, &tv)) { 616 timersub(&tv, &now, &res); 617 if (nbr->state & NBR_STA_DOWN) 618 nctl.dead_timer = DEFAULT_NBR_TMOUT - res.tv_sec; 619 else 620 nctl.dead_timer = res.tv_sec; 621 } else 622 nctl.dead_timer = 0; 623 624 if (nbr->state == NBR_STA_OPER) { 625 nctl.uptime = now.tv_sec - nbr->uptime; 626 } else 627 nctl.uptime = 0; 628 629 return (&nctl); 630 } 631 632 void 633 ldpe_nbr_ctl(struct ctl_conn *c) 634 { 635 struct nbr *nbr; 636 struct ctl_nbr *nctl; 637 638 RB_FOREACH(nbr, nbr_addr_head, &nbrs_by_addr) { 639 nctl = nbr_to_ctl(nbr); 640 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_NBR, 0, 0, -1, nctl, 641 sizeof(struct ctl_nbr)); 642 } 643 imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL, 0); 644 } 645