#define NX_SERVICE_ASSUME_NON_DOMAIN #include "types.h" #include "result.h" #include "sf/service.h" #include "services/sm.h" #include "services/sfdnsres.h" #include 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; // 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 }; 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); if (in_data_size) __builtin_memcpy(in, in_data, in_data_size); 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); if (R_SUCCEEDED(rc) && out_data && out_data_size) __builtin_memcpy(out_data, out, out_data_size); } serviceClose(&srv); return rc; } #define _sfdnsresDispatch(_rid,...) \ _sfdnsresDispatchImpl((_rid),NULL,0,NULL,0,(SfDispatchParams){ __VA_ARGS__ }) #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 cancel_handle, bool use_nsd, const char *name, u32 *h_errno_, 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 cancel_handle; u64 pid_placeholder; } in = { use_nsd ? 1 : 0, cancel_handle, 0 }; struct { u32 h_errno_; u32 errno_; u32 serialized_size; } out = {}; 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 }, }, ); if (R_SUCCEEDED(rc)) { if (h_errno_) *h_errno_ = out.h_errno_; if (errno_) *errno_ = out.errno_; if (out_serialized_size) *out_serialized_size = out.serialized_size; } return rc; } Result sfdnsresGetHostByAddrRequest(const void *in_addr, size_t in_addr_len, u32 type, u32 cancel_handle, u32 *h_errno_, u32 *errno_, void *out_buffer, size_t out_buffer_size, u32 *out_serialized_size) { const struct { u32 len; // wtf nintendo u32 type; u32 cancel_handle; u32 _padding; u64 pid_placeholder; } in = { (u32)in_addr_len, type, cancel_handle, 0, 0 }; struct { u32 h_errno_; u32 errno_; u32 serialized_size; } 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 (h_errno_) *h_errno_ = out.h_errno_; if (errno_) *errno_ = out.errno_; if (out_serialized_size) *out_serialized_size = out.serialized_size; } return rc; } Result sfdnsresGetHostStringErrorRequest(u32 err, char *out_str, size_t out_str_size) { return _sfdnsresCmdInErrOutStr(err, out_str, out_str_size, 4); } Result sfdnsresGetGaiStringErrorRequest(u32 err, char *out_str, size_t out_str_size) { return _sfdnsresCmdInErrOutStr(err, out_str, out_str_size, 5); } Result sfdnsresGetAddrInfoRequest(u32 cancel_handle, 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 *ret, u32 *out_serialized_size) { const struct { u32 use_nsd; // actually u8 bool, but promoted to u32 for convenience u32 cancel_handle; u64 pid_placeholder; } in = { use_nsd ? 1 : 0, cancel_handle, 0 }; struct { u32 errno_; s32 ret; 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 (ret) *ret = out.ret; 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 cancel_handle, u32 *errno_, s32 *ret) { const struct { u32 flags; u32 cancel_handle; u64 pid_placeholder; } in = { flags, cancel_handle, 0 }; struct { u32 errno_; s32 ret; } 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 (ret) *ret = out.ret; } 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; } in = { handle, 0, 0 }; return _sfdnsresDispatchIn(9, in, .in_send_pid = true); }