mirror of
https://github.com/soypat/lneto.git
synced 2026-08-16 12:53:26 +00:00
refine DHCP value acquisition
This commit is contained in:
+59
-35
@@ -26,19 +26,41 @@ type Client struct {
|
||||
tIPLease uint32
|
||||
currentXID uint32
|
||||
state ClientState
|
||||
offer [4]byte
|
||||
svip [4]byte // OptServerIdentification.
|
||||
siip [4]byte // SIAddr.
|
||||
reqIP [4]byte
|
||||
router [4]byte
|
||||
subnet [4]byte
|
||||
broadcast [4]byte
|
||||
gateway [4]byte
|
||||
offer addr4
|
||||
svip addr4 // OptServerIdentification.
|
||||
siip addr4 // SIAddr.
|
||||
reqIP addr4
|
||||
router addr4
|
||||
subnet addr4
|
||||
broadcast addr4
|
||||
gateway addr4
|
||||
clientMAC [6]byte
|
||||
|
||||
auxbuf [64]byte
|
||||
}
|
||||
|
||||
type addr4 struct {
|
||||
addr [4]byte
|
||||
valid bool
|
||||
}
|
||||
|
||||
func (a *addr4) unpack() ([4]byte, bool) {
|
||||
return a.addr, a.valid
|
||||
}
|
||||
|
||||
func (a *addr4) setmaybe(data []byte) {
|
||||
if len(data) == 4 {
|
||||
a.set4([4]byte(data[:]))
|
||||
} else {
|
||||
a.valid = false
|
||||
}
|
||||
}
|
||||
|
||||
func (a *addr4) set4(addr [4]byte) {
|
||||
a.valid = true
|
||||
a.addr = addr
|
||||
}
|
||||
|
||||
type RequestConfig struct {
|
||||
RequestedAddr [4]byte
|
||||
ClientHardwareAddr [6]byte
|
||||
@@ -59,7 +81,7 @@ func (c *Client) BeginRequest(xid uint32, cfg RequestConfig) error {
|
||||
c.state = StateInit
|
||||
c.currentXID = xid
|
||||
c.reqHostname = cfg.Hostname
|
||||
c.reqIP = cfg.RequestedAddr
|
||||
c.reqIP = addr4{addr: cfg.RequestedAddr, valid: true}
|
||||
c.clientMAC = cfg.ClientHardwareAddr
|
||||
return nil
|
||||
}
|
||||
@@ -91,7 +113,7 @@ func (c *Client) setIP(b []byte, frameOffset int) {
|
||||
func (c *Client) Encapsulate(carrierFrame []byte, frameOffset int) (int, error) {
|
||||
if c.isClosed() {
|
||||
return 0, net.ErrClosed
|
||||
} else if c.state == StateSelecting && c.offer == [4]byte{} {
|
||||
} else if c.state == StateSelecting && !c.offer.valid {
|
||||
return 0, nil // No offer received yet.
|
||||
} else if c.state == StateBound {
|
||||
return 0, nil // Done!
|
||||
@@ -123,22 +145,22 @@ func (c *Client) Encapsulate(carrierFrame []byte, frameOffset int) (int, error)
|
||||
}
|
||||
n, _ = EncodeOption16(opts[numOpts:], OptMaximumMessageSize, uint16(maxlen))
|
||||
numOpts += n
|
||||
if c.reqIP != [4]byte{} {
|
||||
n, _ = EncodeOption(opts[numOpts:], OptRequestedIPaddress, c.reqIP[:]...)
|
||||
if !c.reqIP.valid {
|
||||
n, _ = EncodeOption(opts[numOpts:], OptRequestedIPaddress, c.reqIP.addr[:]...)
|
||||
numOpts += n
|
||||
}
|
||||
nextState = StateSelecting
|
||||
|
||||
case StateSelecting:
|
||||
if c.offer == ([4]byte{}) {
|
||||
if !c.offer.valid {
|
||||
return 0, nil // Offer not yet received.
|
||||
}
|
||||
// Send out request, we know we've received an offer by now.
|
||||
n, _ := EncodeOption(opts[numOpts:], OptMessageType, byte(MsgRequest))
|
||||
numOpts += n
|
||||
n, _ = EncodeOption(opts[numOpts:], OptRequestedIPaddress, c.offer[:]...)
|
||||
n, _ = EncodeOption(opts[numOpts:], OptRequestedIPaddress, c.offer.addr[:]...)
|
||||
numOpts += n
|
||||
n, _ = EncodeOption(opts[numOpts:], OptServerIdentification, c.svip[:]...)
|
||||
n, _ = EncodeOption(opts[numOpts:], OptServerIdentification, c.svip.addr[:]...)
|
||||
numOpts += n
|
||||
nextState = StateRequesting
|
||||
|
||||
@@ -193,11 +215,11 @@ func (c *Client) Demux(carrierData []byte, frameOffset int) error {
|
||||
|
||||
switch c.state {
|
||||
case StateSelecting:
|
||||
if msgType == MsgOffer && c.offer == [4]byte{} {
|
||||
if msgType == MsgOffer && !c.offer.valid {
|
||||
// Lock in on this offer.
|
||||
c.gateway = *frm.GIAddr()
|
||||
c.offer = *frm.YIAddr()
|
||||
c.siip = *frm.SIAddr()
|
||||
c.gateway.set4(*frm.GIAddr())
|
||||
c.offer.set4(*frm.YIAddr())
|
||||
c.siip.set4(*frm.SIAddr())
|
||||
}
|
||||
|
||||
case StateRequesting:
|
||||
@@ -237,13 +259,13 @@ func (c *Client) setOptions(frm Frame) error {
|
||||
case OptRebindingTimeValue:
|
||||
c.tRebind = maybeU32(data)
|
||||
case OptServerIdentification:
|
||||
c.svip = maybe4byte(data)
|
||||
c.svip.setmaybe(data)
|
||||
case OptRouter:
|
||||
c.router = maybe4byte(data)
|
||||
c.router.setmaybe(data)
|
||||
case OptBroadcastAddress:
|
||||
c.broadcast = maybe4byte(data)
|
||||
c.broadcast.setmaybe(data)
|
||||
case OptSubnetMask:
|
||||
c.subnet = maybe4byte(data)
|
||||
c.subnet.setmaybe(data)
|
||||
|
||||
case OptHostName:
|
||||
if len(data) < maxHostSize {
|
||||
@@ -271,7 +293,7 @@ func (c *Client) setHeader(frm Frame) {
|
||||
frm.SetHardware(1, 6, 0)
|
||||
frm.SetSecs(1)
|
||||
if c.state.HasIP() {
|
||||
*frm.CIAddr() = c.offer
|
||||
*frm.CIAddr() = c.offer.addr
|
||||
}
|
||||
if c.state == StateInit {
|
||||
siaddr := frm.SIAddr()[:]
|
||||
@@ -279,13 +301,13 @@ func (c *Client) setHeader(frm Frame) {
|
||||
siaddr[i] = 255
|
||||
}
|
||||
} else {
|
||||
if c.siip == [4]byte{} {
|
||||
*frm.SIAddr() = c.svip
|
||||
if !c.siip.valid {
|
||||
*frm.SIAddr() = c.svip.addr
|
||||
} else {
|
||||
*frm.SIAddr() = c.siip
|
||||
*frm.SIAddr() = c.siip.addr
|
||||
}
|
||||
}
|
||||
*frm.YIAddr() = c.offer
|
||||
*frm.YIAddr() = c.offer.addr
|
||||
copy(frm.CHAddrAs6()[:], c.clientMAC[:])
|
||||
frm.SetMagicCookie(MagicCookie)
|
||||
}
|
||||
@@ -302,11 +324,12 @@ func (c *Client) reset(xid uint32) {
|
||||
|
||||
func (d *Client) State() ClientState { return d.state }
|
||||
|
||||
func (d *Client) BroadcastAddr() [4]byte { return d.broadcast }
|
||||
func (d *Client) AssignedAddr() [4]byte { return d.offer }
|
||||
func (d *Client) ServerAddr() [4]byte { return d.svip }
|
||||
func (d *Client) RouterAddr() [4]byte { return d.router }
|
||||
func (d *Client) GatewayAddr() [4]byte { return d.gateway }
|
||||
func (d *Client) BroadcastAddr() ([4]byte, bool) { return d.broadcast.unpack() }
|
||||
func (d *Client) AssignedAddr() ([4]byte, bool) { return d.offer.unpack() }
|
||||
func (d *Client) ServerAddr() ([4]byte, bool) { return d.svip.unpack() }
|
||||
func (d *Client) RouterAddr() ([4]byte, bool) { return d.router.unpack() }
|
||||
func (d *Client) GatewayAddr() ([4]byte, bool) { return d.gateway.unpack() }
|
||||
func (d *Client) Subnet() ([4]byte, bool) { return d.subnet.unpack() }
|
||||
func (d *Client) RebindingSeconds() uint32 { return d.tRebind }
|
||||
func (d *Client) RenewalSeconds() uint32 { return d.tRenew }
|
||||
func (d *Client) IPLeaseSeconds() uint32 { return d.tIPLease }
|
||||
@@ -318,11 +341,12 @@ func (d *Client) DNSServerFirst() netip.Addr {
|
||||
}
|
||||
return d.dns[0]
|
||||
}
|
||||
|
||||
func (d *Client) CIDRBits() uint8 {
|
||||
if d.subnet == [4]byte{} {
|
||||
if !d.subnet.valid {
|
||||
return 0
|
||||
}
|
||||
v := binary.BigEndian.Uint32(d.subnet[:])
|
||||
v := binary.BigEndian.Uint32(d.subnet.addr[:])
|
||||
return 32 - uint8(bits.TrailingZeros32(v))
|
||||
}
|
||||
|
||||
|
||||
+14
-3
@@ -121,18 +121,29 @@ func run() (err error) {
|
||||
dhcpIsDone := stack.dhcp.State() == dhcpv4.StateBound
|
||||
if dhcpIsDone {
|
||||
state = stateInitARP
|
||||
err = stack.ip.SetAddr(netip.AddrFrom4(stack.dhcp.AssignedAddr()))
|
||||
assigned4, ok := stack.dhcp.AssignedAddr()
|
||||
if !ok {
|
||||
return errors.New("DHCP client address not assigned")
|
||||
}
|
||||
err = stack.ip.SetAddr(netip.AddrFrom4(assigned4))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = stack.StartResolveHardwareAddress6(netip.AddrFrom4(stack.dhcp.RouterAddr()))
|
||||
routeraddr, ok := stack.dhcp.RouterAddr()
|
||||
if !ok {
|
||||
return errors.New("DHCP router address not assigned")
|
||||
}
|
||||
err = stack.StartResolveHardwareAddress6(netip.AddrFrom4(routeraddr))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
case stateInitARP:
|
||||
router := stack.dhcp.RouterAddr()
|
||||
router, ok := stack.dhcp.RouterAddr()
|
||||
if !ok {
|
||||
return errors.New("DHCP router address not assigned")
|
||||
}
|
||||
hw, err := stack.ResultResolveHardwareAddress6(netip.AddrFrom4(router))
|
||||
if err == nil {
|
||||
stack.link.SetGateway6(hw)
|
||||
|
||||
Reference in New Issue
Block a user