From 3f1edad4e6ba0a7876750aea55507fae14d8badf Mon Sep 17 00:00:00 2001 From: Milan Lenco Date: Wed, 11 Oct 2017 16:40:58 +0200 Subject: ODPM 266: Go-libmemif + 2 examples. Change-Id: Icdb9b9eb2314eff6c96afe7996fcf2728291de4a Signed-off-by: Milan Lenco --- .../github.com/google/gopacket/afpacket/header.go | 158 +++++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 vendor/github.com/google/gopacket/afpacket/header.go (limited to 'vendor/github.com/google/gopacket/afpacket/header.go') diff --git a/vendor/github.com/google/gopacket/afpacket/header.go b/vendor/github.com/google/gopacket/afpacket/header.go new file mode 100644 index 0000000..0b9918e --- /dev/null +++ b/vendor/github.com/google/gopacket/afpacket/header.go @@ -0,0 +1,158 @@ +// Copyright 2012 Google, Inc. All rights reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. + +// +build linux + +package afpacket + +import ( + "reflect" + "time" + "unsafe" +) + +// #include +import "C" + +// Our model of handling all TPacket versions is a little hacky, to say the +// least. We use the header interface to handle interactions with the +// tpacket1/tpacket2 packet header AND the tpacket3 block header. The big +// difference is that tpacket3's block header implements the next() call to get +// the next packet within the block, while v1/v2 just always return false. + +type header interface { + // getStatus returns the TPacket status of the current header. + getStatus() int + // clearStatus clears the status of the current header, releasing its + // underlying data back to the kernel for future use with new packets. + // Using the header after calling clearStatus is an error. clearStatus + // should only be called after next() returns false. + clearStatus() + // getTime returns the timestamp for the current packet pointed to by + // the header. + getTime() time.Time + // getData returns the packet data pointed to by the current header. + getData() []byte + // getLength returns the total length of the packet. + getLength() int + // getIfaceIndex returns the index of the network interface + // where the packet was seen. The index can later be translated to a name. + getIfaceIndex() int + // next moves this header to point to the next packet it contains, + // returning true on success (in which case getTime and getData will + // return values for the new packet) or false if there are no more + // packets (in which case clearStatus should be called). + next() bool +} + +func tpAlign(x int) int { + return int((uint(x) + tpacketAlignment - 1) &^ (tpacketAlignment - 1)) +} + +type v1header C.struct_tpacket_hdr +type v2header C.struct_tpacket2_hdr + +func makeSlice(start uintptr, length int) (data []byte) { + slice := (*reflect.SliceHeader)(unsafe.Pointer(&data)) + slice.Data = start + slice.Len = length + slice.Cap = length + return +} + +func (h *v1header) getStatus() int { + return int(h.tp_status) +} +func (h *v1header) clearStatus() { + h.tp_status = 0 +} +func (h *v1header) getTime() time.Time { + return time.Unix(int64(h.tp_sec), int64(h.tp_usec)*1000) +} +func (h *v1header) getData() []byte { + return makeSlice(uintptr(unsafe.Pointer(h))+uintptr(h.tp_mac), int(h.tp_snaplen)) +} +func (h *v1header) getLength() int { + return int(h.tp_len) +} +func (h *v1header) getIfaceIndex() int { + ll := (*C.struct_sockaddr_ll)(unsafe.Pointer(uintptr(unsafe.Pointer(h)) + uintptr(tpAlign(int(C.sizeof_struct_tpacket_hdr))))) + return int(ll.sll_ifindex) +} +func (h *v1header) next() bool { + return false +} + +func (h *v2header) getStatus() int { + return int(h.tp_status) +} +func (h *v2header) clearStatus() { + h.tp_status = 0 +} +func (h *v2header) getTime() time.Time { + return time.Unix(int64(h.tp_sec), int64(h.tp_nsec)) +} +func (h *v2header) getData() []byte { + return makeSlice(uintptr(unsafe.Pointer(h))+uintptr(h.tp_mac), int(h.tp_snaplen)) +} +func (h *v2header) getLength() int { + return int(h.tp_len) +} +func (h *v2header) getIfaceIndex() int { + ll := (*C.struct_sockaddr_ll)(unsafe.Pointer(uintptr(unsafe.Pointer(h)) + uintptr(tpAlign(int(C.sizeof_struct_tpacket2_hdr))))) + return int(ll.sll_ifindex) +} +func (h *v2header) next() bool { + return false +} + +type v3wrapper struct { + block *C.struct_tpacket_block_desc + blockhdr *C.struct_tpacket_hdr_v1 + packet *C.struct_tpacket3_hdr + used C.__u32 +} + +func initV3Wrapper(block unsafe.Pointer) (w v3wrapper) { + w.block = (*C.struct_tpacket_block_desc)(block) + w.blockhdr = (*C.struct_tpacket_hdr_v1)(unsafe.Pointer(&w.block.hdr[0])) + w.packet = (*C.struct_tpacket3_hdr)(unsafe.Pointer(uintptr(block) + uintptr(w.blockhdr.offset_to_first_pkt))) + return +} +func (w *v3wrapper) getStatus() int { + return int(w.blockhdr.block_status) +} +func (w *v3wrapper) clearStatus() { + w.blockhdr.block_status = 0 +} +func (w *v3wrapper) getTime() time.Time { + return time.Unix(int64(w.packet.tp_sec), int64(w.packet.tp_nsec)) +} +func (w *v3wrapper) getData() []byte { + return makeSlice(uintptr(unsafe.Pointer(w.packet))+uintptr(w.packet.tp_mac), int(w.packet.tp_snaplen)) +} +func (w *v3wrapper) getLength() int { + return int(w.packet.tp_len) +} +func (w *v3wrapper) getIfaceIndex() int { + ll := (*C.struct_sockaddr_ll)(unsafe.Pointer(uintptr(unsafe.Pointer(w.packet)) + uintptr(tpAlign(int(C.sizeof_struct_tpacket3_hdr))))) + return int(ll.sll_ifindex) +} +func (w *v3wrapper) next() bool { + w.used++ + if w.used >= w.blockhdr.num_pkts { + return false + } + + next := uintptr(unsafe.Pointer(w.packet)) + if w.packet.tp_next_offset != 0 { + next += uintptr(w.packet.tp_next_offset) + } else { + next += uintptr(tpacketAlign(int(w.packet.tp_snaplen) + int(w.packet.tp_mac))) + } + w.packet = (*C.struct_tpacket3_hdr)(unsafe.Pointer(next)) + return true +} -- cgit 1.2.3-korg