繁体   English   中英

TCP校验和为0

[英]TCP checksum is 0

我有tcp标头的以下代码:

struct tcp_header {
    uint16_t tcp_sport;
    uint16_t tcp_dport;
    uint32_t tcp_th_seq;
    uint32_t tcp_ack;
    uint8_t tcp_off:4;
    uint8_t tcp_res:6;
    uint8_t tcp_uf:1, tcp_af:1, tcp_pf:1, tcp_rf:1, tcp_sf:1, tcp_ff:1;
    uint16_t tcp_win;
    uint16_t tcp_sum;
    uint16_t tcp_urp;
};

...

void decode_tcp(const unsigned char *header_start) {

    const struct tcp_header *tcp_hdr;

    tcp_hdr = (const struct tcp_header *)(header_start + ETHERNET_HEADER_SIZE + IP_HEADER_SIZE);

    printf("\n    TCP Header\n");

    printf("\tSource Port       : %u\n", ntohs(tcp_hdr->tcp_sport));
    printf("\tDestination Port  : %u\n", ntohs(tcp_hdr->tcp_dport));
    printf("\tSequence number   : %u\n", ntohl(tcp_hdr->tcp_th_seq));
    printf("\tAcknowledge number: %u\n", ntohl(tcp_hdr->tcp_ack));
    printf("\tOffset            : %d\n", tcp_hdr->tcp_off);
    printf("\tReserved          : %d\n", (unsigned int)tcp_hdr->tcp_res);
    printf("\tUrgent Flag       : %d\n", (unsigned int)tcp_hdr->tcp_uf);
    printf("\tAcknoledge Flag   : %d\n", (unsigned int)tcp_hdr->tcp_af);
    printf("\tPush Flag         : %d\n", (unsigned int)tcp_hdr->tcp_pf);
    printf("\tReset Flag        : %d\n", (unsigned int)tcp_hdr->tcp_rf);
    printf("\tSynchronise Flag  : %d\n", (unsigned int)tcp_hdr->tcp_sf);
    printf("\tFinish Flag       : %d\n", (unsigned int)tcp_hdr->tcp_ff);
    printf("\tWindow            : %d\n", ntohs(tcp_hdr->tcp_win));
    printf("\tChecksum          : %d\n", ntohs(tcp_hdr->tcp_sum));
    printf("\tUrgent Pointer    : %d", ntohs(tcp_hdr->tcp_urp));
}

我得到的输出是 在此输入图像描述

CHecksum是0,所以我认为有些事情是错误的。 你们能发现错误吗? 或者canchecksum应该是0?

sourceport也可以22?

这里使用的大多数转换说明符都是错误的:

printf("\tSource Port       : %u\n", ntohs(tcp_hdr->tcp_sport));
printf("\tDestination Port  : %u\n", ntohs(tcp_hdr->tcp_dport));
printf("\tSequence number   : %u\n", ntohl(tcp_hdr->tcp_th_seq));
printf("\tAcknowledge number: %u\n", ntohl(tcp_hdr->tcp_ack));
printf("\tOffset            : %d\n", tcp_hdr->tcp_off);
printf("\tReserved          : %d\n", (unsigned int)tcp_hdr->tcp_res);
printf("\tUrgent Flag       : %d\n", (unsigned int)tcp_hdr->tcp_uf);
printf("\tAcknoledge Flag   : %d\n", (unsigned int)tcp_hdr->tcp_af);
printf("\tPush Flag         : %d\n", (unsigned int)tcp_hdr->tcp_pf);
printf("\tReset Flag        : %d\n", (unsigned int)tcp_hdr->tcp_rf);
printf("\tSynchronise Flag  : %d\n", (unsigned int)tcp_hdr->tcp_sf);
printf("\tFinish Flag       : %d\n", (unsigned int)tcp_hdr->tcp_ff);
printf("\tWindow            : %d\n", ntohs(tcp_hdr->tcp_win));
printf("\tChecksum          : %d\n", ntohs(tcp_hdr->tcp_sum));
printf("\tUrgent Pointer    : %d", ntohs(tcp_hdr->tcp_urp));

它应该是:

printf("\tSource Port       : %hu\n", ntohs(tcp_hdr->tcp_sport));
printf("\tDestination Port  : %hu\n", ntohs(tcp_hdr->tcp_dport));
printf("\tSequence number   : %u\n", ntohl(tcp_hdr->tcp_th_seq));
printf("\tAcknowledge number: %u\n", ntohl(tcp_hdr->tcp_ack));
printf("\tOffset            : %hhu\n", tcp_hdr->tcp_off);
printf("\tReserved          : %u\n", (unsigned int)tcp_hdr->tcp_res);
printf("\tUrgent Flag       : %u\n", (unsigned int)tcp_hdr->tcp_uf);
printf("\tAcknoledge Flag   : %u\n", (unsigned int)tcp_hdr->tcp_af);
printf("\tPush Flag         : %u\n", (unsigned int)tcp_hdr->tcp_pf);
printf("\tReset Flag        : %u\n", (unsigned int)tcp_hdr->tcp_rf);
printf("\tSynchronise Flag  : %u\n", (unsigned int)tcp_hdr->tcp_sf);
printf("\tFinish Flag       : %u\n", (unsigned int)tcp_hdr->tcp_ff);
printf("\tWindow            : %hu\n", ntohs(tcp_hdr->tcp_win));
printf("\tChecksum          : %hu\n", ntohs(tcp_hdr->tcp_sum));
printf("\tUrgent Pointer    : %hu", ntohs(tcp_hdr->tcp_urp));

如果你将所有这些转换删除为unsigned int你可以使用hhu作为printf()转换说明符,因为所有这些变量都被定义为unsigned 8位值。

您的代码有一些问题:

  • 不要使用位域! 它们不能在不同的ABI中移植。
  • 确保结构被打包(例如通过__attribute__((__packed__))注释)。 ABI可以在其他属性之间添加填充。
  • tcp_hdr = (const struct tcp_header *)(header_start在读取/写入tcp_hdr字段时可能导致错位访问。上面的__packed__注释可以防止这种情况;或者,您可以复制(正确对齐的)局部变量中的内容。

我会添加一些健全性检查

BUILD_BUG_ON(offsetof(struct tcp_header, tcp_sum) != 0x10));

(请检查tcp rfc tcp_sum是否确实位于0x10位置!)

我认为你的TCP头定义有问题(这是24字节,但标准头是20)。 在系统上使用标准声明,也考虑对齐:

#include <netinet/tcp.h>

tcp头定义:

struct tcphdr {
    u_short th_sport;               /* source port */
    u_short th_dport;               /* destination port */
    tcp_seq th_seq;                 /* sequence number */
    tcp_seq th_ack;                 /* acknowledgement number */
#if __BYTE_ORDER == __LITTLE_ENDIAN
    u_int   th_x2:4,                /* (unused) */
        th_off:4;               /* data offset */
#endif
#if __BYTE_ORDER == __BIG_ENDIAN
    u_int   th_off:4,               /* data offset */
        th_x2:4;                /* (unused) */
#endif
    u_char  th_flags;
#define TH_FIN  0x01
#define TH_SYN  0x02
#define TH_RST  0x04
#define TH_PUSH 0x08
#define TH_ACK  0x10
#define TH_URG  0x20
#define TH_FLAGS (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG)

    u_short th_win;                 /* window */
    u_short th_sum;                 /* checksum */
    u_short th_urp;                 /* urgent pointer */
};

入境或出境? 如果启用了校验和卸载到NIC,则出站校验和可以为0 ...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM