it-tools icon indicating copy to clipboard operation
it-tools copied to clipboard

MAC to IPv6 Link-Local Converter

Open justwjx opened this issue 8 months ago • 1 comments

What type of request is this?

New tool idea

Clear and concise description of the feature you are proposing

`

MAC to IPv6 Link-Local Converter

MAC to IPv6 Link-Local Converter

    <div class="mb-4">
        <label for="macInput" class="block text-sm font-medium text-gray-700 mb-1">Enter MAC Address (XX:XX:XX:XX:XX:XX):</label>
        <input type="text" id="macInput" name="macInput" placeholder="e.g., 00:1A:2B:3C:4D:5E" class="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm">
    </div>

    <div class="text-center mb-6">
        <button id="convertBtn" class="bg-indigo-600 hover:bg-indigo-700 text-white font-bold py-2 px-4 rounded-md shadow focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 transition duration-150 ease-in-out">
            Convert
        </button>
    </div>

    <div id="outputSection" class="mt-4 hidden">
        <label class="block text-sm font-medium text-gray-700 mb-1">IPv6 Link-Local Address:</label>
        <div id="ipv6Output" class="mt-1 p-3 bg-gray-50 border border-gray-200 rounded-md text-gray-800 result-box">
            </div>
        <p id="errorMsg" class="mt-2 text-sm text-red-600 hidden"></p>
        <p id="infoMsg" class="mt-2 text-sm text-blue-600 hidden"></p> </div>

    <div id="explanation" class="mt-6 p-4 bg-blue-50 border border-blue-200 rounded-md text-sm text-blue-800 hidden">
         <h3 class="font-semibold mb-2">How it works:</h3>
         <ol class="list-decimal list-inside space-y-1">
             <li>The MAC address is split into two halves.</li>
             <li>'FFFE' is inserted in the middle.</li>
             <li>The 7th bit of the first byte is flipped (U/L bit).</li>
             <li>The result is combined with the 'fe80::' prefix.</li>
             <li>The final address is formatted canonically (lowercase, zero compression).</li>
         </ol>
    </div>

</div>

<script>
    const macInput = document.getElementById('macInput');
    const convertBtn = document.getElementById('convertBtn');
    const outputSection = document.getElementById('outputSection');
    const ipv6Output = document.getElementById('ipv6Output');
    const errorMsg = document.getElementById('errorMsg');
    const infoMsg = document.getElementById('infoMsg');
    const explanation = document.getElementById('explanation');

    convertBtn.addEventListener('click', () => {
        const mac = macInput.value.trim();
        // Reset previous messages
        errorMsg.textContent = '';
        errorMsg.classList.add('hidden');
        infoMsg.textContent = '';
        infoMsg.classList.add('hidden');
        ipv6Output.textContent = '';
        outputSection.classList.add('hidden');
        explanation.classList.add('hidden');


        // 1. Verify input format (XX:XX:XX:XX:XX:XX or XX-XX-XX-XX-XX-XX)
        const macRegex = /^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/;
        if (!macRegex.test(mac)) {
            showError("Invalid MAC address format. Please use XX:XX:XX:XX:XX:XX (hexadecimal).");
            return;
        }

        // Normalize MAC to use colons and lowercase
        const normalizedMac = mac.replace(/-/g, ':').toLowerCase();
        const parts = normalizedMac.split(':');

        // Check for multicast MAC (LSB of the first byte is 1)
        const firstByte = parseInt(parts[0], 16);
        if ((firstByte & 1) === 1) {
            showError("Multicast MAC addresses (first byte's LSB=1) cannot be converted to EUI-64 based link-local addresses.");
            return;
        }

        try {
            // 2. Split MAC
            const firstHalf = parts.slice(0, 3); // ['00', '1a', '2b']
            const secondHalf = parts.slice(3, 6); // ['3c', '4d', '5e']

            // 3. Insert FFFE
            const middle = ['ff', 'fe'];

            // 4. Flip the 7th bit of the first byte (U/L bit)
            // Convert first byte to binary, flip the 7th bit (index 6), convert back to hex
            let firstByteInt = parseInt(firstHalf[0], 16);
            firstByteInt ^= 0x02; // XOR with 00000010 flips the 7th bit
            const modifiedFirstByte = firstByteInt.toString(16).padStart(2, '0');

            // Construct the interface identifier parts
            const interfaceIdentifier = [
                modifiedFirstByte, firstHalf[1], firstHalf[2],
                middle[0], middle[1],
                secondHalf[0], secondHalf[1], secondHalf[2]
            ]; // ['02', '1a', '2b', 'ff', 'fe', '3c', '4d', '5e']

            // 5. Combine with fe80:: prefix and format
            // Group into 4-hextet segments
            const hextets = [];
            for (let i = 0; i < interfaceIdentifier.length; i += 2) {
                hextets.push(interfaceIdentifier[i] + interfaceIdentifier[i+1]);
            } // ['021a', '2bff', 'fe3c', '4d5e']

            // Format according to RFC 5952 (Canonical IPv6 Address Representation)
            // Start with the prefix
            let ipv6String = 'fe80::';

            // Add the interface identifier hextets
            ipv6String += hextets.map(h => parseInt(h, 16).toString(16)).join(':'); // Remove leading zeros within hextets

            // Display result
            ipv6Output.textContent = ipv6String;
            outputSection.classList.remove('hidden');
            explanation.classList.remove('hidden'); // Show explanation on success
            showInfo(`Successfully converted MAC ${normalizedMac}. The 7th bit (U/L bit) of the first byte (${parts[0]}) was flipped to ${modifiedFirstByte}.`);

        } catch (error) {
            console.error("Conversion error:", error);
            showError("An unexpected error occurred during conversion.");
        }
    });

    function showError(message) {
        errorMsg.textContent = message;
        errorMsg.classList.remove('hidden');
        outputSection.classList.remove('hidden'); // Show section to display the error
        ipv6Output.textContent = ''; // Clear any previous success result
        explanation.classList.add('hidden');
    }

     function showInfo(message) {
        infoMsg.textContent = message;
        infoMsg.classList.remove('hidden');
    }

    // Allow pressing Enter in the input field to trigger conversion
    macInput.addEventListener('keypress', function(event) {
        if (event.key === 'Enter') {
            event.preventDefault(); // Prevent default form submission if it were in a form
            convertBtn.click(); // Trigger the button click
        }
    });

</script>
`

Is their example of this tool in the wild?

Image

Additional context

No response

Validations

  • [x] Check the feature is not already implemented in the project.
  • [x] Check that there isn't already an issue that request the same feature to avoid creating a duplicate.
  • [x] Check that the feature can be implemented in a client side only app (IT-Tools is client side only, no server).

justwjx avatar Apr 30 '25 02:04 justwjx

Hi @justwjx, implemented here : https://sharevb-it-tools.vercel.app/mac-address-converter

And if you are interested in an up to date version of it-tools, with many improvements, new tools, and bug fixes, as this repo is almost no more maintained, I made a fork here : https://github.com/sharevb/it-tools (https://sharevb-it-tools.vercel.app/ and docker images https://github.com/sharevb/it-tools/pkgs/container/it-tools)

sharevb avatar Nov 02 '25 13:11 sharevb