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;
memcpy(he->h_name, buf, name_size); if(name_size == 1)
he->h_name = NULL;
else {
he->h_name = (char*)he + sizeof(struct hostent);
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,40 +1154,47 @@ 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);
// Nintendo just byteswaps everything recursively... even fields that are already byteswapped. if(hdr->ai_addrlen == 0)
switch(ai->ai_family) { *(u32 *)((u8 *)hdr + sizeof(struct addrinfo_serialized_hdr)) = 0;
case AF_INET: { else {
struct sockaddr_in sa = {0}; // Nintendo just byteswaps everything recursively... even fields that are already byteswapped.
memcpy(&sa, ai->ai_addr, subsize1 <= sizeof(struct sockaddr_in) ? subsize1 : sizeof(struct sockaddr_in)); switch(ai->ai_family) {
sa.sin_port = htons(sa.sin_port); case AF_INET: {
sa.sin_addr.s_addr = htonl(sa.sin_addr.s_addr); struct sockaddr_in sa = {0};
memcpy((u8 *)hdr + sizeof(struct addrinfo_serialized_hdr), &sa, sizeof(struct sockaddr_in)); memcpy(&sa, ai->ai_addr, subsize1 <= sizeof(struct sockaddr_in) ? subsize1 : sizeof(struct sockaddr_in));
break; sa.sin_port = htons(sa.sin_port);
sa.sin_addr.s_addr = htonl(sa.sin_addr.s_addr);
memcpy((u8 *)hdr + sizeof(struct addrinfo_serialized_hdr), &sa, sizeof(struct sockaddr_in));
break;
}
case AF_INET6: {
struct sockaddr_in6 sa6 = {0};
memcpy(&sa6, ai->ai_addr, subsize1 <= sizeof(struct sockaddr_in6) ? subsize1 : sizeof(struct sockaddr_in6));
sa6.sin6_port = htons(sa6.sin6_port);
sa6.sin6_flowinfo = htonl(sa6.sin6_flowinfo);
sa6.sin6_scope_id = htonl(sa6.sin6_scope_id);
memcpy((u8 *)hdr + sizeof(struct addrinfo_serialized_hdr), &sa6, sizeof(struct sockaddr_in6));
break;
}
default:
memcpy((u8 *)hdr + sizeof(struct addrinfo_serialized_hdr), ai->ai_addr, subsize1);
} }
case AF_INET6: {
struct sockaddr_in6 sa6 = {0};
memcpy(&sa6, ai->ai_addr, subsize1 <= sizeof(struct sockaddr_in6) ? subsize1 : sizeof(struct sockaddr_in6));
sa6.sin6_port = htons(sa6.sin6_port);
sa6.sin6_flowinfo = htonl(sa6.sin6_flowinfo);
sa6.sin6_scope_id = htonl(sa6.sin6_scope_id);
memcpy((u8 *)hdr + sizeof(struct addrinfo_serialized_hdr), &sa6, sizeof(struct sockaddr_in6));
break;
}
default:
memcpy((u8 *)hdr + sizeof(struct addrinfo_serialized_hdr), ai->ai_addr, subsize1);
} }
memcpy((u8 *)hdr + sizeof(struct addrinfo_serialized_hdr) + subsize1, ai->ai_canonname, subsize2); 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);
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,32 +1245,42 @@ 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);
// Nintendo just byteswaps everything recursively... even fields that are already byteswapped. if(node->info.ai_addrlen == 0)
switch(node->info.ai_family) { node->info.ai_addr = NULL;
case AF_INET: { else {
struct sockaddr_in *sa = (struct sockaddr_in *)&node->info.ai_addr; node->info.ai_addr = (struct sockaddr *)&node->addr;
sa->sin_port = ntohs(sa->sin_port); memcpy(node->info.ai_addr, (const u8 *)hdr + sizeof(struct addrinfo_serialized_hdr), node->info.ai_addrlen);
sa->sin_addr.s_addr = ntohl(sa->sin_addr.s_addr); // Nintendo just byteswaps everything recursively... even fields that are already byteswapped.
break; switch(node->info.ai_family) {
case AF_INET: {
struct sockaddr_in *sa = (struct sockaddr_in *)&node->info.ai_addr;
sa->sin_port = ntohs(sa->sin_port);
sa->sin_addr.s_addr = ntohl(sa->sin_addr.s_addr);
break;
}
case AF_INET6: {
struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)&node->info.ai_addr;
sa6->sin6_port = ntohs(sa6->sin6_port);
sa6->sin6_flowinfo = ntohl(sa6->sin6_flowinfo);
sa6->sin6_scope_id = ntohl(sa6->sin6_scope_id);
break;
}
default:
break;
} }
case AF_INET6: {
struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)&node->info.ai_addr;
sa6->sin6_port = ntohs(sa6->sin6_port);
sa6->sin6_flowinfo = ntohl(sa6->sin6_flowinfo);
sa6->sin6_scope_id = ntohl(sa6->sin6_scope_id);
break;
}
default:
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);
@ -1418,7 +1440,7 @@ int getaddrinfo(const char *node, const char *service, const struct addrinfo *hi
struct addrinfo_serialized_hdr *hints_serialized = _socketSerializeAddrInfoList(&hints_sz, hints); struct addrinfo_serialized_hdr *hints_serialized = _socketSerializeAddrInfoList(&hints_sz, hints);
struct addrinfo_serialized_hdr *out_serialized = NULL; struct addrinfo_serialized_hdr *out_serialized = NULL;
struct addrinfo *out = NULL; struct addrinfo *out = NULL;
SfdnsresRequestResults ret; SfdnsresRequestResults ret;
if(hints_serialized == NULL) { if(hints_serialized == NULL) {
gaie = EAI_MEMORY; gaie = EAI_MEMORY;
@ -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);