Skip to content

Commit 79b4b7d

Browse files
committed
Add support for (optional) population of packet type in afpacket via ancillary data
1 parent 32ee382 commit 79b4b7d

File tree

3 files changed

+38
-4
lines changed

3 files changed

+38
-4
lines changed

afpacket/afpacket.go

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,13 @@ type AncillaryVLAN struct {
5757
VLAN int
5858
}
5959

60+
// AncillaryPktType structures are used to pass the packet type
61+
// as ancillary data via CaptureInfo.
62+
type AncillaryPktType struct {
63+
// The packet type provided by the kernel.
64+
Type uint8
65+
}
66+
6067
// Stats is a set of counters detailing the work TPacket has done so far.
6168
type Stats struct {
6269
// Packets is the total number of packets returned to the caller.
@@ -293,10 +300,11 @@ func (h *TPacket) releaseCurrentPacket() error {
293300
// to old bytes when using ZeroCopyReadPacketData... if you need to keep data past
294301
// the next time you call ZeroCopyReadPacketData, use ReadPacketData, which copies
295302
// the bytes into a new buffer for you.
296-
// tp, _ := NewTPacket(...)
297-
// data1, _, _ := tp.ZeroCopyReadPacketData()
298-
// // do everything you want with data1 here, copying bytes out of it if you'd like to keep them around.
299-
// data2, _, _ := tp.ZeroCopyReadPacketData() // invalidates bytes in data1
303+
//
304+
// tp, _ := NewTPacket(...)
305+
// data1, _, _ := tp.ZeroCopyReadPacketData()
306+
// // do everything you want with data1 here, copying bytes out of it if you'd like to keep them around.
307+
// data2, _, _ := tp.ZeroCopyReadPacketData() // invalidates bytes in data1
300308
func (h *TPacket) ZeroCopyReadPacketData() (data []byte, ci gopacket.CaptureInfo, err error) {
301309
h.mu.Lock()
302310
retry:
@@ -324,6 +332,9 @@ retry:
324332
if vlan >= 0 {
325333
ci.AncillaryData = append(ci.AncillaryData, AncillaryVLAN{vlan})
326334
}
335+
if h.opts.addPktType {
336+
ci.AncillaryData = append(ci.AncillaryData, AncillaryPktType{h.current.getPktType()})
337+
}
327338
atomic.AddInt64(&h.stats.Packets, 1)
328339
h.headerNextNeeded = true
329340
h.mu.Unlock()

afpacket/header.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
// that can be found in the LICENSE file in the root of the source
55
// tree.
66

7+
//go:build linux
78
// +build linux
89

910
package afpacket
@@ -45,6 +46,8 @@ type header interface {
4546
// getIfaceIndex returns the index of the network interface
4647
// where the packet was seen. The index can later be translated to a name.
4748
getIfaceIndex() int
49+
// getPktType returns the packet type
50+
getPktType() uint8
4851
// getVLAN returns the VLAN of a packet if it was provided out-of-band
4952
getVLAN() int
5053
// next moves this header to point to the next packet it contains,
@@ -103,6 +106,10 @@ func (h *v1header) getIfaceIndex() int {
103106
ll := (*C.struct_sockaddr_ll)(unsafe.Pointer(uintptr(unsafe.Pointer(h)) + uintptr(tpAlign(int(C.sizeof_struct_tpacket_hdr)))))
104107
return int(ll.sll_ifindex)
105108
}
109+
func (h *v1header) getPktType() uint8 {
110+
ll := (*C.struct_sockaddr_ll)(unsafe.Pointer(uintptr(unsafe.Pointer(h)) + uintptr(tpAlign(int(C.sizeof_struct_tpacket_hdr)))))
111+
return uint8(ll.sll_pkttype)
112+
}
106113
func (h *v1header) next() bool {
107114
return false
108115
}
@@ -130,6 +137,10 @@ func (h *v2header) getIfaceIndex() int {
130137
ll := (*C.struct_sockaddr_ll)(unsafe.Pointer(uintptr(unsafe.Pointer(h)) + uintptr(tpAlign(int(C.sizeof_struct_tpacket2_hdr)))))
131138
return int(ll.sll_ifindex)
132139
}
140+
func (h *v2header) getPktType() uint8 {
141+
ll := (*C.struct_sockaddr_ll)(unsafe.Pointer(uintptr(unsafe.Pointer(h)) + uintptr(tpAlign(int(C.sizeof_struct_tpacket2_hdr)))))
142+
return uint8(ll.sll_pkttype)
143+
}
133144
func (h *v2header) next() bool {
134145
return false
135146
}
@@ -178,6 +189,10 @@ func (w *v3wrapper) getIfaceIndex() int {
178189
ll := (*C.struct_sockaddr_ll)(unsafe.Pointer(uintptr(unsafe.Pointer(w.packet)) + uintptr(tpAlign(int(C.sizeof_struct_tpacket3_hdr)))))
179190
return int(ll.sll_ifindex)
180191
}
192+
func (w *v3wrapper) getPktType() uint8 {
193+
ll := (*C.struct_sockaddr_ll)(unsafe.Pointer(uintptr(unsafe.Pointer(w.packet)) + uintptr(tpAlign(int(C.sizeof_struct_tpacket3_hdr)))))
194+
return uint8(ll.sll_pkttype)
195+
}
181196
func (w *v3wrapper) next() bool {
182197
w.used++
183198
if w.used >= w.blockhdr.num_pkts {

afpacket/options.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
// that can be found in the LICENSE file in the root of the source
55
// tree.
66

7+
//go:build linux
78
// +build linux
89

910
package afpacket
@@ -106,6 +107,10 @@ type OptPollTimeout time.Duration
106107
// be provided if available.
107108
type OptAddVLANHeader bool
108109

110+
// OptAddPktType enables extraction / population of the packet type as reported by the
111+
// kernel via the AncillaryPktType struct in CaptureInfo.AncillaryData
112+
type OptAddPktType bool
113+
109114
// Default constants used by options.
110115
const (
111116
DefaultFrameSize = 4096 // Default value for OptFrameSize.
@@ -121,6 +126,7 @@ type options struct {
121126
blockSize int
122127
numBlocks int
123128
addVLANHeader bool
129+
addPktType bool
124130
blockTimeout time.Duration
125131
pollTimeout time.Duration
126132
version OptTPacketVersion
@@ -160,6 +166,8 @@ func parseOptions(opts ...interface{}) (ret options, err error) {
160166
ret.socktype = v
161167
case OptAddVLANHeader:
162168
ret.addVLANHeader = bool(v)
169+
case OptAddPktType:
170+
ret.addPktType = bool(v)
163171
default:
164172
err = errors.New("unknown type in options")
165173
return

0 commit comments

Comments
 (0)