dcs_msg.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 2000 by Sun Microsystems, Inc.
* All rights reserved.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* This file is a module that handles the logging features of the
* DCS. All error messages that are generated by the DCS are kept in
* a static array and accessed through one of the access functions
* defined in this file.
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <syslog.h>
#include <libintl.h>
#include "dcs.h"
#define SYSLOG_FMT "<%d> %s"
/*
* This is an array of strings representing all of the error and
* informational messages that are used by the DCS. This includes
* messages that are logged using syslog(3C) and those that are
* displayed to the user through a message callback.
*/
static const char *dcs_err_fmt[] = {
/*
* Network Errors:
*/
/* DCS_INIT_ERR */ "network initialization failed",
/* DCS_NO_PORT */ "failed to acquire reserved port",
/* DCS_CONNECT_ERR */ "connection attempt failed",
/* DCS_RECEIVE_ERR */ "unable to receive message",
/* DCS_OP_REPLY_ERR */ "unable to send message for %s operation",
/* DCS_NO_SERV */ "%s service not found, using reserved port 665",
/* DCS_DISCONNECT */ "client disconnected",
/*
* Session Errors:
*/
/* DCS_SES_HAND_ERR */ "failed to start a new session handler",
/* DCS_ABORT_ERR */ "abort attempt of session, %d, unsuccessful",
/* DCS_VER_INVAL */ "unsupported message protocol version %d.%d",
/* DCS_SES_ABORTED */ "session aborted",
/*
* DR Request Errors:
*/
/* DCS_UNKNOWN_OP */ "unknown operation requested",
/* DCS_OP_FAILED */ "operation failed",
/* DCS_SEQ_INVAL */ "invalid session establishment sequence",
/* DCS_NO_SES_ESTBL */ "%s operation issued before session established",
/* DCS_MSG_INVAL */ "received an invalid message",
/* DCS_CONF_CB_ERR */ "confirm callback failed, aborting operation",
/* DCS_MSG_CB_ERR */ "message callback failed, continuing",
/* DCS_BAD_RETRY */ "retry value invalid (%d)",
/* DCS_BAD_TIMEOUT */ "timeout value invalid (%d)",
/* DCS_RETRY */ "retrying operation, attempt %d",
/*
* General Errors:
*/
/* DCS_NO_PRIV */ "permission denied",
/* DCS_INT_ERR */ "internal error: %s: %s",
/* DCS_UNKNOWN_ERR */ "unrecognized error reported",
/* DCS_BAD_OPT */ "illegal option (-%c), exiting",
/* DCS_BAD_OPT_ARG */ "illegal argument to -%c flag (%s), %s",
/* DCS_CFGA_UNKNOWN */ "configuration administration unknown error",
/* DCS_CFGA_ERR */ "%s: %s",
/* DCS_RSRC_ERR */ "resource info init error (%d)",
/* DCS_MSG_COUNT */ NULL
};
/*
* dcs_log_msg:
*
* Based on an error code, construct an error string and output it to
* a logfile using syslog(3C). Note that the string will not be localized.
*/
void
dcs_log_msg(int priority, int err_code, ...)
{
va_list vap;
char err_str[MAX_MSG_LEN];
char syslog_str[MAX_MSG_LEN];
/* check if error code is out of bounds */
if ((err_code < 0) || (err_code >= DCS_MSG_COUNT)) {
syslog(LOG_NOTICE, dcs_err_fmt[DCS_UNKNOWN_ERR]);
return;
}
va_start(vap, err_code);
(void) vsnprintf(err_str, MAX_MSG_LEN, dcs_err_fmt[err_code], vap);
va_end(vap);
/* prepend session identifier */
snprintf(syslog_str, MAX_MSG_LEN, SYSLOG_FMT, curr_ses_id(), err_str);
syslog(priority, syslog_str);
if (standalone) {
fprintf(stderr, "%s\n", syslog_str);
}
}
/*
* dcs_strerror:
*
* Return the format string associated with a supplied DCS specific
* error code. dgettext(3C) is used to retrieve the localized version
* of the format string.
*/
const char *
dcs_strerror(int err_code)
{
/* check if code is out of bounds */
if ((err_code < 0) || (err_code >= DCS_MSG_COUNT)) {
return (dgettext(TEXT_DOMAIN, dcs_err_fmt[DCS_UNKNOWN_ERR]));
}
return (dgettext(TEXT_DOMAIN, dcs_err_fmt[err_code]));
}
/*
* dcs_cfga_str:
*
* Assemble a string that describes a particular libcfgadm error code.
* This string will contain both the platform dependent and platform
* independent message strings available from a libcfgadm function call.
* The resulting string will be localized indirectly through the call
* to config_strerror() and the localized error string returned from
* the libcfgadm operation.
*/
char *
dcs_cfga_str(char **err_strp, int err_code)
{
const char *ep;
char *buf;
char *err_str;
/*
* Extract the platform specific message passed as
* a parameter, or use NULL to signal that no error
* string was passed.
*/
if (err_strp && *err_strp) {
err_str = *err_strp;
} else {
err_str = NULL;
}
buf = (char *)malloc(MAX_MSG_LEN);
if (buf == NULL) {
dcs_log_msg(LOG_ERR, DCS_INT_ERR, "malloc", strerror(errno));
return (NULL);
}
/* get the platform independent message */
ep = config_strerror(err_code);
if (ep == NULL) {
ep = dgettext(TEXT_DOMAIN, dcs_err_fmt[DCS_CFGA_UNKNOWN]);
}
/*
* Check if a platform specific message was provided, and
* generate the appropriate message.
*/
if ((err_str != NULL) && (*err_str != '\0')) {
snprintf(buf, MAX_MSG_LEN, "%s: %s\n", ep, err_str);
} else {
snprintf(buf, MAX_MSG_LEN, "%s\n", ep);
}
return (buf);
}
/*
* dcs_dbg:
*
* Output a debugging message to a logfile using syslog(3C). The bits
* in the debug mask specify the category of the message. They have
* the following meanings:
*
* 0x1 - the string contains basic information
* 0x2 - the string contains message information
* 0x4 - the string contains session information
* 0x8 - the string contains state information
*
* The debug mask is compared to the global value of dcs_debug which is
* set through a command line option. This determines whether or not
* to output the message to the logfile.
*/
void
dcs_dbg(int dbg_mask, char *fmt, ...)
{
va_list vap;
char err_str[MAX_MSG_LEN];
char syslog_str[MAX_MSG_LEN];
if ((dcs_debug & dbg_mask) == 0) {
return;
}
va_start(vap, fmt);
(void) vsnprintf(err_str, MAX_MSG_LEN, fmt, vap);
va_end(vap);
/* prepend session identifier */
snprintf(syslog_str, MAX_MSG_LEN, SYSLOG_FMT, curr_ses_id(), err_str);
syslog(LOG_DEBUG, syslog_str);
if (standalone) {
fprintf(stderr, "%s\n", syslog_str);
}
}
/*
* print_msg_hdr:
*
* Print selected information from the header for a given message. The
* information logged includes the information needed to track the flow
* of messages: opcode, send/receive, request/reply, and success/failure.
*/
void
print_msg_hdr(dcs_msg_type_t type, rdr_msg_hdr_t *hdr)
{
static char *type_str[] = {
"INVALID TYPE",
"RDR_REQUEST",
"RDR_REPLY"
};
static char *op_str[] = {
"RDR_INVALID_OP",
"RDR_SES_REQ",
"RDR_SES_ESTBL",
"RDR_SES_END",
"RDR_CONF_CHANGE_STATE",
"RDR_CONF_PRIVATE_FUNC",
"RDR_CONF_TEST",
"RDR_CONF_LIST_EXT",
"RDR_CONF_HELP",
"RDR_CONF_AP_ID_CMP",
"RDR_CONF_ABORT_CMD",
"RDR_CONF_CONFIRM_CALLBACK",
"RDR_CONF_MSG_CALLBACK",
"RDR_RSRC_INFO"
};
assert(hdr);
/* clamp an invalid opcode */
if (hdr->message_opcode >= RDR_NUM_OPS) {
hdr->message_opcode = 0;
}
/* clamp an invalid type */
if (hdr->data_type > RDR_REPLY) {
hdr->data_type = 0;
}
DCS_DBG(DBG_MSG, "message %s: <%s, %s%s>",
(type == DCS_RECEIVE) ? "received" : "sent",
op_str[hdr->message_opcode],
type_str[hdr->data_type],
((hdr->data_type == RDR_REQUEST) ||
(hdr->message_opcode == RDR_CONF_AP_ID_CMP)) ? "" :
(hdr->status == RDR_SUCCESS) ? ", RDR_SUCCESS" :
", RDR_FAILED");
}