-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathsccp.go
81 lines (68 loc) · 1.67 KB
/
sccp.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
package tcapflow
import (
"bytes"
"encoding/binary"
"fmt"
"github.com/google/gopacket"
)
type SCCPUDT struct {
MessageType uint8
Options uint8
FirstMandatory uint8
SecondMandatory uint8
ThirdMandatory uint8
}
type SCCPAddress struct {
Ssn uint8
Ton uint8
Npi uint8
Number string
}
func parseAddr(data []uint8) (addr SCCPAddress, err error) {
if len(data) < 5 {
err = fmt.Errorf("Not enough bytes for SSN and GT: %#v", data)
return
}
addr.Ssn = data[1]
addr.Ton = data[3] & 0xF0 >> 4
oddEven := data[3]&0x01 == 1
addr.Npi = data[4]
number := make([]byte, 0, 16)
for i := 5; i < len(data); i++ {
nibble := data[i] & 0x0F
number = append(number, nibble+48)
nibble = data[i] & 0xF0 >> 4
number = append(number, nibble+48)
}
if oddEven {
addr.Number = string(number[0 : len(number)-1])
} else {
addr.Number = string(number)
}
return
}
func handleSCCP(handler DataHandler, data []uint8, packet gopacket.Packet) {
sccp := SCCPUDT{}
if data[0] != 0x09 {
fmt.Printf("SCCP: Not unitdata\n")
return
}
buf := bytes.NewReader(data)
err := binary.Read(buf, binary.BigEndian, &sccp)
if err != nil {
fmt.Printf("Failed SCCP: %v\n", err)
return
}
offset := 2 + sccp.FirstMandatory
calledLen := data[offset]
calledDat := data[offset+1 : offset+1+calledLen]
calledAddr, err := parseAddr(calledDat)
offset = 3 + sccp.SecondMandatory
callingLen := data[offset]
callingDat := data[offset+1 : offset+1+callingLen]
callingAddr, err := parseAddr(callingDat)
offset = 4 + sccp.ThirdMandatory
payloadLen := data[offset]
payloadDat := data[offset+1 : offset+1+payloadLen]
handler.OnData(calledAddr, callingAddr, payloadDat, packet)
}