标签 Unix 下的文章

编译Ethereal On Windows

最近在研究项目下一期中新增的信令跟踪功能,在这个开源盛行的时代,开源工具当然是首选。我们发现了Ethereal,一款强大的网络分析工具包。我们不仅仅要使用Ethereal,而是在Ethereal上做二次开发,增加一个新dissector或者一个plugin,用来分析我们自己的应用层协议。

之所以选择Ethereal还有一个很重要的原因就是它已经支持300多个协议包了,这说明Ethereal的框架已经很成熟了,在其上面做二次开发具备可行性。我们最终要形成的成果物可能要运行在Solaris上,但是家里的服务器环境都是没有显示终端的,也看不到运行画面,所以我决定现在Windows上作开发,然后移植到Solaris上。Ethereal底层的图形接口采用的是GTK,GTK是一种可在跨平台的图形界面开发包,它屏蔽了不同OS的底层细节,便于我们的程序在各个OS平台上移植。由于GTK的使用,我才觉得我的开发方案是正确的:)。另外开发一个新的dissector涉及到的代码都应该是可移植的,所需的接口Ethereal都已经提供了,调用即可。所以我在想在Windows上开发成功后,拿到Solaris下重新编译后是应该能正确运行的,有些过于理想了^_^。

目前第一步工作就是先在Windows上编译Ethereal包,通过浏览Ethereal的Developer’s Guide和网上的一些资料得知,编译Ethereal并非易事呀,因为Ethereal依赖很多开源包以及一些其他工具(如Cygwin等)。虽然Ethereal提供的自动化构建脚本会自动下载依赖包,但是大多时候都会下载失败,我在公司的网络和家里的网络都尝试过,无一成功,无奈之中只好手工下载。依赖的开源工具包在Readme.win32中有列出。

(一)首先我们需要一个编译器,一般在Windows上编译Ethereal用的都是VC6.0的编译器,切记在装完VC6.0后运行一下vcvars32.bat,设置一下环境变量,一般VC的安装向导程序在最后一步都会提示你是否设置环境变量的,你同意即可。

(二)其次,编译Ethereal需要Cygwin这个工具,Cygwin呢,我在机器上早已经安装过了,我一直用它在Windows下写一些Unix下的小测试程序的。不过我当时安装的时候没有把所有的包都选择上,导致我还得重新运行Cygwin的Setup.exe程序。那么如何检查你的Cygwin中缺少哪些软件包呢,可以按照如下步骤来检查:
1. 将cygwin的bin目录作为环境变量加入到系统环境变量path中;
2. 在Windows命令提示符窗口下进入到Ethereal的源码包目录下,找到config.nmake文件,修改ETHEREAL_LIBS=C:\ethereal-win32-libs
   CYGWIN_PATH=c:\cygwin\bin;
3. 在Windows命令提示符窗口下运行:nmake -f Makefile.nmake verify_tools
如果有工具包没有装全,我们会从该命令的执行结果中看到的,比如我在运行该命令之后的输出结果为:
Microsoft (R) Program Maintenance Utility   Version 6.00.8168.0
Copyright (C) Microsoft Corp 1988-1998. All rights reserved.

Checking for required applications:
        cl: /cygdrive/d/Program Files/Microsoft Visual Studio/VC98/bin/cl
        link: /cygdrive/d/Program Files/Microsoft Visual Studio/VC98/bin/link
        nmake: /cygdrive/d/Program Files/Microsoft Visual Studio/VC98/bin/nmake

        bash: /usr/bin/bash
        bison: /usr/bin/bison

ERROR: Can’t find flex. This is probably an optional cygwin package not yet inst
alled. Try to install it using cygwin’s setup.exe!

NMAKE : fatal error U1077: ‘bash’ : return code ’0×1′
Stop.

可以看出flex这个工具包没有安装,还好找到一个很好的cygwin各种包的下载站点xmission,速度很快,缺少什么就上去下载,然后到cygwin的根目录’/'下,
bzip2 -d xx.tar.bz2
tar xvf xx.tar即可。
反复执行上面步骤直到运行verify_tools顺利通过为止。

下面是verify_tools运行通过的输出结果:
D:\Ethereal\ethereal-0.99.0>nmake -f Makefile.nmake verify_tools

Microsoft (R) Program Maintenance Utility   Version 6.00.8168.0
Copyright (C) Microsoft Corp 1988-1998. All rights reserved.

Checking for required applications:
        cl: /cygdrive/d/Program Files/Microsoft Visual Studio/VC98/bin/cl
        link: /cygdrive/d/Program Files/Microsoft Visual Studio/VC98/bin/link
        nmake: /cygdrive/d/Program Files/Microsoft Visual Studio/VC98/bin/nmake

        bash: /usr/bin/bash
        bison: /usr/bin/bison
        flex: /usr/bin/flex
        env: /usr/bin/env
        grep: /usr/bin/grep
        /usr/bin/find: /usr/bin/find
        perl: /usr/bin/perl
        env: /usr/bin/env
        python: /usr/bin/python
        sed: /usr/bin/sed
        unzip: /usr/bin/unzip
        wget: /usr/bin/wget

这里有一个小插曲,verify_tools命令使用的应该是cygwin中的bash shell,但是我起初运行verify_tools时始终提示我’which’包找不到,我检查了cygwin,明明’which’包已经安装了,我疑惑的查看了系统环境变量path,终于发现了蛛丝马迹,原来我以前安装过’UnxUtils‘软件包,运行verify_tools时用的是该包里的bash shell。把UnxUtil从path中删除,问题解决。

(三)我们要找全编译Ethereal所依赖的包,Readme.win32中也列出了依赖包的列表,以及这些包解压后应该释放到的位置:
必选的:
Package                                Location
    ——-                               —————-
    glib-2.4.7.zip                        C:\ethereal-win32-libs\glib
    glib-dev-2.4.7.zip                    C:\ethereal-win32-libs\glib
    gtk+-1.3.0-20030717.zip               C:\ethereal-win32-libs\gtk+
    gtk+-dev-1.3.0-20030115.zip           C:\ethereal-win32-libs\gtk+
    libiconv-1.9.1.bin.woe32.zip          C:\ethereal-win32-libs\libiconv-1.9.1.bin.woe32
    gettext-runtime-0.13.1.zip            C:\ethereal-win32-libs\gettext-runtime-0.13.1
    net-snmp-5.2.1.2.zip                  C:\ethereal-win32-libs
    wpdpack_3_0.zip                       C:\ethereal-win32-libs

可选的:
Package                                Location
    ——-                               —————-
    adns-1.0-win32-04.zip                 C:\ethereal-win32-libs
    pcre-4.4.zip                          C:\ethereal-win32-libs
    zlib123-dll.zip                       C:\ethereal-win32-libs\zlib123-dll

尽量按照Package的版本下载,否则除了问题很难搞定,这里面除了net-snmp我没有找到5.2.1.2版本,我用了5.2.3替代之外,其余的都可以找到,这里有个站点http://mirror.sg.depaul.edu/pub/security/ethereal/win32/development/,几乎可以下载到上面所有的软件。net-snmp我下载的是源码包,需要先编译一下,记住编译Release版本即可。

(四)最后一步执行:nmake -f Makefile.nmake all
编译过程中的几个问题:
1. 编译过程中经常会中断,很多是因为’can’t open the file ‘uni
std.h”这个头文件,如果出现这样的问题,可以修改出错源文件的代码,将#include <unistd.h>修改为
#ifdef HAVE_UNISTD_H
#include<unistd.h>
#endif
即可。

2. 另外在编译过程中还发现需要lua5.1这个包。
3. 如果你下载的是gtk 1.x的包,你就是用gtk+这个目录,并且需要在config.nmake中注释掉GTK2_DIR=$(ETHEREAL_LIBS)\gtk2这项,我在编译中如果不注释掉该项,始终编译不过去。

编译过程很耗时,也许是我的本本CPU主频低的缘故,这可是考验耐性的活儿呀^_^。

挖掘一下C语言中的多维数组

好久没有看技术类的书籍了,今晚恰看到以前不知什么时候下到的一本oreilly的叫’mastering algorithms with c’的书,从书名可以看出这是一本讲算法的书,不过由于是选用了C语言作为讲解语言,所以难免不说说C语言。其中看到一节讲指针和数组,恰好碰到书中说: a[i][j] <=> *(*(a+i) + j),这个等价式看起来显而易见,但是还是有些东西值得挖掘一下的。

我们都知道C语言定义的多维数组是’行主序’的,这意味着越靠右边的下标变换越快。a[i][j]形象的可以看成一个i行j列的矩阵,但是实际在内存中存储时,a[i][j]肯定不是矩阵存储,因为存储器可是线性下来的,至于a[i][j]各元素的存储位置我们可以通过测试获得,结果也验证了’行主序’的规则。

以a[2][3]为例,

#include <stdio.h>

int main() {
 int a[2][3] = {{1,2,3}, {4,5,6}};
 int i;
 int j;
 int k;
 int *p;

 for (i = 0; i < 2; i++) {
  for (j = 0; j < 3; j++) {
   printf("a[%d][%d] = %d; addr = [0x%X]\n", i, j, a[i][j], &a[i][j]);
  }

 }

 return 0;
}

输出结果:

a[0][0] = 1; addr = [0x23FE94]
a[0][1] = 2; addr = [0x23FE98]
a[0][2] = 3; addr = [0x23FE9C]
a[1][0] = 4; addr = [0x23FEA0]
a[1][1] = 5; addr = [0x23FEA4]
a[1][2] = 6; addr = [0x23FEA8]

从结果addr的规律看得出: 先排行元素,再排列元素。也就是说第一行排完,再来排第二行。

我们再来分析一下上面提到的那个等价式:a[i][j] <=> *(*(a+i) + j),其实这里不一定要用常理分析,我们通过实验能得出一些结论:

#include <stdio.h>

int main() {
 int a[2][3] = {{1,2,3}, {4,5,6}};
 int i;
 int j;
 int k;
 int *p;

 for (i = 0; i < 2; i++) {
  for (j = 0; j < 3; j++) {
   printf("a[%d][%d] = %d; addr = [0x%X]\n", i, j, a[i][j], &a[i][j]);
  }

 }

 p = a;
 
 for (k =0 ; k < 6; k++) {
  printf("p[%d] = %d\n", k, p[k]);
 }

 printf("a+1 = 0x%X\n", a+1);
 printf("*(a+1) = 0x%X\n", *(a+1));
 printf("*(*(a+1)+2) = %d\n", *(*(a+1)+2));
 printf("*(a+1)+2 = 0x%X\n", *(a+1)+2);
 return 0;

}

输出结果:

a[0][0] = 1; addr = [0x23FE94]
a[0][1] = 2; addr = [0x23FE98]
a[0][2] = 3; addr = [0x23FE9C]
a[1][0] = 4; addr = [0x23FEA0]
a[1][1] = 5; addr = [0x23FEA4]
a[1][2] = 6; addr = [0x23FEA8]
p[0] = 1
p[1] = 2
p[2] = 3
p[3] = 4
p[4] = 5
p[5] = 6
a+1 = 0x23FEA0
*(a+1) = 0x23FEA0
*(*(a+1)+2) = 6
*(a+1)+2 = 0x23FEA8

这里关键的就是a+1 = 0x23FEA0以及*(a+1) = 0x23FEA0,奇怪了吧,加不加’*'号结果一致;实际上 *(*(a+i) + j)中的a + i是为了取第i行的首地址,按照常理用a+i即可了。但是由于是多维数组,取数组中某一元素的值,不仅要行还要列,那这么写: *((a +i) +j )能行吗?这就是当时C的设计者要考虑到问题了。显然*((a +i) +j )这么做欠妥,依然以上面的例子为例,我们再输出些信息瞧瞧:

printf("*((a+1)+2) = 0x%X\n", *((a+1) +2));

输出结果:
*((a+1)+2) = 0x23FEB8

这显然不是a[1][2]的值,0x23FEB8是什么呢,实际上是第四行的行首地址,当然在我们的程序中只有两行在合法的范围之内。好了,问题既然出现了,当时的C设计者就考虑要区别于这种情况,遂就如是做了: *(*(a+1)+2);这样结果正确了,*(*(a+1)+2) = 6。至于当时C设计者的真实考虑我无从而知,权当逗乐打趣吧。

如发现本站页面被黑,比如:挂载广告、挖矿等恶意代码,请朋友们及时联系我。十分感谢! Go语言第一课 Go语言进阶课 Go语言精进之路1 Go语言精进之路2 Go语言第一课 Go语言编程指南
商务合作请联系bigwhite.cn AT aliyun.com

欢迎使用邮件订阅我的博客

输入邮箱订阅本站,只要有新文章发布,就会第一时间发送邮件通知你哦!

这里是 Tony Bai的个人Blog,欢迎访问、订阅和留言! 订阅Feed请点击上面图片

如果您觉得这里的文章对您有帮助,请扫描上方二维码进行捐赠 ,加油后的Tony Bai将会为您呈现更多精彩的文章,谢谢!

如果您希望通过微信捐赠,请用微信客户端扫描下方赞赏码:

如果您希望通过比特币或以太币捐赠,可以扫描下方二维码:

比特币:

以太币:

如果您喜欢通过微信浏览本站内容,可以扫描下方二维码,订阅本站官方微信订阅号“iamtonybai”;点击二维码,可直达本人官方微博主页^_^:
本站Powered by Digital Ocean VPS。
选择Digital Ocean VPS主机,即可获得10美元现金充值,可 免费使用两个月哟! 著名主机提供商Linode 10$优惠码:linode10,在 这里注册即可免费获 得。阿里云推荐码: 1WFZ0V立享9折!


View Tony Bai's profile on LinkedIn
DigitalOcean Referral Badge

文章

评论

  • 正在加载...

分类

标签

归档



View My Stats