UNIX: разработка сетевых приложений
Часть 207 из 399 Информация о книге
4 get_ifi_info(int family, int doaliases)5 {6 int flags;7 char *buf, *next, *lim;8 size_t len;9 struct if_msghdr *ifm;10 struct ifa_msghdr *ifam;11 struct sockaddr *sa, *rti_info[RTAX_MAX];12 struct sockaddr_dl *sdl;13 struct ifi_info *ifi, *ifisave, *ifihead, **ifipnext;14 buf = Net_rt_iflist(family, 0, &len);15 ifihead = NULL;16 ifipnext = &ifihead;17 lim = buf + len;18 for (next = buf; next < lim; next += ifm->ifm_msglen) {19 ifm = (struct if_msghdr*)next;20 if (ifm->ifm_type = RTM_IFINFO) {21 if (((flags = ifm->ifm_flags) & IFF_UP) == 0)22 continue; /* игнорируем, если интерфейс не активен */23 sa = (struct sockaddr*)(ifm + 1);24 get_rtaddrs(ifm->ifm_addrs, sa, rti_info);25 if ((sa = rti_info[RTAX_IFP]) != NULL) {26 ifi = Calloc(1, sizeof(struct ifi_info));27 *ifipnext = ifi; /* предыдущий указатель указывал на этуструктуру */28 ifipnext = &ifi->ifi_next; /* указатель на следующую структуру */29 ifi->ifi_flags = flags;30 if (sa->sa_family == AF_LINK) {31 sdl = (struct sockaddr_dl*)sa;32 ifi->ifi_index = sdl->sdl_index;33 if (sdl->sdl_nlen > 0)34 snprintf(ifi->ifi_name, IFI_NAME, "%*s",35 sdl->sdl_nlen, &sdl->sdl_data[0]);36 else37 snprintf(ifi->ifi_name, IFI_NAME, "index %d",38 sdl->sdl_index);39 if ((ifi->ifi_hlen = sdl->sdl_alen) > 0)40 memcpy(ifi->ifi_haddr, LLADDR(sdl),41 min(IFI_HADDR, sdl->sdl_alen));42 }43 }Мы объявляем локальные переменные и затем вызываем нашу функцию6-14.net_rt_iflistЦикл17-19— это цикл по всем сообщениям маршрутизации, попадающим в буфер в результате выполнения функцииfor. Мы предполагаем, что сообщение — это структураsysctl, и рассматриваем полеif_msghdr(вспомните, что первые три элемента трех структур идентичны, поэтому все равно, какую из трех структур мы используем для просмотра типа элемента).ifm_typeПроверка, включен ли интерфейсДля каждого интерфейса возвращается структура20-22. Если интерфейс не активен, он игнорируется.RTM_IFINFOОпределение, какие структуры адреса сокета присутствуют23-24указывает на первую структуру адреса сокета, следующую за структуройsa. Наша функция get_rtaddrs инициализирует массивif_msghdrв зависимости от того, какие структуры адреса сокета присутствуют.rti_infoОбработка имени интерфейса
Если присутствует структура адреса сокета с именем интерфейса, в памяти размещается структура25-42и хранятся флаги интерфейса. Предполагаемым семейством этой структуры адреса сокета являетсяifi_info, что означает структуру адреса сокета канального уровня. Если элемент sdl_AF_LINKненулевой, имя интерфейса копируется в структуруnlen. В противном случае в качестве имени хранится строка, содержащая индекс интерфейса. Если элементifi_infoненулевой, аппаратный адрес (например, адрес Ethernet) копируется в структуруsdl_alen, а его длина также возвращается какifi_info.ifi_hlenВ листинге 18.10 показана вторая часть нашей функции
, которая возвращает IP-адреса для интерфейса.get_ifi_infoЛистинг 18.10. Функция get_ifi_info, вторая часть
//route/get_ifi_info.c44 } else if (ifm->ifm_type == RTM_NEWADDR) {45 if (ifi->ifi_addr) { /* уже имеется IP-адрес для интерфейса */46 if (doaliases == 0)47 continue;48 /* у нас имеется новый IP-адрес для существующего интерфейса */49 ifisave = ifi;50 ifi = Calloc(1, sizeof(struct ifi_info));51 *ifipnext = ifi; /* предыдущий указатель указывал на этуструктуру */52 ifipnext = &ifi->ifi_next; /* указатель на следующую структуру */53 ifi->ifi_flags = ifi_save->ifi_flags;54 ifi->ifi_index = ifisave->ifi_index;55 ifi->ifi_hlen = ifisave->ifi_hlen;56 memcpy(ifi->ifi_name, ifisave->ifi_name, IFI_NAME);57 memcpy(ifi->ifi_haddr, ifisave->ifi_haddr, IFI_HADDR);