分析dhcp真正的帧格式



背景知识:

第一:需要了解libcap的基本架构!

第二:需要了解TCP/IP协议头部结构体(网摘小结)

第三:下面的图示概念需要了解



67 bootps 引导协议(BOOTP)服务;还被动态主机配置协议(DHCP)服务使用
68 bootpc Bootstrap(BOOTP)客户;还被动态主机配置协议(DHCP)客户使用
#define SPERW   (7 * 24 * 3600)
#define SPERD   (24 * 3600)
#define SPERH   (3600)
#define SPERM   (60)


#define LARGESTRING 1024


// header variables
u_char  timestamp[40];          // timestamp on header
u_char  mac_origin[40];         // mac address of origin
u_char  mac_destination[40];        // mac address of destination
u_char  ip_origin[40];          // ip address of origin
u_char  ip_destination[40];     // ip address of destination
int max_data_len;           // maximum size of a packet


int tcpdump_style = -1;
char    errbuf[PCAP_ERRBUF_SIZE];
char    *hmask = NULL;
regex_t preg;


int check_ch(u_char *data, int data_len);
int readheader(u_char *buf);
int readdata(u_char *buf, u_char *data, int *data_len);
int printdata(u_char *data, int data_len);
void    pcap_callback(u_char *user, const struct pcap_pkthdr *h,
        const u_char *sp);


void    printIPaddress(u_char *data);
void    printIPaddressAddress(u_char *data);
void    printIPaddressMask(u_char *data);
void    print8bits(u_char *data);
void    print16bits(u_char *data);
void    print32bits(u_char *data);
void    printTime8(u_char *data);
void    printTime32(u_char *data);
void    printReqParmList(u_char *data, int len);
void    printHexColon(u_char *data, int len);
void    printHex(u_char *data, int len);
void    printHexString(u_char *data, int len);


void usage() {
    printf("Usage: $0 <-i interface> [-h macaddress]\n");
    exit(0);
}


int main(int argc, char **argv) {
    int i;
    pcap_t *cap;
    struct bpf_program fp;
    char    *interface = NULL;


    for (i = 1; i < argc; i++) {
        if (argv[i] == NULL || argv[i][0] != '-') break;
        switch (argv[i][1]) {
        case 'h':
            hmask = argv[++i];
            break;
        case 'i':
            interface = argv[++i];
            break;
        default:
            fprintf(stderr, "%s: %c: uknown option\n",
                argv[0], argv[i][1]);
            usage();
        }
    }


    if (interface == NULL) usage();


    if (hmask)
        regcomp(&preg, hmask, REG_EXTENDED | REG_ICASE | REG_NOSUB);


    if ((cap = pcap_open_live(interface, 1500, 1, 100, errbuf)) == NULL)
        errx(1, "pcap_open_live(): %s", errbuf);
    if (pcap_compile(cap, &fp, "udp and (port bootpc or port bootps)", 0, 0) < 0)
        errx(1,"pcap_compile: %s", pcap_geterr(cap));
    if (pcap_setfilter(cap, &fp) < 0)
        errx(1,"pcap_setfilter: %s", pcap_geterr(cap));
    if (pcap_loop(cap, 0, pcap_callback, NULL) < 0)
        errx(1,"pcap_loop(%s): %s", interface, pcap_geterr(cap));


    return 0;
}


void pcap_callback(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) {
    struct ether_header *eh;
    struct ip *ip;
    struct udphdr *udp;
    int offset = 0;


    if (h->caplen < ETHER_HDR_LEN) {
        printf("Ignored too short ethernet packet: %d bytes\n",
            h->caplen);
        return;
    }
    //获取eth的头部
    eh = (struct ether_header *)(sp + offset);
    offset += ETHER_HDR_LEN;


    // Check for IPv4 packets
    if (eh->ether_type != 8) { 
        printf("Ignored non IPv4 packet: %d\n", eh->ether_type);
        return;
    }


    // Check for length
    if (h->caplen < offset + sizeof(struct ip)) {
        printf("Ignored too short IPv4 packet: %d bytes\n", h->caplen);
        return;
    }
    //获取ip的头部
    ip = (struct ip *)(sp + offset);
    offset += sizeof(struct ip);
    //获取udp的头部
    udp = (struct udphdr *)(sp + offset);
    offset += sizeof(struct udphdr);


    {
        struct timeval tp;
        gettimeofday(&tp, NULL);
        strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%S.",
            localtime(&(tp.tv_sec)));
        sprintf(timestamp + strlen(timestamp), "%03ld",
            tp.tv_usec / 1000);
    }


    strcpy(mac_origin, ether_ntoa((struct ether_addr *)eh->ether_shost));
    strcpy(mac_destination,
        ether_ntoa((struct ether_addr *)eh->ether_dhost));


    strcpy(ip_origin, (u_char *)inet_ntoa(ip->ip_src));
    strcpy(ip_destination, (u_char *)inet_ntoa(ip->ip_dst));


    if (hmask && check_ch((u_char *)(sp + offset), ntohs(udp->len))) return;

    //这里拿到了udp,也就是dhcp协议头部,根据http://blog.csdn.net/jl2011/article/details/49334297

    可以很容易的了解结果!
    printdata((u_char *)(sp + offset), ntohs(udp->len));
}

 

这里是dhcp的字段

通过运行程序,可以

发现是ok的!

---------------------------------------------------------------------------


  TIME: 2007-01-04 19:15:21.921
    IP: 172.21.18.69 (28:80:23:f8:b1:56) > 255.255.255.255 (ff:ff:ff:ff:ff:ff)
    OP: 1 (BOOTPREQUEST)
 HTYPE: 1 (Ethernet)
  HLEN: 6
  HOPS: 0
   XID: 4ede74e9
  SECS: 0
 FLAGS: 0
CIADDR: 0.0.0.0
YIADDR: 0.0.0.0
^Z  TIME: 2007-01-04 19:15:27.033
    IP: 172.21.18.57 (34:e6:d7:29:2f:f8) > 255.255.255.255 (ff:ff:ff:ff:ff:ff)
    OP: 1 (BOOTPREQUEST)
 HTYPE: 1 (Ethernet)
  HLEN: 6
  HOPS: 0
   XID: feabbf46
  SECS: 0
 FLAGS: 7f80
CIADDR: 172.21.18.57
YIADDR: 0.0.0.0
SIADDR: 0.0.0.0
GIADDR: 0.0.0.0
CHADDR: 34:e6:d7:29:2f:f8:00:00:00:00:00:00:00:00:00:00
 SNAME: .
 FNAME: .
OPTION:  53 (  1) DHCP message type         8 (DHCPINFORM)
OPTION:  61 (  7) Client-identifier         01:34:e6:d7:29:2f:f8
OPTION:  12 (  9) Host name                 sznb01404
OPTION:  60 (  8) Vendor class identifier   MSFT 5.0
OPTION:  55 ( 13) Parameter Request List      1 (Subnet mask)
    15 (Domainname)
     3 (Routers)
     6 (DNS server)
    44 (NetBIOS name server)
    46 (NetBIOS node type)
    47 (NetBIOS scope)
    31 (Perform router discovery)
    33 (Static route)
   121 (Classless Static Route)
   249 (MSFT - Classless route)
    43 (Vendor specific info)
   252 (MSFT - WinSock Proxy Auto Detect)
   
---------------------------------------------------------------------------


  TIME: 2007-01-04 19:15:27.036
    IP: 172.21.18.254 (00:22:56:a5:75:c4) > 255.255.255.255 (ff:ff:ff:ff:ff:ff)
    OP: 2 (BOOTPREPLY)
 HTYPE: 1 (Ethernet)
  HLEN: 6
  HOPS: 0
   XID: feabbf46
  SECS: 0
 FLAGS: 7f80
CIADDR: 172.21.18.57
YIADDR: 0.0.0.0
SIADDR: 0.0.0.0
GIADDR: 172.21.18.254
CHADDR: 34:e6:d7:29:2f:f8:00:00:00:00:00:00:00:00:00:00
 SNAME: .
 FNAME: .
OPTION:  53 (  1) DHCP message type         5 (DHCPACK)
OPTION:  54 (  4) Server identifier         172.21.80.51
OPTION:   1 (  4) Subnet mask               255.255.254.0
OPTION:  43 (  5) Vendor specific info      dc034e4150       ?NAP
OPTION:  15 ( 17) Domainname               **********************
OPTION:   3 (  4) Routers                   172.21.18.254
OPTION:   6 (  8) DNS server                172.21.80.100,172.21.80.51
---------------------------------------------------------------------------


版权声明:本文为lishanmin11原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/lishanmin11/article/details/76685187

智能推荐

函数调用过程中的栈帧分析

说到函数栈帧,就不得不提到另外一个名词“栈”,栈的主要特点:先入后出,后入先出(就像叠罗汉一样),增长的方向,高地址向低地址生长,系统自动回收 那么栈帧是什么呢? 栈帧首先是存储在栈上,栈帧记录函数调用过程的一些信息的,例如变量、上一级栈帧的帧指针、函数的返回地址等,一个程序不止一个函数,很多时候都是函数的嵌套调用,那么栈上面肯定有多个栈帧(栈溢出因为栈空间不够,栈帧太多会...

Linux信号及工作原理

  什么是信号     信号可以理解为软件中断,是在软件层次上对中断机制的一种模拟,在原理上,一个进程收到一个信号与处理器收到一个中断请求可以说是差不多的。信号是异步的,一个进程不必通过任何操作来等待信号的到达。信号可以直接进行用户空间进程和内核进程之间的交互,内核进程也可以利用它来通知用户空间进程发生了哪些系统事件。   谁来产生信号 信号事件的发生有两个...

手机端图片放大,双指放大,元素的双指缩放

在做webapp时候,遇到一个需要做双指放大的功能,需求是:一张带有坐标的图片上有固定的点,需要点击这些坐标上的点进入相应的商品,并且需要对这一块进行双指可以缩放,双击缩放; 一开始是自己写监听touch事件进行处理,但是再缩放的时候,偶尔出现卡顿闪烁,用户体验不很好,后来采用插件 pinch-zoom GitHub地址: https://github.com/manuelstofer/...

leetcode 剑指offer 54 二叉搜索树的第k大节点

第 K 大节点即反中序遍历大第 K 个数。...

redis 初步了解

1.连接redis 通过java操作 1.首先 导入redis驱动 2.连接redis通过jedis 2.创建redis连接池 连接redis通过 jedis 相当于HTTPclient 1.创建单例模式的方法 在调用的时候被创建 2.创建私有静态 jedisPool 3. 创建私有类 创建静态代码块 放入连接池的基本配置 4.有 最大连接数 最大空闲书 最小空闲连接数 5. 创建连接redis对...

猜你喜欢

第6章数据类型-基本数据类型-Boolean类型-main

防采集标记:亢少军老师的课程和资料 Dart交流群:1046954554 Flutter开源项目请关注: https://github.com/kangshaojun @作者: 亢少军 '...

使用 Infura 和 web3.js 呼叫合约

如果你希望马上开始学习以太坊DApp开发,可以访问汇智网提供的出色的在线互动教程: 以太坊DApp实战入门教程 以太坊去中心化电商应用开发实战 如果你希望了解如何部署合约,可以查看另一篇文章:在truffle中使用infura部署以太坊智能合约。 Infura 提供公开的 Ethereum 主网和测试网络节点。到 Infura 官网申请,只要输入一点基本资料和 Email,就可以收到 API-ke...

手写RPC通信框架

RPC基本介绍 服务器端构建 API包下主体编写 首先初始采用Socket进行通信利用IO进行数据交互,对客户端要提供API调用接口,使得客户端可以利用API中提供的接口,获得服务器端的数据。服务器端模块目录如下: 先编写一个接口,该接口放置在api模块下,实现类放置在provider模块下,这样做目的是让客户端仅加载API包的条件下,可以调用服务器端的实现类完成具体业务逻辑。 服务器端需要客户端...

Highcharts饼状图Ajax动态赋值的问题

这种饼状图是动态的当鼠标放上面那一部分会突出的 Highcharts下载:点击下载 Highcharts-zh_CN.js下载:点击下载 效果图: 前台js代码: 控制层代码: 其中用到两种传值方式一种JSON另一种用Map传值给Ajax,下面为取到的值。 两个饼状图并列展示前台代码: 给饼状图赋值主要就是取json拼接成 data:[[name,y],[name,y]]这样的数组 注意y后面的数...

Qt工程Windows下的安装包制作

工具 Depends.exe nisedit2.0.3.exe nsis-2.50-setup.exe 先安装nsis-2.50-setup.exe, 在安装nisedit2.0.3.exe. 都按默认安装即可. Depends.exe不需要安装. 步骤 1, 在工程中的main()函数里添加如下代码解决库路径问题. 2, 在工程文件.pro中添加如下内容, 其中”DESTDIR=in...