UNIX: разработка сетевых приложений
Часть 196 из 399 Информация о книге
Обработка альтернативных именНам нужно обнаружить все альтернативные имена (псевдонимы), которые могут существовать для интерфейса, то есть присвоенные этому интерфейсу дополнительные адреса. Обратите внимание в наших примерах, следующих за листингом 17.3, что в Solaris псевдоним содержит двоеточие, в то время как в 4.4BSD имя интерфейса в псевдониме не изменяется. Чтобы обработать оба случая, мы сохраняем последнее имя интерфейса в64-72и сравниваем его только до двоеточия, если оно присутствует. Если двоеточия нет, мы игнорируем этот интерфейс в том случае, когда имя эквивалентно последнему обработанному интерфейсу.lastnameПолучение флагов интерфейсаМы выполняем вызов73-77функцииSIOCGIFFLAGS(см. раздел 16.5), чтобы получить флаги интерфейса. Третий аргумент функцииioctl— это указатель на структуруioctl, содержащую имя интерфейса, для которого мы хотим получить флаги. Мы создаем копию структурыifreq, перед тем как запустить функцию ioctl, поскольку в противном случае этот вызов перезаписал бы IP-адрес интерфейса, потому что оба они являются элементами одного и того же объединения из листинга 17.1. Если интерфейс не активен, мы игнорируем его.ifreqВ листинге 17.6 представлена третья часть нашей функции.
Листинг 17.6. Получение и возвращение адресов интерфейса
//ioctl/get_ifi_infо.c78 ifi = Calloc(1, sizeof(struct ifi_info));79 *ifipnext = ifi; /* prev указывает на новую структуру */80 ifipnext = &ifi->ifi_next; /* сюда указывает указатель наследующую структуру */81 ifi->ifi_flags = flags; /* значения IFF_xxx */82 ifi->ifi_myflags = myflags; /* значения IFI_xxx */83 #if defined(SIOCGIFMTU) && defined(HAVE_STRUCT_IFREQ_IFR_MTU)84 Ioctl(sockfd, SIOCGIFMTU, &ifrcopy);85 ifi->ifi_mtu = ifrcopy.ifr_mtu;86 #else87 ifi->ifi_mtu = 0;88 #endif89 memcpy(ifi->ifi_name, ifr->ifr_name, IFI_NAME);90 ifi->ifi_name[IFI_NAME-1] = '\0';91 /* если sockaddr_dl относится к другому интерфейсу, он игнорируется */92 if (sdlname == NULL || strcmp(sdlname, ifr->ifr_name) != 0)93 idx = hlen = 0;94 ifi->ifi_index = idx;95 ifi->ifi_hlen = hlen;96 if (ifi->ifi_hlen > IFI_HADDR)97 ifi->ifi_hlen = IFI_HADDR;98 if (hlen)99 memcpy(ifi->ifi_haddr, haddr, ifi->ifi_hlen);Выделение памяти и инициализация структуры ifi_infoНа этом этапе мы знаем, что возвратим данный интерфейс вызывающему процессу. Мы выделяем память для нашей структуры78-99и добавляем ее в конец связного списка, который мы создаем. Мы копируем флаги и имя интерфейса в эту структуру. Далее мы проверяем, заканчивается ли имя интерфейса нулем, и поскольку функцияifi_infoинициализирует выделенную в памяти область нулями, мы знаем, чтоcallосинициализируется нулем, aifi_hlen— пустым указателем.ifi_nextВ листинге 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 SIOCGIFBRDADDR106 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 #endif113 #ifdef SIOCGIFDSTADDR114 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 #endif121 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 SIOCGIFDSTADDR127 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));