|  | @@ -3,14 +3,22 @@ package logic
 | 
	
		
			
				|  |  |  import (
 | 
	
		
			
				|  |  |  	"errors"
 | 
	
		
			
				|  |  |  	"fmt"
 | 
	
		
			
				|  |  | +	"net"
 | 
	
		
			
				|  |  |  	"slices"
 | 
	
		
			
				|  |  |  	"sort"
 | 
	
		
			
				|  |  |  	"time"
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +	"github.com/google/uuid"
 | 
	
		
			
				|  |  |  	"github.com/gravitl/netmaker/database"
 | 
	
		
			
				|  |  |  	"github.com/gravitl/netmaker/logger"
 | 
	
		
			
				|  |  |  	"github.com/gravitl/netmaker/models"
 | 
	
		
			
				|  |  |  	"github.com/gravitl/netmaker/servercfg"
 | 
	
		
			
				|  |  | +	"golang.org/x/exp/slog"
 | 
	
		
			
				|  |  | +)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +var (
 | 
	
		
			
				|  |  | +	IPv4Network = "0.0.0.0/0"
 | 
	
		
			
				|  |  | +	IPv6Network = "::/0"
 | 
	
		
			
				|  |  |  )
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  // IsInternetGw - checks if node is acting as internet gw
 | 
	
	
		
			
				|  | @@ -267,9 +275,6 @@ func DeleteIngressGateway(nodeid string) (models.Node, []models.ExtClient, error
 | 
	
		
			
				|  |  |  	logger.Log(3, "deleting ingress gateway")
 | 
	
		
			
				|  |  |  	node.LastModified = time.Now().UTC()
 | 
	
		
			
				|  |  |  	node.IsIngressGateway = false
 | 
	
		
			
				|  |  | -	if !servercfg.IsPro {
 | 
	
		
			
				|  |  | -		node.IsInternetGateway = false
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  |  	delete(node.Tags, models.TagID(fmt.Sprintf("%s.%s", node.Network, models.GwTagName)))
 | 
	
		
			
				|  |  |  	node.IngressGatewayRange = ""
 | 
	
		
			
				|  |  |  	node.Metadata = ""
 | 
	
	
		
			
				|  | @@ -316,3 +321,157 @@ func IsUserAllowedAccessToExtClient(username string, client models.ExtClient) bo
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  	return true
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +func ValidateInetGwReq(inetNode models.Node, req models.InetNodeReq, update bool) error {
 | 
	
		
			
				|  |  | +	inetHost, err := GetHost(inetNode.HostID.String())
 | 
	
		
			
				|  |  | +	if err != nil {
 | 
	
		
			
				|  |  | +		return err
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	if inetHost.FirewallInUse == models.FIREWALL_NONE {
 | 
	
		
			
				|  |  | +		return errors.New("iptables or nftables needs to be installed")
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	if inetNode.InternetGwID != "" {
 | 
	
		
			
				|  |  | +		return fmt.Errorf("node %s is using a internet gateway already", inetHost.Name)
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	if inetNode.IsRelayed {
 | 
	
		
			
				|  |  | +		return fmt.Errorf("node %s is being relayed", inetHost.Name)
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	for _, clientNodeID := range req.InetNodeClientIDs {
 | 
	
		
			
				|  |  | +		clientNode, err := GetNodeByID(clientNodeID)
 | 
	
		
			
				|  |  | +		if err != nil {
 | 
	
		
			
				|  |  | +			return err
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +		if clientNode.IsFailOver {
 | 
	
		
			
				|  |  | +			return errors.New("failover node cannot be set to use internet gateway")
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +		clientHost, err := GetHost(clientNode.HostID.String())
 | 
	
		
			
				|  |  | +		if err != nil {
 | 
	
		
			
				|  |  | +			return err
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +		if clientHost.IsDefault {
 | 
	
		
			
				|  |  | +			return errors.New("default host cannot be set to use internet gateway")
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +		if clientHost.OS != models.OS_Types.Linux && clientHost.OS != models.OS_Types.Windows {
 | 
	
		
			
				|  |  | +			return errors.New("can only attach linux or windows machine to a internet gateway")
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +		if clientNode.IsInternetGateway {
 | 
	
		
			
				|  |  | +			return fmt.Errorf("node %s acting as internet gateway cannot use another internet gateway", clientHost.Name)
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +		if update {
 | 
	
		
			
				|  |  | +			if clientNode.InternetGwID != "" && clientNode.InternetGwID != inetNode.ID.String() {
 | 
	
		
			
				|  |  | +				return fmt.Errorf("node %s is already using a internet gateway", clientHost.Name)
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +		} else {
 | 
	
		
			
				|  |  | +			if clientNode.InternetGwID != "" {
 | 
	
		
			
				|  |  | +				return fmt.Errorf("node %s is already using a internet gateway", clientHost.Name)
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +		if clientNode.FailedOverBy != uuid.Nil {
 | 
	
		
			
				|  |  | +			ResetFailedOverPeer(&clientNode)
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		if clientNode.IsRelayed && clientNode.RelayedBy != inetNode.ID.String() {
 | 
	
		
			
				|  |  | +			return fmt.Errorf("node %s is being relayed", clientHost.Name)
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		for _, nodeID := range clientHost.Nodes {
 | 
	
		
			
				|  |  | +			node, err := GetNodeByID(nodeID)
 | 
	
		
			
				|  |  | +			if err != nil {
 | 
	
		
			
				|  |  | +				continue
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +			if node.InternetGwID != "" && node.InternetGwID != inetNode.ID.String() {
 | 
	
		
			
				|  |  | +				return errors.New("nodes on same host cannot use different internet gateway")
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	return nil
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// SetInternetGw - sets the node as internet gw based on flag bool
 | 
	
		
			
				|  |  | +func SetInternetGw(node *models.Node, req models.InetNodeReq) {
 | 
	
		
			
				|  |  | +	node.IsInternetGateway = true
 | 
	
		
			
				|  |  | +	node.InetNodeReq = req
 | 
	
		
			
				|  |  | +	for _, clientNodeID := range req.InetNodeClientIDs {
 | 
	
		
			
				|  |  | +		clientNode, err := GetNodeByID(clientNodeID)
 | 
	
		
			
				|  |  | +		if err != nil {
 | 
	
		
			
				|  |  | +			continue
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +		clientNode.InternetGwID = node.ID.String()
 | 
	
		
			
				|  |  | +		UpsertNode(&clientNode)
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +func UnsetInternetGw(node *models.Node) {
 | 
	
		
			
				|  |  | +	nodes, err := GetNetworkNodes(node.Network)
 | 
	
		
			
				|  |  | +	if err != nil {
 | 
	
		
			
				|  |  | +		slog.Error("failed to get network nodes", "network", node.Network, "error", err)
 | 
	
		
			
				|  |  | +		return
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	for _, clientNode := range nodes {
 | 
	
		
			
				|  |  | +		if node.ID.String() == clientNode.InternetGwID {
 | 
	
		
			
				|  |  | +			clientNode.InternetGwID = ""
 | 
	
		
			
				|  |  | +			UpsertNode(&clientNode)
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	node.IsInternetGateway = false
 | 
	
		
			
				|  |  | +	node.InetNodeReq = models.InetNodeReq{}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +func SetDefaultGwForRelayedUpdate(relayed, relay models.Node, peerUpdate models.HostPeerUpdate) models.HostPeerUpdate {
 | 
	
		
			
				|  |  | +	if relay.InternetGwID != "" {
 | 
	
		
			
				|  |  | +		relayedHost, err := GetHost(relayed.HostID.String())
 | 
	
		
			
				|  |  | +		if err != nil {
 | 
	
		
			
				|  |  | +			return peerUpdate
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +		peerUpdate.ChangeDefaultGw = true
 | 
	
		
			
				|  |  | +		peerUpdate.DefaultGwIp = relay.Address.IP
 | 
	
		
			
				|  |  | +		if peerUpdate.DefaultGwIp == nil || relayedHost.EndpointIP == nil {
 | 
	
		
			
				|  |  | +			peerUpdate.DefaultGwIp = relay.Address6.IP
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	return peerUpdate
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +func SetDefaultGw(node models.Node, peerUpdate models.HostPeerUpdate) models.HostPeerUpdate {
 | 
	
		
			
				|  |  | +	if node.InternetGwID != "" {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		inetNode, err := GetNodeByID(node.InternetGwID)
 | 
	
		
			
				|  |  | +		if err != nil {
 | 
	
		
			
				|  |  | +			return peerUpdate
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +		host, err := GetHost(node.HostID.String())
 | 
	
		
			
				|  |  | +		if err != nil {
 | 
	
		
			
				|  |  | +			return peerUpdate
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		peerUpdate.ChangeDefaultGw = true
 | 
	
		
			
				|  |  | +		peerUpdate.DefaultGwIp = inetNode.Address.IP
 | 
	
		
			
				|  |  | +		if peerUpdate.DefaultGwIp == nil || host.EndpointIP == nil {
 | 
	
		
			
				|  |  | +			peerUpdate.DefaultGwIp = inetNode.Address6.IP
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	return peerUpdate
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// GetAllowedIpForInetNodeClient - get inet cidr for node using a inet gw
 | 
	
		
			
				|  |  | +func GetAllowedIpForInetNodeClient(node, peer *models.Node) []net.IPNet {
 | 
	
		
			
				|  |  | +	var allowedips = []net.IPNet{}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if peer.Address.IP != nil {
 | 
	
		
			
				|  |  | +		_, ipnet, _ := net.ParseCIDR(IPv4Network)
 | 
	
		
			
				|  |  | +		allowedips = append(allowedips, *ipnet)
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if peer.Address6.IP != nil {
 | 
	
		
			
				|  |  | +		_, ipnet, _ := net.ParseCIDR(IPv6Network)
 | 
	
		
			
				|  |  | +		allowedips = append(allowedips, *ipnet)
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return allowedips
 | 
	
		
			
				|  |  | +}
 |