diff --git a/wol.c b/wol.c index e7aa930..9e40089 100644 --- a/wol.c +++ b/wol.c @@ -9,20 +9,56 @@ #include #include #include -#include -#define MAC_REGEX "^([0-9A-Fa-f]{2}[:-]?){5}([0-9A-Fa-f]{2})$" +#define MAX_TRIES 10 + +static int +xdigit (char c) +{ + if (c >= '0' && c <= '9') + return (c - '0'); + else if (c >= 'A' && c <= 'F') + return (c - 'A'); + else if (c >= 'a' && c <= 'f') + return (c - 'a'); + return -1; +} + +static uint8_t * +ether_str2addr(const char *str, uint8_t *addr) +{ + int val0, val1; + + for (int i = 0; i < 6; ++i) { + val0 = xdigit(*str); + str++; + if (val0 < 0) + return NULL; + val1 = xdigit(*str); + str++; + if (val1 < 0) + return NULL; + addr[i] = (uint8_t)((val0 << 4) | val1); + if (i < 5 && !isxdigit(*str)) + str++; + } + if (*str != '\0') + return NULL; + + return addr; +} static void wake_on_lan(const char *mac_address) { - char payload[102]; - int mac[6]; + uint8_t payload[102]; + uint8_t mac[6]; - sscanf(mac_address, "%2x%2x%2x%2x%2x%2x", &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]); + if (ether_str2addr(mac_address, mac) == NULL) + errx(1, "Invalid MAC address: %s", mac_address); memset(payload, 0xFF, 6); for (unsigned int i = 6; i < sizeof(payload); i += 6) - memcpy(payload + i, mac, sizeof(mac)); + memcpy(payload + i, mac, 6); struct sockaddr_in sa; memset(&sa, 0, sizeof(sa)); @@ -37,7 +73,7 @@ wake_on_lan(const char *mac_address) { if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &(int){1}, sizeof(int)) < 0) err(1, "%s", "setsockopt"); - for (int i = 0; i < 10; ++i) + for (int i = 0; i < MAX_TRIES; ++i) if (sendto(sock, payload, sizeof(payload), 0, (struct sockaddr*)&sa, sizeof(sa)) < 0) err(1, "sendto"); @@ -51,25 +87,9 @@ main(int argc, char *argv[]) { exit(1); } - regex_t regex; - if (regcomp(®ex, MAC_REGEX, REG_EXTENDED) != 0) - errx(1, "%s", "Failed to compile regular expression"); - - for (int i = 1; i < argc; ++i) { - if (regexec(®ex, argv[i], 0, NULL, 0) != 0) - errx(1, "Invalid MAC address: %s", argv[i]); - - char mac_address[13]; - int k = 0; - for (int j = 0; argv[i][j]; ++j) - if (isxdigit((int) argv[i][j])) - mac_address[k++] = argv[i][j]; - mac_address[k] = '\0'; - - wake_on_lan(mac_address); - } + for (int i = 1; i < argc; ++i) + wake_on_lan(argv[i]); - regfree(®ex); return (0); }