Index: ossp-pkg/l2/l2_ch_socket.c RCS File: /v/ossp/cvs/ossp-pkg/l2/l2_ch_socket.c,v rcsdiff -q -kk '-r1.5' '-r1.6' -u '/v/ossp/cvs/ossp-pkg/l2/l2_ch_socket.c,v' 2>/dev/null --- l2_ch_socket.c 2001/08/26 13:07:27 1.5 +++ l2_ch_socket.c 2001/09/02 14:38:51 1.6 @@ -27,37 +27,86 @@ ** l2_ch_socket.c: socket channel implementation */ -#include "l2.h" -#include "l2_p.h" - #include #include #include +#include +#include +#include + +#include "l2.h" +#include "l2_p.h" + +#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) +{ + 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 */ + + if (iFamily == AF_INET) + { + if (inet_aton(pszAddress, &IP4Addr)) + { + memcpy(pvMemref, &IP4Addr, sizeof(struct in_addr)); + return 1; + } + return 0; + } + + else if (iFamily == AF_INET6) + { + for (i = 0; i < 16; 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) + return 0; /* User is supplying a IPv6 format we don't support */ + } + memcpy(pvMemref, &IP6Addr, sizeof(struct in6_addr)); + return 1; + } + + else /* User converting from an address family that we don't support */ + { + errno = EAFNOSUPPORT; + return -1; + } +} +#else +#error "neither inet_pton nor inet_aton available" +#endif +#endif /* declare private channel configuration */ -typedef struct { - int iSocket; /* Socket descriptor */ - int iDomain; /* Hardcoded to support only IPv4 and IPv6 */ - int iProtocol; /* Hardcoded to support only IPv4 and IPv6 */ - int iType; /* Hardcoded for writing streams to iSocket */ - struct sockaddr *pAddr; /* Where do we open a socket? */ +typedef struct +{ + 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 */ } l2_ch_socket_t; /* create channel */ static int hook_create(l2_context_t *ctx) { - l2_ch_socket_t *cfg; + l2_ch_socket_t *cfg = NULL; /* allocate private channel configuration */ if ((cfg = (l2_ch_socket_t *)malloc(sizeof(l2_ch_socket_t))) == NULL) return L2_ERROR; /* initialize configuration with reasonable defaults */ - cfg->iSocket = 0; - cfg->iDomain = PF_INET; /* Internet family */ - cfg->iType = SOCK_STREAM; /* We write streams reliably */ - cfg->iProtocol = IPPROTO_TCP; /* TCP socket */ - cfg->pAddr = NULL; + cfg->pszHost = NULL; + cfg->iPort = 0; + cfg->iSocket = -1; /* link private channel configuration into channel context */ ctx->vp = cfg; @@ -69,21 +118,16 @@ static int hook_configure(l2_context_t *ctx, const char *fmt, va_list ap) { l2_ch_socket_t *cfg; - char pszAddress[L2_MAX_STRING]; - unsigned short unInport; l2_param_t pa[3]; l2_result_t rv; - unInport = 0; - /* parameter checks */ if ((cfg = (l2_ch_socket_t *)ctx->vp) == NULL) return L2_ERROR; /* feed and call generic parameter parsing engine */ - L2_PARAM_SET(pa[0], address, CHARPTR, pszAddress); - L2_PARAM_SET(pa[1], port, USHORT, &unInport); -/* TODO: Fill in the cfg-> structure after building the socket */ + L2_PARAM_SET(pa[0], host, CHARPTR, &cfg->pszHost); + L2_PARAM_SET(pa[1], port, INT, &cfg->iPort); L2_PARAM_END(pa[2]); rv = l2_channel_setparams(pa, fmt, ap); @@ -93,13 +137,55 @@ /* open channel */ static int hook_open(l2_context_t *ctx, l2_channel_t *downstream) { - l2_ch_socket_t *cfg; + l2_ch_socket_t *cfg; + struct hostent *pHostentry; + struct sockaddr_in IP4Sockaddr; + struct sockaddr_in6 IP6Sockaddr; /* parameter checks */ if ((cfg = (l2_ch_socket_t *)ctx->vp) == NULL) return L2_ERROR; + if (cfg->pszHost == NULL) + 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 (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 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)); + } + } + + else + return L2_ERROR; - /* open channel socket */ + 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; + } /* optionally open downstream channel, too */ if (downstream != NULL) @@ -118,8 +204,12 @@ /* parameter checks */ if ((cfg = (l2_ch_socket_t *)ctx->vp) == NULL) return L2_ERROR; + if (cfg->iSocket == -1) + return L2_ERROR; /* write message to channel socket */ + if (send(cfg->iSocket, buf, buf_size, 0) == -1) + return L2_ERROR; /* optionally write to downstream channel, too */ if (downstream != NULL) @@ -132,6 +222,8 @@ /* flush channel */ static int hook_flush(l2_context_t *ctx, l2_channel_t *downstream) { + /* NOP for this channel, because Unix I/O sockets are unbuffered! */ + /* optionally flush downstream channel, too */ if (downstream != NULL) if (l2_channel_flush(downstream) == L2_ERROR) @@ -153,8 +245,12 @@ /* parameter checks */ if ((cfg = (l2_ch_socket_t *)ctx->vp) == NULL) return L2_ERROR; + if (cfg->iSocket == -1) + return L2_ERROR; /* close channel socket */ + if ((shutdown(cfg->iSocket, SHUT_RDWR)) || (close(cfg->iSocket))) + return L2_ERROR; return L2_OK; }