• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
80 const 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  */
88 int
cmpsaddr(addr1,addr2)89 cmpsaddr(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 #ifdef ANDROID_PATCHED
146 
getlocaladdr(struct sockaddr * remote)147 struct sockaddr *getlocaladdr(struct sockaddr *remote)
148 {
149     struct sockaddr_storage local;
150     socklen_t len = sysdep_sa_len(remote);
151     int s = privsep_socket(remote->sa_family, SOCK_DGRAM, 0);
152     if (s == -1 || connect(s, remote, len) == -1 ||
153         getsockname(s, (struct sockaddr *)&local, &len) == -1) {
154         close(s);
155         return NULL;
156     }
157     close(s);
158     return dupsaddr((struct sockaddr *)&local);
159 }
160 
recvfromto(int s,void * buf,size_t len,int flags,struct sockaddr * from,socklen_t * fromlen,struct sockaddr * to,unsigned int * tolen)161 int recvfromto(int s, void *buf, size_t len, int flags, struct sockaddr *from,
162                socklen_t *fromlen, struct sockaddr *to, unsigned int *tolen)
163 {
164     if (getsockname(s, to, (socklen_t *)tolen) == -1) {
165         return -1;
166     }
167     return recvfrom(s, buf, len, flags, from, fromlen);
168 }
169 
sendfromto(int s,const void * buf,size_t len,struct sockaddr * from,struct sockaddr * to,int count)170 int sendfromto(int s, const void *buf, size_t len, struct sockaddr *from,
171                struct sockaddr *to, int count)
172 {
173     int i;
174     for (i = 0; i < count; ++i) {
175         if (sendto(s, buf, len, 0, to, sysdep_sa_len(to)) == -1) {
176             return -1;
177         }
178     }
179     return len;
180 }
181 
setsockopt_bypass(int s,int family)182 int setsockopt_bypass(int s, int family)
183 {
184     struct sadb_x_policy p = {
185         .sadb_x_policy_len = PFKEY_UNIT64(sizeof(struct sadb_x_policy)),
186         .sadb_x_policy_exttype = SADB_X_EXT_POLICY,
187         .sadb_x_policy_type = IPSEC_POLICY_BYPASS,
188         .sadb_x_policy_dir = IPSEC_DIR_INBOUND,
189 #ifdef HAVE_PFKEY_POLICY_PRIORITY
190         .sadb_x_policy_priority = PRIORITY_DEFAULT,
191 #endif
192     };
193     int level = (family == AF_INET) ? IPPROTO_IP : IPPROTO_IPV6;
194     int option = (family == AF_INET) ? IP_IPSEC_POLICY : IPV6_IPSEC_POLICY;
195     int len = PFKEY_EXTLEN(&p);
196     if (setsockopt(s, level, option, &p, len) == -1) {
197         plog(LLV_WARNING, LOCATION, NULL, "setsockopt in bypass: %s\n",
198                 strerror(errno));
199     }
200     p.sadb_x_policy_dir = IPSEC_DIR_OUTBOUND;
201     if (setsockopt(s, level, option, &p, len) == -1) {
202         plog(LLV_WARNING, LOCATION, NULL, "setsockopt out bypass: %s\n",
203                 strerror(errno));
204     }
205     return 0;
206 }
207 
208 #else
209 
210 /* get local address against the destination. */
211 struct sockaddr *
getlocaladdr(remote)212 getlocaladdr(remote)
213 	struct sockaddr *remote;
214 {
215 	struct sockaddr *local;
216 	u_int local_len = sizeof(struct sockaddr_storage);
217 	int s;	/* for dummy connection */
218 
219 	/* allocate buffer */
220 	if ((local = racoon_calloc(1, local_len)) == NULL) {
221 		plog(LLV_ERROR, LOCATION, NULL,
222 			"failed to get address buffer.\n");
223 		goto err;
224 	}
225 
226 	/* get real interface received packet */
227 	if ((s = SOCKET(remote->sa_family, SOCK_DGRAM, 0)) < 0) {
228 		plog(LLV_ERROR, LOCATION, NULL,
229 			"socket (%s)\n", strerror(errno));
230 		goto err;
231 	}
232 
233 	setsockopt_bypass(s, remote->sa_family);
234 
235 	if (connect(s, remote, sysdep_sa_len(remote)) < 0) {
236 		plog(LLV_ERROR, LOCATION, NULL,
237 			"connect (%s)\n", strerror(errno));
238 		close(s);
239 		goto err;
240 	}
241 
242 	if (getsockname(s, local, &local_len) < 0) {
243 		plog(LLV_ERROR, LOCATION, NULL,
244 			"getsockname (%s)\n", strerror(errno));
245 		close(s);
246 		return NULL;
247 	}
248 
249 	close(s);
250 	return local;
251 
252     err:
253 	if (local != NULL)
254 		racoon_free(local);
255 	return NULL;
256 }
257 
258 /*
259  * Receive packet, with src/dst information.  It is assumed that necessary
260  * setsockopt() have already performed on socket.
261  */
262 int
recvfromto(s,buf,buflen,flags,from,fromlen,to,tolen)263 recvfromto(s, buf, buflen, flags, from, fromlen, to, tolen)
264 	int s;
265 	void *buf;
266 	size_t buflen;
267 	int flags;
268 	struct sockaddr *from;
269 	socklen_t *fromlen;
270 	struct sockaddr *to;
271 	u_int *tolen;
272 {
273 	int otolen;
274 	socklen_t slen;
275 	int len;
276 	union sockaddr_any sa;
277 	struct msghdr m;
278 	struct cmsghdr *cm;
279 	struct iovec iov[2];
280 	u_char cmsgbuf[256];
281 #if defined(INET6) && defined(INET6_ADVAPI)
282 	struct in6_pktinfo *pi;
283 #endif /*INET6_ADVAPI*/
284 	struct sockaddr_in *sin;
285 #ifdef INET6
286 	struct sockaddr_in6 *sin6;
287 #endif
288 
289 	slen = sizeof(sa);
290 	if (getsockname(s, &sa.sa, &slen) < 0) {
291 		plog(LLV_ERROR, LOCATION, NULL,
292 			"getsockname (%s)\n", strerror(errno));
293 		return -1;
294 	}
295 
296 	m.msg_name = (caddr_t)from;
297 	m.msg_namelen = *fromlen;
298 	iov[0].iov_base = (caddr_t)buf;
299 	iov[0].iov_len = buflen;
300 	m.msg_iov = iov;
301 	m.msg_iovlen = 1;
302 	memset(cmsgbuf, 0, sizeof(cmsgbuf));
303 	cm = (struct cmsghdr *)cmsgbuf;
304 	m.msg_control = (caddr_t)cm;
305 	m.msg_controllen = sizeof(cmsgbuf);
306 	if ((len = recvmsg(s, &m, flags)) < 0) {
307 		plog(LLV_ERROR, LOCATION, NULL,
308 			"recvmsg (%s)\n", strerror(errno));
309 		return -1;
310 	}
311 	*fromlen = m.msg_namelen;
312 
313 	otolen = *tolen;
314 	*tolen = 0;
315 	for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(&m);
316 	     m.msg_controllen != 0 && cm;
317 	     cm = (struct cmsghdr *)CMSG_NXTHDR(&m, cm)) {
318 #if 0
319 		plog(LLV_ERROR, LOCATION, NULL,
320 			"cmsg %d %d\n", cm->cmsg_level, cm->cmsg_type);)
321 #endif
322 #if defined(INET6) && defined(INET6_ADVAPI)
323 		if (sa.sa.sa_family == AF_INET6
324 		 && cm->cmsg_level == IPPROTO_IPV6
325 		 && cm->cmsg_type == IPV6_PKTINFO
326 		 && otolen >= sizeof(*sin6)) {
327 			pi = (struct in6_pktinfo *)(CMSG_DATA(cm));
328 			*tolen = sizeof(*sin6);
329 			sin6 = (struct sockaddr_in6 *)to;
330 			memset(sin6, 0, sizeof(*sin6));
331 			sin6->sin6_family = AF_INET6;
332 #ifndef __linux__
333 			sin6->sin6_len = sizeof(*sin6);
334 #endif
335 			memcpy(&sin6->sin6_addr, &pi->ipi6_addr,
336 				sizeof(sin6->sin6_addr));
337 			/* XXX other cases, such as site-local? */
338 			if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
339 				sin6->sin6_scope_id = pi->ipi6_ifindex;
340 			else
341 				sin6->sin6_scope_id = 0;
342 			sin6->sin6_port = sa.sin6.sin6_port;
343 			otolen = -1;	/* "to" already set */
344 			continue;
345 		}
346 #endif
347 #ifdef __linux__
348 		if (sa.sa.sa_family == AF_INET
349 		 && cm->cmsg_level == IPPROTO_IP
350 		 && cm->cmsg_type == IP_PKTINFO
351 		 && otolen >= sizeof(sin)) {
352 			struct in_pktinfo *pi = (struct in_pktinfo *)(CMSG_DATA(cm));
353 			*tolen = sizeof(*sin);
354 			sin = (struct sockaddr_in *)to;
355 			memset(sin, 0, sizeof(*sin));
356 			sin->sin_family = AF_INET;
357 			memcpy(&sin->sin_addr, &pi->ipi_addr,
358 				sizeof(sin->sin_addr));
359 			sin->sin_port = sa.sin.sin_port;
360 			otolen = -1;	/* "to" already set */
361 			continue;
362 		}
363 #endif
364 #if defined(INET6) && defined(IPV6_RECVDSTADDR)
365 		if (sa.sa.sa_family == AF_INET6
366 		      && cm->cmsg_level == IPPROTO_IPV6
367 		      && cm->cmsg_type == IPV6_RECVDSTADDR
368 		      && otolen >= sizeof(*sin6)) {
369 			*tolen = sizeof(*sin6);
370 			sin6 = (struct sockaddr_in6 *)to;
371 			memset(sin6, 0, sizeof(*sin6));
372 			sin6->sin6_family = AF_INET6;
373 			sin6->sin6_len = sizeof(*sin6);
374 			memcpy(&sin6->sin6_addr, CMSG_DATA(cm),
375 				sizeof(sin6->sin6_addr));
376 			sin6->sin6_port = sa.sin6.sin6_port;
377 			otolen = -1;	/* "to" already set */
378 			continue;
379 		}
380 #endif
381 #ifndef __linux__
382 		if (sa.sa.sa_family == AF_INET
383 		 && cm->cmsg_level == IPPROTO_IP
384 		 && cm->cmsg_type == IP_RECVDSTADDR
385 		 && otolen >= sizeof(*sin)) {
386 			*tolen = sizeof(*sin);
387 			sin = (struct sockaddr_in *)to;
388 			memset(sin, 0, sizeof(*sin));
389 			sin->sin_family = AF_INET;
390 			sin->sin_len = sizeof(*sin);
391 			memcpy(&sin->sin_addr, CMSG_DATA(cm),
392 				sizeof(sin->sin_addr));
393 			sin->sin_port = sa.sin.sin_port;
394 			otolen = -1;	/* "to" already set */
395 			continue;
396 		}
397 #endif
398 	}
399 
400 	return len;
401 }
402 
403 /* send packet, with fixing src/dst address pair. */
404 int
sendfromto(s,buf,buflen,src,dst,cnt)405 sendfromto(s, buf, buflen, src, dst, cnt)
406 	int s, cnt;
407 	const void *buf;
408 	size_t buflen;
409 	struct sockaddr *src;
410 	struct sockaddr *dst;
411 {
412 	struct sockaddr_storage ss;
413 	socklen_t slen;
414 	int len = 0;
415 	int i;
416 
417 	if (src->sa_family != dst->sa_family) {
418 		plog(LLV_ERROR, LOCATION, NULL,
419 			"address family mismatch\n");
420 		return -1;
421 	}
422 
423 	slen = sizeof(ss);
424 	if (getsockname(s, (struct sockaddr *)&ss, &slen) < 0) {
425 		plog(LLV_ERROR, LOCATION, NULL,
426 			"getsockname (%s)\n", strerror(errno));
427 		return -1;
428 	}
429 
430 	plog(LLV_DEBUG, LOCATION, NULL,
431 		"sockname %s\n", saddr2str((struct sockaddr *)&ss));
432 	plog(LLV_DEBUG, LOCATION, NULL,
433 		"send packet from %s\n", saddr2str(src));
434 	plog(LLV_DEBUG, LOCATION, NULL,
435 		"send packet to %s\n", saddr2str(dst));
436 
437 	if (src->sa_family != ss.ss_family) {
438 		plog(LLV_ERROR, LOCATION, NULL,
439 			"address family mismatch\n");
440 		return -1;
441 	}
442 
443 	switch (src->sa_family) {
444 #if defined(INET6) && defined(INET6_ADVAPI)
445 // XXX: This block wasn't compiled on Linux - does it work?
446 	case AF_INET6:
447 	    {
448 		struct msghdr m;
449 		struct cmsghdr *cm;
450 		struct iovec iov[2];
451 		u_char cmsgbuf[256];
452 		struct in6_pktinfo *pi;
453 		int ifindex;
454 		struct sockaddr_in6 src6, dst6;
455 
456 		memcpy(&src6, src, sizeof(src6));
457 		memcpy(&dst6, dst, sizeof(dst6));
458 
459 		/* XXX take care of other cases, such as site-local */
460 		ifindex = 0;
461 		if (IN6_IS_ADDR_LINKLOCAL(&src6.sin6_addr)
462 		 || IN6_IS_ADDR_MULTICAST(&src6.sin6_addr)) {
463 			ifindex = src6.sin6_scope_id;	/*???*/
464 		}
465 
466 		/* XXX some sanity check on dst6.sin6_scope_id */
467 
468 		/* flowinfo for IKE?  mmm, maybe useful but for now make it 0 */
469 		src6.sin6_flowinfo = dst6.sin6_flowinfo = 0;
470 
471 		memset(&m, 0, sizeof(m));
472 		m.msg_name = (caddr_t)&dst6;
473 		m.msg_namelen = sizeof(dst6);
474 		iov[0].iov_base = (char *)buf;
475 		iov[0].iov_len = buflen;
476 		m.msg_iov = iov;
477 		m.msg_iovlen = 1;
478 
479 		memset(cmsgbuf, 0, sizeof(cmsgbuf));
480 		cm = (struct cmsghdr *)cmsgbuf;
481 		m.msg_control = (caddr_t)cm;
482 		m.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
483 
484 		cm->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
485 		cm->cmsg_level = IPPROTO_IPV6;
486 		cm->cmsg_type = IPV6_PKTINFO;
487 		pi = (struct in6_pktinfo *)CMSG_DATA(cm);
488 		memcpy(&pi->ipi6_addr, &src6.sin6_addr, sizeof(src6.sin6_addr));
489 		pi->ipi6_ifindex = ifindex;
490 
491 		plog(LLV_DEBUG, LOCATION, NULL,
492 			"src6 %s %d\n",
493 			saddr2str((struct sockaddr *)&src6),
494 			src6.sin6_scope_id);
495 		plog(LLV_DEBUG, LOCATION, NULL,
496 			"dst6 %s %d\n",
497 			saddr2str((struct sockaddr *)&dst6),
498 			dst6.sin6_scope_id);
499 
500 		for (i = 0; i < cnt; i++) {
501 			len = sendmsg(s, &m, 0 /*MSG_DONTROUTE*/);
502 			if (len < 0) {
503 				plog(LLV_ERROR, LOCATION, NULL,
504 					"sendmsg (%s)\n", strerror(errno));
505 				return -1;
506 			}
507 			plog(LLV_DEBUG, LOCATION, NULL,
508 				"%d times of %d bytes message will be sent "
509 				"to %s\n",
510 				i + 1, len, saddr2str(dst));
511 		}
512 		plogdump(LLV_DEBUG, (char *)buf, buflen);
513 
514 		return len;
515 	    }
516 #endif
517 #ifdef __linux__
518 	case AF_INET:
519 	    {
520 		struct msghdr m;
521 		struct cmsghdr *cm;
522 		struct iovec iov[2];
523 		u_char cmsgbuf[256];
524 		struct in_pktinfo *pi;
525 		int ifindex = 0;
526 		struct sockaddr_in src6, dst6;
527 
528 		memcpy(&src6, src, sizeof(src6));
529 		memcpy(&dst6, dst, sizeof(dst6));
530 
531 		memset(&m, 0, sizeof(m));
532 		m.msg_name = (caddr_t)&dst6;
533 		m.msg_namelen = sizeof(dst6);
534 		iov[0].iov_base = (char *)buf;
535 		iov[0].iov_len = buflen;
536 		m.msg_iov = iov;
537 		m.msg_iovlen = 1;
538 
539 		memset(cmsgbuf, 0, sizeof(cmsgbuf));
540 		cm = (struct cmsghdr *)cmsgbuf;
541 		m.msg_control = (caddr_t)cm;
542 		m.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo));
543 
544 		cm->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
545 		cm->cmsg_level = IPPROTO_IP;
546 		cm->cmsg_type = IP_PKTINFO;
547 		pi = (struct in_pktinfo *)CMSG_DATA(cm);
548 		memcpy(&pi->ipi_spec_dst, &src6.sin_addr, sizeof(src6.sin_addr));
549 		pi->ipi_ifindex = ifindex;
550 
551 		plog(LLV_DEBUG, LOCATION, NULL,
552 			"src4 %s\n",
553 			saddr2str((struct sockaddr *)&src6));
554 		plog(LLV_DEBUG, LOCATION, NULL,
555 			"dst4 %s\n",
556 			saddr2str((struct sockaddr *)&dst6));
557 
558 		for (i = 0; i < cnt; i++) {
559 			len = sendmsg(s, &m, 0 /*MSG_DONTROUTE*/);
560 			if (len < 0) {
561 				plog(LLV_ERROR, LOCATION, NULL,
562 					"sendmsg (%s)\n", strerror(errno));
563 				return -1;
564 			}
565 			plog(LLV_DEBUG, LOCATION, NULL,
566 				"%d times of %d bytes message will be sent "
567 				"to %s\n",
568 				i + 1, len, saddr2str(dst));
569 		}
570 		plogdump(LLV_DEBUG, (char *)buf, buflen);
571 
572 		return len;
573 	    }
574 #endif /* __linux__ */
575 	default:
576 	    {
577 		int needclose = 0;
578 		int sendsock;
579 
580 		if (ss.ss_family == src->sa_family && memcmp(&ss, src, sysdep_sa_len(src)) == 0) {
581 			sendsock = s;
582 			needclose = 0;
583 		} else {
584 			int yes = 1;
585 			/*
586 			 * Use newly opened socket for sending packets.
587 			 * NOTE: this is unsafe, because if the peer is quick enough
588 			 * the packet from the peer may be queued into sendsock.
589 			 * Better approach is to prepare bind'ed udp sockets for
590 			 * each of the interface addresses.
591 			 */
592 			sendsock = SOCKET(src->sa_family, SOCK_DGRAM, 0);
593 			if (sendsock < 0) {
594 				plog(LLV_ERROR, LOCATION, NULL,
595 					"socket (%s)\n", strerror(errno));
596 				return -1;
597 			}
598 			if (setsockopt(sendsock, SOL_SOCKET,
599 #ifdef __linux__
600 				       SO_REUSEADDR,
601 #else
602 				       SO_REUSEPORT,
603 #endif
604 				       (void *)&yes, sizeof(yes)) < 0) {
605 				plog(LLV_ERROR, LOCATION, NULL,
606 					"setsockopt SO_REUSEPORT (%s)\n",
607 					strerror(errno));
608 				close(sendsock);
609 				return -1;
610 			}
611 #ifdef IPV6_USE_MIN_MTU
612 			if (src->sa_family == AF_INET6 &&
613 			    setsockopt(sendsock, IPPROTO_IPV6, IPV6_USE_MIN_MTU,
614 			    (void *)&yes, sizeof(yes)) < 0) {
615 				plog(LLV_ERROR, LOCATION, NULL,
616 					"setsockopt IPV6_USE_MIN_MTU (%s)\n",
617 					strerror(errno));
618 				close(sendsock);
619 				return -1;
620 			}
621 #endif
622 			if (setsockopt_bypass(sendsock, src->sa_family) < 0) {
623 				close(sendsock);
624 				return -1;
625 			}
626 
627 			if (BIND(sendsock, (struct sockaddr *)src,
628 				 sysdep_sa_len(src)) < 0) {
629 				plog(LLV_ERROR, LOCATION, NULL,
630 					"bind 1 (%s)\n", strerror(errno));
631 				close(sendsock);
632 				return -1;
633 			}
634 			needclose = 1;
635 		}
636 
637 		for (i = 0; i < cnt; i++) {
638 			len = sendto(sendsock, buf, buflen, 0, dst, sysdep_sa_len(dst));
639 			if (len < 0) {
640 				plog(LLV_ERROR, LOCATION, NULL,
641 					"sendto (%s)\n", strerror(errno));
642 				if (needclose)
643 					close(sendsock);
644 				return len;
645 			}
646 			plog(LLV_DEBUG, LOCATION, NULL,
647 				"%d times of %d bytes message will be sent "
648 				"to %s\n",
649 				i + 1, len, saddr2str(dst));
650 		}
651 		plogdump(LLV_DEBUG, (char *)buf, buflen);
652 
653 		if (needclose)
654 			close(sendsock);
655 
656 		return len;
657 	    }
658 	}
659 }
660 
661 int
setsockopt_bypass(so,family)662 setsockopt_bypass(so, family)
663 	int so, family;
664 {
665 	int level;
666 	char *buf;
667 	char *policy;
668 
669 	switch (family) {
670 	case AF_INET:
671 		level = IPPROTO_IP;
672 		break;
673 #ifdef INET6
674 	case AF_INET6:
675 		level = IPPROTO_IPV6;
676 		break;
677 #endif
678 	default:
679 		plog(LLV_ERROR, LOCATION, NULL,
680 			"unsupported address family %d\n", family);
681 		return -1;
682 	}
683 
684 	policy = "in bypass";
685 	buf = ipsec_set_policy(policy, strlen(policy));
686 	if (buf == NULL) {
687 		plog(LLV_ERROR, LOCATION, NULL,
688 			"ipsec_set_policy (%s)\n",
689 			ipsec_strerror());
690 		return -1;
691 	}
692 	if (SETSOCKOPT(so, level,
693 	               (level == IPPROTO_IP ?
694 	                         IP_IPSEC_POLICY : IPV6_IPSEC_POLICY),
695 	               buf, ipsec_get_policylen(buf)) < 0) {
696 		plog(LLV_ERROR, LOCATION, NULL,
697 			"setsockopt IP_IPSEC_POLICY (%s)\n",
698 			strerror(errno));
699 		return -1;
700 	}
701 	racoon_free(buf);
702 
703 	policy = "out bypass";
704 	buf = ipsec_set_policy(policy, strlen(policy));
705 	if (buf == NULL) {
706 		plog(LLV_ERROR, LOCATION, NULL,
707 			"ipsec_set_policy (%s)\n",
708 			ipsec_strerror());
709 		return -1;
710 	}
711 	if (SETSOCKOPT(so, level,
712 	               (level == IPPROTO_IP ?
713 	                         IP_IPSEC_POLICY : IPV6_IPSEC_POLICY),
714 	               buf, ipsec_get_policylen(buf)) < 0) {
715 		plog(LLV_ERROR, LOCATION, NULL,
716 			"setsockopt IP_IPSEC_POLICY (%s)\n",
717 			strerror(errno));
718 		return -1;
719 	}
720 	racoon_free(buf);
721 
722 	return 0;
723 }
724 
725 #endif
726 
727 struct sockaddr *
newsaddr(len)728 newsaddr(len)
729 	int len;
730 {
731 	struct sockaddr *new;
732 
733 	if ((new = racoon_calloc(1, len)) == NULL) {
734 		plog(LLV_ERROR, LOCATION, NULL,
735 			"%s\n", strerror(errno));
736 		goto out;
737 	}
738 
739 #ifdef __linux__
740 	if (len == sizeof (struct sockaddr_in6))
741 		new->sa_family = AF_INET6;
742 	else
743 		new->sa_family = AF_INET;
744 #else
745 	/* initial */
746 	new->sa_len = len;
747 #endif
748 out:
749 	return new;
750 }
751 
752 struct sockaddr *
dupsaddr(src)753 dupsaddr(src)
754 	struct sockaddr *src;
755 {
756 	struct sockaddr *dst;
757 
758 	dst = racoon_calloc(1, sysdep_sa_len(src));
759 	if (dst == NULL) {
760 		plog(LLV_ERROR, LOCATION, NULL,
761 			"%s\n", strerror(errno));
762 		return NULL;
763 	}
764 
765 	memcpy(dst, src, sysdep_sa_len(src));
766 
767 	return dst;
768 }
769 
770 char *
saddr2str(saddr)771 saddr2str(saddr)
772 	const struct sockaddr *saddr;
773 {
774 	static char buf[NI_MAXHOST + NI_MAXSERV + 10];
775 	char addr[NI_MAXHOST], port[NI_MAXSERV];
776 
777 	if (saddr == NULL)
778 		return NULL;
779 
780 	if (saddr->sa_family == AF_UNSPEC)
781 		snprintf (buf, sizeof(buf), "%s", "anonymous");
782 	else {
783 		GETNAMEINFO(saddr, addr, port);
784 		snprintf(buf, sizeof(buf), "%s[%s]", addr, port);
785 	}
786 
787 	return buf;
788 }
789 
790 char *
saddrwop2str(saddr)791 saddrwop2str(saddr)
792 	const struct sockaddr *saddr;
793 {
794 	static char buf[NI_MAXHOST + NI_MAXSERV + 10];
795 	char addr[NI_MAXHOST];
796 
797 	if (saddr == NULL)
798 		return NULL;
799 
800 	GETNAMEINFO_NULL(saddr, addr);
801 	snprintf(buf, sizeof(buf), "%s", addr);
802 
803 	return buf;
804 }
805 
806 char *
naddrwop2str(const struct netaddr * naddr)807 naddrwop2str(const struct netaddr *naddr)
808 {
809 	static char buf[NI_MAXHOST + 10];
810 	static const struct sockaddr sa_any;	/* this is initialized to all zeros */
811 
812 	if (naddr == NULL)
813 		return NULL;
814 
815 	if (memcmp(&naddr->sa, &sa_any, sizeof(sa_any)) == 0)
816 		snprintf(buf, sizeof(buf), "%s", "any");
817 	else {
818 		snprintf(buf, sizeof(buf), "%s", saddrwop2str(&naddr->sa.sa));
819 		snprintf(&buf[strlen(buf)], sizeof(buf) - strlen(buf), "/%ld", naddr->prefix);
820 	}
821 	return buf;
822 }
823 
824 char *
naddrwop2str_fromto(const char * format,const struct netaddr * saddr,const struct netaddr * daddr)825 naddrwop2str_fromto(const char *format, const struct netaddr *saddr,
826 		    const struct netaddr *daddr)
827 {
828 	static char buf[2*(NI_MAXHOST + NI_MAXSERV + 10) + 100];
829 	char *src, *dst;
830 
831 	src = racoon_strdup(naddrwop2str(saddr));
832 	dst = racoon_strdup(naddrwop2str(daddr));
833 	STRDUP_FATAL(src);
834 	STRDUP_FATAL(dst);
835 	/* WARNING: Be careful about the format string! Don't
836 	   ever pass in something that a user can modify!!! */
837 	snprintf (buf, sizeof(buf), format, src, dst);
838 	racoon_free (src);
839 	racoon_free (dst);
840 
841 	return buf;
842 }
843 
844 char *
saddr2str_fromto(format,saddr,daddr)845 saddr2str_fromto(format, saddr, daddr)
846 	const char *format;
847 	const struct sockaddr *saddr;
848 	const struct sockaddr *daddr;
849 {
850 	static char buf[2*(NI_MAXHOST + NI_MAXSERV + 10) + 100];
851 	char *src, *dst;
852 
853 	src = racoon_strdup(saddr2str(saddr));
854 	dst = racoon_strdup(saddr2str(daddr));
855 	STRDUP_FATAL(src);
856 	STRDUP_FATAL(dst);
857 	/* WARNING: Be careful about the format string! Don't
858 	   ever pass in something that a user can modify!!! */
859 	snprintf (buf, sizeof(buf), format, src, dst);
860 	racoon_free (src);
861 	racoon_free (dst);
862 
863 	return buf;
864 }
865 
866 struct sockaddr *
str2saddr(host,port)867 str2saddr(host, port)
868 	char *host;
869 	char *port;
870 {
871 	struct addrinfo hints, *res;
872 	struct sockaddr *saddr;
873 	int error;
874 
875 	memset(&hints, 0, sizeof(hints));
876 	hints.ai_family = PF_UNSPEC;
877 	hints.ai_socktype = SOCK_DGRAM;
878 	hints.ai_flags = AI_NUMERICHOST;
879 	error = getaddrinfo(host, port, &hints, &res);
880 	if (error != 0) {
881 		plog(LLV_ERROR, LOCATION, NULL,
882 			"getaddrinfo(%s%s%s): %s\n",
883 			host, port ? "," : "", port ? port : "",
884 			gai_strerror(error));
885 		return NULL;
886 	}
887 	if (res->ai_next != NULL) {
888 		plog(LLV_WARNING, LOCATION, NULL,
889 			"getaddrinfo(%s%s%s): "
890 			"resolved to multiple address, "
891 			"taking the first one\n",
892 			host, port ? "," : "", port ? port : "");
893 	}
894 	saddr = racoon_malloc(res->ai_addrlen);
895 	if (saddr == NULL) {
896 		plog(LLV_ERROR, LOCATION, NULL,
897 			"failed to allocate buffer.\n");
898 		freeaddrinfo(res);
899 		return NULL;
900 	}
901 	memcpy(saddr, res->ai_addr, res->ai_addrlen);
902 	freeaddrinfo(res);
903 
904 	return saddr;
905 }
906 
907 void
mask_sockaddr(a,b,l)908 mask_sockaddr(a, b, l)
909 	struct sockaddr *a;
910 	const struct sockaddr *b;
911 	size_t l;
912 {
913 	size_t i;
914 	u_int8_t *p, alen;
915 
916 	switch (b->sa_family) {
917 	case AF_INET:
918 		alen = sizeof(struct in_addr);
919 		p = (u_int8_t *)&((struct sockaddr_in *)a)->sin_addr;
920 		break;
921 #ifdef INET6
922 	case AF_INET6:
923 		alen = sizeof(struct in6_addr);
924 		p = (u_int8_t *)&((struct sockaddr_in6 *)a)->sin6_addr;
925 		break;
926 #endif
927 	default:
928 		plog(LLV_ERROR, LOCATION, NULL,
929 			"invalid family: %d\n", b->sa_family);
930 		exit(1);
931 	}
932 
933 	if ((alen << 3) < l) {
934 		plog(LLV_ERROR, LOCATION, NULL,
935 			"unexpected inconsistency: %d %zu\n", b->sa_family, l);
936 		exit(1);
937 	}
938 
939 	memcpy(a, b, sysdep_sa_len(b));
940 	p[l / 8] &= (0xff00 >> (l % 8)) & 0xff;
941 	for (i = l / 8 + 1; i < alen; i++)
942 		p[i] = 0x00;
943 }
944 
945 /* Compute a score describing how "accurate" a netaddr is for a given sockaddr.
946  * Examples:
947  * 	Return values for address 10.20.30.40 [port 500] and given netaddresses...
948  * 		10.10.0.0/16	=> -1	... doesn't match
949  * 		0.0.0.0/0	=> 0	... matches, but only 0 bits.
950  * 		10.20.0.0/16	=> 16	... 16 bits match
951  * 		10.20.30.0/24	=> 24	... guess what ;-)
952  * 		10.20.30.40/32	=> 32	... whole address match
953  * 		10.20.30.40:500	=> 33	... both address and port match
954  * 		10.20.30.40:501	=> -1	... port doesn't match and isn't 0 (=any)
955  */
956 int
naddr_score(const struct netaddr * naddr,const struct sockaddr * saddr)957 naddr_score(const struct netaddr *naddr, const struct sockaddr *saddr)
958 {
959 	static const struct netaddr naddr_any;	/* initialized to all-zeros */
960 	struct sockaddr sa;
961 	u_int16_t naddr_port, saddr_port;
962 	int port_score;
963 
964 	if (!naddr || !saddr) {
965 		plog(LLV_ERROR, LOCATION, NULL,
966 		     "Call with null args: naddr=%p, saddr=%p\n",
967 		     naddr, saddr);
968 		return -1;
969 	}
970 
971 	/* Wildcard address matches, but only 0 bits. */
972 	if (memcmp(naddr, &naddr_any, sizeof(naddr_any)) == 0)
973 		return 0;
974 
975 	/* If families don't match we really can't do much... */
976 	if (naddr->sa.sa.sa_family != saddr->sa_family)
977 		return -1;
978 
979 	/* If port check fail don't bother to check addresses. */
980 	naddr_port = extract_port(&naddr->sa.sa);
981 	saddr_port = extract_port(saddr);
982 	if (naddr_port == 0 || saddr_port == 0)	/* wildcard match */
983 		port_score = 0;
984 	else if (naddr_port == saddr_port)	/* exact match */
985 		port_score = 1;
986 	else					/* mismatch :-) */
987 		return -1;
988 
989 	/* Here it comes - compare network addresses. */
990 	mask_sockaddr(&sa, saddr, naddr->prefix);
991 	if (loglevel >= LLV_DEBUG) {	/* debug only */
992 		char *a1, *a2, *a3;
993 		a1 = racoon_strdup(naddrwop2str(naddr));
994 		a2 = racoon_strdup(saddrwop2str(saddr));
995 		a3 = racoon_strdup(saddrwop2str(&sa));
996 		STRDUP_FATAL(a1);
997 		STRDUP_FATAL(a2);
998 		STRDUP_FATAL(a3);
999 		plog(LLV_DEBUG, LOCATION, NULL,
1000 		     "naddr=%s, saddr=%s (masked=%s)\n",
1001 		     a1, a2, a3);
1002 		free(a1);
1003 		free(a2);
1004 		free(a3);
1005 	}
1006 	if (cmpsaddr(&sa, &naddr->sa.sa) <= CMPSADDR_WOP_MATCH)
1007 		return naddr->prefix + port_score;
1008 
1009 	return -1;
1010 }
1011 
1012 /* Some useful functions for sockaddr port manipulations. */
1013 u_int16_t
extract_port(const struct sockaddr * addr)1014 extract_port (const struct sockaddr *addr)
1015 {
1016   u_int16_t port = 0;
1017 
1018   if (!addr)
1019     return port;
1020 
1021   switch (addr->sa_family) {
1022     case AF_UNSPEC:
1023       break;
1024     case AF_INET:
1025       port = ((struct sockaddr_in *)addr)->sin_port;
1026       break;
1027     case AF_INET6:
1028       port = ((struct sockaddr_in6 *)addr)->sin6_port;
1029       break;
1030     default:
1031       plog(LLV_ERROR, LOCATION, NULL, "unknown AF: %u\n", addr->sa_family);
1032       break;
1033   }
1034 
1035   return ntohs(port);
1036 }
1037 
1038 u_int16_t *
get_port_ptr(struct sockaddr * addr)1039 get_port_ptr (struct sockaddr *addr)
1040 {
1041   u_int16_t *port_ptr;
1042 
1043   if (!addr)
1044     return NULL;
1045 
1046   switch (addr->sa_family) {
1047     case AF_INET:
1048       port_ptr = &(((struct sockaddr_in *)addr)->sin_port);
1049       break;
1050     case AF_INET6:
1051       port_ptr = &(((struct sockaddr_in6 *)addr)->sin6_port);
1052       break;
1053     default:
1054       plog(LLV_ERROR, LOCATION, NULL, "unknown AF: %u\n", addr->sa_family);
1055       return NULL;
1056       break;
1057   }
1058 
1059   return port_ptr;
1060 }
1061 
1062 u_int16_t *
set_port(struct sockaddr * addr,u_int16_t new_port)1063 set_port (struct sockaddr *addr, u_int16_t new_port)
1064 {
1065   u_int16_t *port_ptr;
1066 
1067   port_ptr = get_port_ptr (addr);
1068 
1069   if (port_ptr)
1070     *port_ptr = htons(new_port);
1071 
1072   return port_ptr;
1073 }
1074