xref: /openbsd/usr.sbin/sasyncd/net.c (revision 898184e3)
1 /*	$OpenBSD: net.c,v 1.20 2013/03/11 17:40:11 deraadt Exp $	*/
2 
3 /*
4  * Copyright (c) 2005 H�kan Olsson.  All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 /*
29  * This code was written under funding by Multicom Security AB.
30  */
31 
32 #include <sys/types.h>
33 #include <sys/socket.h>
34 #include <sys/time.h>
35 #include <netinet/in.h>
36 #include <arpa/inet.h>
37 #include <ifaddrs.h>
38 #include <netdb.h>
39 #include <signal.h>
40 
41 #include <openssl/aes.h>
42 #include <openssl/sha.h>
43 
44 #include <errno.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <unistd.h>
49 
50 #include "sasyncd.h"
51 #include "net.h"
52 
53 struct msg {
54 	u_int8_t	*buf;
55 	u_int32_t	 len;
56 	int		 refcnt;
57 };
58 
59 struct qmsg {
60 	SIMPLEQ_ENTRY(qmsg)	next;
61 	struct msg	*msg;
62 };
63 
64 int	*listeners;
65 AES_KEY	aes_key[2];
66 #define AES_IV_LEN	AES_BLOCK_SIZE
67 
68 /* We never send (or expect to receive) messages smaller/larger than this. */
69 #define MSG_MINLEN	12
70 #define MSG_MAXLEN	4096
71 
72 /* Local prototypes. */
73 static u_int8_t *net_read(struct syncpeer *, u_int32_t *, u_int32_t *);
74 static int	 net_set_sa(struct sockaddr *, char *, in_port_t);
75 static void	 net_check_peers(void *);
76 
77 /* Pretty-print a buffer. */
78 void
79 dump_buf(int lvl, u_int8_t *b, u_int32_t len, char *title)
80 {
81 	u_int32_t	i, off, blen;
82 	u_int8_t	*buf;
83 	const char	def[] = "Buffer:";
84 
85 	if (cfgstate.verboselevel < lvl)
86 		return;
87 
88 	blen = 2 * (len + len / 36) + 3 + (title ? strlen(title) : sizeof def);
89 	if (!(buf = (u_int8_t *)calloc(1, blen)))
90 		return;
91 
92 	snprintf(buf, blen, "%s\n ", title ? title : def);
93 	off = strlen(buf);
94 	for (i = 0; i < len; i++, off+=2) {
95 		snprintf(buf + off, blen - off, "%02x", b[i]);
96 		if ((i+1) % 36 == 0) {
97 			off += 2;
98 			snprintf(buf + off, blen - off, "\n ");
99 		}
100 	}
101 	log_msg(lvl, "%s", buf);
102 	free(buf);
103 }
104 
105 /* Add a listening socket. */
106 static int
107 net_add_listener(struct sockaddr *sa)
108 {
109 	char	host[NI_MAXHOST], port[NI_MAXSERV];
110 	int	r, s;
111 
112 	s = socket(sa->sa_family, SOCK_STREAM, 0);
113 	if (s < 0) {
114 		perror("net_add_listener: socket()");
115 		close(s);
116 		return -1;
117 	}
118 
119 	r = 1;
120 	if (setsockopt(s, SOL_SOCKET,
121 		cfgstate.listen_on ? SO_REUSEADDR : SO_REUSEPORT, (void *)&r,
122 		sizeof r)) {
123 		perror("net_add_listener: setsockopt()");
124 		close(s);
125 		return -1;
126 	}
127 
128 	if (bind(s, sa, sa->sa_family == AF_INET ? sizeof(struct sockaddr_in) :
129 		sizeof (struct sockaddr_in6))) {
130 		perror("net_add_listener: bind()");
131 		close(s);
132 		return -1;
133 	}
134 
135 	if (listen(s, 3)) {
136 		perror("net_add_listener: listen()");
137 		close(s);
138 		return -1;
139 	}
140 
141 	if (getnameinfo(sa, sa->sa_len, host, sizeof host, port, sizeof port,
142 		NI_NUMERICHOST | NI_NUMERICSERV))
143 		log_msg(2, "listening on port %u fd %d", cfgstate.listen_port,
144 		    s);
145 	else
146 		log_msg(2, "listening on %s port %s fd %d", host, port, s);
147 
148 	return s;
149 }
150 
151 /* Allocate and fill in listeners array. */
152 static int
153 net_setup_listeners(void)
154 {
155 	struct sockaddr_storage	 sa_storage;
156 	struct sockaddr		*sa = (struct sockaddr *)&sa_storage;
157 	struct sockaddr_in	*sin = (struct sockaddr_in *)sa;
158 	struct sockaddr_in6	*sin6 = (struct sockaddr_in6 *)sa;
159 	struct ifaddrs		*ifap = 0, *ifa;
160 	int			 i, count;
161 
162 	/* Setup listening sockets.  */
163 	memset(&sa_storage, 0, sizeof sa_storage);
164 	if (net_set_sa(sa, cfgstate.listen_on, cfgstate.listen_port) == 0) {
165 		listeners = (int *)calloc(2, sizeof(int));
166 		if (!listeners) {
167 			perror("net_setup_listeners: calloc()");
168 			goto errout;
169 		}
170 		listeners[1] = -1;
171 		listeners[0] = net_add_listener(sa);
172 		if (listeners[0] == -1) {
173 			log_msg(0, "net_setup_listeners: could not find "
174 			    "listen address (%s)", cfgstate.listen_on);
175 			goto errout;
176 		}
177 		return 0;
178 	}
179 
180 	/*
181 	 * If net_set_sa() failed, cfgstate.listen_on is probably an
182 	 * interface name, so we should listen on all it's addresses.
183 	 */
184 
185 	if (getifaddrs(&ifap) != 0) {
186 		perror("net_setup_listeners: getifaddrs()");
187 		goto errout;
188 	}
189 
190 	/* How many addresses matches? */
191 	for (count = 0, ifa = ifap; ifa; ifa = ifa->ifa_next) {
192 		if (!ifa->ifa_name || !ifa->ifa_addr ||
193 		    (ifa->ifa_addr->sa_family != AF_INET &&
194 			ifa->ifa_addr->sa_family != AF_INET6))
195 			continue;
196 		if (cfgstate.listen_family &&
197 		    cfgstate.listen_family != ifa->ifa_addr->sa_family)
198 			continue;
199 		if (strcmp(ifa->ifa_name, cfgstate.listen_on) != 0)
200 			continue;
201 		count++;
202 	}
203 
204 	if (!count) {
205 		log_msg(0, "net_setup_listeners: no listeners found for %s",
206 		    cfgstate.listen_on);
207 		goto errout;
208 	}
209 
210 	/* Allocate one extra slot and set to -1, marking end of array. */
211 	listeners = (int *)calloc(count + 1, sizeof(int));
212 	if (!listeners) {
213 		perror("net_setup_listeners: calloc()");
214 		goto errout;
215 	}
216 	for (i = 0; i <= count; i++)
217 		listeners[i] = -1;
218 
219 	/* Create listening sockets */
220 	for (count = 0, ifa = ifap; ifa; ifa = ifa->ifa_next) {
221 		if (!ifa->ifa_name || !ifa->ifa_addr ||
222 		    (ifa->ifa_addr->sa_family != AF_INET &&
223 			ifa->ifa_addr->sa_family != AF_INET6))
224 			continue;
225 		if (cfgstate.listen_family &&
226 		    cfgstate.listen_family != ifa->ifa_addr->sa_family)
227 			continue;
228 		if (strcmp(ifa->ifa_name, cfgstate.listen_on) != 0)
229 			continue;
230 
231 		memset(&sa_storage, 0, sizeof sa_storage);
232 		sa->sa_family = ifa->ifa_addr->sa_family;
233 		switch (sa->sa_family) {
234 		case AF_INET:
235 			sin->sin_port = htons(cfgstate.listen_port);
236 			sin->sin_len = sizeof *sin;
237 			memcpy(&sin->sin_addr,
238 			    &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr,
239 			    sizeof sin->sin_addr);
240 			break;
241 		case AF_INET6:
242 			sin6->sin6_port = htons(cfgstate.listen_port);
243 			sin6->sin6_len = sizeof *sin6;
244 			memcpy(&sin6->sin6_addr,
245 			    &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr,
246 			    sizeof sin6->sin6_addr);
247 			break;
248 		}
249 
250 		listeners[count] = net_add_listener(sa);
251 		if (listeners[count] == -1) {
252 			log_msg(2, "net_setup_listeners(setup): failed to "
253 			    "add listener, count = %d", count);
254 			goto errout;
255 		}
256 		count++;
257 	}
258 	freeifaddrs(ifap);
259 	return 0;
260 
261   errout:
262 	if (ifap)
263 		freeifaddrs(ifap);
264 	if (listeners) {
265 		for (i = 0; listeners[i] != -1; i++)
266 			close(listeners[i]);
267 		free(listeners);
268 	}
269 	return -1;
270 }
271 
272 int
273 net_init(void)
274 {
275 	struct syncpeer *p;
276 
277 	if (AES_set_encrypt_key(cfgstate.sharedkey, cfgstate.sharedkey_len,
278 	    &aes_key[0]) ||
279 	    AES_set_decrypt_key(cfgstate.sharedkey, cfgstate.sharedkey_len,
280 	    &aes_key[1])) {
281 		fprintf(stderr, "Bad AES shared key\n");
282 		return -1;
283 	}
284 
285 	if (net_setup_listeners())
286 		return -1;
287 
288 	for (p = LIST_FIRST(&cfgstate.peerlist); p; p = LIST_NEXT(p, link)) {
289 		p->socket = -1;
290 		SIMPLEQ_INIT(&p->msgs);
291 	}
292 
293 	net_check_peers(0);
294 	return 0;
295 }
296 
297 static void
298 net_enqueue(struct syncpeer *p, struct msg *m)
299 {
300 	struct qmsg	*qm;
301 
302 	if (p->socket < 0)
303 		return;
304 
305 	qm = (struct qmsg *)malloc(sizeof *qm);
306 	if (!qm) {
307 		log_err("net_enqueue: malloc()");
308 		return;
309 	}
310 
311 	memset(qm, 0, sizeof *qm);
312 	qm->msg = m;
313 	m->refcnt++;
314 
315 	SIMPLEQ_INSERT_TAIL(&p->msgs, qm, next);
316 	return;
317 }
318 
319 /*
320  * Queue a message for transmission to a particular peer,
321  * or to all peers if no peer is specified.
322  */
323 int
324 net_queue(struct syncpeer *p0, u_int32_t msgtype, u_int8_t *buf, u_int32_t len)
325 {
326 	struct syncpeer *p = p0;
327 	struct msg	*m;
328 	SHA_CTX		 ctx;
329 	u_int8_t	 hash[SHA_DIGEST_LENGTH];
330 	u_int8_t	 iv[AES_IV_LEN], tmp_iv[AES_IV_LEN];
331 	u_int32_t	 v, padlen = 0;
332 	int		 i, offset;
333 
334 	m = (struct msg *)calloc(1, sizeof *m);
335 	if (!m) {
336 		log_err("net_queue: calloc()");
337 		free(buf);
338 		return -1;
339 	}
340 
341 	/* Generate hash */
342 	SHA1_Init(&ctx);
343 	SHA1_Update(&ctx, buf, len);
344 	SHA1_Final(hash, &ctx);
345 	dump_buf(2, hash, sizeof hash, "net_queue: computed hash");
346 
347 	/* Padding required? */
348 	i = len % AES_IV_LEN;
349 	if (i) {
350 		u_int8_t *pbuf;
351 		i = AES_IV_LEN - i;
352 		pbuf = realloc(buf, len + i);
353 		if (!pbuf) {
354 			log_err("net_queue: realloc()");
355 			free(buf);
356 			free(m);
357 			return -1;
358 		}
359 		padlen = i;
360 		while (i > 0)
361 			pbuf[len++] = (u_int8_t)i--;
362 		buf = pbuf;
363 	}
364 
365 	/* Get random IV */
366 	for (i = 0; (size_t)i <= sizeof iv - sizeof v; i += sizeof v) {
367 		v = arc4random();
368 		memcpy(&iv[i], &v, sizeof v);
369 	}
370 	dump_buf(2, iv, sizeof iv, "net_queue: IV");
371 	memcpy(tmp_iv, iv, sizeof tmp_iv);
372 
373 	/* Encrypt */
374 	dump_buf(2, buf, len, "net_queue: pre encrypt");
375 	AES_cbc_encrypt(buf, buf, len, &aes_key[0], tmp_iv, AES_ENCRYPT);
376 	dump_buf(2, buf, len, "net_queue: post encrypt");
377 
378 	/* Allocate send buffer */
379 	m->len = len + sizeof iv + sizeof hash + 3 * sizeof(u_int32_t);
380 	m->buf = (u_int8_t *)malloc(m->len);
381 	if (!m->buf) {
382 		free(m);
383 		free(buf);
384 		log_err("net_queue: calloc()");
385 		return -1;
386 	}
387 	offset = 0;
388 
389 	/* Fill it (order must match parsing code in net_read()) */
390 	v = htonl(m->len - sizeof(u_int32_t));
391 	memcpy(m->buf + offset, &v, sizeof v);
392 	offset += sizeof v;
393 	v = htonl(msgtype);
394 	memcpy(m->buf + offset, &v, sizeof v);
395 	offset += sizeof v;
396 	v = htonl(padlen);
397 	memcpy(m->buf + offset, &v, sizeof v);
398 	offset += sizeof v;
399 	memcpy(m->buf + offset, hash, sizeof hash);
400 	offset += sizeof hash;
401 	memcpy(m->buf + offset, iv, sizeof iv);
402 	offset += sizeof iv;
403 	memcpy(m->buf + offset, buf, len);
404 	free(buf);
405 
406 	if (p)
407 		net_enqueue(p, m);
408 	else
409 		for (p = LIST_FIRST(&cfgstate.peerlist); p;
410 		     p = LIST_NEXT(p, link))
411 			net_enqueue(p, m);
412 
413 	if (!m->refcnt) {
414 		free(m->buf);
415 		free(m);
416 	}
417 
418 	return 0;
419 }
420 
421 /* Set all write pending filedescriptors. */
422 int
423 net_set_pending_wfds(fd_set *fds)
424 {
425 	struct syncpeer *p;
426 	int		max_fd = -1;
427 
428 	for (p = LIST_FIRST(&cfgstate.peerlist); p; p = LIST_NEXT(p, link))
429 		if (p->socket > -1 && SIMPLEQ_FIRST(&p->msgs)) {
430 			FD_SET(p->socket, fds);
431 			if (p->socket > max_fd)
432 				max_fd = p->socket;
433 		}
434 	return max_fd + 1;
435 }
436 
437 /*
438  * Set readable filedescriptors. They are basically the same as for write,
439  * plus the listening socket.
440  */
441 int
442 net_set_rfds(fd_set *fds)
443 {
444 	struct syncpeer *p;
445 	int		i, max_fd = -1;
446 
447 	for (p = LIST_FIRST(&cfgstate.peerlist); p; p = LIST_NEXT(p, link)) {
448 		if (p->socket > -1)
449 			FD_SET(p->socket, fds);
450 		if (p->socket > max_fd)
451 			max_fd = p->socket;
452 	}
453 	for (i = 0; listeners[i] != -1; i++) {
454 		FD_SET(listeners[i], fds);
455 		if (listeners[i] > max_fd)
456 			max_fd = listeners[i];
457 	}
458 	return max_fd + 1;
459 }
460 
461 static void
462 net_accept(int accept_socket)
463 {
464 	struct sockaddr_storage	 sa_storage, sa_storage2;
465 	struct sockaddr		*sa = (struct sockaddr *)&sa_storage;
466 	struct sockaddr		*sa2 = (struct sockaddr *)&sa_storage2;
467 	struct sockaddr_in	*sin, *sin2;
468 	struct sockaddr_in6	*sin6, *sin62;
469 	struct syncpeer		*p;
470 	socklen_t		 socklen;
471 	int			 s, found;
472 
473 	/* Accept a new incoming connection */
474 	socklen = sizeof sa_storage;
475 	memset(&sa_storage, 0, socklen);
476 	memset(&sa_storage2, 0, socklen);
477 	s = accept(accept_socket, sa, &socklen);
478 	if (s > -1) {
479 		/* Setup the syncpeer structure */
480 		found = 0;
481 		for (p = LIST_FIRST(&cfgstate.peerlist); p && !found;
482 		     p = LIST_NEXT(p, link)) {
483 
484 			/* Match? */
485 			if (net_set_sa(sa2, p->name, 0))
486 				continue;
487 			if (sa->sa_family != sa2->sa_family)
488 				continue;
489 			if (sa->sa_family == AF_INET) {
490 				sin = (struct sockaddr_in *)sa;
491 				sin2 = (struct sockaddr_in *)sa2;
492 				if (memcmp(&sin->sin_addr, &sin2->sin_addr,
493 					sizeof(struct in_addr)))
494 					continue;
495 			} else {
496 				sin6 = (struct sockaddr_in6 *)sa;
497 				sin62 = (struct sockaddr_in6 *)sa2;
498 				if (memcmp(&sin6->sin6_addr, &sin62->sin6_addr,
499 					sizeof(struct in6_addr)))
500 					continue;
501 			}
502 			/* Match! */
503 			found++;
504 			p->socket = s;
505 			log_msg(1, "net: peer \"%s\" connected", p->name);
506 			if (cfgstate.runstate == MASTER)
507 				timer_add("pfkey_snap", 2, pfkey_snapshot, p);
508 		}
509 		if (!found) {
510 			log_msg(1, "net: found no matching peer for accepted "
511 			    "socket, closing.");
512 			close(s);
513 		}
514 	} else if (errno != EWOULDBLOCK && errno != EINTR &&
515 	    errno != ECONNABORTED)
516 		log_err("net: accept()");
517 }
518 
519 void
520 net_handle_messages(fd_set *fds)
521 {
522 	struct syncpeer *p;
523 	u_int8_t	*msg;
524 	u_int32_t	 msgtype, msglen;
525 	int		 i;
526 
527 	for (i = 0; listeners[i] != -1; i++)
528 		if (FD_ISSET(listeners[i], fds))
529 			net_accept(listeners[i]);
530 
531 	for (p = LIST_FIRST(&cfgstate.peerlist); p; p = LIST_NEXT(p, link)) {
532 		if (p->socket < 0 || !FD_ISSET(p->socket, fds))
533 			continue;
534 		msg = net_read(p, &msgtype, &msglen);
535 		if (!msg)
536 			continue;
537 
538 		log_msg(2, "net_handle_messages: got msg type %u len %u from "
539 		    "peer %s", msgtype, msglen, p->name);
540 
541 		switch (msgtype) {
542 		case MSG_SYNCCTL:
543 			net_ctl_handle_msg(p, msg, msglen);
544 			free(msg);
545 			break;
546 
547 		case MSG_PFKEYDATA:
548 			if (p->runstate != MASTER ||
549 			    cfgstate.runstate == MASTER) {
550 				log_msg(1, "net: got PFKEY message from "
551 				    "non-MASTER peer");
552 				free(msg);
553 				if (cfgstate.runstate == MASTER)
554 					net_ctl_send_state(p);
555 				else
556 					net_ctl_send_error(p, 0);
557 			} else if (pfkey_queue_message(msg, msglen))
558 				free(msg);
559 			break;
560 
561 		default:
562 			log_msg(0, "net: got unknown message type %u len %u "
563 			    "from peer %s", msgtype, msglen, p->name);
564 			free(msg);
565 			net_ctl_send_error(p, 0);
566 		}
567 	}
568 }
569 
570 void
571 net_send_messages(fd_set *fds)
572 {
573 	struct syncpeer *p;
574 	struct qmsg	*qm;
575 	struct msg	*m;
576 	ssize_t		 r;
577 
578 	for (p = LIST_FIRST(&cfgstate.peerlist); p; p = LIST_NEXT(p, link)) {
579 		if (p->socket < 0 || !FD_ISSET(p->socket, fds))
580 			continue;
581 		qm = SIMPLEQ_FIRST(&p->msgs);
582 		if (!qm) {
583 			/* XXX Log */
584 			continue;
585 		}
586 		m = qm->msg;
587 
588 		log_msg(2, "net_send_messages: msg %p len %u ref %d "
589 		    "to peer %s", m, m->len, m->refcnt, p->name);
590 
591 		/* write message */
592 		r = write(p->socket, m->buf, m->len);
593 		if (r == -1) {
594 			net_disconnect_peer(p);
595 			log_msg(0, "net_send_messages: write() failed, "
596 			    "peer disconnected");
597 		} else if (r < (ssize_t)m->len) {
598 			/* retransmit later */
599 			continue;
600 		}
601 
602 		/* cleanup */
603 		SIMPLEQ_REMOVE_HEAD(&p->msgs, next);
604 		free(qm);
605 
606 		if (--m->refcnt < 1) {
607 			log_msg(2, "net_send_messages: freeing msg %p", m);
608 			free(m->buf);
609 			free(m);
610 		}
611 	}
612 	return;
613 }
614 
615 void
616 net_disconnect_peer(struct syncpeer *p)
617 {
618 	if (p->socket > -1) {
619 		log_msg(1, "net_disconnect_peer: peer \"%s\" removed",
620 		    p->name);
621 		close(p->socket);
622 	}
623 	p->socket = -1;
624 }
625 
626 void
627 net_shutdown(void)
628 {
629 	struct syncpeer *p;
630 	struct qmsg	*qm;
631 	struct msg	*m;
632 	int		 i;
633 
634 	while ((p = LIST_FIRST(&cfgstate.peerlist))) {
635 		while ((qm = SIMPLEQ_FIRST(&p->msgs))) {
636 			SIMPLEQ_REMOVE_HEAD(&p->msgs, next);
637 			m = qm->msg;
638 			if (--m->refcnt < 1) {
639 				free(m->buf);
640 				free(m);
641 			}
642 			free(qm);
643 		}
644 		net_disconnect_peer(p);
645 		if (p->sa)
646 			free(p->sa);
647 		if (p->name)
648 			free(p->name);
649 		LIST_REMOVE(p, link);
650 		cfgstate.peercnt--;
651 		free(p);
652 	}
653 
654 	if (listeners) {
655 		for (i = 0; listeners[i] != -1; i++)
656 			close(listeners[i]);
657 		free(listeners);
658 		listeners = 0;
659 	}
660 }
661 
662 /*
663  * Helper functions (local) below here.
664  */
665 
666 static u_int8_t *
667 net_read(struct syncpeer *p, u_int32_t *msgtype, u_int32_t *msglen)
668 {
669 	u_int8_t	*msg, *blob, *rhash, *iv, hash[SHA_DIGEST_LENGTH];
670 	u_int32_t	 v, blob_len, pos = 0;
671 	int		 padlen = 0, offset = 0;
672 	ssize_t 	 r;
673 	SHA_CTX		 ctx;
674 
675 	/* Read blob length */
676 	r = read(p->socket, &v, sizeof v);
677 	if (r != (ssize_t)sizeof v) {
678 		if (r < 1)
679 			net_disconnect_peer(p);
680 		return NULL;
681 	}
682 
683 	blob_len = ntohl(v);
684 	if (blob_len < sizeof hash + AES_IV_LEN + 2 * sizeof(u_int32_t))
685 		return NULL;
686 	*msglen = blob_len - sizeof hash - AES_IV_LEN - 2 * sizeof(u_int32_t);
687 	if (*msglen < MSG_MINLEN || *msglen > MSG_MAXLEN)
688 		return NULL;
689 
690 	/* Read message blob */
691 	blob = (u_int8_t *)malloc(blob_len);
692 	if (!blob) {
693 		log_err("net_read: malloc()");
694 		return NULL;
695 	}
696 
697 	while (blob_len > pos) {
698 		switch (r = read(p->socket, blob + pos, blob_len - pos)) {
699 		case -1:
700 			if (errno == EINTR || errno == EAGAIN)
701 				continue;
702                         /* FALLTHROUGH */
703 		case 0:
704 			net_disconnect_peer(p);
705 			free(blob);
706 			return NULL;
707                         /* NOTREACHED */
708 		default:
709 			pos += r;
710 		}
711 	}
712 
713 	offset = 0;
714 	memcpy(&v, blob + offset, sizeof v);
715 	*msgtype = ntohl(v);
716 	offset += sizeof v;
717 
718 	if (*msgtype > MSG_MAXTYPE) {
719 		free(blob);
720 		return NULL;
721 	}
722 
723 	memcpy(&v, blob + offset, sizeof v);
724 	padlen = ntohl(v);
725 	offset += sizeof v;
726 
727 	rhash = blob + offset;
728 	iv    = rhash + sizeof hash;
729 	msg = (u_int8_t *)malloc(*msglen);
730 	if (!msg) {
731 		free(blob);
732 		return NULL;
733 	}
734 	memcpy(msg, iv + AES_IV_LEN, *msglen);
735 
736 	dump_buf(2, rhash, sizeof hash, "net_read: got hash");
737 	dump_buf(2, iv, AES_IV_LEN, "net_read: got IV");
738 	dump_buf(2, msg, *msglen, "net_read: pre decrypt");
739 	AES_cbc_encrypt(msg, msg, *msglen, &aes_key[1], iv, AES_DECRYPT);
740 	dump_buf(2, msg, *msglen, "net_read: post decrypt");
741 	*msglen -= padlen;
742 
743 	SHA1_Init(&ctx);
744 	SHA1_Update(&ctx, msg, *msglen);
745 	SHA1_Final(hash, &ctx);
746 	dump_buf(2, hash, sizeof hash, "net_read: computed hash");
747 
748 	if (memcmp(hash, rhash, sizeof hash) != 0) {
749 		free(blob);
750 		free(msg);
751 		log_msg(0, "net_read: got bad message (typo in shared key?)");
752 		return NULL;
753 	}
754 	free(blob);
755 	return msg;
756 }
757 
758 static int
759 net_set_sa(struct sockaddr *sa, char *name, in_port_t port)
760 {
761 	struct sockaddr_in	*sin = (struct sockaddr_in *)sa;
762 	struct sockaddr_in6	*sin6 = (struct sockaddr_in6 *)sa;
763 
764 	if (!name) {
765 		/* XXX Assume IPv4 */
766 		sa->sa_family = AF_INET;
767 		sin->sin_port = htons(port);
768 		sin->sin_len = sizeof *sin;
769 		return 0;
770 	}
771 
772 	if (inet_pton(AF_INET, name, &sin->sin_addr) == 1) {
773 		sa->sa_family = AF_INET;
774 		sin->sin_port = htons(port);
775 		sin->sin_len = sizeof *sin;
776 		return 0;
777 	}
778 
779 	if (inet_pton(AF_INET6, name, &sin6->sin6_addr) == 1) {
780 		sa->sa_family = AF_INET6;
781 		sin6->sin6_port = htons(port);
782 		sin6->sin6_len = sizeof *sin6;
783 		return 0;
784 	}
785 
786 	return -1;
787 }
788 
789 static void
790 got_sigalrm(int s)
791 {
792 	return;
793 }
794 
795 void
796 net_connect(void)
797 {
798 	struct itimerval	iv;
799 	struct syncpeer		*p;
800 
801 	signal(SIGALRM, got_sigalrm);
802 	memset(&iv, 0, sizeof iv);
803 	iv.it_value.tv_sec = 5;
804 	iv.it_interval.tv_sec = 5;
805 	setitimer(ITIMER_REAL, &iv, NULL);
806 
807 	for (p = LIST_FIRST(&cfgstate.peerlist); p; p = LIST_NEXT(p, link)) {
808 		if (p->socket > -1)
809 			continue;
810 		if (!p->sa) {
811 			p->sa = (void *)calloc(1,
812 			    sizeof(struct sockaddr_storage));
813 			if (!p->sa)
814 				return;
815 			if (net_set_sa(p->sa, p->name, cfgstate.listen_port))
816 				continue;
817 		}
818 		p->socket = socket(p->sa->sa_family, SOCK_STREAM, 0);
819 		if (p->socket < 0) {
820 			log_err("peer \"%s\": socket()", p->name);
821 			continue;
822 		}
823 		if (connect(p->socket, p->sa, p->sa->sa_len)) {
824 			log_msg(1, "net_connect: peer \"%s\" not ready yet",
825 			    p->name);
826 			net_disconnect_peer(p);
827 			continue;
828 		}
829 		if (net_ctl_send_state(p)) {
830 			log_msg(0, "net_connect: peer \"%s\" failed", p->name);
831 			net_disconnect_peer(p);
832 			continue;
833 		}
834 		log_msg(1, "net_connect: peer \"%s\" connected, fd %d",
835 		    p->name, p->socket);
836 
837 		/* Schedule a pfkey sync to the newly connected peer. */
838 		if (cfgstate.runstate == MASTER)
839 			timer_add("pfkey_snapshot", 2, pfkey_snapshot, p);
840 	}
841 
842 	timerclear(&iv.it_value);
843 	timerclear(&iv.it_interval);
844 	setitimer(ITIMER_REAL, &iv, NULL);
845 	signal(SIGALRM, SIG_IGN);
846 
847 	return;
848 }
849 
850 static void
851 net_check_peers(void *arg)
852 {
853 	net_connect();
854 	(void)timer_add("peer recheck", 600, net_check_peers, 0);
855 }
856