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