Mercurial > hg > freeDiameter
changeset 726:c0c0a7781b09
Added new contribution: Wireshark patch to display Diameter over TLS over SCTP
author | Sebastien Decugis <sdecugis@nict.go.jp> |
---|---|
date | Wed, 23 Feb 2011 16:00:47 +0900 |
parents | 8b03c672261f |
children | bfe14a099603 |
files | contrib/README contrib/wireshark/HOWTO contrib/wireshark/sample/192.168.103.10.priv.pem contrib/wireshark/sample/192.168.103.20.priv.pem contrib/wireshark/sample/README contrib/wireshark/sample/capture.cap contrib/wireshark/wireshark-1.2.7-diameter-tls.patch |
diffstat | 7 files changed, 842 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/contrib/README Tue Feb 22 15:50:45 2011 +0900 +++ b/contrib/README Wed Feb 23 16:00:47 2011 +0900 @@ -50,3 +50,6 @@ - dict_legacy: XML and DTD files for the dict_legacy_xml.fdx extension. + +- wireshark: This contains some information on how to use Wireshark to monitor Diameter + exchange protected with TLS. It involves patching the wireshark software.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/contrib/wireshark/HOWTO Wed Feb 23 16:00:47 2011 +0900 @@ -0,0 +1,68 @@ + -------- + FOREWORD + -------- + +The patch in this folder allows Wireshark to process packets that contain TLS-protected +Diameter messages over SCTP multi-stream associations. Each SCTP stream pairs is handled +as a separate TLS channel (RFC3436), which is consistent with freeDiameter 1.0.x mechanism. + +It should be noted however that rfc3588bis (revised Diameter) recommends that DTLS is used +instead of TLS over SCTP, for the reasons highlighted in the introduction of RFC6083. +When this new mechanism is implemented in freeDiameter, a different patch will probably +be required for wireshark. + + +The instructions in this file will change your wireshark binary in a way suitable for +analysis of Diameter over TLS over SCTP, but may have unexpected side-effects +on some other protocols analysis (including DTLS). + +The instructions refer to Debian-style packaging (apt), you should adapt +the process to build a new modified package of wireshark for your distribution. + +The provided patch has been successfully tested with: + - wireshark-1.2.7 (Ubuntu Lucid) + - wireshark-1.2.11 (Ubuntu Maverick) +It may or may not work on more recent or ancient versions. + + + ------------ + INSTRUCTIONS + ------------ + +The steps are: + - get your wireshark source + apt-get source wireshark + cd wireshark-1.2.* + + - apply the patch + cat ~/wireshark-1.2.7-diameter-tls.patch | patch -p1 + + - increase the version number + dch -lfD "Added support for Diameter over TLS over SCTP" + + - Create a new package, this might take a while + debian/rules binary + + - Install the modified version + sudo dpkg --install ../wireshark-common_*fD*.deb ../wireshark_*fD*.deb + + - Start the new wireshark: + wireshark & + +To analyze a capture file, you will need the private keys of both peers involved. + +Let's imagine for example: + peer A with IP address 192.168.0.10 has private key privA.pem + peer B with IP address 192.168.0.11 has private key privB.pem + +In wireshark you must do the following: + - go to menu Edit->Preferences + - In the left panel, under Protocols, scroll to "SSL" and select it. + - In the right panel, fill "RSA keys list" as follow: + 192.168.0.10,3869,diameter,/absolute/path/to/privA.pem;192.168.0.11,3869,diameter,/absolute/path/to/privB.pem + - You may find also useful to select an SSL debug file to get a hint of any problem. + +Once this configuration is complete, you should be able to see the contents of SCTP packets, +including protected Diameter payload. + +Check the "sample" subdirectory for a test capture file.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/contrib/wireshark/sample/192.168.103.10.priv.pem Wed Feb 23 16:00:47 2011 +0900 @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQDMcXy2iVqcXkGaY44yNihVNzW/zHptqID49/ZyyyOinxHenvf9 +o/fr613XvUuyquaapL99yiMPuLU3I1UxxacWBSAb496eGd7fY1Udw1RtqKCeb60c +jpTc3zKySGPHtnzOxeSMDK/R6uqkFirF6Lnu18mKZyAwJtvFYnh0wK3SwwIDAQAB +AoGAa6kX08hhPxcj1Pm4WBjNBJMeavJzRmwF/xYVYj43ddvuvR1Z2ugOFt7LfGDj +DCOTbLx1Wvinng/W3kJtCtjbM3w3k5cuFJdJcURXda73IHSaJOHnBAw5RlvFCE79 +12yKqGOBgy80gGHDlqnSIjISCGb/9wLcHYLccakekckPc4ECQQDubt5fWzN4wUwU +yW+e/SO9Vz4j+FiIC2aZy2OM9XXt6cgh4v0hQ3l0sWVJ6lTvK17aD9LXE5rluAOI +thnPZElFAkEA24GH8Po/+3K6A5d5Zh1+hwoMLbWrykQDWSOgtmaOtbAvezlolF8O +W18pVdvyMJg3gUiCA/rHG+r+OBxa4sx4ZwJAH4c1jHJo2fzlbJI+Wk2q3iydIPCD +9GldhdSpM0h58Z3KQwDa6/0aIF4cwKtl08JuZnNVM+95ugqdHQTHYO8n6QJBAIgO +m+KEWxBSpnX/d+IRuhGd6rqSdu8ihSjFaqJko2R+1o98oBQHb3C3ZXmwoUf5sb3S +4bPxx2TIndbNzI/zyVUCQGqN7eyoeTxtPD8P08lUGTUnC2n0imZ1mU5p8Bnv8gw5 +lwt9qxuz0Ujr7uFPPu58bvGsYeoFUV23WRmS0rKLXv0= +-----END RSA PRIVATE KEY-----
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/contrib/wireshark/sample/192.168.103.20.priv.pem Wed Feb 23 16:00:47 2011 +0900 @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXgIBAAKBgQDef8CrqawfvmCLBwmlPRlWjwB6V4TvVMRhivAYlwwFbUSoU5bm +2D780IBr3fNL3zP38ySa7r9cXxPgk7mbj3PhcJbI0Ix0AjQdFSB08AOXev4gqU8p +qgEODFV04tnFhOcDysp77qH/DFuNwxd2xtFUbGKfGhroAssHxJuogOmiWQIDAQAB +AoGAP6H7wVyCLIXu6HP3zzkdIQM+2L5k92mfzGHG7tFsD7VDWHyngJfB093xjGfq +p/1KyJPSGTlEoy9R6P12rMWnFv7sYYKmPGfKdRUMxZYIXbplw6+L/gwW3MCiOMDD +zRzRjknE3a+Mjo3e2XMHh6Z+GJ61megMeGInODP05/h66AECQQDyFhT+D8DVj1hp +RlaYTFDKCmS9rgMQ+g4YyqMLzuakkKwaJwbCIlMbQortGBvY9I+0uZC4jklcOpnl +YYcGIUEBAkEA60l5uAVBk6vKWKWX2cksBP/VlJM2B9pkvmlL7tPwJVEfoaAzZx4N +rPpC9sOsFlX1ShpirAmIqmvY16in4xEJWQJBAOvULSEOcZjZapQrjEIS3gTkOR06 +fgw0vDTUeh8PsEmSEcXsTL4jt/fvS+0KNl6UZ8Xzm5LeMYLiJ3d4GZQUIwECQQCb +vYLoH/KMQMYrb1DYQ6TzmjRRqC+3ewP8Vc6BQ6BN0yjQ3y2nL+l1eiIhHNwn3LYE +Wvq9TYI87C4YcfbPAlPhAkEA0bNU/Utgdbv/yT4lUmw+0toqFHkcT5s13RFWzNJU +KdQ308kwz9rSDmuQ8eYzn5V02TioJKV4r0NZz+WcCyDY3A== +-----END RSA PRIVATE KEY-----
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/contrib/wireshark/sample/README Wed Feb 23 16:00:47 2011 +0900 @@ -0,0 +1,56 @@ +This folder contains an example capture file, as well as the two +private keys required to decode the TLS-protected exchanges. + +In order to decrypt properly the packets, you'll need a patched wireshark (see parent directory) +and the SSL "RSA Private Keys" properties set to (replace with real full path): + 192.168.103.10,3869,diameter,freeDiameter/contrib/wireshark/sample/192.168.103.10.priv.pem;192.168.103.20,3869,diameter,freeDiameter/contrib/wireshark/sample/192.168.103.20.priv.pem + + +This capture contains everything that was exchanged by the peer since it boot up. +The captured peer is "relay.a.rt.freediameter.net" with IP address 192.168.103.20. + +Here is the detail of what you can see in the capture, if the decyphering +works as expected, in chronological order: + +----------------------------------------------------------------------------- +Frames | Comments +----------------------------------------------------------------------------- +1-24 | Peer booting up: DHCP, NTP, ... + | +25-29 | Connection attempt from 192.168.103.10 + | first attempt on SCTP (frames 26-27) + | then on TCP (frames 28-29) + | +32-35 | freeDiameter starting: Diameter Identities + | from the peer's configuration file are + | DNS resolved. + | +36-39 | SCTP connection to 192.168.103.10 + | +40-45 | Failed attempt to connect to 192.168.103.30 + | where freeDiameter was not started. + | +46-49 | (I think this is trigged by Debug output, + | I have to check) + | +50-73 | TLS handshake on first stream pair (#0). + | +74-90 | Resumed handshakes on streams #1 and #2 in parallel. + | (not sure where to find that it is resumed, + | except that certificates are not re-exchanged) + | +91-92 | CER/CEA exchange. +93-96 | DWR/DWA exchange. + | +103-118 | SCTP heartbeats are exchanged more frequently than DWR/DWA. + | +119-124 | Concurrent DWR/DWA (it happens sometimes) + | +125-128 | Another failed attempt to 192.168.103.30 (cf. frames 40-45) + | +137-140 | DPR/DPA exchange. + | +141-153 | TLS clean shutdown on all streams in parallel. + | +154-157 | SCTP association is closed. +-----------------------------------------------------------------------------
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/contrib/wireshark/wireshark-1.2.7-diameter-tls.patch Wed Feb 23 16:00:47 2011 +0900 @@ -0,0 +1,685 @@ +diff -Nur wireshark-1.2.7/epan/conversation.c wireshark-1.2.7-fD/epan/conversation.c +--- wireshark-1.2.7/epan/conversation.c 2010-04-01 01:44:39.000000000 +0900 ++++ wireshark-1.2.7-fD/epan/conversation.c 2011-02-23 14:26:35.000000000 +0900 +@@ -40,6 +40,11 @@ + static GHashTable *conversation_hashtable_exact = NULL; + + /* ++ * Hash table for conversations without strid. ++ */ ++static GHashTable *conversation_hashtable_no_strid = NULL; ++ ++/* + * Hash table for conversations with one wildcard address. + */ + static GHashTable *conversation_hashtable_no_addr2 = NULL; +@@ -63,6 +68,7 @@ + port_type ptype; + guint32 port1; + guint32 port2; ++ guint32 strid; + } conversation_key; + #endif + /* +@@ -193,6 +199,7 @@ + hash_val += key->port1; + ADD_ADDRESS_TO_HASH(hash_val, &key->addr2); + hash_val += key->port2; ++ hash_val += key->strid; + + return hash_val; + } +@@ -217,6 +224,78 @@ + */ + if (v1->port1 == v2->port1 && + v1->port2 == v2->port2 && ++ v1->strid == v2->strid && ++ ADDRESSES_EQUAL(&v1->addr1, &v2->addr1) && ++ ADDRESSES_EQUAL(&v1->addr2, &v2->addr2)) { ++ /* ++ * Yes. It's the same conversation, and the two ++ * address/port pairs are going in the same direction. ++ */ ++ return 1; ++ } ++ ++ /* ++ * Is the first port 2 the same as the second port 1, the first ++ * port 1 the same as the second port 2, the first address 2 ++ * the same as the second address 1, and the first address 1 ++ * the same as the second address 2? ++ */ ++ if (v1->port2 == v2->port1 && ++ v1->port1 == v2->port2 && ++ v1->strid == v2->strid && ++ ADDRESSES_EQUAL(&v1->addr2, &v2->addr1) && ++ ADDRESSES_EQUAL(&v1->addr1, &v2->addr2)) { ++ /* ++ * Yes. It's the same conversation, and the two ++ * address/port pairs are going in opposite directions. ++ */ ++ return 1; ++ } ++ ++ /* ++ * The addresses or the ports don't match. ++ */ ++ return 0; ++} ++ ++/* ++ * Compute the hash value for two given address/port pairs if the match ++ * has a wildcard stream id. ++ */ ++static guint ++conversation_hash_no_strid(gconstpointer v) ++{ ++ const conversation_key *key = (const conversation_key *)v; ++ guint hash_val; ++ ++ hash_val = 0; ++ ADD_ADDRESS_TO_HASH(hash_val, &key->addr1); ++ hash_val += key->port1; ++ hash_val += key->port2; ++ ++ return hash_val; ++} ++ ++/* ++ * Compare two conversation keys, except for the stream id value. ++ */ ++static gint ++conversation_match_no_strid(gconstpointer v, gconstpointer w) ++{ ++ const conversation_key *v1 = (const conversation_key *)v; ++ const conversation_key *v2 = (const conversation_key *)w; ++ ++ if (v1->ptype != v2->ptype) ++ return 0; /* different types of port */ ++ ++ /* ++ * Are the first and second port 1 values the same, the first and ++ * second port 2 values the same, the first and second address ++ * 1 values the same, and the first and second address 2 values ++ * the same? ++ */ ++ if (v1->port1 == v2->port1 && ++ v1->port2 == v2->port2 && + ADDRESSES_EQUAL(&v1->addr1, &v2->addr1) && + ADDRESSES_EQUAL(&v1->addr2, &v2->addr2)) { + /* +@@ -263,6 +342,7 @@ + ADD_ADDRESS_TO_HASH(hash_val, &key->addr1); + hash_val += key->port1; + hash_val += key->port2; ++ hash_val += key->strid; + + return hash_val; + } +@@ -289,6 +369,7 @@ + */ + if (v1->port1 == v2->port1 && + v1->port2 == v2->port2 && ++ v1->strid == v2->strid && + ADDRESSES_EQUAL(&v1->addr1, &v2->addr1)) { + /* + * Yes. It's the same conversation, and the two +@@ -317,6 +398,7 @@ + ADD_ADDRESS_TO_HASH(hash_val, &key->addr1); + hash_val += key->port1; + ADD_ADDRESS_TO_HASH(hash_val, &key->addr2); ++ hash_val += key->strid; + + return hash_val; + } +@@ -342,6 +424,7 @@ + * address 2 values the same? + */ + if (v1->port1 == v2->port1 && ++ v1->strid == v2->strid && + ADDRESSES_EQUAL(&v1->addr1, &v2->addr1) && + ADDRESSES_EQUAL(&v1->addr2, &v2->addr2)) { + /* +@@ -370,6 +453,7 @@ + hash_val = 0; + ADD_ADDRESS_TO_HASH(hash_val, &key->addr1); + hash_val += key->port1; ++ hash_val += key->strid; + + return hash_val; + } +@@ -394,6 +478,7 @@ + * and second address 1 values the same? + */ + if (v1->port1 == v2->port1 && ++ v1->strid == v2->strid && + ADDRESSES_EQUAL(&v1->addr1, &v2->addr1)) { + /* + * Yes. It's the same conversation, and the two +@@ -420,6 +505,8 @@ + conversation_keys = NULL; + if (conversation_hashtable_exact != NULL) + g_hash_table_destroy(conversation_hashtable_exact); ++ if (conversation_hashtable_no_strid != NULL) ++ g_hash_table_destroy(conversation_hashtable_no_strid); + if (conversation_hashtable_no_addr2 != NULL) + g_hash_table_destroy(conversation_hashtable_no_addr2); + if (conversation_hashtable_no_port2 != NULL) +@@ -438,6 +525,9 @@ + conversation_hashtable_exact = + g_hash_table_new(conversation_hash_exact, + conversation_match_exact); ++ conversation_hashtable_no_strid = ++ g_hash_table_new(conversation_hash_no_strid, ++ conversation_match_no_strid); + conversation_hashtable_no_addr2 = + g_hash_table_new(conversation_hash_no_addr2, + conversation_match_no_addr2); +@@ -466,6 +556,15 @@ + conversation_new(guint32 setup_frame, address *addr1, address *addr2, port_type ptype, + guint32 port1, guint32 port2, guint options) + { ++ return conversation_new_ext(setup_frame, addr1, addr2, ptype, ++ port1, port2, options & ~(DISTINCT_SCTP_STREAMID), 0); ++ ++} ++ ++conversation_t * ++conversation_new_ext(guint32 setup_frame, address *addr1, address *addr2, port_type ptype, ++ guint32 port1, guint32 port2, guint options, guint16 strid) ++{ + /* + DISSECTOR_ASSERT(!(options | CONVERSATION_TEMPLATE) || ((options | (NO_ADDR2 | NO_PORT2 | NO_PORT2_FORCE))) && + "A conversation template may not be constructed without wildcard options"); +@@ -486,7 +585,11 @@ + if (options & (NO_PORT2|NO_PORT2_FORCE)) { + hashtable = conversation_hashtable_no_port2; + } else { +- hashtable = conversation_hashtable_exact; ++ if (options & DISTINCT_SCTP_STREAMID) { ++ hashtable = conversation_hashtable_exact; ++ } else { ++ hashtable = conversation_hashtable_no_strid; ++ } + } + } + +@@ -495,6 +598,7 @@ + existing_key.ptype = ptype; + existing_key.port1 = port1; + existing_key.port2 = port2; ++ existing_key.strid = strid; + + conversation = g_hash_table_lookup(hashtable, &existing_key); + tc = conversation; /* Remember if lookup was successful */ +@@ -507,6 +611,7 @@ + new_key->ptype = ptype; + new_key->port1 = port1; + new_key->port2 = port2; ++ new_key->strid = strid; + + if (conversation) { + for (; conversation->next; conversation = conversation->next) +@@ -568,8 +673,13 @@ + g_hash_table_insert(conversation_hashtable_no_addr2, + conv->key_ptr, conv); + } else { +- g_hash_table_insert(conversation_hashtable_exact, +- conv->key_ptr, conv); ++ if (conv->options & DISTINCT_SCTP_STREAMID) { ++ g_hash_table_insert(conversation_hashtable_exact, ++ conv->key_ptr, conv); ++ } else { ++ g_hash_table_insert(conversation_hashtable_no_strid, ++ conv->key_ptr, conv); ++ } + } + } + +@@ -602,18 +712,23 @@ + g_hash_table_insert(conversation_hashtable_no_port2, + conv->key_ptr, conv); + } else { +- g_hash_table_insert(conversation_hashtable_exact, +- conv->key_ptr, conv); ++ if (conv->options & DISTINCT_SCTP_STREAMID) { ++ g_hash_table_insert(conversation_hashtable_exact, ++ conv->key_ptr, conv); ++ } else { ++ g_hash_table_insert(conversation_hashtable_no_strid, ++ conv->key_ptr, conv); ++ } + } + } + + /* + * Search a particular hash table for a conversation with the specified +- * {addr1, port1, addr2, port2} and set up before frame_num. ++ * {addr1, port1, addr2, port2, strid} and set up before frame_num. + */ + static conversation_t * + conversation_lookup_hashtable(GHashTable *hashtable, guint32 frame_num, address *addr1, address *addr2, +- port_type ptype, guint32 port1, guint32 port2) ++ port_type ptype, guint32 port1, guint32 port2, guint16 strid) + { + conversation_t* conversation; + conversation_t* match; +@@ -628,6 +743,7 @@ + key.ptype = ptype; + key.port1 = port1; + key.port2 = port2; ++ key.strid = strid; + + match = g_hash_table_lookup(hashtable, &key); + +@@ -685,12 +801,19 @@ + find_conversation(guint32 frame_num, address *addr_a, address *addr_b, port_type ptype, + guint32 port_a, guint32 port_b, guint options) + { ++ return find_conversation_ext(frame_num, addr_a, addr_b, ptype, ++ port_a, port_b, options | IGNORE_SCTP_STREAMID, 0); ++} ++conversation_t * ++find_conversation_ext(guint32 frame_num, address *addr_a, address *addr_b, port_type ptype, ++ guint32 port_a, guint32 port_b, guint options, guint16 strid) ++{ + conversation_t *conversation; + + /* +- * First try an exact match, if we have two addresses and ports. ++ * First try an exact match, if we have two addresses and ports and strid. + */ +- if (!(options & (NO_ADDR_B|NO_PORT_B))) { ++ if (!(options & (NO_ADDR_B|NO_PORT_B|IGNORE_SCTP_STREAMID))) { + /* + * Neither search address B nor search port B are wildcarded, + * start out with an exact match. +@@ -699,7 +822,7 @@ + conversation = + conversation_lookup_hashtable(conversation_hashtable_exact, + frame_num, addr_a, addr_b, ptype, +- port_a, port_b); ++ port_a, port_b, strid); + if ((conversation == NULL) && (addr_a->type == AT_FC)) { + /* In Fibre channel, OXID & RXID are never swapped as + * TCP/UDP ports are in TCP/IP. +@@ -707,7 +830,33 @@ + conversation = + conversation_lookup_hashtable(conversation_hashtable_exact, + frame_num, addr_b, addr_a, ptype, +- port_a, port_b); ++ port_a, port_b, strid); ++ } ++ if (conversation != NULL) ++ return conversation; ++ } ++ ++ /* ++ * Then, ignoring strid try an exact match, if we have two addresses and ports. ++ */ ++ if (!(options & (NO_ADDR_B|NO_PORT_B|NO_IGNORE_SCTP_STREAMID))) { ++ /* ++ * Neither search address B nor search port B are wildcarded, ++ * start out with an exact match. ++ * Exact matches check both directions. ++ */ ++ conversation = ++ conversation_lookup_hashtable(conversation_hashtable_no_strid, ++ frame_num, addr_a, addr_b, ptype, ++ port_a, port_b, strid); ++ if ((conversation == NULL) && (addr_a->type == AT_FC)) { ++ /* In Fibre channel, OXID & RXID are never swapped as ++ * TCP/UDP ports are in TCP/IP. ++ */ ++ conversation = ++ conversation_lookup_hashtable(conversation_hashtable_no_strid, ++ frame_num, addr_b, addr_a, ptype, ++ port_a, port_b, strid); + } + if (conversation != NULL) + return conversation; +@@ -729,7 +878,7 @@ + */ + conversation = + conversation_lookup_hashtable(conversation_hashtable_no_addr2, +- frame_num, addr_a, addr_b, ptype, port_a, port_b); ++ frame_num, addr_a, addr_b, ptype, port_a, port_b, strid); + if ((conversation == NULL) && (addr_a->type == AT_FC)) { + /* In Fibre channel, OXID & RXID are never swapped as + * TCP/UDP ports are in TCP/IP. +@@ -737,7 +886,7 @@ + conversation = + conversation_lookup_hashtable(conversation_hashtable_no_addr2, + frame_num, addr_b, addr_a, ptype, +- port_a, port_b); ++ port_a, port_b, strid); + } + if (conversation != NULL) { + /* +@@ -779,7 +928,7 @@ + if (!(options & NO_ADDR_B)) { + conversation = + conversation_lookup_hashtable(conversation_hashtable_no_addr2, +- frame_num, addr_b, addr_a, ptype, port_b, port_a); ++ frame_num, addr_b, addr_a, ptype, port_b, port_a, strid); + if (conversation != NULL) { + /* + * If this is for a connection-oriented +@@ -821,14 +970,14 @@ + */ + conversation = + conversation_lookup_hashtable(conversation_hashtable_no_port2, +- frame_num, addr_a, addr_b, ptype, port_a, port_b); ++ frame_num, addr_a, addr_b, ptype, port_a, port_b, strid); + if ((conversation == NULL) && (addr_a->type == AT_FC)) { + /* In Fibre channel, OXID & RXID are never swapped as + * TCP/UDP ports are in TCP/IP + */ + conversation = + conversation_lookup_hashtable(conversation_hashtable_no_port2, +- frame_num, addr_b, addr_a, ptype, port_a, port_b); ++ frame_num, addr_b, addr_a, ptype, port_a, port_b, strid); + } + if (conversation != NULL) { + /* +@@ -870,7 +1019,7 @@ + if (!(options & NO_PORT_B)) { + conversation = + conversation_lookup_hashtable(conversation_hashtable_no_port2, +- frame_num, addr_b, addr_a, ptype, port_b, port_a); ++ frame_num, addr_b, addr_a, ptype, port_b, port_a, strid); + if (conversation != NULL) { + /* + * If this is for a connection-oriented +@@ -907,7 +1056,7 @@ + */ + conversation = + conversation_lookup_hashtable(conversation_hashtable_no_addr2_or_port2, +- frame_num, addr_a, addr_b, ptype, port_a, port_b); ++ frame_num, addr_a, addr_b, ptype, port_a, port_b, strid); + if (conversation != NULL) { + /* + * If this is for a connection-oriented protocol: +@@ -952,11 +1101,11 @@ + if (addr_a->type == AT_FC) + conversation = + conversation_lookup_hashtable(conversation_hashtable_no_addr2_or_port2, +- frame_num, addr_b, addr_a, ptype, port_a, port_b); ++ frame_num, addr_b, addr_a, ptype, port_a, port_b, strid); + else + conversation = + conversation_lookup_hashtable(conversation_hashtable_no_addr2_or_port2, +- frame_num, addr_b, addr_a, ptype, port_b, port_a); ++ frame_num, addr_b, addr_a, ptype, port_b, port_a, strid); + if (conversation != NULL) { + /* + * If this is for a connection-oriented protocol, set the +diff -Nur wireshark-1.2.7/epan/conversation.h wireshark-1.2.7-fD/epan/conversation.h +--- wireshark-1.2.7/epan/conversation.h 2010-04-01 01:44:39.000000000 +0900 ++++ wireshark-1.2.7-fD/epan/conversation.h 2011-02-23 14:25:44.000000000 +0900 +@@ -39,11 +39,13 @@ + * TEMPLATE flag will be altered once the first connections (connection + * oriented protocols only) to include the newly found information which + * matched the wildcard options. ++ * DISTINCT_SCTP_STREAMID will also save the SCTP stream identifier, if any. + */ + #define NO_ADDR2 0x01 + #define NO_PORT2 0x02 + #define NO_PORT2_FORCE 0x04 + #define CONVERSATION_TEMPLATE 0x08 ++#define DISTINCT_SCTP_STREAMID 0x10 + + /* + * Flags to pass to "find_conversation()" to indicate that the address B +@@ -51,6 +53,8 @@ + */ + #define NO_ADDR_B 0x01 + #define NO_PORT_B 0x02 ++#define IGNORE_SCTP_STREAMID 0x04 ++#define NO_IGNORE_SCTP_STREAMID 0x08 + + #include "packet.h" /* for conversation dissector type */ + +@@ -64,6 +68,7 @@ + port_type ptype; + guint32 port1; + guint32 port2; ++ guint16 strid; + } conversation_key; + + typedef struct conversation { +@@ -85,6 +90,13 @@ + extern conversation_t *find_conversation(guint32 frame_num, address *addr_a, address *addr_b, + port_type ptype, guint32 port_a, guint32 port_b, guint options); + ++/* for SCTP stream */ ++extern conversation_t *conversation_new_ext(guint32 setup_frame, address *addr1, address *addr2, ++ port_type ptype, guint32 port1, guint32 port2, guint options, guint16 strid); ++extern conversation_t *find_conversation_ext(guint32 frame_num, address *addr_a, address *addr_b, ++ port_type ptype, guint32 port_a, guint32 port_b, guint options, guint16 strid); ++ ++ + extern void conversation_add_proto_data(conversation_t *conv, int proto, + void *proto_data); + extern void *conversation_get_proto_data(conversation_t *conv, int proto); +diff -Nur wireshark-1.2.7/epan/dissectors/packet-diameter.c wireshark-1.2.7-fD/epan/dissectors/packet-diameter.c +--- wireshark-1.2.7/epan/dissectors/packet-diameter.c 2010-04-01 01:44:21.000000000 +0900 ++++ wireshark-1.2.7-fD/epan/dissectors/packet-diameter.c 2011-02-23 13:33:10.000000000 +0900 +@@ -63,8 +63,10 @@ + #include "packet-ntp.h" + #include "packet-diameter.h" + #include "diam_dict.h" ++#include "packet-ssl.h" + + #define SCTP_PORT_DIAMETER 3868 ++#define SCTP_TLS_PORT_DIAMETER 3869 + + /* Diameter Header Flags */ + /* RPETrrrrCCCCCCCCCCCCCCCCCCCCCCCC */ +@@ -271,10 +273,13 @@ + + + static guint gbl_diameterSctpPort=SCTP_PORT_DIAMETER; ++static guint gbl_diameterSctpTlsPort=SCTP_TLS_PORT_DIAMETER; + + static dissector_handle_t diameter_tcp_handle; + static range_t *global_diameter_tcp_port_range; ++static range_t *global_diameter_tcp_tls_port_range; + #define DEFAULT_DIAMETER_PORT_RANGE "3868" ++#define DEFAULT_DIAMETER_TLS_PORT_RANGE "3869" + + /* desegmentation of Diameter over TCP */ + static gboolean gbl_diameter_desegment = TRUE; +@@ -1358,13 +1363,27 @@ + dissector_add("tcp.port", port, diameter_tcp_handle); + } + ++static void ++range_delete_callback_sec(guint32 port) ++{ ++ ssl_dissector_delete(port, "diameter", TRUE); ++} ++ ++static void ++range_add_callback_sec(guint32 port) ++{ ++ ssl_dissector_add(port, "diameter", TRUE); ++} ++ + void + proto_reg_handoff_diameter(void) + { + static gboolean Initialized=FALSE; + static guint SctpPort; ++ static guint SctpsPort; + static dissector_handle_t diameter_handle; + static range_t *diameter_tcp_port_range; ++ static range_t *diameters_tcp_port_range; + + if (!Initialized) { + diameter_handle = find_dissector("diameter"); +@@ -1382,20 +1401,27 @@ + /* AVP Code: 463 EAP-Reissued-Payload */ + dissector_add("diameter.base", 463, + new_create_dissector_handle(dissect_diameter_eap_payload, proto_diameter)); ++ ++ /* set port for future deletes */ ++ diameter_tcp_port_range = range_copy(global_diameter_tcp_port_range); ++ range_foreach(diameter_tcp_port_range, range_add_callback); ++ diameters_tcp_port_range = range_copy(global_diameter_tcp_tls_port_range); ++ range_foreach(diameters_tcp_port_range, range_add_callback_sec); ++ ++ dissector_add("sctp.port", gbl_diameterSctpPort, diameter_handle); ++ ssl_dissector_add(gbl_diameterSctpTlsPort, "diameter", TRUE); + + Initialized=TRUE; + } else { + range_foreach(diameter_tcp_port_range, range_delete_callback); + g_free(diameter_tcp_port_range); ++ range_foreach(diameters_tcp_port_range, range_delete_callback_sec); ++ g_free(diameters_tcp_port_range); + dissector_delete("sctp.port", SctpPort, diameter_handle); + } + +- /* set port for future deletes */ +- diameter_tcp_port_range = range_copy(global_diameter_tcp_port_range); +- range_foreach(diameter_tcp_port_range, range_add_callback); + +- SctpPort=gbl_diameterSctpPort; +- dissector_add("sctp.port", gbl_diameterSctpPort, diameter_handle); ++ + } + + /* registration with the filtering engine */ +@@ -1543,8 +1569,9 @@ + diameter_dissector_table = register_dissector_table("diameter.base", "DIAMETER_3GPP_AVPS", FT_UINT32, BASE_DEC); + diameter_3gpp_avp_dissector_table = register_dissector_table("diameter.3gpp", "DIAMETER_3GPP_AVPS", FT_UINT32, BASE_DEC); + +- /* Set default TCP ports */ ++ /* Set default TCP & TLS ports */ + range_convert_str(&global_diameter_tcp_port_range, DEFAULT_DIAMETER_PORT_RANGE, MAX_UDP_PORT); ++ range_convert_str(&global_diameter_tcp_tls_port_range, DEFAULT_DIAMETER_TLS_PORT_RANGE, MAX_UDP_PORT); + + /* Register configuration options for ports */ + diameter_module = prefs_register_protocol(proto_diameter, +diff -Nur wireshark-1.2.7/epan/dissectors/packet-sctp.c wireshark-1.2.7-fD/epan/dissectors/packet-sctp.c +--- wireshark-1.2.7/epan/dissectors/packet-sctp.c 2010-04-01 01:44:28.000000000 +0900 ++++ wireshark-1.2.7-fD/epan/dissectors/packet-sctp.c 2011-02-23 13:54:13.000000000 +0900 +@@ -2693,6 +2693,7 @@ + b_bit = tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET) & SCTP_DATA_CHUNK_B_BIT; + u_bit = tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET) & SCTP_DATA_CHUNK_U_BIT; + stream_id = tvb_get_ntohs(chunk_tvb, DATA_CHUNK_STREAM_ID_OFFSET); ++ pinfo->strid = stream_id; + stream_seq_num = tvb_get_ntohs(chunk_tvb, DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET); + tsn = tvb_get_ntohl(chunk_tvb, DATA_CHUNK_TSN_OFFSET); + +diff -Nur wireshark-1.2.7/epan/dissectors/packet-ssl.c wireshark-1.2.7-fD/epan/dissectors/packet-ssl.c +--- wireshark-1.2.7/epan/dissectors/packet-ssl.c 2010-04-01 01:44:34.000000000 +0900 ++++ wireshark-1.2.7-fD/epan/dissectors/packet-ssl.c 2011-02-23 14:56:36.000000000 +0900 +@@ -500,6 +500,7 @@ + guint* conv_version; + Ssl_private_key_t * private_key; + guint32 port; ++ guint16 strid; + + ti = NULL; + ssl_tree = NULL; +@@ -507,9 +508,14 @@ + first_record_in_frame = TRUE; + ssl_session = NULL; + port = 0; ++ strid = 0; + + + ssl_debug_printf("\ndissect_ssl enter frame #%u (%s)\n", pinfo->fd->num, (pinfo->fd->flags.visited)?"already visited":"first time"); ++ ++ if (pinfo->ptype == PT_SCTP) { ++ ssl_debug_printf("\ndissect_ssl SCTP stream %hd\n", pinfo->strid); ++ } + + /* Track the version using conversations to reduce the + * chance that a packet that simply *looks* like a v2 or +@@ -523,14 +529,14 @@ + * the conv_version, must set the copy in the conversation + * in addition to conv_version + */ +- conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, +- pinfo->srcport, pinfo->destport, 0); ++ conversation = find_conversation_ext(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, ++ pinfo->srcport, pinfo->destport, NO_IGNORE_SCTP_STREAMID, pinfo->strid); + + if (!conversation) + { + /* create a new conversation */ +- conversation = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, +- pinfo->srcport, pinfo->destport, 0); ++ conversation = conversation_new_ext(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, ++ pinfo->srcport, pinfo->destport, (pinfo->ptype == PT_SCTP) ? DISTINCT_SCTP_STREAMID : 0, pinfo->strid); + ssl_debug_printf(" new conversation = %p created\n", (void *)conversation); + } + conv_data = conversation_get_proto_data(conversation, proto_ssl); +@@ -549,7 +555,7 @@ + conversation_add_proto_data(conversation, proto_ssl, ssl_session); + + /* we need to know which side of the conversation is speaking */ +- if (ssl_packet_from_server(ssl_associations, pinfo->srcport, pinfo->ptype == PT_TCP)) { ++ if (ssl_packet_from_server(ssl_associations, pinfo->srcport, pinfo->ptype != PT_UDP)) { + dummy.addr = pinfo->src; + dummy.port = port = pinfo->srcport; + } else { +@@ -762,7 +768,7 @@ + * add decrypted data to this packet info */ + ssl_debug_printf("decrypt_ssl3_record: app_data len %d ssl, state 0x%02X\n", + record_length, ssl->state); +- direction = ssl_packet_from_server(ssl_associations, pinfo->srcport, pinfo->ptype == PT_TCP); ++ direction = ssl_packet_from_server(ssl_associations, pinfo->srcport, pinfo->ptype != PT_UDP); + + /* retrieve decoder for this packet direction */ + if (direction != 0) { +@@ -1504,7 +1510,7 @@ + col_append_str(pinfo->cinfo, COL_INFO, "Change Cipher Spec"); + dissect_ssl3_change_cipher_spec(tvb, ssl_record_tree, + offset, conv_version, content_type); +- if (ssl) ssl_change_cipher(ssl, ssl_packet_from_server(ssl_associations, pinfo->srcport, pinfo->ptype == PT_TCP)); ++ if (ssl) ssl_change_cipher(ssl, ssl_packet_from_server(ssl_associations, pinfo->srcport, pinfo->ptype != PT_UDP)); + break; + case SSL_ID_ALERT: + { +@@ -1566,8 +1572,8 @@ + /* we need dissector information when the selected packet is shown. + * ssl session pointer is NULL at that time, so we can't access + * info cached there*/ +- association = ssl_association_find(ssl_associations, pinfo->srcport, pinfo->ptype == PT_TCP); +- association = association ? association: ssl_association_find(ssl_associations, pinfo->destport, pinfo->ptype == PT_TCP); ++ association = ssl_association_find(ssl_associations, pinfo->srcport, pinfo->ptype != PT_UDP); ++ association = association ? association: ssl_association_find(ssl_associations, pinfo->destport, pinfo->ptype != PT_UDP); + + proto_item_set_text(ssl_record_tree, + "%s Record Layer: %s Protocol: %s", +diff -Nur wireshark-1.2.7/epan/dissectors/packet-ssl-utils.c wireshark-1.2.7-fD/epan/dissectors/packet-ssl-utils.c +--- wireshark-1.2.7/epan/dissectors/packet-ssl-utils.c 2010-04-01 01:44:27.000000000 +0900 ++++ wireshark-1.2.7-fD/epan/dissectors/packet-ssl-utils.c 2011-02-23 13:33:10.000000000 +0900 +@@ -2713,9 +2713,10 @@ + fprintf(stderr, "association_add() could not find handle for protocol:%s\n",protocol); + } else { + if(port) { +- if(tcp) ++ if(tcp) { + dissector_add("tcp.port", port, handle); +- else ++ dissector_add("sctp.port", port, handle); ++ } else + dissector_add("udp.port", port, handle); + } + g_tree_insert(associations, assoc, assoc); +diff -Nur wireshark-1.2.7/epan/packet_info.h wireshark-1.2.7-fD/epan/packet_info.h +--- wireshark-1.2.7/epan/packet_info.h 2010-04-01 01:44:40.000000000 +0900 ++++ wireshark-1.2.7-fD/epan/packet_info.h 2011-02-23 13:54:52.000000000 +0900 +@@ -169,6 +169,7 @@ + tvbuff_t *gssapi_decrypted_tvb; + gboolean gssapi_data_encrypted; + ++ guint16 strid; /* Stream Id of the last DATA chunk in the packet */ + guint32 ppid; /* SCTP PPI of current DATA chunk */ + guint32 ppids[MAX_NUMBER_OF_PPIDS]; /* The first NUMBER_OF_PPIDS PPIDS which are present + * in the SCTP packet