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()
				}
			}
		}
	}
}
Example #3
0
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!")
}
Example #4
0
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()
		}
	}
}