Skip to content

MAC Address Generator — C source

Generate random EUI-48 MAC addresses with a chosen separator, optional OUI prefix, uppercase formatting, and a locally-administered flag. Runs entirely in your browser with crypto-grade randomness.

This is the C implementation — the same logic the interactive tool runs, in a shareable, citable form.

/* mac-address-generator — random EUI-48 MAC address generator. C99 port
 * (canonical TS: src/lib/mac-generator.ts; Go twin: cli/mac-address-generator).
 * Octets come from rand() seeded once (the TS default draws from
 * crypto.getRandomValues; C99 has no portable crypto source). %02x pairs are
 * sprintf'd into a caller buffer, joined with the separator. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

typedef struct {
    const char *separator;     /* NULL -> ":" */
    int uppercase;
    const char *oui;           /* NULL or "" -> random OUI octets */
    int locally_administered;  /* force U/L bit (0x02) of the first octet */
} MacOptions;

/* Strip non-hex chars, require exactly 6 digits, parse the 3 OUI octets. */
static int parse_oui(const char *oui, unsigned char out[3]) {
    char clean[8] = {0};
    int n = 0;
    for (const char *p = oui; *p; p++)
        if (isxdigit((unsigned char)*p)) {
            if (n == 6) return 0; /* too many hex digits */
            clean[n++] = *p;
        }
    if (n != 6) return 0;
    for (int i = 0; i < 3; i++) {
        char pair[3] = { clean[i * 2], clean[i * 2 + 1], 0 };
        out[i] = (unsigned char)strtoul(pair, NULL, 16);
    }
    return 1;
}

/* Build a random EUI-48 MAC: 3 OUI octets (given or random) + 3 random, U/L
 * bit forced when asked, joined as %02x with the separator. out must hold
 * 12 hex digits + 5 separators + 1 NUL. */
static void generate_mac(const MacOptions *o, char *out) {
    unsigned char oct[6];
    if (o->oui && *o->oui) {
        if (!parse_oui(o->oui, oct)) {
            fprintf(stderr, "OUI must be 6 hex digits, got \"%s\"\n", o->oui);
            exit(1);
        }
    } else {
        for (int i = 0; i < 3; i++) oct[i] = (unsigned char)(rand() & 0xFF);
    }
    for (int i = 3; i < 6; i++) oct[i] = (unsigned char)(rand() & 0xFF);
    if (o->locally_administered) oct[0] = (unsigned char)((oct[0] & 0xFD) | 0x02);
    const char *sep = o->separator ? o->separator : ":";
    char *w = out;
    for (int i = 0; i < 6; i++) {
        if (i) w += sprintf(w, "%s", sep);
        w += sprintf(w, "%02x", oct[i]);
    }
    if (o->uppercase)
        for (char *p = out; *p; p++) *p = (char)toupper((unsigned char)*p);
}

int main(void) {
    srand(42); /* demo seed */
    char mac[64];
    generate_mac(&(MacOptions){0}, mac), puts(mac); /* 6 random hex pairs */
    generate_mac(&(MacOptions){.separator = "-"}, mac), puts(mac);
    generate_mac(&(MacOptions){.oui = "aa-bb-cc"}, mac), puts(mac); /* aa:bb:cc:xx:xx:xx */
    generate_mac(&(MacOptions){.locally_administered = 1, .uppercase = 1}, mac), puts(mac); /* first pair ends in 2 */
    return 0;
}

Also available in 13 other languages

Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →