Ejemplo n.º 1
0
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)
	}

}
Ejemplo n.º 2
0
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")
}