void create_bound_listeners(int dienow)
{
for (iface = daemon->interfaces; iface; iface = iface->next)
{
new = create_listeners(&iface->addr, iface->tftp_ok, dienow)
new->iface = iface;
new->next = daemon->listeners;
daemon->listeners = new;
iface->done = 1;
}
}
//创建server的fd,同时也通过next串联起来
void allocate_sfd()
{
struct serverfd *sfd;
if (!(sfd = whine_malloc(sizeof(struct serverfd))))
if ((sfd->fd = socket(addr->sa.sa_family, SOCK_DGRAM, 0)) == -1)
local_bind(sfd->fd, addr, intname, ifindex, 0)
sfd->source_addr = *addr;
sfd->next = daemon->sfds;
sfd->ifindex = ifindex;
sfd->preallocated = 0;
daemon->sfds = sfd;
}
void check_servers(void)
{
//这里就是下游的server
for (count = 0, serv = daemon->servers; serv; serv = serv->next)
{
serv->edns_pktsz = daemon->edns_pktsz;
//如果配置的是域名的话,则要检测域名的合法性
//获取到地址中的port
port = prettyprint_addr(&serv->addr, daemon->namebuff);
//为下游创建socket
if (!serv->sfd &!(serv->sfd = allocate_sfd(&serv->source_addr, serv->interface)) &&errno != 0)
serv->sfd->used = 1;
}
}
void set_dns_listeners()
{
//将server的fd加入到poll中进行监控
for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
{
poll_listen(serverfdp->fd, POLLIN);
}
}
static void async_event(int pipe, time_t now)
{
if (read_event(pipe, &ev, &msg))
{
switch (ev.event)
case EVENT_INIT:
clear_cache_and_reload(now);
}
}
void reply_query()
{
//接收信息
ssize_t n = recvfrom(fd, daemon->packet, daemon->packet_buff_sz, 0, &serveraddr.sa, &addrlen);
//下面就是纪录信息之类的,检测包的合法性
//如果响应的包是不合法的,那就重新查询下一个合法的上游server
//根据响应包重构查询包发送给next的上游服务端
server = forward->sentto;
if ((nn = process_reply())
{
return resize_packet(header, n, pheader, plen);
}
//内部调用sendmsg,
send_from()
}
void receive_query()
{
if ((n = recvmsg(listen->fd, &msg, 0))
//后面的就是开始匹配查询
如果cache命中就查询cache,否则查询后端
m = answer_request()
send_from(listen->fd)
//查询后端的
forward_query()
{
sendto(fd)
}
}
static void check_dns_listeners(time_t now)
{
//当上游的服务器可读的时候,将关键信息进行缓存,同时将结果响应给客户端的请求
for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
{
if (poll_check(serverfdp->fd, POLLIN))
reply_query(serverfdp->fd, serverfdp->source_addr.sa.sa_family, now);
}
//检测到来的dns查询
for (listener = daemon->listeners; listener; listener = listener->next)
{
if (listener->fd != -1 && poll_check(listener->fd, POLLIN))
receive_query(listener, now);
}
}
//如果是-a选项(就是监听的端口),则把地址存储到if_addrs中,如果是LOPT_AUTHPEER,则存储到auth_peers中,通过create_listen放入到listeners中
//如果是-S选项(就是连接的后端的地址),则把地址信息存储到servers中
从main函数开始
注册一些信号的函数
依据配置文件和命令行设置struct daemon的值
检测它配置的一些合法性
//开始创建监听端口,调用socket,bind等,把监听socket通过next连接,同时连入到listeners中
create_bound_listeners(1);
{
for (if_tmp = daemon->if_addrs; if_tmp; if_tmp = if_tmp->next)
{
new = create_listeners(&if_tmp->addr, !!option_bool(OPT_TFTP), dienow))
new->next = daemon->listeners;
daemon->listeners = new;
}
}
//初始化cache
cache_init();
//创建管道
safe_pipe(pipefd, 1);
//fork()
if (daemon->port != 0)
check_servers();
//获取到当前的pid
pid = getpid();
piperead = pipefd[0];
pipewrite = pipefd[1];
//写EVENT_INIT进去
send_event(pipewrite, EVENT_INIT, 0, NULL);
err_pipe[1] = -1;
//下面是将进程放到后台执行
//将pid写入file
sprintf(daemon->namebuff, "%d\n", (int) getpid());
if (daemon->port != 0)
check_servers();
//选择一个resolve文件
#ifdef HAVE_INOTIFY
/* Using inotify, have to select a resolv file at startup */
poll_resolv(1, 0, now);
#endif
while(1)
{
//初始化poll,nfds=0
poll_reset();
//将server的fd注册到pollfd
t = set_dns_listeners(now)
//将piperead注册到pollfd
poll_listen(piperead, POLLIN);
//内部就是调用poll,
if (do_poll(timeout) < 0)
continue;
//如果piperead有信息来了,则要去处理相关server
if (poll_check(piperead, POLLIN))
async_event(piperead, now);
//调用poll
if (do_poll(timeout) < 0)
continue;
//就是处理dns逻辑请求的
check_dns_listeners(now);
}