我正在尝试编写一个代码(用于实验室),该代码以ICMP数据包(类型ICMP_ECHO)发送数据
这是我的发送功能:
int send_data(int sid, struct in_addr to, FILE*fp, int fraglen){
long flength;
struct icmp icmph;
struct sockaddr_in sa;
struct stat buf;
uint8_t *msg;
long i, max;
int snd,c,j,is_EOF = FALSE;
uint16_t csum;
memset(&icmph,0,sizeof(icmph));
memset(&sa,0,sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_addr = to;
if(fp == NULL){
perror("send_data : file pointer is NULL \n");
return FALSE;
}
if((msg = malloc((ICMP_HDRLEN+fraglen)*sizeof(uint8_t)))==NULL){
perror("send_data : failed to allocate memory \n");
return FALSE;
}
if(init_icmphdr(&icmph, ICMP_ECHO,0,0,0)==FALSE){
free(msg);
perror("send_data : failed to initialize icmp header \n");
return FALSE;
}
fstat(fileno(fp),&buf);
flength = buf.st_size;
uint8_t *data = msg+sizeof(uint8_t)*ICMP_HDRLEN;
max = (flength % fraglen == 0 ? flength/fraglen : flength/fraglen+1);
printf("sending data to %s \n",inet_ntoa(sa.sin_addr));
for(i = 0; i<max;i++){
memset(msg,0,ICMP_HDRLEN+fraglen);
if(init_icmphdr(&icmph,ICMP_ECHO,0,1,i)==FALSE){
perror("send_to : icmp header init failed \n");
return FALSE;
}
memcpy(msg,&icmph, ICMP_HDRLEN);
for(j=0;j<fraglen && is_EOF == FALSE;j++){
c = getc(fp);
if(c == EOF)
is_EOF = TRUE;
else
*(data+sizeof(uint8_t)*j) = c;
}
csum=ip_checksum(msg,ICMP_HDRLEN+fraglen); //Checksum and write it to package
memcpy(&icmph,msg,ICMP_HDRLEN);
icmph.icmp_cksum = csum;
memcpy(msg,&icmph,ICMP_HDRLEN);
printf("msg %lu checksum written :%" PRIu16 "\n", i,csum);
if((snd=sendto(sid,msg,ICMP_HDRLEN+fraglen,0,(struct sockaddr*)&sa,sizeof(sa)))<0){
printf("sending of data-msg %lu failed \n",i);
return FALSE;
}
printf("Sent %i Bytes \n", snd);
}
//Send final message
memset(&icmph,0,ICMP_HDRLEN);
memset(msg,0,ICMP_HDRLEN+fraglen);
init_icmphdr(&icmph,ICMP_ECHO,0,2,0); //ID 0 <=> stop transmission
memcpy(msg,&icmph,ICMP_HDRLEN);
csum = ip_checksum(msg,ICMP_HDRLEN+fraglen);
icmph.icmp_cksum = csum;
memcpy(msg,&icmph,ICMP_HDRLEN);
if((snd=sendto(sid,msg,ICMP_HDRLEN+fraglen,0,(struct sockaddr*)&sa,sizeof(sa)))<0){
printf("sending of data-msg %lu failed \n",i);
return FALSE;
}
free(msg);
return TRUE;
}
int main(int argc, char** argv){
struct in_addr dst;
FILE *fp;
int sid;
struct ifreq ifr;
if(argc < 4){
printf("To few args? \n");
return 1;
}
if((fp = fopen(argv[2],"r")) == NULL ){
printf("opening file failed \n");
return 1;
}
if((sid = socket(AF_INET,SOCK_RAW,IPPROTO_ICMP)) < 0){
printf("opening socket failed \n");
return 1;
}
printf("CLIENT SOCKET ID: %i \n", sid);
memset(&ifr,0,sizeof(ifr));
snprintf (ifr.ifr_name, sizeof (ifr.ifr_name), "%s", interface);
if (ioctl (sid, SIOCGIFINDEX, &ifr) < 0) { //Interface index
perror ("ioctl() failed to find interface ");
return (EXIT_FAILURE);
}
if (setsockopt (sid, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof (ifr)) < 0) {
perror ("setsockopt() failed to bind to interface "); //Bind to interface
return (EXIT_FAILURE);
}
if(inet_aton(argv[1],&dst)==0){
perror("invalid IP \n");
return (EXIT_FAILURE);
}
if(send_shake(sid,dst) != TRUE){
perror("send_shake failed \n");
return(EXIT_FAILURE);
}
printf("Sent shake \n");
if(recv_shake(sid,dst)==TRUE){
printf("shake made, sending data.. \n");
send_data(sid,dst,fp,atoi(argv[3]));
}
fclose(fp);
close(sid);
return 0;
}
我一直在尝试发送仅包含“ Hello!Hello!”的文本文件。在里面。 从我的角度来看,我有一些奇怪的错误。
以下是此函数的两次运行的输出:
1。
将数据发送到127.0.0.1
写入的味精0校验和:65300已发送69字节 写入的味精1校验和:64325已发送69字节
写入的味精2校验和:28063已发送69字节 发送数据消息3失败
2。
将数据发送到127.0.0.1
写入的味精0校验和:57116已发送69字节 写入的味精1校验和:56141已发送69字节
写入的味精2校验和:19879发送69字节 发送数据消息3失败\ n
所以,由于我要多次检查程序,所以3个程序包的校验和总是会变化。虽然在写包之前我清除了整个消息缓冲区 最后一次打包总是失败。
我还编码了一个接收已发送包裹的接收者。我总是在一台计算机上测试它们,使用原始套接字绑定到环回接口“ lo”
两个星期以来,我一直坐在这个小地方,这让我发疯。一些建议,将不胜感激:D