//
// Wake on LAN
//
//   usage: % wol 192.168.1.255 00:10:dc:50:8a:f4
//

#include	<stdio.h>
#include	<stdlib.h>
#include	<string.h>
#include	<ctype.h>

#include	<unistd.h>
#include	<sys/socket.h>
#include	<netinet/in.h>
#include	<netdb.h>

#include	<errno.h>


typedef		unsigned char	byte;
typedef		unsigned long	ulong;

int main(int argc, char* argv[])
{
	if (argc != 3 && argc != 4) { 
		printf("%% wol IP-bcast-addr MACaddr [port]\n"); 
		return -1; 
	}

	byte	mac[7];
	char*	p = argv[2];
	for (int i = 0; i < 6; i++, p+=3) {
		if (isxdigit(p[0]) && isxdigit(p[1]) && (!p[2] || p[2] == ':')) {
			ulong	a = strtoul(p, NULL, 16);
			if (a != ULONG_MAX) { mac[i] = (byte)a; continue; }
		}
		fprintf(stderr, "invalid MAC address.%d %s\n", i, p); return -1;
	}

	int		sockfd;
	struct	hostent*	host;
	struct	sockaddr_in	peeraddr;

	sockfd = socket(AF_INET, SOCK_DGRAM, 0);
	int		optval = 1;
	setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(optval));

	host = gethostbyname(argv[1]);
	memset(&peeraddr, 0, sizeof(peeraddr));
	peeraddr.sin_family = AF_INET;
	memcpy(&peeraddr.sin_addr, host->h_addr, host->h_length);
	
	// port
	int		port= 9;
	if(argc == 4)
		sscanf(argv[3], "%d", &port);
	peeraddr.sin_port = htons(port);	// discard

	char	buf[6+6*16];
	memset(buf, 0xff, 6);
	for (int i = 0; i < 16; i++) 
		memcpy(buf+6+i*6, mac, 6);

	sendto(sockfd, buf, 6+6*16, 0, (struct sockaddr*)&peeraddr, sizeof(peeraddr));

	return 0;
}
