diff --git a/FastGithub.Dns/DnsServerHostedService.cs b/FastGithub.Dns/DnsServerHostedService.cs index 812f3af..773a06b 100644 --- a/FastGithub.Dns/DnsServerHostedService.cs +++ b/FastGithub.Dns/DnsServerHostedService.cs @@ -3,6 +3,7 @@ using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using System; +using System.Diagnostics; using System.Net; using System.Net.Sockets; using System.Threading; @@ -46,7 +47,13 @@ namespace FastGithub.Dns /// public override Task StartAsync(CancellationToken cancellationToken) { - this.socket.Bind(new IPEndPoint(IPAddress.Any, 53)); + const int DNS_PORT = 53; + if (OperatingSystem.IsWindows() && UdpTable.TryGetOwnerProcessId(DNS_PORT, out var processId)) + { + Process.GetProcessById(processId).Kill(); + } + + this.socket.Bind(new IPEndPoint(IPAddress.Any, DNS_PORT)); if (OperatingSystem.IsWindows()) { const int SIO_UDP_CONNRESET = unchecked((int)0x9800000C); diff --git a/FastGithub.Dns/FastGithub.Dns.csproj b/FastGithub.Dns/FastGithub.Dns.csproj index efd748e..6e90918 100644 --- a/FastGithub.Dns/FastGithub.Dns.csproj +++ b/FastGithub.Dns/FastGithub.Dns.csproj @@ -2,6 +2,7 @@ net5.0 + true diff --git a/FastGithub.Dns/UdpTable.cs b/FastGithub.Dns/UdpTable.cs new file mode 100644 index 0000000..73ec7f1 --- /dev/null +++ b/FastGithub.Dns/UdpTable.cs @@ -0,0 +1,94 @@ +using System; +using System.Buffers.Binary; +using System.Net; +using System.Net.Sockets; +using System.Runtime.InteropServices; +using System.Runtime.Versioning; + +namespace FastGithub.Dns +{ + /// + /// windows iphlpapi + /// + [SupportedOSPlatform("windows")] + unsafe static class UdpTable + { + private const int ERROR_INSUFFICIENT_BUFFER = 122; + + [DllImport("iphlpapi.dll", SetLastError = true)] + private static extern uint GetExtendedUdpTable(void* pUdpTable, ref int pdwSize, bool bOrder, AddressFamily ulAf, UDP_TABLE_CLASS tableClass, uint reserved = 0); + + /// + /// 获取udp端口的占用进程id + /// + /// + /// + /// + public static bool TryGetOwnerProcessId(int port, out int processId) + { + processId = 0; + var pdwSize = 0; + var result = GetExtendedUdpTable(null, ref pdwSize, false, AddressFamily.InterNetwork, UDP_TABLE_CLASS.UDP_TABLE_OWNER_PID); + if (result != ERROR_INSUFFICIENT_BUFFER) + { + return false; + } + + var buffer = new byte[pdwSize]; + fixed (byte* pUdpTable = &buffer[0]) + { + result = GetExtendedUdpTable(pUdpTable, ref pdwSize, false, AddressFamily.InterNetwork, UDP_TABLE_CLASS.UDP_TABLE_OWNER_PID); + if (result != 0) + { + return false; + } + + var table = Marshal.PtrToStructure(new IntPtr(pUdpTable)); + foreach (var row in table.rows) + { + if (row.LocalPort == port) + { + processId = row.ProcessId; + return true; + } + } + } + + return false; + } + + + private enum UDP_TABLE_CLASS + { + UDP_TABLE_BASIC, + UDP_TABLE_OWNER_PID, + UDP_TABLE_OWNER_MODULE + } + + [StructLayout(LayoutKind.Sequential)] + private struct MIB_UDPTABLE_OWNER_PID + { + public uint dwNumEntries; + + [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 1)] + public MIB_UDPROW_OWNER_PID[] rows; + } + + [StructLayout(LayoutKind.Sequential)] + private struct MIB_UDPROW_OWNER_PID + { + public uint localAddr; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + public byte[] localPort; + + public int owningPid; + + public int ProcessId => owningPid; + + public IPAddress LocalAddress => new(localAddr); + + public ushort LocalPort => BinaryPrimitives.ReadUInt16BigEndian(this.localPort); + } + } +}