Фрагментация пакетов с необработанными сокетами + заголовки IP / UDP - PullRequest
0 голосов
/ 26 февраля 2020

Я создал 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 и сетевым программированием. Поэтому я прошу прощения, если что-то упустил.

Если вам нужна дополнительная информация или код, пожалуйста, дайте мне знать.

Любая помощь высоко ценится и спасибо за ваше время!

...