Add sfdnsres

This commit is contained in:
TuxSH 2018-02-04 23:31:49 +01:00 committed by plutoo
parent 6884a9dd19
commit b8fb1722d0
4 changed files with 323 additions and 2 deletions

View File

@ -9,7 +9,6 @@
#include "../types.h"
#include "../kernel/tmem.h"
#include <sys/types.h> // for ssize_t, etc.
#include <sys/socket.h> // for socklen_t
#include <sys/select.h> // for fd_set
#include <poll.h> // for struct pollfd, ndfs_t

View File

@ -0,0 +1,40 @@
#pragma once
#include "../types.h"
#include <sys/socket.h> // For socklen_t, etc.
/// 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 DNS requests: 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(char *str, size_t str_size);
Result sfdnsresGetGaiStringError(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);
Result sfdnsresRequestCancelHandle(u32 *out_handle);
/// Bug: always sets errno ?
Result sfdnsresCancelSocketCall(SfdnsresRequestResults *ret, u32 handle);
/// Bug: always sets errno ?
Result sfdnsresCancelAllSocketCalls(SfdnsresRequestResults *ret);
Result sfdnsresClearDnsIpServerAddressArray(void);

View File

@ -53,7 +53,7 @@
*/
// Stripped some of them
#include <sys/types.h> // for ssize_t, etc.
#include <stdint.h>
#ifndef _SA_FAMILY_T_DECLARED

View File

@ -0,0 +1,282 @@
#include "types.h"
#include "result.h"
#include "ipc.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;
Result rc = smGetService(&sfdnsres, "sfdnsres");
if(R_FAILED(rc)) goto cleanup;
memcpy(ipcPrepareHeader(c, raw_size), raw, raw_size);
rc = serviceIpcDispatch(&sfdnsres);
if(R_FAILED(rc)) goto cleanup;
ipcParse(r);
cleanup:
serviceClose(&sfdnsres);
return rc;
}
static Result _sfdnsresDnsRequestCommand(IpcCommand *c, u64 cmd_id, SfdnsresRequestResults *ret, const SfdnsresConfig *config, bool has_serialized_data_out, int *arg) {
Result rc;
IpcParsedCommand r;
struct {
u64 magic;
u64 cmd_id;
int arg;
int timeout;
u64 pid_placeholder;
} raw;
ipcSendPid(c);
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;
rc = _sfdnsresDispatchCommand(&r, c, &raw, sizeof(raw));
if(R_FAILED(rc)) return rc;
struct {
u64 magic;
u64 result;
int ret;
int errno_;
int out_serialized_size; // OOB if !has_serialized_data
} *resp = r.Raw;
rc = resp->result;
if(R_FAILED(rc)) return rc;
ret->ret = resp->ret;
ret->errno_ = resp->errno_;
ret->out_serialized_size = has_serialized_data_out ? resp->out_serialized_size : 0;
return rc;
}
static Result _sfdnsresErrorStringGetterCommand(u64 cmd_id, 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;
} raw;
raw.magic = SFCI_MAGIC;
raw.cmd_id = cmd_id;
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;
}
Result sfdnsresGetHostByName(SfdnsresRequestResults *ret, const SfdnsresConfig *config, void *out_he_serialized, const char *name) {
IpcCommand c;
ipcInitialize(&c);
ipcAddSendBuffer(&c, name, 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) {
IpcCommand c;
ipcInitialize(&c);
ipcAddRecvBuffer(&c, out_he_serialized, config->serialized_out_hostent_max_size, 0);
return _sfdnsresDnsRequestCommand(&c, 3, ret, config, true, &type);
}
Result sfdnsresGetHostStringError(char *str, size_t str_size) {
return _sfdnsresErrorStringGetterCommand(4, str, str_size);
}
Result sfdnsresGetGaiStringError(char *str, size_t str_size) {
return _sfdnsresErrorStringGetterCommand(5, 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;
ipcInitialize(&c);
ipcAddSendBuffer(&c, node, strlen(node) + 1, 0);
ipcAddSendBuffer(&c, node, strlen(service) + 1, 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;
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;
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;
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) {
Result rc;
IpcCommand c;
IpcParsedCommand r;
struct {
u64 magic;
u64 cmd_id;
u32 handle;
u64 pid_placeholder;
} raw;
ipcInitialize(&c);
ipcSendPid(&c);
raw.magic = SFCI_MAGIC;
raw.cmd_id = 9;
raw.handle = handle;
raw.pid_placeholder = 0;
rc = _sfdnsresDispatchCommand(&r, &c, &raw, sizeof(raw));
if(R_FAILED(rc)) return rc;
struct {
u64 magic;
u64 result;
int ret;
int errno_;
} *resp = r.Raw;
rc = resp->result;
if(R_FAILED(rc)) return rc;
ret->ret = resp->ret;
ret->errno_ = resp->errno_;
return rc;
}
/// Bug: always sets errno ?
Result sfdnsresCancelAllSocketCalls(SfdnsresRequestResults *ret) {
Result rc;
IpcCommand c;
IpcParsedCommand r;
struct {
u64 magic;
u64 cmd_id;
u64 pid_placeholder;
} raw;
ipcInitialize(&c);
ipcSendPid(&c);
raw.magic = SFCI_MAGIC;
raw.cmd_id = 10;
raw.pid_placeholder = 0;
rc = _sfdnsresDispatchCommand(&r, &c, &raw, sizeof(raw));
if(R_FAILED(rc)) return rc;
struct {
u64 magic;
u64 result;
int ret;
int errno_;
} *resp = r.Raw;
rc = resp->result;
if(R_FAILED(rc)) return rc;
ret->ret = resp->ret;
ret->errno_ = resp->errno_;
return rc;
}
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;
}