Created
September 8, 2013 02:48
-
-
Save lionello/6481448 to your computer and use it in GitHub Desktop.
Wake-On-LAN
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Portable Wake-On-Lan by Lionello Lunesu, placed in the public domain | |
#ifdef _WIN32 | |
#define WIN32_LEAN_AND_MEAN | |
#include <windows.h> | |
#include <winsock2.h> | |
#ifdef _MSC_VER | |
#pragma comment(lib, "ws2_32.lib") | |
#endif | |
#else | |
#include <sys/socket.h> | |
#include <netinet/in.h> | |
#include <arpa/inet.h> | |
#include <unistd.h> | |
#include <errno.h> | |
typedef unsigned char BYTE; | |
typedef char TCHAR; | |
typedef int BOOL; | |
typedef int SOCKET; | |
#endif | |
#include <stdio.h> | |
#define MACLEN (6) | |
#define PACKLEN (17*MACLEN) | |
int H2I(TCHAR m) { | |
return m <= '9' ? m - '0' : (m | 32) - 'a' + 10; | |
} | |
BOOL ValidHex(TCHAR t) { | |
return (t >= '0' && t <= '9') || (t >= 'a' && t <= 'f') || (t >= 'A' && t <= 'F'); | |
} | |
int main(int argc, char* argv[]) | |
{ | |
#ifdef _WIN32 | |
WSADATA wsaData; | |
#endif | |
const char* pMac = (argc >= 2 ? argv[1] : NULL); | |
const char* pIp = (argc == 3 ? argv[2] : NULL); | |
struct sockaddr_in addr; | |
int t = 0, i; | |
SOCKET sock; | |
TCHAR nibble1, nibble2; | |
BOOL BroadCast = 1; | |
char pack[PACKLEN]; | |
if (pMac == NULL) { | |
printf("Usage: wol <MAC> [IP]\n"); | |
return -3; | |
} | |
// FFFFFFFFFFFF | |
while (t < MACLEN) | |
pack[t++] = 0xFF; | |
// first MAC | |
for (i=0; t < MACLEN+MACLEN; ++i) { | |
nibble1 = pMac[i]; | |
if (nibble1 == 0) | |
break; | |
if (!ValidHex(nibble1)) | |
continue; | |
nibble2 = pMac[++i]; | |
if (!ValidHex(nibble2)) | |
break; | |
pack[t++] = (H2I(nibble1) << 4) | H2I(nibble2); | |
} | |
if (t < MACLEN+MACLEN) | |
{ | |
printf("Could not parse MAC address\n"); | |
return -2; | |
} | |
// repeat 15 more times | |
for (;t < PACKLEN; ++t) | |
pack[t] = pack[t - MACLEN]; | |
addr.sin_addr.s_addr = ~0; | |
#ifdef _WIN32 | |
// Initialize Winsock | |
i = WSAStartup(MAKEWORD(2,2), &wsaData); | |
if (i != 0) { | |
printf("WSAStartup failed: %d\n", i); | |
return i; | |
} | |
if (pIp && InetPton(AF_INET, pIp, &addr) <= 0) | |
{ | |
printf("Could not parse IP address\n"); | |
return WSAGetLastError(); | |
} | |
#else | |
if (pIp && inet_pton(AF_INET, pIp, &addr) <= 0) | |
{ | |
printf("Could not parse IP address\n"); | |
return errno; | |
} | |
#endif | |
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); | |
#ifdef _WIN32 | |
if (sock == INVALID_SOCKET) { | |
i = WSAGetLastError(); | |
} | |
#else | |
if (sock < 0) { | |
i = errno; | |
} | |
#endif | |
else { | |
i = setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (const char*)&BroadCast, sizeof(BroadCast)); | |
addr.sin_family = AF_INET; | |
addr.sin_port = htons(9); // network byte order | |
t = sendto(sock, pack, PACKLEN, 0, (struct sockaddr*)&addr, sizeof(addr)); | |
#ifdef _WIN32 | |
if (t != PACKLEN) | |
i = WSAGetLastError(); | |
closesocket(sock); | |
#else | |
if (t != PACKLEN) | |
i = errno; | |
close(sock); | |
#endif | |
} | |
#ifdef _WIN32 | |
WSACleanup(); | |
#endif | |
return i; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment