情報ネットワーク演習 村川猛彦 2006 年 10 月 12 日 ( 木 ) 1
本日の内容 課題 5 HTTP クライアントハイパーテキストへのアクセス 課題 4 HTTP サーバのビルド 課題 3 ソケットを用いたプロセス間通信 課題 1 低水準入出力 課題 2 名前解決 ( ホスト名 IP アドレス ) 2
第 2 回課題 実施内容と意図 IP アドレスとホスト名の相互変換をするプログラムを拡張する. この課題を通じて,IPv4 における名前解決の方法, および関連するライブラリルーチンや構造体の仕様を学ぶ. 3
ホスト名とは 例 nachi00 nachi00.sys.wakayama-u.ac.jp www.wakayama-u.ac.jp www.google.co.jp localhost 書式 英数字等を. でつなぐ. 演習室内ではこれらは同じ計算機 ( ホスト, ノード ) を指す FQDN (Fully Qualified Domain Name) と呼ばれる 4
IP アドレスとは ( 文字列 ) 例 133.42.159.1 66.249.89.104 127.0.0.1 書式 32 ビット 0~255 の整数を 4 つ書き,. でつなぐ. ドット付き 10 進記法 (dotted decimal notation) ともいう. 5
IP アドレス ( バイナリ ) 例 10000110 00101010 10011111 00000001 文字列による IP アドレスを 4 オクテット (4 バイト ) で表現し, 順番に ( ネットワークバイトオーダ, またはビッグエンディアン ) メモリに格納する. プロセス間通信 ( 課題 3) で,connect システムコールを使って接続先ホストを指定する際に, この形式が不可欠! 6
IP アドレスとホスト名を知るコマンド host Vine Linuxでも利用可 host nachi00 host 133.42.159.1 host www.google.co.jp nslookup 古い (obsolete) コマンド. 最近の Linux では非推奨 7
DNS (Domain Name System) インターネットにおけるホスト名と IP アドレスとを対応させるシステム ホスト名 IP アドレスを 正引き, IP アドレス ホスト名を 逆引き という. DNS サーバ に リゾルバ (resolver) が問い合わせて情報を得る. DNS サーバ間で情報交換をすることも 演習室環境で, 通信する DNS サーバを知りたければ cat /etc/resolv.conf ソフトウェアでは BIND (Berkeley Internet Name Domain) が有名 8
ホスト名と IP アドレスは多対多 (1) 多対多 は二つの 一対多 に分ける 一つのホスト名に複数の IP アドレス ホスト名と IP アドレスは一対多 www.l.google.com www.google.com www.google.co.jp mail.sys.wakayama-u.ac.jp ntp.sys.wakayama-u.ac.jp ns.sys.wakayama-u.ac.jp dns.sys.wakayama-u.ac.jp 66.249.89.99 66.249.89.104 133.42.159.1 一つの IP アドレスに複数のホスト名 IP アドレスとホスト名は一対多 9
ホスト名と IP アドレスは多対多 (2) 実用上は ホスト名から IP アドレスの一つ, IP アドレスからホスト名の一つ ( 正式なホスト名 ) を求めれば十分 利用例は クライアント : サーバのホスト名 IP アドレス サーバ : 例えばアクセスをログに記録する際, クライアントの IP アドレス ホスト名
IPv4 と IPv6 本演習では,IPv4 のみを対象とする. IPv4 アドレス長 : 32 ビット ( アドレス空間 : 2 32 ) IPv6 アドレス長 : 128 ビット ( アドレス空間 : 2 128 ) IP アドレスは. ではなく : で区切って表記する. 省略記法もある. IPv6 に移行しても, ホスト名は変わらない 11
相互変換プログラムを C で書くには 数個のライブラリルーチンと構造体を理解すること ライブラリ関数 : gethostbyname, gethostbyaddr, inet_aton, inet_ntoa 構造体 : hostent, inet_addr DNS サーバへの通信などは, ライブラリルーチンに任せる 12
ライブラリルーチン (1) struct hostent *gethostbyaddr(const void *addr, int len, int type); ネットワーク上のホストのエントリを取得する. get host by address struct hostent *gethostbyname(const char *name); 与えられたホスト名に対応するエントリを取得する. get host by name 文字列形式の IP アドレスを与えても, 一応, 情報は得られる. 詳細は,jman 3 gethostbyname 13
ライブラリルーチン (2) int inet_aton(const char *cp, struct in_addr *inp); IP アドレスをドット付き 10 進記法からバイナリ値へ変換する. internet: ascii string to network address char *inet_ntoa(struct in_addr in); IP アドレスをバイナリ値からドット付き 10 進記法へ変換する. internet: network address to ascii string 詳細は,jman 3 inet_aton 14
hostent 構造体 gethostbyname,gethostbyaddr で問い合わせが成功したら, この構造体のポインタを返す. char ** 型のメンバは? h_aliases は文字列の配列を指すポインタ h_addr_list はバイト列 ( バイナリ形式の IP アドレス ) の配列を指すポインタ いずれも NULL で終端 (argv と同様 ) struct hostent { char *h_name; /* 正式なホスト名 */ char **h_aliases; /* ホスト名の別名 (0 個以上 ) */ int h_addrtype; /* ホストアドレスの種類 */ int h_length; /* アドレス長 (IPv4なら4) */ char **h_addr_list; /* IPアドレス (1 個以上 ) */ } #define h_addr h_addr_list[0] /* 後方互換性のため */ 15
in_addr 構造体 inet_aton ではポインタ渡し 変換に成功したら, 参照先に格納される. inet_ntoa では値渡し メンバ s_addr の値を char * 型に変換 ( キャスト ) してから使うことが多い. struct in_addr { unsigned long int s_addr; } 16
ホスト情報獲得の留意点 gethostbyname,gethostbyaddr は 呼び出してから値を得るまでに時間がかかる 特に, 値の獲得に失敗するとき /etc/hosts を参照したり,/etc/resolv.conf で指示された DNS サーバに問い合わせたりしているため gethostbyname,gethostbyaddt,inet_ntoa は 連続して呼び出してはいけない 実体は ( 例えば static 領域にあって ) 使い回されるため 17
相互変換プログラムの方針 1 文字列は,IP アドレスか? inet_aton の戻り値を調べる. もしそうであれば, ついでに, バイナリ形式の情報を格納する. gethostbyaddr により, バイナリ形式の IP アドレスからホスト情報を獲得する. 獲得に失敗したら, エラー終了. 2 文字列は, ホスト名か? gethostbyname により, ホスト情報を獲得する. 獲得に失敗したら, エラー終了. inet_ntoa により文字列の IP アドレスを求め, 出力する. 逆順にはできない. 文字列の IP アドレスに対しても, gethostbyname で ( 一般には不完全な ) ホスト情報を獲得できてしまうため. 18
課題 2(1) ~takehiko/network-enshu2006/2/ip-host は, 引数が IP アドレスならホスト名に, ホスト名ならば IP アドレスに変換して出力する. cd ~takehiko/network-enshu-2006/2./ip-host nachi00.sys.wakayama-u.ac.jp 133.42.125.50./ip-host 133.42.125.50 nachi00.sys.wakayama-u.ac.jp./ip-host www.google.com 66.249.89.99 host www.google.com... 結果は各自確認のこと 19
課題 2(2) ~takehiko/network-enshu2006/2/ip-host.c をコピーして ~/network-enshu2006/2/ip-host.c とし, 以下の仕様を満たすよう, 修正をしなさい. 複数のコマンドライン引数を処理する. n 番目の引数の結果は, 標準出力の n 行目に出力する. 引数が ホスト名 で, その IP アドレス が複数あるときは, セミコロンで区切って出力する. 逆も同様. ホスト情報獲得に失敗したときは invalid を標準出力に出力する ( 標準エラー出力には何も出力しない ). コメントを変更 ( 作成者, 作成日時 ) し, 作業メモを残す. ディレクトリのパーミッションは 705, ファイルは 604 にしておくこと. 20
課題 2 の追加事項とヒント 機能ごとに関数分割してもよいし,main 関数のみでもよい. 課題はこれでできた, と思ったら, ~takehiko/network-enshu2006/bin/validator2 を実行してみよう. 余裕があれば, 実行時間を短縮するアイデアを考えよう. 作業メモに記録してあれば加点する. 仕様に反しない限り, その機能をコード化してもよい. 実行時間を知るには, コマンド名の前に time 21
期限 2006 年 10 月 18 日 ( 水 )19:30 の回収までに完成させておくこと. それ以降の提出は, 経過時間に応じて減点する. 期限後のプログラム修正は? 最終的な回収までの修正 ( コメントの充実, デバッグなど ) は OK. 22
テストプログラムについて ~takehiko/network-enshu2006/bin/validatorα でテストする. 実行中に参照するファイル ~/network-enshu2006/α/ ソースファイル.c ~takehiko/network-enshu2006/α/commandβ ~takehiko/network-enshu2006/α/commandβ-answer 生成されるファイル ~/network-enshu2006/α/ ソースファイル ~/network-enshu2006/α/ ソースファイル _code.c ~/network-enshu2006/α/ ソースファイル _comment.c ~/network-enshu2006/α/error+warning Everything is just fine! を目指せ! 課題番号今は 1 か 2 23