【转载请注明出处:钱国正专栏 http://blog.csdn.net/qianguozheng/article/details/37666829】
起因
为了解决客户反映的openwrt系统上不了网的问题,我们对其进行了远程协助,发现ip可以访问,只是域名访问不了,这就帮助我们定位了问题---DNS.
网上搜寻
找到了个有同样的问题,说是域名服务器不能用,同样是20M光纤拨号,真是巧合啊,到网上搜了这个哥们的网名,找到不少,但是最近发表的不多哦,无果,自己看代码查查。
代码分析
从拨号进行找了/lib/netifd脚本,无果,自己看看在线进程,发现竟然存在这么一个进程 netifd, 既然这样,那就看看源代码吧。
至此,又发现了【http://xinliang.me/blog/?p=149】,这位兄弟的博客,绝对是先驱,看他的东西很有条理,学习到了,openwrt下果然是使用ubus类似Linux发行版上的dbus, ubus主要是用于系统进程间通信,关于详情,请访问这个哥的博客。
nfetifd的ubus RPC接口如下:
<span style="font-size:18px;">static struct ubus_method main_object_methods[] = { { .name = "restart", .handler = netifd_handle_restart }, { .name = "reload", .handler = netifd_handle_reload }, UBUS_METHOD("add_host_route", netifd_add_host_route, route_policy), { .name = "get_proto_handlers", .handler = netifd_get_proto_handlers }, UBUS_METHOD("add_dynamic", netifd_add_dynamic, dynamic_policy), }; static struct ubus_object_type main_object_type = UBUS_OBJECT_TYPE("netifd", main_object_methods); static struct ubus_object main_object = { .name = "network", .type = &main_object_type, .methods = main_object_methods, .n_methods = ARRAY_SIZE(main_object_methods), }; </span>
具体注册的对象在下面
<span style="font-size:18px;">root@YSWiFi:/etc/config# ubus list -v 'dhcp' @8f0c907e "ipv4leases":{} "ipv6leases":{} 'log' @92083360 "read":{"lines":"Integer"} "write":{"event":"String"} <span style="color:#000099;">'network' @36acc569 "restart":{} "reload":{} "add_host_route":{"target":"String","v6":"Boolean","interface":"String"} "get_proto_handlers":{} "add_dynamic":{"name":"String"}</span> 'network.device' @7b6892b7 "status":{"name":"String"} "set_alias":{"alias":"Array","device":"String"} "set_state":{"name":"String","defer":"Boolean"} 'network.interface' @e62dccc3 "up":{} "down":{} "status":{} "prepare":{} "dump":{} "add_device":{"name":"String"} "remove_device":{"name":"String"} "notify_proto":{} "remove":{} "set_data":{} 'network.interface.lan' @817ffe0f "up":{} "down":{} "status":{} "prepare":{} "dump":{} "add_device":{"name":"String"} "remove_device":{"name":"String"} "notify_proto":{} "remove":{} "set_data":{} 'network.interface.lan2' @137330bd "up":{} "down":{} "status":{} "prepare":{} "dump":{} "add_device":{"name":"String"} "remove_device":{"name":"String"} "notify_proto":{} "remove":{} "set_data":{} 'network.interface.loopback' @44806906 "up":{} "down":{} "status":{} "prepare":{} "dump":{} "add_device":{"name":"String"} "remove_device":{"name":"String"} "notify_proto":{} "remove":{} "set_data":{} 'network.interface.wan' @4ebe9d3b "up":{} "down":{} "status":{} "prepare":{} "dump":{} "add_device":{"name":"String"} "remove_device":{"name":"String"} "notify_proto":{} "remove":{} "set_data":{} 'network.wireless' @9a257aa5 "up":{} "down":{} "status":{} "notify":{} 'service' @582b527e "set":{"name":"String","script":"String","instances":"Table","triggers":"Array","validate":"Array"} "add":{"name":"String","script":"String","instances":"Table","triggers":"Array","validate":"Array"} "list":{"name":"String"} "delete":{"name":"String","instance":"String"} "update_start":{"name":"String"} "update_complete":{"name":"String"} "event":{"type":"String","data":"Table"} "validate":{"package":"String","type":"String","service":"String"} 'system' @d8c56a4b "board":{} "info":{} "upgrade":{} "watchdog":{"frequency":"Integer","timeout":"Integer","stop":"Boolean"} "signal":{"pid":"Integer","signum":"Integer"} root@YSWiFi:/etc/config# </span>
简单来说,我想找的问题,就是resolv.conf.auto是如何产生的,是由谁产生的, 在wan口up的时候netifd进行会更新状态,根据获得的心的DNS地址填写这个resolv.conf.auto文件。
netifd.h
<span style="font-size:18px;">#ifdef DUMMY_MODE #define DEFAULT_MAIN_PATH "./examples" #define DEFAULT_CONFIG_PATH "./config" #define DEFAULT_HOTPLUG_PATH "./examples/hotplug-cmd" #define DEFAULT_RESOLV_CONF "./tmp/resolv.conf" #else #define DEFAULT_MAIN_PATH "/lib/netifd" #define DEFAULT_CONFIG_PATH NULL /* use the default set in libuci */ #define DEFAULT_HOTPLUG_PATH "/sbin/hotplug-call" <span style="color:#000099;">#define DEFAULT_RESOLV_CONF "/tmp/resolv.conf.auto"</span> #endif</span>
interface-ip.c
<span style="font-size:18px;">void interface_write_resolv_conf(void) { struct interface *iface; char *path = alloca(strlen(resolv_conf) + 5); FILE *f; uint32_t crcold, crcnew; sprintf(path, "%s.tmp", resolv_conf); unlink(path); f = fopen(path, "w+"); if (!f) { D(INTERFACE, "Failed to open %s for writing\n", path); return; } vlist_for_each_element(&interfaces, iface, node) { if (iface->state != IFS_UP) continue; if (vlist_simple_empty(&iface->proto_ip.dns_search) && vlist_simple_empty(&iface->proto_ip.dns_servers) && vlist_simple_empty(&iface->config_ip.dns_search) && vlist_simple_empty(&iface->config_ip.dns_servers)) continue; fprintf(f, "# Interface %s\n", iface->name); write_resolv_conf_entries(f, &iface->config_ip); if (!iface->proto_ip.no_dns) write_resolv_conf_entries(f, &iface->proto_ip); } fflush(f); rewind(f); crcnew = crc32_file(f); fclose(f); crcold = crcnew + 1; f = fopen(resolv_conf, "r"); if (f) { crcold = crc32_file(f); fclose(f); } if (crcold == crcnew) { unlink(path); } else if (rename(path, resolv_conf) < 0) { D(INTERFACE, "Failed to replace %s\n", resolv_conf); unlink(path); } } </span>
总结:
虽然找到了在哪里生产的文件,要一下子解决或者是重现这个问题可不容易。所以我采取了一种折中的方法,指定每个客户端的DNS服务器为google的DNS服务器8.8.8.8 , 8.8.4.4.
【转载请注明出处:钱国正专栏
http://blog.csdn.net/qianguozheng/article/details/37666829】