情報ネットワーク演習 2007 年 10 月 11 日 ( 木 )
本日の内容 課題 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 バイト ) で表現し, 順番に ( ネットワークバイトオーダ, またはビッグエンディアン ) メモリに格納する. 計算機が処理するのに適している. 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 で書くには 数個のライブラリルーチンと構造体を理解すること ライブラリルーチン : getaddrinfo, getnameinfo, inet_ntoa, freeaddrinfo 構造体 : struct addrinfo DNS サーバへの通信などは, ライブラリルーチンに任せる 12
getaddrinfo ライブラリルーチン int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res); ソケットアドレス構造体を生成する. node は, ホスト名または文字列形式の IP アドレスの文字列. service は, サービス名もしくはポート番号の文字列. 今回は NULL にする. hints に, ヒント情報を格納して呼び出す ( ポインタ渡し ). res はソケットアドレスのリストのポインタのポインタ. あらかじめ struct addrinfo * 型のポインタ変数を確保した上で & 変数 と書く ( ポインタ渡し ).
addrinfo 構造体 struct は不可欠 ( struct addrinfo 型 を宣言している ) struct addrinfo { int ai_flags; /* フラグ */ int ai_family; /* プロトコルファミリ */ int ai_socktype; /* TCP, UDPの別 */ int ai_protocol; /* プロトコル詳細 */ size_t ai_addrlen; /* ai_addrのバイト数 */ struct sockaddr *ai_addr; /* IPアドレス ( バイナリ ) */ char *ai_canonname; /* ホスト名文字列 */ struct addrinfo *ai_next; /* 次へのリンク */ }; 戻り値 ( 線形リスト )... ai_addr: 133042159002... ai_next: 実際にはバイナリ形式... ai_addr: 133042160002... ai_next: NULL 適切なホスト名が格納されている保証はない
getnameinfo ライブラリルーチン int getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags); アドレスから名前へ変換する. sa は IP アドレス ( バイナリ ),salen はその長さ. addrinfo 構造体の ai_addr, ai_addrlen に対応する. host にホスト名が格納される. 配列などにより, あらかじめ領域を確保しておく.hostlen はその長さを指定する. serv と servlen は,host と hostlen と同様. 今回は使用しないので,NULL と 0 を指定する. flags も,0 でよい.
inet_ntoa ライブラリルーチン char *inet_ntoa(struct in_addr in); IPアドレスをバイナリ値から文字列形式に変換する. internet: network address to ascii string 逆変換関数のinet_atonもある. 16
再入可能性 inet_ntoa は, 再入可能でない. 配列領域を別のところで (static 領域などに ) 確保しており, そのアドレスを返す. 連続して呼び出すと, 前の結果は上書きされる. getaddrinfo,getnameinfo は, 再入可能である. 連続して呼び出しても, 問題ない. 戻り値の領域を, 呼び出し側が確保し, 引数に与える. ポインタ渡しになる. getaddrinfo の内部で malloc などによりソケットアドレス構造体が作られる. 開放するには,(free ではなく ) freeaddrinfo ライブラリルーチンを呼び出す.
課題 2(1) ~takehiko/network-enshu2007/2/resolver は, ホスト名を引数にとり, その IP アドレス ( 複数あっても一つだけ ) をドット付き 10 進記法で出力する. cd ~takehiko/network-enshu2007/2./resolver nachi00.sys.wakayama-u.ac.jp 133.42.125.50./resolver www.google.com 66.249.89.147 host www.google.com... 結果は各自確認のこと 18
課題 2(2) ~takehiko/network-enshu2007/2/resolver.c をコピーして ~/network-enshu2007/2/resolver.c とし, 以下の仕様を満たすよう, 修正をしなさい. ホスト名が複数の IP アドレスに結び付けられているとき, それぞれを出力する (1 行 1 アドレスで ). 1 行を IP アドレス ( ホスト名 ) の形で出力する. ~takehiko/network-enshu2007/2/command01-answer を参考に コメントを変更 ( 作成者, 作成日時 ) し, 作業メモを残す. ディレクトリのパーミッションは 705, ファイルは 604 にしておくこと. 19
課題 2 の追加事項とヒント 課題はこれでできた, と思ったら, ~takehiko/network-enshu2007/bin/validator2 を実行してみよう. 余力のある人は,inet_ntoa を使うことなく, ドット付き 10 進記法の IP アドレスを出力するようにしてみよう.( ヒント : inet_ntoa を getnameinfo に置き換える. jman 3 getnameinfo.) 20
期限 2007 年 10 月 12 日 ( 金 )19:30 の回収までに完成させておくこと. 期限後のプログラム修正は? 最終的な回収までの修正 ( コメントの充実, デバッグなど ) は OK. 21
テストプログラムについて ~takehiko/network-enshu2007/bin/validatorα でテストする. 実行中に参照するファイル ~/network-enshu2007/α/ ソースファイル.c ~takehiko/network-enshu2007/α/commandβ ~takehiko/network-enshu2007/α/commandβ-answer 生成されるファイル ~/network-enshu2007/α/ ソースファイル ~/network-enshu2007/α/ ソースファイル _code.c ~/network-enshu2007/α/ ソースファイル _comment.c ~/network-enshu2007/α/error+warning ~/network-enshu2007/α/.commandβ-answer Everything is just fine! を目指せ! 課題番号今は 1 か 2 ドットファイル. ls -a で確認できる. 22
余談 昨年度まで当演習では,gethostbyname, gethostbyaddr といったライブラリ関数を用いていた. これらは,IPv4 にしか対応していないことや, 再入可能でない ( 連続して呼び出せない ) といった問題があった. getnameinfo などを使うと,IPv4/IPv6 の両方に対応するようになった. また, 第 3 回課題のサーバプログラムがすっきり記述できるようになる.