IP Utils
A comprehensive Go package for IP address and CIDR network calculations. This package provides utilities for working with IP addresses, CIDR blocks, subnetting, and more.
Features
- Calculate network details (network address, broadcast address, first/last usable IP)
- Determine total and usable IP addresses in a CIDR block
- Subnet networks into smaller networks
- Convert between CIDR notation and netmask format
- Check if an IP is within a CIDR block
- Determine if CIDRs overlap
- Format network sizes in human-readable format
- Manage sets of IP addresses with efficient operations (union, intersection, difference)
- Convert between IP ranges and CIDR blocks
- Convert wildcard notation (e.g., 192.168..) to CIDR blocks
- Convert octet ranges (e.g., 192.168.[1-5].0) to CIDR blocks
- Check if an IP is in a private range or bogon range
- Advanced functionality like supernets and next/previous networks
- Iterate through IP addresses in a CIDR block
Installation
go get -u github.com/Dontjustadream/ip-utils
Project Structure
github.com/Dontjustadream/ip-utils/
├── cidr/ # Core CIDR operations
│ ├── cidr.go # CIDR type and basic methods
│ ├── subnet.go # Subnetting operations
│ └── iterate.go # IP iteration utilities
├── ipset/ # IP Set operations
│ ├── ipset.go # IPSet type and basic methods
│ ├── operations.go # Set operations (union, intersection, etc.)
│ └── io.go # File I/O for IP sets
├── convert/ # Format conversion utilities
│ ├── netmask.go # CIDR and netmask conversions
│ ├── range.go # IP range conversions
│ ├── wildcard.go # Wildcard and octet range conversions
│ └── format.go # Human-readable formatting
├── check/ # IP validation and classification
│ ├── private.go # Private IP detection
│ ├── bogon.go # Bogon IP detection
│ └── version.go # IPv4/IPv6 detection
└── util/ # Common utilities
├── ip.go # IP manipulation (clone, increment, etc.)
└── math.go # Math utilities
Basic Usage
package main
import (
"fmt"
"github.com/Dontjustadream/ip-utils/cidr"
"github.com/Dontjustadream/ip-utils/check"
"github.com/Dontjustadream/ip-utils/ipset"
)
func main() {
// Create a new CIDR object
c, err := cidr.New("192.168.1.0/24")
if err != nil {
panic(err)
}
// Get basic information
fmt.Printf("CIDR: %s\n", c.String())
fmt.Printf("Network: %s\n", c.NetworkIP)
fmt.Printf("Broadcast: %s\n", c.BroadcastIP)
fmt.Printf("First usable IP: %s\n", c.FirstIP)
fmt.Printf("Last usable IP: %s\n", c.LastIP)
fmt.Printf("Total IPs: %s\n", c.TotalIPs)
fmt.Printf("Usable IPs: %s\n", c.UsableIPs)
// Check if an IP is in the network
ip := "192.168.1.10"
fmt.Printf("Is %s in the network? %v\n", ip, c.Contains(ip))
// Check if an IP is in a private range
if check.IsPrivateIP(ip) {
fmt.Println("IP is in a private range")
}
// Check if an IP is a bogon
if check.IsBogonIP(ip) {
fmt.Println("IP is a bogon")
}
// Create a set of IPs
set := ipset.New()
set.Add("192.168.1.1")
set.Add("192.168.1.2")
set.AddCIDR("10.0.0.0/30")
fmt.Printf("Set contains %d IPv4 addresses\n", set.GetIPv4Count())
}
Working with CIDRs
// Subnet a network into smaller networks
subnets, err := c.Subnet(26) // Split into /26 networks
if err != nil {
panic(err)
}
fmt.Printf("Subnets: %d\n", len(subnets))
for _, subnet := range subnets {
fmt.Printf(" %s (%s IPs)\n", subnet.String(), subnet.TotalIPs)
}
// Iterate through all IPs in a network (use with caution for large networks!)
fmt.Println("First 5 IPs in the network:")
count := 0
c.Each(func(ip string) bool {
fmt.Printf(" %s\n", ip)
count++
return count < 5 // Only process the first 5 IPs
})
// Check if networks overlap
net1, _ := cidr.New("192.168.1.0/24")
net2, _ := cidr.New("192.168.0.0/16")
if net1.Overlaps(net2) {
fmt.Println("Networks overlap")
}
Working with IP Sets
// Create a new IP set
set := ipset.New()
// Add IPs to the set
set.Add("192.168.1.1")
set.Add("192.168.1.2")
set.Add("2001:db8::1")
// Add a CIDR block
set.AddCIDR("192.168.2.0/24")
// Check if an IP is in the set
if set.Contains("192.168.1.1") {
fmt.Println("IP found in set")
}
// Get counts
fmt.Printf("IPv4 count: %d\n", set.GetIPv4Count())
fmt.Printf("IPv6 count: %d\n", set.GetIPv6Count())
fmt.Printf("Total IPs: %d\n", set.Size())
// Convert to optimized CIDR blocks
ipv4CIDRs, ipv6CIDRs, _ := set.ToCIDRs()
fmt.Println("IPv4 CIDRs:")
for _, c := range ipv4CIDRs {
fmt.Println(c.String())
}
// Set operations
setA := ipset.New()
setA.Add("192.168.1.1")
setA.Add("192.168.1.2")
setB := ipset.New()
setB.Add("192.168.1.2")
setB.Add("192.168.1.3")
// Union of sets
unionSet := ipset.Union(setA, setB)
fmt.Printf("Union has %d IPs\n", unionSet.Size())
// Intersection
setA.Intersection(setB)
fmt.Printf("After intersection, setA has %d IPs\n", setA.Size())
IP Checking Functions
ip := "192.168.1.1"
// Check IP version
if check.IsIPv4(ip) {
fmt.Println("This is an IPv4 address")
} else if check.IsIPv6(ip) {
fmt.Println("This is an IPv6 address")
}
// Check if IP is private
if check.IsPrivateIP(ip) {
fmt.Println("This is a private IP")
}
// Check if IP is a bogon (should not appear on public internet)
if check.IsBogonIP(ip) {
fmt.Println("This is a bogon IP")
}
// Check if IP is a loopback address
if check.IsLoopbackIP(ip) {
fmt.Println("This is a loopback IP")
}
// Check if IP is a documentation address
if check.IsDocumentationIP(ip) {
fmt.Println("This is a documentation IP")
}
// Convert netmask to prefix length
prefixLen, _ := convert.NetmaskToPrefixLen("255.255.255.0")
fmt.Printf("Prefix length: /%d\n", prefixLen)
// Convert prefix length to netmask
netmask, _ := convert.PrefixLenToNetmask(24)
fmt.Printf("Netmask: %s\n", netmask)
// Convert IP and netmask to CIDR notation
cidrNotation, _ := convert.NetmaskToCIDR("192.168.1.0", "255.255.255.0")
fmt.Printf("CIDR notation: %s\n", cidrNotation)
// Convert IP range to CIDRs
cidrs, _ := convert.IPRangeToCIDRs("192.168.1.0", "192.168.2.255")
fmt.Println("CIDRs that cover the range:")
for _, c := range cidrs {
fmt.Println(c.String())
}
Wildcard and Octet Range Conversions
import "github.com/Dontjustadream/ip-utils/convert"
// Convert wildcard notation to CIDR blocks
cidrs, err := convert.WildcardToCIDRs("192.168.*.*")
if err != nil {
panic(err)
}
fmt.Printf("192.168.*.* = %s\n", cidrs[0].String()) // 192.168.0.0/16
// Convert octet range notation to CIDR blocks
cidrs, err = convert.OctetRangeToCIDRs("192.168.[1-5].0")
if err != nil {
panic(err)
}
fmt.Printf("192.168.[1-5].0 = %d CIDR blocks\n", len(cidrs))
for _, c := range cidrs {
fmt.Printf(" %s\n", c.String())
}
// Automatic detection of format (wildcard, range, CIDR, or single IP)
cidrs, err = convert.WildcardAndRangeToCIDRs("10.[1-2].*.*")
if err != nil {
panic(err)
}
fmt.Printf("10.[1-2].*.* = %d CIDR blocks\n", len(cidrs))
License
This project is licensed under the MIT License - see the LICENSE file for details.