ネットワークアドレスからネットワーク情報を取得する
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) です。
そのため、pack
と unpack
を使って文字列に変換します。
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)
}