mirror of
https://github.com/danderson/netboot.git
synced 2025-12-04 00:51:25 +01:00
dhcp: tighten up the exported interface by removing some cruft.
Notably, some of the helpers for implementing Conns are internal now.
This commit is contained in:
parent
45dd5dfe4d
commit
ae696d0c3d
58
dhcp/conn.go
58
dhcp/conn.go
@ -16,6 +16,7 @@ package dhcp
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -23,10 +24,55 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// defined as a var so tests can override it.
|
// defined as a var so tests can override it.
|
||||||
var dhcpClientPort = 68
|
var (
|
||||||
|
dhcpClientPort = 68
|
||||||
|
platformConn func(string) (Conn, error)
|
||||||
|
)
|
||||||
|
|
||||||
var platformConn func(string) (Conn, error)
|
// txType describes how a Packet should be sent on the wire.
|
||||||
|
type txType int
|
||||||
|
|
||||||
|
// The various transmission strategies described in RFC 2131. "MUST",
|
||||||
|
// "MUST NOT", "SHOULD" and "MAY" are as specified in RFC 2119.
|
||||||
|
const (
|
||||||
|
// Packet MUST be broadcast.
|
||||||
|
txBroadcast txType = iota
|
||||||
|
// Packet MUST be unicasted to port 67 of RelayAddr
|
||||||
|
txRelayAddr
|
||||||
|
// Packet MUST be unicasted to port 68 of ClientAddr
|
||||||
|
txClientAddr
|
||||||
|
// Packet SHOULD be unicasted to port 68 of YourAddr, with the
|
||||||
|
// link-layer destination explicitly set to HardwareAddr. You MUST
|
||||||
|
// NOT rely on ARP resolution to discover the link-layer
|
||||||
|
// destination address.
|
||||||
|
//
|
||||||
|
// Conn implementations that cannot explicitly set the link-layer
|
||||||
|
// destination address MAY instead broadcast the packet.
|
||||||
|
txHardwareAddr
|
||||||
|
)
|
||||||
|
|
||||||
|
// Conn is a DHCP-oriented packet socket.
|
||||||
|
//
|
||||||
|
// Multiple goroutines may invoke methods on a Conn simultaneously.
|
||||||
|
type Conn interface {
|
||||||
|
io.Closer
|
||||||
|
// RecvDHCP reads a Packet from the connection. It returns the
|
||||||
|
// packet and the interface it was received on, which may be nil
|
||||||
|
// if interface information cannot be obtained.
|
||||||
|
RecvDHCP() (pkt *Packet, intf *net.Interface, err error)
|
||||||
|
// SendDHCP sends pkt. The precise transmission mechanism depends
|
||||||
|
// on pkt.txType(). intf should be the net.Interface returned by
|
||||||
|
// RecvDHCP if responding to a DHCP client, or the interface for
|
||||||
|
// which configuration is desired if acting as a client.
|
||||||
|
SendDHCP(pkt *Packet, intf *net.Interface) error
|
||||||
|
// SetReadDeadline sets the deadline for future Read calls.
|
||||||
|
// If the deadline is reached, Read will fail with a timeout
|
||||||
|
// (see type Error) instead of blocking.
|
||||||
|
// A zero value for t means Read will not time out.
|
||||||
|
SetReadDeadline(t time.Time) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewConn creates a Conn bound to the given UDP ip:port.
|
||||||
func NewConn(addr string) (Conn, error) {
|
func NewConn(addr string) (Conn, error) {
|
||||||
if platformConn != nil {
|
if platformConn != nil {
|
||||||
c, err := platformConn(addr)
|
c, err := platformConn(addr)
|
||||||
@ -90,8 +136,8 @@ func (c *portableConn) SendDHCP(pkt *Packet, intf *net.Interface) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
switch pkt.TxType() {
|
switch pkt.txType() {
|
||||||
case TxBroadcast, TxHardwareAddr:
|
case txBroadcast, txHardwareAddr:
|
||||||
cm := ipv4.ControlMessage{
|
cm := ipv4.ControlMessage{
|
||||||
IfIndex: intf.Index,
|
IfIndex: intf.Index,
|
||||||
}
|
}
|
||||||
@ -101,7 +147,7 @@ func (c *portableConn) SendDHCP(pkt *Packet, intf *net.Interface) error {
|
|||||||
}
|
}
|
||||||
_, err = c.conn.WriteTo(b, &cm, &addr)
|
_, err = c.conn.WriteTo(b, &cm, &addr)
|
||||||
return err
|
return err
|
||||||
case TxRelayAddr:
|
case txRelayAddr:
|
||||||
// Send to the server port, not the client port.
|
// Send to the server port, not the client port.
|
||||||
addr := net.UDPAddr{
|
addr := net.UDPAddr{
|
||||||
IP: pkt.RelayAddr,
|
IP: pkt.RelayAddr,
|
||||||
@ -109,7 +155,7 @@ func (c *portableConn) SendDHCP(pkt *Packet, intf *net.Interface) error {
|
|||||||
}
|
}
|
||||||
_, err = c.conn.WriteTo(b, nil, &addr)
|
_, err = c.conn.WriteTo(b, nil, &addr)
|
||||||
return err
|
return err
|
||||||
case TxClientAddr:
|
case txClientAddr:
|
||||||
addr := net.UDPAddr{
|
addr := net.UDPAddr{
|
||||||
IP: pkt.ClientAddr,
|
IP: pkt.ClientAddr,
|
||||||
Port: dhcpClientPort,
|
Port: dhcpClientPort,
|
||||||
|
|||||||
@ -153,19 +153,19 @@ func (c *linuxConn) SendDHCP(pkt *Packet, intf *net.Interface) error {
|
|||||||
Protocol: 17,
|
Protocol: 17,
|
||||||
}
|
}
|
||||||
|
|
||||||
switch pkt.TxType() {
|
switch pkt.txType() {
|
||||||
case TxBroadcast, TxHardwareAddr:
|
case txBroadcast, txHardwareAddr:
|
||||||
hdr.Dst = net.IPv4bcast
|
hdr.Dst = net.IPv4bcast
|
||||||
cm := ipv4.ControlMessage{
|
cm := ipv4.ControlMessage{
|
||||||
IfIndex: intf.Index,
|
IfIndex: intf.Index,
|
||||||
}
|
}
|
||||||
return c.conn.WriteTo(&hdr, raw, &cm)
|
return c.conn.WriteTo(&hdr, raw, &cm)
|
||||||
case TxRelayAddr:
|
case txRelayAddr:
|
||||||
// Send to the server port, not the client port.
|
// Send to the server port, not the client port.
|
||||||
binary.BigEndian.PutUint16(raw[2:4], 67)
|
binary.BigEndian.PutUint16(raw[2:4], 67)
|
||||||
hdr.Dst = pkt.RelayAddr
|
hdr.Dst = pkt.RelayAddr
|
||||||
return c.conn.WriteTo(&hdr, raw, nil)
|
return c.conn.WriteTo(&hdr, raw, nil)
|
||||||
case TxClientAddr:
|
case txClientAddr:
|
||||||
hdr.Dst = pkt.ClientAddr
|
hdr.Dst = pkt.ClientAddr
|
||||||
return c.conn.WriteTo(&hdr, raw, nil)
|
return c.conn.WriteTo(&hdr, raw, nil)
|
||||||
default:
|
default:
|
||||||
|
|||||||
@ -68,22 +68,15 @@ func (o Options) Unmarshal(bs []byte) error {
|
|||||||
// Marshal returns the wire encoding of o.
|
// Marshal returns the wire encoding of o.
|
||||||
func (o Options) Marshal() ([]byte, error) {
|
func (o Options) Marshal() ([]byte, error) {
|
||||||
var ret bytes.Buffer
|
var ret bytes.Buffer
|
||||||
if err := o.MarshalTo(&ret); err != nil {
|
opts, err := o.marshalLimited(&ret, 0, false)
|
||||||
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return ret.Bytes(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// MarshalTo serializes o into w.
|
|
||||||
func (o Options) MarshalTo(w io.Writer) error {
|
|
||||||
opts, err := o.marshalLimited(w, 0, false)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if len(opts) > 0 {
|
if len(opts) > 0 {
|
||||||
return errors.New("some options not written, but no limit was given (please file a bug)")
|
return nil, errors.New("some options not written, but no limit was given (please file a bug)")
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
|
return ret.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy returns a shallow copy of o.
|
// Copy returns a shallow copy of o.
|
||||||
|
|||||||
@ -12,7 +12,6 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
// Package dhcp implements parsing and serialization of DHCP packets.
|
|
||||||
package dhcp
|
package dhcp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -83,23 +82,22 @@ type Packet struct {
|
|||||||
Options Options
|
Options Options
|
||||||
}
|
}
|
||||||
|
|
||||||
// TxType determines how the Packet should be sent on the wire, based
|
// decides how to send Packet on the wire, based on its field values.
|
||||||
// on its field values.
|
|
||||||
//
|
//
|
||||||
// This implements the transmission decision process in section 4.1 of
|
// This implements the transmission decision process in section 4.1 of
|
||||||
// RFC 2131.
|
// RFC 2131.
|
||||||
func (p *Packet) TxType() TxType {
|
func (p *Packet) txType() txType {
|
||||||
switch {
|
switch {
|
||||||
case p.RelayAddr != nil && p.RelayAddr.IsGlobalUnicast():
|
case p.RelayAddr != nil && p.RelayAddr.IsGlobalUnicast():
|
||||||
return TxRelayAddr
|
return txRelayAddr
|
||||||
case p.Type == MsgNack:
|
case p.Type == MsgNack:
|
||||||
return TxBroadcast
|
return txBroadcast
|
||||||
case p.ClientAddr != nil && (p.ClientAddr.IsGlobalUnicast() || p.ClientAddr.IsLoopback()):
|
case p.ClientAddr != nil && (p.ClientAddr.IsGlobalUnicast() || p.ClientAddr.IsLoopback()):
|
||||||
return TxClientAddr
|
return txClientAddr
|
||||||
case p.Broadcast:
|
case p.Broadcast:
|
||||||
return TxBroadcast
|
return txBroadcast
|
||||||
default:
|
default:
|
||||||
return TxHardwareAddr
|
return txHardwareAddr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -227,9 +225,13 @@ func (p *Packet) Marshal() ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ret.Write(magic)
|
ret.Write(magic)
|
||||||
if err := opts.MarshalTo(ret); err != nil {
|
leftover, err := opts.marshalLimited(ret, 0, false)
|
||||||
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if len(leftover) > 0 {
|
||||||
|
return nil, errors.New("some options not written, but no limit was given (please file a bug)")
|
||||||
|
}
|
||||||
|
|
||||||
return ret.Bytes(), nil
|
return ret.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,64 +0,0 @@
|
|||||||
// Copyright 2016 Google Inc.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package dhcp // import "go.universe.tf/netboot/dhcp"
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
"net"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// TxType describes how a Packet should be sent on the wire.
|
|
||||||
type TxType int
|
|
||||||
|
|
||||||
// The various transmission strategies described in RFC 2131. "MUST",
|
|
||||||
// "MUST NOT", "SHOULD" and "MAY" are as specified in RFC 2119.
|
|
||||||
const (
|
|
||||||
// Packet MUST be broadcast.
|
|
||||||
TxBroadcast TxType = iota
|
|
||||||
// Packet MUST be unicasted to port 67 of RelayAddr
|
|
||||||
TxRelayAddr
|
|
||||||
// Packet MUST be unicasted to port 68 of ClientAddr
|
|
||||||
TxClientAddr
|
|
||||||
// Packet SHOULD be unicasted to port 68 of YourAddr, with the
|
|
||||||
// link-layer destination explicitly set to HardwareAddr. You MUST
|
|
||||||
// NOT rely on ARP resolution to discover the link-layer
|
|
||||||
// destination address.
|
|
||||||
//
|
|
||||||
// Conn implementations that cannot explicitly set the link-layer
|
|
||||||
// destination address MAY instead broadcast the packet.
|
|
||||||
TxHardwareAddr
|
|
||||||
)
|
|
||||||
|
|
||||||
// Conn is a DHCP-oriented packet socket.
|
|
||||||
//
|
|
||||||
// Multiple goroutines may invoke methods on a Conn simultaneously.
|
|
||||||
type Conn interface {
|
|
||||||
io.Closer
|
|
||||||
// RecvDHCP reads a Packet from the connection. It returns the
|
|
||||||
// packet and the interface it was received on, which may be nil
|
|
||||||
// if interface information cannot be obtained.
|
|
||||||
RecvDHCP() (pkt *Packet, intf *net.Interface, err error)
|
|
||||||
// SendDHCP sends pkt. The precise transmission mechanism depends
|
|
||||||
// on pkt.TxType(). intf should be the net.Interface returned by
|
|
||||||
// RecvDHCP if responding to a DHCP client, or the interface for
|
|
||||||
// which configuration is desired if acting as a client.
|
|
||||||
SendDHCP(pkt *Packet, intf *net.Interface) error
|
|
||||||
// SetReadDeadline sets the deadline for future Read calls.
|
|
||||||
// If the deadline is reached, Read will fail with a timeout
|
|
||||||
// (see type Error) instead of blocking.
|
|
||||||
// A zero value for t means Read will not time out.
|
|
||||||
SetReadDeadline(t time.Time) error
|
|
||||||
}
|
|
||||||
Loading…
x
Reference in New Issue
Block a user