From ad4af954c25dd25e5ed1bd2ac7df20bd72642105 Mon Sep 17 00:00:00 2001 From: Somebody Whoisbored Date: Thu, 7 Jun 2018 15:00:51 -0700 Subject: [PATCH] Added nifm service (#110) * Added nifm service * Properly implemented gethostid * Implemented gethostname --- nx/include/switch.h | 1 + nx/include/switch/services/nifm.h | 18 ++++ nx/source/runtime/devices/socket.c | 34 ++++--- nx/source/services/nifm.c | 149 +++++++++++++++++++++++++++++ 4 files changed, 187 insertions(+), 15 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/services/nifm.h b/nx/include/switch/services/nifm.h new file mode 100644 index 00000000..ca5dce2b --- /dev/null +++ b/nx/include/switch/services/nifm.h @@ -0,0 +1,18 @@ +/** + * @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" + +Result nifmInitialize(void); +void nifmExit(void); + +Result nifmGetCurrentIpAddress(u32* out); diff --git a/nx/source/runtime/devices/socket.c b/nx/source/runtime/devices/socket.c index 27f1712e..fd9492ee 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,23 @@ cleanup: return gaie; } +long gethostid(void) { + Result rc; + u32 id; + rc = nifmGetCurrentIpAddress(&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; } @@ -1593,18 +1611,4 @@ struct servent *getservbyport(int a, const char *s) { (void)a; (void)s; h_errno struct servent *getservent(void) { h_errno = NO_RECOVERY; errno = ENOSYS; return NULL; } void sethostent(int a) { (void)a;} 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; -} +void setprotoent(int a) { (void)a; } \ No newline at end of file diff --git a/nx/source/services/nifm.c b/nx/source/services/nifm.c new file mode 100644 index 00000000..d1e3bfcb --- /dev/null +++ b/nx/source/services/nifm.c @@ -0,0 +1,149 @@ +/** + * @file nifm.h + * @brief Network interface service IPC wrapper. + * @author shadowninja108 + * @copyright libnx Authors + */ + +#include "services/nifm.h" +#include "arm/atomics.h" + +static Service g_nifmSrv; +static Service g_nifmIGS; +static u64 g_refCnt; + +static Result _nifmCreateGeneralService(Service* out, u64 in); +static Result _nifmCreateGeneralServiceOld(Service* out); + +Result nifmInitialize(void) { + atomicIncrement64(&g_refCnt); + + if (serviceIsActive(&g_nifmSrv)) + return 0; + + Result rc; + rc = smGetService(&g_nifmSrv, "nifm:u"); + + if (R_SUCCEEDED(rc)) { + if (kernelAbove200()) + rc = _nifmCreateGeneralService(&g_nifmIGS, 0); // What does this parameter do? + else + rc = _nifmCreateGeneralServiceOld(&g_nifmIGS); + } + + if (R_FAILED(rc)) + nifmExit(); + + return rc; +} + +void nifmExit(void) { + if (atomicDecrement64(&g_refCnt) == 0) { + serviceClose(&g_nifmIGS); + serviceClose(&g_nifmSrv); + } +} + +Result nifmGetCurrentIpAddress(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(&g_nifmIGS); + + 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; +} + +static Result _nifmCreateGeneralService(Service* 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, r.Handles[0]); + } + + return rc; +} + +static Result _nifmCreateGeneralServiceOld(Service* 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, r.Handles[0]); + } + + return rc; +}