Knigi-for.me

Уильям Стивенс - UNIX: разработка сетевых приложений

Тут можно читать бесплатно Уильям Стивенс - UNIX: разработка сетевых приложений. Жанр: Программное обеспечение издательство -, год -. Так же Вы можете читать полную версию (весь текст) онлайн без регистрации и SMS на сайте knigi-for.me (knigi for me) или прочесть краткое содержание, предисловие (аннотацию), описание и ознакомиться с отзывами (комментариями) о произведении.

48      client[i].family == AF_INET6 &&

49      client[i].lport == sport) {


50      bzero(&dest, sizeof(dest));

51      dest.sin6_family = AF_INET6;

52 #ifdef HAVE_SOCKADDR_SA_LEN

53      dest.sin6_len = sizeof(dest);

54 #endif

55      memcpy(&dest.sin6_addr, &hip6->ip6_dst,

56       sizeof(struct in6_addr));

57      dest.sin6_port = udp->uh_dport;


58      icmpd_err.icmpd_type = icmp6->icmp6_type;

59      icmpd_err.icmpd_code = icmp6->icmp6_code;

60      icmpd_err.icmpd_len = sizeof(struct sockaddr_in6);

61      memcpy(&icmpd_err.icmpd_dest, &dest, sizeof(dest));


62      /* преобразование типа и кода ICMPv6 к значению errno */

63      icmpd_err.icmpd_errno = EHOSTUNREACH; /* по умолчанию */

64      if (icmp6->icmp6_type == ICMP6_DST_UNREACH &&

65       icmp6->icmp6_code ICMP6_DST_UNREACH_NOPORT)

66       icmpd_err.icmpd_errno = ECONNREFUSED;

67      if (icmp6->icmp6_type == ICMP6_PACKET_TOO_BIG)

68       icmpd_err.icmpd_errno = EMSGSIZE;

69      Write(client[i].connfd, &icmpd_err, sizeof(icmpd_err));

70     }

71    }

72   }

73  }

74  return(--nready);

75 #endif

76 }

28.8. Резюме

Символьные сокеты обеспечивают три возможности:

1. Чтение и запись пакетов ICMPv4, IGMPv4 и ICMPv6.

2. Чтение и запись IP-дейтаграммы с полем протокола, которое не обрабатывается ядром.

3. Формирование своих собственных заголовков IPv4, обычно используемых в диагностических целях (или, к сожалению, хакерами).

Два традиционных диагностических средства — программы ping и traceroute — используют символьные сокеты. Мы разработали наши собственные версии этих программ, поддерживающие обе версии протокола — и IPv4, и IPv6. Также нами разработан наш собственный демон icmpd, который обеспечивает доступ к сообщениям об ошибках ICMP через сокет UDP. Данный пример также иллюстрирует передачу дескриптора через доменный сокет Unix между неродственными клиентом и сервером.

Упражнения

1. В этой главе говорилось, что почти все поля заголовка IPv6 и все дополнительные заголовки доступны приложению через параметры сокета или вспомогательные данные. Какая информация из дейтаграммы IPv6 не доступна приложению?

2. Что произойдет в листинге 28.30, если по какой-либо причине клиент перестанет производить считывание из своего доменного сокета Unix и демон icmpd накопит множество сообщений для данного клиента? В чем заключается простейшее решение этой проблемы?

3. Если задать нашей программе ping адрес широковещательной передачи, направленный в подсеть, она будет работать. То есть широковещательный эхо- запрос ICMP посылается как широковещательный запрос канального уровня, даже если мы не установим параметр сокета SO_BROADCAST. Почему?

4. Что произойдет с программой ping, если мы запустим ее на узле с несколькими интерфейсами, а в качестве аргумента имени узла возьмем групповой адрес 224.0.0.1?

Глава 29

Доступ к канальному уровню

29.1. Введение

В настоящее время большинство операционных систем позволяют приложению получать доступ к канальному уровню. Это подразумевает следующие возможности:

1. Отслеживание пакетов, принимаемых на канальном уровне, что, в свою очередь, позволяет запускать такие программы, как tcpdump, на обычных компьютерных системах (а не только на специальных аппаратных устройствах для отслеживания пакетов). Если добавить к этому способность сетевого интерфейса работать в смешанном режиме (promiscuous mode), приложение сможет отслеживать все пакеты, проходящие по локальному кабелю, а не только предназначенные для того узла, на котором работает эта программа.

ПРИМЕЧАНИЕ

Эта возможность не так полезна в коммутируемых сетях, которые получили широкое распространение в последнее время. Дело в том, что коммутатор пропускает трафик на конкретный порт только в том случае, если этот трафик адресован конкретному устройству или устройствам, подключенным к этому порту, каким бы трафик ни был: направленным, широковещательным или многоадресным. Для того чтобы получать трафик, передаваемый через другие порты коммутатора, нужно сначала переключить свой порт коммутатора в режим контроля (monitor mode или port mirroring). Заметьте, что многие устройства, которые обычно не считают коммутаторами, на самом деле являются таковыми. Например, двухскоростной концентратор 10/100 обычно является двухпортовым коммутатором: один порт для сетей, работающих на 100 Мбит/с, другой — для сетей на 10 Мбит/с.

2. Возможность запуска определенных программ как обычных приложений, а не как частей ядра. Скажем, большинство версий Unix сервера RARP — это обычные приложения, которые считывают запросы RARP с канального уровня (запросы RARP не являются дейтаграммами IP), а затем передают ответы также на канальный уровень.

Три наиболее распространенных средства получения доступа к канальному уровню в Unix — это пакетный фильтр BSD (BPF, BSD Packet Filter), DLPI в SVR4 (Datalink Provider Interface — интерфейс поставщика канального уровня) и интерфейс пакетных сокетов Linux (SOCK_PACKET). Мы приводим в этой главе обзор перечисленных средств, а затем описываем libcap — открытую для свободного доступа библиотеку, содержащую функции для захвата пакетов. Эта библиотека работает со всеми тремя перечисленными средствами, и использование библиотеки позволяет сделать наши программы не зависящими от фактического способа обеспечения доступа к канальному уровню, применяемому в данной операционной системе. Мы описываем эту библиотеку, разрабатывая программу, которая посылает запросы серверу имен DNS (мы составляем свои собственные дейтаграммы UDP и записываем их в символьный сокет) и считывает ответ при помощи libcap, чтобы определить, добавляет ли сервер имен контрольную сумму в дейтаграммы UDP.

29.2. BPF: пакетный фильтр BSD

4.4BSD и многие другие Беркли-реализации поддерживают BPF — пакетный фильтр BSD (BSD Packet Filter). Реализация BPF описана в главе 31 [128]. История BPF, описание псевдопроцессора BPF и сравнение с пакетным фильтром SunOs 4.1.x NIT приведены в [72].

Каждый канальный уровень вызывает BPF сразу после получения пакета и непосредственно перед его передачей выше, как показано на рис. 29.1.

Рис. 29.1. Захват пакета с использованием BPF

Примеры подобных вызовов для интерфейса Ethernet приведены на рис. 4.11 и 4.19 в [128]. Вызов BPF должен произойти как можно скорее после получения пакета и как можно позже перед его передачей, так как это увеличивает точность временных отметок.

Организовать само по себе перехватывание пакетов из канального уровня не очень сложно, однако преимущество BPF заключается в возможности их фильтрации. Каждое приложение, открывающее устройство BPF, может загрузить свой собственный фильтр, который затем BPF применяет к каждому пакету. В то время как некоторые фильтры достаточно просты (например, при использовании фильтра udp or tcp принимаются только пакеты UDP и TCP), другие фильтры позволяют исследовать значения определенных полей в заголовках пакетов. Например, фильтр

tcp and port 80 and tcp[13:l] & 0x7 != 0

использовался в главе 14 [128] для отбора сегментов TCP, направлявшихся к порту 80 или от него и содержащих флаги SYN, FIN или RST. Выражение tcp [13:1] соответствует однобайтовому значению, начинающемуся с 13-го байта от начала заголовка TCP.

В BPF реализован основанный на регистрах механизм фильтрации, который применяет специфические для приложений фильтры к каждому полученному пакету. Хотя можно написать свою программу фильтрации на машинном языке псевдопроцессора (он описан в руководстве по использованию BPF), проще всего будет компилировать строки ASCII (такие, как только что показанная строка, начинающаяся с tcp) в машинный язык с помощью функции pcap_compile, о которой мы рассказываем в разделе 29.7.

В технологии BPF применяются три метода, позволяющие уменьшить накладные расходы на ее использование.

1. Фильтрация BPF происходит внутри ядра, за счет чего минимизируется количество данных, которые нужно копировать из ядра в приложение. Копирование из пространства ядра в пользовательское пространство является довольно дорогостоящим. Если бы приходилось копировать каждый пакет, у BPF могли бы возникнуть проблемы при попытке взаимодействия с быстрыми каналами.

2. BPF передает приложению только часть каждого пакета. Здесь речь идет о длине захвата (capture length). Большинству приложений требуется только заголовок пакета, а не содержащиеся в нем данные. Это также уменьшает количество данных, которые BPF должен скопировать в приложение. В программе tcpdump, например, по умолчанию это значение равно 68 байт, и этого достаточно для размещения 14-байтового заголовка Ethernet, 20-байтового заголовка IP, 20-байтового заголовка TCP и 14 байт данных. Но для вывода дополнительной информации по другим протоколам (например, DNS или NFS) требуется, чтобы пользователь увеличил это значение при запуске программы tcpdump.


Уильям Стивенс читать все книги автора по порядку

Уильям Стивенс - все книги автора в одном месте читать по порядку полные версии на сайте онлайн библиотеки kniga-for.me.

Все материалы на сайте размещаются его пользователями.
Администратор сайта не несёт ответственности за действия пользователей сайта..
Вы можете направить вашу жалобу на почту knigi.for.me@yandex.ru или заполнить форму обратной связи.