Уильям Стивенс - UNIX: разработка сетевых приложений
- Название:UNIX: разработка сетевых приложений
- Автор:
- Жанр:
- Издательство:Питер
- Год:2007
- Город:Санкт-Петербург
- ISBN:5-94723-991-4
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Уильям Стивенс - UNIX: разработка сетевых приложений краткое содержание
Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.
UNIX: разработка сетевых приложений - читать онлайн бесплатно ознакомительный отрывок
Интервал:
Закладка:
76 err_quit("unexpected message type %d", ifm->ifm_type);
77 }
78 /* "ifihead" указывает на первую структуру в связном списке */
79 return (ifihead); /* указатель на первую структуру в связном списке */
80 }
44-65
Сообщение RTM_NEWADDR
возвращается функцией sysctl
для каждого адреса, связанного с интерфейсом: для первичного адреса и для всех альтернативных имен (псевдонимов). Если мы уже заполнили IP-адрес для этого интерфейса, то мы имеем дело с альтернативным именем. Поэтому если вызывающему процессу нужен адрес псевдонима, мы должны выделить память для другой структуры ifi_info
, скопировать заполненные поля и затем заполнить возвращенный адрес.
66-75
Если интерфейс поддерживает широковещательную передачу, возвращается широковещательный адрес, а если интерфейс является интерфейсом типа «точка-точка», возвращается адрес получателя.
18.6. Функции имени и индекса интерфейса
Документ RFC 3493 [36] определяет четыре функции, обрабатывающие имена и индексы интерфейсов. Эти четыре функции используются во многих случаях, когда необходимо описать интерфейс. Они были предложены в процессе разработки API IPv6 (главы 21 и 27), однако индексы интерфейсов имеются и в API IPv4 (например, в вызове IP_RECVIF
или AF_LINK
для маршрутизирующего сокета). Основной принцип, объявляемый в этом документе, состоит в том, что каждый интерфейс имеет уникальное имя и уникальный положительный индекс (нуль в качестве индекса никогда не используется).
#include
unsigned int if_nametoindex(const char * ifname );
Возвращает: положительный индекс интерфейса в случае успешного выполнения, 0 в случае ошибки
char *if_indextoname(unsigned int ifindex , char * ifname );
Возвращает: указатель на имя интерфейса в случае успешного выполнения, NULL в случае ошибки
struct if_nameindex *if_nameindex(void);
Возвращает: непустой указатель в случае успешного выполнения, NULL в случае ошибки
void if_freenameindex(struct if_nameindex * Iptr );
Функция if_nametoindex
возвращает индекс интерфейса, имеющего имя ifname
. Функция if_indextoname
возвращает указатель на имя интерфейса, если задан его индекс ifindex
. Аргумент ifname
указывает на буфер размера IFNAMSIZ
(определяемый в заголовочном файле из листинга 17.1), который вызывающий процесс должен выделить для хранения результата, и этот указатель возвращается в случае успешного выполнения функции if_indextoname
.
Функция if_nameindex
возвращает указатель на массив структур if_nameindex
:
struct if_nameindex {
unsigned int if_index; /* 1, 2. ... */
char *if_name; /* имя, завершаемое нулем: "le0", ... */
};
Последняя запись в этом массиве содержит структуру с нулевым индексом if_index
и с пустым указателем ifname
. Память для этого массива, а также для имен, на которые указывают элементы массива, выделяется динамически и освобождается при вызове функции if_freenameindex
.
Теперь мы представим реализацию этих четырех функций с использованием маршрутизирующих сокетов.
Функция if_nametoindex
В листинге 18.11 показана функция if_nametoindex
.
Листинг 18.11. Возвращение индекса интерфейса по его имени
//libroute/if_nametoindex.c
1 #include "unpifi.h"
2 #include "unproute.h"
3 unsigned int
4 if_nametoindex(const char *name)
5 {
6 unsigned int idx, namelen;
7 char *buf, *next, *lim;
8 size_t len;
9 struct if_msghdr *ifm;
10 struct sockadd *sa, *rti_info[RTAX_MAX];
11 struct sockaddr_dl *sdl;
12 if ((buf = net_rt_iflist(0, 0, &len)) == NULL)
13 return(0);
14 namelen = strlen(name);
15 lim = buf + len;
16 for (next = buf; next ifm_msglen) {
17 ifm = (struct if_msghdr*)next;
18 if (ifm->ifm_type == RTM_IFINFO) {
19 sa = (struct sockaddr*)(ifm + 1);
20 get_rtaddrs(ifm->ifm_addrs, sa, rti_info);
21 if ((sa = rti_infо[RTAX_IFP]) != NULL) {
22 if (sa->sa_family == AF_LINK) {
23 sdl = (struct sockaddr_dl*)sa;
24 if (sdl->sdl_nlen == namelen
25 && strncmp(&sdl->sdl_data[0], name,
26 sdl->sdl_nlen) == 0) {
27 idx = sdl->sdl_index; /* сохранение перед
вызовом free */
28 free(buf);
29 return(idx);
30 }
31 }
32 }
33 }
34 }
35 free(buf);
36 return(0); /* индекс для имени не найден */
37 }
12-13
Наша функция net_rt_iflist
возвращает список интерфейсов.
17-30
Мы обрабатываем сообщения в буфере (см. рис. 18.4) в поисках сообщений типа RTM_IFINFO
. Найдя такое сообщение, мы вызываем нашу функцию get_rtaddrs
, чтобы установить указатели на структуры адреса сокета, а если присутствует структура имени интерфейса (элемент RTAX_IFP
массива rti_info
), то имя интерфейса сравнивается с аргументом.
Функция if_indextoname
Следующая функция, if_indextoname
, показана в листинге 18.12.
Листинг 18.12. Возвращение имени интерфейса по его индексу
libroute/if_indextoname.c
1 #include "unpifi.h"
2 #include "unproute.h"
3 char*
4 if_indextoname(unsigned int index, char *name)
5 {
6 char *buf, *next, *lim;
7 size_t len;
8 struct if_msghdr *ifm;
9 struct sockaddr *sa, *rti_info[RTAX_MAX];
10 struct sockaddr_dl *sdl;
11 if ((buf = net_rt_iflist(0, index, &len)) == NULL)
12 return (NULL);
13 lim = buf + len;
14 for (next = buf; next ifm_msglen) {
15 ifm = (struct if_msghdr*)next;
16 if (ifm->ifm_type == RTM_IFINFO) {
17 sa = (struct sockaddr*)(ifm + 1);
18 get_rtaddrs(ifm->ifm_addrs, sa, rti_info);
19 if ((sa = rti_info[RTAX_IFP]) != NULL) {
20 if (sa->sa_family == AF_LINK) {
21 sdl = (struct sockaddr_dl*)sa;
22 if (sdl->sdl_index == index) {
23 int slen = min(IFNAMSIZ - 1, sdl->sdl_nlen);
24 strncpy(name, sdl->sdl_data, slen);
25 name[slen] = 0; /* завершающий нуль */
26 free(buf);
27 return (name);
28 }
29 }
30 }
31 }
32 }
33 free(buf);
34 return (NULL); /* нет соответствия индексу */
35 }
Эта функция практически идентична предыдущей, но вместо поиска имени интерфейса мы сравниваем индекс интерфейса с аргументом вызывающего процесса. Кроме того, второй аргумент нашей функции net_rt_iflist
— это заданный индекс, поэтому результат должен содержать информацию только для определенного интерфейса. Когда обнаруживается совпадение, возвращается имя интерфейса, к которому добавляется завершающий нуль.
Функция if_nameindex
Следующая функция, if_nameindex
, возвращает массив структур if_nameindex
, содержащих все имена интерфейсов и индексы. Она показана в листинге 18.13.
Листинг 18.13. Возвращение всех имен и индексов интерфейсов
/ /libroute/if_nameindex.c
1 #include "unpifi.h"
Интервал:
Закладка: