1 /* $OpenBSD: neighbor.c,v 1.78 2016/09/03 16:07:08 renato Exp $ */ 2 3 /* 4 * Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org> 5 * Copyright (c) 2009 Michele Marchetto <michele@openbsd.org> 6 * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org> 7 * Copyright (c) 2004, 2005, 2008 Esben Norby <norby@openbsd.org> 8 * 9 * Permission to use, copy, modify, and distribute this software for any 10 * purpose with or without fee is hereby granted, provided that the above 11 * copyright notice and this permission notice appear in all copies. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 20 */ 21 22 #include <sys/types.h> 23 #include <sys/time.h> 24 #include <netinet/tcp.h> 25 #include <arpa/inet.h> 26 #include <errno.h> 27 #include <stdlib.h> 28 #include <string.h> 29 #include <unistd.h> 30 31 #include "ldpd.h" 32 #include "ldpe.h" 33 #include "lde.h" 34 #include "log.h" 35 36 static __inline int nbr_id_compare(struct nbr *, struct nbr *); 37 static __inline int nbr_addr_compare(struct nbr *, struct nbr *); 38 static __inline int nbr_pid_compare(struct nbr *, struct nbr *); 39 static void nbr_update_peerid(struct nbr *); 40 static void nbr_ktimer(int, short, void *); 41 static void nbr_start_ktimer(struct nbr *); 42 static void nbr_ktimeout(int, short, void *); 43 static void nbr_start_ktimeout(struct nbr *); 44 static void nbr_itimeout(int, short, void *); 45 static void nbr_start_itimeout(struct nbr *); 46 static void nbr_idtimer(int, short, void *); 47 static int nbr_act_session_operational(struct nbr *); 48 static void nbr_send_labelmappings(struct nbr *); 49 50 RB_GENERATE(nbr_id_head, nbr, id_tree, nbr_id_compare) 51 RB_GENERATE(nbr_addr_head, nbr, addr_tree, nbr_addr_compare) 52 RB_GENERATE(nbr_pid_head, nbr, pid_tree, nbr_pid_compare) 53 54 struct { 55 int state; 56 enum nbr_event event; 57 enum nbr_action action; 58 int new_state; 59 } nbr_fsm_tbl[] = { 60 /* current state event that happened action to take resulting state */ 61 /* Passive Role */ 62 {NBR_STA_PRESENT, NBR_EVT_MATCH_ADJ, NBR_ACT_NOTHING, NBR_STA_INITIAL}, 63 {NBR_STA_INITIAL, NBR_EVT_INIT_RCVD, NBR_ACT_PASSIVE_INIT, NBR_STA_OPENREC}, 64 {NBR_STA_OPENREC, NBR_EVT_KEEPALIVE_RCVD, NBR_ACT_SESSION_EST, NBR_STA_OPER}, 65 /* Active Role */ 66 {NBR_STA_PRESENT, NBR_EVT_CONNECT_UP, NBR_ACT_CONNECT_SETUP, NBR_STA_INITIAL}, 67 {NBR_STA_INITIAL, NBR_EVT_INIT_SENT, NBR_ACT_NOTHING, NBR_STA_OPENSENT}, 68 {NBR_STA_OPENSENT, NBR_EVT_INIT_RCVD, NBR_ACT_KEEPALIVE_SEND, NBR_STA_OPENREC}, 69 /* Session Maintenance */ 70 {NBR_STA_OPER, NBR_EVT_PDU_RCVD, NBR_ACT_RST_KTIMEOUT, 0}, 71 {NBR_STA_SESSION, NBR_EVT_PDU_RCVD, NBR_ACT_NOTHING, 0}, 72 {NBR_STA_OPER, NBR_EVT_PDU_SENT, NBR_ACT_RST_KTIMER, 0}, 73 {NBR_STA_SESSION, NBR_EVT_PDU_SENT, NBR_ACT_NOTHING, 0}, 74 /* Session Close */ 75 {NBR_STA_PRESENT, NBR_EVT_CLOSE_SESSION, NBR_ACT_NOTHING, 0}, 76 {NBR_STA_SESSION, NBR_EVT_CLOSE_SESSION, NBR_ACT_CLOSE_SESSION, NBR_STA_PRESENT}, 77 {-1, NBR_EVT_NOTHING, NBR_ACT_NOTHING, 0}, 78 }; 79 80 const char * const nbr_event_names[] = { 81 "NOTHING", 82 "ADJACENCY MATCHED", 83 "CONNECTION UP", 84 "SESSION CLOSE", 85 "INIT RECEIVED", 86 "KEEPALIVE RECEIVED", 87 "PDU RECEIVED", 88 "PDU SENT", 89 "INIT SENT" 90 }; 91 92 const char * const nbr_action_names[] = { 93 "NOTHING", 94 "RESET KEEPALIVE TIMEOUT", 95 "START NEIGHBOR SESSION", 96 "RESET KEEPALIVE TIMER", 97 "SETUP NEIGHBOR CONNECTION", 98 "SEND INIT AND KEEPALIVE", 99 "SEND KEEPALIVE", 100 "CLOSE SESSION" 101 }; 102 103 struct nbr_id_head nbrs_by_id = RB_INITIALIZER(&nbrs_by_id); 104 struct nbr_addr_head nbrs_by_addr = RB_INITIALIZER(&nbrs_by_addr); 105 struct nbr_pid_head nbrs_by_pid = RB_INITIALIZER(&nbrs_by_pid); 106 107 static __inline int 108 nbr_id_compare(struct nbr *a, struct nbr *b) 109 { 110 return (ntohl(a->id.s_addr) - ntohl(b->id.s_addr)); 111 } 112 113 static __inline int 114 nbr_addr_compare(struct nbr *a, struct nbr *b) 115 { 116 if (a->af < b->af) 117 return (-1); 118 if (a->af > b->af) 119 return (1); 120 121 return (ldp_addrcmp(a->af, &a->raddr, &b->raddr)); 122 } 123 124 static __inline int 125 nbr_pid_compare(struct nbr *a, struct nbr *b) 126 { 127 return (a->peerid - b->peerid); 128 } 129 130 int 131 nbr_fsm(struct nbr *nbr, enum nbr_event event) 132 { 133 struct timeval now; 134 int old_state; 135 int new_state = 0; 136 int i; 137 138 old_state = nbr->state; 139 for (i = 0; nbr_fsm_tbl[i].state != -1; i++) 140 if ((nbr_fsm_tbl[i].state & old_state) && 141 (nbr_fsm_tbl[i].event == event)) { 142 new_state = nbr_fsm_tbl[i].new_state; 143 break; 144 } 145 146 if (nbr_fsm_tbl[i].state == -1) { 147 /* event outside of the defined fsm, ignore it. */ 148 log_warnx("%s: lsr-id %s, event %s not expected in " 149 "state %s", __func__, inet_ntoa(nbr->id), 150 nbr_event_names[event], nbr_state_name(old_state)); 151 return (0); 152 } 153 154 if (new_state != 0) 155 nbr->state = new_state; 156 157 if (old_state != nbr->state) { 158 log_debug("%s: event %s resulted in action %s and " 159 "changing state for lsr-id %s from %s to %s", 160 __func__, nbr_event_names[event], 161 nbr_action_names[nbr_fsm_tbl[i].action], 162 inet_ntoa(nbr->id), nbr_state_name(old_state), 163 nbr_state_name(nbr->state)); 164 165 if (nbr->state == NBR_STA_OPER) { 166 gettimeofday(&now, NULL); 167 nbr->uptime = now.tv_sec; 168 } 169 } 170 171 if (nbr->state == NBR_STA_OPER || nbr->state == NBR_STA_PRESENT) 172 nbr_stop_itimeout(nbr); 173 else 174 nbr_start_itimeout(nbr); 175 176 switch (nbr_fsm_tbl[i].action) { 177 case NBR_ACT_RST_KTIMEOUT: 178 nbr_start_ktimeout(nbr); 179 break; 180 case NBR_ACT_RST_KTIMER: 181 nbr_start_ktimer(nbr); 182 break; 183 case NBR_ACT_SESSION_EST: 184 nbr_act_session_operational(nbr); 185 nbr_start_ktimer(nbr); 186 nbr_start_ktimeout(nbr); 187 if (nbr->v4_enabled) 188 send_address_all(nbr, AF_INET); 189 if (nbr->v6_enabled) 190 send_address_all(nbr, AF_INET6); 191 nbr_send_labelmappings(nbr); 192 break; 193 case NBR_ACT_CONNECT_SETUP: 194 nbr->tcp = tcp_new(nbr->fd, nbr); 195 196 /* trigger next state */ 197 send_init(nbr); 198 nbr_fsm(nbr, NBR_EVT_INIT_SENT); 199 break; 200 case NBR_ACT_PASSIVE_INIT: 201 send_init(nbr); 202 send_keepalive(nbr); 203 break; 204 case NBR_ACT_KEEPALIVE_SEND: 205 nbr_start_ktimeout(nbr); 206 send_keepalive(nbr); 207 break; 208 case NBR_ACT_CLOSE_SESSION: 209 ldpe_imsg_compose_lde(IMSG_NEIGHBOR_DOWN, nbr->peerid, 0, 210 NULL, 0); 211 session_close(nbr); 212 break; 213 case NBR_ACT_NOTHING: 214 /* do nothing */ 215 break; 216 } 217 218 return (0); 219 } 220 221 struct nbr * 222 nbr_new(struct in_addr id, int af, int ds_tlv, union ldpd_addr *addr, 223 uint32_t scope_id) 224 { 225 struct nbr *nbr; 226 struct nbr_params *nbrp; 227 struct adj *adj; 228 struct pending_conn *pconn; 229 230 log_debug("%s: lsr-id %s transport-address %s", __func__, 231 inet_ntoa(id), log_addr(af, addr)); 232 233 if ((nbr = calloc(1, sizeof(*nbr))) == NULL) 234 fatal(__func__); 235 236 LIST_INIT(&nbr->adj_list); 237 nbr->state = NBR_STA_PRESENT; 238 nbr->peerid = 0; 239 nbr->af = af; 240 nbr->ds_tlv = ds_tlv; 241 if (af == AF_INET || ds_tlv) 242 nbr->v4_enabled = 1; 243 if (af == AF_INET6 || ds_tlv) 244 nbr->v6_enabled = 1; 245 nbr->id = id; 246 nbr->laddr = (ldp_af_conf_get(leconf, af))->trans_addr; 247 nbr->raddr = *addr; 248 nbr->raddr_scope = scope_id; 249 nbr->conf_seqnum = 0; 250 251 LIST_FOREACH(adj, &global.adj_list, global_entry) { 252 if (adj->lsr_id.s_addr == nbr->id.s_addr) { 253 adj->nbr = nbr; 254 LIST_INSERT_HEAD(&nbr->adj_list, adj, nbr_entry); 255 } 256 } 257 258 if (RB_INSERT(nbr_id_head, &nbrs_by_id, nbr) != NULL) 259 fatalx("nbr_new: RB_INSERT(nbrs_by_id) failed"); 260 if (RB_INSERT(nbr_addr_head, &nbrs_by_addr, nbr) != NULL) 261 fatalx("nbr_new: RB_INSERT(nbrs_by_addr) failed"); 262 263 TAILQ_INIT(&nbr->mapping_list); 264 TAILQ_INIT(&nbr->withdraw_list); 265 TAILQ_INIT(&nbr->request_list); 266 TAILQ_INIT(&nbr->release_list); 267 TAILQ_INIT(&nbr->abortreq_list); 268 269 /* set event structures */ 270 evtimer_set(&nbr->keepalive_timeout, nbr_ktimeout, nbr); 271 evtimer_set(&nbr->keepalive_timer, nbr_ktimer, nbr); 272 evtimer_set(&nbr->init_timeout, nbr_itimeout, nbr); 273 evtimer_set(&nbr->initdelay_timer, nbr_idtimer, nbr); 274 275 nbrp = nbr_params_find(leconf, nbr->id); 276 if (nbrp && pfkey_establish(nbr, nbrp) == -1) 277 fatalx("pfkey setup failed"); 278 279 pconn = pending_conn_find(nbr->af, &nbr->raddr); 280 if (pconn) { 281 session_accept_nbr(nbr, pconn->fd); 282 pending_conn_del(pconn); 283 } 284 285 return (nbr); 286 } 287 288 void 289 nbr_del(struct nbr *nbr) 290 { 291 log_debug("%s: lsr-id %s", __func__, inet_ntoa(nbr->id)); 292 293 nbr_fsm(nbr, NBR_EVT_CLOSE_SESSION); 294 pfkey_remove(nbr); 295 296 if (nbr_pending_connect(nbr)) 297 event_del(&nbr->ev_connect); 298 nbr_stop_ktimer(nbr); 299 nbr_stop_ktimeout(nbr); 300 nbr_stop_itimeout(nbr); 301 nbr_stop_idtimer(nbr); 302 303 mapping_list_clr(&nbr->mapping_list); 304 mapping_list_clr(&nbr->withdraw_list); 305 mapping_list_clr(&nbr->request_list); 306 mapping_list_clr(&nbr->release_list); 307 mapping_list_clr(&nbr->abortreq_list); 308 309 if (nbr->peerid) 310 RB_REMOVE(nbr_pid_head, &nbrs_by_pid, nbr); 311 RB_REMOVE(nbr_id_head, &nbrs_by_id, nbr); 312 RB_REMOVE(nbr_addr_head, &nbrs_by_addr, nbr); 313 314 free(nbr); 315 } 316 317 static void 318 nbr_update_peerid(struct nbr *nbr) 319 { 320 static uint32_t peercnt = 1; 321 322 if (nbr->peerid) 323 RB_REMOVE(nbr_pid_head, &nbrs_by_pid, nbr); 324 325 /* get next unused peerid */ 326 while (nbr_find_peerid(++peercnt)) 327 ; 328 nbr->peerid = peercnt; 329 330 if (RB_INSERT(nbr_pid_head, &nbrs_by_pid, nbr) != NULL) 331 fatalx("nbr_update_peerid: RB_INSERT(nbrs_by_pid) failed"); 332 } 333 334 struct nbr * 335 nbr_find_ldpid(uint32_t lsr_id) 336 { 337 struct nbr n; 338 n.id.s_addr = lsr_id; 339 return (RB_FIND(nbr_id_head, &nbrs_by_id, &n)); 340 } 341 342 struct nbr * 343 nbr_find_addr(int af, union ldpd_addr *addr) 344 { 345 struct nbr n; 346 n.af = af; 347 n.raddr = *addr; 348 return (RB_FIND(nbr_addr_head, &nbrs_by_addr, &n)); 349 } 350 351 struct nbr * 352 nbr_find_peerid(uint32_t peerid) 353 { 354 struct nbr n; 355 n.peerid = peerid; 356 return (RB_FIND(nbr_pid_head, &nbrs_by_pid, &n)); 357 } 358 359 int 360 nbr_adj_count(struct nbr *nbr, int af) 361 { 362 struct adj *adj; 363 int total = 0; 364 365 LIST_FOREACH(adj, &nbr->adj_list, nbr_entry) 366 if (adj_get_af(adj) == af) 367 total++; 368 369 return (total); 370 } 371 372 int 373 nbr_session_active_role(struct nbr *nbr) 374 { 375 if (ldp_addrcmp(nbr->af, &nbr->laddr, &nbr->raddr) > 0) 376 return (1); 377 378 return (0); 379 } 380 381 /* timers */ 382 383 /* Keepalive timer: timer to send keepalive message to neighbors */ 384 385 static void 386 nbr_ktimer(int fd, short event, void *arg) 387 { 388 struct nbr *nbr = arg; 389 390 send_keepalive(nbr); 391 nbr_start_ktimer(nbr); 392 } 393 394 static void 395 nbr_start_ktimer(struct nbr *nbr) 396 { 397 struct timeval tv; 398 399 /* send three keepalives per period */ 400 timerclear(&tv); 401 tv.tv_sec = (time_t)(nbr->keepalive / KEEPALIVE_PER_PERIOD); 402 if (evtimer_add(&nbr->keepalive_timer, &tv) == -1) 403 fatal(__func__); 404 } 405 406 void 407 nbr_stop_ktimer(struct nbr *nbr) 408 { 409 if (evtimer_pending(&nbr->keepalive_timer, NULL) && 410 evtimer_del(&nbr->keepalive_timer) == -1) 411 fatal(__func__); 412 } 413 414 /* Keepalive timeout: if the nbr hasn't sent keepalive */ 415 416 static void 417 nbr_ktimeout(int fd, short event, void *arg) 418 { 419 struct nbr *nbr = arg; 420 421 log_debug("%s: lsr-id %s", __func__, inet_ntoa(nbr->id)); 422 423 session_shutdown(nbr, S_KEEPALIVE_TMR, 0, 0); 424 } 425 426 static void 427 nbr_start_ktimeout(struct nbr *nbr) 428 { 429 struct timeval tv; 430 431 timerclear(&tv); 432 tv.tv_sec = nbr->keepalive; 433 434 if (evtimer_add(&nbr->keepalive_timeout, &tv) == -1) 435 fatal(__func__); 436 } 437 438 void 439 nbr_stop_ktimeout(struct nbr *nbr) 440 { 441 if (evtimer_pending(&nbr->keepalive_timeout, NULL) && 442 evtimer_del(&nbr->keepalive_timeout) == -1) 443 fatal(__func__); 444 } 445 446 /* Session initialization timeout: if nbr got stuck in the initialization FSM */ 447 448 static void 449 nbr_itimeout(int fd, short event, void *arg) 450 { 451 struct nbr *nbr = arg; 452 453 log_debug("%s: lsr-id %s", __func__, inet_ntoa(nbr->id)); 454 455 nbr_fsm(nbr, NBR_EVT_CLOSE_SESSION); 456 } 457 458 static void 459 nbr_start_itimeout(struct nbr *nbr) 460 { 461 struct timeval tv; 462 463 timerclear(&tv); 464 tv.tv_sec = INIT_FSM_TIMEOUT; 465 if (evtimer_add(&nbr->init_timeout, &tv) == -1) 466 fatal(__func__); 467 } 468 469 void 470 nbr_stop_itimeout(struct nbr *nbr) 471 { 472 if (evtimer_pending(&nbr->init_timeout, NULL) && 473 evtimer_del(&nbr->init_timeout) == -1) 474 fatal(__func__); 475 } 476 477 /* Init delay timer: timer to retry to iniziatize session */ 478 479 static void 480 nbr_idtimer(int fd, short event, void *arg) 481 { 482 struct nbr *nbr = arg; 483 484 log_debug("%s: lsr-id %s", __func__, inet_ntoa(nbr->id)); 485 486 nbr_establish_connection(nbr); 487 } 488 489 void 490 nbr_start_idtimer(struct nbr *nbr) 491 { 492 struct timeval tv; 493 494 timerclear(&tv); 495 496 tv.tv_sec = INIT_DELAY_TMR; 497 switch(nbr->idtimer_cnt) { 498 default: 499 /* do not further increase the counter */ 500 tv.tv_sec = MAX_DELAY_TMR; 501 break; 502 case 2: 503 tv.tv_sec *= 2; 504 /* FALLTHROUGH */ 505 case 1: 506 tv.tv_sec *= 2; 507 /* FALLTHROUGH */ 508 case 0: 509 nbr->idtimer_cnt++; 510 break; 511 } 512 513 if (evtimer_add(&nbr->initdelay_timer, &tv) == -1) 514 fatal(__func__); 515 } 516 517 void 518 nbr_stop_idtimer(struct nbr *nbr) 519 { 520 if (evtimer_pending(&nbr->initdelay_timer, NULL) && 521 evtimer_del(&nbr->initdelay_timer) == -1) 522 fatal(__func__); 523 } 524 525 int 526 nbr_pending_idtimer(struct nbr *nbr) 527 { 528 if (evtimer_pending(&nbr->initdelay_timer, NULL)) 529 return (1); 530 531 return (0); 532 } 533 534 int 535 nbr_pending_connect(struct nbr *nbr) 536 { 537 if (event_initialized(&nbr->ev_connect) && 538 event_pending(&nbr->ev_connect, EV_WRITE, NULL)) 539 return (1); 540 541 return (0); 542 } 543 544 static void 545 nbr_connect_cb(int fd, short event, void *arg) 546 { 547 struct nbr *nbr = arg; 548 int error; 549 socklen_t len; 550 551 len = sizeof(error); 552 if (getsockopt(nbr->fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { 553 log_warn("%s: getsockopt SOL_SOCKET SO_ERROR", __func__); 554 return; 555 } 556 557 if (error) { 558 close(nbr->fd); 559 errno = error; 560 log_debug("%s: error while connecting to %s: %s", __func__, 561 log_addr(nbr->af, &nbr->raddr), strerror(errno)); 562 return; 563 } 564 565 nbr_fsm(nbr, NBR_EVT_CONNECT_UP); 566 } 567 568 int 569 nbr_establish_connection(struct nbr *nbr) 570 { 571 struct sockaddr_storage local_sa; 572 struct sockaddr_storage remote_sa; 573 struct adj *adj; 574 struct nbr_params *nbrp; 575 int opt = 1; 576 577 nbr->fd = socket(nbr->af, 578 SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0); 579 if (nbr->fd == -1) { 580 log_warn("%s: error while creating socket", __func__); 581 return (-1); 582 } 583 584 nbrp = nbr_params_find(leconf, nbr->id); 585 if (nbrp && nbrp->auth.method == AUTH_MD5SIG) { 586 if (sysdep.no_pfkey || sysdep.no_md5sig) { 587 log_warnx("md5sig configured but not available"); 588 close(nbr->fd); 589 return (-1); 590 } 591 if (setsockopt(nbr->fd, IPPROTO_TCP, TCP_MD5SIG, 592 &opt, sizeof(opt)) == -1) { 593 log_warn("setsockopt md5sig"); 594 close(nbr->fd); 595 return (-1); 596 } 597 } 598 599 memcpy(&local_sa, addr2sa(nbr->af, &nbr->laddr, 0), sizeof(local_sa)); 600 memcpy(&remote_sa, addr2sa(nbr->af, &nbr->raddr, LDP_PORT), 601 sizeof(local_sa)); 602 if (nbr->af == AF_INET6 && nbr->raddr_scope) 603 addscope((struct sockaddr_in6 *)&remote_sa, nbr->raddr_scope); 604 605 if (bind(nbr->fd, (struct sockaddr *)&local_sa, 606 local_sa.ss_len) == -1) { 607 log_warn("%s: error while binding socket to %s", __func__, 608 log_sockaddr((struct sockaddr *)&local_sa)); 609 close(nbr->fd); 610 return (-1); 611 } 612 613 if (nbr_gtsm_check(nbr->fd, nbr, nbrp)) { 614 close(nbr->fd); 615 return (-1); 616 } 617 618 /* 619 * Send an extra hello to guarantee that the remote peer has formed 620 * an adjacency as well. 621 */ 622 LIST_FOREACH(adj, &nbr->adj_list, nbr_entry) 623 send_hello(adj->source.type, adj->source.link.ia, 624 adj->source.target); 625 626 if (connect(nbr->fd, (struct sockaddr *)&remote_sa, 627 remote_sa.ss_len) == -1) { 628 if (errno == EINPROGRESS) { 629 event_set(&nbr->ev_connect, nbr->fd, EV_WRITE, 630 nbr_connect_cb, nbr); 631 event_add(&nbr->ev_connect, NULL); 632 return (0); 633 } 634 log_warn("%s: error while connecting to %s", __func__, 635 log_sockaddr((struct sockaddr *)&remote_sa)); 636 close(nbr->fd); 637 return (-1); 638 } 639 640 /* connection completed immediately */ 641 nbr_fsm(nbr, NBR_EVT_CONNECT_UP); 642 643 return (0); 644 } 645 646 int 647 nbr_gtsm_enabled(struct nbr *nbr, struct nbr_params *nbrp) 648 { 649 /* 650 * RFC 6720 - Section 3: 651 * "This document allows for the implementation to provide an option to 652 * statically (e.g., via configuration) and/or dynamically override the 653 * default behavior and enable/disable GTSM on a per-peer basis". 654 */ 655 if (nbrp && (nbrp->flags & F_NBRP_GTSM)) 656 return (nbrp->gtsm_enabled); 657 658 if ((ldp_af_conf_get(leconf, nbr->af))->flags & F_LDPD_AF_NO_GTSM) 659 return (0); 660 661 /* By default, GTSM support has to be negotiated for LDPv4 */ 662 if (nbr->af == AF_INET && !(nbr->flags & F_NBR_GTSM_NEGOTIATED)) 663 return (0); 664 665 return (1); 666 } 667 668 int 669 nbr_gtsm_setup(int fd, int af, struct nbr_params *nbrp) 670 { 671 int ttl = 255; 672 673 if (nbrp && (nbrp->flags & F_NBRP_GTSM_HOPS)) 674 ttl = 256 - nbrp->gtsm_hops; 675 676 switch (af) { 677 case AF_INET: 678 if (sock_set_ipv4_minttl(fd, ttl) == -1) 679 return (-1); 680 ttl = 255; 681 if (sock_set_ipv4_ucast_ttl(fd, ttl) == -1) 682 return (-1); 683 break; 684 case AF_INET6: 685 if (sock_set_ipv6_minhopcount(fd, ttl) == -1) 686 return (-1); 687 ttl = 255; 688 if (sock_set_ipv6_ucast_hops(fd, ttl) == -1) 689 return (-1); 690 break; 691 default: 692 fatalx("nbr_gtsm_setup: unknown af"); 693 } 694 695 return (0); 696 } 697 698 int 699 nbr_gtsm_check(int fd, struct nbr *nbr, struct nbr_params *nbrp) 700 { 701 if (!nbr_gtsm_enabled(nbr, nbrp)) { 702 switch (nbr->af) { 703 case AF_INET: 704 sock_set_ipv4_ucast_ttl(fd, -1); 705 break; 706 case AF_INET6: 707 /* 708 * Send packets with a Hop Limit of 255 even when GSTM 709 * is disabled to guarantee interoperability. 710 */ 711 sock_set_ipv6_ucast_hops(fd, 255); 712 break; 713 default: 714 fatalx("nbr_gtsm_check: unknown af"); 715 break; 716 } 717 return (0); 718 } 719 720 if (nbr_gtsm_setup(fd, nbr->af, nbrp) == -1) { 721 log_warnx("%s: error enabling GTSM for lsr-id %s", __func__, 722 inet_ntoa(nbr->id)); 723 return (-1); 724 } 725 726 return (0); 727 } 728 729 static int 730 nbr_act_session_operational(struct nbr *nbr) 731 { 732 struct lde_nbr lde_nbr; 733 734 nbr->idtimer_cnt = 0; 735 736 /* this is necessary to avoid ipc synchronization issues */ 737 nbr_update_peerid(nbr); 738 739 memset(&lde_nbr, 0, sizeof(lde_nbr)); 740 lde_nbr.id = nbr->id; 741 lde_nbr.v4_enabled = nbr->v4_enabled; 742 lde_nbr.v6_enabled = nbr->v6_enabled; 743 return (ldpe_imsg_compose_lde(IMSG_NEIGHBOR_UP, nbr->peerid, 0, 744 &lde_nbr, sizeof(lde_nbr))); 745 } 746 747 static void 748 nbr_send_labelmappings(struct nbr *nbr) 749 { 750 ldpe_imsg_compose_lde(IMSG_LABEL_MAPPING_FULL, nbr->peerid, 0, 751 NULL, 0); 752 } 753 754 struct nbr_params * 755 nbr_params_new(struct in_addr lsr_id) 756 { 757 struct nbr_params *nbrp; 758 759 if ((nbrp = calloc(1, sizeof(*nbrp))) == NULL) 760 fatal(__func__); 761 762 nbrp->lsr_id = lsr_id; 763 nbrp->auth.method = AUTH_NONE; 764 765 return (nbrp); 766 } 767 768 struct nbr_params * 769 nbr_params_find(struct ldpd_conf *xconf, struct in_addr lsr_id) 770 { 771 struct nbr_params *nbrp; 772 773 LIST_FOREACH(nbrp, &xconf->nbrp_list, entry) 774 if (nbrp->lsr_id.s_addr == lsr_id.s_addr) 775 return (nbrp); 776 777 return (NULL); 778 } 779 780 uint16_t 781 nbr_get_keepalive(int af, struct in_addr lsr_id) 782 { 783 struct nbr_params *nbrp; 784 785 nbrp = nbr_params_find(leconf, lsr_id); 786 if (nbrp && (nbrp->flags & F_NBRP_KEEPALIVE)) 787 return (nbrp->keepalive); 788 789 return ((ldp_af_conf_get(leconf, af))->keepalive); 790 } 791 792 struct ctl_nbr * 793 nbr_to_ctl(struct nbr *nbr) 794 { 795 static struct ctl_nbr nctl; 796 struct timeval now; 797 798 nctl.af = nbr->af; 799 nctl.id = nbr->id; 800 nctl.laddr = nbr->laddr; 801 nctl.raddr = nbr->raddr; 802 nctl.nbr_state = nbr->state; 803 804 gettimeofday(&now, NULL); 805 if (nbr->state == NBR_STA_OPER) { 806 nctl.uptime = now.tv_sec - nbr->uptime; 807 } else 808 nctl.uptime = 0; 809 810 return (&nctl); 811 } 812 813 void 814 nbr_clear_ctl(struct ctl_nbr *nctl) 815 { 816 struct nbr *nbr; 817 818 RB_FOREACH(nbr, nbr_addr_head, &nbrs_by_addr) { 819 if (ldp_addrisset(nctl->af, &nctl->raddr) && 820 ldp_addrcmp(nctl->af, &nctl->raddr, &nbr->raddr)) 821 continue; 822 823 log_debug("%s: neighbor %s manually cleared", __func__, 824 log_addr(nbr->af, &nbr->raddr)); 825 session_shutdown(nbr, S_SHUTDOWN, 0, 0); 826 } 827 } 828