mirror of
https://github.com/soypat/lneto.git
synced 2026-09-01 12:29:05 +00:00
Error rewrites (#43)
* pcap: reuse Frame memory * slog: reduce heap allocations of addresses; also prevent heap alloc of dhcp options in pcap * dns: heapless improvement; add StackAsync buffer for more heapless operation; start thinking of errors * errors: begin standardise errors in lneto * errors: finish standardization of errors * fix merge issues * add more lneto errors to rest of package * format errors.go
This commit is contained in:
+12
-12
@@ -2,8 +2,6 @@ package dhcpv4
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log/slog"
|
||||
"math"
|
||||
@@ -80,13 +78,13 @@ func (c *Client) Reset() {
|
||||
|
||||
func (c *Client) BeginRequest(xid uint32, cfg RequestConfig) error {
|
||||
if len(cfg.Hostname) > 36 {
|
||||
return errors.New("requested hostname too long")
|
||||
return lneto.ErrInvalidConfig
|
||||
} else if c.state != StateInit && c.state != 0 {
|
||||
return errors.New("dhcp client must be closed/Init before new request")
|
||||
return lneto.ErrInvalidConfig
|
||||
} else if xid == 0 {
|
||||
return errors.New("zero xid")
|
||||
return lneto.ErrInvalidConfig
|
||||
} else if len(cfg.ClientID) > 32 {
|
||||
return errors.New("client ID too long")
|
||||
return lneto.ErrInvalidConfig
|
||||
}
|
||||
c.reset(xid)
|
||||
c.state = StateInit
|
||||
@@ -143,7 +141,7 @@ func (c *Client) Encapsulate(carrierData []byte, offsetToIP, offsetToFrame int)
|
||||
}
|
||||
opts := frm.OptionsPayload()
|
||||
if len(opts) < 255 {
|
||||
return 0, errors.New("too short packet for options")
|
||||
return 0, lneto.ErrShortBuffer
|
||||
}
|
||||
|
||||
var nextState ClientState
|
||||
@@ -181,7 +179,8 @@ func (c *Client) Encapsulate(carrierData []byte, offsetToIP, offsetToFrame int)
|
||||
nextState = StateRequesting
|
||||
|
||||
default:
|
||||
return 0, errors.New("unhandled state" + c.state.String())
|
||||
internal.LogAttrs(nil, slog.LevelError, "dhcpv4:unhandled-state", slog.String("state", c.state.String()))
|
||||
return 0, lneto.ErrBug
|
||||
}
|
||||
n, _ := EncodeOption(opts[numOpts:], OptClientIdentifier, c.clientID...)
|
||||
numOpts += n
|
||||
@@ -210,13 +209,13 @@ func (c *Client) Demux(carrierData []byte, frameOffset int) error {
|
||||
if err != nil {
|
||||
return err
|
||||
} else if frm.XID() != c.currentXID {
|
||||
return errors.New("dhcpv4 unexpected transaction ID")
|
||||
return lneto.ErrMismatch
|
||||
} else if frm.MagicCookie() != MagicCookie {
|
||||
return errors.New("dhcpv4 bad magic cookie")
|
||||
return lneto.ErrInvalidField
|
||||
}
|
||||
msgType := c.getMessageType(frm)
|
||||
if msgType == MsgNack {
|
||||
return errors.New("dhcp nack received")
|
||||
return lneto.ErrPacketDrop
|
||||
}
|
||||
|
||||
msgOK := msgType == MsgOffer || msgType == MsgAck
|
||||
@@ -243,7 +242,8 @@ func (c *Client) Demux(carrierData []byte, frameOffset int) error {
|
||||
c.state = StateBound
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("dhcpv4 unexpected state in recv %s", c.state.String())
|
||||
internal.LogAttrs(nil, slog.LevelError, "dhcpv4:unexpected-recv-state", slog.String("state", c.state.String()))
|
||||
return lneto.ErrBug
|
||||
}
|
||||
if frameOffset > 28 && c.svIPtos == 0 {
|
||||
ifrm, _ := ipv4.NewFrame(carrierData)
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
package dhcpv4
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"unsafe"
|
||||
|
||||
"github.com/soypat/lneto"
|
||||
)
|
||||
|
||||
//go:generate stringer -type=OptNum,Op,MessageType,ClientState -linecomment -output stringers.go
|
||||
@@ -52,9 +53,9 @@ func EncodeOption32(dst []byte, opt OptNum, v uint32) (int, error) {
|
||||
|
||||
func EncodeOption(dst []byte, opt OptNum, data ...byte) (int, error) {
|
||||
if len(data) > 255 {
|
||||
return 0, errors.New("DHCPv4 option data too long (>255)")
|
||||
return 0, lneto.ErrInvalidLengthField
|
||||
} else if len(dst) < 2+len(data) {
|
||||
return 0, errors.New("DHCP option buffer too short")
|
||||
return 0, lneto.ErrShortBuffer
|
||||
}
|
||||
_ = dst[2+len(data)]
|
||||
dst[0] = byte(opt)
|
||||
|
||||
+5
-13
@@ -2,7 +2,6 @@ package dhcpv4
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
|
||||
"github.com/soypat/lneto"
|
||||
)
|
||||
@@ -27,7 +26,7 @@ const (
|
||||
// An error is returned if the buffer size is smaller than 240.
|
||||
func NewFrame(buf []byte) (Frame, error) {
|
||||
if len(buf) < OptionsOffset {
|
||||
return Frame{}, errSmallFrame
|
||||
return Frame{}, lneto.ErrShortBuffer
|
||||
}
|
||||
return Frame{buf: buf}, nil
|
||||
}
|
||||
@@ -126,9 +125,9 @@ func (frm Frame) ForEachOption(fn func(off int, opt OptNum, data []byte) error)
|
||||
// Parse DHCP options.
|
||||
ptr := OptionsOffset
|
||||
if ptr > len(frm.buf) {
|
||||
return errSmallFrame
|
||||
return lneto.ErrShortBuffer
|
||||
} else if len(frm.buf[ptr:]) == 0 {
|
||||
return errNoOptions
|
||||
return lneto.ErrInvalidField
|
||||
}
|
||||
callback := fn != nil
|
||||
for ptr+1 < len(frm.buf) {
|
||||
@@ -141,7 +140,7 @@ func (frm Frame) ForEachOption(fn func(off int, opt OptNum, data []byte) error)
|
||||
}
|
||||
optlen := int(frm.buf[ptr+1])
|
||||
if ptr+2+optlen > len(frm.buf) {
|
||||
return errDHCPBadOption
|
||||
return lneto.ErrInvalidLengthField
|
||||
}
|
||||
if callback {
|
||||
optionData := frm.buf[ptr+2 : ptr+2+optlen]
|
||||
@@ -158,16 +157,9 @@ func (frm Frame) ForEachOption(fn func(off int, opt OptNum, data []byte) error)
|
||||
// Validation API.
|
||||
//
|
||||
|
||||
var (
|
||||
errSmallFrame = errors.New("DHCPv4: frame size <240")
|
||||
errDHCPBadOption = errors.New("DHCPv4: opt length exceeds payload")
|
||||
errNoOptions = errors.New("DHCPv4: no options")
|
||||
errOptionNotFit = errors.New("DHCPv4: options dont fit")
|
||||
)
|
||||
|
||||
func (frm Frame) ValidateSize(vld *lneto.Validator) {
|
||||
err := frm.ForEachOption(nil) // Does all necessary validation.
|
||||
if err != nil {
|
||||
vld.AddError(errDHCPBadOption)
|
||||
vld.AddError(lneto.ErrInvalidLengthField)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@ import (
|
||||
"github.com/soypat/lneto/internal"
|
||||
)
|
||||
|
||||
var errOptionNotFit = errors.New("DHCPv4: options dont fit")
|
||||
|
||||
type Server struct {
|
||||
connID uint64
|
||||
nextAddr netip.Addr
|
||||
|
||||
Reference in New Issue
Block a user