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)
	}
}
String returns a string version of a DHCP Option.
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
}