c - 解析 TCP 数据包数据

标签 c tcp packet packet-capture packet-sniffers

我正在尝试解析一个 tcp 数据包,然后分配一个指向有效负载开始的指针。

我正在使用 C,这是我目前的代码:

void dump(const unsigned char *data, int length) { //*data contains the raw packet data
    unsigned int i;
    static unsigned long pcount = 0;

    // Decode Packet Header
    struct ether_header *eth_header = (struct ether_header *) data;

    printf("\n\n === PACKET %ld HEADER ===\n", pcount);

    printf("\nSource MAC: ");
    for (i = 0; i < 6; ++i) {
        printf("%02x", eth_header->ether_shost[i]); //? Why don't i use nthos here?
        if (i < 5) printf(":");
    }

    unsigned short ethernet_type = ntohs(eth_header->ether_type);
    printf("\nType: %hu\n", ethernet_type);

    if (ethernet_type == ETHERTYPE_IP) { //IP Header
        printf("\n  == IP HEADER ==\n");
        struct ip *ip_hdr = (struct ip*) data + sizeof(struct ether_header);
        unsigned int size_ip = ip_hdr->ip_hl * 4;
        printf("\nIP Version: %u", ip_hdr->ip_v); //? Nthos or no nthos
        printf("\nHeader Length: %u", ip_hdr->ip_hl); //? Nthos or no nthos
        printf("\nTotal Length: %hu", ntohs(ip_hdr->ip_len)); //? Nthos or no nthos

        // TCP Header
        printf("\n== TCP HEADER ==\n");
        struct tcphdr *tcp_hdr = (struct tcphdr*) data + sizeof(struct ether_header) + size_ip;
        printf("\n Source Port: %" PRIu16, nthos(tcp_hdr->th_sport));
        printf("\n Destination Port: %" PRIu16, nthos(tcp_hdr->th_dport));
        printf("\n fin: %" PRIu16, tcp_hdr->fin);
        printf("\n urg: %" PRIu16, tcp_hdr->urg);
        printf("\n ack_seq: %" PRIu32, ntohl(tcp_hdr->ack_seq));

        //Transport payload! i.e. rest of the data
        const unsigned char *payload = data + ETH_HLEN + size_ip + sizeof(struct tcphdr) + tcp_hdr->doff;

    }

我确定这段代码中有错误,因为端口号都很奇怪。没有一个分配给 80。输出的 Ip 版本也可能非常奇怪(如版本 11)。我究竟做错了什么?谢谢!

此外,我不确定何时使用 nthos,何时不使用。我知道 nthos 用于 16 位无符号整数,我知道 nthol 用于 32 位无符号整数,但我知道您并不打算将它们用于这些数据包中的所有内容(例如:tcp_hdr->fin)。为什么是某些东西而不是它们?

非常感谢!

编辑:

感谢 Art 解决了大部分问题。我编辑了我的 tcp_hdr 和 ip_hdr,所以括号现在是正确的!

我还有两个问题:

  • 有效载荷的前 10 个字节有奇怪的符号(所以我认为我没有正确分配有效载荷)。
  • 我仍然不确定何时使用 nthos/nthol。我知道 u_int16_t 是 ntohs,u_int32_t 是 ntohl。但是那些带有 signed int 或 unisgned short int 的东西呢?例如,我没有将 ntohs 或 nthol 用于 ip_v 以使其工作。为什么不? “ip_hdr->ip_hl”是 nthol 吗?等等……

EDIT2

我已经修复了为什么我的有效载荷输出不正确(这是因为我计算的 TCP_header 大小错误)。

虽然我仍然对何时使用 nthos 感到困惑,但我会将其作为一个单独的问题提出,因为我认为我在这 1 个帖子中问了太多问题!

When to use ntohs and ntohl in C?

最佳答案

您的问题很可能出在这里:

struct ip *ip_hdr = (struct ip*) data + sizeof(struct ether_header);
struct tcphdr *tcp_hdr = (struct tcphdr*) data + sizeof(struct ether_header) + size_ip;

执行 (struct ip*) data + sizeof(struct ether_header) 首先将数据转换为 struct ip *,然后添加 sizeof(struct ether_header) 到它,我们从指针算术中知道它不会做你期望它做的事情。

如果问题仍然不清楚,这里有一个简单的程序可以为您指明正确的方向:

#include <stdio.h>

struct foo {
    int a, b;
};

int
main(int argc, char **argv)
{
    char *x = NULL;

    printf("%p\n", x);
    printf("%p\n", (struct foo *)x + 4);
    printf("%p\n", (struct foo *)(x + 4));

    return 0;
}

关于c - 解析 TCP 数据包数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27296160/

相关文章:

vb.net - 当数据应该存在时不要从套接字获取任何数据,并且没有引发异常,连接已打开。使用 DataAvailable 等待数据

ios - Bluetooth Low Energy - 重复更新特征值

java - Java中不使用libpcap进行网络数据包捕获

c - 使用 C 退出到 linux 的 ssh session

c - 通过数组用 C 编写的人脸检测器程序

c - 像tcl的vwait,C编程有没有?

python - 检测 tcp 客户端何时不活动超过 5 秒

不能分配超过一百万个整数

http - 托管在不同 Web 服务器上的 HTTP 请求对象的 TCP 连接

java - Java中使用AES算法加密