From 23da34056cc39b07ba427d16124036bceb61abd6 Mon Sep 17 00:00:00 2001 From: shadowninja108 Date: Sun, 3 Jun 2018 02:38:20 -0700 Subject: [PATCH] Added nifm service Added nifm service Implemented gethostname --- nx/include/switch.h | 1 + nx/include/switch/runtime/devices/socket.h | 5 + nx/include/switch/services/nifm.h | 26 ++++ nx/source/runtime/devices/socket.c | 36 ++++-- nx/source/services/nifm.c | 135 +++++++++++++++++++++ 5 files changed, 191 insertions(+), 12 deletions(-) create mode 100644 nx/include/switch/services/nifm.h create mode 100644 nx/source/services/nifm.c diff --git a/nx/include/switch.h b/nx/include/switch.h index 603ec9de..2ed024d1 100644 --- a/nx/include/switch.h +++ b/nx/include/switch.h @@ -51,6 +51,7 @@ extern "C" { #include "switch/services/pl.h" #include "switch/services/vi.h" #include "switch/services/nv.h" +#include "switch/services/nifm.h" #include "switch/services/ns.h" #include "switch/services/ldr.h" #include "switch/services/pm.h" diff --git a/nx/include/switch/runtime/devices/socket.h b/nx/include/switch/runtime/devices/socket.h index 155eea6f..4aaf84d9 100644 --- a/nx/include/switch/runtime/devices/socket.h +++ b/nx/include/switch/runtime/devices/socket.h @@ -21,6 +21,11 @@ typedef struct { int dns_timeout; ///< For DNS requests: timeout or 0. } SocketInitConfig; +long gethostid(void); + +// Get host IP formatted +int gethostname(char *name, size_t namelen); + /// Fetch the default configuration for the socket driver. const SocketInitConfig *socketGetDefaultInitConfig(void); /// Initalize the socket driver. diff --git a/nx/include/switch/services/nifm.h b/nx/include/switch/services/nifm.h new file mode 100644 index 00000000..5920ef7c --- /dev/null +++ b/nx/include/switch/services/nifm.h @@ -0,0 +1,26 @@ +/** + * @file nifm.h + * @brief Network interface service IPC wrapper. + * @author shadowninja108 + * @copyright libnx Authors + */ + +#pragma once + +#include "../kernel/ipc.h" +#include "../kernel/detect.h" + +#include "../services/sm.h" + +typedef struct { + Service s; +} IGeneralService; + +Result nifmInitialize(); +void nifmExit(void); + +Result CreateGeneralService(IGeneralService*out); +Result _CreateGeneralService(IGeneralService* out, u64 in); +Result _CreateGeneralServiceOld(IGeneralService* out); + +Result GetCurrentIpAddress(IGeneralService* srv, u32* out); \ No newline at end of file diff --git a/nx/source/runtime/devices/socket.c b/nx/source/runtime/devices/socket.c index 27f1712e..d88a445f 100644 --- a/nx/source/runtime/devices/socket.c +++ b/nx/source/runtime/devices/socket.c @@ -21,6 +21,7 @@ #include "runtime/devices/socket.h" #include "services/bsd.h" #include "services/sfdnsres.h" +#include "services/nifm.h" #include "result.h" __thread int h_errno; @@ -1580,6 +1581,29 @@ cleanup: return gaie; } + +long gethostid(void) { + Result rc; + IGeneralService igs; + rc = CreateGeneralService(&igs); + if(R_SUCCEEDED(rc)){ + u32 id; + rc = GetCurrentIpAddress(&igs, &id); + if(R_SUCCEEDED(rc)){ + return id; + } + } + return INADDR_LOOPBACK; +} + +int gethostname(char *name, size_t namelen) { + // The Switch doesn't have a proper name, so let's use its IP + struct in_addr in; + in.s_addr = gethostid(); + const char *hostname = inet_ntop(AF_INET, &in, name, namelen); + return hostname == NULL ? -1 : 0; +} + // Unimplementable functions, left for compliance: struct hostent *gethostent(void) { h_errno = NO_RECOVERY; errno = ENOSYS; return NULL; } struct netent *getnetbyaddr(uint32_t a, int b) { (void)a; (void)b; h_errno = NO_RECOVERY; errno = ENOSYS; return NULL; } @@ -1596,15 +1620,3 @@ void setnetent(int a) { (void)a;} void setprotoent(int a) { (void)a; } /************************************************************************************************************************/ - -long gethostid(void) { - return INADDR_LOOPBACK; //FIXME -} - -int gethostname(char *name, size_t namelen) { - // The Switch doesn't have a proper name, so let's use its IP - struct in_addr in; - in.s_addr = gethostid(); - const char *hostname = inet_ntop(AF_INET, &in, name, namelen); - return hostname == NULL ? -1 : 0; -} diff --git a/nx/source/services/nifm.c b/nx/source/services/nifm.c new file mode 100644 index 00000000..29e625b3 --- /dev/null +++ b/nx/source/services/nifm.c @@ -0,0 +1,135 @@ +/** + * @file nifm.h + * @brief Network interface service IPC wrapper. + * @author shadowninja108 + * @copyright libnx Authors + */ +#include "services/nifm.h" + +static Service g_nifmSrv; + +Result nifmInitialize(){ + if (serviceIsActive(&g_nifmSrv)) + return 0; + return smGetService(&g_nifmSrv, "nifm:u"); +} + +void nifmExit(void){ + serviceClose(&g_nifmSrv); +} + +Result CreateGeneralService(IGeneralService *out){ + if(kernelAbove200()) + return _CreateGeneralService(out, 0); // What does this parameter do? + else + return _CreateGeneralServiceOld(out); +} + +Result _CreateGeneralService(IGeneralService* out, u64 in){ + IpcCommand c; + ipcInitialize(&c); + ipcSendPid(&c); + + struct { + u64 magic; + u64 cmd_id; + u64 param; + } PACKED *raw; + + raw = ipcPrepareHeader(&c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 5; + raw->param = in; + + Result rc = serviceIpcDispatch(&g_nifmSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + ipcParse(&r); + + struct { + u64 magic; + u64 result; + } *resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc)) { + serviceCreate(&out->s, r.Handles[0]); + } + } + + return rc; +} + +Result _CreateGeneralServiceOld(IGeneralService* out){ + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + } PACKED *raw; + + raw = ipcPrepareHeader(&c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 4; + + Result rc = serviceIpcDispatch(&g_nifmSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + ipcParse(&r); + + struct { + u64 magic; + u64 result; + } *resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc)) { + serviceCreate(&out->s, r.Handles[0]); + } + } + + return rc; +} + +Result GetCurrentIpAddress(IGeneralService* srv, u32* out){ + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + } *raw; + + raw = ipcPrepareHeader(&c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 12; + + Result rc = serviceIpcDispatch(&srv->s); + + if (R_SUCCEEDED(rc)) + { + IpcParsedCommand r; + ipcParse(&r); + + struct + { + u64 magic; + u64 result; + u32 out; + } *resp = r.Raw; + + rc = resp->result; + *out = resp->out; + } + + return rc; + +} \ No newline at end of file