package logic import ( "errors" "fmt" "net" "github.com/google/uuid" "golang.org/x/exp/slog" "github.com/gravitl/netmaker/models" ) const ( IPv4Network = "0.0.0.0/0" IPv6Network = "::/0" ) 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.EgressDetails.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.EgressDetails.IsInternetGateway { return fmt.Errorf("node %s acting as internet gateway cannot use another internet gateway", clientHost.Name) } if update { if clientNode.EgressDetails.InternetGwID != "" && clientNode.EgressDetails.InternetGwID != inetNode.ID.String() { return fmt.Errorf("node %s is already using a internet gateway", clientHost.Name) } } else { if clientNode.EgressDetails.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.EgressDetails.InternetGwID != "" && node.EgressDetails.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.EgressDetails.IsInternetGateway = true node.EgressDetails.InetNodeReq = req for _, clientNodeID := range req.InetNodeClientIDs { clientNode, err := GetNodeByID(clientNodeID) if err != nil { continue } clientNode.EgressDetails.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.EgressDetails.InternetGwID { clientNode.EgressDetails.InternetGwID = "" UpsertNode(&clientNode) } } node.EgressDetails.IsInternetGateway = false node.EgressDetails.InetNodeReq = models.InetNodeReq{} } func SetDefaultGwForRelayedUpdate(relayed, relay models.Node, peerUpdate models.HostPeerUpdate) models.HostPeerUpdate { if relay.EgressDetails.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.EgressDetails.InternetGwID != "" { inetNode, err := GetNodeByID(node.EgressDetails.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 }