xref: /onnv-gate/usr/src/common/openssl/crypto/err/err.c (revision 2139:6243c3338933)
10Sstevel@tonic-gate /* crypto/err/err.c */
20Sstevel@tonic-gate /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
30Sstevel@tonic-gate  * All rights reserved.
40Sstevel@tonic-gate  *
50Sstevel@tonic-gate  * This package is an SSL implementation written
60Sstevel@tonic-gate  * by Eric Young (eay@cryptsoft.com).
70Sstevel@tonic-gate  * The implementation was written so as to conform with Netscapes SSL.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  * This library is free for commercial and non-commercial use as long as
100Sstevel@tonic-gate  * the following conditions are aheared to.  The following conditions
110Sstevel@tonic-gate  * apply to all code found in this distribution, be it the RC4, RSA,
120Sstevel@tonic-gate  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
130Sstevel@tonic-gate  * included with this distribution is covered by the same copyright terms
140Sstevel@tonic-gate  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
150Sstevel@tonic-gate  *
160Sstevel@tonic-gate  * Copyright remains Eric Young's, and as such any Copyright notices in
170Sstevel@tonic-gate  * the code are not to be removed.
180Sstevel@tonic-gate  * If this package is used in a product, Eric Young should be given attribution
190Sstevel@tonic-gate  * as the author of the parts of the library used.
200Sstevel@tonic-gate  * This can be in the form of a textual message at program startup or
210Sstevel@tonic-gate  * in documentation (online or textual) provided with the package.
220Sstevel@tonic-gate  *
230Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
240Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
250Sstevel@tonic-gate  * are met:
260Sstevel@tonic-gate  * 1. Redistributions of source code must retain the copyright
270Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer.
280Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
290Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in the
300Sstevel@tonic-gate  *    documentation and/or other materials provided with the distribution.
310Sstevel@tonic-gate  * 3. All advertising materials mentioning features or use of this software
320Sstevel@tonic-gate  *    must display the following acknowledgement:
330Sstevel@tonic-gate  *    "This product includes cryptographic software written by
340Sstevel@tonic-gate  *     Eric Young (eay@cryptsoft.com)"
350Sstevel@tonic-gate  *    The word 'cryptographic' can be left out if the rouines from the library
360Sstevel@tonic-gate  *    being used are not cryptographic related :-).
370Sstevel@tonic-gate  * 4. If you include any Windows specific code (or a derivative thereof) from
380Sstevel@tonic-gate  *    the apps directory (application code) you must include an acknowledgement:
390Sstevel@tonic-gate  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
400Sstevel@tonic-gate  *
410Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
420Sstevel@tonic-gate  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
430Sstevel@tonic-gate  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
440Sstevel@tonic-gate  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
450Sstevel@tonic-gate  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
460Sstevel@tonic-gate  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
470Sstevel@tonic-gate  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
480Sstevel@tonic-gate  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
490Sstevel@tonic-gate  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
500Sstevel@tonic-gate  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
510Sstevel@tonic-gate  * SUCH DAMAGE.
520Sstevel@tonic-gate  *
530Sstevel@tonic-gate  * The licence and distribution terms for any publically available version or
540Sstevel@tonic-gate  * derivative of this code cannot be changed.  i.e. this code cannot simply be
550Sstevel@tonic-gate  * copied and put under another distribution licence
560Sstevel@tonic-gate  * [including the GNU Public Licence.]
570Sstevel@tonic-gate  */
580Sstevel@tonic-gate /* ====================================================================
590Sstevel@tonic-gate  * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.
600Sstevel@tonic-gate  *
610Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
620Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
630Sstevel@tonic-gate  * are met:
640Sstevel@tonic-gate  *
650Sstevel@tonic-gate  * 1. Redistributions of source code must retain the above copyright
660Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer.
670Sstevel@tonic-gate  *
680Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
690Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in
700Sstevel@tonic-gate  *    the documentation and/or other materials provided with the
710Sstevel@tonic-gate  *    distribution.
720Sstevel@tonic-gate  *
730Sstevel@tonic-gate  * 3. All advertising materials mentioning features or use of this
740Sstevel@tonic-gate  *    software must display the following acknowledgment:
750Sstevel@tonic-gate  *    "This product includes software developed by the OpenSSL Project
760Sstevel@tonic-gate  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
770Sstevel@tonic-gate  *
780Sstevel@tonic-gate  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
790Sstevel@tonic-gate  *    endorse or promote products derived from this software without
800Sstevel@tonic-gate  *    prior written permission. For written permission, please contact
810Sstevel@tonic-gate  *    openssl-core@openssl.org.
820Sstevel@tonic-gate  *
830Sstevel@tonic-gate  * 5. Products derived from this software may not be called "OpenSSL"
840Sstevel@tonic-gate  *    nor may "OpenSSL" appear in their names without prior written
850Sstevel@tonic-gate  *    permission of the OpenSSL Project.
860Sstevel@tonic-gate  *
870Sstevel@tonic-gate  * 6. Redistributions of any form whatsoever must retain the following
880Sstevel@tonic-gate  *    acknowledgment:
890Sstevel@tonic-gate  *    "This product includes software developed by the OpenSSL Project
900Sstevel@tonic-gate  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
910Sstevel@tonic-gate  *
920Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
930Sstevel@tonic-gate  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
940Sstevel@tonic-gate  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
950Sstevel@tonic-gate  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
960Sstevel@tonic-gate  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
970Sstevel@tonic-gate  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
980Sstevel@tonic-gate  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
990Sstevel@tonic-gate  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1000Sstevel@tonic-gate  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
1010Sstevel@tonic-gate  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
1020Sstevel@tonic-gate  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
1030Sstevel@tonic-gate  * OF THE POSSIBILITY OF SUCH DAMAGE.
1040Sstevel@tonic-gate  * ====================================================================
1050Sstevel@tonic-gate  *
1060Sstevel@tonic-gate  * This product includes cryptographic software written by Eric Young
1070Sstevel@tonic-gate  * (eay@cryptsoft.com).  This product includes software written by Tim
1080Sstevel@tonic-gate  * Hudson (tjh@cryptsoft.com).
1090Sstevel@tonic-gate  *
1100Sstevel@tonic-gate  */
1110Sstevel@tonic-gate 
1120Sstevel@tonic-gate #include <stdio.h>
1130Sstevel@tonic-gate #include <stdarg.h>
1140Sstevel@tonic-gate #include <string.h>
115*2139Sjp161948 #include "cryptlib.h"
1160Sstevel@tonic-gate #include <openssl/lhash.h>
1170Sstevel@tonic-gate #include <openssl/crypto.h>
1180Sstevel@tonic-gate #include <openssl/buffer.h>
1190Sstevel@tonic-gate #include <openssl/bio.h>
1200Sstevel@tonic-gate #include <openssl/err.h>
1210Sstevel@tonic-gate 
1220Sstevel@tonic-gate static void err_load_strings(int lib, ERR_STRING_DATA *str);
1230Sstevel@tonic-gate 
1240Sstevel@tonic-gate static void ERR_STATE_free(ERR_STATE *s);
1250Sstevel@tonic-gate #ifndef OPENSSL_NO_ERR
1260Sstevel@tonic-gate static ERR_STRING_DATA ERR_str_libraries[]=
1270Sstevel@tonic-gate 	{
1280Sstevel@tonic-gate {ERR_PACK(ERR_LIB_NONE,0,0)		,"unknown library"},
1290Sstevel@tonic-gate {ERR_PACK(ERR_LIB_SYS,0,0)		,"system library"},
1300Sstevel@tonic-gate {ERR_PACK(ERR_LIB_BN,0,0)		,"bignum routines"},
1310Sstevel@tonic-gate {ERR_PACK(ERR_LIB_RSA,0,0)		,"rsa routines"},
1320Sstevel@tonic-gate {ERR_PACK(ERR_LIB_DH,0,0)		,"Diffie-Hellman routines"},
1330Sstevel@tonic-gate {ERR_PACK(ERR_LIB_EVP,0,0)		,"digital envelope routines"},
1340Sstevel@tonic-gate {ERR_PACK(ERR_LIB_BUF,0,0)		,"memory buffer routines"},
1350Sstevel@tonic-gate {ERR_PACK(ERR_LIB_OBJ,0,0)		,"object identifier routines"},
1360Sstevel@tonic-gate {ERR_PACK(ERR_LIB_PEM,0,0)		,"PEM routines"},
1370Sstevel@tonic-gate {ERR_PACK(ERR_LIB_DSA,0,0)		,"dsa routines"},
1380Sstevel@tonic-gate {ERR_PACK(ERR_LIB_X509,0,0)		,"x509 certificate routines"},
1390Sstevel@tonic-gate {ERR_PACK(ERR_LIB_ASN1,0,0)		,"asn1 encoding routines"},
1400Sstevel@tonic-gate {ERR_PACK(ERR_LIB_CONF,0,0)		,"configuration file routines"},
1410Sstevel@tonic-gate {ERR_PACK(ERR_LIB_CRYPTO,0,0)		,"common libcrypto routines"},
1420Sstevel@tonic-gate {ERR_PACK(ERR_LIB_EC,0,0)		,"elliptic curve routines"},
1430Sstevel@tonic-gate {ERR_PACK(ERR_LIB_SSL,0,0)		,"SSL routines"},
1440Sstevel@tonic-gate {ERR_PACK(ERR_LIB_BIO,0,0)		,"BIO routines"},
1450Sstevel@tonic-gate {ERR_PACK(ERR_LIB_PKCS7,0,0)		,"PKCS7 routines"},
1460Sstevel@tonic-gate {ERR_PACK(ERR_LIB_X509V3,0,0)		,"X509 V3 routines"},
1470Sstevel@tonic-gate {ERR_PACK(ERR_LIB_PKCS12,0,0)		,"PKCS12 routines"},
1480Sstevel@tonic-gate {ERR_PACK(ERR_LIB_RAND,0,0)		,"random number generator"},
1490Sstevel@tonic-gate {ERR_PACK(ERR_LIB_DSO,0,0)		,"DSO support routines"},
1500Sstevel@tonic-gate {ERR_PACK(ERR_LIB_ENGINE,0,0)		,"engine routines"},
1510Sstevel@tonic-gate {ERR_PACK(ERR_LIB_OCSP,0,0)		,"OCSP routines"},
1520Sstevel@tonic-gate {0,NULL},
1530Sstevel@tonic-gate 	};
1540Sstevel@tonic-gate 
1550Sstevel@tonic-gate static ERR_STRING_DATA ERR_str_functs[]=
1560Sstevel@tonic-gate 	{
1570Sstevel@tonic-gate 	{ERR_PACK(0,SYS_F_FOPEN,0),     	"fopen"},
1580Sstevel@tonic-gate 	{ERR_PACK(0,SYS_F_CONNECT,0),		"connect"},
1590Sstevel@tonic-gate 	{ERR_PACK(0,SYS_F_GETSERVBYNAME,0),	"getservbyname"},
1600Sstevel@tonic-gate 	{ERR_PACK(0,SYS_F_SOCKET,0),		"socket"},
1610Sstevel@tonic-gate 	{ERR_PACK(0,SYS_F_IOCTLSOCKET,0),	"ioctlsocket"},
1620Sstevel@tonic-gate 	{ERR_PACK(0,SYS_F_BIND,0),		"bind"},
1630Sstevel@tonic-gate 	{ERR_PACK(0,SYS_F_LISTEN,0),		"listen"},
1640Sstevel@tonic-gate 	{ERR_PACK(0,SYS_F_ACCEPT,0),		"accept"},
1650Sstevel@tonic-gate #ifdef OPENSSL_SYS_WINDOWS
1660Sstevel@tonic-gate 	{ERR_PACK(0,SYS_F_WSASTARTUP,0),	"WSAstartup"},
1670Sstevel@tonic-gate #endif
1680Sstevel@tonic-gate 	{ERR_PACK(0,SYS_F_OPENDIR,0),		"opendir"},
1690Sstevel@tonic-gate 	{ERR_PACK(0,SYS_F_FREAD,0),		"fread"},
1700Sstevel@tonic-gate 	{0,NULL},
1710Sstevel@tonic-gate 	};
1720Sstevel@tonic-gate 
1730Sstevel@tonic-gate static ERR_STRING_DATA ERR_str_reasons[]=
1740Sstevel@tonic-gate 	{
1750Sstevel@tonic-gate {ERR_R_SYS_LIB				,"system lib"},
1760Sstevel@tonic-gate {ERR_R_BN_LIB				,"BN lib"},
1770Sstevel@tonic-gate {ERR_R_RSA_LIB				,"RSA lib"},
1780Sstevel@tonic-gate {ERR_R_DH_LIB				,"DH lib"},
1790Sstevel@tonic-gate {ERR_R_EVP_LIB				,"EVP lib"},
1800Sstevel@tonic-gate {ERR_R_BUF_LIB				,"BUF lib"},
1810Sstevel@tonic-gate {ERR_R_OBJ_LIB				,"OBJ lib"},
1820Sstevel@tonic-gate {ERR_R_PEM_LIB				,"PEM lib"},
1830Sstevel@tonic-gate {ERR_R_DSA_LIB				,"DSA lib"},
1840Sstevel@tonic-gate {ERR_R_X509_LIB				,"X509 lib"},
1850Sstevel@tonic-gate {ERR_R_ASN1_LIB				,"ASN1 lib"},
1860Sstevel@tonic-gate {ERR_R_CONF_LIB				,"CONF lib"},
1870Sstevel@tonic-gate {ERR_R_CRYPTO_LIB			,"CRYPTO lib"},
1880Sstevel@tonic-gate {ERR_R_EC_LIB				,"EC lib"},
1890Sstevel@tonic-gate {ERR_R_SSL_LIB				,"SSL lib"},
1900Sstevel@tonic-gate {ERR_R_BIO_LIB				,"BIO lib"},
1910Sstevel@tonic-gate {ERR_R_PKCS7_LIB			,"PKCS7 lib"},
1920Sstevel@tonic-gate {ERR_R_X509V3_LIB			,"X509V3 lib"},
1930Sstevel@tonic-gate {ERR_R_PKCS12_LIB			,"PKCS12 lib"},
1940Sstevel@tonic-gate {ERR_R_RAND_LIB				,"RAND lib"},
1950Sstevel@tonic-gate {ERR_R_DSO_LIB				,"DSO lib"},
1960Sstevel@tonic-gate {ERR_R_ENGINE_LIB			,"ENGINE lib"},
1970Sstevel@tonic-gate {ERR_R_OCSP_LIB				,"OCSP lib"},
1980Sstevel@tonic-gate 
1990Sstevel@tonic-gate {ERR_R_NESTED_ASN1_ERROR		,"nested asn1 error"},
2000Sstevel@tonic-gate {ERR_R_BAD_ASN1_OBJECT_HEADER		,"bad asn1 object header"},
2010Sstevel@tonic-gate {ERR_R_BAD_GET_ASN1_OBJECT_CALL		,"bad get asn1 object call"},
2020Sstevel@tonic-gate {ERR_R_EXPECTING_AN_ASN1_SEQUENCE	,"expecting an asn1 sequence"},
2030Sstevel@tonic-gate {ERR_R_ASN1_LENGTH_MISMATCH		,"asn1 length mismatch"},
2040Sstevel@tonic-gate {ERR_R_MISSING_ASN1_EOS			,"missing asn1 eos"},
2050Sstevel@tonic-gate 
2060Sstevel@tonic-gate {ERR_R_FATAL                            ,"fatal"},
2070Sstevel@tonic-gate {ERR_R_MALLOC_FAILURE			,"malloc failure"},
2080Sstevel@tonic-gate {ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED	,"called a function you should not call"},
2090Sstevel@tonic-gate {ERR_R_PASSED_NULL_PARAMETER		,"passed a null parameter"},
2100Sstevel@tonic-gate {ERR_R_INTERNAL_ERROR			,"internal error"},
211*2139Sjp161948 {ERR_R_DISABLED				,"called a function that was disabled at compile-time"},
2120Sstevel@tonic-gate 
2130Sstevel@tonic-gate {0,NULL},
2140Sstevel@tonic-gate 	};
2150Sstevel@tonic-gate #endif
2160Sstevel@tonic-gate 
2170Sstevel@tonic-gate 
2180Sstevel@tonic-gate /* Define the predeclared (but externally opaque) "ERR_FNS" type */
2190Sstevel@tonic-gate struct st_ERR_FNS
2200Sstevel@tonic-gate 	{
2210Sstevel@tonic-gate 	/* Works on the "error_hash" string table */
2220Sstevel@tonic-gate 	LHASH *(*cb_err_get)(int create);
2230Sstevel@tonic-gate 	void (*cb_err_del)(void);
2240Sstevel@tonic-gate 	ERR_STRING_DATA *(*cb_err_get_item)(const ERR_STRING_DATA *);
2250Sstevel@tonic-gate 	ERR_STRING_DATA *(*cb_err_set_item)(ERR_STRING_DATA *);
2260Sstevel@tonic-gate 	ERR_STRING_DATA *(*cb_err_del_item)(ERR_STRING_DATA *);
2270Sstevel@tonic-gate 	/* Works on the "thread_hash" error-state table */
2280Sstevel@tonic-gate 	LHASH *(*cb_thread_get)(int create);
2290Sstevel@tonic-gate 	void (*cb_thread_release)(LHASH **hash);
2300Sstevel@tonic-gate 	ERR_STATE *(*cb_thread_get_item)(const ERR_STATE *);
2310Sstevel@tonic-gate 	ERR_STATE *(*cb_thread_set_item)(ERR_STATE *);
2320Sstevel@tonic-gate 	void (*cb_thread_del_item)(const ERR_STATE *);
2330Sstevel@tonic-gate 	/* Returns the next available error "library" numbers */
2340Sstevel@tonic-gate 	int (*cb_get_next_lib)(void);
2350Sstevel@tonic-gate 	};
2360Sstevel@tonic-gate 
2370Sstevel@tonic-gate /* Predeclarations of the "err_defaults" functions */
2380Sstevel@tonic-gate static LHASH *int_err_get(int create);
2390Sstevel@tonic-gate static void int_err_del(void);
2400Sstevel@tonic-gate static ERR_STRING_DATA *int_err_get_item(const ERR_STRING_DATA *);
2410Sstevel@tonic-gate static ERR_STRING_DATA *int_err_set_item(ERR_STRING_DATA *);
2420Sstevel@tonic-gate static ERR_STRING_DATA *int_err_del_item(ERR_STRING_DATA *);
2430Sstevel@tonic-gate static LHASH *int_thread_get(int create);
2440Sstevel@tonic-gate static void int_thread_release(LHASH **hash);
2450Sstevel@tonic-gate static ERR_STATE *int_thread_get_item(const ERR_STATE *);
2460Sstevel@tonic-gate static ERR_STATE *int_thread_set_item(ERR_STATE *);
2470Sstevel@tonic-gate static void int_thread_del_item(const ERR_STATE *);
2480Sstevel@tonic-gate static int int_err_get_next_lib(void);
2490Sstevel@tonic-gate /* The static ERR_FNS table using these defaults functions */
2500Sstevel@tonic-gate static const ERR_FNS err_defaults =
2510Sstevel@tonic-gate 	{
2520Sstevel@tonic-gate 	int_err_get,
2530Sstevel@tonic-gate 	int_err_del,
2540Sstevel@tonic-gate 	int_err_get_item,
2550Sstevel@tonic-gate 	int_err_set_item,
2560Sstevel@tonic-gate 	int_err_del_item,
2570Sstevel@tonic-gate 	int_thread_get,
2580Sstevel@tonic-gate 	int_thread_release,
2590Sstevel@tonic-gate 	int_thread_get_item,
2600Sstevel@tonic-gate 	int_thread_set_item,
2610Sstevel@tonic-gate 	int_thread_del_item,
2620Sstevel@tonic-gate 	int_err_get_next_lib
2630Sstevel@tonic-gate 	};
2640Sstevel@tonic-gate 
2650Sstevel@tonic-gate /* The replacable table of ERR_FNS functions we use at run-time */
2660Sstevel@tonic-gate static const ERR_FNS *err_fns = NULL;
2670Sstevel@tonic-gate 
2680Sstevel@tonic-gate /* Eg. rather than using "err_get()", use "ERRFN(err_get)()". */
2690Sstevel@tonic-gate #define ERRFN(a) err_fns->cb_##a
2700Sstevel@tonic-gate 
2710Sstevel@tonic-gate /* The internal state used by "err_defaults" - as such, the setting, reading,
2720Sstevel@tonic-gate  * creating, and deleting of this data should only be permitted via the
2730Sstevel@tonic-gate  * "err_defaults" functions. This way, a linked module can completely defer all
2740Sstevel@tonic-gate  * ERR state operation (together with requisite locking) to the implementations
2750Sstevel@tonic-gate  * and state in the loading application. */
2760Sstevel@tonic-gate static LHASH *int_error_hash = NULL;
2770Sstevel@tonic-gate static LHASH *int_thread_hash = NULL;
2780Sstevel@tonic-gate static int int_thread_hash_references = 0;
2790Sstevel@tonic-gate static int int_err_library_number= ERR_LIB_USER;
2800Sstevel@tonic-gate 
2810Sstevel@tonic-gate /* Internal function that checks whether "err_fns" is set and if not, sets it to
2820Sstevel@tonic-gate  * the defaults. */
err_fns_check(void)2830Sstevel@tonic-gate static void err_fns_check(void)
2840Sstevel@tonic-gate 	{
2850Sstevel@tonic-gate 	if (err_fns) return;
2860Sstevel@tonic-gate 
2870Sstevel@tonic-gate 	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
2880Sstevel@tonic-gate 	if (!err_fns)
2890Sstevel@tonic-gate 		err_fns = &err_defaults;
2900Sstevel@tonic-gate 	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
2910Sstevel@tonic-gate 	}
2920Sstevel@tonic-gate 
2930Sstevel@tonic-gate /* API functions to get or set the underlying ERR functions. */
2940Sstevel@tonic-gate 
ERR_get_implementation(void)2950Sstevel@tonic-gate const ERR_FNS *ERR_get_implementation(void)
2960Sstevel@tonic-gate 	{
2970Sstevel@tonic-gate 	err_fns_check();
2980Sstevel@tonic-gate 	return err_fns;
2990Sstevel@tonic-gate 	}
3000Sstevel@tonic-gate 
ERR_set_implementation(const ERR_FNS * fns)3010Sstevel@tonic-gate int ERR_set_implementation(const ERR_FNS *fns)
3020Sstevel@tonic-gate 	{
3030Sstevel@tonic-gate 	int ret = 0;
3040Sstevel@tonic-gate 
3050Sstevel@tonic-gate 	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
3060Sstevel@tonic-gate 	/* It's too late if 'err_fns' is non-NULL. BTW: not much point setting
3070Sstevel@tonic-gate 	 * an error is there?! */
3080Sstevel@tonic-gate 	if (!err_fns)
3090Sstevel@tonic-gate 		{
3100Sstevel@tonic-gate 		err_fns = fns;
3110Sstevel@tonic-gate 		ret = 1;
3120Sstevel@tonic-gate 		}
3130Sstevel@tonic-gate 	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
3140Sstevel@tonic-gate 	return ret;
3150Sstevel@tonic-gate 	}
3160Sstevel@tonic-gate 
3170Sstevel@tonic-gate /* These are the callbacks provided to "lh_new()" when creating the LHASH tables
3180Sstevel@tonic-gate  * internal to the "err_defaults" implementation. */
3190Sstevel@tonic-gate 
3200Sstevel@tonic-gate /* static unsigned long err_hash(ERR_STRING_DATA *a); */
3210Sstevel@tonic-gate static unsigned long err_hash(const void *a_void);
3220Sstevel@tonic-gate /* static int err_cmp(ERR_STRING_DATA *a, ERR_STRING_DATA *b); */
3230Sstevel@tonic-gate static int err_cmp(const void *a_void, const void *b_void);
3240Sstevel@tonic-gate /* static unsigned long pid_hash(ERR_STATE *pid); */
3250Sstevel@tonic-gate static unsigned long pid_hash(const void *pid_void);
3260Sstevel@tonic-gate /* static int pid_cmp(ERR_STATE *a,ERR_STATE *pid); */
3270Sstevel@tonic-gate static int pid_cmp(const void *a_void,const void *pid_void);
3280Sstevel@tonic-gate static unsigned long get_error_values(int inc,int top,const char **file,int *line,
3290Sstevel@tonic-gate 				      const char **data,int *flags);
3300Sstevel@tonic-gate 
3310Sstevel@tonic-gate /* The internal functions used in the "err_defaults" implementation */
3320Sstevel@tonic-gate 
int_err_get(int create)3330Sstevel@tonic-gate static LHASH *int_err_get(int create)
3340Sstevel@tonic-gate 	{
3350Sstevel@tonic-gate 	LHASH *ret = NULL;
3360Sstevel@tonic-gate 
3370Sstevel@tonic-gate 	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
3380Sstevel@tonic-gate 	if (!int_error_hash && create)
3390Sstevel@tonic-gate 		{
3400Sstevel@tonic-gate 		CRYPTO_push_info("int_err_get (err.c)");
3410Sstevel@tonic-gate 		int_error_hash = lh_new(err_hash, err_cmp);
3420Sstevel@tonic-gate 		CRYPTO_pop_info();
3430Sstevel@tonic-gate 		}
3440Sstevel@tonic-gate 	if (int_error_hash)
3450Sstevel@tonic-gate 		ret = int_error_hash;
3460Sstevel@tonic-gate 	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
3470Sstevel@tonic-gate 
3480Sstevel@tonic-gate 	return ret;
3490Sstevel@tonic-gate 	}
3500Sstevel@tonic-gate 
int_err_del(void)3510Sstevel@tonic-gate static void int_err_del(void)
3520Sstevel@tonic-gate 	{
3530Sstevel@tonic-gate 	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
3540Sstevel@tonic-gate 	if (int_error_hash)
3550Sstevel@tonic-gate 		{
3560Sstevel@tonic-gate 		lh_free(int_error_hash);
3570Sstevel@tonic-gate 		int_error_hash = NULL;
3580Sstevel@tonic-gate 		}
3590Sstevel@tonic-gate 	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
3600Sstevel@tonic-gate 	}
3610Sstevel@tonic-gate 
int_err_get_item(const ERR_STRING_DATA * d)3620Sstevel@tonic-gate static ERR_STRING_DATA *int_err_get_item(const ERR_STRING_DATA *d)
3630Sstevel@tonic-gate 	{
3640Sstevel@tonic-gate 	ERR_STRING_DATA *p;
3650Sstevel@tonic-gate 	LHASH *hash;
3660Sstevel@tonic-gate 
3670Sstevel@tonic-gate 	err_fns_check();
3680Sstevel@tonic-gate 	hash = ERRFN(err_get)(0);
3690Sstevel@tonic-gate 	if (!hash)
3700Sstevel@tonic-gate 		return NULL;
3710Sstevel@tonic-gate 
3720Sstevel@tonic-gate 	CRYPTO_r_lock(CRYPTO_LOCK_ERR);
3730Sstevel@tonic-gate 	p = (ERR_STRING_DATA *)lh_retrieve(hash, d);
3740Sstevel@tonic-gate 	CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
3750Sstevel@tonic-gate 
3760Sstevel@tonic-gate 	return p;
3770Sstevel@tonic-gate 	}
3780Sstevel@tonic-gate 
int_err_set_item(ERR_STRING_DATA * d)3790Sstevel@tonic-gate static ERR_STRING_DATA *int_err_set_item(ERR_STRING_DATA *d)
3800Sstevel@tonic-gate 	{
3810Sstevel@tonic-gate 	ERR_STRING_DATA *p;
3820Sstevel@tonic-gate 	LHASH *hash;
3830Sstevel@tonic-gate 
3840Sstevel@tonic-gate 	err_fns_check();
3850Sstevel@tonic-gate 	hash = ERRFN(err_get)(1);
3860Sstevel@tonic-gate 	if (!hash)
3870Sstevel@tonic-gate 		return NULL;
3880Sstevel@tonic-gate 
3890Sstevel@tonic-gate 	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
3900Sstevel@tonic-gate 	p = (ERR_STRING_DATA *)lh_insert(hash, d);
3910Sstevel@tonic-gate 	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
3920Sstevel@tonic-gate 
3930Sstevel@tonic-gate 	return p;
3940Sstevel@tonic-gate 	}
3950Sstevel@tonic-gate 
int_err_del_item(ERR_STRING_DATA * d)3960Sstevel@tonic-gate static ERR_STRING_DATA *int_err_del_item(ERR_STRING_DATA *d)
3970Sstevel@tonic-gate 	{
3980Sstevel@tonic-gate 	ERR_STRING_DATA *p;
3990Sstevel@tonic-gate 	LHASH *hash;
4000Sstevel@tonic-gate 
4010Sstevel@tonic-gate 	err_fns_check();
4020Sstevel@tonic-gate 	hash = ERRFN(err_get)(0);
4030Sstevel@tonic-gate 	if (!hash)
4040Sstevel@tonic-gate 		return NULL;
4050Sstevel@tonic-gate 
4060Sstevel@tonic-gate 	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
4070Sstevel@tonic-gate 	p = (ERR_STRING_DATA *)lh_delete(hash, d);
4080Sstevel@tonic-gate 	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
4090Sstevel@tonic-gate 
4100Sstevel@tonic-gate 	return p;
4110Sstevel@tonic-gate 	}
4120Sstevel@tonic-gate 
int_thread_get(int create)4130Sstevel@tonic-gate static LHASH *int_thread_get(int create)
4140Sstevel@tonic-gate 	{
4150Sstevel@tonic-gate 	LHASH *ret = NULL;
4160Sstevel@tonic-gate 
4170Sstevel@tonic-gate 	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
4180Sstevel@tonic-gate 	if (!int_thread_hash && create)
4190Sstevel@tonic-gate 		{
4200Sstevel@tonic-gate 		CRYPTO_push_info("int_thread_get (err.c)");
4210Sstevel@tonic-gate 		int_thread_hash = lh_new(pid_hash, pid_cmp);
4220Sstevel@tonic-gate 		CRYPTO_pop_info();
4230Sstevel@tonic-gate 		}
4240Sstevel@tonic-gate 	if (int_thread_hash)
4250Sstevel@tonic-gate 		{
4260Sstevel@tonic-gate 		int_thread_hash_references++;
4270Sstevel@tonic-gate 		ret = int_thread_hash;
4280Sstevel@tonic-gate 		}
4290Sstevel@tonic-gate 	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
4300Sstevel@tonic-gate 	return ret;
4310Sstevel@tonic-gate 	}
4320Sstevel@tonic-gate 
int_thread_release(LHASH ** hash)4330Sstevel@tonic-gate static void int_thread_release(LHASH **hash)
4340Sstevel@tonic-gate 	{
4350Sstevel@tonic-gate 	int i;
4360Sstevel@tonic-gate 
4370Sstevel@tonic-gate 	if (hash == NULL || *hash == NULL)
4380Sstevel@tonic-gate 		return;
4390Sstevel@tonic-gate 
4400Sstevel@tonic-gate 	i = CRYPTO_add(&int_thread_hash_references, -1, CRYPTO_LOCK_ERR);
4410Sstevel@tonic-gate 
4420Sstevel@tonic-gate #ifdef REF_PRINT
4430Sstevel@tonic-gate 	fprintf(stderr,"%4d:%s\n",int_thread_hash_references,"ERR");
4440Sstevel@tonic-gate #endif
4450Sstevel@tonic-gate 	if (i > 0) return;
4460Sstevel@tonic-gate #ifdef REF_CHECK
4470Sstevel@tonic-gate 	if (i < 0)
4480Sstevel@tonic-gate 		{
4490Sstevel@tonic-gate 		fprintf(stderr,"int_thread_release, bad reference count\n");
4500Sstevel@tonic-gate 		abort(); /* ok */
4510Sstevel@tonic-gate 		}
4520Sstevel@tonic-gate #endif
4530Sstevel@tonic-gate 	*hash = NULL;
4540Sstevel@tonic-gate 	}
4550Sstevel@tonic-gate 
int_thread_get_item(const ERR_STATE * d)4560Sstevel@tonic-gate static ERR_STATE *int_thread_get_item(const ERR_STATE *d)
4570Sstevel@tonic-gate 	{
4580Sstevel@tonic-gate 	ERR_STATE *p;
4590Sstevel@tonic-gate 	LHASH *hash;
4600Sstevel@tonic-gate 
4610Sstevel@tonic-gate 	err_fns_check();
4620Sstevel@tonic-gate 	hash = ERRFN(thread_get)(0);
4630Sstevel@tonic-gate 	if (!hash)
4640Sstevel@tonic-gate 		return NULL;
4650Sstevel@tonic-gate 
4660Sstevel@tonic-gate 	CRYPTO_r_lock(CRYPTO_LOCK_ERR);
4670Sstevel@tonic-gate 	p = (ERR_STATE *)lh_retrieve(hash, d);
4680Sstevel@tonic-gate 	CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
4690Sstevel@tonic-gate 
4700Sstevel@tonic-gate 	ERRFN(thread_release)(&hash);
4710Sstevel@tonic-gate 	return p;
4720Sstevel@tonic-gate 	}
4730Sstevel@tonic-gate 
int_thread_set_item(ERR_STATE * d)4740Sstevel@tonic-gate static ERR_STATE *int_thread_set_item(ERR_STATE *d)
4750Sstevel@tonic-gate 	{
4760Sstevel@tonic-gate 	ERR_STATE *p;
4770Sstevel@tonic-gate 	LHASH *hash;
4780Sstevel@tonic-gate 
4790Sstevel@tonic-gate 	err_fns_check();
4800Sstevel@tonic-gate 	hash = ERRFN(thread_get)(1);
4810Sstevel@tonic-gate 	if (!hash)
4820Sstevel@tonic-gate 		return NULL;
4830Sstevel@tonic-gate 
4840Sstevel@tonic-gate 	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
4850Sstevel@tonic-gate 	p = (ERR_STATE *)lh_insert(hash, d);
4860Sstevel@tonic-gate 	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
4870Sstevel@tonic-gate 
4880Sstevel@tonic-gate 	ERRFN(thread_release)(&hash);
4890Sstevel@tonic-gate 	return p;
4900Sstevel@tonic-gate 	}
4910Sstevel@tonic-gate 
int_thread_del_item(const ERR_STATE * d)4920Sstevel@tonic-gate static void int_thread_del_item(const ERR_STATE *d)
4930Sstevel@tonic-gate 	{
4940Sstevel@tonic-gate 	ERR_STATE *p;
4950Sstevel@tonic-gate 	LHASH *hash;
4960Sstevel@tonic-gate 
4970Sstevel@tonic-gate 	err_fns_check();
4980Sstevel@tonic-gate 	hash = ERRFN(thread_get)(0);
4990Sstevel@tonic-gate 	if (!hash)
5000Sstevel@tonic-gate 		return;
5010Sstevel@tonic-gate 
5020Sstevel@tonic-gate 	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
5030Sstevel@tonic-gate 	p = (ERR_STATE *)lh_delete(hash, d);
5040Sstevel@tonic-gate 	/* make sure we don't leak memory */
5050Sstevel@tonic-gate 	if (int_thread_hash_references == 1
5060Sstevel@tonic-gate 		&& int_thread_hash && (lh_num_items(int_thread_hash) == 0))
5070Sstevel@tonic-gate 		{
5080Sstevel@tonic-gate 		lh_free(int_thread_hash);
5090Sstevel@tonic-gate 		int_thread_hash = NULL;
5100Sstevel@tonic-gate 		}
5110Sstevel@tonic-gate 	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
5120Sstevel@tonic-gate 
5130Sstevel@tonic-gate 	ERRFN(thread_release)(&hash);
5140Sstevel@tonic-gate 	if (p)
5150Sstevel@tonic-gate 		ERR_STATE_free(p);
5160Sstevel@tonic-gate 	}
5170Sstevel@tonic-gate 
int_err_get_next_lib(void)5180Sstevel@tonic-gate static int int_err_get_next_lib(void)
5190Sstevel@tonic-gate 	{
5200Sstevel@tonic-gate 	int ret;
5210Sstevel@tonic-gate 
5220Sstevel@tonic-gate 	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
5230Sstevel@tonic-gate 	ret = int_err_library_number++;
5240Sstevel@tonic-gate 	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
5250Sstevel@tonic-gate 
5260Sstevel@tonic-gate 	return ret;
5270Sstevel@tonic-gate 	}
5280Sstevel@tonic-gate 
5290Sstevel@tonic-gate 
5300Sstevel@tonic-gate #ifndef OPENSSL_NO_ERR
5310Sstevel@tonic-gate #define NUM_SYS_STR_REASONS 127
5320Sstevel@tonic-gate #define LEN_SYS_STR_REASON 32
5330Sstevel@tonic-gate 
5340Sstevel@tonic-gate static ERR_STRING_DATA SYS_str_reasons[NUM_SYS_STR_REASONS + 1];
5350Sstevel@tonic-gate /* SYS_str_reasons is filled with copies of strerror() results at
5360Sstevel@tonic-gate  * initialization.
5370Sstevel@tonic-gate  * 'errno' values up to 127 should cover all usual errors,
5380Sstevel@tonic-gate  * others will be displayed numerically by ERR_error_string.
5390Sstevel@tonic-gate  * It is crucial that we have something for each reason code
5400Sstevel@tonic-gate  * that occurs in ERR_str_reasons, or bogus reason strings
5410Sstevel@tonic-gate  * will be returned for SYSerr(), which always gets an errno
5420Sstevel@tonic-gate  * value and never one of those 'standard' reason codes. */
5430Sstevel@tonic-gate 
build_SYS_str_reasons(void)544*2139Sjp161948 static void build_SYS_str_reasons(void)
5450Sstevel@tonic-gate 	{
5460Sstevel@tonic-gate 	/* OPENSSL_malloc cannot be used here, use static storage instead */
5470Sstevel@tonic-gate 	static char strerror_tab[NUM_SYS_STR_REASONS][LEN_SYS_STR_REASON];
5480Sstevel@tonic-gate 	int i;
5490Sstevel@tonic-gate 	static int init = 1;
5500Sstevel@tonic-gate 
5510Sstevel@tonic-gate 	if (!init) return;
5520Sstevel@tonic-gate 
5530Sstevel@tonic-gate 	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
5540Sstevel@tonic-gate 
5550Sstevel@tonic-gate 	for (i = 1; i <= NUM_SYS_STR_REASONS; i++)
5560Sstevel@tonic-gate 		{
5570Sstevel@tonic-gate 		ERR_STRING_DATA *str = &SYS_str_reasons[i - 1];
5580Sstevel@tonic-gate 
5590Sstevel@tonic-gate 		str->error = (unsigned long)i;
5600Sstevel@tonic-gate 		if (str->string == NULL)
5610Sstevel@tonic-gate 			{
5620Sstevel@tonic-gate 			char (*dest)[LEN_SYS_STR_REASON] = &(strerror_tab[i - 1]);
5630Sstevel@tonic-gate 			char *src = strerror(i);
5640Sstevel@tonic-gate 			if (src != NULL)
5650Sstevel@tonic-gate 				{
5660Sstevel@tonic-gate 				strncpy(*dest, src, sizeof *dest);
5670Sstevel@tonic-gate 				(*dest)[sizeof *dest - 1] = '\0';
5680Sstevel@tonic-gate 				str->string = *dest;
5690Sstevel@tonic-gate 				}
5700Sstevel@tonic-gate 			}
5710Sstevel@tonic-gate 		if (str->string == NULL)
5720Sstevel@tonic-gate 			str->string = "unknown";
5730Sstevel@tonic-gate 		}
5740Sstevel@tonic-gate 
5750Sstevel@tonic-gate 	/* Now we still have SYS_str_reasons[NUM_SYS_STR_REASONS] = {0, NULL},
5760Sstevel@tonic-gate 	 * as required by ERR_load_strings. */
5770Sstevel@tonic-gate 
5780Sstevel@tonic-gate 	init = 0;
5790Sstevel@tonic-gate 
5800Sstevel@tonic-gate 	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
5810Sstevel@tonic-gate 	}
5820Sstevel@tonic-gate #endif
5830Sstevel@tonic-gate 
5840Sstevel@tonic-gate #define err_clear_data(p,i) \
585*2139Sjp161948 	do { \
5860Sstevel@tonic-gate 	if (((p)->err_data[i] != NULL) && \
5870Sstevel@tonic-gate 		(p)->err_data_flags[i] & ERR_TXT_MALLOCED) \
5880Sstevel@tonic-gate 		{  \
5890Sstevel@tonic-gate 		OPENSSL_free((p)->err_data[i]); \
5900Sstevel@tonic-gate 		(p)->err_data[i]=NULL; \
5910Sstevel@tonic-gate 		} \
592*2139Sjp161948 	(p)->err_data_flags[i]=0; \
593*2139Sjp161948 	} while(0)
594*2139Sjp161948 
595*2139Sjp161948 #define err_clear(p,i) \
596*2139Sjp161948 	do { \
597*2139Sjp161948 	(p)->err_flags[i]=0; \
598*2139Sjp161948 	(p)->err_buffer[i]=0; \
599*2139Sjp161948 	err_clear_data(p,i); \
600*2139Sjp161948 	(p)->err_file[i]=NULL; \
601*2139Sjp161948 	(p)->err_line[i]= -1; \
602*2139Sjp161948 	} while(0)
6030Sstevel@tonic-gate 
ERR_STATE_free(ERR_STATE * s)6040Sstevel@tonic-gate static void ERR_STATE_free(ERR_STATE *s)
6050Sstevel@tonic-gate 	{
6060Sstevel@tonic-gate 	int i;
6070Sstevel@tonic-gate 
6080Sstevel@tonic-gate 	if (s == NULL)
6090Sstevel@tonic-gate 	    return;
6100Sstevel@tonic-gate 
6110Sstevel@tonic-gate 	for (i=0; i<ERR_NUM_ERRORS; i++)
6120Sstevel@tonic-gate 		{
6130Sstevel@tonic-gate 		err_clear_data(s,i);
6140Sstevel@tonic-gate 		}
6150Sstevel@tonic-gate 	OPENSSL_free(s);
6160Sstevel@tonic-gate 	}
6170Sstevel@tonic-gate 
ERR_load_ERR_strings(void)6180Sstevel@tonic-gate void ERR_load_ERR_strings(void)
6190Sstevel@tonic-gate 	{
6200Sstevel@tonic-gate 	err_fns_check();
6210Sstevel@tonic-gate #ifndef OPENSSL_NO_ERR
6220Sstevel@tonic-gate 	err_load_strings(0,ERR_str_libraries);
6230Sstevel@tonic-gate 	err_load_strings(0,ERR_str_reasons);
6240Sstevel@tonic-gate 	err_load_strings(ERR_LIB_SYS,ERR_str_functs);
6250Sstevel@tonic-gate 	build_SYS_str_reasons();
6260Sstevel@tonic-gate 	err_load_strings(ERR_LIB_SYS,SYS_str_reasons);
6270Sstevel@tonic-gate #endif
6280Sstevel@tonic-gate 	}
6290Sstevel@tonic-gate 
err_load_strings(int lib,ERR_STRING_DATA * str)6300Sstevel@tonic-gate static void err_load_strings(int lib, ERR_STRING_DATA *str)
6310Sstevel@tonic-gate 	{
6320Sstevel@tonic-gate 	while (str->error)
6330Sstevel@tonic-gate 		{
634*2139Sjp161948 		if (lib)
635*2139Sjp161948 			str->error|=ERR_PACK(lib,0,0);
6360Sstevel@tonic-gate 		ERRFN(err_set_item)(str);
6370Sstevel@tonic-gate 		str++;
6380Sstevel@tonic-gate 		}
6390Sstevel@tonic-gate 	}
6400Sstevel@tonic-gate 
ERR_load_strings(int lib,ERR_STRING_DATA * str)6410Sstevel@tonic-gate void ERR_load_strings(int lib, ERR_STRING_DATA *str)
6420Sstevel@tonic-gate 	{
6430Sstevel@tonic-gate 	ERR_load_ERR_strings();
6440Sstevel@tonic-gate 	err_load_strings(lib, str);
6450Sstevel@tonic-gate 	}
6460Sstevel@tonic-gate 
ERR_unload_strings(int lib,ERR_STRING_DATA * str)6470Sstevel@tonic-gate void ERR_unload_strings(int lib, ERR_STRING_DATA *str)
6480Sstevel@tonic-gate 	{
6490Sstevel@tonic-gate 	while (str->error)
6500Sstevel@tonic-gate 		{
651*2139Sjp161948 		if (lib)
652*2139Sjp161948 			str->error|=ERR_PACK(lib,0,0);
6530Sstevel@tonic-gate 		ERRFN(err_del_item)(str);
6540Sstevel@tonic-gate 		str++;
6550Sstevel@tonic-gate 		}
6560Sstevel@tonic-gate 	}
6570Sstevel@tonic-gate 
ERR_free_strings(void)6580Sstevel@tonic-gate void ERR_free_strings(void)
6590Sstevel@tonic-gate 	{
6600Sstevel@tonic-gate 	err_fns_check();
6610Sstevel@tonic-gate 	ERRFN(err_del)();
6620Sstevel@tonic-gate 	}
6630Sstevel@tonic-gate 
6640Sstevel@tonic-gate /********************************************************/
6650Sstevel@tonic-gate 
ERR_put_error(int lib,int func,int reason,const char * file,int line)6660Sstevel@tonic-gate void ERR_put_error(int lib, int func, int reason, const char *file,
6670Sstevel@tonic-gate 	     int line)
6680Sstevel@tonic-gate 	{
6690Sstevel@tonic-gate 	ERR_STATE *es;
6700Sstevel@tonic-gate 
6710Sstevel@tonic-gate #ifdef _OSD_POSIX
6720Sstevel@tonic-gate 	/* In the BS2000-OSD POSIX subsystem, the compiler generates
6730Sstevel@tonic-gate 	 * path names in the form "*POSIX(/etc/passwd)".
6740Sstevel@tonic-gate 	 * This dirty hack strips them to something sensible.
6750Sstevel@tonic-gate 	 * @@@ We shouldn't modify a const string, though.
6760Sstevel@tonic-gate 	 */
6770Sstevel@tonic-gate 	if (strncmp(file,"*POSIX(", sizeof("*POSIX(")-1) == 0) {
6780Sstevel@tonic-gate 		char *end;
6790Sstevel@tonic-gate 
6800Sstevel@tonic-gate 		/* Skip the "*POSIX(" prefix */
6810Sstevel@tonic-gate 		file += sizeof("*POSIX(")-1;
6820Sstevel@tonic-gate 		end = &file[strlen(file)-1];
6830Sstevel@tonic-gate 		if (*end == ')')
6840Sstevel@tonic-gate 			*end = '\0';
6850Sstevel@tonic-gate 		/* Optional: use the basename of the path only. */
6860Sstevel@tonic-gate 		if ((end = strrchr(file, '/')) != NULL)
6870Sstevel@tonic-gate 			file = &end[1];
6880Sstevel@tonic-gate 	}
6890Sstevel@tonic-gate #endif
6900Sstevel@tonic-gate 	es=ERR_get_state();
6910Sstevel@tonic-gate 
6920Sstevel@tonic-gate 	es->top=(es->top+1)%ERR_NUM_ERRORS;
6930Sstevel@tonic-gate 	if (es->top == es->bottom)
6940Sstevel@tonic-gate 		es->bottom=(es->bottom+1)%ERR_NUM_ERRORS;
695*2139Sjp161948 	es->err_flags[es->top]=0;
6960Sstevel@tonic-gate 	es->err_buffer[es->top]=ERR_PACK(lib,func,reason);
6970Sstevel@tonic-gate 	es->err_file[es->top]=file;
6980Sstevel@tonic-gate 	es->err_line[es->top]=line;
6990Sstevel@tonic-gate 	err_clear_data(es,es->top);
7000Sstevel@tonic-gate 	}
7010Sstevel@tonic-gate 
ERR_clear_error(void)7020Sstevel@tonic-gate void ERR_clear_error(void)
7030Sstevel@tonic-gate 	{
7040Sstevel@tonic-gate 	int i;
7050Sstevel@tonic-gate 	ERR_STATE *es;
7060Sstevel@tonic-gate 
7070Sstevel@tonic-gate 	es=ERR_get_state();
7080Sstevel@tonic-gate 
7090Sstevel@tonic-gate 	for (i=0; i<ERR_NUM_ERRORS; i++)
7100Sstevel@tonic-gate 		{
711*2139Sjp161948 		err_clear(es,i);
7120Sstevel@tonic-gate 		}
7130Sstevel@tonic-gate 	es->top=es->bottom=0;
7140Sstevel@tonic-gate 	}
7150Sstevel@tonic-gate 
7160Sstevel@tonic-gate 
ERR_get_error(void)7170Sstevel@tonic-gate unsigned long ERR_get_error(void)
7180Sstevel@tonic-gate 	{ return(get_error_values(1,0,NULL,NULL,NULL,NULL)); }
7190Sstevel@tonic-gate 
ERR_get_error_line(const char ** file,int * line)7200Sstevel@tonic-gate unsigned long ERR_get_error_line(const char **file,
7210Sstevel@tonic-gate 	     int *line)
7220Sstevel@tonic-gate 	{ return(get_error_values(1,0,file,line,NULL,NULL)); }
7230Sstevel@tonic-gate 
ERR_get_error_line_data(const char ** file,int * line,const char ** data,int * flags)7240Sstevel@tonic-gate unsigned long ERR_get_error_line_data(const char **file, int *line,
7250Sstevel@tonic-gate 	     const char **data, int *flags)
7260Sstevel@tonic-gate 	{ return(get_error_values(1,0,file,line,data,flags)); }
7270Sstevel@tonic-gate 
7280Sstevel@tonic-gate 
ERR_peek_error(void)7290Sstevel@tonic-gate unsigned long ERR_peek_error(void)
7300Sstevel@tonic-gate 	{ return(get_error_values(0,0,NULL,NULL,NULL,NULL)); }
7310Sstevel@tonic-gate 
ERR_peek_error_line(const char ** file,int * line)7320Sstevel@tonic-gate unsigned long ERR_peek_error_line(const char **file, int *line)
7330Sstevel@tonic-gate 	{ return(get_error_values(0,0,file,line,NULL,NULL)); }
7340Sstevel@tonic-gate 
ERR_peek_error_line_data(const char ** file,int * line,const char ** data,int * flags)7350Sstevel@tonic-gate unsigned long ERR_peek_error_line_data(const char **file, int *line,
7360Sstevel@tonic-gate 	     const char **data, int *flags)
7370Sstevel@tonic-gate 	{ return(get_error_values(0,0,file,line,data,flags)); }
7380Sstevel@tonic-gate 
7390Sstevel@tonic-gate 
ERR_peek_last_error(void)7400Sstevel@tonic-gate unsigned long ERR_peek_last_error(void)
7410Sstevel@tonic-gate 	{ return(get_error_values(0,1,NULL,NULL,NULL,NULL)); }
7420Sstevel@tonic-gate 
ERR_peek_last_error_line(const char ** file,int * line)7430Sstevel@tonic-gate unsigned long ERR_peek_last_error_line(const char **file, int *line)
7440Sstevel@tonic-gate 	{ return(get_error_values(0,1,file,line,NULL,NULL)); }
7450Sstevel@tonic-gate 
ERR_peek_last_error_line_data(const char ** file,int * line,const char ** data,int * flags)7460Sstevel@tonic-gate unsigned long ERR_peek_last_error_line_data(const char **file, int *line,
7470Sstevel@tonic-gate 	     const char **data, int *flags)
7480Sstevel@tonic-gate 	{ return(get_error_values(0,1,file,line,data,flags)); }
7490Sstevel@tonic-gate 
7500Sstevel@tonic-gate 
get_error_values(int inc,int top,const char ** file,int * line,const char ** data,int * flags)7510Sstevel@tonic-gate static unsigned long get_error_values(int inc, int top, const char **file, int *line,
7520Sstevel@tonic-gate 	     const char **data, int *flags)
7530Sstevel@tonic-gate 	{
7540Sstevel@tonic-gate 	int i=0;
7550Sstevel@tonic-gate 	ERR_STATE *es;
7560Sstevel@tonic-gate 	unsigned long ret;
7570Sstevel@tonic-gate 
7580Sstevel@tonic-gate 	es=ERR_get_state();
7590Sstevel@tonic-gate 
7600Sstevel@tonic-gate 	if (inc && top)
7610Sstevel@tonic-gate 		{
7620Sstevel@tonic-gate 		if (file) *file = "";
7630Sstevel@tonic-gate 		if (line) *line = 0;
7640Sstevel@tonic-gate 		if (data) *data = "";
7650Sstevel@tonic-gate 		if (flags) *flags = 0;
7660Sstevel@tonic-gate 
7670Sstevel@tonic-gate 		return ERR_R_INTERNAL_ERROR;
7680Sstevel@tonic-gate 		}
7690Sstevel@tonic-gate 
7700Sstevel@tonic-gate 	if (es->bottom == es->top) return 0;
7710Sstevel@tonic-gate 	if (top)
7720Sstevel@tonic-gate 		i=es->top;			 /* last error */
7730Sstevel@tonic-gate 	else
7740Sstevel@tonic-gate 		i=(es->bottom+1)%ERR_NUM_ERRORS; /* first error */
7750Sstevel@tonic-gate 
7760Sstevel@tonic-gate 	ret=es->err_buffer[i];
7770Sstevel@tonic-gate 	if (inc)
7780Sstevel@tonic-gate 		{
7790Sstevel@tonic-gate 		es->bottom=i;
7800Sstevel@tonic-gate 		es->err_buffer[i]=0;
7810Sstevel@tonic-gate 		}
7820Sstevel@tonic-gate 
7830Sstevel@tonic-gate 	if ((file != NULL) && (line != NULL))
7840Sstevel@tonic-gate 		{
7850Sstevel@tonic-gate 		if (es->err_file[i] == NULL)
7860Sstevel@tonic-gate 			{
7870Sstevel@tonic-gate 			*file="NA";
7880Sstevel@tonic-gate 			if (line != NULL) *line=0;
7890Sstevel@tonic-gate 			}
7900Sstevel@tonic-gate 		else
7910Sstevel@tonic-gate 			{
7920Sstevel@tonic-gate 			*file=es->err_file[i];
7930Sstevel@tonic-gate 			if (line != NULL) *line=es->err_line[i];
7940Sstevel@tonic-gate 			}
7950Sstevel@tonic-gate 		}
7960Sstevel@tonic-gate 
7970Sstevel@tonic-gate 	if (data == NULL)
7980Sstevel@tonic-gate 		{
7990Sstevel@tonic-gate 		if (inc)
8000Sstevel@tonic-gate 			{
8010Sstevel@tonic-gate 			err_clear_data(es, i);
8020Sstevel@tonic-gate 			}
8030Sstevel@tonic-gate 		}
8040Sstevel@tonic-gate 	else
8050Sstevel@tonic-gate 		{
8060Sstevel@tonic-gate 		if (es->err_data[i] == NULL)
8070Sstevel@tonic-gate 			{
8080Sstevel@tonic-gate 			*data="";
8090Sstevel@tonic-gate 			if (flags != NULL) *flags=0;
8100Sstevel@tonic-gate 			}
8110Sstevel@tonic-gate 		else
8120Sstevel@tonic-gate 			{
8130Sstevel@tonic-gate 			*data=es->err_data[i];
8140Sstevel@tonic-gate 			if (flags != NULL) *flags=es->err_data_flags[i];
8150Sstevel@tonic-gate 			}
8160Sstevel@tonic-gate 		}
8170Sstevel@tonic-gate 	return ret;
8180Sstevel@tonic-gate 	}
8190Sstevel@tonic-gate 
ERR_error_string_n(unsigned long e,char * buf,size_t len)8200Sstevel@tonic-gate void ERR_error_string_n(unsigned long e, char *buf, size_t len)
8210Sstevel@tonic-gate 	{
8220Sstevel@tonic-gate 	char lsbuf[64], fsbuf[64], rsbuf[64];
8230Sstevel@tonic-gate 	const char *ls,*fs,*rs;
8240Sstevel@tonic-gate 	unsigned long l,f,r;
8250Sstevel@tonic-gate 
8260Sstevel@tonic-gate 	l=ERR_GET_LIB(e);
8270Sstevel@tonic-gate 	f=ERR_GET_FUNC(e);
8280Sstevel@tonic-gate 	r=ERR_GET_REASON(e);
8290Sstevel@tonic-gate 
8300Sstevel@tonic-gate 	ls=ERR_lib_error_string(e);
8310Sstevel@tonic-gate 	fs=ERR_func_error_string(e);
8320Sstevel@tonic-gate 	rs=ERR_reason_error_string(e);
8330Sstevel@tonic-gate 
8340Sstevel@tonic-gate 	if (ls == NULL)
8350Sstevel@tonic-gate 		BIO_snprintf(lsbuf, sizeof(lsbuf), "lib(%lu)", l);
8360Sstevel@tonic-gate 	if (fs == NULL)
8370Sstevel@tonic-gate 		BIO_snprintf(fsbuf, sizeof(fsbuf), "func(%lu)", f);
8380Sstevel@tonic-gate 	if (rs == NULL)
8390Sstevel@tonic-gate 		BIO_snprintf(rsbuf, sizeof(rsbuf), "reason(%lu)", r);
8400Sstevel@tonic-gate 
8410Sstevel@tonic-gate 	BIO_snprintf(buf, len,"error:%08lX:%s:%s:%s", e, ls?ls:lsbuf,
8420Sstevel@tonic-gate 		fs?fs:fsbuf, rs?rs:rsbuf);
8430Sstevel@tonic-gate 	if (strlen(buf) == len-1)
8440Sstevel@tonic-gate 		{
8450Sstevel@tonic-gate 		/* output may be truncated; make sure we always have 5
8460Sstevel@tonic-gate 		 * colon-separated fields, i.e. 4 colons ... */
8470Sstevel@tonic-gate #define NUM_COLONS 4
8480Sstevel@tonic-gate 		if (len > NUM_COLONS) /* ... if possible */
8490Sstevel@tonic-gate 			{
8500Sstevel@tonic-gate 			int i;
8510Sstevel@tonic-gate 			char *s = buf;
8520Sstevel@tonic-gate 
8530Sstevel@tonic-gate 			for (i = 0; i < NUM_COLONS; i++)
8540Sstevel@tonic-gate 				{
8550Sstevel@tonic-gate 				char *colon = strchr(s, ':');
8560Sstevel@tonic-gate 				if (colon == NULL || colon > &buf[len-1] - NUM_COLONS + i)
8570Sstevel@tonic-gate 					{
8580Sstevel@tonic-gate 					/* set colon no. i at last possible position
8590Sstevel@tonic-gate 					 * (buf[len-1] is the terminating 0)*/
8600Sstevel@tonic-gate 					colon = &buf[len-1] - NUM_COLONS + i;
8610Sstevel@tonic-gate 					*colon = ':';
8620Sstevel@tonic-gate 					}
8630Sstevel@tonic-gate 				s = colon + 1;
8640Sstevel@tonic-gate 				}
8650Sstevel@tonic-gate 			}
8660Sstevel@tonic-gate 		}
8670Sstevel@tonic-gate 	}
8680Sstevel@tonic-gate 
8690Sstevel@tonic-gate /* BAD for multi-threading: uses a local buffer if ret == NULL */
8700Sstevel@tonic-gate /* ERR_error_string_n should be used instead for ret != NULL
8710Sstevel@tonic-gate  * as ERR_error_string cannot know how large the buffer is */
ERR_error_string(unsigned long e,char * ret)8720Sstevel@tonic-gate char *ERR_error_string(unsigned long e, char *ret)
8730Sstevel@tonic-gate 	{
8740Sstevel@tonic-gate 	static char buf[256];
8750Sstevel@tonic-gate 
8760Sstevel@tonic-gate 	if (ret == NULL) ret=buf;
8770Sstevel@tonic-gate 	ERR_error_string_n(e, ret, 256);
8780Sstevel@tonic-gate 
8790Sstevel@tonic-gate 	return ret;
8800Sstevel@tonic-gate 	}
8810Sstevel@tonic-gate 
ERR_get_string_table(void)8820Sstevel@tonic-gate LHASH *ERR_get_string_table(void)
8830Sstevel@tonic-gate 	{
8840Sstevel@tonic-gate 	err_fns_check();
8850Sstevel@tonic-gate 	return ERRFN(err_get)(0);
8860Sstevel@tonic-gate 	}
8870Sstevel@tonic-gate 
ERR_get_err_state_table(void)8880Sstevel@tonic-gate LHASH *ERR_get_err_state_table(void)
8890Sstevel@tonic-gate 	{
8900Sstevel@tonic-gate 	err_fns_check();
8910Sstevel@tonic-gate 	return ERRFN(thread_get)(0);
8920Sstevel@tonic-gate 	}
8930Sstevel@tonic-gate 
ERR_release_err_state_table(LHASH ** hash)8940Sstevel@tonic-gate void ERR_release_err_state_table(LHASH **hash)
8950Sstevel@tonic-gate 	{
8960Sstevel@tonic-gate 	err_fns_check();
8970Sstevel@tonic-gate 	ERRFN(thread_release)(hash);
8980Sstevel@tonic-gate 	}
8990Sstevel@tonic-gate 
ERR_lib_error_string(unsigned long e)9000Sstevel@tonic-gate const char *ERR_lib_error_string(unsigned long e)
9010Sstevel@tonic-gate 	{
9020Sstevel@tonic-gate 	ERR_STRING_DATA d,*p;
9030Sstevel@tonic-gate 	unsigned long l;
9040Sstevel@tonic-gate 
9050Sstevel@tonic-gate 	err_fns_check();
9060Sstevel@tonic-gate 	l=ERR_GET_LIB(e);
9070Sstevel@tonic-gate 	d.error=ERR_PACK(l,0,0);
9080Sstevel@tonic-gate 	p=ERRFN(err_get_item)(&d);
9090Sstevel@tonic-gate 	return((p == NULL)?NULL:p->string);
9100Sstevel@tonic-gate 	}
9110Sstevel@tonic-gate 
ERR_func_error_string(unsigned long e)9120Sstevel@tonic-gate const char *ERR_func_error_string(unsigned long e)
9130Sstevel@tonic-gate 	{
9140Sstevel@tonic-gate 	ERR_STRING_DATA d,*p;
9150Sstevel@tonic-gate 	unsigned long l,f;
9160Sstevel@tonic-gate 
9170Sstevel@tonic-gate 	err_fns_check();
9180Sstevel@tonic-gate 	l=ERR_GET_LIB(e);
9190Sstevel@tonic-gate 	f=ERR_GET_FUNC(e);
9200Sstevel@tonic-gate 	d.error=ERR_PACK(l,f,0);
9210Sstevel@tonic-gate 	p=ERRFN(err_get_item)(&d);
9220Sstevel@tonic-gate 	return((p == NULL)?NULL:p->string);
9230Sstevel@tonic-gate 	}
9240Sstevel@tonic-gate 
ERR_reason_error_string(unsigned long e)9250Sstevel@tonic-gate const char *ERR_reason_error_string(unsigned long e)
9260Sstevel@tonic-gate 	{
9270Sstevel@tonic-gate 	ERR_STRING_DATA d,*p=NULL;
9280Sstevel@tonic-gate 	unsigned long l,r;
9290Sstevel@tonic-gate 
9300Sstevel@tonic-gate 	err_fns_check();
9310Sstevel@tonic-gate 	l=ERR_GET_LIB(e);
9320Sstevel@tonic-gate 	r=ERR_GET_REASON(e);
9330Sstevel@tonic-gate 	d.error=ERR_PACK(l,0,r);
9340Sstevel@tonic-gate 	p=ERRFN(err_get_item)(&d);
9350Sstevel@tonic-gate 	if (!p)
9360Sstevel@tonic-gate 		{
9370Sstevel@tonic-gate 		d.error=ERR_PACK(0,0,r);
9380Sstevel@tonic-gate 		p=ERRFN(err_get_item)(&d);
9390Sstevel@tonic-gate 		}
9400Sstevel@tonic-gate 	return((p == NULL)?NULL:p->string);
9410Sstevel@tonic-gate 	}
9420Sstevel@tonic-gate 
9430Sstevel@tonic-gate /* static unsigned long err_hash(ERR_STRING_DATA *a) */
err_hash(const void * a_void)9440Sstevel@tonic-gate static unsigned long err_hash(const void *a_void)
9450Sstevel@tonic-gate 	{
9460Sstevel@tonic-gate 	unsigned long ret,l;
9470Sstevel@tonic-gate 
948*2139Sjp161948 	l=((const ERR_STRING_DATA *)a_void)->error;
9490Sstevel@tonic-gate 	ret=l^ERR_GET_LIB(l)^ERR_GET_FUNC(l);
9500Sstevel@tonic-gate 	return(ret^ret%19*13);
9510Sstevel@tonic-gate 	}
9520Sstevel@tonic-gate 
9530Sstevel@tonic-gate /* static int err_cmp(ERR_STRING_DATA *a, ERR_STRING_DATA *b) */
err_cmp(const void * a_void,const void * b_void)9540Sstevel@tonic-gate static int err_cmp(const void *a_void, const void *b_void)
9550Sstevel@tonic-gate 	{
956*2139Sjp161948 	return((int)(((const ERR_STRING_DATA *)a_void)->error -
957*2139Sjp161948 			((const ERR_STRING_DATA *)b_void)->error));
9580Sstevel@tonic-gate 	}
9590Sstevel@tonic-gate 
9600Sstevel@tonic-gate /* static unsigned long pid_hash(ERR_STATE *a) */
pid_hash(const void * a_void)9610Sstevel@tonic-gate static unsigned long pid_hash(const void *a_void)
9620Sstevel@tonic-gate 	{
963*2139Sjp161948 	return(((const ERR_STATE *)a_void)->pid*13);
9640Sstevel@tonic-gate 	}
9650Sstevel@tonic-gate 
9660Sstevel@tonic-gate /* static int pid_cmp(ERR_STATE *a, ERR_STATE *b) */
pid_cmp(const void * a_void,const void * b_void)9670Sstevel@tonic-gate static int pid_cmp(const void *a_void, const void *b_void)
9680Sstevel@tonic-gate 	{
969*2139Sjp161948 	return((int)((long)((const ERR_STATE *)a_void)->pid -
970*2139Sjp161948 			(long)((const ERR_STATE *)b_void)->pid));
9710Sstevel@tonic-gate 	}
9720Sstevel@tonic-gate 
ERR_remove_state(unsigned long pid)9730Sstevel@tonic-gate void ERR_remove_state(unsigned long pid)
9740Sstevel@tonic-gate 	{
9750Sstevel@tonic-gate 	ERR_STATE tmp;
9760Sstevel@tonic-gate 
9770Sstevel@tonic-gate 	err_fns_check();
9780Sstevel@tonic-gate 	if (pid == 0)
9790Sstevel@tonic-gate 		pid=(unsigned long)CRYPTO_thread_id();
9800Sstevel@tonic-gate 	tmp.pid=pid;
9810Sstevel@tonic-gate 	/* thread_del_item automatically destroys the LHASH if the number of
9820Sstevel@tonic-gate 	 * items reaches zero. */
9830Sstevel@tonic-gate 	ERRFN(thread_del_item)(&tmp);
9840Sstevel@tonic-gate 	}
9850Sstevel@tonic-gate 
ERR_get_state(void)9860Sstevel@tonic-gate ERR_STATE *ERR_get_state(void)
9870Sstevel@tonic-gate 	{
9880Sstevel@tonic-gate 	static ERR_STATE fallback;
9890Sstevel@tonic-gate 	ERR_STATE *ret,tmp,*tmpp=NULL;
9900Sstevel@tonic-gate 	int i;
9910Sstevel@tonic-gate 	unsigned long pid;
9920Sstevel@tonic-gate 
9930Sstevel@tonic-gate 	err_fns_check();
9940Sstevel@tonic-gate 	pid=(unsigned long)CRYPTO_thread_id();
9950Sstevel@tonic-gate 	tmp.pid=pid;
9960Sstevel@tonic-gate 	ret=ERRFN(thread_get_item)(&tmp);
9970Sstevel@tonic-gate 
9980Sstevel@tonic-gate 	/* ret == the error state, if NULL, make a new one */
9990Sstevel@tonic-gate 	if (ret == NULL)
10000Sstevel@tonic-gate 		{
10010Sstevel@tonic-gate 		ret=(ERR_STATE *)OPENSSL_malloc(sizeof(ERR_STATE));
10020Sstevel@tonic-gate 		if (ret == NULL) return(&fallback);
10030Sstevel@tonic-gate 		ret->pid=pid;
10040Sstevel@tonic-gate 		ret->top=0;
10050Sstevel@tonic-gate 		ret->bottom=0;
10060Sstevel@tonic-gate 		for (i=0; i<ERR_NUM_ERRORS; i++)
10070Sstevel@tonic-gate 			{
10080Sstevel@tonic-gate 			ret->err_data[i]=NULL;
10090Sstevel@tonic-gate 			ret->err_data_flags[i]=0;
10100Sstevel@tonic-gate 			}
10110Sstevel@tonic-gate 		tmpp = ERRFN(thread_set_item)(ret);
10120Sstevel@tonic-gate 		/* To check if insertion failed, do a get. */
10130Sstevel@tonic-gate 		if (ERRFN(thread_get_item)(ret) != ret)
10140Sstevel@tonic-gate 			{
10150Sstevel@tonic-gate 			ERR_STATE_free(ret); /* could not insert it */
10160Sstevel@tonic-gate 			return(&fallback);
10170Sstevel@tonic-gate 			}
10180Sstevel@tonic-gate 		/* If a race occured in this function and we came second, tmpp
10190Sstevel@tonic-gate 		 * is the first one that we just replaced. */
10200Sstevel@tonic-gate 		if (tmpp)
10210Sstevel@tonic-gate 			ERR_STATE_free(tmpp);
10220Sstevel@tonic-gate 		}
10230Sstevel@tonic-gate 	return ret;
10240Sstevel@tonic-gate 	}
10250Sstevel@tonic-gate 
ERR_get_next_error_library(void)10260Sstevel@tonic-gate int ERR_get_next_error_library(void)
10270Sstevel@tonic-gate 	{
10280Sstevel@tonic-gate 	err_fns_check();
10290Sstevel@tonic-gate 	return ERRFN(get_next_lib)();
10300Sstevel@tonic-gate 	}
10310Sstevel@tonic-gate 
ERR_set_error_data(char * data,int flags)10320Sstevel@tonic-gate void ERR_set_error_data(char *data, int flags)
10330Sstevel@tonic-gate 	{
10340Sstevel@tonic-gate 	ERR_STATE *es;
10350Sstevel@tonic-gate 	int i;
10360Sstevel@tonic-gate 
10370Sstevel@tonic-gate 	es=ERR_get_state();
10380Sstevel@tonic-gate 
10390Sstevel@tonic-gate 	i=es->top;
10400Sstevel@tonic-gate 	if (i == 0)
10410Sstevel@tonic-gate 		i=ERR_NUM_ERRORS-1;
10420Sstevel@tonic-gate 
10430Sstevel@tonic-gate 	err_clear_data(es,i);
10440Sstevel@tonic-gate 	es->err_data[i]=data;
10450Sstevel@tonic-gate 	es->err_data_flags[i]=flags;
10460Sstevel@tonic-gate 	}
10470Sstevel@tonic-gate 
ERR_add_error_data(int num,...)10480Sstevel@tonic-gate void ERR_add_error_data(int num, ...)
10490Sstevel@tonic-gate 	{
10500Sstevel@tonic-gate 	va_list args;
10510Sstevel@tonic-gate 	int i,n,s;
10520Sstevel@tonic-gate 	char *str,*p,*a;
10530Sstevel@tonic-gate 
10540Sstevel@tonic-gate 	s=80;
10550Sstevel@tonic-gate 	str=OPENSSL_malloc(s+1);
10560Sstevel@tonic-gate 	if (str == NULL) return;
10570Sstevel@tonic-gate 	str[0]='\0';
10580Sstevel@tonic-gate 
10590Sstevel@tonic-gate 	va_start(args, num);
10600Sstevel@tonic-gate 	n=0;
10610Sstevel@tonic-gate 	for (i=0; i<num; i++)
10620Sstevel@tonic-gate 		{
10630Sstevel@tonic-gate 		a=va_arg(args, char*);
10640Sstevel@tonic-gate 		/* ignore NULLs, thanks to Bob Beck <beck@obtuse.com> */
10650Sstevel@tonic-gate 		if (a != NULL)
10660Sstevel@tonic-gate 			{
10670Sstevel@tonic-gate 			n+=strlen(a);
10680Sstevel@tonic-gate 			if (n > s)
10690Sstevel@tonic-gate 				{
10700Sstevel@tonic-gate 				s=n+20;
10710Sstevel@tonic-gate 				p=OPENSSL_realloc(str,s+1);
10720Sstevel@tonic-gate 				if (p == NULL)
10730Sstevel@tonic-gate 					{
10740Sstevel@tonic-gate 					OPENSSL_free(str);
10750Sstevel@tonic-gate 					goto err;
10760Sstevel@tonic-gate 					}
10770Sstevel@tonic-gate 				else
10780Sstevel@tonic-gate 					str=p;
10790Sstevel@tonic-gate 				}
1080*2139Sjp161948 			BUF_strlcat(str,a,(size_t)s+1);
10810Sstevel@tonic-gate 			}
10820Sstevel@tonic-gate 		}
10830Sstevel@tonic-gate 	ERR_set_error_data(str,ERR_TXT_MALLOCED|ERR_TXT_STRING);
10840Sstevel@tonic-gate 
10850Sstevel@tonic-gate err:
10860Sstevel@tonic-gate 	va_end(args);
10870Sstevel@tonic-gate 	}
1088*2139Sjp161948 
ERR_set_mark(void)1089*2139Sjp161948 int ERR_set_mark(void)
1090*2139Sjp161948 	{
1091*2139Sjp161948 	ERR_STATE *es;
1092*2139Sjp161948 
1093*2139Sjp161948 	es=ERR_get_state();
1094*2139Sjp161948 
1095*2139Sjp161948 	if (es->bottom == es->top) return 0;
1096*2139Sjp161948 	es->err_flags[es->top]|=ERR_FLAG_MARK;
1097*2139Sjp161948 	return 1;
1098*2139Sjp161948 	}
1099*2139Sjp161948 
ERR_pop_to_mark(void)1100*2139Sjp161948 int ERR_pop_to_mark(void)
1101*2139Sjp161948 	{
1102*2139Sjp161948 	ERR_STATE *es;
1103*2139Sjp161948 
1104*2139Sjp161948 	es=ERR_get_state();
1105*2139Sjp161948 
1106*2139Sjp161948 	while(es->bottom != es->top
1107*2139Sjp161948 		&& (es->err_flags[es->top] & ERR_FLAG_MARK) == 0)
1108*2139Sjp161948 		{
1109*2139Sjp161948 		err_clear(es,es->top);
1110*2139Sjp161948 		es->top-=1;
1111*2139Sjp161948 		if (es->top == -1) es->top=ERR_NUM_ERRORS;
1112*2139Sjp161948 		}
1113*2139Sjp161948 
1114*2139Sjp161948 	if (es->bottom == es->top) return 0;
1115*2139Sjp161948 	es->err_flags[es->top]&=~ERR_FLAG_MARK;
1116*2139Sjp161948 	return 1;
1117*2139Sjp161948 	}
1118