Я создал C программу, которая в основном отправляет UDP-пакеты в пункт назначения Linux (Ubuntu 18.04). Я пытаюсь отправить пакеты, размер которых превышает размер MTU сетевого интерфейса (и, следовательно, должен быть фрагментирован). Однако всякий раз, когда я пытаюсь это сделать, функция sendto()
возвращает -1
, и пакет никогда не отправляется. Я также указываю свои собственные заголовки IP + UDP. Из того, что я нашел в сети, фрагментация должна обрабатываться автоматически даже при передаче ваших собственных заголовков IP и UDP. Хотя я не смог найти много других с похожими проблемами. Я думал, что, возможно, мне нужно было какое-то время сделать l oop и проверить, сколько данных sendto()
на самом деле отправляет. Однако, как я уже говорил, функция возвращает -1
каждый раз только при отправке пакетов, размер которых превышает размер MTU.
Хочу отметить, что я также не привязываю сокет.
Вот как выглядят мои заголовки IP и UDP:
// Fill out IP and UDP headers.
iphdr->ihl = 5;
iphdr->frag_off = 0;
iphdr->version = 4;
iphdr->protocol = IPPROTO_UDP;
iphdr->tos = 16;
iphdr->ttl = 64;
iphdr->id = 0;
iphdr->check = 0;
iphdr->saddr = inet_addr(con->sIP);
iphdr->daddr = inet_addr(con->dIP);
iphdr->tot_len = sizeof(struct iphdr) + sizeof(struct udphdr) + len;
udphdr->uh_dport = htons(con->dPort);
udphdr->uh_sport = htons(port);
udphdr->len = htons(sizeof(struct udphdr) + len);
udphdr->check = 0;
iphdr->check = ip_csum((unsigned short *)buffer, sizeof(struct iphdr));
Я также планирую рассчитать контрольную сумму UDP (я планировал сделать это после устранения проблемы фрагментации).
Вот код, который я использовал для создания сокета:
// Create socket.
int sockfd, one = 1;
sockfd = socket(PF_INET, SOCK_RAW, IPPROTO_UDP);
// Check for socket error.
if (sockfd <= 0)
{
fprintf(stderr, "Socket() Error - %s\n", strerror(errno));
perror("socket");
exit(1);
}
// Assign sockfd.
con.sockfd = sockfd;
// Set socket option that tells the socket we want to send our own headers.
if (setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, &one, sizeof(one)) < 0)
{
fprintf(stderr, "SetSockOpt() Error - %s\n", strerror(errno));
perror("setsockopt");
// Close socket.
close(sockfd);
exit(1);
}
Я довольно плохо знаком с C и сетевым программированием. Поэтому я прошу прощения, если что-то упустил.
Если вам нужна дополнительная информация или код, пожалуйста, дайте мне знать.
Любая помощь высоко ценится и спасибо за ваше время!