diff --git a/net/cidr/range.go b/net/cidr/range.go new file mode 100644 index 0000000..e5c9abd --- /dev/null +++ b/net/cidr/range.go @@ -0,0 +1,37 @@ +package cidr + +import ( + "fmt" + "net" +) + +func NewCIDRRanger(cidr string) (CIDRRanger, error) { + nIP, nIPNet, err := net.ParseCIDR(cidr) + if nil != err { + return nil, err + } + + switch len(nIP) { + case net.IPv4len: + cr := &cidrRangeIPv4{ + cidrNet: nIPNet, + } + return cr, nil + case net.IPv6len: + cr := &cidrRangeIPv6{ + cidrNet: nIPNet, + } + return cr, nil + default: + return nil, fmt.Errorf("Net: not supported IP length") + } +} + +type CIDRRanger interface { + Contains(ip net.IP) bool + First() net.IP + Last() net.IP + Range() []net.IP + Broadcast() net.IP + Network() net.IP +} diff --git a/net/cidr/range_v4.go b/net/cidr/range_v4.go new file mode 100644 index 0000000..ae814fc --- /dev/null +++ b/net/cidr/range_v4.go @@ -0,0 +1,75 @@ +package cidr + +import ( + "net" + + "git.loafle.net/commons_go/util/net/converter" +) + +type cidrRangeIPv4 struct { + cidrNet *net.IPNet +} + +func (cr *cidrRangeIPv4) Contains(ip net.IP) bool { + return cr.cidrNet.Contains(ip) +} + +func (cr *cidrRangeIPv4) First() net.IP { + nIP := cr.Network() + return cr.Next(nIP) +} + +func (cr *cidrRangeIPv4) Last() net.IP { + bIP := cr.Broadcast() + return cr.Previous(bIP) +} + +func (cr *cidrRangeIPv4) Range() []net.IP { + fIP := cr.First() + if nil == fIP { + return nil + } + lIP := cr.Last() + if nil == lIP { + return nil + } + fNum := converter.IPv4ToInt(fIP.To4()) + lNum := converter.IPv4ToInt(lIP.To4()) + r := make([]net.IP, 0) + for i := fNum; i <= lNum; i++ { + r = append(r, converter.IntToIPv4(i)) + } + return r +} + +func (cr *cidrRangeIPv4) Broadcast() net.IP { + ip := cr.cidrNet.IP.To4() + bIP := net.IPv4(0, 0, 0, 0).To4() + for i := 0; i < len(bIP); i++ { + bIP[i] = ip[i] | ^cr.cidrNet.Mask[i] + } + return bIP +} + +func (cr *cidrRangeIPv4) Network() net.IP { + ip := cr.cidrNet.IP.To4() + return ip.Mask(cr.cidrNet.Mask) +} + +func (cr *cidrRangeIPv4) Next(ip net.IP) net.IP { + nNum := converter.IPv4ToInt(ip.To4()) + 1 + nIP := converter.IntToIPv4(nNum) + if cr.Contains(nIP) { + return nIP + } + return nil +} + +func (cr *cidrRangeIPv4) Previous(ip net.IP) net.IP { + nNum := converter.IPv4ToInt(ip.To4()) - 1 + nIP := converter.IntToIPv4(nNum) + if cr.Contains(nIP) { + return nIP + } + return nil +} diff --git a/net/cidr/range_v6.go b/net/cidr/range_v6.go new file mode 100644 index 0000000..4ec8804 --- /dev/null +++ b/net/cidr/range_v6.go @@ -0,0 +1,39 @@ +package cidr + +import "net" + +type cidrRangeIPv6 struct { + cidrNet *net.IPNet +} + +func (cr *cidrRangeIPv6) Contains(ip net.IP) bool { + return cr.cidrNet.Contains(ip) +} + +func (cr *cidrRangeIPv6) First() net.IP { + +} + +func (cr *cidrRangeIPv6) Last() net.IP { + +} + +func (cr *cidrRangeIPv6) Range() []net.IP { + +} + +func (cr *cidrRangeIPv6) Broadcast() net.IP { + +} + +func (cr *cidrRangeIPv6) Network() net.IP { + +} + +func (cr *cidrRangeIPv6) Next(ip net.IP) { + +} + +func (cr *cidrRangeIPv6) Previous(ip net.IP) { + +} diff --git a/net/converter/ip.go b/net/converter/ip.go index a70194c..5768225 100644 --- a/net/converter/ip.go +++ b/net/converter/ip.go @@ -1,64 +1,17 @@ package converter import ( - "strconv" - "strings" + "fmt" + "net" ) -func IPToUint64(ip string) uint64 { - isV4 := true - for i := 0; i < len(ip); i++ { - switch ip[i] { - case ':': - isV4 = false - break - case '.': - isV4 = true - break - } +func IPToInt(ip net.IP) (int32, error) { + switch len(ip) { + case net.IPv4len: + return IPv4ToInt(ip), nil + case net.IPv6len: + return IPv6ToInt(ip), nil + default: + return 0, fmt.Errorf("Net: not supported IP length") } - if !isV4 { - return ipv6ToUint64(ip) - } - return IPV4ToUint64(ip) -} - -func IPV4ToUint64(s string) uint64 { - bits := strings.Split(s, ".") - - b0, _ := strconv.Atoi(bits[0]) - b1, _ := strconv.Atoi(bits[1]) - b2, _ := strconv.Atoi(bits[2]) - b3, _ := strconv.Atoi(bits[3]) - - var sum uint64 - - // left shifting 24,16,8,0 and bitwise OR - - sum += uint64(b0) << 24 - sum += uint64(b1) << 16 - sum += uint64(b2) << 8 - sum += uint64(b3) - - return sum -} - -func ipv6ToUint64(s string) uint64 { - bits := strings.Split(s, ":") - - b0, _ := strconv.Atoi(bits[0]) - b1, _ := strconv.Atoi(bits[1]) - b2, _ := strconv.Atoi(bits[2]) - b3, _ := strconv.Atoi(bits[3]) - - var sum uint64 - - // left shifting 24,16,8,0 and bitwise OR - - sum += uint64(b0) << 24 - sum += uint64(b1) << 16 - sum += uint64(b2) << 8 - sum += uint64(b3) - - return sum } diff --git a/net/converter/ip_v4.go b/net/converter/ip_v4.go new file mode 100644 index 0000000..88d4efc --- /dev/null +++ b/net/converter/ip_v4.go @@ -0,0 +1,17 @@ +package converter + +import ( + "encoding/binary" + "net" +) + +func IPv4ToInt(ip net.IP) int32 { + return int32(binary.BigEndian.Uint32(ip.To4())) +} + +func IntToIPv4(n int32) net.IP { + b := make([]byte, 4) + binary.BigEndian.PutUint32(b, uint32(n)) + return net.IP(b) + +} diff --git a/net/converter/ip_v6.go b/net/converter/ip_v6.go new file mode 100644 index 0000000..676ad64 --- /dev/null +++ b/net/converter/ip_v6.go @@ -0,0 +1,15 @@ +package converter + +import ( + "net" +) + +// Not implemented +func IPv6ToInt(ip net.IP) int32 { + return 0 +} + +// Not implemented +func IntToIPv6(n int32) net.IP { + return nil +}