public QueryResult Resolve(Query query) { // Find potential matches var matches = _dnsRuleGroups .Select(group => new { Group = group, RuleMatchResult = GetRuleMatch(query, group) }) .Where(match => match.RuleMatchResult.Match) .OrderByDescending(match => match.RuleMatchResult.HostnameSimilarity) .ToArray(); if (!matches.Any()) { return new QueryResult() { Result = false }; } var bestMatch = matches.First(); var rule = bestMatch.RuleMatchResult.Rule; string ruleValue; if (!string.IsNullOrWhiteSpace(rule.ValueAlias)) { var result = _dnsValueAliases .Where(alias => alias != null && rule.ValueAlias != null && string.Compare(alias.Name, rule.ValueAlias, StringComparison.InvariantCultureIgnoreCase) == 0) .FirstOrDefault(); if (result == null) { throw new WranglerConfigurationException( string.Format("Alias {0} is specified in Rule {1} but wasn't found", rule.ValueAlias, rule.ToString())); } ruleValue = result.Value; } else { ruleValue = rule.Value; } return new QueryResult() { Result = true, RecordType = rule.RecordType, RecordValue = ruleValue, RuleResult = rule.RuleType }; }
private double FindHostnameSimilarity(Query query, DnsRule rule) { var hostnames = rule.Hostnames; if (query.QueryType != DnsRecordType.CNAME && query.QueryType != DnsRecordType.A) { if (hostnames.Any(hostname => hostname.HostnameType == HostnameType.Exact && hostname.HostnameEntry == query.Question)) { return 1; } return 0; } if (hostnames.Any(hostname => hostname.HostnameType == HostnameType.Exact && hostname.HostnameEntry == query.Question)) { return 1; } if (hostnames.Any(hostname => hostname.HostnameType == HostnameType.Wildcard && query.Question.EndsWith(hostname.HostnameEntry))) { return 0.9; } return 0; }
private double SimilarRuleTypes(Query query, DnsRule rule) { if (rule.RuleType.HasValue && (rule.RuleType.Value == DnsRuleType.NXDomain || rule.RuleType.Value == DnsRuleType.ResolveUpstream)) { return 0.1; } if (rule.RecordType == query.QueryType) { return 1; } if (query.QueryType == DnsRecordType.A && rule.RecordType == DnsRecordType.CNAME) { return 0.9; } return 0; }
private RuleMatchResult GetRuleMatch(Query query, DnsRuleGroup group) { // Examine the group's rules and give a result. var similarRules = group.Rules .Select(rule => new { HostnameSimilarity = FindHostnameSimilarity(query, rule), TypeSimilarity = SimilarRuleTypes(query, rule), Rule = rule }) .Where(result => result.HostnameSimilarity > 0 && result.TypeSimilarity > 0) .OrderByDescending(rule => rule.HostnameSimilarity) .ThenByDescending(rule => rule.TypeSimilarity) .ToArray(); if (!similarRules.Any()) { return new RuleMatchResult { Match = false }; } return similarRules .Select( rule => new RuleMatchResult { HostnameSimilarity = rule.HostnameSimilarity, Match = true, Rule = rule.Rule }) .FirstOrDefault(); }