#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <dlfcn.h>
#include <netdb.h>
#include <libdscp.h>
#include <sys/socket.h>
#include <sys/systeminfo.h>
#include <netinet/tcp.h>
#include "dcs.h"
#include "remote_cfg.h"
#include "rdr_param_types.h"
#include "rdr_messages.h"
typedef struct {
int ap_id_int_size;
int ap_id_char_size;
int *ap_id_sizes;
char *ap_id_chars;
int errstring_strlen;
int errstring_pad_sz;
int options_strlen;
int options_pad_sz;
int listopts_strlen;
int listopts_pad_sz;
int function_strlen;
int function_pad_sz;
} rdr_variable_message_info_t;
#define NOMSG 0
#define SHORTMSG (150 * 1024)
#define LONGMSG (3 * 1024 * 1024)
struct {
ulong_t req_max;
ulong_t reply_max;
} msg_sizes[] = {
{ NOMSG, NOMSG },
{ SHORTMSG, SHORTMSG },
{ NOMSG, NOMSG },
{ NOMSG, NOMSG },
{ SHORTMSG, SHORTMSG },
{ SHORTMSG, SHORTMSG },
{ SHORTMSG, SHORTMSG },
{ SHORTMSG, LONGMSG },
{ SHORTMSG, NOMSG },
{ SHORTMSG, NOMSG },
{ SHORTMSG, NOMSG },
{ SHORTMSG, SHORTMSG },
{ SHORTMSG, NOMSG },
{ SHORTMSG, LONGMSG }
};
#define RDR_BAD_FD (-1)
#define RDR_MSG_HDR_SIZE sizeof (rdr_msg_hdr_t)
static const int RDR_ALIGN_64_BIT = 8;
#define LIBDSCP_PATH "/usr/platform/%s/lib/libdscp.so.1"
#define LIBDSCP_BIND "dscpBind"
#define LIBDSCP_SECURE "dscpSecure"
#define LIBDSCP_AUTH "dscpAuth"
typedef enum {
LIBDSCP_UNKNOWN = 0,
LIBDSCP_AVAILABLE,
LIBDSCP_UNAVAILABLE
} dscp_status_t;
typedef struct {
dscp_status_t status;
int (*bind)(int, int, int);
int (*secure)(int, int);
int (*auth)(int, struct sockaddr *, int);
} libdscp_t;
static libdscp_t libdscp;
static int rdr_setopt(int fd, int name, int level);
static int rdr_bind(int fd, struct sockaddr *addr);
static int rdr_secure(int fd, struct sockaddr *addr);
static int rdr_auth(struct sockaddr *addr, int len);
static int rdr_snd(int fd, rdr_msg_hdr_t *hdr, char *data, int data_sz,
int timeout);
static int rdr_snd_raw(int fd, char *msg, int data_sz, int timeout);
static int rdr_rcv(int fd, rdr_msg_hdr_t *hdr, char **data, int timeout);
static int rdr_rcv_raw(int fd, char *msg, int data_size, int timeout);
static int validate_header(rdr_msg_hdr_t *hdr);
static int pack_ses_req_request(ses_req_params_t *params, char **buf,
int *buf_size);
static int unpack_ses_req_request(ses_req_params_t *params, const char *buf);
static int pack_ses_req_reply(ses_req_params_t *params, char **buf,
int *buf_size);
static int unpack_ses_req_reply(ses_req_params_t *params, const char *buf);
static int pack_change_state_request(change_state_params_t *params,
char **buf, int *buf_size);
static int unpack_change_state_request(change_state_params_t *params,
const char *buf);
static int pack_change_state_reply(change_state_params_t *params,
char **buf, int *buf_size);
static int unpack_change_state_reply(change_state_params_t *params,
const char *buf);
static int pack_private_func_request(private_func_params_t *params,
char **buf, int *buf_size);
static int unpack_private_func_request(private_func_params_t *params,
const char *buf);
static int pack_private_func_reply(private_func_params_t *params,
char **buf, int *buf_size);
static int unpack_private_func_reply(private_func_params_t *params,
const char *buf);
static int pack_test_request(test_params_t *params, char **buf, int *buf_size);
static int unpack_test_request(test_params_t *params, const char *buf);
static int pack_test_reply(test_params_t *params, char **buf, int *buf_size);
static int unpack_test_reply(test_params_t *params, const char *buf);
static int pack_list_ext_request(list_ext_params_t *params, char **buf,
int *buf_size);
static int unpack_list_ext_request(list_ext_params_t *params, const char *buf);
static int pack_list_ext_reply(list_ext_params_t *params, char **buf,
int *buf_size);
static int unpack_list_ext_reply(list_ext_params_t *params, const char *buf);
static int pack_help_request(help_params_t *params, char **buf, int *buf_size);
static int unpack_help_request(help_params_t *params, const char *buf);
static int pack_ap_id_cmp_request(ap_id_cmp_params_t *params, char **buf,
int *buf_size);
static int unpack_ap_id_cmp_request(ap_id_cmp_params_t *params,
const char *buf);
static int pack_abort_cmd_request(abort_cmd_params_t *params, char **buf,
int *buf_size);
static int unpack_abort_cmd_request(abort_cmd_params_t *params,
const char *buf);
static int pack_confirm_request(confirm_callback_params_t *params, char **buf,
int *buf_size);
static int unpack_confirm_request(confirm_callback_params_t *params,
const char *buf);
static int pack_confirm_reply(confirm_callback_params_t *params,
char **buf, int *buf_size);
static int unpack_confirm_reply(confirm_callback_params_t *params,
const char *buf);
static int pack_message_request(msg_callback_params_t *params, char **buf,
int *buf_size);
static int unpack_message_request(msg_callback_params_t *params,
const char *buf);
static int pack_rsrc_info_request(rsrc_info_params_t *params, char **buf,
int *buf_size);
static int unpack_rsrc_info_request(rsrc_info_params_t *params,
const char *buf);
static int pack_rsrc_info_reply(rsrc_info_params_t *params, char **buf,
int *buf_size, int encoding);
static int unpack_rsrc_info_reply(rsrc_info_params_t *params, const char *buf);
static int pack_ap_ids(int num_ap_ids, char *const *ap_ids,
rdr_variable_message_info_t *var_msg_info);
static int unpack_ap_ids(int num_ap_ids, char **ap_ids, const char *buf,
rdr_variable_message_info_t *var_msg_info);
static int find_options_sizes(char *options,
rdr_variable_message_info_t *var_msg_info);
static int find_listopts_sizes(char *listopts,
rdr_variable_message_info_t *var_msg_info);
static int find_function_sizes(char *function,
rdr_variable_message_info_t *var_msg_info);
static int find_errstring_sizes(char **errstring,
rdr_variable_message_info_t *var_msg_info);
static int get_ap_ids_from_buf(char ***ap_id_ptr, int num_ap_ids,
rdr_variable_message_info_t *var_msg_info,
const char *buf);
static int get_string_from_buf(char **stringptr, int strsize, const char *buf);
static int cleanup_ap_ids(int num_ap_ids, char **ap_ids);
static int cleanup_errstring(char **errstring);
static void cleanup_variable_ap_id_info(
rdr_variable_message_info_t *var_msg_info);
static int load_libdscp(libdscp_t *libdscp);
int
rdr_open(int family)
{
int newfd;
if ((newfd = socket(family, SOCK_STREAM, 0)) == -1) {
return (RDR_BAD_FD);
}
return (newfd);
}
int
rdr_init(int fd, struct sockaddr *addr, int *opts, int num_opts, int blog)
{
int i;
if ((fd < 0) || (addr == NULL)) {
return (RDR_ERROR);
}
if ((opts == NULL) || (num_opts < 0)) {
num_opts = 0;
}
if (rdr_secure(fd, addr) != RDR_OK) {
return (RDR_NET_ERR);
}
if (rdr_bind(fd, addr) != RDR_OK) {
return (RDR_NET_ERR);
}
if (rdr_setopt(fd, TCP_NODELAY, IPPROTO_TCP) != RDR_OK) {
return (RDR_NET_ERR);
}
for (i = 0; i < num_opts; i++) {
if (rdr_setopt(fd, opts[i], SOL_SOCKET) != RDR_OK) {
return (RDR_NET_ERR);
}
}
if (blog != 0) {
if (listen(fd, blog) == -1) {
return (RDR_NET_ERR);
}
}
return (RDR_OK);
}
int
rdr_connect_clnt(int fd, struct sockaddr *addr)
{
unsigned int addr_len;
if (addr == NULL) {
return (RDR_ERROR);
}
switch (addr->sa_family) {
case AF_INET:
addr_len = sizeof (struct sockaddr_in);
break;
case AF_INET6:
addr_len = sizeof (struct sockaddr_in6);
break;
default:
return (RDR_ERROR);
}
if (connect(fd, addr, addr_len) == -1) {
return (RDR_NET_ERR);
}
return (RDR_OK);
}
int
rdr_connect_srv(int fd)
{
int newfd;
unsigned int faddr_len;
struct sockaddr_storage faddr;
faddr_len = sizeof (faddr);
if ((newfd = accept(fd, (struct sockaddr *)&faddr, &faddr_len)) == -1) {
return (RDR_BAD_FD);
}
if (rdr_auth((struct sockaddr *)&faddr, faddr_len) != RDR_OK) {
(void) close(newfd);
return (RDR_BAD_FD);
}
return (newfd);
}
int
rdr_reject(int fd)
{
unsigned int faddr_len;
struct sockaddr_storage faddr;
faddr_len = sizeof (faddr);
if (accept(fd, (struct sockaddr *)&faddr, &faddr_len) == -1) {
return (RDR_NET_ERR);
}
(void) close(fd);
return (RDR_OK);
}
int
rdr_close(int fd)
{
(void) close(fd);
return (RDR_OK);
}
int
rdr_snd_msg(int fd, rdr_msg_hdr_t *hdr, cfga_params_t *param, int timeout)
{
int err;
char *pack_buf = NULL;
int pack_buf_sz = 0;
if ((hdr == NULL) || (param == NULL)) {
return (RDR_ERROR);
}
switch (hdr->message_opcode) {
case RDR_SES_REQ: {
ses_req_params_t *rparam;
rparam = (ses_req_params_t *)param;
if (hdr->data_type == RDR_REQUEST) {
err = pack_ses_req_request(rparam,
&pack_buf, &pack_buf_sz);
} else {
err = pack_ses_req_reply(rparam,
&pack_buf, &pack_buf_sz);
}
break;
}
case RDR_SES_ESTBL:
case RDR_SES_END:
err = RDR_OK;
break;
case RDR_CONF_CHANGE_STATE: {
change_state_params_t *cparam;
cparam = (change_state_params_t *)param;
if (hdr->data_type == RDR_REQUEST) {
err = pack_change_state_request(cparam,
&pack_buf, &pack_buf_sz);
} else {
err = pack_change_state_reply(cparam,
&pack_buf, &pack_buf_sz);
}
break;
}
case RDR_CONF_PRIVATE_FUNC: {
private_func_params_t *pparam;
pparam = (private_func_params_t *)param;
if (hdr->data_type == RDR_REQUEST) {
err = pack_private_func_request(pparam,
&pack_buf, &pack_buf_sz);
} else {
err = pack_private_func_reply(pparam,
&pack_buf, &pack_buf_sz);
}
break;
}
case RDR_CONF_TEST: {
test_params_t *tparam;
tparam = (test_params_t *)param;
if (hdr->data_type == RDR_REQUEST) {
err = pack_test_request(tparam,
&pack_buf, &pack_buf_sz);
} else {
err = pack_test_reply(tparam,
&pack_buf, &pack_buf_sz);
}
break;
}
case RDR_CONF_LIST_EXT: {
list_ext_params_t *lparam;
lparam = (list_ext_params_t *)param;
if (hdr->data_type == RDR_REQUEST) {
err = pack_list_ext_request(lparam, &pack_buf,
&pack_buf_sz);
} else {
err = pack_list_ext_reply(lparam, &pack_buf,
&pack_buf_sz);
}
break;
}
case RDR_CONF_HELP: {
help_params_t *hparam;
hparam = (help_params_t *)param;
if (hdr->data_type == RDR_REQUEST) {
err = pack_help_request(hparam,
&pack_buf, &pack_buf_sz);
} else {
err = RDR_OK;
}
break;
}
case RDR_CONF_AP_ID_CMP: {
ap_id_cmp_params_t *aparam;
aparam = (ap_id_cmp_params_t *)param;
if (hdr->data_type == RDR_REQUEST) {
err = pack_ap_id_cmp_request(aparam,
&pack_buf, &pack_buf_sz);
} else {
err = RDR_OK;
}
break;
}
case RDR_CONF_ABORT_CMD: {
abort_cmd_params_t *aparam;
aparam = (abort_cmd_params_t *)param;
if (hdr->data_type == RDR_REQUEST) {
err = pack_abort_cmd_request(aparam,
&pack_buf, &pack_buf_sz);
} else {
err = RDR_OK;
}
break;
}
case RDR_CONF_CONFIRM_CALLBACK: {
confirm_callback_params_t *cparam;
cparam = (confirm_callback_params_t *)param;
if (hdr->data_type == RDR_REQUEST) {
err = pack_confirm_request(cparam,
&pack_buf, &pack_buf_sz);
} else {
err = pack_confirm_reply(cparam, &pack_buf,
&pack_buf_sz);
}
break;
}
case RDR_CONF_MSG_CALLBACK: {
msg_callback_params_t *mparam;
mparam = (msg_callback_params_t *)param;
if (hdr->data_type == RDR_REQUEST) {
err = pack_message_request(mparam,
&pack_buf, &pack_buf_sz);
} else {
err = RDR_MSG_INVAL;
}
break;
}
case RDR_RSRC_INFO: {
rsrc_info_params_t *rparam;
rparam = (rsrc_info_params_t *)param;
if (hdr->data_type == RDR_REQUEST) {
err = pack_rsrc_info_request(rparam, &pack_buf,
&pack_buf_sz);
} else {
if ((hdr->major_version == 1) &&
(hdr->minor_version == 0)) {
err = pack_rsrc_info_reply(rparam,
&pack_buf, &pack_buf_sz,
NV_ENCODE_NATIVE);
} else {
err = pack_rsrc_info_reply(rparam,
&pack_buf, &pack_buf_sz,
NV_ENCODE_XDR);
}
}
break;
}
default:
err = RDR_MSG_INVAL;
break;
}
if (err != RDR_OK) {
return (err);
}
err = rdr_snd(fd, hdr, pack_buf, pack_buf_sz, timeout);
free((void *)pack_buf);
return (err);
}
int
rdr_rcv_msg(int fd, rdr_msg_hdr_t *hdr, cfga_params_t *param, int timeout)
{
int err;
char *unpack_buf = NULL;
if ((hdr == NULL) || (param == NULL)) {
return (RDR_ERROR);
}
(void) memset(param, 0, sizeof (cfga_params_t));
if ((err = rdr_rcv(fd, hdr, &unpack_buf, timeout)) != RDR_OK) {
return (err);
}
switch (hdr->message_opcode) {
case RDR_SES_REQ: {
ses_req_params_t *rparam;
rparam = (ses_req_params_t *)param;
if (hdr->data_type == RDR_REQUEST) {
err = unpack_ses_req_request(rparam,
unpack_buf);
} else {
err = unpack_ses_req_reply(rparam, unpack_buf);
}
break;
}
case RDR_SES_ESTBL:
case RDR_SES_END:
(void) memset(param, 0, sizeof (cfga_params_t));
err = RDR_OK;
break;
case RDR_CONF_CHANGE_STATE: {
change_state_params_t *cparam;
cparam = (change_state_params_t *)param;
if (hdr->data_type == RDR_REQUEST) {
err = unpack_change_state_request(cparam,
unpack_buf);
} else {
err = unpack_change_state_reply(cparam,
unpack_buf);
}
break;
}
case RDR_CONF_PRIVATE_FUNC: {
private_func_params_t *pparam;
pparam = (private_func_params_t *)param;
if (hdr->data_type == RDR_REQUEST) {
err = unpack_private_func_request(pparam,
unpack_buf);
} else {
err = unpack_private_func_reply(pparam,
unpack_buf);
}
break;
}
case RDR_CONF_TEST: {
test_params_t *tparam;
tparam = (test_params_t *)param;
if (hdr->data_type == RDR_REQUEST) {
err = unpack_test_request(tparam, unpack_buf);
} else {
err = unpack_test_reply(tparam, unpack_buf);
}
break;
}
case RDR_CONF_LIST_EXT: {
list_ext_params_t *lparam;
lparam = (list_ext_params_t *)param;
if (hdr->data_type == RDR_REQUEST) {
err = unpack_list_ext_request(lparam,
unpack_buf);
} else {
err = unpack_list_ext_reply(lparam, unpack_buf);
}
break;
}
case RDR_CONF_HELP: {
help_params_t *hparam;
hparam = (help_params_t *)param;
if (hdr->data_type == RDR_REQUEST) {
err = unpack_help_request(hparam,
unpack_buf);
} else {
err = RDR_OK;
}
break;
}
case RDR_CONF_AP_ID_CMP: {
ap_id_cmp_params_t *aparam;
aparam = (ap_id_cmp_params_t *)param;
if (hdr->data_type == RDR_REQUEST) {
err = unpack_ap_id_cmp_request(aparam,
unpack_buf);
} else {
err = RDR_OK;
}
break;
}
case RDR_CONF_ABORT_CMD: {
abort_cmd_params_t *aparam;
aparam = (abort_cmd_params_t *)param;
if (hdr->data_type == RDR_REQUEST) {
err = unpack_abort_cmd_request(aparam,
unpack_buf);
} else {
(void) memset(param, 0, sizeof (cfga_params_t));
err = RDR_OK;
}
break;
}
case RDR_CONF_CONFIRM_CALLBACK: {
confirm_callback_params_t *cparam;
cparam = (confirm_callback_params_t *)param;
if (hdr->data_type == RDR_REQUEST) {
err = unpack_confirm_request(cparam,
unpack_buf);
} else {
err = unpack_confirm_reply(cparam, unpack_buf);
}
break;
}
case RDR_CONF_MSG_CALLBACK: {
msg_callback_params_t *mparam;
mparam = (msg_callback_params_t *)param;
if (hdr->data_type == RDR_REQUEST) {
err = unpack_message_request(mparam,
unpack_buf);
} else {
(void) memset(param, 0, sizeof (cfga_params_t));
err = RDR_MSG_INVAL;
}
break;
}
case RDR_RSRC_INFO: {
rsrc_info_params_t *rparam;
rparam = (rsrc_info_params_t *)param;
if (hdr->data_type == RDR_REQUEST) {
err = unpack_rsrc_info_request(rparam,
unpack_buf);
} else {
err = unpack_rsrc_info_reply(rparam,
unpack_buf);
}
break;
}
default:
err = RDR_MSG_INVAL;
break;
}
free(unpack_buf);
if (err != RDR_OK) {
return (err);
}
return (RDR_OK);
}
int
rdr_cleanup_params(rdr_msg_opcode_t message_opcode, cfga_params_t *param)
{
if ((param == NULL)) {
return (RDR_ERROR);
}
switch (message_opcode) {
case RDR_SES_REQ: {
ses_req_params_t *sparam;
sparam = (ses_req_params_t *)param;
if (sparam->locale_str != NULL) {
free((void *)sparam->locale_str);
sparam->locale_str = NULL;
}
break;
}
case RDR_SES_ESTBL:
case RDR_SES_END:
break;
case RDR_CONF_CHANGE_STATE: {
change_state_params_t *cparam;
cparam = (change_state_params_t *)param;
cleanup_ap_ids(cparam->num_ap_ids, (char **)cparam->ap_ids);
cparam->ap_ids = NULL;
if (cparam->options != NULL) {
free((void *)cparam->options);
cparam->options = NULL;
}
if (cparam->confp != NULL) {
free((void *)cparam->confp);
cparam->confp = NULL;
}
if (cparam->msgp != NULL) {
free((void *)cparam->msgp);
cparam->msgp = NULL;
}
cleanup_errstring(cparam->errstring);
break;
}
case RDR_CONF_PRIVATE_FUNC: {
private_func_params_t *pparam;
pparam = (private_func_params_t *)param;
cleanup_ap_ids(pparam->num_ap_ids, (char **)pparam->ap_ids);
pparam->ap_ids = NULL;
if (pparam->options != NULL) {
free((void *)pparam->options);
pparam->options = NULL;
}
if (pparam->confp != NULL) {
free((void *)pparam->confp);
pparam->confp = NULL;
}
if (pparam->msgp != NULL) {
free((void *)pparam->msgp);
pparam->msgp = NULL;
}
cleanup_errstring(pparam->errstring);
break;
}
case RDR_CONF_TEST: {
test_params_t *tparam;
tparam = (test_params_t *)param;
cleanup_ap_ids(tparam->num_ap_ids, (char **)tparam->ap_ids);
tparam->ap_ids = NULL;
if (tparam->options != NULL) {
free((void *)tparam->options);
tparam->options = NULL;
}
if (tparam->msgp != NULL) {
free((void *)tparam->msgp);
tparam->msgp = NULL;
}
cleanup_errstring(tparam->errstring);
break;
}
case RDR_CONF_LIST_EXT: {
list_ext_params_t *lparam;
lparam = (list_ext_params_t *)param;
cleanup_ap_ids(lparam->num_ap_ids, (char **)lparam->ap_ids);
lparam->ap_ids = NULL;
if (lparam->nlist != NULL) {
free((void *)lparam->nlist);
lparam->nlist = NULL;
}
if (lparam->ap_id_list != NULL) {
if (*lparam->ap_id_list != NULL) {
free((void *)*lparam->ap_id_list);
}
free((void *)lparam->ap_id_list);
lparam->ap_id_list = NULL;
}
if (lparam->ap_id_list != NULL) {
free((void *)lparam->ap_id_list);
lparam->ap_id_list = NULL;
}
if (lparam->options != NULL) {
free((void *)lparam->options);
lparam->options = NULL;
}
if (lparam->listopts != NULL) {
free((void *)lparam->listopts);
lparam->listopts = NULL;
}
cleanup_errstring(lparam->errstring);
break;
}
case RDR_CONF_HELP: {
help_params_t *hparam;
hparam = (help_params_t *)param;
cleanup_ap_ids(hparam->num_ap_ids, (char **)hparam->ap_ids);
hparam->ap_ids = NULL;
if (hparam->msgp != NULL) {
free((void *)hparam->msgp);
hparam->msgp = NULL;
}
if (hparam->options != NULL) {
free((void *)hparam->options);
hparam->options = NULL;
}
break;
}
case RDR_CONF_AP_ID_CMP: {
ap_id_cmp_params_t *aparam;
aparam = (ap_id_cmp_params_t *)param;
if (aparam->ap_log_id1 != NULL) {
free((void *)aparam->ap_log_id1);
aparam->ap_log_id1 = NULL;
}
if (aparam->ap_log_id2 != NULL) {
free((void *)aparam->ap_log_id2);
aparam->ap_log_id2 = NULL;
}
break;
}
case RDR_CONF_ABORT_CMD:
break;
case RDR_CONF_CONFIRM_CALLBACK: {
confirm_callback_params_t *cparam;
cparam = (confirm_callback_params_t *)param;
if (cparam->confp != NULL) {
free((void *)cparam->confp);
cparam->confp = NULL;
}
if (cparam->message != NULL) {
free((void *)cparam->message);
cparam->message = NULL;
}
break;
}
case RDR_CONF_MSG_CALLBACK: {
msg_callback_params_t *mparam;
mparam = (msg_callback_params_t *)param;
if (mparam->msgp != NULL) {
free((void *)mparam->msgp);
mparam->msgp = NULL;
}
if (mparam->message != NULL) {
free((void *)mparam->message);
mparam->message = NULL;
}
break;
}
default:
return (RDR_ERROR);
break;
}
return (RDR_OK);
}
int
rdr_setsockopt(int fd, int level, int optname, const void *optval, int optlen)
{
if (setsockopt(fd, level, optname, optval, optlen) == -1)
return (RDR_NET_ERR);
else
return (RDR_OK);
}
static int
rdr_setopt(int fd, int name, int level)
{
int on = 1;
if (setsockopt(fd, level, name, &on, sizeof (on)) == -1) {
return (RDR_NET_ERR);
}
return (RDR_OK);
}
static int
rdr_bind(int fd, struct sockaddr *addr)
{
unsigned int addr_len;
int rc;
switch (addr->sa_family) {
case AF_INET:
addr_len = sizeof (struct sockaddr_in);
break;
case AF_INET6:
addr_len = sizeof (struct sockaddr_in6);
break;
default:
return (RDR_ERROR);
}
rc = bind(fd, addr, addr_len);
if ((rc == -1) && (errno != EINVAL)) {
return (RDR_NET_ERR);
}
addr_len = sizeof (*addr);
if (getsockname(fd, addr, &addr_len) == -1) {
(void) memset(addr, 0, sizeof (*addr));
return (RDR_NET_ERR);
}
return (RDR_OK);
}
static int
rdr_secure(int fd, struct sockaddr *addr)
{
struct sockaddr_in *sin;
int port;
int error;
if (use_libdscp == 0) {
return (RDR_OK);
}
if (load_libdscp(&libdscp) != 1) {
return (RDR_ERROR);
}
sin = (struct sockaddr_in *)addr;
port = ntohs(sin->sin_port);
error = libdscp.bind(0, fd, port);
if ((error != DSCP_OK) && (error != DSCP_ERROR_ALREADY)) {
return (RDR_ERROR);
}
if (libdscp.secure(0, fd) != DSCP_OK) {
return (RDR_ERROR);
}
return (RDR_OK);
}
static int
rdr_auth(struct sockaddr *addr, int len)
{
if (use_libdscp != 0) {
if ((load_libdscp(&libdscp) == 0) ||
(libdscp.auth(0, addr, len) != DSCP_OK)) {
return (RDR_ERROR);
}
}
return (RDR_OK);
}
static int
rdr_snd(int fd, rdr_msg_hdr_t *hdr, char *data, int data_sz, int timeout)
{
int err;
if (hdr == NULL) {
return (RDR_ERROR);
}
hdr->pad_byte1 = 0;
hdr->pad_byte2 = 0;
hdr->data_length = data_sz;
err = rdr_snd_raw(fd, (char *)hdr, RDR_MSG_HDR_SIZE, timeout);
if (err != RDR_OK) {
return (err);
}
if (data_sz == 0) {
return (RDR_OK);
}
err = rdr_snd_raw(fd, data, data_sz, timeout);
if (err != RDR_OK) {
return (err);
}
return (RDR_OK);
}
static int
rdr_snd_raw(int fd, char *msg, int data_sz, int timeout)
{
int err;
int num_bytes;
int bytes_left;
char *bufp;
struct pollfd pfd;
bufp = (char *)msg;
bytes_left = data_sz;
pfd.fd = fd;
pfd.events = POLLOUT;
while (bytes_left > 0) {
pfd.revents = 0;
if ((err = poll(&pfd, 1, timeout)) == -1) {
if (errno == EINTR) {
return (RDR_ABORTED);
}
return (RDR_ERROR);
} else if (err == 0) {
return (RDR_TIMEOUT);
}
if (pfd.revents & POLLOUT) {
num_bytes = write(fd, bufp, bytes_left);
if (num_bytes == -1) {
if (errno == EPIPE) {
return (RDR_ABORTED);
} else {
return (RDR_NET_ERR);
}
}
if (num_bytes == 0) {
return (RDR_ABORTED);
}
} else {
return (RDR_NET_ERR);
}
bytes_left -= num_bytes;
bufp += num_bytes;
}
return (RDR_OK);
}
static int
rdr_rcv(int fd, rdr_msg_hdr_t *hdr, char **data, int timeout)
{
int err;
int data_sz;
char hdr_buf[RDR_MSG_HDR_SIZE];
char *buf = NULL;
if (hdr == NULL) {
return (RDR_ERROR);
}
err = rdr_rcv_raw(fd, hdr_buf, RDR_MSG_HDR_SIZE, timeout);
if (err != RDR_OK) {
return (err);
}
if (validate_header((rdr_msg_hdr_t *)hdr_buf) != RDR_OK) {
return (RDR_MSG_INVAL);
}
data_sz = ((rdr_msg_hdr_t *)hdr_buf)->data_length;
buf = (char *)malloc(data_sz);
if (!buf) {
return (RDR_MEM_ALLOC);
}
if (data_sz != 0) {
err = rdr_rcv_raw(fd, buf, data_sz, timeout);
if (err != RDR_OK) {
free((void *)buf);
return (err);
}
}
*data = buf;
(void) memcpy(hdr, hdr_buf, RDR_MSG_HDR_SIZE);
return (RDR_OK);
}
static int
rdr_rcv_raw(int fd, char *msg, int data_size, int timeout)
{
int num_bytes;
int err;
int bytes_left;
char *bufp;
struct pollfd pollfd;
bufp = (char *)msg;
bytes_left = data_size;
pollfd.fd = fd;
pollfd.events = POLLIN;
while (bytes_left > 0) {
errno = 0;
pollfd.revents = 0;
if ((err = poll(&pollfd, 1, timeout)) == -1) {
if ((errno == 0) || (errno == EINTR)) {
continue;
}
return (RDR_ABORTED);
} else if (err == 0) {
return (RDR_TIMEOUT);
}
if (pollfd.revents & POLLIN) {
num_bytes = read(fd, bufp, bytes_left);
if (num_bytes == -1) {
if (errno == ECONNRESET) {
return (RDR_ABORTED);
} else {
return (RDR_NET_ERR);
}
}
if (num_bytes == 0) {
return (RDR_ABORTED);
}
} else {
return (RDR_NET_ERR);
}
bytes_left -= num_bytes;
bufp += num_bytes;
}
return (RDR_OK);
}
static int
validate_header(rdr_msg_hdr_t *hdr)
{
unsigned char op;
if (hdr == NULL) {
return (RDR_ERROR);
}
op = hdr->message_opcode;
if ((op < RDR_SES_REQ) || (op >= RDR_NUM_OPS)) {
return (RDR_ERROR);
}
switch (hdr->data_type) {
case RDR_REQUEST:
if (hdr->data_length > msg_sizes[op].req_max) {
return (RDR_ERROR);
}
break;
case RDR_REPLY:
if (hdr->data_length > msg_sizes[op].reply_max) {
return (RDR_ERROR);
}
break;
default:
return (RDR_ERROR);
}
return (RDR_OK);
}
static int
pack_ses_req_request(ses_req_params_t *params, char **buf, int *buf_size)
{
char *bufptr;
int locale_str_len;
rdr_ses_req_t ses_req;
if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
return (RDR_ERROR);
}
if (params->locale_str != NULL) {
locale_str_len = strlen(params->locale_str) + 1;
} else {
locale_str_len = 0;
}
*buf_size = sizeof (rdr_ses_req_t);
*buf_size += locale_str_len;
*buf = (char *)malloc(*buf_size);
if (*buf == NULL) {
return (RDR_MEM_ALLOC);
}
ses_req.locale_size = locale_str_len;
bufptr = *buf;
(void) memcpy(bufptr, &ses_req, sizeof (rdr_ses_req_t));
bufptr += sizeof (rdr_ses_req_t);
if (params->locale_str != NULL) {
(void) memcpy(bufptr, params->locale_str, locale_str_len);
bufptr += locale_str_len;
}
return (RDR_OK);
}
static int
unpack_ses_req_request(ses_req_params_t *params, const char *buf)
{
char *bufptr;
rdr_ses_req_t ses_req_data;
if ((params == NULL) || (buf == NULL)) {
return (RDR_ERROR);
}
bufptr = (char *)buf;
(void) memcpy(&ses_req_data, bufptr, sizeof (rdr_ses_req_t));
bufptr += sizeof (rdr_ses_req_t);
if (get_string_from_buf(&(params->locale_str),
ses_req_data.locale_size, bufptr)) {
return (RDR_ERROR);
}
return (RDR_OK);
}
static int
pack_ses_req_reply(ses_req_params_t *params, char **buf, int *buf_size)
{
rdr_ses_req_reply_t ses_req_reply_data;
if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
return (RDR_ERROR);
}
*buf_size = sizeof (rdr_ses_req_reply_t);
*buf = (char *)malloc(*buf_size);
if (*buf == NULL) {
return (RDR_MEM_ALLOC);
}
ses_req_reply_data.session_id = params->session_id;
(void) memcpy(*buf, &ses_req_reply_data, sizeof (rdr_ses_req_reply_t));
return (RDR_OK);
}
static int
unpack_ses_req_reply(ses_req_params_t *params, const char *buf)
{
rdr_ses_req_reply_t *ses_req_reply_datap;
if ((params == NULL) || (buf == NULL)) {
return (RDR_ERROR);
}
ses_req_reply_datap = (rdr_ses_req_reply_t *)buf;
params->session_id = ses_req_reply_datap->session_id;
return (RDR_OK);
}
static int
pack_change_state_request(change_state_params_t *params, char **buf,
int *buf_size)
{
int i;
char *bufptr;
rdr_change_state_t change_state_data;
rdr_variable_message_info_t var_msg_info;
if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
return (RDR_ERROR);
}
(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
if (pack_ap_ids(params->num_ap_ids, params->ap_ids, &var_msg_info)) {
cleanup_variable_ap_id_info(&var_msg_info);
return (RDR_ERROR);
}
if (find_options_sizes(params->options, &var_msg_info)) {
cleanup_variable_ap_id_info(&var_msg_info);
return (RDR_ERROR);
}
*buf_size = sizeof (rdr_change_state_t);
*buf_size += var_msg_info.ap_id_int_size;
*buf_size += var_msg_info.ap_id_char_size;
*buf_size += var_msg_info.options_strlen;
*buf_size += var_msg_info.options_pad_sz;
*buf = (char *)malloc(*buf_size);
if (*buf == NULL) {
cleanup_variable_ap_id_info(&var_msg_info);
return (RDR_MEM_ALLOC);
}
change_state_data.num_ap_ids = params->num_ap_ids;
change_state_data.ap_id_char_size = var_msg_info.ap_id_char_size;
change_state_data.options_size = var_msg_info.options_strlen +
var_msg_info.options_pad_sz;
if (params->confp != NULL) {
change_state_data.confirm_callback_id =
(unsigned long)params->confp->confirm;
change_state_data.confirm_appdata_ptr =
(unsigned long)params->confp->appdata_ptr;
} else {
change_state_data.confirm_callback_id = 0;
change_state_data.confirm_appdata_ptr = 0;
}
if (params->msgp != NULL) {
change_state_data.msg_callback_id =
(unsigned long)params->msgp->message_routine;
change_state_data.msg_appdata_ptr =
(unsigned long)params->msgp->appdata_ptr;
} else {
change_state_data.msg_callback_id = 0;
change_state_data.msg_appdata_ptr = 0;
}
change_state_data.flags = params->flags;
change_state_data.timeval = params->timeval;
change_state_data.state_change_cmd = params->state_change;
if (params->errstring != NULL) {
change_state_data.error_msg_ctl = RDR_GENERATE_ERR_MSGS;
} else {
change_state_data.error_msg_ctl = RDR_DONT_GENERATE_ERR_MSGS;
}
change_state_data.retries = params->retries;
bufptr = *buf;
(void) memcpy(bufptr, &change_state_data, sizeof (rdr_change_state_t));
bufptr += sizeof (rdr_change_state_t);
if (var_msg_info.ap_id_sizes != NULL) {
(void) memcpy(bufptr, var_msg_info.ap_id_sizes,
var_msg_info.ap_id_int_size);
bufptr += var_msg_info.ap_id_int_size;
}
if (var_msg_info.ap_id_chars != NULL) {
(void) memcpy(bufptr, var_msg_info.ap_id_chars,
var_msg_info.ap_id_char_size);
bufptr += var_msg_info.ap_id_char_size;
}
if (params->options != NULL) {
(void) memcpy(bufptr, params->options,
var_msg_info.options_strlen);
bufptr += var_msg_info.options_strlen;
for (i = 0; i < var_msg_info.options_pad_sz; i++) {
bufptr[i] = 0;
}
bufptr += var_msg_info.options_pad_sz;
}
cleanup_variable_ap_id_info(&var_msg_info);
return (RDR_OK);
}
static int
unpack_change_state_request(change_state_params_t *params, const char *buf)
{
char *bufptr;
rdr_variable_message_info_t var_msg_info;
rdr_change_state_t change_state_data;
if ((params == NULL) || (buf == NULL)) {
return (RDR_ERROR);
}
(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
bufptr = (char *)buf;
(void) memcpy(&change_state_data, bufptr, sizeof (rdr_change_state_t));
bufptr += sizeof (rdr_change_state_t);
var_msg_info.ap_id_char_size = change_state_data.ap_id_char_size;
if (get_ap_ids_from_buf((char ***)&(params->ap_ids),
change_state_data.num_ap_ids, &var_msg_info, bufptr)) {
return (RDR_ERROR);
}
bufptr += var_msg_info.ap_id_int_size;
bufptr += var_msg_info.ap_id_char_size;
if (get_string_from_buf(&(params->options),
change_state_data.options_size, bufptr)) {
return (RDR_ERROR);
}
bufptr += change_state_data.options_size;
params->state_change = (cfga_cmd_t)change_state_data.state_change_cmd;
params->num_ap_ids = change_state_data.num_ap_ids;
params->confp = (struct cfga_confirm *)
malloc(sizeof (struct cfga_confirm));
if (params->confp == NULL) {
return (RDR_MEM_ALLOC);
}
(void) memcpy((void*)params->confp,
&(change_state_data.confirm_callback_id), sizeof (unsigned long));
params->confp->appdata_ptr =
(void*)change_state_data.confirm_appdata_ptr;
params->msgp = (struct cfga_msg *)malloc(sizeof (struct cfga_msg));
if (params->msgp == NULL) {
return (RDR_MEM_ALLOC);
}
(void) memcpy((void*)params->msgp,
&(change_state_data.msg_callback_id), sizeof (unsigned long));
params->msgp->appdata_ptr =
(void*)change_state_data.msg_appdata_ptr;
if (change_state_data.error_msg_ctl == RDR_GENERATE_ERR_MSGS) {
params->errstring = (char **)malloc(sizeof (char *));
if (params->errstring == NULL) {
return (RDR_MEM_ALLOC);
}
*(params->errstring) = NULL;
} else {
params->errstring = NULL;
}
params->flags = change_state_data.flags;
params->timeval = change_state_data.timeval;
params->retries = change_state_data.retries;
return (RDR_OK);
}
static int
pack_change_state_reply(change_state_params_t *params, char **buf,
int *buf_size)
{
int i;
char *bufptr;
rdr_change_state_reply_t change_state_data;
rdr_variable_message_info_t var_msg_info;
(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
return (RDR_ERROR);
}
if (find_errstring_sizes(params->errstring, &var_msg_info)) {
return (RDR_ERROR);
}
*buf_size = sizeof (rdr_change_state_reply_t);
*buf_size += var_msg_info.errstring_strlen;
*buf_size += var_msg_info.errstring_pad_sz;
*buf = (char *)malloc(*buf_size);
if (*buf == NULL) {
return (RDR_MEM_ALLOC);
}
change_state_data.errstring_size = var_msg_info.errstring_strlen +
var_msg_info.errstring_pad_sz;
bufptr = *buf;
(void) memcpy(bufptr, &change_state_data,
sizeof (rdr_change_state_reply_t));
bufptr += sizeof (rdr_change_state_reply_t);
if ((params->errstring != NULL) && (*(params->errstring) != NULL)) {
(void) memcpy(bufptr, *(params->errstring),
var_msg_info.errstring_strlen);
bufptr += var_msg_info.errstring_strlen;
for (i = 0; i < var_msg_info.errstring_pad_sz; i++) {
bufptr[i] = 0;
}
bufptr += var_msg_info.errstring_pad_sz;
}
return (RDR_OK);
}
static int
unpack_change_state_reply(change_state_params_t *params, const char *buf)
{
char *bufptr;
rdr_change_state_reply_t change_state_data;
if ((params == NULL) || (buf == NULL)) {
return (RDR_ERROR);
}
bufptr = (char *)buf;
(void) memcpy(&change_state_data, bufptr,
sizeof (rdr_change_state_reply_t));
bufptr += sizeof (rdr_change_state_reply_t);
params->errstring = (char **)malloc(sizeof (char *));
if (params->errstring == NULL) {
return (RDR_MEM_ALLOC);
}
if (get_string_from_buf(params->errstring,
change_state_data.errstring_size, bufptr)) {
return (RDR_ERROR);
}
bufptr += change_state_data.errstring_size;
return (RDR_OK);
}
static int
pack_private_func_request(private_func_params_t *params, char **buf,
int *buf_size)
{
int i;
char *bufptr;
rdr_private_func_t private_func_data;
rdr_variable_message_info_t var_msg_info;
if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
return (RDR_ERROR);
}
(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
if (pack_ap_ids(params->num_ap_ids, params->ap_ids, &var_msg_info)) {
cleanup_variable_ap_id_info(&var_msg_info);
return (RDR_ERROR);
}
if (find_options_sizes(params->options, &var_msg_info)) {
cleanup_variable_ap_id_info(&var_msg_info);
return (RDR_ERROR);
}
if (find_function_sizes(params->function, &var_msg_info)) {
cleanup_variable_ap_id_info(&var_msg_info);
return (RDR_ERROR);
}
*buf_size = sizeof (rdr_private_func_t);
*buf_size += var_msg_info.ap_id_int_size;
*buf_size += var_msg_info.ap_id_char_size;
*buf_size += var_msg_info.options_strlen;
*buf_size += var_msg_info.options_pad_sz;
*buf_size += var_msg_info.function_strlen;
*buf_size += var_msg_info.function_pad_sz;
*buf = (char *)malloc(*buf_size);
if (*buf == NULL) {
cleanup_variable_ap_id_info(&var_msg_info);
return (RDR_MEM_ALLOC);
}
private_func_data.num_ap_ids = params->num_ap_ids;
private_func_data.ap_id_char_size = var_msg_info.ap_id_char_size;
private_func_data.options_size = var_msg_info.options_strlen +
var_msg_info.options_pad_sz;
private_func_data.function_size = var_msg_info.function_strlen +
var_msg_info.function_pad_sz;
if (params->confp != NULL) {
private_func_data.confirm_callback_id =
(unsigned long)params->confp->confirm;
private_func_data.confirm_appdata_ptr =
(unsigned long)params->confp->appdata_ptr;
} else {
private_func_data.confirm_callback_id = 0;
private_func_data.confirm_appdata_ptr = 0;
}
if (params->msgp != NULL) {
private_func_data.msg_callback_id =
(unsigned long)params->msgp->message_routine;
private_func_data.msg_appdata_ptr =
(unsigned long)params->msgp->appdata_ptr;
} else {
private_func_data.msg_callback_id = 0;
private_func_data.msg_appdata_ptr = 0;
}
private_func_data.flags = params->flags;
if (params->errstring != NULL) {
private_func_data.error_msg_ctl = RDR_GENERATE_ERR_MSGS;
} else {
private_func_data.error_msg_ctl = RDR_DONT_GENERATE_ERR_MSGS;
}
bufptr = *buf;
(void) memcpy(bufptr, &private_func_data, sizeof (rdr_private_func_t));
bufptr += sizeof (rdr_private_func_t);
if (var_msg_info.ap_id_sizes != NULL) {
(void) memcpy(bufptr, var_msg_info.ap_id_sizes,
var_msg_info.ap_id_int_size);
bufptr += var_msg_info.ap_id_int_size;
}
if (var_msg_info.ap_id_chars != NULL) {
(void) memcpy(bufptr, var_msg_info.ap_id_chars,
var_msg_info.ap_id_char_size);
bufptr += var_msg_info.ap_id_char_size;
}
if (params->options != NULL) {
(void) memcpy(bufptr, params->options,
var_msg_info.options_strlen);
bufptr += var_msg_info.options_strlen;
for (i = 0; i < var_msg_info.options_pad_sz; i++) {
bufptr[i] = 0;
}
bufptr += var_msg_info.options_pad_sz;
}
if (params->function != NULL) {
(void) memcpy(bufptr, params->function,
var_msg_info.function_strlen);
bufptr += var_msg_info.function_strlen;
for (i = 0; i < var_msg_info.function_pad_sz; i++) {
bufptr[i] = 0;
}
bufptr += var_msg_info.function_pad_sz;
}
cleanup_variable_ap_id_info(&var_msg_info);
return (RDR_OK);
}
static int
unpack_private_func_request(private_func_params_t *params, const char *buf)
{
char *bufptr;
rdr_variable_message_info_t var_msg_info;
rdr_private_func_t private_func_data;
(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
if ((params == NULL) || (buf == NULL)) {
return (RDR_ERROR);
}
bufptr = (char *)buf;
(void) memcpy(&private_func_data, bufptr, sizeof (rdr_private_func_t));
bufptr += sizeof (rdr_private_func_t);
var_msg_info.ap_id_char_size = private_func_data.ap_id_char_size;
if (get_ap_ids_from_buf((char ***)&(params->ap_ids),
private_func_data.num_ap_ids, &var_msg_info, bufptr)) {
return (RDR_ERROR);
}
bufptr += var_msg_info.ap_id_int_size;
bufptr += var_msg_info.ap_id_char_size;
if (get_string_from_buf(&(params->options),
private_func_data.options_size, bufptr)) {
return (RDR_ERROR);
}
bufptr += private_func_data.options_size;
if (get_string_from_buf(&(params->function),
private_func_data.function_size, bufptr)) {
return (RDR_ERROR);
}
bufptr += private_func_data.function_size;
params->num_ap_ids = private_func_data.num_ap_ids;
params->confp = (struct cfga_confirm *)
malloc(sizeof (struct cfga_confirm));
if (params->confp == NULL) {
return (RDR_MEM_ALLOC);
}
(void) memcpy((void*)params->confp,
&(private_func_data.confirm_callback_id), sizeof (unsigned long));
params->confp->appdata_ptr =
(void*)private_func_data.confirm_appdata_ptr;
params->msgp = (struct cfga_msg *)malloc(sizeof (struct cfga_msg));
if (params->msgp == NULL) {
return (RDR_MEM_ALLOC);
}
(void) memcpy((void*)params->msgp,
&(private_func_data.msg_callback_id), sizeof (unsigned long));
params->msgp->appdata_ptr =
(void*)private_func_data.msg_appdata_ptr;
if (private_func_data.error_msg_ctl == RDR_GENERATE_ERR_MSGS) {
params->errstring = (char **)malloc(sizeof (char *));
if (params->errstring == NULL) {
return (RDR_MEM_ALLOC);
}
*(params->errstring) = NULL;
} else {
params->errstring = NULL;
}
params->flags = private_func_data.flags;
return (RDR_OK);
}
static int
pack_private_func_reply(private_func_params_t *params, char **buf,
int *buf_size)
{
int i;
char *bufptr;
rdr_private_func_reply_t private_func_data;
rdr_variable_message_info_t var_msg_info;
(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
return (RDR_ERROR);
}
if (find_errstring_sizes(params->errstring, &var_msg_info)) {
return (RDR_ERROR);
}
*buf_size = sizeof (rdr_private_func_reply_t);
*buf_size += var_msg_info.errstring_strlen;
*buf_size += var_msg_info.errstring_pad_sz;
*buf = (char *)malloc(*buf_size);
if (*buf == NULL) {
return (RDR_MEM_ALLOC);
}
private_func_data.errstring_size = var_msg_info.errstring_strlen +
var_msg_info.errstring_pad_sz;
bufptr = *buf;
(void) memcpy(bufptr, &private_func_data,
sizeof (rdr_private_func_reply_t));
bufptr += sizeof (rdr_private_func_reply_t);
if ((params->errstring != NULL) && (*(params->errstring) != NULL)) {
(void) memcpy(bufptr, *(params->errstring),
var_msg_info.errstring_strlen);
bufptr += var_msg_info.errstring_strlen;
for (i = 0; i < var_msg_info.errstring_pad_sz; i++) {
bufptr[i] = 0;
}
bufptr += var_msg_info.errstring_pad_sz;
}
return (RDR_OK);
}
static int
unpack_private_func_reply(private_func_params_t *params, const char *buf)
{
char *bufptr;
rdr_private_func_reply_t private_func_data;
if ((params == NULL) || (buf == NULL)) {
return (RDR_ERROR);
}
bufptr = (char *)buf;
(void) memcpy(&private_func_data, bufptr,
sizeof (rdr_private_func_reply_t));
bufptr += sizeof (rdr_private_func_reply_t);
params->errstring = (char **)malloc(sizeof (char *));
if (params->errstring == NULL) {
return (RDR_MEM_ALLOC);
}
if (get_string_from_buf(params->errstring,
private_func_data.errstring_size, bufptr)) {
return (RDR_ERROR);
}
bufptr += private_func_data.errstring_size;
return (RDR_OK);
}
static int
pack_test_request(test_params_t *params, char **buf, int *buf_size)
{
int i;
char *bufptr;
rdr_test_t test_data;
rdr_variable_message_info_t var_msg_info;
if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
return (RDR_ERROR);
}
(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
if (pack_ap_ids(params->num_ap_ids, params->ap_ids, &var_msg_info)) {
cleanup_variable_ap_id_info(&var_msg_info);
return (RDR_ERROR);
}
if (find_options_sizes(params->options, &var_msg_info)) {
cleanup_variable_ap_id_info(&var_msg_info);
return (RDR_ERROR);
}
*buf_size = sizeof (rdr_test_t);
*buf_size += var_msg_info.ap_id_int_size;
*buf_size += var_msg_info.ap_id_char_size;
*buf_size += var_msg_info.options_strlen;
*buf_size += var_msg_info.options_pad_sz;
*buf = (char *)malloc(*buf_size);
if (*buf == NULL) {
cleanup_variable_ap_id_info(&var_msg_info);
return (RDR_MEM_ALLOC);
}
test_data.num_ap_ids = params->num_ap_ids;
test_data.ap_id_char_size = var_msg_info.ap_id_char_size;
test_data.options_size = var_msg_info.options_strlen +
var_msg_info.options_pad_sz;
if (params->msgp != NULL) {
test_data.msg_callback_id =
(unsigned long)params->msgp->message_routine;
test_data.msg_appdata_ptr =
(unsigned long)params->msgp->appdata_ptr;
} else {
test_data.msg_callback_id = 0;
test_data.msg_appdata_ptr = 0;
}
test_data.flags = params->flags;
if (params->errstring != NULL) {
test_data.error_msg_ctl = RDR_GENERATE_ERR_MSGS;
} else {
test_data.error_msg_ctl = RDR_DONT_GENERATE_ERR_MSGS;
}
bufptr = *buf;
(void) memcpy(bufptr, &test_data, sizeof (rdr_test_t));
bufptr += sizeof (rdr_test_t);
if (var_msg_info.ap_id_sizes != NULL) {
(void) memcpy(bufptr, var_msg_info.ap_id_sizes,
var_msg_info.ap_id_int_size);
bufptr += var_msg_info.ap_id_int_size;
}
if (var_msg_info.ap_id_chars != NULL) {
(void) memcpy(bufptr, var_msg_info.ap_id_chars,
var_msg_info.ap_id_char_size);
bufptr += var_msg_info.ap_id_char_size;
}
if (params->options != NULL) {
(void) memcpy(bufptr, params->options,
var_msg_info.options_strlen);
bufptr += var_msg_info.options_strlen;
for (i = 0; i < var_msg_info.options_pad_sz; i++) {
bufptr[i] = 0;
}
bufptr += var_msg_info.options_pad_sz;
}
cleanup_variable_ap_id_info(&var_msg_info);
return (RDR_OK);
}
static int
unpack_test_request(test_params_t *params, const char *buf)
{
char *bufptr;
rdr_variable_message_info_t var_msg_info;
rdr_test_t test_data;
if ((params == NULL) || (buf == NULL)) {
return (RDR_ERROR);
}
(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
bufptr = (char *)buf;
(void) memcpy(&test_data, bufptr, sizeof (rdr_test_t));
bufptr += sizeof (rdr_test_t);
var_msg_info.ap_id_char_size = test_data.ap_id_char_size;
if (get_ap_ids_from_buf((char ***)&(params->ap_ids),
test_data.num_ap_ids, &var_msg_info, bufptr)) {
return (RDR_ERROR);
}
bufptr += var_msg_info.ap_id_int_size;
bufptr += var_msg_info.ap_id_char_size;
if (get_string_from_buf(&(params->options),
test_data.options_size, bufptr)) {
return (RDR_ERROR);
}
bufptr += test_data.options_size;
params->num_ap_ids = test_data.num_ap_ids;
params->msgp = (struct cfga_msg *)malloc(sizeof (struct cfga_msg));
if (params->msgp == NULL) {
return (RDR_MEM_ALLOC);
}
(void) memcpy((void*)params->msgp,
&(test_data.msg_callback_id), sizeof (unsigned long));
params->msgp->appdata_ptr =
(void*)test_data.msg_appdata_ptr;
if (test_data.error_msg_ctl == RDR_GENERATE_ERR_MSGS) {
params->errstring = (char **)malloc(sizeof (char *));
if (params->errstring == NULL) {
return (RDR_MEM_ALLOC);
}
*(params->errstring) = NULL;
} else {
params->errstring = NULL;
}
params->flags = test_data.flags;
return (RDR_OK);
}
static int
pack_test_reply(test_params_t *params, char **buf, int *buf_size)
{
int i;
char *bufptr;
rdr_test_reply_t test_data;
rdr_variable_message_info_t var_msg_info;
if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
return (RDR_ERROR);
}
(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
if (find_errstring_sizes(params->errstring, &var_msg_info)) {
return (RDR_ERROR);
}
*buf_size = sizeof (rdr_test_reply_t);
*buf_size += var_msg_info.errstring_strlen;
*buf_size += var_msg_info.errstring_pad_sz;
*buf = (char *)malloc(*buf_size);
if (*buf == NULL) {
return (RDR_MEM_ALLOC);
}
test_data.errstring_size = var_msg_info.errstring_strlen +
var_msg_info.errstring_pad_sz;
bufptr = *buf;
(void) memcpy(bufptr, &test_data, sizeof (rdr_test_reply_t));
bufptr += sizeof (rdr_test_reply_t);
if ((params->errstring != NULL) && (*(params->errstring) != NULL)) {
(void) memcpy(bufptr, *(params->errstring),
var_msg_info.errstring_strlen);
bufptr += var_msg_info.errstring_strlen;
for (i = 0; i < var_msg_info.errstring_pad_sz; i++) {
bufptr[i] = 0;
}
bufptr += var_msg_info.errstring_pad_sz;
}
return (RDR_OK);
}
static int
unpack_test_reply(test_params_t *params, const char *buf)
{
char *bufptr;
rdr_test_reply_t test_data;
if ((params == NULL) || (buf == NULL)) {
return (RDR_ERROR);
}
bufptr = (char *)buf;
(void) memcpy(&test_data, bufptr, sizeof (rdr_test_reply_t));
bufptr += sizeof (rdr_test_reply_t);
params->errstring = (char **)malloc(sizeof (char *));
if (params->errstring == NULL) {
return (RDR_MEM_ALLOC);
}
if (get_string_from_buf(params->errstring,
test_data.errstring_size, bufptr)) {
return (RDR_ERROR);
}
bufptr += test_data.errstring_size;
return (RDR_OK);
}
static int
pack_list_ext_request(list_ext_params_t *params, char **buf, int *buf_size)
{
int i;
char *bufptr;
rdr_list_ext_t list_ext_data;
rdr_variable_message_info_t var_msg_info;
if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
return (RDR_ERROR);
}
(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
if (pack_ap_ids(params->num_ap_ids, params->ap_ids, &var_msg_info)) {
cleanup_variable_ap_id_info(&var_msg_info);
return (RDR_ERROR);
}
if (find_options_sizes(params->options, &var_msg_info)) {
cleanup_variable_ap_id_info(&var_msg_info);
return (RDR_ERROR);
}
if (find_listopts_sizes(params->listopts, &var_msg_info)) {
cleanup_variable_ap_id_info(&var_msg_info);
return (RDR_ERROR);
}
*buf_size = sizeof (rdr_list_ext_t);
*buf_size += var_msg_info.ap_id_int_size;
*buf_size += var_msg_info.ap_id_char_size;
*buf_size += var_msg_info.options_strlen;
*buf_size += var_msg_info.options_pad_sz;
*buf_size += var_msg_info.listopts_strlen;
*buf_size += var_msg_info.listopts_pad_sz;
*buf = (char *)malloc(*buf_size);
if (*buf == NULL) {
cleanup_variable_ap_id_info(&var_msg_info);
return (RDR_MEM_ALLOC);
}
list_ext_data.num_ap_ids = params->num_ap_ids;
list_ext_data.ap_id_char_size = var_msg_info.ap_id_char_size;
list_ext_data.options_size = var_msg_info.options_strlen +
var_msg_info.options_pad_sz;
list_ext_data.listopts_size = var_msg_info.listopts_strlen +
var_msg_info.listopts_pad_sz;
if (params->errstring != NULL) {
list_ext_data.error_msg_ctl = RDR_GENERATE_ERR_MSGS;
} else {
list_ext_data.error_msg_ctl = RDR_DONT_GENERATE_ERR_MSGS;
}
if ((params->num_ap_ids != 0) || (params->ap_ids != NULL)) {
list_ext_data.list_msg_ctl = RDR_LIST_ONLY_PARAM_APS;
} else {
list_ext_data.list_msg_ctl = RDR_LIST_ALL_APS;
}
list_ext_data.flags = params->flags;
list_ext_data.permissions = params->permissions;
bufptr = *buf;
(void) memcpy(bufptr, &list_ext_data, sizeof (rdr_list_ext_t));
bufptr += sizeof (rdr_list_ext_t);
if (var_msg_info.ap_id_sizes != NULL) {
(void) memcpy(bufptr, var_msg_info.ap_id_sizes,
var_msg_info.ap_id_int_size);
bufptr += var_msg_info.ap_id_int_size;
}
if (var_msg_info.ap_id_chars != NULL) {
(void) memcpy(bufptr, var_msg_info.ap_id_chars,
var_msg_info.ap_id_char_size);
bufptr += var_msg_info.ap_id_char_size;
}
if (params->options != NULL) {
(void) memcpy(bufptr, params->options,
var_msg_info.options_strlen);
bufptr += var_msg_info.options_strlen;
for (i = 0; i < var_msg_info.options_pad_sz; i++) {
bufptr[i] = 0;
}
bufptr += var_msg_info.options_pad_sz;
}
if (params->listopts != NULL) {
(void) memcpy(bufptr, params->listopts,
var_msg_info.listopts_strlen);
bufptr += var_msg_info.listopts_strlen;
for (i = 0; i < var_msg_info.listopts_pad_sz; i++) {
bufptr[i] = 0;
}
bufptr += var_msg_info.listopts_pad_sz;
}
cleanup_variable_ap_id_info(&var_msg_info);
return (RDR_OK);
}
static int
unpack_list_ext_request(list_ext_params_t *params, const char *buf)
{
char *bufptr;
rdr_variable_message_info_t var_msg_info;
rdr_list_ext_t list_ext_data;
if ((params == NULL) || (buf == NULL)) {
return (RDR_ERROR);
}
(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
bufptr = (char *)buf;
(void) memcpy(&list_ext_data, bufptr, sizeof (rdr_list_ext_t));
bufptr += sizeof (rdr_list_ext_t);
var_msg_info.ap_id_char_size = list_ext_data.ap_id_char_size;
if (get_ap_ids_from_buf(&(params->ap_ids), list_ext_data.num_ap_ids,
&var_msg_info, bufptr)) {
return (RDR_ERROR);
}
bufptr += var_msg_info.ap_id_int_size;
bufptr += var_msg_info.ap_id_char_size;
if (get_string_from_buf(&(params->options),
list_ext_data.options_size, bufptr)) {
return (RDR_ERROR);
}
bufptr += list_ext_data.options_size;
if (get_string_from_buf(&(params->listopts),
list_ext_data.listopts_size, bufptr)) {
return (RDR_ERROR);
}
bufptr += list_ext_data.listopts_size;
params->num_ap_ids = list_ext_data.num_ap_ids;
params->ap_id_list = (rdr_list_t **)malloc(sizeof (rdr_list_t *));
if (params->ap_id_list == NULL) {
return (RDR_MEM_ALLOC);
}
*(params->ap_id_list) = NULL;
params->nlist = (int *)malloc(sizeof (int));
if (params->nlist == NULL) {
return (RDR_MEM_ALLOC);
}
if (list_ext_data.error_msg_ctl == RDR_GENERATE_ERR_MSGS) {
params->errstring = (char **)malloc(sizeof (char *));
if (params->errstring == NULL) {
return (RDR_MEM_ALLOC);
}
*(params->errstring) = NULL;
} else {
params->errstring = NULL;
}
params->flags = list_ext_data.flags;
params->permissions = list_ext_data.permissions;
return (RDR_OK);
}
static int
pack_list_ext_reply(list_ext_params_t *params, char **buf, int *buf_size)
{
int i;
char *bufptr;
rdr_list_ext_reply_t list_ext_data;
rdr_variable_message_info_t var_msg_info;
int list_data_size;
(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
return (RDR_ERROR);
}
if (find_errstring_sizes(params->errstring, &var_msg_info)) {
return (RDR_ERROR);
}
if (params->nlist == NULL) {
list_data_size = 0;
} else {
list_data_size = *(params->nlist) * sizeof (rdr_list_t);
}
*buf_size = sizeof (rdr_list_ext_reply_t);
*buf_size += list_data_size;
*buf_size += var_msg_info.errstring_strlen;
*buf_size += var_msg_info.errstring_pad_sz;
*buf = (char *)malloc(*buf_size);
if (*buf == NULL) {
return (RDR_MEM_ALLOC);
}
list_ext_data.num_ap_ids = (params->nlist) ? *(params->nlist) : 0;
list_ext_data.errstring_size = var_msg_info.errstring_strlen +
var_msg_info.errstring_pad_sz;
bufptr = *buf;
(void) memcpy(bufptr, &list_ext_data, sizeof (rdr_list_ext_reply_t));
bufptr += sizeof (rdr_list_ext_reply_t);
if ((params->ap_id_list != NULL) && (*(params->ap_id_list) != NULL)) {
(void) memcpy(bufptr, *(params->ap_id_list), list_data_size);
bufptr += list_data_size;
} else if (list_data_size) {
(void) free((void *)*buf);
*buf = NULL;
return (RDR_ERROR);
}
if ((params->errstring != NULL) && (*(params->errstring) != NULL)) {
(void) memcpy(bufptr, *(params->errstring),
var_msg_info.errstring_strlen);
bufptr += var_msg_info.errstring_strlen;
for (i = 0; i < var_msg_info.errstring_pad_sz; i++) {
bufptr[i] = 0;
}
bufptr += var_msg_info.errstring_pad_sz;
}
return (RDR_OK);
}
static int
unpack_list_ext_reply(list_ext_params_t *params, const char *buf)
{
int list_data_size;
char *bufptr;
rdr_list_ext_reply_t list_ext_data;
if ((params == NULL) || (buf == NULL)) {
return (RDR_ERROR);
}
bufptr = (char *)buf;
(void) memcpy(&list_ext_data, bufptr, sizeof (rdr_list_ext_reply_t));
bufptr += sizeof (rdr_list_ext_reply_t);
if (list_ext_data.num_ap_ids > 0) {
params->nlist = (int *)malloc(sizeof (int));
if (params->nlist == NULL) {
return (RDR_MEM_ALLOC);
}
*(params->nlist) = list_ext_data.num_ap_ids;
params->ap_id_list = (rdr_list_t **)
malloc(sizeof (rdr_list_t *));
if (params->ap_id_list == NULL) {
return (RDR_MEM_ALLOC);
}
*(params->ap_id_list) = (rdr_list_t *)
malloc(sizeof (rdr_list_t) * list_ext_data.num_ap_ids);
if (*(params->ap_id_list) == NULL) {
return (RDR_MEM_ALLOC);
}
list_data_size = list_ext_data.num_ap_ids * sizeof (rdr_list_t);
(void) memcpy(*(params->ap_id_list), bufptr, list_data_size);
bufptr += list_data_size;
}
params->errstring = (char **)malloc(sizeof (char *));
if (params->errstring == NULL) {
return (RDR_MEM_ALLOC);
}
if (get_string_from_buf(params->errstring,
list_ext_data.errstring_size, bufptr)) {
return (RDR_ERROR);
}
bufptr += list_ext_data.errstring_size;
return (RDR_OK);
}
static int
pack_help_request(help_params_t *params, char **buf, int *buf_size)
{
int i;
char *bufptr;
rdr_help_t help_data;
rdr_variable_message_info_t var_msg_info;
(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
return (RDR_ERROR);
}
if (pack_ap_ids(params->num_ap_ids, params->ap_ids, &var_msg_info)) {
cleanup_variable_ap_id_info(&var_msg_info);
return (RDR_ERROR);
}
if (find_options_sizes(params->options, &var_msg_info)) {
cleanup_variable_ap_id_info(&var_msg_info);
return (RDR_ERROR);
}
*buf_size = sizeof (rdr_help_t);
*buf_size += var_msg_info.ap_id_int_size;
*buf_size += var_msg_info.ap_id_char_size;
*buf_size += var_msg_info.options_strlen;
*buf_size += var_msg_info.options_pad_sz;
*buf = (char *)malloc(*buf_size);
if (*buf == NULL) {
cleanup_variable_ap_id_info(&var_msg_info);
return (RDR_MEM_ALLOC);
}
help_data.num_ap_ids = params->num_ap_ids;
help_data.ap_id_char_size = var_msg_info.ap_id_char_size;
help_data.options_size = var_msg_info.options_strlen +
var_msg_info.options_pad_sz;
if (params->msgp != NULL) {
help_data.msg_callback_id =
(unsigned long)params->msgp->message_routine;
help_data.msg_appdata_ptr =
(unsigned long)params->msgp->appdata_ptr;
} else {
help_data.msg_callback_id = 0;
help_data.msg_appdata_ptr = 0;
}
help_data.flags = params->flags;
bufptr = *buf;
(void) memcpy(bufptr, &help_data, sizeof (rdr_help_t));
bufptr += sizeof (rdr_help_t);
if (var_msg_info.ap_id_sizes != NULL) {
(void) memcpy(bufptr, var_msg_info.ap_id_sizes,
var_msg_info.ap_id_int_size);
bufptr += var_msg_info.ap_id_int_size;
}
if (var_msg_info.ap_id_chars != NULL) {
(void) memcpy(bufptr, var_msg_info.ap_id_chars,
var_msg_info.ap_id_char_size);
bufptr += var_msg_info.ap_id_char_size;
}
if (params->options != NULL) {
(void) memcpy(bufptr, params->options,
var_msg_info.options_strlen);
bufptr += var_msg_info.options_strlen;
for (i = 0; i < var_msg_info.options_pad_sz; i++) {
bufptr[i] = 0;
}
bufptr += var_msg_info.options_pad_sz;
}
cleanup_variable_ap_id_info(&var_msg_info);
return (RDR_OK);
}
static int
unpack_help_request(help_params_t *params, const char *buf)
{
char *bufptr;
rdr_variable_message_info_t var_msg_info;
rdr_help_t help_data;
if ((params == NULL) || (buf == NULL)) {
return (RDR_ERROR);
}
(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
bufptr = (char *)buf;
(void) memcpy(&help_data, bufptr, sizeof (rdr_help_t));
bufptr += sizeof (rdr_help_t);
var_msg_info.ap_id_char_size = help_data.ap_id_char_size;
if (get_ap_ids_from_buf((char ***)&(params->ap_ids),
help_data.num_ap_ids, &var_msg_info, bufptr)) {
return (RDR_ERROR);
}
bufptr += var_msg_info.ap_id_int_size;
bufptr += var_msg_info.ap_id_char_size;
if (get_string_from_buf(&(params->options),
help_data.options_size, bufptr)) {
return (RDR_ERROR);
}
bufptr += help_data.options_size;
params->num_ap_ids = help_data.num_ap_ids;
params->msgp = (struct cfga_msg *)malloc(sizeof (struct cfga_msg));
if (params->msgp == NULL) {
return (RDR_MEM_ALLOC);
}
(void) memcpy((void*)params->msgp, &(help_data.msg_callback_id),
sizeof (unsigned long));
params->msgp->appdata_ptr = (void*)help_data.msg_appdata_ptr;
params->flags = help_data.flags;
return (RDR_OK);
}
static int
pack_ap_id_cmp_request(ap_id_cmp_params_t *params, char **buf, int *buf_size)
{
int i;
char *bufptr;
rdr_ap_id_cmp_t ap_id_cmp_data;
int ap_id1_strlen;
int ap_id1_pad_sz;
int ap_id2_strlen;
int ap_id2_pad_sz;
if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
return (RDR_ERROR);
}
if (params->ap_log_id1 != NULL) {
ap_id1_strlen = strlen(params->ap_log_id1) + 1;
ap_id1_pad_sz = RDR_ALIGN_64_BIT -
(ap_id1_strlen % RDR_ALIGN_64_BIT);
} else {
ap_id1_strlen = 0;
ap_id1_pad_sz = 0;
}
if (params->ap_log_id2 != NULL) {
ap_id2_strlen = strlen(params->ap_log_id2) + 1;
ap_id2_pad_sz = RDR_ALIGN_64_BIT -
(ap_id2_strlen % RDR_ALIGN_64_BIT);
} else {
ap_id2_strlen = 0;
ap_id2_pad_sz = 0;
}
*buf_size = sizeof (rdr_ap_id_cmp_t);
*buf_size += ap_id1_strlen;
*buf_size += ap_id1_pad_sz;
*buf_size += ap_id2_strlen;
*buf_size += ap_id2_pad_sz;
*buf = (char *)malloc(*buf_size);
if (*buf == NULL) {
return (RDR_MEM_ALLOC);
}
ap_id_cmp_data.ap_id1_size = ap_id1_strlen + ap_id1_pad_sz;
ap_id_cmp_data.ap_id2_size = ap_id2_strlen + ap_id2_pad_sz;
bufptr = *buf;
(void) memcpy(bufptr, &ap_id_cmp_data, sizeof (rdr_ap_id_cmp_t));
bufptr += sizeof (rdr_ap_id_cmp_t);
if (params->ap_log_id1 != NULL) {
(void) memcpy(bufptr, params->ap_log_id1, ap_id1_strlen);
bufptr += ap_id1_strlen;
for (i = 0; i < ap_id1_pad_sz; i++) {
bufptr[i] = 0;
}
bufptr += ap_id1_pad_sz;
}
if (params->ap_log_id2 != NULL) {
(void) memcpy(bufptr, params->ap_log_id2, ap_id2_strlen);
bufptr += ap_id2_strlen;
for (i = 0; i < ap_id2_pad_sz; i++) {
bufptr[i] = 0;
}
bufptr += ap_id2_pad_sz;
}
return (RDR_OK);
}
static int
unpack_ap_id_cmp_request(ap_id_cmp_params_t *params, const char *buf)
{
char *bufptr;
rdr_ap_id_cmp_t ap_id_cmp_data;
if ((params == NULL) || (buf == NULL)) {
return (RDR_ERROR);
}
bufptr = (char *)buf;
(void) memcpy(&ap_id_cmp_data, bufptr, sizeof (rdr_ap_id_cmp_t));
bufptr += sizeof (rdr_ap_id_cmp_t);
if (get_string_from_buf(&(params->ap_log_id1),
ap_id_cmp_data.ap_id1_size, bufptr)) {
return (RDR_ERROR);
}
bufptr += ap_id_cmp_data.ap_id1_size;
if (get_string_from_buf(&(params->ap_log_id2),
ap_id_cmp_data.ap_id2_size, bufptr)) {
return (RDR_ERROR);
}
bufptr += ap_id_cmp_data.ap_id2_size;
return (RDR_OK);
}
static int
pack_abort_cmd_request(abort_cmd_params_t *params, char **buf, int *buf_size)
{
rdr_abort_cmd_t abort_cmd_data;
if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
return (RDR_ERROR);
}
*buf_size = sizeof (rdr_abort_cmd_t);
*buf = (char *)malloc(*buf_size);
if (*buf == NULL) {
return (RDR_MEM_ALLOC);
}
abort_cmd_data.session_id = params->session_id;
(void) memcpy(*buf, &abort_cmd_data, sizeof (rdr_abort_cmd_t));
return (RDR_OK);
}
static int
unpack_abort_cmd_request(abort_cmd_params_t *params, const char *buf)
{
rdr_abort_cmd_t *abort_cmd_datap;
if ((params == NULL) || (buf == NULL)) {
return (RDR_ERROR);
}
abort_cmd_datap = (rdr_abort_cmd_t *)buf;
params->session_id = abort_cmd_datap->session_id;
return (RDR_OK);
}
static int
pack_confirm_request(confirm_callback_params_t *params, char **buf,
int *buf_size)
{
int i;
char *bufptr;
rdr_confirm_callback_t confirm_callback_data;
int message_strlen;
int message_pad_sz;
if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
return (RDR_ERROR);
}
if (params->message != NULL) {
message_strlen = strlen(params->message) + 1;
message_pad_sz = RDR_ALIGN_64_BIT -
(message_strlen % RDR_ALIGN_64_BIT);
} else {
message_strlen = 0;
message_pad_sz = 0;
}
*buf_size = sizeof (rdr_confirm_callback_t);
*buf_size += message_strlen;
*buf_size += message_pad_sz;
*buf = (char *)malloc(*buf_size);
if (*buf == NULL) {
return (RDR_MEM_ALLOC);
}
if (params->confp != NULL) {
confirm_callback_data.confirm_callback_id =
(unsigned long)params->confp->confirm;
confirm_callback_data.appdata_ptr =
(unsigned long)params->confp->appdata_ptr;
} else {
confirm_callback_data.confirm_callback_id = 0;
confirm_callback_data.appdata_ptr = 0;
}
confirm_callback_data.message_size = message_strlen + message_pad_sz;
bufptr = *buf;
(void) memcpy(bufptr, &confirm_callback_data,
sizeof (rdr_confirm_callback_t));
bufptr += sizeof (rdr_confirm_callback_t);
if (params->message != NULL) {
(void) memcpy(bufptr, params->message, message_strlen);
bufptr += message_strlen;
for (i = 0; i < message_pad_sz; i++) {
bufptr[i] = 0;
}
bufptr += message_pad_sz;
}
return (RDR_OK);
}
static int
unpack_confirm_request(confirm_callback_params_t *params, const char *buf)
{
char *bufptr;
rdr_confirm_callback_t confirm_callback_data;
if ((params == NULL) || (buf == NULL)) {
return (RDR_ERROR);
}
bufptr = (char *)buf;
(void) memcpy(&confirm_callback_data, bufptr,
sizeof (rdr_confirm_callback_t));
bufptr += sizeof (rdr_confirm_callback_t);
if (get_string_from_buf(&(params->message),
confirm_callback_data.message_size, bufptr)) {
return (RDR_ERROR);
}
bufptr += confirm_callback_data.message_size;
params->confp = (struct cfga_confirm *)
malloc(sizeof (struct cfga_confirm));
if (params->confp == NULL) {
return (RDR_MEM_ALLOC);
}
(void) memcpy((void*)params->confp,
&(confirm_callback_data.confirm_callback_id),
sizeof (unsigned long));
params->confp->appdata_ptr =
(void*)confirm_callback_data.appdata_ptr;
return (RDR_OK);
}
static int
pack_confirm_reply(confirm_callback_params_t *params, char **buf, int *buf_size)
{
char *bufptr;
rdr_confirm_callback_reply_t confirm_callback_data;
if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
return (RDR_ERROR);
}
*buf_size = sizeof (confirm_callback_params_t);
*buf = (char *)malloc(*buf_size);
if (*buf == NULL) {
return (RDR_MEM_ALLOC);
}
if (params->confp != NULL) {
confirm_callback_data.confirm_callback_id =
(unsigned long)params->confp->confirm;
confirm_callback_data.appdata_ptr =
(unsigned long)params->confp->appdata_ptr;
} else {
confirm_callback_data.confirm_callback_id = 0;
confirm_callback_data.appdata_ptr = 0;
}
confirm_callback_data.response = params->response;
bufptr = *buf;
(void) memcpy(bufptr, &confirm_callback_data,
sizeof (rdr_confirm_callback_reply_t));
return (RDR_OK);
}
static int
unpack_confirm_reply(confirm_callback_params_t *params, const char *buf)
{
char *bufptr;
rdr_confirm_callback_reply_t confirm_callback_data;
if ((params == NULL) || (buf == NULL)) {
return (RDR_ERROR);
}
bufptr = (char *)buf;
(void) memcpy(&confirm_callback_data, bufptr,
sizeof (rdr_confirm_callback_reply_t));
bufptr += sizeof (confirm_callback_params_t);
params->confp = (struct cfga_confirm *)
malloc(sizeof (struct cfga_confirm));
if (params->confp == NULL) {
return (RDR_MEM_ALLOC);
}
(void) memcpy((void*)params->confp,
&(confirm_callback_data.confirm_callback_id),
sizeof (unsigned long));
params->confp->appdata_ptr =
(void*)confirm_callback_data.appdata_ptr;
params->response = confirm_callback_data.response;
return (RDR_OK);
}
static int
pack_message_request(msg_callback_params_t *params, char **buf, int *buf_size)
{
int i;
char *bufptr;
rdr_msg_callback_t msg_callback_data;
int message_strlen;
int message_pad_sz;
if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
return (RDR_ERROR);
}
if (params->message != NULL) {
message_strlen = strlen(params->message) + 1;
message_pad_sz = RDR_ALIGN_64_BIT -
(message_strlen % RDR_ALIGN_64_BIT);
} else {
message_strlen = 0;
message_pad_sz = 0;
}
*buf_size = sizeof (rdr_msg_callback_t);
*buf_size += message_strlen;
*buf_size += message_pad_sz;
*buf = (char *)malloc(*buf_size);
if (*buf == NULL) {
return (RDR_MEM_ALLOC);
}
if (params->msgp != NULL) {
msg_callback_data.msg_callback_id =
(unsigned long)params->msgp->message_routine;
msg_callback_data.appdata_ptr =
(unsigned long)params->msgp->appdata_ptr;
} else {
msg_callback_data.msg_callback_id = 0;
msg_callback_data.appdata_ptr = 0;
}
msg_callback_data.message_size = message_strlen + message_pad_sz;
bufptr = *buf;
(void) memcpy(bufptr, &msg_callback_data, sizeof (rdr_msg_callback_t));
bufptr += sizeof (rdr_msg_callback_t);
if (params->message != NULL) {
(void) memcpy(bufptr, params->message, message_strlen);
bufptr += message_strlen;
for (i = 0; i < message_pad_sz; i++) {
bufptr[i] = 0;
}
bufptr += message_pad_sz;
}
return (RDR_OK);
}
static int
unpack_message_request(msg_callback_params_t *params, const char *buf)
{
char *bufptr;
rdr_msg_callback_t msg_callback_data;
if ((params == NULL) || (buf == NULL)) {
return (RDR_ERROR);
}
bufptr = (char *)buf;
(void) memcpy(&msg_callback_data, bufptr, sizeof (rdr_msg_callback_t));
bufptr += sizeof (rdr_msg_callback_t);
if (get_string_from_buf(&(params->message),
msg_callback_data.message_size, bufptr)) {
return (RDR_ERROR);
}
bufptr += msg_callback_data.message_size;
params->msgp = (struct cfga_msg *)malloc(sizeof (struct cfga_msg));
if (params->msgp == NULL) {
return (RDR_MEM_ALLOC);
}
(void) memcpy((void*)params->msgp, &(msg_callback_data.msg_callback_id),
sizeof (unsigned long));
params->msgp->appdata_ptr = (void*)msg_callback_data.appdata_ptr;
return (RDR_OK);
}
static int
pack_rsrc_info_request(rsrc_info_params_t *params, char **buf, int *buf_size)
{
char *bufptr;
rdr_rsrc_info_t rsrc_info_data;
rdr_variable_message_info_t var_msg_info;
if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
return (RDR_ERROR);
}
(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
if (pack_ap_ids(params->num_ap_ids, params->ap_ids, &var_msg_info)) {
cleanup_variable_ap_id_info(&var_msg_info);
return (RDR_ERROR);
}
*buf_size = sizeof (rdr_rsrc_info_t);
*buf_size += var_msg_info.ap_id_int_size;
*buf_size += var_msg_info.ap_id_char_size;
*buf = (char *)malloc(*buf_size);
if (*buf == NULL) {
return (RDR_MEM_ALLOC);
}
rsrc_info_data.num_ap_ids = params->num_ap_ids;
rsrc_info_data.ap_id_char_size = var_msg_info.ap_id_char_size;
rsrc_info_data.flags = params->flags;
bufptr = *buf;
(void) memcpy(bufptr, &rsrc_info_data, sizeof (rdr_rsrc_info_t));
bufptr += sizeof (rdr_rsrc_info_t);
if (var_msg_info.ap_id_sizes != NULL) {
(void) memcpy(bufptr, var_msg_info.ap_id_sizes,
var_msg_info.ap_id_int_size);
bufptr += var_msg_info.ap_id_int_size;
}
if (var_msg_info.ap_id_chars != NULL) {
(void) memcpy(bufptr, var_msg_info.ap_id_chars,
var_msg_info.ap_id_char_size);
bufptr += var_msg_info.ap_id_char_size;
}
cleanup_variable_ap_id_info(&var_msg_info);
return (RDR_OK);
}
static int
unpack_rsrc_info_request(rsrc_info_params_t *params, const char *buf)
{
char *bufptr;
rdr_variable_message_info_t var_msg_info;
rdr_rsrc_info_t rsrc_info_data;
if ((params == NULL) || (buf == NULL)) {
return (RDR_ERROR);
}
(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
bufptr = (char *)buf;
(void) memcpy(&rsrc_info_data, bufptr, sizeof (rdr_rsrc_info_t));
bufptr += sizeof (rdr_rsrc_info_t);
var_msg_info.ap_id_char_size = rsrc_info_data.ap_id_char_size;
if (get_ap_ids_from_buf(&(params->ap_ids), rsrc_info_data.num_ap_ids,
&var_msg_info, bufptr)) {
return (RDR_ERROR);
}
bufptr += var_msg_info.ap_id_int_size;
bufptr += var_msg_info.ap_id_char_size;
params->num_ap_ids = rsrc_info_data.num_ap_ids;
params->flags = rsrc_info_data.flags;
return (RDR_OK);
}
static int
pack_rsrc_info_reply(rsrc_info_params_t *params, char **buf, int *buf_size,
int encoding)
{
char *bufptr;
rdr_rsrc_info_reply_t rsrc_info_data;
int pack_status;
caddr_t rsrc_info_bufp = NULL;
size_t rsrc_info_size;
if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
return (RDR_ERROR);
}
pack_status = ri_pack(params->hdl, &rsrc_info_bufp, &rsrc_info_size,
encoding);
if (pack_status != 0) {
return (RDR_ERROR);
}
*buf_size = sizeof (rdr_rsrc_info_reply_t);
*buf_size += rsrc_info_size;
*buf = (char *)malloc(*buf_size);
if (*buf == NULL) {
free(rsrc_info_bufp);
return (RDR_MEM_ALLOC);
}
rsrc_info_data.packed_hdl_size = rsrc_info_size;
bufptr = *buf;
(void) memcpy(bufptr, &rsrc_info_data, sizeof (rdr_rsrc_info_reply_t));
bufptr += sizeof (rdr_rsrc_info_reply_t);
if (rsrc_info_bufp) {
(void) memcpy(bufptr, rsrc_info_bufp, rsrc_info_size);
free(rsrc_info_bufp);
}
return (RDR_OK);
}
static int
unpack_rsrc_info_reply(rsrc_info_params_t *params, const char *buf)
{
int unpack_status;
char *bufptr;
rdr_rsrc_info_reply_t rsrc_info_data;
if ((params == NULL) || (buf == NULL)) {
return (RDR_ERROR);
}
bufptr = (char *)buf;
(void) memcpy(&rsrc_info_data, bufptr, sizeof (rdr_rsrc_info_reply_t));
bufptr += sizeof (rdr_rsrc_info_reply_t);
unpack_status = ri_unpack(bufptr, rsrc_info_data.packed_hdl_size,
¶ms->hdl);
return ((unpack_status == 0) ? RDR_OK : RDR_ERROR);
}
static int
pack_ap_ids(int num_ap_ids, char *const *ap_ids,
rdr_variable_message_info_t *var_msg_info)
{
int i;
int ap_id_pad_sz;
char *bufptr;
if (var_msg_info == NULL) {
return (RDR_ERROR);
}
if ((ap_ids == NULL) && (num_ap_ids != 0)) {
num_ap_ids = 0;
}
var_msg_info->ap_id_int_size = sizeof (int) * num_ap_ids;
if (num_ap_ids > 0) {
var_msg_info->ap_id_sizes = (int *)malloc(sizeof (int) *
var_msg_info->ap_id_int_size);
if (var_msg_info->ap_id_sizes == NULL) {
return (RDR_MEM_ALLOC);
}
}
for (i = 0; i < num_ap_ids; i++) {
if (ap_ids[i] != NULL) {
var_msg_info->ap_id_sizes[i] = strlen(ap_ids[i]) + 1;
var_msg_info->ap_id_char_size +=
var_msg_info->ap_id_sizes[i];
}
}
if (var_msg_info->ap_id_char_size > 0) {
ap_id_pad_sz = RDR_ALIGN_64_BIT -
(var_msg_info->ap_id_char_size % RDR_ALIGN_64_BIT);
var_msg_info->ap_id_char_size += ap_id_pad_sz;
var_msg_info->ap_id_chars = (char *)
malloc(var_msg_info->ap_id_char_size);
if (var_msg_info->ap_id_chars == NULL) {
return (RDR_MEM_ALLOC);
}
bufptr = var_msg_info->ap_id_chars;
for (i = 0; i < num_ap_ids; i++) {
(void) memcpy(bufptr, ap_ids[i],
var_msg_info->ap_id_sizes[i]);
bufptr += var_msg_info->ap_id_sizes[i];
}
for (i = 0; i < ap_id_pad_sz; i++) {
bufptr[i] = 0;
}
} else {
ap_id_pad_sz = 0;
}
return (RDR_OK);
}
static int
unpack_ap_ids(int num_ap_ids, char **ap_ids, const char *buf,
rdr_variable_message_info_t *var_msg_info)
{
int i;
int ap_id_size;
int chars_copied;
char *bufptr;
if ((ap_ids == NULL) || (buf == NULL) || (var_msg_info == NULL)) {
return (RDR_ERROR);
}
bufptr = (char *)buf;
var_msg_info->ap_id_int_size = sizeof (int) * num_ap_ids;
if (num_ap_ids > 0) {
var_msg_info->ap_id_sizes = (int *)
malloc(sizeof (int) * var_msg_info->ap_id_int_size);
if (var_msg_info->ap_id_sizes == NULL) {
return (RDR_MEM_ALLOC);
}
(void) memcpy(var_msg_info->ap_id_sizes, bufptr,
var_msg_info->ap_id_int_size);
}
bufptr += var_msg_info->ap_id_int_size;
chars_copied = 0;
for (i = 0; i < num_ap_ids; i++) {
ap_id_size = var_msg_info->ap_id_sizes[i];
if (ap_id_size <= 0) {
continue;
}
if ((chars_copied + ap_id_size) >
var_msg_info->ap_id_char_size) {
return (RDR_ERROR);
}
ap_ids[i] = (char *)malloc(ap_id_size);
if (ap_ids[i] == NULL) {
return (RDR_MEM_ALLOC);
}
(void) memcpy(ap_ids[i], bufptr, ap_id_size);
bufptr += ap_id_size;
chars_copied += ap_id_size;
}
return (RDR_OK);
}
static int
find_options_sizes(char *options, rdr_variable_message_info_t *var_msg_info)
{
if (var_msg_info == NULL) {
return (RDR_ERROR);
}
if (options != NULL) {
var_msg_info->options_strlen = strlen(options) + 1;
var_msg_info->options_pad_sz = RDR_ALIGN_64_BIT -
(var_msg_info->options_strlen % RDR_ALIGN_64_BIT);
} else {
var_msg_info->options_strlen = 0;
var_msg_info->options_pad_sz = 0;
}
return (RDR_OK);
}
static int
find_listopts_sizes(char *listopts, rdr_variable_message_info_t *var_msg_info)
{
if (var_msg_info == NULL) {
return (RDR_ERROR);
}
if (listopts != NULL) {
var_msg_info->listopts_strlen = strlen(listopts) + 1;
var_msg_info->listopts_pad_sz = RDR_ALIGN_64_BIT -
(var_msg_info->listopts_strlen % RDR_ALIGN_64_BIT);
} else {
var_msg_info->listopts_strlen = 0;
var_msg_info->listopts_pad_sz = 0;
}
return (RDR_OK);
}
static int
find_function_sizes(char *function, rdr_variable_message_info_t *var_msg_info)
{
if (var_msg_info == NULL) {
return (RDR_ERROR);
}
if (function != NULL) {
var_msg_info->function_strlen = strlen(function) + 1;
var_msg_info->function_pad_sz = RDR_ALIGN_64_BIT -
(var_msg_info->function_strlen % RDR_ALIGN_64_BIT);
} else {
var_msg_info->function_strlen = 0;
var_msg_info->function_pad_sz = 0;
}
return (RDR_OK);
}
static int
find_errstring_sizes(char **errstring,
rdr_variable_message_info_t *var_msg_info)
{
if ((errstring != NULL) && (*errstring != NULL)) {
var_msg_info->errstring_strlen = strlen(*errstring) + 1;
var_msg_info->errstring_pad_sz = RDR_ALIGN_64_BIT -
(var_msg_info->errstring_strlen % RDR_ALIGN_64_BIT);
} else {
var_msg_info->errstring_strlen = 0;
var_msg_info->errstring_pad_sz = 0;
}
return (RDR_OK);
}
static int
get_ap_ids_from_buf(char ***ap_id_ptr, int num_ap_ids,
rdr_variable_message_info_t *var_msg_info, const char *buf)
{
if ((ap_id_ptr == NULL) || (buf == NULL) || (var_msg_info == NULL)) {
return (RDR_ERROR);
}
if (num_ap_ids > 0) {
*ap_id_ptr = (char **)malloc(sizeof (char *) * num_ap_ids);
if (*ap_id_ptr == NULL) {
return (RDR_MEM_ALLOC);
}
if (unpack_ap_ids(num_ap_ids, *ap_id_ptr, buf, var_msg_info)) {
cleanup_variable_ap_id_info(var_msg_info);
return (RDR_ERROR);
}
} else if (num_ap_ids < 0) {
return (RDR_ERROR);
}
cleanup_variable_ap_id_info(var_msg_info);
return (RDR_OK);
}
static int
get_string_from_buf(char **stringptr, int strsize, const char *buf)
{
if (buf == NULL) {
return (RDR_ERROR);
}
if (stringptr != NULL) {
if (strsize > 0) {
*stringptr = (char *)malloc(strsize);
if (*stringptr == NULL) {
return (RDR_MEM_ALLOC);
}
(void) memcpy(*stringptr, buf, strsize);
} else if (strsize == 0) {
*stringptr = NULL;
} else if (strsize < 0) {
*stringptr = NULL;
return (RDR_ERROR);
}
}
return (RDR_OK);
}
static int
cleanup_ap_ids(int num_ap_ids, char ** ap_ids)
{
int i;
if (ap_ids == NULL) {
return (RDR_ERROR);
}
for (i = 0; i < num_ap_ids; i++) {
if (ap_ids[i] != NULL) {
free((void *)ap_ids[i]);
ap_ids[i] = NULL;
}
}
return (RDR_OK);
}
static int
cleanup_errstring(char **errstring)
{
if (errstring) {
if (*errstring) {
free((void *)*errstring);
}
free((void *)errstring);
errstring = NULL;
}
return (RDR_OK);
}
static void
cleanup_variable_ap_id_info(rdr_variable_message_info_t *var_msg_info)
{
if (var_msg_info != NULL) {
if (var_msg_info->ap_id_sizes != NULL) {
free((void *)var_msg_info->ap_id_sizes);
var_msg_info->ap_id_sizes = NULL;
}
if (var_msg_info->ap_id_chars != NULL) {
free((void *)var_msg_info->ap_id_chars);
var_msg_info->ap_id_chars = NULL;
}
}
}
static int
load_libdscp(libdscp_t *libdscp)
{
int len;
void *lib;
static char platform[100];
static char pathname[MAXPATHLEN];
if (libdscp->status == LIBDSCP_AVAILABLE) {
return (1);
}
if (libdscp->status == LIBDSCP_UNAVAILABLE) {
return (0);
}
len = sysinfo(SI_PLATFORM, platform, sizeof (platform));
if ((len < 0) || (len > sizeof (platform))) {
return (0);
}
len = snprintf(pathname, MAXPATHLEN, LIBDSCP_PATH, platform);
if (len >= MAXPATHLEN) {
libdscp->status = LIBDSCP_UNAVAILABLE;
return (0);
}
if ((lib = dlopen(pathname, RTLD_LAZY)) == NULL) {
libdscp->status = LIBDSCP_UNAVAILABLE;
return (0);
}
libdscp->bind = (int (*)(int, int, int))dlsym(lib, LIBDSCP_BIND);
libdscp->secure = (int (*)(int, int))dlsym(lib, LIBDSCP_SECURE);
libdscp->auth = (int (*)(int, struct sockaddr *, int))dlsym(lib,
LIBDSCP_AUTH);
if ((libdscp->bind == NULL) ||
(libdscp->secure == NULL) ||
(libdscp->auth == NULL)) {
(void) dlclose(lib);
libdscp->status = LIBDSCP_UNAVAILABLE;
return (0);
}
libdscp->status = LIBDSCP_AVAILABLE;
return (1);
}