1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright (c) 2000 by Sun Microsystems, Inc. 24 * All rights reserved. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * This file is a module that handles the logging features of the 31 * DCS. All error messages that are generated by the DCS are kept in 32 * a static array and accessed through one of the access functions 33 * defined in this file. 34 */ 35 36 #include <stdlib.h> 37 #include <stdio.h> 38 #include <stdarg.h> 39 #include <string.h> 40 #include <errno.h> 41 #include <assert.h> 42 #include <syslog.h> 43 #include <libintl.h> 44 45 #include "dcs.h" 46 47 48 #define SYSLOG_FMT "<%d> %s" 49 50 51 /* 52 * This is an array of strings representing all of the error and 53 * informational messages that are used by the DCS. This includes 54 * messages that are logged using syslog(3C) and those that are 55 * displayed to the user through a message callback. 56 */ 57 static const char *dcs_err_fmt[] = { 58 59 /* 60 * Network Errors: 61 */ 62 /* DCS_INIT_ERR */ "network initialization failed", 63 /* DCS_NO_PORT */ "failed to acquire reserved port", 64 /* DCS_CONNECT_ERR */ "connection attempt failed", 65 /* DCS_RECEIVE_ERR */ "unable to receive message", 66 /* DCS_OP_REPLY_ERR */ "unable to send message for %s operation", 67 /* DCS_NO_SERV */ "%s service not found, using reserved port 665", 68 /* DCS_DISCONNECT */ "client disconnected", 69 70 /* 71 * Session Errors: 72 */ 73 /* DCS_SES_HAND_ERR */ "failed to start a new session handler", 74 /* DCS_ABORT_ERR */ "abort attempt of session, %d, unsuccessful", 75 /* DCS_VER_INVAL */ "unsupported message protocol version %d.%d", 76 /* DCS_SES_ABORTED */ "session aborted", 77 78 /* 79 * DR Request Errors: 80 */ 81 /* DCS_UNKNOWN_OP */ "unknown operation requested", 82 /* DCS_OP_FAILED */ "operation failed", 83 /* DCS_SEQ_INVAL */ "invalid session establishment sequence", 84 /* DCS_NO_SES_ESTBL */ "%s operation issued before session established", 85 /* DCS_MSG_INVAL */ "received an invalid message", 86 /* DCS_CONF_CB_ERR */ "confirm callback failed, aborting operation", 87 /* DCS_MSG_CB_ERR */ "message callback failed, continuing", 88 /* DCS_BAD_RETRY */ "retry value invalid (%d)", 89 /* DCS_BAD_TIMEOUT */ "timeout value invalid (%d)", 90 /* DCS_RETRY */ "retrying operation, attempt %d", 91 92 /* 93 * General Errors: 94 */ 95 /* DCS_NO_PRIV */ "permission denied", 96 /* DCS_INT_ERR */ "internal error: %s: %s", 97 /* DCS_UNKNOWN_ERR */ "unrecognized error reported", 98 /* DCS_BAD_OPT */ "illegal option (-%c), exiting", 99 /* DCS_BAD_OPT_ARG */ "illegal argument to -%c flag (%s), %s", 100 /* DCS_CFGA_UNKNOWN */ "configuration administration unknown error", 101 /* DCS_CFGA_ERR */ "%s: %s", 102 /* DCS_RSRC_ERR */ "resource info init error (%d)", 103 /* DCS_MSG_COUNT */ NULL 104 }; 105 106 107 /* 108 * dcs_log_msg: 109 * 110 * Based on an error code, construct an error string and output it to 111 * a logfile using syslog(3C). Note that the string will not be localized. 112 */ 113 void 114 dcs_log_msg(int priority, int err_code, ...) 115 { 116 va_list vap; 117 char err_str[MAX_MSG_LEN]; 118 char syslog_str[MAX_MSG_LEN]; 119 120 121 /* check if error code is out of bounds */ 122 if ((err_code < 0) || (err_code >= DCS_MSG_COUNT)) { 123 syslog(LOG_NOTICE, dcs_err_fmt[DCS_UNKNOWN_ERR]); 124 return; 125 } 126 127 va_start(vap, err_code); 128 (void) vsnprintf(err_str, MAX_MSG_LEN, dcs_err_fmt[err_code], vap); 129 va_end(vap); 130 131 /* prepend session identifier */ 132 snprintf(syslog_str, MAX_MSG_LEN, SYSLOG_FMT, curr_ses_id(), err_str); 133 134 syslog(priority, syslog_str); 135 136 if (standalone) { 137 fprintf(stderr, "%s\n", syslog_str); 138 } 139 } 140 141 142 /* 143 * dcs_strerror: 144 * 145 * Return the format string associated with a supplied DCS specific 146 * error code. dgettext(3C) is used to retrieve the localized version 147 * of the format string. 148 */ 149 const char * 150 dcs_strerror(int err_code) 151 { 152 /* check if code is out of bounds */ 153 if ((err_code < 0) || (err_code >= DCS_MSG_COUNT)) { 154 return (dgettext(TEXT_DOMAIN, dcs_err_fmt[DCS_UNKNOWN_ERR])); 155 } 156 157 return (dgettext(TEXT_DOMAIN, dcs_err_fmt[err_code])); 158 } 159 160 161 /* 162 * dcs_cfga_str: 163 * 164 * Assemble a string that describes a particular libcfgadm error code. 165 * This string will contain both the platform dependent and platform 166 * independent message strings available from a libcfgadm function call. 167 * The resulting string will be localized indirectly through the call 168 * to config_strerror() and the localized error string returned from 169 * the libcfgadm operation. 170 */ 171 char * 172 dcs_cfga_str(char **err_strp, int err_code) 173 { 174 const char *ep; 175 char *buf; 176 char *err_str; 177 178 179 /* 180 * Extract the platform specific message passed as 181 * a parameter, or use NULL to signal that no error 182 * string was passed. 183 */ 184 if (err_strp && *err_strp) { 185 err_str = *err_strp; 186 } else { 187 err_str = NULL; 188 } 189 190 buf = (char *)malloc(MAX_MSG_LEN); 191 192 if (buf == NULL) { 193 dcs_log_msg(LOG_ERR, DCS_INT_ERR, "malloc", strerror(errno)); 194 return (NULL); 195 } 196 197 /* get the platform independent message */ 198 ep = config_strerror(err_code); 199 200 if (ep == NULL) { 201 ep = dgettext(TEXT_DOMAIN, dcs_err_fmt[DCS_CFGA_UNKNOWN]); 202 } 203 204 /* 205 * Check if a platform specific message was provided, and 206 * generate the appropriate message. 207 */ 208 if ((err_str != NULL) && (*err_str != '\0')) { 209 snprintf(buf, MAX_MSG_LEN, "%s: %s\n", ep, err_str); 210 } else { 211 snprintf(buf, MAX_MSG_LEN, "%s\n", ep); 212 } 213 214 return (buf); 215 } 216 217 218 /* 219 * dcs_dbg: 220 * 221 * Output a debugging message to a logfile using syslog(3C). The bits 222 * in the debug mask specify the category of the message. They have 223 * the following meanings: 224 * 225 * 0x1 - the string contains basic information 226 * 0x2 - the string contains message information 227 * 0x4 - the string contains session information 228 * 0x8 - the string contains state information 229 * 230 * The debug mask is compared to the global value of dcs_debug which is 231 * set through a command line option. This determines whether or not 232 * to output the message to the logfile. 233 */ 234 void 235 dcs_dbg(int dbg_mask, char *fmt, ...) 236 { 237 va_list vap; 238 char err_str[MAX_MSG_LEN]; 239 char syslog_str[MAX_MSG_LEN]; 240 241 242 if ((dcs_debug & dbg_mask) == 0) { 243 return; 244 } 245 246 va_start(vap, fmt); 247 (void) vsnprintf(err_str, MAX_MSG_LEN, fmt, vap); 248 va_end(vap); 249 250 /* prepend session identifier */ 251 snprintf(syslog_str, MAX_MSG_LEN, SYSLOG_FMT, curr_ses_id(), err_str); 252 253 syslog(LOG_DEBUG, syslog_str); 254 255 if (standalone) { 256 fprintf(stderr, "%s\n", syslog_str); 257 } 258 } 259 260 261 /* 262 * print_msg_hdr: 263 * 264 * Print selected information from the header for a given message. The 265 * information logged includes the information needed to track the flow 266 * of messages: opcode, send/receive, request/reply, and success/failure. 267 */ 268 void 269 print_msg_hdr(dcs_msg_type_t type, rdr_msg_hdr_t *hdr) 270 { 271 static char *type_str[] = { 272 "INVALID TYPE", 273 "RDR_REQUEST", 274 "RDR_REPLY" 275 }; 276 277 static char *op_str[] = { 278 "RDR_INVALID_OP", 279 "RDR_SES_REQ", 280 "RDR_SES_ESTBL", 281 "RDR_SES_END", 282 "RDR_CONF_CHANGE_STATE", 283 "RDR_CONF_PRIVATE_FUNC", 284 "RDR_CONF_TEST", 285 "RDR_CONF_LIST_EXT", 286 "RDR_CONF_HELP", 287 "RDR_CONF_AP_ID_CMP", 288 "RDR_CONF_ABORT_CMD", 289 "RDR_CONF_CONFIRM_CALLBACK", 290 "RDR_CONF_MSG_CALLBACK", 291 "RDR_RSRC_INFO" 292 }; 293 294 assert(hdr); 295 296 /* clamp an invalid opcode */ 297 if (hdr->message_opcode >= RDR_NUM_OPS) { 298 hdr->message_opcode = 0; 299 } 300 301 /* clamp an invalid type */ 302 if (hdr->data_type > RDR_REPLY) { 303 hdr->data_type = 0; 304 } 305 306 DCS_DBG(DBG_MSG, "message %s: <%s, %s%s>", 307 (type == DCS_RECEIVE) ? "received" : "sent", 308 op_str[hdr->message_opcode], 309 type_str[hdr->data_type], 310 ((hdr->data_type == RDR_REQUEST) || 311 (hdr->message_opcode == RDR_CONF_AP_ID_CMP)) ? "" : 312 (hdr->status == RDR_SUCCESS) ? ", RDR_SUCCESS" : 313 ", RDR_FAILED"); 314 } 315