| /* |
| * |
| * Copyright (C) 2007 Mindspeed Technologies, Inc. |
| * |
| * This program 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. |
| * |
| * This program 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| */ |
| |
| #include <signal.h> |
| #include <sys/types.h> |
| #include <sys/ipc.h> |
| #include <sys/msg.h> |
| |
| #include "cmm.h" |
| #include "libcmm.h" |
| #include "fpp.h" |
| #include "cmmd.h" |
| #include "voicebuf.h" |
| |
| int dumpmem(int argc, char *argv[]); |
| |
| #ifndef caseretstr |
| #define caseretstr(x) case x: return #x |
| #endif |
| |
| char * getErrorString(unsigned short error) |
| { |
| switch (error) |
| { |
| /* common errors */ |
| caseretstr(FPP_ERR_UNKNOWN_COMMAND); |
| caseretstr(FPP_ERR_WRONG_COMMAND_SIZE); |
| caseretstr(FPP_ERR_WRONG_COMMAND_PARAM); |
| caseretstr(FPP_ERR_UNKNOWN_ACTION); |
| |
| caseretstr(FPP_ERR_CT_ENTRY_ALREADY_REGISTERED); |
| caseretstr(FPP_ERR_CT_ENTRY_NOT_FOUND); |
| |
| caseretstr(FPP_ERR_RT_ENTRY_ALREADY_REGISTERED); |
| caseretstr(FPP_ERR_RT_ENTRY_NOT_FOUND); |
| |
| caseretstr(FPP_ERR_VLAN_ENTRY_ALREADY_REGISTERED); |
| caseretstr(FPP_ERR_VLAN_ENTRY_NOT_FOUND); |
| |
| caseretstr(FPP_ERR_PPPOE_ENTRY_ALREADY_REGISTERED); |
| caseretstr(FPP_ERR_PPPOE_ENTRY_NOT_FOUND); |
| |
| caseretstr(FPP_ERR_TNL_ENTRY_NOT_FOUND); |
| caseretstr(FPP_ERR_SA_ENTRY_NOT_FOUND); |
| caseretstr(FPP_ERR_MC_ENTRY_NOT_FOUND); |
| |
| /* rtp stats errors */ |
| caseretstr(FPP_ERR_SOCK_ALREADY_OPEN); |
| caseretstr(FPP_ERR_SOCKID_ALREADY_USED); |
| caseretstr(FPP_ERR_SOCK_ALREADY_OPENED_WITH_OTHER_ID); |
| caseretstr(FPP_ERR_TOO_MANY_SOCKET_OPEN); |
| caseretstr(FPP_ERR_SOCKID_UNKNOWN); |
| caseretstr(FPP_ERR_SOCK_ALREADY_IN_USE); |
| caseretstr(FPP_ERR_RTP_CALLID_IN_USE); |
| caseretstr(FPP_ERR_RTP_UNKNOWN_CALL); |
| caseretstr(FPP_ERR_WRONG_SOCKID); |
| caseretstr(FPP_ERR_RTP_SPECIAL_PKT_LEN); |
| caseretstr(FPP_ERR_RTP_CALL_TABLE_FULL); |
| caseretstr(FPP_ERR_WRONG_SOCK_FAMILY); |
| caseretstr(FPP_ERR_WRONG_SOCK_PROTO); |
| caseretstr(FPP_ERR_WRONG_SOCK_TYPE); |
| |
| /* rtp stats errors */ |
| caseretstr(FPP_ERR_RTP_STATS_MAX_ENTRIES); |
| caseretstr(FPP_ERR_RTP_STATS_STREAMID_ALREADY_USED); |
| caseretstr(FPP_ERR_RTP_STATS_STREAMID_UNKNOWN); |
| caseretstr(FPP_ERR_RTP_STATS_DUPLICATED); |
| caseretstr(FPP_ERR_RTP_STATS_WRONG_DTMF_PT); |
| caseretstr(FPP_ERR_RTP_STATS_WRONG_TYPE); |
| |
| default: |
| return (char *) "Unknown error code"; |
| } |
| } |
| |
| |
| /***************************************************************** |
| * cmmClientPrintHelp() |
| * |
| * Print command syntax |
| * |
| *****************************************************************/ |
| void cmmClientPrintHelp() |
| { |
| |
| /* |
| * The commands syntax must be: |
| * <set / show> <module name> <option1> <value1> <option2> <value2> .... |
| */ |
| |
| cmm_print(DEBUG_STDOUT, "Command usage: set <module_name> [option ...]\n" |
| "\trx: Manage RX module (ICC, Bridging ...)\n" |
| "\tqm: Manage QM module (QOS, Rate Limiting ...)\n" |
| "\tmc6: Manage IPv6 Multicast module\n" |
| "\tmc4: Manage IPv4 Multicast module\n" |
| "\tstat: Manage Statistics module\n" |
| "\troute: Manage Extended Route module\n" |
| "\tconfig: Manage Alternate Configurations\n" |
| "\tsocket: Manage Socket module\n" |
| "\tsocket6: Manage V6 socket module\n" |
| "\trtp: Manage RTP Relay module\n" |
| "\tnatpt: Manage NAT-PT module\n" |
| "\tsa_query_timer: Manage IPsec SA query timer module\n" |
| #ifdef C2000_DPI |
| "\tdpi: Manage DPI Enable/disable\n" |
| #endif |
| "\tasym_fastforward: Manage Asymmetric Fastforward Enable/disable\n" |
| "\trtpstats: Manage RTP Stats for Fast Forwarded connections\n" |
| "\tbridge: Manage bridge (timeout)\n" |
| "\ttimeout: set timeout for udp/tc flows\n" |
| "\texpt_queue: manage queue configurations\n" |
| "\tff: manage fast forwarding control\n" |
| "\tipsec: manage ipsec configurations\n" |
| "\tvoicebuf: manage voicebuf control \n" |
| "\tfrag: manage ipv4/ipv6 fragmentation configurations\n" |
| "\t4rd-id-conversion: Enable/ Disable IPv4 header Identification conversion,\n" |
| "\t\tfor 4rd interfaces\n"); |
| cmm_print(DEBUG_STDOUT, "\nCommand usage: show <module_name> [option ...]\n" |
| "\trx: show RX module (ICC, Bridging ...)\n" |
| "\tqm: show QM module (QOS, Rate Limiting ...)\n" |
| "\tmc6: show IPv6 Multicast module\n" |
| "\tmc4: show IPv4 Multicast module\n" |
| "\tstat: show Statistics module\n" |
| "\troute: show Extended Route module\n" |
| "\tsocket: show Socket module\n" |
| "\tsocket6: show V6 socket module\n"); |
| cmm_print(DEBUG_STDOUT, "\nCommand usage: query < module_name> \n" |
| "\trx: Receive (bridge)\n" |
| "\tvlan: VLAN devices\n" |
| "\tpppoe: PPPoE Sessions\n" |
| "\tsa: SA Entries\n" |
| "\tmc6: IPv6 Multicast Entries\n" |
| "\tmc4: IPv4 Multicast Entries\n" |
| "\tqm: QOS information\n" |
| "\tqmexptrate: Exception Rate\n" |
| "\tconnections: IPV4 connections\n" |
| "\troute: IP routes\n" |
| "\tv6connections: IPV6 Connections\n" |
| "\tsocket: IPV4 sockets\n" |
| "\trtcp: RTP relay statistics\n" |
| "\trtpstats: RTP statistics for Fast Forwarded connections\n" |
| "\tnatpt: NAT-PT Entries\n" |
| "\tl2flows: L2 and L3-4 flows Entries\n" |
| "\tmacvlan: Mac-vlan interfaces\n" |
| "\ttunnels: tunnel interfaces\n"); |
| |
| cmm_print(DEBUG_STDOUT, "\nCommand usage: { msp | dm | prf | tunnel | relay | vlan | pktcapture | icc | ipv4 |ipv6 } <options> \n"); |
| |
| } |
| |
| /***************************************************************** |
| * cmmSendToDaemon() |
| * |
| * This function sends a message to cmm daemon |
| * and waits for the answer. |
| * |
| *****************************************************************/ |
| int cmmSendToDaemon(daemon_handle_t handle, unsigned short commandCode, void * dataToSend, int dataSize, void* dataToRcv) |
| { |
| int rcvBytes = 0; |
| #ifdef NEW_IPC |
| cmm_command_t cmd; |
| cmm_response_t res; |
| |
| cmd.func = commandCode; |
| cmd.length = dataSize; |
| memcpy(cmd.buf, dataToSend, dataSize); |
| |
| if(cmm_send(handle, &cmd, 0) < 0) |
| { |
| cmm_print(DEBUG_STDERR, "%s: cmm_send failed, %s\n", __func__, strerror(errno)); |
| return -1; |
| } |
| |
| rcvBytes = cmm_recv(handle, &res, 0); |
| if (rcvBytes < 0) |
| { |
| cmm_print(DEBUG_STDERR, "%s: cmm_recv failed, %s\n", __func__, strerror(errno)); |
| return rcvBytes; |
| } |
| |
| if (dataToRcv) { |
| /* XXX: to have same output as with old IPC, |
| * this should be refactored |
| */ |
| memcpy(dataToRcv, res.buf, res.length); |
| } |
| |
| rcvBytes = res.length; |
| #else |
| int queueIdRx; |
| int queueIdTx; |
| struct cmm_msg msg; |
| key_t key; |
| |
| handle = ((handle & 0xff) ^ ((handle >> 8) & 0xff)) | 1; |
| |
| key = ftok("/tmp", handle); |
| if (key == (key_t)-1) |
| { |
| cmm_print(DEBUG_STDERR, "%s: ftok(%d) failed, %s\n", __func__, handle, strerror(errno)); |
| return -1; |
| } |
| |
| queueIdRx = msgget(key, 0); |
| if (queueIdRx < 0) |
| { |
| cmm_print(DEBUG_STDERR, "%s: rx msgget() failed, %s\n", __func__, strerror(errno)); |
| return -1; |
| } |
| |
| key = ftok("/tmp", handle ^ 0xff); |
| if (key == (key_t)-1) |
| { |
| cmm_print(DEBUG_STDERR, "%s: ftok(%d) failed, %s\n", __func__, handle ^ 0xff, strerror(errno)); |
| return -1; |
| } |
| |
| queueIdTx = msgget(key, 0); |
| if (queueIdTx < 0) |
| { |
| cmm_print(DEBUG_STDERR, "%s: tx msgget() failed, %s\n", __func__, strerror(errno)); |
| return -1; |
| } |
| |
| if (dataSize > sizeof(msg.buffer)) |
| return -1; |
| |
| msg.mtype = commandCode; |
| if (dataToSend) |
| memcpy(msg.buffer, dataToSend, dataSize); |
| |
| #if 0 |
| if ((globalConf.debug_level & DEBUG_INFO) || (globalConf.log_level & DEBUG_INFO)) |
| { |
| int rcvDataSize; |
| cmm_print(DEBUG_INFO, "commandCode: (%04x) \n", (unsigned int)msg.mtype); |
| for(rcvDataSize = 0; rcvDataSize < dataSize; rcvDataSize+=2) |
| { |
| cmm_print(DEBUG_INFO, "%02x%02x \n", msg.buffer[rcvDataSize + 1], msg.buffer[rcvDataSize]); |
| } |
| cmm_print(DEBUG_INFO, "\n"); |
| } |
| #endif |
| |
| if (msgsnd(queueIdTx, &msg, dataSize, 0) < 0) |
| { |
| cmm_print(DEBUG_STDERR, "%s: msgsnd() failed, %s\n", __func__, strerror(errno)); |
| return -1; |
| } |
| |
| // Now wait for an answer |
| if ((rcvBytes = msgrcv(queueIdRx, &msg, sizeof(msg.buffer), commandCode, 0)) < 0) |
| { |
| // Error !! |
| cmm_print(DEBUG_STDERR, "%s: msgrcv() failed, %s\n", __func__, strerror(errno)); |
| return -1; |
| } |
| |
| #if 0 |
| if ((globalConf.debug_level & DEBUG_INFO) || (globalConf.log_level & DEBUG_INFO)) |
| { |
| int rcvDataSize; |
| cmm_print(DEBUG_INFO, "commandAck: (%04x) \n", (unsigned int)msg.mtype); |
| for(rcvDataSize = 0; rcvDataSize < rcvBytes ; rcvDataSize += 2) |
| { |
| cmm_print(DEBUG_INFO, "%04x \n", ((unsigned short *)msg.buffer)[rcvDataSize]); |
| } |
| cmm_print(DEBUG_INFO, "\n"); |
| } |
| #endif |
| |
| if ((dataToRcv) && (rcvBytes)) |
| memcpy(dataToRcv, msg.buffer, rcvBytes); |
| #endif |
| return (rcvBytes ); |
| } |
| |
| |
| /***************************************************************** |
| * cmmClientCommandParser() |
| * |
| * cmm client command parser |
| * |
| *****************************************************************/ |
| int cmmClientProcessCmd(char * command, int argc, char ** argv, daemon_handle_t daemon_handle) |
| { |
| char * keywords[128]; /*We allow up to 256 keywords*/ |
| int cpt,i; |
| char *saveptr, *strl = NULL; |
| if ((command == NULL) && (argc == 0)) |
| goto help; |
| /* |
| * First split the string to get |
| * each keywords in a separate buffer |
| */ |
| if (command ) { |
| for (cpt = 0, strl = command; cpt < 128 ; cpt++, strl = NULL) |
| { |
| keywords[cpt] = strtok_r(strl, " ", &saveptr); |
| if(keywords[cpt] == NULL) |
| break; |
| } |
| } else { |
| cpt = 0; |
| } |
| for(i=0; (i < argc) && (cpt < 128); i++) { |
| keywords[cpt] = argv[i]; |
| cpt++; |
| } |
| if (cpt < 128) |
| keywords[cpt] = NULL; |
| // We nead at least 2 keywords to perform the parsing |
| if(cpt < 1) |
| goto help; |
| |
| /* |
| * Check if first keyword is correct |
| */ |
| if(strcasecmp(keywords[0], "set")== 0) |
| { |
| if(cpt < 2) |
| goto help; |
| if (strcasecmp(keywords[1], "rx") == 0) |
| { |
| /*Call Rx process function*/ |
| if (cmmRxSetProcess(keywords, 2, daemon_handle)) |
| return -1; |
| } |
| else if (strcasecmp(keywords[1], "qm") == 0) |
| { |
| /*Call QM process function*/ |
| if(cmmQmSetProcess(keywords, 2, daemon_handle)) |
| return -1; |
| } |
| else if (strcasecmp(keywords[1], "mc6") == 0) |
| { |
| /*Call QM process function*/ |
| if(cmmMc6SetProcess(keywords, 2, daemon_handle)) |
| return -1; |
| } |
| else if (strcasecmp(keywords[1], "mc4") == 0) |
| { |
| /*Call QM process function*/ |
| if(cmmMc4SetProcess(keywords, 2, daemon_handle)) |
| return -1; |
| } |
| else if (strcasecmp(keywords[1], "timeout") == 0) |
| { |
| if(cmmtimeoutSet(daemon_handle, keywords, cpt, 2)) |
| return -1; |
| } |
| else if (strcasecmp(keywords[1], "stat") == 0) |
| { |
| if(cmmStatSetProcess(keywords, 2, daemon_handle)) |
| return -1; |
| } |
| else if (strcasecmp(keywords[1], "expt_queue") == 0) |
| { |
| if(cmmExptSetProcess(keywords, 2, daemon_handle)) |
| return -1; |
| } |
| else if (strcasecmp(keywords[1], "ff") == 0) |
| { |
| if(cmmFFControlProcess(keywords, 2, daemon_handle)) |
| return -1; |
| } |
| else if (strcasecmp(keywords[1], "route") == 0) |
| { |
| if(cmmRouteSetProcess(keywords, 2, daemon_handle)) |
| return -1; |
| } |
| else if (strcasecmp(keywords[1], "sa_query_timer") == 0) |
| { |
| if(cmmDPDSaQuerySetProcess(keywords, 2, daemon_handle)) |
| return -1; |
| } |
| #ifdef C2000_DPI |
| else if (strcasecmp(keywords[1], "dpi") == 0) |
| { |
| if(cmmDPIFlagSetProcess(keywords, 2, daemon_handle)) |
| return -1; |
| } |
| #endif |
| else if (strcasecmp(keywords[1], "asym_fastforward") == 0) |
| { |
| if(cmmAsymFFSetProcess(keywords, 2, daemon_handle)) |
| return -1; |
| } |
| else if (strcasecmp(keywords[1], "config") == 0) |
| { |
| if (cmmAltConfClient(cpt,keywords,2,daemon_handle)) |
| return -1; |
| |
| } |
| else if (strcasecmp(keywords[1], "ipsec") == 0) |
| { |
| if(cmmIPsecSetProcess(keywords, 2, daemon_handle)) |
| return -1; |
| } |
| else if (strcasecmp(keywords[1], "rtp") == 0) |
| { |
| if (cmmRTPSetProcess(keywords, 2, daemon_handle)) |
| return -1; |
| } |
| else if (!strcasecmp(keywords[1], "socket") || !strcasecmp(keywords[1], "socket6")) |
| { |
| if (cmmSocketSetProcess(keywords, 2, daemon_handle)) |
| return -1; |
| } |
| else if (strcasecmp(keywords[1], "rtpstats") == 0) |
| { |
| if (cmmRTPStatsSetProcess(keywords, 2, daemon_handle)) |
| return -1; |
| } |
| else if (strcasecmp(keywords[1], "natpt") == 0) |
| { |
| if (cmmNATPTSetProcess(keywords, 2, daemon_handle)) |
| return -1; |
| } |
| else if (strcasecmp(keywords[1], "voicebuf") == 0) |
| { |
| if (cmmVoiceBufSetProcess(cpt - 2, &keywords[2], daemon_handle)) |
| return -1; |
| } |
| else if (strcasecmp(keywords[1], "frag") == 0) |
| { |
| if (cmmFragTimeoutSet(keywords, 2, daemon_handle)) |
| return -1; |
| } |
| else if (strcasecmp(keywords[1], "bridge") == 0) |
| { |
| if (cmmBridgeControlProcess(keywords, 2, daemon_handle)) |
| return -1; |
| } |
| else if (strcasecmp(keywords[1], "4rd-id-conversion") == 0) |
| { |
| if (cmm4rdIdConvSetProcess(keywords, 2, (cpt - 2), daemon_handle)) |
| return -1; |
| } |
| else |
| goto help; |
| } |
| else if (strcasecmp(keywords[0], "show") == 0) |
| { |
| if(cpt < 2) |
| goto help; |
| |
| if (strcasecmp(keywords[1], "rx") == 0) |
| { |
| /*Call Rx process function*/ |
| if (cmmRxShowProcess(keywords, 2, daemon_handle)) |
| return -1; |
| } |
| else if (strcasecmp(keywords[1], "qm") == 0) |
| { |
| /*Call QM process function*/ |
| if(cmmQmShowProcess(keywords, 2, daemon_handle)) |
| return -1; |
| } |
| else if (strcasecmp(keywords[1], "mc6") == 0) |
| { |
| /*Call QM process function*/ |
| if(cmmMc6ShowProcess(keywords, 2, daemon_handle)) |
| return -1; |
| } |
| else if (strcasecmp(keywords[1], "mc4") == 0) |
| { |
| /*Call QM process function*/ |
| if(cmmMc4ShowProcess(keywords, 2, daemon_handle)) |
| return -1; |
| } |
| else if (strcasecmp(keywords[1], "stat") == 0) |
| { |
| /*Call Stat process function*/ |
| if(cmmStatShowProcess(keywords, 2, daemon_handle)) |
| return -1; |
| } |
| else if (strcasecmp(keywords[1], "expt") == 0) |
| { |
| /*Call QM process function*/ |
| if(cmmExptShowProcess(keywords, 2, daemon_handle)) |
| return -1; |
| } |
| else if (strcasecmp(keywords[1], "route") == 0) |
| { |
| if(cmmRouteShowProcess(keywords, 2, daemon_handle)) |
| return -1; |
| } |
| else if (!strcasecmp(keywords[1], "socket") || !strcasecmp(keywords[1], "socket6")) |
| { |
| if(cmmSocketShowProcess(keywords, 2, daemon_handle)) |
| return -1; |
| } |
| else |
| goto help; |
| } |
| else if (strcasecmp(keywords[0], "query") == 0) |
| { |
| if(cpt < 2) |
| goto help; |
| |
| if (strcasecmp(keywords[1], "rx") == 0) |
| { |
| /*Call Rx process function*/ |
| if (cmmRxQueryProcess(keywords, 2, daemon_handle)) |
| return -1; |
| } |
| else if (strcasecmp(keywords[1], "qm") == 0) |
| { |
| /*Call QM process function*/ |
| if(cmmQmQueryProcess(keywords, 2, daemon_handle)) |
| return -1; |
| } |
| else if (strcasecmp(keywords[1], "qmexptrate") == 0) |
| { |
| /*Call QM process function*/ |
| if(cmmQmExptRateQueryProcess(keywords, 2, daemon_handle)) |
| return -1; |
| } |
| else if (strcasecmp(keywords[1], "mc6") == 0) |
| { |
| /*Call QM process function*/ |
| if(cmmMc6QueryProcess(keywords, 2, daemon_handle)) |
| return -1; |
| } |
| else if (strcasecmp(keywords[1], "mc4") == 0) |
| { |
| /*Call QM process function*/ |
| if(cmmMc4QueryProcess(keywords, 2, daemon_handle)) |
| return -1; |
| } |
| else if (strcasecmp(keywords[1], "pppoe") == 0) |
| { |
| if(cmmPPPoEQueryProcess(keywords, 2, daemon_handle)) |
| return -1; |
| } |
| else if (strcasecmp(keywords[1], "route") == 0) |
| { |
| if(cmmRtQueryProcess(keywords, 2, daemon_handle)) |
| return -1; |
| } |
| else if (strcasecmp(keywords[1], "connections") == 0) |
| { |
| if(cmmCtQueryProcess(keywords, 2, daemon_handle)) |
| return -1; |
| } |
| else if (strcasecmp(keywords[1], "v6connections") == 0) |
| { |
| if(cmmCt6QueryProcess(keywords, 2, daemon_handle)) |
| return -1; |
| } |
| else if (strcasecmp(keywords[1], "vlan") == 0) |
| { |
| if(cmmVlanQuery(keywords, 2, daemon_handle)) |
| return -1; |
| } |
| else if (strcasecmp(keywords[1], "macvlan") == 0) |
| { |
| if(cmmMacVlanQueryProcess(keywords, 2, daemon_handle)) |
| return -1; |
| } |
| else if (strcasecmp(keywords[1], "sa") == 0) |
| { |
| if(cmmSAQueryProcess(keywords, 2, daemon_handle)) |
| return -1; |
| } |
| else if (strcasecmp(keywords[1], "rtcp") == 0) |
| { |
| if(cmmRTCPQueryProcess(keywords, 2, daemon_handle)) |
| return -1; |
| } |
| else if (strcasecmp(keywords[1], "rtpstats") == 0) |
| { |
| if(cmmRTPStatsQueryProcess(keywords, 2, daemon_handle)) |
| return -1; |
| } |
| else if (strcasecmp(keywords[1], "tunnels") == 0) |
| { |
| if(cmmTnlQueryProcess(keywords, 2, daemon_handle)) |
| return -1; |
| } |
| else if (strcasecmp(keywords[1], "natpt") == 0) |
| { |
| if(cmmNATPTQueryProcess(keywords, 2, daemon_handle)) |
| return -1; |
| } |
| #ifdef AUTO_BRIDGE |
| else if (strcasecmp(keywords[1], "l2flows") == 0) |
| { |
| if(cmmL2FlowQueryProcess(keywords, 2, daemon_handle)) |
| return -1; |
| } |
| #endif |
| else |
| { |
| goto help; |
| } |
| } |
| else if (strncasecmp(keywords[0], "msp",3) ==0) |
| { |
| /* mspmem */ |
| if (cmmPrfMem(cpt,keywords,1,daemon_handle)) |
| return -1; |
| } |
| else if (strncasecmp(keywords[0], "dm",2) ==0) |
| { |
| if (dumpmem(cpt,keywords)) |
| return -1; |
| } |
| else if (strcasecmp(keywords[0],"prf") == 0) |
| { |
| if (cmmPrfNM(cpt,keywords,1,daemon_handle)) |
| return -1; |
| } |
| else if (strcasecmp(keywords[0],"tunnel") == 0) |
| { |
| if (cmm_tunnel_parse_cmd(cpt,keywords,1,daemon_handle)) |
| return -1; |
| } |
| else if (strcasecmp(keywords[0],"relay") == 0) |
| { |
| return cmmRelayParseCmd(cpt,keywords,1,daemon_handle); |
| } |
| else if (strncasecmp(keywords[0], "vlan", 4) == 0) |
| { |
| if (cmmVlanClient(cpt,keywords, 1, daemon_handle)) |
| return -1; |
| } |
| else if (strcasecmp(keywords[0], "ipv4") == 0) |
| { |
| if(cpt < 2) |
| goto help; |
| |
| if (strcasecmp(keywords[1], "update") == 0) |
| { |
| /*Call IPv4 update function*/ |
| if (cmmCtChangeProcess4(keywords, 2, daemon_handle)) |
| return -1; |
| } |
| } |
| else if (strcasecmp(keywords[0], "ipv6") == 0) |
| { |
| if(cpt < 2) |
| goto help; |
| |
| if (strcasecmp(keywords[1], "update") == 0) |
| { |
| /*Call IPv6 update function*/ |
| if (cmmCtChangeProcess6(keywords, 2, daemon_handle)) |
| return -1; |
| } |
| } |
| else if (strcasecmp(keywords[0], "pktcapture") == 0) |
| { |
| if (cpt < 2) |
| goto help; |
| |
| if (strcasecmp(keywords[1], "status") == 0) |
| { |
| if (PktCapStatProcess(daemon_handle, cpt-2, &keywords[2])) |
| return -1; |
| } |
| else if (strcasecmp(keywords[1], "slice") == 0) |
| { |
| if (PktCapSliceProcess(daemon_handle, cpt-2,&keywords[2])) |
| return -1; |
| } |
| else if (strcasecmp(keywords[1], "filter") == 0) |
| { |
| if (PktCapFilterProcess(daemon_handle , cpt-2 , &keywords[2])) |
| return -1; |
| } |
| else |
| { |
| char buf[128]; |
| print_all_gemac_ports(buf, 128); |
| cmm_print(DEBUG_STDOUT, "Command usage: pktcapture [status| slice| filter] [%s] <value>\n", buf); |
| } |
| |
| } |
| else if (strcasecmp(keywords[0], "icc") == 0) |
| { |
| if (cpt < 2) |
| goto help; |
| |
| if (strcasecmp(keywords[1], "reset") == 0) |
| { |
| if (IccReset(daemon_handle, cpt-2, &keywords[2])) |
| return -1; |
| } |
| else if (strcasecmp(keywords[1], "threshold") == 0) |
| { |
| if (IccThreshold(daemon_handle, cpt-2,&keywords[2])) |
| return -1; |
| } |
| else if (strcasecmp(keywords[1], "add") == 0) |
| { |
| if (IccAdd(daemon_handle , cpt-2 , &keywords[2])) |
| return -1; |
| } |
| else if (strcasecmp(keywords[1], "delete") == 0) |
| { |
| if (IccDelete(daemon_handle , cpt-2 , &keywords[2])) |
| return -1; |
| } |
| else if (strcasecmp(keywords[1], "query") == 0) |
| { |
| if (IccQuery(daemon_handle, cpt-2,&keywords[2])) |
| return -1; |
| } |
| else |
| { |
| cmm_print(DEBUG_STDOUT, "Command usage: icc [reset | threshold | add | delete | query] <parameters...>\n"); |
| } |
| |
| } |
| |
| else |
| goto help; |
| |
| return 0; |
| |
| help: |
| cmmClientPrintHelp(); |
| |
| return -1; |
| } |
| |
| |
| /***************************************************************** |
| * cmmClient() |
| * |
| * cmm client main function |
| * |
| *****************************************************************/ |
| int cmmClient(char * command, int argc, char **argv) |
| { |
| daemon_handle_t daemon_handle; |
| int rc; |
| |
| #ifdef NEW_IPC |
| daemon_handle = cmm_open(); |
| if (!daemon_handle) |
| { |
| cmm_print(DEBUG_STDERR, "%s: CMM handle creation failed\n", __func__); |
| return -1; |
| } |
| #else |
| /*First check cmm daemon is alive*/ |
| if( (daemon_handle = cmmIsDaemonRunning()) <= 0) |
| { |
| cmm_print(DEBUG_CRIT, "Error, cmm daemon is not running\n"); |
| return -1; |
| } |
| #endif |
| |
| /*Process the command*/ |
| rc = cmmClientProcessCmd(command, argc, argv, daemon_handle); |
| |
| #ifdef NEW_IPC |
| cmm_close(daemon_handle); |
| #endif |
| |
| return rc; |
| } |
| |
| static int cmmCommandParse(struct cmm_daemon *ctx, int function_code, u_int8_t *cmd_buf, u_int16_t cmd_len, u_int16_t *res_buf, u_int16_t *res_len); |
| |
| /***************************************************************** |
| * cmmdaemonThread() |
| * |
| * cmm client main function |
| * |
| *****************************************************************/ |
| static void *cmmDaemonThread(void *data) |
| { |
| struct cmm_daemon *ctx = data; |
| |
| #ifdef NEW_IPC |
| cmm_command_t cmd; |
| cmm_response_t res; |
| #else |
| struct cmm_msg msg; |
| #endif |
| int dataSize; |
| unsigned short dataRcvSize; |
| int rc; |
| unsigned int func; |
| u_int8_t *rx_buf; |
| u_int8_t *tx_buf; |
| |
| cmm_print(DEBUG_INFO, "%s: pid %d\n", __func__, getpid()); |
| |
| while (1) |
| { |
| // Waiting for a message |
| #ifdef NEW_IPC |
| /* We have to reset errno, because it could left after previous error condition, |
| * and we will wrongly report it later as "daemon_errno" even if no error occured. |
| * From 'man errno': |
| * "Successful calls never set errno; once set, it remains until another error occurs". |
| * XXX: this is a hack needed to support "daemon_errno" field in cmm_response_t. |
| * CMM library on client side sets system errno according to "daemon_errno" |
| * and returns -1 when it's not 0. |
| */ |
| errno = 0; |
| |
| memset(&cmd, 0, sizeof(cmd)); |
| memset(&res, 0, sizeof(res)); |
| msgrcv(ctx->queueIdRx, &cmd, sizeof(cmd), 0, 0); |
| res.msg_type = cmd.msg_type; |
| dataSize = cmd.length; |
| dataRcvSize = sizeof(res.buf); |
| func = cmd.func; |
| rx_buf = cmd.buf; |
| tx_buf = res.buf; |
| #else |
| dataSize = msgrcv(ctx->queueIdRx, &msg, sizeof(msg.buffer), 0, 0); |
| dataRcvSize = sizeof(msg.buffer); |
| func = msg.mtype; |
| rx_buf = msg.buffer; |
| tx_buf = msg.buffer; |
| #endif |
| if (dataSize < 0) |
| { |
| /* Exit if queue id no longer exists */ |
| if ((errno == EIDRM) || (errno == ENOENT)) |
| break; |
| |
| // If we have an error receiving a msg, do nothing and continue waiting for a new one |
| cmm_print(DEBUG_WARNING, "%s: msgrcv() failed, %s\n", __func__, strerror(errno)); |
| rc = -1; |
| dataRcvSize = 0; |
| goto answer; |
| } |
| |
| if (dataSize > CMM_BUF_SIZE) { |
| cmm_print(DEBUG_ERROR, "%s: message size exceeds limit of %d\n", __func__, CMM_BUF_SIZE); |
| rc = -1; |
| dataRcvSize = 0; |
| goto answer; |
| } |
| |
| // Debug |
| if ((globalConf.debug_level & DEBUG_INFO) || (globalConf.log_level & DEBUG_INFO)) |
| { |
| int x; |
| char outbuf[CMM_BUF_SIZE * 3 + 1]; /* 3 chars for each byte + trailing '\0' */ |
| cmm_print(DEBUG_INFO, "%s: Received commandCode: (%04x) size %d\n", __func__, func, dataSize); |
| for (x = 0, outbuf[0] = '\0'; x < dataSize; x++) |
| { |
| snprintf(outbuf + strlen(outbuf), sizeof(outbuf) - strlen(outbuf), "%02x ", rx_buf[x]); |
| if ((x & 0xF) == 0xF || x == dataSize - 1) |
| { |
| cmm_print(DEBUG_INFO, "%s\n", outbuf); |
| outbuf[0] = '\0'; |
| } |
| } |
| cmm_print(DEBUG_INFO, "\n"); |
| } |
| |
| rc = cmmCommandParse(ctx, func, rx_buf, dataSize, (u_int16_t*)tx_buf, &dataRcvSize); |
| |
| if (dataRcvSize > CMM_BUF_SIZE) { |
| cmm_print(DEBUG_ERROR, "%s: message size exceeds limit of %d\n", __func__, CMM_BUF_SIZE); |
| rc = -1; |
| dataRcvSize = 0; |
| goto answer; |
| } |
| |
| // Debug |
| if ((globalConf.debug_level & DEBUG_INFO) || (globalConf.log_level & DEBUG_INFO)) |
| { |
| int x; |
| char outbuf[CMM_BUF_SIZE * 3 + 1]; /* 3 chars for each byte + trailing '\0' */ |
| cmm_print(DEBUG_INFO, "%s: Sending ack commandCode: %04x, rc 0x%04x, dataSize: %d \n", __func__, func, rc ,dataRcvSize); |
| for (x = 0, outbuf[0] = '\0'; x < dataRcvSize; x++) |
| { |
| snprintf(outbuf + strlen(outbuf), sizeof(outbuf) - strlen(outbuf), "%02x ", tx_buf[x]); |
| if ((x & 0xF) == 0xF || x == dataRcvSize - 1) |
| { |
| cmm_print(DEBUG_INFO, "%s\n", outbuf); |
| outbuf[0] = '\0'; |
| } |
| } |
| cmm_print(DEBUG_INFO, "\n"); |
| } |
| |
| answer: |
| // Send answer to client |
| #ifdef NEW_IPC |
| res.func = func; |
| if (rc < 0) { |
| if (errno) |
| res.daemon_errno = errno; |
| else |
| res.daemon_errno = EIO; |
| } |
| |
| res.length = dataRcvSize; |
| if (msgsnd(ctx->queueIdTx, &res, sizeof(res) - sizeof(res.buf) + res.length, 0) < 0) |
| #else |
| if (msgsnd(ctx->queueIdTx, &msg, dataRcvSize, 0) < 0) |
| #endif |
| { |
| cmm_print(DEBUG_WARNING, "%s: msgsnd() failed, %s\n", __func__, strerror(errno)); |
| break; |
| } |
| } |
| |
| cmm_print(DEBUG_INFO, "%s: exiting\n", __func__); |
| |
| kill(0, SIGTERM); |
| pthread_exit(NULL); |
| |
| return NULL; |
| } |
| |
| int cmmDaemonInit(struct cmm_daemon *ctx) |
| { |
| key_t key; |
| int id = (int)globalConf.cmmPid; |
| |
| id = ((id & 0xff) ^ ((id >> 8) & 0xff)) | 1; |
| |
| cmm_print(DEBUG_INFO, "%s\n", __func__); |
| |
| key = ftok("/tmp", id ^ 0xff); |
| if (key == (key_t)-1) |
| { |
| cmm_print(DEBUG_CRIT, "%s: ftok(%d) failed, %s\n", __func__, id ^ 0xff, strerror(errno)); |
| goto err0; |
| } |
| |
| // Create the message queue |
| ctx->queueIdRx = msgget(key, IPC_CREAT | IPC_EXCL); |
| if (ctx->queueIdRx < 0) |
| { |
| cmm_print(DEBUG_CRIT, "%s: rx msgget() failed, %s\n", __func__, strerror(errno)); |
| goto err0; |
| } |
| |
| key = ftok("/tmp", id); |
| if (key == (key_t)-1) |
| { |
| cmm_print(DEBUG_CRIT, "%s: ftok(%d) failed, %s\n", __func__, id, strerror(errno)); |
| goto err1; |
| } |
| |
| ctx->queueIdTx = msgget(key, IPC_CREAT | IPC_EXCL); |
| if (ctx->queueIdTx < 0) |
| { |
| cmm_print(DEBUG_CRIT, "%s: tx msgget() failed, %s\n", __func__, strerror(errno)); |
| goto err1; |
| } |
| |
| ctx->fci_handle = fci_open(FCILIB_FF_TYPE, 0); |
| if (!ctx->fci_handle) |
| { |
| cmm_print(DEBUG_CRIT, "%s: fci_open() failed, %s\n", __func__, strerror(errno)); |
| goto err2; |
| } |
| |
| #if !defined(IPSEC_SUPPORT_DISABLED) |
| ctx->fci_key_handle = fci_open(FCILIB_KEY_TYPE, 0); |
| if (!ctx->fci_key_handle) |
| { |
| cmm_print(DEBUG_CRIT, "%s::%d: fci_open() failed, %s\n", __func__, __LINE__, strerror(errno)); |
| goto err3; |
| } |
| #endif |
| voice_buffer_reset(ctx->fci_handle); |
| |
| // Thread for getting cmm client command |
| if (pthread_create(&ctx->pthread, NULL, cmmDaemonThread, ctx) < 0) |
| { |
| cmm_print(DEBUG_CRIT, "%s: pthread_create() failed, %s\n", __func__, strerror(errno)); |
| goto err4; |
| } |
| |
| return 0; |
| |
| err4: |
| #if !defined(IPSEC_SUPPORT_DISABLED) |
| fci_close(ctx->fci_key_handle); |
| |
| err3: |
| #endif |
| fci_close(ctx->fci_handle); |
| |
| err2: |
| msgctl(ctx->queueIdTx, IPC_RMID, NULL); |
| |
| err1: |
| msgctl(ctx->queueIdRx, IPC_RMID, NULL); |
| |
| err0: |
| return -1; |
| } |
| |
| void cmmDaemonExit(struct cmm_daemon *ctx) |
| { |
| cmm_print(DEBUG_INFO, "%s\n", __func__); |
| |
| #if defined(__UCLIBC__) |
| /* workaround uclibc pthread_cancel() bug, force thread to exit */ |
| msgctl(ctx->queueIdTx, IPC_RMID, NULL); |
| msgctl(ctx->queueIdRx, IPC_RMID, NULL); |
| #else |
| pthread_cancel(ctx->pthread); |
| #endif |
| |
| pthread_join(ctx->pthread, NULL); |
| |
| fci_close(ctx->fci_handle); |
| #if !defined(IPSEC_SUPPORT_DISABLED) |
| fci_close(ctx->fci_key_handle); |
| #endif |
| #if !defined(__UCLIBC__) |
| msgctl(ctx->queueIdTx, IPC_RMID, NULL); |
| msgctl(ctx->queueIdRx, IPC_RMID, NULL); |
| #endif |
| |
| cmm_print(DEBUG_INFO, "%s: exiting\n", __func__); |
| } |
| |
| /***************************************************************** |
| * cmmCommandParse() |
| * |
| * returns: |
| * 0 - success |
| * -1 - system error. errno variable indicates error in this case. |
| *****************************************************************/ |
| static int cmmCommandParse(struct cmm_daemon *ctx, int function_code, u_int8_t *cmd_buf, u_int16_t cmd_len, u_int16_t *res_buf, u_int16_t *res_len) |
| { |
| if ((function_code & FPP_CMD_TRC_MASK) == FPP_CMD_TRC_VAL) |
| goto FCI_CMD; |
| |
| switch (function_code) |
| { |
| case CMMD_CMD_IPV4_CONNTRACK: |
| case CMMD_CMD_IPV6_CONNTRACK: |
| return cmmCtHandle(ctx->fci_handle, function_code, cmd_buf, cmd_len, res_buf, res_len); |
| |
| case CMMD_CMD_IPV4_FF_CONTROL: |
| return cmmFeFFControl(ctx->fci_handle, cmd_buf, cmd_len, res_buf, res_len); |
| |
| // Multicast commands, we accept but we need to do a local process |
| case CMMD_CMD_MC6_MULTICAST: |
| case CMMD_CMD_MC6_RESET: |
| case CMMD_CMD_MC6_MODE: |
| return cmmMc6ProcessClientCmd(ctx->fci_handle, function_code, cmd_buf, cmd_len, res_buf, res_len); |
| |
| case CMMD_CMD_MC4_MULTICAST: |
| case CMMD_CMD_MC4_RESET: |
| return cmmMc4ProcessClientCmd(ctx->fci_handle, function_code, cmd_buf, cmd_len, res_buf, res_len); |
| |
| /* Tunnel commands */ |
| case CMMD_CMD_TUNNEL_ADD: |
| case CMMD_CMD_TUNNEL_DEL: |
| case CMMD_CMD_TUNNEL_SHOW: |
| case CMMD_CMD_TUNNEL_IDCONV_psid: |
| #ifdef SAM_LEGACY |
| case CMMD_CMD_TUNNEL_SAMREADY: |
| #endif |
| return tunnel_daemon_msg_recv(ctx->fci_handle, ctx->fci_key_handle, function_code, cmd_buf, cmd_len, res_buf, res_len); |
| |
| case CMMD_CMD_PPPOE_RELAY_ADD: |
| case CMMD_CMD_PPPOE_RELAY_REMOVE: |
| return cmmRelayProcessClientCmd(ctx->fci_handle, function_code, cmd_buf, cmd_len, res_buf, res_len); |
| |
| case CMMD_CMD_VLAN_ENTRY: |
| return cmmVlanProcessClientCmd(ctx->fci_handle, function_code, cmd_buf, cmd_len, res_buf, res_len); |
| |
| case CMMD_CMD_EXTROUTE: |
| return cmmRouteProcessClientCmd(ctx->fci_handle, function_code, cmd_buf, res_buf, res_len); |
| |
| case CMMD_CMD_IPSEC_DPDSAQUERYTIMER: |
| return cmmDPDSAQUERYProcessClientCmd(cmd_buf, res_buf, res_len); |
| #ifdef C2000_DPI |
| case CMMD_CMD_DPIENABLE: |
| return cmmDPIFlagProcessClientCmd(cmd_buf, res_buf, res_len); |
| #endif |
| case CMMD_ASYM_FF_ENABLE: |
| return cmmAsymFFProcessClientCmd(cmd_buf, res_buf, res_len); |
| case CMMD_CMD_SOCKET_OPEN: |
| case CMMD_CMD_SOCKET_CLOSE: |
| case CMMD_CMD_SOCKET_UPDATE: |
| case CMMD_CMD_SOCKET_SHOW: |
| return socket_daemon(ctx->fci_handle, ctx->fci_key_handle, function_code, cmd_buf, cmd_len, res_buf, res_len); |
| |
| case CMMD_CMD_VOICE_FILE_LOAD: |
| return voice_file_load(ctx->fci_handle, (cmmd_voice_file_load_cmd_t *)cmd_buf, res_buf, res_len); |
| |
| case CMMD_CMD_VOICE_FILE_UNLOAD: |
| return voice_file_unload(ctx->fci_handle, (cmmd_voice_file_unload_cmd_t *)cmd_buf, res_buf, res_len); |
| |
| case CMMD_CMD_L2TP_SESSION_CREATE: |
| case CMMD_CMD_L2TP_SESSION_DESTROY: |
| return l2tp_daemon(ctx->fci_handle,function_code, (cmmd_l2tp_session_t *) cmd_buf, cmd_len, res_buf, res_len); |
| |
| //Bridge commands |
| case FPP_CMD_RX_L2BRIDGE_ENABLE: |
| case FPP_CMD_RX_L2BRIDGE_ADD: |
| case FPP_CMD_RX_L2BRIDGE_REMOVE: |
| case FPP_CMD_RX_L2BRIDGE_QUERY_STATUS: |
| case FPP_CMD_RX_L2BRIDGE_QUERY_ENTRY: |
| return cmmL2BridgeProcessClientCmd(ctx->fci_handle, function_code, cmd_buf, cmd_len, res_buf, res_len); |
| |
| // Special processing for QM Reset and Scheduler config (need to notify eth driver) |
| |
| case FPP_CMD_QM_RESET: |
| cmmQmResetQ2Prio((fpp_qm_reset_cmd_t *)cmd_buf, cmd_len); |
| goto FCI_CMD; |
| |
| case FPP_CMD_QM_SCHED_CFG: |
| cmmQmUpdateQ2Prio((fpp_qm_scheduler_cfg_t *)cmd_buf, cmd_len); |
| goto FCI_CMD; |
| |
| // Accept the remaining qm commands |
| case FPP_CMD_QM_QOSENABLE: |
| case FPP_CMD_QM_QOSALG: |
| case FPP_CMD_QM_NHIGH: |
| case FPP_CMD_QM_MAX_TXDEPTH: |
| case FPP_CMD_QM_MAX_QDEPTH: |
| case FPP_CMD_QM_MAX_WEIGHT: |
| case FPP_CMD_QM_RATE_LIMIT: |
| case FPP_CMD_QM_EXPT_RATE: |
| case FPP_CMD_QM_QUERY: |
| case FPP_CMD_QM_QUERY_EXPT_RATE: |
| case FPP_CMD_QM_SHAPER_CFG: |
| case FPP_CMD_QM_DSCP_MAP: |
| case FPP_CMD_QM_QUEUE_QOSENABLE: |
| // Accept ICC commands |
| case FPP_CMD_ICC_RESET: |
| case FPP_CMD_ICC_THRESHOLD: |
| case FPP_CMD_ICC_ADD_DELETE: |
| case FPP_CMD_ICC_QUERY: |
| // Accept some RX commands |
| case FPP_CMD_RX_CNG_ENABLE: |
| case FPP_CMD_RX_CNG_DISABLE: |
| case FPP_CMD_RX_CNG_SHOW: |
| case FPP_CMD_RX_L2FLOW_ENTRY: |
| case FPP_CMD_RX_L2BRIDGE_FLOW_TIMEOUT: |
| // Accept timeout set command |
| case FPP_CMD_IPV4_SET_TIMEOUT: |
| case FPP_CMD_IPV4_FRAGTIMEOUT: |
| case FPP_CMD_IPV4_SAMFRAGTIMEOUT: |
| case FPP_CMD_IPV4_GET_TIMEOUT: |
| case FPP_CMD_IPV6_GET_TIMEOUT: |
| case FPP_CMD_IPV6_FRAGTIMEOUT: |
| // accept for ACTION_QUERY |
| case FPP_CMD_IP_ROUTE: |
| case FPP_CMD_PPPOE_ENTRY: |
| case FPP_CMD_IPSEC_SA_ACTION_QUERY: |
| case FPP_CMD_IPSEC_SA_ACTION_QUERY_CONT: |
| |
| // Voice Buffer |
| case FPP_CMD_VOICE_BUFFER_START: |
| case FPP_CMD_VOICE_BUFFER_STOP: |
| // accept stat commands |
| case FPP_CMD_STAT_ENABLE: |
| case FPP_CMD_STAT_QUEUE: |
| case FPP_CMD_STAT_INTERFACE_PKT: |
| case FPP_CMD_STAT_CONNECTION: |
| case FPP_CMD_STAT_PPPOE_STATUS: |
| case FPP_CMD_STAT_PPPOE_ENTRY: |
| case FPP_CMD_STAT_BRIDGE_STATUS: |
| case FPP_CMD_STAT_BRIDGE_ENTRY: |
| case FPP_CMD_STAT_IPSEC_STATUS: |
| case FPP_CMD_STAT_IPSEC_ENTRY: |
| case FPP_CMD_STAT_VLAN_STATUS: |
| case FPP_CMD_STAT_VLAN_ENTRY: |
| // accept alternate Configuration commands |
| case FPP_CMD_ALTCONF_SET: |
| case FPP_CMD_ALTCONF_RESET: |
| // Expt |
| case FPP_CMD_EXPT_QUEUE_RESET: |
| case FPP_CMD_EXPT_QUEUE_DSCP: |
| case FPP_CMD_EXPT_QUEUE_CONTROL: |
| case FPP_CMD_IPSEC_FRAG_CFG: |
| // Socket and RTP statistics |
| case FPP_CMD_RTP_CLOSE: |
| case FPP_CMD_RTP_CONTROL: |
| case FPP_CMD_RTP_OPEN: |
| case FPP_CMD_RTP_SPECTX_CTRL: |
| case FPP_CMD_RTP_SPECTX_PLD: |
| case FPP_CMD_RTP_TAKEOVER: |
| case FPP_CMD_RTP_UPDATE: |
| case FPP_CMD_RTCP_QUERY: |
| case FPP_CMD_RTP_STATS_ENABLE: |
| case FPP_CMD_RTP_STATS_DISABLE: |
| case FPP_CMD_RTP_STATS_QUERY: |
| case FPP_CMD_RTP_STATS_DTMF_PT: |
| case FPP_CMD_NATPT_OPEN: |
| case FPP_CMD_NATPT_CLOSE: |
| case FPP_CMD_NATPT_QUERY: |
| case FPP_CMD_PKTCAP_IFSTATUS: |
| case FPP_CMD_PKTCAP_SLICE: |
| case FPP_CMD_PKTCAP_FLF: |
| case FPP_CMD_PKTCAP_QUERY: |
| case FPP_CMD_MACVLAN_ENTRY: |
| case FPP_CMD_TUNNEL_QUERY: |
| case FPP_CMD_TUNNEL_QUERY_CONT: |
| case FPP_CMD_TUNNEL_4rd_ID_CONV_dport: |
| goto FCI_CMD; |
| |
| // Other commands, we refuse |
| default: |
| res_buf[0] = CMMD_ERR_UNKNOWN_COMMAND; |
| *res_len = 2; |
| } |
| |
| return 0; |
| |
| FCI_CMD: |
| //Sending message to FPP |
| return fci_cmd(ctx->fci_handle, function_code, (unsigned short *)cmd_buf, cmd_len, (unsigned short *)res_buf, res_len); |
| } |
| |
| |
| ///////////////////////////////////////////////////////////////////////////////////////////////////////// |
| |
| int parse_value(char *p, u_int32_t *value, u_int32_t maxval) |
| { |
| char *endp; |
| u_int32_t val; |
| val = strtoul(p, &endp, 0); |
| if (*endp || val > maxval) |
| return -1; |
| *value = val; |
| return 0; |
| } |
| |
| |
| int parse_range(char *p, u_int32_t *from, u_int32_t *to, u_int32_t maxval) |
| { |
| char *endp; |
| u_int32_t fromval, toval; |
| fromval = strtoul(p, &endp, 0); |
| if (*endp) |
| { |
| if (*endp++ != '-') |
| return -1; |
| if (parse_value(endp, &toval, maxval) < 0) |
| return -1; |
| } |
| else |
| toval = fromval; |
| if (toval < fromval || toval > maxval) |
| return -1; |
| *from = fromval; |
| *to = toval; |
| return 0; |
| } |
| |
| ///////////////////////////////////////////////////////////////////////////////////////////////////////// |
| |
| |
| #include<sys/stat.h> |
| #include<sys/mman.h> |
| |
| #define DISP_LINE_LEN 16 |
| #define MMAP_SIZE 0x01000000 |
| |
| volatile unsigned char *base_addr; |
| |
| int dumpmem(int argc, char *argv[]) |
| { |
| unsigned long addr, size, length=16; |
| unsigned long i, nbytes, linebytes; |
| unsigned char *cp; |
| int fd; |
| int rc = 0; |
| char outbuf[256]; |
| |
| /* We use the last specified parameters, unless new ones are |
| * entered. |
| */ |
| |
| if (argc != 2 && argc != 3) { |
| cmm_print(DEBUG_ERROR, "Usage : dm[b|w|l] address [size]\n"); |
| return(1); |
| } |
| |
| switch(argv[0][2]) { |
| case 'b': |
| size = 1; |
| break; |
| case 'w': |
| size = 2; |
| break; |
| case 'l': |
| size = 4; |
| break; |
| default: |
| size = 4; |
| break; |
| } |
| |
| addr = strtoul(argv[1], NULL, 16); |
| fd = open("/dev/mem", O_RDWR); |
| if (fd == -1) { |
| cmm_print(DEBUG_ERROR, "open() error. errno:%m\n"); |
| return(1); |
| } |
| base_addr = mmap(0, |
| MMAP_SIZE, |
| PROT_READ|PROT_WRITE, |
| MAP_SHARED, |
| fd, |
| (addr & 0xFF000000)); |
| if (base_addr == (unsigned char*)(-1)){ |
| cmm_print(DEBUG_ERROR, "mmap() error. errno:%m\n"); |
| rc = 1; |
| goto err; |
| } |
| |
| /* If another parameter, it is the length to display. |
| * Length is the number of objects, not number of bytes. |
| */ |
| if (argc == 3) { |
| length = strtoul(argv[2], NULL, 16); |
| } |
| |
| /* Print the lines. |
| * |
| * We buffer all read data, so we can make sure data is read only |
| * once, and all accesses are with the specified bus width. |
| */ |
| nbytes = length * size; |
| if (nbytes > MMAP_SIZE) { |
| cmm_print(DEBUG_ERROR, "display size over ( 0x%08x > 0x%08x ).\n", (int)nbytes, MMAP_SIZE); |
| rc = 1; |
| goto err; |
| } |
| do { |
| u_int8_t linebuf[DISP_LINE_LEN]; |
| unsigned int *uip = (unsigned int *)linebuf; |
| unsigned short *usp = (unsigned short *)linebuf; |
| unsigned char *ucp = (unsigned char *)linebuf; |
| |
| sprintf(outbuf, "%08lx:", addr); |
| linebytes = (nbytes>DISP_LINE_LEN)?DISP_LINE_LEN:nbytes; |
| for (i=0; i<linebytes; i+= size) { |
| if (size == 4) { |
| sprintf(outbuf + strlen(outbuf), " %08x", (*uip++ = *((unsigned int *)(base_addr+(addr&0x00ffffff))))); |
| } else if (size == 2) { |
| sprintf(outbuf + strlen(outbuf), " %04x", (*usp++ = *((unsigned short *)(base_addr+(addr&0x00ffffff))))); |
| } else { |
| sprintf(outbuf + strlen(outbuf), " %02x", (*ucp++ = *((unsigned char *)(base_addr+(addr&0x00ffffff))))); |
| } |
| addr += size; |
| } |
| sprintf(outbuf + strlen(outbuf), " "); |
| cp = linebuf; |
| for (i=0; i<linebytes; i++) { |
| if ((*cp < 0x20) || (*cp > 0x7e)) |
| sprintf(outbuf + strlen(outbuf), "."); |
| else |
| sprintf(outbuf + strlen(outbuf), "%c", *cp); |
| cp++; |
| } |
| cmm_print(DEBUG_STDOUT, "%s\n", outbuf); |
| nbytes -= linebytes; |
| } while (nbytes > 0); |
| |
| munmap((void*)base_addr, MMAP_SIZE); |
| err: |
| close(fd); |
| return (rc); |
| } |