Skip to content

Instantly share code, notes, and snippets.

@autch
Last active May 13, 2021 02:06
Show Gist options
  • Save autch/c5da605a42fa99838b72e23363adeab5 to your computer and use it in GitHub Desktop.
Save autch/c5da605a42fa99838b72e23363adeab5 to your computer and use it in GitHub Desktop.
Wake-On-LAN, Usage: ./wol.rb 192.168.0.255 01:23:45:67:89:ab
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define HWADDR_SIZE 6
#define WOL_PAYLOAD_SIZE (6 + HWADDR_SIZE * 16) // (0xff * 6) + (target hwaddr * 16)
int main(int argc, char** argv)
{
uint8_t mac[HWADDR_SIZE];
uint8_t buf[WOL_PAYLOAD_SIZE];
char* p = argv[2];
int sockfd;
struct hostent* host;
struct sockaddr_in peeraddr;
int optval = 1;
int i;
if(argc != 3) {
printf("%% wol IP-bcast-addr MACaddr\n");
return -1;
}
for(i = 0; i < HWADDR_SIZE; i++, p += 3) {
if(isxdigit(p[0]) && isxdigit(p[1]) && (!p[2] || p[2] == ':')) {
uint32_t a = strtoul(p, NULL, 16);
if(a != -1) { mac[i] = (uint8_t)a; continue; }
}
fprintf(stderr, "invalid MAC address.%d %s\n", i, p); return -1;
}
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
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_list[0], host->h_length);
peeraddr.sin_port = htons(9); // discard
memset(buf, 0xff, 6);
for(i = 0; i < 16; i++)
memcpy(buf + 6 + i * HWADDR_SIZE, mac, HWADDR_SIZE);
sendto(sockfd, buf, WOL_PAYLOAD_SIZE, 0, (struct sockaddr*)&peeraddr, sizeof(peeraddr));
close(sockfd);
return 0;
}
// go run wol.go 192.168.0.255 aa:bb:cc:dd:ee:ff
package main
import (
"bytes"
"encoding/hex"
"log"
"net"
"os"
"regexp"
)
func main() {
hexstr := regexp.MustCompile("[-: ]").ReplaceAllString(os.Args[2], "")
mac, err := hex.DecodeString(hexstr)
if err != nil {
log.Fatal(err)
}
buf := append(bytes.Repeat([]byte{0xff}, 6), bytes.Repeat(mac, 16)...)
dst, err := net.ResolveUDPAddr("udp", net.JoinHostPort(os.Args[1], "9"))
if err != nil {
log.Fatal(err)
}
conn, err := net.DialUDP("udp4", nil, dst)
if err != nil {
log.Fatal(err)
}
defer conn.Close()
_, err = conn.Write(buf)
}
const dgram = require('dgram');
const mac_addr = process.argv.pop();
const bcast_addr = process.argv.pop();
const HWADDR_SIZE = 6;
const buf = new Uint8Array(6 + HWADDR_SIZE * 16).fill(0xff, 0, 6);
const hwaddr = Uint8Array.from(mac_addr.split(/:/).map(i => parseInt(i, 16)));
for(let i = 0; i < 16; i++)
buf.set(hwaddr, 6 + HWADDR_SIZE * i);
const sock = dgram.createSocket('udp4');
sock.bind({ port: 0 }, () => {
sock.setBroadcast(true);
sock.send(buf, 9, bcast_addr, () => {
sock.close();
});
});
#!/usr/bin/env python
import sys
import socket
hwaddr = bytearray.fromhex(sys.argv[2].replace(':', ' '))
BUF = bytearray.fromhex('ff ' * 6)
BUF += hwaddr * 16
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
sock.sendto(BUF, (sys.argv[1], 9))
#!/usr/bin/env ruby
require 'socket'
hwaddr = [ARGV[1].gsub(/:/, '')].pack('H12')
buffer = ("\xff" * 6).force_encoding('BINARY')
buffer += hwaddr * 16
sock = UDPSocket.new()
sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_BROADCAST, 1)
sock.send(buffer, 0, ARGV[0], 9)
use std::env;
use std::net::{Ipv4Addr, SocketAddrV4, UdpSocket};
fn main() {
let args: Vec<String> = env::args().collect();
let bcast_addr: Ipv4Addr = args[1].parse().expect("invalid broadcast addr");
let hw_addr: Vec<u8> = args[2]
.split(':')
.map(|c| u8::from_str_radix(c, 16).unwrap())
.collect();
let mut buf: Vec<u8> = vec![0xff].repeat(6);
buf.extend_from_slice(&hw_addr.repeat(16));
let socket = UdpSocket::bind("0.0.0.0:0").expect("Cannot bind to address");
socket.set_broadcast(true).expect("set_broadcast failed");
socket
.send_to(&buf, SocketAddrV4::new(bcast_addr, 9))
.expect("Cannot send magic packet");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment