From f062c6ecabf90c02acde5f00b335f951e3009aa5 Mon Sep 17 00:00:00 2001
From: fincs <fincs@devkitpro.org>
Date: Mon, 28 Oct 2019 14:04:25 +0100
Subject: [PATCH] resolver: Clean up and simplify
 gethostbyname/gethostbyaddr/getnameinfo

---
 nx/source/runtime/resolver.c | 233 ++++++++++++++++-------------------
 1 file changed, 109 insertions(+), 124 deletions(-)

diff --git a/nx/source/runtime/resolver.c b/nx/source/runtime/resolver.c
index 5c825b4b..753731eb 100644
--- a/nx/source/runtime/resolver.c
+++ b/nx/source/runtime/resolver.c
@@ -77,7 +77,7 @@ Result resolverRemoveIpAddressFromCache(u32 ip) {
     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 *pos, *pos_aliases, *pos_addresses;
     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
     if (addrtype != AF_INET || addrlen != sizeof(struct in_addr)) {
-        *err = NO_ADDRESS;
+        h_errno = NO_ADDRESS;
+        errno = EINVAL;
         return NULL;
     }
 
@@ -134,7 +135,8 @@ static struct hostent *_resolverDeserializeHostent(int *err, const void *out_he_
     );
 
     if (!he) {
-        *err = NO_RECOVERY;
+        h_errno = NETDB_INTERNAL;
+        errno = ENOMEM;
         return NULL;
     }
 
@@ -357,111 +359,107 @@ void freeaddrinfo(struct addrinfo *ai) {
 }
 
 struct hostent *gethostbyname(const char *name) {
-    Result rc = 0;
-    void *out_he_serialized = malloc(g_resolverHostByNameBufferSize);
-    struct hostent *he = NULL;
-    u32 ret = 0;
-    u32 errno_ = 0;
-
-    if(out_he_serialized == NULL) {
-        h_errno = NO_RECOVERY;
-        errno = ENOMEM; // POSIX leaves this unspecified
-        goto cleanup;
+    if (!name) {
+        h_errno = HOST_NOT_FOUND;
+        errno = EINVAL;
+        return NULL;
     }
-    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_resolverDisableServiceDiscovery,
         name,
-        &ret,
-        &errno_,
-        out_he_serialized, g_resolverHostByNameBufferSize,
+        (u32*)&h_errno,
+        (u32*)&errno,
+        out_serialized, g_resolverHostByNameBufferSize,
         NULL);
     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;
-    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) {
-    Result rc = 0;
-    void *out_he_serialized = malloc(g_resolverHostByAddrBufferSize);
-    struct hostent *he = NULL;
-    u32 ret = 0;
-    u32 errno_ = 0;
-
-    if(out_he_serialized == NULL) {
-        h_errno = NO_RECOVERY;
-        errno = ENOMEM; // POSIX leaves this unspecified
-        goto cleanup;
+    if (!addr || !len) {
+        h_errno = HOST_NOT_FOUND;
+        errno = EINVAL;
+        return NULL;
     }
-    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,
         type,
         g_resolverCancelHandle,
-        &ret,
-        &errno_,
-        out_he_serialized, g_resolverHostByAddrBufferSize,
+        (void*)&h_errno,
+        (void*)&errno,
+        out_serialized, g_resolverHostByAddrBufferSize,
         NULL);
     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;
-    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) {
@@ -517,7 +515,7 @@ int getaddrinfo(const char *node, const char *service, const struct addrinfo *hi
         return EAI_FAIL;
     }
 
-    s32 gaie = 0;
+    s32 ret = 0;
     Result rc = sfdnsresGetAddrInfoRequest(
         g_resolverCancelHandle,
         !g_resolverDisableServiceDiscovery,
@@ -526,7 +524,7 @@ int getaddrinfo(const char *node, const char *service, const struct addrinfo *hi
         hints_serialized, hints_sz,
         out_serialized, g_resolverAddrInfoBufferSize,
         (u32*)&errno,
-        &gaie,
+        &ret,
         NULL);
     g_resolverResult = rc;
     g_resolverCancelHandle = 0;
@@ -539,61 +537,48 @@ int getaddrinfo(const char *node, const char *service, const struct addrinfo *hi
             errno = EFAULT;
         else
             errno = EPIPE;
-        gaie = EAI_SYSTEM;
+        ret = EAI_SYSTEM;
     }
 
-    if (gaie == 0) {
+    if (ret == 0) {
         *res = _resolverDeserializeAddrInfoList(out_serialized);
         if (!*res) {
             errno = ENOMEM;
-            gaie = EAI_MEMORY;
+            ret = EAI_MEMORY;
         }
     }
 
     free(out_serialized);
-    return gaie;
+    return ret;
 }
 
 int getnameinfo(const struct sockaddr *sa, socklen_t salen,
                 char *host, socklen_t hostlen,
                 char *serv, socklen_t servlen,
                 int flags) {
-    Result rc = 0;
-    u32 errno_ = 0;
-    s32 gaie = 0;
-
-    rc = sfdnsresGetNameInfoRequest(
+    s32 ret = 0;
+    Result rc = sfdnsresGetNameInfoRequest(
         flags,
         sa, salen,
         host, hostlen,
         serv, servlen,
         g_resolverCancelHandle,
-        &errno_,
-        &gaie);
+        (u32*)&errno,
+        &ret);
+    g_resolverResult = rc;
     g_resolverCancelHandle = 0;
 
-    if(rc == 0xD401) {
-        gaie = EAI_SYSTEM;
-        errno = EFAULT;
-        goto cleanup;
-    }
-    else if(R_FAILED(rc) && R_MODULE(rc) == 1) { // Kernel
-        gaie = EAI_AGAIN;
-        goto cleanup;
-    }
-    else if(R_FAILED(rc)) {
-        gaie = EAI_FAIL;
-        goto cleanup;
+    if (R_FAILED(rc)) {
+        if (R_MODULE(rc) == 21) // SM
+            errno = EAGAIN;
+        else if (R_MODULE(rc) == 1) // Kernel
+            errno = EFAULT;
+        else
+            errno = EPIPE;
+        ret = EAI_SYSTEM;
     }
 
-    if(gaie != 0) {
-        if(gaie == EAI_SYSTEM)
-            errno = errno_;
-    }
-
-cleanup:
-    g_resolverResult = rc;
-    return gaie;
+    return ret;
 }
 
 long gethostid(void) {