Files
raven/testdata/native_loader/protocol_client.c
T
Clansty 24d09e747b feat: answer getprotobyname and getprotobynumber from the protocols database
- Both calls read the host's protocols database into one PROTOENT the process reuses, as Winsock reuses its per-thread one: the name, an empty list of aliases and the protocol number.

- The record keeps its pointers, so the 32-bit and 64-bit layouts are written apart; a protocol the database does not list answers NULL with WSANO_DATA, as the services calls beside them do.

- The new guest fixture protocol_client.c checks that both spellings of a protocol name the same record, that a second call reuses it, and that an unlisted name and an unlisted number are refused. It is built for 64-bit and 32-bit callers.

Assisted-by: Claude Code:deepseek-v4.1-flash-1017

AI-Scope: Wrote the two handlers next to the existing getservbyname ones, the PROTOENT writer for both pointer widths, and the guest fixture; checked with ctest (native_protocol_database_client, native_protocol_database_client_x32).
2026-11-02 11:59:35 +08:00

45 lines
1.4 KiB
C

#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
/* getprotobyname and getprotobynumber answer from the protocols database into one PROTOENT that the following call reuses, as Winsock
reuses its per-thread one. Both spellings of a protocol name the same record, and a protocol the database does not list is refused. */
static int same(const char *left, const char *right)
{
if (!left || !right)
return 0;
for (unsigned at = 0;; ++at) {
char a = left[at], b = right[at];
if (a >= 'A' && a <= 'Z')
a = (char)(a - 'A' + 'a');
if (a != b)
return 0;
if (!a)
return 1;
}
}
int raven_entry(void)
{
WSADATA data;
if (WSAStartup(MAKEWORD(2, 2), &data))
return 1;
struct protoent *tcp = getprotobyname("tcp");
if (!tcp || tcp->p_proto != 6 || !same(tcp->p_name, "tcp"))
return 2;
struct protoent *by_number = getprotobynumber(6);
if (!by_number || by_number->p_proto != 6 || !same(by_number->p_name, "tcp"))
return 3;
// The record is the one the earlier call answered with, and it has no aliases.
if (tcp != by_number || !by_number->p_aliases || by_number->p_aliases[0])
return 4;
struct protoent *udp = getprotobynumber(17);
if (!udp || udp->p_proto != 17 || !same(udp->p_name, "udp"))
return 5;
// A protocol the database does not list has no record.
SetLastError(0xdead);
if (getprotobyname("no-such-protocol") || getprotobynumber(200))
return 6;
WSACleanup();
return 0;
}