1 /* $OpenBSD: packet.c,v 1.77 2024/11/21 13:29:28 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 buf_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
gen_ldp_hdr(struct ibuf * buf,uint16_t size)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
gen_msg_hdr(struct ibuf * buf,uint16_t type,uint16_t size)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
send_packet(int fd,int af,union ldpd_addr * dst,struct iface_af * ia,void * pkt,size_t len)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
disc_recv_packet(int fd,short event,void * bula)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 *
disc_find_iface(unsigned int ifindex,int af,union ldpd_addr * src,int multicast)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
session_accept(int fd,short event,void * bula)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
session_accept_nbr(struct nbr * nbr,int fd)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
session_read(int fd,short event,void * arg)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
session_write(int fd,short event,void * arg)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 (ibuf_write(fd, tcp->wbuf.wbuf) == -1)
602 if (nbr)
603 nbr_fsm(nbr, NBR_EVT_CLOSE_SESSION);
604
605 if (nbr == NULL && msgbuf_queuelen(tcp->wbuf.wbuf) == 0) {
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
session_shutdown(struct nbr * nbr,uint32_t status,uint32_t msg_id,uint32_t msg_type)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
session_close(struct nbr * nbr)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
session_get_pdu(struct buf_read * r,char ** b)654 session_get_pdu(struct buf_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 *
tcp_new(int fd,struct nbr * nbr)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 buf_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
tcp_close(struct tcp_conn * tcp)707 tcp_close(struct tcp_conn *tcp)
708 {
709 /* try to flush write buffer */
710 ibuf_write(tcp->fd, 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 *
pending_conn_new(int fd,int af,union ldpd_addr * addr)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
pending_conn_del(struct pending_conn * pconn)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 *
pending_conn_find(int af,union ldpd_addr * addr)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
pending_conn_timeout(int fd,short event,void * arg)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 ibuf_write(fd, tcp->wbuf.wbuf);
787
788 pending_conn_del(pconn);
789 }
790