in internal/tcp/tcp.go [154:218]
func makePkt(
af int,
srcAddr net.IP,
dstAddr net.IP,
srcPort layers.TCPPort,
dstPort layers.TCPPort,
dscpv ip.DSCPValue,
flags tcpFlags,
seqNum uint32,
ackNum uint32,
) ([]byte, error) {
buf := gopacket.NewSerializeBuffer()
// gopacket serialization options for IP header are OS specific
optsIP := ip.GetIPLayerOptions()
// When replying with SYN+ACK, a time-stamped payload is included
if flags.syn != false && flags.ack != false {
payloadTime, err := timeNow().MarshalBinary()
if err != nil {
return nil, err
}
payloadLayer := gopacket.Payload(payloadTime)
payloadLayer.SerializeTo(buf, optsTCP)
}
tcpLayer := &layers.TCP{
SrcPort: srcPort,
DstPort: dstPort,
Seq: seqNum,
Ack: ackNum,
DataOffset: uint8(defines.TCPHeaderLength / 4), // TCP Header size in 32-bit words
SYN: flags.syn,
RST: flags.rst,
ACK: flags.ack,
Window: defines.TCPWindowSize,
Checksum: 0, // computed upon serialization
}
// Length of TCP portion is payload length + fixed 20 bytes for Header
tcpLen := defines.TCPHeaderLength + len(buf.Bytes())
ipLayer, err := ip.GetIPHeaderLayer(af, dscpv, uint16(tcpLen), srcAddr, dstAddr)
if err != nil {
return nil, err
}
tcpLayer.SetNetworkLayerForChecksum(ipLayer)
if err = tcpLayer.SerializeTo(buf, optsTCP); err != nil {
return nil, err
}
switch layer := ipLayer.(type) {
case *layers.IPv4:
err = layer.SerializeTo(buf, optsIP)
case *layers.IPv6:
err = layer.SerializeTo(buf, optsIP)
}
if err != nil {
return nil, err
}
return buf.Bytes(), nil
}