Skip to content

Commit 5190bdd

Browse files
committed
More error checks, use lru instead fifo
1 parent b553f73 commit 5190bdd

File tree

3 files changed

+79
-75
lines changed

3 files changed

+79
-75
lines changed

Diff for: decoder/decoder.go

+32-39
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@ import (
55
"hash"
66
"os"
77
"strconv"
8-
"time"
98

10-
"github.com/allegro/bigcache"
119
"github.com/cespare/xxhash"
1210
"github.com/google/gopacket"
1311
"github.com/google/gopacket/layers"
@@ -32,7 +30,8 @@ type Decoder struct {
3230
UDPFlow gopacket.Flow
3331
SIPHash hash.Hash64
3432
SIPCache *lru.Cache
35-
RTCPCache *bigcache.BigCache
33+
SDPCache *lru.Cache
34+
RTCPCache *lru.Cache
3635
}
3736

3837
type Packet struct {
@@ -56,37 +55,21 @@ func NewDecoder() *Decoder {
5655
host = "sniffer"
5756
}
5857

59-
sh := xxhash.New()
58+
hSIP := xxhash.New()
6059

61-
sc, err := lru.New(8000)
60+
cSIP, err := lru.New(2000)
6261
if err != nil {
63-
logp.Err("lru %v", err)
62+
logp.Err("SIPCache %v", err)
6463
}
6564

66-
rcConf := bigcache.Config{
67-
// number of shards (must be a power of 2)
68-
Shards: 1024,
69-
// time after which entry can be evicted
70-
LifeWindow: 180 * time.Minute,
71-
// rps * lifeWindow, used only in initial memory allocation
72-
MaxEntriesInWindow: 1000 * 180 * 60,
73-
// max entry size in bytes, used only in initial memory allocation
74-
MaxEntrySize: 300,
75-
// prints information about additional memory allocation
76-
Verbose: false,
77-
// cache will not allocate more memory than this limit, value in MB
78-
// if value is reached then the oldest entries can be overridden for the new ones
79-
// 0 value means no size limit
80-
HardMaxCacheSize: 512,
81-
// callback fired when the oldest entry is removed because of its
82-
// expiration time or no space left for the new entry. Default value is nil which
83-
// means no callback and it prevents from unwrapping the oldest entry.
84-
OnRemove: nil,
65+
cSDP, err := lru.New(10000)
66+
if err != nil {
67+
logp.Err("SDPCache %v", err)
8568
}
8669

87-
rc, err := bigcache.NewBigCache(rcConf)
70+
cRTCP, err := lru.New(10000)
8871
if err != nil {
89-
logp.Err("bigcache %v", err)
72+
logp.Err("RTCPCache %v", err)
9073
}
9174

9275
d := &Decoder{
@@ -99,9 +82,10 @@ func NewDecoder() *Decoder {
9982
tcpCount: 0,
10083
dnsCount: 0,
10184
unknownCount: 0,
102-
SIPHash: sh,
103-
SIPCache: sc,
104-
RTCPCache: rc,
85+
SIPHash: hSIP,
86+
SIPCache: cSIP,
87+
SDPCache: cSDP,
88+
RTCPCache: cRTCP,
10589
}
10690
go d.flushFrag()
10791
go d.printStats()
@@ -190,7 +174,7 @@ func (d *Decoder) Process(data []byte, ci *gopacket.CaptureInfo) (*Packet, error
190174

191175
if config.Cfg.Mode == "SIPRTCP" {
192176
d.cacheSDPIPPort(udp.Payload)
193-
if (udp.Payload[0]&0xc0)>>6 == 2 && (udp.Payload[1] == 200 || udp.Payload[1] == 201) {
177+
if (udp.Payload[0]&0xc0)>>6 == 2 && udp.SrcPort%2 != 0 && udp.DstPort%2 != 0 && (udp.Payload[1] == 200 || udp.Payload[1] == 201) {
194178
pkt.Payload, pkt.CorrelationID, pkt.Type = d.correlateRTCP(udp.Payload)
195179
}
196180
}
@@ -276,23 +260,32 @@ func (d *Decoder) cacheSDPIPPort(payload []byte) {
276260
logp.Warn("Couldn't find end of Call-ID in '%s'", string(restID))
277261
}
278262
}
279-
d.RTCPCache.Set(SDPIP+RTCPPort, callID)
263+
d.SDPCache.Add(SDPIP+RTCPPort, callID)
280264
}
281265
}
282266

283267
func (d *Decoder) correlateRTCP(payload []byte) ([]byte, []byte, byte) {
284268
jsonRTCP, err := protos.ParseRTCP(payload)
285269
if err != nil {
286270
logp.Warn("%v", err)
287-
return nil, nil, 0
271+
if jsonRTCP == nil {
272+
return nil, nil, 0
273+
}
288274
}
289275

290-
corrID, err := d.RTCPCache.Get(d.IPFlow.Src().String() + d.UDPFlow.Src().String())
291-
if err != nil {
292-
logp.Warn("%v", err)
293-
return nil, nil, 0
276+
if corrID, ok := d.SDPCache.Get(d.IPFlow.Src().String() + d.UDPFlow.Src().String()); ok {
277+
logp.Debug("decoder", "SDPCache RTCP JSON payload: %s", string(jsonRTCP))
278+
d.RTCPCache.Add(d.IPFlow.Src().String()+d.UDPFlow.Src().String(), corrID)
279+
//fmt.Println(string(jsonRTCP))
280+
//fmt.Println(string(corrID.([]byte)))
281+
return jsonRTCP, corrID.([]byte), 5
282+
} else if corrID, ok := d.RTCPCache.Get(d.IPFlow.Src().String() + d.UDPFlow.Src().String()); ok {
283+
logp.Debug("decoder", "RTCPCache RTCP JSON payload: %s", string(jsonRTCP))
284+
d.RTCPCache.Add(d.IPFlow.Src().String()+d.UDPFlow.Src().String(), corrID)
285+
return jsonRTCP, corrID.([]byte), 5
286+
} else {
287+
logp.Warn("Couldn't find RTCP correlation value for key=%v", d.IPFlow.Src().String()+d.UDPFlow.Src().String())
294288
}
295289

296-
logp.Debug("decoder", "RTCP JSON payload: %s", string(jsonRTCP))
297-
return jsonRTCP, corrID, 5
290+
return nil, nil, 0
298291
}

Diff for: protos/rtcp.go

+43-36
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package protos
22

33
import (
44
"encoding/binary"
5+
"encoding/hex"
56
"encoding/json"
67
"fmt"
78

@@ -177,32 +178,37 @@ func (rp *RTCP_Packet) MarshalJSON() ([]byte, error) {
177178
func ParseRTCP(data []byte) ([]byte, error) {
178179
dataLen := len(data)
179180
if dataLen < 28 {
180-
return nil, fmt.Errorf("Useless data inside RTCP packet='%s' length=%d", string(data), dataLen)
181+
return nil, fmt.Errorf("Fishy RTCP packet length=%d in packet:\n%v\n", dataLen, hex.Dump(data))
181182
}
183+
var err error
182184
pkt := &RTCP_Packet{}
185+
rtcpPkt := []byte{}
183186
offset := 0
184187

185188
for dataLen > 0 {
186189
if dataLen < 4 || dataLen > 576 {
187-
return nil, fmt.Errorf("Fishy RTCP packet=%v length=%d", data, dataLen)
190+
return nil, fmt.Errorf("Fishy RTCP packet length=%d in packet:\n%v\n", dataLen, hex.Dump(data))
188191
}
189192

190193
//version := (data[offset] & 0xc0) >> 6
191194
//padding := (data[offset] & 0x20) >> 5
192-
receptionReportCount := data[offset] & 0x1f
193-
RTCPType := data[offset+1]
194-
RTCPLength := binary.BigEndian.Uint16(data[offset+2:]) * 4
195-
195+
receptionReportCount := int(data[offset] & 0x1f)
196+
RTCPType := int(data[offset+1])
197+
RTCPLength := int(binary.BigEndian.Uint16(data[offset+2:]) * 4)
196198
offset += 4
197199

198200
if receptionReportCount < 0 || receptionReportCount > 4 {
199-
return nil, fmt.Errorf("Fishy RTCP receptionReportCount=%d", receptionReportCount)
201+
return rtcpPkt, fmt.Errorf("Fishy RTCP receptionReportCount=%v type=%d length=%d offset=%d in packet:\n%v", receptionReportCount, RTCPType, dataLen, offset, hex.Dump(data))
202+
} else if RTCPLength > dataLen {
203+
return rtcpPkt, fmt.Errorf("Fishy RTCP report length=%d in packet:\n%v", RTCPLength, hex.Dump(data))
204+
} else if RTCPType < 200 || RTCPType > 207 {
205+
return rtcpPkt, fmt.Errorf("Fishy RTCP type=%d in packet:\n%v", RTCPType, hex.Dump(data))
200206
}
201207

202208
switch RTCPType {
203209
case TYPE_RTCP_SR:
204-
if RTCPLength < 24 {
205-
return nil, fmt.Errorf("To small RTCP packet=%v length=%d type=%d", data[offset:RTCPLength], RTCPLength, RTCPType)
210+
if RTCPLength < 24 || offset+24 > len(data) {
211+
return rtcpPkt, fmt.Errorf("Fishy RTCP packet=%v length=%d type=%d offset=%d", data, RTCPLength, RTCPType, offset)
206212
}
207213

208214
pkt.Ssrc = binary.BigEndian.Uint32(data[offset:])
@@ -213,9 +219,9 @@ func ParseRTCP(data []byte) ([]byte, error) {
213219
pkt.SenderInformation.Octet_count = binary.BigEndian.Uint32(data[offset+20:])
214220
offset += 24
215221

216-
if receptionReportCount > 0 && RTCPLength >= 24 {
222+
if receptionReportCount > 0 && RTCPLength >= 24 && offset+24 <= len(data) {
217223
tmpReportBlocks := make([]RTCP_report_block, receptionReportCount)
218-
for i := 0; i < int(receptionReportCount); i++ {
224+
for i := 0; i < receptionReportCount; i++ {
219225
tmpReportBlocks[i].SourceSsrc = binary.BigEndian.Uint32(data[offset:])
220226
tmpReportBlocks[i].Fraction_lost = data[offset+4]
221227
var cumBuf [4]byte
@@ -225,25 +231,29 @@ func ParseRTCP(data []byte) ([]byte, error) {
225231
tmpReportBlocks[i].Jitter = binary.BigEndian.Uint32(data[offset+12:])
226232
tmpReportBlocks[i].LastSR = binary.BigEndian.Uint32(data[offset+16:])
227233
tmpReportBlocks[i].Delay_last_SR = binary.BigEndian.Uint32(data[offset+20:])
228-
tmpReportBlocks[i].ReportCount = receptionReportCount
229-
tmpReportBlocks[i].RTCPType = RTCPType
234+
tmpReportBlocks[i].ReportCount = uint8(receptionReportCount)
235+
tmpReportBlocks[i].RTCPType = uint8(RTCPType)
230236
offset += 24
231237
RTCPLength -= 24
232238
pkt.ReportBlocks = pkt.AddReportBlock(tmpReportBlocks[i])
233239
}
234240
}
241+
rtcpPkt, err = pkt.MarshalJSON()
242+
if err != nil {
243+
return nil, err
244+
}
235245

236246
case TYPE_RTCP_RR:
237-
if RTCPLength < 4 {
238-
return nil, fmt.Errorf("To small RTCP packet=%v length=%d type=%d", data[offset:RTCPLength], RTCPLength, RTCPType)
247+
if RTCPLength < 4 || offset+4 > len(data) {
248+
return rtcpPkt, fmt.Errorf("Fishy RTCP packet=%v length=%d type=%d offset=%d", data, RTCPLength, RTCPType, offset)
239249
}
240250

241251
pkt.Ssrc = binary.BigEndian.Uint32(data[offset:])
242252
offset += 4
243253

244-
if receptionReportCount > 0 && RTCPLength >= 24 {
254+
if receptionReportCount > 0 && RTCPLength >= 24 && offset+24 <= len(data) {
245255
tmpReportBlocks := make([]RTCP_report_block, receptionReportCount)
246-
for i := 0; i < int(receptionReportCount); i++ {
256+
for i := 0; i < receptionReportCount; i++ {
247257
tmpReportBlocks[i].SourceSsrc = binary.BigEndian.Uint32(data[offset:])
248258
tmpReportBlocks[i].Fraction_lost = data[offset+4]
249259
var cumBuf [4]byte
@@ -253,39 +263,36 @@ func ParseRTCP(data []byte) ([]byte, error) {
253263
tmpReportBlocks[i].Jitter = binary.BigEndian.Uint32(data[offset+12:])
254264
tmpReportBlocks[i].LastSR = binary.BigEndian.Uint32(data[offset+16:])
255265
tmpReportBlocks[i].Delay_last_SR = binary.BigEndian.Uint32(data[offset+20:])
256-
tmpReportBlocks[i].ReportCount = receptionReportCount
257-
tmpReportBlocks[i].RTCPType = RTCPType
266+
tmpReportBlocks[i].ReportCount = uint8(receptionReportCount)
267+
tmpReportBlocks[i].RTCPType = uint8(RTCPType)
258268
offset += 24
259269
RTCPLength -= 24
260270
pkt.ReportBlocks = pkt.AddReportBlock(tmpReportBlocks[i])
261271
}
262272
}
273+
rtcpPkt, err = pkt.MarshalJSON()
274+
if err != nil {
275+
return nil, err
276+
}
263277

264278
case TYPE_RTCP_SDES:
265-
logp.Debug("rtcp", "Discard RTCP_SDES packet type: %d", RTCPType)
266-
offset += int(RTCPLength)
279+
logp.Debug("rtcp", "Discard RTCP_SDES packet type=%d", RTCPType)
280+
offset += RTCPLength
267281
case TYPE_RTCP_APP:
268-
logp.Debug("rtcp", "Discard RTCP_APP packet type: %d", RTCPType)
269-
offset += int(RTCPLength)
282+
logp.Debug("rtcp", "Discard RTCP_APP packet type=%d", RTCPType)
283+
offset += RTCPLength
270284
case TYPE_RTCP_BYE:
271-
logp.Debug("rtcp", "Discard RTCP_BYE packet type: %d", RTCPType)
272-
offset += int(RTCPLength)
285+
logp.Debug("rtcp", "Discard RTCP_BYE packet type=%d", RTCPType)
286+
offset += RTCPLength
273287
case TYPE_RTCP_XR:
274-
logp.Debug("rtcp", "Discard RTCP_XR packet type: %d", RTCPType)
275-
offset += int(RTCPLength)
288+
logp.Debug("rtcp", "Discard RTCP_XR packet type=%d", RTCPType)
289+
offset += RTCPLength
276290
default:
277-
logp.Debug("rtcp", "Discard unsupported packet type: %d", RTCPType)
278-
offset += int(RTCPLength)
291+
logp.Warn("rtcp", "Discard unsupported packet type=%d length=%d offset=%d in packet:\n%v", RTCPType, dataLen, offset, hex.Dump(data))
292+
return nil, fmt.Errorf("Discard unsupported packet type: %d", RTCPType)
279293
}
280294

281295
dataLen -= offset
282-
283296
}
284-
285-
rtcpPkt, err := pkt.MarshalJSON()
286-
if err != nil {
287-
return nil, err
288-
}
289-
290297
return rtcpPkt, nil
291298
}

Diff for: sniffer/sniffer.go

+4
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,10 @@ func (sniffer *SnifferSetup) setFromConfig(cfg *config.InterfacesConfig) error {
120120
if err != nil {
121121
return fmt.Errorf("couldn't open file %v! %v", sniffer.config.ReadFile, err)
122122
}
123+
err = sniffer.pcapHandle.SetBPFFilter(sniffer.filter)
124+
if err != nil {
125+
return fmt.Errorf("SetBPFFilter '%s' for ReadFile pcap: %v", sniffer.filter, err)
126+
}
123127
} else {
124128
sniffer.pcapHandle, err = pcap.OpenLive(sniffer.config.Device, int32(sniffer.config.Snaplen), true, pcap.BlockForever)
125129
if err != nil {

0 commit comments

Comments
 (0)