仅以此文作为学习笔记,初学者,如有错误欢迎批评指正,但求轻喷。
一般而言,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. android学习日记01--综述

    开个博客,写点关于Android的知识,希望温故而知新吧! 一.总体框架 先上一张google提供官方的Android框架图: Android系统架构由5部分组成,分别是:Linux Kernel.A ...

  2. WF追忆

    前一阵子学习了一下工作流,现在写个总结记录一下这个过程.要弄工作流,首先就要有个界面来画图,做web的,没办法,只能选择javascript和silverlight,找来找去,最后用了Shareide ...

  3. 没有启动 ASP.NET State service错误的解决方法

    具体错误如下: 异常详细信息: System.Web.HttpException: 无法向会话状态服务器发出会话状态请求.请确保已启动 ASP.NET State service,并且客户端和服务器端 ...

  4. 从jQuery谈库与框架的设计之优劣

    jQuery是业内知名的javascript框架,它的实现和设计可以说代表了javascript界最高的水平,本文试从四个方面来以jQuery为例总结库与框架设计的原则和优劣判断. 解决问题 首先请看 ...

  5. 空间管理 您的位置: 51Testing软件测试网 » lilisx2006的个人空间 » 日志 在一个没有测试经理的小公司如何做好测试

    如何在一个没有测试经理的小公司做好测试? 首先,没有测试经理意味着测试人员没有最直接的管理者,往往这种时候的管理者是开发经理或技术总监,但他们何其忙耶?同时,在无人监管的情况下,测试是一个很容易偷懒的 ...

  6. Windows通用知识讲解一

    Window应用程序的类型 --控制台程序Console DOS程序,本身没有窗口,通过Windows DOS窗口执行 --窗口程序 拥有自己的窗口,可以与用户交互 --库程序 存放代码.数据的程序, ...

  7. am335x LCD参数更改

    /******************************************************************** * am335x LCD参数更改 * * 本文记录am335 ...

  8. sendEvent()

    sendEvent()(QObject *receiver, QEvent *event)可以将自己创建事件event发送给制定的receiver 例如, //创建按键事件 QKeyEvent key ...

  9. poj 3414 Pots(广搜BFS+路径输出)

    转载请注明出处:http://blog.csdn.net/u012860063?viewmode=contents 题目链接:id=3414">http://poj.org/probl ...

  10. django-south使用 [转]

    转自: http://alexliyu.blog.163.com/blog/static/16275449620126239949478/ 使用South之前铭记:请你一定要相信他的能力,抛弃对他的不 ...