clixon/lib/src/clixon_proto_encode.c
2016-03-14 21:22:37 +01:00

915 lines
24 KiB
C

/*
*
Copyright (C) 2009-2016 Olof Hagsand and Benny Holmgren
This file is part of CLIXON.
CLIXON is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
CLIXON is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with CLIXON; see the file LICENSE. If not, see
<http://www.gnu.org/licenses/>.
*
* Protocol to communicate between clients (eg clicon_cli, clicon_netconf)
* and server (clicon_backend)
*/
#ifdef HAVE_CONFIG_H
#include "clixon_config.h" /* generated by config & autoconf */
#endif
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <assert.h>
#include <syslog.h>
#include <signal.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
/* cligen */
#include <cligen/cligen.h>
/* clicon */
#include "clixon_err.h"
#include "clixon_log.h"
#include "clixon_queue.h"
#include "clixon_chunk.h"
#include "clixon_sig.h"
#include "clixon_hash.h"
#include "clixon_handle.h"
#include "clixon_proto.h"
#include "clixon_proto_encode.h"
struct clicon_msg *
clicon_msg_commit_encode(char *dbsrc, char *dbdst,
uint32_t snapshot, uint32_t startup,
const char *label)
{
struct clicon_msg *msg;
uint16_t len;
int hdrlen = sizeof(*msg);
int p;
uint32_t tmp;
clicon_debug(2, "%s: snapshot: %d startup: %d dbsrc: %s dbdst: %s",
__FUNCTION__,
snapshot, startup, dbsrc, dbdst);
p = 0;
len = sizeof(*msg) + 2*sizeof(uint32_t) + strlen(dbsrc) + 1 +
strlen(dbdst) + 1;
if ((msg = (struct clicon_msg *)chunk(len, label)) == NULL){
clicon_err(OE_PROTO, errno, "%s: chunk", __FUNCTION__);
return NULL;
}
memset(msg, 0, len);
/* hdr */
msg->op_type = htons(CLICON_MSG_COMMIT);
msg->op_len = htons(len);
/* body */
tmp = htonl(snapshot);
memcpy(msg->op_body+p, &tmp, sizeof(uint32_t));
p += sizeof(uint32_t);
tmp = htonl(startup);
memcpy(msg->op_body+p, &tmp, sizeof(uint32_t));
p += sizeof(uint32_t);
strncpy(msg->op_body+p, dbsrc, len-p-hdrlen);
p += strlen(dbsrc)+1;
strncpy(msg->op_body+p, dbdst, len-p-hdrlen);
p += strlen(dbdst)+1;
return msg;
}
int
clicon_msg_commit_decode(struct clicon_msg *msg,
char **dbsrc, char **dbdst,
uint32_t *snapshot, uint32_t *startup,
const char *label)
{
int p;
uint32_t tmp;
p = 0;
/* body */
memcpy(&tmp, msg->op_body+p, sizeof(uint32_t));
*snapshot = ntohl(tmp);
p += sizeof(uint32_t);
memcpy(&tmp, msg->op_body+p, sizeof(uint32_t));
*startup = ntohl(tmp);
p += sizeof(uint32_t);
if ((*dbsrc = chunk_sprintf(label, "%s", msg->op_body+p)) == NULL){
clicon_err(OE_PROTO, errno, "%s: chunk_sprintf",
__FUNCTION__);
return -1;
}
p += strlen(*dbsrc)+1;
if ((*dbdst = chunk_sprintf(label, "%s", msg->op_body+p)) == NULL){
clicon_err(OE_PROTO, errno, "%s: chunk_sprintf",
__FUNCTION__);
return -1;
}
p += strlen(*dbdst)+1;
clicon_debug(2, "%s: snapshot: %d startup: %d dbsrc: %s dbdst: %s",
__FUNCTION__,
*snapshot, *startup, *dbsrc, *dbdst);
return 0;
}
struct clicon_msg *
clicon_msg_validate_encode(char *db, const char *label)
{
struct clicon_msg *msg;
uint16_t len;
int hdrlen = sizeof(*msg);
clicon_debug(2, "%s: db: %s", __FUNCTION__, db);
len = sizeof(*msg) + strlen(db) + 1;
if ((msg = (struct clicon_msg *)chunk(len, label)) == NULL){
clicon_err(OE_PROTO, errno, "%s: chunk", __FUNCTION__);
return NULL;
}
memset(msg, 0, len);
/* hdr */
msg->op_type = htons(CLICON_MSG_VALIDATE);
msg->op_len = htons(len);
/* body */
strncpy(msg->op_body, db, len-hdrlen);
return msg;
}
int
clicon_msg_validate_decode(struct clicon_msg *msg, char **db, const char *label)
{
/* body */
if ((*db = chunk_sprintf(label, "%s", msg->op_body)) == NULL){
clicon_err(OE_PROTO, errno, "%s: chunk_sprintf", __FUNCTION__);
return -1;
}
clicon_debug(2, "%s: db: %s", __FUNCTION__, *db);
return 0;
}
struct clicon_msg *
clicon_msg_change_encode(char *db,
uint32_t op,
char *key,
char *str,
uint32_t str_len,
const char *label)
{
struct clicon_msg *msg;
uint16_t len;
int hdrlen = sizeof(*msg);
int p;
uint32_t tmp;
clicon_debug(2, "%s: op: %d str_len: %d db: %s key: '%s'",
__FUNCTION__,
op, str_len, db, key);
p = 0;
len = sizeof(*msg) + 2*sizeof(uint32_t) + strlen(db) + 1 +
strlen(key) + 1 + str_len;
if ((msg = (struct clicon_msg *)chunk(len, label)) == NULL){
clicon_err(OE_PROTO, errno, "%s: chunk", __FUNCTION__);
return NULL;
}
memset(msg, 0, len);
/* hdr */
msg->op_type = htons(CLICON_MSG_CHANGE);
msg->op_len = htons(len);
/* body */
tmp = htonl(op);
memcpy(msg->op_body+p, &tmp, sizeof(uint32_t));
p += sizeof(uint32_t);
tmp = htonl(str_len);
memcpy(msg->op_body+p, &tmp, sizeof(uint32_t));
p += sizeof(uint32_t);
strncpy(msg->op_body+p, db, len-p-hdrlen);
p += strlen(db)+1;
strncpy(msg->op_body+p, key, len-p-hdrlen);
p += strlen(key)+1;
memcpy(msg->op_body+p, str, str_len);
p += str_len;
return msg;
}
int
clicon_msg_change_decode(struct clicon_msg *msg,
char **db,
uint32_t *op,
char **key,
char **str,
uint32_t *str_len,
const char *label)
{
int p;
uint32_t tmp;
p = 0;
/* body */
memcpy(&tmp, msg->op_body+p, sizeof(uint32_t));
*op = ntohl(tmp);
p += sizeof(uint32_t);
memcpy(&tmp, msg->op_body+p, sizeof(uint32_t));
*str_len = ntohl(tmp);
p += sizeof(uint32_t);
if ((*db = chunk_sprintf(label, "%s", msg->op_body+p)) == NULL){
clicon_err(OE_PROTO, errno, "%s: chunk_sprintf",
__FUNCTION__);
return -1;
}
p += strlen(*db)+1;
if ((*key = chunk_sprintf(label, "%s", msg->op_body+p)) == NULL){
clicon_err(OE_PROTO, errno, "%s: chunk_sprintf",
__FUNCTION__);
return -1;
}
p += strlen(*key)+1;
if (*str_len){
if ((*str = chunk(*str_len, label)) == NULL){
clicon_err(OE_PROTO, errno, "%s: chunk",
__FUNCTION__);
return -1;
}
memcpy(*str, msg->op_body+p, *str_len);
p += *str_len;
}
else
*str = NULL;
clicon_debug(2, "%s: op: %d str_len: %d db: %s key: '%s'",
__FUNCTION__,
*op, *str_len, *db, *key);
return 0;
}
/*! Encode xmlput / edit of database content
* @param[in] db Name of database
* @param[in] op set|merge|delete. See lv_op_t
* @param[in] xml XML data string
* @param[in] label Memory chunk label
* @retval msg Encoded message
* @retval NULL Error
*/
struct clicon_msg *
clicon_msg_xmlput_encode(char *db,
uint32_t op,
char *xml,
const char *label)
{
struct clicon_msg *msg;
uint16_t len;
int hdrlen = sizeof(*msg);
int p;
uint32_t tmp;
clicon_debug(2, "%s: op: %d db: %s xml: %s",
__FUNCTION__,
op, db, xml);
p = 0;
hdrlen = sizeof(*msg);
len = sizeof(*msg) + sizeof(uint32_t) + strlen(db) + 1 + strlen(xml) + 1;
if ((msg = (struct clicon_msg *)chunk(len, label)) == NULL){
clicon_err(OE_PROTO, errno, "%s: chunk", __FUNCTION__);
return NULL;
}
memset(msg, 0, len);
/* hdr */
msg->op_type = htons(CLICON_MSG_XMLPUT);
msg->op_len = htons(len);
/* body */
tmp = htonl(op);
memcpy(msg->op_body+p, &tmp, sizeof(uint32_t));
p += sizeof(uint32_t);
strncpy(msg->op_body+p, db, len-p-hdrlen);
p += strlen(db)+1;
strncpy(msg->op_body+p, xml, len-p-hdrlen);
p += strlen(xml)+1;
return msg;
}
/*! Decode xmlput / edit of database content
* @param[in] msg Incoming message to be decoded
* @param[out] db Name of database
* @param[out] op set|merge|delete. See lv_op_t
* @param[out] xml XML data string
* @param[in] label Memory chunk label
* @retval 0 OK
* @retval -1 Error
*/
int
clicon_msg_xmlput_decode(struct clicon_msg *msg,
char **db,
uint32_t *op,
char **xml,
const char *label)
{
int p;
uint32_t tmp;
p = 0;
/* body */
memcpy(&tmp, msg->op_body+p, sizeof(uint32_t));
*op = ntohl(tmp);
p += sizeof(uint32_t);
if ((*db = chunk_sprintf(label, "%s", msg->op_body+p)) == NULL){
clicon_err(OE_PROTO, errno, "%s: chunk_sprintf",
__FUNCTION__);
return -1;
}
p += strlen(*db)+1;
if ((*xml = chunk_sprintf(label, "%s", msg->op_body+p)) == NULL){
clicon_err(OE_PROTO, errno, "%s: chunk_sprintf",
__FUNCTION__);
return -1;
}
p += strlen(*xml)+1;
clicon_debug(2, "%s: op: %d db: %s xml: %s",
__FUNCTION__,
*op, *db, *xml);
return 0;
}
struct clicon_msg *
clicon_msg_save_encode(char *db, uint32_t snapshot, char *filename,
const char *label)
{
struct clicon_msg *msg;
uint16_t len;
int hdrlen = sizeof(*msg);
int p;
uint32_t tmp;
clicon_debug(2, "%s: snapshot: %d db: %s filename: %s",
__FUNCTION__,
snapshot, db, filename);
p = 0;
hdrlen = sizeof(*msg);
len = sizeof(*msg) + sizeof(uint32_t) + strlen(db) + 1;
if (!snapshot)
len += strlen(filename) + 1;
if ((msg = (struct clicon_msg *)chunk(len, label)) == NULL){
clicon_err(OE_PROTO, errno, "%s: chunk", __FUNCTION__);
return NULL;
}
memset(msg, 0, len);
/* hdr */
msg->op_type = htons(CLICON_MSG_SAVE);
msg->op_len = htons(len);
/* body */
tmp = htonl(snapshot);
memcpy(msg->op_body+p, &tmp, sizeof(uint32_t));
p += sizeof(uint32_t);
strncpy(msg->op_body+p, db, len-p-hdrlen);
p += strlen(db)+1;
if (!snapshot){
strncpy(msg->op_body+p, filename, len-p-hdrlen);
p += strlen(filename)+1;
}
return msg;
}
int
clicon_msg_save_decode(struct clicon_msg *msg,
char **db, uint32_t *snapshot, char **filename,
const char *label)
{
int p;
uint32_t tmp;
p = 0;
/* body */
memcpy(&tmp, msg->op_body+p, sizeof(uint32_t));
*snapshot = ntohl(tmp);
p += sizeof(uint32_t);
if ((*db = chunk_sprintf(label, "%s", msg->op_body+p)) == NULL){
clicon_err(OE_PROTO, errno, "%s: chunk_sprintf",
__FUNCTION__);
return -1;
}
p += strlen(*db)+1;
if (*snapshot == 0){
if ((*filename = chunk_sprintf(label, "%s", msg->op_body+p)) == NULL){
clicon_err(OE_PROTO, errno, "%s: chunk_sprintf",
__FUNCTION__);
return -1;
}
p += strlen(*filename)+1;
}
clicon_debug(2, "%s: snapshot: %d db: %s filename: %s",
__FUNCTION__,
*snapshot, *db, *filename);
return 0;
}
struct clicon_msg *
clicon_msg_load_encode(int replace, char *db, char *filename, const char *label)
{
struct clicon_msg *msg;
int hdrlen = sizeof(*msg);
uint16_t len;
uint32_t tmp;
int p;
clicon_debug(2, "%s: replace: %d db: %s filename: %s",
__FUNCTION__,
replace, db, filename);
p = 0;
len = sizeof(*msg) + sizeof(uint32_t) + strlen(db) + 1 + strlen(filename) + 1;
if ((msg = (struct clicon_msg *)chunk(len, label)) == NULL){
clicon_err(OE_PROTO, errno, "%s: chunk", __FUNCTION__);
return NULL;
}
memset(msg, 0, len);
/* hdr */
msg->op_type = htons(CLICON_MSG_LOAD);
msg->op_len = htons(len);
/* body */
tmp = htonl(replace);
memcpy(msg->op_body+p, &tmp, sizeof(uint32_t));
p += sizeof(uint32_t);
strncpy(msg->op_body+p, db, len-p-hdrlen);
p += strlen(db)+1;
strncpy(msg->op_body+p, filename, len-p-hdrlen);
p += strlen(filename)+1;
return msg;
}
int
clicon_msg_load_decode(struct clicon_msg *msg,
int *replace,
char **db,
char **filename,
const char *label)
{
int p;
uint32_t tmp;
p = 0;
/* body */
memcpy(&tmp, msg->op_body+p, sizeof(uint32_t));
*replace = ntohl(tmp);
p += sizeof(uint32_t);
if ((*db = chunk_sprintf(label, "%s", msg->op_body+p)) == NULL){
clicon_err(OE_PROTO, errno, "%s: chunk_sprintf",
__FUNCTION__);
return -1;
}
p += strlen(*db)+1;
if ((*filename = chunk_sprintf(label, "%s", msg->op_body+p)) == NULL){
clicon_err(OE_PROTO, errno, "%s: chunk_sprintf",
__FUNCTION__);
return -1;
}
p += strlen(*filename)+1;
clicon_debug(2, "%s: %d db: %s filename: %s",
__FUNCTION__,
ntohs(msg->op_type),
*db, *filename);
return 0;
}
struct clicon_msg *
clicon_msg_copy_encode(char *db_src, char *db_dst,
const char *label)
{
struct clicon_msg *msg;
int hdrlen = sizeof(*msg);
uint16_t len;
int p;
clicon_debug(2, "%s: db_src: %s db_dst: %s",
__FUNCTION__,
db_src, db_dst);
p = 0;
len = hdrlen + strlen(db_src) + 1 + strlen(db_dst) + 1;
if ((msg = (struct clicon_msg *)chunk(len, label)) == NULL){
clicon_err(OE_PROTO, errno, "%s: chunk", __FUNCTION__);
return NULL;
}
memset(msg, 0, len);
/* hdr */
msg->op_type = htons(CLICON_MSG_COPY);
msg->op_len = htons(len);
/* body */
strncpy(msg->op_body+p, db_src, len-p-hdrlen);
p += strlen(db_src)+1;
strncpy(msg->op_body+p, db_dst, len-p-hdrlen);
p += strlen(db_dst)+1;
return msg;
}
int
clicon_msg_copy_decode(struct clicon_msg *msg,
char **db_src, char **db_dst,
const char *label)
{
int p;
p = 0;
/* body */
if ((*db_src = chunk_sprintf(label, "%s", msg->op_body+p)) == NULL){
clicon_err(OE_PROTO, errno, "%s: chunk_sprintf",
__FUNCTION__);
return -1;
}
p += strlen(*db_src)+1;
if ((*db_dst = chunk_sprintf(label, "%s", msg->op_body+p)) == NULL){
clicon_err(OE_PROTO, errno, "%s: chunk_sprintf",
__FUNCTION__);
return -1;
}
p += strlen(*db_dst)+1;
clicon_debug(2, "%s: db_src: %s db_dst: %s",
__FUNCTION__,
*db_src, *db_dst);
return 0;
}
struct clicon_msg *
clicon_msg_kill_encode(uint32_t session_id, const char *label)
{
struct clicon_msg *msg;
uint16_t len;
int p;
uint32_t tmp;
clicon_debug(2, "%s: %d", __FUNCTION__, session_id);
p = 0;
len = sizeof(*msg) + sizeof(uint32_t);
if ((msg = (struct clicon_msg *)chunk(len, label)) == NULL){
clicon_err(OE_PROTO, errno, "%s: chunk", __FUNCTION__);
return NULL;
}
memset(msg, 0, len);
/* hdr */
msg->op_type = htons(CLICON_MSG_KILL);
msg->op_len = htons(len);
/* body */
tmp = htonl(session_id);
memcpy(msg->op_body+p, &tmp, sizeof(uint32_t));
p += sizeof(uint32_t);
return msg;
}
int
clicon_msg_kill_decode(struct clicon_msg *msg,
uint32_t *session_id,
const char *label)
{
int p;
uint32_t tmp;
p = 0;
/* body */
memcpy(&tmp, msg->op_body+p, sizeof(uint32_t));
*session_id = ntohl(tmp);
p += sizeof(uint32_t);
clicon_debug(2, "%s: session-id: %u", __FUNCTION__, *session_id);
return 0;
}
struct clicon_msg *
clicon_msg_debug_encode(uint32_t level, const char *label)
{
struct clicon_msg *msg;
uint16_t len;
int p;
uint32_t tmp;
clicon_debug(2, "%s: %d", __FUNCTION__, label);
p = 0;
len = sizeof(*msg) + sizeof(uint32_t);
if ((msg = (struct clicon_msg *)chunk(len, label)) == NULL){
clicon_err(OE_PROTO, errno, "%s: chunk", __FUNCTION__);
return NULL;
}
memset(msg, 0, len);
/* hdr */
msg->op_type = htons(CLICON_MSG_DEBUG);
msg->op_len = htons(len);
/* body */
tmp = htonl(level);
memcpy(msg->op_body+p, &tmp, sizeof(uint32_t));
p += sizeof(uint32_t);
return msg;
}
int
clicon_msg_debug_decode(struct clicon_msg *msg,
uint32_t *level,
const char *label)
{
int p;
uint32_t tmp;
p = 0;
/* body */
memcpy(&tmp, msg->op_body+p, sizeof(uint32_t));
*level = ntohl(tmp);
p += sizeof(uint32_t);
clicon_debug(2, "%s: session-id: %u", __FUNCTION__, *level);
return 0;
}
struct clicon_msg *
clicon_msg_call_encode(uint16_t op,
char *plugin,
char *func,
uint16_t arglen,
void *arg,
const char *label)
{
struct clicon_msg *msg;
struct clicon_msg_call_req *req;
int hdrlen = sizeof(*msg);
int len;
clicon_debug(2, "%s: %d plugin: %s func: %s arglen: %d",
__FUNCTION__, op, plugin, func, arglen);
len =
hdrlen +
sizeof(struct clicon_msg_call_req) +
strlen(plugin) + 1 +
strlen(func) + 1 +
arglen;
if ((msg = (struct clicon_msg *)chunk(len, label)) == NULL){
clicon_err(OE_PROTO, errno, "%s: chunk", __FUNCTION__);
return NULL;
}
memset(msg, 0, len);
/* hdr */
msg->op_type = htons(CLICON_MSG_CALL);
msg->op_len = htons(len);
/* req */
req = (struct clicon_msg_call_req *)msg->op_body;
req->cr_len = htons(len - hdrlen);
req->cr_op = htons(op);
req->cr_plugin = req->cr_data;
strncpy(req->cr_plugin, plugin, strlen(plugin));
req->cr_func = req->cr_plugin + strlen(req->cr_plugin) + 1;
strncpy(req->cr_func, func, strlen(func));
req->cr_arglen = htons(arglen);
req->cr_arg = req->cr_func + strlen(req->cr_func) + 1;
memcpy(req->cr_arg, arg, arglen);
return msg;
}
int
clicon_msg_call_decode(struct clicon_msg *msg,
struct clicon_msg_call_req **req,
const char *label)
{
uint16_t len;
struct clicon_msg_call_req *r;
r = (struct clicon_msg_call_req *)msg->op_body;
len = ntohs(r->cr_len);
if ((*req = chunk(len, label)) == NULL) {
clicon_err(OE_PROTO, errno, "%s: chunk", __FUNCTION__);
return -1;
}
memcpy(*req, r, len);
(*req)->cr_len = ntohs(r->cr_len);
(*req)->cr_op = ntohs(r->cr_op);
(*req)->cr_arglen = ntohs(r->cr_arglen);
(*req)->cr_plugin = (*req)->cr_data;
(*req)->cr_func = (*req)->cr_plugin + strlen((*req)->cr_plugin) +1;
(*req)->cr_arg = (*req)->cr_func + strlen((*req)->cr_func) +1;
return 0;
}
struct clicon_msg *
clicon_msg_subscription_encode(int status,
char *stream,
enum format_enum format,
char *filter,
const char *label)
{
struct clicon_msg *msg;
uint16_t len;
int hdrlen = sizeof(*msg);
int p;
int tmp;
clicon_debug(2, "%s: %d %d %s %s", __FUNCTION__, status, format, stream, filter);
p = 0;
assert(filter);
len = hdrlen + sizeof(uint32_t) + sizeof(uint32_t) + strlen(stream) + 1 + strlen(filter) + 1;
if ((msg = (struct clicon_msg *)chunk(len, label)) == NULL){
clicon_err(OE_PROTO, errno, "%s: chunk", __FUNCTION__);
return NULL;
}
memset(msg, 0, len);
/* hdr */
msg->op_type = htons(CLICON_MSG_SUBSCRIPTION);
msg->op_len = htons(len);
/* body */
tmp = htonl(status);
memcpy(msg->op_body+p, &tmp, sizeof(int));
p += sizeof(int);
tmp = htonl(format);
memcpy(msg->op_body+p, &tmp, sizeof(int));
p += sizeof(int);
strncpy(msg->op_body+p, stream, len-p-hdrlen);
p += strlen(stream)+1;
strncpy(msg->op_body+p, filter, len-p-hdrlen);
p += strlen(filter)+1;
return msg;
}
int
clicon_msg_subscription_decode(struct clicon_msg *msg,
int *status,
char **stream,
enum format_enum *format,
char **filter,
const char *label)
{
int p;
int tmp;
p = 0;
/* body */
memcpy(&tmp, msg->op_body+p, sizeof(int));
*status = ntohl(tmp);
p += sizeof(int);
memcpy(&tmp, msg->op_body+p, sizeof(int));
*format = ntohl(tmp);
p += sizeof(int);
if ((*stream = chunk_sprintf(label, "%s", msg->op_body+p)) == NULL){
clicon_err(OE_PROTO, errno, "%s: chunk_sprintf",
__FUNCTION__);
return -1;
}
p += strlen(*stream)+1;
if ((*filter = chunk_sprintf(label, "%s", msg->op_body+p)) == NULL){
clicon_err(OE_PROTO, errno, "%s: chunk_sprintf",
__FUNCTION__);
return -1;
}
p += strlen(*filter)+1;
clicon_debug(2, "%s: %d %s %d %s", __FUNCTION__, *status, *filter, *stream, *filter);
return 0;
}
struct clicon_msg *
clicon_msg_notify_encode(int level, char *event, const char *label)
{
struct clicon_msg *msg;
uint16_t len;
int hdrlen = sizeof(*msg);
int p;
int tmp;
clicon_debug(2, "%s: %d %s", __FUNCTION__, level, event);
p = 0;
hdrlen = sizeof(*msg);
len = sizeof(*msg) + sizeof(uint32_t) + strlen(event) + 1;
if ((msg = (struct clicon_msg *)chunk(len, label)) == NULL){
clicon_err(OE_PROTO, errno, "%s: chunk", __FUNCTION__);
return NULL;
}
memset(msg, 0, len);
/* hdr */
msg->op_type = htons(CLICON_MSG_NOTIFY);
msg->op_len = htons(len);
/* body */
tmp = htonl(level);
memcpy(msg->op_body+p, &tmp, sizeof(int));
p += sizeof(int);
strncpy(msg->op_body+p, event, len-p-hdrlen);
p += strlen(event)+1;
return msg;
}
int
clicon_msg_notify_decode(struct clicon_msg *msg,
int *level, char **event,
const char *label)
{
int p;
int tmp;
p = 0;
/* body */
memcpy(&tmp, msg->op_body+p, sizeof(int));
*level = ntohl(tmp);
p += sizeof(int);
if ((*event = chunk_sprintf(label, "%s", msg->op_body+p)) == NULL){
clicon_err(OE_PROTO, errno, "%s: chunk_sprintf",
__FUNCTION__);
return -1;
}
p += strlen(*event)+1;
clicon_debug(2, "%s: %d %s", __FUNCTION__, *level, *event);
return 0;
}
struct clicon_msg *
clicon_msg_err_encode(uint32_t err, uint32_t suberr, char *reason, const char *label)
{
struct clicon_msg *msg;
uint16_t len;
int hdrlen = sizeof(*msg);
int p;
uint32_t tmp;
clicon_debug(2, "%s: %d %d %s", __FUNCTION__, err, suberr, reason);
p = 0;
hdrlen = sizeof(*msg);
len = sizeof(*msg) + 2*sizeof(uint32_t) + strlen(reason) + 1;
if ((msg = (struct clicon_msg *)chunk(len, label)) == NULL){
clicon_err(OE_PROTO, errno, "%s: chunk", __FUNCTION__);
return NULL;
}
memset(msg, 0, len);
/* hdr */
msg->op_type = htons(CLICON_MSG_ERR);
msg->op_len = htons(len);
/* body */
tmp = htonl(err);
memcpy(msg->op_body+p, &tmp, sizeof(uint32_t));
p += sizeof(uint32_t);
tmp = htonl(suberr);
memcpy(msg->op_body+p, &tmp, sizeof(uint32_t));
p += sizeof(uint32_t);
strncpy(msg->op_body+p, reason, len-p-hdrlen);
p += strlen(reason)+1;
return msg;
}
int
clicon_msg_err_decode(struct clicon_msg *msg,
uint32_t *err, uint32_t *suberr, char **reason,
const char *label)
{
int p;
uint32_t tmp;
p = 0;
/* body */
memcpy(&tmp, msg->op_body+p, sizeof(uint32_t));
*err = ntohl(tmp);
p += sizeof(uint32_t);
memcpy(&tmp, msg->op_body+p, sizeof(uint32_t));
*suberr = ntohl(tmp);
p += sizeof(uint32_t);
if ((*reason = chunk_sprintf(label, "%s", msg->op_body+p)) == NULL){
clicon_err(OE_PROTO, errno, "%s: chunk_sprintf",
__FUNCTION__);
return -1;
}
p += strlen(*reason)+1;
clicon_debug(2, "%s: %d %d %s",
__FUNCTION__,
*err, *suberr, *reason);
return 0;
}