pax_global_header00006660000000000000000000000064125670173030014516gustar00rootroot0000000000000052 comment=e0331f03a311f40d6e682a52418b4d2b75edb6a5 golang-github-d2g-dhcp4-0.0~git20150413/000077500000000000000000000000001256701730300173005ustar00rootroot00000000000000golang-github-d2g-dhcp4-0.0~git20150413/LICENSE000066400000000000000000000027411256701730300203110ustar00rootroot00000000000000Copyright (c) 2013 Skagerrak Software Limited. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Skagerrak Software Limited nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.golang-github-d2g-dhcp4-0.0~git20150413/README.md000066400000000000000000000003521256701730300205570ustar00rootroot00000000000000# DHCP4 - A DHCP library written in Go. Warning: This library is still being developed. Function calls will change. I've removed Server Functionality, for me this project supports the underlying DHCP format not the implementation. golang-github-d2g-dhcp4-0.0~git20150413/constants.go000066400000000000000000000121101256701730300216360ustar00rootroot00000000000000package dhcp4 // OpCodes const ( BootRequest OpCode = 1 // From Client BootReply OpCode = 2 // From Server ) // DHCP Message Type 53 const ( Discover MessageType = 1 // Broadcast Packet From Client - Can I have an IP? Offer MessageType = 2 // Broadcast From Server - Here's an IP Request MessageType = 3 // Broadcast From Client - I'll take that IP (Also start for renewals) Decline MessageType = 4 // Broadcast From Client - Sorry I can't use that IP ACK MessageType = 5 // From Server, Yes you can have that IP NAK MessageType = 6 // From Server, No you cannot have that IP Release MessageType = 7 // From Client, I don't need that IP anymore Inform MessageType = 8 // From Client, I have this IP and there's nothing you can do about it ) // DHCP Options const ( End OptionCode = 255 Pad OptionCode = 0 OptionSubnetMask OptionCode = 1 OptionTimeOffset OptionCode = 2 OptionRouter OptionCode = 3 OptionTimeServer OptionCode = 4 OptionNameServer OptionCode = 5 OptionDomainNameServer OptionCode = 6 OptionLogServer OptionCode = 7 OptionCookieServer OptionCode = 8 OptionLPRServer OptionCode = 9 OptionImpressServer OptionCode = 10 OptionResourceLocationServer OptionCode = 11 OptionHostName OptionCode = 12 OptionBootFileSize OptionCode = 13 OptionMeritDumpFile OptionCode = 14 OptionDomainName OptionCode = 15 OptionSwapServer OptionCode = 16 OptionRootPath OptionCode = 17 OptionExtensionsPath OptionCode = 18 // IP Layer Parameters per Host OptionIPForwardingEnableDisable OptionCode = 19 OptionNonLocalSourceRoutingEnableDisable OptionCode = 20 OptionPolicyFilter OptionCode = 21 OptionMaximumDatagramReassemblySize OptionCode = 22 OptionDefaultIPTimeToLive OptionCode = 23 OptionPathMTUAgingTimeout OptionCode = 24 OptionPathMTUPlateauTable OptionCode = 25 // IP Layer Parameters per Interface OptionInterfaceMTU OptionCode = 26 OptionAllSubnetsAreLocal OptionCode = 27 OptionBroadcastAddress OptionCode = 28 OptionPerformMaskDiscovery OptionCode = 29 OptionMaskSupplier OptionCode = 30 OptionPerformRouterDiscovery OptionCode = 31 OptionRouterSolicitationAddress OptionCode = 32 OptionStaticRoute OptionCode = 33 // Link Layer Parameters per Interface OptionTrailerEncapsulation OptionCode = 34 OptionARPCacheTimeout OptionCode = 35 OptionEthernetEncapsulation OptionCode = 36 // TCP Parameters OptionTCPDefaultTTL OptionCode = 37 OptionTCPKeepaliveInterval OptionCode = 38 OptionTCPKeepaliveGarbage OptionCode = 39 // Application and Service Parameters OptionNetworkInformationServiceDomain OptionCode = 40 OptionNetworkInformationServers OptionCode = 41 OptionNetworkTimeProtocolServers OptionCode = 42 OptionVendorSpecificInformation OptionCode = 43 OptionNetBIOSOverTCPIPNameServer OptionCode = 44 OptionNetBIOSOverTCPIPDatagramDistributionServer OptionCode = 45 OptionNetBIOSOverTCPIPNodeType OptionCode = 46 OptionNetBIOSOverTCPIPScope OptionCode = 47 OptionXWindowSystemFontServer OptionCode = 48 OptionXWindowSystemDisplayManager OptionCode = 49 OptionNetworkInformationServicePlusDomain OptionCode = 64 OptionNetworkInformationServicePlusServers OptionCode = 65 OptionMobileIPHomeAgent OptionCode = 68 OptionSimpleMailTransportProtocol OptionCode = 69 OptionPostOfficeProtocolServer OptionCode = 70 OptionNetworkNewsTransportProtocol OptionCode = 71 OptionDefaultWorldWideWebServer OptionCode = 72 OptionDefaultFingerServer OptionCode = 73 OptionDefaultInternetRelayChatServer OptionCode = 74 OptionStreetTalkServer OptionCode = 75 OptionStreetTalkDirectoryAssistance OptionCode = 76 // DHCP Extensions OptionRequestedIPAddress OptionCode = 50 OptionIPAddressLeaseTime OptionCode = 51 OptionOverload OptionCode = 52 OptionDHCPMessageType OptionCode = 53 OptionServerIdentifier OptionCode = 54 OptionParameterRequestList OptionCode = 55 OptionMessage OptionCode = 56 OptionMaximumDHCPMessageSize OptionCode = 57 OptionRenewalTimeValue OptionCode = 58 OptionRebindingTimeValue OptionCode = 59 OptionVendorClassIdentifier OptionCode = 60 OptionClientIdentifier OptionCode = 61 OptionTFTPServerName OptionCode = 66 OptionBootFileName OptionCode = 67 OptionUserClass OptionCode = 77 OptionClientArchitecture OptionCode = 93 OptionTZPOSIXString OptionCode = 100 OptionTZDatabaseString OptionCode = 101 OptionClasslessRouteFormat OptionCode = 121 ) golang-github-d2g-dhcp4-0.0~git20150413/helpers.go000066400000000000000000000031701256701730300212720ustar00rootroot00000000000000package dhcp4 import ( "encoding/binary" "net" "time" ) // IPRange returns how many ips in the ip range from start to stop (inclusive) func IPRange(start, stop net.IP) int { //return int(Uint([]byte(stop))-Uint([]byte(start))) + 1 return int(binary.BigEndian.Uint32(stop.To4())) - int(binary.BigEndian.Uint32(start.To4())) + 1 } // IPAdd returns a copy of start + add. // IPAdd(net.IP{192,168,1,1},30) returns net.IP{192.168.1.31} func IPAdd(start net.IP, add int) net.IP { // IPv4 only start = start.To4() //v := Uvarint([]byte(start)) result := make(net.IP, 4) binary.BigEndian.PutUint32(result, binary.BigEndian.Uint32(start)+uint32(add)) //PutUint([]byte(result), v+uint64(add)) return result } // IPLess returns where IP a is less than IP b. func IPLess(a, b net.IP) bool { b = b.To4() for i, ai := range a.To4() { if ai != b[i] { return ai < b[i] } } return false } // IPInRange returns true if ip is between (inclusive) start and stop. func IPInRange(start, stop, ip net.IP) bool { return !(IPLess(ip, start) || IPLess(stop, ip)) } // OptionsLeaseTime - converts a time.Duration to a 4 byte slice, compatible // with OptionIPAddressLeaseTime. func OptionsLeaseTime(d time.Duration) []byte { leaseBytes := make([]byte, 4) binary.BigEndian.PutUint32(leaseBytes, uint32(d/time.Second)) //PutUvarint(leaseBytes, uint64(d/time.Second)) return leaseBytes } // JoinIPs returns a byte slice of IP addresses, one immediately after the other // This may be useful for creating multiple IP options such as OptionRouter. func JoinIPs(ips []net.IP) (b []byte) { for _, v := range ips { b = append(b, v.To4()...) } return } golang-github-d2g-dhcp4-0.0~git20150413/option.go000066400000000000000000000020271256701730300211400ustar00rootroot00000000000000package dhcp4 type OptionCode byte type Option struct { Code OptionCode Value []byte } // Map of DHCP options type Options map[OptionCode][]byte // SelectOrderOrAll has same functionality as SelectOrder, except if the order // param is nil, whereby all options are added (in arbitary order). func (o Options) SelectOrderOrAll(order []byte) []Option { if order == nil { opts := make([]Option, 0, len(o)) for i, v := range o { opts = append(opts, Option{Code: i, Value: v}) } return opts } return o.SelectOrder(order) } // SelectOrder returns a slice of options ordered and selected by a byte array // usually defined by OptionParameterRequestList. This result is expected to be // used in ReplyPacket()'s []Option parameter. func (o Options) SelectOrder(order []byte) []Option { opts := make([]Option, 0, len(order)) for _, v := range order { if data, ok := o[OptionCode(v)]; ok { opts = append(opts, Option{Code: OptionCode(v), Value: data}) } } return opts } type OpCode byte type MessageType byte // Option 53 golang-github-d2g-dhcp4-0.0~git20150413/packet.go000066400000000000000000000110761256701730300211030ustar00rootroot00000000000000package dhcp4 import ( "net" "time" ) // A DHCP packet type Packet []byte func (p Packet) OpCode() OpCode { return OpCode(p[0]) } func (p Packet) HType() byte { return p[1] } func (p Packet) HLen() byte { return p[2] } func (p Packet) Hops() byte { return p[3] } func (p Packet) XId() []byte { return p[4:8] } func (p Packet) Secs() []byte { return p[8:10] } // Never Used? func (p Packet) Flags() []byte { return p[10:12] } func (p Packet) CIAddr() net.IP { return net.IP(p[12:16]) } func (p Packet) YIAddr() net.IP { return net.IP(p[16:20]) } func (p Packet) SIAddr() net.IP { return net.IP(p[20:24]) } func (p Packet) GIAddr() net.IP { return net.IP(p[24:28]) } func (p Packet) CHAddr() net.HardwareAddr { hLen := p.HLen() if hLen > 16 { // Prevent chaddr exceeding p boundary hLen = 16 } return net.HardwareAddr(p[28 : 28+hLen]) // max endPos 44 } // 192 bytes of zeros BOOTP legacy func (p Packet) Cookie() []byte { return p[236:240] } func (p Packet) Options() []byte { if len(p) > 240 { return p[240:] } return nil } func (p Packet) Broadcast() bool { return p.Flags()[0] > 127 } func (p Packet) SetBroadcast(broadcast bool) { if p.Broadcast() != broadcast { p.Flags()[0] ^= 128 } } func (p Packet) SetOpCode(c OpCode) { p[0] = byte(c) } func (p Packet) SetCHAddr(a net.HardwareAddr) { copy(p[28:44], a) p[2] = byte(len(a)) } func (p Packet) SetHType(hType byte) { p[1] = hType } func (p Packet) SetCookie(cookie []byte) { copy(p.Cookie(), cookie) } func (p Packet) SetHops(hops byte) { p[3] = hops } func (p Packet) SetXId(xId []byte) { copy(p.XId(), xId) } func (p Packet) SetSecs(secs []byte) { copy(p.Secs(), secs) } func (p Packet) SetFlags(flags []byte) { copy(p.Flags(), flags) } func (p Packet) SetCIAddr(ip net.IP) { copy(p.CIAddr(), ip.To4()) } func (p Packet) SetYIAddr(ip net.IP) { copy(p.YIAddr(), ip.To4()) } func (p Packet) SetSIAddr(ip net.IP) { copy(p.SIAddr(), ip.To4()) } func (p Packet) SetGIAddr(ip net.IP) { copy(p.GIAddr(), ip.To4()) } // Parses the packet's options into an Options map func (p Packet) ParseOptions() Options { opts := p.Options() options := make(Options, 10) for len(opts) >= 2 && OptionCode(opts[0]) != End { if OptionCode(opts[0]) == Pad { opts = opts[1:] continue } size := int(opts[1]) if len(opts) < 2+size { break } options[OptionCode(opts[0])] = opts[2 : 2+size] opts = opts[2+size:] } return options } func NewPacket(opCode OpCode) Packet { p := make(Packet, 241) p.SetOpCode(opCode) p.SetHType(1) // Ethernet p.SetCookie([]byte{99, 130, 83, 99}) p[240] = byte(End) return p } // Appends a DHCP option to the end of a packet func (p *Packet) AddOption(o OptionCode, value []byte) { *p = append((*p)[:len(*p)-1], []byte{byte(o), byte(len(value))}...) // Strip off End, Add OptionCode and Length *p = append(*p, value...) // Add Option Value *p = append(*p, byte(End)) // Add on new End } // Removes all options from packet. func (p *Packet) StripOptions() { *p = append((*p)[:240], byte(End)) } // Creates a request packet that a Client would send to a server. func RequestPacket(mt MessageType, chAddr net.HardwareAddr, cIAddr net.IP, xId []byte, broadcast bool, options []Option) Packet { p := NewPacket(BootRequest) p.SetCHAddr(chAddr) p.SetXId(xId) if cIAddr != nil { p.SetCIAddr(cIAddr) } p.SetBroadcast(broadcast) p.AddOption(OptionDHCPMessageType, []byte{byte(mt)}) for _, o := range options { p.AddOption(o.Code, o.Value) } p.PadToMinSize() return p } // ReplyPacket creates a reply packet that a Server would send to a client. // It uses the req Packet param to copy across common/necessary fields to // associate the reply the request. func ReplyPacket(req Packet, mt MessageType, serverId, yIAddr net.IP, leaseDuration time.Duration, options []Option) Packet { p := NewPacket(BootReply) p.SetXId(req.XId()) p.SetFlags(req.Flags()) p.SetYIAddr(yIAddr) p.SetGIAddr(req.GIAddr()) p.SetCHAddr(req.CHAddr()) p.SetSecs(req.Secs()) p.AddOption(OptionDHCPMessageType, []byte{byte(mt)}) p.AddOption(OptionServerIdentifier, []byte(serverId)) p.AddOption(OptionIPAddressLeaseTime, OptionsLeaseTime(leaseDuration)) for _, o := range options { p.AddOption(o.Code, o.Value) } p.PadToMinSize() return p } // PadToMinSize pads a packet so that when sent over UDP, the entire packet, // is 300 bytes (BOOTP min), to be compatible with really old devices. var padder [272]byte func (p *Packet) PadToMinSize() { if n := len(*p); n < 272 { *p = append(*p, padder[:272-n]...) } }