using System.Net; using System.Net.NetworkInformation; using System.Net.Sockets; using System.Text; // Args: [interface_ip] [interval_ms] // Defaults: auto-detect LAN IP, 50ms string localIp = args.Length > 0 ? args[0] : GetLanInterfaceIp() ?? "0.0.0.0"; int intervalMs = args.Length > 1 && int.TryParse(args[1], out int iv) ? iv : 50; using var sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); sock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); sock.EnableBroadcast = true; var localEp = new IPEndPoint(IPAddress.Parse(localIp), 68); sock.Bind(localEp); Console.WriteLine($"Bound to {localEp} (SO_REUSEADDR)"); Console.WriteLine("Sending NOPs + listening. Press Ctrl+C to stop."); Console.WriteLine(); var cts = new CancellationTokenSource(); var recvTask = Task.Run(() => ReceiveLoop(sock, cts.Token)); var destEp = new IPEndPoint(IPAddress.Broadcast, 67); uint session = 1; uint nonce = 0; while (!cts.Token.IsCancellationRequested) { nonce++; string msg = $"HKMSTR {session} {nonce}\n"; byte[] payload = Encoding.UTF8.GetBytes(msg); try { int sent = sock.SendTo(payload, destEp); Console.WriteLine($"[{DateTime.Now:HH:mm:ss.fff}] SENT s={session} n={nonce} {sent} bytes"); } catch (Exception ex) { Console.WriteLine($"[{DateTime.Now:HH:mm:ss.fff}] SEND FAILED: {ex.Message}"); } try { Thread.Sleep(intervalMs); } catch (OperationCanceledException) { break; } } cts.Cancel(); await recvTask; static string? GetLanInterfaceIp() { foreach (var nic in NetworkInterface.GetAllNetworkInterfaces()) { if (nic.OperationalStatus != OperationalStatus.Up) continue; if (nic.NetworkInterfaceType == NetworkInterfaceType.Loopback) continue; if (nic.Description.Contains("WireGuard", StringComparison.OrdinalIgnoreCase)) continue; foreach (var addr in nic.GetIPProperties().UnicastAddresses) { if (addr.Address.AddressFamily == AddressFamily.InterNetwork) { var ip = addr.Address.ToString(); if (ip.StartsWith("192.168.") || ip.StartsWith("10.") || ip.StartsWith("172.")) return ip; } } } return null; } static void ReceiveLoop(Socket sock, CancellationToken ct) { byte[] buffer = new byte[4096]; EndPoint fromEp = new IPEndPoint(IPAddress.Any, 0); while (!ct.IsCancellationRequested) { int received; try { if (!sock.Poll(500_000, SelectMode.SelectRead)) continue; received = sock.ReceiveFrom(buffer, ref fromEp); } catch (Exception ex) { Console.WriteLine($"[{DateTime.Now:HH:mm:ss.fff}] RECV ERROR: {ex.Message}"); continue; } string text = Encoding.UTF8.GetString(buffer, 0, received).TrimEnd('\n', '\r'); if (!text.StartsWith("HKMSTR")) { Console.WriteLine($"[{DateTime.Now:HH:mm:ss.fff}] RECV {received} bytes from {fromEp} (no magic)"); continue; } Console.WriteLine($"[{DateTime.Now:HH:mm:ss.fff}] RECV {received} bytes from {fromEp}: {text}"); } }