summaryrefslogtreecommitdiffstats
path: root/contrib/wakeonlan/wol.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/wakeonlan/wol.c')
-rw-r--r--contrib/wakeonlan/wol.c452
1 files changed, 93 insertions, 359 deletions
diff --git a/contrib/wakeonlan/wol.c b/contrib/wakeonlan/wol.c
index 07b7e4fc..40a8415a 100644
--- a/contrib/wakeonlan/wol.c
+++ b/contrib/wakeonlan/wol.c
@@ -1,374 +1,108 @@
-/*****************************************************************************
+/*
+ * Copyright (C) 2008 William Stewart.
*
- * wol.c - Wake-On-LAN utility to wake a networked PC
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
*
- * by R. Edwards (bob@cs.anu.edu.au), January 2000
- * (in_ether routine adapted from net-tools-1.51/lib/ether.c by
- * Fred N. van Kempen)
- * added file input, some minor changes for compiling for NetWare
- * added switches -q and -d=<ms>, added Win32 target support
- * by G. Knauf (gk@gknw.de), 30-Jan-2001
- * added switches -b=<bcast> and -p=<port>
- * by G. Knauf (gk@gknw.de), 10-Okt-2001
- * added OS/2 target support
- * by G. Knauf (gk@gknw.de), 24-May-2002
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
*
- * This utility allows a PC with WOL configured to be powered on by
- * sending a "Magic Packet" to it's network adaptor (see:
- * http://www.amd.com/products/npd/overview/20212.html).
- * Only the ethernet dest address needs to be given to make this work.
- * Current version uses a UDP broadcast to send out the Magic Packet.
- *
- * compile with: gcc -Wall -o wol wol.c
- * with Solaris: (g)cc -o wol wol.c -lsocket -lnsl
- * with MingW32: gcc -Wall -o wol wol.c -lwsock32
- *
- * usage: wol <dest address>
- * where <dest address> is in [ddd.ddd.ddd.ddd-]xx:xx:xx:xx:xx:xx format.
- * or: wol [-q] [-b=<bcast>] [-p=<port>] [-d=<ms>] -f=<File name>
- * where <File name> is a file containing one dest address per line,
- * optional followed by a hostname or ip separated by a blank.
- * -b sets optional broadcast address, -p sets optional port,
- * -q supresses output, -d=<ms> delays ms milliseconds between sending.
- *
- * Released under GNU Public License January, 2000.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-
-#define VERSION "1.12.2 (c) G.Knauf http://www.gknw.de/"
-
-#include <errno.h>
#include <stdio.h>
+#include <stdint.h>
#include <stdlib.h>
#include <string.h>
-#ifdef WATTCP
- #define strncasecmp strnicmp
- #include <ctype.h>
- #include <dos.h>
- #include <tcp.h>
-#else
-#ifdef WIN32 /* Win32 platform */
- #define USE_WINSOCKAPI
- #define delay Sleep
- #if (defined(__LCC__) || defined(__BORLANDC__))
- #define strncasecmp strnicmp
- #else
- #define strncasecmp _strnicmp
- #endif
-#elif defined(N_PLAT_NLM) /* NetWare platform */
-#ifdef __NOVELL_LIBC__
- #include <ctype.h>
-#else
- extern int isdigit(int c); /* no ctype.h for NW3.x */
- #include <nwthread.h>
- #define strncasecmp strnicmp
-#endif
-#elif defined(__OS2__) /* OS/2 platform */
- #ifdef __EMX__
- #define strncasecmp strnicmp
- #endif
- extern int DosSleep(long t);
- #define delay DosSleep
-#else /* all other platforms */
- #define delay(t) usleep(t*1000)
-#endif
-#ifndef N_PLAT_NLM /* ! NetWare platform */
- #include <ctype.h>
-#endif
-#ifndef WIN32 /* ! Win32 platform */
- #include <unistd.h>
-#endif
-#ifdef USE_WINSOCKAPI /* Winsock2 platforms */
- #ifdef N_PLAT_NLM /* NetWare platform */
- #include <ws2nlm.h>
- #else
- #include <winsock.h>
- #endif
- #define close(s) { \
- closesocket(s); \
- WSACleanup(); \
- }
-#else /* Socket platforms */
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #if defined(__OS2__) && !defined(__EMX__)
- #include <utils.h>
- #else
- #include <arpa/inet.h>
- #endif
-#endif
-
-#endif
-
-static int read_file (char *destfile);
-static int in_ether (char *bufp, unsigned char *addr);
-static int send_wol (char *dest, char *host);
-
-
-char *progname;
-int quiet = 0;
-int twait = 0;
-unsigned int port = 60000;
-unsigned long bcast = 0xffffffff;
-
-int main (int argc, char *argv[]) {
-
- int cmdindx = 0;
- progname = argv[0];
-
- if (argc > 1) {
- /* parse input parameters */
- for (argc--, argv++; *argv; argc--, argv++) {
- char *bp;
- char *ep;
-
- if (strncasecmp (*argv, "-", 1) == 0) {
- if (strncasecmp (*argv, "-F=", 3) == 0) {
- bp = *argv + 3;
- read_file (bp);
- } else if (strncasecmp (*argv, "-B=", 3) == 0) {
- bp = *argv + 3;
- bcast = inet_addr(bp);
- if (bcast == -1) {
- fprintf (stderr, "%s: expected address argument at %s\n", progname, *argv);
- exit (1);
- }
- } else if (strncasecmp (*argv, "-D=", 3) == 0) {
- bp = *argv + 3;
- twait = strtol (bp, &ep, 0);
- if (ep == bp || *ep != '\0') {
- fprintf (stderr, "%s: expected integer argument at %s\n", progname, *argv);
- exit (1);
- }
- } else if (strncasecmp (*argv, "-P=", 3) == 0) {
- bp = *argv + 3;
- port = strtol (bp, &ep, 0);
- if (ep == bp || *ep != '\0') {
- fprintf (stderr, "%s: expected integer argument at %s\n", progname, *argv);
- exit (1);
- }
- } else if (strncasecmp (*argv, "-Q", 2) == 0) {
- quiet = 1;
- } else if (strncasecmp (*argv, "-V", 2) == 0) {
- fprintf (stderr, "\r%s Version %s\n", progname, VERSION);
- exit (0);
- } else {
- fprintf (stderr, "\r%s: invalid or unknown option %s\n", progname, *argv);
- exit (1);
- }
- } else {
- send_wol (*argv, "");
- }
- cmdindx++;
- }
- return (0);
- } else {
- /* No arguments given -> usage message */
- fprintf (stderr, "\rUsage: %s [-q] [-b=<bcast>] [-p=<port>] [-d=<ms>] -f=<file> | <dest>\n", progname);
- fprintf (stderr, " need at least hardware address or file option\n");
- return (-1);
- }
-}
-
-
-
-static int in_ether (char *bufp, unsigned char *addr) {
-
- char c, *orig;
- int i;
- unsigned char *ptr = addr;
- unsigned val;
-
- i = 0;
- orig = bufp;
- while ((*bufp != '\0') && (i < 6)) {
- val = 0;
- c = *bufp++;
- if (isdigit(c))
- val = c - '0';
- else if (c >= 'a' && c <= 'f')
- val = c - 'a' + 10;
- else if (c >= 'A' && c <= 'F')
- val = c - 'A' + 10;
- else {
-#ifdef DEBUG
- fprintf (stderr, "\rin_ether(%s): invalid ether address!\n", orig);
-#endif
- errno = EINVAL;
- return (-1);
- }
- val <<= 4;
- c = *bufp;
- if (isdigit(c))
- val |= c - '0';
- else if (c >= 'a' && c <= 'f')
- val |= c - 'a' + 10;
- else if (c >= 'A' && c <= 'F')
- val |= c - 'A' + 10;
- else if (c == ':' || c == 0)
- val >>= 4;
- else {
-#ifdef DEBUG
- fprintf (stderr, "\rin_ether(%s): invalid ether address!\n", orig);
-#endif
- errno = EINVAL;
- return (-1);
- }
- if (c != 0)
- bufp++;
- *ptr++ = (unsigned char) (val & 0377);
- i++;
-
- /* We might get a semicolon here - not required. */
- if (*bufp == ':') {
- if (i == 6) {
- ; /* nothing */
- }
- bufp++;
- }
- }
- if (bufp - orig != 17) {
- return (-1);
- } else {
- return (0);
- }
-} /* in_ether */
-
-
-static int read_file (char *destfile) {
-
- FILE *pfile = NULL;
- char dest[64];
- char host[32];
- char buffer[512];
-
- pfile = fopen (destfile, "r+");
+#include <errno.h>
+#include <byteswap.h>
+#include <gpxe/features.h>
+#include <gpxe/netdevice.h>
+#include <gpxe/if_ether.h>
+#include <gpxe/iobuf.h>
+#include <usr/ifmgmt.h>
+#include <usr/wol.h>
+#include <timer.h>
+
+/** @file
+ *
+ * Wake on lan
+ *
+ */
- if (pfile) {
- while (fgets (buffer, 511, pfile) != NULL) {
- if (buffer[0] != '#' && buffer[0] != ';') {
- dest[0] = host[0] = '\0';
- sscanf (buffer, "%s %s", dest, host);
- send_wol (dest, host);
- }
+/**
+ * Boot from a network device
+ *
+ * @v netdev Network device
+ * @ret rc Return status code
+ */
+#define WOL_MSG_LEN (6 + 16*6)
+
+void wakeup_server(char *server_adr)
+{
+ int rc, i,j;
+ unsigned char *buf;
+ uint8_t eth_broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+ unsigned int len;
+ struct io_buffer *iobuf;
+ struct ethhdr *ethhdr;
+ struct net_device *netdev;
+
+ for_each_netdev ( netdev ) {
+ break;
+ }
+
+ if (netdev == NULL)
+ {
+ printf("Could not find netdev\n");
+ return;
}
- fclose (pfile);
- return (0);
- } else {
- fprintf (stderr, "\r%s: destfile '%s' not found\n", progname, destfile);
- return (-1);
- }
-}
-
-
-static int send_wol (char *dest, char *host) {
-
- int i, j;
- int packet;
- struct sockaddr_in sap;
- unsigned char ethaddr[8];
- unsigned char *ptr;
- unsigned char buf [128];
- unsigned long bc;
- char mask[32];
- char *tmp;
-#ifdef USE_WINSOCKAPI
- WORD wVersionRequested;
- WSADATA wsaData;
- int err;
-#endif
-#ifdef WATTCP
- static udp_Socket sock;
- udp_Socket *s;
-#else
- int optval = 1;
-#endif
-
- /* Fetch the broascast address if present. */
- if ((tmp = strstr(dest,"-"))) {
-printf("found: %s\n", tmp);
- tmp[0] = 32;
- sscanf (dest, "%s %s", mask, dest);
- bc = inet_addr(mask);
-printf("bc: string %s address %08lX\n", mask, bc);
- if (bc == -1) {
- fprintf (stderr, "\r%s: expected address argument at %s\n", progname, mask);
- return (-1);
- }
- } else
- bc = bcast;
-
- /* Fetch the hardware address. */
- if (in_ether (dest, ethaddr) < 0) {
- fprintf (stderr, "\r%s: invalid hardware address\n", progname);
- return (-1);
- }
-
-#ifdef USE_WINSOCKAPI
- /* I would like to have Socket Vers. 1.1 */
- wVersionRequested = MAKEWORD(1, 1);
- err = WSAStartup (wVersionRequested, &wsaData);
- if (err != 0) {
- fprintf (stderr, "\r%s: couldn't init Winsock Version 1.1\n", progname);
- WSACleanup ();
- return (-1);
- }
-#endif
-
- /* setup the packet socket */
-#ifdef WATTCP
- sock_init();
- s = &sock;
- if (!udp_open( s, 0, bc, port, NULL )) {
-#else
- if ((packet = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
-#endif
- fprintf (stderr, "\r%s: socket failed\n", progname);
-#ifdef USE_WINSOCKAPI
- WSACleanup ();
-#endif
- return (-1);
- }
+
+ /* Open device and display device status */
+ if ( (ifopen ( netdev ) ) != 0 )
+ {
+ printf("Could not open netdev\n");
+ return;
+ }
+
+ /* Create outgoing I/O buffer */
+ iobuf = alloc_iob ((ETH_HLEN + WOL_MSG_LEN)*2);
+ if (!iobuf)
+ {
+ printf("Could not allocate iob\n");
+ return;
+ }
+
+ ethhdr = iob_put(iobuf, sizeof(*ethhdr));
+
+ /* Build Ethernet header */
+ memcpy (ethhdr->h_dest, eth_broadcast, ETH_ALEN );
+ memcpy (ethhdr->h_source, netdev->ll_addr, ETH_ALEN );
+ ethhdr->h_protocol = htons (0x0842);
+
+ buf = iob_put (iobuf, WOL_MSG_LEN);
+
+ /* Build the message to send - 6 x 0xff then 16 x dest address */
+ len =0;
+ for (i = 0; i < 6; i++)
+ buf[len++] = 0xff;
+ for (j = 0; j < 16; j++)
+ for (i = 0; i < 6; i++)
+ buf[len++] = server_adr[i];
-#ifndef WATTCP
- /* Set socket options */
- if (setsockopt (packet, SOL_SOCKET, SO_BROADCAST, (char *)&optval, sizeof (optval)) < 0) {
- fprintf (stderr, "\r%s: setsocket failed %s\n", progname, strerror (errno));
- close (packet);
- return (-1);
- }
+ rc = netdev_tx (netdev, iobuf);
- /* Set up broadcast address */
- sap.sin_family = AF_INET;
- sap.sin_addr.s_addr = bc; /* broadcast address */
- sap.sin_port = htons(port);
-#endif
+ if (rc !=0)
+ printf("Failed to transmit WOL packet\n");
- /* Build the message to send - 6 x 0xff then 16 x dest address */
- ptr = buf;
- for (i = 0; i < 6; i++)
- *ptr++ = 0xff;
- for (j = 0; j < 16; j++)
- for (i = 0; i < 6; i++)
- *ptr++ = ethaddr [i];
+ /* Give the controller a chance to send it before checking */
+ mdelay(100);
- /* Send the packet out */
-#ifdef WATTCP
- sock_write( s, buf, 102 );
- sock_close( s );
-#else
- if (sendto (packet, (char *)buf, 102, 0, (struct sockaddr *)&sap, sizeof (sap)) < 0) {
- fprintf (stderr, "\r%s: sendto failed, %s\n", progname, strerror(errno));
- close (packet);
- return (-1);
- }
- close (packet);
-#endif
- if (!quiet) fprintf (stderr, "\r%s: packet sent to %04X:%08lX-%s %s\n",
- progname, port, (unsigned long)htonl(bc), dest, host);
- if (twait > 0 ) {
- delay (twait);
- }
- return (0);
+ netdev_poll(netdev);
}