/*
   WAKE ON LAN - Remote Power On

   hpwake.c: Sendet eine Broadcast Message an alle Clients des Subnetzes,
   die eine Abfolge von Bytes enthaelt um einen Rechner zu booten.
   
   Version 1.1 06.10.2000
   
   Unterstuetzte OS: HP-UX 10.20 und 9.05
   Kompilieren: cc -o hpwake hpwake.c
   Aufruf: hpwake xx:xx:xx:xx:xx:xx
   xx:xx:xx:xx:xx:xx ist die MAC Adresse der Ethernetkarte in Hexadezimalwerten,
   man erhaelt sie fuer einen entsprechenden Rechner durch Eingabe von:
   Unter HP-UX: lanscan
   Unter Windoof NT: ipconfig -all
   Unter Windoof 95: winipcfg
   
   email: wann@kcm-01.ik.mb.uni-siegen.de
*/

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

u_char magicpacket[500];


int get_magicpacket(packet,arg)

unsigned char *packet;
char *arg;

{
        unsigned char ether_addr[6];
        int dstaddr[6];
        int i;
        int j;
        int k;
        char *a;

        for (a = arg; *a; a++)
                if (*a != ':' && !isxdigit(*a)) {
                        fprintf(stderr, "MAC Adresse muss hexadezimal angegeben werden! [00:11:22:33:44:55]\n");
                        fprintf(stderr, "MAC address must be given in hex! [00:11:22:33:44:55]\n");
                        exit(2);
                }

        k = sscanf(arg, "%2x:%2x:%2x:%2x:%2x:%2x",
                &dstaddr[0], &dstaddr[1], &dstaddr[2], &dstaddr[3], &dstaddr[4], &dstaddr[5]);
        
        if (k != 6) {
                fprintf(stderr, "Ungueltige MAC Adresse! [00:11:22:33:44:55]\n");
                fprintf(stderr, "Invalid MAC address! [00:11:22:33:44:55]\n");
                exit(2);
        }
                   
        for (i = 0; i < 6; i++)
                ether_addr[i] = dstaddr[i];
                
        memcpy(packet, ether_addr, 6);
        packet[6] = 0x00;
        packet[7] = 0x74;
        j = 8;

        memset(packet+j, 0xff, 6);
        j += 6;

        for (i = 0; i < 16; i++) {
                memcpy(packet+j, ether_addr, 6);
                j += 6;
        }

        packet[111] = 0x40;
        packet[112] = 0x00;
        packet[113] = 0x90;
        packet[114] = 0x90;
        packet[115] = 0x40;
        packet[116] = 0x00;
        
        j += 6;
        
        return j;
}




main(argc,argv)

int argc;
char *argv[];

{

        struct sockaddr_in client, server;
        int one = 1;
        int packetsize;
        int s;
        int i;

        if (argc < 2) {
                fprintf(stderr, "Usage: %s xx:xx:xx:xx:xx:xx\n", argv[0]);
                exit(1);
        }

        packetsize = get_magicpacket(magicpacket, argv[1]);
        
        if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
                perror("socket");

        if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char *)&one, sizeof(one)) < 0)
                perror("setsockopt");
        
        server.sin_family = AF_INET;
        server.sin_port = 0;
        server.sin_addr.s_addr = INADDR_ANY;
        
        client.sin_family = AF_INET;
        client.sin_port = 32768+666;
        client.sin_addr.s_addr = INADDR_BROADCAST;
        
        if (bind(s, (struct sockaddr *)&server, sizeof(server)) < 0)
                perror("bind");
                   
        if ((i = sendto(s, magicpacket, packetsize, 0, (struct sockaddr *)&client, sizeof(client))) < 0)
                perror("sendto");
                
        close(s);

        return 0;
        
}


