Литмир - Электронная Библиотека
Содержание  
A
A

15 void init_v6(void);

16 void proc_v4(char*, ssize_t, struct msghdr*, struct timeval*);

17 void proc_v6(char*, ssize_t., struct msghdr*, struct timeval*);

18 void send_v4(void);

19 void send_v6(void):

20 void readloop(void);

21 void sig_alrm(int);

22 void tv_sub(struct timeval*, struct timeval*);

23 struct proto {

24  void (*fproc)(char*, ssize_t, struct msghdr*, struct timeval*);

25  void (*fsend)(void);

26  void (*finit)(void);

27  struct sockaddr *sasend; /* структура sockaddr{} для отправки,

                                полученная от getaddrinfo */

28  struct sockaddr *sarecv; /* sockaddr{} для получения */

29  socklen_t salen; /* длина sockaddr{} */

30  int icmpproto; /* значение IPPROTO_xxx для ICMP */

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;

47  pr->sarecv = Calloc(1, ai->ai_addrlen);

48  pr->salen = ai->ai_addrlen;

49  readloop();

50  exit(0);

51 }

Определение структуры proto для IPv4 и IPv6
310
{"b":"225366","o":1}