美文网首页
IP数据报解析C语言

IP数据报解析C语言

作者: 二进制人类 | 来源:发表于2022-09-21 22:51 被阅读0次

相关API

创建套接字

#include <sys/types.h>
#include <sys/socket.h>

/**
 * [socket 创建套接字]
 * @param  domain   [由于需要创建原始套接字(基于链路层创建),需要选择通信域为: AF_PACKET]
 * @param  type     [使用的是SOCK_RAW表示创建的是原始套接字文件]
 * @param  protocol [
 *                  指定可以接收或发送的数据包类型
 *                   ETH_P_IP:     IP数据包
                     ETH_P_ARP:    ARP数据包
                     ETH_P_ALL:    任何协议类型的数据包
 *                   ]
 * @return          [成功返回一个大于0的文件描述符,表示网络数据链路层的套接字文件;
    失败返回-1,且修改errno的值]
 */
int socket(int domain, int type, int protocol);

接收

#include <sys/types.h>
#include <sys/socket.h>
/**
 * [recvfrom 接收数据]
 * @param  sockfd   [sockfd套接字文件描述符]
 * @param  buf      [buf指针指向的空间用存储接收到的数据]
 * @param  len      [len表示参数2指向空间的大小]
 * @param  flags    [flags表示数据接收的方式,常用0表示阻塞接收]
 * @param  src_addr [src_addr指向的空间用来返回对端的IP地址和端口号,如果不关心则使用NULL]
 * @param  addrlen  [addrlen指针指向的空间用来返回参数5指向对端空间的大小]
 * @return          [成功返回接收数据的字节数,失败返回-1且修改errno的值]
 */
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);

实例

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>        
#include <sys/socket.h>
#include <netinet/ether.h>
#include <arpa/inet.h>

int main()
{
    int ret;
    int sockfd;
    unsigned char buf[1024];
    char dest_mac[18];
    char src_mac[18];
    unsigned short type;

    /* 创建原始套接字文件:基于链路层,可用于任意协议数据的收发 */
    sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
    if(sockfd == -1)
    {
        perror("socket");
        return -1;
    }
    //循环接收
    while(1)
    {
        //sleep(1);
        ret = recvfrom(sockfd, buf, sizeof(buf), 0, NULL, NULL);
        if (ret == -1)
        {
            perror("recvfrom");
            return -1;
        }
        /* 解析数据:以太网数据:目的mac和源mac地址 */
        sprintf(dest_mac, "%02x:%02x:%02x:%02x:%02x:%02x", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
        sprintf(src_mac, "%02x:%02x:%02x:%02x:%02x:%02x", buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]);

        /* 解析得到报文的类型:由于是网络字节序数据,所以需要转换为主机字节序 */
        type = htons(*((unsigned short *)(buf + 12)));
        if (type == 0x0806)
        {
           printf(" ARP\n");
            /* 在进行ARP请求的时候需要添加IP地址,在做出ARP应答产生 */
        }
        else if (type == 0x8035)
        {
            printf(" RARP\n");
            /* 在进行RARP请求的时候需要添加MAC地址,在做出RARP应答产生 */
        }
        else if (type == 0x0800)
        {
            printf("IP Data:");
            /* 解析IP报文数据:源IP和目的IP、UDP报文或者TCP报文 */
            unsigned char *ip_buf = buf + 14;/* 14字节是以太网头: */

            /* 输出源mac -> 目的mac */
            //printf("%s -> %s\n", src_mac, dest_mac);


            /* 解析首部长度 */
            unsigned int ip_head_len = ((*ip_buf) & 0xf) * 4;
            //printf("%d\n", ip_head_len);

            /* 解析IP报文中的源IP和目的IP */
            char src_ip[16];
            char dest_ip[16];
            inet_ntop(AF_INET, ip_buf + 12, src_ip, sizeof(src_ip));
            inet_ntop(AF_INET, ip_buf + 16, dest_ip, sizeof(dest_ip));
            //printf("\t%s -> %s\n", src_ip, dest_ip);

            /* 解析IP报文的类型 */
            unsigned char ip_type = *(ip_buf + 9);
            if ( ip_type == 1 )
            {
                printf("\t\tICMP");
            }
            else if ( ip_type == 2 )
            {
                printf("\t\tIGMP");
            }
            else if ( ip_type == 6 )
            {
                printf("\t\tTCP Data:\n");
                unsigned char *tcp_buf = ip_buf + ip_head_len;
                /* 解析TCP的源端口和目的端口 */
                unsigned short src_port = ntohs(*(unsigned short *)tcp_buf);
                unsigned short dest_port = ntohs(*(unsigned short *)(tcp_buf + 2));

                /* 解析数据内容 */
                /* tcp头部长度 */
                unsigned int tcp_head_len = ((*(tcp_buf + 12) >> 4) & 0x0f) * 4;
                printf("tcp:%s:%d -> %s:%d : %s\n", src_ip, src_port, dest_ip, dest_port, tcp_buf + tcp_head_len);
            }
            else if ( ip_type == 17 )
            {
                unsigned char *udp_buf = ip_buf + ip_head_len;/* 跳转到UDP报文起始地址 */
                /* 解析UDP的源端口和目的端口 */
                unsigned short src_port = ntohs(*(unsigned short *)udp_buf);
                unsigned short dest_port = ntohs(*(unsigned short *)(udp_buf + 2));
                /* 解析得到udp数据内容 */
                //printf("%s\n", udp_buf+8);
                printf("%s -> %s\n", src_mac, dest_mac);
                printf("%s:%d -> %s:%d : %s\n", src_ip, src_port, dest_ip, dest_port, udp_buf + 8);
            }
        }
        else
        {

        }

    }

}

相关文章

  • IP数据报解析C语言

    相关API 创建套接字 接收 实例

  • DNS解析

    DNS解析 了解DNS解析 域名到IP地址的映射,DNS解析请求 才有UDP数据报,且明文 DNS解析查询方式 D...

  • DNS解析

    了解DNS解析吗? 域名到IP地址的映射,DNS解析请求采用UDP数据报,并且明文显示。 DNS解析查询方...

  • 2020-05-12 四

    dns 域名到ip 53端口udp 数据报 明文传输 DNS劫持问题:因为DNS解析使用UDP数据报且是明文...

  • DNS解析&Session/Cookie

    一. DNS解析 1. 了解DNS解析域名到IP地址的映射, DNS解析请求采用UDP数据报, 且明文 2. DN...

  • DNS解析

    了解DNS解析吗? 域名到IP地址的映射,DNS解析请求采用UDP数据报,且明文 client向server端请求...

  • 第十章、网络相关

    一、了解DNS解析吗? 域名到IP地址的映射,DNS解析请求采用UDP数据报,且明文。之所以采用UDP,TCP连接...

  • 计算机网络:网络层(2)

    IP数据报的格式: 如图,一个IP数据报由首部和数据两部分组成。首部的前一部分是固定长度,共20字节,是所有IP数...

  • ipv4转整数

    IP与整数互转,C语言实现 IP 与整数互转,JAVA语言实现

  • https笔记

    HTTPS就是将HTTP协议数据包放到SSL/TSL层加密后,在TCP/IP层组成IP数据报去传输,以此保证传输数...

网友评论

      本文标题:IP数据报解析C语言

      本文链接:https://www.haomeiwen.com/subject/rmygortx.html