Annotation of embedaddon/ipsec-tools/src/racoon/sockmisc.c, revision 1.1.1.1
1.1 misho 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
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: /* get local address against the destination. */
146: struct sockaddr *
147: getlocaladdr(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: */
197: int
198: recvfromto(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. */
339: int
340: sendfromto(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:
596: int
597: setsockopt_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:
660: struct sockaddr *
661: newsaddr(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
681: out:
682: return new;
683: }
684:
685: struct sockaddr *
686: dupsaddr(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:
703: char *
704: saddr2str(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:
723: char *
724: saddrwop2str(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:
739: char *
740: naddrwop2str(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:
757: char *
758: naddrwop2str_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:
777: char *
778: saddr2str_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:
799: struct sockaddr *
800: str2saddr(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:
840: void
841: mask_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: */
889: int
890: naddr_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. */
946: u_int16_t
947: extract_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:
971: u_int16_t *
972: get_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:
995: u_int16_t *
996: set_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: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>