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