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