ping源码分析

本文详细分析了ping命令的源码,从获取源码到编译,再到核心的主流程及选项处理。重点探讨了主函数如何创建套接字、设置信号处理函数,以及在main_loop()中如何控制发包时间间隔。通过对ping源码的学习,可以了解到Linux网络编程、信号使用、时间相关系统调用和ICMP报文处理等知识。
摘要由CSDN通过智能技术生成

第一回分析源码

 

程序流程一览图

 
 
 

感觉有点简单吧,ping的核心就是上面的图了,而其它都是对选项的处理,不仅仅是ping源码,其它开源代码一般都是一堆选项,如果一开始就被那些对分析程序核心没有帮助的选项所困扰,那么分析一个程序需要的时间和效率就可想而知。当然ping的很多选项都是值得分析的。

这个ping源码控制发包的时间间隔是通过main_loop()比较复杂的时间计算控制,因为它要控制诸如-l这样的选项,如果纯粹是控制时间,那么注册个SIGALRM信号处理函数,再加个1秒的定时器alarm(1)或者就直接sleep(1)就可以很轻松的实现。-w选项就是通过alarm完成的,SIGALRM信号处理函数是在main()->setup()中设置的,具体请看setup函数分析。

 

1,准备工作,获得ping源码并学会编译

会编译了看代码其实就是后续的活,网上找的方法,挺好用……

[root@xxx study_2]# type ping

ping is /bin/ping

[root@xxx study_2]# rpm -qf /bin/ping  

iputils-20020927-46.el5

 

从而得知ping属于iputils包,去下iputils源码包即可,其它linux 命令源码获取方法类似。

 

[root@xxx iputils]# make

Please, set correct KERNEL_INCLUDE

make: *** [check-kernel] 错误 1

 

反正是一堆错误,改了这个来了那个,看了INSTALL说是被定制过的linux头文件可能会不支持,反正只要能编出ping就行,改了下Makefile,把有关KERNEL_INCLUDE的都屏蔽了,编译成功。

 

2,源码分析

    只分析实现最简单的不带选项的ping程序。也花了一个星期的业余时间。

 

 112main(int argc, char **argv)

 113{

 114    struct hostent *hp;

 115    int ch, hold, packlen;

 116    int socket_errno;

 117    u_char *packet;

 118    char *target, hnamebuf[MAXHOSTNAMELEN];

 119    char rspace[3 + 4 * NROUTES + 1];  /* record route space */

 120#ifdef DO_IPSEC

 121    char *policy_string = NULL;

 122#endif

 123

 124    icmp_sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); //创建icmp套接字

 125    socket_errno = errno;

 126

 127    uid = getuid();//设置进程有效用户ID为实际用户uid,访问权限方面的知识。

 128    setuid(uid);

 129

 130    source.sin_family = AF_INET;

 131

 132    preload = 1;//这个参数默认为1,可由-l选项控制,一次发多个包而不管对方是否回应,其本质还是通过计算时间来实现,具体可看main_loop().没兴趣不用管。

 133    while ((ch = getopt(argc, argv, COMMON_OPTSTR "bRT:P:")) !=EOF) {

 134        switch(ch) {//getopt得好好学会。

 213        default:

 214            usage();

 215        }

 216    }

 217    argc -= optind;//可参考GETOPT(3) ,是个全局变量

 218    argv += optind;

 219

 

//这里对选项的处理,不管,option为0。

 220    printf("options :%d\n", options );

 221    if (argc == 0)

 222        usage();

 223    if (argc > 1) {

 224        if (options & F_RROUTE)

 225            usage();

 226        else if (options & F_TIMESTAMP) {

 227            if (ts_type != IPOPT_TS_PRESPEC)

 228                 usage();

 229            if (argc > 5)

 230                 usage();

 231        } else {

 232            if (argc > 10)

 233                 usage();

 234            options |= F_SOURCEROUTE;

 235         }

 236    }

 

//处理传给ping的参数

 237       while (argc > 0) {

//我只传一个目标IP,所以argc=1,这个循环只做一回,把IP地址给了target

 238        target = *argv;

 239        printf("target:%s\n", target);

 240

 241        bzero((char *)&whereto, sizeof(whereto));

 242        whereto.sin_family = AF_INET;

 243        if (inet_aton(target, &whereto.sin_addr) == 1) {//如果是IP地址

 244            hostname = target;

 245            if (argc == 1)

 246                 options |= F_NUMERIC;

 247        } else {//如果是其它域名

 248            hp = gethostbyname(target);

 249            if (!hp) {//如果解析域名不成功,返回

 250                 fprintf(stderr, "ping:unknown host %s\n", target);

 251                 exit(2);

 252            }

 253            memcpy(&whereto.sin_addr, hp->h_addr, 4);

 254             strncpy(hnamebuf, hp->h_name,sizeof(hnamebuf) - 1);

 255            hnamebuf[sizeof(hnamebuf) - 1] = 0;

 256            hostname = hnamebuf;

 257        }

 258        if (argc > 1)

 259            route[nroute++] =

  • 4
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值