/* * Copyright (c) 2012, Sangoma Technologies * Kapil Gupta * All rights reserved. * * */ /* INCLUDES *******************************************************************/ #include "mod_megaco.h" #include "megaco_stack.h" /******************************************************************************/ /* FUNCTION PROTOTYPES ********************************************************/ switch_status_t megaco_profile_status(switch_stream_handle_t *stream, megaco_profile_t* mg_cfg); switch_status_t megaco_profile_xmlstatus(switch_stream_handle_t *stream, megaco_profile_t* mg_cfg); switch_status_t megaco_profile_peer_xmlstatus(switch_stream_handle_t *stream, megaco_profile_t* mg_cfg); void get_peer_xml_buffer(char* prntBuf, MgPeerSta* cfm); /******************************************************************************/ /* FUNCTIONS ******************************************************************/ switch_status_t mg_process_cli_cmd(const char *cmd, switch_stream_handle_t *stream) { int argc; char* argv[10]; char* dup = NULL; megaco_profile_t* profile = NULL; if (zstr(cmd)) { goto usage; } dup = strdup(cmd); argc = switch_split(dup, ' ', argv); if (argc < 1 || zstr(argv[0])) { goto usage; } /**********************************************************************************/ if (!strcmp(argv[0], "profile")) { if (zstr(argv[1]) || zstr(argv[2])) { goto usage; } /**********************************************************************************/ profile = megaco_profile_locate(argv[1]); /**********************************************************************************/ if (!strcmp(argv[2], "start")) { /**********************************************************************************/ if (profile) { megaco_profile_release(profile); stream->write_function(stream, "-ERR Profile %s is already started\n", argv[2]); } else { megaco_profile_start(argv[1]); stream->write_function(stream, "+OK\n"); } /**********************************************************************************/ } else if (!strcmp(argv[2], "stop")) { /**********************************************************************************/ if (profile) { megaco_profile_release(profile); megaco_profile_destroy(&profile); stream->write_function(stream, "+OK\n"); } else { stream->write_function(stream, "-ERR No such profile\n"); } /**********************************************************************************/ }else if(!strcmp(argv[2], "status")) { /**********************************************************************************/ if (profile) { megaco_profile_release(profile); megaco_profile_status(stream, profile); } else { stream->write_function(stream, "-ERR No such profile\n"); } /**********************************************************************************/ }else if(!strcmp(argv[2], "xmlstatus")) { /**********************************************************************************/ if (profile) { megaco_profile_release(profile); megaco_profile_xmlstatus(stream, profile); } else { stream->write_function(stream, "-ERR No such profile\n"); } /**********************************************************************************/ }else if(!strcmp(argv[2], "peerxmlstatus")) { /**********************************************************************************/ if (profile) { megaco_profile_release(profile); megaco_profile_peer_xmlstatus(stream, profile); } else { stream->write_function(stream, "-ERR No such profile\n"); } /**********************************************************************************/ }else { /**********************************************************************************/ goto usage; } } goto done; usage: stream->write_function(stream, "-ERR Usage: "MEGACO_FUNCTION_SYNTAX"\n"); done: switch_safe_free(dup); return SWITCH_STATUS_SUCCESS; } /******************************************************************************/ switch_status_t megaco_profile_peer_xmlstatus(switch_stream_handle_t *stream, megaco_profile_t* mg_cfg) { int idx = 0x00; int len = 0x00; MgMngmt cfm; char* xmlhdr = ""; char prntBuf[3048]; int i = 0x00; char *asciiAddr; CmInetIpAddr ip; mg_peer_profile_t* mg_peer = NULL; switch_assert(mg_cfg); memset((U8 *)&cfm, 0, sizeof(cfm)); memset((char *)&prntBuf, 0, sizeof(prntBuf)); mg_peer = megaco_peer_profile_locate(mg_cfg->peer_list[0]); if(!mg_peer){ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR," No MG peer configuration found for peername[%s] against profilename[%s]\n",mg_cfg->peer_list[0],mg_cfg->name); return SWITCH_STATUS_FALSE; } idx = mg_cfg->idx; len = len + sprintf(&prntBuf[0] + len,"%s\n",xmlhdr); len = len + sprintf(&prntBuf[0] + len,"\n"); len = len + sprintf(&prntBuf[0] + len,"%s\n",mg_cfg->peer_list[0]); /* TODO - as of now supporting only one peer .. need to add logic to iterate through all the peers associated with this profile..*/ /* send request to MEGACO Trillium stack to get peer information*/ sng_mgco_mg_get_status(STGCPENT, &cfm, mg_cfg, mg_peer); ip = ntohl(cfm.t.ssta.s.mgPeerSta.peerAddrTbl.netAddr[i].u.ipv4NetAddr); cmInetNtoa(ip, &asciiAddr); len = len + sprintf(prntBuf+len, "%s\n",asciiAddr); len = len + sprintf(prntBuf+len, "%s\n",PRNT_MG_PEER_STATE(cfm.t.ssta.s.mgPeerSta.peerState)); len = len + sprintf(&prntBuf[0] + len,"\n"); stream->write_function(stream, "\n%s\n",&prntBuf[0]); return SWITCH_STATUS_SUCCESS; } /******************************************************************************/ switch_status_t megaco_profile_xmlstatus(switch_stream_handle_t *stream, megaco_profile_t* mg_cfg) { int idx = 0x00; int len = 0x00; MgMngmt cfm; char* xmlhdr = ""; char prntBuf[3048]; int i = 0x00; char *asciiAddr; CmInetIpAddr ip; mg_peer_profile_t* mg_peer = NULL; switch_assert(mg_cfg); memset((U8 *)&cfm, 0, sizeof(cfm)); memset((char *)&prntBuf, 0, sizeof(prntBuf)); mg_peer = megaco_peer_profile_locate(mg_cfg->peer_list[0]); if(!mg_peer){ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR," No MG peer configuration found for peername[%s] against profilename[%s]\n",mg_cfg->peer_list[0],mg_cfg->name); return SWITCH_STATUS_FALSE; } idx = mg_cfg->idx; len = len + sprintf(&prntBuf[0] + len,"%s\n",xmlhdr); len = len + sprintf(&prntBuf[0] + len,"\n"); len = len + sprintf(&prntBuf[0] + len,"%s\n",mg_cfg->name); /****************************************************************************************************************/ /* Print Peer Information ***************************************************************************************/ /* TODO - as of now supporting only one peer .. need to add logic to iterate through all the peers associated with this profile..*/ len = len + sprintf(&prntBuf[0] + len,"\n"); len = len + sprintf(&prntBuf[0] + len,"\n",mg_peer->name); /* send request to MEGACO Trillium stack to get peer information*/ sng_mgco_mg_get_status(STGCPENT, &cfm, mg_cfg, mg_peer); get_peer_xml_buffer(&prntBuf[0] + len, &cfm.t.ssta.s.mgPeerSta); len = len + sprintf(&prntBuf[0] + len,"\n"); len = len + sprintf(&prntBuf[0] + len,"\n"); /****************************************************************************************************************/ /* Print MG SAP Information ***************************************************************************************/ len = len + sprintf(&prntBuf[0] + len,"\n"); /* MG SAP Information */ sng_mgco_mg_get_status(STSSAP, &cfm, mg_cfg, mg_peer); len = len + sprintf(prntBuf+len, " %s \n", PRNT_SAP_STATE((int)(cfm.t.ssta.s.mgSSAPSta.state))); len = len + sprintf(prntBuf+len, " %u \n", (unsigned int)(cfm.t.ssta.s.mgSSAPSta.numAssocPeer)); len = len + sprintf(prntBuf+len, " %u \n", (unsigned int)(cfm.t.ssta.s.mgSSAPSta.numServers)); len = len + sprintf(&prntBuf[0] + len,"\n"); for (i = 0; i < cfm.t.ssta.s.mgSSAPSta.numAssocPeer; i++) { len = len + sprintf(&prntBuf[0] + len,"\n"); if(cfm.t.ssta.s.mgSSAPSta.peerInfo[i].dname.namePres.pres == PRSNT_NODEF) { len = len + sprintf(prntBuf+len, " %s \n", (char *)(cfm.t.ssta.s.mgSSAPSta.peerInfo[i].dname.name)); } switch(cfm.t.ssta.s.mgSSAPSta.peerInfo[i].dname.netAddr.type) { case CM_NETADDR_IPV4: { ip = ntohl(cfm.t.ssta.s.mgSSAPSta.peerInfo[i].dname.netAddr.u.ipv4NetAddr); cmInetNtoa(ip, &asciiAddr); len = len + sprintf(prntBuf+len, "%s\n",asciiAddr); break; } default: len = len + sprintf(prntBuf+len, "invalid type \n"); break; } #ifdef GCP_MGCO if (PRSNT_NODEF == cfm.t.ssta.s.mgSSAPSta.peerInfo[i].mid.pres) { len = len + sprintf(prntBuf+len, " %s \n", (char *)(cfm.t.ssta.s.mgSSAPSta.peerInfo[i].mid.val)); } #endif /* GCP_MGCO */ len = len + sprintf(&prntBuf[0] + len,"\n"); } len = len + sprintf(&prntBuf[0] + len,"\n"); len = len + sprintf(&prntBuf[0] + len,"\n"); /****************************************************************************************************************/ /* Print MG Transport SAP Information ***************************************************************************************/ len = len + sprintf(&prntBuf[0] + len,"\n"); /* MG Transport SAP Information */ sng_mgco_mg_get_status(STTSAP, &cfm, mg_cfg, mg_peer); len = len + sprintf(&prntBuf[0] + len," %s \n", PRNT_SAP_STATE(cfm.t.ssta.s.mgTSAPSta.state)); len = len + sprintf(&prntBuf[0] + len," %u \n", (unsigned int)(cfm.t.ssta.s.mgTSAPSta.numServers)); len = len + sprintf(&prntBuf[0] + len,"\n"); /****************************************************************************************************************/ /* Print MG Transport Server Information ***************************************************************************************/ if(sng_mgco_mg_get_status(STSERVER, &cfm, mg_cfg, mg_peer)){ len = len + sprintf(&prntBuf[0] + len," no established server found \n"); } else { len = len + sprintf(&prntBuf[0] + len,"\n"); len = len + sprintf(&prntBuf[0] + len," %s \n", PRNT_SAP_STATE(cfm.t.ssta.s.mgTptSrvSta.state)); len = len + sprintf(prntBuf+len, ""); switch (cfm.t.ssta.s.mgTptSrvSta.tptAddr.type) { case CM_TPTADDR_NOTPRSNT: { len = len + sprintf(prntBuf+len, "none"); break; } case CM_TPTADDR_IPV4: { ip = ntohl(cfm.t.ssta.s.mgTptSrvSta.tptAddr.u.ipv4TptAddr.address); cmInetNtoa(ip, &asciiAddr); len = len + sprintf(prntBuf+len, "IPv4 IP address #%s, port %u",asciiAddr, (unsigned int)(cfm.t.ssta.s.mgTptSrvSta.tptAddr.u.ipv4TptAddr.port)); break; } default: len = len + sprintf(prntBuf+len, "unknown"); break; } len = len + sprintf(prntBuf+len, "\n"); len = len + sprintf(&prntBuf[0] + len,"\n"); } /****************************************************************************************************************/ len = len + sprintf(&prntBuf[0] + len,"\n"); stream->write_function(stream, "\n%s\n",&prntBuf[0]); return SWITCH_STATUS_SUCCESS; } /****************************************************************************************************************/ switch_status_t megaco_profile_status(switch_stream_handle_t *stream, megaco_profile_t* mg_cfg) { int idx = 0x00; int len = 0x00; MgMngmt cfm; char prntBuf[1024]; mg_peer_profile_t* mg_peer = NULL; switch_assert(mg_cfg); memset((U8 *)&cfm, 0, sizeof(cfm)); memset((char *)&prntBuf, 0, sizeof(prntBuf)); mg_peer = megaco_peer_profile_locate(mg_cfg->peer_list[0]); if(!mg_peer){ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR," No MG peer configuration found for peername[%s] against profilename[%s]\n",mg_cfg->peer_list[0],mg_cfg->name); return SWITCH_STATUS_FALSE; } idx = mg_cfg->idx; /*stream->write_function(stream, "Collecting MG Profile[%s] status... \n",profilename);*/ /* Fetch data from Trillium MEGACO Stack * * SystemId - Software version information * * SSAP - MG SAP Information * * TSAP - MG Transport SAP Information * * Peer - MG Peer Information * * TPT-Server - MG Transport Server information * */ #if 0 /* get System ID */ sng_mgco_mg_get_status(STSID, &cfm, idx); stream->write_function(stream, "***********************************************\n"); stream->write_function(stream, "**** TRILLIUM MEGACO Software Information *****\n"); stream->write_function(stream, "Version = %d \n", cfm.t.ssta.s.systemId.mVer); stream->write_function(stream, "Version Revision = %d \n", cfm.t.ssta.s.systemId.mRev); stream->write_function(stream, "Branch Version = %d \n", cfm.t.ssta.s.systemId.bVer); stream->write_function(stream, "Branch Revision = %d \n", cfm.t.ssta.s.systemId.bRev); stream->write_function(stream, "Part Number = %d \n", cfm.t.ssta.s.systemId.ptNmb); stream->write_function(stream, "***********************************************\n"); #endif /* MG Peer Information */ sng_mgco_mg_get_status(STGCPENT, &cfm, mg_cfg, mg_peer); smmgPrntPeerSta(&cfm.t.ssta.s.mgPeerSta); /* MG Peer Information */ sng_mgco_mg_get_status(STSSAP, &cfm, mg_cfg, mg_peer); smmgPrntSsapSta(&cfm.t.ssta.s.mgSSAPSta); /* MG Transport SAP Information */ sng_mgco_mg_get_status(STTSAP, &cfm, mg_cfg, mg_peer); len = len + sprintf(prntBuf+len,"***********************************************\n"); len = len + sprintf(prntBuf+len,"**********MG TRANSPORT SAP Information**********\n"); len = len + sprintf(prntBuf+len,"TSAP status:\n"); len = len + sprintf(prntBuf+len,"state = %d, number of listeners %u\n", (int)(cfm.t.ssta.s.mgTSAPSta.state), (unsigned int)(cfm.t.ssta.s.mgTSAPSta.numServers)); len = len + sprintf(prntBuf+len,"***********************************************\n"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO,"%s\n",prntBuf); /* MG Transport Server Information */ sng_mgco_mg_get_status(STSERVER, &cfm, mg_cfg, mg_peer); smmgPrntSrvSta(&cfm.t.ssta.s.mgTptSrvSta); return SWITCH_STATUS_SUCCESS; } /******************************************************************************/ void get_peer_xml_buffer(char* prntBuf, MgPeerSta* cfm) { int len = 0x00; int i = 0x00; char *asciiAddr; CmInetIpAddr ip; if(PRSNT_NODEF == cfm->namePres.pres) { len = len + sprintf(prntBuf+len, " %s \n", (char *)(cfm->name)); } else { len = len + sprintf(prntBuf+len, " Not Present \n"); } /* * Print all IP addresses in the IP addr table */ for(i=0; ipeerAddrTbl.count; i++) { switch (cfm->peerAddrTbl.netAddr[i].type) { case CM_NETADDR_IPV4: { ip = ntohl(cfm->peerAddrTbl.netAddr[i].u.ipv4NetAddr); cmInetNtoa(ip, &asciiAddr); len = len + sprintf(prntBuf+len, "%s\n",asciiAddr); break; } case CM_NETADDR_IPV6: { char ipv6_buf[128]; int len1= 0; int j = 0; memset(&ipv6_buf[0], 0, sizeof(ipv6_buf)); len1 = len1 + sprintf(ipv6_buf+len1, "IP V6 address : %2x", (unsigned int) (cfm->peerAddrTbl.netAddr[i].u.ipv6NetAddr[0])); for (j = 1; j < CM_IPV6ADDR_SIZE; j++) { len1 = len1 + sprintf(ipv6_buf+len1, ":%2x", (unsigned int) (cfm->peerAddrTbl.netAddr[i].u.ipv6NetAddr[j])); } len1 = len1 + sprintf(ipv6_buf+len1, "\n"); len = len + sprintf(prntBuf+len, "%s\n", ipv6_buf); break; } default: { len = len + sprintf(prntBuf+len, " Invalid address type[%d]\n", cfm->peerAddrTbl.netAddr[i].type); break; } } } /* End of for */ len = len + sprintf(prntBuf+len," %lu \n",(unsigned long)(cfm->numPendOgTxn)); len = len + sprintf(prntBuf+len," %lu \n",(unsigned long)(cfm->numPendIcTxn)); len = len + sprintf(prntBuf+len," %lu \n",(unsigned long)(cfm->rttEstimate)); switch(cfm->protocol) { case LMG_PROTOCOL_MGCP: len = len + sprintf(prntBuf+len," MGCP \n"); break; case LMG_PROTOCOL_MGCO: len = len + sprintf(prntBuf+len," MEGACO \n"); break; case LMG_PROTOCOL_NONE: len = len + sprintf(prntBuf+len," MGCP/MEGACO \n"); break; default: len = len + sprintf(prntBuf+len," invalid \n"); break; } switch(cfm->transportType) { case LMG_TPT_UDP: len = len + sprintf(prntBuf+len, "UDP\n"); break; case LMG_TPT_TCP: len = len + sprintf(prntBuf+len, "TCP\n"); break; case LMG_TPT_NONE: len = len + sprintf(prntBuf+len, "UDP/TCP\n"); break; default: len = len + sprintf(prntBuf+len, "invalid\n"); break; } #ifdef GCP_MGCO switch(cfm->encodingScheme) { case LMG_ENCODE_BIN: len = len + sprintf(prntBuf+len, "BINARY\n"); break; case LMG_ENCODE_TXT: len = len + sprintf(prntBuf+len, "TEXT\n"); break; case LMG_ENCODE_NONE: len = len + sprintf(prntBuf+len, "TEXT/BINARY\n"); break; default: len = len + sprintf(prntBuf+len, "invalid\n"); break; } if(LMG_VER_PROF_MGCO_H248_1_0 == cfm->version){ len = len + sprintf(prntBuf+len, "1.0 \n"); } else if(LMG_VER_PROF_MGCO_H248_2_0 == cfm->version){ len = len + sprintf(prntBuf+len, "2.0 \n"); }else if(LMG_VER_PROF_MGCO_H248_3_0 == cfm->version){ len = len + sprintf(prntBuf+len, "3.0 \n"); } else{ len = len + sprintf(prntBuf+len, "invalid \n"); } #endif } /******************************************************************************/