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