Starting DHCP packets.
This commit is contained in:
15
dhcp/BUILD.bazel
Normal file
15
dhcp/BUILD.bazel
Normal file
@@ -0,0 +1,15 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "dhcp",
|
||||
srcs = [
|
||||
"options.go",
|
||||
"packet.go",
|
||||
],
|
||||
importpath = "git.wntrmute.dev/kyle/kdhcp/dhcp",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//log",
|
||||
"@com_github_davecgh_go_spew//spew",
|
||||
],
|
||||
)
|
||||
46
dhcp/options.go
Normal file
46
dhcp/options.go
Normal file
@@ -0,0 +1,46 @@
|
||||
package dhcp
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
)
|
||||
|
||||
type OptionTag uint8
|
||||
|
||||
type Option func(req *BootRequest, r io.Reader) error
|
||||
|
||||
const (
|
||||
OptionTagPadding OptionTag = 0
|
||||
OptionTagHostName = 12
|
||||
OptionTagMessageType = 53
|
||||
OptionTagParameterRequestList = 55
|
||||
OptionTagEnd = 255
|
||||
)
|
||||
|
||||
var optionRegistry = map[OptionTag]Option{
|
||||
OptionTagPadding: OptionTag,
|
||||
OptionTagHostName: OptionHostName,
|
||||
OptionTagMessageType: OptionMessageType,
|
||||
OptionTagParameterRequestList: OptionParameterRequestList,
|
||||
OptionTagEnd: OptionEnd,
|
||||
}
|
||||
|
||||
func OptionPad(req *BootRequest, r io.Reader) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func OptionHostName(req *BootRequest, r io.Reader) error {
|
||||
return errors.New("dhcp: option not implemented yet")
|
||||
}
|
||||
|
||||
func OptionMessageType(req *BootRequest, r io.Reader) error {
|
||||
return errors.New("dhcp: option not implemented yet")
|
||||
}
|
||||
|
||||
func OptionParameterRequestList(req *BootRequest, r io.Reader) error {
|
||||
return errors.New("dhcp: option not implemented yet")
|
||||
}
|
||||
|
||||
func OptionEnd(req *BootRequest, r io.Reader) error {
|
||||
return errors.New("dhcp: option not implemented yet")
|
||||
}
|
||||
143
dhcp/packet.go
Normal file
143
dhcp/packet.go
Normal file
@@ -0,0 +1,143 @@
|
||||
package dhcp
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
"git.wntrmute.dev/kyle/kdhcp/log"
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
)
|
||||
|
||||
const (
|
||||
maxHardwareAddrLen = 16
|
||||
maxServerName = 64
|
||||
maxFileName = 128
|
||||
)
|
||||
|
||||
var anyAddr = net.IP([]byte{0, 0, 0, 0})
|
||||
|
||||
func formatMAC(mac []byte) string {
|
||||
s := []string{}
|
||||
for i := 0; i < len(mac); i++ {
|
||||
s = append(s, fmt.Sprintf("%0x", mac[i:i+1]))
|
||||
}
|
||||
|
||||
return strings.Join(s, ":")
|
||||
}
|
||||
|
||||
type BootRequest struct {
|
||||
MessageType uint8
|
||||
HardwareType uint8
|
||||
HardwareAddress []byte
|
||||
Hops uint8
|
||||
TransactionID uint32
|
||||
SecondsElapsed uint16
|
||||
Flags uint16
|
||||
ServerName string
|
||||
FileName string
|
||||
|
||||
ClientIP net.IP
|
||||
YourIP net.IP
|
||||
NextIP net.IP
|
||||
RelayIP net.IP
|
||||
|
||||
DHCPType uint8 // option 53
|
||||
HostName string // option 12
|
||||
ParameterRequests []string
|
||||
}
|
||||
|
||||
func (req *BootRequest) Read(packet []byte) error {
|
||||
buf := bytes.NewBuffer(packet)
|
||||
read := func(v any) error {
|
||||
return binary.Read(buf, binary.BigEndian, v)
|
||||
}
|
||||
|
||||
if err := read(&req.MessageType); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := read(&req.HardwareType); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var hwaLength uint8
|
||||
if err := read(&hwaLength); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := read(&req.Hops); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := read(&req.TransactionID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := read(&req.SecondsElapsed); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := read(&req.Flags); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
req.ClientIP = anyAddr[:]
|
||||
if _, err := buf.Read(req.ClientIP); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
req.YourIP = anyAddr[:]
|
||||
if _, err := buf.Read(req.YourIP); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
req.NextIP = anyAddr[:]
|
||||
if _, err := buf.Read(req.NextIP); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
req.RelayIP = anyAddr[:]
|
||||
if _, err := buf.Read(req.RelayIP); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
req.HardwareAddress = make([]byte, int(hwaLength))
|
||||
if _, err := buf.Read(req.HardwareAddress); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
hwaPad := make([]byte, maxHardwareAddrLen-hwaLength)
|
||||
if _, err := buf.Read(hwaPad); err != nil {
|
||||
return err
|
||||
}
|
||||
log.Debugf("padding: %x", hwaPad)
|
||||
|
||||
tempBuf := make([]byte, maxServerName)
|
||||
if _, err := buf.Read(tempBuf); err != nil {
|
||||
return err
|
||||
}
|
||||
req.ServerName = string(bytes.Trim(tempBuf, "\x00"))
|
||||
|
||||
tempBuf = make([]byte, maxFileName)
|
||||
if _, err := buf.Read(tempBuf); err != nil {
|
||||
return err
|
||||
}
|
||||
req.FileName = string(bytes.Trim(tempBuf, "\x00"))
|
||||
|
||||
spew.Dump(*req)
|
||||
return nil
|
||||
}
|
||||
|
||||
func ReadRequest(pkt []byte) (*BootRequest, error) {
|
||||
req := &BootRequest{}
|
||||
err := req.Read(pkt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
log.Debugf("dhcp: BOOTP request with txid %d for %s", req.TransactionID, formatMAC(req.HardwareAddress))
|
||||
return req, nil
|
||||
}
|
||||
Reference in New Issue
Block a user