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 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
Sub Main() ListenForRawData() end sub Dim RAWSocket As System.Net.Sockets.Socket Private Const IOC_VENDOR As Integer = &H18000000 Private Const IOC_IN As Integer = -2147483648 Private Const SIO_RCVALL As Integer = IOC_IN Or IOC_VENDOR Or 1 Private Const SECURITY_BUILTIN_DOMAIN_RID As Integer = &H20 Private Const DOMAIN_ALIAS_RID_ADMINS As Integer = &H220 Dim MyIPAddr As String = vbNullString Dim MyStateObject As StateObject Public Class StateObject Public workSocket As System.Net.Sockets.Socket = Nothing Public Const BUFFER_SIZE As Integer = 65535 Public buffer(BUFFER_SIZE) As Byte Public sb As New System.Text.StringBuilder() End Class 'StateObject Private Sub ListenForRawData() 'To get local address Dim sHostName As String sHostName = System.Net.Dns.GetHostName() Dim ipE As System.Net.IPHostEntry = System.Net.Dns.GetHostByName(sHostName) Dim IpA() As System.Net.IPAddress = ipE.AddressList MyIPAddr = IpA(0).ToString() MyStateObject = New StateObject() RAWSocket = New System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Raw, System.Net.Sockets.ProtocolType.IP) Dim OptionIn() As Byte = BitConverter.GetBytes(1) Dim OptionOut() As Byte = Nothing Dim InByte() As Byte = {1, 0, 0, 0} Dim outByte(4) As Byte 'RAWSocket.Bind(New System.Net.IPEndPoint(Net.IPAddress.Any, 0)) RAWSocket.Bind(New System.Net.IPEndPoint(System.Net.IPAddress.Parse(MyIPAddr), 0)) 'must be bound to a IP ' RAWSocket.IOControl(SIO_RCVALL, InByte, outByte) RAWSocket.BeginReceive(MyStateObject.buffer, 0, StateObject.BUFFER_SIZE, System.Net.Sockets.SocketFlags.Peek, New AsyncCallback(AddressOf SockCallBack), Nothing) Debug.WriteLine("Listening On: " & MyIPAddr) End Sub Private Sub SockCallBack(ByVal ar As System.IAsyncResult) Dim BytesReturned = RAWSocket.EndReceive(ar) Dim ListboxData As String = vbNullString Select Case MyStateObject.buffer(9) Case &H1 'Protocol ICMP Case &H2 'Debug.WriteLine("IGAP,IGMP,RGMP") Case &H6 'TCP 'MyThreadToCall.TypeOfData = TypeOfPacket.TCP 'MyThreadToCall.STRData = DumpTCP(MyStateObject.buffer, BytesReturned, MyThreadToCall.TypeOfData) Case &H11 'UDP Case Else 'Debug.Write("Protocol Unknown - " & Hex$(MyStateObject.buffer(9))) End Select 'For i = 0 To BytesReturned - 1 ' Debug.Write(Hex$(MyStateObject.buffer(i)) & " ") ' If i = 9 Or i = 19 Or i = 29 Or i = 39 Or i = 49 Then Debug.WriteLine("") ' Next ' Debug.WriteLine("") ' Debug.WriteLine("") ' Select Case MyStateObject.buffer(9) Case &H1 Dim FROMIP As String = MyStateObject.buffer(12) & "." & MyStateObject.buffer(13) & "." & MyStateObject.buffer(14) & "." & MyStateObject.buffer(15) Dim DESTIP As String = MyStateObject.buffer(16) & "." & MyStateObject.buffer(17) & "." & MyStateObject.buffer(18) & "." & MyStateObject.buffer(19) If FROMIP = MyIPAddr Then If MyStateObject.buffer(20) = 0 Then 'Ping Reply Debug.WriteLine("You sent a Ping Reply to: " & DESTIP) Else Debug.WriteLine("You sent a Ping Request to: " & DESTIP) End If RAWSocket.BeginReceive(MyStateObject.buffer, 0, MyStateObject.BUFFER_SIZE, System.Net.Sockets.SocketFlags.None, New AsyncCallback(AddressOf SockCallBack), Nothing) Exit Sub End If If MyStateObject.buffer(20) = 0 Then 'Ping Reply Debug.WriteLine("Ping Reply: " & FROMIP) RAWSocket.BeginReceive(MyStateObject.buffer, 0, MyStateObject.BUFFER_SIZE, System.Net.Sockets.SocketFlags.None, New AsyncCallback(AddressOf SockCallBack), Nothing) Exit Sub End If Debug.WriteLine("Ping Request From - " & FROMIP & " | Bytes: " & (BytesReturned - 28) & " | TTL=" & MyStateObject.buffer(8)) '-28 shows the ping payload 'If TempClass.STRData <> vbNullString Then 'Me.Invoke(New MyDelPtr(AddressOf TempClass.ADDTOLISTBOX)) 'Invoke on main thread 'End If 'For i = 0 To BytesReturned - 1 ' Debug.Write(Hex$(MyStateObject.buffer(i)) & " ") ' If i = 9 Or i = 19 Or i = 29 Or i = 39 Or i = 49 Then Debug.WriteLine("") ' Next Case &H2 'Debug.WriteLine("IGAP,IGMP,RGMP") Case &H6 Debug.WriteLine("TCP ") Dim DestPort As UInteger = MyStateObject.buffer(22) DestPort <<= 8 DestPort += MyStateObject.buffer(23) Dim SrcPort As UInteger = MyStateObject.buffer(20) SrcPort <<= 8 SrcPort += MyStateObject.buffer(21) Dim FROMIP As String = MyStateObject.buffer(12) & "." & MyStateObject.buffer(13) & "." & MyStateObject.buffer(14) & "." & MyStateObject.buffer(15) Dim Data As String = vbNullString '= System.Text.ASCIIEncoding.ASCII.GetString(MyStateObject.buffer) For Each MyByte As Byte In MyStateObject.buffer If MyByte >= 32 AndAlso MyByte <= 126 Then Data &= Chr(MyByte) End If Next If DestPort = 5060 Or SrcPort = 5060 Then Debug.WriteLine("Phone!") Debug.WriteLine("Data: " & SrcPort & " -> " & DestPort & " | " & Data) End If If (Data.Contains("INVITE sip:")) Then 'From: "IS Sys Ops 1" <sip:1549@10.1.20.42> 'To: <sip:6588@ccm-02.emc.org> End If Dim myTo As String Dim myFrom As String Dim matches As MatchCollection = Regex.Matches(Data, "(To|From):.*?<sip:[\d]{1,4}@.*?>") ' Loop over matches. For Each m As Match In matches ' Loop over captures. For Each c As Capture In m.Captures ' Display. 'Console.WriteLine("Index={0}, Value={1}", c.Index, c.Value) If c.Value.Contains("From:") Then myFrom = c.Value End If If c.Value.Contains("To:") Then myTo = c.Value End If Next Next If Data.Contains("INVITE sip") Then Console.WriteLine("Incomming call: " & myFrom & " -> " & myTo) 'RaiseEvent CallIncomming() End If If Data.Contains("Request Cancelled") Then Console.WriteLine("Request Canceled: " & myFrom & " -> " & myTo) 'RaiseEvent CallMissed() End If If Data.Contains("RingingVia") Then Console.WriteLine("Rining Phone: " & myFrom & " -> " & myTo) 'RaiseEvent CallMissed() End If If Data.Contains("CANCEL sip") Then Console.WriteLine("CANCEL sip: " & myFrom & " -> " & myTo) 'RaiseEvent CallMissed() End If If Data.Contains("UPDATE sip") Then Console.WriteLine("UPDATE sip: " & myFrom & " -> " & myTo) 'RaiseEvent CallMissed() End If If Data.Contains("BYE sip") Then Console.WriteLine("Call ending: " & myFrom & " -> " & myTo) ' RaiseEvent CallEnded() End If If Data.Contains("Accepted") Then Console.WriteLine("Accepted: " & myFrom & " -> " & myTo) 'RaiseEvent CallStarted() End If Select Case MyStateObject.buffer(33) Case &H2 'Debug.Write("[SYN] - ") Case &H10 'Debug.Write("[ACK] - ") Case &H11 'Debug.Write("[FIN, ACK] - ") Case &H12 'Debug.Write("[SYN, ACK] - ") Case &H14 'Debug.Write("[RST, ACK] - ") Case &H18 Debug.Write("[PSH, ACK] - ") Case Else 'Debug.Write("[Unknown] - ") End Select 'DumpLayer4(MyStateObject.buffer) Case &H11 'Debug.Write("UDP - ") 'Debug.WriteLine("") Case Else 'Debug.Write("Protocol Unknown - " & Hex$(MyStateObject.buffer(9))) End Select 'For i = 0 To BytesReturned - 1 ' Debug.Write(Hex$(MyStateObject.buffer(i)) & " ") ' If i = 9 Or i = 19 Or i = 29 Or i = 39 Or i = 49 Then Debug.WriteLine("") ' Next ' Debug.WriteLine("") ' Debug.WriteLine("") ' RAWSocket.BeginReceive(MyStateObject.buffer, 0, MyStateObject.BUFFER_SIZE, System.Net.Sockets.SocketFlags.None, New AsyncCallback(AddressOf SockCallBack), Nothing) End Sub |
Now I had to do a conversion to C# to add to my VSTO plugin. This is a translations but also includes removing duped packets based on session id’s to prevent duplicate events being kicked off on the same pickup / hangup.
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 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 |
ArrayList ByeServerList = new ArrayList(); ArrayList ByeSipList = new ArrayList(); private System.Net.Sockets.Socket RAWSocket; private const int IOC_VENDOR = 0x18000000; private const int IOC_IN = -2147483648; private const int SIO_RCVALL = IOC_IN | IOC_VENDOR | 1; private const int SECURITY_BUILTIN_DOMAIN_RID = 0x20; private const int DOMAIN_ALIAS_RID_ADMINS = 0x220; private string MyIPAddr = ""; private StateObject MyStateObject; public class StateObject { public System.Net.Sockets.Socket workSocket = null; public const int BUFFER_SIZE = 65535; public byte[] buffer = new byte[65536]; public System.Text.StringBuilder sb = new System.Text.StringBuilder(); } // StateObject private void ListenForRawData() { // To get local address string sHostName; sHostName = System.Net.Dns.GetHostName(); System.Net.IPHostEntry ipE = System.Net.Dns.GetHostByName(sHostName); System.Net.IPAddress[] IpA = ipE.AddressList; MyIPAddr = IpA[0].ToString(); MyStateObject = new StateObject(); RAWSocket = new System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Raw, System.Net.Sockets.ProtocolType.IP); byte[] OptionIn = BitConverter.GetBytes(1); byte[] OptionOut = null; byte[] InByte = new byte[] { 1, 0, 0, 0 }; byte[] outByte = new byte[5]; // RAWSocket.Bind(New System.Net.IPEndPoint(Net.IPAddress.Any, 0)) RAWSocket.Bind(new System.Net.IPEndPoint(System.Net.IPAddress.Parse(MyIPAddr), 0)); // must be bound to a IP // RAWSocket.IOControl(SIO_RCVALL, InByte, outByte); RAWSocket.BeginReceive(MyStateObject.buffer, 0, StateObject.BUFFER_SIZE, System.Net.Sockets.SocketFlags.Peek, new AsyncCallback(SockCallBack), null); Debug.WriteLine("Listening On: " + MyIPAddr); } private void SockCallBack(System.IAsyncResult ar) { var BytesReturned = RAWSocket.EndReceive(ar); string ListboxData = null; switch (MyStateObject.buffer[9]) { case 0x1 // Protocol ICMP : { break; } case 0x2: { break; } case 0x6 // TCP : { break; } case 0x11 // UDP : { break; } default: { break; } } // For i = 0 To BytesReturned - 1 // Debug.Write(Hex$(MyStateObject.buffer(i)) & " ") // If i = 9 Or i = 19 Or i = 29 Or i = 39 Or i = 49 Then Debug.WriteLine("") // Next // Debug.WriteLine("") // Debug.WriteLine("") // switch (MyStateObject.buffer[9]) { case 0x1: { string FROMIP = MyStateObject.buffer[12] + "." + MyStateObject.buffer[13] + "." + MyStateObject.buffer[14] + "." + MyStateObject.buffer[15]; string DESTIP = MyStateObject.buffer[16] + "." + MyStateObject.buffer[17] + "." + MyStateObject.buffer[18] + "." + MyStateObject.buffer[19]; if (FROMIP == MyIPAddr) { if (MyStateObject.buffer[20] == 0) Debug.WriteLine("You sent a Ping Reply to: " + DESTIP); else Debug.WriteLine("You sent a Ping Request to: " + DESTIP); RAWSocket.BeginReceive(MyStateObject.buffer, 0, 65535, System.Net.Sockets.SocketFlags.None, new AsyncCallback(SockCallBack), null); return; } if (MyStateObject.buffer[20] == 0) { Debug.WriteLine("Ping Reply: " + FROMIP); RAWSocket.BeginReceive(MyStateObject.buffer, 0, 65535, System.Net.Sockets.SocketFlags.None, new AsyncCallback(SockCallBack), null); return; } Debug.WriteLine("Ping Request From - " + FROMIP + " | Bytes: " + (BytesReturned - 28) + " | TTL=" + MyStateObject.buffer[8]); // -28 shows the ping payload break; } case 0x2: { break; } case 0x6: { //Debug.WriteLine("TCP "); uint DestPort = MyStateObject.buffer[22]; DestPort <<= 8; DestPort += MyStateObject.buffer[23]; uint SrcPort = MyStateObject.buffer[20]; SrcPort <<= 8; SrcPort += MyStateObject.buffer[21]; string FROMIP = MyStateObject.buffer[12] + "." + MyStateObject.buffer[13] + "." + MyStateObject.buffer[14] + "." + MyStateObject.buffer[15]; string Data = null; // = System.Text.ASCIIEncoding.ASCII.GetString(MyStateObject.buffer) foreach (byte MyByte in MyStateObject.buffer) { if (MyByte >= 32 && MyByte <= 126) Data += System.Text.ASCIIEncoding.ASCII.GetString(new[] { MyByte }); } if (DestPort == 5060 | SrcPort == 5060) { Debug.WriteLine("Data: " + SrcPort + " -> " + DestPort + " | " + Data); } if ((Data.Contains("INVITE sip:"))) { } string myTo = null; string myFrom = null; string myDuration = null; MatchCollection matches = Regex.Matches(Data, @"(To|From):.*?<sip:[\d]{1,4}@.*?>"); // Loop over matches. foreach (Match m in matches) { // Loop over captures. foreach (Capture c in m.Captures) { // Display. // Console.WriteLine("Index={0}, Value={1}", c.Index, c.Value) if (c.Value.Contains("From:")) myFrom = c.Value; if (c.Value.Contains("To:")) myTo = c.Value; } } if (Data.Contains("INVITE sip")) Debug.WriteLine("Incomming call: " + myFrom + " -> " + myTo); if (Data.Contains("Request Cancelled")) Debug.WriteLine("Request Canceled: " + myFrom + " -> " + myTo); if (Data.Contains("RingingVia")) Debug.WriteLine("Rining Phone: " + myFrom + " -> " + myTo); if (Data.Contains("CANCEL sip")) Debug.WriteLine("CANCEL sip: " + myFrom + " -> " + myTo); if (Data.Contains("UPDATE sip")) Debug.WriteLine("UPDATE sip: " + myFrom + " -> " + myTo); if (Data.Contains("BYE sip")) { MatchCollection matches3 = Regex.Matches(Data, @"Session-ID: [[0-9a-fA-F]+;"); // Loop over matches. foreach (Match m in matches3) { if (ByeSipList.Contains(m.Value)) { //Debug.WriteLine("Call Concluded"); return; } ByeSipList.Add(m.Value); } Debug.WriteLine("Call ending: " + myFrom + " -> " + myTo); MatchCollection matches2 = Regex.Matches(Data, @"RTP-RxStat: Dur=[\d]+,"); // Loop over matches. foreach (Match m in matches2) { myDuration = m.Value.ToString().Replace("RTP-RxStat: Dur=", "").Replace(",", ""); Debug.WriteLine("BYE sip: Duration of call in seconds: " + myDuration); } if (myDuration != null) { if (!AddCallLog(" " + myFrom + " -> " + myTo, Convert.ToDouble(myDuration +60))) //Add a minute to each call. Each call takes at least a minute of our day right? { Debug.WriteLine("Failed to write calllog"); //break; } } } if (Data.Contains("BYEServer: Cisco-CSF") && Data.Contains("RTP-TxStat:")) //OKVia: SIP { MatchCollection matches3 = Regex.Matches(Data, @"Session-ID: [[0-9a-fA-F]+;"); // Loop over matches. foreach (Match m in matches3) { if (ByeServerList.Contains(m.Value)) { //Debug.WriteLine("Call Concluded"); return; } ByeServerList.Add(m.Value); } Debug.WriteLine("Call ending from Callee: " + myFrom + " -> " + myTo); MatchCollection matches2 = Regex.Matches(Data, @"RTP-RxStat: Dur=[\d]+,"); // Loop over matches. foreach (Match m in matches2) { myDuration = m.Value.ToString().Replace("RTP-RxStat: Dur=", "").Replace(",", ""); Debug.WriteLine("BYEServer: Duration of call in seconds: " + myDuration); } if (myDuration != null) { if (!AddCallLog(" " + myFrom + " -> " + myTo, Convert.ToDouble(myDuration + 60))) //Add a minute to each call. Each call takes at least a minute of our day right? { Debug.WriteLine("Failed to write calllog"); //break; } } } if (Data.Contains("Accepted")) Debug.WriteLine("Accepted: " + myFrom + " -> " + myTo); switch (MyStateObject.buffer[33]) { case 0x2: { break; } case 0x10: { break; } case 0x11: { break; } case 0x12: { break; } case 0x14: { break; } case 0x18: { //Debug.Write("[PSH, ACK] - "); break; } default: { break; } } break; } case 0x11: { break; } default: { break; } } // For i = 0 To BytesReturned - 1 // Debug.Write(Hex$(MyStateObject.buffer(i)) & " ") // If i = 9 Or i = 19 Or i = 29 Or i = 39 Or i = 49 Then Debug.WriteLine("") // Next // Debug.WriteLine("") // Debug.WriteLine("") // RAWSocket.BeginReceive(MyStateObject.buffer, 0, 65535, System.Net.Sockets.SocketFlags.None, new AsyncCallback(SockCallBack), null); } |