diff --git a/.gitignore b/.gitignore index 9ed661cf..afacb181 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ *.o *.so *.so.* +*.a *.obj *.lib *.dll* diff --git a/makefile b/makefile index 63d9985c..94d34e8c 100755 --- a/makefile +++ b/makefile @@ -10,11 +10,11 @@ # print print the build settings PLAT?= linux -PLATS= macosx linux win32 win64 mingw freebsd solaris +PLATS= macosx linux win32 win64 mingw freebsd solaris psp all: $(PLAT) -$(PLATS) none install install-unix local clean: +$(PLATS) none install install-unix install-static local clean: $(MAKE) -C src $@ print: diff --git a/src/config.h b/src/config.h new file mode 100644 index 00000000..147bc87d --- /dev/null +++ b/src/config.h @@ -0,0 +1,13 @@ +/* + * This file is needed to compile PSP stubs + */ + +#define STDC_HEADERS +#define HAVE_STRING_H +#define HAVE_MEMORY_H +#define HAVE_STDLIB_H +//#define ENABLE_PTHREAD +//#define ENABLE_NLS +#define HAVE_MEMCPY + +#include "netdb-compat.h" \ No newline at end of file diff --git a/src/getaddrinfo.c b/src/getaddrinfo.c new file mode 100644 index 00000000..b9ccf2ac --- /dev/null +++ b/src/getaddrinfo.c @@ -0,0 +1,593 @@ +/* + * Copyright (c) 2001, 02 Motoyuki Kasahara + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * This program provides getaddrinfo() and getnameinfo() described in + * RFC2133, 2553 and 3493. These functions are mainly used for IPv6 + * application to resolve hostname or address. + * + * This program is designed to be working on traditional IPv4 systems + * which don't have those functions. Therefore, this implementation + * supports IPv4 only. + * + * This program is useful for application which should support both IPv6 + * and traditional IPv4 systems. Use genuine getaddrinfo() and getnameinfo() + * provided by system if the system supports IPv6. Otherwise, use this + * implementation. + * + * This program is intended to be used in combination with GNU Autoconf. + * + * This program also provides freeaddrinfo() and gai_strerror(). + * + * To use this program in your application, insert the following lines to + * C source files after including `sys/types.h', `sys/socket.h' and + * `netdb.h'. `getaddrinfo.h' defines `struct addrinfo' and AI_, NI_, + * EAI_ macros. + * + * #ifndef HAVE_GETADDRINFO + * #include "getaddrinfo.h" + * #endif + * + * Restriction: + * getaddrinfo() and getnameinfo() of this program are NOT thread + * safe, unless the cpp macro ENABLE_PTHREAD is defined. + */ + +/* + * Add the following code to your configure.ac (or configure.in). + * AC_C_CONST + * AC_HEADER_STDC + * AC_CHECK_HEADERS(string.h memory.h stdlib.h) + * AC_CHECK_FUNCS(memcpy) + * AC_REPLACE_FUNCS(memset) + * AC_TYPE_SOCKLEN_T + * AC_TYPE_IN_PORT_T + * AC_DECL_H_ERRNO + * + * AC_CHECK_FUNCS(getaddrinfo getnameinfo) + * if test "$ac_cv_func_getaddrinfo$ac_cv_func_getnameinfo" != yesyes ; then + * LIBOBJS="$LIBOBJS getaddrinfo.$ac_objext" + * fi + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include + +#if defined(STDC_HEADERS) || defined(HAVE_STRING_H) +#include +#if !defined(STDC_HEADERS) && defined(HAVE_MEMORY_H) +#include +#endif /* not STDC_HEADERS and HAVE_MEMORY_H */ +#else /* not STDC_HEADERS and not HAVE_STRING_H */ +#include +#endif /* not STDC_HEADERS and not HAVE_STRING_H */ + +#ifdef HAVE_STDLIB_H +#include +#endif + +#ifdef ENABLE_PTHREAD +#include +#endif + +#ifdef ENABLE_NLS +#include +#endif + +#ifndef HAVE_MEMCPY +#define memcpy(d, s, n) bcopy((s), (d), (n)) +#ifdef __STDC__ +void *memchr(const void *, int, size_t); +int memcmp(const void *, const void *, size_t); +void *memmove(void *, const void *, size_t); +void *memset(void *, int, size_t); +#else /* not __STDC__ */ +char *memchr(); +int memcmp(); +char *memmove(); +char *memset(); +#endif /* not __STDC__ */ +#endif /* not HAVE_MEMCPY */ + +#ifndef H_ERRNO_DECLARED +extern int h_errno; +#endif + +#include "getaddrinfo.h" + +#ifdef ENABLE_NLS +#define _(string) gettext(string) +#ifdef gettext_noop +#define N_(string) gettext_noop(string) +#else +#define N_(string) (string) +#endif +#else +#define gettext(string) (string) +#define _(string) (string) +#define N_(string) (string) +#endif + +/* + * Error messages for gai_strerror(). + */ +static char *eai_errlist[] = { + N_("Success"), + + /* EAI_ADDRFAMILY */ + N_("Address family for hostname not supported"), + + /* EAI_AGAIN */ + N_("Temporary failure in name resolution"), + + /* EAI_BADFLAGS */ + N_("Invalid value for ai_flags"), + + /* EAI_FAIL */ + N_("Non-recoverable failure in name resolution"), + + /* EAI_FAMILY */ + N_("ai_family not supported"), + + /* EAI_MEMORY */ + N_("Memory allocation failure"), + + /* EAI_NONAME */ + N_("hostname nor servname provided, or not known"), + + /* EAI_OVERFLOW */ + N_("An argument buffer overflowed"), + + /* EAI_SERVICE */ + N_("servname not supported for ai_socktype"), + + /* EAI_SOCKTYPE */ + N_("ai_socktype not supported"), + + /* EAI_SYSTEM */ + N_("System error returned in errno") +}; + +/* + * Default hints for getaddrinfo(). + */ +static struct addrinfo default_hints = { + 0, PF_UNSPEC, 0, 0, 0, NULL, NULL, NULL +}; + +/* + * Mutex. + */ +#ifdef ENABLE_PTHREAD +static pthread_mutex_t gai_mutex = PTHREAD_MUTEX_INITIALIZER; +#endif + +/* + * Declaration of static functions. + */ +#ifdef __STDC__ +static int is_integer(const char *); +static int is_address(const char *); +static int itoa_length(int); +#else +static int is_integer(); +static int is_address(); +static int itoa_length(); +#endif + +/* + * gai_strerror(). + */ +const char * +gai_strerror(ecode) + int ecode; +{ + if (ecode < 0 || ecode > EAI_SYSTEM) + return _("Unknown error"); + + return gettext(eai_errlist[ecode]); +} + +/* + * freeaddrinfo(). + */ +void +freeaddrinfo(ai) + struct addrinfo *ai; +{ + struct addrinfo *next_ai; + + while (ai != NULL) { + if (ai->ai_canonname != NULL) + free(ai->ai_canonname); + if (ai->ai_addr != NULL) + free(ai->ai_addr); + next_ai = ai->ai_next; + free(ai); + ai = next_ai; + } +} + +/* + * Return 1 if the string `s' represents an integer. + */ +static int +is_integer(s) + const char *s; +{ + if (*s == '-' || *s == '+') + s++; + if (*s < '0' || '9' < *s) + return 0; + + s++; + while ('0' <= *s && *s <= '9') + s++; + + return (*s == '\0'); +} + +/* + * Return 1 if the string `s' represents an IPv4 address. + * Unlike inet_addr(), it doesn't permit malformed nortation such + * as "192.168". + */ +static int +is_address(s) + const char *s; +{ + const static char delimiters[] = {'.', '.', '.', '\0'}; + int i, j; + int octet; + + for (i = 0; i < 4; i++) { + if (*s == '0' && *(s + 1) != delimiters[i]) + return 0; + for (j = 0, octet = 0; '0' <= *s && *s <= '9' && j < 3; s++, j++) + octet = octet * 10 + (*s - '0'); + if (j == 0 || octet > 255 || *s != delimiters[i]) + return 0; + s++; + } + + return 1; +} + +/* + * Calcurate length of the string `s', where `s' is set by + * sprintf(s, "%d", n). + */ +static int +itoa_length(n) + int n; +{ + int result = 1; + + if (n < 0) { + n = -n; + result++; + } + + while (n >= 10) { + result++; + n /= 10; + } + + return result; +} + +/* + * getaddrinfo(). + */ +int +getaddrinfo(nodename, servname, hints, res) + const char *nodename; + const char *servname; + const struct addrinfo *hints; + struct addrinfo **res; +{ + struct addrinfo *head_res = NULL; + struct addrinfo *tail_res = NULL; + struct addrinfo *new_res; + struct sockaddr_in *sa_in; + struct in_addr **addr_list; + struct in_addr *addr_list_buf[2]; + struct in_addr addr_buf; + struct in_addr **ap; + struct servent *servent; + struct hostent *hostent; + const char *canonname = NULL; + in_port_t port; + int saved_h_errno; + int result = 0; + +#ifdef ENABLE_PTHREAD + pthread_mutex_lock(&gai_mutex); +#endif + + saved_h_errno = h_errno; + + if (nodename == NULL && servname == NULL) { + result = EAI_NONAME; + goto end; + } + + if (hints != NULL) { + if (hints->ai_family != PF_INET && hints->ai_family != PF_UNSPEC) { + result = EAI_FAMILY; + goto end; + } + if (hints->ai_socktype != SOCK_DGRAM + && hints->ai_socktype != SOCK_STREAM + && hints->ai_socktype != 0) { + result = EAI_SOCKTYPE; + goto end; + } + } else { + hints = &default_hints; + } + + if (servname != NULL) { + if (is_integer(servname)) + port = htons(atoi(servname)); + else { + if (hints->ai_flags & AI_NUMERICSERV) { + result = EAI_NONAME; + goto end; + } + + if (hints->ai_socktype == SOCK_DGRAM) + servent = getservbyname(servname, "udp"); + else if (hints->ai_socktype == SOCK_STREAM) + servent = getservbyname(servname, "tcp"); + else if (hints->ai_socktype == 0) + servent = getservbyname(servname, "tcp"); + else { + result = EAI_SOCKTYPE; + goto end; + } + + if (servent == NULL) { + result = EAI_SERVICE; + goto end; + } + port = servent->s_port; + } + } else { + port = htons(0); + } + + if (nodename != NULL) { + if (is_address(nodename)) { + addr_buf.s_addr = inet_addr(nodename); + addr_list_buf[0] = &addr_buf; + addr_list_buf[1] = NULL; + addr_list = addr_list_buf; + + if (hints->ai_flags & AI_CANONNAME + && !(hints->ai_flags & AI_NUMERICHOST)) { + hostent = gethostbyaddr((char *)&addr_buf, + sizeof(struct in_addr), AF_INET); + if (hostent != NULL) + canonname = hostent->h_name; + else + canonname = nodename; + } + } else { + if (hints->ai_flags & AI_NUMERICHOST) { + result = EAI_NONAME; + goto end; + } + + hostent = gethostbyname(nodename); + if (hostent == NULL) { + switch (h_errno) { + case HOST_NOT_FOUND: + case NO_DATA: + result = EAI_NONAME; + goto end; + case TRY_AGAIN: + result = EAI_AGAIN; + goto end; + default: + result = EAI_FAIL; + goto end; + } + } + addr_list = (struct in_addr **)hostent->h_addr_list; + + if (hints->ai_flags & AI_CANONNAME) + canonname = hostent->h_name; + } + } else { + if (hints->ai_flags & AI_PASSIVE) + addr_buf.s_addr = htonl(INADDR_ANY); + else + addr_buf.s_addr = htonl(0x7F000001); + addr_list_buf[0] = &addr_buf; + addr_list_buf[1] = NULL; + addr_list = addr_list_buf; + } + + for (ap = addr_list; *ap != NULL; ap++) { + new_res = (struct addrinfo *)malloc(sizeof(struct addrinfo)); + if (new_res == NULL) { + if (head_res != NULL) + freeaddrinfo(head_res); + result = EAI_MEMORY; + goto end; + } + + new_res->ai_family = PF_INET; + new_res->ai_socktype = hints->ai_socktype; + new_res->ai_protocol = hints->ai_protocol; + new_res->ai_addr = NULL; + new_res->ai_addrlen = sizeof(struct sockaddr_in); + new_res->ai_canonname = NULL; + new_res->ai_next = NULL; + + new_res->ai_addr = (struct sockaddr *) + malloc(sizeof(struct sockaddr_in)); + if (new_res->ai_addr == NULL) { + free(new_res); + if (head_res != NULL) + freeaddrinfo(head_res); + result = EAI_MEMORY; + goto end; + } + + sa_in = (struct sockaddr_in *)new_res->ai_addr; + memset(sa_in, 0, sizeof(struct sockaddr_in)); + sa_in->sin_family = PF_INET; + sa_in->sin_port = port; + memcpy(&sa_in->sin_addr, *ap, sizeof(struct in_addr)); + + if (head_res == NULL) + head_res = new_res; + else + tail_res->ai_next = new_res; + tail_res = new_res; + } + + if (canonname != NULL && head_res != NULL) { + head_res->ai_canonname = (char *)malloc(strlen(canonname) + 1); + if (head_res->ai_canonname != NULL) + strcpy(head_res->ai_canonname, canonname); + } + + *res = head_res; + + end: + h_errno = saved_h_errno; +#ifdef ENABLE_PTHREAD + pthread_mutex_unlock(&gai_mutex); +#endif + return result; +} + +/* + * getnameinfo(). + */ +int +getnameinfo(sa, salen, node, nodelen, serv, servlen, flags) + const struct sockaddr *sa; + socklen_t salen; + char *node; + socklen_t nodelen; + char *serv; + socklen_t servlen; + int flags; +{ + const struct sockaddr_in *sa_in = (const struct sockaddr_in *)sa; + struct hostent *hostent; + struct servent *servent; + char *ntoa_address; + int saved_h_errno; + int result = 0; + +#ifdef ENABLE_PTHREAD + pthread_mutex_lock(&gai_mutex); +#endif + + saved_h_errno = h_errno; + + if (sa_in->sin_family != PF_INET) { + result = EAI_FAMILY; + goto end; + } else if (node == NULL && serv == NULL) { + result = EAI_NONAME; + goto end; + } + + if (serv != NULL && servlen > 0) { + if (flags & NI_NUMERICSERV) + servent = NULL; + else if (flags & NI_DGRAM) + servent = getservbyport(sa_in->sin_port, "udp"); + else + servent = getservbyport(sa_in->sin_port, "tcp"); + + if (servent != NULL) { + if (servlen <= strlen(servent->s_name)) { + result = EAI_OVERFLOW; + goto end; + } + strcpy(serv, servent->s_name); + } else { + if (servlen <= itoa_length(ntohs(sa_in->sin_port))) { + result = EAI_OVERFLOW; + goto end; + } + sprintf(serv, "%d", ntohs(sa_in->sin_port)); + } + } + + if (node != NULL && nodelen > 0) { + if (flags & NI_NUMERICHOST) + hostent = NULL; + else { + hostent = gethostbyaddr((char *)&sa_in->sin_addr, + sizeof(struct in_addr), AF_INET); + } + if (hostent != NULL) { + if (nodelen <= strlen(hostent->h_name)) { + result = EAI_OVERFLOW; + goto end; + } + strcpy(node, hostent->h_name); + } else { + if (flags & NI_NAMEREQD) { + result = EAI_NONAME; + goto end; + } + ntoa_address = inet_ntoa(sa_in->sin_addr); + if (nodelen <= strlen(ntoa_address)) { + result = EAI_OVERFLOW; + goto end; + } + strcpy(node, ntoa_address); + } + + } + + end: + h_errno = saved_h_errno; +#ifdef ENABLE_PTHREAD + pthread_mutex_unlock(&gai_mutex); +#endif + return result; +} + diff --git a/src/getaddrinfo.h b/src/getaddrinfo.h new file mode 100644 index 00000000..0d190a91 --- /dev/null +++ b/src/getaddrinfo.h @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2001, 02 Motoyuki Kasahara + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef GETADDRINFO_H +#define GETADDRINFO_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +/********************************************************************/ +/* + * Undefine all the macros. + * might defines some of them. + */ +#ifdef EAI_ADDRFAMILY +#undef EAI_ADDRFAMILY +#endif +#ifdef EAI_AGAIN +#undef EAI_AGAIN +#endif +#ifdef EAI_BADFLAGS +#undef EAI_BADFLAGS +#endif +#ifdef EAI_FAIL +#undef EAI_FAIL +#endif +#ifdef EAI_FAMILY +#undef EAI_FAMILY +#endif +#ifdef EAI_MEMORY +#undef EAI_MEMORY +#endif +#ifdef EAI_NONAME +#undef EAI_NONAME +#endif +#ifdef EAI_OVERFLOW +#undef EAI_OVERFLOW +#endif +#ifdef EAI_SERVICE +#undef EAI_SERVICE +#endif +#ifdef EAI_SOCKTYPE +#undef EAI_SOCKTYPE +#endif +#ifdef EAI_SYSTEM +#undef EAI_SYSTEM +#endif + +#ifdef AI_PASSIVE +#undef AI_PASSIVE +#endif +#ifdef AI_CANONNAME +#undef AI_CANONNAME +#endif +#ifdef AI_NUMERICHOST +#undef AI_NUMERICHOST +#endif +#ifdef AI_NUMERICSERV +#undef AI_NUMERICSERV +#endif +#ifdef AI_V4MAPPED +#undef AI_V4MAPPED +#endif +#ifdef AI_ALL +#undef AI_ALL +#endif +#ifdef AI_ADDRCONFIG +#undef AI_ADDRCONFIG +#endif +#ifdef AI_DEFAULT +#undef AI_DEFAULT +#endif + +#ifdef NI_NOFQDN +#undef NI_NOFQDN +#endif +#ifdef NI_NUMERICHOST +#undef NI_NUMERICHOST +#endif +#ifdef NI_NAMEREQD +#undef NI_NAMEREQD +#endif +#ifdef NI_NUMERICSERV +#undef NI_NUMERICSERV +#endif +#ifdef NI_NUMERICSCOPE +#undef NI_NUMERICSCOPE +#endif + +#ifdef NI_DGRAM +#undef NI_DGRAM +#endif +#ifdef NI_MAXHOST +#undef NI_MAXHOST +#endif +#ifdef NI_MAXSERV +#undef NI_MAXSERV +#endif + +/* + * Fake struct and function names. + * might declares all or some of them. + */ +#if defined(HAVE_GETADDRINFO) || defined(HAVE_GETNAMEINFO) +#define addrinfo my_addrinfo +#define gai_strerror my_gai_strerror +#define freeaddrinfo my_freeaddrinfo +#define getaddrinfo my_getaddrinfo +#define getnameinfo my_getnameinfo +#endif + +/********************************************************************/ +/* + * Error codes. + */ +#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_NONAME 7 +#define EAI_OVERFLOW 8 +#define EAI_SERVICE 9 +#define EAI_SOCKTYPE 10 +#define EAI_SYSTEM 11 + +/* + * Flags for getaddrinfo(). + */ +#define AI_ADDRCONFIG 0x0001 +#define AI_ALL 0x0002 +#define AI_CANONNAME 0x0004 +#define AI_NUMERICHOST 0x0008 +#define AI_NUMERICSERV 0x0010 +#define AI_PASSIVE 0x0020 +#define AI_V4MAPPED 0x0040 +#define AI_DEFAULT (AI_V4MAPPED | AI_ADDRCONFIG) + +/* + * Flags for getnameinfo(). + */ +#define NI_DGRAM 0x0001 +#define NI_NAMEREQD 0x0002 +#define NI_NOFQDN 0x0004 +#define NI_NUMERICHOST 0x0008 +#define NI_NUMERICSCOPE 0x0010 +#define NI_NUMERICSERV 0x0020 + +/* + * Maximum length of FQDN and servie name for getnameinfo(). + */ +#define NI_MAXHOST 1025 +#define NI_MAXSERV 32 + +/* + * Address families and Protocol families. + */ +#ifndef AF_UNSPEC +#define AF_UNSPEC AF_INET +#endif +#ifndef PF_UNSPEC +#define PF_UNSPEC PF_INET +#endif + +/* + * struct addrinfo. + */ +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; +}; + +/* + * Functions. + */ +#ifdef __STDC__ +const char *gai_strerror(int); +void freeaddrinfo(struct addrinfo *); +int getaddrinfo(const char *, const char *, const struct addrinfo *, + struct addrinfo **); +int getnameinfo(const struct sockaddr *, socklen_t, char *, + socklen_t, char *, socklen_t, int); +#else +const char *gai_strerror(); +void freeaddrinfo(); +int getaddrinfo(); +int getnameinfo(); +#endif + +#endif /* not GETADDRINFO_H */ diff --git a/src/inet.c b/src/inet.c index afef5f45..efcfe3f9 100755 --- a/src/inet.c +++ b/src/inet.c @@ -9,6 +9,13 @@ #include #include +#ifdef PSP +int gethostname (char *__name, size_t __len) { + snprintf(__name, __len, "psp"); + return 0; +} +#endif + /*=========================================================================*\ * Internal function prototypes. \*=========================================================================*/ @@ -348,10 +355,12 @@ static void inet_pushresolved(lua_State *L, struct hostent *hp) \*-------------------------------------------------------------------------*/ const char *inet_trycreate(p_socket ps, int family, int type, int protocol) { const char *err = socket_strerror(socket_create(ps, family, type, protocol)); +#ifdef IPV6_V6ONLY if (err == NULL && family == AF_INET6) { int yes = 1; setsockopt(*ps, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&yes, sizeof(yes)); } +#endif return err; } @@ -369,6 +378,7 @@ const char *inet_trydisconnect(p_socket ps, int family, p_timeout tm) return socket_strerror(socket_connect(ps, (SA *) &sin, sizeof(sin), tm)); } +#ifndef NOIPV6 case AF_INET6: { struct sockaddr_in6 sin6; struct in6_addr addrany = IN6ADDR_ANY_INIT; @@ -378,6 +388,7 @@ const char *inet_trydisconnect(p_socket ps, int family, p_timeout tm) return socket_strerror(socket_connect(ps, (SA *) &sin6, sizeof(sin6), tm)); } +#endif } return NULL; } @@ -436,7 +447,9 @@ const char *inet_tryaccept(p_socket server, int family, p_socket client, socklen_t len; t_sockaddr_storage addr; switch (family) { +#ifndef NOIPV6 case AF_INET6: len = sizeof(struct sockaddr_in6); break; +#endif case AF_INET: len = sizeof(struct sockaddr_in); break; default: len = sizeof(addr); break; } @@ -524,9 +537,11 @@ int inet_pton(int af, const char *src, void *dst) if (af == AF_INET) { struct sockaddr_in *in = (struct sockaddr_in *) res->ai_addr; memcpy(dst, &in->sin_addr, sizeof(in->sin_addr)); +#ifndef NOIPV6 } else if (af == AF_INET6) { struct sockaddr_in6 *in = (struct sockaddr_in6 *) res->ai_addr; memcpy(dst, &in->sin6_addr, sizeof(in->sin6_addr)); +#endif } else { ret = -1; } diff --git a/src/inet.h b/src/inet.h index 5618b61b..037ae748 100644 --- a/src/inet.h +++ b/src/inet.h @@ -18,6 +18,10 @@ #include "socket.h" #include "timeout.h" +#ifdef PSP +#include "getaddrinfo.h" +#endif + #ifdef _WIN32 #define LUASOCKET_INET_ATON #endif diff --git a/src/makefile b/src/makefile index 25b293c7..26c6a354 100755 --- a/src/makefile +++ b/src/makefile @@ -105,6 +105,19 @@ LUAPREFIX_solaris?=/usr/local CDIR_solaris?=lib/lua/$(LUAV) LDIR_solaris?=share/lua/$(LUAV) +# LUAINC_psp: +# LUALIB_psp: +# where lua headers and libraries are found for psp builds +ifeq ($(PLAT),psp) +PSP_PREFIX=$(shell psp-config -P) +endif +LUAINC_psp?=$(PSP_PREFIX)/include +LUAPREFIX_psp?=/psp +CDIR_psp?=lib/lua/$(LUAV) +LDIR_psp?=share/lua/$(LUAV) +LUALIB_psp_base?=$(PSP_PREFIX)/lib +LUALIB_psp=$(LUALIB_psp_base)/liblua.a + # prefix: /usr/local /usr /opt/local /sw # the top of the default install tree prefix?=$(LUAPREFIX_$(PLAT)) @@ -153,7 +166,7 @@ print: #------ # Supported platforms # -PLATS= macosx linux win32 win64 mingw solaris +PLATS= macosx linux win32 win64 mingw freebsd solaris psp #------ # Compiler and linker settings @@ -262,6 +275,26 @@ LDFLAGS_win64= //nologo //link //NOLOGO //DLL //INCREMENTAL:NO \ LD_win64=cl SOCKET_win64=wsocket.obj +#------ +# Compiler and linker settings +# for PSP +ifeq ($(PLAT),psp) +PSPSDK=$(shell psp-config -p) +endif + +SO_psp=a +O_psp=o +A_psp=a +CC_psp=psp-gcc +DEF_psp=-DLUASOCKET_$(DEBUG) -DUNIX_HAS_SUN_LEN +CFLAGS_psp=$(LUAINC:%=-I%) $(PSPSDK:%=-I%)/include $(DEF) -Wall -Wshadow -Wextra \ + -Wimplicit -O2 -ggdb3 -DHAVE_CONFIG_H -DSOCKET_SELECT -DNOIPV6 +LDFLAGS_psp=$(LUALIB) && mv templib.a +LD_psp=psp-ar rcs templib.a +AR_psp=psp-ar rcs +SOCKET_psp=usocket.o + + .SUFFIXES: .obj .c.obj: @@ -279,6 +312,9 @@ MIME_SO=mime-$(MIME_V).$(SO) UNIX_SO=unix.$(SO) SERIAL_SO=serial.$(SO) SOCKET=$(SOCKET_$(PLAT)) +STATIC_LIB=libluasocket.$(A_$(PLAT)) +COMBINED_H=luasocket-combined.h +TARGET_H=luasocket.h #------ # Settings selected for platform @@ -288,9 +324,17 @@ DEF=$(DEF_$(PLAT)) CFLAGS=$(MYCFLAGS) $(CFLAGS_$(PLAT)) LDFLAGS=$(MYLDFLAGS) $(LDFLAGS_$(PLAT)) LD=$(LD_$(PLAT)) +AR=$(AR_$(PLAT)) LUAINC= $(LUAINC_$(PLAT)) LUALIB= $(LUALIB_$(PLAT)) +#------ +# Platform-specific modules +# +PLATFORM_OBJS_psp= \ + netdb-compat.$(O) \ + getaddrinfo.$(O) + #------ # Modules belonging to socket-core # @@ -387,6 +431,9 @@ mingw: solaris: $(MAKE) all-unix PLAT=solaris +psp: + $(MAKE) static PLAT=psp + none: @echo "Please run" @echo " make PLATFORM" @@ -395,7 +442,18 @@ none: all: $(SOCKET_SO) $(MIME_SO) -$(SOCKET_SO): $(SOCKET_OBJS) +static: $(STATIC_LIB) $(COMBINED_H) + +$(COMBINED_H): luasocket.h compat.h mime.h + sed '29,$$d' luasocket.h > $(COMBINED_H) + sed -e '1,2d' -e '$$d' compat.h >> $(COMBINED_H) + sed -n '30,$$p' luasocket.h >> $(COMBINED_H) + sed '11d' mime.h >> $(COMBINED_H) + +$(STATIC_LIB): $(PLATFORM_OBJS_$(PLAT)) $(SOCKET_OBJS) $(MIME_OBJS) $(UNIX_OBJS) $(SERIAL_OBJS) + $(AR) $@ $(PLATFORM_OBJS_$(PLAT)) $(SOCKET_OBJS) $(MIME_OBJS) $(UNIX_OBJS) $(SERIAL_OBJS) + +$(SOCKET_SO): $(PLATFORM_OBJS_$(PLAT)) $(SOCKET_OBJS) $(LD) $(SOCKET_OBJS) $(LDFLAGS)$@ $(MIME_SO): $(MIME_OBJS) @@ -423,12 +481,22 @@ install-unix: install $(INSTALL_EXEC) $(UNIX_SO) $(INSTALL_SOCKET_CDIR)/$(UNIX_SO) $(INSTALL_EXEC) $(SERIAL_SO) $(INSTALL_SOCKET_CDIR)/$(SERIAL_SO) +install-static: + $(INSTALL_DIR) $(INSTALL_TOP_LDIR) + $(INSTALL_DATA) $(TO_TOP_LDIR) $(INSTALL_TOP_LDIR) + $(INSTALL_DIR) $(INSTALL_SOCKET_LDIR) + $(INSTALL_DATA) $(TO_SOCKET_LDIR) $(INSTALL_SOCKET_LDIR) + $(INSTALL_DIR) $(INSTALL_TOP)/lib + $(INSTALL_EXEC) $(STATIC_LIB) $(INSTALL_TOP)/lib + $(INSTALL_DIR) $(INSTALL_TOP)/include + $(INSTALL_DATA) $(COMBINED_H) $(INSTALL_TOP)/include/$(TARGET_H) + local: $(MAKE) install INSTALL_TOP_CDIR=.. INSTALL_TOP_LDIR=.. clean: - rm -f $(SOCKET_SO) $(SOCKET_OBJS) $(SERIAL_OBJS) - rm -f $(MIME_SO) $(UNIX_SO) $(SERIAL_SO) $(MIME_OBJS) $(UNIX_OBJS) + rm -f $(SOCKET_SO) $(PLATFORM_OBJS_$(PLAT)) $(SOCKET_OBJS) $(SERIAL_OBJS) $(COMBINED_H) + rm -f $(STATIC_LIB) $(MIME_SO) $(UNIX_SO) $(SERIAL_SO) $(MIME_OBJS) $(UNIX_OBJS) .PHONY: all $(PLATS) default clean echo none @@ -459,3 +527,5 @@ unix.$(O): unix.c auxiliar.h socket.h io.h timeout.h usocket.h \ options.h unix.h buffer.h usocket.$(O): usocket.c socket.h io.h timeout.h usocket.h wsocket.$(O): wsocket.c socket.h io.h timeout.h usocket.h +getaddrinfo.$(O): getaddrinfo.c getaddrinfo.h +netdb-compat.$(O): netdb-compat.c netdb-compat.h diff --git a/src/netdb-compat.c b/src/netdb-compat.c new file mode 100644 index 00000000..61ba6b8f --- /dev/null +++ b/src/netdb-compat.c @@ -0,0 +1,142 @@ +/* + * symbian_stubs.c + * + * Copyright (c) Nokia 2004-2005. All rights reserved. + * This code is licensed under the same terms as Perl itself. + * + * netdb-compat.c + * Copyright (c) Dima Pulkinen 2024 + * + */ + +#include "netdb-compat.h" +#include + +static const struct protoent protocols[] = { + { "tcp", 0, 6 }, + { "udp", 0, 17 } +}; + +/* The protocol field (the last) is left empty to save both space + * and time because practically all services have both tcp and udp + * allocations in IANA. */ +static const struct servent services[] = { + { "http", 0, 80, 0 }, /* Optimization. */ + { "https", 0, 443, 0 }, + { "imap", 0, 143, 0 }, + { "imaps", 0, 993, 0 }, + { "smtp", 0, 25, 0 }, + { "irc", 0, 194, 0 }, + + { "ftp", 0, 21, 0 }, + { "ssh", 0, 22, 0 }, + { "tftp", 0, 69, 0 }, + { "pop3", 0, 110, 0 }, + { "sftp", 0, 115, 0 }, + { "nntp", 0, 119, 0 }, + { "ntp", 0, 123, 0 }, + { "snmp", 0, 161, 0 }, + { "ldap", 0, 389, 0 }, + { "rsync", 0, 873, 0 }, + { "socks", 0, 1080, 0 } +}; + +struct protoent* getprotobynumber(int number) { + int i; + for (i = 0; i < sizeof(protocols)/sizeof(struct protoent); i++) + if (protocols[i].p_proto == number) + return (struct protoent*)(&(protocols[i])); + return 0; +} + +struct protoent* getprotobyname(const char* name) { + int i; + for (i = 0; i < sizeof(protocols)/sizeof(struct protoent); i++) + if (strcmp(name, protocols[i].p_name) == 0) + return (struct protoent*)(&(protocols[i])); + return 0; +} + +struct servent* getservbyname(const char* name, const char* proto) { + int i; + for (i = 0; i < sizeof(services)/sizeof(struct servent); i++) + if (strcmp(name, services[i].s_name) == 0) + return (struct servent*)(&(services[i])); + return 0; +} + +struct servent* getservbyport(int port, const char* proto) { + int i; + for (i = 0; i < sizeof(services)/sizeof(struct servent); i++) + if (services[i].s_port == port) + return (struct servent*)(&(services[i])); + return 0; +} + +/* + * Copyright (c) 1987, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +static const char *h_errlist[] = +{ + "Resolver Error 0 (no error)", + "Unknown host", /* 1 HOST_NOT_FOUND */ + "Host name lookup failure", /* 2 TRY_AGAIN */ + "Unknown server error", /* 3 NO_RECOVERY */ + "No address associated with name", /* 4 NO_ADDRESS */ +}; +#define h_nerr (int)(sizeof h_errlist / sizeof h_errlist[0]) + + +const char *hstrerror(int err) +{ + if (err < 0) + return "Resolver internal error"; + else if (err < h_nerr) + return h_errlist[err]; + + return "Unknown resolver error"; +} + diff --git a/src/netdb-compat.h b/src/netdb-compat.h new file mode 100644 index 00000000..af370b39 --- /dev/null +++ b/src/netdb-compat.h @@ -0,0 +1,55 @@ +/* + * Phoenix-RTOS + * + * libphoenix + * + * netdb.h + * + * Copyright 2018 Phoenix Systems + * Author: Jan Sikorski, Michal Miroslaw + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + * + * netdb-compat.h + * Copyright (c) Dima Pulkinen 2024 + * + */ + +#ifndef _NETDB_COMPAT_H_ +#define _NETDB_COMPAT_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +struct servent { + char *s_name; + char **s_aliases; + int s_port; + char *s_proto; +}; + + +struct protoent { + char *p_name; + char **p_aliases; + int p_proto; +}; + +const char *hstrerror(int err); + +struct servent *getservbyname(const char *name, const char *proto); +struct servent *getservbyport(int port, const char *proto); + +struct protoent *getprotobyname(const char *name); +struct protoent *getprotobynumber(int proto); + + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/src/options.c b/src/options.c index 9dea6bda..399e5cae 100644 --- a/src/options.c +++ b/src/options.c @@ -12,7 +12,9 @@ * Internal functions prototypes \*=========================================================================*/ static int opt_setmembership(lua_State *L, p_socket ps, int level, int name); +#if defined(IPV6_ADD_MEMBERSHIP) || defined(IPV6_DROP_MEMBERSHIP) static int opt_ip6_setmembership(lua_State *L, p_socket ps, int level, int name); +#endif static int opt_setboolean(lua_State *L, p_socket ps, int level, int name); static int opt_getboolean(lua_State *L, p_socket ps, int level, int name); static int opt_setint(lua_State *L, p_socket ps, int level, int name); @@ -243,6 +245,7 @@ int opt_set_tcp_defer_accept(lua_State *L, p_socket ps) #endif /*------------------------------------------------------*/ +#ifdef IPV6_UNICAST_HOPS int opt_set_ip6_unicast_hops(lua_State *L, p_socket ps) { return opt_setint(L, ps, IPPROTO_IPV6, IPV6_UNICAST_HOPS); @@ -252,8 +255,10 @@ int opt_get_ip6_unicast_hops(lua_State *L, p_socket ps) { return opt_getint(L, ps, IPPROTO_IPV6, IPV6_UNICAST_HOPS); } +#endif /*------------------------------------------------------*/ +#ifdef IPV6_MULTICAST_HOPS int opt_set_ip6_multicast_hops(lua_State *L, p_socket ps) { return opt_setint(L, ps, IPPROTO_IPV6, IPV6_MULTICAST_HOPS); @@ -263,6 +268,7 @@ int opt_get_ip6_multicast_hops(lua_State *L, p_socket ps) { return opt_getint(L, ps, IPPROTO_IPV6, IPV6_MULTICAST_HOPS); } +#endif /*------------------------------------------------------*/ int opt_set_ip_multicast_loop(lua_State *L, p_socket ps) @@ -276,6 +282,7 @@ int opt_get_ip_multicast_loop(lua_State *L, p_socket ps) } /*------------------------------------------------------*/ +#ifdef IPV6_MULTICAST_LOOP int opt_set_ip6_multicast_loop(lua_State *L, p_socket ps) { return opt_setboolean(L, ps, IPPROTO_IPV6, IPV6_MULTICAST_LOOP); @@ -285,6 +292,7 @@ int opt_get_ip6_multicast_loop(lua_State *L, p_socket ps) { return opt_getboolean(L, ps, IPPROTO_IPV6, IPV6_MULTICAST_LOOP); } +#endif /*------------------------------------------------------*/ int opt_set_linger(lua_State *L, p_socket ps) @@ -362,17 +370,22 @@ int opt_set_ip_drop_membersip(lua_State *L, p_socket ps) } /*------------------------------------------------------*/ +#ifdef IPV6_ADD_MEMBERSHIP int opt_set_ip6_add_membership(lua_State *L, p_socket ps) { return opt_ip6_setmembership(L, ps, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP); } +#endif +#ifdef IPV6_DROP_MEMBERSHIP int opt_set_ip6_drop_membersip(lua_State *L, p_socket ps) { return opt_ip6_setmembership(L, ps, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP); } +#endif /*------------------------------------------------------*/ +#ifdef IPV6_V6ONLY int opt_get_ip6_v6only(lua_State *L, p_socket ps) { return opt_getboolean(L, ps, IPPROTO_IPV6, IPV6_V6ONLY); @@ -382,6 +395,7 @@ int opt_set_ip6_v6only(lua_State *L, p_socket ps) { return opt_setboolean(L, ps, IPPROTO_IPV6, IPV6_V6ONLY); } +#endif /*------------------------------------------------------*/ int opt_get_error(lua_State *L, p_socket ps) @@ -421,6 +435,7 @@ static int opt_setmembership(lua_State *L, p_socket ps, int level, int name) return opt_set(L, ps, level, name, (char *) &val, sizeof(val)); } +#if defined(IPV6_ADD_MEMBERSHIP) || defined(IPV6_DROP_MEMBERSHIP) static int opt_ip6_setmembership(lua_State *L, p_socket ps, int level, int name) { struct ipv6_mreq val; /* obj, opt-name, table */ @@ -446,6 +461,7 @@ static int opt_ip6_setmembership(lua_State *L, p_socket ps, int level, int name) } return opt_set(L, ps, level, name, (char *) &val, sizeof(val)); } +#endif static int opt_get(lua_State *L, p_socket ps, int level, int name, void *val, int* len) diff --git a/src/options.h b/src/options.h index 26d6f025..2331cce4 100644 --- a/src/options.h +++ b/src/options.h @@ -1,11 +1,11 @@ #ifndef OPTIONS_H #define OPTIONS_H /*=========================================================================*\ -* Common option interface +* Common option interface * LuaSocket toolkit * * This module provides a common interface to socket options, used mainly by -* modules UDP and TCP. +* modules UDP and TCP. \*=========================================================================*/ #include "luasocket.h" @@ -78,17 +78,23 @@ int opt_set_tcp_fastopen(lua_State *L, p_socket ps); int opt_set_tcp_fastopen_connect(lua_State *L, p_socket ps); #endif +#ifdef IPV6_UNICAST_HOPS int opt_set_ip6_unicast_hops(lua_State *L, p_socket ps); int opt_get_ip6_unicast_hops(lua_State *L, p_socket ps); +#endif +#ifdef IPV6_MULTICAST_HOPS int opt_set_ip6_multicast_hops(lua_State *L, p_socket ps); int opt_get_ip6_multicast_hops(lua_State *L, p_socket ps); +#endif int opt_set_ip_multicast_loop(lua_State *L, p_socket ps); int opt_get_ip_multicast_loop(lua_State *L, p_socket ps); +#ifdef IPV6_MULTICAST_LOOP int opt_set_ip6_multicast_loop(lua_State *L, p_socket ps); int opt_get_ip6_multicast_loop(lua_State *L, p_socket ps); +#endif int opt_set_linger(lua_State *L, p_socket ps); int opt_get_linger(lua_State *L, p_socket ps); @@ -101,11 +107,17 @@ int opt_get_ip_multicast_if(lua_State *L, p_socket ps); int opt_set_ip_add_membership(lua_State *L, p_socket ps); int opt_set_ip_drop_membersip(lua_State *L, p_socket ps); +#ifdef IPV6_ADD_MEMBERSHIP int opt_set_ip6_add_membership(lua_State *L, p_socket ps); +#endif +#ifdef IPV6_DROP_MEMBERSHIP int opt_set_ip6_drop_membersip(lua_State *L, p_socket ps); +#endif +#ifdef IPV6_V6ONLY int opt_set_ip6_v6only(lua_State *L, p_socket ps); int opt_get_ip6_v6only(lua_State *L, p_socket ps); +#endif int opt_get_error(lua_State *L, p_socket ps); diff --git a/src/psp-un.h b/src/psp-un.h new file mode 100644 index 00000000..467af624 --- /dev/null +++ b/src/psp-un.h @@ -0,0 +1,59 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * psp-un.h + * Copyright (c) Dima Pulkinen 2024 + */ + +#ifndef _PSP_UN_H_ +#define _PSP_UN_H_ + +#include + +/* + * Historically, (struct sockaddr) needed to fit inside an mbuf. + * For this reason, UNIX domain sockets were therefore limited to + * 104 bytes. While this limit is no longer necessary, it is kept for + * binary compatibility reasons. + */ +#define SUNPATHLEN 104 + +/* + * Definitions for UNIX IPC domain. + */ +struct sockaddr_un { + unsigned char sun_len; /* sockaddr len including null */ + sa_family_t sun_family; /* AF_UNIX */ + char sun_path[SUNPATHLEN]; /* path name (gag) */ +}; + +#endif /* !_PSP_UN_H_ */ diff --git a/src/serial.c b/src/serial.c index 21485d3e..688f1326 100644 --- a/src/serial.c +++ b/src/serial.c @@ -10,7 +10,11 @@ #include "unix.h" #include +#ifndef PSP #include +#else +#include "psp-un.h" +#endif /* Reuses userdata definition from unix.h, since it is useful for all diff --git a/src/tcp.c b/src/tcp.c index f0012064..87d078d4 100644 --- a/src/tcp.c +++ b/src/tcp.c @@ -107,7 +107,9 @@ static t_opt optset[] = { #ifdef TCP_KEEPINTVL {"tcp-keepintvl", opt_set_tcp_keepintvl}, #endif +#ifdef IPV6_V6ONLY {"ipv6-v6only", opt_set_ip6_v6only}, +#endif {"linger", opt_set_linger}, {"recv-buffer-size", opt_set_recv_buf_size}, {"send-buffer-size", opt_set_send_buf_size}, diff --git a/src/udp.c b/src/udp.c index 712ad50f..73de6450 100755 --- a/src/udp.c +++ b/src/udp.c @@ -80,12 +80,24 @@ static t_opt optset[] = { {"ip-multicast-loop", opt_set_ip_multicast_loop}, {"ip-add-membership", opt_set_ip_add_membership}, {"ip-drop-membership", opt_set_ip_drop_membersip}, +#ifdef IPV6_UNICAST_HOPS {"ipv6-unicast-hops", opt_set_ip6_unicast_hops}, +#endif +#ifdef IPV6_MULTICAST_HOPS {"ipv6-multicast-hops", opt_set_ip6_unicast_hops}, +#endif +#ifdef IPV6_MULTICAST_LOOP {"ipv6-multicast-loop", opt_set_ip6_multicast_loop}, +#endif +#ifdef IPV6_ADD_MEMBERSHIP {"ipv6-add-membership", opt_set_ip6_add_membership}, +#endif +#ifdef IPV6_DROP_MEMBERSHIP {"ipv6-drop-membership", opt_set_ip6_drop_membersip}, +#endif +#ifdef IPV6_V6ONLY {"ipv6-v6only", opt_set_ip6_v6only}, +#endif {"recv-buffer-size", opt_set_recv_buf_size}, {"send-buffer-size", opt_set_send_buf_size}, {NULL, NULL} @@ -100,10 +112,18 @@ static t_opt optget[] = { {"ip-multicast-if", opt_get_ip_multicast_if}, {"ip-multicast-loop", opt_get_ip_multicast_loop}, {"error", opt_get_error}, +#ifdef IPV6_UNICAST_HOPS {"ipv6-unicast-hops", opt_get_ip6_unicast_hops}, +#endif +#ifdef IPV6_MULTICAST_HOPS {"ipv6-multicast-hops", opt_get_ip6_unicast_hops}, +#endif +#ifdef IPV6_MULTICAST_LOOP {"ipv6-multicast-loop", opt_get_ip6_multicast_loop}, +#endif +#ifdef IPV6_V6ONLY {"ipv6-v6only", opt_get_ip6_v6only}, +#endif {"recv-buffer-size", opt_get_recv_buf_size}, {"send-buffer-size", opt_get_send_buf_size}, {NULL, NULL} diff --git a/src/unixdgram.c b/src/unixdgram.c index 69093d73..20c98292 100644 --- a/src/unixdgram.c +++ b/src/unixdgram.c @@ -12,7 +12,11 @@ #include #include +#ifndef PSP #include +#else +#include "psp-un.h" +#endif #define UNIXDGRAM_DATAGRAMSIZE 8192 diff --git a/src/unixstream.c b/src/unixstream.c index 02aced9c..b5b0b8ad 100644 --- a/src/unixstream.c +++ b/src/unixstream.c @@ -10,7 +10,11 @@ #include "unixstream.h" #include +#ifndef PSP #include +#else +#include "psp-un.h" +#endif /*=========================================================================*\ * Internal function prototypes diff --git a/src/usocket.h b/src/usocket.h index 45f2f99f..3e21b24a 100644 --- a/src/usocket.h +++ b/src/usocket.h @@ -29,7 +29,16 @@ #include /* TCP options (nagle algorithm disable) */ #include +#ifndef PSP #include +#else +#include "getaddrinfo.h" + +#ifndef INET6_ADDRSTRLEN +#define INET6_ADDRSTRLEN INET_ADDRSTRLEN +#endif + +#endif #ifndef SO_REUSEPORT #define SO_REUSEPORT SO_REUSEADDR