diff --git a/ipam/http.go b/ipam/http.go index f3525808..47a5b566 100644 --- a/ipam/http.go +++ b/ipam/http.go @@ -17,12 +17,12 @@ func badRequest(w http.ResponseWriter, err error) { } func parseCIDR(w http.ResponseWriter, cidrStr string, net bool) (address.CIDR, bool) { - subnetAddr, cidr, err := address.ParseCIDR(cidrStr) + cidr, err := address.ParseCIDR(cidrStr) if err != nil { badRequest(w, err) return address.CIDR{}, false } - if net && cidr.Addr != subnetAddr { + if net && !cidr.IsSubnet() { badRequest(w, fmt.Errorf("Invalid subnet %s - bits after network prefix are not all zero", cidrStr)) return address.CIDR{}, false } diff --git a/net/address/address.go b/net/address/address.go index 3d712c94..67cfee45 100644 --- a/net/address/address.go +++ b/net/address/address.go @@ -50,17 +50,22 @@ func ParseIP(s string) (Address, error) { return 0, &net.ParseError{Type: "IP Address", Text: s} } -func ParseCIDR(s string) (Address, CIDR, error) { +func ParseCIDR(s string) (CIDR, error) { if ip, ipnet, err := net.ParseCIDR(s); err != nil { - return 0, CIDR{}, err + return CIDR{}, err } else if ipnet.IP.To4() == nil { - return 0, CIDR{}, &net.ParseError{Type: "Non-IPv4 address not supported", Text: s} + return CIDR{}, &net.ParseError{Type: "Non-IPv4 address not supported", Text: s} } else { prefixLen, _ := ipnet.Mask.Size() - return FromIP4(ip), CIDR{Addr: FromIP4(ipnet.IP), PrefixLen: prefixLen}, nil + return CIDR{Addr: FromIP4(ip), PrefixLen: prefixLen}, nil } } +func (cidr CIDR) IsSubnet() bool { + mask := cidr.Size() - 1 + return Offset(cidr.Addr)&mask == 0 +} + func (cidr CIDR) Size() Offset { return 1 << uint(32-cidr.PrefixLen) } func (cidr CIDR) Range() Range { diff --git a/prog/weaver/main.go b/prog/weaver/main.go index 09ee7f48..70a3aba5 100644 --- a/prog/weaver/main.go +++ b/prog/weaver/main.go @@ -340,9 +340,12 @@ func createOverlay(datapathName string, ifaceName string, host string, port int, } func parseAndCheckCIDR(cidrStr string) address.CIDR { - _, cidr, err := address.ParseCIDR(cidrStr) + cidr, err := address.ParseCIDR(cidrStr) checkFatal(err) + if !cidr.IsSubnet() { + Log.Fatalf("Invalid allocation range %s - bits after network prefix are not all zero", cidrStr) + } if cidr.Size() < ipam.MinSubnetSize { Log.Fatalf("Allocation range smaller than minimum size %d: %s", ipam.MinSubnetSize, cidrStr) }