UNIX: разработка сетевых приложений
Часть 333 из 399 Информация о книге
14 extern socklen_t destlen, locallen;15 extern int datalink;16 extern char *device;17 extern pcap_t *pd;18 extern int rawfd;19 extern int snaplen;20 extern int verbose;21 extern int zerosum;22 /* прототипы функций */23 void cleanup(int);24 char *next_pcap(int*);25 void open_output(void);26 void open_pcap(void);27 void send_dns_query(void);28 void test_udp(void);29 void udp_write(char*, int);30 struct udpiphdr *udp_read(void);Для работы с полями заголовков IP и UDP требуются дополнительные заголовочные файлы Интернета.3-10Мы определяем некоторые глобальные переменные и прототипы для своих собственных функций, которые вскоре покажем.11-30Первая часть функции
показана в листинге 29.2.mainЛистинг 29.2. Функция main: определения
//udpcksum/main.c1 #include "udpcksum.h"2 /* определение глобальных переменных */3 struct sockaddr *dest, *local;4 struct sockaddr_in locallookup;5 socklen_t destlen, locallen;6 int datalink; /* из pcap_datalink(), файл <net/bpf.h> */7 char *device; /* устройство pcap */8 pcap_t *pd; /* указатель на структуру захваченных пакетов */9 int rawfd; /* символьный сокет */10 int snaplen = 200; /* объем захваченных данных */11 int verbose;12 int zerosum; /* отправка UDP-запроса без контрольной суммы */13 static void usage(const char*);14 int15 main(int argc, char *argv[])16 {17 int c, lopt=0;18 char *ptr, localname[1024], *localport;19 struct addrinfo *aip;В следующей части функции
, представленной в листинге 29.3, обрабатываются аргументы командной строки.mainЛистинг 29.3. Функция main: обработка аргументов командной строки
//udpcksum/main.c20 opterr = 0; /* отключаем запись сообщений getopt() в stderr */21 while ((с = getopt(argc, argv, "0i:l:v")) != -1) {22 switch (с) {23 case '0':24 zerosum = 1;25 break;26 case 'i';27 device = optarg; /* устройство pcap */28 break;29 case 'l'; /* локальный IP адрес и номер порта; a.b.c.d.p */30 if ((ptr = strrchr(optarg, '.')) == NULL)31 usage("invalid -l option");32 *ptr++ = 0; /* нуль заменяет последнюю точку. */33 local port = ptr; /* имя сервиса или номер порта */34 strncpy(localname, optarg, sizeof(localname));35 lopt = 1;36 break;37 case 'v':38 verbose = 1;39 break;40 case '?':41 usage("unrecognized option");42 }43 }Обработка аргументов командной строкиМы вызываем функцию20-25для обработки аргументов командной строки. С помощью параметраgetoptмы посылаем запросы UDP без контрольной суммы UDP, чтобы выяснить, обрабатываются ли эти дейтаграммы сервером иначе, чем дейтаграммы с контрольной суммой.-0Параметр26позволяет нам задать интерфейс, на котором будут приниматься ответы сервера. Если этот интерфейс не будет задан, библиотека для захвата пакетов выберет какой-либо интерфейс самостоятельно, но в случае узла с несколькими сетевыми интерфейсами этот выбор может оказаться некорректным. В этом заключается одно из различий между считыванием из обычного сокета и из устройства для захвата пакетов: в первом случае мы можем указать универсальный локальный адрес, что позволяет получать пакеты, прибывающие на любой из сетевых интерфейсов. Но во втором случае при работе с устройством для захвата пакетов мы можем получать пакеты, прибывающие только на конкретный интерфейс.-iПРИМЕЧАНИЕМожно отметить, что для пакетных сокетов Linux захват пакетов не ограничен одним устройством. Тем не менее библиотека libcap обеспечивает фильтрацию либо по умолчанию, либо согласно заданному нами параметру -i.
Параметр29-36позволяет нам задать IP-адрес отправителя и номер порта. В качестве номера порта (или названия службы) берется строка, следующая за последней точкой, а IP-адресом является все, что расположено перед последней точкой.-lПоследняя часть функции
показана в листинге 29.4.mainЛистинг 29.4. Функция main: преобразование имен узлов и названий служб, создание сокета
//udpcksum/main.c