| // Copyright 2015 CNI authors |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| package ip |
| |
| import ( |
| "math/big" |
| "net" |
| ) |
| |
| // NextIP returns IP incremented by 1, if IP is invalid, return nil |
| func NextIP(ip net.IP) net.IP { |
| normalizedIP := normalizeIP(ip) |
| if normalizedIP == nil { |
| return nil |
| } |
| |
| i := ipToInt(normalizedIP) |
| return intToIP(i.Add(i, big.NewInt(1)), len(normalizedIP) == net.IPv6len) |
| } |
| |
| // PrevIP returns IP decremented by 1, if IP is invalid, return nil |
| func PrevIP(ip net.IP) net.IP { |
| normalizedIP := normalizeIP(ip) |
| if normalizedIP == nil { |
| return nil |
| } |
| |
| i := ipToInt(normalizedIP) |
| return intToIP(i.Sub(i, big.NewInt(1)), len(normalizedIP) == net.IPv6len) |
| } |
| |
| // Cmp compares two IPs, returning the usual ordering: |
| // a < b : -1 |
| // a == b : 0 |
| // a > b : 1 |
| // incomparable : -2 |
| func Cmp(a, b net.IP) int { |
| normalizedA := normalizeIP(a) |
| normalizedB := normalizeIP(b) |
| |
| if len(normalizedA) == len(normalizedB) && len(normalizedA) != 0 { |
| return ipToInt(normalizedA).Cmp(ipToInt(normalizedB)) |
| } |
| |
| return -2 |
| } |
| |
| func ipToInt(ip net.IP) *big.Int { |
| return big.NewInt(0).SetBytes(ip) |
| } |
| |
| func intToIP(i *big.Int, isIPv6 bool) net.IP { |
| intBytes := i.Bytes() |
| |
| if len(intBytes) == net.IPv4len || len(intBytes) == net.IPv6len { |
| return intBytes |
| } |
| |
| if isIPv6 { |
| return append(make([]byte, net.IPv6len-len(intBytes)), intBytes...) |
| } |
| |
| return append(make([]byte, net.IPv4len-len(intBytes)), intBytes...) |
| } |
| |
| // normalizeIP will normalize IP by family, |
| // IPv4 : 4-byte form |
| // IPv6 : 16-byte form |
| // others : nil |
| func normalizeIP(ip net.IP) net.IP { |
| if ipTo4 := ip.To4(); ipTo4 != nil { |
| return ipTo4 |
| } |
| return ip.To16() |
| } |
| |
| // Network masks off the host portion of the IP, if IPNet is invalid, |
| // return nil |
| func Network(ipn *net.IPNet) *net.IPNet { |
| if ipn == nil { |
| return nil |
| } |
| |
| maskedIP := ipn.IP.Mask(ipn.Mask) |
| if maskedIP == nil { |
| return nil |
| } |
| |
| return &net.IPNet{ |
| IP: maskedIP, |
| Mask: ipn.Mask, |
| } |
| } |