瀏覽代碼

modules/ims_registrar_scscf: fixed possible shm corruption
- in async reply mode, working on shm orig request is bad
- instead work on a copy of original request in pkg (parsing, etc)

jaybeepee 9 年之前
父節點
當前提交
4b9031ccd8

+ 16 - 7
modules/ims_registrar_scscf/cxdx_sar.c

@@ -64,6 +64,7 @@
 #include "../../parser/hf.h"
 #include "../../lib/ims/ims_getters.h"
 #include "registrar_notify.h"
+#include "pvt_message.h"
 
 extern struct cdp_binds cdpb;
 
@@ -103,6 +104,7 @@ void async_cdp_callback(int is_timeout, void *param, AAAMessage *saa, long elaps
     int rc = -1, experimental_rc = -1;
     int result = CSCF_RETURN_TRUE;
     saved_transaction_t* data = 0;
+    struct sip_msg* req;
 
     str xml_data = {0, 0}, ccf1 = {0, 0}, ccf2 = {0, 0}, ecf1 = {0, 0}, ecf2 = {0, 0};
     ims_subscription* s = 0;
@@ -156,6 +158,12 @@ void async_cdp_callback(int is_timeout, void *param, AAAMessage *saa, long elaps
 
         get_act_time();
 
+        req = get_request_from_tx(t);
+        if (!req) {
+            LM_ERR("Failed to get SIP Request from Transaction\n");
+            goto error_no_send;
+        }
+        
         if (is_timeout) {
         	update_stat(stat_sar_timeouts, 1);
             LM_ERR("Transaction timeout - did not get SAA\n");
@@ -171,8 +179,9 @@ void async_cdp_callback(int is_timeout, void *param, AAAMessage *saa, long elaps
         update_stat(sar_replies_received, 1);
         update_stat(sar_replies_response_time, elapsed_msecs);
 
+        
         /* check and see that all the required headers are available and can be parsed */
-        if (parse_message_for_register(t->uas.request) < 0) {
+        if (parse_message_for_register(req) < 0) {
             LM_ERR("Unable to parse register message correctly\n");
             rerrno = R_SAR_FAILED;
             goto error;
@@ -250,7 +259,7 @@ void async_cdp_callback(int is_timeout, void *param, AAAMessage *saa, long elaps
 
         if (s) {
             //here we update the contacts and also build the new contact header for the 200 OK reply
-            if (update_contacts_new(t->uas.request, data->domain, &data->public_identity, data->sar_assignment_type, &s, &ccf1, &ccf2, &ecf1, &ecf2, &data->contact_header) <= 0) {
+            if (update_contacts(req, data->domain, &data->public_identity, data->sar_assignment_type, &s, &ccf1, &ccf2, &ecf1, &ecf2, &data->contact_header) <= 0) {
                 LM_ERR("Error processing REGISTER\n");
                 rerrno = R_SAR_FAILED;
                 goto error;
@@ -270,7 +279,7 @@ success:
 
 done:
     if (data->sar_assignment_type != AVP_IMS_SAR_UNREGISTERED_USER)
-        reg_send_reply_transactional(t->uas.request, data->contact_header, t);
+        reg_send_reply_transactional(req, data->contact_header, t);
     LM_DBG("DBG:SAR Async CDP callback: ... Done resuming transaction\n");
 
     create_return_code(result);
@@ -282,11 +291,11 @@ done:
     //free memory
     if (saa) cdpb.AAAFreeMessage(&saa);
     if (t) {
-        del_nonshm_lump_rpl(&t->uas.request->reply_lump);
+//        del_nonshm_lump_rpl(&req->reply_lump);
         tmb.unref_cell(t);
     }
     //free path vector pkg memory
-    reset_path_vector(t->uas.request);
+//    reset_path_vector(req);
 
     tmb.t_continue(data->tindex, data->tlabel, data->act);
     free_saved_transaction_data(data);
@@ -295,14 +304,14 @@ done:
 error:
     create_return_code(-2);
     if (data->sar_assignment_type != AVP_IMS_SAR_UNREGISTERED_USER)
-        reg_send_reply_transactional(t->uas.request, data->contact_header, t);
+        reg_send_reply_transactional(req, data->contact_header, t);
 		
 error_no_send: //if we don't have the transaction then we can't send a transaction response
     update_stat(rejected_registrations, 1);
     //free memory
     if (saa) cdpb.AAAFreeMessage(&saa);
     if (t) {
-        del_nonshm_lump_rpl(&t->uas.request->reply_lump);
+//        del_nonshm_lump_rpl(&req->reply_lump);
         tmb.unref_cell(t);
     }
     tmb.t_continue(data->tindex, data->tlabel, data->act);

+ 2 - 2
modules/ims_registrar_scscf/lookup.c

@@ -46,8 +46,8 @@
 #include "reg_mod.h"
 #include "lookup.h"
 #include "config.h"
-
 #include "save.h"
+#include "pvt_message.h"
 
 #define allowed_method(_msg, _c) \
 	( !method_filtering || ((_msg)->REQ_METHOD)&((_c)->methods) )
@@ -365,7 +365,7 @@ int term_impu_registered(struct sip_msg* _m, char* _t, char* _s) {
         return -1;
     }
     if (req->first_line.type != SIP_REQUEST) {
-        req = get_request_from_reply(req);
+        req = get_request_from_tx(0);
     }
 
     if (_m->new_uri.s) uri = _m->new_uri;

+ 133 - 0
modules/ims_registrar_scscf/pvt_message.c

@@ -0,0 +1,133 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2012 Smile Communications, [email protected]
+ * Copyright (C) 2012 Smile Communications, [email protected]
+ * 
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Fokus. 
+ * Copyright (C) 2004-2006 FhG Fokus
+ * Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ */
+
+#include "pvt_message.h"
+#include "../../modules/tm/tm_load.h"
+
+extern struct tm_binds tmb;
+extern struct _pv_req_data _pv_treq;
+
+void pv_tmx_data_init(void) {
+    memset(&_pv_treq, 0, sizeof (struct _pv_req_data));
+}
+
+int pv_t_copy_msg(struct sip_msg *src, struct sip_msg *dst) {
+    dst->id = src->id;
+    dst->rcv = src->rcv;
+    dst->set_global_address = src->set_global_address;
+    dst->set_global_port = src->set_global_port;
+    dst->flags = src->flags;
+    dst->fwd_send_flags = src->fwd_send_flags;
+    dst->rpl_send_flags = src->rpl_send_flags;
+    dst->force_send_socket = src->force_send_socket;
+
+    if (parse_msg(dst->buf, dst->len, dst) != 0) {
+        LM_ERR("parse msg failed\n");
+        return -1;
+    }
+    return 0;
+}
+
+struct sip_msg* get_request_from_tx(struct cell *t) {
+    if (t == NULL) {
+        t = tmb.t_gett();
+    }
+    if (!t || t == (void*) - 1) {
+        LM_ERR("Reply without transaction\n");
+        return 0;
+    }
+    if (t) {
+
+        /*  we may need the request message from here on.. if there are headers we need that were not parsed in the original request
+        (which we cannot assume) then we would pollute the shm_msg t->uas.request if we did any parsing on it. Instead, we need to 
+        make a private copy of the message and free it when we are done 
+         */
+        if (_pv_treq.T != t || t->uas.request != _pv_treq.tmsgp
+                && t->uas.request->id != _pv_treq.id) {
+
+            /* make a copy */
+            if (_pv_treq.buf == NULL || _pv_treq.buf_size < t->uas.request->len + 1) {
+                if (_pv_treq.buf != NULL)
+                    pkg_free(_pv_treq.buf);
+                if (_pv_treq.tmsgp)
+                    free_sip_msg(&_pv_treq.msg);
+                _pv_treq.tmsgp = NULL;
+                _pv_treq.id = 0;
+                _pv_treq.T = NULL;
+                _pv_treq.buf_size = t->uas.request->len + 1;
+                _pv_treq.buf = (char*) pkg_malloc(_pv_treq.buf_size * sizeof (char));
+                if (_pv_treq.buf == NULL) {
+                    LM_ERR("no more pkg\n");
+                    _pv_treq.buf_size = 0;
+                    return 0;
+                }
+            }
+            if (_pv_treq.tmsgp)
+                free_sip_msg(&_pv_treq.msg);
+            memset(&_pv_treq.msg, 0, sizeof (struct sip_msg));
+            memcpy(_pv_treq.buf, t->uas.request->buf, t->uas.request->len);
+            _pv_treq.buf[t->uas.request->len] = '\0';
+            _pv_treq.msg.len = t->uas.request->len;
+            _pv_treq.msg.buf = _pv_treq.buf;
+            _pv_treq.tmsgp = t->uas.request;
+            _pv_treq.id = t->uas.request->id;
+            _pv_treq.T = t;
+
+
+            if (pv_t_copy_msg(t->uas.request, &_pv_treq.msg) != 0) {
+                pkg_free(_pv_treq.buf);
+                _pv_treq.buf_size = 0;
+                _pv_treq.buf = NULL;
+                _pv_treq.tmsgp = NULL;
+                _pv_treq.T = NULL;
+                return 0;
+            }
+        }
+
+        return &_pv_treq.msg;
+    } else
+        return 0;
+
+}

+ 68 - 0
modules/ims_registrar_scscf/pvt_message.h

@@ -0,0 +1,68 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2012 Smile Communications, [email protected]
+ * Copyright (C) 2012 Smile Communications, [email protected]
+ * 
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Fokus. 
+ * Copyright (C) 2004-2006 FhG Fokus
+ * Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ */ 
+
+
+#ifndef PVT_MESSAGE_H
+#define PVT_MESSAGE_H
+
+
+#include "../../parser/msg_parser.h"
+
+struct _pv_req_data {
+    struct cell *T;
+    struct sip_msg msg;
+    struct sip_msg *tmsgp;
+    unsigned int id;
+    char *buf;
+    int buf_size;
+};
+
+void pv_tmx_data_init(void);
+
+int pv_t_copy_msg(struct sip_msg *src, struct sip_msg *dst);
+
+struct sip_msg* get_request_from_tx(struct cell* t);
+
+#endif /* PVT_MESSAGE_H */

+ 5 - 0
modules/ims_registrar_scscf/reg_mod.c

@@ -73,6 +73,7 @@
 #include "cxdx_callbacks.h"
 #include "registrar_notify.h"
 #include "../cdp_avp/mod_export.h"
+#include "pvt_message.h"
 
 MODULE_VERSION
 
@@ -111,6 +112,8 @@ str scscf_serviceroute_uri_str; /* Service Route URI */
 
 char *domain = "location";  ///TODO should be configurable mod param
 
+struct _pv_req_data _pv_treq;
+
 /*! \brief Module init & destroy function */
 static int mod_init(void);
 static int child_init(int);
@@ -344,6 +347,8 @@ static int mod_init(void) {
                 scscf_name_str.s, scscf_name_str.len);
         scscf_serviceroute_uri_str.len += scscf_name_str.len;
     }
+    
+    pv_tmx_data_init();
 
     /* </build required strings> */
 

+ 0 - 13
modules/ims_registrar_scscf/save.c

@@ -509,19 +509,6 @@ static inline int is_impu_registered(udomain_t* _d, str* public_identity) {
     return ret;
 }
 
-struct sip_msg* get_request_from_reply(struct sip_msg *reply) {
-    struct cell *t;
-    t = tmb.t_gett();
-    if (!t || t == (void*) - 1) {
-        LM_ERR("get_request_from_reply: Reply without transaction\n");
-        return 0;
-    }
-    if (t)
-        return t->uas.request;
-    else
-        return 0;
-}
-
 /**
  * update the contacts for a public identity. Make sure you have the lock on the domain before calling this
  * returns 0 on success, -1 on failure

+ 0 - 2
modules/ims_registrar_scscf/save.h

@@ -66,6 +66,4 @@ int update_contacts(struct sip_msg* msg, udomain_t* _d,
         str* public_identity, int assignment_type, ims_subscription** s,
         str* ccf1, str* ccf2, str* ecf1, str* ecf2, contact_for_header_t** contact_header);
 
-struct sip_msg* get_request_from_reply(struct sip_msg *reply);
-
 #endif /* SAVE_H */