IP-SENDTO with pf=ip4 failed with "trailing garbage"

This commit is contained in:
Gerhard Rieger 2024-07-26 10:14:57 +02:00
parent 602a54420e
commit bd727963a0
4 changed files with 53 additions and 71 deletions

View file

@ -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

View file

@ -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 */

View file

@ -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)

View file

@ -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];