// 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 }
// 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 }
// 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 }
// 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 }
// 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 }
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 }
// 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 }
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 }
// 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 }
// 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 }
// 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 }
// 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 }
// 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 }
// 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 }
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 }
// 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 }
// 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 }