<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>仙石浩明の日記</title>
	<atom:link href="http://www.gcd.org/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.gcd.org/blog</link>
	<description>CTO兼プログラマ兼システム管理者の視点から</description>
	<lastBuildDate>Thu, 03 May 2012 21:45:02 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.2</generator>
		<item>
		<title>米 at&amp;t のプリペイド SIM カードのデータ通信が改訂 〜 短期滞在者にとっては大幅値上げ！</title>
		<link>http://www.gcd.org/blog/2012/05/939/</link>
		<comments>http://www.gcd.org/blog/2012/05/939/#comments</comments>
		<pubDate>Wed, 02 May 2012 13:04:55 +0000</pubDate>
		<dc:creator>hiroaki_sengoku</dc:creator>
				<category><![CDATA[Hawaii]]></category>
		<category><![CDATA[SIM]]></category>

		<guid isPermaLink="false">http://www.gcd.org/blog/?p=939</guid>
		<description><![CDATA[米国 AT&#38;T のプリペイド SIM カードには、 課金プラン (Rate Plan) として、 月単位のプラン ($50 Monthly Unlimited Plan と $25 Monthly Plan)、  [...]]]></description>
			<content:encoded><![CDATA[<p>
米国 <a href="http://www.gcd.org/blog/2009/04/173/">AT&amp;T のプリペイド SIM カード</a>には、
<a href="https://www.paygonline.com/websc/rateplans/rateplan_en.jsp">課金プラン (Rate Plan)</a> として、
月単位のプラン ($50 Monthly Unlimited Plan と $25 Monthly Plan)、
日単位のプラン (Daily Unlimited Plan)、
そして分単位のプラン (<a href="https://www.paygonline.com/websc/rateplans/GP01_en.jsp">10cent/Minute Plan</a>) がある。
</p>
<table class="ruler" width="100%" style="margin: 6px 0 6px 0;">
<tr>
<th></th>
<th>$50&nbsp;Monthly<br />Unlimited</th>
<th>$25&nbsp;Monthly</th>
<th>Daily&nbsp;Unlimited</th>
<th><a href="https://www.paygonline.com/websc/rateplans/GP01_en.jsp">10cent/Minute</a></th>
</tr>
<tr>
<th width="70">基本料金</th>
<td>月額 $50</td>
<td>月額 $25</td>
<td>使用した日のみ<br />日額 $2</td>
<td>無し</td>
</tr>
<tr>
<th>米国内通話</th>
<td>無制限</td>
<td>250分を超えると<br />10cent/分</td>
<td>無制限</td>
<td>10cent/分</td>
</tr>
<tr>
<th>SMS/MMS</th>
<td>無制限</td>
<td>無制限</td>
<td>無制限</td>
<td>20cent/通</td>
</tr>
</table>
<table class="ruler-right">
<tr>
<th>データ量</th><th>料金</th>
</tr>
<tr>
<td align="right">1GB</td><td align="right">$25</td>
</tr>
<tr>
<td align="right">200MB</td><td align="right">$15</td>
</tr>
<tr>
<td align="right">50MB</td><td align="right">$5</td>
</tr>
</table>
<p>
以前は、
どのプランでも Data Package を購入してデータ通信できた
(少なくとも 4/14 の時点では購入できた) が、
先月中旬頃 (私が改訂に気付いたのは 4/19) に 
Data Package の要件が改訂されてしまい、
月単位プランが必須となってしまった
(追記: <a href="http://www.blogfromamerica.com/wp/?p=7886">4/18</a>
だったそうです)。
つまり、
$50 Monthly Unlimited Plan あるいは
$25 Monthly Plan 以外のプランだと、
Data Package を購入することができなくなってしまった。
その代わり、
通信できるデータ量が増えて、
$25 だと (4/14 の時点では) 500MB だったのが 1GB ぶん通信できるようになった。
</p>
<p>
<img src="http://www.gcd.org/sengoku/picts/GoPhone.jpg" alt="go phone $2 PER DAY" width="292" height="389" class="pict-left" />
Data Package が Monthly Plan 必須になってしまうと、
基本料金無料をウリにしていた (スマホな) GoPhone の立場は、
どーなるんだ...
と思っていたら、<br />
← 「$2 PER DAY」
な go phone に、
「SEE ASSOCIATE」(店員にお問い合わせ下さい)
と書いたシールが貼られていた
(この写真は <a href="http://www.pearlridgeonline.com/store/radioshack/412/2138817518">Pearlridge の RadioShack</a> で撮影)。
at&amp;t が唐突に Data Package の要件を変えるものだから、
ショップとしては困惑しているのではないか？
</p>
<p>
Data Package を購入せずにデータ通信を行なうと、
5KB あたり 1セントも課金されてしまい現実的ではない
(例えば 100MB で $200)。
メガバイト単位の通信が必要 (スマホなら当然) なら、
月単位プランを選択せざるを得ないが、
基本料金 $25 (250分ぶんの通話料が含まれる) がかかるので、
短期滞在 (一週間以内とか) だと少々割高となる。
</p>
<p>
例えば、
2日間の滞在で 200MB 使う場合 (フツーはそんなに使わない) だと、
$25+$15=$40 (約 3400円) となって、
<a href="http://mb.softbank.jp/mb/international/roaming/area_price/packet/">海外パケットし放題</a>を使う場合 (2980円*2=5960円)
と比べて (SIM を購入するなどの手間を考えると) 
あまり価格メリットが無くなってしまう。
もちろん、
滞在日数が多くなればなるほど両者の差は開く一方なので、
大抵の場合は SIM を購入する方が有利。
</p>
<blockquote>
ちなみに、
私が初めて <a href="http://www.gcd.org/blog/2010/05/582/">at&amp;t の Data Package を購入した</a>
2010年5月の時点までは、
「<a href="https://www.paygonline.com/websc/rateplans/GPUM_en.jsp">$1 Mobile to Mobile Plan</a>」
という日単位のプランがあった (追記: 2010年10月3日に廃止されたらしい)。
この $1 が値上げされて $2 になったのが、
現在の Daily Unlimited Plan なわけで、
もちろん今この
「<a href="https://www.paygonline.com/websc/rateplans/GPUM_en.jsp">$1 Mobile to Mobile Plan</a>」
を選択することは不可能だが、
以前からのユーザであればこの $1 プランを使い続けることは可能であるようだ。
しかも、
$1 プランは (例外的に) Data Package の購入が可能！
at&amp;t がこの $1 プランを廃止する (例えば現行の日単位プランへ強制移行させる) 
可能性は常にあるものの、
もし今 $1 のユーザであるなら、
その SIM を失効させないよう refill し続けるべきだろう
(クレジットカード払いで自動的に refill してくれる
<a href="https://www.myprepaidrefill.com/MobilityUSWeb/displayAutoRefillSummary.do">Auto-Refill</a> 
の設定をしておくと便利)。
</blockquote>
<p>
滞在日数が一ヶ月近くになれば、
月単位プランが必須でも、
さほどデメリットとはならなくなるが、
月単位プランは、
電話を使用しない月も自動的に基本料金を課金されるので、
次回の訪米に備えて SIM カードを維持したい場合は、
基本料金が不要な分単位プラン (あるいは日単位プラン) に変更しておく必要がある。
</p>
<p>
ところが、
課金プランの変更は 
<a href="https://www.paygonline.com/">Web 上</a>では 
(今のところ) 不可能。
現在の月単位プランの
「切れ目」
で分単位プランへ変更するといった
「予約」
もできない。
それはあまりに融通が効かなさすぎ、
と思ったので、
2箇所の at&amp;t ショップ で直談判してみたのだけど、
できるのは今この場でプラン変更することだけで、
一ヶ月後とかの変更は承れないと突っぱねられた。
しかも、
プラン変更した瞬間、
Data Package の残高は失われるらしい。
</p>
<p>
というわけで、
データ通信が不要になった時 (日本に帰国した後とか) に、
+1-800-901-9878 (<a href="https://www.google.com/voice">google voice</a> を使えば無料。
at&amp;t なケータイからは 611 でも可) に電話して、
「automated customer service」
にアクセスし、
分単位プランへ変更するのがよさげ。
</p>
<p>
「automated customer service」
というのは、
音声自動応答 (Interactive Voice Response) システムで、
音声 (もちろん英語) で操作する必要があり、
英語が苦手な私にとってはハードルが高い。
日本に帰国した後だと、
万一プラン変更に失敗するとリカバリ手段が無い
(米国にいる間なら、
at&amp;t ショップに直談判に行ける)
ので、
米国滞在最終日に課金プラン変更を行なうことにした。
変更後はデータ通信ができなくなってしまうが、
私は 
<a href="http://www.gcd.org/blog/2011/05/788/">T-Mobile の SIM</a> 
も持っていて、
私のメイン端末である
<a href="http://www.gcd.org/blog/2012/03/923/">Galaxy Nexus</a> 
は T-Mobile でも 3G 通信できるので問題無い。
</p>
<blockquote>
T-Mobile の SIM を持っているのに何故 at&amp;t の SIM を買ったかというと、
T-Mobile は圏外になったり EDGE (2G) でしか繋がらなくなったりする場所が多い
(大きな建物の中とか、山の中とか) ため。
以前のメイン端末 Nexus S は at&amp;t の 3G 通信 (1900MHz) に対応していないので 
T-Mobile SIM を使っていたが、
今のメイン端末 Galaxy Nexus は、
at&amp;t と T-Mobile 両方の 3G 通信に対応している。
</blockquote>

<p>
まず、
at&amp;t の SIM を入れた電話
(<a href="http://www.gcd.org/blog/2011/01/706/">Galaxy S</a>)
でデータ通信を無効にしておく
(データ通信が有効のままだと、
課金プランを変更した直後から 5KB あたり 1セント課金されてしまう)。
</p>
<p>
次に、
611 をダイヤルして
「automated customer service」 へアクセス。
すると残高や現在利用している課金プランのアナウンスがあった後、
「What's go on ?」
と聞かれる。
そんなこと聞かれても... 
何と答えてよいやら... 
と絶句していると、
</p>
<blockquote>
Main menu.  What's like to do ?  You can say:<br />
"add money",<br />
"features",<br />
"rate plan",<br />
"account ballance",<br />
or "more options".
</blockquote>
<p>
と、
助け船を出してもらえるので、
元気良く
「rate plan !」
と発声してみる。
すると...
無情にも
「Oh, I didn't catch that.」
とのお答え。
元々英語には自信がないのだけど、
さらに自信を失う。
やっぱり
「r」
の発音がダメなのかなぁ... ;-(
</p>
<p>
落ち込んでいるとさらに助け船を出してくれる:
</p>
<blockquote>
Here is your all choices:<br />
To add money to your account, say "add money" or press 1.<br />
To check your feature packages or buy features, say "features" or press 2.<br />
To change your rate plan, say "rate plan" or press 3.<br />
To get your account balance, say "account balance" or press 4.<br />
Or say "more options" or press 5.<br />
</blockquote>
<p>
最初からそう言ってくれればよいものを... と思いつつ 
「3」 
を押す。
</p>
<p>
通じなければプッシュボタンでの操作を案内してくれる、
ということが分かったので、
気にせずテキトーに発声して進む。
次なる選択枝は:
</p>
<blockquote>
To check whatever plans are available, press 1.<br />
To hear your plan summery again, press 2.<br />
To hear your plan detail, press 3.<br />
Or if you're done here, press pound key.
</blockquote>
<p>
「1」
を押して現在選択可能なプランを列挙させる。
すると、
</p>
<blockquote>
Are you currently using a smartphone device ?<br />
If you don't know, say "I'm not sure".
</blockquote>
<p>
と聞いてくる。
おそらくスマホだと、選択できるプランが月単位のプランに限定されるのだろう。
そこで (今まさにスマホを使っているのだけど) 力強く
「No !」
と答える。
さすがにこれは聞き返されること無く一発で通じて (←当たり前)、
</p>
<blockquote>
What type of plans would you like to hear about ?<br />
You can say:<br />
"monthly",<br />
"daily",<br />
or "by the minutes".<br />
Or say "stay with my current plan".<br />
</blockquote>
<p>
と聞いてくるので、
「minutes」
と答える。
</p>
<p>
すると、
「OK, that's the 10 cents per minute plan.」
と返事が返ってきて、
分単位プランの概要説明がある。
そして、
</p>
<blockquote>
This is the summery of the plan,<br />
but for full description, you should say "plan detail".<br />
You can also say "switch to this plan",<br />
"go back to the lists of plans",<br />
or "stay with my current plan".<br />
</blockquote>
<p>
と聞かれるので、
「switch」
とだけ答える。
単語だけで答える方が通じやすいようだ。
</p>
<p>
「10cent/Minute Plan」
に変更すると Data Package を失う旨の警告があった後、
</p>
<blockquote>
To confirm you are right to go heading to switch to this plan,<br />
please say "change my plan",<br />
otherwise, say "cancel".
</blockquote>
<p>
と聞かれる。
最終確認のようだ。
「change my plan」
と答えると、
「All right, just a minute.」
と返事が返ってきて、
チクタクチクタク (効果音) の後、
「OK, you are all set.」
と言われてプラン変更が完了する。
</p>
<p>
試しに
「*777*3#」
にダイヤルして Data Package の残高を調べてみると、
「0 kilobytes」
と表示された。
プラン変更前は 400MB byte 以上残っていたのだが...
次回からは、
訪米直前に Data Package を購入し (月単位プランへの変更を強制される)、
日本に帰国してから分単位プランへ戻す、
といった運用がよさげ。
</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gcd.org/blog/2012/05/939/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>新規一括 0円の Galaxy Nexus (SC-04D) を買ってみた 〜 国際版 Galaxy Nexus と全く同じにする</title>
		<link>http://www.gcd.org/blog/2012/03/923/</link>
		<comments>http://www.gcd.org/blog/2012/03/923/#comments</comments>
		<pubDate>Mon, 05 Mar 2012 11:21:31 +0000</pubDate>
		<dc:creator>hiroaki_sengoku</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[SIM]]></category>

		<guid isPermaLink="false">http://www.gcd.org/blog/?p=923</guid>
		<description><![CDATA[よほど在庫が積み上がってるのか、 ドコモ SC-04D Galaxy Nexus が新規一括 0円で売っていた。 あんなに大々的な宣伝を行なっておいて何をやってるんだか... 私が見た店は、 0円の条件として、 ひとりで [...]]]></description>
			<content:encoded><![CDATA[<p>
<img src="http://www.gcd.org/sengoku/picts/SC-04D_option.jpg" class="pict-right" width="308" height="231" alt="mandatory option" />
よほど在庫が積み上がってるのか、
ドコモ SC-04D Galaxy Nexus が新規一括 0円で売っていた。
あんなに<a href="http://www.gcd.org/sengoku/picts/SC-04D_advertize.jpg">大々的な宣伝</a>を行なっておいて何をやってるんだか...
</p>
<p>
私が見た店は、
0円の条件として、
<a href="http://www.nttdocomo.co.jp/charge/discount/hitoridemo/">ひとりでも割50</a> が必須。
つまり 2年間の契約期間中に割引サービスを廃止 (あるいは回線ごと解約)
する場合は、
9,975円の解約金が必要となる。
契約事務手数料 3000円の他、
初月のみ
「<a href="http://www.nttdocomo.co.jp/charge/packet/pake_hodai_w2/">パケ・ホーダイ ダブル2定額</a>」
など諸々のオプション (写真→) を付ける必要があり、
違約金以外に 5000〜7000円ほどかかる。
加入条件のオプションの多さに圧倒されるが、
「パケホダブル」
以外のオプションは初月無料がほとんどで、
今月中に解約すれば費用はかからない。
パケホダブルは月額2,100円だが日割が適用されるので、
月末近くに契約すればもっと安くなる (あいにく私が買ったのは月初だが)。
</p>
<p>
なんたって Galaxy Nexus である。
わずか 3ヶ月前に HK$5398 (約 54,000円) もしたケータイが、
2万円かからずに入手できるのは見逃せない。
<a href="https://www.facebook.com/photo.php?fbid=182112331902475">思わず衝動買い</a> 
(0円なので 「買った」 とは言えない?) してしまった。
</p>
<p>
<a href="http://www.gcd.org/sengoku/picts/SC-04D_SystemUpdate.png"><img src="http://www.gcd.org/sengoku/picts/SC-04D_SystemUpdate.png" class="pict-right" width="240" height="427" alt="SC-04D System Update Dialog" /></a>
帰宅して SC-04D の電源を入れようとすると...
う、電源が ON のままだったか。
てっきりショップで電源を OFF にして渡してくれたものと思い込んでいた。
そしてディスプレイが点灯してそこに表示されたのは、
無情な
「システムアップデート」
の文字。
</p>
<p>
あとで分かったが、
ショップを出て帰宅するまでの短い時間に、
9.3MB ものアップデートファイル
(yakjusc_ITL41D_to_ICL53F.zip)
が転送されていて、
この日のパケット代が、
いきなり 3800円。
<a href="https://www.facebook.com/sengoku.hiroaki/posts/182775808502794">SC-04D を安く入手しようという目論見が、いきなりパー</a>。
なにもこんなタイミングでアップデートファイルを送りつけなくても...
無線LAN に接続するまで待って欲しかった。
</p>
<p>
で、
こんなアップデートのお知らせはサックリ無視して真っ先に行なったのは、
ブートローダのアンロック (fastboot oem unlock)。
いきなりドコモの保証がパー。
</p>
<p>
一度フツーに起動させてフラッシュメモリの初期化を行なった後
(一度フツーに OS を起動しないと、
フラッシュメモリにアクセスできない)、
<a href="http://clockworkmod.com/rommanager">Clockwork Mod Recovery</a>
を fastboot で起動する (fastboot boot &lt;kernel&gt;)。
そして、
初期状態のドコモ純正ROM を、
ベースバンド込みで丸ごとバックアップ。
これでいつでも元の状態に戻せるようになったので、
ClockworkMod Recovery をフラッシュメモリの
「recovery」
領域 (リカバリ用のカーネルを格納する領域) に書込む 
(fastboot flash recovery &lt;kernel&gt;)。
</p>
<pre class="terminal-scroll">
senri:~ $ fastboot oem unlock
...
OKAY [ 52.022s]
finished. total time: 52.022s
senri:~ $ fastboot boot recovery-clockwork-5.5.0.2-maguro.img
downloading 'boot.img'...
OKAY [  0.553s]
booting...
OKAY [  0.329s]
finished. total time: 0.882s
senri:~ $ adb shell
~ # dd if=/dev/block/platform/omap/omap_hsmmc.0/by-name/radio of=/sdcard/SC04DOMKKD.img bs=1024
16384+0 records in
16384+0 records out
16777216 bytes transferred in 6.601 secs (2541617 bytes/sec)
~ # exit
senri:~ $ adb pull /sdcard/SC04DOMKKD.img
4569 KB/s (16777216 bytes in 3.585s)
senri:~ $ mkdir backup
senri:~ $ adb pull /sdcard/clockworkmod/backup/ backup/
pull: building file list...
pull: /sdcard/clockworkmod/backup/2012-03-04.01.09.21/nandroid.md5 -> backup/2012-03-04.01.09.21/nandroid.md5
pull: /sdcard/clockworkmod/backup/2012-03-04.01.09.21/cache.ext4.tar -> backup/2012-03-04.01.09.21/cache.ext4.tar
pull: /sdcard/clockworkmod/backup/2012-03-04.01.09.21/data.ext4.tar -> backup/2012-03-04.01.09.21/data.ext4.tar
pull: /sdcard/clockworkmod/backup/2012-03-04.01.09.21/system.ext4.tar -> backup/2012-03-04.01.09.21/system.ext4.tar
pull: /sdcard/clockworkmod/backup/2012-03-04.01.09.21/recovery.img -> backup/2012-03-04.01.09.21/recovery.img
pull: /sdcard/clockworkmod/backup/2012-03-04.01.09.21/boot.img -> backup/2012-03-04.01.09.21/boot.img
6 files pulled. 0 files skipped.
4308 KB/s (384848109 bytes in 87.229s)
senri:~ $ fastboot flash recovery recovery-clockwork-5.5.0.2-maguro.img
sending 'recovery' (5300 KB)...
OKAY [  0.552s]
writing 'recovery'...
OKAY [  1.015s]
finished. total time: 1.567s
</pre>
<p>
再び通常起動して、
(今度は抜かり無く)
無線LAN の設定を行なってから、放置
(念のため、
「データ通信を有効にする」
を無効にしておく)。
ほどなく再びアップデートファイルがダウンロードされてきた。
</p>
<p>
フラッシュに書込んだ ClockworkMod Recovery を起動して、
/cache に格納されていた
94ec403ff247.update_yakjusc_ITL41D_to_ICL53F.zip (アップデートファイル)
を /sdcard へコピー。
で、ClockworkMod Recovery からこの zip ファイルをインストール。
この時点で (ClockworkMod Recovery を書込んだ) recovery 領域は、
ドコモ (というか Google) 純正リカバリ用カーネルで上書きされる。
</p>
<p>
これでビルド番号が ICL53F.SC04DOMLA1 になった。
ちなみに末尾の 
「LA1」
というのは、
「L」
が 2012年 (L は 12番目のアルファベットだから) を意味し、
その次の
「A」
が 1月 (A は 1番目のアルファベット) を意味し、
その次の
「1」
は、
その月にリリースされた最初のバージョンであることを意味する。
</p>
<p>
「L53F」 
も同様に、
「L」
が 2011年第4四半期 (2009年第1四半期を A として) を意味し、
「53」
が、
その四半期で 53日目であることを意味し、
「F」
は同じ日の 6番目のリリースであることを意味するらしい。
先頭の
「I」
は、
Ice Cream Sandwich の頭文字。
</p>
<p>
このバージョンのドコモ純正ROM も、
上記と同様に ClockworkMod Recovery を使って、
ベースバンド込みで丸ごとバックアップ。
無線LAN の設定を行なったので厳密には初期状態ではないが、
初期化するのが面倒なので、
まあよしとする。
</p>
<p>
以上で、
いつでもドコモ純正ROM に戻る手段を確保できたので、
ここでドコモ純正ROM にサヨナラする。
私が普段使ってる Galaxy Nexus (3ヶ月前に香港で買った) を丸ごとバックアップし、
そのバックアップファイルを SC-04D へ、
ClockworkMod Recovery を使って丸ごとリストア
(もちろん、リストアする代わりに 
<a href="http://code.google.com/android/nexus/images.html">Google 純正ROM</a> を書き込んで、
国際版の初期状態にしてもよい)。
</p>
<p>
<a href="http://www.gcd.org/sengoku/picts/GalaxyNexus.jpg"><img src="http://www.gcd.org/sengoku/picts/GalaxyNexus.jpg" class="pict-left" width="414" height="387" alt="Galaxy Nexus * 2" /></a>
左が香港で買った Galaxy Nexus i9250 GSM (もちろん SIM ロックフリー),<br />
右が今回買ったドコモ SC-04D
</p>
<p>
裏ブタ記載の文字が異なる
(なぜ SC-04D には Google ロゴがない?)
他は、
全く同じ外観。
丸ごとリストアしたので、
フラッシュメモリの中身も全く同じ 
(もちろん IMEI など、端末固有のデータは異なる)。
</p>
<p>
丸ごとリストアしたことによって
OS も書き換えてしまったので、
ドコモのテザリングの制約 (勝手に APN が dcmtrg.ne.jp に切り替わるとか)
から解放される (はず)。
「パソコンなどの外部機器を接続した通信」
ではなく
スマートフォン定額通信の範囲でテザリングできるはずだが、
私は興味がない (ドコモは今月一杯で解約するつもりだし) ので試していない。
OS が書き変わっても、
IMEI 上は
「ドコモ純正端末」
なので、
フツーに 
<a href="http://www.nttdocomo.co.jp/service/provider/spmode/">spモード</a>を利用できる。
こうなってくると、
ドコモが何のために接続する端末の IMEI を制限しているのか分からなくなる。
</p>
<p>
二つの Galaxy Nexus の OS は同じになったが、
SC-04D にはまだ SIM ロックがかかっている。
ドコモショップで 
<a href="http://www.nttdocomo.co.jp/support/procedure/simcard/unlock_dcm/">SIMロック解除</a>の手続きを行なってくれるが、
ブートローダをアンロックした Nexus も対象となるのか?
ブートローダだけならまだしも、
OS ごと入れ替えてしまっていても拒否されないのか?
</p>
<p>
SIMロックは、
(Samsung製) Android 端末の場合
/data/radio/nv_data.bin
などで設定されている。
このファイルを
「正しく」
書き換えることができれば
SIMロックを解除できるのだが、
このファイルが改変されていないか検証するために、
/data/radio/nv_data.bin.md5
に MD5 値が保存されている。
そして残念なことに、
この MD5 の算出方法が不明。
もちろん、
単純に nv_data.bin の MD5 を算出するだけではダメで、
何らかの秘密の seed が必要なのだと思われる
(ファイル名の通り MD5 が使われていると仮定してだが)。
</p>
<p>
MD5 の値が一致しなかったなどの理由で検証にパスしなかった場合、
あるいは (Android を初期化したなどの理由で)
そもそも /data/radio/nv_data.bin が存在しなかった場合は、
/factory/nv_data.bin を使って
/data/radio/nv_data.bin が作られる。
ところが、
/factory/nv_data.bin にも、
/factory/nv_data.bin.md5 があって、
その内容が書き換えられないように保護されている。
</p>
<p>
/factory/nv_data.bin が検証をパスしないと、
/factory/.nv_data.bak が使われるらしい。
何段もの防御があって、
なかなか突破するのが難しそうである。
そこで、
改変した nv_data.bin を /factory/nv_data.bin と
/factory/.nv_data.bak にコピーして、
検証が通らなくて書き戻そうにも、
本来の nv_data.bin を参照できないようにしてみた。
</p>
<p>
すると...
驚いたことに、
ドコモ以外の SIM でも使えてしまった。
google で検索すると、
あちこちで SIMロックの解除方法を説明したページが見つかるが、
ほとんど (全て?) は同様の方法であるようだ。
しかし、
この方法には重大な欠点がある。
それは、
IMEI の値が
「004999010640000」
になってしまう点。
キャリア側で IMEI の値をチェックしていなければ、
そのまま使えてしまうのかもしれないが、
これでは
「ここに不正改造無線局があります〜」
と吹聴して歩き回るのと大差なく、
甚だ具合がよろしくない。
</p>
<p>
<img src="http://www.gcd.org/sengoku/picts/SC-04D_SIM_UnlockPIN.jpg" class="pict-right" width="321" height="428" alt="SIM Unlock PIN" />
というわけで万策尽きたので、
解除コード (Unlock Code)
を業者から買うことにした。
だいたい $30 前後で、
ドコモ (3,150円) より若干安い。
この期に及んでドコモのサービスを使わないのは、
前述した懸念点があるのと、
ドコモショップでは
<a href="http://blog.goo.ne.jp/clausewitz1780-1831/e/036fed0ffb7c0721ff769ad21a69b2c2">「解除PIN」 を教えてもらえなかった</a>、
という話をネット上で見かけたため。
</p>
<p>
ドコモショップの店長が、
<a href="http://blog.goo.ne.jp/clausewitz1780-1831/e/036fed0ffb7c0721ff769ad21a69b2c2">「このコードはドコモの内部情報になるため、お客様にはお伝えできません」</a>
と言ったらしいが、
この話が本当なら、
とんでもない話だと思う。
3,150円も取っておきながら
PIN 一つ教えないとはどーいうことだ。
</p>
<p>
ドコモショップで 
SIM ロック解除したケータイを海外に持って行き、
現地の SIM を入れて電源を入れたら、
「SIMネットワークのロック解除PIN」
を入力する画面になってしまい往生した、
という怨嗟の声をネット上で見かけるが、
おそらく何らかの理由で /data/radio/nv_data.bin の内容が壊れてしまい、
/factory/nv_data.bin の内容で書き戻されたために、
ロック解除PIN の入力が必要になってしまったものと思われる。
</p>
<p>
つまり、
ロック解除PIN を入力して SIM ロックを解除した後、
/data/radio/nv_data.bin および /data/radio/nv_data.bin.md5 を
/factory へコピーしておけばこのような事態に陥ることを回避できる。
ただし、
Android の root 権限が必要。
root 権限がないと、
そもそも /data/radio/nv_data.bin を読むことができない。
だから、
何かあったときのため、
ロック解除PIN を記録しておくことが重要。
</p>
<p>
<a href="http://www.cellunlocker.net/samsung-unlock.php">Cell Unlocker .net</a>
で、
device 名として
「Galaxy Nexus」、
SIM ロック先のキャリアとして、
「All Asia Countries」
を指定し、
IMEI (「*#06#」 をダイヤルすると表示される) を入力した。
すると <a href="http://www.paypal.com/">PayPal</a> の支払い画面に遷移するので、
$29.99 の支払いボタンを押すだけ。
</p>
<p>
7時間半後、
ロック解除PIN が書かれたメールが送られてきた。
メールには、
</p>
<blockquote>
Video proof will be required if code does not work, 
it's a good idea to film inputting the unlock code 
so we can help trouble shoot what the problem is.
</blockquote>
<p>
と書かれていたので、
まず、
デジカメ (ビデオカメラは持ってない) 
を三脚にセットして動画撮影する準備を整えた。
<a href="http://www.gcd.org/blog/2012/02/912/">SingTel の SIM</a> (ドコモ以外ならどこでも) を SC-04D に入れて電源を入れる。
すると、
↑ の写真にあるような
「SIMネットワークのロック解除PIN」
を入力する画面になったので、
デジカメで動画撮影しつつ、
メールに書かれていた unlock code を入力した。
すると、
「ネットワークのロック解除をリクエスト中...」
と表示され、
すぐ
「ネットワークロックを解除しました。」
と表示された。
数秒後、
Android のホーム画面が表示された。
</p>
<p>
以上で、
二つの Galaxy Nexus は (IMEI 以外は) 完全に同じになった。
今まで Galaxy Nexus で使っていた Softbank SIM を、
SC-04D に入れて、
今後は SC-04D のほうを使ってみようと思う。
普通に使っている限り、
たぶん、何の違いも見いだせないに違いない。
</p>]]></content:encoded>
			<wfw:commentRss>http://www.gcd.org/blog/2012/03/923/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>シンガポールで SingTel と StarHub プリペイド SIMカードを買ってみた</title>
		<link>http://www.gcd.org/blog/2012/02/912/</link>
		<comments>http://www.gcd.org/blog/2012/02/912/#comments</comments>
		<pubDate>Tue, 21 Feb 2012 07:53:09 +0000</pubDate>
		<dc:creator>hiroaki_sengoku</dc:creator>
				<category><![CDATA[SIM]]></category>

		<guid isPermaLink="false">http://www.gcd.org/blog/?p=912</guid>
		<description><![CDATA[チャンギ国際空港 Terminal 3 に着いて入国審査を終えると、 (Baggage Claim に行く前の) Transit Lounge に RHB Bank の両替所があって、 SingTel の Prepaid [...]]]></description>
			<content:encoded><![CDATA[<p>
<a href="http://www.changiairport.com/">チャンギ国際空港</a> 
Terminal 3 に着いて入国審査を終えると、
(Baggage Claim に行く前の) Transit Lounge に
<a href="http://rhb.com.sg/">RHB Bank</a> の両替所があって、
<a href="http://info.singtel.com/personal/communication/mobile/prepaid-plans/prepaid-mobile">SingTel の Prepaid SIM</a> を購入できた。
支払いは現金のみだが、
入国審査ゲートを抜けた直後に ATM があり、
既にシンガポールドルを得ていたので、
スムーズに SIM を購入できた
(もっとも、両替所なのだから日本円でも買えるはず)。
と、ここまで飛行機を降りてから (入国審査も含めて) 10分もかかっていない。
初めて訪れた国で、
ここまで手早く SIM を購入できたのは初めて。
</p>
<img src="http://www.gcd.org/sengoku/picts/Changi_RHB.jpg" alt="RHB Bank Currency Exchange" width="427" height="320" />
<p>
RHB Bank 両替所 ↑ の裏は UOB (大華銀行) の両替所になっていて、
そこでは <a href="http://www.starhub.com/mobile/prepaidcards/prepaidmobile.html">StarHub の SIM</a> 
を購入できたことを後で (出国時に) 知った。
「裏には UOB の両替所があるよ!」
って看板を出しておいて欲しい...
入国時は時間がない 
(荷物が出て来る前に Baggage Claim にたどり着きたい)  
のだから、
カウンターをぐるっと回って裏まで見に行っている余裕はない。
</p>
<p>
パックツアー (といっても空港⇔ホテルの送り迎え以外は全日程終日自由行動)
なので SIM を購入するなどの (他のツアー客を待たせる) 
単独行動は慎まなければならないが、
この空港のように Baggage Claim 以前に (SIM を売ってる) 両替所があると、
荷物が出てくるまでの時間を有効に活用できるので、
とても助かる。
</p>
<p>
ただし、
街中では S$15 (約 900円) で売ってる額面 S$18 の SIM は空港内では買えず、
S$28 (約 1700円) あるいは S$50 のみ。
StarHub (後述) も、SIM (S$15) だけで買うことはできず、
Top-Up カードと抱き合わせ。
さらに、
空港ではデータ通信専用の SIM は売っていないらしい (未確認)。
私にとって通話機能は必須 (妻との連絡のため) なので、
データ通信専用 SIM には興味がなく、
売ってるか否かの確認はしていない。
街中だと数多くの SIM から好きな電話番号の SIM を選べたりもするので、
急いでいるのでなければ街中で買った方がいいかも。
</p>
<p>
税関を抜けてツアーガイドに会ったら、
他のツアー客はまだ出てきていないとのことなので、
もう一枚、
別のキャリアの SIM を買おうと思って到着ロビーを見渡す。
UOB (大華銀行) の両替所があったので、
StarHub の SIM を購入した。
シンガポールには SingTel と StarHub の他に 
<a href="http://www.m1.com.sg/">M1</a> もあるが、
あいにく <a href="http://www.m1shop.com.sg/">M1 Shop</a> 
は少し離れたところ (到着ロビー中央) にあって目に入らなかった。
</p>
<p>
<a href="http://www.gcd.org/sengoku/picts/StarHub_MaxMobile.jpg"><img src="http://www.gcd.org/sengoku/picts/StarHub_MaxMobile.jpg" alt="StarHub MaxMobile" width="214" height="285" class="pict-left" /></a>
ホテルに向かうツアーバスの中で、
StarHub の SIM を Galaxy Nexus に入れてみる。
「98500000」
をダイヤルして SIM カードを activate.
次に
「*131#」
にダイヤルすると、
左の写真のような表示 
(<a href="http://www.gcd.org/sengoku/picts/StarHub_MaxMobile.jpg">クリックで拡大</a>) 
になる。
</p>
<p>
電話アプリに、
こんなメッセージを表示したり、
こちらからの返答を送信したりする機能があったとは。
USSD (<a href="http://en.wikipedia.org/wiki/Unstructured_Supplementary_Service_Data">Unstructured Supplementary Service Data</a>)
って言うらしい。
2G 時代の昔からあるプロトコルだが、
(「*〜#」
へダイヤルして終わりとするのではなく)
ユーザからの入力を求める場面で使われるケースは珍しいように思う。
SMS に似ているが、
USSD は 182 文字までの通信で、
SMS と違ってセッション中は接続しっぱなしらしい。
</p>
<p>
私は 
「1GB at S$7 (7D)」
つまり S$7 (約 420円) で 7日間有効な 1GB プランを選んだ。
転送データ量が 1GB を超えた場合にどうなるか 
(1GB ごと自動的に S$7 引かれるのか、
1GB に達した時点で通信不能になるのか、
はたまた S$0.27/KB の従量課金になるのか) は不明。
「3」
を送信すると確認画面が表示されるので
「Confirm」
するとデータ通信できるようになる。
</p>
<p>
続いて、
SingTel の SIM を (妻の) Galaxy Note に入れた。
こちらは activate 不要で即、使える。
試しに Galaxy Nexus から電話をかけてみたら、
無事 Galaxy Note が鳴った。
データ通信を行なうには、
APN として
「hicard」
を設定する。
5MB までのデータ通信が無料で可能。
5MB くらいはスマホだとすぐ使い切ってしまうので、
「727050」
へ
「3」
とだけ書いた SMS を送る。
すると、
以下の SMS が 727011 から届いた:
</p>
<blockquote>
Pls reply with the options:<br />
1. Check for existing Data bundle/expiry date for Notebook/Tablet<br />
2. Subscribe to Data bundle for Notebook/Tablet
</blockquote>
<p>
送信元の電話番号は (少なくとも) 下3桁の部分は毎回変わる。
選択は SMSアプリでフツーに返信すればよい。
USSD による操作方法を見た後だと、
SMS による操作はやぼったく見える。
「2」
を返信すると、
以下の SMS が 727012 から届いた:
</p>
<blockquote>
Pls reply with the options:<br />
1. Value Surfer 10MB @ $1 valid for 7 days<br />
2. Super Surfer 1GB @ $7 valid for 7 days<br />
3. Unlimited Data Plan @ $6. Valid for 1 day<br />
4. Unlimited Data Plan @ $15. Valid for 3 days<br />
5. Unlimited Data Plan @ $25.  Valid for 7 days
</blockquote>
<p>
私は
「2」
を返信した。
つまり 7日間有効な 1GB プラン。
無制限データプランも魅力的だったのだが、
5日間の滞在で 1GB 以上使うとは思えなかったため。
</p>
<p>
すると、
確認を求める以下のような SMS が 727015 から届いたので、
</p>
<blockquote>
You have selected to buy Super Surfer Pack of 1GB. $7 will be deducted from your Main Account balance. To confirm, reply 1.
</blockquote>
<p>
「1」
を返信した。
</p>
<p>
以上で、
2枚の SIM とも通話・通信が可能になった。
両 SIM とも HSPA
(<a href="http://ja.wikipedia.org/wiki/HSPA">High Speed Packet Access</a>)
によるデータ通信が可能だが、
1Mbps 程度の転送速度しか出ていなかったように思う。
StarHub の方が下り 2Mbps くらいまで出ることがあるものの、
上りに関しては StarHub は (場所によっては) 速度の低下が著しく 
(100kbps 以下になる)、
SingTel の方が安定していた。
両 SIM とも (観光地など) 人が大勢集まる場所では接続できないケースが頻発し、
(同程度にサービスエリアが狭い) 
香港と比べるとインフラ整備が追い付いていないような印象を受けた。
</p>
<p>
StarHub は、 
Galaxy Nexus に初めから登録されていた APN 
「internet」 
のままでも通信できたが、
場所によっては接続ができないこともあったため、
「shppd」
に設定し直した。
「shppd」
は StarHub PrePaiD の意味だと思うが、
この設定が必須かどうかは不明。
</p>
<p>
その晩、
ホテルに戻って Galaxy Nexus (StarHub SIM) をポータブルWi-Fiアクセスポイント
(いわゆるテザリング)
として利用したら、
(このアクセスポイントに接続した) 
ノート PC で WWW ブラウズがほとんどできなくて驚いた。
ssh だとそれなりに通信できるので、
TCP/IP セッションを短時間に大量に張ろうとすると、
パケット落ちが著しいのだと思われる。
画像がたくさんある WWW ページ (きょうび、そういうページばかりだけど) 
をアクセスしようとすると、
全くといっていいほど画像が表示できない。
</p>
<p>
これでは使い物にならないと思い、
Galaxy Note (SingTel SIM) をポータブルWi-Fiアクセスポイントとして利用したら、
(1Mbps 程度なので速くはないが) それなりに WWW ブラウズもできる。
下り転送速度だけを見ると StarHub の方がむしろ速く見えるだけに、
ユースケースに合わせた評価方法が重要と再認識。
</p>
<p>
<a href="https://www.facebook.com/photo.php?fbid=171394882974220"><img src="https://fbcdn-sphotos-a.akamaihd.net/hphotos-ak-ash4/338331_171394882974220_100003111270011_249530_852574613_o.jpg" width="356" height="267" class="pict-right" alt="" /></a>
いくら下り通信速度が速くても、
わたし的にはホテルでテザリングができなければ論外なので、
翌朝ホテル近くのセブンイレブンで 
<a href="https://www.facebook.com/photo.php?fbid=171394882974220">SingTel の SIM を買い直した</a>。
パスポート等を提示する必要があるが、
(空港と違って) 
S$15 で買えるし、
複数の SIM の中から好きな電話番号の SIM を選ぶことができる。
</p>
<p>
ホテルに戻って、
朝食を食べながらデータ通信の設定を行なう。
シンガポール滞在は 3日後の 15:00 まで (78時間くらい) なのだけれど、
ものは試しと
「4. Unlimited Data Plan @ $15. Valid for 3 days」
つまり 3日間有効な無制限データプランにしてみた。
これでテザリングも転送量を気にせず行なえる。
最終日は使えなくなってしまうが、
(7日間データ通信できる) StarHub の SIM もあるから構わないかな...
と思っていたら、
72時間が経過した後 (初日を 1日目と数えれば 4日目の朝) も問題無く使えてしまった。
飛行機に搭乗した 15:30 ギリギリまで通信できたのは何故なんだろう...?
</p>
<p>
S$20 未満の SIM だと有効期限が 120日 (S$20 以上だと 180日)。
幸い、
<a href="https://inno.ideas.singtel.com/easyonlinetopup/">Online Top-Up</a>
がクレジットカードで可能であるようなので、
期限切れになる前に Top-Up を行なえば、
シンガポールを訪れなくても SIM を維持し続けることが可能 (と思われる)。
</p>]]></content:encoded>
			<wfw:commentRss>http://www.gcd.org/blog/2012/02/912/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>adb (Android Debug Bridge) 経由で rsync を使ってバックアップできるようにしてみた 〜 shell の echo back を回避する方法</title>
		<link>http://www.gcd.org/blog/2012/02/900/</link>
		<comments>http://www.gcd.org/blog/2012/02/900/#comments</comments>
		<pubDate>Wed, 01 Feb 2012 00:44:57 +0000</pubDate>
		<dc:creator>hiroaki_sengoku</dc:creator>
				<category><![CDATA[Android]]></category>

		<guid isPermaLink="false">http://www.gcd.org/blog/?p=900</guid>
		<description><![CDATA[最初の Android 4.0 端末である Galaxy Nexus は、 今までの Android 端末と異なり USB Storage として使うことができない。 PC とデータをやりとりしたいときは MTP (Me [...]]]></description>
			<content:encoded><![CDATA[<p>
最初の Android 4.0 端末である Galaxy Nexus は、
今までの Android 端末と異なり 
<a href="http://ja.wikipedia.org/wiki/USB%E3%83%A1%E3%83%A2%E3%83%AA">USB Storage</a> として使うことができない。
PC とデータをやりとりしたいときは MTP 
(<a href="http://ja.wikipedia.org/wiki/%E3%83%A1%E3%83%87%E3%82%A3%E3%82%A2%E8%BB%A2%E9%80%81%E3%83%97%E3%83%AD%E3%83%88%E3%82%B3%E3%83%AB">Media Transfer Protocol</a>) 
を使えということらしい。
従来の Android 端末は、
PC と USB ケーブルで接続することによって、
Android 端末のストレージ (microSD カードなど) を
USB Storage として
PC からアクセスすることができた。
</p>
<p>
ただし、
PC と Android 双方から同じストレージを同時に読み書きすると破綻するので、
PC からアクセスするときは、
Android 端末からそのストレージを一時的に切り離す (umount する) 
実装になっている。
このため、
ストレージに Android が必要とするデータがあると、
切り離したときに問題が起きる。
例えば着信音 (着メロ) を microSD カード上に置いていると、
切り離しているときに電話がかかってきても、
その着信音を鳴せない
(Nexus S などだと、
設定した着信音がアクセスできない場合は、
デフォルトの着信音に切り替わる)。
</p>
<p>
MTP はブロックデバイス単位でなくファイル単位でストレージを管理する。
したがって PC との接続時でも
Android 端末からストレージ全体がアクセスできなくなるという問題がない。
しかも MTP は
Windows Vista 以降なら標準でサポートしている。
と、
このように (Samsung と Google は) 考えて、
Galaxy Nexus では USB Storage の代わりに MTP を使うようにしたのだろう
(Samsung の一つ前の世代の Android 端末である Galaxy S でも MTP が使える)。
なお、
今後登場する Android 4.0 (Ice Cream Sandwich, ICS) 端末で 
USB Storage 機能が廃止されるかどうかは不明。
少なくとも Nexus S を ICS にシステムアップデートしても、
従来通り USB Storage を使うことができた。
</p>
<p>
一見妥当のように見える MTP の採用だが、
実際に使ってみると問題が多い。
ストレートに言えば
「全く使い物にならない」。
Windows XP だと Windows Media Player 10 
以降のバージョンをインストールしないと MTP が使えないし、
Windows 以外だと、
標準で MTP をサポートしている OS はほとんどない。
しかも Windows でも、
MTP うんぬん以前に
Samsung 端末用の USB ドライバを入手するのが大変。
以前は SAMSUNG_USB_Driver_for_Mobile_Phones.exe 
が単体で配布されていたようだが、
今は Kies をインストールしないと入手できない (-_-ﾒ)。
</p>
<p>
さんざん苦労して MTP が使えるようにしても、
データ転送速度が極めて遅い (まだ実装がこなれてないため?)。
さらに、
普通のブロックデバイス 
(あるいはファイルシステム) として OS から見えないため、
MTP 対応を謳っていない限り、
普通のバックアップアップツールでは扱えないことが多い。
数MB 程度のファイルを一つ二つコピーする程度であればさほど問題無いが、
バックアップなど大量のデータを転送したい場合は不向き。
</p>
<p>
私の場合、
Galaxy Nexus のストレージ
(/mnt/sdcard パーティション,
実際には /data/media を FUSE で /mnt/sdcard に mount している)
を毎日 PC (Linux マシン) へバックアップしたい。
全部で数GB の大きさがあるので、
全データを毎回コピーするのは非現実的。
そこで
<a href="https://market.android.com/details?id=eu.kowalczuk.rsync4android">rsync backup for Android</a> 
アプリを使ってみた。
このアプリは、
内部に rsync と ssh コマンドを持っていて、
<a href="http://rsync.samba.org/">rsync</a> 
を以下のような形で実行している:
</p>
<pre class="code">
/data/data/eu.kowalczuk.rsync4android/files/rsync -vHrltD \
    --chmod=Du+rwx,go-rwx,Fu+rw,go-rw --no-perms --delete-after \
    -e '/data/data/eu.kowalczuk.rsync4android/files/ssh -y -p 22 \
            -i /data/data/eu.kowalczuk.rsync4android/files/dss_key' \
    /mnt/sdcard/ sengoku@senri.gcd.org:~/android/sdcard/
</pre>
<p>
Galaxy Nexus には有線LAN が無いので WiFi 経由で通信することになるが、
PC 同士で rsync する場合と全く同じで、とても簡単。
Android も Linux なのだから、
MTP みたいな得体の知れないものを無理に使うより、
使い慣れた rsync の方が断然 (・∀・)ｲｲ!!
</p>
<p>
とはいえ、
使ってると WiFi の通信の遅さが気になってきた。
「USBテザリング」
を使えば USB ケーブル経由で TCP/IP 通信を行なうこともできるが、
rsync でデータ転送を行なうためだけにテザリングするのは牛刀な感じが否めない。
また、
テザリングの場合 Android の default route が 3G 回線へ向いてしまうので、
特定のアドレス (プライベート IP アドレス) を 
USB へ向ける route 設定が必要。
</p>
<p>
そもそも Android 端末と PC とは adb 
(<a href="http://developer.android.com/guide/developing/tools/adb.html">Android Debug Bridge</a>) 
でデータをやりとりしているのだから、
rsync も adb 上で行ないたいと思うのが人情というもの。
</p>
<p>
前フリが長くなったが、ここからが本題。
</p>
<span id="more-900"></span>
<p>
PC 上で adb コマンドを使うと、
任意のコマンドを Android 上で実行できる。
例えば、
Android 上で tar コマンドを実行することによって 
Android 上のディレクトリを PC へコピーできる:
</p>
<pre class="terminal-scroll">
senri:~ $ adb shell 'tar cf - /mnt/sdcard/media 2>/dev/null' | tar xvf -
tar: Record size = 8 blocks
drwxrwxr-x root/sdcard_rw    0 2010-07-15 10:39 mnt/sdcard/media/
drwxrwxr-x root/sdcard_rw    0 2010-07-15 10:39 mnt/sdcard/media/audio/
drwxrwxr-x root/sdcard_rw    0 2012-01-08 00:22 mnt/sdcard/media/audio/notifications/
	...
</pre>
<p>
「tar cf - /mnt/sdcard/media 2>/dev/null」
が Android 上で実行するコマンド。
STDERR (「2>」, 標準エラー出力) を /dev/null へリダイレクトしているのは、
tar が STDERR へ出力したエラーメッセージが、
転送データ (STDOUT へ出力される) と混じるのを防ぐため。
</p>
<p>
このように Android 上で実行したコマンドの出力は、
PC 側へ伝わるが、
その逆、
PC 上で実行したコマンドの出力は Android へは伝わらない。
例えば次のように実行しても、
文字列
「test」
は Android 側に伝わらず、
cat コマンドは何も出力しない:
</p>
<pre class="terminal-scroll">
senri:~ $ echo test | adb shell cat
</pre>
<p>
これは、
PC 側で実行した adb コマンドにおいて、
adb の STDIN (標準入力) から入力されたデータ
(上記の例だと、
文字列
「test」)
を、 
Android 側へ送る実装になっていないため。
以下のパッチをあてることにより adb の STDIN を、
そのまま Android 上で実行したコマンドの STDIN へ伝えるようにすることができる:
</p>
<pre class="code">
--- system/core/adb/commandline.c.org	2012-01-29 09:28:25.000000000 +0900
+++ system/core/adb/commandline.c	2012-01-29 08:48:54.987004744 +0900
@@ -270,6 +270,35 @@
     free(buf);
 }
 
+static void *raw_read_thread(void *x)
+{
+    int fd, fdi;
+    unsigned char buf[1024];
+    int r;
+
+    int *fds = (int*) x;
+    fd = fds[0];
+    fdi = fds[1];
+    free(fds);
+
+    for(;;) {
+        /* fdi is really the client's stdin, so use read, not adb_read here */
+        D("raw_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
+        r = unix_read(fdi, buf, 1024);
+        D("raw_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
+        if(r == 0) break;
+        if(r &lt; 0) {
+            if(errno == EINTR) continue;
+            break;
+        }
+        r = adb_write(fd, buf, r);
+        if(r &lt;= 0) {
+            break;
+        }
+    }
+    return 0;
+}
+
 static void *stdin_read_thread(void *x)
 {
     int fd, fdi;
@@ -1022,6 +1051,12 @@
             D("interactive shell loop. buff=%s\n", buf);
             fd = adb_connect(buf);
             if(fd &gt;= 0) {
+		adb_thread_t thr;
+		int *fds;
+		fds = malloc(sizeof(int) * 2);
+		fds[0] = fd;
+		fds[1] = 0;
+		adb_thread_create(&amp;thr, raw_read_thread, fds);
                 D("about to read_and_dump(fd=%d)\n", fd);
                 read_and_dump(fd);
                 D("read_and_dump() done.\n");
</pre>
<p>
raw_read_thread は、
adb コマンドの STDIN から入力されたデータを、
そのまま Android へ送るスレッド。
system/core/adb/commandline.c で定義されていた 
stdin_read_thread を若干書き換えただけ。
</p>
<p>
で、上記パッチをあてた adb を試してみると...:
</p>
<pre class="terminal-scroll">
senri:~ $ echo test | adb shell cat
test
test
</pre>
<p>
ありゃ?
なんで
「test」
が二度出力されるんだ?
</p>
<p>
Android 側では adbd (デーモン) が動いていて、
PC 側で
「adb shell コマンド列」
を実行すると、
それを受けて adbd は、
Android 上で
「/system/bin/sh -c コマンド列」
を実行する。
一般にシェル (この場合は /system/bin/sh) は、
対話 (interactive) モードだと
STDIN から入力されたデータを、
そのまま STDOUT へエコーバック (echo back) する。
「test」
が二度出力されたのは、
エコーバックによる出力と、
cat コマンドの出力なのだろう。
</p>
<p>
でも、
なんで対話モードになってしまっているのだろう?
フツー、
「-c」 
オプション付でシェルを実行するときは、
非対話モードにするものだと思うのだけど...
と思って adbd のソースを読むと、
「-c」 
オプション付で /system/bin/sh を実行するときまで、
擬似端末 (Pseudo Terminal, pty) を使っていた。
これってバグじゃないのか?
と思いつつ、
「-c」 
オプション付の時は疑似端末を使わずに 
/system/bin/sh を実行するパッチを書いてみた:
</p>
<pre class="code">
--- system/core/adb/services.c.org	2012-01-29 09:28:25.000000000 +0900
+++ system/core/adb/services.c	2012-01-31 14:38:28.735416305 +0900
@@ -275,46 +275,54 @@
     return -1;
 #else /* !HAVE_WIN32_PROC */
     char *devname;
-    int ptm;
+    int fds[2];
 
-    ptm = unix_open("/dev/ptmx", O_RDWR); // | O_NOCTTY);
-    if(ptm &lt; 0){
-        printf("[ cannot open /dev/ptmx - %s ]\n",strerror(errno));
-        return -1;
-    }
-    fcntl(ptm, F_SETFD, FD_CLOEXEC);
-
-    if(grantpt(ptm) || unlockpt(ptm) ||
-       ((devname = (char*) ptsname(ptm)) == 0)){
-        printf("[ trouble with /dev/ptmx - %s ]\n", strerror(errno));
-        adb_close(ptm);
-        return -1;
+    if (arg1) {
+	if (adb_socketpair(fds)) {
+	    printf("[ cannot open socketpair - %s ]\n",strerror(errno));
+	    return -1;
+	}
+    } else {
+        fds[0] = unix_open("/dev/ptmx", O_RDWR); // | O_NOCTTY);
+        if(fds[0] &lt; 0){
+	    printf("[ cannot open /dev/ptmx - %s ]\n",strerror(errno));
+	    return -1;
+	}
+	fcntl(fds[0], F_SETFD, FD_CLOEXEC);
+
+	if(grantpt(fds[0]) || unlockpt(fds[0]) ||
+	   ((devname = (char*) ptsname(fds[0])) == 0)){
+	    printf("[ trouble with /dev/ptmx - %s ]\n", strerror(errno));
+	    adb_close(fds[0]);
+	    return -1;
+	}
     }
 
     *pid = fork();
     if(*pid &lt; 0) {
         printf("- fork failed: %s -\n", strerror(errno));
-        adb_close(ptm);
+        adb_close(fds[0]);
+	if (arg1) adb_close(fds[1]);
         return -1;
     }
 
     if(*pid == 0){
-        int pts;
-
         setsid();
 
-        pts = unix_open(devname, O_RDWR);
-        if(pts &lt; 0) {
-            fprintf(stderr, "child failed to open pseudo-term slave: %s\n", devname);
-            exit(-1);
-        }
-
-        dup2(pts, 0);
-        dup2(pts, 1);
-        dup2(pts, 2);
+	if (!arg1) {
+	    fds[1] = unix_open(devname, O_RDWR);
+	    if(fds[1] &lt; 0) {
+                fprintf(stderr, "child failed to open pseudo-term slave: %s\n", devname);
+		exit(-1);
+	    }
+	}
+
+        dup2(fds[1], 0);
+        dup2(fds[1], 1);
+        dup2(fds[1], 2);
 
-        adb_close(pts);
-        adb_close(ptm);
+        adb_close(fds[1]);
+        adb_close(fds[0]);
 
         // set OOM adjustment to zero
         char text[64];
@@ -335,7 +343,8 @@
         // Let the child do it itself, as sometimes the parent starts
         // running before the child has a /proc/pid/oom_adj.
         // """adb: unable to open /proc/644/oom_adj""" seen in some logs.
-        return ptm;
+	if (arg1) adb_close(fds[1]);
+        return fds[0];
     }
 #endif /* !HAVE_WIN32_PROC */
 }
</pre>
<p>
「-c」 
オプション付の時は 
「arg1」 
が非0 になるので、
「if (arg1) { ... }」
において、
adb_socketpair(fds) を呼び出して socketpair を用意する。
「arg1」 
が 0 の時は、
unix_open("/dev/ptmx", O_RDWR) によって疑似端末が用意されるので、
「-c」 
オプション無しの時はエコーバックが行なわれる。
</p>
<p>
adbd は /sbin/adbd にあって、
Android の場合
/sbin は initramfs のものがそのまま使われるので、
/sbin/adbd を書き換えても再起動すると元に戻ってしまう。
initramfs を書き換える
(つまり boot.img を書き換える)
とシステムアップデートの時に面倒なので、
以下のスクリプトを起動時に走らせることにした:
</p>
<pre class="code">
if [ -x /data/cust/sbin/adbd -a ! -f /sbin/adbd.org ]; then
    mount -oremount,rw null /
    mv /sbin/adbd /sbin/adbd.org
    cp -a /data/cust/sbin/adbd /sbin/
    mount -oremount,ro null /
    stop adbd
    start adbd
fi
</pre>
<p>
起動時にスクリプトを実行するには、
/system/etc/install-recovery.sh に書き加えておけばよい。
Galaxy Nexus の場合、
もともとこのファイルは存在しないが、
従来の Android と同様、
このファイルが存在すれば<a href="http://www.gcd.org/blog/2010/10/658/">起動時に実行される</a>。
</p>
<p>
以上で、
adb 経由で rsync が使えるようになる。
例えば以下のように実行すると、
Android 上の /mnt/sdcard を、
PC 上の ~/android/sdcard へ丸ごとバックアップできる:
</p>
<pre class="terminal">
senri:~ $ rsync --delete -av -e adb shell:/mnt/sdcard ~/android/
receiving incremental file list

sent 511 bytes  received 210692 bytes  46934.00 bytes/sec
total size is 5859784477  speedup is 27744.80
</pre>
<p>
本来 rsync は ssh を呼び出して remote host との通信路を確保するが、
「-e」
オプションで ssh の代わりに使うコマンドを指定できる。
上記の例だと、
rsync は adb を以下のような引数をつけて呼び出す:
</p>
<pre class="code">
adb shell rsync --server --sender -vlogDtpre.iLsf . /mnt/sdcard
</pre>]]></content:encoded>
			<wfw:commentRss>http://www.gcd.org/blog/2012/02/900/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>香港で洗濯を</title>
		<link>http://www.gcd.org/blog/2012/01/891/</link>
		<comments>http://www.gcd.org/blog/2012/01/891/#comments</comments>
		<pubDate>Thu, 12 Jan 2012 01:10:06 +0000</pubDate>
		<dc:creator>hiroaki_sengoku</dc:creator>
				<category><![CDATA[香港]]></category>

		<guid isPermaLink="false">http://www.gcd.org/blog/?p=891</guid>
		<description><![CDATA[旅行期間が長くなると当然着替えがたくさん必要になる。 下着を毎日替えるのはアタリマエだが、 シャツもできれば毎日着替えたい。 滞在期間が一週間を超えると、 衣類だけでスーツケースが一杯になってしまう。 近年多くの航空会社 [...]]]></description>
			<content:encoded><![CDATA[<p>
旅行期間が長くなると当然着替えがたくさん必要になる。
下着を毎日替えるのはアタリマエだが、
シャツもできれば毎日着替えたい。
滞在期間が一週間を超えると、
衣類だけでスーツケースが一杯になってしまう。
近年多くの航空会社が、
荷物を各 50ポンド (約 23kg) 2個までに制限するようになったので、
持って行く衣類は 5日分くらいに抑えて、
現地で洗濯して着まわすようにしたい。
</p>
<p>
米国など多くの国では、
ホテル内 (あるいはホテルの至近) にコインランドリーがあるので、
数日毎に洗濯していたのだが、
香港ではコインランドリーを見かけたことがなかった。
いつも利用しているホテルにコインランドリーが無いだけでなく、
香港じゅうどこへ行ってもコインランドリーらしきものが見当たらない。
香港に長期滞在している人達は、
いったい洗濯物をどうしているんだろう?
と思っていた。
</p>
<a href="http://www.gcd.org/sengoku/picts/NewBrightLightLaundromat.jpg"><img src="http://www.gcd.org/sengoku/picts/NewBrightLightLaundromat.jpg" alt="新明亮 專業乾洗 New Bright &amp; Light Laundromat" width="288" height="384" class="pict-left" /></a>
<p>
← ただ、
ホテルの前にクリーニング店らしきものがあることには以前から気付いていた。
店内にはカウンターがあって、
店番のおばちゃんが一人座っている。
ドライクリーニング済と思しき、
一着一着ハンガーに掛けられ透明袋で覆われた衣服が、
ところ狭しと上から多数吊り下げられている。
いくら香港の物価が安いといっても、
下着を含めて全てドライクリーニングするわけにもいかないよなぁ、
と思っていた。
</p>
<p>
この店の看板には
「新明亮 專業乾洗」
と漢字の店名の他に、
「New Bright &amp; Light Laundromat」
と英語の店名が併記してある。
Laundromat (Laundry + Automatic の造語) は、
米国だと
「コインランドリー」
の意味なのだけれど、
お客が洗濯機を直接いじれる状況ではなく、
コインランドリーとはかけはなれた感じ。
どーみても (日本の街角で見かける) クリーニング店である。
</p>
<p>
店名にある
「乾洗」
は文字通り
「ドライクリーニング」
の意味だが、
店のガラスに貼ってある掲示をよく見てみると、
「乾洗」
の価格表の他に、
「磅洗 1-7磅 $31.5 (毎磅+$4.5)」
などと書いてある。
「<a href="http://ja.wiktionary.org/wiki/%E7%A3%85">磅</a>」
は
「ポンド」
の意味で、
7 ポンド (約 3.2kg) までは HK$31.5 (約 315円) で、
1 ポンド増えるごとに HK$4.5 (45円) 増しという意味。
これは洗濯物を量り洗いしてくれるという意味ではなかろうか?
ちなみに、
料金が妙に中途半端な数字なのは、
「磅洗九折」
つまり 10% 割引のため。
元の値段は、
HK$35 毎磅+HK$5 だったのだろう。
</p>
<p>
英語が (中国語と共に) 公用語である香港ではあるが、
個人商店だと英語が通じる可能性は低い
(最も通用するのは中国語の一方言である広東語)。
おばちゃんに、
量り洗いを、
どんな仕上がりでやってくれるのか英語で尋ねても、
たぶんこちらの意図は通じないだろう。
意を決して、
洗濯物の袋を持ち込んでみた (12/19)。
</p>
<p>
もちろん、
最悪の事態を想定して、
なくなっても (あるいはズタボロにされても) 
そんなに困らない下着やシャツに限定してビニール袋に詰め込んで持ち込む。
ホテルのロビー前を、
下着満載の袋を持って通り過ぎるのはちょっと恥ずかしい。
</p>
<a href="http://www.gcd.org/sengoku/picts/NewBrightLightLaundromat_receipt.jpg"><img src="http://www.gcd.org/sengoku/picts/NewBrightLightLaundromat_receipt.jpg" alt="11磅 HK$50 と書かれたレシート" width="288" height="384" class="pict-right" /></a>
<p>
袋を持って店に入ると、
店番のおばちゃんが入口わきの秤を指し示した。
よかった、
少なくともここまでは、
こちらの意図が通じている。
秤に乗せると 11ポンド (約5kg) だった。
おばちゃんが
「ん、さっぷまん」
と言った (のだと思う)。
こんな単純な単語でも、
なかなか聞き取れない。
広東語は
「ん」
で始まる発音が重要なのだけど、
あいにく日本語には
「ん」
から始まる語がないので、
日本人にとって
「ん」
から始まる単語を聞き取るのは難しいし、
発音するのも難しい
(広東語で
「しりとり」
をしたら
「ん」
で終わる単語を禁止しなくていいかも)。
</p>
<p>
おばちゃんがレシート (写真右 → ) に 50 と書いて見せたので、
HK$50 (約 500円) を支払う。
11ポンドなら HK$31.5 + HK$4.5 * (11磅-7磅) = HK$49.5 なので、
HK$50 なら計算も合ってる。
</p>
<p>
するとおばちゃん曰く
「とだい」。<br />
む?
一瞬何を言ったか分からず固まってしまったが、
「Today」
らしい。
私に広東語が通じないんで英語に切り替えてくれたらしい。
でも、
おばちゃんが喋れる英語はここまで。
どうやら
「今日できるよ」、
と言いたいらしい。
どんな仕上がりで返ってくるか一抹の不安を感じたが、
まあ、
なるようになるでしょ。
このレシートを受け取って店を出る。
レシートの右上に
「未付款 not yet paid」
と書かれているが、
レシート中央に斜めに赤字のスタンプで
「已付款」
と押してあるので、
既に支払い済という意味なのだろう (
「<a href="http://ja.wiktionary.org/wiki/%E5%B7%B2">已</a>」
は
「既に」
という意味の漢字)。
スタンプも英語併記にしておいてくれると助かるのだが。
レシート上で店名の
「Laundromat」
の綴りが間違っているのはご愛嬌。
</p>
<p>
ホテルに向かうと、
私と同じように大きな袋をぶら下げてホテルを出てくる人を発見。
なんだ、
みんな同じような感じで洗濯物を出していたのか。
なんでいままで気づかなかったんだろう。
</p>
<p>
その日の晩、
ホテルに戻ってきたら 20:00 を15分ほど過ぎてしまい、
店は既に閉っていた。
営業時間は、
月曜〜土曜が 8:00〜20:00、
祝祭日が 9:00〜17:00 で、
日曜は休み。
ただし冬節 (冬至, 2011年は 12月22日だった) 
は中国人にとって特別の日であるらしく、
営業時間が (この店に限らず) 変則的なので注意が必要 
(営業しないか、開店しても早々に閉店する)。
実は前掲の店の写真は 12月22日、
冬節の朝 10:19 に撮ったものだが、
まだ開店しておらず
「梢候片刻 PLEASE WAIT」
の札がドア中央にかけてある。
両隣の店のシャッターが閉っているのは冬節だからだと思われる。
決してシャッター街になってしまっているわけではない。
</p>
<img src="http://www.gcd.org/sengoku/picts/NewBrightLightLaundromat_bag.jpg" alt="洗濯済衣類の袋" width="192" height="256" class="pict-right" />
<p>
次の日 (12/20) の朝、どきどきしながら店へ行ってレシートを
(昨日と同じ) おばちゃんに差し出す。
おばちゃんは、店内に積み上げてある袋の中から一つを引き出してカウンターへもってきてくれた (写真右 →)。
</p>
<p>
ここで
「むごーい」
(「唔該」, 
「ありがとう」
の意味)
と言えばいいのだろうけど、
つい
「Thank you」
と言ってしまった。
練習を積まないと、
なかなか自然には出てこない。
</p>
<p>
なにはともあれ、
ここまでは想定通りにコトが進んだ。
スムーズすぎるくらい。
袋をホテルの部屋に持ち帰り、
どんな状態の衣類が出てくるか、
固唾を飲んで袋の口をほどく。
</p>
<p>
なんと、
シャツや下着が一枚ずつ丁寧に畳んで重ねてあった。
ハンカチもきちんと二つ折りにしてあった (写真下 ↓)。
量り洗いなのに、
ここまで丁寧に畳んでくれるとは。
</p>
<img src="http://www.gcd.org/sengoku/picts/NewBrightLightLaundromat_clothes.jpg" alt="きちんと畳まれた衣類" width="312" height="359" class="pict-left" />
<p>
しかも洗濯から畳むまで全て込み込みで、
わずか 500円。
ちなみに米国だとコインランドリーを使う料金だけで 
US$7.0 (約 546円) くらいかかる
(おまけに 25セント硬貨で用意しなければならないので大変)。
</p>
<p>
あとで気付いたが、
レシートに書いてあった伝票番号 11834 が、
袋にも (手書きで) 書いてあった。
店内に積み上げられた袋の中から、
おばちゃんはこの数字を頼りに私の袋を引き出したのだろう。
</p>
<p>
きちんと畳まれた仕上がりに感動したので、
日本へ帰る直前にもう一度、
この
「新明亮 專業乾洗」
を利用した。
こんどは 
「ズタボロにされても構わない」
衣類だけでなく、
旅行中に着た服を全て出した
(最初の利用日のわずか 2日後だったが、11ポンドもあった) が、
同様に満足のいく仕上がりだった。
おかげで、
日本に帰ってから洗う必要があった衣服はほとんど無く、
帰宅後に大量の洗濯をする羽目にならずに済んだ。
</p>
<p>
実は、
帰宅翌日に自宅の洗濯機が故障して往生した 
(年末だったので年内に配達してもらえる洗濯機、
という条件で選んだら、
日本製は在庫がないということでハイアール製になった。
こうやって日本のメーカはシェアを失っていくのだろう)。
もし、
香港で洗濯していなかったら、
新しい洗濯機が届くまで洗濯物があふれかえって、
もっと悲惨な事態になっていたところだった。
やはり洗濯は旅行中に済ませてしまうに限る。
</p>]]></content:encoded>
			<wfw:commentRss>http://www.gcd.org/blog/2012/01/891/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>スマートフォン用の外付バッテリー</title>
		<link>http://www.gcd.org/blog/2012/01/888/</link>
		<comments>http://www.gcd.org/blog/2012/01/888/#comments</comments>
		<pubDate>Wed, 04 Jan 2012 02:56:41 +0000</pubDate>
		<dc:creator>hiroaki_sengoku</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[香港]]></category>

		<guid isPermaLink="false">http://www.gcd.org/blog/?p=888</guid>
		<description><![CDATA[あけましておめでとうございます。今年もよろしくお願いします。 近頃のスマートフォン (スマホ) は、 ちょっと使ってるとバッテリーが一日もたない。 出先でバッテリー切れになると大変困るので、 外付バッテリーを携帯している [...]]]></description>
			<content:encoded><![CDATA[<p>
あけましておめでとうございます。今年もよろしくお願いします。 
</p>
<p>
近頃のスマートフォン (スマホ) は、
ちょっと使ってるとバッテリーが一日もたない。
出先でバッテリー切れになると大変困るので、
<a href="http://www.amazon.co.jp/%E9%9B%BB%E6%B1%A0%E5%BC%8F%E5%85%85%E9%9B%BB%E5%99%A8%E3%83%BB%E5%85%85%E9%9B%BB%E3%83%91%E3%83%83%E3%82%AF-%E6%90%BA%E5%B8%AF%E9%9B%BB%E8%A9%B1%E3%83%BBIP%E3%83%95%E3%82%A9%E3%83%B3%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B5%E3%83%AA-%E6%90%BA%E5%B8%AF%E9%9B%BB%E8%A9%B1%E3%83%BBIP%E3%83%95%E3%82%A9%E3%83%B3-%E3%82%AB%E3%83%86%E3%82%B4%E3%83%AA%E3%83%BC%E5%88%A5/b/?_encoding=UTF8&amp;pf_rd_t=101&amp;node=128193011&amp;tag=gcd-22&amp;linkCode=ur2&amp;pf_rd_m=AN1VRQENFRJN5&amp;pf_rd_p=109173529&amp;pf_rd_s=center-3&amp;camp=247&amp;pf_rd_r=03NSS7WTMWJWJV9XV9FR&amp;creative=1211&amp;pf_rd_i=128187011">外付バッテリー</a>を携帯している人も多いのではないか。
外付バッテリーには、
リチウムイオン二次電池 (充電式電池, 充電池) を利用するものと、
単三乾電池 (あるいはエネループ等のニッケル水素二次電池) 
を利用するものがあるが、
前者は (安全性の観点から) 充電池を交換できないことが多く、
充電池が寿命を迎えると使い捨てになってしまう
(<a href="http://www.amazon.co.jp/dp/B005DUMNSE/?_encoding=UTF8&amp;tag=gcd-22&amp;linkCode=ur2&amp;camp=247&amp;creative=1211">eneloop mobile booster KBC-L54D</a> など。3900円もするものを使い捨てにするのはモッタイナイ)。
</p>
<p>
一方後者は、
リチウムイオン充電池に比べると質量あたりの蓄えられる電力量
(重量エネルギー密度)
が小さい。
18650 リチウムイオン充電池が、
3.7V * 2400mAh / 47g = 188Wh/kg 程度あるのに対し、
単三のエネループは 1.2V * 1900mAh / 27g = 84Wh/kg と、
リチウムイオン充電池の半分以下しかなく、
スマホの充電用としては力不足。
</p>
<p>
特に、
単三形ニッケル水素充電池 2本を用いる外付バッテリー
(<a href="http://www.amazon.co.jp/dp/B005V9XMW8/?_encoding=UTF8&amp;tag=gcd-22&amp;linkCode=ur2&amp;camp=247&amp;creative=1211">eneloop stick booster</a> など) は、
2.4V (1.2V * 2) を倍以上の 
5V (USB の電源電圧) に昇圧して出力するため、
900mAh 程度 (1.2V * 2 * 1900mAh / 5V,  
損失があるはずなので実際にはもっと少ないはず) しか出力できず、
スマホを充電しても満充電にはほど遠い。
単三形ニッケル水素充電池を用いるなら 3本〜4本を直列すべきだが、
そうすると重く大きくなってしまい常時携帯するには不適。
</p>
<p>
というわけで、
私はスマホの充電に、
いわゆる<a href="http://www.dealextreme.com/p/white-light-led-flashlight-emergency-usb-charger-with-cell-phone-adapters-18883">中華充電器</a> 
(<a href="http://www.tinydeal.com/ru/18650-batttery-powered-usb-bright-torch-7pc-adapter-mobile-power-charger-suit-for-nokia-motorola-sony-ericsson-lg-hui10954-p-9839.html">18650 Batttery Powered USB Bright Torch</a>,
本体側面に 「PORTABLE POWER」 と書かれている)
を使っている。
これはリチウムイオン充電池を利用する外付バッテリーだが、
18650 と呼ばれる (直径 18mm 長さ 65.0mm という意味)
安価な汎用リチウムイオン充電池 (一個 300円〜500円) を用いるため、
充電池が寿命を迎えたら充電池のみ交換できる。
18650 充電池の電圧 3.7V を 5V に昇圧して USB コネクタで出力する他、
充電回路も組み込まれているので、
USB ケーブルをつなぐだけで充電も可能。
</p>
<a href="http://www.gcd.org/sengoku/picts/18650.jpg"><img src="http://www.gcd.org/sengoku/picts/18650.jpg" alt="18650 battery" width="427" height="320" /></a>
<p>
写真 ↑ の直方体 (白と黒) が中華充電器。
黒い方は裏蓋を外して中身の 18650 充電池が見える状態にして撮影。
手前の面の USB A ソケットに USB ケーブルを接続して充放電を行なう。
中の赤い 18650 充電池は、
ノートPC 用のバッテリーを殻割りして取り出した充電池なので、
接着剤を剥した痕がある。
その隣の青い (「UltraFire」 と書いてある) 18650 充電池は、
香港の<a href="http://maps.google.com/maps?ll=22.329951,114.162339&amp;z=19">鴨寮街</a> (深水埗駅の出口すぐ) で買った 18650 充電池 2個パック (2個で HK$68 = 約 680円)。
</p>
<img src="http://www.gcd.org/sengoku/picts/BatteryGraph.png" alt="Battery Graph while charging" width="240" height="426" class="pict-left" />
<p>
もちろん、
安全回路なしのリチウムイオン充電池をセル単体 (つまり 18650) 
で扱うことは危険であり、
発火や爆発の可能性も考慮にいれた運用が求められる。
その危険性故に、
日本では 18650 は、
一般には市販されていない
(秋葉原などでは売っている店もある)。
18650 を充電器から日常的に出し入れするなど、
ニッケル水素充電池 (エネループ等) と同様の感覚で扱うことは絶対に避けるべき。
</p>
<p>
この中華充電器は軽量コンパクトでありながら、
スマホを (ほぼ) 満充電にできるくらいの電力量があるので、
私は常に持ち歩いている。
</p>
<p>
Galaxy Nexus (香港で購入した GT-I9250) のバッテリーが残り 10% になった段階 
(左の<a href="https://market.android.com/details?id=com.modroid.battery">グラフ</a>で 19:47 の時点) で、
中華充電器による充電を開始してみた
(ディスプレイを消灯したまま放置)。
2時間55分後 (22:42) に充電が停止し、
94% まで充電することができた。
</p>
<p>
Galaxy Nexus のバッテリーは、
1750mAh のリチウムイオン充電池 (スマホの中では容量が大きい方)。
3.7V 2400mAh の 18650 を 5V に昇圧して出力する中華充電器で、
Galaxy Nexus を 10% から 94% まで充電できれば悪くない。
つまり、
充電電気量は 3.7V * 2400mAh / 5V ≒ 1700mAh 程度になる
(実際には損失がある) ので、
84% (94% - 10%) を充電できれば充分。
3時間弱の充電中も Galaxy Nexus が 150mAh くらいは消費しているはず
(Galaxy Nexus など大抵のスマホは、
ほとんど使わない待受け状態で放置していても 
12時間くらいしかバッテリーが持たない) 
なので、
実際に充電された電気量は 1750mAh * 84% + 150mAh = 1620mAh 
くらいになっていると思われる。
</p>
<p>
充電 (中華充電器にとっては放電)
が停止したときの中華充電器の 18650 の電圧が 3.38V で、
リチウムイオン充電池の放電終止電圧 2.7V よりだいぶ高いが、
中華充電器の昇圧回路が機能する電圧がこのあたりなのだろう。
また、
中華充電器を満充電したときの 18650 の電圧は、
4.13V だった。
充電中の電圧は 4.2V を超えていないようなので
(オシロスコープを持ってないので正確なところは不明)、
まあ大丈夫なのだろう。
</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gcd.org/blog/2012/01/888/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>生涯 「こだわらないエンジニア」 宣言</title>
		<link>http://www.gcd.org/blog/2011/11/884/</link>
		<comments>http://www.gcd.org/blog/2011/11/884/#comments</comments>
		<pubDate>Mon, 28 Nov 2011 06:59:11 +0000</pubDate>
		<dc:creator>hiroaki_sengoku</dc:creator>
				<category><![CDATA[元CTO の日記]]></category>
		<category><![CDATA[自己啓発]]></category>

		<guid isPermaLink="false">http://www.gcd.org/blog/?p=884</guid>
		<description><![CDATA[2011年11月28日の KLab(株) 株主総会 (上場前の株主名簿に基づく最後の総会) 終了後、 私は取締役CTO を退任いたしました。 今から遡ること 11年前 2000年8月1日の (株)ケイ・ラボラトリー (当 [...]]]></description>
			<content:encoded><![CDATA[<p>
2011年11月28日の KLab(株)
株主総会
(上場前の株主名簿に基づく最後の総会)
終了後、
私は<a href="http://v4.eir-parts.net/v4Contents/View.aspx?cat=tdnet&amp;sid=936284">取締役CTO を退任いたしました</a>。
今から遡ること 11年前 2000年8月1日の
(株)ケイ・ラボラトリー (当時の KLab の社名) 創業以来、
会社経営については全く無知であった私が何とかここまでやってこれたのは、
ひとえに皆々様方のご指導ご鞭撻のおかげであったと深く感謝いたします。
誠にありがとうございます。
<!-- 引き続き KLab(株) 技術顧問として留まりますので、
今後ともよろしくお願いいたします。 -->
なお、
後任として安井真伸が CTO に就任しました。
</p>
<p>
11年前、
日立製作所の研究所勤務の一研究員だった私が、
なぜケイ・ラボラトリーの立ち上げに参加したかといえば、
未知のモノに関わるチャンスがあれば、
あまり後先考えずに飛び付いてみる性格だったというのが大きかったと思います。
</p>
<blockquote>
中途半端に好きな状態で居るのではなく、
興味を持ったのなら、全力で取り組んでみる。
自分の能力がどれくらいのものかと、把握できるまでやってみる。
そして向いてない、止めると決めたらそれ以上は手を出さない。
それを繰り返すことで、本当に自分が好きなもの、
人並み以上の価値を生み出せるものを見つけ出し、
それを仕事にしていったのが仙石氏のキャリアなのだ。 
<div align="right"><a href="http://www.gcd.org/blog/2010/12/692/">“自分に向いたこと” を見つけ、自分にしか生み出せない価値を持て</a></div>
</blockquote>
<p>
日立では一人の部下も持っていなかった私が、
マネジメントの何たるかを全く理解しないままに、
当時規模は小さかったとはいえ、
エンジニア集団のトップとして責任を負う立場に立ったというのは、
チャレンジというよりは無謀であったかもしれません。
</p>
<p>
失敗も多かったのですが、
まがりなりにも 11年も続けられたということは、
「経営者」
が向いていたということなのでしょう。
それまで私は自分のことを 100% 技術者 (ちょっとだけ研究者) だと思っていたのに、
マネジメントもそれなりに向いていたというのは発見でした。
「ベンチャー立ち上げ」
というチャンスに後先考えずに飛び付いて本当に良かったと思います。
</p>
<p>
もちろん、
私がしでかした数多くの失敗で、
多くの方々にご迷惑をおかけしました。
私の未熟さゆえに厄災に遭われた方々
(が本ブログの読者である可能性は低いのですが)
にはこの場をお借りしてお詫び申し上げます。
</p>
<p>
右も左も分からない手探り状態で CTO の仕事を始めて以来、
一貫して自分に課していたことがあります。
それは、
「部下に仕事を任せること」。
ケイ・ラボラトリーの黎明期は、
やるべきことが多すぎて、
それこそ猫の手も借りたい状態だったので、
「仕事を任せること」
を自分に課したというよりは、
手が回らないから結果的に任せた格好になっていただけなのですが、
経営陣の末席を汚しているうちに経営とは何であるか私なりに学ぶ機会もあり、
黎明期を脱した後も、
たとえ自分がやりたい仕事であっても、
部下でもできる仕事であれば敢えて手を出さず、
任せるようにしてきました。
</p>
<p>
部下を育てなければ会社がまわらないわけで、
「仕事を任せることが重要」
なんてことは誰でも知ってるし、
誰でも実践していることだと思いますが、
自分がやりたい仕事まで手放す、
ということになるとどうでしょうか?
</p>
<p>
2006年に、
こんなことを書いています:
</p>
<blockquote>
積極的に<a href="http://www.gcd.org/blog/2006/05/68/">今の仕事を捨てる</a>べきでしょう。
部下 (or 後輩) が成長してきて、
自分の代わりがつとまるようになったら、
全てその部下に任せてしまい、
新しいことにチャレンジするわけです。
そうすれば部下も育つし、
自分を変えることができます。
運がよければ新たな成長フェーズに入れるかもしれません。 
<div align="right"><a href="http://www.gcd.org/blog/2006/08/376/">成長する秘訣は、今の仕事を捨てて自分を変えること</a></div>
</blockquote>
<p>
私は、
チャンスに巡り合ったときに躊躇なく飛び付けるように、
あるいは新しいチャンスに巡り合う確率を上げるために、
取組んでいた仕事がある程度まわるようになったら、
その仕事にはこだわらず、
むしろその仕事を手放して別のことに取組むようにしてきました。
</p>
<p>
手放した仕事の中で一番大きかったのは、
大学院と日立で計 11年間も続いていた研究者としての仕事だったわけですが、
もし、
ベンチャー立ち上げに参加するチャンスに巡り合ったとき、
研究者としての仕事にこだわってチャンスに飛び付くのを躊躇していたら、
CTO をやってみることもなかったかもしれません。
当時は研究こそ自分の
「やりたい仕事」
だと思っていたのですが、
それを敢えて手放したことで CTO としての仕事に巡り合えたのだと思います。
</p>
<p>
その CTO の仕事も 2008年の時点で丸 8年になり、
かつての部下が二人も役員に登り詰めるに至って、
そろそろ私が KLab で果たせる役割も終わりが近づいてきたと意識し始めました。
社内で、
ことあるごとに
「CTO を辞めるつもり」
と (誰も本気にしてくれませんでしたが) 言っていましたし、
社外でも公言していました:
</p>
<blockquote>
KLab を設立してから、どんどん仕事を捨てて自分を変えている 
(ピーターの法則に陥らないように)。
部下が成長したらすべて任せてしまう。
すべての仕事を部下に振り終えたら、私は CTO をやめる予定。
早く育成しないと。 
<div align="right"><a href="http://www.gcd.org/blog/2009/10/402/">パネルディスカッション ～CTO のから騒ぎ for the future～ に登壇しました</a></div>
</blockquote>
<p>
株式の上場が現実味を帯びてきた頃、
ボトルネックの一つが人事制度でした。
人事は私にとって全く未知のモノでしたから迷わず飛び付きました。
労働基準法を一から勉強したり、
人事マネージャ候補を 20人以上面接したり、
弁護士や社労士の先生方と連係したりと、
初めてのことばかりで失敗もあったのですが得難い経験をしました。
特に人事担当者を採用するための面接は、
技術者の面接とはまるで異質で、
大変勉強になりました。
とはいえ、
私は (予想通り) あまり人事向きではなかったので、
一年程度で人事の仕事は手放して後任に引き継ぎました。
</p>
<p>
そして無事上場を果たしたいま、
KLab の業績は<a href="http://v4.eir-parts.net/v4Contents/View.aspx?template=ir_material&amp;sid=12067&amp;code=3656">絶好調</a>です。
過去 11年間の KLab の歴史の中で最も好調な今だからこそ、
11年続いたこの仕事を捨てて自分を変える最適のタイミングだと判断しました。
未練がないと言えば嘘になりますが、
新しいチャンスに巡り合うために敢えて取締役を退任することを願い出た次第です。
私のワガママを快く受け入れてくださった、
真田社長をはじめとする取締役の方々に感謝いたします。
</p>
<p>
今後は、
<!-- 籍こそ KLab に残すものの、
非常勤ですので時間は最大限自由に使うことができます。 -->
まずは様々な人とお話しして、
どこかにチャンスが落ちていないか ;-) 探すつもりです。
私から連絡するかも知れませんが、
もしご関心があればご連絡頂ければ幸いです。
私は今まで何百人 (数えたことがないので正確な数は不明) 
もの人を面接してきましたが、
面接を受けたのは (新卒時を含めて) 数回程度しかないので、
他社がどんな面接をしているのか大変興味があります ;-)。
</p>
<p>
私は、
23歳からの 11年間を研究者として、
次の 11年間を経営者として全力で取組んできました。
私はまだ 45歳、
さらにもう 11年間くらいは何か別のことに全力で取組むことができるはずです。
</p>
<blockquote>
ついでにいうと、
コンピュータに巡り合ったのが 12歳の時なので、
コンピュータを専ら趣味でいじってた期間も 11年間です。
そしてこの 33年間、
コンピュータに対する関心だけは変らず一貫しているので、
根底ではエンジニアが一番向いているということなのでしょう。
</blockquote>
<p>
私がいままでやってきたことにこだわるつもりはありません。
11年前、
それまで研究者だった私が、
研究にこだわらずに無謀にもベンチャーの立ち上げに参加したからこそ、
今の私があるわけで、
これからも、
そして生涯、
こだわらずに未知への挑戦を続けていきたいと思います。
</p>]]></content:encoded>
			<wfw:commentRss>http://www.gcd.org/blog/2011/11/884/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>ベンチャーが学校教育に求めること</title>
		<link>http://www.gcd.org/blog/2011/10/853/</link>
		<comments>http://www.gcd.org/blog/2011/10/853/#comments</comments>
		<pubDate>Thu, 13 Oct 2011 13:50:23 +0000</pubDate>
		<dc:creator>hiroaki_sengoku</dc:creator>
				<category><![CDATA[元CTO の日記]]></category>
		<category><![CDATA[技術者の成長]]></category>

		<guid isPermaLink="false">http://www.gcd.org/blog/?p=853</guid>
		<description><![CDATA[東北大学大学院の教壇に立ちました。 産学連係講義 「先端技術の基礎と実践」 という講義で、 毎週一人づつ企業から講師を招いて、 ソフトウェアや IT 技術の様々な側面について理論的、 あるいは実際的な観点から講義してもら [...]]]></description>
			<content:encoded><![CDATA[<p>
東北大学大学院の教壇に立ちました。
産学連係講義
「先端技術の基礎と実践」
という講義で、
毎週一人づつ企業から講師を招いて、
ソフトウェアや IT 技術の様々な側面について理論的、
あるいは実際的な観点から講義してもらう、
という趣旨でした。
講義題目の一覧を見ると、
私以外は、
(講義の趣旨から言って当然ですが)
技術的な内容ばかりで、
私の講義
「学生のうちに身につけて欲しい、たった一つの能力」
だけ浮きまくっていました (^^;。
</p>
<p>
本当にこんな内容で話していいのか
(ある意味、大学院での教育方針にケンカを売るような内容ですので)
と内心不安だったのですが、
少なくとも一部の学生さんには積極的に質問してもらえて、
1コマの授業時間だけでなく、
講義後のフリートークも時間いっぱいいっぱい使って、
学生さん達とお話しすることができました。
型破りな講義内容を快諾して頂いた先生方に深く感謝致します。
</p>
<p>
以下、
講義の内容です
(実際の講義は脱線してしまったので、こんなに整っていませんが)。
囲み部分はスライドの内容です。
</p>
<div align="center">- o -</div>

<blockquote>
おかげさまで KLab 株式会社は、先月 9月 27日に東証に上場しました
</blockquote>
<p>
SAP (Social Application Provider) として上場するのは、
KLab が国内初だったこともあり注目を集めました。
SAP というのは、
GREE, モバゲー, mixi, ニコニコ動画などの
SNS (Social Network Service)
上で遊べるアプリ (ソーシャルゲーム) を提供する会社のことです。
2009年に国内で初めて mixi が SNS プラットフォームをオープン化したのに合わせて
KLab はソーシャルゲーム開発に舵を切り、
ソーシャルゲーム関連の売上が急拡大中です。
でも、
今日はソーシャルゲームの話はしません。
なぜか？
</p>
<p>
一つは、
明日が 2011年 8月期の決算発表で、
今うっかり先走って業績などを喋ってしまうと大変なことになるからですが、
もう一つは ↓
</p>
<blockquote>
事業内容をみて就活するヤツ多すぎ (´･ω･`)
</blockquote>
<p>
私は仕事柄、
就職活動中の学生さんとお話しする機会が多いのですが、
エンジニア志望なのに、
事業内容で会社を選ぼうとしている学生さんが多いことに違和感を覚えます。
みなさんは会社に入って事業をやりたいんでしょうか?
</p>
<p>
最初こそプログラマとして入社するけど、
あくまでそれは事業を理解する端緒としてであって、
なるべく早く開発を統括できるようになり、
事業を発展させることによって自らも成長し、
ゆくゆくは事業部長を目指し、
あわよくば社長も狙いたい、
ということであれば、
事業内容で会社を選ぶのも理解できます。
</p>
<p>
しかしながらエンジニア志望の学生さんの多くは、
事業部長を目指すというよりはもっと技術志向で、
専門性を活かした職種、
例えば技術コンサルタントやチーフアーキテクト、
あるいは
「技術者の社長」
であるところの CTO などをイメージしていたりします。
できればマネジメントはやりたくない、
開発の現場を離れたくない、
と考えている人も多いのではないでしょうか。
</p>
<p>
事業と技術、
どちらのキャリアを歩もうとするのか、
社会人としての最初の一歩を踏み出す前に、
もっと意識すべきではないでしょうか?
なぜなら、
事業を中心に考えるのであれば技術は単なる手段であり、
極論すれば技術は新人の仕事ということになります。
できるだけ早く新人の仕事としての技術は脱却して、
マネジメント手法を学んでいかなければ 
<a href="http://cto.gcd.org/2006/05/357/">35歳でエンジニアとしての定年</a>を迎えてしまいます。
</p>
<p>
一方、
技術を中心に考えるのであれば<a href="http://www.gcd.org/blog/2006/12/109/">事業は単なる手段</a>であり、
極論すれば事業が立ち行かなくなって会社が潰れてしまっても、
自身の技術力さえ伸ばせれば成功と言えるでしょう。
ずば抜けた技術力があれば転職も思いのままだし、
給料も言いたい放題でしょう。
だから、
事業内容で会社を選ぶのではなく、
その会社が<a href="http://cto.gcd.org/2007/05/392/">自分の成長に役立つ</a>か否かで選ぶべきです。
</p>
<p>
言うまでもなくどっちつかずなのが最悪で、
残念なことにエンジニア志望だった人の多くが ↓ のような道を歩んでしまいます。
</p>
<blockquote>
どっちつかずな人の末路 orz<br />
<br />
若いうちは技術をやれ、と言われてデスマーチでこき使われる。<br />
辛いけど自分は技術が好きなんだ、と現場にこだわり続ける。<br />
<br />
そして、35歳でエンジニア定年。
泣く泣く現場を離れてマネジメントの道を歩み始めるが、<br />
自ら進んでマネージャを目指した同期に追い付くのは不可能。
</blockquote>
<p>
ただし技術の道を選んだとしても、
「ずば抜けた技術力」
が身につけられるのは、
元々その素質を持っていた人に限られます。
どの分野の技術でも向き不向きはあると思いますが、
ことコンピュータ関連の技術に関してはその傾向が顕著で、
努力すれば身につくような種類のものだとは到底言えないでしょう。
むしろ、
努力しなくても自然とスキルが伸びてしまったというような、
元々その素質を持っている人だけが、
高い技術力を獲得できる傾向があるように思われます。
</p>
<p>
なので、
自分が何に向いているか早く見つけることが何より重要、
ということになります。
ただし、いわゆる
「自分探し」
は時間の無駄です。
なぜなら、
向いているか向いてないかは、
やってみなければ分からないからです。
</p>
<p>
就活でちょろっとその会社の説明を聞いたぐらいで、
その仕事が自分に向いているか分かるわけはないのはもちろんですが、
実際に働き始めてみて
「自分に合いそう」
とか
「この仕事は自分に向いていない」
とか思うのもタイテー間違っていて、
自身の能力の限界まで力を出しきってみて初めて、
向いているか否かが分かる性質のものだと思います。
そもそもろくに仕事の内容を理解できてない段階で
「好き」
だの
「嫌い」
だの言ってみても始まりません。
何事もつきつめていけばそれまで見えなかったものが見えてくるわけで、
「好き」
だの
「嫌い」
だのは視野が充分広がった後で判断すべきものでしょう。
</p>
<blockquote>
「好きなこと」
を仕事にするのは叶わぬ夢なのか?
</blockquote>
<p>
「好きなこと」
「向いていること」
を仕事にしたい。
多くの人がそう望んでいると思いますが、
現実はそうなっていません。
むしろ、
生活のため仕方なく仕事している、
という人がほとんどでしょう。
「好きなことはあるけれど、
それで食っていくことはできない」
とあきらめてしまっています。
</p>
<p>
例えば、
私の周囲にはセミプロ級 (自称) のカメラマンがいます。
そんなに好きならなぜプロにならないのか? 
と聞いたこともあるのですが、
「カメラは趣味だからいいんだ」
などと意味不明な答が返ってきます。
彼らはプロを目指さず、
あまり好きでもないソフトウェア開発業務に携わっているわけですが、
それはプロのカメラマンを目指そうとすると、
自身にその素質がないことが白日のもとにさらされると思っているからなのでしょう。
つまり、
本気でプロを目指して挫折すると、
せっかくの
「趣味」
が嫌いになってしまうのが怖いのだと思います。
</p>
<p>
つまり、
「好きなことで食っていけない」
のではなくて、
プロを目指してみる覚悟がないだけなのです。
本気でプロを目指せば、
その道の素質があるか否か、
たちどころに分かることでしょう。
もし素質がなければ、
さっさとあきらめて別の道を試せばいいだけの話です。
手当たり次第に試していけば、
きっと自分に向いていて、
かつ本当に好きと思える仕事が見つかることでしょう。
</p>
<p>
だから最初に何をやるかは実はあまり重要ではなくて、
何をやるにしても本気でプロを目指してみることが重要、
ということになります。
大学に残ってアカデミックな世界のハイアラーキを登り詰めようというのでなければ、
プロを目指すのは就職してからが本番ということになります。
</p>
<p>
では、いま何をすべきか?
</p>
<p>
「産業界が学生に求めるのはコミュニケーション能力だ」
というデマが出回っているようですが、
これは嘘ですので忘れてください。
マトモな人に聞いてみれば誰でも同じ答がすぐ返ってくると思うのですが、
一番重要なのは
「考える力」
です。
</p>
<blockquote>
考える力がないヤツ多すぎ (´･ω･`)
</blockquote>
<p>
そもそも大多数の学生さんは
「考える力」
が何だか分かっていません。
幾多の試験を突破し、
大学院にまで登り詰めた学生さんを相手にずいぶんな言いようだと思いますが、
実際に数多くの学生さんと話してみた結果なのだから仕方ありません。
逆に、
考える力のある学生さんなら、
学歴・知識・コミュニケーション能力など一切不問で採用します。
</p>
<p>
例えば、
ほとんどの学生さんは、
何を聞いても質問一つできません。
当人は質問すべきことがないから質問しないだけ、
と思ってヘーキな顔をしていますが、
本当は<a href="http://cto.gcd.org/2010/04/576/">何を質問したらいいか考えられない</a>だけなのです。
また、
学生さんが就職して会社で開口一番、
何と言うか分かりますか?
</p>
<p>
少なくない人が
「早く仕事に慣れて、みなさんのお役に立ちたい」
って言うんです。
ベルトコンベアの組立工とか、
マニュアル通りに振る舞うことが期待されるマクドナルドの店員とかなら、
仕事に慣れることも必要でしょうが、
そういう仕事だと思って就職したんでしょうか?
いくら今まで仕事をした経験がないといって、
あまりにウブすぎます。
</p>
<p>
そして極めつけは、
知識の習得には貪欲でも、
習得して何がしたいかの展望をまるで持っていないことです。
知識は手段であって目的ではありません。
それが小学校〜大学院 6+3+3+4+2=18年にもおよぶ学習期間において、
ひたすら知識を習得し続けた結果、
なんのために習得したのか、
その目的をすっかり忘れてしまったのでしょう。
</p>
<blockquote>
学びて思わざれば、すなわち罔し
</blockquote>
<p>
「目的意識を明確に持て」
とは誰しも言う言葉ですが、
では目的とは具体的には何なのか?
「世のため人のため」
とか途方もなく抽象的なことを言ってお茶を濁していませんか?
あるいは逆に
「給料をもらうため」
とか途方もなく具体的なことを言ってしまうかも知れません。
いずれの場合も、
そこから考える余地があまりなく、
思考停止してしまいがちです。
</p>
<p>
抽象的な話では面白くないので、
私自身の例を紹介しますと、
ずいぶん前から (たぶん中学生のころから)
「有名になりたい」
という目的を持ち続けています。
自分の名前を売るにはどうすればいいか考え、
(オープンソースという言葉ができる以前から) 
オープンソースソフトウェア 
(例えば <a href="http://www.gcd.org/sengoku/stone/Welcome.ja.html">stone</a>) を公開し、
<a href="http://www.gcd.org/blog/">ブログ</a>を書き、
<a href="http://cto.gcd.org/2010/12/692/">インタビュー</a>を受け、
いろんなところで<a href="http://cto.gcd.org/2008/04/398/">講演</a>したり<a href="http://cto.gcd.org/2009/10/402/">パネルディスカッション</a>に登壇したりしています。
今日、
ここでこうやって講演しているのも、
実を言えば、
人前でうまく話す練習をしたい、
というのが一番の動機だったりします。
</p>
<p>
ついでにいうと、
なんで有名になりたいかと言えば、
自由になりたいからです。
近頃は
「社蓄」(「会社＋家畜」から来た造語)
という言葉が使われるようになりましたが、
いわゆるフツーのサラリーマンは少しも自由ではありません。
嫌な仕事でも生活のためにヤムを得ず働いているわけです。
会社に依存せずに生きるには、
会社の肩書がなくてもやっていけるだけのネームバリューが必要ということに
(たぶん中学生のころ) 気付き、
それ以来、
自由になるにはどうすればよいか考え続けてきました。
</p>
<p>
考える力は、
考えることによってしか伸びないわけで、
そのためには自分の考えが足りないことを自覚することが必須でしょう。
そして考えが足りないことを自覚するには、
まず自分が無知であること、
すなわち自分は何が分かっていないかを自覚することが必要です。
</p>
<p>
ここで重要なのは、
「分かってない」
と
「知らない」
の違いです。
「知らない」
ことは調べれば済む話で、
考えてどうこうできる問題ではありません。
つまり
「自分には知らないことがある」
と自覚したところでそれは考えるきっかけにはなり得ません。
</p>
<p>
一方、
「分かってない」
のは決して知識が足らないためではありません。
だから調べてどうこうできる問題ではありません。
例えば
「数」
の概念が分かってない人に
「数」
とは何かを教えようとする状況を想像してみてください。
あるいは逆に、
自分が
「数」
という概念を分かってなかったとして、
どうしたら
「数という概念が分かっていない」
ことに気付けるか想像してみてください。
</p>
<blockquote>
「分かってない」
と
「知らない」
は違う<br />
<br />
「分かる」
と
「自転車に乗れるようになる」
は似ている
</blockquote>
<p>
思うに、
「分かる」
というのは
「自転車に乗れるようになる」
ことに似ていると思います。
「分かってない人」
が無自覚であると同様、
自転車を見たことがない人にとっては、
自分が自転車に乗れないと気に病むことはないでしょう。
そして最初の
「分かろう」/「乗ろう」
というチャレンジは確実に失敗します。
どうすれば
「分かるか」/「乗れるか」
皆目見当がつかない一方で、
いったん
「分かる」/「乗れる」
と、
どうやってそれができるようになったのか思い出せなくなってしまいます。
</p>
<p>
というわけで、
「考える」
ためにはまず自分が
「分かってない」
ことを自覚し、
次に
「分かろう」
と努力することが必要です。
</p>
<p>
後者は、
「分からないこと」
が目の前にあるわけですから、
あきらめさえしなければさほど難しくはないでしょう。
といっても思考停止という罠がたくさんあるので、
後者は後者で一筋縄には行かないのですけれど、
そんなことより問題は前者です。
</p>
<p>
すなわち、
「分かってない」
ことをいかに自覚するか?
が鍵となります。
</p>
<p>
おそらく、
自力で自分の
「分かってなさ」
を自覚することは無理で、
他者に指摘してもらって初めて気付かされる、
という場合がほとんどなのではないかと思います。
じゃ、
どうすれば他者に指摘してもらえるか?
黙っていては無理で、
自分から自身の考えを発信してみることが重要なのではないでしょうか?
</p>
<p>
変なことを発信すれば、
親切な人が
「おまえは何を言ってるんだ?」
と指摘してくれるかも知れませんし、
慣れてくると他者の反応もあらかじめ予測できるようになり、
発信する文章を練っている段階で自分の至らなさを痛感するかも知れません。
私自身、
こうやって自身の考えを長々と述べていますが、
この考えのほとんどは、
いろいろな人と対話した結果生まれたものであって、
決して私の頭だけで考え出したものではなかったりします。
</p>
<p>
というわけで、
まずは内容は二の次で、
自分の言葉を発してみることが何よりも重要でしょう。
例えば今この場で、
<a href="http://cto.gcd.org/2008/04/398/">質問してみる</a>ところから始めてみてはいかがでしょう?
</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gcd.org/blog/2011/10/853/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Android 端末で Picasa を使用して画像を共有できなかったので、対策を考えてみた</title>
		<link>http://www.gcd.org/blog/2011/08/847/</link>
		<comments>http://www.gcd.org/blog/2011/08/847/#comments</comments>
		<pubDate>Mon, 22 Aug 2011 22:31:06 +0000</pubDate>
		<dc:creator>hiroaki_sengoku</dc:creator>
				<category><![CDATA[Android]]></category>

		<guid isPermaLink="false">http://www.gcd.org/blog/?p=847</guid>
		<description><![CDATA[Android 上のアプリの多くは 「共有」 機能を用いて他のアプリへデータを送ることができる。 例えば画像ビューアだと、 「メニュー」 から 「共有」 を選び、 「Picasa」 を選ぶことで Android 標準の  [...]]]></description>
			<content:encoded><![CDATA[<img src="http://www.gcd.org/sengoku/android/share_Picasa.png" width="240" height="400" class="pict-left" alt="share - Picasa" />
<p>
Android 上のアプリの多くは
「共有」
機能を用いて他のアプリへデータを送ることができる。
例えば画像ビューアだと、
「メニュー」
から
「共有」
を選び、
「Picasa」
を選ぶことで
Android 標準の com.google.android.apps.uploader
(マイアップロード)
アプリを使って、
<a href="http://picasaweb.google.com/">Picasa ウェブアルバム</a>へ画像をアップロードできる
(← 左図)。
</p>
<p>
ところが、
この Picasa には Google アカウントとの連係に問題があって、
Android 端末の状態によっては 
<a href="https://plus.google.com/115826285346738411970/posts/CaZ481LmGJA">Picasa へのアップロードができなくなってしまう</a>。
つまり、
「Picasa」
を選んだときに、
「Googleアカウントを追加」
する画面に遷移してしまい先に進めない (↓ 下図)。
</p>
<img src="http://www.gcd.org/sengoku/android/add_account.png" width="240" height="400" class="pict-right" alt="add Google Account" />
<p>
既にこの携帯に登録済の Googleアカウントで、
画像をアップロードしたいのに、
「マイアップロード」
が現在の登録済アカウントを認識できず、
アカウントの追加を求めてくる。
</p>
<p>
[戻る]
ボタンを押すと
「マイアップロード」
が終了してしまうので、
仕方なく
[次へ]
をタップして
Googleアカウントを追加しようとすると、
「アカウントが既に存在します」
と言われてしまう (↓ 下図)。
</p>
<img src="http://www.gcd.org/sengoku/android/account_exists.png" width="240" height="400" class="pict-left" alt="Google Account exists already" />
<p>
「アカウントが存在する」
のが分かってるなら、
そのアカウントで画像をアップロードしろよ！
と言いたくなるが、
画面には
[戻る]
しかないのでどうにもならない。
</p>
<p>
<a href="http://www.google.com/support/accounts/bin/answer.py?hl=ja&amp;answer=183013">Google ヘルプ</a>を見ると、
<a href="http://picasaweb.google.com/">http://picasaweb.google.com</a> 
に一度もアクセスしない状態でアップロードを試みると、
このような二進も三進も行かない状態に陥る、
ということらしい。
そこまで分かってるなら対策しろよ、
と言いたくなる。
まあ、
Google 的には、
Picasa へ直接アップロードするのではなく、
Google+ 経由で使って欲しいということなのかもしれないが。
</p>
<img src="http://www.gcd.org/sengoku/android/delete_account.png" width="240" height="400" class="pict-right" alt="delete Google Account" />
<p>
もちろん、
現在の Googleアカウントをいったん削除すれば、
アカウントを追加することは可能になる (はず)。
しかし、
アカウントを削除しようとすると、
「携帯のメール、連絡先などのすべてのデータも削除されます」
などと脅される (右図 →)。
</p>
<p>
アカウントを削除しても、
再度アカウントを追加すれば、
削除されたメールや連絡先も再同期されるのだとは思うが、
「<a href="http://blog.livedoor.jp/ramerika/archives/51572329.html">１つ目のアカウントを絶対削除したらだめ</a>」
という先達の意見をスルーするのも気が引ける。
</p>
<p>
また、
<a href="http://mobile-s.jugem.jp/?eid=6">知らぬ間にPicasaとの同期が始まる</a>ケースもあるらしいが、
ただ待ってるというのも能がないし、
待っていれば必ず始まるというものでもないだろう。
</p>
<p>
そこで、
アカウントを削除すること無く、
他への影響を最小限に抑えつつ、
Picasa Web Albums を同期させる方法を考えてみた。
</p>
<span id="more-847"></span>
<p>
要は、
マイアップロードにおいて
Googleアカウントを追加する際、
追加したいアカウント (この場合だと sengoku@gmail.com) 
が存在しないと判定されれば、
前述したようなエラーが出ること無く、
Picasa Web Albums の同期のセットアップが完了できるはず。
</p>
<p>
Android には、
/data/system/accounts.db というデータベース (DB) がある:
</p>
<pre class="terminal">
senri:~ $ adb shell<span style="color:red">↓</span>
$ su<span style="color:red">↓</span>
# sqlite3 /data/system/accounts.db<span style="color:red">↓</span>
SQLite version 3.6.22
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> .tables<span style="color:red">↓</span>
accounts          authtokens        grants
android_metadata  extras            meta
sqlite> .schema accounts<span style="color:red">↓</span>
CREATE TABLE accounts ( _id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, type TEXT NOT NULL, password TEXT, UNIQUE(name,type));
CREATE TRIGGER accountsDelete DELETE ON accounts BEGIN   DELETE FROM authtokens     WHERE accounts_id=OLD._id ;   DELETE FROM extras     WHERE accounts_id=OLD._id ;   DELETE FROM grants     WHERE accounts_id=OLD._id ; END;
sqlite> select * from accounts;<span style="color:red">↓</span>
1|sengoku@gmail.com|com.google|《暗号化してBase64エンコードしたパスワード》
2|gcd_org|com.twitter.android.auth.login|
3|hiroaki_sengoku|com.skype.contacts.sync|
sqlite> 
</pre>
<p>
Android は同期を行なう際、
この DB のデータを使ってサーバへのログインを行なっているようだ。
ということは、
この DB 内の accounts テーブルにおいて、
「sengoku@gmail.com」
のレコードを削除してしまえば、
sengoku@gmail.com が存在しないと判定されて、
Googleアカウントを追加することが可能になる?
<img src="http://www.gcd.org/sengoku/android/login_account.png" width="240" height="400" class="pict-right" alt="login Google Account" />
</p>
<p>
DB のレコードを削除した直後にアカウントの追加を行なえば、
レコードが存在しない時間を最小限にできる。
この DB を参照するプログラムが動いたりしない限り、
悪影響を及ぼすことはないだろう。
もちろん、
「自動同期」
はオフにしておくべき。
また、
動いているアプリをできる限り終了させておく。
</p>
<p>
accounts.db のコピーをどこかへ保存しておけば、
万一、
なにか異常事態に陥っても、
accounts.db の内容を元に戻すことにより復旧は可能だろう。
万万が一に備えて、
念のためにシステム全体のバックアップも取っておく。
</p>
<p>
万全の備えをした後に、
<a href="https://market.android.com/details?id=com.alensw.PicFolder">画像ビューア</a>にて適当な画像を選び、
「共有」
メニューから
「Picasa」
を選ぶ。
すると、
前述したように
「Googleアカウントを追加」
する画面に遷移するので、
[次へ]
をタップし、
(携帯に登録済の) Googleアカウントを入力する (右図→)。
</p>
<p>
ここで
[ログイン]
をタップすると、
前述したように
「アカウントが既に存在します」
と言われてしまうので、
[ログイン]
をタップする前に、
accounts テーブルから、
「sengoku@gmail.com」
のレコードを削除する:
</p>
<pre class="terminal">
sqlite> delete from accounts where _id=1;<span style="color:red">↓</span>
sqlite> select * from accounts;<span style="color:red">↓</span>
2|gcd_org|com.twitter.android.auth.login|
3|hiroaki_sengoku|com.skype.contacts.sync|
sqlite> 
</pre>
<img src="http://www.gcd.org/sengoku/android/account_registered.png" width="240" height="400" class="pict-right" alt="Google Account registered" />
<p>
そして、
間をおかずに
[ログイン]
をタップ。
すると、
めでたく登録が完了した (右図→)。<br />
これで、
[設定]→
[アカウントと同期] に、
「Picasa Web Albums を同期」
の項目が表示されるようになった。
</p>
<p>
メールや連絡先の同期も問題無く行なうことができた。
3日ほど普通に使っているが、
特に問題は起きていない。
</p>
<img src="http://www.gcd.org/sengoku/android/access_request.png" width="240" height="400" class="pict-left" alt="Access Request" />
<p>
accounts テーブルの schema を見ると分かる通り、
DELETE TRIGGER が定義されていて、
レコードが削除されると、
grants テーブルからも該当レコードが削除される。
なので、
アクセスリクエストを再度許可する必要は生じる (← 左図)。
</p>
<p>
その一方で、
accounts.db は 
<a href="http://developer.android.com/reference/android/provider/Settings.Secure.html#ANDROID_ID">Android ID</a> 
等の端末固有情報とは関係がないので、
<a href="https://market.android.com/">Android マーケット</a>におけるアカウントには影響しない。
私は有料アプリ/コンテンツを買ったことがないので確認はできないが、
おそらくアプリからはレコード削除後も同一端末と見なされるはず
(ライセンスが無効になったりはしないと思われる)。
</p>]]></content:encoded>
			<wfw:commentRss>http://www.gcd.org/blog/2011/08/847/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>OpenVZ な ServersMan@VPS で独自 OS を動かしてみた</title>
		<link>http://www.gcd.org/blog/2011/07/842/</link>
		<comments>http://www.gcd.org/blog/2011/07/842/#comments</comments>
		<pubDate>Sun, 31 Jul 2011 01:48:25 +0000</pubDate>
		<dc:creator>hiroaki_sengoku</dc:creator>
				<category><![CDATA[IPv6]]></category>
		<category><![CDATA[システム構築・運用]]></category>

		<guid isPermaLink="false">http://www.gcd.org/blog/?p=842</guid>
		<description><![CDATA[国内に (自宅以外で) IPv6 が使えるサーバが欲しかったので、 ServersMan@VPS を使ってみた。 ServersMan@VPS は仮想化プラットフォームが OpenVZ なので今まで敬遠していたのだが、  [...]]]></description>
			<content:encoded><![CDATA[<p>
国内に (自宅以外で) 
<a href="http://www.gcd.org/blog/2011/07/820/#more-820">IPv6 が使えるサーバが欲しかった</a>ので、
<a href="http://dream.jp/vps/">ServersMan@VPS</a> を使ってみた。
ServersMan@VPS は仮想化プラットフォームが
<a href="http://wiki.openvz.org/Main_Page">OpenVZ</a> 
なので今まで敬遠していたのだが、
<a href="http://www.saases.jp/vps/">Osukini サーバ</a> 
(<a href="http://xen.org/">Xen</a>) も、
<a href="http://vps.sakura.ad.jp/">さくらの VPS</a> 
(<a href="http://www.linux-kvm.org/page/Main_Page">KVM</a>) も、
いまのところネイティブな IPv6 はサポートしていない
(さくらの IPv6 は <a href="http://research.sakura.ad.jp/6rd-trial/">6rd</a>) 
ので、
やむなく契約してみた次第。
</p>
<p>
Xen や KVM などの完全仮想化と異なり、
OpenVZ はホストOS のカーネルがゲスト OS のカーネルとしても使われる。
つまり VPS (Virtual Private Server) 
サービスのユーザが別のカーネルを立ち上げることができない
(ServersMan@VPS Perfect は完全仮想化だが月額 
3150円と高いのでここでは考えない)。
OS は CentOS, Debian, ubuntu から選ぶことになる。
</p>
<p>
しかしながら、
私が個人的に管理しているサーバは、
全て OS を独自の
「<a href="http://www.gcd.org/blog/2007/09/129/#mydistribution">my distribution</a>」
(便宜上ここでは GCD OS と呼ぶ)
に統一していて、
全サーバでディスクの内容を同期させている。
つまりある特定のサーバ固有の設定情報も、
全サーバが共有している。
共有していないのは各サーバのホスト名と、
秘密鍵などごく一部の情報だけ。
だからサーバが壊れた場合も、
新しいマシンを用意して他のサーバからディスク内容を丸ごとコピーするだけで済む。
</p>
<p>
私個人で管理しているサーバ (もちろん会社で運用しているサーバは除く) は、
仮想環境も含めると 20台ほどになるので、
異なる OS はできれば管理したくない。
ServersMan@VPS で提供されるカーネルを使うのは
(OpenVZ の仕組み上) 仕方がないとして、
ディスクの内容は GCD OS と入れ替えることにした。
</p>
<p>
稼働中のサーバをいじるとき重要なのが、
トラブった時に
「元に戻せるか?」
ということ。
元に戻せるなら多少の失敗を恐れることはない。
ほとんどの VPS サービスは、
最悪の事態に陥っても初期化すれば元通りになるので、
操作をミスっても一からやり直せばいいのだが、
OS を入れ替えようとする場合は
(当然) 新しい OS 一式を送り込む必要があり、
初期化するとこれが消えてしまうので再度転送する羽目になる。
GCD OS は最小セットで 7GB 近くあるので、
何度も転送を繰り返したりすると 
VPS サービスの契約ネットワーク帯域を使いきってしまう。
</p>
<p>
幸い、
ServersMan@VPS に帯域制限は無いが、
一日に 何十GB も転送していたら、
きっと管理者に睨まれるはず。
そこで、
どんなに失敗しても、
再起動すれば ssh でログインできる状態に戻るような 
OS 入れ替え手順を考えてみた。
ssh でログインできさえすれば後は何とでも修復できる。
逆に言うと ServersMan@VPS のようなコンソールが提供されない 
VPS サービスでは ssh でログインできなくなると万事休す、
残された復旧手段は初期化しかない。
</p>
<p>
まず ServersMan@VPS Standard プランを契約 (月額 980円) して、
Ubuntu(64bit) の最小構成 (シンプルセット) を選択。
ssh でログインして 
netstat でソケットを開いているデーモンを調べ、
片っ端から dpkg --purge (アンインストール) する。
もちろん sshd (ssh サーバ) だけは purge してはいけない。
syslog や cron などフツーは決して purge しないデーモンも遠慮無く purge する。
ps したとき sshd のプロセスのみが表示されるような状態になるまで 
purge しまくる。
で、
一通り purge し終わったら念のため再起動してみる。
もしここで ssh でログインできなくなってしまっていたら、
初期化して振出しに戻る。
</p>
<p>
この時、
sshd が 22番ポートで listen している場合は、
GCD OS が起動する sshd と衝突するので、
22番ポート以外に変えておく。
幸い ServersMan@VPS の場合は sshd が初めから 3843番ポートで 
listen する設定になっていた (なぜ?) ので、
そのままにしておく。
</p>
<p>
次に、
デーモン類以外のパッケージも、
残しておくとディスクの肥やしになるだけなので、
できるだけ purge する。
とはいっても、
多くのパッケージが数MB 以下で容量的には誤差の範囲なので、
無理に purge して再起不能状態に陥るリスクを冒すより、
ディスクの肥やしにしておいた方がマシ。
で、
一通り purge し終わったら念のため再起動してみる。
もしここで ssh でログインできなかったら、
初期化して振出しに戻る。
</p>
<p>
こうして
netstat -nap しても ps axf しても 
sshd 以外のプロセスが一切残っていない状態になったら、
いよいよ GCD OS 一式を送り込む。
</p>
<pre class="terminal-scroll">
senri:/ # mirror -v -r /usr/local/gcd -e 'ssh -p 3843' 'core64[183.181.54.38]' > /tmp/serversman &amp;
</pre>
<p>
mirror というのはサーバ間で GCD OS の同期を行なうためのスクリプト。
64bit (x86_64) の最小セットをコピーするために引数として 
「core64」 
を指定した。
このスクリプトは、
同期すべきファイルのリストを作成して 
<a href="http://rsync.samba.org/">rsync</a> を呼び出す。
「-e 'ssh -p 3843'」
オプションは、
そのまま rsync に渡される。
このコマンド列で GCD OS 最小セット約 7GB が 
VPS の /usr/local/gcd ディレクトリ以下へ丸ごとコピーされる。
7GB の転送にどのくらいかかるかと思っていたら、
わずか 10分弱で終わってしまった。
100Mbps 以上の帯域ということになる。
結構すごい。
</p>
<p>
ホスト名を chiyoda.gcd.org に設定し、
このサーバ専用の秘密鍵を作成すれば GCD OS のインストールが完了。
あとは、
/usr/local/gcd 以下へ chroot して GCD OS を起動するだけ。
次のような GCD OS 起動スクリプト /etc/init.d/chroot を書いてみた。
</p>
<pre class="code">
#!/bin/sh
root=`echo $0 | sed -e 's@/etc/init.d/chroot$@@'`
if [ ! -d $root ]; then
   echo "Can't find root: $root"
   exit 1
fi
mount -obind /lib/modules $root/boot/lib/modules
chroot $root sh &lt;&lt;EOF
mount -a
svscanboot &amp;
/etc/rc.d/rc.M
EOF
</pre>
<p>
このスクリプトも GCD OS 一式をコピーするときに
/usr/local/gcd/etc/init.d/chroot へコピーされる。
で、/usr/local/gcd/etc/init.d/chroot を、
とりあえず手動で実行。
手動で実行するところがミソで、
もしこのスクリプトにバグがあって異常事態に陥っても、
再起動すれば元に戻る。
</p>
<p>
上記 /usr/local/gcd/etc/init.d/chroot は、
chroot /usr/local/gcd sh を実行して、
chroot 環境下で 
<a href="http://cr.yp.to/daemontools/svscanboot.html">svscanboot</a> と
/etc/rc.d/rc.M を実行する。
svscanboot は 
<a href="http://cr.yp.to/daemontools.html">daemontools</a> の起動スクリプト。
GCD OS のほとんどのデーモン類は daemontools の管理下で起動される。
一方 /etc/rc.d/rc.M は、
GCD OS のブートスクリプトで、
ファイアウォールなどネットワークまわりの設定や、
個々のサーバ特有の設定、
および一部のデーモン類の起動を行なう。
</p>
<p>
普通の Linux OS だと init から直接起動されるデーモンもあるが、
GCD OS の場合 init が起動するのは
/etc/rc.d/rc.S と /etc/rc.d/rc.M および svscanboot だけ。
/etc/rc.d/rc.S は、
OpenVZ 環境下では不要な処理ばかりなので実行する必要はない。
</p>
<p>
こうして chroot 環境下で GCD OS が起動したら、
chroot /usr/local/gcd sh などと実行して GCD OS 環境へ入ることができる。
各種設定が正しく機能しているか、
デーモン類が正しく動いているか確認する。
</p>
<p>
ServersMan@VPS で使われているカーネルが、
<a href="http://wiki.openvz.org/Download/kernel/rhel5/028stab069.6">2.6.18-194.3.1.el5.028stab069.6</a> と、
かなり古い (2.6.18 などという 5年も昔のカーネルを使い続けないでほしい ＞ RHEL) 
ので、
GCD OS をきちんと動かすには問題があった。
特に困ったのが、
iptables の owner モジュールが使えない点:
</p>
<pre class="terminal-scroll">
chiyoda:/ # uname -rv
2.6.18-194.3.1.el5.028stab069.6 #1 SMP Wed May 26 18:31:05 MSD 2010
chiyoda:/ # iptables -t nat -j REDIRECT -p udp --dport 53 --to-port 2053 -A dnscache.lo -s 127.0.0.1 -d 127.0.0.1 -m owner ! --uid-owner Gdnscache
iptables: No chain/target/match by that name.
</pre>
<p>
このエラーは、
カーネルに 
<a href="http://cateee.net/lkddb/web-lkddb/NETFILTER_XT_MATCH_OWNER.html">CONFIG_NETFILTER_XT_MATCH_OWNER</a> の設定がないのが原因。
NETFILTER_XT_MATCH_OWNER が導入されたのは 2.6.25 以降なので、
そもそも元から 2.6.18 には存在しない。
</p>
<p>
なぜ --uid-owner が必要かと言えば、
GCD OS では tinydns と dnscache を、
<a href="http://www.gcd.org/blog/2006/07/87/">同じ IP アドレスで動かす</a>ことが基本になっているから。
つまり、
通常の名前解決に 127.0.0.1 の dnscache を利用するのだが、
dnscache (Gdnscache 権限で動作) が 127.0.0.1 に問合わせる時に限り 
<a href="http://www.gcd.org/blog/2010/03/573/">mydns</a> が返事をするようにしたい。
</p>
<p>
仕方がないので、
iptables に --uid-owner を指定してエラーになる場合は、
--uid-owner 抜きで iptables を再実行するように修正した:
</p>
<pre class="code">
nsredirect="-t nat -j REDIRECT --dport 53 --to-port $PORT"
chain=dnscache.lo
iptables -t nat -N $chain 2&gt;/dev/null || iptables -t nat -F $chain
nsinner="$nsredirect -A $chain -s 127.0.0.1 -d 127.0.0.1 \
	-m owner ! --uid-owner Gdnscache"
iptables -p udp $nsinner
if [ $? -ne 0 ]; then
    nsinner="$nsredirect -A $chain -s 127.0.0.1 -d 127.0.0.1"
    iptables -p udp $nsinner
fi
iptables -p tcp $nsinner
</pre>
<p>
このような修正を、
chiyoda.gcd.org だけでなく、
GCD OS をインストールしている全サーバで一斉に行なう点がミソ。
サーバごとにファイルの内容が微妙に異なっていたりしたら、
GCD OS を使う意味がない。
</p>
<p>
当然、
--uid-owner 抜きで iptables を実行した場合は、
dnscache が 127.0.0.1 の mydns に問合わせをすることができないが、
127.0.0.1 以外、
つまり 183.181.54.38 あるいは 2001:2e8:634:0:2:1:0:2a ならば 
mydns に問合わせることができるので問題無い。
</p>
<p>
じゃ、
なんのために、
わざわざ --uid-owner を使って 127.0.0.1 の 
mydns に問合わせられるようになっているかというと、
127.0.0.1 以外の IP アドレスが動的に変わるサーバ (ノートPC など) 
も想定しているから。
GCD OS は VirtualBox や Xen などの完全仮想化環境だけでなく、
<a href="http://www.colinux.org/">coLinux</a> や今回の OpenVZ など、
仮想化環境としてはやや異質なものもサポートしている。
</p>
<p>
以上のような細かい修正を行なっていって、
GCD OS が問題無く立ち上がるようになったら、
/usr/local/gcd/etc/init.d/chroot の呼び出しを
(ubuntu の) /etc/rc.local に追加して、
VPS の起動時に自動的に GCD OS が起動されるようにする。
</p>
<p>
GCD OS が正しく立ち上がれば、
外部から 22番ポートに対して ssh ログインして GCD OS が使える。
22番ポートでログインできることが確認できたら、
3843番ポートの sshd は止めてもよい。
<a href="http://www.gcd.org/blog/2007/09/132/">chroot 環境からはいつでも脱出できる</a>ので、
3843番ポートを止めても本来の
(chroot する前の) ubuntu 環境にアクセスすることが可能:
</p>
<pre class="terminal">
senri:~ # ssh chiyoda.gcd.org
Enter passphrase for key '/root/.ssh/id_rsa':
Last login: Sat Jul 30 09:14:54 2011 from 2409:82:5fff:0:5542:d84e:971a:9656
Linux 2.6.18-194.3.1.el5.028stab069.6.
chiyoda:~ # ls -F /					<span style="color:red">↓ GCD OS</span>
bin@   dev/  ftp/   lib/    proc/  run/   sys/  usr/
boot/  etc/  home/  lib64@  root/  sbin@  tmp/  var/
chiyoda:/ # chroot_escape /bin/bash			<span style="color:red">← chroot から脱出</span>
groups: cannot find name for group ID 11
groups: cannot find name for group ID 14
root@chiyoda:/# ls -F --color=never			<span style="color:red">↓ ubuntu</span>
aquota.group@  boot/  fastboot  lib32/  mnt/   sbin/     sys/  var/
aquota.user@   dev/   home/     lib64@  proc/  selinux/  tmp/
bin/           etc/   lib/      media/  root/  srv/      usr/
root@chiyoda:/# cat /etc/debian_version
squeeze/sid
root@chiyoda:/# lsb_release -r
Release:	10.10
root@chiyoda:/# exit
chiyoda:~ # 						<span style="color:red">↓ GCD OS</span>
</pre>
<p>
「chroot_escape /bin/bash」
が、
<a href="http://www.gcd.org/blog/2007/09/132/">chroot 環境から脱出するコマンド</a>。
脱出して、
「本来の」 
root 環境 (この例では ubuntu) 下で、
引数のコマンド
「/bin/bash」
を実行する。
この bash を使って ubuntu の操作ができて、
exit すると元の GCD OS へ戻る。
まるで chroot 下の GCD OS の方が 「主」 で、
本来の root が 「従」 のように見える ;-)。
</p>
<p>
なお、
chroot_escape コマンド実行時の
「groups: cannot find name for group ID 〜」
というエラーは、
GCD OS の /etc/group と ubuntu の /etc/group が異なるため。
つまり GCD OS の root は ID 11 と 14 のグループに属しているが、
ubuntu には ID が 11 と 14 のグループが存在しないため、
このようなエラーが表示される。
</p>
<p>
ここまでやるなら、
chroot といわず root に GCD OS をインストールしてしまえば? 
という声が聞こえてきそうであるが、
ServersMan@VPS ではコンソールが利用できないため、
トラブったときのために何らかの
「バックドア」
は残しておきたい。
GCD OS がどのような状況に陥っても、
3843番ポートの sshd 
(init から起動されるので kill しても再起動する)
にログインできれば、
ubuntu 環境で GCD OS の修復が可能。
</p>
<p>
というわけで一週間ほど ServersMan@VPS Standard プランを使っているが、
意外に (失礼!) 使えるので驚いた。
実は、
OpenVZ な 512MB ということであまり期待していなかった。
OpenVZ は swap を使えないので、
メモリ 512MB だと、
ちょっと重い処理をさせるだけですぐ OOM Killer が動き出すのだろうと思っていた。
ところが、
</p>
<pre class="terminal">
chiyoda:~ $ free
             total       used       free     shared    buffers     cached
Mem:       2097152     425020    1672132          0          0          0
-/+ buffers/cache:     425020    1672132
Swap:            0          0          0
</pre>
<p>
512MB というのは実メモリ? の割当量のようで、
見かけ上は 2GB のメモリがある。
OpenVZ な VPS サービスによっては、
これをメモリ 2GB と言い張るところもあるんじゃないかと思うので、
ServersMan@VPS は良心的。
</p>
<p>
どのくらいのパフォーマンスなのか、
<a href="http://www.gcd.org/blog/">この日記</a> (WordPress を使用)
の処理時間を測ってみる。
senri.gcd.org から ApacheBench でアクセスすると:
</p>
<pre class="terminal">
senri:~ $ /usr/apache2/bin/ab -n 10 http://chiyoda.gcd.org/blog/
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
	...
Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        6    7   0.3      7       7
Processing:   992 1116  94.1   1139    1259
Waiting:      305  403  78.3    380     561
Total:        998 1122  94.1   1146    1265
</pre>
<p>
これを、
<a href="http://www.gcd.org/blog/2010/02/544/">Linode Xen 512MB プラン</a>
(fremont.gcd.org)
と比較する。
fremont.gcd.org は米国西海岸にある VPS なので、
同じく<a href="http://www.gcd.org/blog/2010/06/590/">西海岸にある prgmr.gcd.org</a> 
から ApacheBench でアクセスすると:
</p>
<pre class="terminal">
prgmr:~ $ /usr/apache2/bin/ab -n 10 http://fremont.gcd.org/blog/
	...
              min  mean[+/-sd] median   max
Connect:        2    3   0.1      3       3
Processing:   996 1081  73.8   1084    1197
Waiting:      354  391  30.5    388     450
Total:        999 1084  73.8   1086    1200
</pre>
<p>
両者は、
ほとんど同等のパフォーマンスであることが分かる。
Linode Xen 512MB プランは、
ディスク 20GB で月額 $19.95 (約 1600円)
なので、
ServersMan@VPS Standard プラン (ディスク 30GB, 月額 980円) 
の方がコストパフォーマンスが良い。
</p>
<p>
もちろん、
ServersMan@VPS Standard には、
カーネルのバージョンが古すぎ、という問題点があるし、
メモリ 512MB を超える部分のパフォーマンスは、
ホストOS 側の負荷状況に左右されると思われるので、
単純に比較すべきではない。
</p>]]></content:encoded>
			<wfw:commentRss>http://www.gcd.org/blog/2011/07/842/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>フレッツ 光ネクストの IPv6 IPoE 接続 (ネイティブ方式) を使ってみた</title>
		<link>http://www.gcd.org/blog/2011/07/820/</link>
		<comments>http://www.gcd.org/blog/2011/07/820/#comments</comments>
		<pubDate>Sun, 24 Jul 2011 09:33:16 +0000</pubDate>
		<dc:creator>hiroaki_sengoku</dc:creator>
				<category><![CDATA[IPv6]]></category>
		<category><![CDATA[システム構築・運用]]></category>

		<guid isPermaLink="false">http://www.gcd.org/blog/?p=820</guid>
		<description><![CDATA[IPv6 閉域網であることを今までさんざん dis られてきたフレッツ網 (NGN, 次世代ネットワーク) が、 ついに 7月21日からインターネットに接続できるようになった。 これでもう 「NGN と IPv6 インタ [...]]]></description>
			<content:encoded><![CDATA[<p>
IPv6 閉域網であることを今までさんざん dis られてきたフレッツ網 
(NGN, 次世代ネットワーク) が、
ついに 7月21日から<a href="http://www.ntt-east.co.jp/release/detail/20110719_01.html">インターネットに接続できるようになった</a>。
これでもう
「<a href="http://itpro.nikkeibp.co.jp/article/OPINION/20080227/294865/">NGN と IPv6 インターネットは併用できない</a>」
などとは言わせない。
私は IPv6 を既に <a href="http://www.gcd.org/blog/2011/06/812/">PPPoE 接続で使っている</a>のだが、
トンネル方式 (PPPoE) よりネイティブ方式 (IPoE) のほうがいいにきまってる、
ということで<a href="https://plus.google.com/115826285346738411970/posts/7zBdLThjQDp">さっそく申し込んでみた</a>。
</p>
<p>
<a href="http://www.flets-east.jp/">NGN のサービス情報サイト</a>
(NGN からでないとアクセスできない) のページで
「サービス申込受付」
をクリック。
「お客様ID」 
と 
「アクセスキー」
を入力してログインすると、
「<a href="http://flets.com/v6option/">フレッツ・v6オプション</a>」
を申し込むことができる (このページから申し込むと無料)。
</p>
<p>
申込み後、
NGN から流れてくる IPv6 ルータ広告 (RA, Router Advertisement)
を tcpdump で監視していたら、
34分経過した頃にプレフィックスが突然変わった。
<a href="http://www.gcd.org/blog/2009/11/180/">NGN の契約</a>以来、
今まで一度も変わったことがなかったプレフィックス 2408:82:5fff:86a::/64 が、
2408:282:5fff::/64 になった。
これはきっとインターネットと通信できるプレフィックスに違いないと思って、
<a href="http://fremont.gcd.org/test">他のサイト</a>から ping6 を打ってみた。
が、
NGN からは RA 以外は何も流れてこない。
うーん。
ちなみに RA の送信元 (NGN のエッジ・ルータ) は 
fe80::21e:13ff:fec2:69c2 のまま変わらず。
</p>
<p>
その後 1時間ほど放置してみたが何も状況が変化しなかったので、
「フレッツ・v6オプション」
って何? と思い直して 
(サービス内容をよく確認せずに申し込んでしまっていた)、
あらためて
<a href="http://flets.com/faq/service/090800.html">FAQ</a> を見ると、
</p>
<dl class="dialog">
<dt><b>　Q</b></dt><dd>
「フレッツ・v6オプション」を利用してインターネットへの接続はできますか？
</dd>
<dt><b>　A</b></dt><dd>
「フレッツ・v6オプション」
は、NTT東日本が構築するNGN内での通信が可能ですが、
「フレッツ・v6オプション」
のみではインターネットへの接続はできません。
インターネットへの接続には、
別途プロバイダサービスをお申し込みいただく必要があります。
</dd>
</dl>
<p>
インターネットへ接続するには、
フレッツ・v6オプションとプロバイダ契約の両方が必要らしい。
では、
どのプロバイダの、
どんなサービスを申し込めばいいんだろう?
と思って、
<a href="http://flets.com/next/ipv6_ipoe/isp.html">フレッツ 光ネクスト IPv6 IPoE対応プロバイダ</a>を調べてみると、
神奈川県だと現時点で対応しているのは 
<a href="http://www.iij.ad.jp/service/fletslineup.html">IIJmio</a>
だけだった (神奈川県だけでなく他県も同様)。
IIJ は今まで契約したことがなかったが、
他に選択肢が無いのであれば仕方がない。
さくっとクレジットカード番号を入力して
<a href="https://www.iijmio.jp/guide/outline/nbd/?l=0w149a">IIJmio FiberAccess/NF</a> を契約した (月額 2100円)。
これで半固定 IPv6 アドレスによる IPoE サービスと、
動的割当て IPv4 アドレスによる PPPoE サービスが利用できる。
</p>
<p>
Ether 上に IP を流すのはごくごく普通のことなので、
あらたまって
「IPoE」
(IP over Ether)
と表現されると何だか妙な感じ。
「半固定」
というのも微妙な表現だが、
注意書きには
「お客様の移転、フレッツ回線の品目変更やNTTのメンテナンスにより、
変更になる場合があります」
と書いてあるので、
普通に使ってる限りプレフィックスが変わることは無さそう。
</p>
<blockquote>
mio FiberAccess/NFサービスは、
<a href="http://www.mfeed.co.jp/">インターネットマルチフィード株式会社</a>が提供する
「<a href="http://www.mfeed.co.jp/transix/index.html">transix (トランジックス)</a>」
サービスを利用して、
NTT東西の
「インターネット（IPv6 IPoE）接続」
に対応したIPv6接続を提供します。
IPv6接続に加えて、
PPPoE接続方式によるIPv4接続もあわせて提供するため、
お客様は一つのサービスでIPv6、
IPv4の両方の接続環境を利用することができます。 
<div align="right">IIJmio <a href="https://www.iijmio.jp/guide/outline/nbd/?l=0w149a">FiberAccess/NF概要</a> から引用</div>
</blockquote>
<p>
IPv6 接続は全て transix が担っていて、
IIJmio はネットワーク的には何の役割も果たしていない。
IIJmio がやってるのは課金などユーザ管理関連だけ。
プロバイダである IIJmio が絡むから、
IPv4 接続も提供するなどという抱き合わせ商法になる。
動的割当の IPv4 PPPoE 接続サービスなんて要らないから、
もう少し安いプランがあればいいのにと思う。
</p>
<p>
本来、
ネイティブ方式の IPv6 接続サービスは、
NTT東西だけで提供するのが自然な形だった。
ところが、
NGN を持っていて地域独占な NTT東西が接続サービスまで提供してしまっては、
他のプロバイダの出る幕がなくなると猛反発されて、
<a href="http://www.bbix.net/">BBIX</a>, 
<a href="http://www.jpne.co.jp/">JPNE</a>, 
<a href="http://www.mfeed.co.jp/">インターネットマルチフィード</a>
の三社が接続サービスを提供することになった。
なぜ三社だけかといえば、
プロバイダを増やすと経路情報の処理量が膨大になって
NGN の各ルータの処理能力の限界を超えてしまうから。
</p>
<p>
ところが、
三社だけでは少なすぎると他のプロバイダ達が反対したので、
その他大勢の中小プロバイダにも参入の余地を無理矢理作ったということなのだろう。
でも、
やってることは単なるユーザ管理なので、
通信事業者じゃなくてもできる簡単なお仕事。
この期に及んで業界保護みたいなことはやめてほしい。
インターネット接続サービスは既にコモディティ化しているのだから、
体力のないところは淘汰されるべき。
</p>
<p>
FiberAccess/NF を契約してから 1時間が経過したとき、
NGN から流れてくる RA のプレフィックスが 2409:82:5fff::/64 に変わった。
今度こそ疎通したかと思い、
senri.gcd.org に IPv6 アドレス 2409:82:5fff::3c20:55dc を割当てて、
<a href="http://fremont.gcd.org/test">他のサイト</a>から
2409:82:5fff::3c20:55dc に対して ping6 を打ってみる。
すると無事、NGN IPoE 経由で senri.gcd.org に ICMPv6 パケットが届いた。
</p>
<p>
ただし、
まだ senri.gcd.org の routing 設定を行なっていないので、
返りパケットは PPPoE 経由で OCN 側へ行ってしまう 
(おそらく OCN 内部で捨てられる)。
そこで、
とりあえずの対策として NGN から届いたパケットは NGN へ返すように、
policy routing rule を設定した:
</p>
<pre class="terminal">
senri:/ # ip -6 rule add from 2409:82:5fff::/64 table 100 pref 25600
senri:/ # ip -6 route add default table 100 via fe80::21e:13ff:fec2:69c2 dev eth1
</pre>
<p>
つまり、
送信元アドレスが 2409:82:5fff::/64 なパケットは
routing table 100 を参照するようにして、
routing table 100 において default route を、
fe80::21e:13ff:fec2:69c2 (NGN のエッジ・ルータ) へ向ける。
</p>
<p>
これで ping に対して応答できるようになった。
</p>
<pre class="terminal">
fremont:~ $ ping6 -c 3 2409:82:5fff::3c20:55dc
PING 2409:82:5fff::3c20:55dc(2409:82:5fff::3c20:55dc) 56 data bytes
64 bytes from 2409:82:5fff::3c20:55dc: icmp_seq=1 ttl=49 time=122 ms
64 bytes from 2409:82:5fff::3c20:55dc: icmp_seq=2 ttl=49 time=122 ms
64 bytes from 2409:82:5fff::3c20:55dc: icmp_seq=3 ttl=49 time=122 ms

--- 2409:82:5fff::3c20:55dc ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 122.479/122.526/122.591/0.289 ms
fremont:~ $ tcpspray 2409:82:5fff::3c20:55dc
Transmitted 102400 bytes in 0.491628 seconds (203.406 kbytes/s)
</pre>
<p>
RTT (Round Trip Time, 往復所要時間) が 122ms もかかってるのは、
<a href="http://www.gcd.org/blog/2010/02/544/">fremont.gcd.org が米国の西海岸にある</a>ため。
2400:400d:100::3c20:55dc (OCN の PPPoE 接続) 宛の場合↓ と比べると、
transix は RTT で 50ms ほど速く、
帯域 (tcpspray による簡易測定) で倍くらい広い。
</p>
<pre class="terminal">
fremont:~ $ ping6 -c 3 2400:400d:100::3c20:55dc
PING 2400:400d:100::3c20:55dc(2400:400d:100::3c20:55dc) 56 data bytes
64 bytes from 2400:400d:100::3c20:55dc: icmp_seq=1 ttl=49 time=174 ms
64 bytes from 2400:400d:100::3c20:55dc: icmp_seq=2 ttl=49 time=174 ms
64 bytes from 2400:400d:100::3c20:55dc: icmp_seq=3 ttl=49 time=174 ms

--- 2400:400d:100::3c20:55dc ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2002ms
rtt min/avg/max/mdev = 174.046/174.386/174.593/0.539 ms

fremont:~ $ tcpspray 2400:400d:100::3c20:55dc
Transmitted 102400 bytes in 0.905523 seconds (110.433 kbytes/s)
</pre>
<p>
参考までに IPv4 60.32.85.216 (OCN の PPPoE 接続) の場合も測ってみた。
すると RTT も帯域も transix と同程度だった。
つまり OCN の IPv6 PPPoE だけが突出して遅く、
帯域も狭い。
</p>
<pre class="terminal">
fremont:~ $ ping -c 3 60.32.85.216
PING 60.32.85.216 (60.32.85.216) 56(84) bytes of data.
64 bytes from 60.32.85.216: icmp_req=1 ttl=51 time=130 ms
64 bytes from 60.32.85.216: icmp_req=2 ttl=51 time=130 ms
64 bytes from 60.32.85.216: icmp_req=3 ttl=51 time=129 ms

--- 60.32.85.216 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2002ms
rtt min/avg/max/mdev = 129.377/129.903/130.202/0.559 ms

fremont:~ $ tcpspray 60.32.85.216
Transmitted 102400 bytes in 0.518052 seconds (193.031 kbytes/s)
</pre>
<p>
米国西海岸から transix までの IPv6 の経路はこんな感じ:
</p>
<pre class="terminal">
fremont:~ $ tracepath6 2409:82:5fff::3c20:55dc
 1?: [LOCALHOST]                        0.021ms pmtu 1500
 1:  2600:3c01:ffff:0:ca4c:75ff:fef5:d63f                  0.558ms
 1:  2600:3c01:ffff:0:ca4c:75ff:fef5:d63f                  0.480ms
 2:  10gigabitethernet2-3.core1.fmt1.he.net                3.149ms
 3:  10gigabitethernet1-2.core1.sjc2.he.net               11.042ms
 4:  equi6ix.sv.iij.com                                    1.834ms asymm  5
 5:  sjc002bf00.iij.net                                    9.384ms asymm  7
 6:  2001:48b0:bb00:8016::71                             120.588ms asymm  7
 7:  tky009bb11.IIJ.Net                                  120.730ms asymm  8
 8:  tky009ip50.IIJ.Net                                  121.048ms
 9:  2001:240:bb5c:1008::cafe                            120.365ms
10:  2404:8e00:feed:101::2                               121.852ms
11:  no reply
12:  no reply
13:  no reply
14:  no reply
15:  no reply
16:  2409:82:5fff::3c20:55dc                             127.409ms reached
     Resume: pmtu 1500 hops 16 back 49
</pre>
<p>
「IIJmio はネットワーク的には何の役割も果たしていない」
が、
日米間の回線は IIJ が担っているようだ (あれっ? ^^;)。
日本に上陸後 (6 以降) はほとんど遅延していない。
</p>
<p>
OCN の PPPoE の場合だと、こんな感じ:
</p>
<pre class="terminal">
fremont:~ $ tracepath6 2400:400d:100::3c20:55dc
 1?: [LOCALHOST]                        0.047ms pmtu 1500
 1:  2600:3c01:ffff:0:ca4c:75ff:fef5:d63f                  3.935ms
 1:  2600:3c01:ffff:0:ca4c:75ff:fef5:d63f                  0.852ms
 2:  10gigabitethernet2-3.core1.fmt1.he.net                7.978ms
 3:  10gigabitethernet1-2.core1.sjc2.he.net                2.532ms
 4:  xe-0.equinix.snjsca04.us.bb.gin.ntt.net               2.018ms asymm  5
 5:  as-1.r21.osakjp01.jp.bb.gin.ntt.net                 168.074ms asymm 11
 6:  ae-0.ocn.osakjp01.jp.bb.gin.ntt.net                 167.792ms asymm 14
 7:  2001:380:8060:6::1                                  159.446ms asymm 13
 8:  2001:380:8170:4::1                                  167.630ms asymm 14
 9:  2001:380:8030:16::1                                 168.401ms asymm 15
10:  2001:380:8110:d::1                                  170.344ms asymm 14
11:  2001:380:8110:f::2                                  178.503ms asymm 13
12:  2001:380:8130:11::13                                178.131ms asymm 13
13:  2001:380:8270:8::2                                  172.448ms
14:  2001:380:4d:101::2                                  179.036ms
15:  2001:380:4d:182::2                                  181.317ms
16:  no reply
17:  2001:380:4d:181::2                                  173.127ms pmtu 1454
17:  senri.v6.gcd.org                                    183.023ms reached
     Resume: pmtu 1454 hops 17 back 49
</pre>
<p>
日米間に 160ms もかかっている上に、
日本に上陸後 (5 以降) も 15ms ほど遅延がある。
なぜこんなに遅いのだろう?
また、PPPoE なので mtu が 1454 になっている。
</p>
<p>
同じ OCN の PPPoE でも、
IPv4 だと遅くない (というか transix より若干速い) ので、
OCN の IPv6 PPPoE 接続サービスには、
なにか問題がありそう。
まあ、
追加料金無しのサービスなので、
IPv4 のオマケ的な位置づけなのかも?
</p>
<pre class="terminal">
fremont:~ $ tracepath 60.32.85.216
 1:  fremont.gcd.org                                       0.169ms pmtu 1500
 1:  184.105.143.85                                        1.702ms
 1:  184.105.143.85                                        0.418ms
 2:  10gigabitethernet2-3.core1.fmt1.he.net                0.665ms
 3:  10gigabitethernet1-1.core1.pao1.he.net                8.907ms
 4:  sjo-bb1-link.telia.net                                1.297ms asymm  5
 5:  verio-119529-sjo-bb1.telia.net                        4.568ms
 6:  ae-8.r20.snjsca04.us.bb.gin.ntt.net                   1.922ms
 7:  as-2.r20.tokyjp01.jp.bb.gin.ntt.net                 112.093ms asymm  8
 8:  ae-1.ocn.tokyjp01.jp.bb.gin.ntt.net                 119.692ms asymm 11
 9:  60.37.27.137                                        120.641ms asymm 10
10:  60.37.55.158                                        119.549ms asymm 11
11:  122.1.173.238                                       121.243ms
12:  118.23.5.78                                         128.853ms asymm 14
13:  no reply
14:  118.23.8.9                                          128.712ms pmtu 1454
14:  gcd.org                                             123.788ms reached
     Resume: pmtu 1454 hops 14 back 52
</pre>
<span id="more-820"></span>
<p>
7月26日追記:
</p>
<p>
西海岸から ping6 を打つのは 2階から目薬もびっくりなので、
<a href="http://dream.jp/vps/">国内の IPv6 が使える VPS</a> 
を急遽<a href="http://chiyoda.gcd.org/test">契約して</a> (2ヵ月無料キャンペーン)、
ping6 を打ってみた。
</p>
<pre class="terminal">
chiyoda:~ $ ping6 -c 3 senri
PING senri(2409:82:5fff::3c20:55dc) 56 data bytes
64 bytes from 2409:82:5fff::3c20:55dc: icmp_seq=1 ttl=49 time=6.96 ms
64 bytes from 2409:82:5fff::3c20:55dc: icmp_seq=2 ttl=49 time=6.72 ms
64 bytes from 2409:82:5fff::3c20:55dc: icmp_seq=3 ttl=49 time=6.51 ms

--- senri ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2001ms
rtt min/avg/max/mdev = 6.515/6.734/6.969/0.208 ms

chiyoda:~ $ tcpspray -n 10000 2409:82:5fff::3c20:55dc
Transmitted 10240000 bytes in 0.864344 seconds (11569.468 kbytes/s)
</pre>
<p>
さすがに国内からだと速くて広い。
93Mbps 出れば普通の用途には充分。
OCN PPPoE の IPv6 および IPv4 でも測ってみたが、
有意な差は見られない:
</p>
<pre class="terminal">
chiyoda:~ $ ping6 -c 3 2400:400d:100::3c20:55dc
PING 2400:400d:100::3c20:55dc(2400:400d:100::3c20:55dc) 56 data bytes
64 bytes from 2400:400d:100::3c20:55dc: icmp_seq=1 ttl=54 time=8.84 ms
64 bytes from 2400:400d:100::3c20:55dc: icmp_seq=2 ttl=54 time=6.58 ms
64 bytes from 2400:400d:100::3c20:55dc: icmp_seq=3 ttl=54 time=6.46 ms

--- 2400:400d:100::3c20:55dc ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2001ms
rtt min/avg/max/mdev = 6.465/7.298/8.843/1.097 ms

chiyoda:~ $ tcpspray -n 10000 2400:400d:100::3c20:55dc
Transmitted 10240000 bytes in 0.844327 seconds (11843.752 kbytes/s)

chiyoda:~ $ ping -c 3 60.32.85.216
PING 60.32.85.216 (60.32.85.216) 56(84) bytes of data.
64 bytes from 60.32.85.216: icmp_req=1 ttl=53 time=6.62 ms
64 bytes from 60.32.85.216: icmp_req=2 ttl=53 time=6.64 ms
64 bytes from 60.32.85.216: icmp_req=3 ttl=53 time=6.95 ms

--- 60.32.85.216 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 1999ms
rtt min/avg/max/mdev = 6.623/6.740/6.955/0.152 ms

chiyoda:~ $ tcpspray -n 10000 60.32.85.216
Transmitted 10240000 bytes in 0.842140 seconds (11874.510 kbytes/s)
</pre>
<p>
経路は、
それぞれ以下のような感じ:
</p>
<p>
transix IPv6 IPoE:
</p>
<pre class="terminal">
chiyoda:~ $ tracepath6 2409:82:5fff::3c20:55dc
 1?: [LOCALHOST]                        0.016ms pmtu 1500
 1:  2001:2e8:634:0:2:2:0:1                                0.054ms 
 1:  2001:2e8:634:0:2:2:0:1                                0.038ms 
 2:  2001:2e8:22:202::2                                    1.192ms asymm  4 
 3:  2001:2e8:20::22:11                                    1.466ms asymm  5 
 4:  2001:7fa:7:1::2497:1                                 53.299ms asymm  6 
 5:  tky008bf01.IIJ.Net                                    3.417ms asymm  6 
 6:  tky009bb10.IIJ.Net                                    2.622ms asymm  8 
 7:  tky009ip50.IIJ.Net                                    2.763ms asymm  8 
 8:  2001:240:bb5c:1008::cafe                              3.188ms asymm  9 
 9:  2404:8e00:feed:101::2                                 3.911ms asymm 10 
10:  no reply
11:  no reply
12:  no reply
13:  no reply
14:  no reply
15:  2409:82:5fff::3c20:55dc                               8.107ms reached
     Resume: pmtu 1500 hops 15 back 49 
</pre>
<p>
OCN IPv6 PPPoE:
</p>
<pre class="terminal">
chiyoda:~ $ tracepath6 2400:400d:100::3c20:55dc
 1?: [LOCALHOST]                        0.019ms pmtu 1500
 1:  2001:2e8:634:0:2:2:0:1                                0.058ms 
 1:  2001:2e8:634:0:2:2:0:1                                0.037ms 
 2:  2001:2e8:22:202::2                                    2.505ms asymm  4 
 3:  2001:2e8:20::22:11                                    2.464ms asymm  5 
 4:  2001:380:0:2516::1                                    3.111ms asymm  6 
 5:  2001:380:8280:f::1                                   19.584ms asymm  7 
 6:  2001:380:8150:f::12                                   3.486ms asymm  8 
 7:  2001:380:8270:7::2                                    5.817ms asymm  8 
 8:  2001:380:4d:100::2                                    4.504ms asymm  9 
 9:  2001:380:4d:181::2                                   14.276ms asymm 10 
10:  no reply
11:  2001:380:4d:181::2                                    7.015ms pmtu 1454
11:  senri.v6.gcd.org                                      7.457ms reached
     Resume: pmtu 1454 hops 11 back 54 
</pre>
<p>
OCN IPv4 PPPoE:
</p>
<pre class="terminal">
chiyoda:~ $ tracepath 60.32.85.216
 1:  v-183-181-54-38.ub-freebit.net                        0.117ms pmtu 1500
 1:  v-183-181-55-247.ub-freebit.net                       0.040ms 
 1:  v-183-181-55-247.ub-freebit.net                       0.022ms 
 2:  202.216.248.129                                       0.515ms asymm  3 
 3:  no reply
 4:  oi-gate-1.otemachi4.dti.ad.jp                         1.899ms asymm  6 
 5:  122.28.177.109                                        2.830ms asymm  7 
 6:  118.23.146.121                                        8.064ms asymm  8 
 7:  118.23.168.8                                          3.123ms asymm  9 
 8:  60.37.55.154                                          5.095ms asymm  9 
 9:  122.1.173.238                                         4.176ms asymm 10 
10:  118.23.5.74                                           5.482ms asymm 12 
11:  no reply
12:  118.23.8.9                                            5.328ms pmtu 1454
12:  gcd.org                                               7.036ms reached
     Resume: pmtu 1454 hops 12 back 53 
</pre>

<p>
「国際区間で遅延が大きめなのは、
OCNから fremont.gcd.org への帰りのパケットが香港経由になってるため」
というコメントを頂いたので、
返りの経路も調べてみた。
確かに、
hkix.net 経由になっていて、
東京-香港間に 50ms ほどかかっている:
</p>
<pre class="terminal-scroll">
senri:/ # traceroute6 -s 2400:400d:100::3c20:55dc fremont.gcd.org
traceroute to fremont.gcd.org (2600:3c01::f03c:91ff:fe96:f285) from 2400:400d:100::3c20:55dc, 30 hops max, 24 byte packets
 1  2001:380:4d:1ff::3 (2001:380:4d:1ff::3)  4.876 ms  3.907 ms  4.369 ms
 2  2001:380:4d:181::1 (2001:380:4d:181::1)  3.104 ms  2.888 ms  3.556 ms
 3  2001:380:4d:100::1 (2001:380:4d:100::1)  5.911 ms  6.002 ms  5.581 ms
 4  2001:380:8270:7::1 (2001:380:8270:7::1)  4.072 ms  4.156 ms  3.969 ms
 5  2001:380:8150:f::18 (2001:380:8150:f::18)  4.622 ms  4.689 ms  4.584 ms
 6  ae-5.r20.tokyjp01.jp.bb.gin.ntt.net (2001:218:0:5000::d)  4.54 ms  4.172 ms  4.577 ms
 7  ae-2.r25.tokyjp01.jp.bb.gin.ntt.net (2001:218:0:2000::1c6)  5.063 ms  4.27 ms  4.511 ms
 8  as-3.r21.newthk02.hk.bb.gin.ntt.net (2001:218:0:2000::13e)  56.208 ms  56.149 ms  55.959 ms
 9  xe-2-1.r01.newthk01.hk.bb.gin.ntt.net (2001:218:0:2000::159)  101.451 ms  57.473 ms  57.487 ms
10  ae-3.a02.newthk01.hk.ra.gin.ntt.net (2001:218:0:6000::156)  56.489 ms  56.368 ms  107.274 ms
11  hurricaneelectric-RGE.hkix.net (2001:7fa:0:1::ca28:a19e)  57.228 ms  57.492 ms  57.619 ms
12  gige-g3-7.core1.lax1.he.net (2001:470:0:16b::1)  174.14 ms  173.967 ms  174.26 ms
13  10gigabitethernet7-4.core1.fmt2.he.net (2001:470:0:18d::1)  180.178 ms  188.238 ms  181.149 ms
14  gige-g4-18.core1.fmt1.he.net (2001:470:0:2d::1)  173.357 ms  173.099 ms  173.85 ms
15  2001:470:1:1db::2 (2001:470:1:1db::2)  173.973 ms  173.424 ms  178.249 ms
16  2600:3c01::f03c:91ff:fe96:f285 (2600:3c01::f03c:91ff:fe96:f285)  174.287 ms  174.162 ms  174.175 ms
</pre>
<p>
8月24日追記:
</p>
<p>
「fremont.gcd.org と senri.gcd.org 間のIPv6の遅延は改善されたんじゃないか」
というコメントを頂いたので、
再度調べてみた:
</p>
<pre class="terminal-scroll">
senri:/ # traceroute6 -s 2400:400d:100::3c20:55dc fremont.gcd.org
traceroute to fremont.gcd.org (2600:3c01::f03c:91ff:fe96:f285) from 2400:400d:100::3c20:55dc, 30 hops max, 24 byte packets
 1  asao.v6.gcd.org (2400:400d:100::3c20:55dd)  0.239 ms  0.152 ms  0.14 ms
 2  2001:380:4d:1ff::3 (2001:380:4d:1ff::3)  4.61 ms  4.696 ms  3.957 ms
 3  2001:380:4d:181::1 (2001:380:4d:181::1)  3.445 ms  3.73 ms  3.347 ms
 4  2001:380:4d:100::1 (2001:380:4d:100::1)  5.994 ms  5.893 ms  5.813 ms
 5  2001:380:8270:7::1 (2001:380:8270:7::1)  3.727 ms  3.58 ms  3.82 ms
 6  2001:380:8150:f::18 (2001:380:8150:f::18)  4.51 ms  4.119 ms  4.769 ms
 7  ae-5.r20.tokyjp01.jp.bb.gin.ntt.net (2001:218:0:5000::d)  4.353 ms  4.446 ms  4.526 ms
 8  ae-3.r20.osakjp01.jp.bb.gin.ntt.net (2001:218:0:2000::da)  14.744 ms  14.429 ms  14.338 ms
 9  as-2.r20.snjsca04.us.bb.gin.ntt.net (2001:218:0:2000::7d)  122.714 ms  122.792 ms  122.84 ms
10  ae-0.r21.snjsca04.us.bb.gin.ntt.net (2001:418:0:2000::66)  130.233 ms  130.342 ms  176.712 ms
11  10gigabitethernet2-3.core1.sjc2.he.net (2001:504:0:1::6939:1)  132.712 ms  122.997 ms  122.804 ms
12  10gigabitethernet1-1.core1.fmt1.he.net (2001:470:0:2f::1)  132.042 ms  141.087 ms  132.982 ms
13  2001:470:1:1db::2 (2001:470:1:1db::2)  124.032 ms  124.21 ms  124.141 ms
14  2600:3c01::f03c:91ff:fe96:f285 (2600:3c01::f03c:91ff:fe96:f285)  125.249 ms  124.642 ms  125.253 ms
</pre>
<p>
確かに、
ntt.net から直接 he.net へ行く経路に変わっていて、
香港に迂回していた時と比べ、
50ms ほど速くなっている。
1hop目が asao になっているのは、
asao と senri で冗長構成になっていて、
前回は senri が master だったが現在は asao が master に切り替わっているため。
</p>]]></content:encoded>
			<wfw:commentRss>http://www.gcd.org/blog/2011/07/820/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>フレッツ 光ネクストの IPv6 PPPoE 接続を OCN 光アクセスで使ってみた</title>
		<link>http://www.gcd.org/blog/2011/06/812/</link>
		<comments>http://www.gcd.org/blog/2011/06/812/#comments</comments>
		<pubDate>Mon, 20 Jun 2011 00:08:04 +0000</pubDate>
		<dc:creator>hiroaki_sengoku</dc:creator>
				<category><![CDATA[IPv6]]></category>
		<category><![CDATA[システム構築・運用]]></category>

		<guid isPermaLink="false">http://www.gcd.org/blog/?p=812</guid>
		<description><![CDATA[6月1日から NTT東日本のフレッツ 光ネクストにおいて IPv6 PPPoE 接続の提供が始まった。 私は OCN光アクセスを契約しているが、 幸い OCN (NTTコミュニケーションズ) も、 NTT東日本に合わせて [...]]]></description>
			<content:encoded><![CDATA[<p>
6月1日から NTT東日本の<a href="http://flets.com/next/">フレッツ 光ネクスト</a>において
<a href="http://www.ntt-east.co.jp/release/1105/110526c.html">IPv6 PPPoE 接続の提供が始まった</a>。
私は <a href="http://www.gcd.org/blog/2009/11/180/">OCN光アクセスを契約している</a>が、
幸い OCN (NTTコミュニケーションズ) も、
NTT東日本に合わせて<a href="http://www.ntt.com/release/monthNEWS/detail/20110526.html">順次対応を開始</a>ということなので、
さっそく OCN へ電話で問合わせてみたら、
申込書をメールで送るので記入押印の上 FAX で送り返して欲しい、とのこと。
</p>
<p>
いまどき Web で申し込めないなんて、
と思いつつ 8ページにもわたる申込書
(いつも感じるが OCN の申込書は無駄にページ数が多い *_*)
を FAX で送付。
すると翌日電話がかかってきて、
開通日は 10日後などとおっしゃる。
それじゃ 
<a href="https://twitter.com/gcd_org/status/78613974916153344">World IPv6 Day</a>
に間に合わないじゃんと思ったが、
どんな変更でも申込みから 7営業日は最低でもかかるらしいので仕方がない。
なお、
工事費および月額使用料は無料。
</p>
<p>
OCN には元々月額 315円の 
「<a href="http://www.ocn.ne.jp/ipv6/service/index.html">OCN IPv6</a>」
というサービスがあるが、
OCN IPv6 はフレッツ網に PPPoE によるトンネルを張って 
IPv4 を通し (OCN フレッツ光)、
その IPv4 上に L2TP (Layer 2 Tunneling Protocol) によるトンネルを張って
PPP セッションを通し、
その PPP 上に IPv6 を通すという屋上屋を架す方式だったのに対し、
6月1日から始まった
「IPv6インターネット接続」
はフレッツ網に PPPoE によるトンネルを張って IPv6 を通す方式。
</p>
<p>
つまり OCN フレッツ光の IPv4 の部分を 
IPv6 でそのまま置き換えたシンプルな方式。
もちろんフレッツ網に IPv6 を直接通す
「ネイティブ方式」
が一番シンプルだが、
ネイティブ方式に関しては
「平成23年7月を目途に提供を予定」
ということなので、
どのようなサービスが始まるのか今のところ不明
(もう来週には 7月が始まってしまうのだが)。
7/24追記: <a href="http://www.gcd.org/blog/2011/07/820/">ネイティブ方式サービスが始まった！</a>
</p>
<p>
開通日の 2日前に郵便で届いた
「ご利用内容のご案内」
の欄外の注釈に、
</p>
<blockquote>
IPv6 でインターネットに接続する際、
認証ID の @ 右側を
&ldquo;@bizf.ocn.ne.jp&rdquo;
の場合は
&ldquo;@bizf6.ocn.ne.jp&rdquo;
に、
&ldquo;@bizd.ocn.ne.jp&rdquo;
の場合は
&ldquo;@bizd6.ocn.ne.jp&rdquo;
に変更してご利用下さい。
</blockquote>
<p>
と書いてあった。
IPv6 での接続に関する説明はこの部分だけなので、
あとは推測するしかない
(サポートに接続方法を聞いても、
単に <a href="http://www.ntt-east.co.jp/release/1105/110526b.html">IPv6トンネル対応ルータ</a>を購入してくれと言われる)。
</p>
<p>
とりあえず、
ふだん IPv4 で接続するときに使ってる PPPoE スクリプト
(<a href="http://www.roaringpenguin.com/products/pppoe">RP-PPPoE</a>)
を、
認証ID を &ldquo;xxxx@bizf.ocn.ne.jp&rdquo; から 
&ldquo;xxxx@bizf6.ocn.ne.jp&rdquo;
に変更して走らせてみる:
</p>
<pre class="terminal-scroll">
20:39:13 senri pppd[16587]: Plugin /etc/ppp/plugins/rp-pppoe.so loaded.
20:39:13 senri pppd[16587]: RP-PPPoE plugin version 3.10 compiled against pppd 2.4.5
20:39:13 senri pppd[16587]: pppd 2.4.5 started by root, uid 0
20:39:13 senri pppd[16587]: PPP session is 6394 (0x18fa)
20:39:13 senri pppd[16587]: Connected to 00:1e:13:c2:69:c2 via interface eth1
20:39:13 senri pppd[16587]: Using interface ppp0
20:39:13 senri pppd[16587]: Connect: ppp0 <--> eth1
20:39:13 senri pppd[16587]: Couldn't increase MTU to 1500
20:39:13 senri pppd[16587]: Couldn't increase MRU to 1500
20:39:13 senri pppd[16587]: PAP authentication succeeded
20:39:13 senri pppd[16587]: peer from calling number 00:1E:13:C2:69:C2 authorized
20:39:13 senri pppd[16587]: local  LL address <span style="color:green">fe80::fd61:ff9b:eb97:1f93</span>
20:39:13 senri pppd[16587]: remote LL address fe80::0090:1a00:41a3:d3f3
</pre>
<p>
PPP は 1 つ以上のネットワーク層プロトコルを選択できるので、
IPCP (IP Control Protocol) と IPv6CP (IPv6 Control Protocol) の両方が流れてくるのかと予想したのだが、
流れてきたのは IPv6CP のみだった。
つまり &ldquo;@bizf.ocn.ne.jp&rdquo; で IPv4 用、
&ldquo;@bizf6.ocn.ne.jp&rdquo; で IPv6 用、
計 2本の PPPoE セッションを張ることになる。
</p>
<p>
上記ログから分かる通り
Link Local とはいえ IPv6 なアドレス <span style="color:green">fe80::fd61:ff9b:eb97:1f93</span>
が割り振られたのだから、
IPv6 で通信できるはず。
試しに PPP の対向サーバへ ping を打ってみると、
ちゃんと応答が返ってきた:
</p>
<pre class="terminal">
senri:~ $ ping6 -c 3 fe80::0090:1a00:41a3:d3f3%ppp0<span style="color:red">↓</span>
PING fe80::90:1a00:41a3:d3f3%ppp0 (fe80::90:1a00:41a3:d3f3%ppp0): 48 data bytes
56 bytes from fe80::90:1a00:41a3:d3f3%ppp0: icmp_seq=0 ttl=255 time=3.936 ms
56 bytes from fe80::90:1a00:41a3:d3f3%ppp0: icmp_seq=1 ttl=255 time=4.050 ms
56 bytes from fe80::90:1a00:41a3:d3f3%ppp0: icmp_seq=2 ttl=255 time=4.176 ms
--- fe80::0090:1a00:41a3:d3f3%ppp0 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max/stddev = 3.936/4.054/4.176/0.098 ms
senri:~ $ 
</pre>
<p>
じゃ、
Global なアドレス
(固定アドレス契約なのでプレフィックスが
「ご利用内容のご案内」
に書かれていた)
を付けて routing 設定を行なえば Global に通信できそうと思い、
試してみると...
</p>
<pre class="terminal">
senri:/ # ifconfig eth0 add 2400:400d:100::1/56<span style="color:red">↓</span>
senri:/ # ip -6 route add default via fe80::0090:1a00:41a3:d3f3 dev ppp0<span style="color:red">↓</span>
senri:/ # ping6 www.kame.net<span style="color:red">↓</span>
PING www.kame.net (2001:200:dff:fff1:216:3eff:feb1:44d7): 48 data bytes
<span style="color:red">^C</span>--- www.kame.net ping statistics ---
15 packets transmitted, 0 packets received, 100% packet loss
senri:/ # 
</pre>
<p>
う〜ん、ダメか。
tcpdump を使って ppp0 に届く IPv6 パケットを監視してみたが、
OCN へ送信したパケットのみが表示され、
OCN 側からは何のパケットも届かない。
</p>
<p>
しかも、
<a href="http://fremont.gcd.org/test">他のサイト</a>から 
2400:400d:100::1 に対して ping6 を打ってみても何も届かない。
仮にこちらの設定に何か間違いがあったとしても、
OCN 側で 2400:400d:100::1 宛のパケットを routing していれば、
パケット自体は流れてきそうな気がするのだが...
少なくとも IPv4 の場合なら、
こちらの IP アドレス設定が間違っていても、
受け取れないだけでパケット自体は流れてくる。
</p>
<p>
ひょっとして、
「ご利用内容のご案内」に書かれていた
「2400:400d:100::」
というプレフィックスが間違っているんじゃ? と、
途方に暮れる。
</p>
<span id="more-812"></span>
<p>
仕方がないので
「<a href="http://www.ntt-east.co.jp/info-st/mutial/ngn/index.html">次世代ネットワークに関する情報</a>」
で提供されている仕様書にざっと目を通してみる。
すると、
<a href="http://www.ntt-east.co.jp/info-st/mutial/ngn/110601tunnel_uni.pdf">NGN IPv6 ISP接続＜トンネル方式＞UNI仕様書</a>の 7ページに、
IPv6 通信開始までの通信シーケンス図があった:
</p>
<a href="http://www.ntt-east.co.jp/info-st/mutial/ngn/110601tunnel_uni.pdf#page=7"><img src="http://www.gcd.org/sengoku/picts/IPv6_sequence.png" width="510" height="540" alt="IPv6 sequence diagram" /></a>
<p>
現在は IPv6CP まで完了している段階だから、
次は DHCPv6-PD Prefix 付与フェーズということになる。
この時まで、
DHCP (Dynamic Host Configuration Protocol) は自動設定のための仕掛けだから、
固定プレフィックスの場合は PD (Prefix Delegation, プレフィックス委譲) 
してもらうまでもないと思い込んでいた。
少なくとも IPv4 の場合は、
DHCP クライアントを動かさずに勝手に IP アドレスを割当てても通信できる。
</p>
<p>
OCN 側から一切パケットが流れてこないということは、
プレフィックス委譲してもらわなければ通信できない、
ということになる。
なぜ OCN は、
そんな不便な仕様にしているのか?
と疑問に思いつつも、
<a href="http://sourceforge.net/projects/wide-dhcpv6/">WIDE-DHCPv6</a>
をインストールして dhcp6c (DHCPv6 クライアント) を実行してみる:
</p>
<pre class="terminal">
senri:/ # cat /tmp/dhcp6c.conf<span style="color:red">↓</span>
interface ppp0 {
	send ia-pd 0;
};
id-assoc pd 0{
	prefix-interface eth0 {
		sla-len 0;
	};
};
senri:/ # dhcp6c -c /tmp/dhcp6c.conf ppp0<span style="color:red">↓</span>
</pre>
<p>
「send ia-pd 0」
が solicit message (要請メッセージ) を 
OCN のルータ (上記シーケンス図では 「IP通信網」) へ送信するための設定。
「ia-pd」
というのは Identity Association for Prefix Delegation 
(プレフィックス委譲ID) の意味で、
複数の委譲を行ないたいときにそれぞれを区別するための ID らしいが、
今回は一つだけなのでデフォルトの 0 を指定。
</p>
<p>
「id-assoc pd 0」
がプレフィックス委譲ID が 0 のもの (今回は一つだけなので 0 しかない) 
に関する設定で、
「prefix-interface eth0」
と指定することによって、
OCN から委譲されたプレフィックスを 
eth0 インタフェースに割当てる。
</p>
<p>
dhcp6c を実行しつつ tcpdump で ppp0 での通信を監視してみると:
</p>
<pre class="terminal-scroll">
senri:/ # tcpdump -i ppp0<span style="color:red">↓</span>
tcpdump: WARNING: ppp0: no IPv4 address assigned
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ppp0, link-type LINUX_SLL (Linux cooked), capture size 65535 bytes
23:38:43.826300 IP6 <span style="color:green">fe80::fd61:ff9b:eb97:1f93</span>.546 > ff02::1:2.547: dhcp6 solicit
23:38:43.831744 IP6 fe80::90:1a00:41a3:d3f3.547 > <span style="color:green">fe80::fd61:ff9b:eb97:1f93</span>.546: dhcp6 advertise
23:38:44.871958 IP6 <span style="color:green">fe80::fd61:ff9b:eb97:1f93</span>.546 > ff02::1:2.547: dhcp6 solicit
23:38:44.876597 IP6 fe80::90:1a00:41a3:d3f3.547 > <span style="color:green">fe80::fd61:ff9b:eb97:1f93</span>.546: dhcp6 advertise
</pre>
<p>
無事、
solicit message が OCN へ送られ、
シーケンス図通り OCN から advertise が返ってきていることが分かる。
IPv6 のアドレスは桁数が多くて目がチラチラする (^^; ので、
こちら側
(シーケンス図では 「端末機器」) のアドレス 
<span style="color:green">fe80::fd61:ff9b:eb97:1f93</span> 
を<span style="color:green">緑色</span>で表した。
</p>
<p>
シーケンス図によると advertise を受け取った後、
端末機器は Request を送らなければならないのだが、
なぜか 1秒待って solicit を再送している。
これが今回唯一のハマったところ。
原因を探るために DHCPv6 の仕組みを一通り調べる羽目になった。
</p>
<p>
原因は分かってみれば単純で、
単に ip6tables で advertise パケットを落とす設定になっていただけ。
そのため dhcp6c が advertise パケットを受け取れず、
solicit の再送を繰り返していた。
Link Local からの UDP 546番ポート宛のパケットを受け入れるよう設定したら、
無事 DHCPv6-PD のシーケンスも完了して IPv6 通信を開始することができた。
</p>
<p>
より正確に言えば、元々
「-m conntrack --ctstate ESTABLISHED,RELATED」
などと送信パケットと関連があるパケットは受け入れる設定にしていたが、
DHCPv6 の solicit は ff02::1:2 宛、
つまり全ルーターアドレス宛のマルチキャストであるのに対し、
OCN から返ってくる advertise は (当然) ユニキャストであるため、
関連があるパケットとは見なされず落としてしまっていた。
</p>
<p>
以下のような ipv6-up / ipv6-down スクリプト
(IPv6 接続/切断時に 
<a href="http://ppp.samba.org/ppp/download.html">pppd</a> が呼び出すスクリプト)
を書いて、
dhcp6c および <a href="http://www.litech.org/radvd/">radvd</a> が自動的に起動/終了するようにした。
</p>
<pre class="code">
#!/bin/sh
PATH=/usr/bin:/usr/sbin:/bin:/sbin
. /etc/rc.d/hostname
command=$0
interface=$1
device=$2
speed=$3
local=$4
remote=$5
ipparam=$6
echo `date "+%F %T"` "$0" "$@" &gt;&gt; /var/log/pppd-ip6.log
case $command in
    *ipv6-up)
	updown="up"
	cat &gt; /var/run/dhcp6c.$interface.conf &lt;&lt;EOF
interface $interface {
	send ia-pd 0;
};
id-assoc pd 0{
	prefix-interface $INNER_DEV {
		sla-len 0;
	};
};
EOF
	dhcp6c -c /var/run/dhcp6c.$interface.conf -p /var/run/dhcp6c.$interface.pid $interface
	;;
    *ipv6-down)
	updown="down"
	if [ -f /var/run/dhcp6c.$interface.pid ]; then
	    kill `cat /var/run/dhcp6c.$interface.pid`
	fi
	;;
    *)
	exit 1
esac
case $ipparam in
    ngn6)
	if [ $updown = "up" ]; then
	    ip -6 addr add 2400:400d:100::1 dev $INNER_DEV
	    ip -6 route add default via $remote dev $interface
	    radvd -C /usr/etc/radvd.conf
	else
	    ip -6 addr del 2400:400d:100::1 dev $INNER_DEV
	    if [ -f /var/run/radvd.pid ]; then
		kill `cat /var/run/radvd.pid`
	    fi
	fi
	;;
    *)
	exit 1
esac
</pre>
<p>
dhcp6c によって自動的に割当てられる IPv6 アドレスの他に、
対外サービス用として
<a href="http://[2400:400d:100::1]/test">2400:400d:100::1</a>
も割当てるようにしている。
</p>]]></content:encoded>
			<wfw:commentRss>http://www.gcd.org/blog/2011/06/812/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Android 端末上で透過型プロキシを動かしてみる 〜 VPN のように使えて、しかも省電力</title>
		<link>http://www.gcd.org/blog/2011/06/806/</link>
		<comments>http://www.gcd.org/blog/2011/06/806/#comments</comments>
		<pubDate>Thu, 02 Jun 2011 00:41:20 +0000</pubDate>
		<dc:creator>hiroaki_sengoku</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[stone 開発日記]]></category>

		<guid isPermaLink="false">http://www.gcd.org/blog/?p=806</guid>
		<description><![CDATA[透過型プロキシ (Transparent Proxy) というのは、 ブラウザから 「見えない」 プロキシのこと。 ブラウザ自身は WWW サーバにアクセスしているつもりなのに、 ブラウザが送信したリクエストをプロキシが [...]]]></description>
			<content:encoded><![CDATA[<p>
透過型プロキシ (Transparent Proxy) というのは、
ブラウザから 「見えない」 プロキシのこと。
ブラウザ自身は WWW サーバにアクセスしているつもりなのに、
ブラウザが送信したリクエストをプロキシが横取りし、
プロキシから出し直す。
サーバからのレスポンスは当然プロキシに返り、
プロキシがそれをブラウザに送信するのだけど、
パケットがブラウザに届くまでの間に送信元アドレスが書き換えられて、
サーバから直接レスポンスが届いたようにブラウザからは見える。
</p>
<p>
フツーの 「見える」 プロキシは、
ブラウザ等でプロキシ設定が必要であるのに対し、
透過型プロキシだと設定が不要。
だから一部の ISP (インターネット接続プロバイダ) などで、
フツーのプロキシの代りに使われていたりする
(ユーザにプロキシ設定の方法を説明する必要がなくてサポートコストが削減できる)。
あるいは企業等で、
従業員が仕事と関係ない Web ページを閲覧していないか監視するために、
社内から社外へ接続するゲートウェイ等に透過型プロキシを設置して、
社外への http アクセスを記録していたりする
(監視だけならパケットをダンプするだけでも用が足りるが、
アクセス先のサイト毎に細かな制御を行なおうとすると、
プロキシを使った方が楽)。
</p>
<p>
このように、
透過型プロキシはその存在を隠すために使われることが多いが、
ブラウザにプロキシ設定の機能が無い場合は、
透過型プロキシを使わざるを得ない。
例えば、
Android 端末で使われるブラウザの多くが、
なぜかプロキシ設定の機能を持っていない。
プロキシ経由でアクセスされると、
モバイル端末からのアクセスなのか、
フツーの PC からのアクセスなのか、
区別がつかなくなってしまうので、
あえてプロキシ設定できないようにしているのかも知れないが、
プロキシを使わないとアクセスできない場合は困ってしまう。
</p>
<p>
私の場合、
勤務先の LAN 内のサーバに社外からアクセスするとき、
社内アクセス専用のプロキシ 
(ここでは仮にホスト名を proxy.klab.org とする) を利用している。
例えば <a href="http://senri.gcd.org/test">senri.gcd.org</a> 
(自宅のサーバ、つまり社外) からこのプロキシをアクセスすると、
こんな感じ:
</p>
<pre class="terminal-scroll">
senri:~ $ openssl s_client -connect proxy.klab.org:443 -cert cert.pem -key key.pem -CApath /usr/ssl/certs -quiet<span style="color:red">↓</span>
Enter pass phrase for key.pem:xxxxxxxx<span style="color:red">↓</span>

depth=1 /C=US/O=Equifax/OU=Equifax Secure Certificate Authority
verify return:1
depth=0 /serialNumber=-cn4oMJtlqoqfQZaTat68U68dNVbM8iQ/C=JP/O=*.klab.org/OU=GT41256819/OU=See www.rapidssl.com/resources/cps (c)09/OU=Domain Control Validated - RapidSSL(R)/CN=*.klab.org
verify return:1
CONNECT irc.klab.org:6667 HTTP/1.1<span style="color:red">↓</span>
<span style="color:red">↓</span>
HTTP/1.0 200 OK

:irc.klab.org NOTICE AUTH :*** Looking up your hostname...
:irc.klab.org NOTICE AUTH :*** Found your hostname
</pre>
<p>
行末に 
「<span style="color:red">↓</span>」
がある行が入力行。
「<span style="color:red">↓</span>」
は Enter キー押下。
秘密鍵 key.pem でクライアント認証を受けて proxy.klab.org
に接続し、
CONNECT リクエストを送信することにより、
社内の任意のサーバ:ポートに接続できる。
上記の例では<a href="http://www.gcd.org/blog/2006/12/382/">社内 IRC サーバ</a>である 
irc.klab.org:6667 に接続しているが、
もちろん社内の任意の WWW サーバにも接続できる。
</p>
<blockquote>
説明を簡単にするため proxy.klab.org と書いたが、
実際には <a href="http://www.gcd.org/blog/2006/05/359/">VPN Warp</a> を使っている
(だから proxy.klab.org というサーバは存在しない)。
VPN Warp も stone で接続することができるので、
以下の説明は VPN Warp の場合もほとんど同様に適用することができる。
</blockquote>
<p>
プロキシというと、
ファイアウォールの内側から外部のインターネットをアクセスするために用いるものと思っている人が多いせいか、
外からファイアウォールの内側をアクセスするためのプロキシは、
特にリバースプロキシ (reverse proxy) と呼ばれることもある。
</p>
<p>
proxy.klab.org を透過型プロキシとして利用できれば、
社内の任意のサーバに透過的にアクセスできるようになる。
例えばこんな感じ:
</p>
<pre class="terminal">
senri:~ $ adb shell<span style="color:red">↓</span>
$ getprop ro.build.description<span style="color:red">↓</span>
soju-user 2.3.4 GRJ22 121341 release-keys
$ su<span style="color:red">↓</span>
# busybox traceroute irc.klab.org<span style="color:red">↓</span>
traceroute to irc.klab.org (10.10.0.18), 30 hops max, 38 byte packets
 1  110.158.20.29 (110.158.20.29)  701.203 ms  90.517 ms  85.570 ms
 2  *  *  *
 3  *  *  *
 4  110.158.18.138 (110.158.18.138)  79.540 ms !A  *  *
 5  *  *  *
 6  *  <span style="color:red">^C</span>
senri:~ $ adb shell<span style="color:red">↓</span>
$ telnet irc.klab.org 6667<span style="color:red">↓</span>
:irc.klab.org NOTICE AUTH :*** Looking up your hostname...
:irc.klab.org NOTICE AUTH :*** Found your hostname
</pre>
<p>
「<a href="http://en.wikipedia.org/wiki/Soju">soju</a>-user 2.3.4 GRJ22」
つまり Android 2.3.4 な 
<a href="http://www.gcd.org/blog/2011/03/777/">Nexus S</a> で、
パケットが届かないはずの irc.klab.org (10.10.0.18) に対して、
telnet でアクセスできている。
telnet でアクセスできるということは、
もちろん任意の <a href="https://market.android.com/details?id=net.andchat">IRC アプリ</a>で
irc.klab.org にアクセスできるということ。
</p>
<p>
VPN (Virtual Private Network) でも同じことができる!
という声が聞こえてきそうだが、
VPN だと TCP でデータを送受信していないときも、 
VPN セッションを張っているだけでいろんなパケット 
(例えば ARP) が行き交って、
そのたびに電波が飛んで電池を消耗するので、
あまりモバイル向きではないと思う。
</p>
<p>
あるいは、
<a href="https://market.android.com/details?id=org.connectbot">ConnectBot</a> 
などを使って ssh で port forward を行なう方法もあるが、
これまた ssh セッションを張りっぱなしだと電池消耗が心配だし、
かといって IRC を使う前に毎回 ssh 接続を行なうのはメンドクサイ。
また、
通信先/宛先ポートが増えるたび port foward 設定を追加するのもメンドクサイ。
</p>
<p>
その点、
透過型プロキシだと実際にパケットが飛ぶときのみ通信が行なわれるので、
電池消耗をあまり心配せずに TCP セッションを張りっぱなしにできる。
また、
LAN 内の通信先/宛先ポートが増えても設定変更は不要。
モバイルで LAN 内にアクセスする方法として最適だと思う
(便利なのに普及していないのはナゼ?)。
</p>
<span id="more-806"></span>
<p>
前述したように、
透過型プロキシでは、
クライアントが送信した往路パケットの宛先を書き換えてプロキシへ送り込む必要がある。
これは、
Linux (もちろん Android を含む) だと 
iptables コマンドを使えば簡単に実現できる:
</p>
<pre class="terminal">
senri:~ $ adb shell<span style="color:red">↓</span>
$ su<span style="color:red">↓</span>
# iptables -t nat -p tcp -A OUTPUT -j REDIRECT -d 10.10.0.0/24 --to-port 9980<span style="color:red">↓</span>
getsockopt for multiport failed strangely: No such file or directory
getsockopt for multiport failed strangely: No such file or directory
FIX ME! implement getprotobyname() bionic/libc/bionic/stubs.c:378
# 
</pre>
<p>
これで 10.10.0.* (LAN 内の IP アドレス) 宛の 
TCP パケットが宛先を書き換えられて、
外部に送信されることなく端末自身の 9980番ポートに届く。
ただし端末によっては
CONFIG_NF_NAT を有効にしていないカーネルを使っている場合があり
(froyo 以前の端末は大半が該当するかも?)、
上記 iptables コマンドを実行すると
「can't initialize iptables table `nat': Table does not exist (do you need to insmod?)」
などのエラーメッセージが出てしまう。
その場合は、
CONFIG_NF_NAT を有効にしてカーネルを再構築すればよい
(Linux カーネルは GPL なので再構築に必要なソースは入手できるはず)。
</p>
<blockquote>
上記の実行例では
「getsockopt for multiport failed strangely: No such file or directory」
というエラーメッセージが出ているが、
これはカーネルに xt_multiport モジュールが組み込まれていないにもかかわらず、
iptables コマンドには multiport 拡張が組み込まれていて、
iptables コマンド実行時に multiport 拡張のバージョンをチェックしようと
getsockopt で IPT_SO_GET_REVISION_MATCH オプションの値を得ようとするため。
カーネルの xt_find_revision (net/netfilter/x_tables.c) が
xt_multiport モジュールを見つけられず、
ENOENT (No such file or directory) を返すため、
このようなエラーメッセージが表示される。
上記の例では multiport 拡張を使っていないので、
このエラーは無視して構わない。
<br />
また、
「FIX ME! implement getprotobyname()」
というエラーメッセージも出ているが、
これは
Android の libc である bionic において
<a href="http://linux.die.net/man/3/getprotobyname">getprotobyname(3)</a> がまだ実装されておらず、
現時点では常に NULL を返している、
という意味。
iptables コマンドはプロトコル名 (例えば 「tcp」) 
からプロトコル番号 (tcp の場合なら 6) への変換テーブルを自前で持っているので、
getprotobyname(3) が NULL を返しても問題無い。
</blockquote>
<p>
あとは 9980番ポートに届いたパケットを、
proxy.klab.org へ転送してやればよい。
ただし、
社内アクセス専用プロキシ
proxy.klab.org を利用するには、
前述したように
(1) SSL クライアント認証を受けることが必要。
さらに、
クライアント (上記の例だと telnet コマンドや IRC アプリ)
がどこへ接続しようとしていたかを調べ、
proxy.klab.org へ
(2) CONNECT メソッドを使って接続先を伝える必要がある
(上記の例だと、
「CONNECT irc.klab.org:6667 HTTP/1.1」
を送信)。
</p>
<p>
まず (1) は<a href="http://www.gcd.org/sengoku/stone/Welcome.ja.html">拙作 stone</a> 
を使うと簡単に実現できる:
</p>
<pre class="terminal-scroll">
senri:~ $ adb shell<span style="color:red">↓</span>
$ cd /data/local/tmp<span style="color:red">↓</span>
$ stone -l -q cert=cert.pem -q key=key.pem -q passfile=key.passwd proxy.klab.org:443/ssl localhost:8080 &amp;<span style="color:red">↓</span>
$ telnet localhost 8080<span style="color:red">↓</span>
CONNECT irc.klab.org:6667 HTTP/1.1<span style="color:red">↓</span>
<span style="color:red">↓</span>
HTTP/1.0 200 OK

:irc.klab.org NOTICE AUTH :*** Looking up your hostname...
:irc.klab.org NOTICE AUTH :*** Found your hostname
</pre>
<p>
クライアントから localhost:8080 に接続すると、
stone が SSL クライアント認証を受けて暗号化を行なった上で
proxy.klab.org:443 へ転送してくれる。
つまりクライアントから見ると、
localhost:8080 に認証不要なプロキシがあるように見える。
</p>
<p>
「-l」 オプションは、
stone のログ出力を Android の logging system へ出力するための指定
(指定しないと stone は標準出力にログを出す)。
logging system へ出力されたログは、
<a href="http://developer.android.com/guide/developing/tools/logcat.html">logcat</a> 
コマンドや<a href="https://market.android.com/details?id=org.jtb.alogcat">アプリ</a>で見ることができる。
</p>
<p>
SSL クライアント認証のための鍵の指定
(「-q cert=」「-q key=」「-q passfile=」オプション)
は、
前述した openssl の指定方法とほとんど同じだが、
stone の場合は Android の認証情報ストレージ (Credential storage)
を利用することもできる (後述)。
</p>
<blockquote>
Android 版 stone は、
「<a href="http://dsas.blog.klab.org/archives/51813490.html">パケットリピータ「stone」を Android へポーティング</a>」
から入手できる。
あるいは <a href="http://sourceforge.jp/cvs/view/stone/stone/">CVS レポジトリ</a>の中の
<a href="http://sourceforge.jp/cvs/view/stone/stone/Android.mk?view=log">Android.mk</a> 
を使って最新版の 
<a href="http://sourceforge.jp/cvs/view/stone/stone/stone.c?view=log">stone.c</a> 
をビルドしてもよい。
</blockquote>
<p>
(2) を実現するには、
クライアントが送信し 9980番ポートに届いてしまったパケットの、
元々の宛先を知る必要がある。
パケットの宛先は既に書き換えられてしまっているので役に立たないが、
Linux では getsockopt を使って 
SO_ORIGINAL_DST オプションの値を調べることにより、
TCP 接続の元々の宛先を得ることができる。
もちろん、
書き換えられた後で外部から届いた TCP 接続の 
「元々の宛先」
なんて分かるわけはなく、
あくまで同一マシンで書き換えられて
(正確に言えば PREROUTING あるいは OUTPUT chain で REDIRECT されて)、
そのままマシンから出ること無く同一マシンに着信した TCP 接続のみ。
</p>
<p>
stone では TCP 接続を転送する際、
TCP セッションの冒頭に
「CONNECT irc.klab.org:6667 HTTP/1.1」
等の文字列 (リクエストヘッダ) を付加することができる。
さらに付加する文字列として、
「CONNECT \D HTTP/1.1」
などと 「\D」 を指定すると、
「元々の宛先」
で置き換えてくれる。
つまり、
以下のように stone を実行することで (2) が実現できる:
</p>
<pre class="terminal-scroll">
senri:~ $ adb shell<span style="color:red">↓</span>
$ su<span style="color:red">↓</span>
# stone -l -q store=sengoku proxy.klab.org:443/ssl,http 9980 'CONNECT \D HTTP/1.1' &amp;<span style="color:red">↓</span>
# exit<span style="color:red">↓</span>
$ telnet irc.klab.org 6667<span style="color:red">↓</span>
:irc.klab.org NOTICE AUTH :*** Looking up your hostname...
:irc.klab.org NOTICE AUTH :*** Found your hostname
</pre>
<p>
転送先の指定 (上記実行例では 「proxy.klab.org:443」) には
「/」 に続けて拡張子をつけることができる。
「ssl」 は SSL で暗号化した上で転送する指定で、
「http」 が
「CONNECT ...」
を proxy.klab.org:443 へ送信するための指定。
「http」
をつけたときは、
転送元 (上記実行例では 「9980」) の次にもう一つ文字列引数が必要になり、
この文字列 ('CONNECT \D HTTP/1.1') をリクエストメソッドとして、
転送先へ送信する。
</p>
<p>
「-q store=sengoku」
オプションを指定することによって stone は
Android の認証情報ストレージ (Credential storage) から秘密鍵等を読み込む。
</p>
<p>
「認証情報ストレージ」
というのは鍵ペア (証明書と秘密鍵) および CA証明書を保存できるストレージで、
実体は /data/misc/keystore にある。
もちろん暗号化されていて、
stone などのプログラムや、
アプリなどから鍵を利用するには、
Android の設定メニューから
「位置情報とセキュリティの設定」 (Location &amp; security) の中の
「安全な認証情報の使用」 (Use secure credentials) 
をチェックしてパスワードを入力する必要がある。
</p>
<p>
stone のオプションで秘密鍵を指定する際、
「-q key=key.pem -q passfile=key.passwd」
などと秘密鍵および秘密鍵のパスワードをファイルで指定するよりは、
「-q store=sengoku」
などと指定 (「sengoku」 は鍵ペアの CN)
して認証情報ストレージを使った方が安全といえる。
</p>
<p>
認証情報ストレージに格納された鍵は、
格納したアプリの権限
(Android ではアプリごとにユーザID が割当てられる)
でないと読み出せないが、
設定メニューの「位置情報とセキュリティの設定 ⇒ USBストレージからのインストール」
で格納すると system (uid=1000) 権限で格納された扱いになる。
しかし system 権限だと <a href="http://linux.die.net/man/3/socket">socket(3)</a> が Permission denied (errno=EACCES) になるので、 
stone の実行権限としては不適当。
</p>
<p>
じゃ、どうすれば? 
と思ってソース frameworks/base/cmds/keystore/keystore.c
を見てみると、
root (uid=0), wifi (1010), vpn (1016) でも 
uid=1000 な鍵を読むことができるらしい。
上記実行例では (安易だが) root で走らせることにした。
</p>
<blockquote>
<a href="http://www.gcd.org/blog/2008/12/165/">WPA EAP-TLS</a> 
な無線LAN AP に接続するときに使用する鍵ペアも、
設定メニューの 「USBストレージからのインストール / Install from USB storage」 
を使って認証情報ストレージに格納しておく。
wpa_supplicant は wifi (uid=1010) 権限で動くので読み出すことができる。<br />
にしても、
「USBストレージ」 とは何ぞ? (なぜ USB が関係あるのか?) と思ってしまうが、
Android 端末によって
「SD カードからインストール / Install from SD card」 だったり
「Install encrypted certificates」 だったりと、
いろいろなバリエーションがあるようだ。
Nexus S の場合、
「SD カード」 が無いので 
「SD カードからインストール」 と書くわけにはいかなかったのだろうが、
普通に 「証明書のインポート」 でいいのではないかと思う。
</blockquote>
<p>
以上で、
Android 端末上で透過型プロキシを動かすことができた。
あとは Android のブート時に、
前述した iptables コマンドと stone を実行するように設定するだけ。
Nexus S や Nexus One および 
Google の設定をそのまま踏襲している Android 端末だと、
/init.rc において 
/system/etc/install-recovery.sh を実行する設定になっているので、
install-recovery.sh に以下のスクリプトを追記すればよい。
</p>
<pre class="code">
iptables -t nat -p tcp -A OUTPUT -j REDIRECT -d 10.10.0.0/24 --to-port 9980
stone -l -n -D -q verbose -q store=sengoku -q verify \
    proxy.klab.org:443/ssl,http 9980 'CONNECT \D HTTP/1.1'
</pre>
<p>
<a href="http://www.cyanogenmod.com/">CyanogenMod</a>
などのカスタムROM だと、
ブート時に
「run-parts /system/etc/init.d」
を実行してくれるので、
/system/etc/init.d ディレクトリの中に上記内容のスクリプトを 
30stone などのファイル名で入れておけば、
ブート時に実行される。
</p>

<p>
6月6日追記:
</p>
<p>
これで OK と思っていたら、
テザリングすると iptables で設定した内容が消えてしまった。
正確に言うと、
テザリングを開始すると nat table の 
POSTROUTING chain に以下のルールが追加され、
</p>
<pre class="terminal">
Chain POSTROUTING (policy ACCEPT 26086 packets, 1638K bytes)
 pkts bytes target     prot opt in     out     source               destination

    0     0 MASQUERADE  0    --  *      rmnet0  0.0.0.0/0            0.0.0.0/0

</pre>
<p>
テザリングを終了すると
filter table の INPUT, OUTPUT, FORWARD の各 chain と、
nat table の全 chain が初期化 (iptables -F) されてしまう。
つまり POSTROUTING chain に追加した上記ルールだけ消せばいいものを、
全 chain の初期化を行なうものだから、
透過型プロキシを実現するために設定した 
nat table の OUTPUT chain まで巻き添えを食って消されてしまう。
</p>
<p>
原因は、
/system/bin/netd において NAT を disable する際
(テザリングを終了させるとき)
setDefaults() で全 table を初期化する実装 (なんて乱暴な!) になっているため。
</p>
<p>
iptables -t nat -A POSTROUTING ... で POSTROUTING chain へ追加したルールは、
きちんと iptables -t nat -D POSTROUTING ... 
で削除すべきだと思うのだが...(*_*)
追加と削除が対にならない事態に陥ることを恐れて、
こういう実装にしているのかも知れないが、
それなら対にならなかったとき (iptables がエラーになったとき) 
のみ初期化すればいいだけの話。
</p>
<p>
以下のような修正で、
初期化ではなく個々のルールを削除させることができる。
</p>
<pre class="terminal">
--- system/netd/NatController.cpp.org	2011-02-28 16:56:08.573705126 +0900
+++ system/netd/NatController.cpp	2011-06-06 18:52:08.730041739 +0900
@@ -92,15 +92,15 @@
     char cmd[255];
 
     // handle decrement to 0 case (do reset to defaults) and erroneous dec below 0
-    if (add == false) {
-        if (natCount &lt;= 1) {
-            int ret = setDefaults();
-            if (ret == 0) {
-                natCount=0;
-            }
-            return ret;
-        }
-    }
+//  if (add == false) {
+//      if (natCount &lt;= 1) {
+//          int ret = setDefaults();
+//          if (ret == 0) {
+//              natCount=0;
+//          }
+//          return ret;
+//      }
+//  }
 
     if (!interfaceExists(intIface) || !interfaceExists (extIface)) {
         LOGE("Invalid interface specified");
@@ -128,8 +128,8 @@
     }
 
     // add this if we are the first added nat
-    if (add &amp;&amp; natCount == 0) {
-        snprintf(cmd, sizeof(cmd), "-t nat -A POSTROUTING -o %s -j MASQUERADE", extIface);
+    if ((add &amp;&amp; natCount == 0) || (!add &amp;&amp; natCount == 1)) {
+        snprintf(cmd, sizeof(cmd), "-t nat -%s POSTROUTING -o %s -j MASQUERADE", (add ? "A" : "D"), extIface);
         if (runIptablesCmd(cmd)) {
             // unwind what's been done, but don't care about success - what more could we do?
             setDefaults();;
</pre>
<p>
ちなみに、
com.android.server.NetworkManagementService の enableNat() と disableNat() が
netd にコマンドを送って NAT の enable/disable を行なっている。
</p>
<p>
/system/bin/ndc を使って同等のコマンドを netd へ送ることが可能:
</p>
<pre class="terminal">
# ndc nat enable usb0 rmnet0<span style="color:red">↓</span>
200 Nat operation succeeded
# iptables -t nat -L POSTROUTING -nv<span style="color:red">↓</span>
getsockopt for multiport failed strangely: No such file or directory
getsockopt for multiport failed strangely: No such file or directory
Chain POSTROUTING (policy ACCEPT 26282 packets, 1650K bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 MASQUERADE  0    --  *      rmnet0  0.0.0.0/0            0.0.0.0/0           
# ndc nat disable usb0 rmnet0<span style="color:red">↓</span>
200 Nat operation succeeded
# iptables -t nat -L POSTROUTING -nv<span style="color:red">↓</span>
getsockopt for multiport failed strangely: No such file or directory
getsockopt for multiport failed strangely: No such file or directory
Chain POSTROUTING (policy ACCEPT 26282 packets, 1650K bytes)
 pkts bytes target     prot opt in     out     source               destination         
# 
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.gcd.org/blog/2011/06/806/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>TheBus でヌアヌ・パリ展望台 (Nu‘uanu Pali Lookout) へ行ってみた</title>
		<link>http://www.gcd.org/blog/2011/05/802/</link>
		<comments>http://www.gcd.org/blog/2011/05/802/#comments</comments>
		<pubDate>Mon, 23 May 2011 00:43:22 +0000</pubDate>
		<dc:creator>hiroaki_sengoku</dc:creator>
				<category><![CDATA[Hawaii]]></category>

		<guid isPermaLink="false">http://www.gcd.org/blog/?p=802</guid>
		<description><![CDATA[ハワイ州オアフ島の観光スポットの定番、 ヌアヌ・パリ (Nu‘uanu Pali) 展望台。 地図中 赤印 A → 一昔前のパック・ツアーなどだと、 空港に到着後、 ホテルへチェックインする前に観光バスで連れて行ってもら [...]]]></description>
			<content:encoded><![CDATA[<p>
<a href="http://www.gcd.org/sengoku/picts/PaliHwy/PaliHwy_BusStop.jpg"><img src="http://www.gcd.org/sengoku/picts/PaliHwy/PaliHwy_BusStop.jpg" alt="" width="315" height="283" class="pict-right" /></a>
ハワイ州オアフ島の観光スポットの定番、
ヌアヌ・パリ (<a href="http://en.wikipedia.org/wiki/Nu%E2%80%98uanu_Pali">Nu‘uanu Pali</a>) 展望台。
地図中 <font color="red">赤印 A</font> →<br />
一昔前のパック・ツアーなどだと、
空港に到着後、
ホテルへチェックインする前に観光バスで連れて行ってもらえたりしたが、
自力で行こうとすると難度が高い。
すなわち、
ハワイ唯一の公共交通機関 TheBus だと最寄りのバス停
(地図 <font color="blue">青印</font> 3ヶ所) から遠い
(もちろんレンタカーを使えば簡単に行けるが、
ここでは車を使う方法は除外して考える)。
</p>
<p>
遠いだけならまだしも、
「展望台」
であるから
(当然) 山の中であり、
しかも展望台があるのは高速道路 (Pali Highway, 61号線) の真上 (標高 386m)。
展望台 <font color="red">A</font> のホノルル側 
(地図で左下方向) の二つのバス停は、
直線距離で 4km 以上ある上に、
途中トンネルなどもあって、
徒歩で行くのは現実的では無さそう
(Pali Highway はオアフ島の幹線で、
かなり交通量がある上に車速も 80km/h 程度と速く、
路肩を歩くのは危険)。
</p>
<p>
可能性があるのは <font color="red">A</font> のカイルア側 
(地図で右上方向) のバス停 (Kamehameha Highway との交差点)。
直線距離で 1.6km ほどだが、
道路がヘアピンカーブになっているので、
実際には 3km くらいになる。
展望台から 500m ほど、
今は使われていない旧道 (Old Pali Road) があって
(この旧道の下に Pali Highway のトンネルがある)、
その先は山道 <a href="http://hawaiitrails.ehawaii.gov/trail.php?TrailID=OA+13+088">Maunawili Trail</a> に接続している。
</p>
<span id="more-802"></span>
<p>
つまり、
<a href="http://maps.google.com/maps/place?ftid=0x7c006b434b2bccb1:0x625f60d3bf84ccd1&amp;q=type:transit_station:%22Pali+Hwy+%2B+Opp+Kamehameha+Hwy%22&amp;hl=ja&amp;cad=src:ppiwlink&amp;ei=OQrWTYCRII3euAOZjqDeCg&amp;dtab=0">Pali Hwy + Opp Kamehameha Hwy</a>
バス停 (以下の拡大図 <font color="red">赤印 B</font> ) で 
TheBus を下車し、
そこから Maunawili Trail の入口
(<font color="blue">青印 6</font> )
まで歩いて行くことができれば、
後は Maunawili Trail (<font color="blue">青印 6</font> 〜 
<font color="blue">7</font> ) と Old Pali Road を通って、
ヌアヌ・パリ展望台 (<font color="red">赤印 A</font> ) 
まで歩いて行くことができる。
</p>
<a href="http://goo.gl/maps/dJU8"><img src="http://www.gcd.org/sengoku/picts/PaliHwy/PaliHwy_Map.jpg" alt="" width="489" height="365" /></a>
<p>
ハワイには Maunawili Trail のような Trail が沢山ある。
1時間ほどで歩ける手軽なものから、
丸一日かけて山々を縦走するコースまで、
難度もいろいろ。
大勢の人々が訪れているらしく、
どの Trail でも 1時間も歩いていると何組ものハイカーに出会う。
</p>
<p>
<a href="http://www.gcd.org/sengoku/picts/PaliHwy/MaunawiliTrail.jpg"><img src="http://www.gcd.org/sengoku/picts/PaliHwy/MaunawiliTrail.jpg" alt="" width="237" height="178" class="pict-right" /></a>
Trail の入口や分岐点には、
右の写真のように
Trail の名称 (MAUNAWILI TRAIL) を書いた看板が立ててあるので、
Trail の名称と位置関係さえ把握していれば、
あまり迷う心配はない。
</p>
<p>
とはいえ、
ケモノ道と大差ない部分もあり、
道無き道に踏み込んでしまうと 
Trail を見失ったりする。
また、
(ビーチと違って) 
山の多くは熱帯雨林気候なので日常的に大雨が降る。
普段は飛び石づたいに歩いて渡れる小川が、
あっというまに激流になって渡れなくなることもあるので、
天候の変化に注意。
</p>
<p>
<a href="http://www.gcd.org/sengoku/picts/PaliHwy/LookoutParking.jpg"><img src="http://www.gcd.org/sengoku/picts/PaliHwy/LookoutParking.jpg" alt="" width="237" height="178" class="pict-left" /></a>
ハワイは (というか米国はどこでも) 車社会なので、
ほとんどの Trail は近くに駐車場があり、
ハイカーの多くは駐車場に車を停めて Trail に入る。
</p>
<p>
← は、
Maunawili Trail の入口 (<font color="blue">青印 6</font> ) 
から駐車場 (<font color="blue">青印 5</font> ) 方向を撮った写真。
ガードレールに切目があって、
駐車場から Trail の入口へ、
スムーズに入ることができる。
</p>
<p>
というわけで、
問題は
<font color="red">赤印 B</font> のバス停から、
どうやってこの駐車場 <font color="blue">5</font> まで歩いてくるか。
交通量が多い Pali Highway なので、
できれば路肩は歩きたくないし、
まして道路を横断することは不可能。
Pali Highway はバスで何度も通っているので、
ホノルルからカイルア方面へ向かうバスに乗ったときは、
駐車場 <font color="blue">5</font> 
からバス停 <font color="red">B</font> まで、
進行方向右側 (つまり駐車場と同じ側) の路肩の様子をじっくり観察した。
</p>
<p>
<a href="http://www.gcd.org/sengoku/picts/PaliHwy/HairpinCurve.jpg"><img src="http://www.gcd.org/sengoku/picts/PaliHwy/HairpinCurve.jpg" alt="" width="237" height="178" class="pict-right" /></a>
ヘアピンカーブの部分、
つまり <font color="blue">青印 5</font> の駐車場から
<font color="blue">青印 4</font> のあたりまでは、
右の写真 →<br />
で分かる通り、
道路の縁石の外側を歩くことができそう。
車が縁石に衝突して外に飛び出してこない限りは安全と思われる。
</p>
<p>
<font color="blue">青印 4</font> のあたりから、
縁石に替ってガードレールになるが、
ここもガードレールの外側を安全に歩くことができそう。
</p>
<p>
<font color="blue">青印 3</font> 
でブッシュが生い茂ってきて、
ガードレールとブッシュとの間の隙間が ↓ ほとんどなくなる。
<a href="http://www.gcd.org/sengoku/picts/PaliHwy/Guardrail_Bush.jpg"><img src="http://www.gcd.org/sengoku/picts/PaliHwy/Guardrail_Bush.jpg" alt="" width="237" height="178" class="pict-left" /></a>
</p>
<p>
歩くのは不可能、
とまでは言わないが、
かなり歩きにくそうなので、
車の流れが途切れているときは路肩を歩くのもやむなしか。
</p>
<p>
といっても、
ガードレールの外側に隙間がない区間は高々 100m ほどで、
<font color="blue">青印 4</font> から
<font color="blue">青印 2</font> の区間のほとんどは、
ガードレールの外側を歩けそう。
</p>
<p>
ちなみに
「SPEED LIMIT 35」
(上限 56km/h) の標識が写っているが、
下り坂だと TheBus でさえ 80km/h くらい出している (いいのか?)。
</p>
<p>
<a href="http://www.gcd.org/sengoku/picts/PaliHwy/RunawayTruckRamp.jpg"><img src="http://www.gcd.org/sengoku/picts/PaliHwy/RunawayTruckRamp.jpg" alt="" width="237" height="178" class="pict-right" /></a>
<font color="blue">青印 2</font> から
<font color="blue">青印 1</font> まで緊急待避所がある →<br />
Pali Highway はここまで急な坂道が続くので、
ブレーキが利かなくなった車は、
ここ (道路脇に登り坂がある)
に突っ込んで車を無理矢理停める。
そうしないと、すぐ 300m 前方に交差点
(<font color="red">赤印 B</font> )
がある。
</p>
<p>
緊急待避所のおかげで、
この区間には広大な路肩 (というか待避所) がある。
ブレーキが利かなくなった車なんてそうそう来ないだろうから、
この待避所の区間は安全に歩けそう。
</p>
<p>
<a href="http://www.gcd.org/sengoku/picts/PaliHwy/NarrowShoulder.jpg"><img src="http://www.gcd.org/sengoku/picts/PaliHwy/NarrowShoulder.jpg" alt="" width="237" height="178" class="pict-left" /></a>
緊急待避所を過ぎると、
「JCT 83」
の標識が見える。
83号線というのは Kamehameha Highway のこと。
Pali Highway と
Kamehameha Highway との交差点に、
目指すバス停 (<font color="red">赤印 B</font> ) がある。
</p>
<p>
← ところがこの区間だけは、
ガードレールが無い。
路肩からすぐ斜面になっている。
<font color="blue">青印 1</font>
から 100m あまりこのような路肩が続く。
この区間だけは路肩を歩かざるを得ない。
車の流れが途切れた時をねらって速やかに通過したい。
</p>
<p>
<a href="http://www.gcd.org/sengoku/picts/PaliHwy/Guardrail.jpg"><img src="http://www.gcd.org/sengoku/picts/PaliHwy/Guardrail.jpg" alt="" width="237" height="178" class="pict-right" /></a>
そして、
バス停直前の最後の 200m ほどは →<br />
ガードレールがあり、
その外側を安全に歩くことができる。
</p>
<p>
というわけで、
途中 2回ほど路肩を歩かなければならない区間があるが、
どちらも 100m ほどなので、
車の流れが途切れたタイミングを見計らって歩けば、
さほど危険とは思われない。
</p>
<p>
そこで、
<font color="red">赤印 B</font>
のバス停で
<a href="http://www.gcd.org/sengoku/picts/PaliHwy/PaliHwy_KamehamehaHwy_BusStop.jpg">TheBus を降り</a>、
<font color="blue">青印 5</font> の駐車場まで
Pali Highway 沿いに歩き、
<a href="http://www.gcd.org/sengoku/picts/PaliHwy/NuuanuPaliLookout.jpg"><img src="http://www.gcd.org/sengoku/picts/PaliHwy/NuuanuPaliLookout.jpg" alt="Nu‘uanu Pali Lookout" width="178" height="237" class="pict-left" /></a>
<a href="http://www.gcd.org/sengoku/picts/PaliHwy/Parking2Trail.jpg"><font color="blue">青印 6</font> から Maunawili Trail へ</a>入って、
Old Pali Road を通って、
<font color="red">赤印 A</font>
の<a href="https://twitter.com/gcd_org/status/64063452473331714">ヌアヌ・パリ展望台</a>まで歩いてみた。
さらに、
<a href="https://market.android.com/details?id=com.google.android.maps.mytracks">My Tracks</a> (Android アプリ) を使って、
歩いた<a href="http://goo.gl/maps/dJU8">軌跡を記録してみた</a>。
記録によれば、
歩いた距離は 4.09 km で、
平均移動速度は 5.79 km/h となっている。
</p>
<p>
なお、
Maunawili Trail から Old Pali Road になるあたり、
<font color="blue">青印 7</font> に分岐点があり、
北に曲がって Pali Highway の下をくぐるコースを進むと、
Kionaole Rd に出る。
Kionaole Rd は途中で通行止めになっているので車は通れないが歩くことはできて、
バス停 <font color="red">B</font> のすぐ近くで Pali Highway に出る。
だから、
山道をほとんど通らずに、
バス停 <font color="red">B</font> から
Kionaole Rd と Old Pali Road を通って、
ヌアヌ・パリ展望台まで歩くことも可能。
</p>]]></content:encoded>
			<wfw:commentRss>http://www.gcd.org/blog/2011/05/802/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>nook color を買って CyanogenMod 7 をインストールしてみた 〜 レンガ化リスクが無い PC のようなタブレット端末</title>
		<link>http://www.gcd.org/blog/2011/05/799/</link>
		<comments>http://www.gcd.org/blog/2011/05/799/#comments</comments>
		<pubDate>Tue, 17 May 2011 22:43:22 +0000</pubDate>
		<dc:creator>hiroaki_sengoku</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Hawaii]]></category>

		<guid isPermaLink="false">http://www.gcd.org/blog/?p=799</guid>
		<description><![CDATA[ハワイ滞在中、 泊ったホテルのすぐ近くに米国最大の書店チェーン Barnes &#38; Noble があった。 当然しばしば立ち寄ったが、 電子ブックリーダ nook のデモ機を店内の一番目立つ場所 (入口を入ってすぐ [...]]]></description>
			<content:encoded><![CDATA[<p>
ハワイ滞在中、
泊ったホテルのすぐ近くに米国最大の書店チェーン 
<a href="http://www.barnesandnoble.com/">Barnes &amp; Noble</a> があった。
当然しばしば立ち寄ったが、
電子ブックリーダ 
<a href="http://www.barnesandnoble.com/nook/">nook</a> 
のデモ機を店内の一番目立つ場所 
(入口を入ってすぐのところ) に並べて説明員が張り付いていて、
いつ訪れても、
来店する人々に nook を勧めたり説明したりしていた。
<a href="http://www.gcd.org/blog/2010/05/582/">昨年</a> (2010年4月) 
訪れたときもこういう状態だったので、
もうかれこれ一年以上やっているのだと思うが、
今回は昨年と違って、
nook color がラインアップに加わっている。
</p>
<p>
電子ブックリーダというと、
初代 nook や Kindle や 
<a href="http://www.borders.com/">BORDERS</a> (米国二番手の書店チェーン, 経営再建中) の
<a href="http://koboereader.com/">kobo eReader</a>
など、
電子インク (E Ink) をディスプレイに用いた機種が思い浮かぶが、
nook color は普通の液晶ディスプレイ。
電子書籍を読むなら圧倒的に電子インクの方が適していると思うが、
あいにく日本では電子書籍の普及は今一つだし、
近い将来普及が進むかというとなかなか難しそう
(そもそも普及に懸ける書店の意気込みがぜんぜん違う)。
だから (英語がニガテな私は) 
電子インクなブックリーダにはあまり興味がなかった
(自炊は大変そう)。
でも、
nook color は液晶ディスプレイなので Android タブレットとして使えそう。
</p>
<p>
店頭デモ機をいじってみると、
そのままでも WWW ブラウザで日本語表示できるし、
ちょっと検索してみると<a href="http://nookdevs.com/">ハック</a>もいろいろ進んでいる
(Android 3.0 honeycomb も動く) ようだ。
しかも $249 と Android タブレットとしてみると格安。
同じく 7インチ液晶の Galaxy Tab (382g) よりは重いが、
9.7インチ液晶の iPad2 (601g, ずっしり重くて私には無理) よりは軽い 450g.
</p>
<p>
というわけでハワイ滞在最終日に衝動買い (^^;)。
ちょうど円高が進んでいる昨今でもあるし〜 (言い訳)。
説明員のお姉さんに、
コレちょうだいと言うと、
すぐカウンターの下から (そんなところに在庫を入れていたのか) 
取り出してレジへ。
ハワイ州の Sales Tax 4.710% が加算されて $260.73 (約 21000円)。
そのままスーツケースに放り込んで帰国。
</p>
<p>
で、
まず root 化。
<a href="http://forum.xda-developers.com/showthread.php?t=942424">Auto-Nooter 3.0.0</a> を使うと、
root 権限の取得から各種ソフトウェアのインストールまで、
全自動でやってくれるらしい。
Auto-Nooter をダウンロードして、
micro SD カードに書込み、
nook color に挿入して USB ケーブルで PC とつなぐと、
勝手にブートして勝手に全部やってくれる。
なんて簡単な...
</p>
<p>
ところが!
</p>
<span id="more-799"></span>
<p>
簡単すぎる操作手順には落とし穴が付き物。
USB ケーブルをつないでも、
電源がオンになった気配が全く無かった
(画面は消えたままだし、
LED 等の表示装置は元々無いし、
ハードディスク等の可動部分もないので何の音もしない) ので、
これはきっと USB ケーブルをつないだだけでは電源がオンにならなかったのだろうと、
思わず電源スイッチを長押ししてしまった。
ところが、
実はこのときすでに root 化 &amp; インストールが進行中だった。
つまり、
電源スイッチを長押ししたことによって強制電源断となる。
</p>
<p>
システム書き換え中に電源断すれば何が起きるかなんて火を見るより明らかなわけで、
(micro SD カードを抜いても) 立ち上がらなくなってしまった orz。
これはもしかしてレンガ状態?
電源を入れると、
「Touch the Future of Reading」 が表示された後、
中央に nook の 「n」 のロゴと、
下部に
「Contains Reader&reg; Mobile technology by Adobe Systems Incorporated.」
と表示された画面のまま止ってしまう。
これは Android の起動アニメーションが表示される前の画面なので、
/init の実行前 (あるいはカーネルの起動前?) に問題が起きたのだと思われる。
</p>
<blockquote>
後日、
Auto-Nooter の中身を調べてみると、
micro SD カードから /system と /data と /tmp へ、
各種ファイル 
(/system/app/Superuser.apk や /data/app/SoftKeys_3.06.apk など) 
をコピーした後、
/tmp へコピーしたスクリプト /tmp/scripts/Nooter を実行している。
このスクリプト Nooter は
「chmod 4775 su」
などを行なった後、
uRamdisk (initramfs) をいったん展開して default.prop などを書き換えた後、
uRamdisk を作り直す。<br />
おそらく、
強制電源断を行なったとき Nooter が uRamdisk の再作成中だったのではないか。
uRamdisk の内容が壊れれば /init を起動できなくなる。
また、
再度 Auto-Nooter を micro SD カードから起動しても、
Nooter は uRamdisk を新たに作ってくれるわけではないので、
uRamdisk は壊れたままとなる。<br />
とはいえ、
Auto-Nooter 自体は正常に起動している
(ウンともスンとも言わないので、
とても
「正常」 
には見えないが)
ので、
「レンガ状態」
と呼ぶのは不適切かも。
</blockquote>
<p>
開封して数時間でいきなりレンガ化か〜
(奇しくも Adobe の文字が画面に ;_;)
と愕然としながらも、
<a href="http://nookdevs.com/Flash_back_to_clean_stock_ROM">Flash back to clean stock ROM</a> 
と書いてあるページを見つけたので試してみることにした。
</p>
<p>
曰く、
「リブートカウンタ /rom/devconf/BootCnt が 8 に到達すると、
工場出荷時状態へのリセットが行なわれる」。
つまり、
なんらかの方法で BootCnt を 8 にして起動すれば、
フラッシュメモリの内容が工場出荷時状態に書き戻されるらしい。
</p>
<p>
BootCnt は正常起動できなかった回数を数えるカウンタで、
電源オン時にブートローダ u-boot.bin によってカウントアップされる。
正常起動できたときは
/init.rc から呼び出される 
/system/bin/clrbootcount.sh によって BootCnt はゼロクリアされる。
正常起動できなかったときは、
ゼロクリアされないので、
カウントアップされたままになる。
</p>
<p>
つまり連続して起動に失敗した回数が BootCnt に保存される。
電源オン時に BootCnt が 8 ということは、
過去 8回連続で起動に失敗したことを意味するわけで、
nook color は自身が再起不能状態になったと自己診断して、
フラッシュメモリ (/system パーティション) 
の再インストールを行なうというわけ。
<a href="http://www.gcd.org/sengoku/picts/nook_factory_reset.jpg"><img src="http://www.gcd.org/sengoku/picts/nook_factory_reset.jpg" alt="nook color re-flash its /system partition" class="pict-right" width="267" height="356" /></a>
</p>
<p>
起動途中で電源ボタンを押し続けて強制電源断を行なうと、
ゼロクリアされる前に電源オフになるので、
これを 8回繰り返せば 
BootCnt の値を 8 にできる。
強制電源断を 8回も行なうなんて、
ずいぶん乱暴な方法だなと思いつつ、
</p>
<p>
電源ボタンを押して電源投入<br />
　　↓<br />
「Welcome to the future of reading」 
が表示されたらすぐに電源ボタンを長押し
<br />
　　↓<br />
「Touch the Future of Reading」 が消えた後、電源がオフになる
</p>
<p>
以上の操作を 8回繰り返した。
すると、
唐突に再インストールの画面が現れた！ →
</p>
<p>
再インストールが終わるまで待つこと数分、
無事起動するようになった。
念のため、
「Erase &amp; Deregister Device」
を行なってユーザ領域も初期化。
これで完全に工場出荷時状態
(バージョン 1.1.0) に戻った。
</p>
<blockquote>
レンガ状態から復旧させることができた安堵感から BootCnt++ と思ったのだが、
冷静になってから考えて直してみると、
NookColor は micro SD カードからブートできるわけで、
クリーンインストールを行なえるような micro SD カードを用意しておけば、
BootCnt などに頼らなくても同じことが可能。
レンガ化リスクが全く無い安全な端末と言える。
</blockquote>
<p>
というわけで、
開封時の振出しに戻ったので root 化に再度挑戦。
こんどは慎重に Auto-Nooter の動作を見守る (見ていただけ)。
ウンともスンとも言わない状態を見守り続けるのは、
「いらち」な私には少々つらいが、
待つこと数分、
無事 root 化された nook color が立ち上がった。
後は
<a href="http://forum.xda-developers.com/showthread.php?t=942424">Auto-Nooter 3.0.0 の説明</a>に書いてある通り、
YouTube アプリを使って Gmail アカウントにログインし、
続いて Gmail アプリで同期を行なうと、
<a href="http://market.android.com/">Android マーケット</a>が利用できるようになる。
</p>
<blockquote>
多くの Android 端末にとって
「root 化」
が Android OS の脆弱性を突いた
root 権限 「奪取」
であるのに対し、
nook color の場合は micro SD カードからブートしてシステムを書き換える、
いわば無理のない 「自然な」 方法。
「root 化」
と呼ぶのは適切ではないかも。
</blockquote>
<p>
root 化されたといっても外見は元の nook color のままなので、
電子書籍を買ったり読んだりするための操作体系。
Android タブレットとして使おうとすると少々使いにくい。
致命的なのは日本語を入力できないこと。
「<a href="https://market.android.com/details?id=com.pm9.flickwnn">OpenWnn flick 対応版</a>」
をインストールしてみたのだが、
なぜか入力方法を OpenWnn へ切り替えることができない。
Android OS をベースにした電子ブックリーダって、
Home アプリを入れ替えて操作体系を変更しただけのものと思っていたのだが、
Home アプリだけでなく OS の部分にも手を入れてあるようだ。
</p>
<p>
nook color 本来の操作体系に未練はなかった
(純 Android 化しても電子書籍を買ったり読んだりすることはできる)
ので、
ひと思いに 
<a href="http://ja.wikipedia.org/wiki/CyanogenMod">CyanogenMod</a> 
をインストールしてしまうことにした。
</p>
<p>
まず <a href="https://market.android.com/details?id=com.koushikdutta.rommanager">ROM Manager</a> をインストールし、
「ClockworkMod recovery を導入」。
いちおう、
「現在のROMをバックアップ」
してから、
<a href="http://forum.cyanogenmod.com/topic/20138-cyanogenmod-7-for-barnes-noble-nook-color-v703-9-may-2011/">CyanogenMod 7 for Barnes &amp; Noble Nook Color</a>
を書込んだ。
起動すると、
全くフツーの Android 2.3 gingerbread タブレットに生まれ変わった。
電子ブックリーダだったころの面影は全く残っていない。
Google アカウントの設定を行なえば、
<a href="http://market.android.com/">Android マーケット</a>も利用できるようになる。
</p>
<p>
他の Android 端末だと
ClockworkMod recovery を使ったインストールが一番手軽なので、
つい ClockworkMod recovery を使ってしまったが、
nook color は micro SD カードから任意の OS をブートできるので、
「インストール SD カード」
のようなものを作ってインストールする方が、
より簡単で安全と思われる。
ちょうど PC に OS をインストールするときに、
「インストール CD-ROM」
を使うのが一般的であるように。
この意味で、
nook color は
「より PC に近い」
タブレット端末と言えそう。
</p>]]></content:encoded>
			<wfw:commentRss>http://www.gcd.org/blog/2011/05/799/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

