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
dcs_log_msg(int priority,int err_code,...)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 *
dcs_strerror(int err_code)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 *
dcs_cfga_str(char ** err_strp,int err_code)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
dcs_dbg(int dbg_mask,char * fmt,...)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
print_msg_hdr(dcs_msg_type_t type,rdr_msg_hdr_t * hdr)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