--- packet-smpp.c@rev=HEAD	2003-07-09 11:28:49.000000000 +0200
+++ packet-smpp.c	2003-07-09 11:25:34.000000000 +0200
@@ -62,6 +62,7 @@
 #include <glib.h>
 
 #include <epan/packet.h>
+#include <epan/conversation.h>
 
 #include "prefs.h"
 #include "reassemble.h"
@@ -701,17 +702,19 @@
  * \param	offset	Location of field in buffer, returns location of
  * 			next field
  */
-static void
+static const char *
 smpp_handle_string(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
 {
     guint	 len;
+	gchar	*str = NULL;
 
     len = tvb_strsize(tvb, *offset);
     if (len > 1) {
-      proto_tree_add_string(tree, field, tvb, *offset, len,
-          tvb_get_ptr(tvb, *offset, len));
+	  str = (gchar *)tvb_get_ptr(tvb, *offset, len);
+      proto_tree_add_string(tree, field, tvb, *offset, len, str);
     }
     (*offset) += len;
+	return str;
 }
 
 static void
@@ -1188,7 +1191,7 @@
 							hf_smpp_udh_multiple_messages_msg_part,
 							tvb, i-1, 1, frag);
 				} else {
-					proto_item_append_text(subtree, "Invalid format!");
+					proto_item_append_text(subtree, " - Invalid format!");
 					i += len;
 				}
 				break;
@@ -1210,8 +1213,12 @@
 					proto_tree_add_uint (subtree, hf_smpp_udh_ports_dst,
 							tvb, i-2, 2, p_dst);
 					ports_available = TRUE;
+					/* Update ports in pinfo (will be reset after we leave
+					 * this function; is required for correct reassembly */
+					pinfo->srcport = p_src;
+					pinfo->destport = p_dst;
 				} else {
-					proto_item_append_text(subtree, "Invalid format!");
+					proto_item_append_text(subtree, " - Invalid format!");
 					i += len;
 				}
 				break;
@@ -1247,7 +1254,8 @@
 			show_fragment_seq_tree (fd_sm, &sm_frag_items, tree, pinfo, sm_tvb);
 		} else {
 			if (check_col (pinfo->cinfo, COL_INFO))
-				col_append_str (pinfo->cinfo, COL_INFO, " (Short Message unreassembled)");
+				col_append_str (pinfo->cinfo, COL_INFO,
+						" (Short Message unreassembled)");
 		}
 	}
 	if (ports_available) { /* Port Number UDH is present */
@@ -1289,14 +1297,35 @@
     int		 offset = 0;
     guint8	 flag, udhi;
     guint8	 length;
+	conversation_t *conv;
+	address addr_a, addr_b;
+	const gchar *src, *dst;
+	address save_src, save_dst;
+	guint32 save_srcport, save_destport;
 
     smpp_handle_string(tree, tvb, hf_smpp_service_type, &offset);
     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_ton, &offset);
     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_npi, &offset);
-    smpp_handle_string(tree, tvb, hf_smpp_source_addr, &offset);
+	src = smpp_handle_string(tree, tvb, hf_smpp_source_addr, &offset);
+	if (src) {
+	    addr_a.data = (const guint8 *) src;
+		addr_a.len = strlen ((gchar *)(addr_a.data));
+	} else {
+	    addr_a.data = NULL;
+		addr_a.len = 0;
+	}
+	addr_a.type = AT_NONE;
     smpp_handle_int1(tree, tvb, hf_smpp_dest_addr_ton, &offset);
     smpp_handle_int1(tree, tvb, hf_smpp_dest_addr_npi, &offset);
-    smpp_handle_string(tree, tvb, hf_smpp_destination_addr, &offset);
+	dst = smpp_handle_string(tree, tvb, hf_smpp_destination_addr, &offset);
+	if (dst) {
+	    addr_b.data = dst;
+		addr_b.len = strlen ((gchar *)(addr_b.data));
+	} else {
+		addr_b.data = NULL;
+		addr_b.len = 0;
+	}
+	addr_b.type = AT_NONE;
     flag = tvb_get_guint8(tvb, offset);
     udhi = flag & 0x40;
     proto_tree_add_item(tree, hf_smpp_esm_submit_msg_mode,
@@ -1324,14 +1353,75 @@
     proto_tree_add_uint(tree, hf_smpp_sm_length, tvb, offset++, 1, length);
     if (length)
     {
-	proto_tree_add_item(tree, hf_smpp_short_message,
-			    tvb, offset, length, FALSE);
-	if (udhi) /* UDHI indicator present */
-	{
-	    tvb_msg = tvb_new_subset (tvb, offset,
-				      MIN(length, tvb_reported_length(tvb) - offset), length);
-	    parse_sm_message(tree, tvb_msg, pinfo);
-	}
+		proto_tree_add_item(tree, hf_smpp_short_message,
+				tvb, offset, length, FALSE);
+		if (udhi) /* UDHI indicator present */
+		{
+			guint conv_flags;
+			if (src) {
+				if (dst) {
+					conv_flags = NO_PORT_B;
+				} else {
+					conv_flags = NO_PORT_B | NO_ADDR_B;
+				}
+				conv = find_conversation (&addr_a, &addr_b,
+						PT_NONE, 0, 0, conv_flags);
+				if (conv == NULL) {
+					conv = conversation_new (&addr_a, &addr_b,
+							PT_NONE, 0, 0, conv_flags);
+				}
+			} else {
+				if (dst) {
+					/* Invert src and dst, NO_PORT_B | NO_ADDR_B */
+					conv_flags = NO_PORT_B | NO_ADDR_B;
+					conv = find_conversation (&addr_b, &addr_a,
+							PT_NONE, 0, 0, conv_flags);
+					if (conv == NULL) {
+						conv = conversation_new (&addr_b, &addr_a,
+								PT_NONE, 0, 0, conv_flags);
+					}
+				} else {
+					/* No src and no dst ==> no conversation */
+					conv = NULL;
+				}
+			}
+			/* Only try to reassemble if a conversation exists */
+			if (conv) {
+#ifdef DEBUG
+				proto_tree_add_text(tree, tvb, 0, -1,
+						"Conversation = %u", conv->index);
+#endif
+				conversation_set_dissector (conv, find_dissector ("smpp"));
+				/* Overwrite addresses and ports so reassembly code works
+				 * in the situation where segmented messages are
+				 * transmitted over ultiple SMPP connections. */
+				SET_ADDRESS(&save_src, pinfo->src.type, pinfo->src.len,
+						pinfo->src.data);
+				SET_ADDRESS(&save_dst, pinfo->dst.type, pinfo->dst.len,
+						pinfo->dst.data);
+				SET_ADDRESS(&(pinfo->src), addr_a.type, addr_a.len,
+						addr_a.data);
+				SET_ADDRESS(&(pinfo->dst), addr_b.type, addr_b.len,
+						addr_b.data);
+				save_srcport = pinfo->srcport;
+				save_destport = pinfo->destport;
+				pinfo->srcport = 0;
+				pinfo->destport = 0;
+
+				/* Pass the SM with UDH to the parsing function */
+		    	tvb_msg = tvb_new_subset (tvb, offset,
+						MIN(length, tvb_reported_length(tvb) - offset), length);
+		    	parse_sm_message(tree, tvb_msg, pinfo);
+				
+				/* Restore addresses and ports */
+				SET_ADDRESS(&(pinfo->src), save_src.type, save_src.len,
+						save_src.data);
+				SET_ADDRESS(&(pinfo->dst), save_dst.type, save_dst.len,
+						save_dst.data);
+				pinfo->srcport = save_srcport;
+				pinfo->destport = save_destport;
+			}
+		}
     	offset += length;
     }
     smpp_handle_tlv(tree, tvb, &offset);
