mirror of
https://repo.or.cz/socat.git
synced 2024-12-22 15:32:35 +00:00
IP-SENDTO with pf=ip4 failed with "trailing garbage"
This commit is contained in:
parent
602a54420e
commit
bd727963a0
4 changed files with 53 additions and 71 deletions
4
CHANGES
4
CHANGES
|
@ -19,8 +19,8 @@ Corrections:
|
||||||
did not work.
|
did not work.
|
||||||
Thanks to Linus Luessing for reporting this bug.
|
Thanks to Linus Luessing for reporting this bug.
|
||||||
|
|
||||||
Up to version 1.8.0.0 IP-SENDTO and option pf (protocol-family) with
|
IP-SENDTO and option pf (protocol-family) with protocol name (vs.numeric
|
||||||
protocol name (vs.numeric argument) failed with message:
|
argument) failed with message:
|
||||||
E retropts_int(): trailing garbage in numerical arg of option "protocol-family"
|
E retropts_int(): trailing garbage in numerical arg of option "protocol-family"
|
||||||
Test: IP_SENDTO_PF
|
Test: IP_SENDTO_PF
|
||||||
|
|
||||||
|
|
|
@ -346,7 +346,7 @@ int sockaddr_vm_parse(struct sockaddr_vm *sa, const char *cid_str,
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif /* WITH_IP4 */
|
#endif /* WITH_VSOCK */
|
||||||
|
|
||||||
#if !HAVE_INET_NTOP
|
#if !HAVE_INET_NTOP
|
||||||
/* http://www.opengroup.org/onlinepubs/000095399/functions/inet_ntop.html */
|
/* http://www.opengroup.org/onlinepubs/000095399/functions/inet_ntop.html */
|
||||||
|
|
72
xio-ip.c
72
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);
|
ai_flags?ai_flags[0]:0, ai_flags?ai_flags[1]:0, res);
|
||||||
if (service && service[0]=='\0') {
|
if (service && service[0]=='\0') {
|
||||||
Error("xiogetaddrinfo(): empty port and service");
|
Error("xiogetaddrinfo(): empty port and service");
|
||||||
|
return EAI_NONAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if LATER
|
#if LATER
|
||||||
#ifdef WITH_VSOCK
|
#ifdef WITH_VSOCK
|
||||||
if (family == AF_VSOCK) {
|
if (family == AF_VSOCK) {
|
||||||
error_num = sockaddr_vm_parse(&sau->vm, node, service);
|
error_num = sockaddr_vm_parse(&sau->vm, node, service);
|
||||||
if (error_num < 0)
|
if (error_num < 0) {
|
||||||
return STAT_NORETRY;
|
errno = EINVAL;
|
||||||
|
return EAI_SYSTEM;
|
||||||
return STAT_OK;
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
#endif /* WITH_VSOCK */
|
#endif /* WITH_VSOCK */
|
||||||
#endif /* LATER */
|
#endif /* LATER */
|
||||||
|
@ -457,7 +459,7 @@ int xiogetaddrinfo(const char *node, const char *service,
|
||||||
#if WITH_IP6
|
#if WITH_IP6
|
||||||
} else if (node && node[0] == '[' && node[(nodelen=strlen(node))-1]==']') {
|
} else if (node && node[0] == '[' && node[(nodelen=strlen(node))-1]==']') {
|
||||||
if ((numnode = Malloc(nodelen-1)) == NULL)
|
if ((numnode = Malloc(nodelen-1)) == NULL)
|
||||||
return STAT_NORETRY;
|
return EAI_MEMORY;
|
||||||
|
|
||||||
strncpy(numnode, node+1, nodelen-2); /* ok */
|
strncpy(numnode, node+1, nodelen-2); /* ok */
|
||||||
numnode[nodelen-2] = '\0';
|
numnode[nodelen-2] = '\0';
|
||||||
|
@ -507,25 +509,19 @@ int xiogetaddrinfo(const char *node, const char *service,
|
||||||
freeaddrinfo(*res);
|
freeaddrinfo(*res);
|
||||||
if (numnode)
|
if (numnode)
|
||||||
free(numnode);
|
free(numnode);
|
||||||
return STAT_NORETRY;
|
return EAI_SERVICE;
|
||||||
}
|
}
|
||||||
/* Probably unsupported protocol (e.g. UDP-Lite), fallback to 0 */
|
/* Probably unsupported protocol (e.g. UDP-Lite), fallback to 0 */
|
||||||
hints.ai_protocol = 0;
|
hints.ai_protocol = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ((error_num = Getaddrinfo(node, service, &hints, res)) != 0) {
|
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)
|
if (*res != NULL)
|
||||||
freeaddrinfo(*res);
|
freeaddrinfo(*res);
|
||||||
if (numnode)
|
if (numnode)
|
||||||
free(numnode);
|
free(numnode);
|
||||||
|
|
||||||
return STAT_RETRYLATER;
|
return error_num;
|
||||||
}
|
}
|
||||||
} while (1);
|
} while (1);
|
||||||
service = NULL; /* do not resolve later again */
|
service = NULL; /* do not resolve later again */
|
||||||
|
@ -645,12 +641,13 @@ int xiogetaddrinfo(const char *node, const char *service,
|
||||||
|
|
||||||
#else
|
#else
|
||||||
Error("no resolver function available");
|
Error("no resolver function available");
|
||||||
return STAT_NORETRY;
|
errno = ENOSYS;
|
||||||
|
return EAI_SYSTEM;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (numnode) free(numnode);
|
if (numnode) free(numnode);
|
||||||
|
|
||||||
return STAT_OK;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void xiofreeaddrinfo(struct addrinfo *res) {
|
void xiofreeaddrinfo(struct addrinfo *res) {
|
||||||
|
@ -668,11 +665,12 @@ void xiofreeaddrinfo(struct addrinfo *res) {
|
||||||
|
|
||||||
/* A simple resolver interface that just returns one address,
|
/* A simple resolver interface that just returns one address,
|
||||||
the first found by calling xiogetaddrinfo().
|
the first found by calling xiogetaddrinfo().
|
||||||
family may be AF_INET, AF_INET6, or AF_UNSPEC;
|
pf may be AF_INET, AF_INET6, or AF_UNSPEC;
|
||||||
Returns -1 when an error occurred or when no result found.
|
on failure logs error message;
|
||||||
|
returns STAT_OK, STAT_RETRYLATER, STAT_NORETRY
|
||||||
*/
|
*/
|
||||||
int xioresolve(const char *node, const char *service,
|
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,
|
union sockaddr_union *addr, socklen_t *addrlen,
|
||||||
const int ai_flags[2])
|
const int ai_flags[2])
|
||||||
{
|
{
|
||||||
|
@ -680,28 +678,38 @@ int xioresolve(const char *node, const char *service,
|
||||||
struct addrinfo *aip;
|
struct addrinfo *aip;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
rc = xiogetaddrinfo(node, service, family, socktype, protocol,
|
rc = xiogetaddrinfo(node, service, pf, socktype, protocol,
|
||||||
&res, ai_flags);
|
&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);
|
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) {
|
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);
|
xiofreeaddrinfo(res);
|
||||||
return -1;
|
return STAT_NORETRY;
|
||||||
}
|
}
|
||||||
if (res->ai_addrlen > *addrlen) {
|
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);
|
xiofreeaddrinfo(res);
|
||||||
return -1;
|
return STAT_NORETRY;
|
||||||
}
|
}
|
||||||
if (res->ai_next != NULL) {
|
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?"\"":"");
|
Info4("xioresolve(node=\"%s\", service=%s%s%s, ...): More than one address found", node?node:"NULL", service?"\"":"", service?service:"NULL", service?"\"":"");
|
||||||
}
|
}
|
||||||
|
|
||||||
aip = res;
|
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,
|
/* We select the first IPv6 address, if available,
|
||||||
because this might accept IPv4 connections too */
|
because this might accept IPv4 connections too */
|
||||||
while (aip != NULL) {
|
while (aip != NULL) {
|
||||||
|
@ -711,12 +719,22 @@ int xioresolve(const char *node, const char *service,
|
||||||
}
|
}
|
||||||
if (aip == NULL)
|
if (aip == NULL)
|
||||||
aip = res;
|
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);
|
memcpy(addr, aip->ai_addr, aip->ai_addrlen);
|
||||||
*addrlen = aip->ai_addrlen;
|
*addrlen = aip->ai_addrlen;
|
||||||
xiofreeaddrinfo(res);
|
xiofreeaddrinfo(res);
|
||||||
return 0;
|
return STAT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(HAVE_STRUCT_CMSGHDR) && defined(CMSG_DATA)
|
#if defined(HAVE_STRUCT_CMSGHDR) && defined(CMSG_DATA)
|
||||||
|
|
46
xio-udp.c
46
xio-udp.c
|
@ -286,21 +286,8 @@ int xioopen_ipdgram_listen(
|
||||||
}
|
}
|
||||||
|
|
||||||
xioinit_ip(&pf, xioparms.default_ip);
|
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_socket_pf(opts, &pf);
|
||||||
|
|
||||||
retropt_int(opts, OPT_SO_PROTOTYPE, &ipproto);
|
retropt_int(opts, OPT_SO_PROTOTYPE, &ipproto);
|
||||||
|
|
||||||
if (applyopts_single(sfd, opts, PH_INIT) < 0)
|
if (applyopts_single(sfd, opts, PH_INIT) < 0)
|
||||||
|
@ -460,6 +447,7 @@ int xioopen_udp_datagram(
|
||||||
sfd->para.socket.ip.dosourceport = true;
|
sfd->para.socket.ip.dosourceport = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xioinit_ip(&pf, xioparms.default_ip);
|
||||||
retropt_socket_pf(opts, &pf);
|
retropt_socket_pf(opts, &pf);
|
||||||
|
|
||||||
result =
|
result =
|
||||||
|
@ -535,23 +523,11 @@ int xioopen_udp_recvfrom(
|
||||||
}
|
}
|
||||||
|
|
||||||
xioinit_ip(&pf, xioparms.default_ip);
|
xioinit_ip(&pf, xioparms.default_ip);
|
||||||
|
retropt_socket_pf(opts, &pf);
|
||||||
|
|
||||||
sfd->howtoend = END_NONE;
|
sfd->howtoend = END_NONE;
|
||||||
if (sfd->howtoend == END_UNSPEC)
|
if (sfd->howtoend == END_UNSPEC)
|
||||||
sfd->howtoend = END_NONE;
|
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 */
|
/* Set AI_PASSIVE, except when it is explicitely disabled */
|
||||||
ai_flags2[0] = xfd->stream.para.socket.ip.ai_flags[0];
|
ai_flags2[0] = xfd->stream.para.socket.ip.ai_flags[0];
|
||||||
|
@ -626,20 +602,8 @@ int xioopen_udp_recv(
|
||||||
return STAT_NORETRY;
|
return STAT_NORETRY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xioinit_ip(&pf, xioparms.default_ip);
|
||||||
retropt_socket_pf(opts, &pf);
|
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 */
|
/* Set AI_PASSIVE, except when it is explicitely disabled */
|
||||||
ai_flags2[0] = xfd->stream.para.socket.ip.ai_flags[0];
|
ai_flags2[0] = xfd->stream.para.socket.ip.ai_flags[0];
|
||||||
|
|
Loading…
Reference in a new issue