1 /* $OpenBSD: neighbor.c,v 1.43 2013/10/17 17:47:04 renato 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 <errno.h> 32 #include <stdio.h> 33 #include <stdlib.h> 34 #include <string.h> 35 #include <event.h> 36 #include <unistd.h> 37 38 #include "ldpd.h" 39 #include "ldp.h" 40 #include "ldpe.h" 41 #include "control.h" 42 #include "log.h" 43 #include "lde.h" 44 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_pid_compare(struct nbr *, struct nbr *); 50 51 RB_HEAD(nbr_id_head, nbr); 52 RB_PROTOTYPE(nbr_id_head, nbr, id_tree, nbr_id_compare) 53 RB_GENERATE(nbr_id_head, nbr, id_tree, nbr_id_compare) 54 RB_HEAD(nbr_pid_head, nbr); 55 RB_PROTOTYPE(nbr_pid_head, nbr, pid_tree, nbr_pid_compare) 56 RB_GENERATE(nbr_pid_head, nbr, pid_tree, nbr_pid_compare) 57 58 static __inline int 59 nbr_id_compare(struct nbr *a, struct nbr *b) 60 { 61 return (ntohl(a->id.s_addr) - ntohl(b->id.s_addr)); 62 } 63 64 static __inline int 65 nbr_pid_compare(struct nbr *a, struct nbr *b) 66 { 67 return (a->peerid - b->peerid); 68 } 69 70 struct nbr_id_head nbrs_by_id = RB_INITIALIZER(&nbrs_by_id); 71 struct nbr_pid_head nbrs_by_pid = RB_INITIALIZER(&nbrs_by_pid); 72 73 u_int32_t peercnt = NBR_CNTSTART; 74 75 extern struct ldpd_conf *leconf; 76 77 struct { 78 int state; 79 enum nbr_event event; 80 enum nbr_action action; 81 int new_state; 82 } nbr_fsm_tbl[] = { 83 /* current state event that happened action to take resulting state */ 84 /* Passive Role */ 85 {NBR_STA_PRESENT, NBR_EVT_MATCH_ADJ, NBR_ACT_NOTHING, NBR_STA_INITIAL}, 86 {NBR_STA_INITIAL, NBR_EVT_INIT_RCVD, NBR_ACT_PASSIVE_INIT, NBR_STA_OPENREC}, 87 {NBR_STA_OPENREC, NBR_EVT_KEEPALIVE_RCVD, NBR_ACT_SESSION_EST, NBR_STA_OPER}, 88 /* Active Role */ 89 {NBR_STA_PRESENT, NBR_EVT_CONNECT_UP, NBR_ACT_CONNECT_SETUP, NBR_STA_INITIAL}, 90 {NBR_STA_INITIAL, NBR_EVT_INIT_SENT, NBR_ACT_NOTHING, NBR_STA_OPENSENT}, 91 {NBR_STA_OPENSENT, NBR_EVT_INIT_RCVD, NBR_ACT_KEEPALIVE_SEND, NBR_STA_OPENREC}, 92 /* Session Maintenance */ 93 {NBR_STA_OPER, NBR_EVT_PDU_RCVD, NBR_ACT_RST_KTIMEOUT, 0}, 94 {NBR_STA_OPER, NBR_EVT_PDU_SENT, NBR_ACT_RST_KTIMER, 0}, 95 /* Session Close */ 96 {NBR_STA_PRESENT, NBR_EVT_CLOSE_SESSION, NBR_ACT_NOTHING, 0}, 97 {NBR_STA_SESSION, NBR_EVT_CLOSE_SESSION, NBR_ACT_CLOSE_SESSION, NBR_STA_PRESENT}, 98 {-1, NBR_EVT_NOTHING, NBR_ACT_NOTHING, 0}, 99 }; 100 101 const char * const nbr_event_names[] = { 102 "NOTHING", 103 "ADJACENCY MATCHED", 104 "CONNECTION UP", 105 "SESSION CLOSE", 106 "INIT RECEIVED", 107 "KEEPALIVE RECEIVED", 108 "PDU RECEIVED", 109 "PDU SENT", 110 "INIT SENT" 111 }; 112 113 const char * const nbr_action_names[] = { 114 "NOTHING", 115 "RESET KEEPALIVE TIMEOUT", 116 "START NEIGHBOR SESSION", 117 "RESET KEEPALIVE TIMER", 118 "SETUP NEIGHBOR CONNECTION", 119 "SEND INIT AND KEEPALIVE", 120 "SEND KEEPALIVE", 121 "CLOSE SESSION" 122 }; 123 124 int 125 nbr_fsm(struct nbr *nbr, enum nbr_event event) 126 { 127 struct timeval now; 128 int old_state; 129 int new_state = 0; 130 int i; 131 132 old_state = nbr->state; 133 for (i = 0; nbr_fsm_tbl[i].state != -1; i++) 134 if ((nbr_fsm_tbl[i].state & old_state) && 135 (nbr_fsm_tbl[i].event == event)) { 136 new_state = nbr_fsm_tbl[i].new_state; 137 break; 138 } 139 140 if (nbr_fsm_tbl[i].state == -1) { 141 /* event outside of the defined fsm, ignore it. */ 142 log_warnx("nbr_fsm: neighbor ID %s, " 143 "event %s not expected in state %s", 144 inet_ntoa(nbr->id), nbr_event_names[event], 145 nbr_state_name(old_state)); 146 return (0); 147 } 148 149 if (new_state != 0) 150 nbr->state = new_state; 151 152 if (old_state != nbr->state) { 153 log_debug("nbr_fsm: event %s resulted in action %s and " 154 "changing state for neighbor ID %s from %s to %s", 155 nbr_event_names[event], 156 nbr_action_names[nbr_fsm_tbl[i].action], 157 inet_ntoa(nbr->id), nbr_state_name(old_state), 158 nbr_state_name(nbr->state)); 159 160 if (nbr->state == NBR_STA_OPER) { 161 gettimeofday(&now, NULL); 162 nbr->uptime = now.tv_sec; 163 } 164 } 165 166 switch (nbr_fsm_tbl[i].action) { 167 case NBR_ACT_RST_KTIMEOUT: 168 nbr_start_ktimeout(nbr); 169 break; 170 case NBR_ACT_RST_KTIMER: 171 nbr_start_ktimer(nbr); 172 break; 173 case NBR_ACT_SESSION_EST: 174 nbr_act_session_operational(nbr); 175 nbr_start_ktimer(nbr); 176 nbr_start_ktimeout(nbr); 177 send_address(nbr, NULL); 178 nbr_send_labelmappings(nbr); 179 break; 180 case NBR_ACT_CONNECT_SETUP: 181 nbr->tcp = tcp_new(nbr->fd, nbr); 182 183 /* trigger next state */ 184 send_init(nbr); 185 nbr_fsm(nbr, NBR_EVT_INIT_SENT); 186 break; 187 case NBR_ACT_PASSIVE_INIT: 188 send_init(nbr); 189 send_keepalive(nbr); 190 break; 191 case NBR_ACT_KEEPALIVE_SEND: 192 nbr_start_ktimeout(nbr); 193 send_keepalive(nbr); 194 break; 195 case NBR_ACT_CLOSE_SESSION: 196 ldpe_imsg_compose_lde(IMSG_NEIGHBOR_DOWN, nbr->peerid, 0, 197 NULL, 0); 198 session_close(nbr); 199 break; 200 case NBR_ACT_NOTHING: 201 /* do nothing */ 202 break; 203 } 204 205 return (0); 206 } 207 208 struct nbr * 209 nbr_new(struct in_addr id, struct in_addr addr) 210 { 211 struct nbr *nbr; 212 213 log_debug("nbr_new: LSR ID %s", inet_ntoa(id)); 214 215 if ((nbr = calloc(1, sizeof(*nbr))) == NULL) 216 fatal("nbr_new"); 217 218 nbr->state = NBR_STA_PRESENT; 219 nbr->id.s_addr = id.s_addr; 220 nbr->addr.s_addr = addr.s_addr; 221 222 /* get next unused peerid */ 223 while (nbr_find_peerid(++peercnt)) 224 ; 225 nbr->peerid = peercnt; 226 227 if (RB_INSERT(nbr_pid_head, &nbrs_by_pid, nbr) != NULL) 228 fatalx("nbr_new: RB_INSERT(nbrs_by_pid) failed"); 229 if (RB_INSERT(nbr_id_head, &nbrs_by_id, nbr) != NULL) 230 fatalx("nbr_new: RB_INSERT(nbrs_by_id) failed"); 231 232 TAILQ_INIT(&nbr->mapping_list); 233 TAILQ_INIT(&nbr->withdraw_list); 234 TAILQ_INIT(&nbr->request_list); 235 TAILQ_INIT(&nbr->release_list); 236 TAILQ_INIT(&nbr->abortreq_list); 237 238 /* set event structures */ 239 evtimer_set(&nbr->keepalive_timeout, nbr_ktimeout, nbr); 240 evtimer_set(&nbr->keepalive_timer, nbr_ktimer, nbr); 241 evtimer_set(&nbr->initdelay_timer, nbr_idtimer, nbr); 242 243 return (nbr); 244 } 245 246 void 247 nbr_del(struct nbr *nbr) 248 { 249 log_debug("nbr_del: LSR ID %s", inet_ntoa(nbr->id)); 250 251 nbr_fsm(nbr, NBR_EVT_CLOSE_SESSION); 252 253 if (event_pending(&nbr->ev_connect, EV_WRITE, NULL)) 254 event_del(&nbr->ev_connect); 255 nbr_stop_ktimer(nbr); 256 nbr_stop_ktimeout(nbr); 257 nbr_stop_idtimer(nbr); 258 259 mapping_list_clr(&nbr->mapping_list); 260 mapping_list_clr(&nbr->withdraw_list); 261 mapping_list_clr(&nbr->request_list); 262 mapping_list_clr(&nbr->release_list); 263 mapping_list_clr(&nbr->abortreq_list); 264 265 RB_REMOVE(nbr_pid_head, &nbrs_by_pid, nbr); 266 RB_REMOVE(nbr_id_head, &nbrs_by_id, nbr); 267 268 free(nbr); 269 } 270 271 struct nbr * 272 nbr_find_peerid(u_int32_t peerid) 273 { 274 struct nbr n; 275 n.peerid = peerid; 276 return (RB_FIND(nbr_pid_head, &nbrs_by_pid, &n)); 277 } 278 279 struct nbr * 280 nbr_find_ldpid(u_int32_t rtr_id) 281 { 282 struct nbr n; 283 n.id.s_addr = rtr_id; 284 return (RB_FIND(nbr_id_head, &nbrs_by_id, &n)); 285 } 286 287 int 288 nbr_session_active_role(struct nbr *nbr) 289 { 290 if (ntohl(ldpe_router_id()) > ntohl(nbr->addr.s_addr)) 291 return (1); 292 293 return (0); 294 } 295 296 /* timers */ 297 298 /* Keepalive timer: timer to send keepalive message to neighbors */ 299 300 void 301 nbr_ktimer(int fd, short event, void *arg) 302 { 303 struct nbr *nbr = arg; 304 struct timeval tv; 305 306 send_keepalive(nbr); 307 308 timerclear(&tv); 309 tv.tv_sec = (time_t)(nbr->keepalive / KEEPALIVE_PER_PERIOD); 310 if (evtimer_add(&nbr->keepalive_timer, &tv) == -1) 311 fatal("nbr_ktimer"); 312 } 313 314 void 315 nbr_start_ktimer(struct nbr *nbr) 316 { 317 struct timeval tv; 318 319 timerclear(&tv); 320 321 /* XXX: just to be sure it will send three keepalives per period */ 322 tv.tv_sec = (time_t)(nbr->keepalive / KEEPALIVE_PER_PERIOD); 323 324 if (evtimer_add(&nbr->keepalive_timer, &tv) == -1) 325 fatal("nbr_start_ktimer"); 326 } 327 328 void 329 nbr_stop_ktimer(struct nbr *nbr) 330 { 331 if (evtimer_pending(&nbr->keepalive_timer, NULL) && 332 evtimer_del(&nbr->keepalive_timer) == -1) 333 fatal("nbr_stop_ktimer"); 334 } 335 336 /* Keepalive timeout: if the nbr hasn't sent keepalive */ 337 338 void 339 nbr_ktimeout(int fd, short event, void *arg) 340 { 341 struct nbr *nbr = arg; 342 343 log_debug("nbr_ktimeout: neighbor ID %s peerid %u", inet_ntoa(nbr->id), 344 nbr->peerid); 345 346 session_shutdown(nbr, S_KEEPALIVE_TMR, 0, 0); 347 } 348 349 void 350 nbr_start_ktimeout(struct nbr *nbr) 351 { 352 struct timeval tv; 353 354 timerclear(&tv); 355 tv.tv_sec = nbr->keepalive; 356 357 if (evtimer_add(&nbr->keepalive_timeout, &tv) == -1) 358 fatal("nbr_start_ktimeout"); 359 } 360 361 void 362 nbr_stop_ktimeout(struct nbr *nbr) 363 { 364 if (evtimer_pending(&nbr->keepalive_timeout, NULL) && 365 evtimer_del(&nbr->keepalive_timeout) == -1) 366 fatal("nbr_stop_ktimeout"); 367 } 368 369 /* Init delay timer: timer to retry to iniziatize session */ 370 371 void 372 nbr_idtimer(int fd, short event, void *arg) 373 { 374 struct nbr *nbr = arg; 375 376 log_debug("nbr_idtimer: neighbor ID %s peerid %u", inet_ntoa(nbr->id), 377 nbr->peerid); 378 379 if (nbr_session_active_role(nbr)) 380 nbr_establish_connection(nbr); 381 else if (nbr->state == NBR_STA_INITIAL) 382 nbr_fsm(nbr, NBR_EVT_INIT_RCVD); 383 } 384 385 void 386 nbr_start_idtimer(struct nbr *nbr) 387 { 388 struct timeval tv; 389 390 timerclear(&tv); 391 392 tv.tv_sec = INIT_DELAY_TMR; 393 switch(nbr->idtimer_cnt) { 394 default: 395 /* do not further increase the counter */ 396 tv.tv_sec = MAX_DELAY_TMR; 397 break; 398 case 2: 399 tv.tv_sec *= 2; 400 /* FALLTHROUGH */ 401 case 1: 402 tv.tv_sec *= 2; 403 /* FALLTHROUGH */ 404 case 0: 405 nbr->idtimer_cnt++; 406 break; 407 } 408 409 if (evtimer_add(&nbr->initdelay_timer, &tv) == -1) 410 fatal("nbr_start_idtimer"); 411 } 412 413 void 414 nbr_stop_idtimer(struct nbr *nbr) 415 { 416 if (evtimer_pending(&nbr->initdelay_timer, NULL) && 417 evtimer_del(&nbr->initdelay_timer) == -1) 418 fatal("nbr_stop_idtimer"); 419 } 420 421 int 422 nbr_pending_idtimer(struct nbr *nbr) 423 { 424 if (evtimer_pending(&nbr->initdelay_timer, NULL)) 425 return (1); 426 427 return (0); 428 } 429 430 int 431 nbr_pending_connect(struct nbr *nbr) 432 { 433 if (event_initialized(&nbr->ev_connect) && 434 event_pending(&nbr->ev_connect, EV_WRITE, NULL)) 435 return (1); 436 437 return (0); 438 } 439 440 static void 441 nbr_connect_cb(int fd, short event, void *arg) 442 { 443 struct nbr *nbr = arg; 444 int error; 445 socklen_t len; 446 447 len = sizeof(error); 448 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { 449 log_warn("nbr_connect_cb getsockopt SOL_SOCKET SO_ERROR"); 450 return; 451 } 452 453 if (error) { 454 close(nbr->fd); 455 errno = error; 456 log_debug("nbr_connect_cb: error while " 457 "connecting to %s: %s", inet_ntoa(nbr->addr), 458 strerror(errno)); 459 return; 460 } 461 462 nbr_fsm(nbr, NBR_EVT_CONNECT_UP); 463 } 464 465 int 466 nbr_establish_connection(struct nbr *nbr) 467 { 468 struct sockaddr_in local_sa; 469 struct sockaddr_in remote_sa; 470 struct adj *adj; 471 472 nbr->fd = socket(AF_INET, SOCK_STREAM, 0); 473 if (nbr->fd == -1) { 474 log_warn("nbr_establish_connection: error while " 475 "creating socket"); 476 return (-1); 477 } 478 479 session_socket_blockmode(nbr->fd, BM_NONBLOCK); 480 481 bzero(&local_sa, sizeof(local_sa)); 482 local_sa.sin_family = AF_INET; 483 local_sa.sin_port = htons(0); 484 local_sa.sin_addr.s_addr = ldpe_router_id(); 485 486 if (bind(nbr->fd, (struct sockaddr *) &local_sa, 487 sizeof(struct sockaddr_in)) == -1) { 488 log_warn("nbr_establish_connection: error while " 489 "binding socket to %s", inet_ntoa(local_sa.sin_addr)); 490 close(nbr->fd); 491 return (-1); 492 } 493 494 bzero(&remote_sa, sizeof(remote_sa)); 495 remote_sa.sin_family = AF_INET; 496 remote_sa.sin_port = htons(LDP_PORT); 497 remote_sa.sin_addr.s_addr = nbr->addr.s_addr; 498 499 /* 500 * Send an extra hello to guarantee that the remote peer has formed 501 * an adjacency as well. 502 */ 503 LIST_FOREACH(adj, &nbr->adj_list, nbr_entry) 504 send_hello(adj->source.type, adj->source.link.iface, 505 adj->source.target); 506 507 if (connect(nbr->fd, (struct sockaddr *)&remote_sa, 508 sizeof(remote_sa)) == -1) { 509 if (errno == EINPROGRESS) { 510 event_set(&nbr->ev_connect, nbr->fd, EV_WRITE, 511 nbr_connect_cb, nbr); 512 event_add(&nbr->ev_connect, NULL); 513 return (0); 514 } 515 log_warn("nbr_establish_connection: error while " 516 "connecting to %s", inet_ntoa(nbr->addr)); 517 close(nbr->fd); 518 return (-1); 519 } 520 521 /* connection completed immediately */ 522 nbr_fsm(nbr, NBR_EVT_CONNECT_UP); 523 524 return (0); 525 } 526 527 int 528 nbr_act_session_operational(struct nbr *nbr) 529 { 530 nbr->idtimer_cnt = 0; 531 532 return (ldpe_imsg_compose_lde(IMSG_NEIGHBOR_UP, nbr->peerid, 0, 533 &nbr->id, sizeof(nbr->id))); 534 } 535 536 void 537 nbr_send_labelmappings(struct nbr *nbr) 538 { 539 if (leconf->mode & MODE_ADV_UNSOLICITED) { 540 ldpe_imsg_compose_lde(IMSG_LABEL_MAPPING_FULL, nbr->peerid, 0, 541 NULL, 0); 542 } 543 } 544 545 void 546 nbr_mapping_add(struct nbr *nbr, struct mapping_head *mh, struct map *map) 547 { 548 struct mapping_entry *me; 549 550 me = calloc(1, sizeof(*me)); 551 if (me == NULL) 552 fatal("nbr_mapping_add"); 553 me->map = *map; 554 555 TAILQ_INSERT_TAIL(mh, me, entry); 556 } 557 558 struct mapping_entry * 559 nbr_mapping_find(struct nbr *nbr, struct mapping_head *mh, struct map *map) 560 { 561 struct mapping_entry *me = NULL; 562 563 TAILQ_FOREACH(me, mh, entry) { 564 if (me->map.prefix.s_addr == map->prefix.s_addr && 565 me->map.prefixlen == map->prefixlen) 566 return (me); 567 } 568 569 return (NULL); 570 } 571 572 void 573 nbr_mapping_del(struct nbr *nbr, struct mapping_head *mh, struct map *map) 574 { 575 struct mapping_entry *me; 576 577 me = nbr_mapping_find(nbr, mh, map); 578 if (me == NULL) 579 return; 580 581 TAILQ_REMOVE(mh, me, entry); 582 free(me); 583 } 584 585 void 586 mapping_list_clr(struct mapping_head *mh) 587 { 588 struct mapping_entry *me; 589 590 while ((me = TAILQ_FIRST(mh)) != NULL) { 591 TAILQ_REMOVE(mh, me, entry); 592 free(me); 593 } 594 } 595 596 struct ctl_nbr * 597 nbr_to_ctl(struct nbr *nbr) 598 { 599 static struct ctl_nbr nctl; 600 struct timeval now; 601 602 memcpy(&nctl.id, &nbr->id, sizeof(nctl.id)); 603 memcpy(&nctl.addr, &nbr->addr, sizeof(nctl.addr)); 604 nctl.nbr_state = nbr->state; 605 606 gettimeofday(&now, NULL); 607 if (nbr->state == NBR_STA_OPER) { 608 nctl.uptime = now.tv_sec - nbr->uptime; 609 } else 610 nctl.uptime = 0; 611 612 return (&nctl); 613 } 614 615 void 616 ldpe_nbr_ctl(struct ctl_conn *c) 617 { 618 struct nbr *nbr; 619 struct ctl_nbr *nctl; 620 621 RB_FOREACH(nbr, nbr_pid_head, &nbrs_by_pid) { 622 nctl = nbr_to_ctl(nbr); 623 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_NBR, 0, 0, -1, nctl, 624 sizeof(struct ctl_nbr)); 625 } 626 imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL, 0); 627 } 628