networks.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. package logic
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "net"
  7. "os/exec"
  8. "strings"
  9. "github.com/go-playground/validator/v10"
  10. "github.com/gravitl/netmaker/database"
  11. "github.com/gravitl/netmaker/models"
  12. "github.com/gravitl/netmaker/netclient/ncutils"
  13. "github.com/gravitl/netmaker/validation"
  14. )
  15. // GetNetworks - returns all networks from database
  16. func GetNetworks() ([]models.Network, error) {
  17. var networks []models.Network
  18. collection, err := database.FetchRecords(database.NETWORKS_TABLE_NAME)
  19. if err != nil {
  20. return networks, err
  21. }
  22. for _, value := range collection {
  23. var network models.Network
  24. if err := json.Unmarshal([]byte(value), &network); err != nil {
  25. return networks, err
  26. }
  27. // add network our array
  28. networks = append(networks, network)
  29. }
  30. return networks, err
  31. }
  32. // GetParentNetwork - get parent network
  33. func GetParentNetwork(networkname string) (models.Network, error) {
  34. var network models.Network
  35. networkData, err := database.FetchRecord(database.NETWORKS_TABLE_NAME, networkname)
  36. if err != nil {
  37. return network, err
  38. }
  39. if err = json.Unmarshal([]byte(networkData), &network); err != nil {
  40. return models.Network{}, err
  41. }
  42. return network, nil
  43. }
  44. // GetParentNetwork - get parent network
  45. func GetNetworkSettings(networkname string) (models.Network, error) {
  46. var network models.Network
  47. networkData, err := database.FetchRecord(database.NETWORKS_TABLE_NAME, networkname)
  48. if err != nil {
  49. return network, err
  50. }
  51. if err = json.Unmarshal([]byte(networkData), &network); err != nil {
  52. return models.Network{}, err
  53. }
  54. network.AccessKeys = []models.AccessKey{}
  55. return network, nil
  56. }
  57. // UniqueAddress - see if address is unique
  58. func UniqueAddress(networkName string) (string, error) {
  59. var network models.Network
  60. network, err := GetParentNetwork(networkName)
  61. if err != nil {
  62. fmt.Println("UniqueAddress encountered an error")
  63. return "666", err
  64. }
  65. offset := true
  66. ip, ipnet, err := net.ParseCIDR(network.AddressRange)
  67. if err != nil {
  68. fmt.Println("UniqueAddress encountered an error")
  69. return "666", err
  70. }
  71. for ip := ip.Mask(ipnet.Mask); ipnet.Contains(ip); Inc(ip) {
  72. if offset {
  73. offset = false
  74. continue
  75. }
  76. if networkName == "comms" {
  77. if IsIPUnique(networkName, ip.String(), database.INT_CLIENTS_TABLE_NAME, false) {
  78. return ip.String(), err
  79. }
  80. } else {
  81. if IsIPUnique(networkName, ip.String(), database.NODES_TABLE_NAME, false) && IsIPUnique(networkName, ip.String(), database.EXT_CLIENT_TABLE_NAME, false) {
  82. return ip.String(), err
  83. }
  84. }
  85. }
  86. //TODO
  87. err1 := errors.New("ERROR: No unique addresses available. Check network subnet.")
  88. return "W1R3: NO UNIQUE ADDRESSES AVAILABLE", err1
  89. }
  90. // IsIPUnique - checks if an IP is unique
  91. func IsIPUnique(network string, ip string, tableName string, isIpv6 bool) bool {
  92. isunique := true
  93. collection, err := database.FetchRecords(tableName)
  94. if err != nil {
  95. return isunique
  96. }
  97. for _, value := range collection { // filter
  98. var node models.Node
  99. if err = json.Unmarshal([]byte(value), &node); err != nil {
  100. continue
  101. }
  102. if isIpv6 {
  103. if node.Address6 == ip && node.Network == network {
  104. return false
  105. }
  106. } else {
  107. if node.Address == ip && node.Network == network {
  108. return false
  109. }
  110. }
  111. }
  112. return isunique
  113. }
  114. // UniqueAddress6 - see if ipv6 address is unique
  115. func UniqueAddress6(networkName string) (string, error) {
  116. var network models.Network
  117. network, err := GetParentNetwork(networkName)
  118. if err != nil {
  119. fmt.Println("Network Not Found")
  120. return "", err
  121. }
  122. if network.IsDualStack == "no" {
  123. return "", nil
  124. }
  125. offset := true
  126. ip, ipnet, err := net.ParseCIDR(network.AddressRange6)
  127. if err != nil {
  128. fmt.Println("UniqueAddress6 encountered an error")
  129. return "666", err
  130. }
  131. for ip := ip.Mask(ipnet.Mask); ipnet.Contains(ip); Inc(ip) {
  132. if offset {
  133. offset = false
  134. continue
  135. }
  136. if IsIPUnique(networkName, ip.String(), database.NODES_TABLE_NAME, true) {
  137. return ip.String(), err
  138. }
  139. }
  140. //TODO
  141. err1 := errors.New("ERROR: No unique addresses available. Check network subnet.")
  142. return "W1R3: NO UNIQUE ADDRESSES AVAILABLE", err1
  143. }
  144. // GetLocalIP - gets the local ip
  145. func GetLocalIP(node models.Node) string {
  146. var local string
  147. ifaces, err := net.Interfaces()
  148. if err != nil {
  149. return local
  150. }
  151. _, localrange, err := net.ParseCIDR(node.LocalRange)
  152. if err != nil {
  153. return local
  154. }
  155. found := false
  156. for _, i := range ifaces {
  157. if i.Flags&net.FlagUp == 0 {
  158. continue // interface down
  159. }
  160. if i.Flags&net.FlagLoopback != 0 {
  161. continue // loopback interface
  162. }
  163. addrs, err := i.Addrs()
  164. if err != nil {
  165. return local
  166. }
  167. for _, addr := range addrs {
  168. var ip net.IP
  169. switch v := addr.(type) {
  170. case *net.IPNet:
  171. if !found {
  172. ip = v.IP
  173. local = ip.String()
  174. if node.IsLocal == "yes" {
  175. found = localrange.Contains(ip)
  176. } else {
  177. found = true
  178. }
  179. }
  180. case *net.IPAddr:
  181. if !found {
  182. ip = v.IP
  183. local = ip.String()
  184. if node.IsLocal == "yes" {
  185. found = localrange.Contains(ip)
  186. } else {
  187. found = true
  188. }
  189. }
  190. }
  191. }
  192. }
  193. return local
  194. }
  195. // UpdateNetworkLocalAddresses - updates network localaddresses
  196. func UpdateNetworkLocalAddresses(networkName string) error {
  197. collection, err := database.FetchRecords(database.NODES_TABLE_NAME)
  198. if err != nil {
  199. return err
  200. }
  201. for _, value := range collection {
  202. var node models.Node
  203. err := json.Unmarshal([]byte(value), &node)
  204. if err != nil {
  205. fmt.Println("error in node address assignment!")
  206. return err
  207. }
  208. if node.Network == networkName {
  209. ipaddr, iperr := UniqueAddress(networkName)
  210. if iperr != nil {
  211. fmt.Println("error in node address assignment!")
  212. return iperr
  213. }
  214. node.Address = ipaddr
  215. newNodeData, err := json.Marshal(&node)
  216. if err != nil {
  217. fmt.Println("error in node address assignment!")
  218. return err
  219. }
  220. node.SetID()
  221. database.Insert(node.ID, string(newNodeData), database.NODES_TABLE_NAME)
  222. }
  223. }
  224. return nil
  225. }
  226. // UpdateNetworkNodeAddresses - updates network node addresses
  227. func UpdateNetworkNodeAddresses(networkName string) error {
  228. collections, err := database.FetchRecords(database.NODES_TABLE_NAME)
  229. if err != nil {
  230. return err
  231. }
  232. for _, value := range collections {
  233. var node models.Node
  234. err := json.Unmarshal([]byte(value), &node)
  235. if err != nil {
  236. fmt.Println("error in node address assignment!")
  237. return err
  238. }
  239. if node.Network == networkName {
  240. ipaddr, iperr := UniqueAddress(networkName)
  241. if iperr != nil {
  242. fmt.Println("error in node address assignment!")
  243. return iperr
  244. }
  245. node.Address = ipaddr
  246. node.PullChanges = "yes"
  247. data, err := json.Marshal(&node)
  248. if err != nil {
  249. return err
  250. }
  251. node.SetID()
  252. database.Insert(node.ID, string(data), database.NODES_TABLE_NAME)
  253. }
  254. }
  255. return nil
  256. }
  257. // IsNetworkDisplayNameUnique - checks if displayname is unique from other networks
  258. func IsNetworkDisplayNameUnique(network *models.Network) (bool, error) {
  259. isunique := true
  260. records, err := GetNetworks()
  261. if err != nil && !database.IsEmptyRecord(err) {
  262. return false, err
  263. }
  264. for i := 0; i < len(records); i++ {
  265. if network.NetID == records[i].DisplayName {
  266. isunique = false
  267. }
  268. }
  269. return isunique, nil
  270. }
  271. // IsNetworkNameUnique - checks to see if any other networks have the same name (id)
  272. func IsNetworkNameUnique(network *models.Network) (bool, error) {
  273. isunique := true
  274. dbs, err := GetNetworks()
  275. if err != nil && !database.IsEmptyRecord(err) {
  276. return false, err
  277. }
  278. for i := 0; i < len(dbs); i++ {
  279. if network.NetID == dbs[i].NetID {
  280. isunique = false
  281. }
  282. }
  283. return isunique, nil
  284. }
  285. // UpdateNetwork - updates a network with another network's fields
  286. func UpdateNetwork(currentNetwork *models.Network, newNetwork *models.Network) (bool, bool, error) {
  287. if err := ValidateNetwork(newNetwork, true); err != nil {
  288. return false, false, err
  289. }
  290. if newNetwork.NetID == currentNetwork.NetID {
  291. hasrangeupdate := newNetwork.AddressRange != currentNetwork.AddressRange
  292. localrangeupdate := newNetwork.LocalRange != currentNetwork.LocalRange
  293. data, err := json.Marshal(newNetwork)
  294. if err != nil {
  295. return false, false, err
  296. }
  297. newNetwork.SetNetworkLastModified()
  298. err = database.Insert(newNetwork.NetID, string(data), database.NETWORKS_TABLE_NAME)
  299. return hasrangeupdate, localrangeupdate, err
  300. }
  301. // copy values
  302. return false, false, errors.New("failed to update network " + newNetwork.NetID + ", cannot change netid.")
  303. }
  304. // Inc - increments an IP
  305. func Inc(ip net.IP) {
  306. for j := len(ip) - 1; j >= 0; j-- {
  307. ip[j]++
  308. if ip[j] > 0 {
  309. break
  310. }
  311. }
  312. }
  313. // GetNetwork - gets a network from database
  314. func GetNetwork(networkname string) (models.Network, error) {
  315. var network models.Network
  316. networkData, err := database.FetchRecord(database.NETWORKS_TABLE_NAME, networkname)
  317. if err != nil {
  318. return network, err
  319. }
  320. if err = json.Unmarshal([]byte(networkData), &network); err != nil {
  321. return models.Network{}, err
  322. }
  323. return network, nil
  324. }
  325. // Network.NetIDInNetworkCharSet - checks if a netid of a network uses valid characters
  326. func NetIDInNetworkCharSet(network *models.Network) bool {
  327. charset := "abcdefghijklmnopqrstuvwxyz1234567890-_."
  328. for _, char := range network.NetID {
  329. if !strings.Contains(charset, strings.ToLower(string(char))) {
  330. return false
  331. }
  332. }
  333. return true
  334. }
  335. // Network.Validate - validates fields of an network struct
  336. func ValidateNetwork(network *models.Network, isUpdate bool) error {
  337. v := validator.New()
  338. _ = v.RegisterValidation("netid_valid", func(fl validator.FieldLevel) bool {
  339. inCharSet := NetIDInNetworkCharSet(network)
  340. if isUpdate {
  341. return inCharSet
  342. }
  343. isFieldUnique, _ := IsNetworkNameUnique(network)
  344. return isFieldUnique && inCharSet
  345. })
  346. //
  347. _ = v.RegisterValidation("displayname_valid", func(fl validator.FieldLevel) bool {
  348. isFieldUnique, _ := IsNetworkDisplayNameUnique(network)
  349. inCharSet := network.DisplayNameInNetworkCharSet()
  350. if isUpdate {
  351. return inCharSet
  352. }
  353. return isFieldUnique && inCharSet
  354. })
  355. _ = v.RegisterValidation("checkyesorno", func(fl validator.FieldLevel) bool {
  356. return validation.CheckYesOrNo(fl)
  357. })
  358. err := v.Struct(network)
  359. if err != nil {
  360. for _, e := range err.(validator.ValidationErrors) {
  361. fmt.Println(e)
  362. }
  363. }
  364. return err
  365. }
  366. // == Private ==
  367. func deleteInterface(ifacename string, postdown string) error {
  368. var err error
  369. if !ncutils.IsKernel() {
  370. err = RemoveConf(ifacename, true)
  371. } else {
  372. ipExec, errN := exec.LookPath("ip")
  373. err = errN
  374. if err != nil {
  375. Log(err.Error(), 1)
  376. }
  377. _, err = ncutils.RunCmd(ipExec+" link del "+ifacename, false)
  378. if postdown != "" {
  379. runcmds := strings.Split(postdown, "; ")
  380. err = ncutils.RunCmds(runcmds, false)
  381. }
  382. }
  383. return err
  384. }
  385. func isInterfacePresent(iface string, address string) (string, bool) {
  386. var interfaces []net.Interface
  387. var err error
  388. interfaces, err = net.Interfaces()
  389. if err != nil {
  390. Log("ERROR: could not read interfaces", 0)
  391. return "", true
  392. }
  393. for _, currIface := range interfaces {
  394. var currAddrs []net.Addr
  395. currAddrs, err = currIface.Addrs()
  396. if err != nil || len(currAddrs) == 0 {
  397. continue
  398. }
  399. for _, addr := range currAddrs {
  400. if strings.Contains(addr.String(), address) && currIface.Name != iface {
  401. Log("found iface "+addr.String()+" "+currIface.Name, 2)
  402. return currIface.Name, false
  403. }
  404. }
  405. }
  406. Log("failed to find iface "+iface, 2)
  407. return "", true
  408. }