Skip to content

Commit

Permalink
etcdconfigweb: use IPv4/IPv6 for range env vars v2
Browse files Browse the repository at this point in the history
v2 fixes some bugs that were present in both the original code and v1
- combine IPv4 and IPv6 calculations into one
- the new version can handle abitrary IPv4 or IPv6 subnet sizes and is
  not bound to specific sizes
  • Loading branch information
grische committed Nov 12, 2024
1 parent 7c151f1 commit 17368fc
Showing 1 changed file with 55 additions and 39 deletions.
94 changes: 55 additions & 39 deletions etcdconfigweb/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ package main
import (
"context"
"encoding/base64"
"encoding/binary"
"encoding/json"
"errors"
"fmt"
"log"
"math/big"
"net"
"net/http"
"net/url"
Expand Down Expand Up @@ -35,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 uint, 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
Expand Down Expand Up @@ -82,54 +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) {
v4_range_str := os.Getenv("PARKER_V4_RANGE")
v4_range_size_str := os.Getenv("PARKER_V4_RANGE_SIZE")
v6_range_str := os.Getenv("PARKER_V6_RANGE")
const CLIENT_V4_RANGE_SIZE uint = 22
const CLIENT_V6_RANGE_SIZE uint = 64

if v4_range_str == "" {
v4_range_str = "10.0.0.0"
}
if v4_range_size_str == "" {
v4_range_size_str = "10"
}
if v6_range_str == "" {
v6_range_str = "2001:bf7:381::"
// IPv4 handling
v4RangeStr := os.Getenv("PARKER_V4_RANGE")
if v4RangeStr == "" {
v4RangeStr = "10.0.0.0/8" // default IPv4 range for backwards compatibility
}

v4_base_ip := net.ParseIP(v4_range_str).To4()
if v4_base_ip == nil {
panic("Invalid v4 base address" + v4_range_str)
// IPv6 handling
v6RangeStr := os.Getenv("PARKER_V6_RANGE")
if v6RangeStr == "" {
v6RangeStr = "2001:bf7:381::/48" // default IPv6 range for backwards compatibility
}
V4_BASE := binary.BigEndian.Uint32(v4_base_ip)

v4_range_uint8, err := strconv.ParseInt(v4_range_size_str, 0, 8)
V4_RANGE_SIZE := uint8(v4_range_uint8)
num := *info.ID

v4ClientSubnet, err := getNthSubnet(v4RangeStr, num, CLIENT_V4_RANGE_SIZE)
if err != nil {
panic(err)
}
v4ClientRangeStr := fmt.Sprintf("%s/%d", v4ClientSubnet, CLIENT_V4_RANGE_SIZE)
v4BigAddr := new(big.Int).SetBytes(v4ClientSubnet)
v4BigAddr.Add(v4BigAddr, big.NewInt(1)) // use the next free IPv4
v4ClientAddrStr := net.IP(v4BigAddr.Bytes()).String()

v6Addr := net.ParseIP(v6_range_str).To16()
if v6Addr == nil {
panic("Invalid v6 base address: " + v6_range_str)
v6ClientSubnet, err := getNthSubnet(v6RangeStr, num, CLIENT_V6_RANGE_SIZE)
if err != nil {
panic(err)
}

num := *info.ID

var v4Addr [net.IPv4len]byte
binary.BigEndian.PutUint32(v4Addr[:], V4_BASE|(uint32(num)<<V4_RANGE_SIZE))
v4range := fmt.Sprintf("%s/%d", net.IP(v4Addr[:]), 8*net.IPv4len-V4_RANGE_SIZE)
v4Addr[net.IPv4len-1] = 1
v4addr := net.IP(v4Addr[:]).String()

binary.BigEndian.PutUint16(v6Addr[6:8], uint16(num))
v6range := fmt.Sprintf("%s/64", net.IP(v6Addr[:]))
v6Addr[net.IPv6len-1] = 1
v6addr := net.IP(v6Addr[:]).String()

info.Address4 = &v4addr
info.Range4 = &v4range
info.Address6 = &v6addr
info.Range6 = &v6range
v6ClientRangeStr := fmt.Sprintf("%s/%d", v6ClientSubnet, CLIENT_V6_RANGE_SIZE)
v6BigAddr := new(big.Int).SetBytes(v6ClientSubnet)
v6BigAddr.Add(v6BigAddr, big.NewInt(1)) // use the next free IPv6
v6ClientAddrStr := net.IP(v6BigAddr.Bytes()).String()

info.Address4 = &v4ClientAddrStr
info.Range4 = &v4ClientRangeStr
info.Address6 = &v6ClientAddrStr
info.Range6 = &v6ClientRangeStr
})
if err != nil {
return nil, err
Expand Down

0 comments on commit 17368fc

Please sign in to comment.