Added option res-nsaddr

This commit is contained in:
Gerhard Rieger 2023-10-01 22:16:20 +02:00
parent 282db9feda
commit 254958a34d
12 changed files with 234 additions and 12 deletions

View file

@ -140,6 +140,9 @@ Features:
number of times to retransmit. number of times to retransmit.
Disable them and the old res-* opts with: ./configure --disable-resolve Disable them and the old res-* opts with: ./configure --disable-resolve
Added option res-nsaddr that overrides /etc/resolv.conf nameserver
address based on an undocumented resolver feature.
Corrections: Corrections:
When a sub process (EXEC, SYSTEM) terminated with exit code other than When a sub process (EXEC, SYSTEM) terminated with exit code other than
0, its last sent data might have been lost depending on timing of read/ 0, its last sent data might have been lost depending on timing of read/

View file

@ -1 +1 @@
"1.7.4.5+" "1.7.4.5+20230721"

View file

@ -680,6 +680,7 @@
#undef HAVE_RES_RETRANS #undef HAVE_RES_RETRANS
#undef HAVE_RES_RETRY #undef HAVE_RES_RETRY
#undef HAVE_RES_NSADDR_LIST
#undef HAVE_SETGRENT #undef HAVE_SETGRENT
#undef HAVE_GETGRENT #undef HAVE_GETGRENT

View file

@ -2156,6 +2156,12 @@ AC_TRY_COMPILE([#include <resolv.h>],
[AC_MSG_RESULT(yes); [AC_MSG_RESULT(yes);
AC_DEFINE(HAVE_RES_RETRY, 1)], AC_DEFINE(HAVE_RES_RETRY, 1)],
[AC_MSG_RESULT(no)]) [AC_MSG_RESULT(no)])
AC_MSG_CHECKING(for _res.nsaddr_list)
AC_TRY_COMPILE([#include <resolv.h>],
[_res.nsaddr_list[0].sin_family == 0],
[AC_MSG_RESULT(yes);
AC_DEFINE(HAVE_RES_NSADDR_LIST, 1)],
[AC_MSG_RESULT(no)])
dnl "tcpd" "tcpwrappers" dnl "tcpd" "tcpwrappers"

View file

@ -2397,23 +2397,39 @@ label(OPTOIN_IP_TRANSPARENT)
dit(bf(tt(ip-transparent))) dit(bf(tt(ip-transparent)))
Sets the IP_TRANSPARENT socket option. Sets the IP_TRANSPARENT socket option.
This option might require root privilege. This option might require root privilege.
enddit()
startdit()enddit()nl()
label(OPTIONS_RESOLVER)em(bf(Resolver options))
These options temporarily change the behaviour of hostname resolution. The
options of form code(ai-*) affect behaviour of the code(getaddrinfo()) function that
includes code(/etc/hosts) and NIS based lookups.
The addresses of form code(res-*) only affect DNS lookups, and only when the
result is not cached in code(nscd). These options might not work on all
operating systems or libc implementations.
startdit()
label(OPTION_AI_ADDRCONFIG) label(OPTION_AI_ADDRCONFIG)
dit(bf(tt(ai-addrconfig[=0|1]))), dit(bf(tt(addrconfig[=0|1]))) dit(bf(tt(ai-addrconfig[=0|1]))) dit(bf(tt(addrconfig[=0|1])))
Sets or unsets the AI_ADDRCONFIG flag to prevent name resolution to address Sets or unsets the AI_ADDRCONFIG flag to prevent name resolution to address
families that are not available on the computer (e.g. IPv6). Default value families that are not available on the computer (e.g. IPv6). Default value
is 1 in case the resolver does not get an address family hint from Socat is 1 in case the resolver does not get an address family hint from Socat
address or defaults. address or defaults.
label(OPTION_AI_PASSIVE) label(OPTION_AI_PASSIVE)
dit(bf(tt(ai-passive[=0|1]))), dit(bf(tt(passive[=0|1]))) dit(bf(tt(ai-passive[=0|1]))) dit(bf(tt(passive[=0|1])))
Sets of unsets the AI_ADDRCONFIG flag for code(getaddrinfo()) calls. Sets of unsets the AI_PASSIVE flag for code(getaddrinfo()) calls.
Default is 1 for LISTEN, RECV, and RECVFROM type addresses, and with Default is 1 for LISTEN, RECV, and RECVFROM type addresses, and with
link(bind)(OPTION_BIND) option. link(bind)(OPTION_BIND) option.
label(OPTION_AI_V4MAPPED) label(OPTION_AI_V4MAPPED)
dit(bf(tt(ai-v4mapped[=0|1]))), dit(bf(tt(v4mapped[=0|1]))) dit(bf(tt(ai-v4mapped[=0|1]))) dit(bf(tt(v4mapped[=0|1])))
Sets or unsets the AI_V4MAPPED flag for code(getaddrinfo()). With socat() Sets or unsets the AI_V4MAPPED flag for code(getaddrinfo()). With socat()
addresses requiring IPv6 addresses, this resolves IPv4 addresses to the addresses requiring IPv6 addresses, this resolves IPv4 addresses to the
approriate IPv6 address [::ffff:*:*]. For IPv6 Socat addresses, the default approriate IPv6 address [::ffff:*:*]. For IPv6 Socat addresses, the default
is 1. is 1.
label(OPTION_RES_DEBUG)dit(bf(tt(res-debug))) label(OPTION_RES_DEBUG)dit(bf(tt(res-debug)))
label(OPTION_RES_AAONLY)dit(bf(tt(res-aaonly))) label(OPTION_RES_AAONLY)dit(bf(tt(res-aaonly)))
label(OPTION_RES_USEVC)dit(bf(tt(res-usevc))) label(OPTION_RES_USEVC)dit(bf(tt(res-usevc)))
@ -2437,6 +2453,12 @@ label(OPTION_RES_RETRANS)dit(bf(tt(res-retrans=<int>)))
label(OPTION_RES_RETRY)dit(bf(tt(res-retry=<int>))) label(OPTION_RES_RETRY)dit(bf(tt(res-retry=<int>)))
Sets the number of retransmits of the DNS resolver (based on an undocumented Sets the number of retransmits of the DNS resolver (based on an undocumented
feature). feature).
label(OPTION_RES_NSADDR)dit(bf(tt(res-nsaddr=<ipaddr>[:<port>])))
Tries to overwrite nameserver settings loaded from /etc/resolv.conf by
writing the given IPv4 address into the undocumented
code(_res:nsaddr_list[0]) field.
code(/etc/hosts) is still checked by resolver. Please note that glibc's
code(nscd) is always queried first when it is running!
enddit() enddit()
startdit()enddit()nl() startdit()enddit()nl()
@ -2707,6 +2729,7 @@ label(OPTION_ACCEPT_TIMEOUT)dit(bf(tt(accept-timeout=<seconds>)))
End waiting for a connection after <seconds> [link(timeval)(TYPE_TIMEVAL)] End waiting for a connection after <seconds> [link(timeval)(TYPE_TIMEVAL)]
with error status. with error status.
enddit() enddit()
startdit()enddit()nl() startdit()enddit()nl()
@ -2826,6 +2849,7 @@ label(GROUP_SHELL)
Options for link(address SHELL)(ADDRESS_SHELL) Options for link(address SHELL)(ADDRESS_SHELL)
startdit()
label(OPTION_SHELL)dit(bf(tt(shell=<filename>))) label(OPTION_SHELL)dit(bf(tt(shell=<filename>)))
Overwrites use the default shell with the named executable, e.g. Overwrites use the default shell with the named executable, e.g.
tt(/bin/dash). Also sets the tt(SHELL) environment variable. tt(/bin/dash). Also sets the tt(SHELL) environment variable.
@ -3217,6 +3241,7 @@ measures are required to get the VLAN information, see NOEXPAND(packet(7)) PACKE
and to optionally insert the tag into the packet again, use option and to optionally insert the tag into the packet again, use option
link(retrieve-vlan)(OPTION_RETRIEVE_VLAN) when you need this. link(retrieve-vlan)(OPTION_RETRIEVE_VLAN) when you need this.
startdit()
label(OPTION_RETRIEVE_VLAN)dit(bf(tt(retrieve-vlan))) label(OPTION_RETRIEVE_VLAN)dit(bf(tt(retrieve-vlan)))
On packets incoming on raw sockets, retrieve the VLAN information and insert On packets incoming on raw sockets, retrieve the VLAN information and insert
it into the packets for further processing (Linux) it into the packets for further processing (Linux)

75
test.sh
View file

@ -17287,6 +17287,80 @@ esac
N=$((N+1)) N=$((N+1))
# Test the res-nsaddr (resolver, dns) option
NAME=RES_NSADDR
case "$TESTS" in
*%$N%*|*%functions%*|*%resolv%*|*%ip4%*|*%tcp4%*|*%socket%*|*%$NAME%*)
TEST="$NAME: test the res-nsaddr option"
# Start a supplementary Socat instance that will receive the DNS query.
# Run main Socat process, opening an IPv4 socket with option res-nsaddr
# directed to the aux process.
# When the supplementary Socat instance received the query the test succeeded.
if ! eval $NUMCOND; then :;
elif ! F=$(testfeats STDIO IP4 UDP TCP); then
$PRINTF "test $F_n $TEST... ${YELLOW}Feature $F not configured in $SOCAT${NORMAL}\n" $N
numCANT=$((numCANT+1))
listCANT="$listCANT $N"
elif ! A=$(testaddrs STDIO TCP4 UDP-RECVFROM); then
$PRINTF "test $F_n $TEST... ${YELLOW}Address $A not available in $SOCAT${NORMAL}\n" $N
numCANT=$((numCANT+1))
listCANT="$listCANT $N"
elif ! o=$(testoptions res-nsaddr) >/dev/null; then
$PRINTF "test $F_n $TEST... ${YELLOW}Option $o not available in $SOCAT${NORMAL}\n" $N
numCANT=$((numCANT+1))
listCANT="$listCANT $N"
elif ! runsip4 >/dev/null; then
$PRINTF "test $F_n $TEST... ${YELLOW}IPv4 not available on host${NORMAL}\n" $N
numCANT=$((numCANT+1))
listCANT="$listCANT $N"
else
tf="$td/test$N.stdout"
te="$td/test$N.stderr"
tdiff="$td/test$N.diff"
da="$(echo test$N $(date) $RANDOM |tr ' :' '-')"
echo "$da" >"$td/test$N.da"
newport udp4 # or whatever proto, or drop this line
CMD0="$TRACE $SOCAT $opts -u UDP-RECVFROM:$PORT -"
CMD1="$TRACE $SOCAT $opts - TCP4:$da:0,res-nsaddr=$LOCALHOST:$PORT"
printf "test $F_n $TEST... " $N
$CMD0 >/dev/null 2>"${te}0" >"${tf}0" &
pid0=$!
waitudp4port $PORT 1
$CMD1 >"${tf}1" 2>"${te}1"
rc1=$?
kill $pid0 2>/dev/null; wait
if grep "$da" "${tf}0" >/dev/null; then
$PRINTF "$OK\n"
if [ "$VERBOSE" ]; then echo "$CMD0 &"; fi
if [ "$DEBUG" ]; then cat "${te}0" >&2; fi
if [ "$VERBOSE" ]; then echo "$CMD1"; fi
if [ "$DEBUG" ]; then cat "${te}1" >&2; fi
numOK=$((numOK+1))
elif pgrep -u root nscd >/dev/null 2>&1; then
$PRINTF "${YELLOW}FAILED (due to nscd?)${NORMAL}\n"
if [ "$VERBOSE" ]; then echo "$CMD0 &"; fi
if [ "$DEBUG" ]; then cat "${te}0" >&2; fi
if [ "$VERBOSE" ]; then echo "$CMD1"; fi
if [ "$DEBUG" ]; then cat "${te}1" >&2; fi
numCANT=$((numCANT+1))
listCANT="$listCANT $N"
namesCAnT="$namesCANT $NAME"
else
$PRINTF "$FAILED (query not received)\n"
echo "$CMD0 &"
cat "${te}0" >&2
echo "$CMD1"
cat "${te}1" >&2
numFAIL=$((numFAIL+1))
listFAIL="$listFAIL $N"
namesFAIL="$namesFAIL $NAME"
fi
fi # NUMCOND
;;
esac
N=$((N+1))
# end of common tests # end of common tests
################################################################################## ##################################################################################
@ -17502,6 +17576,7 @@ elif [ ??? ]; then
if [ "$DEBUG" ]; then cat "${te}1" >&2; fi if [ "$DEBUG" ]; then cat "${te}1" >&2; fi
numCANT=$((numCANT+1)) numCANT=$((numCANT+1))
listCANT="$listCANT $N" listCANT="$listCANT $N"
namesCANT="$namesCANT $NAME"
else else
$PRINTF "$OK\n" $PRINTF "$OK\n"
if [ "$VERBOSE" ]; then echo "$CMD0 &"; fi if [ "$VERBOSE" ]; then echo "$CMD0 &"; fi

View file

@ -116,6 +116,9 @@ const struct optdesc opt_res_retrans = { "res-retrans", "retrans", OPT_RES_RE
#if HAVE_RES_RETRY #if HAVE_RES_RETRY
const struct optdesc opt_res_retry = { "res-retry", NULL, OPT_RES_RETRY, GROUP_SOCK_IP, PH_OFFSET, TYPE_INT, OFUNC_OFFSET, XIO_OFFSETOF(para.socket.ip.res.retry), XIO_SIZEOF(para.socket.ip.res.retry), RES_MAXRETRY }; const struct optdesc opt_res_retry = { "res-retry", NULL, OPT_RES_RETRY, GROUP_SOCK_IP, PH_OFFSET, TYPE_INT, OFUNC_OFFSET, XIO_OFFSETOF(para.socket.ip.res.retry), XIO_SIZEOF(para.socket.ip.res.retry), RES_MAXRETRY };
#endif #endif
#if HAVE_RES_NSADDR_LIST
const struct optdesc opt_res_nsaddr = { "res-nsaddr", "dns", OPT_RES_NSADDR, GROUP_SOCK_IP, PH_OFFSET, TYPE_IP4SOCK, OFUNC_OFFSET, XIO_OFFSETOF(para.socket.ip.res.nsaddr), XIO_SIZEOF(para.socket.ip.res.retry), RES_MAXRETRY };
#endif
#endif /* HAVE_RESOLV_H */ #endif /* HAVE_RESOLV_H */
#endif /* WITH_RESOLVE */ #endif /* WITH_RESOLVE */
#endif /* WITH_IP4 || WITH_IP6 */ #endif /* WITH_IP4 || WITH_IP6 */
@ -139,7 +142,9 @@ int xioinit_ip(
return 0; return 0;
} }
#if HAVE_RESOLV_H #if HAVE_RESOLV_H
int Res_init(void) { int Res_init(void) {
int result; int result;
Debug("res_init()"); Debug("res_init()");
@ -147,13 +152,9 @@ int Res_init(void) {
Debug1("res_init() -> %d", result); Debug1("res_init() -> %d", result);
return result; return result;
} }
#endif /* HAVE_RESOLV_H */ #endif /* HAVE_RESOLV_H */
#if HAVE_RESOLV_H
unsigned long res_opts() {
return _res.options;
}
#endif /* HAVE_RESOLV_H */
/* 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:
@ -1015,7 +1016,18 @@ int xio_res_init(
struct __res_state *save_res) struct __res_state *save_res)
{ {
if (sfd->para.socket.ip.res.opts[0] || if (sfd->para.socket.ip.res.opts[0] ||
sfd->para.socket.ip.res.opts[1]) { sfd->para.socket.ip.res.opts[1] ||
#if HAVE_RES_RETRANS
sfd->para.socket.ip.res.retrans >= 0 ||
#endif
#if HAVE_RES_RETRY
sfd->para.socket.ip.res.retry >= 0 ||
#endif
#if HAVE_RES_NSADDR_LIST
sfd->para.socket.ip.res.nsaddr.sin_family != PF_UNSPEC ||
#endif
0 /* for canonical reasons */
) {
if (!(_res.options & RES_INIT)) { if (!(_res.options & RES_INIT)) {
if (Res_init() < 0) { if (Res_init() < 0) {
Error("res_init() failed"); Error("res_init() failed");
@ -1027,8 +1039,44 @@ int xio_res_init(
_res.options &= ~sfd->para.socket.ip.res.opts[1]; _res.options &= ~sfd->para.socket.ip.res.opts[1];
Debug2("changed _res.options from 0x%lx to 0x%lx", Debug2("changed _res.options from 0x%lx to 0x%lx",
save_res->options, _res.options); save_res->options, _res.options);
#if HAVE_RES_RETRANS
if (sfd->para.socket.ip.res.retrans >= 0) {
_res.retrans = sfd->para.socket.ip.res.retrans;
Debug2("changed _res.retrans from 0x%x to 0x%x",
save_res->retrans, _res.retrans);
}
#endif
#if HAVE_RES_RETRY
if (sfd->para.socket.ip.res.retry >= 0) {
_res.retry = sfd->para.socket.ip.res.retry;
Debug2("changed _res.retry from 0x%x to 0x%x",
save_res->retry, _res.retry);
}
#endif
#if HAVE_RES_NSADDR_LIST
if (sfd->para.socket.ip.res.nsaddr.sin_family == PF_INET) {
_res.nscount = 1;
_res.nsaddr_list[0] = sfd->para.socket.ip.res.nsaddr;
if (_res.nsaddr_list[0].sin_port == htons(0))
_res.nsaddr_list[0].sin_port = htons(53);
Debug10("changed _res.nsaddr_list[0] from %u.%u.%u.%u:%u to %u.%u.%u.%u:%u",
((unsigned char *)&save_res->nsaddr_list[0].sin_addr.s_addr)[0],
((unsigned char *)&save_res->nsaddr_list[0].sin_addr.s_addr)[1],
((unsigned char *)&save_res->nsaddr_list[0].sin_addr.s_addr)[2],
((unsigned char *)&save_res->nsaddr_list[0].sin_addr.s_addr)[3],
ntohs(save_res->nsaddr_list[0].sin_port),
((unsigned char *)&_res.nsaddr_list[0].sin_addr.s_addr)[0],
((unsigned char *)&_res.nsaddr_list[0].sin_addr.s_addr)[1],
((unsigned char *)&_res.nsaddr_list[0].sin_addr.s_addr)[2],
((unsigned char *)&_res.nsaddr_list[0].sin_addr.s_addr)[3],
ntohs(_res.nsaddr_list[0].sin_port));
}
#endif /* HAVE_RES_NSADDR_LIST */
return 1; return 1;
} }
return 0; return 0;
} }

View file

@ -44,6 +44,7 @@ extern const struct optdesc opt_res_stayopen;
extern const struct optdesc opt_res_dnsrch; extern const struct optdesc opt_res_dnsrch;
extern const struct optdesc opt_res_retrans; extern const struct optdesc opt_res_retrans;
extern const struct optdesc opt_res_retry; extern const struct optdesc opt_res_retry;
extern const struct optdesc opt_res_nsaddr;
extern int xioinit_ip(int *pf, char ipv); extern int xioinit_ip(int *pf, char ipv);

5
xio.h
View file

@ -143,6 +143,10 @@ struct para_ip_res {
#if HAVE_RES_RETRY #if HAVE_RES_RETRY
int retry; int retry;
#endif #endif
#if HAVE_RES_NSADDR_LIST
# undef nsaddr /* resolv.h might define this, breaks debugger */
struct sockaddr_in nsaddr;
#endif
} ; } ;
#endif /* WITH_RESOLVE && HAVE_RESOLV_H */ #endif /* WITH_RESOLVE && HAVE_RESOLV_H */
@ -423,6 +427,7 @@ union integral {
#endif /* HAVE_STRUCT_TIMESPEC */ #endif /* HAVE_STRUCT_TIMESPEC */
#if WITH_IP4 #if WITH_IP4
struct in_addr u_ip4addr; struct in_addr u_ip4addr;
struct sockaddr_in u_ip4sock;
#endif #endif
} ; } ;

View file

@ -22,7 +22,7 @@ static const char *optiontypenames[] = {
"OFF64_T", "INT:INT", "INT:INTP", "INT:BIN", "OFF64_T", "INT:INT", "INT:INTP", "INT:BIN",
"INT:STRING", "INT:INT:INT", "INT:INT:BIN", "INT:INT:STRING", "INT:STRING", "INT:INT:INT", "INT:INT:BIN", "INT:INT:STRING",
"INT:INT:GENERIC", "INT:INT:GENERIC",
"IP4NAME", "IP4NAME", "IP4SOCK",
#if HAVE_STRUCT_LINGER #if HAVE_STRUCT_LINGER
"STRUCT-LINGER", "STRUCT-LINGER",
#endif #endif

View file

@ -430,6 +430,9 @@ const struct optname optionnames[] = {
#ifdef VDISCARD #ifdef VDISCARD
IF_TERMIOS("discard", &opt_vdiscard) IF_TERMIOS("discard", &opt_vdiscard)
#endif #endif
#if HAVE_RES_NSADDR_LIST
IF_IP ("dns", &opt_res_nsaddr)
#endif
#if HAVE_RESOLV_H #if HAVE_RESOLV_H
IF_RESOLVE("dnsrch", &opt_res_dnsrch) IF_RESOLVE("dnsrch", &opt_res_dnsrch)
#endif /* HAVE_RESOLV_H */ #endif /* HAVE_RESOLV_H */
@ -1020,6 +1023,9 @@ const struct optname optionnames[] = {
IF_IP ("multicast-ttl", &opt_ip_multicast_ttl) IF_IP ("multicast-ttl", &opt_ip_multicast_ttl)
IF_IP ("multicastloop", &opt_ip_multicast_loop) IF_IP ("multicastloop", &opt_ip_multicast_loop)
IF_IP ("multicastttl", &opt_ip_multicast_ttl) IF_IP ("multicastttl", &opt_ip_multicast_ttl)
#if HAVE_RES_NSADDR_LIST
IF_IP ("nameserver", &opt_res_nsaddr)
#endif
#if defined(O_NDELAY) && (!defined(O_NONBLOCK) || O_NDELAY != O_NONBLOCK) #if defined(O_NDELAY) && (!defined(O_NONBLOCK) || O_NDELAY != O_NONBLOCK)
IF_ANY ("ndelay", &opt_o_ndelay) IF_ANY ("ndelay", &opt_o_ndelay)
#else #else
@ -1085,6 +1091,9 @@ const struct optname optionnames[] = {
IF_OPENSSL("nosni", &opt_openssl_no_sni) IF_OPENSSL("nosni", &opt_openssl_no_sni)
#endif #endif
IF_INTERFACE("notrailers", &opt_iff_notrailers) IF_INTERFACE("notrailers", &opt_iff_notrailers)
#if HAVE_RES_NSADDR_LIST
IF_IP ("nsaddr", &opt_res_nsaddr)
#endif
#ifdef O_NSHARE #ifdef O_NSHARE
IF_OPEN ("nshare", &opt_o_nshare) IF_OPEN ("nshare", &opt_o_nshare)
#endif #endif
@ -1426,6 +1435,9 @@ const struct optname optionnames[] = {
# if HAVE_RES_RETRY # if HAVE_RES_RETRY
IF_RESOLVE("res-maxretry", &opt_res_retry) IF_RESOLVE("res-maxretry", &opt_res_retry)
# endif # endif
# if HAVE_RES_NSADDR_LIST
IF_IP ("res-nsaddr", &opt_res_nsaddr)
# endif
# if WITH_RES_PRIMARY # if WITH_RES_PRIMARY
IF_RESOLVE("res-primary", &opt_res_primary) IF_RESOLVE("res-primary", &opt_res_primary)
# endif # endif
@ -2630,6 +2642,7 @@ int parseopts_table(const char **a, groups_t groups, struct opt **opts,
#if WITH_IP4 #if WITH_IP4
case TYPE_IP4NAME: case TYPE_IP4NAME:
{ {
/*! On a good day merge this with code in retropt_bind() */
struct sockaddr_in sa; socklen_t salen = sizeof(sa); struct sockaddr_in sa; socklen_t salen = sizeof(sa);
const char *ends[] = { NULL }; const char *ends[] = { NULL };
const char *nests[] = { "[","]", NULL }; const char *nests[] = { "[","]", NULL };
@ -2659,6 +2672,40 @@ int parseopts_table(const char **a, groups_t groups, struct opt **opts,
opt->value.u_ip4addr = sa.sin_addr; opt->value.u_ip4addr = sa.sin_addr;
} }
break; break;
case TYPE_IP4SOCK:
{
/*! On a good day merge this with code for TYPE_IP4NAME */
struct sockaddr_in sa; socklen_t salen = sizeof(sa);
const char portsep[] = ":";
const char *ends[] = { portsep, NULL };
const char *nests[] = { "[","]", NULL };
char hostname[512], *hostp = hostname, *portp = NULL;
size_t hostlen = sizeof(hostname)-1;
tokp = token;
parsres =
nestlex((const char **)&tokp, &hostp, &hostlen,
ends, NULL, NULL, nests,
true, false, false);
if (parsres < 0) {
Error1("option too long: \"%s\"", *a);
return -1;
} else if (parsres > 0) {
Error1("syntax error in \"%s\"", *a);
return -1;
}
*hostp++ = '\0';
if (!strncmp(tokp, portsep, strlen(portsep))) {
portp = tokp + strlen(portsep);
}
if (xioresolve(hostname, portp, AF_INET, SOCK_DGRAM, IPPROTO_IP,
(union sockaddr_union *)&sa, &salen, 0)
!= STAT_OK) {
opt->desc = ODESC_ERROR; continue;
}
opt->value.u_ip4sock = sa;
}
break;
#endif /* defined(WITH_IP4) */ #endif /* defined(WITH_IP4) */
#if LATER #if LATER
@ -4132,6 +4179,15 @@ static int applyopt_offset(struct single *sfd, struct opt *opt) {
case TYPE_CONST: case TYPE_CONST:
*(int *)ptr = opt->desc->minor; *(int *)ptr = opt->desc->minor;
break; break;
case TYPE_IP4NAME:
memset(ptr, 0, sizeof(struct sockaddr_in));
((struct sockaddr_in *)ptr)->sin_addr = opt->value.u_ip4addr;
((struct sockaddr_in *)ptr)->sin_family = PF_INET;
break;
case TYPE_IP4SOCK:
memset(ptr, 0, sizeof(struct sockaddr_in));
*(struct sockaddr_in *)ptr = opt->value.u_ip4sock;
break;
default: default:
Error2("applyopt_offset(opt:%s): type %s not implemented", Error2("applyopt_offset(opt:%s): type %s not implemented",
opt->desc->defname, xiohelp_opttypename(opt->desc->type)); opt->desc->defname, xiohelp_opttypename(opt->desc->type));

View file

@ -68,6 +68,7 @@ enum e_types {
TYPE_INT_INT_GENERIC, /* 3 params: first and second are int, 3rd is specified by value (dalan syntax) */ TYPE_INT_INT_GENERIC, /* 3 params: first and second are int, 3rd is specified by value (dalan syntax) */
TYPE_IP4NAME, /* IPv4 hostname or address */ TYPE_IP4NAME, /* IPv4 hostname or address */
TYPE_IP4SOCK, /* IPv4 hostname or address optionally with port */
#if HAVE_STRUCT_LINGER #if HAVE_STRUCT_LINGER
TYPE_LINGER, /* struct linger */ TYPE_LINGER, /* struct linger */
#endif /* HAVE_STRUCT_LINGER */ #endif /* HAVE_STRUCT_LINGER */
@ -628,6 +629,7 @@ enum e_optcode {
OPT_RES_DEFNAMES, /* resolver(3) */ OPT_RES_DEFNAMES, /* resolver(3) */
OPT_RES_DNSRCH, /* resolver(3) */ OPT_RES_DNSRCH, /* resolver(3) */
OPT_RES_IGNTC, /* resolver(3) */ OPT_RES_IGNTC, /* resolver(3) */
OPT_RES_NSADDR, /* undocumented */
OPT_RES_PRIMARY, /* resolver(3) */ OPT_RES_PRIMARY, /* resolver(3) */
OPT_RES_RECURSE, /* resolver(3) */ OPT_RES_RECURSE, /* resolver(3) */
OPT_RES_RETRANS, /* undocumented */ OPT_RES_RETRANS, /* undocumented */