Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.os.linux.misc > #86000

Re: CIDR Calculator

From Fritz Wuehler <fritz@spamexpire-202604.rodent.frell.theremailer.net>
Subject Re: CIDR Calculator
References <XnsB43B9C55314F7makowiecatnycapdotrE@157.180.91.226>
Message-ID <230682093e8d6870b570336706434104@msgid.frell.theremailer.net> (permalink)
Date 2026-04-29 00:08 +0200
Newsgroups comp.os.linux.misc
Organization dizum.com - The Internet Problem Provider

Show all headers | View raw


Joe Makowiec <makow...@invalid.invalid> [JM]:
JM> What I'm looking for, though, is one where you can feed it a
JM> low IP address and a high IP address, and it will figure out
JM> the (singular) range which covers all the IP addresses.

Here is a LLM-generated plain C and javascript/nodejs such
function. Take your pick.


// 8<---------------------------- C -------------------------

/*
 * findMinimumCIDR.c
 *
 * Build the smallest single CIDR block that contains two IPv4 addresses.
 *
 * Example:
 *   192.168.0.8 and 192.168.5.200  ->  192.168.0.0/21
 *
 * Build:
 *   cc -O2 -Wall -Wextra -std=c11 findMinimumCIDR.c -o findMinimumCIDR
 *
 * Run:
 *   ./findMinimumCIDR 192.168.0.8 192.168.5.200
 */

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>

static int parse_ipv4(const char *s, uint32_t *out)
{
    unsigned a, b, c, d;
    char tail;

    /* Ensure full-string match (no trailing junk) */
    if (sscanf(s, "%u.%u.%u.%u%c", &a, &b, &c, &d, &tail) != 4)
        return 0;
    if (a > 255 || b > 255 || c > 255 || d > 255)
        return 0;

    *out = (a << 24) | (b << 16) | (c << 8) | d;
    return 1;
}

static void ipv4_to_str(uint32_t ip, char buf[16])
{
    snprintf(buf, 16, "%u.%u.%u.%u",
             (ip >> 24) & 255u, (ip >> 16) & 255u, (ip >> 8) & 255u, ip & 255u);
}

static unsigned prefix_len_for_range(uint32_t a, uint32_t b)
{
    uint32_t x = a ^ b;           /* differing bits */
    unsigned common = 32;

    if (x != 0) {
        /* count leading zeros in x (portable loop) */
        common = 0;
        for (int i = 31; i >= 0; --i) {
            if ((x >> i) & 1u) break;
            common++;
        }
    }
    return common; /* number of equal leading bits => CIDR prefix length */
}

int main(int argc, char **argv)
{
    if (argc != 3) {
        fprintf(stderr, "Usage: %s <ipv4_1> <ipv4_2>\n", argv[0]);
        return 2;
    }

    uint32_t ip1, ip2;
    if (!parse_ipv4(argv[1], &ip1) || !parse_ipv4(argv[2], &ip2)) {
        fprintf(stderr, "Invalid IPv4 address.\n");
        return 2;
    }

    unsigned prefix = prefix_len_for_range(ip1, ip2);

    uint32_t mask = (prefix == 0) ? 0u : (0xFFFFFFFFu << (32 - prefix));
    uint32_t network = ip1 & mask; /* ip1 and ip2 share these prefix bits */

    char netstr[16];
    ipv4_to_str(network, netstr);
    printf("%s/%u\n", netstr, prefix);

    return 0;
}



// 8<--------------------- javascript/nodejs ----------------

/* How it works:

1. IP to Integer Conversion: Converts each IPv4 address to a 32-bit integer for bitwise operations.

2. XOR Operation: Uses XOR (`^`) to find where the two IP addresses differ in their binary representation.

3. Prefix Length Calculation: Counts the number of leading bits that are the same in both addresses by examining the XOR result.

4. Network Address Calculation: Creates a network mask and applies it to find the network address.

5. CIDR Format: Returns the result in CIDR notation (network/prefix-length).

Example walkthrough with `192.168.0.8` and `192.168.5.200`:

- 192.168.0.8 = 11000000.10101000.00000000.00001000
- 192.168.5.200 = 11000000.10101000.00000101.11001000
- XOR result shows differences starting at bit 21
- First 21 bits are common, so prefix length is 21
- Network address: `192.168.0.0/21`

The function handles the parameters in any order and will always return the same CIDR range regardless of which IP is passed first.
*/

function findMinimumCIDR(ip1, ip2) {
    // Convert IP address string to 32-bit integer
    function ipToInt(ip) {
        return ip.split('.').reduce((acc, octet, index) => {
            return acc + (parseInt(octet) << (8 * (3 - index)));
        }, 0) >>> 0; // Use unsigned right shift to ensure positive integer
    }
    
    // Convert 32-bit integer back to IP address string
    function intToIp(int) {
        return [
            (int >>> 24) & 255,
            (int >>> 16) & 255,
            (int >>> 8) & 255,
            int & 255
        ].join('.');
    }
    
    // Convert both IPs to integers
    const int1 = ipToInt(ip1);
    const int2 = ipToInt(ip2);
    
    // Find the XOR to see where bits differ
    const xor = int1 ^ int2;
    
    // Count leading zeros in the XOR result to find common prefix length
    let prefixLength = 0;
    let mask = 0x80000000; // Start with leftmost bit
    
    for (let i = 0; i < 32; i++) {
        if ((xor & mask) === 0) {
            prefixLength++;
            mask >>>= 1;
        } else {
            break;
        }
    }
    
    // Create network mask
    const networkMask = (0xFFFFFFFF << (32 - prefixLength)) >>> 0;
    
    // Calculate network address (use the smaller IP for consistency)
    const networkAddress = Math.min(int1, int2) & networkMask;
    
    return `${intToIp(networkAddress)}/${prefixLength}`;
}

// Testing
console.log(findMinimumCIDR('192.168.0.8', '192.168.5.200'));   // 192.168.0.0/21
console.log(findMinimumCIDR('192.168.5.200', '192.168.0.8'));   // 192.168.0.0/21

// Additional test cases
console.log(findMinimumCIDR('10.0.0.1', '10.0.0.2'));           // 10.0.0.0/30
console.log(findMinimumCIDR('192.168.1.1', '192.168.1.1'));     // 192.168.1.1/32
console.log(findMinimumCIDR('172.16.0.1', '172.17.255.254'));   // 172.16.0.0/15

Back to comp.os.linux.misc | Previous | NextPrevious in thread | Next in thread | Find similar


Thread

CIDR Calculator Joe Makowiec <makowiec@invalid.invalid> - 2026-04-27 19:22 +0000
  Re: CIDR Calculator John Ames <commodorejohn@gmail.com> - 2026-04-27 13:31 -0700
    Re: CIDR Calculator Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-04-29 01:59 +0000
  Re: CIDR Calculator Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-04-27 22:35 +0000
  Re: CIDR Calculator Marc Haber <mh+usenetspam2616@zugschl.us> - 2026-04-28 07:49 +0200
    Re: CIDR Calculator Rene Kita <mail@rkta.de> - 2026-04-29 07:09 +0000
      Re: CIDR Calculator Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-04-29 08:05 +0000
  Re: CIDR Calculator Fritz Wuehler <fritz@spamexpire-202604.rodent.frell.theremailer.net> - 2026-04-29 00:08 +0200
  Re: CIDR Calculator 🇵🇱Jacek Marcin Jaworski🇵🇱 <jmj@energokod.gda.pl> - 2026-04-29 07:10 +0200
    Re: CIDR Calculator 🇵🇱Jacek Marcin Jaworski🇵🇱 <jmj@energokod.gda.pl> - 2026-04-29 23:52 +0200

csiph-web