diff options
Diffstat (limited to 'pkg/dhcp/dhcp.go')
-rw-r--r-- | pkg/dhcp/dhcp.go | 280 |
1 files changed, 0 insertions, 280 deletions
diff --git a/pkg/dhcp/dhcp.go b/pkg/dhcp/dhcp.go deleted file mode 100644 index f96ffd891..000000000 --- a/pkg/dhcp/dhcp.go +++ /dev/null @@ -1,280 +0,0 @@ -// Copyright 2018 The gVisor Authors. -// -// 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 implements a DHCP client and server as described in RFC 2131. -package dhcp - -import ( - "bytes" - "encoding/binary" - "fmt" - "time" - - "gvisor.googlesource.com/gvisor/pkg/tcpip" -) - -// Config is standard DHCP configuration. -type Config struct { - Error error - ServerAddress tcpip.Address // address of the server - SubnetMask tcpip.AddressMask // client address subnet mask - Gateway tcpip.Address // client default gateway - DNS []tcpip.Address // client DNS server addresses - LeaseLength time.Duration // length of the address lease -} - -func (cfg *Config) decode(opts []option) error { - *cfg = Config{} - for _, opt := range opts { - b := opt.body - if !opt.code.lenValid(len(b)) { - return fmt.Errorf("%s: bad length: %d", opt.code, len(b)) - } - switch opt.code { - case optLeaseTime: - t := binary.BigEndian.Uint32(b) - cfg.LeaseLength = time.Duration(t) * time.Second - case optSubnetMask: - cfg.SubnetMask = tcpip.AddressMask(b) - case optDHCPServer: - cfg.ServerAddress = tcpip.Address(b) - case optDefaultGateway: - cfg.Gateway = tcpip.Address(b) - case optDomainNameServer: - for ; len(b) > 0; b = b[4:] { - if len(b) < 4 { - return fmt.Errorf("DNS bad length: %d", len(b)) - } - cfg.DNS = append(cfg.DNS, tcpip.Address(b[:4])) - } - } - } - return nil -} - -func (cfg Config) encode() (opts []option) { - if cfg.ServerAddress != "" { - opts = append(opts, option{optDHCPServer, []byte(cfg.ServerAddress)}) - } - if cfg.SubnetMask != "" { - opts = append(opts, option{optSubnetMask, []byte(cfg.SubnetMask)}) - } - if cfg.Gateway != "" { - opts = append(opts, option{optDefaultGateway, []byte(cfg.Gateway)}) - } - if len(cfg.DNS) > 0 { - dns := make([]byte, 0, 4*len(cfg.DNS)) - for _, addr := range cfg.DNS { - dns = append(dns, addr...) - } - opts = append(opts, option{optDomainNameServer, dns}) - } - if l := cfg.LeaseLength / time.Second; l != 0 { - v := make([]byte, 4) - v[0] = byte(l >> 24) - v[1] = byte(l >> 16) - v[2] = byte(l >> 8) - v[3] = byte(l >> 0) - opts = append(opts, option{optLeaseTime, v}) - } - return opts -} - -const ( - // ServerPort is the well-known UDP port number for a DHCP server. - ServerPort = 67 - // ClientPort is the well-known UDP port number for a DHCP client. - ClientPort = 68 -) - -var magicCookie = []byte{99, 130, 83, 99} // RFC 1497 - -type xid uint32 - -type header []byte - -func (h header) init() { - h[1] = 0x01 // htype - h[2] = 0x06 // hlen - h[3] = 0x00 // hops - h[8], h[9] = 0, 0 // secs - copy(h[236:240], magicCookie) -} - -func (h header) isValid() bool { - if len(h) < 241 { - return false - } - if o := h.op(); o != opRequest && o != opReply { - return false - } - if h[1] != 0x01 || h[2] != 0x06 { - return false - } - return bytes.Equal(h[236:240], magicCookie) -} - -func (h header) op() op { return op(h[0]) } -func (h header) setOp(o op) { h[0] = byte(o) } -func (h header) xidbytes() []byte { return h[4:8] } -func (h header) xid() xid { return xid(h[4])<<24 | xid(h[5])<<16 | xid(h[6])<<8 | xid(h[7]) } -func (h header) setBroadcast() { h[10], h[11] = 0x80, 0x00 } // flags top bit -func (h header) ciaddr() []byte { return h[12:16] } -func (h header) yiaddr() []byte { return h[16:20] } -func (h header) siaddr() []byte { return h[20:24] } -func (h header) giaddr() []byte { return h[24:28] } -func (h header) chaddr() []byte { return h[28:44] } -func (h header) sname() []byte { return h[44:108] } -func (h header) file() []byte { return h[108:236] } - -func (h header) options() (opts options, err error) { - i := headerBaseSize - for i < len(h) { - if h[i] == 0 { - i++ - continue - } - if h[i] == 255 { - break - } - if len(h) <= i+1 { - return nil, fmt.Errorf("option missing length") - } - optlen := int(h[i+1]) - if len(h) < i+2+optlen { - return nil, fmt.Errorf("option %v too long i=%d, optlen=%d", optionCode(h[i]), i, optlen) - } - opts = append(opts, option{ - code: optionCode(h[i]), - body: h[i+2 : i+2+optlen], - }) - i += 2 + optlen - } - return opts, nil -} - -func (h header) setOptions(opts []option) { - i := headerBaseSize - for _, opt := range opts { - h[i] = byte(opt.code) - h[i+1] = byte(len(opt.body)) - copy(h[i+2:i+2+len(opt.body)], opt.body) - i += 2 + len(opt.body) - } - h[i] = 255 // End option - i++ - for ; i < len(h); i++ { - h[i] = 0 - } -} - -// headerBaseSize is the size of a DHCP packet, including the magic cookie. -// -// Note that a DHCP packet is required to have an 'end' option that takes -// up an extra byte, so the minimum DHCP packet size is headerBaseSize + 1. -const headerBaseSize = 240 - -type option struct { - code optionCode - body []byte -} - -type optionCode byte - -const ( - optSubnetMask optionCode = 1 - optDefaultGateway optionCode = 3 - optDomainNameServer optionCode = 6 - optDomainName optionCode = 15 - optReqIPAddr optionCode = 50 - optLeaseTime optionCode = 51 - optDHCPMsgType optionCode = 53 // dhcpMsgType - optDHCPServer optionCode = 54 - optParamReq optionCode = 55 - optMessage optionCode = 56 - optClientID optionCode = 61 -) - -func (code optionCode) lenValid(l int) bool { - switch code { - case optSubnetMask, optDefaultGateway, - optReqIPAddr, optLeaseTime, optDHCPServer: - return l == 4 - case optDHCPMsgType: - return l == 1 - case optDomainNameServer: - return l%4 == 0 - case optMessage, optDomainName, optClientID: - return l >= 1 - case optParamReq: - return true // no fixed length - default: - return true // unknown option, assume ok - } -} - -type options []option - -func (opts options) dhcpMsgType() (dhcpMsgType, error) { - for _, opt := range opts { - if opt.code == optDHCPMsgType { - if len(opt.body) != 1 { - return 0, fmt.Errorf("%s: bad length: %d", opt.code, len(opt.body)) - } - v := opt.body[0] - if v <= 0 || v >= 8 { - return 0, fmt.Errorf("DHCP bad length: %d", len(opt.body)) - } - return dhcpMsgType(v), nil - } - } - return 0, nil -} - -func (opts options) message() string { - for _, opt := range opts { - if opt.code == optMessage { - return string(opt.body) - } - } - return "" -} - -func (opts options) len() int { - l := 0 - for _, opt := range opts { - l += 1 + 1 + len(opt.body) // code + len + body - } - return l + 1 // extra byte for 'pad' option -} - -type op byte - -const ( - opRequest op = 0x01 - opReply op = 0x02 -) - -// dhcpMsgType is the DHCP Message Type from RFC 1533, section 9.4. -type dhcpMsgType byte - -const ( - dhcpDISCOVER dhcpMsgType = 1 - dhcpOFFER dhcpMsgType = 2 - dhcpREQUEST dhcpMsgType = 3 - dhcpDECLINE dhcpMsgType = 4 - dhcpACK dhcpMsgType = 5 - dhcpNAK dhcpMsgType = 6 - dhcpRELEASE dhcpMsgType = 7 -) |