warning: overflow in implicit constant conversion
[obnox/wireshark/wip.git] / packet-sip.c
1 /* packet-sip.c
2  * Routines for the Session Initiation Protocol (SIP) dissection.
3  * RFCs 3261-3264
4  *
5  * TODO: Pay attention to Content-Type: It might not always be SDP.
6  *      Content-Type is fixed, mixed/mode is not handled though.
7  *       hf_ display filters for headers of SIP extension RFCs: 
8  *              Done for RFC 3265, RFC 3262
9  *              Use hash table for list of headers
10  *       Add sip msg body dissection based on Content-Type for:
11  *                SDP, MIME, and other types
12  *       Align SIP methods with recent Internet Drafts or RFC
13  *               (SIP INFO, rfc2976 - done)
14  *               (SIP SUBSCRIBE-NOTIFY - done)
15  *               (SIP REFER - done)
16  *               check for other
17  *
18  * Copyright 2000, Heikki Vatiainen <hessu@cs.tut.fi>
19  * Copyright 2001, Jean-Francois Mule <jfm@cablelabs.com>
20  *
21  * $Id: packet-sip.c,v 1.52 2003/12/17 20:52:38 guy Exp $
22  *
23  * Ethereal - Network traffic analyzer
24  * By Gerald Combs <gerald@ethereal.com>
25  * Copyright 1998 Gerald Combs
26  *
27  * Copied from packet-cops.c
28  *
29  * This program is free software; you can redistribute it and/or
30  * modify it under the terms of the GNU General Public License
31  * as published by the Free Software Foundation; either version 2
32  * of the License, or (at your option) any later version.
33  *
34  * This program is distributed in the hope that it will be useful,
35  * but WITHOUT ANY WARRANTY; without even the implied warranty of
36  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
37  * GNU General Public License for more details.
38  *
39  * You should have received a copy of the GNU General Public License
40  * along with this program; if not, write to the Free Software
41  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
42  */
43
44 #ifdef HAVE_CONFIG_H
45 # include "config.h"
46 #endif
47
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <ctype.h>
52
53 #include "prefs.h"
54
55 #include <glib.h>
56 #include <epan/packet.h>
57
58 #define TCP_PORT_SIP 5060
59 #define UDP_PORT_SIP 5060
60
61 /* Initialize the protocol and registered fields */
62 static gint proto_sip = -1;
63 static gint proto_raw_sip = -1;
64 static gint hf_msg_hdr = -1;
65 static gint hf_Method = -1;
66 static gint hf_Status_Code = -1;
67 static gint hf_sip_to_addr = -1;
68 static gint hf_sip_from_addr = -1;
69 static gint hf_sip_tag = -1;
70
71 /* Initialize the subtree pointers */
72 static gint ett_sip             = -1;
73 static gint ett_sip_reqresp     = -1;
74 static gint ett_sip_hdr         = -1;
75 static gint ett_raw_text        = -1;
76 static gint ett_sip_element     = -1;
77 static gint ett_sip_message_body = -1;
78
79 /* PUBLISH method added as per http://www.ietf.org/internet-drafts/draft-ietf-sip-publish-01.txt */
80 static const char *sip_methods[] = {
81         "<Invalid method>",      /* Pad so that the real methods start at index 1 */
82         "ACK",
83         "BYE",
84         "CANCEL",
85         "DO",
86         "INFO",
87         "INVITE",
88         "MESSAGE",
89         "NOTIFY",
90         "OPTIONS",
91         "PRACK",
92         "QAUTH",
93         "REFER",
94         "REGISTER",
95         "SPRACK",
96         "SUBSCRIBE",
97         "UPDATE",
98         "PUBLISH"
99 };
100
101 /* from RFC 3261 */
102 /* Updated with info from http://www.iana.org/assignments/sip-parameters */
103 /* (last updated 2003-10-31) */
104 /* Added two headsers ( Etag and If-Match )from http://www.ietf.org/internet-drafts/draft-ietf-sip-publish-01.txt */
105 typedef struct {
106         char *name;
107         char *compact_name;
108 } sip_header_t;
109 static const sip_header_t sip_headers[] = {
110                 { "Unknown-header",             NULL }, /* Pad so that the real headers start at index 1 */
111                 { "Accept",                     NULL },
112                 { "Accept-Encoding",            NULL },
113                 { "Accept-Language",            NULL },
114                 { "Alert-Info",                 NULL },
115                 { "Allow",                      NULL },
116                 { "Allow-Events",               NULL },
117                 { "Authentication-Info",        NULL },
118                 { "Authorization",              NULL },
119                 { "Call-ID",                    "i"  },
120                 { "Call-Info",                  NULL },
121                 { "Contact",                    "m"  },
122                 { "Content-Disposition",        NULL },
123                 { "Content-Encoding",           "e"  },
124                 { "Content-Language",           NULL },
125                 { "Content-Length",             "l"  },
126                 { "Content-Type",               "c"  },
127                 { "CSeq",                       NULL },
128                 { "Date",                       NULL },
129                 { "Error-Info",                 NULL },
130                 { "Event",                      "o"  },
131                 { "Expires",                    NULL },
132                 { "From",                       "f"  },
133                 { "In-Reply-To",                NULL },
134                 { "Max-Forwards",               NULL },
135                 { "MIME-Version",               NULL },
136                 { "Min-Expires",                NULL },
137                 { "Organization",               NULL },
138                 { "Priority",                   NULL },
139                 { "Proxy-Authenticate",         NULL },
140                 { "Proxy-Authorization",        NULL },
141                 { "Proxy-Require",              NULL },
142                 { "RAck",                       NULL },
143                 { "RSeq",                       NULL },
144                 { "Record-Route",               NULL },
145                 { "Reply-To",                   NULL },
146                 { "Require",                    NULL },
147                 { "Retry-After",                NULL },
148                 { "Route",                      NULL },
149                 { "Server",                     NULL },
150                 { "Subject",                    "s"  },
151                 { "Subscription-State",         NULL },
152                 { "Supported",                  "k" },
153                 { "Timestamp",                  NULL },
154                 { "To",                         "t"  },
155                 { "Unsupported",                NULL },
156                 { "User-Agent",                 NULL },
157                 { "Via",                        "v" },
158                 { "Warning",                    NULL },
159                 { "WWW-Authenticate",           NULL },
160                 { "P-Access-Network-Info",      NULL },  /*  RFC3455  */  
161                 { "P-Asserted-Identity",        NULL },  /*  RFC3325  */  
162                 { "P-Associated-URI",           NULL },  /*  RFC3455  */  
163                 { "P-Called-Party-ID",          NULL },  /*  RFC3455  */  
164                 { "P-Charging-Function-Addresses",NULL }, /*  RFC3455  */  
165                 { "P-Charging-Vector",          NULL },  /*  RFC3455  */  
166                 { "P-DCS-Trace-Party-ID",       NULL },  /*  RFC3603  */  
167                 { "P-DCS-OSPS",                 NULL },  /*  RFC3603  */  
168                 { "P-DCS-Billing-Info",         NULL },  /*  RFC3603  */  
169                 { "P-DCS-LAES",                 NULL },  /*  RFC3603  */  
170                 { "P-DCS-Redirect",             NULL },  /*  RFC3603  */  
171                 { "P-Media-Authorization",      NULL },  /*  RFC3313  */  
172                 { "P-Preferred-Identity",       NULL },  /*  RFC3325  */  
173                 { "P-Visited-Network-ID",       NULL },  /*  RFC3455  */  
174                 { "Path",                       NULL },  /*  RFC3327  */  
175                 { "Privacy",                    NULL },  /*  RFC3323  */  
176                 { "Reason",                     NULL },  /*  RFC3326  */  
177                 { "Refer-To",                   "r"  },  /*  RFC3515  */  
178                 { "Service-Route",              NULL },  /*  RFC3608  */  
179                 { "ETag",                       NULL },  /*  draft-ietf-sip-publish-01  */  
180                 { "If-Match",                   NULL },  /*  draft-ietf-sip-publish-01  */  
181
182 };
183
184
185 #define POS_ACCEPT                      1
186 #define POS_ACCEPT_ENCODING             2
187 #define POS_ACCEPT_LANGUAGE             3
188 #define POS_ALERT_INFO                  4
189 #define POS_ALLOW                       5
190 #define POS_ALLOW_EVENTS                6
191 #define POS_AUTHENTICATION_INFO         7
192 #define POS_AUTHORIZATION               8
193 #define POS_CALL_ID                     9
194 #define POS_CALL_INFO                   10
195 #define POS_CONTACT                     11
196 #define POS_CONTENT_DISPOSITION         12
197 #define POS_CONTENT_ENCODING            13
198 #define POS_CONTENT_LANGUAGE            14
199 #define POS_CONTENT_LENGTH              15
200 #define POS_CONTENT_TYPE                16
201 #define POS_CSEQ                        17
202 #define POS_DATE                        18
203 #define POS_ERROR_INFO                  19
204 #define POS_EVENT                       20
205 #define POS_EXPIRES                     21
206 #define POS_FROM                        22
207 #define POS_IN_REPLY_TO                 23
208 #define POS_MAX_FORWARDS                24
209 #define POS_MIME_VERSION                25
210 #define POS_MIN_EXPIRES                 26
211 #define POS_ORGANIZATION                27
212 #define POS_PRIORITY                    28
213 #define POS_PROXY_AUTHENTICATE          29
214 #define POS_PROXY_AUTHORIZATION         30
215 #define POS_PROXY_REQUIRE               31
216 #define POS_RACK                        32
217 #define POS_RSEQ                        33
218 #define POS_RECORD_ROUTE                34
219 #define POS_REPLY_TO                    35
220 #define POS_REQUIRE                     36
221 #define POS_RETRY_AFTER                 37
222 #define POS_ROUTE                       38
223 #define POS_SERVER                      39
224 #define POS_SUBJECT                     40
225 #define POS_SUBSCRIPTION_STATE          41
226 #define POS_SUPPORTED                   42
227 #define POS_TIMESTAMP                   43
228 #define POS_TO                          44
229 #define POS_UNSUPPORTED                 45
230 #define POS_USER_AGENT                  46
231 #define POS_VIA                         47
232 #define POS_WARNING                     48
233 #define POS_WWW_AUTHENTICATE            49
234
235 #define POS_P_ACCESS_NETWORK_INFO       50  
236 #define POS_P_ASSERTED_IDENTITY         51    
237 #define POS_P_ASSOCIATED_URI            52  
238 #define POS_P_CALLED_PARTY_ID           53  
239 #define POS_P_CHARGING_FUNCTION_ADDRESSES 54  
240 #define POS_P_CHARGING_VECTOR           55
241 #define POS_P_DCS_TRACE_PARTY_ID        56 
242 #define POS_P_DCS_OSPS                  57  
243 #define POS_P_DCS_BILLING_INFO          58  
244 #define POS_P_DCS_LAES                  59  
245 #define POS_P_DCS_REDIRECT              60  
246 #define POS_P_MEDIA_AUTHORIZATION       61  
247 #define POS_P_PREFERRED_IDENTITY        62  
248 #define POS_P_VISITED_NETWORK_ID        63  
249 #define POS_PATH                        64  
250 #define POS_PRIVACY                     65  
251 #define POS_REASON                      66 
252 #define POS_REFER_TO                    67 
253 #define POS_SERVICE_ROUTE               68 
254 #define POS_ETAG                        69 
255 #define POS_IF_MATCH                    70  
256
257 static gint hf_header_array[] = {
258                 -1, /* "Unknown-header" - Pad so that the real headers start at index 1 */
259                 -1, /* "Accept" */
260                 -1, /* "Accept-Encoding" */
261                 -1, /* "Accept-Language" */
262                 -1, /* "Alert-Info" */
263                 -1, /* "Allow" */
264                 -1, /* "Allow-Events" - RFC 3265 */
265                 -1, /* "Authentication-Info" */
266                 -1, /* "Authorization" */
267                 -1, /* "Call-ID" */
268                 -1, /* "Call-Info" */
269                 -1, /* "Contact" */
270                 -1, /* "Content-Disposition" */
271                 -1, /* "Content-Encoding" */
272                 -1, /* "Content-Language" */
273                 -1, /* "Content-Length" */
274                 -1, /* "Content-Type" */
275                 -1, /* "CSeq" */
276                 -1, /* "Date" */
277                 -1, /* "Error-Info" */
278                 -1, /* "Expires" */
279                 -1, /* "Event" - RFC 3265 */
280                 -1, /* "From" */
281                 -1, /* "In-Reply-To" */
282                 -1, /* "Max-Forwards" */
283                 -1, /* "MIME-Version" */
284                 -1, /* "Min-Expires" */
285                 -1, /* "Organization" */
286                 -1, /* "Priority" */
287                 -1, /* "Proxy-Authenticate" */
288                 -1, /* "Proxy-Authorization" */
289                 -1, /* "Proxy-Require" */
290                 -1, /* "RAck" - RFC 3262 */
291                 -1, /* "RSeq" - RFC 3261 */
292                 -1, /* "Record-Route" */
293                 -1, /* "Reply-To" */
294                 -1, /* "Require" */
295                 -1, /* "Retry-After" */
296                 -1, /* "Route" */
297                 -1, /* "Server" */
298                 -1, /* "Subject" */
299                 -1, /* "Subscription-State" - RFC 3265 */
300                 -1, /* "Supported" */
301                 -1, /* "Timestamp" */
302                 -1, /* "To" */
303                 -1, /* "Unsupported" */
304                 -1, /* "User-Agent" */
305                 -1, /* "Via" */
306                 -1, /* "Warning" */
307                 -1,  /* "WWW-Authenticate" */
308                 -1,  /* "P-Access-Network-Info" -   RFC3455  */  
309                 -1,  /* "P-Asserted-Identity"   -   RFC3325  */  
310                 -1,  /* "P-Associated-URI"      -   RFC3455  */  
311                 -1,  /* "P-Called-Party-ID"     -   RFC3455  */  
312                 -1,  /* "P-Charging-Function-Addresses" -   RFC3455  */  
313                 -1,  /* "P-Charging-Vector"     -   RFC3455  */  
314                 -1,  /* "P-DCS-Trace-Party-ID"  -   RFC3603  */  
315                 -1,  /* "P-DCS-OSPS"            -   RFC3603  */  
316                 -1,  /* "P-DCS-Billing-Info"    -   RFC3603  */  
317                 -1,  /* "P-DCS-LAES"            -   RFC3603  */  
318                 -1,  /* "P-DCS-Redirect"        -   RFC3603  */  
319                 -1,  /* "P-Media-Authorization"         -   RFC3313  */  
320                 -1,  /* "P-Preferred-Identity"  -   RFC3325  */  
321                 -1,  /* "P-Visited-Network-ID"  -   RFC3455  */  
322                 -1,  /* "Path"                  -   RFC3327  */  
323                 -1,  /* "Privacy"               -   RFC3323  */  
324                 -1,  /* "Reason"                -   RFC3326  */  
325                 -1,  /* "Refer-To"              -   RFC3515  */  
326                 -1,  /* "Service-Route"                 -   RFC3608  */  
327                 -1,  /* "ETag"     draft-ietf-sip-publish-01  */  
328                 -1,  /* "If-Match  draft-ietf-sip-publish-01  */  
329
330 };
331
332 /*
333  * Type of line.  It's either a SIP Request-Line, a SIP Status-Line, or
334  * another type of line.
335  */
336 typedef enum {
337         REQUEST_LINE,
338         STATUS_LINE,
339         OTHER_LINE
340 } line_type_t;
341
342 /* global_sip_raw_text determines whether we are going to display               */
343 /* the raw text of the SIP message, much like the MEGACO dissector does.        */
344 static gboolean global_sip_raw_text = FALSE;
345
346 static gboolean dissect_sip_common(tvbuff_t *tvb, packet_info *pinfo,
347     proto_tree *tree, gboolean is_heur);
348 static line_type_t sip_parse_line(tvbuff_t *tvb, gint linelen,
349     guint *token_1_len);
350 static gboolean sip_is_known_request(tvbuff_t *tvb, int meth_offset,
351     guint meth_len, guint *meth_idx);
352 static gint sip_is_known_sip_header(tvbuff_t *tvb, int offset,
353     guint header_len);
354 static void dfilter_sip_request_line(tvbuff_t *tvb, proto_tree *tree,
355     guint meth_len);
356 static void dfilter_sip_status_line(tvbuff_t *tvb, proto_tree *tree);
357 static void tvb_raw_text_add(tvbuff_t *tvb, proto_tree *tree);
358
359 /* SIP content type and internet media type used by other dissectors are the same */
360 /* List of nmediatypes from IANA at: http://www.iana.org/assignments/media-types/index.html */
361 static dissector_table_t media_type_dissector_table;
362
363 #define SIP2_HDR "SIP/2.0"
364 #define SIP2_HDR_LEN (strlen (SIP2_HDR))
365
366 /* Code to actually dissect the packets */
367 static int
368 dissect_sip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
369 {
370         if (!dissect_sip_common(tvb, pinfo, tree, FALSE))
371                 return 0;
372         return tvb_length(tvb);
373 }
374
375 static void
376 dissect_sip_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
377 {
378         dissect_sip_common(tvb, pinfo, tree, TRUE);
379 }
380
381 static gboolean
382 dissect_sip_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
383 {
384         return dissect_sip_common(tvb, pinfo, tree, FALSE);
385 }
386
387 static gboolean
388 dissect_sip_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
389     gboolean dissect_other_as_continuation)
390 {
391         int offset;
392         gint next_offset, linelen;
393         line_type_t line_type;
394         tvbuff_t *next_tvb;
395         gboolean is_known_request;
396         gboolean found_match = FALSE;
397         char *descr;
398         guint token_1_len;
399         guint current_method_idx = 0;
400         proto_item *ts = NULL, *ti, *th = NULL, *sip_element_item;
401         proto_tree *sip_tree = NULL, *reqresp_tree, *hdr_tree = NULL, *sip_element_tree, *message_body_tree;
402         guchar contacts = 0, contact_is_star = 0, expires_is_0 = 0;     
403         char csec_method[16] = "";
404         char *media_type_str = NULL;
405         char *content_type_parameter_str = NULL;
406
407         /*
408          * Note that "tvb_find_line_end()" will return a value that
409          * is not longer than what's in the buffer, so the
410          * "tvb_get_ptr()" calls below won't throw exceptions.
411          *
412          * Note that "tvb_strneql()" doesn't throw exceptions, so
413          * "sip_parse_line()" won't throw an exception.
414          */
415         offset = 0;
416         linelen = tvb_find_line_end(tvb, 0, -1, &next_offset, FALSE);
417         line_type = sip_parse_line(tvb, linelen, &token_1_len);
418         if (line_type == OTHER_LINE) {
419                 /*
420                  * This is neither a SIP request nor response.
421                  */
422                 if (!dissect_other_as_continuation) {
423                         /*
424                          * We were asked to reject this.
425                          */
426                         return FALSE;
427                 }
428
429                 /*
430                  * Just dissect it as a continuation.
431                  */
432         }
433
434         if (check_col(pinfo->cinfo, COL_PROTOCOL))
435                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SIP");
436
437         switch (line_type) {
438
439         case REQUEST_LINE:
440                 is_known_request = sip_is_known_request(tvb, 0, token_1_len, &current_method_idx);
441                 descr = is_known_request ? "Request" : "Unknown request";
442                 if (check_col(pinfo->cinfo, COL_INFO)) {
443                         col_add_fstr(pinfo->cinfo, COL_INFO, "%s: %s",
444                              descr,
445                              tvb_format_text(tvb, 0, linelen - SIP2_HDR_LEN - 1));
446                 }
447                 break;
448
449         case STATUS_LINE:
450                 descr = "Status";
451                 if (check_col(pinfo->cinfo, COL_INFO)) {
452                         col_add_fstr(pinfo->cinfo, COL_INFO, "Status: %s",
453                              tvb_format_text(tvb, SIP2_HDR_LEN + 1, linelen - SIP2_HDR_LEN - 1));
454                 }
455                 break;
456
457         case OTHER_LINE:
458         default: /* Squelch compiler complaints */
459                 descr = "Continuation";
460                 if (check_col(pinfo->cinfo, COL_INFO))
461                         col_set_str(pinfo->cinfo, COL_INFO, "Continuation");
462                 break;
463         }
464         if (tree) {
465                 ts = proto_tree_add_item(tree, proto_sip, tvb, 0, -1, FALSE);
466                 sip_tree = proto_item_add_subtree(ts, ett_sip);
467
468                 ti = proto_tree_add_text(sip_tree, tvb, 0, next_offset,
469                                          "%s line: %s", descr,
470                                          tvb_format_text(tvb, 0, linelen));
471                 reqresp_tree = proto_item_add_subtree(ti, ett_sip_reqresp);
472
473                 switch (line_type) {
474
475                 case REQUEST_LINE:
476                         dfilter_sip_request_line(tvb, reqresp_tree, token_1_len);
477                         break;
478
479                 case STATUS_LINE:
480                         dfilter_sip_status_line(tvb, reqresp_tree);
481                         break;
482
483                 case OTHER_LINE:
484                         proto_tree_add_text(sip_tree, tvb, 0, -1,
485                             "Continuation data");
486                         return TRUE;
487                 }
488
489                 offset = next_offset;
490                 th = proto_tree_add_item(sip_tree, hf_msg_hdr, tvb, offset, -1,
491                     FALSE);
492                 hdr_tree = proto_item_add_subtree(th, ett_sip_hdr);
493         }
494
495         /*
496          * Process the headers - if we're not building a protocol tree,
497          * we just do this to find the blank line separating the
498          * headers from the message body.
499          */
500         next_offset = offset;
501         while (tvb_reported_length_remaining(tvb, offset) > 0) {
502                 gint line_end_offset;
503                 gint colon_offset;
504                 gint semicolon_offset;
505                 gint content_type_len, content_type_parameter_str_len;
506                 gint header_len;
507                 gint hf_index;
508                 gint value_offset,tag_offset;
509                 guchar c;
510                 size_t value_len;
511                 char *value;
512
513                 linelen = tvb_find_line_end(tvb, offset, -1, &next_offset,
514                     FALSE);
515                 if (linelen == 0) {
516                         /*
517                          * This is a blank line separating the
518                          * message header from the message body.
519                          */
520                         break;
521                 }
522                 line_end_offset = offset + linelen;
523                 colon_offset = tvb_find_guint8(tvb, offset, linelen, ':');
524                 if (colon_offset == -1) {
525                         /*
526                          * Malformed header - no colon after the name.
527                          */
528                         proto_tree_add_text(hdr_tree, tvb, offset,
529                             next_offset - offset, "%s",
530                             tvb_format_text(tvb, offset, linelen));
531                 } else {
532                         header_len = colon_offset - offset;
533                         hf_index = sip_is_known_sip_header(tvb,
534                             offset, header_len);
535
536                         if (hf_index == -1) {
537                                 proto_tree_add_text(hdr_tree, tvb,
538                                     offset, next_offset - offset, "%s",
539                                     tvb_format_text(tvb, offset, linelen));
540                         } else {
541                                 /*
542                                  * Skip whitespace after the colon.
543                                  */
544                                 value_offset = colon_offset + 1;
545                                 while (value_offset < line_end_offset
546                                     && ((c = tvb_get_guint8(tvb,
547                                             value_offset)) == ' '
548                                       || c == '\t'))
549                                         value_offset++;
550                                 /*
551                                  * Fetch the value.
552                                  */
553                                 value_len = line_end_offset - value_offset;
554                                 value = tvb_get_string(tvb, value_offset,
555                                     value_len);
556
557                                 /*
558                                  * Add it to the protocol tree,
559                                  * but display the line as is.
560                                  */
561                                 switch ( hf_index ) {
562
563                                 case POS_TO :
564                                         sip_element_item = proto_tree_add_string_format(hdr_tree,
565                                             hf_header_array[hf_index], tvb,
566                                             offset, next_offset - offset,
567                                             value, "%s",
568                                             tvb_format_text(tvb, offset, linelen));
569                                         sip_element_tree = proto_item_add_subtree( sip_element_item,
570                                                  ett_sip_element);
571                                         tag_offset = tvb_find_guint8(tvb, offset,linelen, ';');
572                                         if ( tag_offset != -1){
573                                                 tag_offset = tag_offset + 1;
574                                                 c = tvb_get_guint8(tvb,tag_offset);
575                                                 if ( c == 't' ){/* tag found */
576                                                         proto_tree_add_string(sip_element_tree,
577                                                             hf_sip_to_addr, tvb,
578                                                             value_offset, (tag_offset - value_offset - 1),
579                                                         tvb_format_text(tvb, value_offset,
580                                                         ( tag_offset - value_offset - 1)));
581                                                         tag_offset = tvb_find_guint8(tvb, tag_offset,linelen, '=') + 1;
582                                                         proto_tree_add_string(sip_element_tree,
583                                                             hf_sip_tag, tvb,
584                                                             tag_offset, (line_end_offset - tag_offset),
585                                                         tvb_format_text(tvb, tag_offset, (line_end_offset - tag_offset)));
586                                                 
587                                                 }
588                                                 else {
589                                                         proto_tree_add_string_format(sip_element_tree,
590                                                             hf_sip_to_addr, tvb,
591                                                             offset, line_end_offset - offset,
592                                                             value, "%s",
593                                                             tvb_format_text(tvb, offset, linelen));
594                                                 }/* if c= t */
595                                         } /* if tag offset */
596                                         break;  
597
598                                 case POS_FROM :
599                                         sip_element_item = proto_tree_add_string_format(hdr_tree,
600                                             hf_header_array[hf_index], tvb,
601                                             offset, next_offset - offset,
602                                             value, "%s",
603                                             tvb_format_text(tvb, offset, linelen));
604                                         sip_element_tree = proto_item_add_subtree( sip_element_item, ett_sip_element);
605                                         tag_offset = tvb_find_guint8(tvb, offset,linelen, ';');
606                                         if ( tag_offset != -1){
607                                                 tag_offset = tag_offset + 1;
608                                                 c = tvb_get_guint8(tvb,tag_offset);
609                                                 if ( c == 't' ){/* tag found */
610                                                         proto_tree_add_string(sip_element_tree,
611                                                             hf_sip_from_addr, tvb,
612                                                             value_offset, (tag_offset - value_offset - 1),
613                                                             tvb_format_text(tvb, value_offset, ( tag_offset - value_offset - 1)));
614                                                         tag_offset = tvb_find_guint8(tvb, offset,linelen, '=') + 1;
615                                                         proto_tree_add_string(sip_element_tree,
616                                                             hf_sip_tag, tvb,
617                                                             tag_offset, (line_end_offset - tag_offset),
618                                                             tvb_format_text(tvb, tag_offset, (line_end_offset - tag_offset)));
619                                                 }
620                                                 else {
621                                                         tag_offset = tvb_find_guint8(tvb, tag_offset,linelen, ';');
622                                                         if ( tag_offset != -1){
623                                                                 tag_offset = tag_offset + 1;
624                                                                 c = tvb_get_guint8(tvb,tag_offset);
625                                                                 if ( c == 't' ){/* tag found */
626                                                                         proto_tree_add_string(sip_element_tree,
627                                                                            hf_sip_from_addr, tvb,
628                                                                            value_offset, (tag_offset - value_offset - 1),
629                                                                            tvb_format_text(tvb, value_offset, ( tag_offset - value_offset - 1)));
630                                                                         tag_offset = tvb_find_guint8(tvb, tag_offset,linelen, '=') + 1;
631                                                                         proto_tree_add_string(sip_element_tree,
632                                                                             hf_sip_tag, tvb,
633                                                                             tag_offset, (line_end_offset - tag_offset),
634                                                                             tvb_format_text(tvb, tag_offset, (line_end_offset - tag_offset)));
635                                                                 }
636                                                         }
637                                                 }/* if c= t */
638                                         } /* if tag offset */
639                                         break;
640
641                                 case POS_CSEQ :
642                                         /* Extract method name from value */
643                                         for (value_offset = 0; value_offset < (gint)strlen(value); value_offset++)
644                                         {
645                                                 if (isalpha(value[value_offset]))
646                                                 {
647                                                         strcpy(csec_method,value+value_offset);
648                                                         break;
649                                                 }
650                                         }
651                                         /* Add 'CSeq' string item to tree */
652                                         proto_tree_add_string_format(hdr_tree,
653                                             hf_header_array[hf_index], tvb,
654                                             offset, next_offset - offset,
655                                             value, "%s",
656                                             tvb_format_text(tvb, offset, linelen));
657                                         break;
658
659                                 case POS_EXPIRES :
660                                         if (strcmp(value, "0") == 0)
661                                         {
662                                                 expires_is_0 = 1;
663                                         }
664                                         /* Add 'Expires' string item to tree */
665                                         proto_tree_add_string_format(hdr_tree,
666                                             hf_header_array[hf_index], tvb,
667                                             offset, next_offset - offset,
668                                             value, "%s",
669                                             tvb_format_text(tvb, offset, linelen));
670                                         break;
671
672                                 /*
673                                  * Content-Type is the same as Internet
674                                  * media type used by other dissectors,
675                                  * appropriate dissector found by
676                                  * lookup in "media_type" dissector table.
677                                  */
678                                 case POS_CONTENT_TYPE :
679                                         proto_tree_add_string_format(hdr_tree,
680                                             hf_header_array[hf_index], tvb,
681                                             offset, next_offset - offset,
682                                             value, "%s",
683                                             tvb_format_text(tvb, offset, linelen));
684                                         content_type_len = value_len;
685                                         semicolon_offset = tvb_find_guint8(tvb, value_offset,linelen, ';');
686                                         if ( semicolon_offset != -1) {
687                                                 content_type_len = semicolon_offset - value_offset;
688                                                 content_type_parameter_str_len = linelen - semicolon_offset; 
689                                                 content_type_parameter_str = tvb_get_string(tvb, semicolon_offset + 1, content_type_parameter_str_len);
690                                         }
691                                         media_type_str = tvb_get_string(tvb, value_offset, content_type_len);
692                                         break;
693
694                                 case POS_CONTACT :
695                                         contacts++;
696                                         if (strcmp(value, "*") == 0)
697                                         {
698                                                 contact_is_star = 1;
699                                         }
700                                         /* Fall through to default case to add string to tree */
701
702                                 default :       
703                                         proto_tree_add_string_format(hdr_tree,
704                                             hf_header_array[hf_index], tvb,
705                                             offset, next_offset - offset,
706                                             value, "%s",
707                                             tvb_format_text(tvb, offset, linelen));
708                                 break;
709                                 }/* end switch */
710                                 g_free(value);
711                         }/*if HF_index */
712                 }/* if colon_offset */ 
713                 offset = next_offset;
714         }/* End while */
715
716         if (tvb_offset_exists(tvb, next_offset)) {
717
718                 /*
719                  * There's a message body starting at "next_offset".
720                  * Set the length of the SIP portion and of the
721                  * header item.
722                  */
723                 proto_item_set_end(ts, tvb, next_offset);
724                 proto_item_set_end(th, tvb, next_offset);
725                 next_tvb = tvb_new_subset(tvb, next_offset, -1, -1);
726                 ti = proto_tree_add_text(sip_tree, next_tvb, 0, -1,
727                                          "Message body");
728                 message_body_tree = proto_item_add_subtree(ti, ett_sip_message_body);
729
730                 /* give the content type parameters to sub dissectors */
731                 
732                 if ( media_type_str != NULL ) {
733                         pinfo->private_data = content_type_parameter_str;
734                         found_match = dissector_try_string(media_type_dissector_table,
735                                                            media_type_str,
736                                                            next_tvb, pinfo,
737                                                            message_body_tree);
738                         g_free(media_type_str);
739                         g_free(content_type_parameter_str);
740                         /* If no match dump as text */
741                 }
742                 if ( found_match != TRUE )
743                 {
744                         offset = 0;
745                         while (tvb_offset_exists(next_tvb, offset)) {
746                                 tvb_find_line_end(next_tvb, offset, -1, &next_offset, FALSE);
747                                 linelen = next_offset - offset;
748                                 proto_tree_add_text(message_body_tree, next_tvb, offset, linelen,
749                                         "%s", tvb_format_text(next_tvb, offset, linelen));
750                                 offset = next_offset;
751                         }/* end while */
752                 }
753         }
754
755
756         /* Add to info column interesting things learned from header fields. */
757         if (check_col(pinfo->cinfo, COL_INFO))
758         {
759                 /* Registration requests */
760                 if (strcmp(sip_methods[current_method_idx], "REGISTER") == 0)
761                 {
762                         if (contact_is_star && expires_is_0)
763                         {
764                                 col_append_str(pinfo->cinfo, COL_INFO, "    (remove all bindings)");
765                         }
766                         else
767                         if (!contacts)
768                         {
769                                 col_append_str(pinfo->cinfo, COL_INFO, "    (fetch bindings)");
770                         }
771                 }
772
773                 /* Registration responses */
774                 if (line_type == STATUS_LINE && (strcmp(csec_method, "REGISTER") == 0))
775                 {
776                         col_append_fstr(pinfo->cinfo, COL_INFO, "    (%d bindings)", contacts);
777                 }
778         }
779
780         if (global_sip_raw_text)
781                 tvb_raw_text_add(tvb, tree);
782
783         return TRUE;
784 }
785
786 /* Display filter for SIP Request-Line */
787 static void
788 dfilter_sip_request_line(tvbuff_t *tvb, proto_tree *tree, guint meth_len)
789 {
790         char    *string;
791
792         /*
793          * We know we have the entire method; otherwise, "sip_parse_line()"
794          * would have returned OTHER_LINE.
795          */
796         string = tvb_get_string(tvb, 0, meth_len);
797         proto_tree_add_string(tree, hf_Method, tvb, 0, meth_len, string);
798         g_free(string);
799 }
800
801 /* Display filter for SIP Status-Line */
802 static void
803 dfilter_sip_status_line(tvbuff_t *tvb, proto_tree *tree)
804 {
805         char string[3+1];
806
807         /*
808          * We know we have the entire status code; otherwise,
809          * "sip_parse_line()" would have returned OTHER_LINE.
810          * We also know that we have a version string followed by a
811          * space at the beginning of the line, for the same reason.
812          */
813         tvb_memcpy(tvb, (guint8 *)string, SIP2_HDR_LEN + 1, 3);
814         string[3] = '\0';
815         proto_tree_add_string(tree, hf_Status_Code, tvb, SIP2_HDR_LEN + 1,
816             3, string);
817 }
818
819 /* From section 4.1 of RFC 2543:
820  *
821  * Request-Line  =  Method SP Request-URI SP SIP-Version CRLF
822  *
823  * From section 5.1 of RFC 2543:
824  *
825  * Status-Line  =  SIP-version SP Status-Code SP Reason-Phrase CRLF
826  */
827 static line_type_t
828 sip_parse_line(tvbuff_t *tvb, gint linelen, guint *token_1_lenp)
829 {
830         gint space_offset;
831         guint token_1_len;
832         gint token_2_start;
833         guint token_2_len;
834         gint token_3_start;
835         guint token_3_len;
836         gint colon_pos;
837
838         space_offset = tvb_find_guint8(tvb, 0, -1, ' ');
839         if (space_offset <= 0) {
840                 /*
841                  * Either there's no space in the line (which means
842                  * the line is empty or doesn't have a token followed
843                  * by a space; neither is valid for a request or status), or
844                  * the first character in the line is a space (meaning
845                  * the method is empty, which isn't valid for a request,
846                  * or the SIP version is empty, which isn't valid for a
847                  * status).
848                  */
849                 return OTHER_LINE;
850         }
851         token_1_len = space_offset;
852         token_2_start = space_offset + 1;
853         space_offset = tvb_find_guint8(tvb, token_2_start, -1, ' ');
854         if (space_offset == -1) {
855                 /*
856                  * There's no space after the second token, so we don't
857                  * have a third token.
858                  */
859                 return OTHER_LINE;
860         }
861         token_2_len = space_offset - token_2_start;
862         token_3_start = space_offset + 1;
863         token_3_len = linelen - token_3_start;
864         
865         *token_1_lenp = token_1_len;
866
867         /*
868          * Is the first token a version string?
869          */
870         if (token_1_len == SIP2_HDR_LEN &&
871             tvb_strneql(tvb, 0, SIP2_HDR, SIP2_HDR_LEN) == 0) {
872                 /*
873                  * Yes, so this is either a Status-Line or something
874                  * else other than a Request-Line.  To be a Status-Line,
875                  * the second token must be a 3-digit number.
876                  */
877                 if (token_2_len != 3) {
878                         /*
879                          * We don't have 3-character status code.
880                          */
881                         return OTHER_LINE;
882                 }
883                 if (!isdigit(tvb_get_guint8(tvb, token_2_start)) ||
884                     !isdigit(tvb_get_guint8(tvb, token_2_start + 1)) ||
885                     !isdigit(tvb_get_guint8(tvb, token_2_start + 2))) {
886                         /*
887                          * 3 characters yes, 3 digits no.
888                          */
889                         return OTHER_LINE;
890                 }
891                 return STATUS_LINE;
892         } else {
893                 /*
894                  * No, so this is either a Request-Line or something
895                  * other than a Status-Line.  To be a Request-Line, the
896                  * second token must be a URI and the third token must
897                  * be a version string.
898                  */
899                 if (token_2_len < 3) {
900                         /*
901                          * We don't have a URI consisting of at least 3
902                          * characters.
903                          */
904                         return OTHER_LINE;
905                 }
906                 colon_pos = tvb_find_guint8(tvb, token_2_start + 1, -1, ':');
907                 if (colon_pos == -1) {
908                         /*
909                          * There is no colon after the method, so the URI
910                          * doesn't have a colon in it, so it's not valid.
911                          */
912                         return OTHER_LINE;
913                 }
914                 if (colon_pos >= token_3_start) {
915                         /*
916                          * The colon is in the version string, not the URI.
917                          */
918                         return OTHER_LINE;
919                 }
920                 /* XXX - Check for a proper URI prefix? */
921                 if (token_3_len != SIP2_HDR_LEN ||
922                     tvb_strneql(tvb, token_3_start, SIP2_HDR, SIP2_HDR_LEN) == -1) {
923                         /*
924                          * The version string isn't an SIP version 2.0 version
925                          * string.
926                          */
927                         return OTHER_LINE;
928                 }
929                 return REQUEST_LINE;
930         }
931 }
932
933 static gboolean sip_is_known_request(tvbuff_t *tvb, int meth_offset,
934     guint meth_len, guint *meth_idx)
935 {
936         guint i;
937
938         for (i = 1; i < array_length(sip_methods); i++) {
939                 if (meth_len == strlen(sip_methods[i]) &&
940                     tvb_strneql(tvb, meth_offset, sip_methods[i], meth_len) == 0)
941                 {
942                      *meth_idx = i;
943                      return TRUE;
944                 }
945         }
946
947         return FALSE;
948 }
949
950 /* Returns index of method in sip_headers */
951 static gint sip_is_known_sip_header(tvbuff_t *tvb, int offset, guint header_len)
952 {
953         guint i;
954
955         for (i = 1; i < array_length(sip_headers); i++) {
956                 if (header_len == strlen(sip_headers[i].name) &&
957                     tvb_strncaseeql(tvb, offset, sip_headers[i].name, header_len) == 0)
958                         return i;
959                 if (sip_headers[i].compact_name != NULL &&
960                     header_len == strlen(sip_headers[i].compact_name) &&
961                     tvb_strncaseeql(tvb, offset, sip_headers[i].compact_name, header_len) == 0)
962                         return i;
963         }
964
965         return -1;
966 }
967
968 /*
969  * Display the entire message as raw text.
970  */
971 static void
972 tvb_raw_text_add(tvbuff_t *tvb, proto_tree *tree)
973 {
974         proto_tree *raw_tree;
975         proto_item *ti;
976         int offset, next_offset, linelen;
977
978         ti = proto_tree_add_item(tree, proto_raw_sip, tvb, 0, -1, FALSE);
979         raw_tree = proto_item_add_subtree(ti, ett_raw_text);
980
981         offset = 0;
982
983         while (tvb_offset_exists(tvb, offset)) {
984                 tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
985                 linelen = next_offset - offset;
986                 proto_tree_add_text(raw_tree, tvb, offset, linelen,
987                     "%s", tvb_format_text(tvb, offset, linelen));
988                 offset = next_offset;
989         }
990 }
991
992 /* Register the protocol with Ethereal */
993 void proto_register_sip(void)
994 {
995
996         /* Setup list of header fields */
997         static hf_register_info hf[] = {
998
999                 { &hf_msg_hdr,
1000                         { "Message Header",           "sip.msg_hdr",
1001                         FT_NONE, 0, NULL, 0,
1002                         "Message Header in SIP message", HFILL }
1003                 },
1004                 { &hf_Method,
1005                        { "Method",              "sip.Method", 
1006                        FT_STRING, BASE_NONE,NULL,0x0,
1007                         "SIP Method", HFILL }
1008                 },
1009                 { &hf_Status_Code,
1010                        { "Status-Code",                 "sip.Status-Code", 
1011                        FT_STRING, BASE_NONE,NULL,0x0,
1012                         "SIP Status Code", HFILL }
1013                 },
1014                 { &hf_sip_to_addr,
1015                        { "SIP to address",              "sip.from_addr", 
1016                        FT_STRING, BASE_NONE,NULL,0x0,
1017                         "RFC 3261: from addr", HFILL }
1018                 },
1019                 { &hf_sip_from_addr,
1020                        { "SIP from address",            "sip.to_addr", 
1021                        FT_STRING, BASE_NONE,NULL,0x0,
1022                         "RFC 3261: to addr", HFILL }
1023                 },
1024                 { &hf_sip_tag,
1025                        { "SIP tag",             "sip.tag", 
1026                        FT_STRING, BASE_NONE,NULL,0x0,
1027                         "RFC 3261: tag", HFILL }
1028                 },
1029                 { &hf_header_array[POS_ACCEPT],
1030                        { "Accept",              "sip.Accept", 
1031                        FT_STRING, BASE_NONE,NULL,0x0,
1032                         "RFC 3261: Accept Header", HFILL }
1033                 },
1034                 { &hf_header_array[POS_ACCEPT_ENCODING],
1035                        { "Accept-Encoding",             "sip.Accept-Encoding", 
1036                        FT_STRING, BASE_NONE,NULL,0x0,
1037                         "RFC 3261: Accept-Encoding Header", HFILL }
1038                 },
1039                 { &hf_header_array[POS_ACCEPT_LANGUAGE],
1040                        { "Accept-Language",             "sip.Accept-Language", 
1041                        FT_STRING, BASE_NONE,NULL,0x0,
1042                         "RFC 3261: Accept-Language Header", HFILL }
1043                 },
1044                 { &hf_header_array[POS_ALERT_INFO],
1045                        { "Alert-Info",          "sip.Alert-Info", 
1046                        FT_STRING, BASE_NONE,NULL,0x0,
1047                         "RFC 3261: Alert-Info Header", HFILL }
1048                 },
1049                 { &hf_header_array[POS_ALLOW],
1050                        { "Allow",               "sip.Allow", 
1051                        FT_STRING, BASE_NONE,NULL,0x0,
1052                         "RFC 3261: Allow Header", HFILL }
1053                 },
1054                 { &hf_header_array[POS_ALLOW_EVENTS],
1055                        { "Allow-Events",                "sip.Allow-Events", 
1056                        FT_STRING, BASE_NONE,NULL,0x0,
1057                         "RFC 3265: Allow-Events Header", HFILL }
1058                 },
1059                 { &hf_header_array[POS_AUTHENTICATION_INFO],
1060                        { "Authentication-Info",                 "sip.Authentication-Info", 
1061                        FT_STRING, BASE_NONE,NULL,0x0,
1062                         "RFC 3261: Authentication-Info Header", HFILL }
1063                 },
1064                 { &hf_header_array[POS_AUTHORIZATION],
1065                        { "Authorization",               "sip.Authorization", 
1066                        FT_STRING, BASE_NONE,NULL,0x0,
1067                         "RFC 3261: Authorization Header", HFILL }
1068                 },
1069                 { &hf_header_array[POS_CALL_ID],
1070                        { "Call-ID",             "sip.Call-ID", 
1071                        FT_STRING, BASE_NONE,NULL,0x0,
1072                         "RFC 3261: Call-ID Header", HFILL }
1073                 },
1074                 { &hf_header_array[POS_CALL_INFO],
1075                        { "Call-Info",           "sip.Call-Info", 
1076                        FT_STRING, BASE_NONE,NULL,0x0,
1077                         "RFC 3261: Call-Info Header", HFILL }
1078                 },
1079                 { &hf_header_array[POS_CONTACT],
1080                        { "Contact",             "sip.Contact", 
1081                        FT_STRING, BASE_NONE,NULL,0x0,
1082                         "RFC 3261: Contact Header", HFILL }
1083                 },
1084                 { &hf_header_array[POS_CONTENT_DISPOSITION],
1085                        { "Content-Disposition",                 "sip.Content-Disposition", 
1086                        FT_STRING, BASE_NONE,NULL,0x0,
1087                         "RFC 3261: Content-Disposition Header", HFILL }
1088                 },
1089                 { &hf_header_array[POS_CONTENT_ENCODING],
1090                        { "Content-Encoding",            "sip.Content-Encoding", 
1091                        FT_STRING, BASE_NONE,NULL,0x0,
1092                         "RFC 3261: Content-Encoding Header", HFILL }
1093                 },
1094                 { &hf_header_array[POS_CONTENT_LANGUAGE],
1095                        { "Content-Language",            "sip.Content-Language", 
1096                        FT_STRING, BASE_NONE,NULL,0x0,
1097                         "RFC 3261: Content-Language Header", HFILL }
1098                 },
1099                 { &hf_header_array[POS_CONTENT_LENGTH],
1100                        { "Content-Length",              "sip.Content-Length", 
1101                        FT_STRING, BASE_NONE,NULL,0x0,
1102                         "RFC 3261: Content-Length Header", HFILL }
1103                 },
1104                 { &hf_header_array[POS_CONTENT_TYPE],
1105                        { "Content-Type",                "sip.Content-Type", 
1106                        FT_STRING, BASE_NONE,NULL,0x0,
1107                         "RFC 3261: Content-Type Header", HFILL }
1108                 },
1109                 { &hf_header_array[POS_CSEQ],
1110                        { "CSeq",                "sip.CSeq", 
1111                        FT_STRING, BASE_NONE,NULL,0x0,
1112                         "RFC 3261: CSeq Header", HFILL }
1113                 },
1114                 { &hf_header_array[POS_DATE],
1115                        { "Date",                "sip.Date", 
1116                        FT_STRING, BASE_NONE,NULL,0x0,
1117                         "RFC 3261: Date Header", HFILL }
1118                 },
1119                 { &hf_header_array[POS_ERROR_INFO],
1120                        { "Error-Info",          "sip.Error-Info", 
1121                        FT_STRING, BASE_NONE,NULL,0x0,
1122                         "RFC 3261: Error-Info Header", HFILL }
1123                 },
1124                 { &hf_header_array[POS_EVENT],
1125                        { "Event",               "sip.Event", 
1126                        FT_STRING, BASE_NONE,NULL,0x0,
1127                         "RFC 3265: Event Header", HFILL }
1128                 },
1129                 { &hf_header_array[POS_EXPIRES],
1130                        { "Expires",             "sip.Expires", 
1131                        FT_STRING, BASE_NONE,NULL,0x0,
1132                         "RFC 3261: Expires Header", HFILL }
1133                 },
1134                 { &hf_header_array[POS_FROM],
1135                        { "From",                "sip.From", 
1136                        FT_STRING, BASE_NONE,NULL,0x0,
1137                         "RFC 3261: From Header", HFILL }
1138                 },
1139                 { &hf_header_array[POS_IN_REPLY_TO],
1140                        { "In-Reply-To",                 "sip.In-Reply-To", 
1141                        FT_STRING, BASE_NONE,NULL,0x0,
1142                         "RFC 3261: In-Reply-To Header", HFILL }
1143                 },
1144                 { &hf_header_array[POS_MAX_FORWARDS],
1145                        { "Max-Forwards",                "sip.Max-Forwards", 
1146                        FT_STRING, BASE_NONE,NULL,0x0,
1147                         "RFC 3261: Max-Forwards Header", HFILL }
1148                 },
1149                 { &hf_header_array[POS_MIME_VERSION],
1150                        { "MIME-Version",                "sip.MIME-Version", 
1151                        FT_STRING, BASE_NONE,NULL,0x0,
1152                         "RFC 3261: MIME-Version Header", HFILL }
1153                 },
1154                 { &hf_header_array[POS_MIN_EXPIRES],
1155                        { "Min-Expires",                 "sip.Min-Expires", 
1156                        FT_STRING, BASE_NONE,NULL,0x0,
1157                         "RFC 3261: Min-Expires Header", HFILL }
1158                 },
1159                 { &hf_header_array[POS_ORGANIZATION],
1160                        { "Organization",                "sip.Organization", 
1161                        FT_STRING, BASE_NONE,NULL,0x0,
1162                         "RFC 3261: Organization Header", HFILL }
1163                 },
1164                 { &hf_header_array[POS_PRIORITY],
1165                        { "Priority",            "sip.Priority", 
1166                        FT_STRING, BASE_NONE,NULL,0x0,
1167                         "RFC 3261: Priority Header", HFILL }
1168                 },
1169                 { &hf_header_array[POS_PROXY_AUTHENTICATE],
1170                        { "Proxy-Authenticate",          "sip.Proxy-Authenticate", 
1171                        FT_STRING, BASE_NONE,NULL,0x0,
1172                         "RFC 3261: Proxy-Authenticate Header", HFILL }
1173                 },
1174                 { &hf_header_array[POS_PROXY_AUTHORIZATION],
1175                        { "Proxy-Authorization",                 "sip.Proxy-Authorization", 
1176                        FT_STRING, BASE_NONE,NULL,0x0,
1177                         "RFC 3261: Proxy-Authorization Header", HFILL }
1178                 },
1179                 { &hf_header_array[POS_RACK],
1180                        { "RAck",                "sip.RAck", 
1181                        FT_STRING, BASE_NONE,NULL,0x0,
1182                         "RFC 3262: RAck Header", HFILL }
1183                 },
1184                 { &hf_header_array[POS_RSEQ],
1185                        { "RSeq",                "sip.RSeq", 
1186                        FT_STRING, BASE_NONE,NULL,0x0,
1187                         "RFC 3262: RSeq Header", HFILL }
1188                 },
1189                 { &hf_header_array[POS_PROXY_REQUIRE],
1190                        { "Proxy-Require",               "sip.Proxy-Require", 
1191                        FT_STRING, BASE_NONE,NULL,0x0,
1192                         "RFC 3261: Proxy-Require Header", HFILL }
1193                 },
1194                 { &hf_header_array[POS_RECORD_ROUTE],
1195                        { "Record-Route",                "sip.Record-Route", 
1196                        FT_STRING, BASE_NONE,NULL,0x0,
1197                         "RFC 3261: Record-Route Header", HFILL }
1198                 },
1199                 { &hf_header_array[POS_REPLY_TO],
1200                        { "Reply-To",            "sip.Reply-To", 
1201                        FT_STRING, BASE_NONE,NULL,0x0,
1202                         "RFC 3261: Reply-To Header", HFILL }
1203                 },
1204                 { &hf_header_array[POS_REQUIRE],
1205                        { "Require",             "sip.Require", 
1206                        FT_STRING, BASE_NONE,NULL,0x0,
1207                         "RFC 3261: Require Header", HFILL }
1208                 },
1209                 { &hf_header_array[POS_RETRY_AFTER],
1210                        { "Retry-After",                 "sip.Retry-After", 
1211                        FT_STRING, BASE_NONE,NULL,0x0,
1212                         "RFC 3261: Retry-After Header", HFILL }
1213                 },
1214                 { &hf_header_array[POS_ROUTE],
1215                        { "Route",               "sip.Route", 
1216                        FT_STRING, BASE_NONE,NULL,0x0,
1217                         "RFC 3261: Route Header", HFILL }
1218                 },
1219                 { &hf_header_array[POS_SERVER],
1220                        { "Server",              "sip.Server", 
1221                        FT_STRING, BASE_NONE,NULL,0x0,
1222                         "RFC 3261: Server Header", HFILL }
1223                 },
1224                 { &hf_header_array[POS_SUBJECT],
1225                        { "Subject",             "sip.Subject", 
1226                        FT_STRING, BASE_NONE,NULL,0x0,
1227                         "RFC 3261: Subject Header", HFILL }
1228                 },
1229                 { &hf_header_array[POS_SUBSCRIPTION_STATE],
1230                        { "Subscription-State",          "sip.Subscription-State", 
1231                        FT_STRING, BASE_NONE,NULL,0x0,
1232                         "RFC 3265: Subscription-State Header", HFILL }
1233                 },
1234                 { &hf_header_array[POS_SUPPORTED],
1235                        { "Supported",           "sip.Supported", 
1236                        FT_STRING, BASE_NONE,NULL,0x0,
1237                         "RFC 3261: Supported Header", HFILL }
1238                 },
1239                 { &hf_header_array[POS_TIMESTAMP],
1240                        { "Timestamp",           "sip.Timestamp", 
1241                        FT_STRING, BASE_NONE,NULL,0x0,
1242                         "RFC 3261: Timestamp Header", HFILL }
1243                 },
1244                 { &hf_header_array[POS_TO],
1245                        { "To",          "sip.To", 
1246                        FT_STRING, BASE_NONE,NULL,0x0,
1247                         "RFC 3261: To Header", HFILL }
1248                 },
1249                 { &hf_header_array[POS_UNSUPPORTED],
1250                        { "Unsupported",                 "sip.Unsupported", 
1251                        FT_STRING, BASE_NONE,NULL,0x0,
1252                         "RFC 3261: Unsupported Header", HFILL }
1253                 },
1254                 { &hf_header_array[POS_USER_AGENT],
1255                        { "User-Agent",          "sip.User-Agent", 
1256                        FT_STRING, BASE_NONE,NULL,0x0,
1257                         "RFC 3261: User-Agent Header", HFILL }
1258                 },
1259                 { &hf_header_array[POS_VIA],
1260                        { "Via",                 "sip.Via", 
1261                        FT_STRING, BASE_NONE,NULL,0x0,
1262                         "RFC 3261: Via Header", HFILL }
1263                 },
1264                 { &hf_header_array[POS_WARNING],
1265                        { "Warning",             "sip.Warning", 
1266                        FT_STRING, BASE_NONE,NULL,0x0,
1267                         "RFC 3261: Warning Header", HFILL }
1268                 },
1269                 { &hf_header_array[POS_WWW_AUTHENTICATE],
1270                        { "WWW-Authenticate",            "sip.WWW-Authenticate", 
1271                        FT_STRING, BASE_NONE,NULL,0x0,
1272                         "RFC 3261: WWW-Authenticate Header", HFILL }
1273                 },
1274                 { &hf_header_array[POS_P_ACCESS_NETWORK_INFO],  
1275                        { "P-Access-Network-Info",       "sip.P-Access-Network-Info",  
1276                        FT_STRING, BASE_NONE,NULL,0x0,
1277                         "P-Access-Network-Info Header", HFILL }
1278                 },
1279
1280                 { &hf_header_array[POS_P_ASSERTED_IDENTITY],    
1281                        { "P-Asserted-Identity",         "sip.P-Asserted-Identity",  
1282                        FT_STRING, BASE_NONE,NULL,0x0,
1283                         "P-Asserted-Identity Header", HFILL }
1284                 },
1285
1286                 { &hf_header_array[POS_P_ASSOCIATED_URI],  
1287                        { "P-Associated-URI",            "sip.P-Associated-URI", 
1288                        FT_STRING, BASE_NONE,NULL,0x0,
1289                         "P-Associated-URI Header", HFILL }
1290                 },
1291
1292                 { &hf_header_array[POS_P_CALLED_PARTY_ID],  
1293                        { "P-Called-Party-ID",           "sip.P-Called-Party-ID", 
1294                        FT_STRING, BASE_NONE,NULL,0x0,
1295                         "P-Called-Party-ID Header", HFILL }
1296                 },
1297
1298                 { &hf_header_array[POS_P_CHARGING_FUNCTION_ADDRESSES],  
1299                        { "P-Charging-Function-Addresses","sip.P-Charging-Function-Addresses",  
1300                        FT_STRING, BASE_NONE,NULL,0x0,
1301                         "P-Charging-Function-Addresses", HFILL }
1302                 },
1303
1304                 { &hf_header_array[POS_P_CHARGING_VECTOR],
1305                        { "P-Charging-Vector",           "sip.P-Charging-Vector", 
1306                        FT_STRING, BASE_NONE,NULL,0x0,
1307                         "P-Charging-Vector Header", HFILL }
1308                 },
1309
1310                 { &hf_header_array[POS_P_DCS_TRACE_PARTY_ID], 
1311                        { "P-DCS-Trace-Party-ID",        "sip.P-DCS-Trace-Party-ID", 
1312                        FT_STRING, BASE_NONE,NULL,0x0,
1313                         "P-DCS-Trace-Party-ID Header", HFILL }
1314                 },
1315
1316                 { &hf_header_array[POS_P_DCS_OSPS],  
1317                        { "P-DCS-OSPS",                  "sip.P-DCS-OSPS", 
1318                        FT_STRING, BASE_NONE,NULL,0x0,
1319                         "P-DCS-OSPS Header", HFILL }
1320                 },
1321
1322                 { &hf_header_array[POS_P_DCS_BILLING_INFO],  
1323                        { "P-DCS-Billing-Info",          "sip.P-DCS-Billing-Info", 
1324                        FT_STRING, BASE_NONE,NULL,0x0,
1325                         "P-DCS-Billing-Info Header", HFILL }
1326                 },
1327
1328                 { &hf_header_array[POS_P_DCS_LAES],  
1329                        { "P-DCS-LAES",                  "sip.P-DCS-LAES", 
1330                        FT_STRING, BASE_NONE,NULL,0x0,
1331                         "P-DCS-LAES Header", HFILL }
1332                 },
1333
1334                 { &hf_header_array[POS_P_DCS_REDIRECT],  
1335                        { "P-DCS-Redirect",              "sip.P-DCS-Redirect", 
1336                        FT_STRING, BASE_NONE,NULL,0x0,
1337                         "P-DCS-Redirect Header", HFILL }
1338                 },
1339
1340                 { &hf_header_array[POS_P_MEDIA_AUTHORIZATION],  
1341                        { "P-Media-Authorization",       "sip.P-Media-Authorization", 
1342                        FT_STRING, BASE_NONE,NULL,0x0,
1343                         "P-Media-Authorization Header", HFILL }
1344                 },
1345
1346                 { &hf_header_array[POS_P_PREFERRED_IDENTITY],  
1347                        { "P-Preferred-Identity",        "sip.P-Preferred-Identity", 
1348                        FT_STRING, BASE_NONE,NULL,0x0,
1349                         "P-Preferred-Identity Header", HFILL }
1350                 },
1351
1352                 { &hf_header_array[POS_P_VISITED_NETWORK_ID],  
1353                        { "P-Visited-Network-ID",        "sip.P-Visited-Network-ID",  
1354                        FT_STRING, BASE_NONE,NULL,0x0,
1355                         "P-Visited-Network-ID Header", HFILL }
1356                 },
1357
1358                 { &hf_header_array[POS_PATH],  
1359                        { "Path",                        "sip.Path", 
1360                        FT_STRING, BASE_NONE,NULL,0x0,
1361                         "Path Header", HFILL }
1362                 },
1363
1364                 { &hf_header_array[POS_PRIVACY],  
1365                        { "Privacy",                     "sip.Privacy", 
1366                        FT_STRING, BASE_NONE,NULL,0x0,
1367                         "Privacy Header", HFILL }
1368                 },
1369
1370                 { &hf_header_array[POS_REASON], 
1371                        { "Reason",                      "sip.Reason", 
1372                        FT_STRING, BASE_NONE,NULL,0x0,
1373                         "Reason Header", HFILL }
1374                 },
1375
1376                 { &hf_header_array[POS_REFER_TO], 
1377                        { "Refer-To",                    "sip.Refer-To", 
1378                        FT_STRING, BASE_NONE,NULL,0x0,
1379                         "Refer-To Header", HFILL }
1380                 },
1381
1382                 { &hf_header_array[POS_SERVICE_ROUTE],                  
1383                        { "Service-Route",               "sip.Service-Route", 
1384                        FT_STRING, BASE_NONE,NULL,0x0,
1385                         "Service-Route Header", HFILL }
1386                 },
1387
1388                 { &hf_header_array[POS_ETAG],                  
1389                        { "ETag",                "sip.ETag", 
1390                        FT_STRING, BASE_NONE,NULL,0x0,
1391                         "ETag Header", HFILL }
1392                 },
1393                 { &hf_header_array[POS_IF_MATCH],                  
1394                        { "If_Match",            "sip.If_Match", 
1395                        FT_STRING, BASE_NONE,NULL,0x0,
1396                         "If-Match Header", HFILL }
1397                 },
1398         };
1399
1400         /* Setup protocol subtree array */
1401         static gint *ett[] = {
1402                 &ett_sip,
1403                 &ett_sip_reqresp,
1404                 &ett_sip_hdr,
1405                 &ett_sip_element,
1406                 &ett_sip_message_body,
1407         };
1408         static gint *ett_raw[] = {
1409                 &ett_raw_text,
1410         };
1411
1412         module_t *sip_module;
1413
1414         /* Register the protocol name and description */
1415         proto_sip = proto_register_protocol("Session Initiation Protocol",
1416             "SIP", "sip");
1417         proto_raw_sip = proto_register_protocol("Session Initiation Protocol (SIP as raw text)",
1418             "Raw_SIP", "raw_sip");
1419
1420         /* Required function calls to register the header fields and subtrees used */
1421         proto_register_field_array(proto_sip, hf, array_length(hf));
1422         proto_register_subtree_array(ett, array_length(ett));
1423         proto_register_subtree_array(ett_raw, array_length(ett_raw));
1424
1425         /* SIP content type and internet media type used by other dissectors are the same */
1426
1427         media_type_dissector_table = find_dissector_table("media_type");
1428
1429
1430         sip_module = prefs_register_protocol(proto_sip, NULL);
1431
1432         prefs_register_bool_preference(sip_module, "display_raw_text",
1433                 "Display raw text for SIP message",
1434                 "Specifies that the raw text of the "
1435                 "SIP message should be displayed "
1436                 "in addition to the dissection tree",
1437                 &global_sip_raw_text);
1438 }
1439
1440 void
1441 proto_reg_handoff_sip(void)
1442 {
1443         dissector_handle_t sip_handle, sip_tcp_handle;
1444
1445         sip_handle = new_create_dissector_handle(dissect_sip, proto_sip);
1446         dissector_add("udp.port", UDP_PORT_SIP, sip_handle);
1447
1448         sip_tcp_handle = create_dissector_handle(dissect_sip_tcp, proto_sip);
1449         dissector_add("tcp.port", TCP_PORT_SIP, sip_tcp_handle);
1450
1451         heur_dissector_add("udp", dissect_sip_heur, proto_sip);
1452         heur_dissector_add("tcp", dissect_sip_heur, proto_sip);
1453         heur_dissector_add("sctp", dissect_sip_heur, proto_sip);
1454
1455 }