1// Copyright 2017 Google, Inc. All rights reserved. 2// 3// Use of this source code is governed by a BSD-style license 4// that can be found in the LICENSE file in the root of the source 5// tree. 6 7package layers 8 9import ( 10 "bytes" 11 "fmt" 12 "io" 13 "strconv" 14 "strings" 15 16 "github.com/google/gopacket" 17) 18 19// SIPVersion defines the different versions of the SIP Protocol 20type SIPVersion uint8 21 22// Represents all the versions of SIP protocol 23const ( 24 SIPVersion1 SIPVersion = 1 25 SIPVersion2 SIPVersion = 2 26) 27 28func (sv SIPVersion) String() string { 29 switch sv { 30 default: 31 // Defaulting to SIP/2.0 32 return "SIP/2.0" 33 case SIPVersion1: 34 return "SIP/1.0" 35 case SIPVersion2: 36 return "SIP/2.0" 37 } 38} 39 40// GetSIPVersion is used to get SIP version constant 41func GetSIPVersion(version string) (SIPVersion, error) { 42 switch strings.ToUpper(version) { 43 case "SIP/1.0": 44 return SIPVersion1, nil 45 case "SIP/2.0": 46 return SIPVersion2, nil 47 default: 48 return 0, fmt.Errorf("Unknown SIP version: '%s'", version) 49 50 } 51} 52 53// SIPMethod defines the different methods of the SIP Protocol 54// defined in the different RFC's 55type SIPMethod uint16 56 57// Here are all the SIP methods 58const ( 59 SIPMethodInvite SIPMethod = 1 // INVITE [RFC3261] 60 SIPMethodAck SIPMethod = 2 // ACK [RFC3261] 61 SIPMethodBye SIPMethod = 3 // BYE [RFC3261] 62 SIPMethodCancel SIPMethod = 4 // CANCEL [RFC3261] 63 SIPMethodOptions SIPMethod = 5 // OPTIONS [RFC3261] 64 SIPMethodRegister SIPMethod = 6 // REGISTER [RFC3261] 65 SIPMethodPrack SIPMethod = 7 // PRACK [RFC3262] 66 SIPMethodSubscribe SIPMethod = 8 // SUBSCRIBE [RFC6665] 67 SIPMethodNotify SIPMethod = 9 // NOTIFY [RFC6665] 68 SIPMethodPublish SIPMethod = 10 // PUBLISH [RFC3903] 69 SIPMethodInfo SIPMethod = 11 // INFO [RFC6086] 70 SIPMethodRefer SIPMethod = 12 // REFER [RFC3515] 71 SIPMethodMessage SIPMethod = 13 // MESSAGE [RFC3428] 72 SIPMethodUpdate SIPMethod = 14 // UPDATE [RFC3311] 73 SIPMethodPing SIPMethod = 15 // PING [https://tools.ietf.org/html/draft-fwmiller-ping-03] 74) 75 76func (sm SIPMethod) String() string { 77 switch sm { 78 default: 79 return "Unknown method" 80 case SIPMethodInvite: 81 return "INVITE" 82 case SIPMethodAck: 83 return "ACK" 84 case SIPMethodBye: 85 return "BYE" 86 case SIPMethodCancel: 87 return "CANCEL" 88 case SIPMethodOptions: 89 return "OPTIONS" 90 case SIPMethodRegister: 91 return "REGISTER" 92 case SIPMethodPrack: 93 return "PRACK" 94 case SIPMethodSubscribe: 95 return "SUBSCRIBE" 96 case SIPMethodNotify: 97 return "NOTIFY" 98 case SIPMethodPublish: 99 return "PUBLISH" 100 case SIPMethodInfo: 101 return "INFO" 102 case SIPMethodRefer: 103 return "REFER" 104 case SIPMethodMessage: 105 return "MESSAGE" 106 case SIPMethodUpdate: 107 return "UPDATE" 108 case SIPMethodPing: 109 return "PING" 110 } 111} 112 113// GetSIPMethod returns the constant of a SIP method 114// from its string 115func GetSIPMethod(method string) (SIPMethod, error) { 116 switch strings.ToUpper(method) { 117 case "INVITE": 118 return SIPMethodInvite, nil 119 case "ACK": 120 return SIPMethodAck, nil 121 case "BYE": 122 return SIPMethodBye, nil 123 case "CANCEL": 124 return SIPMethodCancel, nil 125 case "OPTIONS": 126 return SIPMethodOptions, nil 127 case "REGISTER": 128 return SIPMethodRegister, nil 129 case "PRACK": 130 return SIPMethodPrack, nil 131 case "SUBSCRIBE": 132 return SIPMethodSubscribe, nil 133 case "NOTIFY": 134 return SIPMethodNotify, nil 135 case "PUBLISH": 136 return SIPMethodPublish, nil 137 case "INFO": 138 return SIPMethodInfo, nil 139 case "REFER": 140 return SIPMethodRefer, nil 141 case "MESSAGE": 142 return SIPMethodMessage, nil 143 case "UPDATE": 144 return SIPMethodUpdate, nil 145 case "PING": 146 return SIPMethodPing, nil 147 default: 148 return 0, fmt.Errorf("Unknown SIP method: '%s'", method) 149 } 150} 151 152// Here is a correspondance between long header names and short 153// as defined in rfc3261 in section 20 154var compactSipHeadersCorrespondance = map[string]string{ 155 "accept-contact": "a", 156 "allow-events": "u", 157 "call-id": "i", 158 "contact": "m", 159 "content-encoding": "e", 160 "content-length": "l", 161 "content-type": "c", 162 "event": "o", 163 "from": "f", 164 "identity": "y", 165 "refer-to": "r", 166 "referred-by": "b", 167 "reject-contact": "j", 168 "request-disposition": "d", 169 "session-expires": "x", 170 "subject": "s", 171 "supported": "k", 172 "to": "t", 173 "via": "v", 174} 175 176// SIP object will contains information about decoded SIP packet. 177// -> The SIP Version 178// -> The SIP Headers (in a map[string][]string because of multiple headers with the same name 179// -> The SIP Method 180// -> The SIP Response code (if it's a response) 181// -> The SIP Status line (if it's a response) 182// You can easily know the type of the packet with the IsResponse boolean 183// 184type SIP struct { 185 BaseLayer 186 187 // Base information 188 Version SIPVersion 189 Method SIPMethod 190 Headers map[string][]string 191 192 // Request 193 RequestURI string 194 195 // Response 196 IsResponse bool 197 ResponseCode int 198 ResponseStatus string 199 200 // Private fields 201 cseq int64 202 contentLength int64 203 lastHeaderParsed string 204} 205 206// decodeSIP decodes the byte slice into a SIP type. It also 207// setups the application Layer in PacketBuilder. 208func decodeSIP(data []byte, p gopacket.PacketBuilder) error { 209 s := NewSIP() 210 err := s.DecodeFromBytes(data, p) 211 if err != nil { 212 return err 213 } 214 p.AddLayer(s) 215 p.SetApplicationLayer(s) 216 return nil 217} 218 219// NewSIP instantiates a new empty SIP object 220func NewSIP() *SIP { 221 s := new(SIP) 222 s.Headers = make(map[string][]string) 223 return s 224} 225 226// LayerType returns gopacket.LayerTypeSIP. 227func (s *SIP) LayerType() gopacket.LayerType { 228 return LayerTypeSIP 229} 230 231// Payload returns the base layer payload 232func (s *SIP) Payload() []byte { 233 return s.BaseLayer.Payload 234} 235 236// CanDecode returns the set of layer types that this DecodingLayer can decode 237func (s *SIP) CanDecode() gopacket.LayerClass { 238 return LayerTypeSIP 239} 240 241// NextLayerType returns the layer type contained by this DecodingLayer 242func (s *SIP) NextLayerType() gopacket.LayerType { 243 return gopacket.LayerTypePayload 244} 245 246// DecodeFromBytes decodes the slice into the SIP struct. 247func (s *SIP) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error { 248 // Init some vars for parsing follow-up 249 var countLines int 250 var line []byte 251 var err error 252 var offset int 253 254 // Iterate on all lines of the SIP Headers 255 // and stop when we reach the SDP (aka when the new line 256 // is at index 0 of the remaining packet) 257 buffer := bytes.NewBuffer(data) 258 259 for { 260 261 // Read next line 262 line, err = buffer.ReadBytes(byte('\n')) 263 if err != nil { 264 if err == io.EOF { 265 if len(bytes.Trim(line, "\r\n")) > 0 { 266 df.SetTruncated() 267 } 268 break 269 } else { 270 return err 271 } 272 } 273 offset += len(line) 274 275 // Trim the new line delimiters 276 line = bytes.Trim(line, "\r\n") 277 278 // Empty line, we hit Body 279 if len(line) == 0 { 280 break 281 } 282 283 // First line is the SIP request/response line 284 // Other lines are headers 285 if countLines == 0 { 286 err = s.ParseFirstLine(line) 287 if err != nil { 288 return err 289 } 290 291 } else { 292 err = s.ParseHeader(line) 293 if err != nil { 294 return err 295 } 296 } 297 298 countLines++ 299 } 300 s.BaseLayer = BaseLayer{Contents: data[:offset], Payload: data[offset:]} 301 302 return nil 303} 304 305// ParseFirstLine will compute the first line of a SIP packet. 306// The first line will tell us if it's a request or a response. 307// 308// Examples of first line of SIP Prococol : 309// 310// Request : INVITE bob@example.com SIP/2.0 311// Response : SIP/2.0 200 OK 312// Response : SIP/2.0 501 Not Implemented 313// 314func (s *SIP) ParseFirstLine(firstLine []byte) error { 315 316 var err error 317 318 // Splits line by space 319 splits := strings.SplitN(string(firstLine), " ", 3) 320 321 // We must have at least 3 parts 322 if len(splits) < 3 { 323 return fmt.Errorf("invalid first SIP line: '%s'", string(firstLine)) 324 } 325 326 // Determine the SIP packet type 327 if strings.HasPrefix(splits[0], "SIP") { 328 329 // --> Response 330 s.IsResponse = true 331 332 // Validate SIP Version 333 s.Version, err = GetSIPVersion(splits[0]) 334 if err != nil { 335 return err 336 } 337 338 // Compute code 339 s.ResponseCode, err = strconv.Atoi(splits[1]) 340 if err != nil { 341 return err 342 } 343 344 // Compute status line 345 s.ResponseStatus = splits[2] 346 347 } else { 348 349 // --> Request 350 351 // Validate method 352 s.Method, err = GetSIPMethod(splits[0]) 353 if err != nil { 354 return err 355 } 356 357 s.RequestURI = splits[1] 358 359 // Validate SIP Version 360 s.Version, err = GetSIPVersion(splits[2]) 361 if err != nil { 362 return err 363 } 364 } 365 366 return nil 367} 368 369// ParseHeader will parse a SIP Header 370// SIP Headers are quite simple, there are colon separated name and value 371// Headers can be spread over multiple lines 372// 373// Examples of header : 374// 375// CSeq: 1 REGISTER 376// Via: SIP/2.0/UDP there.com:5060 377// Authorization:Digest username="UserB", 378// realm="MCI WorldCom SIP", 379// nonce="1cec4341ae6cbe5a359ea9c8e88df84f", opaque="", 380// uri="sip:ss2.wcom.com", response="71ba27c64bd01de719686aa4590d5824" 381// 382func (s *SIP) ParseHeader(header []byte) (err error) { 383 384 // Ignore empty headers 385 if len(header) == 0 { 386 return 387 } 388 389 // Check if this is the following of last header 390 // RFC 3261 - 7.3.1 - Header Field Format specify that following lines of 391 // multiline headers must begin by SP or TAB 392 if header[0] == '\t' || header[0] == ' ' { 393 394 header = bytes.TrimSpace(header) 395 s.Headers[s.lastHeaderParsed][len(s.Headers[s.lastHeaderParsed])-1] += fmt.Sprintf(" %s", string(header)) 396 return 397 } 398 399 // Find the ':' to separate header name and value 400 index := bytes.Index(header, []byte(":")) 401 if index >= 0 { 402 403 headerName := strings.ToLower(string(bytes.Trim(header[:index], " "))) 404 headerValue := string(bytes.Trim(header[index+1:], " ")) 405 406 // Add header to object 407 s.Headers[headerName] = append(s.Headers[headerName], headerValue) 408 s.lastHeaderParsed = headerName 409 410 // Compute specific headers 411 err = s.ParseSpecificHeaders(headerName, headerValue) 412 if err != nil { 413 return err 414 } 415 } 416 417 return nil 418} 419 420// ParseSpecificHeaders will parse some specific key values from 421// specific headers like CSeq or Content-Length integer values 422func (s *SIP) ParseSpecificHeaders(headerName string, headerValue string) (err error) { 423 424 switch headerName { 425 case "cseq": 426 427 // CSeq header value is formatted like that : 428 // CSeq: 123 INVITE 429 // We split the value to parse Cseq integer value, and method 430 splits := strings.Split(headerValue, " ") 431 if len(splits) > 1 { 432 433 // Parse Cseq 434 s.cseq, err = strconv.ParseInt(splits[0], 10, 64) 435 if err != nil { 436 return err 437 } 438 439 // Validate method 440 if s.IsResponse { 441 s.Method, err = GetSIPMethod(splits[1]) 442 if err != nil { 443 return err 444 } 445 } 446 } 447 448 case "content-length": 449 450 // Parse Content-Length 451 s.contentLength, err = strconv.ParseInt(headerValue, 10, 64) 452 if err != nil { 453 return err 454 } 455 } 456 457 return nil 458} 459 460// GetAllHeaders will return the full headers of the 461// current SIP packets in a map[string][]string 462func (s *SIP) GetAllHeaders() map[string][]string { 463 return s.Headers 464} 465 466// GetHeader will return all the headers with 467// the specified name. 468func (s *SIP) GetHeader(headerName string) []string { 469 headerName = strings.ToLower(headerName) 470 h := make([]string, 0) 471 if _, ok := s.Headers[headerName]; ok { 472 if len(s.Headers[headerName]) > 0 { 473 return s.Headers[headerName] 474 } else if len(s.Headers[compactSipHeadersCorrespondance[headerName]]) > 0 { 475 return s.Headers[compactSipHeadersCorrespondance[headerName]] 476 } 477 } 478 return h 479} 480 481// GetFirstHeader will return the first header with 482// the specified name. If the current SIP packet has multiple 483// headers with the same name, it returns the first. 484func (s *SIP) GetFirstHeader(headerName string) string { 485 headerName = strings.ToLower(headerName) 486 if _, ok := s.Headers[headerName]; ok { 487 if len(s.Headers[headerName]) > 0 { 488 return s.Headers[headerName][0] 489 } else if len(s.Headers[compactSipHeadersCorrespondance[headerName]]) > 0 { 490 return s.Headers[compactSipHeadersCorrespondance[headerName]][0] 491 } 492 } 493 return "" 494} 495 496// 497// Some handy getters for most used SIP headers 498// 499 500// GetAuthorization will return the Authorization 501// header of the current SIP packet 502func (s *SIP) GetAuthorization() string { 503 return s.GetFirstHeader("Authorization") 504} 505 506// GetFrom will return the From 507// header of the current SIP packet 508func (s *SIP) GetFrom() string { 509 return s.GetFirstHeader("From") 510} 511 512// GetTo will return the To 513// header of the current SIP packet 514func (s *SIP) GetTo() string { 515 return s.GetFirstHeader("To") 516} 517 518// GetContact will return the Contact 519// header of the current SIP packet 520func (s *SIP) GetContact() string { 521 return s.GetFirstHeader("Contact") 522} 523 524// GetCallID will return the Call-ID 525// header of the current SIP packet 526func (s *SIP) GetCallID() string { 527 return s.GetFirstHeader("Call-ID") 528} 529 530// GetUserAgent will return the User-Agent 531// header of the current SIP packet 532func (s *SIP) GetUserAgent() string { 533 return s.GetFirstHeader("User-Agent") 534} 535 536// GetContentLength will return the parsed integer 537// Content-Length header of the current SIP packet 538func (s *SIP) GetContentLength() int64 { 539 return s.contentLength 540} 541 542// GetCSeq will return the parsed integer CSeq header 543// header of the current SIP packet 544func (s *SIP) GetCSeq() int64 { 545 return s.cseq 546} 547