From bd727963a027673810b1813de64437e19e48fdad Mon Sep 17 00:00:00 2001 From: Gerhard Rieger Date: Fri, 26 Jul 2024 10:14:57 +0200 Subject: [PATCH] IP-SENDTO with pf=ip4 failed with "trailing garbage" --- CHANGES | 4 +-- sysutils.c | 2 +- xio-ip.c | 72 ++++++++++++++++++++++++++++++++++-------------------- xio-udp.c | 46 ++++------------------------------ 4 files changed, 53 insertions(+), 71 deletions(-) diff --git a/CHANGES b/CHANGES index a15e331..7b30fd0 100644 --- a/CHANGES +++ b/CHANGES @@ -19,8 +19,8 @@ Corrections: did not work. Thanks to Linus Luessing for reporting this bug. - Up to version 1.8.0.0 IP-SENDTO and option pf (protocol-family) with - protocol name (vs.numeric argument) failed with message: + IP-SENDTO and option pf (protocol-family) with protocol name (vs.numeric + argument) failed with message: E retropts_int(): trailing garbage in numerical arg of option "protocol-family" Test: IP_SENDTO_PF diff --git a/sysutils.c b/sysutils.c index c62d555..ee24454 100644 --- a/sysutils.c +++ b/sysutils.c @@ -346,7 +346,7 @@ int sockaddr_vm_parse(struct sockaddr_vm *sa, const char *cid_str, return 0; } -#endif /* WITH_IP4 */ +#endif /* WITH_VSOCK */ #if !HAVE_INET_NTOP /* http://www.opengroup.org/onlinepubs/000095399/functions/inet_ntop.html */ diff --git a/xio-ip.c b/xio-ip.c index 6d07f63..f188c77 100644 --- a/xio-ip.c +++ b/xio-ip.c @@ -393,16 +393,18 @@ int xiogetaddrinfo(const char *node, const char *service, ai_flags?ai_flags[0]:0, ai_flags?ai_flags[1]:0, res); if (service && service[0]=='\0') { Error("xiogetaddrinfo(): empty port and service"); + return EAI_NONAME; } #if LATER #ifdef WITH_VSOCK if (family == AF_VSOCK) { error_num = sockaddr_vm_parse(&sau->vm, node, service); - if (error_num < 0) - return STAT_NORETRY; - - return STAT_OK; + if (error_num < 0) { + errno = EINVAL; + return EAI_SYSTEM; + } + return 0; } #endif /* WITH_VSOCK */ #endif /* LATER */ @@ -457,7 +459,7 @@ 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) - return STAT_NORETRY; + return EAI_MEMORY; strncpy(numnode, node+1, nodelen-2); /* ok */ numnode[nodelen-2] = '\0'; @@ -507,25 +509,19 @@ int xiogetaddrinfo(const char *node, const char *service, freeaddrinfo(*res); if (numnode) free(numnode); - return STAT_NORETRY; + return EAI_SERVICE; } /* Probably unsupported protocol (e.g. UDP-Lite), fallback to 0 */ hints.ai_protocol = 0; continue; } if ((error_num = Getaddrinfo(node, service, &hints, res)) != 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)); if (*res != NULL) freeaddrinfo(*res); if (numnode) free(numnode); - return STAT_RETRYLATER; + return error_num; } } while (1); service = NULL; /* do not resolve later again */ @@ -645,12 +641,13 @@ int xiogetaddrinfo(const char *node, const char *service, #else Error("no resolver function available"); - return STAT_NORETRY; + errno = ENOSYS; + return EAI_SYSTEM; #endif if (numnode) free(numnode); - return STAT_OK; + return 0; } void xiofreeaddrinfo(struct addrinfo *res) { @@ -668,11 +665,12 @@ void xiofreeaddrinfo(struct addrinfo *res) { /* A simple resolver interface that just returns one address, the first found by calling xiogetaddrinfo(). - family may be AF_INET, AF_INET6, or AF_UNSPEC; - Returns -1 when an error occurred or when no result found. + pf may be AF_INET, AF_INET6, or AF_UNSPEC; + on failure logs error message; + returns STAT_OK, STAT_RETRYLATER, STAT_NORETRY */ int xioresolve(const char *node, const char *service, - int family, int socktype, int protocol, + int pf, int socktype, int protocol, union sockaddr_union *addr, socklen_t *addrlen, const int ai_flags[2]) { @@ -680,28 +678,38 @@ int xioresolve(const char *node, const char *service, struct addrinfo *aip; int rc; - rc = xiogetaddrinfo(node, service, family, socktype, protocol, + rc = xiogetaddrinfo(node, service, pf, socktype, protocol, &res, ai_flags); - if (rc != 0) { + if (rc == EAI_AGAIN) { + Warn3("xioresolve(node=\"%s\", pf=%d, ...): %s", + node?node:"NULL", pf, gai_strerror(rc)); xiofreeaddrinfo(res); - return -1; + return STAT_RETRYLATER; + } else if (rc != 0) { + Error3("xioresolve(node=\"%s\", pf=%d, ...): %s", + node?node:"NULL", pf, + (rc == EAI_SYSTEM)?strerror(errno):gai_strerror(rc)); + xiofreeaddrinfo(res); + return STAT_NORETRY; } if (res == NULL) { - Warn1("xioresolve(node=\"%s\", ...): No result", node); + Error3("xioresolve(node=\"%s\", pf=%d, ...): %s", + node?node:"NULL", pf, gai_strerror(EAI_NODATA)); xiofreeaddrinfo(res); - return -1; + return STAT_NORETRY; } if (res->ai_addrlen > *addrlen) { - Warn3("xioresolve(node=\"%s\", addrlen="F_socklen", ...): "F_socklen" bytes required", node, *addrlen, res->ai_addrlen); + Error3("xioresolve(node=\"%s\", addrlen="F_socklen", ...): "F_socklen" bytes required", + node, *addrlen, res->ai_addrlen); xiofreeaddrinfo(res); - return -1; + return STAT_NORETRY; } if (res->ai_next != NULL) { Info4("xioresolve(node=\"%s\", service=%s%s%s, ...): More than one address found", node?node:"NULL", service?"\"":"", service?service:"NULL", service?"\"":""); } aip = res; - if (ai_flags != NULL && ai_flags[0] & AI_PASSIVE && family == PF_UNSPEC) { + if (ai_flags != NULL && ai_flags[0] & AI_PASSIVE && pf == PF_UNSPEC) { /* We select the first IPv6 address, if available, because this might accept IPv4 connections too */ while (aip != NULL) { @@ -711,12 +719,22 @@ int xioresolve(const char *node, const char *service, } if (aip == NULL) aip = res; + } else if (pf == PF_UNSPEC && xioparms.preferred_ip != '0') { + int prefip = PF_UNSPEC; + xioinit_ip(&prefip, xioparms.preferred_ip); + while (aip != NULL) { + if (aip->ai_family == prefip) + break; + aip = aip->ai_next; + } + if (aip == NULL) + aip = res; } memcpy(addr, aip->ai_addr, aip->ai_addrlen); *addrlen = aip->ai_addrlen; xiofreeaddrinfo(res); - return 0; + return STAT_OK; } #if defined(HAVE_STRUCT_CMSGHDR) && defined(CMSG_DATA) diff --git a/xio-udp.c b/xio-udp.c index b624281..10704e3 100644 --- a/xio-udp.c +++ b/xio-udp.c @@ -286,21 +286,8 @@ int xioopen_ipdgram_listen( } xioinit_ip(&pf, xioparms.default_ip); - if (pf == PF_UNSPEC) { -#if WITH_IP4 && WITH_IP6 - switch (xioparms.default_ip) { - case '4': pf = PF_INET; break; - case '6': pf = PF_INET6; break; - default: break; /* includes \0 */ - } -#elif WITH_IP6 - pf = PF_INET6; -#else - pf = PF_INET; -#endif - } - retropt_socket_pf(opts, &pf); + retropt_int(opts, OPT_SO_PROTOTYPE, &ipproto); if (applyopts_single(sfd, opts, PH_INIT) < 0) @@ -460,6 +447,7 @@ int xioopen_udp_datagram( sfd->para.socket.ip.dosourceport = true; } + xioinit_ip(&pf, xioparms.default_ip); retropt_socket_pf(opts, &pf); result = @@ -535,23 +523,11 @@ int xioopen_udp_recvfrom( } xioinit_ip(&pf, xioparms.default_ip); + retropt_socket_pf(opts, &pf); + sfd->howtoend = END_NONE; if (sfd->howtoend == END_UNSPEC) sfd->howtoend = END_NONE; - retropt_socket_pf(opts, &pf); - if (pf == PF_UNSPEC) { -#if WITH_IP4 && WITH_IP6 - switch (xioparms.default_ip) { - case '4': pf = PF_INET; break; - case '6': pf = PF_INET6; break; - default: break; /* includes \0 */ - } -#elif WITH_IP6 - pf = PF_INET6; -#else - pf = PF_INET; -#endif - } /* Set AI_PASSIVE, except when it is explicitely disabled */ ai_flags2[0] = xfd->stream.para.socket.ip.ai_flags[0]; @@ -626,20 +602,8 @@ int xioopen_udp_recv( return STAT_NORETRY; } + xioinit_ip(&pf, xioparms.default_ip); retropt_socket_pf(opts, &pf); - if (pf == PF_UNSPEC) { -#if WITH_IP4 && WITH_IP6 - switch (xioparms.default_ip) { - case '4': pf = PF_INET; break; - case '6': pf = PF_INET6; break; - default: break; /* includes \0 */ - } -#elif WITH_IP6 - pf = PF_INET6; -#else - pf = PF_INET; -#endif - } /* Set AI_PASSIVE, except when it is explicitely disabled */ ai_flags2[0] = xfd->stream.para.socket.ip.ai_flags[0];