To create a network share between a Linux host and an MS-DOS guest running in QEMU in order to share files between the host and a running guest bidirectionally and instantly; and to have a packet driver ready at interrupt 0x60 for the usual-suspect networking programs.
QEMU emulator version 7.2.22 (Debian 1:7.2+dfsg-7+deb12u18+b2)
Samba installed (samba package in Debian). Configuration
will be described later.
A QEMU VM with an installation of MS-DOS 6.22. I’ve installed from disk images found in the Internet Archive and started the setup described here from a clean slate.
Microsoft Network Client 3.0. This
post provides a ZIP archive containing two self-extracting archives for
DOS, each of which contains the files for one installation disk. I
struggled a bit trying to create floppy images using qemu-img and
mkfs.fat, and copying the files from within the VM (the floppies kept
getting corrupt), so I ended up using mtools for formatting
and copying.
dd if=/dev/zero of=disk1.img bs=1024 count=1440
mformat -f 1440 -i disk1.img :: # Note the double colon at the end of these lines
mcopy -i disk1.img hd/DSK1/* ::
mdir -i disk1.img ::
You can mount your raw (not qcow2) harddisk image as a loopback
device in order to get the files out of the guest after self-extraction.
Since the image has a partition table, this requires passing
mount the offset to the actual filesystem, which can be
done using a Bash function like the one below. Which will probably break
if the output format of fdisk doesn’t match exactly what I
have. The gist is just
offset = physical_sector_size * start_sector_of_partition.
#
# mount_img(image, mount_point)
#
mount_img() {
o=$(sudo fdisk -l "$1" | tr '\n' ' ')
ptn1='Sector size[^:]+:[^/]+/ ([0-9]+)'
ptn2=$1'1[[:space:]*]+([0-9]+)'
[[ "$o" =~ $ptn1 ]]; secsize=${BASH_REMATCH[1]}
[[ "$o" =~ $ptn2 ]]; startsec=${BASH_REMATCH[1]}
uid=$(id -u); gid=$(id -g)
sudo mount -o loop,offset=$((secsize * startsec)),uid=$uid,gid=$gid "$1" "$2"
}
It is not advisable to have the image mounted while the guest is
running: I’ve experienced disk writes from the guest being discarded
when the disk was mounted on both sides. This is precisely why I wanted
to set up a network share. It’s still good to be able to mount the image
and write to it though, since this is how you revert changes to the
guest’s AUTOEXEC.BAT and CONFIG.SYS when
you’ve bricked it.
AMD PCnet FAST III Ethernet drivers. You can get
these here
(only OEMSETUP.INF and PCNTND.DOS are
needed).
Packet driver interface over NDIS.
DIS_PKT.DOS is in the archive downloadable here.
So, to recapitulate, by now you have the following resources ready.
disk1.img and
disk2.img, with the contents from DSK3-1.EXE
and DSK3-2.EXE from msnetwork_client_3-0.zip
each. Copy the exes to your guest, extract them, shut down the guest,
and copy the extracted files onto the disk images as described above.
(If you manage to copy them from within the guest, you’re luckier than
me.)
OEMSETUP.INF and
PCNTND.DOS to a directory on the guest, say
C:\PCNET.
DIS_PKT.DOS to C:\NET.
Before installing anything in DOS, let’s configure Samba. The SMB
that Microsoft Network Client will be speaking is quite old, so we need
to tune Samba down to let it accept the stone age version of the
protocol. This is done quite easily by setting a few options in
/etc/samba/smb.conf.
In the [global] section:
netbios name = ELSEWHERE
server min protocol = CORE
server max protocol = NT1
lanman auth = yes
client lanman auth = yes
ntlm auth = yes
raw NTLMv2 auth = yes
client NTLMv2 auth = yes
bind interfaces only = no
map to guest = Bad User
guest ok = yes
netbios name is your personal name, and it must match
what you use to connect from the guest side later, so keep note of
it.
And, at the bottom of the file, add a section describing the share.
The section name (dos_share here) is the name of the share
and will be passed to the net utility in DOS later.
[dos_share]
comment = good stuff
path = /home/user/dosshare
browseable = yes
read only = no
guest ok = yes
create mask = 0777
directory mask = 0777
force user = user
In force user = user, user is your username
on the host. (I happen to always name myself user.) The
path is of course the directory on the host where the
shared files will be located. Create it.
After applying these changes, restart Samba
(sudo systemctl restart smbd) and verify its status is OK
(sudo systemctl status smbd).
With that out of the way, and the prerequisites from the other
section met, we can start installing the DOS software. Launch
qemu-system-i386 with the harddisk image and the two floppy
images, passing the correct network card model (pcnet):
qemu-system-i386 -m 8m -fda disk1.img -fdb disk2.img -hda hd.img \
-net nic,model=pcnet -net user -monitor stdio
-monitor stdio is a convenience that starts a ‘qemu
shell’ where you can enter commands such as
change floppy0 image_file.img, eject floppy0,
and system_reset while the guest is running. Interestingly,
qemu also supports rendering the VGA text screen directly in your
terminal using ncurses, and when you do this, you can assign the monitor
to a socket and connect to it with socat. This requires qemu to have
been built with ncurses support. Using the ncurses display has the
advantage of being able to copy from the VGA screen to the host
clipboard. If your terminal’s colour scheme makes some DOS screens
unreadable, you can change the terminal colours using ANSI escape codes
to set them to the standard CGA palette, like
printf '\e]4;5;#AA00AA\a' for setting colour 5 to magenta,
for example. (Provided your terminal emulator supports this.) A function
that sets all 16 CGA colours can be found in the util.sh
script that’s in the archive that I will attach below.
qemu-system-i386 -m 8m -fda disk1.img -fdb disk2.img -hda hd.img -net nic,model=pcnet \
-net user -display curses -monitor unix:/tmp/qemu.sock,server,nowait
socat - UNIX-CONNECT:/tmp/qemu.sock
Now that we’re in DOS, we can start the MNC setup utility.
A:
SETUP
Install the Network Client files in C:\NET (the
default). When prompted to pick an adapter, select
*Network adapter not shown on list below ....
Then specify the path where you put OEMSETUP.INF and
PCNTND.DOS before (C:\PCNET).
It will find the Advanced Micro Devices PCNET family
adapter. Install it. I just accepted when it asked me if I’d like to
‘setup for best performance’. Then enter your username. This can be
anything and doesn’t have to match the username on the host side. On the
following screen, select Change Setup Options.
Change Change Redir Options to
Use the Basic Redirector.
Go back to the previous screen, select
Change Network Configuration, and there, add the TCP/IP
protocol (Add Protocol ->
Microsoft TCP/IP). Your
Installed Network Adapter(s) and Protocol(s) should end up
looking like this.
Then go back to the previous screen and select
The listed options are correct. It will ask you for the
OEM Driver Disk, which at this point is B:\
(disk2.img). This concludes the MNC installer. Go to your
qemu monitor, enter eject floppy0 and
eject floppy1, then back to DOS, and hit ENTER to reboot.
On startup, some network-related things will be printed, after which you
are asked for your username. Confirm the one you’ve entered before, then
enter an empty password. When asked if you want to create a
password-list file, enter Y, and confirm your
empty password. After this, MNC’s initial setup is completed.
Open your LMHOSTS file
(EDIT C:\NET\LMHOSTS) and add an entry for the
netbios name that you’ve set in your Samba
configuration:
10.0.2.2 ELSEWHERE #PRE #NOFNR
10.0.2.2 is the IP address by which the host is reachable
from the guest. It’s a qemu default. Reboot the quest (by entering
system_reset in the qemu monitor). Apparently the
LMHOSTS entry is required to be present at boot time.
Now you can mount your share.
net use /PERSISTENT:NO z: \\ELSEWHERE\dos_share
(net has already been added to the path.) I’m using
/PERSISTENT:NO because I’ve experienced some hiccups when
mounting the share in persistent mode. In case you do mount a persistent
share and want to remove it: net use z: /DELETE. The same
can be achieved by wiping C:\NET\CONNECT.DAT, where the
shares are persisted in a binary format. Anyway, now you can edit files
on the host and see the changes reflected in DOS instantly, and vice
versa.
There’s something else left to do though. We need to free up some
conventional memory (i.e. the first 640K of RAM), as all the network
stuff that’s being loaded on startup now uses quite a bit of it. We’ll
get rid of NWLINK, as we don’t need IPX, and we’ll move
some things to high memory. I’ll add the files we’re modifying
(AUTOEXEC.BAT, CONFIG.SYS, and
NET\PROTOCOL.INI) to the archive I’ll attach below.
Open C:\NET\PROTOCOL.INI and remove these lines:
transport=ms$nwlink,MS$NWLINK
lana0=ms$pcntn3,1,ms$nwlink
Change the lana entries in [network.setup]
so you have
lana0=ms$pcntn3,1,ms$ndishlp
lana1=ms$pcntn3,1,tcpip
Then add the [PKTDRV] section.
[PKTDRV]
DriverName=PKTDRV$
BINDINGS=MS$PCNTN3
INTVEC=0x60
CHAINVEC=0x68
That’s it for this file. Let’s move on to CONFIG.SYS.
Change it so it contains the following.
DEVICE=C:\DOS\SETVER.EXE
DEVICE=C:\DOS\HIMEM.SYS
DEVICE=C:\DOS\EMM386.EXE NOEMS
DOS=HIGH,UMB
FILES=30
BUFFERS=15,0
DEVICEHIGH=C:\NET\PROTMAN.DOS /I:C:\NET
DEVICEHIGH=C:\NET\PCNTND.DOS
DEVICEHIGH=C:\NET\DIS_PKT.DOS
DEVICEHIGH=C:\NET\NEMM.DOS
DEVICEHIGH=C:\NET\TCPDRV.DOS
DEVICEHIGH=C:\NET\ifshlp.sys
LASTDRIVE=Z
Now, let’s edit AUTOEXEC.BAT. Remove these lines:
C:\NET\nwlink
C:\NET\umb.com
C:\NET\nmtsr.exe
C:\NET\emsbfr.exe
C:\NET\net start
Lastly, we add a line to mount our share on startup (if desired), so
the whole of AUTOEXEC.BAT ends up looking like this.
@ECHO OFF
PROMPT $p$g
PATH C:\NET;C:\DOS
SET TEMP=C:\DOS
C:\NET\net initialize
C:\NET\netbind.com
C:\NET\tcptsr.exe
C:\NET\tinyrfc.exe
NET USE /YES /PERSISTENT:NO Z: \\ELSEWHERE\dos_share
Now we have our share ready every time the DOS VM boots up, and
MEM reveals that our Total under 1 MB of free
memory is 563K, which is fair, I guess.
Oh, and here’s the archive I’ve mentioned, containing the required files for DOS, and the configuration files we’ve changed.
dos-smb-share.tar.bz2 (1.1M)
That’s all, folks. Happy DOSing!
–hekliet, 2026-06-24
[^1] Hansen, U. (2007). Networking FreeDOS - NDIS driver installation (W. Spiegl, Mod., 2022). Retrieved from https://home.mnet-online.de/willybilly/fdhelp-109/en/hhstndrd/network/ndis_ins.htm