]>
git.saurik.com Git - apple/ipsec.git/blob - ipsec-tools/racoon/sockmisc.c
98d0a696b8cecb27be0b8f5e62d1e6137638812e
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
68 #ifndef IP_IPSEC_POLICY
69 #define IP_IPSEC_POLICY 16 /* XXX: from linux/in.h */
72 #ifndef IPV6_IPSEC_POLICY
73 #define IPV6_IPSEC_POLICY 34 /* XXX: from linux/???.h per
74 "Tom Lendacky" <toml@us.ibm.com> */
77 const int niflags
= 0;
80 * compare two sockaddr without port number.
85 cmpsaddrwop(addr1
, addr2
)
86 const struct sockaddr
*addr1
;
87 const struct sockaddr
*addr2
;
91 if (addr1
== 0 && addr2
== 0)
93 if (addr1
== 0 || addr2
== 0)
97 if (addr1
->sa_family
!= addr2
->sa_family
)
100 if (addr1
->sa_len
!= addr2
->sa_len
101 || addr1
->sa_family
!= addr2
->sa_family
)
104 #endif /* __linux__ */
106 switch (addr1
->sa_family
) {
108 sa1
= (caddr_t
)&((struct sockaddr_in
*)addr1
)->sin_addr
;
109 sa2
= (caddr_t
)&((struct sockaddr_in
*)addr2
)->sin_addr
;
110 if (memcmp(sa1
, sa2
, sizeof(struct in_addr
)) != 0)
115 sa1
= (caddr_t
)&((struct sockaddr_in6
*)addr1
)->sin6_addr
;
116 sa2
= (caddr_t
)&((struct sockaddr_in6
*)addr2
)->sin6_addr
;
117 if (memcmp(sa1
, sa2
, sizeof(struct in6_addr
)) != 0)
119 if (((struct sockaddr_in6
*)addr1
)->sin6_scope_id
!=
120 ((struct sockaddr_in6
*)addr2
)->sin6_scope_id
)
132 * compare two sockaddr with port, taking care wildcard.
133 * addr1 is a subject address, addr2 is in a database entry.
138 cmpsaddrwild(addr1
, addr2
)
139 const struct sockaddr
*addr1
;
140 const struct sockaddr
*addr2
;
143 u_short port1
, port2
;
145 if (addr1
== 0 && addr2
== 0)
147 if (addr1
== 0 || addr2
== 0)
151 if (addr1
->sa_family
!= addr2
->sa_family
)
154 if (addr1
->sa_len
!= addr2
->sa_len
155 || addr1
->sa_family
!= addr2
->sa_family
)
158 #endif /* __linux__ */
160 switch (addr1
->sa_family
) {
162 sa1
= (caddr_t
)&((struct sockaddr_in
*)addr1
)->sin_addr
;
163 sa2
= (caddr_t
)&((struct sockaddr_in
*)addr2
)->sin_addr
;
164 port1
= ((struct sockaddr_in
*)addr1
)->sin_port
;
165 port2
= ((struct sockaddr_in
*)addr2
)->sin_port
;
166 if (!(port1
== IPSEC_PORT_ANY
||
167 port2
== IPSEC_PORT_ANY
||
170 if (memcmp(sa1
, sa2
, sizeof(struct in_addr
)) != 0)
175 sa1
= (caddr_t
)&((struct sockaddr_in6
*)addr1
)->sin6_addr
;
176 sa2
= (caddr_t
)&((struct sockaddr_in6
*)addr2
)->sin6_addr
;
177 port1
= ((struct sockaddr_in6
*)addr1
)->sin6_port
;
178 port2
= ((struct sockaddr_in6
*)addr2
)->sin6_port
;
179 if (!(port1
== IPSEC_PORT_ANY
||
180 port2
== IPSEC_PORT_ANY
||
183 if (memcmp(sa1
, sa2
, sizeof(struct in6_addr
)) != 0)
185 if (((struct sockaddr_in6
*)addr1
)->sin6_scope_id
!=
186 ((struct sockaddr_in6
*)addr2
)->sin6_scope_id
)
198 * compare two sockaddr with strict match on port.
203 cmpsaddrstrict(addr1
, addr2
)
204 const struct sockaddr
*addr1
;
205 const struct sockaddr
*addr2
;
208 u_short port1
, port2
;
210 if (addr1
== 0 && addr2
== 0)
212 if (addr1
== 0 || addr2
== 0)
216 if (addr1
->sa_family
!= addr2
->sa_family
)
219 if (addr1
->sa_len
!= addr2
->sa_len
220 || addr1
->sa_family
!= addr2
->sa_family
)
223 #endif /* __linux__ */
225 switch (addr1
->sa_family
) {
227 sa1
= (caddr_t
)&((struct sockaddr_in
*)addr1
)->sin_addr
;
228 sa2
= (caddr_t
)&((struct sockaddr_in
*)addr2
)->sin_addr
;
229 port1
= ((struct sockaddr_in
*)addr1
)->sin_port
;
230 port2
= ((struct sockaddr_in
*)addr2
)->sin_port
;
233 if (memcmp(sa1
, sa2
, sizeof(struct in_addr
)) != 0)
238 sa1
= (caddr_t
)&((struct sockaddr_in6
*)addr1
)->sin6_addr
;
239 sa2
= (caddr_t
)&((struct sockaddr_in6
*)addr2
)->sin6_addr
;
240 port1
= ((struct sockaddr_in6
*)addr1
)->sin6_port
;
241 port2
= ((struct sockaddr_in6
*)addr2
)->sin6_port
;
244 if (memcmp(sa1
, sa2
, sizeof(struct in6_addr
)) != 0)
246 if (((struct sockaddr_in6
*)addr1
)->sin6_scope_id
!=
247 ((struct sockaddr_in6
*)addr2
)->sin6_scope_id
)
258 /* get local address against the destination. */
261 struct sockaddr
*remote
;
263 struct sockaddr
*local
;
264 u_int local_len
= sizeof(struct sockaddr_storage
);
265 int s
; /* for dummy connection */
267 /* allocate buffer */
268 if ((local
= racoon_calloc(1, local_len
)) == NULL
) {
269 plog(LLV_ERROR
, LOCATION
, NULL
,
270 "failed to get address buffer.\n");
274 /* get real interface received packet */
275 if ((s
= socket(remote
->sa_family
, SOCK_DGRAM
, 0)) < 0) {
276 plog(LLV_ERROR
, LOCATION
, NULL
,
277 "socket (%s)\n", strerror(errno
));
281 setsockopt_bypass(s
, remote
->sa_family
);
283 if (connect(s
, remote
, sysdep_sa_len(remote
)) < 0) {
284 plog(LLV_ERROR
, LOCATION
, NULL
,
285 "connect (%s)\n", strerror(errno
));
290 if (getsockname(s
, local
, &local_len
) < 0) {
291 plog(LLV_ERROR
, LOCATION
, NULL
,
292 "getsockname (%s)\n", strerror(errno
));
307 * Receive packet, with src/dst information. It is assumed that necessary
308 * setsockopt() have already performed on socket.
311 recvfromto(s
, buf
, buflen
, flags
, from
, fromlen
, to
, tolen
)
316 struct sockaddr
*from
;
323 struct sockaddr_storage ss
;
325 struct cmsghdr
*cm
, *cm_prev
;
328 #if defined(INET6) && defined(INET6_ADVAPI)
329 struct in6_pktinfo
*pi
;
330 #endif /*INET6_ADVAPI*/
331 struct sockaddr_in
*sin
;
333 struct sockaddr_in6
*sin6
;
337 if (getsockname(s
, (struct sockaddr
*)&ss
, &len
) < 0) {
338 plog(LLV_ERROR
, LOCATION
, NULL
,
339 "getsockname (%s)\n", strerror(errno
));
343 m
.msg_name
= (caddr_t
)from
;
344 m
.msg_namelen
= *fromlen
;
345 iov
[0].iov_base
= (caddr_t
)buf
;
346 iov
[0].iov_len
= buflen
;
349 memset(cmsgbuf
, 0, sizeof(cmsgbuf
));
350 cm
= (struct cmsghdr
*)cmsgbuf
;
351 m
.msg_control
= (caddr_t
)cm
;
352 m
.msg_controllen
= sizeof(cmsgbuf
);
353 if ((len
= recvmsg(s
, &m
, flags
)) < 0) {
354 plog(LLV_ERROR
, LOCATION
, NULL
,
355 "recvmsg (%s)\n", strerror(errno
));
357 } else if (len
== 0) {
360 *fromlen
= m
.msg_namelen
;
364 for (cm
= (struct cmsghdr
*)CMSG_FIRSTHDR(&m
), cm_prev
= NULL
;
365 m
.msg_controllen
!= 0 && cm
&& cm
!= cm_prev
;
366 cm_prev
= cm
, cm
= (struct cmsghdr
*)CMSG_NXTHDR(&m
, cm
)) {
368 plog(LLV_ERROR
, LOCATION
, NULL
,
369 "cmsg %d %d\n", cm
->cmsg_level
, cm
->cmsg_type
);)
371 #if defined(INET6) && defined(INET6_ADVAPI)
372 if (ss
.ss_family
== AF_INET6
373 && cm
->cmsg_level
== IPPROTO_IPV6
374 && cm
->cmsg_type
== IPV6_PKTINFO
375 && otolen
>= sizeof(*sin6
)) {
376 pi
= (struct in6_pktinfo
*)(CMSG_DATA(cm
));
377 *tolen
= sizeof(*sin6
);
378 sin6
= (struct sockaddr_in6
*)to
;
379 memset(sin6
, 0, sizeof(*sin6
));
380 sin6
->sin6_family
= AF_INET6
;
382 sin6
->sin6_len
= sizeof(*sin6
);
384 memcpy(&sin6
->sin6_addr
, &pi
->ipi6_addr
,
385 sizeof(sin6
->sin6_addr
));
386 /* XXX other cases, such as site-local? */
387 if (IN6_IS_ADDR_LINKLOCAL(&sin6
->sin6_addr
))
388 sin6
->sin6_scope_id
= pi
->ipi6_ifindex
;
390 sin6
->sin6_scope_id
= 0;
392 ((struct sockaddr_in6
*)&ss
)->sin6_port
;
393 otolen
= -1; /* "to" already set */
398 if (ss
.ss_family
== AF_INET
399 && cm
->cmsg_level
== IPPROTO_IP
400 && cm
->cmsg_type
== IP_PKTINFO
401 && otolen
>= sizeof(sin
)) {
402 struct in_pktinfo
*pi
= (struct in_pktinfo
*)(CMSG_DATA(cm
));
403 *tolen
= sizeof(*sin
);
404 sin
= (struct sockaddr_in
*)to
;
405 memset(sin
, 0, sizeof(*sin
));
406 sin
->sin_family
= AF_INET
;
407 memcpy(&sin
->sin_addr
, &pi
->ipi_addr
,
408 sizeof(sin
->sin_addr
));
410 ((struct sockaddr_in
*)&ss
)->sin_port
;
411 otolen
= -1; /* "to" already set */
415 #if defined(INET6) && defined(IPV6_RECVDSTADDR)
416 if (ss
.ss_family
== AF_INET6
417 && cm
->cmsg_level
== IPPROTO_IPV6
418 && cm
->cmsg_type
== IPV6_RECVDSTADDR
419 && otolen
>= sizeof(*sin6
)) {
420 *tolen
= sizeof(*sin6
);
421 sin6
= (struct sockaddr_in6
*)to
;
422 memset(sin6
, 0, sizeof(*sin6
));
423 sin6
->sin6_family
= AF_INET6
;
424 sin6
->sin6_len
= sizeof(*sin6
);
425 memcpy(&sin6
->sin6_addr
, CMSG_DATA(cm
),
426 sizeof(sin6
->sin6_addr
));
428 ((struct sockaddr_in6
*)&ss
)->sin6_port
;
429 otolen
= -1; /* "to" already set */
434 if (ss
.ss_family
== AF_INET
435 && cm
->cmsg_level
== IPPROTO_IP
436 && cm
->cmsg_type
== IP_RECVDSTADDR
437 && otolen
>= sizeof(*sin
)) {
438 *tolen
= sizeof(*sin
);
439 sin
= (struct sockaddr_in
*)to
;
440 memset(sin
, 0, sizeof(*sin
));
441 sin
->sin_family
= AF_INET
;
442 sin
->sin_len
= sizeof(*sin
);
443 memcpy(&sin
->sin_addr
, CMSG_DATA(cm
),
444 sizeof(sin
->sin_addr
));
445 sin
->sin_port
= ((struct sockaddr_in
*)&ss
)->sin_port
;
446 otolen
= -1; /* "to" already set */
455 /* send packet, with fixing src/dst address pair. */
457 sendfromto(s
, buf
, buflen
, src
, dst
, cnt
)
461 struct sockaddr
*src
;
462 struct sockaddr
*dst
;
464 struct sockaddr_storage ss
;
468 if (src
->sa_family
!= dst
->sa_family
) {
469 plog(LLV_ERROR
, LOCATION
, NULL
,
470 "address family mismatch\n");
475 if (getsockname(s
, (struct sockaddr
*)&ss
, &len
) < 0) {
476 plog(LLV_ERROR
, LOCATION
, NULL
,
477 "getsockname (%s)\n", strerror(errno
));
481 plog(LLV_DEBUG
, LOCATION
, NULL
,
482 "sockname %s\n", saddr2str((struct sockaddr
*)&ss
));
483 plog(LLV_DEBUG
, LOCATION
, NULL
,
484 "send packet from %s\n", saddr2str(src
));
485 plog(LLV_DEBUG
, LOCATION
, NULL
,
486 "send packet to %s\n", saddr2str(dst
));
488 if (src
->sa_family
!= ss
.ss_family
) {
489 plog(LLV_ERROR
, LOCATION
, NULL
,
490 "address family mismatch\n");
494 switch (src
->sa_family
) {
495 #if defined(INET6) && defined(INET6_ADVAPI)
496 // XXX: This block wasn't compiled on Linux - does it work?
503 struct in6_pktinfo
*pi
;
505 struct sockaddr_in6 src6
, dst6
;
507 memcpy(&src6
, src
, sizeof(src6
));
508 memcpy(&dst6
, dst
, sizeof(dst6
));
510 /* XXX take care of other cases, such as site-local */
512 if (IN6_IS_ADDR_LINKLOCAL(&src6
.sin6_addr
)
513 || IN6_IS_ADDR_MULTICAST(&src6
.sin6_addr
)) {
514 ifindex
= src6
.sin6_scope_id
; /*???*/
517 /* XXX some sanity check on dst6.sin6_scope_id */
519 /* flowinfo for IKE? mmm, maybe useful but for now make it 0 */
520 src6
.sin6_flowinfo
= dst6
.sin6_flowinfo
= 0;
522 memset(&m
, 0, sizeof(m
));
523 m
.msg_name
= (caddr_t
)&dst6
;
524 m
.msg_namelen
= sizeof(dst6
);
525 iov
[0].iov_base
= (char *)buf
;
526 iov
[0].iov_len
= buflen
;
530 memset(cmsgbuf
, 0, sizeof(cmsgbuf
));
531 cm
= (struct cmsghdr
*)cmsgbuf
;
532 m
.msg_control
= (caddr_t
)cm
;
533 m
.msg_controllen
= CMSG_SPACE(sizeof(struct in6_pktinfo
));
535 cm
->cmsg_len
= CMSG_LEN(sizeof(struct in6_pktinfo
));
536 cm
->cmsg_level
= IPPROTO_IPV6
;
537 cm
->cmsg_type
= IPV6_PKTINFO
;
538 pi
= (struct in6_pktinfo
*)CMSG_DATA(cm
);
539 memcpy(&pi
->ipi6_addr
, &src6
.sin6_addr
, sizeof(src6
.sin6_addr
));
540 pi
->ipi6_ifindex
= ifindex
;
542 plog(LLV_DEBUG
, LOCATION
, NULL
,
544 saddr2str((struct sockaddr
*)&src6
),
546 plog(LLV_DEBUG
, LOCATION
, NULL
,
548 saddr2str((struct sockaddr
*)&dst6
),
551 for (i
= 0; i
< cnt
; i
++) {
552 len
= sendmsg(s
, &m
, 0 /*MSG_DONTROUTE*/);
554 plog(LLV_ERROR
, LOCATION
, NULL
,
555 "sendmsg (%s)\n", strerror(errno
));
558 plog(LLV_DEBUG
, LOCATION
, NULL
,
559 "%d times of %d bytes message will be sent "
561 i
+ 1, len
, saddr2str(dst
));
563 plogdump(LLV_DEBUG
, (char *)buf
, buflen
);
575 struct in_pktinfo
*pi
;
577 struct sockaddr_in src6
, dst6
;
579 memcpy(&src6
, src
, sizeof(src6
));
580 memcpy(&dst6
, dst
, sizeof(dst6
));
582 memset(&m
, 0, sizeof(m
));
583 m
.msg_name
= (caddr_t
)&dst6
;
584 m
.msg_namelen
= sizeof(dst6
);
585 iov
[0].iov_base
= (char *)buf
;
586 iov
[0].iov_len
= buflen
;
590 memset(cmsgbuf
, 0, sizeof(cmsgbuf
));
591 cm
= (struct cmsghdr
*)cmsgbuf
;
592 m
.msg_control
= (caddr_t
)cm
;
593 m
.msg_controllen
= CMSG_SPACE(sizeof(struct in_pktinfo
));
595 cm
->cmsg_len
= CMSG_LEN(sizeof(struct in_pktinfo
));
596 cm
->cmsg_level
= IPPROTO_IP
;
597 cm
->cmsg_type
= IP_PKTINFO
;
598 pi
= (struct in_pktinfo
*)CMSG_DATA(cm
);
599 memcpy(&pi
->ipi_spec_dst
, &src6
.sin_addr
, sizeof(src6
.sin_addr
));
600 pi
->ipi_ifindex
= ifindex
;
602 plog(LLV_DEBUG
, LOCATION
, NULL
,
604 saddr2str((struct sockaddr
*)&src6
));
605 plog(LLV_DEBUG
, LOCATION
, NULL
,
607 saddr2str((struct sockaddr
*)&dst6
));
609 for (i
= 0; i
< cnt
; i
++) {
610 len
= sendmsg(s
, &m
, 0 /*MSG_DONTROUTE*/);
612 plog(LLV_ERROR
, LOCATION
, NULL
,
613 "sendmsg (%s)\n", strerror(errno
));
616 plog(LLV_DEBUG
, LOCATION
, NULL
,
617 "%d times of %d bytes message will be sent "
619 i
+ 1, len
, saddr2str(dst
));
621 plogdump(LLV_DEBUG
, (char *)buf
, buflen
);
625 #endif /* __linux__ */
631 if (ss
.ss_family
== src
->sa_family
&& memcmp(&ss
, src
, sysdep_sa_len(src
)) == 0) {
637 * Use newly opened socket for sending packets.
638 * NOTE: this is unsafe, because if the peer is quick enough
639 * the packet from the peer may be queued into sendsock.
640 * Better approach is to prepare bind'ed udp sockets for
641 * each of the interface addresses.
643 sendsock
= socket(src
->sa_family
, SOCK_DGRAM
, 0);
645 plog(LLV_ERROR
, LOCATION
, NULL
,
646 "socket (%s)\n", strerror(errno
));
649 if (setsockopt(sendsock
, SOL_SOCKET
,
655 (void *)&yes
, sizeof(yes
)) < 0) {
656 plog(LLV_ERROR
, LOCATION
, NULL
,
657 "setsockopt SO_REUSEPORT (%s)\n",
662 #ifdef IPV6_USE_MIN_MTU
663 if (src
->sa_family
== AF_INET6
&&
664 setsockopt(sendsock
, IPPROTO_IPV6
, IPV6_USE_MIN_MTU
,
665 (void *)&yes
, sizeof(yes
)) < 0) {
666 plog(LLV_ERROR
, LOCATION
, NULL
,
667 "setsockopt IPV6_USE_MIN_MTU (%s)\n",
673 if (setsockopt_bypass(sendsock
, src
->sa_family
) < 0) {
678 if (bind(sendsock
, (struct sockaddr
*)src
, sysdep_sa_len(src
)) < 0) {
679 plog(LLV_ERROR
, LOCATION
, NULL
,
680 "bind 1 (%s)\n", strerror(errno
));
687 for (i
= 0; i
< cnt
; i
++) {
688 len
= sendto(sendsock
, buf
, buflen
, 0, dst
, sysdep_sa_len(dst
));
690 plog(LLV_ERROR
, LOCATION
, NULL
,
691 "sendto (%s)\n", strerror(errno
));
696 plog(LLV_DEBUG
, LOCATION
, NULL
,
697 "%d times of %d bytes message will be sent "
699 i
+ 1, len
, saddr2str(dst
));
701 plogdump(LLV_DEBUG
, (char *)buf
, buflen
);
712 setsockopt_bypass(so
, family
)
725 level
= IPPROTO_IPV6
;
729 plog(LLV_ERROR
, LOCATION
, NULL
,
730 "unsupported address family %d\n", family
);
734 policy
= "in bypass";
735 buf
= ipsec_set_policy(policy
, strlen(policy
));
737 plog(LLV_ERROR
, LOCATION
, NULL
,
738 "ipsec_set_policy (%s)\n",
742 if (setsockopt(so
, level
,
743 (level
== IPPROTO_IP
?
744 IP_IPSEC_POLICY
: IPV6_IPSEC_POLICY
),
745 buf
, ipsec_get_policylen(buf
)) < 0) {
746 plog(LLV_ERROR
, LOCATION
, NULL
,
747 "setsockopt IP_IPSEC_POLICY (%s)\n",
753 policy
= "out bypass";
754 buf
= ipsec_set_policy(policy
, strlen(policy
));
756 plog(LLV_ERROR
, LOCATION
, NULL
,
757 "ipsec_set_policy (%s)\n",
761 if (setsockopt(so
, level
,
762 (level
== IPPROTO_IP
?
763 IP_IPSEC_POLICY
: IPV6_IPSEC_POLICY
),
764 buf
, ipsec_get_policylen(buf
)) < 0) {
765 plog(LLV_ERROR
, LOCATION
, NULL
,
766 "setsockopt IP_IPSEC_POLICY (%s)\n",
779 struct sockaddr
*new;
781 if ((new = racoon_calloc(1, len
)) == NULL
) {
782 plog(LLV_ERROR
, LOCATION
, NULL
,
783 "%s\n", strerror(errno
));
788 if (len
== sizeof (struct sockaddr_in6
))
789 new->sa_family
= AF_INET6
;
791 new->sa_family
= AF_INET
;
802 struct sockaddr
*src
;
804 struct sockaddr
*dst
;
806 dst
= racoon_calloc(1, sysdep_sa_len(src
));
808 plog(LLV_ERROR
, LOCATION
, NULL
,
809 "%s\n", strerror(errno
));
813 memcpy(dst
, src
, sysdep_sa_len(src
));
820 const struct sockaddr
*saddr
;
822 static char buf
[NI_MAXHOST
+ NI_MAXSERV
+ 10];
823 char addr
[NI_MAXHOST
], port
[NI_MAXSERV
];
828 if (saddr
->sa_family
== AF_UNSPEC
)
829 snprintf (buf
, sizeof(buf
), "%s", "anonymous");
831 GETNAMEINFO(saddr
, addr
, port
);
832 snprintf(buf
, sizeof(buf
), "%s[%s]", addr
, port
);
840 const struct sockaddr
*saddr
;
842 static char buf
[NI_MAXHOST
+ NI_MAXSERV
+ 10];
843 char addr
[NI_MAXHOST
];
848 GETNAMEINFO_NULL(saddr
, addr
);
849 snprintf(buf
, sizeof(buf
), "%s", addr
);
855 naddrwop2str(const struct netaddr
*naddr
)
857 static char buf
[NI_MAXHOST
+ 10];
858 static const struct sockaddr sa_any
; /* this is initialized to all zeros */
863 if (memcmp(&naddr
->sa
, &sa_any
, sizeof(sa_any
)) == 0)
864 snprintf(buf
, sizeof(buf
), "%s", "any");
866 snprintf(buf
, sizeof(buf
), "%s", saddrwop2str(&naddr
->sa
.sa
));
867 snprintf(&buf
[strlen(buf
)], sizeof(buf
) - strlen(buf
), "/%ld", naddr
->prefix
);
873 naddrwop2str_fromto(const char *format
, const struct netaddr
*saddr
,
874 const struct netaddr
*daddr
)
876 static char buf
[2*(NI_MAXHOST
+ NI_MAXSERV
+ 10) + 100];
879 src
= racoon_strdup(naddrwop2str(saddr
));
880 dst
= racoon_strdup(naddrwop2str(daddr
));
883 /* WARNING: Be careful about the format string! Don't
884 ever pass in something that a user can modify!!! */
885 snprintf (buf
, sizeof(buf
), format
, src
, dst
);
893 saddr2str_fromto(format
, saddr
, daddr
)
895 const struct sockaddr
*saddr
;
896 const struct sockaddr
*daddr
;
898 static char buf
[2*(NI_MAXHOST
+ NI_MAXSERV
+ 10) + 100];
901 src
= racoon_strdup(saddr2str(saddr
));
902 dst
= racoon_strdup(saddr2str(daddr
));
905 /* WARNING: Be careful about the format string! Don't
906 ever pass in something that a user can modify!!! */
907 snprintf (buf
, sizeof(buf
), format
, src
, dst
);
915 str2saddr(host
, port
)
919 struct addrinfo hints
, *res
;
920 struct sockaddr
*saddr
;
923 memset(&hints
, 0, sizeof(hints
));
924 hints
.ai_family
= PF_UNSPEC
;
925 hints
.ai_socktype
= SOCK_DGRAM
;
926 hints
.ai_flags
= AI_NUMERICHOST
;
927 error
= getaddrinfo(host
, port
, &hints
, &res
);
929 plog(LLV_ERROR
, LOCATION
, NULL
,
930 "getaddrinfo(%s%s%s): %s\n",
931 host
, port
? "," : "", port
? port
: "",
932 gai_strerror(error
));
935 if (res
->ai_next
!= NULL
) {
936 plog(LLV_WARNING
, LOCATION
, NULL
,
937 "getaddrinfo(%s%s%s): "
938 "resolved to multiple address, "
939 "taking the first one\n",
940 host
, port
? "," : "", port
? port
: "");
942 saddr
= racoon_malloc(res
->ai_addrlen
);
944 plog(LLV_ERROR
, LOCATION
, NULL
,
945 "failed to allocate buffer.\n");
949 memcpy(saddr
, res
->ai_addr
, res
->ai_addrlen
);
956 mask_sockaddr(a
, b
, l
)
958 const struct sockaddr
*b
;
964 switch (b
->sa_family
) {
966 alen
= sizeof(struct in_addr
);
967 p
= (u_int8_t
*)&((struct sockaddr_in
*)a
)->sin_addr
;
971 alen
= sizeof(struct in6_addr
);
972 p
= (u_int8_t
*)&((struct sockaddr_in6
*)a
)->sin6_addr
;
976 plog(LLV_ERROR2
, LOCATION
, NULL
,
977 "invalid address family: %d\n", b
->sa_family
);
981 if ((alen
<< 3) < l
) {
982 plog(LLV_ERROR2
, LOCATION
, NULL
,
983 "unexpected inconsistency: %d %zu\n", b
->sa_family
, l
);
987 memcpy(a
, b
, sysdep_sa_len(b
));
988 p
[l
/ 8] &= (0xff00 >> (l
% 8)) & 0xff;
989 for (i
= l
/ 8 + 1; i
< alen
; i
++)
993 /* Compute a score describing how "accurate" a netaddr is for a given sockaddr.
995 * Return values for address 10.20.30.40 [port 500] and given netaddresses...
996 * 10.10.0.0/16 => -1 ... doesn't match
997 * 0.0.0.0/0 => 0 ... matches, but only 0 bits.
998 * 10.20.0.0/16 => 16 ... 16 bits match
999 * 10.20.30.0/24 => 24 ... guess what ;-)
1000 * 10.20.30.40/32 => 32 ... whole address match
1001 * 10.20.30.40:500 => 33 ... both address and port match
1002 * 10.20.30.40:501 => -1 ... port doesn't match and isn't 0 (=any)
1005 naddr_score(const struct netaddr
*naddr
, const struct sockaddr
*saddr
)
1007 static const struct netaddr naddr_any
; /* initialized to all-zeros */
1009 u_int16_t naddr_port
, saddr_port
;
1012 if (!naddr
|| !saddr
) {
1013 plog(LLV_ERROR
, LOCATION
, NULL
,
1014 "Call with null args: naddr=%p, saddr=%p\n",
1019 /* Wildcard address matches, but only 0 bits. */
1020 if (memcmp(naddr
, &naddr_any
, sizeof(naddr_any
)) == 0)
1023 /* If families don't match we really can't do much... */
1024 if (naddr
->sa
.sa
.sa_family
!= saddr
->sa_family
)
1027 /* If port check fail don't bother to check addresses. */
1028 naddr_port
= extract_port(&naddr
->sa
.sa
);
1029 saddr_port
= extract_port(saddr
);
1030 if (naddr_port
== 0 || saddr_port
== 0) /* wildcard match */
1032 else if (naddr_port
== saddr_port
) /* exact match */
1034 else /* mismatch :-) */
1037 /* Here it comes - compare network addresses. */
1038 mask_sockaddr(&sa
, saddr
, naddr
->prefix
);
1039 if (loglevel
>= LLV_DEBUG
) { /* debug only */
1041 a1
= racoon_strdup(naddrwop2str(naddr
));
1042 a2
= racoon_strdup(saddrwop2str(saddr
));
1043 a3
= racoon_strdup(saddrwop2str(&sa
));
1047 plog(LLV_DEBUG
, LOCATION
, NULL
,
1048 "naddr=%s, saddr=%s (masked=%s)\n",
1054 if (cmpsaddrwop(&sa
, &naddr
->sa
.sa
) == 0)
1055 return naddr
->prefix
+ port_score
;
1060 /* Some usefull functions for sockaddr port manipulations. */
1062 extract_port (const struct sockaddr
*addr
)
1064 u_int16_t port
= -1;
1069 switch (addr
->sa_family
) {
1071 port
= ((struct sockaddr_in
*)addr
)->sin_port
;
1074 port
= ((struct sockaddr_in6
*)addr
)->sin6_port
;
1077 plog(LLV_ERROR
, LOCATION
, NULL
, "unknown AF: %u\n", addr
->sa_family
);
1085 get_port_ptr (struct sockaddr
*addr
)
1087 u_int16_t
*port_ptr
;
1092 switch (addr
->sa_family
) {
1094 port_ptr
= &(((struct sockaddr_in
*)addr
)->sin_port
);
1097 port_ptr
= &(((struct sockaddr_in6
*)addr
)->sin6_port
);
1100 plog(LLV_ERROR
, LOCATION
, NULL
, "unknown AF: %u\n", addr
->sa_family
);
1109 set_port (struct sockaddr
*addr
, u_int16_t new_port
)
1111 u_int16_t
*port_ptr
;
1113 port_ptr
= get_port_ptr (addr
);
1116 *port_ptr
= htons(new_port
);