Browse Source

began refactoring of client

worker-9 4 years ago
parent
commit
44d03f6805

+ 13 - 6
controllers/authGrpc.go

@@ -4,6 +4,7 @@ import (
 	"context"
 	"encoding/json"
 	"errors"
+
 	"github.com/gravitl/netmaker/database"
 	"github.com/gravitl/netmaker/functions"
 	nodepb "github.com/gravitl/netmaker/grpc"
@@ -97,12 +98,17 @@ func grpcAuthorize(ctx context.Context) error {
 }
 
 //Node authenticates using its password and retrieves a JWT for authorization.
-func (s *NodeServiceServer) Login(ctx context.Context, req *nodepb.LoginRequest) (*nodepb.LoginResponse, error) {
+func (s *NodeServiceServer) Login(ctx context.Context, req *nodepb.Object) (*nodepb.Object, error) {
 
 	//out := new(LoginResponse)
-	macaddress := req.GetMacaddress()
-	network := req.GetNetwork()
-	password := req.GetPassword()
+	var reqNode models.Node
+	if err := json.Unmarshal([]byte(req.Data), &reqNode); err != nil {
+		return nil, err
+	}
+
+	macaddress := reqNode.MacAddress
+	network := reqNode.Network
+	password := reqNode.Password
 
 	var result models.NodeAuth
 
@@ -148,8 +154,9 @@ func (s *NodeServiceServer) Login(ctx context.Context, req *nodepb.LoginRequest)
 				return nil, err
 			}
 
-			response := &nodepb.LoginResponse{
-				Accesstoken: tokenString,
+			response := &nodepb.Object{
+				Data: tokenString,
+				Type: nodepb.ACCESS_TOKEN,
 			}
 			return response, nil
 		}

+ 40 - 102
controllers/common.go

@@ -2,7 +2,6 @@ package controller
 
 import (
 	"encoding/json"
-	"fmt"
 	"log"
 	"strconv"
 	"strings"
@@ -16,9 +15,9 @@ import (
 	"golang.org/x/crypto/bcrypt"
 )
 
-func GetPeersList(networkName string) ([]models.PeersResponse, error) {
+func GetPeersList(networkName string) ([]models.Node, error) {
 
-	var peers []models.PeersResponse
+	var peers []models.Node
 	collection, err := database.FetchRecords(database.NODES_TABLE_NAME)
 	if err != nil {
 		log.Println(err)
@@ -30,35 +29,31 @@ func GetPeersList(networkName string) ([]models.PeersResponse, error) {
 	}
 	for _, value := range collection {
 		var node models.Node
-		var peer models.PeersResponse
+		var peer models.Node
 		err := json.Unmarshal([]byte(value), &node)
 		if err != nil {
 			log.Println(err)
 			continue
 		}
-		err = json.Unmarshal([]byte(value), &peer)
-		if err != nil {
-			log.Println(err)
-			continue
-		}
 		if node.IsEgressGateway == "yes" {
-			peer.EgressGatewayRanges = strings.Join(node.EgressGatewayRanges, ",")
+			peer.EgressGatewayRanges = node.EgressGatewayRanges
 		}
 		if node.Network == networkName && node.IsPending != "yes" {
-			if node.UDPHolePunch == "yes" && errN == nil && functions.CheckEndpoint(udppeers[peer.PublicKey]) {
-				endpointstring := udppeers[peer.PublicKey]
+			peer.PublicKey = node.PublicKey
+			if node.UDPHolePunch == "yes" && errN == nil && functions.CheckEndpoint(udppeers[node.PublicKey]) {
+				endpointstring := udppeers[node.PublicKey]
 				endpointarr := strings.Split(endpointstring, ":")
-				log.Println("got values:",endpointstring,endpointarr)
+				log.Println("got values:", endpointstring, endpointarr)
 				if len(endpointarr) == 2 {
 					port, err := strconv.Atoi(endpointarr[1])
 					if err == nil {
-						log.Println("overriding:",endpointarr[0],int32(port))
+						log.Println("overriding:", endpointarr[0], int32(port))
 						peer.Endpoint = endpointarr[0]
 						peer.ListenPort = int32(port)
 					}
 				}
 			}
-			log.Println("setting peer:",peer.PublicKey,peer.Endpoint,peer.ListenPort)
+			log.Println("setting peer:", peer.PublicKey, peer.Endpoint, peer.ListenPort)
 			peers = append(peers, peer)
 		}
 	}
@@ -98,21 +93,38 @@ func GetExtPeersList(networkName string, macaddress string) ([]models.ExtPeersRe
 	return peers, err
 }
 
-func DeleteNode(macaddress string, network string) error {
-
-	key, err := functions.GetRecordKey(macaddress, network)
-	if err != nil {
-		return err
+/**
+ * If being deleted by server, create a record in the DELETED_NODES_TABLE for the client to find
+ * If being deleted by the client, delete completely
+ */
+func DeleteNode(key string, exterminate bool) error {
+	var err error
+	if !exterminate {
+		args := strings.Split(key, "###")
+		node, err := GetNode(args[0], args[1])
+		if err != nil {
+			return err
+		}
+		node.Action = models.NODE_DELETE
+		nodedata, err := json.Marshal(&node)
+		if err != nil {
+			return err
+		}
+		err = database.Insert(key, string(nodedata), database.DELETED_NODES_TABLE_NAME)
+		if err != nil {
+			return err
+		}
+	} else {
+		if err := database.DeleteRecord(database.DELETED_NODES_TABLE_NAME, key); err != nil {
+			log.Println(err)
+		}
 	}
-	if err = database.DeleteRecord(database.NODES_TABLE_NAME, key); err != nil {
+	if err := database.DeleteRecord(database.NODES_TABLE_NAME, key); err != nil {
 		return err
 	}
-
-	err = SetNetworkNodesLastModified(network)
 	if servercfg.IsDNSMode() {
 		err = SetDNS()
 	}
-
 	return err
 }
 
@@ -136,6 +148,10 @@ func GetNode(macaddress string, network string) (models.Node, error) {
 	}
 	data, err := database.FetchRecord(database.NODES_TABLE_NAME, key)
 	if err != nil {
+		if data == "" {
+			data, err = database.FetchRecord(database.DELETED_NODES_TABLE_NAME, key)
+			err = json.Unmarshal([]byte(data), &node)
+		}
 		return node, err
 	}
 	if err = json.Unmarshal([]byte(data), &node); err != nil {
@@ -222,84 +238,6 @@ func NotifyNetworkCheck(networkName string) bool {
 	}
 }
 
-func NodeCheckIn(node models.Node, networkName string) (models.CheckInResponse, error) {
-
-	var response models.CheckInResponse
-
-	parentnetwork, err := functions.GetParentNetwork(networkName)
-	if err != nil {
-		err = fmt.Errorf("%w; Couldnt retrieve Network "+networkName+": ", err)
-		return response, err
-	}
-
-	parentnode, err := GetNode(node.MacAddress, networkName)
-	if err != nil {
-		err = fmt.Errorf("%w; Couldnt Get Node "+node.MacAddress, err)
-		return response, err
-	}
-
-	if parentnode.Name == "netmaker" {
-		if NotifyNetworkCheck(networkName) {
-			err := SetNetworkNodesLastModified(networkName)
-			if err != nil {
-				log.Println(err, "could not notify network to update peers")
-			}
-		}
-		return models.CheckInResponse{
-			Success:true,
-			NeedPeerUpdate:true,
-			NeedKeyUpdate: false,
-			NeedConfigUpdate:false,
-			NeedDelete:false,
-			NodeMessage:"",
-			IsPending:false,
-		}, nil
-	}
-
-	if parentnode.IsPending == "yes" {
-		err = fmt.Errorf("%w; Node checking in is still pending: "+node.MacAddress, err)
-		response.IsPending = true
-		return response, err
-	}
-
-	networklm := parentnetwork.NetworkLastModified
-	peerslm := parentnetwork.NodesLastModified
-	gkeyupdate := parentnetwork.KeyUpdateTimeStamp
-	nkeyupdate := parentnode.KeyUpdateTimeStamp
-	peerlistlm := parentnode.LastPeerUpdate
-	parentnodelm := parentnode.LastModified
-	parentnodelastcheckin := parentnode.LastCheckIn
-
-	if parentnodelastcheckin < parentnodelm {
-		response.NeedConfigUpdate = true
-	}
-
-	if parentnodelm < networklm {
-		response.NeedConfigUpdate = true
-	}
-	if peerlistlm < peerslm {
-		response.NeedPeerUpdate = true
-	}
-	if nkeyupdate < gkeyupdate {
-		response.NeedKeyUpdate = true
-	}
-
-	if time.Now().Unix() > parentnode.ExpirationDateTime {
-		response.NeedDelete = true
-		err = DeleteNode(node.MacAddress, networkName)
-	} else {
-		err = TimestampNode(parentnode, true, false, false)
-
-		if err != nil {
-			err = fmt.Errorf("%w; Couldnt Timestamp Node: ", err)
-			return response, err
-		}
-	}
-	response.Success = true
-
-	return response, err
-}
-
 func SetNetworkNodesLastModified(networkName string) error {
 
 	timestamp := time.Now().Unix()

+ 4 - 9
controllers/networkHttpController.go

@@ -4,10 +4,11 @@ import (
 	"encoding/base64"
 	"encoding/json"
 	"errors"
+	"log"
 	"net/http"
 	"strings"
 	"time"
-	"log"
+
 	"github.com/go-playground/validator/v10"
 	"github.com/gorilla/mux"
 	"github.com/gravitl/netmaker/database"
@@ -232,17 +233,11 @@ func keyUpdate(w http.ResponseWriter, r *http.Request) {
 }
 
 func KeyUpdate(netname string) (models.Network, error) {
-	network, err := functions.GetParentNetwork(netname)
-	if err != nil {
-		return models.Network{}, err
-	}
-	network.KeyUpdateTimeStamp = time.Now().Unix()
-	data, err := json.Marshal(&network)
+	err := functions.NetworkNodesUpdateKey(netname)
 	if err != nil {
 		return models.Network{}, err
 	}
-	database.Insert(netname, string(data), database.NETWORKS_TABLE_NAME)
-	return network, nil
+	return models.Network{}, nil
 }
 
 //Update a network

+ 90 - 269
controllers/nodeGrpcController.go

@@ -2,83 +2,53 @@ package controller
 
 import (
 	"context"
-	"fmt"
+	"encoding/json"
+	"errors"
+	"log"
+
 	"github.com/gravitl/netmaker/functions"
 	nodepb "github.com/gravitl/netmaker/grpc"
 	"github.com/gravitl/netmaker/models"
-	"github.com/gravitl/netmaker/servercfg"
-	"google.golang.org/grpc/codes"
-	"google.golang.org/grpc/status"
 )
 
 type NodeServiceServer struct {
 	nodepb.UnimplementedNodeServiceServer
 }
 
-func (s *NodeServiceServer) ReadNode(ctx context.Context, req *nodepb.ReadNodeReq) (*nodepb.ReadNodeRes, error) {
+func (s *NodeServiceServer) ReadNode(ctx context.Context, req *nodepb.Object) (*nodepb.Object, error) {
 	// convert string id (from proto) to mongoDB ObjectId
-	macaddress := req.GetMacaddress()
-	networkName := req.GetNetwork()
-	network, _ := functions.GetParentNetwork(networkName)
+	var node models.Node
+	if err := json.Unmarshal([]byte(req.Data), &node); err != nil {
+		return nil, err
+	}
+	macaddress := node.MacAddress
+	networkName := node.Network
 
 	node, err := GetNode(macaddress, networkName)
 
 	if err != nil {
-		return nil, status.Errorf(codes.InvalidArgument, fmt.Sprintf("Something went wrong: %v", err))
+		log.Println("could not get node "+macaddress+" "+networkName, err)
+		return nil, err
 	}
 	// Cast to ReadNodeRes type
-
-	response := &nodepb.ReadNodeRes{
-		Node: &nodepb.Node{
-			Macaddress:          node.MacAddress,
-			Name:                node.Name,
-			Address:             node.Address,
-			Address6:            node.Address6,
-			Endpoint:            node.Endpoint,
-			Password:            node.Password,
-			Nodenetwork:         node.Network,
-			Interface:           node.Interface,
-			Localaddress:        node.LocalAddress,
-			Postdown:            node.PostDown,
-			Postup:              node.PostUp,
-			Checkininterval:     node.CheckInInterval,
-			Dnsoff:              !servercfg.IsDNSMode(),
-			Ispending:           node.IsPending == "yes",
-			Isingressgateway:    node.IsIngressGateway == "yes",
-			Ingressgatewayrange: node.IngressGatewayRange,
-			Publickey:           node.PublicKey,
-			Listenport:          node.ListenPort,
-			Keepalive:           node.PersistentKeepalive,
-			Islocal:             network.IsLocal == "yes",
-			Isdualstack:         network.IsDualStack == "yes",
-			Localrange:          network.LocalRange,
-			Udpholepunch:        node.UDPHolePunch,
-		},
+	nodeData, err := json.Marshal(&node)
+	if err != nil {
+		return nil, err
+	}
+	response := &nodepb.Object{
+		Data: string(nodeData),
+		Type: nodepb.NODE_TYPE,
 	}
 	return response, nil
 }
 
-func (s *NodeServiceServer) CreateNode(ctx context.Context, req *nodepb.CreateNodeReq) (*nodepb.CreateNodeRes, error) {
+func (s *NodeServiceServer) CreateNode(ctx context.Context, req *nodepb.Object) (*nodepb.Object, error) {
 	// Get the protobuf node type from the protobuf request type
 	// Essentially doing req.Node to access the struct with a nil check
-	data := req.GetNode()
-	// Now we have to convert this into a NodeItem type to convert into BSON
-	node := models.Node{
-		// ID:       primitive.NilObjectID,
-		MacAddress:          data.GetMacaddress(),
-		LocalAddress:        data.GetLocaladdress(),
-		Name:                data.GetName(),
-		Address:             data.GetAddress(),
-		Address6:            data.GetAddress6(),
-		AccessKey:           data.GetAccesskey(),
-		Endpoint:            data.GetEndpoint(),
-		PersistentKeepalive: data.GetKeepalive(),
-		Password:            data.GetPassword(),
-		Interface:           data.GetInterface(),
-		Network:             data.GetNodenetwork(),
-		PublicKey:           data.GetPublickey(),
-		ListenPort:          data.GetListenport(),
-		UDPHolePunch:        data.GetUdpholepunch(),
+	var node models.Node
+	data := req.GetData()
+	if err := json.Unmarshal([]byte(data), &node); err != nil {
+		return nil, err
 	}
 
 	//Check to see if key is valid
@@ -86,7 +56,7 @@ func (s *NodeServiceServer) CreateNode(ctx context.Context, req *nodepb.CreateNo
 	validKey := functions.IsKeyValid(node.Network, node.AccessKey)
 	network, err := functions.GetParentNetwork(node.Network)
 	if err != nil {
-		return nil, status.Errorf(codes.NotFound, fmt.Sprintf("Could not find network: %v", err))
+		return nil, err
 	}
 
 	if !validKey {
@@ -95,274 +65,125 @@ func (s *NodeServiceServer) CreateNode(ctx context.Context, req *nodepb.CreateNo
 		if network.AllowManualSignUp == "yes" {
 			node.IsPending = "yes"
 		} else {
-			return nil, status.Errorf(
-				codes.Internal,
-				fmt.Sprintf("Invalid key, and network does not allow no-key signups"),
-			)
+			return nil, errors.New("invalid key, and network does not allow no-key signups")
 		}
 	}
 
 	node, err = CreateNode(node, node.Network)
-
 	if err != nil {
-		// return internal gRPC error to be handled later
-		return nil, status.Errorf(
-			codes.Internal,
-			fmt.Sprintf("Internal error: %v", err),
-		)
+		log.Println("could not create node on network " + node.Network + " (gRPC controller)")
+		return nil, err
 	}
-
+	nodeData, err := json.Marshal(&node)
 	// return the node in a CreateNodeRes type
-	response := &nodepb.CreateNodeRes{
-		Node: &nodepb.Node{
-			Macaddress:   node.MacAddress,
-			Localaddress: node.LocalAddress,
-			Name:         node.Name,
-			Address:      node.Address,
-			Address6:     node.Address6,
-			Endpoint:     node.Endpoint,
-			Password:     node.Password,
-			Interface:    node.Interface,
-			Nodenetwork:  node.Network,
-			Dnsoff:       !servercfg.IsDNSMode(),
-			Ispending:    node.IsPending == "yes",
-			Publickey:    node.PublicKey,
-			Listenport:   node.ListenPort,
-			Keepalive:    node.PersistentKeepalive,
-			Islocal:      network.IsLocal == "yes",
-			Isdualstack:  network.IsDualStack == "yes",
-			Localrange:   network.LocalRange,
-			Udpholepunch: node.UDPHolePunch,
-		},
+	response := &nodepb.Object{
+		Data: string(nodeData),
+		Type: nodepb.NODE_TYPE,
 	}
 	err = SetNetworkNodesLastModified(node.Network)
 	if err != nil {
-		return nil, status.Errorf(codes.NotFound, fmt.Sprintf("Could not update network last modified date: %v", err))
-	}
-
-	return response, nil
-}
-
-func (s *NodeServiceServer) CheckIn(ctx context.Context, req *nodepb.CheckInReq) (*nodepb.CheckInRes, error) {
-	// Get the protobuf node type from the protobuf request type
-	// Essentially doing req.Node to access the struct with a nil check
-	data := req.GetNode()
-	//postchanges := req.GetPostchanges()
-	// Now we have to convert this into a NodeItem type to convert into BSON
-	node := models.Node{
-		// ID:       primitive.NilObjectID,
-		MacAddress:          data.GetMacaddress(),
-		Address:             data.GetAddress(),
-		Address6:            data.GetAddress6(),
-		Endpoint:            data.GetEndpoint(),
-		Network:             data.GetNodenetwork(),
-		Password:            data.GetPassword(),
-		LocalAddress:        data.GetLocaladdress(),
-		ListenPort:          data.GetListenport(),
-		PersistentKeepalive: data.GetKeepalive(),
-		PublicKey:           data.GetPublickey(),
-		UDPHolePunch:        data.GetUdpholepunch(),
-		SaveConfig:          data.GetSaveconfig(),
+		return nil, err
 	}
 
-	checkinresponse, err := NodeCheckIn(node, node.Network)
-
-	if err != nil {
-		// return internal gRPC error to be handled later
-		if checkinresponse == (models.CheckInResponse{}) || !checkinresponse.IsPending {
-			return nil, status.Errorf(
-				codes.Internal,
-				fmt.Sprintf("Internal error: %v", err),
-			)
-		}
-	}
-	// return the node in a CreateNodeRes type
-	response := &nodepb.CheckInRes{
-		Checkinresponse: &nodepb.CheckInResponse{
-			Success:          checkinresponse.Success,
-			Needpeerupdate:   checkinresponse.NeedPeerUpdate,
-			Needdelete:       checkinresponse.NeedDelete,
-			Needconfigupdate: checkinresponse.NeedConfigUpdate,
-			Needkeyupdate:    checkinresponse.NeedKeyUpdate,
-			Nodemessage:      checkinresponse.NodeMessage,
-			Ispending:        checkinresponse.IsPending,
-		},
-	}
 	return response, nil
 }
 
-func (s *NodeServiceServer) UpdateNode(ctx context.Context, req *nodepb.UpdateNodeReq) (*nodepb.UpdateNodeRes, error) {
+func (s *NodeServiceServer) UpdateNode(ctx context.Context, req *nodepb.Object) (*nodepb.Object, error) {
 	// Get the node data from the request
-	data := req.GetNode()
-	// Now we have to convert this into a NodeItem type to convert into BSON
-	newnode := models.Node{
-		// ID:       primitive.NilObjectID,
-		MacAddress:          data.GetMacaddress(),
-		Name:                data.GetName(),
-		Address:             data.GetAddress(),
-		Address6:            data.GetAddress6(),
-		LocalAddress:        data.GetLocaladdress(),
-		Endpoint:            data.GetEndpoint(),
-		Password:            data.GetPassword(),
-		PersistentKeepalive: data.GetKeepalive(),
-		Network:             data.GetNodenetwork(),
-		Interface:           data.GetInterface(),
-		PostDown:            data.GetPostdown(),
-		PostUp:              data.GetPostup(),
-		PublicKey:           data.GetPublickey(),
-		ListenPort:          data.GetListenport(),
-		UDPHolePunch:        data.GetUdpholepunch(),
-		SaveConfig:          data.GetSaveconfig(),
+	var newnode models.Node
+	if err := json.Unmarshal([]byte(req.GetData()), &newnode); err != nil {
+		return nil, err
 	}
-
-	// Convert the Id string to a MongoDB ObjectId
 	macaddress := newnode.MacAddress
 	networkName := newnode.Network
-	network, _ := functions.GetParentNetwork(networkName)
 
 	node, err := functions.GetNodeByMacAddress(networkName, macaddress)
 	if err != nil {
-		return nil, status.Errorf(
-			codes.NotFound,
-			fmt.Sprintf("Could not find node with supplied Mac Address: %v", err),
-		)
+		return nil, err
 	}
 
 	err = node.Update(&newnode)
-
 	if err != nil {
-		return nil, status.Errorf(
-			codes.NotFound,
-			fmt.Sprintf("Could not update node: %v", err),
-		)
+		return nil, err
 	}
-	return &nodepb.UpdateNodeRes{
-		Node: &nodepb.Node{
-			Macaddress:   newnode.MacAddress,
-			Localaddress: newnode.LocalAddress,
-			Name:         newnode.Name,
-			Address:      newnode.Address,
-			Address6:     newnode.Address6,
-			Endpoint:     newnode.Endpoint,
-			Password:     newnode.Password,
-			Interface:    newnode.Interface,
-			Postdown:     newnode.PostDown,
-			Postup:       newnode.PostUp,
-			Nodenetwork:  newnode.Network,
-			Ispending:    newnode.IsPending == "yes",
-			Publickey:    newnode.PublicKey,
-			Dnsoff:       !servercfg.IsDNSMode(),
-			Listenport:   newnode.ListenPort,
-			Keepalive:    newnode.PersistentKeepalive,
-			Islocal:      network.IsLocal == "yes",
-			Isdualstack:  network.IsDualStack == "yes",
-			Localrange:   network.LocalRange,
-			Udpholepunch: newnode.UDPHolePunch,
-		},
+	nodeData, err := json.Marshal(&node)
+
+	return &nodepb.Object{
+		Data: string(nodeData),
+		Type: nodepb.NODE_TYPE,
 	}, nil
 }
 
-func (s *NodeServiceServer) DeleteNode(ctx context.Context, req *nodepb.DeleteNodeReq) (*nodepb.DeleteNodeRes, error) {
-	macaddress := req.GetMacaddress()
-	network := req.GetNetworkName()
-
-	err := DeleteNode(macaddress, network)
+func (s *NodeServiceServer) DeleteNode(ctx context.Context, req *nodepb.Object) (*nodepb.Object, error) {
+	nodeID := req.GetData()
 
+	err := DeleteNode(nodeID, true)
 	if err != nil {
-		fmt.Println("Error deleting node.")
-		fmt.Println(err)
-		return nil, status.Errorf(codes.NotFound, fmt.Sprintf("Could not find/delete node with mac address %s", macaddress))
+		log.Println("Error deleting node (gRPC controller).")
+		return nil, err
 	}
 
-	fmt.Println("updating network last modified of " + req.GetNetworkName())
-	err = SetNetworkNodesLastModified(req.GetNetworkName())
-	if err != nil {
-		fmt.Println("Error updating Network")
-		fmt.Println(err)
-		return nil, status.Errorf(codes.NotFound, fmt.Sprintf("Could not update network last modified date: %v", err))
-	}
-
-	return &nodepb.DeleteNodeRes{
-		Success: true,
+	return &nodepb.Object{
+		Data: "success",
+		Type: nodepb.STRING_TYPE,
 	}, nil
 }
 
-func (s *NodeServiceServer) GetPeers(req *nodepb.GetPeersReq, stream nodepb.NodeService_GetPeersServer) error {
-	// Initiate a NodeItem type to write decoded data to
-	//data := &models.PeersResponse{}
-	// collection.Find returns a cursor for our (empty) query
-	peers, err := GetPeersList(req.GetNetwork())
-
-	if err != nil {
-		return status.Errorf(codes.Internal, fmt.Sprintf("Unknown internal error: %v", err))
-	}
-	// cursor.Next() returns a boolean, if false there are no more items and loop will break
-	for i := 0; i < len(peers); i++ {
-
-		// If no error is found send node over stream
-		stream.Send(&nodepb.GetPeersRes{
-			Peers: &nodepb.PeersResponse{
-				Address:            peers[i].Address,
-				Address6:           peers[i].Address6,
-				Endpoint:           peers[i].Endpoint,
-				Egressgatewayranges: peers[i].EgressGatewayRanges,
-				Isegressgateway:    peers[i].IsEgressGateway == "yes",
-				Publickey:          peers[i].PublicKey,
-				Keepalive:          peers[i].KeepAlive,
-				Listenport:         peers[i].ListenPort,
-				Localaddress:       peers[i].LocalAddress,
-			},
-		})
-	}
-
-	node, err := functions.GetNodeByMacAddress(req.GetNetwork(), req.GetMacaddress())
-	if err != nil {
-		return status.Errorf(codes.Internal, fmt.Sprintf("Could not get node: %v", err))
+func (s *NodeServiceServer) GetPeers(ctx context.Context, req *nodepb.Object) (*nodepb.Object, error) {
+	var node models.Node
+	if err := json.Unmarshal([]byte(req.GetData()), &node); err != nil {
+		return nil, err
 	}
 
-	err = TimestampNode(node, false, true, false)
+	peers, err := GetPeersList(node.Network)
 	if err != nil {
-		return status.Errorf(codes.Internal, fmt.Sprintf("Internal error occurred: %v", err))
+		return nil, err
 	}
 
-	return nil
+	peersData, err := json.Marshal(&peers)
+	return &nodepb.Object{
+		Data: string(peersData),
+		Type: nodepb.NODE_TYPE,
+	}, nil
 }
 
-func (s *NodeServiceServer) GetExtPeers(req *nodepb.GetExtPeersReq, stream nodepb.NodeService_GetExtPeersServer) error {
+/**
+ * Return Ext Peers (clients).NodeCheckIn
+ * When a gateway node checks in, it pulls these peers to add to peers list in addition to normal network peers.
+ */
+func (s *NodeServiceServer) GetExtPeers(ctx context.Context, req *nodepb.Object) (*nodepb.Object, error) {
 	// Initiate a NodeItem type to write decoded data to
 	//data := &models.PeersResponse{}
 	// collection.Find returns a cursor for our (empty) query
-	peers, err := GetExtPeersList(req.GetNetwork(), req.GetMacaddress())
-
+	var reqNode models.Node
+	if err := json.Unmarshal([]byte(req.Data), &reqNode); err != nil {
+		return nil, err
+	}
+	peers, err := GetExtPeersList(reqNode.Network, reqNode.MacAddress)
 	if err != nil {
-		return status.Errorf(codes.Internal, fmt.Sprintf("Unknown internal error: %v", err))
+		return nil, err
 	}
 	// cursor.Next() returns a boolean, if false there are no more items and loop will break
+	var extPeers []models.Node
 	for i := 0; i < len(peers); i++ {
-
-		// If no error is found send node over stream
-		stream.Send(&nodepb.GetExtPeersRes{
-			Extpeers: &nodepb.ExtPeersResponse{
-				Address:      peers[i].Address,
-				Address6:     peers[i].Address6,
-				Endpoint:     peers[i].Endpoint,
-				Publickey:    peers[i].PublicKey,
-				Keepalive:    peers[i].KeepAlive,
-				Listenport:   peers[i].ListenPort,
-				Localaddress: peers[i].LocalAddress,
-			},
+		extPeers = append(extPeers, models.Node{
+			Address:             peers[i].Address,
+			Address6:            peers[i].Address6,
+			Endpoint:            peers[i].Endpoint,
+			PublicKey:           peers[i].PublicKey,
+			PersistentKeepalive: peers[i].KeepAlive,
+			ListenPort:          peers[i].ListenPort,
+			LocalAddress:        peers[i].LocalAddress,
 		})
 	}
 
-	node, err := functions.GetNodeByMacAddress(req.GetNetwork(), req.GetMacaddress())
-	if err != nil {
-		return status.Errorf(codes.Internal, fmt.Sprintf("Could not get node: %v", err))
-	}
-
-	err = TimestampNode(node, false, true, false)
+	extData, err := json.Marshal(&extPeers)
 	if err != nil {
-		return status.Errorf(codes.Internal, fmt.Sprintf("Internal error occurred: %v", err))
+		return nil, err
 	}
 
-	return nil
+	return &nodepb.Object{
+		Data: string(extData),
+		Type: nodepb.EXT_PEER,
+	}, nil
 }

+ 1 - 1
controllers/nodeHttpController.go

@@ -809,7 +809,7 @@ func deleteNode(w http.ResponseWriter, r *http.Request) {
 	// get params
 	var params = mux.Vars(r)
 
-	err := DeleteNode(params["macaddress"], params["network"])
+	err := DeleteNode(params["macaddress"]+"###"+params["network"], false)
 
 	if err != nil {
 		returnErrorResponse(w, r, formatError(err, "internal"))

+ 1 - 1
controllers/userHttpController.go

@@ -183,7 +183,7 @@ func HasAdmin() (bool, error) {
 
 	collection, err := database.FetchRecords(database.USERS_TABLE_NAME)
 	if err != nil {
-		return false, err
+		return true, err
 	}
 
 	for _, value := range collection { // filter for isadmin true

+ 12 - 0
database/database.go

@@ -9,6 +9,7 @@ import (
 
 const NETWORKS_TABLE_NAME = "networks"
 const NODES_TABLE_NAME = "nodes"
+const DELETED_NODES_TABLE_NAME = "deletednodes"
 const USERS_TABLE_NAME = "users"
 const DNS_TABLE_NAME = "dns"
 const EXT_CLIENT_TABLE_NAME = "extclients"
@@ -16,6 +17,10 @@ const INT_CLIENTS_TABLE_NAME = "intclients"
 const PEERS_TABLE_NAME = "peers"
 const DATABASE_FILENAME = "netmaker.db"
 
+// == ERROR CONSTS ==
+const NO_RECORD = "no result found"
+const NO_RECORDS = "could not find any records"
+
 var Database gorqlite.Connection
 
 func InitializeDatabase() error {
@@ -35,6 +40,7 @@ func InitializeDatabase() error {
 func createTables() {
 	createTable(NETWORKS_TABLE_NAME)
 	createTable(NODES_TABLE_NAME)
+	createTable(DELETED_NODES_TABLE_NAME)
 	createTable(USERS_TABLE_NAME)
 	createTable(DNS_TABLE_NAME)
 	createTable(EXT_CLIENT_TABLE_NAME)
@@ -104,6 +110,9 @@ func FetchRecord(tableName string, key string) (string, error) {
 	if err != nil {
 		return "", err
 	}
+	if results[key] == "" {
+		return "", errors.New(NO_RECORD)
+	}
 	return results[key], nil
 }
 
@@ -119,6 +128,9 @@ func FetchRecords(tableName string) (map[string]string, error) {
 		row.Scan(&key, &value)
 		records[key] = value
 	}
+	if len(records) == 0 {
+		return nil, errors.New(NO_RECORDS)
+	}
 	// log.Println(records)
 	return records, nil
 }

+ 6 - 2
database/statics.go

@@ -2,6 +2,7 @@ package database
 
 import (
 	"encoding/json"
+	"strings"
 )
 
 func SetPeers(newPeers map[string]string, networkName string) bool {
@@ -26,7 +27,6 @@ func GetPeers(networkName string) (map[string]string, error) {
 	return currentDataMap, err
 }
 
-
 func PeersAreEqual(toCompare map[string]string, networkName string) bool {
 	currentDataMap, err := GetPeers(networkName)
 	if err != nil {
@@ -36,9 +36,13 @@ func PeersAreEqual(toCompare map[string]string, networkName string) bool {
 		return false
 	}
 	for k := range currentDataMap {
-		if currentDataMap[k] != toCompare[k] {
+		if toCompare[k] != currentDataMap[k] {
 			return false
 		}
 	}
 	return true
 }
+
+func IsEmptyRecord(err error) bool {
+	return strings.Contains(err.Error(), NO_RECORD) || strings.Contains(err.Error(), NO_RECORDS)
+}

+ 28 - 4
functions/helpers.go

@@ -21,7 +21,7 @@ import (
 )
 
 func CheckEndpoint(endpoint string) bool {
-    endpointarr := strings.Split(endpoint,":")
+	endpointarr := strings.Split(endpoint, ":")
 	return net.ParseIP(endpointarr[0]) == nil
 }
 
@@ -200,9 +200,6 @@ func GetRecordKey(id string, network string) (string, error) {
 	return id + "###" + network, nil
 }
 
-//TODO: This is  very inefficient (N-squared). Need to find a better way.
-//Takes a list of  nodes in a network and iterates through
-//for each node, it gets a unique address. That requires checking against all other nodes once more
 func UpdateNetworkNodeAddresses(networkName string) error {
 
 	collections, err := database.FetchRecords(database.NODES_TABLE_NAME)
@@ -235,6 +232,33 @@ func UpdateNetworkNodeAddresses(networkName string) error {
 	return nil
 }
 
+func NetworkNodesUpdateKey(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
+		}
+
+		node.Action = models.NODE_UPDATE_KEY
+		data, err := json.Marshal(&node)
+		if err != nil {
+			return err
+		}
+		database.Insert(node.MacAddress, string(data), database.NODES_TABLE_NAME)
+	}
+
+	return nil
+}
+
 func UpdateNetworkLocalAddresses(networkName string) error {
 
 	collection, err := database.FetchRecords(database.NODES_TABLE_NAME)

File diff suppressed because it is too large
+ 48 - 1669
grpc/node.pb.go


+ 12 - 153
grpc/node.proto

@@ -3,159 +3,18 @@ package node;
 option go_package = "google.golang.org/protobuf/types/known/nodepb";
 
 service NodeService {
-    rpc Login(LoginRequest) returns (LoginResponse);
-    rpc CreateNode(CreateNodeReq) returns (CreateNodeRes);
-    rpc ReadNode(ReadNodeReq) returns (ReadNodeRes);
-    rpc UpdateNode(UpdateNodeReq) returns (UpdateNodeRes);
-    rpc DeleteNode(DeleteNodeReq) returns (DeleteNodeRes);
-    rpc GetPeers(GetPeersReq) returns (stream GetPeersRes);
-    rpc GetExtPeers(GetExtPeersReq) returns (stream GetExtPeersRes);
-    rpc CheckIn(CheckInReq) returns (CheckInRes);
+    rpc Login(Object) returns (Object);
+    rpc CreateNode(Object) returns (Object);
+    rpc ReadNode(Object) returns (Object);
+    rpc UpdateNode(Object) returns (Object);
+    rpc DeleteNode(Object) returns (Object);
+    rpc GetPeers(Object) returns (Object);
+    rpc GetExtPeers(Object) returns (Object);
+    rpc CheckIn(Object) returns (Object);
 }
 
-message LoginRequest {
-  string macaddress = 1;
-  string password = 2;
-  string network = 3;
+message Object {  
+    string Data = 1;
+    string Type = 2;
+    string Metadata = 3;
 }
-
-message LoginResponse { string accesstoken = 1; }
-
-message Node {
-    string id = 1;
-    string name = 2;
-    string address = 3;
-    string address6 = 26;
-    int32 listenport = 4;
-    string publickey = 5;
-    string endpoint = 6;
-    string macaddress = 7;
-    string password = 8;
-    string nodenetwork = 9;
-    bool ispending = 10;
-    string postup = 11;
-    string postdown = 12;
-    int32 keepalive = 13;
-    string saveconfig = 14;
-    string accesskey = 15;
-    string interface = 16;
-    string lastcheckin = 17;
-    string lastmodified = 18;
-    int32 checkininterval = 19;
-    string localaddress = 20;
-    string postchanges = 21;
-    string allowedips = 22;
-    bool islocal = 23;
-    bool isingressgateway = 28;
-    string ingressgatewayrange = 29;
-    bool isdualstack = 27;
-    bool dnsoff = 24;
-    string localrange = 25;
-    string udpholepunch = 30;
-}
-
-message CheckInResponse {
-    bool success = 1;
-    bool needpeerupdate = 2;
-    bool needconfigupdate = 3;
-    string nodemessage = 4;
-    bool ispending = 5;
-    bool needkeyupdate = 6;
-    bool needdelete = 7;
-}
-
-message PeersResponse {
-    bool isegressgateway = 1;
-    string egressgatewayranges = 2;
-    string ingressgatewayrange = 9;
-    string publickey = 5;
-    string endpoint = 6;
-    string address = 3;
-    string address6 = 8;
-    int32 listenport = 4;
-    string localaddress = 7;
-    int32 keepalive = 13;
-}
-
-message ExtPeersResponse {
-    string publickey = 5;
-    string endpoint = 6;
-    string address = 3;
-    string address6 = 8;
-    int32 listenport = 4;
-    string localaddress = 7;
-    int32 keepalive = 13;
-}
-
-message Client {
-    string privatekey = 1;
-    string publickey = 2;
-    string accesskey = 3;
-    string address = 4;
-    string address6 = 5;
-    string serverwgendpoint = 6;
-    string serverport = 7;
-    string serverkey = 8;
-}
-
-message CreateNodeReq {
-    Node node = 1; // Node id blank
-}
-
-message CreateNodeRes {
-    Node node = 1; // Node id filled in
-}
-
-message UpdateNodeReq {
-    Node node = 1;
-}
-
-message UpdateNodeRes {
-    Node node = 1;
-}
-
-message ReadNodeReq {
-    string macaddress = 1;
-    string network = 2;
-}
-
-message ReadNodeRes {
-    Node node = 1;
-}
-
-message DeleteNodeReq {
-    string macaddress = 1;
-    string networkName = 2;
-}
-
-message DeleteNodeRes {
-    bool success = 1;
-}
-
-message GetPeersReq {
-    string macaddress = 1;
-    string network = 2;
-}
-
-message GetExtPeersReq {
-    string macaddress = 1;
-    string network = 2;
-}
-
-message GetPeersRes {
-    PeersResponse peers = 1;
-}
-
-message GetExtPeersRes {
-    ExtPeersResponse extpeers = 1;
-}
-
-message CheckInReq {
-    Node node = 1;
- //   bool postchanges = 2;
-}
-
-message CheckInRes {
-    CheckInResponse checkinresponse = 1;
-}
-

+ 95 - 150
grpc/node_grpc.pb.go

@@ -18,14 +18,14 @@ const _ = grpc.SupportPackageIsVersion7
 //
 // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
 type NodeServiceClient interface {
-	Login(ctx context.Context, in *LoginRequest, opts ...grpc.CallOption) (*LoginResponse, error)
-	CreateNode(ctx context.Context, in *CreateNodeReq, opts ...grpc.CallOption) (*CreateNodeRes, error)
-	ReadNode(ctx context.Context, in *ReadNodeReq, opts ...grpc.CallOption) (*ReadNodeRes, error)
-	UpdateNode(ctx context.Context, in *UpdateNodeReq, opts ...grpc.CallOption) (*UpdateNodeRes, error)
-	DeleteNode(ctx context.Context, in *DeleteNodeReq, opts ...grpc.CallOption) (*DeleteNodeRes, error)
-	GetPeers(ctx context.Context, in *GetPeersReq, opts ...grpc.CallOption) (NodeService_GetPeersClient, error)
-	GetExtPeers(ctx context.Context, in *GetExtPeersReq, opts ...grpc.CallOption) (NodeService_GetExtPeersClient, error)
-	CheckIn(ctx context.Context, in *CheckInReq, opts ...grpc.CallOption) (*CheckInRes, error)
+	Login(ctx context.Context, in *Object, opts ...grpc.CallOption) (*Object, error)
+	CreateNode(ctx context.Context, in *Object, opts ...grpc.CallOption) (*Object, error)
+	ReadNode(ctx context.Context, in *Object, opts ...grpc.CallOption) (*Object, error)
+	UpdateNode(ctx context.Context, in *Object, opts ...grpc.CallOption) (*Object, error)
+	DeleteNode(ctx context.Context, in *Object, opts ...grpc.CallOption) (*Object, error)
+	GetPeers(ctx context.Context, in *Object, opts ...grpc.CallOption) (*Object, error)
+	GetExtPeers(ctx context.Context, in *Object, opts ...grpc.CallOption) (*Object, error)
+	CheckIn(ctx context.Context, in *Object, opts ...grpc.CallOption) (*Object, error)
 }
 
 type nodeServiceClient struct {
@@ -36,8 +36,8 @@ func NewNodeServiceClient(cc grpc.ClientConnInterface) NodeServiceClient {
 	return &nodeServiceClient{cc}
 }
 
-func (c *nodeServiceClient) Login(ctx context.Context, in *LoginRequest, opts ...grpc.CallOption) (*LoginResponse, error) {
-	out := new(LoginResponse)
+func (c *nodeServiceClient) Login(ctx context.Context, in *Object, opts ...grpc.CallOption) (*Object, error) {
+	out := new(Object)
 	err := c.cc.Invoke(ctx, "/node.NodeService/Login", in, out, opts...)
 	if err != nil {
 		return nil, err
@@ -45,8 +45,8 @@ func (c *nodeServiceClient) Login(ctx context.Context, in *LoginRequest, opts ..
 	return out, nil
 }
 
-func (c *nodeServiceClient) CreateNode(ctx context.Context, in *CreateNodeReq, opts ...grpc.CallOption) (*CreateNodeRes, error) {
-	out := new(CreateNodeRes)
+func (c *nodeServiceClient) CreateNode(ctx context.Context, in *Object, opts ...grpc.CallOption) (*Object, error) {
+	out := new(Object)
 	err := c.cc.Invoke(ctx, "/node.NodeService/CreateNode", in, out, opts...)
 	if err != nil {
 		return nil, err
@@ -54,8 +54,8 @@ func (c *nodeServiceClient) CreateNode(ctx context.Context, in *CreateNodeReq, o
 	return out, nil
 }
 
-func (c *nodeServiceClient) ReadNode(ctx context.Context, in *ReadNodeReq, opts ...grpc.CallOption) (*ReadNodeRes, error) {
-	out := new(ReadNodeRes)
+func (c *nodeServiceClient) ReadNode(ctx context.Context, in *Object, opts ...grpc.CallOption) (*Object, error) {
+	out := new(Object)
 	err := c.cc.Invoke(ctx, "/node.NodeService/ReadNode", in, out, opts...)
 	if err != nil {
 		return nil, err
@@ -63,8 +63,8 @@ func (c *nodeServiceClient) ReadNode(ctx context.Context, in *ReadNodeReq, opts
 	return out, nil
 }
 
-func (c *nodeServiceClient) UpdateNode(ctx context.Context, in *UpdateNodeReq, opts ...grpc.CallOption) (*UpdateNodeRes, error) {
-	out := new(UpdateNodeRes)
+func (c *nodeServiceClient) UpdateNode(ctx context.Context, in *Object, opts ...grpc.CallOption) (*Object, error) {
+	out := new(Object)
 	err := c.cc.Invoke(ctx, "/node.NodeService/UpdateNode", in, out, opts...)
 	if err != nil {
 		return nil, err
@@ -72,8 +72,8 @@ func (c *nodeServiceClient) UpdateNode(ctx context.Context, in *UpdateNodeReq, o
 	return out, nil
 }
 
-func (c *nodeServiceClient) DeleteNode(ctx context.Context, in *DeleteNodeReq, opts ...grpc.CallOption) (*DeleteNodeRes, error) {
-	out := new(DeleteNodeRes)
+func (c *nodeServiceClient) DeleteNode(ctx context.Context, in *Object, opts ...grpc.CallOption) (*Object, error) {
+	out := new(Object)
 	err := c.cc.Invoke(ctx, "/node.NodeService/DeleteNode", in, out, opts...)
 	if err != nil {
 		return nil, err
@@ -81,72 +81,26 @@ func (c *nodeServiceClient) DeleteNode(ctx context.Context, in *DeleteNodeReq, o
 	return out, nil
 }
 
-func (c *nodeServiceClient) GetPeers(ctx context.Context, in *GetPeersReq, opts ...grpc.CallOption) (NodeService_GetPeersClient, error) {
-	stream, err := c.cc.NewStream(ctx, &NodeService_ServiceDesc.Streams[0], "/node.NodeService/GetPeers", opts...)
+func (c *nodeServiceClient) GetPeers(ctx context.Context, in *Object, opts ...grpc.CallOption) (*Object, error) {
+	out := new(Object)
+	err := c.cc.Invoke(ctx, "/node.NodeService/GetPeers", in, out, opts...)
 	if err != nil {
 		return nil, err
 	}
-	x := &nodeServiceGetPeersClient{stream}
-	if err := x.ClientStream.SendMsg(in); err != nil {
-		return nil, err
-	}
-	if err := x.ClientStream.CloseSend(); err != nil {
-		return nil, err
-	}
-	return x, nil
-}
-
-type NodeService_GetPeersClient interface {
-	Recv() (*GetPeersRes, error)
-	grpc.ClientStream
-}
-
-type nodeServiceGetPeersClient struct {
-	grpc.ClientStream
-}
-
-func (x *nodeServiceGetPeersClient) Recv() (*GetPeersRes, error) {
-	m := new(GetPeersRes)
-	if err := x.ClientStream.RecvMsg(m); err != nil {
-		return nil, err
-	}
-	return m, nil
+	return out, nil
 }
 
-func (c *nodeServiceClient) GetExtPeers(ctx context.Context, in *GetExtPeersReq, opts ...grpc.CallOption) (NodeService_GetExtPeersClient, error) {
-	stream, err := c.cc.NewStream(ctx, &NodeService_ServiceDesc.Streams[1], "/node.NodeService/GetExtPeers", opts...)
+func (c *nodeServiceClient) GetExtPeers(ctx context.Context, in *Object, opts ...grpc.CallOption) (*Object, error) {
+	out := new(Object)
+	err := c.cc.Invoke(ctx, "/node.NodeService/GetExtPeers", in, out, opts...)
 	if err != nil {
 		return nil, err
 	}
-	x := &nodeServiceGetExtPeersClient{stream}
-	if err := x.ClientStream.SendMsg(in); err != nil {
-		return nil, err
-	}
-	if err := x.ClientStream.CloseSend(); err != nil {
-		return nil, err
-	}
-	return x, nil
-}
-
-type NodeService_GetExtPeersClient interface {
-	Recv() (*GetExtPeersRes, error)
-	grpc.ClientStream
-}
-
-type nodeServiceGetExtPeersClient struct {
-	grpc.ClientStream
-}
-
-func (x *nodeServiceGetExtPeersClient) Recv() (*GetExtPeersRes, error) {
-	m := new(GetExtPeersRes)
-	if err := x.ClientStream.RecvMsg(m); err != nil {
-		return nil, err
-	}
-	return m, nil
+	return out, nil
 }
 
-func (c *nodeServiceClient) CheckIn(ctx context.Context, in *CheckInReq, opts ...grpc.CallOption) (*CheckInRes, error) {
-	out := new(CheckInRes)
+func (c *nodeServiceClient) CheckIn(ctx context.Context, in *Object, opts ...grpc.CallOption) (*Object, error) {
+	out := new(Object)
 	err := c.cc.Invoke(ctx, "/node.NodeService/CheckIn", in, out, opts...)
 	if err != nil {
 		return nil, err
@@ -158,14 +112,14 @@ func (c *nodeServiceClient) CheckIn(ctx context.Context, in *CheckInReq, opts ..
 // All implementations must embed UnimplementedNodeServiceServer
 // for forward compatibility
 type NodeServiceServer interface {
-	Login(context.Context, *LoginRequest) (*LoginResponse, error)
-	CreateNode(context.Context, *CreateNodeReq) (*CreateNodeRes, error)
-	ReadNode(context.Context, *ReadNodeReq) (*ReadNodeRes, error)
-	UpdateNode(context.Context, *UpdateNodeReq) (*UpdateNodeRes, error)
-	DeleteNode(context.Context, *DeleteNodeReq) (*DeleteNodeRes, error)
-	GetPeers(*GetPeersReq, NodeService_GetPeersServer) error
-	GetExtPeers(*GetExtPeersReq, NodeService_GetExtPeersServer) error
-	CheckIn(context.Context, *CheckInReq) (*CheckInRes, error)
+	Login(context.Context, *Object) (*Object, error)
+	CreateNode(context.Context, *Object) (*Object, error)
+	ReadNode(context.Context, *Object) (*Object, error)
+	UpdateNode(context.Context, *Object) (*Object, error)
+	DeleteNode(context.Context, *Object) (*Object, error)
+	GetPeers(context.Context, *Object) (*Object, error)
+	GetExtPeers(context.Context, *Object) (*Object, error)
+	CheckIn(context.Context, *Object) (*Object, error)
 	mustEmbedUnimplementedNodeServiceServer()
 }
 
@@ -173,28 +127,28 @@ type NodeServiceServer interface {
 type UnimplementedNodeServiceServer struct {
 }
 
-func (UnimplementedNodeServiceServer) Login(context.Context, *LoginRequest) (*LoginResponse, error) {
+func (UnimplementedNodeServiceServer) Login(context.Context, *Object) (*Object, error) {
 	return nil, status.Errorf(codes.Unimplemented, "method Login not implemented")
 }
-func (UnimplementedNodeServiceServer) CreateNode(context.Context, *CreateNodeReq) (*CreateNodeRes, error) {
+func (UnimplementedNodeServiceServer) CreateNode(context.Context, *Object) (*Object, error) {
 	return nil, status.Errorf(codes.Unimplemented, "method CreateNode not implemented")
 }
-func (UnimplementedNodeServiceServer) ReadNode(context.Context, *ReadNodeReq) (*ReadNodeRes, error) {
+func (UnimplementedNodeServiceServer) ReadNode(context.Context, *Object) (*Object, error) {
 	return nil, status.Errorf(codes.Unimplemented, "method ReadNode not implemented")
 }
-func (UnimplementedNodeServiceServer) UpdateNode(context.Context, *UpdateNodeReq) (*UpdateNodeRes, error) {
+func (UnimplementedNodeServiceServer) UpdateNode(context.Context, *Object) (*Object, error) {
 	return nil, status.Errorf(codes.Unimplemented, "method UpdateNode not implemented")
 }
-func (UnimplementedNodeServiceServer) DeleteNode(context.Context, *DeleteNodeReq) (*DeleteNodeRes, error) {
+func (UnimplementedNodeServiceServer) DeleteNode(context.Context, *Object) (*Object, error) {
 	return nil, status.Errorf(codes.Unimplemented, "method DeleteNode not implemented")
 }
-func (UnimplementedNodeServiceServer) GetPeers(*GetPeersReq, NodeService_GetPeersServer) error {
-	return status.Errorf(codes.Unimplemented, "method GetPeers not implemented")
+func (UnimplementedNodeServiceServer) GetPeers(context.Context, *Object) (*Object, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method GetPeers not implemented")
 }
-func (UnimplementedNodeServiceServer) GetExtPeers(*GetExtPeersReq, NodeService_GetExtPeersServer) error {
-	return status.Errorf(codes.Unimplemented, "method GetExtPeers not implemented")
+func (UnimplementedNodeServiceServer) GetExtPeers(context.Context, *Object) (*Object, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method GetExtPeers not implemented")
 }
-func (UnimplementedNodeServiceServer) CheckIn(context.Context, *CheckInReq) (*CheckInRes, error) {
+func (UnimplementedNodeServiceServer) CheckIn(context.Context, *Object) (*Object, error) {
 	return nil, status.Errorf(codes.Unimplemented, "method CheckIn not implemented")
 }
 func (UnimplementedNodeServiceServer) mustEmbedUnimplementedNodeServiceServer() {}
@@ -211,7 +165,7 @@ func RegisterNodeServiceServer(s grpc.ServiceRegistrar, srv NodeServiceServer) {
 }
 
 func _NodeService_Login_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
-	in := new(LoginRequest)
+	in := new(Object)
 	if err := dec(in); err != nil {
 		return nil, err
 	}
@@ -223,13 +177,13 @@ func _NodeService_Login_Handler(srv interface{}, ctx context.Context, dec func(i
 		FullMethod: "/node.NodeService/Login",
 	}
 	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
-		return srv.(NodeServiceServer).Login(ctx, req.(*LoginRequest))
+		return srv.(NodeServiceServer).Login(ctx, req.(*Object))
 	}
 	return interceptor(ctx, in, info, handler)
 }
 
 func _NodeService_CreateNode_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
-	in := new(CreateNodeReq)
+	in := new(Object)
 	if err := dec(in); err != nil {
 		return nil, err
 	}
@@ -241,13 +195,13 @@ func _NodeService_CreateNode_Handler(srv interface{}, ctx context.Context, dec f
 		FullMethod: "/node.NodeService/CreateNode",
 	}
 	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
-		return srv.(NodeServiceServer).CreateNode(ctx, req.(*CreateNodeReq))
+		return srv.(NodeServiceServer).CreateNode(ctx, req.(*Object))
 	}
 	return interceptor(ctx, in, info, handler)
 }
 
 func _NodeService_ReadNode_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
-	in := new(ReadNodeReq)
+	in := new(Object)
 	if err := dec(in); err != nil {
 		return nil, err
 	}
@@ -259,13 +213,13 @@ func _NodeService_ReadNode_Handler(srv interface{}, ctx context.Context, dec fun
 		FullMethod: "/node.NodeService/ReadNode",
 	}
 	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
-		return srv.(NodeServiceServer).ReadNode(ctx, req.(*ReadNodeReq))
+		return srv.(NodeServiceServer).ReadNode(ctx, req.(*Object))
 	}
 	return interceptor(ctx, in, info, handler)
 }
 
 func _NodeService_UpdateNode_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
-	in := new(UpdateNodeReq)
+	in := new(Object)
 	if err := dec(in); err != nil {
 		return nil, err
 	}
@@ -277,13 +231,13 @@ func _NodeService_UpdateNode_Handler(srv interface{}, ctx context.Context, dec f
 		FullMethod: "/node.NodeService/UpdateNode",
 	}
 	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
-		return srv.(NodeServiceServer).UpdateNode(ctx, req.(*UpdateNodeReq))
+		return srv.(NodeServiceServer).UpdateNode(ctx, req.(*Object))
 	}
 	return interceptor(ctx, in, info, handler)
 }
 
 func _NodeService_DeleteNode_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
-	in := new(DeleteNodeReq)
+	in := new(Object)
 	if err := dec(in); err != nil {
 		return nil, err
 	}
@@ -295,55 +249,49 @@ func _NodeService_DeleteNode_Handler(srv interface{}, ctx context.Context, dec f
 		FullMethod: "/node.NodeService/DeleteNode",
 	}
 	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
-		return srv.(NodeServiceServer).DeleteNode(ctx, req.(*DeleteNodeReq))
+		return srv.(NodeServiceServer).DeleteNode(ctx, req.(*Object))
 	}
 	return interceptor(ctx, in, info, handler)
 }
 
-func _NodeService_GetPeers_Handler(srv interface{}, stream grpc.ServerStream) error {
-	m := new(GetPeersReq)
-	if err := stream.RecvMsg(m); err != nil {
-		return err
+func _NodeService_GetPeers_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(Object)
+	if err := dec(in); err != nil {
+		return nil, err
 	}
-	return srv.(NodeServiceServer).GetPeers(m, &nodeServiceGetPeersServer{stream})
-}
-
-type NodeService_GetPeersServer interface {
-	Send(*GetPeersRes) error
-	grpc.ServerStream
-}
-
-type nodeServiceGetPeersServer struct {
-	grpc.ServerStream
-}
-
-func (x *nodeServiceGetPeersServer) Send(m *GetPeersRes) error {
-	return x.ServerStream.SendMsg(m)
-}
-
-func _NodeService_GetExtPeers_Handler(srv interface{}, stream grpc.ServerStream) error {
-	m := new(GetExtPeersReq)
-	if err := stream.RecvMsg(m); err != nil {
-		return err
+	if interceptor == nil {
+		return srv.(NodeServiceServer).GetPeers(ctx, in)
 	}
-	return srv.(NodeServiceServer).GetExtPeers(m, &nodeServiceGetExtPeersServer{stream})
-}
-
-type NodeService_GetExtPeersServer interface {
-	Send(*GetExtPeersRes) error
-	grpc.ServerStream
-}
-
-type nodeServiceGetExtPeersServer struct {
-	grpc.ServerStream
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/node.NodeService/GetPeers",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(NodeServiceServer).GetPeers(ctx, req.(*Object))
+	}
+	return interceptor(ctx, in, info, handler)
 }
 
-func (x *nodeServiceGetExtPeersServer) Send(m *GetExtPeersRes) error {
-	return x.ServerStream.SendMsg(m)
+func _NodeService_GetExtPeers_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(Object)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(NodeServiceServer).GetExtPeers(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/node.NodeService/GetExtPeers",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(NodeServiceServer).GetExtPeers(ctx, req.(*Object))
+	}
+	return interceptor(ctx, in, info, handler)
 }
 
 func _NodeService_CheckIn_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
-	in := new(CheckInReq)
+	in := new(Object)
 	if err := dec(in); err != nil {
 		return nil, err
 	}
@@ -355,7 +303,7 @@ func _NodeService_CheckIn_Handler(srv interface{}, ctx context.Context, dec func
 		FullMethod: "/node.NodeService/CheckIn",
 	}
 	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
-		return srv.(NodeServiceServer).CheckIn(ctx, req.(*CheckInReq))
+		return srv.(NodeServiceServer).CheckIn(ctx, req.(*Object))
 	}
 	return interceptor(ctx, in, info, handler)
 }
@@ -388,21 +336,18 @@ var NodeService_ServiceDesc = grpc.ServiceDesc{
 			Handler:    _NodeService_DeleteNode_Handler,
 		},
 		{
-			MethodName: "CheckIn",
-			Handler:    _NodeService_CheckIn_Handler,
+			MethodName: "GetPeers",
+			Handler:    _NodeService_GetPeers_Handler,
 		},
-	},
-	Streams: []grpc.StreamDesc{
 		{
-			StreamName:    "GetPeers",
-			Handler:       _NodeService_GetPeers_Handler,
-			ServerStreams: true,
+			MethodName: "GetExtPeers",
+			Handler:    _NodeService_GetExtPeers_Handler,
 		},
 		{
-			StreamName:    "GetExtPeers",
-			Handler:       _NodeService_GetExtPeers_Handler,
-			ServerStreams: true,
+			MethodName: "CheckIn",
+			Handler:    _NodeService_CheckIn_Handler,
 		},
 	},
+	Streams:  []grpc.StreamDesc{},
 	Metadata: "grpc/node.proto",
 }

+ 6 - 0
grpc/types.go

@@ -0,0 +1,6 @@
+package nodepb
+
+const STRING_TYPE = "string"
+const NODE_TYPE = "node"
+const EXT_PEER = "extpeer"
+const ACCESS_TOKEN = "accesstoken"

+ 2 - 3
main.go

@@ -7,7 +7,6 @@ import (
 	"log"
 	"net"
 	"os"
-	"os/exec"
 	"os/signal"
 	"strconv"
 	"sync"
@@ -16,6 +15,7 @@ import (
 	"github.com/gravitl/netmaker/database"
 	"github.com/gravitl/netmaker/functions"
 	nodepb "github.com/gravitl/netmaker/grpc"
+	"github.com/gravitl/netmaker/netclient/local"
 	"github.com/gravitl/netmaker/servercfg"
 	"google.golang.org/grpc"
 )
@@ -34,8 +34,7 @@ func initialize() { // Client Mode Prereq Check
 		log.Fatal(err)
 	}
 	log.Println("database successfully connected.")
-	cmd := exec.Command("id", "-u")
-	output, err := cmd.Output()
+	output, err := local.RunCmd("id -u")
 
 	if err != nil {
 		log.Println("Error running 'id -u' for prereq check. Please investigate or disable client mode.")

+ 22 - 22
models/network.go

@@ -157,7 +157,7 @@ func (network *Network) IsNetworkNameUnique() (bool, error) {
 
 	dbs, err := GetNetworks()
 
-	if err != nil {
+	if err != nil && !database.IsEmptyRecord(err) {
 		return false, err
 	}
 
@@ -299,29 +299,29 @@ func (currentNetwork *Network) Update(newNetwork *Network) (bool, bool, error) {
 
 func (network *Network) SetNetworkNodesLastModified() error {
 
-        timestamp := time.Now().Unix()
-
-        network.NodesLastModified = timestamp
-        data, err := json.Marshal(&network)
-        if err != nil {
-                return err
-        }
-        err = database.Insert(network.NetID, string(data), database.NETWORKS_TABLE_NAME)
-        if err != nil {
-                return err
-        }
-        return nil
+	timestamp := time.Now().Unix()
+
+	network.NodesLastModified = timestamp
+	data, err := json.Marshal(&network)
+	if err != nil {
+		return err
+	}
+	err = database.Insert(network.NetID, string(data), database.NETWORKS_TABLE_NAME)
+	if err != nil {
+		return err
+	}
+	return nil
 }
 
 func GetNetwork(networkname string) (Network, error) {
 
-        var network 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 Network{}, err
-        }
-        return network, nil
+	var network 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 Network{}, err
+	}
+	return network, nil
 }

+ 90 - 37
models/node.go

@@ -16,48 +16,82 @@ import (
 const charset = "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
 const TEN_YEARS_IN_SECONDS = 300000000
 
+// == ACTIONS == (can only be set by GRPC)
+const NODE_UPDATE_KEY = "updatekey"
+const NODE_DELETE = "delete"
+const NODE_IS_PENDING = "pending"
+
 var seededRand *rand.Rand = rand.New(
 	rand.NewSource(time.Now().UnixNano()))
 
 //node struct
 type Node struct {
 	ID                  string   `json:"id,omitempty" bson:"id,omitempty"`
-	Address             string   `json:"address" bson:"address" validate:"omitempty,ipv4"`
-	Address6            string   `json:"address6" bson:"address6" validate:"omitempty,ipv6"`
-	LocalAddress        string   `json:"localaddress" bson:"localaddress" validate:"omitempty,ip"`
-	Name                string   `json:"name" bson:"name" validate:"omitempty,max=12,in_charset"`
-	ListenPort          int32    `json:"listenport" bson:"listenport" validate:"omitempty,numeric,min=1024,max=65535"`
-	PublicKey           string   `json:"publickey" bson:"publickey" validate:"required,base64"`
-	Endpoint            string   `json:"endpoint" bson:"endpoint" validate:"required,ip"`
-	PostUp              string   `json:"postup" bson:"postup"`
-	PostDown            string   `json:"postdown" bson:"postdown"`
-	AllowedIPs          []string `json:"allowedips" bson:"allowedips"`
-	PersistentKeepalive int32    `json:"persistentkeepalive" bson:"persistentkeepalive" validate:"omitempty,numeric,max=1000"`
-	SaveConfig          string   `json:"saveconfig" bson:"saveconfig" validate:"checkyesorno"`
-	AccessKey           string   `json:"accesskey" bson:"accesskey"`
-	Interface           string   `json:"interface" bson:"interface"`
-	LastModified        int64    `json:"lastmodified" bson:"lastmodified"`
-	KeyUpdateTimeStamp  int64    `json:"keyupdatetimestamp" bson:"keyupdatetimestamp"`
-	ExpirationDateTime  int64    `json:"expdatetime" bson:"expdatetime"`
-	LastPeerUpdate      int64    `json:"lastpeerupdate" bson:"lastpeerupdate"`
-	LastCheckIn         int64    `json:"lastcheckin" bson:"lastcheckin"`
-	MacAddress          string   `json:"macaddress" bson:"macaddress" validate:"required,mac,macaddress_unique"`
-	CheckInInterval     int32    `json:"checkininterval" bson:"checkininterval"`
-	Password            string   `json:"password" bson:"password" validate:"required,min=6"`
-	Network             string   `json:"network" bson:"network" validate:"network_exists"`
-	IsPending           string   `json:"ispending" bson:"ispending"`
-	IsEgressGateway     string   `json:"isegressgateway" bson:"isegressgateway"`
-	IsIngressGateway    string   `json:"isingressgateway" bson:"isingressgateway"`
-	EgressGatewayRanges []string `json:"egressgatewayranges" bson:"egressgatewayranges"`
-	IngressGatewayRange string   `json:"ingressgatewayrange" bson:"ingressgatewayrange"`
-	PostChanges         string   `json:"postchanges" bson:"postchanges"`
-	StaticIP            string   `json:"staticip" bson:"staticip"`
-	StaticPubKey        string   `json:"staticpubkey" bson:"staticpubkey"`
-	UDPHolePunch        string   `json:"udpholepunch" bson:"udpholepunch" validate:"checkyesorno"`
+	Address             string   `json:"address" bson:"address" yaml:"address" validate:"omitempty,ipv4"`
+	Address6            string   `json:"address6" bson:"address6" yaml:"address6" validate:"omitempty,ipv6"`
+	LocalAddress        string   `json:"localaddress" bson:"localaddress" yaml:"localaddress" validate:"omitempty,ip"`
+	Name                string   `json:"name" bson:"name" yaml:"name" validate:"omitempty,max=12,in_charset"`
+	ListenPort          int32    `json:"listenport" bson:"listenport" yaml:"listenport" validate:"omitempty,numeric,min=1024,max=65535"`
+	PublicKey           string   `json:"publickey" bson:"publickey" yaml:"publickey" validate:"required,base64"`
+	Endpoint            string   `json:"endpoint" bson:"endpoint" yaml:"endpoint" validate:"required,ip"`
+	PostUp              string   `json:"postup" bson:"postup" yaml:"postup"`
+	PostDown            string   `json:"postdown" bson:"postdown" yaml:"postdown"`
+	AllowedIPs          []string `json:"allowedips" bson:"allowedips" yaml:"allowedips"`
+	PersistentKeepalive int32    `json:"persistentkeepalive" bson:"persistentkeepalive" yaml:"persistentkeepalive" validate:"omitempty,numeric,max=1000"`
+	SaveConfig          string   `json:"saveconfig" bson:"saveconfig" yaml:"saveconfig" validate:"checkyesorno"`
+	AccessKey           string   `json:"accesskey" bson:"accesskey" yaml:"accesskey"`
+	Interface           string   `json:"interface" bson:"interface" yaml:"interface"`
+	LastModified        int64    `json:"lastmodified" bson:"lastmodified" yaml:"lastmodified"`
+	KeyUpdateTimeStamp  int64    `json:"keyupdatetimestamp" bson:"keyupdatetimestamp" yaml:"keyupdatetimestamp"`
+	ExpirationDateTime  int64    `json:"expdatetime" bson:"expdatetime" yaml:"expdatetime"`
+	LastPeerUpdate      int64    `json:"lastpeerupdate" bson:"lastpeerupdate" yaml:"lastpeerupdate"`
+	LastCheckIn         int64    `json:"lastcheckin" bson:"lastcheckin" yaml:"lastcheckin"`
+	MacAddress          string   `json:"macaddress" bson:"macaddress" yaml:"macaddress" validate:"required,mac,macaddress_unique"`
+	CheckInInterval     int32    `json:"checkininterval" bson:"checkininterval" yaml:"checkininterval"`
+	Password            string   `json:"password" bson:"password" yaml:"password" validate:"required,min=6"`
+	Network             string   `json:"network" bson:"network" yaml:"network" validate:"network_exists"`
+	IsPending           string   `json:"ispending" bson:"ispending" yaml:"ispending"`
+	IsEgressGateway     string   `json:"isegressgateway" bson:"isegressgateway" yaml:"isegressgateway"`
+	IsIngressGateway    string   `json:"isingressgateway" bson:"isingressgateway" yaml:"isingressgateway"`
+	EgressGatewayRanges []string `json:"egressgatewayranges" bson:"egressgatewayranges" yaml:"egressgatewayranges"`
+	IngressGatewayRange string   `json:"ingressgatewayrange" bson:"ingressgatewayrange" yaml:"ingressgatewayrange"`
+	StaticIP            string   `json:"staticip" bson:"staticip" yaml:"staticip"`
+	StaticPubKey        string   `json:"staticpubkey" bson:"staticpubkey" yaml:"staticpubkey"`
+	UDPHolePunch        string   `json:"udpholepunch" bson:"udpholepunch" yaml:"udpholepunch" validate:"checkyesorno"`
+	PullChanges         string   `json:"pullchanges" bson:"pullchanges" yaml:"pullchanges" validate:"checkyesorno"`
+	DNSOn               string   `json:"dnson" bson:"dnson" yaml:"dnson" validate:"checkyesorno"`
+	IsDualStack         string   `json:"isdualstack" bson:"isdualstack" yaml:"isdualstack" validate:"checkyesorno"`
+	Action              string   `json:"action" bson:"action" yaml:"action"`
+	IsLocal             string   `json:"islocal" bson:"islocal" yaml:"islocal" validate:"checkyesorno"`
+	LocalRange          string   `json:"localrange" bson:"localrange" yaml:"localrange"`
+	Roaming             string   `json:"roaming" bson:"roaming" yaml:"roaming" validate:"checkyesorno"`
+	IPForwarding        string   `json:"ipforwarding" bson:"ipforwarding" yaml:"ipforwarding" validate:"checkyesorno"`
+}
+
+func (node *Node) SetIPForwardingDefault() {
+	if node.IPForwarding == "" {
+		node.IPForwarding = "no"
+	}
+}
+
+func (node *Node) SetIsLocalDefault() {
+	if node.IsLocal == "" {
+		node.IsLocal = "no"
+	}
+}
+
+func (node *Node) SetDNSOnDefault() {
+	if node.DNSOn == "" {
+		node.DNSOn = "no"
+	}
+}
+
+func (node *Node) SetIsDualStackDefault() {
+	if node.IsDualStack == "" {
+		node.IsDualStack = "no"
+	}
 }
 
-//TODO:
-//Not sure if below two methods are necessary. May want to revisit
 func (node *Node) SetLastModified() {
 	node.LastModified = time.Now().Unix()
 }
@@ -141,7 +175,10 @@ func (node *Node) SetDefaults() {
 		}
 	}
 	node.CheckInInterval = parentNetwork.DefaultCheckInInterval
-
+	node.SetIPForwardingDefault()
+	node.SetDNSOnDefault()
+	node.SetIsLocalDefault()
+	node.SetIsDualStackDefault()
 	node.SetLastModified()
 	node.SetDefaultName()
 	node.SetLastCheckIn()
@@ -260,8 +297,24 @@ func (newNode *Node) Fill(currentNode *Node) {
 	if newNode.UDPHolePunch == "" {
 		newNode.UDPHolePunch = currentNode.SaveConfig
 	}
-
-	newNode.PostChanges = "no"
+	if newNode.DNSOn == "" {
+		newNode.DNSOn = currentNode.DNSOn
+	}
+	if newNode.IsDualStack == "" {
+		newNode.IsDualStack = currentNode.IsDualStack
+	}
+	if newNode.IsLocal == "" {
+		newNode.IsLocal = currentNode.IsLocal
+	}
+	if newNode.IPForwarding == "" {
+		newNode.IPForwarding = currentNode.IPForwarding
+	}
+	if newNode.Roaming == "" {
+		newNode.Roaming = currentNode.Roaming
+	}
+	if newNode.Action == "" {
+		newNode.Action = currentNode.Action
+	}
 }
 
 func (currentNode *Node) Update(newNode *Node) error {

+ 78 - 51
netclient/auth/auth.go

@@ -1,69 +1,96 @@
 package auth
 
 import (
-    "github.com/gravitl/netmaker/netclient/config"
-    "fmt"
-//    "os"
-    "context"
-    "io/ioutil"
-    "google.golang.org/grpc/metadata"
-    "google.golang.org/grpc/status"
-    "google.golang.org/grpc/codes"
-    nodepb "github.com/gravitl/netmaker/grpc"
+	"encoding/json"
+	"fmt"
 
+	"github.com/gravitl/netmaker/models"
+	"github.com/gravitl/netmaker/netclient/config"
+
+	//    "os"
+	"context"
+	"io/ioutil"
+
+	nodepb "github.com/gravitl/netmaker/grpc"
+	"google.golang.org/grpc/codes"
+	"google.golang.org/grpc/metadata"
+	"google.golang.org/grpc/status"
 )
 
 // CreateJWT func will used to create the JWT while signing in and signing out
 func SetJWT(client nodepb.NodeServiceClient, network string) (context.Context, error) {
-		//home, err := os.UserHomeDir()
-		home := "/etc/netclient"
-		tokentext, err := ioutil.ReadFile(home + "/nettoken-"+network)
-                if err != nil {
-			err = AutoLogin(client, network)
-			if err != nil {
-                                return nil, status.Errorf(codes.Unauthenticated, fmt.Sprintf("Something went wrong with Auto Login: %v", err))
-                        }
-			tokentext, err = ioutil.ReadFile(home + "/nettoken-"+network)
-			if err != nil {
-				return nil, status.Errorf(codes.Unauthenticated, fmt.Sprintf("Something went wrong: %v", err))
-			}
+	//home, err := os.UserHomeDir()
+	home := "/etc/netclient"
+	tokentext, err := ioutil.ReadFile(home + "/nettoken-" + network)
+	if err != nil {
+		err = AutoLogin(client, network)
+		if err != nil {
+			return nil, status.Errorf(codes.Unauthenticated, fmt.Sprintf("Something went wrong with Auto Login: %v", err))
 		}
-                token := string(tokentext)
+		tokentext, err = ioutil.ReadFile(home + "/nettoken-" + network)
+		if err != nil {
+			return nil, status.Errorf(codes.Unauthenticated, fmt.Sprintf("Something went wrong: %v", err))
+		}
+	}
+	token := string(tokentext)
 
-                // Anything linked to this variable will transmit request headers.
-                md := metadata.New(map[string]string{"authorization": token})
-                ctx := context.Background()
-                ctx = metadata.NewOutgoingContext(ctx, md)
-		return ctx, nil
+	// Anything linked to this variable will transmit request headers.
+	md := metadata.New(map[string]string{"authorization": token})
+	ctx := context.Background()
+	ctx = metadata.NewOutgoingContext(ctx, md)
+	return ctx, nil
 }
 
 func AutoLogin(client nodepb.NodeServiceClient, network string) error {
-	        //home, err := os.UserHomeDir()
-		home := "/etc/netclient"
-		//nodecfg := config.Config.Node
-                cfg, err := config.ReadConfig(network) 
-		if err != nil {
-			return err
-		}
-		login := &nodepb.LoginRequest{
-                        Password: cfg.Node.Password,
-                        Macaddress: cfg.Node.MacAddress,
-                        Network: network,
-                }
-    // RPC call
-                res, err := client.Login(context.TODO(), login)
-                if err != nil {
-                        return err
-                }
-                tokenstring := []byte(res.Accesstoken)
-                err = ioutil.WriteFile(home + "/nettoken-"+network, tokenstring, 0644)
-                if err != nil {
-                        return err
-                }
-                return err
+	//home, err := os.UserHomeDir()
+	home := "/etc/netclient"
+	//nodecfg := config.Config.Node
+	cfg, err := config.ReadConfig(network)
+	if err != nil {
+		return err
+	}
+	pass, err := RetrieveSecret(network)
+	if err != nil {
+		return err
+	}
+	node := models.Node{
+		Password:   pass,
+		MacAddress: cfg.Node.MacAddress,
+		Network:    network,
+	}
+	data, err := json.Marshal(&node)
+	if err != nil {
+		return nil
+	}
+
+	login := &nodepb.Object{
+		Data: string(data),
+	}
+	// RPC call
+	res, err := client.Login(context.TODO(), login)
+	if err != nil {
+		return err
+	}
+	tokenstring := []byte(res.Data)
+	err = ioutil.WriteFile(home+"/nettoken-"+network, tokenstring, 0644)
+	if err != nil {
+		return err
+	}
+	return err
+}
+
+func StoreSecret(key string, network string) error {
+	d1 := []byte(key)
+	err := ioutil.WriteFile("/etc/netclient/secret-"+network, d1, 0644)
+	return err
+}
+
+func RetrieveSecret(network string) (string, error) {
+	dat, err := ioutil.ReadFile("/etc/netclient/secret-" + network)
+	return string(dat), err
 }
 
 type Configuration struct {
 	MacAddress string
-	Password string
+	Password   string
 }

+ 52 - 61
netclient/command/commands.go

@@ -1,32 +1,28 @@
 package command
 
 import (
-        "github.com/gravitl/netmaker/netclient/functions"
-        "github.com/gravitl/netmaker/netclient/config"
-        "github.com/gravitl/netmaker/netclient/local"
-        "golang.zx2c4.com/wireguard/wgctrl"
-        nodepb "github.com/gravitl/netmaker/grpc"
+	"log"
 	"os"
 	"strings"
-	"log"
+
+	nodepb "github.com/gravitl/netmaker/grpc"
+	"github.com/gravitl/netmaker/netclient/config"
+	"github.com/gravitl/netmaker/netclient/functions"
+	"github.com/gravitl/netmaker/netclient/local"
+	"golang.zx2c4.com/wireguard/wgctrl"
 )
 
 var (
-        wgclient *wgctrl.Client
+	wgclient *wgctrl.Client
 )
 
 var (
-        wcclient nodepb.NodeServiceClient
+	wcclient nodepb.NodeServiceClient
 )
 
-func Register(cfg config.GlobalConfig) error {
-        err := functions.Register(cfg)
-        return err
-}
-
-func Join(cfg config.ClientConfig) error {
+func Join(cfg config.ClientConfig, privateKey string) error {
 
-	err := functions.JoinNetwork(cfg)
+	err := functions.JoinNetwork(cfg, privateKey)
 	if err != nil {
 		if !strings.Contains(err.Error(), "ALREADY_INSTALLED") {
 			log.Println("Error installing: ", err)
@@ -38,15 +34,15 @@ func Join(cfg config.ClientConfig) error {
 				}
 			}
 			if cfg.Daemon != "off" {
-	                        err = local.RemoveSystemDServices(cfg.Network)
-	                        if err != nil {
-	                                log.Println("Error removing services: ", err)
-	                        }
+				err = local.RemoveSystemDServices(cfg.Network)
+				if err != nil {
+					log.Println("Error removing services: ", err)
+				}
 			}
 		}
 		return err
 	}
-        log.Println("joined " + cfg.Network)
+	log.Println("joined " + cfg.Network)
 	if cfg.Daemon != "off" {
 		err = functions.InstallDaemon(cfg)
 	}
@@ -54,74 +50,70 @@ func Join(cfg config.ClientConfig) error {
 }
 
 func CheckIn(cfg config.ClientConfig) error {
-        if cfg.Network == "all" || cfg.Network == "" {
+	if cfg.Network == "all" || cfg.Network == "" {
 		log.Println("Required, '-n'. No network provided. Exiting.")
-                os.Exit(1)
-        }
-	err := functions.CheckIn(cfg)
-	if err != nil {
-		log.Println("Error checking in: ", err)
 		os.Exit(1)
 	}
-	return nil
+	err := functions.CheckConfig(cfg)
+	return err
 }
 
 func Leave(cfg config.ClientConfig) error {
 	err := functions.LeaveNetwork(cfg.Network)
-        if err != nil {
+	if err != nil {
 		log.Println("Error attempting to leave network " + cfg.Network)
-        }
+	}
 	return err
 }
 
 func Push(cfg config.ClientConfig) error {
-        var err error
-        if cfg.Network == "all" {
-                log.Println("No network selected. Running Push for all networks.")
-                networks, err := functions.GetNetworks()
-                if err != nil {
-                        log.Println("Error retrieving networks. Exiting.")
-                        return err
-                }
-                for _, network := range networks {
-                        err = functions.Push(network)
-                        if err != nil {
-                                log.Printf("Error pushing network configs for " + network + " network: ", err)
-                        } else {
-                                log.Println("pushed network config for " + network)
-                        }
-                }
-                err = nil
-        } else {
-                err = functions.Push(cfg.Network)
-        }
-        log.Println("Completed pushing network configs to remote server.")
-        return err
+	var err error
+	if cfg.Network == "all" {
+		log.Println("No network selected. Running Push for all networks.")
+		networks, err := functions.GetNetworks()
+		if err != nil {
+			log.Println("Error retrieving networks. Exiting.")
+			return err
+		}
+		for _, network := range networks {
+			err = functions.Push(network)
+			if err != nil {
+				log.Printf("Error pushing network configs for "+network+" network: ", err)
+			} else {
+				log.Println("pushed network config for " + network)
+			}
+		}
+		err = nil
+	} else {
+		err = functions.Push(cfg.Network)
+	}
+	log.Println("Completed pushing network configs to remote server.")
+	return err
 }
 
 func Pull(cfg config.ClientConfig) error {
-        var err error
+	var err error
 	if cfg.Network == "all" {
-                log.Println("No network selected. Running Pull for all networks.")
+		log.Println("No network selected. Running Pull for all networks.")
 		networks, err := functions.GetNetworks()
 		if err != nil {
 			log.Println("Error retrieving networks. Exiting.")
 			return err
 		}
 		for _, network := range networks {
-			err = functions.Pull(network)
+			_, err = functions.Pull(network, true)
 			if err != nil {
-				log.Printf("Error pulling network config for " + network + " network: ", err)
+				log.Printf("Error pulling network config for "+network+" network: ", err)
 			} else {
 				log.Println("pulled network config for " + network)
 			}
 		}
 		err = nil
 	} else {
-	        err = functions.Pull(cfg.Network)
+		_, err = functions.Pull(cfg.Network, true)
 	}
 	log.Println("Completed pulling network and peer configs.")
-        return err
+	return err
 }
 
 func List(cfg config.ClientConfig) error {
@@ -133,10 +125,9 @@ func Uninstall(cfg config.GlobalConfig) error {
 	log.Println("Uninstalling netclient")
 	err := functions.Uninstall()
 	err = functions.Unregister(cfg)
-        return err
+	return err
 }
 func Unregister(cfg config.GlobalConfig) error {
-        err := functions.Unregister(cfg)
-        return err
+	err := functions.Unregister(cfg)
+	return err
 }
-

+ 28 - 184
netclient/config/config.go

@@ -9,7 +9,6 @@ import (
 	"log"
 	"os"
 
-	nodepb "github.com/gravitl/netmaker/grpc"
 	"github.com/gravitl/netmaker/models"
 	"github.com/urfave/cli/v2"
 	"gopkg.in/yaml.v3"
@@ -22,7 +21,7 @@ type GlobalConfig struct {
 
 type ClientConfig struct {
 	Server          ServerConfig `yaml:"server"`
-	Node            NodeConfig   `yaml:"node"`
+	Node            models.Node  `yaml:"node"`
 	Network         string       `yaml:"network"`
 	Daemon          string       `yaml:"daemon"`
 	OperatingSystem string       `yaml:"operatingsystem"`
@@ -36,45 +35,6 @@ type ServerConfig struct {
 	GRPCWireGuard string `yaml:"grpcwg"`
 }
 
-type ListConfig struct {
-	Name           string `yaml:"name"`
-	Interface      string `yaml:"interface"`
-	PrivateIPv4    string `yaml:"wgaddress"`
-	PrivateIPv6    string `yaml:"wgaddress6"`
-	PublicEndpoint string `yaml:"endpoint"`
-}
-
-type NodeConfig struct {
-	Name             string `yaml:"name"`
-	Interface        string `yaml:"interface"`
-	Network          string `yaml:"network"`
-	Password         string `yaml:"password"`
-	MacAddress       string `yaml:"macaddress"`
-	LocalAddress     string `yaml:"localaddress"`
-	WGAddress        string `yaml:"wgaddress"`
-	WGAddress6       string `yaml:"wgaddress6"`
-	Roaming          string `yaml:"roaming"`
-	DNS              string `yaml:"dns"`
-	IsLocal          string `yaml:"islocal"`
-	IsDualStack      string `yaml:"isdualstack"`
-	IsIngressGateway string `yaml:"isingressgateway"`
-	LocalRange       string `yaml:"localrange"`
-	PostUp           string `yaml:"postup"`
-	PostDown         string `yaml:"postdown"`
-	Port             int32  `yaml:"port"`
-	KeepAlive        int32  `yaml:"keepalive"`
-	PublicKey        string `yaml:"publickey"`
-	ServerPubKey     string `yaml:"serverpubkey"`
-	PrivateKey       string `yaml:"privatekey"`
-	Endpoint         string `yaml:"endpoint"`
-	PostChanges      string `yaml:"postchanges"`
-	StaticIP         string `yaml:"staticip"`
-	StaticPubKey     string `yaml:"staticpubkey"`
-	IPForwarding     string `yaml:"ipforwarding"`
-	UDPHolePunch     string `yaml:"udpholepunch"`
-	SaveConfig     string `yaml:"saveconfig"`
-}
-
 //reading in the env file
 func Write(config *ClientConfig, network string) error {
 	if network == "" {
@@ -232,6 +192,7 @@ func (config *ClientConfig) ReadConfig() {
 			fmt.Println(err)
 			log.Fatal(err)
 		} else {
+			config.Node.SetID()
 			//config = cfg
 		}
 	}
@@ -289,10 +250,10 @@ func ModGlobalConfig(cfg models.IntClient) error {
 	return err
 }
 
-func ModConfig(node *nodepb.Node) error {
-	network := node.Nodenetwork
+func ModConfig(node *models.Node) error {
+	network := node.Network
 	if network == "" {
-		return errors.New("No Network Provided")
+		return errors.New("no network provided")
 	}
 	var modconfig ClientConfig
 	var err error
@@ -303,90 +264,23 @@ func ModConfig(node *nodepb.Node) error {
 		}
 		modconfig = *useconfig
 	}
-	nodecfg := modconfig.Node
-	if node.Name != "" {
-		nodecfg.Name = node.Name
-	}
-	if node.Interface != "" {
-		nodecfg.Interface = node.Interface
-	}
-	if node.Nodenetwork != "" {
-		nodecfg.Network = node.Nodenetwork
-	}
-	if node.Macaddress != "" {
-		nodecfg.MacAddress = node.Macaddress
-	}
-	if node.Localaddress != "" {
-		nodecfg.LocalAddress = node.Localaddress
-	}
-	if node.Postup != "" {
-		nodecfg.PostUp = node.Postup
-	}
-	if node.Postdown != "" {
-		nodecfg.PostDown = node.Postdown
-	}
-	if node.Listenport != 0 {
-		nodecfg.Port = node.Listenport
-	}
-	if node.Keepalive != 0 {
-		nodecfg.KeepAlive = node.Keepalive
-	}
-	if node.Publickey != "" {
-		nodecfg.PublicKey = node.Publickey
-	}
-	if node.Endpoint != "" {
-		nodecfg.Endpoint = node.Endpoint
-	}
-	if node.Password != "" {
-		nodecfg.Password = node.Password
-	}
-	if node.Address != "" {
-		nodecfg.WGAddress = node.Address
-	}
-	if node.Address6 != "" {
-		nodecfg.WGAddress6 = node.Address6
-	}
-	if node.Postchanges != "" {
-		nodecfg.PostChanges = node.Postchanges
-	}
-	if node.Dnsoff == true {
-		nodecfg.DNS = "off"
-	}
-	if node.Isdualstack == true {
-		nodecfg.IsDualStack = "yes"
-	}
-	if node.Udpholepunch != "" {
-		nodecfg.UDPHolePunch = node.Udpholepunch
-	}
-        if node.Saveconfig != "" {
-                nodecfg.SaveConfig = node.Saveconfig
-        }
-	if node.Isingressgateway {
-		nodecfg.IsIngressGateway = "yes"
-	} else {
-		nodecfg.IsIngressGateway = "no"
-	}
-	if node.Localrange != "" && node.Islocal {
-		nodecfg.IsLocal = "yes"
-		nodecfg.LocalRange = node.Localrange
-	}
-	modconfig.Node = nodecfg
+	modconfig.Node.Fill(node)
 	err = Write(&modconfig, network)
 	return err
 }
 
-func GetCLIConfig(c *cli.Context) (ClientConfig, error) {
+func GetCLIConfig(c *cli.Context) (ClientConfig, string, error) {
 	var cfg ClientConfig
 	if c.String("token") != "" {
 		tokenbytes, err := base64.StdEncoding.DecodeString(c.String("token"))
 		if err != nil {
 			log.Println("error decoding token")
-			return cfg, err
+			return cfg, "", err
 		}
 		var accesstoken models.AccessToken
 		if err := json.Unmarshal(tokenbytes, &accesstoken); err != nil {
 			log.Println("error converting token json to object", tokenbytes)
-			return cfg, err
+			return cfg, "", err
 		}
 
 		if accesstoken.ServerConfig.APIConnString != "" {
@@ -454,87 +348,25 @@ func GetCLIConfig(c *cli.Context) (ClientConfig, error) {
 	cfg.Node.Password = c.String("password")
 	cfg.Node.MacAddress = c.String("macaddress")
 	cfg.Node.LocalAddress = c.String("localaddress")
-	cfg.Node.WGAddress = c.String("address")
-	cfg.Node.WGAddress6 = c.String("addressIPV6")
+	cfg.Node.Address = c.String("address")
+	cfg.Node.Address6 = c.String("addressIPV6")
 	cfg.Node.Roaming = c.String("roaming")
-	cfg.Node.DNS = c.String("dns")
+	cfg.Node.DNSOn = c.String("dns")
 	cfg.Node.IsLocal = c.String("islocal")
 	cfg.Node.IsDualStack = c.String("isdualstack")
 	cfg.Node.PostUp = c.String("postup")
 	cfg.Node.PostDown = c.String("postdown")
-	cfg.Node.Port = int32(c.Int("port"))
-	cfg.Node.KeepAlive = int32(c.Int("keepalive"))
+	cfg.Node.ListenPort = int32(c.Int("port"))
+	cfg.Node.PersistentKeepalive = int32(c.Int("keepalive"))
 	cfg.Node.PublicKey = c.String("publickey")
-	cfg.Node.PrivateKey = c.String("privatekey")
+	privateKey := c.String("privatekey")
 	cfg.Node.Endpoint = c.String("endpoint")
 	cfg.Node.IPForwarding = c.String("ipforwarding")
 	cfg.OperatingSystem = c.String("operatingsystem")
 	cfg.Daemon = c.String("daemon")
 	cfg.Node.UDPHolePunch = c.String("udpholepunch")
 
-	return cfg, nil
-}
-
-func GetCLIConfigRegister(c *cli.Context) (GlobalConfig, error) {
-	var cfg GlobalConfig
-	if c.String("token") != "" {
-		tokenbytes, err := base64.StdEncoding.DecodeString(c.String("token"))
-		if err != nil {
-			log.Println("error decoding token")
-			return cfg, err
-		}
-		var accesstoken models.AccessToken
-		if err := json.Unmarshal(tokenbytes, &accesstoken); err != nil {
-			log.Println("error converting token json to object", tokenbytes)
-			return cfg, err
-		}
-		cfg.GRPCWireGuard = accesstoken.WG.GRPCWireGuard
-		cfg.Client.ServerPrivateAddress = accesstoken.WG.GRPCWGAddress
-		cfg.Client.ServerGRPCPort = accesstoken.WG.GRPCWGPort
-		if err != nil {
-			log.Println("error decoding token grpcserver")
-			return cfg, err
-		}
-		if err != nil {
-			log.Println("error decoding token apiserver")
-			return cfg, err
-		}
-		if accesstoken.ServerConfig.APIConnString != "" {
-			cfg.Client.ServerPublicEndpoint = accesstoken.ServerConfig.APIConnString
-		} else {
-			cfg.Client.ServerPublicEndpoint = accesstoken.ServerConfig.APIHost
-			if accesstoken.ServerConfig.APIPort != "" {
-				cfg.Client.ServerAPIPort = accesstoken.ServerConfig.APIPort
-			}
-		}
-		cfg.Client.ServerWGPort = accesstoken.WG.GRPCWGPort
-		cfg.Client.ServerKey = accesstoken.ClientConfig.Key
-		cfg.Client.ServerKey = accesstoken.WG.GRPCWGPubKey
-
-		if c.String("grpcserver") != "" {
-			cfg.Client.ServerPrivateAddress = c.String("grpcserver")
-		}
-		if c.String("apiserver") != "" {
-			cfg.Client.ServerPublicEndpoint = c.String("apiserver")
-		}
-		if c.String("pubkey") != "" {
-			cfg.Client.ServerKey = c.String("pubkey")
-		}
-		if c.String("network") != "all" {
-			cfg.Client.Network = c.String("network")
-		}
-	} else {
-		cfg.Client.ServerPrivateAddress = c.String("grpcserver")
-		cfg.Client.ServerPublicEndpoint = c.String("apiserver")
-		cfg.Client.ServerKey = c.String("key")
-		cfg.Client.Network = c.String("network")
-	}
-	cfg.Client.Address = c.String("address")
-	cfg.Client.Address6 = c.String("addressIPV6")
-	cfg.Client.PublicKey = c.String("pubkey")
-	cfg.Client.PrivateKey = c.String("privkey")
-
-	return cfg, nil
+	return cfg, privateKey, nil
 }
 
 func ReadConfig(network string) (*ClientConfig, error) {
@@ -596,3 +428,15 @@ func FileExists(f string) bool {
 	}
 	return !info.IsDir()
 }
+
+func GetNode(network string) models.Node {
+
+	modcfg, err := ReadConfig(network)
+	if err != nil {
+		log.Fatalf("Error: %v", err)
+	}
+	var node models.Node
+	node.Fill(&modcfg.Node)
+
+	return node
+}

+ 238 - 343
netclient/functions/checkin.go

@@ -1,389 +1,284 @@
 package functions
 
 import (
-        "google.golang.org/grpc/credentials"
-        "crypto/tls"
-	"context"
-	"strings"
+	"crypto/tls"
+	"encoding/json"
+	"errors"
 	"log"
-	"net"
-	"os/exec"
-        "github.com/gravitl/netmaker/netclient/config"
-        "github.com/gravitl/netmaker/netclient/local"
-        "github.com/gravitl/netmaker/netclient/wireguard"
-        "github.com/gravitl/netmaker/netclient/server"
-        "github.com/gravitl/netmaker/netclient/auth"
-        nodepb "github.com/gravitl/netmaker/grpc"
-        "google.golang.org/grpc"
+
+	nodepb "github.com/gravitl/netmaker/grpc"
+	"github.com/gravitl/netmaker/models"
+	"github.com/gravitl/netmaker/netclient/auth"
+	"github.com/gravitl/netmaker/netclient/config"
+	"github.com/gravitl/netmaker/netclient/local"
+	"github.com/gravitl/netmaker/netclient/wireguard"
+	"google.golang.org/grpc"
+	"google.golang.org/grpc/credentials"
 	"google.golang.org/grpc/metadata"
 	//homedir "github.com/mitchellh/go-homedir"
 )
 
-func CheckIn(cliconf config.ClientConfig) error {
-	network := cliconf.Network
-	node := server.GetNode(network)
-        cfg, err := config.ReadConfig(network)
-        if err != nil {
-                return err
-        }
-	nodecfg := cfg.Node
-	servercfg := cfg.Server
-	log.Println("Checking into server at " + servercfg.GRPCAddress)
-
-	setupcheck := true
+func checkIP(node *models.Node, servercfg config.ServerConfig, cliconf config.ClientConfig, network string) bool {
 	ipchange := false
+	var err error
+	if node.Roaming == "yes" {
+		if node.IsLocal == "no" {
+			log.Println("Checking to see if public addresses have changed")
+			extIP, err := getPublicIP()
+			if err != nil {
+				log.Println("error encountered checking ip addresses:", err)
+			}
+			if node.Endpoint != extIP && extIP != "" {
+				log.Println("Endpoint has changed from " +
+					node.Endpoint + " to " + extIP)
+				log.Println("Updating address")
+				node.Endpoint = extIP
+				ipchange = true
+			}
+			intIP, err := getPrivateAddr()
+			if err != nil {
+				log.Println("error encountered checking ip addresses:", err)
+			}
+			if node.LocalAddress != intIP && intIP != "" {
+				log.Println("Local Address has changed from " +
+					node.LocalAddress + " to " + intIP)
+				log.Println("Updating address")
+				node.LocalAddress = intIP
+				ipchange = true
+			}
+		} else {
+			log.Println("Checking to see if local addresses have changed")
+			localIP, err := getLocalIP(node.LocalRange)
+			if err != nil {
+				log.Println("error encountered checking ip addresses:", err)
+			}
+			if node.Endpoint != localIP && localIP != "" {
+				log.Println("Endpoint has changed from " +
+					node.Endpoint + " to " + localIP)
+				log.Println("Updating address")
+				node.Endpoint = localIP
+				node.LocalAddress = localIP
+				ipchange = true
+			}
+		}
+	}
+	if ipchange {
+		err = config.ModConfig(node)
+		if err != nil {
+			log.Println("Error:", err)
+			return false
+		}
+		err = wireguard.SetWGConfig(network, false)
+		if err != nil {
+			log.Println("Error:", err)
+			return false
+		}
+	}
+	return ipchange && err == nil
+}
 
-        if nodecfg.DNS == "on" || cliconf.Node.DNS == "on" {
+func setDNS(node *models.Node, servercfg config.ServerConfig, nodecfg *models.Node) {
+	if nodecfg.DNSOn == "yes" {
 		log.Println("setting dns")
 		ifacename := node.Interface
 		nameserver := servercfg.CoreDNSAddr
-		network := node.Nodenetwork
-                _ = local.UpdateDNS(ifacename, network, nameserver)
-        }
-
-	if !(nodecfg.IPForwarding == "off") {
-		out, err := exec.Command("sysctl", "net.ipv4.ip_forward").Output()
-                 if err != nil {
-	                 log.Println(err)
-			 log.Println("WARNING: Error encountered setting ip forwarding. This can break functionality.")
-                 } else {
-                         s := strings.Fields(string(out))
-                         if s[2] != "1" {
-				_, err = exec.Command("sysctl", "-w", "net.ipv4.ip_forward=1").Output()
-				if err != nil {
-					log.Println(err)
-					log.Println("WARNING: Error encountered setting ip forwarding. You may want to investigate this.")
-				}
-			}
-		}
+		network := node.Network
+		_ = local.UpdateDNS(ifacename, network, nameserver)
 	}
+}
 
-	if nodecfg.Roaming != "off" {
-		if nodecfg.IsLocal != "yes" {
-		log.Println("Checking to see if public addresses have changed")
-		extIP, err := getPublicIP()
+/**
+ *
+ *
+ */
+func checkNodeActions(node *models.Node, network string, servercfg config.ServerConfig) string {
+	if node.Action == models.NODE_UPDATE_KEY {
+		err := wireguard.SetWGKeyConfig(network, servercfg.GRPCAddress)
 		if err != nil {
-			log.Println("Error encountered checking ip addresses: %v", err)
-		}
-		if nodecfg.Endpoint != extIP  && extIP != "" {
-	                log.Println("Endpoint has changed from " +
-			nodecfg.Endpoint + " to " + extIP)
-			log.Println("Updating address")
-			nodecfg.Endpoint = extIP
-			nodecfg.PostChanges = "true"
-			node.Endpoint = extIP
-			node.Postchanges = "true"
-			ipchange = true
-		}
-		intIP, err := getPrivateAddr()
-                if err != nil {
-                        log.Println("Error encountered checking ip addresses: %v", err)
-                }
-                if nodecfg.LocalAddress != intIP  && intIP != "" {
-                        log.Println("Local Address has changed from " +
-			nodecfg.LocalAddress + " to " + intIP)
-			log.Println("Updating address")
-			nodecfg.LocalAddress = intIP
-			nodecfg.PostChanges = "true"
-			node.Localaddress = intIP
-			node.Postchanges = "true"
-			ipchange = true
-                }
-		} else {
-                log.Println("Checking to see if local addresses have changed")
-                localIP, err := getLocalIP(nodecfg.LocalRange)
-                if err != nil {
-                        log.Println("Error encountered checking ip addresses: %v", err)
-                }
-                if nodecfg.Endpoint != localIP  && localIP != "" {
-                        log.Println("Endpoint has changed from " +
-                        nodecfg.Endpoint + " to " + localIP)
-                        log.Println("Updating address")
-                        nodecfg.Endpoint = localIP
-                        nodecfg.LocalAddress = localIP
-                        nodecfg.PostChanges = "true"
-                        node.Endpoint = localIP
-                        node.Localaddress = localIP
-                        node.Postchanges = "true"
-                        ipchange = true
-                }
-		}
-		if node.Postchanges != "true" {
-			log.Println("Addresses have not changed.")
+			log.Println("Unable to process reset keys request:", err)
+			return ""
 		}
+		node.Action = ""
+		return ""
 	}
-	if ipchange {
-		err := config.ModConfig(&node)
-                if err != nil {
-                        return err
-                        log.Fatalf("Error: %v", err)
-                }
-                err = wireguard.SetWGConfig(network, false)
-                if err != nil {
-                        return err
-                        log.Fatalf("Error: %v", err)
-                }
-	        node = server.GetNode(network)
-		cfg, err := config.ReadConfig(network)
+	if node.Action == models.NODE_DELETE {
+		err := LeaveNetwork(network)
 		if err != nil {
-			return err
+			log.Println("Error:", err)
+			return ""
 		}
-		nodecfg = cfg.Node
+		return models.NODE_DELETE
 	}
+	return ""
+}
 
-        var wcclient nodepb.NodeServiceClient
-        var requestOpts grpc.DialOption
-        requestOpts = grpc.WithInsecure()
-        if servercfg.GRPCSSL == "on" {
-		log.Println("using SSL")
-                h2creds := credentials.NewTLS(&tls.Config{NextProtos: []string{"h2"}})
-                requestOpts = grpc.WithTransportCredentials(h2creds)
-        } else {
-                log.Println("using insecure GRPC connection")
-	}
-        conn, err := grpc.Dial(servercfg.GRPCAddress, requestOpts)
-        if err != nil {
-		log.Println("Cant dial GRPC server: %v", err)
-		return err
-        }
-        wcclient = nodepb.NewNodeServiceClient(conn)
+/**
+ * Pull changes if any (interface refresh)
+ * - Save it
+ * Check local changes for (ipAddress, publickey, configfile changes) (interface refresh)
+ * - Save it
+ * - Push it
+ * Pull Peers (sync)
+ */
+func CheckConfig(cliconf config.ClientConfig) error {
 
-        ctx := context.Background()
-        log.Println("Authenticating with GRPC Server")
-        ctx, err = auth.SetJWT(wcclient, network)
-        if err != nil {
-                log.Println("Failed to authenticate: %v", err)
+	network := cliconf.Network
+	// node := server.GetNode(network)
+	cfg, err := config.ReadConfig(network)
+	if err != nil {
 		return err
 	}
-        log.Println("Authenticated")
-        log.Println("Checking In.")
+	// nodecfg := cfg.Node
+	servercfg := cfg.Server
 
-        var header metadata.MD
-	node.Nodenetwork = network
-        checkinres, err := wcclient.CheckIn(
-                ctx,
-                &nodepb.CheckInReq{
-                        Node: &node,
-                },
-		grpc.Header(&header),
-        )
-        if err != nil {
-        if  checkinres != nil && checkinres.Checkinresponse.Ispending {
-                log.Println("Node is in pending status. Waiting for Admin approval of  node before making further updates.")
-                return nil
-        }
-                log.Println("Unable to process Check In request: %v", err)
-		return err
-        }
-	log.Println("Checked in.")
-	if  checkinres.Checkinresponse.Ispending {
-		log.Println("Node is in pending status. Waiting for Admin approval of  node before making further updates.")
+	newNode, err := Pull(network, false)
+	if err != nil {
 		return err
 	}
-
-                newinterface := server.GetNode(network).Interface
-                readreq := &nodepb.ReadNodeReq{
-                        Macaddress: node.Macaddress,
-                        Network: node.Nodenetwork,
-                }
-                readres, err := wcclient.ReadNode(ctx, readreq, grpc.Header(&header))
-                if err != nil {
-                        log.Println("Error: %v", err)
-                } else {
-                currentiface := readres.Node.Interface
-                ifaceupdate := newinterface != currentiface
-                if err != nil {
-                        log.Println("Error retrieving interface: %v", err)
-                }
-                if ifaceupdate {
-			log.Println("Interface update: " + currentiface +
-			" >>>> " + newinterface)
-                        err := DeleteInterface(currentiface, nodecfg.PostDown)
-                        if err != nil {
-                                log.Println("ERROR DELETING INTERFACE: " + currentiface)
-                        }
-                err = wireguard.SetWGConfig(network, false)
-                if err != nil {
-                        log.Println("Error updating interface: %v", err)
-                }
-		}
-		}
-
-	if checkinres.Checkinresponse.Needconfigupdate {
-		log.Println("Server has requested that node update config.")
-		log.Println("Updating config from remote server.")
-                req := &nodepb.ReadNodeReq{
-                        Macaddress: node.Macaddress,
-                        Network: node.Nodenetwork,
-                }
-                readres, err := wcclient.ReadNode(ctx, req, grpc.Header(&header))
-                if err != nil {
-			return err
-                        log.Fatalf("Error: %v", err)
-                }
-                err = config.ModConfig(readres.Node)
-                if err != nil {
-			return err
-                        log.Fatalf("Error: %v", err)
-                }
-                err = wireguard.SetWGConfig(network, false)
-                if err != nil {
-			return err
-                        log.Fatalf("Error: %v", err)
-                }
-		setupcheck = false
-	} else if nodecfg.PostChanges == "true" {
-                log.Println("Node has requested to update remote config.")
-                log.Println("Posting local config to remote server.")
-		postnode := server.GetNode(network)
-		log.Println("POSTING NODE: ",postnode.Macaddress,postnode.Saveconfig)
-		req := &nodepb.UpdateNodeReq{
-                               Node: &postnode,
-                        }
-		res, err := wcclient.UpdateNode(ctx, req, grpc.Header(&header))
-                if err != nil {
-			return err
-			log.Fatalf("Error: %v", err)
-                }
-		res.Node.Postchanges = "false"
-		err = config.ModConfig(res.Node)
-                if err != nil {
-			return err
-                        log.Fatalf("Error: %v", err)
-                }
-                if err != nil {
-			return err
-                        log.Fatalf("Error: %v", err)
-                }
-		setupcheck = false
+	if newNode.IsPending == "yes" {
+		return errors.New("node is pending")
 	}
-        if checkinres.Checkinresponse.Needkeyupdate {
-                log.Println("Server has requested that node update key pairs.")
-                log.Println("Proceeding to re-generate key pairs for Wiregard.")
-                err = wireguard.SetWGKeyConfig(network, servercfg.GRPCAddress)
-                if err != nil {
-                        return err
-                        log.Fatalf("Unable to process reset keys request: %v", err)
-                }
-                setupcheck = false
-        }
-        if checkinres.Checkinresponse.Needpeerupdate {
-                log.Println("Server has requested that node update peer list.")
-                log.Println("Updating peer list from remote server.")
-                err = wireguard.SetWGConfig(network, true)
-                if err != nil {
-			return err
-                        log.Fatalf("Unable to process Set Peers request: %v", err)
-                }
-		setupcheck = false
-        }
-	if checkinres.Checkinresponse.Needdelete {
-		log.Println("This machine got the delete signal. Deleting.")
-                err := LeaveNetwork(network)
-                if err != nil {
-                        return err
-                        log.Fatalf("Error: %v", err)
-                }
+	// check for interface change
+	if cfg.Node.Interface != newNode.Interface {
+		if err = DeleteInterface(cfg.Node.Interface, cfg.Node.PostDown); err != nil {
+			log.Println("could not delete old interface", cfg.Node.Interface)
+		}
 	}
-	if setupcheck {
-	iface := nodecfg.Interface
-	_, err := net.InterfaceByName(iface)
-        if err != nil {
-		log.Println("interface " + iface + " does not currently exist. Setting up WireGuard.")
-                err = wireguard.SetWGKeyConfig(network, servercfg.GRPCAddress)
-                if err != nil {
-                        return err
-                        log.Fatalf("Error: %v", err)
-                }
+
+	actionCompleted := checkNodeActions(newNode, network, servercfg)
+	if actionCompleted == models.NODE_DELETE {
+		return errors.New("node has been removed")
 	}
+	// Check if ip changed and push if so
+	if checkIP(newNode, servercfg, cliconf, network) {
+		err = Push(network)
 	}
-        //err = Pull(network)
 	return err
 }
 
-func Pull (network string) error{
-        node := server.GetNode(network)
+/**
+ * Pull the latest node from server
+ * Perform action if necessary
+ */
+func Pull(network string, manual bool) (*models.Node, error) {
+	node := config.GetNode(network)
 	cfg, err := config.ReadConfig(network)
-        if err != nil {
-                return err
-        }
-        servercfg := cfg.Server
-        var header metadata.MD
+	if err != nil {
+		return nil, err
+	}
+	servercfg := cfg.Server
+	var header metadata.MD
 
-	var wcclient nodepb.NodeServiceClient
-        var requestOpts grpc.DialOption
-        requestOpts = grpc.WithInsecure()
-        if cfg.Server.GRPCSSL == "on" {
-                h2creds := credentials.NewTLS(&tls.Config{NextProtos: []string{"h2"}})
-                requestOpts = grpc.WithTransportCredentials(h2creds)
-        }
-        conn, err := grpc.Dial(servercfg.GRPCAddress, requestOpts)
-        if err != nil {
-                log.Println("Cant dial GRPC server: %v", err)
-                return err
-        }
-        wcclient = nodepb.NewNodeServiceClient(conn)
+	if cfg.Node.IPForwarding == "yes" {
+		if err = local.SetIPForwarding(); err != nil {
+			return nil, err
+		}
+	}
 
-        ctx := context.Background()
-        ctx, err = auth.SetJWT(wcclient, network)
-        if err != nil {
-                log.Println("Failed to authenticate: %v", err)
-                return err
-        }
+	var requestOpts grpc.DialOption
+	requestOpts = grpc.WithInsecure()
+	if cfg.Server.GRPCSSL == "on" {
+		h2creds := credentials.NewTLS(&tls.Config{NextProtos: []string{"h2"}})
+		requestOpts = grpc.WithTransportCredentials(h2creds)
+	}
+	conn, err := grpc.Dial(servercfg.GRPCAddress, requestOpts)
+	if err != nil {
+		log.Println("Cant dial GRPC server:", err)
+		return nil, err
+	}
+	wcclient := nodepb.NewNodeServiceClient(conn)
 
-        req := &nodepb.ReadNodeReq{
-                Macaddress: node.Macaddress,
-                Network: node.Nodenetwork,
-        }
-         readres, err := wcclient.ReadNode(ctx, req, grpc.Header(&header))
-         if err != nil {
-               return err
-         }
-         err = config.ModConfig(readres.Node)
-         if err != nil {
-                return err
-         }
-         err = wireguard.SetWGConfig(network, false)
-        if err != nil {
-                return err
-        }
+	ctx, err := auth.SetJWT(wcclient, network)
+	if err != nil {
+		log.Println("Failed to authenticate:", err)
+		return nil, err
+	}
 
-	return err
+	req := &nodepb.Object{
+		Data: node.MacAddress + "###" + node.Network,
+		Type: nodepb.STRING_TYPE,
+	}
+	readres, err := wcclient.ReadNode(ctx, req, grpc.Header(&header))
+	if err != nil {
+		return nil, err
+	}
+	var resNode models.Node
+	if err = json.Unmarshal([]byte(readres.Data), &resNode); err != nil {
+		return nil, err
+	}
+	if resNode.PullChanges == "yes" || manual {
+		if err = config.ModConfig(&resNode); err != nil {
+			return nil, err
+		}
+		if err = wireguard.SetWGConfig(network, false); err != nil {
+			return nil, err
+		}
+		resNode.PullChanges = "no"
+		nodeData, err := json.Marshal(&resNode)
+		if err != nil {
+			return &resNode, err
+		}
+		req := &nodepb.Object{
+			Data:     string(nodeData),
+			Type:     nodepb.NODE_TYPE,
+			Metadata: "",
+		}
+		_, err = wcclient.UpdateNode(ctx, req, grpc.Header(&header))
+		if err != nil {
+			return &resNode, err
+		}
+	}
+	setDNS(&node, servercfg, &cfg.Node)
+
+	return &node, err
 }
 
-func Push (network string) error{
-        postnode := server.GetNode(network)
-        cfg, err := config.ReadConfig(network)
-        if err != nil {
-                return err
-        }
-        servercfg := cfg.Server
-        var header metadata.MD
+func Push(network string) error {
+	postnode := config.GetNode(network)
+	cfg, err := config.ReadConfig(network)
+	if err != nil {
+		return err
+	}
+	servercfg := cfg.Server
+	var header metadata.MD
 
-        var wcclient nodepb.NodeServiceClient
-        var requestOpts grpc.DialOption
-        requestOpts = grpc.WithInsecure()
-        if cfg.Server.GRPCSSL == "on" {
-                h2creds := credentials.NewTLS(&tls.Config{NextProtos: []string{"h2"}})
-                requestOpts = grpc.WithTransportCredentials(h2creds)
-        }
-        conn, err := grpc.Dial(servercfg.GRPCAddress, requestOpts)
-        if err != nil {
-                log.Println("Cant dial GRPC server: %v", err)
-                return err
-        }
-        wcclient = nodepb.NewNodeServiceClient(conn)
+	var wcclient nodepb.NodeServiceClient
+	var requestOpts grpc.DialOption
+	requestOpts = grpc.WithInsecure()
+	if cfg.Server.GRPCSSL == "on" {
+		h2creds := credentials.NewTLS(&tls.Config{NextProtos: []string{"h2"}})
+		requestOpts = grpc.WithTransportCredentials(h2creds)
+	}
+	conn, err := grpc.Dial(servercfg.GRPCAddress, requestOpts)
+	if err != nil {
+		log.Println("Cant dial GRPC server:", err)
+		return err
+	}
+	wcclient = nodepb.NewNodeServiceClient(conn)
 
-        ctx := context.Background()
-        ctx, err = auth.SetJWT(wcclient, network)
-        if err != nil {
-                log.Println("Failed to authenticate: %v", err)
-                return err
-        }
+	ctx, err := auth.SetJWT(wcclient, network)
+	if err != nil {
+		log.Println("Failed to authenticate:", err)
+		return err
+	}
+	nodeData, err := json.Marshal(&postnode)
+	if err != nil {
+		return err
+	}
 
-        req := &nodepb.UpdateNodeReq{
-                       Node: &postnode,
-                }
-        _, err = wcclient.UpdateNode(ctx, req, grpc.Header(&header))
-        return err
+	req := &nodepb.Object{
+		Data:     string(nodeData),
+		Type:     nodepb.NODE_TYPE,
+		Metadata: "",
+	}
+	data, err := wcclient.UpdateNode(ctx, req, grpc.Header(&header))
+	if err != nil {
+		return err
+	}
+	err = json.Unmarshal([]byte(data.Data), &postnode)
+	if err != nil {
+		return err
+	}
+	err = config.ModConfig(&postnode)
+	return err
 }

+ 210 - 239
netclient/functions/common.go

@@ -1,66 +1,68 @@
 package functions
 
 import (
-        "google.golang.org/grpc/credentials"
-        "crypto/tls"
-	"fmt"
+	"context"
+	"crypto/tls"
 	"encoding/json"
 	"errors"
-	"context"
-        "net/http"
-        "io/ioutil"
-	"strings"
+	"fmt"
+	"io/ioutil"
 	"log"
 	"net"
+	"net/http"
 	"os"
 	"os/exec"
-        "github.com/gravitl/netmaker/netclient/config"
-        "github.com/gravitl/netmaker/netclient/local"
-        "github.com/gravitl/netmaker/netclient/auth"
-        nodepb "github.com/gravitl/netmaker/grpc"
+	"strings"
+
+	nodepb "github.com/gravitl/netmaker/grpc"
+	"github.com/gravitl/netmaker/models"
+	"github.com/gravitl/netmaker/netclient/auth"
+	"github.com/gravitl/netmaker/netclient/config"
+	"github.com/gravitl/netmaker/netclient/local"
 	"golang.zx2c4.com/wireguard/wgctrl"
-        "google.golang.org/grpc"
+	"google.golang.org/grpc"
+	"google.golang.org/grpc/credentials"
 	"google.golang.org/grpc/metadata"
 	//homedir "github.com/mitchellh/go-homedir"
 )
 
 var (
-        wcclient nodepb.NodeServiceClient
+	wcclient nodepb.NodeServiceClient
 )
 
-func ListPorts() error{
+func ListPorts() error {
 	wgclient, err := wgctrl.New()
-	if err  != nil {
+	if err != nil {
 		return err
 	}
 	devices, err := wgclient.Devices()
-        if err  != nil {
-                return err
-        }
+	if err != nil {
+		return err
+	}
 	fmt.Println("Here are your ports:")
-	 for _, i := range devices {
+	for _, i := range devices {
 		fmt.Println(i.ListenPort)
 	}
 	return err
 }
 
-func GetFreePort(rangestart int32) (int32, error){
-        wgclient, err := wgctrl.New()
-        if err  != nil {
-                return 0, err
-        }
-        devices, err := wgclient.Devices()
-        if err  != nil {
-                return 0, err
-        }
+func GetFreePort(rangestart int32) (int32, error) {
+	wgclient, err := wgctrl.New()
+	if err != nil {
+		return 0, err
+	}
+	devices, err := wgclient.Devices()
+	if err != nil {
+		return 0, err
+	}
 	var portno int32
 	portno = 0
-	for  x := rangestart; x <= 60000; x++ {
+	for x := rangestart; x <= 60000; x++ {
 		conflict := false
 		for _, i := range devices {
 			if int32(i.ListenPort) == x {
 				conflict = true
-				break;
+				break
 			}
 		}
 		if conflict {
@@ -69,49 +71,49 @@ func GetFreePort(rangestart int32) (int32, error){
 		portno = x
 		break
 	}
-        return portno, err
+	return portno, err
 }
 
 func getLocalIP(localrange string) (string, error) {
 	_, localRange, err := net.ParseCIDR(localrange)
-        if err != nil {
-                return "", err
-        }
+	if err != nil {
+		return "", err
+	}
 	ifaces, err := net.Interfaces()
-        if err != nil {
+	if err != nil {
 		return "", err
-        }
-        var local string
-        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 "", err
-        }
-        for _, addr := range addrs {
-                var ip net.IP
-                switch v := addr.(type) {
-                case *net.IPNet:
-			if !found {
-				 ip = v.IP
-                                 local = ip.String()
-                                 found = localRange.Contains(ip)
-                        }
-		case *net.IPAddr:
-			if !found {
-				ip = v.IP
-                                local = ip.String()
-                                found = localRange.Contains(ip)
-                        }
-                }
-        }
-        }
+	}
+	var local string
+	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 "", err
+		}
+		for _, addr := range addrs {
+			var ip net.IP
+			switch v := addr.(type) {
+			case *net.IPNet:
+				if !found {
+					ip = v.IP
+					local = ip.String()
+					found = localRange.Contains(ip)
+				}
+			case *net.IPAddr:
+				if !found {
+					ip = v.IP
+					local = ip.String()
+					found = localRange.Contains(ip)
+				}
+			}
+		}
+	}
 	if !found || local == "" {
 		return "", errors.New("Failed to find local IP in range " + localrange)
 	}
@@ -120,10 +122,10 @@ func getLocalIP(localrange string) (string, error) {
 
 func getPublicIP() (string, error) {
 
-	iplist := []string{"http://ip.client.gravitl.com","https://ifconfig.me", "http://api.ipify.org", "http://ipinfo.io/ip"}
+	iplist := []string{"http://ip.client.gravitl.com", "https://ifconfig.me", "http://api.ipify.org", "http://ipinfo.io/ip"}
 	endpoint := ""
 	var err error
-	    for _, ipserver := range iplist {
+	for _, ipserver := range iplist {
 		resp, err := http.Get(ipserver)
 		if err != nil {
 			continue
@@ -140,125 +142,97 @@ func getPublicIP() (string, error) {
 
 	}
 	if err == nil && endpoint == "" {
-		err =  errors.New("Public Address Not Found.")
+		err = errors.New("Public Address Not Found.")
 	}
 	return endpoint, err
 }
 
 func getMacAddr() ([]string, error) {
-    ifas, err := net.Interfaces()
-    if err != nil {
-        return nil, err
-    }
-    var as []string
-    for _, ifa := range ifas {
-        a := ifa.HardwareAddr.String()
-        if a != "" {
-            as = append(as, a)
-        }
-    }
-    return as, nil
+	ifas, err := net.Interfaces()
+	if err != nil {
+		return nil, err
+	}
+	var as []string
+	for _, ifa := range ifas {
+		a := ifa.HardwareAddr.String()
+		if a != "" {
+			as = append(as, a)
+		}
+	}
+	return as, nil
 }
 
 func getPrivateAddr() (string, error) {
-                ifaces, err := net.Interfaces()
-                if err != nil {
-                        return "", err
-                }
-                var local string
-                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 "", err
-                        }
-                        for _, addr := range addrs {
-                                var ip net.IP
-                                switch v := addr.(type) {
-                                case *net.IPNet:
-                                        if !found {
-                                                ip = v.IP
-                                                local = ip.String()
-                                                found = true
-                                        }
-                                case *net.IPAddr:
-                                        if  !found {
-                                                ip = v.IP
-                                                local = ip.String()
-                                                found = true
-                                        }
-                                }
-                        }
-                }
-		if !found {
-			err := errors.New("Local Address Not Found.")
+	ifaces, err := net.Interfaces()
+	if err != nil {
+		return "", err
+	}
+	var local string
+	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 "", err
 		}
-		return local, err
+		for _, addr := range addrs {
+			var ip net.IP
+			switch v := addr.(type) {
+			case *net.IPNet:
+				if !found {
+					ip = v.IP
+					local = ip.String()
+					found = true
+				}
+			case *net.IPAddr:
+				if !found {
+					ip = v.IP
+					local = ip.String()
+					found = true
+				}
+			}
+		}
+	}
+	if !found {
+		err := errors.New("Local Address Not Found.")
+		return "", err
+	}
+	return local, err
 }
 
 func needInterfaceUpdate(ctx context.Context, mac string, network string, iface string) (bool, string, error) {
-                var header metadata.MD
-		req := &nodepb.ReadNodeReq{
-                        Macaddress: mac,
-                        Network: network,
-                }
-                readres, err := wcclient.ReadNode(ctx, req, grpc.Header(&header))
-                if err != nil {
-                        return false, "", err
-                        log.Fatalf("Error: %v", err)
-                }
-		oldiface := readres.Node.Interface
+	var header metadata.MD
+	req := &nodepb.Object{
+		Data: mac + "###" + network,
+		Type: nodepb.STRING_TYPE,
+	}
+	readres, err := wcclient.ReadNode(ctx, req, grpc.Header(&header))
+	if err != nil {
+		return false, "", err
+		log.Fatalf("Error: %v", err)
+	}
+	var resNode models.Node
+	if err := json.Unmarshal([]byte(readres.Data), &resNode); err != nil {
+		return false, iface, err
+	}
+	oldiface := resNode.Interface
 
-		return iface != oldiface, oldiface, err
+	return iface != oldiface, oldiface, err
 }
 
-func GetNode(network string) nodepb.Node {
+func GetNode(network string) models.Node {
 
-        modcfg, err := config.ReadConfig(network)
-        if err != nil {
-                log.Fatalf("Error: %v", err)
-        }
-
-	nodecfg := modcfg.Node
-	var node nodepb.Node
+	modcfg, err := config.ReadConfig(network)
+	if err != nil {
+		log.Fatalf("Error: %v", err)
+	}
 
-	node.Name = nodecfg.Name
-	node.Interface = nodecfg.Interface
-	node.Nodenetwork = nodecfg.Network
-	node.Localaddress = nodecfg.LocalAddress
-	node.Address = nodecfg.WGAddress
-	node.Address6 = nodecfg.WGAddress6
-	node.Listenport = nodecfg.Port
-	node.Keepalive = nodecfg.KeepAlive
-	node.Postup = nodecfg.PostUp
-	node.Postdown = nodecfg.PostDown
-	node.Publickey = nodecfg.PublicKey
-	node.Macaddress = nodecfg.MacAddress
-	node.Endpoint = nodecfg.Endpoint
-	node.Password = nodecfg.Password
-        if nodecfg.DNS == "on" {
-                node.Dnsoff = true
-        } else {
-                node.Dnsoff = false
-        }
-	if nodecfg.IsDualStack == "yes" {
-		node.Isdualstack = true
-	} else {
-		node.Isdualstack = false
-	}
-        if nodecfg.IsIngressGateway == "yes" {
-                node.Isingressgateway = true
-        } else {
-                node.Isingressgateway = false
-        }
-        return node
+	return modcfg.Node
 }
 
 func Uninstall() error {
@@ -270,7 +244,7 @@ func Uninstall() error {
 		for _, network := range networks {
 			err = LeaveNetwork(network)
 			if err != nil {
-				log.Println("Encounter issue leaving network " + network + ": ", err)
+				log.Println("Encounter issue leaving network "+network+": ", err)
 			}
 		}
 	}
@@ -278,40 +252,40 @@ func Uninstall() error {
 }
 
 func LeaveNetwork(network string) error {
-        //need to  implement checkin on server side
-        cfg, err := config.ReadConfig(network)
-        if err != nil {
-                return err
-        }
+	//need to  implement checkin on server side
+	cfg, err := config.ReadConfig(network)
+	if err != nil {
+		return err
+	}
 	servercfg := cfg.Server
-        node := cfg.Node
+	node := cfg.Node
 
-        var wcclient nodepb.NodeServiceClient
-        var requestOpts grpc.DialOption
-        requestOpts = grpc.WithInsecure()
-        if cfg.Server.GRPCSSL == "on" {
-                h2creds := credentials.NewTLS(&tls.Config{NextProtos: []string{"h2"}})
-                requestOpts = grpc.WithTransportCredentials(h2creds)
-        }
-        conn, err := grpc.Dial(servercfg.GRPCAddress, requestOpts)
+	var wcclient nodepb.NodeServiceClient
+	var requestOpts grpc.DialOption
+	requestOpts = grpc.WithInsecure()
+	if cfg.Server.GRPCSSL == "on" {
+		h2creds := credentials.NewTLS(&tls.Config{NextProtos: []string{"h2"}})
+		requestOpts = grpc.WithTransportCredentials(h2creds)
+	}
+	conn, err := grpc.Dial(servercfg.GRPCAddress, requestOpts)
 	if err != nil {
-                log.Printf("Unable to establish client connection to " + servercfg.GRPCAddress + ": %v", err)
-        }else {
+		log.Printf("Unable to establish client connection to "+servercfg.GRPCAddress+": %v", err)
+	} else {
 		wcclient = nodepb.NewNodeServiceClient(conn)
 
 		ctx := context.Background()
 		ctx, err = auth.SetJWT(wcclient, network)
 		if err != nil {
-                log.Printf("Failed to authenticate: %v", err)
+			log.Printf("Failed to authenticate: %v", err)
 		} else {
 			var header metadata.MD
 			_, err = wcclient.DeleteNode(
-			ctx,
-			&nodepb.DeleteNodeReq{
-				Macaddress: node.MacAddress,
-				NetworkName: node.Network,
-			},
-			grpc.Header(&header),
+				ctx,
+				&nodepb.Object{
+					Data: node.ID,
+					Type: nodepb.STRING_TYPE,
+				},
+				grpc.Header(&header),
 			)
 			if err != nil {
 				log.Printf("Encountered error deleting node: %v", err)
@@ -323,41 +297,40 @@ func LeaveNetwork(network string) error {
 	}
 	err = local.WipeLocal(network)
 	if err != nil {
-                log.Printf("Unable to wipe local config: %v", err)
+		log.Printf("Unable to wipe local config: %v", err)
 	} else {
 		log.Println("Removed " + node.Network + " network locally")
 	}
 	if cfg.Daemon != "off" {
-		err =  local.RemoveSystemDServices(network)
+		err = local.RemoveSystemDServices(network)
 	}
 	return err
 }
 
-func DeleteInterface(ifacename string, postdown string) error{
-        ipExec, err := exec.LookPath("ip")
+func DeleteInterface(ifacename string, postdown string) error {
+	ipExec, err := exec.LookPath("ip")
 
-        cmdIPLinkDel := &exec.Cmd {
-                Path: ipExec,
-                Args: []string{ ipExec, "link", "del", ifacename },
-                Stdout: os.Stdout,
-                Stderr: os.Stdout,
-        }
-        err = cmdIPLinkDel.Run()
-        if  err  !=  nil {
-                log.Println(err)
-        }
-        if postdown != "" {
-                runcmds := strings.Split(postdown, "; ")
-                err = local.RunCmds(runcmds)
-                if err != nil {
-                        log.Println("Error encountered running PostDown: " + err.Error())
-                }
-        }
-        return err
+	cmdIPLinkDel := &exec.Cmd{
+		Path:   ipExec,
+		Args:   []string{ipExec, "link", "del", ifacename},
+		Stdout: os.Stdout,
+		Stderr: os.Stdout,
+	}
+	err = cmdIPLinkDel.Run()
+	if err != nil {
+		log.Println(err)
+	}
+	if postdown != "" {
+		runcmds := strings.Split(postdown, "; ")
+		err = local.RunCmds(runcmds)
+		if err != nil {
+			log.Println("Error encountered running PostDown: " + err.Error())
+		}
+	}
+	return err
 }
 
-
-func List() error{
+func List() error {
 
 	networks, err := GetNetworks()
 	if err != nil {
@@ -366,36 +339,34 @@ func List() error{
 	for _, network := range networks {
 		cfg, err := config.ReadConfig(network)
 		if err == nil {
-			//cfg2 := *cfg
-			listconfig := &config.ListConfig{
-					Name: cfg.Node.Name,
-					Interface: cfg.Node.Interface,
-					PrivateIPv4: cfg.Node.WGAddress,
-					PrivateIPv6: cfg.Node.WGAddress6,
-					PublicEndpoint: cfg.Node.Endpoint,
-				}
-			jsoncfg, _ := json.Marshal(listconfig)
+			jsoncfg, _ := json.Marshal(
+				map[string]string{
+					"Name":           cfg.Node.Name,
+					"Interface":      cfg.Node.Interface,
+					"PrivateIPv4":    cfg.Node.Address,
+					"PrivateIPv6":    cfg.Node.Address6,
+					"PublicEndpoint": cfg.Node.Endpoint,
+				})
 			log.Println(network + ": " + string(jsoncfg))
 		} else {
 			log.Println(network + ": Could not retrieve network configuration.")
 		}
 	}
 	return nil
-
 }
 
 func GetNetworks() ([]string, error) {
-        var networks []string
-        files, err := ioutil.ReadDir("/etc/netclient")
-        if err != nil {
-                return networks, err
-        }
-        for _, f := range files {
-                if strings.Contains(f.Name(), "netconfig-") && !strings.Contains(f.Name(), "global-001"){
-                        networkname := stringAfter(f.Name(), "netconfig-")
-                        networks = append(networks, networkname)
-                }
-        }
+	var networks []string
+	files, err := ioutil.ReadDir("/etc/netclient")
+	if err != nil {
+		return networks, err
+	}
+	for _, f := range files {
+		if strings.Contains(f.Name(), "netconfig-") && !strings.Contains(f.Name(), "global-001") {
+			networkname := stringAfter(f.Name(), "netconfig-")
+			networks = append(networks, networkname)
+		}
+	}
 	return networks, err
 }
 

+ 48 - 39
netclient/functions/join.go

@@ -3,6 +3,7 @@ package functions
 import (
 	"context"
 	"crypto/tls"
+	"encoding/json"
 	"errors"
 	"fmt"
 	"log"
@@ -11,6 +12,8 @@ import (
 	"time"
 
 	nodepb "github.com/gravitl/netmaker/grpc"
+	"github.com/gravitl/netmaker/models"
+	"github.com/gravitl/netmaker/netclient/auth"
 	"github.com/gravitl/netmaker/netclient/config"
 	"github.com/gravitl/netmaker/netclient/local"
 	"github.com/gravitl/netmaker/netclient/server"
@@ -22,7 +25,7 @@ import (
 	//homedir "github.com/mitchellh/go-homedir"
 )
 
-func JoinNetwork(cfg config.ClientConfig) error {
+func JoinNetwork(cfg config.ClientConfig, privateKey string) error {
 
 	hasnet := local.HasNetwork(cfg.Network)
 	if hasnet {
@@ -100,12 +103,12 @@ func JoinNetwork(cfg config.ClientConfig) error {
 	}
 	if cfg.Node.Password == "" {
 		cfg.Node.Password = GenPass()
+		auth.StoreSecret(cfg.Node.Password, cfg.Node.Network)
 	}
 	if cfg.Node.Endpoint == "" {
 		if cfg.Node.IsLocal == "yes" && cfg.Node.LocalAddress != "" {
 			cfg.Node.Endpoint = cfg.Node.LocalAddress
 		} else {
-
 			cfg.Node.Endpoint, err = getPublicIP()
 			if err != nil {
 				fmt.Println("Error setting cfg.Node.Endpoint.")
@@ -115,13 +118,13 @@ func JoinNetwork(cfg config.ClientConfig) error {
 	} else {
 		cfg.Node.Endpoint = cfg.Node.Endpoint
 	}
-	if cfg.Node.PrivateKey == "" {
-		privatekey, err := wgtypes.GeneratePrivateKey()
+	if privateKey == "" {
+		wgPrivatekey, err := wgtypes.GeneratePrivateKey()
 		if err != nil {
 			log.Fatal(err)
 		}
-		cfg.Node.PrivateKey = privatekey.String()
-		cfg.Node.PublicKey = privatekey.PublicKey().String()
+		privateKey = wgPrivatekey.String()
+		cfg.Node.PublicKey = wgPrivatekey.PublicKey().String()
 	}
 
 	if cfg.Node.MacAddress == "" {
@@ -134,8 +137,8 @@ func JoinNetwork(cfg config.ClientConfig) error {
 			cfg.Node.MacAddress = macs[0]
 		}
 	}
-	if cfg.Node.Port == 0 {
-		cfg.Node.Port, err = GetFreePort(51821)
+	if cfg.Node.ListenPort == 0 {
+		cfg.Node.ListenPort, err = GetFreePort(51821)
 		if err != nil {
 			fmt.Printf("Error retrieving port: %v", err)
 		}
@@ -155,59 +158,65 @@ func JoinNetwork(cfg config.ClientConfig) error {
 
 	wcclient = nodepb.NewNodeServiceClient(conn)
 
-	postnode := &nodepb.Node{
-		Password:     cfg.Node.Password,
-		Macaddress:   cfg.Node.MacAddress,
-		Accesskey:    cfg.Server.AccessKey,
-		Nodenetwork:  cfg.Network,
-		Listenport:   cfg.Node.Port,
-		Postup:       cfg.Node.PostUp,
-		Postdown:     cfg.Node.PostDown,
-		Keepalive:    cfg.Node.KeepAlive,
-		Localaddress: cfg.Node.LocalAddress,
-		Interface:    cfg.Node.Interface,
-		Publickey:    cfg.Node.PublicKey,
-		Name:         cfg.Node.Name,
-		Endpoint:     cfg.Node.Endpoint,
-		Saveconfig:     cfg.Node.SaveConfig,
-		Udpholepunch:     cfg.Node.UDPHolePunch,
+	postnode := &models.Node{
+		Password:            cfg.Node.Password,
+		MacAddress:          cfg.Node.MacAddress,
+		AccessKey:           cfg.Server.AccessKey,
+		Network:             cfg.Network,
+		ListenPort:          cfg.Node.ListenPort,
+		PostUp:              cfg.Node.PostUp,
+		PostDown:            cfg.Node.PostDown,
+		PersistentKeepalive: cfg.Node.PersistentKeepalive,
+		LocalAddress:        cfg.Node.LocalAddress,
+		Interface:           cfg.Node.Interface,
+		PublicKey:           cfg.Node.PublicKey,
+		Name:                cfg.Node.Name,
+		Endpoint:            cfg.Node.Endpoint,
+		SaveConfig:          cfg.Node.SaveConfig,
+		UDPHolePunch:        cfg.Node.UDPHolePunch,
+	}
+	if err = config.ModConfig(postnode); err != nil {
+		return err
 	}
-	err = config.ModConfig(postnode)
+	data, err := json.Marshal(&postnode)
 	if err != nil {
 		return err
 	}
 
 	res, err := wcclient.CreateNode(
 		context.TODO(),
-		&nodepb.CreateNodeReq{
-			Node: postnode,
+		&nodepb.Object{
+			Data: string(data),
+			Type: nodepb.NODE_TYPE,
 		},
 	)
 	if err != nil {
 		return err
 	}
 	log.Println("node created on remote server...updating configs")
-	node := res.Node
-	if err != nil {
+
+	nodeData := res.Data
+	var node models.Node
+	if err = json.Unmarshal([]byte(nodeData), &node); err != nil {
 		return err
 	}
 
-	if node.Dnsoff == true {
-		cfg.Node.DNS = "yes"
+	if node.DNSOn == "yes" {
+		cfg.Node.DNSOn = "yes"
 	}
-	if !(cfg.Node.IsLocal == "yes") && node.Islocal && node.Localrange != "" {
-		node.Localaddress, err = getLocalIP(node.Localrange)
+	if !(cfg.Node.IsLocal == "yes") && node.IsLocal == "yes" && node.LocalRange != "" {
+		node.LocalAddress, err = getLocalIP(node.LocalRange)
 		if err != nil {
 			return err
 		}
-		node.Endpoint = node.Localaddress
+		node.Endpoint = node.LocalAddress
 	}
-	err = config.ModConfig(node)
+	err = config.ModConfig(&node)
 	if err != nil {
 		return err
 	}
 
-	if node.Ispending {
+	if node.IsPending == "yes" {
 		fmt.Println("Node is marked as PENDING.")
 		fmt.Println("Awaiting approval from Admin before configuring WireGuard.")
 		if cfg.Daemon != "off" {
@@ -216,18 +225,18 @@ func JoinNetwork(cfg config.ClientConfig) error {
 		}
 	}
 	log.Println("retrieving remote peers")
-	peers, hasGateway, gateways, err := server.GetPeers(node.Macaddress, cfg.Network, cfg.Server.GRPCAddress, node.Isdualstack, node.Isingressgateway)
+	peers, hasGateway, gateways, err := server.GetPeers(node.MacAddress, cfg.Network, cfg.Server.GRPCAddress, node.IsDualStack == "yes", node.IsIngressGateway == "yes")
 
 	if err != nil {
 		log.Println("failed to retrieve peers")
 		return err
 	}
-	err = wireguard.StorePrivKey(cfg.Node.PrivateKey, cfg.Network)
+	err = wireguard.StorePrivKey(privateKey, cfg.Network)
 	if err != nil {
 		return err
 	}
 	log.Println("starting wireguard")
-	err = wireguard.InitWireguard(node, cfg.Node.PrivateKey, peers, hasGateway, gateways)
+	err = wireguard.InitWireguard(&node, privateKey, peers, hasGateway, gateways)
 	if err != nil {
 		return err
 	}

+ 44 - 44
netclient/local/dns.go

@@ -4,56 +4,56 @@ import (
 	"io/ioutil"
 	"os"
 	"strings"
+
 	//"github.com/davecgh/go-spew/spew"
-        "log"
-        "os/exec"
+	"log"
+	"os/exec"
 )
 
 func SetDNS(nameserver string) error {
-        bytes, err := ioutil.ReadFile("/etc/resolv.conf")
-        if err != nil {
-                return err
-        }
-        resolvstring := string(bytes)
-        // //check whether s contains substring text
-        hasdns := strings.Contains(resolvstring, nameserver)
-        if hasdns {
-                return nil
-        }
-        resolv, err := os.OpenFile("/etc/resolv.conf",os.O_APPEND|os.O_WRONLY, 0644)
-        if err != nil {
-                return err
-        }
-        defer resolv.Close()
-        _, err = resolv.WriteString("nameserver " + nameserver + "\n")
+	bytes, err := ioutil.ReadFile("/etc/resolv.conf")
+	if err != nil {
+		return err
+	}
+	resolvstring := string(bytes)
+	// //check whether s contains substring text
+	hasdns := strings.Contains(resolvstring, nameserver)
+	if hasdns {
+		return nil
+	}
+	resolv, err := os.OpenFile("/etc/resolv.conf", os.O_APPEND|os.O_WRONLY, 0644)
+	if err != nil {
+		return err
+	}
+	defer resolv.Close()
+	_, err = resolv.WriteString("nameserver " + nameserver + "\n")
 
-        return err
+	return err
 }
 
-
 func UpdateDNS(ifacename string, network string, nameserver string) error {
-                _, err := exec.LookPath("resolvectl")
-                if err != nil {
-                        log.Println(err)
-                        log.Println("WARNING: resolvectl not present. Unable to set dns. Install resolvectl or run manually.")
-                } else {
-                        _, err = exec.Command("resolvectl", "domain", ifacename, "~"+network).Output()
-                        if err != nil {
-                                log.Println(err)
-                                log.Println("WARNING: Error encountered setting domain on dns. Aborted setting dns.")
-                        } else {
-                                _, err = exec.Command("resolvectl", "default-route", ifacename, "false").Output()
-                                if err != nil {
-                                        log.Println(err)
-                                        log.Println("WARNING: Error encountered setting default-route on dns. Aborted setting dns.")
-                                } else {
-                                        _, err = exec.Command("resolvectl", "dns", ifacename, nameserver).Output()
-                                        if err!= nil {
-						log.Println("WARNING: Error encountered running resolvectl dns " + ifacename + " " + nameserver)
-						log.Println(err)
-					}
-                                }
-                        }
-                }
-		return err
+	_, err := exec.LookPath("resolvectl")
+	if err != nil {
+		log.Println(err)
+		log.Println("WARNING: resolvectl not present. Unable to set dns. Install resolvectl or run manually.")
+	} else {
+		_, err = RunCmd("resolvectl domain " + ifacename + " ~" + network)
+		if err != nil {
+			log.Println(err)
+			log.Println("WARNING: Error encountered setting domain on dns. Aborted setting dns.")
+		} else {
+			_, err = RunCmd("resolvectl default-route " + ifacename + " false")
+			if err != nil {
+				log.Println(err)
+				log.Println("WARNING: Error encountered setting default-route on dns. Aborted setting dns.")
+			} else {
+				_, err = RunCmd("resolvectl dns " + ifacename + " " + nameserver)
+				if err != nil {
+					log.Println("WARNING: Error encountered running resolvectl dns " + ifacename + " " + nameserver)
+					log.Println(err)
+				}
+			}
+		}
+	}
+	return err
 }

+ 229 - 227
netclient/local/local.go

@@ -1,83 +1,122 @@
 package local
 
 import (
-        //"github.com/davecgh/go-spew/spew"
+	//"github.com/davecgh/go-spew/spew"
 	"errors"
-	"github.com/gravitl/netmaker/netclient/config"
+	"io"
+	"io/ioutil"
 	"log"
-        "io/ioutil"
+	"os"
+	"os/exec"
 	"path/filepath"
-        "io"
+	"runtime"
 	"strings"
-        "os"
-        "os/exec"
+
+	"github.com/gravitl/netmaker/netclient/config"
 )
 
+func SetIPForwarding() error {
+	os := runtime.GOOS
+	var err error
+	switch os {
+	case "linux":
+		err = SetIPForwardingLinux()
+	default:
+		err = errors.New("This OS is not supported")
+	}
+	return err
+}
+
+func SetIPForwardingLinux() error {
+	out, err := RunCmd("sysctl net.ipv4.ip_forward")
+	if err != nil {
+		log.Println(err)
+		log.Println("WARNING: Error encountered setting ip forwarding. This can break functionality.")
+		return err
+	} else {
+		s := strings.Fields(string(out))
+		if s[2] != "1" {
+			_, err = RunCmd("sysctl -w net.ipv4.ip_forward=1")
+			if err != nil {
+				log.Println(err)
+				log.Println("WARNING: Error encountered setting ip forwarding. You may want to investigate this.")
+				return err
+			}
+		}
+	}
+	return nil
+}
+
+func RunCmd(command string) (string, error) {
+	args := strings.Fields(command)
+	out, err := exec.Command(args[0], args[1:]...).Output()
+	return string(out), err
+}
+
 func RunCmds(commands []string) error {
-        var err error
-        for _, command := range commands {
-                args := strings.Fields(command)
-                out, err := exec.Command(args[0], args[1:]...).Output()
-                if string(out) != "" {
+	var err error
+	for _, command := range commands {
+		args := strings.Fields(command)
+		out, err := exec.Command(args[0], args[1:]...).Output()
+		if string(out) != "" {
 			log.Println(string(out))
 		}
-                if err != nil {
-                        return err
-                }
-        }
-        return err
+		if err != nil {
+			return err
+		}
+	}
+	return err
 }
 
 func FileExists(f string) bool {
-    info, err := os.Stat(f)
-    if os.IsNotExist(err) {
-        return false
-    }
-    return !info.IsDir()
+	info, err := os.Stat(f)
+	if os.IsNotExist(err) {
+		return false
+	}
+	return !info.IsDir()
 }
 
 func ConfigureSystemD(network string) error {
 	/*
-	path, err := os.Getwd()
-	if err != nil {
-		log.Println(err)
-		return err
-	}
+		path, err := os.Getwd()
+		if err != nil {
+			log.Println(err)
+			return err
+		}
 	*/
 	//binarypath := path  + "/netclient"
 	dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
 	if err != nil {
-            return err
+		return err
 	}
-	binarypath := dir  + "/netclient"
+	binarypath := dir + "/netclient"
 
 	_, err = os.Stat("/etc/netclient")
-        if os.IsNotExist(err) {
-                os.Mkdir("/etc/netclient", 744)
-        } else if err != nil {
-                log.Println("couldnt find or create /etc/netclient")
-                return err
-        }
-
-	if !FileExists("/usr/local/bin/netclient") {
-		os.Symlink("/etc/netclient/netclient","/usr/local/bin/netclient")
-	/*
-	_, err = copy(binarypath, "/usr/local/bin/netclient")
-	if err != nil {
-		log.Println(err)
+	if os.IsNotExist(err) {
+		os.Mkdir("/etc/netclient", 744)
+	} else if err != nil {
+		log.Println("couldnt find or create /etc/netclient")
 		return err
 	}
-	*/
+
+	if !FileExists("/usr/local/bin/netclient") {
+		os.Symlink("/etc/netclient/netclient", "/usr/local/bin/netclient")
+		/*
+			_, err = copy(binarypath, "/usr/local/bin/netclient")
+			if err != nil {
+				log.Println(err)
+				return err
+			}
+		*/
 	}
 	if !FileExists("/etc/netclient/netclient") {
-        _, err = copy(binarypath, "/etc/netclient/netclient")
-        if err != nil {
-                log.Println(err)
-                return err
-        }
+		_, err = copy(binarypath, "/etc/netclient/netclient")
+		if err != nil {
+			log.Println(err)
+			return err
+		}
 	}
 
-
 	systemservice := `[Unit]
 Description=network check for remote peers and local config
 Wants=netclient.timer
@@ -94,18 +133,18 @@ WantedBy=multi-user.target
 Description=Calls the Netmaker Mesh Client Service
 
 `
-systemtimer = systemtimer + "Requires=netclient@"+network+".service"
+	systemtimer = systemtimer + "Requires=netclient@" + network + ".service"
 
-systemtimer = systemtimer +
-`
+	systemtimer = systemtimer +
+		`
 
 [Timer]
 
 `
-systemtimer = systemtimer + "Unit=netclient@"+network+".service"
+	systemtimer = systemtimer + "Unit=netclient@" + network + ".service"
 
-systemtimer = systemtimer +
-`
+	systemtimer = systemtimer +
+		`
 
 OnCalendar=*:*:0/30
 
@@ -117,67 +156,41 @@ WantedBy=timers.target
 	timerbytes := []byte(systemtimer)
 
 	if !FileExists("/etc/systemd/system/[email protected]") {
-	err = ioutil.WriteFile("/etc/systemd/system/[email protected]", servicebytes, 0644)
-        if err != nil {
-                log.Println(err)
-                return err
-        }
-	}
-
-        if !FileExists("/etc/systemd/system/netclient-"+network+".timer") {
-        err = ioutil.WriteFile("/etc/systemd/system/netclient-"+network+".timer", timerbytes, 0644)
-        if err != nil {
-                log.Println(err)
-                return err
-        }
-	}
-        //sysExec, err := exec.LookPath("systemctl")
-
-        cmdSysEnableService := exec.Command("systemctl", "enable", "[email protected]")/*&exec.Cmd {
-                Path: sysExec,
-                Args: []string{ sysExec, "enable", "[email protected]" },
-                Stdout: os.Stdout,
-                Stderr: os.Stdout,
-        }*/
-        cmdSysDaemonReload := exec.Command("systemctl", "daemon-reload")/*&exec.Cmd {
-                Path: sysExec,
-                Args: []string{ sysExec, "daemon-reload"},
-                Stdout: os.Stdout,
-                Stderr: os.Stdout,
-        }*/
-        cmdSysEnableTimer := exec.Command("systemctl", "enable", "netclient-"+network+".timer")/*&exec.Cmd {
-                Path: sysExec,
-                Args: []string{ sysExec, "enable", "netclient-"+network+".timer" },
-                Stdout: os.Stdout,
-                Stderr: os.Stdout,
-        }*/
-        cmdSysStartTimer := exec.Command("systemctl", "start", "netclient-"+network+".timer")/*&exec.Cmd {
-                Path: sysExec,
-		Args: []string{ sysExec, "start", "netclient-"+network+".timer"},
-                Stdout: os.Stdout,
-                Stderr: os.Stdout,
-        }*/
-
-        err = cmdSysEnableService.Run()
-        if  err  !=  nil {
-                log.Println("Error enabling [email protected]. Please investigate.")
-                log.Println(err)
-        }
-        err = cmdSysDaemonReload.Run()
-        if  err  !=  nil {
-                log.Println("Error reloading system daemons. Please investigate.")
-                log.Println(err)
-        }
-        err = cmdSysEnableTimer.Run()
-        if  err  !=  nil {
-                log.Println("Error enabling netclient.timer. Please investigate.")
-                log.Println(err)
-        }
-        err = cmdSysStartTimer.Run()
-        if  err  !=  nil {
-                log.Println("Error starting netclient-"+network+".timer. Please investigate.")
-                log.Println(err)
-        }
+		err = ioutil.WriteFile("/etc/systemd/system/[email protected]", servicebytes, 0644)
+		if err != nil {
+			log.Println(err)
+			return err
+		}
+	}
+
+	if !FileExists("/etc/systemd/system/netclient-" + network + ".timer") {
+		err = ioutil.WriteFile("/etc/systemd/system/netclient-"+network+".timer", timerbytes, 0644)
+		if err != nil {
+			log.Println(err)
+			return err
+		}
+	}
+
+	_, err = RunCmd("systemctl enable [email protected]")
+	if err != nil {
+		log.Println("Error enabling [email protected]. Please investigate.")
+		log.Println(err)
+	}
+	_, err = RunCmd("systemctl daemon-reload")
+	if err != nil {
+		log.Println("Error reloading system daemons. Please investigate.")
+		log.Println(err)
+	}
+	_, err = RunCmd("systemctl enable netclient-" + network + ".timer")
+	if err != nil {
+		log.Println("Error enabling netclient.timer. Please investigate.")
+		log.Println(err)
+	}
+	_, err = RunCmd("systemctl start netclient-" + network + ".timer")
+	if err != nil {
+		log.Println("Error starting netclient-" + network + ".timer. Please investigate.")
+		log.Println(err)
+	}
 	return nil
 }
 
@@ -188,7 +201,7 @@ func isOnlyService(network string) (bool, error) {
 		return isonly, err
 	}
 	count := len(files)
-	if count  == 0 {
+	if count == 0 {
 		isonly = true
 	}
 	return isonly, err
@@ -196,78 +209,67 @@ func isOnlyService(network string) (bool, error) {
 }
 
 func RemoveSystemDServices(network string) error {
-        //sysExec, err := exec.LookPath("systemctl")
-
+	//sysExec, err := exec.LookPath("systemctl")
 
 	fullremove, err := isOnlyService(network)
 	if err != nil {
 		log.Println(err)
 	}
 
-	cmdSysDisableService := exec.Command("systemctl","disable","[email protected]")
-        cmdSysDaemonReload := exec.Command("systemctl","daemon-reload")
-        cmdSysResetFailed := exec.Command("systemctl","reset-failed")
-        cmdSysStopTimer := exec.Command("systemctl", "stop", "netclient-"+network+".timer")
-        cmdSysDisableTimer :=  exec.Command("systemctl", "disable", "netclient-"+network+".timer")
-        if  err  !=  nil {
-                log.Println("Error stopping [email protected]. Please investigate.")
-                log.Println(err)
-        }
 	if fullremove {
-        err = cmdSysDisableService.Run()
-        if  err  !=  nil {
-                log.Println("Error disabling [email protected]. Please investigate.")
-                log.Println(err)
-        }
-	}
-        err = cmdSysStopTimer.Run()
-        if  err  !=  nil {
-                log.Println("Error stopping netclient-"+network+".timer. Please investigate.")
-                log.Println(err)
-        }
-        err = cmdSysDisableTimer.Run()
-        if  err  !=  nil {
-                log.Println("Error disabling netclient-"+network+".timer. Please investigate.")
-                log.Println(err)
-        }
+		_, err = RunCmd("systemctl disable [email protected]")
+		if err != nil {
+			log.Println("Error disabling [email protected]. Please investigate.")
+			log.Println(err)
+		}
+	}
+	_, err = RunCmd("systemctl daemon-reload")
+	if err != nil {
+		log.Println("Error stopping netclient-" + network + ".timer. Please investigate.")
+		log.Println(err)
+	}
+	_, err = RunCmd("systemctl disable netclient-" + network + ".timer")
+	if err != nil {
+		log.Println("Error disabling netclient-" + network + ".timer. Please investigate.")
+		log.Println(err)
+	}
 	if fullremove {
 		if FileExists("/etc/systemd/system/[email protected]") {
 			err = os.Remove("/etc/systemd/system/[email protected]")
 		}
 	}
-	if FileExists("/etc/systemd/system/netclient-"+network+".timer") {
-		err = os.Remove("/etc/systemd/system/netclient-"+network+".timer")
+	if FileExists("/etc/systemd/system/netclient-" + network + ".timer") {
+		err = os.Remove("/etc/systemd/system/netclient-" + network + ".timer")
+	}
+	if err != nil {
+		log.Println("Error removing file. Please investigate.")
+		log.Println(err)
+	}
+	_, err = RunCmd("systemctl daemon-reload")
+	if err != nil {
+		log.Println("Error reloading system daemons. Please investigate.")
+		log.Println(err)
 	}
+	_, err = RunCmd("systemctl reset-failed")
 	if err != nil {
-                log.Println("Error removing file. Please investigate.")
-                log.Println(err)
-	}
-        err = cmdSysDaemonReload.Run()
-        if  err  !=  nil {
-                log.Println("Error reloading system daemons. Please investigate.")
-                log.Println(err)
-        }
-        err = cmdSysResetFailed.Run()
-        if  err  !=  nil {
-                log.Println("Error reseting failed system services. Please investigate.")
-                log.Println(err)
-        }
+		log.Println("Error reseting failed system services. Please investigate.")
+		log.Println(err)
+	}
 	return err
-
 }
 
-func WipeLocal(network string) error{
-        cfg, err := config.ReadConfig(network)
-        if err != nil {
-                return err
-        }
-        nodecfg := cfg.Node
-        ifacename := nodecfg.Interface
+func WipeLocal(network string) error {
+	cfg, err := config.ReadConfig(network)
+	if err != nil {
+		return err
+	}
+	nodecfg := cfg.Node
+	ifacename := nodecfg.Interface
 
-        //home, err := homedir.Dir()
-        home := "/etc/netclient"
+	//home, err := homedir.Dir()
+	home := "/etc/netclient"
 	if FileExists(home + "/netconfig-" + network) {
-	        _ = os.Remove(home + "/netconfig-" + network)
+		_ = os.Remove(home + "/netconfig-" + network)
 	}
 	if FileExists(home + "/nettoken-" + network) {
 		_ = os.Remove(home + "/nettoken-" + network)
@@ -276,79 +278,79 @@ func WipeLocal(network string) error{
 		_ = os.Remove(home + "/wgkey-" + network)
 	}
 
-        ipExec, err := exec.LookPath("ip")
-
-        if ifacename != "" {
-        cmdIPLinkDel := &exec.Cmd {
-                Path: ipExec,
-                Args: []string{ ipExec, "link", "del", ifacename },
-                Stdout: os.Stdout,
-                Stderr: os.Stdout,
-        }
-        err = cmdIPLinkDel.Run()
-        if  err  !=  nil {
-                log.Println(err)
-        }
-        if nodecfg.PostDown != "" {
-                runcmds := strings.Split(nodecfg.PostDown, "; ")
-                err = RunCmds(runcmds)
-                if err != nil {
-                        log.Println("Error encountered running PostDown: " + err.Error())
-                }
-        }
-        }
-        return err
+	ipExec, err := exec.LookPath("ip")
+
+	if ifacename != "" {
+		cmdIPLinkDel := &exec.Cmd{
+			Path:   ipExec,
+			Args:   []string{ipExec, "link", "del", ifacename},
+			Stdout: os.Stdout,
+			Stderr: os.Stdout,
+		}
+		err = cmdIPLinkDel.Run()
+		if err != nil {
+			log.Println(err)
+		}
+		if nodecfg.PostDown != "" {
+			runcmds := strings.Split(nodecfg.PostDown, "; ")
+			err = RunCmds(runcmds)
+			if err != nil {
+				log.Println("Error encountered running PostDown: " + err.Error())
+			}
+		}
+	}
+	return err
 
 }
 
-func WipeGRPCClient() error{
-        home := "/etc/netclient"
-        _ = os.Remove(home + "/netconfig-global-001")
+func WipeGRPCClient() error {
+	home := "/etc/netclient"
+	_ = os.Remove(home + "/netconfig-global-001")
 
 	ipExec, err := exec.LookPath("ip")
 
-        cmdIPLinkDel := &exec.Cmd {
-                Path: ipExec,
-                Args: []string{ ipExec, "link", "del", "grpc-wg-001" },
-                Stdout: os.Stdout,
-                Stderr: os.Stdout,
-        }
-        err = cmdIPLinkDel.Run()
-        return err
+	cmdIPLinkDel := &exec.Cmd{
+		Path:   ipExec,
+		Args:   []string{ipExec, "link", "del", "grpc-wg-001"},
+		Stdout: os.Stdout,
+		Stderr: os.Stdout,
+	}
+	err = cmdIPLinkDel.Run()
+	return err
 }
 
-func HasNetwork(network string) bool{
+func HasNetwork(network string) bool {
 
-return  FileExists("/etc/systemd/system/netclient-"+network+".timer") ||
-	FileExists("/etc/netclient/netconfig-"+network)
+	return FileExists("/etc/systemd/system/netclient-"+network+".timer") ||
+		FileExists("/etc/netclient/netconfig-"+network)
 
 }
 
 func copy(src, dst string) (int64, error) {
-        sourceFileStat, err := os.Stat(src)
-        if err != nil {
-                return 0, err
-        }
-
-        if !sourceFileStat.Mode().IsRegular() {
-                return 0, errors.New(src + " is not a regular file")
-        }
-
-        source, err := os.Open(src)
-        if err != nil {
-                return 0, err
-        }
-        defer source.Close()
-
-        destination, err := os.Create(dst)
-        if err != nil {
-                return 0, err
-        }
-        defer destination.Close()
-        nBytes, err := io.Copy(destination, source)
+	sourceFileStat, err := os.Stat(src)
+	if err != nil {
+		return 0, err
+	}
+
+	if !sourceFileStat.Mode().IsRegular() {
+		return 0, errors.New(src + " is not a regular file")
+	}
+
+	source, err := os.Open(src)
+	if err != nil {
+		return 0, err
+	}
+	defer source.Close()
+
+	destination, err := os.Create(dst)
+	if err != nil {
+		return 0, err
+	}
+	defer destination.Close()
+	nBytes, err := io.Copy(destination, source)
 	err = os.Chmod(dst, 0755)
 	if err != nil {
 		log.Println(err)
 	}
-        return nBytes, err
+	return nBytes, err
 }

+ 9 - 30
netclient/main.go

@@ -9,6 +9,7 @@ import (
 
 	"github.com/gravitl/netmaker/netclient/command"
 	"github.com/gravitl/netmaker/netclient/config"
+	"github.com/gravitl/netmaker/netclient/local"
 	"github.com/urfave/cli/v2"
 )
 
@@ -202,33 +203,12 @@ func main() {
 	}
 
 	app.Commands = []*cli.Command{
-		{
-			Name:  "register",
-			Usage: "Register with Netmaker Server for secure GRPC communications.",
-			Flags: cliFlags,
-			Action: func(c *cli.Context) error {
-				cfg, err := config.GetCLIConfigRegister(c)
-				if err != nil {
-					return err
-				}
-				if cfg.GRPCWireGuard == "off" {
-					log.Println("Server is not using WireGuard to secure GRPC. Skipping.")
-					return err
-				}
-				if cfg.Client.ServerPrivateAddress == "" {
-					err = errors.New("No server address provided.")
-					return err
-				}
-				err = command.Register(cfg)
-				return err
-			},
-		},
 		{
 			Name:  "join",
 			Usage: "Join a Netmaker network.",
 			Flags: cliFlags,
 			Action: func(c *cli.Context) error {
-				cfg, err := config.GetCLIConfig(c)
+				cfg, pvtKey, err := config.GetCLIConfig(c)
 				if err != nil {
 					return err
 				}
@@ -240,7 +220,7 @@ func main() {
 					err = errors.New("No server address provided.")
 					return err
 				}
-				err = command.Join(cfg)
+				err = command.Join(cfg, pvtKey)
 				return err
 			},
 		},
@@ -251,7 +231,7 @@ func main() {
 			// the action, or code that will be executed when
 			// we execute our `ns` command
 			Action: func(c *cli.Context) error {
-				cfg, err := config.GetCLIConfig(c)
+				cfg, _, err := config.GetCLIConfig(c)
 				if err != nil {
 					return err
 				}
@@ -266,7 +246,7 @@ func main() {
 			// the action, or code that will be executed when
 			// we execute our `ns` command
 			Action: func(c *cli.Context) error {
-				cfg, err := config.GetCLIConfig(c)
+				cfg, _, err := config.GetCLIConfig(c)
 				if err != nil {
 					return err
 				}
@@ -281,7 +261,7 @@ func main() {
 			// the action, or code that will be executed when
 			// we execute our `ns` command
 			Action: func(c *cli.Context) error {
-				cfg, err := config.GetCLIConfig(c)
+				cfg, _, err := config.GetCLIConfig(c)
 				if err != nil {
 					return err
 				}
@@ -296,7 +276,7 @@ func main() {
 			// the action, or code that will be executed when
 			// we execute our `ns` command
 			Action: func(c *cli.Context) error {
-				cfg, err := config.GetCLIConfig(c)
+				cfg, _, err := config.GetCLIConfig(c)
 				if err != nil {
 					return err
 				}
@@ -311,7 +291,7 @@ func main() {
 			// the action, or code that will be executed when
 			// we execute our `ns` command
 			Action: func(c *cli.Context) error {
-				cfg, err := config.GetCLIConfig(c)
+				cfg, _, err := config.GetCLIConfig(c)
 				if err != nil {
 					return err
 				}
@@ -356,8 +336,7 @@ func main() {
 	}
 
 	// start our application
-	getID := exec.Command("id", "-u")
-	out, err := getID.Output()
+	out, err := local.RunCmd("id -u")
 
 	if err != nil {
 		log.Fatal(err)

+ 295 - 314
netclient/server/grpc.go

@@ -1,373 +1,354 @@
 package server
 
 import (
-	"google.golang.org/grpc/credentials"
-        "crypto/tls"
-	"fmt"
 	"context"
+	"crypto/tls"
+	"encoding/json"
+	"fmt"
 	"log"
-	"strings"
-	"strconv"
 	"net"
+	"strconv"
 	"time"
-	"io"
-        "golang.zx2c4.com/wireguard/wgctrl/wgtypes"
+
+	nodepb "github.com/gravitl/netmaker/grpc"
+	"github.com/gravitl/netmaker/models"
+	"github.com/gravitl/netmaker/netclient/auth"
 	"github.com/gravitl/netmaker/netclient/config"
-        "github.com/gravitl/netmaker/netclient/auth"
-        "github.com/gravitl/netmaker/netclient/local"
-        nodepb "github.com/gravitl/netmaker/grpc"
-        "google.golang.org/grpc"
+	"github.com/gravitl/netmaker/netclient/local"
+	"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
+	"google.golang.org/grpc"
+	"google.golang.org/grpc/credentials"
 	"google.golang.org/grpc/metadata"
 	//homedir "github.com/mitchellh/go-homedir"
 )
 
-func GetNode(network string) nodepb.Node {
-
-        modcfg, err := config.ReadConfig(network)
-        if err != nil {
-                log.Fatalf("Error: %v", err)
-        }
-
-	nodecfg := modcfg.Node
-	var node nodepb.Node
-
-	node.Name = nodecfg.Name
-	node.Interface = nodecfg.Interface
-	node.Nodenetwork = nodecfg.Network
-	node.Localaddress = nodecfg.LocalAddress
-	node.Address = nodecfg.WGAddress
-	node.Address6 = nodecfg.WGAddress6
-	node.Listenport = nodecfg.Port
-	node.Keepalive = nodecfg.KeepAlive
-	node.Postup = nodecfg.PostUp
-	node.Postdown = nodecfg.PostDown
-	node.Publickey = nodecfg.PublicKey
-	node.Macaddress = nodecfg.MacAddress
-	node.Endpoint = nodecfg.Endpoint
-	node.Password = nodecfg.Password
-	node.Saveconfig = nodecfg.SaveConfig
-	node.Udpholepunch = nodecfg.UDPHolePunch
-	if nodecfg.DNS == "on" {
-		node.Dnsoff = false
-	} else {
-		node.Dnsoff = true
+func getGrpcClient(cfg *config.ClientConfig) (nodepb.NodeServiceClient, error) {
+	servercfg := cfg.Server
+	var wcclient nodepb.NodeServiceClient
+	// == GRPC SETUP ==
+	var requestOpts grpc.DialOption
+	requestOpts = grpc.WithInsecure()
+	if cfg.Server.GRPCSSL == "on" {
+		h2creds := credentials.NewTLS(&tls.Config{NextProtos: []string{"h2"}})
+		requestOpts = grpc.WithTransportCredentials(h2creds)
+	}
+	conn, err := grpc.Dial(servercfg.GRPCAddress, requestOpts)
+	if err != nil {
+		return nil, err
 	}
-        if nodecfg.IsDualStack == "yes" {
-                node.Isdualstack = true
-        } else {
-                node.Isdualstack = false
-        }
-        if nodecfg.IsIngressGateway == "yes" {
-                node.Isingressgateway= true
-        } else {
-                node.Isingressgateway = false
-        }
-        return node
+	wcclient = nodepb.NewNodeServiceClient(conn)
+	return wcclient, nil
 }
 
-
+func CheckIn(network string) (*models.Node, error) {
+	cfg, err := config.ReadConfig(network)
+	if err != nil {
+		return nil, err
+	}
+	node := cfg.Node
+	wcclient, err := getGrpcClient(cfg)
+	if err != nil {
+		return nil, err
+	}
+	// == run client action ==
+	var header metadata.MD
+	ctx, err := auth.SetJWT(wcclient, network)
+	nodeData, err := json.Marshal(&node)
+	if err != nil {
+		return nil, err
+	}
+	response, err := wcclient.ReadNode(
+		ctx,
+		&nodepb.Object{
+			Data: string(nodeData),
+			Type: nodepb.NODE_TYPE,
+		},
+		grpc.Header(&header),
+	)
+	if err != nil {
+		log.Printf("Encountered error checking in node: %v", err)
+	}
+	if err = json.Unmarshal([]byte(response.GetData()), &node); err != nil {
+		return nil, err
+	}
+	return &node, err
+}
 
 func RemoveNetwork(network string) error {
-        //need to  implement checkin on server side
-        cfg, err := config.ReadConfig(network)
-        if err != nil {
-                return err
-        }
+	//need to  implement checkin on server side
+	cfg, err := config.ReadConfig(network)
+	if err != nil {
+		return err
+	}
 	servercfg := cfg.Server
-        node := cfg.Node
+	node := cfg.Node
 	fmt.Println("Deleting remote node with MAC: " + node.MacAddress)
 
-        var wcclient nodepb.NodeServiceClient
-        var requestOpts grpc.DialOption
-        requestOpts = grpc.WithInsecure()
-        if cfg.Server.GRPCSSL == "on" {
-                h2creds := credentials.NewTLS(&tls.Config{NextProtos: []string{"h2"}})
-                requestOpts = grpc.WithTransportCredentials(h2creds)
-        }
-        conn, err := grpc.Dial(servercfg.GRPCAddress, requestOpts)
+	var wcclient nodepb.NodeServiceClient
+	var requestOpts grpc.DialOption
+	requestOpts = grpc.WithInsecure()
+	if cfg.Server.GRPCSSL == "on" {
+		h2creds := credentials.NewTLS(&tls.Config{NextProtos: []string{"h2"}})
+		requestOpts = grpc.WithTransportCredentials(h2creds)
+	}
+	conn, err := grpc.Dial(servercfg.GRPCAddress, requestOpts)
 	if err != nil {
-                log.Printf("Unable to establish client connection to " + servercfg.GRPCAddress + ": %v", err)
+		log.Printf("Unable to establish client connection to "+servercfg.GRPCAddress+": %v", err)
 		//return err
-        }else {
-        wcclient = nodepb.NewNodeServiceClient(conn)
-
-        ctx := context.Background()
-        ctx, err = auth.SetJWT(wcclient, network)
-        if err != nil {
-                //return err
-                log.Printf("Failed to authenticate: %v", err)
-        } else {
+	} else {
+		wcclient = nodepb.NewNodeServiceClient(conn)
+		ctx, err := auth.SetJWT(wcclient, network)
+		if err != nil {
+			//return err
+			log.Printf("Failed to authenticate: %v", err)
+		} else {
 
-        var header metadata.MD
+			var header metadata.MD
 
-        _, err = wcclient.DeleteNode(
-                ctx,
-                &nodepb.DeleteNodeReq{
-                        Macaddress: node.MacAddress,
-                        NetworkName: node.Network,
-                },
-                grpc.Header(&header),
-        )
-        if err != nil {
-		log.Printf("Encountered error deleting node: %v", err)
-		fmt.Println(err)
-        } else {
-		fmt.Println("Deleted node " + node.MacAddress)
-	}
-	}
+			_, err = wcclient.DeleteNode(
+				ctx,
+				&nodepb.Object{
+					Data: node.MacAddress + "###" + node.Network,
+					Type: nodepb.STRING_TYPE,
+				},
+				grpc.Header(&header),
+			)
+			if err != nil {
+				log.Printf("Encountered error deleting node: %v", err)
+				fmt.Println(err)
+			} else {
+				fmt.Println("Deleted node " + node.MacAddress)
+			}
+		}
 	}
 	err = local.WipeLocal(network)
 	if err != nil {
-                log.Printf("Unable to wipe local config: %v", err)
+		log.Printf("Unable to wipe local config: %v", err)
 	}
 	if cfg.Daemon != "off" {
-		err =  local.RemoveSystemDServices(network)
+		err = local.RemoveSystemDServices(network)
 	}
 	return err
 }
 
 func GetPeers(macaddress string, network string, server string, dualstack bool, isIngressGateway bool) ([]wgtypes.PeerConfig, bool, []string, error) {
-        //need to  implement checkin on server side
-        hasGateway := false
-        var gateways []string
-        var peers []wgtypes.PeerConfig
-        var wcclient nodepb.NodeServiceClient
-        cfg, err := config.ReadConfig(network)
-        if err != nil {
-                log.Fatalf("Issue retrieving config for network: " + network +  ". Please investigate: %v", err)
-        }
-        nodecfg := cfg.Node
-        keepalive := nodecfg.KeepAlive
-        keepalivedur, err := time.ParseDuration(strconv.FormatInt(int64(keepalive), 10) + "s")
-        keepaliveserver, err := time.ParseDuration(strconv.FormatInt(int64(5), 10) + "s")
-        if err != nil {
-                log.Fatalf("Issue with format of keepalive value. Please update netconfig: %v", err)
-        }
-
+	//need to  implement checkin on server side
+	hasGateway := false
+	var gateways []string
+	var peers []wgtypes.PeerConfig
+	var wcclient nodepb.NodeServiceClient
+	cfg, err := config.ReadConfig(network)
+	if err != nil {
+		log.Fatalf("Issue retrieving config for network: "+network+". Please investigate: %v", err)
+	}
+	nodecfg := cfg.Node
+	keepalive := nodecfg.PersistentKeepalive
+	keepalivedur, err := time.ParseDuration(strconv.FormatInt(int64(keepalive), 10) + "s")
+	keepaliveserver, err := time.ParseDuration(strconv.FormatInt(int64(5), 10) + "s")
+	if err != nil {
+		log.Fatalf("Issue with format of keepalive value. Please update netconfig: %v", err)
+	}
 
-        requestOpts := grpc.WithInsecure()
-        if cfg.Server.GRPCSSL == "on" {
-                h2creds := credentials.NewTLS(&tls.Config{NextProtos: []string{"h2"}})
-                requestOpts = grpc.WithTransportCredentials(h2creds)
-        }
+	requestOpts := grpc.WithInsecure()
+	if cfg.Server.GRPCSSL == "on" {
+		h2creds := credentials.NewTLS(&tls.Config{NextProtos: []string{"h2"}})
+		requestOpts = grpc.WithTransportCredentials(h2creds)
+	}
 
 	conn, err := grpc.Dial(server, requestOpts)
-        if err != nil {
-                log.Fatalf("Unable to establish client connection to localhost:50051: %v", err)
-        }
-        // Instantiate the BlogServiceClient with our client connection to the server
-        wcclient = nodepb.NewNodeServiceClient(conn)
-
-        req := &nodepb.GetPeersReq{
-                Macaddress: macaddress,
-                Network: network,
-        }
-        ctx := context.Background()
-        ctx, err = auth.SetJWT(wcclient, network)
-        if err != nil {
-                log.Println("Failed to authenticate.")
-                return peers, hasGateway, gateways, err
-        }
-        var header metadata.MD
+	if err != nil {
+		log.Fatalf("Unable to establish client connection to localhost:50051: %v", err)
+	}
+	// Instantiate the BlogServiceClient with our client connection to the server
+	wcclient = nodepb.NewNodeServiceClient(conn)
 
-        stream, err := wcclient.GetPeers(ctx, req, grpc.Header(&header))
-        if err != nil {
-                log.Println("Error retrieving peers")
-                log.Println(err)
-                return nil, hasGateway, gateways, err
-        }
-        for {
-                res, err := stream.Recv()
-                // If end of stream, break the loop
+	req := &nodepb.Object{
+		Data: macaddress + "###" + network,
+		Type: nodepb.STRING_TYPE,
+	}
+	ctx := context.Background()
+	ctx, err = auth.SetJWT(wcclient, network)
+	if err != nil {
+		log.Println("Failed to authenticate.")
+		return peers, hasGateway, gateways, err
+	}
+	var header metadata.MD
 
-                if err == io.EOF {
-                        break
-                }
-                // if err, return an error
-                if err != nil {
-                        if strings.Contains(err.Error(), "mongo: no documents in result") {
-                                continue
-                        } else {
-                        fmt.Println("ERROR ENCOUNTERED WITH RESPONSE")
-                        fmt.Println(res)
-                        return peers, hasGateway, gateways, err
-                        }
-                }
-                pubkey, err := wgtypes.ParseKey(res.Peers.Publickey)
-                if err != nil {
-                        fmt.Println("error parsing key")
-                        return peers, hasGateway, gateways, err
-                }
+	response, err := wcclient.GetPeers(ctx, req, grpc.Header(&header))
+	if err != nil {
+		log.Println("Error retrieving peers")
+		log.Println(err)
+		return nil, hasGateway, gateways, err
+	}
+	var nodes []models.Node
+	if err := json.Unmarshal([]byte(response.GetData()), &nodes); err != nil {
+		log.Println("Error unmarshaling data for peers")
+		return nil, hasGateway, gateways, err
+	}
+	for _, node := range nodes {
+		pubkey, err := wgtypes.ParseKey(node.PublicKey)
+		if err != nil {
+			fmt.Println("error parsing key")
+			return peers, hasGateway, gateways, err
+		}
 
-                if nodecfg.PublicKey == res.Peers.Publickey {
-                        continue
-                }
-                if nodecfg.Endpoint == res.Peers.Endpoint {
-                        if nodecfg.LocalAddress != res.Peers.Localaddress && res.Peers.Localaddress != "" {
-				res.Peers.Endpoint = res.Peers.Localaddress
+		if nodecfg.PublicKey == node.PublicKey {
+			continue
+		}
+		if nodecfg.Endpoint == node.Endpoint {
+			if nodecfg.LocalAddress != node.LocalAddress && node.LocalAddress != "" {
+				node.Endpoint = node.LocalAddress
 			} else {
 				continue
 			}
-                }
+		}
 
-                var peer wgtypes.PeerConfig
-                var peeraddr = net.IPNet{
-                        IP: net.ParseIP(res.Peers.Address),
-                        Mask: net.CIDRMask(32, 32),
-                }
-                var allowedips []net.IPNet
-                allowedips = append(allowedips, peeraddr)
-                if res.Peers.Isegressgateway {
-                        hasGateway = true
-			ranges := strings.Split(res.Peers.Egressgatewayranges, ",")
+		var peer wgtypes.PeerConfig
+		var peeraddr = net.IPNet{
+			IP:   net.ParseIP(node.Address),
+			Mask: net.CIDRMask(32, 32),
+		}
+		var allowedips []net.IPNet
+		allowedips = append(allowedips, peeraddr)
+		if node.IsEgressGateway == "yes" {
+			hasGateway = true
+			ranges := node.EgressGatewayRanges
 			for _, iprange := range ranges {
-			gateways = append(gateways,iprange)
-                        _, ipnet, err := net.ParseCIDR(iprange)
-                        if err != nil {
-                                fmt.Println("ERROR ENCOUNTERED SETTING GATEWAY")
-                                fmt.Println("NOT SETTING GATEWAY")
-                                fmt.Println(err)
-                        } else {
-                                fmt.Println("    Gateway Range: "  + iprange)
-                                allowedips = append(allowedips, *ipnet)
-                        }
+				gateways = append(gateways, iprange)
+				_, ipnet, err := net.ParseCIDR(iprange)
+				if err != nil {
+					fmt.Println("ERROR ENCOUNTERED SETTING GATEWAY")
+					fmt.Println("NOT SETTING GATEWAY")
+					fmt.Println(err)
+				} else {
+					fmt.Println("    Gateway Range: " + iprange)
+					allowedips = append(allowedips, *ipnet)
+				}
+			}
+		}
+		if node.Address6 != "" && dualstack {
+			var addr6 = net.IPNet{
+				IP:   net.ParseIP(node.Address6),
+				Mask: net.CIDRMask(128, 128),
+			}
+			allowedips = append(allowedips, addr6)
+		}
+		if nodecfg.Name == "netmaker" {
+			peer = wgtypes.PeerConfig{
+				PublicKey:                   pubkey,
+				PersistentKeepaliveInterval: &keepaliveserver,
+				ReplaceAllowedIPs:           true,
+				AllowedIPs:                  allowedips,
 			}
-                }
-                if res.Peers.Address6 != "" && dualstack {
-                        var addr6 = net.IPNet{
-                                IP: net.ParseIP(res.Peers.Address6),
-                                Mask: net.CIDRMask(128, 128),
-                        }
-                        allowedips = append(allowedips, addr6)
-                }
-                if nodecfg.Name == "netmaker" {
-                peer = wgtypes.PeerConfig{
-                        PublicKey: pubkey,
-                        PersistentKeepaliveInterval: &keepaliveserver,
-                        ReplaceAllowedIPs: true,
-                        AllowedIPs: allowedips,
-                        }
 		} else if keepalive != 0 {
-                peer = wgtypes.PeerConfig{
-                        PublicKey: pubkey,
-                        PersistentKeepaliveInterval: &keepalivedur,
-                        Endpoint: &net.UDPAddr{
-                                IP:   net.ParseIP(res.Peers.Endpoint),
-                                Port: int(res.Peers.Listenport),
-                        },
-                        ReplaceAllowedIPs: true,
-                        AllowedIPs: allowedips,
-                        }
-                } else {
-                peer = wgtypes.PeerConfig{
-                        PublicKey: pubkey,
-                        Endpoint: &net.UDPAddr{
-                                IP:   net.ParseIP(res.Peers.Endpoint),
-                                Port: int(res.Peers.Listenport),
-                        },
-                        ReplaceAllowedIPs: true,
-                        AllowedIPs: allowedips,
-                        }
-                }
-                peers = append(peers, peer)
+			peer = wgtypes.PeerConfig{
+				PublicKey:                   pubkey,
+				PersistentKeepaliveInterval: &keepalivedur,
+				Endpoint: &net.UDPAddr{
+					IP:   net.ParseIP(node.Endpoint),
+					Port: int(node.ListenPort),
+				},
+				ReplaceAllowedIPs: true,
+				AllowedIPs:        allowedips,
+			}
+		} else {
+			peer = wgtypes.PeerConfig{
+				PublicKey: pubkey,
+				Endpoint: &net.UDPAddr{
+					IP:   net.ParseIP(node.Endpoint),
+					Port: int(node.ListenPort),
+				},
+				ReplaceAllowedIPs: true,
+				AllowedIPs:        allowedips,
+			}
+		}
+		peers = append(peers, peer)
 
-        }
-        if isIngressGateway {
-                extPeers, err := GetExtPeers(macaddress, network, server, dualstack)
-                if err == nil {
-                        peers = append(peers, extPeers...)
-                } else {
-                        fmt.Println("ERROR RETRIEVING EXTERNAL PEERS")
-                        fmt.Println(err)
-                }
-        }
-        return peers, hasGateway, gateways, err
+	}
+	if isIngressGateway {
+		extPeers, err := GetExtPeers(macaddress, network, server, dualstack)
+		if err == nil {
+			peers = append(peers, extPeers...)
+		} else {
+			fmt.Println("ERROR RETRIEVING EXTERNAL PEERS")
+			fmt.Println(err)
+		}
+	}
+	return peers, hasGateway, gateways, err
 }
 
 func GetExtPeers(macaddress string, network string, server string, dualstack bool) ([]wgtypes.PeerConfig, error) {
-        var peers []wgtypes.PeerConfig
-        var wcclient nodepb.NodeServiceClient
-        cfg, err := config.ReadConfig(network)
-        if err != nil {
-                log.Fatalf("Issue retrieving config for network: " + network +  ". Please investigate: %v", err)
-        }
-        nodecfg := cfg.Node
-
-        requestOpts := grpc.WithInsecure()
-        conn, err := grpc.Dial(server, requestOpts)
-        if err != nil {
-                log.Fatalf("Unable to establish client connection to localhost:50051: %v", err)
-        }
-        // Instantiate the BlogServiceClient with our client connection to the server
-        wcclient = nodepb.NewNodeServiceClient(conn)
+	var peers []wgtypes.PeerConfig
+	var wcclient nodepb.NodeServiceClient
+	cfg, err := config.ReadConfig(network)
+	if err != nil {
+		log.Fatalf("Issue retrieving config for network: "+network+". Please investigate: %v", err)
+	}
+	nodecfg := cfg.Node
 
-        req := &nodepb.GetExtPeersReq{
-                Macaddress: macaddress,
-                Network: network,
-        }
-        ctx := context.Background()
-        ctx, err = auth.SetJWT(wcclient, network)
-        if err != nil {
-                fmt.Println("Failed to authenticate.")
-                return peers, err
-        }
-        var header metadata.MD
+	requestOpts := grpc.WithInsecure()
+	conn, err := grpc.Dial(server, requestOpts)
+	if err != nil {
+		log.Fatalf("Unable to establish client connection to localhost:50051: %v", err)
+	}
+	// Instantiate the BlogServiceClient with our client connection to the server
+	wcclient = nodepb.NewNodeServiceClient(conn)
 
-        stream, err := wcclient.GetExtPeers(ctx, req, grpc.Header(&header))
-        if err != nil {
-                fmt.Println("Error retrieving peers")
-                fmt.Println(err)
-                return nil, err
-        }
-        for {
-                res, err := stream.Recv()
-                // If end of stream, break the loop
+	req := &nodepb.Object{
+		Data: macaddress + "###" + network,
+		Type: nodepb.STRING_TYPE,
+	}
+	ctx := context.Background()
+	ctx, err = auth.SetJWT(wcclient, network)
+	if err != nil {
+		fmt.Println("Failed to authenticate.")
+		return peers, err
+	}
+	var header metadata.MD
 
-                if err == io.EOF {
-                        break
-                }
-                // if err, return an error
-                if err != nil {
-                        if strings.Contains(err.Error(), "mongo: no documents in result") {
-                                continue
-                        } else {
-                        fmt.Println("ERROR ENCOUNTERED WITH RESPONSE")
-                        fmt.Println(res)
-                        return peers, err
-                        }
-                }
-                pubkey, err := wgtypes.ParseKey(res.Extpeers.Publickey)
-                if err != nil {
-                        fmt.Println("error parsing key")
-                        return peers, err
-                }
+	responseObject, err := wcclient.GetExtPeers(ctx, req, grpc.Header(&header))
+	if err != nil {
+		fmt.Println("Error retrieving peers")
+		fmt.Println(err)
+		return nil, err
+	}
+	var extPeers []models.Node
+	if err = json.Unmarshal([]byte(responseObject.Data), extPeers); err != nil {
+		return nil, err
+	}
+	for _, extPeer := range extPeers {
+		pubkey, err := wgtypes.ParseKey(extPeer.PublicKey)
+		if err != nil {
+			fmt.Println("error parsing key")
+			return peers, err
+		}
 
-                if nodecfg.PublicKey == res.Extpeers.Publickey {
-                        continue
-                }
+		if nodecfg.PublicKey == extPeer.PublicKey {
+			continue
+		}
 
-                var peer wgtypes.PeerConfig
-                var peeraddr = net.IPNet{
-                        IP: net.ParseIP(res.Extpeers.Address),
-                        Mask: net.CIDRMask(32, 32),
-                }
-                var allowedips []net.IPNet
-                allowedips = append(allowedips, peeraddr)
+		var peer wgtypes.PeerConfig
+		var peeraddr = net.IPNet{
+			IP:   net.ParseIP(extPeer.Address),
+			Mask: net.CIDRMask(32, 32),
+		}
+		var allowedips []net.IPNet
+		allowedips = append(allowedips, peeraddr)
 
-		if res.Extpeers.Address6 != "" && dualstack {
-                        var addr6 = net.IPNet{
-                                IP: net.ParseIP(res.Extpeers.Address6),
-                                Mask: net.CIDRMask(128, 128),
-                        }
-                        allowedips = append(allowedips, addr6)
-                }
-                peer = wgtypes.PeerConfig{
-                        PublicKey: pubkey,
-                        ReplaceAllowedIPs: true,
-                        AllowedIPs: allowedips,
-                        }
-                peers = append(peers, peer)
+		if extPeer.Address6 != "" && dualstack {
+			var addr6 = net.IPNet{
+				IP:   net.ParseIP(extPeer.Address6),
+				Mask: net.CIDRMask(128, 128),
+			}
+			allowedips = append(allowedips, addr6)
+		}
+		peer = wgtypes.PeerConfig{
+			PublicKey:         pubkey,
+			ReplaceAllowedIPs: true,
+			AllowedIPs:        allowedips,
+		}
+		peers = append(peers, peer)
 
-        }
-        return peers, err
+	}
+	return peers, err
 }

+ 49 - 61
netclient/wireguard/kernel.go

@@ -3,6 +3,7 @@ package wireguard
 import (
 	"context"
 	"crypto/tls"
+	"encoding/json"
 	"errors"
 	"fmt"
 	"io/ioutil"
@@ -13,7 +14,6 @@ import (
 	"strconv"
 	"strings"
 
-
 	nodepb "github.com/gravitl/netmaker/grpc"
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/netclient/auth"
@@ -53,12 +53,9 @@ func InitGRPCWireguard(client models.IntClient) error {
 	if client.Address6 == "" && client.Address == "" {
 		return errors.New("no address to configure")
 	}
-	cmdIPDevLinkAdd := exec.Command("ip", "link", "add", "dev", ifacename, "type", "wireguard")
-	cmdIPAddrAdd := exec.Command("ip", "address", "add", "dev", ifacename, client.Address+"/24")
-	cmdIPAddr6Add := exec.Command("ip", "address", "add", "dev", ifacename, client.Address6+"/64")
 	currentiface, err := net.InterfaceByName(ifacename)
 	if err != nil {
-		err = cmdIPDevLinkAdd.Run()
+		_, err = local.RunCmd("ip link add dev " + ifacename + " type wireguard")
 		if err != nil && !strings.Contains(err.Error(), "exists") {
 			log.Println("Error creating interface")
 		}
@@ -77,14 +74,14 @@ func InitGRPCWireguard(client models.IntClient) error {
 		}
 	}
 	if !match && client.Address != "" {
-		err = cmdIPAddrAdd.Run()
+		_, err = local.RunCmd("ip address add dev " + ifacename + " " + client.Address + "/24")
 		if err != nil {
 			log.Println("Error adding ipv4 address")
 			fmt.Println(err)
 		}
 	}
 	if !match6 && client.Address6 != "" {
-		err = cmdIPAddr6Add.Run()
+		_, err = local.RunCmd("ip address add dev" + ifacename + " " + client.Address6 + "/64")
 		if err != nil {
 			log.Println("Error adding ipv6 address")
 			fmt.Println(err)
@@ -133,10 +130,8 @@ func InitGRPCWireguard(client models.IntClient) error {
 		}
 	}
 
-	cmdIPLinkUp := exec.Command("ip", "link", "set", "up", "dev", ifacename)
-	cmdIPLinkDown := exec.Command("ip", "link", "set", "down", "dev", ifacename)
-	err = cmdIPLinkDown.Run()
-	err = cmdIPLinkUp.Run()
+	_, err = local.RunCmd("ip link set up dev " + ifacename)
+	_, err = local.RunCmd("ip link set down dev " + ifacename)
 	if err != nil {
 		return err
 	}
@@ -144,7 +139,7 @@ func InitGRPCWireguard(client models.IntClient) error {
 	return err
 }
 
-func InitWireguard(node *nodepb.Node, privkey string, peers []wgtypes.PeerConfig, hasGateway bool, gateways []string) error {
+func InitWireguard(node *models.Node, privkey string, peers []wgtypes.PeerConfig, hasGateway bool, gateways []string) error {
 
 	ipExec, err := exec.LookPath("ip")
 	if err != nil {
@@ -159,7 +154,7 @@ func InitWireguard(node *nodepb.Node, privkey string, peers []wgtypes.PeerConfig
 	if err != nil {
 		return err
 	}
-	modcfg, err := config.ReadConfig(node.Nodenetwork)
+	modcfg, err := config.ReadConfig(node.Network)
 	if err != nil {
 		return err
 	}
@@ -183,29 +178,16 @@ func InitWireguard(node *nodepb.Node, privkey string, peers []wgtypes.PeerConfig
 		log.Fatal("no address to configure")
 	}
 	nameserver := servercfg.CoreDNSAddr
-	network := node.Nodenetwork
+	network := node.Network
 	if nodecfg.Network != "" {
 		network = nodecfg.Network
-	} else if node.Nodenetwork != "" {
-		network = node.Nodenetwork
+	} else if node.Network != "" {
+		network = node.Network
 	}
-	cmdIPDevLinkAdd := &exec.Cmd{
-		Path:   ipExec,
-		Args:   []string{ipExec, "link", "add", "dev", ifacename, "type", "wireguard"},
-		Stdout: os.Stdout,
-		Stderr: os.Stdout,
-	}
-	cmdIPAddrAdd := &exec.Cmd{
-		Path:   ipExec,
-		Args:   []string{ipExec, "address", "add", "dev", ifacename, node.Address + "/24"},
-		Stdout: os.Stdout,
-		Stderr: os.Stdout,
-	}
-	cmdIPLinkDelete := exec.Command("ip", "link", "delete", "dev", ifacename)
 
-	delErr := cmdIPLinkDelete.Run()
-	addLinkErr := cmdIPDevLinkAdd.Run()
-	addErr := cmdIPAddrAdd.Run()
+	_, delErr := local.RunCmd("ip link delete dev " + ifacename)
+	_, addLinkErr := local.RunCmd(ipExec + " link add dev " + ifacename + " type wireguard")
+	_, addErr := local.RunCmd(ipExec + " address add dev " + ifacename + " " + node.Address + "/24")
 	if delErr != nil {
 		log.Println(delErr)
 	}
@@ -216,7 +198,7 @@ func InitWireguard(node *nodepb.Node, privkey string, peers []wgtypes.PeerConfig
 		log.Println(addErr)
 	}
 	var nodeport int
-	nodeport = int(node.Listenport)
+	nodeport = int(node.ListenPort)
 
 	conf := wgtypes.Config{}
 	if nodecfg.UDPHolePunch == "yes" && nodecfg.Name != "netmaker" {
@@ -254,7 +236,7 @@ func InitWireguard(node *nodepb.Node, privkey string, peers []wgtypes.PeerConfig
 		}
 	}
 	//=========DNS Setup==========\\
-	if nodecfg.DNS == "on" {
+	if nodecfg.DNSOn == "yes" {
 		_ = local.UpdateDNS(ifacename, network, nameserver)
 	}
 	//=========End DNS Setup=======\\
@@ -295,16 +277,16 @@ func InitWireguard(node *nodepb.Node, privkey string, peers []wgtypes.PeerConfig
 	}
 	if hasGateway {
 		for _, gateway := range gateways {
-			out, err := exec.Command(ipExec, "-4", "route", "add", gateway, "dev", ifacename).Output()
+			out, err := local.RunCmd(ipExec + " -4 route add " + gateway + " dev " + ifacename)
 			fmt.Println(string(out))
 			if err != nil {
 				fmt.Println("Error encountered adding gateway: " + err.Error())
 			}
 		}
 	}
-	if node.Address6 != "" && node.Isdualstack {
+	if node.Address6 != "" && node.IsDualStack == "yes" {
 		fmt.Println("Adding address: " + node.Address6)
-		out, err := exec.Command(ipExec, "address", "add", "dev", ifacename, node.Address6+"/64").Output()
+		out, err := local.RunCmd(ipExec + " address add dev " + ifacename + " " + node.Address6 + "/64")
 		if err != nil {
 			fmt.Println(out)
 			fmt.Println("Error encountered adding ipv6: " + err.Error())
@@ -345,7 +327,7 @@ func SetWGKeyConfig(network string, serveraddr string) error {
 		return err
 	}
 
-	node := server.GetNode(network)
+	node := config.GetNode(network)
 
 	privatekey, err := wgtypes.GeneratePrivateKey()
 	if err != nil {
@@ -354,7 +336,7 @@ func SetWGKeyConfig(network string, serveraddr string) error {
 	privkeystring := privatekey.String()
 	publickey := privatekey.PublicKey()
 
-	node.Publickey = publickey.String()
+	node.PublicKey = publickey.String()
 
 	err = StorePrivKey(privkeystring, network)
 	if err != nil {
@@ -365,10 +347,15 @@ func SetWGKeyConfig(network string, serveraddr string) error {
 		return err
 	}
 
-	postnode := server.GetNode(network)
+	postnode := config.GetNode(network)
 
-	req := &nodepb.UpdateNodeReq{
-		Node: &postnode,
+	nodeData, err := json.Marshal(&postnode)
+	if err != nil {
+		return err
+	}
+	req := &nodepb.Object{
+		Data: string(nodeData),
+		Type: nodepb.NODE_TYPE,
 	}
 
 	_, err = wcclient.UpdateNode(ctx, req, grpc.Header(&header))
@@ -392,9 +379,9 @@ func SetWGConfig(network string, peerupdate bool) error {
 	}
 	servercfg := cfg.Server
 	nodecfg := cfg.Node
-	node := server.GetNode(network)
+	node := config.GetNode(network)
 
-	peers, hasGateway, gateways, err := server.GetPeers(node.Macaddress, nodecfg.Network, servercfg.GRPCAddress, node.Isdualstack, node.Isingressgateway)
+	peers, hasGateway, gateways, err := server.GetPeers(node.MacAddress, nodecfg.Network, servercfg.GRPCAddress, node.IsDualStack == "yes", node.IsIngressGateway == "yes")
 	if err != nil {
 		return err
 	}
@@ -403,7 +390,7 @@ func SetWGConfig(network string, peerupdate bool) error {
 		return err
 	}
 	if peerupdate {
-		SetPeers(node.Interface, node.Keepalive, peers)
+		SetPeers(node.Interface, node.PersistentKeepalive, peers)
 	} else {
 		err = InitWireguard(&node, privkey, peers, hasGateway, gateways)
 	}
@@ -426,29 +413,30 @@ func SetPeers(iface string, keepalive int32, peers []wgtypes.PeerConfig) {
 		return
 	}
 	for _, peer := range peers {
-		
+
 		for _, currentPeer := range device.Peers {
-			if currentPeer.AllowedIPs[0].String() == peer.AllowedIPs[0].String() && 
-			   currentPeer.PublicKey.String() == peer.PublicKey.String() {
-					err := exec.Command("wg","set",iface,"peer",currentPeer.PublicKey.String(),"delete").Run()
-					if err != nil {
-						log.Println("error setting peer",peer.Endpoint.String(),)
-					}		
+			if currentPeer.AllowedIPs[0].String() == peer.AllowedIPs[0].String() &&
+				currentPeer.PublicKey.String() == peer.PublicKey.String() {
+				_, err := local.RunCmd("wg set " + iface + " peer " + currentPeer.PublicKey.String() + " delete")
+				if err != nil {
+					log.Println("error setting peer", peer.Endpoint.String())
+				}
 			}
-		}		
-		udpendpoint := peer.Endpoint.IP.String()+":"+peer.Endpoint.IP.String()
+		}
+		udpendpoint := peer.Endpoint.IP.String() + ":" + peer.Endpoint.IP.String()
 		var allowedips string
 		var iparr []string
 		for _, ipaddr := range peer.AllowedIPs {
-			iparr = append(iparr,ipaddr.String())
+			iparr = append(iparr, ipaddr.String())
 		}
-		allowedips = strings.Join(iparr,",")
-		err := exec.Command("wg","set",iface,"peer",peer.PublicKey.String(),
-							"endpoint",udpendpoint,
-							"persistent-keepalive",string(keepalive),
-							"allowed-ips",allowedips)
+		allowedips = strings.Join(iparr, ",")
+
+		_, err = local.RunCmd("wg set " + iface + " peer " + peer.PublicKey.String() +
+			" endpoint " + udpendpoint +
+			" persistent-keepalive " + string(keepalive) +
+			" allowed-ips " + allowedips)
 		if err != nil {
-			log.Println("error setting peer",peer.Endpoint.String(),)
+			log.Println("error setting peer", peer.Endpoint.String())
 		}
 	}
 }

+ 2 - 1
serverctl/serverctl.go

@@ -12,6 +12,7 @@ import (
 	"github.com/gravitl/netmaker/database"
 	"github.com/gravitl/netmaker/functions"
 	"github.com/gravitl/netmaker/models"
+	"github.com/gravitl/netmaker/netclient/local"
 	"github.com/gravitl/netmaker/servercfg"
 )
 
@@ -121,7 +122,7 @@ func RemoveNetwork(network string) (bool, error) {
 		log.Println("could not find /etc/netclient")
 		return false, err
 	}
-	cmdoutput, err := exec.Command("/etc/netclient/netclient", "leave", "-n", network).Output()
+	cmdoutput, err := local.RunCmd("/etc/netclient/netclient leave -n " + network)
 	if err != nil {
 		log.Println(string(cmdoutput))
 		return false, err

Some files were not shown because too many files changed in this diff