package packet import ( "crypto/sha1" "encoding/base64" "encoding/json" "errors" "fmt" "io/fs" "os" ) // FieldValue implements protocol.ProtocolFieldReferencer type FieldValue struct { Value string Generate bool } // Layer implements protocol.ProtocolReferencer type Layer struct { ProtocolName string Values []FieldValue } // Packet contains all layers of a packet and the data in different formats type Packet struct { MetaData Meta data []byte Hex string B64 string Sha1 string Layers []Layer } // NewPacketStructure creates a new empty packet structure func NewPacketStructure() *Packet { p := Packet{} return &p } // UpdateMetaData is still a method stub func UpdateMetaData( pack *Packet, ) { // still empty } // NewPacketLayer creates a new empty Layer structure func NewPacketLayer() *Layer { p := Layer{} return &p } // NewEmptyFieldValue creates a new empty field value func NewEmptyFieldValue() *FieldValue { f := FieldValue{} return &f } // NewFieldValue creates a new prefilled field value func NewFieldValue( value string, ) *FieldValue { f := FieldValue{ Value: value, } return &f } // AppendField appends a new FieldValue to the Layer func (pack *Layer) AppendField(field *FieldValue) int { i := len(pack.Values) pack.Values = append(pack.Values, *field) return i + 1 } // AddField adds a FieldValue at any position func (pack *Layer) AddField(index int, field *FieldValue) { if len(pack.Values) == index { pack.AppendField(field) return } ret := make([]FieldValue, 0) ret = append(ret, pack.Values[:index]...) ret = append(ret, *field) ret = append(ret, pack.Values[index:]...) pack.Values = ret } // AppendLayer appends a Layer to the list of Layers func (pack *Packet) AppendLayer(layer *Layer) { pack.Layers = append(pack.Layers, *layer) } // AddLayer adds a Layer at any position func (pack *Packet) AddLayer(index int, layer *Layer) { if len(pack.Layers) == index { pack.AppendLayer(layer) return } ret := make([]Layer, 0) ret = append(ret, pack.Layers[:index]...) ret = append(ret, *layer) ret = append(ret, pack.Layers[index:]...) pack.Layers = ret } // UpdateField updates a field of a layer func (pack *Layer) UpdateField(e int, field *FieldValue) { pack.Values[e] = *field } // UpdateLayer updates a Layer with a reference to a new Layer func (pack *Packet) UpdateLayer(e int, layer *Layer) { pack.Layers[e] = *layer } // RemoveField removes a field from a Layer func (pack *Layer) RemoveField(e int) { l := len(pack.Values) - 1 ret := make([]FieldValue, l) ret = append(ret, pack.Values[:e]...) ret = append(ret, pack.Values[e+1:]...) pack.Values = ret } // RemoveLayer removes a layer from the list at specified index func (pack *Packet) RemoveLayer(e int) { l := len(pack.Layers) - 1 ret := make([]Layer, l) ret = append(ret, pack.Layers[:e]...) ret = append(ret, pack.Layers[e+1:]...) pack.Layers = ret } // Load a packet from a file path func (pack *Packet) Load(path string) error { data, err := os.ReadFile(path) if err != nil { return err } err = json.Unmarshal(data, pack) pack.data, err = base64.StdEncoding.DecodeString(pack.B64) if err != nil { return err } if pack.Sha1 != fmt.Sprintf("%x", sha1.Sum(pack.data)) { return errors.New("sha1sum does not match") } return err } // UpdateData updates the data holding elements with the actual hex/b64 binary representations and a sha1 hash of it. func (pack *Packet) UpdateData() { pack.Hex = fmt.Sprintf("%x", pack.data) pack.B64 = base64.RawStdEncoding.EncodeToString(pack.data) pack.Sha1 = fmt.Sprintf("%x", sha1.Sum(pack.data)) } // ToJSON returns a JSON string of the packet structure func (pack *Packet) ToJSON() string { pack.UpdateData() data, err := json.MarshalIndent(*pack, "", " ") if err != nil { return "" } return string(data) } // Save the packet structure as JSON file at specified path func (pack *Packet) Save(path string) error { pack.UpdateData() data, err := json.MarshalIndent(*pack, "", " ") if err != nil { return err } err = os.WriteFile(path, data, fs.ModeAppend) return err }