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