xref: /openbsd/usr.sbin/ldpd/packet.c (revision 5ff72af8)
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