MochaPayload/source/ios_mcp/source/socket.c
2023-02-16 20:04:17 +01:00

236 lines
5.1 KiB
C

#include "socket.h"
#include "imports.h"
#include "svc.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static int socket_handle = 0;
int socketInit() {
if (socket_handle) return socket_handle;
int ret = svcOpen("/dev/socket", 0);
if (ret > 0) {
socket_handle = ret;
return socket_handle;
}
return ret;
}
int socketExit() {
int ret = svcClose(socket_handle);
socket_handle = 0;
return ret;
}
static void *allocIobuf(u32 size) {
void *ptr = svcAlloc(0xCAFF, size);
if (ptr) memset(ptr, 0x00, size);
return ptr;
}
static void freeIobuf(void *ptr) {
svcFree(0xCAFF, ptr);
}
int socket(int domain, int type, int protocol) {
u8 *iobuf = allocIobuf(0xC);
u32 *inbuf = (u32 *) iobuf;
inbuf[0] = domain;
inbuf[1] = type;
inbuf[2] = protocol;
int ret = svcIoctl(socket_handle, 0x11, inbuf, 0xC, NULL, 0);
freeIobuf(iobuf);
return ret;
}
int closesocket(int sockfd) {
u8 *iobuf = allocIobuf(0x4);
u32 *inbuf = (u32 *) iobuf;
inbuf[0] = sockfd;
int ret = svcIoctl(socket_handle, 0x3, inbuf, 0x4, NULL, 0);
freeIobuf(iobuf);
return ret;
}
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) {
u8 *iobuf = allocIobuf(0x18);
u32 *inbuf = (u32 *) iobuf;
u32 *outbuf = (u32 *) inbuf;
inbuf[0] = sockfd;
int ret = -1;
if (addr && addrlen && *addrlen == 0x10) {
inbuf[5] = *addrlen;
ret = svcIoctl(socket_handle, 0x1, inbuf, 0x18, outbuf, 0x18);
if (ret >= 0) {
memcpy(addr, &outbuf[1], outbuf[5]);
*addrlen = outbuf[5];
}
} else {
inbuf[5] = 0x10;
ret = svcIoctl(socket_handle, 0x1, inbuf, 0x18, outbuf, 0x18);
}
freeIobuf(iobuf);
return ret;
}
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
if (addrlen != 0x10) return -1;
u8 *iobuf = allocIobuf(0x18);
u32 *inbuf = (u32 *) iobuf;
inbuf[0] = sockfd;
memcpy(&inbuf[1], addr, addrlen);
inbuf[5] = addrlen;
int ret = svcIoctl(socket_handle, 0x2, inbuf, 0x18, NULL, 0);
freeIobuf(iobuf);
return ret;
}
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
if (addrlen != 0x10) return -1;
u8 *iobuf = allocIobuf(0x18);
u32 *inbuf = (u32 *) iobuf;
inbuf[0] = sockfd;
memcpy(&inbuf[1], addr, addrlen);
inbuf[5] = addrlen;
int ret = svcIoctl(socket_handle, 0x4, inbuf, 0x18, NULL, 0);
freeIobuf(iobuf);
return ret;
}
int listen(int sockfd, int backlog) {
u8 *iobuf = allocIobuf(0x8);
u32 *inbuf = (u32 *) iobuf;
inbuf[0] = sockfd;
inbuf[1] = backlog;
int ret = svcIoctl(socket_handle, 0xA, inbuf, 0x8, NULL, 0);
freeIobuf(iobuf);
return ret;
}
int shutdown(int sockfd, int how) {
u8 *iobuf = allocIobuf(0x8);
u32 *inbuf = (u32 *) iobuf;
inbuf[0] = sockfd;
inbuf[1] = how;
int ret = svcIoctl(socket_handle, 0x10, inbuf, 0x8, NULL, 0);
freeIobuf(iobuf);
return ret;
}
int recv(int sockfd, void *buf, size_t len, int flags) {
if (!len) return -101;
// TODO : size checks, split up data into multiple vectors if necessary
void *data_buf = svcAllocAlign(0xCAFF, len, 0x40);
if (!data_buf) return -100;
u8 *iobuf = allocIobuf(0x38);
iovec_s *iovec = (iovec_s *) iobuf;
u32 *inbuf = (u32 *) &iobuf[0x30];
inbuf[0] = sockfd;
inbuf[1] = flags;
iovec[0].ptr = inbuf;
iovec[0].len = 0x8;
iovec[1].ptr = (void *) data_buf;
iovec[1].len = len;
int ret = svcIoctlv(socket_handle, 0xC, 1, 3, iovec);
if (ret > 0 && buf) {
memcpy(buf, data_buf, ret);
}
freeIobuf(data_buf);
freeIobuf(iobuf);
return ret;
}
int send(int sockfd, const void *buf, size_t len, int flags) {
if (!buf || !len) return -101;
// TODO : size checks, split up data into multiple vectors if necessary
void *data_buf = svcAllocAlign(0xCAFF, len, 0x40);
if (!data_buf) return -100;
u8 *iobuf = allocIobuf(0x38);
iovec_s *iovec = (iovec_s *) iobuf;
u32 *inbuf = (u32 *) &iobuf[0x30];
memcpy(data_buf, buf, len);
inbuf[0] = sockfd;
inbuf[1] = flags;
iovec[0].ptr = inbuf;
iovec[0].len = 0x8;
iovec[1].ptr = (void *) data_buf;
iovec[1].len = len;
int ret = svcIoctlv(socket_handle, 0xE, 4, 0, iovec);
freeIobuf(data_buf);
freeIobuf(iobuf);
return ret;
}
int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen) {
void *data_buf = svcAllocAlign(0xCAFF, optlen, 0x40);
if (!data_buf) return -100;
u8 *iobuf = allocIobuf(sizeof(IOSVec) * 2 + sizeof(uint32_t) * 3);
iovec_s *iovec = (iovec_s *) iobuf;
memcpy(data_buf, optval, optlen);
iovec[0].ptr = data_buf;
iovec[0].len = optlen;
iovec[1].ptr = iovec;
iovec[1].len = sizeof(IOSVec) * 3;
((uint32_t *) iovec)[6] = sockfd;
((uint32_t *) iovec)[7] = level;
((uint32_t *) iovec)[8] = optname;
int ret = svcIoctlv(socket_handle, 0x9, 2, 0, iovec);
freeIobuf(iobuf);
freeIobuf(data_buf);
return ret;
}