NetFoss requires you to run it with a command line similar to this:
nf.bat /n[#] /h[#] [command line]
where /n[#] is a node number and /h[#] is an OS socket handle.
I want to write something in C# very similar to what a telnet BBS would do when it runs door games. It should accept the client socket, gather a bit of information passed into it from the client, then pass the socket over to NetFoss to be used to run a DOS based application that supports communications via a fossil driver.
I honestly was just guessing about how to go about this, and here's what I came up with:
class Program
{
const int BACKLOG_SIZE = 20;
static void Main(string[] args)
{
Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
server.Bind(new IPEndPoint(IPAddress.Any, 3102));
server.Listen(BACKLOG_SIZE);
while (true)
{
Socket socket = server.Accept();
Process p = new Process();
p.EnableRaisingEvents = false;
p.StartInfo.FileName = #"c:\netfoss\nf.bat";
p.StartInfo.Arguments = #"/n1 /h" + socket.Handle + #" c:\game\game.bat 1";
p.StartInfo.WorkingDirectory = "c:\netfoss";
p.StartInfo.UseShellExecute = false;
p.Start();
}
}
}
Interestingly enough, the application that NetFoss is running via game.bat is being output to the C# application's console window but not the telnet client, and even more interesting is that the telnet client DOES receive the initial NetFoss message that shows it is able to communicate with the socket. So, why is the application that is passed to NetFoss outputting to my console window instead of the telnet client?
Anyone know what I'm missing?
EDIT:
I forgot to mention that I also tried setting UseShellExecute to TRUE, and this throws a NetFoss error saying that it is an invalid handle. From my understanding, I would have to duplicate the handle in some way so that the unmanaged application can access it? Is there any way to accomplish what I'm trying to do using C#?
Thanks,
Marc
It is normal that the DOS application outputs to your console window, but it should also output to the telnet client.
Since you are seeing the initial NetFoss version message in your telnet client, we know that the socket handle is being sucesfully passed to NetFoss... So it sounds like the problem is that your DOS application is not FOSSIL aware, or is not currently configured to use a FOSSIL or an INT14h communications method.
Regards, Mike
NetFoss developer
Related
I have a need to talk to multiple devices on a private LAN using a proprietary UDP protocol. In a production setting we have a industrial PC running a C++ application that can connect to multiple devices and communicate freely with them. I am trying to duplicate that communication using C# for a windows application that technicians, testers and others would be using. I have probably done this myself a thousands times in c++ but c# seems to be giving me all sorts of fits.
I have one UDP listener listening on Any IP and specific Port. This port is different from the device command port. This receives a periodic heartbeat from each device. From this communication I am able to get the specific IP and command Port for that device. The program maintains a list of devices and displays that lists to the user. The user can then select a specific device and inspect it more for more details.
If there are several devices with the same port number the program will not be able to inspect those devices at the same time. When the user selects the device the program creates a new instance of the UdpClient. In pseudo-code form:
udpConnection = new UdpClient();
udpConnection.ExclusiveAddressUse = false;
udpConnection.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
udpConnection.Client.Bind(localEndpoint);
udpConnection.Client.Connect(remoteEndpoint);
Local Endpoint is the Local interface IP and the Device Port Number of the machine the application is running on. Remote EndPoint is the Device IP and Device Port that the application wants to inspect further.
As anyone had similar issues and what have you done to get around it?
Thanks in advance
Update sample network diagram and further explanation:
Network Diagram
In the image I will be able to have two windows viewing Device A and C or B and C simultaneously with no issues. However if I have Device A and C the window that I opened second will not get any communications updates until I close the first window. If I "sniff" the network with WireShark I see all the communications as I would expect.
Code Snippet:
private void ClientThread()
{
IPEndPoint myEndPoint;
myLogger = LogManager.GetLogger("ClientLogs");
myLogger.Debug("Client Started!");
IPAddress ClientAddress = System.Net.IPAddress.Parse(ClientIP);
myIP = "10.0.0.4"; // Currently hard-coded local interface IP
IPAddress thisAddress = System.Net.IPAddress.Parse(myIP);
ClientEndPoint = new IPEndPoint(ClientAddress, Convert.ToInt32(ClientPort));
myEndPoint = new IPEndPoint(thisAddress, Convert.ToInt32(ClientPort)); // Both forms launch but only the first one will receive data.
//myEndPoint = new IPEndPoint(thisAddress, 0); // Both forms will launch but no data received (packets do show being received in wireshark)
//myEndPoint = new IPEndPoint(IPAddress.Any, ClientPort); // Both forms launch but only the first one will receive data.
try
{
myUDP = new UdpClient();
myUDP.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); // "Only one usage of each socket address (protocol/network address/port) is normally permitted" Exception when removed.
myUDP.ExclusiveAddressUse = false; // No difference if this is removed
myUDP.Client.Bind(myEndPoint); // Neither form will receive data if this is removed
myUDP.Client.Connect(ClientEndPoint); // removing this will allow the forms to launch but again the only the first will receive data
}
catch (Exception ex)
{
myUDP = null;
myLogger.Fatal(String.Format("Error in setting up UDP Client: {0}", ex.Message));
return;
}
myLogger.Debug(String.Format("Attempt to connect to : {0} on {1}", ClientIP, Convert.ToInt32(ClientPort)));
byte[] bytes = new byte[1452];
try
{
while (ThreadLoop)
{
IPEndPoint newEndPoint = new IPEndPoint(IPAddress.Any, 0);
Byte[] receiveBytes = myUDP.Receive(ref newEndPoint);
ParseProtocolPacket(ref receiveBytes); // Code to parse the data received
}
}
catch (Exception Ex)
{
myLogger.Debug("Client Socket Other Error: " + Ex.Message);
}
}
I think your problem is here:
udpConnection.Client.Bind(localEndpoint);
This line, if I understand correctly, is telling it to use the same local port to make the outbound request. But you already have another UdpClient listening on that port, so Windows won't know which one to send the traffic to (or it just sends it to the first one).
You should be able to just not use Bind() here. Without it, when you call Connect(), it will assign a random local port, which is the way most outbound network requests work.
Or if you need to specify the network interface, then pass 0 for the port and Windows will assign one:
localEndpoint = new IPEndPoint(ipAddress, 0);
I have a 'honeypot' that I am developing in C# that listens on a series of ports (user inputted). It is a large project/windows service that functions as expected for almost any port entered and will not listen on ports that currently have something listening already. The problem is that when I test the service using telnet or netcat, opening a connection on port 23 is not caught by my service and therefore establishes the connection.
I open the ports in the firewall by doing the following:
for (int i = 0; i < ports.Length; i++)
{
string arg = "advfirewall firewall add rule name=\"PeepHole Open" + "\" dir=in action=allow protocol=TCP localport=" + ports[i];
string arg1 = "advfirewall firewall add rule name=\"PeepHole Open" + "\" dir=in action=allow protocol=UDP localport=" + ports[i];
ProcessStartInfo procStartInfo = new ProcessStartInfo("netsh", arg);
ProcessStartInfo procStartInfo1 = new ProcessStartInfo("netsh", arg1);
procStartInfo.RedirectStandardOutput = true;
procStartInfo1.RedirectStandardOutput = true;
procStartInfo.UseShellExecute = false;
procStartInfo1.UseShellExecute = false;
procStartInfo.CreateNoWindow = true;
procStartInfo1.CreateNoWindow = true;
Process.Start(procStartInfo1);
Process.Start(procStartInfo);
}
And I start the listeners by:
IPEndPoint Ep = new IPEndPoint(IPAddress.Parse("0.0.0.0"), current_port);
//TcpListener tempListener = new TcpListener(hostIP, current_port);
TcpListener tempListener = new TcpListener(Ep);
TCP_Listener listen = new TCP_Listener(); //my defined tcplistener struct
listen.listener = tempListener; //set the Listener's TcpListener field
listen.port = current_port; //set the Listener's Port field
listen.listener.Start(); //start this particular TcpListener
tcp_listener_list.Add(listen); //add the struct to the list of Listeners
And accept the TCP connection by:
for (int i = 0; i < tcp_listener_list.Count - 1; i++)
{
if (tcp_listener_list[i].listener.Pending())
{
TcpClient client = tcp_listener_list[i].listener.AcceptTcpClient();
int clientPort = tcp_listener_list[i].port;
IPEndPoint ep = client.Client.RemoteEndPoint as IPEndPoint;
ThreadPool.QueueUserWorkItem(LogTCP, new object[] { client, clientPort, ep });
}
}
And in LogTCP I close the connection by (where client is a TcpClient object):
NetworkStream networkStream = client.GetStream();
networkStream.Close();
client.Close(); //close the connection, all the data is gleaned from the attacker already
Now the problem is that when I run telnet or netcat to test the closing and logging of the port, my code is never executed and the connection is established because the port is opened; the TCP connection never is .Pending() and if I remove that, the issue is persistent. Also, I have the same issue if I set up the listeners to use IPAddress.Any and if I reconfigure my accept method to AcceptSocket with or without the .Pending() if statement. Does windows treat certain ports differently on a low level with certain programs?
I am running a windows service from Windows 8.1 and sending TCP connections through telnet on putty (on the machine that the service is installed on) and telnet and netcat on a Linux VM. Both Telnet Client and Telnet Server are disabled on the 'host' machine.
I have tried many different variations of closing the sockets and connections that I found during my researching.
client.Client.Close() produces an ObjectDisposedException
client.Client.Shutdown(SocketShutdown.Both) makes all previously 'working' ports hang connections with CLOSE_WAIT
I think the key here, is you mention as an aside that you have created your own struct. Structs are very tricky. You might think that the below code will end up with a TCP_Listener instance that has your tempListener and current_port. But if you set a breakpoint you'll probably notice otherwise. Every modification you do on a struct actually returns a brand new struct, so you can't assign fields one at a time like you do with a class.
TCP_Listener listen = new TCP_Listener(); //my defined tcplistener struct
listen.listener = tempListener; //set the Listener's TcpListener field
listen.port = current_port; //set the Listener's Port field
listen.listener.Start();
I would recommend, rather than a struct, you use a class. Or you initialize your struct as new TCP_Listener(tempListener, current_port), then Start it.
That is at least part of your problem. Once you fix that, let us know if it's still not working and we can look at the next issue.
Pending is never needed. Just continually accept on all listeners. Start one task per listener to do that:
while (true) {
ProcessConnectionAsync(await listener.AcceptAsync());
}
Something like this.
And here is an off-by-one bug: tcp_listener_list.Count - 1. But that bug goes away when you do it as explained above.
Regarding closing, why not just client.Dispose();? This is the normal way to do resource management in .NET. Nothing else is required.
I am working with some legacy TCP server code that works with sockets directly as it was written in .NET 2.0 and earlier. The server has a feature to 'stop' and 'start' accepting client connections.
To troubleshoot the issue I run the server in the console mode as admin user. On top of that I have eliminated the socket accept thread from the equation and all the code does is something like:
tcpListener = new TcpListener(IPAddress.Any, this.Port);
tcpListener.Start();
and
tcpListener.Stop();
This called from different methods. I have debugged the code and I am pretty sure the code executes only once. However, the issue is that call to Stop does not actually releases the socket address and subsequent call to Start therefore fails with the error "Only one usage of each socket address (protocol/network address/port) is normally permitted". I can also confirm from the ProcessExplorer that the server is still listening on the server port.
When I write a small console app that uses the same code snippets everything works fine. I have even tried tracing the .NET network and socket libraries, but there is no error or anything to indicate problems there.
It is not clear to me why call to Stop does not release the socket address?
Update:
After more investigation it turns out that there is some strange effect of child process launch to the TcpListener. I have made a 'bare bone' sample code that illustrates the issue:
using System;
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
using System.Reflection;
using System.Threading;
namespace TcpListenerStartStop
{
class MyTcpListener
{
public static void Main(string[] args)
{
Int32 port = 13000;
if (args.Length > 0) // indicates child process
{
Thread.Sleep(4000); // as a child do nothing and wait for a few seconds
}
else // parent will play with the TcpListener
{
//LaunchChildProcess(); // launch child here and listener restart is fine?!?
var tcpListener = new TcpListener(IPAddress.Any, port);
tcpListener.Start();
Console.WriteLine("Starting test in 2 seconds...");
Thread.Sleep(2000);
LaunchChildProcess(); // launch child here and listener restart is not fine?!?
tcpListener.Stop();
Console.WriteLine("Stopped.");
Thread.Sleep(1000);
tcpListener.Start();
Console.WriteLine("Started");
}
Console.WriteLine("All is good, no exceptions :)");
}
private static void LaunchChildProcess()
{
Process process = new Process();
var processStartInfo = new ProcessStartInfo
{
CreateNoWindow = true,
FileName = Assembly.GetExecutingAssembly().Location,
UseShellExecute = false, // comment out this line out listener restart is fine?!?
Arguments = "child"
};
process.StartInfo = processStartInfo;
process.Start();
}
}
}
As you can see from the code if I launch the child process before creating a listener everything is fine, if I do it after listener restart fails. This has something to do with the UseShellExecute = false option for the child process.
Not sure if this is .NET bug or some special behavior I was not aware of?
The real reason for this behavior is that TcpListener socket handle is inherited by the child process together with many other handles. Some discussions on the topic can be found here and here.
One obvious solution is to launch the child process before initializing TcpListener.
Another solution is to have UseShellExecute = true to avoid this socket handle inheritance.
Ideal solution would be to set socket handle option to prevent the inheritance by the child process. It is possible to do it in .NET via a P/Invoke on the TcpListener socket handle:
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool SetHandleInformation(IntPtr hObject, uint dwMask, uint dwFlags);
private const uint HANDLE_FLAG_INHERIT = 1;
private static void MakeNotInheritable(TcpListener tcpListener)
{
var handle = tcpListener.Server.Handle;
SetHandleInformation(handle, HANDLE_FLAG_INHERIT, 0);
}
I'm using C# and .NET 4.5, with the Visual Studio 2012 compiler/IDE to open and interact with a serial port. My code is designed to connect to the QSB quadrature-to-USB converter from US Digital.
Here is the code that I'm using to open the port and connect.
this.Port = new SerialPort();
this.Port.BaudRate = 230400;
this.Port.PortName = "COM9";
this.Port.Parity = Parity.None;
this.Port.Handshake = Handshake.None;
this.Port.DataBits = 8;
this.Port.StopBits = StopBits.One;
this.Port.Open();
Setting a breakpoint immediately after this.Port.Open() allows me to verify that the serial port is indeed connected. In another section of code, the following is called in response to a button push:
this.Port.WriteLine("W168");
This command *should cause my hardware to spin a motor, and in fact it does if I send the command using Putty, or using a Python script that I wrote (both using exactly the same settings as the C# code does). Yet nothing happens. I can open the port in Putty or Python and execute the command with the expected results, and then run my C# code and nothing happens.
Am I missing something C# specific that prevents this from working?
For what it's worth, here is my working Python code:
ser = serial.Serial("COM9", 230400, timeout=1)
ser.write(b"W168\n")
Link to pySerial documentation: http://pyserial.sourceforge.net/pyserial_api.html#classes
Default values for fields mentioned in the C# code but not mentioned in the python call above are:
bytesize = 8
parity = none
stopbits = one
xonxoff = false
rtscts = false
dsrdtr = false
When working with Serial Ports in C# there is one thing to always remember when establishing a connection. If you set the handshake value to none like this:
this.Port.Handshake = Handshake.None;
Then you need to set a few more parameters as well for the connection to be completed, and they are:
this.Port.DtrEnable = true;
this.Port.RtsEnable = true;
The reaso is because the Dtrenable means this:
Data Terminal Ready (DTR) signal
MSDN explains what DTR means as this:
Data Terminal Ready (DTR) is typically enabled during XON/XOFF software handshaking and Request to Send/Clear to Send (RTS/CTS) hardware handshaking, and modem communications.
Rtsenable means this:
Request to Send (RTS) signal
MSDN explains what RTS means as this:
The Request to Transmit (RTS) signal is typically used in Request to Send/Clear to Send (RTS/CTS) hardware handshaking.
Together these two parameters handle the handshaking of the serial port communications without you having to define it between the master and slave.
This problem is driving me crazy! I've read all the questions on Stack Overflow but I'm still stuck.
My as3 program works very well, but when I have finished it and put it on a server, it starts to request this famous policy file.
AS3 script:
socket.addEventListener(Event.CONNECT, onConnect);
socket.addEventListener(Event.CLOSE, onClose);
socket.addEventListener(IOErrorEvent.IO_ERROR, onError);
socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecError);
socket.addEventListener(ProgressEvent.SOCKET_DATA, onResponse);
socket.connect( MYHOST, 4242 );
C# server code:
TcpListener serverSocket = new TcpListener(4242);
TcpClient clientSocket = default(TcpClient);
serverSocket.Start();
clientSocket = serverSocket.AcceptTcpClient();
NetworkStream networkStream = clientSocket.GetStream();
StreamReader read = new StreamReader(networkStream, Encoding.UTF8);
StreamWriter write = new StreamWriter(networkStream, Encoding.UTF8);
response = read.ReadLine();
if (response.Contains("policy"))
{
write.Write("<?xml version=\"1.0\"?><cross-domain-policy><allow-access-from domain=\"*\" to-ports=\"*\" /></cross-domain-policy>\0");
write.Flush();
clientSocket.Close();
return;
}
So, when the AS3 doesn't find the policy on the default port 843 (or something similar), it asks directly on the same socket as the connection.
My C# code sees the request and replies, after which the AS3 script closes the connection (which is OK), but it never reconnects.
I have tried to put this in the AS3 before the connect():
Security.loadPolicyFile( "xmlsocket://myhost.com:4242");
But when I do the connect() it simply gets stuck and never requests the policy file. After I close the AS3 application, my server sees the request, but the connection is closed. It's like the client forget to do a flush.
Can someone tell me how I can solve this problem correctly?
After 3 days i have finally discovered what is the bug in the code.
A bounty of 50 points and no one have noticed it :-(
Is very stupid, a novice error:
When the flash application ask for the policy file dont send the newline char, but the terminating char '\0'.
and im reading with the read.ReadLine(); that read until the '\n', so it stuck.
Thank you all for your replies.
I've faced a problem similar to your's. The fact is, that while running a Flash app into a C#, it lose lot's of requests which port differs from standart. The solution is not to use such requests in Flash. So you have to put them into C#, and call this functions with Flash's ExternalInterface.call. When the request is completed, your C# must call a Flash function, passing req's answer as a parameter.