Skip to content

Commit a7f21f2

Browse files
authored
Merge pull request #36 from fragglet/modularize-branch
Merge modularize-branch
2 parents 3b1055f + 3146e50 commit a7f21f2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+870
-341
lines changed

.github/workflows/go.yml

+3
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ jobs:
5252
cd artifacts
5353
go build -tags nopcap -v ../ipxbox.go
5454
go build -tags nopcap -v ../standalone/ipxbox_uplink.go
55+
go build -tags nopcap -v ../standalone/standalone_ipxpkt.go
56+
go build -tags nopcap -v ../standalone/standalone_pptp.go
57+
go build -tags nopcap -v ../standalone/standalone_qproxy.go
5558
env:
5659
GOARCH: ${{ matrix.goarch }}
5760
GOOS: ${{ matrix.goos }}

.gitignore

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
*.exe
2+
ipxbox
3+
ipxbox_uplink
4+
standalone_ipxpkt
5+
standalone_pptp
6+
standalone_qproxy

.lvimrc

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
" Local vimrc configuration file. Install the localvimrc.vim vim script.
2-
setlocal tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab cindent
2+
setlocal tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab smartindent nocindent
33
if &ft == "markdown"
44
setlocal softtabstop=4 shiftwidth=4 expandtab smartindent nocindent
55
endif

BRIDGE-HOWTO.md

+93-33
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,13 @@ a lot of damage you can do with the IPX protocol nowadays but there's still the
1414
possibility that if you use this on a public server, you might be exposing
1515
something on your network that you don't intend to.
1616

17-
There are two ways to set things up: `ipxbox` can either create a TAP device
18-
(use `--enable_tap`) or use `libpcap` to connect to a real Ethernet device.
19-
If you don't know what this means, you'll want to use the `libpcap` approach.
17+
There are two ways to set things up: `ipxbox` can either create a
18+
[TAP device](https://en.wikipedia.org/wiki/TUN/TAP) or use
19+
[`libpcap`](https://en.wikipedia.org/wiki/Pcap)
20+
to connect to a real Ethernet device. If you don't know what this means,
21+
you'll want to use the `libpcap` approach.
22+
23+
## Bridging with libpcap
2024

2125
Find out which Ethernet interface (network card) you want to use by using the
2226
Linux `ifconfig` command. Usually the interface will be named something like
@@ -29,9 +33,9 @@ sudo setcap cap_net_raw,cap_net_admin=eip ./ipxbox
2933
```
3034
On other systems (BSD, etc.) only the `root` user can access raw sockets.
3135

32-
Next run `ipxbox` with the `--pcap_device` argument, eg.
36+
Next run `ipxbox` with the `--bridge` argument, eg.
3337
```
34-
./ipxbox --port=10000 --pcap_device=eth0
38+
./ipxbox --port=10000 --bridge=pcap:eth0
3539
```
3640
If working correctly, clients connecting to the server will now be bridged to
3741
`eth0`. You can test this using `tcpdump` to listen for IPX packets and
@@ -47,6 +51,39 @@ listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
4751
05:08:48.888311 IPX 00000000.02:cf:0d:86:54:e5.0002 > 00000000.02:ff:ff:ff:00:00.0002: ipx-#2 0
4852
```
4953

54+
## Using a TAP device
55+
56+
To use TAP instead of pcap, specify `--bridge=tap` instead. For example:
57+
```
58+
./ipxbox --bridge=tap
59+
```
60+
creates a new network device while the server is running:
61+
```
62+
$ ifconfig -a
63+
tap0: flags=4098<BROADCAST,MULTICAST> mtu 1500
64+
ether 9e:db:a8:4b:d2:19 txqueuelen 1000 (Ethernet)
65+
RX packets 0 bytes 0 (0.0 B)
66+
RX errors 0 dropped 0 overruns 0 frame 0
67+
TX packets 0 bytes 0 (0.0 B)
68+
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
69+
```
70+
Note that the TAP device will be down by default and you will need to bring
71+
it up yourself with `ifconfig tap0 up`.
72+
73+
You can also specify the name; for example:
74+
```
75+
./ipxbox --bridge=tap:blerg
76+
```
77+
produces:
78+
```
79+
$ ifconfig -a
80+
blerg: flags=4098<BROADCAST,MULTICAST> mtu 1500
81+
ether 16:91:8d:c6:d1:4c txqueuelen 1000 (Ethernet)
82+
RX packets 0 bytes 0 (0.0 B)
83+
RX errors 0 dropped 0 overruns 0 frame 0
84+
TX packets 0 bytes 0 (0.0 B)
85+
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
86+
```
5087
## Configuring frame type
5188

5289
After following the above instructions you might find problems getting a
@@ -69,7 +106,7 @@ the first thing to check.
69106
format can be changed by using the `--ethernet_framing` command line flag.
70107
For example:
71108
```
72-
./ipxbox --port=10000 --pcap_device=eth0 --ethernet_framing=eth-ii
109+
./ipxbox --port=10000 --bridge=pcap:eth0 --ethernet_framing=eth-ii
73110
```
74111

75112
| `--ethernet_framing` value | Description | Notes |
@@ -151,37 +188,45 @@ problems you can disable autodetection and manually specify it.
151188
| `snap` | Ethernet 802.2 SNAP | 802.3 with 802.2 LLC and SNAP headers |
152189
| `eth-ii` | Ethernet II | Ethernet II |
153190

154-
## Advanced topic: TCP/IP over IPX
191+
## Advanced topic: TCP/IP over IPX (ipxpkt)
155192

156193
Much DOS software that communicates over the network (particularly using the
157194
TCP/IP protocol stack used on the Internet) uses the
158195
[packet driver](https://en.wikipedia.org/wiki/PC/TCP_Packet_Driver) interface.
159196
There are packet drivers available for most network cards, providing a
160197
standard interface for sending and receiving data over the network.
161-
162198
Some forks of DOSbox can emulate the Novell NE2000 card, allowing such
163199
software to be used. However, vanilla DOSbox at the time of writing does not
164200
include this feature. Furthermore, it typically requires granting DOSbox
165201
special permission to be able to send and receive raw network packets.
166-
The [`ipxpkt.com`](ipxpkt/driver/) driver is a packet driver that tunnels an
167-
Ethernet link over IPX packets, and ipxbox includes support for its protocol.
168-
This allows DOSbox users to use packet driver-based software.
202+
203+
The [`ipxpkt.com`](module/ipxpkt/driver/) driver is a packet driver that
204+
tunnels an Ethernet link over IPX packets, and ipxbox includes support for its
205+
protocol. This allows you to use packet driver-based software from within
206+
vanilla DOSbox; you can [see a demo video
207+
here](https://www.youtube.com/watch?v=5VeVaFbORhI).
169208

170209
**First, a word of warning**: the DOSBox IPX protocol is completely insecure.
171210
There's no encryption or authentication supported, and enabling this feature
172-
gives a potential backdoor into the network where the ipxbox server is running.
173-
If you don't understand the implications of this, don't enable this feature
174-
on a public-facing ipxbox server.
211+
gives a backdoor into the network where the ipxbox server is running. If you
212+
don't understand the implications of this, don't enable this feature on a
213+
public-facing ipxbox server.
175214

176215
To use this feature:
177216

178-
1. First set up an IPX bridge by following the instructions from the previous
179-
section.
217+
1. Install the [`libslirp-helper`](https://packages.debian.org/sid/libslirp-helper)
218+
package (on Debian; it is available on other Linux distros too).
219+
220+
- libslirp provides a connection to a simulated network without
221+
requiring any special permissions. Alternatively, you can bridge the
222+
ipxpkt packets to a real, physical network. Follow the instructions
223+
from the previous section about setting up an IPX bridge, but use the
224+
`--ipxpkt_bridge` flag instead of `--bridge`.
180225

181226
2. Read the warning in the paragraph above this list. Then add
182227
`--enable_ipxpkt` to the ipxbox command line. For example:
183228
```
184-
./ipxbox --port=10000 --pcap_device=eth0 --enable_ipxpkt
229+
./ipxbox --port=10000 --enable_ipxpkt
185230
```
186231
3. Start a DOSbox client and connect to the server as normal. Make sure to
187232
mount a directory containing the [`ipxpkt.com`](ipxpkt/driver/) driver.
@@ -204,8 +249,9 @@ My Ethernet address is 02:57:04:31:68:FA
204249
C:\>
205250
```
206251
5. Test the connection is working correctly by trying some software that uses
207-
the packet driver interface. The [mTCP stack](http://www.brutman.com/mTCP/)
208-
makes for a good first step. For example:
252+
the packet driver interface (but don't use `ping` because it won't work in
253+
Slirp). The [mTCP stack](http://www.brutman.com/mTCP/) makes for a good first
254+
step. For example:
209255
```
210256
C:\>set mtcpcfg=c:\mtcp\mtcp.cfg
211257
C:\>dhcp
@@ -220,26 +266,40 @@ DHCP request sent, attempt 1: Offer received, Acknowledged
220266
221267
Good news everyone!
222268
223-
IPADDR 192.168.128.45
224-
NETMASK 255.255.0.0
225-
GATEWAY 192.168.60.1
226-
NAMESERVER 8.8.8.8
269+
IPADDR 10.0.2.15
270+
NETMASK 255.255.255.0
271+
GATEWAY 10.0.2.2
272+
NAMESERVER 10.0.2.3
227273
LEASE_TIME 86400 seconds
228274
229275
Settings written to 'c:\mtcp\mtcp.cfg'
230276
231-
C:\>ping 8.8.8.8
277+
C:\>ftp ftp.freebsd.org
232278
233-
mTCP Ping by M Brutman ([email protected]) (C)opyright 2009-2020
234-
Version: Mar 7 2020
279+
mTCP FTP by M Brutman ([email protected]) (C)opyright 2008-2025
280+
Version: Jan 10 2025
281+
282+
FTP server resolved in 0.00 seconds
283+
284+
Opening control connection to 96.47.72.116:21 with local port 1914
285+
Connected
235286
236-
ICMP Packet payload is 32 bytes.
287+
220 This is ftp0.nyi.freebsd.org - hosted at NYI.net.
288+
Userid: anonymous
289+
331 Please specify the password.
290+
Password:
291+
230-
292+
230-This is ftp0.nyi.FreeBSD.org, graciously hosted by
293+
230-365 Data Centers - 365DataCenters.com
294+
230-
295+
230-FreeBSD files can be found in the /pub/FreeBSD directory.
296+
230-
297+
230 Login successful.
237298
238-
Packet sequence number 0 received in 45.90 ms, ttl=114
239-
Packet sequence number 1 received in 44.20 ms, ttl=114
240-
Packet sequence number 2 received in 41.65 ms, ttl=114
241-
Packet sequence number 3 received in 54.40 ms, ttl=114
299+
Setting the server file transfer mode to BIN
300+
200 Switching to Binary mode.
301+
File transfer mode set to BIN.
242302
243-
Packets sent: 4, Replies received: 4, Replies lost: 0
244-
Average time for a reply: 46.53 ms (not counting lost packets)
303+
--> quit
304+
221 Goodbye.
245305
```

PPTP-HOWTO.md

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ Me. If you have a retro computer running one of these operating systems,
55
you can therefore use this feature to connect to a server and play with
66
DOSbox clients (or others using PPTP as well).
77

8+
You can [see a demo video here](https://www.youtube.com/watch?v=ut37z6EE5Hc).
9+
810
## Client setup
911

1012
First check that the `ipxbox` server you're connecting to has PPTP

client/dosbox/client.go

+22-9
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ import (
1919
const maxConnectAttempts = 5
2020

2121
var (
22-
_ = (network.Node)(&client{})
22+
_ = (network.Node)(&connection{})
23+
_ = (network.Network)(&Client{})
2324
)
2425

2526
type connectFailure struct {
@@ -34,26 +35,26 @@ func (cf *connectFailure) Unwrap() error {
3435
return os.ErrDeadlineExceeded
3536
}
3637

37-
type client struct {
38+
type connection struct {
3839
inner ipx.ReadWriteCloser
3940
rxpipe ipx.ReadWriteCloser
4041
addr ipx.Addr
4142
}
4243

43-
func (c *client) ReadPacket(ctx context.Context) (*ipx.Packet, error) {
44+
func (c *connection) ReadPacket(ctx context.Context) (*ipx.Packet, error) {
4445
return c.rxpipe.ReadPacket(ctx)
4546
}
4647

47-
func (c *client) WritePacket(packet *ipx.Packet) error {
48+
func (c *connection) WritePacket(packet *ipx.Packet) error {
4849
return c.inner.WritePacket(packet)
4950
}
5051

51-
func (c *client) Close() error {
52+
func (c *connection) Close() error {
5253
c.rxpipe.Close()
5354
return c.inner.Close()
5455
}
5556

56-
func (c *client) GetProperty(x interface{}) bool {
57+
func (c *connection) GetProperty(x interface{}) bool {
5758
switch x.(type) {
5859
case *ipx.Addr:
5960
*x.(*ipx.Addr) = c.addr
@@ -63,7 +64,7 @@ func (c *client) GetProperty(x interface{}) bool {
6364
}
6465
}
6566

66-
func (c *client) sendPingReply(addr *ipx.Addr) {
67+
func (c *connection) sendPingReply(addr *ipx.Addr) {
6768
c.inner.WritePacket(&ipx.Packet{
6869
Header: ipx.Header{
6970
Dest: ipx.HeaderAddr{
@@ -82,7 +83,7 @@ func isPing(hdr *ipx.Header) bool {
8283
return hdr.Dest.Addr == ipx.AddrBroadcast && hdr.Dest.Socket == 2
8384
}
8485

85-
func (c *client) recvLoop(ctx context.Context) {
86+
func (c *connection) recvLoop(ctx context.Context) {
8687
for {
8788
packet, err := c.inner.ReadPacket(ctx)
8889
if errors.Is(err, io.ErrClosedPipe) {
@@ -156,7 +157,7 @@ func Dial(ctx context.Context, addr string) (network.Node, error) {
156157
if err != nil {
157158
return nil, err
158159
}
159-
c := &client{
160+
c := &connection{
160161
inner: udp,
161162
rxpipe: pipe.New(),
162163
}
@@ -167,3 +168,15 @@ func Dial(ctx context.Context, addr string) (network.Node, error) {
167168
go c.recvLoop(context.Background())
168169
return c, nil
169170
}
171+
172+
// Client is an implementation of network.Network that creates a new connection
173+
// to a remote dosbox server for every new node created.
174+
type Client struct {
175+
// TODO: It's bad practice to save a context in a struct:
176+
Context context.Context
177+
Address string
178+
}
179+
180+
func (c *Client) NewNode() (network.Node, error) {
181+
return Dial(c.Context, c.Address)
182+
}

0 commit comments

Comments
 (0)