--- l2_ch_socket.c 2001/09/04 19:18:49 1.10
+++ l2_ch_socket.c 2001/09/04 19:34:33 1.11
@@ -30,7 +30,6 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
-#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
@@ -40,14 +39,13 @@
#define HAVE_INET_ATON
#ifndef HAVE_INET_PTON
#ifdef HAVE_INET_ATON
-/* !!! TODO change pton1 to pton !!! */
-static int inet_pton1(int iFamily, const char *pszAddress, void *pvMemref)
+static int inet_pton(int iFamily, const char *pszAddress, void *pvMemref)
{
int i = 0;
struct in_addr IP4Addr;
struct in6_addr IP6Addr;
- char *pszNextfield = NULL; /* For IPv6 address trans */
- char **ppszVerify = &pszNextfield; /* To check IPv6 validity */
+ char *pszIndex = NULL; /* To index IPv6 validity */
+ char *pszNextfield = NULL; /* For IPv6 address trans */
if (iFamily == AF_INET)
{
@@ -59,18 +57,23 @@
return 0;
}
- else if (iFamily == AF_INET6)
- {
- for (i = 0; i < 16; i++) /* Iterate through the IPv6 address fields */
+ else if (iFamily == AF_INET6) /* If we are translating IPv6 addresses */
+ { /* the user needs to use precise notation */
+ pszIndex = malloc(strlen(pszAddress));
+ strcpy(pszIndex, pszAddress); /* Initialize, verify in loop */
+ for (i = 0; i < 8; i++) /* Iterate through the IPv6 address fields */
{
- ppszVerify = &pszNextfield; /* Reset and compare later to verify */
- IP6Addr.__u6_addr.__u6_addr8[i] = (u_int8_t)strtol(pszAddress,\
- &pszNextfield, 16);
- *pszNextfield++; /* !!! TODO Problema !!! */
-
- if ((&pszNextfield - ppszVerify) != 2)
+ IP6Addr.__u6_addr.__u6_addr16[i] =\
+ ntohs((u_int16_t)strtol(pszIndex, &pszNextfield, 16));
+ if ((pszNextfield == '\0') ||\
+ ((pszNextfield - pszIndex) != (4 * sizeof(char))))
+ {
return 0; /* User is supplying a IPv6 format we don't support */
+ }
+
+ pszIndex = ++pszNextfield;
}
+
memcpy(pvMemref, &IP6Addr, sizeof(struct in6_addr));
return 1;
}
@@ -89,6 +92,7 @@
/* declare private channel configuration */
typedef struct
{
+ int iFamily; /* IP version to use, AF_INET4 or AF_INET6 */
char *pszHost; /* IP Address or name of host to connect to */
int iPort; /* TCP Port to connect to */
int iSocket; /* Socket descriptor used during writing */
@@ -118,7 +122,7 @@
static l2_result_t hook_configure(l2_context_t *ctx, l2_channel_t *ch, const char *fmt, va_list ap)
{
l2_ch_socket_t *cfg;
- l2_param_t pa[3];
+ l2_param_t pa[4];
l2_result_t rv;
/* parameter checks */
@@ -126,9 +130,10 @@
return L2_ERROR;
/* feed and call generic parameter parsing engine */
- L2_PARAM_SET(pa[0], host, CHARPTR, &cfg->pszHost);
- L2_PARAM_SET(pa[1], port, INT, &cfg->iPort);
- L2_PARAM_END(pa[2]);
+ L2_PARAM_SET(pa[0], ipversion, INT, &cfg->iFamily);
+ L2_PARAM_SET(pa[1], host, CHARPTR, &cfg->pszHost);
+ L2_PARAM_SET(pa[2], port, INT, &cfg->iPort);
+ L2_PARAM_END(pa[3]);
rv = l2_util_setparams(pa, fmt, ap);
return rv;
@@ -141,6 +146,7 @@
struct hostent *pHostentry;
struct sockaddr_in IP4Sockaddr;
struct sockaddr_in6 IP6Sockaddr;
+ struct in6_addr *IP6Addr;
/* parameter checks */
if ((cfg = (l2_ch_socket_t *)ctx->vp) == NULL)
@@ -149,45 +155,85 @@
return L2_ERROR;
/* open channel socket */
- /* resolve host numerically */
- if (inet_pton1(AF_INET, cfg->pszHost, &IP4Sockaddr.sin_addr.s_addr) == 1)
- {
- IP4Sockaddr.sin_family = AF_INET;
- IP4Sockaddr.sin_port = htons(cfg->iPort);
- }
-
- /* resolve host nominally */
- else if ((pHostentry = gethostbyname(cfg->pszHost)) != NULL)
+ if (cfg->iFamily == AF_INET) /* IPv4 */
{
- if (pHostentry->h_addrtype == AF_INET)
+ /* resolve host numerically */
+ if (inet_pton(AF_INET, cfg->pszHost, &IP4Sockaddr.sin_addr.s_addr) == 1)
{
IP4Sockaddr.sin_family = AF_INET;
IP4Sockaddr.sin_port = htons(cfg->iPort);
- memcpy(&IP4Sockaddr.sin_addr.s_addr, pHostentry->h_addr_list[0],\
- sizeof(IP4Sockaddr.sin_addr.s_addr));
}
- else if (pHostentry->h_addrtype == AF_INET6)
+ /* resolve host nominally */
+ else if ((pHostentry = gethostbyname(cfg->pszHost)) != NULL)
+ {
+ if (pHostentry->h_addrtype == AF_INET)
+ {
+ IP4Sockaddr.sin_family = AF_INET;
+ IP4Sockaddr.sin_port = htons(cfg->iPort);
+ memcpy(&IP4Sockaddr.sin_addr.s_addr, pHostentry->h_addr_list[0],\
+ sizeof(IP4Sockaddr.sin_addr.s_addr));
+ }
+
+ else
+ return L2_ERROR; /* what?? we specify IPv4 when it is not? */
+ }
+
+ else /* host string was not parsable for some reason */
+ return L2_ERROR;
+
+ if ((cfg->iSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
+ return L2_ERROR;
+
+ if (connect(cfg->iSocket, (struct sockaddr *)&IP4Sockaddr, sizeof(IP4Sockaddr)))
+ {
+ close(cfg->iSocket);
+ return L2_ERROR;
+ }
+
+ return L2_OK; /* we are connected */
+ }
+
+ else if (cfg->iFamily == AF_INET6) /* IPv6 */
+ {
+ /* resolve host numerically */
+ if (inet_pton(AF_INET6, cfg->pszHost, &IP6Sockaddr.sin6_addr.s6_addr) == 1)
{
IP6Sockaddr.sin6_family = AF_INET6;
IP6Sockaddr.sin6_port = htons(cfg->iPort);
- memcpy(&IP6Sockaddr.sin6_addr.__u6_addr, pHostentry->h_addr_list[0],\
- sizeof(IP6Sockaddr.sin6_addr.__u6_addr));
}
- }
- else
- return L2_ERROR;
+ /* resolve host nominally */
+ else if ((pHostentry = gethostbyname2(cfg->pszHost, AF_INET6)) != NULL)
+ {
+ if (pHostentry->h_addrtype == AF_INET6)
+ {
+ IP6Sockaddr.sin6_family = AF_INET6;
+ IP6Sockaddr.sin6_port = htons(cfg->iPort);
+ memcpy(&IP6Sockaddr.sin6_addr.__u6_addr, pHostentry->h_addr_list[0],\
+ sizeof(IP6Sockaddr.sin6_addr.__u6_addr));
+ }
- if ((cfg->iSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
- return L2_ERROR;
- if (connect(cfg->iSocket, (struct sockaddr *)&IP4Sockaddr, sizeof(IP4Sockaddr)))
- {
- close(cfg->iSocket);
- return L2_ERROR;
+ else
+ return L2_ERROR; /* what?? we specify IPv6 when it is not? */
+ }
+
+ else /* host string was not parsable for some reason */
+ return L2_ERROR;
+
+ if ((cfg->iSocket = socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP)) == -1)
+ return L2_ERROR;
+
+ if (connect(cfg->iSocket, (struct sockaddr *)&IP6Sockaddr, sizeof(IP6Sockaddr)))
+ {
+ close(cfg->iSocket);
+ return L2_ERROR;
+ }
+
+ return L2_OK; /* we are connected */
}
- return L2_OK;
+ return L2_ERROR;
}
/* write to channel */
@@ -195,6 +241,8 @@
const char *buf, size_t buf_size)
{
l2_ch_socket_t *cfg;
+ size_t sizeWrite;
+ size_t sizeRemain;
/* parameter checks */
if ((cfg = (l2_ch_socket_t *)ctx->vp) == NULL)
@@ -202,9 +250,18 @@
if (cfg->iSocket == -1)
return L2_ERROR;
- /* write message to channel socket */
- if (send(cfg->iSocket, buf, buf_size, 0) == -1)
- return L2_ERROR;
+ /* write message to channel socket, but check to make */
+ /* sure that the whole message was successfully written */
+ sizeWrite = 0;
+ sizeRemain = buf_size;
+ while(sizeRemain)
+ {
+ sizeWrite = send(cfg->iSocket, buf + sizeWrite, sizeRemain, 0);
+ sizeRemain = sizeRemain - sizeWrite; /* how much is left? */
+
+ if (sizeWrite == -1)
+ return L2_ERROR;
+ }
return L2_OK;
}
|