123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374 |
- /*****************************************************************************
- *
- * wol.c - Wake-On-LAN utility to wake a networked PC
- *
- * 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 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.
- */
-
- #define VERSION "1.12.2 (c) G.Knauf http://www.gknw.de/"
-
- #include <errno.h>
- #include <stdio.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+");
-
- 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);
- }
- }
- 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);
- }
-
- #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);
- }
-
- /* Set up broadcast address */
- sap.sin_family = AF_INET;
- sap.sin_addr.s_addr = bc; /* broadcast address */
- sap.sin_port = htons(port);
- #endif
-
- /* 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];
-
- /* 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);
- }
|