dhcp reads done, moving on to offers

This commit is contained in:
2023-05-09 07:28:54 +00:00
parent 6ba2bf3911
commit f66fbc0f6c
20 changed files with 196 additions and 58 deletions

View File

@@ -9,5 +9,5 @@ go_library(
],
importpath = "git.wntrmute.dev/kyle/kdhcp/dhcp",
visibility = ["//visibility:public"],
deps = ["@dev_wntrmute_git_kyle_goutils//syslog"],
deps = ["@dev_wntrmute_git_kyle_goutils//log"],
)

View File

@@ -33,6 +33,8 @@ const (
OptionTagNBScope OptionTag = 47
OptionTagMessageType OptionTag = 53
OptionTagParameterRequestList OptionTag = 55
OptionTagDHCPMaxMessageSize OptionTag = 57
OptionTagClientID OptionTag = 61
OptionTagDomainSearch OptionTag = 119
OptionTagClasslessStaticRoute OptionTag = 121
OptionTagEnd OptionTag = 255
@@ -53,6 +55,8 @@ var optionStrings = map[OptionTag]string{
OptionTagNBScope: "NetBIOS scope",
OptionTagMessageType: "message type",
OptionTagParameterRequestList: "parameter request list",
OptionTagDHCPMaxMessageSize: "DHCP max message size",
OptionTagClientID: "client ID",
OptionTagDomainSearch: "search domain",
OptionTagClasslessStaticRoute: "classless static route",
OptionTagEnd: "end",

View File

@@ -8,7 +8,7 @@ import (
"net"
"strings"
log "git.wntrmute.dev/kyle/goutils/syslog"
log "git.wntrmute.dev/kyle/goutils/log"
)
const (
@@ -46,6 +46,7 @@ type BootRequest struct {
DHCPType DHCPMessageType // option 53
HostName string // option 12
ClientID string // option 61
ParameterRequests []OptionTag
endOptions bool
}

View File

@@ -6,7 +6,7 @@ import (
"fmt"
"io"
log "git.wntrmute.dev/kyle/goutils/syslog"
log "git.wntrmute.dev/kyle/goutils/log"
)
var optionRegistry = map[OptionTag]Option{
@@ -14,6 +14,7 @@ var optionRegistry = map[OptionTag]Option{
OptionTagHostName: OptionHostName,
OptionTagMessageType: OptionMessageType,
OptionTagParameterRequestList: OptionParameterRequestList,
OptionTagClientID: OptionClientID,
OptionTagEnd: OptionEnd,
}
@@ -22,6 +23,19 @@ func OptionPad(req *BootRequest, r io.Reader) error {
return nil
}
func getOptionLength(r io.Reader) (int, error) {
var length uint8
read := newPacketReaderFunc(r)
if err := read(&length); err != nil {
return -1, fmt.Errorf("dhcp: reading option length for DHCP Message Type")
} else if length == 0 {
return -1, errors.New("dhcp: read option length 0, but expected option length for DHCP Host Name is >= 1")
}
return int(length), nil
}
// OptionHostName reads a DHCP host name option.
//
// 3.14. Host Name Option
@@ -33,13 +47,9 @@ func OptionPad(req *BootRequest, r io.Reader) error {
// The code for this option is 12, and its minimum length is 1.
func OptionHostName(req *BootRequest, r io.Reader) error {
read := newPacketReaderFunc(r)
var length uint8
if err := read(&length); err != nil {
return fmt.Errorf("dhcp: reading option length for DHCP Message Type")
} else if length == 0 {
return errors.New("dhcp: read option length 0, but expected option length for DHCP Host Name is >= 1")
length, err := getOptionLength(r)
if err != nil {
return err
}
hostName := make([]byte, int(length))
@@ -56,9 +66,8 @@ func OptionHostName(req *BootRequest, r io.Reader) error {
func OptionMessageType(req *BootRequest, r io.Reader) error {
read := newPacketReaderFunc(r)
var length uint8
if err := read(&length); err != nil {
return fmt.Errorf("dhcp: reading option length for DHCP Message Type")
if length, err := getOptionLength(r); err != nil {
return err
} else if length != 1 {
return fmt.Errorf("dhcp: read option length %d, but expected option length for DHCP Message Type is 1", length)
}
@@ -71,11 +80,9 @@ func OptionMessageType(req *BootRequest, r io.Reader) error {
}
func OptionParameterRequestList(req *BootRequest, r io.Reader) error {
read := newPacketReaderFunc(r)
var length uint8
if err := read(&length); err != nil {
return fmt.Errorf("dhcp: reading option length for DHCP Message Type")
length, err := getOptionLength(r)
if err != nil {
return err
} else if length == 0 {
return fmt.Errorf("dhcp: read option length %d, but expected option length for DHCP Parameter Request is >= 1", length)
}
@@ -96,6 +103,25 @@ func OptionParameterRequestList(req *BootRequest, r io.Reader) error {
return nil
}
func OptionClientID(req *BootRequest, r io.Reader) error {
length, err := getOptionLength(r)
if err != nil {
return err
} else if length == 0 {
return fmt.Errorf("dhcp: read option length %d, but expected option length for DHCP Parameter Request is >= 1", length)
}
var clientID = make([]byte, int(length))
if n, err := r.Read(clientID); err != nil {
return fmt.Errorf("dhcp: while reading client ID: %w", err)
} else if n != int(length) {
return fmt.Errorf("dhcp: only read %d bytes of client ID, expected %d bytes", n, length)
}
req.ClientID = string(clientID)
return nil
}
func OptionEnd(req *BootRequest, r io.Reader) error {
req.endOptions = true
return nil
@@ -108,7 +134,27 @@ func ReadOption(req *BootRequest, tag byte, r io.Reader) error {
return f(req, r)
}
return fmt.Errorf("dhcp: unknown/unhandled option %d", opt)
return readUnknownOption(req, tag, r)
}
func readUnknownOption(req *BootRequest, tag byte, r io.Reader) error {
length, err := getOptionLength(r)
if err != nil {
return err
} else if length == 0 {
log.Debugf("skipped option %d/%02x with length 0", tag, tag)
return nil
}
var data = make([]byte, length)
if n, err := r.Read(data); err != nil {
return fmt.Errorf("dhcp: while skipping unknown tag %d/%02x: %w", tag, tag, err)
} else if n != int(length) {
return fmt.Errorf("dhcp: only read %d bytes of unknown tag %d/%02x, expected %d bytes", n, tag, tag, length)
}
log.Infof("skipped unknown tag %d/%02x with data %0x", tag, tag, data)
return nil
}
const magicCookieLength = 4