仅以此文作为学习笔记,初学者,如有错误欢迎批评指正,但求轻喷。
一般而言,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<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 == -)
{
cout<<"Socket init error!"<<endl;
return -;
}
/*
下面设置接口结构
*/
char *ifname = "eth0";
struct ifreq ifr;
strcpy(ifr.ifr_name,ifname);
int result = ioctl(sockfd,SIOCGIFFLAGS,&ifr);
if(result == -)
{
cout<<"Can't get flags!"<<endl;
close(sockfd);
return -;
}
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 == -)
{
cout<<"Can't set flags!"<<endl;
close(sockfd);
return -;
} return sockfd;
}
int getframe(int sockfd,int num)
{
struct ethhdr* fheader;
fheader = (struct ethhdr*)ethernet_frame;
memset(ethernet_frame,,ETH_FRAME_LEN);
int size = read(sockfd,ethernet_frame,ETH_FRAME_LEN);
if(size <= )
{
cout<<"No packet or packet error!"<<endl;
return -;
}
cout<<"************************Packet"<<num<<"received from eth0 START!************************"<<endl;
printf("DST MAC: ");
for(int i=;i<ETH_ALEN-;i++)
{
printf("%2x-",fheader->h_dest[i]);
}
printf("%2x\n",fheader->h_dest[ETH_ALEN-]);
printf("SRC MAC: ");
for(int i=;i<ETH_ALEN-;i++)
{
printf("%2x-",fheader->h_source[i]);
}
printf("%2x\n",fheader->h_source[ETH_ALEN-]);
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 ;
}
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 == )
{
cout<<"PROTOCOL: ICMP"<<endl;
}
if(ipheader->protocol == )
{
cout<<"PROTOCOL: TCP"<<endl;
}
if(ipheader->protocol == )
{
cout<<"PROTOCOL: UDP"<<endl;
}
return ipheader->protocol;
} int gettcp(int protocol)
{
if(protocol != )
{
return -;
}
struct tcphdr* tcph;
tcph = (struct tcphdr*)(ipheader+((ipheader->ihl)*));
printf("SRC PORT: %d",ntohs(tcph->source));
cout<<endl;
printf("DST PORT: %d",ntohs(tcph->dest));
cout<<endl;
return ;
} int getudp(int protocol)
{
if(protocol != )
{
return -;
}
struct udphdr* udph;
udph = (struct udphdr*)(ipheader+((ipheader->ihl)*));
printf("SRC PORT: %d",ntohs(udph->source));
cout<<endl;
printf("DST PORT: %d",ntohs(udph->dest));
cout<<endl;
return ;
} int main(int argc,char *argv[])
{
if(argc < )
{
cout<<"Please input the nummber of packet that you want to catch!"<<endl;
return ;
}
int num = (int)argv[][];
int sock = socketcreate();
for(int i=;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 ;
}

Linux数据链路层的包解析的更多相关文章

  1. linux下抓包工具tcpdump详解

    本文转自:http://www.cnblogs.com/ggjucheng/archive/2012/01/14/2322659.html 简介 用简单的话来定义tcpdump,就是:dump the ...

  2. linux网络配置完全解析

    概述:熟悉了windows下面的网络配置,对linux下的网络配置缺未必了解透彻.熟练掌握linux下的网络配置原理,能帮助我们更容易掌握网络传输原理:同时具备一些网络连接不通对应问题的排查能力.文本 ...

  3. Linux下 解包/打包 Android 映像文件 system.img, boot.img, ramdisk.img, userdata.img.

    Linux下 解包/打包 Android 映像文件 system.img, boot.img, ramdisk.img, userdata.img. 2014年10月20日 ⁄ 计算机视觉 ⁄ 共 1 ...

  4. linux ssh使用深度解析(key登录详解)

    linux ssh使用深度解析(key登录详解) SSH全称Secure SHell,顾名思义就是非常安全的shell的意思,SSH协议是IETF(Internet Engineering Task ...

  5. [Docker]Docker与Linux ip_forward数据包转发

    背景 今天在一台新虚拟机上需要临时启动一个consul服务,安装Docker后使用docker启动,但是在执行启动命令后发现docker有一个警告: WARNING: IPv4 forwarding ...

  6. Wireshark-过滤器-数据包解析

    目录 过滤器 数据包解析 参考 推荐阅读: https://www.cnblogs.com/zwtblog/tag/计算机网络/ 过滤器 显示过滤器 和 捕获过滤器,俩者使用非常类似. 在Wiresh ...

  7. java jar包解析:打包文件,引入文件

    java jar包解析:打包文件,引入文件 cmd下: jar命令:package包打包 javac命令:普通类文件打包 Hello.java: package org.lxh.demo; publi ...

  8. Linux内核数据包的发送传输

    本文主要讲解了Linux内核数据包的传输流程,使用的内核的版本是2.6.32.27 为了方便理解,本文采用整体流程图加伪代码的方式从内核高层面上梳理了二层数据包发送传输的流程,希望可以对大家有所帮助. ...

  9. Android做法说明(3)---Fragment使用app袋或v4包解析

    Android做法说明(3)---Fragment使用app袋或v4包解析 1)问题简述 相信非常多的朋友在调用Fragment都会遇到以下的情况: watermark/2/text/aHR0cDov ...

随机推荐

  1. Hibernate- 动态实例查询

    什么是动态实例查询: 就是将查询出的单一列的字段,重新封装成对象,如果不适用特殊方法,会返回Object对象数组. 01.搭建环境 02.动态实例查询 需要使用相应的构造方法: public Book ...

  2. 当数据库的字段为date类型时候

    当数据库的字段为date类型时候: //--------------------------------------------------数据库设计------------------------- ...

  3. R绘制中国地图,并展示流行病学数据

    流行病学的数据讲究“三间分布”,即人群分布.时间分布和空间分布.其中的“空间分布”最好是在地图上展示,才比较清楚.R软件集统计分析与高级绘图于大成,是最适合做这项工作了.关于地图的绘制过程,谢益辉.邱 ...

  4. Translating between qplot and base graphics

    Translating between qplot and base graphics Description There are two types of graphics functions in ...

  5. jquery json解析详解

    我们先以解析上例中的comments对象的JSON数据为例,然后再小结jQuery中解析JSON数据的方法. JSON数据如下,是一个嵌套JSON: 1 {"comments":[ ...

  6. 25+开源的在线购物软件(PHP, JavaScript 和 ASP.Net)

    25 +免费开源的电子商务解决方案,提供了建立一个在线购物所有主要功能,并能够连接到一个支付处理系统1. Magento Magento是一套专业开源的PHP电子商务系统.Magento设计得非常灵活 ...

  7. e673. Getting Amount of Free Accelerated Image Memory

    Images in accelerated memory are much faster to draw on the screen. However, accelerated memory is t ...

  8. DOM编程 学习笔记(一)

    PS:虽然自己JS基本语法算是掌握了,但是其实在JS掌握的只是远远还不够,网页上有太多好看的动态效果都是用JS 做出来的,自己也就仅仅会那么一两个动态的效果,学的只是皮毛...等有空的时候一定要好好的 ...

  9. Python调用打印机参考例子

    参考资料: http://blog.csdn.net/jdh99/article/details/42585987 http://www.oschina.net/question/1438043_23 ...

  10. js时间转化

    const defaultTicks = 621355968000000000; export function convertDateToTicks(date = new Date()) { ret ...