Index: ossp-pkg/l2/l2_ut_sa.ac RCS File: /v/ossp/cvs/ossp-pkg/l2/l2_ut_sa.ac,v rcsdiff -q -kk '-r1.3' '-r1.4' -u '/v/ossp/cvs/ossp-pkg/l2/l2_ut_sa.ac,v' 2>/dev/null --- l2_ut_sa.ac 2001/10/24 13:04:11 1.3 +++ l2_ut_sa.ac 2001/10/26 10:59:47 1.4 @@ -1,39 +1,70 @@ -## -## SA - OSSP Socket Abstraction Library -## Copyright (c) 2001 The OSSP Project (http://www.ossp.org/) -## Copyright (c) 2001 Cable & Wireless Deutschland (http://www.cw.com/de/) -## -## This file is part of OSSP SA, a socket abstraction library which -## can be found at http://www.ossp.org/pkg/sa/. -## -## 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. -## -## THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 AUTHORS AND COPYRIGHT HOLDERS AND THEIR -## 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. -## -## sa.ac: socket abstraction Autoconf checks -## +dnl ## +dnl ## SA - OSSP Socket Abstraction Library +dnl ## Copyright (c) 2001 Ralf S. Engelschall +dnl ## Copyright (c) 2001 The OSSP Project +dnl ## Copyright (c) 2001 Cable & Wireless Deutschland +dnl ## +dnl ## This file is part of OSSP SA, a socket abstraction library which +dnl ## can be found at http://www.ossp.org/pkg/sa/. +dnl ## +dnl ## Permission to use, copy, modify, and distribute this software for +dnl ## any purpose with or without fee is hereby granted, provided that +dnl ## the above copyright notice and this permission notice appear in all +dnl ## copies. +dnl ## +dnl ## THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED +dnl ## WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +dnl ## MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +dnl ## IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR +dnl ## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +dnl ## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +dnl ## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +dnl ## USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +dnl ## ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +dnl ## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +dnl ## OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +dnl ## SUCH DAMAGE. +dnl ## +dnl ## sa.ac: socket abstraction Autoconf checks +dnl ## -AC_DEFUN(AC_CHECK_SA,[ +dnl # Check for an ANSI C typedef in a header +dnl # configure.in: +dnl # SA_CHECK_TYPEDEF(,
) +dnl # acconfig.h: +dnl # #undef HAVE_ + +AC_DEFUN(SA_CHECK_TYPEDEF,[dnl + AC_REQUIRE([AC_HEADER_STDC])dnl + AC_MSG_CHECKING(for typedef $1) + AC_CACHE_VAL(ac_cv_typedef_$1,[ + AC_EGREP_CPP(dnl +changequote(<<,>>)dnl +<<(^|[^a-zA-Z_0-9])$1[^a-zA-Z_0-9]>>dnl +changequote([,]), [ +#include <$2>], + ac_cv_typedef_$1=yes, + ac_cv_typedef_$1=no + ) + ])dnl + AC_MSG_RESULT($ac_cv_typedef_$1) + if test $ac_cv_typedef_$1 = yes; then + AC_DEFINE(HAVE_[]translit($1, [a-z], [A-Z])) + fi +]) + +dnl # Check for anything OSSP SA wants to know +dnl # configure.in: +dnl # SA_CHECK_ALL + +AC_DEFUN(SA_CHECK_ALL,[ # make sure libnsl and libsocket are linked in if they exist AC_CHECK_LIB(nsl, gethostname) if test ".`echo $LIBS | grep nsl`" = .; then AC_CHECK_LIB(nsl, gethostbyname) fi AC_CHECK_LIB(socket, accept) + # make sure some platforms find their IPv6 library AC_CHECK_LIB(inet6, getaddrinfo) @@ -42,5 +73,9 @@ # check for system functions AC_CHECK_FUNCS(inet_aton inet_pton inet_ntoa inet_ntop snprintf) + + dnl # check for network/socket size type + SA_CHECK_TYPEDEF(socklen_t, sys/socket.h) + SA_CHECK_TYPEDEF(ssize_t, sys/types.h) ]) Index: ossp-pkg/l2/l2_ut_sa.c RCS File: /v/ossp/cvs/ossp-pkg/l2/l2_ut_sa.c,v rcsdiff -q -kk '-r1.15' '-r1.16' -u '/v/ossp/cvs/ossp-pkg/l2/l2_ut_sa.c,v' 2>/dev/null --- l2_ut_sa.c 2001/10/10 15:58:27 1.15 +++ l2_ut_sa.c 2001/10/26 10:59:47 1.16 @@ -51,6 +51,24 @@ /* include own API header */ #include "l2_ut_sa.h" +/* boolean values */ +#ifndef FALSE +#define FALSE (0) +#endif +#ifndef TRUE +#define TRUE (!FALSE) +#endif + +/* backward compatibility for AF_LOCAL */ +#if !defined(AF_LOCAL) && defined(AF_UNIX) +#define AF_LOCAL AF_UNIX +#endif + +/* backward compatibility for ssize_t */ +#if defined(HAVE_CONFIG_H) && !defined(HAVE_SSIZE_T) +#define ssize_t long +#endif + /* system call structure declaration macros */ #define SA_SC_DECLARE_0(rc_t, fn) \ struct { \ @@ -178,23 +196,10 @@ socklen_t slBuf; /* the length of "struct sockaddr_xx" */ }; -/* boolean values */ -#ifndef FALSE -#define FALSE (0) -#endif -#ifndef TRUE -#define TRUE (!FALSE) -#endif - /* handy struct timeval check */ #define SA_TVISZERO(tv) \ ((tv).tv_sec == 0 && (tv).tv_usec == 0) -/* backward compatibility for AF_LOCAL */ -#if !defined(AF_LOCAL) && defined(AF_UNIX) -#define AF_LOCAL AF_UNIX -#endif - /* convert Internet address from presentation to network format */ static int sa_inet_pton(int family, const char *strptr, void *addrptr) { @@ -419,6 +424,7 @@ #ifdef AF_INET6 struct sockaddr_in6 sa6; #endif + int bIPv6; struct hostent *he; struct servent *se; int bNumeric; @@ -471,7 +477,7 @@ } else cp = un.sun_path; - memcpy(un.sun_path, cpPath, n+1); + memcpy(cp, cpPath, n+1); un.sun_family = AF_LOCAL; /* provide results */ @@ -480,12 +486,36 @@ sf = AF_LOCAL; } else if (strncmp(uri, "inet://", 7) == 0) { - /* parse URI */ + /* parse URI into host, port and protocol parts */ cpHost = (char *)(uri+7); - if ((cp = strrchr(cpHost, ':')) == NULL) + bIPv6 = FALSE; + if (cpHost[0] == '[') { + /* IPv6 address (see RFC2732) */ +#ifndef AF_INET6 return SA_ERR_ARG; - *cp++ = '\0'; +#else + bIPv6 = TRUE; + cpHost++; + if ((cp = strchr(cpHost, ']')) == NULL) + return SA_ERR_ARG; + *cp++ = '\0'; + if (*cp != ':') + return SA_ERR_ARG; + cp++; +#endif + } + else { + /* IPv4 address or hostname */ + if ((cp = strrchr(cpHost, ':')) == NULL) + return SA_ERR_ARG; + *cp++ = '\0'; + } cpPort = cp; + cpProto = "tcp"; + if ((cp = strchr(cpPort, '#')) != NULL) { + *cp++ = '\0'; + cpProto = cp; + } /* resolve port */ nPort = 0; @@ -499,11 +529,6 @@ if (bNumeric) nPort = atoi(cpPort); else { - cpProto = "tcp"; - if ((cp = strchr(cpPort, '#')) != NULL) { - *cp++ = '\0'; - cpProto = cp; - } if ((se = getservbyname(cpPort, cpProto)) == NULL) return SA_ERR_SYS; nPort = ntohs(se->s_port); @@ -515,9 +540,9 @@ memset(&sa6, 0, sizeof(sa6)); #endif - /* resolve host by trying to parse it as either directly a IPv4 or - IPv6 address or by resolving it to either a IPv4 or IPv6 address */ - if (sa_inet_pton(AF_INET, cpHost, &sa4.sin_addr.s_addr) == 1) { + /* resolve host by trying to parse it as either directly an IPv4 or + IPv6 address or by resolving it to either an IPv4 or IPv6 address */ + if (!bIPv6 && sa_inet_pton(AF_INET, cpHost, &sa4.sin_addr.s_addr) == 1) { sa4.sin_family = AF_INET; sa4.sin_port = htons(nPort); sa = (struct sockaddr *)&sa4; @@ -525,7 +550,7 @@ sf = AF_INET; } #ifdef AF_INET6 - else if (sa_inet_pton(AF_INET6, cpHost, &sa6.sin6_addr.s6_addr) == 1) { + else if (bIPv6 && sa_inet_pton(AF_INET6, cpHost, &sa6.sin6_addr.s6_addr) == 1) { sa6.sin6_family = AF_INET6; sa6.sin6_port = htons(nPort); sa = (struct sockaddr *)&sa6; @@ -578,13 +603,6 @@ /* import "struct sockaddr" into address object */ sa_rc_t sa_addr_s2a(sa_addr_t *saa, const struct sockaddr *sabuf, socklen_t salen) { - struct sockaddr_un *un; - struct sockaddr_in *sa4; -#ifdef AF_INET6 - struct sockaddr_in6 *sa6; -#endif - int sf; - /* argument sanity check(s) */ if (saa == NULL || sabuf == NULL || salen == 0) return SA_ERR_ARG; @@ -597,28 +615,8 @@ memcpy(saa->saBuf, sabuf, salen); saa->slBuf = salen; - /* resolve family */ - sf = 0; - if (sizeof(struct sockaddr_un) == salen) { - un = (struct sockaddr_un *)((void *)sabuf); - if (un->sun_family == AF_LOCAL) - sf = AF_LOCAL; - } - if (sf == 0 && sizeof(struct sockaddr_in) == salen) { - sa4 = (struct sockaddr_in *)((void *)sabuf); - if (sa4->sin_family == AF_INET) - sf = AF_INET; - } -#ifdef AF_INET6 - if (sf == 0 && sizeof(struct sockaddr_in6) == salen) { - sa6 = (struct sockaddr_in6 *)((void *)sabuf); - if (sa6->sin6_family == AF_INET6) - sf = AF_INET6; - } -#endif - if (sf == 0) - return SA_ERR_ARG; - saa->nFamily = sf; + /* remember family */ + saa->nFamily = sabuf->sa_family; return SA_OK; } @@ -642,27 +640,31 @@ /* export object contents */ if (saa->nFamily == AF_LOCAL) { un = (struct sockaddr_un *)((void *)saa->saBuf); - sa_msnprintf(uribuf, sizeof(uribuf), "unix:%s", un->sun_path); + if ( ( saa->slBuf >= (socklen_t)(&(((struct sockaddr_un *)0)->sun_path[0])) + && un->sun_path[0] == '\0') + || saa->slBuf < sizeof(struct sockaddr_un)) + /* in case the remote side of a Unix Domain socket was not + bound, a "struct sockaddr_un" can occur with a length less + than the expected one. Then there is actually no path at all. + This has been verified under FreeBSD, Linux and Solaris. */ + sa_msnprintf(uribuf, sizeof(uribuf), "unix:/NOT-BOUND"); + else + sa_msnprintf(uribuf, sizeof(uribuf), "unix:%s", un->sun_path); } -#ifdef AF_INET6 - else if (saa->nFamily == AF_INET || saa->nFamily == AF_INET6) { -#else else if (saa->nFamily == AF_INET) { -#endif - if (saa->nFamily == AF_INET) { - sa4 = (struct sockaddr_in *)((void *)saa->saBuf); - sa_inet_ntop(AF_INET, &sa4->sin_addr.s_addr, caHost, sizeof(caHost)); - nPort = ntohs(sa4->sin_port); - } -#ifdef AF_INET6 - else { - sa6 = (struct sockaddr_in6 *)((void *)saa->saBuf); - sa_inet_ntop(AF_INET6, &sa6->sin6_addr.s6_addr, caHost, sizeof(caHost)); - nPort = ntohs(sa6->sin6_port); - } -#endif + sa4 = (struct sockaddr_in *)((void *)saa->saBuf); + sa_inet_ntop(AF_INET, &sa4->sin_addr.s_addr, caHost, sizeof(caHost)); + nPort = ntohs(sa4->sin_port); sa_msnprintf(uribuf, sizeof(uribuf), "inet://%s:%d", caHost, nPort); } +#ifdef AF_INET6 + else if (saa->nFamily == AF_INET6) { + sa6 = (struct sockaddr_in6 *)((void *)saa->saBuf); + sa_inet_ntop(AF_INET6, &sa6->sin6_addr.s6_addr, caHost, sizeof(caHost)); + nPort = ntohs(sa6->sin6_port); + sa_msnprintf(uribuf, sizeof(uribuf), "inet://[%s]:%d", caHost, nPort); + } +#endif else return SA_ERR_INT; @@ -693,21 +695,23 @@ const unsigned char *ucp1, *ucp2; unsigned int uc1, uc2, mask; size_t l1, l2; - int nFamily; int nBytes; int nBits; +#ifdef AF_INET6 + int i; + const unsigned char *ucp0; +#endif /* argument sanity check(s) */ if (saa1 == NULL || saa2 == NULL || prefixlen < -1) return SA_ERR_ARG; - /* match short circuiting */ - if (saa1->nFamily != saa2->nFamily) - return SA_ERR_MTC; + /* short circuiting for wildcard matching */ + if (prefixlen == 0) + return SA_OK; /* determine address representation pointer and size */ - nFamily = saa1->nFamily; - if (nFamily == AF_LOCAL) { + if (saa1->nFamily == AF_LOCAL) { ucp1 = (const unsigned char *)(((struct sockaddr_un *)saa1->saBuf)->sun_path); ucp2 = (const unsigned char *)(((struct sockaddr_un *)saa2->saBuf)->sun_path); l1 = strlen(((struct sockaddr_un *)saa1->saBuf)->sun_path) * 8; @@ -723,13 +727,38 @@ nBits = prefixlen; } } - else if (nFamily == AF_INET) { +#ifdef AF_INET6 + else if ( (saa1->nFamily == AF_INET && saa2->nFamily == AF_INET6) + || (saa1->nFamily == AF_INET6 && saa2->nFamily == AF_INET )) { + /* special case of comparing a regular IPv4 address (1.2.3.4) with an + "IPv4-mapped IPv6 address" (::ffff:1.2.3.4). For details see RFC 2373. */ + if (saa1->nFamily == AF_INET6) { + ucp1 = (const unsigned char *)&(((struct sockaddr_in6 *)saa1->saBuf)->sin6_addr); + ucp2 = (const unsigned char *)&(((struct sockaddr_in *)saa2->saBuf)->sin_addr); + ucp0 = ucp1; + ucp1 += 12; + } + else { + ucp1 = (const unsigned char *)&(((struct sockaddr_in *)saa1->saBuf)->sin_addr); + ucp2 = (const unsigned char *)&(((struct sockaddr_in6 *)saa2->saBuf)->sin6_addr); + ucp0 = ucp2; + ucp2 += 12; + } + for (i = 0; i < 10; i++) + if (ucp0[i] != 0x00) + return SA_ERR_MTC; + if (!(ucp0[10] == 0xFF && ucp0[11] == 0xFF)) + return SA_ERR_MTC; + nBits = 32; + } +#endif + else if (saa1->nFamily == AF_INET) { ucp1 = (const unsigned char *)&(((struct sockaddr_in *)saa1->saBuf)->sin_addr); ucp2 = (const unsigned char *)&(((struct sockaddr_in *)saa2->saBuf)->sin_addr); nBits = 32; } #ifdef AF_INET6 - else if (nFamily == AF_INET6) { + else if (saa1->nFamily == AF_INET6) { ucp1 = (const unsigned char *)&(((struct sockaddr_in6 *)saa1->saBuf)->sin6_addr); ucp2 = (const unsigned char *)&(((struct sockaddr_in6 *)saa2->saBuf)->sin6_addr); nBits = 128; @@ -1141,6 +1170,7 @@ } else if (n == 0) { close(sa->fdSocket); /* stop TCP three-way handshake */ + sa->fdSocket = -1; rv = SA_ERR_TMT; goto done; } @@ -1158,6 +1188,7 @@ /* optionally set errno */ if (error != 0) { close(sa->fdSocket); /* just in case */ + sa->fdSocket = -1; errno = error; rv = SA_ERR_SYS; } @@ -1194,6 +1225,7 @@ int n; fd_set fds; union { + struct sockaddr_un un; struct sockaddr_in sa4; #ifdef AF_INET6 struct sockaddr_in6 sa6; @@ -1502,6 +1534,7 @@ char c; size_t n; size_t res; + sa_rc_t rv; /* argument sanity check(s) */ if (sa == NULL || cpBuf == NULL || nBufReq == 0) @@ -1519,9 +1552,12 @@ buffers are enabled, this is not as stupid as it looks at the first hand and if buffers are disabled, there is no better solution anyway. */ + rv = SA_OK; res = 0; while (res < (nBufReq-1)) { - sa_read(sa, &c, 1, &n); + rv = sa_read(sa, &c, 1, &n); + if (rv != SA_OK) + break; if (n <= 0) break; cpBuf[res++] = c; @@ -1534,7 +1570,7 @@ if (nBufRes != NULL) *nBufRes = res; - return SA_OK; + return rv; } /* internal raw write operation */