Я пытаюсь написать код (для лаборатории), который отправляет данные в пакетах 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
msg 0 контрольная сумма написана: 65300 отправлено 69 байт
Сообщение контрольной суммы сообщения 1: 64325 Отправлено 69 байт
msg 2 контрольная сумма написана: 28063 отправлено 69 байт
отправка данных-сообщения 3 не удалась
2
отправка данных на 127.0.0.1
msg 0 контрольная сумма написана: 57116 отправлено 69 байт
Сообщение контрольной суммы сообщения 1: 56141 Отправлено 69 байт
msg 2 контрольная сумма написана: 19879 отправлено 69 байт
отправка данных-сообщения 3 не удалась \ n
ТАК, так как я проверяю программу несколько раз, контрольные суммы 3 пакетов всегда меняются. Хотя перед записью в пакет я очищаю весь буфер сообщений
Последний пакет всегда терпит неудачу.
Я также закодировал приемник, который получает отправленные посылки. Я всегда проверяю их на одном компьютере, используя необработанные сокеты, привязываемые к интерфейсу обратной связи "lo"
Я сижу на этом маленьком кусочке уже две недели, и он сводит меня с ума. Некоторые советы будут оценены: D