fis-gtm/sr_unix_cm/rc_srvc_xct.c

372 lines
9.5 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. *
* *
****************************************************************/
/*
* rc_srvc_xact.c ---
*
* Process a client's RC transaction.
*
*/
#ifndef lint
static char rcsid[] = "$Header:$";
#endif
#include "mdef.h"
#include "gtm_stdio.h"
#include "gtm_string.h"
#include <errno.h>
#include "gtcm.h"
#include "omi.h"
#include "gtmio.h"
#include "have_crit.h"
#include "rc.h"
typedef struct rc_clnt_err rc_clnt_err;
struct rc_clnt_err
{
rc_clnt_err *next;
int4 pid;
};
GBLDEF int rc_size_return = 0;
GBLDEF UINTPTR_T rc_auxown = 0;
GBLDEF int rc_errno = 0;
GBLDEF int rc_nxact = 0;
GBLDEF int rc_nerrs = 0;
GBLDEF rof_struct *rc_overflow = (rof_struct *) 0;
GBLREF int history;
GBLREF int omi_pid;
static rc_op rc_dispatch_table[RC_OP_MAX] = {
0,
rc_prc_opnd,
rc_prc_clsd,
/* rc_prc_exch */ 0,
rc_prc_lock,
rc_prc_logn,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
rc_prc_getp,
rc_prc_getr,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
rc_prc_kill,
rc_prc_set,
rc_prc_setf,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* rc_prc_ntrx */ 0
};
int
rc_srvc_xact(cptr, xend)
omi_conn *cptr;
char *xend;
{
rc_xblk_hdr *fxhdr;
rc_q_hdr *qhdr;
rc_clnt_err *elst, *eptr;
rc_rsp_page *rpg;
char *cpte;
int rv, rqlen;
char *tptr;
int dumped = 0;
int pkt_len = (int)(xend - (char *) cptr);
/* Reserve space for the RC header in the response buffer */
fxhdr = (rc_xblk_hdr *) cptr->xptr;
cptr->xptr += SIZEOF(rc_xblk_hdr);
/* If true, this not a known RC block type */
if (fxhdr->method.value != RC_METHOD)
{
#ifdef DEBUG
gtcm_cpktdmp((char *)cptr, pkt_len,"Unknown RC block type.");
dumped = 1;
#endif
return -OMI_ER_PR_INVMSGFMT;
}
/* Check the endianism of the XBLK */
#ifdef LTL_END
if (fxhdr->big_endian.value)
return -OMI_ER_PR_INVMSGFMT;
#else /* defined(LTL_END) */
#ifdef BIG_END
if (!fxhdr->big_endian.value)
return -OMI_ER_PR_INVMSGFMT;
#else /* defined(BIG_END) */
return -OMI_ER_PR_INVMSGFMT;
#endif /* !defined(BIG_END) */
#endif /* !defined(LTL_END) */
/* Stash this for any lock operations */
rc_auxown = (UINTPTR_T)cptr;
/* This is the list of errors */
elst = (rc_clnt_err *) 0;
/* This is the offset of the first error Aq */
fxhdr->err_aq.value = 0;
tptr = cptr->xptr;
/* Loop through the requests in the XBLK */
for (qhdr = (rc_q_hdr *) 0; cptr->xptr < xend;)
{
qhdr = (rc_q_hdr *) tptr;
rqlen = qhdr->a.len.value;
if (history)
{
init_rc_hist(cptr->stats.id);
save_rc_req((char *)qhdr,qhdr->a.len.value);
}
rv = -1;
/* Check to see if this is a error'd PID, throw away packets
from these. */
/* 9/8/94 VTF: protocol change
* Process any LOCK/UNLOCK requests from an error'd PID
*/
for (eptr = elst; eptr; eptr = eptr->next)
if (eptr->pid == ((qhdr->r.pid1.value << 16) | qhdr->r.pid2.value)
&& qhdr->r.typ.value != RC_LOCK_NAMES)
break;
if (eptr)
qhdr->a.erc.value = RC_NETREQIGN;
/* Do we do this yet? */
else if ( /* (qhdr->r.typ.value < 0) || */ /* this is commented out as it always evaluates to FALSE */
(qhdr->r.typ.value > RC_OP_MAX )
|| (!rc_dispatch_table[qhdr->r.typ.value]))
{
#ifdef DEBUG
if (qhdr->r.typ.value == RC_EXCH_INFO)
{
dumped = 1;
OMI_DBG((omi_debug, "Note: Unsupported request type (ExchangeInfo)\n"));
}
else
{
gtcm_cpktdmp((char *)qhdr, qhdr->a.len.value, "Unknown request type.");
dumped = 1;
}
#endif
qhdr->a.erc.value = RC_NETERRNTIMPL;
}
/* Try it */
else
{
/*
* Calculate the size available for a response
* page
*/
if (qhdr->r.typ.value == RC_GET_PAGE
|| qhdr->r.typ.value == RC_GET_RECORD)
{
rc_size_return = (int4)((char *) fxhdr
+ fxhdr->end.value - RC_MIN_CPT_SIZ - (char *) qhdr
- SIZEOF(rc_rsp_page) + 1);
}
rc_overflow = cptr->of;
rc_errno = RC_SUCCESS;
if (fxhdr->free.value > fxhdr->end.value)
{
char msg[256];
SPRINTF(msg,"invalid packet : free (%x) > end (%x). Dumped RC header + packet",
fxhdr->free.value, fxhdr->end.value);
/*GTM64: Assuming length of packet wont excced MAX_INT */
gtcm_cpktdmp((char *)fxhdr, (int4)(((char *)xend) - ((char *)fxhdr)),msg);
if (history)
dump_omi_rq();
return -OMI_ER_PR_INVMSGFMT;
}
rv = (*rc_dispatch_table[qhdr->r.typ.value]) (qhdr);
if (fxhdr->free.value > fxhdr->end.value)
{
char msg[256];
char *p;
SPRINTF(msg,"corrupted packet, free (%x) > end.value (%x). Dumped RC header + packet",
fxhdr->free.value,fxhdr->end.value);
gtcm_cpktdmp((char *)fxhdr, (int)(((char *)xend) - ((char *)fxhdr)),msg);
p = (char *)-1L;
*p = 1; /*guarenteed core dump */
}
if (qhdr->a.len.value > fxhdr->end.value)
{
char msg[256];
char *p;
SPRINTF(msg,"corrupted packet, qhdr.a.len.value=%x > fxhdr end (%x). Dumped RC header + packet",
qhdr->a.len.value,fxhdr->end.value);
gtcm_cpktdmp((char *)qhdr, qhdr->a.len.value, msg);
p = (char *)-1L;
*p = 1; /*guarenteed core dump */
}
rc_nxact++;
if (rc_errno != RC_SUCCESS)
{
rc_nerrs++;
qhdr->a.erc.value = rc_errno;
rv = -1;
#ifdef DEBUG
{
char msg[256];
SPRINTF(msg,"RC error (0x%x).",rc_errno);
gtcm_cpktdmp((char *)qhdr, qhdr->a.len.value, msg);
dumped = 1;
}
#endif
}
}
/* Keep track of erroneous PIDs */
if (rv < 0)
{
/*
* OMI_DBG_STMP; OMI_DBG((omi_debug, "gtcm_server:
* rc_srvc_xct(error: %d)\n",
* qhdr->a.erc.value));
*/
#ifdef DEBUG
if (!dumped)
gtcm_cpktdmp((char *)qhdr, qhdr->a.len.value,
"RC Request returned error.");
dumped = 1;
#endif
eptr = (rc_clnt_err *) malloc(SIZEOF(rc_clnt_err));
eptr->pid = (qhdr->r.pid1.value << 16) | qhdr->r.pid2.value;
eptr->next = elst;
elst = eptr;
if (fxhdr->err_aq.value == 0)
fxhdr->err_aq.value = (char *) qhdr - (char *) fxhdr;
}
qhdr->r.typ.value |= 0x80;
if (history)
save_rc_rsp((char *)qhdr,qhdr->a.len.value);
/* Move to the next request */
cptr->xptr += rqlen;
tptr = (char *)qhdr;
tptr += RC_AQ_HDR;
if (qhdr->r.typ.value ==
(RC_GET_PAGE | 0x80) ||
qhdr->r.typ.value == (RC_GET_RECORD | 0x80))
break; /* Reads are always the last request in
* the buffer */
else {
if (cptr->xptr < xend)
{
/* ensure that the length of the next request
* actually fits into this XBLK
*/
assert(((rc_q_hdr *)(cptr->xptr))
->a.len.value <= xend - cptr->xptr);
memcpy(tptr, cptr->xptr, ((rc_q_hdr
*)(cptr->xptr))->a.len.value);
}
qhdr->a.len.value = RC_AQ_HDR;
}
}
/* Forget the erroneous PIDs */
if (elst)
{
for (eptr = elst->next; eptr; eptr = (elst = eptr)->next)
free(elst);
free(elst);
}
/*
* If true, there was an XBLK, so fill in some of the response
* fields
*/
/* There's no way that I can see to get to this point with a
null qhdr. */
if (qhdr)
{
fxhdr->last_aq.value = (char *) qhdr - (char *) fxhdr;
fxhdr->cpt_tab.value = ((char *) qhdr -
(char *) fxhdr) + qhdr->a.len.value;
fxhdr->cpt_siz.value = fxhdr->end.value - fxhdr->cpt_tab.value;
} else
{
fxhdr->last_aq.value = 0;
fxhdr->cpt_tab.value = fxhdr->free.value;
fxhdr->cpt_siz.value = fxhdr->end.value - fxhdr->cpt_tab.value;
}
if (fxhdr->free.value > fxhdr->end.value)
{
char msg[256];
SPRINTF(msg,"invalid packet : free (%x) > end (%x). Dumped RC header + packet",
fxhdr->free.value, fxhdr->end.value);
/*GTM64: Assuming length of packet wont excced MAX_INT */
gtcm_cpktdmp((char *)fxhdr, (int4)(((char *)xend) - ((char *)fxhdr)),msg);
if (history)
dump_omi_rq();
return -OMI_ER_PR_INVMSGFMT;
}
else if (fxhdr->cpt_tab.value > fxhdr->end.value)
{
char msg[256];
SPRINTF(msg,"invalid packet : cpt_tab (%x) > end (%x). Dumped RC header + packet",
fxhdr->cpt_tab.value, fxhdr->end.value);
/*GTM64: Assuming length of packet wont excced MAX_INT */
gtcm_cpktdmp((char *)fxhdr, (int)(((char *)xend) - ((char *)fxhdr)),msg);
if (history)
dump_omi_rq();
return -OMI_ER_PR_INVMSGFMT;
}
else if (fxhdr->cpt_tab.value + fxhdr->cpt_siz.value
> fxhdr->end.value)
{
char msg[256];
SPRINTF(msg,"invalid packet : cpt_tab + cpt_siz (%x) > end (%x). Dumped RC header + packet",
fxhdr->cpt_tab.value + fxhdr->cpt_siz.value,
fxhdr->end.value);
/*GTM64: Assuming length of packet wont excced MAX_INT */
gtcm_cpktdmp((char *)fxhdr, (int4)(((char *)xend) - ((char *)fxhdr)),msg);
if (history)
dump_omi_rq();
return -OMI_ER_PR_INVMSGFMT;
}
rc_send_cpt(fxhdr, (rc_rsp_page *) qhdr);
if (fxhdr->free.value > fxhdr->end.value)
{
char msg[256];
SPRINTF(msg,"invalid Aq packet : free (%x) > end (%x). Dumped RC header + packet",
fxhdr->free.value, fxhdr->end.value);
/*GTM64: Assuming length of packet wont excced MAX_INT */
gtcm_cpktdmp((char *)fxhdr, (int4)(((char *)xend) - ((char *)fxhdr)),msg);
if (history)
dump_omi_rq();
assert(fxhdr->free.value <= fxhdr->end.value);
return -OMI_ER_PR_INVMSGFMT;
}
return fxhdr->free.value;
}