Уильям Стивенс - UNIX: разработка сетевых приложений
- Название:UNIX: разработка сетевых приложений
- Автор:
- Жанр:
- Издательство:Питер
- Год:2007
- Город:Санкт-Петербург
- ISBN:5-94723-991-4
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Уильям Стивенс - UNIX: разработка сетевых приложений краткое содержание
Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.
UNIX: разработка сетевых приложений - читать онлайн бесплатно ознакомительный отрывок
Интервал:
Закладка:
В листинге 17.7 представлена последняя часть нашей функции.
Листинг 17.7. Получение и возврат адреса интерфейса
100 switch (ifr->ifr_addr.sa_family) {
101 case AF_INET:
102 sinptr = (struct sockaddr_in*)&ifr->ifr_addr;
103 ifi->ifi_addr = Calloc(1, sizeof(struct sockaddr_in));
104 memcpy(ifi->ifi_addr, sinptr, sizeof(struct sockaddr_in));
105 #ifdef SIOCGIFBRDADDR
106 if (flags & IFF_BROADCAST) {
107 Ioctl(sockfd, SIOCGIFBRDADDR, &ifrcopy);
108 sinptr = (struct sockaddr_in*) &ifrcopy.ifr_broadaddr;
109 ifi->ifi_brdaddr = Calloc(1, sizeof(struct sockaddr_in));
110 memcpy(ifi->ifi_brdaddr, sinptr, sizeof(struct sockaddr_in));
111 }
112 #endif
113 #ifdef SIOCGIFDSTADDR
114 if (flags & IFF_POINTOPOINT) {
115 Ioctl(sockfd, SIOCGIFDSTADDR, &ifrcopy);
116 sinptr = (struct sockaddr_in*) &ifrcopy.ifr_dstaddr;
117 ifi->ifi_dstaddr = Calloc(1, sizeof(struct sockaddr_in));
118 memcpy(ifi->ifi_dstaddr, sinptr, sizeof(struct sockaddr_in));
119 }
120 #endif
121 break;
122 case AF_INET6:
123 sin6ptr = (struct sockaddr_in6*)&ifr->ifr_addr;
124 ifi->ifi_addr = Calloc(1, sizeof(struct sockaddr_in6));
125 memcpy(ifi->ifi_addr, sin6ptr, sizeof(struct sockaddr_in6));
126 #ifdef SIOCGIFDSTADDR
127 if (flags & IFF_POINTOPOINT) {
128 Ioctl(sockfd, SIOCGIFDSTADDR, &ifrcopy);
129 sin6ptr = (struct sockaddr_in6*)&ifrcopy.ifr_dstaddf;
130 ifi->ifi_dstaddr = Calloc(1, sizeof(struct sockaddr_in6));
131 memcpy(ifi->ifi_dstaddr, sin6ptr,
132 sizeof(struct sockaddr_in6));
133 }
134 #endif
135 break;
136 default:
137 break;
138 }
139 }
140 free(buf);
141 return(ifihead); /* указатель на первую структуру в связной списке */
142 }
102-104 Мы копируем IP-адрес, возвращенный из нашего начального вызова SIOCGIFCONFфункции ioctl, в структуру, которую мы создаем.
106-119 Если интерфейс поддерживает широковещательную передачу, мы получаем широковещательный адрес с помощью вызова SIOCGIFBRDADDRфункции ioctl. Мы выделяем память для структуры адреса сокета, содержащей этот адрес, и добавляем ее к структуре ifi_info, которую мы создаем. Аналогично, если интерфейс является интерфейсом типа «точка-точка», вызов SIOCGIFBRDADDRвозвращает IP-адрес другого конца связи.
123-133 Обработка случая IPv6 — полная аналогия IPv4 за тем исключением, что вызов SIOCGIFBRDADDRне делается, потому что IPv6 не поддерживает широковещательную передачу.
В листинге 17.8 показана функция free_ifi_info, которой передается указатель, возвращенный функцией get_ifi_info. Эта функция освобождает всю динамически выделенную память.
Листинг 17.8. Функция free_ifi_info: освобождение памяти, которая была динамически выделена функцией get_ifi_info
//iосtl/get_ifi_info.c
143 void
144 free_ifi_info(struct ifi_info *ifihead)
145 {
146 struct ifi_info *ifi, *ifinext;
147 for (ifi = ifihead; ifi != NULL; ifi = ifinext) {
148 if (ifi->ifi_addr != NULL)
149 free(ifi->ifi_addr);
150 if (ifi->ifi_brdaddr != NULL)
151 free(ifi->ifi_brdaddr);
152 if (ifi->ifi_dstaddr != NULL)
153 free(ifi->ifi_dstaddr);
154 ifinext = ifi->ifi_next; /* невозможно получить ifi_next
после вызова freed */
155 free(ifi);
156 }
157 }
17.7. Операции с интерфейсами
Как мы показали в предыдущем разделе, запрос SIOCGIFCONFвозвращает имя и структуру адреса сокета для каждого сконфигурированного интерфейса. Существует множество других вызовов, позволяющих установить или получить все остальные характеристики интерфейса. Версия getэтих вызовов ( SIOCGxxx) часто запускается программой netstat, а версия set( SIOCSxxx) — программой ifconfig. Любой пользователь может получить информацию об интерфейсе, в то время как установка этой информации требует прав привилегированного пользователя.
Эти вызовы получают или возвращают структуру ifreq, адрес которой задается в качестве третьего аргумента функции ioctl. Интерфейс всегда идентифицируется по имени: le0, lo0, ppp0, — то есть по имени, заданному в элементе ifr_nameструктуры ifreq.
Многие из этих запросов используют структуру адреса сокета, для того чтобы задать или возвратить IP-адрес или маску адреса. Для IPv4 адрес или маска содержится в элементе sin_addrиз структуры адреса сокета Интернета. Для IPv6 они помещаются в элемент sin6_addrструктуры адреса сокета IPv6.
■ SIOCGIFADDR. Возвращает адрес направленной передачи в элементе ifr_addr.
■ SIOCSIFADDR. Устанавливает адрес интерфейса из элемента ifr_addr. Также вызывается функция инициализации для интерфейса.
■ SIOCGIFFLAGS. Возвращает флаги интерфейса в элементе ifr_flags. Имена различных флагов определяются в виде IFF_xxxв заголовочном файле . Флаги указывают, например, включен ли интерфейс ( IFF_UP), является ли он интерфейсом типа «точка-точка» ( IFF_POINTOPOINT), поддерживает ли широковещательную передачу ( IFF_BROADCAST) и т.д.
■ SIOCSIFFLAGS. Устанавливает флаги из элемента ifr_flags.
■ SIOCGIFDSTADDR. Возвращает адрес типа «точка-точка» в элементе ifr_dstaddr.
■ SIOCSIFDSTADDR. Устанавливает адрес типа «точка-точка» из элемента ifr_dstaddr.
■ SIOCGIFBRDADDR. Возвращает широковещательный адрес в элементе ifr_broadaddr. Приложение сначала должно получить флаги интерфейса, а затем сделать корректный вызов: SIOCGIFBRDADDRдля широковещательного интерфейса или SIOCGIFDSTADDR— для интерфейса типа «точка-точка».
■ SIOCSIFBRDADDR. Устанавливает широковещательный адрес из элемента ifr_broadaddr.
■ SIOCGIFNETMASK. Возвращает маску подсети в элементе ifr_addr.
■ SIOCSIFNETMASK. Устанавливает маску подсети из элемента ifr_addr.
■ SIOCGIFMETRIC. Возвращает метрику интерфейса в элементе ifr_metric. Метрика поддерживается ядром для каждого интерфейса, но используется демоном маршрутизации routed. Метрика интерфейса добавляется к счетчику количества переходов.
■ SIOCSIFMETRIC. Устанавливает метрику интерфейса из элемента ifr_metric.
В этом разделе мы описали наиболее типичные операции интерфейсов. Во многих реализациях появились дополнительные операции.
17.8. Операции с кэшем ARP
Операции с кэшем ARP также осуществляются с помощью функции ioctl. В этих запросах используется структура arpreq, показанная в листинге 17.9 и определяемая в заголовочном файле .
Листинг 17.9. Структура arpreq, используемая с вызовами ioctl для кэша ARP
struct arpreq {
struct sockaddr arp_pa; /* адрес протокола */
struct sockaddr arp_ha; /* аппаратный адрес */
int arp_flags; /* флаги */
};
#define ATF_INUSE 0x01 /* запись, которую нужно использовать */
#define ATF_COM 0x02 /* завершенная запись */
#define ATF_PERM 0x04 /* постоянная запись */
#define ATF_PUBL 0x08 /* опубликованная запись (отсылается другим узлам) */
Третий аргумент функции ioctlдолжен указывать на одну из этих структур. Поддерживаются следующие три вызова:
Интервал:
Закладка: