mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-21 12:32:40 +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
|
||||
* @brief Domain name resolution service IPC wrapper. Please use socket.c instead.
|
||||
* @author TuxSH
|
||||
* @author fincs
|
||||
* @copyright libnx Authors
|
||||
*/
|
||||
#pragma once
|
||||
#include "../types.h"
|
||||
|
||||
#include <sys/socket.h> // For socklen_t, etc.
|
||||
// SetDnsAddressesPrivateRequest & GetDnsAddressPrivateRequest are stubbed
|
||||
|
||||
/// 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;
|
||||
|
||||
/// 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);
|
||||
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);
|
||||
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);
|
||||
Result sfdnsresGetHostStringErrorRequest(u32 err, char *out_str, size_t out_str_size);
|
||||
Result sfdnsresGetGaiStringErrorRequest(u32 err, char *out_str, size_t out_str_size);
|
||||
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);
|
||||
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);
|
||||
Result sfdnsresGetCancelHandleRequest(u32 *out_handle);
|
||||
Result sfdnsresCancelRequest(u32 handle);
|
||||
|
@ -25,6 +25,14 @@
|
||||
#include "services/nifm.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;
|
||||
|
||||
int _convert_errno(int bsdErrno);
|
||||
@ -1425,14 +1433,22 @@ struct hostent *gethostbyname(const char *name) {
|
||||
Result rc = 0;
|
||||
void *out_he_serialized = malloc(g_sfdnsresConfig.serialized_out_hostent_max_size);
|
||||
struct hostent *he = NULL;
|
||||
SfdnsresRequestResults ret;
|
||||
u32 ret = 0;
|
||||
u32 errno_ = 0;
|
||||
|
||||
if(out_he_serialized == NULL) {
|
||||
h_errno = NO_RECOVERY;
|
||||
errno = ENOMEM; // POSIX leaves this unspecified
|
||||
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) {
|
||||
h_errno = NO_RECOVERY;
|
||||
errno = EFAULT; // POSIX leaves this unspecified
|
||||
@ -1448,9 +1464,9 @@ struct hostent *gethostbyname(const char *name) {
|
||||
errno = EINVAL; // POSIX leaves this unspecified
|
||||
goto cleanup;
|
||||
}
|
||||
if(ret.ret != NETDB_SUCCESS) {
|
||||
h_errno = ret.ret;
|
||||
errno = ret.errno_; // POSIX leaves this unspecified
|
||||
if(ret != NETDB_SUCCESS) {
|
||||
h_errno = ret;
|
||||
errno = errno_; // POSIX leaves this unspecified
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@ -1469,14 +1485,22 @@ struct hostent *gethostbyaddr(const void *addr, socklen_t len, int type) {
|
||||
Result rc = 0;
|
||||
void *out_he_serialized = malloc(g_sfdnsresConfig.serialized_out_hostent_max_size);
|
||||
struct hostent *he = NULL;
|
||||
SfdnsresRequestResults ret;
|
||||
u32 ret = 0;
|
||||
u32 errno_ = 0;
|
||||
|
||||
if(out_he_serialized == NULL) {
|
||||
h_errno = NO_RECOVERY;
|
||||
errno = ENOMEM; // POSIX leaves this unspecified
|
||||
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) {
|
||||
h_errno = NO_RECOVERY; // POSIX leaves this unspecified
|
||||
errno = EFAULT;
|
||||
@ -1492,9 +1516,9 @@ struct hostent *gethostbyaddr(const void *addr, socklen_t len, int type) {
|
||||
errno = EINVAL; // POSIX leaves this unspecified
|
||||
goto cleanup;
|
||||
}
|
||||
if(ret.ret != NETDB_SUCCESS) {
|
||||
h_errno = ret.ret;
|
||||
errno = ret.errno_; // POSIX leaves this unspecified
|
||||
if(ret != NETDB_SUCCESS) {
|
||||
h_errno = ret;
|
||||
errno = errno_; // POSIX leaves this unspecified
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@ -1511,7 +1535,7 @@ cleanup:
|
||||
|
||||
const char *hstrerror(int err) {
|
||||
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...
|
||||
strcpy(buf, "System busy, try again.");
|
||||
g_sfdnsresResult = rc;
|
||||
@ -1524,7 +1548,7 @@ void herror(const char *str) {
|
||||
|
||||
const char *gai_strerror(int err) {
|
||||
static __thread char buf[0x80];
|
||||
Result rc = sfdnsresGetGaiStringError(err, buf, 0x80);
|
||||
Result rc = sfdnsresGetGaiStringErrorRequest(err, buf, sizeof(buf));
|
||||
if(R_FAILED(rc))
|
||||
strcpy(buf, "System busy, try again.");
|
||||
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 gaie = 0;
|
||||
Result rc = 0;
|
||||
size_t hints_sz;
|
||||
struct addrinfo_serialized_hdr *hints_serialized = _socketSerializeAddrInfoList(&hints_sz, hints);
|
||||
struct addrinfo_serialized_hdr *out_serialized = NULL;
|
||||
struct addrinfo *out = NULL;
|
||||
SfdnsresRequestResults ret;
|
||||
u32 errno_ = 0;
|
||||
s32 gaie = 0;
|
||||
|
||||
if(hints_serialized == NULL) {
|
||||
gaie = EAI_MEMORY;
|
||||
@ -1552,7 +1576,16 @@ int getaddrinfo(const char *node, const char *service, const struct addrinfo *hi
|
||||
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) {
|
||||
gaie = EAI_SYSTEM;
|
||||
@ -1568,10 +1601,9 @@ int getaddrinfo(const char *node, const char *service, const struct addrinfo *hi
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
gaie = ret.ret;
|
||||
if(gaie != 0) {
|
||||
if(gaie == EAI_SYSTEM)
|
||||
errno = ret.errno_;
|
||||
errno = errno_;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@ -1591,11 +1623,18 @@ int getnameinfo(const struct sockaddr *sa, socklen_t salen,
|
||||
char *host, socklen_t hostlen,
|
||||
char *serv, socklen_t servlen,
|
||||
int flags) {
|
||||
int gaie = 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) {
|
||||
gaie = EAI_SYSTEM;
|
||||
errno = EFAULT;
|
||||
@ -1610,11 +1649,9 @@ int getnameinfo(const struct sockaddr *sa, socklen_t salen,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
||||
gaie = ret.ret;
|
||||
if(gaie != 0) {
|
||||
if(gaie == EAI_SYSTEM)
|
||||
errno = ret.errno_;
|
||||
errno = errno_;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
|
@ -1,274 +1,235 @@
|
||||
#define NX_SERVICE_ASSUME_NON_DOMAIN
|
||||
#include "types.h"
|
||||
#include "result.h"
|
||||
#include "kernel/ipc.h"
|
||||
#include "sf/service.h"
|
||||
#include "services/sm.h"
|
||||
#include "services/sfdnsres.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
static Result _sfdnsresDispatchCommand(IpcParsedCommand *r, IpcCommand *c, const void *raw, size_t raw_size) {
|
||||
Service sfdnsres;
|
||||
NX_INLINE Result _sfdnsresDispatchImpl(
|
||||
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");
|
||||
if(R_FAILED(rc)) goto cleanup;
|
||||
// Construct service struct
|
||||
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(R_FAILED(rc)) goto cleanup;
|
||||
if (in_data_size)
|
||||
__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:
|
||||
serviceClose(&sfdnsres);
|
||||
if (R_SUCCEEDED(rc) && out_data && out_data_size)
|
||||
__builtin_memcpy(out_data, out, out_data_size);
|
||||
}
|
||||
|
||||
serviceClose(&srv);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static Result _sfdnsresDispatchDnsRequest(IpcCommand *c, SfdnsresRequestResults *ret, const void *raw, size_t raw_size, bool has_serialized_data_out) {
|
||||
Result rc;
|
||||
IpcParsedCommand r;
|
||||
ipcSendPid(c);
|
||||
#define _sfdnsresDispatch(_rid,...) \
|
||||
_sfdnsresDispatchImpl((_rid),NULL,0,NULL,0,(SfDispatchParams){ __VA_ARGS__ })
|
||||
|
||||
rc = _sfdnsresDispatchCommand(&r, c, raw, raw_size);
|
||||
if(R_FAILED(rc)) return rc;
|
||||
#define _sfdnsresDispatchIn(_rid,_in,...) \
|
||||
_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 {
|
||||
u64 magic;
|
||||
u64 result;
|
||||
int ret;
|
||||
int errno_;
|
||||
int out_serialized_size; // OOB if !has_serialized_data
|
||||
} *resp = r.Raw;
|
||||
u32 ret;
|
||||
u32 errno_;
|
||||
u32 serialized_size;
|
||||
} out = {};
|
||||
|
||||
rc = resp->result;
|
||||
if(R_FAILED(rc)) return rc;
|
||||
Result rc = _sfdnsresDispatchInOut(2, in, out,
|
||||
.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;
|
||||
ret->errno_ = resp->errno_;
|
||||
ret->out_serialized_size = has_serialized_data_out ? resp->out_serialized_size : 0;
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
if (ret) *ret = out.ret;
|
||||
if (errno_) *errno_ = out.errno_;
|
||||
if (out_serialized_size) *out_serialized_size = out.serialized_size;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static Result _sfdnsresDnsRequestCommand(IpcCommand *c, u64 cmd_id, SfdnsresRequestResults *ret, const SfdnsresConfig *config, bool has_serialized_data_out, int *arg) {
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 cmd_id;
|
||||
int arg;
|
||||
int timeout;
|
||||
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) {
|
||||
const struct {
|
||||
u32 len; // wtf nintendo
|
||||
u32 type;
|
||||
u32 timeout;
|
||||
u32 _padding;
|
||||
u64 pid_placeholder;
|
||||
} raw;
|
||||
|
||||
raw.magic = SFCI_MAGIC;
|
||||
raw.cmd_id = cmd_id;
|
||||
raw.arg = arg == NULL ? (config->bypass_nsd ? 0 : 1) : *arg;
|
||||
raw.timeout = config->timeout;
|
||||
raw.pid_placeholder = 0;
|
||||
|
||||
return _sfdnsresDispatchDnsRequest(c, ret, &raw, sizeof(raw), has_serialized_data_out);
|
||||
}
|
||||
|
||||
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);
|
||||
} in = { (u32)in_addr_len, type, timeout, 0, 0 };
|
||||
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 cmd_id;
|
||||
int err;
|
||||
} raw;
|
||||
u32 ret;
|
||||
u32 errno_;
|
||||
u32 serialized_size;
|
||||
} out = {};
|
||||
|
||||
raw.magic = SFCI_MAGIC;
|
||||
raw.cmd_id = cmd_id;
|
||||
raw.err = err;
|
||||
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 },
|
||||
},
|
||||
);
|
||||
|
||||
rc = _sfdnsresDispatchCommand(&r, &c, &raw, sizeof(raw));
|
||||
if(R_FAILED(rc)) return rc;
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
if (ret) *ret = out.ret;
|
||||
if (errno_) *errno_ = out.errno_;
|
||||
if (out_serialized_size) *out_serialized_size = out.serialized_size;
|
||||
}
|
||||
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 result;
|
||||
} *resp = r.Raw;
|
||||
|
||||
rc = resp->result;
|
||||
return rc;
|
||||
}
|
||||
|
||||
Result sfdnsresGetHostByName(SfdnsresRequestResults *ret, const SfdnsresConfig *config, void *out_he_serialized, const char *name) {
|
||||
IpcCommand c;
|
||||
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 sfdnsresGetHostStringErrorRequest(u32 err, char *out_str, size_t out_str_size) {
|
||||
return _sfdnsresCmdInErrOutStr(err, out_str, out_str_size, 4);
|
||||
}
|
||||
|
||||
Result sfdnsresGetHostByAddr(SfdnsresRequestResults *ret, const SfdnsresConfig *config, void *out_he_serialized, const void *addr, socklen_t len, int type) {
|
||||
IpcCommand c;
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 cmd_id;
|
||||
socklen_t len; // wtf nintendo
|
||||
int type;
|
||||
int timeout;
|
||||
Result sfdnsresGetGaiStringErrorRequest(u32 err, char *out_str, size_t out_str_size) {
|
||||
return _sfdnsresCmdInErrOutStr(err, out_str, out_str_size, 5);
|
||||
}
|
||||
|
||||
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) {
|
||||
const struct {
|
||||
u32 use_nsd; // actually u8 bool, but promoted to u32 for convenience
|
||||
u32 timeout;
|
||||
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 {
|
||||
u64 magic;
|
||||
u64 cmd_id;
|
||||
u32 errno_;
|
||||
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;
|
||||
} raw;
|
||||
|
||||
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;
|
||||
} in = { flags, timeout, 0 };
|
||||
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 result;
|
||||
u32 handle;
|
||||
} *resp = r.Raw;
|
||||
|
||||
rc = resp->result;
|
||||
if(R_FAILED(rc)) return rc;
|
||||
|
||||
*out_handle = resp->handle;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/// Bug: always sets errno ?
|
||||
Result sfdnsresCancelSocketCall(SfdnsresRequestResults *ret, u32 handle) {
|
||||
IpcCommand c;
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 cmd_id;
|
||||
u32 errno_;
|
||||
s32 gaie;
|
||||
} out;
|
||||
|
||||
Result rc = _sfdnsresDispatchInOut(7, in, out,
|
||||
.in_send_pid = true,
|
||||
.buffer_attrs = {
|
||||
SfBufferAttr_HipcMapAlias | SfBufferAttr_In,
|
||||
SfBufferAttr_HipcMapAlias | SfBufferAttr_Out,
|
||||
SfBufferAttr_HipcMapAlias | SfBufferAttr_Out,
|
||||
},
|
||||
.buffers = {
|
||||
{ in_sa, in_sa_size },
|
||||
{ out_host, out_host_size },
|
||||
{ out_serv, out_serv_len },
|
||||
},
|
||||
);
|
||||
|
||||
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 _padding;
|
||||
u64 pid_placeholder;
|
||||
} raw;
|
||||
} in = { handle, 0, 0 };
|
||||
|
||||
ipcInitialize(&c);
|
||||
|
||||
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;
|
||||
return _sfdnsresDispatchIn(9, in, .in_send_pid = true);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user