resolver: Clean up and simplify gethostbyname/gethostbyaddr/getnameinfo

This commit is contained in:
fincs 2019-10-28 14:04:25 +01:00
parent af4a025e9b
commit f062c6ecab
No known key found for this signature in database
GPG Key ID: 62C7609ADA219C60

View File

@ -77,7 +77,7 @@ Result resolverRemoveIpAddressFromCache(u32 ip) {
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); // not implemented return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); // not implemented
} }
static struct hostent *_resolverDeserializeHostent(int *err, const void *out_he_serialized) { static struct hostent *_resolverDeserializeHostent(const void *out_he_serialized) {
const char *buf = (const char *)out_he_serialized; const char *buf = (const char *)out_he_serialized;
const char *pos, *pos_aliases, *pos_addresses; const char *pos, *pos_aliases, *pos_addresses;
size_t name_size, total_aliases_size = 0; size_t name_size, total_aliases_size = 0;
@ -114,7 +114,8 @@ static struct hostent *_resolverDeserializeHostent(int *err, const void *out_he_
// sfdnsres will only return IPv4 addresses for the "host" commands // sfdnsres will only return IPv4 addresses for the "host" commands
if (addrtype != AF_INET || addrlen != sizeof(struct in_addr)) { if (addrtype != AF_INET || addrlen != sizeof(struct in_addr)) {
*err = NO_ADDRESS; h_errno = NO_ADDRESS;
errno = EINVAL;
return NULL; return NULL;
} }
@ -134,7 +135,8 @@ static struct hostent *_resolverDeserializeHostent(int *err, const void *out_he_
); );
if (!he) { if (!he) {
*err = NO_RECOVERY; h_errno = NETDB_INTERNAL;
errno = ENOMEM;
return NULL; return NULL;
} }
@ -357,111 +359,107 @@ void freeaddrinfo(struct addrinfo *ai) {
} }
struct hostent *gethostbyname(const char *name) { struct hostent *gethostbyname(const char *name) {
Result rc = 0; if (!name) {
void *out_he_serialized = malloc(g_resolverHostByNameBufferSize); h_errno = HOST_NOT_FOUND;
struct hostent *he = NULL; errno = EINVAL;
u32 ret = 0; return NULL;
u32 errno_ = 0;
if(out_he_serialized == NULL) {
h_errno = NO_RECOVERY;
errno = ENOMEM; // POSIX leaves this unspecified
goto cleanup;
} }
rc = sfdnsresGetHostByNameRequest(
if (!g_resolverHostByNameBufferSize) {
h_errno = NETDB_INTERNAL;
errno = ENOSPC;
return NULL;
}
void *out_serialized = malloc(g_resolverHostByNameBufferSize);
if (!out_serialized) {
h_errno = NETDB_INTERNAL;
errno = ENOMEM;
return NULL;
}
Result rc = sfdnsresGetHostByNameRequest(
g_resolverCancelHandle, g_resolverCancelHandle,
!g_resolverDisableServiceDiscovery, !g_resolverDisableServiceDiscovery,
name, name,
&ret, (u32*)&h_errno,
&errno_, (u32*)&errno,
out_he_serialized, g_resolverHostByNameBufferSize, out_serialized, g_resolverHostByNameBufferSize,
NULL); NULL);
g_resolverCancelHandle = 0; g_resolverCancelHandle = 0;
if(rc == 0xD401) {
h_errno = NO_RECOVERY;
errno = EFAULT; // POSIX leaves this unspecified
goto cleanup;
}
else if(R_FAILED(rc) && R_MODULE(rc) == 1) { // Kernel
h_errno = TRY_AGAIN;
errno = EAGAIN; // POSIX leaves this unspecified
goto cleanup;
}
else if(R_FAILED(rc)) {
h_errno = NO_RECOVERY;
errno = EINVAL; // POSIX leaves this unspecified
goto cleanup;
}
if(ret != NETDB_SUCCESS) {
h_errno = ret;
errno = errno_; // POSIX leaves this unspecified
goto cleanup;
}
he = _resolverDeserializeHostent(&h_errno, out_he_serialized);
if(he == NULL) {
h_errno = NO_RECOVERY;
errno = ENOMEM; // POSIX leaves this unspecified
}
cleanup:
g_resolverResult = rc; g_resolverResult = rc;
free(out_he_serialized);
return he; if (R_FAILED(rc)) {
if (R_MODULE(rc) == 21) // SM
errno = EAGAIN;
else if (R_MODULE(rc) == 1) // Kernel
errno = EFAULT;
else
errno = EPIPE;
h_errno = NETDB_INTERNAL;
}
struct hostent *ret = NULL;
if (h_errno == NETDB_SUCCESS)
ret = _resolverDeserializeHostent(out_serialized);
free(out_serialized);
return ret;
} }
struct hostent *gethostbyaddr(const void *addr, socklen_t len, int type) { struct hostent *gethostbyaddr(const void *addr, socklen_t len, int type) {
Result rc = 0; if (!addr || !len) {
void *out_he_serialized = malloc(g_resolverHostByAddrBufferSize); h_errno = HOST_NOT_FOUND;
struct hostent *he = NULL; errno = EINVAL;
u32 ret = 0; return NULL;
u32 errno_ = 0;
if(out_he_serialized == NULL) {
h_errno = NO_RECOVERY;
errno = ENOMEM; // POSIX leaves this unspecified
goto cleanup;
} }
rc = sfdnsresGetHostByAddrRequest(
if (type != AF_INET) {
h_errno = HOST_NOT_FOUND;
errno = EOPNOTSUPP;
return NULL;
}
if (!g_resolverHostByAddrBufferSize) {
h_errno = NETDB_INTERNAL;
errno = ENOSPC;
return NULL;
}
void *out_serialized = malloc(g_resolverHostByAddrBufferSize);
if (!out_serialized) {
h_errno = NETDB_INTERNAL;
errno = ENOMEM;
return NULL;
}
Result rc = sfdnsresGetHostByAddrRequest(
addr, len, addr, len,
type, type,
g_resolverCancelHandle, g_resolverCancelHandle,
&ret, (void*)&h_errno,
&errno_, (void*)&errno,
out_he_serialized, g_resolverHostByAddrBufferSize, out_serialized, g_resolverHostByAddrBufferSize,
NULL); NULL);
g_resolverCancelHandle = 0; g_resolverCancelHandle = 0;
if(rc == 0xD401) {
h_errno = NO_RECOVERY; // POSIX leaves this unspecified
errno = EFAULT;
goto cleanup;
}
else if(R_FAILED(rc) && R_MODULE(rc) == 1) { // Kernel
h_errno = TRY_AGAIN;
errno = EAGAIN; // POSIX leaves this unspecified
goto cleanup;
}
else if(R_FAILED(rc)) {
h_errno = NO_RECOVERY;
errno = EINVAL; // POSIX leaves this unspecified
goto cleanup;
}
if(ret != NETDB_SUCCESS) {
h_errno = ret;
errno = errno_; // POSIX leaves this unspecified
goto cleanup;
}
he = _resolverDeserializeHostent(&h_errno, out_he_serialized);
if(he == NULL) {
h_errno = NO_RECOVERY;
errno = ENOMEM; // POSIX leaves this unspecified
}
cleanup:
g_resolverResult = rc; g_resolverResult = rc;
free(out_he_serialized);
return he; if (R_FAILED(rc)) {
if (R_MODULE(rc) == 21) // SM
errno = EAGAIN;
else if (R_MODULE(rc) == 1) // Kernel
errno = EFAULT;
else
errno = EPIPE;
h_errno = NETDB_INTERNAL;
}
struct hostent *ret = NULL;
if (h_errno == NETDB_SUCCESS)
ret = _resolverDeserializeHostent(out_serialized);
free(out_serialized);
return ret;
} }
const char *hstrerror(int err) { const char *hstrerror(int err) {
@ -517,7 +515,7 @@ int getaddrinfo(const char *node, const char *service, const struct addrinfo *hi
return EAI_FAIL; return EAI_FAIL;
} }
s32 gaie = 0; s32 ret = 0;
Result rc = sfdnsresGetAddrInfoRequest( Result rc = sfdnsresGetAddrInfoRequest(
g_resolverCancelHandle, g_resolverCancelHandle,
!g_resolverDisableServiceDiscovery, !g_resolverDisableServiceDiscovery,
@ -526,7 +524,7 @@ int getaddrinfo(const char *node, const char *service, const struct addrinfo *hi
hints_serialized, hints_sz, hints_serialized, hints_sz,
out_serialized, g_resolverAddrInfoBufferSize, out_serialized, g_resolverAddrInfoBufferSize,
(u32*)&errno, (u32*)&errno,
&gaie, &ret,
NULL); NULL);
g_resolverResult = rc; g_resolverResult = rc;
g_resolverCancelHandle = 0; g_resolverCancelHandle = 0;
@ -539,61 +537,48 @@ int getaddrinfo(const char *node, const char *service, const struct addrinfo *hi
errno = EFAULT; errno = EFAULT;
else else
errno = EPIPE; errno = EPIPE;
gaie = EAI_SYSTEM; ret = EAI_SYSTEM;
} }
if (gaie == 0) { if (ret == 0) {
*res = _resolverDeserializeAddrInfoList(out_serialized); *res = _resolverDeserializeAddrInfoList(out_serialized);
if (!*res) { if (!*res) {
errno = ENOMEM; errno = ENOMEM;
gaie = EAI_MEMORY; ret = EAI_MEMORY;
} }
} }
free(out_serialized); free(out_serialized);
return gaie; return ret;
} }
int getnameinfo(const struct sockaddr *sa, socklen_t salen, int getnameinfo(const struct sockaddr *sa, socklen_t salen,
char *host, socklen_t hostlen, char *host, socklen_t hostlen,
char *serv, socklen_t servlen, char *serv, socklen_t servlen,
int flags) { int flags) {
Result rc = 0; s32 ret = 0;
u32 errno_ = 0; Result rc = sfdnsresGetNameInfoRequest(
s32 gaie = 0;
rc = sfdnsresGetNameInfoRequest(
flags, flags,
sa, salen, sa, salen,
host, hostlen, host, hostlen,
serv, servlen, serv, servlen,
g_resolverCancelHandle, g_resolverCancelHandle,
&errno_, (u32*)&errno,
&gaie); &ret);
g_resolverResult = rc;
g_resolverCancelHandle = 0; g_resolverCancelHandle = 0;
if(rc == 0xD401) { if (R_FAILED(rc)) {
gaie = EAI_SYSTEM; if (R_MODULE(rc) == 21) // SM
errno = EFAULT; errno = EAGAIN;
goto cleanup; else if (R_MODULE(rc) == 1) // Kernel
} errno = EFAULT;
else if(R_FAILED(rc) && R_MODULE(rc) == 1) { // Kernel else
gaie = EAI_AGAIN; errno = EPIPE;
goto cleanup; ret = EAI_SYSTEM;
}
else if(R_FAILED(rc)) {
gaie = EAI_FAIL;
goto cleanup;
} }
if(gaie != 0) { return ret;
if(gaie == EAI_SYSTEM)
errno = errno_;
}
cleanup:
g_resolverResult = rc;
return gaie;
} }
long gethostid(void) { long gethostid(void) {