helpers.go 24 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067
  1. //TODO: Consider restructuring this file/folder "github.com/gorilla/handlers"
  2. //It may make more sense to split into different files and not call it "helpers"
  3. package functions
  4. import (
  5. "context"
  6. "encoding/base64"
  7. "encoding/json"
  8. "errors"
  9. "fmt"
  10. "log"
  11. "math/rand"
  12. "net"
  13. "strings"
  14. "time"
  15. "github.com/gravitl/netmaker/models"
  16. "github.com/gravitl/netmaker/mongoconn"
  17. "github.com/gravitl/netmaker/servercfg"
  18. "go.mongodb.org/mongo-driver/bson"
  19. "go.mongodb.org/mongo-driver/bson/primitive"
  20. "go.mongodb.org/mongo-driver/mongo"
  21. "go.mongodb.org/mongo-driver/mongo/options"
  22. )
  23. func PrintUserLog(username string, message string, loglevel int) {
  24. log.SetFlags(log.Flags() &^ (log.Llongfile | log.Lshortfile))
  25. if int32(loglevel) <= servercfg.GetVerbose() && servercfg.GetVerbose() != 0 {
  26. log.Println(username, message)
  27. }
  28. }
  29. //Takes in an arbitrary field and value for field and checks to see if any other
  30. //node has that value for the same field within the network
  31. func SliceContains(slice []string, item string) bool {
  32. set := make(map[string]struct{}, len(slice))
  33. for _, s := range slice {
  34. set[s] = struct{}{}
  35. }
  36. _, ok := set[item]
  37. return ok
  38. }
  39. func CreateServerToken(netID string) (string, error) {
  40. var network models.Network
  41. var accesskey models.AccessKey
  42. network, err := GetParentNetwork(netID)
  43. if err != nil {
  44. return "", err
  45. }
  46. var accessToken models.AccessToken
  47. servervals := models.ServerConfig{
  48. APIConnString: "127.0.0.1" + servercfg.GetAPIPort(),
  49. GRPCConnString: "127.0.0.1" + servercfg.GetGRPCPort(),
  50. GRPCSSL: "off",
  51. }
  52. accessToken.ServerConfig = servervals
  53. accessToken.ClientConfig.Network = netID
  54. accessToken.ClientConfig.Key = GenKey()
  55. accesskey.Name = GenKeyName()
  56. accesskey.Value = GenKey()
  57. accesskey.Uses = 1
  58. <<<<<<< HEAD
  59. privAddr := ""
  60. if *network.IsLocal {
  61. privAddr = network.LocalRange
  62. }
  63. accessstringdec := address + "|" + address + "|" + address + "|" + netID + "|" + accesskey.Value + "|" + privAddr
  64. =======
  65. tokenjson, err := json.Marshal(accessToken)
  66. if err != nil {
  67. return accesskey.AccessString, err
  68. }
  69. >>>>>>> 35826caa6fb2dfe3dbe65d25799d243f5a444999
  70. accesskey.AccessString = base64.StdEncoding.EncodeToString([]byte(tokenjson))
  71. network.AccessKeys = append(network.AccessKeys, accesskey)
  72. collection := mongoconn.Client.Database("netmaker").Collection("networks")
  73. ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
  74. // Create filter
  75. filter := bson.M{"netid": netID}
  76. // prepare update model.
  77. update := bson.D{
  78. {"$set", bson.D{
  79. {"accesskeys", network.AccessKeys},
  80. }},
  81. }
  82. errN := collection.FindOneAndUpdate(ctx, filter, update).Decode(&network)
  83. defer cancel()
  84. if errN != nil {
  85. return "", errN
  86. }
  87. return accesskey.AccessString, nil
  88. }
  89. func GetPeersList(networkName string) ([]models.PeersResponse, error) {
  90. var peers []models.PeersResponse
  91. //Connection mongoDB with mongoconn class
  92. collection := mongoconn.Client.Database("netmaker").Collection("nodes")
  93. ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
  94. //Get all nodes in the relevant network which are NOT in pending state
  95. filter := bson.M{"network": networkName, "ispending": false}
  96. cur, err := collection.Find(ctx, filter)
  97. if err != nil {
  98. return peers, err
  99. }
  100. // Close the cursor once finished and cancel if it takes too long
  101. defer cancel()
  102. for cur.Next(context.TODO()) {
  103. var peer models.PeersResponse
  104. err := cur.Decode(&peer)
  105. if err != nil {
  106. log.Fatal(err)
  107. }
  108. // add the node to our node array
  109. //maybe better to just return this? But then that's just GetNodes...
  110. peers = append(peers, peer)
  111. }
  112. //Uh oh, fatal error! This needs some better error handling
  113. //TODO: needs appropriate error handling so the server doesnt shut down.
  114. if err := cur.Err(); err != nil {
  115. log.Fatal(err)
  116. }
  117. return peers, err
  118. }
  119. func GetIntPeersList() ([]models.PeersResponse, error) {
  120. var peers []models.PeersResponse
  121. collection := mongoconn.Client.Database("netmaker").Collection("intclients")
  122. ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
  123. filter := bson.M{"isserver": ""}
  124. cur, err := collection.Find(ctx, filter)
  125. if err != nil {
  126. return peers, err
  127. }
  128. // Close the cursor once finished and cancel if it takes too long
  129. defer cancel()
  130. for cur.Next(context.TODO()) {
  131. var peer models.PeersResponse
  132. err := cur.Decode(&peer)
  133. if err != nil {
  134. log.Fatal(err)
  135. }
  136. // add the node to our node array
  137. //maybe better to just return this? But then that's just GetNodes...
  138. peers = append(peers, peer)
  139. }
  140. //Uh oh, fatal error! This needs some better error handling
  141. //TODO: needs appropriate error handling so the server doesnt shut down.
  142. if err := cur.Err(); err != nil {
  143. log.Fatal(err)
  144. }
  145. return peers, err
  146. }
  147. func IsFieldUnique(network string, field string, value string) bool {
  148. var node models.Node
  149. isunique := true
  150. collection := mongoconn.Client.Database("netmaker").Collection("nodes")
  151. ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
  152. filter := bson.M{field: value, "network": network}
  153. err := collection.FindOne(ctx, filter).Decode(&node)
  154. defer cancel()
  155. if err != nil {
  156. return isunique
  157. }
  158. if node.Name != "" {
  159. isunique = false
  160. }
  161. return isunique
  162. }
  163. func ServerIntClientExists() (bool, error) {
  164. collection := mongoconn.Client.Database("netmaker").Collection("intclients")
  165. ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
  166. filter := bson.M{"isserver": "yes"}
  167. var result bson.M
  168. err := collection.FindOne(ctx, filter).Decode(&result)
  169. defer cancel()
  170. if err != nil {
  171. if err == mongo.ErrNoDocuments {
  172. return false, nil
  173. }
  174. }
  175. return true, err
  176. }
  177. func NetworkExists(name string) (bool, error) {
  178. collection := mongoconn.Client.Database("netmaker").Collection("networks")
  179. ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
  180. filter := bson.M{"netid": name}
  181. var result bson.M
  182. err := collection.FindOne(ctx, filter).Decode(&result)
  183. defer cancel()
  184. if err != nil {
  185. if err == mongo.ErrNoDocuments {
  186. return false, nil
  187. }
  188. }
  189. return true, err
  190. }
  191. //TODO: This is very inefficient (N-squared). Need to find a better way.
  192. //Takes a list of nodes in a network and iterates through
  193. //for each node, it gets a unique address. That requires checking against all other nodes once more
  194. func UpdateNetworkNodeAddresses(networkName string) error {
  195. //Connection mongoDB with mongoconn class
  196. collection := mongoconn.Client.Database("netmaker").Collection("nodes")
  197. ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
  198. filter := bson.M{"network": networkName}
  199. cur, err := collection.Find(ctx, filter)
  200. if err != nil {
  201. return err
  202. }
  203. defer cancel()
  204. for cur.Next(context.TODO()) {
  205. var node models.Node
  206. err := cur.Decode(&node)
  207. if err != nil {
  208. fmt.Println("error in node address assignment!")
  209. return err
  210. }
  211. ipaddr, iperr := UniqueAddress(networkName)
  212. if iperr != nil {
  213. fmt.Println("error in node address assignment!")
  214. return iperr
  215. }
  216. filter := bson.M{"macaddress": node.MacAddress}
  217. update := bson.D{{"$set", bson.D{{"address", ipaddr}}}}
  218. errN := collection.FindOneAndUpdate(ctx, filter, update).Decode(&node)
  219. defer cancel()
  220. if errN != nil {
  221. return errN
  222. }
  223. }
  224. return err
  225. }
  226. //TODO TODO TODO!!!!!
  227. func UpdateNetworkPrivateAddresses(networkName string) error {
  228. //Connection mongoDB with mongoconn class
  229. collection := mongoconn.Client.Database("netmaker").Collection("nodes")
  230. ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
  231. filter := bson.M{"network": networkName}
  232. cur, err := collection.Find(ctx, filter)
  233. if err != nil {
  234. return err
  235. }
  236. defer cancel()
  237. for cur.Next(context.TODO()) {
  238. var node models.Node
  239. err := cur.Decode(&node)
  240. if err != nil {
  241. fmt.Println("error in node address assignment!")
  242. return err
  243. }
  244. ipaddr, iperr := UniqueAddress(networkName)
  245. if iperr != nil {
  246. fmt.Println("error in node address assignment!")
  247. return iperr
  248. }
  249. filter := bson.M{"macaddress": node.MacAddress}
  250. update := bson.D{{"$set", bson.D{{"address", ipaddr}}}}
  251. errN := collection.FindOneAndUpdate(ctx, filter, update).Decode(&node)
  252. defer cancel()
  253. if errN != nil {
  254. return errN
  255. }
  256. }
  257. return err
  258. }
  259. //Checks to see if any other networks have the same name (id)
  260. func IsNetworkNameUnique(name string) (bool, error) {
  261. isunique := true
  262. dbs, err := ListNetworks()
  263. if err != nil {
  264. return false, err
  265. }
  266. for i := 0; i < len(dbs); i++ {
  267. if name == dbs[i].NetID {
  268. isunique = false
  269. }
  270. }
  271. return isunique, nil
  272. }
  273. func IsNetworkDisplayNameUnique(name string) (bool, error) {
  274. isunique := true
  275. dbs, err := ListNetworks()
  276. if err != nil {
  277. return false, err
  278. }
  279. for i := 0; i < len(dbs); i++ {
  280. if name == dbs[i].DisplayName {
  281. isunique = false
  282. }
  283. }
  284. return isunique, nil
  285. }
  286. func GetNetworkNodeNumber(networkName string) (int, error) {
  287. collection := mongoconn.Client.Database("netmaker").Collection("nodes")
  288. ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
  289. filter := bson.M{"network": networkName}
  290. count, err := collection.CountDocuments(ctx, filter)
  291. returncount := int(count)
  292. //not sure if this is the right way of handling this error...
  293. if err != nil {
  294. return 9999, err
  295. }
  296. defer cancel()
  297. return returncount, err
  298. }
  299. //Kind of a weird name. Should just be GetNetworks I think. Consider changing.
  300. //Anyway, returns all the networks
  301. func ListNetworks() ([]models.Network, error) {
  302. var networks []models.Network
  303. collection := mongoconn.Client.Database("netmaker").Collection("networks")
  304. ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
  305. cur, err := collection.Find(ctx, bson.M{}, options.Find().SetProjection(bson.M{"_id": 0}))
  306. if err != nil {
  307. return networks, err
  308. }
  309. defer cancel()
  310. for cur.Next(context.TODO()) {
  311. var network models.Network
  312. err := cur.Decode(&network)
  313. if err != nil {
  314. return networks, err
  315. }
  316. // add network our array
  317. networks = append(networks, network)
  318. }
  319. if err := cur.Err(); err != nil {
  320. return networks, err
  321. }
  322. return networks, err
  323. }
  324. //Checks to see if access key is valid
  325. //Does so by checking against all keys and seeing if any have the same value
  326. //may want to hash values before comparing...consider this
  327. //TODO: No error handling!!!!
  328. func IsKeyValid(networkname string, keyvalue string) bool {
  329. network, _ := GetParentNetwork(networkname)
  330. var key models.AccessKey
  331. foundkey := false
  332. isvalid := false
  333. for i := len(network.AccessKeys) - 1; i >= 0; i-- {
  334. currentkey := network.AccessKeys[i]
  335. if currentkey.Value == keyvalue {
  336. key = currentkey
  337. foundkey = true
  338. }
  339. }
  340. if foundkey {
  341. if key.Uses > 0 {
  342. isvalid = true
  343. }
  344. }
  345. return isvalid
  346. }
  347. func IsKeyValidGlobal(keyvalue string) bool {
  348. networks, _ := ListNetworks()
  349. var key models.AccessKey
  350. foundkey := false
  351. isvalid := false
  352. for _, network := range networks {
  353. for i := len(network.AccessKeys) - 1; i >= 0; i-- {
  354. currentkey := network.AccessKeys[i]
  355. if currentkey.Value == keyvalue {
  356. key = currentkey
  357. foundkey = true
  358. break
  359. }
  360. }
  361. if foundkey {
  362. break
  363. }
  364. }
  365. if foundkey {
  366. if key.Uses > 0 {
  367. isvalid = true
  368. }
  369. }
  370. return isvalid
  371. }
  372. //TODO: Contains a fatal error return. Need to change
  373. //This just gets a network object from a network name
  374. //Should probably just be GetNetwork. kind of a dumb name.
  375. //Used in contexts where it's not the Parent network.
  376. func GetParentNetwork(networkname string) (models.Network, error) {
  377. var network models.Network
  378. collection := mongoconn.Client.Database("netmaker").Collection("networks")
  379. ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
  380. filter := bson.M{"netid": networkname}
  381. err := collection.FindOne(ctx, filter).Decode(&network)
  382. defer cancel()
  383. if err != nil {
  384. return network, err
  385. }
  386. return network, nil
  387. }
  388. func IsIpNet(host string) bool {
  389. return net.ParseIP(host) != nil
  390. }
  391. //Similar to above but checks if Cidr range is valid
  392. //At least this guy's got some print statements
  393. //still not good error handling
  394. func IsIpCIDR(host string) bool {
  395. ip, ipnet, err := net.ParseCIDR(host)
  396. if err != nil {
  397. fmt.Println(err)
  398. fmt.Println("Address Range is not valid!")
  399. return false
  400. }
  401. return ip != nil && ipnet != nil
  402. }
  403. //This is used to validate public keys (make sure they're base64 encoded like all public keys should be).
  404. func IsBase64(s string) bool {
  405. _, err := base64.StdEncoding.DecodeString(s)
  406. return err == nil
  407. }
  408. //This should probably just be called GetNode
  409. //It returns a node based on the ID of the node.
  410. //Why do we need this?
  411. //TODO: Check references. This seems unnecessary.
  412. func GetNodeObj(id primitive.ObjectID) models.Node {
  413. var node models.Node
  414. collection := mongoconn.Client.Database("netmaker").Collection("nodes")
  415. ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
  416. filter := bson.M{"_id": id}
  417. err := collection.FindOne(ctx, filter).Decode(&node)
  418. defer cancel()
  419. if err != nil {
  420. fmt.Println(err)
  421. fmt.Println("Did not get the node...")
  422. return node
  423. }
  424. fmt.Println("Got node " + node.Name)
  425. return node
  426. }
  427. //This checks to make sure a network name is valid.
  428. //Switch to REGEX?
  429. func NameInNetworkCharSet(name string) bool {
  430. charset := "abcdefghijklmnopqrstuvwxyz1234567890-_."
  431. for _, char := range name {
  432. if !strings.Contains(charset, strings.ToLower(string(char))) {
  433. return false
  434. }
  435. }
  436. return true
  437. }
  438. func NameInDNSCharSet(name string) bool {
  439. charset := "abcdefghijklmnopqrstuvwxyz1234567890-."
  440. for _, char := range name {
  441. if !strings.Contains(charset, strings.ToLower(string(char))) {
  442. return false
  443. }
  444. }
  445. return true
  446. }
  447. func NameInNodeCharSet(name string) bool {
  448. charset := "abcdefghijklmnopqrstuvwxyz1234567890-"
  449. for _, char := range name {
  450. if !strings.Contains(charset, strings.ToLower(string(char))) {
  451. return false
  452. }
  453. }
  454. return true
  455. }
  456. //This returns a node based on its mac address.
  457. //The mac address acts as the Unique ID for nodes.
  458. //Is this a dumb thing to do? I thought it was cool but maybe it's dumb.
  459. //It doesn't really provide a tangible benefit over a random ID
  460. func GetNodeByMacAddress(network string, macaddress string) (models.Node, error) {
  461. var node models.Node
  462. filter := bson.M{"macaddress": macaddress, "network": network}
  463. collection := mongoconn.Client.Database("netmaker").Collection("nodes")
  464. ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
  465. err := collection.FindOne(ctx, filter).Decode(&node)
  466. defer cancel()
  467. if err != nil {
  468. return node, err
  469. }
  470. return node, nil
  471. }
  472. func DeleteAllIntClients() error {
  473. collection := mongoconn.Client.Database("netmaker").Collection("intclients")
  474. ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
  475. // Filter out them ID's again
  476. err := collection.Drop(ctx)
  477. if err != nil {
  478. return err
  479. }
  480. defer cancel()
  481. return nil
  482. }
  483. func GetAllIntClients() ([]models.IntClient, error) {
  484. var client models.IntClient
  485. var clients []models.IntClient
  486. collection := mongoconn.Client.Database("netmaker").Collection("intclients")
  487. ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
  488. // Filter out them ID's again
  489. cur, err := collection.Find(ctx, bson.M{}, options.Find().SetProjection(bson.M{"_id": 0}))
  490. if err != nil {
  491. return []models.IntClient{}, err
  492. }
  493. defer cancel()
  494. for cur.Next(context.TODO()) {
  495. err := cur.Decode(&client)
  496. if err != nil {
  497. return []models.IntClient{}, err
  498. }
  499. // add node to our array
  500. clients = append(clients, client)
  501. }
  502. //TODO: Fatal error
  503. if err := cur.Err(); err != nil {
  504. return []models.IntClient{}, err
  505. }
  506. return clients, nil
  507. }
  508. func GetAllExtClients() ([]models.ExtClient, error) {
  509. var extclient models.ExtClient
  510. var extclients []models.ExtClient
  511. collection := mongoconn.Client.Database("netmaker").Collection("extclients")
  512. ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
  513. // Filter out them ID's again
  514. cur, err := collection.Find(ctx, bson.M{}, options.Find().SetProjection(bson.M{"_id": 0}))
  515. if err != nil {
  516. return []models.ExtClient{}, err
  517. }
  518. defer cancel()
  519. for cur.Next(context.TODO()) {
  520. err := cur.Decode(&extclient)
  521. if err != nil {
  522. return []models.ExtClient{}, err
  523. }
  524. // add node to our array
  525. extclients = append(extclients, extclient)
  526. }
  527. //TODO: Fatal error
  528. if err := cur.Err(); err != nil {
  529. return []models.ExtClient{}, err
  530. }
  531. return extclients, nil
  532. }
  533. //This returns a unique address for a node to use
  534. //it iterates through the list of IP's in the subnet
  535. //and checks against all nodes to see if it's taken, until it finds one.
  536. //TODO: We do not handle a case where we run out of addresses.
  537. //We will need to handle that eventually
  538. func UniqueAddress(networkName string) (string, error) {
  539. var network models.Network
  540. network, err := GetParentNetwork(networkName)
  541. if err != nil {
  542. fmt.Println("UniqueAddress encountered an error")
  543. return "666", err
  544. }
  545. offset := true
  546. ip, ipnet, err := net.ParseCIDR(network.AddressRange)
  547. if err != nil {
  548. fmt.Println("UniqueAddress encountered an error")
  549. return "666", err
  550. }
  551. for ip := ip.Mask(ipnet.Mask); ipnet.Contains(ip); Inc(ip) {
  552. if offset {
  553. offset = false
  554. continue
  555. }
  556. if networkName == "comms" {
  557. if IsIPUniqueClients(networkName, ip.String()) {
  558. return ip.String(), err
  559. }
  560. } else {
  561. if IsIPUnique(networkName, ip.String()) && IsIPUniqueExtClients(networkName, ip.String()) {
  562. return ip.String(), err
  563. }
  564. }
  565. }
  566. //TODO
  567. err1 := errors.New("ERROR: No unique addresses available. Check network subnet.")
  568. return "W1R3: NO UNIQUE ADDRESSES AVAILABLE", err1
  569. }
  570. func UniqueAddress6(networkName string) (string, error) {
  571. var network models.Network
  572. network, err := GetParentNetwork(networkName)
  573. if err != nil {
  574. fmt.Println("Network Not Found")
  575. return "", err
  576. }
  577. if network.IsDualStack == nil || *network.IsDualStack == false {
  578. if networkName != "comms" {
  579. return "", nil
  580. }
  581. }
  582. offset := true
  583. ip, ipnet, err := net.ParseCIDR(network.AddressRange6)
  584. if err != nil {
  585. fmt.Println("UniqueAddress6 encountered an error")
  586. return "666", err
  587. }
  588. for ip := ip.Mask(ipnet.Mask); ipnet.Contains(ip); Inc(ip) {
  589. if offset {
  590. offset = false
  591. continue
  592. }
  593. if networkName == "comms" {
  594. if IsIP6UniqueClients(networkName, ip.String()) {
  595. return ip.String(), err
  596. }
  597. } else {
  598. if IsIP6Unique(networkName, ip.String()) {
  599. return ip.String(), err
  600. }
  601. }
  602. }
  603. //TODO
  604. err1 := errors.New("ERROR: No unique addresses available. Check network subnet.")
  605. return "W1R3: NO UNIQUE ADDRESSES AVAILABLE", err1
  606. }
  607. //generate an access key value
  608. func GenKey() string {
  609. var seededRand *rand.Rand = rand.New(
  610. rand.NewSource(time.Now().UnixNano()))
  611. length := 16
  612. charset := "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
  613. b := make([]byte, length)
  614. for i := range b {
  615. b[i] = charset[seededRand.Intn(len(charset))]
  616. }
  617. return string(b)
  618. }
  619. //generate a key value
  620. //we should probably just have 1 random string generator
  621. //that can be used across all functions
  622. //have a "base string" a "length" and a "charset"
  623. func GenKeyName() string {
  624. var seededRand *rand.Rand = rand.New(
  625. rand.NewSource(time.Now().UnixNano()))
  626. length := 5
  627. charset := "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
  628. b := make([]byte, length)
  629. for i := range b {
  630. b[i] = charset[seededRand.Intn(len(charset))]
  631. }
  632. return "key" + string(b)
  633. }
  634. func IsIPUniqueExtClients(network string, ip string) bool {
  635. var extclient models.ExtClient
  636. isunique := true
  637. collection := mongoconn.Client.Database("netmaker").Collection("extclients")
  638. ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
  639. filter := bson.M{"address": ip, "network": network}
  640. err := collection.FindOne(ctx, filter).Decode(&extclient)
  641. defer cancel()
  642. if err != nil {
  643. return isunique
  644. }
  645. if extclient.Address == ip {
  646. isunique = false
  647. }
  648. return isunique
  649. }
  650. //checks if IP is unique in the address range
  651. //used by UniqueAddress
  652. func IsIPUnique(network string, ip string) bool {
  653. var node models.Node
  654. isunique := true
  655. collection := mongoconn.Client.Database("netmaker").Collection("nodes")
  656. ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
  657. filter := bson.M{"address": ip, "network": network}
  658. err := collection.FindOne(ctx, filter).Decode(&node)
  659. defer cancel()
  660. if err != nil {
  661. return isunique
  662. }
  663. if node.Address == ip {
  664. isunique = false
  665. }
  666. return isunique
  667. }
  668. //checks if IP is unique in the address range
  669. //used by UniqueAddress
  670. func IsIP6Unique(network string, ip string) bool {
  671. var node models.Node
  672. isunique := true
  673. collection := mongoconn.Client.Database("netmaker").Collection("nodes")
  674. ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
  675. filter := bson.M{"address6": ip, "network": network}
  676. err := collection.FindOne(ctx, filter).Decode(&node)
  677. defer cancel()
  678. if err != nil {
  679. return isunique
  680. }
  681. if node.Address6 == ip {
  682. isunique = false
  683. }
  684. return isunique
  685. }
  686. //checks if IP is unique in the address range
  687. //used by UniqueAddress
  688. func IsIP6UniqueClients(network string, ip string) bool {
  689. var client models.IntClient
  690. isunique := true
  691. collection := mongoconn.Client.Database("netmaker").Collection("intclients")
  692. ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
  693. filter := bson.M{"address6": ip, "network": network}
  694. err := collection.FindOne(ctx, filter).Decode(&client)
  695. defer cancel()
  696. if err != nil {
  697. return isunique
  698. }
  699. if client.Address6 == ip {
  700. isunique = false
  701. }
  702. return isunique
  703. }
  704. //checks if IP is unique in the address range
  705. //used by UniqueAddress
  706. func IsIPUniqueClients(network string, ip string) bool {
  707. var client models.IntClient
  708. isunique := true
  709. collection := mongoconn.Client.Database("netmaker").Collection("intclients")
  710. ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
  711. filter := bson.M{"address": ip, "network": network}
  712. err := collection.FindOne(ctx, filter).Decode(&client)
  713. defer cancel()
  714. if err != nil {
  715. return isunique
  716. }
  717. if client.Address == ip {
  718. isunique = false
  719. }
  720. return isunique
  721. }
  722. //called once key has been used by createNode
  723. //reduces value by one and deletes if necessary
  724. func DecrimentKey(networkName string, keyvalue string) {
  725. var network models.Network
  726. network, err := GetParentNetwork(networkName)
  727. if err != nil {
  728. return
  729. }
  730. for i := len(network.AccessKeys) - 1; i >= 0; i-- {
  731. currentkey := network.AccessKeys[i]
  732. if currentkey.Value == keyvalue {
  733. network.AccessKeys[i].Uses--
  734. if network.AccessKeys[i].Uses < 1 {
  735. //this is the part where it will call the delete
  736. //not sure if there's edge cases I'm missing
  737. DeleteKey(network, i)
  738. return
  739. }
  740. }
  741. }
  742. collection := mongoconn.Client.Database("netmaker").Collection("networks")
  743. ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
  744. filter := bson.M{"netid": network.NetID}
  745. update := bson.D{
  746. {"$set", bson.D{
  747. {"accesskeys", network.AccessKeys},
  748. }},
  749. }
  750. errN := collection.FindOneAndUpdate(ctx, filter, update).Decode(&network)
  751. defer cancel()
  752. if errN != nil {
  753. return
  754. }
  755. }
  756. //takes the logic from controllers.deleteKey
  757. func DeleteKey(network models.Network, i int) {
  758. network.AccessKeys = append(network.AccessKeys[:i],
  759. network.AccessKeys[i+1:]...)
  760. collection := mongoconn.Client.Database("netmaker").Collection("networks")
  761. ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
  762. // Create filter
  763. filter := bson.M{"netid": network.NetID}
  764. // prepare update model.
  765. update := bson.D{
  766. {"$set", bson.D{
  767. {"accesskeys", network.AccessKeys},
  768. }},
  769. }
  770. errN := collection.FindOneAndUpdate(ctx, filter, update).Decode(&network)
  771. defer cancel()
  772. if errN != nil {
  773. return
  774. }
  775. }
  776. //increments an IP over the previous
  777. func Inc(ip net.IP) {
  778. for j := len(ip) - 1; j >= 0; j-- {
  779. ip[j]++
  780. if ip[j] > 0 {
  781. break
  782. }
  783. }
  784. }
  785. func GetAllNodes() ([]models.Node, error) {
  786. var node models.Node
  787. var nodes []models.Node
  788. collection := mongoconn.Client.Database("netmaker").Collection("nodes")
  789. ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
  790. // Filter out them ID's again
  791. cur, err := collection.Find(ctx, bson.M{}, options.Find().SetProjection(bson.M{"_id": 0}))
  792. if err != nil {
  793. return []models.Node{}, err
  794. }
  795. defer cancel()
  796. for cur.Next(context.TODO()) {
  797. err := cur.Decode(&node)
  798. if err != nil {
  799. return []models.Node{}, err
  800. }
  801. // add node to our array
  802. nodes = append(nodes, node)
  803. }
  804. //TODO: Fatal error
  805. if err := cur.Err(); err != nil {
  806. return []models.Node{}, err
  807. }
  808. return nodes, nil
  809. }