diff --git a/include/netdb.h b/include/netdb.h new file mode 100644 index 0000000..1165dab --- /dev/null +++ b/include/netdb.h @@ -0,0 +1,129 @@ +#pragma once +#include +#include + +extern int h_errno; + +struct hostent +{ + char *h_name; + char **h_aliases; + int h_addrtype; + int h_length; + char **h_addr_list; +#define h_addr h_addr_list[0] +}; + +struct servent +{ + char *s_name; + char **s_aliases; + int s_port; + char *s_proto; +}; + +struct addrinfo +{ + int ai_flags; + int ai_family; + int ai_socktype; + int ai_protocol; + socklen_t ai_addrlen; + char *ai_canonname; + struct sockaddr *ai_addr; + struct addrinfo *ai_next; +}; + +#define NETDB_INTERNAL -1 +#define NETDB_SUCCESS 0 +#define HOST_NOT_FOUND 1 +#define TRY_AGAIN 2 +#define NO_RECOVERY 3 +#define NO_DATA 4 +#define NO_ADDRESS NO_DATA + +#define EAI_ADDRFAMILY 1 +#define EAI_AGAIN 2 +#define EAI_BADFLAGS 3 +#define EAI_FAIL 4 +#define EAI_FAMILY 5 +#define EAI_MEMORY 6 +#define EAI_NODATA 7 +#define EAI_NONAME 8 +#define EAI_SERVICE 9 +#define EAI_SOCKTYPE 10 +#define EAI_SYSTEM 11 +#define EAI_BADHINTS 12 +#define EAI_PROTOCOL 13 +#define EAI_OVERFLOW 14 +#define EAI_MAX 15 + +#define NI_MAXHOST 1025 +#define NI_MAXSERV 32 + +// nsysnet only implements NI_NOFQDN, NI_NUMERICHOST and NI_NUMERICSERV +#define NI_NOFQDN 0x0001 +#define NI_NUMERICHOST 0x0002 +#define NI_NAMEREQD 0x0004 +#define NI_NUMERICSERV 0x0008 +#define NI_DGRAM 0x0010 +#define NI_NUMERICSCOPE 0x0020 + +// nsysnet only implements AI_PASSIVE, AI_CANONNAME and AI_NUMERICHOST +#define AI_PASSIVE 0x0001 +#define AI_CANONNAME 0x0002 +#define AI_NUMERICHOST 0x0004 +#define AI_V4MAPPED 0x0008 +#define AI_ALL 0x0010 +#define AI_ADDRCONFIG 0x0020 + +#ifdef __cplusplus +extern "C" { +#endif + +struct hostent * +gethostbyname(const char *name); + +struct hostent * +gethostbyaddr(const void *addr, + socklen_t len, + int type); + +struct hostent * +gethostent(void); + +struct servent * +getservbyname(const char *name, + const char *proto); + +struct servent * +getservbyport(int port, + const char *proto); + +struct servent * +getservent(void); + +int +getaddrinfo(const char *node, + const char *service, + const struct addrinfo *hints, + struct addrinfo **res); + +void +freeaddrinfo(struct addrinfo *res); + +int +getnameinfo(const struct sockaddr *addr, + socklen_t addrlen, + char *host, + socklen_t hostlen, + char *serv, + socklen_t servlen, + int flags); + +const char * +gai_strerror(int ecode); + +#ifdef __cplusplus +} +#endif diff --git a/include/nsysnet/_netdb.h b/include/nsysnet/_netdb.h new file mode 100644 index 0000000..d0f406f --- /dev/null +++ b/include/nsysnet/_netdb.h @@ -0,0 +1,57 @@ +#pragma once +#include +#include + +/** + * \defgroup nsysnet_netdb Netdb + * \ingroup nsysnet + * @{ + */ +#ifdef __cplusplus +extern "C" { +#endif + +struct hostent * +RPLWRAP(gethostbyaddr)(const void *addr, + size_t len, + int type); + +struct hostent * +RPLWRAP(gethostbyname)(const char *name); + +int +RPLWRAP(getaddrinfo)(const char *node, + const char *service, + const struct addrinfo *hints, + struct addrinfo **res); + +void +RPLWRAP(freeaddrinfo)(struct addrinfo *res); + +int +RPLWRAP(getnameinfo)(const struct sockaddr *addr, + socklen_t addrlen, + char *host, + socklen_t hostlen, + char *serv, + socklen_t servlen, + int flags); + +void +RPLWRAP(clear_resolver_cache)(void); + +int +RPLWRAP(set_resolver_allocator)(void* (*alloc)(uint32_t), + void (*free)(void*)); + +int * +RPLWRAP(get_h_errno)(void); + +const char * +RPLWRAP(gai_strerror)(int ecode); + +#ifdef __cplusplus +} +#endif + +/** @} */ diff --git a/include/sys/filio.h b/include/sys/filio.h new file mode 100644 index 0000000..c2e486d --- /dev/null +++ b/include/sys/filio.h @@ -0,0 +1,21 @@ +#pragma once + +#include + +/* Generic file-descriptor ioctl's. */ +#define FIOCLEX _IO('f', 1) /* set close on exec on fd */ +#define FIONCLEX _IO('f', 2) /* remove close on exec */ +#define FIONREAD _IOR('f', 127, int) /* get # bytes to read */ +#define FIONWRITE _IOR('f', 119, int) /* get # bytes (yet) to write */ +#define FIONBIO _IOW('f', 126, int) /* set/clear non-blocking i/o */ +#define FIOASYNC _IOW('f', 125, int) /* set/clear async i/o */ +#define FIOSETOWN _IOW('f', 124, int) /* set owner */ +#define FIOGETOWN _IOR('f', 123, int) /* get owner */ +#define FIODTYPE _IOR('f', 122, int) /* get d_flags type part */ +#define FIOGETLBA _IOR('f', 121, int) /* get start blk # */ +struct fiodgname_arg { + int len; + void *buf; +}; +#define FIODGNAME _IOW('f', 120, struct fiodgname_arg) /* get dev. name */ +#define FIONSPACE _IOR('f', 118, int) /* get space in send queue */ diff --git a/include/sys/ioccom.h b/include/sys/ioccom.h new file mode 100644 index 0000000..c47fd89 --- /dev/null +++ b/include/sys/ioccom.h @@ -0,0 +1,40 @@ +#pragma once + +/* + * Ioctl's have the command encoded in the lower word, and the size of + * any in or out parameters in the upper word. The high 3 bits of the + * upper word are used to encode the in/out status of the parameter. + */ +#define IOCPARM_SHIFT 13 /* number of bits for ioctl size */ +#define IOCPARM_MASK ((1 << IOCPARM_SHIFT) - 1) /* parameter length mask */ +#define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK) +#define IOCBASECMD(x) ((x) & ~(IOCPARM_MASK << 16)) +#define IOCGROUP(x) (((x) >> 8) & 0xff) + +#define IOCPARM_MAX (1 << IOCPARM_SHIFT) /* max size of ioctl */ +#define IOC_VOID 0x20000000 /* no parameters */ +#define IOC_OUT 0x40000000 /* copy out parameters */ +#define IOC_IN 0x80000000 /* copy in parameters */ +#define IOC_INOUT (IOC_IN|IOC_OUT) +#define IOC_DIRMASK (IOC_VOID|IOC_OUT|IOC_IN) + +#define _IOC(inout,group,num,len) ((int) \ + ((inout) | (((len) & IOCPARM_MASK) << 16) | ((group) << 8) | (num))) +#define _IO(g,n) _IOC(IOC_VOID, (g), (n), 0) +#define _IOWINT(g,n) _IOC(IOC_VOID, (g), (n), sizeof(int)) +#define _IOR(g,n,t) _IOC(IOC_OUT, (g), (n), sizeof(t)) +#define _IOW(g,n,t) _IOC(IOC_IN, (g), (n), sizeof(t)) +/* this should be _IORW, but stdio got there first */ +#define _IOWR(g,n,t) _IOC(IOC_INOUT, (g), (n), sizeof(t)) + +#ifdef __cplusplus +extern "C" { +#endif + +int ioctl(int fd, + int request, + ...); + +#ifdef __cplusplus +} +#endif diff --git a/include/sys/ioctl.h b/include/sys/ioctl.h new file mode 100644 index 0000000..998b5d0 --- /dev/null +++ b/include/sys/ioctl.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +#include diff --git a/include/sys/socket.h b/include/sys/socket.h index 95fbab9..b5f40b6 100644 --- a/include/sys/socket.h +++ b/include/sys/socket.h @@ -26,6 +26,7 @@ * SOL_SOCKET options */ #define SO_REUSEADDR 0x0004 // reuse address +#define SO_KEEPALIVE 0x0008 // keep connections alive #define SO_BROADCAST 0x0020 // broadcast #define SO_LINGER 0x0080 // linger (no effect?) #define SO_OOBINLINE 0x0100 // out-of-band data inline (no effect?) @@ -37,6 +38,8 @@ #define SO_RCVLOWAT 0x1004 // receive low-water mark #define SO_TYPE 0x1008 // get socket type #define SO_ERROR 0x1009 // get socket error +#define SO_RXDATA 0x1011 // get count of bytes in sb_rcv +#define SO_TXDATA 0x1012 // get count of bytes in sb_snd #define SO_NBIO 0x1014 // set socket to NON-blocking mode #define SO_BIO 0x1015 // set socket to blocking mode #define SO_NONBLOCK 0x1016 // set/get blocking mode via optval param diff --git a/libraries/wutsocket/addrinfo.c b/libraries/wutsocket/addrinfo.c new file mode 100644 index 0000000..a866f90 --- /dev/null +++ b/libraries/wutsocket/addrinfo.c @@ -0,0 +1,53 @@ +#include "wut_socket.h" +#include +#include + +int +getaddrinfo(const char *node, + const char *service, + const struct addrinfo *hints, + struct addrinfo **res) +{ + int rc; + + if (!node && !service) { + return EAI_NONAME; + } + + if (!res) { + errno = EINVAL; + return EAI_SYSTEM; + } + + rc = RPLWRAP(getaddrinfo)(node, service, hints, res); + + return rc; +} + +void +freeaddrinfo(struct addrinfo *res) +{ + RPLWRAP(freeaddrinfo)(res); +} + +int +getnameinfo(const struct sockaddr *addr, + socklen_t addrlen, + char *host, + socklen_t hostlen, + char *serv, + socklen_t servlen, + int flags) +{ + int rc; + + rc = RPLWRAP(getnameinfo)(addr, addrlen, host, hostlen, serv, servlen, flags); + + return rc; +} + +const char * +gai_strerror(int ecode) +{ + return RPLWRAP(gai_strerror)(ecode); +} diff --git a/libraries/wutsocket/host.c b/libraries/wutsocket/host.c new file mode 100644 index 0000000..8342ebb --- /dev/null +++ b/libraries/wutsocket/host.c @@ -0,0 +1,40 @@ +#include "wut_socket.h" +#include +#include + +struct hostent * +gethostbyaddr(const void *addr, + socklen_t len, + int type) +{ + if (!addr || !len) { + h_errno = HOST_NOT_FOUND; + return NULL; + } + + if (type != AF_INET) { + h_errno = HOST_NOT_FOUND; + return NULL; + } + + struct hostent *ent = RPLWRAP(gethostbyaddr)(addr, len, type); + + h_errno = *RPLWRAP(get_h_errno)(); + + return ent; +} + +struct hostent * +gethostbyname(const char *name) +{ + if (!name) { + h_errno = HOST_NOT_FOUND; + return NULL; + } + + struct hostent *ent = RPLWRAP(gethostbyname)(name); + + h_errno = *RPLWRAP(get_h_errno)(); + + return ent; +} diff --git a/libraries/wutsocket/ioctl.c b/libraries/wutsocket/ioctl.c new file mode 100644 index 0000000..0feb08d --- /dev/null +++ b/libraries/wutsocket/ioctl.c @@ -0,0 +1,60 @@ +#include "wut_socket.h" +#include + +int +ioctl(int fd, + int request, + ...) +{ + void *data; + va_list args; + int sockfd; + int rc; + + va_start(args, request); + data = (request & IOC_INOUT) ? va_arg(args, void *) : NULL; + va_end(args); + + if(data == NULL && (request & IOC_INOUT) && IOCPARM_LEN(request) != 0) { + errno = EFAULT; + return -1; + } + + sockfd = __wut_get_nsysnet_fd(fd); + if (sockfd == -1) { + return -1; + } + + switch(request) { + case FIONBIO: { + int flags = fcntl(fd, F_GETFL, 0); + if(flags == -1) { + return -1; + } + flags = *(int *)data != 0 ? (flags | O_NONBLOCK) : (flags & ~O_NONBLOCK); + return fcntl(fd, F_SETFL, flags); + } + case FIONREAD: { + socklen_t optlen = sizeof(int32_t); + rc = RPLWRAP(getsockopt)(sockfd, + SOL_SOCKET, + SO_RXDATA, + data, + &optlen); + return __wut_get_nsysnet_result(NULL, rc); + } + case FIONWRITE: { + socklen_t optlen = sizeof(int32_t); + rc = RPLWRAP(getsockopt)(sockfd, + SOL_SOCKET, + SO_TXDATA, + data, + &optlen); + return __wut_get_nsysnet_result(NULL, rc); + } + default: + break; + } + + return -1; +} diff --git a/libraries/wutsocket/stubs.c b/libraries/wutsocket/stubs.c new file mode 100644 index 0000000..e9e0ec9 --- /dev/null +++ b/libraries/wutsocket/stubs.c @@ -0,0 +1,36 @@ +#include "wut_socket.h" +#include + +struct servent * +getservbyname(const char *name, + const char *proto) +{ + h_errno = NO_RECOVERY; + errno = ENOSYS; + return NULL; +} + +struct servent * +getservbyport(int port, + const char *proto) +{ + h_errno = NO_RECOVERY; + errno = ENOSYS; + return NULL; +} + +struct servent * +getservent(void) +{ + h_errno = NO_RECOVERY; + errno = ENOSYS; + return NULL; +} + +struct hostent * +gethostent(void) +{ + h_errno = NO_RECOVERY; + errno = ENOSYS; + return NULL; +} diff --git a/libraries/wutsocket/wut_socket_common.c b/libraries/wutsocket/wut_socket_common.c index efc2352..b174499 100644 --- a/libraries/wutsocket/wut_socket_common.c +++ b/libraries/wutsocket/wut_socket_common.c @@ -2,6 +2,8 @@ #define NSYSNET_UNKNOWN_ERROR_OFFSET 10000 +int h_errno; + static BOOL __wut_socket_initialised = FALSE;