Home | History | Annotate | Line # | Download | only in rpc
      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 *
     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 *
     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
    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 *
    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
    239 clnt_perrno(enum clnt_stat num)
    240 {
    241 	(void) fprintf(stderr, "%s\n", clnt_sperrno(num));
    242 }
    243 
    244 
    245 char *
    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
    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 *
    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