]>
git.saurik.com Git - apple/ipsec.git/blob - ipsec-tools/racoon/sockmisc.c
9deb6abd5284396addd310fc405cfe6c5bf6edc8
1 /* $Id: sockmisc.c,v 1.17.4.4 2005/10/04 09:54:27 manubsd Exp $ */
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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
34 #include <sys/types.h>
35 #include <sys/param.h>
36 #include <sys/socket.h>
39 #include <netinet/in.h>
40 #ifndef HAVE_NETINET6_IPSEC
41 #include <netinet/ipsec.h>
43 #include <netinet6/ipsec.h>
46 #if defined(INET6) && !defined(INET6_ADVAPI) && \
47 defined(IP_RECVDSTADDR) && !defined(IPV6_RECVDSTADDR)
48 #define IPV6_RECVDSTADDR IP_RECVDSTADDR
69 #ifndef IP_IPSEC_POLICY
70 #define IP_IPSEC_POLICY 16 /* XXX: from linux/in.h */
73 #ifndef IPV6_IPSEC_POLICY
74 #define IPV6_IPSEC_POLICY 34 /* XXX: from linux/???.h per
75 "Tom Lendacky" <toml@us.ibm.com> */
78 const int niflags
= 0;
81 * compare two sockaddr without port number.
86 cmpsaddrwop(addr1
, addr2
)
87 const struct sockaddr_storage
*addr1
;
88 const struct sockaddr_storage
*addr2
;
92 if (addr1
== 0 && addr2
== 0)
94 if (addr1
== 0 || addr2
== 0)
97 if (addr1
->ss_len
!= addr2
->ss_len
98 || addr1
->ss_family
!= addr2
->ss_family
)
100 switch (addr1
->ss_family
) {
102 sa1
= (caddr_t
)&((struct sockaddr_in
*)addr1
)->sin_addr
;
103 sa2
= (caddr_t
)&((struct sockaddr_in
*)addr2
)->sin_addr
;
104 if (memcmp(sa1
, sa2
, sizeof(struct in_addr
)) != 0)
109 sa1
= (caddr_t
)&((struct sockaddr_in6
*)addr1
)->sin6_addr
;
110 sa2
= (caddr_t
)&((struct sockaddr_in6
*)addr2
)->sin6_addr
;
111 if (memcmp(sa1
, sa2
, sizeof(struct in6_addr
)) != 0)
113 if (((struct sockaddr_in6
*)addr1
)->sin6_scope_id
!=
114 ((struct sockaddr_in6
*)addr2
)->sin6_scope_id
)
126 * compare two sockaddr without port number using prefix.
131 cmpsaddrwop_withprefix(const struct sockaddr_storage
*addr1
, const struct sockaddr_storage
*addr2
, int prefix
)
136 if (addr1
== 0 && addr2
== 0)
138 if (addr1
== 0 || addr2
== 0)
141 if (addr1
->ss_len
!= addr2
->ss_len
142 || addr1
->ss_family
!= addr2
->ss_family
)
144 switch (addr1
->ss_family
) {
148 if ((((struct sockaddr_in
*)addr1
)->sin_addr
.s_addr
& htonl(mask
)) !=
149 (((struct sockaddr_in
*)addr2
)->sin_addr
.s_addr
& htonl(mask
)))
154 for (i
= 0; i
< 4; i
++) {
158 } else if (prefix
== 0)
165 if ((((struct sockaddr_in6
*)addr1
)->sin6_addr
.__u6_addr
.__u6_addr32
[i
] & htonl(mask
)) !=
166 (((struct sockaddr_in6
*)addr2
)->sin6_addr
.__u6_addr
.__u6_addr32
[i
] & htonl(mask
)))
169 if (((struct sockaddr_in6
*)addr1
)->sin6_scope_id
!=
170 ((struct sockaddr_in6
*)addr2
)->sin6_scope_id
)
183 * compare two sockaddr with port, taking care wildcard.
184 * addr1 is a subject address, addr2 is in a database entry.
189 cmpsaddrwild(addr1
, addr2
)
190 const struct sockaddr_storage
*addr1
;
191 const struct sockaddr_storage
*addr2
;
194 u_short port1
, port2
;
196 if (addr1
== 0 && addr2
== 0)
198 if (addr1
== 0 || addr2
== 0)
201 if (addr1
->ss_len
!= addr2
->ss_len
202 || addr1
->ss_family
!= addr2
->ss_family
)
205 switch (addr1
->ss_family
) {
207 sa1
= (caddr_t
)&((struct sockaddr_in
*)addr1
)->sin_addr
;
208 sa2
= (caddr_t
)&((struct sockaddr_in
*)addr2
)->sin_addr
;
209 port1
= ((struct sockaddr_in
*)addr1
)->sin_port
;
210 port2
= ((struct sockaddr_in
*)addr2
)->sin_port
;
211 if (!(port1
== IPSEC_PORT_ANY
||
212 port2
== IPSEC_PORT_ANY
||
215 if (memcmp(sa1
, sa2
, sizeof(struct in_addr
)) != 0)
220 sa1
= (caddr_t
)&((struct sockaddr_in6
*)addr1
)->sin6_addr
;
221 sa2
= (caddr_t
)&((struct sockaddr_in6
*)addr2
)->sin6_addr
;
222 port1
= ((struct sockaddr_in6
*)addr1
)->sin6_port
;
223 port2
= ((struct sockaddr_in6
*)addr2
)->sin6_port
;
224 if (!(port1
== IPSEC_PORT_ANY
||
225 port2
== IPSEC_PORT_ANY
||
228 if (memcmp(sa1
, sa2
, sizeof(struct in6_addr
)) != 0)
230 if (((struct sockaddr_in6
*)addr1
)->sin6_scope_id
!=
231 ((struct sockaddr_in6
*)addr2
)->sin6_scope_id
)
243 * compare two sockaddr with strict match on port.
248 cmpsaddrstrict(addr1
, addr2
)
249 const struct sockaddr_storage
*addr1
;
250 const struct sockaddr_storage
*addr2
;
253 u_short port1
, port2
;
255 if (addr1
== 0 && addr2
== 0)
257 if (addr1
== 0 || addr2
== 0)
260 if (addr1
->ss_len
!= addr2
->ss_len
261 || addr1
->ss_family
!= addr2
->ss_family
)
264 switch (addr1
->ss_family
) {
266 sa1
= (caddr_t
)&((struct sockaddr_in
*)addr1
)->sin_addr
;
267 sa2
= (caddr_t
)&((struct sockaddr_in
*)addr2
)->sin_addr
;
268 port1
= ((struct sockaddr_in
*)addr1
)->sin_port
;
269 port2
= ((struct sockaddr_in
*)addr2
)->sin_port
;
272 if (memcmp(sa1
, sa2
, sizeof(struct in_addr
)) != 0)
277 sa1
= (caddr_t
)&((struct sockaddr_in6
*)addr1
)->sin6_addr
;
278 sa2
= (caddr_t
)&((struct sockaddr_in6
*)addr2
)->sin6_addr
;
279 port1
= ((struct sockaddr_in6
*)addr1
)->sin6_port
;
280 port2
= ((struct sockaddr_in6
*)addr2
)->sin6_port
;
283 if (memcmp(sa1
, sa2
, sizeof(struct in6_addr
)) != 0)
285 if (((struct sockaddr_in6
*)addr1
)->sin6_scope_id
!=
286 ((struct sockaddr_in6
*)addr2
)->sin6_scope_id
)
298 * compare two sockaddr with strict match on port using prefix.
303 cmpsaddrstrict_withprefix(const struct sockaddr_storage
*addr1
, const struct sockaddr_storage
*addr2
, int prefix
)
305 u_short port1
, port2
;
309 if (addr1
== 0 && addr2
== 0)
311 if (addr1
== 0 || addr2
== 0)
314 if (addr1
->ss_len
!= addr2
->ss_len
315 || addr1
->ss_family
!= addr2
->ss_family
)
318 switch (addr1
->ss_family
) {
320 port1
= ((struct sockaddr_in
*)addr1
)->sin_port
;
321 port2
= ((struct sockaddr_in
*)addr2
)->sin_port
;
326 if ((((struct sockaddr_in
*)addr1
)->sin_addr
.s_addr
& htonl(mask
)) !=
327 (((struct sockaddr_in
*)addr2
)->sin_addr
.s_addr
& htonl(mask
)))
332 port1
= ((struct sockaddr_in6
*)addr1
)->sin6_port
;
333 port2
= ((struct sockaddr_in6
*)addr2
)->sin6_port
;
336 for (i
= 0; i
< 4; i
++) {
340 } else if (prefix
== 0)
347 if ((((struct sockaddr_in6
*)addr1
)->sin6_addr
.__u6_addr
.__u6_addr32
[i
] & htonl(mask
)) !=
348 (((struct sockaddr_in6
*)addr2
)->sin6_addr
.__u6_addr
.__u6_addr32
[i
] & htonl(mask
)))
351 if (((struct sockaddr_in6
*)addr1
)->sin6_scope_id
!=
352 ((struct sockaddr_in6
*)addr2
)->sin6_scope_id
)
364 /* get local address against the destination. */
365 struct sockaddr_storage
*
367 struct sockaddr
*remote
;
369 struct sockaddr_storage
*local
;
370 u_int local_len
= sizeof(struct sockaddr
);
371 int s
; /* for dummy connection */
373 /* allocate buffer */
374 if ((local
= racoon_calloc(1, local_len
)) == NULL
) {
375 plog(LLV_ERROR
, LOCATION
, NULL
,
376 "failed to get address buffer.\n");
380 /* get real interface received packet */
381 if ((s
= socket(remote
->sa_family
, SOCK_DGRAM
, 0)) < 0) {
382 plog(LLV_ERROR
, LOCATION
, NULL
,
383 "socket (%s)\n", strerror(errno
));
387 if (fcntl(s
, F_SETFL
, O_NONBLOCK
) == -1) {
388 plog(LLV_ERROR
, LOCATION
, NULL
,
389 "failed to put localaddr socket in non-blocking mode\n");
392 setsockopt_bypass(s
, remote
->sa_family
);
394 if (connect(s
, remote
, sysdep_sa_len(remote
)) < 0) {
395 plog(LLV_ERROR
, LOCATION
, NULL
,
396 "connect (%s)\n", strerror(errno
));
401 if (getsockname(s
, (struct sockaddr
*)local
, &local_len
) < 0) {
402 plog(LLV_ERROR
, LOCATION
, NULL
,
403 "getsockname (%s)\n", strerror(errno
));
418 * Receive packet, with src/dst information. It is assumed that necessary
419 * setsockopt() have already performed on socket.
422 recvfromto(s
, buf
, buflen
, flags
, from
, fromlen
, to
, tolen
)
427 struct sockaddr_storage
*from
;
429 struct sockaddr_storage
*to
;
434 struct sockaddr_storage ss
;
436 struct cmsghdr
*cm
, *cm_prev
;
438 u_int32_t cmsgbuf
[256/sizeof(u_int32_t
)]; // Wcast-align fix - force 32 bit alignment
439 #if defined(INET6) && defined(INET6_ADVAPI)
440 struct in6_pktinfo
*pi
;
441 #endif /*INET6_ADVAPI*/
442 struct sockaddr_in
*sin
;
444 struct sockaddr_in6
*sin6
;
448 if (getsockname(s
, (struct sockaddr
*)&ss
, &len
) < 0) {
449 plog(LLV_ERROR
, LOCATION
, NULL
,
450 "getsockname (%s)\n", strerror(errno
));
454 m
.msg_name
= (caddr_t
)from
;
455 m
.msg_namelen
= *fromlen
;
456 iov
[0].iov_base
= (caddr_t
)buf
;
457 iov
[0].iov_len
= buflen
;
460 memset(cmsgbuf
, 0, sizeof(cmsgbuf
));
461 cm
= (struct cmsghdr
*)cmsgbuf
;
462 m
.msg_control
= (caddr_t
)cm
;
463 m
.msg_controllen
= sizeof(cmsgbuf
);
464 while ((len
= recvmsg(s
, &m
, flags
)) < 0) {
467 plog(LLV_ERROR
, LOCATION
, NULL
,
468 "recvmsg (%s)\n", strerror(errno
));
474 *fromlen
= m
.msg_namelen
;
478 for (cm
= (struct cmsghdr
*)CMSG_FIRSTHDR(&m
), cm_prev
= NULL
;
479 m
.msg_controllen
!= 0 && cm
&& cm
!= cm_prev
;
480 cm_prev
= cm
, cm
= (struct cmsghdr
*)CMSG_NXTHDR(&m
, cm
)) {
482 plog(LLV_ERROR
, LOCATION
, NULL
,
483 "cmsg %d %d\n", cm
->cmsg_level
, cm
->cmsg_type
);)
485 #if defined(INET6) && defined(INET6_ADVAPI)
486 if (ss
.ss_family
== AF_INET6
487 && cm
->cmsg_level
== IPPROTO_IPV6
488 && cm
->cmsg_type
== IPV6_PKTINFO
489 && otolen
>= sizeof(*sin6
)) {
490 pi
= ALIGNED_CAST(struct in6_pktinfo
*)(CMSG_DATA(cm
));
491 *tolen
= sizeof(*sin6
);
492 sin6
= (struct sockaddr_in6
*)to
;
493 memset(sin6
, 0, sizeof(*sin6
));
494 sin6
->sin6_family
= AF_INET6
;
495 sin6
->sin6_len
= sizeof(*sin6
);
496 memcpy(&sin6
->sin6_addr
, &pi
->ipi6_addr
,
497 sizeof(sin6
->sin6_addr
));
498 /* XXX other cases, such as site-local? */
499 if (IN6_IS_ADDR_LINKLOCAL(&sin6
->sin6_addr
))
500 sin6
->sin6_scope_id
= pi
->ipi6_ifindex
;
502 sin6
->sin6_scope_id
= 0;
504 ((struct sockaddr_in6
*)&ss
)->sin6_port
;
505 otolen
= -1; /* "to" already set */
509 #if defined(INET6) && defined(IPV6_RECVDSTADDR)
510 if (ss
.ss_family
== AF_INET6
511 && cm
->cmsg_level
== IPPROTO_IPV6
512 && cm
->cmsg_type
== IPV6_RECVDSTADDR
513 && otolen
>= sizeof(*sin6
)) {
514 *tolen
= sizeof(*sin6
);
515 sin6
= (struct sockaddr_in6
*)to
;
516 memset(sin6
, 0, sizeof(*sin6
));
517 sin6
->sin6_family
= AF_INET6
;
518 sin6
->sin6_len
= sizeof(*sin6
);
519 memcpy(&sin6
->sin6_addr
, CMSG_DATA(cm
),
520 sizeof(sin6
->sin6_addr
));
522 ((struct sockaddr_in6
*)&ss
)->sin6_port
;
523 otolen
= -1; /* "to" already set */
527 if (ss
.ss_family
== AF_INET
528 && cm
->cmsg_level
== IPPROTO_IP
529 && cm
->cmsg_type
== IP_RECVDSTADDR
530 && otolen
>= sizeof(*sin
)) {
531 *tolen
= sizeof(*sin
);
532 sin
= (struct sockaddr_in
*)to
;
533 memset(sin
, 0, sizeof(*sin
));
534 sin
->sin_family
= AF_INET
;
535 sin
->sin_len
= sizeof(*sin
);
536 memcpy(&sin
->sin_addr
, CMSG_DATA(cm
),
537 sizeof(sin
->sin_addr
));
538 sin
->sin_port
= ((struct sockaddr_in
*)&ss
)->sin_port
;
539 otolen
= -1; /* "to" already set */
547 /* send packet, with fixing src/dst address pair. */
549 sendfromto(s
, buf
, buflen
, src
, dst
, cnt
)
553 struct sockaddr_storage
*src
;
554 struct sockaddr_storage
*dst
;
556 struct sockaddr_storage ss
;
560 if (src
->ss_family
!= dst
->ss_family
) {
561 plog(LLV_ERROR
, LOCATION
, NULL
,
562 "address family mismatch\n");
567 if (getsockname(s
, (struct sockaddr
*)&ss
, &len
) < 0) {
568 plog(LLV_ERROR
, LOCATION
, NULL
,
569 "getsockname (%s)\n", strerror(errno
));
573 plog(LLV_DEBUG
, LOCATION
, NULL
,
574 "sockname %s\n", saddr2str((struct sockaddr
*)&ss
));
575 plog(LLV_DEBUG
, LOCATION
, NULL
,
576 "send packet from %s\n", saddr2str((struct sockaddr
*)src
));
577 plog(LLV_DEBUG
, LOCATION
, NULL
,
578 "send packet to %s\n", saddr2str((struct sockaddr
*)dst
));
580 if (src
->ss_family
!= ss
.ss_family
) {
581 plog(LLV_ERROR
, LOCATION
, NULL
,
582 "address family mismatch\n");
586 switch (src
->ss_family
) {
587 #if defined(INET6) && defined(INET6_ADVAPI)
593 u_int32_t cmsgbuf
[256/sizeof(u_int32_t
)]; // Wcast-align fix - force 32 bit alignment
594 struct in6_pktinfo
*pi
;
596 struct sockaddr_in6 src6
, dst6
;
598 memcpy(&src6
, src
, sizeof(src6
));
599 memcpy(&dst6
, dst
, sizeof(dst6
));
601 /* XXX take care of other cases, such as site-local */
603 if (IN6_IS_ADDR_LINKLOCAL(&src6
.sin6_addr
)
604 || IN6_IS_ADDR_MULTICAST(&src6
.sin6_addr
)) {
605 ifindex
= src6
.sin6_scope_id
; /*???*/
608 /* XXX some sanity check on dst6.sin6_scope_id */
610 /* flowinfo for IKE? mmm, maybe useful but for now make it 0 */
611 src6
.sin6_flowinfo
= dst6
.sin6_flowinfo
= 0;
613 memset(&m
, 0, sizeof(m
));
614 m
.msg_name
= (caddr_t
)&dst6
;
615 m
.msg_namelen
= sizeof(dst6
);
616 iov
[0].iov_base
= (char *)buf
;
617 iov
[0].iov_len
= buflen
;
621 memset(cmsgbuf
, 0, sizeof(cmsgbuf
));
622 cm
= (struct cmsghdr
*)cmsgbuf
;
623 m
.msg_control
= (caddr_t
)cm
;
624 m
.msg_controllen
= CMSG_SPACE(sizeof(struct in6_pktinfo
));
626 cm
->cmsg_len
= CMSG_LEN(sizeof(struct in6_pktinfo
));
627 cm
->cmsg_level
= IPPROTO_IPV6
;
628 cm
->cmsg_type
= IPV6_PKTINFO
;
629 pi
= ALIGNED_CAST(struct in6_pktinfo
*)CMSG_DATA(cm
);
630 memcpy(&pi
->ipi6_addr
, &src6
.sin6_addr
, sizeof(src6
.sin6_addr
));
631 pi
->ipi6_ifindex
= ifindex
;
633 plog(LLV_DEBUG
, LOCATION
, NULL
,
635 saddr2str((struct sockaddr
*)&src6
),
637 plog(LLV_DEBUG
, LOCATION
, NULL
,
639 saddr2str((struct sockaddr
*)&dst6
),
642 for (i
= 0; i
< cnt
; i
++) {
643 len
= sendmsg(s
, &m
, 0 /*MSG_DONTROUTE*/);
645 plog(LLV_ERROR
, LOCATION
, NULL
,
646 "sendmsg (%s)\n", strerror(errno
));
647 if (errno
!= EHOSTUNREACH
&& errno
!= ENETDOWN
&& errno
!= ENETUNREACH
) {
650 // <rdar://problem/6609744> treat these failures like
651 // packet loss, in case the network interface is flaky
654 plog(LLV_DEBUG
, LOCATION
, NULL
,
655 "%d times of %d bytes message will be sent "
657 i
+ 1, len
, saddr2str((struct sockaddr
*)dst
));
659 plogdump(LLV_DEBUG
, (char *)buf
, buflen
);
669 if (ss
.ss_family
== src
->ss_family
&& memcmp(&ss
, src
, sysdep_sa_len((struct sockaddr
*)src
)) == 0) {
675 * Use newly opened socket for sending packets.
676 * NOTE: this is unsafe, because if the peer is quick enough
677 * the packet from the peer may be queued into sendsock.
678 * Better approach is to prepare bind'ed udp sockets for
679 * each of the interface addresses.
681 sendsock
= socket(src
->ss_family
, SOCK_DGRAM
, 0);
683 plog(LLV_ERROR
, LOCATION
, NULL
,
684 "socket (%s)\n", strerror(errno
));
687 if (fcntl(sendsock
, F_SETFL
, O_NONBLOCK
) == -1) {
688 plog(LLV_ERROR
, LOCATION
, NULL
,
689 "failed to put sendsock socket in non-blocking mode\n");
691 if (setsockopt(sendsock
, SOL_SOCKET
,
693 (void *)&yes
, sizeof(yes
)) < 0) {
694 plog(LLV_ERROR
, LOCATION
, NULL
,
695 "setsockopt SO_REUSEPORT (%s)\n",
700 #ifdef IPV6_USE_MIN_MTU
701 if (src
->ss_family
== AF_INET6
&&
702 setsockopt(sendsock
, IPPROTO_IPV6
, IPV6_USE_MIN_MTU
,
703 (void *)&yes
, sizeof(yes
)) < 0) {
704 plog(LLV_ERROR
, LOCATION
, NULL
,
705 "setsockopt IPV6_USE_MIN_MTU (%s)\n",
711 if (setsockopt_bypass(sendsock
, src
->ss_family
) < 0) {
716 if (bind(sendsock
, (struct sockaddr
*)src
, sysdep_sa_len((struct sockaddr
*)src
)) < 0) {
717 plog(LLV_ERROR
, LOCATION
, NULL
,
718 "bind 1 (%s)\n", strerror(errno
));
725 for (i
= 0; i
< cnt
; i
++) {
726 len
= sendto(sendsock
, buf
, buflen
, 0, (struct sockaddr
*)dst
, sysdep_sa_len((struct sockaddr
*)dst
));
728 plog(LLV_ERROR
, LOCATION
, NULL
,
729 "sendto (%s)\n", strerror(errno
));
730 if (errno
!= EHOSTUNREACH
&& errno
!= ENETDOWN
&& errno
!= ENETUNREACH
) {
735 plog(LLV_ERROR
, LOCATION
, NULL
,
736 "treating socket error (%s) like packet loss\n", strerror(errno
));
737 // else treat these failures like a packet loss
740 plog(LLV_DEBUG
, LOCATION
, NULL
,
741 "%d times of %d bytes message will be sent "
743 i
+ 1, len
, saddr2str((struct sockaddr
*)dst
));
745 plogdump(LLV_DEBUG
, (char *)buf
, buflen
);
756 setsockopt_bypass(so
, family
)
769 level
= IPPROTO_IPV6
;
773 plog(LLV_ERROR
, LOCATION
, NULL
,
774 "unsupported address family %d\n", family
);
778 policy
= "in bypass";
779 buf
= ipsec_set_policy(policy
, strlen(policy
));
781 plog(LLV_ERROR
, LOCATION
, NULL
,
782 "ipsec_set_policy (%s)\n",
786 if (setsockopt(so
, level
,
787 (level
== IPPROTO_IP
?
788 IP_IPSEC_POLICY
: IPV6_IPSEC_POLICY
),
789 buf
, ipsec_get_policylen(buf
)) < 0) {
790 plog(LLV_ERROR
, LOCATION
, NULL
,
791 "setsockopt IP_IPSEC_POLICY (%s)\n",
797 policy
= "out bypass";
798 buf
= ipsec_set_policy(policy
, strlen(policy
));
800 plog(LLV_ERROR
, LOCATION
, NULL
,
801 "ipsec_set_policy (%s)\n",
805 if (setsockopt(so
, level
,
806 (level
== IPPROTO_IP
?
807 IP_IPSEC_POLICY
: IPV6_IPSEC_POLICY
),
808 buf
, ipsec_get_policylen(buf
)) < 0) {
809 plog(LLV_ERROR
, LOCATION
, NULL
,
810 "setsockopt IP_IPSEC_POLICY (%s)\n",
819 struct sockaddr_storage
*
823 struct sockaddr_storage
*new;
825 if ((new = racoon_calloc(1, len
)) == NULL
) {
826 plog(LLV_ERROR
, LOCATION
, NULL
,
827 "%s\n", strerror(errno
));
836 struct sockaddr_storage
*
838 struct sockaddr
*src
;
840 struct sockaddr_storage
*dst
;
842 dst
= racoon_calloc(1, sysdep_sa_len(src
));
844 plog(LLV_ERROR
, LOCATION
, NULL
,
845 "%s\n", strerror(errno
));
849 memcpy(dst
, src
, sysdep_sa_len(src
));
856 const struct sockaddr
*saddr
;
858 static char buf
[NI_MAXHOST
+ NI_MAXSERV
+ 10];
859 char addr
[NI_MAXHOST
], port
[NI_MAXSERV
];
866 if (saddr
->sa_family
== AF_UNSPEC
)
867 snprintf (buf
, sizeof(buf
), "%s", "anonymous");
869 GETNAMEINFO(saddr
, addr
, port
);
870 snprintf(buf
, sizeof(buf
), "%s[%s]", addr
, port
);
877 saddr2str_with_prefix(saddr
, prefix
)
878 const struct sockaddr
*saddr
;
881 static char buf
[NI_MAXHOST
+ NI_MAXSERV
+ 10];
882 char addr
[NI_MAXHOST
], port
[NI_MAXSERV
];
889 if (saddr
->sa_family
== AF_UNSPEC
)
890 snprintf (buf
, sizeof(buf
), "%s", "anonymous");
892 GETNAMEINFO(saddr
, addr
, port
);
893 snprintf(buf
, sizeof(buf
), "%s/%d[%s]", addr
, prefix
, port
);
902 const struct sockaddr
*saddr
;
904 static char buf
[NI_MAXHOST
+ NI_MAXSERV
+ 10];
905 char addr
[NI_MAXHOST
];
912 GETNAMEINFO_NULL(saddr
, addr
);
913 snprintf(buf
, sizeof(buf
), "%s", addr
);
919 naddrwop2str(const struct netaddr
*naddr
)
921 static char buf
[NI_MAXHOST
+ 10];
922 static const struct sockaddr sa_any
; /* this is initialized to all zeros */
929 if (memcmp(&naddr
->sa
, &sa_any
, sizeof(sa_any
)) == 0)
930 snprintf(buf
, sizeof(buf
), "%s", "any");
932 snprintf(buf
, sizeof(buf
), "%s", saddrwop2str((struct sockaddr
*)&naddr
->sa
.sa
));
933 snprintf(&buf
[strlen(buf
)], sizeof(buf
) - strlen(buf
), "/%ld", naddr
->prefix
);
939 naddrwop2str_fromto(const char *format
, const struct netaddr
*saddr
,
940 const struct netaddr
*daddr
)
942 static char buf
[2*(NI_MAXHOST
+ NI_MAXSERV
+ 10) + 100];
945 src
= racoon_strdup(naddrwop2str(saddr
));
946 dst
= racoon_strdup(naddrwop2str(daddr
));
949 /* WARNING: Be careful about the format string! Don't
950 ever pass in something that a user can modify!!! */
951 snprintf (buf
, sizeof(buf
), format
, src
, dst
);
959 saddr2str_fromto(format
, saddr
, daddr
)
961 const struct sockaddr
*saddr
;
962 const struct sockaddr
*daddr
;
964 static char buf
[2*(NI_MAXHOST
+ NI_MAXSERV
+ 10) + 100];
968 src
= racoon_strdup(saddr2str(saddr
));
974 dst
= racoon_strdup(saddr2str(daddr
));
979 /* WARNING: Be careful about the format string! Don't
980 ever pass in something that a user can modify!!! */
981 snprintf (buf
, sizeof(buf
), format
, src
? src
:"[null]", dst
? dst
:"[null]");
992 struct sockaddr_storage
*
993 str2saddr(host
, port
)
997 struct addrinfo hints
, *res
;
998 struct sockaddr_storage
*saddr
;
1001 memset(&hints
, 0, sizeof(hints
));
1002 hints
.ai_family
= PF_UNSPEC
;
1003 hints
.ai_socktype
= SOCK_DGRAM
;
1004 hints
.ai_flags
= AI_NUMERICHOST
;
1005 error
= getaddrinfo(host
, port
, &hints
, &res
);
1007 plog(LLV_ERROR
, LOCATION
, NULL
,
1008 "getaddrinfo(%s%s%s): %s\n",
1009 host
, port
? "," : "", port
? port
: "",
1010 gai_strerror(error
));
1013 if (res
->ai_next
!= NULL
) {
1014 plog(LLV_WARNING
, LOCATION
, NULL
,
1015 "getaddrinfo(%s%s%s): "
1016 "resolved to multiple address, "
1017 "taking the first one\n",
1018 host
, port
? "," : "", port
? port
: "");
1020 saddr
= newsaddr(sizeof(*saddr
));
1021 if (saddr
== NULL
) {
1022 plog(LLV_ERROR
, LOCATION
, NULL
,
1023 "failed to allocate buffer.\n");
1027 memcpy(saddr
, res
->ai_addr
, res
->ai_addrlen
);
1034 mask_sockaddr(a
, b
, l
)
1035 struct sockaddr_storage
*a
;
1036 const struct sockaddr_storage
*b
;
1042 switch (b
->ss_family
) {
1044 alen
= sizeof(struct in_addr
);
1045 p
= (u_int8_t
*)&((struct sockaddr_in
*)a
)->sin_addr
;
1049 alen
= sizeof(struct in6_addr
);
1050 p
= (u_int8_t
*)&((struct sockaddr_in6
*)a
)->sin6_addr
;
1054 plog(LLV_ERROR2
, LOCATION
, NULL
,
1055 "invalid address family: %d\n", b
->ss_family
);
1059 if ((alen
<< 3) < l
) {
1060 plog(LLV_ERROR2
, LOCATION
, NULL
,
1061 "unexpected inconsistency: %d %zu\n", b
->ss_family
, l
);
1065 memcpy(a
, b
, sysdep_sa_len((struct sockaddr
*)b
));
1066 p
[l
/ 8] &= (0xff00 >> (l
% 8)) & 0xff;
1067 for (i
= l
/ 8 + 1; i
< alen
; i
++)
1071 /* Compute a score describing how "accurate" a netaddr is for a given sockaddr.
1073 * Return values for address 10.20.30.40 [port 500] and given netaddresses...
1074 * 10.10.0.0/16 => -1 ... doesn't match
1075 * 0.0.0.0/0 => 0 ... matches, but only 0 bits.
1076 * 10.20.0.0/16 => 16 ... 16 bits match
1077 * 10.20.30.0/24 => 24 ... guess what ;-)
1078 * 10.20.30.40/32 => 32 ... whole address match
1079 * 10.20.30.40:500 => 33 ... both address and port match
1080 * 10.20.30.40:501 => -1 ... port doesn't match and isn't 0 (=any)
1083 naddr_score(const struct netaddr
*naddr
, const struct sockaddr_storage
*saddr
)
1085 static const struct netaddr naddr_any
; /* initialized to all-zeros */
1086 struct sockaddr_storage sa
;
1087 u_int16_t naddr_port
, saddr_port
;
1090 if (!naddr
|| !saddr
) {
1091 plog(LLV_ERROR
, LOCATION
, NULL
,
1092 "Call with null args: naddr=%p, saddr=%p\n",
1097 /* Wildcard address matches, but only 0 bits. */
1098 if (memcmp(naddr
, &naddr_any
, sizeof(naddr_any
)) == 0)
1101 /* If families don't match we really can't do much... */
1102 if (naddr
->sa
.sa
.ss_family
!= saddr
->ss_family
)
1105 /* If port check fail don't bother to check addresses. */
1106 naddr_port
= extract_port(&naddr
->sa
.sa
);
1107 saddr_port
= extract_port(saddr
);
1108 if (naddr_port
== 0 || saddr_port
== 0) /* wildcard match */
1110 else if (naddr_port
== saddr_port
) /* exact match */
1112 else /* mismatch :-) */
1115 /* Here it comes - compare network addresses. */
1116 mask_sockaddr(&sa
, saddr
, naddr
->prefix
);
1117 if (loglevel
>= LLV_DEBUG
) { /* debug only */
1119 a1
= racoon_strdup(naddrwop2str(naddr
));
1120 a2
= racoon_strdup(saddrwop2str((struct sockaddr
*)saddr
));
1121 a3
= racoon_strdup(saddrwop2str((struct sockaddr
*)&sa
));
1125 plog(LLV_DEBUG
, LOCATION
, NULL
,
1126 "naddr=%s, saddr=%s (masked=%s)\n",
1132 if (cmpsaddrwop(&sa
, &naddr
->sa
.sa
) == 0)
1133 return naddr
->prefix
+ port_score
;
1138 /* Some usefull functions for sockaddr_storage port manipulations. */
1140 extract_port (const struct sockaddr_storage
*addr
)
1142 u_int16_t port
= -1;
1147 switch (addr
->ss_family
) {
1149 port
= ((struct sockaddr_in
*)addr
)->sin_port
;
1152 port
= ((struct sockaddr_in6
*)addr
)->sin6_port
;
1155 plog(LLV_ERROR
, LOCATION
, NULL
, "unknown AF: %u\n", addr
->ss_family
);
1163 get_port_ptr (struct sockaddr_storage
*addr
)
1165 u_int16_t
*port_ptr
;
1170 switch (addr
->ss_family
) {
1172 port_ptr
= &(((struct sockaddr_in
*)addr
)->sin_port
);
1175 port_ptr
= &(((struct sockaddr_in6
*)addr
)->sin6_port
);
1178 plog(LLV_ERROR
, LOCATION
, NULL
, "unknown AF: %u\n", addr
->ss_family
);
1187 set_port (struct sockaddr_storage
*addr
, u_int16_t new_port
)
1189 u_int16_t
*port_ptr
;
1191 port_ptr
= get_port_ptr (addr
);
1194 *port_ptr
= htons(new_port
);