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 (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
29 /*
30 * Portions of this source code were derived from Berkeley
31 * 4.3 BSD under license from the Regents of the University of
32 * California.
33 */
34
35 #pragma ident "%Z%%M% %I% %E% SMI"
36
37 /*
38 * clnt_perror.c
39 *
40 */
41
42 #include "mt.h"
43 #include "rpc_mt.h"
44 #include <stdio.h>
45 #include <libintl.h>
46 #include <string.h>
47 #include <rpc/types.h>
48 #include <rpc/auth.h>
49 #include <sys/tiuser.h>
50 #include <rpc/clnt.h>
51 #include <stdlib.h>
52 #include <syslog.h>
53 #include <string.h>
54
55 extern char *netdir_sperror();
56
57 const char __nsl_dom[] = "SUNW_OST_NETRPC";
58
59 #define ERRBUFSZ 512
60
61 static char *
__buf(void)62 __buf(void)
63 {
64 char *buf;
65 static char buf_main[ERRBUFSZ];
66 static pthread_key_t perror_key = PTHREAD_ONCE_KEY_NP;
67
68 buf = thr_main()? buf_main :
69 thr_get_storage(&perror_key, ERRBUFSZ, free);
70 if (buf == NULL)
71 syslog(LOG_WARNING,
72 "clnt_sperror: malloc failed when trying to create buffer\n");
73 return (buf);
74 }
75
76 static char *
auth_errmsg(enum auth_stat stat)77 auth_errmsg(enum auth_stat stat)
78 {
79 switch (stat) {
80 case AUTH_OK:
81 return (dgettext(__nsl_dom, "Authentication OK"));
82 case AUTH_BADCRED:
83 return (dgettext(__nsl_dom, "Invalid client credential"));
84 case AUTH_REJECTEDCRED:
85 return (dgettext(__nsl_dom, "Server rejected credential"));
86 case AUTH_BADVERF:
87 return (dgettext(__nsl_dom, "Invalid client verifier"));
88 case AUTH_REJECTEDVERF:
89 return (dgettext(__nsl_dom, "Server rejected verifier"));
90 case AUTH_TOOWEAK:
91 return (dgettext(__nsl_dom, "Client credential too weak"));
92 case AUTH_INVALIDRESP:
93 return (dgettext(__nsl_dom, "Invalid server verifier"));
94 case AUTH_FAILED:
95 return (dgettext(__nsl_dom, "Failed (unspecified error)"));
96
97 /* kerberos specific */
98 case AUTH_DECODE:
99 return (dgettext(__nsl_dom, "Could not decode authenticator"));
100 case AUTH_TIMEEXPIRE:
101 return (dgettext(__nsl_dom, "Time of credential expired"));
102 case AUTH_TKT_FILE:
103 return (dgettext(__nsl_dom,
104 "Something wrong with kerberos ticket file"));
105 case AUTH_NET_ADDR:
106 return (dgettext(__nsl_dom,
107 "Incorrect network address in kerberos ticket"));
108 case AUTH_KERB_GENERIC:
109 return (dgettext(__nsl_dom, "Kerberos generic error"));
110 }
111 return (dgettext(__nsl_dom, "Unknown authentication error"));
112 }
113
114 /*
115 * Return string reply error info. For use after clnt_call()
116 */
117
118 #define REMAINDER (ERRBUFSZ - (str - strstart))
119
120 char *
clnt_sperror(const CLIENT * cl,const char * s)121 clnt_sperror(const CLIENT *cl, const char *s)
122 {
123 struct rpc_err e;
124 char *err;
125 char *str = __buf();
126 char *strstart = str;
127
128 if (str == NULL)
129 return (NULL);
130 CLNT_GETERR((CLIENT *) cl, &e);
131
132 (void) snprintf(str, ERRBUFSZ, "%s: ", s);
133 str += strlcat(str, clnt_sperrno(e.re_status), ERRBUFSZ);
134
135 switch (e.re_status) {
136 case RPC_SUCCESS:
137 case RPC_CANTENCODEARGS:
138 case RPC_CANTDECODERES:
139 case RPC_TIMEDOUT:
140 case RPC_PROGUNAVAIL:
141 case RPC_PROCUNAVAIL:
142 case RPC_CANTDECODEARGS:
143 case RPC_SYSTEMERROR:
144 case RPC_UNKNOWNHOST:
145 case RPC_UNKNOWNPROTO:
146 case RPC_UNKNOWNADDR:
147 case RPC_NOBROADCAST:
148 case RPC_RPCBFAILURE:
149 case RPC_PROGNOTREGISTERED:
150 case RPC_FAILED:
151 break;
152
153 case RPC_N2AXLATEFAILURE:
154 (void) snprintf(str, REMAINDER, "; %s", netdir_sperror());
155 str += strlen(str);
156 break;
157
158 case RPC_TLIERROR:
159 (void) snprintf(str, REMAINDER, "; %s", t_errlist[e.re_terrno]);
160 str += strlen(str);
161 if (e.re_errno) {
162 (void) snprintf(str, REMAINDER,
163 "; %s", strerror(e.re_errno));
164 str += strlen(str);
165 }
166 break;
167
168 case RPC_CANTSTORE:
169 case RPC_CANTSEND:
170 case RPC_CANTRECV:
171 if (e.re_errno) {
172 (void) snprintf(str, REMAINDER, "; errno = %s",
173 strerror(e.re_errno));
174 str += strlen(str);
175 }
176 if (e.re_terrno) {
177 (void) snprintf(str, REMAINDER,
178 "; %s", t_errlist[e.re_terrno]);
179 str += strlen(str);
180 }
181 break;
182
183 case RPC_VERSMISMATCH:
184 (void) snprintf(str, REMAINDER,
185 "; low version = %lu, high version = %lu",
186 e.re_vers.low, e.re_vers.high);
187 str += strlen(str);
188 break;
189
190 case RPC_AUTHERROR:
191 err = auth_errmsg(e.re_why);
192 (void) snprintf(str, REMAINDER, "; why = ");
193 str += strlen(str);
194 if (err != NULL) {
195 (void) snprintf(str, REMAINDER, "%s", err);
196 } else {
197 (void) snprintf(str, REMAINDER,
198 "(unknown authentication error - %d)",
199 (int)e.re_why);
200 }
201 str += strlen(str);
202 break;
203
204 case RPC_PROGVERSMISMATCH:
205 (void) snprintf(str, REMAINDER,
206 "; low version = %lu, high version = %lu",
207 e.re_vers.low, e.re_vers.high);
208 str += strlen(str);
209 break;
210
211 default: /* unknown */
212 (void) snprintf(str, REMAINDER, "; s1 = %lu, s2 = %lu",
213 e.re_lb.s1, e.re_lb.s2);
214 str += strlen(str);
215 break;
216 }
217 return (strstart);
218 }
219 #undef REMAINDER
220
221 void
clnt_perror(const CLIENT * cl,const char * s)222 clnt_perror(const CLIENT *cl, const char *s)
223 {
224 (void) fprintf(stderr, "%s\n", clnt_sperror(cl, s));
225 }
226
227 void
clnt_perrno(const enum clnt_stat num)228 clnt_perrno(const enum clnt_stat num)
229 {
230 (void) fprintf(stderr, "%s\n", clnt_sperrno(num));
231 }
232
233 /*
234 * Why a client handle could not be created
235 */
236 char *
clnt_spcreateerror(const char * s)237 clnt_spcreateerror(const char *s)
238 {
239 char *errstr;
240 char *str = __buf();
241
242 if (str == NULL)
243 return (NULL);
244 (void) snprintf(str, ERRBUFSZ, "%s: ", s);
245 (void) strlcat(str, clnt_sperrno(rpc_createerr.cf_stat), ERRBUFSZ);
246
247 switch (rpc_createerr.cf_stat) {
248 case RPC_N2AXLATEFAILURE:
249 (void) strlcat(str, " - ", ERRBUFSZ);
250 (void) strlcat(str, netdir_sperror(), ERRBUFSZ);
251 break;
252
253 case RPC_RPCBFAILURE:
254 (void) strlcat(str, " - ", ERRBUFSZ);
255 (void) strlcat(str,
256 clnt_sperrno(rpc_createerr.cf_error.re_status),
257 ERRBUFSZ);
258 break;
259
260 case RPC_SYSTEMERROR:
261 (void) strlcat(str, " - ", ERRBUFSZ);
262 errstr = strerror(rpc_createerr.cf_error.re_errno);
263 if (errstr != NULL)
264 (void) strlcat(str, errstr, ERRBUFSZ);
265 else
266 (void) snprintf(&str[strlen(str)],
267 ERRBUFSZ - strlen(str), "Error %d",
268 rpc_createerr.cf_error.re_errno);
269 break;
270
271 case RPC_TLIERROR:
272 (void) strlcat(str, " - ", ERRBUFSZ);
273 if ((rpc_createerr.cf_error.re_terrno > 0) &&
274 (rpc_createerr.cf_error.re_terrno < t_nerr)) {
275 (void) strlcat(str,
276 t_errlist[rpc_createerr.cf_error.re_terrno],
277 ERRBUFSZ);
278 if (rpc_createerr.cf_error.re_terrno == TSYSERR) {
279 char *err;
280 err = strerror(rpc_createerr.cf_error.re_errno);
281 if (err) {
282 (void) strlcat(str, " (", ERRBUFSZ);
283 (void) strlcat(str, err, ERRBUFSZ);
284 (void) strlcat(str, ")", ERRBUFSZ);
285 }
286 }
287 } else {
288 (void) snprintf(&str[strlen(str)],
289 ERRBUFSZ - strlen(str),
290 dgettext(__nsl_dom, "TLI Error %d"),
291 rpc_createerr.cf_error.re_terrno);
292 }
293 errstr = strerror(rpc_createerr.cf_error.re_errno);
294 if (errstr != NULL)
295 (void) strlcat(str, errstr, ERRBUFSZ);
296 else
297 (void) snprintf(&str[strlen(str)],
298 ERRBUFSZ - strlen(str), "Error %d",
299 rpc_createerr.cf_error.re_errno);
300 break;
301
302 case RPC_AUTHERROR:
303 (void) strlcat(str, " - ", ERRBUFSZ);
304 (void) strlcat(str,
305 auth_errmsg(rpc_createerr.cf_error.re_why), ERRBUFSZ);
306 break;
307 }
308 return (str);
309 }
310
311 void
clnt_pcreateerror(const char * s)312 clnt_pcreateerror(const char *s)
313 {
314 (void) fprintf(stderr, "%s\n", clnt_spcreateerror(s));
315 }
316
317 /*
318 * This interface for use by rpc_call() and rpc_broadcast()
319 */
320 const char *
clnt_sperrno(const enum clnt_stat stat)321 clnt_sperrno(const enum clnt_stat stat)
322 {
323 switch (stat) {
324 case RPC_SUCCESS:
325 return (dgettext(__nsl_dom, "RPC: Success"));
326 case RPC_CANTENCODEARGS:
327 return (dgettext(__nsl_dom, "RPC: Can't encode arguments"));
328 case RPC_CANTDECODERES:
329 return (dgettext(__nsl_dom, "RPC: Can't decode result"));
330 case RPC_CANTSTORE:
331 return (dgettext(__nsl_dom, "RPC: Can't store request"));
332 case RPC_CANTSEND:
333 return (dgettext(__nsl_dom, "RPC: Unable to send"));
334 case RPC_CANTRECV:
335 return (dgettext(__nsl_dom, "RPC: Unable to receive"));
336 case RPC_TIMEDOUT:
337 return (dgettext(__nsl_dom, "RPC: Timed out"));
338 case RPC_VERSMISMATCH:
339 return (dgettext(__nsl_dom,
340 "RPC: Incompatible versions of RPC"));
341 case RPC_AUTHERROR:
342 return (dgettext(__nsl_dom, "RPC: Authentication error"));
343 case RPC_PROGUNAVAIL:
344 return (dgettext(__nsl_dom, "RPC: Program unavailable"));
345 case RPC_PROGVERSMISMATCH:
346 return (dgettext(__nsl_dom, "RPC: Program/version mismatch"));
347 case RPC_PROCUNAVAIL:
348 return (dgettext(__nsl_dom, "RPC: Procedure unavailable"));
349 case RPC_CANTDECODEARGS:
350 return (dgettext(__nsl_dom,
351 "RPC: Server can't decode arguments"));
352
353 case RPC_SYSTEMERROR:
354 return (dgettext(__nsl_dom, "RPC: Remote system error"));
355 case RPC_UNKNOWNHOST:
356 return (dgettext(__nsl_dom, "RPC: Unknown host"));
357 case RPC_UNKNOWNPROTO:
358 return (dgettext(__nsl_dom, "RPC: Unknown protocol"));
359 case RPC_RPCBFAILURE:
360 return (dgettext(__nsl_dom, "RPC: Rpcbind failure"));
361 case RPC_N2AXLATEFAILURE:
362 return (dgettext(__nsl_dom,
363 "RPC: Name to address translation failed"));
364 case RPC_NOBROADCAST:
365 return (dgettext(__nsl_dom, "RPC: Broadcast not supported"));
366 case RPC_PROGNOTREGISTERED:
367 return (dgettext(__nsl_dom, "RPC: Program not registered"));
368 case RPC_UNKNOWNADDR:
369 return (dgettext(__nsl_dom,
370 "RPC: Remote server address unknown"));
371 case RPC_TLIERROR:
372 return (dgettext(__nsl_dom, "RPC: Miscellaneous tli error"));
373 case RPC_FAILED:
374 return (dgettext(__nsl_dom, "RPC: Failed (unspecified error)"));
375 case RPC_INPROGRESS:
376 return (dgettext(__nsl_dom, "RPC: RAC call in progress"));
377 case RPC_STALERACHANDLE:
378 return (dgettext(__nsl_dom, "RPC: Stale RAC handle"));
379 case RPC_CANTCONNECT:
380 return (dgettext(__nsl_dom, "RPC: Couldn't make connection"));
381 case RPC_XPRTFAILED:
382 return (dgettext(__nsl_dom,
383 "RPC: Received disconnect from remote"));
384 case RPC_CANTCREATESTREAM:
385 return (dgettext(__nsl_dom, "RPC: Can't push RPC module"));
386 }
387 return (dgettext(__nsl_dom, "RPC: (unknown error code)"));
388 }
389