地址对齐问题引起的 Bug 一则
这两天一直在圈人一起玩 google+ 。由于众所周之的原因,在墙内推广这个东西阻力重重。还好不需要必须翻墙,google 在北京是有网关的,修改本机 hosts 文件,把相关的域名指过去即可。在这里就不列出方法了,希望下面的评论中也不要贴出来,私下交流即可。还好移动版 G+并没有封掉,究其原因可能是 m.google.com 是所有 google 移动服务的统一入口,如果封杀影响较大。而 https 协议让墙无法分析 url ,不可能做到部分干扰。如果有一天真封禁了,手机上都无法阅读 greader ,收取 gmail ,那还真是个悲剧。
我在拉我老爸玩 G+ 的过程中,他老人家反应了一个问题,家里用手机使用 android 的 app 发不了帖子。我估摸着可能是被墙了。虽然可以让他 root 掉手机修改 hosts ,但显然这不是一个简便的解决方案。我便着手远程登陆家里的网关。那是一台用 LinkStation Pro 改造的 linux debian 机器。拥有一块 Arm9 CPU ,在上面跑一个 DNS 服务,足以让家中的局域网解析到可以登陆 G+ 的 ip 地址。
我先想到的是配置 bind9 服务。这个用过一段时间,大致知道该怎么折腾。不过 google+ 用到的域名很多,配置起来非常麻烦。我想肯定有更简便的解决方案,搜索了一下没有找到,想想这种事情拜一下 twitter 大神即可。果然,5 分钟以后,各种半夜不睡觉的死程就跳出来刷拉拉列了一串解决方案。
我选了 @wuwx 同学的 DNRD 方案。因为它看起来最接近我一开始自己提出的需求。我需要一个类似 hosts 文件的列表,优先解析这些域名到我指定的 ip ,其它的 dns query 就转发出去好了。
apt-get 没有找到现成的包,便下载了一个编译。还好是 C 而不是 C++ 写的,让那台破机器可以几分钟编译完。但是,我配置了半天都无法正确工作。列表中有的域名可以正确解析,有的则不行。作为一个死程,当然第一反应就是 debug 了。我以为可能是列表格式有问题,但这部分 dnrd 没有给出详细的 log 。我只好自己加了几行,并在查询的地方也输出了一些 log 。但试验结果是,列表中所有的域名都加载了,但 query 时,根本没有进入匹配查询。
把 dnrd 的 debug level 开到最大 4 ,可以看到很详细的信息。仔细比较了一下可以正常工作的域名,和不能正常工作的域名,发现 query type 正常时是 1 ,也就是 'A' 类查询,而不正常时是 0 ,未知类型。class 也分别是 1 和 256 。而从 query 包的字节流看,表示 type 和 class 的地方的四个字节都是 00 01 00 01 。
我的第一反应是错位了。因为 256 正好是 0x100 。检查了一下源代码,没发现什么问题。在 src/dns.c 里发现了这么几行:
脑子里一下闪现出初学 C 语言时某本书上提到的一句话:某些机器上,读取宽字需要地址对齐。
也就是说,如果 &msg[i] 的地址不对齐,从中读取一个 unsigned short 很可能是不可靠的(会强制对齐)。而网络包是紧凑排列,前面排的是域名字符串,不可能刚好在那个位置保证对齐。这也解释了为什么不同长度的域名查询,有的可以正确解析,有的不行。
加了几行 log 验证了我的想法之后,我动手 fix 这个 bug 。非常简单,只需要先用 memcpy 把 &msg[i] 后 sizeof(unsigned short) 个字节复制到一个局部 unsigned short 变量中,然后再调用 ntohs 即可。事实上,drnd 早期的版本正是这样做的,memcpy 的那几行还被注释在下面,不知道为何,后来改成了现在这样错误的版本。
修改过后,一切正常了。
Comments
Posted by: BF200 | (28) May 28, 2016 11:50 AM
Posted by: 福利工口姬 | (27) April 16, 2014 03:42 PM
Posted by: 400电话 | (26) September 5, 2011 03:20 PM
Posted by: liruqi | (25) September 5, 2011 02:17 PM
Posted by: masefee | (24) August 29, 2011 08:57 AM
Posted by: slade | (23) August 22, 2011 10:53 AM
Posted by: slade | (22) August 22, 2011 10:07 AM
Posted by: slade | (21) August 15, 2011 12:11 PM
Posted by: zelor | (20) August 6, 2011 12:26 AM
Posted by: 哲 | (19) August 4, 2011 11:31 AM
Posted by: 期刊 | (18) August 1, 2011 09:48 AM
Posted by: 辐射报 | (17) August 1, 2011 09:46 AM
Posted by: 大大方方 | (16) July 31, 2011 07:52 PM
Posted by: balsampear | (15) July 31, 2011 12:25 PM
Posted by: hanson | (14) July 30, 2011 07:28 PM
Posted by: Anonymous | (13) July 29, 2011 05:01 PM
Posted by: lifc0 | (12) July 28, 2011 10:32 PM
Posted by: snowflip | (11) July 28, 2011 02:24 PM
Posted by: sword007 | (10) July 28, 2011 12:07 PM
Posted by: daseny | (9) July 28, 2011 09:28 AM
Posted by: pig345 | (8) July 28, 2011 09:16 AM
Posted by: nothanks | (7) July 27, 2011 10:28 AM
Posted by: tw | (6) July 27, 2011 03:54 AM
Posted by: shell | (5) July 26, 2011 10:34 PM
Posted by: 防辐射服 | (4) July 26, 2011 07:16 PM
Posted by: est | (3) July 26, 2011 04:17 PM
Posted by: Adieu | (2) July 26, 2011 03:25 PM
Posted by: 云快印 | (1) July 26, 2011 01:52 PM