11.20. Устаревшие функции поиска адресов IPv6
В процессе разработки IPv6 интерфейс поиска адресов IPv6 много раз претерпевал серьезные изменения. В какой-то момент интерфейс был сочтен усложненным и недостаточно гибким, так что от него полностью отказались в RFC 2553 [38]. Документ RFC 2553 предлагал собственные функции, которые в RFC 3493 [36] были попросту заменены getaddrinfo и getnameinfo. В этом разделе мы вкратце рассмотрим старые интерфейсы на тот случай, если вам придется переписывать программы, использующие их.
Константа RES_USE_INET6
Поскольку функция gethostbyname не имеет аргумента для указания нужного семейства адресов (подобного hints.ai_family для getaddrinfo), в первом варианте API использовалась константа RES_USE_INET6, которая должна была добавляться к флагам распознавателя посредством внутреннего интерфейса. Этот API был недостаточно переносимым, поскольку системам, использовавшим альтернативные внутренние интерфейсы распознавателя, приходилось имитировать интерфейс BIND.
Включение RES_USE_INET6 приводило к тому, что функция gethostbyname начинала поиск с записей AAAA, а записи А возвращались только в случае отсутствия первых. Поскольку в структуре hostent есть только одно поле длины адреса, функция gethostbyname могла возвращать адреса только одного типа (либо IPv6, либо IPv4).
Кроме того, включение RES_USE_INET6 приводило к тому, что функция gethostbyname2 начинала возвращать адреса IPv4 в преобразованном к IPv6 виде.
Функция gethostbyname2
Функция gethostbyname2 имеет добавочный аргумент, позволяющий задать семейство адресов.
#include <netdb.h>
struct hostent *gethostbyname2(const char *<i>hostname</i>, int <i>family</i>);
<i>Возвращает: непустой указатель в случае успешного выполнения, в случае ошибки возвращает NULL и задает значение переменной h_errno</i>
Возвращаемое значение то же, что и у функции gethostbyname — указатель на структуру hostent, и сама эта структура устроена так же. Логика функции зависит от аргумента family и параметра распознавателя RES_USE_INET6 (который мы упомянули в конце предыдущего раздела).
Функция getipnodebyname
Документ RFC 2553 [38] запретил использование RES_USE_INET6 и gethostbyname2 из-за глобальности флага RES_USE_INET6 и желания предоставить больше возможностей по управлению возвращаемыми сведениями. Для решения перечисленных проблем была предложена функция getipnodebyname.
#include <sys/socket.h>
#include <netdb.h>
struct hostent *getipnodebyname(const char *<i>name</i>, int <i>af</i>,
int <i>flags</i>, int *<i>error_num</i>);
<i>Возвращает: ненулевой указатель в случае успешного завершения, нулевой в случае ошибки</i>
Функция возвращает указатель на ту же структуру hostent, которая использовалась gethostbyname. Аргументы af и flags непосредственно соответствуют полям hints.ai_family и hints.ai_flags. Для обеспечения безопасности в многопоточной среде возвращаемое значение выделяется динамически, поэтому его приходится освобождать вызовом freehostent.
#include <netdb.h>
void freehostent(struct hostent *<i>ptr</i>);
Функции getipnodebyname и getipnodebyaddr были отменены в RFC 3493 [36], а вместо них было предложено использовать getaddrinfo и getnameinfo.
11.21. Другая информация о сетях
В этой главе мы сфокусировали внимание на именах узлов, IP-адресах, именах и номерах портов служб. Если же обобщить полученную информацию, мы увидим, что существует четыре типа данных (имеющих отношение к сетям), которые могут понадобиться приложению: узлы, сети, протоколы и службы. В большинстве случаев происходит поиск данных, относящихся к узлам (функции gethostbyname и gethostbyaddr), реже — к службам (функции getservbyname и getservbyaddr) и еще реже — к сетям и протоколам.
Все четыре типа данных могут храниться в файле, и для каждого из четырех типов определены три функции:
1. Функция get<i>XXX</i>ent, читающая следующую запись в файле, при необходимости открывающая файл.
2. Функция set<i>XXX</i>ent, которая открывает файл (если он еще не открыт) и переходит к началу файла.
3. Функция end<i>XXX</i>ent, закрывающая файл.
Для каждого из четырех типов данных определяется его собственная структура (соответственно, структуры hostent, netent, protoent и servent), что требует включения заголовка <netdb.h>.
В дополнение к трем функциям get, set и end, которые допускают последовательную обработку файла, для каждого из четырех типов данных предоставляются функции ключевого поиска, или поиска по ключу (keyed lookup). Эти функции последовательно проходят файл (вызывая функцию get<i>XXX</i>ent для чтения каждой строки файла), но вместо того чтобы возвращать каждую строку вызывающему процессу, эти функции ищут элемент, совпадающий с аргументом. Имена функций поиска по ключу имеют вид get<i>XXX</i>by<i>YYY</i>. Например, две функции ключевого поиска для информации об узле — это функции gethostbyname (ищет элемент, совпадающий с именем узла) и gethostbyaddr (ищет элемент, совпадающий с IP-адресом). Таблица 11.5 обобщает эту информацию.