/* * 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. */ /* * 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 #include #include #include #include #include #include #include #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"); }