-
Notifications
You must be signed in to change notification settings - Fork 14
Expand file tree
/
Copy pathipxbox.go
More file actions
122 lines (109 loc) · 3.75 KB
/
ipxbox.go
File metadata and controls
122 lines (109 loc) · 3.75 KB
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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// Package main implements a standalone DOSbox-IPX server.
package main
import (
"context"
"flag"
"log"
"os"
"github.com/fragglet/ipxbox/ipx"
"github.com/fragglet/ipxbox/logging"
"github.com/fragglet/ipxbox/module"
"github.com/fragglet/ipxbox/module/aggregate"
"github.com/fragglet/ipxbox/module/bridge"
"github.com/fragglet/ipxbox/module/ipxpkt"
"github.com/fragglet/ipxbox/module/pptp"
"github.com/fragglet/ipxbox/module/qproxy"
"github.com/fragglet/ipxbox/module/server"
"github.com/fragglet/ipxbox/network"
"github.com/fragglet/ipxbox/network/addressable"
"github.com/fragglet/ipxbox/network/filter"
"github.com/fragglet/ipxbox/network/ipxswitch"
"github.com/fragglet/ipxbox/network/stats"
"github.com/fragglet/ipxbox/network/tappable"
"github.com/fragglet/ipxbox/phys"
"github.com/google/gopacket/layers"
"github.com/google/gopacket/pcapgo"
)
var (
dumpPackets = flag.String("dump_packets", "", "Write packets to a .pcap file with the given name.")
allowNetBIOS = flag.Bool("allow_netbios", false, "If true, allow packets to be forwarded that may contain Windows file sharing (NetBIOS) packets.")
enableIpxpkt = flag.Bool("enable_ipxpkt", false, "If true, route encapsulated packets from the IPXPKT.COM driver to the physical network")
enablePPTP = flag.Bool("enable_pptp", false, "If true, run PPTP VPN server on TCP port 1723.")
)
func makePcapWriter() *pcapgo.Writer {
var f *os.File
// eg. `ipxbox --dump_packets /dev/stdout | tcpdump -nlr -`
if *dumpPackets == "-" {
f = os.Stdout
} else {
var err error
f, err = os.Create(*dumpPackets)
if err != nil {
log.Fatalf("failed to open pcap file for write: %v", err)
}
}
w := pcapgo.NewWriter(f)
w.WriteFileHeader(1500, layers.LinkTypeEthernet)
return w
}
func makeNetwork(ctx context.Context) (network.Network, network.Network) {
// We build the network up in layers, each layer adding an extra
// feature. This approach allows for modularity and separation of
// concerns, avoiding the complexity of a big monolithic system.
// This is best read in reverse order. Life of an rx packet:
// 1. Packet received from client; WritePacket() by server
// 2. Check source address matches client address (addressable)
// 3. Increment receive statistics (stats)
// 4. Drop packet if a NetBIOS packet (filter)
// 5. Fork incoming traffic to any network taps (tappable)
// 6. Forward to receive queue(s) of other clients (ipxswitch)
// Then back out the other way (tx):
// 1. Read packet from receive queue (ipxswitch)
// 2. No-op (tappable)
// 3. Filter NetBIOS packets (filter)
// 4. Increment transmit statistics (stats)
// 5. Check dest address matches client address (addressable)
// 5. ReadPacket() by server, and transmit to client.
var net network.Network
net = ipxswitch.New()
if *dumpPackets != "" {
tappableLayer := tappable.Wrap(net)
w := makePcapWriter()
sink := phys.NewPcapgoSink(w, phys.FramerEthernetII)
go ipx.CopyPackets(ctx, tappableLayer.NewTap(), sink)
net = tappableLayer
}
if !*allowNetBIOS {
net = filter.Wrap(net)
}
uplinkable := net
net = addressable.Wrap(net)
net = stats.Wrap(net)
return net, stats.Wrap(uplinkable)
}
func main() {
mainmod := aggregate.MakeModule(
module.Optional(ipxpkt.Module, enableIpxpkt),
module.Optional(pptp.Module, enablePPTP),
bridge.Module,
qproxy.Module,
server.Module,
)
mainmod.Initialize()
logspec := logging.RegisterFlag()
flag.Parse()
ctx := context.Background()
logger, err := logspec.MakeLogger()
if err != nil {
log.Fatalf("error initializing logging: %v", err)
}
net, uplinkable := makeNetwork(ctx)
err = mainmod.Start(ctx, &module.Parameters{
Network: net,
Uplinkable: uplinkable,
Logger: logger,
})
if err != nil {
log.Fatalf("server terminated with error: %v", err)
}
}