YAMAHAルーターにMACフィルタを行うマクロを作った備忘録

##要件
マクロはTeraterm向け。
接続、静的フィルタ再作成、フィルタ適用、切断を行う。
上記を対象複数ルーターで行う。

あまりこの手の案件はなく忘れそうなのでメモしておく。


##要点

###Teratermマクロの構文

####よく使いそうなもの

```javascript
//;カレントディレクトリ取得
getdir BASE_DIR

//;文字列フォーマット
sprintf2 tmp '%s\%s.log' BASE_DIR 'tmp'
```

####配列

```javascript
//;宣言
strdim array 10

//;文字列型設定
array[i] = 'xxxx'

//;数値型設定
array[i] = 0
```
長さ固定で宣言する。アクセスはかぎ括弧指定。

####サブルーチン

```javascript
//;サブルーチン結果格納用変数
RESULT=''

//;呼び出し
call sublootin
messagebox RESULT 'debug'

・・・

//;サブルーチン定義
:sublootin

・・・(処理)
RESULT = '結果'

return
```
returnで制御が呼び出しに戻るが戻り価を返す仕組みはないのでグローバル変数に格納してあげる。BASICを思い出す。

####ファイル操作

```javascript
//;ファイルオープン　第四引数が1なら追記、0なら新規
fileopen handleConf conffile 0 1

//;1行単位の読込ループ
while 1
  //;1行読み込み
  filereadln handleConf confLine

  //;最終行検知
  if result then
    break
  endif

　・・（処理）・・

endwhile

//;ファイルクローズ
fileclose handleConf
```

最終行検知はfilereadlnを実行後にシステム変数resultに設定される。
この変数は他のコマンドを実行すると結果が上書きされてしまうため、間にコードを入れずに書く必要がある。

####文字列の長さチェック
```javascript
//;コマンド実行
strlen array[i]
if result>0 then
  長さが0より大きい場合に実行する処理
endif
```
これもstrlenコマンドを実行すると結果がシステム変数resultに設定される。

####文字列の比較
```javascript
//;コマンド実行
strcompare tmp 'xxxxx'
if result == 0 then
  変数の中身がxxxxxの場合に実行する処理
endif
```
これもstrcompareコマンドを実行すると結果がシステム変数resultに設定される。

####文字列の分割
```javascript
//;コマンド実行
strsplit tmp ','
array[0] = groupmatchstr1
array[1] = groupmatchstr2
array[2] = groupmatchstr3
array[3] = groupmatchstr4
array[4] = groupmatchstr5
```
strsplit コマンドを実行すると結果がシステム変数groupmatchstr1～に設定される。

###YAMAHAルーターへの設定

####準備編

```javascript
//;ルーターへの接続
sprintf2 connectCommand '%s:22 /ssh /2 /auth=password /user=%s /passwd=%s' host user pass
connect connectCommand
//;応答待機
wait '>'

//;コマンドを送る
sendln '実行コマンド'
//;応答待機
wait 'Password:'

//;切断
sendln 'exit'
disconnect 0
unlink
```
接続してコマンドを送って切断。
基本的にコマンドを送ったら返ってくるであろうもの、つまりプロンプト出力を待機することで同期をとる。

####MACフィルター設定編

```javascript
//;管理者権限になる
sendln 'administrator'
wait 'Password:'
sendln 'パスワード'
wait '>'

//;動作安定のためプロンプトをカスタマイズ
sprintf2 command "console prompt '%s'" PROMPT
sendln command

//;インターフェースに適用されている静的フィルターを解除
sendln 'no ethernet lan1 filter in 1 2 ・・・ 98 99 100'
wait PROMPT

//;静的フィルターをクリア
sprintf2 command 'no ethernet filter 1'
sendln command
wait PROMPT

//;許可する静的フィルターを再作成
sprintf2 command 'ethernet filter 1 pass-nolog 11:22:33:44:55:66'
sendln command 
wait PROMPT

//;許可以外を拒絶する静的フィルターを再作成
sprintf2 command 'ethernet filter 100 reject-log *'
sendln command
wait PROMPT

//;作った静的フィルターをインターフェースに適用
sprintf2 command 'ethernet lan1 filter in 1'
sendln command
wait PROMPT

//;変更した後のルーターの設定をダンプ
sendln 'show config'
wait PROMPT

//;変更内容の保存
sendln 'save'
wait PROMPT

//;管理者権限を抜ける
sendln 'exit'
wait PROMPT
```

####ログ出力
Teratermコマンドのログ出力はターミナルで受信したものをすべて出力してくれるので便利。ただし接続してから切断するまでの間しか使えない。
なので接続前の準備処理分はファイル操作コマンドで出すようにした。

```javascript
(マクロ開始)

//;全体ログ出力開始(新規作成)
sprintf2 MAINLOG_PATH '%s\%s.log' BASE_DIR MAINLOG_FILE
fileopen MAINLOGhandle MAINLOG_PATH 1 0

//;全体ログへの書き込み(タイムスタンプ付き)
getdate timestamp '%Y/%m/%d %H:%M:%S'
sprintf2 tmp '%s %s' timestamp __MESSAGE
strconcat tmp '\n'
strspecial tmp
filewrite MAINLOGhandle tmp

(初期処理～接続手前まで)

connect ・・・

//;ルーター別ログ出力開始(新規作成)
sprintf2 logfile '%s\%s.log' logOutputPath fileBaseName
logopen logfile 1 0

(接続中の処理)

disconnect 0
unlink

(後処理)

; 全体ログ出力終了
fileclose MAINLOGhandle

```

以上です。