#ip-address #ip #subnet #networking #prefix #cidr #address-range

无需std ipnet

提供用于处理IPv4和IPv6网络地址的类型和实用方法,通常称为IP前缀。新的IpNetIpv4NetIpv6Net类型基于Rust标准库中已提供的IpAddrIpv4AddrIpv6Addr类型,并与它们的设计保持一致。该模块还提供了扩展Ipv4AddrIpv6Addr的实用特质,增加了AddSubBitAndBitOr操作的方法。该模块只使用稳定特性,因此保证使用稳定工具链进行编译。

65个版本 (18个稳定版本)

2.9.0 2023年10月22日
2.8.0 2023年6月26日
2.7.2 2023年3月27日
2.7.0 2022年12月11日
0.28.1 2017年9月21日

1 in #ip-address

Download history 1156772/week @ 2024-04-26 1129547/week @ 2024-05-03 1172513/week @ 2024-05-10 1192914/week @ 2024-05-17 1143382/week @ 2024-05-24 1296032/week @ 2024-05-31 1264726/week @ 2024-06-07 1252425/week @ 2024-06-14 1314672/week @ 2024-06-21 1214404/week @ 2024-06-28 1217306/week @ 2024-07-05 1293418/week @ 2024-07-12 1341341/week @ 2024-07-19 1339303/week @ 2024-07-26 1358935/week @ 2024-08-02 1196103/week @ 2024-08-09

每月下载量 5,469,044
13,564crate中使用 (直接使用198个)

MIT/Apache

135KB
2K SLoC

Build Status

此模块提供用于处理IPv4和IPv6网络地址的类型和实用方法,通常称为IP前缀。新的IpNetIpv4NetIpv6Net类型基于Rust标准库中已提供的IpAddrIpv4AddrIpv6Addr类型,并与它们的设计保持一致。

该模块还提供了IpSubnetsIpv4SubnetsIpv6Subnets类型,用于遍历IP地址范围内的子网。以及IpAddrRangeIpv4AddrRangeIpv6AddrRange类型,用于遍历范围内的IP地址。此外,还提供了扩展Ipv4AddrIpv6Addr的特质,增加了Rust标准库中缺失的加法、减法、按位与和按位或操作的方法。

该模块仅使用稳定特性,因此保证使用稳定工具链进行编译。测试旨在实现全面覆盖,可以在测试模块和doctests中找到。如果您有任何问题、请求或建议的改进,请在GitHub上提交问题

请参阅文档以获取完整详情。您可以在Crates.io上找到它。

2.0 版本要求

2.0 版本需要 Rust 1.26 或更高版本。1.0 版本使用了一个自定义的模拟 128 位整数类型(Emu128)以完全支持 IPv6 地址。这已经被 Rust 的内置 128 位整数所取代,自 Rust 1.26 起已稳定。有报告称在某些目标(例如 Emscripten)上使用 Rust 的 128 位整数存在问题。如果您在所选目标上遇到问题,请在问题解决之前继续使用 1.0 版本。

示例

创建一个网络地址并打印主机掩码和网络掩码

extern crate ipnet;
use std::net::{Ipv4Addr, Ipv6Addr};
use std::str::FromStr;
use ipnet::{IpNet, Ipv4Net, Ipv6Net};

fn main() {
    // Create an Ipv4Net and Ipv6Net from their constructors.

    let net4 = Ipv4Net::new(Ipv4Addr::new(10, 1, 1, 0), 24).unwrap();
    let net6 = Ipv6Net::new(Ipv6Addr::new(0xfd, 0, 0, 0, 0, 0, 0, 0), 24).unwrap();

    // They can also be created from string representations.

    let net4 = Ipv4Net::from_str("10.1.1.0/24").unwrap();
    let net6 = Ipv6Net::from_str("fd00::/24").unwrap();

    // Or alternatively as follows.
    
    let net4: Ipv4Net = "10.1.1.0/24".parse().unwrap();
    let net6: Ipv6Net = "fd00::/24".parse().unwrap();

    // IpNet can represent either an IPv4 or IPv6 network address.

    let net = IpNet::from(net4);
    
    // It can also be created from string representations.

    let net = IpNet::from_str("10.1.1.0/24").unwrap();
    let net: IpNet = "10.1.1.0/24".parse().unwrap();

    // There are a number of methods that can be used. Read the
    // documentation for the full details.

    println!("{} hostmask = {}", net, net.hostmask());
    println!("{} netmask = {}", net4, net4.netmask());
}

将现有的 IP 网络细分为更小的子网

extern crate ipnet;
use ipnet::Ipv4Net;

fn main() {
    let net: Ipv4Net = "192.168.0.0/23".parse().unwrap();

    println!("\n/25 subnets in {}:", net);

    // Note: `subnets()` returns a `Result`. If the given prefix length
    // is less than the existing prefix length the `Result` will contain
    // an error.

    let subnets = net.subnets(25)
        .expect("PrefixLenError: new prefix length cannot be shorter than existing");

    // Output:
    //  subnet 0 = 192.168.0.0/25
    //  subnet 1 = 192.168.0.128/25
    //  subnet 2 = 192.168.1.0/25
    //  subnet 3 = 192.168.1.128/25

    for (i, n) in subnets.enumerate() {
        println!("\tsubnet {} = {}", i, n);
    }
}

遍历两个 IPv4 地址之间的有效子网

extern crate ipnet;
use std::net::Ipv4Addr;
use ipnet::Ipv4Subnets;

fn main() {
    let start = Ipv4Addr::new(10, 0, 0, 0);
    let end = Ipv4Addr::new(10, 0, 0, 239);

    println!("\n/0 or greater subnets between {} and {}:", start, end);

    // Output all subnets starting with the largest that will fit. This
    // will give us the smallest possible set of valid subnets.
    //
    // Output:
    //  subnet 0 = 10.0.0.0/25
    //  subnet 1 = 10.0.0.128/26
    //  subnet 2 = 10.0.0.192/27
    //  subnet 3 = 10.0.0.224/28

    let subnets = Ipv4Subnets::new(start, end, 0);

    for (i, n) in subnets.enumerate() {
        println!("\tsubnet {} = {}", i, n);
    }

    println!("\n/26 or greater subnets between {} and {}:", start, end);

    // Output all subnets with prefix lengths less than or equal to 26.
    // This results in more subnets, but limits them to a maximum size.
    //
    // Output:
    //  subnet 0 = 10.0.0.0/26
    //  subnet 1 = 10.0.0.64/26
    //  subnet 2 = 10.0.0.128/26
    //  subnet 3 = 10.0.0.192/27
    //  subnet 4 = 10.0.0.224/28

    let subnets = Ipv4Subnets::new(start, end, 26);

    for (i, n) in subnets.enumerate() {
        println!("\tsubnet {} = {}", i, n);
    }
}

聚合一系列 IP 前缀

extern crate ipnet;
use ipnet::IpNet;

fn main() {}
    // Example input list of overlapping and adjacent prefixes.

    let strings = vec![
        "10.0.0.0/24", "10.0.1.0/24", "10.0.1.1/24", "10.0.1.2/24",
        "10.0.2.0/24",
        "10.1.0.0/24", "10.1.1.0/24",
        "192.168.0.0/24", "192.168.1.0/24", "192.168.2.0/24", "192.168.3.0/24",
        "fd00::/32", "fd00:1::/32",
    ];

    let nets: Vec<IpNet> = strings.iter().filter_map(|p| p.parse().ok()).collect();
    
    println!("\nAggregated IP prefixes:");
    
    // Output:
    //  10.0.0.0/23
    //  10.0.2.0/24
    //  10.1.0.0/23
    //  192.168.0.0/22
    //  fd00::/31
    
    for n in IpNet::aggregate(&nets) {
        println!("\t{}", n);
    }
}

未来

  • std::ops::{Add, Sub, BitAnd, BitOr} 实现 Ipv4AddrIpv6Addr 会很有用,因为这些是 IP 地址上的常见操作。如果实现,本模块提供的扩展特征将被移除,并增加主版本号。实现这些需要更改标准库。我在 Rust 内部 讨论板上开始了这个话题的讨论。
  • hosts() 和潜在的 subnets() 的结果应表示为 Range 而不是本模块提供的自定义 IpAddrRangeIpSubnets 类型。这要求目标类型实现 AddStep。为 IpAddrIpv4AddrIpv6Addr 实现 Add 需要更改标准库(见上文)。而 Step 仍然是不稳定的,所以探索这个话题也要等到它稳定之后。

许可协议

版权所有(c)2017,Juniper Networks,Inc. 保留所有权利。

此代码的许可协议为 MIT 许可证或 Apache 许可证 2.0 版,您可选择("许可")。您只能在不违反许可协议的情况下使用此代码。此代码不是 Juniper 的官方产品。您可以在以下位置获取许可协议的副本:[https://opensource.org/licenses/MIT](https://opensource.org/licenses/MIT) 或 [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)

依赖项

~0–435KB