看了openssl的erro模块,简单聊一聊该模块的一些事情。
erro模块的作用是记录openssl在运行的过程中的错误情况,相当于工程开发中的日志统计功能。当然erro模块所记录的都是一些出错的地方,比只日志统计要弱一些。因为通常的日志统计要包括正常的统计和异常的统计等内容。
整个err模块记录的信息分为三个层次,即library,function,reason。所谓的library指的是openssl各个基础的模块,function表示函数级别的统计,reason表示具体的原因。在err.h可以看到定义了所有需要输出日志的模块信息,例如
# define ERR_LIB_SYS 2
表示系统模块级别的错误,所谓的系统错误指的是ssl下层,也就是tcp层的传递的一些错误,可以看到该模块对应的function为
# define SYS_F_CONNECT 2
# define SYS_F_SOCKET 4
# define SYS_F_BIND 6
# define SYS_F_LISTEN 7
# define SYS_F_ACCEPT 8
等操作,由于tcp层对于ssl层相当于黑盒,没有具体的reason。
# define ERR_LIB_X509 11
同理表示证书结模块错误
# define ERR_LIB_SSL 20
表示ssl协议栈模块错误。
关于各个模块的function和reason的具体代号在各自的模块中(也就是相应的文件夹下面会有定义)。例如ssl模块的具体错误定义在ssl_err.h
中,常量 SSL_str_functs
以及SSL_str_reasons
分别是具体的函数和原因数组。当然这两个数组的类型为ERR_STRING_DATA
,是在err.h中定义的错误消息结构,如下:
typedef struct ERR_string_data_st {
unsigned long error;
const char *string;
} ERR_STRING_DATA;
上述结构中erro为错误消息码,string为具体的字符串消息。 以SSL_str_functs
数组中的某一项为例。消息码的为一个4字节整形,具体是通过ERR_PAC
K宏来生成的。该消息码的最高8位表示library,因此最多能够表示255个模块,接着12个位表示函数function,最后12位表示原因reason。
值的注意的是对于一个特定的函数来说,如果其是某一个模块的函数,那么对于该函数错误消息码来说就是依赖于这个模块的,因此可以看到在SSL_str_functs
数组中,最高8为都是ERR_LIB_SSL
,如下:
{ERR_PACK(ERR_LIB_SSL, SSL_F_SET_CLIENT_CIPHERSUITE, 0),"set_client_ciphersuite"},
同理对于一个具体的错误消息,可能会出现多次,因此该消息并不依赖某一个特定的函数,但是要依赖某一个模块。在SSL_str_reasons
数组中,如下:
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_UNSUPPORTED_EXTENSION),
"tlsv1 unsupported extension"},
当然,对于具体的表征函数的宏
SSL_F_SET_CLIENT_CIPHERSUITE
以及表征原因的宏
SSL_R_TLSV1_UNSUPPORTED_EXTENSION
在sslerr.h中均有定义。
可以理解为在一个具体的模块下面下挂了所有的函数代号,以及所有的错误原因代号。给定一个具体的错误码,就能都通过模块代号,函数代号,原因代号就能够定位到具体的错误原因。
openssl错误消息的组织方式是以ssl模块为例,在ssl_err.c中函数ERR_load_SSL_strings
会将定义的两个常量数组加载到全局的哈希表int_error_hash
中。哈希函数为err_string_data_hash
,哈希值也是由library,function以及reason代号生成的。 当然erro模块本身定义的library,function以及reason则由ERR_load_ERR_strings
加载到全局哈希表中。
本文为CSDN村中少年原创文章,转载记得加上小尾巴偶,博主链接这里。