La Fonera
あけましておめでとうございます。 今年もよろしくお願いします。
La Fonera (La Fonera+) のブート・ローダ RedBoot は、 TFTP サーバに置いたカーネルを load して起動することができる。 したがって、 TFTP サーバから load したカーネルで root ファイル・システムを NFS マウントすれば、 フラッシュ・メモリを使わずにブートすること (ディスクレス・ブート、というか flashless boot) ができる。
La Fonera のようなルータをディスクレスにして 何が嬉しいのかと思う人もいるかもしれないが、 ルータのように常時ネットワークにつなぐものだからこそ、 ネットワークにつないでいないと使えないという ディスクレス最大の欠点が欠点にならないわけで、 むしろルータこそ積極的にディスクレスにすべきではなかろうか。
ディスクレス化することによるメリットは数多い。 なんといっても最大のメリットは、 フラッシュ・メモリを書き換えること無く、 手軽にファームウェアを入れ替えられる (OpenWrt や DD-WRT など) こと。 フラッシュ・メモリを書き換える時間が節約できるし、 書き換え回数を気にする必要もなくなるわけで、 心置き無くファームウェアのデバッグを行なえる。 また、 NFS を使えばフラッシュ・メモリの容量をはるかに超えるディスク領域を使えるので、 セルフ・コンパイル環境の構築なども容易に行なうことができる。
試しに、 La Fonera のフラッシュ・メモリを書き換えること無く DD-WRT をブートさせてみる。
まず、 DD-WRT の root ファイル・システムを NFS サーバ上に展開する。 ここでは例として /nfs/dd-wrt に展開した。 /usr/sbin/udhcpc の実行を抑制するため (理由は後述) に、 /nfs/dd-wrt/usr/sbin/udhcpc を削除しておく。
senri:/tmp # wget "http://www.dd-wrt.com/dd-wrtv2/downloads/release candidates/DD-WRT v24 RC6.2/Atheros WiSoc/Fonera/root.fs"
--09:22:37-- http://www.dd-wrt.com/dd-wrtv2/downloads/release%20candidates/DD-WRT%20v24%20RC6.2/Atheros%20WiSoc/Fonera/root.fs
=> `root.fs'
...
09:22:46 (335.56 KB/s) - `root.fs' saved [2834432/2834432]
senri:/tmp # unsquashfs.dd-wrt -dest /nfs/dd-wrt root.fs
Reading a different endian SQUASHFS filesystem on root.fs
created 347 files
created 61 directories
created 159 symlinks
created 0 devices
created 0 fifos
senri:/tmp # rm /nfs/dd-wrt/usr/sbin/udhcpc
次に DD-WRT のカーネルを改変して、 root ファイル・システムを NFS マウントできるようにする。 DD-WRT のソースを取得:
senri:/usr/local/src % svn co svn://svn.dd-wrt.com/DD-WRT A DD-WRT/tools A DD-WRT/tools/addpattern_gs A DD-WRT/tools/uemf.h ...
La Fonera 用のカーネルは、
DD-WRT/src/linux/ar531x/linux-2.6.23 にある。
SVN revision 8745 の場合は Linux 2.6.23.12 ベース。
ビルド用ディレクトリ /usr/local/src/linux-2.6.23.12-dd-wrt を作って、
DD-WRT のデフォルトのカーネル設定ファイル .config_generic をコピーし、
make menuconfig を実行:
senri:/usr/local/src % mkdir /usr/local/src/linux-2.6.23.12-dd-wrt senri:/usr/local/src % cd DD-WRT/src/linux/ar531x/linux-2.6.23 senri:/usr/local/src/DD-WRT/src/linux/ar531x/linux-2.6.23 % make O=/usr/local/src/linux-2.6.23.12-dd-wrt menuconfig ... senri:/usr/local/src/DD-WRT/src/linux/ar531x/linux-2.6.23 % cp .config_generic /usr/local/src/linux-2.6.23.12-dd-wrt/ senri:/usr/local/src/DD-WRT/src/linux/ar531x/linux-2.6.23 % cd /usr/local/src/linux-2.6.23.12-dd-wrt senri:/usr/local/src/linux-2.6.23.12-dd-wrt % make menuconfig
root ファイル・システムを NFS マウントするために必要な変更は以下の通り:
まず、 カーネルによる IP アドレス自動取得機能を有効にする:
-> Networking
-> Networking support (NET [=y])
-> Networking options
-> TCP/IP networking (INET [=y])
-> IP: kernel level autoconfiguration (IP_PNP [=y])
-> IP: DHCP support (IP_PNP_DHCP [=y])
DD-WRT のデフォルト設定では、 ネットワーク・ドライバ AR2313 がモジュールになっているので、 カーネル組み込み (built-in) に変更する:
-> Device Drivers
-> Network device support (NETDEVICES [=y])
-> Ethernet (10 or 100Mbit) (NET_ETHERNET [=y])
-> AR2313 Ethernet support (AR2313 [=y])
そして NFS サポートを有効にする:
-> File systems
-> Network File Systems
-> NFS file system support (NFS_FS [=y])
-> Provide NFSv3 client support (NFS_V3 [=y])
-> Root file system on NFS (ROOT_NFS [=y])
root ファイル・システムはカーネルがマウントするので mount コマンドは使用しないが、 La Fonera 用の DD-WRT の mount コマンド (busybox に含まれる) は、 NFS をサポートしていないので注意が必要である。 NFS サーバ上の root ディレクトリ /nfs/dd-wrt には、 NFS マウントをサポートした mount コマンドをインストールしておいたほうが便利。
RedBoot の exec コマンドでカーネル・コマンドラインを指定しても、 なぜか無視される (バグ?) ので、 カーネルのデフォルト・コマンドラインを変更しておく:
-> Kernel hacking -> Default kernel command string (CMDLINE)
カーネル・コマンドラインとして以下を設定:
console=ttyS0,115200 ip=on root=/dev/nfs nfsroot=/nfs/dd-wrt,nolock
以上まとめると、 カーネル設定ファイル .config の変更箇所は以下の通り:
CONFIG_IP_PNP=y CONFIG_IP_PNP_DHCP=y CONFIG_AR2313=y CONFIG_NFS_FS=y CONFIG_NFS_V3=y CONFIG_ROOT_NFS=y CONFIG_LOCKD=y CONFIG_LOCKD_V4=y CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y CONFIG_CMDLINE="console=ttyS0,115200 ip=on root=/dev/nfs nfsroot=/nfs/dd-wrt,nolock"
make して TFTP サーバに置く:
senri:/usr/local/src/linux-2.6.23.12-dd-wrt % make make -C /usr/local/src/DD-WRT/src/linux/ar531x/linux-2.6.23 O=/usr/local/src/linux-2.6.23.12-dd-wrt GEN /usr/local/src/linux-2.6.23.12-dd-wrt/Makefile ... LD vmlinux SYSMAP System.map ... senri:/usr/local/src/linux-2.6.23.12-dd-wrt % mips-linux-uclibc-objcopy -O binary vmlinux /var/tftp/vmlinux.bin
La Fonera で読み込んでブートさせる... といいたいところだが、 DD-WRT のカーネルは、 flash RAM に「nvram」という名前の区画がないと Kernel panic を起こす:
RedBoot> load -r -b 0x80041000 vmlinux.bin Using default protocol (TFTP) Raw file loaded 0x80041000-0x8031cbb3, assumed entry at 0x80041000 RedBoot> exec Now booting linux kernel: Base address 0x80030000 Entry 0x80041000 Cmdline : Linux version 2.6.23.12 (sengoku@senri.gcd.org) (gcc version 4.1.2) #14 Wed Jan 2 13:20:19 JST 2008 ... Unhandled kernel unaligned access[#1]: Cpu 0 $ 0 : 00000000 0000006e ffffffed 00000000 ... Kernel panic - not syncing: Attempted to kill init!
flash-less boot の主旨には反するが (^^;)、 nvram 区画を作って再度ブートを試みる。
もちろん、 flash を一切参照しないファームウェアを作ることも可能ではあるが、 わずか 64k byte の flash 領域を確保するだけで、 既存のファームウェアをほとんどそのまま流用できるのであれば、 費用対効果の高い flash の使い方と言えるのではないだろうか。
nvram 区画の内容は「空っぽ」でも構わないのであるが、 ついでなので他の DD-WRT マシンで設定した nvram (nvram.bin) をコピーすれば、 設定の手間が省ける。
DD-WRT のデフォルト設定では、 ath0 (無線LAN) と eth0 (WAN) がブリッジとして動作する設定になっていて、 ブート途中で一時的に eth0 を停止する (ifconfig eth0 down あるいは ifconfig eth0 0.0.0.0)。 当然、eth0 を止めた瞬間に NFS サーバと通信できなくなり、 「nfs: server not responding, still trying」という ログを出し続けてハングしてしまう。 したがって、 eth0 を止めない設定にしておく必要がある。 例えば、 NFS サーバ上の root ディレクトリから /usr/sbin/udhcpc を削除した上で、 「WAN Connection Type」を DHCP に設定する。
ついで^2 に、 La Fonera+ には、 「image2」という名前の普段は使われていない区画がある (「image」区画が壊れた場合の非常用) ので削除しておく (fis delete image2)。
RedBoot> fis delete image2 Delete image 'image2' - continue (y/n)? y ... Erase from 0xa8660000-0xa87a0000: .................... ... Erase from 0xa87e0000-0xa87f0000: . ... Program from 0x80ff0000-0x81000000 at 0xa87e0000: . RedBoot> load -r -b 0x80041000 nvram.bin Using default protocol (TFTP) Raw file loaded 0x80041000-0x80050fff, assumed entry at 0x80041000 RedBoot> fis create -b 0x80041000 -f 0xA87D0000 -l 0x00010000 nvram ... Erase from 0xa87d0000-0xa87e0000: . ... Program from 0x80041000-0x80051000 at 0xa87d0000: . ... Erase from 0xa87e0000-0xa87f0000: . ... Program from 0x80ff0000-0x81000000 at 0xa87e0000: . RedBoot> fis list Name FLASH addr Mem addr Length Entry point RedBoot 0xA8000000 0xA8000000 0x00030000 0x00000000 loader 0xA8030000 0x80100000 0x00010000 0x80100000 image 0xA8040000 0x80040400 0x00240230 0x80040400 nvram 0xA87D0000 0xA87D0000 0x00010000 0x80041000 FIS directory 0xA87E0000 0xA87E0000 0x0000F000 0x00000000 RedBoot config 0xA87EF000 0xA87EF000 0x00001000 0x00000000
flash がこの状態でも、 La Fonera+ のオリジナル・ファームウェアは正常に起動する。 また、 ここでは La Fonera+ を使用しているが、 La Fonera でも同様に nvram 区画を作ればよい。
より正確に言うと、 区画の個数が同じ (/dev/mtd9 が board_config) でないと、 オリジナル・ファームウェアでは fonsmcd が異常終了してしまって、 FON ルータが接続されていないと FON にみなされてしまう。 image2 を削除して nvram を追加すれば区画の個数は変わらないので、 fonsmcd を正常に動かすことができる。
ついでに言うと、 区画の個数が変化してしまっても、 /usr/sbin/fonsmcd ファイル中の「/dev/mtd9ro」という部分を変更すれば、 この問題は回避できる。 MTD パーティションの番号をハードコーディングしてしまっているのは、 この部分だけだと思われる。
再度ブート:
RedBoot> load -r -b 0x80041000 vmlinux.bin
Using default protocol (TFTP)
Raw file loaded 0x80041000-0x8031cbb3, assumed entry at 0x80041000
RedBoot> exec
Now booting linux kernel:
Base address 0x80030000 Entry 0x80041000
Cmdline :
Linux version 2.6.23.12 (sengoku@senri.gcd.org) (gcc version 4.1.2) #14 Wed Jan 2 13:20:19 JST 2008
...
IP-Config: Got DHCP answer from 172.16.255.254, my address is 172.16.191.230
IP-Config: Complete:
device=eth0, addr=172.16.191.230, mask=255.255.0.0, gw=172.16.255.254,
host=172.16.191.230, domain=, nis-domain=(none),
bootserver=172.16.255.254, rootserver=172.16.255.254, rootpath=
Looking up port of RPC 100003/2 on 172.16.255.254
Looking up port of RPC 100005/1 on 172.16.255.254
VFS: Mounted root (nfs filesystem) readonly.
Mounted devfs on /dev
Freeing unused kernel memory: 140k freed
...
DD-WRT v24 std (c) 2008 NewMedia-NET GmbH
Release: 01/02/08 (SVN revision: 8743)
DD-WRT login: root
Password: XXXXXXXX
==========================================================
____ ___ __ ______ _____ ____ _ _
| _ \| _ \ \ \ / / _ \_ _| __ _|___ \| || |
|| | || ||____\ \ /\ / /| |_) || | \ \ / / __) | || |
||_| ||_||_____\ V V / | _ < | | \ V / / __/|__ _|
|___/|___/ \_/\_/ |_| \_\|_| \_/ |_____| |_|
DD-WRT v24
http://www.dd-wrt.com
==========================================================
BusyBox v1.4.2 (2008-01-02 03:34:20 CET) Built-in shell (ash)
Enter 'help' for a list of built-in commands.
root@DD-WRT:~# cat /proc/mounts
rootfs / rootfs rw 0 0
/dev/root / nfs ro,vers=2,rsize=4096,wsize=4096,hard,nolock,proto=udp,timeo=10,retrans=2,sec=sys,addr=172.16.255.254 0 0
none /dev devfs rw 0 0
proc /proc proc rw 0 0
sysfs /sys sysfs rw 0 0
ramfs /tmp ramfs rw 0 0
devpts /dev/pts devpts rw 0 0
root@DD-WRT:~#
NFS サーバに置いた DD-WRT の root ディレクトリ /nfs/dd-wrt が、 無事 / にマウントできている。
前回抽出した ROOT ディレクトリ を改変する。 真っ先に変更すべきなのは /etc/inittab で、 以下のように 1行挿入して /bin/ash が立ち上がるようにしておく。 これだけで、 シリアル・コンソールでシェルが使えるようになる。
--- ROOT.org/etc/inittab 2007-06-19 03:47:32.000000000 +0900 +++ ROOT/etc/inittab 2007-12-15 10:28:06.317233846 +0900 @@ -1,2 +1,3 @@ ::sysinit:/etc/init.d/rcS +ttyS0::askfirst:/bin/ash --login #::respawn:/sbin/monit -Ic /etc/monitrc
この変更だけでも、 La Fonera+ がいじり放題になるので、 改変ファームウェアを作ってみる。
当然 kernel が必要になる。 FON のソースからビルドするのは難しくはないが、 クロスコンパイル環境の構築など、 それなりの時間がかかるので、 とりあえず純正ファームウェアのものをそのまま使って、 改変ファームウェアを作ってみる。 まず純正ファームウェアから取り出した image_full のヘッダを参照して、...
senri:/tmp % od -t x1 image_full | head -1 0000000 00 21 bf de a2 14 d3 9b 00 0a 50 34 6d 00 00 80
前回説明したように image_full は以下のフォーマットなので、 「lzma 圧縮したカーネル」は、 12 バイト目から 000A5034 (上記ヘッダ 8 バイト目〜 に注目) バイトであることが分かる。
┌───────┬───────┬───────┬───<<───┬───<<───┐ │rootイメージの│チェック・サム│rootイメージの│lzma 圧縮した │root イメージ │ │サイズ 4byte│(CRC32) 4byte│位置 4byte│カーネル │squashfs │ └───────┴───────┴───────┴───>>───┴───>>───┘
000A5034 は 10進数に直すと 675892 なので、 以下のように dd コマンドに「count=675892」を指定して、 image_full から lzma 圧縮したカーネル「vmlinux.lzma」を取り出す:
senri:/tmp % dd if=image_full bs=1 skip=12 count=675892 of=vmlinux.lzma 675892+0 records in 675892+0 records out 675892 bytes (676 kB) copied, 1.25156 seconds, 540 kB/s
前述したパッチを前回抽出した ROOT ディレクトリへ適用し、 mksquashfs-lzma コマンドを使って root イメージ root.squashfs を作成する:
senri:/tmp # patch -p0 < patch patching file ROOT/etc/inittab senri:/tmp # mksquashfs-lzma ROOT root.squashfs -nopad -noappend -root-owned -be Creating big endian 3.0 filesystem on root.squashfs, block size 65536. Big endian filesystem, data block size 65536, compressed data, compressed metadata, compressed fragments Filesystem size 1499.77 Kbytes (1.46 Mbytes) 31.47% of uncompressed filesystem size (4766.19 Kbytes) Inode table size 4802 bytes (4.69 Kbytes) 23.45% of uncompressed inode table size (20479 bytes) Directory table size 5571 bytes (5.44 Kbytes) 56.99% of uncompressed directory table size (9776 bytes) Number of duplicate files found 4 Number of inodes 639 Number of files 407 Number of fragments 28 Number of symbolic links 165 Number of device nodes 0 Number of fifo nodes 0 Number of socket nodes 0 Number of directories 67 Number of uids 1 root (0) Number of gids 0
以上で、 カーネルと root イメージの準備ができた。 vmlinux.lzma と root.squashfs をつなげて image ファイルを作成する:
senri:/tmp % fonimage.pl image vmlinux.lzma root.squashfs
fonimage.pl は、 FON のソース を展開すると、 fon/target/linux/fonera-2.6/image/fonimage.pl にある perl スクリプト。 CRC32 の算出 (前述した image_full のフォーマット参照) のため、 Digest::CRC モジュールが必要。
できた image を TFTP サーバに置いて、 La Fonera+ の flash へ書込む。
試しに起動してみる:
RedBoot> fis load loader
RedBoot> go
Failsafe loader v0.2
Looking for board config data... found at offset 0xa87f0000
Reset button GPIO: 6
Reading flash from 0xa8040000 to 0xa825bf48... done.
Verifying CRC... OK - 0x766770d6
Uncompressing Linux... Ok, booting the kernel.
[sighandler]: No more events to be processed, quitting.
[cleanup]: Waiting for children.
[cleanup]: All children terminated.
Unlocking rootfs ...
Could not open mtd device: rootfs
switching to jffs2
init started: BusyBox v1.4.1 (2007-09-03 10:39:50 UTC) multi-call binary
Please press Enter to activate this console.
BusyBox v1.4.1 (2007-09-03 10:39:50 UTC) Built-in shell (ash)
Enter 'help' for a list of built-in commands.
______ __
/\ ___\ /\ \
\ \ \__/ __ ___ __ _ __ __ \_\ \___
\ \ _\/ __`\ /' _ `\ /'__`\/\`'__\/'__`\ /\___ __\
\ \ \/\ \L\ \/\ \/\ \/\ __/\ \ \//\ \L\.\_ \/__/\ \_/
\ \_\ \____/\ \_\ \_\ \____\\ \_\\ \__/.\_\ \ \_\
\/_/\/___/ \/_/\/_/\/____/ \/_/ \/__/\/_/ \/_/
-------------- Fonera 1.5 Firmware (v1.1.1.1) -----------------
* Based on OpenWrt - http://openwrt.org
* Powered by FON - http://www.fon.com
-----------------------------------------------------
root@OpenWrt:/#
カーネルは改変していないので、 起動ログを見ることはできないが、 シェルが使えるのでいじり放題。
では早速...
root@OpenWrt:/# cat > /etc/ipkg.conf <<EOF > src gcd http://www.gcd.org/fonera > dest root / > dest ram /tmp > EOF root@OpenWrt:/# ipkg update Downloading http://www.gcd.org/fonera/Packages Updated list of available packages in /usr/lib/ipkg/lists/gcd Done. root@OpenWrt:/# ipkg install dropbear Installing dropbear (0.48.1-1) to root... Downloading http://www.gcd.org/fonera/dropbear_0.48.1-1_mips.ipk xsystem: ERROR: fork failed before execution: `wget --passive-ftp -q -P /tmp/ipkg-0dCiiX http://www.gcd.org/fonera/dropbear_0.48.1-1_mips.ipk' Nothing to be done An error ocurred, return value: 22. Collected errors: Failed to download dropbear. Perhaps you need to run 'ipkg update'? root@OpenWrt:/#
つまり GCD の ipkg feed から dropbear をインストールしようとしたのだが、 La Fonera+ の wget は busybox 内蔵のもので ipkg が期待する wget とは引数の形式が異なるようだ。 ipkg のためだけに GNU Wget をインストールするのも牛刀なので、 手作業で dropbear をインストールしてみる。
root@OpenWrt:~# wget http://www.gcd.org/fonera/Plus/dropbear_0.49-1_mips.ipk Connecting to www.gcd.org [60.32.85.216:80] dropbear_0.49-1_mips 100% |*****************************| 98 KB --:--:-- ETA root@OpenWrt:~# tar xvzf dropbear_0.49-1_mips.ipk ./debian-binary ./data.tar.gz ./control.tar.gz root@OpenWrt:~# cd / root@OpenWrt:/# tar xvzf ~/data.tar.gz ./ ./usr/ ./usr/sbin/ ./usr/sbin/dropbear ./usr/bin/ ./usr/bin/scp ./usr/bin/ssh ./usr/bin/dbclient ./usr/bin/dropbearkey ./etc/ ./etc/config/ ./etc/config/dropbear ./etc/init.d/ ./etc/init.d/dropbear root@OpenWrt:/# /etc/init.d/dropbear start root@OpenWrt:/#
これで外部から ssh でログインできるようになる。
La Fonera+ 起動時に自動的に dropbear (ssh サーバ) を立ち上げるには、
root@OpenWrt:/# /etc/init.d/dropbear enable
を実行すればよい。 以上は、 dropbear を La Fonera+ に直接インストール方法であるが、 もちろん前述した ROOT ディレクトリに対して dropbear をインストールして、 dropbear 入り image ファイルを作って flash メモリに書込んだ方がよい。
La Fonera+ の場合、 全てのソースが公開されているわけでは無い (例えば fonsmcd などが非公開)。 したがって La Fonera+ の機能を出来るかぎり損なわずに ファームウェアの改変を行なうには、 ソースから全てをビルドすることを目指すよりは、 純正ファームウェアの root イメージを入手して、 それをベースに改変を行なう方がよい。
純正ファームウェアの root イメージを入手する方法としては、 La Fonera+ をディスクレス (フラッシュメモリレス?) 起動させて フラッシュ・メモリの内容を丸ごとコピーする方法がまず考えられる。 実際、私はこの方法で La Fonera+ のフラッシュ・メモリの内容を抽出したのだが、 La Fonera+ は 純正ファームウェアがダウンロードできる。 わざわざ実機からファームウェアを抽出しなくてもいいのでお手軽である。 そこで今回はダウンロードした純正ファームウェアから root イメージを取り出して 改変を行なう方法を紹介する。
まず FON のダウンロードページ から foneraplus_1.1.1.1.fon をダウンロードする。 「.fon」という見慣れない拡張子だが、 このファイルの 519 バイト目以降が tar + gz アーカイブになっている。 519 という数字はバージョンによって変わるかも知れないので、 算出方法を説明しておく。 先頭 4 バイトは マジック・ナンバー「FON5」なのでスキップ。
余談だが、 La Fonera のファームウェア (例えば fonera_0.7.1.1.fon) の場合だと、 このマジック・ナンバーは「FON3」であり、 La Fonera のファームウェアの更新差分 (例えば upgrade.fon) の場合だと、 「FON4」になっている。
マジック・ナンバーの次、すなわち 4 バイト目 (先頭を 0 バイト目と数える) から 3 バイトに注目する。
% od -t a foneraplus_1.1.1.1.fon | head -1 0000000 F O N 5 5 1 2 ! V sub , cr ^ - k e
ASCII コードで「512」と入っていることが分かる。 この数値は、 tar + gz アーカイブの位置を表わしている。 すなわち、 この「512」の文字列の直後の位置 (つまり 7 バイト目) から数えて 512 バイト目、 先頭から数えれば 519 バイト目が、 tar + gz アーカイブの先頭位置である。 アーカイブを取り出して展開してみる:
% dd if=foneraplus_1.1.1.1.fon bs=1 skip=519 of=foneraplus_1.1.1.1.tgz 2213430+0 records in 2213430+0 records out 2213430 bytes (2.2 MB) copied, 4.95395 seconds, 447 kB/s % tar xvzf foneraplus_1.1.1.1.tgz -rwxr-xr-x iurgi/iurgi 666 2007-09-07 23:39 upgrade -rw-r--r-- iurgi/iurgi 2293764 2007-09-05 23:28 image_full -rw-r--r-- iurgi/iurgi 102 2007-04-23 21:12 hotfix
展開すると「image_full」というファイルが得られる。 これは、 kernel と root イメージをつなげて、 先頭にヘッダをつけた、 次のようなフォーマットのファイル。
┌───────┬───────┬───────┬───<<───┬───<<───┐ │rootイメージの│チェック・サム│rootイメージの│lzma 圧縮した │root イメージ │ │サイズ 4byte│(CRC32) 4byte│位置 4byte│カーネル │squashfs │ └───────┴───────┴───────┴───>>───┴───>>───┘
つまり 前回 flash へ書込んだ image ファイルと同じフォーマットである。
image_full から root イメージを取り出すには、 このファイルのヘッダから 「root イメージサイズ」と「root イメージの位置」を取り出せばよい。
% od -t x1 image_full | head -1 0000000 00 21 bf de a2 14 d3 9b 00 0a 50 34 6d 00 00 80
先頭 4 バイトは「0021BFDE」であり、 これを 10進数に変換すると 2211806 であるから、 root イメージサイズが 2211806 バイトであることがわかる。 また、 8 バイト目から 4 バイトは「000A5034」であり、 これを 10進数に変換すると 675892 であることから、 root イメージの位置がこの「000A5034」の直後の位置 (つまり 12 バイト目) から数えて 675892 バイト目、 すなわち先頭から数えれば 675904 バイト目であることがわかる。 root イメージを取り出して展開してみる:
% dd if=image_full bs=1 skip=675904 count=2211806 of=root.squashfs 1617860+0 records in 1617860+0 records out 1617860 bytes (1.6 MB) copied, 3.61499 seconds, 448 kB/s # unsquashfs-lzma -dest ROOT root.squashfs Reading a different endian SQUASHFS filesystem on root.squashfs created 407 files created 67 directories created 165 symlinks created 0 devices created 0 fifos
これで、La Fonera+ の root ディレクトリ以下の全ファイルが、 ROOT ディレクトリ以下に展開される。 unsquashfs-lzma というコマンドが見慣れないかも知れないが、 これは squashfs に含まれる unsquashfs を lzma ライブラリとリンク して作ったコマンドである。
FON ソーシャル・ルータ La Fonera+ へログインするのは、 La Fonera のときほど容易ではない。 La Fonera はシリアル・コンソールでシェル (/bin/ash) を使えたので、 dropbear (ssh サーバ) を立ち上げるだけで、 ssh でログインできるようになる。 しかし La Fonera+ はシリアル・コンソールをつなげても シェルが動いていないので、 Linux 起動後はコンソール出力を眺めることくらいしかできない。
ログインできないようにしてあると、 余計にログインしたくなるのは人の常であるようで、 すでに多くの方が挑戦し 成功しているようだ。 基本的には、 ファームウェアを書き換えてシリアル・コンソールを 有効にしてしまえばいいだけのことであるが、 いかに La Fonera+ の機能そのままに、 シリアル・コンソールだけ有効にするかが肝であろう。
というわけで、 先人が作ったファームウェアをそのまま使うのでは面白くないので、 FON が公開しているソース を元に、 改変ファームウェアを作ってみた。 作り方を書いていると長くなるので、 次回以降で説明するとして、 まずは作った改変ファームウェアを La Fonera+ に書込むところから。
RedBoot> load -r -b 0x80040400 image Using default protocol (TFTP) Raw file loaded 0x80040400-0x8028062f, assumed entry at 0x80040400 RedBoot> fis create image ... Erase from 0xa8040000-0xa8280230: ..................................... ... Program from 0x80040400-0x80280630 at 0xa8040000: ..................................... ... Erase from 0xa87e0000-0xa87f0000: . ... Program from 0x80ff0000-0x81000000 at 0xa87e0000: .
ここで TFTP サーバから読み込んでフラッシュへ書込んだ image というファイルが、 今回作成した改変ファームウェア。 これは、 kernel と root イメージをつなげて、 先頭にヘッダをつけた、 次のようなフォーマットのファイル。
┌───────┬───────┬───────┬───<<───┬───<<───┐ │rootイメージの│チェック・サム│rootイメージの│lzma 圧縮した │root イメージ │ │サイズ 4byte│(CRC32) 4byte│位置 4byte│カーネル │squashfs │ └───────┴───────┴───────┴───>>───┴───>>───┘
FON のソース に含まれる (fon/target/linux/fonera-2.6/image/fonimage.pl)、 fonimage.pl コマンドを 以下のように実行すると、 この image ファイルを作成できる。
fonimage.pl image 《lzma圧縮したカーネルイメージ》 《squashfsなrootイメージ》
前回書いたように、 La Fonera+ は起動すると「loader」を起動する。 この loader プログラムが、 上記 image ファイルを読み込んで、 カーネルと root イメージに分解し、 カーネルを lzma 展開した上で起動する。
試しに起動してみる。 printk サポートを有効にしてある (CONFIG_PRINTK=y) ので、 Linux 起動ログを見ることができる。
RedBoot> fis load loader RedBoot> go Failsafe loader v0.2 Looking for board config data... found at offset 0xa87f0000 Reset button GPIO: 6 Reading flash from 0xa8040000 to 0xa8280224... done. Verifying CRC... OK - 0x9ffc079a Uncompressing Linux... Ok, booting the kernel. Linux version 2.6.19.2 (sengoku@senri.gcd.org) (gcc version 4.1.2) #8 Sun Dec 16 16:52:31 JST 2007 CPU revision is: 00019064 Determined physical RAM map: memory: 01000000 @ 00000000 (usable) Initrd not found or empty - disabling initrd Built 1 zonelists. Total pages: 4064 Kernel command line: console=ttyS0,115200 rootfstype=squashfs,jffs2 init=/etc/preinit ... 中略 ... switching to jffs2 mini_fo: using base directory: / mini_fo: using storage directory: /jffs init started: BusyBox v1.4.1 (2007-12-13 15:41:27 JST) multi-call binary Please press Enter to activate this console. eth0.0: dev_set_promiscuity(master, 1) device eth0 entered promiscuous mode device eth0.0 entered promiscuous mode : udhcpc (v1.4.1) started ... 中略 ... : 21 2 * * * /bin/thinclient cron : 13 5 * * * ntpclient -s -h ntp-1.cso.uiuc.edu : fonsmcd successfully started
La Fonera と同様に mini_fo を使って、 squashfs の上に jffs2 を 重ねることによって、 / (root ファイル・システム) を書込み可能にしている。
La Fonera と同様、 cron から /bin/thinclient を実行しているが、 実はこれは機能していない。 つまり、 /bin/thinclient cron を実行してみると、 以下のように Usage が表示されてしまう。
root@OpenWrt:/# /bin/thinclient cron Usage /bin/thinclient (dummy|start|config|upgrade) [voucher_file]
La Fonera の thinclient が果たしていた役割は、 La Fonera+ では /usr/sbin/fonsmcd が担っているようだ。 しかしながら fonsmcd のソースは公開されていない (少なくとも前述したソースには含まれていない) ので、 詳細は不明。
シリアル・コンソールで「Enter」を入力すれば、 シェルを使うことができるようにしてある。 さらに、ネットワーク経由で ssh ログインすることもできる:
% rsh -l root 172.16.191.252
BusyBox v1.4.1 (2007-12-13 15:41:27 JST) Built-in shell (ash)
Enter 'help' for a list of built-in commands.
______ __
/\ ___\ /\ \
\ \ \__/ __ ___ __ _ __ __ \_\ \___
\ \ _\/ __`\ /' _ `\ /'__`\/\`'__\/'__`\ /\___ __\
\ \ \/\ \L\ \/\ \/\ \/\ __/\ \ \//\ \L\.\_ \/__/\ \_/
\ \_\ \____/\ \_\ \_\ \____\\ \_\\ \__/.\_\ \ \_\
\/_/\/___/ \/_/\/_/\/____/ \/_/ \/__/\/_/ \/_/
-------------- Fonera 1.5 Firmware (v1.1.0.2) -----------------
* Based on OpenWrt - http://openwrt.org
* Powered by FON - http://www.fon.com
-----------------------------------------------------
root@OpenWrt:/# df
Filesystem 1k-blocks Used Available Use% Mounted on
tmpfs 512 0 512 0% /dev
/dev/mtdblock4 3840 284 3556 7% /jffs
/jffs 1664 1664 0 100% /
root@OpenWrt:/# free
total used free shared buffers
Mem: 13612 12680 932 0 1064
Swap: 0 0 0
Total: 13612 12680 932
root@OpenWrt:/# ifconfig eth0.1
eth0.1 Link encap:Ethernet HWaddr 00:18:84:XX:XX:XX
inet addr:172.16.191.252 Bcast:172.16.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1480 Metric:1
RX packets:1367 errors:0 dropped:0 overruns:0 frame:0
TX packets:1212 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:129328 (126.2 KiB) TX bytes:184394 (180.0 KiB)
root@OpenWrt:/#
La Fonera+ には ether ケーブルのソケットが二つついているが、 カーネルから見ると WAN 側ソケットは eth0.1 つまり VLAN デバイスとして見える。 LAN 側ソケットは eth0.0 である。
(つづく)
FON から無料キャンペーンのお知らせが来たので、 土曜日に秋葉原の九十九電機へ行ってラ・フォネラ+を ?台買ってきた。
一台 1000円。 以前から La Fonera+ に興味はあったのだが、 3800円はチト高いなぁと思って手を出さずにいたので、 この機会に是非入手すべく、朝早く (といっても 10:00 ごろだが) から店頭へ。
ツクモ パソコン本店には開店前から行列ができている。 本店の整然とした並びとは対照的に、 DOS/V パソコン館では La Fonera+ の棚の前に無秩序に人が群がっている。 私は大阪人なので、並ぶのはニガテである。 なので DOS/V パソコン館の前で開店を待つことにする。 ちなみに、 ツクモケース王国や 12号店は開店時間が 11:00 なので誰も並んでいない。
10:30 開店の合図と同時に La Fonera+ 目指して飛びかかる客数人 (^^;)。 みるみる間に棚の上の La Fonera+ が減っていく。 無事入手して足早に秋葉原を後にする。
帰宅してすぐ、La Fonera+ 裏面のゴム足をはがす。 う、トルクス (TORX は登録商標なので、ヘックスローブ Hexlobe とも呼ばれる) ねじだ。 La Fonera は普通の「+」ネジだったのに... 慌てて近所のホームセンターに走る。 ねじのサイズは T-9H のようだ。 1サイズ小さい T-8H でも使えた。
La Fonera にはヒートシンクがあったのに、La Fonera+ には無い。 ↑ 基板下辺に、JP1 と書かれたジャンパ・ピンが 4本立っている。 基板裏を見ると、一番右は明らかに GND である。 真ん中二本は信号線のようなので、 UP-12C (USB携帯電話メモリー転送ケーブル) の線を、 JP1 左から NC(つながない)、白(Rx)、緑(Tx)、黒(GND) の順につないでみると、 無事 RedBoot の出力を PC 側で見ることができた。
google で検索してみると、 UP-12C の緑が Rx で、白が Tx と書いてある説明が多いが、 これは緑を (デバイスの) Rx につなぐという意味で書いた (オリジナルの) 記述が、 「緑=Rx」と誤解されて広まったためではないだろうか? デバイス (La Fonera+) の Rx (受信入力) につなぐのは、 UP-12C の Tx 信号 (送信) 線だから、 「緑=Tx」「白=Rx」と書くべきだと思う。 逆に、ジャンパ・ピンの説明をするなら、 緑をつなぐピンが Rx ということになる。
つまり、JP1 左から (La Fonera+ 側から見て) Vcc, Tx, Rx, GND だと思われる。 ちなみに UP-12C の赤は電源なので接続してはいけない。 赤をショートさせると、 USB の電源供給能力一杯の電流が流れ、 UP-12C 本体が過熱する (でも壊れなかった。経験者談 ^^;)。
RedBoot は boot script を自動的に実行しようとするので、 2秒以内に ^C を入力すると、 RedBoot のコマンドプロンプトが表示される:
senri % cu -l ttyUSB1 Connected. +Ethernet eth0: MAC address 00:18:84:xx:xx:xx IP: 192.168.1.1/255.255.255.0, Gateway: 0.0.0.0 Default server: 192.168.1.254 RedBoot(tm) bootstrap and debug environment [ROMRAM] OpenWrt certified release, version 1.1 - built 22:32:28, May 7 2007 Copyright (C) 2000, 2001, 2002, 2003, 2004 Red Hat, Inc. Board: FON 2201 RAM: 0x80000000-0x81000000, [0x80040290-0x80fe1000] available FLASH: 0xa8000000 - 0xa87f0000, 128 blocks of 0x00010000 bytes each. == Executing boot script in 2.000 seconds - enter ^C to abort ^C RedBoot>
コマンド一覧を表示させてみる:
RedBoot> help
Manage aliases kept in FLASH memory
alias name [value]
Set/Query the system console baud rate
baudrate [-b <rate>]
Move Atheros Board Data information
bdmove
Restore Atheros Board Data information
bdrestore
Manage machine caches
cache [ON | OFF]
Display/switch console channel
channel [-1|<channel number>]
Compute a 32bit checksum [POSIX algorithm] for a range of memory
cksum -b <location> -l <length>
Display (hex dump) a range of memory
dump -b <location> [-l <length>] [-s] [-1|2|4]
Execute an image
exec [-b <argv addr>] [-c "kernel command line"] [-w <timeout>]
[<entry point>]
Manage FLASH images
fis {cmds}
Manage configuration kept in FLASH memory
fconfig [-i] [-l] [-n] [-f] [-d] | [-d] nickname [value]
Get Key number
get_key
Get Mac addresses
get_mac
Get Serial number
get_serial
Execute code at a location
go [-w <timeout>] [-c] [-n] [entry]
Help about help?
help [<topic>]
Display command history
history
Set/change IP addresses
ip_address [-l <local_ip_address>[/<mask_len>]] [-h <server_address>]
Load a file
load [-r] [-v] [-d] [-h <host>] [-p <TCP port>][-m <varies>] [-c <channel_number>]
[-b <base_address>] <file_name>
Compare two blocks of memory
mcmp -s <location> -d <location> -l <length> [-1|-2|-4]
Copy memory from one address to another
mcopy -s <location> -d <location> -l <length> [-1|-2|-4]
Fill a block of memory with a pattern
mfill -b <location> -l <length> -p <pattern> [-1|-2|-4]
Network connectivity test
ping [-v] [-n <count>] [-l <length>] [-t <timeout>] [-r <rate>]
[-i <IP_addr>] -h <IP_addr>
Reset the system
reset
Set values
set
Display RedBoot version information
version
Display (hex dump) a range of memory
x -b <location> [-l <length>] [-s] [-1|2|4]
La Fonera の RedBoot と比べると、 bdshow コマンド (Display Atheros Board Data information) が削除され、 get_key, get_mac, get_serial, set コマンドが追加されているが、 機能的には大差ないようだ。
フラッシュ・メモリの内容は、こんな感じ:
RedBoot> fis list Name FLASH addr Mem addr Length Entry point RedBoot 0xA8000000 0x80040400 0x00030000 0xA8000000 loader 0xA8030000 0x80100000 0x00010000 0x80100000 image 0xA8040000 0x80040400 0x00230004 0x80040400 image2 0xA8660000 0xA8660000 0x00140000 0x80040400 FIS directory 0xA87E0000 0xA87E0000 0x0000F000 0x00000000 RedBoot config 0xA87EF000 0xA87EF000 0x00001000 0x00000000
「vmlinux.bin.l7」や「rootfs」の区画があった La Fonera とは様変わりしている。 サイズからいって、「loader」は単なるイニシャル・ローダであろう。 「image」「image2」はカーネル・イメージ? 0xA8270004 〜 0xA8660000 の 4M Byte 弱 (0x3EFFFC = 4128764) が空いているが、 おそらくここにルート・イメージがあるのではないかと思われる。 ルート・イメージにしては少し小さすぎる気がするが、 おいおい解析していく予定。
設定 (fconfig) は次のようになっていた:
Run script at boot: true Boot script: .. fis load -b 0x80100000 loader .. go 0x80100000 Boot script timeout (1000ms resolution): 2 Use BOOTP for network configuration: false Gateway IP address: Local IP address: 192.168.1.1 Local IP address mask: 255.255.255.0 Default server IP address: 192.168.1.254 Console baud rate: 9600 GDB connection port: 9000 Force console for special debug messages: false Network debug at boot time: false
なぜ RedBoot から直接 Linux を起動せず、 「loader」を起動しているのか謎であるが、 変則的な fis list と関係があるのかも知れない。 また、La Fonera と異なり、 La Fonera+ ではシリアル・コンソールが有効になっていない。 すなわちカーネルの起動メッセージが出力されず、 ブート後にログインすることもできない。
さて、一段落ついたところで、 「La Fonera+ の登録」をしておこうかと思い、 同梱されていたマニュアルにしたがって http://registerlafonera.fon.com にアクセスしたところ、
EN
You are not connected through your “MyPlace” signal. Please choose the “MyPlace” signal in your “Wireless Network Connection” window and click connect. See image.
日本語
あなたはMy Placeでの接続をなさっておりません。 'ワイアレスネットワークコ ネクションより 'My Place'を選択して接続し直してください。画像をご覧になってください。
と表示されてしまった。 今まで何台かの La Fonera を登録してきたが、 スムーズに登録できたためしがない。 FON の主旨は面白いのに、 こういう細かいところのツメが甘いのは、とてもモッタイナイ。 ついでに言うと、 あいかわらず日本語が微妙なのはなんとかならないものか。
「あなたはMy Placeでの接続をなさっておりません」などと 決めつけられてしまったが、 もちろん決してそんなことはない。 WPA パスフレーズとして S/N を入力して接続に成功したのだから、 確かに目の前の La Fonera+ の My Place 経由で インターネットに接続しているはずである。
さて、どうしたものか、と思いつつ、試しに FON_AP のほうを試してみたら、 あっさり登録できてしまった。 なんだかなぁ... これでは以前の La Fonera と同じ登録方法ではないか。 FON_AP 経由でルータ登録を行なうこの方法では、 第三者が勝手に他人の La Fonera+ を登録できてしまう。
FON ソーシャルルータ La Fonera のファームウェアは Linux であり、 RedBoot ブートローダ から起動される。 デフォルト状態の La Fonera では、 以下のように RedBoot がフラッシュメモリから Linux カーネルをロードして 自動起動する設定になっている。
== Executing boot script in 1.000 seconds - enter ^C to abort RedBoot> fis load -l vmlinux.bin.l7 Image loaded from 0x80041000-0x801ba000 RedBoot> exec Now booting linux kernel: Base address 0x80030000 Entry 0x80041000 Cmdline : (以下略)
fis (Flash Image System) は、 フラッシュメモリの読み書きを行なうためのコマンドである。
「fis load -l vmlinux.bin.l7」を実行することにより、 フラッシュメモリ内の「vmlinux.bin.l7」と名前をつけられた区画の内容を RAM へコピー (つまり load) する。
ところが、 fis load コマンドのマニュアルには、 「-l」オプションの記述がない。
Synopsis
fis load [-b load address] [-c ] [-d ] [name]
にもかかわらず、 La Fonera の RedBoot で fis コマンドのヘルプを表示させると、 「-l」オプションが指定できることが分かる。
RedBoot> fis help
*** invalid 'fis' command: unrecognized command
Usage:
fis create -b <mem_base> -l <image_length> [-s <data_length>]
[-f <flash_addr>] [-e <entry_point>] [-r <ram_addr>] [-n] <name>
fis delete name
fis erase -f <flash_addr> -l <length>
fis free
fis init [-f]
fis list [-c] [-d]
fis load [-d] [-l] [-b <memory_load_address>] [-c] name ← コレ
fis write -f <flash_addr> -b <mem_base> -l <image_length>
一体この「-l」オプションとは何なのか?
というか、
そもそも「vmlinux.bin.l7」という名前の見慣れない拡張子「L7」とは何なのか?
(L7 というと Layer 7 くらいしか思いつかない... ^^;)
というわけで調べてみた。
「vmlinux.bin.l7」の内容と、 「fis load -l」コマンドによって 0x80041000 番地にロードされた内容を見比べると、 「vmlinux.bin.l7」はデータ圧縮を行なった形式であるように見える。 おそらく「-l」オプションは、 フラッシュメモリ上の圧縮データを展開して RAM へロードするための オプションなのだろう。 圧縮データを展開するオプションとして「fis load」コマンドには、 すでに「-d」(gzip 圧縮データを展開) があるにもかかわらず、 何故わざわざ gzip 以外の圧縮形式を使っているのか謎であるが、 おそらくはより圧縮率の高い圧縮形式を使いたかったのだろう。
gzip より圧縮率が高い圧縮形式で「7」といえば 「7-Zip」、 という (安直な ^^;) 連想をもとに、 とりあえず手元にあった lzma コマンドで展開を試みてみる。
% lzma d vmlinux.bin.l7 vmlinux.bin LZMA 4.43 Copyright (c) 1999-2006 Igor Pavlov 2006-06-04
ありゃ、あっさり展開できてしまった。 ちょっと拍子抜け。
展開した vmlinux.bin を TFTP サーバに置いて、 La Fonera に読み込ませて起動してみる:
RedBoot> load -r -b 0x80041000 vmlinux.bin Using default protocol (TFTP) Raw file loaded 0x80041000-0x8029aa37, assumed entry at 0x80041000 RedBoot> exec Now booting linux kernel: Base address 0x80030000 Entry 0x80041000 Cmdline : (以下略)
これで、TFTP サーバに置いた任意のカーネルを La Fonera で起動することが できるようになった。 フラッシュメモリに書込む必要がないので手軽にカーネルの入れ替えができる。
ちなみに、 「vmlinux.bin」は RAM 上にコピーして即実行 (RedBoot の exec コマンド) 可能であることから、 raw binary 形式 (つまりオブジェクトファイルから、 シンボル情報やリロケーション情報を取り除いたもの) であることが分かる。 つまり、「vmlinux.bin」の拡張子「bin」は「raw binary」の意味なのだろう。 vmlinux から raw binary 形式のファイル vmlinux.bin を得るには、 次のように objcopy コマンドを実行すればよい。
% mips-linux-uclibc-objcopy -O binary vmlinux vmlinux.bin
ネットワーク経由で La Fonera にパッケージをインストール
La Fonera (FON ソーシャル ルータ) のベースとなっている OpenWrt は、 パッケージ管理システムとして ipkg を利用している。 La Fonera 用の ipkg feed を 作ってみた。 この feed を使うには、 以下のように /etc/ipkg.conf に 「src gcd http://www.gcd.org/fonera」 を追加し、 「ipkg update」 を実行する。
root@OpenWrt:/# echo "src gcd http://www.gcd.org/fonera" >> /etc/ipkg.conf root@OpenWrt:/# ipkg update Downloading http://www.gcd.org/fonera/Packages Updated list of available packages in /usr/lib/ipkg/lists/gcd Done.
すると、feed のリスト (パッケージ名の一覧) が /usr/lib/ipkg/lists/gcd に保存される。 あとは、「ipkg install パッケージ名」などと実行するだけで、 パッケージをネットワーク経由で La Fonera にインストールできる。
例えば stone をインストールするには、 次のように「ipkg install stone」と実行するだけでよい。
root@OpenWrt:~# ipkg install stone Installing stone (2.3c-2.2.4.12) to root... Downloading http://www.gcd.org/fonera/stone_2.3c-2.2.4.12_mips.ipk Installing libopenssl (0.9.8d-1) to root... Downloading http://www.gcd.org/fonera/libopenssl_0.9.8d-1_mips.ipk Installing zlib (1.2.3-3) to root... Downloading http://www.gcd.org/fonera/zlib_1.2.3-3_mips.ipk Installing libpthread (0.9.28-8) to root... Downloading http://www.gcd.org/fonera/libpthread_0.9.28-8_mips.ipk Configuring libopenssl Configuring libpthread Configuring stone Configuring zlib Done.
stone の実行に必要な、libopenssl, zlib, libpthread パッケージの インストールも自動的に行なわれている。 このようにパッケージの依存関係も管理してくれるので便利なのであるが、 残念ながら現行の La Fonera 上の ipkg にはバグがある。 インストールしたパッケージをアンインストールしようとして、
ipkg remove stone
などと実行してはいけない。 /usr/bin/stone だけでなく、 /usr/bin ディレクトリまでもが削除されてしまう。 なぜこんなバグがあるかというと、 mini_fo の rmdir の実装にバグがあるからだ。 すなわち、空でないディレクトリに対して rmdir を行なっても、 ディレクトリが削除されてしまうことがある。 試しに、あまり重要そうでないディレクトリに対して rmdir してみる:
root@OpenWrt:/www/images# ls -a table . bottom-right.gif logo.gif top-left.gif .. bottom.gif right.gif top-right.gif bottom-left.gif left.gif sidebar.gif top.gif root@OpenWrt:/www/images# rmdir table root@OpenWrt:/www/images# ls table ls: table: No such file or directory
La Fonera のファイルシステムは mini_fo (mini fan-out) を使っている。 つまり squashfs を read only でマウントした「上」に、 jffs を重ねてマウントしている。 前述の例で言えば、 /www/images/table ディレクトリは squashfs 上にあり、 jffs 上には /www/images/table ディレクトリは存在しない。 「rmdir table」などファイルシステムに対する変更は、 「上」に重ねられた jffs に対して行なわれるが、 ディレクトリが空か否かの判断まで、 「上」のファイルシステムに対してのみ行なっているのだろう、 jffs 上では /www/images/table ディレクトリの中にはファイルが存在しない (ディレクトリが存在しないので当然だが) ため、 rmdir がエラーにならずにディレクトリの削除が行なわれてしまう。
La Fonera の ipkg (busybox に含まれている) のソース ipkg_remove.c を 確認してみると、
for (iter = installed_dirs.head; iter; iter = iter->next) {
file_name = iter->data;
if (rmdir(file_name) == 0) {
ipkg_message(conf, IPKG_INFO, " deleting %s\n", file_name);
removed_a_dir = 1;
str_list_remove(&installed_dirs, &iter);
}
}
などとなっている。 つまりディレクトリが空かどうかは判断せず、 いきなり rmdir してみて成功すればヨシとしている。 このため、「ipkg remove パッケージ名」を実行すると、 空でないディレクトリまで削除してしまうのだろう。
空でないディレクトリに対して rmdir を実行したら ENOTEMPTY を返すのがスジであるので、 mini_fo 側を修正すべきだとは思うのだが、 とりあえず sh スクリプト版の ipkg を拾ってきて、 rmdir するまえに中身の確認をするように変更し、 /usr/bin/ipkg を この修正済み sh スクリプトで置き換えてみた。
root@OpenWrt:~# wget http://www.gcd.org/fonera/ipkg-0.9-1.32.sh Connecting to www.gcd.org[60.32.85.216]:80 ipkg-0.9-1.32.sh 100% |*****************************| 27925 00:00 ETA root@OpenWrt:~# chmod 755 ipkg-0.9-1.32.sh root@OpenWrt:~# mv ipkg-0.9-1.32.sh /usr/bin/ipkg
などと置き換えるとよいだろう。 これで安全にパッケージをアンインストールできるようになる。
root@OpenWrt:~# ipkg remove stone ipkg_remove: Removing stone... ipkg_remove: Warning: Not removing the following directories since they are not empty: /usr /usr/bin Done.
/usr および /usr/bin ディレクトリが空でなかったので削除できなかった旨が、 表示されている。
La Fonera の自動アップデートのまとめ
La Fonera の自動アップデートは、 cron から呼び出される /bin/thinclient プログラムによって行なわれている。 このアップデートは ipkg とは独立した形で行なわれているので、 ipkg でパッケージのインストールを行なう場合は、 この自動アップデートで何が行なわれているか把握しておく必要がある。 確認できたアップデートについてまとめてみた。
- 0.7.0 rev 2 -> 0.7.0 rev 3 (upgrade.fon)
- 修正: /usr/lib/webif/validate.awk
- 0.7.0 rev 3 -> 0.7.0 rev 4 (upgrade.fon)
-
[WiFi] 暗号方式のデフォルトを WPA+TKIP に変更
修正: /etc/init.d/rcS /sbin/ifup /www/cgi-bin/webif/*.sh
変更: /lib/modules/2.4.32/wlan.o /lib/modules/2.4.32/ath_ahb.o
追加: /etc/hotplug.d/iface/10-ppp_hack - 0.7.0 rev 4 -> 0.7.1 rev 1 (upgrade.fon) 2006-11-21 0.7.1 rev 1
-
[Web interface] 多言語サポート
[Web interface] ポートフォワード機能
[NTP] ntpclient による時刻同期
修正: /bin/thinclient /etc/functions.sh /usr/lib/webif/*
変更: /usr/bin/webif-page
追加: /etc/config/ntpservers /etc/config/openports /etc/config/webif /etc/init.d/N45ntpclient /usr/lib/webif/lang /usr/sbin/adjtimex /usr/sbin/ntpclient /www/cgi-bin/webif/adv_pf.sh /www/cgi-bin/webif/language.sh - 0.7.1 rev 1 -> 0.7.1 rev 2 (upgrade.fon) 2007-01-04 01:00 JST
-
[Web interface] 任意のコマンドを実行させられてしまう脆弱性を修正
[NTP] crontab に複数の ntpclient 呼び出しが登録されてしまうバグを修正
修正: /etc/init.d/N45ntpclient /usr/lib/webif/validate.awk /www/cgi-bin/webif/*.sh
変更: /usr/bin/haserl
特に重要なのが、0.7.1 rev 2 で行なわれた、 Web インタフェースにおける脆弱性の修正だろう。 POST した入力データのチェックが厳密になった。 La Fonera に ssh でログインする最も手軽な方法が、 この脆弱性を利用する方法だっただけに、 0.7.1 rev 2 にアップデートする際は注意が必要である。
La Fonera (FON ソーシャル ルータ) のファーム ウェアのソース コードは、 Fon blog に書かれているように、 http://download.fon.com/firmware/fonera/latest/fonera.tar.bz2 から取得できる。 これを展開して make を実行すると、 「OpenWrt Configuration」ダイアログが表示される。 現行の La Fonera のファーム ウェアと同じものをビルドするだけなら Configuration の変更は不要。そのまま save して exit すればビルドが行なわれる。
stone を make するには、
libpthread と libopenssl が必要なので、
以下のように設定する。
まず、
Base system --->
を選択して、以下のように libpthread を make するように指定する:
<*> libpthread.......................................... POSIX threa
続いて、
Libraries --->
を選択して、以下のように libopenssl も make するように指定しておく:
<M> libopenssl..................................... Open source SSL < > openssl-util.............................. OpenSSL command lin <M> zlib................. Library implementing the deflate compressi
「Do you wish to save your new OpenWrt configuration?」 と聞かれるので「Yes」と答える。 するとクロスコンパイル環境とファームウェアのビルドがどんどん進む。
*** End of OpenWrt configuration. *** Execute 'make' to build the OpenWrt or try 'make help'. make[2] toolchain/install make[3] -C toolchain install make[4] -C toolchain/sed prepare make[4] -C toolchain/sed compile make[4] -C toolchain/sed install make[4] -C toolchain/kernel-headers prepare make[4] -C toolchain/kernel-headers compile make[4] -C toolchain/kernel-headers install make[4] -C toolchain/sstrip prepare make[4] -C toolchain/sstrip compile make[4] -C toolchain/sstrip install make[4] -C toolchain/uClibc prepare make[4] -C toolchain/binutils prepare make[4] -C toolchain/binutils compile make[4] -C toolchain/binutils install make[4] -C toolchain/gcc prepare make[4] -C toolchain/gcc compile make[4] -C toolchain/uClibc compile make[4] -C toolchain/uClibc install make[4] -C toolchain/gcc install make[4] -C toolchain/ipkg-utils prepare make[4] -C toolchain/ipkg-utils compile make[4] -C toolchain/ipkg-utils install make[4] -C toolchain/libnotimpl prepare make[4] -C toolchain/libnotimpl compile make[4] -C toolchain/libnotimpl install make[4] -C toolchain/lzma prepare make[4] -C toolchain/lzma compile make[4] -C toolchain/lzma install make[4] -C toolchain/squashfs prepare make[4] -C toolchain/squashfs compile make[4] -C toolchain/squashfs install make[4] -C toolchain/jffs2 prepare make[4] -C toolchain/jffs2 compile make[4] -C toolchain/jffs2 install
「install」と表示されているが、 これは「./staging_dir_mips」ディレクトリへのインストール。 「./staging_dir_mips」にクロスコンパイル環境がインストールされた後に、 これを使ってカーネルやライブラリ等のコンパイルが進む。
make[2] target/compile make[3] -C target compile make[4] -C target/utils prepare make[4] -C target/utils compile make[4] -C target/utils install make[4] -C target/linux prepare make[5] -C target/linux/ar531x-2.4 prepare make[4] -C target/linux compile make[5] -C target/linux/ar531x-2.4 compile make[6] -C target/linux/ar531x-2.4 modules make[6] -C target/linux/ar531x-2.4 packages make[4] -C target/image/ar531x compile make[2] package/compile make[3] -C package compile make[4] -C package compile-targets make[5] -C package/base-files compile make[5] -C package/bridge compile make[5] -C package/busybox compile make[5] -C package/chillispot compile make[5] -C package/dnsmasq compile make[5] -C package/dropbear compile make[5] -C package/foncheckrsa compile make[5] -C package/haserl compile make[5] -C package/madwifi compile make[5] -C package/hostapd compile make[5] -C package/iptables compile make[5] -C package/mini_fo compile make[5] -C package/mtd compile make[5] -C package/libpcap compile make[5] -C package/linux-atm compile make[5] -C package/ppp compile make[5] -C package/pptp compile make[5] -C package/iproute2 compile make[5] -C package/qos compile make[5] -C package/webif compile make[5] -C package/wireless-tools compile make[5] -C package/zlib compile make[5] -C package/openssl compile
「OpenWrt Configuration」ダイアログで指定しなかった パッケージまで表示されるが、 これは単に make がそのパッケージのディレクトリの Makefile を実行しただけで、 コンパイルなどは何も行なわずに抜けている。
make[2] package/install make[3] -C package install make[4] -C package install-targets make[5] -C package/base-files install make[5] -C package/bridge install make[5] -C package/busybox install make[5] -C package/chillispot install make[5] -C package/dnsmasq install make[5] -C package/dropbear install make[5] -C package/foncheckrsa install make[5] -C package/haserl install make[5] -C package/hostapd install make[5] -C package/iptables install make[5] -C package/madwifi install make[5] -C package/mini_fo install make[5] -C package/mtd install make[5] -C package/ppp install make[5] -C package/pptp install make[5] -C package/qos install make[5] -C package/iproute2 install make[5] -C package/webif install make[5] -C package/wireless-tools install make[2] target/install make[3] -C target install make[4] -C target/image/ar531x clean make[5] -C target/image/generic/lzma-loader clean make[4] -C target/utils prepare make[4] -C target/utils compile make[4] -C target/utils install make[4] -C target/linux prepare make[5] -C target/linux/ar531x-2.4 prepare make[4] -C target/linux compile make[5] -C target/linux/ar531x-2.4 compile make[4] -C target/linux install make[5] -C target/linux/ar531x-2.4 install make[4] -C target/image/ar531x compile make[4] -C target/image/ar531x install make[5] -C target/image/generic/lzma-loader clean compile
以上で、クロスコンパイル環境とファームウェアのビルドが全て完了。 所要時間は 30分ほど (私の Celeron D 345 マシンの場合)。
ビルドしたクロスコンパイル環境は、 「staging_dir_mips/bin」に PATH を通すだけで使用できる。
stone を make してみる。 まずは CVS レポジトリから最新版を checkout する:
senri % cvs -d:pserver:anonymous@cvs.sourceforge.jp:/cvsroot/stone login Logging in to :pserver:anonymous@cvs.sourceforge.jp:2401/cvsroot/stone CVS password: senri % cvs -z3 -d:pserver:anonymous@cvs.sourceforge.jp:/cvsroot/stone co stone cvs checkout: Updating stone U stone/GPL.txt U stone/Makefile U stone/README.en.txt U stone/README.txt U stone/cryptoapi.c U stone/dist U stone/global.h U stone/logmsg.mc U stone/md5.h U stone/md5c.c U stone/stone.1 U stone/stone.1.ja U stone/stone.c U stone/stone.cnf U stone/stone.sh U stone/stone.spec
次に make する:
senri % cd stone senri % make fon-ssl make CC="mips-linux-uclibc-gcc" SSL_LIBS="-lssl -lcrypto" TARGET=fon ssl_stone make[1]: Entering directory `stone' make FLAGS="-DUSE_POP -DUSE_SSL " LIBS=" -lssl -lcrypto" fon make[2]: Entering directory `stone' make CC="mips-linux-uclibc-gcc" FLAGS="-Wall -DPTHREAD -DUNIX_DAEMON -DPRCTL -DUSE_POP -DUSE_SSL " LIBS="-lpthread -lssl -lcrypto" stone make[3]: Entering directory `stone' mips-linux-uclibc-gcc -Wall -DPTHREAD -DUNIX_DAEMON -DPRCTL -DUSE_POP -DUSE_SSL -o stone stone.c -lpthread -lssl -lcrypto make[3]: Leaving directory `stone' mips-linux-uclibc-strip stone make[2]: Leaving directory `stone' make[1]: Leaving directory `stone'
なお、CVS から checkout した最新版でなくても、 例えば stone 2.3c において
senri:/usr/src/stone-2.3c % mips-linux-uclibc-gcc -Wall -DPTHREAD -DUNIX_DAEMON -DPRCTL -DUSE_POP -DUSE_SSL -o stone stone.c -lpthread -lssl -lcrypto
などとコンパイルすることにより La Fonera 版 stone を make することができる。 つまり特に変更することなく make できるわけで、 いかに La Fonera がフツーの Linux マシンであるかが分かる。
make した stone および、 libpthread, libopenssl を La Fonera へコピーすれば (libopenssl は SSL 版 stone の場合のみ必要)、 La Fonera 上で stone を実行することができる。
root@OpenWrt:~# stone
Jan 4 00:18:08.478674 1024 start (2.3c) [14946]
Jan 4 00:18:08.488958 1024 stone 2.3c http://www.gcd.org/sengoku/stone/
Jan 4 00:18:08.570372 1024 Copyright(C)2007 by Hiroaki Sengoku <sengoku@gcd.org>
Jan 4 00:18:08.579479 1024 using OpenSSL 0.9.8d 28 Sep 2006 http://www.openssl.org/
Usage: stone <opt>... <stone> [-- <stone>]...
opt: -h opt ; help for <opt> more
-h stone ; help for <stone>
-h ssl ; help for <SSL>, see -q/-z opt
La Fonera (FON ソーシャル ルータ) は、
無線LAN アクセス ポイントであるが、
中身は普通の Linux マシンなので、
いろんな用途に使うことができる。
一例として無線LAN 端末として使ってみる。
まずは ssh で La Fonera にログイン:
senri:/home/sengoku % ssh -l root 172.16.254.254 root@172.16.254.254's password: BusyBox v1.1.3 (2006.09.11-19:54+0000) Built-in shell (ash) Enter 'help' for a list of built-in commands. _______ _______ _______ | ____|| || _ | | ____|| - || | | | | | |_______||__| |__| |___| Fonera Firmware (Version 0.7.1 rev 1) ------------- * * Based on OpenWrt - http://openwrt.org * Powered by FON - http://www.fon.com --------------------------------------------------- root@OpenWrt:~# route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 169.254.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth0 172.16.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth0
実験に先だってアクセスポイントとしての機能は殺してあるので、 ルーティング テーブルは至ってシンプル。 default route がないので、この時点では当然インターネットへはアクセスできない。
まず wlanconfig コマンドを使って無線LAN デバイスを端末モードで作成し、 続いて接続先アクセスポイント (もう一台の La Fonera ;-) の ESSID および WEP キー (もちろん伏せ字) を設定:
root@OpenWrt:~# wlanconfig ath0 create wlandev wifi0 wlanmode sta ath0 root@OpenWrt:~# iwconfig ath0 essid "MyPlace" root@OpenWrt:~# iwconfig ath0 key "6162636465666768696a6b6c6d" root@OpenWrt:~# ifconfig ath0 up
これだけでアクセスポイントへの接続が完了する。 iwconfig コマンドで確認してみる。
root@OpenWrt:~# iwconfig ath0
ath0 IEEE 802.11g ESSID:"MyPlace"
Mode:Managed Frequency:2.417 GHz Access Point: 00:18:84:10:XX:XX
Bit Rate:36 Mb/s Tx-Power:18 dBm Sensitivity=0/3
Retry:off RTS thr:off Fragment thr:off
Encryption key:6162-6364-6566-6768-696a-6b6c-6d Security mode:restricted
Power Management:off
Link Quality=53/98 Signal level=-42 dBm Noise level=-95 dBm
Rx invalid nwid:664 Rx invalid crypt:0 Rx invalid frag:0
Tx excessive retries:0 Invalid misc:0 Missed beacon:0
あとは 「ifconfig ath0 192.168.10.2」 などと手で IP アドレスを設定するか、 あるいは DHCP クライアントを実行すればよい。
root@OpenWrt:~# udhcpc -i ath0 info, udhcpc (v0.9.9-pre) started debug, Sending discover... debug, Sending select for 192.168.10.146... info, Lease of 192.168.10.146 obtained, lease time 43200 deleting routers adding router 192.168.10.1 adding dns 192.168.10.1 root@OpenWrt:~# route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 192.168.10.0 0.0.0.0 255.255.255.0 U 0 0 0 ath0 169.254.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth0 172.16.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth0 0.0.0.0 192.168.10.1 0.0.0.0 UG 0 0 0 ath0
設定された default route 192.168.10.1 は NAT ルータなので、 これでインターネットへの接続が完了している。試しにアクセスしてみる:
root@OpenWrt:~# telnet mx.gcd.org 25 220 senri.gcd.org ESMTP help 214 qmail home page: http://pobox.com/~djb/qmail.html quit 221 senri.gcd.org Connection closed by foreign host. root@OpenWrt:~# wget http://www.klab.org/ Connecting to www.klab.org[211.13.209.203]:80 index.html 100% |*****************************| 11992 00:00 ETA root@OpenWrt:~# ls -la index.html -rw-r--r-- 1 root root 11992 Dec 22 05:27 index.html
La Fonera (FON ソーシャル ルータ) を2台購入した (正確に言うと1台は店頭で購入、もう1台は無料キャンペーンで入手)。
| 入手方法 | 店頭で購入 | 無料キャンペーン |
|---|---|---|
| Model | FON2100E | FON2100E |
| S/N | 8638001XXX | 8646022XXX |
| MACアドレス | 00:18:84:10:XX:XX | 00:18:84:16:XX:XX |
| ROMバージョン | 0.7.0 r3 | 0.7.0 r4 |
店頭で購入した物のほうが古いのは、まあ当たり前か。 新しい方のシリアル番号の下のほうの桁が 2万を超えているので、 現在は万単位で製造しているのだろう。 シリアル番号の上の方の桁、 および ROMバージョンが異なるのは、 製造ロットが違うから? もちろん両ルータともネットにつないでおくことにより、 現時点での最新バージョンである 0.7.1 r1 に自動アップデートした。
自動アップデートは、 cron から呼び出される /bin/thinclient プログラムによって行なわれる (/bin/thinclient は起動時にも呼び出される)。
root@OpenWrt:~# /bin/thinclient cron upgrade.fon 100% |*****************************| 61473 00:00 ETA This is a FON hotfix v2 archive Verified OK Upgrade name: upgrade_0711 Upgrading...
/bin/thinclient は、まず download.fon.com:1937 へ ssh 接続する。 ポート番号が変則的なのは、 間にファイアウォールがはさまっていないか確認するためか? なお、ssh は /etc/dropbear/key にある秘密鍵を用いて DSA 認証を行なう。 この秘密鍵は両ルータとも同じ内容だった。 /bin/thinclient は、次に この ssh セッションにおいて、 次の文字列を送信する。
mode='cron' wlmac='00:18:84:16:XX:XX' mac='00:18:84:16:XX:XX' fonrev='4' firmware='0.7.0'
ここで、「mode=」は /bin/thinclient の実行方法を示している。 cron から呼び出されたときは「mode='cron'」、 起動時に呼び出されたときは「mode='start'」。 「wlmac=」および「mac=」はそれぞれ、 無線(FON_AP)側の MAC アドレスと、 有線(WAN)側の MAC アドレス。 後者の MAC アドレスに 1 加えた値が前者のアドレスになっているようだ (ちなみにプライベート アクセス ポイント(MyPlace)側の MAC アドレスは、 さらに 1 を加えた値)。 「firmware=」および「fonrev=」はバージョンおよびリビジョン番号を示す。 つまり、個体識別ID を FON に送信しているものと考えられる。
すると、download.fon.com:1937 から、 以下のような sh スクリプトが返ってくる。
cd /tmp wget http://download.fon.com/firmware/update/0.7.0/4/upgrade.fon /bin/fonverify /etc/public_fon_rsa_key.der /tmp/upgrade.fon rm -f /tmp/.thinclient.sh exit
/bin/thinclient は、 この送られてきた sh スクリプトを /tmp/.thinclient.sh に保存した上で実行する。 つまり、 この例の場合だと、「upgrade.fon」をダウンロードして 「/bin/fonverify」に与える。 おそらく upgrade.fon がアップデートのための差分データで、 「/bin/fonverify」が、このデータを認証した上で展開しているのだろう。
アップデートの必要がないときは、 以下のような何もしない sh スクリプトが返ってくる。
rm -f /tmp/.thinclient.sh exit
0.7.0 r4 と 0.7.1 r1 の差分をとってみた。
新規に追加されたファイル:
/etc/config/ntpservers /etc/config/openports /etc/config/webif /etc/init.d/N45ntpclient
ntpclient を使って時刻あわせするようになったようだ。 アップデート前するは起動時に「2000年1月1日 9:00 JST」にセットされていた。 これでは起動時からの経過時間しかわからないので、 ntpclient を使うように変更したのだろう。
変更されたファイル:
--- /rom/etc/banner 2006-09-13 02:41:30.000000000 +0900
+++ /jffs/etc/banner 2006-11-22 04:07:20.000000000 +0900
@@ -4,7 +4,7 @@
| | |_______||__| |__|
|___|
- Fonera Firmware (Version 0.7.0 rev 4) -------------
+ Fonera Firmware (Version 0.7.1 rev 1) -------------
*
* Based on OpenWrt - http://openwrt.org
* Powered by FON - http://www.fon.com
--- /rom/etc/fon_revision 2006-09-12 06:43:42.000000000 +0900
+++ /jffs/etc/fon_revision 2006-11-16 05:08:40.000000000 +0900
@@ -1 +1 @@
-4
+1
--- /rom/etc/fon_version 2006-09-12 04:32:01.000000000 +0900
+++ /jffs/etc/fon_version 2006-11-16 05:08:40.000000000 +0900
@@ -1 +1 @@
-0.7.0
+0.7.1
--- /rom/etc/functions.sh 2006-09-12 04:32:01.000000000 +0900
+++ /jffs/etc/functions.sh 2006-11-15 02:44:26.000000000 +0900
@@ -112,3 +112,18 @@
esac
}
+#
+# This functions forwards a port. The next args are required:
+# $1 = WAN interface
+# $2 = Origin Port
+# $3 = Destination IP
+# $4 = Destination Port
+# $5 = protocol used
+#
+# Example: open_port $WAN 8080 192.168.1.2 80 tcp
+#
+open_port() {
+ iptables -t nat -A prerouting_rule -i $1 -p $5 --dport $2 -j DNAT --to-destination $3:$4
+ pdots=`echo $4 | sed 's/-/:/g'`
+ iptables -A forwarding_rule -i $1 -p $5 --dport $pdots -d $3 -j ACCEPT
+}
--- /rom/etc/hotfix 2006-09-12 04:32:01.000000000 +0900
+++ /jffs/etc/hotfix 2000-01-01 09:35:00.000000000 +0900
@@ -0,0 +1 @@
+upgrade_0711
--- /rom/etc/init.d/S45firewall 2006-09-12 04:56:53.000000000 +0900
+++ /jffs/etc/init.d/S45firewall 2006-11-17 22:12:29.000000000 +0900
@@ -105,3 +105,7 @@
}
# check if the connection is already up and add WAN_HOOK rules automatically
env -i ACTION=ifup INTERFACE=wan /bin/sh /etc/hotplug.d/iface/20-firewall
+#
+# Forwarded ports
+#
+/etc/config/openports $WAN
--- /rom/etc/sysctl.conf 2006-09-12 04:32:01.000000000 +0900
+++ /jffs/etc/sysctl.conf 2006-11-08 03:04:39.000000000 +0900
@@ -6,3 +6,4 @@
net.ipv4.tcp_keepalive_time=120
net.ipv4.tcp_timestamps=0
net.ipv4.tcp_vegas_cong_avoid=1
+net.ipv4.ip_local_port_range=4096 8192
このあたりはわずかな修正だが...
--- /rom/etc/init.d/rcS 2006-09-12 22:16:13.000000000 +0900 +++ /jffs/etc/init.d/rcS 2006-11-15 02:44:26.000000000 +0900 @@ -21,13 +21,24 @@ done while :; do + lock -w /var/run/restart-services + + # just in case + lock -u /var/run/network-connection + killall lock + + # grab the locks again lock /var/run/restart-services + lock /var/run/network-connection + killall N50chillispot killall chilli killall dnsmasq ifup lan_noinet ifup wan /etc/init.d/S45firewall + + lock -w /var/run/network-connection for i in /etc/init.d/N*; do $i start 2>&1 done
これは、起動時に問題が起きることがあることへの対策か?
そして、0.7.1 へのアップデートで一番の目玉が、 /usr/lib/webif 以下の変更、 すなわち設定 Web インターフェースの多言語対応なのだろう。 /usr/lib/webif/lang ディレクトリが追加され、 /usr/lib/webif/lang/jp/fon.txt などのファイルに、 ローカライズのための文字列置換表が追加された。 /etc/config/webif に現在選択している言語が設定される。
日本語で設定できるようになったのはいいことだと思うが、 0.7.1 r1 にアップデートしてから、 FON Maps で濃いグリーンで表示されなくなったような気がする... アップデート前は FON_AP 登録位置に濃いグリーンの円が表示されていたのだが、 アップデート直後から薄いグリーン(直近で非アクティブ)の円で 表示されるようになってしまった。 前述したようにバージョン番号は thinclient で FON へ送信されるが、 0.7.1 r1 だと電波を出しているとは認識してもらえなくなってしまったのか? (thinclient の実行頻度を高めてみても、淡い緑のまま...)
もう一点、気づいた不具合として、 設定 Web インタフェースにて WAN 以外の設定を行なわずに何らかの設定を行なうと、 WAN が使えなくなってしまう、という問題がある。 すなわち、/etc/config/fon において
config network wan option mode ''
などとなってしまう。 これだと WAN (つまり有線インタフェース) に IP アドレスが設定されない。 つまり有線もパブリック アクセス ポイント「FON_AP」も使えなくなってしまう。 エイリアス「eth0:1」には常に 169.254.255.1 が設定されるので、 大事には至らないのだが...
eth0:1 Link encap:Ethernet HWaddr 00:18:84:16:XX:XX
inet addr:169.254.255.1 Bcast:169.254.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING PROMISC MULTICAST MTU:1500 Metric:1
Interrupt:4 Base address:0x1000
このような状態になってしまったときは、 この 169.254.255.1 へアクセスするか、 プライベート アクセス ポイント「MyPlace」へアクセスして、 設定 Web インタフェースにて WAN の設定を行なえばよい。 例えば「DHCP」を設定すると、 /etc/config/fon の該当箇所が
config network wan option mode 'dhcp' option ipaddr ''
となるので、「/sbin/ifup wan」を実行するか、 あるいは再起動すれば DHCP で取得した IP アドレスが WAN に設定される。