• Please review our updated Terms and Rules here

Call for ideas/fixes for the next mTCP version

Thanks. I know that manually renaming the files should work, but having to change imported source code is always a hassle. The 'unzip' utility also has the "-LL" argument to force lower-casing of all file names when extracting (this is also the most convenient solution for mass-renaming).

If you could consider this at some point in the future, it would be appreciated. Downstream projects often include a copy of mTCP, making them needlessly harder to cross-compile unless the maintainer does the work himself.

I saw the -LL option as a cheat that somebody else posted and I thought it was cute, and it is easier to do that the multiple passes of renaming. After that only the makefiles needs to be fixed.

At some point I'll do it, but I'd rather do that in a special update where there are no other changes. (Kind of a like a source code formatting only change.) It makes the review so much easier.
 
The Packet Driver interface is not designed to handle multiple concurrent users, but nothing prevents you from running two mTCP applications attached to different packet drivers simultaneously. You could write a Packet Driver 'shim' to provide multiple entry points (interrupts), but you'd need to figure out how to assign incoming packets to them. The easy solution is to set the hardware into promiscuous mode, assign a separate MAC address to each interrupt, then filter by incoming MAC address. Essentially, each application would become its own system on the network. (Note: This is not compatible with wireless networks.)
The packet driver interface supports multiple applications so long as they use different protocols. An application can register itself as a receiver of a certain EtherType or, as in the case of mTCP, register itself to receive all packets regardless of type. This is, in my opinion, actually a bug in the mTCP applications - they attempt to register themselves as a receiver of all EtherTypes, and if that fails (because some other protocol is already registered), then they won't even try to register themselves for only the protocols they actually need (e.g. IP and ARP).

Of course, this is rarely a problem in practice because in DOS you can only have one foreground application so the other networking software has to be a TSR. Also, these days most people (applications) only use IP and ARP anyway so it's kind of a moot point.
 
What you are calling a bug was a conscious design decision at the time. It simplified the code and that's what I was looking for.

The only problem with it that I see is that I did not foresee something like EtherDFS which would use a reserved ethertype. Somehow people are using that at the same time as mTCP so I suspect many packet drivers are not honoring the restriction anyway.
 
Another possible problem might be that older packet drivers (written to conform to specification versions prior to 1.07) will not work with mTCP at all. I'm not sure how common that problem is though.
 
In the 15 years I have been widely distributing mTCP programs I have not had a report of a packet driver that it did not work with, until NetDrive last year which the 3Com 3C905 (PCI) driver hated. I worked around that by experimenting and changing the way I hook interrupts.

When that kind of thing happens I debug it and make changes. So far I've never had a report of a packet driver not working with one of the standard mTCP programs.
 
OK, so here's a couple of bugs.

Under DOS 2.11 DHCP.EXE writes a bogus timestamp to the MTCP configuration file which makes the rest of the applications complain about the DHCP lease being expired. A workaround is to use a static IP but that might not be an option for some of us die-hard DOS 2.x users. ;)

NETDRIVE.SYS; If the server responds with an error to a write-with-verify request then the driver will ignore the error and proceed to verify the data in the response. I'm not actually sure if this is a bug or by design but it seems a bit strange.

EDIT: Also, what is the purpose of fakeStat() in NETDRIVE.EXE? It doesn't appear to be needed.
 
Last edited:
OK, so here's a couple of bugs.

Under DOS 2.11 DHCP.EXE writes a bogus timestamp to the MTCP configuration file which makes the rest of the applications complain about the DHCP lease being expired. A workaround is to use a static IP but that might not be an option for some of us die-hard DOS 2.x users. ;)

NETDRIVE.SYS; If the server responds with an error to a write-with-verify request then the driver will ignore the error and proceed to verify the data in the response. I'm not actually sure if this is a bug or by design but it seems a bit strange.

EDIT: Also, what is the purpose of fakeStat() in NETDRIVE.EXE? It doesn't appear to be needed.

There is nothing strange or different about the code under DOS 2.1 vs. any other version of DOS. To actually be able to debug this I need to know the sequence of what you did.
  • What was the system time set to before DHCP ran?
  • What was recorded in the DHCP file?
  • Did you run SNTP to set the system time after running DHCP or set the time some other way?
It's a known problem that if you boot the system and the time is not set, running DHCP and then setting the system time with SNTP makes the DHCP lease look ancient. The workaround for that (if you did that) is to run DHCP a second time after running SNTP.
 
Nevermind. I just realized it's probably a machine specific clock driver that doesn't work under QEMU. I'm using "Microsoft MS-DOS 2.11 [Leading Edge OEM] (5.25-360k).7z" downloaded from... somewhere that I don't recall. The time is always reported as 11:11:11.11 and the date changes completely with just seconds between running date. So, apologies for wasting your time.

Though, what about the write-with-verify thing in NETDRIVE.SYS? Is that intentional?
 
Good catch, that's a bug but not a serious one - it doesn't affect correctness or break anything. I will fix it because source code should not be confusing.

It would be more efficient to check the return code first and not even bother comparing the contents of the received packet, but honestly, unless DOS asks for a sector that doesn't exist, the image is read-only, or there is a server error you are never going to get a bad return code. If you do then it will cost some extra time but the end result will be the same - the write is not done.

I also fixed the Compaq DOS 3.31 "fixme" recently .. FAT16B will work correctly in that version with the next code.
 
Good catch, that's a bug but not a serious one - it doesn't affect correctness or break anything. I will fix it because source code should not be confusing.
Well, if it was hard to write it should be hard to read, right? :D

It would be more efficient to check the return code first and not even bother comparing the contents of the received packet, but honestly, unless DOS asks for a sector that doesn't exist, the image is read-only, or there is a server error you are never going to get a bad return code. If you do then it will cost some extra time but the end result will be the same - the write is not done.
I haven't checked the server source code but I assume the server doesn't send data back for verification if there's an error. If it does then that would be a problem with this bug.

I also fixed the Compaq DOS 3.31 "fixme" recently .. FAT16B will work correctly in that version with the next code.
I was looking into that myself (I've been following the vogons thread) and was looking in RBIL and found this;
Code:
    Note:    to reliably determine which variant of the request block for
          functions 04h,08h,09h has been passed to the driver, check
          the length field as well as the word at offset 14h.  If the
          length is 1Eh and 14h=FFFFh, use the DWORD at 1Ah as the
          starting sector number; if the length is 18h, use the DWORD
          at 14h; otherwise, use the WORD at 14h.
It seems that the request header length is 22 (16h) bytes in both DOS 2.x and DOS 4.x (search for DRDWRHL) so now I'm left wondering which DOS versions uses header lengths of 18h and 1Eh bytes. (I'm trying to find the request header lengths for all DOS versions so I can figure out the most efficient way to do this).
 
I will fix it because source code should not be confusing.
I found something else that makes me confused;
Code:
       ; This is a successful read.  Copy the payload, but only copy what we
       ; requested.  If the number of received bytes doesn't match the expected
       ; bytes then we mark this as bad.

       mov ax, [bx].pkt_udp_len
       xchg al, ah                  ; Never forget, network byte order for UDP fields.
       sub ax, Udp_Nd_Len
       jz receiveExit
You subtract the UDP and NetDrive header lengths to get the length of the payload but then just exit without marking it as bad if the payload size is zero. It seems to me that the "jz receiveExit" at the end should not be there as the expected size should be the amount of requested sectors in bytes (and you check for that just below this code).
 
It's not a bug. I think that case covers a zero length read. It's not supposed to be possible, but I coded defensively. I wasn't consistent everywhere with it, but as the code matures that will improve.

This thread is for gathering ideas for the next mTCP and making the occasional release announcement. Please send me a bug report if you really have a bug.
 
Last edited:
Back
Top