我是網絡編程的新手。在過去的幾天裏,我正在學習這一點。今天我試圖玩原始插座。一切順利。但是Ip校驗並沒有幫到我。不管我手動給iph->檢查的值是多少,而接收到的校驗和都不同。IP校驗和自動更改
其實我所做的是我創建了一個原始套接字C程序,它將使用原始套接字創建一個發送到環回接口的TCP數據包。我用wireshark捕獲了這個包。但是當我解釋接收到的數據包時,我發現無論我在程序中給出的校驗和值如何,它都顯示出一些不同的常數值。
這裏是我的代碼
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <errno.h>
//#include <linux/in.h>
unsigned short calculate_check_sum (unsigned short *buf, int nwords) {
unsigned long sum;
for (sum = 0; nwords > 0; nwords--) {
sum += *buf++;
}
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
return ~sum;
}
int main() {
int sockfd = socket (PF_INET, SOCK_RAW, 6);
if (sockfd < 0) {
perror ("socket failed: ");
return -1;
}
char packet[4096];
struct iphdr *iph = (struct iphdr *) packet;
struct tcphdr *tcph = (struct tcphdr *) packet + sizeof (struct iphdr);
//char *payload = packet + sizeof (struct iphdr) + sizeof (struct tcphdr);
memset (packet, 0, 4096);
//strcpy (payload, "helllo");
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons (1330);
inet_pton (AF_INET, "127.0.0.1", &(sin.sin_addr));
/* TESTING
char var[123];
inet_ntop (AF_INET, &(sin.sin_addr), var, INET_ADDRSTRLEN);
printf ("%s\n", var);
*/
//WRITING ON IP HEADER
iph->ihl = 5;
iph->version = 4;
iph->tos = 0;
iph->tot_len = sizeof (struct iphdr) + sizeof (struct tcphdr); //+ strlen (payload);
iph->id = htons (1234);
iph->frag_off = 0;
iph->ttl = 225;
iph->protocol = 6;
iph->check = 0;
iph->saddr = inet_addr ("43.88.80.72");
iph->daddr = sin.sin_addr.s_addr;
//WRITING TCP HEADER
tcph->source = htons (1234);
tcph->dest = htons (1330);
tcph->seq = random();
tcph->ack_seq = 0;
tcph->res1 = 0;
tcph->doff = 0;
tcph->syn = 1;
tcph->window = htons (1000);
tcph->check = 0;
tcph->urg_ptr = 0;
//CALCULATE CHECK SUM AND PUT IN THEIR PLACES
//iph->check = calculate_check_sum ((unsigned short *) packet, iph->tot_len >> 1);
iph->check = 0xffff;
int one = 1;
if (setsockopt (sockfd, 0, IP_HDRINCL, &one, sizeof (one)) < 0) {
perror ("setsockopt faild: ");
return -1;
}
int ret = sendto (sockfd, packet, iph->tot_len, 0, (struct sockaddr *) &sin, sizeof (sin));
if (ret < 0) {
perror ("sendto failed: ");
return -1;
}
return 0;
}
這是Wireshark的捕獲流 00000000000000000000000008004500002804d20000e106 * da5c * 2b5850487f0000010000000000000000000000000000000000000000
這裏5cda(在astrics之間)是我得到的校驗。
也代替Wireshark的,我已經創建了自己的捕捉程序如下,
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/tcp.h>
#include <netinet/ip.h>
#include <string.h>
#include <errno.h>
int main() {
int fd = socket (PF_INET, SOCK_RAW, 6);
int len_msg;
if (fd < 0)
perror ("socket failed: ");
char buf [8192];
memset (buf, 0, 8192);
struct sockaddr_in sock_addr;
inet_pton (AF_INET, "127.0.0.1", &(sock_addr.sin_addr));
int len = sizeof (struct sockaddr);
printf ("%s\n",inet_ntoa(sock_addr.sin_addr.s_addr));
if (bind (fd, (struct sockaddr *) &sock_addr, len)) {
perror ("bind failed: ");
return -1;
}
while ((len_msg = recvfrom (fd, buf, 8192, 0, (struct sockaddr *) &sock_addr, (socklen_t *)&len)) != -1) {
//printf ("%s\n", buf+sizeof(struct iphdr)+sizeof(struct tcphdr));
//printf ("%s\n", buf);
int i;
printf ("%d\n", len_msg);
for (i = 0; i < len_msg; i += 1)
printf ("%x ", (unsigned char) *(buf + i));
printf ("\n");
printf ("*****************************************\n");
struct iphdr *iph = (struct iphdr *) buf;
printf ("checksum: %x\n", iph->check);
break;
}
printf ("%s\n",inet_ntoa(sock_addr.sin_addr.s_addr));
return 0;
}
不過我正在檢查的值相同。無論我在第一個程序中輸入什麼值,作爲校驗和,捕獲的數據包只有值0x5cda作爲其校驗和。
我正在使用CentOS。內核本身在數據包中做了什麼改變? 請幫助我。
由於提前