2021年8月18日水曜日

openwrtのDNS portforwarding設定

 2021/06の中旬ごろから、家で使っているISPのDNSが、fc2.xxxの名前解決をしてくれなくなりました。
hostやdigコマンドで名前を引こうとすると、SERVFAILが発生してしまいます。

はじめは検閲の類かと思ったのですが、ISPとしてどうなのか、ということでお客様窓口に連絡してみました。
何度かのやり取りの後、問題が再現したので調査すると言われ、解消を待っているのですが、2ヶ月以上経過した現在でも、未だに解決したとの連絡がありません。
先方の技術の方からは、問題が解消するまでの間はGoogleのDNSを使って下さいというコメントもあったので、openwrtが動いているルータの設定を変えてみました。 

ちなみに、openwrtのDNS関連の設定は整理されておらず、かなりハマりました。

今回の問題を解決する方法としては、以下の2つのやり方があります。

(1) ルーターのDHCPで通知されるDNSのアドレスを、8.8.8.8と8.8.4.4に変更する。
(2) ルーターのDNS Forwarding先に8.8.8.8と8.8.4.4を設定する。

上記(1)は、DHCPクライアントが一定時間古いDNSアドレスを保持してしまい、設定が即時に反映されないやり方なので、(2)の方で対応したいと思います。

この設定は、openwrtのGUI(luci)上だけで設定可能です。

ログイン後、Netorkタブの「DHCP and DNS」→「General Setting」の「DNS forwardings」に8.8.8.8と8.8.4.4の2つを追加します。
ただ、これだけではダメで、「Resolv and Hosts Files」の「Ignore resolve file」のチェックを入れる必要があります。

後者は、ルーターが起動した際に自動的に生成されるresolv.confファイルを使わないという設定です。
resolv.confには、WAN側から通知されたDNSサーバーの情報が反映されるため、これを無視するという意味です。

どちらの設定もSave & Applyすれば、ルーターに問い合わせた名前解決が、指定した2つのDNSに転送され解決します。

参考までに、「Network」→「Interfaces」の「WAN」の「Edit」で遷移できる画面で、「Advanced Settings」の「Use DNS servers advertised by peer」
のチェックを外して指定できるDNSサーバーは、ルーター本体が名前解決をするために使うDNSの設定なので、(1)(2)のどちらにも対応しません。

もう少しわかり易く整理してくれればなと思います。

それにしても、いつになったら直るんだろう、某ISPのDNS。

2021年6月20日日曜日

Windows 10起動直後の長時間のディスクアクセスは、Windows Updateファイルが原因かも

 我が家には、第4世代のCore i7を搭載した、そこそこのスペックのデスクトップPCがあり、このPCのハードディスクにWindows 10をインストールして利用しています。
最近、Windows 10が起動直後にやたらとディスクアクセスし、かなり重たい状態が続くようになっています。

タスクマネージャを見ると、「WaasMedic Agent Exe」というプロセスが、ディスクにアクセスしているようです。

マイクロソフトのサポートによれば、Waasmedic agent exeは、Windows Updateの修復プログラムで、ウイルスではないので終わるまで待ってほしいとのことでした。

このWaasmedic agent exeは、調べてもあまり情報が出てこないのですが、働きとして、ディスクに保存された過去のWindows Updateのファイルの整合性をとることにあるようです。

Windows 10に限った話ではないのですが、Windows Updateのファイルは保存され、蓄積されていきます。
これは実際にシステムに更新されたファイルとは別に、更新用のパッケージと、更新前のファイルをバックアップしていくもので、Windows Updateを切り戻すときのために保存されています。

つまり、Windows Updateを切り戻さない限りは不要なファイルが、Windows Updateのたびに蓄積されていくわけです。

これが悪さをしているのではないかと思い、過去のWindows Updateのファイルを削除して変化がないか、試して見ることにしました。

やり方は非常に簡単で、Windows 10の起動後、エクスプローラーでWindowsがインストールされているディスクのプロパティを開き、全般のタブから「ディスクのクリーンアップ」を選択します。
その後、「システムファイルのクリーンアップ」を選択し、「Windows Updateのクリーンアップ」にチェックを入れ、「OK」を押してしばらく待ちます。

私の環境では、Windows Updateのファイルは8GB程度になっていました。
待つこと20分ぐらいで、ファイルはきれいさっぱり消えました。

改めて、Windows 10を再起動させてみましたが、ディスクアクセスは嘘のように消えて、非常に快適になりました。

もし、皆様も同じような現象に遭遇しているようでしたら、お試し下さい。

2021年5月7日金曜日

YAMAHA RTX1100のファームウェアを更新する

YAMAHA RTX1100という有線ルーターを中古で入手しました。

かなり古い製品で、3つあるいずれのLANポートとも100Mbpsまでの対応ですが、家庭向けの簡易的なルーターとは違い、3つのネットワークのルーティングができたり、内向きのDNS機能があったりと、なかなか高性能です。

また、YAMAHAの製品に対するサポートは非常に充実しており、販売終了して10年以上経つ商品についても、マニュアルやファームウェアをダウンロード提供しています。

こういう姿勢、非常に好感が持てますよね。

さて、このRTX1100ですが、中級者~上級者向けの製品なので、BUFFALOのルータみたいに、デフォルトでIPアドレスが振られていたりはしません。

また、設定はシリアルコンソールを通じて行う必要があります。

正確には、telnetやsshでもできるのですが、これらを有効にするために、シリアルコンソールで設定を行う必要があります。

まず、前のオーナーの設定が残っていると諸々問題があるので、工場出荷時の設定に変更します。

その後、ファームウェアを最新のものに更新します。

工場出荷時の設定に戻すには、背面のINITを爪楊枝で押したまま、電源を投入します。

その後、シリアルケーブル(クロス/インターリンク)でRTX1100とPCを繋ぎます。

PCでは、Tera Termなどを使ってRTX1100のシリアルコンソールにアクセスします。

シリアルの設定は以下の通りです。

Speed    : 9600bps
Data     : 8bit
Parity   : none
Stop Bit : 1bit
Flow Ctl : none

また、RTX1100はデフォルトではSJISの日本語のエラーメッセージを吐くので、Tera Termの設定で「漢字-受信」を「SJIS」に設定するのもお忘れなく。

本体が生きていれば、電源を投入すると、シリアルコンソールにメッセージが表示されます。

ENTERを押すと、ユーザのパスワードの入力を求められるので、何も入力せずに「ENTER」を押します。(デフォルトはパスワードなしです。)

続いて、本体のIPアドレスを設定します。

本体の動作にかかわる設定については、管理者モードに入る必要があります。

    administrator

と入力し「ENTER」を押すと、管理者のパスワードパスワードの入力を求められるので、何も入力せずに「ENTER」押します。(デフォルトはパスワードなし)

RTX1100には3つのLANポートがありますが、まずはLAN1(ハブ経由で4ポートあります)にIPアドレスを割り当て、TFTPでファームウェア更新ができるようにします。

    ip lan1 address 192.168.0.8/24
    tftp host 192.168.0.9
    save

これで、LAN1に192.168.0.8というIPアドレスが割り当てられます。

また、192.168.0.9からTFTPで更新するファームウェアの受け取りを許可します。

あとは、Windows10やUbuntu、FreeBSDなどからtftpコマンドでファームウェアをアップロードしてやればOKです。

Windows 10 64bitで使えるSCSIカードを求めて

 ふとしたことから、SCSI接続のMOドライブを使って、MOに記録されたデータを読み出したいニーズが出てきました。
SCSI規格は、2000年ごろは全盛だったのですが、今となっては失われたテクノロジーとなっています。

SCSI接続のデバイスを利用するには、SCSI-USB変換ケーブルや、PCI接続のSCSIカードに接続する方法があります。

ノートPCならば前者が必須ですが、入手性が非常に悪く、むしろUSB接続のMOドライブを探すほうが簡単です。
一方、デスクトップPCならば、前者のSCSI-USB変換ケーブルに加え、PCI拡張スロットがあれば、後者のSCSIカードを利用することができます。

SCSIカードの有名どころといえばAdaptecで、SCSIデバイスのメーカが動作確認・保証するのは決まってこのAdaptec製のSCSIカードでした。
しかし、Adaptec(現在はMICROCHIPの製造元であるMicrosemiの一部門になっている)のSCSIカードは、多くはWindows 7 32bitまでのドライバしか提供されておらず、64bit環境での利用は出来ません。

今メインで利用している、Windows 10 64bitがインストールされているPCで利用できるSCSIカードがないか、いろいろ探してみたところ、Symbios/LSILogic 53C8XXベースのSCSIカードはWindows 10 64bit環境で使えそうなのがわかってきました。

どうも、Dawicontrolというストレージメーカが、自社製のSCSIカードをWindows 10 64bitで使えるようドライバを書いてくれているようで、大変ありがたいことです。

Symbios/LSILogic 53C8XX、具体的には53C860、53C870、53C875、53C895あたりは、IO-DATA製のSCSIカードに多く採用されていました。
これらのSCSIカードは、過去多数流通しており、今でもメルカリなどで出品されていたりするので、試しに一つ入手して試すことにしてみました。

入手したのは、SC-UPCINというカードで、搭載しているのは「LSI 53C870」というチップです。
基板の刻印は「SC-UPCIN-1」となっていました。

DawicontrolのドライバはSCSI BIOSが有効になっているとリソースの競合が起こるため、これを無効化する必要があります。
IO-DATAのSCSIカードであるSC-UPCI、及びそのバリエーションには、だいたいジャンパーがあり、JP1にある2つのジャンパーを両方ともOPENにすることにより、SCSI BIOS(AT互換機用/PC-98用)を無効化出来ます。
(JP2は内蔵ターミネーターの有効/無効の設定で、AUTOを意味する1-2のまま変更しません。)

JP2を変更し、SCSI BIOSの無効化の設定をしたら、あとはSC-UPCINをデスクトップPCのPCI拡張スロットに挿し、SCSIデバイスを接続してからPC本体を起動させるだけです。

無事、

Daiwacontrol DC-2975U/2976UW SCSI Hostadapter

と認識されました。

 Windows 10 64bitは未署名のドライバを弾くのですが、このドライバはちゃんと署名されているようで、何もせずに適用されます。


Daiwacontrolには本当に感謝の言葉しかないですね。

2021年4月1日木曜日

headless firefoxがFreeBSD jail環境でcoreを吐く件

いくつかのWebページをチェックするために、firefoxをheadlessモードかつmarionetteで制御してクローラーとして使っています。
FreeBSDをインストールしたシステム上にjail環境を作り、その上でfirefoxを導入して動かしている感じです。

先日、firefoxを86.01あたりにpkg upgradeしたところ、firefoxが起動する度にcoreを吐くようになりました。
クローリング自体は無事に終わっているのですが、気持ち悪いのでいろいろ試行錯誤してみました。
結果、jail環境から/devへのアクセスを許可したことにより、問題が解消されました。

昔書いたまとめがありますので、ご参考まで。

ご参考までに、coreを吐いているのは、以下のメッセージが出ているあたりです。

Crash Annotation GraphicsCriticalError: |[0][GFX1-]: No GPUs detected via PCI (t=1.23038) [GFX1-]: No GPUs detected via PCI
Crash Annotation GraphicsCriticalError: |[0][GFX1-]: No GPUs detected via PCI (t=1.23038) |[1][GFX1-]: glxtest: process failed (received signal 11) (t=1.23147) [GFX1-]: glxtest: process failed (received signal 11)

比較のために、別の環境にFreeBSDを導入し、jailを介さずにfirefoxを起動したところ、メッセージは以下の通りでした。

Crash Annotation GraphicsCriticalError: |[0][GFX1-]: glxtest: libpci missing (t=7.06715) [GFX1-]: glxtest: libpci missing
Crash Annotation GraphicsCriticalError: |[0][GFX1-]: glxtest: libpci missing (t=7.06715) |[1][GFX1-]: No GPUs detected via PCI  (t=7.09677) [GFX1-]: No GPUs detected via PCI

初めは、firefoxのabout:configで、ハードウェアアクセラレーションを無効化したり色々試行錯誤したのですが、どうやってもPCIにGPUを探しにいく振る舞いを止めることはできませんでした。

仮想環境で動かすこともあるんだから、ハードウェアアクセラレーションを切ったら、PCI見に行くのは止めて欲しいです、ほんとに。

2020年8月2日日曜日

Raspberry pi 2とFreeBSDで7セグLED時計を作る - プログラミング編


の続きです。

前回まででRaspberry pi 2のFreeBSDの設定は、ハード・ソフトともに終了しました。
最後は、時計のプログラムを書いて終了です。
はじめはSPIを使って制御しようと思ったのですが、1つしかないSPIを使うのは勿体無いので、GPIOを4つ使うことにしました。

GPIOの制御はgpioctlを使ってもできるのですが、シェルスクリプトで時計を書くのはちょっと面倒なので、C言語で書くことにします。

C言語でのGPIOの制御の仕方は、gpio(3)のmanを見ると良いと思います。

サンプルコードはこんな感じです。
コンパイルには、libgpio.hとgpio.cが必要です。
FreeBSDのソースツリーから持ってくるか、以下から入手してください。


clock.c

#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/time.h>

#include "libgpio.h"

#define CLOCK_PIN_MOSI  (17)
#define CLOCK_PIN_SCLK  (27)
#define CLOCK_PIN_LATCH (23)
#define CLOCK_PIN_BLINK (24)

#define CLOCK_INTERRUPTION (20)

unsigned char iTable[256];

void CLOCK_initTable(void)
{
    for(int tCount1=0;tCount1<256;tCount1++)
    {
        iTable[tCount1]=0x00;
    }

    iTable['0']=0x3f;
    iTable['1']=0x06;
    iTable['2']=0x5b;
    iTable['3']=0x4f;
    iTable['4']=0x66;
    iTable['5']=0x6d;
    iTable['6']=0x7d;
    iTable['7']=0x27;
    iTable['8']=0x7f;
    iTable['9']=0x6f;
    iTable['C']=0x39;
    iTable['E']=0x79;
    iTable['G']=0x3d;
    iTable['H']=0x76;
    iTable['I']=0x06;
    iTable['J']=0x1e;
    iTable['L']=0x38;
    iTable['O']=0x3f;
    iTable['P']=0x73;
    iTable['T']=0x31;
    iTable['U']=0x3e;
    iTable['Y']=0x66;
    iTable['a']=0x77;
    iTable['b']=0x7c;
    iTable['c']=0x58;
    iTable['d']=0x5e;
    iTable['e']=0x7b;
    iTable['f']=0x71;
    iTable['g']=0x6f;
    iTable['h']=0x74;
    iTable['i']=0x05;
    iTable['j']=0x0d;
    iTable['l']=0x18;
    iTable['n']=0x54;
    iTable['o']=0x5c;
    iTable['p']=0x73;
    iTable['q']=0x67;
    iTable['r']=0x50;
    iTable['s']=0x6d;
    iTable['t']=0x78;
    iTable['u']=0x1c;
    iTable['y']=0x6e;
    iTable['=']=0x09;
    iTable['-']=0x40;
}

void CLOCK_sendChar(gpio_handle_t aHandle,unsigned char aChar)
{
    for(int tCount1=0;tCount1<8;tCount1++)
    {
        gpio_pin_low(aHandle,CLOCK_PIN_SCLK);

        if(iTable[aChar]&(0x80>>tCount1))
        {
            gpio_pin_high(aHandle,CLOCK_PIN_MOSI);
        }
        else
        {
            gpio_pin_low(aHandle,CLOCK_PIN_MOSI);
        }

        gpio_pin_high(aHandle,CLOCK_PIN_SCLK);
    }
}

void CLOCK_reflect(gpio_handle_t aHandle)
{
    gpio_pin_high(aHandle,CLOCK_PIN_LATCH);
    gpio_pin_low(aHandle,CLOCK_PIN_LATCH);
}

volatile sig_atomic_t iEFlag=0;

void signal_handler(int aSig, siginfo_t *aInfo, void *aCtx)
{
    iEFlag=1;
}

int main(void)
{
    gpio_handle_t tHandle;
    char tDateString[64];
    char tDateSecond;
    time_t tEpocMinites;
    struct timeval tCurrentTime;
    int tToggleCount;
    long tInterruption;

    struct sigaction tSASigAbrt,tSASigTerm;

    memset(&tSASigAbrt,0,sizeof(tSASigAbrt));
    memset(&tSASigTerm,0,sizeof(tSASigTerm));

    tSASigAbrt.sa_sigaction=signal_handler;
    tSASigAbrt.sa_flags=SA_SIGINFO;

    tSASigTerm.sa_sigaction=signal_handler;
    tSASigTerm.sa_flags=SA_SIGINFO;

    if(sigaction(SIGINT,&tSASigAbrt,NULL)<0)
    {
        exit(1);
    }

    if(sigaction(SIGTERM,&tSASigTerm,NULL)<0)
    {
        exit(1);
    }

    CLOCK_initTable();

    tHandle=gpio_open(0);

    gpio_pin_output(tHandle,CLOCK_PIN_MOSI);
    gpio_pin_output(tHandle,CLOCK_PIN_SCLK);
    gpio_pin_output(tHandle,CLOCK_PIN_LATCH);
    gpio_pin_output(tHandle,CLOCK_PIN_BLINK);

    gpio_pin_low(tHandle,CLOCK_PIN_MOSI);
    gpio_pin_low(tHandle,CLOCK_PIN_SCLK);
    gpio_pin_low(tHandle,CLOCK_PIN_LATCH);
    gpio_pin_low(tHandle,CLOCK_PIN_BLINK);

    tInterruption=(1000000/CLOCK_INTERRUPTION);
    tToggleCount=0;

    tDateSecond=0x00;

    while(1)
    {
        gettimeofday(&tCurrentTime,NULL);

        tEpocMinites=(time_t)tCurrentTime.tv_sec;

        strftime(tDateString,sizeof(tDateString),"%H%M%S",localtime(&tEpocMinites));

        if(tDateSecond!=tDateString[5])
        {
            tDateSecond=tDateString[5];

            if(tDateString[0]=='0')
            {
                tDateString[0]=0x00;
            }

            for(int tCount1=0;tCount1<6;tCount1++)
            {
                CLOCK_sendChar(tHandle,tDateString[tCount1]);
            }

            CLOCK_reflect(tHandle);

            gpio_pin_high(tHandle,CLOCK_PIN_BLINK);
            tToggleCount=0;
        }

        if(tToggleCount==(CLOCK_INTERRUPTION/2))
        {
            gpio_pin_low(tHandle,CLOCK_PIN_BLINK);
        }

        tToggleCount++;

        usleep(tInterruption);

        if(iEFlag)
        {
            for(int tCount1=0;tCount1<6;tCount1++)
            {
                CLOCK_sendChar(tHandle,0x00);
            }

            CLOCK_reflect(tHandle);

            gpio_pin_low(tHandle,CLOCK_PIN_MOSI);
            gpio_pin_low(tHandle,CLOCK_PIN_SCLK);
            gpio_pin_low(tHandle,CLOCK_PIN_LATCH);
            gpio_pin_low(tHandle,CLOCK_PIN_BLINK);

            gpio_close(tHandle);

            exit(1);           
        }

    }

    gpio_close(tHandle);

    return 0;
}

冒頭のdefineで設定しているのは、GPIOのピン番号です。
物理ピン番号ではなく、論理ピン番号(=BCMピン番号)ですので注意してください。

冒頭に制作したLED時計との接続は、以下の通りです。

Vcc       ----  物理ピン 4番
SDI       ----  物理ピン11番(GPIO 17)
CLK      ----  物理ピン13番(GPIO 27)
BLK      ----  物理ピン16番(GPIO 23)
LATCH ----  物理ピン18番(GPIO 24)
GND     ----  物理ピン 6番


このプログラムでは、論理ピン番号17、27のGPIOで、SPIをエミュレートしています。

大したことをしていないプログラムですので、読めばわかると思いますが、比較的わかりにくい部分だけ解説すると、

iTable                           7セグLED用のフォントデータ
CLOCK_sendChar   CLKに8クロックを出力して1文字分のコードを送る関数
CLOCK_reflect          LATCHに立ち上がりクロックを出力して、シフトレジスタに蓄積された文字を7セグLEDに反映させる関数

です。

mainでは、1/CLOCK_INTERRUPTION秒毎に現在の時間を取得し、前回の取得時から1秒進んでいた場合に、時計の再描画を掛けています。

やる気のないビルド用スクリプトもつけておきますので、これを使ってビルドしてください。

build.sh

#!/bin/sh

rm *.o

cc -c gpio.c
cc -c main.c
cc -o clock gpio.o main.o

特に問題なければ、clockという実行ファイルができるので、これを実行すれば7セグLED時計は動作するはずです。

2020年7月31日金曜日

Raspberry pi 2とFreeBSDで7セグLED時計を作る - ソフトウェア設定編



の続きです。

Raspberry pi 2にインストールした後の設定方法は、一般的なi386/AMD64のFreeBSDとほぼ同じです。

rootのパスワードの変更は以下のコマンドで行います。

passwd

Raspberry pi 2版のFreeBSDでは、予めfreebsdというユーザが作られているので、必要に応じてrmuserで削除します。

rmuser freebsd

私の環境では、/etc/rc.confに以下の記述を追記しています。

Raspberry piには標準でRTCが搭載されていない為、再起動するたびに時間がクリアされてしまうため、起動毎にntpdateで時計合わせをするようにしています。
また、標準のkeypmapはUS配列ですので、これを106キー日本語配列に設定しています。

keymap="jp.kbd"
ntpdate_enable="YES"
ntpdate_flags="-b NTPサーバのIPアドレス"

タイムゾーンをJSTに変更するには、以下のようにします。

cp -p /usr/share/zoneinfo/Asia/Tokyo /etc/localtime

これぐらいしておけば、あとはほぼ一般的なi386/AMD64版のFreeBSDと同じように使うことができると思います。