targeting.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. package targeting
  2. import (
  3. "fmt"
  4. "net"
  5. "strings"
  6. )
  7. type TargetOptions int
  8. const (
  9. TargetGlobal = 1 << iota
  10. TargetContinent
  11. TargetCountry
  12. TargetRegionGroup
  13. TargetRegion
  14. TargetASN
  15. TargetIP
  16. )
  17. var cidr48Mask net.IPMask
  18. func init() {
  19. cidr48Mask = net.CIDRMask(48, 128)
  20. }
  21. func (t TargetOptions) GetTargets(ip net.IP, hasClosest bool) ([]string, int, *Location) {
  22. targets := make([]string, 0)
  23. var country, continent, region, regionGroup, asn string
  24. var netmask int
  25. var location *Location
  26. g := GeoIP()
  27. if t&TargetASN > 0 {
  28. asn, netmask = g.GetASN(ip)
  29. }
  30. if t&TargetRegion > 0 || t&TargetRegionGroup > 0 || hasClosest {
  31. country, continent, regionGroup, region, netmask, location = geoIP.GetCountryRegion(ip)
  32. } else if t&TargetCountry > 0 || t&TargetContinent > 0 {
  33. country, continent, netmask = g.GetCountry(ip)
  34. }
  35. if t&TargetIP > 0 {
  36. ipStr := ip.String()
  37. targets = append(targets, "["+ipStr+"]")
  38. ip4 := ip.To4()
  39. if ip4 != nil {
  40. if ip4[3] != 0 {
  41. ip4[3] = 0
  42. targets = append(targets, "["+ip4.String()+"]")
  43. }
  44. } else {
  45. // v6 address, also target the /48 address
  46. ip48 := ip.Mask(cidr48Mask)
  47. targets = append(targets, "["+ip48.String()+"]")
  48. }
  49. }
  50. if t&TargetASN > 0 && len(asn) > 0 {
  51. targets = append(targets, asn)
  52. }
  53. if t&TargetRegion > 0 && len(region) > 0 {
  54. targets = append(targets, region)
  55. }
  56. if t&TargetRegionGroup > 0 && len(regionGroup) > 0 {
  57. targets = append(targets, regionGroup)
  58. }
  59. if t&TargetCountry > 0 && len(country) > 0 {
  60. targets = append(targets, country)
  61. }
  62. if t&TargetContinent > 0 && len(continent) > 0 {
  63. targets = append(targets, continent)
  64. }
  65. if t&TargetGlobal > 0 {
  66. targets = append(targets, "@")
  67. }
  68. return targets, netmask, location
  69. }
  70. func (t TargetOptions) String() string {
  71. targets := make([]string, 0)
  72. if t&TargetGlobal > 0 {
  73. targets = append(targets, "@")
  74. }
  75. if t&TargetContinent > 0 {
  76. targets = append(targets, "continent")
  77. }
  78. if t&TargetCountry > 0 {
  79. targets = append(targets, "country")
  80. }
  81. if t&TargetRegionGroup > 0 {
  82. targets = append(targets, "regiongroup")
  83. }
  84. if t&TargetRegion > 0 {
  85. targets = append(targets, "region")
  86. }
  87. if t&TargetASN > 0 {
  88. targets = append(targets, "asn")
  89. }
  90. if t&TargetIP > 0 {
  91. targets = append(targets, "ip")
  92. }
  93. return strings.Join(targets, " ")
  94. }
  95. func ParseTargets(v string) (tgt TargetOptions, err error) {
  96. targets := strings.Split(v, " ")
  97. for _, t := range targets {
  98. var x TargetOptions
  99. switch t {
  100. case "@":
  101. x = TargetGlobal
  102. case "country":
  103. x = TargetCountry
  104. case "continent":
  105. x = TargetContinent
  106. case "regiongroup":
  107. x = TargetRegionGroup
  108. case "region":
  109. x = TargetRegion
  110. case "asn":
  111. x = TargetASN
  112. case "ip":
  113. x = TargetIP
  114. default:
  115. err = fmt.Errorf("Unknown targeting option '%s'", t)
  116. }
  117. tgt = tgt | x
  118. }
  119. return
  120. }