BSD

FreeBSDで Bluetooth Low Energy (BLE)を使う

いろいろと案件がありまして、LinuxやらほげほげやらいろんなものでBLEを使って調べ物をしていたのですが、これがなかなか期待通り動いてくれないんですよねぇ・・・いつものようにソースやらBluetooth4.0の仕様書(2000頁以上ある)などをいろいろ読み始めたのですが linuxの bleno -> Bluezという流れが複雑で実験環境すらままならないので使い慣れたFreeBSDで動かんものかとtwitterでつぶやいてみました。すると・・・

以外と近いところに解はあるんだなー。まさかフォロワーさんがCURRENTにコミットしてたとわ。 ということで手持ちのPCに最新のCURRENTをいれてセコセコ調査を始めた次第。

ちなみにドングルはこれ アイ・オー・データ機器 I-O DATA USB-BT40LE [Bluetooth4.0+EDR/LE準拠 USBアダプター]

ぱっと調べたところBroadcomの BCM20702を使ってるドングルはアイオーのこれしかないようなので無難に。あきばお~とかで安売りしているやつは地雷の可能性が大そうなのでやめました。

これをBSDに差してみるとこういうメッセージが出ます

Sep 10 10:45:01  kernel: WARNING: attempt to domain_add(netgraph) after domainfinalize()
Sep 10 10:45:06  kernel: ugen0.3: <Broadcom Corp> at usbus0
Sep 10 10:45:06  kernel: ubt0: <Broadcom Corp BCM20702A0, rev 2.00/1.12, addr 3> on usbus0
Sep 10 10:45:06  kernel: WARNING: attempt to domain_add(bluetooth) after domainfinalize()

何やらwarningは出ますがとりあえず使えそう…… ngctl listで見ると

 # ngctl list
There are 8 total nodes:
  Name: ubt0            Type: ubt             ID: 00000002   Num hooks: 1
  Name: btsock_hci_raw  Type: btsock_hci_raw  ID: 00000003   Num hooks: 1
  Name: btsock_l2c_raw  Type: btsock_l2c_raw  ID: 00000004   Num hooks: 1
  Name: btsock_l2c      Type: btsock_l2c      ID: 00000005   Num hooks: 1
  Name: btsock_sco      Type: btsock_sco      ID: 00000006   Num hooks: 0
  Name: ubt0hci         Type: hci             ID: 00000008   Num hooks: 3
  Name: ubt0l2cap       Type: l2cap           ID: 0000000c   Num hooks: 3
  Name: ngctl714        Type: socket          ID: 00000012   Num hooks: 0

hccontrolでスキャンをしてみます。BLE対応の接続先が必要ですが、iOSでlightBlueをつかって立てました

# hccontrol le_enable enable
# hccontrol le_set_scan_param passive 10 10 public all
# hccontrol le_set_scan_enable enable

結果は近傍キャッシュから読めました

# hccontrol read_neighbor_cache
BD_ADDR           Features                Clock offset Page scan Rep. scan
XX:XX:XX:XX:XX:XX 00 00 00 00 00 00 00 00            0         0         0

今回はここまで

Posted by issei

Category : BSD

FreeBSDのオリジナルのpkgサイトを作る

標準のオプションでコンパイルしていないportsを利用しているときとか自分専用のpkgサイトがあると便利ですよね。例えば弊社ではDOVECOT2のオプションをONにしてpostfixをビルドしています。その作り方をかなり前に社内の掲示板に書いたのですが、それをブログに転載します。

STEP1

普通にportsからpostfixをコンパイル、インストールする。

STEP2

pkgコマンドでpackageにする。

pkg -vv で ABIを確認しておくとVersion毎にディレクトリをわけなくてよいので楽。

とりあえず

/usr/ports/packages/FreeBSD:10:amd64

をパッケージの保存先とする。dovecot2,cyrus-sasl,pcreも依存しているのでいれておく

# pkg create -o /usr/ports/packages/FreeBSD:10:amd64 postfix

STEP3

レポジトリを作る

# pkg repo /usr/ports/packages/FreeBSD:10:amd64/

STEP4

ローカルファイルから持ってくるだけならこれで完成である

/usr/local/etc/pkg/repos/test.conf

というファイルに

test: {
  url: file:/usr/ports/packages/${ABI}
  enable: yes
  priority: 1
}

と書いておけばよい。pkg -vvで確認できる。その後

# pkg install -r test postfix

でインストールできることを確認できる。

# pkg install -rtest postfix
Updating test repository catalogue...
test repository is up-to-date.
All repositories are up-to-date.
The following 2 packages will be affected (of 0 checked):

New packages to be INSTALLED:
        postfix: 2.11.3_3,1 [test]
        dovecot2: 2.2.15_2 [test]

The process will require 27 MB more space.
5 MB to be downloaded.

Proceed with this action? [y/N]:

ネットワーク経由で持ってくる

man pkg.confによると URLは

http://, https://, ftp://, file://, ssh://

が使えるようである。SSHは

ssh: {
  url: ssh://user@ssh.example.com/usr/ports/packages/${ABI}
  enable: yes
  priority: 1
}

と書いておけばよい。httpもftpも同様。

ftp: {
  url: ftp://ftp.example.com/pub/packages/${ABI}
  enable: yes
  priority: 1
}

当然 sshや ftpのサーバをセットアップしておかないといけない

pkg+httpとは何ぞや?

デフォルトの設定 /etc/pkg/FreeBSD.conf
を覗くと、

url: "pkg+http://pkg.FreeBSD.org/${ABI}/latest",

と書いてある。これはDNSのSRVレコードを使って効率よく
ミラー等を利用するための記法である。drillや digコマンドを使って

# drill _http._tcp.pkg.freebsd.org. srv

と調べてみるとよいであろう。

署名を付ける

ここまでの手順で作成したものには署名がない。個人的に使う分にはこれでよいだろうが、
一般公開をするためには署名があったほうがよいであろう。
(もちろん署名があるだけでは不十分で通信そのものがSSLなどで保護されているべきである)
署名の方法は公開鍵とフィンガープリントの二種類用意されている。

opensslで公開鍵のペアを作り公開鍵を提示する手法。

% man pkg-repo

に詳しく書いてある。まず鍵を作成する

       % openssl genrsa -out repo.key 2048
       % chmod 0400 repo.key
       % openssl rsa -in repo.key -out repo.pub -pubout

repo.keyが秘密鍵で、repo.pubが公開鍵である。公開鍵はなんらか方法でクライアント(pkgを利用するサイト)に送っておく

次にその秘密鍵で署名をしてレポジトリを作成する

# pkg repo /usr/ports/packages/FreeBSD:10:amd64/ repo.key

クライアント側では設定ファイルに公開鍵のパスを指定する

test: {
  url: http://www.example.com/pub/packages/${ABI}
  enable: yes
  priority: 1
  signature_type: pubkey
  pubkey: /usr/local/etc/pkg/repos/repo.pub
}

FingerPrint

man pkg-repoを参考に署名をするためのscriptを作成する。
sign.shとでもして作成をしておく

       #!/bin/sh
       read -t 2 sum
       [ -z "$sum" ] && exit 1
       echo SIGNATURE
       echo -n $sum | /usr/bin/openssl dgst -sign repo.key -sha256 -binary
       echo
       echo CERT
       cat repo.pub
       echo END

その後

# pkg repo /usr/ports/packages/FreeBSD:10:amd64/ signing_command: ./sign.sh

を実行する。

インストールする側に署名ファイルを置いておく必要がある。ここでは

/usr/local/etc/pkg/repos

とし、その下に revokedと trustedというディレクトリを用意する。
fingerprintを

# sha256 -q repo.pub

で求めておき、truestedの下に適当なファイル名で

function: sha256
fingerprint: ae9f016190512cc2107f2555c070c5ab2bad1ef73a370edc96f1b1b18022cdc1

のように置いておく。

クライアント側の設定は以下のようにする。

test: {
  url: http://www.example.com/pub/packages/${ABI}
  enable: yes
  priority: 1
  signature_type: fingerprints
  pubkey: /usr/local/etc/pkg/repos
}
Posted by issei

Category : BSD

再起動するとさくらのVPSの時刻が9時間ずれる

いつからか分からないけれど(いや最初からかもしれませんが)、さくらのVPSはCMOSがJSTに合わせられているようで再起動すると9時間ずれてしまうことに気がつきました。 というわけで、

# touch /etc/wall_cmos_clock 

で解決。

Posted by issei

Category : BSD

FreeBSD DHCP6で Name Serverを自動設定する

request domain-name-servers;

をinteterfaceの設定に書くとDNSのサーバが降ってくるので、それをスクリプトをつかって/etc/resolv.confを書き換える

といった流れにするのがよいようです。もっとよいやり方があるのかもしれませんが・・・ちなみにname serversは $new_domain_name_serversでスクリプトから参照することができます。

/usr/local/etc/dhcp6c.conf:

interface tun2{
     send ia-pd 0;
     request domain-name-servers;
     script "/usr/local/sbin/iijmio6.script";        
};

id-assoc pd 0 {
        prefix-interface fxp0 {
                sla-id 1;
                sla-len 8;
        };
};

私は以下のようなスクリプトを書きました。

/usr/local/sbin/iijmio6.script:

#!/bin/sh

echo -n "" > /etc/newresolv.conf
if [ -n "$new_domain_name_servers" ] ; then
  for i in $new_domain_name_servers ; do
    echo nameserver $i >> /etc/newresolv.conf
  done
  mv /etc/newresolv.conf /etc/resolv.conf
fi

 

Posted by issei

Category : BSD

FreeBSDで DHCPv6でアドレスを配るときのメモ

rtadvdだけで配るのなら簡単なんですが、やはりちゃんと逆引きもさせたいよねー、とかなるとDHCPv6で配りたくなるというのが人情。その場合

  • RAの Managed address configuration flagと Other stateful configration flagのビットを立てる。
  • pinfoflagsは Autonomous address condifuration flagsを落とす。

の二つが必要なようですが、それは分かっても具体的な記述方法がよくわかりませんでした。これは、普通に10進数で /etc/rtadvd.confで raflagsに 192, pinfoflagsに 128を指定すればよいようです。

例)

fxp0:\
        :addr="2400:XXXX:YYYY:ZZZZ::":prefixlen#64:raflags#192:pinfoflags#128

これで、RAからのアドレスではなくDHCPv6サーバから取得したアドレスをクライアントが振るようになりました。

Posted by issei

Category : BSD

FreeBSD で IIJmioへ pppoe+DHCPv6で 接続するときのメモ

我が家のマンションもBフレッツからフレッツネクストになり、やっとIPv6接続が安価に可能になりました。IIJmioに限らずフレッツ網使ってる限り、pppoeで接続後にDHCPv6でプレフィックスが振り出されるというやり方は基本同じなので、他のプロバイダでも通用するでしょう。

DHCPv6が必要になるので、あらかじめ pkg から dhcp6を インストールしておきます。

# pkg install dhcp6

pppの設定

/etc/ppp/ppp.conf:

iijmiov6:
 set authname AUTHNAME@bnf6.iij.ad.jp
 set authkey AUTHKEY
 set device PPPoE:re0:pppoe-in
 enable lqr
 disable ipcp
 enable ipv6cp
 set cd 5
 set dial
 set login
 set redial 0 0
 set timeout 0
 set reconnect 10 20

AUTHNAME, AUTHKEY, deviceは適宜環境に合わせてください。 ipcpをdisableしてipv6cpをenableにするのがコツです。うまく設定できているかどうかは以下のコマンドで確認できます。

# ppp -unit2 iijmiov6
Working in interactive mode
Using interface: tun2
ppp ON peach> dial
ppp ON peach> Warning: deflink: Reducing configured MRU from 1500 to 1492
Ppp ON peach> 
PPp ON peach> Warning: ::/0: Change route failed: errno: No such process
PPP ON peach> 

pppがPPPになれば、リンクが確立したことになります。ここで、ワーニングが出ますが、これを消す方法があるのかどうかは不明です。別に出てもちゃんと動くようなので気にしないようにしました。

この状態では、リンクがつながってもIPアドレスも振られてなければdefault rotueも設定されていないので、まだIPv6で通信はできません。これらを自動で取得するためにpppを一旦終了し、次のような設定ファイルを書きます。

/etc/ppp/ppp.linkup:

iijmiov6:
  ! sh -c "/usr/local/sbin/dhcp6c tun2"
  ! sh -c "route -6 add default -iface tun2"

/etc/ppp/ppp.linkdown:

iijmiov6:
  ! sh -c "route -6 delete default"
  ! sh -c "kill `cat /var/run/dhcp6c.pid`"

/usr/local/etc/dhcp6c.conf:

interface tun2{
        send ia-pd 0;
};

id-assoc pd 0 {
        prefix-interface fxp0 {
                sla-id 1;
                sla-len 8;
        };
};

dhcp6c.confの fxp0等は適宜読み替えてください。

やってることはなんということはなく、リンクが確立したら

/usr/local/sbin/dhcp6c tun2
route -6 add default -iface tun2

が順番に実行されるだけです。設定段階では上記コマンドを手動でタイプしてちゃんと動いているかどうか、設定に間違いがないかどうか確認するとよいでしょう。特にdhcp6cは間違いやすいので -D -f オプションをつけて実行すると捗るのではないかと思います。

ちなみに dhcp6c.confの意味ですが、プロバイダから振り出されたプレフィックスに 8ビット足してその部分を1にしたものがfxp0にIPv6アドレスとして振るという設定です。IIJmioからは /56でIPv6アドレスが振り出されるので結果/64のアドレスがfxp0に振られます。

うまく動いているようでしたら、起動時に自動で実行されるよう /etc/rc.confに以下の行を追加します

ppp_enable="YES"
ppp_profile="iijmiov6"
ppp_mode="ddial"
ppp_iijmiov6_unit="2"
ppp_iijmiov6_nat="NO"

これで

# /etc/rc.d/ppp start

でIPv6アドレスが振り出されていれば成功です。

 

 

Posted by issei

Category : BSD

IntelのNUC(DN2820FY)のファームを更新したらFreeBSD-CURRENTが起動しなくなった

imagejpg

IntelのNUC(DN2820FY)のファームをFY0041.BIOからFY0048.BIOにしたところ起動しなくなりました(UEFI経由)。

写真のように

elf64_exec: ExitBootServices() returned 0x8000000000000002

とか表示されて起動がとまってしまいます。少しづつファームを戻していったところFY0045.BIOでは起動することまでは確認しました。UEFI経由で起動しなければいいだけどいう話もありますが、その場合はパーティションがMBRでないと起動しないので、それもどうかと思いますし・・

調べて見るとこの問題はFreeBSDのUEFI wikiに Knwon Issues としてかかれていて

0x8000000000000002 is EFI_INVALID_PARAMETER and indicates that MapKey is incorrect - i.e., that the memory map has changed between the last call to GetMemoryMap and ExitBootServices. The main issue with real hardware fixed in r258754. This issue is still encountered on some hardware.

とります。ファームのバージョンアップで some hardwareに属してしまったぽいです。

このr258754の修正を見てみると printfの位置をずらしているだけで(printfがあるせいでメモリマップが変わってしまうというもののようで、しかも今現在CURRENTには取り込まれていないようなので、この修正を手動であててみれば起動するやもしれません。

Posted by issei

Category : BSD

pkg searchが使えなくなった

search しても何も帰ってこない。というかinstallもできない。

そこで ls -l /var/db/pkg/repo-FreeBSD.sqlite

を見てみると

-rw-r--r--  1 root  wheel      54272  2月  5 09:49 /var/db/pkg/repo-FreeBSD.sqlite

とあからさまにファイルのサイズが小さいようです。どうもぶっ壊れたもよう。

sqlite3を起動して select name from packages;とかやっても何も帰ってきません。

強引に更新するほうほうが分からなかったのでrepo-FreeBSD.sqliteを削除。その後

pkg searchなど実行したら

-rw-r--r--  1 root  wheel  43327488  2月  5 03:41 /var/db/pkg/repo-FreeBSD.sqlite

となり正常になりました

Posted by issei

Category : BSD

freebsd-updateでjailをupgradeする

ググると結構面倒な方法でupgradeしている人が多いのでメモがてら。

例えば母艦が10.1で、jailが10.0の場合、母艦側で

# freebsd-update -b /jails/hogehoge -r 10.1-RELEASE upgrade

とかやっても

freebsd-update: Cannot upgrade from 10.1-RELEASE to itself

というエラーが出てupdateできません。これは環境変数をいじくってunameの出力をごまかしてやることで解決できます。

# setenv UNAME_r 10.0-RELEASE

とすれば自分自身が10.0-RELEASEに見えるので、(uname -rで出力を確認できる)その状態で

# freebsd-update -b /jails/hogehoge -r 10.1-RELEASE upgrade

を実行すれば jailがupgradeされます。その後

# freebsd-update -b /jails/hogehoge  install

を実行すると

Installing updates...
Kernel updates have been installed.  Please reboot and run
"/usr/sbin/freebsd-update install" again to finish installing updates.

のようにrebootしろと出ますが、これは

# unsetenv UNAME_r 10.0-RELEASE

とするだけでok。これで10.1-RELEASEにバージョンがあがったように見えます。その後何食わぬ顔で

# freebsd-update -b /jails/hogehoge  install

を再び実行してやればokです

Posted by issei

Category : BSD

IntelのNUCでUEFIからFreeBSDを起動させる

今迄業務でDebianを入れていたIntelのNUC(DN2820FYKH)にFreeBSD-10.1を入れてみました。

このマシンは発売当初から結構クセがあってBIOSのバージョンをアップデートしたり、設定しなおしたりで、なんとかDebianを動かした記憶があるので(具体的に何をしたかは忘れました)今回も苦労するだろうなぁと思ったらやっぱりその通りでした。以下そのメモです

まず、BIOSは現時点での最新のものをもってきました。

FY0041.BIO

というやつです。ググって見ると古いほうが安定してるとかいろんな情報がありますが一々確認してられないのでとりあえず最新のにしました。設定もとりあえずBIOSのデフォルトに。

次に 起動imageをもってきます。USBメモリからの起動が楽だと思います。10.1からはUEFIからの起動イメージがあるんでそれを持ってきました。

ftp://ftp6.jp.freebsd.org/pub/FreeBSD/ISO-IMAGES-amd64/10.1/
ftp://ftp6.jp.freebsd.org/pub/FreeBSD/ISO-IMAGES-amd64/10.1/FreeBSD-10.1-RELEASE-amd64-uefi-mini-memstick.img.xz

xzを解凍してからusbメモリに焼きます。このUSBから起動してインストールをすすめていくとUEFIから起動するようにパーティションが切られてセットアップが完了するはず……なんですが、あっさりとはいきませんでした

ブートする途中でコケてしまうんですよね。ちなみに非UEFIバージョンのイメージではちゃんと起動します。これで起動してLiveCDに移行して gpart等でパーティションを作ってインストールするという手段をとるとインストールはできましたが、OSの再起動で同じことがおきます。詰み。 さてどうしたものかと、試行錯誤的を繰替えしていたところ

Booting [/boot/kernel/kernel] in 10 seconds...

とカウントダウンが始まったら適当なキー(スペースとか)を押して止めて

mode 2
boot

とタイプして画面のモードを切りかえてbootすればうまく行くことにきがつきました。あとはインストーラが起動するのでそれに従っていきます。diskパーティションは Auto(UFS)を選択すればUEFIから起動するようにパーティションが自動で設定されます。

インストールが終わってHDDから起動するときもbootの途中で止めて、

mode 2
boot

をタイプします。毎回こんなことをしてられないので

/boot/loader.rc.local

というファイルを作成し

mode 2

と書いておけば次から自動でmodeが切り替わります。まぁまだ

Root mount waiting for: usbus0
ugen0.3: <Logitech> at usbus0
Root mount waiting for: usbus0
usb_alloc_device: set address 4 failed (USB_ERR_TIMEOUT, ignored)
Root mount waiting for: usbus0
usbd_setup_device_desc: getting device descriptor at addr 4 failed, USB_ERR_TIMEOUT

とか妙な警告がでますが・・・これについてはこれから調査。

Posted by issei

Category : BSD