Home | History | Annotate | Download | only in err
      1 /* crypto/err/err_def.c */
      2 /* Copyright (C) 1995-1998 Eric Young (eay (at) cryptsoft.com)
      3  * All rights reserved.
      4  *
      5  * This package is an SSL implementation written
      6  * by Eric Young (eay (at) cryptsoft.com).
      7  * The implementation was written so as to conform with Netscapes SSL.
      8  *
      9  * This library is free for commercial and non-commercial use as long as
     10  * the following conditions are aheared to.  The following conditions
     11  * apply to all code found in this distribution, be it the RC4, RSA,
     12  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
     13  * included with this distribution is covered by the same copyright terms
     14  * except that the holder is Tim Hudson (tjh (at) cryptsoft.com).
     15  *
     16  * Copyright remains Eric Young's, and as such any Copyright notices in
     17  * the code are not to be removed.
     18  * If this package is used in a product, Eric Young should be given attribution
     19  * as the author of the parts of the library used.
     20  * This can be in the form of a textual message at program startup or
     21  * in documentation (online or textual) provided with the package.
     22  *
     23  * Redistribution and use in source and binary forms, with or without
     24  * modification, are permitted provided that the following conditions
     25  * are met:
     26  * 1. Redistributions of source code must retain the copyright
     27  *    notice, this list of conditions and the following disclaimer.
     28  * 2. Redistributions in binary form must reproduce the above copyright
     29  *    notice, this list of conditions and the following disclaimer in the
     30  *    documentation and/or other materials provided with the distribution.
     31  * 3. All advertising materials mentioning features or use of this software
     32  *    must display the following acknowledgement:
     33  *    "This product includes cryptographic software written by
     34  *     Eric Young (eay (at) cryptsoft.com)"
     35  *    The word 'cryptographic' can be left out if the rouines from the library
     36  *    being used are not cryptographic related :-).
     37  * 4. If you include any Windows specific code (or a derivative thereof) from
     38  *    the apps directory (application code) you must include an acknowledgement:
     39  *    "This product includes software written by Tim Hudson (tjh (at) cryptsoft.com)"
     40  *
     41  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
     42  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     43  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     44  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     45  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     46  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     47  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     49  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     50  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     51  * SUCH DAMAGE.
     52  *
     53  * The licence and distribution terms for any publically available version or
     54  * derivative of this code cannot be changed.  i.e. this code cannot simply be
     55  * copied and put under another distribution licence
     56  * [including the GNU Public Licence.]
     57  */
     58 /* ====================================================================
     59  * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.
     60  *
     61  * Redistribution and use in source and binary forms, with or without
     62  * modification, are permitted provided that the following conditions
     63  * are met:
     64  *
     65  * 1. Redistributions of source code must retain the above copyright
     66  *    notice, this list of conditions and the following disclaimer.
     67  *
     68  * 2. Redistributions in binary form must reproduce the above copyright
     69  *    notice, this list of conditions and the following disclaimer in
     70  *    the documentation and/or other materials provided with the
     71  *    distribution.
     72  *
     73  * 3. All advertising materials mentioning features or use of this
     74  *    software must display the following acknowledgment:
     75  *    "This product includes software developed by the OpenSSL Project
     76  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
     77  *
     78  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
     79  *    endorse or promote products derived from this software without
     80  *    prior written permission. For written permission, please contact
     81  *    openssl-core (at) openssl.org.
     82  *
     83  * 5. Products derived from this software may not be called "OpenSSL"
     84  *    nor may "OpenSSL" appear in their names without prior written
     85  *    permission of the OpenSSL Project.
     86  *
     87  * 6. Redistributions of any form whatsoever must retain the following
     88  *    acknowledgment:
     89  *    "This product includes software developed by the OpenSSL Project
     90  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
     91  *
     92  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
     93  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     94  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     95  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
     96  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     97  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     98  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     99  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    100  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
    101  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    102  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
    103  * OF THE POSSIBILITY OF SUCH DAMAGE.
    104  * ====================================================================
    105  *
    106  * This product includes cryptographic software written by Eric Young
    107  * (eay (at) cryptsoft.com).  This product includes software written by Tim
    108  * Hudson (tjh (at) cryptsoft.com).
    109  *
    110  */
    111 
    112 #include <stdio.h>
    113 #include <stdarg.h>
    114 #include <string.h>
    115 #include "cryptlib.h"
    116 #include <openssl/lhash.h>
    117 #include <openssl/crypto.h>
    118 #include <openssl/buffer.h>
    119 #include <openssl/bio.h>
    120 #include <openssl/err.h>
    121 
    122 #define err_clear_data(p,i) \
    123 	do { \
    124 	if (((p)->err_data[i] != NULL) && \
    125 		(p)->err_data_flags[i] & ERR_TXT_MALLOCED) \
    126 		{  \
    127 		OPENSSL_free((p)->err_data[i]); \
    128 		(p)->err_data[i]=NULL; \
    129 		} \
    130 	(p)->err_data_flags[i]=0; \
    131 	} while(0)
    132 
    133 #define err_clear(p,i) \
    134 	do { \
    135 	(p)->err_flags[i]=0; \
    136 	(p)->err_buffer[i]=0; \
    137 	err_clear_data(p,i); \
    138 	(p)->err_file[i]=NULL; \
    139 	(p)->err_line[i]= -1; \
    140 	} while(0)
    141 
    142 static void err_load_strings(int lib, ERR_STRING_DATA *str);
    143 
    144 static void ERR_STATE_free(ERR_STATE *s);
    145 
    146 /* Define the predeclared (but externally opaque) "ERR_FNS" type */
    147 struct st_ERR_FNS
    148 	{
    149 	/* Works on the "error_hash" string table */
    150 	LHASH *(*cb_err_get)(int create);
    151 	void (*cb_err_del)(void);
    152 	ERR_STRING_DATA *(*cb_err_get_item)(const ERR_STRING_DATA *);
    153 	ERR_STRING_DATA *(*cb_err_set_item)(ERR_STRING_DATA *);
    154 	ERR_STRING_DATA *(*cb_err_del_item)(ERR_STRING_DATA *);
    155 	/* Works on the "thread_hash" error-state table */
    156 	LHASH *(*cb_thread_get)(int create);
    157 	void (*cb_thread_release)(LHASH **hash);
    158 	ERR_STATE *(*cb_thread_get_item)(const ERR_STATE *);
    159 	ERR_STATE *(*cb_thread_set_item)(ERR_STATE *);
    160 	void (*cb_thread_del_item)(const ERR_STATE *);
    161 	/* Returns the next available error "library" numbers */
    162 	int (*cb_get_next_lib)(void);
    163 	};
    164 
    165 /* Predeclarations of the "err_defaults" functions */
    166 static LHASH *int_err_get(int create);
    167 static void int_err_del(void);
    168 static ERR_STRING_DATA *int_err_get_item(const ERR_STRING_DATA *);
    169 static ERR_STRING_DATA *int_err_set_item(ERR_STRING_DATA *);
    170 static ERR_STRING_DATA *int_err_del_item(ERR_STRING_DATA *);
    171 static LHASH *int_thread_get(int create);
    172 static void int_thread_release(LHASH **hash);
    173 static ERR_STATE *int_thread_get_item(const ERR_STATE *);
    174 static ERR_STATE *int_thread_set_item(ERR_STATE *);
    175 static void int_thread_del_item(const ERR_STATE *);
    176 static int int_err_get_next_lib(void);
    177 /* The static ERR_FNS table using these defaults functions */
    178 static const ERR_FNS err_defaults =
    179 	{
    180 	int_err_get,
    181 	int_err_del,
    182 	int_err_get_item,
    183 	int_err_set_item,
    184 	int_err_del_item,
    185 	int_thread_get,
    186 	int_thread_release,
    187 	int_thread_get_item,
    188 	int_thread_set_item,
    189 	int_thread_del_item,
    190 	int_err_get_next_lib
    191 	};
    192 
    193 /* The replacable table of ERR_FNS functions we use at run-time */
    194 static const ERR_FNS *err_fns = NULL;
    195 
    196 /* Eg. rather than using "err_get()", use "ERRFN(err_get)()". */
    197 #define ERRFN(a) err_fns->cb_##a
    198 
    199 /* The internal state used by "err_defaults" - as such, the setting, reading,
    200  * creating, and deleting of this data should only be permitted via the
    201  * "err_defaults" functions. This way, a linked module can completely defer all
    202  * ERR state operation (together with requisite locking) to the implementations
    203  * and state in the loading application. */
    204 static LHASH *int_error_hash = NULL;
    205 static LHASH *int_thread_hash = NULL;
    206 static int int_thread_hash_references = 0;
    207 static int int_err_library_number= ERR_LIB_USER;
    208 
    209 /* Internal function that checks whether "err_fns" is set and if not, sets it to
    210  * the defaults. */
    211 static void err_fns_check(void)
    212 	{
    213 	if (err_fns) return;
    214 
    215 	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
    216 	if (!err_fns)
    217 		err_fns = &err_defaults;
    218 	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
    219 	}
    220 
    221 /* API functions to get or set the underlying ERR functions. */
    222 
    223 const ERR_FNS *ERR_get_implementation(void)
    224 	{
    225 	err_fns_check();
    226 	return err_fns;
    227 	}
    228 
    229 int ERR_set_implementation(const ERR_FNS *fns)
    230 	{
    231 	int ret = 0;
    232 
    233 	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
    234 	/* It's too late if 'err_fns' is non-NULL. BTW: not much point setting
    235 	 * an error is there?! */
    236 	if (!err_fns)
    237 		{
    238 		err_fns = fns;
    239 		ret = 1;
    240 		}
    241 	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
    242 	return ret;
    243 	}
    244 
    245 /* These are the callbacks provided to "lh_new()" when creating the LHASH tables
    246  * internal to the "err_defaults" implementation. */
    247 
    248 /* static unsigned long err_hash(ERR_STRING_DATA *a); */
    249 static unsigned long err_hash(const void *a_void);
    250 /* static int err_cmp(ERR_STRING_DATA *a, ERR_STRING_DATA *b); */
    251 static int err_cmp(const void *a_void, const void *b_void);
    252 /* static unsigned long pid_hash(ERR_STATE *pid); */
    253 static unsigned long pid_hash(const void *pid_void);
    254 /* static int pid_cmp(ERR_STATE *a,ERR_STATE *pid); */
    255 static int pid_cmp(const void *a_void,const void *pid_void);
    256 
    257 /* The internal functions used in the "err_defaults" implementation */
    258 
    259 static LHASH *int_err_get(int create)
    260 	{
    261 	LHASH *ret = NULL;
    262 
    263 	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
    264 	if (!int_error_hash && create)
    265 		{
    266 		CRYPTO_push_info("int_err_get (err.c)");
    267 		int_error_hash = lh_new(err_hash, err_cmp);
    268 		CRYPTO_pop_info();
    269 		}
    270 	if (int_error_hash)
    271 		ret = int_error_hash;
    272 	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
    273 
    274 	return ret;
    275 	}
    276 
    277 static void int_err_del(void)
    278 	{
    279 	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
    280 	if (int_error_hash)
    281 		{
    282 		lh_free(int_error_hash);
    283 		int_error_hash = NULL;
    284 		}
    285 	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
    286 	}
    287 
    288 static ERR_STRING_DATA *int_err_get_item(const ERR_STRING_DATA *d)
    289 	{
    290 	ERR_STRING_DATA *p;
    291 	LHASH *hash;
    292 
    293 	err_fns_check();
    294 	hash = ERRFN(err_get)(0);
    295 	if (!hash)
    296 		return NULL;
    297 
    298 	CRYPTO_r_lock(CRYPTO_LOCK_ERR);
    299 	p = (ERR_STRING_DATA *)lh_retrieve(hash, d);
    300 	CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
    301 
    302 	return p;
    303 	}
    304 
    305 static ERR_STRING_DATA *int_err_set_item(ERR_STRING_DATA *d)
    306 	{
    307 	ERR_STRING_DATA *p;
    308 	LHASH *hash;
    309 
    310 	err_fns_check();
    311 	hash = ERRFN(err_get)(1);
    312 	if (!hash)
    313 		return NULL;
    314 
    315 	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
    316 	p = (ERR_STRING_DATA *)lh_insert(hash, d);
    317 	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
    318 
    319 	return p;
    320 	}
    321 
    322 static ERR_STRING_DATA *int_err_del_item(ERR_STRING_DATA *d)
    323 	{
    324 	ERR_STRING_DATA *p;
    325 	LHASH *hash;
    326 
    327 	err_fns_check();
    328 	hash = ERRFN(err_get)(0);
    329 	if (!hash)
    330 		return NULL;
    331 
    332 	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
    333 	p = (ERR_STRING_DATA *)lh_delete(hash, d);
    334 	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
    335 
    336 	return p;
    337 	}
    338 
    339 static LHASH *int_thread_get(int create)
    340 	{
    341 	LHASH *ret = NULL;
    342 
    343 	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
    344 	if (!int_thread_hash && create)
    345 		{
    346 		CRYPTO_push_info("int_thread_get (err.c)");
    347 		int_thread_hash = lh_new(pid_hash, pid_cmp);
    348 		CRYPTO_pop_info();
    349 		}
    350 	if (int_thread_hash)
    351 		{
    352 		int_thread_hash_references++;
    353 		ret = int_thread_hash;
    354 		}
    355 	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
    356 	return ret;
    357 	}
    358 
    359 static void int_thread_release(LHASH **hash)
    360 	{
    361 	int i;
    362 
    363 	if (hash == NULL || *hash == NULL)
    364 		return;
    365 
    366 	i = CRYPTO_add(&int_thread_hash_references, -1, CRYPTO_LOCK_ERR);
    367 
    368 #ifdef REF_PRINT
    369 	fprintf(stderr,"%4d:%s\n",int_thread_hash_references,"ERR");
    370 #endif
    371 	if (i > 0) return;
    372 #ifdef REF_CHECK
    373 	if (i < 0)
    374 		{
    375 		fprintf(stderr,"int_thread_release, bad reference count\n");
    376 		abort(); /* ok */
    377 		}
    378 #endif
    379 	*hash = NULL;
    380 	}
    381 
    382 static ERR_STATE *int_thread_get_item(const ERR_STATE *d)
    383 	{
    384 	ERR_STATE *p;
    385 	LHASH *hash;
    386 
    387 	err_fns_check();
    388 	hash = ERRFN(thread_get)(0);
    389 	if (!hash)
    390 		return NULL;
    391 
    392 	CRYPTO_r_lock(CRYPTO_LOCK_ERR);
    393 	p = (ERR_STATE *)lh_retrieve(hash, d);
    394 	CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
    395 
    396 	ERRFN(thread_release)(&hash);
    397 	return p;
    398 	}
    399 
    400 static ERR_STATE *int_thread_set_item(ERR_STATE *d)
    401 	{
    402 	ERR_STATE *p;
    403 	LHASH *hash;
    404 
    405 	err_fns_check();
    406 	hash = ERRFN(thread_get)(1);
    407 	if (!hash)
    408 		return NULL;
    409 
    410 	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
    411 	p = (ERR_STATE *)lh_insert(hash, d);
    412 	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
    413 
    414 	ERRFN(thread_release)(&hash);
    415 	return p;
    416 	}
    417 
    418 static void int_thread_del_item(const ERR_STATE *d)
    419 	{
    420 	ERR_STATE *p;
    421 	LHASH *hash;
    422 
    423 	err_fns_check();
    424 	hash = ERRFN(thread_get)(0);
    425 	if (!hash)
    426 		return;
    427 
    428 	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
    429 	p = (ERR_STATE *)lh_delete(hash, d);
    430 	/* make sure we don't leak memory */
    431 	if (int_thread_hash_references == 1
    432 		&& int_thread_hash && (lh_num_items(int_thread_hash) == 0))
    433 		{
    434 		lh_free(int_thread_hash);
    435 		int_thread_hash = NULL;
    436 		}
    437 	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
    438 
    439 	ERRFN(thread_release)(&hash);
    440 	if (p)
    441 		ERR_STATE_free(p);
    442 	}
    443 
    444 static int int_err_get_next_lib(void)
    445 	{
    446 	int ret;
    447 
    448 	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
    449 	ret = int_err_library_number++;
    450 	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
    451 
    452 	return ret;
    453 	}
    454 
    455 static void ERR_STATE_free(ERR_STATE *s)
    456 	{
    457 	int i;
    458 
    459 	if (s == NULL)
    460 	    return;
    461 
    462 	for (i=0; i<ERR_NUM_ERRORS; i++)
    463 		{
    464 		err_clear_data(s,i);
    465 		}
    466 	OPENSSL_free(s);
    467 	}
    468 
    469 static void err_load_strings(int lib, ERR_STRING_DATA *str)
    470 	{
    471 	while (str->error)
    472 		{
    473 		if (lib)
    474 			str->error|=ERR_PACK(lib,0,0);
    475 		ERRFN(err_set_item)(str);
    476 		str++;
    477 		}
    478 	}
    479 
    480 void ERR_load_strings(int lib, ERR_STRING_DATA *str)
    481 	{
    482 	err_fns_check();
    483 	err_load_strings(lib, str);
    484 	}
    485 
    486 void ERR_unload_strings(int lib, ERR_STRING_DATA *str)
    487 	{
    488 	while (str->error)
    489 		{
    490 		if (lib)
    491 			str->error|=ERR_PACK(lib,0,0);
    492 		ERRFN(err_del_item)(str);
    493 		str++;
    494 		}
    495 	}
    496 
    497 void ERR_free_strings(void)
    498 	{
    499 	err_fns_check();
    500 	ERRFN(err_del)();
    501 	}
    502 
    503 LHASH *ERR_get_string_table(void)
    504 	{
    505 	err_fns_check();
    506 	return ERRFN(err_get)(0);
    507 	}
    508 
    509 LHASH *ERR_get_err_state_table(void)
    510 	{
    511 	err_fns_check();
    512 	return ERRFN(thread_get)(0);
    513 	}
    514 
    515 void ERR_release_err_state_table(LHASH **hash)
    516 	{
    517 	err_fns_check();
    518 	ERRFN(thread_release)(hash);
    519 	}
    520 
    521 const char *ERR_lib_error_string(unsigned long e)
    522 	{
    523 	ERR_STRING_DATA d,*p;
    524 	unsigned long l;
    525 
    526 	err_fns_check();
    527 	l=ERR_GET_LIB(e);
    528 	d.error=ERR_PACK(l,0,0);
    529 	p=ERRFN(err_get_item)(&d);
    530 	return((p == NULL)?NULL:p->string);
    531 	}
    532 
    533 const char *ERR_func_error_string(unsigned long e)
    534 	{
    535 	ERR_STRING_DATA d,*p;
    536 	unsigned long l,f;
    537 
    538 	err_fns_check();
    539 	l=ERR_GET_LIB(e);
    540 	f=ERR_GET_FUNC(e);
    541 	d.error=ERR_PACK(l,f,0);
    542 	p=ERRFN(err_get_item)(&d);
    543 	return((p == NULL)?NULL:p->string);
    544 	}
    545 
    546 const char *ERR_reason_error_string(unsigned long e)
    547 	{
    548 	ERR_STRING_DATA d,*p=NULL;
    549 	unsigned long l,r;
    550 
    551 	err_fns_check();
    552 	l=ERR_GET_LIB(e);
    553 	r=ERR_GET_REASON(e);
    554 	d.error=ERR_PACK(l,0,r);
    555 	p=ERRFN(err_get_item)(&d);
    556 	if (!p)
    557 		{
    558 		d.error=ERR_PACK(0,0,r);
    559 		p=ERRFN(err_get_item)(&d);
    560 		}
    561 	return((p == NULL)?NULL:p->string);
    562 	}
    563 
    564 /* static unsigned long err_hash(ERR_STRING_DATA *a) */
    565 static unsigned long err_hash(const void *a_void)
    566 	{
    567 	unsigned long ret,l;
    568 
    569 	l=((const ERR_STRING_DATA *)a_void)->error;
    570 	ret=l^ERR_GET_LIB(l)^ERR_GET_FUNC(l);
    571 	return(ret^ret%19*13);
    572 	}
    573 
    574 /* static int err_cmp(ERR_STRING_DATA *a, ERR_STRING_DATA *b) */
    575 static int err_cmp(const void *a_void, const void *b_void)
    576 	{
    577 	return((int)(((const ERR_STRING_DATA *)a_void)->error -
    578 			((const ERR_STRING_DATA *)b_void)->error));
    579 	}
    580 
    581 /* static unsigned long pid_hash(ERR_STATE *a) */
    582 static unsigned long pid_hash(const void *a_void)
    583 	{
    584 	return(((const ERR_STATE *)a_void)->pid*13);
    585 	}
    586 
    587 /* static int pid_cmp(ERR_STATE *a, ERR_STATE *b) */
    588 static int pid_cmp(const void *a_void, const void *b_void)
    589 	{
    590 	return((int)((long)((const ERR_STATE *)a_void)->pid -
    591 			(long)((const ERR_STATE *)b_void)->pid));
    592 	}
    593 #ifdef OPENSSL_FIPS
    594 static void int_err_remove_state(unsigned long pid)
    595 #else
    596 void ERR_remove_state(unsigned long pid)
    597 #endif
    598 	{
    599 	ERR_STATE tmp;
    600 
    601 	err_fns_check();
    602 	if (pid == 0)
    603 		pid=(unsigned long)CRYPTO_thread_id();
    604 	tmp.pid=pid;
    605 	/* thread_del_item automatically destroys the LHASH if the number of
    606 	 * items reaches zero. */
    607 	ERRFN(thread_del_item)(&tmp);
    608 	}
    609 
    610 #ifdef OPENSSL_FIPS
    611 	static ERR_STATE *int_err_get_state(void)
    612 #else
    613 ERR_STATE *ERR_get_state(void)
    614 #endif
    615 	{
    616 	static ERR_STATE fallback;
    617 	ERR_STATE *ret,tmp,*tmpp=NULL;
    618 	int i;
    619 	unsigned long pid;
    620 
    621 	err_fns_check();
    622 	pid=(unsigned long)CRYPTO_thread_id();
    623 	tmp.pid=pid;
    624 	ret=ERRFN(thread_get_item)(&tmp);
    625 
    626 	/* ret == the error state, if NULL, make a new one */
    627 	if (ret == NULL)
    628 		{
    629 		ret=(ERR_STATE *)OPENSSL_malloc(sizeof(ERR_STATE));
    630 		if (ret == NULL) return(&fallback);
    631 		ret->pid=pid;
    632 		ret->top=0;
    633 		ret->bottom=0;
    634 		for (i=0; i<ERR_NUM_ERRORS; i++)
    635 			{
    636 			ret->err_data[i]=NULL;
    637 			ret->err_data_flags[i]=0;
    638 			}
    639 		tmpp = ERRFN(thread_set_item)(ret);
    640 		/* To check if insertion failed, do a get. */
    641 		if (ERRFN(thread_get_item)(ret) != ret)
    642 			{
    643 			ERR_STATE_free(ret); /* could not insert it */
    644 			return(&fallback);
    645 			}
    646 		/* If a race occured in this function and we came second, tmpp
    647 		 * is the first one that we just replaced. */
    648 		if (tmpp)
    649 			ERR_STATE_free(tmpp);
    650 		}
    651 	return ret;
    652 	}
    653 
    654 #ifdef OPENSSL_FIPS
    655 void int_ERR_lib_init(void)
    656 	{
    657 	int_ERR_set_state_func(int_err_get_state, int_err_remove_state);
    658 	}
    659 #endif
    660 
    661 int ERR_get_next_error_library(void)
    662 	{
    663 	err_fns_check();
    664 	return ERRFN(get_next_lib)();
    665 	}
    666