Шрифт:
31 } *pr;
32 #ifdef IPV6
33 #include <netinet/ip6.h>
34 #include <netinet/icmp6.h>
35 #endif
Подключение заголовочных файлов IPv4 и ICMPv4
1-22
Подключаются основные заголовочные файлы IPv4 и ICMPv4, определяются некоторые глобальные переменные и прототипы функций. Определение структуры proto
23-31
Для обработки различий между IPv4 и IPv6 используется структура proto
. Данная структура содержит два указателя на функции, два указателя на структуры адреса сокета, размер структуры адреса сокета и значение протокола для ICMP. Глобальный указатель pr
будет указывать на одну из этих структур, которая будет инициализироваться для IPv4 или IPv6. Подключение заголовочных файлов IPv6 и ICMPv6
32-35
Подключаются два заголовочных файла, определяющие структуры и константы IPv6 и ICMPv6 (RFC 3542 [114]). Функция
main
приведена в листинге 28.3. Листинг 28.3. Функция main
//ping/main.c
1 #include "ping.h"
2 struct proto proto_v4 =
3 { proc_v4, send_v4, NULL, NULL, NULL, 0, IPPROTO_ICMP };
4 #ifdef IPV6
5 struct proto proto_v6 =
6 { proc_v6, send_v6, init_v6, NULL, NULL, 0, IPPROTO_ICMPV6 };
7 #endif
8 int datalen = 56; /* размер данных в эхо-запросе ICMP */
9 int
10 main(int argc, char **argv)
11 {
12 int c;
13 struct addrinfo *ai;
14 char *h;
15 opterr = 0; /* отключаем запись сообщений getopt в stderr */
16 while ((с = getopt(argc, argv, "v")) != -1) {
17 switch (c) {
18 case 'v':
19 verbose++;
20 break;
21 case '?':
22 err_quit("unrecognized option %c", c);
23 }
24 }
25 if (optind != argc-1)
26 err_quit("usage: ping [ -v ] <hostname>");
27 host = argv[optind];
28 pid = getpid & 0xffff; /* поле идентификатора ICMP имеет размер 16 бит */
29 Signal(SIGALRM, sig_alrm);
30 ai = Host_serv(host, NULL, 0, 0);
31 h = Sock_ntop_host(ai->ai_addr, ai->ai_addrlen);
32 printf("PING %s (%s): %d data bytes\n",
33 ai->ai_canonname ? ai->ai_canonname : h, h, datalen);
34 /* инициализация в соответствии с протоколом */
35 if (ai->ai_family == AF_INET) {
36 pr = &proto_v4;
37 #ifdef IPV6
38 } else if (ai->ai_family == AF_INET6) {
39 pr = &proto_v6;
40 if (IN6_IS_ADDR_V4MAPPED(&(((struct sockaddr_in6*)
41 ai->ai_addr)->sin6_addr)))
42 err_quit("cannot ping IPv4-mapped IPv6 address");
43 #endif
44 } else
45 err_quit("unknown address family %d", ai->ai_family);
46 pr->sasend = ai->ai_addr;