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
135KB
2K SLoC
此模块提供用于处理IPv4和IPv6网络地址的类型和实用方法,通常称为IP前缀。新的IpNet
、Ipv4Net
和Ipv6Net
类型基于Rust标准库中已提供的IpAddr
、Ipv4Addr
和Ipv6Addr
类型,并与它们的设计保持一致。
该模块还提供了IpSubnets
、Ipv4Subnets
和Ipv6Subnets
类型,用于遍历IP地址范围内的子网。以及IpAddrRange
、Ipv4AddrRange
和Ipv6AddrRange
类型,用于遍历范围内的IP地址。此外,还提供了扩展Ipv4Addr
和Ipv6Addr
的特质,增加了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}
实现Ipv4Addr
和Ipv6Addr
会很有用,因为这些是 IP 地址上的常见操作。如果实现,本模块提供的扩展特征将被移除,并增加主版本号。实现这些需要更改标准库。我在 Rust 内部 讨论板上开始了这个话题的讨论。 hosts()
和潜在的subnets()
的结果应表示为Range
而不是本模块提供的自定义IpAddrRange
和IpSubnets
类型。这要求目标类型实现Add
和Step
。为IpAddr
、Ipv4Addr
和Ipv6Addr
实现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