奇妙な理由で、TCP チェックサムを正しく検証できません。IP と UDP のチェックサムをチェックするコードがあり、完全に正常に動作しますが、TCP の場合、ロジックに問題があります。
これらのヘッダーの構造体定義は、データを完全に読み取ることができるため問題ありません (wireshark から検証済み)。私が抱えている唯一の問題は、TCP チェックサムの場合、チェックサムが実際に正しいかどうかを確認できないことです。私がこれを間違っている場所について何か考えはありますか?
非常に高く評価。
チェックサム機能
unsigned short in_cksum(unsigned short *addr,int len)
{
register int sum = 0;
u_short answer = 0;
register u_short *w = addr;
register int nleft = len;
/*
* Our algorithm is simple, using a 32 bit accumulator (sum), we add
* sequential 16 bit words to it, and at the end, fold back all the
* carry bits from the top 16 bits into the lower 16 bits.
*/
while (nleft > 1) {
sum += *w++;
nleft -= 2;
}
if (nleft == 1) {
*(u_char *)(&answer) = *(u_char *)w ;
sum += answer;
}
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
answer = ~sum;
return(answer);
}
read TCP 関数 (古い、編集されたバージョンを確認)
/* packets are read using the pcap libraries */
void readTCP(const u_char *packets) {
struct TCP_Header *tcp = (struct TCP_Header*) (packets + sizeof(struct Ethernet_Header) + sizeof(struct IP_Header));
struct IP_Header *ip = (struct IP_Header*) (packets + sizeof(struct Ethernet_Header));
struct TCP_Pseudo tcpPseudo;
char tcpcsumblock[sizeof(struct TCP_Pseudo) + sizeof(struct TCP_Header)];
/* tcp pseudo header */
memset(&tcpPseudo, 0, sizeof(struct TCP_Pseudo));
tcpPseudo.source_ip = ip->source_ip.s_addr;
tcpPseudo.destination_ip = ip->destination_ip.s_addr;
tcpPseudo.zero = 0;
tcpPseudo.protocol = 6;
tcpPseudo.length = htons(sizeof(struct TCP_Header));
/* grab tcp checksum and reset it */
int tcpCheckSum = htons(tcp->tcp_checksum);
tcp->tcp_checksum = 0;
/* place the data from the tcp pseudo infront of the tcp header */
memcpy(tcpcsumblock, &tcpPseudo, sizeof(TCPPseudoHeader));
memcpy(tcpcsumblock+sizeof(TCPPseudoHeader),tcp, sizeof(TCPHeader));
/* here is the issue, the checksum that i'm calculating isn't the correct checksum (i checked this by examing the packets from wireshark */
u_short checksum = in_cksum((unsigned short *)tcpcsumblock, sizeof(tcpcsumblock));
}
==編集==
新しい TCP 関数
/* packets are read using the pcap libraries */
void readTCP(const u_char *packets) {
struct TCP_Header *tcp = (struct TCP_Header*) (packets + sizeof(struct Ethernet_Header) + sizeof(struct IP_Header));
struct IP_Header *ip = (struct IP_Header*) (packets + sizeof(struct Ethernet_Header));
struct TCP_Pseudo tcpPseudo;
/* tcp pseudo header */
memset(&tcpPseudo, 0, sizeof(struct TCP_Pseudo));
tcpPseudo.source_ip = ip->source_ip;
tcpPseudo.destination_ip = ip->destination_ip;
tcpPseudo.zero = 0;
tcpPseudo.protocol = 6;
tcpPseudo.len = htons(ip->ip_len - (ip->ip_hdr_len * 4));
int len = sizeof(struct TCP_Pseudo) + tcpPseudo.len;
u_char tcpcsumblock[len];
memcpy(tcpcsumblock, &tcpPseudo, sizeof(struct TCP_Pseudo));
memcpy(tcpcsumblock + sizeof(struct TCP_Pseudo), (packets + sizeof(struct Ethernet_Header) + sizeof(struct IP_Header)), tcpPseudo.len);
/* here is the issue, the checksum that i'm calculating isn't the correct checksum (i checked this by examing the packets from wireshark */
u_short checksum = in_cksum((unsigned short *)ps_tcp, len);
char *cs = checksum ? "Invalid Checksum!" : "Valid!";
}
IP ヘッダー
typedef struct IP_Header {
#if __BYTE_ORDER__ == __LITTLE_ENDIAN__
uint8_t ip_hdr_len:4; /* header length */
uint8_t ip_version:4; /* ip version */
#else
uint8_t ip_version:4; /* ip version */
uint8_t ip_hdr_len:4; /* The IP header length */
#endif
uint8_t ip_tos; /* type of service */
uint16_t ip_len; /* total length */
uint16_t ip_id; /* identification */
uint16_t ip_off; /* fragment offset field */
#define IP_DF 0x4000 /* dont fragment flag */
#define IP_MF 0x2000 /* more fragments flag */
#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
uint8_t ip_ttl; /* time to live */
uint8_t ip_p; /* protocol */
uint16_t ip_sum; /* checksum */
struct in_addr ip_src, ip_dst; /* source and dest address */
} __attribute__ ((packed));
TCPヘッダー
typedef struct TCP_Header {
uint16_t tcp_source_port; /* source port */
uint16_t tcp_dest_port; /* destination port */
uint32_t tcp_seq; /* sequence */
uint32_t tcp_ack; /* acknowledgement number */
uint8_t tcp_offest; /* data offset */
#define TH_OFF(th) (((th)->th_offx2 & 0xf0) >> 4)
uint8_t tcp_flags; /* 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_ECE 0x40
#define TH_CWR 0x80
#define TH_NS 0x100
#define TH_RS 0xE00
uint16_t tcp_window; /* window */
uint16_t tcp_sum; /* checksum */
uint16_t tcp_urp; /* urgent pointer */
} __attribute__ ((packed));
tcp 疑似ヘッダー
typedef struct TCP_Pseudo {
struct in_addr src_ip; /* source ip */
struct in_addr dest_ip; /* destination ip */
uint8_t zeroes; /* = 0 */
uint8_t protocol; /* = 6 */
uint16_t len; /* length of TCPHeader */
} __attribute__ ((packed));