我有tcp header的后续代码:
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?
源端口也可以22?
答案 0 :(得分:1)
这里使用的大多数转换说明符都是错误的:
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比特值。
答案 1 :(得分:1)
您的代码存在一些问题:
__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位置!)
答案 2 :(得分:0)
我认为您的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 */
};
答案 3 :(得分:0)
入境或出境?如果启用校验和卸载到NIC,则出站校验和可以为0 ...