Index: smsc/smsc_smpp.c
===================================================================
RCS file: /home/cvs/gateway/gw/smsc/smsc_smpp.c,v
retrieving revision 1.114
diff -u -r1.114 smsc_smpp.c
--- smsc/smsc_smpp.c	2 Apr 2009 20:30:19 -0000	1.114
+++ smsc/smsc_smpp.c	30 Apr 2009 09:16:18 -0000
@@ -499,6 +499,13 @@
         octstr_delete(msg->sms.msgdata, 0, udhl);
     }
 
+    //support SAR parameters
+	if (pdu->u.deliver_sm.sar_total_segments > 1) {
+		msg->sms.sar_msg_ref_num = pdu->u.deliver_sm.sar_msg_ref_num;
+		msg->sms.sar_total_segments = pdu->u.deliver_sm.sar_total_segments;
+		msg->sms.sar_segment_seqnum = pdu->u.deliver_sm.sar_segment_seqnum;
+	}
+
     dcs_to_fields(&msg, pdu->u.deliver_sm.data_coding);
 
     /* handle default data coding */
Index: msg-decl.h
===================================================================
RCS file: /home/cvs/gateway/gw/msg-decl.h,v
retrieving revision 1.37
diff -u -r1.37 msg-decl.h
--- msg-decl.h	14 Jan 2009 11:11:46 -0000	1.37
+++ msg-decl.h	30 Apr 2009 09:16:17 -0000
@@ -1,58 +1,58 @@
-/* ==================================================================== 
- * The Kannel Software License, Version 1.0 
- * 
- * Copyright (c) 2001-2009 Kannel Group  
- * Copyright (c) 1998-2001 WapIT Ltd.   
- * All rights reserved. 
- * 
- * Redistribution and use in source and binary forms, with or without 
- * modification, are permitted provided that the following conditions 
- * are met: 
- * 
- * 1. Redistributions of source code must retain the above copyright 
- *    notice, this list of conditions and the following disclaimer. 
- * 
- * 2. Redistributions in binary form must reproduce the above copyright 
- *    notice, this list of conditions and the following disclaimer in 
- *    the documentation and/or other materials provided with the 
- *    distribution. 
- * 
- * 3. The end-user documentation included with the redistribution, 
- *    if any, must include the following acknowledgment: 
- *       "This product includes software developed by the 
- *        Kannel Group (http://www.kannel.org/)." 
- *    Alternately, this acknowledgment may appear in the software itself, 
- *    if and wherever such third-party acknowledgments normally appear. 
- * 
- * 4. The names "Kannel" and "Kannel Group" must not be used to 
- *    endorse or promote products derived from this software without 
- *    prior written permission. For written permission, please  
- *    contact org@kannel.org. 
- * 
- * 5. Products derived from this software may not be called "Kannel", 
- *    nor may "Kannel" appear in their name, without prior written 
- *    permission of the Kannel Group. 
- * 
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
- * DISCLAIMED.  IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS 
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,  
- * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR  
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE  
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,  
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
- * ==================================================================== 
- * 
- * This software consists of voluntary contributions made by many 
- * individuals on behalf of the Kannel Group.  For more information on  
- * the Kannel Group, please see <http://www.kannel.org/>. 
- * 
- * Portions of this software are based upon software originally written at  
- * WapIT Ltd., Helsinki, Finland for the Kannel project.  
- */ 
+/* ====================================================================
+ * The Kannel Software License, Version 1.0
+ *
+ * Copyright (c) 2001-2009 Kannel Group
+ * Copyright (c) 1998-2001 WapIT Ltd.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ *    if any, must include the following acknowledgment:
+ *       "This product includes software developed by the
+ *        Kannel Group (http://www.kannel.org/)."
+ *    Alternately, this acknowledgment may appear in the software itself,
+ *    if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Kannel" and "Kannel Group" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please
+ *    contact org@kannel.org.
+ *
+ * 5. Products derived from this software may not be called "Kannel",
+ *    nor may "Kannel" appear in their name, without prior written
+ *    permission of the Kannel Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Kannel Group.  For more information on
+ * the Kannel Group, please see <http://www.kannel.org/>.
+ *
+ * Portions of this software are based upon software originally written at
+ * WapIT Ltd., Helsinki, Finland for the Kannel project.
+ */
 
 /*
  * msg-decl.h - message declarations
@@ -76,7 +76,7 @@
         INTEGER(command);
         OCTSTR(boxc_id);
     })
-    
+
 MSG(sms,
 	{
 		OCTSTR(sender);
@@ -111,6 +111,9 @@
         INTEGER(resend_try);
         INTEGER(resend_time);
         OCTSTR(meta_data);
+		INTEGER(sar_msg_ref_num);
+		INTEGER(sar_total_segments);
+		INTEGER(sar_segment_seqnum);
 	})
 
 MSG(ack,
@@ -119,7 +122,7 @@
 		INTEGER(time);
 		UUID(id);
 	})
-    
+
 MSG(wdp_datagram,
 	{
 		OCTSTR(source_address);
Index: bb_smscconn.c
===================================================================
RCS file: /home/cvs/gateway/gw/bb_smscconn.c,v
retrieving revision 1.100
diff -u -r1.100 bb_smscconn.c
--- bb_smscconn.c	14 Jan 2009 11:11:46 -0000	1.100
+++ bb_smscconn.c	30 Apr 2009 09:16:16 -0000
@@ -1,58 +1,58 @@
-/* ==================================================================== 
- * The Kannel Software License, Version 1.0 
- * 
- * Copyright (c) 2001-2009 Kannel Group  
- * Copyright (c) 1998-2001 WapIT Ltd.   
- * All rights reserved. 
- * 
- * Redistribution and use in source and binary forms, with or without 
- * modification, are permitted provided that the following conditions 
- * are met: 
- * 
- * 1. Redistributions of source code must retain the above copyright 
- *    notice, this list of conditions and the following disclaimer. 
- * 
- * 2. Redistributions in binary form must reproduce the above copyright 
- *    notice, this list of conditions and the following disclaimer in 
- *    the documentation and/or other materials provided with the 
- *    distribution. 
- * 
- * 3. The end-user documentation included with the redistribution, 
- *    if any, must include the following acknowledgment: 
- *       "This product includes software developed by the 
- *        Kannel Group (http://www.kannel.org/)." 
- *    Alternately, this acknowledgment may appear in the software itself, 
- *    if and wherever such third-party acknowledgments normally appear. 
- * 
- * 4. The names "Kannel" and "Kannel Group" must not be used to 
- *    endorse or promote products derived from this software without 
- *    prior written permission. For written permission, please  
- *    contact org@kannel.org. 
- * 
- * 5. Products derived from this software may not be called "Kannel", 
- *    nor may "Kannel" appear in their name, without prior written 
- *    permission of the Kannel Group. 
- * 
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
- * DISCLAIMED.  IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS 
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,  
- * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR  
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE  
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,  
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
- * ==================================================================== 
- * 
- * This software consists of voluntary contributions made by many 
- * individuals on behalf of the Kannel Group.  For more information on  
- * the Kannel Group, please see <http://www.kannel.org/>. 
- * 
- * Portions of this software are based upon software originally written at  
- * WapIT Ltd., Helsinki, Finland for the Kannel project.  
- */ 
+/* ====================================================================
+ * The Kannel Software License, Version 1.0
+ *
+ * Copyright (c) 2001-2009 Kannel Group
+ * Copyright (c) 1998-2001 WapIT Ltd.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ *    if any, must include the following acknowledgment:
+ *       "This product includes software developed by the
+ *        Kannel Group (http://www.kannel.org/)."
+ *    Alternately, this acknowledgment may appear in the software itself,
+ *    if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Kannel" and "Kannel Group" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please
+ *    contact org@kannel.org.
+ *
+ * 5. Products derived from this software may not be called "Kannel",
+ *    nor may "Kannel" appear in their name, without prior written
+ *    permission of the Kannel Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Kannel Group.  For more information on
+ * the Kannel Group, please see <http://www.kannel.org/>.
+ *
+ * Portions of this software are based upon software originally written at
+ * WapIT Ltd., Helsinki, Finland for the Kannel project.
+ */
 
 /*
  * SMSC Connection interface for Bearerbox.
@@ -65,7 +65,7 @@
  * Kalle Marjola 2000 for project Kannel
  * Alexander Malysh <amalysh at kannel.org> 2003, 2004, 2005
  */
- 
+
 #include "gw-config.h"
 
 #include <errno.h>
@@ -193,7 +193,7 @@
 static void handle_split(SMSCConn *conn, Msg *msg, long reason)
 {
     struct split_parts *split = msg->sms.split_parts;
-    
+
     /*
      * If temporarely failed, try again immediately but only if connection active.
      * Because if connection is not active we will loop for ever here consuming 100% CPU
@@ -205,7 +205,7 @@
         msg_destroy(msg);
         return;
     }
-    
+
     /*
      * if the reason is not a success and status is still success
      * then set status of a split to the reason.
@@ -233,7 +233,7 @@
      * we will split it again in smscconn_send(...).
      */
     msg_destroy(msg);
-        
+
     if (counter_decrease(split->parts_left) <= 1) {
         /* all splited parts were processed */
         counter_destroy(split->parts_left);
@@ -257,7 +257,7 @@
         octstr_destroy(reply);
         return;
     }
-    
+
     counter_increase(outgoing_sms_counter);
     load_increase(outgoing_sms_load);
     if (conn) counter_increase(conn->sent);
@@ -294,7 +294,7 @@
         octstr_destroy(reply);
         return;
     }
-    
+
     switch (reason) {
     case SMSCCONN_FAILED_TEMPORARILY:
         /*
@@ -309,7 +309,7 @@
              */
            if (sms_resend_retry >= 0 && sms->sms.resend_try >= sms_resend_retry) {
                warning(0, "Maximum retries for message exceeded, discarding it!");
-               bb_smscconn_send_failed(NULL, sms, SMSCCONN_FAILED_DISCARDED, 
+               bb_smscconn_send_failed(NULL, sms, SMSCCONN_FAILED_DISCARDED,
                                        octstr_create("Retries Exceeded"));
                break;
            }
@@ -318,7 +318,7 @@
        }
        gwlist_produce(outgoing_sms, sms);
        break;
-       
+
     case SMSCCONN_FAILED_SHUTDOWN:
         gwlist_produce(outgoing_sms, sms);
         break;
@@ -388,7 +388,7 @@
         msg_destroy(sms);
         return SMSCCONN_FAILED_REJECTED;
     }
-    
+
     if (black_list &&
 	numhash_find_number(black_list, sms->sms.sender) == 1) {
 	info(0, "Number <%s> is in black-list, message discarded",
@@ -439,7 +439,7 @@
                 msg_destroy(sms);
                 return SMSCCONN_SUCCESS;
             case concat_complete:
-                /* Combined sms received! save new one since it is now combined. */ 
+                /* Combined sms received! save new one since it is now combined. */
                 msg_destroy(sms);
                 /* Change the sms. */
                 sms = msg_duplicate(copy);
@@ -463,7 +463,7 @@
          */
         rc = route_incoming_to_boxc(copy);
     }
-    
+
     if (rc == -1 || (rc != SMSCCONN_SUCCESS && rc != SMSCCONN_QUEUED)) {
         warning(0, "incoming messages queue too long, dropping a message");
         if (sms->sms.sms_type == report_mo)
@@ -597,7 +597,7 @@
 
     /* create split sms counter */
     split_msg_counter = counter_create();
-    
+
     /* create smsc list and rwlock for it */
     smsc_list = gwlist_create();
     gw_rwlock_init_static(&smsc_list_lock);
@@ -610,7 +610,7 @@
     white_list_url = cfg_get(grp, octstr_imm("white-list"));
     if (white_list_url != NULL) {
         if ((white_list = numhash_create(octstr_get_cstr(white_list_url))) == NULL)
-            panic(0, "Could not get white-list at URL <%s>", 
+            panic(0, "Could not get white-list at URL <%s>",
                   octstr_get_cstr(white_list_url));
     }
     if ((os = cfg_get(grp, octstr_imm("white-list-regex"))) != NULL) {
@@ -618,11 +618,11 @@
             panic(0, "Could not compile pattern '%s'", octstr_get_cstr(os));
         octstr_destroy(os);
     }
-    
+
     black_list_url = cfg_get(grp, octstr_imm("black-list"));
     if (black_list_url != NULL) {
         if ((black_list = numhash_create(octstr_get_cstr(black_list_url))) == NULL)
-            panic(0, "Could not get black-list at URL <%s>", 
+            panic(0, "Could not get black-list at URL <%s>",
                   octstr_get_cstr(black_list_url));
     }
     if ((os = cfg_get(grp, octstr_imm("black-list-regex"))) != NULL) {
@@ -636,7 +636,7 @@
         sms_resend_frequency = 60;
     }
     info(0, "Set SMS resend frequency to %ld seconds.", sms_resend_frequency);
-            
+
     if (cfg_get_integer(&sms_resend_retry, grp, octstr_imm("sms-resend-retry")) == -1) {
         sms_resend_retry = -1;
         info(0, "SMS resend retry set to unlimited.");
@@ -659,18 +659,18 @@
 
     smsc_groups = cfg_get_multi_group(cfg, octstr_imm("smsc"));
     gwlist_add_producer(smsc_list);
-    for (i = 0; i < gwlist_len(smsc_groups) && 
+    for (i = 0; i < gwlist_len(smsc_groups) &&
         (grp = gwlist_get(smsc_groups, i)) != NULL; i++) {
-        conn = smscconn_create(grp, 1); 
+        conn = smscconn_create(grp, 1);
         if (conn == NULL)
             panic(0, "Cannot start with SMSC connection failing");
         gwlist_append(smsc_list, conn);
     }
     gwlist_remove_producer(smsc_list);
-    
+
     if ((router_thread = gwthread_create(sms_router, NULL)) == -1)
 	panic(0, "Failed to start a new thread for SMS routing");
-    
+
     gwlist_add_producer(incoming_sms);
     smsc_running = 1;
     return 0;
@@ -749,7 +749,7 @@
         /* find the group with equal smsc id */
         hit = 0;
         grp = NULL;
-        for (group_index = 0; group_index < gwlist_len(smsc_groups) && 
+        for (group_index = 0; group_index < gwlist_len(smsc_groups) &&
              (grp = gwlist_get(smsc_groups, group_index)) != NULL; group_index++) {
             smscid = cfg_get(grp, octstr_imm("smsc-id"));
             if (smscid != NULL && octstr_compare(smscid, id) == 0) {
@@ -767,7 +767,7 @@
             error(0, "HTTP: Could not find config for smsc-id `%s'", octstr_get_cstr(id));
             break;
         }
-        
+
         info(0,"HTTP: Re-starting smsc-id `%s'", octstr_get_cstr(id));
 
         new_conn = smscconn_create(grp, 1);
@@ -775,7 +775,7 @@
             error(0, "Start of SMSC connection failed, smsc-id `%s'", octstr_get_cstr(id));
             continue; /* keep old connection on the list */
         }
-        
+
         /* drop old connection from the active smsc list */
         gwlist_delete(smsc_list, i, 1);
         /* destroy the connection */
@@ -785,11 +785,11 @@
         num++;
     }
     gw_rwlock_unlock(&smsc_list_lock);
-    
+
     /* wake-up the router */
     if (router_thread >= 0)
         gwthread_wakeup(router_thread);
-    
+
     return 0;
 }
 
@@ -807,7 +807,7 @@
         smscconn_start(conn);
     }
     gw_rwlock_unlock(&smsc_list_lock);
-    
+
     if (router_thread >= 0)
         gwthread_wakeup(router_thread);
 }
@@ -874,7 +874,7 @@
         return;
 
     debug("smscconn", 0, "final clean-up for SMSCConn");
-    
+
     gw_rwlock_wrlock(&smsc_list_lock);
     for (i = 0; i < gwlist_len(smsc_list); i++) {
         conn = gwlist_get(smsc_list, i);
@@ -884,7 +884,7 @@
     smsc_list = NULL;
     gw_rwlock_unlock(&smsc_list_lock);
     gwlist_destroy(smsc_groups, NULL);
-    octstr_destroy(unified_prefix);    
+    octstr_destroy(unified_prefix);
     numhash_destroy(white_list);
     numhash_destroy(black_list);
     octstr_destroy(white_list_url);
@@ -940,8 +940,8 @@
         conn = gwlist_get(smsc_list, i);
 
         if ((smscconn_info(conn, &info) == -1)) {
-            /* 
-             * we do not delete SMSCs from the list 
+            /*
+             * we do not delete SMSCs from the list
              * this way we can show in the status which links are dead
              */
             continue;
@@ -959,7 +959,7 @@
             octstr_append_cstr(tmp, "    ");
             octstr_append(tmp, conn_id);
             octstr_append_cstr(tmp, "    ");
-        } 
+        }
         if (status_type == BBSTATUS_XML) {
             octstr_append_cstr(tmp, "<smsc>\n\t\t<name>");
             octstr_append(tmp, conn_name);
@@ -990,7 +990,7 @@
             default:
                 sprintf(tmp3, "unknown");
         }
-	
+
         if (status_type == BBSTATUS_XML)
             octstr_format_append(tmp, "<status>%s</status>\n\t\t<received>%ld</received>"
                 "\n\t\t<sent>%ld</sent>\n\t\t<failed>%ld</failed>\n\t\t"
@@ -1165,11 +1165,11 @@
 static long route_incoming_to_smsc(SMSCConn *conn, Msg *msg)
 {
     Octstr *smsc;
-    
+
     /* sanity check */
     if (!conn || !msg)
         return -1;
-        
+
     /* check for dlr rerouting */
     if (!conn->reroute_dlr && (msg->sms.sms_type == report_mo || msg->sms.sms_type == report_mt))
         return -1;
@@ -1186,7 +1186,7 @@
         /* drop into outbound queue again for routing */
         return smsc2_rout(msg, 0);
     }
-    
+
     if (conn->reroute_to_smsc) {
         /* change message direction */
         store_save_ack(msg, ack_success);
@@ -1197,7 +1197,7 @@
         msg->sms.smsc_id = octstr_duplicate(conn->reroute_to_smsc);
         return smsc2_rout(msg, 0);
     }
-    
+
     if (conn->reroute_by_receiver && msg->sms.receiver &&
                  (smsc = dict_get(conn->reroute_by_receiver, msg->sms.receiver))) {
         /* change message direction */
@@ -1211,7 +1211,7 @@
         return smsc2_rout(msg, 0);
     }
 
-    return -1; 
+    return -1;
 }
 
 
@@ -1254,7 +1254,7 @@
 {
     if (incoming_concat_msgs != NULL) /* already initialised? */
         return;
-    incoming_concat_msgs = dict_create(max_incoming_sms_qlength > 0 ? max_incoming_sms_qlength : 1024, 
+    incoming_concat_msgs = dict_create(max_incoming_sms_qlength > 0 ? max_incoming_sms_qlength : 1024,
                                        destroy_concatMsg);
     concat_lock = mutex_create();
     debug("bb.sms",0,"smsbox MO concatenated message handling enabled");
@@ -1357,6 +1357,114 @@
     gwlist_destroy(keys, octstr_destroy_item);
 }
 
+/**
+ * Concatenate using sar parameters
+ */
+static int check_concatenation_sar(Msg **pmsg, Octstr *smscid)
+{
+    Msg *msg = *pmsg;
+    Octstr *key;
+	int refnum = msg->sms.sar_msg_ref_num;
+	int totalparts = msg->sms.sar_total_segments;
+	int part = msg->sms.sar_segment_seqnum;
+	ConcatMsg *cmsg;
+    int ret = concat_complete;
+    int i;
+
+    if(totalparts == 0) {
+    	return concat_none;
+    }
+
+    if (part < 1 || part > totalparts) {
+        warning(0, "Invalid concatenation SAR [ref = %d] in message from %s!",
+                refnum, octstr_get_cstr(msg->sms.sender));
+        return concat_none;
+    }
+
+    debug("bb.sms.splits", 0, "Got part %d [ref %d, total parts %d] of message from %s. Dump follows:",
+          part, refnum,totalparts, octstr_get_cstr(msg->sms.sender));
+
+    msg_dump(msg,0);
+
+    key = octstr_format("%S %S %S %d", msg->sms.sender, msg->sms.receiver, smscid, refnum);
+    mutex_lock(concat_lock);
+    if ((cmsg = dict_get(incoming_concat_msgs, key)) == NULL) {
+        cmsg = gw_malloc(sizeof(*cmsg));
+        cmsg->refnum = refnum;
+        cmsg->total_parts = totalparts;
+        cmsg->num_parts = 0;
+        cmsg->key = octstr_duplicate(key);
+        cmsg->ack = ack_success;
+        cmsg->parts = gw_malloc(totalparts * sizeof(*cmsg->parts));
+        memset(cmsg->parts, 0, cmsg->total_parts * sizeof(*cmsg->parts)); /* clear it. */
+
+        dict_put(incoming_concat_msgs, key, cmsg);
+    }
+    octstr_destroy(key);
+
+    if (totalparts != cmsg->total_parts) {
+        /* totalparts in udh and cmsg not equal assume bad message */
+        error(0, "Totalparts in SAR doesn't match received before, "
+                "total parts <%d>:<%d> part %d, ref %d, from %s, to %s. Discarded!",
+                cmsg->total_parts, totalparts, part, refnum, octstr_get_cstr(msg->sms.sender), octstr_get_cstr(msg->sms.receiver));
+        mutex_unlock(concat_lock);
+        store_save_ack(msg, ack_success);
+        msg_destroy(msg);
+        *pmsg = msg = NULL;
+        return concat_error;
+    }
+
+    /* check if we have seen message part before... */
+    if (cmsg->parts[part - 1] != NULL) {
+        warning(0, "Duplicate message part %d, ref %d, from %s, to %s. Discarded!",
+                part, refnum, octstr_get_cstr(msg->sms.sender), octstr_get_cstr(msg->sms.receiver));
+        store_save_ack(msg, ack_success);
+        msg_destroy(msg);
+        *pmsg = msg = NULL;
+    } else {
+        cmsg->parts[part -1] = msg;
+        cmsg->num_parts++;
+        /* always update receive time so we have it from last part and don't timeout */
+        cmsg->trecv = time(NULL);
+    }
+
+    if (cmsg->num_parts < cmsg->total_parts) {  /* wait for more parts. */
+        *pmsg = msg = NULL;
+        mutex_unlock(concat_lock);
+        return concat_pending;
+    }
+
+    /* we have all the parts: Put them together, return message. */
+    msg = msg_duplicate(cmsg->parts[0]);
+    uuid_generate(msg->sms.id); /* give it a new ID. */
+
+    debug("bb.sms.splits",0,"Received all concatenated message parts from %s, to %s, refnum %d",
+          octstr_get_cstr(msg->sms.sender), octstr_get_cstr(msg->sms.receiver), refnum);
+
+    for (i = 1; i < cmsg->total_parts; i++)
+        octstr_append(msg->sms.msgdata, cmsg->parts[i]->sms.msgdata);
+
+    /* Attempt to save the new one, if that fails, then reply with fail. */
+    if (store_save(msg) == -1) {
+        mutex_unlock(concat_lock);
+        msg_destroy(msg);
+        *pmsg = msg = NULL;
+        return concat_error;
+    } else
+        *pmsg = msg; /* return the message part. */
+
+    /* Delete it from the queue and from the Dict. */
+    /* Note: dict_put with NULL value delete and destroy value */
+    dict_put(incoming_concat_msgs, cmsg->key, NULL);
+    mutex_unlock(concat_lock);
+
+    debug("bb.sms.splits", 0, "Got full message [ref %d] of message from %s to %s. Dumping: ",
+          refnum, octstr_get_cstr(msg->sms.sender), octstr_get_cstr(msg->sms.receiver));
+    msg_dump(msg,0);
+
+    return ret;
+}
+
 /* Checks if message is concatenated. Returns:
  * - returns concat_complete if no concat parts, or message complete
  * - returns concat_pending (and sets *pmsg to NULL) if parts pending
@@ -1369,12 +1477,18 @@
     Octstr *udh = msg->sms.udhdata, *key;
     ConcatMsg *cmsg;
     int ret = concat_complete;
+    int ret_sar = concat_complete;
 
     /* ... module not initialised or there is no UDH or smscid is NULL. */
-    if (incoming_concat_msgs == NULL || (l = octstr_len(udh)) == 0 || smscid == NULL)
+    if (incoming_concat_msgs == NULL || ((l = octstr_len(udh)) == 0 && msg->sms.sar_total_segments == 0) || smscid == NULL)
         return concat_none;
 
-    for (pos = 1, c = -1; pos < l - 1; pos += iel + 2) {
+    ret_sar = check_concatenation_sar(pmsg, smscid);
+	if (ret_sar != concat_none && ret_sar != concat_complete) {
+		return ret_sar;
+	}
+
+	for (pos = 1, c = -1; pos < l - 1; pos += iel + 2) {
         iel = octstr_get_char(udh, pos + 1);
         if ((c = octstr_get_char(udh,pos)) == 0 || c == 8)
             break;
@@ -1397,9 +1511,9 @@
 
     debug("bb.sms.splits", 0, "Got part %d [ref %d, total parts %d] of message from %s. Dump follows:",
           part, refnum,totalparts, octstr_get_cstr(msg->sms.sender));
-     
+
     msg_dump(msg,0);
-     
+
     key = octstr_format("%S %S %S %d", msg->sms.sender, msg->sms.receiver, smscid, refnum);
     mutex_lock(concat_lock);
     if ((cmsg = dict_get(incoming_concat_msgs, key)) == NULL) {
@@ -1429,11 +1543,11 @@
     }
 
     /* check if we have seen message part before... */
-    if (cmsg->parts[part - 1] != NULL) {	  
+    if (cmsg->parts[part - 1] != NULL) {
         warning(0, "Duplicate message part %d, ref %d, from %s, to %s. Discarded!",
                 part, refnum, octstr_get_cstr(msg->sms.sender), octstr_get_cstr(msg->sms.receiver));
         store_save_ack(msg, ack_success);
-        msg_destroy(msg); 
+        msg_destroy(msg);
         *pmsg = msg = NULL;
     } else {
         cmsg->parts[part -1] = msg;
@@ -1459,12 +1573,12 @@
         octstr_append(msg->sms.msgdata, cmsg->parts[i]->sms.msgdata);
 
     /* Attempt to save the new one, if that fails, then reply with fail. */
-    if (store_save(msg) == -1) {	  
+    if (store_save(msg) == -1) {
         mutex_unlock(concat_lock);
         msg_destroy(msg);
         *pmsg = msg = NULL;
         return concat_error;
-    } else 
+    } else
         *pmsg = msg; /* return the message part. */
 
     /* Delete it from the queue and from the Dict. */
@@ -1498,7 +1612,7 @@
 {
     numhash_destroy(white_list);
     numhash_destroy(black_list);
-    
+
     if (white_list_url != NULL) {
         white_list = numhash_create(octstr_get_cstr(white_list_url));
     }
