1/* $Id: sockmisc.c,v 1.17.4.4 2005/10/04 09:54:27 manubsd 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 "config.h"
33
34#include <sys/types.h>
35#include <sys/param.h>
36#include <sys/socket.h>
37#include <sys/uio.h>
38
39#include <netinet/in.h>
40#ifndef HAVE_NETINET6_IPSEC
41#include <netinet/ipsec.h>
42#else
43#include <netinet6/ipsec.h>
44#endif
45
46#if defined(INET6) && !defined(INET6_ADVAPI) && \
47	defined(IP_RECVDSTADDR) && !defined(IPV6_RECVDSTADDR)
48#define IPV6_RECVDSTADDR IP_RECVDSTADDR
49#endif
50
51#include <stdlib.h>
52#include <stdio.h>
53#include <string.h>
54#include <errno.h>
55#ifdef HAVE_UNISTD_H
56#include <unistd.h>
57#endif
58#include <fcntl.h>
59
60#include "var.h"
61#include "misc.h"
62#include "plog.h"
63#include "sockmisc.h"
64#include "debug.h"
65#include "gcmalloc.h"
66#include "libpfkey.h"
67
68#ifndef IP_IPSEC_POLICY
69#define IP_IPSEC_POLICY 16	/* XXX: from linux/in.h */
70#endif
71
72#ifndef IPV6_IPSEC_POLICY
73#define IPV6_IPSEC_POLICY 34	/* XXX: from linux/???.h per
74				   "Tom Lendacky" <toml@us.ibm.com> */
75#endif
76
77const int niflags = 0;
78
79/*
80 * compare two sockaddr without port number.
81 * OUT:	0: equal.
82 *	1: not equal.
83 */
84int
85cmpsaddrwop(addr1, addr2)
86	const struct sockaddr_storage *addr1;
87	const struct sockaddr_storage *addr2;
88{
89	caddr_t sa1, sa2;
90
91	if (addr1 == 0 && addr2 == 0)
92		return 0;
93	if (addr1 == 0 || addr2 == 0)
94		return 1;
95
96	if (addr1->ss_len != addr2->ss_len
97	 || addr1->ss_family != addr2->ss_family)
98		return 1;
99	switch (addr1->ss_family) {
100	case AF_INET:
101		sa1 = (caddr_t)&((struct sockaddr_in *)addr1)->sin_addr;
102		sa2 = (caddr_t)&((struct sockaddr_in *)addr2)->sin_addr;
103		if (memcmp(sa1, sa2, sizeof(struct in_addr)) != 0)
104			return 1;
105		break;
106#ifdef INET6
107	case AF_INET6:
108		sa1 = (caddr_t)&((struct sockaddr_in6 *)addr1)->sin6_addr;
109		sa2 = (caddr_t)&((struct sockaddr_in6 *)addr2)->sin6_addr;
110		if (memcmp(sa1, sa2, sizeof(struct in6_addr)) != 0)
111			return 1;
112		if (((struct sockaddr_in6 *)addr1)->sin6_scope_id !=
113		    ((struct sockaddr_in6 *)addr2)->sin6_scope_id)
114			return 1;
115		break;
116#endif
117	default:
118		return 1;
119	}
120
121	return 0;
122}
123
124/*
125 * compare two sockaddr without port number using prefix.
126 * OUT:	0: equal.
127 *	1: not equal.
128 */
129int
130cmpsaddrwop_withprefix(const struct sockaddr_storage *addr1, const struct sockaddr_storage *addr2, int prefix)
131{
132    u_int32_t mask;
133    int i;
134
135	if (addr1 == 0 && addr2 == 0)
136		return 0;
137	if (addr1 == 0 || addr2 == 0)
138		return 1;
139
140	if (addr1->ss_len != addr2->ss_len
141        || addr1->ss_family != addr2->ss_family)
142		return 1;
143	switch (addr1->ss_family) {
144        case AF_INET:
145            mask = ~0;
146            mask <<= 32-prefix;
147            if ((((struct sockaddr_in *)addr1)->sin_addr.s_addr & htonl(mask)) !=
148                (((struct sockaddr_in *)addr2)->sin_addr.s_addr & htonl(mask)))
149                return 1;
150            break;
151#ifdef INET6
152        case AF_INET6:
153            for (i = 0; i < 4; i++) {
154                if (prefix >= 32) {
155                    mask = ~0;
156                    prefix -= 32;
157                } else if (prefix == 0)
158                    mask = 0;
159                else {
160                    mask = ~0;
161                    mask <<= 32-prefix;
162                    prefix = 0;
163                }
164                if ((((struct sockaddr_in6 *)addr1)->sin6_addr.__u6_addr.__u6_addr32[i] & htonl(mask)) !=
165                    (((struct sockaddr_in6 *)addr2)->sin6_addr.__u6_addr.__u6_addr32[i] & htonl(mask)))
166                    return 1;
167            }
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/*
182 * compare two sockaddr with port, taking care wildcard.
183 * addr1 is a subject address, addr2 is in a database entry.
184 * OUT:	0: equal.
185 *	1: not equal.
186 */
187int
188cmpsaddrwild(addr1, addr2)
189	const struct sockaddr_storage *addr1;
190	const struct sockaddr_storage *addr2;
191{
192	caddr_t sa1, sa2;
193	u_short port1, port2;
194
195	if (addr1 == 0 && addr2 == 0)
196		return 0;
197	if (addr1 == 0 || addr2 == 0)
198		return 1;
199
200	if (addr1->ss_len != addr2->ss_len
201	 || addr1->ss_family != addr2->ss_family)
202		return 1;
203
204	switch (addr1->ss_family) {
205	case AF_INET:
206		sa1 = (caddr_t)&((struct sockaddr_in *)addr1)->sin_addr;
207		sa2 = (caddr_t)&((struct sockaddr_in *)addr2)->sin_addr;
208		port1 = ((struct sockaddr_in *)addr1)->sin_port;
209		port2 = ((struct sockaddr_in *)addr2)->sin_port;
210		if (!(port1 == IPSEC_PORT_ANY ||
211		      port2 == IPSEC_PORT_ANY ||
212		      port1 == port2))
213			return 1;
214		if (memcmp(sa1, sa2, sizeof(struct in_addr)) != 0)
215			return 1;
216		break;
217#ifdef INET6
218	case AF_INET6:
219		sa1 = (caddr_t)&((struct sockaddr_in6 *)addr1)->sin6_addr;
220		sa2 = (caddr_t)&((struct sockaddr_in6 *)addr2)->sin6_addr;
221		port1 = ((struct sockaddr_in6 *)addr1)->sin6_port;
222		port2 = ((struct sockaddr_in6 *)addr2)->sin6_port;
223		if (!(port1 == IPSEC_PORT_ANY ||
224		      port2 == IPSEC_PORT_ANY ||
225		      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/*
242 * compare two sockaddr with strict match on port.
243 * OUT:	0: equal.
244 *	1: not equal.
245 */
246int
247cmpsaddrstrict(const struct sockaddr_storage *addr1, const struct sockaddr_storage *addr2)
248{
249	caddr_t sa1, sa2;
250	u_short port1, port2;
251
252	if (addr1 == 0 && addr2 == 0)
253		return 0;
254	if (addr1 == 0 || addr2 == 0)
255		return 1;
256
257	if (addr1->ss_len != addr2->ss_len
258	 || addr1->ss_family != addr2->ss_family)
259		return 1;
260
261	switch (addr1->ss_family) {
262	case AF_INET:
263		sa1 = (caddr_t)&((struct sockaddr_in *)addr1)->sin_addr;
264		sa2 = (caddr_t)&((struct sockaddr_in *)addr2)->sin_addr;
265		port1 = ((struct sockaddr_in *)addr1)->sin_port;
266		port2 = ((struct sockaddr_in *)addr2)->sin_port;
267		if (port1 != port2)
268			return 1;
269		if (memcmp(sa1, sa2, sizeof(struct in_addr)) != 0)
270			return 1;
271		break;
272#ifdef INET6
273	case AF_INET6:
274		sa1 = (caddr_t)&((struct sockaddr_in6 *)addr1)->sin6_addr;
275		sa2 = (caddr_t)&((struct sockaddr_in6 *)addr2)->sin6_addr;
276		port1 = ((struct sockaddr_in6 *)addr1)->sin6_port;
277		port2 = ((struct sockaddr_in6 *)addr2)->sin6_port;
278		if (port1 != port2)
279			return 1;
280		if (memcmp(sa1, sa2, sizeof(struct in6_addr)) != 0)
281			return 1;
282		if (((struct sockaddr_in6 *)addr1)->sin6_scope_id !=
283		    ((struct sockaddr_in6 *)addr2)->sin6_scope_id)
284			return 1;
285		break;
286#endif
287	default:
288		return 1;
289	}
290
291	return 0;
292}
293
294/*
295 * compare two sockaddr with strict match on port using prefix.
296 * OUT:	0: equal.
297 *	1: not equal.
298 */
299int
300cmpsaddrstrict_withprefix(const struct sockaddr_storage *addr1, const struct sockaddr_storage *addr2, int prefix)
301{
302	u_short port1, port2;
303    u_int32_t mask;
304    int i;
305
306	if (addr1 == 0 && addr2 == 0)
307		return 0;
308	if (addr1 == 0 || addr2 == 0)
309		return 1;
310
311	if (addr1->ss_len != addr2->ss_len
312        || addr1->ss_family != addr2->ss_family)
313		return 1;
314
315	switch (addr1->ss_family) {
316        case AF_INET:
317            port1 = ((struct sockaddr_in *)addr1)->sin_port;
318            port2 = ((struct sockaddr_in *)addr2)->sin_port;
319            if (port1 != port2)
320                return 1;
321            mask = ~0;
322            mask <<= 32-prefix;
323            if ((((struct sockaddr_in *)addr1)->sin_addr.s_addr & htonl(mask)) !=
324                (((struct sockaddr_in *)addr2)->sin_addr.s_addr & htonl(mask)))
325                return 1;
326            break;
327#ifdef INET6
328        case AF_INET6:
329            port1 = ((struct sockaddr_in6 *)addr1)->sin6_port;
330            port2 = ((struct sockaddr_in6 *)addr2)->sin6_port;
331            if (port1 != port2)
332                return 1;
333            for (i = 0; i < 4; i++) {
334                if (prefix >= 32) {
335                    mask = ~0;
336                    prefix -= 32;
337                } else if (prefix == 0)
338                    mask = 0;
339                else {
340                    mask = ~0;
341                    mask <<= 32-prefix;
342                    prefix = 0;
343                }
344                if ((((struct sockaddr_in6 *)addr1)->sin6_addr.__u6_addr.__u6_addr32[i] & htonl(mask)) !=
345                    (((struct sockaddr_in6 *)addr2)->sin6_addr.__u6_addr.__u6_addr32[i] & htonl(mask)))
346                    return 1;
347            }
348            if (((struct sockaddr_in6 *)addr1)->sin6_scope_id !=
349                ((struct sockaddr_in6 *)addr2)->sin6_scope_id)
350                return 1;
351            break;
352#endif
353        default:
354            return 1;
355	}
356
357	return 0;
358}
359
360
361/* get local address against the destination. */
362struct sockaddr_storage *
363getlocaladdr(struct sockaddr *remote)
364{
365	struct sockaddr_storage *local;
366	u_int local_len = sizeof(struct sockaddr);
367	int s;	/* for dummy connection */
368
369	/* allocate buffer */
370	if ((local = racoon_calloc(1, local_len)) == NULL) {
371		plog(ASL_LEVEL_ERR,
372			"failed to get address buffer.\n");
373		goto err;
374	}
375
376	/* get real interface received packet */
377	if ((s = socket(remote->sa_family, SOCK_DGRAM, 0)) < 0) {
378		plog(ASL_LEVEL_ERR,
379			"socket (%s)\n", strerror(errno));
380		goto err;
381	}
382
383	if (fcntl(s, F_SETFL, O_NONBLOCK) == -1) {
384		plog(ASL_LEVEL_ERR, "failed to put localaddr socket in non-blocking mode\n");
385	}
386
387	setsockopt_bypass(s, remote->sa_family);
388
389	if (connect(s, remote, sysdep_sa_len(remote)) < 0) {
390		plog(ASL_LEVEL_ERR,
391			"connect (%s)\n", strerror(errno));
392		close(s);
393		goto err;
394	}
395
396	if (getsockname(s, (struct sockaddr *)local, &local_len) < 0) {
397		plog(ASL_LEVEL_ERR,
398			"getsockname (%s)\n", strerror(errno));
399		close(s);
400		return NULL;
401	}
402
403	close(s);
404	return local;
405
406    err:
407	if (local != NULL)
408		racoon_free(local);
409	return NULL;
410}
411
412/*
413 * Receive packet, with src/dst information.  It is assumed that necessary
414 * setsockopt() have already performed on socket.
415 */
416int
417recvfromto(int s,
418           void *buf,
419           size_t buflen,
420           int flags,
421           struct sockaddr_storage *from,
422           socklen_t *fromlen,
423           struct sockaddr_storage *to,
424           u_int *tolen)
425{
426	int otolen;
427	ssize_t len;
428	struct sockaddr_storage ss;
429	struct msghdr m;
430	struct cmsghdr *cm, *cm_prev;
431	struct iovec iov[2];
432    u_int32_t cmsgbuf[256/sizeof(u_int32_t)];       // Wcast-align fix - force 32 bit alignment
433#if defined(INET6) && defined(INET6_ADVAPI)
434	struct in6_pktinfo *pi;
435#endif /*INET6_ADVAPI*/
436	struct sockaddr_in *sin;
437#ifdef INET6
438	struct sockaddr_in6 *sin6;
439#endif
440
441	len = sizeof(ss);
442	if (getsockname(s, (struct sockaddr *)&ss, (socklen_t*)&len) < 0) {
443		plog(ASL_LEVEL_ERR,
444			"getsockname (%s)\n", strerror(errno));
445		return -1;
446	}
447
448	m.msg_name = (caddr_t)from;
449	m.msg_namelen = *fromlen;
450	iov[0].iov_base = (caddr_t)buf;
451	iov[0].iov_len = buflen;
452	m.msg_iov = iov;
453	m.msg_iovlen = 1;
454	memset(cmsgbuf, 0, sizeof(cmsgbuf));
455	cm = (struct cmsghdr *)cmsgbuf;
456	m.msg_control = (caddr_t)cm;
457	m.msg_controllen = sizeof(cmsgbuf);
458	while ((len = recvmsg(s, &m, flags)) < 0) {
459		if (errno == EINTR)
460			continue;
461		plog(ASL_LEVEL_ERR, "recvmsg (%s)\n", strerror(errno));
462		return -1;
463	}
464	if (len == 0) {
465		return 0;
466	}
467	*fromlen = m.msg_namelen;
468
469	otolen = *tolen;
470	*tolen = 0;
471	for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(&m), cm_prev = NULL;
472	     m.msg_controllen != 0 && cm && cm != cm_prev;
473	     cm_prev = cm, cm = (struct cmsghdr *)CMSG_NXTHDR(&m, cm)) {
474#if 0
475		plog(ASL_LEVEL_ERR,
476			"cmsg %d %d\n", cm->cmsg_level, cm->cmsg_type);)
477#endif
478#if defined(INET6) && defined(INET6_ADVAPI)
479		if (ss.ss_family == AF_INET6
480		 && cm->cmsg_level == IPPROTO_IPV6
481		 && cm->cmsg_type == IPV6_PKTINFO
482		 && otolen >= sizeof(*sin6)) {
483			pi = ALIGNED_CAST(struct in6_pktinfo *)(CMSG_DATA(cm));
484			*tolen = sizeof(*sin6);
485			sin6 = (struct sockaddr_in6 *)to;
486			memset(sin6, 0, sizeof(*sin6));
487			sin6->sin6_family = AF_INET6;
488			sin6->sin6_len = sizeof(*sin6);
489			memcpy(&sin6->sin6_addr, &pi->ipi6_addr,
490				sizeof(sin6->sin6_addr));
491			/* XXX other cases, such as site-local? */
492			if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
493				sin6->sin6_scope_id = pi->ipi6_ifindex;
494			else
495				sin6->sin6_scope_id = 0;
496			sin6->sin6_port =
497				((struct sockaddr_in6 *)&ss)->sin6_port;
498			otolen = -1;	/* "to" already set */
499			continue;
500		}
501#endif
502#if defined(INET6) && defined(IPV6_RECVDSTADDR)
503		if (ss.ss_family == AF_INET6
504		      && cm->cmsg_level == IPPROTO_IPV6
505		      && cm->cmsg_type == IPV6_RECVDSTADDR
506		      && otolen >= sizeof(*sin6)) {
507			*tolen = sizeof(*sin6);
508			sin6 = (struct sockaddr_in6 *)to;
509			memset(sin6, 0, sizeof(*sin6));
510			sin6->sin6_family = AF_INET6;
511			sin6->sin6_len = sizeof(*sin6);
512			memcpy(&sin6->sin6_addr, CMSG_DATA(cm),
513				sizeof(sin6->sin6_addr));
514			sin6->sin6_port =
515				((struct sockaddr_in6 *)&ss)->sin6_port;
516			otolen = -1;	/* "to" already set */
517			continue;
518		}
519#endif
520		if (ss.ss_family == AF_INET
521		 && cm->cmsg_level == IPPROTO_IP
522		 && cm->cmsg_type == IP_RECVDSTADDR
523		 && otolen >= sizeof(*sin)) {
524			*tolen = sizeof(*sin);
525			sin = (struct sockaddr_in *)to;
526			memset(sin, 0, sizeof(*sin));
527			sin->sin_family = AF_INET;
528			sin->sin_len = sizeof(*sin);
529			memcpy(&sin->sin_addr, CMSG_DATA(cm),
530				sizeof(sin->sin_addr));
531			sin->sin_port = ((struct sockaddr_in *)&ss)->sin_port;
532			otolen = -1;	/* "to" already set */
533			continue;
534		}
535	}
536    plogdump(ASL_LEVEL_DEBUG, buf, buflen, "@@@@@@ data from readmsg:\n");
537	return len;
538}
539
540/* send packet, with fixing src/dst address pair. */
541int
542sendfromto(s, buf, buflen, src, dst, cnt)
543	int s, cnt;
544	const void *buf;
545	size_t buflen;
546	struct sockaddr_storage *src;
547	struct sockaddr_storage *dst;
548{
549	struct sockaddr_storage ss;
550	int len;
551	int i;
552
553	if (src->ss_family != dst->ss_family) {
554		plog(ASL_LEVEL_ERR,
555			"address family mismatch\n");
556		return -1;
557	}
558
559	len = sizeof(ss);
560	if (getsockname(s, (struct sockaddr *)&ss, (socklen_t*)&len) < 0) {
561		plog(ASL_LEVEL_ERR,
562			"getsockname (%s)\n", strerror(errno));
563		return -1;
564	}
565
566	plog(ASL_LEVEL_DEBUG,
567		"sockname %s\n", saddr2str((struct sockaddr *)&ss));
568	plog(ASL_LEVEL_DEBUG,
569		"send packet from %s\n", saddr2str((struct sockaddr *)src));
570	plog(ASL_LEVEL_DEBUG,
571		"send packet to %s\n", saddr2str((struct sockaddr *)dst));
572
573	if (src->ss_family != ss.ss_family) {
574		plog(ASL_LEVEL_ERR,
575			"address family mismatch\n");
576		return -1;
577	}
578
579	switch (src->ss_family) {
580#if defined(INET6) && defined(INET6_ADVAPI)
581	case AF_INET6:
582	    {
583		struct msghdr m;
584		struct cmsghdr *cm;
585		struct iovec iov[2];
586        u_int32_t cmsgbuf[256/sizeof(u_int32_t)];   // Wcast-align fix - force 32 bit alignment
587		struct in6_pktinfo *pi;
588		int ifindex;
589		struct sockaddr_in6 src6, dst6;
590
591		memcpy(&src6, src, sizeof(src6));
592		memcpy(&dst6, dst, sizeof(dst6));
593
594		/* XXX take care of other cases, such as site-local */
595		ifindex = 0;
596		if (IN6_IS_ADDR_LINKLOCAL(&src6.sin6_addr)
597		 || IN6_IS_ADDR_MULTICAST(&src6.sin6_addr)) {
598			ifindex = src6.sin6_scope_id;	/*???*/
599		}
600
601		/* XXX some sanity check on dst6.sin6_scope_id */
602
603		/* flowinfo for IKE?  mmm, maybe useful but for now make it 0 */
604		src6.sin6_flowinfo = dst6.sin6_flowinfo = 0;
605
606		memset(&m, 0, sizeof(m));
607		m.msg_name = (caddr_t)&dst6;
608		m.msg_namelen = sizeof(dst6);
609		iov[0].iov_base = (char *)buf;
610		iov[0].iov_len = buflen;
611		m.msg_iov = iov;
612		m.msg_iovlen = 1;
613
614		memset(cmsgbuf, 0, sizeof(cmsgbuf));
615		cm = (struct cmsghdr *)cmsgbuf;
616		m.msg_control = (caddr_t)cm;
617		m.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
618
619		cm->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
620		cm->cmsg_level = IPPROTO_IPV6;
621		cm->cmsg_type = IPV6_PKTINFO;
622		pi = ALIGNED_CAST(struct in6_pktinfo *)CMSG_DATA(cm);
623		memcpy(&pi->ipi6_addr, &src6.sin6_addr, sizeof(src6.sin6_addr));
624		pi->ipi6_ifindex = ifindex;
625
626		plog(ASL_LEVEL_DEBUG,
627			"src6 %s %d\n",
628			saddr2str((struct sockaddr *)&src6),
629			src6.sin6_scope_id);
630		plog(ASL_LEVEL_DEBUG,
631			"dst6 %s %d\n",
632			saddr2str((struct sockaddr *)&dst6),
633			dst6.sin6_scope_id);
634
635		for (i = 0; i < cnt; i++) {
636			len = sendmsg(s, &m, 0 /*MSG_DONTROUTE*/);
637			if (len < 0) {
638				plog(ASL_LEVEL_ERR,
639					"sendmsg (%s)\n", strerror(errno));
640				if (errno != EHOSTUNREACH && errno != ENETDOWN && errno != ENETUNREACH) {
641				        return -1;
642				}
643				// <rdar://problem/6609744> treat these failures like
644				// packet loss, in case the network interface is flaky
645				len = 0;
646			}
647			plog(ASL_LEVEL_DEBUG,
648				"%d times of %d bytes message will be sent "
649				"to %s\n",
650				i + 1, len, saddr2str((struct sockaddr *)dst));
651		}
652
653		return len;
654	    }
655#endif
656	default:
657	    {
658		int needclose = 0;
659		int sendsock;
660
661		if (ss.ss_family == src->ss_family && memcmp(&ss, src, sysdep_sa_len((struct sockaddr *)src)) == 0) {
662			sendsock = s;
663			needclose = 0;
664		} else {
665			int yes = 1;
666			/*
667			 * Use newly opened socket for sending packets.
668			 * NOTE: this is unsafe, because if the peer is quick enough
669			 * the packet from the peer may be queued into sendsock.
670			 * Better approach is to prepare bind'ed udp sockets for
671			 * each of the interface addresses.
672			 */
673			sendsock = socket(src->ss_family, SOCK_DGRAM, 0);
674			if (sendsock < 0) {
675				plog(ASL_LEVEL_ERR,
676					"socket (%s)\n", strerror(errno));
677				return -1;
678			}
679			if (fcntl(sendsock, F_SETFL, O_NONBLOCK) == -1) {
680				plog(ASL_LEVEL_ERR, "failed to put sendsock socket in non-blocking mode\n");
681			}
682			if (setsockopt(sendsock, SOL_SOCKET,
683				       SO_REUSEPORT,
684				       (void *)&yes, sizeof(yes)) < 0) {
685				plog(ASL_LEVEL_ERR,
686					"setsockopt SO_REUSEPORT (%s)\n",
687					strerror(errno));
688				close(sendsock);
689				return -1;
690			}
691#ifdef IPV6_USE_MIN_MTU
692			if (src->ss_family == AF_INET6 &&
693			    setsockopt(sendsock, IPPROTO_IPV6, IPV6_USE_MIN_MTU,
694			    (void *)&yes, sizeof(yes)) < 0) {
695				plog(ASL_LEVEL_ERR,
696					"setsockopt IPV6_USE_MIN_MTU (%s)\n",
697					strerror(errno));
698				close(sendsock);
699				return -1;
700			}
701#endif
702			if (setsockopt_bypass(sendsock, src->ss_family) < 0) {
703				close(sendsock);
704				return -1;
705			}
706
707			if (bind(sendsock, (struct sockaddr *)src, sysdep_sa_len((struct sockaddr *)src)) < 0) {
708				plog(ASL_LEVEL_ERR,
709					"bind 1 (%s)\n", strerror(errno));
710				close(sendsock);
711				return -1;
712			}
713			needclose = 1;
714		}
715
716        plogdump(ASL_LEVEL_DEBUG, (void*)buf, buflen, "@@@@@@ data being sent:\n");
717
718            for (i = 0; i < cnt; i++) {
719			len = sendto(sendsock, buf, buflen, 0, (struct sockaddr *)dst, sysdep_sa_len((struct sockaddr *)dst));
720			if (len < 0) {
721				plog(ASL_LEVEL_ERR,
722					"sendto (%s)\n", strerror(errno));
723				if (errno != EHOSTUNREACH && errno != ENETDOWN && errno != ENETUNREACH) {
724				        if (needclose)
725					        close(sendsock);
726					return -1;
727				}
728				plog(ASL_LEVEL_ERR,
729					"treating socket error (%s) like packet loss\n", strerror(errno));
730				// else treat these failures like a packet loss
731				len = 0;
732			}
733			plog(ASL_LEVEL_DEBUG,
734				"%d times of %d bytes message will be sent "
735				"to %s\n",
736				i + 1, len, saddr2str((struct sockaddr *)dst));
737		}
738		//plog(ASL_LEVEL_DEBUG, "sent %d bytes", buflen);
739
740		if (needclose)
741			close(sendsock);
742
743		return len;
744	    }
745	}
746}
747
748int
749setsockopt_bypass(int so, int family)
750{
751	int level;
752	char *buf;
753	char *policy;
754
755	switch (family) {
756	case AF_INET:
757		level = IPPROTO_IP;
758		break;
759#ifdef INET6
760	case AF_INET6:
761		level = IPPROTO_IPV6;
762		break;
763#endif
764	default:
765		plog(ASL_LEVEL_ERR,
766			"unsupported address family %d\n", family);
767		return -1;
768	}
769
770	policy = "in bypass";
771	buf = ipsec_set_policy(policy, strlen(policy));
772	if (buf == NULL) {
773		plog(ASL_LEVEL_ERR,
774			"ipsec_set_policy (%s)\n",
775			ipsec_strerror());
776		return -1;
777	}
778	if (setsockopt(so, level,
779	               (level == IPPROTO_IP ?
780	                         IP_IPSEC_POLICY : IPV6_IPSEC_POLICY),
781	               buf, ipsec_get_policylen(buf)) < 0) {
782		plog(ASL_LEVEL_ERR,
783			"setsockopt IP_IPSEC_POLICY (%s)\n",
784			strerror(errno));
785		return -1;
786	}
787	racoon_free(buf);
788
789	policy = "out bypass";
790	buf = ipsec_set_policy(policy, strlen(policy));
791	if (buf == NULL) {
792		plog(ASL_LEVEL_ERR,
793			"ipsec_set_policy (%s)\n",
794			ipsec_strerror());
795		return -1;
796	}
797	if (setsockopt(so, level,
798	               (level == IPPROTO_IP ?
799	                         IP_IPSEC_POLICY : IPV6_IPSEC_POLICY),
800	               buf, ipsec_get_policylen(buf)) < 0) {
801		plog(ASL_LEVEL_ERR,
802			"setsockopt IP_IPSEC_POLICY (%s)\n",
803			strerror(errno));
804		return -1;
805	}
806	racoon_free(buf);
807
808	return 0;
809}
810
811struct sockaddr_storage *
812newsaddr(int len)
813{
814	struct sockaddr_storage *new;
815
816	if ((new = racoon_calloc(1, sizeof(*new))) == NULL) {
817		plog(ASL_LEVEL_ERR,
818			"%s\n", strerror(errno));
819		goto out;
820	}
821	/* initial */
822	new->ss_len = len;
823out:
824	return new;
825}
826
827struct sockaddr_storage *
828dupsaddr(struct sockaddr_storage *addr)
829{
830	struct sockaddr_storage *new;
831
832	new = racoon_calloc(1, sizeof(*new));
833	if (new == NULL) {
834		plog(ASL_LEVEL_ERR, "%s\n", strerror(errno));
835		return NULL;
836	}
837
838	memcpy(new, addr, addr->ss_len);
839
840	return new;
841}
842
843char *
844saddr2str(const struct sockaddr *saddr)
845{
846	static char buf[NI_MAXHOST + NI_MAXSERV + 10];
847	char addr[NI_MAXHOST], port[NI_MAXSERV];
848
849	if (saddr == NULL) {
850		buf[0] = '\0';
851		return buf;
852	}
853
854	if (saddr->sa_family == AF_UNSPEC)
855		snprintf (buf, sizeof(buf), "%s", "anonymous");
856	else {
857		GETNAMEINFO(saddr, addr, port);
858		snprintf(buf, sizeof(buf), "%s[%s]", addr, port);
859	}
860
861	return buf;
862}
863
864char *
865saddr2str_with_prefix(const struct sockaddr *saddr, int prefix)
866{
867	static char buf[NI_MAXHOST + NI_MAXSERV + 10];
868	char addr[NI_MAXHOST], port[NI_MAXSERV];
869
870	if (saddr == NULL) {
871		buf[0] = '\0';
872		return buf;
873	}
874
875	if (saddr->sa_family == AF_UNSPEC)
876		snprintf (buf, sizeof(buf), "%s", "anonymous");
877	else {
878		GETNAMEINFO(saddr, addr, port);
879		snprintf(buf, sizeof(buf), "%s/%d[%s]", addr, prefix, port);
880	}
881
882	return buf;
883}
884
885
886char *
887saddrwop2str(const struct sockaddr *saddr)
888{
889	static char buf[NI_MAXHOST + NI_MAXSERV + 10];
890	char addr[NI_MAXHOST];
891
892	if (saddr == NULL) {
893		buf[0] = '\0';
894		return buf;
895	}
896
897	GETNAMEINFO_NULL(saddr, addr);
898	snprintf(buf, sizeof(buf), "%s", addr);
899
900	return buf;
901}
902
903char *
904naddrwop2str(const struct netaddr *naddr)
905{
906	static char buf[NI_MAXHOST + 10];
907	static const struct sockaddr sa_any;	/* this is initialized to all zeros */
908
909	if (naddr == NULL) {
910		buf[0] = '\0';
911		return buf;
912	}
913
914	if (memcmp(&naddr->sa, &sa_any, sizeof(sa_any)) == 0)
915		snprintf(buf, sizeof(buf), "%s", "any");
916	else {
917		snprintf(buf, sizeof(buf), "%s", saddrwop2str((struct sockaddr *)&naddr->sa.sa));
918		snprintf(&buf[strlen(buf)], sizeof(buf) - strlen(buf), "/%ld", naddr->prefix);
919	}
920	return buf;
921}
922
923char *
924naddrwop2str_fromto(const char *format, const struct netaddr *saddr,
925		    const struct netaddr *daddr)
926{
927	static char buf[2*(NI_MAXHOST + NI_MAXSERV + 10) + 100];
928	char *src, *dst;
929
930	src = racoon_strdup(naddrwop2str(saddr));
931	dst = racoon_strdup(naddrwop2str(daddr));
932	STRDUP_FATAL(src);
933	STRDUP_FATAL(dst);
934	/* WARNING: Be careful about the format string! Don't
935	   ever pass in something that a user can modify!!! */
936	snprintf (buf, sizeof(buf), format, src, dst);
937	racoon_free (src);
938	racoon_free (dst);
939
940	return buf;
941}
942
943char *
944saddr2str_fromto(format, saddr, daddr)
945	const char *format;
946	const struct sockaddr *saddr;
947	const struct sockaddr *daddr;
948{
949	static char buf[2*(NI_MAXHOST + NI_MAXSERV + 10) + 100];
950	char *src, *dst;
951
952	if (saddr) {
953		src = racoon_strdup(saddr2str(saddr));
954		STRDUP_FATAL(src);
955	} else {
956		src = NULL;
957	}
958	if (daddr) {
959		dst = racoon_strdup(saddr2str(daddr));
960		STRDUP_FATAL(dst);
961	} else {
962		dst = NULL;
963	}
964	/* WARNING: Be careful about the format string! Don't
965	   ever pass in something that a user can modify!!! */
966	snprintf (buf, sizeof(buf), format, src? src:"[null]", dst? dst:"[null]");
967	if (src) {
968		racoon_free (src);
969	}
970	if (dst) {
971		racoon_free (dst);
972	}
973
974	return buf;
975}
976
977struct sockaddr_storage *
978str2saddr(char *host, char *port)
979{
980	struct addrinfo hints, *res;
981	struct sockaddr_storage *saddr;
982	int error;
983
984	memset(&hints, 0, sizeof(hints));
985	hints.ai_family = PF_UNSPEC;
986	hints.ai_socktype = SOCK_DGRAM;
987	hints.ai_flags = AI_NUMERICHOST;
988	error = getaddrinfo(host, port, &hints, &res);
989	if (error != 0) {
990		plog(ASL_LEVEL_ERR,
991			"getaddrinfo(%s%s%s): %s\n",
992			host, port ? "," : "", port ? port : "",
993			gai_strerror(error));
994		return NULL;
995	}
996	if (res->ai_next != NULL) {
997		plog(ASL_LEVEL_WARNING,
998			"getaddrinfo(%s%s%s): "
999			"resolved to multiple address, "
1000			"taking the first one\n",
1001			host, port ? "," : "", port ? port : "");
1002	}
1003	saddr = newsaddr(sizeof(*saddr));
1004	if (saddr == NULL) {
1005		plog(ASL_LEVEL_ERR,
1006			"failed to allocate buffer.\n");
1007		freeaddrinfo(res);
1008		return NULL;
1009	}
1010	memcpy(saddr, res->ai_addr, res->ai_addrlen);
1011	freeaddrinfo(res);
1012
1013	return saddr;
1014}
1015
1016void
1017mask_sockaddr(a, b, l)
1018	struct sockaddr_storage *a;
1019	const struct sockaddr_storage *b;
1020	size_t l;
1021{
1022	size_t i;
1023	u_int8_t *p, alen;
1024
1025	switch (b->ss_family) {
1026	case AF_INET:
1027		alen = sizeof(struct in_addr);
1028		p = (u_int8_t *)&((struct sockaddr_in *)a)->sin_addr;
1029		break;
1030#ifdef INET6
1031	case AF_INET6:
1032		alen = sizeof(struct in6_addr);
1033		p = (u_int8_t *)&((struct sockaddr_in6 *)a)->sin6_addr;
1034		break;
1035#endif
1036	default:
1037		plog(ASL_LEVEL_ERR,
1038			"invalid address family: %d\n", b->ss_family);
1039		exit(1);
1040	}
1041
1042	if ((alen << 3) < l) {
1043		plog(ASL_LEVEL_ERR,
1044			"unexpected inconsistency: %d %zu\n", b->ss_family, l);
1045		exit(1);
1046	}
1047
1048	memcpy(a, b, sysdep_sa_len((struct sockaddr *)b));
1049	p[l / 8] &= (0xff00 >> (l % 8)) & 0xff;
1050	for (i = l / 8 + 1; i < alen; i++)
1051		p[i] = 0x00;
1052}
1053
1054/* Compute a score describing how "accurate" a netaddr is for a given sockaddr.
1055 * Examples:
1056 * 	Return values for address 10.20.30.40 [port 500] and given netaddresses...
1057 * 		10.10.0.0/16	=> -1	... doesn't match
1058 * 		0.0.0.0/0	=> 0	... matches, but only 0 bits.
1059 * 		10.20.0.0/16	=> 16	... 16 bits match
1060 * 		10.20.30.0/24	=> 24	... guess what ;-)
1061 * 		10.20.30.40/32	=> 32	... whole address match
1062 * 		10.20.30.40:500	=> 33	... both address and port match
1063 * 		10.20.30.40:501	=> -1	... port doesn't match and isn't 0 (=any)
1064 */
1065int
1066naddr_score(const struct netaddr *naddr, const struct sockaddr_storage *saddr)
1067{
1068	static const struct netaddr naddr_any;	/* initialized to all-zeros */
1069	struct sockaddr_storage sa;
1070	u_int16_t naddr_port, saddr_port;
1071	int port_score;
1072
1073	if (!naddr || !saddr) {
1074		plog(ASL_LEVEL_ERR,
1075		     "Call with null args: naddr=%p, saddr=%p\n",
1076		     naddr, saddr);
1077		return -1;
1078	}
1079
1080	/* Wildcard address matches, but only 0 bits. */
1081	if (memcmp(naddr, &naddr_any, sizeof(naddr_any)) == 0)
1082		return 0;
1083
1084	/* If families don't match we really can't do much... */
1085	if (naddr->sa.sa.ss_family != saddr->ss_family)
1086		return -1;
1087
1088	/* If port check fail don't bother to check addresses. */
1089	naddr_port = extract_port(&naddr->sa.sa);
1090	saddr_port = extract_port(saddr);
1091	if (naddr_port == 0 || saddr_port == 0)	/* wildcard match */
1092		port_score = 0;
1093	else if (naddr_port == saddr_port)	/* exact match */
1094		port_score = 1;
1095	else					/* mismatch :-) */
1096		return -1;
1097
1098	/* Here it comes - compare network addresses. */
1099	mask_sockaddr(&sa, saddr, naddr->prefix);
1100	if (loglevel >= ASL_LEVEL_DEBUG) {	/* debug only */
1101		char *a1, *a2, *a3;
1102		a1 = racoon_strdup(naddrwop2str(naddr));
1103		a2 = racoon_strdup(saddrwop2str((struct sockaddr *)saddr));
1104		a3 = racoon_strdup(saddrwop2str((struct sockaddr *)&sa));
1105		STRDUP_FATAL(a1);
1106		STRDUP_FATAL(a2);
1107		STRDUP_FATAL(a3);
1108		plog(ASL_LEVEL_DEBUG,
1109		     "naddr=%s, saddr=%s (masked=%s)\n",
1110		     a1, a2, a3);
1111		free(a1);
1112		free(a2);
1113		free(a3);
1114	}
1115	if (cmpsaddrwop(&sa, &naddr->sa.sa) == 0)
1116		return naddr->prefix + port_score;
1117
1118	return -1;
1119}
1120
1121/* Some useful functions for sockaddr_storage port manipulations. */
1122u_int16_t
1123extract_port (const struct sockaddr_storage *addr)
1124{
1125  u_int16_t port = -1;
1126
1127  if (!addr)
1128    return port;
1129
1130  switch (addr->ss_family) {
1131    case AF_INET:
1132      port = ((struct sockaddr_in *)addr)->sin_port;
1133      break;
1134    case AF_INET6:
1135      port = ((struct sockaddr_in6 *)addr)->sin6_port;
1136      break;
1137    default:
1138      plog(ASL_LEVEL_ERR, "unknown AF: %u\n", addr->ss_family);
1139      break;
1140  }
1141
1142  return ntohs(port);
1143}
1144
1145u_int16_t *
1146get_port_ptr (struct sockaddr_storage *addr)
1147{
1148  u_int16_t *port_ptr;
1149
1150  if (!addr)
1151    return NULL;
1152
1153  switch (addr->ss_family) {
1154    case AF_INET:
1155      port_ptr = &(((struct sockaddr_in *)addr)->sin_port);
1156      break;
1157    case AF_INET6:
1158      port_ptr = &(((struct sockaddr_in6 *)addr)->sin6_port);
1159      break;
1160    default:
1161      plog(ASL_LEVEL_ERR, "unknown AF: %u\n", addr->ss_family);
1162      return NULL;
1163      break;
1164  }
1165
1166  return port_ptr;
1167}
1168
1169u_int16_t *
1170set_port (struct sockaddr_storage *addr, u_int16_t new_port)
1171{
1172  u_int16_t *port_ptr;
1173
1174  port_ptr = get_port_ptr (addr);
1175
1176  if (port_ptr)
1177    *port_ptr = htons(new_port);
1178
1179  return port_ptr;
1180}
1181