anchor.diff:  
   %% @doc Resolve the questions in the message.
   -spec resolve(dns:message(), [dns:rr()], dns:ip()) -> dns:message().
  -resolve(Message, AuthorityRecords, Host) ->
  -  resolve(Message, AuthorityRecords, Host, Message#dns_message.questions).
  +resolve(Message, AuthorityRecords, ClientIP) ->
  +  resolve(Message, AuthorityRecords, ClientIP, Message#dns_message.questions).
   
   
   %% There were no questions in the message so just return it.
   -spec resolve(dns:message(), [dns:rr()], dns:ip(), [dns:question()]) -> dns:message().
  -resolve(Message, _AuthorityRecords, _Host, []) -> Message;
  +resolve(Message, _AuthorityRecords, _ClientIP, []) -> Message;
   %% There is one question in the message; resolve it.
  -resolve(Message, AuthorityRecords, Host, [Question]) -> resolve(Message, AuthorityRecords, Host, Question);
  +resolve(Message, AuthorityRecords, ClientIP, [Question]) -> resolve(Message, AuthorityRecords, ClientIP, Question);
   %% Resolve the first question. Additional questions will be thrown away for now.
  -resolve(Message, AuthorityRecords, Host, [Question|_]) -> resolve(Message, AuthorityRecords, Host, Question);
  +resolve(Message, AuthorityRecords, ClientIP, [Question|_]) -> resolve(Message, AuthorityRecords, ClientIP, Question);
   
   %% Start the resolution process on the given question.
   %% Step 1: Set the RA bit to false as we do not handle recursive queries.
  -resolve(Message, AuthorityRecords, Host, Question) when is_record(Question, dns_query) ->
  -  resolve(Message#dns_message{ra = false}, AuthorityRecords, Question#dns_query.name, Question#dns_query.type, Host).
  +resolve(Message, AuthorityRecords, ClientIP, Question) when is_record(Question, dns_query) ->
  +  resolve(Message#dns_message{ra = false}, AuthorityRecords, Question#dns_query.name, Question#dns_query.type, ClientIP).
   
   %% With the extracted Qname and Qtype in hand, find the nearest zone
   %% Step 2: Search the available zones for the zone which is the nearest ancestor to QNAME
  
positive.code:       %lager:debug("No type matches found, using custom handlers"),
        NewRecords = lists:map(erldns_records:replace_name(Qname), lists:flatten(lists:map(custom_lookup(Qname, Qtype, MatchedRecords), erldns_handler:get_handlers()))),
        %lager:debug("Records from custom handlers: ~p", [NewRecords]),
        resolve_best_match_with_wildcard(Message, Qname, Qtype, Host, CnameChain, MatchedRecords, Zone, [], NewRecords);
      _ ->
        resolve_best_match_with_wildcard(Message, Qname, Qtype, Host, CnameChain, MatchedRecords, Zone, [], TypeMatches)
    end;
  
  % It is a wildcard CNAME
  resolve_best_match_with_wildcard(Message, Qname, Qtype, Host, CnameChain, BestMatchRecords, Zone, CnameRecords) ->
    resolve_best_match_with_wildcard_cname(Message, Qname, Qtype, Host, CnameChain, BestMatchRecords, Zone, CnameRecords).
  
  % It is not a CNAME and there were no exact type matches
  resolve_best_match_with_wildcard(Message, _Qname, _Qtype, _Host, _CnameChain, _BestMatchRecords, Zone, [], []) ->
    Message#dns_message{aa = true, authority=Zone#zone.authority};
  
  % It is not a CNAME and there were exact type matches
  resolve_best_match_with_wildcard(Message, _Qname, _Qtype, _Host, _CnameChain, _BestMatchRecords, _Zone, [], TypeMatches) ->
    Message#dns_message{aa = true, answers = Message#dns_message.answers ++ TypeMatches}.
  
  
  
  
  % It is a CNAME and the Qtype was CNAME
  resolve_best_match_with_wildcard_cname(Message, _Qname, ?DNS_TYPE_CNAME, _Host, _CnameChain, _BestMatchRecords, _Zone, CnameRecords) ->
    Message#dns_message{aa = true, answers = Message#dns_message.answers ++ CnameRecords};
  
  % It is a CNAME and the Qtype was not CNAME
  resolve_best_match_with_wildcard_cname(Message, Qname, Qtype, Host, CnameChain, BestMatchRecords, Zone, CnameRecords) ->
    CnameRecord = lists:last(CnameRecords), % There should only be one CNAME. Multiple CNAMEs kill unicorns.
    resolve_best_match_with_wildcard_cname(Message, Qname, Qtype, Host, CnameChain, BestMatchRecords, Zone, CnameRecords, lists:member(CnameRecord, CnameChain)).
  
  % Indicates CNAME loop
  resolve_best_match_with_wildcard_cname(Message, _Qname, _Qtype, _Host, _CnameChain, _BestMatchRecords, _Zone, _CnameRecords, true) ->
    %lager:debug("CNAME loop detected (best match)"),
    Message#dns_message{aa = true, rc = ?DNS_RCODE_SERVFAIL};
  
  % We should follow the CNAME
  resolve_best_match_with_wildcard_cname(Message, _Qname, Qtype, Host, CnameChain, _BestMatchRecords, Zone, CnameRecords, false) ->
    %lager:debug("Follow CNAME (best match)"),
    CnameRecord = lists:last(CnameRecords),
    Name = CnameRecord#dns_rr.data#dns_rrdata_cname.dname,
    restart_query(Message#dns_message{aa = true, answers = Message#dns_message.answers ++ CnameRecords}, Name, Qtype, Host, CnameChain ++ CnameRecords, Zone, erldns_zone_cache:in_zone(Name)).
  
  
  
  
  % There are referral records
  resolve_best_match_referral(Message, Qname, Qtype, Host, CnameChain, BestMatchRecords, Zone, ReferralRecords) ->
    resolve_best_match_referral(Message, Qname, Qtype, Host, CnameChain, BestMatchRecords, Zone, ReferralRecords, lists:filter(erldns_records:match_type(?DNS_TYPE_SOA), BestMatchRecords)). % Lookup SOA in best match records
  
  % Indicate that we are not authoritative for the name as there were no
  % SOA records in the best-match results. The name has thus been delegated
  % to another authority.
  resolve_best_match_referral(Message, _Qname, _Qtype, _Host, _CnameChain, _BestMatchRecords, _Zone, ReferralRecords, []) ->
    Message#dns_message{aa = false, authority = Message#dns_message.authority ++ ReferralRecords};
  
  % We are authoritative for the name since there was an SOA record in
  % the best match results.
  resolve_best_match_referral(Message, _Qname, _Qtype, _Host, [], _BestMatchRecords, _Zone, _ReferralRecords, Authority) ->
    Message#dns_message{aa = true, rc = ?DNS_RCODE_NXDOMAIN, authority = Authority};
  
  % We are authoritative and the Qtype is ANY so we just return the 
  % original message.
  resolve_best_match_referral(Message, _Qname, ?DNS_TYPE_ANY, _Host, _CnameChain, _BestMatchRecords, _Zone, _ReferralRecords, _Authority) ->
    Message;
  resolve_best_match_referral(Message, _Qname, _Qtype, _Host, _CnameChain, _BestMatchRecords, _Zone, _ReferralRecords, Authority) ->
    Message#dns_message{authority = Authority}.
  
  
  
negative.code:     {Records0, SOA} = normalize_dns_rr_list(RecordsSOA),
      Response = Message#dns_message{answers = [SOA] ++ Records0},
      Response;
  resolve(Message, AuthorityRecords, Qname, Qtype, ClientIP) ->
    Zone = erldns_zone_cache:find_zone(Qname, lists:last(AuthorityRecords)), % Zone lookup
    Records = resolve(Message, Qname, Qtype, Zone, ClientIP, _CnameChain = []),
    additional_processing(rewrite_soa_ttl(Records), ClientIP, Zone).
  
  %% No SOA was found for the Qname so we return the root hints
  %% Note: it seems odd that we are indicating we are authoritative here.
  resolve(Message, _Qname, _Qtype, {error, not_authoritative}, _ClientIP, _CnameChain) ->
    case erldns_config:use_root_hints() of
      true ->
        {Authority, Additional} = erldns_records:root_hints(),
  