Linux数据链路层的包解析
仅以此文作为学习笔记,初学者,如有错误欢迎批评指正,但求轻喷。
一般而言,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数据链路层的包解析的更多相关文章
- linux下抓包工具tcpdump详解
本文转自:http://www.cnblogs.com/ggjucheng/archive/2012/01/14/2322659.html 简介 用简单的话来定义tcpdump,就是:dump the ...
- linux网络配置完全解析
概述:熟悉了windows下面的网络配置,对linux下的网络配置缺未必了解透彻.熟练掌握linux下的网络配置原理,能帮助我们更容易掌握网络传输原理:同时具备一些网络连接不通对应问题的排查能力.文本 ...
- Linux下 解包/打包 Android 映像文件 system.img, boot.img, ramdisk.img, userdata.img.
Linux下 解包/打包 Android 映像文件 system.img, boot.img, ramdisk.img, userdata.img. 2014年10月20日 ⁄ 计算机视觉 ⁄ 共 1 ...
- linux ssh使用深度解析(key登录详解)
linux ssh使用深度解析(key登录详解) SSH全称Secure SHell,顾名思义就是非常安全的shell的意思,SSH协议是IETF(Internet Engineering Task ...
- [Docker]Docker与Linux ip_forward数据包转发
背景 今天在一台新虚拟机上需要临时启动一个consul服务,安装Docker后使用docker启动,但是在执行启动命令后发现docker有一个警告: WARNING: IPv4 forwarding ...
- Wireshark-过滤器-数据包解析
目录 过滤器 数据包解析 参考 推荐阅读: https://www.cnblogs.com/zwtblog/tag/计算机网络/ 过滤器 显示过滤器 和 捕获过滤器,俩者使用非常类似. 在Wiresh ...
- java jar包解析:打包文件,引入文件
java jar包解析:打包文件,引入文件 cmd下: jar命令:package包打包 javac命令:普通类文件打包 Hello.java: package org.lxh.demo; publi ...
- Linux内核数据包的发送传输
本文主要讲解了Linux内核数据包的传输流程,使用的内核的版本是2.6.32.27 为了方便理解,本文采用整体流程图加伪代码的方式从内核高层面上梳理了二层数据包发送传输的流程,希望可以对大家有所帮助. ...
- Android做法说明(3)---Fragment使用app袋或v4包解析
Android做法说明(3)---Fragment使用app袋或v4包解析 1)问题简述 相信非常多的朋友在调用Fragment都会遇到以下的情况: watermark/2/text/aHR0cDov ...
随机推荐
- hadoop错误之ClassNotFoundException(下)
hadoop开发环境:window上eclipse+虚拟机的ubuntu13.04+hadoop-1.1.2+JDK1.7 在win7下运行hadoop-1.1.2 worldcount代码的时候出现 ...
- A/libc:fatal signal 11(SIGSEGV).code 1, fault addr 0x0 in tid 26488 (VideoEncoder)
在调试Camera模块:发现相同的代码在厂家提供的环境里边编译.就是ok的,在我们的源码树中编译,将HAL库推进去后.就会signal 11退出. 一.现象 F/libc ( ): Fatal sig ...
- 数学符号arg含义
argument of the maximum/minimum arg max f(x): 当f(x)取最大值时,x的取值 arg min f(x):当f(x)取最小值时,x的取值 表示使目标函数取最 ...
- .NET操作Excel笔记
如果你新建一个项目的话,首先要添加Microsoft.Office.Core 与Microsoft.Office.Interop.Exce这两个应用,然后就能很方便的操作了,示例代码(只实现了简单的读 ...
- 关于Cocos2d-x中UI按钮的定义
1.要有两张不同状态的图片 2.定义一个MenuItemSprite的实例,把这两张图的Sprite实例放进MenuItemSprite的实例 3.把MenuItemSprite的实例放进Menu实例 ...
- 转载:【原译】Erlang列表处理(Efficiency Guide)
转自:http://www.cnblogs.com/futuredo/archive/2012/10/22/2734186.html List handling 1 Creating a list ...
- CentOS系统安装后的基础优化
在运维工作中,我们发现Linux系统安装之后并不能立即投入生产环境使用,往往需要先经过我们运维人员的优化才行. 下面我就为大家简单讲解几点关于Linux系统安装后的基础优化操作. 注意:本次优化都是基 ...
- 【Java面试题】32 ArrayList和Vector的区别
1. Vector & ArrayList 相同点: 1.ArrayList和Vector都是继承了相同的父类和实现了相同的接口 2.底层都是数组实现的 3.初始默认长度都为10. 不同点: ...
- hadoop学习笔记之-hbase完全分布模式安装-5
http://blog.csdn.net/lichangzai/article/details/8441975 http://blog.csdn.net/jpiverson/article/detai ...
- window用Xmanager4.0的Xstart连接linux远程桌面
安装包: xorg-x11-xauth xterm.x86_64 0:253-1.el6 Execute command path:/usr/bin/xterm Xstart连接Linux远程桌面有一 ...