/// <summary> /// Removes all gamespy related redirects in the specified hosts file container /// </summary> /// <param name="HostFile"></param> private static void RemoveRedirects(HostsFile HostFile) { // Remove Gamespy Addresses. Use a Bitwise OR here to execute both methods if (HostFile.Remove(Bf2StatsHost) | HostFile.RemoveAll(GamespyHosts)) { // Save Changes HostFile.Save(); // Flush the Cache of the gamespy hosts foreach (string host in GamespyHosts) { DnsFlushResolverCacheEntry(host); } // Flush stats server DnsFlushResolverCacheEntry(Bf2StatsHost); } }
/// <summary> /// Preforms the pings required to fill the dns cache. /// The reason we ping, is because once the HOSTS file is locked, any request /// made to a url (when the DNS cache is empty), will skip the hosts file, because /// it cant be read. If we ping first, then the DNS cache fills up with the IP /// addresses in the hosts file. /// </summary> public static void RebuildDNSCache(CancellationToken CancelToken) { // Must be hosts file! if (RedirectMethod == RedirectMode.DnsServer || !RedirectsEnabled) { return; } // Grab hosts file base HostsFile hFile = (RedirectMethod == RedirectMode.HostsFile) ? HostsFileSys as HostsFile : HostsFileIcs as HostsFile; // Rebuild the DNS cache with the hosts file redirects foreach (string hostname in hFile.GetLines().Keys) { // Quit on cancel if (CancelToken.IsCancellationRequested) { return; } // Only ping gamespy urls with the hosts ics file if (RedirectMethod == RedirectMode.HostsIcsFile && !hostname.Contains("gamespy")) { continue; } // Attempt to ping the server try { // Clear the record from the DNS cache DnsFlushResolverCacheEntry(hostname); // Ping server to get the IP address in the dns cache Dns.GetHostAddresses(hostname); } catch { continue; } } }
/// <summary> /// Queries the DNS Cache for the Gamespy hosts, and verifies that the /// IP addresses in the DNS Cache match that of the desired redirect IP /// </summary> public static bool VerifyDNSCache(IProgress <DnsCacheResult> Progress = null) { // Nothing to do here if redirects are disabled if (!RedirectsEnabled) { return(false); } // Grab our saved hosts file IP addresses if (RedirectMethod != RedirectMode.DnsServer) { // Grab hosts file base HostsFile hFile = (RedirectMethod == RedirectMode.HostsFile) ? HostsFileSys as HostsFile : HostsFileIcs as HostsFile; // Fetch our saved IPAddresses GamespyServerAddress = (hFile.HasEntry("master.gamespy.com")) ? hFile.Get("master.gamespy.com") : null; StatsServerAddress = (hFile.HasEntry(Bf2StatsHost)) ? hFile.Get(Bf2StatsHost) : null; } // Flush our cache report DnsCacheReport.Entries.Clear(); // Verify Gamespy Server IP addresses if (GamespyServerAddress != null) { foreach (string address in GamespyHosts) { // Create new report DnsCacheResult Result = new DnsCacheResult(address, GamespyServerAddress); // Add the result to the report DnsCacheReport.AddOrUpdate(Result); // Report progress if we have a progress object if (Progress != null) { Progress.Report(Result); } } } // Verify Stats Server address if (StatsServerAddress != null) { // Create new report DnsCacheResult Result = new DnsCacheResult(Bf2StatsHost, StatsServerAddress); // Add the result to the report DnsCacheReport.AddOrUpdate(Result); // Report progress if we have a progress object if (Progress != null) { Progress.Report(Result); } } // Set internal DnsCacheReport.LastRefresh = DateTime.Now; return(DnsCacheReport.ErrorFree); }
/// <summary> /// Applies the specified IP address redirects for the chosen redirect method /// </summary> public static Task <bool> ApplyRedirectsAsync(ServiceProvider Provider, IProgress <TaskStep> Progress) { return(Task.Run(() => { // Try and grab the IPAddresses of these providers try { SetProviderIPAddress(Provider); Program.Config.LastUsedProvider = Provider.Name; } catch (Exception e) { Progress.Report(new TaskStep(0, e.Message, true, e)); return false; } // Can't do anything with a dns server if (RedirectMethod == RedirectMode.DnsServer) { return true; } // Remove old settings if (RedirectsEnabled) { RemoveRedirects(); } // === Apply new settings === // // Grab hosts file base HostsFile hFile = (RedirectMethod == RedirectMode.HostsFile) ? HostsFileSys as HostsFile : HostsFileIcs as HostsFile; // Unlock system hosts file if (RedirectMethod == RedirectMode.HostsFile) { // Make sure file is writable if (SysHostsFile.IsLocked && !HostsFileSys.UnLock()) { Progress.Report(new TaskStep(0, "Cannot allow READ permissions on the Hosts File", true, hFile.LastException)); return false; } else { Progress.Report(new TaskStep(0, "")); } } // Make sure file is writable if (!hFile.CanRead) { Progress.Report(new TaskStep(1, "Cannot read the Hosts File", true, hFile.LastException)); return false; } else { Progress.Report(new TaskStep(1, "")); } // Make sure file is readable if (!hFile.CanWrite) { Progress.Report(new TaskStep(2, "Cannot write to the Hosts File", true, hFile.LastException)); return false; } else { Progress.Report(new TaskStep(2, "")); } // ===== Set Redirect Addresses ===== // // Stats Server if (StatsServerAddress != null) { hFile.Set(Bf2StatsHost, StatsServerAddress); } // Gamespy Servers if (GamespyServerAddress != null) { foreach (string hostname in GamespyHosts) { hFile.Set(hostname, GamespyServerAddress); } } // Report Progress Progress.Report(new TaskStep(3, "Gamespy Redirects Set")); // ===== Save Redirects ===== // int Step = 4; string ErrDesc = ""; try { // Attempt to save the hosts file ErrDesc = "Unable to Save Hosts File!"; hFile.Save(); // Report Success Progress.Report(new TaskStep(Step++, "Hosts File Saved Successfully")); // Rebuild the DNS Cache ErrDesc = "Failed to Rebuild the DNS Cache"; RebuildDNSCache(CancellationToken.None); // Report Success Progress.Report(new TaskStep(Step++, "DNS Cache Rebuilt Successfully")); } catch (Exception e) { RemoveRedirects(); Progress.Report(new TaskStep(Step, ErrDesc, true, e)); return false; } // Lock system hosts File if (RedirectMethod == RedirectMode.HostsFile) { if (HostsFileSys.Lock()) { // Report Success Progress.Report(new TaskStep(Step++, "Hosts File Read Permissions Removed")); return true; } else { // Report Error Progress.Report(new TaskStep(Step++, "Cannot Remove Hosts File Read Permissions!", true, HostsFileSys.LastException)); return true; } } return true; })); }
/// <summary> /// The main entry point for the redirector /// </summary> /// <returns>Returns wether the DNS cache results match the selected IPAddresses</returns> public static bool Initialize() { // Only initialize once if (!IsInitialized) { IsInitialized = true; TraceLog.WriteLine("Initializing Redirector"); TraceLog.Indent(); // Set the System.Net DNS Cache refresh timeout to 1 millisecond ServicePointManager.DnsRefreshTimeout = 1; // Get config options RedirectMethod = Program.Config.RedirectMode; TraceLog.WriteLine("Chosen Redirect mode: " + RedirectMethod.ToString()); // Create new Instances HostsFileSys = new SysHostsFile(); HostsFileIcs = new HostsFileIcs(); // Detect redirects bool IcsHasRedirects = HostsFileIcs.HasAnyEntry(GamespyHosts) || HostsFileIcs.HasEntry(Bf2StatsHost); bool HostsHasRedirects = HostsFileSys.HasAnyEntry(GamespyHosts) || HostsFileSys.HasEntry(Bf2StatsHost); // Write tracelogs TraceLog.WriteLine("System Hosts has redirects: " + ((HostsHasRedirects) ? "True" : "False")); TraceLog.WriteLine("Hosts.ics has redirects: " + ((IcsHasRedirects) ? "True" : "False")); // Both files cannot have redirects! if (IcsHasRedirects && HostsHasRedirects) { // Get the Non-Selected mode, and remove those redirects HostsFile toRemove = (RedirectMethod == RedirectMode.HostsFile) ? HostsFileIcs as HostsFile : HostsFileSys as HostsFile; try { // Remove all redirects TraceLog.Write("Removing redirects from unchosen hostsfile... "); RemoveRedirects(toRemove); TraceLog.WriteLine("Success"); } catch (Exception e) { TraceLog.WriteLine("Failed!"); TraceLog.Indent(); TraceLog.TraceError(e.Message); } } // Set old redirect data if we have it if (RedirectsEnabled) { // Grab our service provider ServiceProvider provider = ClientSettings.ServiceProviders .Where(x => x.Name == Program.Config.LastUsedProvider) .FirstOrDefault(); // Make sure we have an object before settings if (provider != null) { SetProviderIPAddress(provider); } } // Remove all indents TraceLog.Unindent(true); } // Verify cache return((RedirectsEnabled) ? VerifyDNSCache() : true); }