コード例 #1
0
ファイル: udp.go プロジェクト: read-later/gopacket
// SerializeTo writes the serialized form of this layer into the
// SerializationBuffer, implementing gopacket.SerializableLayer.
// See the docs for gopacket.SerializableLayer for more info.
func (u *UDP) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	payload := b.Bytes()
	bytes, err := b.PrependBytes(8)
	if err != nil {
		return err
	}
	binary.BigEndian.PutUint16(bytes, uint16(u.SrcPort))
	binary.BigEndian.PutUint16(bytes[2:], uint16(u.DstPort))
	if opts.FixLengths {
		u.Length = uint16(len(payload)) + 8
	}
	binary.BigEndian.PutUint16(bytes[4:], u.Length)
	if opts.ComputeChecksums {
		// zero out checksum bytes
		bytes[6] = 0
		bytes[7] = 0
		csum, err := u.computeChecksum(b.Bytes(), IPProtocolUDP)
		if err != nil {
			return err
		}
		u.Checksum = csum
	}
	binary.BigEndian.PutUint16(bytes[6:], u.Checksum)
	return nil
}
コード例 #2
0
ファイル: ip6.go プロジェクト: read-later/gopacket
// SerializeTo writes the serialized form of this layer into the
// SerializationBuffer, implementing gopacket.SerializableLayer.
// See the docs for gopacket.SerializableLayer for more info.
func (ip6 *IPv6) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	payload := b.Bytes()
	if ip6.HopByHop != nil {
		return fmt.Errorf("unable to serialize hopbyhop for now")
	}
	bytes, err := b.PrependBytes(40)
	if err != nil {
		return err
	}
	bytes[0] = (ip6.Version << 4) | (ip6.TrafficClass >> 4)
	bytes[1] = (ip6.TrafficClass << 4) | uint8(ip6.FlowLabel>>16)
	binary.BigEndian.PutUint16(bytes[2:], uint16(ip6.FlowLabel))
	if opts.FixLengths {
		ip6.Length = uint16(len(payload))
	}
	binary.BigEndian.PutUint16(bytes[4:], ip6.Length)
	bytes[6] = byte(ip6.NextHeader)
	bytes[7] = byte(ip6.HopLimit)
	if err := ip6.AddressTo16(); err != nil {
		return err
	}
	copy(bytes[8:], ip6.SrcIP)
	copy(bytes[24:], ip6.DstIP)
	return nil
}
コード例 #3
0
ファイル: vxlan.go プロジェクト: ccordes-snaproute/gopacket
// SerializeTo writes the serialized form of this layer into the
// SerializationBuffer, implementing gopacket.SerializableLayer.
// See the docs for gopacket.SerializableLayer for more info.
func (eth *VxlanEthernet) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	if len(eth.DstMAC) != 6 {
		return fmt.Errorf("invalid dst MAC: %v", eth.DstMAC)
	}
	if len(eth.SrcMAC) != 6 {
		return fmt.Errorf("invalid src MAC: %v", eth.SrcMAC)
	}
	payload := b.Bytes()
	bytes, err := b.PrependBytes(14)
	if err != nil {
		return err
	}
	copy(bytes, eth.DstMAC)
	copy(bytes[6:], eth.SrcMAC)
	if eth.Length != 0 || eth.EthernetType == EthernetTypeLLC {
		if opts.FixLengths {
			eth.Length = uint16(len(payload))
		}
		if eth.EthernetType != EthernetTypeLLC {
			return fmt.Errorf("ethernet type %v not compatible with length value %v", eth.EthernetType, eth.Length)
		} else if eth.Length > 0x0600 {
			return fmt.Errorf("invalid ethernet length %v", eth.Length)
		}
		binary.BigEndian.PutUint16(bytes[12:], eth.Length)
	} else {
		binary.BigEndian.PutUint16(bytes[12:], uint16(eth.EthernetType))
	}
	return nil
}
コード例 #4
0
ファイル: sctp.go プロジェクト: cdshann/minimega
// SerializeTo is for gopacket.SerializableLayer.
func (sc SCTPData) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	payload := b.Bytes()
	// Pad the payload to a 32 bit boundary
	if rem := len(payload) % 4; rem != 0 {
		b.AppendBytes(4 - rem)
	}
	length := 16
	bytes, err := b.PrependBytes(length)
	if err != nil {
		return err
	}
	bytes[0] = uint8(sc.Type)
	flags := uint8(0)
	if sc.Unordered {
		flags |= 0x4
	}
	if sc.BeginFragment {
		flags |= 0x2
	}
	if sc.EndFragment {
		flags |= 0x1
	}
	bytes[1] = flags
	binary.BigEndian.PutUint16(bytes[2:4], uint16(length+len(payload)))
	binary.BigEndian.PutUint32(bytes[4:8], sc.TSN)
	binary.BigEndian.PutUint16(bytes[8:10], sc.StreamId)
	binary.BigEndian.PutUint16(bytes[10:12], sc.StreamSequence)
	binary.BigEndian.PutUint32(bytes[12:16], uint32(sc.PayloadProtocol))
	return nil
}
コード例 #5
0
ファイル: tcp.go プロジェクト: cdshann/minimega
// SerializeTo writes the serialized form of this layer into the
// SerializationBuffer, implementing gopacket.SerializableLayer.
// See the docs for gopacket.SerializableLayer for more info.
func (t *TCP) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	var optionLength int
	for _, o := range t.Options {
		switch o.OptionType {
		case 0, 1:
			optionLength += 1
		default:
			optionLength += 2 + len(o.OptionData)
		}
	}
	if opts.FixLengths {
		if rem := optionLength % 4; rem != 0 {
			t.Padding = lotsOfZeros[:4-rem]
		}
		t.DataOffset = uint8((len(t.Padding) + optionLength + 20) / 4)
	}
	bytes, err := b.PrependBytes(20 + optionLength + len(t.Padding))
	if err != nil {
		return err
	}
	binary.BigEndian.PutUint16(bytes, uint16(t.SrcPort))
	binary.BigEndian.PutUint16(bytes[2:], uint16(t.DstPort))
	binary.BigEndian.PutUint32(bytes[4:], t.Seq)
	binary.BigEndian.PutUint32(bytes[8:], t.Ack)
	binary.BigEndian.PutUint16(bytes[12:], t.flagsAndOffset())
	binary.BigEndian.PutUint16(bytes[14:], t.Window)
	binary.BigEndian.PutUint16(bytes[18:], t.Urgent)
	start := 20
	for _, o := range t.Options {
		bytes[start] = byte(o.OptionType)
		switch o.OptionType {
		case 0, 1:
			start++
		default:
			if opts.FixLengths {
				o.OptionLength = uint8(len(o.OptionData) + 2)
			}
			bytes[start+1] = o.OptionLength
			copy(bytes[start+2:start+len(o.OptionData)+2], o.OptionData)
			start += int(o.OptionLength)
		}
	}
	copy(bytes[start:], t.Padding)
	if opts.ComputeChecksums {
		// zero out checksum bytes in current serialization.
		bytes[16] = 0
		bytes[17] = 0
		csum, err := t.computeChecksum(b.Bytes(), IPProtocolTCP)
		if err != nil {
			return err
		}
		t.Checksum = csum
	}
	binary.BigEndian.PutUint16(bytes[16:], t.Checksum)
	return nil
}
コード例 #6
0
ファイル: moldudp64.go プロジェクト: ikravets/ev
func (m *MoldUDP64MessageBlockChained) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) (err error) {
	defer errs.PassE(&err)
	payload := b.Bytes()
	bytes, err := b.PrependBytes(2)
	errs.CheckE(err)
	if opts.FixLengths {
		m.MessageLength = uint16(len(payload))
	}
	binary.BigEndian.PutUint16(bytes, uint16(m.MessageLength))
	return
}
コード例 #7
0
ファイル: ip4.go プロジェクト: cdshann/minimega
// SerializeTo writes the serialized form of this layer into the
// SerializationBuffer, implementing gopacket.SerializableLayer.
func (ip *IPv4) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	optionLength := ip.getIPv4OptionSize()
	bytes, err := b.PrependBytes(20 + int(optionLength))
	if err != nil {
		return err
	}
	if opts.FixLengths {
		ip.IHL = 5 + (optionLength / 4)
		ip.Length = uint16(len(b.Bytes()))
	}
	bytes[0] = (ip.Version << 4) | ip.IHL
	bytes[1] = ip.TOS
	binary.BigEndian.PutUint16(bytes[2:], ip.Length)
	binary.BigEndian.PutUint16(bytes[4:], ip.Id)
	binary.BigEndian.PutUint16(bytes[6:], ip.flagsfrags())
	bytes[8] = ip.TTL
	bytes[9] = byte(ip.Protocol)
	if err := ip.AddressTo4(); err != nil {
		return err
	}
	copy(bytes[12:16], ip.SrcIP)
	copy(bytes[16:20], ip.DstIP)

	curLocation := 20
	// Now, we will encode the options
	for _, opt := range ip.Options {
		switch opt.OptionType {
		case 0:
			// this is the end of option lists
			bytes[curLocation] = 0
			curLocation++
		case 1:
			// this is the padding
			bytes[curLocation] = 1
			curLocation++
		default:
			bytes[curLocation] = opt.OptionType
			bytes[curLocation+1] = opt.OptionLength

			// sanity checking to protect us from buffer overrun
			if len(opt.OptionData) > int(opt.OptionLength-2) {
				return fmt.Errorf("option length is smaller than length of option data")
			}
			copy(bytes[curLocation+2:curLocation+int(opt.OptionLength)], opt.OptionData)
			curLocation += int(opt.OptionLength)
		}
	}

	if opts.ComputeChecksums {
		ip.Checksum = checksum(bytes)
	}
	binary.BigEndian.PutUint16(bytes[10:], ip.Checksum)
	return nil
}
コード例 #8
0
ファイル: suppl.go プロジェクト: skyportsystems/suppl
func (self Dot11NoFCS) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	dot11 := append([]byte{}, b.Bytes()...)
	if err := b.Clear(); err != nil {
		return err
	}
	bytes, err := b.AppendBytes(len(dot11) - 4) // remove FCS
	if err != nil {
		return err
	}
	copy(bytes, dot11)
	return nil
}
コード例 #9
0
ファイル: pppoe.go プロジェクト: hgGeorg/mongo
// SerializeTo writes the serialized form of this layer into the
// SerializationBuffer, implementing gopacket.SerializableLayer.
// See the docs for gopacket.SerializableLayer for more info.
func (p *PPPoE) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	payload := b.Bytes()
	bytes, err := b.PrependBytes(6)
	if err != nil {
		return err
	}
	bytes[0] = (p.Version << 4) | p.Type
	bytes[1] = byte(p.Code)
	binary.BigEndian.PutUint16(bytes[2:], p.SessionId)
	if opts.FixLengths {
		p.Length = uint16(len(payload))
	}
	binary.BigEndian.PutUint16(bytes[4:], p.Length)
	return nil
}
コード例 #10
0
ファイル: icmp4.go プロジェクト: CNDonny/scope
// SerializeTo writes the serialized form of this layer into the
// SerializationBuffer, implementing gopacket.SerializableLayer.
// See the docs for gopacket.SerializableLayer for more info.
func (i *ICMPv4) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	bytes, err := b.PrependBytes(8)
	if err != nil {
		return err
	}
	binary.BigEndian.PutUint16(bytes, uint16(i.TypeCode))
	binary.BigEndian.PutUint16(bytes[4:], i.Id)
	binary.BigEndian.PutUint16(bytes[6:], i.Seq)
	if opts.ComputeChecksums {
		bytes[2] = 0
		bytes[3] = 0
		i.Checksum = tcpipChecksum(b.Bytes(), 0)
	}
	binary.BigEndian.PutUint16(bytes[2:], i.Checksum)
	return nil
}
コード例 #11
0
ファイル: sctp.go プロジェクト: cdshann/minimega
// SerializeTo is for gopacket.SerializableLayer.
func (s SCTP) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	bytes, err := b.PrependBytes(12)
	if err != nil {
		return err
	}
	binary.BigEndian.PutUint16(bytes[0:2], uint16(s.SrcPort))
	binary.BigEndian.PutUint16(bytes[2:4], uint16(s.DstPort))
	binary.BigEndian.PutUint32(bytes[4:8], s.VerificationTag)
	if opts.ComputeChecksums {
		// Note:  MakeTable(Castagnoli) actually only creates the table once, then
		// passes back a singleton on every other call, so this shouldn't cause
		// excessive memory allocation.
		binary.LittleEndian.PutUint32(bytes[8:12], crc32.Checksum(b.Bytes(), crc32.MakeTable(crc32.Castagnoli)))
	}
	return nil
}
コード例 #12
0
ファイル: ip4.go プロジェクト: gusev-vitaliy/gopacket
// SerializeTo writes the serialized form of this layer into the
// SerializationBuffer, implementing gopacket.SerializableLayer.
func (ip *IPv4) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	if len(ip.Options) > 0 {
		return fmt.Errorf("cannot currently serialize IPv4 options")
	}
	bytes, err := b.PrependBytes(20)
	if err != nil {
		return err
	}
	if opts.FixLengths {
		ip.IHL = 5 // Fix when we add support for options.
		ip.Length = uint16(len(b.Bytes()))
	}
	bytes[0] = (ip.Version << 4) | ip.IHL
	bytes[1] = ip.TOS
	binary.BigEndian.PutUint16(bytes[2:], ip.Length)
	binary.BigEndian.PutUint16(bytes[4:], ip.Id)
	binary.BigEndian.PutUint16(bytes[6:], ip.flagsfrags())
	bytes[8] = ip.TTL
	bytes[9] = byte(ip.Protocol)
	if len(ip.SrcIP) != 4 {
		return fmt.Errorf("invalid src IP %v", ip.SrcIP)
	}
	if len(ip.DstIP) != 4 {
		return fmt.Errorf("invalid dst IP %v", ip.DstIP)
	}
	copy(bytes[12:16], ip.SrcIP)
	copy(bytes[16:20], ip.DstIP)
	if opts.ComputeChecksums {
		// Clear checksum bytes
		bytes[10] = 0
		bytes[11] = 0
		// Compute checksum
		var csum uint32
		for i := 0; i < len(bytes); i += 2 {
			csum += uint32(bytes[i]) << 8
			csum += uint32(bytes[i+1])
		}
		ip.Checksum = ^uint16((csum >> 16) + csum)
	}
	binary.BigEndian.PutUint16(bytes[10:], ip.Checksum)
	return nil
}
コード例 #13
0
ファイル: icmp6.go プロジェクト: nplanel/gopacket
// SerializeTo writes the serialized form of this layer into the
// SerializationBuffer, implementing gopacket.SerializableLayer.
// See the docs for gopacket.SerializableLayer for more info.
func (i *ICMPv6) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	if i.TypeBytes == nil {
		i.TypeBytes = lotsOfZeros[:4]
	} else if len(i.TypeBytes) != 4 {
		return fmt.Errorf("invalid type bytes for ICMPv6 packet: %v", i.TypeBytes)
	}
	bytes, err := b.PrependBytes(8)
	if err != nil {
		return err
	}
	i.TypeCode.SerializeTo(bytes)
	copy(bytes[4:8], i.TypeBytes)
	if opts.ComputeChecksums {
		bytes[2] = 0
		bytes[3] = 0
		csum, err := i.computeChecksum(b.Bytes(), IPProtocolICMPv6)
		if err != nil {
			return err
		}
		i.Checksum = csum
	}
	binary.BigEndian.PutUint16(bytes[2:], i.Checksum)
	return nil
}
コード例 #14
0
ファイル: udp.go プロジェクト: CNDonny/scope
// SerializeTo writes the serialized form of this layer into the
// SerializationBuffer, implementing gopacket.SerializableLayer.
// See the docs for gopacket.SerializableLayer for more info.
func (u *UDP) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	var jumbo bool

	payload := b.Bytes()
	if _, ok := u.pseudoheader.(*IPv6); ok {
		if len(payload)+8 > 65535 {
			jumbo = true
		}
	}
	bytes, err := b.PrependBytes(8)
	if err != nil {
		return err
	}
	binary.BigEndian.PutUint16(bytes, uint16(u.SrcPort))
	binary.BigEndian.PutUint16(bytes[2:], uint16(u.DstPort))
	if opts.FixLengths {
		if jumbo {
			u.Length = 0
		} else {
			u.Length = uint16(len(payload)) + 8
		}
	}
	binary.BigEndian.PutUint16(bytes[4:], u.Length)
	if opts.ComputeChecksums {
		// zero out checksum bytes
		bytes[6] = 0
		bytes[7] = 0
		csum, err := u.computeChecksum(b.Bytes(), IPProtocolUDP)
		if err != nil {
			return err
		}
		u.Checksum = csum
	}
	binary.BigEndian.PutUint16(bytes[6:], u.Checksum)
	return nil
}
コード例 #15
0
ファイル: libpkt.go プロジェクト: vvb/netplugin
func SendPacket(ovsDriver *ovsdbDriver.OvsDriver, srcPort string, pkt *Packet, numPkts int) error {

	options = gopacket.SerializeOptions{}
	var buffer gopacket.SerializeBuffer
	handle, err = pcap.OpenLive("port12", snapshot_len, true, pcap.BlockForever)
	if err != nil {
		log.Errorf("openlive: %v", err)
		return err
	}
	defer handle.Close()

	buffer = gopacket.NewSerializeBuffer()
	options.FixLengths = true
	options.ComputeChecksums = true

	sMac, _ := net.ParseMAC(pkt.SrcMAC)
	dMac, _ := net.ParseMAC(pkt.DstMAC)
	ethLayer := &layers.Ethernet{
		SrcMAC: sMac,
		DstMAC: dMac,
	}
	switch {
	case pkt.Arp != nil:
		arpLayer := buildArp(pkt.Arp)
		log.Infof("Sending an ARP packet on %s", srcPort)
		ethLayer.EthernetType = layers.EthernetTypeARP
		gopacket.SerializeLayers(buffer,
			options,
			ethLayer,
			arpLayer)
	case pkt.IPv4 != nil:
		ipLayer := buildIpv4(pkt.IPv4)
		log.Infof("Sending an IPv4 packer on %s", srcPort)
		ethLayer.EthernetType = layers.EthernetTypeIPv4
		gopacket.SerializeLayers(buffer,
			options,
			ethLayer,
			ipLayer)
	case pkt.IPv6 != nil:
		fmt.Println("ipv6")
		log.Infof("Sending an IPv6 packet on %s", srcPort)
		ipLayer := buildIpv6(pkt.IPv6)
		ethLayer.EthernetType = layers.EthernetTypeIPv6
		gopacket.SerializeLayers(buffer,
			options,
			ethLayer,
			ipLayer)
	default:
		ethLayer.EthernetType = 0xFFFF
		log.Infof("Sending an Ethernet packet on %s", srcPort)
		gopacket.SerializeLayers(buffer,
			options,
			ethLayer)
	}

	outgoingPacket := buffer.Bytes()
	for i := 0; i < numPkts; i++ {
		fmt.Println(outgoingPacket)
		handle.WritePacketData(outgoingPacket)
	}

	return err
}
コード例 #16
0
ファイル: gre.go プロジェクト: karamsivia/netplugin
// SerializeTo writes the serialized form of this layer into the SerializationBuffer,
// implementing gopacket.SerializableLayer. See the docs for gopacket.SerializableLayer for more info.
func (g *GRE) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	size := 4
	if g.ChecksumPresent || g.RoutingPresent {
		size += 4
	}
	if g.KeyPresent {
		size += 4
	}
	if g.SeqPresent {
		size += 4
	}
	if g.RoutingPresent {
		r := g.GRERouting
		for r != nil {
			size += 4 + int(r.SRELength)
			r = r.Next
		}
	}
	buf, err := b.PrependBytes(size)
	if err != nil {
		return err
	}
	// Reset any potentially dirty memory in the first 2 bytes, as these use OR to set flags.
	buf[0] = 0
	buf[1] = 0
	if g.ChecksumPresent {
		buf[0] |= 0x80
	}
	if g.RoutingPresent {
		buf[0] |= 0x40
	}
	if g.KeyPresent {
		buf[0] |= 0x20
	}
	if g.SeqPresent {
		buf[0] |= 0x10
	}
	if g.StrictSourceRoute {
		buf[0] |= 0x08
	}
	buf[0] |= g.RecursionControl
	buf[1] |= g.Flags << 3
	buf[1] |= g.Version
	binary.BigEndian.PutUint16(buf[2:4], uint16(g.Protocol))
	offset := 4
	if g.ChecksumPresent || g.RoutingPresent {
		// Don't write the checksum value yet, as we may need to compute it,
		// which requires the entire header be complete.
		// Instead we zeroize the memory in case it is dirty.
		buf[offset] = 0
		buf[offset+1] = 0
		binary.BigEndian.PutUint16(buf[offset+2:offset+4], g.Offset)
		offset += 4
	}
	if g.KeyPresent {
		binary.BigEndian.PutUint32(buf[offset:offset+4], g.Key)
		offset += 4
	}
	if g.SeqPresent {
		binary.BigEndian.PutUint32(buf[offset:offset+4], g.Seq)
		offset += 4
	}
	if g.RoutingPresent {
		sre := g.GRERouting
		for sre != nil {
			binary.BigEndian.PutUint16(buf[offset:offset+2], sre.AddressFamily)
			buf[offset+2] = sre.SREOffset
			buf[offset+3] = sre.SRELength
			copy(buf[offset+4:offset+4+int(sre.SRELength)], sre.RoutingInformation)
			offset += 4 + int(sre.SRELength)
			sre = sre.Next
		}
	}
	if g.ChecksumPresent {
		if opts.ComputeChecksums {
			g.Checksum = tcpipChecksum(b.Bytes(), 0)
		}

		binary.BigEndian.PutUint16(buf[4:6], g.Checksum)
	}
	return nil
}
コード例 #17
0
ファイル: ip6.go プロジェクト: hgGeorg/mongo
// SerializeTo writes the serialized form of this layer into the
// SerializationBuffer, implementing gopacket.SerializableLayer.
// See the docs for gopacket.SerializableLayer for more info.
func (ip6 *IPv6) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	var jumbo bool
	var err error

	payload := b.Bytes()
	pLen := len(payload)
	if pLen > ipv6MaxPayloadLength {
		jumbo = true
		if opts.FixLengths {
			// We need to set the length later because the hop-by-hop header may
			// not exist or else need padding, so pLen may yet change
			addIPv6JumboOption(ip6)
		} else if ip6.HopByHop == nil {
			return fmt.Errorf("Cannot fit payload length of %d into IPv6 packet", pLen)
		} else {
			_, ok, err := getIPv6HopByHopJumboLength(ip6.HopByHop)
			if err != nil {
				return err
			}
			if !ok {
				return fmt.Errorf("Missing jumbo length hop-by-hop option")
			}
		}
	}
	if ip6.HopByHop != nil {
		if ip6.NextHeader != IPProtocolIPv6HopByHop {
			// Just fix it instead of throwing an error
			ip6.NextHeader = IPProtocolIPv6HopByHop
		}
		err = ip6.HopByHop.SerializeTo(b, opts)
		if err != nil {
			return err
		}
		payload = b.Bytes()
		pLen = len(payload)
		if opts.FixLengths && jumbo {
			err := setIPv6PayloadJumboLength(payload)
			if err != nil {
				return err
			}
		}
	}
	if !jumbo && pLen > ipv6MaxPayloadLength {
		return fmt.Errorf("Cannot fit payload into IPv6 header")
	}
	bytes, err := b.PrependBytes(40)
	if err != nil {
		return err
	}
	bytes[0] = (ip6.Version << 4) | (ip6.TrafficClass >> 4)
	bytes[1] = (ip6.TrafficClass << 4) | uint8(ip6.FlowLabel>>16)
	binary.BigEndian.PutUint16(bytes[2:], uint16(ip6.FlowLabel))
	if opts.FixLengths {
		if jumbo {
			ip6.Length = 0
		} else {
			ip6.Length = uint16(pLen)
		}
	}
	binary.BigEndian.PutUint16(bytes[4:], ip6.Length)
	bytes[6] = byte(ip6.NextHeader)
	bytes[7] = byte(ip6.HopLimit)
	if err := ip6.AddressTo16(); err != nil {
		return err
	}
	copy(bytes[8:], ip6.SrcIP)
	copy(bytes[24:], ip6.DstIP)
	return nil
}