概要

Wake On Lanは、電源が切れている機器にマジックパケットを送信し電源を入れる規格である。
本プログラムは、LAN内に対してはブロードキャストアドレスとMACアドレスを指定することによりマジックパケットを送信する。
MACアドレスとは、ベンダー名が上位3オクテットで下位3オクテットが重複しない番号となっている。
WANに対してはグローバルIPアドレスとポート番号、MACアドレスを指定することによりマジックパケットを送信する。WANを使用する場合、ルータがWAN側からの指定されているLANのIPアドレスのポートへパケットを通すような設定にしなければなりません。うまく動かないことが多いようです。また電源が入っていない機器はブロードキャストに反応しませんので、ルータのARPキャッシュが時間が経過し消えればできなくなります。Wake On LAN対応のルーターが必要です。

マジックパケットの概要

マジックパケットは、0xffを6回送信後、MACアドレスを16回送信することで作成できます。

ブロードキャストアドレス

電源が入っていない機器であるためIPアドレスは確定していない。よって、ブロードキャストアドレスを用いる。
本プログラムを実行するパソコンのIPアドレスが192.168.0.1、ネットマスクが255.255.255.0の場合、
まずそれぞれを16進数に直すと、0xc0,0xa8,0x00,0x01、0xff,0xff,0xff,0
2進数では、以下の通りとなります。

IP         11000000 10101000 00000000 00000001
MASK       11111111 11111111 11111111 00000000
MASKを反転させIPと論理和を求めるとブロードキャストアドレスが得られます。

IP & MASK  11000000 10101000 00000000 00000000
~MASK      00000000 00000000 00000000 11111111
IP | ~MASK 11000000 10101000 00000000 11111111
           192.168.0.255
プログラムを使用するには、ソースファイルに記述されているIPアドレスとMACアドレスを修正してコンパイルしてください。

テスト環境

コンパイラ

Visual C++ 2008 Standard 32/64bit
Visual C++ 2013 Express 32/64bit

実行環境

マジックパケット送信側

Windows 8.1 Enterprise 64bit Windows 7 EnterPrise Service Pack 1 64bit
Windows Vista Ultimate Service Pack 2 32bit
Windows XP Professional Service Pack 3 32bit

マジックパケット受信側

IO-DATA RECBOX

プログラムソースの概要

グロバール変数macにMACアドレス、グロバール変数ipにブロードキャストアドレスを設定します。
例えばMACアドレス 34:76:c5:12:34:56、IPアドレス192.168.0.255の場合、以下のように設定します。

BYTE mac[6] = { 0x34, 0x76, 0xc5, 0x12, 0x34, 0x56 };
BYTE ip[4] = { 192, 168, 0, 255 };

_tWinMain関数

Windowsから最初に_tWinain関数が呼び出されます。
WSAStartup関数を呼び出しWinsockを初期化します。
TransMagicPacket関数を呼び出しマジックパケットを送信します。
WSACleanup関数でWinsockを解放します。

TransMagicPacket関数

パケットサイズは、6+6*19=102バイトですので、BYTE型の102バイトの配列packetを作成します。
packet配列の先頭から6個分、0xffで初期化します。
memcopy関数でmacアドレスを6回、packet配列にコピーします。
socket関数でUDPソケットを指定します。
SOCKADDR_IN構造体にアドレスとポート等を設定します。
sendto関数でpacket配列を送信します。
closesocket関数でソケットを閉じます。

プログラムソース

//      Wake On Lan テストプログラム
//      Visual C++ 2008/2013 32/64bit

#include <windows.h>
#include <tchar.h>

#pragma comment(lib,"Ws2_32.lib")

BYTE mac[6] = { 0x34, 0x76, 0xc5, 0x12, 0x34, 0x56 };   //      MACアドレスの設定
BYTE ip[4] = { 192, 168, 0, 255 };      //      ブロードキャストアドレスの設定

//      マジックパケットを送信
BOOL TransMagicPacket(DWORD addr, int port, BYTE *mac);

int WINAPI _tWinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, TCHAR* CmdLine, int nCmdShow){
        WSADATA wsaData;

        // WinSockの初期化
        if (WSAStartup(MAKEWORD(2, 2), &wsaData))
                return 0;

        // マジックパケットの送信
        DWORD ipa = *(DWORD*)ip;
        TransMagicPacket(ipa, 0, mac);

        WSACleanup();
        return 0;
}

//      マジックパケットを送信

BOOL TransMagicPacket(DWORD addr, int port, BYTE *mac){
        SOCKET      s;
        SOCKADDR_IN sockadd;
        BYTE        packet[6 + 6 * 16];
        int n;
        // 0xFFを16回設定
        for (n = 0; n<6; n++)
                packet[n] = 0xff;

        // MACアドレスを16回設定
        for (n = 0; n<16; n++)
                memcpy(packet + 6 + n * 6, mac, 6);
        // UDPソケット作成
        s = socket(PF_INET, SOCK_DGRAM, 0);
        if (s == SOCKET_ERROR)
                return FALSE;

        // ソケットアドレスの設定
        sockadd.sin_family = AF_INET;
        sockadd.sin_addr.s_addr = addr;
        sockadd.sin_port = htons(port);

        // 送信
        sendto(s, (LPSTR)&packet, sizeof(packet), 0, (LPSOCKADDR)&sockadd, sizeof(sockadd));
        // ソケットを閉じる
        closesocket(s);
        return TRUE;
}

ソースファイルのダウンロード

ダウンロード wol.zip(903Byte)
ZIPファイルに含まれるファイル

wol.cpp