common.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407
  1. package functions
  2. import (
  3. "fmt"
  4. "encoding/json"
  5. "errors"
  6. "context"
  7. "net/http"
  8. "io/ioutil"
  9. "strings"
  10. "log"
  11. "net"
  12. "os"
  13. "os/exec"
  14. "github.com/gravitl/netmaker/netclient/config"
  15. "github.com/gravitl/netmaker/netclient/local"
  16. "github.com/gravitl/netmaker/netclient/auth"
  17. nodepb "github.com/gravitl/netmaker/grpc"
  18. "golang.zx2c4.com/wireguard/wgctrl"
  19. "google.golang.org/grpc"
  20. "google.golang.org/grpc/metadata"
  21. //homedir "github.com/mitchellh/go-homedir"
  22. )
  23. var (
  24. wcclient nodepb.NodeServiceClient
  25. )
  26. func ListPorts() error{
  27. wgclient, err := wgctrl.New()
  28. if err != nil {
  29. return err
  30. }
  31. devices, err := wgclient.Devices()
  32. if err != nil {
  33. return err
  34. }
  35. fmt.Println("Here are your ports:")
  36. for _, i := range devices {
  37. fmt.Println(i.ListenPort)
  38. }
  39. return err
  40. }
  41. func GetFreePort(rangestart int32) (int32, error){
  42. wgclient, err := wgctrl.New()
  43. if err != nil {
  44. return 0, err
  45. }
  46. devices, err := wgclient.Devices()
  47. if err != nil {
  48. return 0, err
  49. }
  50. var portno int32
  51. portno = 0
  52. for x := rangestart; x <= 60000; x++ {
  53. conflict := false
  54. for _, i := range devices {
  55. if int32(i.ListenPort) == x {
  56. conflict = true
  57. break;
  58. }
  59. }
  60. if conflict {
  61. continue
  62. }
  63. portno = x
  64. break
  65. }
  66. return portno, err
  67. }
  68. func getLocalIP(localrange string) (string, error) {
  69. _, localRange, err := net.ParseCIDR(localrange)
  70. if err != nil {
  71. return "", err
  72. }
  73. ifaces, err := net.Interfaces()
  74. if err != nil {
  75. return "", err
  76. }
  77. var local string
  78. found := false
  79. for _, i := range ifaces {
  80. if i.Flags&net.FlagUp == 0 {
  81. continue // interface down
  82. }
  83. if i.Flags&net.FlagLoopback != 0 {
  84. continue // loopback interface
  85. }
  86. addrs, err := i.Addrs()
  87. if err != nil {
  88. return "", err
  89. }
  90. for _, addr := range addrs {
  91. var ip net.IP
  92. switch v := addr.(type) {
  93. case *net.IPNet:
  94. if !found {
  95. ip = v.IP
  96. local = ip.String()
  97. found = localRange.Contains(ip)
  98. }
  99. case *net.IPAddr:
  100. if !found {
  101. ip = v.IP
  102. local = ip.String()
  103. found = localRange.Contains(ip)
  104. }
  105. }
  106. }
  107. }
  108. if !found || local == "" {
  109. return "", errors.New("Failed to find local IP in range " + localrange)
  110. }
  111. return local, nil
  112. }
  113. func getPublicIP() (string, error) {
  114. iplist := []string{"http://ip.client.gravitl.com","https://ifconfig.me", "http://api.ipify.org", "http://ipinfo.io/ip"}
  115. endpoint := ""
  116. var err error
  117. for _, ipserver := range iplist {
  118. resp, err := http.Get(ipserver)
  119. if err != nil {
  120. continue
  121. }
  122. defer resp.Body.Close()
  123. if resp.StatusCode == http.StatusOK {
  124. bodyBytes, err := ioutil.ReadAll(resp.Body)
  125. if err != nil {
  126. continue
  127. }
  128. endpoint = string(bodyBytes)
  129. break
  130. }
  131. }
  132. if err == nil && endpoint == "" {
  133. err = errors.New("Public Address Not Found.")
  134. }
  135. return endpoint, err
  136. }
  137. func getMacAddr() ([]string, error) {
  138. ifas, err := net.Interfaces()
  139. if err != nil {
  140. return nil, err
  141. }
  142. var as []string
  143. for _, ifa := range ifas {
  144. a := ifa.HardwareAddr.String()
  145. if a != "" {
  146. as = append(as, a)
  147. }
  148. }
  149. return as, nil
  150. }
  151. func getPrivateAddr() (string, error) {
  152. ifaces, err := net.Interfaces()
  153. if err != nil {
  154. return "", err
  155. }
  156. var local string
  157. found := false
  158. for _, i := range ifaces {
  159. if i.Flags&net.FlagUp == 0 {
  160. continue // interface down
  161. }
  162. if i.Flags&net.FlagLoopback != 0 {
  163. continue // loopback interface
  164. }
  165. addrs, err := i.Addrs()
  166. if err != nil {
  167. return "", err
  168. }
  169. for _, addr := range addrs {
  170. var ip net.IP
  171. switch v := addr.(type) {
  172. case *net.IPNet:
  173. if !found {
  174. ip = v.IP
  175. local = ip.String()
  176. found = true
  177. }
  178. case *net.IPAddr:
  179. if !found {
  180. ip = v.IP
  181. local = ip.String()
  182. found = true
  183. }
  184. }
  185. }
  186. }
  187. if !found {
  188. err := errors.New("Local Address Not Found.")
  189. return "", err
  190. }
  191. return local, err
  192. }
  193. func needInterfaceUpdate(ctx context.Context, mac string, network string, iface string) (bool, string, error) {
  194. var header metadata.MD
  195. req := &nodepb.ReadNodeReq{
  196. Macaddress: mac,
  197. Network: network,
  198. }
  199. readres, err := wcclient.ReadNode(ctx, req, grpc.Header(&header))
  200. if err != nil {
  201. return false, "", err
  202. log.Fatalf("Error: %v", err)
  203. }
  204. oldiface := readres.Node.Interface
  205. return iface != oldiface, oldiface, err
  206. }
  207. func GetNode(network string) nodepb.Node {
  208. modcfg, err := config.ReadConfig(network)
  209. if err != nil {
  210. log.Fatalf("Error: %v", err)
  211. }
  212. nodecfg := modcfg.Node
  213. var node nodepb.Node
  214. node.Name = nodecfg.Name
  215. node.Interface = nodecfg.Interface
  216. node.Nodenetwork = nodecfg.Network
  217. node.Localaddress = nodecfg.LocalAddress
  218. node.Address = nodecfg.WGAddress
  219. node.Address6 = nodecfg.WGAddress6
  220. node.Listenport = nodecfg.Port
  221. node.Keepalive = nodecfg.KeepAlive
  222. node.Postup = nodecfg.PostUp
  223. node.Postdown = nodecfg.PostDown
  224. node.Publickey = nodecfg.PublicKey
  225. node.Macaddress = nodecfg.MacAddress
  226. node.Endpoint = nodecfg.Endpoint
  227. node.Password = nodecfg.Password
  228. if nodecfg.DNS == "on" {
  229. node.Dnsoff = true
  230. } else {
  231. node.Dnsoff = false
  232. }
  233. if nodecfg.IsDualStack == "yes" {
  234. node.Isdualstack = true
  235. } else {
  236. node.Isdualstack = false
  237. }
  238. if nodecfg.IsIngressGateway == "yes" {
  239. node.Isingressgateway = true
  240. } else {
  241. node.Isingressgateway = false
  242. }
  243. return node
  244. }
  245. func Uninstall() error {
  246. networks, err := GetNetworks()
  247. if err != nil {
  248. log.Println("unable to retrieve networks: ", err)
  249. log.Println("continuing uninstall without leaving networks")
  250. } else {
  251. for _, network := range networks {
  252. err = LeaveNetwork(network)
  253. if err != nil {
  254. log.Println("Encounter issue leaving network " + network + ": ", err)
  255. }
  256. }
  257. }
  258. return err
  259. }
  260. func LeaveNetwork(network string) error {
  261. //need to implement checkin on server side
  262. cfg, err := config.ReadConfig(network)
  263. if err != nil {
  264. return err
  265. }
  266. servercfg := cfg.Server
  267. node := cfg.Node
  268. var wcclient nodepb.NodeServiceClient
  269. var requestOpts grpc.DialOption
  270. requestOpts = grpc.WithInsecure()
  271. conn, err := grpc.Dial(servercfg.GRPCAddress, requestOpts)
  272. if err != nil {
  273. log.Printf("Unable to establish client connection to " + servercfg.GRPCAddress + ": %v", err)
  274. }else {
  275. wcclient = nodepb.NewNodeServiceClient(conn)
  276. ctx := context.Background()
  277. ctx, err = auth.SetJWT(wcclient, network)
  278. if err != nil {
  279. log.Printf("Failed to authenticate: %v", err)
  280. } else {
  281. var header metadata.MD
  282. _, err = wcclient.DeleteNode(
  283. ctx,
  284. &nodepb.DeleteNodeReq{
  285. Macaddress: node.MacAddress,
  286. NetworkName: node.Network,
  287. },
  288. grpc.Header(&header),
  289. )
  290. if err != nil {
  291. log.Printf("Encountered error deleting node: %v", err)
  292. log.Println(err)
  293. } else {
  294. log.Println("Removed machine from " + node.Network + " network on remote server")
  295. }
  296. }
  297. }
  298. err = local.WipeLocal(network)
  299. if err != nil {
  300. log.Printf("Unable to wipe local config: %v", err)
  301. } else {
  302. log.Println("Removed " + node.Network + " network locally")
  303. }
  304. if cfg.Daemon != "off" {
  305. err = local.RemoveSystemDServices(network)
  306. }
  307. return err
  308. }
  309. func DeleteInterface(ifacename string, postdown string) error{
  310. ipExec, err := exec.LookPath("ip")
  311. cmdIPLinkDel := &exec.Cmd {
  312. Path: ipExec,
  313. Args: []string{ ipExec, "link", "del", ifacename },
  314. Stdout: os.Stdout,
  315. Stderr: os.Stdout,
  316. }
  317. err = cmdIPLinkDel.Run()
  318. if err != nil {
  319. log.Println(err)
  320. }
  321. if postdown != "" {
  322. runcmds := strings.Split(postdown, "; ")
  323. err = local.RunCmds(runcmds)
  324. if err != nil {
  325. log.Println("Error encountered running PostDown: " + err.Error())
  326. }
  327. }
  328. return err
  329. }
  330. func List() error{
  331. networks, err := GetNetworks()
  332. if err != nil {
  333. return err
  334. }
  335. for _, network := range networks {
  336. cfg, err := config.ReadConfig(network)
  337. if err == nil {
  338. //cfg2 := *cfg
  339. listconfig := &config.ListConfig{
  340. Name: cfg.Node.Name,
  341. Interface: cfg.Node.Interface,
  342. PrivateIPv4: cfg.Node.WGAddress,
  343. PrivateIPv6: cfg.Node.WGAddress6,
  344. PublicEndpoint: cfg.Node.Endpoint,
  345. }
  346. jsoncfg, _ := json.Marshal(listconfig)
  347. log.Println(network + ": " + string(jsoncfg))
  348. } else {
  349. log.Println(network + ": Could not retrieve network configuration.")
  350. }
  351. }
  352. return nil
  353. }
  354. func GetNetworks() ([]string, error) {
  355. var networks []string
  356. files, err := ioutil.ReadDir("/etc/netclient")
  357. if err != nil {
  358. return networks, err
  359. }
  360. for _, f := range files {
  361. if strings.Contains(f.Name(), "netconfig-") && !strings.Contains(f.Name(), "global-001"){
  362. networkname := stringAfter(f.Name(), "netconfig-")
  363. networks = append(networks, networkname)
  364. }
  365. }
  366. return networks, err
  367. }
  368. func stringAfter(original string, substring string) string {
  369. position := strings.LastIndex(original, substring)
  370. if position == -1 {
  371. return ""
  372. }
  373. adjustedPosition := position + len(substring)
  374. if adjustedPosition >= len(original) {
  375. return ""
  376. }
  377. return original[adjustedPosition:len(original)]
  378. }