android10 dnsmasq 工作不正常问题

在Android 10项目中遇到dnsmasq工作异常,无论预装2.51版还是2.78版都无法正常运行。问题出在dnsmasq无法响应localhost的53端口DNS请求,导致初始化后的事件检查失败。经过分析代码和创建简单示例,发现只有当使用busbox中的ping指令时,dnsmasq才能正常工作。原因是Android 10放弃了dnsmasq,转而在netd中实现DNS解析器,并在dhcpserver中实现DHCP服务,原有网络测试命令无效。
摘要由CSDN通过智能技术生成

 

 

 

近期在android10的项目中用到了dnsmasq,正如大家所了解的一样,这东西是个解析并缓存dns的工具。但是本人发现无论预装的2.51版本还是我后来移植源码编译的2.78版本都不能正常。我本是打算用dnsmasq的 conf-file配置调用ipset的,但是通过log发现,即使dnsmasq成功的解析了ipset的指令,但是并没有设置成功。

configfile.con

ipset=/baidu.com.com/iplist

 

dnsmasq/src/option.c // 此程序是专门解析各种配置指令的

    case LOPT_IPSET: /* --ipset */
#ifndef HAVE_IPSET
      ret_err(_("recompile with HAVE_IPSET defined to enable ipset directives"));
      break;
#else
      {
	 struct ipsets ipsets_head;
	 struct ipsets *ipsets = &ipsets_head;
	 int size;
	 char *end;
	 char **sets, **sets_pos;
	 memset(ipsets, 0, sizeof(struct ipsets));
	 unhide_metas(arg);
	 if (arg && *arg == '/') 
	   {
	     arg++;
	     while ((end = split_chr(arg, '/'))) 
	       {
		 char *domain = NULL;
		 /* elide leading dots - they are implied in the search algorithm */
		 while (*arg == '.')
		   arg++;
		 /* # matches everything and becomes a zero length domain string */
		 if (strcmp(arg, "#") == 0 || !*arg)
		   domain = "";
		 else if (strlen(arg) != 0 && !(domain = canonicalise_opt(arg)))
		   ret_err(gen_err);
		 ipsets->next = opt_malloc(sizeof(struct ipsets));
		 ipsets = ipsets->next;
		 memset(ipsets, 0, sizeof(struct ipsets));
		 ipsets->domain = domain;
		 arg = end;
         my_syslog(LOG_INFO, _("junqiang, domain:%s arg: %s"), domain, arg);
	       }
	   } 
	 else 
	   {
	     ipsets->next = opt_malloc(sizeof(struct ipsets));
	     ipsets = ipsets->next;
	     memset(ipsets, 0, sizeof(struct ipsets));
	     ipsets->domain = "";
	   }
	 
	 if (!arg || !*arg)
	   ret_err(gen_err);
	 
	 for (size = 2, end = arg; *end; ++end) 
	   if (*end == ',')
	       ++size;
     
	 sets = sets_pos = opt_malloc(sizeof(char *) * size);
	 
	 do {
	   end = split(arg);
	   *sets_pos++ = opt_string_alloc(arg);
	   arg = end;
	 } while (end);
	 *sets_pos = 0;
	 for (ipsets = &ipsets_head; ipsets->next; ipsets = ipsets->next)
	   ipsets->next->sets = sets;
	 ipsets->next = daemon->ipsets;
	 daemon->ipsets = ipsets_head.next;
	 
	 break;
      }
#endif
I/dnsmasq: started, version 2.78 cachesize 150
I/dnsmasq: compile time options: no-IPv6 GNU-getopt no-DBus no-i18n no-IDN DHCP no-DHCPv6 no-scripts no-TFTP no-conntrack ipset auth no-DNSSEC loop-detect inotify
I/dnsmasq: reading /data/system/dnsmasq/resolv.dnsmasq.conf
I/dnsmasq: using nameserver 223.5.5.5#53
E/dnsmasq: bad address at /etc/hosts line 2
I/dnsmasq: read /etc/hosts - 1 addresses
I/dnsmasq: junqiang, domain:baidu.com arg: iplist

从log来看 解析完指令后,dnsmasq的工作就没有再继续了。。。  肯定是中间哪里出问题导致程序没有继续运行下去。

 

然后就在dnsmasq.c中开始打log,发现在check_dns_listeners(time_t now)之后就没有其他进一步操作了

static void check_dns_listeners(time_t now)
{
  struct serverfd *serverfdp;
  struct listener *listener;
  int i;
  int pipefd[2];
  
  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);
  
  if (daemon->port != 0 && !daemon->osport)
    for (i = 0; i < RANDOM_SOCKS; i++)
      if (daemon->randomsocks[i].refcount != 0 && 
	  poll_check(daemon->randomsocks[i].fd, POLLIN))
	reply_query(daemon->randomsocks[i].fd, daemon->randomsocks[i].family, now);

  /* Races. The child process can die before we read all of the data from the
     pipe, or vice versa. Therefore send tcp_pids to zero when we wait() the 
     process, and tcp_pipes to -1 and close the FD when we read the last
     of the data - indicated by cache_recv_insert returning zero.
     The order of these events is indeterminate, and both are needed
     to free the process slot. Once the child process has gone, poll()
     returns POLLHUP, not POLLIN, so have to check for both here. */
  if (!option_bool(OPT_DEBUG))
    for (i = 0; i < MAX_PROCS; i++)
      if (daemon->tcp_pipes[i] != -1 &&
	  poll_check(daemon->tcp_pipes[i], POLLIN | POLLHUP) &&
	  !cache_recv_insert(now, daemon->tcp_pipes[i]))
	{
	  close(daemon->tcp_pipes[i]);
	  daemon->tcp_pipes[i] = -1;	
	}
	
  for (listener = daemon->listeners; listener; listener = listener->next)
    {
      if (listener->fd != -1 && poll_check(listener->fd, POLLIN))
	receive_query(listener, now); 
      
#ifdef HAVE_TFTP     
      if (listener->tftpfd != -1 && poll_check(listener->tftpfd, POLLIN))
	tftp_request(listener, now);
#endif

...

从上面代码中我们可以看到在reply_query操作之前都会进行poll_check。  从阅读代码我们发现运行ipset指令的过程就在reply_query中进行的。那么思路就很清晰了,看看poll_check为什么会不成功。

poll.c

int do_poll(int timeout)
{
  return poll(pollfds, nfds, timeout);
}

int poll_check(int fd, short event)
{
  nfds_t i = fd_search(fd);
  
  if (i < nfds && pollfds[i].fd == fd)
    return pollfds[i].revents & event;

  return 0;
}

从上面这段代码中我们又可以知道poll_check是进行了事件检查,检查do_poll是否有相应时间的发生。 那么poll又是在获取什么呢???

 

 

继续阅读代码发现:

在dnsmasq.c刚开始初始化中 先调用了create

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值