通过《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 头部报文分析的更多相关文章

  1. Linux网络编程——原始套接字编程

    原始套接字编程和之前的 UDP 编程差不多,无非就是创建一个套接字后,通过这个套接字接收数据或者发送数据.区别在于,原始套接字可以自行组装数据包(伪装本地 IP,本地 MAC),可以接收本机网卡上所有 ...

  2. Linux网络编程——原始套接字能干什么?

    通常情况下程序员接所接触到的套接字(Socket)为两类: (1)流式套接字(SOCK_STREAM):一种面向连接的 Socket,针对于面向连接的TCP 服务应用: (2)数据报式套接字(SOCK ...

  3. LINUX 网络编程 原始套接字

    一 原始套接字 原始套接字(SOCK_RAW)是一种不同于SOCK_STREAM.SOCK_DGRAM的套接字,它实现于系统核心.然而,原始套接字能做什么呢?首先来说,普通的套接字无法处理ICMP.I ...

  4. UNIX网络编程——原始套接字(dos攻击)

    原始套接字(SOCK_RAW).应用原始套接字,我们可以编写出由TCP和UDP套接字不能够实现的功能. 注意原始套接字只能够由有 root权限的人创建. 可以参考前面的博客<<UNIX网络 ...

  5. UNIX网络编程——原始套接字的魔力【续】

    如何从链路层直接发送数据帧 上一篇里面提到的是从链路层"收发"数据,该篇是从链路层发送数据帧. 上一节我们主要研究了如何从链路层直接接收数据帧,可以通过bind函数来将原始套接字绑 ...

  6. UNIX网络编程——原始套接字的魔力【上】

    基于原始套接字编程 在开发面向连接的TCP和面向无连接的UDP程序时,我们所关心的核心问题在于数据收发层面,数据的传输特性由TCP或UDP来保证: 也就是说,对于TCP或UDP的程序开发,焦点在Dat ...

  7. UNIX网络编程——原始套接字SOCK_RAW

    实际上,我们常用的网络编程都是在应用层的报文的收发操作,也就是大多数程序员接触到的流式套接字(SOCK_STREAM)和数据包式套接字(SOCK_DGRAM).而这些数据包都是由系统提供的协议栈实现, ...

  8. UNIX网络编程——原始套接字的魔力【下】

    可以接收链路层MAC帧的原始套接字 前面我们介绍过了通过原始套接字socket(AF_INET, SOCK_RAW, protocol)我们可以直接实现自行构造整个IP报文,然后对其收发.提醒一点,在 ...

  9. Linux网络编程之套接字基础

    1.套接字的基本结构 struct sockaddr 这个结构用来存储套接字地址. 数据定义: struct sockaddr { unsigned short sa_family; /* addre ...

随机推荐

  1. vue打包添加样式兼容前缀

    在ios8 版本上的h5对flex的支持不太好,需要有兼容的写法. vue-cli自带了postCss autoprefixer 进行兼容处理,配置如下 在vue-loader.config.js中开 ...

  2. Mining Station on the Sea (hdu 2448 SPFA+KM)

    Mining Station on the Sea Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Jav ...

  3. 1.html+css页面设计

    转自:http://www.cnblogs.com/ywang/archive/2014/04/16/3668638.html 今天用html+css做一个最简单的页面.效果图如下: 说明:这里的韩文 ...

  4. mycat快速体验(转)

    横空出世的MyCat截至到2015年4月,保守估计已经有超过60个项目在使用,主要应用在电信领域.互联网项目,大部分是交易和管理系统,少量是信息系统.比较大的系统中,数据规模单表单月30亿.本人也初步 ...

  5. UVA - 590Always on the run(递推)

    题目:UVA - 590Always on the run(递推) 题目大意:有一个小偷如今在计划着逃跑的路线,可是又想省机票费. 他刚開始在城市1,必须K天都在这N个城市里跑来跑去.最后一天达到城市 ...

  6. javascript预解释中的机制

    预解释是一种毫无节操的机制(自从学了预解释,从此节操是路人) in:‘num’ in window 判断num是否为window这个对象的一个属性,是的话返回true,不是返回false 1.预解释的 ...

  7. [D3] Better Code Organization with selection.call() with D3 v4

    Most of D3’s native selection APIs also return the selection (or a new selection), to enable multipl ...

  8. springMVC easyUI filebox 单个文件上传

    被这个文件上传坑到如今.还是自己技术问题,照着之前extjs项目那边的上传实例,愣是上传不了 到后面就查了下springMVC的文件上传,依照那样搞定了http://blog.csdn.net/jad ...

  9. JavaScript系列--JavaScript数组高阶函数reduce()方法详解及奇淫技巧

    一.前言 reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值. reduce() 可以作为一个高阶函数,用于函数的 compose. reduce()方 ...

  10. 9.4 Binder系统_驱动情景分析_服务使用过程

    5. 服务使用过程 test_client进程: 用户态: (1)已结获得了“hello”服务,handle=1; (2)构造数据:code(那个函数)和函数参数 (3)发送ioctl后进入内核态,先 ...