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