c - TCP头端口号偶尔为0

标签 c tcp header

我正在尝试编写一个简单的应用程序来输出 dst 和 src TCP 端口号。为了进行测试,我尝试将 pcap 过滤器应用于仅嗅探进出端口 80 的数据包。但是,我不断获得端口号 0,尽管一切对我来说都是正确的。大约 10% 的情况下,我会得到 5 位数字的端口号。谁能给我任何关于我可能做错了什么的提示?

#include<pcap.h>
#include<stdio.h>
#include<net/ethernet.h>
#include<netinet/ip.h>
#include<netinet/tcp.h>
#include<arpa/inet.h>

void handle_packet(u_char* args, const struct pcap_pkthdr* pkthdr, const u_char* p)
{
    struct iphdr* ip_hdr;
    struct tcphdr* tcp_hdr;

    ip_hdr = (struct iphdr*) (p+sizeof(struct ether_header));
    tcp_hdr = (struct tcphdr*) (ip_hdr+sizeof(struct iphdr));
    printf("src:%d\n", ntohs(tcp_hdr->source));
    printf("dst:%d\n", ntohs(tcp_hdr->dest));
}

int main(int argc, char** argv)
{
    pcap_t *handle;                /* Session handle */
    char *dev;                     /* The device to sniff on */
    char errbuf[PCAP_ERRBUF_SIZE]; /* Error string */
    struct bpf_program filter;     /* The compiled filter */
    char filter_app[] = "tcp port 80"; /* The filter expression */
    bpf_u_int32 mask;              /* Our netmask */
    bpf_u_int32 net;               /* Our IP */

    /* Define the device */
    dev = pcap_lookupdev(errbuf);

    /* Find the properties for the device */
    pcap_lookupnet(dev, &net, &mask, errbuf);

    /* Open the session in promiscuous mode */
    handle = pcap_open_live(dev, BUFSIZ, 0, 0, errbuf);

    /* Compile and apply the filter */
    pcap_compile(handle, &filter, filter_app, 0, net);
    pcap_setfilter(handle, &filter);

    pcap_loop(handle, 10, handle_packet, NULL);

    pcap_close(handle);
    return(0);
}

最佳答案

这里有两个问题。首先,请记住,C 中的指针算术是按比例缩放的。所以,当你说这样的话:

tcp_hdr = (struct tcphdr*) (ip_hdr+sizeof(struct iphdr));

事实上,您前进的字节数比您预期的要多得多(准确地说是sizeof(struct iphdr) * sizeof(struct iphdr))。为了实现你想要的,你可以说:

tcp_hdr = (struct tcphdr*) &ip_hdr[1];

但这也行不通。 IP header 没有固定长度。相反,您应该检查 header 的 ihl字段和计算应该看起来更像这样:

tcp_hdr = (struct tcphdr*) ((char*)ip_hdr + 4*ip_hdr->ihl); /* ihl is the number of 32-bit words in the header */

警告:我不确定以太网帧以及它们的 header 是否有固定长度。您还需要验证这一点。

关于c - TCP头端口号偶尔为0,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15178746/

相关文章:

tcp - 将 BufferedReader.readLine() 与套接字一起使用并陷入无限循环

java - 套接字连接问题

c++ - 如何在头文件中组织代码实体?

c - 在 Windows x64 上访问 char** 的内容会导致异常

c - FreeBSD POSIX C Oracle API

c - 在C中返回一个指针

sockets - 如何配置 EC2 安全组以允许通过公共(public) IP 地址进行环回?

winapi - ERROR_PENDING 在哪里定义?

html - 如何在标题中并排放置两个图像

c - C 指针数组中的负索引