通过《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. JS match方法的返回数据的探究

    match方法是JS的字符串方法,详细说明可以看MDN的说明. 如果正则表达式匹配成功的话,match方法会返回一个数组,而数组里的数据有两种形式,对应着匹配方式:全局匹配与非全局匹配. 1. 全局匹 ...

  2. BZOJ2243: [SDOI2011]染色(树链剖分/LCT)

    Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段), 如 ...

  3. itchat转发指定的微信群里某个用户的发言到指定的群

    复读机功能, 如果有比较多的用户,超出500人,那就得分开至少两个群,如何把一些消息自动复制到另一个群呢. 自动转发指定用户的发言,转发到别的群 # !/usr/bin/env python # -* ...

  4. WCF 字节数据传输

    准备工作 1.新建一个工程,添加一个WCF服务库, 然后公共的类库, 添加一个默认可序列化的的CompositeType类用于压缩. [Serializable] public class Compo ...

  5. 【MapReduce】经常使用计算模型具体解释

    前一阵子參加炼数成金的MapReduce培训,培训中的作业样例比較有代表性,用于解释问题再好只是了. 有一本国外的有关MR的教材,比較有用.点此下载. 一.MapReduce应用场景 MR能解决什么问 ...

  6. 洛谷 P1143 进制转换

    P1143 进制转换 题目描述 请你编一程序实现两种不同进制之间的数据转换. 输入输出格式 输入格式: 输入数据共有三行,第一行是一个正整数,表示需要转换的数的进制n(2≤n≤16),第二行是一个n进 ...

  7. [RxJS] How To get the results of two HTTP requests made in sequence

    switchMap can chain two HTTP requests together, creating one request based on the results of the fir ...

  8. AMBA标准

    AMBA标准定义了三种不同的总线 高级高性能总线(AHB): 高级系统总线(ASB):-----用的比较少 高级外设总线(APB). 基于AMBA的典型微控制器: 典型的AMBA AHB系统设计包含以 ...

  9. x264代码剖析(十五):核心算法之宏块编码中的变换编码

    x264代码剖析(十五):核心算法之宏块编码中的变换编码 为了进一步节省图像的传输码率.须要对图像进行压缩,通常採用变换编码及量化来消除图像中的相关性以降低图像编码的动态范围.本文主要介绍变换编码的相 ...

  10. Android LoaderManager与CursorLoader用法

    一.基本概念 1.LoaderManager LoaderManager用来负责管理与Activity或者Fragment联系起来的一个或多个Loaders对象. 每个Activity或者Fragme ...