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