免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1722 | 回复: 0
打印 上一主题 下一主题

[OpenBSD] 系统工具ifconfig源代码阅读路线图1(OpenBSD5.3) [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-10-11 19:54 |只看该作者 |倒序浏览
/* 作者 老董  dz0212@foxmail.com  */

"学习编写伟大代码的方法是阅读代码,阅读大量的代码;高品质的代码...如果不这样,我们就会不断地重复别人已经完成的工作,重复过去已经发生过的成功和错误"

                                        --Diomidis Spinellis 《CODE Reading》  
0x01引言
    网上那些大忽悠,让初学者去阅读*nix内核代码,庞大的内核代码,初学者看起来困难重重,感觉没一个入口,与其在旁边瞎转悠,最后放弃,不如迂回前进。革命胜利是从农村包围城市,直到解放全中国。unix系统提供了大量的系统工具,这些系统工具,代码量适中,从这入手学习unix代码是最好的方法。本人喜欢OpenBSD,端庄朴素手感好,还是从OpenBSD提供的ifconfig代码来分析。
    先粗后细,读线索读关键函数
0x02 ifconfig代码组织和编译
有四个文件,
Makefile
brconfig.h
brconfig.c
ifconfig.c
先看Makefile
$ more Makefile
#       $OpenBSD: Makefile,v 1.13 2012/09/07 00:33:24 deraadt Exp $
PROG=   ifconfig
SRCS=   ifconfig.c brconfig.c
MAN=    ifconfig.8
LDADD=  -lutil
DPADD=  ${LIBUTIL}
CPPFLAGS+=-DINET6
.include <bsd.prog.mk>
这个文件看起来太费劲,又包含了bsd.prog.mk这个文件,它的位置在/usr/share/mk,看下去,你会发现又包含了好多其它的文件。与其雾里看花,不如直奔主题,看它具体做了什么;

“检查大型编译过程的各个步骤时,可以使用make程序的-n开关进行预演”
--Diomidis Spinellis 《CODE Reading》
$ make -n
cc -O2 -pipe    -DINET6 -c ifconfig.c
cc -O2 -pipe    -DINET6 -c brconfig.c
cc -O2  -o ifconfig ifconfig.o brconfig.o -lutil
呵呵 编译链接过程是不是很清楚了。“合理饮食,适当运动”,电视里传来了
养身节目专家的声音,太有道理了,如果人都没了,看这代码有毛用?
好了自己写一个Makefile,呵呵,看清楚不是Makelove
$ vi Makefile
all:
        cc -g -pipe    -DINET6 -c ifconfig.c
        cc -g -pipe    -DINET6 -c brconfig.c
        cc -g  -o ifconfig ifconfig.o brconfig.o -lutil
为什么要用-g参数?过一会我们要用gdb调试

0x03 ifconfig.c代码分析

"第一次分析一个程序时,main是一个好的起点。"   --Diomidis Spinellis《CODE Reading》
分析源代码从不用任何参数的情况开始,从最简单开始,也符合unix的哲学
分析方法:
(1)从main函数开始,根据命令在屏幕上的显示信息,分析出所有相关的输出函数;
(2)分析这些输出函数周边代码,搞清楚输出信息是如何获得的;
完成以上两步,代码的大框架就完全搞清楚了。
-> main()
前边代码看不懂不要紧一直往下看,直到下边这行注释
/* If no args at all, print all interfaces.  */如果没有参数,显示所有网卡接口
        if (argc < 2) {
                aflag = 1;
                printif(NULL, 0);
                exit(0);
        }
很清楚应从printif()函数入手。
-> printif()
“有时想了解程序在某一方面的功能,运行它可能比阅读源代码更为恰当。”
--Diomidis Spinellis 《CODE Reading》

里边的代码翻遍了,看不出明显的输出,呵呵,gdb该出面了
$ make all
$ gdb ./ifconfig
(gdb) start
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Breakpoint 2 at 0x1c0015e4: file ifconfig.c, line 568.
Starting program: /home/walkman/ifconfig/ifconfig
main () at ifconfig.c:568
568     {
(gdb) next
main () at ifconfig.c:569
......
(gdb)
581             printif(NULL,0);
(gdb) step    此处要使用它,进入printif函数
printif (ifname=0x0, ifaliases=0) at ifconfig.c:929
921             char *oname = NULL;
(gdb) next
923             int count = 0, noinet = 1;
.......
979     status(1, (struct sockaddr_dl *)ifa->ifa_addr,  /*执行到这个函数时,显示接口信息*/
(gdb) next
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 33196
        priority: 0
        groups: lo
......
(gdb) next
999                        (*p->af_status)(0);  /*显示网卡与ip相关的信息*/
(gdb)
        inet 127.0.0.1 netmask 0xff000000
现在该总结出,路线了 main()->printif()->status()和(*p->af_status)(0)

0x04 分析printif()
先粗略浏览此函数,分析输出的信息是如何获得的,判断出关键的语句。
......
    939         if (getifaddrs(&ifap) != 0)  /*1 需要重点分析的语句*/
    940                 err(1, "getifaddrs");
    941
    942         namep = NULL;
    943         for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
    944                 if (oname) {
    945                         if (nlen && isdigit(oname[nlen - 1])) {
    946                                 /* must have exact match */
    947                                 if (strcmp(oname, ifa->ifa_name) != 0)
    948                                         continue;
    949                         } else {
    950                                 /* partial match OK if it ends w/ digit */
    951                                 if (strncmp(oname, ifa->ifa_name, nlen) != 0 ||
    952                                     !isdigit(ifa->ifa_name[nlen]))
    953                                         continue;
    954                         }
    955                 }
......
    971                 strlcpy(name, ifa->ifa_name, sizeof(name));
    972                 strlcpy(ifrp->ifr_name, ifa->ifa_name, sizeof(ifrp->ifr_name));
    973
    974                 if (ifa->ifa_addr->sa_family == AF_LINK) {
    975                         namep = ifa->ifa_name;
    976                         if (getinfo(ifrp, 0) < 0)
    977                                 continue;
    978                         ifdata = ifa->ifa_data;
    979                         status(1, (struct sockaddr_dl *)ifa->ifa_addr,
    980                             ifdata->ifi_link_state);/*需要重点分析此前后的语句段*/
    981                         count++;
    982                         noinet = 1;
    983                         continue;
    984                 }
    985
    986                 if (!namep || !strcmp(namep, ifa->ifa_name)) {
    987                         const struct afswtch *p;
    988
    989                         if (ifa->ifa_addr->sa_family == AF_INET &&
    990                             ifaliases == 0 && noinet == 0)
    991                                 continue;
    992                         if ((p = afp) != NULL) {
    993                                 if (ifa->ifa_addr->sa_family == p->af_af)
    994                                         (*p->af_status)(1);
    995                         } else {
    996                                 for (p = afs; p->af_name; p++) {
    997                                         if (ifa->ifa_addr->sa_family ==
    998                                             p->af_af)
    999                                                 (*p->af_status)(0);/*需要重点分析此前后的语句段*/
   1000                                 }
   1001                         }
   1002                         count++;
   1003                         if (ifa->ifa_addr->sa_family == AF_INET)
   1004                                 noinet = 0;
   1005                         continue;
   1006                 }
   1007         }
上边程序段,943-1007是个循环体,其循环控制变量与939行对比,可知939行getifaddrs()函数获得输出信息,应重点分析。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP