123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181 |
- package targeting
- import (
- "fmt"
- "log"
- "net"
- "strings"
- "github.com/abh/geodns/targeting/geo"
- )
- type TargetOptions int
- const (
- TargetGlobal = 1 << iota
- TargetContinent
- TargetCountry
- TargetRegionGroup
- TargetRegion
- TargetASN
- TargetIP
- )
- var cidr48Mask net.IPMask
- func init() {
- cidr48Mask = net.CIDRMask(48, 128)
- }
- var g geo.Provider
- // Setup sets the global geo provider
- func Setup(gn geo.Provider) error {
- g = gn
- return nil
- }
- // Geo returns the global geo provider
- func Geo() geo.Provider {
- return g
- }
- func (t TargetOptions) getGeoTargets(ip net.IP, hasClosest bool) ([]string, int, *geo.Location) {
- targets := make([]string, 0)
- if t&TargetASN > 0 {
- asn, _, err := g.GetASN(ip)
- if err != nil {
- log.Printf("GetASN error: %s", err)
- }
- if len(asn) > 0 {
- targets = append(targets, asn)
- }
- }
- var country, continent, region, regionGroup string
- var netmask int
- var location *geo.Location
- if t&TargetRegion > 0 || t&TargetRegionGroup > 0 || hasClosest {
- var err error
- location, err = g.GetLocation(ip)
- if location == nil || err != nil {
- return targets, 0, nil
- }
- // log.Printf("Location for '%s' (err: %s): %+v", ip, err, location)
- country = location.Country
- continent = location.Continent
- region = location.Region
- regionGroup = location.RegionGroup
- // continent, regionGroup, region, netmask,
- } else if t&TargetCountry > 0 || t&TargetContinent > 0 {
- country, continent, netmask = g.GetCountry(ip)
- }
- if t&TargetRegion > 0 && len(region) > 0 {
- targets = append(targets, region)
- }
- if t&TargetRegionGroup > 0 && len(regionGroup) > 0 {
- targets = append(targets, regionGroup)
- }
- if t&TargetCountry > 0 && len(country) > 0 {
- targets = append(targets, country)
- }
- if t&TargetContinent > 0 && len(continent) > 0 {
- targets = append(targets, continent)
- }
- return targets, netmask, location
- }
- func (t TargetOptions) GetTargets(ip net.IP, hasClosest bool) ([]string, int, *geo.Location) {
- targets := make([]string, 0)
- var location *geo.Location
- var netmask int
- if t&TargetIP > 0 {
- ipStr := ip.String()
- targets = append(targets, "["+ipStr+"]")
- ip4 := ip.To4()
- if ip4 != nil {
- if ip4[3] != 0 {
- ip4[3] = 0
- targets = append(targets, "["+ip4.String()+"]")
- }
- } else {
- // v6 address, also target the /48 address
- ip48 := ip.Mask(cidr48Mask)
- targets = append(targets, "["+ip48.String()+"]")
- }
- }
- if g != nil {
- var geotargets []string
- geotargets, netmask, location = t.getGeoTargets(ip, hasClosest)
- targets = append(targets, geotargets...)
- }
- if t&TargetGlobal > 0 {
- targets = append(targets, "@")
- }
- return targets, netmask, location
- }
- func (t TargetOptions) String() string {
- targets := make([]string, 0)
- if t&TargetGlobal > 0 {
- targets = append(targets, "@")
- }
- if t&TargetContinent > 0 {
- targets = append(targets, "continent")
- }
- if t&TargetCountry > 0 {
- targets = append(targets, "country")
- }
- if t&TargetRegionGroup > 0 {
- targets = append(targets, "regiongroup")
- }
- if t&TargetRegion > 0 {
- targets = append(targets, "region")
- }
- if t&TargetASN > 0 {
- targets = append(targets, "asn")
- }
- if t&TargetIP > 0 {
- targets = append(targets, "ip")
- }
- return strings.Join(targets, " ")
- }
- func ParseTargets(v string) (tgt TargetOptions, err error) {
- targets := strings.Split(v, " ")
- for _, t := range targets {
- var x TargetOptions
- switch t {
- case "@":
- x = TargetGlobal
- case "country":
- x = TargetCountry
- case "continent":
- x = TargetContinent
- case "regiongroup":
- x = TargetRegionGroup
- case "region":
- x = TargetRegion
- case "asn":
- x = TargetASN
- case "ip":
- x = TargetIP
- default:
- err = fmt.Errorf("Unknown targeting option '%s'", t)
- }
- tgt = tgt | x
- }
- return
- }
|