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