diff --git a/libctru/include/netdb.h b/libctru/include/netdb.h index 4e42861..5840deb 100644 --- a/libctru/include/netdb.h +++ b/libctru/include/netdb.h @@ -17,6 +17,21 @@ struct hostent { char *h_addr; }; +#define NI_MAXHOST 1025 +#define NI_MAXSERV 32 + +#define NI_NOFQDN 0x01 +#define NI_NUMERICHOST 0x02 +#define NI_NAMEREQD 0x04 +#define NI_NUMERICSERV 0x00 /* probably 0x08 but services names are never resolved */ +#define NI_DGRAM 0x00 /* probably 0x10 but services names are never resolved */ + +#define EAI_FAMILY (-303) +#define EAI_MEMORY (-304) +#define EAI_NONAME (-305) +#define EAI_SOCKTYPE (-307) + + #ifdef __cplusplus extern "C" { #endif @@ -27,6 +42,10 @@ extern "C" { void herror(const char *s); const char* hstrerror(int err); + int getnameinfo(const struct sockaddr *sa, socklen_t salen, + char *host, socklen_t hostlen, + char *serv, socklen_t servlen, int flags); + #ifdef __cplusplus } #endif diff --git a/libctru/source/services/soc/soc_getnameinfo.c b/libctru/source/services/soc/soc_getnameinfo.c new file mode 100644 index 0000000..05c9ab6 --- /dev/null +++ b/libctru/source/services/soc/soc_getnameinfo.c @@ -0,0 +1,68 @@ +#include "soc_common.h" +#include +#include <3ds/ipc.h> +#include <3ds/result.h> + +int getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, socklen_t hostlen, char *serv, socklen_t servlen, int flags) +{ + int i,tmp_addrlen; + u32 *cmdbuf = getThreadCommandBuffer(); + u32 saved_threadstorage[4]; + u8 tmpaddr[0x1c]; // sockaddr size for the kernel is 0x1C (sockaddr_in6?) + + if((host == NULL || hostlen == 0) && (serv == NULL || servlen == 0)) + { + return EAI_NONAME; + } + + if(sa->sa_family == AF_INET) + tmp_addrlen = 8; + else + tmp_addrlen = 0x1c; + + if(salen < tmp_addrlen) { + errno = EINVAL; + return -1; + } + + tmpaddr[0] = tmp_addrlen; + tmpaddr[1] = sa->sa_family; + memcpy(&tmpaddr[2], &sa->sa_data, tmp_addrlen-2); + + cmdbuf[0] = IPC_MakeHeader(0x10,4,2); // 0x100102 + cmdbuf[1] = sizeof(tmpaddr); + cmdbuf[2] = hostlen; + cmdbuf[3] = servlen; + cmdbuf[4] = flags; + cmdbuf[5] = IPC_Desc_StaticBuffer(sizeof(tmpaddr),8); + cmdbuf[6] = (u32)tmpaddr; + + u32 * staticbufs = getThreadStaticBuffers(); + + // Save the thread storage values + for(i = 0 ; i < 4 ; ++i) + saved_threadstorage[i] = staticbufs[i]; + + staticbufs[0] = IPC_Desc_StaticBuffer(hostlen,0); + staticbufs[1] = (u32)host; + staticbufs[2] = IPC_Desc_StaticBuffer(servlen,0); + staticbufs[3] = (u32)serv; + + Result ret = svcSendSyncRequest(SOCU_handle); + + // Restore the thread storage values + for(i = 0 ; i < 4 ; ++i) + staticbufs[i] = saved_threadstorage[i]; + + if(R_FAILED(ret)) { + errno = SYNC_ERROR; + return ret; + } + + ret = cmdbuf[1]; + if(R_FAILED(ret)) { + errno = SYNC_ERROR; + return ret; + } + return cmdbuf[2]; +}