mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-21 20:42:44 +02:00
sfdnsres: Major rewrite using new-ipc, fixed numerous IPC bugs, removed phantom commands
This commit is contained in:
parent
b6af00d908
commit
1592b2892f
@ -2,47 +2,19 @@
|
|||||||
* @file sfdnsres.h
|
* @file sfdnsres.h
|
||||||
* @brief Domain name resolution service IPC wrapper. Please use socket.c instead.
|
* @brief Domain name resolution service IPC wrapper. Please use socket.c instead.
|
||||||
* @author TuxSH
|
* @author TuxSH
|
||||||
|
* @author fincs
|
||||||
* @copyright libnx Authors
|
* @copyright libnx Authors
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "../types.h"
|
#include "../types.h"
|
||||||
|
|
||||||
#include <sys/socket.h> // For socklen_t, etc.
|
// SetDnsAddressesPrivateRequest & GetDnsAddressPrivateRequest are stubbed
|
||||||
|
|
||||||
/// Configuration structure for sfdnsres.
|
Result sfdnsresGetHostByNameRequest(u32 timeout, bool use_nsd, const char *name, u32 *ret, u32 *errno_, void *out_buffer, size_t out_buffer_size, u32 *out_serialized_size);
|
||||||
typedef struct {
|
Result sfdnsresGetHostByAddrRequest(const void *in_addr, size_t in_addr_len, u32 type, u32 timeout, u32 *ret, u32 *errno_, void *out_buffer, size_t out_buffer_size, u32 *out_serialized_size);
|
||||||
size_t serialized_out_addrinfos_max_size; ///< For getaddrinfo.
|
Result sfdnsresGetHostStringErrorRequest(u32 err, char *out_str, size_t out_str_size);
|
||||||
size_t serialized_out_hostent_max_size; ///< For gethostbyname/gethostbyaddr.
|
Result sfdnsresGetGaiStringErrorRequest(u32 err, char *out_str, size_t out_str_size);
|
||||||
bool bypass_nsd; ///< For name gethostbyname/getaddrinfo: bypass the Name Server Daemon.
|
Result sfdnsresGetAddrInfoRequest(u32 timeout, bool use_nsd, const char *node, const char *service, const void *in_hints, size_t in_hints_size, void *out_buffer, size_t out_buffer_size, u32 *errno_, s32 *gaie, u32 *out_serialized_size);
|
||||||
int timeout; ///< For DNS requests: timeout or 0.
|
Result sfdnsresGetNameInfoRequest(u32 flags, const void *in_sa, size_t in_sa_size, char *out_host, size_t out_host_size, char *out_serv, size_t out_serv_len, u32 timeout, u32 *errno_, s32 *gaie);
|
||||||
} SfdnsresConfig;
|
Result sfdnsresGetCancelHandleRequest(u32 *out_handle);
|
||||||
|
Result sfdnsresCancelRequest(u32 handle);
|
||||||
/// Result values returned by the DNS request commands.
|
|
||||||
typedef struct {
|
|
||||||
int ret; ///< Return value (error code).
|
|
||||||
int errno_; ///< Errno.
|
|
||||||
ssize_t out_serialized_size; ///< Size of the serialized output buffer or -1 (?).
|
|
||||||
} SfdnsresRequestResults;
|
|
||||||
|
|
||||||
// SetDnsAddressesPrivate & GetDnsAddressPrivate are stubbed
|
|
||||||
|
|
||||||
Result sfdnsresGetHostByName(SfdnsresRequestResults *ret, const SfdnsresConfig *config, void *out_he_serialized, const char *name);
|
|
||||||
Result sfdnsresGetHostByAddr(SfdnsresRequestResults *ret, const SfdnsresConfig *config, void *out_he_serialized, const void *addr, socklen_t len, int type);
|
|
||||||
|
|
||||||
Result sfdnsresGetHostStringError(int err, char *str, size_t str_size);
|
|
||||||
Result sfdnsresGetGaiStringError(int err, char *str, size_t str_size);
|
|
||||||
|
|
||||||
Result sfdnsresGetAddrInfo(SfdnsresRequestResults *ret, const SfdnsresConfig *config, const char *node, const char *service,
|
|
||||||
const void *hints_serialized, size_t hints_serialized_size, void *res_serialized);
|
|
||||||
Result sfdnsresGetNameInfo(SfdnsresRequestResults *ret, const SfdnsresConfig *config,
|
|
||||||
const struct sockaddr *sa, socklen_t salen, char *host, size_t hostlen,
|
|
||||||
char *serv, size_t servlen, int flags);
|
|
||||||
|
|
||||||
/// Requests an handle for use with @ref sfdnsresCancelSocketCall.
|
|
||||||
Result sfdnsresRequestCancelHandle(u32 *out_handle);
|
|
||||||
/// Cancels a DNS request (how? which requests?). Bug: always sets errno?
|
|
||||||
Result sfdnsresCancelSocketCall(SfdnsresRequestResults *ret, u32 handle);
|
|
||||||
/// Cancels all DNS requests made by the current process (how? which requests?). Bug: always sets errno?
|
|
||||||
Result sfdnsresCancelAllSocketCalls(SfdnsresRequestResults *ret);
|
|
||||||
/// Clears up to 4 DNS server IPs registered by bsdcfg (DHCP client, etc.).
|
|
||||||
Result sfdnsresClearDnsIpServerAddressArray(void);
|
|
||||||
|
@ -25,6 +25,14 @@
|
|||||||
#include "services/nifm.h"
|
#include "services/nifm.h"
|
||||||
#include "result.h"
|
#include "result.h"
|
||||||
|
|
||||||
|
/// Configuration structure for sfdnsres.
|
||||||
|
typedef struct {
|
||||||
|
size_t serialized_out_addrinfos_max_size; ///< For getaddrinfo.
|
||||||
|
size_t serialized_out_hostent_max_size; ///< For gethostbyname/gethostbyaddr.
|
||||||
|
bool bypass_nsd; ///< For name gethostbyname/getaddrinfo: bypass the Name Server Daemon.
|
||||||
|
int timeout; ///< For DNS requests: timeout or 0.
|
||||||
|
} SfdnsresConfig;
|
||||||
|
|
||||||
__attribute__((weak)) size_t __nx_pollfd_sb_max_fds = 64;
|
__attribute__((weak)) size_t __nx_pollfd_sb_max_fds = 64;
|
||||||
|
|
||||||
int _convert_errno(int bsdErrno);
|
int _convert_errno(int bsdErrno);
|
||||||
@ -1425,14 +1433,22 @@ struct hostent *gethostbyname(const char *name) {
|
|||||||
Result rc = 0;
|
Result rc = 0;
|
||||||
void *out_he_serialized = malloc(g_sfdnsresConfig.serialized_out_hostent_max_size);
|
void *out_he_serialized = malloc(g_sfdnsresConfig.serialized_out_hostent_max_size);
|
||||||
struct hostent *he = NULL;
|
struct hostent *he = NULL;
|
||||||
SfdnsresRequestResults ret;
|
u32 ret = 0;
|
||||||
|
u32 errno_ = 0;
|
||||||
|
|
||||||
if(out_he_serialized == NULL) {
|
if(out_he_serialized == NULL) {
|
||||||
h_errno = NO_RECOVERY;
|
h_errno = NO_RECOVERY;
|
||||||
errno = ENOMEM; // POSIX leaves this unspecified
|
errno = ENOMEM; // POSIX leaves this unspecified
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
rc = sfdnsresGetHostByName(&ret, &g_sfdnsresConfig, out_he_serialized, name);
|
rc = sfdnsresGetHostByNameRequest(
|
||||||
|
g_sfdnsresConfig.timeout,
|
||||||
|
!g_sfdnsresConfig.bypass_nsd,
|
||||||
|
name,
|
||||||
|
&ret,
|
||||||
|
&errno_,
|
||||||
|
out_he_serialized, g_sfdnsresConfig.serialized_out_hostent_max_size,
|
||||||
|
NULL);
|
||||||
if(rc == 0xD401) {
|
if(rc == 0xD401) {
|
||||||
h_errno = NO_RECOVERY;
|
h_errno = NO_RECOVERY;
|
||||||
errno = EFAULT; // POSIX leaves this unspecified
|
errno = EFAULT; // POSIX leaves this unspecified
|
||||||
@ -1448,9 +1464,9 @@ struct hostent *gethostbyname(const char *name) {
|
|||||||
errno = EINVAL; // POSIX leaves this unspecified
|
errno = EINVAL; // POSIX leaves this unspecified
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
if(ret.ret != NETDB_SUCCESS) {
|
if(ret != NETDB_SUCCESS) {
|
||||||
h_errno = ret.ret;
|
h_errno = ret;
|
||||||
errno = ret.errno_; // POSIX leaves this unspecified
|
errno = errno_; // POSIX leaves this unspecified
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1469,14 +1485,22 @@ struct hostent *gethostbyaddr(const void *addr, socklen_t len, int type) {
|
|||||||
Result rc = 0;
|
Result rc = 0;
|
||||||
void *out_he_serialized = malloc(g_sfdnsresConfig.serialized_out_hostent_max_size);
|
void *out_he_serialized = malloc(g_sfdnsresConfig.serialized_out_hostent_max_size);
|
||||||
struct hostent *he = NULL;
|
struct hostent *he = NULL;
|
||||||
SfdnsresRequestResults ret;
|
u32 ret = 0;
|
||||||
|
u32 errno_ = 0;
|
||||||
|
|
||||||
if(out_he_serialized == NULL) {
|
if(out_he_serialized == NULL) {
|
||||||
h_errno = NO_RECOVERY;
|
h_errno = NO_RECOVERY;
|
||||||
errno = ENOMEM; // POSIX leaves this unspecified
|
errno = ENOMEM; // POSIX leaves this unspecified
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
rc = sfdnsresGetHostByAddr(&ret, &g_sfdnsresConfig, out_he_serialized, addr, len, type);
|
rc = sfdnsresGetHostByAddrRequest(
|
||||||
|
addr, len,
|
||||||
|
type,
|
||||||
|
g_sfdnsresConfig.timeout,
|
||||||
|
&ret,
|
||||||
|
&errno_,
|
||||||
|
out_he_serialized, g_sfdnsresConfig.serialized_out_hostent_max_size,
|
||||||
|
NULL);
|
||||||
if(rc == 0xD401) {
|
if(rc == 0xD401) {
|
||||||
h_errno = NO_RECOVERY; // POSIX leaves this unspecified
|
h_errno = NO_RECOVERY; // POSIX leaves this unspecified
|
||||||
errno = EFAULT;
|
errno = EFAULT;
|
||||||
@ -1492,9 +1516,9 @@ struct hostent *gethostbyaddr(const void *addr, socklen_t len, int type) {
|
|||||||
errno = EINVAL; // POSIX leaves this unspecified
|
errno = EINVAL; // POSIX leaves this unspecified
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
if(ret.ret != NETDB_SUCCESS) {
|
if(ret != NETDB_SUCCESS) {
|
||||||
h_errno = ret.ret;
|
h_errno = ret;
|
||||||
errno = ret.errno_; // POSIX leaves this unspecified
|
errno = errno_; // POSIX leaves this unspecified
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1511,7 +1535,7 @@ cleanup:
|
|||||||
|
|
||||||
const char *hstrerror(int err) {
|
const char *hstrerror(int err) {
|
||||||
static __thread char buf[0x80];
|
static __thread char buf[0x80];
|
||||||
Result rc = sfdnsresGetHostStringError(err, buf, 0x80);
|
Result rc = sfdnsresGetHostStringErrorRequest(err, buf, sizeof(buf));
|
||||||
if(R_FAILED(rc)) // a bit limiting, given the broad range of errors the kernel can give to us...
|
if(R_FAILED(rc)) // a bit limiting, given the broad range of errors the kernel can give to us...
|
||||||
strcpy(buf, "System busy, try again.");
|
strcpy(buf, "System busy, try again.");
|
||||||
g_sfdnsresResult = rc;
|
g_sfdnsresResult = rc;
|
||||||
@ -1524,7 +1548,7 @@ void herror(const char *str) {
|
|||||||
|
|
||||||
const char *gai_strerror(int err) {
|
const char *gai_strerror(int err) {
|
||||||
static __thread char buf[0x80];
|
static __thread char buf[0x80];
|
||||||
Result rc = sfdnsresGetGaiStringError(err, buf, 0x80);
|
Result rc = sfdnsresGetGaiStringErrorRequest(err, buf, sizeof(buf));
|
||||||
if(R_FAILED(rc))
|
if(R_FAILED(rc))
|
||||||
strcpy(buf, "System busy, try again.");
|
strcpy(buf, "System busy, try again.");
|
||||||
g_sfdnsresResult = rc;
|
g_sfdnsresResult = rc;
|
||||||
@ -1532,13 +1556,13 @@ const char *gai_strerror(int err) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res) {
|
int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res) {
|
||||||
int gaie = 0;
|
|
||||||
Result rc = 0;
|
Result rc = 0;
|
||||||
size_t hints_sz;
|
size_t hints_sz;
|
||||||
struct addrinfo_serialized_hdr *hints_serialized = _socketSerializeAddrInfoList(&hints_sz, hints);
|
struct addrinfo_serialized_hdr *hints_serialized = _socketSerializeAddrInfoList(&hints_sz, hints);
|
||||||
struct addrinfo_serialized_hdr *out_serialized = NULL;
|
struct addrinfo_serialized_hdr *out_serialized = NULL;
|
||||||
struct addrinfo *out = NULL;
|
struct addrinfo *out = NULL;
|
||||||
SfdnsresRequestResults ret;
|
u32 errno_ = 0;
|
||||||
|
s32 gaie = 0;
|
||||||
|
|
||||||
if(hints_serialized == NULL) {
|
if(hints_serialized == NULL) {
|
||||||
gaie = EAI_MEMORY;
|
gaie = EAI_MEMORY;
|
||||||
@ -1552,7 +1576,16 @@ int getaddrinfo(const char *node, const char *service, const struct addrinfo *hi
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = sfdnsresGetAddrInfo(&ret, &g_sfdnsresConfig, node, service, hints_serialized, hints_sz, out_serialized);
|
rc = sfdnsresGetAddrInfoRequest(
|
||||||
|
g_sfdnsresConfig.timeout,
|
||||||
|
!g_sfdnsresConfig.bypass_nsd,
|
||||||
|
node,
|
||||||
|
service,
|
||||||
|
hints_serialized, hints_sz,
|
||||||
|
out_serialized, g_sfdnsresConfig.serialized_out_addrinfos_max_size,
|
||||||
|
&errno_,
|
||||||
|
&gaie,
|
||||||
|
NULL);
|
||||||
|
|
||||||
if(rc == 0xD401) {
|
if(rc == 0xD401) {
|
||||||
gaie = EAI_SYSTEM;
|
gaie = EAI_SYSTEM;
|
||||||
@ -1568,10 +1601,9 @@ int getaddrinfo(const char *node, const char *service, const struct addrinfo *hi
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
gaie = ret.ret;
|
|
||||||
if(gaie != 0) {
|
if(gaie != 0) {
|
||||||
if(gaie == EAI_SYSTEM)
|
if(gaie == EAI_SYSTEM)
|
||||||
errno = ret.errno_;
|
errno = errno_;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1591,11 +1623,18 @@ 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) {
|
||||||
int gaie = 0;
|
|
||||||
Result rc = 0;
|
Result rc = 0;
|
||||||
SfdnsresRequestResults ret;
|
u32 errno_ = 0;
|
||||||
|
s32 gaie = 0;
|
||||||
|
|
||||||
rc = sfdnsresGetNameInfo(&ret, &g_sfdnsresConfig, sa, salen, host, hostlen, serv, servlen, flags);
|
rc = sfdnsresGetNameInfoRequest(
|
||||||
|
flags,
|
||||||
|
sa, salen,
|
||||||
|
host, hostlen,
|
||||||
|
serv, servlen,
|
||||||
|
g_sfdnsresConfig.timeout,
|
||||||
|
&errno_,
|
||||||
|
&gaie);
|
||||||
if(rc == 0xD401) {
|
if(rc == 0xD401) {
|
||||||
gaie = EAI_SYSTEM;
|
gaie = EAI_SYSTEM;
|
||||||
errno = EFAULT;
|
errno = EFAULT;
|
||||||
@ -1610,11 +1649,9 @@ int getnameinfo(const struct sockaddr *sa, socklen_t salen,
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
gaie = ret.ret;
|
|
||||||
if(gaie != 0) {
|
if(gaie != 0) {
|
||||||
if(gaie == EAI_SYSTEM)
|
if(gaie == EAI_SYSTEM)
|
||||||
errno = ret.errno_;
|
errno = errno_;
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
|
@ -1,274 +1,235 @@
|
|||||||
|
#define NX_SERVICE_ASSUME_NON_DOMAIN
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "result.h"
|
#include "result.h"
|
||||||
#include "kernel/ipc.h"
|
#include "sf/service.h"
|
||||||
#include "services/sm.h"
|
#include "services/sm.h"
|
||||||
#include "services/sfdnsres.h"
|
#include "services/sfdnsres.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
static Result _sfdnsresDispatchCommand(IpcParsedCommand *r, IpcCommand *c, const void *raw, size_t raw_size) {
|
NX_INLINE Result _sfdnsresDispatchImpl(
|
||||||
Service sfdnsres;
|
u32 request_id,
|
||||||
|
const void* in_data, u32 in_data_size,
|
||||||
|
void* out_data, u32 out_data_size,
|
||||||
|
const SfDispatchParams disp
|
||||||
|
) {
|
||||||
|
Handle h = INVALID_HANDLE;
|
||||||
|
Result rc = smGetServiceOriginal(&h, smEncodeName("sfdnsres"));
|
||||||
|
if (R_FAILED(rc))
|
||||||
|
return rc;
|
||||||
|
|
||||||
Result rc = smGetService(&sfdnsres, "sfdnsres");
|
// Construct service struct
|
||||||
if(R_FAILED(rc)) goto cleanup;
|
Service srv = {
|
||||||
|
.session = h,
|
||||||
|
.own_handle = 1,
|
||||||
|
.object_id = 0,
|
||||||
|
.pointer_buffer_size = 0, // No sfdnsres commands use HipcAutoSelect so this is left as 0
|
||||||
|
};
|
||||||
|
|
||||||
memcpy(ipcPrepareHeader(c, raw_size), raw, raw_size);
|
void* in = serviceMakeRequest(&srv, request_id, disp.context,
|
||||||
|
in_data_size, disp.in_send_pid,
|
||||||
|
disp.buffer_attrs, disp.buffers,
|
||||||
|
disp.in_num_objects, disp.in_objects,
|
||||||
|
disp.in_num_handles, disp.in_handles);
|
||||||
|
|
||||||
rc = serviceIpcDispatch(&sfdnsres);
|
if (in_data_size)
|
||||||
if(R_FAILED(rc)) goto cleanup;
|
__builtin_memcpy(in, in_data, in_data_size);
|
||||||
|
|
||||||
ipcParse(r);
|
rc = svcSendSyncRequest(h);
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
void* out = NULL;
|
||||||
|
rc = serviceParseResponse(&srv,
|
||||||
|
out_data_size, &out,
|
||||||
|
disp.out_num_objects, disp.out_objects,
|
||||||
|
disp.out_handle_attrs, disp.out_handles);
|
||||||
|
|
||||||
cleanup:
|
if (R_SUCCEEDED(rc) && out_data && out_data_size)
|
||||||
serviceClose(&sfdnsres);
|
__builtin_memcpy(out_data, out, out_data_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
serviceClose(&srv);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Result _sfdnsresDispatchDnsRequest(IpcCommand *c, SfdnsresRequestResults *ret, const void *raw, size_t raw_size, bool has_serialized_data_out) {
|
#define _sfdnsresDispatch(_rid,...) \
|
||||||
Result rc;
|
_sfdnsresDispatchImpl((_rid),NULL,0,NULL,0,(SfDispatchParams){ __VA_ARGS__ })
|
||||||
IpcParsedCommand r;
|
|
||||||
ipcSendPid(c);
|
|
||||||
|
|
||||||
rc = _sfdnsresDispatchCommand(&r, c, raw, raw_size);
|
#define _sfdnsresDispatchIn(_rid,_in,...) \
|
||||||
if(R_FAILED(rc)) return rc;
|
_sfdnsresDispatchImpl((_rid),&(_in),sizeof(_in),NULL,0,(SfDispatchParams){ __VA_ARGS__ })
|
||||||
|
|
||||||
|
#define _sfdnsresDispatchOut(_rid,_out,...) \
|
||||||
|
_sfdnsresDispatchImpl((_rid),NULL,0,&(_out),sizeof(_out),(SfDispatchParams){ __VA_ARGS__ })
|
||||||
|
|
||||||
|
#define _sfdnsresDispatchInOut(_rid,_in,_out,...) \
|
||||||
|
_sfdnsresDispatchImpl((_rid),&(_in),sizeof(_in),&(_out),sizeof(_out),(SfDispatchParams){ __VA_ARGS__ })
|
||||||
|
|
||||||
|
static Result _sfdnsresCmdInErrOutStr(u32 err, char *out_str, size_t out_str_size, u32 cmd_id) {
|
||||||
|
return _sfdnsresDispatchIn(cmd_id, err,
|
||||||
|
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out },
|
||||||
|
.buffers = { { out_str, out_str_size } },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result sfdnsresGetHostByNameRequest(u32 timeout, bool use_nsd, const char *name, u32 *ret, u32 *errno_, void *out_buffer, size_t out_buffer_size, u32 *out_serialized_size) {
|
||||||
|
const struct {
|
||||||
|
u32 use_nsd; // actually u8 bool, but promoted to u32 for convenience
|
||||||
|
u32 timeout;
|
||||||
|
u64 pid_placeholder;
|
||||||
|
} in = { use_nsd ? 1 : 0, timeout, 0 };
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
u64 magic;
|
u32 ret;
|
||||||
u64 result;
|
u32 errno_;
|
||||||
int ret;
|
u32 serialized_size;
|
||||||
int errno_;
|
} out = {};
|
||||||
int out_serialized_size; // OOB if !has_serialized_data
|
|
||||||
} *resp = r.Raw;
|
|
||||||
|
|
||||||
rc = resp->result;
|
Result rc = _sfdnsresDispatchInOut(2, in, out,
|
||||||
if(R_FAILED(rc)) return rc;
|
.in_send_pid = true,
|
||||||
|
.buffer_attrs = {
|
||||||
|
SfBufferAttr_HipcMapAlias | SfBufferAttr_In,
|
||||||
|
SfBufferAttr_HipcMapAlias | SfBufferAttr_Out,
|
||||||
|
},
|
||||||
|
.buffers = {
|
||||||
|
{ name, name ? strlen(name) + 1 : 0 },
|
||||||
|
{ out_buffer, out_buffer_size },
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
ret->ret = resp->ret;
|
if (R_SUCCEEDED(rc)) {
|
||||||
ret->errno_ = resp->errno_;
|
if (ret) *ret = out.ret;
|
||||||
ret->out_serialized_size = has_serialized_data_out ? resp->out_serialized_size : 0;
|
if (errno_) *errno_ = out.errno_;
|
||||||
|
if (out_serialized_size) *out_serialized_size = out.serialized_size;
|
||||||
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Result _sfdnsresDnsRequestCommand(IpcCommand *c, u64 cmd_id, SfdnsresRequestResults *ret, const SfdnsresConfig *config, bool has_serialized_data_out, int *arg) {
|
Result sfdnsresGetHostByAddrRequest(const void *in_addr, size_t in_addr_len, u32 type, u32 timeout, u32 *ret, u32 *errno_, void *out_buffer, size_t out_buffer_size, u32 *out_serialized_size) {
|
||||||
struct {
|
const struct {
|
||||||
u64 magic;
|
u32 len; // wtf nintendo
|
||||||
u64 cmd_id;
|
u32 type;
|
||||||
int arg;
|
u32 timeout;
|
||||||
int timeout;
|
u32 _padding;
|
||||||
u64 pid_placeholder;
|
u64 pid_placeholder;
|
||||||
} raw;
|
} in = { (u32)in_addr_len, type, timeout, 0, 0 };
|
||||||
|
|
||||||
raw.magic = SFCI_MAGIC;
|
struct {
|
||||||
raw.cmd_id = cmd_id;
|
u32 ret;
|
||||||
raw.arg = arg == NULL ? (config->bypass_nsd ? 0 : 1) : *arg;
|
u32 errno_;
|
||||||
raw.timeout = config->timeout;
|
u32 serialized_size;
|
||||||
raw.pid_placeholder = 0;
|
} out = {};
|
||||||
|
|
||||||
return _sfdnsresDispatchDnsRequest(c, ret, &raw, sizeof(raw), has_serialized_data_out);
|
Result rc = _sfdnsresDispatchInOut(3, in, out,
|
||||||
|
.buffer_attrs = {
|
||||||
|
SfBufferAttr_HipcMapAlias | SfBufferAttr_In,
|
||||||
|
SfBufferAttr_HipcMapAlias | SfBufferAttr_Out,
|
||||||
|
},
|
||||||
|
.buffers = {
|
||||||
|
{ in_addr, in_addr_len },
|
||||||
|
{ out_buffer, out_buffer_size },
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
if (ret) *ret = out.ret;
|
||||||
|
if (errno_) *errno_ = out.errno_;
|
||||||
|
if (out_serialized_size) *out_serialized_size = out.serialized_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Result _sfdnsresErrorStringGetterCommand(u64 cmd_id, int err, char *str, size_t str_size) {
|
|
||||||
IpcCommand c;
|
|
||||||
Result rc;
|
|
||||||
IpcParsedCommand r;
|
|
||||||
|
|
||||||
ipcInitialize(&c);
|
|
||||||
ipcAddRecvBuffer(&c, str, str_size, 0);
|
|
||||||
|
|
||||||
struct {
|
|
||||||
u64 magic;
|
|
||||||
u64 cmd_id;
|
|
||||||
int err;
|
|
||||||
} raw;
|
|
||||||
|
|
||||||
raw.magic = SFCI_MAGIC;
|
|
||||||
raw.cmd_id = cmd_id;
|
|
||||||
raw.err = err;
|
|
||||||
|
|
||||||
rc = _sfdnsresDispatchCommand(&r, &c, &raw, sizeof(raw));
|
|
||||||
if(R_FAILED(rc)) return rc;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
u64 magic;
|
|
||||||
u64 result;
|
|
||||||
} *resp = r.Raw;
|
|
||||||
|
|
||||||
rc = resp->result;
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result sfdnsresGetHostByName(SfdnsresRequestResults *ret, const SfdnsresConfig *config, void *out_he_serialized, const char *name) {
|
Result sfdnsresGetHostStringErrorRequest(u32 err, char *out_str, size_t out_str_size) {
|
||||||
IpcCommand c;
|
return _sfdnsresCmdInErrOutStr(err, out_str, out_str_size, 4);
|
||||||
ipcInitialize(&c);
|
|
||||||
ipcAddSendBuffer(&c, name, name == NULL ? 0 : strlen(name) + 1, 0);
|
|
||||||
ipcAddRecvBuffer(&c, out_he_serialized, config->serialized_out_hostent_max_size, 0);
|
|
||||||
|
|
||||||
return _sfdnsresDnsRequestCommand(&c, 2, ret, config, true, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result sfdnsresGetHostByAddr(SfdnsresRequestResults *ret, const SfdnsresConfig *config, void *out_he_serialized, const void *addr, socklen_t len, int type) {
|
Result sfdnsresGetGaiStringErrorRequest(u32 err, char *out_str, size_t out_str_size) {
|
||||||
IpcCommand c;
|
return _sfdnsresCmdInErrOutStr(err, out_str, out_str_size, 5);
|
||||||
struct {
|
}
|
||||||
u64 magic;
|
|
||||||
u64 cmd_id;
|
Result sfdnsresGetAddrInfoRequest(u32 timeout, bool use_nsd, const char *node, const char *service, const void *in_hints, size_t in_hints_size, void *out_buffer, size_t out_buffer_size, u32 *errno_, s32 *gaie, u32 *out_serialized_size) {
|
||||||
socklen_t len; // wtf nintendo
|
const struct {
|
||||||
int type;
|
u32 use_nsd; // actually u8 bool, but promoted to u32 for convenience
|
||||||
int timeout;
|
u32 timeout;
|
||||||
u64 pid_placeholder;
|
u64 pid_placeholder;
|
||||||
} raw;
|
} in = { use_nsd ? 1 : 0, timeout, 0 };
|
||||||
|
|
||||||
ipcInitialize(&c);
|
|
||||||
ipcAddSendBuffer(&c, addr, addr == NULL ? 0 : len, 0);
|
|
||||||
ipcAddRecvBuffer(&c, out_he_serialized, config->serialized_out_hostent_max_size, 0);
|
|
||||||
|
|
||||||
raw.magic = SFCI_MAGIC;
|
|
||||||
raw.cmd_id = 3;
|
|
||||||
raw.len = len;
|
|
||||||
raw.type = type;
|
|
||||||
raw.timeout = config->timeout;
|
|
||||||
raw.pid_placeholder = 0;
|
|
||||||
|
|
||||||
return _sfdnsresDispatchDnsRequest(&c, ret, &raw, sizeof(raw), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result sfdnsresGetHostStringError(int err, char *str, size_t str_size) {
|
|
||||||
return _sfdnsresErrorStringGetterCommand(4, err, str, str_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result sfdnsresGetGaiStringError(int err, char *str, size_t str_size) {
|
|
||||||
return _sfdnsresErrorStringGetterCommand(5, err, str, str_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result sfdnsresGetAddrInfo(SfdnsresRequestResults *ret, const SfdnsresConfig *config, const char *node, const char *service,
|
|
||||||
const void *hints_serialized, size_t hints_serialized_size, void *res_serialized) {
|
|
||||||
IpcCommand c;
|
|
||||||
size_t node_size = node == NULL ? 0 : strlen(node) + 1;
|
|
||||||
size_t service_size = service == NULL ? 0 : strlen(service) + 1;
|
|
||||||
hints_serialized_size = hints_serialized == NULL ? 0 : hints_serialized_size;
|
|
||||||
|
|
||||||
ipcInitialize(&c);
|
|
||||||
ipcAddSendBuffer(&c, node, node_size, 0);
|
|
||||||
ipcAddSendBuffer(&c, service, service_size, 0);
|
|
||||||
ipcAddSendBuffer(&c, hints_serialized, hints_serialized_size, 0);
|
|
||||||
|
|
||||||
ipcAddRecvBuffer(&c, res_serialized, config->serialized_out_hostent_max_size, 0);
|
|
||||||
|
|
||||||
return _sfdnsresDnsRequestCommand(&c, 6, ret, config, true, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result sfdnsresGetNameInfo(SfdnsresRequestResults *ret, const SfdnsresConfig *config,
|
|
||||||
const struct sockaddr *sa, socklen_t salen, char *host, size_t hostlen,
|
|
||||||
char *serv, size_t servlen, int flags) {
|
|
||||||
IpcCommand c;
|
|
||||||
|
|
||||||
salen = sa == NULL ? 0 : salen;
|
|
||||||
hostlen = host == NULL ? 0 : hostlen;
|
|
||||||
servlen = serv == NULL ? 0 : servlen;
|
|
||||||
|
|
||||||
ipcInitialize(&c);
|
|
||||||
ipcAddSendBuffer(&c, sa, salen, 0);
|
|
||||||
|
|
||||||
ipcAddRecvBuffer(&c, host, hostlen, 0);
|
|
||||||
ipcAddRecvBuffer(&c, serv, servlen, 0);
|
|
||||||
|
|
||||||
return _sfdnsresDnsRequestCommand(&c, 7, ret, config, false, &flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result sfdnsresRequestCancelHandle(u32 *out_handle) {
|
|
||||||
Result rc;
|
|
||||||
IpcCommand c;
|
|
||||||
IpcParsedCommand r;
|
|
||||||
struct {
|
struct {
|
||||||
u64 magic;
|
u32 errno_;
|
||||||
u64 cmd_id;
|
s32 gaie;
|
||||||
|
u32 serialized_size;
|
||||||
|
} out = {};
|
||||||
|
|
||||||
|
Result rc = _sfdnsresDispatchInOut(6, in, out,
|
||||||
|
.in_send_pid = true,
|
||||||
|
.buffer_attrs = {
|
||||||
|
SfBufferAttr_HipcMapAlias | SfBufferAttr_In,
|
||||||
|
SfBufferAttr_HipcMapAlias | SfBufferAttr_In,
|
||||||
|
SfBufferAttr_HipcMapAlias | SfBufferAttr_In,
|
||||||
|
SfBufferAttr_HipcMapAlias | SfBufferAttr_Out,
|
||||||
|
},
|
||||||
|
.buffers = {
|
||||||
|
{ node, node ? strlen(node) + 1 : 0 },
|
||||||
|
{ service, service ? strlen(service) + 1 : 0 },
|
||||||
|
{ in_hints, in_hints_size },
|
||||||
|
{ out_buffer, out_buffer_size },
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
if (errno_) *errno_ = out.errno_;
|
||||||
|
if (gaie) *gaie = out.gaie;
|
||||||
|
if (out_serialized_size) *out_serialized_size = out.serialized_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result sfdnsresGetNameInfoRequest(u32 flags, const void *in_sa, size_t in_sa_size, char *out_host, size_t out_host_size, char *out_serv, size_t out_serv_len, u32 timeout, u32 *errno_, s32 *gaie) {
|
||||||
|
const struct {
|
||||||
|
u32 flags;
|
||||||
|
u32 timeout;
|
||||||
u64 pid_placeholder;
|
u64 pid_placeholder;
|
||||||
} raw;
|
} in = { flags, timeout, 0 };
|
||||||
|
|
||||||
ipcInitialize(&c);
|
|
||||||
ipcSendPid(&c);
|
|
||||||
|
|
||||||
raw.magic = SFCI_MAGIC;
|
|
||||||
raw.cmd_id = 8;
|
|
||||||
raw.pid_placeholder = 0;
|
|
||||||
|
|
||||||
rc = _sfdnsresDispatchCommand(&r, &c, &raw, sizeof(raw));
|
|
||||||
if(R_FAILED(rc)) return rc;
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
u64 magic;
|
u32 errno_;
|
||||||
u64 result;
|
s32 gaie;
|
||||||
u32 handle;
|
} out;
|
||||||
} *resp = r.Raw;
|
|
||||||
|
Result rc = _sfdnsresDispatchInOut(7, in, out,
|
||||||
rc = resp->result;
|
.in_send_pid = true,
|
||||||
if(R_FAILED(rc)) return rc;
|
.buffer_attrs = {
|
||||||
|
SfBufferAttr_HipcMapAlias | SfBufferAttr_In,
|
||||||
*out_handle = resp->handle;
|
SfBufferAttr_HipcMapAlias | SfBufferAttr_Out,
|
||||||
|
SfBufferAttr_HipcMapAlias | SfBufferAttr_Out,
|
||||||
return rc;
|
},
|
||||||
}
|
.buffers = {
|
||||||
|
{ in_sa, in_sa_size },
|
||||||
/// Bug: always sets errno ?
|
{ out_host, out_host_size },
|
||||||
Result sfdnsresCancelSocketCall(SfdnsresRequestResults *ret, u32 handle) {
|
{ out_serv, out_serv_len },
|
||||||
IpcCommand c;
|
},
|
||||||
struct {
|
);
|
||||||
u64 magic;
|
|
||||||
u64 cmd_id;
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
if (errno_) *errno_ = out.errno_;
|
||||||
|
if (gaie) *gaie = out.gaie;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result sfdnsresGetCancelHandleRequest(u32 *out_handle) {
|
||||||
|
u64 pid_placeholder = 0;
|
||||||
|
return _sfdnsresDispatchInOut(8, pid_placeholder, *out_handle, .in_send_pid = true);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result sfdnsresCancelRequest(u32 handle) {
|
||||||
|
const struct {
|
||||||
u32 handle;
|
u32 handle;
|
||||||
|
u32 _padding;
|
||||||
u64 pid_placeholder;
|
u64 pid_placeholder;
|
||||||
} raw;
|
} in = { handle, 0, 0 };
|
||||||
|
|
||||||
ipcInitialize(&c);
|
return _sfdnsresDispatchIn(9, in, .in_send_pid = true);
|
||||||
|
|
||||||
raw.magic = SFCI_MAGIC;
|
|
||||||
raw.cmd_id = 9;
|
|
||||||
raw.handle = handle;
|
|
||||||
raw.pid_placeholder = 0;
|
|
||||||
|
|
||||||
return _sfdnsresDispatchDnsRequest(&c, ret, &raw, sizeof(raw), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Bug: always sets errno ?
|
|
||||||
Result sfdnsresCancelAllSocketCalls(SfdnsresRequestResults *ret) {
|
|
||||||
IpcCommand c;
|
|
||||||
struct {
|
|
||||||
u64 magic;
|
|
||||||
u64 cmd_id;
|
|
||||||
u64 pid_placeholder;
|
|
||||||
} raw;
|
|
||||||
|
|
||||||
ipcInitialize(&c);
|
|
||||||
|
|
||||||
raw.magic = SFCI_MAGIC;
|
|
||||||
raw.cmd_id = 10;
|
|
||||||
raw.pid_placeholder = 0;
|
|
||||||
|
|
||||||
return _sfdnsresDispatchDnsRequest(&c, ret, &raw, sizeof(raw), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result sfdnsresClearDnsIpServerAddressArray(void) {
|
|
||||||
Result rc;
|
|
||||||
IpcCommand c;
|
|
||||||
IpcParsedCommand r;
|
|
||||||
struct {
|
|
||||||
u64 magic;
|
|
||||||
u64 cmd_id;
|
|
||||||
} raw;
|
|
||||||
|
|
||||||
ipcInitialize(&c);
|
|
||||||
|
|
||||||
raw.magic = SFCI_MAGIC;
|
|
||||||
raw.cmd_id = 11;
|
|
||||||
|
|
||||||
rc = _sfdnsresDispatchCommand(&r, &c, &raw, sizeof(raw));
|
|
||||||
if(R_FAILED(rc)) return rc;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
u64 magic;
|
|
||||||
u64 result;
|
|
||||||
} *resp = r.Raw;
|
|
||||||
|
|
||||||
rc = resp->result;
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user