1/*	$NetBSD: sockmisc.c,v 1.19 2011/03/14 17:18:13 tteras Exp $	*/
2
3/* Id: sockmisc.c,v 1.24 2006/05/07 21:32:59 manubsd Exp */
4
5/*
6 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the project nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#include "config.h"
35
36#include <sys/types.h>
37#include <sys/param.h>
38#include <sys/socket.h>
39#include <sys/uio.h>
40
41#include <netinet/in.h>
42#include PATH_IPSEC_H
43
44#if defined(INET6) && !defined(INET6_ADVAPI) && \
45	defined(IP_RECVDSTADDR) && !defined(IPV6_RECVDSTADDR)
46#define IPV6_RECVDSTADDR IP_RECVDSTADDR
47#endif
48
49#include <stdlib.h>
50#include <stdio.h>
51#include <string.h>
52#include <errno.h>
53#ifdef HAVE_UNISTD_H
54#include <unistd.h>
55#endif
56
57#include "var.h"
58#include "misc.h"
59#include "vmbuf.h"
60#include "plog.h"
61#include "sockmisc.h"
62#include "debug.h"
63#include "gcmalloc.h"
64#include "debugrm.h"
65#include "libpfkey.h"
66#include "isakmp_var.h"
67
68#ifdef NOUSE_PRIVSEP
69#define BIND bind
70#define SOCKET socket
71#define SETSOCKOPT setsockopt
72#else
73#include "admin.h"
74#include "privsep.h"
75#define BIND privsep_bind
76#define SOCKET privsep_socket
77#define SETSOCKOPT privsep_setsockopt
78#endif
79
80const int niflags = 0;
81
82/*
83 * compare two sockaddr with port, taking care wildcard.
84 * addr1 is a subject address, addr2 is in a database entry.
85 * OUT:	0: equal.
86 *	1: not equal.
87 */
88int
89cmpsaddr(addr1, addr2)
90	const struct sockaddr *addr1;
91	const struct sockaddr *addr2;
92{
93	caddr_t sa1, sa2;
94	u_short port1 = IPSEC_PORT_ANY;
95	u_short port2 = IPSEC_PORT_ANY;
96
97	if (addr1 == NULL && addr2 == NULL)
98		return CMPSADDR_MATCH;
99
100	if (addr1 == NULL || addr2 == NULL)
101		return CMPSADDR_MISMATCH;
102
103	if (addr1->sa_family != addr2->sa_family ||
104	    sysdep_sa_len(addr1) != sysdep_sa_len(addr2))
105		return CMPSADDR_MISMATCH;
106
107	switch (addr1->sa_family) {
108	case AF_UNSPEC:
109		break;
110	case AF_INET:
111		sa1 = (caddr_t)&((struct sockaddr_in *)addr1)->sin_addr;
112		sa2 = (caddr_t)&((struct sockaddr_in *)addr2)->sin_addr;
113		port1 = ((struct sockaddr_in *)addr1)->sin_port;
114		port2 = ((struct sockaddr_in *)addr2)->sin_port;
115		if (memcmp(sa1, sa2, sizeof(struct in_addr)) != 0)
116			return CMPSADDR_MISMATCH;
117		break;
118#ifdef INET6
119	case AF_INET6:
120		sa1 = (caddr_t)&((struct sockaddr_in6 *)addr1)->sin6_addr;
121		sa2 = (caddr_t)&((struct sockaddr_in6 *)addr2)->sin6_addr;
122		port1 = ((struct sockaddr_in6 *)addr1)->sin6_port;
123		port2 = ((struct sockaddr_in6 *)addr2)->sin6_port;
124		if (memcmp(sa1, sa2, sizeof(struct in6_addr)) != 0)
125			return CMPSADDR_MISMATCH;
126		if (((struct sockaddr_in6 *)addr1)->sin6_scope_id !=
127		    ((struct sockaddr_in6 *)addr2)->sin6_scope_id)
128			return CMPSADDR_MISMATCH;
129		break;
130#endif
131	default:
132		return CMPSADDR_MISMATCH;
133	}
134
135	if (port1 == port2)
136		return CMPSADDR_MATCH;
137
138	if (port1 == IPSEC_PORT_ANY ||
139	    port2 == IPSEC_PORT_ANY)
140		return CMPSADDR_WILDPORT_MATCH;
141
142	return CMPSADDR_WOP_MATCH;
143}
144
145/* get local address against the destination. */
146struct sockaddr *
147getlocaladdr(remote)
148	struct sockaddr *remote;
149{
150	struct sockaddr *local;
151	u_int local_len = sizeof(struct sockaddr_storage);
152	int s;	/* for dummy connection */
153
154	/* allocate buffer */
155	if ((local = racoon_calloc(1, local_len)) == NULL) {
156		plog(LLV_ERROR, LOCATION, NULL,
157			"failed to get address buffer.\n");
158		goto err;
159	}
160
161	/* get real interface received packet */
162	if ((s = SOCKET(remote->sa_family, SOCK_DGRAM, 0)) < 0) {
163		plog(LLV_ERROR, LOCATION, NULL,
164			"socket (%s)\n", strerror(errno));
165		goto err;
166	}
167
168	setsockopt_bypass(s, remote->sa_family);
169
170	if (connect(s, remote, sysdep_sa_len(remote)) < 0) {
171		plog(LLV_ERROR, LOCATION, NULL,
172			"connect (%s)\n", strerror(errno));
173		close(s);
174		goto err;
175	}
176
177	if (getsockname(s, local, &local_len) < 0) {
178		plog(LLV_ERROR, LOCATION, NULL,
179			"getsockname (%s)\n", strerror(errno));
180		close(s);
181		return NULL;
182	}
183
184	close(s);
185	return local;
186
187    err:
188	if (local != NULL)
189		racoon_free(local);
190	return NULL;
191}
192
193/*
194 * Receive packet, with src/dst information.  It is assumed that necessary
195 * setsockopt() have already performed on socket.
196 */
197int
198recvfromto(s, buf, buflen, flags, from, fromlen, to, tolen)
199	int s;
200	void *buf;
201	size_t buflen;
202	int flags;
203	struct sockaddr *from;
204	socklen_t *fromlen;
205	struct sockaddr *to;
206	u_int *tolen;
207{
208	int otolen;
209	socklen_t slen;
210	int len;
211	union sockaddr_any sa;
212	struct msghdr m;
213	struct cmsghdr *cm;
214	struct iovec iov[2];
215	u_char cmsgbuf[256];
216#if defined(INET6) && defined(INET6_ADVAPI)
217	struct in6_pktinfo *pi;
218#endif /*INET6_ADVAPI*/
219	struct sockaddr_in *sin;
220#ifdef INET6
221	struct sockaddr_in6 *sin6;
222#endif
223
224	slen = sizeof(sa);
225	if (getsockname(s, &sa.sa, &slen) < 0) {
226		plog(LLV_ERROR, LOCATION, NULL,
227			"getsockname (%s)\n", strerror(errno));
228		return -1;
229	}
230
231	m.msg_name = (caddr_t)from;
232	m.msg_namelen = *fromlen;
233	iov[0].iov_base = (caddr_t)buf;
234	iov[0].iov_len = buflen;
235	m.msg_iov = iov;
236	m.msg_iovlen = 1;
237	memset(cmsgbuf, 0, sizeof(cmsgbuf));
238	cm = (struct cmsghdr *)cmsgbuf;
239	m.msg_control = (caddr_t)cm;
240	m.msg_controllen = sizeof(cmsgbuf);
241	if ((len = recvmsg(s, &m, flags)) < 0) {
242		plog(LLV_ERROR, LOCATION, NULL,
243			"recvmsg (%s)\n", strerror(errno));
244		return -1;
245	}
246	*fromlen = m.msg_namelen;
247
248	otolen = *tolen;
249	*tolen = 0;
250	for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(&m);
251	     m.msg_controllen != 0 && cm;
252	     cm = (struct cmsghdr *)CMSG_NXTHDR(&m, cm)) {
253#if 0
254		plog(LLV_ERROR, LOCATION, NULL,
255			"cmsg %d %d\n", cm->cmsg_level, cm->cmsg_type);)
256#endif
257#if defined(INET6) && defined(INET6_ADVAPI)
258		if (sa.sa.sa_family == AF_INET6
259		 && cm->cmsg_level == IPPROTO_IPV6
260		 && cm->cmsg_type == IPV6_PKTINFO
261		 && otolen >= sizeof(*sin6)) {
262			pi = (struct in6_pktinfo *)(CMSG_DATA(cm));
263			*tolen = sizeof(*sin6);
264			sin6 = (struct sockaddr_in6 *)to;
265			memset(sin6, 0, sizeof(*sin6));
266			sin6->sin6_family = AF_INET6;
267#ifndef __linux__
268			sin6->sin6_len = sizeof(*sin6);
269#endif
270			memcpy(&sin6->sin6_addr, &pi->ipi6_addr,
271				sizeof(sin6->sin6_addr));
272			/* XXX other cases, such as site-local? */
273			if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
274				sin6->sin6_scope_id = pi->ipi6_ifindex;
275			else
276				sin6->sin6_scope_id = 0;
277			sin6->sin6_port = sa.sin6.sin6_port;
278			otolen = -1;	/* "to" already set */
279			continue;
280		}
281#endif
282#ifdef __linux__
283		if (sa.sa.sa_family == AF_INET
284		 && cm->cmsg_level == IPPROTO_IP
285		 && cm->cmsg_type == IP_PKTINFO
286		 && otolen >= sizeof(sin)) {
287			struct in_pktinfo *pi = (struct in_pktinfo *)(CMSG_DATA(cm));
288			*tolen = sizeof(*sin);
289			sin = (struct sockaddr_in *)to;
290			memset(sin, 0, sizeof(*sin));
291			sin->sin_family = AF_INET;
292			memcpy(&sin->sin_addr, &pi->ipi_addr,
293				sizeof(sin->sin_addr));
294			sin->sin_port = sa.sin.sin_port;
295			otolen = -1;	/* "to" already set */
296			continue;
297		}
298#endif
299#if defined(INET6) && defined(IPV6_RECVDSTADDR)
300		if (sa.sa.sa_family == AF_INET6
301		      && cm->cmsg_level == IPPROTO_IPV6
302		      && cm->cmsg_type == IPV6_RECVDSTADDR
303		      && otolen >= sizeof(*sin6)) {
304			*tolen = sizeof(*sin6);
305			sin6 = (struct sockaddr_in6 *)to;
306			memset(sin6, 0, sizeof(*sin6));
307			sin6->sin6_family = AF_INET6;
308			sin6->sin6_len = sizeof(*sin6);
309			memcpy(&sin6->sin6_addr, CMSG_DATA(cm),
310				sizeof(sin6->sin6_addr));
311			sin6->sin6_port = sa.sin6.sin6_port;
312			otolen = -1;	/* "to" already set */
313			continue;
314		}
315#endif
316#ifndef __linux__
317		if (sa.sa.sa_family == AF_INET
318		 && cm->cmsg_level == IPPROTO_IP
319		 && cm->cmsg_type == IP_RECVDSTADDR
320		 && otolen >= sizeof(*sin)) {
321			*tolen = sizeof(*sin);
322			sin = (struct sockaddr_in *)to;
323			memset(sin, 0, sizeof(*sin));
324			sin->sin_family = AF_INET;
325			sin->sin_len = sizeof(*sin);
326			memcpy(&sin->sin_addr, CMSG_DATA(cm),
327				sizeof(sin->sin_addr));
328			sin->sin_port = sa.sin.sin_port;
329			otolen = -1;	/* "to" already set */
330			continue;
331		}
332#endif
333	}
334
335	return len;
336}
337
338/* send packet, with fixing src/dst address pair. */
339int
340sendfromto(s, buf, buflen, src, dst, cnt)
341	int s, cnt;
342	const void *buf;
343	size_t buflen;
344	struct sockaddr *src;
345	struct sockaddr *dst;
346{
347	struct sockaddr_storage ss;
348	socklen_t slen;
349	int len = 0;
350	int i;
351
352	if (src->sa_family != dst->sa_family) {
353		plog(LLV_ERROR, LOCATION, NULL,
354			"address family mismatch\n");
355		return -1;
356	}
357
358	slen = sizeof(ss);
359	if (getsockname(s, (struct sockaddr *)&ss, &slen) < 0) {
360		plog(LLV_ERROR, LOCATION, NULL,
361			"getsockname (%s)\n", strerror(errno));
362		return -1;
363	}
364
365	plog(LLV_DEBUG, LOCATION, NULL,
366		"sockname %s\n", saddr2str((struct sockaddr *)&ss));
367	plog(LLV_DEBUG, LOCATION, NULL,
368		"send packet from %s\n", saddr2str(src));
369	plog(LLV_DEBUG, LOCATION, NULL,
370		"send packet to %s\n", saddr2str(dst));
371
372	if (src->sa_family != ss.ss_family) {
373		plog(LLV_ERROR, LOCATION, NULL,
374			"address family mismatch\n");
375		return -1;
376	}
377
378	switch (src->sa_family) {
379#if defined(INET6) && defined(INET6_ADVAPI)
380// XXX: This block wasn't compiled on Linux - does it work?
381	case AF_INET6:
382	    {
383		struct msghdr m;
384		struct cmsghdr *cm;
385		struct iovec iov[2];
386		u_char cmsgbuf[256];
387		struct in6_pktinfo *pi;
388		int ifindex;
389		struct sockaddr_in6 src6, dst6;
390
391		memcpy(&src6, src, sizeof(src6));
392		memcpy(&dst6, dst, sizeof(dst6));
393
394		/* XXX take care of other cases, such as site-local */
395		ifindex = 0;
396		if (IN6_IS_ADDR_LINKLOCAL(&src6.sin6_addr)
397		 || IN6_IS_ADDR_MULTICAST(&src6.sin6_addr)) {
398			ifindex = src6.sin6_scope_id;	/*???*/
399		}
400
401		/* XXX some sanity check on dst6.sin6_scope_id */
402
403		/* flowinfo for IKE?  mmm, maybe useful but for now make it 0 */
404		src6.sin6_flowinfo = dst6.sin6_flowinfo = 0;
405
406		memset(&m, 0, sizeof(m));
407		m.msg_name = (caddr_t)&dst6;
408		m.msg_namelen = sizeof(dst6);
409		iov[0].iov_base = (char *)buf;
410		iov[0].iov_len = buflen;
411		m.msg_iov = iov;
412		m.msg_iovlen = 1;
413
414		memset(cmsgbuf, 0, sizeof(cmsgbuf));
415		cm = (struct cmsghdr *)cmsgbuf;
416		m.msg_control = (caddr_t)cm;
417		m.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
418
419		cm->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
420		cm->cmsg_level = IPPROTO_IPV6;
421		cm->cmsg_type = IPV6_PKTINFO;
422		pi = (struct in6_pktinfo *)CMSG_DATA(cm);
423		memcpy(&pi->ipi6_addr, &src6.sin6_addr, sizeof(src6.sin6_addr));
424		pi->ipi6_ifindex = ifindex;
425
426		plog(LLV_DEBUG, LOCATION, NULL,
427			"src6 %s %d\n",
428			saddr2str((struct sockaddr *)&src6),
429			src6.sin6_scope_id);
430		plog(LLV_DEBUG, LOCATION, NULL,
431			"dst6 %s %d\n",
432			saddr2str((struct sockaddr *)&dst6),
433			dst6.sin6_scope_id);
434
435		for (i = 0; i < cnt; i++) {
436			len = sendmsg(s, &m, 0 /*MSG_DONTROUTE*/);
437			if (len < 0) {
438				plog(LLV_ERROR, LOCATION, NULL,
439					"sendmsg (%s)\n", strerror(errno));
440				return -1;
441			}
442			plog(LLV_DEBUG, LOCATION, NULL,
443				"%d times of %d bytes message will be sent "
444				"to %s\n",
445				i + 1, len, saddr2str(dst));
446		}
447		plogdump(LLV_DEBUG, (char *)buf, buflen);
448
449		return len;
450	    }
451#endif
452#ifdef __linux__
453	case AF_INET:
454	    {
455		struct msghdr m;
456		struct cmsghdr *cm;
457		struct iovec iov[2];
458		u_char cmsgbuf[256];
459		struct in_pktinfo *pi;
460		int ifindex = 0;
461		struct sockaddr_in src6, dst6;
462
463		memcpy(&src6, src, sizeof(src6));
464		memcpy(&dst6, dst, sizeof(dst6));
465
466		memset(&m, 0, sizeof(m));
467		m.msg_name = (caddr_t)&dst6;
468		m.msg_namelen = sizeof(dst6);
469		iov[0].iov_base = (char *)buf;
470		iov[0].iov_len = buflen;
471		m.msg_iov = iov;
472		m.msg_iovlen = 1;
473
474		memset(cmsgbuf, 0, sizeof(cmsgbuf));
475		cm = (struct cmsghdr *)cmsgbuf;
476		m.msg_control = (caddr_t)cm;
477		m.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo));
478
479		cm->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
480		cm->cmsg_level = IPPROTO_IP;
481		cm->cmsg_type = IP_PKTINFO;
482		pi = (struct in_pktinfo *)CMSG_DATA(cm);
483		memcpy(&pi->ipi_spec_dst, &src6.sin_addr, sizeof(src6.sin_addr));
484		pi->ipi_ifindex = ifindex;
485
486		plog(LLV_DEBUG, LOCATION, NULL,
487			"src4 %s\n",
488			saddr2str((struct sockaddr *)&src6));
489		plog(LLV_DEBUG, LOCATION, NULL,
490			"dst4 %s\n",
491			saddr2str((struct sockaddr *)&dst6));
492
493		for (i = 0; i < cnt; i++) {
494			len = sendmsg(s, &m, 0 /*MSG_DONTROUTE*/);
495			if (len < 0) {
496				plog(LLV_ERROR, LOCATION, NULL,
497					"sendmsg (%s)\n", strerror(errno));
498				return -1;
499			}
500			plog(LLV_DEBUG, LOCATION, NULL,
501				"%d times of %d bytes message will be sent "
502				"to %s\n",
503				i + 1, len, saddr2str(dst));
504		}
505		plogdump(LLV_DEBUG, (char *)buf, buflen);
506
507		return len;
508	    }
509#endif /* __linux__ */
510	default:
511	    {
512		int needclose = 0;
513		int sendsock;
514
515		if (ss.ss_family == src->sa_family && memcmp(&ss, src, sysdep_sa_len(src)) == 0) {
516			sendsock = s;
517			needclose = 0;
518		} else {
519			int yes = 1;
520			/*
521			 * Use newly opened socket for sending packets.
522			 * NOTE: this is unsafe, because if the peer is quick enough
523			 * the packet from the peer may be queued into sendsock.
524			 * Better approach is to prepare bind'ed udp sockets for
525			 * each of the interface addresses.
526			 */
527			sendsock = SOCKET(src->sa_family, SOCK_DGRAM, 0);
528			if (sendsock < 0) {
529				plog(LLV_ERROR, LOCATION, NULL,
530					"socket (%s)\n", strerror(errno));
531				return -1;
532			}
533			if (setsockopt(sendsock, SOL_SOCKET,
534#ifdef __linux__
535				       SO_REUSEADDR,
536#else
537				       SO_REUSEPORT,
538#endif
539				       (void *)&yes, sizeof(yes)) < 0) {
540				plog(LLV_ERROR, LOCATION, NULL,
541					"setsockopt SO_REUSEPORT (%s)\n",
542					strerror(errno));
543				close(sendsock);
544				return -1;
545			}
546#ifdef IPV6_USE_MIN_MTU
547			if (src->sa_family == AF_INET6 &&
548			    setsockopt(sendsock, IPPROTO_IPV6, IPV6_USE_MIN_MTU,
549			    (void *)&yes, sizeof(yes)) < 0) {
550				plog(LLV_ERROR, LOCATION, NULL,
551					"setsockopt IPV6_USE_MIN_MTU (%s)\n",
552					strerror(errno));
553				close(sendsock);
554				return -1;
555			}
556#endif
557			if (setsockopt_bypass(sendsock, src->sa_family) < 0) {
558				close(sendsock);
559				return -1;
560			}
561
562			if (BIND(sendsock, (struct sockaddr *)src,
563				 sysdep_sa_len(src)) < 0) {
564				plog(LLV_ERROR, LOCATION, NULL,
565					"bind 1 (%s)\n", strerror(errno));
566				close(sendsock);
567				return -1;
568			}
569			needclose = 1;
570		}
571
572		for (i = 0; i < cnt; i++) {
573			len = sendto(sendsock, buf, buflen, 0, dst, sysdep_sa_len(dst));
574			if (len < 0) {
575				plog(LLV_ERROR, LOCATION, NULL,
576					"sendto (%s)\n", strerror(errno));
577				if (needclose)
578					close(sendsock);
579				return len;
580			}
581			plog(LLV_DEBUG, LOCATION, NULL,
582				"%d times of %d bytes message will be sent "
583				"to %s\n",
584				i + 1, len, saddr2str(dst));
585		}
586		plogdump(LLV_DEBUG, (char *)buf, buflen);
587
588		if (needclose)
589			close(sendsock);
590
591		return len;
592	    }
593	}
594}
595
596int
597setsockopt_bypass(so, family)
598	int so, family;
599{
600	int level;
601	char *buf;
602	char *policy;
603
604	switch (family) {
605	case AF_INET:
606		level = IPPROTO_IP;
607		break;
608#ifdef INET6
609	case AF_INET6:
610		level = IPPROTO_IPV6;
611		break;
612#endif
613	default:
614		plog(LLV_ERROR, LOCATION, NULL,
615			"unsupported address family %d\n", family);
616		return -1;
617	}
618
619	policy = "in bypass";
620	buf = ipsec_set_policy(policy, strlen(policy));
621	if (buf == NULL) {
622		plog(LLV_ERROR, LOCATION, NULL,
623			"ipsec_set_policy (%s)\n",
624			ipsec_strerror());
625		return -1;
626	}
627	if (SETSOCKOPT(so, level,
628	               (level == IPPROTO_IP ?
629	                         IP_IPSEC_POLICY : IPV6_IPSEC_POLICY),
630	               buf, ipsec_get_policylen(buf)) < 0) {
631		plog(LLV_ERROR, LOCATION, NULL,
632			"setsockopt IP_IPSEC_POLICY (%s)\n",
633			strerror(errno));
634		return -1;
635	}
636	racoon_free(buf);
637
638	policy = "out bypass";
639	buf = ipsec_set_policy(policy, strlen(policy));
640	if (buf == NULL) {
641		plog(LLV_ERROR, LOCATION, NULL,
642			"ipsec_set_policy (%s)\n",
643			ipsec_strerror());
644		return -1;
645	}
646	if (SETSOCKOPT(so, level,
647	               (level == IPPROTO_IP ?
648	                         IP_IPSEC_POLICY : IPV6_IPSEC_POLICY),
649	               buf, ipsec_get_policylen(buf)) < 0) {
650		plog(LLV_ERROR, LOCATION, NULL,
651			"setsockopt IP_IPSEC_POLICY (%s)\n",
652			strerror(errno));
653		return -1;
654	}
655	racoon_free(buf);
656
657	return 0;
658}
659
660struct sockaddr *
661newsaddr(len)
662	int len;
663{
664	struct sockaddr *new;
665
666	if ((new = racoon_calloc(1, len)) == NULL) {
667		plog(LLV_ERROR, LOCATION, NULL,
668			"%s\n", strerror(errno));
669		goto out;
670	}
671
672#ifdef __linux__
673	if (len == sizeof (struct sockaddr_in6))
674		new->sa_family = AF_INET6;
675	else
676		new->sa_family = AF_INET;
677#else
678	/* initial */
679	new->sa_len = len;
680#endif
681out:
682	return new;
683}
684
685struct sockaddr *
686dupsaddr(src)
687	struct sockaddr *src;
688{
689	struct sockaddr *dst;
690
691	dst = racoon_calloc(1, sysdep_sa_len(src));
692	if (dst == NULL) {
693		plog(LLV_ERROR, LOCATION, NULL,
694			"%s\n", strerror(errno));
695		return NULL;
696	}
697
698	memcpy(dst, src, sysdep_sa_len(src));
699
700	return dst;
701}
702
703char *
704saddr2str(saddr)
705	const struct sockaddr *saddr;
706{
707	static char buf[NI_MAXHOST + NI_MAXSERV + 10];
708	char addr[NI_MAXHOST], port[NI_MAXSERV];
709
710	if (saddr == NULL)
711		return NULL;
712
713	if (saddr->sa_family == AF_UNSPEC)
714		snprintf (buf, sizeof(buf), "%s", "anonymous");
715	else {
716		GETNAMEINFO(saddr, addr, port);
717		snprintf(buf, sizeof(buf), "%s[%s]", addr, port);
718	}
719
720	return buf;
721}
722
723char *
724saddrwop2str(saddr)
725	const struct sockaddr *saddr;
726{
727	static char buf[NI_MAXHOST + NI_MAXSERV + 10];
728	char addr[NI_MAXHOST];
729
730	if (saddr == NULL)
731		return NULL;
732
733	GETNAMEINFO_NULL(saddr, addr);
734	snprintf(buf, sizeof(buf), "%s", addr);
735
736	return buf;
737}
738
739char *
740naddrwop2str(const struct netaddr *naddr)
741{
742	static char buf[NI_MAXHOST + 10];
743	static const struct sockaddr sa_any;	/* this is initialized to all zeros */
744
745	if (naddr == NULL)
746		return NULL;
747
748	if (memcmp(&naddr->sa, &sa_any, sizeof(sa_any)) == 0)
749		snprintf(buf, sizeof(buf), "%s", "any");
750	else {
751		snprintf(buf, sizeof(buf), "%s", saddrwop2str(&naddr->sa.sa));
752		snprintf(&buf[strlen(buf)], sizeof(buf) - strlen(buf), "/%ld", naddr->prefix);
753	}
754	return buf;
755}
756
757char *
758naddrwop2str_fromto(const char *format, const struct netaddr *saddr,
759		    const struct netaddr *daddr)
760{
761	static char buf[2*(NI_MAXHOST + NI_MAXSERV + 10) + 100];
762	char *src, *dst;
763
764	src = racoon_strdup(naddrwop2str(saddr));
765	dst = racoon_strdup(naddrwop2str(daddr));
766	STRDUP_FATAL(src);
767	STRDUP_FATAL(dst);
768	/* WARNING: Be careful about the format string! Don't
769	   ever pass in something that a user can modify!!! */
770	snprintf (buf, sizeof(buf), format, src, dst);
771	racoon_free (src);
772	racoon_free (dst);
773
774	return buf;
775}
776
777char *
778saddr2str_fromto(format, saddr, daddr)
779	const char *format;
780	const struct sockaddr *saddr;
781	const struct sockaddr *daddr;
782{
783	static char buf[2*(NI_MAXHOST + NI_MAXSERV + 10) + 100];
784	char *src, *dst;
785
786	src = racoon_strdup(saddr2str(saddr));
787	dst = racoon_strdup(saddr2str(daddr));
788	STRDUP_FATAL(src);
789	STRDUP_FATAL(dst);
790	/* WARNING: Be careful about the format string! Don't
791	   ever pass in something that a user can modify!!! */
792	snprintf (buf, sizeof(buf), format, src, dst);
793	racoon_free (src);
794	racoon_free (dst);
795
796	return buf;
797}
798
799struct sockaddr *
800str2saddr(host, port)
801	char *host;
802	char *port;
803{
804	struct addrinfo hints, *res;
805	struct sockaddr *saddr;
806	int error;
807
808	memset(&hints, 0, sizeof(hints));
809	hints.ai_family = PF_UNSPEC;
810	hints.ai_socktype = SOCK_DGRAM;
811	hints.ai_flags = AI_NUMERICHOST;
812	error = getaddrinfo(host, port, &hints, &res);
813	if (error != 0) {
814		plog(LLV_ERROR, LOCATION, NULL,
815			"getaddrinfo(%s%s%s): %s\n",
816			host, port ? "," : "", port ? port : "",
817			gai_strerror(error));
818		return NULL;
819	}
820	if (res->ai_next != NULL) {
821		plog(LLV_WARNING, LOCATION, NULL,
822			"getaddrinfo(%s%s%s): "
823			"resolved to multiple address, "
824			"taking the first one\n",
825			host, port ? "," : "", port ? port : "");
826	}
827	saddr = racoon_malloc(res->ai_addrlen);
828	if (saddr == NULL) {
829		plog(LLV_ERROR, LOCATION, NULL,
830			"failed to allocate buffer.\n");
831		freeaddrinfo(res);
832		return NULL;
833	}
834	memcpy(saddr, res->ai_addr, res->ai_addrlen);
835	freeaddrinfo(res);
836
837	return saddr;
838}
839
840void
841mask_sockaddr(a, b, l)
842	struct sockaddr *a;
843	const struct sockaddr *b;
844	size_t l;
845{
846	size_t i;
847	u_int8_t *p, alen;
848
849	switch (b->sa_family) {
850	case AF_INET:
851		alen = sizeof(struct in_addr);
852		p = (u_int8_t *)&((struct sockaddr_in *)a)->sin_addr;
853		break;
854#ifdef INET6
855	case AF_INET6:
856		alen = sizeof(struct in6_addr);
857		p = (u_int8_t *)&((struct sockaddr_in6 *)a)->sin6_addr;
858		break;
859#endif
860	default:
861		plog(LLV_ERROR, LOCATION, NULL,
862			"invalid family: %d\n", b->sa_family);
863		exit(1);
864	}
865
866	if ((alen << 3) < l) {
867		plog(LLV_ERROR, LOCATION, NULL,
868			"unexpected inconsistency: %d %zu\n", b->sa_family, l);
869		exit(1);
870	}
871
872	memcpy(a, b, sysdep_sa_len(b));
873	p[l / 8] &= (0xff00 >> (l % 8)) & 0xff;
874	for (i = l / 8 + 1; i < alen; i++)
875		p[i] = 0x00;
876}
877
878/* Compute a score describing how "accurate" a netaddr is for a given sockaddr.
879 * Examples:
880 * 	Return values for address 10.20.30.40 [port 500] and given netaddresses...
881 * 		10.10.0.0/16	=> -1	... doesn't match
882 * 		0.0.0.0/0	=> 0	... matches, but only 0 bits.
883 * 		10.20.0.0/16	=> 16	... 16 bits match
884 * 		10.20.30.0/24	=> 24	... guess what ;-)
885 * 		10.20.30.40/32	=> 32	... whole address match
886 * 		10.20.30.40:500	=> 33	... both address and port match
887 * 		10.20.30.40:501	=> -1	... port doesn't match and isn't 0 (=any)
888 */
889int
890naddr_score(const struct netaddr *naddr, const struct sockaddr *saddr)
891{
892	static const struct netaddr naddr_any;	/* initialized to all-zeros */
893	struct sockaddr sa;
894	u_int16_t naddr_port, saddr_port;
895	int port_score;
896
897	if (!naddr || !saddr) {
898		plog(LLV_ERROR, LOCATION, NULL,
899		     "Call with null args: naddr=%p, saddr=%p\n",
900		     naddr, saddr);
901		return -1;
902	}
903
904	/* Wildcard address matches, but only 0 bits. */
905	if (memcmp(naddr, &naddr_any, sizeof(naddr_any)) == 0)
906		return 0;
907
908	/* If families don't match we really can't do much... */
909	if (naddr->sa.sa.sa_family != saddr->sa_family)
910		return -1;
911
912	/* If port check fail don't bother to check addresses. */
913	naddr_port = extract_port(&naddr->sa.sa);
914	saddr_port = extract_port(saddr);
915	if (naddr_port == 0 || saddr_port == 0)	/* wildcard match */
916		port_score = 0;
917	else if (naddr_port == saddr_port)	/* exact match */
918		port_score = 1;
919	else					/* mismatch :-) */
920		return -1;
921
922	/* Here it comes - compare network addresses. */
923	mask_sockaddr(&sa, saddr, naddr->prefix);
924	if (loglevel >= LLV_DEBUG) {	/* debug only */
925		char *a1, *a2, *a3;
926		a1 = racoon_strdup(naddrwop2str(naddr));
927		a2 = racoon_strdup(saddrwop2str(saddr));
928		a3 = racoon_strdup(saddrwop2str(&sa));
929		STRDUP_FATAL(a1);
930		STRDUP_FATAL(a2);
931		STRDUP_FATAL(a3);
932		plog(LLV_DEBUG, LOCATION, NULL,
933		     "naddr=%s, saddr=%s (masked=%s)\n",
934		     a1, a2, a3);
935		free(a1);
936		free(a2);
937		free(a3);
938	}
939	if (cmpsaddr(&sa, &naddr->sa.sa) <= CMPSADDR_WOP_MATCH)
940		return naddr->prefix + port_score;
941
942	return -1;
943}
944
945/* Some useful functions for sockaddr port manipulations. */
946u_int16_t
947extract_port (const struct sockaddr *addr)
948{
949  u_int16_t port = 0;
950
951  if (!addr)
952    return port;
953
954  switch (addr->sa_family) {
955    case AF_UNSPEC:
956      break;
957    case AF_INET:
958      port = ((struct sockaddr_in *)addr)->sin_port;
959      break;
960    case AF_INET6:
961      port = ((struct sockaddr_in6 *)addr)->sin6_port;
962      break;
963    default:
964      plog(LLV_ERROR, LOCATION, NULL, "unknown AF: %u\n", addr->sa_family);
965      break;
966  }
967
968  return ntohs(port);
969}
970
971u_int16_t *
972get_port_ptr (struct sockaddr *addr)
973{
974  u_int16_t *port_ptr;
975
976  if (!addr)
977    return NULL;
978
979  switch (addr->sa_family) {
980    case AF_INET:
981      port_ptr = &(((struct sockaddr_in *)addr)->sin_port);
982      break;
983    case AF_INET6:
984      port_ptr = &(((struct sockaddr_in6 *)addr)->sin6_port);
985      break;
986    default:
987      plog(LLV_ERROR, LOCATION, NULL, "unknown AF: %u\n", addr->sa_family);
988      return NULL;
989      break;
990  }
991
992  return port_ptr;
993}
994
995u_int16_t *
996set_port (struct sockaddr *addr, u_int16_t new_port)
997{
998  u_int16_t *port_ptr;
999
1000  port_ptr = get_port_ptr (addr);
1001
1002  if (port_ptr)
1003    *port_ptr = htons(new_port);
1004
1005  return port_ptr;
1006}
1007