├── go.mod ├── .gitignore ├── helpers.go ├── v6.go ├── parse.go ├── v4.go ├── LICENSE └── README.md /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/m7shapan/cidr 2 | 3 | go 1.13 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, built with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | 14 | # Dependency directories (remove the comment below to include it) 15 | # vendor/ 16 | -------------------------------------------------------------------------------- /helpers.go: -------------------------------------------------------------------------------- 1 | package cidr 2 | 3 | import ( 4 | "encoding/binary" 5 | "math/big" 6 | "net" 7 | ) 8 | 9 | // IPv4tod convert IPv4 to decimal 10 | // in case IP is not IPv4 will return 0 11 | func IPv4tod(ip net.IP) uint32 { 12 | if ip.To4() == nil { 13 | return 0 14 | } 15 | 16 | ip = ip.To4() 17 | var intIP uint32 18 | intIP += uint32(ip[0]) << 24 19 | intIP += uint32(ip[1]) << 16 20 | intIP += uint32(ip[2]) << 8 21 | intIP += uint32(ip[3]) 22 | 23 | return intIP 24 | } 25 | 26 | // IPv6tod convert IPv6 to decimal 27 | // in case IP is not IPv6 will return nil 28 | func IPv6tod(ip net.IP) *big.Int { 29 | if ip.To4() != nil { 30 | return nil 31 | } 32 | return big.NewInt(0).SetBytes(ip.To16()) 33 | } 34 | 35 | func DtoIPv4(i uint32) net.IP { 36 | ip := make(net.IP, 4) 37 | binary.BigEndian.PutUint32(ip, i) 38 | 39 | return ip 40 | } 41 | 42 | func DtoIPv6(i *big.Int) net.IP { 43 | ip := make(net.IP, 16) 44 | ip = i.Bytes() 45 | 46 | return ip 47 | } 48 | -------------------------------------------------------------------------------- /v6.go: -------------------------------------------------------------------------------- 1 | package cidr 2 | 3 | import ( 4 | "math/big" 5 | "net" 6 | ) 7 | 8 | func (p *ParsedCIDR) getLastIPv6() net.IP { 9 | if p.IsIPv6 != true { 10 | return nil 11 | } 12 | 13 | ip := make(net.IP, 16) 14 | ip = p.LastIPv6().Bytes() 15 | return ip 16 | } 17 | 18 | // FirstIPv6 return Decimal FirstIP 19 | func (p *ParsedCIDR) FirstIPv6() *big.Int { 20 | if p.IsIPv6 != true { 21 | return nil 22 | } 23 | 24 | IPInt := big.NewInt(0) 25 | return IPInt.SetBytes(p.FirstIP.To16()) 26 | } 27 | 28 | // HostCountIPv6 return number of IPs on the parsed range 29 | func (p *ParsedCIDR) HostCountIPv6() *big.Int { 30 | ones, bits := p.IPNet.Mask.Size() 31 | var max = big.NewInt(1) 32 | 33 | return max.Lsh(max, uint(bits-ones)) 34 | } 35 | 36 | // LastIPv6 return Decimal LastIP 37 | func (p *ParsedCIDR) LastIPv6() *big.Int { 38 | if p.IsIPv6 != true { 39 | return nil 40 | } 41 | 42 | IPInt := p.FirstIPv6() 43 | return IPInt.Add(IPInt, big.NewInt(0).Sub(p.HostCountIPv6(), big.NewInt(1))) 44 | } 45 | -------------------------------------------------------------------------------- /parse.go: -------------------------------------------------------------------------------- 1 | package cidr 2 | 3 | import ( 4 | "net" 5 | ) 6 | 7 | // An ParsedCIDR contains 8 | // FirstIP the first ip of the parsed range 9 | // LasttIP the last ip of the parsed range 10 | // IPNet represents an IP network 11 | // IsIPv4 check for IPv4 12 | // IsIPv6 check for IPv6 13 | type ParsedCIDR struct { 14 | FirstIP net.IP 15 | LastIP net.IP 16 | IPNet *net.IPNet 17 | IsIPv4 bool 18 | IsIPv6 bool 19 | } 20 | 21 | // ParseCIDR return ParsedCIDR for the provided IP Range 22 | func ParseCIDR(s string) (*ParsedCIDR, error) { 23 | firstIP, ipNet, err := net.ParseCIDR(s) 24 | if err != nil { 25 | return nil, err 26 | } 27 | 28 | var v4, v6 bool 29 | 30 | if firstIP.To4() != nil { 31 | v4 = true 32 | } else { 33 | v6 = true 34 | } 35 | 36 | parsed := ParsedCIDR{ 37 | FirstIP: firstIP, 38 | IPNet: ipNet, 39 | IsIPv4: v4, 40 | IsIPv6: v6, 41 | } 42 | 43 | if parsed.IsIPv4 { 44 | parsed.LastIP = parsed.getLastIPv4() 45 | } else { 46 | parsed.LastIP = parsed.getLastIPv6() 47 | } 48 | 49 | return &parsed, nil 50 | } 51 | -------------------------------------------------------------------------------- /v4.go: -------------------------------------------------------------------------------- 1 | package cidr 2 | 3 | import ( 4 | "encoding/binary" 5 | "net" 6 | ) 7 | 8 | func (p *ParsedCIDR) getLastIPv4() net.IP { 9 | if p.IsIPv4 != true { 10 | return nil 11 | } 12 | 13 | ip := make(net.IP, 4) 14 | binary.BigEndian.PutUint32(ip, p.LastIPv4()) 15 | 16 | return ip 17 | } 18 | 19 | // FirstIPv4 return Decimal FirstIP 20 | func (p *ParsedCIDR) FirstIPv4() uint32 { 21 | if p.IsIPv4 != true { 22 | return 0 23 | } 24 | 25 | ip := p.FirstIP.To4() 26 | var firstIP uint32 27 | firstIP += uint32(ip[0]) << 24 28 | firstIP += uint32(ip[1]) << 16 29 | firstIP += uint32(ip[2]) << 8 30 | firstIP += uint32(ip[3]) 31 | 32 | return firstIP 33 | } 34 | 35 | // HostCountIPv4 return number of IPs on the parsed range 36 | func (p *ParsedCIDR) HostCountIPv4() uint32 { 37 | ones, bits := p.IPNet.Mask.Size() 38 | return uint32(1 << (bits - ones)) 39 | } 40 | 41 | // LastIPv4 return Decimal LastIP 42 | func (p *ParsedCIDR) LastIPv4() uint32 { 43 | if p.IsIPv4 != true { 44 | return 0 45 | } 46 | 47 | return p.FirstIPv4() + p.HostCountIPv4() - 1 48 | } 49 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Mohamed Shapan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CIDR (Classless inter-domain routing) 2 | 3 | This Package converts IP CIDR to range and return First IP, Last IP, First IP decimal, Last IP decimal and Total Host count for IPv4 and IPv6 4 | 5 | ## Install 6 | `go get -u github.com/m7shapan/cidr` 7 | 8 | ## How to use 9 | See [the GoDoc](https://pkg.go.dev/github.com/m7shapan/cidr) 10 | 11 | ```go 12 | package main 13 | 14 | import ( 15 | "fmt" 16 | "log" 17 | 18 | "github.com/m7shapan/cidr" 19 | ) 20 | 21 | func main() { 22 | p, err := cidr.ParseCIDR("1.0.0.0/24") 23 | if err != nil { 24 | log.Fatal(err) 25 | } 26 | 27 | fmt.Println("First IP:", p.FirstIP) 28 | if p.IsIPv4 { 29 | fmt.Println("First IP (Decimal):", p.FirstIPv4()) 30 | } else { 31 | fmt.Println("First IP (Decimal):", p.FirstIPv6()) 32 | } 33 | 34 | fmt.Println("Last IP:", p.LastIP) 35 | 36 | if p.IsIPv4 { 37 | fmt.Println("Last IP (Decimal):", p.LastIPv4()) 38 | } else { 39 | fmt.Println("Last IP (Decimal):", p.LastIPv6()) 40 | } 41 | 42 | if p.IsIPv4 { 43 | fmt.Println("Total Host:", p.HostCountIPv4()) 44 | } else { 45 | fmt.Println("Total Host:", p.HostCountIPv6()) 46 | } 47 | 48 | // First IP: 1.0.0.0 49 | // First IP (Decimal): 16777216 50 | // Last IP: 1.0.0.255 51 | // Last IP (Decimal): 16777471 52 | // Total Host: 256 53 | 54 | 55 | ip := net.ParseIP("1.0.0.0") 56 | fmt.Println(IPv4tod(ip)) // 16777216 57 | 58 | ip := net.ParseIP("2001:4860:4860::8888") 59 | fmt.Println(IPv6tod(ip)) // 42541956123769884636017138956568135816 60 | 61 | var i uint32 = 16777216 62 | fmt.Println(DtoIPv4(i)) // 1.0.0.0 63 | 64 | b := new(big.Int) 65 | b.SetString("42541956123769884636017138956568135816", 10) 66 | fmt.Println(DtoIPv6(b)) // 2001:4860:4860::8888 67 | 68 | } 69 | ``` 70 | 71 | ## Package usage for SEO 72 | - get ip from ip range 73 | - convert ip range to ip 74 | - golang convert ip range to decimal 75 | - How to get first/last IP address of CIDR 76 | - Convert IP version 6 address to integer or decimal number 77 | - IPv4 to IP Decimal Conversion 78 | - ipv4 to decimal golang --------------------------------------------------------------------------------