Netboot Mailing List (by thread)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Wake On LAN?





Thanks for writing that PERL script, Ken. I haven't tested it, but I
did write my own WOL utility yesterday (probably at the same time as
you wrote yours).

Mine is in 'C' and only requires the MAC address, not the IP number
as well. Currently it uses a UDP broadcast as I couldn't get my raw
packet version to work, but I will keep on working on that so that I
have a unicast version.

You can include mine in the Etherboot package as well, if you don't
mind.

Currently, I have only tested it on Intel EEPRO boards. I will test
in on a Trendnet (tulip based card) as soon as I get it installed.

Cheers,

Bob Edwards.

<---cut here--->

/*****************************************************************************
 *
 * 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)
 * 
 * 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 MAC address needs to be given to make this work.
 *
 * Current version uses a UDP broadcast to send out the Magic Packet.
 * A future version will use the raw packet interface to unicast the
 * packet only to the target machine.
 *
 * compile with: gcc -Wall -o wol wol.c
 * 
 * usage: wol <MAC address>
 * where <MAC address> is in xx:xx:xx:xx:xx:xx format.
 *
 * Released under GNU Public License January, 2000.
 */

#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <linux/if_ether.h>
#include <sys/socket.h>
#include <linux/if_packet.h>
#include <linux/if_arp.h>
#include <netinet/in.h>

/* Input an Ethernet address and convert to binary. */
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 < ETH_ALEN)) {
        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, "in_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, "in_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 == ETH_ALEN) {
                    ;           /* nothing */
            }
            bufp++;
        }
    }
    return (0);
} /* in_ether */

int main (int argc, char **argv)
{
        int i, j;
        int packet;
        struct sockaddr_in sap;
        unsigned char ethaddr[8];
        unsigned char *ptr;
        unsigned char buf [128];
        int optval = 1;

    if (argc != 2) {
                fprintf (stderr, "%s: need hardware address\n", argv[0]);
                return (-1);
        }

        /* Fetch the hardware address. */
    if (in_ether (argv[1], ethaddr) < 0) {
        fprintf (stderr, "%s: invalid hardware address\n", argv[0]);
        return (-1);
    }

        /* setup the packet socket */
//      if ((packet = socket (PF_PACKET, SOCK_RAW, htons (ETH_P_802_3))) < 0)
{
        if ((packet = socket (PF_INET, SOCK_DGRAM, 0)) < 0) {
                fprintf (stderr, "%s: socket failed\n", argv[0]);
                return (-1);
        }

        /* Set socket options */
        if (setsockopt (packet, SOL_SOCKET, SO_BROADCAST, (caddr_t) &optval,
                sizeof (optval)) < 0) {
                fprintf (stderr, "%s: setsocket failed %s\n", argv[0],
                        strerror (errno));
                close (packet);
                return (-1);
        }

    /* Set up broadcast address */
        sap.sin_family = AF_INET;
        sap.sin_addr.s_addr = htonl(0xffffffff);        /* broadcast address
*/
        sap.sin_port = htons(60000);

        /* Build the message to send - 6 x 0xff then 16 x MAC address */
        ptr = buf;
        for (i = 0; i < 6; i++)
                *ptr++ = 0xff;
        for (j = 0; j < 16; j++)
                for (i = 0; i < ETH_ALEN; i++)
                        *ptr++ = ethaddr [i];

        /* Send the packet out */
        if (sendto (packet, buf, 102, 0, &sap, sizeof (sap)) < 0) {
                fprintf (stderr, "%s: sendto failed, %s\n", argv[0],
strerror(errno));
                close (packet);
            return (-1);
        }

    close (packet);     
        return (0);
} /* main */
===========================================================================
This Mail was sent to netboot mailing list by:
Bob Edwards <Robert.Edwards@anu.edu.au>
To get help about this list, send a mail with 'help' as the only string in
it's body to majordomo@baghira.han.de. If you have problems with this list,
send a mail to netboot-owner@baghira.han.de.



For requests or suggestions regarding this mailing list archive please write to netboot@gkminix.han.de.