pslaboが試したことの記録

はてなダイヤリーからはてなブログに引っ越してきました

この日記は現在実行中の減量記録を含む個人的なメモとして始めましたが、最近はコンピュータやガジェット、ハック、セキュリティネタのほうがメインになっております。

はてなダイヤリー時代はカテゴリ分けが適当だったのですが、これはそのうち直します。


MTUを調べるスクリプト

ping で調べればよいのは知っているが、パラメータを手でいじりながら試すのはめんどくさい。だからスクリプトにしてみた。単純なスクリプトだとスタート時の値から順番に試すパターンになるけど時間がかかりすぎるわけで、その時間短縮のためにちょっとした工夫が入ってます。

また、MacOSLinux の両方で使えます。パラメータの揺らぎはスクリプト内で吸収しています。

#!/bin/bash
if [ $# -ne 1 ]; then
     echo "usage: $0 [target IP]"
    exit 1
fi

# 初期値、増分
mtu_start=800
mtu_delta=1

mtu_size=$mtu_start
mtu_error=0
retval=0

testcount=1

uname=$( uname )

pingopt="-q -M do -c 1 -s"
if [ "$uname" == "Darwin" ]; then
    pingopt="-t 1 -Q -q -D -c 1 -s"
else
    pingopt="-q -M do -c 1 -s"
fi

while [ 1 ]; do
    # ping で MTU をテストする。
    #ping -q -M do -c 1 -s $(( mtu_size - 28 )) $1 >/dev/null
    ping $pingopt $(( mtu_size - 28 )) $1 >/dev/null 2> /dev/null
    retval=$?

    datetime=$( date +"%Y/%m/%d %H:%M:%S" )
    if [ $retval -eq 0 ]; then
#    if [ $retval -eq 1 ]; then
        # 設定したMTUで ping が通る場合の処理。

        echo "datetime:$datetime    status:OK   MTU:$mtu_size"
        mtu_max=$mtu_size

        # MTU が通らない値が分かっている場合は
        # 通る値と通らない値の中間をテストする。
        # 通らない値が不明の場合はテスト区間を倍に広げる。
        if [ $mtu_error -ne 0 ]; then
            mtu_delta=$(( (mtu_max + mtu_error) / 2 - mtu_max ))
        else
            mtu_delta=$(( mtu_delta * 2 ))
        fi

        # 検査範囲が 0 に収束したら終了
        if [ $mtu_delta -eq 0 ]; then
            echo "result:$mtu_max"
            exit;
        fi
    else
        # 設定したMTUが通らない場合の処理。

        mtu_error=$mtu_size
        echo "datetime:$datetime    status:ng   MTU:$mtu_size"

        # 次のテストでは通る値と通らない値の中間をテストする
        mtu_delta=$(( (mtu_max + mtu_error) / 2 - mtu_max ))
    fi

    mtu_size=$(( $mtu_max + $mtu_delta ))
done


また、同じ処理をコマンドプロンプトで動く版で書いたのがこちら。

@echo off

if "%1" == "" goto ERROR

set mtu_start=800
set mtu_delta=1

set mtu_size=%mtu_start%
set mtu_error=0
set mtu_max=0
set retval=0

set testcount=1

:LOOP
	rem ping で MTU をテストする。
	rem 65536 以上の値は評価しない
	if %mtu_size% lss 65536 (
		set /A mtu_testsize="( mtu_size - 28 )"
		ping -f -l %mtu_testsize% -n 1 %1 | find "パケットの断片化" > NUL
		set /A retval=%ERRORLEVEL%

	) else (
		set /A retval=0
	)

	if not %retval% == 0 (
		echo status:OK	MTU:%mtu_size%
		set mtu_max=%mtu_size%

		rem MTU が通らない値が分かっている場合は
		rem 通る値と通らない値の中間をテストする。
		rem 通らない値が不明の場合はテスト区間を倍に広げる。

		if not %mtu_error% == 0 (
			set /A mtu_delta="(mtu_max + mtu_error)/2"
			set /A mtu_delta="(mtu_delta - mtu_max)"
		) else (
			set /A mtu_delta=%mtu_delta% * 2
		)

		if %mtu_delta% == 0 (
			echo result:%mtu_max%
			goto EOF
		)
	) else (
		set mtu_error=%mtu_size%
		echo status:ng	MTU:%mtu_size%

		set /A mtu_delta="(mtu_max + mtu_error)/2"
		set /A mtu_delta="(mtu_delta - mtu_max)"
	)

	set /A mtu_size=%mtu_max% + %mtu_delta%
	goto LOOP

:ERROR
echo usage: scan_mtu.bat [target IP]

:EOF

そして実行例はこちら。

$ ./scanmtu.sh 192.168.0.1
status:OK       MTU:1000
status:OK       MTU:1002
status:OK       MTU:1006
status:OK       MTU:1014
status:OK       MTU:1030
status:OK       MTU:1062
status:OK       MTU:1126
status:OK       MTU:1254
status:ng       MTU:1510
status:OK       MTU:1382
status:OK       MTU:1446
status:OK       MTU:1478
status:OK       MTU:1494
status:ng       MTU:1502
status:OK       MTU:1498
status:OK       MTU:1500
status:ng       MTU:1501
status:OK       MTU:1500
result:1500

$ ./scanmtu.sh 8.8.8.8
status:OK       MTU:1000
status:OK       MTU:1002
status:OK       MTU:1006
status:OK       MTU:1014
status:OK       MTU:1030
status:OK       MTU:1062
status:OK       MTU:1126
status:OK       MTU:1254
status:ng       MTU:1510
status:OK       MTU:1382
status:OK       MTU:1446
status:ng       MTU:1478
status:ng       MTU:1462
status:OK       MTU:1454
status:ng       MTU:1458
status:ng       MTU:1456
status:ng       MTU:1455
status:OK       MTU:1454
result:1454

$ ./scanmtu.sh localhost
status:OK       MTU:1000
status:OK       MTU:1002
status:OK       MTU:1006
status:OK       MTU:1014
status:OK       MTU:1030
status:OK       MTU:1062
status:OK       MTU:1126
status:OK       MTU:1254
status:OK       MTU:1510
status:OK       MTU:2022
status:OK       MTU:3046
status:OK       MTU:5094
status:OK       MTU:9190
status:ng       MTU:17382
status:OK       MTU:13286
status:OK       MTU:15334
status:OK       MTU:16358
status:ng       MTU:16870
status:ng       MTU:16614
status:ng       MTU:16486
status:OK       MTU:16422
status:ng       MTU:16454
status:ng       MTU:16438
status:OK       MTU:16430
status:OK       MTU:16434
status:OK       MTU:16436
status:ng       MTU:16437
status:OK       MTU:16436
result:16436