mirror of
https://repo.or.cz/socat.git
synced 2024-12-22 15:32:35 +00:00
Added the optional DEVTESTS feature for developer tests with controlled name resolution to both IPv4 and IPV6 addresses
This commit is contained in:
parent
a86376cd1e
commit
602a54420e
7 changed files with 350 additions and 8 deletions
6
CHANGES
6
CHANGES
|
@ -64,6 +64,12 @@ Building:
|
||||||
Thanks to Hongxu Jia for providing an inital patch.
|
Thanks to Hongxu Jia for providing an inital patch.
|
||||||
|
|
||||||
Testing:
|
Testing:
|
||||||
|
Added the optional DEVTESTS feature for developer tests with controlled
|
||||||
|
name resolution to both IPv4 and IPV6 addresses: configure Socat with
|
||||||
|
--enable-devtests, this provides internal resolution of domain
|
||||||
|
dest-unreach.net with host names: localhost-4, localhost-6,
|
||||||
|
localhost-4-6, and localhost-6-4
|
||||||
|
|
||||||
test.sh: lots of corrections and improvements
|
test.sh: lots of corrections and improvements
|
||||||
|
|
||||||
test.sh: many hardcoded sleep values were replaced by much shorter
|
test.sh: many hardcoded sleep values were replaced by much shorter
|
||||||
|
|
|
@ -748,10 +748,10 @@
|
||||||
#undef WITH_LIBWRAP
|
#undef WITH_LIBWRAP
|
||||||
#undef HAVE_TCPD_H
|
#undef HAVE_TCPD_H
|
||||||
#undef HAVE_LIBWRAP
|
#undef HAVE_LIBWRAP
|
||||||
|
|
||||||
#undef WITH_SYCLS
|
#undef WITH_SYCLS
|
||||||
#undef WITH_FILAN
|
#undef WITH_FILAN
|
||||||
#undef WITH_RETRY
|
#undef WITH_RETRY
|
||||||
|
#undef WITH_DEVTESTS
|
||||||
|
|
||||||
#undef WITH_MSGLEVEL
|
#undef WITH_MSGLEVEL
|
||||||
|
|
||||||
|
|
10
configure.ac
10
configure.ac
|
@ -942,6 +942,15 @@ AC_ARG_ENABLE(retry, [ --disable-retry disable retry support],
|
||||||
esac],
|
esac],
|
||||||
[AC_DEFINE(WITH_RETRY) AC_MSG_RESULT(yes)])
|
[AC_DEFINE(WITH_RETRY) AC_MSG_RESULT(yes)])
|
||||||
|
|
||||||
|
AC_MSG_CHECKING(whether to include devtests support)
|
||||||
|
AC_ARG_ENABLE(devtests, [ --enable-devtests enable devtests support],
|
||||||
|
[case "$enableval" in
|
||||||
|
yes) AC_DEFINE(WITH_DEVTESTS) AC_MSG_RESULT(yes);;
|
||||||
|
*) AC_MSG_RESULT(no) ;;
|
||||||
|
esac],
|
||||||
|
[AC_MSG_RESULT(no)])
|
||||||
|
|
||||||
|
|
||||||
AC_MSG_CHECKING(included message level)
|
AC_MSG_CHECKING(included message level)
|
||||||
AC_ARG_ENABLE(msglevel, [ --enable-msglevel=N set max verbosity to debug,info,notice,warn,error,fatal],
|
AC_ARG_ENABLE(msglevel, [ --enable-msglevel=N set max verbosity to debug,info,notice,warn,error,fatal],
|
||||||
[case "$enableval" in
|
[case "$enableval" in
|
||||||
|
@ -965,6 +974,7 @@ AC_ARG_ENABLE(default-ipv, [ --enable-default-ipv=N set default/preferred I
|
||||||
esac],
|
esac],
|
||||||
[AC_DEFINE(WITH_DEFAULT_IPV, '0') AC_MSG_RESULT("0")])
|
[AC_DEFINE(WITH_DEFAULT_IPV, '0') AC_MSG_RESULT("0")])
|
||||||
|
|
||||||
|
|
||||||
#AC_SUBST(V_INCL)
|
#AC_SUBST(V_INCL)
|
||||||
|
|
||||||
dnl Checks for typedefs, structures, and compiler characteristics.
|
dnl Checks for typedefs, structures, and compiler characteristics.
|
||||||
|
|
5
socat.c
5
socat.c
|
@ -714,6 +714,11 @@ void socat_version(FILE *fd) {
|
||||||
#else
|
#else
|
||||||
fputs(" #undef WITH_RETRY\n", fd);
|
fputs(" #undef WITH_RETRY\n", fd);
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef WITH_DEVTESTS
|
||||||
|
fprintf(fd, " #define WITH_DEVTESTS %d\n", WITH_DEVTESTS);
|
||||||
|
#else
|
||||||
|
fputs(" #undef WITH_DEVTESTS\n", fd);
|
||||||
|
#endif
|
||||||
#ifdef WITH_MSGLEVEL
|
#ifdef WITH_MSGLEVEL
|
||||||
fprintf(fd, " #define WITH_MSGLEVEL %d /*%s*/\n", WITH_MSGLEVEL,
|
fprintf(fd, " #define WITH_MSGLEVEL %d /*%s*/\n", WITH_MSGLEVEL,
|
||||||
&"debug\0\0\0info\0\0\0\0notice\0\0warn\0\0\0\0error\0\0\0fatal\0\0\0"[WITH_MSGLEVEL<<3]);
|
&"debug\0\0\0info\0\0\0\0notice\0\0warn\0\0\0\0error\0\0\0fatal\0\0\0"[WITH_MSGLEVEL<<3]);
|
||||||
|
|
28
test.sh
28
test.sh
|
@ -15759,8 +15759,8 @@ tf="$td/test$N.stdout"
|
||||||
te="$td/test$N.stderr"
|
te="$td/test$N.stderr"
|
||||||
tdiff="$td/test$N.diff"
|
tdiff="$td/test$N.diff"
|
||||||
da="test$N $(date) $RANDOM"
|
da="test$N $(date) $RANDOM"
|
||||||
CMD0="$TRACE $SOCAT $opts -t $T4 TCP4-LISTEN:$PORT,reuseaddr EXEC:'$FILAN -s',nofork"
|
CMD0="$TRACE $SOCAT $opts TCP4-LISTEN:$PORT,reuseaddr EXEC:'$FILAN -s',nofork"
|
||||||
CMD1="$TRACE $SOCAT $opts - TCP4:localhost:$PORT"
|
CMD1="$TRACE $SOCAT $opts -t $T4 - TCP4:localhost:$PORT"
|
||||||
printf "test $F_n $TEST... " $N
|
printf "test $F_n $TEST... " $N
|
||||||
eval "$CMD0" >/dev/null 2>"${te}0" &
|
eval "$CMD0" >/dev/null 2>"${te}0" &
|
||||||
pid0=$!
|
pid0=$!
|
||||||
|
@ -19442,7 +19442,8 @@ else
|
||||||
$CMD0 >/dev/null 2>"${te}0" &
|
$CMD0 >/dev/null 2>"${te}0" &
|
||||||
pid0=$!
|
pid0=$!
|
||||||
waittcp4port $tp
|
waittcp4port $tp
|
||||||
echo "$da" |$CMD1 >"${tf}1" 2>"${te}1"
|
# NetBSD-9 seems to need massive delay
|
||||||
|
{ echo "$da"; relsleep 100; } |$CMD1 >"${tf}1" 2>"${te}1"
|
||||||
rc1=$?
|
rc1=$?
|
||||||
kill $pid0 2>/dev/null
|
kill $pid0 2>/dev/null
|
||||||
wait 2>/dev/null
|
wait 2>/dev/null
|
||||||
|
@ -19915,6 +19916,27 @@ esac
|
||||||
N=$((N+1))
|
N=$((N+1))
|
||||||
|
|
||||||
|
|
||||||
|
# DEVTESTS IPv4/IPv6 resolver tests: just manually:
|
||||||
|
|
||||||
|
# Prepare:
|
||||||
|
#socat TCP4-LISTEN:12345,reuseaddr,fork PIPE
|
||||||
|
# These must succeed:
|
||||||
|
#echo AAAA |socat - TCP4:localhost-4.dest-unreach.net:12345
|
||||||
|
#echo AAAA |socat - TCP4:localhost-4-6.dest-unreach.net:12345
|
||||||
|
#echo AAAA |socat - TCP4:localhost-6-4.dest-unreach.net:12345
|
||||||
|
|
||||||
|
# Prepare:
|
||||||
|
#socat TCP6-LISTEN:12345,reuseaddr,fork PIPE
|
||||||
|
# These must succeed:
|
||||||
|
#echo AAAA |socat - TCP6:localhost-6.dest-unreach.net:12345
|
||||||
|
#echo AAAA |socat - TCP6:localhost-6-4.dest-unreach.net:12345
|
||||||
|
#echo AAAA |socat - TCP6:localhost-4-6.dest-unreach.net:12345
|
||||||
|
|
||||||
|
# These must fail with No address associated with hostname
|
||||||
|
#socat - TCP4:localhost-6.dest-unreach.net:12345
|
||||||
|
#socat - TCP6:localhost-4.dest-unreach.net:12345
|
||||||
|
|
||||||
|
|
||||||
# end of common tests
|
# end of common tests
|
||||||
|
|
||||||
##################################################################################
|
##################################################################################
|
||||||
|
|
256
xio-ip.c
256
xio-ip.c
|
@ -161,6 +161,208 @@ int Res_init(void) {
|
||||||
#endif /* HAVE_RESOLV_H */
|
#endif /* HAVE_RESOLV_H */
|
||||||
|
|
||||||
|
|
||||||
|
#if WITH_DEVTESTS
|
||||||
|
|
||||||
|
/* Have a couple of hard coded sockaddr records, to be copied and adapted when
|
||||||
|
needed */
|
||||||
|
|
||||||
|
static bool devtests_inited = false;
|
||||||
|
|
||||||
|
static struct sockaddr_in sockaddr_localhost_4 = {
|
||||||
|
#if HAVE_STRUCT_SOCKADDR_SALEN
|
||||||
|
sizeof(struct sockaddr_in),
|
||||||
|
#endif
|
||||||
|
AF_INET, /*htons*/0, { 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct sockaddr_in6 sockaddr_localhost_6 = {
|
||||||
|
#if HAVE_STRUCT_SOCKADDR_SALEN
|
||||||
|
sizeof(struct sockaddr_in6),
|
||||||
|
#endif
|
||||||
|
AF_INET6, /*htons*/0, 0, { { { 0 } } }, 0
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct addrinfo addrinfo_localhost_4 = {
|
||||||
|
0, AF_INET, 0, 0,
|
||||||
|
sizeof(struct sockaddr_in),
|
||||||
|
(struct sockaddr *)&sockaddr_localhost_4,
|
||||||
|
NULL,
|
||||||
|
NULL
|
||||||
|
} ;
|
||||||
|
|
||||||
|
static struct addrinfo addrinfo_localhost_6 = {
|
||||||
|
0, AF_INET6, 0, 0,
|
||||||
|
sizeof(struct sockaddr_in6),
|
||||||
|
(struct sockaddr *)&sockaddr_localhost_6,
|
||||||
|
NULL,
|
||||||
|
NULL
|
||||||
|
} ;
|
||||||
|
|
||||||
|
static struct addrinfo addrinfo_localhost_4_6[2] =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
0, AF_INET, 0, 0,
|
||||||
|
sizeof(sockaddr_localhost_4),
|
||||||
|
NULL, /* memdup(sockaddr_localhost_4) */
|
||||||
|
NULL,
|
||||||
|
NULL /* &addrinfo_localhost_4_6[1] */
|
||||||
|
},
|
||||||
|
{
|
||||||
|
0, AF_INET6, 0, 0,
|
||||||
|
sizeof(sockaddr_localhost_6),
|
||||||
|
NULL, /* memdup(sockaddr_localhost_6) */
|
||||||
|
NULL,
|
||||||
|
NULL
|
||||||
|
},
|
||||||
|
} ;
|
||||||
|
|
||||||
|
static struct addrinfo addrinfo_localhost_6_4[2] =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
0, AF_INET6, 0, 0,
|
||||||
|
sizeof(sockaddr_localhost_6),
|
||||||
|
NULL, /* memdup(sockaddr_localhost_6) */
|
||||||
|
NULL,
|
||||||
|
NULL, /* &addrinfo_localhost_6_4[1] */
|
||||||
|
},
|
||||||
|
{
|
||||||
|
0, AF_INET, 0, 0,
|
||||||
|
sizeof(sockaddr_localhost_4),
|
||||||
|
NULL, /* memdup(sockaddr_localhost_4) */
|
||||||
|
NULL,
|
||||||
|
NULL },
|
||||||
|
} ;
|
||||||
|
|
||||||
|
/* We keep track of the copied records because they must not be paaed to
|
||||||
|
freeaddrinfo() */
|
||||||
|
#define MAX_HARDCODED_RECORDS 16
|
||||||
|
static struct addrinfo *keep_hardcoded_records[MAX_HARDCODED_RECORDS];
|
||||||
|
static int count_hardcoded_records;
|
||||||
|
|
||||||
|
/* returns 0 on success, EAI_NODATA when no matching af, or
|
||||||
|
EAI_NONAME when node did not match the special names */
|
||||||
|
static int xioip_getaddrinfo_devtests(
|
||||||
|
const char *node,
|
||||||
|
const char *service,
|
||||||
|
int family,
|
||||||
|
int socktype,
|
||||||
|
int protocol,
|
||||||
|
struct addrinfo **res,
|
||||||
|
const int ai_flags[2])
|
||||||
|
{
|
||||||
|
if (!devtests_inited) {
|
||||||
|
devtests_inited = true;
|
||||||
|
sockaddr_localhost_4.sin_addr.s_addr = htonl((127<<24)+1); /* 127.0.0.1 */
|
||||||
|
#if WITH_IP6
|
||||||
|
xioip6_pton("::1", &sockaddr_localhost_6.sin6_addr, 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
if (node == NULL) {
|
||||||
|
;
|
||||||
|
#if WITH_IP4
|
||||||
|
} else if (!strcmp(node, "localhost-4")
|
||||||
|
|| !strcmp(node, "localhost-4-6") && family == AF_INET
|
||||||
|
|| !strcmp(node, "localhost-6-4") && family == AF_INET
|
||||||
|
#if !WITH_IP6
|
||||||
|
|| !strcmp(node, "localhost-4-6")
|
||||||
|
|| !strcmp(node, "localhost-6-4")
|
||||||
|
#endif /* !WITH_IP6 */
|
||||||
|
) {
|
||||||
|
if (family == AF_INET6)
|
||||||
|
return EAI_NODATA;
|
||||||
|
*res = memdup(&addrinfo_localhost_4, sizeof(addrinfo_localhost_4));
|
||||||
|
(*res)->ai_socktype = socktype;
|
||||||
|
(*res)->ai_protocol = protocol;
|
||||||
|
(*res)->ai_addr = memdup(&sockaddr_localhost_4, sizeof(sockaddr_localhost_4));
|
||||||
|
((struct sockaddr_in *)((*res)->ai_addr))->sin_port = (service?htons(atoi(service)):0);
|
||||||
|
keep_hardcoded_records[count_hardcoded_records++] = *res;
|
||||||
|
return 0;
|
||||||
|
#endif /* WITH_IP4 */
|
||||||
|
|
||||||
|
#if WITH_IP6
|
||||||
|
} else if (!strcmp(node, "localhost-6")
|
||||||
|
|| !strcmp(node, "localhost-4-6") && family == AF_INET6
|
||||||
|
|| !strcmp(node, "localhost-6-4") && family == AF_INET6
|
||||||
|
#if !WITH_IP4
|
||||||
|
|| !strcmp(node, "localhost-4-6")
|
||||||
|
|| !strcmp(node, "localhost-6-4")
|
||||||
|
#endif /* !WITH_IP4 */
|
||||||
|
) {
|
||||||
|
if (family == AF_INET)
|
||||||
|
return EAI_NODATA;
|
||||||
|
*res = memdup(&addrinfo_localhost_6, sizeof(addrinfo_localhost_6));
|
||||||
|
(*res)->ai_socktype = socktype;
|
||||||
|
(*res)->ai_protocol = protocol;
|
||||||
|
(*res)->ai_addr = memdup(&sockaddr_localhost_6, sizeof(sockaddr_localhost_6));
|
||||||
|
((struct sockaddr_in6 *)((*res)->ai_addr))->sin6_port =
|
||||||
|
(service?htons(atoi(service)):0);
|
||||||
|
keep_hardcoded_records[count_hardcoded_records++] = *res;
|
||||||
|
return 0;
|
||||||
|
#endif /* !WITH_IP6 */
|
||||||
|
|
||||||
|
#if WITH_IP4 && WITH_IP6
|
||||||
|
} else if (!strcmp(node, "localhost-4-6")) {
|
||||||
|
/* here we come only when both WITH_IP4,WITH_IP6, and family not 4 or 6 */
|
||||||
|
*res = memdup(&addrinfo_localhost_4_6, sizeof(addrinfo_localhost_4_6));
|
||||||
|
(*res)[0].ai_socktype = socktype;
|
||||||
|
(*res)[0].ai_protocol = protocol;
|
||||||
|
(*res)[0].ai_addr = memdup(&sockaddr_localhost_4, sizeof(sockaddr_localhost_4));
|
||||||
|
((struct sockaddr_in *)((*res)[0].ai_addr))->sin_port =
|
||||||
|
(service?htons(atoi(service)):0);
|
||||||
|
(*res)[0].ai_next = &(*res)[1];
|
||||||
|
(*res)[1].ai_socktype = socktype;
|
||||||
|
(*res)[1].ai_protocol = protocol;
|
||||||
|
(*res)[1].ai_addr = memdup(&sockaddr_localhost_6, sizeof(sockaddr_localhost_6));
|
||||||
|
((struct sockaddr_in6 *)((*res)[1].ai_addr))->sin6_port =
|
||||||
|
(service?htons(atoi(service)):0);
|
||||||
|
keep_hardcoded_records[count_hardcoded_records++] = *res;
|
||||||
|
return 0;
|
||||||
|
#endif /* WITH_IP4 && WITH_IP6 */
|
||||||
|
|
||||||
|
#if WITH_IP4 && WITH_IP6
|
||||||
|
} else if (!strcmp(node, "localhost-6-4")) {
|
||||||
|
/* here we come only when both WITH_IP4,WITH_IP6, and family not 4,6 */
|
||||||
|
*res = memdup(&addrinfo_localhost_6_4, sizeof(addrinfo_localhost_6_4));
|
||||||
|
(*res)[0].ai_socktype = socktype;
|
||||||
|
(*res)[0].ai_protocol = protocol;
|
||||||
|
(*res)[0].ai_addr = memdup(&sockaddr_localhost_6, sizeof(sockaddr_localhost_6));
|
||||||
|
((struct sockaddr_in6 *)((*res)[0].ai_addr))->sin6_port =
|
||||||
|
(service?htons(atoi(service)):0);
|
||||||
|
(*res)[0].ai_next = &(*res)[1];
|
||||||
|
(*res)[1].ai_socktype = socktype;
|
||||||
|
(*res)[1].ai_protocol = protocol;
|
||||||
|
(*res)[1].ai_addr = memdup(&sockaddr_localhost_4, sizeof(sockaddr_localhost_4));
|
||||||
|
((struct sockaddr_in *)((*res)[1].ai_addr))->sin_port =
|
||||||
|
service?htons(atoi(service)):0;
|
||||||
|
keep_hardcoded_records[count_hardcoded_records++] = *res;
|
||||||
|
return 0;
|
||||||
|
#endif /* WITH_IP4 && WITH_IP6 */
|
||||||
|
|
||||||
|
}
|
||||||
|
if (count_hardcoded_records == MAX_HARDCODED_RECORDS)
|
||||||
|
--count_hardcoded_records; /* more records will leak memory */
|
||||||
|
|
||||||
|
return EAI_NONAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Checks if res is a devtests construct, returns 0 if so,
|
||||||
|
or 1 otherwise */
|
||||||
|
static int xioip_freeaddrinfo_devtests(
|
||||||
|
struct addrinfo *res)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i=0; i<16; ++i) {
|
||||||
|
if (res == keep_hardcoded_records[i]) {
|
||||||
|
free(res);
|
||||||
|
keep_hardcoded_records[i] = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif /* WITH_DEVTESTS */
|
||||||
|
|
||||||
|
|
||||||
/* the ultimate(?) socat resolver function
|
/* the ultimate(?) socat resolver function
|
||||||
node: the address to be resolved; supported forms:
|
node: the address to be resolved; supported forms:
|
||||||
1.2.3.4 (IPv4 address)
|
1.2.3.4 (IPv4 address)
|
||||||
|
@ -171,7 +373,7 @@ int Res_init(void) {
|
||||||
family: PF_INET, PF_INET6, or PF_UNSPEC permitting both
|
family: PF_INET, PF_INET6, or PF_UNSPEC permitting both
|
||||||
socktype: SOCK_STREAM, SOCK_DGRAM, ...
|
socktype: SOCK_STREAM, SOCK_DGRAM, ...
|
||||||
protocol: IPPROTO_UDP, IPPROTO_TCP
|
protocol: IPPROTO_UDP, IPPROTO_TCP
|
||||||
sau: an uninitialized storage for the resulting socket address
|
res: a pointer to an uninitialized ptr var for the resulting socket address
|
||||||
returns: STAT_OK, STAT_RETRYLATER, STAT_NORETRY, prints message
|
returns: STAT_OK, STAT_RETRYLATER, STAT_NORETRY, prints message
|
||||||
*/
|
*/
|
||||||
int xiogetaddrinfo(const char *node, const char *service,
|
int xiogetaddrinfo(const char *node, const char *service,
|
||||||
|
@ -186,8 +388,11 @@ int xiogetaddrinfo(const char *node, const char *service,
|
||||||
#endif
|
#endif
|
||||||
int error_num;
|
int error_num;
|
||||||
|
|
||||||
|
Debug8("xiogetaddrinfo(node=\"%s\", service=\"%s\", family=%d, socktype=%d, protoco=%d, ai_flags={0x%04x/0x%04x} }, res=%p",
|
||||||
|
node?node:"NULL", service?service:"NULL", family, socktype, protocol,
|
||||||
|
ai_flags?ai_flags[0]:0, ai_flags?ai_flags[1]:0, res);
|
||||||
if (service && service[0]=='\0') {
|
if (service && service[0]=='\0') {
|
||||||
Error("empty port/service");
|
Error("xiogetaddrinfo(): empty port and service");
|
||||||
}
|
}
|
||||||
|
|
||||||
#if LATER
|
#if LATER
|
||||||
|
@ -202,6 +407,48 @@ int xiogetaddrinfo(const char *node, const char *service,
|
||||||
#endif /* WITH_VSOCK */
|
#endif /* WITH_VSOCK */
|
||||||
#endif /* LATER */
|
#endif /* LATER */
|
||||||
|
|
||||||
|
#if WITH_DEVTESTS
|
||||||
|
if (node != NULL && strchr(node, '.') &&
|
||||||
|
(!strcmp(strchr(node, '.'), ".dest-unreach.net") ||
|
||||||
|
!strcmp(strchr(node, '.'), ".dest-unreach.net."))) {
|
||||||
|
char *hname = strdup(node);
|
||||||
|
|
||||||
|
Info("dest-unreach.net domain handled specially");
|
||||||
|
if (hname == NULL)
|
||||||
|
return EAI_MEMORY;
|
||||||
|
if (hname[strlen(hname)-1] == '.')
|
||||||
|
hname[strlen(hname)-1] = '\0';
|
||||||
|
*strchr(hname, '.') = '\0';
|
||||||
|
error_num =
|
||||||
|
xioip_getaddrinfo_devtests(hname, service, family, socktype, protocol,
|
||||||
|
res, ai_flags);
|
||||||
|
if (error_num == EAI_NONAME) {
|
||||||
|
Warn("dest-unreach.net domain name does not resolve specially");
|
||||||
|
/* Pass through to libc resolver */
|
||||||
|
} else if (error_num != 0) {
|
||||||
|
Error7("getaddrinfo(\"%s\", \"%s\", {0x%02x,%d,%d,%d}, {}): %s",
|
||||||
|
node?node:"NULL", service?service:"NULL",
|
||||||
|
hints.ai_flags, hints.ai_family,
|
||||||
|
hints.ai_socktype, hints.ai_protocol,
|
||||||
|
(error_num == EAI_SYSTEM)?
|
||||||
|
strerror(errno):gai_strerror(error_num));
|
||||||
|
return error_num;
|
||||||
|
} else { /* ok */
|
||||||
|
#if WITH_MSGLEVEL <= E_DEBUG
|
||||||
|
struct addrinfo *record;
|
||||||
|
record = *res;
|
||||||
|
while (record) {
|
||||||
|
char buff[256/*!*/];
|
||||||
|
sockaddr_info(record->ai_addr, record->ai_addrlen, buff, sizeof(buff));
|
||||||
|
Debug5("getaddrinfo() -> flags=0x%02x family=%d socktype=%d protocol=%d addr=%s", record->ai_flags, record->ai_family, record->ai_socktype, record->ai_protocol, buff);
|
||||||
|
record = record->ai_next;
|
||||||
|
}
|
||||||
|
#endif /* WITH_MSGLEVEL <= E_DEBUG */
|
||||||
|
return error_num;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* WITH_DEVTESTS */
|
||||||
|
|
||||||
/* the resolver functions might handle numeric forms of node names by
|
/* the resolver functions might handle numeric forms of node names by
|
||||||
reverse lookup, that's not what we want.
|
reverse lookup, that's not what we want.
|
||||||
So we detect these and handle them specially */
|
So we detect these and handle them specially */
|
||||||
|
@ -407,6 +654,11 @@ int xiogetaddrinfo(const char *node, const char *service,
|
||||||
}
|
}
|
||||||
|
|
||||||
void xiofreeaddrinfo(struct addrinfo *res) {
|
void xiofreeaddrinfo(struct addrinfo *res) {
|
||||||
|
#if WITH_DEVTESTS
|
||||||
|
if (!xioip_freeaddrinfo_devtests(res)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#if HAVE_GETADDRINFO
|
#if HAVE_GETADDRINFO
|
||||||
freeaddrinfo(res);
|
freeaddrinfo(res);
|
||||||
#else
|
#else
|
||||||
|
|
51
xioopts.c
51
xioopts.c
|
@ -3338,7 +3338,7 @@ int retropt_bind(struct opt *opts,
|
||||||
return STAT_NORETRY;
|
return STAT_NORETRY;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#endif /* WITH_IP4 || WITH_IP6 */
|
#endif /* WITH_IP4 || WITH_IP6 || WITH_VSOCK */
|
||||||
|
|
||||||
#if WITH_UNIX
|
#if WITH_UNIX
|
||||||
case AF_UNIX:
|
case AF_UNIX:
|
||||||
|
@ -3367,6 +3367,52 @@ int retropt_bind(struct opt *opts,
|
||||||
}
|
}
|
||||||
return STAT_OK;
|
return STAT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
#if _WITH_IP4 || _WITH_IP6
|
||||||
|
/* Looks for a bind option and, if found, calls xiogetaddrinfo and provides the
|
||||||
|
results list in bindlist.
|
||||||
|
returns STAT_OK if option exists and could be resolved,
|
||||||
|
STAT_NORETRY if option exists but had error,
|
||||||
|
or STAT_NOACTION if it does not exist */
|
||||||
|
int retropt_bind_gai(struct opt *opts,
|
||||||
|
int af,
|
||||||
|
int socktype,
|
||||||
|
int ipproto,
|
||||||
|
struct addrinfo **bindlist,
|
||||||
|
int feats, /* TCP etc: 1..address allowed,
|
||||||
|
3..address and port allowed
|
||||||
|
*/
|
||||||
|
const int ai_flags[2])
|
||||||
|
{
|
||||||
|
|
||||||
|
if (retropt_string(opts, OPT_BIND, &bindname) < 0) {
|
||||||
|
return STAT_NOACTION;
|
||||||
|
}
|
||||||
|
bindp = bindname;
|
||||||
|
|
||||||
|
switch (af) {
|
||||||
|
|
||||||
|
#if WITH_IP4 || WITH_IP6
|
||||||
|
case AF_UNSPEC:
|
||||||
|
#if WITH_IP4
|
||||||
|
case AF_INET:
|
||||||
|
#endif
|
||||||
|
#if WITH_IP6
|
||||||
|
case AF_INET6:
|
||||||
|
#endif /*WITH_IP6 */
|
||||||
|
break;
|
||||||
|
#endif /* WITH_IP4 || WITH_IP6 */
|
||||||
|
|
||||||
|
default:
|
||||||
|
Error1("bind: unknown address family %d", af);
|
||||||
|
return STAT_NORETRY;
|
||||||
|
}
|
||||||
|
return STAT_OK;
|
||||||
|
}
|
||||||
|
#endif /* _WITH_IP4 || _WITH_IP6 */
|
||||||
|
#endif /* 0 */
|
||||||
|
|
||||||
#endif /* _WITH_SOCKET */
|
#endif /* _WITH_SOCKET */
|
||||||
|
|
||||||
|
|
||||||
|
@ -4196,7 +4242,8 @@ int applyopts_fchown(int fd, struct opt *opts) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* caller must make sure that option is not yet consumed */
|
/* Offset means a position in the sfd record where value is written.
|
||||||
|
Caller must make sure that option is not yet consumed */
|
||||||
static int applyopt_offset(struct single *sfd, struct opt *opt) {
|
static int applyopt_offset(struct single *sfd, struct opt *opt) {
|
||||||
unsigned char *ptr;
|
unsigned char *ptr;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue