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 * 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 * 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 * 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 220 clnt_perror(const CLIENT *cl, const char *s) 221 { 222 (void) fprintf(stderr, "%s\n", clnt_sperror(cl, s)); 223 } 224 225 void 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 * 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 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 * 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