1
0
Fork 0
mirror of https://repo.or.cz/socat.git synced 2025-07-15 07:33:25 +00:00

Options res-* now apply to whole open phase

This commit is contained in:
Gerhard Rieger 2023-11-05 19:39:01 +01:00
parent b14e65c42a
commit c82e3df210
29 changed files with 204 additions and 207 deletions

133
xio-ip.c
View file

@ -82,11 +82,13 @@ const struct optdesc opt_ip_recvif = { "ip-recvif", "recvdstaddrif",OPT_IP_RECVI
#endif
#ifdef AI_ADDRCONFIG
const struct optdesc opt_ai_addrconfig = { "ai-addrconfig", "addrconfig", OPT_AI_ADDRCONFIG, GROUP_SOCK_IP, PH_INIT, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.socket.ip.ai_flags), XIO_SIZEOF(para.socket.ip.ai_flags), AI_ADDRCONFIG };
const struct optdesc opt_ai_v4mapped = { "ai-v4mapped", "v4mapped", OPT_AI_V4MAPPED, GROUP_SOCK_IP, PH_INIT, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.socket.ip.ai_flags), XIO_SIZEOF(para.socket.ip.ai_flags), AI_V4MAPPED };
const struct optdesc opt_ai_addrconfig = { "ai-addrconfig", "addrconfig", OPT_AI_ADDRCONFIG, GROUP_SOCK_IP, PH_OFFSET, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.socket.ip.ai_flags), XIO_SIZEOF(para.socket.ip.ai_flags), AI_ADDRCONFIG };
#endif
#ifdef AI_V4MAPPED
const struct optdesc opt_ai_v4mapped = { "ai-v4mapped", "v4mapped", OPT_AI_V4MAPPED, GROUP_SOCK_IP, PH_OFFSET, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.socket.ip.ai_flags), XIO_SIZEOF(para.socket.ip.ai_flags), AI_V4MAPPED };
#endif
#ifdef AI_PASSIVE
const struct optdesc opt_ai_passive = { "ai-passive", "passive", OPT_AI_PASSIVE, GROUP_SOCK_IP, PH_INIT, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.socket.ip.ai_flags), XIO_SIZEOF(para.socket.ip.ai_flags), AI_PASSIVE };
const struct optdesc opt_ai_passive = { "ai-passive", "passive", OPT_AI_PASSIVE, GROUP_SOCK_IP, PH_OFFSET, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.socket.ip.ai_flags), XIO_SIZEOF(para.socket.ip.ai_flags), AI_PASSIVE };
#endif
#if WITH_RES_DEPRECATED
@ -94,19 +96,19 @@ const struct optdesc opt_ai_passive = { "ai-passive", "passive", OPT_AI
# define WITH_RES_PRIMARY 1
#endif /* WITH_RES_DEPRECATED */
#if HAVE_RESOLV_H
const struct optdesc opt_res_debug = { "res-debug", NULL, OPT_RES_DEBUG, GROUP_SOCK_IP, PH_INIT, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.socket.ip.res_opts), XIO_SIZEOF(para.socket.ip.res_opts), RES_DEBUG };
const struct optdesc opt_res_debug = { "res-debug", NULL, OPT_RES_DEBUG, GROUP_SOCK_IP, PH_OFFSET, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.socket.ip.res_opts), XIO_SIZEOF(para.socket.ip.res_opts), RES_DEBUG };
#if WITH_RES_AAONLY
const struct optdesc opt_res_aaonly = { "res-aaonly", "aaonly", OPT_RES_AAONLY, GROUP_SOCK_IP, PH_INIT, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.socket.ip.res_opts), XIO_SIZEOF(para.socket.ip.res_opts), RES_AAONLY };
const struct optdesc opt_res_aaonly = { "res-aaonly", "aaonly", OPT_RES_AAONLY, GROUP_SOCK_IP, PH_OFFSET, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.socket.ip.res_opts), XIO_SIZEOF(para.socket.ip.res_opts), RES_AAONLY };
#endif
const struct optdesc opt_res_usevc = { "res-usevc", "usevc", OPT_RES_USEVC, GROUP_SOCK_IP, PH_INIT, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.socket.ip.res_opts), XIO_SIZEOF(para.socket.ip.res_opts), RES_USEVC };
const struct optdesc opt_res_usevc = { "res-usevc", "usevc", OPT_RES_USEVC, GROUP_SOCK_IP, PH_OFFSET, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.socket.ip.res_opts), XIO_SIZEOF(para.socket.ip.res_opts), RES_USEVC };
#if WITH_RES_PRIMARY
const struct optdesc opt_res_primary = { "res-primary", "primary", OPT_RES_PRIMARY, GROUP_SOCK_IP, PH_INIT, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.socket.ip.res_opts), XIO_SIZEOF(para.socket.ip.res_opts), RES_PRIMARY };
const struct optdesc opt_res_primary = { "res-primary", "primary", OPT_RES_PRIMARY, GROUP_SOCK_IP, PH_OFFSET, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.socket.ip.res_opts), XIO_SIZEOF(para.socket.ip.res_opts), RES_PRIMARY };
#endif
const struct optdesc opt_res_igntc = { "res-igntc", "igntc", OPT_RES_IGNTC, GROUP_SOCK_IP, PH_INIT, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.socket.ip.res_opts), XIO_SIZEOF(para.socket.ip.res_opts), RES_IGNTC };
const struct optdesc opt_res_recurse = { "res-recurse", "recurse", OPT_RES_RECURSE, GROUP_SOCK_IP, PH_INIT, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.socket.ip.res_opts), XIO_SIZEOF(para.socket.ip.res_opts), RES_RECURSE };
const struct optdesc opt_res_defnames = { "res-defnames", "defnames", OPT_RES_DEFNAMES, GROUP_SOCK_IP, PH_INIT, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.socket.ip.res_opts), XIO_SIZEOF(para.socket.ip.res_opts), RES_DEFNAMES };
const struct optdesc opt_res_stayopen = { "res-stayopen", "stayopen", OPT_RES_STAYOPEN, GROUP_SOCK_IP, PH_INIT, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.socket.ip.res_opts), XIO_SIZEOF(para.socket.ip.res_opts), RES_STAYOPEN };
const struct optdesc opt_res_dnsrch = { "res-dnsrch", "dnsrch", OPT_RES_DNSRCH, GROUP_SOCK_IP, PH_INIT, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.socket.ip.res_opts), XIO_SIZEOF(para.socket.ip.res_opts), RES_DNSRCH };
const struct optdesc opt_res_igntc = { "res-igntc", "igntc", OPT_RES_IGNTC, GROUP_SOCK_IP, PH_OFFSET, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.socket.ip.res_opts), XIO_SIZEOF(para.socket.ip.res_opts), RES_IGNTC };
const struct optdesc opt_res_recurse = { "res-recurse", "recurse", OPT_RES_RECURSE, GROUP_SOCK_IP, PH_OFFSET, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.socket.ip.res_opts), XIO_SIZEOF(para.socket.ip.res_opts), RES_RECURSE };
const struct optdesc opt_res_defnames = { "res-defnames", "defnames", OPT_RES_DEFNAMES, GROUP_SOCK_IP, PH_OFFSET, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.socket.ip.res_opts), XIO_SIZEOF(para.socket.ip.res_opts), RES_DEFNAMES };
const struct optdesc opt_res_stayopen = { "res-stayopen", "stayopen", OPT_RES_STAYOPEN, GROUP_SOCK_IP, PH_OFFSET, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.socket.ip.res_opts), XIO_SIZEOF(para.socket.ip.res_opts), RES_STAYOPEN };
const struct optdesc opt_res_dnsrch = { "res-dnsrch", "dnsrch", OPT_RES_DNSRCH, GROUP_SOCK_IP, PH_OFFSET, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.socket.ip.res_opts), XIO_SIZEOF(para.socket.ip.res_opts), RES_DNSRCH };
#endif /* HAVE_RESOLV_H */
#endif /* WITH_IP4 || WITH_IP6 */
@ -161,11 +163,9 @@ unsigned long res_opts() {
*/
int xiogetaddrinfo(const char *node, const char *service,
int family, int socktype, int protocol,
struct addrinfo **res, const int ai_flags[2],
const unsigned long res_opts[2]) {
struct addrinfo **res, const int ai_flags[2]) {
char *numnode = NULL;
size_t nodelen;
unsigned long save_res_opts = 0;
#if HAVE_GETADDRINFO
struct addrinfo hints = {0};
#else /* HAVE_PROTOTYPE_LIB_getipnodebyname || nothing */
@ -173,19 +173,6 @@ int xiogetaddrinfo(const char *node, const char *service,
#endif
int error_num;
#if HAVE_RESOLV_H
if (res_opts[0] | res_opts[1]) {
if (!(_res.options & RES_INIT)) {
Res_init(); /*!!! returns -1 on error */
}
save_res_opts = _res.options;
_res.options |= res_opts[0];
_res.options &= ~res_opts[1];
Debug2("changed _res.options from 0x%lx to 0x%lx",
save_res_opts, _res.options);
}
#endif /* HAVE_RESOLV_H */
if (service && service[0]=='\0') {
Error("empty port/service");
}
@ -209,14 +196,9 @@ int xiogetaddrinfo(const char *node, const char *service,
;
#if WITH_IP6
} else if (node && node[0] == '[' && node[(nodelen=strlen(node))-1]==']') {
if ((numnode = Malloc(nodelen-1)) == NULL) {
#if HAVE_RESOLV_H
if (res_opts[0] | res_opts[1]) {
_res.options = save_res_opts;
}
#endif
if ((numnode = Malloc(nodelen-1)) == NULL)
return STAT_NORETRY;
}
strncpy(numnode, node+1, nodelen-2); /* ok */
numnode[nodelen-2] = '\0';
node = numnode;
@ -273,13 +255,8 @@ int xiogetaddrinfo(const char *node, const char *service,
hints.ai_socktype, hints.ai_protocol,
(error_num == EAI_SYSTEM)?
strerror(errno):gai_strerror(error_num));
if (numnode) free(numnode);
#if HAVE_RESOLV_H
if (res_opts[0] | res_opts[1]) {
_res.options = save_res_opts;
}
#endif
if (numnode)
free(numnode);
return STAT_RETRYLATER;
}
} while (1);
@ -373,11 +350,6 @@ int xiogetaddrinfo(const char *node, const char *service,
Error2("gethostbyname(\"%s\"): %s", node,
h_errno == NETDB_INTERNAL ? strerror(errno) :
hstrerror(h_errno));
#if HAVE_RESOLV_H
if (res_opts[0] | res_opts[1]) {
_res.options = save_res_opts;
}
#endif
return STAT_RETRYLATER;
}
if (host->h_addrtype != family) {
@ -407,11 +379,6 @@ int xiogetaddrinfo(const char *node, const char *service,
if (numnode) free(numnode);
#if HAVE_RESOLV_H
if (res_opts[0] | res_opts[1]) {
_res.options = save_res_opts;
}
#endif /* HAVE_RESOLV_H */
return STAT_OK;
}
@ -431,14 +398,14 @@ void xiofreeaddrinfo(struct addrinfo *res) {
int xioresolve(const char *node, const char *service,
int family, int socktype, int protocol,
union sockaddr_union *addr, socklen_t *addrlen,
const int ai_flags[2], const unsigned long res_opts[2])
const int ai_flags[2])
{
struct addrinfo *res = NULL;
struct addrinfo *aip;
int rc;
rc = xiogetaddrinfo(node, service, family, socktype, protocol,
&res, ai_flags, res_opts);
&res, ai_flags);
if (rc != 0) {
xiofreeaddrinfo(res);
return -1;
@ -789,7 +756,7 @@ mc:addr
xioresolve(opt->value.u_string/*multiaddr*/, NULL,
xfd->para.socket.la.soa.sa_family,
SOCK_DGRAM, IPPROTO_IP, &sockaddr1, &socklen1,
xfd->para.socket.ip.ai_flags, xfd->para.socket.ip.res_opts);
xfd->para.socket.ip.ai_flags);
ip4_mreqn.mreq.imr_multiaddr = sockaddr1.ip4.sin_addr;
if (0) {
; /* for canonical reasons */
@ -800,8 +767,7 @@ mc:addr
xioresolve(opt->value2.u_string/*param2*/, NULL,
xfd->para.socket.la.soa.sa_family,
SOCK_DGRAM, IPPROTO_IP, &sockaddr2, &socklen2,
xfd->para.socket.ip.ai_flags,
xfd->para.socket.ip.res_opts);
xfd->para.socket.ip.ai_flags);
ip4_mreqn.mreq.imr_interface = sockaddr2.ip4.sin_addr;
/* third parameter is interface */
if (ifindex(opt->value3.u_string/*ifindex*/,
@ -830,8 +796,7 @@ mc:addr
xfd->para.socket.la.soa.sa_family,
SOCK_DGRAM, IPPROTO_IP,
&sockaddr2, &socklen2,
xfd->para.socket.ip.ai_flags,
xfd->para.socket.ip.res_opts);
xfd->para.socket.ip.ai_flags);
ip4_mreqn.mreq.imr_interface = sockaddr2.ip4.sin_addr;
}
}
@ -982,8 +947,7 @@ int xioapply_ip_add_source_membership(struct single *xfd, struct opt *opt) {
rc = xioresolve(opt->value.u_string/*mcaddr*/, NULL,
xfd->para.socket.la.soa.sa_family,
SOCK_DGRAM, IPPROTO_IP,
&sockaddr1, &socklen1, xfd->para.socket.ip.ai_flags,
xfd->para.socket.ip.res_opts);
&sockaddr1, &socklen1, xfd->para.socket.ip.ai_flags);
if (rc < 0) {
return -1;
}
@ -992,8 +956,7 @@ int xioapply_ip_add_source_membership(struct single *xfd, struct opt *opt) {
rc = xioresolve(opt->value.u_string/*ifaddr*/, NULL,
xfd->para.socket.la.soa.sa_family,
SOCK_DGRAM, IPPROTO_IP,
&sockaddr2, &socklen2, xfd->para.socket.ip.ai_flags,
xfd->para.socket.ip.res_opts);
&sockaddr2, &socklen2, xfd->para.socket.ip.ai_flags);
if (rc < 0) {
return -1;
}
@ -1002,8 +965,7 @@ int xioapply_ip_add_source_membership(struct single *xfd, struct opt *opt) {
rc = xioresolve(opt->value.u_string/*srcaddr*/, NULL,
xfd->para.socket.la.soa.sa_family,
SOCK_DGRAM, IPPROTO_IP,
&sockaddr3, &socklen3, xfd->para.socket.ip.ai_flags,
xfd->para.socket.ip.res_opts);
&sockaddr3, &socklen3, xfd->para.socket.ip.ai_flags);
if (rc < 0) {
return -1;
}
@ -1022,6 +984,47 @@ int xioapply_ip_add_source_membership(struct single *xfd, struct opt *opt) {
}
return 0;
}
#endif /* HAVE_STRUCT_IP_MREQ_SOURCE */
#if HAVE_RESOLV_H
/* When there are options for resolver then this function saves the current
resolver settings to save_res and applies the options to resolver libs state
in _res.
Returns 1 when there were options (state needs to be restored later, see
xio_res_restore());
Returns 0 when there were no options;
Returns -1 on error. */
int xio_res_init(
struct single *sfd,
struct __res_state *save_res)
{
if (sfd->para.socket.ip.res_opts[0] ||
sfd->para.socket.ip.res_opts[1]) {
if (!(_res.options & RES_INIT)) {
if (Res_init() < 0) {
Error("res_init() failed");
return -1;
}
}
*save_res = _res;
_res.options |= sfd->para.socket.ip.res_opts[0];
_res.options &= ~sfd->para.socket.ip.res_opts[1];
Debug2("changed _res.options from 0x%lx to 0x%lx",
save_res->options, _res.options);
return 1;
}
return 0;
}
int xio_res_restore(
struct __res_state *save_res)
{
_res = *save_res;
return 0;
}
#endif /* HAVE_RESOLV_H */
#endif /* _WITH_IP4 || _WITH_IP6 */