見出し画像

TWSNMP FC:Wake On LANに対応 途中

一昨日、フィードバックに要望のあったWake On LANのパケットの送信に対応する方法を調べました。
まずは旧バージョンのTWSNMPのソースコードを読んでみました。

BOOL CWolSock::DoWol(CString szMacAddr,CString szIP)
{
	if( szMacAddr.IsEmpty() ) return(FALSE);
	unsigned int  cMacAddr[6];
	int c = sscanf_s(szMacAddr,"%x:%x:%x:%x:%x:%x",&cMacAddr[0],&cMacAddr[1],&cMacAddr[2],&cMacAddr[3],&cMacAddr[4],&cMacAddr[5]);
	if( c!= 6 ) return(FALSE);
	if(!Create(0,SOCK_DGRAM,0)) return(FALSE);
	BOOL bBcst = TRUE;
	SetSockOpt(SO_BROADCAST,&bBcst,sizeof(BOOL));

	SOCKADDR_IN sa;
	sa.sin_family = AF_INET;
	sa.sin_addr.S_un.S_addr = inet_addr(szIP);
	sa.sin_port = htons(WOL_PORT);
	if( !Connect((SOCKADDR*)&sa,sizeof(SOCKADDR_IN)))return(FALSE);
	char TxBuf[17*6];
	int k =0;
	for(int i = 0; i < 17;i++ ) {
		for(int j =0; j < 6;j++ ) {
			if( i == 0 ) {
				TxBuf[k++] = (char)0xff;
			} else {
				TxBuf[k++]  = (char) cMacAddr[j];
			}
		}
	}
	return(Send(TxBuf,sizeof(TxBuf))== sizeof(TxBuf));
}

VC++で書くとこんな感じです。解説すると0xffを6回、6バイトのMACアドレスを16回ならべたパケットをUDPでブロードキャストしています。たぶん20年近く前に作ったものです。
最近はどうなっているかGO言語で作ったサンプルを探してみました。
ありました。

2019年なので最近の仕様と思って大丈夫そうです。
やっていることは私が作ったものとだいたい同じでした。ここまでが昨日の夜の話です。
今朝は早く試したくて4時に起きて開発を始めました。すぐにコードを書こうと思いましたが作ってもテストする対象(電源をいれるPC)がないことに気づきました。そこから2時間、苦戦苦闘です。
テスト用のVaioのBIOS画面を見ましたがWake On LANの設定がありません。
Mac OSでも試してみましたが簡単にはいきません。
VaioにインストールしたLinux環境(Debian)でできないか調べました。

https://wiki.debian.org/WakeOnLan

でできそうです。
試してみましたが電源OFFからだと起動できません。
サスペンドからだと起動はできました。でも使っているVaioが古いためかOSが元の状態に戻りません。マジックパケットに反応はしているので、この問題を調べるはのは後にしました。
他にWireSharkでパケットキャプチャーすれば確認できました。
調べたことを元にGO言語でプログラムを作ってみました。

func SendWakeOnLanPacket(mac string) error {
	ra, err := net.ResolveUDPAddr("udp4", "255.255.255.255:9")
	if err != nil {
		return err
	}
	la, err := net.ResolveUDPAddr("udp4", ":0")
	if err != nil {
		return err
	}
	c, err := net.DialUDP("udp4", la, ra)
	if err != nil {
		return err
	}
	defer c.Close()
	hw, err := net.ParseMAC(mac)
	if err != nil {
		return err
	}
	packet := []byte{}
	prefix := []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
	packet = append(packet, prefix...)
	for i := 0; i < 16; i++ {
		packet = append(packet, hw...)
	}
	_, err = c.Write(packet)
	return err
}

です。スッキリ書けていると思います。テストコードも書いてみました。

func TestWol(t *testing.T) {
	err := SendWakeOnLanPacket("78:84:3c:2a:ac:08")
	if err != nil {
		t.Fatal(err)
	}
}

です。実行するとちゃんとWake On LAN(WOL)のパケットを送信しています。

画像1

ここまで実施したところで時間切れです。明日、メニューから送信できるようにしようと思います。

明日に続く 

開発のための諸経費(機材、Appleの開発者、サーバー運用)に利用します。 ソフトウェアのマニュアルをnoteの記事で提供しています。 サポートによりnoteの運営にも貢献できるのでよろしくお願います。