Browse Source

added udp holepunching

afeiszli 4 years ago
parent
commit
4a6ebfc108
10 changed files with 2758 additions and 2099 deletions
  1. 21 4
      controllers/common.go
  2. 6 52
      controllers/nodeGrpcController.go
  3. 1 0
      go.mod
  4. 1569 915
      grpc/node.pb.go
  5. 2 1
      grpc/node.proto
  6. 357 355
      netclient/config/config.go
  7. 124 124
      netclient/functions/join.go
  8. 370 364
      netclient/main.go
  9. 285 284
      netclient/wireguard/kernel.go
  10. 23 0
      serverctl/wireguard.go

+ 21 - 4
controllers/common.go

@@ -3,12 +3,16 @@ package controller
 import (
 	"encoding/json"
 	"fmt"
+	"log"
+	"strconv"
+	"strings"
 	"time"
 
 	"github.com/gravitl/netmaker/database"
 	"github.com/gravitl/netmaker/functions"
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/servercfg"
+	"github.com/gravitl/netmaker/serverctl"
 	"golang.org/x/crypto/bcrypt"
 )
 
@@ -16,11 +20,10 @@ func GetPeersList(networkName string) ([]models.PeersResponse, error) {
 
 	var peers []models.PeersResponse
 	collection, err := database.FetchRecords(database.NODES_TABLE_NAME)
-
-	if err != nil {
-		return peers, err
+	udppeers, errN := serverctl.GetPeers(networkName)
+	if errN != nil {
+		log.Println(errN)
 	}
-
 	for _, value := range collection {
 		var node models.Node
 		var peer models.PeersResponse
@@ -33,9 +36,23 @@ func GetPeersList(networkName string) ([]models.PeersResponse, error) {
 			continue
 		}
 		if node.Network == networkName && !node.IsPending {
+			if node.UDPHolePunch == "yes" && errN == nil {
+				endpointstring := udppeers[peer.PublicKey]
+				endpointarr := strings.Split(endpointstring, ":")
+				if len(endpointarr) == 2 {
+					port, err := strconv.Atoi(endpointarr[1])
+					if err == nil {
+						peer.Endpoint = endpointarr[0]
+						peer.ListenPort = int32(port)
+					}
+				}
+			}
 			peers = append(peers, peer)
 		}
 	}
+	if err != nil {
+		return peers, err
+	}
 
 	return peers, err
 }

+ 6 - 52
controllers/nodeGrpcController.go

@@ -59,63 +59,12 @@ func (s *NodeServiceServer) ReadNode(ctx context.Context, req *nodepb.ReadNodeRe
 			Islocal:             network.IsLocal == "yes",
 			Isdualstack:         network.IsDualStack == "yes",
 			Localrange:          network.LocalRange,
+			Udpholepunch:        node.UDPHolePunch,
 		},
 	}
 	return response, nil
 }
 
-/*
-func (s *NodeServiceServer) GetConn(ctx context.Context, data *nodepb.Client) (*nodepb.Client, error) {
-        // Get the protobuf node type from the protobuf request type
-        // Essentially doing req.Node to access the struct with a nil check
-        // Now we have to convert this into a NodeItem type to convert into BSON
-        clientreq := models.IntClient{
-                // ID:       primitive.NilObjectID,
-                Address:             data.GetAddress(),
-                Address6:            data.GetAddress6(),
-                AccessKey:           data.GetAccesskey(),
-                PublicKey:           data.GetPublickey(),
-                PrivateKey:           data.GetPrivatekey(),
-                ServerPort:          data.GetServerport(),
-                ServerKey:          data.GetServerkey(),
-                ServerWGEndpoint:          data.GetServerwgendpoint(),
-        }
-
-        //Check to see if key is valid
-        //TODO: Triple inefficient!!! This is the third call to the DB we make for networks
-        if servercfg.IsRegisterKeyRequired() {
-		validKey := functions.IsKeyValidGlobal(clientreq.AccessKey)
-		if !validKey {
-			return nil, status.Errorf(
-                                codes.Internal,
-                                fmt.Sprintf("Invalid key, and server does not allow no-key signups"),
-                        )
-		}
-	}
-	client, err := RegisterIntClient(clientreq)
-
-        if err != nil {
-                // return internal gRPC error to be handled later
-                return nil, status.Errorf(
-                        codes.Internal,
-                        fmt.Sprintf("Internal error: %v", err),
-                )
-        }
-        // return the node in a CreateNodeRes type
-        response := &nodepb.Client{
-                        Privatekey:   client.PrivateKey,
-                        Publickey: client.PublicKey,
-                        Accesskey:         client.AccessKey,
-                        Address:      client.Address,
-                        Address6:     client.Address6,
-                        Serverwgendpoint:     client.ServerWGEndpoint,
-                        Serverport:     client.ServerPort,
-                        Serverkey:    client.ServerKey,
-        }
-
-        return response, nil
-}
-*/
 func (s *NodeServiceServer) CreateNode(ctx context.Context, req *nodepb.CreateNodeReq) (*nodepb.CreateNodeRes, error) {
 	// Get the protobuf node type from the protobuf request type
 	// Essentially doing req.Node to access the struct with a nil check
@@ -137,6 +86,7 @@ func (s *NodeServiceServer) CreateNode(ctx context.Context, req *nodepb.CreateNo
 		IsPending:           data.GetIspending(),
 		PublicKey:           data.GetPublickey(),
 		ListenPort:          data.GetListenport(),
+		UDPHolePunch:        data.GetUdpholepunch(),
 	}
 
 	err := node.Validate(false)
@@ -197,6 +147,7 @@ func (s *NodeServiceServer) CreateNode(ctx context.Context, req *nodepb.CreateNo
 			Islocal:      network.IsLocal == "yes",
 			Isdualstack:  network.IsDualStack == "yes",
 			Localrange:   network.LocalRange,
+			Udpholepunch: node.UDPHolePunch,
 		},
 	}
 	err = SetNetworkNodesLastModified(node.Network)
@@ -225,6 +176,7 @@ func (s *NodeServiceServer) CheckIn(ctx context.Context, req *nodepb.CheckInReq)
 		ListenPort:          data.GetListenport(),
 		PersistentKeepalive: data.GetKeepalive(),
 		PublicKey:           data.GetPublickey(),
+		UDPHolePunch:        data.GetUdpholepunch(),
 	}
 
 	checkinresponse, err := NodeCheckIn(node, node.Network)
@@ -274,6 +226,7 @@ func (s *NodeServiceServer) UpdateNode(ctx context.Context, req *nodepb.UpdateNo
 		IsPending:           data.GetIspending(),
 		PublicKey:           data.GetPublickey(),
 		ListenPort:          data.GetListenport(),
+		UDPHolePunch:        data.GetUdpholepunch(),
 	}
 
 	// Convert the Id string to a MongoDB ObjectId
@@ -323,6 +276,7 @@ func (s *NodeServiceServer) UpdateNode(ctx context.Context, req *nodepb.UpdateNo
 			Islocal:      network.IsLocal == "yes",
 			Isdualstack:  network.IsDualStack == "yes",
 			Localrange:   network.LocalRange,
+			Udpholepunch: newnode.UDPHolePunch,
 		},
 	}, nil
 }

+ 1 - 0
go.mod

@@ -3,6 +3,7 @@ module github.com/gravitl/netmaker
 go 1.15
 
 require (
+	github.com/aws/aws-sdk-go v1.34.28
 	github.com/davecgh/go-spew v1.1.1 // indirect
 	github.com/dgrijalva/jwt-go v3.2.0+incompatible
 	github.com/go-playground/validator/v10 v10.5.0

+ 1569 - 915
grpc/node.pb.go

@@ -1,1436 +1,2090 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// 	protoc-gen-go v1.25.0-devel
+// 	protoc        v3.14.0
 // source: grpc/node.proto
 
 package nodepb
 
 import (
-	fmt "fmt"
-	proto "github.com/golang/protobuf/proto"
-	math "math"
+	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+	reflect "reflect"
+	sync "sync"
 )
 
-// Reference imports to suppress errors if they are not otherwise used.
-var _ = proto.Marshal
-var _ = fmt.Errorf
-var _ = math.Inf
-
-// This is a compile-time assertion to ensure that this generated file
-// is compatible with the proto package it is being compiled against.
-// A compilation error at this line likely means your copy of the
-// proto package needs to be updated.
-const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+const (
+	// Verify that this generated code is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+	// Verify that runtime/protoimpl is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
 
 type LoginRequest struct {
-	Macaddress           string   `protobuf:"bytes,1,opt,name=macaddress,proto3" json:"macaddress,omitempty"`
-	Password             string   `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"`
-	Network              string   `protobuf:"bytes,3,opt,name=network,proto3" json:"network,omitempty"`
-	XXX_NoUnkeyedLiteral struct{} `json:"-"`
-	XXX_unrecognized     []byte   `json:"-"`
-	XXX_sizecache        int32    `json:"-"`
-}
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
 
-func (m *LoginRequest) Reset()         { *m = LoginRequest{} }
-func (m *LoginRequest) String() string { return proto.CompactTextString(m) }
-func (*LoginRequest) ProtoMessage()    {}
-func (*LoginRequest) Descriptor() ([]byte, []int) {
-	return fileDescriptor_d13bd996b67da4ef, []int{0}
+	Macaddress string `protobuf:"bytes,1,opt,name=macaddress,proto3" json:"macaddress,omitempty"`
+	Password   string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"`
+	Network    string `protobuf:"bytes,3,opt,name=network,proto3" json:"network,omitempty"`
 }
 
-func (m *LoginRequest) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_LoginRequest.Unmarshal(m, b)
-}
-func (m *LoginRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_LoginRequest.Marshal(b, m, deterministic)
-}
-func (m *LoginRequest) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_LoginRequest.Merge(m, src)
+func (x *LoginRequest) Reset() {
+	*x = LoginRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_grpc_node_proto_msgTypes[0]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
-func (m *LoginRequest) XXX_Size() int {
-	return xxx_messageInfo_LoginRequest.Size(m)
+
+func (x *LoginRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
-func (m *LoginRequest) XXX_DiscardUnknown() {
-	xxx_messageInfo_LoginRequest.DiscardUnknown(m)
+
+func (*LoginRequest) ProtoMessage() {}
+
+func (x *LoginRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_grpc_node_proto_msgTypes[0]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
 
-var xxx_messageInfo_LoginRequest proto.InternalMessageInfo
+// Deprecated: Use LoginRequest.ProtoReflect.Descriptor instead.
+func (*LoginRequest) Descriptor() ([]byte, []int) {
+	return file_grpc_node_proto_rawDescGZIP(), []int{0}
+}
 
-func (m *LoginRequest) GetMacaddress() string {
-	if m != nil {
-		return m.Macaddress
+func (x *LoginRequest) GetMacaddress() string {
+	if x != nil {
+		return x.Macaddress
 	}
 	return ""
 }
 
-func (m *LoginRequest) GetPassword() string {
-	if m != nil {
-		return m.Password
+func (x *LoginRequest) GetPassword() string {
+	if x != nil {
+		return x.Password
 	}
 	return ""
 }
 
-func (m *LoginRequest) GetNetwork() string {
-	if m != nil {
-		return m.Network
+func (x *LoginRequest) GetNetwork() string {
+	if x != nil {
+		return x.Network
 	}
 	return ""
 }
 
 type LoginResponse struct {
-	Accesstoken          string   `protobuf:"bytes,1,opt,name=accesstoken,proto3" json:"accesstoken,omitempty"`
-	XXX_NoUnkeyedLiteral struct{} `json:"-"`
-	XXX_unrecognized     []byte   `json:"-"`
-	XXX_sizecache        int32    `json:"-"`
-}
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
 
-func (m *LoginResponse) Reset()         { *m = LoginResponse{} }
-func (m *LoginResponse) String() string { return proto.CompactTextString(m) }
-func (*LoginResponse) ProtoMessage()    {}
-func (*LoginResponse) Descriptor() ([]byte, []int) {
-	return fileDescriptor_d13bd996b67da4ef, []int{1}
+	Accesstoken string `protobuf:"bytes,1,opt,name=accesstoken,proto3" json:"accesstoken,omitempty"`
 }
 
-func (m *LoginResponse) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_LoginResponse.Unmarshal(m, b)
-}
-func (m *LoginResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_LoginResponse.Marshal(b, m, deterministic)
-}
-func (m *LoginResponse) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_LoginResponse.Merge(m, src)
+func (x *LoginResponse) Reset() {
+	*x = LoginResponse{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_grpc_node_proto_msgTypes[1]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
-func (m *LoginResponse) XXX_Size() int {
-	return xxx_messageInfo_LoginResponse.Size(m)
+
+func (x *LoginResponse) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
-func (m *LoginResponse) XXX_DiscardUnknown() {
-	xxx_messageInfo_LoginResponse.DiscardUnknown(m)
+
+func (*LoginResponse) ProtoMessage() {}
+
+func (x *LoginResponse) ProtoReflect() protoreflect.Message {
+	mi := &file_grpc_node_proto_msgTypes[1]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
 
-var xxx_messageInfo_LoginResponse proto.InternalMessageInfo
+// Deprecated: Use LoginResponse.ProtoReflect.Descriptor instead.
+func (*LoginResponse) Descriptor() ([]byte, []int) {
+	return file_grpc_node_proto_rawDescGZIP(), []int{1}
+}
 
-func (m *LoginResponse) GetAccesstoken() string {
-	if m != nil {
-		return m.Accesstoken
+func (x *LoginResponse) GetAccesstoken() string {
+	if x != nil {
+		return x.Accesstoken
 	}
 	return ""
 }
 
 type Node struct {
-	Id                   string   `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
-	Name                 string   `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
-	Address              string   `protobuf:"bytes,3,opt,name=address,proto3" json:"address,omitempty"`
-	Address6             string   `protobuf:"bytes,26,opt,name=address6,proto3" json:"address6,omitempty"`
-	Listenport           int32    `protobuf:"varint,4,opt,name=listenport,proto3" json:"listenport,omitempty"`
-	Publickey            string   `protobuf:"bytes,5,opt,name=publickey,proto3" json:"publickey,omitempty"`
-	Endpoint             string   `protobuf:"bytes,6,opt,name=endpoint,proto3" json:"endpoint,omitempty"`
-	Macaddress           string   `protobuf:"bytes,7,opt,name=macaddress,proto3" json:"macaddress,omitempty"`
-	Password             string   `protobuf:"bytes,8,opt,name=password,proto3" json:"password,omitempty"`
-	Nodenetwork          string   `protobuf:"bytes,9,opt,name=nodenetwork,proto3" json:"nodenetwork,omitempty"`
-	Ispending            bool     `protobuf:"varint,10,opt,name=ispending,proto3" json:"ispending,omitempty"`
-	Postup               string   `protobuf:"bytes,11,opt,name=postup,proto3" json:"postup,omitempty"`
-	Postdown             string   `protobuf:"bytes,12,opt,name=postdown,proto3" json:"postdown,omitempty"`
-	Keepalive            int32    `protobuf:"varint,13,opt,name=keepalive,proto3" json:"keepalive,omitempty"`
-	Saveconfig           bool     `protobuf:"varint,14,opt,name=saveconfig,proto3" json:"saveconfig,omitempty"`
-	Accesskey            string   `protobuf:"bytes,15,opt,name=accesskey,proto3" json:"accesskey,omitempty"`
-	Interface            string   `protobuf:"bytes,16,opt,name=interface,proto3" json:"interface,omitempty"`
-	Lastcheckin          string   `protobuf:"bytes,17,opt,name=lastcheckin,proto3" json:"lastcheckin,omitempty"`
-	Lastmodified         string   `protobuf:"bytes,18,opt,name=lastmodified,proto3" json:"lastmodified,omitempty"`
-	Checkininterval      int32    `protobuf:"varint,19,opt,name=checkininterval,proto3" json:"checkininterval,omitempty"`
-	Localaddress         string   `protobuf:"bytes,20,opt,name=localaddress,proto3" json:"localaddress,omitempty"`
-	Postchanges          string   `protobuf:"bytes,21,opt,name=postchanges,proto3" json:"postchanges,omitempty"`
-	Allowedips           string   `protobuf:"bytes,22,opt,name=allowedips,proto3" json:"allowedips,omitempty"`
-	Islocal              bool     `protobuf:"varint,23,opt,name=islocal,proto3" json:"islocal,omitempty"`
-	Isingressgateway     bool     `protobuf:"varint,28,opt,name=isingressgateway,proto3" json:"isingressgateway,omitempty"`
-	Ingressgatewayrange  string   `protobuf:"bytes,29,opt,name=ingressgatewayrange,proto3" json:"ingressgatewayrange,omitempty"`
-	Isdualstack          bool     `protobuf:"varint,27,opt,name=isdualstack,proto3" json:"isdualstack,omitempty"`
-	Dnsoff               bool     `protobuf:"varint,24,opt,name=dnsoff,proto3" json:"dnsoff,omitempty"`
-	Localrange           string   `protobuf:"bytes,25,opt,name=localrange,proto3" json:"localrange,omitempty"`
-	XXX_NoUnkeyedLiteral struct{} `json:"-"`
-	XXX_unrecognized     []byte   `json:"-"`
-	XXX_sizecache        int32    `json:"-"`
-}
-
-func (m *Node) Reset()         { *m = Node{} }
-func (m *Node) String() string { return proto.CompactTextString(m) }
-func (*Node) ProtoMessage()    {}
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Id                  string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
+	Name                string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
+	Address             string `protobuf:"bytes,3,opt,name=address,proto3" json:"address,omitempty"`
+	Address6            string `protobuf:"bytes,26,opt,name=address6,proto3" json:"address6,omitempty"`
+	Listenport          int32  `protobuf:"varint,4,opt,name=listenport,proto3" json:"listenport,omitempty"`
+	Publickey           string `protobuf:"bytes,5,opt,name=publickey,proto3" json:"publickey,omitempty"`
+	Endpoint            string `protobuf:"bytes,6,opt,name=endpoint,proto3" json:"endpoint,omitempty"`
+	Macaddress          string `protobuf:"bytes,7,opt,name=macaddress,proto3" json:"macaddress,omitempty"`
+	Password            string `protobuf:"bytes,8,opt,name=password,proto3" json:"password,omitempty"`
+	Nodenetwork         string `protobuf:"bytes,9,opt,name=nodenetwork,proto3" json:"nodenetwork,omitempty"`
+	Ispending           bool   `protobuf:"varint,10,opt,name=ispending,proto3" json:"ispending,omitempty"`
+	Postup              string `protobuf:"bytes,11,opt,name=postup,proto3" json:"postup,omitempty"`
+	Postdown            string `protobuf:"bytes,12,opt,name=postdown,proto3" json:"postdown,omitempty"`
+	Keepalive           int32  `protobuf:"varint,13,opt,name=keepalive,proto3" json:"keepalive,omitempty"`
+	Saveconfig          string `protobuf:"bytes,14,opt,name=saveconfig,proto3" json:"saveconfig,omitempty"`
+	Accesskey           string `protobuf:"bytes,15,opt,name=accesskey,proto3" json:"accesskey,omitempty"`
+	Interface           string `protobuf:"bytes,16,opt,name=interface,proto3" json:"interface,omitempty"`
+	Lastcheckin         string `protobuf:"bytes,17,opt,name=lastcheckin,proto3" json:"lastcheckin,omitempty"`
+	Lastmodified        string `protobuf:"bytes,18,opt,name=lastmodified,proto3" json:"lastmodified,omitempty"`
+	Checkininterval     int32  `protobuf:"varint,19,opt,name=checkininterval,proto3" json:"checkininterval,omitempty"`
+	Localaddress        string `protobuf:"bytes,20,opt,name=localaddress,proto3" json:"localaddress,omitempty"`
+	Postchanges         string `protobuf:"bytes,21,opt,name=postchanges,proto3" json:"postchanges,omitempty"`
+	Allowedips          string `protobuf:"bytes,22,opt,name=allowedips,proto3" json:"allowedips,omitempty"`
+	Islocal             bool   `protobuf:"varint,23,opt,name=islocal,proto3" json:"islocal,omitempty"`
+	Isingressgateway    bool   `protobuf:"varint,28,opt,name=isingressgateway,proto3" json:"isingressgateway,omitempty"`
+	Ingressgatewayrange string `protobuf:"bytes,29,opt,name=ingressgatewayrange,proto3" json:"ingressgatewayrange,omitempty"`
+	Isdualstack         bool   `protobuf:"varint,27,opt,name=isdualstack,proto3" json:"isdualstack,omitempty"`
+	Dnsoff              bool   `protobuf:"varint,24,opt,name=dnsoff,proto3" json:"dnsoff,omitempty"`
+	Localrange          string `protobuf:"bytes,25,opt,name=localrange,proto3" json:"localrange,omitempty"`
+	Udpholepunch        string `protobuf:"bytes,30,opt,name=udpholepunch,proto3" json:"udpholepunch,omitempty"`
+}
+
+func (x *Node) Reset() {
+	*x = Node{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_grpc_node_proto_msgTypes[2]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *Node) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Node) ProtoMessage() {}
+
+func (x *Node) ProtoReflect() protoreflect.Message {
+	mi := &file_grpc_node_proto_msgTypes[2]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use Node.ProtoReflect.Descriptor instead.
 func (*Node) Descriptor() ([]byte, []int) {
-	return fileDescriptor_d13bd996b67da4ef, []int{2}
-}
-
-func (m *Node) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_Node.Unmarshal(m, b)
-}
-func (m *Node) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_Node.Marshal(b, m, deterministic)
-}
-func (m *Node) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_Node.Merge(m, src)
-}
-func (m *Node) XXX_Size() int {
-	return xxx_messageInfo_Node.Size(m)
-}
-func (m *Node) XXX_DiscardUnknown() {
-	xxx_messageInfo_Node.DiscardUnknown(m)
+	return file_grpc_node_proto_rawDescGZIP(), []int{2}
 }
 
-var xxx_messageInfo_Node proto.InternalMessageInfo
-
-func (m *Node) GetId() string {
-	if m != nil {
-		return m.Id
+func (x *Node) GetId() string {
+	if x != nil {
+		return x.Id
 	}
 	return ""
 }
 
-func (m *Node) GetName() string {
-	if m != nil {
-		return m.Name
+func (x *Node) GetName() string {
+	if x != nil {
+		return x.Name
 	}
 	return ""
 }
 
-func (m *Node) GetAddress() string {
-	if m != nil {
-		return m.Address
+func (x *Node) GetAddress() string {
+	if x != nil {
+		return x.Address
 	}
 	return ""
 }
 
-func (m *Node) GetAddress6() string {
-	if m != nil {
-		return m.Address6
+func (x *Node) GetAddress6() string {
+	if x != nil {
+		return x.Address6
 	}
 	return ""
 }
 
-func (m *Node) GetListenport() int32 {
-	if m != nil {
-		return m.Listenport
+func (x *Node) GetListenport() int32 {
+	if x != nil {
+		return x.Listenport
 	}
 	return 0
 }
 
-func (m *Node) GetPublickey() string {
-	if m != nil {
-		return m.Publickey
+func (x *Node) GetPublickey() string {
+	if x != nil {
+		return x.Publickey
 	}
 	return ""
 }
 
-func (m *Node) GetEndpoint() string {
-	if m != nil {
-		return m.Endpoint
+func (x *Node) GetEndpoint() string {
+	if x != nil {
+		return x.Endpoint
 	}
 	return ""
 }
 
-func (m *Node) GetMacaddress() string {
-	if m != nil {
-		return m.Macaddress
+func (x *Node) GetMacaddress() string {
+	if x != nil {
+		return x.Macaddress
 	}
 	return ""
 }
 
-func (m *Node) GetPassword() string {
-	if m != nil {
-		return m.Password
+func (x *Node) GetPassword() string {
+	if x != nil {
+		return x.Password
 	}
 	return ""
 }
 
-func (m *Node) GetNodenetwork() string {
-	if m != nil {
-		return m.Nodenetwork
+func (x *Node) GetNodenetwork() string {
+	if x != nil {
+		return x.Nodenetwork
 	}
 	return ""
 }
 
-func (m *Node) GetIspending() bool {
-	if m != nil {
-		return m.Ispending
+func (x *Node) GetIspending() bool {
+	if x != nil {
+		return x.Ispending
 	}
 	return false
 }
 
-func (m *Node) GetPostup() string {
-	if m != nil {
-		return m.Postup
+func (x *Node) GetPostup() string {
+	if x != nil {
+		return x.Postup
 	}
 	return ""
 }
 
-func (m *Node) GetPostdown() string {
-	if m != nil {
-		return m.Postdown
+func (x *Node) GetPostdown() string {
+	if x != nil {
+		return x.Postdown
 	}
 	return ""
 }
 
-func (m *Node) GetKeepalive() int32 {
-	if m != nil {
-		return m.Keepalive
+func (x *Node) GetKeepalive() int32 {
+	if x != nil {
+		return x.Keepalive
 	}
 	return 0
 }
 
-func (m *Node) GetSaveconfig() bool {
-	if m != nil {
-		return m.Saveconfig
+func (x *Node) GetSaveconfig() string {
+	if x != nil {
+		return x.Saveconfig
 	}
-	return false
+	return ""
 }
 
-func (m *Node) GetAccesskey() string {
-	if m != nil {
-		return m.Accesskey
+func (x *Node) GetAccesskey() string {
+	if x != nil {
+		return x.Accesskey
 	}
 	return ""
 }
 
-func (m *Node) GetInterface() string {
-	if m != nil {
-		return m.Interface
+func (x *Node) GetInterface() string {
+	if x != nil {
+		return x.Interface
 	}
 	return ""
 }
 
-func (m *Node) GetLastcheckin() string {
-	if m != nil {
-		return m.Lastcheckin
+func (x *Node) GetLastcheckin() string {
+	if x != nil {
+		return x.Lastcheckin
 	}
 	return ""
 }
 
-func (m *Node) GetLastmodified() string {
-	if m != nil {
-		return m.Lastmodified
+func (x *Node) GetLastmodified() string {
+	if x != nil {
+		return x.Lastmodified
 	}
 	return ""
 }
 
-func (m *Node) GetCheckininterval() int32 {
-	if m != nil {
-		return m.Checkininterval
+func (x *Node) GetCheckininterval() int32 {
+	if x != nil {
+		return x.Checkininterval
 	}
 	return 0
 }
 
-func (m *Node) GetLocaladdress() string {
-	if m != nil {
-		return m.Localaddress
+func (x *Node) GetLocaladdress() string {
+	if x != nil {
+		return x.Localaddress
 	}
 	return ""
 }
 
-func (m *Node) GetPostchanges() string {
-	if m != nil {
-		return m.Postchanges
+func (x *Node) GetPostchanges() string {
+	if x != nil {
+		return x.Postchanges
 	}
 	return ""
 }
 
-func (m *Node) GetAllowedips() string {
-	if m != nil {
-		return m.Allowedips
+func (x *Node) GetAllowedips() string {
+	if x != nil {
+		return x.Allowedips
 	}
 	return ""
 }
 
-func (m *Node) GetIslocal() bool {
-	if m != nil {
-		return m.Islocal
+func (x *Node) GetIslocal() bool {
+	if x != nil {
+		return x.Islocal
 	}
 	return false
 }
 
-func (m *Node) GetIsingressgateway() bool {
-	if m != nil {
-		return m.Isingressgateway
+func (x *Node) GetIsingressgateway() bool {
+	if x != nil {
+		return x.Isingressgateway
 	}
 	return false
 }
 
-func (m *Node) GetIngressgatewayrange() string {
-	if m != nil {
-		return m.Ingressgatewayrange
+func (x *Node) GetIngressgatewayrange() string {
+	if x != nil {
+		return x.Ingressgatewayrange
 	}
 	return ""
 }
 
-func (m *Node) GetIsdualstack() bool {
-	if m != nil {
-		return m.Isdualstack
+func (x *Node) GetIsdualstack() bool {
+	if x != nil {
+		return x.Isdualstack
 	}
 	return false
 }
 
-func (m *Node) GetDnsoff() bool {
-	if m != nil {
-		return m.Dnsoff
+func (x *Node) GetDnsoff() bool {
+	if x != nil {
+		return x.Dnsoff
 	}
 	return false
 }
 
-func (m *Node) GetLocalrange() string {
-	if m != nil {
-		return m.Localrange
+func (x *Node) GetLocalrange() string {
+	if x != nil {
+		return x.Localrange
 	}
 	return ""
 }
 
-type CheckInResponse struct {
-	Success              bool     `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"`
-	Needpeerupdate       bool     `protobuf:"varint,2,opt,name=needpeerupdate,proto3" json:"needpeerupdate,omitempty"`
-	Needconfigupdate     bool     `protobuf:"varint,3,opt,name=needconfigupdate,proto3" json:"needconfigupdate,omitempty"`
-	Nodemessage          string   `protobuf:"bytes,4,opt,name=nodemessage,proto3" json:"nodemessage,omitempty"`
-	Ispending            bool     `protobuf:"varint,5,opt,name=ispending,proto3" json:"ispending,omitempty"`
-	Needkeyupdate        bool     `protobuf:"varint,6,opt,name=needkeyupdate,proto3" json:"needkeyupdate,omitempty"`
-	Needdelete           bool     `protobuf:"varint,7,opt,name=needdelete,proto3" json:"needdelete,omitempty"`
-	XXX_NoUnkeyedLiteral struct{} `json:"-"`
-	XXX_unrecognized     []byte   `json:"-"`
-	XXX_sizecache        int32    `json:"-"`
-}
-
-func (m *CheckInResponse) Reset()         { *m = CheckInResponse{} }
-func (m *CheckInResponse) String() string { return proto.CompactTextString(m) }
-func (*CheckInResponse) ProtoMessage()    {}
-func (*CheckInResponse) Descriptor() ([]byte, []int) {
-	return fileDescriptor_d13bd996b67da4ef, []int{3}
+func (x *Node) GetUdpholepunch() string {
+	if x != nil {
+		return x.Udpholepunch
+	}
+	return ""
 }
 
-func (m *CheckInResponse) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_CheckInResponse.Unmarshal(m, b)
-}
-func (m *CheckInResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_CheckInResponse.Marshal(b, m, deterministic)
+type CheckInResponse struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Success          bool   `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"`
+	Needpeerupdate   bool   `protobuf:"varint,2,opt,name=needpeerupdate,proto3" json:"needpeerupdate,omitempty"`
+	Needconfigupdate bool   `protobuf:"varint,3,opt,name=needconfigupdate,proto3" json:"needconfigupdate,omitempty"`
+	Nodemessage      string `protobuf:"bytes,4,opt,name=nodemessage,proto3" json:"nodemessage,omitempty"`
+	Ispending        bool   `protobuf:"varint,5,opt,name=ispending,proto3" json:"ispending,omitempty"`
+	Needkeyupdate    bool   `protobuf:"varint,6,opt,name=needkeyupdate,proto3" json:"needkeyupdate,omitempty"`
+	Needdelete       bool   `protobuf:"varint,7,opt,name=needdelete,proto3" json:"needdelete,omitempty"`
 }
-func (m *CheckInResponse) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_CheckInResponse.Merge(m, src)
+
+func (x *CheckInResponse) Reset() {
+	*x = CheckInResponse{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_grpc_node_proto_msgTypes[3]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
-func (m *CheckInResponse) XXX_Size() int {
-	return xxx_messageInfo_CheckInResponse.Size(m)
+
+func (x *CheckInResponse) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
-func (m *CheckInResponse) XXX_DiscardUnknown() {
-	xxx_messageInfo_CheckInResponse.DiscardUnknown(m)
+
+func (*CheckInResponse) ProtoMessage() {}
+
+func (x *CheckInResponse) ProtoReflect() protoreflect.Message {
+	mi := &file_grpc_node_proto_msgTypes[3]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
 
-var xxx_messageInfo_CheckInResponse proto.InternalMessageInfo
+// Deprecated: Use CheckInResponse.ProtoReflect.Descriptor instead.
+func (*CheckInResponse) Descriptor() ([]byte, []int) {
+	return file_grpc_node_proto_rawDescGZIP(), []int{3}
+}
 
-func (m *CheckInResponse) GetSuccess() bool {
-	if m != nil {
-		return m.Success
+func (x *CheckInResponse) GetSuccess() bool {
+	if x != nil {
+		return x.Success
 	}
 	return false
 }
 
-func (m *CheckInResponse) GetNeedpeerupdate() bool {
-	if m != nil {
-		return m.Needpeerupdate
+func (x *CheckInResponse) GetNeedpeerupdate() bool {
+	if x != nil {
+		return x.Needpeerupdate
 	}
 	return false
 }
 
-func (m *CheckInResponse) GetNeedconfigupdate() bool {
-	if m != nil {
-		return m.Needconfigupdate
+func (x *CheckInResponse) GetNeedconfigupdate() bool {
+	if x != nil {
+		return x.Needconfigupdate
 	}
 	return false
 }
 
-func (m *CheckInResponse) GetNodemessage() string {
-	if m != nil {
-		return m.Nodemessage
+func (x *CheckInResponse) GetNodemessage() string {
+	if x != nil {
+		return x.Nodemessage
 	}
 	return ""
 }
 
-func (m *CheckInResponse) GetIspending() bool {
-	if m != nil {
-		return m.Ispending
+func (x *CheckInResponse) GetIspending() bool {
+	if x != nil {
+		return x.Ispending
 	}
 	return false
 }
 
-func (m *CheckInResponse) GetNeedkeyupdate() bool {
-	if m != nil {
-		return m.Needkeyupdate
+func (x *CheckInResponse) GetNeedkeyupdate() bool {
+	if x != nil {
+		return x.Needkeyupdate
 	}
 	return false
 }
 
-func (m *CheckInResponse) GetNeeddelete() bool {
-	if m != nil {
-		return m.Needdelete
+func (x *CheckInResponse) GetNeeddelete() bool {
+	if x != nil {
+		return x.Needdelete
 	}
 	return false
 }
 
 type PeersResponse struct {
-	Isegressgateway      bool     `protobuf:"varint,1,opt,name=isegressgateway,proto3" json:"isegressgateway,omitempty"`
-	Egressgatewayrange   string   `protobuf:"bytes,2,opt,name=egressgatewayrange,proto3" json:"egressgatewayrange,omitempty"`
-	Ingressgatewayrange  string   `protobuf:"bytes,9,opt,name=ingressgatewayrange,proto3" json:"ingressgatewayrange,omitempty"`
-	Publickey            string   `protobuf:"bytes,5,opt,name=publickey,proto3" json:"publickey,omitempty"`
-	Endpoint             string   `protobuf:"bytes,6,opt,name=endpoint,proto3" json:"endpoint,omitempty"`
-	Address              string   `protobuf:"bytes,3,opt,name=address,proto3" json:"address,omitempty"`
-	Address6             string   `protobuf:"bytes,8,opt,name=address6,proto3" json:"address6,omitempty"`
-	Listenport           int32    `protobuf:"varint,4,opt,name=listenport,proto3" json:"listenport,omitempty"`
-	Localaddress         string   `protobuf:"bytes,7,opt,name=localaddress,proto3" json:"localaddress,omitempty"`
-	Keepalive            int32    `protobuf:"varint,13,opt,name=keepalive,proto3" json:"keepalive,omitempty"`
-	XXX_NoUnkeyedLiteral struct{} `json:"-"`
-	XXX_unrecognized     []byte   `json:"-"`
-	XXX_sizecache        int32    `json:"-"`
-}
-
-func (m *PeersResponse) Reset()         { *m = PeersResponse{} }
-func (m *PeersResponse) String() string { return proto.CompactTextString(m) }
-func (*PeersResponse) ProtoMessage()    {}
-func (*PeersResponse) Descriptor() ([]byte, []int) {
-	return fileDescriptor_d13bd996b67da4ef, []int{4}
-}
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
 
-func (m *PeersResponse) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_PeersResponse.Unmarshal(m, b)
-}
-func (m *PeersResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_PeersResponse.Marshal(b, m, deterministic)
+	Isegressgateway     bool   `protobuf:"varint,1,opt,name=isegressgateway,proto3" json:"isegressgateway,omitempty"`
+	Egressgatewayrange  string `protobuf:"bytes,2,opt,name=egressgatewayrange,proto3" json:"egressgatewayrange,omitempty"`
+	Ingressgatewayrange string `protobuf:"bytes,9,opt,name=ingressgatewayrange,proto3" json:"ingressgatewayrange,omitempty"`
+	Publickey           string `protobuf:"bytes,5,opt,name=publickey,proto3" json:"publickey,omitempty"`
+	Endpoint            string `protobuf:"bytes,6,opt,name=endpoint,proto3" json:"endpoint,omitempty"`
+	Address             string `protobuf:"bytes,3,opt,name=address,proto3" json:"address,omitempty"`
+	Address6            string `protobuf:"bytes,8,opt,name=address6,proto3" json:"address6,omitempty"`
+	Listenport          int32  `protobuf:"varint,4,opt,name=listenport,proto3" json:"listenport,omitempty"`
+	Localaddress        string `protobuf:"bytes,7,opt,name=localaddress,proto3" json:"localaddress,omitempty"`
+	Keepalive           int32  `protobuf:"varint,13,opt,name=keepalive,proto3" json:"keepalive,omitempty"`
 }
-func (m *PeersResponse) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_PeersResponse.Merge(m, src)
+
+func (x *PeersResponse) Reset() {
+	*x = PeersResponse{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_grpc_node_proto_msgTypes[4]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
-func (m *PeersResponse) XXX_Size() int {
-	return xxx_messageInfo_PeersResponse.Size(m)
+
+func (x *PeersResponse) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
-func (m *PeersResponse) XXX_DiscardUnknown() {
-	xxx_messageInfo_PeersResponse.DiscardUnknown(m)
+
+func (*PeersResponse) ProtoMessage() {}
+
+func (x *PeersResponse) ProtoReflect() protoreflect.Message {
+	mi := &file_grpc_node_proto_msgTypes[4]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
 
-var xxx_messageInfo_PeersResponse proto.InternalMessageInfo
+// Deprecated: Use PeersResponse.ProtoReflect.Descriptor instead.
+func (*PeersResponse) Descriptor() ([]byte, []int) {
+	return file_grpc_node_proto_rawDescGZIP(), []int{4}
+}
 
-func (m *PeersResponse) GetIsegressgateway() bool {
-	if m != nil {
-		return m.Isegressgateway
+func (x *PeersResponse) GetIsegressgateway() bool {
+	if x != nil {
+		return x.Isegressgateway
 	}
 	return false
 }
 
-func (m *PeersResponse) GetEgressgatewayrange() string {
-	if m != nil {
-		return m.Egressgatewayrange
+func (x *PeersResponse) GetEgressgatewayrange() string {
+	if x != nil {
+		return x.Egressgatewayrange
 	}
 	return ""
 }
 
-func (m *PeersResponse) GetIngressgatewayrange() string {
-	if m != nil {
-		return m.Ingressgatewayrange
+func (x *PeersResponse) GetIngressgatewayrange() string {
+	if x != nil {
+		return x.Ingressgatewayrange
 	}
 	return ""
 }
 
-func (m *PeersResponse) GetPublickey() string {
-	if m != nil {
-		return m.Publickey
+func (x *PeersResponse) GetPublickey() string {
+	if x != nil {
+		return x.Publickey
 	}
 	return ""
 }
 
-func (m *PeersResponse) GetEndpoint() string {
-	if m != nil {
-		return m.Endpoint
+func (x *PeersResponse) GetEndpoint() string {
+	if x != nil {
+		return x.Endpoint
 	}
 	return ""
 }
 
-func (m *PeersResponse) GetAddress() string {
-	if m != nil {
-		return m.Address
+func (x *PeersResponse) GetAddress() string {
+	if x != nil {
+		return x.Address
 	}
 	return ""
 }
 
-func (m *PeersResponse) GetAddress6() string {
-	if m != nil {
-		return m.Address6
+func (x *PeersResponse) GetAddress6() string {
+	if x != nil {
+		return x.Address6
 	}
 	return ""
 }
 
-func (m *PeersResponse) GetListenport() int32 {
-	if m != nil {
-		return m.Listenport
+func (x *PeersResponse) GetListenport() int32 {
+	if x != nil {
+		return x.Listenport
 	}
 	return 0
 }
 
-func (m *PeersResponse) GetLocaladdress() string {
-	if m != nil {
-		return m.Localaddress
+func (x *PeersResponse) GetLocaladdress() string {
+	if x != nil {
+		return x.Localaddress
 	}
 	return ""
 }
 
-func (m *PeersResponse) GetKeepalive() int32 {
-	if m != nil {
-		return m.Keepalive
+func (x *PeersResponse) GetKeepalive() int32 {
+	if x != nil {
+		return x.Keepalive
 	}
 	return 0
 }
 
 type ExtPeersResponse struct {
-	Publickey            string   `protobuf:"bytes,5,opt,name=publickey,proto3" json:"publickey,omitempty"`
-	Endpoint             string   `protobuf:"bytes,6,opt,name=endpoint,proto3" json:"endpoint,omitempty"`
-	Address              string   `protobuf:"bytes,3,opt,name=address,proto3" json:"address,omitempty"`
-	Address6             string   `protobuf:"bytes,8,opt,name=address6,proto3" json:"address6,omitempty"`
-	Listenport           int32    `protobuf:"varint,4,opt,name=listenport,proto3" json:"listenport,omitempty"`
-	Localaddress         string   `protobuf:"bytes,7,opt,name=localaddress,proto3" json:"localaddress,omitempty"`
-	Keepalive            int32    `protobuf:"varint,13,opt,name=keepalive,proto3" json:"keepalive,omitempty"`
-	XXX_NoUnkeyedLiteral struct{} `json:"-"`
-	XXX_unrecognized     []byte   `json:"-"`
-	XXX_sizecache        int32    `json:"-"`
-}
-
-func (m *ExtPeersResponse) Reset()         { *m = ExtPeersResponse{} }
-func (m *ExtPeersResponse) String() string { return proto.CompactTextString(m) }
-func (*ExtPeersResponse) ProtoMessage()    {}
-func (*ExtPeersResponse) Descriptor() ([]byte, []int) {
-	return fileDescriptor_d13bd996b67da4ef, []int{5}
-}
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
 
-func (m *ExtPeersResponse) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_ExtPeersResponse.Unmarshal(m, b)
-}
-func (m *ExtPeersResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_ExtPeersResponse.Marshal(b, m, deterministic)
+	Publickey    string `protobuf:"bytes,5,opt,name=publickey,proto3" json:"publickey,omitempty"`
+	Endpoint     string `protobuf:"bytes,6,opt,name=endpoint,proto3" json:"endpoint,omitempty"`
+	Address      string `protobuf:"bytes,3,opt,name=address,proto3" json:"address,omitempty"`
+	Address6     string `protobuf:"bytes,8,opt,name=address6,proto3" json:"address6,omitempty"`
+	Listenport   int32  `protobuf:"varint,4,opt,name=listenport,proto3" json:"listenport,omitempty"`
+	Localaddress string `protobuf:"bytes,7,opt,name=localaddress,proto3" json:"localaddress,omitempty"`
+	Keepalive    int32  `protobuf:"varint,13,opt,name=keepalive,proto3" json:"keepalive,omitempty"`
 }
-func (m *ExtPeersResponse) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_ExtPeersResponse.Merge(m, src)
+
+func (x *ExtPeersResponse) Reset() {
+	*x = ExtPeersResponse{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_grpc_node_proto_msgTypes[5]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
-func (m *ExtPeersResponse) XXX_Size() int {
-	return xxx_messageInfo_ExtPeersResponse.Size(m)
+
+func (x *ExtPeersResponse) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
-func (m *ExtPeersResponse) XXX_DiscardUnknown() {
-	xxx_messageInfo_ExtPeersResponse.DiscardUnknown(m)
+
+func (*ExtPeersResponse) ProtoMessage() {}
+
+func (x *ExtPeersResponse) ProtoReflect() protoreflect.Message {
+	mi := &file_grpc_node_proto_msgTypes[5]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
 
-var xxx_messageInfo_ExtPeersResponse proto.InternalMessageInfo
+// Deprecated: Use ExtPeersResponse.ProtoReflect.Descriptor instead.
+func (*ExtPeersResponse) Descriptor() ([]byte, []int) {
+	return file_grpc_node_proto_rawDescGZIP(), []int{5}
+}
 
-func (m *ExtPeersResponse) GetPublickey() string {
-	if m != nil {
-		return m.Publickey
+func (x *ExtPeersResponse) GetPublickey() string {
+	if x != nil {
+		return x.Publickey
 	}
 	return ""
 }
 
-func (m *ExtPeersResponse) GetEndpoint() string {
-	if m != nil {
-		return m.Endpoint
+func (x *ExtPeersResponse) GetEndpoint() string {
+	if x != nil {
+		return x.Endpoint
 	}
 	return ""
 }
 
-func (m *ExtPeersResponse) GetAddress() string {
-	if m != nil {
-		return m.Address
+func (x *ExtPeersResponse) GetAddress() string {
+	if x != nil {
+		return x.Address
 	}
 	return ""
 }
 
-func (m *ExtPeersResponse) GetAddress6() string {
-	if m != nil {
-		return m.Address6
+func (x *ExtPeersResponse) GetAddress6() string {
+	if x != nil {
+		return x.Address6
 	}
 	return ""
 }
 
-func (m *ExtPeersResponse) GetListenport() int32 {
-	if m != nil {
-		return m.Listenport
+func (x *ExtPeersResponse) GetListenport() int32 {
+	if x != nil {
+		return x.Listenport
 	}
 	return 0
 }
 
-func (m *ExtPeersResponse) GetLocaladdress() string {
-	if m != nil {
-		return m.Localaddress
+func (x *ExtPeersResponse) GetLocaladdress() string {
+	if x != nil {
+		return x.Localaddress
 	}
 	return ""
 }
 
-func (m *ExtPeersResponse) GetKeepalive() int32 {
-	if m != nil {
-		return m.Keepalive
+func (x *ExtPeersResponse) GetKeepalive() int32 {
+	if x != nil {
+		return x.Keepalive
 	}
 	return 0
 }
 
 type Client struct {
-	Privatekey           string   `protobuf:"bytes,1,opt,name=privatekey,proto3" json:"privatekey,omitempty"`
-	Publickey            string   `protobuf:"bytes,2,opt,name=publickey,proto3" json:"publickey,omitempty"`
-	Accesskey            string   `protobuf:"bytes,3,opt,name=accesskey,proto3" json:"accesskey,omitempty"`
-	Address              string   `protobuf:"bytes,4,opt,name=address,proto3" json:"address,omitempty"`
-	Address6             string   `protobuf:"bytes,5,opt,name=address6,proto3" json:"address6,omitempty"`
-	Serverwgendpoint     string   `protobuf:"bytes,6,opt,name=serverwgendpoint,proto3" json:"serverwgendpoint,omitempty"`
-	Serverport           string   `protobuf:"bytes,7,opt,name=serverport,proto3" json:"serverport,omitempty"`
-	Serverkey            string   `protobuf:"bytes,8,opt,name=serverkey,proto3" json:"serverkey,omitempty"`
-	XXX_NoUnkeyedLiteral struct{} `json:"-"`
-	XXX_unrecognized     []byte   `json:"-"`
-	XXX_sizecache        int32    `json:"-"`
-}
-
-func (m *Client) Reset()         { *m = Client{} }
-func (m *Client) String() string { return proto.CompactTextString(m) }
-func (*Client) ProtoMessage()    {}
-func (*Client) Descriptor() ([]byte, []int) {
-	return fileDescriptor_d13bd996b67da4ef, []int{6}
-}
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
 
-func (m *Client) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_Client.Unmarshal(m, b)
+	Privatekey       string `protobuf:"bytes,1,opt,name=privatekey,proto3" json:"privatekey,omitempty"`
+	Publickey        string `protobuf:"bytes,2,opt,name=publickey,proto3" json:"publickey,omitempty"`
+	Accesskey        string `protobuf:"bytes,3,opt,name=accesskey,proto3" json:"accesskey,omitempty"`
+	Address          string `protobuf:"bytes,4,opt,name=address,proto3" json:"address,omitempty"`
+	Address6         string `protobuf:"bytes,5,opt,name=address6,proto3" json:"address6,omitempty"`
+	Serverwgendpoint string `protobuf:"bytes,6,opt,name=serverwgendpoint,proto3" json:"serverwgendpoint,omitempty"`
+	Serverport       string `protobuf:"bytes,7,opt,name=serverport,proto3" json:"serverport,omitempty"`
+	Serverkey        string `protobuf:"bytes,8,opt,name=serverkey,proto3" json:"serverkey,omitempty"`
 }
-func (m *Client) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_Client.Marshal(b, m, deterministic)
-}
-func (m *Client) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_Client.Merge(m, src)
+
+func (x *Client) Reset() {
+	*x = Client{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_grpc_node_proto_msgTypes[6]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
-func (m *Client) XXX_Size() int {
-	return xxx_messageInfo_Client.Size(m)
+
+func (x *Client) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
-func (m *Client) XXX_DiscardUnknown() {
-	xxx_messageInfo_Client.DiscardUnknown(m)
+
+func (*Client) ProtoMessage() {}
+
+func (x *Client) ProtoReflect() protoreflect.Message {
+	mi := &file_grpc_node_proto_msgTypes[6]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
 
-var xxx_messageInfo_Client proto.InternalMessageInfo
+// Deprecated: Use Client.ProtoReflect.Descriptor instead.
+func (*Client) Descriptor() ([]byte, []int) {
+	return file_grpc_node_proto_rawDescGZIP(), []int{6}
+}
 
-func (m *Client) GetPrivatekey() string {
-	if m != nil {
-		return m.Privatekey
+func (x *Client) GetPrivatekey() string {
+	if x != nil {
+		return x.Privatekey
 	}
 	return ""
 }
 
-func (m *Client) GetPublickey() string {
-	if m != nil {
-		return m.Publickey
+func (x *Client) GetPublickey() string {
+	if x != nil {
+		return x.Publickey
 	}
 	return ""
 }
 
-func (m *Client) GetAccesskey() string {
-	if m != nil {
-		return m.Accesskey
+func (x *Client) GetAccesskey() string {
+	if x != nil {
+		return x.Accesskey
 	}
 	return ""
 }
 
-func (m *Client) GetAddress() string {
-	if m != nil {
-		return m.Address
+func (x *Client) GetAddress() string {
+	if x != nil {
+		return x.Address
 	}
 	return ""
 }
 
-func (m *Client) GetAddress6() string {
-	if m != nil {
-		return m.Address6
+func (x *Client) GetAddress6() string {
+	if x != nil {
+		return x.Address6
 	}
 	return ""
 }
 
-func (m *Client) GetServerwgendpoint() string {
-	if m != nil {
-		return m.Serverwgendpoint
+func (x *Client) GetServerwgendpoint() string {
+	if x != nil {
+		return x.Serverwgendpoint
 	}
 	return ""
 }
 
-func (m *Client) GetServerport() string {
-	if m != nil {
-		return m.Serverport
+func (x *Client) GetServerport() string {
+	if x != nil {
+		return x.Serverport
 	}
 	return ""
 }
 
-func (m *Client) GetServerkey() string {
-	if m != nil {
-		return m.Serverkey
+func (x *Client) GetServerkey() string {
+	if x != nil {
+		return x.Serverkey
 	}
 	return ""
 }
 
 type CreateNodeReq struct {
-	Node                 *Node    `protobuf:"bytes,1,opt,name=node,proto3" json:"node,omitempty"`
-	XXX_NoUnkeyedLiteral struct{} `json:"-"`
-	XXX_unrecognized     []byte   `json:"-"`
-	XXX_sizecache        int32    `json:"-"`
-}
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
 
-func (m *CreateNodeReq) Reset()         { *m = CreateNodeReq{} }
-func (m *CreateNodeReq) String() string { return proto.CompactTextString(m) }
-func (*CreateNodeReq) ProtoMessage()    {}
-func (*CreateNodeReq) Descriptor() ([]byte, []int) {
-	return fileDescriptor_d13bd996b67da4ef, []int{7}
+	Node *Node `protobuf:"bytes,1,opt,name=node,proto3" json:"node,omitempty"` // Node id blank
 }
 
-func (m *CreateNodeReq) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_CreateNodeReq.Unmarshal(m, b)
-}
-func (m *CreateNodeReq) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_CreateNodeReq.Marshal(b, m, deterministic)
-}
-func (m *CreateNodeReq) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_CreateNodeReq.Merge(m, src)
+func (x *CreateNodeReq) Reset() {
+	*x = CreateNodeReq{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_grpc_node_proto_msgTypes[7]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
-func (m *CreateNodeReq) XXX_Size() int {
-	return xxx_messageInfo_CreateNodeReq.Size(m)
+
+func (x *CreateNodeReq) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
-func (m *CreateNodeReq) XXX_DiscardUnknown() {
-	xxx_messageInfo_CreateNodeReq.DiscardUnknown(m)
+
+func (*CreateNodeReq) ProtoMessage() {}
+
+func (x *CreateNodeReq) ProtoReflect() protoreflect.Message {
+	mi := &file_grpc_node_proto_msgTypes[7]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
 
-var xxx_messageInfo_CreateNodeReq proto.InternalMessageInfo
+// Deprecated: Use CreateNodeReq.ProtoReflect.Descriptor instead.
+func (*CreateNodeReq) Descriptor() ([]byte, []int) {
+	return file_grpc_node_proto_rawDescGZIP(), []int{7}
+}
 
-func (m *CreateNodeReq) GetNode() *Node {
-	if m != nil {
-		return m.Node
+func (x *CreateNodeReq) GetNode() *Node {
+	if x != nil {
+		return x.Node
 	}
 	return nil
 }
 
 type CreateNodeRes struct {
-	Node                 *Node    `protobuf:"bytes,1,opt,name=node,proto3" json:"node,omitempty"`
-	XXX_NoUnkeyedLiteral struct{} `json:"-"`
-	XXX_unrecognized     []byte   `json:"-"`
-	XXX_sizecache        int32    `json:"-"`
-}
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
 
-func (m *CreateNodeRes) Reset()         { *m = CreateNodeRes{} }
-func (m *CreateNodeRes) String() string { return proto.CompactTextString(m) }
-func (*CreateNodeRes) ProtoMessage()    {}
-func (*CreateNodeRes) Descriptor() ([]byte, []int) {
-	return fileDescriptor_d13bd996b67da4ef, []int{8}
+	Node *Node `protobuf:"bytes,1,opt,name=node,proto3" json:"node,omitempty"` // Node id filled in
 }
 
-func (m *CreateNodeRes) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_CreateNodeRes.Unmarshal(m, b)
-}
-func (m *CreateNodeRes) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_CreateNodeRes.Marshal(b, m, deterministic)
-}
-func (m *CreateNodeRes) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_CreateNodeRes.Merge(m, src)
+func (x *CreateNodeRes) Reset() {
+	*x = CreateNodeRes{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_grpc_node_proto_msgTypes[8]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
-func (m *CreateNodeRes) XXX_Size() int {
-	return xxx_messageInfo_CreateNodeRes.Size(m)
+
+func (x *CreateNodeRes) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
-func (m *CreateNodeRes) XXX_DiscardUnknown() {
-	xxx_messageInfo_CreateNodeRes.DiscardUnknown(m)
+
+func (*CreateNodeRes) ProtoMessage() {}
+
+func (x *CreateNodeRes) ProtoReflect() protoreflect.Message {
+	mi := &file_grpc_node_proto_msgTypes[8]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
 
-var xxx_messageInfo_CreateNodeRes proto.InternalMessageInfo
+// Deprecated: Use CreateNodeRes.ProtoReflect.Descriptor instead.
+func (*CreateNodeRes) Descriptor() ([]byte, []int) {
+	return file_grpc_node_proto_rawDescGZIP(), []int{8}
+}
 
-func (m *CreateNodeRes) GetNode() *Node {
-	if m != nil {
-		return m.Node
+func (x *CreateNodeRes) GetNode() *Node {
+	if x != nil {
+		return x.Node
 	}
 	return nil
 }
 
 type UpdateNodeReq struct {
-	Node                 *Node    `protobuf:"bytes,1,opt,name=node,proto3" json:"node,omitempty"`
-	XXX_NoUnkeyedLiteral struct{} `json:"-"`
-	XXX_unrecognized     []byte   `json:"-"`
-	XXX_sizecache        int32    `json:"-"`
-}
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
 
-func (m *UpdateNodeReq) Reset()         { *m = UpdateNodeReq{} }
-func (m *UpdateNodeReq) String() string { return proto.CompactTextString(m) }
-func (*UpdateNodeReq) ProtoMessage()    {}
-func (*UpdateNodeReq) Descriptor() ([]byte, []int) {
-	return fileDescriptor_d13bd996b67da4ef, []int{9}
+	Node *Node `protobuf:"bytes,1,opt,name=node,proto3" json:"node,omitempty"`
 }
 
-func (m *UpdateNodeReq) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_UpdateNodeReq.Unmarshal(m, b)
-}
-func (m *UpdateNodeReq) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_UpdateNodeReq.Marshal(b, m, deterministic)
-}
-func (m *UpdateNodeReq) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_UpdateNodeReq.Merge(m, src)
+func (x *UpdateNodeReq) Reset() {
+	*x = UpdateNodeReq{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_grpc_node_proto_msgTypes[9]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
-func (m *UpdateNodeReq) XXX_Size() int {
-	return xxx_messageInfo_UpdateNodeReq.Size(m)
+
+func (x *UpdateNodeReq) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
-func (m *UpdateNodeReq) XXX_DiscardUnknown() {
-	xxx_messageInfo_UpdateNodeReq.DiscardUnknown(m)
+
+func (*UpdateNodeReq) ProtoMessage() {}
+
+func (x *UpdateNodeReq) ProtoReflect() protoreflect.Message {
+	mi := &file_grpc_node_proto_msgTypes[9]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
 
-var xxx_messageInfo_UpdateNodeReq proto.InternalMessageInfo
+// Deprecated: Use UpdateNodeReq.ProtoReflect.Descriptor instead.
+func (*UpdateNodeReq) Descriptor() ([]byte, []int) {
+	return file_grpc_node_proto_rawDescGZIP(), []int{9}
+}
 
-func (m *UpdateNodeReq) GetNode() *Node {
-	if m != nil {
-		return m.Node
+func (x *UpdateNodeReq) GetNode() *Node {
+	if x != nil {
+		return x.Node
 	}
 	return nil
 }
 
 type UpdateNodeRes struct {
-	Node                 *Node    `protobuf:"bytes,1,opt,name=node,proto3" json:"node,omitempty"`
-	XXX_NoUnkeyedLiteral struct{} `json:"-"`
-	XXX_unrecognized     []byte   `json:"-"`
-	XXX_sizecache        int32    `json:"-"`
-}
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
 
-func (m *UpdateNodeRes) Reset()         { *m = UpdateNodeRes{} }
-func (m *UpdateNodeRes) String() string { return proto.CompactTextString(m) }
-func (*UpdateNodeRes) ProtoMessage()    {}
-func (*UpdateNodeRes) Descriptor() ([]byte, []int) {
-	return fileDescriptor_d13bd996b67da4ef, []int{10}
+	Node *Node `protobuf:"bytes,1,opt,name=node,proto3" json:"node,omitempty"`
 }
 
-func (m *UpdateNodeRes) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_UpdateNodeRes.Unmarshal(m, b)
-}
-func (m *UpdateNodeRes) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_UpdateNodeRes.Marshal(b, m, deterministic)
-}
-func (m *UpdateNodeRes) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_UpdateNodeRes.Merge(m, src)
+func (x *UpdateNodeRes) Reset() {
+	*x = UpdateNodeRes{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_grpc_node_proto_msgTypes[10]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
-func (m *UpdateNodeRes) XXX_Size() int {
-	return xxx_messageInfo_UpdateNodeRes.Size(m)
+
+func (x *UpdateNodeRes) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
-func (m *UpdateNodeRes) XXX_DiscardUnknown() {
-	xxx_messageInfo_UpdateNodeRes.DiscardUnknown(m)
+
+func (*UpdateNodeRes) ProtoMessage() {}
+
+func (x *UpdateNodeRes) ProtoReflect() protoreflect.Message {
+	mi := &file_grpc_node_proto_msgTypes[10]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
 
-var xxx_messageInfo_UpdateNodeRes proto.InternalMessageInfo
+// Deprecated: Use UpdateNodeRes.ProtoReflect.Descriptor instead.
+func (*UpdateNodeRes) Descriptor() ([]byte, []int) {
+	return file_grpc_node_proto_rawDescGZIP(), []int{10}
+}
 
-func (m *UpdateNodeRes) GetNode() *Node {
-	if m != nil {
-		return m.Node
+func (x *UpdateNodeRes) GetNode() *Node {
+	if x != nil {
+		return x.Node
 	}
 	return nil
 }
 
 type ReadNodeReq struct {
-	Macaddress           string   `protobuf:"bytes,1,opt,name=macaddress,proto3" json:"macaddress,omitempty"`
-	Network              string   `protobuf:"bytes,2,opt,name=network,proto3" json:"network,omitempty"`
-	XXX_NoUnkeyedLiteral struct{} `json:"-"`
-	XXX_unrecognized     []byte   `json:"-"`
-	XXX_sizecache        int32    `json:"-"`
-}
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
 
-func (m *ReadNodeReq) Reset()         { *m = ReadNodeReq{} }
-func (m *ReadNodeReq) String() string { return proto.CompactTextString(m) }
-func (*ReadNodeReq) ProtoMessage()    {}
-func (*ReadNodeReq) Descriptor() ([]byte, []int) {
-	return fileDescriptor_d13bd996b67da4ef, []int{11}
+	Macaddress string `protobuf:"bytes,1,opt,name=macaddress,proto3" json:"macaddress,omitempty"`
+	Network    string `protobuf:"bytes,2,opt,name=network,proto3" json:"network,omitempty"`
 }
 
-func (m *ReadNodeReq) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_ReadNodeReq.Unmarshal(m, b)
-}
-func (m *ReadNodeReq) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_ReadNodeReq.Marshal(b, m, deterministic)
-}
-func (m *ReadNodeReq) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_ReadNodeReq.Merge(m, src)
+func (x *ReadNodeReq) Reset() {
+	*x = ReadNodeReq{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_grpc_node_proto_msgTypes[11]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
-func (m *ReadNodeReq) XXX_Size() int {
-	return xxx_messageInfo_ReadNodeReq.Size(m)
+
+func (x *ReadNodeReq) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
-func (m *ReadNodeReq) XXX_DiscardUnknown() {
-	xxx_messageInfo_ReadNodeReq.DiscardUnknown(m)
+
+func (*ReadNodeReq) ProtoMessage() {}
+
+func (x *ReadNodeReq) ProtoReflect() protoreflect.Message {
+	mi := &file_grpc_node_proto_msgTypes[11]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
 
-var xxx_messageInfo_ReadNodeReq proto.InternalMessageInfo
+// Deprecated: Use ReadNodeReq.ProtoReflect.Descriptor instead.
+func (*ReadNodeReq) Descriptor() ([]byte, []int) {
+	return file_grpc_node_proto_rawDescGZIP(), []int{11}
+}
 
-func (m *ReadNodeReq) GetMacaddress() string {
-	if m != nil {
-		return m.Macaddress
+func (x *ReadNodeReq) GetMacaddress() string {
+	if x != nil {
+		return x.Macaddress
 	}
 	return ""
 }
 
-func (m *ReadNodeReq) GetNetwork() string {
-	if m != nil {
-		return m.Network
+func (x *ReadNodeReq) GetNetwork() string {
+	if x != nil {
+		return x.Network
 	}
 	return ""
 }
 
 type ReadNodeRes struct {
-	Node                 *Node    `protobuf:"bytes,1,opt,name=node,proto3" json:"node,omitempty"`
-	XXX_NoUnkeyedLiteral struct{} `json:"-"`
-	XXX_unrecognized     []byte   `json:"-"`
-	XXX_sizecache        int32    `json:"-"`
-}
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
 
-func (m *ReadNodeRes) Reset()         { *m = ReadNodeRes{} }
-func (m *ReadNodeRes) String() string { return proto.CompactTextString(m) }
-func (*ReadNodeRes) ProtoMessage()    {}
-func (*ReadNodeRes) Descriptor() ([]byte, []int) {
-	return fileDescriptor_d13bd996b67da4ef, []int{12}
+	Node *Node `protobuf:"bytes,1,opt,name=node,proto3" json:"node,omitempty"`
 }
 
-func (m *ReadNodeRes) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_ReadNodeRes.Unmarshal(m, b)
-}
-func (m *ReadNodeRes) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_ReadNodeRes.Marshal(b, m, deterministic)
-}
-func (m *ReadNodeRes) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_ReadNodeRes.Merge(m, src)
+func (x *ReadNodeRes) Reset() {
+	*x = ReadNodeRes{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_grpc_node_proto_msgTypes[12]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
-func (m *ReadNodeRes) XXX_Size() int {
-	return xxx_messageInfo_ReadNodeRes.Size(m)
+
+func (x *ReadNodeRes) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
-func (m *ReadNodeRes) XXX_DiscardUnknown() {
-	xxx_messageInfo_ReadNodeRes.DiscardUnknown(m)
+
+func (*ReadNodeRes) ProtoMessage() {}
+
+func (x *ReadNodeRes) ProtoReflect() protoreflect.Message {
+	mi := &file_grpc_node_proto_msgTypes[12]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
 
-var xxx_messageInfo_ReadNodeRes proto.InternalMessageInfo
+// Deprecated: Use ReadNodeRes.ProtoReflect.Descriptor instead.
+func (*ReadNodeRes) Descriptor() ([]byte, []int) {
+	return file_grpc_node_proto_rawDescGZIP(), []int{12}
+}
 
-func (m *ReadNodeRes) GetNode() *Node {
-	if m != nil {
-		return m.Node
+func (x *ReadNodeRes) GetNode() *Node {
+	if x != nil {
+		return x.Node
 	}
 	return nil
 }
 
 type DeleteNodeReq struct {
-	Macaddress           string   `protobuf:"bytes,1,opt,name=macaddress,proto3" json:"macaddress,omitempty"`
-	NetworkName          string   `protobuf:"bytes,2,opt,name=networkName,proto3" json:"networkName,omitempty"`
-	XXX_NoUnkeyedLiteral struct{} `json:"-"`
-	XXX_unrecognized     []byte   `json:"-"`
-	XXX_sizecache        int32    `json:"-"`
-}
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
 
-func (m *DeleteNodeReq) Reset()         { *m = DeleteNodeReq{} }
-func (m *DeleteNodeReq) String() string { return proto.CompactTextString(m) }
-func (*DeleteNodeReq) ProtoMessage()    {}
-func (*DeleteNodeReq) Descriptor() ([]byte, []int) {
-	return fileDescriptor_d13bd996b67da4ef, []int{13}
+	Macaddress  string `protobuf:"bytes,1,opt,name=macaddress,proto3" json:"macaddress,omitempty"`
+	NetworkName string `protobuf:"bytes,2,opt,name=networkName,proto3" json:"networkName,omitempty"`
 }
 
-func (m *DeleteNodeReq) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_DeleteNodeReq.Unmarshal(m, b)
-}
-func (m *DeleteNodeReq) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_DeleteNodeReq.Marshal(b, m, deterministic)
-}
-func (m *DeleteNodeReq) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_DeleteNodeReq.Merge(m, src)
+func (x *DeleteNodeReq) Reset() {
+	*x = DeleteNodeReq{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_grpc_node_proto_msgTypes[13]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
-func (m *DeleteNodeReq) XXX_Size() int {
-	return xxx_messageInfo_DeleteNodeReq.Size(m)
+
+func (x *DeleteNodeReq) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
-func (m *DeleteNodeReq) XXX_DiscardUnknown() {
-	xxx_messageInfo_DeleteNodeReq.DiscardUnknown(m)
+
+func (*DeleteNodeReq) ProtoMessage() {}
+
+func (x *DeleteNodeReq) ProtoReflect() protoreflect.Message {
+	mi := &file_grpc_node_proto_msgTypes[13]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
 
-var xxx_messageInfo_DeleteNodeReq proto.InternalMessageInfo
+// Deprecated: Use DeleteNodeReq.ProtoReflect.Descriptor instead.
+func (*DeleteNodeReq) Descriptor() ([]byte, []int) {
+	return file_grpc_node_proto_rawDescGZIP(), []int{13}
+}
 
-func (m *DeleteNodeReq) GetMacaddress() string {
-	if m != nil {
-		return m.Macaddress
+func (x *DeleteNodeReq) GetMacaddress() string {
+	if x != nil {
+		return x.Macaddress
 	}
 	return ""
 }
 
-func (m *DeleteNodeReq) GetNetworkName() string {
-	if m != nil {
-		return m.NetworkName
+func (x *DeleteNodeReq) GetNetworkName() string {
+	if x != nil {
+		return x.NetworkName
 	}
 	return ""
 }
 
 type DeleteNodeRes struct {
-	Success              bool     `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"`
-	XXX_NoUnkeyedLiteral struct{} `json:"-"`
-	XXX_unrecognized     []byte   `json:"-"`
-	XXX_sizecache        int32    `json:"-"`
-}
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
 
-func (m *DeleteNodeRes) Reset()         { *m = DeleteNodeRes{} }
-func (m *DeleteNodeRes) String() string { return proto.CompactTextString(m) }
-func (*DeleteNodeRes) ProtoMessage()    {}
-func (*DeleteNodeRes) Descriptor() ([]byte, []int) {
-	return fileDescriptor_d13bd996b67da4ef, []int{14}
+	Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"`
 }
 
-func (m *DeleteNodeRes) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_DeleteNodeRes.Unmarshal(m, b)
-}
-func (m *DeleteNodeRes) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_DeleteNodeRes.Marshal(b, m, deterministic)
-}
-func (m *DeleteNodeRes) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_DeleteNodeRes.Merge(m, src)
+func (x *DeleteNodeRes) Reset() {
+	*x = DeleteNodeRes{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_grpc_node_proto_msgTypes[14]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
-func (m *DeleteNodeRes) XXX_Size() int {
-	return xxx_messageInfo_DeleteNodeRes.Size(m)
+
+func (x *DeleteNodeRes) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
-func (m *DeleteNodeRes) XXX_DiscardUnknown() {
-	xxx_messageInfo_DeleteNodeRes.DiscardUnknown(m)
+
+func (*DeleteNodeRes) ProtoMessage() {}
+
+func (x *DeleteNodeRes) ProtoReflect() protoreflect.Message {
+	mi := &file_grpc_node_proto_msgTypes[14]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
 
-var xxx_messageInfo_DeleteNodeRes proto.InternalMessageInfo
+// Deprecated: Use DeleteNodeRes.ProtoReflect.Descriptor instead.
+func (*DeleteNodeRes) Descriptor() ([]byte, []int) {
+	return file_grpc_node_proto_rawDescGZIP(), []int{14}
+}
 
-func (m *DeleteNodeRes) GetSuccess() bool {
-	if m != nil {
-		return m.Success
+func (x *DeleteNodeRes) GetSuccess() bool {
+	if x != nil {
+		return x.Success
 	}
 	return false
 }
 
 type GetPeersReq struct {
-	Macaddress           string   `protobuf:"bytes,1,opt,name=macaddress,proto3" json:"macaddress,omitempty"`
-	Network              string   `protobuf:"bytes,2,opt,name=network,proto3" json:"network,omitempty"`
-	XXX_NoUnkeyedLiteral struct{} `json:"-"`
-	XXX_unrecognized     []byte   `json:"-"`
-	XXX_sizecache        int32    `json:"-"`
-}
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
 
-func (m *GetPeersReq) Reset()         { *m = GetPeersReq{} }
-func (m *GetPeersReq) String() string { return proto.CompactTextString(m) }
-func (*GetPeersReq) ProtoMessage()    {}
-func (*GetPeersReq) Descriptor() ([]byte, []int) {
-	return fileDescriptor_d13bd996b67da4ef, []int{15}
+	Macaddress string `protobuf:"bytes,1,opt,name=macaddress,proto3" json:"macaddress,omitempty"`
+	Network    string `protobuf:"bytes,2,opt,name=network,proto3" json:"network,omitempty"`
 }
 
-func (m *GetPeersReq) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_GetPeersReq.Unmarshal(m, b)
-}
-func (m *GetPeersReq) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_GetPeersReq.Marshal(b, m, deterministic)
-}
-func (m *GetPeersReq) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_GetPeersReq.Merge(m, src)
+func (x *GetPeersReq) Reset() {
+	*x = GetPeersReq{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_grpc_node_proto_msgTypes[15]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
-func (m *GetPeersReq) XXX_Size() int {
-	return xxx_messageInfo_GetPeersReq.Size(m)
+
+func (x *GetPeersReq) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
-func (m *GetPeersReq) XXX_DiscardUnknown() {
-	xxx_messageInfo_GetPeersReq.DiscardUnknown(m)
+
+func (*GetPeersReq) ProtoMessage() {}
+
+func (x *GetPeersReq) ProtoReflect() protoreflect.Message {
+	mi := &file_grpc_node_proto_msgTypes[15]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
 
-var xxx_messageInfo_GetPeersReq proto.InternalMessageInfo
+// Deprecated: Use GetPeersReq.ProtoReflect.Descriptor instead.
+func (*GetPeersReq) Descriptor() ([]byte, []int) {
+	return file_grpc_node_proto_rawDescGZIP(), []int{15}
+}
 
-func (m *GetPeersReq) GetMacaddress() string {
-	if m != nil {
-		return m.Macaddress
+func (x *GetPeersReq) GetMacaddress() string {
+	if x != nil {
+		return x.Macaddress
 	}
 	return ""
 }
 
-func (m *GetPeersReq) GetNetwork() string {
-	if m != nil {
-		return m.Network
+func (x *GetPeersReq) GetNetwork() string {
+	if x != nil {
+		return x.Network
 	}
 	return ""
 }
 
 type GetExtPeersReq struct {
-	Macaddress           string   `protobuf:"bytes,1,opt,name=macaddress,proto3" json:"macaddress,omitempty"`
-	Network              string   `protobuf:"bytes,2,opt,name=network,proto3" json:"network,omitempty"`
-	XXX_NoUnkeyedLiteral struct{} `json:"-"`
-	XXX_unrecognized     []byte   `json:"-"`
-	XXX_sizecache        int32    `json:"-"`
-}
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
 
-func (m *GetExtPeersReq) Reset()         { *m = GetExtPeersReq{} }
-func (m *GetExtPeersReq) String() string { return proto.CompactTextString(m) }
-func (*GetExtPeersReq) ProtoMessage()    {}
-func (*GetExtPeersReq) Descriptor() ([]byte, []int) {
-	return fileDescriptor_d13bd996b67da4ef, []int{16}
+	Macaddress string `protobuf:"bytes,1,opt,name=macaddress,proto3" json:"macaddress,omitempty"`
+	Network    string `protobuf:"bytes,2,opt,name=network,proto3" json:"network,omitempty"`
 }
 
-func (m *GetExtPeersReq) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_GetExtPeersReq.Unmarshal(m, b)
-}
-func (m *GetExtPeersReq) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_GetExtPeersReq.Marshal(b, m, deterministic)
-}
-func (m *GetExtPeersReq) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_GetExtPeersReq.Merge(m, src)
+func (x *GetExtPeersReq) Reset() {
+	*x = GetExtPeersReq{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_grpc_node_proto_msgTypes[16]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
-func (m *GetExtPeersReq) XXX_Size() int {
-	return xxx_messageInfo_GetExtPeersReq.Size(m)
+
+func (x *GetExtPeersReq) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
-func (m *GetExtPeersReq) XXX_DiscardUnknown() {
-	xxx_messageInfo_GetExtPeersReq.DiscardUnknown(m)
+
+func (*GetExtPeersReq) ProtoMessage() {}
+
+func (x *GetExtPeersReq) ProtoReflect() protoreflect.Message {
+	mi := &file_grpc_node_proto_msgTypes[16]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
 
-var xxx_messageInfo_GetExtPeersReq proto.InternalMessageInfo
+// Deprecated: Use GetExtPeersReq.ProtoReflect.Descriptor instead.
+func (*GetExtPeersReq) Descriptor() ([]byte, []int) {
+	return file_grpc_node_proto_rawDescGZIP(), []int{16}
+}
 
-func (m *GetExtPeersReq) GetMacaddress() string {
-	if m != nil {
-		return m.Macaddress
+func (x *GetExtPeersReq) GetMacaddress() string {
+	if x != nil {
+		return x.Macaddress
 	}
 	return ""
 }
 
-func (m *GetExtPeersReq) GetNetwork() string {
-	if m != nil {
-		return m.Network
+func (x *GetExtPeersReq) GetNetwork() string {
+	if x != nil {
+		return x.Network
 	}
 	return ""
 }
 
 type GetPeersRes struct {
-	Peers                *PeersResponse `protobuf:"bytes,1,opt,name=peers,proto3" json:"peers,omitempty"`
-	XXX_NoUnkeyedLiteral struct{}       `json:"-"`
-	XXX_unrecognized     []byte         `json:"-"`
-	XXX_sizecache        int32          `json:"-"`
-}
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
 
-func (m *GetPeersRes) Reset()         { *m = GetPeersRes{} }
-func (m *GetPeersRes) String() string { return proto.CompactTextString(m) }
-func (*GetPeersRes) ProtoMessage()    {}
-func (*GetPeersRes) Descriptor() ([]byte, []int) {
-	return fileDescriptor_d13bd996b67da4ef, []int{17}
+	Peers *PeersResponse `protobuf:"bytes,1,opt,name=peers,proto3" json:"peers,omitempty"`
 }
 
-func (m *GetPeersRes) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_GetPeersRes.Unmarshal(m, b)
-}
-func (m *GetPeersRes) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_GetPeersRes.Marshal(b, m, deterministic)
-}
-func (m *GetPeersRes) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_GetPeersRes.Merge(m, src)
+func (x *GetPeersRes) Reset() {
+	*x = GetPeersRes{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_grpc_node_proto_msgTypes[17]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
-func (m *GetPeersRes) XXX_Size() int {
-	return xxx_messageInfo_GetPeersRes.Size(m)
+
+func (x *GetPeersRes) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
-func (m *GetPeersRes) XXX_DiscardUnknown() {
-	xxx_messageInfo_GetPeersRes.DiscardUnknown(m)
+
+func (*GetPeersRes) ProtoMessage() {}
+
+func (x *GetPeersRes) ProtoReflect() protoreflect.Message {
+	mi := &file_grpc_node_proto_msgTypes[17]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
 
-var xxx_messageInfo_GetPeersRes proto.InternalMessageInfo
+// Deprecated: Use GetPeersRes.ProtoReflect.Descriptor instead.
+func (*GetPeersRes) Descriptor() ([]byte, []int) {
+	return file_grpc_node_proto_rawDescGZIP(), []int{17}
+}
 
-func (m *GetPeersRes) GetPeers() *PeersResponse {
-	if m != nil {
-		return m.Peers
+func (x *GetPeersRes) GetPeers() *PeersResponse {
+	if x != nil {
+		return x.Peers
 	}
 	return nil
 }
 
 type GetExtPeersRes struct {
-	Extpeers             *ExtPeersResponse `protobuf:"bytes,1,opt,name=extpeers,proto3" json:"extpeers,omitempty"`
-	XXX_NoUnkeyedLiteral struct{}          `json:"-"`
-	XXX_unrecognized     []byte            `json:"-"`
-	XXX_sizecache        int32             `json:"-"`
-}
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
 
-func (m *GetExtPeersRes) Reset()         { *m = GetExtPeersRes{} }
-func (m *GetExtPeersRes) String() string { return proto.CompactTextString(m) }
-func (*GetExtPeersRes) ProtoMessage()    {}
-func (*GetExtPeersRes) Descriptor() ([]byte, []int) {
-	return fileDescriptor_d13bd996b67da4ef, []int{18}
+	Extpeers *ExtPeersResponse `protobuf:"bytes,1,opt,name=extpeers,proto3" json:"extpeers,omitempty"`
 }
 
-func (m *GetExtPeersRes) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_GetExtPeersRes.Unmarshal(m, b)
-}
-func (m *GetExtPeersRes) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_GetExtPeersRes.Marshal(b, m, deterministic)
-}
-func (m *GetExtPeersRes) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_GetExtPeersRes.Merge(m, src)
+func (x *GetExtPeersRes) Reset() {
+	*x = GetExtPeersRes{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_grpc_node_proto_msgTypes[18]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
-func (m *GetExtPeersRes) XXX_Size() int {
-	return xxx_messageInfo_GetExtPeersRes.Size(m)
+
+func (x *GetExtPeersRes) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
-func (m *GetExtPeersRes) XXX_DiscardUnknown() {
-	xxx_messageInfo_GetExtPeersRes.DiscardUnknown(m)
+
+func (*GetExtPeersRes) ProtoMessage() {}
+
+func (x *GetExtPeersRes) ProtoReflect() protoreflect.Message {
+	mi := &file_grpc_node_proto_msgTypes[18]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
 
-var xxx_messageInfo_GetExtPeersRes proto.InternalMessageInfo
+// Deprecated: Use GetExtPeersRes.ProtoReflect.Descriptor instead.
+func (*GetExtPeersRes) Descriptor() ([]byte, []int) {
+	return file_grpc_node_proto_rawDescGZIP(), []int{18}
+}
 
-func (m *GetExtPeersRes) GetExtpeers() *ExtPeersResponse {
-	if m != nil {
-		return m.Extpeers
+func (x *GetExtPeersRes) GetExtpeers() *ExtPeersResponse {
+	if x != nil {
+		return x.Extpeers
 	}
 	return nil
 }
 
 type CheckInReq struct {
-	Node                 *Node    `protobuf:"bytes,1,opt,name=node,proto3" json:"node,omitempty"`
-	XXX_NoUnkeyedLiteral struct{} `json:"-"`
-	XXX_unrecognized     []byte   `json:"-"`
-	XXX_sizecache        int32    `json:"-"`
-}
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
 
-func (m *CheckInReq) Reset()         { *m = CheckInReq{} }
-func (m *CheckInReq) String() string { return proto.CompactTextString(m) }
-func (*CheckInReq) ProtoMessage()    {}
-func (*CheckInReq) Descriptor() ([]byte, []int) {
-	return fileDescriptor_d13bd996b67da4ef, []int{19}
+	Node *Node `protobuf:"bytes,1,opt,name=node,proto3" json:"node,omitempty"` //   bool postchanges = 2;
 }
 
-func (m *CheckInReq) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_CheckInReq.Unmarshal(m, b)
-}
-func (m *CheckInReq) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_CheckInReq.Marshal(b, m, deterministic)
-}
-func (m *CheckInReq) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_CheckInReq.Merge(m, src)
+func (x *CheckInReq) Reset() {
+	*x = CheckInReq{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_grpc_node_proto_msgTypes[19]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
-func (m *CheckInReq) XXX_Size() int {
-	return xxx_messageInfo_CheckInReq.Size(m)
+
+func (x *CheckInReq) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
-func (m *CheckInReq) XXX_DiscardUnknown() {
-	xxx_messageInfo_CheckInReq.DiscardUnknown(m)
+
+func (*CheckInReq) ProtoMessage() {}
+
+func (x *CheckInReq) ProtoReflect() protoreflect.Message {
+	mi := &file_grpc_node_proto_msgTypes[19]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
 
-var xxx_messageInfo_CheckInReq proto.InternalMessageInfo
+// Deprecated: Use CheckInReq.ProtoReflect.Descriptor instead.
+func (*CheckInReq) Descriptor() ([]byte, []int) {
+	return file_grpc_node_proto_rawDescGZIP(), []int{19}
+}
 
-func (m *CheckInReq) GetNode() *Node {
-	if m != nil {
-		return m.Node
+func (x *CheckInReq) GetNode() *Node {
+	if x != nil {
+		return x.Node
 	}
 	return nil
 }
 
 type CheckInRes struct {
-	Checkinresponse      *CheckInResponse `protobuf:"bytes,1,opt,name=checkinresponse,proto3" json:"checkinresponse,omitempty"`
-	XXX_NoUnkeyedLiteral struct{}         `json:"-"`
-	XXX_unrecognized     []byte           `json:"-"`
-	XXX_sizecache        int32            `json:"-"`
-}
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
 
-func (m *CheckInRes) Reset()         { *m = CheckInRes{} }
-func (m *CheckInRes) String() string { return proto.CompactTextString(m) }
-func (*CheckInRes) ProtoMessage()    {}
-func (*CheckInRes) Descriptor() ([]byte, []int) {
-	return fileDescriptor_d13bd996b67da4ef, []int{20}
+	Checkinresponse *CheckInResponse `protobuf:"bytes,1,opt,name=checkinresponse,proto3" json:"checkinresponse,omitempty"`
 }
 
-func (m *CheckInRes) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_CheckInRes.Unmarshal(m, b)
-}
-func (m *CheckInRes) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_CheckInRes.Marshal(b, m, deterministic)
-}
-func (m *CheckInRes) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_CheckInRes.Merge(m, src)
+func (x *CheckInRes) Reset() {
+	*x = CheckInRes{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_grpc_node_proto_msgTypes[20]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
-func (m *CheckInRes) XXX_Size() int {
-	return xxx_messageInfo_CheckInRes.Size(m)
+
+func (x *CheckInRes) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
-func (m *CheckInRes) XXX_DiscardUnknown() {
-	xxx_messageInfo_CheckInRes.DiscardUnknown(m)
+
+func (*CheckInRes) ProtoMessage() {}
+
+func (x *CheckInRes) ProtoReflect() protoreflect.Message {
+	mi := &file_grpc_node_proto_msgTypes[20]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
 
-var xxx_messageInfo_CheckInRes proto.InternalMessageInfo
+// Deprecated: Use CheckInRes.ProtoReflect.Descriptor instead.
+func (*CheckInRes) Descriptor() ([]byte, []int) {
+	return file_grpc_node_proto_rawDescGZIP(), []int{20}
+}
 
-func (m *CheckInRes) GetCheckinresponse() *CheckInResponse {
-	if m != nil {
-		return m.Checkinresponse
+func (x *CheckInRes) GetCheckinresponse() *CheckInResponse {
+	if x != nil {
+		return x.Checkinresponse
 	}
 	return nil
 }
 
-func init() {
-	proto.RegisterType((*LoginRequest)(nil), "node.LoginRequest")
-	proto.RegisterType((*LoginResponse)(nil), "node.LoginResponse")
-	proto.RegisterType((*Node)(nil), "node.Node")
-	proto.RegisterType((*CheckInResponse)(nil), "node.CheckInResponse")
-	proto.RegisterType((*PeersResponse)(nil), "node.PeersResponse")
-	proto.RegisterType((*ExtPeersResponse)(nil), "node.ExtPeersResponse")
-	proto.RegisterType((*Client)(nil), "node.Client")
-	proto.RegisterType((*CreateNodeReq)(nil), "node.CreateNodeReq")
-	proto.RegisterType((*CreateNodeRes)(nil), "node.CreateNodeRes")
-	proto.RegisterType((*UpdateNodeReq)(nil), "node.UpdateNodeReq")
-	proto.RegisterType((*UpdateNodeRes)(nil), "node.UpdateNodeRes")
-	proto.RegisterType((*ReadNodeReq)(nil), "node.ReadNodeReq")
-	proto.RegisterType((*ReadNodeRes)(nil), "node.ReadNodeRes")
-	proto.RegisterType((*DeleteNodeReq)(nil), "node.DeleteNodeReq")
-	proto.RegisterType((*DeleteNodeRes)(nil), "node.DeleteNodeRes")
-	proto.RegisterType((*GetPeersReq)(nil), "node.GetPeersReq")
-	proto.RegisterType((*GetExtPeersReq)(nil), "node.GetExtPeersReq")
-	proto.RegisterType((*GetPeersRes)(nil), "node.GetPeersRes")
-	proto.RegisterType((*GetExtPeersRes)(nil), "node.GetExtPeersRes")
-	proto.RegisterType((*CheckInReq)(nil), "node.CheckInReq")
-	proto.RegisterType((*CheckInRes)(nil), "node.CheckInRes")
-}
-
-func init() { proto.RegisterFile("grpc/node.proto", fileDescriptor_d13bd996b67da4ef) }
-
-var fileDescriptor_d13bd996b67da4ef = []byte{
-	// 1113 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x57, 0x4f, 0x6f, 0x23, 0x35,
-	0x14, 0x57, 0xd2, 0xa6, 0x49, 0x5f, 0x9a, 0xb6, 0xeb, 0xee, 0x16, 0x13, 0x96, 0x55, 0x15, 0x21,
-	0xd4, 0x5d, 0xd1, 0xa6, 0x14, 0x69, 0x85, 0xc4, 0x01, 0x89, 0x2e, 0xaa, 0x40, 0xb0, 0x82, 0x41,
-	0x5c, 0xb8, 0xb9, 0x33, 0x2f, 0xb3, 0x56, 0xa6, 0xf6, 0x74, 0xec, 0x24, 0xdb, 0x3b, 0xdc, 0xf8,
-	0x42, 0x7c, 0x1f, 0xae, 0x7c, 0x07, 0xe4, 0x3f, 0x93, 0xf1, 0x4c, 0xd3, 0x3f, 0xcb, 0xde, 0xb8,
-	0x8d, 0x7f, 0x7e, 0x7f, 0x7f, 0xcf, 0xef, 0xd9, 0x03, 0x3b, 0x69, 0x91, 0xc7, 0x63, 0x21, 0x13,
-	0x3c, 0xce, 0x0b, 0xa9, 0x25, 0x59, 0x37, 0xdf, 0xa3, 0x04, 0xb6, 0x7e, 0x90, 0x29, 0x17, 0x11,
-	0x5e, 0xcd, 0x50, 0x69, 0xf2, 0x0c, 0xe0, 0x92, 0xc5, 0x2c, 0x49, 0x0a, 0x54, 0x8a, 0xb6, 0x0e,
-	0x5a, 0x87, 0x9b, 0x51, 0x80, 0x90, 0x21, 0xf4, 0x72, 0xa6, 0xd4, 0x42, 0x16, 0x09, 0x6d, 0xdb,
-	0xdd, 0xe5, 0x9a, 0x50, 0xe8, 0x0a, 0xd4, 0x0b, 0x59, 0x4c, 0xe9, 0x9a, 0xdd, 0x2a, 0x97, 0xa3,
-	0xcf, 0x61, 0xe0, 0xbd, 0xa8, 0x5c, 0x0a, 0x85, 0xe4, 0x00, 0xfa, 0x2c, 0x8e, 0x51, 0x29, 0x2d,
-	0xa7, 0x28, 0xbc, 0x9f, 0x10, 0x1a, 0xfd, 0xd9, 0x85, 0xf5, 0xd7, 0x32, 0x41, 0xb2, 0x0d, 0x6d,
-	0x9e, 0x78, 0x89, 0x36, 0x4f, 0x08, 0x81, 0x75, 0xc1, 0x2e, 0xd1, 0x7b, 0xb7, 0xdf, 0xc6, 0x73,
-	0x19, 0xb2, 0xf7, 0x1c, 0xc4, 0xeb, 0x3f, 0x5f, 0xd2, 0xa1, 0x8b, 0xb7, 0x5c, 0x9b, 0x5c, 0x33,
-	0xae, 0x34, 0x8a, 0x5c, 0x16, 0x9a, 0xae, 0x1f, 0xb4, 0x0e, 0x3b, 0x51, 0x80, 0x90, 0xa7, 0xb0,
-	0x99, 0xcf, 0x2e, 0x32, 0x1e, 0x4f, 0xf1, 0x9a, 0x76, 0xac, 0x72, 0x05, 0x18, 0xcb, 0x28, 0x92,
-	0x5c, 0x72, 0xa1, 0xe9, 0x86, 0xb3, 0x5c, 0xae, 0x1b, 0x2c, 0x76, 0xef, 0x64, 0xb1, 0xd7, 0x60,
-	0xf1, 0x00, 0xfa, 0xa6, 0x32, 0x25, 0x93, 0x9b, 0x8e, 0x9a, 0x00, 0x32, 0x71, 0x71, 0x95, 0xa3,
-	0x48, 0xb8, 0x48, 0x29, 0x1c, 0xb4, 0x0e, 0x7b, 0x51, 0x05, 0x90, 0x7d, 0xd8, 0xc8, 0xa5, 0xd2,
-	0xb3, 0x9c, 0xf6, 0xad, 0xaa, 0x5f, 0x59, 0x9f, 0x52, 0xe9, 0x44, 0x2e, 0x04, 0xdd, 0xf2, 0x3e,
-	0xfd, 0xda, 0x58, 0x9c, 0x22, 0xe6, 0x2c, 0xe3, 0x73, 0xa4, 0x03, 0x4b, 0x44, 0x05, 0x98, 0x6c,
-	0x14, 0x9b, 0x63, 0x2c, 0xc5, 0x84, 0xa7, 0x74, 0xdb, 0x3a, 0x0c, 0x10, 0xa3, 0xed, 0x2a, 0x67,
-	0x78, 0xda, 0x71, 0x3c, 0x2d, 0x01, 0x1b, 0xad, 0xd0, 0x58, 0x4c, 0x58, 0x8c, 0x74, 0xd7, 0xed,
-	0x2e, 0x01, 0x93, 0x6d, 0xc6, 0x94, 0x8e, 0xdf, 0x60, 0x3c, 0xe5, 0x82, 0x3e, 0x72, 0xd9, 0x06,
-	0x10, 0x19, 0xc1, 0x96, 0x59, 0x5e, 0xca, 0x84, 0x4f, 0x38, 0x26, 0x94, 0x58, 0x91, 0x1a, 0x46,
-	0x0e, 0x61, 0xc7, 0x8b, 0x5b, 0xcb, 0x73, 0x96, 0xd1, 0x3d, 0x9b, 0x45, 0x13, 0xb6, 0xd6, 0x64,
-	0xcc, 0xb2, 0xb2, 0x36, 0x8f, 0xbd, 0xb5, 0x00, 0x33, 0x31, 0x19, 0x66, 0xe2, 0x37, 0x4c, 0xa4,
-	0xa8, 0xe8, 0x13, 0x17, 0x53, 0x00, 0x19, 0x46, 0x58, 0x96, 0xc9, 0x05, 0x26, 0x3c, 0x57, 0x74,
-	0xdf, 0xd5, 0xb7, 0x42, 0xcc, 0x79, 0xe4, 0xca, 0xda, 0xa4, 0x1f, 0x58, 0xba, 0xca, 0x25, 0x79,
-	0x01, 0xbb, 0x5c, 0x71, 0x91, 0x1a, 0x47, 0x29, 0xd3, 0xb8, 0x60, 0xd7, 0xf4, 0xa9, 0x15, 0xb9,
-	0x81, 0x93, 0x13, 0xd8, 0xab, 0x23, 0x85, 0xf1, 0x4e, 0x3f, 0xb6, 0xee, 0x56, 0x6d, 0x99, 0xc8,
-	0xb9, 0x4a, 0x66, 0x2c, 0x53, 0x9a, 0xc5, 0x53, 0xfa, 0x91, 0x35, 0x1c, 0x42, 0xe6, 0x74, 0x24,
-	0x42, 0xc9, 0xc9, 0x84, 0x52, 0xbb, 0xe9, 0x57, 0xb6, 0x17, 0x4c, 0x80, 0xce, 0xc5, 0x87, 0x2e,
-	0xa3, 0x0a, 0x19, 0xfd, 0xd1, 0x86, 0x9d, 0x33, 0xc3, 0xe5, 0x77, 0x55, 0x13, 0x53, 0xe8, 0xaa,
-	0x99, 0xad, 0xb3, 0x6d, 0xcf, 0x5e, 0x54, 0x2e, 0xc9, 0xa7, 0xb0, 0x2d, 0x10, 0x93, 0x1c, 0xb1,
-	0x98, 0xe5, 0x09, 0xd3, 0xae, 0x5b, 0x7b, 0x51, 0x03, 0x35, 0x6c, 0x18, 0xc4, 0x9d, 0x23, 0x2f,
-	0xb9, 0xe6, 0xd8, 0x68, 0xe2, 0x65, 0x5f, 0x5c, 0xa2, 0x52, 0x2c, 0x45, 0xdb, 0xae, 0xbe, 0x2f,
-	0x3c, 0x54, 0xef, 0x8b, 0x4e, 0xb3, 0x2f, 0x3e, 0x81, 0x81, 0xb1, 0x39, 0xc5, 0x6b, 0xef, 0x68,
-	0xc3, 0x4a, 0xd4, 0x41, 0xc3, 0x83, 0x01, 0x12, 0xcc, 0x50, 0xa3, 0xed, 0xdc, 0x5e, 0x14, 0x20,
-	0xa3, 0x7f, 0xda, 0x30, 0xf8, 0x09, 0xb1, 0x50, 0x4b, 0x16, 0x0e, 0x61, 0x87, 0x2b, 0xac, 0x15,
-	0xd4, 0xb1, 0xd1, 0x84, 0xc9, 0x31, 0x10, 0xbc, 0x59, 0x4e, 0x37, 0xc7, 0x56, 0xec, 0xdc, 0x56,
-	0xff, 0xcd, 0xdb, 0xeb, 0xff, 0xdf, 0x27, 0xd6, 0xc3, 0x26, 0x68, 0xef, 0x1d, 0x27, 0x68, 0xb3,
-	0xdb, 0xba, 0x2b, 0xba, 0xed, 0xce, 0xd9, 0x33, 0xfa, 0xbb, 0x05, 0xbb, 0xdf, 0xbe, 0xd5, 0x75,
-	0xca, 0xff, 0x7f, 0x69, 0xfe, 0xde, 0x86, 0x8d, 0xb3, 0x8c, 0xa3, 0xbb, 0x3b, 0xf2, 0x82, 0xcf,
-	0x99, 0x46, 0x93, 0x9d, 0xbf, 0x81, 0x2b, 0xa4, 0x9e, 0x7c, 0xbb, 0x99, 0x7c, 0x6d, 0x16, 0xaf,
-	0x35, 0x67, 0x71, 0x90, 0xfe, 0xfa, 0xed, 0xe9, 0x77, 0x1a, 0xe9, 0xbf, 0x80, 0x5d, 0x85, 0xc5,
-	0x1c, 0x8b, 0x45, 0xda, 0x20, 0xf6, 0x06, 0x6e, 0xef, 0x0a, 0x8b, 0x59, 0xaa, 0xfc, 0xcd, 0x57,
-	0x21, 0x26, 0x3e, 0xb7, 0x32, 0xf1, 0x39, 0x9e, 0x2b, 0x60, 0x34, 0x86, 0xc1, 0x59, 0x81, 0x4c,
-	0xa3, 0xb9, 0xf9, 0x23, 0xbc, 0x22, 0xcf, 0xc0, 0x3e, 0x53, 0x2c, 0x0d, 0xfd, 0x53, 0x38, 0xb6,
-	0xef, 0x17, 0xbb, 0xe9, 0x9e, 0x2f, 0x0d, 0x05, 0xf5, 0x10, 0x85, 0x5f, 0x6d, 0xa7, 0xbf, 0x83,
-	0x87, 0x50, 0xe1, 0x7e, 0x0f, 0xe7, 0xd0, 0x8f, 0x90, 0x25, 0x95, 0xfd, 0xbb, 0x1f, 0x54, 0xc1,
-	0xa3, 0xa9, 0x5d, 0x7f, 0x34, 0x1d, 0x85, 0x86, 0xee, 0xf7, 0xfb, 0x33, 0x0c, 0x5e, 0xd9, 0x19,
-	0xf5, 0x50, 0xcf, 0x66, 0xa0, 0x3a, 0x57, 0xaf, 0xab, 0xf7, 0x54, 0x08, 0x8d, 0x9e, 0xd7, 0x4d,
-	0xaa, 0xdb, 0x27, 0xbe, 0xc9, 0xfa, 0x1c, 0xcb, 0x36, 0x7d, 0x9f, 0xac, 0xbf, 0x87, 0xed, 0x73,
-	0xd4, 0x55, 0xcb, 0xbf, 0x8f, 0xad, 0x2f, 0xc3, 0xa0, 0x14, 0x79, 0x0e, 0x1d, 0x73, 0xf7, 0x28,
-	0x4f, 0xe1, 0x9e, 0xa3, 0xb0, 0x36, 0x5a, 0x22, 0x27, 0x31, 0x7a, 0xd5, 0x88, 0x42, 0x91, 0x53,
-	0xe8, 0xe1, 0x5b, 0x1d, 0xea, 0xef, 0x3b, 0xfd, 0xe6, 0x74, 0x8a, 0x96, 0x72, 0xa3, 0xcf, 0x00,
-	0x96, 0x77, 0xe6, 0xfd, 0x27, 0xed, 0xc7, 0x40, 0x5a, 0x91, 0xaf, 0x97, 0x4f, 0x9a, 0xc2, 0x1b,
-	0xf6, 0x8a, 0x4f, 0x9c, 0x62, 0xe3, 0x32, 0x8e, 0x9a, 0xd2, 0xa7, 0x7f, 0xad, 0x41, 0xdf, 0x58,
-	0xff, 0x05, 0x8b, 0x39, 0x8f, 0xcd, 0x6d, 0xd2, 0xb1, 0x6f, 0x70, 0x42, 0x9c, 0x81, 0xf0, 0xd9,
-	0x3f, 0xdc, 0xab, 0x61, 0x7e, 0xcc, 0xbe, 0x04, 0xa8, 0x9a, 0x8b, 0x78, 0x91, 0x5a, 0x7f, 0x0e,
-	0x57, 0x80, 0x8a, 0x9c, 0x40, 0xaf, 0x3c, 0xb8, 0xe4, 0x91, 0x13, 0x08, 0x3a, 0x62, 0x78, 0x03,
-	0x52, 0xc6, 0x53, 0xd5, 0x64, 0xa5, 0xa7, 0x5a, 0x9f, 0x0e, 0x57, 0x80, 0x56, 0xaf, 0x3a, 0xa0,
-	0xa5, 0x5e, 0xad, 0x0b, 0x86, 0x2b, 0x40, 0x5b, 0xcc, 0xf2, 0x60, 0x94, 0x11, 0x06, 0xa7, 0x77,
-	0x78, 0x03, 0x52, 0x27, 0x2d, 0xf2, 0x95, 0x3d, 0x4c, 0x65, 0xb5, 0xc9, 0xe3, 0xa5, 0x4c, 0x70,
-	0x56, 0x87, 0xab, 0x50, 0xa3, 0x7c, 0x04, 0x5d, 0x5f, 0x30, 0xb2, 0xdb, 0xa8, 0xdf, 0xd5, 0xb0,
-	0x89, 0xa8, 0x6f, 0xc6, 0xbf, 0x1d, 0xa5, 0x52, 0xa6, 0x19, 0x1e, 0xa7, 0x32, 0x63, 0x22, 0x3d,
-	0x96, 0x45, 0x3a, 0xb6, 0xbf, 0x6d, 0x17, 0xb3, 0xc9, 0x58, 0x5f, 0xe7, 0xa8, 0xc6, 0x53, 0x21,
-	0x17, 0xc2, 0xfe, 0xd0, 0xe5, 0x17, 0x17, 0x1b, 0x76, 0xf3, 0x8b, 0x7f, 0x03, 0x00, 0x00, 0xff,
-	0xff, 0xf1, 0xb2, 0x6f, 0x12, 0xe6, 0x0d, 0x00, 0x00,
+var File_grpc_node_proto protoreflect.FileDescriptor
+
+var file_grpc_node_proto_rawDesc = []byte{
+	0x0a, 0x0f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+	0x6f, 0x12, 0x04, 0x6e, 0x6f, 0x64, 0x65, 0x22, 0x64, 0x0a, 0x0c, 0x4c, 0x6f, 0x67, 0x69, 0x6e,
+	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x6d, 0x61, 0x63, 0x61, 0x64,
+	0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6d, 0x61, 0x63,
+	0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77,
+	0x6f, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77,
+	0x6f, 0x72, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x03,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x22, 0x31, 0x0a,
+	0x0d, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x20,
+	0x0a, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x74, 0x6f, 0x6b, 0x65, 0x6e,
+	0x22, 0xb0, 0x07, 0x0a, 0x04, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18,
+	0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d,
+	0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a,
+	0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
+	0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x64, 0x64, 0x72, 0x65,
+	0x73, 0x73, 0x36, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x61, 0x64, 0x64, 0x72, 0x65,
+	0x73, 0x73, 0x36, 0x12, 0x1e, 0x0a, 0x0a, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x70, 0x6f, 0x72,
+	0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x70,
+	0x6f, 0x72, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x6b, 0x65, 0x79,
+	0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x6b, 0x65,
+	0x79, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x06, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x1e, 0x0a,
+	0x0a, 0x6d, 0x61, 0x63, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x0a, 0x6d, 0x61, 0x63, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1a, 0x0a,
+	0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x6e, 0x6f, 0x64,
+	0x65, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b,
+	0x6e, 0x6f, 0x64, 0x65, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x12, 0x1c, 0x0a, 0x09, 0x69,
+	0x73, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09,
+	0x69, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x6f, 0x73,
+	0x74, 0x75, 0x70, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x6f, 0x73, 0x74, 0x75,
+	0x70, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x6f, 0x73, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x18, 0x0c, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x6f, 0x73, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x12, 0x1c, 0x0a,
+	0x09, 0x6b, 0x65, 0x65, 0x70, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x05,
+	0x52, 0x09, 0x6b, 0x65, 0x65, 0x70, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x73,
+	0x61, 0x76, 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x0a, 0x73, 0x61, 0x76, 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1c, 0x0a, 0x09, 0x61,
+	0x63, 0x63, 0x65, 0x73, 0x73, 0x6b, 0x65, 0x79, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09,
+	0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6b, 0x65, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x69, 0x6e, 0x74,
+	0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x69, 0x6e,
+	0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x6c, 0x61, 0x73, 0x74, 0x63,
+	0x68, 0x65, 0x63, 0x6b, 0x69, 0x6e, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6c, 0x61,
+	0x73, 0x74, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x69, 0x6e, 0x12, 0x22, 0x0a, 0x0c, 0x6c, 0x61, 0x73,
+	0x74, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x18, 0x12, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x0c, 0x6c, 0x61, 0x73, 0x74, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x12, 0x28, 0x0a,
+	0x0f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x69, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c,
+	0x18, 0x13, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x69, 0x6e, 0x69,
+	0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x22, 0x0a, 0x0c, 0x6c, 0x6f, 0x63, 0x61, 0x6c,
+	0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6c,
+	0x6f, 0x63, 0x61, 0x6c, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x70,
+	0x6f, 0x73, 0x74, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x0b, 0x70, 0x6f, 0x73, 0x74, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x1e, 0x0a,
+	0x0a, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x69, 0x70, 0x73, 0x18, 0x16, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x0a, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x69, 0x70, 0x73, 0x12, 0x18, 0x0a,
+	0x07, 0x69, 0x73, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x18, 0x17, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07,
+	0x69, 0x73, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x12, 0x2a, 0x0a, 0x10, 0x69, 0x73, 0x69, 0x6e, 0x67,
+	0x72, 0x65, 0x73, 0x73, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x18, 0x1c, 0x20, 0x01, 0x28,
+	0x08, 0x52, 0x10, 0x69, 0x73, 0x69, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x67, 0x61, 0x74, 0x65,
+	0x77, 0x61, 0x79, 0x12, 0x30, 0x0a, 0x13, 0x69, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x67, 0x61,
+	0x74, 0x65, 0x77, 0x61, 0x79, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x1d, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x13, 0x69, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79,
+	0x72, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x69, 0x73, 0x64, 0x75, 0x61, 0x6c, 0x73,
+	0x74, 0x61, 0x63, 0x6b, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x73, 0x64, 0x75,
+	0x61, 0x6c, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6e, 0x73, 0x6f, 0x66,
+	0x66, 0x18, 0x18, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x64, 0x6e, 0x73, 0x6f, 0x66, 0x66, 0x12,
+	0x1e, 0x0a, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x19, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x12,
+	0x22, 0x0a, 0x0c, 0x75, 0x64, 0x70, 0x68, 0x6f, 0x6c, 0x65, 0x70, 0x75, 0x6e, 0x63, 0x68, 0x18,
+	0x1e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x75, 0x64, 0x70, 0x68, 0x6f, 0x6c, 0x65, 0x70, 0x75,
+	0x6e, 0x63, 0x68, 0x22, 0x85, 0x02, 0x0a, 0x0f, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x49, 0x6e, 0x52,
+	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65,
+	0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73,
+	0x73, 0x12, 0x26, 0x0a, 0x0e, 0x6e, 0x65, 0x65, 0x64, 0x70, 0x65, 0x65, 0x72, 0x75, 0x70, 0x64,
+	0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x6e, 0x65, 0x65, 0x64, 0x70,
+	0x65, 0x65, 0x72, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x2a, 0x0a, 0x10, 0x6e, 0x65, 0x65,
+	0x64, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20,
+	0x01, 0x28, 0x08, 0x52, 0x10, 0x6e, 0x65, 0x65, 0x64, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75,
+	0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x6e, 0x6f, 0x64, 0x65, 0x6d, 0x65, 0x73,
+	0x73, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6e, 0x6f, 0x64, 0x65,
+	0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x69, 0x73, 0x70, 0x65, 0x6e,
+	0x64, 0x69, 0x6e, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, 0x70, 0x65,
+	0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x24, 0x0a, 0x0d, 0x6e, 0x65, 0x65, 0x64, 0x6b, 0x65, 0x79,
+	0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x6e, 0x65,
+	0x65, 0x64, 0x6b, 0x65, 0x79, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x6e,
+	0x65, 0x65, 0x64, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52,
+	0x0a, 0x6e, 0x65, 0x65, 0x64, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x22, 0xed, 0x02, 0x0a, 0x0d,
+	0x50, 0x65, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x28, 0x0a,
+	0x0f, 0x69, 0x73, 0x65, 0x67, 0x72, 0x65, 0x73, 0x73, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79,
+	0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x69, 0x73, 0x65, 0x67, 0x72, 0x65, 0x73, 0x73,
+	0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x2e, 0x0a, 0x12, 0x65, 0x67, 0x72, 0x65, 0x73,
+	0x73, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x02, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x12, 0x65, 0x67, 0x72, 0x65, 0x73, 0x73, 0x67, 0x61, 0x74, 0x65, 0x77,
+	0x61, 0x79, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x30, 0x0a, 0x13, 0x69, 0x6e, 0x67, 0x72, 0x65,
+	0x73, 0x73, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x09,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x69, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x67, 0x61, 0x74,
+	0x65, 0x77, 0x61, 0x79, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x75, 0x62,
+	0x6c, 0x69, 0x63, 0x6b, 0x65, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x75,
+	0x62, 0x6c, 0x69, 0x63, 0x6b, 0x65, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f,
+	0x69, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f,
+	0x69, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1a, 0x0a,
+	0x08, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x36, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x08, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x36, 0x12, 0x1e, 0x0a, 0x0a, 0x6c, 0x69, 0x73,
+	0x74, 0x65, 0x6e, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x6c,
+	0x69, 0x73, 0x74, 0x65, 0x6e, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x22, 0x0a, 0x0c, 0x6c, 0x6f, 0x63,
+	0x61, 0x6c, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x0c, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1c, 0x0a,
+	0x09, 0x6b, 0x65, 0x65, 0x70, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x05,
+	0x52, 0x09, 0x6b, 0x65, 0x65, 0x70, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x22, 0xe4, 0x01, 0x0a, 0x10,
+	0x45, 0x78, 0x74, 0x50, 0x65, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
+	0x12, 0x1c, 0x0a, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x6b, 0x65, 0x79, 0x18, 0x05, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x6b, 0x65, 0x79, 0x12, 0x1a,
+	0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64,
+	0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64,
+	0x72, 0x65, 0x73, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x36,
+	0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x36,
+	0x12, 0x1e, 0x0a, 0x0a, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x04,
+	0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x70, 0x6f, 0x72, 0x74,
+	0x12, 0x22, 0x0a, 0x0c, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73,
+	0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x61, 0x64, 0x64,
+	0x72, 0x65, 0x73, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x6b, 0x65, 0x65, 0x70, 0x61, 0x6c, 0x69, 0x76,
+	0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x6b, 0x65, 0x65, 0x70, 0x61, 0x6c, 0x69,
+	0x76, 0x65, 0x22, 0x84, 0x02, 0x0a, 0x06, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x1e, 0x0a,
+	0x0a, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x0a, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x6b, 0x65, 0x79, 0x12, 0x1c, 0x0a,
+	0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x6b, 0x65, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x61,
+	0x63, 0x63, 0x65, 0x73, 0x73, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09,
+	0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64,
+	0x72, 0x65, 0x73, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72,
+	0x65, 0x73, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x36, 0x18,
+	0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x36, 0x12,
+	0x2a, 0x0a, 0x10, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x77, 0x67, 0x65, 0x6e, 0x64, 0x70, 0x6f,
+	0x69, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x73, 0x65, 0x72, 0x76, 0x65,
+	0x72, 0x77, 0x67, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x73,
+	0x65, 0x72, 0x76, 0x65, 0x72, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x0a, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x73,
+	0x65, 0x72, 0x76, 0x65, 0x72, 0x6b, 0x65, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09,
+	0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x6b, 0x65, 0x79, 0x22, 0x2f, 0x0a, 0x0d, 0x43, 0x72, 0x65,
+	0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x12, 0x1e, 0x0a, 0x04, 0x6e, 0x6f,
+	0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e,
+	0x4e, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x6e, 0x6f, 0x64, 0x65, 0x22, 0x2f, 0x0a, 0x0d, 0x43, 0x72,
+	0x65, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x12, 0x1e, 0x0a, 0x04, 0x6e,
+	0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x6e, 0x6f, 0x64, 0x65,
+	0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x6e, 0x6f, 0x64, 0x65, 0x22, 0x2f, 0x0a, 0x0d, 0x55,
+	0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x12, 0x1e, 0x0a, 0x04,
+	0x6e, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x6e, 0x6f, 0x64,
+	0x65, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x6e, 0x6f, 0x64, 0x65, 0x22, 0x2f, 0x0a, 0x0d,
+	0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x12, 0x1e, 0x0a,
+	0x04, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x6e, 0x6f,
+	0x64, 0x65, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x6e, 0x6f, 0x64, 0x65, 0x22, 0x47, 0x0a,
+	0x0b, 0x52, 0x65, 0x61, 0x64, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x12, 0x1e, 0x0a, 0x0a,
+	0x6d, 0x61, 0x63, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x0a, 0x6d, 0x61, 0x63, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x18, 0x0a, 0x07,
+	0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6e,
+	0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x22, 0x2d, 0x0a, 0x0b, 0x52, 0x65, 0x61, 0x64, 0x4e, 0x6f,
+	0x64, 0x65, 0x52, 0x65, 0x73, 0x12, 0x1e, 0x0a, 0x04, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20,
+	0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52,
+	0x04, 0x6e, 0x6f, 0x64, 0x65, 0x22, 0x51, 0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e,
+	0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x12, 0x1e, 0x0a, 0x0a, 0x6d, 0x61, 0x63, 0x61, 0x64, 0x64,
+	0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6d, 0x61, 0x63, 0x61,
+	0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72,
+	0x6b, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6e, 0x65, 0x74,
+	0x77, 0x6f, 0x72, 0x6b, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x29, 0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65,
+	0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63,
+	0x63, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63,
+	0x65, 0x73, 0x73, 0x22, 0x47, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x50, 0x65, 0x65, 0x72, 0x73, 0x52,
+	0x65, 0x71, 0x12, 0x1e, 0x0a, 0x0a, 0x6d, 0x61, 0x63, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73,
+	0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6d, 0x61, 0x63, 0x61, 0x64, 0x64, 0x72, 0x65,
+	0x73, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x02, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x22, 0x4a, 0x0a, 0x0e,
+	0x47, 0x65, 0x74, 0x45, 0x78, 0x74, 0x50, 0x65, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x12, 0x1e,
+	0x0a, 0x0a, 0x6d, 0x61, 0x63, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x0a, 0x6d, 0x61, 0x63, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x18,
+	0x0a, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x22, 0x38, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x50,
+	0x65, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x12, 0x29, 0x0a, 0x05, 0x70, 0x65, 0x65, 0x72, 0x73,
+	0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x50, 0x65,
+	0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x05, 0x70, 0x65, 0x65,
+	0x72, 0x73, 0x22, 0x44, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x45, 0x78, 0x74, 0x50, 0x65, 0x65, 0x72,
+	0x73, 0x52, 0x65, 0x73, 0x12, 0x32, 0x0a, 0x08, 0x65, 0x78, 0x74, 0x70, 0x65, 0x65, 0x72, 0x73,
+	0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x45, 0x78,
+	0x74, 0x50, 0x65, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x08,
+	0x65, 0x78, 0x74, 0x70, 0x65, 0x65, 0x72, 0x73, 0x22, 0x2c, 0x0a, 0x0a, 0x43, 0x68, 0x65, 0x63,
+	0x6b, 0x49, 0x6e, 0x52, 0x65, 0x71, 0x12, 0x1e, 0x0a, 0x04, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x01,
+	0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x4e, 0x6f, 0x64, 0x65,
+	0x52, 0x04, 0x6e, 0x6f, 0x64, 0x65, 0x22, 0x4d, 0x0a, 0x0a, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x49,
+	0x6e, 0x52, 0x65, 0x73, 0x12, 0x3f, 0x0a, 0x0f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x69, 0x6e, 0x72,
+	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e,
+	0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x49, 0x6e, 0x52, 0x65, 0x73, 0x70,
+	0x6f, 0x6e, 0x73, 0x65, 0x52, 0x0f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x69, 0x6e, 0x72, 0x65, 0x73,
+	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xb9, 0x03, 0x0a, 0x0b, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x65,
+	0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x30, 0x0a, 0x05, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x12, 0x12,
+	0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65,
+	0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52,
+	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x0a, 0x43, 0x72, 0x65, 0x61, 0x74,
+	0x65, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x13, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x43, 0x72, 0x65,
+	0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x1a, 0x13, 0x2e, 0x6e, 0x6f, 0x64,
+	0x65, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x12,
+	0x30, 0x0a, 0x08, 0x52, 0x65, 0x61, 0x64, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x11, 0x2e, 0x6e, 0x6f,
+	0x64, 0x65, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x1a, 0x11,
+	0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65,
+	0x73, 0x12, 0x36, 0x0a, 0x0a, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x12,
+	0x13, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64,
+	0x65, 0x52, 0x65, 0x71, 0x1a, 0x13, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x55, 0x70, 0x64, 0x61,
+	0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x12, 0x36, 0x0a, 0x0a, 0x44, 0x65, 0x6c,
+	0x65, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x13, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x44,
+	0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x1a, 0x13, 0x2e, 0x6e,
+	0x6f, 0x64, 0x65, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65,
+	0x73, 0x12, 0x32, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x50, 0x65, 0x65, 0x72, 0x73, 0x12, 0x11, 0x2e,
+	0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x65, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71,
+	0x1a, 0x11, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x65, 0x65, 0x72, 0x73,
+	0x52, 0x65, 0x73, 0x30, 0x01, 0x12, 0x3b, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x45, 0x78, 0x74, 0x50,
+	0x65, 0x65, 0x72, 0x73, 0x12, 0x14, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x45,
+	0x78, 0x74, 0x50, 0x65, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x6e, 0x6f, 0x64,
+	0x65, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x78, 0x74, 0x50, 0x65, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73,
+	0x30, 0x01, 0x12, 0x2d, 0x0a, 0x07, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x49, 0x6e, 0x12, 0x10, 0x2e,
+	0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x49, 0x6e, 0x52, 0x65, 0x71, 0x1a,
+	0x10, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x49, 0x6e, 0x52, 0x65,
+	0x73, 0x42, 0x2f, 0x5a, 0x2d, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x67, 0x6f, 0x6c, 0x61,
+	0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f,
+	0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x2f, 0x6e, 0x6f, 0x64, 0x65,
+	0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+}
+
+var (
+	file_grpc_node_proto_rawDescOnce sync.Once
+	file_grpc_node_proto_rawDescData = file_grpc_node_proto_rawDesc
+)
+
+func file_grpc_node_proto_rawDescGZIP() []byte {
+	file_grpc_node_proto_rawDescOnce.Do(func() {
+		file_grpc_node_proto_rawDescData = protoimpl.X.CompressGZIP(file_grpc_node_proto_rawDescData)
+	})
+	return file_grpc_node_proto_rawDescData
+}
+
+var file_grpc_node_proto_msgTypes = make([]protoimpl.MessageInfo, 21)
+var file_grpc_node_proto_goTypes = []interface{}{
+	(*LoginRequest)(nil),     // 0: node.LoginRequest
+	(*LoginResponse)(nil),    // 1: node.LoginResponse
+	(*Node)(nil),             // 2: node.Node
+	(*CheckInResponse)(nil),  // 3: node.CheckInResponse
+	(*PeersResponse)(nil),    // 4: node.PeersResponse
+	(*ExtPeersResponse)(nil), // 5: node.ExtPeersResponse
+	(*Client)(nil),           // 6: node.Client
+	(*CreateNodeReq)(nil),    // 7: node.CreateNodeReq
+	(*CreateNodeRes)(nil),    // 8: node.CreateNodeRes
+	(*UpdateNodeReq)(nil),    // 9: node.UpdateNodeReq
+	(*UpdateNodeRes)(nil),    // 10: node.UpdateNodeRes
+	(*ReadNodeReq)(nil),      // 11: node.ReadNodeReq
+	(*ReadNodeRes)(nil),      // 12: node.ReadNodeRes
+	(*DeleteNodeReq)(nil),    // 13: node.DeleteNodeReq
+	(*DeleteNodeRes)(nil),    // 14: node.DeleteNodeRes
+	(*GetPeersReq)(nil),      // 15: node.GetPeersReq
+	(*GetExtPeersReq)(nil),   // 16: node.GetExtPeersReq
+	(*GetPeersRes)(nil),      // 17: node.GetPeersRes
+	(*GetExtPeersRes)(nil),   // 18: node.GetExtPeersRes
+	(*CheckInReq)(nil),       // 19: node.CheckInReq
+	(*CheckInRes)(nil),       // 20: node.CheckInRes
+}
+var file_grpc_node_proto_depIdxs = []int32{
+	2,  // 0: node.CreateNodeReq.node:type_name -> node.Node
+	2,  // 1: node.CreateNodeRes.node:type_name -> node.Node
+	2,  // 2: node.UpdateNodeReq.node:type_name -> node.Node
+	2,  // 3: node.UpdateNodeRes.node:type_name -> node.Node
+	2,  // 4: node.ReadNodeRes.node:type_name -> node.Node
+	4,  // 5: node.GetPeersRes.peers:type_name -> node.PeersResponse
+	5,  // 6: node.GetExtPeersRes.extpeers:type_name -> node.ExtPeersResponse
+	2,  // 7: node.CheckInReq.node:type_name -> node.Node
+	3,  // 8: node.CheckInRes.checkinresponse:type_name -> node.CheckInResponse
+	0,  // 9: node.NodeService.Login:input_type -> node.LoginRequest
+	7,  // 10: node.NodeService.CreateNode:input_type -> node.CreateNodeReq
+	11, // 11: node.NodeService.ReadNode:input_type -> node.ReadNodeReq
+	9,  // 12: node.NodeService.UpdateNode:input_type -> node.UpdateNodeReq
+	13, // 13: node.NodeService.DeleteNode:input_type -> node.DeleteNodeReq
+	15, // 14: node.NodeService.GetPeers:input_type -> node.GetPeersReq
+	16, // 15: node.NodeService.GetExtPeers:input_type -> node.GetExtPeersReq
+	19, // 16: node.NodeService.CheckIn:input_type -> node.CheckInReq
+	1,  // 17: node.NodeService.Login:output_type -> node.LoginResponse
+	8,  // 18: node.NodeService.CreateNode:output_type -> node.CreateNodeRes
+	12, // 19: node.NodeService.ReadNode:output_type -> node.ReadNodeRes
+	10, // 20: node.NodeService.UpdateNode:output_type -> node.UpdateNodeRes
+	14, // 21: node.NodeService.DeleteNode:output_type -> node.DeleteNodeRes
+	17, // 22: node.NodeService.GetPeers:output_type -> node.GetPeersRes
+	18, // 23: node.NodeService.GetExtPeers:output_type -> node.GetExtPeersRes
+	20, // 24: node.NodeService.CheckIn:output_type -> node.CheckInRes
+	17, // [17:25] is the sub-list for method output_type
+	9,  // [9:17] is the sub-list for method input_type
+	9,  // [9:9] is the sub-list for extension type_name
+	9,  // [9:9] is the sub-list for extension extendee
+	0,  // [0:9] is the sub-list for field type_name
+}
+
+func init() { file_grpc_node_proto_init() }
+func file_grpc_node_proto_init() {
+	if File_grpc_node_proto != nil {
+		return
+	}
+	if !protoimpl.UnsafeEnabled {
+		file_grpc_node_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*LoginRequest); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_grpc_node_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*LoginResponse); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_grpc_node_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*Node); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_grpc_node_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*CheckInResponse); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_grpc_node_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*PeersResponse); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_grpc_node_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*ExtPeersResponse); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_grpc_node_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*Client); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_grpc_node_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*CreateNodeReq); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_grpc_node_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*CreateNodeRes); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_grpc_node_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*UpdateNodeReq); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_grpc_node_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*UpdateNodeRes); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_grpc_node_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*ReadNodeReq); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_grpc_node_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*ReadNodeRes); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_grpc_node_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*DeleteNodeReq); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_grpc_node_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*DeleteNodeRes); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_grpc_node_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*GetPeersReq); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_grpc_node_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*GetExtPeersReq); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_grpc_node_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*GetPeersRes); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_grpc_node_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*GetExtPeersRes); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_grpc_node_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*CheckInReq); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_grpc_node_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*CheckInRes); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+	}
+	type x struct{}
+	out := protoimpl.TypeBuilder{
+		File: protoimpl.DescBuilder{
+			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+			RawDescriptor: file_grpc_node_proto_rawDesc,
+			NumEnums:      0,
+			NumMessages:   21,
+			NumExtensions: 0,
+			NumServices:   1,
+		},
+		GoTypes:           file_grpc_node_proto_goTypes,
+		DependencyIndexes: file_grpc_node_proto_depIdxs,
+		MessageInfos:      file_grpc_node_proto_msgTypes,
+	}.Build()
+	File_grpc_node_proto = out.File
+	file_grpc_node_proto_rawDesc = nil
+	file_grpc_node_proto_goTypes = nil
+	file_grpc_node_proto_depIdxs = nil
 }

+ 2 - 1
grpc/node.proto

@@ -36,7 +36,7 @@ message Node {
     string postup = 11;
     string postdown = 12;
     int32 keepalive = 13;
-    bool saveconfig = 14;
+    string saveconfig = 14;
     string accesskey = 15;
     string interface = 16;
     string lastcheckin = 17;
@@ -51,6 +51,7 @@ message Node {
     bool isdualstack = 27;
     bool dnsoff = 24;
     string localrange = 25;
+    string udpholepunch = 30;
 }
 
 message CheckInResponse {

+ 357 - 355
netclient/config/config.go

@@ -2,166 +2,170 @@ package config
 
 import (
 	//"github.com/davecgh/go-spew/spew"
-	"github.com/urfave/cli/v2"
-	"os"
-        "encoding/base64"
+	"encoding/base64"
+	"encoding/json"
 	"errors"
 	"fmt"
 	"log"
-        "encoding/json"
-	"gopkg.in/yaml.v3"
+	"os"
+
 	nodepb "github.com/gravitl/netmaker/grpc"
 	"github.com/gravitl/netmaker/models"
+	"github.com/urfave/cli/v2"
+	"gopkg.in/yaml.v3"
 )
+
 type GlobalConfig struct {
 	GRPCWireGuard string `yaml:"grpcwg"`
-	Client models.IntClient
+	Client        models.IntClient
 }
 
 type ClientConfig struct {
-	Server ServerConfig `yaml:"server"`
-	Node NodeConfig `yaml:"node"`
-	Network string `yaml:"network"`
-	Daemon string `yaml:"daemon"`
-	OperatingSystem string `yaml:"operatingsystem"`
+	Server          ServerConfig `yaml:"server"`
+	Node            NodeConfig   `yaml:"node"`
+	Network         string       `yaml:"network"`
+	Daemon          string       `yaml:"daemon"`
+	OperatingSystem string       `yaml:"operatingsystem"`
 }
 type ServerConfig struct {
-        CoreDNSAddr string `yaml:"corednsaddr"`
-        GRPCAddress string `yaml:"grpcaddress"`
-        APIAddress string `yaml:"apiaddress"`
-        AccessKey string `yaml:"accesskey"`
-        GRPCSSL string `yaml:"grpcssl"`
-        GRPCWireGuard string `yaml:"grpcwg"`
+	CoreDNSAddr   string `yaml:"corednsaddr"`
+	GRPCAddress   string `yaml:"grpcaddress"`
+	APIAddress    string `yaml:"apiaddress"`
+	AccessKey     string `yaml:"accesskey"`
+	GRPCSSL       string `yaml:"grpcssl"`
+	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"`
+	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"`
+	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"`
 }
 
 //reading in the env file
-func Write(config *ClientConfig, network string) error{
+func Write(config *ClientConfig, network string) error {
 	if network == "" {
 		err := errors.New("No network provided. Exiting.")
 		return err
 	}
-        _, err := os.Stat("/etc/netclient") 
+	_, err := os.Stat("/etc/netclient")
 	if os.IsNotExist(err) {
-		      os.Mkdir("/etc/netclient", 744)
+		os.Mkdir("/etc/netclient", 744)
 	} else if err != nil {
-                return err
-        }
+		return err
+	}
 	home := "/etc/netclient"
 
-        file := fmt.Sprintf(home + "/netconfig-" + network)
-        f, err := os.OpenFile(file, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm)
-        defer f.Close()
+	file := fmt.Sprintf(home + "/netconfig-" + network)
+	f, err := os.OpenFile(file, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm)
+	defer f.Close()
 
 	err = yaml.NewEncoder(f).Encode(config)
 	if err != nil {
 		return err
 	}
-        return err
+	return err
 }
+
 //reading in the env file
-func WriteGlobal(config *GlobalConfig) error{
-        _, err := os.Stat("/etc/netclient") 
-        if os.IsNotExist(err) {
-                      os.Mkdir("/etc/netclient", 744)
-        } else if err != nil {
-                return err
-        }
-        home := "/etc/netclient"
-
-        if err != nil {
-                log.Fatal(err)
-        }
-        file := fmt.Sprintf(home + "/netconfig-global-001")
-        f, err := os.OpenFile(file, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm)
-        defer f.Close()
-
-        err = yaml.NewEncoder(f).Encode(config)
-        if err != nil {
-                return err
-        }
-        return err
+func WriteGlobal(config *GlobalConfig) error {
+	_, err := os.Stat("/etc/netclient")
+	if os.IsNotExist(err) {
+		os.Mkdir("/etc/netclient", 744)
+	} else if err != nil {
+		return err
+	}
+	home := "/etc/netclient"
+
+	if err != nil {
+		log.Fatal(err)
+	}
+	file := fmt.Sprintf(home + "/netconfig-global-001")
+	f, err := os.OpenFile(file, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm)
+	defer f.Close()
+
+	err = yaml.NewEncoder(f).Encode(config)
+	if err != nil {
+		return err
+	}
+	return err
 }
-func WriteServer(server string, accesskey string, network string) error{
-        if network == "" {
-                err := errors.New("No network provided. Exiting.")
-                return err
-        }
-        nofile := false
-        //home, err := homedir.Dir()
-        _, err := os.Stat("/etc/netclient")
+func WriteServer(server string, accesskey string, network string) error {
+	if network == "" {
+		err := errors.New("No network provided. Exiting.")
+		return err
+	}
+	nofile := false
+	//home, err := homedir.Dir()
+	_, err := os.Stat("/etc/netclient")
 	if os.IsNotExist(err) {
-                os.Mkdir("/etc/netclient", 744)
-        } else if err != nil {
+		os.Mkdir("/etc/netclient", 744)
+	} else if err != nil {
 		fmt.Println("couldnt find or create /etc/netclient")
-                return err
-        }
-        home := "/etc/netclient"
+		return err
+	}
+	home := "/etc/netclient"
 
 	file := fmt.Sprintf(home + "/netconfig-" + network)
-        //f, err := os.Open(file)
-        f, err := os.OpenFile(file, os.O_CREATE|os.O_RDWR, 0666)
+	//f, err := os.Open(file)
+	f, err := os.OpenFile(file, os.O_CREATE|os.O_RDWR, 0666)
 	//f, err := ioutil.ReadFile(file)
-        if err != nil {
+	if err != nil {
 		fmt.Println("couldnt open netconfig-" + network)
 		fmt.Println(err)
-                nofile = true
+		nofile = true
 		//err = nil
 		return err
-        }
-        defer f.Close()
+	}
+	defer f.Close()
 
 	//cfg := &ClientConfig{}
 	var cfg ClientConfig
 
-        if !nofile {
+	if !nofile {
 		fmt.Println("Writing to existing config file at " + home + "/netconfig-" + network)
-                decoder := yaml.NewDecoder(f)
-                err = decoder.Decode(&cfg)
+		decoder := yaml.NewDecoder(f)
+		err = decoder.Decode(&cfg)
 		//err = yaml.Unmarshal(f, &cfg)
-                if err != nil {
+		if err != nil {
 			//fmt.Println(err)
-                        //return err
-                }
+			//return err
+		}
 		f.Close()
 		f, err = os.OpenFile(file, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0666)
-	        if err != nil {
+		if err != nil {
 			fmt.Println("couldnt open netconfig")
 			fmt.Println(err)
 			nofile = true
@@ -170,10 +174,10 @@ func WriteServer(server string, accesskey string, network string) error{
 		}
 		defer f.Close()
 
-                if err != nil {
-                        fmt.Println("trouble opening file")
-                        fmt.Println(err)
-                }
+		if err != nil {
+			fmt.Println("trouble opening file")
+			fmt.Println(err)
+		}
 
 		cfg.Server.GRPCAddress = server
 		cfg.Server.AccessKey = accesskey
@@ -181,36 +185,34 @@ func WriteServer(server string, accesskey string, network string) error{
 		err = yaml.NewEncoder(f).Encode(cfg)
 		//_, err = yaml.Marshal(f, &cfg)
 		if err != nil {
-                        fmt.Println("trouble encoding file")
-                        return err
-                }
+			fmt.Println("trouble encoding file")
+			return err
+		}
 	} else {
-                fmt.Println("Creating new config file at " + home + "/netconfig-" + network)
+		fmt.Println("Creating new config file at " + home + "/netconfig-" + network)
 
-                cfg.Server.GRPCAddress = server
-                cfg.Server.AccessKey = accesskey
+		cfg.Server.GRPCAddress = server
+		cfg.Server.AccessKey = accesskey
 
-                newf, err := os.Create(home + "/netconfig-" + network)
-                err = yaml.NewEncoder(newf).Encode(cfg)
-                defer newf.Close()
-                if err != nil {
-                        return err
-                }
-        }
+		newf, err := os.Create(home + "/netconfig-" + network)
+		err = yaml.NewEncoder(newf).Encode(cfg)
+		defer newf.Close()
+		if err != nil {
+			return err
+		}
+	}
 
-        return err
+	return err
 }
 
-
-
-func(config *ClientConfig) ReadConfig() {
+func (config *ClientConfig) ReadConfig() {
 
 	nofile := false
 	//home, err := homedir.Dir()
 	home := "/etc/netclient"
 	file := fmt.Sprintf(home + "/netconfig-" + config.Network)
 	//f, err := os.Open(file)
-        f, err := os.OpenFile(file, os.O_RDONLY, 0666)
+	f, err := os.OpenFile(file, os.O_RDONLY, 0666)
 	if err != nil {
 		fmt.Println("trouble opening file")
 		fmt.Println(err)
@@ -233,153 +235,153 @@ func(config *ClientConfig) ReadConfig() {
 		}
 	}
 }
-func ModGlobalConfig(cfg models.IntClient) error{
-        var modconfig GlobalConfig
-        var err error
-        if FileExists("/etc/netclient/netconfig-global-001") {
-                useconfig, err := ReadGlobalConfig()
-                if err != nil {
-                        return err
-                }
-                modconfig = *useconfig
-        }
-        if cfg.ServerWGPort != ""{
-                modconfig.Client.ServerWGPort = cfg.ServerWGPort
-        }
-        if cfg.ServerGRPCPort != ""{
-                modconfig.Client.ServerGRPCPort = cfg.ServerGRPCPort
-        }
-        if cfg.ServerAPIPort != ""{
-                modconfig.Client.ServerAPIPort = cfg.ServerAPIPort
-        }
-        if cfg.PublicKey != ""{
-                modconfig.Client.PublicKey = cfg.PublicKey
-        }
-        if cfg.PrivateKey != ""{
-                modconfig.Client.PrivateKey = cfg.PrivateKey
-        }
-        if cfg.ServerPublicEndpoint != ""{
-                modconfig.Client.ServerPublicEndpoint = cfg.ServerPublicEndpoint
-        }
-        if cfg.ServerPrivateAddress != ""{
-                modconfig.Client.ServerPrivateAddress = cfg.ServerPrivateAddress
-        }
-	if cfg.Address != ""{
-                modconfig.Client.Address = cfg.Address
-        }
-        if cfg.Address6 != ""{
-                modconfig.Client.Address6 = cfg.Address6
-        }
-        if cfg.Network != ""{
-                modconfig.Client.Network = cfg.Network
-        }
-        if cfg.ServerKey != ""{
-                modconfig.Client.ServerKey = cfg.ServerKey
-        }
-        if cfg.AccessKey != ""{
-                modconfig.Client.AccessKey = cfg.AccessKey
-        }
-        if cfg.ClientID != ""{
-                modconfig.Client.ClientID = cfg.ClientID
-        }
-
-        err = WriteGlobal(&modconfig)
-        return err
+func ModGlobalConfig(cfg models.IntClient) error {
+	var modconfig GlobalConfig
+	var err error
+	if FileExists("/etc/netclient/netconfig-global-001") {
+		useconfig, err := ReadGlobalConfig()
+		if err != nil {
+			return err
+		}
+		modconfig = *useconfig
+	}
+	if cfg.ServerWGPort != "" {
+		modconfig.Client.ServerWGPort = cfg.ServerWGPort
+	}
+	if cfg.ServerGRPCPort != "" {
+		modconfig.Client.ServerGRPCPort = cfg.ServerGRPCPort
+	}
+	if cfg.ServerAPIPort != "" {
+		modconfig.Client.ServerAPIPort = cfg.ServerAPIPort
+	}
+	if cfg.PublicKey != "" {
+		modconfig.Client.PublicKey = cfg.PublicKey
+	}
+	if cfg.PrivateKey != "" {
+		modconfig.Client.PrivateKey = cfg.PrivateKey
+	}
+	if cfg.ServerPublicEndpoint != "" {
+		modconfig.Client.ServerPublicEndpoint = cfg.ServerPublicEndpoint
+	}
+	if cfg.ServerPrivateAddress != "" {
+		modconfig.Client.ServerPrivateAddress = cfg.ServerPrivateAddress
+	}
+	if cfg.Address != "" {
+		modconfig.Client.Address = cfg.Address
+	}
+	if cfg.Address6 != "" {
+		modconfig.Client.Address6 = cfg.Address6
+	}
+	if cfg.Network != "" {
+		modconfig.Client.Network = cfg.Network
+	}
+	if cfg.ServerKey != "" {
+		modconfig.Client.ServerKey = cfg.ServerKey
+	}
+	if cfg.AccessKey != "" {
+		modconfig.Client.AccessKey = cfg.AccessKey
+	}
+	if cfg.ClientID != "" {
+		modconfig.Client.ClientID = cfg.ClientID
+	}
+	err = WriteGlobal(&modconfig)
+	return err
 }
 
-
-
-func ModConfig(node *nodepb.Node) error{
-        network := node.Nodenetwork
-        if network == "" {
-                return errors.New("No Network Provided")
-        }
+func ModConfig(node *nodepb.Node) error {
+	network := node.Nodenetwork
+	if network == "" {
+		return errors.New("No Network Provided")
+	}
 	var modconfig ClientConfig
 	var err error
-	if FileExists("/etc/netclient/netconfig-"+network) {
+	if FileExists("/etc/netclient/netconfig-" + network) {
 		useconfig, err := ReadConfig(network)
 		if err != nil {
 			return err
 		}
 		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 := 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.Isdualstack == true {
+		nodecfg.IsDualStack = "yes"
+	}
+	if node.Udpholepunch != "" {
+		nodecfg.UDPHolePunch = node.Udpholepunch
+	}
 	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
-        err = Write(&modconfig, network)
-        return err
+		nodecfg.IsIngressGateway = "no"
+	}
+	if node.Localrange != "" && node.Islocal {
+		nodecfg.IsLocal = "yes"
+		nodecfg.LocalRange = node.Localrange
+	}
+	modconfig.Node = nodecfg
+	err = Write(&modconfig, network)
+	return err
 }
 
-func GetCLIConfig(c *cli.Context) (ClientConfig, error){
+func GetCLIConfig(c *cli.Context) (ClientConfig, error) {
 	var cfg ClientConfig
 	if c.String("token") != "" {
-                tokenbytes, err := base64.StdEncoding.DecodeString(c.String("token"))
-                if err  != nil {
+		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 )
+			log.Println("error converting token json to object", tokenbytes)
 			return cfg, err
 		}
 
@@ -391,17 +393,17 @@ func GetCLIConfig(c *cli.Context) (ClientConfig, error){
 				cfg.Server.APIAddress = cfg.Server.APIAddress + ":" + accesstoken.ServerConfig.APIPort
 			}
 		}
-                if accesstoken.ServerConfig.GRPCConnString != "" {
-                        cfg.Server.GRPCAddress = accesstoken.ServerConfig.GRPCConnString
-                } else {
-                        cfg.Server.GRPCAddress = accesstoken.ServerConfig.GRPCHost
-                        if accesstoken.ServerConfig.GRPCPort != "" {
-                                cfg.Server.GRPCAddress = cfg.Server.GRPCAddress + ":" + accesstoken.ServerConfig.GRPCPort
-                        }
-                }
-                cfg.Network = accesstoken.ClientConfig.Network
-                cfg.Node.Network = accesstoken.ClientConfig.Network
-                cfg.Server.AccessKey = accesstoken.ClientConfig.Key
+		if accesstoken.ServerConfig.GRPCConnString != "" {
+			cfg.Server.GRPCAddress = accesstoken.ServerConfig.GRPCConnString
+		} else {
+			cfg.Server.GRPCAddress = accesstoken.ServerConfig.GRPCHost
+			if accesstoken.ServerConfig.GRPCPort != "" {
+				cfg.Server.GRPCAddress = cfg.Server.GRPCAddress + ":" + accesstoken.ServerConfig.GRPCPort
+			}
+		}
+		cfg.Network = accesstoken.ClientConfig.Network
+		cfg.Node.Network = accesstoken.ClientConfig.Network
+		cfg.Server.AccessKey = accesstoken.ClientConfig.Key
 		cfg.Node.LocalRange = accesstoken.ClientConfig.LocalRange
 		cfg.Server.GRPCSSL = accesstoken.ServerConfig.GRPCSSL
 		cfg.Server.GRPCWireGuard = accesstoken.WG.GRPCWireGuard
@@ -409,9 +411,9 @@ func GetCLIConfig(c *cli.Context) (ClientConfig, error){
 		if c.String("grpcserver") != "" {
 			cfg.Server.GRPCAddress = c.String("grpcserver")
 		}
-                if c.String("apiserver") != "" {
-                        cfg.Server.APIAddress = c.String("apiserver")
-                }
+		if c.String("apiserver") != "" {
+			cfg.Server.APIAddress = c.String("apiserver")
+		}
 		if c.String("key") != "" {
 			cfg.Server.AccessKey = c.String("key")
 		}
@@ -422,26 +424,26 @@ func GetCLIConfig(c *cli.Context) (ClientConfig, error){
 		if c.String("localrange") != "" {
 			cfg.Node.LocalRange = c.String("localrange")
 		}
-                if c.String("grpcssl") != "" {
-                        cfg.Server.GRPCSSL = c.String("grpcssl")
-                }
-                if c.String("corednsaddr") != "" {
-                        cfg.Server.CoreDNSAddr = c.String("corednsaddr")
-                }
-                if c.String("grpcwg") != "" {
-                        cfg.Server.GRPCWireGuard = c.String("grpcwg")
-                }
+		if c.String("grpcssl") != "" {
+			cfg.Server.GRPCSSL = c.String("grpcssl")
+		}
+		if c.String("corednsaddr") != "" {
+			cfg.Server.CoreDNSAddr = c.String("corednsaddr")
+		}
+		if c.String("grpcwg") != "" {
+			cfg.Server.GRPCWireGuard = c.String("grpcwg")
+		}
 
 	} else {
 		cfg.Server.GRPCAddress = c.String("grpcserver")
 		cfg.Server.APIAddress = c.String("apiserver")
 		cfg.Server.AccessKey = c.String("key")
-                cfg.Network = c.String("network")
-                cfg.Node.Network = c.String("network")
-                cfg.Node.LocalRange = c.String("localrange")
-                cfg.Server.GRPCWireGuard = c.String("grpcwg")
-                cfg.Server.GRPCSSL = c.String("grpcssl")
-                cfg.Server.CoreDNSAddr = c.String("corednsaddr")
+		cfg.Network = c.String("network")
+		cfg.Node.Network = c.String("network")
+		cfg.Node.LocalRange = c.String("localrange")
+		cfg.Server.GRPCWireGuard = c.String("grpcwg")
+		cfg.Server.GRPCSSL = c.String("grpcssl")
+		cfg.Server.CoreDNSAddr = c.String("corednsaddr")
 	}
 	cfg.Node.Name = c.String("name")
 	cfg.Node.Interface = c.String("interface")
@@ -464,11 +466,12 @@ func GetCLIConfig(c *cli.Context) (ClientConfig, error){
 	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){
+func GetCLIConfigRegister(c *cli.Context) (GlobalConfig, error) {
 	var cfg GlobalConfig
 	if c.String("token") != "" {
 		tokenbytes, err := base64.StdEncoding.DecodeString(c.String("token"))
@@ -476,11 +479,11 @@ func GetCLIConfigRegister(c *cli.Context) (GlobalConfig, error){
 			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
-                }
+		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
@@ -488,54 +491,53 @@ func GetCLIConfigRegister(c *cli.Context) (GlobalConfig, error){
 			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
-                        }
-                }
+		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
-}
+		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
+}
 
 func ReadConfig(network string) (*ClientConfig, error) {
-        if network == "" {
-                err := errors.New("No network provided. Exiting.")
-                return nil, err
-        }
+	if network == "" {
+		err := errors.New("No network provided. Exiting.")
+		return nil, err
+	}
 	nofile := false
 	home := "/etc/netclient"
 	file := fmt.Sprintf(home + "/netconfig-" + network)
@@ -560,33 +562,33 @@ func ReadConfig(network string) (*ClientConfig, error) {
 }
 
 func ReadGlobalConfig() (*GlobalConfig, error) {
-        nofile := false
-        home := "/etc/netclient"
-        file := fmt.Sprintf(home + "/netconfig-global-001")
-        f, err := os.Open(file)
-
-        if err != nil {
-                nofile = true
-        }
-        defer f.Close()
-
-        var cfg GlobalConfig
-
-        if !nofile {
-                decoder := yaml.NewDecoder(f)
-                err = decoder.Decode(&cfg)
-                if err != nil {
-                        fmt.Println("trouble decoding file")
-                        return nil, err
-                }
-        }
-        return &cfg, err
+	nofile := false
+	home := "/etc/netclient"
+	file := fmt.Sprintf(home + "/netconfig-global-001")
+	f, err := os.Open(file)
+
+	if err != nil {
+		nofile = true
+	}
+	defer f.Close()
+
+	var cfg GlobalConfig
+
+	if !nofile {
+		decoder := yaml.NewDecoder(f)
+		err = decoder.Decode(&cfg)
+		if err != nil {
+			fmt.Println("trouble decoding file")
+			return nil, err
+		}
+	}
+	return &cfg, 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()
 }

+ 124 - 124
netclient/functions/join.go

@@ -1,23 +1,24 @@
 package functions
 
 import (
-	"google.golang.org/grpc/credentials"
+	"context"
 	"crypto/tls"
-	"fmt"
 	"errors"
-	"context"
+	"fmt"
 	"log"
-	"net"
 	"math/rand"
+	"net"
 	"time"
-        "github.com/gravitl/netmaker/netclient/config"
-        "github.com/gravitl/netmaker/netclient/wireguard"
-        "github.com/gravitl/netmaker/netclient/server"
-        "github.com/gravitl/netmaker/netclient/local"
-        nodepb "github.com/gravitl/netmaker/grpc"
+
+	nodepb "github.com/gravitl/netmaker/grpc"
+	"github.com/gravitl/netmaker/netclient/config"
+	"github.com/gravitl/netmaker/netclient/local"
+	"github.com/gravitl/netmaker/netclient/server"
+	"github.com/gravitl/netmaker/netclient/wireguard"
 	"golang.zx2c4.com/wireguard/wgctrl"
-        "google.golang.org/grpc"
 	"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
+	"google.golang.org/grpc"
+	"google.golang.org/grpc/credentials"
 	//homedir "github.com/mitchellh/go-homedir"
 )
 
@@ -25,7 +26,7 @@ func JoinNetwork(cfg config.ClientConfig) error {
 
 	hasnet := local.HasNetwork(cfg.Network)
 	if hasnet {
-		   err := errors.New("ALREADY_INSTALLED. Netclient appears to already be installed for " + cfg.Network + ". To re-install, please remove by executing 'sudo netclient leave -n " + cfg.Network + "'. Then re-run the install command.")
+		err := errors.New("ALREADY_INSTALLED. Netclient appears to already be installed for " + cfg.Network + ". To re-install, please remove by executing 'sudo netclient leave -n " + cfg.Network + "'. Then re-run the install command.")
 		return err
 	}
 	log.Println("attempting to join " + cfg.Network + " at " + cfg.Server.GRPCAddress)
@@ -34,73 +35,73 @@ func JoinNetwork(cfg config.ClientConfig) error {
 		return err
 	}
 
-        wgclient, err := wgctrl.New()
-        if err != nil {
+	wgclient, err := wgctrl.New()
+	if err != nil {
 		return err
-        }
-        defer wgclient.Close()
+	}
+	defer wgclient.Close()
 	if cfg.Node.Network == "" {
 		return errors.New("no network provided")
 	}
 	if cfg.Node.LocalRange != "" {
-	if cfg.Node.LocalAddress == "" {
-		log.Println("local vpn, getting local address from range: " + cfg.Node.LocalRange)
-		ifaces, err := net.Interfaces()
-                if err != nil {
-                        return err
-                }
-		_, localrange, err := net.ParseCIDR(cfg.Node.LocalRange)
-		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
+		if cfg.Node.LocalAddress == "" {
+			log.Println("local vpn, getting local address from range: " + cfg.Node.LocalRange)
+			ifaces, err := net.Interfaces()
+			if err != nil {
+				return err
 			}
-			addrs, err := i.Addrs()
+			_, localrange, err := net.ParseCIDR(cfg.Node.LocalRange)
 			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()
-						if cfg.Node.IsLocal == "yes" {
-							found = localrange.Contains(ip)
-						} else {
-							found = true
+
+			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()
+							if cfg.Node.IsLocal == "yes" {
+								found = localrange.Contains(ip)
+							} else {
+								found = true
+							}
 						}
-					}
-				case *net.IPAddr:
-					if  !found {
-						ip = v.IP
-						local = ip.String()
-						if cfg.Node.IsLocal == "yes" {
-							found = localrange.Contains(ip)
+					case *net.IPAddr:
+						if !found {
+							ip = v.IP
+							local = ip.String()
+							if cfg.Node.IsLocal == "yes" {
+								found = localrange.Contains(ip)
 
-						} else {
-							found = true
+							} else {
+								found = true
+							}
 						}
 					}
 				}
 			}
+			cfg.Node.LocalAddress = local
 		}
-		cfg.Node.LocalAddress = local
-	}
 	}
 	if cfg.Node.Password == "" {
 		cfg.Node.Password = GenPass()
 	}
-        if cfg.Node.Endpoint == "" {
+	if cfg.Node.Endpoint == "" {
 		if cfg.Node.IsLocal == "yes" && cfg.Node.LocalAddress != "" {
 			cfg.Node.Endpoint = cfg.Node.LocalAddress
 		} else {
@@ -111,9 +112,9 @@ func JoinNetwork(cfg config.ClientConfig) error {
 				return err
 			}
 		}
-        } else {
-                cfg.Node.Endpoint = cfg.Node.Endpoint
-        }
+	} else {
+		cfg.Node.Endpoint = cfg.Node.Endpoint
+	}
 	if cfg.Node.PrivateKey == "" {
 		privatekey, err := wgtypes.GeneratePrivateKey()
 		if err != nil {
@@ -130,7 +131,7 @@ func JoinNetwork(cfg config.ClientConfig) error {
 		} else if len(macs) == 0 {
 			log.Fatal()
 		} else {
-			cfg.Node.MacAddress  = macs[0]
+			cfg.Node.MacAddress = macs[0]
 		}
 	}
 	if cfg.Node.Port == 0 {
@@ -148,48 +149,48 @@ func JoinNetwork(cfg config.ClientConfig) error {
 	}
 	conn, err := grpc.Dial(cfg.Server.GRPCAddress, requestOpts)
 
-        if err != nil {
-                log.Fatalf("Unable to establish client connection to " + cfg.Server.GRPCAddress + ": %v", err)
-        }
+	if err != nil {
+		log.Fatalf("Unable to establish client connection to "+cfg.Server.GRPCAddress+": %v", err)
+	}
 
-        wcclient = nodepb.NewNodeServiceClient(conn)
+	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,
+	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,
-        }
-        err = config.ModConfig(postnode)
-        if err != nil {
+		Interface:    cfg.Node.Interface,
+		Publickey:    cfg.Node.PublicKey,
+		Name:         cfg.Node.Name,
+		Endpoint:     cfg.Node.Endpoint,
+	}
+	err = config.ModConfig(postnode)
+	if err != nil {
 		return err
-        }
+	}
 
-        res, err := wcclient.CreateNode(
-                context.TODO(),
-                &nodepb.CreateNodeReq{
-                        Node: postnode,
-                },
-        )
-        if err != nil {
-                return err
-        }
+	res, err := wcclient.CreateNode(
+		context.TODO(),
+		&nodepb.CreateNodeReq{
+			Node: postnode,
+		},
+	)
+	if err != nil {
+		return err
+	}
 	log.Println("node created on remote server...updating configs")
-        node := res.Node
-        if err != nil {
-                return err
-        }
+	node := res.Node
+	if err != nil {
+		return err
+	}
 
-       if node.Dnsoff==true  {
+	if node.Dnsoff == true {
 		cfg.Node.DNS = "yes"
 	}
 	if !(cfg.Node.IsLocal == "yes") && node.Islocal && node.Localrange != "" {
@@ -199,15 +200,15 @@ func JoinNetwork(cfg config.ClientConfig) error {
 		}
 		node.Endpoint = node.Localaddress
 	}
-        err = config.ModConfig(node)
-        if err != nil {
-                return err
-        }
+	err = config.ModConfig(node)
+	if err != nil {
+		return err
+	}
 
 	if node.Ispending {
 		fmt.Println("Node is marked as PENDING.")
 		fmt.Println("Awaiting approval from Admin before configuring WireGuard.")
-	        if cfg.Daemon != "off" {
+		if cfg.Daemon != "off" {
 			err = local.ConfigureSystemD(cfg.Network)
 			return err
 		}
@@ -217,23 +218,23 @@ func JoinNetwork(cfg config.ClientConfig) error {
 
 	if err != nil {
 		log.Println("failed to retrieve peers")
-                return err
-        }
+		return err
+	}
 	err = wireguard.StorePrivKey(cfg.Node.PrivateKey, cfg.Network)
-        if err != nil {
-                return err
-        }
-        log.Println("starting wireguard")
+	if err != nil {
+		return err
+	}
+	log.Println("starting wireguard")
 	err = wireguard.InitWireguard(node, cfg.Node.PrivateKey, peers, hasGateway, gateways)
-        if err != nil {
-                return err
-        }
+	if err != nil {
+		return err
+	}
 	if cfg.Daemon != "off" {
 		err = local.ConfigureSystemD(cfg.Network)
 	}
-        if err != nil {
-                return err
-        }
+	if err != nil {
+		return err
+	}
 
 	return err
 }
@@ -241,16 +242,15 @@ func JoinNetwork(cfg config.ClientConfig) error {
 //generate an access key value
 func GenPass() string {
 
-        var seededRand *rand.Rand = rand.New(
-                rand.NewSource(time.Now().UnixNano()))
+	var seededRand *rand.Rand = rand.New(
+		rand.NewSource(time.Now().UnixNano()))
 
-        length := 16
-        charset := "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
+	length := 16
+	charset := "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
 
-        b := make([]byte, length)
-        for i := range b {
-                b[i] = charset[seededRand.Intn(len(charset))]
-        }
-        return string(b)
+	b := make([]byte, length)
+	for i := range b {
+		b[i] = charset[seededRand.Intn(len(charset))]
+	}
+	return string(b)
 }
-

+ 370 - 364
netclient/main.go

@@ -1,379 +1,385 @@
 package main
 
 import (
-    "errors"
-    "github.com/gravitl/netmaker/netclient/command"
-    "github.com/gravitl/netmaker/netclient/config"
-    "github.com/urfave/cli/v2"
-    "log"
-    "os"
-    "os/exec"
-    "strconv"
+	"errors"
+	"log"
+	"os"
+	"os/exec"
+	"strconv"
+
+	"github.com/gravitl/netmaker/netclient/command"
+	"github.com/gravitl/netmaker/netclient/config"
+	"github.com/urfave/cli/v2"
 )
 
 func main() {
-        app := cli.NewApp()
-        app.Name = "Netclient CLI"
-        app.Usage = "Netmaker's netclient agent and CLI. Used to perform interactions with Netmaker server and set local WireGuard config."
-        app.Version = "v0.5.11"
-
-    cliFlags := []cli.Flag{
-        &cli.StringFlag{
-            Name:  "network",
-            Aliases: []string{"n"},
-            EnvVars: []string{"NETCLIENT_NETWORK"},
-	    Value: "all",
-	    Usage: "Network to perform specified action against.",
-        },
-        &cli.StringFlag{
-            Name:  "password",
-            Aliases: []string{"p"},
-            EnvVars: []string{"NETCLIENT_PASSWORD"},
-            Value: "badpassword",
-            Usage: "Password for authenticating with netmaker.",
-        },
-        &cli.StringFlag{
-            Name:  "endpoint",
-            Aliases: []string{"e"},
-            EnvVars: []string{"NETCLIENT_ENDPOINT"},
-            Value: "",
-            Usage: "Reachable (usually public) address for WireGuard (not the private WG address).",
-        },
-        &cli.StringFlag{
-            Name:  "macaddress",
-            Aliases: []string{"m"},
-            EnvVars: []string{"NETCLIENT_MACADDRESS"},
-            Value: "",
-            Usage: "Mac Address for this machine. Used as a unique identifier within Netmaker network.",
-        },
-        &cli.StringFlag{
-            Name:  "publickey",
-            Aliases: []string{"pubkey"},
-            EnvVars: []string{"NETCLIENT_PUBLICKEY"},
-            Value: "",
-            Usage: "Public Key for WireGuard Interface.",
-        },
-        &cli.StringFlag{
-            Name:  "privatekey",
-            Aliases: []string{"privkey"},
-            EnvVars: []string{"NETCLIENT_PRIVATEKEY"},
-            Value: "",
-            Usage: "Private Key for WireGuard Interface.",
-        },
-        &cli.StringFlag{
-            Name:  "port",
-            EnvVars: []string{"NETCLIENT_PORT"},
-            Value: "",
-            Usage: "Port for WireGuard Interface.",
-        },
-        &cli.IntFlag{
-            Name:  "keepalive",
-            EnvVars: []string{"NETCLIENT_KEEPALIVE"},
-            Value: 0,
-            Usage: "Default PersistentKeepAlive for Peers in WireGuard Interface.",
-        },
-        &cli.StringFlag{
-            Name:  "operatingsystem",
-            Aliases: []string{"os"},
-            EnvVars: []string{"NETCLIENT_OS"},
-            Value: "",
-            Usage: "Identifiable name for machine within Netmaker network.",
-        },
-        &cli.StringFlag{
-            Name:  "name",
-            EnvVars: []string{"NETCLIENT_NAME"},
-            Value: "",
-            Usage: "Identifiable name for machine within Netmaker network.",
-        },
-        &cli.StringFlag{
-            Name:  "localaddress",
-            EnvVars: []string{"NETCLIENT_LOCALADDRESS"},
-            Value: "",
-            Usage: "Local address for machine. Can be used in place of Endpoint for machines on the same LAN.",
-        },
-        &cli.StringFlag{
-            Name:  "address",
-            Aliases: []string{"a"},
-            EnvVars: []string{"NETCLIENT_ADDRESS"},
-            Value: "",
-            Usage: "WireGuard address for machine within Netmaker network.",
-        },
-        &cli.StringFlag{
-            Name:  "addressIPv6",
-            Aliases: []string{"a6"},
-            EnvVars: []string{"NETCLIENT_ADDRESSIPV6"},
-            Value: "",
-            Usage: "WireGuard address for machine within Netmaker network.",
-        },
-        &cli.StringFlag{
-            Name:  "interface",
-            Aliases: []string{"i"},
-            EnvVars: []string{"NETCLIENT_INTERFACE"},
-            Value: "",
-            Usage: "WireGuard local network interface name.",
-        },
-        &cli.StringFlag{
-            Name:  "apiserver",
-            EnvVars: []string{"NETCLIENT_API_SERVER"},
-            Value: "",
-	    Usage: "Address + GRPC Port (e.g. 1.2.3.4:50051) of Netmaker server.",
-        },
-        &cli.StringFlag{
-            Name:  "grpcserver",
-            EnvVars: []string{"NETCLIENT_GRPC_SERVER"},
-            Value: "",
-            Usage: "Address + API Port (e.g. 1.2.3.4:8081) of Netmaker server.",
-        },
-        &cli.StringFlag{
-            Name:  "key",
-            Aliases: []string{"k"},
-            EnvVars: []string{"NETCLIENT_ACCESSKEY"},
-            Value: "",
-            Usage: "Access Key for signing up machine with Netmaker server during initial 'add'.",
-        },
-        &cli.StringFlag{
-            Name:  "token",
-            Aliases: []string{"t"},
-            EnvVars: []string{"NETCLIENT_ACCESSTOKEN"},
-            Value: "",
-            Usage: "Access Token for signing up machine with Netmaker server during initial 'add'.",
-        },
-        &cli.StringFlag{
-            Name:  "localrange",
-            EnvVars: []string{"NETCLIENT_LOCALRANGE"},
-            Value: "",
-            Usage: "Local Range if network is local, for instance 192.168.1.0/24.",
-        },
-        &cli.StringFlag{
-            Name:  "dns",
-            EnvVars: []string{"NETCLIENT_DNS"},
-            Value: "on",
-            Usage: "Sets private dns if 'on'. Ignores if 'off'. Will retrieve from network if unset.",
-        },
-        &cli.StringFlag{
-            Name:  "islocal",
-            EnvVars: []string{"NETCLIENT_IS_LOCAL"},
-            Value: "",
-            Usage: "Sets endpoint to local address if 'yes'. Ignores if 'no'. Will retrieve from network if unset.",
-        },
-        &cli.StringFlag{
-            Name:  "isdualstack",
-            EnvVars: []string{"NETCLIENT_IS_DUALSTACK"},
-            Value: "",
-            Usage: "Sets ipv6 address if 'yes'. Ignores if 'no'. Will retrieve from network if unset.",
-        },
-        &cli.StringFlag{
-            Name:  "ipforwarding",
-            EnvVars: []string{"NETCLIENT_IPFORWARDING"},
-            Value: "on",
-	    Usage: "Sets ip forwarding on if 'on'. Ignores if 'off'. On by default.",
-        },
-        &cli.StringFlag{
-            Name:  "postup",
-            EnvVars: []string{"NETCLIENT_POSTUP"},
-            Value: "",
-            Usage: "Sets PostUp command for WireGuard.",
-        },
-        &cli.StringFlag{
-            Name:  "postdown",
-            EnvVars: []string{"NETCLIENT_POSTDOWN"},
-            Value: "",
-            Usage: "Sets PostDown command for WireGuard.",
-        },
-        &cli.StringFlag{
-            Name:  "daemon",
-            EnvVars: []string{"NETCLIENT_DAEMON"},
-            Value: "on",
-            Usage: "Installs daemon if 'on'. Ignores if 'off'. On by default.",
-        },
-        &cli.StringFlag{
-            Name:  "roaming",
-            EnvVars: []string{"NETCLIENT_ROAMING"},
-            Value: "on",
-            Usage: "Checks for IP changes if 'on'. Ignores if 'off'. On by default.",
-        },
-    }
+	app := cli.NewApp()
+	app.Name = "Netclient CLI"
+	app.Usage = "Netmaker's netclient agent and CLI. Used to perform interactions with Netmaker server and set local WireGuard config."
+	app.Version = "v0.5.11"
 
-    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)
-		if err != nil {
-			return err
-		}
-		if cfg.Network == "all" {
-			err = errors.New("No network provided.")
-			return err
-		}
-                if cfg.Server.GRPCAddress == "" {
-                        err = errors.New("No server address provided.")
-                        return err
-                }
-		err = command.Join(cfg)
-                return err
-            },
-        },
-        {
-            Name:  "leave",
-            Usage: "Leave a Netmaker network.",
-            Flags: cliFlags,
-            // 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)
-                if err != nil {
-                        return err
-                }
-                err = command.Leave(cfg)
-                return err
-            },
-        },
-        {
-            Name:  "checkin",
-            Usage: "Checks for local changes and then checks into the specified Netmaker network to ask about remote changes.",
-            Flags: cliFlags,
-            // 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)
-                if err != nil {
-                        return err
-                }
-                err = command.CheckIn(cfg)
-                return err
-            },
-        },
-        {
-            Name:  "push",
-            Usage: "Push configuration changes to server.",
-            Flags: cliFlags,
-            // 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)
-                if err != nil {
-                        return err
-                }
-                err = command.Push(cfg)
-                return err
-            },
-        },
-        {
-            Name:  "pull",
-            Usage: "Pull latest configuration and peers from server.",
-            Flags: cliFlags,
-            // 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)
-                if err != nil {
-                        return err
-                }
-                err = command.Pull(cfg)
-                return err
-            },
-        },
-        {
-            Name:  "list",
-            Usage: "Get list of networks.",
-            Flags: cliFlags,
-            // 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)
-                if err != nil {
-                        return err
-                }
-                err = command.List(cfg)
-                return err
-            },
-        },
-        {
-            Name:  "uninstall",
-            Usage: "Uninstall the netclient system service.",
-            Flags: cliFlags,
-            // the action, or code that will be executed when
-            // we execute our `ns` command
-            Action: func(c *cli.Context) error {
-                cfg, err := config.ReadGlobalConfig()
-                if err != nil {
-                        return err
-                }
-                var gconf config.GlobalConfig
-		gconf = *cfg
-		err = command.Uninstall(gconf)
-                return err
-            },
-        },
-        {
-            Name:  "unregister",
-            Usage: "Unregister the netclient from secure server GRPC.",
-            Flags: cliFlags,
-            // the action, or code that will be executed when
-            // we execute our `ns` command
-            Action: func(c *cli.Context) error {
-                cfg, err := config.ReadGlobalConfig()
-                if err != nil {
-                        return err
-                }
-                var gconf config.GlobalConfig
-                gconf = *cfg
-                err = command.Unregister(gconf)
-                return err
-            },
-        },
-    }
+	cliFlags := []cli.Flag{
+		&cli.StringFlag{
+			Name:    "network",
+			Aliases: []string{"n"},
+			EnvVars: []string{"NETCLIENT_NETWORK"},
+			Value:   "all",
+			Usage:   "Network to perform specified action against.",
+		},
+		&cli.StringFlag{
+			Name:    "password",
+			Aliases: []string{"p"},
+			EnvVars: []string{"NETCLIENT_PASSWORD"},
+			Value:   "badpassword",
+			Usage:   "Password for authenticating with netmaker.",
+		},
+		&cli.StringFlag{
+			Name:    "endpoint",
+			Aliases: []string{"e"},
+			EnvVars: []string{"NETCLIENT_ENDPOINT"},
+			Value:   "",
+			Usage:   "Reachable (usually public) address for WireGuard (not the private WG address).",
+		},
+		&cli.StringFlag{
+			Name:    "macaddress",
+			Aliases: []string{"m"},
+			EnvVars: []string{"NETCLIENT_MACADDRESS"},
+			Value:   "",
+			Usage:   "Mac Address for this machine. Used as a unique identifier within Netmaker network.",
+		},
+		&cli.StringFlag{
+			Name:    "publickey",
+			Aliases: []string{"pubkey"},
+			EnvVars: []string{"NETCLIENT_PUBLICKEY"},
+			Value:   "",
+			Usage:   "Public Key for WireGuard Interface.",
+		},
+		&cli.StringFlag{
+			Name:    "privatekey",
+			Aliases: []string{"privkey"},
+			EnvVars: []string{"NETCLIENT_PRIVATEKEY"},
+			Value:   "",
+			Usage:   "Private Key for WireGuard Interface.",
+		},
+		&cli.StringFlag{
+			Name:    "port",
+			EnvVars: []string{"NETCLIENT_PORT"},
+			Value:   "",
+			Usage:   "Port for WireGuard Interface.",
+		},
+		&cli.IntFlag{
+			Name:    "keepalive",
+			EnvVars: []string{"NETCLIENT_KEEPALIVE"},
+			Value:   0,
+			Usage:   "Default PersistentKeepAlive for Peers in WireGuard Interface.",
+		},
+		&cli.StringFlag{
+			Name:    "operatingsystem",
+			Aliases: []string{"os"},
+			EnvVars: []string{"NETCLIENT_OS"},
+			Value:   "",
+			Usage:   "Identifiable name for machine within Netmaker network.",
+		},
+		&cli.StringFlag{
+			Name:    "name",
+			EnvVars: []string{"NETCLIENT_NAME"},
+			Value:   "",
+			Usage:   "Identifiable name for machine within Netmaker network.",
+		},
+		&cli.StringFlag{
+			Name:    "localaddress",
+			EnvVars: []string{"NETCLIENT_LOCALADDRESS"},
+			Value:   "",
+			Usage:   "Local address for machine. Can be used in place of Endpoint for machines on the same LAN.",
+		},
+		&cli.StringFlag{
+			Name:    "address",
+			Aliases: []string{"a"},
+			EnvVars: []string{"NETCLIENT_ADDRESS"},
+			Value:   "",
+			Usage:   "WireGuard address for machine within Netmaker network.",
+		},
+		&cli.StringFlag{
+			Name:    "addressIPv6",
+			Aliases: []string{"a6"},
+			EnvVars: []string{"NETCLIENT_ADDRESSIPV6"},
+			Value:   "",
+			Usage:   "WireGuard address for machine within Netmaker network.",
+		},
+		&cli.StringFlag{
+			Name:    "interface",
+			Aliases: []string{"i"},
+			EnvVars: []string{"NETCLIENT_INTERFACE"},
+			Value:   "",
+			Usage:   "WireGuard local network interface name.",
+		},
+		&cli.StringFlag{
+			Name:    "apiserver",
+			EnvVars: []string{"NETCLIENT_API_SERVER"},
+			Value:   "",
+			Usage:   "Address + GRPC Port (e.g. 1.2.3.4:50051) of Netmaker server.",
+		},
+		&cli.StringFlag{
+			Name:    "grpcserver",
+			EnvVars: []string{"NETCLIENT_GRPC_SERVER"},
+			Value:   "",
+			Usage:   "Address + API Port (e.g. 1.2.3.4:8081) of Netmaker server.",
+		},
+		&cli.StringFlag{
+			Name:    "key",
+			Aliases: []string{"k"},
+			EnvVars: []string{"NETCLIENT_ACCESSKEY"},
+			Value:   "",
+			Usage:   "Access Key for signing up machine with Netmaker server during initial 'add'.",
+		},
+		&cli.StringFlag{
+			Name:    "token",
+			Aliases: []string{"t"},
+			EnvVars: []string{"NETCLIENT_ACCESSTOKEN"},
+			Value:   "",
+			Usage:   "Access Token for signing up machine with Netmaker server during initial 'add'.",
+		},
+		&cli.StringFlag{
+			Name:    "localrange",
+			EnvVars: []string{"NETCLIENT_LOCALRANGE"},
+			Value:   "",
+			Usage:   "Local Range if network is local, for instance 192.168.1.0/24.",
+		},
+		&cli.StringFlag{
+			Name:    "dns",
+			EnvVars: []string{"NETCLIENT_DNS"},
+			Value:   "on",
+			Usage:   "Sets private dns if 'on'. Ignores if 'off'. Will retrieve from network if unset.",
+		},
+		&cli.StringFlag{
+			Name:    "islocal",
+			EnvVars: []string{"NETCLIENT_IS_LOCAL"},
+			Value:   "",
+			Usage:   "Sets endpoint to local address if 'yes'. Ignores if 'no'. Will retrieve from network if unset.",
+		},
+		&cli.StringFlag{
+			Name:    "isdualstack",
+			EnvVars: []string{"NETCLIENT_IS_DUALSTACK"},
+			Value:   "",
+			Usage:   "Sets ipv6 address if 'yes'. Ignores if 'no'. Will retrieve from network if unset.",
+		},
+		&cli.StringFlag{
+			Name:    "udpholepunch",
+			EnvVars: []string{"NETCLIENT_UDP_HOLEPUNCH"},
+			Value:   "",
+			Usage:   "Turns on udp holepunching if 'yes'. Ignores if 'no'. Will retrieve from network if unset.",
+		},
+		&cli.StringFlag{
+			Name:    "ipforwarding",
+			EnvVars: []string{"NETCLIENT_IPFORWARDING"},
+			Value:   "on",
+			Usage:   "Sets ip forwarding on if 'on'. Ignores if 'off'. On by default.",
+		},
+		&cli.StringFlag{
+			Name:    "postup",
+			EnvVars: []string{"NETCLIENT_POSTUP"},
+			Value:   "",
+			Usage:   "Sets PostUp command for WireGuard.",
+		},
+		&cli.StringFlag{
+			Name:    "postdown",
+			EnvVars: []string{"NETCLIENT_POSTDOWN"},
+			Value:   "",
+			Usage:   "Sets PostDown command for WireGuard.",
+		},
+		&cli.StringFlag{
+			Name:    "daemon",
+			EnvVars: []string{"NETCLIENT_DAEMON"},
+			Value:   "on",
+			Usage:   "Installs daemon if 'on'. Ignores if 'off'. On by default.",
+		},
+		&cli.StringFlag{
+			Name:    "roaming",
+			EnvVars: []string{"NETCLIENT_ROAMING"},
+			Value:   "on",
+			Usage:   "Checks for IP changes if 'on'. Ignores if 'off'. On by default.",
+		},
+	}
 
-    // start our application
-         getID := exec.Command("id", "-u")
-         out, err := getID.Output()
+	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)
+				if err != nil {
+					return err
+				}
+				if cfg.Network == "all" {
+					err = errors.New("No network provided.")
+					return err
+				}
+				if cfg.Server.GRPCAddress == "" {
+					err = errors.New("No server address provided.")
+					return err
+				}
+				err = command.Join(cfg)
+				return err
+			},
+		},
+		{
+			Name:  "leave",
+			Usage: "Leave a Netmaker network.",
+			Flags: cliFlags,
+			// 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)
+				if err != nil {
+					return err
+				}
+				err = command.Leave(cfg)
+				return err
+			},
+		},
+		{
+			Name:  "checkin",
+			Usage: "Checks for local changes and then checks into the specified Netmaker network to ask about remote changes.",
+			Flags: cliFlags,
+			// 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)
+				if err != nil {
+					return err
+				}
+				err = command.CheckIn(cfg)
+				return err
+			},
+		},
+		{
+			Name:  "push",
+			Usage: "Push configuration changes to server.",
+			Flags: cliFlags,
+			// 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)
+				if err != nil {
+					return err
+				}
+				err = command.Push(cfg)
+				return err
+			},
+		},
+		{
+			Name:  "pull",
+			Usage: "Pull latest configuration and peers from server.",
+			Flags: cliFlags,
+			// 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)
+				if err != nil {
+					return err
+				}
+				err = command.Pull(cfg)
+				return err
+			},
+		},
+		{
+			Name:  "list",
+			Usage: "Get list of networks.",
+			Flags: cliFlags,
+			// 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)
+				if err != nil {
+					return err
+				}
+				err = command.List(cfg)
+				return err
+			},
+		},
+		{
+			Name:  "uninstall",
+			Usage: "Uninstall the netclient system service.",
+			Flags: cliFlags,
+			// the action, or code that will be executed when
+			// we execute our `ns` command
+			Action: func(c *cli.Context) error {
+				cfg, err := config.ReadGlobalConfig()
+				if err != nil {
+					return err
+				}
+				var gconf config.GlobalConfig
+				gconf = *cfg
+				err = command.Uninstall(gconf)
+				return err
+			},
+		},
+		{
+			Name:  "unregister",
+			Usage: "Unregister the netclient from secure server GRPC.",
+			Flags: cliFlags,
+			// the action, or code that will be executed when
+			// we execute our `ns` command
+			Action: func(c *cli.Context) error {
+				cfg, err := config.ReadGlobalConfig()
+				if err != nil {
+					return err
+				}
+				var gconf config.GlobalConfig
+				gconf = *cfg
+				err = command.Unregister(gconf)
+				return err
+			},
+		},
+	}
 
-         if err != nil {
-                 log.Fatal(err)
-         }
-         id, err := strconv.Atoi(string(out[:len(out)-1]))
+	// start our application
+	getID := exec.Command("id", "-u")
+	out, err := getID.Output()
 
-         if err != nil {
-                 log.Fatal(err)
-         }
+	if err != nil {
+		log.Fatal(err)
+	}
+	id, err := strconv.Atoi(string(out[:len(out)-1]))
 
-         if id != 0 {
-                 log.Fatal("This program must be run with elevated privileges (sudo). This program installs a SystemD service and configures WireGuard and networking rules. Please re-run with sudo/root.")
-         }
+	if err != nil {
+		log.Fatal(err)
+	}
 
+	if id != 0 {
+		log.Fatal("This program must be run with elevated privileges (sudo). This program installs a SystemD service and configures WireGuard and networking rules. Please re-run with sudo/root.")
+	}
 
-        _, err = exec.LookPath("wg")
-        if err != nil {
-                log.Println(err)
-                log.Fatal("WireGuard not installed. Please install WireGuard (wireguard-tools) and try again.")
-        }
+	_, err = exec.LookPath("wg")
+	if err != nil {
+		log.Println(err)
+		log.Fatal("WireGuard not installed. Please install WireGuard (wireguard-tools) and try again.")
+	}
 
-    err = app.Run(os.Args)
-    if err != nil {
-        log.Fatal(err)
-    }
+	err = app.Run(os.Args)
+	if err != nil {
+		log.Fatal(err)
+	}
 }

+ 285 - 284
netclient/wireguard/kernel.go

@@ -2,185 +2,183 @@ package wireguard
 
 import (
 	//"github.com/davecgh/go-spew/spew"
-        "google.golang.org/grpc/credentials"
-        "crypto/tls"
-	"fmt"
-	"strconv"
-	"errors"
 	"context"
-        "io/ioutil"
-	"strings"
+	"crypto/tls"
+	"errors"
+	"fmt"
+	"io/ioutil"
 	"log"
 	"net"
 	"os"
 	"os/exec"
-        "github.com/gravitl/netmaker/netclient/config"
-        "github.com/gravitl/netmaker/netclient/local"
-        "github.com/gravitl/netmaker/netclient/auth"
-        "github.com/gravitl/netmaker/netclient/server"
-        nodepb "github.com/gravitl/netmaker/grpc"
-        "github.com/gravitl/netmaker/models"
+	"strconv"
+	"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"
+	"github.com/gravitl/netmaker/netclient/server"
 	"golang.zx2c4.com/wireguard/wgctrl"
-        "google.golang.org/grpc"
-	"google.golang.org/grpc/metadata"
 	"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 InitGRPCWireguard(client models.IntClient) error {
-        //spew.Dump(client)
+	//spew.Dump(client)
 
 	key, err := wgtypes.ParseKey(client.PrivateKey)
-        if err !=  nil {
-                return err
-        }
-        serverkey, err := wgtypes.ParseKey(client.ServerKey)
-        if err !=  nil {
-                return err
-        }
+	if err != nil {
+		return err
+	}
+	serverkey, err := wgtypes.ParseKey(client.ServerKey)
+	if err != nil {
+		return err
+	}
 	serverport, err := strconv.Atoi(client.ServerWGPort)
-        if err !=  nil {
-                return err
-        }
-
-        wgclient, err := wgctrl.New()
-        if err != nil {
-                log.Fatalf("failed to open client: %v", err)
-        }
-        defer wgclient.Close()
-
-        ifacename := "grpc-wg-001"
-        if client.Address6 == "" && client.Address == "" {
-                return errors.New("no address to configure")
-        }
-        cmdIPDevLinkAdd := exec.Command("ip","link", "add", "dev", ifacename, "type",  "wireguard" )
+	if err != nil {
+		return err
+	}
+
+	wgclient, err := wgctrl.New()
+	if err != nil {
+		log.Fatalf("failed to open client: %v", err)
+	}
+	defer wgclient.Close()
+
+	ifacename := "grpc-wg-001"
+	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()
-	        if  err  !=  nil && !strings.Contains(err.Error(), "exists") {
-	                log.Println("Error creating interface")
-	        }
-        }
-        match := false
-        match6 := false
-        addrs, _ := currentiface.Addrs()
+	if err != nil {
+		err = cmdIPDevLinkAdd.Run()
+		if err != nil && !strings.Contains(err.Error(), "exists") {
+			log.Println("Error creating interface")
+		}
+	}
+	match := false
+	match6 := false
+	addrs, _ := currentiface.Addrs()
 
 	//Add IPv4Address (make into separate function)
-        for _, a := range addrs {
-                if strings.Contains(a.String(), client.Address){
-                        match = true
-                }
-                if strings.Contains(a.String(), client.Address6){
-                        match6 = true
-                }
-        }
-        if !match && client.Address != "" {
+	for _, a := range addrs {
+		if strings.Contains(a.String(), client.Address) {
+			match = true
+		}
+		if strings.Contains(a.String(), client.Address6) {
+			match6 = true
+		}
+	}
+	if !match && client.Address != "" {
 		err = cmdIPAddrAdd.Run()
-	        if  err  !=  nil {
-	                log.Println("Error adding ipv4 address")
-		fmt.Println(err)
-	        }
-        }
-        if !match6 && client.Address6 !=""{
-                err = cmdIPAddr6Add.Run()
-                if  err  !=  nil {
-                        log.Println("Error adding ipv6 address")
-                fmt.Println(err)
-                }
-        }
+		if err != nil {
+			log.Println("Error adding ipv4 address")
+			fmt.Println(err)
+		}
+	}
+	if !match6 && client.Address6 != "" {
+		err = cmdIPAddr6Add.Run()
+		if err != nil {
+			log.Println("Error adding ipv6 address")
+			fmt.Println(err)
+		}
+	}
 	var peers []wgtypes.PeerConfig
-        var peeraddr = net.IPNet{
-                 IP: net.ParseIP(client.ServerPrivateAddress),
-                 Mask: net.CIDRMask(32, 32),
-        }
+	var peeraddr = net.IPNet{
+		IP:   net.ParseIP(client.ServerPrivateAddress),
+		Mask: net.CIDRMask(32, 32),
+	}
 	var allowedips []net.IPNet
-        allowedips = append(allowedips, peeraddr)
+	allowedips = append(allowedips, peeraddr)
 	net.ParseIP(client.ServerPublicEndpoint)
 	peer := wgtypes.PeerConfig{
-               PublicKey: serverkey,
-               Endpoint: &net.UDPAddr{
-                         IP:   net.ParseIP(client.ServerPublicEndpoint),
-                         Port: serverport,
-               },
-               ReplaceAllowedIPs: true,
-               AllowedIPs: allowedips,
-        }
+		PublicKey: serverkey,
+		Endpoint: &net.UDPAddr{
+			IP:   net.ParseIP(client.ServerPublicEndpoint),
+			Port: serverport,
+		},
+		ReplaceAllowedIPs: true,
+		AllowedIPs:        allowedips,
+	}
 	peers = append(peers, peer)
-        conf := wgtypes.Config{
-                PrivateKey: &key,
-                ReplacePeers: true,
-                Peers: peers,
-        }
-        _, err = wgclient.Device(ifacename)
-        if err != nil {
-                if os.IsNotExist(err) {
-                        log.Println("Device does not exist: ")
-                        log.Println(err)
-                } else {
-                        return err
-                }
-        }
+	conf := wgtypes.Config{
+		PrivateKey:   &key,
+		ReplacePeers: true,
+		Peers:        peers,
+	}
+	_, err = wgclient.Device(ifacename)
+	if err != nil {
+		if os.IsNotExist(err) {
+			log.Println("Device does not exist: ")
+			log.Println(err)
+		} else {
+			return err
+		}
+	}
 	//spew.Dump(conf)
-        err = wgclient.ConfigureDevice(ifacename, conf)
-
-        if err != nil {
-                if os.IsNotExist(err) {
-                        log.Println("Device does not exist: ")
-                        log.Println(err)
-                } else {
-                        log.Printf("This is inconvenient: %v", err)
-                }
-        }
-
-        cmdIPLinkUp := exec.Command("ip", "link", "set", "up", "dev", ifacename)
-        cmdIPLinkDown := exec.Command("ip", "link", "set", "down", "dev", ifacename)
-        err = cmdIPLinkDown.Run()
-        err = cmdIPLinkUp.Run()
-        if  err  !=  nil {
-                return err
-        }
+	err = wgclient.ConfigureDevice(ifacename, conf)
+
+	if err != nil {
+		if os.IsNotExist(err) {
+			log.Println("Device does not exist: ")
+			log.Println(err)
+		} else {
+			log.Printf("This is inconvenient: %v", err)
+		}
+	}
+
+	cmdIPLinkUp := exec.Command("ip", "link", "set", "up", "dev", ifacename)
+	cmdIPLinkDown := exec.Command("ip", "link", "set", "down", "dev", ifacename)
+	err = cmdIPLinkDown.Run()
+	err = cmdIPLinkUp.Run()
+	if err != nil {
+		return err
+	}
 
 	return err
 }
 
-func InitWireguard(node *nodepb.Node, privkey string, peers []wgtypes.PeerConfig, hasGateway bool, gateways []string) error  {
+func InitWireguard(node *nodepb.Node, privkey string, peers []wgtypes.PeerConfig, hasGateway bool, gateways []string) error {
 
-        //spew.Dump(node)
-        //spew.Dump(peers)
 	ipExec, err := exec.LookPath("ip")
-	if err !=  nil {
+	if err != nil {
 		return err
 	}
 	key, err := wgtypes.ParseKey(privkey)
-        if err !=  nil {
-                return err
-        }
+	if err != nil {
+		return err
+	}
 
-        wgclient, err := wgctrl.New()
-	//modcfg := config.Config
-	//modcfg.ReadConfig()
+	wgclient, err := wgctrl.New()
+	if err != nil {
+		return err
+	}
 	modcfg, err := config.ReadConfig(node.Nodenetwork)
 	if err != nil {
-                return err
-        }
-
-
+		return err
+	}
 	nodecfg := modcfg.Node
 	servercfg := modcfg.Server
 
-
-        if err != nil {
-                log.Fatalf("failed to open client: %v", err)
-        }
-        defer wgclient.Close()
+	if err != nil {
+		log.Fatalf("failed to open client: %v", err)
+	}
+	defer wgclient.Close()
 
 	ifacename := node.Interface
 	if nodecfg.Interface != "" {
 		ifacename = nodecfg.Interface
 	} else if node.Interface != "" {
 		ifacename = node.Interface
-	} else  {
+	} else {
 		log.Fatal("no interface to configure")
 	}
 	if node.Address == "" {
@@ -188,68 +186,75 @@ func InitWireguard(node *nodepb.Node, privkey string, peers []wgtypes.PeerConfig
 	}
 	nameserver := servercfg.CoreDNSAddr
 	network := node.Nodenetwork
-        if nodecfg.Network != "" {
-                network = nodecfg.Network
-        } else if node.Nodenetwork != "" {
-                network = node.Nodenetwork
-        }
-        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,
-        }
-
-         currentiface, err := net.InterfaceByName(ifacename)
-
-
-        if err != nil {
-		err = cmdIPDevLinkAdd.Run()
-	if  err  !=  nil && !strings.Contains(err.Error(), "exists") {
-		fmt.Println("Error creating interface")
-		//fmt.Println(err.Error())
-		//return err
+	if nodecfg.Network != "" {
+		network = nodecfg.Network
+	} else if node.Nodenetwork != "" {
+		network = node.Nodenetwork
+	}
+	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,
+	}
+
+	currentiface, err := net.InterfaceByName(ifacename)
+
+	if err != nil {
+		err = cmdIPDevLinkAdd.Run()
+		if err != nil && !strings.Contains(err.Error(), "exists") {
+			fmt.Println("Error creating interface")
+			//fmt.Println(err.Error())
+			//return err
+		}
 	}
 	match := false
 	addrs, _ := currentiface.Addrs()
 	for _, a := range addrs {
-		if strings.Contains(a.String(), node.Address){
+		if strings.Contains(a.String(), node.Address) {
 			match = true
 		}
 	}
 	if !match {
-        err = cmdIPAddrAdd.Run()
-        if  err  !=  nil {
-		fmt.Println("Error adding address")
-                //return err
-        }
+		err = cmdIPAddrAdd.Run()
+		if err != nil {
+			fmt.Println("Error adding address")
+			//return err
+		}
 	}
 	var nodeport int
 	nodeport = int(node.Listenport)
 
-	//pubkey := privkey.PublicKey()
-	conf := wgtypes.Config{
-		PrivateKey: &key,
-		ListenPort: &nodeport,
-		ReplacePeers: true,
-		Peers: peers,
+	conf := wgtypes.Config{}
+	if nodecfg.UDPHolePunch == "yes" {
+		conf = wgtypes.Config{
+			PrivateKey:   &key,
+			ReplacePeers: true,
+			Peers:        peers,
+		}
+	} else {
+		conf = wgtypes.Config{
+			PrivateKey:   &key,
+			ListenPort:   &nodeport,
+			ReplacePeers: true,
+			Peers:        peers,
+		}
 	}
 	_, err = wgclient.Device(ifacename)
-        if err != nil {
-                if os.IsNotExist(err) {
-                        fmt.Println("Device does not exist: ")
-                        fmt.Println(err)
-                } else {
-                        log.Fatalf("Unknown config error: %v", err)
-                }
-        }
+	if err != nil {
+		if os.IsNotExist(err) {
+			fmt.Println("Device does not exist: ")
+			fmt.Println(err)
+		} else {
+			log.Fatalf("Unknown config error: %v", err)
+		}
+	}
 
 	err = wgclient.ConfigureDevice(ifacename, conf)
 
@@ -265,24 +270,23 @@ func InitWireguard(node *nodepb.Node, privkey string, peers []wgtypes.PeerConfig
 	if nodecfg.DNS == "on" {
 		_ = local.UpdateDNS(ifacename, network, nameserver)
 	}
-        //=========End DNS Setup=======\\
-
+	//=========End DNS Setup=======\\
 
-        cmdIPLinkUp := &exec.Cmd {
-                Path: ipExec,
-                Args: []string{ ipExec, "link", "set", "up", "dev", ifacename},
-                Stdout: os.Stdout,
-                Stderr: os.Stdout,
-        }
+	cmdIPLinkUp := &exec.Cmd{
+		Path:   ipExec,
+		Args:   []string{ipExec, "link", "set", "up", "dev", ifacename},
+		Stdout: os.Stdout,
+		Stderr: os.Stdout,
+	}
 
-	cmdIPLinkDown := &exec.Cmd {
-                Path: ipExec,
-                Args: []string{ ipExec, "link", "set", "down", "dev", ifacename},
-                Stdout: os.Stdout,
-                Stderr: os.Stdout,
-        }
-        err = cmdIPLinkDown.Run()
-        if nodecfg.PostDown != "" {
+	cmdIPLinkDown := &exec.Cmd{
+		Path:   ipExec,
+		Args:   []string{ipExec, "link", "set", "down", "dev", ifacename},
+		Stdout: os.Stdout,
+		Stderr: os.Stdout,
+	}
+	err = cmdIPLinkDown.Run()
+	if nodecfg.PostDown != "" {
 		runcmds := strings.Split(nodecfg.PostDown, "; ")
 		err = local.RunCmds(runcmds)
 		if err != nil {
@@ -291,69 +295,68 @@ func InitWireguard(node *nodepb.Node, privkey string, peers []wgtypes.PeerConfig
 	}
 
 	err = cmdIPLinkUp.Run()
-        if  err  !=  nil {
-                return err
-        }
+	if err != nil {
+		return err
+	}
 
 	if nodecfg.PostUp != "" {
-                runcmds := strings.Split(nodecfg.PostUp, "; ")
-                err = local.RunCmds(runcmds)
-                if err != nil {
-                        fmt.Println("Error encountered running PostUp: " + err.Error())
-                }
-        }
-	if (hasGateway) {
-		for _, gateway := range gateways {
-			out, err := exec.Command(ipExec,"-4","route","add",gateway,"dev",ifacename).Output()
-                fmt.Println(string(out))
+		runcmds := strings.Split(nodecfg.PostUp, "; ")
+		err = local.RunCmds(runcmds)
 		if err != nil {
-                        fmt.Println("Error encountered adding gateway: " + err.Error())
-                }
+			fmt.Println("Error encountered running PostUp: " + err.Error())
+		}
+	}
+	if hasGateway {
+		for _, gateway := range gateways {
+			out, err := exec.Command(ipExec, "-4", "route", "add", gateway, "dev", ifacename).Output()
+			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 {
 		fmt.Println("Adding address: " + node.Address6)
-                out, err := exec.Command(ipExec, "address", "add", "dev", ifacename, node.Address6+"/64").Output()
-                if err != nil {
-                        fmt.Println(out)
-                        fmt.Println("Error encountered adding ipv6: " + err.Error())
-                }
+		out, err := exec.Command(ipExec, "address", "add", "dev", ifacename, node.Address6+"/64").Output()
+		if err != nil {
+			fmt.Println(out)
+			fmt.Println("Error encountered adding ipv6: " + err.Error())
+		}
 	}
 
 	return err
 }
 
-
 func SetWGKeyConfig(network string, serveraddr string) error {
 
-        ctx := context.Background()
-        var header metadata.MD
+	ctx := context.Background()
+	var header metadata.MD
 
-        cfg, err := config.ReadConfig(network)
-        if err != nil {
-                return err
-        }
+	cfg, err := config.ReadConfig(network)
+	if err != nil {
+		return err
+	}
 
-        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)
-        }
+	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(serveraddr, requestOpts)
-        if err != nil {
-                fmt.Printf("Cant dial GRPC server: %v", err)
-                return err
-        }
-        wcclient = nodepb.NewNodeServiceClient(conn)
-
-        ctx, err = auth.SetJWT(wcclient, network)
-        if err != nil {
-                fmt.Printf("Failed to authenticate: %v", err)
-                return err
-        }
+	if err != nil {
+		fmt.Printf("Cant dial GRPC server: %v", err)
+		return err
+	}
+	wcclient = nodepb.NewNodeServiceClient(conn)
+
+	ctx, err = auth.SetJWT(wcclient, network)
+	if err != nil {
+		fmt.Printf("Failed to authenticate: %v", err)
+		return err
+	}
 
 	node := server.GetNode(network)
 
@@ -367,65 +370,63 @@ func SetWGKeyConfig(network string, serveraddr string) error {
 	node.Publickey = publickey.String()
 
 	err = StorePrivKey(privkeystring, network)
-        if err != nil {
-                return err
-        }
-        err = config.ModConfig(&node)
-        if err != nil {
-                return err
-        }
-
+	if err != nil {
+		return err
+	}
+	err = config.ModConfig(&node)
+	if err != nil {
+		return err
+	}
 
 	postnode := server.GetNode(network)
 
-        req := &nodepb.UpdateNodeReq{
-               Node: &postnode,
-        }
-
-        _, err = wcclient.UpdateNode(ctx, req, grpc.Header(&header))
-        if err != nil {
-                return err
-        }
-        err = SetWGConfig(network)
-        if err != nil {
-                return err
-                log.Fatalf("Error: %v", err)
-        }
-
-        return err
-}
+	req := &nodepb.UpdateNodeReq{
+		Node: &postnode,
+	}
+
+	_, err = wcclient.UpdateNode(ctx, req, grpc.Header(&header))
+	if err != nil {
+		return err
+	}
+	err = SetWGConfig(network)
+	if err != nil {
+		return err
+		log.Fatalf("Error: %v", err)
+	}
 
+	return err
+}
 
 func SetWGConfig(network string) error {
 
-        cfg, err := config.ReadConfig(network)
-        if err != nil {
-                return err
-        }
+	cfg, err := config.ReadConfig(network)
+	if err != nil {
+		return err
+	}
 	servercfg := cfg.Server
-        nodecfg := cfg.Node
-        node := server.GetNode(network)
+	nodecfg := cfg.Node
+	node := server.GetNode(network)
 
 	peers, hasGateway, gateways, err := server.GetPeers(node.Macaddress, nodecfg.Network, servercfg.GRPCAddress, node.Isdualstack, node.Isingressgateway)
-        if err != nil {
-                return err
-        }
+	if err != nil {
+		return err
+	}
 	privkey, err := RetrievePrivKey(network)
-        if err != nil {
-                return err
-        }
+	if err != nil {
+		return err
+	}
 
-        err = InitWireguard(&node, privkey, peers, hasGateway, gateways)
-        if err != nil {
-                return err
-        }
+	err = InitWireguard(&node, privkey, peers, hasGateway, gateways)
+	if err != nil {
+		return err
+	}
 
 	return err
 }
 
-func StorePrivKey(key string, network string) error{
+func StorePrivKey(key string, network string) error {
 	d1 := []byte(key)
-	err := ioutil.WriteFile("/etc/netclient/wgkey-" + network, d1, 0644)
+	err := ioutil.WriteFile("/etc/netclient/wgkey-"+network, d1, 0644)
 	return err
 }
 

+ 23 - 0
serverctl/wireguard.go

@@ -183,3 +183,26 @@ func ReconfigureServerWireGuard() error {
 	}
 	return nil
 }
+
+func GetPeers(networkName string) (map[string]string, error) {
+	peers := make(map[string]string)
+	network, err := functions.GetParentNetwork(networkName)
+	if err != nil {
+		return peers, err
+	}
+	iface := network.DefaultInterface
+
+	client, err := wgctrl.New()
+	if err != nil {
+		return peers, err
+	}
+	device, err := client.Device(iface)
+	if err != nil {
+		return nil, err
+	}
+	for _, peer := range device.Peers {
+		peers[peer.PublicKey.String()] = peer.Endpoint.String()
+	}
+
+	return peers, nil
+}