NAlek
int main() { return 0; }
« Реализация Wake-on-Lan

Wake-On-Lan – технология удаленного включения компьютера. Идея заключается в том, чтобы по сети отправить удаленному компьютеру, специально сформированный пакет - magic packet.



Сам "magic packet" представляет собой последовательность байт, размером 102 байта, где первые 6 - это 0xFF, остальные MAC адрес удаленного компьютера (повторенный 16 раз).

Прежде чем отправить пакет, необходимо преобразовать его из шестнадцатеричного представления в двоичное.
Этим занимается функция:
int hex2bin( void *dest, const char *src, int max )
(так же эта функция пропускает спец. символы, такие как ":", "-", " ")

После того как пакет сформирован – отправляем его с помощью широковещательной рассылки (broadcast).

NWOL.cpp
// Copyright (C) 2011 NAlek
// Wake-on-Lan v1.0
//

#include "stdafx.h"

#define __WOL_PORT  2304

#define  __COPYRIGHT  "Copyright (C) 2011 NAlek"
#define  __DESCRIPTION "NAlek Wake-on-LAN"

#define __HELP "Usage: nwol.exe destanation_MAC_address [-b <ip_broadcast_address>]"

int hex2bin( void *dest, const char *src, int max )
{
    int i,j,c;
    for(i=j=0;src[i];i++)
    {
        if(j>=2*max) return max;
        c=src[i];
        if(c>='0' && c<='9') c-='0';
        else if(c>='A' && c<='F') c-='A'-10;
        else if(c>='a' && c<='f') c-='a'-10;
    else if( c=='.' || c==' ' || c=='-' || c=='t' || c==':' )
            continue;
        else break;
        if(j&1) ((unsigned char *)dest)[(j-1)>>1]+=c;
        else ((unsigned char *)dest)[j>>1]=c<<4;
        j++;
    }
    return ((j&~1)>>1);
}


int BroadcastMagicPacket( TCHAR **szMAC, int iMACCount, TCHAR *szIPBroadcast, unsigned short usPort )
{
  int iRet =0;

  // создаюм UDP сокет
  SOCKET sSock =socket( AF_INET, SOCK_DGRAM, 0 );
  
  if( sSock ==INVALID_SOCKET )
  {
    // ERROR
    // ошибка создания сокета
    printf("ERROR: socket()nCode: %dn", WSAGetLastError() );
    iRet =1;
  }
  else
  {
    struct sockaddr_in sSA;
    sSA.sin_family =AF_INET;
    sSA.sin_addr.s_addr =INADDR_ANY;
    sSA.sin_port =htons(usPort);
    if( bind( sSock, (struct sockaddr*)&sSA, sizeof(sSA) ) ==SOCKET_ERROR )
    {
      // ERROR
      // ошибка привязки
      printf("ERROR: bind()nCode: %dn", WSAGetLastError() );
      iRet =1;
    }
    else
    {
      BOOL bBroadcast =TRUE;
      if( setsockopt( sSock, SOL_SOCKET, SO_BROADCAST, (char *)&bBroadcast, sizeof(BOOL) ) ==SOCKET_ERROR )
      {
        // ERROR
        // ошибка изменения параметров сокета
        printf("ERROR: setsockopt()nCode: %dn", WSAGetLastError() );
        iRet =1;
      }
      else
      {
        sSA.sin_addr.s_addr = szIPBroadcast ==NULL ? INADDR_BROADCAST : inet_addr(szIPBroadcast);
        //printf("Broadcast Address %snn", szIPBroadcast ==NULL ? "255.255.255.255" : szIPBroadcast );

        for( int i =0; i <iMACCount; ++i )
        {
          if( szMAC[i] ==NULL || strlen(szMAC[i]) !=12 )
          {
            // ERROR
            // неправельный MAC адрес
            printf("Wrong MAC addressn");
            iRet =1;
          }
          else
          {
            // формируем MagicPacket
            char btMacAddress[6] ={NULL};
            hex2bin( btMacAddress, szMAC[i], 6);

            char btMagicPacket[204] ={NULL};
            hex2bin( btMagicPacket, "FFFFFFFFFFFF", 6);

            for( int iOffset=6; iOffset<=96; iOffset +=6 )
              memcpy( btMagicPacket+iOffset, btMacAddress, 6 );

            if( sendto( sSock, btMagicPacket, 102, 0, (struct sockaddr*)&sSA, sizeof(sSA) ) ==SOCKET_ERROR )
            {
              // ERROR
              // ошибка отправки широковещательного сообщения
              printf("ERROR: sendto()nCode: %dn", WSAGetLastError() );
              iRet =1;
            }// sendto
            else
            {
              printf( "Magic Packet sent for [%s] via broadcast address %sn",
              szMAC[i],
              szIPBroadcast ==NULL ? "255.255.255.255" : szIPBroadcast );
            }
          }
        }// for
      }// setsockopt
    }// bind
    
    // закрываем созданный сокет
    closesocket( sSock );
  }// socket

  return iRet;
}


int _tmain(int argc, _TCHAR* argv[])
{
  int iRet =0;

  TCHAR **szMAC =NULL;
  int iMACCount =0;

  TCHAR *szIPBroadcast =NULL;

  WSADATA wsaData;
  WORD wVersionRequested =MAKEWORD( 2, 2 );

  printf("%sn", __DESCRIPTION);
  printf("%snn", __COPYRIGHT);

  // 0 - mac address
  // 1 - broadcas address
  int iArg =-1;

  for( int i =1; i <argc; ++i )
  {
    size_t iLen =strlen(argv[i]);

    if( iArg ==-1 )
    {
      if( !_stricmp( argv[i], "-b" ) && !szIPBroadcast  )
      {
        // broadcast address
        iArg =1;
        continue;
      }
      else
        if( !szMAC )
          iArg =0;
        else
          break;
    }

    switch(iArg)
    {
    // mac
    case 0:
      TCHAR szTmp[13];
      if( sscanf_s( argv[i], "%[0-9A-Za-z]", &szTmp, 13 ) !=0 )
        if( ( szMAC =(TCHAR **)malloc( sizeof(TCHAR *) ) ) )
        {
          if( ( szMAC[iMACCount] =(TCHAR *)calloc(iLen+1, sizeof(TCHAR) ) ) )
            memcpy( szMAC[iMACCount], szTmp, iLen );

          ++iMACCount;
        }

      iArg =-1;
    break;

    // broadcast ip
    case 1:
      if( ( szIPBroadcast =(TCHAR *)calloc(iLen+1, sizeof(TCHAR)) ) )
        memcpy( szIPBroadcast, argv[i], iLen );
      iArg =-1;
    break;
    }
  }


  if( szMAC ==NULL )
  {
    FILE *file;
    TCHAR szTmp[256];
    TCHAR szMACTmp[13];
    
    if( fopen_s(&file, "mac.txt", "r" ) ==0 )
    {
      while( fgets( szTmp, 256, file ) )
      {
        if( sscanf_s( szTmp, "%[0-9A-Za-z]", &szMACTmp, 13 ) ==0 )
          continue;

        if( szMAC ==NULL )
          szMAC =(TCHAR **)malloc( sizeof(TCHAR *) );
        else
          szMAC =(TCHAR **)realloc(szMAC, (iMACCount+1)*sizeof(TCHAR *) );

        if( szMAC )
        {
          if( ( szMAC[iMACCount] =(TCHAR *)calloc( 13, sizeof(TCHAR) ) ) )
            memcpy( szMAC[iMACCount], szMACTmp, 12 );

          ++iMACCount;
        }// if
      }// while
      
      fclose(file);
    }
    else
    {
      printf("%sn", __HELP);
    }
  }

  // загружаем библиатеку winsock
  if( WSAStartup( wVersionRequested, &wsaData ) !=0 )
  {
    // ERROR
    // ошибка приинициализации библиотеки winsock
    iRet =1;
    printf("ERROR: Could not load winsocknCode: %dn", WSAGetLastError() );
  }
  else
  {
    // проверяем инициализируема версия ту которую мы запрашивали
    if( LOBYTE( wsaData.wVersion ) !=2 || HIBYTE( wsaData.wVersion ) !=2 )
    {
      // ERROR
      // загруженая версия winsock отлична от требуемой
      iRet =1;
      printf("ERROR: Bad winsock versionn");
    }
    else
    {
      BroadcastMagicPacket( szMAC, iMACCount, szIPBroadcast, __WOL_PORT );
    }
    // выгружаем библиотеку
    WSACleanup();
  }


  //
  // очищаем выделенную память
  //
  for( int i =0; i <iMACCount; ++i )
    free(szMAC[i]);
  free(szMAC);

  free(szIPBroadcast);

  return iRet;
}

Исходный код | Демонстрация
Яндекс.Метрика