getaddrinfo
Cプログラミングにおいて、 関数と関数は、 ドメイン名、ホスト名、IPアドレスを、人間が読めるテキスト表現とオペレーティングシステムのネットワークAPI用の構造化バイナリ形式の間で 変換します。どちらの関数もPOSIX標準アプリケーションプログラミングインターフェース(API)に含まれています。 [1]getaddrinfo()getnameinfo()
getaddrinfo と getnameinfo は互いに逆関数です。ネットワークプロトコルに依存せず、IPv4とIPv6 の両方をサポートします。プロトコルに依存しないアプリケーションの構築や、従来の IPv4 コードを IPv6 インターネットに移行する際に、名前解決に推奨されるインターフェースです。
内部的には、これらの関数はドメインネームシステム(DNS)に限らず、様々な解決方法を使用する可能性があります。ネームサービススイッチはUnix系システムで一般的に使用されており、 BSDソケット時代の先行関数と同様に、このペアのほとんどの実装に影響を与えます。[2]
住所
ネットワーク API 内でアドレスとホスト名を表すために使用されるCデータ構造は次のとおりです。
struct addrinfo { int ai_flags ; int ai_family ; int ai_socktype ; int ai_protocol ; socklen_t ai_addrlen ; struct sockaddr * ai_addr ; char * ai_canonname ; // 正規名struct addrinfo * ai_next ; // この構造体はリンクリストを形成できます}; 一部の古いシステムでは、 の型ai_addrlenはsize_tではなく です。や などsocklen_tのほとんどのソケット関数では、パラメータに 型が必要であり、プログラマーは構造体の要素にアドレスを渡すことがよくあります。これらの型に互換性がない場合(例えば、が8バイトでが4バイトの64ビットSolaris 9システムなど) 、実行時エラーが発生する可能性があります。accept()getpeername()socklen_t*ai_addrlenaddrinfosize_tsocklen_t
構造体には、独自のフィールドを持つ構造体ai_familyと構造体が含まれます。一部の実装では、関数を使用して構造体が作成された際に、これらの構造体とフィールドは同じ値に設定されます。sockaddrsa_familygetaddrinfo()
getaddrinfo
getaddrinfo()ホスト名またはIPアドレスを表す人間が読めるテキスト文字列を、動的に割り当てられた struct addrinfo構造体のリンクリストに変換します。この関数の関数プロトタイプは次のように定義されます。
int getaddrinfo ( const char *ホスト名、const char *サービス、const struct addrinfo *ヒント、struct addrinfo * res []); hostname- は、「 example.com 」などのドメイン名、 「 127.0.0.1」などのアドレス文字列、または のいずれかになります。この場合、ヒント フラグに応じて
NULLアドレス0.0.0.0または127.0.0.1が割り当てられます。 service- 文字列として渡されるポート番号(例:"80" )、またはサービス名(例:"echo" )を指定できます。後者の場合、典型的な実装では、/etc/servicesファイルを参照してサービスをポート番号に解決します。
getservbyname() hintsNULLまたは、addrinfo要求されたサービスのタイプを含む構造体になります。resaddrinfo関数が正常に完了した後に要求された情報を持つ新しい構造体を指すポインタです。 [3]関数は成功した場合は0を返し、失敗した場合は0以外のエラー値を返します。[1]
実装はプラットフォームによって異なりますが、関数は最初に で分岐してポート番号を取得しようとしますservice。文字列値が数値の場合は、それを整数に変換して を呼び出します。 wwwhtons()などのサービス名の場合は、から派生したプロトコルをその関数の2番目のパラメータとして使用して、でサービスが検索されます。次に、が でない場合は を呼び出し解決し、そうでない場合はアドレス0.0.0.0が使用されます。がAI_PASSIVEに設定されている場合はアドレス127.0.0.1が使用されます。これらの条件のいずれかで適切なsockaddr_inが格納された新しい構造体が割り当てられ、先頭で取得したポートもそれに追加されます。最後に、パラメータが逆参照されて、新しく割り当てられた構造体を指すようになります。[4] Mac OS の Unix バージョンなどの一部の実装では が値をオーバーライドしますが、他の実装ではその逆になります。そのため、コードを複数のプラットフォームで動作させるには、両方を同等の値で定義する必要があります。getservbyname()hints->ai_socktypehostnameNULLgethostbyname()hints->ai_flagsaddrinforesaddrinfohints->ai_protocolhints->ai_socktype
フリーアドレス情報
この関数は、関数 によって割り当てられたメモリを解放しますgetaddrinfo()。後者の結果として、アドレス から始まる addrinfo 構造体のリンクリストが生成されるためai、freeaddrinfo()関数 はリストをループし、各構造体を順番に解放します。
void freeaddrinfo ( struct addrinfo * ai ); getnameinfo
この関数は、getnameinfo()IPアドレスの内部バイナリ表現(ポインタ形式)を、struct sockaddrホスト名、またはIPアドレスを名前に変換できない場合はIPアドレスのテキスト表現、サービスポート名または番号からなるテキスト文字列に変換します。関数のプロトタイプは以下のように定義されます。
int getnameinfo ( const struct sockaddr * sa 、socklen_t salen 、char * host 、size_t hostlen 、char * serv 、size_t servlen 、int flags ); 例
以下の例では、getaddrinfo()ドメイン名www.example.com をアドレスリストに解決し、各結果に対して を呼び出してアドレスの正規名を返します。通常、これは元のホスト名を生成しますが、特定のアドレスに複数の名前がある場合は正規名が返されます。この例では、ドメイン名は3回出力され、それぞれに1回ずつ出力されます。getnameinfo()
#include <stdio.h> #include <stdlib.h> #include <netdb.h> #include <netinet/in.h> #include <sys/socket.h> #ifndef NI_MAXHOST#定義 NI_MAXHOST 1025#endifint main ( void ) { 構造体addrinfo *結果; // ドメイン名をアドレスのリストに解決する int error = getaddrinfo ( "www.example.com" 、NULL 、NULL 、&結果); if (エラー!= 0 ) { if (エラー== EAI_SYSTEM ) { perror ( "getaddrinfo" ); }それ以外{ fprintf ( stderr , "getaddrinfo でエラーが発生しました: %s \n " , gai_strerror ( error )); } EXIT_FAILUREを返します。 } 構造体addrinfo * res =結果; // 返されたすべての結果をループし、逆引き検索を実行します while ( res ) { charホスト名[ NI_MAXHOST ]; error = getnameinfo ( res -> ai_addr 、res -> ai_addrlen 、hostname 、NI_MAXHOST 、NULL 、0 、0 ); if (エラー!= 0 ) { fprintf ( stderr , "getnameinfo でエラーが発生しました: %s \n " , gai_strerror ( error )); 続く; } if ( *ホスト名!= '\0' ) { printf ( "ホスト名: %s \n " ,ホスト名); } res = res -> ai_next } freeaddrinfo (結果); 0を返します。 }安全
2016年2月16日、のglibc実装において、バッファオーバーフロー技術を利用したセキュリティバグが発見され、攻撃者が任意のコードを実行できる可能性があると発表されました。 [5]getaddrinfo()
参照
参考文献
- ^ ab "freeaddrinfo, getaddrinfo - アドレス情報を取得する". The Open Group Base Specifications Issue 7, 2018 edition (POSIX.1-2017) . The Open Group . 2022年3月5日閲覧。
- ^ 「nss - manページ セクション5: ファイル形式」。docs.oracle.com。
- ^ Stevens R., Fenner, Rudoff [2003] UNIX® Network Programming Volume 1, Third Edition: The Sockets Networking API. 出版社: Addison-Wesley Professional. 発行日: 2003年11月14日 p. 256
- ^ Hajimu UMEMOTO [2000] getaddrinfo.c アクセス元: https://opensource.apple.com/source/passwordserver_sasl/passwordserver_sasl-14/cyrus_sasl/lib/getaddrinfo.c 2016年3月4日アーカイブ、Wayback Machineより
- ^ 「CVE-2015-7547: Glibc getaddrinfo スタックベースのバッファオーバーフロー」。
外部リンク
- POSIX.1-2017のfreeaddrinfoおよびgetaddrinfo仕様。The Open Group Base Specifications Issue 7、2018年版
- RFC 3493、IPv6 の基本ソケットインターフェース拡張