Написание базового скрипта traceroute на C

Мне нужно написать скрипт trceroute, но я не уверен, что мои попытки верны.

Прямо сейчас я делаю это так (пожалуйста, поправьте меня, если я делаю неправильно или неуклюже):

  1. Получил структуру для ip- и udpheader
  2. Функция контрольной суммы
  3. Открытие 2-х сокетов: один для отправки UDP-пакетов в режиме SOCK_RAW (для манипулирования ttl) и один для приема ICMP-ответов от роутеров.
  4. Использование sendto() для отправки пакета UDP
  5. Не знаете, как получить и обработать ответ ICMP

Есть ли более удобные способы изменить TTL, чем использование sock_raw, где я должен сам определять все заголовки? Какие параметры следует использовать для socket() при открытии ICMP sock? Как получить ICMP-ответ?


person d.hill    schedule 03.02.2011    source источник


Ответы (2)


На какую платформу вы ориентируетесь? Вот разновидность BSD из исходного кода OpenBSD. :

if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0)
    err(5, "icmp socket");
if ((sndsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
    err(5, "raw socket");

Я считаю, что в Linux вам нужно использовать IP_RECVERR и recvmsg(2) с MSG_ERRQUEUE, см. ip(7).

person Nikolai Fetissov    schedule 03.02.2011
comment
Спасибо за ответ. Это немного продвинуло меня вперед. - person d.hill; 03.02.2011

Что касается установки TTL, вы можете использовать setsockopt(). Вот выдержка из исходного кода iputils для ping в Linux:

if (setsockopt(icmp_sock, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, 1) == -1) {
    perror ("ping: can't set multicast time-to-live");
    exit(2);
}

if (setsockopt(icmp_sock, IPPROTO_IP, IP_TTL, &ittl, sizeof(ittl)) == -1) {
    perror ("ping: can't set unicast time-to-live");
    exit(2);
}
person thkala    schedule 03.02.2011
comment
Спасибо, вроде стало намного легче. - person d.hill; 03.02.2011