* calls to socket() fail when calling getaddrinfo() with IPPROTO_TCP
@ 2021-07-29 22:41 John Scott
2021-07-30 9:34 ` Corinna Vinschen
2021-07-30 16:44 ` Brian Inglis
0 siblings, 2 replies; 5+ messages in thread
From: John Scott @ 2021-07-29 22:41 UTC (permalink / raw)
To: cygwin
[-- Attachment #1: Type: text/plain, Size: 1307 bytes --]
Hi,
I was wondering why my daytime server doesn't work when built for
Cygwin, and I have been able to narrow it down to this reproducible
test case:
#define _POSIX_C_SOURCE 200809L
#include <errno.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
int main(void) {
struct addrinfo *res;
int s = getaddrinfo(NULL, "daytime", &(const struct addrinfo){.ai_flags = AI_PASSIVE, .ai_protocol = IPPROTO_TCP}, &res);
if(s) {
fprintf(stderr, "Failed to get address info: %s\n", (s != EAI_SYSTEM) ? gai_strerror(s) : strerror(errno));
exit(EXIT_FAILURE);
}
for(const struct addrinfo *tmp = res; tmp; tmp = tmp->ai_next) {
int fd = socket(tmp->ai_family, tmp->ai_socktype, tmp->ai_protocol);
if(fd == -1) {
perror("Failed to create socket");
} else if(close(fd) == -1) {
perror("Failed to close socket");
}
}
freeaddrinfo(res);
}
This code fails with "Failed to create socket: Invalid argument". Does
anyone have an idea why this happens, given that the arguments to
socket() come directly from the call to getaddrinfo()? Remarkably,
changing the service from "daytime" to "http" seems to fix it, which
seems quite strange.
I'm not subscribed, so please CC me on replies.
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 252 bytes --]
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: calls to socket() fail when calling getaddrinfo() with IPPROTO_TCP
2021-07-29 22:41 calls to socket() fail when calling getaddrinfo() with IPPROTO_TCP John Scott
@ 2021-07-30 9:34 ` Corinna Vinschen
2021-07-30 10:47 ` Corinna Vinschen
2021-07-30 16:44 ` Brian Inglis
1 sibling, 1 reply; 5+ messages in thread
From: Corinna Vinschen @ 2021-07-30 9:34 UTC (permalink / raw)
To: John Scott; +Cc: cygwin
Hi John,
On Jul 29 22:41, John Scott via Cygwin wrote:
> Hi,
>
> I was wondering why my daytime server doesn't work when built for
> Cygwin, and I have been able to narrow it down to this reproducible
> test case:
> [...]
> This code fails with "Failed to create socket: Invalid argument". Does
> anyone have an idea why this happens, given that the arguments to
> socket() come directly from the call to getaddrinfo()?
Welcome to the Windows implementation of getaddrinfo.
Assuming you call getaddrinfo (NULL, "daytime", NULL, &result), you get
the following return from Linux:
family: 2 socktype 1 protocol 6 AF_INET, STREAM, TCP
family: 2 socktype 2 protocol 17 AF_INET, DGRAM, UCP
family: 10 socktype 1 protocol 6 AF_INET6, STREAM, TCP
family: 10 socktype 2 protocol 17 AF_INET6, DGRAM, UCP
The same call on Windows returns:
family: 23 socktype 0 protocol 0 AF_INET6, any, any
family: 2 socktype 0 protocol 0 AF_INET, any, any
If the service supports both, TCP and UDP, then socktype and protocol
are always 0 on Windows. The restriction from the hints parameter
*only* restricts the output for that very field!
I.e., your hints with .ai_protocol = IPPROTO_TCP only restricts the
output of the ai_protocol field, not the output of the ai_socktype
field:
family: 23 socktype 0 protocol 6 AF_INET6, any, TCP
family: 2 socktype 0 protocol 6 AF_INET, any, TCP
On Linux you get the less surprising result
family: 2 socktype 1 protocol 6 AF_INET, STREAM, TCP
family: 10 socktype 1 protocol 6 AF_INET6, STREAM, TCP
> Remarkably,
> changing the service from "daytime" to "http" seems to fix it, which
> seems quite strange.
Yeah, that's a bad joke as well. The reason is that the http service is
defined for TCP only. Not for UDP. As a result, Windows' getaddrinfo
suddenly returns a valid ai_socktype field:
family: 23 socktype 1 protocol 6 AF_INET6, STREAM, TCP
family: 2 socktype 1 protocol 6 AF_INET, STREAM, TCP
Cygwin implements a shallow (~300 lines) wrapper over the WinSock
GetAddrInfoW function and otherwise relies on the values returned by the
OS. However, it already duplicates the returned list to self-allocated
memory, which is required for fork(2) semantics. It should be possible
to improve the wrapper to duplicate entries with socktype and protocol
0-entries, but that would be in the next Cygwin version earliest.
Back to your problem. For the time being, you can easily "fix" your
code by changing the hints:
- int s = getaddrinfo(NULL, "daytime", &(const struct addrinfo){.ai_flags = AI_PASSIVE, .ai_protocol = IPPROTO_TCP}, &res);
+ int s = getaddrinfo(NULL, "daytime", &(const struct addrinfo){.ai_flags = AI_PASSIVE, .ai_socktype = SOCK_STREAM}, &res);
This returns
family: 23 socktype 1 protocol 0 AF_INET6, STREAM, any
family: 2 socktype 1 protocol 0 AF_INET, STREAM, any
The content of the protocol parameter doesn't really matter to socket(2),
so it will work on Cygwin as well as on Linux and others.
HTH,
Corinna
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: calls to socket() fail when calling getaddrinfo() with IPPROTO_TCP
2021-07-30 9:34 ` Corinna Vinschen
@ 2021-07-30 10:47 ` Corinna Vinschen
2021-07-30 11:02 ` John Scott
0 siblings, 1 reply; 5+ messages in thread
From: Corinna Vinschen @ 2021-07-30 10:47 UTC (permalink / raw)
To: cygwin; +Cc: John Scott
On Jul 30 11:34, Corinna Vinschen via Cygwin wrote:
> Yeah, that's a bad joke as well. The reason is that the http service is
> defined for TCP only. Not for UDP. As a result, Windows' getaddrinfo
> suddenly returns a valid ai_socktype field:
>
> family: 23 socktype 1 protocol 6 AF_INET6, STREAM, TCP
> family: 2 socktype 1 protocol 6 AF_INET, STREAM, TCP
Just to be precise here, the fact that ai_protocol is IPPROTO_TCP
in this example output is only because of your hints. If you don't
restrict ai_protocol, you'll get:
family: 23 socktype 1 protocol 0 AF_INET6, STREAM, any
family: 2 socktype 1 protocol 0 AF_INET, STREAM, any
> Cygwin implements a shallow (~300 lines) wrapper over the WinSock
> GetAddrInfoW function and otherwise relies on the values returned by the
> OS. However, it already duplicates the returned list to self-allocated
> memory, which is required for fork(2) semantics. It should be possible
> to improve the wrapper to duplicate entries with socktype and protocol
> 0-entries, but that would be in the next Cygwin version earliest.
I hacked up a patch which is supposed to do exactly that. In your case
it now returns
family: 23 socktype 1 protocol 6
family: 2 socktype 1 protocol 6
and in case you omit the ai_protocol restriction it returns with
family: 23 socktype 1 protocol 6
family: 23 socktype 2 protocol 17
family: 2 socktype 1 protocol 6
family: 2 socktype 2 protocol 17
rather than with
family: 23 socktype 0 protocol 0
family: 2 socktype 0 protocol 0
I've uploaded a new developer snapshot to https://cygwin.com/snapshots
Please give it a try and report back.
Thanks,
Corinna
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: calls to socket() fail when calling getaddrinfo() with IPPROTO_TCP
2021-07-30 10:47 ` Corinna Vinschen
@ 2021-07-30 11:02 ` John Scott
0 siblings, 0 replies; 5+ messages in thread
From: John Scott @ 2021-07-30 11:02 UTC (permalink / raw)
To: cygwin
[-- Attachment #1: Type: text/plain, Size: 281 bytes --]
On Fri, 2021-07-30 at 12:47 +0200, Corinna Vinschen wrote:
> I've uploaded a new developer snapshot to https://cygwin.com/snapshots
> Please give it a try and report back.
Thank you so much! The snapshot works perfectly and now my daytime
server works without code changes.
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 252 bytes --]
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: calls to socket() fail when calling getaddrinfo() with IPPROTO_TCP
2021-07-29 22:41 calls to socket() fail when calling getaddrinfo() with IPPROTO_TCP John Scott
2021-07-30 9:34 ` Corinna Vinschen
@ 2021-07-30 16:44 ` Brian Inglis
1 sibling, 0 replies; 5+ messages in thread
From: Brian Inglis @ 2021-07-30 16:44 UTC (permalink / raw)
To: cygwin; +Cc: John Scott
On 2021-07-29 16:41, John Scott via Cygwin wrote:
> I was wondering why my daytime server doesn't work when built for
> Cygwin, and I have been able to narrow it down to this reproducible
> test case:
...
> This code fails with "Failed to create socket: Invalid argument". Does
> anyone have an idea why this happens, given that the arguments to
> socket() come directly from the call to getaddrinfo()? Remarkably,
> changing the service from "daytime" to "http" seems to fix it, which
> seems quite strange.
>
> I'm not subscribed, so please CC me on replies.
These obsolete legacy time services have always been available built
into the inetd server in the inetutils package:
$ info inetutils inetd built-in
"daytime
Send back the current date and time in a human readable form. Any
input is discarded.
time
Send back the current date and time as a 32-bit integer number,
nrepresenting the number of seconds since midnight, January 1,
1900."
You could download the source package to study the implementation.
The time protocol client rdate is available from:
https://github.com/openbsd/src/tree/master/usr.sbin/rdate
As daytime is text in arbitrary display format (likely ctime(3),
asctime(3)) telnet, netcat, etc. to the service port was probably used.
For currently supported network time services, Meinberg has for many
years provided native Windows service ports of the latest releases of
the ntp.org NTP V4 client/server daemon, including a kernel serial
driver interface supporting GPS devices with PPS signal pins, the latest
OpenSSL, a Windows installer, and an interactive monitor to control and
display service daemon NTP info, and view loopstats and peerstats graphs:
https://www.meinbergglobal.com/english/sw/ntp.htm#ntp_stable
https://www.meinbergglobal.com/english/sw/ntp-server-monitor.htm
--
Take care. Thanks, Brian Inglis, Calgary, Alberta, Canada
This email may be disturbing to some readers as it contains
too much technical detail. Reader discretion is advised.
[Data in binary units and prefixes, physical quantities in SI.]
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2021-07-30 16:44 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-29 22:41 calls to socket() fail when calling getaddrinfo() with IPPROTO_TCP John Scott
2021-07-30 9:34 ` Corinna Vinschen
2021-07-30 10:47 ` Corinna Vinschen
2021-07-30 11:02 ` John Scott
2021-07-30 16:44 ` Brian Inglis
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).