For a project that I’m working on I had to create MAC generator. Initially I decided that I will do it in BASH.

function gen_mac() {
        mac_vars=(0 1 2 3 4 5 6 7 8 9 a b c d e f)
        mac_base='52:53:54:'
        ret=''
        for i in {1..6}; do
                n=$RANDOM
                let 'n %= 16'
                ret="${ret}${mac_vars[$n]}"
                if [ $i -eq 2 ] || [ $i -eq 4 ]; then
                        ret="${ret}:"
                fi
        done
        echo "${mac_base}${ret}"
}

But unfortunately I had to rewrite it in plpgsql in order to prevent a stupid race condition that can appear.

CREATE OR REPLACE FUNCTION generate_mac() RETURNS text
    LANGUAGE plpgsql
    AS $$DECLARE
	mac TEXT;
	a CHAR;
	count INTEGER;
BEGIN
	mac='52:53:54:';
	FOR count IN 1..6 LOOP
		SELECT substring('0123456789abcdef' FROM (random()*16)::int + 1 FOR 1) INTO a;
		-- This fixes un issue, wehre the above SELECT returns NULL or empty string
		-- If for some reason we concatenate with a NULL string, the result will be NULL string
		WHILE  a IS NULL OR a = '' LOOP
			SELECT substring('0123456789abcdef' FROM (random()*16)::int + 1 FOR 1) INTO a;
		END LOOP;
		mac = mac || a;
		IF count = 2 OR count = 4 THEN
			mac = mac || ':';
		END IF;
	END LOOP;
	RETURN mac;
END;$$;

Comments are closed.

Posted by HackMan
Dated: 25th March 2013
Filled Under: Uncategorized