仅以此文作为学习笔记,初学者,如有错误欢迎批评指正,但求轻喷。
一般而言,Linux系统截获数据包后,会通过协议栈,按照TCP/IP层次进行解析,那我们如何直接获得更为底层的数据报文呢,这里用到一个类型SOCK_PACKET类型。

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

通过上面这个函数可以获得一个特殊的套接字,其中:
AF_INET:                              表示因特网协议族
SOCK_PACKET:                   表示数据包截取在物理层
0x0003:                                 表示数据帧类型不确定
修改网络接口结构:

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

设置混杂模式

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

注意:

进行标志位设定时,遵循以下步骤:
(1)取出原标识位;
(2)与待设定标志位进行位或运算(“|”);
(3)重新写入;
一个小小的抓包程序

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<iostream>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<sys/ioctl.h>
#include<net/if.h>
#include<arpa/inet.h>
#include<netinet/if_ether.h>
#include<netinet/in.h>
#include<netinet/ip.h>
#include<netinet/tcp.h>
#include<netinet/udp.h>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!"<<endl;    return -1;}/*下面设置接口结构*/char *ifname = "eth0";struct ifreq ifr;strcpy(ifr.ifr_name,ifname);int result = ioctl(sockfd,SIOCGIFFLAGS,&ifr);if(result == -1){cout<<"Can't get flags!"<<endl;close(sockfd);return -2;}ifr.ifr_flags|= IFF_PROMISC;/*一般而言,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)重新写入;*/result = ioctl(sockfd,SIOCSIFFLAGS,&ifr);if(result == -1){cout<<"Can't set flags!"<<endl;close(sockfd);return -3;}return sockfd;
}
int getframe(int sockfd,int num)
{struct ethhdr* fheader;fheader = (struct ethhdr*)ethernet_frame;memset(ethernet_frame,0,ETH_FRAME_LEN);int size = read(sockfd,ethernet_frame,ETH_FRAME_LEN);if(size <= 0){cout<<"No packet or packet error!"<<endl;    return -1;}cout<<"************************Packet"<<num<<"received from eth0 START!************************"<<endl;printf("DST MAC: ");for(int i=0;i<ETH_ALEN-1;i++){printf("%2x-",fheader->h_dest[i]);    }printf("%2x\n",fheader->h_dest[ETH_ALEN-1]);printf("SRC MAC: ");for(int i=0;i<ETH_ALEN-1;i++){printf("%2x-",fheader->h_source[i]);    }printf("%2x\n",fheader->h_source[ETH_ALEN-1]);if(ntohs(fheader->h_proto) == 0x0800){cout<<"Protocol: IP"<<endl;    }if(ntohs(fheader->h_proto) == 0x0806){cout<<"Protocol: RAP"<<endl;    }if(ntohs(fheader->h_proto) == 0x8035){cout<<"Protocol: RARP"<<endl;    }int ret = ntohs(fheader->h_proto);return ret;
}int getip(int protocol,int num)
{if(protocol != 0x0800){cout<<"NO IP Packet!"<<endl;cout<<"************************Packet"<<num<<"received from eth0 END!**************************"<<endl;return 0;    }ipheader = (struct iphdr*)(ethernet_frame+ETH_HLEN);printf("Version: 4");cout<<endl;in_addr *p,*q;p = (struct in_addr*)&ipheader->saddr;printf("SRC IP: %s",inet_ntoa(*p));cout<<endl;q = (struct in_addr*)&ipheader->daddr;printf("DST IP: %s",inet_ntoa(*q));cout<<endl;if(ipheader->protocol == 1){cout<<"PROTOCOL: ICMP"<<endl;    }if(ipheader->protocol == 6){cout<<"PROTOCOL: TCP"<<endl;    }if(ipheader->protocol == 17){cout<<"PROTOCOL: UDP"<<endl;    }return ipheader->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<<endl;printf("DST PORT: %d",ntohs(tcph->dest));cout<<endl;return 0;
}int getudp(int protocol)
{if(protocol != 17){return -1;    }struct udphdr* udph;udph = (struct udphdr*)(ipheader+((ipheader->ihl)*4));printf("SRC PORT: %d",ntohs(udph->source));cout<<endl;printf("DST PORT: %d",ntohs(udph->dest));cout<<endl;return 0;
}int main(int argc,char *argv[])
{        if(argc < 2){cout<<"Please input the nummber of packet that you want to catch!"<<endl;return 0;}int num = (int)argv[1][0];int sock = socketcreate();for(int i=1;i<num;i++){int ip_protocol = getframe(sock,i);int trasnport_protocol = getip(ip_protocol,i);gettcp(trasnport_protocol);getudp(trasnport_protocol);cout<<"************************Packet"<<num<<"received from eth0 END!**************************"<<endl;cout<<endl;cout<<endl;cout<<endl;cout<<endl;}return 0;
}

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

Linux数据链路层的包解析相关推荐

  1. Linux TCP SYN包不返回问题解析

    http://www.saview.net/archives/93 Linux TCP SYN包不返回问题解析 现象描述及排查过程: 最早是在网站图片cache集群中出现监控系统偶尔报告vip连接超时 ...

  2. Linux tcpdump抓包

    简介 用简单的话来定义tcpdump,就是:dump the traffic on a network,根据使用者的定义对网络上的数据包进行截获的包分析工具. tcpdump可以将网络中传送的数据包的 ...

  3. Linux下抓包工具tcpdump详解

    简介 用简单的话来定义tcpdump,就是:dump the traffic on a network,根据使用者的定义对网络上的数据包进行截获的包分析工具. tcpdump可以将网络中传送的数据包的 ...

  4. linux 后台运行jar包命令,Linux 运行jar包命令(Cent OS 7后台运行jar包)

    Linux 运行jar包命令如下: 方式一 特点:当前ssh窗口被锁定,可按CTRL + C打断程序运行,或直接关闭窗口,程序退出 那如何让窗口不锁定? 方式二 java -jar shareniu. ...

  5. Linux日常运维管理技巧(一)监控系统状态、监控网卡流量、监控IO性能、查看系统进程、查看网络状态、Linux下抓包tcpdump、Linux网络相关、DNS配置

    目录 监控系统状态 监控网卡流量 监控IO性能 查看系统进程 查看网络状态 Linux下抓包 Linux网络相关 监控系统状态 w/uptime查看系统负载 [root@zyshanlinux-01 ...

  6. 搬砖:网络数据包解析

    Itsad 网络数据包解析 TCP/IP协议数据包,一般由应用层.传输层.网络层.数据链路层封装而成. 四层协议各自的作用: 数据链路层实现了网卡接口的驱动程序. 网络层实现了数据包的选路和转发. 传 ...

  7. 七周二次课(1月23日) 10.6 监控io性能 10.7 free命令 10.8 ps命令 10.9 查看网络状态 10.10 linux下抓包...

    七周二次课(1月23日) 10.6 监控io性能 10.7 free命令 10.8 ps命令 10.9 查看网络状态 10.10 linux下抓包 ========================== ...

  8. centost查看网络信息_监控io性能、free命令、ps命令、查看网络状态、Linux下抓包...

    一.监控io性能 iostat命令 iostat命令被用于监视系统输入输出设备和cpu的使用情况.它的特点是汇报磁盘活动统计情况,同时也会汇报出cpu使用情况.通vmstat一样,iostat也有一个 ...

  9. 关于Linux 网络抓包的一些笔记整理

    写在前面 遇到一个 ping 单通 的情况,需要抓包分析下,所以整理这部分笔记 博文内容涉及: HTTP/TCP 抓包分析 Demo ICMP 抓包分析 Demo Nginx 抓包分析用户名密码 De ...

  10. 【linux tcp抓包之三次握手】

    [linux tcp抓包之三次握手] 写在前面 三次握手 tcpdump 参数说明 返回值说明 IP 127.0.0.1.42004 > 127.0.0.1.5051 Flags [S] win ...

最新文章

  1. led计数电路实验报告_「正点原子FPGA连载」第八章 按键控制LED灯实验
  2. 江苏省2013年会计从业资格考试《会计基础》全真模拟试题
  3. springboot接收JSONArray
  4. mysql having
  5. 采用Lists.UpdateListItems方法更新列表项各种类型值的写法
  6. 程序员修神之路--晦涩难懂的CAP,是否完全正确?
  7. python字典键值可以是元组或列表吗_Python列表、元组、字典、集合的内置使用方法...
  8. 开源中国 开源世界2018_2018年最受欢迎的报道:法律问题和开源社区
  9. 金蝶K3修改核算项目锁定字段的默认长度(以物料主数据的助记码为例)
  10. 详细图文——AVL树
  11. 飞行控制计算机英语怎么说,“飞行模式”英语怎么说
  12. thymeleaf 设置时间格式
  13. message: Content type 'multipart/form-data;boundary=----WebKitFormBoundaryksbSBUwTCB6eHI3j;charse
  14. C语言 单片机 快速计算COS SIN
  15. 视频教程-清华-尹成老师-Python爬虫day13-Python
  16. php每日任务,炉石传说新版本增加35个日常任务 每日任务奖励汇总
  17. matlab实验八,matlab实验八
  18. 组织级项目管理成熟度模型 OPM3模型
  19. ECharts+百度地图实现卫星地图样式
  20. 记第一次生产项目中Flutter接入原生项目遇到的问题

热门文章

  1. (省赛系列——团队第三场)
  2. java为什么要用数据源_【Java】就配置了一个数据源,为什么提示 there is more than one bean of “DataSource” type...
  3. 用Python 开发您的第一个 XGBoost 模型(收藏)
  4. python socketio web 端_使用flask-socketIO怎样讲json格式数据从服务器推送到前端?
  5. 跃迁 成为高手的技术
  6. 自动驾驶 11-2: 激光雷达传感器模型和点云 LIDAR Sensor Models and Point Clouds
  7. Markdown stackoverflow 增加中划线
  8. 算法:间隔重排序链表Reorder List
  9. 易筋SpringBoot 2.1 | 第廿四篇:SpringBoot访问Docker中的MongoDB
  10. 贝叶斯决策中的两类错误率分析