#freeze
TITLE:バッファローの古い無線LANアダプタ(WLA-G54)にUSBストレージを追加してCGIやsambaが動くDD-WRTにする
RIGHT:初出 2013-3-16
RIGHT:最終更新 2015-3-31
LEFT:
私が[[%%%このページ%%%>internet-ir-aircon]]や[[%%%このページ%%%>remote-sys]]で紹介しているシステムには[[CGI>internet-ir-aircon#web_interface]]が動作するウェブサーバが必要です。従来私は、この為のウェブサーバとして省スペースデスクトップを改造した[[%%%このようなもの%%%>onecddebian]]を使ってきましたが、かねがねもっとコンパクトで省電力な物の方が好ましいと思っていました。
#br
こんな場合、普通はMini-ITXとかRaspberry Piを検討するところでしょうが、私はもっと面白いものの方がいいので、不要になっていた、古い無線LANブリッジのハードを小改造してストレージを追加し、「[[DD-WRT:http://www.dd-wrt.com/site/index]]+[[optware:http://www.dd-wrt.com/wiki/index.php/Optware]]」でウェブサーバを立てることにしました。スイッチングハブ内蔵なので部屋がすっきりします。
※WLA-G54の場合、optwareなしのDD-WRTだとCGIやsambaは動きません。
#br
ハードの改造について唯一の資料となったページはこちらです。
[[DD-WRT Forum :: View topic - Old Buffalo WBR/WLA-G54 USB connector pinouts:http://www.dd-wrt.com/phpBB2/viewtopic.php?p=72418&sid=94ed53fde908209374779dd2355278b0]]
Broadcom4702のデータシートは手に入れられなかったので、このページのみを頼りにハード改造作業をおこないました。ただし非常に簡単な作業で済むことは一目瞭然です。
#br
#contents
#br

* ハードの改造 [#a5c1cdb2]
[[&ref(add_usb-port_to_dd-wrt_1_s.jpg);:http://wikiwiki.jp/disklessfun/?plugin=attach&pcmd=open&file=add_usb-port_to_dd-wrt_1_b.jpg&refer=add_usb-port_to_dd-wrt]]
&size(7){クリックすると大きな画像で表示されます};
古いハードなのでケースの大きさに非常に余裕があり、固定のUSBストレージとして、古い4GBのUSBメモリをケース内の基板とケースのガワの間に収納しています。
(固定式)USBメモリのソケットとして100円ショップのUSB延長ケーブルを切断したものを使い、USB・D+をUSB1_Pに、USB・D-をUSB1_Nにつなぎ、USB1_Cを10kΩで3.3Vにプルアップし、5V電源を追加した程度です。外観を綺麗に仕上げたいなら3.3Vの純正ACアダプタを5Vに交換し、3.3Vは内部で作り出すようにするところですが、そんな気は全くなかったので、5Vは別のACアダプタから供給しています。%%利用しているのは基板表面のポート1のみで裏面のポート2の方は手を付けていません。基板をケースから取り外したことさえありません。%%(2013-7-21追記)裏面のポート2の方も配線しました。USBメモリをポート2の方に挿して起動しても動作は全く同じです。普通のUSBの取り扱い方と何ら変わるところはありません。今回追加したポート2の方はソケットをケースの外に出しました。[[%%%これ%%%>send-only-ir-remocon]]なんかを使えるようにです。動作確認も済ませています。
余談ですが、最初にポート1だけ配線したのは失敗でした。はじめからポート2の方も配線すべきでした。というのは今回、ポート2の配線そのものはごく簡単だったのですが、前回作業時に自分で貼った絶縁用の(アセテート)テープを剥がすのにその何倍も苦労しました。
#br
&ref(add_usb-port_to_dd-wrt_2_s.jpg,nolink);
WLA-G54のACアダプタは3.3Vなので、USBの5Vについては別途ACアダプタ(古い携帯用のACアダプタ)を用意しました。
#br
|USB_1P|DATA+|USBの緑の線|
|USB_1N|DATA-|USBの白の線|
|USB_1C|3.3Vにプルアップ|10kΩの抵抗を使用|
|USB_2P|DATA+|USBの緑の線|
|USB_2N|DATA-|USBの白の線|
|USB_2C|3.3Vにプルアップ|10kΩの抵抗を使用|

* 使用ファームウェア [#da4dc71b]
VINTAGE : mini_usb_ftp
ファイル名:dd-wrt.v24-13064_VINT_mini_usb_ftp.bin

* DD-WRTの設定(抜粋) [#le9a7085]
-ネットワーク→USB Support
--Core USB Support:有効
--USB 1.1 Support(OHCI):有効
--USB Storage Support:有効
--ext2 / ext3 File System Support
--Automatic Drive Mount:''無効''

* 起動時スクリプト [#ve4ff8e9]
USBストレージ(メモリ)は固定して使用するので、マウントはここだけでおこなっています。
 mount -o noatime /dev/discs/disc0/part1 /opt
 mount -o noatime /dev/discs/disc0/part3 /mnt
 export PATH=/opt/bin:/opt/sbin:/opt/usr/sbin:/opt/usr/bin:/bin:/usr/bin:/sbin:/usr/sbin
 unset LD_LIBRARY_PATH
 sysctl -w vm.swappiness=0
 swapon /dev/discs/disc0/part2
 echo nobody:*:65534:65534:nobody:/var:/bin/false >> /etc/passwd
 echo owner:*:1000:1000:nobody:/var:/bin/false >> /etc/passwd
 echo owner:x:1000:  >> /etc/group
 /opt/etc/init.d/S80thttpd start
 /opt/etc/init.d/S80samba start

* インストールしたoptware [#l9929ff6]
(optware-install.sh実行後にインストールしたパッケージ)
ipkg-opt install busybox
ipkg-opt install coreutils
ipkg-opt install diffutils
ipkg-opt install findutils
ipkg-opt install thttpd
ipkg-opt install perl-email-send
ipkg-opt install perl-digest-hmac
ipkg-opt install perl-libwww

* thttpd.conf(CGIを有効化) [#a61fc566]
 dir=/opt/share/www
 port=8080
 user=nobody
 nochroot
 nosymlink
 novhost
 logfile=/var/log/thttpd.log
 pidfile=/var/run/thttpd.pid
 cgipat=perl/*

* Perl環境の修正内容(smtp-auth機能の追加) [#de5be316]
Ubuntu 10.04 4 LTSよりコピー
-/opt/lib/perl5/5.8.8/Authen(ディレクトリ丸ごと)
-/opt/lib/perl5/5.8.8/Net/SMTP_auth.pm
-/opt/lib/perl5/5.8.8/Net/Jcode.pm(未使用)

* Firewallスクリプト [#q1ff4621]
これはUSBストレージの追加には全く関係ありません。SMTPのポート変換のみの簡易プロキシ機能の実装です。

 /usr/sbin/iptables -t nat --flush
 /usr/sbin/iptables -t nat -A PREROUTING --dst $(nvram get lan_ipaddr) -p tcp --dport 25
 ↑本当は1行↓
 -j DNAT --to-destination $(nslookup smtp.hogehoge.ne.jp|tail -1|cut -d" " -f3):587
 /usr/sbin/iptables -t nat -A POSTROUTING --dst $(nslookup smtp.hogehoge.ne.jp|tail -1|
 ↑本当は1行↓
 cut -d" " -f3) -j MASQUERADE

ブリッジモードにしているので1行目のflushが必要です。デフォルトのルーターモードなら不要です。

* cronタブエントリ [#u09297d2]
Wake On LANの設定はUSBストレージの追加には全く関係ありません。

 48 9 * * 6 root /usr/sbin/wol -i 192.168.1.255 00:10:XX:XX:XX:XX >/dev/null
 */30 * * * * root /opt/check_and_warning_sendmail.pl >/dev/null 2>&1
 5,20,35,50 * * * * root /opt/watch-samba.sh >/dev/null 2>&1

(2013-9-1追記)
 15 5 * * * root /sbin/reboot >/dev/null
ここ数ヶ月、毎日、自動リブートをおこなってきました。下記のPerlスクリプトを運用すると、メモリーリークが発生しているからか、数日程でスラッシングが起きてしまうからです。何しろメモリが少ないので、ProFTPDも使うときだけ稼働させ、使い終わったらすぐに停止させる運用をおこなっています。工夫してもどうにもならないこともあります。gphoto2で操作できるカメラを持っているので、試しにgphoto2パッケージをインストールし、gphoto2コマンドを引数なし起動してみたのですが、それだけでスラッシング状態に陥りました。カメラの遠隔操作は諦めました。WLA-G54でできることの限界を知った気がします。
(2014-10-23追記)このほどアプリケーション用のwebサーバをWLA-G54から無線LANで繋がった向こう側のネットワーク上にある[[%%%Raspberry Pi%%%>internet-ir-aircon-raspberry-pi]]に移しました。WLA-G54の役割は、ネットワークの向こう側との通信が生きているかどうかをチェックして異常な場合は無線LAN子機を再起動した上で通知メールを送信することだけになりました。そうすると定期的にリブートする必要がなくなりました。thttpdがメモリ・リークしていた可能性が高いです。無線LAN子機を再起動する方法ですが[[%%%こちら%%%>network-io_on_universal_circuit_board]]の2番機をネットワーク経由で操作することでおこなっています。USB接続のIOの動作確認も済んでいるんですがそれは使っていません。

* 設定室温に達すると冷房をつけた上で携帯電話にメールを送信するPerlスクリプトのカスタマイズ版 [#zb02e440]
[[%%%こちら%%%>internet-ir-aircon#check_and_warning_sendmail]]の改良版です。変更内容はリトライ処理の追加と英語化です。リトライ処理は、経路を11aから11nに変更したところ数日に一度程度接続不良が起きるようになったので追加しました。英語化は、メモリ使用量を減らし、スワップを出来るだけ使用しないようにする為です。ちなみに[[CGI>internet-ir-aircon#web_interface]]の方は日本語のままです。[[CGI>internet-ir-aircon#web_interface]]の方には文字コード変換処理がないからです。
''ダウンロード''  &ref(en.check_and_warning_sendmail.pl,nolink);
 #!/usr/bin/perl
 
 # このスクリプトはEUC-JPで保存されている必要があります。
 
 # Debian, Ubuntu系の場合の追加インストールが必要なパッケージ
 # libnet-smtpauth-perl libjcode-pm-perl libwww-perl 
 
 use Net::SMTP_auth;
 #use Jcode;
 #use Encode;
 #use LWP::Simple;
 use LWP::Simple qw($ua get);
 $ua->timeout(10);
 
 
 $smtpserver = 'smtp.hoge.ne.jp:587';               # SMTP認証でアクセスするサーバ
 $smtpacount = 'fugafuga@hoge.ne.jp';               # SMTP認証用のアカウント
 $smtppasswd = 'SECRET';                            # SMTP認証用のパスワード
 $myrealmailaddress = 'fugafuga@hoge.ne.jp';        # 自分の本当のメールアドレス
 $tomailaddress1 = 'foobar@docomo.ne.jp';           # 宛先アドレス
 $tomailaddress2 = 'foobar@hoge.ne.jp';             # 宛先アドレス
 $bccmailaddress = $smtpacount;
 $fromaddress = 'remotecontroleradmin@dummy.com';   # 宛先側で個別の受信設定をおこな
                                                    # えば実在しないアドレスも可
 $remoteaddress="192.168.1.9";                      # PICNICのアドレス
 $limittemp = 34;                                   # メールを送信し始める室温(摂氏)
 
 ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time);
 #$nowdate = sprintf("%d年%d月%d日 %d時%d分%d秒", $year + 1900, $mon +1, $mday,
 $nowdate = sprintf("%d-%02d-%02d %02d:%02d:%02d", $year + 1900, $mon +1, $mday,
  $hour, $min, $sec);
 
 
 for(my $i=1;$i<=6;$i++){
 	for(my $j=1;$j<=6;$j++){
 		$html = get ("http://$remoteaddress/");
 		if ( $html ne '' ){ last; }
 	}
 
 	if ( $html eq '' ) {
 		&make_smtp_error_msg();
 		mailsend();
 		exit;
 	}
 
 
 	# 室温
 	$html =~ />(\d+) Celsius</;
 	$Celcius=$1;
 
 	$port='RB4';
 	# RB4(冷房ボタン用ポート)の現在値の反対
 	$opposite_level=&get_opposite_level($port);
 
 
 	if ( $Celcius >= $limittemp ) {
 
 		$html = get ("http://$remoteaddress/modify.cgi\?$port=$opposite_level");
 		if ( $html eq '' ){ next; }
 
 		#$Subject="室温が$Celcius度です。冷房をつけました。";
 		#$Body="$nowdate\n室温は現在$Celcius度です。\nたった今、冷房をつけました。";
 		$Subject="The room temperature is $Celcius celcius. Just now, I've turned on AC.";
 		$Body="$nowdate\nThe room temperature is $Celcius celcius,now.\nJust now, ".
                      "I've turned on AC.";
 		mailsend();
 
 		exit;
 	}
 }
 
 if ( $html eq '' ) {
 	&make_smtp_error_msg();
 	mailsend();
 	exit;
 }
 
 sub mailsend {
 $smtp = Net::SMTP->new("$smtpserver");
 #$smtp->auth('CRAM-MD5', "$smtpacount", "$smtppasswd");
 $smtp->auth("$smtpacount", "$smtppasswd");
 
 $smtp->mail("$myrealmailaddress");
 $smtp->to("$tomailaddress1","$tomailaddress2");
 $smtp->bcc("$bccmailaddress");
 
 #&Jcode::convert($Subject, 'jis', 'euc');
 #&Jcode::convert($Body, 'jis', 'euc');
 
 $smtp->data();
 $smtp->datasend("From:$fromaddress\n");
 $smtp->datasend("To:$tomailaddress1\n");
 $smtp->datasend("To:$tomailaddress2\n");
 #$smtp->datasend("Subject:".encode('MIME-Header-ISO_2022_JP', $Subject)."\n");
 $smtp->datasend("Subject:$Subject.\n");
 $smtp->datasend($Body);
 $smtp->dataend();
 $smtp->quit;
 
 return;
 }
 
 sub get_opposite_level {
 $word = $_[0];
 $htmlw = $html;
 $htmlw =~ /$word([^ ]+) ([^ ]+) ([^ ]+).*</;
 $ret = $3;
 $ret =~ s/High/L/;
 $ret =~ s/Low/H/;
 return $ret;
 }
 
 sub make_smtp_error_msg {
 #$Subject="コントローラにアクセスできません。";
 #$Body="$nowdate\nコントローラにアクセスできません。\n電源等を確認して下さい。";
 $Subject="Cannot acccess the AC controler";
 $Body="$nowdate\nCannot acccess the AC controler.\nCheck the power supply, etc.";
 }

* samba2 [#k5c85c97]
"一応"、[[Slim Samba2:http://www.dd-wrt.com/wiki/index.php/Slim_samba2]]を使っています。いくら大容量スワップがあっても、所詮USBメモリですから書き込み用途であまり頼りにすることはできません。したがってメモリイーターのsamba3はとても使う気にはなりません。
#br
繰り返しになりますが"一応"、samba2を使っているんですが、実際には月に何度か小ファイルを書き込む程度で大して使っていません。当初から"とりあえず立ててみよう"程度の意識でした。
#br
ダウンロードしたそのままの[[Slim Samba2:http://www.dd-wrt.com/wiki/index.php/Slim_samba2]]は日本語環境で安定して動作する為のパッチがあたってないので、扱うファイル名によっては簡単に落ちます。使える文字にも制限があります。
#br
しかし使用頻度が頻度だけに、当面セルフコンパイルする気は全くありません。代わりにクーロンに「[[samba2が落ちていたら再起動するスクリプト>#watch-samba]]」を仕込んでいます。

&aname(watch-samba);
* samba2が落ちていたら再起動するスクリプト [#c13f2ca7]
[watch-samba.sh]
 #!/bin/sh
 PROCESSNUM=`ps|grep smbd|wc -l`
 if test $PROCESSNUM -le 1; then
 export PATH=/opt/bin:/opt/sbin:/opt/usr/sbin:/opt/usr/bin:/bin:/usr/bin:/sbin:/usr/sbin
 unset LD_LIBRARY_PATH
 date >> /tmp/samba-restart-time
 /opt/etc/init.d/S80samba start
 fi

* 長期運用する場合に定期的に必要な作業 [#c07004f1]
(2015-3-31追記)
[[%%%OneCD Linux%%%>onecddebian#h3_content_1_17]]を長期運用すると細かな問題が発生したりしますが、このページのようにUSBメモリを主要なストレージとしたサーバにも、長期運用時に発生しがちな問題があります。
一般向けのUSBメモリのデータ保持期間はあまり長くないからです。現在使用しているUSBメモリも1年余り使用した段階で読み取りエラーを発見しました。そこで、一旦全データの再書き込みをおこないました。今後は念のため半年に一度程、全データバックアップ及び再書き込みをおこないたいと思っています。

#br
* ご要望、ご意見、質問を下のフォームにどうぞ&br;(でもここより、[[掲示板>board]]や[[書き込みフォーム>form]]のページに書いて頂いた方が気づき易いと思います。) [#i343babf]
#areaedit(nofreeze,noauth,btn:[修正(書き間違った場合にご利用下さい)])
- グレイト! -- [[foo]] &new{2014-10-09 (木) 08:50:07};

#comment
#areaedit(end)