LINUX.ORG.RU

а поясните за UDP

 


0

1

привет, ЛОР! Всем доброго вечера :)

а поясните мне плиз за такой кусочек кода:

ehdr =  (struct ethhdr *)buffer;
ip = (struct iphdr *)(ehdr + 1);
udp = (struct udphdr *)(ip + 1);
i = 0;
j = ntohs(udp->len) - sizeof(struct udphdr) - 1;

printf("Received %d bytes, udp->len = %d, udp->uh_ulen = %d\n", data_size, udp->len, udp->uh_ulen);

вывод моей фигни:

Received 118 bytes, udp->len = 12761, udp->uh_ulen = 12761

точнее, почему значение len у структуры такое дикое?

Потому что у тебя не тот пакет поймался? Алсо

udp = (struct udphdr *)(ip + 1);

Если у тебя в IP заголовке есть доп.хидеры, твой код тут говна поест. Не делай так.

hateyoufeel ★★★★★
()
Последнее исправление: hateyoufeel (всего исправлений: 1)

Оптимист ты однако.

Ты бы проверил для начал, что ehdr->h_proto == ETH_P_IP

Далее проверяем, что ip->version == 4

Потом проверяем, что ip->protocol == IPPROTO_UDP, а потом уже читал данные из udp->

Формально sizeof(struct iphdr) не является константой, так что

udp = (struct udphdr *)((char *)ip +ip->ihl*4)

vel ★★★★★
()
Последнее исправление: vel (всего исправлений: 1)
Ответ на: комментарий от vel

Оптимист ты однако

я, скорее, «плохо осведомленный пессимист» %)))

вот тут вроде всё работало (мои пакетики ловились), а почему сейчас не пашет стало ясно только с Вашими пояснениями :)

metawishmaster ★★★★★
() автор топика
Ответ на: комментарий от firkax

Ко всему сказанному выше добавлю что скорее всего там надо ntohs().

там числа одного порядка были (при подсчете контрольной суммы, но всегда на порялк выше ETH_FRAME_LEN)

metawishmaster ★★★★★
() автор топика
Ответ на: комментарий от metawishmaster
103.       printf("Received %d bytes, udp->len = %d, udp->uh_ulen = %d\n", data_size, udp->len, udp->uh_ulen);

uh_ulen и len это одно и тоже поле (нахрена это нужно?) и оно в сетевом представлении. Двумя строками выше используется ntohs() для его чтения.

Читай внимательно man 2 recvfrom. Судя по всему тебе досталась задача с подвохом.

vel ★★★★★
()
Последнее исправление: vel (всего исправлений: 1)
Ответ на: комментарий от IvanRia

ничего особо в коде не понял, но возможно, что при объявлении структуры надо использовать __attribute__((packed));, тогда поля структуры и сама структура не будет выравниваться по длине слова

да код по ссылке-то работает, у меня проблемы с «копипастом» его в другой проектик %)

metawishmaster ★★★★★
() автор топика
Ответ на: комментарий от metawishmaster

Код по ссылке кривой.

1. Он получает ВСЕ пакеты, а не только udp, как ты надеешься. так что проверяй ehdr->h_proto, ip->version, ip->protocol, а потом уже лезь в udp пакет.

2. В recvfrom/recv есть проблема с длиной пакета. Буфер берем 64к, а читаем только 1514 байт.

Есть способ читать только udp через raw_sock - повесить на сокет bpf-фильтр который пропускает только udp. Через «tcpdump -dd udp» можно получить код фильтра. Но это скорее всего будет не портабельно.

Возможно в данном коде есть подстава с vlan-трафиком - нужно учитывать наличие доп. заголовков в езернет-пакете.

vel ★★★★★
()
Ответ на: комментарий от vel
    if (ntohs(ehdr->h_proto) != ETH_P_IP) {
//    printf("h_proto(0x%x) != ETH_P_IP\n", ehdr->h_proto);
      return;
    }
    if (ntohs(ip->protocol) != IPPROTO_UDP) {
        printf("protocol(0x%x) != IPPROTO_UDP\n", ip->protocol);
        return;
    }


казалось бы это должно было бы отфильтровывать... но по-факту оно откдывает все что можно

metawishmaster ★★★★★
() автор топика
Последнее исправление: metawishmaster (всего исправлений: 2)
Ответ на: комментарий от metawishmaster
ntohs(ehdr->h_proto) != ETH_P_IP

это отбросит IPv6, так что ip->version вроде как можно не проверять.

А еще хорошо бы проверять КС заголовка ip!

ntohs(ip->protocol) != IPPROTO_UDP

Иди проспись! ip->protocol это байт! htons к нему не нужно применять.

vel ★★★★★
()