1 |
|
|
/* $OpenBSD: clnt_perror.c,v 1.24 2015/09/13 15:36:56 guenther 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 <stdio.h> |
35 |
|
|
#include <stdlib.h> |
36 |
|
|
#include <string.h> |
37 |
|
|
#include <rpc/rpc.h> |
38 |
|
|
#include <rpc/types.h> |
39 |
|
|
#include <rpc/auth.h> |
40 |
|
|
#include <rpc/clnt.h> |
41 |
|
|
|
42 |
|
|
static char *auth_errmsg(enum auth_stat stat); |
43 |
|
|
#define CLNT_PERROR_BUFLEN 256 |
44 |
|
|
|
45 |
|
|
static char buf[CLNT_PERROR_BUFLEN]; |
46 |
|
|
|
47 |
|
|
/* |
48 |
|
|
* Print reply error info |
49 |
|
|
*/ |
50 |
|
|
char * |
51 |
|
|
clnt_sperror(CLIENT *rpch, char *s) |
52 |
|
|
{ |
53 |
|
|
char *err, *str = buf; |
54 |
|
|
struct rpc_err e; |
55 |
|
|
int ret, len = CLNT_PERROR_BUFLEN; |
56 |
|
|
|
57 |
|
|
CLNT_GETERR(rpch, &e); |
58 |
|
|
|
59 |
|
|
ret = snprintf(str, len, "%s: %s", s, clnt_sperrno(e.re_status)); |
60 |
|
|
if (ret == -1) |
61 |
|
|
ret = 0; |
62 |
|
|
else if (ret >= len) |
63 |
|
|
goto truncated; |
64 |
|
|
str += ret; |
65 |
|
|
len -= ret; |
66 |
|
|
|
67 |
|
|
switch (e.re_status) { |
68 |
|
|
case RPC_SUCCESS: |
69 |
|
|
case RPC_CANTENCODEARGS: |
70 |
|
|
case RPC_CANTDECODERES: |
71 |
|
|
case RPC_TIMEDOUT: |
72 |
|
|
case RPC_PROGUNAVAIL: |
73 |
|
|
case RPC_PROCUNAVAIL: |
74 |
|
|
case RPC_CANTDECODEARGS: |
75 |
|
|
case RPC_SYSTEMERROR: |
76 |
|
|
case RPC_UNKNOWNHOST: |
77 |
|
|
case RPC_UNKNOWNPROTO: |
78 |
|
|
case RPC_PMAPFAILURE: |
79 |
|
|
case RPC_PROGNOTREGISTERED: |
80 |
|
|
case RPC_FAILED: |
81 |
|
|
break; |
82 |
|
|
|
83 |
|
|
case RPC_CANTSEND: |
84 |
|
|
case RPC_CANTRECV: |
85 |
|
|
ret = snprintf(str, len, "; errno = %s", strerror(e.re_errno)); |
86 |
|
|
if (ret == -1 || ret >= len) |
87 |
|
|
goto truncated; |
88 |
|
|
break; |
89 |
|
|
|
90 |
|
|
case RPC_VERSMISMATCH: |
91 |
|
|
ret = snprintf(str, len, |
92 |
|
|
"; low version = %u, high version = %u", |
93 |
|
|
e.re_vers.low, e.re_vers.high); |
94 |
|
|
if (ret == -1 || ret >= len) |
95 |
|
|
goto truncated; |
96 |
|
|
break; |
97 |
|
|
|
98 |
|
|
case RPC_AUTHERROR: |
99 |
|
|
ret = snprintf(str, len, "; why = "); |
100 |
|
|
if (ret == -1) |
101 |
|
|
ret = 0; |
102 |
|
|
else if (ret >= len) |
103 |
|
|
goto truncated; |
104 |
|
|
str += ret; |
105 |
|
|
len -= ret; |
106 |
|
|
err = auth_errmsg(e.re_why); |
107 |
|
|
if (err != NULL) { |
108 |
|
|
ret = snprintf(str, len, "%s", err); |
109 |
|
|
if (ret == -1 || ret >= len) |
110 |
|
|
goto truncated; |
111 |
|
|
} else { |
112 |
|
|
ret = snprintf(str, len, |
113 |
|
|
"(unknown authentication error - %d)", |
114 |
|
|
(int) e.re_why); |
115 |
|
|
if (ret == -1 || ret >= len) |
116 |
|
|
goto truncated; |
117 |
|
|
} |
118 |
|
|
break; |
119 |
|
|
|
120 |
|
|
case RPC_PROGVERSMISMATCH: |
121 |
|
|
ret = snprintf(str, len, |
122 |
|
|
"; low version = %u, high version = %u", |
123 |
|
|
e.re_vers.low, e.re_vers.high); |
124 |
|
|
if (ret == -1 || ret >= len) |
125 |
|
|
goto truncated; |
126 |
|
|
break; |
127 |
|
|
|
128 |
|
|
default: /* unknown */ |
129 |
|
|
ret = snprintf(str, len, "; s1 = %u, s2 = %u", |
130 |
|
|
e.re_lb.s1, e.re_lb.s2); |
131 |
|
|
if (ret == -1 || ret >= len) |
132 |
|
|
goto truncated; |
133 |
|
|
break; |
134 |
|
|
} |
135 |
|
|
if (strlcat(buf, "\n", CLNT_PERROR_BUFLEN) >= CLNT_PERROR_BUFLEN) |
136 |
|
|
goto truncated; |
137 |
|
|
return (buf); |
138 |
|
|
|
139 |
|
|
truncated: |
140 |
|
|
snprintf(buf + CLNT_PERROR_BUFLEN - 5, 5, "...\n"); |
141 |
|
|
return (buf); |
142 |
|
|
} |
143 |
|
|
DEF_WEAK(clnt_sperror); |
144 |
|
|
|
145 |
|
|
void |
146 |
|
|
clnt_perror(CLIENT *rpch, char *s) |
147 |
|
|
{ |
148 |
|
|
(void) fprintf(stderr, "%s", clnt_sperror(rpch, s)); |
149 |
|
|
} |
150 |
|
|
DEF_WEAK(clnt_perror); |
151 |
|
|
|
152 |
|
|
static const char *const rpc_errlist[] = { |
153 |
|
|
"RPC: Success", /* 0 - RPC_SUCCESS */ |
154 |
|
|
"RPC: Can't encode arguments", /* 1 - RPC_CANTENCODEARGS */ |
155 |
|
|
"RPC: Can't decode result", /* 2 - RPC_CANTDECODERES */ |
156 |
|
|
"RPC: Unable to send", /* 3 - RPC_CANTSEND */ |
157 |
|
|
"RPC: Unable to receive", /* 4 - RPC_CANTRECV */ |
158 |
|
|
"RPC: Timed out", /* 5 - RPC_TIMEDOUT */ |
159 |
|
|
"RPC: Incompatible versions of RPC", /* 6 - RPC_VERSMISMATCH */ |
160 |
|
|
"RPC: Authentication error", /* 7 - RPC_AUTHERROR */ |
161 |
|
|
"RPC: Program unavailable", /* 8 - RPC_PROGUNAVAIL */ |
162 |
|
|
"RPC: Program/version mismatch", /* 9 - RPC_PROGVERSMISMATCH */ |
163 |
|
|
"RPC: Procedure unavailable", /* 10 - RPC_PROCUNAVAIL */ |
164 |
|
|
"RPC: Server can't decode arguments", /* 11 - RPC_CANTDECODEARGS */ |
165 |
|
|
"RPC: Remote system error", /* 12 - RPC_SYSTEMERROR */ |
166 |
|
|
"RPC: Unknown host", /* 13 - RPC_UNKNOWNHOST */ |
167 |
|
|
"RPC: Port mapper failure", /* 14 - RPC_PMAPFAILURE */ |
168 |
|
|
"RPC: Program not registered", /* 15 - RPC_PROGNOTREGISTERED */ |
169 |
|
|
"RPC: Failed (unspecified error)", /* 16 - RPC_FAILED */ |
170 |
|
|
"RPC: Unknown protocol" /* 17 - RPC_UNKNOWNPROTO */ |
171 |
|
|
}; |
172 |
|
|
|
173 |
|
|
|
174 |
|
|
/* |
175 |
|
|
* This interface for use by clntrpc |
176 |
|
|
*/ |
177 |
|
|
char * |
178 |
|
|
clnt_sperrno(enum clnt_stat stat) |
179 |
|
|
{ |
180 |
|
|
unsigned int errnum = stat; |
181 |
|
|
|
182 |
|
|
if (errnum < (sizeof(rpc_errlist)/sizeof(rpc_errlist[0]))) |
183 |
|
|
return (char *)rpc_errlist[errnum]; |
184 |
|
|
|
185 |
|
|
return ("RPC: (unknown error code)"); |
186 |
|
|
} |
187 |
|
|
DEF_WEAK(clnt_sperrno); |
188 |
|
|
|
189 |
|
|
void |
190 |
|
|
clnt_perrno(enum clnt_stat num) |
191 |
|
|
{ |
192 |
|
|
(void) fprintf(stderr, "%s\n", clnt_sperrno(num)); |
193 |
|
|
} |
194 |
|
|
|
195 |
|
|
|
196 |
|
|
char * |
197 |
|
|
clnt_spcreateerror(char *s) |
198 |
|
|
{ |
199 |
|
|
switch (rpc_createerr.cf_stat) { |
200 |
|
|
case RPC_PMAPFAILURE: |
201 |
|
|
(void) snprintf(buf, CLNT_PERROR_BUFLEN, "%s: %s - %s\n", s, |
202 |
|
|
clnt_sperrno(rpc_createerr.cf_stat), |
203 |
|
|
clnt_sperrno(rpc_createerr.cf_error.re_status)); |
204 |
|
|
break; |
205 |
|
|
|
206 |
|
|
case RPC_SYSTEMERROR: |
207 |
|
|
(void) snprintf(buf, CLNT_PERROR_BUFLEN, "%s: %s - %s\n", s, |
208 |
|
|
clnt_sperrno(rpc_createerr.cf_stat), |
209 |
|
|
strerror(rpc_createerr.cf_error.re_errno)); |
210 |
|
|
break; |
211 |
|
|
|
212 |
|
|
default: |
213 |
|
|
(void) snprintf(buf, CLNT_PERROR_BUFLEN, "%s: %s\n", s, |
214 |
|
|
clnt_sperrno(rpc_createerr.cf_stat)); |
215 |
|
|
break; |
216 |
|
|
} |
217 |
|
|
buf[CLNT_PERROR_BUFLEN-2] = '\n'; |
218 |
|
|
buf[CLNT_PERROR_BUFLEN-1] = '\0'; |
219 |
|
|
return (buf); |
220 |
|
|
} |
221 |
|
|
DEF_WEAK(clnt_spcreateerror); |
222 |
|
|
|
223 |
|
|
void |
224 |
|
|
clnt_pcreateerror(char *s) |
225 |
|
|
{ |
226 |
|
|
fprintf(stderr, "%s", clnt_spcreateerror(s)); |
227 |
|
|
} |
228 |
|
|
DEF_WEAK(clnt_pcreateerror); |
229 |
|
|
|
230 |
|
|
static const char *const auth_errlist[] = { |
231 |
|
|
"Authentication OK", /* 0 - AUTH_OK */ |
232 |
|
|
"Invalid client credential", /* 1 - AUTH_BADCRED */ |
233 |
|
|
"Server rejected credential", /* 2 - AUTH_REJECTEDCRED */ |
234 |
|
|
"Invalid client verifier", /* 3 - AUTH_BADVERF */ |
235 |
|
|
"Server rejected verifier", /* 4 - AUTH_REJECTEDVERF */ |
236 |
|
|
"Client credential too weak", /* 5 - AUTH_TOOWEAK */ |
237 |
|
|
"Invalid server verifier", /* 6 - AUTH_INVALIDRESP */ |
238 |
|
|
"Failed (unspecified error)" /* 7 - AUTH_FAILED */ |
239 |
|
|
}; |
240 |
|
|
|
241 |
|
|
static char * |
242 |
|
|
auth_errmsg(enum auth_stat stat) |
243 |
|
|
{ |
244 |
|
|
unsigned int errnum = stat; |
245 |
|
|
|
246 |
|
|
if (errnum < (sizeof(auth_errlist)/sizeof(auth_errlist[0]))) |
247 |
|
|
return (char *)auth_errlist[errnum]; |
248 |
|
|
|
249 |
|
|
return (NULL); |
250 |
|
|
} |