func GetIpinfoStartEnd(i Ipinfo) (uint32, string, uint32, string) { // defer DeleteIpinfo(i) // Must delete ipinfo ! m := NewIpitem() defer DeleteIpitem(m) x := Il_bin2human(i, m, Id_code) if x != nil { x1, x2 := x.GetStart(), x.GetEnd() return utils.Ip4ToInt32(utils.StrToIP(x1)), x1, utils.Ip4ToInt32(utils.StrToIP(x2)), x2 } else { return uint32(0), "", uint32(0), "" } }
func TestIlSearch(t *testing.T) { ipinfo := NewIpinfo() defer DeleteIpinfo(ipinfo) for _, ip := range IPS { if ok := Il_open(DBPATH); ok > 0 { defer Il_close(ok) nip := NewIp(ip) defer DeleteIp(nip) t.Log(nip.GetIn()) n := Il_search(nip, ipinfo, ok) if n > 0 { t.Log(n) // t.Log(ipinfo.GetStart(), ipinfo.GetEnd()) // t.Log(ipinfo.GetStart().GetIn(), ipinfo.GetEnd().GetIn()) // t.Log(reflect.ValueOf(ipinfo.GetStart().GetIn()), reflect.ValueOf(ipinfo.GetEnd().GetIn())) // GetIpValid(ipinfo.GetStart()) n1, n2, n3, n4 := GetIpinfoStartEnd(ipinfo) t.Log(n1, n2, n3, n4) m := NewIpitem() x := Il_bin2human(ipinfo, m, Text) t.Log(m, x, x.GetStart(), x.GetEnd()) t.Log(utils.Ip4ToInt32(utils.StrToIP(x.GetStart())), utils.Ip4ToInt32(utils.StrToIP(x.GetEnd()))) } else { t.Log(n) t.Log(ipinfo.GetStart(), ipinfo.GetEnd()) if ip != "192.168.1.1" { t.Fail() } } } } }
func GetAFromCache(dst, srcIP string) (*DomainNode, []dns.RR, *MyError.MyError) { dn, e := DomainRRCache.GetDomainNodeFromCacheWithName(dst) if e == nil && dn != nil && dn.DomainRegionTree != nil { //Get DomainNode succ, r, e := dn.DomainRegionTree.GetRegionFromCacheWithAddr( utils.Ip4ToInt32(net.ParseIP(srcIP)), DefaultRadixSearchMask) if e == nil && len(r.RR) > 0 { if r.RrType == dns.TypeA { utils.ServerLogger.Debug("GetAFromCache: Goooot A ", dst, srcIP, r.RR) return dn, r.RR, nil } else if r.RrType == dns.TypeCNAME { utils.ServerLogger.Debug("GetAFromCache: Goooot CNAME ", dst, srcIP, r.RR) return dn, r.RR, MyError.NewError(MyError.ERROR_CNAME, "Get CNAME From,Requery A for "+r.RR[0].(*dns.CNAME).Target) } } return dn, nil, MyError.NewError(MyError.ERROR_NOTFOUND, "Not found R in cache, dst :"+dst+" srcIP "+srcIP) // return } else if e == nil && dn != nil && dn.DomainRegionTree == nil { // Get domainNode in cache tree,but no RR in region tree,need query with NS // if RegionTree is nil, init RegionTree First ok, e := dn.InitRegionTree() if e != nil { utils.ServerLogger.Error("InitRegionTree fail %s", e.Error()) } // //fmt.Println("RegionTree is nil ,Init it: "+reflect.ValueOf(ok).String(), e) utils.ServerLogger.Debug("RegionTree is nil ,Init it: %s ", reflect.ValueOf(ok).String()) return dn, nil, MyError.NewError(MyError.ERROR_NORESULT, "Get domainNode in cache tree,but no RR in region tree,need query with NS, dst : "+dst+" srcIP "+srcIP) } else { // e != nil // RegionTree is not nil if e != nil { if e.ErrorNo != MyError.ERROR_NOTFOUND { //fmt.Println("Found unexpected error, need return !") utils.ServerLogger.Info("Not found, need return :", "error :", e, "dn:", dn) //os.Exit(2) } else { utils.ServerLogger.Critical("Found unexpected error, need return !", "error :", e, "dn:", dn) } } return nil, nil, e } return nil, nil, MyError.NewError(MyError.ERROR_UNKNOWN, "Unknown error!") }
func GetAFromMySQLBackend(dst, srcIP string, regionTree *RegionTree) (bool, []dns.RR, uint16, *MyError.MyError) { domainId, e := RRMySQL.GetDomainIDFromMySQL(dst) if e != nil { //todo: //fmt.Println(utils.GetDebugLine(), "Error, GetDomainIDFromMySQL:", e) return false, nil, uint16(0), e } region, ee := RRMySQL.GetRegionWithIPFromMySQL(utils.Ip4ToInt32(utils.StrToIP(srcIP))) if ee != nil { //fmt.Println(utils.GetDebugLine(), "Error GetRegionWithIPFromMySQL:", ee) return false, nil, uint16(0), MyError.NewError(ee.ErrorNo, "GetRegionWithIPFromMySQL return "+ee.Error()) } RR, eee := RRMySQL.GetRRFromMySQL(uint32(domainId), region.IdRegion) if eee != nil && eee.ErrorNo == MyError.ERROR_NORESULT { //fmt.Println(utils.GetDebugLine(), "Error GetRRFromMySQL with DomainID:", domainId, // "RegionID:", region.IdRegion, eee) //fmt.Println(utils.GetDebugLine(), "Try to GetRRFromMySQL with Default Region") utils.ServerLogger.Debug("Try to GetRRFromMySQL with Default Region") RR, eee = RRMySQL.GetRRFromMySQL(uint32(domainId), uint32(0)) if eee != nil { //fmt.Println(utils.GetDebugLine(), "Error GetRRFromMySQL with DomainID:", domainId, // "RegionID:", 0, eee) return false, nil, uint16(0), MyError.NewError(eee.ErrorNo, "Error GetRRFromMySQL with DomainID:"+strconv.Itoa(domainId)+eee.Error()) } } else if eee != nil { utils.ServerLogger.Error(eee.Error()) return false, nil, uint16(0), eee } //fmt.Println(utils.GetDebugLine(), "GetRRFromMySQL Succ!:", RR) utils.ServerLogger.Debug("GetRRFromMySQL Succ!: ", RR) var R []dns.RR var rtype uint16 var reE *MyError.MyError hdr := dns.RR_Header{ Name: dst, Class: RR.RR.Class, Rrtype: RR.RR.RrType, Ttl: RR.RR.Ttl, } //fmt.Println(utils.GetDebugLine(), mr.RR) if RR.RR.RrType == dns.TypeA { for _, mr := range RR.RR.Target { rh := &dns.A{ Hdr: hdr, A: utils.StrToIP(mr), } R = append(R, dns.RR(rh)) } rtype = dns.TypeA // fmt.Println(utils.GetDebugLine(), "Get A RR from MySQL, requery dst:", dst) } else if RR.RR.RrType == dns.TypeCNAME { for _, mr := range RR.RR.Target { rh := &dns.CNAME{ Hdr: hdr, Target: mr, } R = append(R, dns.RR(rh)) } rtype = dns.TypeCNAME //fmt.Println(utils.GetDebugLine(), "Get CNAME RR from MySQL, requery dst:", dst) reE = MyError.NewError(MyError.ERROR_NOTVALID, "Got CNAME result for dst : "+dst+" with srcIP : "+srcIP) } if len(R) > 0 { //Add timer for auto refrech the RegionCache go func(dst, srcIP string, r dns.RR, regionTree *RegionTree) { //fmt.Println(utils.GetDebugLine(), " Refresh record after ", r.Header().Ttl-5, // " Second, dst: ", dst, " srcIP: ", srcIP, "add timer ") time.AfterFunc(time.Duration(r.Header().Ttl-5)*time.Second, func() { GetAFromMySQLBackend(dst, srcIP, regionTree) }) }(dst, srcIP, R[0], regionTree) go func(regionTree *RegionTree, R []dns.RR, srcIP string) { //fmt.Println(utils.GetDebugLine(), "GetAFromMySQLBackend: ", e) startIP, endIP := region.Region.StarIP, region.Region.EndIP cidrmask := utils.GetCIDRMaskWithUint32Range(startIP, endIP) //fmt.Println(utils.GetDebugLine(), " GetRegionWithIPFromMySQL with srcIP: ", // srcIP, " StartIP : ", startIP, "==", utils.Int32ToIP4(startIP).String(), // " EndIP: ", endIP, "==", utils.Int32ToIP4(endIP).String(), " cidrmask : ", cidrmask) // netaddr, mask := DefaultNetaddr, DefaultMask r, _ := NewRegion(R, startIP, cidrmask) regionTree.AddRegionToCache(r) //fmt.Println(utils.GetDebugLine(), "GetAFromMySQLBackend: ", r) // fmt.Println(regionTree.GetRegionFromCacheWithAddr(startIP, cidrmask)) }(regionTree, R, srcIP) return true, R, rtype, reE } return false, nil, uint16(0), MyError.NewError(MyError.ERROR_UNKNOWN, utils.GetDebugLine()+"Unknown Error ") }
func TestMubitRadix(t *testing.T) { cidrNet := []string{ "10.0.0.2/8", "10.20.0.0/14", "10.21.0.0/16", "192.168.0.0/16", "192.168.2.0/24", "8.0.0.0/9", "8.8.8.0/24", "0.0.0.0/0", // "128.0.0.0/1", } ip2Find := []string{ "10.20.1.2", "10.22.1.2", "10.19.0.1", "10.21.0.1", "192.168.2.3", "10.22.0.5", "202.106.0.20", "172.16.3.133", "8.8.8.8", "8.8.7.1", } RadixTree := NewDomainRegionTree() for _, x := range cidrNet { i, n, e := net.ParseCIDR(x) if e != nil { t.Log(e.Error()) t.Fail() continue } a, m := utils.IpNetToInt32(n) RadixTree.AddRegionToCache(&Region{ NetworkAddr: a, NetworkMask: m, RR: []dns.RR{ dns.RR(&dns.A{ A: i, Hdr: dns.RR_Header{ Rrtype: 1, Class: 1, Ttl: 60, }, }), }, }) } // For default route RadixTree.AddRegionToCache(&Region{ NetworkAddr: DefaultRadixNetaddr, NetworkMask: DefaultRadixNetMask, RR: []dns.RR{ dns.RR(&dns.A{ A: utils.Int32ToIP4(DefaultRadixNetaddr), Hdr: dns.RR_Header{ Rrtype: 1, Class: 1, Ttl: 60, }, }), }, }) for _, i := range ip2Find { ii := utils.Ip4ToInt32(utils.StrToIP(i)) r, e := RadixTree.GetRegionFromCacheWithAddr(ii, DefaultRadixSearchMask) if e != nil { t.Log(e) t.Log(i) t.Fail() } else { t.Log(r) } } RadixTree.Radix32.Do(func(r1 *bitradix.Radix32, i int) { t.Log(r1.Key(), r1.Value, r1.Bits()) }) }
func TestA(t *testing.T) { d := "www.a.shifen.com" drr, e := DomainRRCache.GetDomainNodeFromCacheWithName(d) if e == nil { // no error,RR is in RRDB,need check type,if CNAME,need refetch A recode for than CNAME rr if drr != nil { x := utils.Ip4ToInt32(net.ParseIP("124.207.129.171")) rr, e := drr.DomainRegionTree.GetRegionFromCacheWithAddr(x, 32) if e == nil { //got rr t.Log(rr) //need return if rr.RrType == dns.TypeA { t.Log("return rr") } else if rr.RrType == dns.TypeCNAME { t.Log("return cname ,need query A") // QueryA } } else { // err not nil // need query A / CNAME with NS that in DomainSOATree t.Log("error not nil,need query A / CNAME with NS that in DomainSOATree") } } else { t.Log("unknown error") // Unknown error } } else { //No domainNode,need requery all (SOA/NS/CNAME/A/Edns) t.Log(e) var soa *dns.SOA var ns []*dns.NS soanode, e := DomainSOACache.GetDomainSOANodeFromCacheWithDomainName(d) if e == nil { //got soa record from DB,and use ns server to query a t.Log(soanode) ns = soanode.NS } else { // QuerySOA soa, ns, e = QuerySOA(d) if e == nil { //store soa & ns into SOADB DomainSOACache.StoreDomainSOANodeToCache(&DomainSOANode{ SOAKey: d, NS: ns, SOA: soa, }) } else { //QuerySOA failed,need retry, or exit t.Fatal() } } if ns != nil { //Query A var ns_a []string for _, n := range ns { ns_a = append(ns_a, n.Ns) } rr, i, edns, e := QueryA(d, "202.106.0.20", ns_a, "53") if e != nil { t.Log(e) } else { t.Log(rr) t.Log(i) t.Log(edns) if i != nil && edns != nil { //Edns is not null t.Log("edns is not nill,need parse + " + d) t.Log(i) t.Log(edns) } if rr != nil { //RR is array for _, r := range rr { rh := r.Header().Rrtype switch rh { case dns.TypeA: //Got A record ,return t.Log(r.(*dns.A)) case dns.TypeCNAME: //Query CNAME's Target if rc, ok := r.(*dns.CNAME); ok { rc_soa, ns, e := QuerySOA(rc.Target) t.Log(rc_soa) t.Log(ns) if e == nil && ns != nil { var ns_a []string for _, n := range ns { ns_a = append(ns_a, n.Ns) } rr, i, edns, e := QueryA(rc.Target, "202.106.0.20", ns_a, "53") t.Log(rr) t.Log(i) t.Log(edns) t.Log(e) } else { // Need retry t.Log(e) } } default: t.Log(rr) } } } } } else { t.Fatal() } } }