static int soc_close(struct _reent *r, int fd) { Handle sockfd = *(Handle*)fd; int ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); cmdbuf[0] = IPC_MakeHeader(0xB,1,2); // 0xB0042 cmdbuf[1] = (u32)sockfd; cmdbuf[2] = IPC_Desc_CurProcessHandle(); ret = svcSendSyncRequest(SOCU_handle); if(ret != 0) { errno = SYNC_ERROR; return ret; } ret = (int)cmdbuf[1]; if(ret == 0) ret =_net_convert_error(cmdbuf[2]); if(ret < 0) { errno = -ret; return -1; } return 0; }
int socListen(int sockfd, int max_connections) { Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); cmdbuf[0] = IPC_MakeHeader(0x3,2,2); // 0x30082 cmdbuf[1] = (u32)sockfd; cmdbuf[2] = (u32)max_connections; cmdbuf[3] = IPC_Desc_CurProcessHandle(); ret = svcSendSyncRequest(SOCU_handle); if(ret != 0) { //errno = SYNC_ERROR; return ret; } ret = (int)cmdbuf[1]; if(ret == 0) ret = _net_convert_error(cmdbuf[2]); if(ret < 0) { //errno = -ret; return -1; } return 0; }
int socSetsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen) { int ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); cmdbuf[0] = IPC_MakeHeader(0x12,4,4); // 0x120104 cmdbuf[1] = (u32)sockfd; cmdbuf[2] = (u32)level; cmdbuf[3] = (u32)optname; cmdbuf[4] = (u32)optlen; cmdbuf[5] = IPC_Desc_CurProcessHandle(); cmdbuf[7] = IPC_Desc_StaticBuffer(optlen,9); cmdbuf[8] = (u32)optval; ret = svcSendSyncRequest(SOCU_handle); if(ret != 0) { return ret; } ret = (int)cmdbuf[1]; if(ret == 0) ret = _net_convert_error(cmdbuf[2]); if(ret < 0) { //errno = -ret; return -1; } return ret; }
int sockatmark(int sockfd) { int ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); sockfd = soc_get_fd(sockfd); if(sockfd < 0) { errno = -sockfd; return -1; } cmdbuf[0] = IPC_MakeHeader(0x15,1,2); // 0x150042 cmdbuf[1] = (u32)sockfd; cmdbuf[2] = IPC_Desc_CurProcessHandle(); ret = svcSendSyncRequest(SOCU_handle); if(ret != 0) { errno = SYNC_ERROR; return -1; } ret = (int)cmdbuf[1]; if(ret == 0) ret = _net_convert_error(cmdbuf[2]); if(ret < 0) { errno = -ret; return -1; } return ret; }
ssize_t socuipc_cmd8(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen) { int ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); u32 tmp_addrlen = 0; u8 tmpaddr[0x1c]; u32 saved_threadstorage[4]; if(src_addr) tmp_addrlen = 0x1c; memset(tmpaddr, 0, 0x1c); cmdbuf[0] = 0x00080102; cmdbuf[1] = (u32)sockfd; cmdbuf[2] = (u32)len; cmdbuf[3] = (u32)flags; cmdbuf[4] = (u32)tmp_addrlen; cmdbuf[5] = 0x20; saved_threadstorage[0] = cmdbuf[0x100>>2]; saved_threadstorage[1] = cmdbuf[0x104>>2]; saved_threadstorage[2] = cmdbuf[0x108>>2]; saved_threadstorage[3] = cmdbuf[0x10c>>2]; cmdbuf[0x100>>2] = (((u32)len)<<14) | 2; cmdbuf[0x104>>2] = (u32)buf; cmdbuf[0x108>>2] = (tmp_addrlen<<14) | 2; cmdbuf[0x10c>>2] = (u32)tmpaddr; ret = svcSendSyncRequest(SOCU_handle); if(ret != 0) { errno = SYNC_ERROR; return ret; } cmdbuf[0x100>>2] = saved_threadstorage[0]; cmdbuf[0x104>>2] = saved_threadstorage[1]; cmdbuf[0x108>>2] = saved_threadstorage[2]; cmdbuf[0x10c>>2] = saved_threadstorage[3]; ret = (int)cmdbuf[1]; if(ret == 0) ret = _net_convert_error(cmdbuf[2]); if(ret < 0) { errno = -ret; return -1; } if(src_addr != NULL) { src_addr->sa_family = tmpaddr[1]; if(*addrlen > tmpaddr[0]) *addrlen = tmpaddr[0]; memcpy(src_addr->sa_data, &tmpaddr[2], *addrlen - 2); } return ret; }
void dump_result_value(Result val) { if(-val < 0x80) { printf("%li(%li) : %s\n", val, _net_convert_error(val), strerror(-_net_convert_error(val))); return; } ctr_result_value res; res.val = val; printf("0x%08X :\n", (unsigned int)val); // if(val == -1) // return; printf("%-4u: %s\n", res.description, ctr_error_to_str(error_description_str, res.description)); printf("%-4u: %s\n", res.module, ctr_error_to_str(error_module_str, res.module)); printf("%-4u: %s\n", res.summary, ctr_error_to_str(error_summary_str, res.summary)); printf("%-4u: %s\n\n", res.level, ctr_error_to_str(error_level_str, res.level)); }
int getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen) { int ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); u32 saved_threadstorage[2]; u8 tmpaddr[0x1c]; sockfd = soc_get_fd(sockfd); if(sockfd < 0) { errno = -sockfd; return -1; } cmdbuf[0] = IPC_MakeHeader(0x17,2,2); // 0x170082 cmdbuf[1] = (u32)sockfd; cmdbuf[2] = 0x1c; cmdbuf[3] = IPC_Desc_CurProcessHandle(); u32 * staticbufs = getThreadStaticBuffers(); saved_threadstorage[0] = staticbufs[0]; saved_threadstorage[1] = staticbufs[1]; staticbufs[0] = IPC_Desc_StaticBuffer(0x1c,0); staticbufs[1] = (u32)tmpaddr; ret = svcSendSyncRequest(SOCU_handle); staticbufs[0] = saved_threadstorage[0]; staticbufs[1] = saved_threadstorage[1]; if(ret != 0) { errno = SYNC_ERROR; return ret; } ret = (int)cmdbuf[1]; if(ret == 0) ret = _net_convert_error(cmdbuf[2]); if(ret < 0) { errno = -ret; return -1; } if(*addrlen > tmpaddr[0]) *addrlen = tmpaddr[0]; memset(addr, 0, sizeof(struct sockaddr)); addr->sa_family = tmpaddr[1]; memcpy(addr->sa_data, &tmpaddr[2], *addrlen - 2); return ret; }
int socAccept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) { Result ret = 0; int tmp_addrlen = 0x1c; u32 *cmdbuf = getThreadCommandBuffer(); u8 tmpaddr[0x1c]; u32 saved_threadstorage[2]; memset(tmpaddr, 0, 0x1c); cmdbuf[0] = IPC_MakeHeader(0x4,2,2); // 0x40082 cmdbuf[1] = (u32)sockfd; cmdbuf[2] = (u32)tmp_addrlen; cmdbuf[3] = IPC_Desc_CurProcessHandle(); u32 *staticbufs = getThreadStaticBuffers(); saved_threadstorage[0] = staticbufs[0]; saved_threadstorage[1] = staticbufs[1]; staticbufs[0] = IPC_Desc_StaticBuffer(tmp_addrlen,0); staticbufs[1] = (u32)tmpaddr; ret = svcSendSyncRequest(SOCU_handle); staticbufs[0] = saved_threadstorage[0]; staticbufs[1] = saved_threadstorage[1]; if(ret != 0) return ret; ret = (int)cmdbuf[1]; if(ret == 0) ret = _net_convert_error(cmdbuf[2]); if(ret < 0) //errno = -ret; if(ret >= 0 && addr != NULL) { addr->sa_family = tmpaddr[1]; if(*addrlen > tmpaddr[0]) *addrlen = tmpaddr[0]; memcpy(addr->sa_data, &tmpaddr[2], *addrlen - 2); } if(ret < 0) return -1; return ret; }
int socPoll(struct pollfd *fds, nfds_t nfds, int timeout) { int ret = 0; nfds_t i; u32 size = sizeof(struct pollfd)*nfds; u32 *cmdbuf = getThreadCommandBuffer(); u32 saved_threadstorage[2]; if(nfds == 0) { return -1; } for(i = 0; i < nfds; ++i) { fds[i].revents = 0; } cmdbuf[0] = IPC_MakeHeader(0x14,2,4); // 0x140084 cmdbuf[1] = (u32)nfds; cmdbuf[2] = (u32)timeout; cmdbuf[3] = IPC_Desc_CurProcessHandle(); cmdbuf[5] = IPC_Desc_StaticBuffer(size,10); cmdbuf[6] = (u32)fds; u32 * staticbufs = getThreadStaticBuffers(); saved_threadstorage[0] = staticbufs[0]; saved_threadstorage[1] = staticbufs[1]; staticbufs[0] = IPC_Desc_StaticBuffer(size,0); staticbufs[1] = (u32)fds; ret = svcSendSyncRequest(SOCU_handle); staticbufs[0] = saved_threadstorage[0]; staticbufs[1] = saved_threadstorage[1]; if(ret != 0) { return ret; } ret = (int)cmdbuf[1]; if(ret == 0) ret = _net_convert_error(cmdbuf[2]); if(ret < 0) { //errno = -ret; return -1; } return ret; }
int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen) { int ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); u32 saved_threadstorage[2]; sockfd = soc_get_fd(sockfd); if(sockfd < 0) { errno = -sockfd; return -1; } cmdbuf[0] = IPC_MakeHeader(0x11,4,2); // 0x110102 cmdbuf[1] = (u32)sockfd; cmdbuf[2] = (u32)level; cmdbuf[3] = (u32)optname; cmdbuf[4] = (u32)*optlen; cmdbuf[5] = IPC_Desc_CurProcessHandle(); u32 * staticbufs = getThreadStaticBuffers(); saved_threadstorage[0] = staticbufs[0]; saved_threadstorage[1] = staticbufs[1]; staticbufs[0] = IPC_Desc_StaticBuffer(*optlen,0); staticbufs[1] = (u32)optval; ret = svcSendSyncRequest(SOCU_handle); staticbufs[0] = saved_threadstorage[0]; staticbufs[1] = saved_threadstorage[1]; if(ret != 0) { errno = SYNC_ERROR; return ret; } ret = (int)cmdbuf[1]; if(ret == 0) ret = _net_convert_error(cmdbuf[2]); if(ret < 0) { errno = -ret; return -1; } *optlen = cmdbuf[3]; return ret; }
int socBind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { Result ret = 0; socklen_t tmp_addrlen = 0; u32 *cmdbuf = getThreadCommandBuffer(); u8 tmpaddr[0x1c]; memset(tmpaddr, 0, 0x1c); if(addr->sa_family == AF_INET) tmp_addrlen = 8; else tmp_addrlen = 0x1c; if(addrlen < tmp_addrlen) { //errno = EINVAL; return -1; } tmpaddr[0] = tmp_addrlen; tmpaddr[1] = addr->sa_family; memcpy(&tmpaddr[2], &addr->sa_data, tmp_addrlen-2); cmdbuf[0] = IPC_MakeHeader(0x5,2,4); // 0x50084 cmdbuf[1] = (u32)sockfd; cmdbuf[2] = (u32)tmp_addrlen; cmdbuf[3] = IPC_Desc_CurProcessHandle(); cmdbuf[5] = IPC_Desc_StaticBuffer(tmp_addrlen,0); cmdbuf[6] = (u32)tmpaddr; ret = svcSendSyncRequest(SOCU_handle); if(ret != 0) { //errno = SYNC_ERROR; return ret; } ret = (int)cmdbuf[1]; if(ret == 0) ret = _net_convert_error(cmdbuf[2]); if(ret < 0) { //errno = -ret; return -1; } return ret; }
int getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen) { int ret=0; u32 *cmdbuf = getThreadCommandBuffer(); u32 saved_threadstorage[2]; u8 tmpaddr[0x1c]; cmdbuf[0] = 0x00170082; cmdbuf[1] = (u32)sockfd; cmdbuf[2] = 0x1c; cmdbuf[3] = 0x20; saved_threadstorage[0] = cmdbuf[0x100>>2]; saved_threadstorage[1] = cmdbuf[0x104>>2]; cmdbuf[0x100>>2] = (0x1c<<14) | 2; cmdbuf[0x104>>2] = (u32)tmpaddr; if((ret = svcSendSyncRequest(SOCU_handle))!=0)return ret; cmdbuf[0x100>>2] = saved_threadstorage[0]; cmdbuf[0x104>>2] = saved_threadstorage[1]; ret = (int)cmdbuf[1]; if(ret==0)ret = _net_convert_error(cmdbuf[2]); if(ret<0)SOCU_errno = ret; if(ret==0) { if(*addrlen > tmpaddr[0])*addrlen = tmpaddr[0]; memset(addr, 0, sizeof(struct sockaddr)); addr->sa_family = tmpaddr[1]; memcpy(addr->sa_data, &tmpaddr[2], *addrlen - 2); } if(ret<0)return -1; return ret; }
int poll(struct pollfd *fds, nfds_t nfds, int timeout) { int ret = 0; nfds_t i; u32 size = sizeof(struct pollfd)*nfds; u32 *cmdbuf = getThreadCommandBuffer(); u32 saved_threadstorage[2]; if(nfds == 0) { errno = EINVAL; return -1; } struct pollfd *tmp_fds = (struct pollfd*)malloc(sizeof(struct pollfd) * nfds); if(tmp_fds == NULL) { errno = ENOMEM; return -1; } memcpy(tmp_fds, fds, sizeof(struct pollfd) * nfds); for(i = 0; i < nfds; ++i) { tmp_fds[i].fd = soc_get_fd(fds[i].fd); if(tmp_fds[i].fd < 0) { errno = -tmp_fds[i].fd; free(tmp_fds); return -1; } tmp_fds[i].revents = 0; } cmdbuf[0] = IPC_MakeHeader(0x14,2,4); // 0x140084 cmdbuf[1] = (u32)nfds; cmdbuf[2] = (u32)timeout; cmdbuf[3] = IPC_Desc_CurProcessHandle(); cmdbuf[5] = IPC_Desc_StaticBuffer(size,10); cmdbuf[6] = (u32)tmp_fds; u32 * staticbufs = getThreadStaticBuffers(); saved_threadstorage[0] = staticbufs[0]; saved_threadstorage[1] = staticbufs[1]; staticbufs[0] = IPC_Desc_StaticBuffer(size,0); staticbufs[1] = (u32)tmp_fds; ret = svcSendSyncRequest(SOCU_handle); if(ret != 0) { free(tmp_fds); errno = SYNC_ERROR; return ret; } staticbufs[0] = saved_threadstorage[0]; staticbufs[1] = saved_threadstorage[1]; ret = (int)cmdbuf[1]; if(ret == 0) ret = _net_convert_error(cmdbuf[2]); if(ret < 0) { free(tmp_fds); errno = -ret; return -1; } for(i = 0; i < nfds; ++i) fds[i].revents = tmp_fds[i].revents; free(tmp_fds); return ret; }
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) { int ret = 0; int tmp_addrlen = 0x1c; int fd, dev; __handle *handle; u32 *cmdbuf = getThreadCommandBuffer(); u8 tmpaddr[0x1c]; u32 saved_threadstorage[2]; sockfd = soc_get_fd(sockfd); if(sockfd < 0) { errno = -sockfd; return -1; } dev = FindDevice("soc:"); if(dev < 0) { errno = ENODEV; return -1; } fd = __alloc_handle(sizeof(__handle) + sizeof(Handle)); if(fd < 0) { errno = ENOMEM; return -1; } handle = __get_handle(fd); handle->device = dev; handle->fileStruct = ((void *)handle) + sizeof(__handle); memset(tmpaddr, 0, 0x1c); cmdbuf[0] = IPC_MakeHeader(0x4,2,2); // 0x40082 cmdbuf[1] = (u32)sockfd; cmdbuf[2] = (u32)tmp_addrlen; cmdbuf[3] = IPC_Desc_CurProcessHandle(); u32 * staticbufs = getThreadStaticBuffers(); saved_threadstorage[0] = staticbufs[0]; saved_threadstorage[1] = staticbufs[1]; staticbufs[0] = IPC_Desc_StaticBuffer(tmp_addrlen,0); staticbufs[1] = (u32)tmpaddr; ret = svcSendSyncRequest(SOCU_handle); staticbufs[0] = saved_threadstorage[0]; staticbufs[1] = saved_threadstorage[1]; if(ret != 0) { __release_handle(fd); errno = SYNC_ERROR; return ret; } ret = (int)cmdbuf[1]; if(ret == 0) ret = _net_convert_error(cmdbuf[2]); if(ret < 0) errno = -ret; if(ret >= 0 && addr != NULL) { addr->sa_family = tmpaddr[1]; if(*addrlen > tmpaddr[0]) *addrlen = tmpaddr[0]; memcpy(addr->sa_data, &tmpaddr[2], *addrlen - 2); } if(ret < 0) { __release_handle(fd); return -1; } else *(Handle*)handle->fileStruct = ret; return fd; }
int socket(int domain, int type, int protocol) { int ret = 0; int fd, dev; __handle *handle; u32 *cmdbuf = getThreadCommandBuffer(); // The protocol on the 3DS *must* be 0 to work // To that end, when appropriate, we will make the change for the user if (domain == AF_INET && type == SOCK_STREAM && protocol == IPPROTO_TCP) { protocol = 0; // TCP is the only option, so 0 will work as expected } if (domain == AF_INET && type == SOCK_DGRAM && protocol == IPPROTO_UDP) { protocol = 0; // UDP is the only option, so 0 will work as expected } cmdbuf[0] = IPC_MakeHeader(0x2,3,2); // 0x200C2 cmdbuf[1] = domain; cmdbuf[2] = type; cmdbuf[3] = protocol; cmdbuf[4] = IPC_Desc_CurProcessHandle(); dev = FindDevice("soc:"); if(dev < 0) { errno = ENODEV; return -1; } fd = __alloc_handle(sizeof(__handle) + sizeof(Handle)); if(fd < 0) { errno = ENOMEM; return -1; } handle = __get_handle(fd); handle->device = dev; handle->fileStruct = ((void *)handle) + sizeof(__handle); ret = svcSendSyncRequest(SOCU_handle); if(ret != 0) { __release_handle(fd); errno = SYNC_ERROR; return ret; } ret = (int)cmdbuf[1]; if(ret == 0)ret = cmdbuf[2]; if(ret < 0) { __release_handle(fd); if(cmdbuf[1] == 0)errno = _net_convert_error(ret); if(cmdbuf[1] != 0)errno = SYNC_ERROR; return -1; } *(Handle*)handle->fileStruct = cmdbuf[2]; return fd; }
struct hostent* gethostbyaddr(const void *addr, socklen_t len, int type) { int ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); u32 saved_threadstorage[2]; static u8 outbuf[0x1A88]; h_errno = 0; cmdbuf[0] = 0x000E00C2; cmdbuf[1] = len; cmdbuf[2] = type; cmdbuf[3] = sizeof(outbuf); cmdbuf[4] = (len << 14) | 0x1002; cmdbuf[5] = (u32)addr; saved_threadstorage[0] = cmdbuf[0x100>>2]; saved_threadstorage[1] = cmdbuf[0x104>>2]; cmdbuf[0x100>>2] = (sizeof(outbuf) << 14) | 2; cmdbuf[0x104>>2] = (u32)outbuf; ret = svcSendSyncRequest(SOCU_handle); if(ret != 0) { h_errno = NO_RECOVERY; return NULL; } cmdbuf[0x100>>2] = saved_threadstorage[0]; cmdbuf[0x104>>2] = saved_threadstorage[1]; ret = (int)cmdbuf[1]; if(ret == 0) ret = _net_convert_error(cmdbuf[2]); if(ret < 0) { /* TODO: set h_errno based on ret */ h_errno = HOST_NOT_FOUND; return NULL; } u32 num_results, i; memcpy(&num_results, (char*)outbuf+4, sizeof(num_results)); if(num_results > MAX_HOSTENT_RESULTS) num_results = MAX_HOSTENT_RESULTS; SOC_hostent.h_name = (char*)outbuf + 8; SOC_hostent.h_aliases = &SOC_hostent_alias; SOC_hostent.h_addrtype = AF_INET; SOC_hostent.h_length = 4; SOC_hostent.h_addr_list = SOC_hostent_results; SOC_hostent_alias = NULL; for(i = 0; i < num_results; ++i) SOC_hostent_results[i] = (char*)outbuf + 0x1908 + i*0x10; SOC_hostent_results[num_results] = NULL; SOC_hostent.h_addr = SOC_hostent.h_addr_list[0]; return &SOC_hostent; }
struct hostent* gethostbyname(const char *name) { int ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); u32 saved_threadstorage[2]; static u8 outbuf[0x1A88]; h_errno = 0; cmdbuf[0] = IPC_MakeHeader(0xD,2,2); // 0xD0082 cmdbuf[1] = strlen(name)+1; cmdbuf[2] = sizeof(outbuf); cmdbuf[3] = ((strlen(name)+1) << 14) | 0xC02; cmdbuf[4] = (u32)name; u32 * staticbufs = getThreadStaticBuffers(); saved_threadstorage[0] = staticbufs[0]; saved_threadstorage[1] = staticbufs[1]; staticbufs[0] = IPC_Desc_StaticBuffer(sizeof(outbuf),0); staticbufs[1] = (u32)outbuf; ret = svcSendSyncRequest(SOCU_handle); if(ret != 0) { h_errno = NO_RECOVERY; return NULL; } staticbufs[0] = saved_threadstorage[0]; staticbufs[1] = saved_threadstorage[1]; ret = (int)cmdbuf[1]; if(ret == 0) ret = _net_convert_error(cmdbuf[2]); if(ret < 0) { /* TODO: set h_errno based on ret */ h_errno = HOST_NOT_FOUND; return NULL; } u32 num_results, i; memcpy(&num_results, (char*)outbuf+4, sizeof(num_results)); if(num_results > MAX_HOSTENT_RESULTS) num_results = MAX_HOSTENT_RESULTS; SOC_hostent.h_name = (char*)outbuf + 8; SOC_hostent.h_aliases = &SOC_hostent_alias; SOC_hostent.h_addrtype = AF_INET; SOC_hostent.h_length = 4; SOC_hostent.h_addr_list = SOC_hostent_results; SOC_hostent_alias = NULL; for(i = 0; i < num_results; ++i) SOC_hostent_results[i] = (char*)outbuf + 0x1908 + i*0x10; SOC_hostent_results[num_results] = NULL; SOC_hostent.h_addr = SOC_hostent.h_addr_list[0]; return &SOC_hostent; }