func AddAToRegionCache(dst string, srcIP string, R []dns.RR, edns_h *dns.RR_Header, edns *dns.EDNS0_SUBNET) { var dn *DomainNode var domainNodeExist bool = false var retry = 0 var e *MyError.MyError for domainNodeExist = false; (domainNodeExist == false) && (retry < 5); { // wait for goroutine 'StoreDomainNodeToCache' in GetSOARecord to be finished dn, e = DomainRRCache.GetDomainNodeFromCacheWithName(dst) if e != nil { // here ,may be nil // error! need return //fmt.Println(utils.GetDebugLine(), // " GetARecord : have not got cache GetDomainNodeFromCacheWithName, need waite ", e) utils.ServerLogger.Error("GetARecord : have not got cache GetDomainNodeFromCacheWithName, need waite %s", e.Error()) time.Sleep(1 * time.Second) if e.ErrorNo == MyError.ERROR_NOTFOUND { retry++ } else { utils.ServerLogger.Critical("GetARecord error %s", e.Error()) //fmt.Println(utils.GetDebugLine(), e) // todo: need to log error } } else { domainNodeExist = true //fmt.Println(utils.GetDebugLine(), "GetARecord: ", dn) utils.ServerLogger.Debug("GetARecord dn: %s", dn.Domain.DomainName, dn.DomainRegionTree) } } if domainNodeExist == false && retry >= 5 { utils.ServerLogger.Warning("DomainRRCache.GetDomainNodeFromCacheWithName(dst) dst:", dst, " retry for ", retry, " times,but no result!") } else { //dn.InitRegionTree() utils.ServerLogger.Debug("Got dn :", dn) regiontree := dn.DomainRegionTree ////todo: Need to be combined with the go func within GetAFromMySQLBackend //var startIP, endIP uint32 //if config.RC.MySQLEnabled /** && config.RC.MySQLRegionEnabled **/ { // region, ee := RRMySQL.GetRegionWithIPFromMySQL(utils.Ip4ToInt32(utils.StrToIP(srcIP))) // if ee != nil { // //fmt.Println(utils.GetDebugLine(), "Error GetRegionWithIPFromMySQL:", ee) // utils.ServerLogger.Error("Error GetRegionWithIPFromMySQL: %s", ee.Error()) // } else { // startIP, endIP = region.Region.StarIP, region.Region.EndIP // //fmt.Println(utils.GetDebugLine(), region.Region, startIP, endIP) // } // //} else { // // startIP, endIP = iplookup.GetIpinfoStartEndWithIPString(srcIP) //} //cidrmask := utils.GetCIDRMaskWithUint32Range(startIP, endIP) //fmt.Println(utils.GetDebugLine(), "Search client region info with srcIP: ", // srcIP, " StartIP : ", startIP, "==", utils.Int32ToIP4(startIP).String(), // " EndIP: ", endIP, "==", utils.Int32ToIP4(endIP).String(), " cidrmask : ", cidrmask) if edns != nil { var ipnet *net.IPNet ipnet, e := utils.ParseEdnsIPNet(edns.Address, edns.SourceScope, edns.Family) if e != nil { utils.ServerLogger.Error("utils.ParseEdnsIPNet error:", edns) } netaddr, mask := utils.IpNetToInt32(ipnet) //fmt.Println(utils.GetDebugLine(), "Got Edns client subnet from ecs query, netaddr : ", netaddr, // " mask : ", mask) utils.ServerLogger.Debug("Got Edns client subnet from ecs query, netaddr : ", netaddr, " mask : ", mask) //if (netaddr != startIP) || (mask != cidrmask) { // //fmt.Println(utils.GetDebugLine(), "iplookup data dose not match edns query result , netaddr : ", // // netaddr, "<->", startIP, " mask: ", mask, "<->", cidrmask) // utils.ServerLogger.Debug("iplookup data dose not match edns query result , netaddr : ", netaddr, "<->", startIP, " mask: ", mask, "<->", cidrmask) //} //// if there is no region info in region table of mysql db or no info in ipdb //if cidrmask <= 0 || startIP <= 0 { // startIP = netaddr // cidrmask = mask //} r, _ := NewRegion(R, netaddr, mask) // Parse edns client subnet utils.ServerLogger.Debug("GetAFromDNSBackend: ", " edns_h: ", edns_h, " edns: ", edns) regiontree.AddRegionToCache(r) } else { //todo: get StartIP/EndIP from iplookup module // netaddr, mask := DefaultNetaddr, DefaultMask r, _ := NewRegion(R, DefaultRadixNetaddr, DefaultRadixNetMask) //todo: modify to go func,so you can cathe the result regiontree.AddRegionToCache(r) //fmt.Println(utils.GetDebugLine(), "GetAFromDNSBackend: AddRegionToCache: ", r) //fmt.Println(regionTree.GetRegionFromCacheWithAddr(startIP, cidrmask)) } //todo: modify to go func,so you can cathe the result //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, " ns_a: ", ns_a, "add timer ") time.AfterFunc((time.Duration(r.Header().Ttl-5))*time.Second, func() { GetAFromDNSBackend(dst, srcIP) //todo:add timer for update region cache utils.QueryLogger.Info("Need to refresh for domain:", dst, " srcIP: ", srcIP) }) }(dst, srcIP, R[0], regiontree) } }
func QuerySOA(d string) (*dns.SOA, []*dns.NS, *MyError.MyError) { //fmt.Println(utils.GetDebugLine(), " QuerySOA: ", d) utils.ServerLogger.Debug(" QuerySOA domain: %s ", d) if _, ok := dns.IsDomainName(d); !ok { return nil, nil, MyError.NewError(MyError.ERROR_PARAM, d+" is not a domain name") } cf, el := dns.ClientConfigFromFile("/etc/resolv.conf") if el != nil { return nil, nil, MyError.NewError(MyError.ERROR_UNKNOWN, "Get dns config from file /etc/resolv.conf failed") } var soa *dns.SOA var ns_a []*dns.NS for c := 0; (soa == nil) && (c < 3); c++ { soa, ns_a = nil, nil r, e := DoQuery(d, cf.Servers, cf.Port, dns.TypeSOA, nil, UDP) // fmt.Println(r) if e != nil { utils.QueryLogger.Error("QeurySOA got error : "+e.Error()+ ". Param: %s , %v, %s, %v ", d, cf.Servers, cf.Port, dns.TypeSOA) continue } else { var rr []dns.RR if r.Answer != nil { rr = append(rr, r.Answer...) } if r.Ns != nil { rr = append(rr, r.Ns...) } soa, ns_a, e = ParseSOA(d, rr) if e != nil { switch e.ErrorNo { case MyError.ERROR_SUBDOMAIN, MyError.ERROR_NOTVALID: utils.ServerLogger.Error("ERROR_NOTVALID: %s", e.Error()) var ee *MyError.MyError d, ee = GenerateParentDomain(d) if ee != nil { if ee.ErrorNo == MyError.ERROR_NORESULT { // fmt.Println(ee) // continue } return nil, nil, MyError.NewError(MyError.ERROR_NORESULT, d+" has no SOA record "+" because of "+ee.Error()) } continue case MyError.ERROR_NORESULT: // c++ //fmt.Println(utils.GetDebugLine(), e) utils.ServerLogger.Error("ERROR_NORESULT: %s", e.Error()) //fmt.Println("+++++++++++++++++++++++++++++++++++") continue default: // c++ utils.ServerLogger.Error("ERROR_DEFAULT: %s", e.Error()) //fmt.Println(utils.GetDebugLine(), ".....................") //fmt.Println(utils.GetDebugLine(), e) continue // return nil, nil, e } } else { if cap(ns_a) < 1 { //fmt.Println(utils.GetDebugLine(), "QuerySOA: line 223: cap(ns_a)<1, need QueryNS ", soa.Hdr.Name) utils.ServerLogger.Debug("QuerySOA: cap(ns_a)<1, need QueryNS: %s", soa.Hdr.Name) ns_a, e = QueryNS(soa.Hdr.Name) if e != nil { //TODO: do some log } } // fmt.Println("============xxxxxx================") //fmt.Println(utils.GetDebugLine(), "QuerySOA: soa record ", soa, " ns_a: ", ns_a) utils.ServerLogger.Debug("QuerySOA: soa record %v ns_a: %v", soa, ns_a) return soa, ns_a, nil } } } return nil, nil, MyError.NewError(MyError.ERROR_UNKNOWN, d+" QuerySOA faild with unknow error") }