1 /* $OpenBSD: packet.c,v 1.72 2021/01/19 15:59:25 claudio 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) 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 <netinet/in.h> 23 #include <netinet/tcp.h> 24 #include <arpa/inet.h> 25 #include <net/if_dl.h> 26 #include <unistd.h> 27 #include <errno.h> 28 #include <stdlib.h> 29 #include <string.h> 30 31 #include "ldpd.h" 32 #include "ldpe.h" 33 #include "log.h" 34 35 static struct iface *disc_find_iface(unsigned int, int, 36 union ldpd_addr *, int); 37 static void session_read(int, short, void *); 38 static void session_write(int, short, void *); 39 static ssize_t session_get_pdu(struct ibuf_read *, char **); 40 static void tcp_close(struct tcp_conn *); 41 static struct pending_conn *pending_conn_new(int, int, union ldpd_addr *); 42 static void pending_conn_timeout(int, short, void *); 43 44 static u_int8_t *recv_buf; 45 46 int 47 gen_ldp_hdr(struct ibuf *buf, uint16_t size) 48 { 49 struct ldp_hdr ldp_hdr; 50 51 memset(&ldp_hdr, 0, sizeof(ldp_hdr)); 52 ldp_hdr.version = htons(LDP_VERSION); 53 /* exclude the 'Version' and 'PDU Length' fields from the total */ 54 ldp_hdr.length = htons(size - LDP_HDR_DEAD_LEN); 55 ldp_hdr.lsr_id = leconf->rtr_id.s_addr; 56 ldp_hdr.lspace_id = 0; 57 58 return (ibuf_add(buf, &ldp_hdr, LDP_HDR_SIZE)); 59 } 60 61 int 62 gen_msg_hdr(struct ibuf *buf, uint16_t type, uint16_t size) 63 { 64 static int msgcnt = 0; 65 struct ldp_msg msg; 66 67 memset(&msg, 0, sizeof(msg)); 68 msg.type = htons(type); 69 /* exclude the 'Type' and 'Length' fields from the total */ 70 msg.length = htons(size - LDP_MSG_DEAD_LEN); 71 msg.id = htonl(++msgcnt); 72 73 return (ibuf_add(buf, &msg, sizeof(msg))); 74 } 75 76 /* send packets */ 77 int 78 send_packet(int fd, int af, union ldpd_addr *dst, struct iface_af *ia, 79 void *pkt, size_t len) 80 { 81 struct sockaddr *sa; 82 83 switch (af) { 84 case AF_INET: 85 if (ia && IN_MULTICAST(ntohl(dst->v4.s_addr))) { 86 /* set outgoing interface for multicast traffic */ 87 if (sock_set_ipv4_mcast(ia->iface) == -1) { 88 log_debug("%s: error setting multicast " 89 "interface, %s", __func__, ia->iface->name); 90 return (-1); 91 } 92 } 93 break; 94 case AF_INET6: 95 if (ia && IN6_IS_ADDR_MULTICAST(&dst->v6)) { 96 /* set outgoing interface for multicast traffic */ 97 if (sock_set_ipv6_mcast(ia->iface) == -1) { 98 log_debug("%s: error setting multicast " 99 "interface, %s", __func__, ia->iface->name); 100 return (-1); 101 } 102 } 103 break; 104 default: 105 fatalx("send_packet: unknown af"); 106 } 107 108 sa = addr2sa(af, dst, LDP_PORT); 109 if (sendto(fd, pkt, len, 0, sa, sa->sa_len) == -1) { 110 log_warn("%s: error sending packet to %s", __func__, 111 log_sockaddr(sa)); 112 return (-1); 113 } 114 115 return (0); 116 } 117 118 /* Discovery functions */ 119 #define CMSG_MAXLEN max(sizeof(struct sockaddr_dl), sizeof(struct in6_pktinfo)) 120 void 121 disc_recv_packet(int fd, short event, void *bula) 122 { 123 union { 124 struct cmsghdr hdr; 125 char buf[CMSG_SPACE(CMSG_MAXLEN)]; 126 } cmsgbuf; 127 struct msghdr m; 128 struct sockaddr_storage from; 129 struct iovec iov; 130 char *buf; 131 struct cmsghdr *cmsg; 132 ssize_t r; 133 int multicast; 134 int af; 135 union ldpd_addr src; 136 unsigned int ifindex = 0; 137 struct iface *iface; 138 uint16_t len; 139 struct ldp_hdr ldp_hdr; 140 uint16_t pdu_len; 141 struct ldp_msg msg; 142 uint16_t msg_len; 143 struct in_addr lsr_id; 144 145 if (event != EV_READ) 146 return; 147 148 if (recv_buf == NULL) 149 if ((recv_buf = malloc(READ_BUF_SIZE)) == NULL) 150 fatal(__func__); 151 152 /* setup buffer */ 153 memset(&m, 0, sizeof(m)); 154 iov.iov_base = buf = recv_buf; 155 iov.iov_len = READ_BUF_SIZE; 156 m.msg_name = &from; 157 m.msg_namelen = sizeof(from); 158 m.msg_iov = &iov; 159 m.msg_iovlen = 1; 160 m.msg_control = &cmsgbuf.buf; 161 m.msg_controllen = sizeof(cmsgbuf.buf); 162 163 if ((r = recvmsg(fd, &m, 0)) == -1) { 164 if (errno != EAGAIN && errno != EINTR) 165 log_debug("%s: read error: %s", __func__, 166 strerror(errno)); 167 return; 168 } 169 170 multicast = (m.msg_flags & MSG_MCAST) ? 1 : 0; 171 sa2addr((struct sockaddr *)&from, &af, &src); 172 if (bad_addr(af, &src)) { 173 log_debug("%s: invalid source address: %s", __func__, 174 log_addr(af, &src)); 175 return; 176 } 177 178 for (cmsg = CMSG_FIRSTHDR(&m); cmsg != NULL; 179 cmsg = CMSG_NXTHDR(&m, cmsg)) { 180 if (af == AF_INET && cmsg->cmsg_level == IPPROTO_IP && 181 cmsg->cmsg_type == IP_RECVIF) { 182 ifindex = ((struct sockaddr_dl *) 183 CMSG_DATA(cmsg))->sdl_index; 184 break; 185 } 186 if (af == AF_INET6 && cmsg->cmsg_level == IPPROTO_IPV6 && 187 cmsg->cmsg_type == IPV6_PKTINFO) { 188 ifindex = ((struct in6_pktinfo *) 189 CMSG_DATA(cmsg))->ipi6_ifindex; 190 break; 191 } 192 } 193 194 /* find a matching interface */ 195 iface = disc_find_iface(ifindex, af, &src, multicast); 196 if (iface == NULL) 197 return; 198 199 /* check packet size */ 200 len = (uint16_t)r; 201 if (len < (LDP_HDR_SIZE + LDP_MSG_SIZE) || len > LDP_MAX_LEN) { 202 log_debug("%s: bad packet size, source %s", __func__, 203 log_addr(af, &src)); 204 return; 205 } 206 207 /* LDP header sanity checks */ 208 memcpy(&ldp_hdr, buf, sizeof(ldp_hdr)); 209 if (ntohs(ldp_hdr.version) != LDP_VERSION) { 210 log_debug("%s: invalid LDP version %d, source %s", __func__, 211 ntohs(ldp_hdr.version), log_addr(af, &src)); 212 return; 213 } 214 if (ntohs(ldp_hdr.lspace_id) != 0) { 215 log_debug("%s: invalid label space %u, source %s", __func__, 216 ntohs(ldp_hdr.lspace_id), log_addr(af, &src)); 217 return; 218 } 219 /* check "PDU Length" field */ 220 pdu_len = ntohs(ldp_hdr.length); 221 if ((pdu_len < (LDP_HDR_PDU_LEN + LDP_MSG_SIZE)) || 222 (pdu_len > (len - LDP_HDR_DEAD_LEN))) { 223 log_debug("%s: invalid LDP packet length %u, source %s", 224 __func__, ntohs(ldp_hdr.length), log_addr(af, &src)); 225 return; 226 } 227 buf += LDP_HDR_SIZE; 228 len -= LDP_HDR_SIZE; 229 230 lsr_id.s_addr = ldp_hdr.lsr_id; 231 232 /* 233 * For UDP, we process only the first message of each packet. This does 234 * not impose any restrictions since LDP uses UDP only for sending Hello 235 * packets. 236 */ 237 memcpy(&msg, buf, sizeof(msg)); 238 239 /* check "Message Length" field */ 240 msg_len = ntohs(msg.length); 241 if (msg_len < LDP_MSG_LEN || ((msg_len + LDP_MSG_DEAD_LEN) > pdu_len)) { 242 log_debug("%s: invalid LDP message length %u, source %s", 243 __func__, ntohs(msg.length), log_addr(af, &src)); 244 return; 245 } 246 buf += LDP_MSG_SIZE; 247 len -= LDP_MSG_SIZE; 248 249 /* switch LDP packet type */ 250 switch (ntohs(msg.type)) { 251 case MSG_TYPE_HELLO: 252 recv_hello(lsr_id, &msg, af, &src, iface, multicast, buf, len); 253 break; 254 default: 255 log_debug("%s: unknown LDP packet type, source %s", __func__, 256 log_addr(af, &src)); 257 } 258 } 259 260 static struct iface * 261 disc_find_iface(unsigned int ifindex, int af, union ldpd_addr *src, 262 int multicast) 263 { 264 struct iface *iface; 265 struct iface_af *ia; 266 struct if_addr *if_addr; 267 in_addr_t mask; 268 269 iface = if_lookup(leconf, ifindex); 270 if (iface == NULL) 271 return (NULL); 272 273 /* 274 * For unicast packets, we just need to make sure that the interface 275 * is enabled for the given address-family. 276 */ 277 if (!multicast) { 278 ia = iface_af_get(iface, af); 279 if (ia->enabled) 280 return (iface); 281 return (NULL); 282 } 283 284 switch (af) { 285 case AF_INET: 286 LIST_FOREACH(if_addr, &iface->addr_list, entry) { 287 if (if_addr->af != AF_INET) 288 continue; 289 290 switch (iface->type) { 291 case IF_TYPE_POINTOPOINT: 292 if (if_addr->dstbrd.v4.s_addr == src->v4.s_addr) 293 return (iface); 294 break; 295 default: 296 mask = prefixlen2mask(if_addr->prefixlen); 297 if ((if_addr->addr.v4.s_addr & mask) == 298 (src->v4.s_addr & mask)) 299 return (iface); 300 break; 301 } 302 } 303 break; 304 case AF_INET6: 305 if (IN6_IS_ADDR_LINKLOCAL(&src->v6)) 306 return (iface); 307 break; 308 default: 309 fatalx("disc_find_iface: unknown af"); 310 } 311 312 return (NULL); 313 } 314 315 void 316 session_accept(int fd, short event, void *bula) 317 { 318 struct sockaddr_storage src; 319 socklen_t len = sizeof(src); 320 int newfd; 321 int af; 322 union ldpd_addr addr; 323 struct nbr *nbr; 324 struct pending_conn *pconn; 325 326 if (!(event & EV_READ)) 327 return; 328 329 newfd = accept4(fd, (struct sockaddr *)&src, &len, 330 SOCK_NONBLOCK | SOCK_CLOEXEC); 331 if (newfd == -1) { 332 /* 333 * Pause accept if we are out of file descriptors, or 334 * libevent will haunt us here too. 335 */ 336 if (errno == ENFILE || errno == EMFILE) { 337 accept_pause(); 338 } else if (errno != EWOULDBLOCK && errno != EINTR && 339 errno != ECONNABORTED) 340 log_debug("%s: accept error: %s", __func__, 341 strerror(errno)); 342 return; 343 } 344 345 sa2addr((struct sockaddr *)&src, &af, &addr); 346 347 /* 348 * Since we don't support label spaces, we can identify this neighbor 349 * just by its source address. This way we don't need to wait for its 350 * Initialization message to know who we are talking to. 351 */ 352 nbr = nbr_find_addr(af, &addr); 353 if (nbr == NULL) { 354 /* 355 * According to RFC 5036, we would need to send a No Hello 356 * Error Notification message and close this TCP connection 357 * right now. But doing so would trigger the backoff exponential 358 * timer in the remote peer, which would considerably slow down 359 * the session establishment process. The trick here is to wait 360 * five seconds before sending the Notification Message. There's 361 * a good chance that the remote peer will send us a Hello 362 * message within this interval, so it's worth waiting before 363 * taking a more drastic measure. 364 */ 365 pconn = pending_conn_find(af, &addr); 366 if (pconn) 367 close(newfd); 368 else 369 pending_conn_new(newfd, af, &addr); 370 return; 371 } 372 /* protection against buggy implementations */ 373 if (nbr_session_active_role(nbr)) { 374 close(newfd); 375 return; 376 } 377 if (nbr->state != NBR_STA_PRESENT) { 378 log_debug("%s: lsr-id %s: rejecting additional transport " 379 "connection", __func__, inet_ntoa(nbr->id)); 380 close(newfd); 381 return; 382 } 383 384 session_accept_nbr(nbr, newfd); 385 } 386 387 void 388 session_accept_nbr(struct nbr *nbr, int fd) 389 { 390 struct nbr_params *nbrp; 391 int opt; 392 socklen_t len; 393 394 nbrp = nbr_params_find(leconf, nbr->id); 395 if (nbr_gtsm_check(fd, nbr, nbrp)) { 396 close(fd); 397 return; 398 } 399 400 if (!LIST_EMPTY(&leconf->auth_list)) { 401 if (sysdep.no_pfkey || sysdep.no_md5sig) { 402 log_warnx("md5sig configured but not available"); 403 close(fd); 404 return; 405 } 406 407 len = sizeof(opt); 408 if (getsockopt(fd, IPPROTO_TCP, TCP_MD5SIG, &opt, &len) == -1) 409 fatal("getsockopt TCP_MD5SIG"); 410 if (!opt) { /* non-md5'd connection! */ 411 log_warnx("connection attempt without md5 signature"); 412 close(fd); 413 return; 414 } 415 } 416 417 nbr->tcp = tcp_new(fd, nbr); 418 nbr_fsm(nbr, NBR_EVT_MATCH_ADJ); 419 } 420 421 static void 422 session_read(int fd, short event, void *arg) 423 { 424 struct nbr *nbr = arg; 425 struct tcp_conn *tcp = nbr->tcp; 426 struct ldp_hdr *ldp_hdr; 427 struct ldp_msg *msg; 428 char *buf, *pdu; 429 ssize_t n, len; 430 uint16_t pdu_len, msg_len, msg_size, max_pdu_len; 431 int ret; 432 433 if (event != EV_READ) 434 return; 435 436 if ((n = read(fd, tcp->rbuf->buf + tcp->rbuf->wpos, 437 sizeof(tcp->rbuf->buf) - tcp->rbuf->wpos)) == -1) { 438 if (errno != EINTR && errno != EAGAIN) { 439 log_warn("%s: read error", __func__); 440 nbr_fsm(nbr, NBR_EVT_CLOSE_SESSION); 441 return; 442 } 443 /* retry read */ 444 return; 445 } 446 if (n == 0) { 447 /* connection closed */ 448 log_debug("%s: connection closed by remote end", __func__); 449 nbr_fsm(nbr, NBR_EVT_CLOSE_SESSION); 450 return; 451 } 452 tcp->rbuf->wpos += n; 453 454 while ((len = session_get_pdu(tcp->rbuf, &buf)) > 0) { 455 pdu = buf; 456 ldp_hdr = (struct ldp_hdr *)pdu; 457 if (ntohs(ldp_hdr->version) != LDP_VERSION) { 458 session_shutdown(nbr, S_BAD_PROTO_VER, 0, 0); 459 free(buf); 460 return; 461 } 462 463 pdu_len = ntohs(ldp_hdr->length); 464 /* 465 * RFC 5036 - Section 3.5.3: 466 * "Prior to completion of the negotiation, the maximum 467 * allowable length is 4096 bytes". 468 */ 469 if (nbr->state == NBR_STA_OPER) 470 max_pdu_len = nbr->max_pdu_len; 471 else 472 max_pdu_len = LDP_MAX_LEN; 473 if (pdu_len < (LDP_HDR_PDU_LEN + LDP_MSG_SIZE) || 474 pdu_len > max_pdu_len) { 475 session_shutdown(nbr, S_BAD_PDU_LEN, 0, 0); 476 free(buf); 477 return; 478 } 479 pdu_len -= LDP_HDR_PDU_LEN; 480 if (ldp_hdr->lsr_id != nbr->id.s_addr || 481 ldp_hdr->lspace_id != 0) { 482 session_shutdown(nbr, S_BAD_LDP_ID, 0, 0); 483 free(buf); 484 return; 485 } 486 pdu += LDP_HDR_SIZE; 487 len -= LDP_HDR_SIZE; 488 489 nbr_fsm(nbr, NBR_EVT_PDU_RCVD); 490 491 while (len >= LDP_MSG_SIZE) { 492 uint16_t type; 493 494 msg = (struct ldp_msg *)pdu; 495 type = ntohs(msg->type); 496 msg_len = ntohs(msg->length); 497 if (msg_len < LDP_MSG_LEN || 498 (msg_len + LDP_MSG_DEAD_LEN) > pdu_len) { 499 session_shutdown(nbr, S_BAD_TLV_LEN, msg->id, 500 msg->type); 501 free(buf); 502 return; 503 } 504 msg_size = msg_len + LDP_MSG_DEAD_LEN; 505 pdu_len -= msg_size; 506 507 /* check for error conditions earlier */ 508 switch (type) { 509 case MSG_TYPE_INIT: 510 if ((nbr->state != NBR_STA_INITIAL) && 511 (nbr->state != NBR_STA_OPENSENT)) { 512 session_shutdown(nbr, S_SHUTDOWN, 513 msg->id, msg->type); 514 free(buf); 515 return; 516 } 517 break; 518 case MSG_TYPE_KEEPALIVE: 519 if ((nbr->state == NBR_STA_INITIAL) || 520 (nbr->state == NBR_STA_OPENSENT)) { 521 session_shutdown(nbr, S_SHUTDOWN, 522 msg->id, msg->type); 523 free(buf); 524 return; 525 } 526 break; 527 default: 528 if (nbr->state != NBR_STA_OPER) { 529 session_shutdown(nbr, S_SHUTDOWN, 530 msg->id, msg->type); 531 free(buf); 532 return; 533 } 534 break; 535 } 536 537 /* switch LDP packet type */ 538 switch (type) { 539 case MSG_TYPE_NOTIFICATION: 540 ret = recv_notification(nbr, pdu, msg_size); 541 break; 542 case MSG_TYPE_INIT: 543 ret = recv_init(nbr, pdu, msg_size); 544 break; 545 case MSG_TYPE_KEEPALIVE: 546 ret = recv_keepalive(nbr, pdu, msg_size); 547 break; 548 case MSG_TYPE_CAPABILITY: 549 ret = recv_capability(nbr, pdu, msg_size); 550 break; 551 case MSG_TYPE_ADDR: 552 case MSG_TYPE_ADDRWITHDRAW: 553 ret = recv_address(nbr, pdu, msg_size); 554 break; 555 case MSG_TYPE_LABELMAPPING: 556 case MSG_TYPE_LABELREQUEST: 557 case MSG_TYPE_LABELWITHDRAW: 558 case MSG_TYPE_LABELRELEASE: 559 case MSG_TYPE_LABELABORTREQ: 560 ret = recv_labelmessage(nbr, pdu, msg_size, 561 type); 562 break; 563 default: 564 log_debug("%s: unknown LDP message from nbr %s", 565 __func__, inet_ntoa(nbr->id)); 566 if (!(ntohs(msg->type) & UNKNOWN_FLAG)) 567 send_notification(nbr->tcp, 568 S_UNKNOWN_MSG, msg->id, msg->type); 569 /* ignore the message */ 570 ret = 0; 571 break; 572 } 573 574 if (ret == -1) { 575 /* parser failed, giving up */ 576 free(buf); 577 return; 578 } 579 580 /* Analyse the next message */ 581 pdu += msg_size; 582 len -= msg_size; 583 } 584 free(buf); 585 if (len != 0) { 586 session_shutdown(nbr, S_BAD_PDU_LEN, 0, 0); 587 return; 588 } 589 } 590 } 591 592 static void 593 session_write(int fd, short event, void *arg) 594 { 595 struct tcp_conn *tcp = arg; 596 struct nbr *nbr = tcp->nbr; 597 598 if (!(event & EV_WRITE)) 599 return; 600 601 if (msgbuf_write(&tcp->wbuf.wbuf) <= 0) 602 if (errno != EAGAIN && nbr) 603 nbr_fsm(nbr, NBR_EVT_CLOSE_SESSION); 604 605 if (nbr == NULL && !tcp->wbuf.wbuf.queued) { 606 /* 607 * We are done sending the notification message, now we can 608 * close the socket. 609 */ 610 tcp_close(tcp); 611 return; 612 } 613 614 evbuf_event_add(&tcp->wbuf); 615 } 616 617 void 618 session_shutdown(struct nbr *nbr, uint32_t status, uint32_t msg_id, 619 uint32_t msg_type) 620 { 621 switch (nbr->state) { 622 case NBR_STA_PRESENT: 623 if (nbr_pending_connect(nbr)) 624 event_del(&nbr->ev_connect); 625 break; 626 case NBR_STA_INITIAL: 627 case NBR_STA_OPENREC: 628 case NBR_STA_OPENSENT: 629 case NBR_STA_OPER: 630 log_debug("%s: lsr-id %s", __func__, inet_ntoa(nbr->id)); 631 632 send_notification(nbr->tcp, status, msg_id, msg_type); 633 634 nbr_fsm(nbr, NBR_EVT_CLOSE_SESSION); 635 break; 636 default: 637 fatalx("session_shutdown: unknown neighbor state"); 638 } 639 } 640 641 void 642 session_close(struct nbr *nbr) 643 { 644 log_debug("%s: closing session with lsr-id %s", __func__, 645 inet_ntoa(nbr->id)); 646 647 tcp_close(nbr->tcp); 648 nbr_stop_ktimer(nbr); 649 nbr_stop_ktimeout(nbr); 650 nbr_stop_itimeout(nbr); 651 } 652 653 static ssize_t 654 session_get_pdu(struct ibuf_read *r, char **b) 655 { 656 struct ldp_hdr l; 657 size_t av, dlen, left; 658 659 av = r->wpos; 660 if (av < sizeof(l)) 661 return (0); 662 663 memcpy(&l, r->buf, sizeof(l)); 664 dlen = ntohs(l.length) + LDP_HDR_DEAD_LEN; 665 if (dlen > av) 666 return (0); 667 668 if ((*b = malloc(dlen)) == NULL) 669 return (-1); 670 671 memcpy(*b, r->buf, dlen); 672 if (dlen < av) { 673 left = av - dlen; 674 memmove(r->buf, r->buf + dlen, left); 675 r->wpos = left; 676 } else 677 r->wpos = 0; 678 679 return (dlen); 680 } 681 682 struct tcp_conn * 683 tcp_new(int fd, struct nbr *nbr) 684 { 685 struct tcp_conn *tcp; 686 687 if ((tcp = calloc(1, sizeof(*tcp))) == NULL) 688 fatal(__func__); 689 690 tcp->fd = fd; 691 evbuf_init(&tcp->wbuf, tcp->fd, session_write, tcp); 692 693 if (nbr) { 694 if ((tcp->rbuf = calloc(1, sizeof(struct ibuf_read))) == NULL) 695 fatal(__func__); 696 697 event_set(&tcp->rev, tcp->fd, EV_READ | EV_PERSIST, 698 session_read, nbr); 699 event_add(&tcp->rev, NULL); 700 tcp->nbr = nbr; 701 } 702 703 return (tcp); 704 } 705 706 static void 707 tcp_close(struct tcp_conn *tcp) 708 { 709 /* try to flush write buffer */ 710 msgbuf_write(&tcp->wbuf.wbuf); 711 evbuf_clear(&tcp->wbuf); 712 713 if (tcp->nbr) { 714 event_del(&tcp->rev); 715 free(tcp->rbuf); 716 tcp->nbr->tcp = NULL; 717 } 718 719 close(tcp->fd); 720 accept_unpause(); 721 free(tcp); 722 } 723 724 static struct pending_conn * 725 pending_conn_new(int fd, int af, union ldpd_addr *addr) 726 { 727 struct pending_conn *pconn; 728 struct timeval tv; 729 730 if ((pconn = calloc(1, sizeof(*pconn))) == NULL) 731 fatal(__func__); 732 733 pconn->fd = fd; 734 pconn->af = af; 735 pconn->addr = *addr; 736 evtimer_set(&pconn->ev_timeout, pending_conn_timeout, pconn); 737 TAILQ_INSERT_TAIL(&global.pending_conns, pconn, entry); 738 739 timerclear(&tv); 740 tv.tv_sec = PENDING_CONN_TIMEOUT; 741 if (evtimer_add(&pconn->ev_timeout, &tv) == -1) 742 fatal(__func__); 743 744 return (pconn); 745 } 746 747 void 748 pending_conn_del(struct pending_conn *pconn) 749 { 750 if (evtimer_pending(&pconn->ev_timeout, NULL) && 751 evtimer_del(&pconn->ev_timeout) == -1) 752 fatal(__func__); 753 754 TAILQ_REMOVE(&global.pending_conns, pconn, entry); 755 free(pconn); 756 } 757 758 struct pending_conn * 759 pending_conn_find(int af, union ldpd_addr *addr) 760 { 761 struct pending_conn *pconn; 762 763 TAILQ_FOREACH(pconn, &global.pending_conns, entry) 764 if (af == pconn->af && 765 ldp_addrcmp(af, addr, &pconn->addr) == 0) 766 return (pconn); 767 768 return (NULL); 769 } 770 771 static void 772 pending_conn_timeout(int fd, short event, void *arg) 773 { 774 struct pending_conn *pconn = arg; 775 struct tcp_conn *tcp; 776 777 log_debug("%s: no adjacency with remote end: %s", __func__, 778 log_addr(pconn->af, &pconn->addr)); 779 780 /* 781 * Create a write buffer detached from any neighbor to send a 782 * notification message reliably. 783 */ 784 tcp = tcp_new(pconn->fd, NULL); 785 send_notification(tcp, S_NO_HELLO, 0, 0); 786 msgbuf_write(&tcp->wbuf.wbuf); 787 788 pending_conn_del(pconn); 789 } 790