概要
著書「BareMetalで遊ぶ Raspberry Pi - 達人出版会」のプログラムをいちいちSDカードにコピーするのは面倒なので、U-Bootでネットワークブートさせたいです。
そのためにはまずTFTPサーバーを建てる必要があるのですが、他の人の方法では上手くいかなかったので、問題の調査過程と、問題解決の方法をメモしておきます。
TFTPサーバーのインストール
$ sudo aptitude -y install tftp tftpd-hpa
デフォルトの設定はこんな感じ
$cat /etc/default/tftpd-hpa # /etc/default/tftpd-hpa TFTP_USERNAME="tftp" TFTP_DIRECTORY="/srv/tftp" TFTP_ADDRESS="0.0.0.0:69" TFTP_OPTIONS="--secure"
今回はファイルの読み込みしかしないので、特に修正しないことにします。
TFTPサーバーが /srv/tftp
にアクセスできるようにディレクトリの権限を変えておきます。
$ sudo chown -R tftp:nogroup /srv/tftp $ sudo chmod -R 777 /srv/tftp
そしてhosts.allowに追加。
$ sudo sh -c "echo `in.tftpd:ALL` >> /etc/hosts.allow"
後は以下のコマンドでTFTPサーバーを再起動する。
$ sudo /etc/init.d/tftpd-hpa restart
TFTPサーバーの動作確認(問題発生)
U-Bootでチェックする前に、ローカルの環境から接続できるかテストします。
まずはテストのためにファイルを作っておきましょう。 作成後はアクセス権限を付与するのを忘れないように気をつけてください。
$ sudo sh -c "echo `hoge` >> /srv/tftp/hoge.txt" $ sudo chown -R tftp:nogroup /srv/tftp $ sudo chmod -R 777 /srv/tftp
ではこのhoge.txtをダウンロードしてみましょう。
$ tftp localhost tftp> verbose Verbose mode on. tftp> trace Packet tracing on. tftp> get hoge.txt getting from localhost:hoge.txt to hoge.txt [netascii] sent RRQ <file=hoge.txt, mode=netascii> sent RRQ <file=hoge.txt, mode=netascii> sent RRQ <file=hoge.txt, mode=netascii> sent RRQ <file=hoge.txt, mode=netascii> sent RRQ <file=hoge.txt, mode=netascii> Transfer timed out.
あれ…?うまく動かないですね。
xinetdを入れたり色々やってみましたが、状況が変わらないので、ちょっとまじめに調査してみます。
問題の調査
TFTPサーバーの起動確認
まずTFTPサーバーが動いているかを確認しましょう。
$ ps ax | grep tftp 7832 ? Ss 0:00 /usr/sbin/in.tftpd --listen --user tftp --address 0.0.0.0:69 --secure /srv/tftp
動いてますね。特に問題なさそうです。
アクセス権限の確認
次はアクセス権限の確認
$ ls -la /srv/tftp/ total 12 drwxrwxrwx 2 tftp nogroup 4096 Apr 27 16:18 . drwxrwxrwx 3 nobody nogroup 4096 Apr 27 00:18 .. -rwxrwxrwx 1 tftp nogroup 5 Apr 27 16:18 hoge.txt
これも特に問題なさそうです。
ネットワーク接続の確認
netstatを使って、TFTPサーバーの使用するUDP 69番ポートをチェックしてみます。
$ sudo netstat -tlnup | grep :69 udp 0 0 0.0.0.0:69 0.0.0.0:*
これも特に問題なさそうです。
tcpdumpでパケットを覗く
どうにも原因がわからないので、tcpdumpでパケットを覗いて、TFTPクライアントがどのような要求を投げているか確認してみることにします。
もしかすると69以外のポートにアクセスしようとしているかもしれないので、SSHの22番ポート以外すべてをチェックします。
IPアドレスにlocalhostで指定するとループバックインターフェースを使用するので、きちんと指定してあげましょう(実はこれにもハマりました)。
$ tcpdump -i lo not port 22 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on lo, link-type EN10MB (Ethernet), capture size 65535 bytes
この状態でもう1つ端末を開いて、そちらでtftpサーバーにアクセスしてみます。
$ tftp localhost tftp> get hoge.txt
するとtcpdumpを立ち上げていた方に、以下の様なメッセージが出てきます。
21:50:36.734144 IP6 localhost.47887 > localhost.tftp: 20 RRQ "hoge.txt" netascii 21:50:36.734155 IP6 localhost > localhost: ICMP6, destination unreachable, unreachable port, localhost udp port tftp, length 76
どうやらIPv6でアクセスしようとして、失敗しているみたいです。 調べている過程で「IPv6でアクセスすると動かないから、 IPv4固定にしたほうがいいよー」と書いてあるところがあったので、IPv4を使うように指定してみましょう。
IPv4でアクセスしてみる
色々検証した結果、どうやらlocalhostで指定すると、IPv6アドレスの::1
を見に行ってしまうようです。
IPv4で自身にアクセスするには、127.0.0.1
を接続先に指定すれば良いです。
$ tftp 127.0.0.1 tftp> verbose Verbose mode on. tftp> trace Packet tracing on. tftp> get hoge.txt getting from 127.0.0.1:hoge.txt to hoge.txt [netascii] sent RRQ <file=hoge.txt, mode=netascii> received DATA <block=1, 6 bytes> Received 6 bytes in 0.1 seconds [480 bits/sec]
成功しました。 tcpdumpの結果も以下のようになっており、IPv4でアクセスできているみたいです。
22:03:08.299256 IP localhost.59555 > localhost.tftp: 20 RRQ "hoge.txt" netascii 22:03:08.300963 IP localhost.33201 > localhost.59555: UDP, length 10 22:03:08.301045 IP localhost.59555 > localhost.33201: UDP, length 4
おわりに
というわけで、やっとローカルからの動作確認が取れました。
まさかたったこれだけのことに、ほぼ1日じゅう調べ回ることになるとは……。
しかし今回いろいろ調べたお陰で、また同じような問題が起こった際に対処できるようになり、一歩前進したのでよしとします。
同じような問題に引っかかった人の助けになれば嬉しいです。