magiclen / cidr-utils

This crate provides functions for working with IPv4 CIDRs and IPv6 CIDRs.
MIT License
32 stars 11 forks source link

Incorrect value for cidr first/last #5

Closed ian-hamlin closed 4 years ago

ian-hamlin commented 4 years ago

Given the following example:

use cidr_utils::cidr::IpCidr;

fn main() {
    let cidr = IpCidr::from_str("100.64.0.0/10");

    match cidr {
        Ok(IpCidr::V4(cidr)) => {
            println!("{:?} {:?}", cidr.first(), cidr.last());
            println!("{:?} {:?}", cidr.first_as_ipv4_addr(), cidr.last_as_ipv4_addr());
            println!("{:?} {:?}", u32::from(cidr.first_as_ipv4_addr()), u32::from(cidr.last_as_ipv4_addr()));
        },
        _ => {},
    }
}

It prints the following:

16484 4294934372 100.64.0.0 100.127.255.255 1681915904 1686110207

The value for cidr last seems wrong, it should be 1686110207

Edit* The value for first also seems wrong, I've updated the example to show the u32 conversions.

magiclen commented 4 years ago

It is not exactly wrong. More precisely, it should be blamed on bad documentation or the API.

The u32 value returned by the first or last methods is used to represent an IPv4 byte array in native byte order (NE). However, u32::from(cidr.first_as_ipv4_addr()) always uses big-endian byte order (BE) to convert the byte array into an u32 value.

It is confusable because IP values are usually stored in big-endian (which is also known as network byte order). I plan to make this crate use BE instead of NE in the next minor version.

ian-hamlin commented 4 years ago

Thank you for the explanation, that makes perfect sense!

magiclen commented 4 years ago

It's done.

ian-hamlin commented 4 years ago

Amazing, thanks.