Linux数据链路层的包解析

转载至 : https://www.cnblogs.com/KevinGeorge/p/7866735.html

一般而言,Linux系统截获数据包后,会通过协议栈,按照TCP/IP层次进行解析,那我们如何直接获得更为底层的数据报文呢,这里用到一个类型SOCK_PACKET类型。

int sockfd = socket(AF_INET,SOCK_PACKET,htons(0x0003));  

通过上面这个函数可以获得一个特殊的套接字,其中:

  • AF_INET: 表示因特网协议族
  • SOCK_PACKET: 表示数据包截取在物理层
  • 0x0003: 表示数据帧类型不确定

修改网络接口结构:

struct ifreq ifr;
strcpy(ifr.ifr_name,"eth0");
ioctl(sockfd,SIOCGIFFLAGS,&ifr);

设置混杂模式

ifr.ifr_flags| = IFR_PROMISC;
ioctl(sockfd,SIOCSIFFLAGS,&ifr);

注意:进行标志位设定时,遵循以下步骤:

  1. 取出原标识位;

  2. 与待设定标志位进行位或运算(“|”);

  3. 重新写入;

一个小小的抓包程序

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

using namespace std;

char ethernet_frame[ETH_FRAME_LEN];//定义一个数据帧的长度
struct iphdr *ipheader;//定义ip头部指针

int socketcreate()
{
    int sockfd = socket(AF_INET,SOCK_PACKET,htons(0x0003));    
    //构建了一个数据链路层的数据包;
    if(sockfd == -1)
    {
        cout<<"Socket init error!"<h_dest[i]);    
    }
    printf("%2x\n",fheader->h_dest[ETH_ALEN-1]);
    printf("SRC MAC: ");
    for(int i=0;ih_source[i]);    
    }
    printf("%2x\n",fheader->h_source[ETH_ALEN-1]);
    if(ntohs(fheader->h_proto) == 0x0800)
    {
        cout<<"Protocol: IP"<h_proto) == 0x0806)
    {
        cout<<"Protocol: RAP"<h_proto) == 0x8035)
    {
        cout<<"Protocol: RARP"<h_proto);
    return ret;
}

int getip(int protocol,int num)
{
        if(protocol != 0x0800)
        {
            cout<<"NO IP Packet!"<saddr;
        printf("SRC IP: %s",inet_ntoa(*p));
        cout<daddr;
        printf("DST IP: %s",inet_ntoa(*q));
        cout<protocol == 1)
        {
            cout<<"PROTOCOL: ICMP"<protocol == 6)
        {
            cout<<"PROTOCOL: TCP"<protocol == 17)
        {
            cout<<"PROTOCOL: UDP"<protocol;
}

int gettcp(int protocol)
{
    if(protocol != 6)
    {
        return -1;    
    }
    struct tcphdr* tcph;
    tcph = (struct tcphdr*)(ipheader+((ipheader->ihl)*4));
    printf("SRC PORT: %d",ntohs(tcph->source));
    cout<dest));
    cout<ihl)*4));
    printf("SRC PORT: %d",ntohs(udph->source));
    cout<dest));
    cout<

你可能感兴趣的:(Linux数据链路层的包解析)