Reputation: 1763
Try to use gopacket to create an Ethernet packet (ARP, BGP, UDP, TCP) and get the header bytes and length of it.
Try to play with the example as below, try to list all layers and find the payload location then workout the total header length and bytes:
package main
import (
"fmt"
"net"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
)
func main() {
var (
buffer gopacket.SerializeBuffer
options gopacket.SerializeOptions
)
// Create the layers
ethernetLayer := &layers.Ethernet{
SrcMAC: net.HardwareAddr{0xff, 0xaa, 0xfa, 0xaa, 0xff, 0xaa},
DstMAC: net.HardwareAddr{0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd},
EthernetType: layers.EthernetTypeIPv4,
}
ipLayer := &layers.IPv4{
SrcIP: net.IP{192, 168, 1, 3},
DstIP: net.IP{8, 8, 8, 8},
// Version: 4,
// IHL: 5,
Length: 24,
}
tcpLayer := &layers.TCP{
SrcPort: layers.TCPPort(4321),
DstPort: layers.TCPPort(80),
}
fmt.Println(tcpLayer)
payload := []byte{10, 20, 30, 40, 50, 60}
buffer = gopacket.NewSerializeBuffer()
gopacket.SerializeLayers(buffer, options, ethernetLayer, ipLayer, tcpLayer, gopacket.Payload(payload))
outgoingPacket := buffer.Bytes()
packet := gopacket.NewPacket(outgoingPacket, layers.LayerTypeEthernet, gopacket.Default)
for _, layer := range packet.Layers() {
fmt.Println("Packet layer:", layer.LayerType())
}
}
I got the error as below:
Packet layer: Ethernet
Packet layer: IPv4
Packet layer: DecodeFailure
Did I do anything wrong there?
Can anyone give me any idea how can I get the header bytes?
Upvotes: 3
Views: 2026
Reputation: 1516
Firstly, as implied by your commented out IPv4 fields, layer.Error()
contains more information:
if withErr, ok := layer.(interface{ Error() error }); ok {
fmt.Pritnln(withError.Error())
}
In this case, when the IHL field is set to 5, which denotes the header length in 4 byte words. Since you specified a length of 24, there is a mismatch between the calculated length in IHL and the supplied length and gopacket
crashes trying to parse that as an IPv6 packet. You can adjust the length to 20 and the header length to 5 in which case it parses without error, but that does not contain the tcp fields.
gopacket
is not really intended for generation of packets, but for parsing captured ones.
If you really want to do that manually, I suggest you read the relevant RFCs and make sure you cover the various options, calculate checksums, set protocol (6 for tcp), correct length (tcp packets actually have a 32 byte header if I'm not mistaken), etc, which is quite involved.
Under normal circumstances this should all be taken care of by your operating system's sockets. Why are you attempting to generate this manually?
Upvotes: 0