fis-gtm/sr_port/iosocket_create.c

165 lines
5.4 KiB
C

/****************************************************************
* *
* Copyright 2001, 2012 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
* under a license. If you do not know the terms of *
* the license, please stop and do not read further. *
* *
****************************************************************/
/* iosocket_create.c */
/* this module takes care of
* 1. allocate the space
* 2. for passive: local.sin.sin_addr.s_addr & local.sin.sin_port
* for active : remote.sin.sin_addr.s_addr & remote.sin.sin_port
* for $principal: via getsockname and getsockpeer
* 3. socketptr->protocol
* 4. socketptr->sd (initialized to -1) unless already open via inetd
* 5. socketptr->passive
* 6. socketptr->state (initialized to created) unless already open
*/
#include "mdef.h"
#include <errno.h>
#include "gtm_ctype.h"
#include "gtm_stdio.h"
#include "gtm_string.h"
#include "gtm_netdb.h"
#include "gtm_socket.h"
#include "gtm_inet.h"
#include "io.h"
#include "iotcproutine.h"
#include "iotcpdef.h"
#include "gt_timer.h"
#include "iosocketdef.h"
#include "min_max.h"
#include "gtm_caseconv.h"
#ifdef __osf__
/* Tru64 does not have the prototype for "hstrerror" even though the function is available in the library.
* Until we revamp the TCP communications setup stuff to use the new(er) POSIX definitions, we cannot move
* away from "hstrerror". Declare prototype for this function in Tru64 manually until then.
*/
const char *hstrerror(int err);
#endif
GBLREF tcp_library_struct tcp_routines;
error_def(ERR_GETSOCKNAMERR);
error_def(ERR_INVPORTSPEC);
error_def(ERR_INVADDRSPEC);
error_def(ERR_PROTNOTSUP);
error_def(ERR_TEXT);
socket_struct *iosocket_create(char *sockaddr, uint4 bfsize, int file_des)
{
socket_struct *socketptr;
bool passive = FALSE;
unsigned short port;
int ii, save_errno, tmplen;
GTM_SOCKLEN_TYPE socknamelen;
char temp_addr[SA_MAXLITLEN], addr[SA_MAXLEN], tcp[4], *adptr;
const char *errptr;
socketptr = (socket_struct *)malloc(SIZEOF(socket_struct));
memset(socketptr, 0, SIZEOF(socket_struct));
if (0 > file_des)
{ /* no socket descriptor yet */
if (SSCANF(sockaddr, "%[^:]:%hu:%3[^:]", temp_addr, &port, tcp) < 3)
{
passive = TRUE;
socketptr->local.sin.sin_addr.s_addr = INADDR_ANY;
if(SSCANF(sockaddr, "%hu:%3[^:]", &port, tcp) < 2)
{
free(socketptr);
rts_error(VARLSTCNT(1) ERR_INVPORTSPEC);
return NULL;
}
socketptr->local.sin.sin_port = GTM_HTONS(port);
socketptr->local.sin.sin_family = AF_INET;
socketptr->local.port = port;
} else
{
for (ii = 0; ISDIGIT_ASCII(temp_addr[ii]) || '.' == temp_addr[ii]; ii++) /* NOTE: only ASCII digits */
; /* allowed for dotted notation address */
if (temp_addr[ii] != '\0')
{
SPRINTF(socketptr->remote.saddr_lit, "%s", temp_addr);
adptr = iotcp_name2ip(temp_addr);
if (NULL == adptr)
{
free(socketptr);
#if !defined(__hpux) && !defined(__MVS__)
errptr = HSTRERROR(h_errno);
rts_error(VARLSTCNT(6) ERR_INVADDRSPEC, 0, ERR_TEXT, 2, LEN_AND_STR(errptr));
#else
/* Grumble grumble HPUX and z/OS don't have hstrerror() */
rts_error(VARLSTCNT(1) ERR_INVADDRSPEC);
#endif
return NULL;
}
SPRINTF(addr, "%s", adptr);
} else
SPRINTF(addr, "%s", temp_addr);
if ((unsigned int)-1 == (socketptr->remote.sin.sin_addr.s_addr = tcp_routines.aa_inet_addr(addr)))
{ /* Errno not set by inet_addr() */
free(socketptr);
rts_error(VARLSTCNT(1) ERR_INVADDRSPEC);
return NULL;
}
socketptr->remote.sin.sin_port = GTM_HTONS(port);
socketptr->remote.sin.sin_family = AF_INET;
socketptr->remote.port = port;
SPRINTF(socketptr->remote.saddr_ip, "%s", addr);
}
lower_to_upper((uchar_ptr_t)tcp, (uchar_ptr_t)tcp, SIZEOF("TCP") - 1);
if (0 == MEMCMP_LIT(tcp, "TCP"))
socketptr->protocol = socket_tcpip;
else
{
free(socketptr);
rts_error(VARLSTCNT(4) ERR_PROTNOTSUP, 2, MIN(strlen(tcp), SIZEOF("TCP") - 1), tcp);
return NULL;
}
socketptr->sd = FD_INVALID; /* don't mess with 0 */
socketptr->state = socket_created; /* Is this really useful? */
} else
{ /* socket already setup by inetd */
socketptr->sd = file_des;
socknamelen = SIZEOF(socketptr->local.sin);
if (-1 == tcp_routines.aa_getsockname(socketptr->sd, (struct sockaddr *)&socketptr->local.sin, &socknamelen))
{
save_errno = errno;
errptr = (char *)STRERROR(save_errno);
tmplen = STRLEN(errptr);
free(socketptr);
rts_error(VARLSTCNT(5) ERR_GETSOCKNAMERR, 3, save_errno, tmplen, errptr);
return NULL;
}
socketptr->local.port = GTM_NTOHS(socketptr->local.sin.sin_port);
socknamelen = SIZEOF(socketptr->remote.sin);
if (-1 == getpeername(socketptr->sd, (struct sockaddr *)&socketptr->remote.sin, (GTM_SOCKLEN_TYPE *)&socknamelen))
{
save_errno = errno;
errptr = (char *)STRERROR(save_errno);
tmplen = STRLEN(errptr);
free(socketptr);
rts_error(VARLSTCNT(5) ERR_GETSOCKNAMERR, 3, save_errno, tmplen, errptr); /* need new error */
return NULL;
}
socketptr->remote.port = GTM_NTOHS(socketptr->remote.sin.sin_port);
socketptr->state = socket_connected;
socketptr->protocol = socket_tcpip;
}
socketptr->buffer = (char *)malloc(bfsize);
socketptr->buffer_size = bfsize;
socketptr->buffered_length = socketptr->buffered_offset = 0;
socketptr->passive = passive;
socketptr->moreread_timeout = DEFAULT_MOREREAD_TIMEOUT;
return socketptr;
}