From 97d92450b37eb74d4b2694660ff739b414445c03 Mon Sep 17 00:00:00 2001 From: Josh Dersch Date: Thu, 21 Feb 2019 16:34:57 -0800 Subject: [PATCH] Changes to make IFS work correctly with npcap (which replaces WinPcap) in WinPcap compatibility mode. --- .gitignore | 6 ++- PUP/Conf/ifs.cfg | 2 +- PUP/Entrypoint.cs | 3 +- PUP/IFS.csproj | 4 +- PUP/MiscServicesProtocol.cs | 90 ++++++++++++++++++++++++++++++++++++- PUP/PUP.cs | 6 ++- PUP/Transport/Ethernet.cs | 6 +-- 7 files changed, 108 insertions(+), 9 deletions(-) diff --git a/.gitignore b/.gitignore index 7964536..96bd921 100644 --- a/.gitignore +++ b/.gitignore @@ -186,4 +186,8 @@ FakesAssemblies/ # LightSwitch generated files GeneratedArtifacts/ _Pvt_Extensions/ -ModelManifest.xml \ No newline at end of file +ModelManifest.xml +/PUP/.vs/IFS/v15/Server/sqlite3/db.lock +/PUP/.vs/IFS/v15/Server/sqlite3/storage.ide +/PUP/.vs/IFS/v15/Server/sqlite3/storage.ide-shm +/PUP/.vs/IFS/v15/Server/sqlite3/storage.ide-wal diff --git a/PUP/Conf/ifs.cfg b/PUP/Conf/ifs.cfg index 25b2ce4..a890586 100644 --- a/PUP/Conf/ifs.cfg +++ b/PUP/Conf/ifs.cfg @@ -36,4 +36,4 @@ BOLDelay = 5000 # Debug settings LogTypes = All -LogComponents = Routing +LogComponents = None diff --git a/PUP/Entrypoint.cs b/PUP/Entrypoint.cs index 716203f..175d292 100644 --- a/PUP/Entrypoint.cs +++ b/PUP/Entrypoint.cs @@ -85,7 +85,8 @@ namespace IFS { foreach (LivePacketDevice device in LivePacketDevice.AllLocalMachine) { - if (device.GetNetworkInterface().Name.ToLowerInvariant() == Configuration.InterfaceName.ToLowerInvariant()) + if (device.GetNetworkInterface() != null && + device.GetNetworkInterface().Name.ToLowerInvariant() == Configuration.InterfaceName.ToLowerInvariant()) { Router.Instance.RegisterRAWInterface(device); bFound = true; diff --git a/PUP/IFS.csproj b/PUP/IFS.csproj index f5a717f..6918367 100644 --- a/PUP/IFS.csproj +++ b/PUP/IFS.csproj @@ -139,7 +139,9 @@ PreserveNewest - + + PreserveNewest + PreserveNewest diff --git a/PUP/MiscServicesProtocol.cs b/PUP/MiscServicesProtocol.cs index d2363e7..5698802 100644 --- a/PUP/MiscServicesProtocol.cs +++ b/PUP/MiscServicesProtocol.cs @@ -113,7 +113,11 @@ namespace IFS case PupType.MailCheckRequestLaurel: SendMailCheckResponse(p); - break; + break; + + case PupType.MicrocodeRequest: + SendMicrocodeResponse(p); + break; default: Log.Write(LogComponent.MiscServices, String.Format("Unhandled misc. protocol {0}", p.Type)); @@ -427,6 +431,90 @@ namespace IFS } } + private void SendMicrocodeResponse(PUP p) + { + // + // The request PUP contains the file number in the lower-order 16-bits of the pup ID. + // Assuming the number is a valid bootfile, we start sending it to the client's port via EFTP. + // + ushort fileNumber = (ushort)p.ID; + + Log.Write(LogType.Verbose, LogComponent.MiscServices, "Microcode request is for file {0}.", fileNumber); + + FileStream microcodeFile = BootServer.GetStreamForNumber(fileNumber); + + if (microcodeFile == null) + { + Log.Write(LogType.Warning, LogComponent.MiscServices, "Microcode file {0} does not exist or could not be opened.", fileNumber); + } + else + { + // Send the file. The MicrocodeReply protocol is extremely simple: + // Just send a sequence of MicrocodeReply PUPs containing the microcode data, + // there are no acks or flow control of any kind. + Log.Write(LogType.Warning, LogComponent.MiscServices, "Sending microcode file {0}.", fileNumber); + SendMicrocodeFile(p.SourcePort, microcodeFile); + } + } + + private void SendMicrocodeFile(PUPPort sourcePort, Stream microcodeFile) + { + // + // "For version 1 of the protocol, a server willing to supply the data simply sends a sequence of packets + // of type MicrocodeReply as fast as it can. The high half of its pupID contains the version number(1) + // and the low half of the pupID contains the packet sequence number. After all the data packets + // have been sent, the server sends an empty (0 data bytes) packet for an end marker. There are no + // acknowledgments. This protocol is used by Dolphins and Dorados. + // Currently, the version 1 servers send packets containing 3 * n words of data. This constraint is imposed by the + // Rev L Dolphin EPROM microcode. I’d like to remove this restriction if I get a chance, so please don’t take + // advantage of it unless you need to.The Rev L Dolphin EPROM also requires the second word of the source + // socket to be 4. / HGM May - 80." + // + + // TODO: this should happen in a worker thread. + // + + // + // We send 192 words of data per PUP (3 * 64) in an attempt to make the Dolphin happy. + // We space these out a bit to give the D-machine time to keep up, we're much much faster than they are. + // + PUPPort localPort = new PUPPort(DirectoryServices.Instance.LocalHostAddress, 4); + + byte[] buffer = new byte[384]; + bool done = false; + uint id = 0; + + while (!done) + { + int read = microcodeFile.Read(buffer, 0, buffer.Length); + + if (read < buffer.Length) + { + done = true; + } + + if (read > 0) + { + PUP microcodeReply = new PUP(PupType.MicrocodeReply, (id | 0x00010000), sourcePort, localPort, buffer); + Router.Instance.SendPup(microcodeReply); + } + + // Pause a bit to give the D0 time to breathe. + System.Threading.Thread.Sleep(5); + + id++; + } + + // + // Send an empty packet to conclude the transfer. + // + PUP endReply = new PUP(PupType.MicrocodeReply, (id | 0x00010000), sourcePort, localPort, new byte[] { }); + Router.Instance.SendPup(endReply); + + Log.Write(LogType.Warning, LogComponent.MiscServices, "Microcode file sent."); + + } + private struct BootDirectoryBlock { public ushort FileNumber; diff --git a/PUP/PUP.cs b/PUP/PUP.cs index 0e58528..f5f2aac 100644 --- a/PUP/PUP.cs +++ b/PUP/PUP.cs @@ -97,7 +97,11 @@ namespace IFS // Gateway Information Protocol GatewayInformationRequest = 128, - GatewayInformationResponse = 129 + GatewayInformationResponse = 129, + + // D0 Microcode (handled by misc. services) + MicrocodeRequest = 180, + MicrocodeReply = 181, } public struct PUPPort diff --git a/PUP/Transport/Ethernet.cs b/PUP/Transport/Ethernet.cs index 3f30d0f..074a4b8 100644 --- a/PUP/Transport/Ethernet.cs +++ b/PUP/Transport/Ethernet.cs @@ -53,7 +53,7 @@ namespace IFS.Transport _routerCallback = callback; // Now that we have a callback we can start receiving stuff. - Open(false /* not promiscuous */, int.MaxValue); + Open(false /* not promiscuous */, 0); // Kick off the receiver thread, this will never return or exit. Thread receiveThread = new Thread(new ThreadStart(BeginReceive)); @@ -207,7 +207,7 @@ namespace IFS.Transport else { // Not a PUP, Discard the packet. We will not log this, so as to keep noise down. - //Log.Write(LogLevel.DroppedPacket, "Not a PUP. Dropping."); + // Log.Write(LogType.Verbose, LogComponent.Ethernet, "Not a PUP (type 0x{0:x}. Dropping.", p.Ethernet.EtherType); } } @@ -215,7 +215,7 @@ namespace IFS.Transport { _communicator = _interface.Open( 0xffff, - promiscuous ? PacketDeviceOpenAttributes.Promiscuous | PacketDeviceOpenAttributes.NoCaptureLocal: PacketDeviceOpenAttributes.NoCaptureLocal, + promiscuous ? PacketDeviceOpenAttributes.Promiscuous : PacketDeviceOpenAttributes.None, timeout); _communicator.SetKernelMinimumBytesToCopy(1);