-
Notifications
You must be signed in to change notification settings - Fork 196
Expand file tree
/
Copy pathpixicorev6.go
More file actions
102 lines (79 loc) · 2.2 KB
/
pixicorev6.go
File metadata and controls
102 lines (79 loc) · 2.2 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
package pixiecore
import (
"encoding/binary"
"fmt"
"net"
"time"
"go.universe.tf/netboot/dhcp6"
)
// ServerV6 boots machines using a Booter.
type ServerV6 struct {
Address string
Port string
Duid []byte
BootConfig dhcp6.BootConfiguration
PacketBuilder *dhcp6.PacketBuilder
AddressPool dhcp6.AddressPool
errs chan error
Log func(subsystem, msg string)
Debug func(subsystem, msg string)
}
// NewServerV6 returns a new ServerV6.
func NewServerV6() *ServerV6 {
ret := &ServerV6{
Port: "547",
}
return ret
}
// Serve listens for machines attempting to boot, and responds to
// their DHCPv6 requests.
func (s *ServerV6) Serve() error {
s.log("dhcp", "starting...")
dhcp, err := dhcp6.NewConn(s.Address, s.Port)
if err != nil {
return err
}
s.debug("dhcp", "new connection...")
// 5 buffer slots, one for each goroutine, plus one for
// Shutdown(). We only ever pull the first error out, but shutdown
// will likely generate some spurious errors from the other
// goroutines, and we want them to be able to dump them without
// blocking.
s.errs = make(chan error, 6)
s.setDUID(dhcp.SourceHardwareAddress())
go func() { s.errs <- s.serveDHCP(dhcp) }()
// Wait for either a fatal error, or Shutdown().
err = <-s.errs
dhcp.Close()
s.log("dhcp", "stopped...")
return err
}
// Shutdown causes Serve() to exit, cleaning up behind itself.
func (s *ServerV6) Shutdown() {
select {
case s.errs <- nil:
default:
}
}
func (s *ServerV6) log(subsystem, format string, args ...interface{}) {
if s.Log == nil {
return
}
s.Log(subsystem, fmt.Sprintf(format, args...))
}
func (s *ServerV6) debug(subsystem, format string, args ...interface{}) {
if s.Debug == nil {
return
}
s.Debug(subsystem, fmt.Sprintf(format, args...))
}
func (s *ServerV6) setDUID(addr net.HardwareAddr) {
duid := make([]byte, len(addr)+8) // see rfc3315, section 9.2, DUID-LT
copy(duid[0:], []byte{0, 1}) //fixed, x0001
copy(duid[2:], []byte{0, 1}) //hw type ethernet, x0001
utcLoc, _ := time.LoadLocation("UTC")
sinceJanFirst2000 := time.Since(time.Date(2000, time.January, 1, 0, 0, 0, 0, utcLoc))
binary.BigEndian.PutUint32(duid[4:], uint32(sinceJanFirst2000.Seconds()))
copy(duid[8:], addr)
s.Duid = duid
}