1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
|
/****************************************************************
* *
* Copyright (c) 2001-2018 Fidelity National Information *
* Services, Inc. and/or its subsidiaries. All rights reserved. *
* *
* 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. *
* *
****************************************************************/
/* gtcm_cn_acpt.c ---
* Accept a client connection.
*/
#include "mdef.h"
#include <errno.h>
#include "gtm_fcntl.h"
#include "gtm_string.h"
#include "gtm_stdio.h"
#include "gtm_unistd.h" /* for close() used by CLOSEFILE_RESET */
#include "gtm_time.h" /* for ctime and time */
#include "gtcm.h"
#include "rc_oflow.h"
#include "eintr_wrappers.h"
#include "gtm_socket.h"
#include "gtmio.h"
#include "have_crit.h"
#ifdef BSD_TCP
#include "gtm_inet.h"
#endif /* defined(BSD_TCP) */
#ifndef lint
static char rcsid[] = "$Header:$";
#endif
GBLREF char *omi_pklog;
GBLREF int one_conn_per_inaddr;
GBLREF int conn_timeout;
#define MAX_LOG_LEN 1024 + 1
int gtcm_cn_acpt(omi_conn_ll *cll, int now) /* now --> current time in seconds */
{
char pklog[MAX_LOG_LEN], *tmp_time;
int errno_save, i, rc;
omi_conn *cptr;
omi_fd fd;
const boolean_t keepalive = TRUE;
GTM_SOCKLEN_TYPE sln;
int optsize;
struct sockaddr_storage sas;
/* Accept the connection from the network layer */
sln = SIZEOF(sas);
ACCEPT_SOCKET(cll->nve, (struct sockaddr *)&sas, (GTM_SOCKLEN_TYPE *)&sln, fd);
if (0 > fd)
return -1;
/* Build the client data structure */
if (!(cptr = (omi_conn *)malloc(SIZEOF(omi_conn))) || !(cptr->buff = (char *)malloc(OMI_BUFSIZ)))
{
if (cptr)
free(cptr);
CLOSEFILE_RESET(fd, rc); /* resets "fd" to FD_INVALID */
return -1;
}
/* Initialize the connection structure */
cptr->next = (omi_conn *)0;
cptr->fd = fd;
cptr->ping_cnt = 0;
cptr->timeout = now + conn_timeout;
cptr->bsiz = OMI_BUFSIZ;
cptr->bptr = cptr->buff;
cptr->xptr = (char *)0;
cptr->blen = 0;
cptr->exts = 0;
cptr->state = OMI_ST_DISC;
cptr->ga = (ga_struct *)0; /* struct gd_addr_struct */
cptr->of = (oof_struct *) malloc(SIZEOF(struct rc_oflow));
memset(cptr->of, 0, SIZEOF(struct rc_oflow));
cptr->pklog = FD_INVALID;
/* Initialize the statistics */
memcpy(&cptr->stats.sas, &sas, sln);
cptr->stats.ai.ai_addr = (struct sockaddr *)&cptr->stats.sas;
cptr->stats.ai.ai_addrlen = sln;
cptr->stats.bytes_recv = 0;
cptr->stats.bytes_send = 0;
cptr->stats.start = time((time_t *)0);
for (i = 0; i < OMI_OP_MAX; i++)
cptr->stats.xact[i] = 0;
for (i = 0; i < OMI_ER_MAX; i++)
cptr->stats.errs[i] = 0;
/* if we only allowing one connection per internet address, close any existing ones with the same addr. */
if (one_conn_per_inaddr)
{
omi_conn *this, *prev;
for (prev = NULL, this = cll->head; this; prev = this, this = this->next)
{
if (0 == memcmp((sockaddr_ptr)(&this->stats.sas), (sockaddr_ptr)&sas, sln))
{
if (cll->tail == this)
cll->tail = cptr;
if (prev)
prev->next = cptr;
else
cll->head = cptr;
cptr->next = this->next;
OMI_DBG_STMP;
OMI_DBG((omi_debug, "%s: dropping old connection to %s\n",
SRVR_NAME, gtcm_hname(&cptr->stats.ai)));
gtcm_cn_disc(this, cll);
break;
}
}
/* not found - add to the end of the list */
if (!this)
{
if (cll->tail)
{
cll->tail->next = cptr;
cll->tail = cptr;
} else
cll->head = cll->tail = cptr;
}
} else
{
/* Insert the client into the list of connections */
if (cll->tail)
{
cll->tail->next = cptr;
cll->tail = cptr;
} else
cll->head = cll->tail = cptr;
}
cptr->stats.id = ++cll->stats.conn;
DEBUG_ONLY(
if (omi_pklog)
{
(void)SNPRINTF(pklog, MAX_LOG_LEN, "%s.%04d", omi_pklog, cptr->stats.id);
if (INV_FD_P((cptr->pklog = OPEN3(pklog, O_WRONLY|O_CREAT|O_APPEND|O_TRUNC, 0644))))
{
errno_save = errno;
OMI_DBG_STMP;
OMI_DBG((omi_debug, "%s: unable to open packet log \"%s\"\n\t%s\n",
SRVR_NAME, pklog, STRERROR(errno_save)));
}
}
)
GTM_CTIME(tmp_time, &cptr->stats.start);
OMI_DBG((omi_debug, "%s: connection %d from %s by user <%s> at %s", SRVR_NAME,
cptr->stats.id, gtcm_hname(&cptr->stats.ai), cptr->ag_name, tmp_time));
if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char *)&keepalive, SIZEOF(keepalive)) < 0)
{
PERROR("setsockopt:");
return -1;
}
return 0;
}
|