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