added support for string type
[govpp.git] / vendor / github.com / google / gopacket / afpacket / header.go
1 // Copyright 2012 Google, Inc. All rights reserved.
2 //
3 // Use of this source code is governed by a BSD-style license
4 // that can be found in the LICENSE file in the root of the source
5 // tree.
6
7 // +build linux
8
9 package afpacket
10
11 import (
12         "reflect"
13         "time"
14         "unsafe"
15 )
16
17 // #include <linux/if_packet.h>
18 import "C"
19
20 // Our model of handling all TPacket versions is a little hacky, to say the
21 // least.  We use the header interface to handle interactions with the
22 // tpacket1/tpacket2 packet header AND the tpacket3 block header.  The big
23 // difference is that tpacket3's block header implements the next() call to get
24 // the next packet within the block, while v1/v2 just always return false.
25
26 type header interface {
27         // getStatus returns the TPacket status of the current header.
28         getStatus() int
29         // clearStatus clears the status of the current header, releasing its
30         // underlying data back to the kernel for future use with new packets.
31         // Using the header after calling clearStatus is an error.  clearStatus
32         // should only be called after next() returns false.
33         clearStatus()
34         // getTime returns the timestamp for the current packet pointed to by
35         // the header.
36         getTime() time.Time
37         // getData returns the packet data pointed to by the current header.
38         getData() []byte
39         // getLength returns the total length of the packet.
40         getLength() int
41         // getIfaceIndex returns the index of the network interface
42         // where the packet was seen. The index can later be translated to a name.
43         getIfaceIndex() int
44         // next moves this header to point to the next packet it contains,
45         // returning true on success (in which case getTime and getData will
46         // return values for the new packet) or false if there are no more
47         // packets (in which case clearStatus should be called).
48         next() bool
49 }
50
51 func tpAlign(x int) int {
52         return int((uint(x) + tpacketAlignment - 1) &^ (tpacketAlignment - 1))
53 }
54
55 type v1header C.struct_tpacket_hdr
56 type v2header C.struct_tpacket2_hdr
57
58 func makeSlice(start uintptr, length int) (data []byte) {
59         slice := (*reflect.SliceHeader)(unsafe.Pointer(&data))
60         slice.Data = start
61         slice.Len = length
62         slice.Cap = length
63         return
64 }
65
66 func (h *v1header) getStatus() int {
67         return int(h.tp_status)
68 }
69 func (h *v1header) clearStatus() {
70         h.tp_status = 0
71 }
72 func (h *v1header) getTime() time.Time {
73         return time.Unix(int64(h.tp_sec), int64(h.tp_usec)*1000)
74 }
75 func (h *v1header) getData() []byte {
76         return makeSlice(uintptr(unsafe.Pointer(h))+uintptr(h.tp_mac), int(h.tp_snaplen))
77 }
78 func (h *v1header) getLength() int {
79         return int(h.tp_len)
80 }
81 func (h *v1header) getIfaceIndex() int {
82         ll := (*C.struct_sockaddr_ll)(unsafe.Pointer(uintptr(unsafe.Pointer(h)) + uintptr(tpAlign(int(C.sizeof_struct_tpacket_hdr)))))
83         return int(ll.sll_ifindex)
84 }
85 func (h *v1header) next() bool {
86         return false
87 }
88
89 func (h *v2header) getStatus() int {
90         return int(h.tp_status)
91 }
92 func (h *v2header) clearStatus() {
93         h.tp_status = 0
94 }
95 func (h *v2header) getTime() time.Time {
96         return time.Unix(int64(h.tp_sec), int64(h.tp_nsec))
97 }
98 func (h *v2header) getData() []byte {
99         return makeSlice(uintptr(unsafe.Pointer(h))+uintptr(h.tp_mac), int(h.tp_snaplen))
100 }
101 func (h *v2header) getLength() int {
102         return int(h.tp_len)
103 }
104 func (h *v2header) getIfaceIndex() int {
105         ll := (*C.struct_sockaddr_ll)(unsafe.Pointer(uintptr(unsafe.Pointer(h)) + uintptr(tpAlign(int(C.sizeof_struct_tpacket2_hdr)))))
106         return int(ll.sll_ifindex)
107 }
108 func (h *v2header) next() bool {
109         return false
110 }
111
112 type v3wrapper struct {
113         block    *C.struct_tpacket_block_desc
114         blockhdr *C.struct_tpacket_hdr_v1
115         packet   *C.struct_tpacket3_hdr
116         used     C.__u32
117 }
118
119 func initV3Wrapper(block unsafe.Pointer) (w v3wrapper) {
120         w.block = (*C.struct_tpacket_block_desc)(block)
121         w.blockhdr = (*C.struct_tpacket_hdr_v1)(unsafe.Pointer(&w.block.hdr[0]))
122         w.packet = (*C.struct_tpacket3_hdr)(unsafe.Pointer(uintptr(block) + uintptr(w.blockhdr.offset_to_first_pkt)))
123         return
124 }
125 func (w *v3wrapper) getStatus() int {
126         return int(w.blockhdr.block_status)
127 }
128 func (w *v3wrapper) clearStatus() {
129         w.blockhdr.block_status = 0
130 }
131 func (w *v3wrapper) getTime() time.Time {
132         return time.Unix(int64(w.packet.tp_sec), int64(w.packet.tp_nsec))
133 }
134 func (w *v3wrapper) getData() []byte {
135         return makeSlice(uintptr(unsafe.Pointer(w.packet))+uintptr(w.packet.tp_mac), int(w.packet.tp_snaplen))
136 }
137 func (w *v3wrapper) getLength() int {
138         return int(w.packet.tp_len)
139 }
140 func (w *v3wrapper) getIfaceIndex() int {
141         ll := (*C.struct_sockaddr_ll)(unsafe.Pointer(uintptr(unsafe.Pointer(w.packet)) + uintptr(tpAlign(int(C.sizeof_struct_tpacket3_hdr)))))
142         return int(ll.sll_ifindex)
143 }
144 func (w *v3wrapper) next() bool {
145         w.used++
146         if w.used >= w.blockhdr.num_pkts {
147                 return false
148         }
149
150         next := uintptr(unsafe.Pointer(w.packet))
151         if w.packet.tp_next_offset != 0 {
152                 next += uintptr(w.packet.tp_next_offset)
153         } else {
154                 next += uintptr(tpacketAlign(int(w.packet.tp_snaplen) + int(w.packet.tp_mac)))
155         }
156         w.packet = (*C.struct_tpacket3_hdr)(unsafe.Pointer(next))
157         return true
158 }