diff --git a/etcdconfigweb/config.go b/etcdconfigweb/config.go index 1113116..ee535ec 100644 --- a/etcdconfigweb/config.go +++ b/etcdconfigweb/config.go @@ -3,14 +3,15 @@ package main import ( "context" "encoding/base64" - "encoding/binary" "encoding/json" "errors" "fmt" "log" + "math/big" "net" "net/http" "net/url" + "os" "strconv" "strings" "time" @@ -34,6 +35,31 @@ var MISSING_V6MTU = errors.New("Missing v6mtu query parameter") var MISSING_PUBKEY = errors.New("Missing pubkey query parameter") var MISSING_NONCE = errors.New("Missing nonce query parameter") +func getNthSubnet(cidr string, nthSubnet uint64, subnetSize uint) (net.IP, error) { + _, ipCidr, err := net.ParseCIDR(cidr) + if err != nil { + return nil, fmt.Errorf("invalid CIDR notation: %s", cidr) + } + + baseIP := ipCidr.IP + rangeSize, totalIPSize := ipCidr.Mask.Size() + if subnetSize <= uint(rangeSize) { + return nil, fmt.Errorf("subnet size %d too large for CIDR range %s", subnetSize, ipCidr.String()) + } + + subnetShiftSize := subnetSize - uint(rangeSize) + if nthSubnet >= (1 << subnetShiftSize) { + return nil, fmt.Errorf("cannot allocate %dx /%d subnets in the CIDR range %s", nthSubnet+1, subnetSize, ipCidr.String()) + } + + nthSubnetID := big.NewInt(int64(nthSubnet)) + nthSubnetID.Lsh(nthSubnetID, uint(totalIPSize)-subnetSize) + nthSubnetAddr := new(big.Int).SetBytes(baseIP) + nthSubnetAddr.Add(nthSubnetAddr, nthSubnetID) + + return net.IP(nthSubnetAddr.Bytes()), nil +} + func (ch ConfigHandler) handleRequest(ctx context.Context, query url.Values, headers http.Header) (*ConfigResponse, error) { var v6mtu uint64 var err error @@ -81,28 +107,45 @@ func (ch ConfigHandler) handleRequest(ctx context.Context, query url.Values, hea // insert new node err := ch.etcdHandler.CreateNode(ctx, pubkey, func(info *ffbs.NodeInfo) { - const V4_BASE uint32 = 10 << 24 - const V4_RANGE_SIZE uint8 = 10 - const V6_BASE_HIGH uint64 = 0x20010bf70381 << 16 + const CLIENT_V4_RANGE_SIZE uint = 22 + const CLIENT_V6_RANGE_SIZE uint = 64 + + // IPv4 handling + v4RangeStr := os.Getenv("PARKER_V4_RANGE") + if v4RangeStr == "" { + v4RangeStr = "10.0.0.0/8" // default IPv4 range for backwards compatibility + } + + // IPv6 handling + v6RangeStr := os.Getenv("PARKER_V6_RANGE") + if v6RangeStr == "" { + v6RangeStr = "2001:bf7:381::/48" // default IPv6 range for backwards compatibility + } num := *info.ID - var v4Addr [net.IPv4len]byte - binary.BigEndian.PutUint32(v4Addr[:], V4_BASE|(uint32(num)<