moved netns code from daemon/src to netns at the top level, updated files to account for location change
This commit is contained in:
parent
e4a0069bc3
commit
d799390c4a
32 changed files with 14 additions and 14 deletions
509
netns/vnode_client.c
Normal file
509
netns/vnode_client.c
Normal file
|
@ -0,0 +1,509 @@
|
|||
/*
|
||||
* CORE
|
||||
* Copyright (c)2010-2012 the Boeing Company.
|
||||
* See the LICENSE file included in this distribution.
|
||||
*
|
||||
* author: Tom Goff <thomas.goff@boeing.com>
|
||||
*
|
||||
* vnode_client.c
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "vnode_chnl.h"
|
||||
#include "vnode_client.h"
|
||||
#include "vnode_tlv.h"
|
||||
#include "vnode_io.h"
|
||||
|
||||
|
||||
extern int verbose;
|
||||
|
||||
typedef struct {
|
||||
vnode_client_cmddonecb_t cmddonecb;
|
||||
void *data;
|
||||
} vnode_clientcmd_t;
|
||||
|
||||
vnode_client_cmdio_t *vnode_open_clientcmdio(vnode_client_cmdiotype_t iotype)
|
||||
{
|
||||
int err;
|
||||
vnode_client_cmdio_t *clientcmdio;
|
||||
|
||||
clientcmdio = malloc(sizeof(*clientcmdio));
|
||||
if (!clientcmdio)
|
||||
{
|
||||
WARN("malloc() failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
clientcmdio->iotype = iotype;
|
||||
|
||||
switch (clientcmdio->iotype)
|
||||
{
|
||||
case VCMD_IO_NONE:
|
||||
case VCMD_IO_FD:
|
||||
err = 0;
|
||||
break;
|
||||
|
||||
case VCMD_IO_PIPE:
|
||||
err = open_stdio_pipe(&clientcmdio->stdiopipe);
|
||||
break;
|
||||
|
||||
case VCMD_IO_PTY:
|
||||
err = open_stdio_pty(&clientcmdio->stdiopty);
|
||||
break;
|
||||
|
||||
default:
|
||||
WARNX("unknown i/o type: %u", clientcmdio->iotype);
|
||||
err = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (err)
|
||||
{
|
||||
free(clientcmdio);
|
||||
clientcmdio = NULL;
|
||||
}
|
||||
|
||||
return clientcmdio;
|
||||
}
|
||||
|
||||
void vnode_close_clientcmdio(vnode_client_cmdio_t *clientcmdio)
|
||||
{
|
||||
switch (clientcmdio->iotype)
|
||||
{
|
||||
case VCMD_IO_NONE:
|
||||
case VCMD_IO_FD:
|
||||
break;
|
||||
|
||||
case VCMD_IO_PIPE:
|
||||
close_stdio_pipe(&clientcmdio->stdiopipe);
|
||||
break;
|
||||
|
||||
case VCMD_IO_PTY:
|
||||
close_stdio_pty(&clientcmdio->stdiopty);
|
||||
break;
|
||||
|
||||
default:
|
||||
WARNX("unknown i/o type: %u", clientcmdio->iotype);
|
||||
break;
|
||||
}
|
||||
|
||||
memset(clientcmdio, 0, sizeof(*clientcmdio));
|
||||
free(clientcmdio);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void vnode_client_cmddone(vnode_cmdentry_t *cmd)
|
||||
{
|
||||
vnode_clientcmd_t *clientcmd = cmd->data;;
|
||||
|
||||
if (clientcmd->cmddonecb)
|
||||
clientcmd->cmddonecb(cmd->cmdid, cmd->pid, cmd->status, clientcmd->data);
|
||||
|
||||
memset(clientcmd, 0, sizeof(*clientcmd));
|
||||
free(clientcmd);
|
||||
|
||||
memset(cmd, 0, sizeof(*cmd));
|
||||
free(cmd);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int tlv_cmdreqack_cmdid(vnode_tlv_t *tlv, void *data)
|
||||
{
|
||||
vnode_cmdreqack_t *cmdreqack = data;
|
||||
int tmp;
|
||||
|
||||
assert(tlv->type == VNODE_TLV_CMDID);
|
||||
|
||||
tmp = tlv_int32(&cmdreqack->cmdid, tlv);
|
||||
|
||||
if (tmp == 0 && verbose)
|
||||
INFO("VNODE_TLV_CMDID: %d", cmdreqack->cmdid);
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static int tlv_cmdreqack_cmdpid(vnode_tlv_t *tlv, void *data)
|
||||
{
|
||||
vnode_cmdreqack_t *cmdreqack = data;
|
||||
int tmp;
|
||||
|
||||
assert(tlv->type == VNODE_TLV_CMDPID);
|
||||
|
||||
tmp = tlv_int32(&cmdreqack->pid, tlv);
|
||||
|
||||
if (tmp == 0 && verbose)
|
||||
INFO("VNODE_TLV_CMDPID: %d", cmdreqack->pid);
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static void vnode_clientrecv_cmdreqack(vnode_msgio_t *msgio)
|
||||
{
|
||||
vnode_cmdentry_t *cmd;
|
||||
vnode_client_t *client = msgio->data;
|
||||
vnode_cmdreqack_t cmdreqack = CMDREQACK_INIT;
|
||||
static const vnode_tlvhandler_t tlvhandler[VNODE_TLV_MAX] = {
|
||||
[VNODE_TLV_CMDID] = tlv_cmdreqack_cmdid,
|
||||
[VNODE_TLV_CMDPID] = tlv_cmdreqack_cmdpid,
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
WARNX("command request ack");
|
||||
#endif
|
||||
|
||||
assert(msgio->msgbuf.msg->hdr.type == VNODE_MSG_CMDREQACK);
|
||||
|
||||
if (vnode_parsemsg(msgio->msgbuf.msg, &cmdreqack, tlvhandler))
|
||||
return;
|
||||
|
||||
TAILQ_FOREACH(cmd, &client->cmdlisthead, entries)
|
||||
if (cmd->cmdid == cmdreqack.cmdid)
|
||||
break;
|
||||
|
||||
if (cmd == NULL)
|
||||
{
|
||||
WARNX("cmdid %d not found in command list", cmdreqack.cmdid);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
WARNX("cmdid %d found in cmd list", cmdreqack.cmdid);
|
||||
#endif
|
||||
|
||||
cmd->pid = cmdreqack.pid;
|
||||
|
||||
if (cmdreqack.pid == -1)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
WARNX("XXX pid == -1 removing cmd from list");
|
||||
#endif
|
||||
TAILQ_REMOVE(&client->cmdlisthead, cmd, entries);
|
||||
|
||||
cmd->status = -1;
|
||||
vnode_client_cmddone(cmd);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int tlv_cmdstatus_cmdid(vnode_tlv_t *tlv, void *data)
|
||||
{
|
||||
vnode_cmdstatus_t *cmdstatus = data;
|
||||
int tmp;
|
||||
|
||||
assert(tlv->type == VNODE_TLV_CMDID);
|
||||
|
||||
tmp = tlv_int32(&cmdstatus->cmdid, tlv);
|
||||
|
||||
if (tmp == 0 && verbose)
|
||||
INFO("VNODE_TLV_CMDID: %d", cmdstatus->cmdid);
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static int tlv_cmdstatus_status(vnode_tlv_t *tlv, void *data)
|
||||
{
|
||||
vnode_cmdstatus_t *cmdstatus = data;
|
||||
int tmp;
|
||||
|
||||
assert(tlv->type == VNODE_TLV_CMDSTATUS);
|
||||
|
||||
tmp = tlv_int32(&cmdstatus->status, tlv);
|
||||
|
||||
if (tmp == 0 && verbose)
|
||||
INFO("VNODE_TLV_CMDSTATUS: %d", cmdstatus->status);
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static void vnode_clientrecv_cmdstatus(vnode_msgio_t *msgio)
|
||||
{
|
||||
vnode_cmdentry_t *cmd;
|
||||
vnode_client_t *client = msgio->data;
|
||||
vnode_cmdstatus_t cmdstatus = CMDSTATUS_INIT;
|
||||
static const vnode_tlvhandler_t tlvhandler[VNODE_TLV_MAX] = {
|
||||
[VNODE_TLV_CMDID] = tlv_cmdstatus_cmdid,
|
||||
[VNODE_TLV_CMDSTATUS] = tlv_cmdstatus_status,
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
WARNX("command status");
|
||||
#endif
|
||||
|
||||
assert(msgio->msgbuf.msg->hdr.type == VNODE_MSG_CMDSTATUS);
|
||||
|
||||
if (vnode_parsemsg(msgio->msgbuf.msg, &cmdstatus, tlvhandler))
|
||||
return;
|
||||
|
||||
TAILQ_FOREACH(cmd, &client->cmdlisthead, entries)
|
||||
if (cmd->cmdid == cmdstatus.cmdid)
|
||||
break;
|
||||
|
||||
if (cmd == NULL)
|
||||
{
|
||||
WARNX("cmdid %d not found in command list", cmdstatus.cmdid);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
WARNX("cmdid %d found in cmd list; removing", cmdstatus.cmdid);
|
||||
#endif
|
||||
TAILQ_REMOVE(&client->cmdlisthead, cmd, entries);
|
||||
|
||||
cmd->status = cmdstatus.status;
|
||||
vnode_client_cmddone(cmd);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void server_ioerror(vnode_msgio_t *msgio)
|
||||
{
|
||||
vnode_client_t *client = msgio->data;
|
||||
|
||||
#ifdef DEBUG
|
||||
WARNX("i/o error on fd %d; client: %p", msgio->fd, client);
|
||||
#endif
|
||||
|
||||
if (client)
|
||||
{
|
||||
assert(msgio == &client->msgio);
|
||||
if (client->ioerrorcb)
|
||||
client->ioerrorcb(client);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
vnode_client_t *vnode_client(struct ev_loop *loop, const char *ctrlchnlname,
|
||||
vnode_clientcb_t ioerrorcb, void *data)
|
||||
{
|
||||
int fd = -1;
|
||||
vnode_client_t *client;
|
||||
static const vnode_msghandler_t msghandler[VNODE_MSG_MAX] = {
|
||||
[VNODE_MSG_CMDREQACK] = vnode_clientrecv_cmdreqack,
|
||||
[VNODE_MSG_CMDSTATUS] = vnode_clientrecv_cmdstatus,
|
||||
};
|
||||
|
||||
if (!ioerrorcb)
|
||||
{
|
||||
WARNX("no i/o error callback given");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fd = vnode_connect(ctrlchnlname);
|
||||
if (fd < 0)
|
||||
{
|
||||
WARN("vnode_connect() failed for '%s'", ctrlchnlname);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((client = calloc(1, sizeof(*client))) == NULL)
|
||||
{
|
||||
WARN("calloc() failed");
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TAILQ_INIT(&client->cmdlisthead);
|
||||
client->loop = loop;
|
||||
client->serverfd = fd;
|
||||
client->ioerrorcb = ioerrorcb;
|
||||
client->data = data;
|
||||
|
||||
if (vnode_msgiostart(&client->msgio, client->loop,
|
||||
client->serverfd, client, server_ioerror, msghandler))
|
||||
{
|
||||
WARNX("vnode_msgiostart() failed");
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
WARNX("new client connected to %s: %p", ctrlchnlname, client);
|
||||
#endif
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
void vnode_delclient(vnode_client_t *client)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
WARNX("deleting client: %p", client);
|
||||
#endif
|
||||
|
||||
vnode_msgiostop(&client->msgio);
|
||||
if (client->serverfd >= 0)
|
||||
{
|
||||
close(client->serverfd);
|
||||
client->serverfd = -1;
|
||||
}
|
||||
|
||||
while (!TAILQ_EMPTY(&client->cmdlisthead))
|
||||
{
|
||||
vnode_cmdentry_t *cmd;
|
||||
|
||||
cmd = TAILQ_FIRST(&client->cmdlisthead);
|
||||
TAILQ_REMOVE(&client->cmdlisthead, cmd, entries);
|
||||
|
||||
cmd->status = -1;
|
||||
vnode_client_cmddone(cmd);
|
||||
}
|
||||
|
||||
/* XXX more stuff ?? */
|
||||
|
||||
memset(client, 0, sizeof(*client));
|
||||
free(client);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int vnode_setcmdio(int *cmdin, int *cmdout, int *cmderr,
|
||||
vnode_client_cmdio_t *clientcmdio)
|
||||
{
|
||||
switch (clientcmdio->iotype)
|
||||
{
|
||||
case VCMD_IO_NONE:
|
||||
*cmdin = -1;
|
||||
*cmdout = -1;
|
||||
*cmderr = -1;
|
||||
break;
|
||||
|
||||
case VCMD_IO_FD:
|
||||
*cmdin = clientcmdio->stdiofd.infd;
|
||||
*cmdout = clientcmdio->stdiofd.outfd;
|
||||
*cmderr = clientcmdio->stdiofd.errfd;
|
||||
break;
|
||||
|
||||
case VCMD_IO_PIPE:
|
||||
*cmdin = clientcmdio->stdiopipe.infd[0];
|
||||
*cmdout = clientcmdio->stdiopipe.outfd[1];
|
||||
*cmderr = clientcmdio->stdiopipe.errfd[1];
|
||||
break;
|
||||
|
||||
case VCMD_IO_PTY:
|
||||
*cmdin = clientcmdio->stdiopty.slavefd;
|
||||
*cmdout = clientcmdio->stdiopty.slavefd;
|
||||
*cmderr = clientcmdio->stdiopty.slavefd;
|
||||
break;
|
||||
|
||||
default:
|
||||
WARNX("unknown i/o type: %u", clientcmdio->iotype);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void vnode_cleanupcmdio(vnode_client_cmdio_t *clientcmdio)
|
||||
{
|
||||
#define CLOSE(var) \
|
||||
do { \
|
||||
if (var >= 0) \
|
||||
close(var); \
|
||||
var = -1; \
|
||||
} while (0)
|
||||
|
||||
switch (clientcmdio->iotype)
|
||||
{
|
||||
case VCMD_IO_NONE:
|
||||
case VCMD_IO_FD:
|
||||
break;
|
||||
|
||||
case VCMD_IO_PIPE:
|
||||
CLOSE(clientcmdio->stdiopipe.infd[0]);
|
||||
CLOSE(clientcmdio->stdiopipe.outfd[1]);
|
||||
CLOSE(clientcmdio->stdiopipe.errfd[1]);
|
||||
break;
|
||||
|
||||
case VCMD_IO_PTY:
|
||||
CLOSE(clientcmdio->stdiopty.slavefd);
|
||||
break;
|
||||
|
||||
default:
|
||||
WARNX("unknown i/o type: %u", clientcmdio->iotype);
|
||||
break;
|
||||
}
|
||||
|
||||
#undef CLOSE
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int vnode_client_cmdreq(vnode_client_t *client,
|
||||
vnode_client_cmdio_t *clientcmdio,
|
||||
vnode_client_cmddonecb_t cmddonecb, void *data,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
int cmdin, cmdout, cmderr;
|
||||
vnode_clientcmd_t *clientcmd;
|
||||
vnode_cmdentry_t *cmd;
|
||||
|
||||
if (argc >= VNODE_ARGMAX)
|
||||
{
|
||||
WARNX("too many command arguments");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (argv[argc] != NULL)
|
||||
{
|
||||
WARNX("command arguments not null-terminated");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (vnode_setcmdio(&cmdin, &cmdout, &cmderr, clientcmdio))
|
||||
{
|
||||
WARNX("vnode_setcmdio() failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((clientcmd = malloc(sizeof(*clientcmd))) == NULL)
|
||||
{
|
||||
WARN("malloc() failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
clientcmd->cmddonecb = cmddonecb;
|
||||
clientcmd->data = data;
|
||||
|
||||
if ((cmd = malloc(sizeof(*cmd))) == NULL)
|
||||
{
|
||||
WARN("malloc() failed");
|
||||
free(clientcmd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (client->cmdid < 0)
|
||||
client->cmdid = 0;
|
||||
cmd->cmdid = client->cmdid++;
|
||||
cmd->pid = -1;
|
||||
cmd->status = -1;
|
||||
cmd->data = clientcmd;
|
||||
|
||||
TAILQ_INSERT_TAIL(&client->cmdlisthead, cmd, entries);
|
||||
|
||||
if (vnode_send_cmdreq(client->serverfd, cmd->cmdid,
|
||||
argv, cmdin, cmdout, cmderr))
|
||||
{
|
||||
WARN("vnode_send_cmdreq() failed");
|
||||
TAILQ_REMOVE(&client->cmdlisthead, cmd, entries);
|
||||
free(clientcmd);
|
||||
free(cmd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
vnode_cleanupcmdio(clientcmdio);
|
||||
|
||||
return cmd->cmdid;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue