DNS bind9 源码分析

bind9部分源码分析,基于bind9.18.21版源码

udp 启动监听过程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
main			bin/named/main.c   进程入口函数
setup bin/named/main.c 进程入口函数
named_log_init bin/named/log.c 日志初始化
create_managers bin/named/main.c 创建各种管理对象
named_server_create bin/named/server.c 服务端创建
ns_server_create lib/ns/server.c 创建ns server
run_server bin/named/server.c
load_configuration // 加载配置 ,成功后日志才能生效 bin/named/server.c
ns_interfacemgr_scan // lib/ns/interfacemgr.c 扫描本地网卡
do_scan lib/ns/interfacemgr.c
interface_setup lib/ns/interfacemgr.c
ns_interface_listenhttp // 建立http监听
ns_interface_listentls // 建立tsl监听
ns_interface_listenudp // 建立udp监听,,指定连接回调函数为 ns__client_request, lib/ns/interfacemgr.c
isc_nm_listenudp // 建立udp监听 lib/isc/netmgr/udp.c
start_udp_child // 设置udp连接回调函数
isc__nm_udp_lb_socket // 调用
isc__nm_socket // 调用socket函数创建监听 // lib/isc/netmgr/netmgr.c
ns_interface_listentcp // 建立udp监听,
load_zones // 加载zones ,成功后日志才能生效 bin/named/server.c

udp事件循环处理过程

1
2
3
4
5
6
7
8
9
10
11
12
13
create_managers	// 创建各种管理对象 bind/bin/named/main.c
isc_managers_create // 创建管理对象 lib/isc/managers.c
isc__netmgr_create // 创建网络管理对象 初始化libuv使用对象, 并传递nm_thread为线程的启动入口函数,在nm_thread中执行libuv的uv_run循环函数 lib/isc/netmgr/netmgr.c
isc_thread_create // 创建线程 ./lib/isc/thread.c
isc__trampoline_run // ./lib/isc/trampoline.c ./lib/isc/netmgr/netmgr.c //绑定到libuv uv_queue_work
result = (trampoline->start)(trampoline->arg); //启动线程主运行函数


isc__nmsocket_timer_restart // lib/isc/netmgr/netmgr.c
isc__nmsocket_readtimeout_cb // 网络管理器的读超时回调函数 lib/isc/netmgr/netmgr.c
isc__nm_readcb // lib/isc/netmgr/netmgr.c
isc__nm_async_readcb
uvreq->cb.recv(uvreq->handle, eresult, &region, uvreq->cbarg); // 回调到ns__client_request

udp请求处理过程

1
2
3
4
5
6
7
ns__client_request 			// 接收到的udp消息处理入口函数 ./lib/ns/client.c 
result = client->sctx->matchingview(); // 查询view,实际指向bind/bin/named/server.c 的 get_matching_view
dns_acl_allowed // lib/dns/acl.c get_matching_view查询acl
dns_acl_match // lib/dns/acl.c
ns_query_start // 处理查询消息 ./lib/ns/query.c
query_setup
ns__query_start

zone加载过程

1
2
3
4
5
6
7
8
9
10
11
run_server	// 加载zones , bin/named/server.c
load_configuration
cfg_parse_file(conf_parser, filename, &cfg_type_namedconf,&config) // 解析named文件 bin/named/server.c, conf_parser->lexer->sources 存放各个打开的文件对象, sources[i].name = filename; sources[i].input 为打开的FILE流对象
parse2 // lib/isccfg/parser.c
cfg_parse_obj // lib/isccfg/parser.c, result = type->parse(pctx, type, ret);type实际是 cfg_type_namedconf parse实际回调到cfg_parse_mapbody
cfg_parse_mapbody // lib/isccfg/parser.c, // 通过redo 和 parser_openfile 来循环打开各个include文件,并解析相关关键字
CHECK(cfg_parse_listelt(pctx, clause->type, &elt)); // 调用此语句循环解析
cfg_parse_obj 解析
load_zones // 循环加载所有的 zones bin/named/server.c
dns_zone_load // lib/dns/zone.c
zone_load // lib/dns/zone.c

acl

关键变量指向

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
cfg_type_namedconf->of---->指向 变量 namedconf_clausesets 
namedconf_clausesets[0]->type--->指向 变量 namedconf_clauses,
namedconf_clauses[0]->type--->指向 变量 cfg_type_acl 用于解析acl模块
cfg_type_acl->type 指向 cfg_parse_tuple 解析acl后面的内容
cfg_type_acl->of[0]指向acl_fields[0] 存储acl的name
cfg_type_acl->of[1]指向acl_fields[1] 存储acl的地址列表, acl_fields[1].type指向 cfg_type_bracketed_aml
cfg_type_bracketed_aml->type指向 cfg_parse_bracketed_list // 用于解析地址列表
cfg_parse_bracketed_list // parser.c: 解析acl 地址列表块
parse_list // parser.c: 循环解析{}中的所有地址列表
cfg_peektoken // parser.c: 每次解析一个token
cfg_gettoken // parser.c: 获取一个token

namedconf_clausesets[1]--->指向 namedconf_or_view_clauses // clause 指是一个由选项名和对应值组成且以分号结尾的的语句块(block)
namedconf_clauses 中定义了 named.conf文件的顶层字段处理函数

namedconf.c中的cfg_type_acl定义acl标记解析函数

解析调用

1
2
3
4
5
6
7
8
load_configuration	 	// bin/named/server.c
bind9_check_namedconf // lib/bind9/check.c
check_viewconf
checkacl
cfg_acl_fromconfig
cfg_acl_fromconfig2
count_acl_elements
get_acl_def

日志格式说明

13-May-2024 08:48:58.790 client @0x7f2638382ce8 127.0.0.1#50272 (oa.qiyi.domain): view view_default: query: oa.qiyi.domain IN A +E(0)K (127.0.0.1) [ECS 10.1.102.1/32/0]

+/- 递归/非递归
E(0) 0 代表edns版本号

其他

  • include/dns/enumclass.h include/dns/enumtype.h include/dns/rdatastruct.h include/dns/code.h 是通过Makefile生成的,Makefile调用 gen.c文件生成二进制程序gen,来生成相关头文件。 为什么这么做原因待确定

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!