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