func makePkt()

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
}