func PacketFromBytes(b []byte) (Packet, error) {
	var err error
	if len(b) < 240 {
		return Packet{}, ErrShortPacket
	}
	p := Packet{
		RawPacket: make(RawPacket, len(b)),
	}
	copy(p.RawPacket, b)
	p.OptionMap, err = p.ParseOptions()
	if err != nil {
		return Packet{}, err
	}
	return p, nil
}
PacketFromBytes deserializes the wire-level representation of a DHCP packet
contained in the []byte b into a Packet struct. The function returns an
error if the packet is malformed. The contents of []byte b is copied into
the resulting structure and can be reused after this function has returned.
package dhcpv4
import (
	"errors"
	"net"
)
var (
	ErrShortPacket   = errors.New("dhcpv4: short packet")
	ErrInvalidPacket = errors.New("dhcpv4: invalid packet")
)
type OpCode byte
const (
	BootRequest = OpCode(1)
	BootReply   = OpCode(2)
)
type PacketGetter interface {
	GetHType() uint8
	GetHLen() uint8
	GetXID() []byte
	GetFlags() []byte
	GetCHAddr() []byte
	GetCIAddr() net.IP
	GetYIAddr() net.IP
	GetSIAddr() net.IP
	GetGIAddr() net.IP
}
type PacketSetter interface {
	SetCIAddr(ip net.IP)
	SetYIAddr(ip net.IP)
	SetSIAddr(ip net.IP)
	SetGIAddr(ip net.IP)
}
type RawPacket []byte
func (p RawPacket) Op() []byte     { return p[0:1] }
func (p RawPacket) HType() []byte  { return p[1:2] }
func (p RawPacket) HLen() []byte   { return p[2:3] }
func (p RawPacket) Hops() []byte   { return p[3:4] }
func (p RawPacket) XID() []byte    { return p[4:8] }
func (p RawPacket) Secs() []byte   { return p[8:10] }
func (p RawPacket) Flags() []byte  { return p[10:12] }
func (p RawPacket) CIAddr() []byte { return p[12:16] }
func (p RawPacket) YIAddr() []byte { return p[16:20] }
func (p RawPacket) SIAddr() []byte { return p[20:24] }
func (p RawPacket) GIAddr() []byte { return p[24:28] }
func (p RawPacket) CHAddr() []byte { return p[28:44] }
func (p RawPacket) SName() []byte {
	return p[44:108]
}
func (p RawPacket) File() []byte {
	return p[108:236]
}
func (p RawPacket) Cookie() []byte {
	return p[236:240]
}
func (p RawPacket) Options() []byte {
	return p[240:]
}
func (p RawPacket) GetHType() uint8 {
	return uint8(p.HType()[0])
}
func (p RawPacket) GetHLen() uint8 {
	return uint8(p.HLen()[0])
}
func (p RawPacket) GetXID() []byte {
	var out [4]byte
	copy(out[:], p.XID())
	return out[:]
}
func (p RawPacket) GetFlags() []byte {
	var out [2]byte
	copy(out[:], p.Flags())
	return out[:]
}
func (p RawPacket) GetCHAddr() []byte {
	var out [16]byte
	hlen := p.GetHLen()
	if hlen > 16 {
		hlen = 16
	}
	copy(out[:], p.CHAddr()[0:hlen])
	return out[0:hlen]
}
func (p RawPacket) GetCIAddr() net.IP {
	return net.IP(p.CIAddr())
}
func (p RawPacket) SetCIAddr(ip net.IP) {
	copy(p.CIAddr(), ip)
}
func (p RawPacket) GetYIAddr() net.IP {
	return net.IP(p.YIAddr())
}
func (p RawPacket) SetYIAddr(ip net.IP) {
	copy(p.YIAddr(), ip)
}
func (p RawPacket) GetSIAddr() net.IP {
	return net.IP(p.SIAddr())
}
func (p RawPacket) SetSIAddr(ip net.IP) {
	copy(p.SIAddr(), ip)
}
func (p RawPacket) GetGIAddr() net.IP {
	return net.IP(p.GIAddr())
}
func (p RawPacket) SetGIAddr(ip net.IP) {
	copy(p.GIAddr(), ip)
}
func (p RawPacket) ParseOptions() (OptionMap, error) {
	var err error
	opts := make(OptionMap, 255)
	if err = opts.Deserialize(p.Options(), nil); err != nil {
		return nil, err
	}
	if x := opts[OptionOverload]; len(x) > 0 && x[0]&0x1 != 0 {
		if err = opts.Deserialize(p.File(), nil); err != nil {
			return nil, err
		}
	}
	if x := opts[OptionOverload]; len(x) > 0 && x[0]&0x2 != 0 {
		if err = opts.Deserialize(p.SName(), nil); err != nil {
			return nil, err
		}
	}
	return opts, nil
}
type Packet struct {
	RawPacket
	OptionMap
	ifindex int
}
func NewPacket(o OpCode) Packet {
	p := Packet{
		RawPacket: make([]byte, 240),
		OptionMap: make(OptionMap),
	}
	copy(p.Op(), []byte{byte(o)})
	copy(p.Cookie(), []byte{99, 130, 83, 99})
	return p
}
func NewReply(req PacketGetter) Packet {
	rep := NewPacket(BootReply)
	rep.HType()[0] = 1  
	rep.HLen()[0] = 6   
	copy(rep.XID(), req.GetXID()[:])
	copy(rep.Flags(), req.GetFlags())
	copy(rep.CHAddr(), req.GetCHAddr())
	copy(rep.GIAddr(), req.GetGIAddr())
	return rep
}
func (p Packet) InterfaceIndex() int {
	return p.ifindex
}