dnsmasq架构

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);
}

 

你可能感兴趣的:(dnsmasq架构,ddnsmasq)