From a0dd5929cbf033fd3eee241aece18573534852bf Mon Sep 17 00:00:00 2001 From: afeiszli Date: Tue, 27 Apr 2021 23:17:59 -0400 Subject: [PATCH] adding ipv6 details. Need to test now --- controllers/common.go | 48 ++++++++++++++++++------- controllers/dnsHttpController.go | 6 ++-- controllers/networkHttpController.go | 52 ++++++++++++++++++++-------- controllers/nodeHttpController.go | 4 +-- functions/helpers.go | 36 ++++++++++++++++--- models/network.go | 2 ++ models/node.go | 1 + 7 files changed, 111 insertions(+), 38 deletions(-) diff --git a/controllers/common.go b/controllers/common.go index f94dd1ca..7bbf810b 100644 --- a/controllers/common.go +++ b/controllers/common.go @@ -62,21 +62,26 @@ func ValidateNodeCreate(networkName string, node models.Node) error { v := validator.New() _ = v.RegisterValidation("address_check", func(fl validator.FieldLevel) bool { - isIpv4 := functions.IsIpv4Net(node.Address) + isIpv4 := functions.IsIpNet(node.Address) empty := node.Address == "" return (empty || isIpv4) }) + _ = v.RegisterValidation("address6_check", func(fl validator.FieldLevel) bool { + isIpv6 := functions.IsIpNet(node.Address6) + empty := node.Address6 == "" + return (empty || isIpv6) + }) _ = v.RegisterValidation("endpoint_check", func(fl validator.FieldLevel) bool { //var isFieldUnique bool = functions.IsFieldUnique(networkName, "endpoint", node.Endpoint) - isIpv4 := functions.IsIpv4Net(node.Endpoint) + isIp := functions.IsIpNet(node.Endpoint) notEmptyCheck := node.Endpoint != "" - return (notEmptyCheck && isIpv4) + return (notEmptyCheck && isIp) }) _ = v.RegisterValidation("localaddress_check", func(fl validator.FieldLevel) bool { //var isFieldUnique bool = functions.IsFieldUnique(networkName, "endpoint", node.Endpoint) - isIpv4 := functions.IsIpv4Net(node.LocalAddress) + isIp := functions.IsIpNet(node.LocalAddress) empty := node.LocalAddress == "" - return (empty || isIpv4) + return (empty || isIp) }) _ = v.RegisterValidation("macaddress_unique", func(fl validator.FieldLevel) bool { @@ -123,23 +128,27 @@ func ValidateNodeUpdate(networkName string, node models.Node) error { v := validator.New() _ = v.RegisterValidation("address_check", func(fl validator.FieldLevel) bool { - isIpv4 := functions.IsIpv4Net(node.Address) + isIpv4 := functions.IsIpNet(node.Address) empty := node.Address == "" return (empty || isIpv4) }) + _ = v.RegisterValidation("address6_check", func(fl validator.FieldLevel) bool { + isIpv6 := functions.IsIpNet(node.Address6) + empty := node.Address6 == "" + return (empty || isIpv6) + }) _ = v.RegisterValidation("endpoint_check", func(fl validator.FieldLevel) bool { //var isFieldUnique bool = functions.IsFieldUnique(networkName, "endpoint", node.Endpoint) - isIpv4 := functions.IsIpv4Net(node.Endpoint) - empty := node.Endpoint == "" - return (empty || isIpv4) + isIp := functions.IsIpNet(node.Address) + empty := node.Endpoint == "" + return (empty || isIp) }) _ = v.RegisterValidation("localaddress_check", func(fl validator.FieldLevel) bool { //var isFieldUnique bool = functions.IsFieldUnique(networkName, "endpoint", node.Endpoint) - isIpv4 := functions.IsIpv4Net(node.LocalAddress) + isIp := functions.IsIpNet(node.LocalAddress) empty := node.LocalAddress == "" - return (empty || isIpv4) + return (empty || isIp ) }) - _ = v.RegisterValidation("macaddress_unique", func(fl validator.FieldLevel) bool { return true }) @@ -190,6 +199,10 @@ func UpdateNode(nodechange models.Node, node models.Node) (models.Node, error) { node.Address = nodechange.Address notifynetwork = true } + if nodechange.Address6 != "" { + node.Address6 = nodechange.Address6 + notifynetwork = true + } if nodechange.Name != "" { node.Name = nodechange.Name } @@ -258,6 +271,7 @@ func UpdateNode(nodechange models.Node, node models.Node) (models.Node, error) { update := bson.D{ {"$set", bson.D{ {"address", node.Address}, + {"address6", node.Address6}, {"name", node.Name}, {"password", node.Password}, {"listenport", node.ListenPort}, @@ -355,7 +369,6 @@ func CreateNode(node models.Node, networkName string) (models.Node, error) { //Umm, why am I doing this again? //TODO: Why am I using a local function instead of the struct function? I really dont know. //I think I thought it didn't work but uhhh...idk - //anyways, this sets some sensible variables for unset params. node.SetDefaults() //Another DB call here...Inefficient @@ -366,6 +379,15 @@ func CreateNode(node models.Node, networkName string) (models.Node, error) { if err != nil { return node, err } + fmt.Println("Setting node address: " + node.Address) + + node.Address6, err = functions.UniqueAddress6(networkName) + if node.Address6 != "" { + fmt.Println("Setting node ipv6 address: " + node.Address6) + } + if err != nil { + return node, err + } //IDK why these aren't a part of "set defaults. Pretty dumb. //TODO: This is dumb. Consolidate and fix. diff --git a/controllers/dnsHttpController.go b/controllers/dnsHttpController.go index d70dc302..3f8ebcb3 100644 --- a/controllers/dnsHttpController.go +++ b/controllers/dnsHttpController.go @@ -465,8 +465,8 @@ func ValidateDNSCreate(entry models.DNSEntry) error { _ = v.RegisterValidation("address_valid", func(fl validator.FieldLevel) bool { notEmptyCheck := len(entry.Address) > 0 - isIpv4 := functions.IsIpv4Net(entry.Address) - return notEmptyCheck && isIpv4 + isIp := functions.IsIpNet(entry.Address) + return notEmptyCheck && isIp }) _ = v.RegisterValidation("network_exists", func(fl validator.FieldLevel) bool { _, err := functions.GetParentNetwork(entry.Network) @@ -507,7 +507,7 @@ func ValidateDNSUpdate(change models.DNSEntry, entry models.DNSEntry) error { _ = v.RegisterValidation("address_valid", func(fl validator.FieldLevel) bool { isValid := true if entry.Address != "" { - isValid = functions.IsIpv4Net(entry.Address) + isValid = functions.IsIpNet(entry.Address) } return isValid }) diff --git a/controllers/networkHttpController.go b/controllers/networkHttpController.go index 2161563c..c083d043 100644 --- a/controllers/networkHttpController.go +++ b/controllers/networkHttpController.go @@ -109,12 +109,16 @@ func validateNetworkUpdate(network models.Network) error { v := validator.New() _ = v.RegisterValidation("addressrange_valid", func(fl validator.FieldLevel) bool { - isvalid := fl.Field().String() == "" || functions.IsIpv4CIDR(fl.Field().String()) + isvalid := fl.Field().String() == "" || functions.IsIpCIDR(fl.Field().String()) return isvalid }) + _ = v.RegisterValidation("addressrange6_valid", func(fl validator.FieldLevel) bool { + isvalid := fl.Field().String() == "" || functions.IsIpCIDR(fl.Field().String()) + return isvalid + }) _ = v.RegisterValidation("localrange_valid", func(fl validator.FieldLevel) bool { - isvalid := fl.Field().String() == "" || functions.IsIpv4CIDR(fl.Field().String()) + isvalid := fl.Field().String() == "" || functions.IsIpCIDR(fl.Field().String()) return isvalid }) @@ -141,12 +145,17 @@ func validateNetworkCreate(network models.Network) error { v := validator.New() _ = v.RegisterValidation("addressrange_valid", func(fl validator.FieldLevel) bool { - isvalid := functions.IsIpv4CIDR(fl.Field().String()) + isvalid := functions.IsIpCIDR(fl.Field().String()) return isvalid }) + _ = v.RegisterValidation("addressrange6_valid", func(fl validator.FieldLevel) bool { + isvalid := fl.Field().String() == "" || functions.IsIpCIDR(fl.Field().String()) + return isvalid + }) + _ = v.RegisterValidation("localrange_valid", func(fl validator.FieldLevel) bool { - isvalid := fl.Field().String() == "" || functions.IsIpv4CIDR(fl.Field().String()) + isvalid := fl.Field().String() == "" || functions.IsIpCIDR(fl.Field().String()) return isvalid }) @@ -223,19 +232,20 @@ func keyUpdate(w http.ResponseWriter, r *http.Request) { update := bson.D{ {"$set", bson.D{ {"addressrange", network.AddressRange}, + {"addressrange6", network.AddressRange6}, {"displayname", network.DisplayName}, {"defaultlistenport", network.DefaultListenPort}, {"defaultpostup", network.DefaultPostUp}, {"defaultpostdown", network.DefaultPostDown}, - {"defaultkeepalive", network.DefaultKeepalive}, - {"keyupdatetimestamp", network.KeyUpdateTimeStamp}, - {"defaultsaveconfig", network.DefaultSaveConfig}, - {"defaultinterface", network.DefaultInterface}, - {"nodeslastmodified", network.NodesLastModified}, - {"networklastmodified", network.NetworkLastModified}, - {"allowmanualsignup", network.AllowManualSignUp}, - {"checkininterval", network.DefaultCheckInInterval}, - }}, + {"defaultkeepalive", network.DefaultKeepalive}, + {"keyupdatetimestamp", network.KeyUpdateTimeStamp}, + {"defaultsaveconfig", network.DefaultSaveConfig}, + {"defaultinterface", network.DefaultInterface}, + {"nodeslastmodified", network.NodesLastModified}, + {"networklastmodified", network.NetworkLastModified}, + {"allowmanualsignup", network.AllowManualSignUp}, + {"checkininterval", network.DefaultCheckInInterval}, + }}, } err = collection.FindOneAndUpdate(ctx, filter, update).Decode(&network) @@ -304,6 +314,9 @@ func updateNetwork(w http.ResponseWriter, r *http.Request) { if networkChange.AddressRange == "" { networkChange.AddressRange = network.AddressRange } + if networkChange.AddressRange6 == "" { + networkChange.AddressRange6 = network.AddressRange6 + } if networkChange.NetID == "" { networkChange.NetID = network.NetID } @@ -325,7 +338,7 @@ func updateNetwork(w http.ResponseWriter, r *http.Request) { network.AddressRange = networkChange.AddressRange - var isAddressOK bool = functions.IsIpv4CIDR(networkChange.AddressRange) + var isAddressOK bool = functions.IsIpCIDR(networkChange.AddressRange) if !isAddressOK { err := errors.New("Invalid Range of " + networkChange.AddressRange + " for addresses.") returnErrorResponse(w, r, formatError(err, "internal")) @@ -338,7 +351,7 @@ func updateNetwork(w http.ResponseWriter, r *http.Request) { if networkChange.LocalRange != "" { network.LocalRange = networkChange.LocalRange - var isAddressOK bool = functions.IsIpv4CIDR(networkChange.LocalRange) + var isAddressOK bool = functions.IsIpCIDR(networkChange.LocalRange) if !isAddressOK { err := errors.New("Invalid Range of " + networkChange.LocalRange + " for internal addresses.") returnErrorResponse(w, r, formatError(err, "internal")) @@ -350,6 +363,9 @@ func updateNetwork(w http.ResponseWriter, r *http.Request) { if networkChange.IsLocal != nil { network.IsLocal = networkChange.IsLocal } + if networkChange.IsDualStack != nil { + network.IsDualStack = networkChange.IsDualStack + } if networkChange.DefaultListenPort != 0 { network.DefaultListenPort = networkChange.DefaultListenPort haschange = true @@ -394,6 +410,7 @@ func updateNetwork(w http.ResponseWriter, r *http.Request) { update := bson.D{ {"$set", bson.D{ {"addressrange", network.AddressRange}, + {"addressrange6", network.AddressRange6}, {"displayname", network.DisplayName}, {"defaultlistenport", network.DefaultListenPort}, {"defaultpostup", network.DefaultPostUp}, @@ -406,6 +423,7 @@ func updateNetwork(w http.ResponseWriter, r *http.Request) { {"allowmanualsignup", network.AllowManualSignUp}, {"localrange", network.LocalRange}, {"islocal", network.IsLocal}, + {"isdualstack", network.IsDualStack}, {"checkininterval", network.DefaultCheckInInterval}, }}, } @@ -505,6 +523,10 @@ func createNetwork(w http.ResponseWriter, r *http.Request) { falsevar := false network.IsLocal = &falsevar } + if network.IsDualStack == nil { + falsevar := false + network.IsDualStack = &falsevar + } err = validateNetworkCreate(network) if err != nil { diff --git a/controllers/nodeHttpController.go b/controllers/nodeHttpController.go index 5ed8e322..98bc9941 100644 --- a/controllers/nodeHttpController.go +++ b/controllers/nodeHttpController.go @@ -661,9 +661,9 @@ func createGateway(w http.ResponseWriter, r *http.Request) { func validateGateway(gateway models.GatewayRequest) error { var err error - isIpv4 := functions.IsIpv4CIDR(gateway.RangeString) + isIp := functions.IsIpCIDR(gateway.RangeString) empty := gateway.RangeString == "" - if empty || !isIpv4 { + if empty || !isIp { err = errors.New("IP Range Not Valid") } empty = gateway.Interface == "" diff --git a/functions/helpers.go b/functions/helpers.go index 4af24001..92bf4edf 100644 --- a/functions/helpers.go +++ b/functions/helpers.go @@ -378,17 +378,14 @@ func GetParentNetwork(networkname string) (models.Network, error) { return network, nil } -//Check for valid IPv4 address -//Note: We dont handle IPv6 AT ALL!!!!! This definitely is needed at some point -//But for iteration 1, lets just stick to IPv4. Keep it simple stupid. -func IsIpv4Net(host string) bool { +func IsIpNet(host string) bool { return net.ParseIP(host) != nil } //Similar to above but checks if Cidr range is valid //At least this guy's got some print statements //still not good error handling -func IsIpv4CIDR(host string) bool { +func IsIpCIDR(host string) bool { ip, ipnet, err := net.ParseCIDR(host) @@ -529,6 +526,35 @@ func UniqueAddress(networkName string) (string, error) { return "W1R3: NO UNIQUE ADDRESSES AVAILABLE", err1 } +func UniqueAddress6(networkName string) (string, error) { + + var network models.Network + network, err := GetParentNetwork(networkName) + if err != nil { + fmt.Println("UniqueAddress6 encountered an error") + return "666", err + } + + offset := true + ip, ipnet, err := net.ParseCIDR(network.AddressRange) + if err != nil { + fmt.Println("UniqueAddress6 encountered an error") + return "666", err + } + for ip := ip.Mask(ipnet.Mask); ipnet.Contains(ip); Inc(ip) { + if offset { + offset = false + continue + } + if IsIPUnique(networkName, ip.String()) { + return ip.String(), err + } + } + //TODO + err1 := errors.New("ERROR: No unique addresses available. Check network subnet.") + return "W1R3: NO UNIQUE ADDRESSES AVAILABLE", err1 +} + //pretty simple get func GetGlobalConfig() (bool, models.GlobalConfig, error) { diff --git a/models/network.go b/models/network.go index 4183f9ba..180f4704 100644 --- a/models/network.go +++ b/models/network.go @@ -11,6 +11,7 @@ import ( type Network struct { ID primitive.ObjectID `json:"_id,omitempty" bson:"_id,omitempty"` AddressRange string `json:"addressrange" bson:"addressrange" validate:"required,addressrange_valid"` + AddressRange6 string `json:"addressrange6" bson:"addressrange6" validate:"required,addressrange6_valid"` DisplayName string `json:"displayname,omitempty" bson:"displayname,omitempty" validate:"omitempty,displayname_unique,min=1,max=100"` NetID string `json:"netid" bson:"netid" validate:"required,netid_valid,min=1,max=12"` NodesLastModified int64 `json:"nodeslastmodified" bson:"nodeslastmodified"` @@ -25,6 +26,7 @@ type Network struct { AccessKeys []AccessKey `json:"accesskeys" bson:"accesskeys"` AllowManualSignUp *bool `json:"allowmanualsignup" bson:"allowmanualsignup"` IsLocal *bool `json:"islocal" bson:"islocal"` + IsDualStack *bool `json:"isdualstack" bson:"isdualstack"` LocalRange string `json:"localrange" bson:"localrange" validate:"localrange_valid"` DefaultCheckInInterval int32 `json:"checkininterval,omitempty" bson:"checkininterval,omitempty" validate:"omitempty,numeric,min=1,max=100000"` } diff --git a/models/node.go b/models/node.go index 8b435e8e..595b1111 100644 --- a/models/node.go +++ b/models/node.go @@ -20,6 +20,7 @@ var seededRand *rand.Rand = rand.New( type Node struct { ID primitive.ObjectID `json:"_id,omitempty" bson:"_id,omitempty"` Address string `json:"address" bson:"address" validate:"address_check"` + Address6 string `json:"address6" bson:"address6" validate:"address6_check"` LocalAddress string `json:"localaddress" bson:"localaddress" validate:"localaddress_check"` Name string `json:"name" bson:"name" validate:"omitempty,name_valid,max=12"` ListenPort int32 `json:"listenport" bson:"listenport" validate:"omitempty,numeric,min=1024,max=65535"`