Fix netdb functions

This commit is contained in:
TuxSH 2018-02-10 22:29:32 +01:00 committed by plutoo
parent 888f7e101f
commit 3709ee92a5
2 changed files with 85 additions and 54 deletions

View File

@ -1113,13 +1113,17 @@ static struct hostent *_socketDeserializeHostent(int *err, const void *out_he_se
return NULL; return NULL;
} }
he->h_name = (char*)he + sizeof(struct hostent);
he->h_aliases = (char **)(he->h_name + name_size); he->h_aliases = (char **)(he->h_name + name_size);
he->h_addrtype = addrtype; he->h_addrtype = addrtype;
he->h_length = addrlen; he->h_length = addrlen;
he->h_addr_list = he->h_aliases + nb_aliases + 1; he->h_addr_list = he->h_aliases + nb_aliases + 1;
if(name_size == 1)
he->h_name = NULL;
else {
he->h_name = (char*)he + sizeof(struct hostent);
memcpy(he->h_name, buf, name_size); memcpy(he->h_name, buf, name_size);
}
char *alias = (char *)(he->h_addr_list + nb_addresses + 1); char *alias = (char *)(he->h_addr_list + nb_addresses + 1);
memcpy(alias, pos_aliases, total_aliases_size); memcpy(alias, pos_aliases, total_aliases_size);
@ -1150,16 +1154,19 @@ struct addrinfo_serialized_hdr {
}; };
static size_t _socketSerializeAddrInfo(struct addrinfo_serialized_hdr *hdr, const struct addrinfo *ai) { static size_t _socketSerializeAddrInfo(struct addrinfo_serialized_hdr *hdr, const struct addrinfo *ai) {
size_t subsize1 = ai->ai_addrlen == 0 ? 4 : ai->ai_addrlen; // not posix-compliant ? size_t subsize1 = (ai->ai_addr == NULL || ai->ai_addrlen == 0) ? 4 : ai->ai_addrlen; // not posix-compliant ?
size_t subsize2 = strlen(ai->ai_canonname) + 1; size_t subsize2 = ai->ai_canonname == NULL ? 1 : (strlen(ai->ai_canonname) + 1);
hdr->magic = htonl(0xBEEFCAFE); // Seriously. hdr->magic = htonl(0xBEEFCAFE); // Seriously.
hdr->ai_flags = htonl(ai->ai_flags); hdr->ai_flags = htonl(ai->ai_flags);
hdr->ai_family = htonl(ai->ai_family); hdr->ai_family = htonl(ai->ai_family);
hdr->ai_socktype = htonl(ai->ai_socktype); hdr->ai_socktype = htonl(ai->ai_socktype);
hdr->ai_protocol = htonl(ai->ai_protocol); hdr->ai_protocol = htonl(ai->ai_protocol);
hdr->ai_addrlen = htonl((u32)ai->ai_addrlen); hdr->ai_addrlen = ai->ai_addr == NULL ? 0 : htonl((u32)ai->ai_addrlen);
if(hdr->ai_addrlen == 0)
*(u32 *)((u8 *)hdr + sizeof(struct addrinfo_serialized_hdr)) = 0;
else {
// Nintendo just byteswaps everything recursively... even fields that are already byteswapped. // Nintendo just byteswaps everything recursively... even fields that are already byteswapped.
switch(ai->ai_family) { switch(ai->ai_family) {
case AF_INET: { case AF_INET: {
@ -1182,7 +1189,11 @@ static size_t _socketSerializeAddrInfo(struct addrinfo_serialized_hdr *hdr, cons
default: default:
memcpy((u8 *)hdr + sizeof(struct addrinfo_serialized_hdr), ai->ai_addr, subsize1); memcpy((u8 *)hdr + sizeof(struct addrinfo_serialized_hdr), ai->ai_addr, subsize1);
} }
}
if(ai->ai_canonname == NULL)
*((u8 *)hdr + sizeof(struct addrinfo_serialized_hdr) + subsize1) = 0;
else
memcpy((u8 *)hdr + sizeof(struct addrinfo_serialized_hdr) + subsize1, ai->ai_canonname, subsize2); memcpy((u8 *)hdr + sizeof(struct addrinfo_serialized_hdr) + subsize1, ai->ai_canonname, subsize2);
return sizeof(struct addrinfo_serialized_hdr) + subsize1 + subsize2; return sizeof(struct addrinfo_serialized_hdr) + subsize1 + subsize2;
@ -1194,7 +1205,7 @@ static struct addrinfo_serialized_hdr *_socketSerializeAddrInfoList(size_t *out_
for(const struct addrinfo *node = ai; node != NULL; node = node->ai_next) { for(const struct addrinfo *node = ai; node != NULL; node = node->ai_next) {
total_addrlen += node->ai_addrlen == 0 ? 4 : node->ai_addrlen; total_addrlen += node->ai_addrlen == 0 ? 4 : node->ai_addrlen;
total_namelen += strlen(node->ai_canonname) + 1; total_namelen += node->ai_canonname == NULL ? 1 : (strlen(node->ai_canonname) + 1);
n++; n++;
} }
@ -1234,14 +1245,15 @@ static struct addrinfo *_socketDeserializeAddrInfo(size_t *out_len, const struct
node->info.ai_protocol = ntohl(hdr->ai_protocol); node->info.ai_protocol = ntohl(hdr->ai_protocol);
node->info.ai_addrlen = ntohl(hdr->ai_addrlen); node->info.ai_addrlen = ntohl(hdr->ai_addrlen);
node->info.ai_addr = (struct sockaddr *)&node->addr;
node->info.ai_canonname = node->canonname;
// getaddrinfo enforces addrlen = sizeof(struct sockaddr) and family = AF_INET, ie. only IPv4, anyways... // getaddrinfo enforces addrlen = sizeof(struct sockaddr) and family = AF_INET, ie. only IPv4, anyways...
if(node->info.ai_addrlen > sizeof(struct sockaddr_storage)) if(node->info.ai_addrlen > sizeof(struct sockaddr_storage))
node->info.ai_addrlen = sizeof(struct sockaddr_storage); node->info.ai_addrlen = sizeof(struct sockaddr_storage);
memcpy(node->info.ai_addr, (const u8 *)hdr + sizeof(struct addrinfo_serialized_hdr), node->info.ai_addrlen);
memcpy(node->info.ai_canonname, (const u8 *)hdr + sizeof(struct addrinfo_serialized_hdr) + subsize1, subsize2);
if(node->info.ai_addrlen == 0)
node->info.ai_addr = NULL;
else {
node->info.ai_addr = (struct sockaddr *)&node->addr;
memcpy(node->info.ai_addr, (const u8 *)hdr + sizeof(struct addrinfo_serialized_hdr), node->info.ai_addrlen);
// Nintendo just byteswaps everything recursively... even fields that are already byteswapped. // Nintendo just byteswaps everything recursively... even fields that are already byteswapped.
switch(node->info.ai_family) { switch(node->info.ai_family) {
case AF_INET: { case AF_INET: {
@ -1260,6 +1272,15 @@ static struct addrinfo *_socketDeserializeAddrInfo(size_t *out_len, const struct
default: default:
break; break;
} }
}
if(subsize2 == 1)
node->info.ai_canonname = NULL;
else {
node->info.ai_canonname = node->canonname;
memcpy(node->info.ai_canonname, (const u8 *)hdr + sizeof(struct addrinfo_serialized_hdr) + subsize1, subsize2);
}
node->info.ai_next = NULL; node->info.ai_next = NULL;
return &node->info; return &node->info;
@ -1295,6 +1316,7 @@ void freehostent(struct hostent *he) {
} }
void freeaddrinfo(struct addrinfo *ai) { void freeaddrinfo(struct addrinfo *ai) {
if(ai == NULL) return; // not specified by POSIX, but that's convenient (FreeBSD does this too, etc.).
for(struct addrinfo *node = ai, *next; node != NULL; node = next) { for(struct addrinfo *node = ai, *next; node != NULL; node = next) {
next = node->ai_next; next = node->ai_next;
free(node); free(node);
@ -1433,6 +1455,7 @@ int getaddrinfo(const char *node, const char *service, const struct addrinfo *hi
} }
rc = sfdnsresGetAddrInfo(&ret, &g_sfdnsresConfig, node, service, hints_serialized, hints_sz, out_serialized); rc = sfdnsresGetAddrInfo(&ret, &g_sfdnsresConfig, node, service, hints_serialized, hints_sz, out_serialized);
if(rc == 0xD401) { if(rc == 0xD401) {
gaie = EAI_SYSTEM; gaie = EAI_SYSTEM;
errno = EFAULT; errno = EFAULT;
@ -1457,8 +1480,8 @@ int getaddrinfo(const char *node, const char *service, const struct addrinfo *hi
out = _socketDeserializeAddrInfoList(out_serialized); out = _socketDeserializeAddrInfoList(out_serialized);
if(out == NULL) if(out == NULL)
gaie = EAI_MEMORY; gaie = EAI_MEMORY;
*res = out;
cleanup: cleanup:
*res = out;
free(hints_serialized); free(hints_serialized);
free(out_serialized); free(out_serialized);
g_sfdnsresResult = rc; g_sfdnsresResult = rc;

View File

@ -101,7 +101,7 @@ static Result _sfdnsresErrorStringGetterCommand(u64 cmd_id, int err, char *str,
Result sfdnsresGetHostByName(SfdnsresRequestResults *ret, const SfdnsresConfig *config, void *out_he_serialized, const char *name) { Result sfdnsresGetHostByName(SfdnsresRequestResults *ret, const SfdnsresConfig *config, void *out_he_serialized, const char *name) {
IpcCommand c; IpcCommand c;
ipcInitialize(&c); ipcInitialize(&c);
ipcAddSendBuffer(&c, name, strlen(name) + 1, 0); ipcAddSendBuffer(&c, name, name == NULL ? 0 : strlen(name) + 1, 0);
ipcAddRecvBuffer(&c, out_he_serialized, config->serialized_out_hostent_max_size, 0); ipcAddRecvBuffer(&c, out_he_serialized, config->serialized_out_hostent_max_size, 0);
@ -120,7 +120,7 @@ Result sfdnsresGetHostByAddr(SfdnsresRequestResults *ret, const SfdnsresConfig *
} raw; } raw;
ipcInitialize(&c); ipcInitialize(&c);
ipcAddSendBuffer(&c, addr, len, 0); ipcAddSendBuffer(&c, addr, addr == NULL ? 0 : len, 0);
ipcAddRecvBuffer(&c, out_he_serialized, config->serialized_out_hostent_max_size, 0); ipcAddRecvBuffer(&c, out_he_serialized, config->serialized_out_hostent_max_size, 0);
raw.magic = SFCI_MAGIC; raw.magic = SFCI_MAGIC;
@ -144,10 +144,13 @@ Result sfdnsresGetGaiStringError(int err, char *str, size_t str_size) {
Result sfdnsresGetAddrInfo(SfdnsresRequestResults *ret, const SfdnsresConfig *config, const char *node, const char *service, Result sfdnsresGetAddrInfo(SfdnsresRequestResults *ret, const SfdnsresConfig *config, const char *node, const char *service,
const void *hints_serialized, size_t hints_serialized_size, void *res_serialized) { const void *hints_serialized, size_t hints_serialized_size, void *res_serialized) {
IpcCommand c; IpcCommand c;
ipcInitialize(&c); size_t node_size = node == NULL ? 0 : strlen(node) + 1;
size_t service_size = service == NULL ? 0 : strlen(service) + 1;
hints_serialized_size = hints_serialized == NULL ? 0 : hints_serialized_size;
ipcAddSendBuffer(&c, node, strlen(node) + 1, 0); ipcInitialize(&c);
ipcAddSendBuffer(&c, node, strlen(service) + 1, 0); ipcAddSendBuffer(&c, node, node_size, 0);
ipcAddSendBuffer(&c, service, service_size, 0);
ipcAddSendBuffer(&c, hints_serialized, hints_serialized_size, 0); ipcAddSendBuffer(&c, hints_serialized, hints_serialized_size, 0);
ipcAddRecvBuffer(&c, res_serialized, config->serialized_out_hostent_max_size, 0); ipcAddRecvBuffer(&c, res_serialized, config->serialized_out_hostent_max_size, 0);
@ -159,6 +162,11 @@ Result sfdnsresGetNameInfo(SfdnsresRequestResults *ret, const SfdnsresConfig *co
const struct sockaddr *sa, socklen_t salen, char *host, size_t hostlen, const struct sockaddr *sa, socklen_t salen, char *host, size_t hostlen,
char *serv, size_t servlen, int flags) { char *serv, size_t servlen, int flags) {
IpcCommand c; IpcCommand c;
salen = sa == NULL ? 0 : salen;
hostlen = host == NULL ? 0 : hostlen;
servlen = serv == NULL ? 0 : servlen;
ipcInitialize(&c); ipcInitialize(&c);
ipcAddSendBuffer(&c, sa, salen, 0); ipcAddSendBuffer(&c, sa, salen, 0);