123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585 |
- package layers
- import (
- "bytes"
- "encoding/binary"
- "fmt"
- "net"
- "github.com/google/gopacket"
- )
- type DHCPOp byte
- const (
- DHCPOpRequest DHCPOp = 1
- DHCPOpReply DHCPOp = 2
- )
- func (o DHCPOp) String() string {
- switch o {
- case DHCPOpRequest:
- return "Request"
- case DHCPOpReply:
- return "Reply"
- default:
- return "Unknown"
- }
- }
- type DHCPMsgType byte
- const (
- DHCPMsgTypeUnspecified DHCPMsgType = iota
- DHCPMsgTypeDiscover
- DHCPMsgTypeOffer
- DHCPMsgTypeRequest
- DHCPMsgTypeDecline
- DHCPMsgTypeAck
- DHCPMsgTypeNak
- DHCPMsgTypeRelease
- DHCPMsgTypeInform
- )
- func (o DHCPMsgType) String() string {
- switch o {
- case DHCPMsgTypeUnspecified:
- return "Unspecified"
- case DHCPMsgTypeDiscover:
- return "Discover"
- case DHCPMsgTypeOffer:
- return "Offer"
- case DHCPMsgTypeRequest:
- return "Request"
- case DHCPMsgTypeDecline:
- return "Decline"
- case DHCPMsgTypeAck:
- return "Ack"
- case DHCPMsgTypeNak:
- return "Nak"
- case DHCPMsgTypeRelease:
- return "Release"
- case DHCPMsgTypeInform:
- return "Inform"
- default:
- return "Unknown"
- }
- }
- var DHCPMagic uint32 = 0x63825363
- type DHCPv4 struct {
- BaseLayer
- Operation DHCPOp
- HardwareType LinkType
- HardwareLen uint8
- HardwareOpts uint8
- Xid uint32
- Secs uint16
- Flags uint16
- ClientIP net.IP
- YourClientIP net.IP
- NextServerIP net.IP
- RelayAgentIP net.IP
- ClientHWAddr net.HardwareAddr
- ServerName []byte
- File []byte
- Options DHCPOptions
- }
- type DHCPOptions []DHCPOption
- func (o DHCPOptions) String() string {
- buf := &bytes.Buffer{}
- buf.WriteByte('[')
- for i, opt := range o {
- buf.WriteString(opt.String())
- if i+1 != len(o) {
- buf.WriteString(", ")
- }
- }
- buf.WriteByte(']')
- return buf.String()
- }
- func (d *DHCPv4) LayerType() gopacket.LayerType { return LayerTypeDHCPv4 }
- func (d *DHCPv4) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
- d.Options = d.Options[:0]
- d.Operation = DHCPOp(data[0])
- d.HardwareType = LinkType(data[1])
- d.HardwareLen = data[2]
- d.HardwareOpts = data[3]
- d.Xid = binary.BigEndian.Uint32(data[4:8])
- d.Secs = binary.BigEndian.Uint16(data[8:10])
- d.Flags = binary.BigEndian.Uint16(data[10:12])
- d.ClientIP = net.IP(data[12:16])
- d.YourClientIP = net.IP(data[16:20])
- d.NextServerIP = net.IP(data[20:24])
- d.RelayAgentIP = net.IP(data[24:28])
- d.ClientHWAddr = net.HardwareAddr(data[28 : 28+d.HardwareLen])
- d.ServerName = data[44:108]
- d.File = data[108:236]
- if binary.BigEndian.Uint32(data[236:240]) != DHCPMagic {
- return InvalidMagicCookie
- }
- if len(data) <= 240 {
-
- return nil
- }
- options := data[240:]
- stop := len(options)
- start := 0
- for start < stop {
- o := DHCPOption{}
- if err := o.decode(options[start:]); err != nil {
- return err
- }
- if o.Type == DHCPOptEnd {
- break
- }
- d.Options = append(d.Options, o)
-
- if o.Type == DHCPOptPad {
- start++
- } else {
- start += int(o.Length) + 2
- }
- }
- return nil
- }
- func (d *DHCPv4) Len() uint16 {
- n := uint16(240)
- for _, o := range d.Options {
- if o.Type == DHCPOptPad {
- n++
- } else {
- n += uint16(o.Length) + 2
- }
- }
- n++
- return n
- }
- func (d *DHCPv4) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
- plen := int(d.Len())
- data, err := b.PrependBytes(plen)
- if err != nil {
- return err
- }
- data[0] = byte(d.Operation)
- data[1] = byte(d.HardwareType)
- if opts.FixLengths {
- d.HardwareLen = uint8(len(d.ClientHWAddr))
- }
- data[2] = d.HardwareLen
- data[3] = d.HardwareOpts
- binary.BigEndian.PutUint32(data[4:8], d.Xid)
- binary.BigEndian.PutUint16(data[8:10], d.Secs)
- binary.BigEndian.PutUint16(data[10:12], d.Flags)
- copy(data[12:16], d.ClientIP.To4())
- copy(data[16:20], d.YourClientIP.To4())
- copy(data[20:24], d.NextServerIP.To4())
- copy(data[24:28], d.RelayAgentIP.To4())
- copy(data[28:44], d.ClientHWAddr)
- copy(data[44:108], d.ServerName)
- copy(data[108:236], d.File)
- binary.BigEndian.PutUint32(data[236:240], DHCPMagic)
- if len(d.Options) > 0 {
- offset := 240
- for _, o := range d.Options {
- if err := o.encode(data[offset:]); err != nil {
- return err
- }
-
- if o.Type == DHCPOptPad {
- offset++
- } else {
- offset += 2 + len(o.Data)
- }
- }
- optend := NewDHCPOption(DHCPOptEnd, nil)
- if err := optend.encode(data[offset:]); err != nil {
- return err
- }
- }
- return nil
- }
- func (d *DHCPv4) CanDecode() gopacket.LayerClass {
- return LayerTypeDHCPv4
- }
- func (d *DHCPv4) NextLayerType() gopacket.LayerType {
- return gopacket.LayerTypePayload
- }
- func decodeDHCPv4(data []byte, p gopacket.PacketBuilder) error {
- dhcp := &DHCPv4{}
- err := dhcp.DecodeFromBytes(data, p)
- if err != nil {
- return err
- }
- p.AddLayer(dhcp)
- return p.NextDecoder(gopacket.LayerTypePayload)
- }
- type DHCPOpt byte
- const (
- DHCPOptPad DHCPOpt = 0
- DHCPOptSubnetMask DHCPOpt = 1
- DHCPOptTimeOffset DHCPOpt = 2
- DHCPOptRouter DHCPOpt = 3
- DHCPOptTimeServer DHCPOpt = 4
- DHCPOptNameServer DHCPOpt = 5
- DHCPOptDNS DHCPOpt = 6
- DHCPOptLogServer DHCPOpt = 7
- DHCPOptCookieServer DHCPOpt = 8
- DHCPOptLPRServer DHCPOpt = 9
- DHCPOptImpressServer DHCPOpt = 10
- DHCPOptResLocServer DHCPOpt = 11
- DHCPOptHostname DHCPOpt = 12
- DHCPOptBootfileSize DHCPOpt = 13
- DHCPOptMeritDumpFile DHCPOpt = 14
- DHCPOptDomainName DHCPOpt = 15
- DHCPOptSwapServer DHCPOpt = 16
- DHCPOptRootPath DHCPOpt = 17
- DHCPOptExtensionsPath DHCPOpt = 18
- DHCPOptIPForwarding DHCPOpt = 19
- DHCPOptSourceRouting DHCPOpt = 20
- DHCPOptPolicyFilter DHCPOpt = 21
- DHCPOptDatagramMTU DHCPOpt = 22
- DHCPOptDefaultTTL DHCPOpt = 23
- DHCPOptPathMTUAgingTimeout DHCPOpt = 24
- DHCPOptPathPlateuTableOption DHCPOpt = 25
- DHCPOptInterfaceMTU DHCPOpt = 26
- DHCPOptAllSubsLocal DHCPOpt = 27
- DHCPOptBroadcastAddr DHCPOpt = 28
- DHCPOptMaskDiscovery DHCPOpt = 29
- DHCPOptMaskSupplier DHCPOpt = 30
- DHCPOptRouterDiscovery DHCPOpt = 31
- DHCPOptSolicitAddr DHCPOpt = 32
- DHCPOptStaticRoute DHCPOpt = 33
- DHCPOptARPTrailers DHCPOpt = 34
- DHCPOptARPTimeout DHCPOpt = 35
- DHCPOptEthernetEncap DHCPOpt = 36
- DHCPOptTCPTTL DHCPOpt = 37
- DHCPOptTCPKeepAliveInt DHCPOpt = 38
- DHCPOptTCPKeepAliveGarbage DHCPOpt = 39
- DHCPOptNISDomain DHCPOpt = 40
- DHCPOptNISServers DHCPOpt = 41
- DHCPOptNTPServers DHCPOpt = 42
- DHCPOptVendorOption DHCPOpt = 43
- DHCPOptNetBIOSTCPNS DHCPOpt = 44
- DHCPOptNetBIOSTCPDDS DHCPOpt = 45
- DHCPOptNETBIOSTCPNodeType DHCPOpt = 46
- DHCPOptNetBIOSTCPScope DHCPOpt = 47
- DHCPOptXFontServer DHCPOpt = 48
- DHCPOptXDisplayManager DHCPOpt = 49
- DHCPOptRequestIP DHCPOpt = 50
- DHCPOptLeaseTime DHCPOpt = 51
- DHCPOptExtOptions DHCPOpt = 52
- DHCPOptMessageType DHCPOpt = 53
- DHCPOptServerID DHCPOpt = 54
- DHCPOptParamsRequest DHCPOpt = 55
- DHCPOptMessage DHCPOpt = 56
- DHCPOptMaxMessageSize DHCPOpt = 57
- DHCPOptT1 DHCPOpt = 58
- DHCPOptT2 DHCPOpt = 59
- DHCPOptClassID DHCPOpt = 60
- DHCPOptClientID DHCPOpt = 61
- DHCPOptDomainSearch DHCPOpt = 119
- DHCPOptSIPServers DHCPOpt = 120
- DHCPOptClasslessStaticRoute DHCPOpt = 121
- DHCPOptEnd DHCPOpt = 255
- )
- func (o DHCPOpt) String() string {
- switch o {
- case DHCPOptPad:
- return "(padding)"
- case DHCPOptSubnetMask:
- return "SubnetMask"
- case DHCPOptTimeOffset:
- return "TimeOffset"
- case DHCPOptRouter:
- return "Router"
- case DHCPOptTimeServer:
- return "rfc868"
- case DHCPOptNameServer:
- return "ien116"
- case DHCPOptDNS:
- return "DNS"
- case DHCPOptLogServer:
- return "mitLCS"
- case DHCPOptCookieServer:
- return "CookieServer"
- case DHCPOptLPRServer:
- return "LPRServer"
- case DHCPOptImpressServer:
- return "ImpressServer"
- case DHCPOptResLocServer:
- return "ResourceLocationServer"
- case DHCPOptHostname:
- return "Hostname"
- case DHCPOptBootfileSize:
- return "BootfileSize"
- case DHCPOptMeritDumpFile:
- return "MeritDumpFile"
- case DHCPOptDomainName:
- return "DomainName"
- case DHCPOptSwapServer:
- return "SwapServer"
- case DHCPOptRootPath:
- return "RootPath"
- case DHCPOptExtensionsPath:
- return "ExtensionsPath"
- case DHCPOptIPForwarding:
- return "IPForwarding"
- case DHCPOptSourceRouting:
- return "SourceRouting"
- case DHCPOptPolicyFilter:
- return "PolicyFilter"
- case DHCPOptDatagramMTU:
- return "DatagramMTU"
- case DHCPOptDefaultTTL:
- return "DefaultTTL"
- case DHCPOptPathMTUAgingTimeout:
- return "PathMTUAgingTimeout"
- case DHCPOptPathPlateuTableOption:
- return "PathPlateuTableOption"
- case DHCPOptInterfaceMTU:
- return "InterfaceMTU"
- case DHCPOptAllSubsLocal:
- return "AllSubsLocal"
- case DHCPOptBroadcastAddr:
- return "BroadcastAddress"
- case DHCPOptMaskDiscovery:
- return "MaskDiscovery"
- case DHCPOptMaskSupplier:
- return "MaskSupplier"
- case DHCPOptRouterDiscovery:
- return "RouterDiscovery"
- case DHCPOptSolicitAddr:
- return "SolicitAddr"
- case DHCPOptStaticRoute:
- return "StaticRoute"
- case DHCPOptARPTrailers:
- return "ARPTrailers"
- case DHCPOptARPTimeout:
- return "ARPTimeout"
- case DHCPOptEthernetEncap:
- return "EthernetEncap"
- case DHCPOptTCPTTL:
- return "TCPTTL"
- case DHCPOptTCPKeepAliveInt:
- return "TCPKeepAliveInt"
- case DHCPOptTCPKeepAliveGarbage:
- return "TCPKeepAliveGarbage"
- case DHCPOptNISDomain:
- return "NISDomain"
- case DHCPOptNISServers:
- return "NISServers"
- case DHCPOptNTPServers:
- return "NTPServers"
- case DHCPOptVendorOption:
- return "VendorOption"
- case DHCPOptNetBIOSTCPNS:
- return "NetBIOSOverTCPNS"
- case DHCPOptNetBIOSTCPDDS:
- return "NetBiosOverTCPDDS"
- case DHCPOptNETBIOSTCPNodeType:
- return "NetBIOSOverTCPNodeType"
- case DHCPOptNetBIOSTCPScope:
- return "NetBIOSOverTCPScope"
- case DHCPOptXFontServer:
- return "XFontServer"
- case DHCPOptXDisplayManager:
- return "XDisplayManager"
- case DHCPOptEnd:
- return "(end)"
- case DHCPOptSIPServers:
- return "SipServers"
- case DHCPOptRequestIP:
- return "RequestIP"
- case DHCPOptLeaseTime:
- return "LeaseTime"
- case DHCPOptExtOptions:
- return "ExtOpts"
- case DHCPOptMessageType:
- return "MessageType"
- case DHCPOptServerID:
- return "ServerID"
- case DHCPOptParamsRequest:
- return "ParamsRequest"
- case DHCPOptMessage:
- return "Message"
- case DHCPOptMaxMessageSize:
- return "MaxDHCPSize"
- case DHCPOptT1:
- return "Timer1"
- case DHCPOptT2:
- return "Timer2"
- case DHCPOptClassID:
- return "ClassID"
- case DHCPOptClientID:
- return "ClientID"
- case DHCPOptDomainSearch:
- return "DomainSearch"
- case DHCPOptClasslessStaticRoute:
- return "ClasslessStaticRoute"
- default:
- return "Unknown"
- }
- }
- type DHCPOption struct {
- Type DHCPOpt
- Length uint8
- Data []byte
- }
- func (o DHCPOption) String() string {
- switch o.Type {
- case DHCPOptHostname, DHCPOptMeritDumpFile, DHCPOptDomainName, DHCPOptRootPath,
- DHCPOptExtensionsPath, DHCPOptNISDomain, DHCPOptNetBIOSTCPScope, DHCPOptXFontServer,
- DHCPOptXDisplayManager, DHCPOptMessage, DHCPOptDomainSearch:
- return fmt.Sprintf("Option(%s:%s)", o.Type, string(o.Data))
- case DHCPOptMessageType:
- if len(o.Data) != 1 {
- return fmt.Sprintf("Option(%s:INVALID)", o.Type)
- }
- return fmt.Sprintf("Option(%s:%s)", o.Type, DHCPMsgType(o.Data[0]))
- case DHCPOptSubnetMask, DHCPOptServerID, DHCPOptBroadcastAddr,
- DHCPOptSolicitAddr, DHCPOptRequestIP:
- if len(o.Data) < 4 {
- return fmt.Sprintf("Option(%s:INVALID)", o.Type)
- }
- return fmt.Sprintf("Option(%s:%s)", o.Type, net.IP(o.Data))
- case DHCPOptT1, DHCPOptT2, DHCPOptLeaseTime, DHCPOptPathMTUAgingTimeout,
- DHCPOptARPTimeout, DHCPOptTCPKeepAliveInt:
- if len(o.Data) != 4 {
- return fmt.Sprintf("Option(%s:INVALID)", o.Type)
- }
- return fmt.Sprintf("Option(%s:%d)", o.Type,
- uint32(o.Data[0])<<24|uint32(o.Data[1])<<16|uint32(o.Data[2])<<8|uint32(o.Data[3]))
- case DHCPOptParamsRequest:
- buf := &bytes.Buffer{}
- buf.WriteString(fmt.Sprintf("Option(%s:", o.Type))
- for i, v := range o.Data {
- buf.WriteString(DHCPOpt(v).String())
- if i+1 != len(o.Data) {
- buf.WriteByte(',')
- }
- }
- buf.WriteString(")")
- return buf.String()
- default:
- return fmt.Sprintf("Option(%s:%v)", o.Type, o.Data)
- }
- }
- func NewDHCPOption(t DHCPOpt, data []byte) DHCPOption {
- o := DHCPOption{Type: t}
- if data != nil {
- o.Data = data
- o.Length = uint8(len(data))
- }
- return o
- }
- func (o *DHCPOption) encode(b []byte) error {
- switch o.Type {
- case DHCPOptPad, DHCPOptEnd:
- b[0] = byte(o.Type)
- default:
- b[0] = byte(o.Type)
- b[1] = o.Length
- copy(b[2:], o.Data)
- }
- return nil
- }
- func (o *DHCPOption) decode(data []byte) error {
- if len(data) < 1 {
-
- return DecOptionNotEnoughData
- }
- o.Type = DHCPOpt(data[0])
- switch o.Type {
- case DHCPOptPad, DHCPOptEnd:
- o.Data = nil
- default:
- if len(data) < 2 {
- return DecOptionNotEnoughData
- }
- o.Length = data[1]
- if int(o.Length) > len(data[2:]) {
- return DecOptionMalformed
- }
- o.Data = data[2 : 2+int(o.Length)]
- }
- return nil
- }
- type DHCPv4Error string
- func (d DHCPv4Error) Error() string {
- return string(d)
- }
- const (
-
- DecOptionNotEnoughData = DHCPv4Error("Not enough data to decode")
-
- DecOptionMalformed = DHCPv4Error("Option is malformed")
-
- InvalidMagicCookie = DHCPv4Error("Bad DHCP header")
- )
|