/*
**************************************************************************
*
* Component: RDBG
* Module: servcon.c
*
* Synopsis: Management of RPC client connections.
*
**************************************************************************
*/
#include <sys/errno.h>
#include <rdbg/rdbg.h>
#include <rdbg/servrpc.h>
/*
* ConnCreate - create a new connection entry for a client.
*
* This function finds an empty entry in the connection array
* or makes space. It fills in the fields that are passed to it.
* It does not do any validation on net addresses nor does it
* start a validation cycle on other clients. This is done by
* the caller.
*/
int
ConnCreate (struct svc_req* rqstp, open_in* in)
{
NET_OPAQUE sender;
int idx;
CONN_LIST* clst;
setErrno (0);
/* Convert to valid Net address */
if (! TspTranslateRpcAddr (rqstp, &sender)) {
DPRINTF (("ConnCreate: TspTranslateRpcAddr failed\n"));
return -1;
}
if (! TspValidateAddr ((NET_OPAQUE*) in->back_port, &sender)) {
DPRINTF (("ConnCreate: TspValidateAddr failed\n"));
return -1; /* errno now setup with error */
}
/* look for an empty connection entry */
for (idx = 0; idx < conn_list_cnt; idx++) {
if (!conn_list[idx].in_use)
break; /* an empty one found */
}
if (idx >= conn_list_cnt) { /* no empties, create space */
CONN_LIST* tmp_conn_list = conn_list;
conn_list_cnt += CONN_LIST_INC;
if (conn_list) {
conn_list = (CONN_LIST *) Realloc (conn_list, /* extend */
conn_list_cnt * sizeof (CONN_LIST));
} else {
conn_list = (CONN_LIST *)Malloc(conn_list_cnt * sizeof(CONN_LIST));
}
if (!conn_list) { /* unable to get space */
if ((conn_list_cnt -= CONN_LIST_INC)) {
/* was realloc, restore space */
conn_list = tmp_conn_list;
}
return -1; /* errno set by failed alloc */
}
/* clear newly created memory */
memset (conn_list + idx, 0, CONN_LIST_INC * sizeof (CONN_LIST));
} else { /* clear new entry */
memset (conn_list + idx, 0, sizeof (CONN_LIST));
}
clst = conn_list + idx;
clst->in_use = True; /* now in use */
clst->sender = sender;
memcpy (&clst->back_port, &in->back_port, sizeof (NET_OPAQUE));
memcpy (&clst->route, &in->destination, sizeof (NET_OPAQUE));
clst->debug_type = (UCHAR) in->debug_type;
clst->flags = in->flags;
strncpy (clst->user_name, in->user_name, NAMEMAX-1);
clst->user_name [NAMEMAX-1] = 0;
return idx;
}
/*
* ConnDelete - remove connection entry when shutdown.
*
*/
void
ConnDelete (int conn, struct svc_req* rqstp, close_control control)
{
CONN_LIST* clst = conn_list + conn;
int idx;
Boolean prim;
if (! clst->in_use) return; /* not active */
for (idx = 0; idx < pid_list_cnt; idx++) {
PID_LIST* plst = pid_list + idx;
if (! PIDMAP_TEST (conn, idx)) continue;
/* found a controlled pid */
prim = (plst->primary_conn == conn) ? True : False;
TgtDetachCon (conn, idx, True);
/* if still running or alive, we use close control on it */
if (! plst->pid)
continue; /* entry gone */
if (prim && control == CLOSE_KILL) {
/* kill off process */
TgtKillAndDelete (plst, rqstp, True);
} else if (! plst->owners) {
/* no owners left */
if (control == CLOSE_DETACH) {
TgtKillAndDelete (plst, rqstp, False);
}
if (control == CLOSE_DETACH || PROC_TERMINATED (plst)) {
TgtDelete (plst, conn, (control==CLOSE_DETACH) ?
BMSG_DETACH : 0);
}
}
}
if (clst->list) {
Free (clst->list); /* free allocated memory */
}
DPRINTF (("ConnDelete: Connection closed for port %u\n",
HL_W(*((UINT16*) &clst->back_port.c[2]))));
clst->in_use = False; /* free it back */
}