--- 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 */
|