Index: gw/dlr_mysql.c
===================================================================
--- gw/dlr_mysql.c	(revision 4833)
+++ gw/dlr_mysql.c	(working copy)
@@ -138,7 +138,7 @@
 
 static struct dlr_entry* dlr_mysql_get(const Octstr *smsc, const Octstr *ts, const Octstr *dst)
 {
-    Octstr *sql;
+    Octstr *sql, *like = NULL;
     DBPoolConn *pconn;
     List *result = NULL, *row;
     struct dlr_entry *res = NULL;
@@ -148,26 +148,45 @@
     if (pconn == NULL) /* should not happens, but sure is sure */
         return NULL;
 
-    sql = octstr_format("SELECT `%S`, `%S`, `%S`, `%S`, `%S`, `%S` FROM `%S` WHERE `%S`=? AND `%S`=? LIMIT 1",
+    if (dst)
+       sql = octstr_format("SELECT `%S`, `%S`, `%S`, `%S`, `%S`, `%S` FROM `%S` WHERE `%S`=? AND `%S`=? AND `%S` LIKE ? LIMIT 1",
                         fields->field_mask, fields->field_serv,
                         fields->field_url, fields->field_src,
                         fields->field_dst, fields->field_boxc,
                         fields->table, fields->field_smsc,
+                        fields->field_ts, fields->field_dst);
+    else
+       sql = octstr_format("SELECT `%S`, `%S`, `%S`, `%S`, `%S`, `%S` FROM `%S` WHERE `%S`=? AND `%S`=? LIMIT 1",
+                        fields->field_mask, fields->field_serv,
+                        fields->field_url, fields->field_src,
+                        fields->field_dst, fields->field_boxc,
+                        fields->table, fields->field_smsc,
                         fields->field_ts);
 
     gwlist_append(binds, (Octstr *)smsc);
     gwlist_append(binds, (Octstr *)ts);
+    if (dst){
+       int len = octstr_len(dst);
+       char *p = octstr_get_cstr(dst);
 
+       if (len > MIN_DST_LEN)
+           p += len - MIN_DST_LEN;         /* get last MIN_DST_LEN digits */
+       like = octstr_create(strcat("%", p));
+       gwlist_append(binds, like);
+    }
+
 #if defined(DLR_TRACE)
     debug("dlr.mysql", 0, "sql: %s", octstr_get_cstr(sql));
 #endif
 
     if (dbpool_conn_select(pconn, sql, binds, &result) != 0) {
         octstr_destroy(sql);
+        if (like) octstr_destroy(like);
         dbpool_conn_produce(pconn);
         return NULL;
     }
     octstr_destroy(sql);
+    if (like) octstr_destroy(like);
     gwlist_destroy(binds, NULL);
     dbpool_conn_produce(pconn);
 
@@ -195,7 +214,7 @@
 
 static void dlr_mysql_remove(const Octstr *smsc, const Octstr *ts, const Octstr *dst)
 {
-    Octstr *sql;
+    Octstr *sql, *like = NULL;
     DBPoolConn *pconn;
     List *binds = gwlist_create();
     int res;
@@ -207,13 +226,27 @@
     if (pconn == NULL)
         return;
 
-    sql = octstr_format("DELETE FROM `%S` WHERE `%S`=? AND `%S`=? LIMIT 1",
+    if (dst)
+       sql = octstr_format("DELETE FROM `%S` WHERE `%S`=? AND `%S`=? AND `%S` LIKE ? LIMIT 1",
                         fields->table, fields->field_smsc,
+                        fields->field_ts, fields->field_dst);
+    else
+       sql = octstr_format("DELETE FROM `%S` WHERE `%S`=? AND `%S`=? LIMIT 1",
+                        fields->table, fields->field_smsc,
                         fields->field_ts);
 
     gwlist_append(binds, (Octstr *)smsc);
     gwlist_append(binds, (Octstr *)ts);
+    if (dst){
+       int len = octstr_len(dst);
+       char *p = octstr_get_cstr(dst);
 
+       if (len > MIN_DST_LEN)
+           p += len - MIN_DST_LEN;         /* get last MIN_DST_LEN digits */
+       like = octstr_create(strcat("%", p));
+       gwlist_append(binds, like);
+    }
+
 #if defined(DLR_TRACE)
     debug("dlr.mysql", 0, "sql: %s", octstr_get_cstr(sql));
 #endif
@@ -226,11 +259,12 @@
     dbpool_conn_produce(pconn);
     gwlist_destroy(binds, NULL);
     octstr_destroy(sql);
+    if (like) octstr_destroy(like);
 }
 
 static void dlr_mysql_update(const Octstr *smsc, const Octstr *ts, const Octstr *dst, int status)
 {
-    Octstr *sql, *os_status;
+    Octstr *sql, *os_status, *like = NULL;
     DBPoolConn *pconn;
     List *binds = gwlist_create();
     int res;
@@ -242,15 +276,30 @@
     if (pconn == NULL)
         return;
 
-    sql = octstr_format("UPDATE `%S` SET `%S`=? WHERE `%S`=? AND `%S`=? LIMIT 1",
+    if (dst)
+       sql = octstr_format("UPDATE `%S` SET `%S`=? WHERE `%S`=? AND `%S`=? AND `%S` LIKE ? LIMIT 1",
                         fields->table, fields->field_status,
+                        fields->field_smsc, fields->field_ts,
+                        fields->field_dst);
+    else
+       sql = octstr_format("UPDATE `%S` SET `%S`=? WHERE `%S`=? AND `%S`=? LIMIT 1",
+                        fields->table, fields->field_status,
                         fields->field_smsc, fields->field_ts);
 
     os_status = octstr_format("%d", status);
     gwlist_append(binds, (Octstr *)os_status);
     gwlist_append(binds, (Octstr *)smsc);
     gwlist_append(binds, (Octstr *)ts);
+    if (dst){
+       int len = octstr_len(dst);
+       char *p = octstr_get_cstr(dst);
 
+       if (len > MIN_DST_LEN)
+           p += len - MIN_DST_LEN;         /* get last MIN_DST_LEN digits */
+       like = octstr_create(strcat("%", p));
+       gwlist_append(binds, like);
+    }
+
 #if defined(DLR_TRACE)
     debug("dlr.mysql", 0, "sql: %s", octstr_get_cstr(sql));
 #endif
@@ -263,6 +312,7 @@
     gwlist_destroy(binds, NULL);
     octstr_destroy(os_status);
     octstr_destroy(sql);
+    if (like) octstr_destroy(like);
 }
 
 
@@ -446,4 +496,3 @@
     return NULL;
 }
 #endif /* HAVE_MYSQL */
-
Index: gw/dlr_oracle.c
===================================================================
--- gw/dlr_oracle.c	(revision 4833)
+++ gw/dlr_oracle.c	(working copy)
@@ -171,7 +171,7 @@
 
 static void dlr_remove_oracle(const Octstr *smsc, const Octstr *ts, const Octstr *dst)
 {
-    Octstr *sql;
+    Octstr *sql, *like = NULL;
     DBPoolConn *pconn;
     List *binds = gwlist_create();
     int res;
@@ -183,14 +183,25 @@
     if (pconn == NULL)
         return;
 
-    sql = octstr_format("DELETE FROM %S WHERE %S=:1 AND %S=:2 AND %S=:3 AND ROWNUM < 2",
+    if (dst)
+       sql = octstr_format("DELETE FROM %S WHERE %S=:1 AND %S=:2 AND %S LIKE :3 AND ROWNUM < 2",
                         fields->table, fields->field_smsc,
                         fields->field_ts, fields->field_dst);
+    else sql = octstr_format("DELETE FROM %S WHERE %S=:1 AND %S=:2 AND ROWNUM < 2",
+                        fields->table, fields->field_smsc, fields->field_ts);
 
-    gwlist_append(binds, (Octstr *)smsc);      /* :1 */
-    gwlist_append(binds, (Octstr *)ts);        /* :2 */
-    gwlist_append(binds, (Octstr *)dst);       /* :3 */
+    gwlist_append(binds, (Octstr *)smsc);               /* :1 */
+    gwlist_append(binds, (Octstr *)ts);                 /* :2 */
+    if (dst){                                           /* :3 */
+       int len = octstr_len(dst);
+       char *p = octstr_get_cstr(dst);
 
+       if (len > MIN_DST_LEN)
+           p += len - MIN_DST_LEN;         /* get last MIN_DST_LEN digits */
+       like = octstr_create(strcat("%", p));
+       gwlist_append(binds, like);
+    }
+
 #if defined(DLR_TRACE)
     debug("dlr.oracle", 0, "sql: %s", octstr_get_cstr(sql));
 #endif
@@ -203,11 +214,12 @@
     dbpool_conn_produce(pconn);
     gwlist_destroy(binds, NULL);
     octstr_destroy(sql);
+    if (like) octstr_destroy(like);
 }
 
 static struct dlr_entry* dlr_get_oracle(const Octstr *smsc, const Octstr *ts, const Octstr *dst)
 {
-    Octstr *sql;
+    Octstr *sql, *like = NULL;
     DBPoolConn *pconn;
     List *result = NULL, *row;
     struct dlr_entry *res = NULL;
@@ -217,26 +229,44 @@
     if (pconn == NULL) /* should not happens, but sure is sure */
         return NULL;
 
-    sql = octstr_format("SELECT %S, %S, %S, %S, %S, %S FROM %S WHERE %S=:1 AND %S=:2 AND %S=:3 AND ROWNUM < 2",
+    if (dst)
+       sql = octstr_format("SELECT %S, %S, %S, %S, %S, %S FROM %S WHERE %S=:1 AND %S=:2 AND %S LIKE :3 AND ROWNUM < 2",
                         fields->field_mask, fields->field_serv,
                         fields->field_url, fields->field_src,
                         fields->field_dst, fields->field_boxc,
                         fields->table, fields->field_smsc,
                         fields->field_ts, fields->field_dst);
+    else
+       sql = octstr_format("SELECT %S, %S, %S, %S, %S, %S FROM %S WHERE %S=:1 AND %S=:2 AND ROWNUM < 2",
+                        fields->field_mask, fields->field_serv,
+                        fields->field_url, fields->field_src,
+                        fields->field_dst, fields->field_boxc,
+                        fields->table, fields->field_smsc,
+                        fields->field_ts);
 
-    gwlist_append(binds, (Octstr *)smsc);      /* :1 */
-    gwlist_append(binds, (Octstr *)ts);        /* :2 */
-    gwlist_append(binds, (Octstr *)dst);       /* :3 */
+    gwlist_append(binds, (Octstr *)smsc);               /* :1 */
+    gwlist_append(binds, (Octstr *)ts);                 /* :2 */
+    if (dst){
+       int len = octstr_len(dst);
+       char *p = octstr_get_cstr(dst);
 
+       if (len > MIN_DST_LEN)
+           p += len - MIN_DST_LEN;         /* get last MIN_DST_LEN digits */
+       like = octstr_create(strcat("%", p));
+       gwlist_append(binds, like);
+    }
+
 #if defined(DLR_TRACE)
     debug("dlr.oracle", 0, "sql: %s", octstr_get_cstr(sql));
 #endif
     if (dbpool_conn_select(pconn, sql, binds, &result) != 0) {
         octstr_destroy(sql);
+        if (like) octstr_destroy(like);
         dbpool_conn_produce(pconn);
         return NULL;
     }
     octstr_destroy(sql);
+    if (like) octstr_destroy(like);
     gwlist_destroy(binds, NULL);
     dbpool_conn_produce(pconn);
 
@@ -264,7 +294,7 @@
 
 static void dlr_update_oracle(const Octstr *smsc, const Octstr *ts, const Octstr *dst, int status)
 {
-    Octstr *sql, *os_status;
+    Octstr *sql, *os_status, *like = NULL;
     DBPoolConn *pconn;
     List *binds = gwlist_create();
     int res;
@@ -276,15 +306,28 @@
     if (pconn == NULL)
         return;
 
-    sql = octstr_format("UPDATE %S SET %S=:1 WHERE %S=:2 AND %S=:3 AND %S=:4 AND ROWNUM < 2",
+    if (dst)
+       sql = octstr_format("UPDATE %S SET %S=:1 WHERE %S=:2 AND %S=:3 AND %S LIKE :4 AND ROWNUM < 2",
                         fields->table, fields->field_status,
                         fields->field_smsc, fields->field_ts, fields->field_dst);
+    else sql = octstr_format("UPDATE %S SET %S=:1 WHERE %S=:2 AND %S=:3 AND ROWNUM < 2",
+                        fields->table, fields->field_status,
+                        fields->field_smsc, fields->field_ts);
 
     os_status = octstr_format("%d", status);
-    gwlist_append(binds, (Octstr *)os_status); /* :1 */
-    gwlist_append(binds, (Octstr *)smsc);      /* :2 */
-    gwlist_append(binds, (Octstr *)ts);        /* :3 */
-    gwlist_append(binds, (Octstr *)dst);       /* :4 */
+    gwlist_append(binds, (Octstr *)os_status);          /* :1 */
+    gwlist_append(binds, (Octstr *)smsc);               /* :2 */
+    gwlist_append(binds, (Octstr *)ts);                 /* :3 */
+    if (dst){                                           /* :4 */
+       int len = octstr_len(dst);
+       char *p = octstr_get_cstr(dst);
+
+       if (len > MIN_DST_LEN)
+           p += len - MIN_DST_LEN;         /* get last MIN_DST_LEN digits */
+       like = octstr_create(strcat("%", p));
+       gwlist_append(binds, like);
+    }
+
 #if defined(DLR_TRACE)
     debug("dlr.oracle", 0, "sql: %s", octstr_get_cstr(sql));
 #endif
@@ -297,6 +340,7 @@
     gwlist_destroy(binds, NULL);
     octstr_destroy(os_status);
     octstr_destroy(sql);
+    if (like) octstr_destroy(like);
 }
 
 static void dlr_flush_oracle (void)
Index: gw/dlr_pgsql.c
===================================================================
--- gw/dlr_pgsql.c	(revision 4833)
+++ gw/dlr_pgsql.c	(working copy)
@@ -168,14 +168,34 @@
     Octstr *sql;
     List *result, *row;
 
-    sql = octstr_format("SELECT \"%s\", \"%s\", \"%s\", \"%s\", \"%s\", \"%s\" FROM \"%s\" WHERE \"%s\"='%s' AND \"%s\"='%s' LIMIT 1;",
-                        octstr_get_cstr(fields->field_mask), octstr_get_cstr(fields->field_serv),
-                        octstr_get_cstr(fields->field_url), octstr_get_cstr(fields->field_src),
-                        octstr_get_cstr(fields->field_dst), octstr_get_cstr(fields->field_boxc),
-                        octstr_get_cstr(fields->table), octstr_get_cstr(fields->field_smsc),
-                        octstr_get_cstr(smsc), octstr_get_cstr(fields->field_ts), octstr_get_cstr(ts));
+    if (dst){
+       int len = octstr_len(dst);
+       char *p = octstr_get_cstr(dst);
 
 
+       if (len > MIN_DST_LEN)
+           p += len - MIN_DST_LEN;         /* get last MIN_DST_LEN digits */
+       sql = octstr_format("SELECT \"%s\", \"%s\", \"%s\", \"%s\", \"%s\", "
+             "\"%s\" FROM \"%s\" WHERE \"%s\"='%s' AND \"%s\"='%s' AND \"%s\""
+             " LIKE '%%%s' LIMIT 1;", octstr_get_cstr(fields->field_mask),
+             octstr_get_cstr(fields->field_serv), octstr_get_cstr(fields->
+             field_url), octstr_get_cstr(fields->field_src), octstr_get_cstr
+             (fields->field_dst), octstr_get_cstr(fields->field_boxc),
+             octstr_get_cstr(fields->table), octstr_get_cstr(fields->
+             field_smsc), octstr_get_cstr(smsc), octstr_get_cstr(fields->
+             field_ts), octstr_get_cstr(ts), octstr_get_cstr(fields->
+             field_dst), p);
+    }
+    else
+       sql = octstr_format("SELECT \"%s\", \"%s\", \"%s\", \"%s\", \"%s\", "
+             "\"%s\" FROM \"%s\" WHERE \"%s\"='%s' AND \"%s\"='%s' LIMIT 1;",
+             octstr_get_cstr(fields->field_mask), octstr_get_cstr(fields->
+             field_serv), octstr_get_cstr(fields->field_url), octstr_get_cstr
+             (fields->field_src), octstr_get_cstr(fields->field_dst),
+             octstr_get_cstr(fields->field_boxc), octstr_get_cstr(fields->
+             table), octstr_get_cstr(fields->field_smsc), octstr_get_cstr(smsc),
+             octstr_get_cstr(fields->field_ts), octstr_get_cstr(ts));
+
     result = pgsql_select(sql);
     octstr_destroy(sql);
 
@@ -221,12 +241,28 @@
     Octstr *sql;
 
     debug("dlr.pgsql", 0, "removing DLR from database");
-    sql = octstr_format("DELETE FROM \"%s\" WHERE oid = (SELECT oid FROM \"%s\" WHERE \"%s\"='%s' AND \"%s\"='%s' LIMIT 1);",
-                        octstr_get_cstr(fields->table), octstr_get_cstr(fields->table),
-                        octstr_get_cstr(fields->field_smsc),
-                        octstr_get_cstr(smsc), octstr_get_cstr(fields->field_ts), octstr_get_cstr(ts));
+    if (dst){
+       int len = octstr_len(dst);
+       char *p = octstr_get_cstr(dst);
 
 
+       if (len > MIN_DST_LEN)
+           p += len - MIN_DST_LEN;         /* get last MIN_DST_LEN digits */
+       sql = octstr_format("DELETE FROM \"%s\" WHERE oid = (SELECT oid FROM "
+             "\"%s\" WHERE \"%s\"='%s' AND \"%s\"='%s' AND \"%s\" LIKE '%%%s' "
+             "LIMIT 1);", octstr_get_cstr(fields->table), octstr_get_cstr
+             (fields->table), octstr_get_cstr(fields->field_smsc),
+             octstr_get_cstr(smsc), octstr_get_cstr(fields->field_ts),
+             octstr_get_cstr(ts), octstr_get_cstr(fields->field_dst), p);
+    }
+    else
+       sql = octstr_format("DELETE FROM \"%s\" WHERE oid = (SELECT oid FROM "
+             "\"%s\" WHERE \"%s\"='%s' AND \"%s\"='%s' LIMIT 1);",
+             octstr_get_cstr(fields->table), octstr_get_cstr(fields->table),
+             octstr_get_cstr(fields->field_smsc), octstr_get_cstr(smsc),
+             octstr_get_cstr(fields->field_ts), octstr_get_cstr(ts));
+
+
     if (!pgsql_update(sql))
        warning(0, "DLR: PGSQL: No dlr deleted for DST<%s>", octstr_get_cstr(dst));
     octstr_destroy(sql);
@@ -238,12 +274,28 @@
     Octstr *sql;
 
     debug("dlr.pgsql", 0, "updating DLR status in database");
-    sql = octstr_format("UPDATE \"%s\" SET \"%s\"=%d WHERE oid = (SELECT oid FROM \"%s\" WHERE \"%s\"='%s' AND \"%s\"='%s' LIMIT 1);",
-                        octstr_get_cstr(fields->table),
-                        octstr_get_cstr(fields->field_status), status,
-                        octstr_get_cstr(fields->table),
-                        octstr_get_cstr(fields->field_smsc), octstr_get_cstr(smsc),
-                        octstr_get_cstr(fields->field_ts), octstr_get_cstr(ts));
+    if (dst){
+       int len = octstr_len(dst);
+       char *p = octstr_get_cstr(dst);
+
+
+       if (len > MIN_DST_LEN)
+           p += len - MIN_DST_LEN;         /* get last MIN_DST_LEN digits */
+       sql = octstr_format("UPDATE \"%s\" SET \"%s\"=%d WHERE oid = (SELECT "
+           "oid FROM \"%s\" WHERE \"%s\"='%s' AND \"%s\"='%s' AND \"%s\" LIKE "
+           "'%%%s' LIMIT 1);", octstr_get_cstr(fields->table), octstr_get_cstr
+           (fields->field_status), status, octstr_get_cstr(fields->table),
+           octstr_get_cstr(fields->field_smsc), octstr_get_cstr(smsc),
+           octstr_get_cstr(fields->field_ts), octstr_get_cstr(ts),
+           octstr_get_cstr(fields->field_dst), p);
+    }
+    else
+       sql = octstr_format("UPDATE \"%s\" SET \"%s\"=%d WHERE oid = (SELECT "
+             "oid FROM \"%s\" WHERE \"%s\"='%s' AND \"%s\"='%s' LIMIT 1);",
+             octstr_get_cstr(fields->table), octstr_get_cstr(fields->
+             field_status), status, octstr_get_cstr(fields->table),
+             octstr_get_cstr(fields->field_smsc), octstr_get_cstr(smsc),
+             octstr_get_cstr(fields->field_ts), octstr_get_cstr(ts));
     if (!pgsql_update(sql))
        warning(0, "DLR: PGSQL: No dlr updated for DST<%s> (status: %d)", octstr_get_cstr(dst), status);
     octstr_destroy(sql);
Index: gw/dlr_mem.c
===================================================================
--- gw/dlr_mem.c	(revision 4833)
+++ gw/dlr_mem.c	(working copy)
@@ -125,9 +125,23 @@
     /* XXX: check destination addr too, because e.g. for UCP is not enough to check only
      *          smsc and timestamp (timestamp is even without milliseconds)
      */
-    if(octstr_compare(dlr->smsc,smsc) == 0 && octstr_compare(dlr->timestamp,ts) == 0)
-        return 0;
+    if (dst){
+       int size, len1 = octstr_len(dlr->destination), len2 = octstr_len(dst);
+       char *p1 = octstr_get_cstr(dlr->destination), *p2 = octstr_get_cstr(dst);
 
+       size = (len1 < MIN_DST_LEN)? len1: MIN_DST_LEN;
+       size = (len2 < size)? len2: size;
+
+       if (octstr_compare(dlr->smsc, smsc) == 0 && octstr_compare(dlr->
+           timestamp, ts) == 0 && memcmp(p1 + len1 - size, p2 + len2 - size,
+           size) == 0)
+           return 0;
+    }
+    else
+       if (octstr_compare(dlr->smsc, smsc) == 0 && octstr_compare(dlr->
+           timestamp, ts) == 0)
+           return 0;
+
     return 1;
 }
 
Index: gw/dlr_mssql.c
===================================================================
--- gw/dlr_mssql.c	(revision 4833)
+++ gw/dlr_mssql.c	(working copy)
@@ -172,10 +172,21 @@
     if (pconn == NULL)
         return;
 
-    sql = octstr_format("SET ROWCOUNT 1\n"
-            "DELETE FROM %S WHERE %S='%S' AND %S='%S'\n"
-            "SET ROWCOUNT 0",
-            fields->table, fields->field_smsc, smsc,
+    if (dst){
+       int len = octstr_len(dst);
+       char *p = octstr_get_cstr(dst);
+
+
+       if (len > MIN_DST_LEN)
+           p += len - MIN_DST_LEN;         /* get last MIN_DST_LEN digits */
+       sql = octstr_format("SET ROWCOUNT 1\nDELETE FROM %S WHERE %S='%S' AND "
+            "%S='%S' AND %S LIKE '%%%s'\nSET ROWCOUNT 0", fields->table,
+            fields->field_smsc, smsc, fields->field_ts, ts, fields->field_dst,
+            p);
+    }
+    else
+       sql = octstr_format("SET ROWCOUNT 1\nDELETE FROM %S WHERE %S='%S' AND "
+            "%S='%S'\nSET ROWCOUNT 0", fields->table, fields->field_smsc, smsc,
             fields->field_ts, ts);
 
 #if defined(DLR_TRACE)
@@ -202,9 +213,25 @@
     if (pconn == NULL) /* should not happens, but sure is sure */
         return NULL;
 
-    sql = octstr_format("SELECT %S, %S, %S, %S, %S, %S FROM %S WHERE %S='%S' AND %S='%S'",
+    if (dst){
+       int len = octstr_len(dst);
+       char *p = octstr_get_cstr(dst);
+
+
+       if (len > MIN_DST_LEN)
+           p += len - MIN_DST_LEN;         /* get last MIN_DST_LEN digits */
+        sql = octstr_format("SELECT %S, %S, %S, %S, %S, %S FROM %S WHERE %S="
+                "'%S' AND %S='%S' AND %S LIKE '%%%s'",
                 fields->field_mask, fields->field_serv, fields->field_url,
                 fields->field_src, fields->field_dst, fields->field_boxc,
+                fields->table, fields->field_smsc, smsc, fields->field_ts, ts,
+                fields->field_dst, p);
+    }
+    else
+       sql = octstr_format("SELECT %S, %S, %S, %S, %S, %S FROM %S WHERE %S="
+                "'%S' AND %S='%S'",
+                fields->field_mask, fields->field_serv, fields->field_url,
+                fields->field_src, fields->field_dst, fields->field_boxc,
                 fields->table, fields->field_smsc, smsc, fields->field_ts, ts);
 
 #if defined(DLR_TRACE)
@@ -253,12 +280,24 @@
     if (pconn == NULL)
         return;
 
-    sql = octstr_format("SET ROWCOUNT 1\n"
-            "UPDATE %S SET %S=%d WHERE %S='%S' AND %S='%S'\n"
-            "SET ROWCOUNT 0",
-            fields->table, fields->field_status, status,
-            fields->field_smsc, smsc, fields->field_ts, ts);
+    if (dst){
+       int len = octstr_len(dst);
+       char *p = octstr_get_cstr(dst);
 
+
+       if (len > MIN_DST_LEN)
+           p += len - MIN_DST_LEN;         /* get last MIN_DST_LEN digits */
+       sql = octstr_format("SET ROWCOUNT 1\nUPDATE %S SET %S=%d WHERE %S='%S' "
+           "AND %S='%S' AND %S LIKE '%%%s'\nSET ROWCOUNT 0",
+           fields->table, fields->field_status, status,
+           fields->field_smsc, smsc, fields->field_ts, ts, fields->field_dst,
+           p);
+    }
+    else
+       sql = octstr_format("SET ROWCOUNT 1\nUPDATE %S SET %S=%d WHERE %S='%S' "
+            "AND %S='%S'\nSET ROWCOUNT 0", fields->table, fields->field_status,
+            status, fields->field_smsc, smsc, fields->field_ts, ts);
+
 #if defined(DLR_TRACE)
     debug("dlr.mssql", 0, "sql: %s", octstr_get_cstr(sql));
 #endif
Index: gw/dlr_sdb.c
===================================================================
--- gw/dlr_sdb.c	(revision 4833)
+++ gw/dlr_sdb.c	(working copy)
@@ -210,7 +210,7 @@
     return 0;
 }
 
-static struct dlr_entry*  dlr_sdb_get(const Octstr *smsc, const Octstr *ts, const Octstr *dst)
+static struct dlr_entry* dlr_sdb_get(const Octstr *smsc, const Octstr *ts, const Octstr *dst)
 {
     Octstr *sql;
     int	state;
@@ -218,14 +218,33 @@
 
     gw_assert(res != NULL);
 
-    sql = octstr_format("SELECT %s, %s, %s, %s, %s, %s FROM %s WHERE %s='%s' AND %s='%s' %s",
-                        octstr_get_cstr(fields->field_mask), octstr_get_cstr(fields->field_serv),
-                        octstr_get_cstr(fields->field_url), octstr_get_cstr(fields->field_src),
-                        octstr_get_cstr(fields->field_dst), octstr_get_cstr(fields->field_boxc),
-                        octstr_get_cstr(fields->table),
-                        octstr_get_cstr(fields->field_smsc), octstr_get_cstr(smsc),
-                        octstr_get_cstr(fields->field_ts), octstr_get_cstr(ts), sdb_get_limit_str());
+    if (dst){
+       int len = octstr_len(dst);
+       char *p = octstr_get_cstr(dst);
 
+
+       if (len > MIN_DST_LEN)
+           p += len - MIN_DST_LEN;         /* get last MIN_DST_LEN digits */
+       sql = octstr_format("SELECT %s, %s, %s, %s, %s, %s FROM %s WHERE %s="
+             "'%s' AND %s='%s' AND %s LIKE '%%%s' %s", octstr_get_cstr
+             (fields->field_mask), octstr_get_cstr(fields->field_serv),
+             octstr_get_cstr(fields->field_url), octstr_get_cstr(fields->
+             field_src), octstr_get_cstr(fields->field_dst), octstr_get_cstr
+             (fields->field_boxc), octstr_get_cstr(fields->table),
+             octstr_get_cstr(fields->field_smsc), octstr_get_cstr(smsc),
+             octstr_get_cstr(fields->field_ts), octstr_get_cstr(ts),
+             octstr_get_cstr(fields->field_dst), p, sdb_get_limit_str());
+    }
+    else
+       sql = octstr_format("SELECT %s, %s, %s, %s, %s, %s FROM %s WHERE %s='%s'"
+             " AND %s='%s' %s", octstr_get_cstr(fields->field_mask),
+             octstr_get_cstr(fields->field_serv), octstr_get_cstr(fields->
+             field_url), octstr_get_cstr(fields->field_src), octstr_get_cstr
+             (fields->field_dst), octstr_get_cstr(fields->field_boxc),
+             octstr_get_cstr(fields->table), octstr_get_cstr(fields->
+             field_smsc), octstr_get_cstr(smsc), octstr_get_cstr(fields->
+             field_ts), octstr_get_cstr(ts), sdb_get_limit_str());
+
 #if defined(DLR_TRACE)
      debug("dlr.sdb", 0, "SDB: sql: %s", octstr_get_cstr(sql));
 #endif
@@ -256,12 +275,28 @@
     int	state;
 
     debug("dlr.sdb", 0, "SDB: updating DLR status in database");
-    sql = octstr_format("UPDATE %s SET %s=%d WHERE %s='%s' AND %s='%s' %s",
-                        octstr_get_cstr(fields->table),
-                        octstr_get_cstr(fields->field_status), status,
-                        octstr_get_cstr(fields->field_smsc), octstr_get_cstr(smsc),
-                        octstr_get_cstr(fields->field_ts), octstr_get_cstr(ts), sdb_get_limit_str());
 
+    if (dst){
+       int len = octstr_len(dst);
+       char *p = octstr_get_cstr(dst);
+
+
+       if (len > MIN_DST_LEN)
+           p += len - MIN_DST_LEN;         /* get last MIN_DST_LEN digits */
+       sql = octstr_format("UPDATE %s SET %s=%d WHERE %s='%s' AND %s='%s' AND "
+             "%s LIKE '%%%s' %s", octstr_get_cstr(fields->table),
+             octstr_get_cstr(fields->field_status), status, octstr_get_cstr
+             (fields->field_smsc), octstr_get_cstr(smsc), octstr_get_cstr
+             (fields->field_ts), octstr_get_cstr(ts), octstr_get_cstr(fields->
+             field_dst), p, sdb_get_limit_str());
+    }
+    else
+       sql = octstr_format("UPDATE %s SET %s=%d WHERE %s='%s' AND %s='%s' %s",
+             octstr_get_cstr(fields->table), octstr_get_cstr(fields->
+             field_status), status, octstr_get_cstr(fields->field_smsc),
+             octstr_get_cstr(smsc), octstr_get_cstr(fields->field_ts),
+             octstr_get_cstr(ts), sdb_get_limit_str());
+
 #if defined(DLR_TRACE)
      debug("dlr.sdb", 0, "SDB: sql: %s", octstr_get_cstr(sql));
 #endif
@@ -288,19 +323,48 @@
          * to do vacuum regularly, even if it's virtually impossible
          * to hit duplicates since oid's are given in a row
          */
-        sql = octstr_format("DELETE FROM %s WHERE oid = \
-                            (SELECT oid FROM %s WHERE %s='%s' AND %s='%s' LIMIT 1)",
-                            octstr_get_cstr(fields->table),
-                            octstr_get_cstr(fields->table),
-                            octstr_get_cstr(fields->field_smsc), octstr_get_cstr(smsc),
-                            octstr_get_cstr(fields->field_ts), octstr_get_cstr(ts));
-    } else {
-        sql = octstr_format("DELETE FROM %s WHERE %s='%s' AND %s='%s' %s",
-                            octstr_get_cstr(fields->table),
-                            octstr_get_cstr(fields->field_smsc), octstr_get_cstr(smsc),
-                            octstr_get_cstr(fields->field_ts), octstr_get_cstr(ts), sdb_get_limit_str());
+       if (dst){
+          int len = octstr_len(dst);
+          char *p = octstr_get_cstr(dst);
+
+
+          if (len > MIN_DST_LEN)
+              p += len - MIN_DST_LEN;      /* get last MIN_DST_LEN digits */
+          sql = octstr_format("DELETE FROM %s WHERE oid = (SELECT oid FROM %s "
+                "WHERE %s='%s' AND %s='%s' AND %s LIKE '%%%s' LIMIT 1)",
+                octstr_get_cstr(fields->table), octstr_get_cstr(fields->table),
+                octstr_get_cstr(fields->field_smsc), octstr_get_cstr(smsc),
+                octstr_get_cstr(fields->field_ts), octstr_get_cstr(ts),
+                octstr_get_cstr(fields->field_dst), p);
+       }
+       else
+          sql = octstr_format("DELETE FROM %s WHERE oid = (SELECT oid FROM %s "
+                "WHERE %s='%s' AND %s='%s' LIMIT 1)", octstr_get_cstr(fields->
+                table), octstr_get_cstr(fields->table), octstr_get_cstr
+                (fields->field_smsc), octstr_get_cstr(smsc), octstr_get_cstr
+                (fields->field_ts), octstr_get_cstr(ts));
     }
+    else {
+       if (dst){
+          int len = octstr_len(dst);
+          char *p = octstr_get_cstr(dst);
 
+
+          if (len > MIN_DST_LEN)
+              p += len - MIN_DST_LEN;       /* get last MIN_DST_LEN digits */
+          sql = octstr_format("DELETE FROM %s WHERE %s='%s' AND %s='%s' AND %s "
+                "LIKE '%%%s' %s", octstr_get_cstr(fields->table),
+                octstr_get_cstr(fields->field_smsc), octstr_get_cstr(smsc),
+                octstr_get_cstr(fields->field_ts), octstr_get_cstr(ts),
+                octstr_get_cstr(fields->field_dst), p, sdb_get_limit_str());
+       }
+       else
+          sql = octstr_format("DELETE FROM %s WHERE %s='%s' AND %s='%s' %s",
+                octstr_get_cstr(fields->table), octstr_get_cstr(fields->
+                field_smsc), octstr_get_cstr(smsc), octstr_get_cstr(fields->
+                field_ts), octstr_get_cstr(ts), sdb_get_limit_str());
+    }
+
 #if defined(DLR_TRACE)
      debug("dlr.sdb", 0, "SDB: sql: %s", octstr_get_cstr(sql));
 #endif
Index: gw/dlr.c
===================================================================
--- gw/dlr.c	(revision 4833)
+++ gw/dlr.c	(working copy)
@@ -371,7 +371,7 @@
  * NOTE: If typ is end status (e.g. DELIVERED) then dlr entry
  *       will be removed from DB.
  */
-Msg *dlr_find(const Octstr *smsc, const Octstr *ts, const Octstr *dst, int typ)
+Msg *dlr_find(const Octstr *smsc, const Octstr *ts, const Octstr *dst, int typ, int use_dst)
 {
     Msg	*msg = NULL;
     struct dlr_entry *dlr = NULL;
@@ -388,7 +388,10 @@
     debug("dlr.dlr", 0, "DLR[%s]: Looking for DLR smsc=%s, ts=%s, dst=%s, type=%d",
                                  dlr_type(), octstr_get_cstr(smsc), octstr_get_cstr(ts), octstr_get_cstr(dst), typ);
 
-    dlr = handles->dlr_get(smsc, ts, dst);
+    if (use_dst)
+       dlr = handles->dlr_get(smsc, ts, dst);
+    else
+       dlr = handles->dlr_get(smsc, ts, NULL);
     if (dlr == NULL)  {
         warning(0, "DLR[%s]: DLR from SMSC<%s> for DST<%s> not found.",
                 dlr_type(), octstr_get_cstr(smsc), octstr_get_cstr(dst));         
@@ -436,12 +439,19 @@
     if ((typ & DLR_BUFFERED) && ((dlr->mask & DLR_SUCCESS) || (dlr->mask & DLR_FAIL))) {
         debug("dlr.dlr", 0, "DLR[%s]: DLR not destroyed, still waiting for other delivery report", dlr_type());
         /* update dlr entry status if function defined */
-        if (handles != NULL && handles->dlr_update != NULL)
-            handles->dlr_update(smsc, ts, dst, typ);
+        if (handles != NULL && handles->dlr_update != NULL){
+            if (use_dst)
+               handles->dlr_update(smsc, ts, dst, typ);
+            else
+               handles->dlr_update(smsc, ts, NULL, typ);
+        }
     } else {
-        if (handles != NULL && handles->dlr_remove != NULL) {
+        if (handles != NULL && handles->dlr_remove != NULL){
             /* it's not good for internal storage, but better for all others */
-            handles->dlr_remove(smsc, ts, dst);
+            if (use_dst)
+               handles->dlr_remove(smsc, ts, dst);
+            else
+               handles->dlr_remove(smsc, ts, NULL);
         } else {
             warning(0, "DLR[%s]: Storage don't have remove operation defined", dlr_type());
         }
Index: gw/dlr.h
===================================================================
--- gw/dlr.h	(revision 4833)
+++ gw/dlr.h	(working copy)
@@ -103,7 +103,8 @@
  * Find an entry in the list. If there is one a message is returned and 
  * the entry is removed from the list otherwhise the message returned is NULL 
  */
-Msg* dlr_find(const Octstr *smsc, const Octstr *ts, const Octstr *dst, int type);
+Msg* dlr_find(const Octstr *smsc, const Octstr *ts, const Octstr *dst, int type,
+ int use_dst);
 
 /* return the number of DLR messages in the current waiting queue */
 long dlr_messages(void);
Index: gw/dlr_p.h
===================================================================
--- gw/dlr_p.h	(revision 4833)
+++ gw/dlr_p.h	(working copy)
@@ -70,6 +70,8 @@
 
 #define DLR_TRACE 1
 
+/* Used in destination based queries for EMI/UUCP DLRs */
+#define MIN_DST_LEN 7
 /*
  * The structure of a delivery report  entry.
  */
Index: gw/smsc/smsc_cimd2.c
===================================================================
--- gw/smsc/smsc_cimd2.c	(revision 4833)
+++ gw/smsc/smsc_cimd2.c	(working copy)
@@ -2114,7 +2114,7 @@
         code = 0;
     }
     if(code)
-    	msg = dlr_find(conn->name, timestamp, destination, code);
+    	msg = dlr_find(conn->name, timestamp, destination, code, 0);
     else
         msg = NULL;
 
Index: gw/smsc/smsc_soap.c
===================================================================
--- gw/smsc/smsc_soap.c	(revision 4833)
+++ gw/smsc/smsc_soap.c	(working copy)
@@ -1616,7 +1616,7 @@
     /* fetch the DLR */
 
     dlrmsg = dlr_find(conn->id, octstr_imm(msgid), octstr_imm("receiver"), /* destination */
-                      dlrtype);
+                      dlrtype, 0);
 
     if (!dlrmsg) {
         error(0,"SOAP[%s]: parse_dlr invoked (%ld), but no DLR found for MsgID %s", octstr_get_cstr(privdata->name),dlrtype,msgid);
Index: gw/smsc/smsc_oisd.c
===================================================================
--- gw/smsc/smsc_oisd.c	(revision 4833)
+++ gw/smsc/smsc_oisd.c	(working copy)
@@ -1306,7 +1306,7 @@
     }
 
     if (code)
-        msg = dlr_find(conn->name, timestamp, destination, code);
+        msg = dlr_find(conn->name, timestamp, destination, code, 0);
 
     octstr_destroy(destination);
     octstr_destroy(timestamp);
Index: gw/smsc/smsc_at.c
===================================================================
--- gw/smsc/smsc_at.c	(revision 4833)
+++ gw/smsc/smsc_at.c	(working copy)
@@ -2124,7 +2124,7 @@
      * categories. It will catch "reserved" values where the first 3 MSBits 
      * are not set as "Success" which may not be correct. */
 
-    if ((dlrmsg = dlr_find(privdata->conn->id, msg_id, receiver, type)) == NULL) {
+    if ((dlrmsg = dlr_find(privdata->conn->id, msg_id, receiver, type, 0)) == NULL) {
         debug("bb.smsc.at2", 1, "AT2[%s]: Received delivery notification but can't find that ID in the DLR storage",
               octstr_get_cstr(privdata->name));
 	    goto error;
Index: gw/smsc/smsc_fake.c
===================================================================
--- gw/smsc/smsc_fake.c	(revision 4833)
+++ gw/smsc/smsc_fake.c	(working copy)
@@ -291,7 +291,7 @@
                     dlrmsg = dlr_find(conn->id,
                                       tmp, /* smsc message id */
                                       copy->sms.receiver, /* destination */
-                                      dlrstat);
+                                      dlrstat, 0);
                     if (dlrmsg != NULL) {
                         /* XXX TODO: Provide a SMPP DLR text in msgdata */
                         bb_smscconn_receive(conn, dlrmsg);
Index: gw/smsc/smsc_http.c
===================================================================
--- gw/smsc/smsc_http.c	(revision 4833)
+++ gw/smsc/smsc_http.c	(working copy)
@@ -643,7 +643,7 @@
         dlrmsg = dlr_find(conn->id,
             dlrmid, /* message id */
             to, /* destination */
-            dlrmask);
+            dlrmask, 0);
 
         if (dlrmsg != NULL) {
             dlrmsg->sms.sms_type = report_mo;
@@ -931,8 +931,8 @@
 	}
         dlrmsg = dlr_find(conn->id,
             apimsgid, /* smsc message id */
-            dest , /* destination */
-            dlrstat);
+            dest, /* destination */
+            dlrstat, 0);
 
         if (dlrmsg != NULL) {
             /* dlrmsg->sms.msgdata = octstr_duplicate(apimsgid); */
@@ -1410,8 +1410,8 @@
 
         dlrmsg = dlr_find(conn->id,
             mid, /* smsc message id */
-            dest , /* destination */
-            dlrstat);
+            dest, /* destination */
+            dlrstat, 0);
 
         if (dlrmsg != NULL) {
             dlrmsg->sms.msgdata = octstr_duplicate(mid);
@@ -1681,7 +1681,7 @@
         dlrmsg = dlr_find(conn->id,
             dlrmid, /* message id */
             to, /* destination */
-            dlrmask);
+            dlrmask, 0);
 
         if (dlrmsg != NULL) {
             dlrmsg->sms.sms_type = report_mo;
Index: gw/smsc/smsc_smpp.c
===================================================================
--- gw/smsc/smsc_smpp.c	(revision 4833)
+++ gw/smsc/smsc_smpp.c	(working copy)
@@ -1392,7 +1392,7 @@
         dlrmsg = dlr_find(smpp->conn->id,
             tmp, /* smsc message id */
             destination_addr, /* destination */
-            dlrstat);
+            dlrstat, 0);
 
         octstr_destroy(msgid);
     } else
Index: gw/smsc/smsc_cgw.c
===================================================================
--- gw/smsc/smsc_cgw.c	(revision 4833)
+++ gw/smsc/smsc_cgw.c	(working copy)
@@ -1137,19 +1137,19 @@
                 dlrmsg = dlr_find(conn->id,
                                             ts,     /* timestamp */
                                             msid,   /* destination */
-                                  DLR_SUCCESS);
+                                  DLR_SUCCESS, 0);
                 break;
             case 1:     /* buffered */
                 dlrmsg = dlr_find(conn->id,
                                             ts,     /* timestamp */
                                             msid,   /* destination */
-                                  DLR_BUFFERED);
+                                  DLR_BUFFERED, 0);
                 break;
             case 2:     /* not delivered */
                 dlrmsg = dlr_find(conn->id,
                                             ts,     /* timestamp */
                                             msid,   /* destination */
-                                  DLR_FAIL);
+                                  DLR_FAIL, 0);
                 break;
             }
 
