mirror of
https://github.com/danderson/netboot.git
synced 2025-08-07 15:17:15 +02:00
103 lines
2.2 KiB
Go
103 lines
2.2 KiB
Go
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
|
|
}
|