summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Wolff <janw@mailbox.org>2021-07-08 20:31:34 +0200
committerJan Wolff <janw@mailbox.org>2021-07-08 20:31:34 +0200
commit16399fab9e592cf1e12f1fd56c11f12ae9bc575f (patch)
treee428891a59451187c8ce1866332701973fc0cf3a
initial commit
-rw-r--r--.clang-format10
-rw-r--r--.gitattributes2
-rw-r--r--.gitignore3
-rw-r--r--LICENSE.md15
-rw-r--r--Makefile24
-rw-r--r--README.md5
-rw-r--r--wakeup.c83
7 files changed, 142 insertions, 0 deletions
diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..b88d285
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,10 @@
+# Linux-like style
+BasedOnStyle: LLVM
+IndentWidth: 4
+UseTab: Never
+BreakBeforeBraces: Linux
+AllowShortIfStatementsOnASingleLine: true
+IndentCaseLabels: false
+# Force pointers to the type
+DerivePointerAlignment: false
+PointerAlignment: Left
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..5966153
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,2 @@
+.gitattributes export-ignore
+.gitignore export-ignore
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..9b53d96
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+wakeup
+*.o
+*.exe
diff --git a/LICENSE.md b/LICENSE.md
new file mode 100644
index 0000000..0dcc28e
--- /dev/null
+++ b/LICENSE.md
@@ -0,0 +1,15 @@
+Copyright (C) 2020 Jan Wolff
+
+This software is provided 'as-is', without any express or implied warranty. In
+no event will the authors be held liable for any damages arising from the use
+of this software. Permission is granted to anyone to use this software for any
+purpose, including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim
+ that you wrote the original software. If you use this software in a product,
+ an acknowledgment in the product documentation would be appreciated but is
+ not required.
+2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..7055763
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,24 @@
+CC ?= gcc
+CFLAGS ?= -std=c99 -Wall -Werror
+OBJ = wakeup.o
+BIN = wakeup
+PREFIX ?= /usr
+
+prog: $(OBJ)
+ $(CC) $(CFLAGS) $(OBJ) -o $(BIN)
+
+%.o: %.c
+ $(CC) $(CFLAGS) -c $<
+
+install: prog
+ mkdir -p ${PREFIX}/bin
+ install -m 755 -o root -g root -s ${BIN} ${PREFIX}/bin
+
+format:
+ clang-format -i *.c
+
+clean:
+ rm *.o
+ rm $(BIN)
+
+.PHONY: install format clean
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..63202f4
--- /dev/null
+++ b/README.md
@@ -0,0 +1,5 @@
+Wakeup
+======
+
+Performs Wake On Lan by broadcasting a magic packet targeting the given MAC
+address.
diff --git a/wakeup.c b/wakeup.c
new file mode 100644
index 0000000..01ae3af
--- /dev/null
+++ b/wakeup.c
@@ -0,0 +1,83 @@
+#include <arpa/inet.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+void printUsage()
+{
+ puts("usage: wakeup <MAC> <BROADCAST> [PORT]");
+ puts(" MAC: interface address to wakeup (e.g. ff:ff:ff:ff:ff:ff)");
+ puts(" BROADCAST: broadcast address of subnet (e.g. 192.168.2.255)");
+ puts(" PORT: port to send UDP packet on (default: 7)");
+}
+
+/*
+Use the UDP broadcast method to send the magic wakeup packet.
+*/
+int bcast_wakeup(const char* macAddr, const char* broadcast, in_port_t port)
+{
+ int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (sock < 1) {
+ perror("could not open socket");
+ exit(EXIT_FAILURE);
+ }
+
+ int opt_broadcast = 1;
+ setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &opt_broadcast,
+ sizeof(opt_broadcast));
+
+ struct in_addr ip;
+ if (!inet_aton(broadcast, &ip)) {
+ fputs("could not parse broadcast IP address", stderr);
+ exit(EXIT_FAILURE);
+ }
+
+ struct sockaddr_in socket_addr;
+ memset(&socket_addr, 0, sizeof(socket_addr));
+ socket_addr.sin_port = port;
+ socket_addr.sin_family = AF_INET;
+ socket_addr.sin_addr.s_addr = ip.s_addr;
+
+ uint8_t macValues[6];
+ if (sscanf(macAddr, "%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx", &macValues[0],
+ &macValues[1], &macValues[2], &macValues[3], &macValues[4],
+ &macValues[5]) != 6) {
+ fputs("could not parse MAC address", stderr);
+ exit(EXIT_FAILURE);
+ }
+
+ uint8_t data[6 + 16 * 6];
+ memset(&data, 0xFF, 6); // sync stream for magic packet
+ for (size_t i = 0; i < 16;
+ i++) { // followed by 16 repititions of mac address
+ memcpy(data + 6 + 6 * i, &macValues, 6);
+ }
+
+ if (sendto(sock, data, sizeof(data), 0, (struct sockaddr*)&socket_addr,
+ sizeof(socket_addr)) < 0) {
+ fputs("packet sending failed", stderr);
+ perror("Error Code:");
+ exit(EXIT_FAILURE);
+ }
+ return 1;
+}
+
+int main(int argc, char* argv[])
+{
+ const char* mac;
+ const char* ip;
+ in_port_t port = 7;
+ if (argc < 3) {
+ printUsage();
+ exit(0);
+ } else {
+ mac = argv[1];
+ ip = argv[2];
+ }
+ if (argc > 3) {
+ port = atoi(argv[3]);
+ }
+ bcast_wakeup(mac, ip, port);
+ return 0;
+}