1 /*	$NetBSD: clnt_perror.c,v 1.30 2013/03/11 20:19:29 tron Exp $	*/
2 
3 /*
4  * Copyright (c) 2010, Oracle America, Inc.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are
8  * met:
9  *
10  *     * Redistributions of source code must retain the above copyright
11  *       notice, this list of conditions and the following disclaimer.
12  *     * Redistributions in binary form must reproduce the above
13  *       copyright notice, this list of conditions and the following
14  *       disclaimer in the documentation and/or other materials
15  *       provided with the distribution.
16  *     * Neither the name of the "Oracle America, Inc." nor the names of its
17  *       contributors may be used to endorse or promote products derived
18  *       from this software without specific prior written permission.
19  *
20  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24  *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25  *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27  *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29  *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30  *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include <sys/cdefs.h>
35 #if defined(LIBC_SCCS) && !defined(lint)
36 #if 0
37 static char *sccsid = "@(#)clnt_perror.c 1.15 87/10/07 Copyr 1984 Sun Micro";
38 static char *sccsid = "@(#)clnt_perror.c	2.1 88/07/29 4.0 RPCSRC";
39 #else
40 __RCSID("$NetBSD: clnt_perror.c,v 1.30 2013/03/11 20:19:29 tron Exp $");
41 #endif
42 #endif
43 
44 /*
45  * clnt_perror.c
46  *
47  * Copyright (C) 1984, Sun Microsystems, Inc.
48  *
49  */
50 #include "namespace.h"
51 
52 #include <assert.h>
53 #include <stdio.h>
54 #include <stdlib.h>
55 #include <string.h>
56 
57 #include <rpc/rpc.h>
58 #include <rpc/types.h>
59 #include <rpc/auth.h>
60 #include <rpc/clnt.h>
61 
62 #ifdef __weak_alias
63 __weak_alias(clnt_pcreateerror,_clnt_pcreateerror)
64 __weak_alias(clnt_perrno,_clnt_perrno)
65 __weak_alias(clnt_perror,_clnt_perror)
66 __weak_alias(clnt_spcreateerror,_clnt_spcreateerror)
67 __weak_alias(clnt_sperrno,_clnt_sperrno)
68 __weak_alias(clnt_sperror,_clnt_sperror)
69 #endif
70 
71 static char *buf;
72 static size_t buflen;
73 
74 static char *_buf(void);
75 static char *auth_errmsg(enum auth_stat);
76 
77 static char *
_buf(void)78 _buf(void)
79 {
80 
81 	buflen = 256;
82 	if (buf == 0)
83 		buf = malloc(buflen);
84 	return (buf);
85 }
86 
87 /*
88  * Print reply error info
89  */
90 char *
clnt_sperror(CLIENT * rpch,const char * s)91 clnt_sperror(CLIENT *rpch, const char *s)
92 {
93 	struct rpc_err e;
94 	char *err;
95 	char *str;
96 	char *strstart;
97 	size_t len, i;
98 
99 	_DIAGASSERT(rpch != NULL);
100 	_DIAGASSERT(s != NULL);
101 
102 	str = _buf(); /* side effect: sets "buflen" */
103 	if (str == 0)
104 		return (0);
105 	len = buflen;
106 	strstart = str;
107 	CLNT_GETERR(rpch, &e);
108 
109 	i = snprintf(str, len, "%s: ", s);
110 	str += i;
111 	len -= i;
112 
113 	(void)strncpy(str, clnt_sperrno(e.re_status), len - 1);
114 	i = strlen(str);
115 	str += i;
116 	len -= i;
117 
118 	switch (e.re_status) {
119 	case RPC_SUCCESS:
120 	case RPC_CANTENCODEARGS:
121 	case RPC_CANTDECODERES:
122 	case RPC_TIMEDOUT:
123 	case RPC_PROGUNAVAIL:
124 	case RPC_PROCUNAVAIL:
125 	case RPC_CANTDECODEARGS:
126 	case RPC_SYSTEMERROR:
127 	case RPC_UNKNOWNHOST:
128 	case RPC_UNKNOWNPROTO:
129 	case RPC_PMAPFAILURE:
130 	case RPC_PROGNOTREGISTERED:
131 	case RPC_FAILED:
132 		break;
133 
134 	case RPC_CANTSEND:
135 	case RPC_CANTRECV:
136 		i = snprintf(str, len, "; errno = %s", strerror(e.re_errno));
137 		str += i;
138 		len -= i;
139 		break;
140 
141 	case RPC_VERSMISMATCH:
142 		i = snprintf(str, len, "; low version = %u, high version = %u",
143 			e.re_vers.low, e.re_vers.high);
144 		str += i;
145 		len -= i;
146 		break;
147 
148 	case RPC_AUTHERROR:
149 		err = auth_errmsg(e.re_why);
150 		i = snprintf(str, len, "; why = ");
151 		str += i;
152 		len -= i;
153 		if (err != NULL) {
154 			i = snprintf(str, len, "%s",err);
155 		} else {
156 			i = snprintf(str, len,
157 				"(unknown authentication error - %d)",
158 				(int) e.re_why);
159 		}
160 		str += i;
161 		len -= i;
162 		break;
163 
164 	case RPC_PROGVERSMISMATCH:
165 		i = snprintf(str, len, "; low version = %u, high version = %u",
166 			e.re_vers.low, e.re_vers.high);
167 		str += i;
168 		len -= i;
169 		break;
170 
171 	default:	/* unknown */
172 		i = snprintf(str, len, "; s1 = %u, s2 = %u",
173 			e.re_lb.s1, e.re_lb.s2);
174 		str += i;
175 		len -= i;
176 		break;
177 	}
178 	return(strstart) ;
179 }
180 
181 void
clnt_perror(CLIENT * rpch,const char * s)182 clnt_perror(CLIENT *rpch, const char *s)
183 {
184 
185 	_DIAGASSERT(rpch != NULL);
186 	_DIAGASSERT(s != NULL);
187 
188 	(void) fprintf(stderr, "%s\n", clnt_sperror(rpch,s));
189 }
190 
191 static const char *const rpc_errlist[] = {
192 	[RPC_SUCCESS] =			"RPC: Success",
193 	[RPC_CANTENCODEARGS] =		"RPC: Can't encode arguments",
194 	[RPC_CANTDECODERES] =		"RPC: Can't decode result",
195 	[RPC_CANTSEND] =		"RPC: Unable to send",
196 	[RPC_CANTRECV] =		"RPC: Unable to receive",
197 	[RPC_TIMEDOUT] =		"RPC: Timed out",
198 	[RPC_VERSMISMATCH] =		"RPC: Incompatible versions of RPC",
199 	[RPC_AUTHERROR] = 		"RPC: Authentication error",
200 	[RPC_PROGUNAVAIL] =		"RPC: Program unavailable",
201 	[RPC_PROGVERSMISMATCH] =	"RPC: Program/version mismatch",
202 	[RPC_PROCUNAVAIL] =		"RPC: Procedure unavailable",
203 	[RPC_CANTDECODEARGS] =		"RPC: Server can't decode arguments",
204 	[RPC_SYSTEMERROR] =		"RPC: Remote system error",
205 	[RPC_UNKNOWNHOST] =		"RPC: Unknown host",
206 	[RPC_PMAPFAILURE] =		"RPC: Port mapper failure",
207 	[RPC_PROGNOTREGISTERED] =	"RPC: Program not registered",
208 	[RPC_FAILED] =			"RPC: Failed (unspecified error)",
209 	[RPC_UNKNOWNPROTO] =		"RPC: Unknown protocol",
210 	[RPC_UNKNOWNADDR] =		"RPC: Remote address unknown",
211 	[RPC_TLIERROR] =		"RPC: Misc error in the TLI library",
212 	[RPC_NOBROADCAST] =		"RPC: Broadcasting not supported",
213 	[RPC_N2AXLATEFAILURE] =		"RPC: Name -> addr translation failed",
214 	[RPC_INPROGRESS] =		"RPC: In progress",
215 	[RPC_STALERACHANDLE] =		"RPC: Stale handle",
216 };
217 
218 
219 /*
220  * This interface for use by clntrpc
221  */
222 char *
clnt_sperrno(enum clnt_stat stat)223 clnt_sperrno(enum clnt_stat stat)
224 {
225 	unsigned int errnum = stat;
226 	const char *msg;
227 
228 	msg = NULL;
229 	if (errnum < (sizeof(rpc_errlist)/sizeof(rpc_errlist[0]))) {
230 		msg = rpc_errlist[errnum];
231 	}
232 	if (msg == NULL) {
233 		msg = "RPC: (unknown error code)";
234 	}
235 	return __UNCONST(msg);
236 }
237 
238 void
clnt_perrno(enum clnt_stat num)239 clnt_perrno(enum clnt_stat num)
240 {
241 	(void) fprintf(stderr, "%s\n", clnt_sperrno(num));
242 }
243 
244 
245 char *
clnt_spcreateerror(const char * s)246 clnt_spcreateerror(const char *s)
247 {
248 	char *str;
249 	size_t len, i;
250 
251 	_DIAGASSERT(s != NULL);
252 
253 	str = _buf(); /* side effect: sets "buflen" */
254 	if (str == 0)
255 		return(0);
256 	len = buflen;
257 	i = snprintf(str, len, "%s: ", s);
258 	len -= i;
259 	(void)strncat(str, clnt_sperrno(rpc_createerr.cf_stat), len - 1);
260 	switch (rpc_createerr.cf_stat) {
261 	case RPC_PMAPFAILURE:
262 		(void) strncat(str, " - ", len - 1);
263 		(void) strncat(str,
264 		    clnt_sperrno(rpc_createerr.cf_error.re_status), len - 4);
265 		break;
266 
267 	case RPC_SYSTEMERROR:
268 		(void)strncat(str, " - ", len - 1);
269 		(void)strncat(str, strerror(rpc_createerr.cf_error.re_errno),
270 		    len - 4);
271 		break;
272 
273 	case RPC_CANTSEND:
274 	case RPC_CANTDECODERES:
275 	case RPC_CANTENCODEARGS:
276 	case RPC_SUCCESS:
277 	case RPC_UNKNOWNPROTO:
278 	case RPC_PROGNOTREGISTERED:
279 	case RPC_FAILED:
280 	case RPC_UNKNOWNHOST:
281 	case RPC_CANTDECODEARGS:
282 	case RPC_PROCUNAVAIL:
283 	case RPC_PROGVERSMISMATCH:
284 	case RPC_PROGUNAVAIL:
285 	case RPC_AUTHERROR:
286 	case RPC_VERSMISMATCH:
287 	case RPC_TIMEDOUT:
288 	case RPC_CANTRECV:
289 	default:
290 		break;
291 	}
292 	return (str);
293 }
294 
295 void
clnt_pcreateerror(const char * s)296 clnt_pcreateerror(const char *s)
297 {
298 
299 	_DIAGASSERT(s != NULL);
300 
301 	(void) fprintf(stderr, "%s\n", clnt_spcreateerror(s));
302 }
303 
304 static const char *const auth_errlist[] = {
305 	"Authentication OK",			/* 0 - AUTH_OK */
306 	"Invalid client credential",		/* 1 - AUTH_BADCRED */
307 	"Server rejected credential",		/* 2 - AUTH_REJECTEDCRED */
308 	"Invalid client verifier", 		/* 3 - AUTH_BADVERF */
309 	"Server rejected verifier", 		/* 4 - AUTH_REJECTEDVERF */
310 	"Client credential too weak",		/* 5 - AUTH_TOOWEAK */
311 	"Invalid server verifier",		/* 6 - AUTH_INVALIDRESP */
312 	"Failed (unspecified error)"		/* 7 - AUTH_FAILED */
313 };
314 
315 static char *
auth_errmsg(enum auth_stat stat)316 auth_errmsg(enum auth_stat stat)
317 {
318 	unsigned int errnum = stat;
319 
320 	if (errnum < __arraycount(auth_errlist))
321 		return __UNCONST(auth_errlist[errnum]);
322 
323 	return(NULL);
324 }
325