Exemple #1
0
func (s *Server) Query(ctx context.Context, in *pb.RawMsg) (*pb.RawMsg, error) {
	tr := trace.New("grpctodns", "Query")
	defer tr.Finish()

	r := &dns.Msg{}
	err := r.Unpack(in.Data)
	if err != nil {
		return nil, err
	}

	if glog.V(3) {
		tr.LazyPrintf(util.QuestionsToString(r.Question))
	}

	// TODO: we should create our own IDs, in case different users pick the
	// same id and we pass that upstream.
	from_up, err := dns.Exchange(r, s.Upstream)
	if err != nil {
		msg := fmt.Sprintf("dns exchange error: %v", err)
		glog.Info(msg)
		tr.LazyPrintf(msg)
		tr.SetError()
		return nil, err
	}

	if from_up == nil {
		err = fmt.Errorf("no response from upstream")
		tr.LazyPrintf(err.Error())
		tr.SetError()
		return nil, err
	}

	if glog.V(3) {
		util.TraceAnswer(tr, from_up)
	}

	buf, err := from_up.Pack()
	if err != nil {
		glog.Infof("   error packing: %v", err)
		tr.LazyPrintf("error packing: %v", err)
		tr.SetError()
		return nil, err
	}

	return &pb.RawMsg{Data: buf}, nil
}
Exemple #2
0
func (s *Server) Handler(w dns.ResponseWriter, r *dns.Msg) {
	tr := trace.New("dnstox", "Handler")
	defer tr.Finish()

	tr.LazyPrintf("from:%v   id:%v", w.RemoteAddr(), r.Id)

	if glog.V(3) {
		tr.LazyPrintf(util.QuestionsToString(r.Question))
	}

	// We only support single-question queries.
	if len(r.Question) != 1 {
		tr.LazyPrintf("len(Q) != 1, failing")
		dns.HandleFailed(w, r)
		return
	}

	// Forward to the unqualified upstream server if:
	//  - We have one configured.
	//  - There's only one question in the request, to keep things simple.
	//  - The question is unqualified (only one '.' in the name).
	useUnqUpstream := s.unqUpstream != "" &&
		strings.Count(r.Question[0].Name, ".") <= 1
	if useUnqUpstream {
		u, err := dns.Exchange(r, s.unqUpstream)
		if err == nil {
			tr.LazyPrintf("used unqualified upstream")
			if glog.V(3) {
				util.TraceAnswer(tr, u)
			}
			w.WriteMsg(u)
		} else {
			tr.LazyPrintf("unqualified upstream error: %v", err)
			dns.HandleFailed(w, r)
		}

		return
	}

	// Forward to the fallback server if the domain is on our list.
	if _, ok := s.fallbackDomains[r.Question[0].Name]; ok {
		u, err := dns.Exchange(r, s.fallbackUpstream)
		if err == nil {
			tr.LazyPrintf("used fallback upstream (%s)", s.fallbackUpstream)
			if glog.V(3) {
				util.TraceAnswer(tr, u)
			}
			w.WriteMsg(u)
		} else {
			tr.LazyPrintf("fallback upstream error: %v", err)
			dns.HandleFailed(w, r)
		}

		return
	}

	// Create our own IDs, in case different users pick the same id and we
	// pass that upstream.
	oldid := r.Id
	r.Id = <-newId

	from_up, err := s.resolver.Query(r, tr)
	if err != nil {
		glog.Infof(err.Error())
		tr.LazyPrintf(err.Error())
		tr.SetError()
		return
	}

	if glog.V(3) {
		util.TraceAnswer(tr, from_up)
	}

	from_up.Id = oldid
	w.WriteMsg(from_up)
}