xref: /openbsd/usr.sbin/ldpd/packet.c (revision 4ff910d1)
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
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 (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
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 ibuf_read * r,char ** b)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 *
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 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
tcp_close(struct tcp_conn * tcp)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 *
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 	msgbuf_write(&tcp->wbuf.wbuf);
787 
788 	pending_conn_del(pconn);
789 }
790