简易版WireShark实现-相关网络知识(1)
2017-06-18 22:26
260 查看
在Linux下数据链路层的访问通常都是通过编写内核驱动程序来实现的,在应用层使用SOCK_PACKET类型的协议族可以实现部分功能。
其中,AF_INET表示因特网协议族,SOCK_PACKET表示截取数据帧的层次在物理层,网络协议栈对数据不做处理。ETH_P_ALL是Linux系统头文件if_ether.h中的一个宏定义,值为0x0003,表示截取的数据帧的类型不确定,并且处理所有包。如果只想处理IP层协议的数据包的话,可以将这个参数改成 ETH_P_IP。
使用SOCK_PACKET的时候,需要关注的方面主要如下:
协议族选择
获取原始包
定位IP包
定位TCP包
定位UDP包
定位应用层数据
以太网帧总长度最大为1518字节,最小为64字节。其中,目的MAC与源MAC地址均为6字节,协议类型为2字节,含有46~1500字节的数据,尾部为4个字节的CRC校验和。以太网的CRC校验和一般由硬件自动设置或者剥离,应用层不用考虑。
头文件【linux/if_ether.h】中与以太网帧相关的常量定义如下:
以太网头部结构的定义如下:
套接字文件描述符建立后,就可以从此描述符中读取数据,数据格式为上述的以太网数据,即以太网帧。在套接字建立以后,就可以从此套接字中循环读取捕获的链路层以太网帧。建立一个大小为1518的缓冲区,并将以太网头部指向此缓冲区,即可读取相关的数据,如下:
以太网帧中的协议类型是一个2字节的大小的变量,读取它的值可以判断当前帧是属于什么类型的数据:0x0800是IP协议的,0x0806是ARP协议,0x8035是RARP协议,当然,还有很多其他类型的协议,这里就不一一列举了。
SOCK_PACKET类型
建立套接字的时候选择SOCK_PACKET类型,内核将不对网络数据进行处理而直接交给用户,数据直接从网卡的协议栈交给用户。建立一个SOCK_PACKET类型的套接字使用如下方式:int sock = socket(AF_INET, SOCK_PACKET, htons(ETH_P_ALL);
其中,AF_INET表示因特网协议族,SOCK_PACKET表示截取数据帧的层次在物理层,网络协议栈对数据不做处理。ETH_P_ALL是Linux系统头文件if_ether.h中的一个宏定义,值为0x0003,表示截取的数据帧的类型不确定,并且处理所有包。如果只想处理IP层协议的数据包的话,可以将这个参数改成 ETH_P_IP。
使用SOCK_PACKET的时候,需要关注的方面主要如下:
协议族选择
获取原始包
定位IP包
定位TCP包
定位UDP包
定位应用层数据
从套接字中读取以太网帧
设置完套接字后,接下来就需要从套接字中读取以太网帧。在此之前,先来了解一下以太网帧的数据结构,具体如下:以太网帧总长度最大为1518字节,最小为64字节。其中,目的MAC与源MAC地址均为6字节,协议类型为2字节,含有46~1500字节的数据,尾部为4个字节的CRC校验和。以太网的CRC校验和一般由硬件自动设置或者剥离,应用层不用考虑。
头文件【linux/if_ether.h】中与以太网帧相关的常量定义如下:
/* * IEEE 802.3 Ethernet magic constants. The frame sizes omit the preamble * and FCS/CRC (frame check sequence). */ #define ETH_ALEN 6 /* Octets in one ethernet addr */ #define ETH_HLEN 14 /* Total octets in header. */ #define ETH_ZLEN 60 /* Min. octets in frame sans FCS */ #define ETH_DATA_LEN 1500 /* Max. octets in payload */ #define ETH_FRAME_LEN 1514 /* Max. octets in frame sans FCS */ #define ETH_FCS_LEN 4 /* Octets in the FCS */
以太网头部结构的定义如下:
/* * This is an Ethernet frame header. */ struct ethhdr { unsigned char h_dest[ETH_ALEN]; /* destination eth addr */ unsigned char h_source[ETH_ALEN]; /* source ether addr */ __be16 h_proto; /* packet type ID field */ } __attribute__((packed));
套接字文件描述符建立后,就可以从此描述符中读取数据,数据格式为上述的以太网数据,即以太网帧。在套接字建立以后,就可以从此套接字中循环读取捕获的链路层以太网帧。建立一个大小为1518的缓冲区,并将以太网头部指向此缓冲区,即可读取相关的数据,如下:
unsigned char buffer[1518]; //临时存储捕获的数据包 struct ethhdr* p_ethhdr; int n; unsigned short proto_type_ethhdr; unsigned char *ethhead; qstring src_mac_str = "", dst_mac_str = "" n = recvfrom(sock, buffer, sizeof(buffer), 0, null, null); ethhead = buffer; p_ethhdr = (ethhdr *)(buffer); proto_type_ethhdr = htons(ethhdr->h_proto); /*目的mac地址*/ dst_mac_str.sprintf("%02x:%02x:%02x:%02x:%02x:%02x", ethhead[0], ethhead[1], ethhead[2], ethhead[3], ethhead[4], ethhead[5]); /*源mac地址*/ src_mac_str.sprintf("%02x:%02x:%02x:%02x:%02x:%02x", ethhead[6], ethhead[7], ethhead[8], ethhead[9], ethhead[10], ethhead[11]); qdebug() << dst_mac_str; //打印 qdebug() << src_mac_str; switch (proto_type_ethhdr) { case(0x0800): //ip协议 break; case(0x0806): //arp协议 break; case(0x8035): //rarp协议 break; }
以太网帧中的协议类型是一个2字节的大小的变量,读取它的值可以判断当前帧是属于什么类型的数据:0x0800是IP协议的,0x0806是ARP协议,0x8035是RARP协议,当然,还有很多其他类型的协议,这里就不一一列举了。
相关文章推荐
- 简易版WireShark实现-相关网络知识(2)
- 简易版WireShark实现-相关网络知识(3)
- 分布式网络爬虫关键技术分析与实现一网络爬虫相关知识介绍
- 网络相关知识
- 分布式编程->XML Webservice实现原理及相关知识
- XML Webservice实现原理及相关知识
- XML Webservice实现原理及相关知识
- 网络基础知识讲座之六:实现子网(包括IPv6)
- Java 访问数据库 --java与DataBase相关知识总结(四) java数据库连接池实现
- 网络备份及域的相关知识
- 分布式编程->XML Webservice实现原理及相关知识
- [导入]分布式编程->XML Webservice实现原理及相关知识
- Web User Control 相关知识汇总(网络联接)
- 详细讲述XML Webservice实现原理及相关知识
- 网络备份及域的相关知识
- 分布式编程->XML Webservice实现原理及相关知识
- 调用API的SDK相关知识:实现回调函数.
- TCP/IP协议栈的实现相关网络资料
- 网络攻击相关知识(一)
- XML Webservice实现原理及相关知识