Windows sending/receiving IP packets to/from a SLIP connection?

The other side of the SLIP connection is Dosbox using a TCP connection sending/receiving data using it's virtual serial modem emulation. That Dosbox is running Windows 95(using a script when connecting to authenticate username/password/protocol(only slip supported atm). When Windows 95 connects with invalid username/password(if requested by the server, only when password-protected) or protocol(always asked by the server), the server simply hangs up(e.g. terminates the TCP connection and returns to waiting for a new connection). It currently only supports one username/password combination(account) and only one client connected at any point in time.

After authenticating(which happens in unencrypted ascii format, username/password/protocol input being terminated by carriage return(\r), NULL invalidates further input and entire input after it(preventing buffer overflow or invalid input and invalidates said field. Any invalid input continues on to the next step(username, then password, then protocol). The connection is terminated after receiving the protocol with invalid input or credentials in any of the three fields(username/password ignored when unrequested(in the case of them being set to empty values in the server configuration). Protocol must be 'slip'(without quotes), the only currently supported transmission protocol.

After being authenticated and sending the "\rCONNECTED\r" message to the Dosbox(or UniPCemu) client, the server switches into SLIP mode, which will relay packets to/from the real modem using pcap, while relaying received/sent packets to/from the Dosbox client(pcap->server->filters IP packet and removing ethernet header->encodes using SLIP->sent to Dosbox client; received from Dosbox client->decodes using SLIP->adds ethernet header based on configuration data(default gateway=destination MAC, emulated NIC=source MAC, type IP)->send using pcap).

Windows 95 connects successfully and I see it receiving/sending bytes, but I'm unsure that it's receiving valid packets correctly? When running the server and using the Arachne browser(MS-DOS) combined with SLIP driver, I see (using Windows 10 network packet capture software as well as the server's packet logs) it properly sending and receiving the packets(multiple DNS requests according to Windows 10(google.nl DNS request and response), but it doesn't seem to properly recognise the received response from the DNS servers(8.8.8.8/8.8.4.4 google DNS servers used)?

Anyone can see what's going wrong?
This is the code using the buffers to send/receive the SLIP packets to/from the network:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
			modem.networkdatatimer -= modem.networkpolltick; //Timing this byte by byte!
			if (net.packet && (!((modem.connected&2) && (packetserver_stage==PACKETSTAGE_SLIP)))) //Received a packet while not listening?
			{
				freez((void **)&net.packet,net.pktlen,"MODEM_PACKET"); //Release the packet to receive new packets again!				
			}
			if (modem.connected || modem.ringing) //Are we connected?
			{
				if (modem.connected==2) //Running the packet server?
				{
					if (packetserver_stage!=PACKETSTAGE_SLIP) goto skipSLIP; //Don't handle SLIP!
					//Handle packet server packet data transfers into the inputdatabuffer/outputbuffer to the network!
					if (packetserver_receivebuffer) //Properly allocated?
					{
						if (net.packet) //Packet has been received? Try to start transmit it!
						{
							if (fifobuffer_freesize(packetserver_receivebuffer)>=2) //Valid to produce more data?
							{
								if (packetserver_packetpos==0) //New packet?
								{
									if (net.pktlen>sizeof(ethernetheader.data)) //Length OK(at least one byte of content)?
									{
										memcpy(&ethernetheader.data,net.packet,sizeof(ethernetheader.data)); //Copy for inspection!
										if (ethernetheader.type!=SDL_SwapBE16(0x0800)) //Invalid type?
										{
											//dolog("ethernetcard","Discarding type: %04X",SDL_SwapBE16(ethernetheader.type)); //Showing why we discard!
											goto invalidpacket; //Invalid packet!
										}
										if ((memcmp(&ethernetheader.dst,packetserver_sourceMAC,sizeof(ethernetheader.dst))!=0) && (memcmp(&ethernetheader.dst,&packetserver_allMAC,sizeof(ethernetheader.dst))!=0)) //Invalid destination(and not broadcasting)?
										{
											//dolog("ethernetcard","Discarding destination."); //Showing why we discard!
											goto invalidpacket; //Invalid packet!
										}
										//Valid packet! Receive it!
										packetserver_packetpos = sizeof(ethernetheader.data); //Skip the ethernet header and give the raw IP data!
										//dolog("ethernetcard","Skipping %u bytes of header data...",packetserver_packetpos); //Log it!
									}
									else //Invalid length?
									{
										//dolog("ethernetcard","Discarding invalid packet size: %u...",net.pktlen); //Log it!
										invalidpacket:
										//Discard the invalid packet!
										freez((void **)&net.packet,net.pktlen,"MODEM_PACKET"); //Release the packet to receive new packets again!
										//dolog("ethernetcard","Discarding invalid packet size or different cause: %u...",net.pktlen); //Log it!
										net.packet = NULL; //No packet!
									}
								}
								if (net.packet) //Still a valid packet to send?
								{
									//Convert the buffer into transmittable bytes using the proper encoding!
									if (packetserver_packetpos<net.pktlen) //Not finished yet?
									{
										//Start transmitting data into the buffer, according to the protocol!
										datatotransmit = net.packet[packetserver_packetpos++]; //Read the data to construct!
										if (datatotransmit==SLIP_END) //End byte?
										{
											//dolog("ethernetcard","transmitting escaped SLIP END to client");
											writefifobuffer(packetserver_receivebuffer,SLIP_ESC); //Escaped ...
											writefifobuffer(packetserver_receivebuffer,SLIP_ESC_END); //END raw data!
										}
										else if (datatotransmit==SLIP_ESC) //ESC byte?
										{
											//dolog("ethernetcard","transmitting escaped SLIP ESC to client");
											writefifobuffer(packetserver_receivebuffer,SLIP_ESC); //Escaped ...
											writefifobuffer(packetserver_receivebuffer,SLIP_ESC_ESC); //ESC raw data!
										}
										else //Normal data?
										{
											//dolog("ethernetcard","transmitting raw to client: %02X",datatotransmit);
											writefifobuffer(packetserver_receivebuffer,datatotransmit); //Unescaped!
										}
									}
									else //Finished transferring a frame?
									{
										//dolog("ethernetcard","transmitting SLIP END to client and finishing packet buffer(size: %u)",net.pktlen);
										writefifobuffer(packetserver_receivebuffer,SLIP_END); //END of frame!
										logpacket(0,net.packet,net.pktlen); //Log it!
										freez((void **)&net.packet,net.pktlen,"MODEM_PACKET"); //Release the packet to receive new packets again!
										net.packet = NULL; //Discard the packet anyway, no matter what!
									}
								}
							}
						}

						//Transmit the encoded packet buffer to the client!
						if (fifobuffer_freesize(modem.outputbuffer) && peekfifobuffer(packetserver_receivebuffer,&datatotransmit)) //Able to transmit something?
						{
							for (;fifobuffer_freesize(modem.outputbuffer) && peekfifobuffer(packetserver_receivebuffer,&datatotransmit);) //Can we still transmit something more?
							{
								if (writefifobuffer(modem.outputbuffer,datatotransmit)) //Transmitted?
								{
									//dolog("ethernetcard","transmitted SLIP data to client: %02X",datatotransmit);
									datatotransmit = readfifobuffer(packetserver_receivebuffer,&datatotransmit); //Discard the data that's being transmitted!
								}
							}
						}
					}


Last edited on
Second part:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
					//Handle transmitting packets(with automatically increasing buffer sizing, as a packet can be received of any size theoretically)!
					if (peekfifobuffer(modem.inputdatabuffer,&datatotransmit)) //Is anything transmitted yet?
					{
						if (packetserver_transmitlength==0) //We might need to create an ethernet header?
						{
							//Build an ethernet header, platform dependent!
							//Use the data provided by the settings!
							byte b;
							for (b=0;b<6;++b) //Process MAC addresses!
							{
								ethernetheader.dst[b] = packetserver_gatewayMAC[b]; //Gateway MAC is the destination!
								ethernetheader.src[b] = packetserver_sourceMAC[b]; //Packet server MAC is the source!
							}
							ethernetheader.type = SDL_SwapBE16(0x0800); //We're an IP packet!
							for (b=0;b<14;++b) //Use the provided ethernet packet header!
							{
								if (!packetServerAddWriteQueue(ethernetheader.data[b])) //Failed to add?
								{
									break; //Stop adding!
								}
							}
							if (packetserver_transmitlength!=14) //Failed to generate header?
							{
								dolog("ethernetcard","Error: Transmit initialization failed. Resetting transmitter!");
								packetserver_transmitlength = 0; //Abort the packet generation!
							}
							else
							{
								//dolog("ethernetcard","Header for transmitting to the server has been setup!");
							}
						}
						if (datatotransmit==SLIP_END) //End-of-frame? Send the frame!
						{
							readfifobuffer(modem.inputdatabuffer,&datatotransmit); //Ignore the data, just discard the packet END!
							//Clean up the packet container!
							if (packetserver_transmitlength>sizeof(ethernetheader.data)) //Anything buffered(the header is required)?
							{
								//Send the frame to the server, if we're able to!
								if (packetserver_transmitlength<=0xFFFF) //Within length range?
								{
									//dolog("ethernetcard","Sending generated packet(size: %u)!",packetserver_transmitlength);
									logpacket(1,packetserver_transmitbuffer,packetserver_transmitlength); //Log it!

									sendpkt_pcap(packetserver_transmitbuffer,packetserver_transmitlength); //Send the packet!
								}
								else
								{
									dolog("ethernetcard","Error: Can't send packet: packet is too large to send(size: %u)!",packetserver_transmitlength);									
								}

								//Now, cleanup the buffered frame!
								freez((void **)&packetserver_transmitbuffer,packetserver_transmitsize,"MODEM_SENDPACKET"); //Free 
								packetserver_transmitsize = 1024; //How large is out transmit buffer!
								packetserver_transmitbuffer = zalloc(1024,"MODEM_SENDPACKET",NULL); //Simple transmit buffer, the size of a packet byte(when encoded) to be able to buffer any packet(since any byte can be doubled)!
							}
							else
							{
								dolog("ethernetcard","Error: Not enough buffered to send to the server(size: %u)!",packetserver_transmitlength);
							}
							packetserver_transmitlength = 0; //We're at the start of this buffer, nothing is sent yet!
							packetserver_transmitstate = 0; //Not escaped anymore!
						}
						else if (datatotransmit==SLIP_ESC) //Escaped something?
						{
							readfifobuffer(modem.inputdatabuffer,&datatotransmit); //Discard, as it's processed!
							packetserver_transmitstate = 1; //We're escaping something! Multiple escapes are ignored and not sent!
						}
						else //Active data?
						{
							if (packetserver_transmitlength) //Gotten a valid packet?
							{
								if (packetserver_transmitstate && (datatotransmit==SLIP_ESC_END)) //END sent?
								{
									if (packetServerAddWriteQueue(SLIP_END)) //Added to the queue?
									{
										readfifobuffer(modem.inputdatabuffer,&datatotransmit); //Ignore the data, just discard the packet byte!
										packetserver_transmitstate = 0; //We're not escaping something anymore!
									}
								}
								else if (packetserver_transmitstate && (datatotransmit==SLIP_ESC_ESC)) //ESC sent?
								{
									if (packetServerAddWriteQueue(SLIP_ESC)) //Added to the queue?
									{
										readfifobuffer(modem.inputdatabuffer,&datatotransmit); //Ignore the data, just discard the packet byte!
										packetserver_transmitstate = 0; //We're not escaping something anymore!
									}
								}
								else //Parse as a raw data when invalidly escaped or sent unescaped! Also terminate escape sequence!
								{
									if (packetServerAddWriteQueue(datatotransmit)) //Added to the queue?
									{
										readfifobuffer(modem.inputdatabuffer,&datatotransmit); //Ignore the data, just discard the packet byte!
										packetserver_transmitstate = 0; //We're not escaping something anymore!
									}
								}
							}
						}
					}
					skipSLIP: //SLIP isn't available? 


Anyone can see what's going wrong there?
sendpkt sends a packet using pcap(setting the send buffer to NULL). The buffer is automatically extended when filling it using packetServerAddWriteQueue(in increments of 1KB).
net.packet contains the received packet from pcap(discarded when transmitted to the client and set to NULL to receive a new packet).

modem.inputdatabuffer is a fifo buffer containing raw data received from Dosbox's connected modem TCP connection.
modem.outputbuffer is filled with raw data to send to the Dosbox's connected modem TCP connection.
Is there a way to log sent/received packets in Windows 95 to verify the server is working properly?
Eventually managed to get it working. There was a problem with the receiving of packets in that it's state wasn't cleaned up properly for receiving new packets, thus only receiving the first packet, which was discarded and all next packets were skipped. The full source is available at: https://bitbucket.org/superfury/unipcemu/src/5ee63d8b3a0bb33a1c1dca5f48fbb1831e8a2362/UniPCemu/hardware/modem.c?at=master&fileviewer=file-view-default#modem.c-1965

It seems to be working properly(with Windows 95 retrieving HTTP links, HTTPS isn't working(might be due to Windows 95 issues).
Last edited on
Glad you figured it out, thanks for posting your findings.

But I'm curious, why Windows 95? It's so oooooollld.
It's mainly a little side-project to support Windows 95 or MS-DOS providing ISP internet over a virtual TCP connection providing SLIP serial modem internet to e.g. Dosbox, UniPCemu or other software connecting serial to a TCP port.

So far tested with Dosbox running Windows 95(3.11 should work as well) and with the Arachne web browser.

You could theoretically use it with a virtual serial modem as well combined with modem-to-TCP pirt driver and a old dial-up compatible web browser to experience 54K dial-up internet internet on a modern OS(e.g. Windows 10) and maybe browser.
Last edited on
Topic archived. No new replies allowed.