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