/* * $Id: openserSIPPortTable.c 1425 2006-12-18 22:22:51Z jmagder $ * * SNMPStats Module * Copyright (C) 2006 SOMA Networks, INC. * Written by: Jeffrey Magder (jmagder@somanetworks.com) * * This file is part of openser, a free SIP server. * * openser 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 * * openser 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 * * History: * -------- * 2006-11-23 initial version (jmagder) * * Originally Generated with mib2c using mib2c.array-user.conf * * This file implements the openserSIPPortTable. For a full description of the table, * please see the OPENSER-SIP-COMMON-MIB. * */ #include "snmpstats_globals.h" #include "network_stats.h" #include "../../socket_info.h" #include #include #include #include #include "openserSIPPortTable.h" #include "../../statistics.h" #include "../../mem/mem.h" static netsnmp_handler_registration *my_handler = NULL; static netsnmp_table_array_callbacks cb; oid openserSIPPortTable_oid[] = { openserSIPPortTable_TABLE_OID }; size_t openserSIPPortTable_oid_len = OID_LENGTH(openserSIPPortTable_oid); /* Returns a new OID with the following structure: * * ipType.NUM_IP_OCTETS.ipAddress[0].ipAddress[1]...ipAddress[NUM_IP_OCTETS].portNumber * * sizeOfOID will be assigned the length of the oid. * * Note: This function returns a newly allocated block of memory. Make sure to * deallocate the memory when you no longer need it. */ oid *createIndex(int ipType, int *ipAddress, int *sizeOfOID) { oid *currentOIDIndex; int i; /* The size needs to be large enough such that it can store the ipType * (one octet), the prefixed length (one octet), the number of * octets to the IP Address (NUM_IP_OCTETS), and the port. */ *sizeOfOID = NUM_IP_OCTETS + 3; /* Allocate space for the OID Index. */ currentOIDIndex = pkg_malloc((*sizeOfOID) * sizeof(oid)); if (currentOIDIndex == NULL) { LOG(L_ERR, "ERROR: SNMPStats: Could not create a row for" "openserSIPPortTable\n"); *sizeOfOID = 0; return NULL; } /* Assign the OID Index */ currentOIDIndex[0] = ipType; currentOIDIndex[1] = NUM_IP_OCTETS; for (i = 0; i < NUM_IP_OCTETS; i++) { currentOIDIndex[i+2] = ipAddress[i]; } /* Extract out the port number */ currentOIDIndex[NUM_IP_OCTETS+2] = ipAddress[NUM_IP_OCTETS]; return currentOIDIndex; } /* Will return an existing row indexed by the parameter list if one exists, and * return a new one otherwise. If the row is new, then the provided index will be * assigned to the new row. * * Note: NULL will be returned on an error */ openserSIPPortTable_context *getRow(int ipType, int *ipAddress) { int lengthOfOID; oid *currentOIDIndex = createIndex(ipType, ipAddress, &lengthOfOID); if (currentOIDIndex == NULL) { return NULL; } netsnmp_index theIndex; theIndex.oids = currentOIDIndex; theIndex.len = lengthOfOID; openserSIPPortTable_context *rowToReturn; /* Lets check to see if there is an existing row. */ rowToReturn = CONTAINER_FIND(cb.container, &theIndex); /* We found an existing row, so there is no need to create a new one. * Let's return it to the caller. */ if (rowToReturn != NULL) { /* We don't need the index we allocated anymore, because the * existing row already has its own copy, so free the memory */ pkg_free(currentOIDIndex); return rowToReturn; } /* If we are here then the row doesn't exist yet. So lets create it. */ rowToReturn = SNMP_MALLOC_TYPEDEF(openserSIPPortTable_context); /* Not enough memory to create the new row. */ if (rowToReturn == NULL) { pkg_free(currentOIDIndex); return NULL; } /* Assign the Container Index. */ rowToReturn->index.len = lengthOfOID; rowToReturn->index.oids = currentOIDIndex; memcpy(rowToReturn->openserSIPStringIndex, currentOIDIndex, NUM_IP_OCTETS + 3); rowToReturn->openserSIPStringIndex_len = NUM_IP_OCTETS + 3; /* Insert the new row into the table */ CONTAINER_INSERT(cb.container, rowToReturn); return rowToReturn; } /* * Will create rows for this table from theList. The final parameter snmpIndex * can point to any integer >= zero. All rows created by this function will be * indexed starting at snmpIndex++. The parameter is implemented as a pointer * to an integer so that if the function is called again with another * 'protocol', we can continue from the last index. */ void createRowsFromIPList(int *theList, int listSize, int protocol, int *snmpIndex) { openserSIPPortTable_context *currentRow; int curIndexOfIP; int curSocketIdx; int valueToAssign; if (protocol == PROTO_UDP) { valueToAssign = TC_TRANSPORT_PROTOCOL_UDP; } else if (protocol == PROTO_TCP) { valueToAssign = TC_TRANSPORT_PROTOCOL_TCP; } else if (protocol == PROTO_TLS) { valueToAssign = TC_TRANSPORT_PROTOCOL_TLS; } else { valueToAssign = TC_TRANSPORT_PROTOCOL_OTHER; } /* Create all rows with respect to the given protocol */ for (curSocketIdx=0; curSocketIdx < listSize; curSocketIdx++) { curIndexOfIP = (NUM_IP_OCTETS + 1) * curSocketIdx; /* Retrieve an existing row, or a new row if one doesn't * allready exist. */ currentRow = getRow(1, &theList[curIndexOfIP]); if (currentRow == NULL) { LOG(L_ERR, "ERROR: SNMPStats: Unable to create all the " "rows for the openserSIPPortTable\n"); return; } currentRow->openserSIPTransportRcv[0] |= valueToAssign; currentRow->openserSIPTransportRcv_len = 1; } } /* * Initializes the openserSIPPortTable module. * * Specifically, this function will define the tables structure, and then * populate it with the ports and transports that OpenSER is listening on. * */ void init_openserSIPPortTable(void) { int curSNMPIndex = 0; initialize_table_openserSIPPortTable(); int *UDPList = NULL; int *TCPList = NULL; int *TLSList = NULL; int numUDPSockets; int numTCPSockets; int numTLSSockets; /* Retrieve the list of the number of UDP and TCP sockets. */ numUDPSockets = get_socket_list_from_proto(&UDPList, PROTO_UDP); numTCPSockets = get_socket_list_from_proto(&TCPList, PROTO_TCP); numTLSSockets = get_socket_list_from_proto(&TLSList, PROTO_TLS); /* Generate all rows, using all retrieved interfaces. */ createRowsFromIPList(UDPList, numUDPSockets, PROTO_UDP, &curSNMPIndex); curSNMPIndex = 0; createRowsFromIPList(TCPList, numTCPSockets, PROTO_TCP, &curSNMPIndex); curSNMPIndex = 0; createRowsFromIPList(TLSList, numTLSSockets, PROTO_TLS, &curSNMPIndex); } /* Initialize the openserSIPPortTable table by defining how it is structured */ void initialize_table_openserSIPPortTable(void) { netsnmp_table_registration_info *table_info; if(my_handler) { snmp_log(LOG_ERR, "initialize_table_openserSIPPortTable_handler" "called again\n"); return; } memset(&cb, 0x00, sizeof(cb)); /* create the table structure itself */ table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info); my_handler = netsnmp_create_handler_registration("openserSIPPortTable", netsnmp_table_array_helper_handler, openserSIPPortTable_oid, openserSIPPortTable_oid_len, HANDLER_CAN_RONLY); if (!my_handler || !table_info) { snmp_log(LOG_ERR, "malloc failed in " "initialize_table_openserSIPPortTable_handler\n"); return; /** mallocs failed */ } /* Set up the table's structural definition */ /* index: openserSIPPortIndex */ netsnmp_table_helper_add_index(table_info, ASN_OCTET_STR); table_info->min_column = openserSIPPortTable_COL_MIN; table_info->max_column = openserSIPPortTable_COL_MAX; /* register the table with the master agent */ cb.get_value = openserSIPPortTable_get_value; cb.container = netsnmp_container_find("openserSIPPortTable_primary:" "openserSIPPortTable:" "table_container"); DEBUGMSGTL(("initialize_table_openserSIPPortTable", "Registering table openserSIPPortTable " "as a table array\n")); netsnmp_table_container_register(my_handler, table_info, &cb, cb.container, 1); } /* * This routine is called to process get requests for elements of the table. * * The function is mostly left in its auto-generated form */ int openserSIPPortTable_get_value(netsnmp_request_info *request, netsnmp_index *item, netsnmp_table_request_info *table_info ) { netsnmp_variable_list *var = request->requestvb; openserSIPPortTable_context *context = (openserSIPPortTable_context *)item; switch(table_info->colnum) { case COLUMN_OPENSERSIPTRANSPORTRCV: /** OpenSERSIPTransportProtocol = ASN_OCTET_STR */ snmp_set_var_typed_value(var, ASN_OCTET_STR, (unsigned char *) &context->openserSIPTransportRcv, context->openserSIPTransportRcv_len ); break; default: /** We shouldn't get here */ snmp_log(LOG_ERR, "unknown column in " "openserSIPPortTable_get_value\n"); return SNMP_ERR_GENERR; } return SNMP_ERR_NOERROR; } /* Auto-generated function */ const openserSIPPortTable_context * openserSIPPortTable_get_by_idx(netsnmp_index * hdr) { return (const openserSIPPortTable_context *) CONTAINER_FIND(cb.container, hdr ); }