sfdnsres: Major rewrite using new-ipc, fixed numerous IPC bugs, removed phantom commands

This commit is contained in:
fincs 2019-10-27 17:25:53 +01:00
parent b6af00d908
commit 1592b2892f
No known key found for this signature in database
GPG Key ID: 62C7609ADA219C60
3 changed files with 260 additions and 290 deletions

View File

@ -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);

View File

@ -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:

View File

@ -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;
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);
struct { struct {
u64 magic; u32 ret;
u64 cmd_id; u32 errno_;
int err; u32 serialized_size;
} raw; } out = {};
raw.magic = SFCI_MAGIC; Result rc = _sfdnsresDispatchInOut(3, in, out,
raw.cmd_id = cmd_id; .buffer_attrs = {
raw.err = err; 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_SUCCEEDED(rc)) {
if(R_FAILED(rc)) return 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; 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;
} }