USB無線LANをLinuxで動かせるようにしてみた

ルーターから離れた場所(別の階)にサーバーを置きたいがために、無線LANを使えるようにしました。
あまりにも苦労したのでメモ。
Linux無線LAN使うのってこんなに大変なのね・・・orz

環境

OS: Ubuntu Server 10.04
WLAN: Planex GW-US54GXS(USB無線LAN)


[参考]

繋いでみた

まずは何も考えずに繋いでみます。
USBにブスッっと刺します。

$ dmesg
[83346.220015] usb 2-1: new high speed USB device using ehci_hcd and address 4
[83346.370913] usb 2-1: configuration #1 chosen from 1 choice
[83346.428741] cfg80211: Calling CRDA to update world regulatory domain
[83346.553660] cfg80211: World regulatory domain updated:
[83346.553663]  (start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp)
[83346.553667]  (2402000 KHz - 2472000 KHz @ 40000 KHz), (300 mBi, 2000 mBm)
[83346.553670]  (2457000 KHz - 2482000 KHz @ 20000 KHz), (300 mBi, 2000 mBm)
[83346.553674]  (2474000 KHz - 2494000 KHz @ 20000 KHz), (300 mBi, 2000 mBm)
[83346.553677]  (5170000 KHz - 5250000 KHz @ 40000 KHz), (300 mBi, 2000 mBm)
[83346.553680]  (5735000 KHz - 5835000 KHz @ 40000 KHz), (300 mBi, 2000 mBm)
[83346.650018] usb 2-1: reset high speed USB device using ehci_hcd and address 4
[83346.819365] phy0: Selected rate control algorithm 'minstrel'
[83346.820115] zd1211rw 2-1:1.0: phy0
[83346.820142] usbcore: registered new interface driver zd1211rw

dmesgを見てみると、こんな感じで認識されました。
この時点で、zd1211rwというドライバが既に認識されてるようです。

$ lsusb
Bus 002 Device 004: ID 2019:5303 PLANEX GW-US54GXS 802.11bg

lsusbというコマンドでUSBのデバイス情報をとることができるみたいです。
ちゃんと認識してますね。


ただ、色々ググってみるとこれだけではダメらしく、この無線LANバイスを使うためにはひと工夫しなきゃだめだそうです。
(もしかするとこのままでも使えるかもしれないですが未検証なので。。。)
というわけで、ドライバを手動で再構築してみます。

カーネルソースを準備

$ sudo aptitude install linux-source

これで現在動いてるバージョンのLinuxカーネルソースコードがダウンロードされます。
このソースは /usr/src に書庫形式で落とされます。

$ cd /usr/src ←移動
$ sudo tar xvfj linux-source-2.6.32.tar.bz2 ←解凍
$ cp -r /usr/src/linux-source-2.6.32/drivers/net/wireless/zd1211rw ~/ ←ドライバのソースをホームフォルダにコピー

ソースコードの修正

一応パッチファイルを作ったので、面倒な人は以下をホームフォルダにコピペしてパッチファイルを作ってください。
2行だけの修正なので別に手動でやっても問題はないです。

  • ~/zd1211rw_2.6.31.patch
diff -Naru zd1211rw.org/zd_mac.c zd1211rw/zd_mac.c
--- zd1211rw.org/zd_mac.c       2010-06-28 19:12:20.419975222 +0900
+++ zd1211rw/zd_mac.c   2010-06-28 19:13:12.819974415 +0900
@@ -42,6 +42,7 @@
        { ZD_REGDOMAIN_ETSI, "DE" }, /* Generic ETSI, use most restrictive */
        { ZD_REGDOMAIN_JAPAN, "JP" },
        { ZD_REGDOMAIN_JAPAN_ADD, "JP" },
+       { ZD_REGDOMAIN_JAPAN_3, "JP" },
        { ZD_REGDOMAIN_SPAIN, "ES" },
        { ZD_REGDOMAIN_FRANCE, "FR" },
 };
diff -Naru zd1211rw.org/zd_mac.h zd1211rw/zd_mac.h
--- zd1211rw.org/zd_mac.h       2010-06-28 19:12:20.419975222 +0900
+++ zd1211rw/zd_mac.h   2010-06-28 19:13:50.219975209 +0900
@@ -193,6 +193,7 @@
 #define ZD_REGDOMAIN_FRANCE    0x32
 #define ZD_REGDOMAIN_JAPAN_ADD 0x40
 #define ZD_REGDOMAIN_JAPAN     0x41
+#define ZD_REGDOMAIN_JAPAN_3   0x49

 enum {
        MIN_CHANNEL24 = 1,

パッチファイルでやる人はパッチを当てます。

$ cd ~/zd1211rw
$ patch -p1 < ../zd1211rw_2.6.31.patch

Makefileの修正

obj-m += zd1211rw.o

zd1211rw-objs := zd_chip.o zd_mac.o \
        zd_rf_al2230.o zd_rf_rf2959.o \
        zd_rf_al7230b.o zd_rf_uw2453.o \
        zd_rf.o zd_usb.o

KDIR    :=/lib/modules/$(shell uname -r)/build
PWD     := $(shell pwd)
MDIR    :=/lib/modules/$(shell uname -r)/kernel/drivers/net/wireless/zd1211rw/
MNAME   :=zd1211rw.ko
MNAME_BK:=zd1211rw.ko_backup

all:
        $(MAKE) -C $(KDIR) M=$(PWD) modules

clean:
        $(MAKE) -C $(KDIR) M=$(PWD) clean

install:
        mv $(MDIR)$(MNAME) $(MDIR)$(MNAME_BK)
        cp $(PWD)/$(MNAME) $(MDIR)
        depmod -a $(shell uname -r)

uninstall:
        mv $(MDIR)$(MNAME_BK) $(MDIR)$(MNAME)
        depmod -a $(shell uname -r)

あとはいつも通り。

$ make
$ sudo make install

makeでエラーの出る人は、Makefileがきっと違います。
行頭空白は、スペースじゃなくてタブなので注意してください。


これで無線LAN自体は動くようになったはず。
USB無線LANを刺してある状態で、

$ sudo ifconfig wlan0 up ←wlan0の起動
$ ifconfig ←動いてるNICの状態確認
$ iwconfig ←ワイヤレスのNICの状態

などしてあげて、動いてることを確認すればおk。

wlanの自動起動とホットプラグの設定

ここに一番手こずりました。
思考錯誤の結果をまとめ直してるので、合ってるかどうか不安です。
[参考]

今回はUSB無線LANを使ってるので、ドングルを刺したら無線LANで接続し、ドングルを抜いたら無線LANを落とすように設定したいと思います。
Windowsみたいに2つのネットワークの生きてるほうを使う、というアバウトな設定ができなかったので。。。(涙
分かる人は逆に教えてください。


まずは以下のファイルを編集します。

  • /etc/network/interfaces
# Wireless network interface
auto wlan0 ←起動時に自動起動させるため
allow-hotplug wlan0 ←ホットプラグ対応?抜き差ししたときに何かのシグナルが出るらしい。
iface wlan0 inet static ←今回は固定IPで設定します
        address 192.168.1.101
        netmask 255.255.255.0
        network 192.168.1.0
        broadcast 192.168.1.255
        gateway 192.168.1.1
        dns-nameservers 192.168.1.1
        wpa-driver wext 無線LANの暗号化に関する設定
        wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf ←パスキー等の設定ファイル
        up ifconfig eth0 down ←デバイスが有効にされたときに動かすコマンドの設定
        down ifconfig eth0 up ←デバイスが無効にされたときに動かすコマンドの設定

こんな感じでwlan0の設定を追加します。
特に大事なのが最後の2行。
これを書くことで、ifup/ifdownされたときに、upとdownで指定されたコマンドを実行します。
ifup wlan0をされるとeth0を落として、
ifdown wlan0をされたらeth0を復活させます。


次に暗号化設定のファイルです。
今回はWEP暗号方式なので以下の感じです。

  • /etc/wpa_supplicant/wpa_supplicant.conf
ctrl_interface=/var/run/wpa_supplicant ←決まり文句らしい

network={
        ssid="corega" ←無線のESS-IDを指定します
        key_mgmt=NONE ←今回はWEP暗号なので、ここはNone(まだWEP使ってるんだーとか言うなっ!)
        wep_key0=************ ←WEPキーを入力、ここは各自で。 
        wep_tx_keyidx=0 ←どのインデックスキーを使うかの指定
}

ちなみにファイルにはパスフレーズが入ってたりするので、パーミッションを600にしておくこと。

$ sudo chmod 600 /etc/wpa_supplicant/wpa_supplicant.conf

[参考]

WPAとかの場合は上の参考リンクを見てください。
うちもそろそろWEPから変更しなきゃダメですね。。。

デーモン再起動

最後に設定変更を有効にしましょう。

$ sudo /etc/init.d/networking restart


はい、これで設定は一通り完了しました。
これでwlan0かeth0かのどっちかだけが動くようになります。
なので、うちの環境ではwlanとethで同じIPに設定しました。これでSSHとかで繋いでても接続し直しせず自働復活できるはず。

補足

この設定で動くようになるまで相当苦戦したので、本当にあってるかどうかはわかりません。
もっといい方法があったら教えてください。
ついでにいくつかの補足資料と参考URLを載せておきます。

/etc/rc.localを利用して、有線ネットワークを変える方法を教わりました。

ifplugdを利用して、NICを監視して現在のネットワークに応じて設定を切り替えられるらしいです。
試してみたんですが、なかなかうまくいかなかったので、結局この設定は使わずじまいでした。

本来はWLANドライバを動かすためにファームウェアを用意するらしい。
でも今回は使わずに行けました。なんか間違ってるのかしら?


他にも多数のWebページを参考にさせてもらいました。
数々の参考情報に感謝します。
やっぱりLinuxでWLANするには情報が少なすぎてかなり苦戦しました。
誰かの何かの助けになれば幸いです。

余談

コンソール上でこんなツールがあるらしいです。

$ sudo aptitude install wavemon

余談2

Muninでwlan0も追加で監視したいときは、プラグインシンボリックリンクを追加すればいいだけ。

$ sudo ln -s /usr/share/munin/plugins/if_ /etc/munin/plugins/if_wlan0
$ sudo ln -s /usr/share/munin/plugins/if_err_ /etc/munin/plugins/if_err_wlan0
$ sudo /etc/init.d/munin-node restart

プラグイン本体を読んでみると、if_[NIC名]のようにすれば、そのデバイス名のデータを取りに行くらしい。
簡単に増やせて意外でした。