UNIX: разработка сетевых приложений
Часть 316 из 399 Информация о книге
36 struct sockaddr *sarecv; /* структура sockaddr{} для получения */37 struct sockaddr *salast; /* последняя структура sockaddr{} для получения */38 struct sockaddr *sabind; /* структура sockaddr{} для связыванияпорта отправителя*/39 socklen_t salen; /* длина структур sockaddr{}s */40 int icmpproto; /* значение IPPROTO_xxx для ICMP */41 int ttl level; /* значение аргумента level функцииsetsockopt() для задания TTL */42 int ttloptname; /* значение аргумента name функцииsetsockopt() для задания TTL */43 } *pr;44 #ifdef IPV645 #include "ip6.h" /* должно быть <netinet/ip6.h> */46 #include "icmp6.h" /* должно быть <netinet/icmp6.h> */47 #endifПодключаются стандартные заголовочные файлы IPv4, определяющие структуры и константы IPv4, ICMPv4 и UDP. Структура1-11определяет часть посылаемой UDP-дейтаграммы, содержащую собственно данные, но, как мы увидим дальше, нам никогда не придется исследовать эти данные. Они отсылаются в основном для целей отладки.recОпределение структуры protoКак и в программе32-43, описанной в предыдущем разделе, мы обрабатываем различие между протоколами IPv4 и IPv6, определяя структуруping, которая содержит указатели на функции, указатели на структуры адресов сокетов и другие константы, различные для двух версий IP. Глобальная переменнаяprotoбудет установлена как указатель на одну из этих структур, инициализированных либо для IPv4, либо для IPv6, после того как адрес получателя будет обработан функциейpr(поскольку именно адрес получателя определяет, какая версия используется — IPv4 или IPv6).mainПодключение заголовочных файлов IPv6Подключаются заголовочные файлы, определяющие структуры и константы IPv6 и ICMPv6.44-47Функция
приведена в листинге 28.14. Она обрабатывает аргументы командной строки, инициализирует указательmainлибо для IPv4, либо для IPv6 и вызывает нашу функциюpr.traceloopЛистинг 28.14. Функция main программы traceroute
//traceroute/main.c1 #include "trace.h"2 struct proto proto_v4 =3 {icmpcode_v4, recv_v4, NULL, NULL, NULL, NULL, 0,4 IPPROTO_ICMP, IPPROTO_IP, IP_TTL};5 #ifdef IPV66 struct proto proto_v6 =7 {icmpcode_v6, recv_v6, NULL, NULL, NULL, NULL, 0,8 IPPROTO_ICMPV6, IPPROTO_IPV6, IPV6_UNICAST_HOPS};9 #endif10 int datalen = sizeof(struct rec); /* значения по умолчанию */11 int max_ttl = 30;12 int nprobes = 3;13 u_short dport = 32768 + 666;14 int15 main(int argc, char **argv)16 {17 int c;18 struct addrinfo *ai;19 opterr = 0; /* чтобы функция getopt() не записывала в stderr */20 while ((с = getopt(argc, argv, "m:v")) != -1) {21 switch (c) {22 case 'm':23 if ((max_ttl = atoi(optarg)) <= 1)24 err_quit("invalid -m value");25 break;26 case 'v':27 verbose++;28 break;29 case '?':30 err_quit("unrecognized option: %c", c);31 }32 }33 if (optind != argc - 1)34 err_quit("usage: traceroute [ -m <maxttl> -v ] <hostname>");35 host = argv[optind];36 pid = getpid();37 Signal(SIGALRM, sig_alrm);38 ai = Host_serv(host, NULL, 0, 0);39 printf("traceroute to %s (%s): %d hops max, %d data bytes\n",40 ai->ai_canonname,41 Sock_ntop_host(ai->ai_addr, ai->ai_addrlen);42 max_ttl, datalen);43 /* инициализация в зависимости от протокола */44 if (ai->ai_family == AF_INET) {45 pr = &proto_v4;46 #ifdef IPV647 } else if (ai->ai_family == AF_INET6) {48 pr = &proto_v6;49 if (IN6_IS_ADDR_V4MAPPED50 (&(((struct sockaddr_in6*)ai->ai_addr)->sin6_addr)))51 err_quit("cannot traceroute IPv4-mapped IPv6 address");