net.c revision 1.20
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
53struct msg {
54	u_int8_t	*buf;
55	u_int32_t	 len;
56	int		 refcnt;
57};
58
59struct qmsg {
60	SIMPLEQ_ENTRY(qmsg)	next;
61	struct msg	*msg;
62};
63
64int	*listeners;
65AES_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. */
73static u_int8_t *net_read(struct syncpeer *, u_int32_t *, u_int32_t *);
74static int	 net_set_sa(struct sockaddr *, char *, in_port_t);
75static void	 net_check_peers(void *);
76
77/* Pretty-print a buffer. */
78void
79dump_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. */
106static int
107net_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. */
152static int
153net_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
272int
273net_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
297static void
298net_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 */
323int
324net_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. */
422int
423net_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 */
441int
442net_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
461static void
462net_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
519void
520net_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
570void
571net_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
615void
616net_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
626void
627net_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
666static u_int8_t *
667net_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
758static int
759net_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
789static void
790got_sigalrm(int s)
791{
792	return;
793}
794
795void
796net_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
850static void
851net_check_peers(void *arg)
852{
853	net_connect();
854	(void)timer_add("peer recheck", 600, net_check_peers, 0);
855}
856