做《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程序,惭愧,惭愧。。。。