/* * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. * * U.S. Government Rights - Commercial software. Government users are subject * to the Sun Microsystems, Inc. standard license agreement and applicable * provisions of the FAR and its supplements. * * * This distribution may include materials developed by third parties. Sun, * Sun Microsystems, the Sun logo and Solaris are trademarks or registered * trademarks of Sun Microsystems, Inc. in the U.S. and other countries. * */ /* * Note: this file originally auto-generated by mib2c using * : mib2c.iterate.conf,v 5.5 2002/12/16 22:50:18 hardaker Exp $ */ #include #include #include #include "stdhdr.h" #include "entPhysicalContainsTable.h" #include "entPhysicalTable.h" #include "entLastChangeTime.h" static int FreePhyContainsTableEntry(physIndexAndChildIndex_t *); static int isRecursiveChild(int, int); physIndexAndChildIndex_t *gPhyContainsTableHead; int gPhyContainsTableSize; /* Fix for 4910641 */ int_l *zChildIndexesTracker; /* End of Fix for 4910641 */ /** Initialize the entPhysicalContainsTable table by defining its contents and how it's structured */ void initialize_table_entPhysicalContainsTable(void) { static oid entPhysicalContainsTable_oid[] = {1,3,6,1,2,1,47,1,3,3}; netsnmp_table_registration_info *table_info; netsnmp_handler_registration *my_handler; netsnmp_iterator_info *iinfo; /* create the table structure itself */ table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info); iinfo = SNMP_MALLOC_TYPEDEF(netsnmp_iterator_info); /* if your table is read only, it's easiest to change the HANDLER_CAN_RWRITE definition below to HANDLER_CAN_RONLY */ /* Fix for 4910624 - changing HANDLER_CAN_RWRITE to HANDLER_CAN_RONLY */ my_handler = netsnmp_create_handler_registration("entPhysicalContainsTable", entPhysicalContainsTable_handler, entPhysicalContainsTable_oid, OID_LENGTH(entPhysicalContainsTable_oid), HANDLER_CAN_RONLY); /* End of Fix for 4910624 */ if (!my_handler || !table_info || !iinfo) return; /* mallocs failed */ /*************************************************** * Setting up the table's definition */ netsnmp_table_helper_add_indexes(table_info, ASN_INTEGER, /* index: entPhysicalIndex */ ASN_INTEGER, /* index: entPhysicalChildIndex */ 0); table_info->min_column = 1; table_info->max_column = 1; /* iterator access routines */ iinfo->get_first_data_point = entPhysicalContainsTable_get_first_data_point; iinfo->get_next_data_point = entPhysicalContainsTable_get_next_data_point; iinfo->table_reginfo = table_info; /*************************************************** * registering the table with the master agent */ DEBUGMSGTL(("initialize_table_entPhysicalContainsTable", "Registering table entPhysicalContainsTable as a table iterator\n")); netsnmp_register_table_iterator(my_handler, iinfo); } /** Initializes the entPhysicalContainsTable module */ void init_entPhysicalContainsTable(void) { /* here we initialize all the tables we're planning on supporting */ initialize_table_entPhysicalContainsTable(); gPhyContainsTableHead = NULL; gPhyContainsTableSize = 0; } /** returns the first data point within the entPhysicalContainsTable table data. Set the my_loop_context variable to the first data point structure of your choice (from which you can find the next one). This could be anything from the first node in a linked list, to an integer pointer containing the beginning of an array variable. Set the my_data_context variable to something to be returned to you later that will provide you with the data to return in a given row. This could be the same pointer as what my_loop_context is set to, or something different. The put_index_data variable contains a list of snmp variable bindings, one for each index in your table. Set the values of each appropriately according to the data matching the first row and return the put_index_data variable at the end of the function. */ netsnmp_variable_list * entPhysicalContainsTable_get_first_data_point(void **my_loop_context, void **my_data_context, netsnmp_variable_list *put_index_data, netsnmp_iterator_info *mydata) { netsnmp_variable_list *vptr; physIndexAndChildIndex_t *zRunner, *zpValidEntry; int_l *zChildIndexes, zValidChildIdx=0, *zpValidChildIdx; zRunner = gPhyContainsTableHead; while (zRunner) { if (zRunner->entPhysicalIndex > 0) { zChildIndexes = zRunner->childIndexes; while ((zChildIndexes != NULL) && (*zChildIndexes != 0)){ if (*zChildIndexes > 0) { zValidChildIdx = *zChildIndexes; break; } zChildIndexes++; } if (zValidChildIdx) { zpValidEntry = zRunner; zpValidChildIdx = zChildIndexes; break; } } zRunner = zRunner->pNextEntry; } if (zRunner == NULL) return NULL; /* Fix for 4910641: No idea why it worked in Sparc with the original */ /* version. *my_loop_context was pointing to */ /* temporary address, and maybe Intel and Sparc handles */ /* memory differently - that is probably why it worked */ /* on Sparc but not on Intel. This version is */ /* valid, and easier to trace and understand. */ *my_loop_context = (void *) zpValidEntry; *my_data_context = (void *) zpValidChildIdx; zChildIndexesTracker = zpValidChildIdx; /* End of Fix for 4910641 */ vptr = put_index_data; snmp_set_var_value(vptr, (u_char *) &zpValidEntry->entPhysicalIndex, sizeof(zpValidEntry->entPhysicalIndex)); vptr = vptr->next_variable; snmp_set_var_value(vptr, (u_char *) zpValidChildIdx, sizeof(int_l)); vptr = vptr->next_variable; return put_index_data; } /** functionally the same as entPhysicalContainsTable_get_first_data_point, but my_loop_context has already been set to a previous value and should be updated to the next in the list. For example, if it was a linked list, you might want to cast it and the return my_loop_context->next. The my_data_context pointer should be set to something you need later and the indexes in put_index_data updated again. */ netsnmp_variable_list * entPhysicalContainsTable_get_next_data_point(void **my_loop_context, void **my_data_context, netsnmp_variable_list *put_index_data, netsnmp_iterator_info *mydata) { netsnmp_variable_list *vptr; physIndexAndChildIndex_t *zRunner, *zpValidEntry; int_l *zChildIndexes, zValidChildIdx=0, *zpValidChildIdx; /* Fix for 4910641: We need to dereference the pointers, and cast */ /* them back to the appropriate data structure */ zRunner = (physIndexAndChildIndex_t *)*my_loop_context; zChildIndexes = zChildIndexesTracker; /* End of Fix for 4910641 */ if (zChildIndexes) zChildIndexes++; while (zRunner) { if (zRunner->entPhysicalIndex > 0) { while ((zChildIndexes != NULL) && (*zChildIndexes != 0)){ if (*zChildIndexes > 0) { zValidChildIdx = *zChildIndexes; break; } zChildIndexes++; } if (zValidChildIdx) { zpValidEntry = zRunner; zpValidChildIdx = zChildIndexes; break; } } zRunner = zRunner->pNextEntry; if (zRunner) zChildIndexes = zRunner->childIndexes; } if (zRunner == NULL) return NULL; /* Fix for 4910641: We are making sure that *my_loop_context and */ /* *my_data_context are pointing to valid entries. */ *my_loop_context = (void *) zpValidEntry; *my_data_context = (void *) zpValidChildIdx; zChildIndexesTracker = zpValidChildIdx; /* End Fix for 4910641 */ vptr = put_index_data; snmp_set_var_value(vptr, (u_char *) &zpValidEntry->entPhysicalIndex, sizeof(zpValidEntry->entPhysicalIndex)); vptr = vptr->next_variable; snmp_set_var_value(vptr, (u_char *) zpValidChildIdx, sizeof(int_l)); vptr = vptr->next_variable; return put_index_data; } /** handles requests for the entPhysicalContainsTable table, if anything else needs to be done */ int entPhysicalContainsTable_handler( netsnmp_mib_handler *handler, netsnmp_handler_registration *reginfo, netsnmp_agent_request_info *reqinfo, netsnmp_request_info *requests) { netsnmp_request_info *request; netsnmp_table_request_info *table_info; netsnmp_variable_list *var; int_l *idx; for(request = requests; request; request = request->next) { var = request->requestvb; if (request->processed != 0) continue; /* perform anything here that you need to do before each request is processed. */ /* the following extracts the my_data_context pointer set in the loop functions above. You can then use the results to help return data for the columns of the entPhysicalContainsTable table in question */ idx = (int_l *) netsnmp_extract_iterator_context(request); if (idx == NULL) { if (reqinfo->mode == MODE_GET) { netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHINSTANCE); continue; } /* XXX: no row existed, if you support creation and this is a set, start dealing with it here, else continue */ } /* extracts the information about the table from the request */ table_info = netsnmp_extract_table_info(request); /* table_info->colnum contains the column number requested */ /* table_info->indexes contains a linked list of snmp variable bindings for the indexes of the table. Values in the list have been set corresponding to the indexes of the request */ if (table_info==NULL) { continue; } switch(reqinfo->mode) { /* the table_iterator helper should change all GETNEXTs into GETs for you automatically, so you don't have to worry about the GETNEXT case. Only GETs and SETs need to be dealt with here */ case MODE_GET: switch(table_info->colnum) { case COLUMN_ENTPHYSICALCHILDINDEX: snmp_set_var_typed_value(var, ASN_INTEGER, (u_char *) idx, sizeof(idx)); break; default: /* We shouldn't get here */ snmp_log(LOG_ERR, "problem encountered in entPhysicalContainsTable_handler: unknown column\n"); } break; case MODE_SET_RESERVE1: /* set handling... */ default: snmp_log(LOG_ERR, "problem encountered in entPhysicalContainsTable_handler: unsupported mode\n"); } } return SNMP_ERR_NOERROR; } /* Returns 0 for success 1 if the entry already exists -1 for failure -2 for stale index */ /* Fix for 4915033 */ int addPhysicalContainsTableEntry(int xentPhysicalIndex, int xentChildIndex) /* End of Fix for 4915033 */ { entPhysicalEntry_t *physentry, *childentry; physIndexAndChildIndex_t *zContainsTableEntry, *zRunner, *zlastEntry; int_l *zChildIndexes; /* Fix for 4890316: Check that adding itself as a child is not allowed */ if (xentPhysicalIndex == xentChildIndex) { return (-1); } /* End of Fix for 4890316 */ /* Fix for 48888088: -1 for invalid index, -2 for stale entries */ if (xentPhysicalIndex <= 0 || xentPhysicalIndex > MAX_ENTITY_INDEX || xentChildIndex <= 0 || xentChildIndex > MAX_ENTITY_INDEX) return -1; physentry = getPhysicalTableStaleEntry(xentPhysicalIndex); if (physentry != NULL) return -2; childentry = getPhysicalTableStaleEntry(xentChildIndex); if (childentry != NULL) return -2; /* End of Fix for 4888088 */ physentry = getPhysicalTableEntry(xentPhysicalIndex); childentry = getPhysicalTableEntry(xentChildIndex); if (physentry == NULL || childentry == NULL) { /* Handle error here. Send it to log files */ return (-1); } /* Fix for 4915080 */ if (isRecursiveChild(xentChildIndex, xentPhysicalIndex)) return (-1); /* End of Fix for 4915080 */ zlastEntry = NULL; zRunner = gPhyContainsTableHead; while (zRunner != NULL) { if (zRunner->entPhysicalIndex == xentPhysicalIndex) { break; } zlastEntry = zRunner; zRunner = zRunner->pNextEntry; } if (zRunner != NULL ) {/* Found a entry with log index */ int_l *p; p = zRunner->childIndexes; if (p == NULL) { zChildIndexes = (int_l *) malloc(2 * sizeof (int_l)); if (!zChildIndexes) return -1; zChildIndexes[0] = xentChildIndex; zChildIndexes[1] = 0; zRunner->childIndexes = zChildIndexes; } else {/* Add phy index to last entry in the array */ int i=0; int_l *empty = NULL; while (p != NULL && *p != 0) { if (*p == xentChildIndex) { /* Already in the array, return a 1 */ return (1); } if (*p == -1) /* Empty Slot */ empty = p; p++; i++; } if (empty) { /* Reuse a empty spot */ *empty = xentChildIndex; } else { zRunner->childIndexes = (int_l *)realloc(zRunner->childIndexes, (i + 2)*sizeof(int_l)); if (!zRunner->childIndexes) return -1; zRunner->childIndexes[i] = xentChildIndex; zRunner->childIndexes[i+1] = 0; } } /* Fix for 4891869: We replace entPhysicalContainedIn with this */ /* entry only when this index is lower */ if (childentry->entPhysicalContainedIn == 0 || childentry->entPhysicalContainedIn > xentPhysicalIndex) childentry->entPhysicalContainedIn = xentPhysicalIndex; /* End of Fix for 4891869 */ configChanged(); return (0); } /* New entry*/ zContainsTableEntry = (physIndexAndChildIndex_t *)malloc(sizeof(physIndexAndChildIndex_t)); if (!zContainsTableEntry) return -1; zContainsTableEntry->entPhysicalIndex = xentPhysicalIndex; zChildIndexes = (int_l *) malloc(2 * sizeof (int_l)); if (!zChildIndexes) return -1; zChildIndexes[0] = xentChildIndex; zChildIndexes[1] = 0; zContainsTableEntry->childIndexes = zChildIndexes; zContainsTableEntry->pNextEntry = NULL; if (zlastEntry){ zlastEntry->pNextEntry = zContainsTableEntry; } else { gPhyContainsTableHead = zContainsTableEntry; } /* Fix for 4891869: We replace entPhysicalContainedIn with this entry */ /* only when this index is lower */ if (childentry->entPhysicalContainedIn == 0 || childentry->entPhysicalContainedIn > xentPhysicalIndex) childentry->entPhysicalContainedIn = xentPhysicalIndex; /* End of Fix for 4891869 */ gPhyContainsTableSize++; configChanged(); return (0); } /* * Returns NULL if children, else returns int array with null termination * The array is not a copy and SHOULD NOT be written to unless the * intent is to update the master information */ /* Fix for 4915033 */ int *getPhysicalContainsChildren(int parentIndex) /* End of Fix for 4915033 */ { entPhysicalEntry_t *physentry; int_l *childIndexes=NULL; /* Fix for 4914153 */ int *resultIndexes=NULL, i = 0; /* End of Fix for 4914153 */ physIndexAndChildIndex_t *zRunner; /* * Find parent */ physentry = getPhysicalTableEntry(parentIndex); if (physentry == NULL) { return (NULL); /* assume no children */ } zRunner = gPhyContainsTableHead; while (zRunner != NULL) { if ((zRunner->entPhysicalIndex == parentIndex)) { childIndexes = zRunner->childIndexes; /* Fix for 4914153: From this childIndexes array, we only */ /* returns the true children array, excluding those "-1" entries */ if (childIndexes != NULL) { while (*childIndexes != 0) { /* We only need to count this entry if it is a valid */ /* (> -1) entry. Else we move on until the end of the */ /* list */ if (*childIndexes > 0) { resultIndexes = realloc(resultIndexes, (i + 1)*sizeof(int)); if (resultIndexes == NULL) return NULL; /* Not enough memory, just return NULL */ resultIndexes[i] = *childIndexes; i++; } childIndexes++; } } /* We can break here because this condition: */ /* zRunner->entPhysicalIndex == parentIndex condition */ /* can only happen once in the entPhysicalContains linked list */ break; /* End of Fix for 4914153 */ } zRunner = zRunner->pNextEntry; } /* Fix for 4914153: returns a NULL terminated list */ if (i > 0) /* at least one child is found */ resultIndexes = realloc(resultIndexes, (i + 1)*sizeof(int)); if (resultIndexes == NULL) /* Not enough memory or no child found -> NULL */ return NULL; resultIndexes[i] = 0; return (resultIndexes); /* End of Fix for 4914153 */ } /* Fix for 4915033 */ /* This function will delete all the entries which has the parent index = */ /* xParentIndex. */ /* Returns number of entries deleted for success, */ /* -1 if entry not found */ /* -2 if stale */ int deletePhysicalContainsParentIndex(int xParentIndex) { /* We go through the ContainsTable, and remove the parent */ physIndexAndChildIndex_t *zRunner, *prevEntry, *temp=NULL; int num=0; /* Fix for 4926042*/ int *childIndexes, *zchildIndexes; /* End of Fix for 4926042 */ int_l *childIndexes2; int lowest_index = 0; entPhysicalEntry_t *physentry; int num_child=0; /* Fix for 4888088 */ if (xParentIndex <= 0 || xParentIndex > MAX_ENTITY_INDEX) return -1; physentry = getPhysicalTableStaleEntry(xParentIndex); if (physentry != NULL) return -2; /* End of Fix for 4888088 */ zRunner = gPhyContainsTableHead; prevEntry = NULL; while (zRunner != NULL) { if (zRunner->entPhysicalIndex == xParentIndex) { temp = zRunner->pNextEntry; zRunner->pNextEntry = NULL; /* Fix for 4891869: we need to figure out the list of children */ /* belonging to this parent, before actually */ /* deleting the parent */ childIndexes = getPhysicalContainsChildren(xParentIndex); /* Fix for 4926042 */ zchildIndexes = childIndexes; /* End of Fix for 4926042 */ /* End of Fix for 4891869 */ if (prevEntry) prevEntry->pNextEntry = temp; else gPhyContainsTableHead = temp; FreePhyContainsTableEntry(zRunner); num++; gPhyContainsTableSize--; break; } prevEntry = zRunner; zRunner = zRunner->pNextEntry; } if (num) { /* Fix for 4891869: We need to sync the entPhysicalContainedIn */ /* 1. Find all the children that has this as a parent */ /* 2. If the parent is the last one for this child, reset the */ /* entPhysicalContainedIn to 0 */ /* 3. If more than one parent, and if this is the lowest index, */ /* then reset this to the next lowest */ /* 4. Otherwise do nothing */ num_child = 0; while (childIndexes != NULL && *childIndexes != 0) { physentry = getPhysicalTableEntry(*childIndexes); if (physentry != NULL) { /* Need to reset entPhysicalContainedIn only if the */ /* xParentIndex is already the lowest index. In this case, */ /* we will go through the ContainsTable and search for */ /* all the parents for this particular child, and set it */ /* to the second lowest index */ if (physentry->entPhysicalContainedIn == xParentIndex) { zRunner = gPhyContainsTableHead; lowest_index = 0; /* First reset to zero */ while (zRunner != NULL) { childIndexes2 = zRunner->childIndexes; while (childIndexes2 != NULL && *childIndexes2 != 0) { if (*childIndexes2 == *childIndexes) { if (lowest_index == 0) lowest_index = zRunner->entPhysicalIndex; else if (lowest_index > zRunner->entPhysicalIndex) lowest_index = zRunner->entPhysicalIndex; break; } childIndexes2++; } zRunner = zRunner->pNextEntry; } physentry->entPhysicalContainedIn = lowest_index; } } /* Fix for 4888088: count the number of children */ if (*childIndexes > 0) num_child++; /* End of Fix for 4888088 */ childIndexes++; } /* End of Fix for 4891869 */ configChanged(); /* Fix for 4926042 */ free (zchildIndexes); /* End of Fix for 4926042 */ return (num_child); } else { return (-1); } } /* This function will delete all the entries which has the child index = */ /* xChildIndex */ /* Returns number of entries deleted for success, */ /* -1 if entry not found */ /* -2 if entry is stale */ int deletePhysicalContainsChildIndex(int xChildIndex) { physIndexAndChildIndex_t *zRunner; int_l *childIndexes=NULL; int num=0; /* Fix for 4888088 */ entPhysicalEntry_t *physentry; if (xChildIndex <= 0 || xChildIndex > MAX_ENTITY_INDEX) return -1; physentry = getPhysicalTableStaleEntry(xChildIndex); if (physentry != NULL) return -2; /* End of Fix for 4888088 */ zRunner = gPhyContainsTableHead; while (zRunner != NULL) { childIndexes = zRunner->childIndexes; while (childIndexes != NULL && *childIndexes != 0) { if (*childIndexes == xChildIndex) { deletePhysicalContainsTableEntry((int)zRunner->entPhysicalIndex, xChildIndex); num++; } childIndexes++; } zRunner = zRunner->pNextEntry; } if (num) { configChanged(); return (num); } else { return (-1); } } /* Delete the entry specified by the xParentIndex and xChildIndex */ /* returns 0 if successful */ /* -1 if entry not found */ /* -2 if entry is stale */ int deletePhysicalContainsTableEntry(int xParentIndex, int xChildIndex) { physIndexAndChildIndex_t *zRunner; entPhysicalEntry_t *physentry; int zparentIdx; int num=0; int_l *childIndexes=NULL; int lowest_index = 0; /* Fix for 4888088 */ if (xParentIndex <= 0 || xParentIndex > MAX_ENTITY_INDEX || xChildIndex <= 0 || xChildIndex > MAX_ENTITY_INDEX) return -1; physentry = getPhysicalTableStaleEntry(xParentIndex); if (physentry != NULL) return -2; physentry = getPhysicalTableStaleEntry(xChildIndex); if (physentry != NULL) return -2; /* End of Fix for 4888088 */ zRunner = gPhyContainsTableHead; while (zRunner != NULL) { zparentIdx = zRunner->entPhysicalIndex; if (zparentIdx == xParentIndex) { childIndexes = zRunner->childIndexes; while (childIndexes != NULL && *childIndexes != 0) { if (*childIndexes == xChildIndex) { *childIndexes = -1; num++; } childIndexes++; } break; } zRunner = zRunner->pNextEntry; } if (num) { /* Fix for 4891869: we need to make sure that we reset the */ /* entPhysicalContainedIn when necessary */ physentry = getPhysicalTableEntry(xChildIndex); if (physentry != NULL) { if (physentry->entPhysicalContainedIn == xParentIndex) { /* we want to set entPhysicalContainedIn to the lowest value */ /* or to zero if necessary */ zRunner = gPhyContainsTableHead; while (zRunner != NULL) { childIndexes = zRunner->childIndexes; while (childIndexes != NULL && *childIndexes != 0) { if (*childIndexes == xChildIndex) { if (lowest_index == 0) lowest_index = zRunner->entPhysicalIndex; else if (lowest_index > zRunner->entPhysicalIndex) lowest_index = zRunner->entPhysicalIndex; break; } childIndexes++; } zRunner = zRunner->pNextEntry; } physentry->entPhysicalContainedIn = lowest_index; } } /* End of Fix for 4891869 */ configChanged(); return (0); } else { return (-1); } } /* End of Fix for 4915033 */ static int FreePhyContainsTableEntry(physIndexAndChildIndex_t *xEntry) { if (xEntry == NULL) return (-1); free(xEntry->childIndexes); free(xEntry); xEntry = NULL; return 0; } /* Fix for 4915080 */ /* Check to see if childIndex is really related to the parentIndex, in */ /* a directed graph way. Return 1 if it is related, 0 if not. */ static int isRecursiveChild(int parentIndex, int childIndex) { int i, ret; int *childlist; int *childlist2; i = 0; ret = 0; if (parentIndex == childIndex) return 1; /* Check for the entPhysicalContainedIn */ childlist = getAllChildrenFromPhysicalContainedIn(parentIndex); if (childlist != NULL) { while (childlist[i] != NULL) { ret = isRecursiveChild(childlist[i], childIndex); if (ret == 1) { free(childlist); return 1; } i++; } free(childlist); } /* Now we deal with the entPhysicalContainsTable */ childlist2 = getPhysicalContainsChildren(parentIndex); i = 0; if (childlist2 != NULL) { while (childlist2[i] != NULL) { ret = isRecursiveChild(childlist2[i], childIndex); if (ret == 1) { free(childlist2); return 1; } i++; } free(childlist2); } return 0; } /* End of Fix for 4915080 */