forked from danderson/pixiecore
/
pixiecore.go
110 lines (94 loc) · 3.29 KB
/
pixiecore.go
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
package main
import (
"errors"
"flag"
"fmt"
"log"
"os"
"strings"
"time"
"github.com/danderson/pixiecore/tftp"
)
//go:generate go-bindata -o pxelinux_autogen.go -prefix=pxelinux -ignore=README.md pxelinux
var (
// I'm sort of giving you the option to change these ports here,
// but all of them except the HTTP port are hardcoded in the PXE
// option ROM, so it's pretty pointless unless you'd playing
// packet rewriting tricks or doing simulations with packet
// generators.
portDHCP = flag.Int("port-dhcp", 67, "Port to listen on for DHCP requests")
portPXE = flag.Int("port-pxe", 4011, "Port to listen on for PXE requests")
portTFTP = flag.Int("port-tftp", 69, "Port to listen on for TFTP requests")
portHTTP = flag.Int("port-http", 70, "Port to listen on for HTTP requests")
listenAddr = flag.String("listen-addr", "", "Address to listen on (default all)")
apiServer = flag.String("api", "", "Path to the boot API server")
apiTimeout = flag.Duration("api-timeout", 5*time.Second, "Timeout on boot API server requests")
kernelFile = flag.String("kernel", "", "Path to the linux kernel file to boot")
initrdFile = flag.String("initrd", "", "Comma-separated list of initrds to pass to the kernel")
kernelCmdline = flag.String("cmdline", "", "Additional arguments for the kernel commandline")
debug = flag.Bool("debug", false, "Log more things that aren't directly related to booting a recognized client")
)
func pickBooter() (Booter, error) {
switch {
case *apiServer != "":
if *kernelFile != "" {
return nil, errors.New("cannot provide -kernel with -api")
}
if *initrdFile != "" {
return nil, errors.New("cannot provide -initrd with -api")
}
if *kernelCmdline != "" {
return nil, errors.New("cannot provide -cmdline with -api")
}
log.Printf("Starting Pixiecore in API mode, with server %s", *apiServer)
return RemoteBooter(*apiServer, *apiTimeout)
case *kernelFile != "":
if *apiServer != "" {
return nil, errors.New("cannot provide -api with -kernel")
}
if *initrdFile == "" {
return nil, errors.New("must provide -initrd with -kernel")
}
log.Printf("Starting Pixiecore in static mode")
return StaticBooter(*kernelFile, strings.Split(*initrdFile, ","), *kernelCmdline), nil
default:
return nil, errors.New("must specify either -api, or -kernel/-initrd")
}
}
func main() {
flag.Parse()
booter, err := pickBooter()
if err != nil {
flag.Usage()
fmt.Fprintf(os.Stderr, "\nERROR: %s\n", err)
os.Exit(1)
}
pxelinux, err := Asset("lpxelinux.0")
if err != nil {
fmt.Println(err)
os.Exit(1)
}
ldlinux, err := Asset("ldlinux.c32")
if err != nil {
fmt.Println(err)
os.Exit(1)
}
go func() {
addrDHCP := fmt.Sprintf("%s:%d", *listenAddr, *portDHCP)
log.Fatalln(ServeProxyDHCP(addrDHCP, booter))
}()
go func() {
addrPXE := fmt.Sprintf("%s:%d", *listenAddr, *portPXE)
log.Fatalln(ServePXE(addrPXE, *portHTTP))
}()
go func() {
addrTFTP := fmt.Sprintf("%s:%d", *listenAddr, *portTFTP)
tftp.Log = func(msg string, args ...interface{}) { Log("TFTP", msg, args...) }
tftp.Debug = func(msg string, args ...interface{}) { Debug("TFTP", msg, args...) }
log.Fatalln(tftp.ListenAndServe("udp4", addrTFTP, tftp.Blob(pxelinux)))
}()
go func() {
log.Fatalln(ServeHTTP(*listenAddr, *portHTTP, booter, ldlinux))
}()
RecordLogs(*debug)
}