utils.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. package accesscontrol
  2. import (
  3. "bytes"
  4. "errors"
  5. "net"
  6. "strconv"
  7. "strings"
  8. )
  9. //Break an ip range text into independent ip strings
  10. func BreakdownIpRange(ipRange string) []string {
  11. ipRange = strings.ReplaceAll(ipRange, " ", "")
  12. err := ValidateIpRange(ipRange)
  13. if err != nil {
  14. return []string{}
  15. }
  16. if !strings.Contains(ipRange, "-") {
  17. //This is not an ip range but a single ip
  18. return []string{ipRange}
  19. }
  20. //Break down the IP range
  21. results := []string{}
  22. ips := strings.Split(ipRange, "-")
  23. subnet := ips[0][:strings.LastIndex(ips[0], ".")]
  24. startD := ips[0][strings.LastIndex(ips[0], ".")+1:]
  25. if err != nil {
  26. return []string{}
  27. }
  28. endD := ips[1][strings.LastIndex(ips[0], ".")+1:]
  29. if err != nil {
  30. return []string{}
  31. }
  32. startDInt, err := strconv.Atoi(startD)
  33. endDInt, err := strconv.Atoi(endD)
  34. currentDInt := startDInt
  35. for currentDInt < endDInt+1 {
  36. results = append(results, subnet+"."+strconv.Itoa(currentDInt))
  37. currentDInt++
  38. }
  39. return results
  40. }
  41. //Check if an given ip in the given range
  42. func IpInRange(ip string, ipRange string) bool {
  43. ip = strings.TrimSpace(ip)
  44. ipRange = strings.ReplaceAll(ipRange, " ", "")
  45. if ip == ipRange {
  46. //For fields that the ipRange is the ip itself
  47. return true
  48. }
  49. //Try matching range
  50. if strings.Contains(ipRange, "-") {
  51. //Parse the source IP
  52. trial := net.ParseIP(ip)
  53. //Parse the IP range
  54. ips := strings.Split(ipRange, "-")
  55. ip1 := net.ParseIP(ips[0])
  56. if ip1 == nil {
  57. return false
  58. }
  59. ip2 := net.ParseIP(ips[1])
  60. if ip2 == nil {
  61. return false
  62. }
  63. if trial.To4() == nil {
  64. return false
  65. }
  66. if bytes.Compare(trial, ip1) >= 0 && bytes.Compare(trial, ip2) <= 0 {
  67. return true
  68. }
  69. return false
  70. }
  71. return false
  72. }
  73. //Check if the given IP Range string is actually an IP range
  74. func ValidateIpRange(ipRange string) error {
  75. ipRange = strings.TrimSpace(ipRange)
  76. ipRange = strings.ReplaceAll(ipRange, " ", "")
  77. if strings.Contains(ipRange, "-") {
  78. //This is a range
  79. if strings.Count(ipRange, "-") != 1 {
  80. //Invalid range defination
  81. return errors.New("Invalid ip range defination")
  82. }
  83. ips := strings.Split(ipRange, "-")
  84. //Check if the starting IP and ending IP are both valid
  85. if net.ParseIP(ips[0]) == nil {
  86. return errors.New("Starting ip is invalid")
  87. }
  88. if net.ParseIP(ips[1]) == nil {
  89. return errors.New("Ending ip is invalid")
  90. }
  91. //Check if the ending IP is larger than the starting IP
  92. startingIpInt, _ := strconv.Atoi(strings.ReplaceAll(ips[0], ".", ""))
  93. endingIpInt, _ := strconv.Atoi(strings.ReplaceAll(ips[1], ".", ""))
  94. if startingIpInt >= endingIpInt {
  95. return errors.New("Invalid ip range: Starting IP is larger or equal to ending ip")
  96. }
  97. //Check if they are in the same subnet
  98. startSubnet := ips[0][:strings.LastIndex(ips[0], ".")]
  99. endSubnet := ips[1][:strings.LastIndex(ips[1], ".")]
  100. if startSubnet != endSubnet {
  101. //They are not in the same subnet
  102. return errors.New("IP range subnet mismatch")
  103. }
  104. } else {
  105. //This is a single IP instead of range. Check if it is a valid IP addr
  106. if net.ParseIP(ipRange) != nil {
  107. //Ok
  108. return nil
  109. } else {
  110. return errors.New("Invalid ip given")
  111. }
  112. }
  113. return nil
  114. }