@@ -35,6 +35,9 @@ import (
35
35
"fmt"
36
36
"github.com/google/gopacket"
37
37
"github.com/google/gopacket/layers"
38
+ "os"
39
+ "sync"
40
+ "time"
38
41
"unsafe"
39
42
)
40
43
@@ -61,6 +64,7 @@ type NFQueue struct {
61
64
qh * C.struct_nfq_q_handle
62
65
fd C.int
63
66
packets chan NFPacket
67
+ idx uint32
64
68
}
65
69
66
70
//Verdict for a packet
@@ -79,6 +83,9 @@ const (
79
83
NF_DEFAULT_PACKET_SIZE uint32 = 0xffff
80
84
)
81
85
86
+ var theTable = make (map [uint32 ]* chan NFPacket , 0 )
87
+ var theTabeLock sync.RWMutex
88
+
82
89
//Create and bind to queue specified by queueId
83
90
func NewNFQueue (queueId uint16 , maxPacketsInQueue uint32 , packetSize uint32 ) (* NFQueue , error ) {
84
91
var nfq = NFQueue {}
@@ -98,7 +105,11 @@ func NewNFQueue(queueId uint16, maxPacketsInQueue uint32, packetSize uint32) (*N
98
105
}
99
106
100
107
nfq .packets = make (chan NFPacket )
101
- if nfq .qh , err = C .CreateQueue (nfq .h , C .u_int16_t (queueId ), unsafe .Pointer (& nfq .packets )); err != nil || nfq .qh == nil {
108
+ nfq .idx = uint32 (time .Now ().UnixNano ())
109
+ theTabeLock .Lock ()
110
+ theTable [nfq .idx ] = & nfq .packets
111
+ theTabeLock .Unlock ()
112
+ if nfq .qh , err = C .CreateQueue (nfq .h , C .u_int16_t (queueId ), C .u_int32_t (nfq .idx )); err != nil || nfq .qh == nil {
102
113
C .nfq_close (nfq .h )
103
114
return nil , fmt .Errorf ("Error binding to queue: %v\n " , err )
104
115
}
@@ -130,6 +141,9 @@ func NewNFQueue(queueId uint16, maxPacketsInQueue uint32, packetSize uint32) (*N
130
141
func (nfq * NFQueue ) Close () {
131
142
C .nfq_destroy_queue (nfq .qh )
132
143
C .nfq_close (nfq .h )
144
+ theTabeLock .Lock ()
145
+ delete (theTable , nfq .idx )
146
+ theTabeLock .Unlock ()
133
147
}
134
148
135
149
//Get the channel for packets
@@ -142,15 +156,23 @@ func (nfq *NFQueue) run() {
142
156
}
143
157
144
158
//export go_callback
145
- func go_callback (queueId C.int , data * C.uchar , len C.int , cb * chan NFPacket ) Verdict {
159
+ func go_callback (queueId C.int , data * C.uchar , len C.int , idx uint32 ) Verdict {
146
160
xdata := C .GoBytes (unsafe .Pointer (data ), len )
147
161
packet := gopacket .NewPacket (xdata , layers .LayerTypeIPv4 , gopacket.DecodeOptions {Lazy : true , NoCopy : true })
148
162
p := NFPacket {verdictChannel : make (chan Verdict ), Packet : packet }
163
+ theTabeLock .RLock ()
164
+ cb , ok := theTable [idx ]
165
+ theTabeLock .RUnlock ()
166
+ if ! ok {
167
+ fmt .Fprintf (os .Stderr , "Dropping, unexpectedly due to bad idx=%d\n " , idx )
168
+ return NF_DROP
169
+ }
149
170
select {
150
171
case (* cb ) <- p :
151
172
v := <- p .verdictChannel
152
173
return v
153
174
default :
175
+ fmt .Fprintf (os .Stderr , "Dropping, unexpectedly due to no recv, idx=%d\n " , idx )
154
176
return NF_DROP
155
177
}
156
178
}
0 commit comments