| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756 | package logicimport (	"encoding/json"	"errors"	"fmt"	"net"	"os/exec"	"strings"	"github.com/c-robinson/iplib"	validator "github.com/go-playground/validator/v10"	"github.com/gravitl/netmaker/database"	"github.com/gravitl/netmaker/logger"	"github.com/gravitl/netmaker/logic/acls/nodeacls"	"github.com/gravitl/netmaker/logic/pro"	"github.com/gravitl/netmaker/models"	"github.com/gravitl/netmaker/netclient/ncutils"	"github.com/gravitl/netmaker/validation")// GetNetworks - returns all networks from databasefunc GetNetworks() ([]models.Network, error) {	var networks []models.Network	collection, err := database.FetchRecords(database.NETWORKS_TABLE_NAME)	if err != nil {		return networks, err	}	for _, value := range collection {		var network models.Network		if err := json.Unmarshal([]byte(value), &network); err != nil {			return networks, err		}		// add network our array		networks = append(networks, network)	}	return networks, err}// DeleteNetwork - deletes a networkfunc DeleteNetwork(network string) error {	// remove ACL for network	err := nodeacls.DeleteACLContainer(nodeacls.NetworkID(network))	if err != nil {		logger.Log(1, "failed to remove the node acls during network delete for network,", network)	}	nodeCount, err := GetNetworkNonServerNodeCount(network)	if nodeCount == 0 || database.IsEmptyRecord(err) {		// delete server nodes first then db records		servers, err := GetSortedNetworkServerNodes(network)		if err == nil {			for _, s := range servers {				if err = DeleteNodeByID(&s, true); err != nil {					logger.Log(2, "could not removed server", s.Name, "before deleting network", network)				} else {					logger.Log(2, "removed server", s.Name, "before deleting network", network)				}			}		} else {			logger.Log(1, "could not remove servers before deleting network", network)		}		if err = pro.RemoveAllNetworkUsers(network); err != nil {			logger.Log(0, "failed to remove network users on network delete for network", network, err.Error())		}		return database.DeleteRecord(database.NETWORKS_TABLE_NAME, network)	}	return errors.New("node check failed. All nodes must be deleted before deleting network")}// CreateNetwork - creates a network in databasefunc CreateNetwork(network models.Network) (models.Network, error) {	if network.AddressRange != "" {		normalizedRange, err := NormalizeCIDR(network.AddressRange)		if err != nil {			return models.Network{}, err		}		network.AddressRange = normalizedRange	}	if network.AddressRange6 != "" {		normalizedRange, err := NormalizeCIDR(network.AddressRange6)		if err != nil {			return models.Network{}, err		}		network.AddressRange6 = normalizedRange	}	network.SetDefaults()	network.SetNodesLastModified()	network.SetNetworkLastModified()	pro.AddProNetDefaults(&network)	if len(network.ProSettings.AllowedGroups) == 0 {		network.ProSettings.AllowedGroups = []string{pro.DEFAULT_ALLOWED_GROUPS}	}	err := ValidateNetwork(&network, false)	if err != nil {		//logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))		return models.Network{}, err	}	if err = pro.InitializeNetworkUsers(network.NetID); err != nil {		return models.Network{}, err	}	data, err := json.Marshal(&network)	if err != nil {		return models.Network{}, err	}	if err = database.Insert(network.NetID, string(data), database.NETWORKS_TABLE_NAME); err != nil {		return models.Network{}, err	}	// == add all current users to network as network users ==	if err = InitializeNetUsers(&network); err != nil {		return network, err	}	return network, nil}// GetNetworkNonServerNodeCount - get number of network non server nodesfunc GetNetworkNonServerNodeCount(networkName string) (int, error) {	collection, err := database.FetchRecords(database.NODES_TABLE_NAME)	count := 0	if err != nil && !database.IsEmptyRecord(err) {		return count, err	}	for _, value := range collection {		var node models.Node		if err = json.Unmarshal([]byte(value), &node); err != nil {			return count, err		} else {			if node.Network == networkName && node.IsServer != "yes" {				count++			}		}	}	return count, nil}// GetParentNetwork - get parent networkfunc GetParentNetwork(networkname string) (models.Network, error) {	var network models.Network	networkData, err := database.FetchRecord(database.NETWORKS_TABLE_NAME, networkname)	if err != nil {		return network, err	}	if err = json.Unmarshal([]byte(networkData), &network); err != nil {		return models.Network{}, err	}	return network, nil}// GetParentNetwork - get parent networkfunc GetNetworkSettings(networkname string) (models.Network, error) {	var network models.Network	networkData, err := database.FetchRecord(database.NETWORKS_TABLE_NAME, networkname)	if err != nil {		return network, err	}	if err = json.Unmarshal([]byte(networkData), &network); err != nil {		return models.Network{}, err	}	network.AccessKeys = []models.AccessKey{}	return network, nil}// UniqueAddress - see if address is uniquefunc UniqueAddress(networkName string, reverse bool) (string, error) {	var network models.Network	network, err := GetParentNetwork(networkName)	if err != nil {		logger.Log(0, "UniqueAddressServer encountered  an error")		return "666", err	}	if network.IsIPv4 == "no" {		return "", fmt.Errorf("IPv4 not active on network " + networkName)	}	//ensure AddressRange is valid	if _, _, err := net.ParseCIDR(network.AddressRange); err != nil {		logger.Log(0, "UniqueAddress encountered  an error")		return "666", err	}	net4 := iplib.Net4FromStr(network.AddressRange)	newAddrs := net4.FirstAddress()	if reverse {		newAddrs = net4.LastAddress()	}	for {		if IsIPUnique(networkName, newAddrs.String(), database.NODES_TABLE_NAME, false) &&			IsIPUnique(networkName, newAddrs.String(), database.EXT_CLIENT_TABLE_NAME, false) {			return newAddrs.String(), nil		}		if reverse {			newAddrs, err = net4.PreviousIP(newAddrs)		} else {			newAddrs, err = net4.NextIP(newAddrs)		}		if err != nil {			break		}	}	return "W1R3: NO UNIQUE ADDRESSES AVAILABLE", errors.New("ERROR: No unique addresses available. Check network subnet")}// IsIPUnique - checks if an IP is uniquefunc IsIPUnique(network string, ip string, tableName string, isIpv6 bool) bool {	isunique := true	collection, err := database.FetchRecords(tableName)	if err != nil {		return isunique	}	for _, value := range collection { // filter		var node models.Node		if err = json.Unmarshal([]byte(value), &node); err != nil {			continue		}		if isIpv6 {			if node.Address6 == ip && node.Network == network {				return false			}		} else {			if node.Address == ip && node.Network == network {				return false			}		}	}	return isunique}// UniqueAddress6 - see if ipv6 address is uniquefunc UniqueAddress6(networkName string, reverse bool) (string, error) {	var network models.Network	network, err := GetParentNetwork(networkName)	if err != nil {		fmt.Println("Network Not Found")		return "", err	}	if network.IsIPv6 == "no" {		return "", fmt.Errorf("IPv6 not active on network " + networkName)	}	//ensure AddressRange is valid	if _, _, err := net.ParseCIDR(network.AddressRange6); err != nil {		return "666", err	}	net6 := iplib.Net6FromStr(network.AddressRange6)	newAddrs, err := net6.NextIP(net6.FirstAddress())	if reverse {		newAddrs, err = net6.PreviousIP(net6.LastAddress())	}	if err != nil {		return "", err	}	for {		if IsIPUnique(networkName, newAddrs.String(), database.NODES_TABLE_NAME, true) &&			IsIPUnique(networkName, newAddrs.String(), database.EXT_CLIENT_TABLE_NAME, true) {			return newAddrs.String(), nil		}		if reverse {			newAddrs, err = net6.PreviousIP(newAddrs)		} else {			newAddrs, err = net6.NextIP(newAddrs)		}		if err != nil {			break		}	}	return "W1R3: NO UNIQUE ADDRESSES AVAILABLE", errors.New("ERROR: No unique IPv6 addresses available. Check network subnet")}// GetLocalIP - gets the local ipfunc GetLocalIP(node models.Node) string {	var local string	ifaces, err := net.Interfaces()	if err != nil {		return local	}	_, localrange, err := net.ParseCIDR(node.LocalRange)	if err != nil {		return local	}	found := false	for _, i := range ifaces {		if i.Flags&net.FlagUp == 0 {			continue // interface down		}		if i.Flags&net.FlagLoopback != 0 {			continue // loopback interface		}		addrs, err := i.Addrs()		if err != nil {			return local		}		for _, addr := range addrs {			var ip net.IP			switch v := addr.(type) {			case *net.IPNet:				if !found {					ip = v.IP					local = ip.String()					if node.IsLocal == "yes" {						found = localrange.Contains(ip)					} else {						found = true					}				}			case *net.IPAddr:				if !found {					ip = v.IP					local = ip.String()					if node.IsLocal == "yes" {						found = localrange.Contains(ip)					} else {						found = true					}				}			}		}	}	return local}// UpdateNetworkLocalAddresses - updates network localaddressesfunc UpdateNetworkLocalAddresses(networkName string) error {	collection, err := database.FetchRecords(database.NODES_TABLE_NAME)	if err != nil {		return err	}	for _, value := range collection {		var node models.Node		err := json.Unmarshal([]byte(value), &node)		if err != nil {			fmt.Println("error in node address assignment!")			return err		}		if node.Network == networkName {			var ipaddr string			var iperr error			if node.IsServer == "yes" {				ipaddr, iperr = UniqueAddress(networkName, true)			} else {				ipaddr, iperr = UniqueAddress(networkName, false)			}			if iperr != nil {				fmt.Println("error in node  address assignment!")				return iperr			}			node.Address = ipaddr			newNodeData, err := json.Marshal(&node)			if err != nil {				logger.Log(1, "error in node  address assignment!")				return err			}			database.Insert(node.ID, string(newNodeData), database.NODES_TABLE_NAME)		}	}	return nil}// UpdateNetworkLocalAddresses - updates network localaddressesfunc UpdateNetworkHolePunching(networkName string, holepunch string) error {	nodes, err := GetNetworkNodes(networkName)	if err != nil {		return err	}	for _, node := range nodes {		if node.IsServer != "yes" {			node.UDPHolePunch = holepunch			newNodeData, err := json.Marshal(&node)			if err != nil {				logger.Log(1, "error in node hole punch assignment")				return err			}			database.Insert(node.ID, string(newNodeData), database.NODES_TABLE_NAME)		}	}	return nil}// RemoveNetworkNodeIPv6Addresses - removes network node IPv6 addressesfunc RemoveNetworkNodeIPv6Addresses(networkName string) error {	collections, err := database.FetchRecords(database.NODES_TABLE_NAME)	if err != nil {		return err	}	for _, value := range collections {		var node models.Node		err := json.Unmarshal([]byte(value), &node)		if err != nil {			fmt.Println("error in node address assignment!")			return err		}		if node.Network == networkName {			node.Address6 = ""			data, err := json.Marshal(&node)			if err != nil {				return err			}			database.Insert(node.ID, string(data), database.NODES_TABLE_NAME)		}	}	return nil}// UpdateNetworkNodeAddresses - updates network node addressesfunc UpdateNetworkNodeAddresses(networkName string) error {	collections, err := database.FetchRecords(database.NODES_TABLE_NAME)	if err != nil {		return err	}	for _, value := range collections {		var node models.Node		err := json.Unmarshal([]byte(value), &node)		if err != nil {			logger.Log(1, "error in node ipv4 address assignment!")			return err		}		if node.Network == networkName {			var ipaddr string			var iperr error			if node.IsServer == "yes" {				ipaddr, iperr = UniqueAddress(networkName, true)			} else {				ipaddr, iperr = UniqueAddress(networkName, false)			}			if iperr != nil {				logger.Log(1, "error in node ipv4 address assignment!")				return iperr			}			node.Address = ipaddr			data, err := json.Marshal(&node)			if err != nil {				return err			}			database.Insert(node.ID, string(data), database.NODES_TABLE_NAME)		}	}	return nil}// UpdateNetworkNodeAddresses6 - updates network node addressesfunc UpdateNetworkNodeAddresses6(networkName string) error {	collections, err := database.FetchRecords(database.NODES_TABLE_NAME)	if err != nil {		return err	}	for _, value := range collections {		var node models.Node		err := json.Unmarshal([]byte(value), &node)		if err != nil {			logger.Log(1, "error in node ipv6 address assignment!")			return err		}		if node.Network == networkName {			var ipaddr string			var iperr error			if node.IsServer == "yes" {				ipaddr, iperr = UniqueAddress6(networkName, true)			} else {				ipaddr, iperr = UniqueAddress6(networkName, false)			}			if iperr != nil {				logger.Log(1, "error in node ipv6 address assignment!")				return iperr			}			node.Address6 = ipaddr			data, err := json.Marshal(&node)			if err != nil {				return err			}			database.Insert(node.ID, string(data), database.NODES_TABLE_NAME)		}	}	return nil}// IsNetworkNameUnique - checks to see if any other networks have the same name (id)func IsNetworkNameUnique(network *models.Network) (bool, error) {	isunique := true	dbs, err := GetNetworks()	if err != nil && !database.IsEmptyRecord(err) {		return false, err	}	for i := 0; i < len(dbs); i++ {		if network.NetID == dbs[i].NetID {			isunique = false		}	}	return isunique, nil}// UpdateNetwork - updates a network with another network's fieldsfunc UpdateNetwork(currentNetwork *models.Network, newNetwork *models.Network) (bool, bool, bool, bool, []string, []string, error) {	if err := ValidateNetwork(newNetwork, true); err != nil {		return false, false, false, false, nil, nil, err	}	if newNetwork.NetID == currentNetwork.NetID {		hasrangeupdate4 := newNetwork.AddressRange != currentNetwork.AddressRange		hasrangeupdate6 := newNetwork.AddressRange6 != currentNetwork.AddressRange6		localrangeupdate := newNetwork.LocalRange != currentNetwork.LocalRange		hasholepunchupdate := newNetwork.DefaultUDPHolePunch != currentNetwork.DefaultUDPHolePunch		groupDelta := append(StringDifference(newNetwork.ProSettings.AllowedGroups, currentNetwork.ProSettings.AllowedGroups),			StringDifference(currentNetwork.ProSettings.AllowedGroups, newNetwork.ProSettings.AllowedGroups)...)		userDelta := append(StringDifference(newNetwork.ProSettings.AllowedUsers, currentNetwork.ProSettings.AllowedUsers),			StringDifference(currentNetwork.ProSettings.AllowedUsers, newNetwork.ProSettings.AllowedUsers)...)		data, err := json.Marshal(newNetwork)		if err != nil {			return false, false, false, false, nil, nil, err		}		newNetwork.SetNetworkLastModified()		err = database.Insert(newNetwork.NetID, string(data), database.NETWORKS_TABLE_NAME)		return hasrangeupdate4, hasrangeupdate6, localrangeupdate, hasholepunchupdate, groupDelta, userDelta, err	}	// copy values	return false, false, false, false, nil, nil, errors.New("failed to update network " + newNetwork.NetID + ", cannot change netid.")}// GetNetwork - gets a network from databasefunc GetNetwork(networkname string) (models.Network, error) {	var network models.Network	networkData, err := database.FetchRecord(database.NETWORKS_TABLE_NAME, networkname)	if err != nil {		return network, err	}	if err = json.Unmarshal([]byte(networkData), &network); err != nil {		return models.Network{}, err	}	return network, nil}// NetIDInNetworkCharSet - checks if a netid of a network uses valid charactersfunc NetIDInNetworkCharSet(network *models.Network) bool {	charset := "abcdefghijklmnopqrstuvwxyz1234567890-_"	for _, char := range network.NetID {		if !strings.Contains(charset, string(char)) {			return false		}	}	return true}// Validate - validates fields of an network structfunc ValidateNetwork(network *models.Network, isUpdate bool) error {	v := validator.New()	_ = v.RegisterValidation("netid_valid", func(fl validator.FieldLevel) bool {		inCharSet := NetIDInNetworkCharSet(network)		if isUpdate {			return inCharSet		}		isFieldUnique, _ := IsNetworkNameUnique(network)		return isFieldUnique && inCharSet	})	//	_ = v.RegisterValidation("checkyesorno", func(fl validator.FieldLevel) bool {		return validation.CheckYesOrNo(fl)	})	err := v.Struct(network)	if err != nil {		for _, e := range err.(validator.ValidationErrors) {			fmt.Println(e)		}	}	if network.ProSettings != nil {		if network.ProSettings.DefaultAccessLevel < pro.NET_ADMIN || network.ProSettings.DefaultAccessLevel > pro.NO_ACCESS {			return fmt.Errorf("invalid access level")		}		if network.ProSettings.DefaultUserClientLimit < 0 || network.ProSettings.DefaultUserNodeLimit < 0 {			return fmt.Errorf("invalid node/client limit provided")		}	}	return err}// ParseNetwork - parses a network into a modelfunc ParseNetwork(value string) (models.Network, error) {	var network models.Network	err := json.Unmarshal([]byte(value), &network)	return network, err}// KeyUpdate - updates keys on networkfunc KeyUpdate(netname string) (models.Network, error) {	err := networkNodesUpdateAction(netname, models.NODE_UPDATE_KEY)	if err != nil {		return models.Network{}, err	}	return models.Network{}, nil}// SaveNetwork - save network struct to databasefunc SaveNetwork(network *models.Network) error {	data, err := json.Marshal(network)	if err != nil {		return err	}	if err := database.Insert(network.NetID, string(data), database.NETWORKS_TABLE_NAME); err != nil {		return err	}	return nil}// NetworkExists - check if network existsfunc NetworkExists(name string) (bool, error) {	var network string	var err error	if network, err = database.FetchRecord(database.NETWORKS_TABLE_NAME, name); err != nil {		return false, err	}	return len(network) > 0, nil}// == Private ==func networkNodesUpdateAction(networkName string, action string) error {	collections, err := database.FetchRecords(database.NODES_TABLE_NAME)	if err != nil {		if database.IsEmptyRecord(err) {			return nil		}		return err	}	for _, value := range collections {		var node models.Node		err := json.Unmarshal([]byte(value), &node)		if err != nil {			fmt.Println("error in node address assignment!")			return err		}		if action == models.NODE_UPDATE_KEY {			continue		}		if node.Network == networkName {			node.Action = action			data, err := json.Marshal(&node)			if err != nil {				return err			}			database.Insert(node.ID, string(data), database.NODES_TABLE_NAME)		}	}	return nil}func deleteInterface(ifacename string, postdown string) error {	var err error	if !ncutils.IsKernel() {		err = RemoveConf(ifacename, true)	} else {		ipExec, errN := exec.LookPath("ip")		err = errN		if err != nil {			logger.Log(1, err.Error())		}		_, err = ncutils.RunCmd(ipExec+" link del "+ifacename, false)		if postdown != "" {			_, err = ncutils.RunCmd(postdown, false)		}	}	return err}func isInterfacePresent(iface string, address string) (string, bool) {	var interfaces []net.Interface	var err error	interfaces, err = net.Interfaces()	if err != nil {		logger.Log(0, "ERROR: could not read interfaces")		return "", true	}	for _, currIface := range interfaces {		var currAddrs []net.Addr		currAddrs, err = currIface.Addrs()		if err != nil || len(currAddrs) == 0 {			continue		}		for _, addr := range currAddrs {			if strings.Contains(addr.String(), address) && currIface.Name != iface {				// logger.Log(2, "found iface", addr.String(), currIface.Name)				interfaces = nil				currAddrs = nil				return currIface.Name, false			}		}		currAddrs = nil	}	interfaces = nil	// logger.Log(2, "failed to find iface", iface)	return "", true}
 |