diff --git a/dhcpv4/client.go b/dhcpv4/client.go index e517ab7..a5bbbe4 100644 --- a/dhcpv4/client.go +++ b/dhcpv4/client.go @@ -17,6 +17,7 @@ import ( type Client struct { connID uint64 reqHostname string + clientID []byte hostname []byte dns []netip.Addr @@ -26,6 +27,7 @@ type Client struct { tIPLease uint32 currentXID uint32 state ClientState + clientMAC [6]byte offer addr4 svip addr4 // OptServerIdentification. siip addr4 // SIAddr. @@ -34,7 +36,6 @@ type Client struct { subnet addr4 broadcast addr4 gateway addr4 - clientMAC [6]byte auxbuf [64]byte } @@ -78,7 +79,7 @@ func (c *Client) BeginRequest(xid uint32, cfg RequestConfig) error { if len(cfg.Hostname) > 36 { return errors.New("requested hostname too long") } else if c.state != StateInit && c.state != 0 { - return errors.New("dhcp client must be closed/done before new request") + return errors.New("dhcp client must be closed/Init before new request") } else if xid == 0 { return errors.New("zero xid") } @@ -88,6 +89,11 @@ func (c *Client) BeginRequest(xid uint32, cfg RequestConfig) error { c.reqHostname = cfg.Hostname c.reqIP = addr4{addr: cfg.RequestedAddr, valid: true} c.clientMAC = cfg.ClientHardwareAddr + if cfg.ClientID != "" { + c.clientID = append(c.clientID[:0], cfg.ClientID...) + } else { + c.clientID = append(c.clientID[:0], c.clientMAC[:]...) + } return nil } @@ -172,7 +178,7 @@ func (c *Client) Encapsulate(carrierFrame []byte, frameOffset int) (int, error) default: return 0, errors.New("unhandled state" + c.state.String()) } - n, _ := EncodeOption(opts[numOpts:], OptClientIdentifier, c.clientMAC[:]...) + n, _ := EncodeOption(opts[numOpts:], OptClientIdentifier, c.clientID...) numOpts += n if len(c.reqHostname) > 0 { n, err := EncodeOptionString(opts[numOpts:], OptHostName, c.reqHostname) @@ -323,6 +329,7 @@ func (c *Client) reset(xid uint32) { currentXID: xid, reqIP: c.reqIP, clientMAC: c.clientMAC, + clientID: c.clientID, } } diff --git a/internet/stackbasic_test.go b/internet/stackbasic_test.go index bb7f4e2..c431653 100644 --- a/internet/stackbasic_test.go +++ b/internet/stackbasic_test.go @@ -117,7 +117,7 @@ func setupClientServer(t *testing.T, rng *rand.Rand, client, server *StackIP, co if err != nil { t.Fatal(err) } - err = connClient.OpenActive(svip, clip.Port(), 100) + err = connClient.OpenActive(clip.Port(), svip, 100) if err != nil { t.Fatal(err) } diff --git a/tcp/conn.go b/tcp/conn.go index d2a4d4c..2c68035 100644 --- a/tcp/conn.go +++ b/tcp/conn.go @@ -15,7 +15,9 @@ import ( ) var ( - errDeadlineExceeded = os.ErrDeadlineExceeded + errDeadlineExceeded = os.ErrDeadlineExceeded + errNoRemoteAddr = errors.New("tcp: no remote address established") + errMismatchedIPVersion = errors.New("mismatched IP version") ) // Conn builds on the [Handler] abstraction and adds IP header knowledge, time management, and familiar user facing API @@ -27,14 +29,12 @@ type Conn struct { h Handler remoteAddr []byte - rdead time.Time - wdead time.Time - lastTx time.Time - lastRx time.Time - - ipID uint16 + rdead time.Time + wdead time.Time abortErr error logger + + ipID uint16 } type ConnConfig struct { @@ -69,7 +69,7 @@ func (conn *Conn) BufferedInput() int { return conn.h.BufferedInput() } // OpenActive opens a connection to a remote peer with a known IP address and port combination. // iss is the initial send sequence number which is ideally a random number which is far away from the last sequence number used on a connection to the same host. -func (conn *Conn) OpenActive(remote netip.AddrPort, localPort uint16, iss Value) error { +func (conn *Conn) OpenActive(localPort uint16, remote netip.AddrPort, iss Value) error { err := conn.h.OpenActive(localPort, remote.Port(), iss) if err != nil { return err @@ -214,13 +214,13 @@ func (conn *Conn) Demux(buf []byte, off int) (err error) { func (conn *Conn) Encapsulate(buf []byte, off int) (n int, err error) { if len(conn.remoteAddr) == 0 { - return 0, errors.New("unset IP address") + return 0, errNoRemoteAddr } raddr, _, _, _, err := internal.GetIPAddr(buf[:off]) if err != nil { return 0, err } else if len(raddr) != len(conn.remoteAddr) { - return 0, errors.New("mismatched IP version") + return 0, errMismatchedIPVersion } n, err = conn.h.Send(buf[off:]) if err != nil {