getnetbyaddr

ネットワークアドレスからネットワーク情報を取得する

構文

解説

getnetbyaddr は、システムのネットワークデータベース(Linux では主に /etc/networks に登録されている情報)から、 ADDR に指定されたネットワークアドレス、および、 ADDRTYPE に指定されたアドレスタイプ(アドレスファミリー)に一致するネットワーク情報を取得します。 スカラーコンテキストなら、getnetbyaddr はネットワーク名を返します。 もしネットワーク名が見つからなければ undef を返します。

ADDR には、ネットワークアドレスを文字列として指定するのではなく、数値表現で指定しなければいけません。 たとえば IPv4 アドレスなら、ドットで区切られた 4 つの数値を 4 バイトのバイナリーに変換し、 それをネットワークバイトオーダー(ビッグエンディアン)の符号なし 32 ビット整数 (unsigned long) として数値化します。

ADDRTYPE にはアドレスタイプ(アドレスファミリー)を表す整数をしています。 Linux の場合、ADDR に指定する IP アドレスが IPv4 なら 2 を、 IPv6 なら 10 を指定します。

my $addr  = '169.254.0.0';                                     # IPv4 アドレス
my $naddr = unpack( 'N', pack( 'C4', split( /\./, $addr ) ) ); # IP アドレスを数値表現に変換
my $name  = getnetbyaddr( $naddr, 2 );                         # ネットワーク名を取得
if ( defined $name ) {
    print $name, "\n";                                         # link-local
}

ADDRTYPE に指定する値は OS によって異なります。 そのような環境による違いを吸収するために、 標準モジュール Socket モジュールからインポートできる定数を使うと良いでしょう。 IPv4 なら AF_INET を、IPv6 なら AF_INET6 を指定します。

use Socket;
my $addr  = '169.254.0.0';                                     # IPv4 アドレス
my $naddr = unpack( 'N', pack( 'C4', split( /\./, $addr ) ) ); # IP アドレスを数値表現に変換
my $name  = getnetbyaddr( $naddr, AF_INET );                   # ネットワーク名を取得
if ( defined $name ) {
    print $name, "\n";                                         # link-local
}

getnetbyaddr はリストコンテキストなら次のようにネットワーク情報をリストで返します。

#    0      1         2          3
my ( $name, $aliases, $addrtype, $net ) = getnetbyaddr( $naddr, AF_INET );
No. 変数 意味 実例
0 $name ネットワーク名 link-local
1 $aliases エイリアス (別名)
2 $addrtype アドレスタイプ(アドレスファミリー)(2: IPv4, 10: IPv6) 2 (IPv4)
3 $net ネットワークアドレス 2851995648 (169.254.0.0)

$net のネットワークアドレスは、4 バイトの IP アドレスを数値として表現したものです。 正確に言うと、ネットワークバイトオーダー(ビッグエンディアン)の符号なし 32 ビット整数 (unsigned long) です。 そのため、packunpack を使って文字列に変換します。

use Socket;
my $addr  = '169.254.0.0';                                     # IPv4 アドレス
my $naddr = unpack( 'N', pack( 'C4', split( /\./, $addr ) ) ); # IP アドレスを数値表現に変換
my ( $name, $aliases, $addrtype, $net ) = getnetbyaddr( $naddr, AF_INET );
if ( defined $name ) {
    my $addr = join( '.', unpack( 'C4', pack( 'N', $net ) ) ); # 数値表現の IP アドレスを文字列に変換
    print $name, ' (', $addr, ")\n";    # link-local (169.254.0.0)
}