Linux网络编程——原始套接字实例:MAC 头部报文分析
通过《Linux网络编程——原始套接字编程》得知,我们可以通过原始套接字以及 recvfrom( ) 可以获取链路层的数据包,那我们接收的链路层数据包到底长什么样的呢?
链路层封包格式
MAC 头部(有线局域网)
注意:CRC、PAD 在组包时可以忽略
链路层数据包的其中一种情况:
unsigned char msg[] = {
//--------------组MAC--------14------
0xb8, 0x88, 0xe3, 0xe1, 0x10, 0xe6, // dst_mac: b8:88:e3:e1:10:e6
0xc8, 0x9c, 0xdc, 0xb7, 0x0f, 0x19, // src_mac: c8:9c:dc:b7:0f:19
0x08, 0x00, // 类型:0x0800 IP协议
// …… ……
// …… ……
};
接收的链路层数据包,并对其进行简单分析:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/ether.h> int main(int argc,char *argv[])
{
int i = ;
unsigned char buf[] = "";
int sock_raw_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
while()
{
unsigned char src_mac[] = "";
unsigned char dst_mac[] = "";
//获取链路层的数据帧
recvfrom(sock_raw_fd, buf, sizeof(buf),,NULL,NULL);
//从buf里提取目的mac、源mac
sprintf(dst_mac,"%02x:%02x:%02x:%02x:%02x:%02x", buf[], buf[], buf[], buf[], buf[], buf[]);
sprintf(src_mac,"%02x:%02x:%02x:%02x:%02x:%02x", buf[], buf[], buf[], buf[], buf[], buf[]);
//判断是否为IP数据包
if(buf[]==0x08 && buf[]==0x00)
{
printf("______________IP数据报_______________\n");
printf("MAC:%s >> %s\n",src_mac,dst_mac);
}//判断是否为ARP数据包
else if(buf[]==0x08 && buf[]==0x06)
{
printf("______________ARP数据报_______________\n");
printf("MAC:%s >> %s\n",src_mac,dst_mac);
}//判断是否为RARP数据包
else if(buf[]==0x80 && buf[]==0x35)
{
printf("______________RARP数据报_______________\n");
printf("MAC:%s>>%s\n",src_mac,dst_mac);
}
}
return ;
}
记得以管理者权限运行程序:
每个报文头部都有一个相应的结构体,通过这些结构体对报文进行相应的组包或拆包会方便很多。
ubuntu 12.04 中描述网络协议结构的文件如下:
以太网头部(所需要头文件:#include <net/ethernet.h>):
上面的例子,改为用结构体实现,如下:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/ether.h>
#include <net/ethernet.h> // 以太网头部 头文件
#include <netinet/ip.h> // ip头部 头文件
// #include <net/if_arp.h> // arp头部 头文件 int main(int argc,char *argv[])
{
int i = ;
unsigned char buf[] = "";
int sock_raw_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
while()
{
unsigned char src_mac[] = "";
unsigned char dst_mac[] = "";
//获取链路层的数据帧
recvfrom(sock_raw_fd, buf, sizeof(buf),,NULL,NULL); //从数据中提取mac首部信息(14个字节)
struct ether_header *ethdr = NULL;
ethdr = (struct ether_header *)buf; //从buf里提取目的mac、源mac
sprintf(dst_mac,"%02x:%02x:%02x:%02x:%02x:%02x", ethdr->ether_dhost[], ethdr->ether_dhost[],ethdr->ether_dhost[],ethdr->ether_dhost[],ethdr->ether_dhost[],ethdr->ether_dhost[]);
sprintf(src_mac,"%02x:%02x:%02x:%02x:%02x:%02x", ethdr->ether_shost[], ethdr->ether_shost[],ethdr->ether_shost[],ethdr->ether_shost[],ethdr->ether_shost[],ethdr->ether_shost[]); //判断是否为IP数据包
if( 0x0800 == ntohs(ethdr->ether_type) )
{
printf("______________IP数据报_______________\n");
printf("MAC:%s >> %s\n",src_mac,dst_mac); }//0x0806为ARP数据包, 0x8035为RARP数据包
else if( 0x0806 == ntohs(ethdr->ether_type) || 0x8035 == ntohs(ethdr->ether_type) )
{
printf("______________ARP数据报_______________\n");
printf("MAC:%s >> %s\n",src_mac,dst_mac);
} }
return ;
}
转自:http://blog.csdn.net/tennysonsky/article/details/44751997
Linux网络编程——原始套接字实例:MAC 头部报文分析的更多相关文章
- Linux网络编程——原始套接字编程
原始套接字编程和之前的 UDP 编程差不多,无非就是创建一个套接字后,通过这个套接字接收数据或者发送数据.区别在于,原始套接字可以自行组装数据包(伪装本地 IP,本地 MAC),可以接收本机网卡上所有 ...
- Linux网络编程——原始套接字能干什么?
通常情况下程序员接所接触到的套接字(Socket)为两类: (1)流式套接字(SOCK_STREAM):一种面向连接的 Socket,针对于面向连接的TCP 服务应用: (2)数据报式套接字(SOCK ...
- LINUX 网络编程 原始套接字
一 原始套接字 原始套接字(SOCK_RAW)是一种不同于SOCK_STREAM.SOCK_DGRAM的套接字,它实现于系统核心.然而,原始套接字能做什么呢?首先来说,普通的套接字无法处理ICMP.I ...
- UNIX网络编程——原始套接字(dos攻击)
原始套接字(SOCK_RAW).应用原始套接字,我们可以编写出由TCP和UDP套接字不能够实现的功能. 注意原始套接字只能够由有 root权限的人创建. 可以参考前面的博客<<UNIX网络 ...
- UNIX网络编程——原始套接字的魔力【续】
如何从链路层直接发送数据帧 上一篇里面提到的是从链路层"收发"数据,该篇是从链路层发送数据帧. 上一节我们主要研究了如何从链路层直接接收数据帧,可以通过bind函数来将原始套接字绑 ...
- UNIX网络编程——原始套接字的魔力【上】
基于原始套接字编程 在开发面向连接的TCP和面向无连接的UDP程序时,我们所关心的核心问题在于数据收发层面,数据的传输特性由TCP或UDP来保证: 也就是说,对于TCP或UDP的程序开发,焦点在Dat ...
- UNIX网络编程——原始套接字SOCK_RAW
实际上,我们常用的网络编程都是在应用层的报文的收发操作,也就是大多数程序员接触到的流式套接字(SOCK_STREAM)和数据包式套接字(SOCK_DGRAM).而这些数据包都是由系统提供的协议栈实现, ...
- UNIX网络编程——原始套接字的魔力【下】
可以接收链路层MAC帧的原始套接字 前面我们介绍过了通过原始套接字socket(AF_INET, SOCK_RAW, protocol)我们可以直接实现自行构造整个IP报文,然后对其收发.提醒一点,在 ...
- Linux网络编程之套接字基础
1.套接字的基本结构 struct sockaddr 这个结构用来存储套接字地址. 数据定义: struct sockaddr { unsigned short sa_family; /* addre ...
随机推荐
- Robot Framework 自动化测试
Robot Framework 自动化测试 RIDE 是 Robot Framework 测试数据的编辑器.它使测试用例的创建.运行.测试项目的组织可以在图形界面下完成. 通过 RIDE 去学习和使用 ...
- [JWT] JWT with HS256
The advantages of JWT over traditional session based validation is: it effectively removing all auth ...
- “ping”命令的原理就是向对方主机发送UDP数据包,HTTP在每次请求结束后都会主动释放连接,因此HTTP连接是一种“短连接”
Socket 是一套建立在TCP/IP协议上的接口不是一个协议 应用层: HTTP FTP SMTP Web 传输层: 在两个应用程序之间提供了逻辑而不是物理的通信(TCP UDP) T ...
- 如何使用echo.js实现图片的懒加载(整理)
如何使用echo.js实现图片的懒加载(整理) 一.总结 一句话总结:a.在img标签中添加data-echo属性加载真实图片:<img class="loading" sr ...
- Rdis-主从复制
配置 配置一个从服务器非常简单, 只要在配置文件中增加以下的这一行就可以了: slaveof 192.168.1.1 6379 注:主:bind 192.168.10.1 (指定主机IP) 当然, 你 ...
- 15、python学习手册之:python语句、赋值、表达式和打印
1.语句的另一个特殊规则是用一对括号把语句括起来就可以:括号().方括号[].字典的大括号{}.任何括在这些符号里的程序代码都可横跨好几行. 2.括号是可以包含一切的,因为任何表达式都可以包含在内,只 ...
- Leetcode之Best Time to Buy and Sell Stock
Say you have an array for which the ith element is the price of a given stock on day i. If you were ...
- Qt5 UI信号、槽自动连接的控件重名大坑(UI生成的槽函数存在一个隐患,即控件重名。对很复杂的控件,不要在 designer 里做提升,而是等到程序启动后,再动态创建,可以避免很多问题)
对Qt5稍有熟悉的童鞋都知道信号.槽的自动连接机制.该机制使得qt designer 设计的UI中包含的控件,可以不通过显式connect,直接和cpp中的相应槽相关联.该机制的详细文章见 http: ...
- amazeui页面分析2
amazeui页面分析2 一.总结 1.弄清结构:这些部分都是一块一块分好了的,掌握结构之后,想替换哪块就替换哪块,想不要哪块就不要哪块,非常简单的 2.一块一块:替换十分简单 3.弄清楚大块之后,然 ...
- struts2漏洞原理及解决的方法
1.原理 Struts2的核心是使用的webwork框架,处理 action时通过调用底层的getter/setter方法来处理http的參数,它将每一个http參数声明为一个ONGL(这里是ONGL ...