+#include <unistd.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <errno.h>
Handle SOCU_handle = 0;
static int SOCU_errno = 0;
+#define NET_UNKNOWN_ERROR_OFFSET -10000//This is from libogc network_wii.c.
+
+static u8 _net_error_code_map[] = { //This is based on the array from libogc network_wii.c.
+ 0, // 0
+ E2BIG,
+ EACCES,
+ EADDRINUSE,
+ EADDRNOTAVAIL,
+ EAFNOSUPPORT, // 5
+ EAGAIN,
+ EALREADY,
+ EBADF,
+ EBADMSG,
+ EBUSY, // 10
+ ECANCELED,
+ ECHILD,
+ ECONNABORTED,
+ ECONNREFUSED,
+ ECONNRESET, // 15
+ EDEADLK,
+ EDESTADDRREQ,
+ EDOM,
+ EDQUOT,
+ EEXIST, // 20
+ EFAULT,
+ EFBIG,
+ EHOSTUNREACH,
+ EIDRM,
+ EILSEQ, // 25
+ EINPROGRESS,
+ EINTR,
+ EINVAL,
+ EIO,
+ EISCONN, // 30
+ EISDIR,
+ ELOOP,
+ EMFILE,
+ EMLINK,
+ EMSGSIZE, // 35
+ EMULTIHOP,
+ ENAMETOOLONG,
+ ENETDOWN,
+ ENETRESET,
+ ENETUNREACH, // 40
+ ENFILE,
+ ENOBUFS,
+ ENODATA,
+ ENODEV,
+ ENOENT, // 45
+ ENOEXEC,
+ ENOLCK,
+ ENOLINK,
+ ENOMEM,
+ ENOMSG, // 50
+ ENOPROTOOPT,
+ ENOSPC,
+ ENOSR,
+ ENOSTR,
+ ENOSYS, // 55
+ ENOTCONN,
+ ENOTDIR,
+ ENOTEMPTY,
+ ENOTSOCK,
+ ENOTSUP, // 60
+ ENOTTY,
+ ENXIO,
+ EOPNOTSUPP,
+ EOVERFLOW,
+ EPERM, // 65
+ EPIPE,
+ EPROTO,
+ EPROTONOSUPPORT,
+ EPROTOTYPE,
+ ERANGE, // 70
+ EROFS,
+ ESPIPE,
+ ESRCH,
+ ESTALE,
+ ETIME, // 75
+ ETIMEDOUT,
+};
+
+static s32 _net_convert_error(s32 sock_retval)//This is based on the function from libogc network_wii.c.
+{
+ if (sock_retval >= 0) return sock_retval;
+ if (sock_retval < -sizeof(_net_error_code_map)
+ || !_net_error_code_map[-sock_retval])
+ return NET_UNKNOWN_ERROR_OFFSET + sock_retval;
+ return -_net_error_code_map[-sock_retval];
+}
+
Result socu_cmd1(Handle memhandle, u32 memsize)
{
Result ret=0;
SOCU_errno = ret;
if(ret!=0)return -1;
- return (int)cmdbuf[2];
+ return _net_convert_error(cmdbuf[2]);
}
int closesocket(int sockfd)
if((ret = svc_sendSyncRequest(SOCU_handle))!=0)return ret;
ret = (int)cmdbuf[1];
- if(ret==0)ret = (int)cmdbuf[2];
+ if(ret==0)ret =_net_convert_error(cmdbuf[2]);
SOCU_errno = ret;
if(ret!=0)return -1;
if((ret = svc_sendSyncRequest(SOCU_handle))!=0)return ret;
ret = (int)cmdbuf[1];
- if(ret==0)ret = (int)cmdbuf[2];
+ if(ret==0)ret = _net_convert_error(cmdbuf[2]);
SOCU_errno = ret;
if(ret!=0)return -1;
if((ret = svc_sendSyncRequest(SOCU_handle))!=0)return ret;
ret = (int)cmdbuf[1];
- if(ret==0)ret = (int)cmdbuf[2];
+ if(ret==0)ret = _net_convert_error(cmdbuf[2]);
SOCU_errno = ret;
if(ret!=0)return -1;
cmdbuf[0x104>>2] = saved_threadstorage[1];
ret = (int)cmdbuf[1];
- if(ret==0)ret = (int)cmdbuf[2];
+ if(ret==0)ret = _net_convert_error(cmdbuf[2]);
if(ret<0)SOCU_errno = ret;
if(ret>=0 && addr!=NULL)
if((ret = svc_sendSyncRequest(SOCU_handle))!=0)return ret;
ret = (int)cmdbuf[1];
- if(ret==0)ret = (int)cmdbuf[2];
+ if(ret==0)ret = _net_convert_error(cmdbuf[2]);
SOCU_errno = ret;
if(ret<0)return -1;
if((ret = svc_sendSyncRequest(SOCU_handle))!=0)return ret;
ret = (int)cmdbuf[1];
- if(ret==0)ret = (int)cmdbuf[2];
+ if(ret==0)ret = _net_convert_error(cmdbuf[2]);
SOCU_errno = ret;
if(ret<0)return -1;
cmdbuf[0x104>>2] = saved_threadstorage[1];
ret = (int)cmdbuf[1];
- if(ret==0)ret = (int)cmdbuf[2];
+ if(ret==0)ret = _net_convert_error(cmdbuf[2]);
if(ret<0)SOCU_errno = ret;
if(ret<0)return -1;
cmdbuf[0x10c>>2] = saved_threadstorage[3];
ret = (int)cmdbuf[1];
- if(ret==0)ret = (int)cmdbuf[2];
+ if(ret==0)ret = _net_convert_error(cmdbuf[2]);
if(ret<0)SOCU_errno = ret;
if(ret<0)return -1;
if((ret = svc_sendSyncRequest(SOCU_handle))!=0)return ret;
ret = (int)cmdbuf[1];
- if(ret==0)ret = (int)cmdbuf[2];
+ if(ret==0)ret = _net_convert_error(cmdbuf[2]);
if(ret<0)SOCU_errno = ret;
if(ret<0)return -1;
if((ret = svc_sendSyncRequest(SOCU_handle))!=0)return ret;
ret = (int)cmdbuf[1];
- if(ret==0)ret = (int)cmdbuf[2];
+ if(ret==0)ret = _net_convert_error(cmdbuf[2]);
if(ret<0)SOCU_errno = ret;
if(ret<0)return -1;
return sendto(sockfd, buf, len, flags, NULL, 0);
}
+int getsockopt(int sockfd, int level, int option_name, void * data, int * data_len)
+{
+ int ret=0;
+ u32 *cmdbuf = getThreadCommandBuffer();
+ u32 saved_threadstorage[2];
+
+ cmdbuf[0] = 0x00110102;
+ cmdbuf[1] = (u32)sockfd;
+ cmdbuf[2] = (u32)level;
+ cmdbuf[3] = (u32)option_name;
+ cmdbuf[4] = (u32)*data_len;
+ cmdbuf[5] = 0x20;
+
+ saved_threadstorage[0] = cmdbuf[0x100>>2];
+ saved_threadstorage[1] = cmdbuf[0x104>>2];
+
+ cmdbuf[0x100>>2] = ((*data_len)<<14) | 2;
+ cmdbuf[0x104>>2] = (u32)data;
+
+ if((ret = svc_sendSyncRequest(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)*data_len = cmdbuf[3];
+
+ if(ret<0)return -1;
+ return ret;
+}
+
+int setsockopt(int sockfd, int level, int option_name, const void * data, int data_len)
+{
+ int ret=0;
+ u32 *cmdbuf = getThreadCommandBuffer();
+
+ cmdbuf[0] = 0x00120104;
+ cmdbuf[1] = (u32)sockfd;
+ cmdbuf[2] = (u32)level;
+ cmdbuf[3] = (u32)option_name;
+ cmdbuf[4] = (u32)data_len;
+ cmdbuf[5] = 0x20;
+ cmdbuf[7] = (data_len<<14) | 0x2402;
+ cmdbuf[8] = (u32)data;
+
+ if((ret = svc_sendSyncRequest(SOCU_handle))!=0)return ret;
+
+ ret = (int)cmdbuf[1];
+ if(ret==0)ret = _net_convert_error(cmdbuf[2]);
+ if(ret<0)SOCU_errno = ret;
+
+ if(ret<0)return -1;
+ return ret;
+}
+
+int fcntl(int sockfd, int cmd, ...)
+{
+ int ret=0;
+ int arg=0;
+ u32 *cmdbuf = getThreadCommandBuffer();
+
+ va_list args;
+ va_start(args, cmd);
+
+ if(cmd!=F_GETFL && cmd!=F_SETFL)
+ {
+ SOCU_errno = -EINVAL;
+ return -1;
+ }
+
+ if(cmd==F_SETFL)
+ {
+ arg = va_arg(args, int);
+
+ if(arg && arg!=O_NONBLOCK)
+ {
+ SOCU_errno = -EINVAL;
+ return -1;
+ }
+
+ if(arg==O_NONBLOCK)arg = 0x4;
+ }
+
+ cmdbuf[0] = 0x001300C2;
+ cmdbuf[1] = (u32)sockfd;
+ cmdbuf[2] = (u32)cmd;
+ cmdbuf[3] = (u32)arg;
+ cmdbuf[4] = 0x20;
+
+ if((ret = svc_sendSyncRequest(SOCU_handle))!=0)return ret;
+
+ ret = (int)cmdbuf[1];
+ if(ret==0)ret = _net_convert_error(cmdbuf[2]);
+ if(ret<0)SOCU_errno = ret;
+
+ if(ret<0)return -1;
+ return ret;
+}
+
+int sockatmark(int sockfd)
+{
+ int ret=0;
+ u32 *cmdbuf = getThreadCommandBuffer();
+
+ cmdbuf[0] = 0x00150042;
+ cmdbuf[1] = (u32)sockfd;
+ cmdbuf[2] = 0x20;
+
+ if((ret = svc_sendSyncRequest(SOCU_handle))!=0)return ret;
+
+ ret = (int)cmdbuf[1];
+ if(ret==0)ret = _net_convert_error(cmdbuf[2]);
+ if(ret<0)SOCU_errno = ret;
+
+ if(ret<0)return -1;
+ return ret;
+}
+
+long gethostid()
+{
+ int ret=0;
+ u32 *cmdbuf = getThreadCommandBuffer();
+
+ cmdbuf[0] = 0x00160000;
+
+ if((ret = svc_sendSyncRequest(SOCU_handle))!=0)return ret;
+
+ ret = (int)cmdbuf[1];
+ if(ret==0)ret = cmdbuf[2];
+
+ return ret;
+}
+
+int getsockname(int sockfd, struct sockaddr *addr, int * addr_len)
+{
+ 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 = svc_sendSyncRequest(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)
+ {
+ addr->sa_family = tmpaddr[1];
+ if(*addr_len > tmpaddr[0])*addr_len = tmpaddr[0];
+ memcpy(addr->sa_data, &tmpaddr[2], *addr_len - 2);
+ }
+
+ if(ret<0)return -1;
+ return ret;
+}
+
+int getpeername(int sockfd, struct sockaddr *addr, int * addr_len)
+{
+ int ret=0;
+ u32 *cmdbuf = getThreadCommandBuffer();
+ u32 saved_threadstorage[2];
+ u8 tmpaddr[0x1c];
+
+ cmdbuf[0] = 0x00180082;
+ 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 = svc_sendSyncRequest(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)
+ {
+ addr->sa_family = tmpaddr[1];
+ if(*addr_len > tmpaddr[0])*addr_len = tmpaddr[0];
+ memcpy(addr->sa_data, &tmpaddr[2], *addr_len - 2);
+ }
+
+ if(ret<0)return -1;
+ return ret;
+}
+