IP报文的截取与分析

来源:互联网 发布:linux continue 编辑:程序博客网 时间:2024/06/08 03:09

做《IP报文的截取与分析》实验,弄了一个上午还是一头雾水,回到宿舍网上查阅,windows7加上ubantu,才勉强搞懂...

------------------------------------------------这是程序代码----------------------------------------------------------------

#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/ip.h>
#include <netinet/if_ether.h>
#include <net/if.h>

int main()
{
 /*套接口捕获链路帧*/
 int i=0;
 int fd;
 /*利用类型为SOCK_PACKET的套接口来捕获链路帧*/
 fd=socket(AF_INET,SOCK_PACKET,htons(0x0003));//函数返回值的意义?
   //AF_INET=ARPA Internet protocols,即TCP/IP协议族
 /*设置网卡的工作方式*/
 
 struct ifreq ifr; // in 'net/if.h'
 char *dev="eth0";
 strcpy(ifr.ifr_name,dev);   // interface name  
 i=ioctl(fd,SIOCGIFFLAGS,&ifr);//SIOCGIFFLAGS(0x8913)表示取出工作方式
  //返回0:成功    -1:出错

 if(i<0)
 {
 close(fd);
 perror("can't get flags/n");
 //exit(0);
 }
 ifr.ifr_flags|=IFF_PROMISC; //在标志中加入“混杂“方式
 i=ioctl(fd,SIOCSIFFLAGS,&ifr); //获取所有接口信息
 if(i<0)
 {
 perror("can't set promiscuous/n");
 //exit(0);
 }
 /*从套接口读取帧并分析报头*/
  char ep[ETH_FRAME_LEN];
 
  struct ethhdr *eh;
  struct iphdr *ip;
  int fl;
 eh = (struct ethhdr *) ep;//eh指向帧头
 ip = (struct iphdr *) ( (unsigned long) ep + ETH_HLEN );//ETH_HLEN帧头长

  fl = read (fd,(struct etherpacket*) ep,sizeof(ep));//捕获的数据帧长


printf("数据协议类型代码:%x/n",eh->h_proto);
printf("服务类型: %x/n",ip->tos);
printf("总长度:%x/n",ip->tot_len);
printf("总标识域:%x/n",ip->id);
printf("分片控制和分片偏移量:%x/n",ip->frag_off);
printf("生命周期:%x/n",ip->ttl); 
printf("协议:%x/n",ip->protocol);
printf("校验和:%x/n",ip->check);
printf("源IP地址:%x/n",ip->saddr);
printf("目标地址:%x/n",ip->daddr);

printf("/n");
}
 -----------------------------------------------------------------------------------------------------------

 

 

经过一个下午的挣扎,明白了一下几点:

 

1.fd=socket(AF_INET,SOCK_PACKET,htons(0x0003));该语句用于获得一个socket,成功则返回socket,    失败则返回一个“失败的socket”,而socket为int型,因此成功则为0,失败则返回-1,

                      以下文字对socket稍加说明:

          int socket (int family, int type, int protocol);

          /*
          * TCP客户端与TCP服务器建立连接,调用此函数会触发TCP的三次握手,并建立连接。调用此函数前,不必调用bind函数,内核会           决定源IP并选择一个临时端口作为源端口。
         * 参数:
         sockfd - 套接口描述字
         servaddr - 包含要连接的服务器的IP和端口号的套接口地址结构
         addrlen - servaddr套接口地址结构体的大小
         * 返回:成功 - 0,失败 - -1
         */

 

2. i=ioctl(fd,SIOCGIFFLAGS,&ifr);//SIOCGIFFLAGS(0x8913)表示取出工作方式
         一、 什么是ioctl。
         ioctl是设备驱动程序中对设备的I/O通道进行管理的函数。所谓对I/O通道进行管理,就
        是对设备的一些特性进行控制,例如串口的传输波特率、马达的转速等等。它的调用个数
        如下:
        int ioctl(int fd, ind cmd, …);
        其中fd就是用户程序打开设备时使用open函数返回的文件标示符,cmd就是用户程序对设
         备的控制命令,至于后面的省略号,那是一些补充参数,一般最多一个,有或没有是和
        cmd的意义相关的。
        ioctl函数是文件结构中的一个属性分量,就是说如果你的驱动程序提供了对ioctl的支
        持,用户就可以在用户程序中使用ioctl函数控制设备的I/O通道。
        二、 ioctl的必要性
        如果不用ioctl的话,也可以实现对设备I/O通道的控制,但那就是蛮拧了。例如,我们可
        以在驱动程序中实现write的时候检查一下是否有特殊约定的数据流通过,如果有的话,
        那么后面就跟着控制命令(一般在socket编程中常常这样做)。但是如果这样做的话,会
        导致代码分工不明,程序结构混乱,程序员自己也会头昏眼花的。
        所以,我们就使用ioctl来实现控制的功能。要记住,用户程序所作的只是通过命令码告
        诉驱动程序它想做什么,至于怎么解释这些命令和怎么实现这些命令,这都是驱动程序要
        做的事情。

         混杂模式是网络监听程序要用到的工作模式,其实就是改变网卡设置,把网卡原来只接收属于自己的数据包的模式,改为不管什么数据 包都接收的模式

 

 

---------------------------------------------------------------------------------------------------------------

linux如此强大,强大的让人觉得它很迷人,唉,可惜本人linux这么水,前几天才懂得用gcc编译和运行c程序,惭愧,惭愧。。。。

原创粉丝点击