summaryrefslogtreecommitdiff
path: root/lib/wol.c
blob: 2fb1eca8bfce9f4d8816c1f15c600c0a104f4fc7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/*
 * wol.c: 
 *
 * See the README file for copyright information and how to reach the author.
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <errno.h>

#include "common.h"
#include "wol.h"

//***************************************************************************
// Send WOL
//***************************************************************************

int sendWol(const char* mac, const char* device)
{
   struct sockaddr_in addr;
   unsigned char packet[sizeWolPacket];
   int sock;
   int optval = 1;
   cWolHeader wolHeader;
   const char* bcast = "";

   if (isEmpty(device))
      device = getFirstInterface();
   
   bcast = bcastAddressOf(getIpOf(device), getMaskOf(device));
      
   if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
   {
      tell(0, "Error: Cannot open socket '%s'", strerror(errno));
      return fail;
   }
   
   if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char*)&optval, sizeof(optval)) < 0)
   {
      tell(0, "Error: Cannot set socket options '%s'", strerror(errno));
      return fail;
   }

   sprintf(wolHeader.remoteAddr, "%.*s", sizeAddr, bcast);

   if (packMacAddr(mac, &wolHeader.macAddr) < 0)
   {
      tell(0, "Error: MAC Address '%s' ist not valid", mac);
      return fail;
   }
   
   // .....
   
   addr.sin_family = AF_INET;
   addr.sin_port = htons(wolPort);
   
   if (inet_aton(wolHeader.remoteAddr, &addr.sin_addr) == 0)
   {
      tell(0, "Error: Invalid remote ip address given '%s'", wolHeader.remoteAddr);
      return fail;
   }
   
   for (int i = 0; i < 6; i++)
      packet[i] = 0xFF;
   
   for (int i = 1; i <= 16; i++)
      for (int j = 0; j < 6; j++)
         packet[i * 6 + j] = wolHeader.macAddr.macAddr[j];
   
   if (sendto(sock, packet, sizeof(packet), 0, (struct sockaddr*)&addr, sizeof(addr)) < 0)
   {
      tell(0, "Error: Cannot send data '%s'", strerror(errno));
      return fail;
   }

   tell(0, "Info: Successful sent WOL magic packet to '%s' via bcast '%s'",
        wolHeader.macAddr.macAddrStr, bcast);
   
   close(sock);
   
   return success;
}

//***************************************************************************
// Pack MAC Address
//***************************************************************************

int packMacAddr(const char* mac, cMacAddr* packedMac)
{
   char* tmpMac = strdup(mac);
   char* tok;
  
   tok = strtok(tmpMac, ":");
   
   for (int i = 0; i < macAddrTupel; i++)
   {
      if (!tok)
      {
         free(tmpMac);
         return fail;
      }
      
      packedMac->macAddr[i] = (unsigned char)strtol(tok, 0, 16);  // HEX
      tok = strtok(0, ":");
   }

   strncpy(packedMac->macAddrStr, mac, sizeMacStr);
   free(tmpMac);
   
   return success;
}