2171 lines
64 KiB
C
2171 lines
64 KiB
C
|
|
/*
|
|
******************************************************************************
|
|
* INTERPEAK SOURCE FILE
|
|
*
|
|
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmip_cli.c,v $ $Revision: 1.23.10.4 $
|
|
* $Source: /home/interpeak/CVSRoot/ipmip/src/ipmip_cli.c,v $
|
|
* $Author: jsheng $
|
|
* $State: Exp $ $Locker: $
|
|
*
|
|
* INTERPEAK_COPYRIGHT_STRING
|
|
* Design and implementation by Joel Hortelius <joel.hortelis@interpeak.se>
|
|
******************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 1 DESCRIPTION
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 2 CONFIGURATION
|
|
****************************************************************************
|
|
*/
|
|
|
|
#include "ipmip_config.h"
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 3 INCLUDE FILES
|
|
****************************************************************************
|
|
*/
|
|
|
|
#define IPCOM_USE_CLIB_PROTO
|
|
#include <ipcom_clib.h>
|
|
#include <ipcom_clib2.h>
|
|
#include <ipcom_err.h>
|
|
#include <ipcom_inet.h>
|
|
#include <ipcom_ipd.h>
|
|
#include <ipcom_list.h>
|
|
#include <ipcom_hash.h>
|
|
#include <ipcom_os.h>
|
|
#include <ipcom_sock.h>
|
|
#include <ipcom_sock.h>
|
|
#include <ipcom_sock2.h>
|
|
#include <ipcom_sysctl.h>
|
|
#include <ipcom_syslog.h>
|
|
#include <ipcom_sysvar.h>
|
|
#include <ipcom_cmd.h>
|
|
#include <ipcom_getopt.h>
|
|
|
|
|
|
#include <ipmip.h>
|
|
#include <private/ipmip_util.h>
|
|
#include <private/ipmip_buffer.h>
|
|
#include <private/ipmip_context.h>
|
|
#include <private/ipmip_cli.h>
|
|
#include <private/ipmip_util.h>
|
|
#include <private/ipmip_sysvar.h>
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 4 DEFINES
|
|
****************************************************************************
|
|
*/
|
|
#define IPCOM_SYSLOG_PRIORITY IPCOM_LOG_DEBUG2
|
|
#define IPCOM_SYSLOG_FACILITY IPCOM_LOG_IPMIP
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 5 TYPES
|
|
****************************************************************************
|
|
*/
|
|
typedef struct Ipmip_cli_client_mcast
|
|
{
|
|
Ipcom_list next;
|
|
Ip_u32 channel;
|
|
} Ipmip_cli_client_mcast_t;
|
|
|
|
typedef struct Ipmip_cli_client
|
|
{
|
|
Ipcom_list next;
|
|
Ipcom_block block;
|
|
Ipmip_proc_t *proc;
|
|
|
|
/**/
|
|
Ipmip_cli_message_t *request;
|
|
Ip_fd fd;
|
|
|
|
/* Connection information */
|
|
union Ip_sockaddr_union conn_local;
|
|
union Ip_sockaddr_union conn_remote;
|
|
|
|
Ipmip_cli_context_t *cli;
|
|
Ipmip_cli_ident_t ident;
|
|
|
|
Ipcom_list replies;
|
|
Ipcom_list mcasts;
|
|
} Ipmip_cli_client_t;
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 6 EXTERN PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 7 LOCAL PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 8 DATA
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 9 STATIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
IP_STATIC void
|
|
ipmip_cli_config_name_print(Ipmip_proc_t *proc,
|
|
Ipmip_cli_daemon_t *daemon,
|
|
const char *name)
|
|
{
|
|
Ipmip_cli_daemon_req_t req;
|
|
Ipmip_attr_iter_t riter;
|
|
|
|
IPMIP_UNUSED_PARAMETER(proc);
|
|
|
|
ipmip_cli_daemon_request_init(&req);
|
|
if (ipmip_cli_config_list(daemon, &req, name) == IPCOM_SUCCESS)
|
|
{
|
|
const char *cfg;
|
|
|
|
/**/
|
|
ipmip_cli_daemon_iter_request_init(&req, &riter);
|
|
while ((cfg = ipmip_cli_config_next(&riter)) != IP_NULL)
|
|
ipcom_printf("%s"IP_LF, cfg);
|
|
}
|
|
|
|
ipmip_cli_daemon_request_release(&req);
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip_cli_context_client_free
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC void
|
|
ipmip_cli_context_client_free(Ipmip_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
Ipmip_cli_client_t *client)
|
|
{
|
|
Ipmip_cli_message_t *reply;
|
|
Ipcom_list *n;
|
|
|
|
if (client->request)
|
|
ipmip_cli_message_free(ctx, proc, client->request);
|
|
|
|
if (client->fd != IP_INVALID_SOCKET)
|
|
ipcom_socketclose(client->fd);
|
|
|
|
/* Free any non-processed replies */
|
|
while ((reply = IPCOM_LIST_FIRST(&client->replies)) != IP_NULL)
|
|
{
|
|
ipcom_list_remove(&reply->next);
|
|
ipmip_cli_message_free(ctx, proc, reply);
|
|
}
|
|
|
|
while ((n = IPCOM_LIST_FIRST(&client->mcasts)) != IP_NULL)
|
|
{
|
|
ipcom_list_remove(n);
|
|
ipcom_free(n);
|
|
}
|
|
|
|
ipcom_block_delete(&client->block);
|
|
ipcom_free(client);
|
|
}
|
|
|
|
IP_STATIC int
|
|
ipmip_cli_read_data(Ip_fd fd,
|
|
Ipmip_buffer_t *rbuf,
|
|
struct Ip_timeval *tv,
|
|
Ip_size_t sz)
|
|
{
|
|
int ret;
|
|
|
|
if (ipmip_buffer_reserve(rbuf, sz) == IP_FALSE)
|
|
return -IP_ERRNO_ENOMEM;
|
|
|
|
if (tv == IP_NULL)
|
|
{
|
|
for (; sz > 0;)
|
|
{
|
|
ret = ipcom_recv(fd, IPMIP_BUFFER_CURRENT(rbuf), sz, 0);
|
|
if (ret < 0)
|
|
return -ipcom_errno;
|
|
else if (ret == 0)
|
|
return -IP_ERRNO_ENOTCONN;
|
|
|
|
/* Append */
|
|
ipmip_buffer_append(rbuf, IP_NULL, ret);
|
|
sz -= ret;
|
|
}
|
|
|
|
ip_assert(sz == 0);
|
|
}
|
|
else
|
|
{
|
|
for (; sz > 0;)
|
|
{
|
|
Ip_fd_set rset;
|
|
|
|
/* Clear it */
|
|
IP_FD_ZERO(&rset);
|
|
|
|
/* Add the client socket */
|
|
IP_FD_SET(fd, &rset);
|
|
|
|
ret = ipcom_socketselect(fd + 1, &rset, IP_NULL, IP_NULL, tv);
|
|
if (ret == 0)
|
|
return sz;
|
|
|
|
ret = ipcom_recv(fd, IPMIP_BUFFER_CURRENT(rbuf), sz, IP_MSG_DONTWAIT);
|
|
if (ret <= 0)
|
|
{
|
|
if (ret < 0)
|
|
{
|
|
if (ipcom_errno != IP_ERRNO_EAGAIN && ipcom_errno != IP_ERRNO_EWOULDBLOCK)
|
|
return -ipcom_errno;
|
|
continue;
|
|
}
|
|
|
|
/* EOF */
|
|
return -IP_ERRNO_ENOTCONN;
|
|
}
|
|
|
|
/* Append */
|
|
ipmip_buffer_append(rbuf, IP_NULL, ret);
|
|
sz -= ret;
|
|
}
|
|
}
|
|
|
|
return sz;
|
|
}
|
|
|
|
IP_STATIC int
|
|
ipmip_cli_recvmsg(Ip_fd fd,
|
|
Ipmip_buffer_t *rbuf,
|
|
struct Ip_timeval *tv)
|
|
{
|
|
struct Ipmip_attr_header *hdr;
|
|
Ip_size_t hdr_sz = IPMIP_BUFFER_SIZE(rbuf);
|
|
Ip_size_t msg_sz = 0;
|
|
int ret = 0;
|
|
|
|
/* Already have a complete message? */
|
|
if (hdr_sz >= IPMIP_ATTR_HDR_LENGTH(0))
|
|
{
|
|
Ip_u32 sz;
|
|
|
|
hdr = (struct Ipmip_attr_header *)IPMIP_BUFFER_DATA(rbuf);
|
|
sz = IPMIP_ATTR_HDR_SIZE(hdr);
|
|
if (sz == hdr_sz)
|
|
{
|
|
/* Must Truncate */
|
|
ipmip_buffer_shrink(rbuf, 0);
|
|
hdr_sz = IPMIP_ATTR_HDR_LENGTH(0);
|
|
}
|
|
else
|
|
{
|
|
/* Have some data to read still */
|
|
msg_sz = sz - hdr_sz;
|
|
hdr_sz = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Must read header */
|
|
hdr_sz = IPMIP_ATTR_HDR_LENGTH(0) - hdr_sz;
|
|
}
|
|
|
|
if (hdr_sz)
|
|
{
|
|
if ((ret = ipmip_cli_read_data(fd, rbuf, tv, hdr_sz)) != 0)
|
|
return ret;
|
|
|
|
hdr = (struct Ipmip_attr_header *)IPMIP_BUFFER_DATA(rbuf);
|
|
msg_sz = IPMIP_ATTR_HDR_PAYLOAD(hdr);
|
|
}
|
|
|
|
if (msg_sz)
|
|
ret = ipmip_cli_read_data(fd, rbuf, tv, msg_sz);
|
|
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip_cli_senddata
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC int
|
|
ipmip_cli_senddata(Ipmip_cli_client_t *client,
|
|
Ipmip_cli_message_t *request)
|
|
{
|
|
for (;;)
|
|
{
|
|
int remain = IPMIP_BUFFER_SIZE(&request->message) - request->remain;
|
|
int rsize = IP_MIN(remain, 1500);
|
|
int ret;
|
|
|
|
if (rsize == 0)
|
|
return 0;
|
|
|
|
rsize = IP_MIN(rsize, 1500);
|
|
|
|
ret = ipcom_send(client->fd,
|
|
ipmip_buffer_offset(&request->message, request->remain),
|
|
rsize,
|
|
IP_MSG_DONTWAIT);
|
|
|
|
if (ret < 0)
|
|
{
|
|
if (ipcom_errno == IP_ERRNO_EAGAIN && ipcom_errno == IP_ERRNO_EWOULDBLOCK)
|
|
return remain;
|
|
return ret;
|
|
}
|
|
|
|
request->remain += ret;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip_cli_sendreply
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC void
|
|
ipmip_cli_sendreply(Ipmip_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
Ipmip_cli_client_t *client,
|
|
Ipmip_cli_message_t *request)
|
|
{
|
|
if(IP_NULL == request)
|
|
return;
|
|
|
|
/* Put it last in the list */
|
|
(void)ipcom_block_wait(client->block, -1);
|
|
|
|
if (IPCOM_LIST_FIRST(&client->replies) == IP_NULL)
|
|
{
|
|
int ret = ipmip_cli_senddata(client, request);
|
|
if (ret == 0)
|
|
{
|
|
ipcom_block_post(client->block);
|
|
ipmip_cli_message_free(ctx, proc, request);
|
|
return;
|
|
}
|
|
}
|
|
|
|
ipcom_list_insert_last(&client->replies, &request->next);
|
|
ipcom_block_post(client->block);
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip_cli_client_loop
|
|
*===========================================================================
|
|
* Description:
|
|
*
|
|
*/
|
|
IP_STATIC void
|
|
ipmip_cli_client_loop(Ipmip_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
Ipmip_cli_client_t *client)
|
|
{
|
|
struct Ip_timeval nw;
|
|
nw.tv_sec = 0;
|
|
nw.tv_usec = 0;
|
|
|
|
/*********** tick loop ***********/
|
|
for (; proc->quit != IP_TRUE;)
|
|
{
|
|
Ip_fd_set rset;
|
|
Ip_fd_set wset;
|
|
int ret;
|
|
struct Ip_timeval tv;
|
|
|
|
if (client->request == IP_NULL)
|
|
{
|
|
client->request = ipmip_cli_message_alloc(&client->ident);
|
|
if (client->request == IP_NULL)
|
|
return;
|
|
}
|
|
|
|
/* Clear it */
|
|
IP_FD_ZERO(&rset);
|
|
IP_FD_ZERO(&wset);
|
|
|
|
(void)ipcom_block_wait(client->block, -1);
|
|
|
|
/* Add the client socket */
|
|
IP_FD_SET(client->fd, &rset);
|
|
|
|
/**/
|
|
if (IPCOM_LIST_FIRST(&client->replies) != IP_NULL)
|
|
IP_FD_SET(client->fd, &wset);
|
|
|
|
|
|
ipcom_block_post(client->block);
|
|
|
|
tv.tv_sec = 0;
|
|
tv.tv_usec = 200 * 1000;
|
|
ret = ipcom_socketselect(client->fd + 1, &rset, &wset, IP_NULL, &tv);
|
|
|
|
/* Timeout */
|
|
if (ret == 0)
|
|
continue;
|
|
else if (ret < 0)
|
|
{
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
(void)ipcom_block_wait(client->block, -1);
|
|
if (IP_FD_ISSET(client->fd, &wset))
|
|
{
|
|
Ipmip_cli_message_t *request;
|
|
|
|
/* Need to send */
|
|
while ((request = IPCOM_LIST_FIRST(&client->replies)) != IP_NULL)
|
|
{
|
|
ret = ipmip_cli_senddata(client, request);
|
|
|
|
if (ret != 0)
|
|
break;
|
|
|
|
ipcom_list_remove(&request->next);
|
|
ipmip_cli_message_free(ctx, proc, request);
|
|
}
|
|
}
|
|
ipcom_block_post(client->block);
|
|
|
|
if (ret < 0)
|
|
break;
|
|
|
|
if (IP_FD_ISSET(client->fd, &rset))
|
|
{
|
|
if ((ret = ipmip_cli_recvmsg(client->fd, &client->request->request, &nw)) < 0)
|
|
break;
|
|
|
|
if (ret == 0)
|
|
{
|
|
struct Ipmip_attr_header *hdr = (struct Ipmip_attr_header*)IPMIP_BUFFER_DATA(&client->request->request);
|
|
|
|
/**/
|
|
if (IPMIP_ATTR_HDR_SYSTEM(hdr) != client->cli->subsystem)
|
|
ret = -IP_ERRNO_EINVAL;
|
|
else
|
|
{
|
|
if (ctx->cli->busy)
|
|
ret = -IP_ERRNO_EBUSY;
|
|
else
|
|
{
|
|
if (IPMIP_ATTR_HDR_TYPE(hdr) == IPMIP_CLI_TYPE_MULTICAST_ADD || IPMIP_ATTR_HDR_TYPE(hdr) == IPMIP_CLI_TYPE_MULTICAST_DEL)
|
|
{
|
|
struct Ipmip_attr *attr = IPMIP_ATTR_HDR_DATA(hdr);
|
|
Ip_size_t attrlen = IPMIP_ATTR_HDR_PAYLOAD(hdr);
|
|
|
|
while (IPMIP_ATTR_OK(attr, (int)attrlen))
|
|
{
|
|
if (IPMIP_ATTR_TYPE(attr) == IPMIP_CLI_MULTICAST_ATTR_CHANNEL && IPMIP_ATTR_PAYLOAD(attr) == sizeof(Ip_u32))
|
|
{
|
|
Ipmip_cli_client_mcast_t *mc;
|
|
Ip_u32 channel = IP_GET_NTOHL(IPMIP_ATTR_DATA(attr));
|
|
|
|
ipcom_mutex_lock(client->cli->lock);
|
|
|
|
for (mc = IPCOM_LIST_FIRST(&client->mcasts); mc != IP_NULL; mc = IPCOM_LIST_NEXT(&mc->next))
|
|
if (mc->channel == channel)
|
|
break;
|
|
|
|
if (IPMIP_ATTR_HDR_TYPE(hdr) == IPMIP_CLI_TYPE_MULTICAST_ADD)
|
|
{
|
|
if (mc == IP_NULL)
|
|
{
|
|
mc = ipcom_calloc(1, sizeof(*mc));
|
|
if(IP_NULL == mc)
|
|
{
|
|
ipcom_mutex_unlock(client->cli->lock);
|
|
return;
|
|
}
|
|
mc->channel = channel;
|
|
ipcom_list_insert_last(&client->mcasts, &mc->next);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (mc != IP_NULL)
|
|
{
|
|
ipcom_list_remove(&mc->next);
|
|
ipcom_free(mc);
|
|
}
|
|
}
|
|
|
|
ipcom_mutex_unlock(client->cli->lock);
|
|
}
|
|
|
|
attr = IPMIP_ATTR_NEXT(attr, attrlen);
|
|
}
|
|
|
|
/* If we have a reply header; terminate it */
|
|
ipmip_attr_hdr_finalize(&client->request->message,
|
|
ipmip_attr_hdr_ack_create(&client->request->message,
|
|
IPMIP_ATTR_HDR_SYSTEM(hdr),
|
|
IPMIP_ATTR_HDR_SEQUENCE(hdr),
|
|
IPMIP_ATTR_HDR_TYPE(hdr)));
|
|
ipmip_cli_sendreply(ctx, proc, client, client->request);
|
|
}
|
|
else
|
|
{
|
|
/* Provide the opaque parameter */
|
|
client->request->opaque = client->cli->opaque;
|
|
|
|
/* Invoke the callback */
|
|
ret = (*client->cli->callback) (ctx,
|
|
proc,
|
|
client->request);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (ret < 0)
|
|
{
|
|
/* Reuse the buffer */
|
|
ipmip_buffer_assign(&client->request->message, &client->request->request);
|
|
|
|
/* Clear data */
|
|
ipmip_buffer_shrink(&client->request->message, 0);
|
|
|
|
/* Create the error message */
|
|
ipmip_attr_hdr_finalize(&client->request->message,
|
|
ipmip_attr_hdr_err_create(&client->request->message,
|
|
IPMIP_ATTR_HDR_SYSTEM(hdr),
|
|
IPMIP_ATTR_HDR_SEQUENCE(hdr),
|
|
IPMIP_ATTR_HDR_TYPE(hdr),
|
|
-ret,
|
|
ipcom_strerror(-ret)));
|
|
|
|
/* Send it */
|
|
ipmip_cli_sendreply(ctx, proc, client, client->request);
|
|
}
|
|
|
|
/* No longer ours */
|
|
client->request = IP_NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip_cli_start_client
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ip_bool
|
|
ipmip_cli_start_client(struct Ipmip_context *ctx,
|
|
struct Ipmip_proc *proc,
|
|
Ipmip_cli_context_t *cli,
|
|
Ip_fd fd,
|
|
Ipmip_cli_ident_t *ident)
|
|
{
|
|
/* Do create a new client */
|
|
Ipmip_cli_client_t *client = ipcom_calloc(1, sizeof(*client));
|
|
if (client)
|
|
{
|
|
Ip_socklen_t slen;
|
|
ipcom_block_create(&client->block);
|
|
|
|
ipcom_mutex_lock(cli->lock);
|
|
client->ident.pid = ++cli->pids;
|
|
ipcom_mutex_unlock(cli->lock);
|
|
|
|
client->ident.timestamp = ipmip_util_time();
|
|
client->cli = cli;
|
|
client->fd = fd;
|
|
|
|
ipcom_list_init(&client->replies);
|
|
ipcom_list_init(&client->mcasts);
|
|
|
|
|
|
if (ident)
|
|
*ident = client->ident;
|
|
|
|
/* Connection information */
|
|
slen = sizeof(client->conn_local);
|
|
(void)ipcom_getsockname(fd, &client->conn_local.sa, &slen);
|
|
|
|
slen = sizeof(client->conn_remote);
|
|
(void)ipcom_getpeername(fd, &client->conn_remote.sa, &slen);
|
|
|
|
client->proc = ipmip_proc_start(ctx,
|
|
proc,
|
|
"cli_client",
|
|
(Ipmip_proc_func_t)ipmip_cli_client_loop,
|
|
client);
|
|
|
|
if (client->proc == IP_NULL)
|
|
{
|
|
ipmip_cli_context_client_free(ctx, proc, client);
|
|
return IP_FALSE;
|
|
}
|
|
|
|
ipcom_mutex_lock(cli->lock);
|
|
ipcom_list_insert_first(&cli->clients, &client->next);
|
|
ipcom_mutex_unlock(cli->lock);
|
|
|
|
/* Release it */
|
|
ipcom_block_post(client->block);
|
|
return IP_TRUE;
|
|
}
|
|
|
|
return IP_FALSE;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip_cli_loop
|
|
*===========================================================================
|
|
* Description:
|
|
*
|
|
*/
|
|
IP_STATIC void
|
|
ipmip_cli_loop(Ipmip_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
Ipmip_cli_context_t *cli)
|
|
{
|
|
Ipmip_cli_client_t *client;
|
|
int opt;
|
|
Ip_socklen_t slen;
|
|
union Ip_sockaddr_union saX;
|
|
|
|
cli->sfd = IP_INVALID_SOCKET;
|
|
|
|
/* Create the FD */
|
|
#ifdef IPCOM_USE_INET6
|
|
if (cli->sin6.sin6_family == IP_AF_INET6)
|
|
{
|
|
cli->sfd = ipcom_socket(IP_AF_INET6, IP_SOCK_STREAM, IP_IPPROTO_TCP);
|
|
if (cli->sfd != IP_INVALID_SOCKET)
|
|
{
|
|
opt = 1;
|
|
(void)ipcom_setsockopt(cli->sfd, IP_SOL_SOCKET, IP_SO_REUSEPORT, (char *)&opt, sizeof(opt));
|
|
|
|
slen = IPCOM_SA_LEN_GET(&cli->sin6);
|
|
if (ipcom_bind(cli->sfd, (struct Ip_sockaddr *) &cli->sin6, slen) >= 0)
|
|
goto cli_process;
|
|
|
|
ipcom_socketclose(cli->sfd);
|
|
cli->sfd = IP_INVALID_SOCKET;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#ifdef IPCOM_USE_INET
|
|
if (cli->sin4.sin_family == IP_AF_INET)
|
|
{
|
|
cli->sfd = ipcom_socket(IP_AF_INET, IP_SOCK_STREAM, IP_IPPROTO_TCP);
|
|
if (cli->sfd != IP_INVALID_SOCKET)
|
|
{
|
|
opt = 1;
|
|
(void)ipcom_setsockopt(cli->sfd, IP_SOL_SOCKET, IP_SO_REUSEPORT, (char *)&opt, sizeof(opt));
|
|
|
|
slen = IPCOM_SA_LEN_GET(&cli->sin4);
|
|
if (ipcom_bind(cli->sfd, (struct Ip_sockaddr *) &cli->sin4, slen) >= 0)
|
|
goto cli_process;
|
|
|
|
ipcom_socketclose(cli->sfd);
|
|
cli->sfd = IP_INVALID_SOCKET;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
cli_process:
|
|
if (cli->sfd == IP_INVALID_SOCKET)
|
|
goto errout;
|
|
|
|
slen = sizeof(saX);
|
|
if (ipcom_getsockname(cli->sfd, (struct Ip_sockaddr *)&saX, &slen) < 0)
|
|
goto errout;
|
|
else
|
|
{
|
|
Ip_u16 port = 0;
|
|
|
|
#ifdef IPCOM_USE_INET6
|
|
if (saX.sa.sa_family == IP_AF_INET6)
|
|
port = saX.sin6.sin6_port;
|
|
#endif
|
|
#ifdef IPCOM_USE_INET
|
|
if (saX.sa.sa_family == IP_AF_INET)
|
|
port = saX.sin.sin_port;
|
|
#endif
|
|
/* Write connection information */
|
|
ipcom_snprintf(proc->ntop.ntop_pbuf, sizeof(proc->ntop.ntop_pbuf), "%s %u", ipmip_ntop_sa(proc, &saX), ipcom_ntohs(port));
|
|
ipmip_sysvar_set(proc->ntop.ntop_pbuf, "ipmip.cli.%s", cli->header);
|
|
}
|
|
|
|
|
|
if (ipcom_listen(cli->sfd, 5) < 0)
|
|
goto errout;
|
|
|
|
/*********** tick loop ***********/
|
|
for (; proc->quit != IP_TRUE;)
|
|
{
|
|
Ip_fd_set rset;
|
|
int ret;
|
|
struct Ip_timeval tv;
|
|
Ipmip_cli_client_t *lclient;
|
|
|
|
/* Try collect clients */
|
|
ipcom_mutex_lock(cli->lock);
|
|
for (client = IPCOM_LIST_FIRST(&cli->clients); client != IP_NULL;)
|
|
{
|
|
lclient = IPCOM_LIST_NEXT(&client->next);
|
|
if (ipmip_proc_collect(ctx,proc,client->proc))
|
|
{
|
|
ipcom_list_remove(&client->next);
|
|
ipmip_cli_context_client_free(ctx, proc, client);
|
|
}
|
|
client = lclient;
|
|
}
|
|
ipcom_mutex_unlock(cli->lock);
|
|
|
|
/* Clear it */
|
|
IP_FD_ZERO(&rset);
|
|
|
|
/* Add the client socket */
|
|
IP_FD_SET(cli->sfd, &rset);
|
|
|
|
tv.tv_sec = 0;
|
|
tv.tv_usec = 200 * 1000;
|
|
ret = ipcom_socketselect(cli->sfd + 1, &rset, IP_NULL, IP_NULL, &tv);
|
|
/* Timeout */
|
|
if (ret == 0)
|
|
continue;
|
|
else if (ret > 0)
|
|
{
|
|
slen = sizeof(saX);
|
|
|
|
/* Check the */
|
|
if (IP_FD_ISSET(cli->sfd, &rset))
|
|
{
|
|
Ip_fd cfd = ipcom_accept(cli->sfd, (struct Ip_sockaddr *)&saX, &slen);
|
|
if (cfd != IP_INVALID_SOCKET)
|
|
{
|
|
if (!ipmip_cli_start_client(ctx, proc, ctx->cli, cfd, IP_NULL))
|
|
ipcom_socketclose(cfd);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
errout:
|
|
|
|
/* Stop all clients */
|
|
for (client = IPCOM_LIST_FIRST(&cli->clients); client != IP_NULL; client = IPCOM_LIST_NEXT(&client->next))
|
|
ipmip_proc_stop(ctx, proc, client->proc, IP_NULL, IP_NULL);
|
|
|
|
/* Destroy all clients */
|
|
ipcom_mutex_lock(cli->lock);
|
|
while ((client = IPCOM_LIST_FIRST(&cli->clients)) != IP_NULL)
|
|
{
|
|
ipcom_list_remove(&client->next);
|
|
ipmip_cli_context_client_free(ctx, proc, client);
|
|
}
|
|
ipcom_mutex_unlock(cli->lock);
|
|
|
|
if (cli->sfd != IP_INVALID_SOCKET)
|
|
ipcom_socketclose(cli->sfd);
|
|
}
|
|
|
|
IP_STATIC Ipmip_cli_message_t *
|
|
ipmip_cli_message_duplicate(Ipmip_cli_message_t *request)
|
|
{
|
|
Ipmip_cli_message_t *msg = ipmip_cli_message_alloc(&request->ident);
|
|
if(IP_NULL == msg)
|
|
{
|
|
return IP_NULL;
|
|
}
|
|
|
|
/**/
|
|
ipmip_buffer_append(&msg->message, IPMIP_BUFFER_DATA(&request->message), IPMIP_BUFFER_SIZE(&request->message));
|
|
return msg;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip_cli_connect
|
|
*===========================================================================
|
|
* Description: Connect to a CLI context
|
|
* Parameters: proc - Process context
|
|
* header - The ipmip name
|
|
* magic - Magic
|
|
* version - Version
|
|
* Returns: A connection context if successful
|
|
*
|
|
*/
|
|
IP_STATIC Ip_fd
|
|
ipmip_cli_connect(Ipmip_proc_t *proc,
|
|
union Ip_sockaddr_union *remote,
|
|
union Ip_sockaddr_union *local)
|
|
{
|
|
Ip_fd fd = IP_INVALID_SOCKET;
|
|
|
|
IPMIP_UNUSED_PARAMETER(proc);
|
|
|
|
if (local != IP_NULL && local->sa.sa_family != remote->sa.sa_family)
|
|
return IP_INVALID_SOCKET;
|
|
|
|
fd = ipcom_socket(remote->sa.sa_family, IP_SOCK_STREAM, IP_IPPROTO_TCP);
|
|
if (fd == IP_INVALID_SOCKET)
|
|
return fd;
|
|
|
|
if (local)
|
|
{
|
|
int opt = 1;
|
|
Ip_socklen_t slen;
|
|
|
|
(void)ipcom_setsockopt(fd, IP_SOL_SOCKET, IP_SO_REUSEPORT, (char *)&opt, sizeof(opt));
|
|
|
|
slen = IPCOM_SA_LEN_GET(&local->sa);
|
|
if (ipcom_bind(fd, (struct Ip_sockaddr *) &local->sa, slen) < 0)
|
|
{
|
|
ipcom_socketclose(fd);
|
|
return IP_INVALID_SOCKET;
|
|
}
|
|
}
|
|
|
|
if (ipcom_connect(fd, &remote->sa, IPCOM_SA_LEN_GET(&remote->sa)) != 0)
|
|
{
|
|
ipcom_socketclose(fd);
|
|
fd = IP_INVALID_SOCKET;
|
|
}
|
|
|
|
return fd;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip_cli_connect
|
|
*===========================================================================
|
|
* Description: Connect to a CLI context
|
|
* Parameters: proc - Process context
|
|
* header - The ipmip name
|
|
* magic - Magic
|
|
* version - Version
|
|
* Returns: A connection context if successful
|
|
*
|
|
*/
|
|
IP_STATIC Ip_fd
|
|
ipmip_cli_connect_local(Ipmip_proc_t *proc,
|
|
const char *header)
|
|
{
|
|
Ip_fd fd = IP_INVALID_SOCKET;
|
|
char *pvar;
|
|
union Ip_sockaddr_union saX;
|
|
|
|
IPMIP_UNUSED_PARAMETER(proc);
|
|
|
|
pvar = ipmip_sysvar("ipmip.cli.%s", header);
|
|
if (pvar == IP_NULL)
|
|
return fd;
|
|
|
|
if (!ipmip_util_sockaddrX(pvar, &saX))
|
|
{
|
|
ipcom_free(pvar);
|
|
return fd;
|
|
}
|
|
|
|
ipcom_free(pvar);
|
|
|
|
/* Connect */
|
|
return ipmip_cli_connect(proc, &saX, IP_NULL);
|
|
}
|
|
|
|
|
|
IP_STATIC int
|
|
ipmip_cli_daemon_request_reply(Ipmip_cli_daemon_t *daemon_info,
|
|
Ipmip_cli_daemon_req_t *daemon_req)
|
|
{
|
|
struct Ipmip_attr_header *req_hdr = (struct Ipmip_attr_header *)IPMIP_BUFFER_DATA(&daemon_req->reqbuf);
|
|
for (;;)
|
|
{
|
|
struct Ipmip_attr_header *hdr;
|
|
int ret = ipmip_cli_daemon_recvmsg(daemon_info, IP_NULL);
|
|
|
|
/* */
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
hdr = (struct Ipmip_attr_header *)IPMIP_BUFFER_DATA(&daemon_info->message);
|
|
if (IPMIP_ATTR_HDR_SYSTEM(hdr) != IPMIP_ATTR_HDR_SYSTEM(req_hdr) || IPMIP_ATTR_HDR_SEQUENCE(hdr) != IPMIP_ATTR_HDR_SEQUENCE(req_hdr))
|
|
{
|
|
IPCOM_LOG4(ERR, "BAD: %08x != %08x, %08x != %08x",
|
|
IPMIP_ATTR_HDR_SYSTEM(hdr),
|
|
IPMIP_ATTR_HDR_SYSTEM(req_hdr),
|
|
IPMIP_ATTR_HDR_SEQUENCE(hdr),
|
|
IPMIP_ATTR_HDR_SEQUENCE(req_hdr));
|
|
continue;
|
|
}
|
|
|
|
if (IPMIP_ATTR_HDR_TYPE(hdr) != IPMIP_ATTR_HDR_TYPE(req_hdr))
|
|
return -IP_ERRNO_EINVAL;
|
|
|
|
|
|
if (IPMIP_ATTR_HDR_ERROR(hdr) != 0)
|
|
return -IPMIP_ATTR_HDR_ERROR(hdr);
|
|
|
|
/* Copy reply to request */
|
|
if (IP_BIT_ISFALSE(daemon_req->reqflags, IPMIP_CLI_REQ_REPLY_NOCOPY))
|
|
{
|
|
ipmip_buffer_shrink(&daemon_req->reqbuf, 0);
|
|
ipmip_buffer_append(&daemon_req->reqbuf, IPMIP_BUFFER_DATA(&daemon_info->message), IPMIP_BUFFER_SIZE(&daemon_info->message));
|
|
}
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip_cli_context_stop
|
|
*===========================================================================
|
|
* Description: Stop the CLI context
|
|
* Parameters: ctx - Context
|
|
* proc - Process
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC void
|
|
ipmip_cli_context_kill(struct Ipmip_context *ctx,
|
|
struct Ipmip_proc *proc,
|
|
Ipmip_cli_context_t *cli)
|
|
{
|
|
/* Lock the global mutex */
|
|
if (cli != IP_NULL && cli->proc != IP_NULL)
|
|
{
|
|
cli->busy = IP_TRUE;
|
|
|
|
ipmip_proc_stop(ctx,
|
|
proc,
|
|
cli->proc,
|
|
IP_NULL,
|
|
IP_NULL);
|
|
cli->proc = IP_NULL;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip_cli_context_start
|
|
*===========================================================================
|
|
* Description: Start the CLI context
|
|
* Parameters: ctx - Context
|
|
* proc - Process
|
|
* Returns: IP_TRUE on success.
|
|
*
|
|
*/
|
|
IP_STATIC Ip_bool
|
|
ipmip_cli_context_exec(struct Ipmip_context *ctx,
|
|
struct Ipmip_proc *proc,
|
|
Ipmip_cli_context_t *cli)
|
|
{
|
|
/* Lock the global mutex */
|
|
if (cli != IP_NULL && cli->proc == IP_NULL)
|
|
{
|
|
cli->proc = ipmip_proc_start(ctx,
|
|
proc,
|
|
"cli",
|
|
(Ipmip_proc_func_t) ipmip_cli_loop,
|
|
cli);
|
|
|
|
if (cli->proc != IP_NULL)
|
|
cli->busy = IP_FALSE;
|
|
}
|
|
|
|
return cli != IP_NULL && cli->proc != IP_NULL;
|
|
}
|
|
|
|
IP_STATIC void
|
|
ipmip_cli_context_free(struct Ipmip_proc *proc,
|
|
Ipmip_cli_context_t *cli)
|
|
{
|
|
IPMIP_UNUSED_PARAMETER(proc);
|
|
|
|
if (cli != IP_NULL)
|
|
{
|
|
ipcom_free(cli->header);
|
|
ipcom_mutex_delete(&cli->lock);
|
|
ipcom_free(cli);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip_cli_context_create
|
|
*===========================================================================
|
|
* Description: Allocate an CLI context
|
|
* Parameters: ctx - Context
|
|
* proc - Process
|
|
* header - The ipmip name
|
|
* magic - Magic
|
|
* version - Version
|
|
* callback - Function callback to be invoked on messages
|
|
* Returns: IP_TRUE on success
|
|
*
|
|
*/
|
|
IP_STATIC Ipmip_cli_context_t *
|
|
ipmip_cli_context_alloc(struct Ipmip_proc *proc,
|
|
const char *header,
|
|
Ip_u32 subsystem,
|
|
Ipmip_cli_callback_t callback,
|
|
union Ip_sockaddr_union *saX,
|
|
void *opaque)
|
|
{
|
|
Ipmip_cli_context_t *cli = ipcom_calloc(1, sizeof(*cli));
|
|
|
|
IPMIP_UNUSED_PARAMETER(proc);
|
|
|
|
if (cli)
|
|
{
|
|
cli->callback = callback;
|
|
cli->subsystem = subsystem;
|
|
cli->header = ipcom_strdup(header);
|
|
cli->opaque = opaque;
|
|
if (cli->header == IP_NULL)
|
|
goto errout;
|
|
|
|
if (saX == IP_NULL)
|
|
{
|
|
#ifdef IPCOM_USE_INET6
|
|
cli->sin6.sin6_family = IP_AF_INET6;
|
|
IPCOM_SA_LEN_SET(&cli->sin6, sizeof(cli->sin6));
|
|
ipcom_memcpy(&cli->sin6.sin6_addr, &ip_in6addr_loopback, sizeof(ip_in6addr_loopback));
|
|
cli->sin6.sin6_port = 0;
|
|
#endif
|
|
#ifdef IPCOM_USE_INET
|
|
cli->sin4.sin_family = IP_AF_INET;
|
|
IPCOM_SA_LEN_SET(&cli->sin4, sizeof(cli->sin4));
|
|
cli->sin4.sin_addr.s_addr = ip_htonl(IP_INADDR_LOOPBACK);
|
|
cli->sin4.sin_port = 0;
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
#ifdef IPCOM_USE_INET6
|
|
if (saX->sa.sa_family == IP_AF_INET6)
|
|
ipcom_memcpy(&cli->sin6, &saX->sin6, sizeof(cli->sin6));
|
|
#endif
|
|
#ifdef IPCOM_USE_INET
|
|
if (saX->sa.sa_family == IP_AF_INET)
|
|
ipcom_memcpy(&cli->sin4, &saX->sin, sizeof(cli->sin4));
|
|
#endif
|
|
}
|
|
|
|
(void)ipcom_mutex_create(&cli->lock);
|
|
|
|
/* Create the client head */
|
|
ipcom_list_init(&cli->clients);
|
|
return cli;
|
|
}
|
|
|
|
errout:
|
|
ipcom_free(cli);
|
|
return IP_NULL;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip_cli_sendbuffer
|
|
*===========================================================================
|
|
* Description: Send a message over fd
|
|
* Parameters: fd - File descriptor.
|
|
* buf - Pointer to buffer.
|
|
* Returns: 0 if successful.
|
|
*
|
|
*/
|
|
IP_STATIC int
|
|
ipmip_cli_sendbuffer(Ip_fd fd,
|
|
Ipmip_buffer_t *buf)
|
|
{
|
|
if (buf && buf->offset)
|
|
{
|
|
Ip_size_t totsize = IPMIP_BUFFER_SIZE(buf);
|
|
Ip_size_t csize = 0;
|
|
Ip_u8 *data = IPMIP_BUFFER_PTR(buf);
|
|
|
|
while (csize != totsize)
|
|
{
|
|
Ip_size_t ssize = IP_MIN((totsize - csize), 1500);
|
|
|
|
if (ipcom_send(fd, (void *)&data[csize], ssize, 0) != (int)ssize)
|
|
return -ipcom_errno;
|
|
|
|
csize += ssize;
|
|
}
|
|
|
|
return IPCOM_SUCCESS;
|
|
}
|
|
|
|
return -IP_ERRNO_EINVAL;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip_cli_command
|
|
*===========================================================================
|
|
* Description: Issue a command and retrieve the reply
|
|
* Parameters: fd - File descriptor.
|
|
* rbuf - Pointer to buffer pointer. Will hold the
|
|
* dynamically allocated buffer on success.
|
|
* Returns: IP_TRUE on success
|
|
*
|
|
*/
|
|
IP_STATIC void
|
|
ipmip_cli_request_setup(Ipmip_buffer_t *rbuf,
|
|
Ip_u32 type,
|
|
Ip_u32 subsystem,
|
|
Ip_u32 seq)
|
|
{
|
|
/**/
|
|
Ip_size_t off = IPMIP_BUFFER_SIZE(rbuf);
|
|
|
|
if (off)
|
|
{
|
|
Ipmip_buffer_t nbuf;
|
|
Ip_size_t rhdr;
|
|
ipmip_buffer_init(&nbuf);
|
|
|
|
rhdr = ipmip_attr_hdr_req_create(&nbuf,subsystem,seq,type);
|
|
ipmip_buffer_append(&nbuf, IPMIP_BUFFER_DATA(rbuf), off);
|
|
ipmip_attr_hdr_finalize(&nbuf, rhdr);
|
|
ipmip_buffer_assign(rbuf, &nbuf);
|
|
}
|
|
else
|
|
{
|
|
ipmip_attr_hdr_finalize(rbuf,
|
|
ipmip_attr_hdr_req_create(rbuf,subsystem,seq,type));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip_cli_daemon_request
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC int
|
|
ipmip_cli_daemon_request_send(Ipmip_cli_daemon_t *daemon_info,
|
|
Ipmip_cli_daemon_req_t *daemon_req)
|
|
{
|
|
int i;
|
|
|
|
/**/
|
|
ipmip_cli_request_setup(&daemon_req->reqbuf, daemon_req->reqtype, daemon_info->pid, ++daemon_info->seq);
|
|
|
|
for (i = 0; i < 10; i++)
|
|
{
|
|
int ret = -IP_ERRNO_ENOTCONN;
|
|
|
|
if (daemon_info->fd == IP_INVALID_SOCKET)
|
|
{
|
|
if (!ipmip_cli_daemon_connect(daemon_info))
|
|
{
|
|
ipcom_sleep(1);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
ret = ipmip_cli_sendbuffer(daemon_info->fd, &daemon_req->reqbuf);
|
|
|
|
switch (-ret)
|
|
{
|
|
default:
|
|
case IPCOM_SUCCESS:
|
|
return ret;
|
|
|
|
case IP_ERRNO_ECONNRESET:
|
|
case IP_ERRNO_ENOTCONN:
|
|
case IP_ERRNO_EBUSY:
|
|
ipmip_cli_daemon_disconnect(daemon_info);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**/
|
|
return -IP_ERRNO_ENOTCONN;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip_cli_message_commit
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ip_bool
|
|
ipmip_cli_message_deliver(struct Ipmip_context *ctx,
|
|
struct Ipmip_proc *proc,
|
|
Ipmip_cli_context_t *cli,
|
|
Ipmip_cli_message_t *request)
|
|
{
|
|
Ipmip_cli_client_t *client;
|
|
|
|
IPMIP_UNUSED_PARAMETER(ctx);
|
|
IPMIP_UNUSED_PARAMETER(proc);
|
|
|
|
if (cli == IP_NULL)
|
|
cli = ctx->cli;
|
|
|
|
/* Try collect clients */
|
|
ipcom_mutex_lock(cli->lock);
|
|
for (client = IPCOM_LIST_FIRST(&cli->clients); client != IP_NULL; client = IPCOM_LIST_NEXT(&client->next))
|
|
{
|
|
if (client->ident.pid == request->ident.pid && client->ident.timestamp == request->ident.timestamp)
|
|
{
|
|
/* Found it */
|
|
ipmip_cli_sendreply(ctx, proc, client, request);
|
|
request = IP_NULL;
|
|
break;
|
|
}
|
|
}
|
|
ipcom_mutex_unlock(cli->lock);
|
|
|
|
if (request)
|
|
return IP_FALSE;
|
|
|
|
return IP_TRUE;
|
|
}
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 10 GLOBAL FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
|
|
IP_GLOBAL void
|
|
ipmip_cli_message_multicast(struct Ipmip_context *ctx,
|
|
struct Ipmip_proc *proc,
|
|
Ipmip_cli_context_t *cli,
|
|
Ip_u32 channel,
|
|
Ipmip_cli_message_t *request)
|
|
{
|
|
Ipmip_cli_client_t *client;
|
|
Ipmip_cli_client_t *nclient = IP_NULL;
|
|
|
|
IPMIP_UNUSED_PARAMETER(ctx);
|
|
IPMIP_UNUSED_PARAMETER(proc);
|
|
|
|
/**/
|
|
if (cli == IP_NULL)
|
|
cli = ctx->cli;
|
|
|
|
/* Try collect clients */
|
|
ipcom_mutex_lock(cli->lock);
|
|
for (client = IPCOM_LIST_FIRST(&cli->clients); client != IP_NULL; client = IPCOM_LIST_NEXT(&client->next))
|
|
{
|
|
Ipmip_cli_client_mcast_t *mc;
|
|
for (mc = IPCOM_LIST_FIRST(&client->mcasts); mc != IP_NULL; mc = IPCOM_LIST_NEXT(&mc->next))
|
|
if (mc->channel == channel)
|
|
break;
|
|
|
|
if (mc != IP_NULL)
|
|
{
|
|
if (nclient)
|
|
ipmip_cli_sendreply(ctx, proc, nclient, ipmip_cli_message_duplicate(request));
|
|
nclient = client;
|
|
}
|
|
}
|
|
|
|
if (nclient)
|
|
{
|
|
ipmip_cli_sendreply(ctx, proc, nclient, request);
|
|
request = IP_NULL;
|
|
}
|
|
|
|
ipcom_mutex_unlock(cli->lock);
|
|
|
|
|
|
if (request)
|
|
ipmip_cli_message_free(ctx, proc, request);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip_cli_context_create
|
|
*===========================================================================
|
|
* Description: Allocate an CLI context
|
|
* Parameters: ctx - Context
|
|
* proc - Process
|
|
* header - The ipmip name
|
|
* magic - Magic
|
|
* version - Version
|
|
* callback - Function callback to be invoked on messages
|
|
* Returns: IP_TRUE on success
|
|
*
|
|
*/
|
|
IP_GLOBAL Ip_bool
|
|
ipmip_cli_context_create(struct Ipmip_context *ctx,
|
|
struct Ipmip_proc *proc,
|
|
const char *header,
|
|
Ip_u32 subsystem,
|
|
Ipmip_cli_callback_t callback)
|
|
{
|
|
Ipmip_cli_context_t *cli = ipmip_cli_context_alloc(proc, header, subsystem, callback, IP_NULL, IP_NULL);
|
|
|
|
if (cli)
|
|
{
|
|
ctx->cli = cli;
|
|
return IP_TRUE;
|
|
}
|
|
|
|
return IP_FALSE;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip_cli_context_start
|
|
*===========================================================================
|
|
* Description: Start the CLI context
|
|
* Parameters: ctx - Context
|
|
* proc - Process
|
|
* Returns: IP_TRUE on success.
|
|
*
|
|
*/
|
|
IP_GLOBAL Ip_bool
|
|
ipmip_cli_context_start(struct Ipmip_context *ctx,
|
|
struct Ipmip_proc *proc)
|
|
{
|
|
/**/
|
|
return ipmip_cli_context_exec(ctx, proc, ctx->cli);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip_cli_context_stop
|
|
*===========================================================================
|
|
* Description: Stop the CLI context
|
|
* Parameters: ctx - Context
|
|
* proc - Process
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL void
|
|
ipmip_cli_context_stop(struct Ipmip_context *ctx,
|
|
struct Ipmip_proc *proc)
|
|
{
|
|
ipmip_cli_context_kill(ctx, proc, ctx->cli);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip_cli_context_destroy
|
|
*===========================================================================
|
|
* Description: Free an CLI context
|
|
* Parameters: ctx - Context
|
|
* proc - Process
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL void
|
|
ipmip_cli_context_destroy(struct Ipmip_context *ctx,
|
|
struct Ipmip_proc *proc)
|
|
{
|
|
ipmip_cli_context_free(proc, ctx->cli);
|
|
ctx->cli = IP_NULL;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip_cli_message_commit
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL void
|
|
ipmip_cli_message_commit(struct Ipmip_context *ctx,
|
|
struct Ipmip_proc *proc,
|
|
Ipmip_cli_message_t *request)
|
|
{
|
|
/**/
|
|
if (!ipmip_cli_message_deliver(ctx, proc, ctx->cli, request))
|
|
ipmip_cli_message_free(ctx, proc, request);
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip_cli_message_free
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL void
|
|
ipmip_cli_message_free(struct Ipmip_context *ctx,
|
|
struct Ipmip_proc *proc,
|
|
Ipmip_cli_message_t *req)
|
|
{
|
|
ipmip_timer_cancel(ctx, proc, &req->timer);
|
|
|
|
ipmip_buffer_release(&req->message);
|
|
ipmip_buffer_release(&req->request);
|
|
ipcom_free(req);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip_cli_message_alloc
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL Ipmip_cli_message_t *
|
|
ipmip_cli_message_alloc(Ipmip_cli_ident_t *ident)
|
|
{
|
|
Ipmip_cli_message_t *req = ipcom_calloc(1, sizeof(*req));
|
|
if(IP_NULL == req)
|
|
{
|
|
return IP_NULL;
|
|
}
|
|
|
|
ipmip_buffer_init(&req->request);
|
|
ipmip_buffer_init(&req->message);
|
|
|
|
IPMIP_TIMER_INIT(&req->timer);
|
|
|
|
/**/
|
|
if (ident)
|
|
req->ident = *ident;
|
|
return req;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip_cli_daemon_connect
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL Ip_bool
|
|
ipmip_cli_daemon_connect(Ipmip_cli_daemon_t *daemon_info)
|
|
{
|
|
if (daemon_info->fd == IP_INVALID_SOCKET)
|
|
{
|
|
daemon_info->seq = ((Ip_u32)ipmip_util_time()) + ipcom_random();;
|
|
daemon_info->fd = ipmip_cli_connect_local(IP_NULL, daemon_info->header);
|
|
ipmip_buffer_init(&daemon_info->message);
|
|
}
|
|
|
|
return daemon_info->fd != IP_INVALID_SOCKET;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip_cli_daemon_disconnect
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL void
|
|
ipmip_cli_daemon_disconnect(Ipmip_cli_daemon_t *daemon_info)
|
|
{
|
|
if (daemon_info->fd != IP_INVALID_SOCKET)
|
|
{
|
|
ipcom_socketclose(daemon_info->fd);
|
|
daemon_info->fd = IP_INVALID_SOCKET;
|
|
ipmip_buffer_release(&daemon_info->message);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip_cli_daemon_init
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL void
|
|
ipmip_cli_daemon_init(Ipmip_cli_daemon_t *daemon_info,
|
|
const char *header,
|
|
Ip_u32 pid)
|
|
{
|
|
daemon_info->fd = IP_INVALID_SOCKET;
|
|
daemon_info->header = header;
|
|
daemon_info->pid = pid;
|
|
}
|
|
|
|
|
|
IP_GLOBAL int
|
|
ipmip_cli_daemon_recvmsg(Ipmip_cli_daemon_t *daemon_info,
|
|
struct Ip_timeval *tv)
|
|
{
|
|
/**/
|
|
return ipmip_cli_recvmsg(daemon_info->fd, &daemon_info->message, tv);
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip_cli_daemon_request
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL int
|
|
ipmip_cli_daemon_request(Ipmip_cli_daemon_t *daemon_info,
|
|
Ipmip_cli_daemon_req_t *daemon_req)
|
|
{
|
|
int ret = ipmip_cli_daemon_request_send(daemon_info, daemon_req);
|
|
if (ret == IPCOM_SUCCESS)
|
|
ret = ipmip_cli_daemon_request_reply(daemon_info, daemon_req);
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip_cli_daemon_request_init
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL void
|
|
ipmip_cli_daemon_request_init(Ipmip_cli_daemon_req_t *daemon_req)
|
|
{
|
|
daemon_req->reqflags = 0;
|
|
ipmip_buffer_init(&daemon_req->reqbuf);
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip_cli_daemon_request_start
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL void
|
|
ipmip_cli_daemon_request_start(Ipmip_cli_daemon_req_t *daemon_req,
|
|
Ip_u32 req_type)
|
|
{
|
|
ipmip_buffer_shrink(&daemon_req->reqbuf, 0);
|
|
daemon_req->reqtype = req_type;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip_cli_daemon_request_release
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL void
|
|
ipmip_cli_daemon_request_release(Ipmip_cli_daemon_req_t *daemon_req)
|
|
{
|
|
ipmip_buffer_release(&daemon_req->reqbuf);
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip_cli_event_next
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_PUBLIC Ip_bool
|
|
ipmip_cli_event_next(Ipmip_attr_iter_t *iter,
|
|
const char **message,
|
|
Ip_time_t *tval,
|
|
int *loglevel)
|
|
{
|
|
/**/
|
|
struct Ipmip_attr *rta = ipmip_attr_iter_next(iter, IPMIP_CLI_ITEM_EVENT);
|
|
if (rta != IP_NULL)
|
|
{
|
|
struct Ipmip_attr *eattr[IPMIP_CLI_ITEM_EVENT_MAX];
|
|
|
|
/* parse it */
|
|
ipmip_attr_parse(IPMIP_CLI_ITEM_EVENT_MAX,
|
|
IPMIP_ATTR_DATA(rta),
|
|
IPMIP_ATTR_PAYLOAD(rta),
|
|
eattr);
|
|
|
|
if (eattr[IPMIP_CLI_ITEM_EVENT_TIME] &&
|
|
eattr[IPMIP_CLI_ITEM_EVENT_MESSAGE] &&
|
|
eattr[IPMIP_CLI_ITEM_EVENT_LEVEL])
|
|
{
|
|
*loglevel = (int)ipmip_attr_get_u32(eattr[IPMIP_CLI_ITEM_EVENT_LEVEL]);
|
|
*tval = ipmip_attr_get_time_t(eattr[IPMIP_CLI_ITEM_EVENT_TIME]);
|
|
*message = ipmip_attr_get_str(eattr[IPMIP_CLI_ITEM_EVENT_MESSAGE]);
|
|
return IP_TRUE;
|
|
}
|
|
}
|
|
|
|
return IP_FALSE;
|
|
}
|
|
|
|
|
|
IP_PUBLIC int
|
|
ipmip_cli_event_list(Ipmip_cli_daemon_t *daemon,
|
|
Ipmip_cli_daemon_req_t *req)
|
|
{
|
|
ipmip_cli_daemon_request_start(req, IPMIP_CLI_EVENT_GET);
|
|
return ipmip_cli_daemon_request(daemon, req);
|
|
}
|
|
|
|
|
|
IP_PUBLIC int
|
|
ipmip_cli_event_flush(Ipmip_cli_daemon_t *daemon)
|
|
{
|
|
Ipmip_cli_daemon_req_t req;
|
|
int rval;
|
|
|
|
ipmip_cli_daemon_request_init(&req);
|
|
ipmip_cli_daemon_request_start(&req, IPMIP_CLI_EVENT_FLUSH);
|
|
rval = ipmip_cli_daemon_request(daemon, &req);
|
|
ipmip_cli_daemon_request_release(&req);
|
|
return rval;
|
|
}
|
|
|
|
|
|
IP_PUBLIC void
|
|
ipmip_cli_event_print(Ipmip_proc_t *proc,
|
|
Ipmip_cli_daemon_t *daemon,
|
|
int loglevel)
|
|
{
|
|
Ipmip_cli_daemon_req_t req;
|
|
|
|
ipmip_cli_daemon_request_init(&req);
|
|
if (ipmip_cli_event_list(daemon, &req) == IPCOM_SUCCESS)
|
|
{
|
|
Ipmip_attr_iter_t riter;
|
|
const char *msg;
|
|
Ip_time_t tm;
|
|
int ll;
|
|
|
|
/**/
|
|
ipmip_cli_daemon_iter_request_init(&req, &riter);
|
|
while (ipmip_cli_event_next(&riter, &msg, &tm, &ll))
|
|
{
|
|
if (loglevel < 0 || ll <= loglevel)
|
|
{
|
|
/* Time, subject & message */
|
|
ipcom_printf("%s %s: %s"IP_LF,
|
|
ipmip_ntop_tm(proc, tm),
|
|
ipmip_util_syslog_priority_name(ll),
|
|
msg);
|
|
}
|
|
}
|
|
}
|
|
|
|
ipmip_cli_daemon_request_release(&req);
|
|
}
|
|
|
|
|
|
|
|
IP_PUBLIC const char *
|
|
ipmip_cli_config_next(Ipmip_attr_iter_t *iter)
|
|
{
|
|
/**/
|
|
return ipmip_attr_get_str(ipmip_attr_iter_next(iter, IPMIP_CLI_ITEM_CONFIG_LINE));
|
|
}
|
|
|
|
IP_PUBLIC const char *
|
|
ipmip_cli_name_next(Ipmip_attr_iter_t *iter)
|
|
{
|
|
/**/
|
|
return ipmip_attr_get_str(ipmip_attr_iter_next(iter, IPMIP_CLI_ITEM_NAME));
|
|
}
|
|
|
|
IP_PUBLIC int
|
|
ipmip_cli_name_list(Ipmip_cli_daemon_t *daemon,
|
|
Ipmip_cli_daemon_req_t *req)
|
|
{
|
|
ipmip_cli_daemon_request_start(req, IPMIP_CLI_NAME_LIST);
|
|
return ipmip_cli_daemon_request(daemon, req);
|
|
}
|
|
|
|
|
|
IP_PUBLIC void
|
|
ipmip_cli_set_name(Ipmip_cli_daemon_req_t *req,
|
|
const char *name)
|
|
{
|
|
if (name)
|
|
ipmip_attr_put_str(&req->reqbuf, IPMIP_CLI_ITEM_NAME, name);
|
|
}
|
|
|
|
IP_PUBLIC void
|
|
ipmip_cli_set_size(Ipmip_cli_daemon_req_t *req,
|
|
Ip_u32 size)
|
|
{
|
|
ipmip_attr_put_u32(&req->reqbuf, IPMIP_CLI_ITEM_SIZE, size);
|
|
}
|
|
|
|
|
|
IP_PUBLIC int
|
|
ipmip_cli_config_list(Ipmip_cli_daemon_t *daemon,
|
|
Ipmip_cli_daemon_req_t *req,
|
|
const char *name)
|
|
{
|
|
ipmip_cli_daemon_request_start(req, IPMIP_CLI_CONFIG_GET);
|
|
ipmip_cli_set_name(req, name);
|
|
return ipmip_cli_daemon_request(daemon, req);
|
|
}
|
|
|
|
|
|
|
|
IP_PUBLIC void
|
|
ipmip_cli_config_print(Ipmip_proc_t *proc,
|
|
Ipmip_cli_daemon_t *daemon,
|
|
const char *name)
|
|
{
|
|
IPMIP_UNUSED_PARAMETER(proc);
|
|
if (name == IP_NULL)
|
|
{
|
|
Ipmip_cli_daemon_req_t nreq;
|
|
ipmip_cli_daemon_request_init(&nreq);
|
|
/**/
|
|
if (ipmip_cli_name_list(daemon, &nreq) == IPCOM_SUCCESS)
|
|
{
|
|
Ipmip_attr_iter_t niter;
|
|
ipmip_cli_daemon_iter_request_init(&nreq, &niter);
|
|
while ((name = ipmip_cli_name_next(&niter)) != IP_NULL)
|
|
ipmip_cli_config_name_print(proc, daemon, name);
|
|
return;
|
|
}
|
|
ipmip_cli_daemon_request_release(&nreq);
|
|
}
|
|
|
|
ipmip_cli_config_name_print(proc, daemon, name);
|
|
}
|
|
|
|
IP_GLOBAL void
|
|
ipmip_cli_config_printf(struct Ipmip_buffer *reqbuf,
|
|
const char *format,
|
|
...)
|
|
{
|
|
Ip_size_t off;
|
|
va_list ap;
|
|
|
|
if (ipmip_buffer_reserve(reqbuf, 256))
|
|
{
|
|
struct Ipmip_attr *attr;
|
|
int sz;
|
|
|
|
off = ipmip_attr_begin(reqbuf, IPMIP_CLI_ITEM_CONFIG_LINE);
|
|
|
|
/* Get */
|
|
attr = ipmip_buffer_offset(reqbuf, off);
|
|
|
|
va_start(ap, format);
|
|
sz = ipcom_vsnprintf(IPMIP_ATTR_DATA(attr), 256 - IPMIP_ATTR_LENGTH(0), format , ap);
|
|
va_end(ap);
|
|
|
|
/* Move past */
|
|
ipmip_buffer_append(reqbuf, IP_NULL, sz + 1);
|
|
|
|
/* Terminate */
|
|
ipmip_attr_end(reqbuf, off);
|
|
}
|
|
}
|
|
|
|
|
|
IP_PUBLIC void
|
|
ipmip_cli_loglevel_set(Ipmip_cli_daemon_t *daemon,
|
|
int loglevel)
|
|
{
|
|
Ipmip_cli_daemon_req_t req;
|
|
|
|
ipmip_cli_daemon_request_init(&req);
|
|
ipmip_cli_daemon_request_start(&req, IPMIP_CLI_LOG_LEVEL_SET);
|
|
ipmip_cli_set_size(&req, (Ip_u32)loglevel);
|
|
ipmip_cli_daemon_request(daemon, &req);
|
|
ipmip_cli_daemon_request_release(&req);
|
|
}
|
|
|
|
IP_PUBLIC void
|
|
ipmip_cli_multicast_add(Ipmip_cli_daemon_t *daemon,
|
|
Ip_u32 channel)
|
|
{
|
|
Ipmip_cli_daemon_req_t req;
|
|
|
|
ipmip_cli_daemon_request_init(&req);
|
|
ipmip_cli_daemon_request_start(&req, IPMIP_CLI_TYPE_MULTICAST_ADD);
|
|
ipmip_attr_put_u32(&req.reqbuf, IPMIP_CLI_MULTICAST_ATTR_CHANNEL, channel);
|
|
ipmip_cli_daemon_request(daemon, &req);
|
|
ipmip_cli_daemon_request_release(&req);
|
|
}
|
|
|
|
IP_PUBLIC void
|
|
ipmip_cli_multicast_del(Ipmip_cli_daemon_t *daemon,
|
|
Ip_u32 channel)
|
|
{
|
|
Ipmip_cli_daemon_req_t req;
|
|
|
|
ipmip_cli_daemon_request_init(&req);
|
|
ipmip_cli_daemon_request_start(&req, IPMIP_CLI_TYPE_MULTICAST_DEL);
|
|
ipmip_attr_put_u32(&req.reqbuf, IPMIP_CLI_MULTICAST_ATTR_CHANNEL, channel);
|
|
ipmip_cli_daemon_request(daemon, &req);
|
|
ipmip_cli_daemon_request_release(&req);
|
|
}
|
|
|
|
|
|
IP_PUBLIC void
|
|
ipmip_cli_history_set(Ipmip_cli_daemon_t *daemon,
|
|
Ip_u32 history)
|
|
{
|
|
Ipmip_cli_daemon_req_t req;
|
|
|
|
ipmip_cli_daemon_request_init(&req);
|
|
ipmip_cli_daemon_request_start(&req, IPMIP_CLI_EVENT_HISTORY_SET);
|
|
ipmip_cli_set_size(&req, history);
|
|
ipmip_cli_daemon_request(daemon, &req);
|
|
ipmip_cli_daemon_request_release(&req);
|
|
}
|
|
|
|
|
|
IP_PUBLIC Ip_u32
|
|
ipmip_cli_loglevel_get(Ipmip_cli_daemon_t *daemon)
|
|
{
|
|
Ipmip_cli_daemon_req_t req;
|
|
Ip_u32 size = 0;
|
|
|
|
ipmip_cli_daemon_request_init(&req);
|
|
ipmip_cli_daemon_request_start(&req, IPMIP_CLI_LOG_LEVEL_GET);
|
|
if (ipmip_cli_daemon_request(daemon, &req) == IPCOM_SUCCESS)
|
|
size = ipmip_attr_hdr_find_u32(ipmip_cli_daemon_request_header(&req), IPMIP_CLI_ITEM_SIZE);
|
|
ipmip_cli_daemon_request_release(&req);
|
|
return size;
|
|
}
|
|
|
|
|
|
IP_PUBLIC Ip_u32
|
|
ipmip_cli_history_get(Ipmip_cli_daemon_t *daemon)
|
|
{
|
|
Ipmip_cli_daemon_req_t req;
|
|
Ip_u32 size = 0;
|
|
|
|
ipmip_cli_daemon_request_init(&req);
|
|
ipmip_cli_daemon_request_start(&req, IPMIP_CLI_EVENT_HISTORY_GET);
|
|
if (ipmip_cli_daemon_request(daemon, &req) == IPCOM_SUCCESS)
|
|
size = ipmip_attr_hdr_find_u32(ipmip_cli_daemon_request_header(&req), IPMIP_CLI_ITEM_SIZE);
|
|
ipmip_cli_daemon_request_release(&req);
|
|
return size;
|
|
}
|
|
|
|
|
|
IP_GLOBAL int
|
|
ipmip_cli_shell_cmd(int argc,
|
|
char **argv,
|
|
Ipmip_proc_t *proc,
|
|
Ipmip_cli_daemon_t *daemon)
|
|
{
|
|
static Ipcom_cmd_int_str_map ops[] = {
|
|
{ 0, "loglevel" },
|
|
{ 1, "history" },
|
|
{ 2, "config" },
|
|
{ 3, "events" },
|
|
{ 4, "debug" },
|
|
{ 0, 0 }
|
|
};
|
|
static Ipcom_cmd_int_str_map set_get_ops[] = {
|
|
{ 0, "set" },
|
|
{ 1, "get" },
|
|
{ 0, 0 }
|
|
};
|
|
|
|
static Ipcom_cmd_int_str_map events_ops[] = {
|
|
{ 0, "get" },
|
|
{ 1, "flush" },
|
|
{ 0, 0 }
|
|
};
|
|
|
|
Ipcom_getopt opt;
|
|
Ipmip_cli_daemon_req_t req;
|
|
int op_val;
|
|
int i;
|
|
const char *name = IP_NULL;
|
|
|
|
ipmip_cli_daemon_request_init(&req);
|
|
|
|
if (argc < 2)
|
|
return -1;
|
|
|
|
op_val = ipcom_cmd_str_to_key(ops, argv[1]);
|
|
|
|
if (op_val == -1)
|
|
return -1;
|
|
|
|
ipmip_cli_daemon_request_init(&req);
|
|
|
|
ipcom_getopt_clear_r(&opt);
|
|
if (op_val == 0)
|
|
{
|
|
/* LOGLEVEL */
|
|
int sg;
|
|
int val;
|
|
|
|
if (argc < 3)
|
|
{
|
|
ipcom_printf("Too few arguments to loglevel command"IP_LF);
|
|
goto exit_out;
|
|
}
|
|
|
|
sg = ipcom_cmd_str_to_key(set_get_ops, argv[2]);
|
|
if (sg == -1)
|
|
{
|
|
ipcom_printf("Unknown loglevel subcommand %s"IP_LF, argv[2]);
|
|
goto exit_out;
|
|
}
|
|
|
|
if (sg == 0)
|
|
{
|
|
/* SET */
|
|
if (argc < 4)
|
|
{
|
|
ipcom_printf("Too few arguments to loglevel set command"IP_LF);
|
|
goto exit_out;
|
|
}
|
|
|
|
if ((val = ipmip_util_syslog_priority(argv[3])) == -1)
|
|
{
|
|
ipcom_printf("Bad priority value %s in loglevel set command"IP_LF, argv[3]);
|
|
goto exit_out;
|
|
}
|
|
|
|
ipmip_cli_loglevel_set(daemon, val);
|
|
}
|
|
|
|
/* GET */
|
|
val = ipmip_cli_loglevel_get(daemon);
|
|
ipcom_printf("Current Loglevel: %s"IP_LF, ipmip_util_syslog_priority_name(val));
|
|
}
|
|
else if (op_val == 1)
|
|
{
|
|
/* HISTORY */
|
|
int sg;
|
|
Ip_u32 val;
|
|
|
|
if (argc < 3)
|
|
{
|
|
ipcom_printf("Too few arguments to history command"IP_LF);
|
|
goto exit_out;
|
|
}
|
|
|
|
sg = ipcom_cmd_str_to_key(set_get_ops, argv[2]);
|
|
if (sg == -1)
|
|
{
|
|
ipcom_printf("Unknown history subcommand %s"IP_LF, argv[2]);
|
|
goto exit_out;
|
|
}
|
|
|
|
if (sg == 0)
|
|
{
|
|
/* SET */
|
|
if (argc < 4)
|
|
{
|
|
ipcom_printf("Too few arguments to history set command"IP_LF);
|
|
goto exit_out;
|
|
}
|
|
|
|
val = ipcom_strtoul(argv[3], IP_NULL, 0);
|
|
ipmip_cli_history_set(daemon, val);
|
|
}
|
|
|
|
/* GET */
|
|
val = ipmip_cli_history_get(daemon);
|
|
ipcom_printf("Current History: %u"IP_LF, val);
|
|
}
|
|
else if (op_val == 2)
|
|
{
|
|
/* CONFIG */
|
|
/* Time to retrieve data regarding this particular network */
|
|
while ((i = ipcom_getopt_r(argc - 1, argv + 1, "n:a", &opt)) != -1)
|
|
{
|
|
switch (i)
|
|
{
|
|
case 'a':
|
|
break;
|
|
case 'n':
|
|
name = opt.optarg;
|
|
break;
|
|
default:
|
|
ipcom_printf("invalid option '%c'"IP_LF, i);
|
|
goto exit_out;
|
|
}
|
|
}
|
|
|
|
ipmip_cli_config_print(proc, daemon, name);
|
|
}
|
|
else if (op_val == 3)
|
|
{
|
|
int evop = 0;
|
|
int consumed = 1;
|
|
|
|
if (argc > 3)
|
|
{
|
|
if (argv[2][0] != '-')
|
|
{
|
|
evop = ipcom_cmd_str_to_key(events_ops, argv[2]);
|
|
if (evop == -1)
|
|
{
|
|
ipcom_printf("Unknown events subcommand %s"IP_LF, argv[2]);
|
|
goto exit_out;
|
|
}
|
|
else
|
|
consumed++;
|
|
}
|
|
}
|
|
|
|
if (evop == 0)
|
|
{
|
|
int lvl = IPCOM_LOG_DEBUG2;
|
|
|
|
/* Skip two args; */
|
|
/* Time to retrieve data regarding this particular network */
|
|
while ((i = ipcom_getopt_r(argc - consumed, argv + consumed, "l:", &opt)) != -1)
|
|
{
|
|
switch (i)
|
|
{
|
|
case 'l':
|
|
lvl = ipmip_util_syslog_priority(opt.optarg);
|
|
break;
|
|
default:
|
|
ipcom_printf("invalid option '%c'"IP_LF, i);
|
|
goto exit_out;
|
|
}
|
|
}
|
|
|
|
/* EVENTS */
|
|
ipmip_cli_event_print(proc, daemon, lvl);
|
|
}
|
|
else if (evop == 1)
|
|
{
|
|
ipmip_cli_event_flush(daemon);
|
|
}
|
|
}
|
|
else if (op_val == 4)
|
|
{
|
|
Ipmip_cli_daemon_req_t req;
|
|
int rval;
|
|
|
|
ipmip_cli_daemon_request_init(&req);
|
|
ipmip_cli_daemon_request_start(&req, IPMIP_CLI_TYPE_SYSTEM);
|
|
rval = ipmip_cli_daemon_request(daemon, &req);
|
|
ipmip_cli_daemon_request_release(&req);
|
|
ipcom_printf("returned value '%d'"IP_LF, rval);
|
|
}
|
|
|
|
exit_out:
|
|
ipmip_cli_daemon_request_release(&req);
|
|
return 0;
|
|
}
|
|
|
|
IP_GLOBAL void
|
|
ipmip_cli_shell_usage(Ipmip_proc_t *proc)
|
|
{
|
|
ipmip_util_cmdprintf(proc, 1, "events flush ", "Flush events from the daemon");
|
|
ipmip_util_cmdprintf(proc, 1, "events [get] [-l <loglevel>] ", "Get events from the daemon");
|
|
ipmip_util_identprintf(proc, 2, "-l <loglevel> Only list events higher or equal to <loglevel>"IP_LF);
|
|
|
|
ipmip_util_cmdprintf(proc, 1, "config [-a] [-n <name>] ", "Dump configuration from the daemon");
|
|
ipmip_util_identprintf(proc, 2, "-a Dump all configurations"IP_LF);
|
|
ipmip_util_identprintf(proc, 2, "-n <name> Only dump configuration from the entity specified by name"IP_LF);
|
|
|
|
ipmip_util_cmdprintf(proc, 1, "loglevel set <value|priority>", "Set the loglevel to the indicated priority");
|
|
ipmip_util_identprintf(proc, 2, "<value> A syslog priority value or number"IP_LF);
|
|
|
|
ipmip_util_cmdprintf(proc, 1, "loglevel get", "Get the current loglevel");
|
|
|
|
ipmip_util_cmdprintf(proc, 1, "history set <value>", "Set the history size");
|
|
ipmip_util_identprintf(proc, 2, "<value> The new history size"IP_LF);
|
|
|
|
ipmip_util_cmdprintf(proc, 1, "history get", "Get the history size");
|
|
|
|
#ifdef IPTESTENGINE
|
|
ipmip_util_identprintf(proc, 0, "TEST EXTENSIONS ENABLED" IP_LF);
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 11 PUBLIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* END OF FILE
|
|
****************************************************************************
|
|
*/
|