diff options
| author | Jan Wolff <janw@mailbox.org> | 2021-07-08 20:31:34 +0200 |
|---|---|---|
| committer | Jan Wolff <janw@mailbox.org> | 2021-07-08 20:31:34 +0200 |
| commit | 16399fab9e592cf1e12f1fd56c11f12ae9bc575f (patch) | |
| tree | e428891a59451187c8ce1866332701973fc0cf3a | |
initial commit
| -rw-r--r-- | .clang-format | 10 | ||||
| -rw-r--r-- | .gitattributes | 2 | ||||
| -rw-r--r-- | .gitignore | 3 | ||||
| -rw-r--r-- | LICENSE.md | 15 | ||||
| -rw-r--r-- | Makefile | 24 | ||||
| -rw-r--r-- | README.md | 5 | ||||
| -rw-r--r-- | wakeup.c | 83 |
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; +} |
