|
>>3322 岩崎 Mew のことは http://www.mew.org で質問した方が早く解決すると思います。 >>3323 pyontan > いつ、どのように消えてしまったかを知る術はあるのでしょうか? 残念ながら、よっぽど特別な仕掛けでも仕込んでおかない限り 無理だと思います。 > 領域不足で、優先度が低く削除されたとか、 さすがにこれはないでしょう。ちなみに UNIX では、ファイルに 優先度という概念はないです。 > 誰かがrmコマンドを実行したとか…。 というようなログも、一般的な UNIX では用意されていないです。 |
|
こんばんは。 現在、DNSクライアントを勉強中です。 サンプルをまだ解析中なんですけど、どうしてもわからない箇所がいくつかあるので…質問させていただきます。 まず、フラグについてです。 えっと…少し説明しにくいんですけど、何故、16ビットと書いてあるのに第15ビットまでの説明までしかないのでしょうか? 次に、ネットワークバイトオーダについてです。 サンプル中で、質問数、回答数、権威数などはpackするときにネットワークバイトオーダに変換しているのに、IDとフラグを変換しないのは何故でしょうか? どういう物をネットワークバイトオーダに変換しなければいけないのかよくわからなくて…。 最後に、サンプル中に出てくる$restについてです。 データを受信した時、細かく言うと$restにはどういった順番でデータが入っているのでしょうか? それがよくわからなく、get_domainサブルーチンに渡したときの処理の仕方がよくわかりません…(−−; 以上長々と申し訳ありませんが、どうかよろしくお願いしますm(_ _)m |
|
>>3325 ken > 何故、16ビットと書いてあるのに第15ビットまでの説明までしか > ないのでしょうか? http://x68000.startshop.co.jp/~68user/net/resolver-2.html#flag のところですね。わたくしの誤りです。RCODE が 3ビットとなって いますが、正しくは4ビットです。近いうちに直します。 # 表の部分で「1……15bit」とあるところも、「1……16bit」の # 誤りですね。 > 質問数、回答数、権威数などはpackするときにネットワークバイト > オーダに変換しているのに、IDとフラグを変換しないのは何故でしょうか? http://x68000.startshop.co.jp/~68user/net/resolver-3.html#4 の以下の部分ですね (一部略)。 sub make_query { my ($type, $class) = @_; # 識別子設定 my $id = pack('B16', '0000000000000000'); # フラグを構成する各要素を設定 my $qr = QR::Query; # 0:質問 my $opcode = OPCODE::StandardQuery; # 0:標準照会 my $aa = 0; # Authoritative Answer (応答時にセット) # フラグ (0 と 1 の文字列) my $flg_binary = sprintf("%d%04d%d%d%d%d%03d%d", $qr, $opcode, $aa, (略)); # フラグ (2バイトのバイナリ) my $flg = pack("B16", $flg_binary); # 質問数のみ 1。回答数、権威数、追加情報数はいずれも 0。 my $question_count = pack('n', 1); my $response_count = pack('n', 0); # foo.example.com というホスト名を 3foo7example3com という形に変換。 my $query_name = &make_domain($query_host); # リクエストは「識別子+フラグ+質問数+回答数+権威数+追加情報数+質問」からなる。 my $request = $id.$flg.$question_count.$response_count.$auth_count.$ext_count.$question; return $request; } ID やフラグは pack('B16') でバイナリデータに変換していますが、 その際に順番が入れ替わることはありません。 pack('B16', '1111000000000011') は順序を保持したまま 1111000000000011 となります。 0000001111110000 となることはありません。 ただし数値の場合は、Short 値を作ろうとして素直に my $question_count = pack('s', 1); などとしてしまうと、リトルエンディアンな Intel 系では 0x01 0x00、 ビッグエンディアンな Motorola・Sparc 系では 0x00 0x01 となって しまいます。よってこの場合は my $question_count = pack('n', 1); と n を使って、どの環境でも 0x00 0x01 となるようにするわけです。 > データを受信した時、細かく言うと$restにはどういった順番でデータが > 入っているのでしょうか? 以下、http://x68000.startshop.co.jp/~68user/net/sample/resolver-1.pl の sub parse_response 関数の説明をします。 my ($id, $flg, $question_count, $response_count, $auth_count, $ext_count, $rest) = unpack('nnnnnna*', $org_dgram); の時点では、$rest には「(7)質問レコード以降のデータ」(回答レコード・権威 レコード・追加情報レコードも含む) が入っています。 データの順序は http://x68000.startshop.co.jp/~68user/net/resolver-2.html#4 の「解析した応答の構成」の順のとおりです。 $rest の先頭のデータは「(7)質問レコード」ですが、「(7)質問レコード」は (7.1)照会名 (可変長) (7.2)照会タイプ (7.3)照会クラス から成り立っていますので、$rest の先頭データは「(7.1)照会名」であるとも 言えます。 その後、 foreach my $count ($question_count){ my $domain; # この時点で $rest の先頭データは「(7.1)照会名」 ($domain, $rest) = get_domain($rest, $org_dgram); # この時点で $rest の先頭データは「(7.2)照会タイプ」 my ($type, $class) = unpack('nn', $rest); # ↑「(7.2)照会タイプ」と「(7.3)照会クラス」を取り出す。 substr($rest, 0, 4) = ''; # ↑取り出した「(7.2)照会タイプ」と「(7.3)照会クラス」を削る。 printf "質問: ドメイン名: %s\n", $domain; printf "質問: タイプ: %d (%s)\n", $type, TYPE::getName($type); printf "質問: クラス: %d (%s)\n", $class, CLASS::getName($class); print $hr_line; } といったふうに、$rest の先頭部分から順に、データを取り出す⇒削る という処理を繰り返します。 質問部分を読み終わると、$rest にはリソースレコード (回答・権威・追加情報) が 残っています。リソースレコードは ドメイン名 (可変長) タイプ クラス 生存時間 (TTL) リソースデータ長 リソースデータ (可変長) から成っていますので、 foreach (1 .. $count){ my $domain; ($domain, $rest) = get_domain($rest, $org_dgram); # ↑ここでドメインを切り出す。 my ($type, $class, $ttl, $rdata_length) = unpack('nnNn', $rest); # ↑タイプ・クラス・生存時間・リソースデータ長を取り出す。 substr($rest, 0, 10) = ''; # ↑タイプ・クラス・生存時間・リソースデータ長の分を削る。 my ($rdata) = substr($rest, 0, $rdata_length); substr($rest, 0, $rdata_length) = ''; # ↑リソースデータ取得 } と、ここでもやはり「データを先頭から取り出し、削る」の繰り返している わけです。 |
|
なるほど…だいたいよくわかりました、ありがとうございます。 でもまだget_domainサブルーチン中の処理がよくわかりませんねぇ…。 while文の最初のif文の中です。 493: if ( ( $len & 0xc0 ) == 0xc0 ){ 494: # 上位 2ビットが立っていたら、もう 1バイト読みこむ (合計 16ビット)。 495: # そして上位 2ビットを落とし、残り 14ビットを DNS サーバから 496: # 返された UDP データグラム先頭からのオフセットとして再帰。。 497: 498: my $offset = unpack('n', $data) ^ 0xc000; 499: my $new_data = substr($org_data, $offset); 500: substr($data, 0, 2) = ''; 501: 502: my ($domain_part) = get_domain($new_data, $org_data); 503: push(@domains, $domain_part); 504: last; 505: 506: } else { 507: # 上位 2ビットが立っていないので、カウンタとして扱う。 508: substr($data, 0, 1) = ''; 509: } まず、if文の中で$dataの上位2ビットが立っていたときに、その2ビットを除いた上位14ビットを$offsetに入れて、$org_dataの$offset番目からのデータを$new_dataに入れて、$dataの上位2ビットを落としたところまではわかりました。 そのあと再びget_domainサブルーチンを呼び出すところからが…どうなるのでしょうか??(^^; また、else文の中の1行はどういった意味を持っているのでしょうか? ここでいう「カウンタ」という物もよくわからなくて…。 どうか、よろしくお願いします |