]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
adding validation of megaco commands code and modification in handling ADD message
authorKapil <kgupta@sangoma.com>
Tue, 17 Jul 2012 17:07:32 +0000 (13:07 -0400)
committerKapil <kgupta@sangoma.com>
Tue, 17 Jul 2012 17:07:32 +0000 (13:07 -0400)
src/mod/endpoints/mod_media_gateway/media_gateway.c
src/mod/endpoints/mod_media_gateway/media_gateway_cmd_handler.c
src/mod/endpoints/mod_media_gateway/media_gateway_stack.h
src/mod/endpoints/mod_media_gateway/media_gateway_utils.c
src/mod/endpoints/mod_media_gateway/mod_media_gateway.c
src/mod/endpoints/mod_media_gateway/mod_media_gateway.h

index 0c43adab6bd919bc537cfe5b84c49fbbc754a421..769bdc5465427201702c9874e39ab509b55b7416 100644 (file)
@@ -46,6 +46,63 @@ void megaco_peer_profile_release(mg_peer_profile_t *profile)
        switch_thread_rwlock_unlock(profile->rwlock);
 }
 
+megaco_profile_t*  megaco_get_profile_by_suId(SuId suId)
+{
+       megaco_profile_t*    profile = NULL;
+       void            *val = NULL;
+       switch_hash_index_t *hi = NULL;
+       int found = 0x00;
+       const void *var;
+
+       /*iterate through profile list to get requested suID profile */
+       for (hi = switch_hash_first(NULL, megaco_globals.profile_hash); hi; hi = switch_hash_next(hi)) {
+               switch_hash_this(hi, &var, NULL, &val);
+               profile = (megaco_profile_t *) val;
+               if (profile->idx == suId) {
+                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Got profile[%s] associated with suId[%d]\n",profile->name, suId);
+                       found = 0x01;
+                       break;
+               }
+       }
+
+       if(!found){
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, " Not able to find profile associated with suId[%d]\n",suId);
+               return NULL;
+       }
+
+       return profile;
+}
+
+mg_context_t *megaco_find_context_by_suid(SuId suId, uint32_t context_id)
+{
+    mg_context_t *result = NULL;
+    megaco_profile_t*    profile = NULL;
+    
+    if(NULL == (profile = megaco_get_profile_by_suId(suId))){
+           return NULL;
+    }
+
+    
+    if (context_id > MG_MAX_CONTEXTS) {
+        return NULL;
+    }
+    
+    switch_thread_rwlock_rdlock(profile->contexts_rwlock);
+    
+    /* Context exists */
+    if (profile->contexts_bitmap[context_id % 8] & (1 << (context_id / 8))) {
+        for (result = profile->contexts[context_id % MG_CONTEXT_MODULO]; result; result = result->next) {
+            if (result->context_id == context_id) {
+                break;
+            }
+        }
+    }
+    
+    switch_thread_rwlock_unlock(profile->contexts_rwlock);
+    
+    return result;
+}
+
 mg_context_t *megaco_get_context(megaco_profile_t *profile, uint32_t context_id)
 {
     mg_context_t *result = NULL;
index 7855bcd9d97258aef5621a479307bb0d7c91f7ec..b19d799a9df66e73a10bf53ab0ff217fac31c876 100644 (file)
@@ -29,16 +29,65 @@ const char *mg_service_change_reason[] = {
 *
 *
 */
-switch_status_t handle_mg_add_cmd(MgMgcoAmmReq *addReq)
+switch_status_t handle_mg_add_cmd(megaco_profile_t* mg_profile, MgMgcoCommand *inc_cmd)
 {
-       int descId;
-       for (descId = 0; descId < addReq->dl.num.val; descId++) {
-               switch (addReq->dl.descs[descId]->type.val) {
+       MgMgcoContextId  *ctxtId;
+       int               descId;
+       MgStr             errTxt;
+       MgMgcoInd         *mgErr;
+       MgMgcoTermId     *termId;
+       MgMgcoTermIdLst*  termLst;
+       int               err_code;
+       MgMgcoAmmReq      *cmd = &inc_cmd->u.mgCmdInd[0]->cmd.u.add;
+       U32                txn_id = inc_cmd->transId.val;
+
+       /********************************************************************/
+       ctxtId  = &inc_cmd->contextId;
+       termLst = mg_get_term_id_list(inc_cmd);
+       termId  = termLst->terms[0];
+
+       /********************************************************************/
+       /* Validating ADD request *******************************************/
+
+       /*-- NULL Context & ALL Context not applicable for ADD request --*/
+       if ((NOTPRSNT != ctxtId->type.pres)          &&
+                       ((MGT_CXTID_ALL == ctxtId->type.val)     ||
+                        (MGT_CXTID_NULL == ctxtId->type.val))) {
+
+               switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_ERROR," ADD Request processing failed, Context ALL/NULL not allowed\n");
+
+               mg_util_set_ctxt_string(&errTxt, ctxtId);
+               err_code = MGT_MGCO_RSP_CODE_PROT_ERROR;
+               goto error;
+       }
+
+       /********************************************************************/
+       /* Allocate context - if context type is CHOOSE */
+       if ((NOTPRSNT != ctxtId->type.pres)  &&
+                       (MGT_CXTID_CHOOSE == ctxtId->type.val)){
+
+               /* TODO - Matt */
+       }
+
+       /********************************************************************/
+       /* Allocate new RTP termination - If term type is CHOOSE */
+       if ((NOTPRSNT != termId->type.pres)   &&
+                       (MGT_TERMID_CHOOSE == termId->type.val)){
+
+               /* TODO - Matt */
+               /* allocate rtp term and associated the same to context */
+       }
+
+       /********************************************************************/
+
+
+       for (descId = 0; descId < cmd->dl.num.val; descId++) {
+               switch (cmd->dl.descs[descId]->type.val) {
                        case MGT_MEDIADESC:
                                {
                                        int mediaId;
-                                       for (mediaId = 0; mediaId < addReq->dl.descs[descId]->u.media.num.val; mediaId++) {
-                                               MgMgcoMediaPar *mediaPar = addReq->dl.descs[descId]->u.media.parms[mediaId];
+                                       for (mediaId = 0; mediaId < cmd->dl.descs[descId]->u.media.num.val; mediaId++) {
+                                               MgMgcoMediaPar *mediaPar = cmd->dl.descs[descId]->u.media.parms[mediaId];
                                                switch (mediaPar->type.val) {
                                                        case MGT_MEDIAPAR_LOCAL:
                                                                {
@@ -94,6 +143,13 @@ switch_status_t handle_mg_add_cmd(MgMgcoAmmReq *addReq)
 
 
        return SWITCH_STATUS_SUCCESS;   
+error:
+       if (SWITCH_STATUS_SUCCESS == 
+                       mg_build_mgco_err_request(&mgErr, txn_id, ctxtId, err_code, &errTxt)) {
+               sng_mgco_send_err(mg_profile->idx, mgErr);
+       }
+       mg_free_cmd(cmd);
+       return SWITCH_STATUS_FALSE;     
 }
 
 /*****************************************************************************************************************************/
index cdbde20c1343f2f83676007aa5eaa0ef973d41ca..8225ee95700997b8f22731fe2297abb95090ab68 100644 (file)
@@ -133,7 +133,7 @@ int sng_mgco_mg_get_status(int elemId, MgMngmt* cfm, megaco_profile_t* mg_cfg, m
 switch_status_t mg_send_end_of_axn(SuId suId, MgMgcoTransId* transId, MgMgcoContextId* ctxtId, TknU32* peerId);
 void mgco_print_sdp(CmSdpInfoSet *sdp);
 void mg_util_set_ctxt_string ( MgStr  *errTxt, MgMgcoContextId     *ctxtId);
-switch_status_t handle_mg_add_cmd(MgMgcoAmmReq *addReq);
+switch_status_t handle_mg_add_cmd(megaco_profile_t* mg_profile, MgMgcoCommand *addReq);
 switch_status_t mg_stack_free_mem(void* msg);
 switch_status_t mg_stack_alloc_mem( Ptr* _memPtr, Size _memSize );
 MgMgcoMediaDesc* get_default_media_desc(void);
@@ -144,6 +144,8 @@ void mg_util_set_txn_string(MgStr  *errTxt, U32 *txnId);
 switch_status_t mg_build_mgco_err_request(MgMgcoInd  **errcmd,U32  trans_id, MgMgcoContextId   *ctxt_id, U32  err, MgStr  *errTxt);
 switch_status_t mg_send_audit_rsp(SuId suId, MgMgcoCommand *req);
 switch_status_t handle_mg_audit_cmd(SuId suId, MgMgcoCommand *auditReq);
+switch_status_t mg_stack_termination_is_in_service(char* term_str, int len);
+void mg_util_set_cmd_name_string (MgStr *errTxt, MgMgcoCommand       *cmd);
 
 switch_status_t mg_send_modify_rsp(SuId suId, MgMgcoCommand *req);
 switch_status_t mg_send_subtract_rsp(SuId suId, MgMgcoCommand *req);
index ed70b741739914d4970b9ed57ea3268f28f1aa5f..e536fd83bf2b5d8782196b59f369791ee7f72df6 100644 (file)
@@ -78,6 +78,14 @@ switch_status_t mg_stack_free_mem(void* msg)
 }
 
 
+/*****************************************************************************************************************************/
+
+/* TODO - Matt - to see if term is in service or not */
+switch_status_t mg_stack_termination_is_in_service(char* term_str,int len)
+{
+        return SWITCH_STATUS_SUCCESS;
+}
+
 /*****************************************************************************************************************************/
 
 S16 mg_fill_mgco_termid ( MgMgcoTermId  *termId, char* term_str, int term_len, CmMemListCp   *memCp)
@@ -351,6 +359,55 @@ void mg_util_set_ctxt_string ( MgStr  *errTxt, MgMgcoContextId     *ctxtId)
                        "info, error-text is: %s\n", __PRETTY_FUNCTION__,errTxt->val);
 }
 
+/*****************************************************************************************************************************/
+
+void mg_util_set_cmd_name_string (MgStr *errTxt, MgMgcoCommand       *cmd)
+{
+       MG_ZERO((errTxt->val), sizeof(errTxt->val));
+       errTxt->len = 0;
+
+       if ((!cmd) && (!cmd->u.mgCmdInd[0])) {
+               switch(cmd->u.mgCmdInd[0]->cmd.type.val)
+               {
+                       case MGT_AUDITCAP:
+                               errTxt->val[0]='\"';
+                               errTxt->val[1]='A';
+                               errTxt->val[2]='u';
+                               errTxt->val[3]='d';
+                               errTxt->val[4]='i';
+                               errTxt->val[5]='t';
+                               errTxt->val[6]='C';
+                               errTxt->val[7]='a';
+                               errTxt->val[8]='p';
+                               errTxt->val[9]='a';
+                               errTxt->val[10]='b';
+                               errTxt->val[11]='i';
+                               errTxt->val[12]='l';
+                               errTxt->val[13]='i';
+                               errTxt->val[14]='t';
+                               errTxt->val[15]='y';
+                               errTxt->val[16]='\"';
+                               errTxt->len = 17;
+                               break;
+
+                       case MGT_MOVE:
+                               errTxt->val[0]='\"';
+                               errTxt->val[1]='M';
+                               errTxt->val[2]='o';
+                               errTxt->val[3]='v';
+                               errTxt->val[4]='e';
+                               errTxt->val[5]='\"';
+                               errTxt->len = 6;
+                               break;
+
+                       default:
+                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "%s: Not expected command Type[%d]\n",
+                                               __PRETTY_FUNCTION__,cmd->u.mgCmdInd[0]->cmd.type.val);
+
+                               break;
+               }
+       }
+}
 
 /*****************************************************************************************************************************/
 void mgco_print_sdp(CmSdpInfoSet *sdp)
index 7e4be231ca152c6997119180fd1b84b8ebd076b4..a6202295fd55f1b8bf5e30fac0f728fe4ff07c1b 100644 (file)
@@ -233,6 +233,9 @@ static switch_status_t mgco_parse_local_sdp(mg_termination_t *term, CmSdpInfoSet
 }
 #endif
 
+/* KAPIL- NOTE : We are using Command mode operation of MEGACO stack, so we will always get command indication instead of transaction */
+/* Below API is not useful ... just leaving as it is...*/
+
 void handle_mgco_txn_ind(Pst *pst, SuId suId, MgMgcoMsg* msg)
 {
     size_t txnIter;
@@ -425,8 +428,12 @@ void handle_mgco_cmd_ind(Pst *pst, SuId suId, MgMgcoCommand* cmd)
        MgMgcoInd  *mgErr;
        MgStr      errTxt;
        MgMgcoContextId   ctxtId;
+       MgMgcoContextId   *inc_context;
        MgMgcoTermIdLst*  termLst;
-
+       MgMgcoTermId     *termId;
+       int               count;
+       int               err_code;
+       megaco_profile_t* mg_profile;
 
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "%s: Received Command Type[%s] \n", __PRETTY_FUNCTION__, PRNT_MG_CMD_TYPE(cmd->cmdType.val));
 
@@ -442,15 +449,8 @@ void handle_mgco_cmd_ind(Pst *pst, SuId suId, MgMgcoCommand* cmd)
                ctxtId.val.pres  = NOTPRSNT;
 
                mg_util_set_txn_string(&errTxt, &txn_id);
-
-               if (SWITCH_STATUS_SUCCESS == mg_build_mgco_err_request(&mgErr, txn_id, &ctxtId,
-                                               MGT_MGCO_RSP_CODE_INVLD_IDENTIFIER, &errTxt)) {
-                       sng_mgco_send_err(suId, mgErr);
-               }
-
-               /* deallocate the msg */
-               mg_free_cmd(cmd);
-               return ;        
+               err_code = MGT_MGCO_RSP_CODE_INVLD_IDENTIFIER;
+               goto error;
        }
 
        /* Get the termination Id list from the command(Note: GCP_2_1 has termination list , else it will be termination Id)  */
@@ -458,12 +458,80 @@ void handle_mgco_cmd_ind(Pst *pst, SuId suId, MgMgcoCommand* cmd)
        if ((NULL == termLst) || (NOTPRSNT == termLst->num.pres)) {
                /* termination-id not present , error */
                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Termination-Id Not received..rejecting command \n");
-               mg_free_cmd(cmd);
-               return ;        
+
+               /*-- Send Error to MG Stack --*/
+               MG_ZERO(&ctxtId, sizeof(MgMgcoContextId));
+               ctxtId.type.pres = NOTPRSNT;
+               ctxtId.val.pres  = NOTPRSNT;
+               mg_util_set_txn_string(&errTxt, &txn_id);
+               err_code = MGT_MGCO_RSP_CODE_INVLD_IDENTIFIER;
+               goto error;
+       }
+
+       termId  = termLst->terms[0];
+
+       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Termination-Id received..value[%s] type[%d] \n", termId->name.lcl.val, termId->type.val);
+
+       /* Not sure - IF Stack fills term type properly..but adding code just to be sure ...*/
+       if ((PRSNT_NODEF == termId->type.pres) &&
+                       (MGT_TERMID_OTHER == termId->type.val)) {
+               /* Checking the $ in the pathname    */
+               if ((PRSNT_NODEF == termId->name.pres.pres) &&
+                               (PRSNT_NODEF == termId->name.lcl.pres)) {
+                       for (count = 0; count < termId->name.lcl.len; count++) {
+                               if (termId->name.lcl.val[count] == '$') {
+                                       termId->type.val = MGT_TERMID_CHOOSE;
+                                       break;
+                               }
+
+                               if (termId->name.lcl.val[count] == '*') {
+                                       termId->type.val = MGT_TERMID_ALL;
+                                       break;
+                               }
+                       }
+               }
        }
 
+       /*If term type is other then check if that term is configured with us..for term type CHOOSE/ALL , no need to check */
+       if (MGT_TERMID_OTHER == termId->type.val){
+               if(SWITCH_STATUS_FALSE != mg_stack_termination_is_in_service((char*)termId->name.lcl.val, termId->name.lcl.len)){
+                       mg_util_set_term_string(&errTxt, termId);
+                       err_code = MGT_MGCO_RSP_CODE_UNKNOWN_TERM_ID;
+                       goto error;
+               }
+       }
+
+
+       /* Validate Context - if context is specified then check if its present with us */
+       inc_context = &cmd->contextId;
+       MG_ZERO(&ctxtId, sizeof(MgMgcoContextId));
+       memcpy(&ctxtId, inc_context, sizeof(MgMgcoContextId));
+
+       if(NOTPRSNT == inc_context->type.pres){
+               goto ctxt_error;
+
+       }else if(MGT_CXTID_OTHER == inc_context->type.pres){
+
+               if(NOTPRSNT != inc_context->val.pres){
+                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO,"Context specific request for contextId[%d]\n",inc_context->val.val);
+                       /* check if context present with us */
+                       if(NULL == megaco_find_context_by_suid(suId, inc_context->val.val)){
+                               goto ctxt_error;
+                       }               
+               }else{
+                       /* context id value not present - in case of type OTHER we should have context value */
+                       goto ctxt_error;
+               }
+       }
+       
+
        /*mgAccEvntPrntMgMgcoCommand(cmd, stdout);*/
 
+       /*get mg profile associated with SuId */
+       if(NULL == (mg_profile = megaco_get_profile_by_suId(suId))){
+               goto error1;
+       }
+
        switch(cmd->cmdType.val)
        {
                case CH_CMD_TYPE_IND:
@@ -475,7 +543,7 @@ void handle_mgco_cmd_ind(Pst *pst, SuId suId, MgMgcoCommand* cmd)
                                {
                                        case MGT_ADD:
                                                {
-                                                       handle_mg_add_cmd(&cmd->u.mgCmdInd[0]->cmd.u.add);
+                                                       handle_mg_add_cmd(mg_profile, cmd);
                                                        mg_send_add_rsp(suId, cmd);
                                                        break;
                                                }
@@ -488,9 +556,10 @@ void handle_mgco_cmd_ind(Pst *pst, SuId suId, MgMgcoCommand* cmd)
                                                }
                                        case MGT_MOVE:
                                                {
-                                                       /*MgMgcoAmmReq *addReq = &cmdReq->cmd.u.move;*/
-                                                       break;
-
+                                                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "MOVE Method Not Yet Supported\n");
+                                                       err_code = MGT_MGCO_RSP_CODE_UNSUPPORTED_CMD;
+                                                       mg_util_set_cmd_name_string(&errTxt, cmd);
+                                                       goto error;
                                                }
                                        case MGT_SUB:
                                                {
@@ -511,7 +580,9 @@ void handle_mgco_cmd_ind(Pst *pst, SuId suId, MgMgcoCommand* cmd)
                                        case MGT_AUDITCAP:
                                                {
                                                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Audit-Capability Method Not Yet Supported\n");
-                                                       break;
+                                                       err_code = MGT_MGCO_RSP_CODE_UNSUPPORTED_CMD;
+                                                       mg_util_set_cmd_name_string(&errTxt, cmd);
+                                                       goto error;
                                                }
                                        case MGT_AUDITVAL:
                                                {
@@ -542,6 +613,18 @@ void handle_mgco_cmd_ind(Pst *pst, SuId suId, MgMgcoCommand* cmd)
        }
 
        return;
+
+ctxt_error:
+       err_code = MGT_MGCO_RSP_CODE_UNKNOWN_CTXT;
+
+error:
+       if (SWITCH_STATUS_SUCCESS == 
+                       mg_build_mgco_err_request(&mgErr, txn_id, &ctxtId, err_code, &errTxt)) {
+               sng_mgco_send_err(suId, mgErr);
+       }
+error1:
+       mg_free_cmd(cmd);
+       return;
 }
 
 /*****************************************************************************************************************************/
index 91dc74210c1d5a620dd4f912dafe505267adc495..f1da14a4f296f70701fb0f0149a5e04df98c361b 100644 (file)
@@ -139,6 +139,9 @@ mg_context_t *megaco_get_context(megaco_profile_t *profile, uint32_t context_id)
 mg_context_t *megaco_choose_context(megaco_profile_t *profile);
 void megaco_release_context(mg_context_t *ctx);
 
+megaco_profile_t*  megaco_get_profile_by_suId(SuId suId);
+mg_context_t *megaco_find_context_by_suid(SuId suId, uint32_t context_id);
+
 switch_status_t config_profile(megaco_profile_t *profile, switch_bool_t reload);
 switch_status_t sng_mgco_start(megaco_profile_t* profile);
 switch_status_t sng_mgco_stop(megaco_profile_t* profile);