Begin documenting things
This commit is contained in:
parent
994d434f52
commit
a91332924a
60
packet.go
60
packet.go
|
@ -9,6 +9,7 @@ import (
|
||||||
"github.com/dirtbags/netshovel/gapstring"
|
"github.com/dirtbags/netshovel/gapstring"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Error returned by convenience methods that are unable to get enough data
|
||||||
type ShortError struct {
|
type ShortError struct {
|
||||||
wanted, available int
|
wanted, available int
|
||||||
}
|
}
|
||||||
|
@ -16,48 +17,60 @@ func (e *ShortError) Error() string {
|
||||||
return fmt.Sprintf("Short read: wanted %d of %d available", e.wanted, e.available)
|
return fmt.Sprintf("Short read: wanted %d of %d available", e.wanted, e.available)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Error returned by convenience methods that are unable to operate on gaps in data
|
||||||
type MissingError struct {
|
type MissingError struct {
|
||||||
}
|
}
|
||||||
func (e *MissingError) Error() string {
|
func (e *MissingError) Error() string {
|
||||||
return "Operation on missing bytes"
|
return "Operation on missing bytes"
|
||||||
}
|
}
|
||||||
|
|
||||||
type PacketFactory func()Packet
|
// A Key,Value Pair
|
||||||
|
type namedField struct {
|
||||||
type NamedField struct {
|
|
||||||
key, value string
|
key, value string
|
||||||
}
|
}
|
||||||
|
|
||||||
type HeaderField struct {
|
// An application protocol header field
|
||||||
|
type headerField struct {
|
||||||
name string
|
name string
|
||||||
bits int
|
bits int
|
||||||
value interface{}
|
value interface{}
|
||||||
order binary.ByteOrder
|
order binary.ByteOrder
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A Packet represents a single application-layer packet
|
||||||
|
//
|
||||||
|
// The Packet struct provides helper methods to assist
|
||||||
|
// with
|
||||||
|
// reverse-engineering new protocols
|
||||||
|
// and
|
||||||
|
// documenting header structure.
|
||||||
type Packet struct {
|
type Packet struct {
|
||||||
Name string
|
|
||||||
Opcode int
|
Opcode int
|
||||||
Description string
|
Description string
|
||||||
When time.Time
|
When time.Time
|
||||||
Payload gapstring.GapString
|
Payload gapstring.GapString
|
||||||
Header []HeaderField
|
header []headerField
|
||||||
Fields []NamedField
|
fields []namedField
|
||||||
}
|
}
|
||||||
|
|
||||||
var never = time.Unix(0, 0)
|
var never = time.Unix(0, 0)
|
||||||
|
|
||||||
|
// Return a new packet
|
||||||
func NewPacket() Packet {
|
func NewPacket() Packet {
|
||||||
return Packet{
|
return Packet{
|
||||||
Opcode: -1,
|
Opcode: -1,
|
||||||
Description: "Undefined",
|
Description: "Undefined",
|
||||||
When: never,
|
When: never,
|
||||||
Payload: gapstring.GapString{},
|
Payload: gapstring.GapString{},
|
||||||
Header: []HeaderField{},
|
header: []headerField{},
|
||||||
Fields: []NamedField{},
|
fields: []namedField{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return a multi-line string describing this packet
|
||||||
|
//
|
||||||
|
// This shows the timestamp, opcode, description, and hex dump.
|
||||||
|
// If you set any values, those are displayed in the order they were set.
|
||||||
func (pkt *Packet) Describe() string {
|
func (pkt *Packet) Describe() string {
|
||||||
out := new(strings.Builder)
|
out := new(strings.Builder)
|
||||||
|
|
||||||
|
@ -74,35 +87,45 @@ func (pkt *Packet) Describe() string {
|
||||||
return out.String()
|
return out.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set a value
|
||||||
|
//
|
||||||
|
// This is intended to be used to note debugging information
|
||||||
|
// that you'd like to see on each packet.
|
||||||
func (pkt *Packet) Set(key, value string) {
|
func (pkt *Packet) Set(key, value string) {
|
||||||
pkt.Fields = append(pkt.Fields, NamedField{key, value})
|
pkt.fields = append(pkt.fields, namedField{key, value})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set a string value, displaying its Go string representation
|
||||||
func (pkt *Packet) SetString(key, value string) {
|
func (pkt *Packet) SetString(key, value string) {
|
||||||
pkt.Set(key, fmt.Sprintf("%#v", value))
|
pkt.Set(key, fmt.Sprintf("%#v", value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set an int value, displaying its decimal and hexadecimal representations
|
||||||
func (pkt *Packet) SetInt(key string, value int) {
|
func (pkt *Packet) SetInt(key string, value int) {
|
||||||
pkt.Set(key, fmt.Sprintf("%d == 0x%x", value, value))
|
pkt.Set(key, fmt.Sprintf("%d == 0x%x", value, value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set an unsigned int value, displaying its decimal and hexadecimal representations
|
||||||
func (pkt *Packet) SetUint(key string, value uint) {
|
func (pkt *Packet) SetUint(key string, value uint) {
|
||||||
pkt.Set(key, fmt.Sprintf("%d == 0x%x", value, value))
|
pkt.Set(key, fmt.Sprintf("%d == 0x%x", value, value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set an Unt32 value, displaying its decimal and 0-padded hexadecimal representations
|
||||||
func (pkt *Packet) SetUint32(key string, value uint32) {
|
func (pkt *Packet) SetUint32(key string, value uint32) {
|
||||||
pkt.Set(key, fmt.Sprintf("%d == 0x%04x", value, value))
|
pkt.Set(key, fmt.Sprintf("%d == 0x%04x", value, value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set an []byte value, displaying the hex encoding of the bytes
|
||||||
func (pkt *Packet) SetBytes(key string, value []byte) {
|
func (pkt *Packet) SetBytes(key string, value []byte) {
|
||||||
pkt.Set(key, hex.EncodeToString(value))
|
pkt.Set(key, hex.EncodeToString(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set a GapString value, displaying the hex encoding and runes encoding (like a hex dump)
|
||||||
func (pkt *Packet) SetGapString(key string, value gapstring.GapString) {
|
func (pkt *Packet) SetGapString(key string, value gapstring.GapString) {
|
||||||
pkt.Set(key, fmt.Sprintf("%s %s", value.HexString(), value.Runes()))
|
pkt.Set(key, fmt.Sprintf("%s %s", value.HexString(), value.Runes()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Peel octets bytes off of the Payload, returning those bytes
|
||||||
func (pkt *Packet) Peel(octets int) ([]byte, error) {
|
func (pkt *Packet) Peel(octets int) ([]byte, error) {
|
||||||
pllen := pkt.Payload.Length()
|
pllen := pkt.Payload.Length()
|
||||||
if octets > pllen {
|
if octets > pllen {
|
||||||
|
@ -118,16 +141,18 @@ func (pkt *Packet) Peel(octets int) ([]byte, error) {
|
||||||
return b, nil
|
return b, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add a field to the header field description
|
||||||
func (pkt *Packet) AddHeaderField(order binary.ByteOrder, name string, bits int, value interface{}) {
|
func (pkt *Packet) AddHeaderField(order binary.ByteOrder, name string, bits int, value interface{}) {
|
||||||
h := HeaderField{
|
h := headerField{
|
||||||
name: name,
|
name: name,
|
||||||
bits: bits,
|
bits: bits,
|
||||||
value: value,
|
value: value,
|
||||||
order: order,
|
order: order,
|
||||||
}
|
}
|
||||||
pkt.Header = append(pkt.Header, h)
|
pkt.header = append(pkt.header, h)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Peel from Payload an unsigned integer of size bits, adding it to the header field list
|
||||||
func (pkt *Packet) readUint(order binary.ByteOrder, bits int, name string) (interface{}, error) {
|
func (pkt *Packet) readUint(order binary.ByteOrder, bits int, name string) (interface{}, error) {
|
||||||
switch bits {
|
switch bits {
|
||||||
case 8:
|
case 8:
|
||||||
|
@ -155,11 +180,12 @@ func (pkt *Packet) readUint(order binary.ByteOrder, bits int, name string) (inte
|
||||||
case 64:
|
case 64:
|
||||||
value = order.Uint64(b)
|
value = order.Uint64(b)
|
||||||
}
|
}
|
||||||
pkt.AddHeaderField(order, name, bits, value)
|
pkt.AddheaderField(order, name, bits, value)
|
||||||
|
|
||||||
return value, nil
|
return value, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Peel off a uint64, little-endian
|
||||||
func (pkt *Packet) Uint64LE(name string) (uint64, error) {
|
func (pkt *Packet) Uint64LE(name string) (uint64, error) {
|
||||||
value, err := pkt.readUint(binary.LittleEndian, 64, name)
|
value, err := pkt.readUint(binary.LittleEndian, 64, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -168,6 +194,7 @@ func (pkt *Packet) Uint64LE(name string) (uint64, error) {
|
||||||
return value.(uint64), err
|
return value.(uint64), err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Peel off a uint32, little-endian
|
||||||
func (pkt *Packet) Uint32LE(name string) (uint32, error) {
|
func (pkt *Packet) Uint32LE(name string) (uint32, error) {
|
||||||
value, err := pkt.readUint(binary.LittleEndian, 32, name)
|
value, err := pkt.readUint(binary.LittleEndian, 32, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -176,6 +203,7 @@ func (pkt *Packet) Uint32LE(name string) (uint32, error) {
|
||||||
return value.(uint32), err
|
return value.(uint32), err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Peel off a uint16, little-endian
|
||||||
func (pkt *Packet) Uint16LE(name string) (uint16, error) {
|
func (pkt *Packet) Uint16LE(name string) (uint16, error) {
|
||||||
value, err := pkt.readUint(binary.LittleEndian, 16, name)
|
value, err := pkt.readUint(binary.LittleEndian, 16, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -184,6 +212,7 @@ func (pkt *Packet) Uint16LE(name string) (uint16, error) {
|
||||||
return value.(uint16), err
|
return value.(uint16), err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Peel off a uint64, big-endian
|
||||||
func (pkt *Packet) Uint64BE(name string) (uint64, error) {
|
func (pkt *Packet) Uint64BE(name string) (uint64, error) {
|
||||||
value, err := pkt.readUint(binary.BigEndian, 64, name)
|
value, err := pkt.readUint(binary.BigEndian, 64, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -192,6 +221,7 @@ func (pkt *Packet) Uint64BE(name string) (uint64, error) {
|
||||||
return value.(uint64), err
|
return value.(uint64), err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Peel off a uint32, big-endian
|
||||||
func (pkt *Packet) Uint32BE(name string) (uint32, error) {
|
func (pkt *Packet) Uint32BE(name string) (uint32, error) {
|
||||||
value, err := pkt.readUint(binary.BigEndian, 32, name)
|
value, err := pkt.readUint(binary.BigEndian, 32, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -200,6 +230,7 @@ func (pkt *Packet) Uint32BE(name string) (uint32, error) {
|
||||||
return value.(uint32), err
|
return value.(uint32), err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Peel off a uint16, big-endian
|
||||||
func (pkt *Packet) Uint16BE(name string) (uint16, error) {
|
func (pkt *Packet) Uint16BE(name string) (uint16, error) {
|
||||||
value, err := pkt.readUint(binary.BigEndian, 16, name)
|
value, err := pkt.readUint(binary.BigEndian, 16, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -208,6 +239,7 @@ func (pkt *Packet) Uint16BE(name string) (uint16, error) {
|
||||||
return value.(uint16), err
|
return value.(uint16), err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Peel off a uint8 (aka byte)
|
||||||
func (pkt *Packet) Uint8(name string) (uint8, error) {
|
func (pkt *Packet) Uint8(name string) (uint8, error) {
|
||||||
value, err := pkt.readUint(binary.BigEndian, 8, name)
|
value, err := pkt.readUint(binary.BigEndian, 8, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
Loading…
Reference in New Issue