You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

50 lines
1.1 KiB

#include <net/if.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
unsigned char get_byte(FILE *fp) {
unsigned char ret = 0;
for (int i = 0; i < 2; ++i) {
int c = getc(fp);
if (c == EOF)
perror("getc"), exit(1);
c = c > '9' ? c - 'a' + 0xa : c - '0' + 0x0;
if (c > 0xf)
fputs("unexpected char in serial number\n", stderr), exit(1);
ret <<= 4;
ret |= c;
}
return ret;
}
int main(int argc, char *argv[]) {
if (argc != 2)
fputs("Expected a single argument.\n", stderr), exit(1);
struct ifreq dev;
strcpy(dev.ifr_name, argv[1]);
int sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0)
perror("socket"), exit(1);
if (ioctl(sock, SIOCGIFHWADDR, &dev) < 0)
perror("get hwaddr ioctl"), exit(1);
FILE *fp = fopen("/sys/firmware/devicetree/base/serial-number", "r");
if (!fp)
perror("serial-number fopen"), exit(1);
dev.ifr_hwaddr.sa_data[0] = get_byte(fp);
if (fseek(fp, 4, SEEK_CUR))
perror("fseek"), exit(1);
for (uint i = 1; i < 6; ++i)
dev.ifr_hwaddr.sa_data[i] = get_byte(fp);
if (ioctl(sock, SIOCSIFHWADDR, &dev) < 0)
perror("set hwaddr ioctl"), exit(1);
}