/* ****************************************************************************** * 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 ****************************************************************************** */ /* **************************************************************************** * 1 DESCRIPTION **************************************************************************** */ /* **************************************************************************** * 2 CONFIGURATION **************************************************************************** */ #include "ipmip_config.h" /* **************************************************************************** * 3 INCLUDE FILES **************************************************************************** */ #define IPCOM_USE_CLIB_PROTO #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* **************************************************************************** * 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 ] ", "Get events from the daemon"); ipmip_util_identprintf(proc, 2, "-l Only list events higher or equal to "IP_LF); ipmip_util_cmdprintf(proc, 1, "config [-a] [-n ] ", "Dump configuration from the daemon"); ipmip_util_identprintf(proc, 2, "-a Dump all configurations"IP_LF); ipmip_util_identprintf(proc, 2, "-n Only dump configuration from the entity specified by name"IP_LF); ipmip_util_cmdprintf(proc, 1, "loglevel set ", "Set the loglevel to the indicated priority"); ipmip_util_identprintf(proc, 2, " 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 ", "Set the history size"); ipmip_util_identprintf(proc, 2, " 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 **************************************************************************** */