static void testInit(void) { BOOL (WINAPI *pInit)(DWORD, HANDLE *, AsnObjectIdentifier *); BOOL ret; HANDLE event; AsnObjectIdentifier oid; pInit = (void *)GetProcAddress(inetmib1, "SnmpExtensionInit"); if (!pInit) { win_skip("no SnmpExtensionInit\n"); return; } /* Crash ret = pInit(0, NULL, NULL); ret = pInit(0, NULL, &oid); ret = pInit(0, &event, NULL); */ ret = pInit(0, &event, &oid); ok(ret, "SnmpExtensionInit failed: %d\n", GetLastError()); ok(!strcmp("1.3.6.1.2.1.1", SnmpUtilOidToA(&oid)), "Expected 1.3.6.1.2.1.1, got %s\n", SnmpUtilOidToA(&oid)); SnmpUtilOidFree(&oid); }
// // SnmpSvcReleaseMessage // Releases all memory associated with a message. // // Notes: // // Return Codes: // SNMPAPI_NOERROR // SNMPAPI_ERROR // // Error Codes: // None. // SNMPAPI SNMP_FUNC_TYPE SnmpSvcReleaseMessage( IN OUT SnmpMgmtCom *snmpMgmtCom // Message to release ) { // Release source and destination OID SnmpUtilOidFree( &snmpMgmtCom->dstParty ); SnmpUtilOidFree( &snmpMgmtCom->srcParty ); // Free community if dynamic if ( snmpMgmtCom->community.dynamic ) { SnmpUtilMemFree( snmpMgmtCom->community.stream ); } // Release PDU return PDU_ReleaseAnyPDU( &snmpMgmtCom->pdu ); } // SnmpSvcReleaseMessage
VOID SNMP_FUNC_TYPE SnmpUtilVarBindFree(IN OUT RFC1157VarBind *VarBind) { BYTE asnType; // free object name SnmpUtilOidFree(&VarBind->name); asnType = VarBind->value.asnType; if(asnType==ASN_OBJECTIDENTIFIER){ SnmpUtilOidFree(&VarBind->value.asnValue.object); } else if( (asnType==ASN_OCTETSTRING) || (asnType==ASN_RFC1155_IPADDRESS) || (asnType==ASN_RFC1155_OPAQUE) || (asnType==ASN_SEQUENCE)){ if(VarBind->value.asnValue.string.dynamic){ GlobalFree(VarBind->value.asnValue.string.stream); } } VarBind->value.asnType = ASN_NULL; }
static BOOL mib2IfNumberQuery(BYTE bPduType, SnmpVarBind *pVarBind, AsnInteger32 *pErrorStatus) { AsnObjectIdentifier numberOid = DEFINE_OID(mib2IfNumber); BOOL ret = TRUE; TRACE("(0x%02x, %s, %p)\n", bPduType, SnmpUtilOidToA(&pVarBind->name), pErrorStatus); switch (bPduType) { case SNMP_PDU_GET: case SNMP_PDU_GETNEXT: if ((bPduType == SNMP_PDU_GET && !SnmpUtilOidNCmp(&pVarBind->name, &numberOid, numberOid.idLength)) || SnmpUtilOidNCmp(&pVarBind->name, &numberOid, numberOid.idLength) < 0) { DWORD numIfs = ifTable ? ifTable->dwNumEntries : 0; copyInt(&pVarBind->value, &numIfs); if (bPduType == SNMP_PDU_GETNEXT) { SnmpUtilOidFree(&pVarBind->name); SnmpUtilOidCpy(&pVarBind->name, &numberOid); } *pErrorStatus = SNMP_ERRORSTATUS_NOERROR; } else { *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME; /* Caller deals with OID if bPduType == SNMP_PDU_GETNEXT, so don't * need to set it here. */ } break; case SNMP_PDU_SET: *pErrorStatus = SNMP_ERRORSTATUS_READONLY; ret = FALSE; break; default: FIXME("0x%02x: unsupported PDU type\n", bPduType); *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME; } return ret; }
static INT setOidWithItem(AsnObjectIdentifier *dst, AsnObjectIdentifier *base, UINT item) { UINT id; AsnObjectIdentifier oid; INT ret; SnmpUtilOidFree(dst); ret = SnmpUtilOidCpy(dst, base); if (ret) { oid.idLength = 1; oid.ids = &id; id = item; ret = SnmpUtilOidAppend(dst, &oid); } return ret; }
// // MIB_odom_lmget // Retrieve print queue table information from Lan Manager. // If not cached, sort it and then // cache it. // // Notes: // // Return Codes: // SNMPAPI_NOERROR // SNMPAPI_ERROR // // Error Codes: // None. // SNMPAPI MIB_odoms_lmget( ) { DWORD totalentries; LPBYTE bufptr; unsigned lmCode; WKSTA_USER_INFO_1 *DataTable; DOM_OTHER_ENTRY *MIB_DomOtherDomainTableElement ; char *p; char *next; time_t curr_time ; unsigned i; SNMPAPI nResult = SNMPAPI_NOERROR; time(&curr_time); // get the time // // // If cached, return piece of info. // // if((NULL != cache_table[C_ODOM_TABLE].bufptr) && (curr_time < (cache_table[C_ODOM_TABLE].acquisition_time + cache_expire[C_ODOM_TABLE] ) ) ) { // it has NOT expired! goto Exit; // the global table is valid } // // // Do network call to gather information and put it in a nice array // // // // remember to free the existing data // MIB_DomOtherDomainTableElement = MIB_DomOtherDomainTable.Table ; // iterate over the whole table for(i=0; i<MIB_DomOtherDomainTable.Len ;i++) { // free any alloc'ed elements of the structure SnmpUtilOidFree(&(MIB_DomOtherDomainTableElement->Oid)); SafeFree(MIB_DomOtherDomainTableElement->domOtherName.stream); MIB_DomOtherDomainTableElement ++ ; // increment table entry } SafeFree(MIB_DomOtherDomainTable.Table) ; // free the base Table MIB_DomOtherDomainTable.Table = NULL ; // just for safety MIB_DomOtherDomainTable.Len = 0 ; // just for safety lmCode = NetWkstaUserGetInfo( 0, // required 1, // level 0, &bufptr // data structure to return ); DataTable = (WKSTA_USER_INFO_1 *) bufptr ; if((NERR_Success == lmCode) || (ERROR_MORE_DATA == lmCode)) { // valid so process it, otherwise error if(NULL==DataTable->wkui1_oth_domains) { totalentries = 0; // alloc the table space MIB_DomOtherDomainTable.Table = SnmpUtilMemAlloc(totalentries * sizeof(DOM_OTHER_ENTRY) ); } else { // compute it totalentries = chrcount((char *)DataTable->wkui1_oth_domains); if(0 == MIB_DomOtherDomainTable.Len) { // 1st time, alloc the whole table // alloc the table space MIB_DomOtherDomainTable.Table = SnmpUtilMemAlloc(totalentries * sizeof(DOM_OTHER_ENTRY) ); } MIB_DomOtherDomainTableElement = MIB_DomOtherDomainTable.Table ; // make a pointer to the beginning of the string field #ifdef UNICODE SnmpUtilUnicodeToAnsi( &p, DataTable->wkui1_oth_domains, TRUE); #else p = DataTable->wkui1_oth_domains ; #endif // scan through the field, making an entry for each space // separated domain while( (NULL != p ) & ('\0' != *p) ) { // once for each entry in the buffer // increment the entry number MIB_DomOtherDomainTable.Len ++; // find the end of this one next = strchr(p,' '); // if more to come, ready next pointer and mark end of this one if(NULL != next) { *next='\0' ; // replace space with EOS next++ ; // point to beginning of next domain } MIB_DomOtherDomainTableElement->domOtherName.stream = SnmpUtilMemAlloc ( strlen( p ) ) ; MIB_DomOtherDomainTableElement->domOtherName.length = strlen( p ) ; MIB_DomOtherDomainTableElement->domOtherName.dynamic = TRUE; memcpy( MIB_DomOtherDomainTableElement->domOtherName.stream, p, strlen( p ) ) ; MIB_DomOtherDomainTableElement ++ ; // and table entry DataTable ++ ; // advance pointer to next sess entry in buffer } // while still more to do } // if there really were entries } // if data is valid to process else { // Signal error nResult = SNMPAPI_ERROR; goto Exit; } // free all of the lan man data SafeBufferFree( bufptr ) ; // iterate over the table populating the Oid field build_odom_entry_oids(); // Sort the table information using MSC QuickSort routine qsort( (void *)&MIB_DomOtherDomainTable.Table[0], (size_t)MIB_DomOtherDomainTable.Len, (size_t)sizeof(DOM_OTHER_ENTRY), odom_entry_cmp ); // // // Cache table // // if(0 != MIB_DomOtherDomainTable.Len) { cache_table[C_ODOM_TABLE].acquisition_time = curr_time ; cache_table[C_ODOM_TABLE].bufptr = bufptr ; } // // // Return piece of information requested // // Exit: return nResult; } // MIB_odom_get
BOOL CSNMP::SnmpQueryTable( LPCTSTR apColumnOidList[], UINT nListLen, std::vector<std::pair<CString, std::vector<AsnAny>>> *pTable ) { if (!apColumnOidList || !pTable) { m_strLastError = L"[SnmpQueryTable] : Verify the arguments failed. "; return FALSE; } pTable->clear(); if (!nListLen) return TRUE; typedef std::map<CString, AsnAny> RELATIVE_OID_TO_VALUE_MAP; std::vector<RELATIVE_OID_TO_VALUE_MAP> vColumnRelativeOidToValue(nListLen); SnmpVarBindList CurrentVarBindList; CurrentVarBindList.len = 0; CurrentVarBindList.list = NULL; AsnObjectIdentifier TargetObjectIdentifier; TargetObjectIdentifier.idLength = 0; TargetObjectIdentifier.ids = NULL; BOOL bRes = FALSE; do { UINT i = 0; for (; i < nListLen; i++) { SnmpUtilVarBindListFree(&CurrentVarBindList); CurrentVarBindList.len = 1; CurrentVarBindList.list = (SnmpVarBind *)SnmpUtilMemAlloc(sizeof(SnmpVarBind)); CurrentVarBindList.list->name.idLength = 0; CurrentVarBindList.list->name.ids = NULL; CurrentVarBindList.list->value.asnType = ASN_NULL; #ifdef _UNICODE CStringA strOIDA = XLibS::StringCode::ConvertWideStrToAnsiStr(apColumnOidList[i]); #else CStringA strOIDA = apColumnOidList[i]; #endif if(!::SnmpMgrStrToOid(strOIDA.GetBuffer(), &CurrentVarBindList.list->name) || !CurrentVarBindList.list->name.ids || !CurrentVarBindList.list->name.idLength) { #ifdef _UNICODE CStringW strOIDW = apColumnOidList[i]; #else CStringW strOIDW = XLibS::StringCode::ConvertAnsiStrToWideStr(apColumnOidList[i]); #endif m_strLastError.Format(L"[SnmpQueryTable] : Bad OID string \"%s\". ", (LPCWSTR)strOIDW); strOIDA.ReleaseBuffer(); break; } strOIDA.ReleaseBuffer(); SnmpUtilOidFree(&TargetObjectIdentifier); TargetObjectIdentifier.idLength = 0; TargetObjectIdentifier.ids = NULL; if (!SnmpUtilOidCpy(&TargetObjectIdentifier, &CurrentVarBindList.list->name) || !TargetObjectIdentifier.ids || !TargetObjectIdentifier.idLength) { m_strLastError.Format(L"[SnmpQueryTable] : Copy OID failed. "); break; } BOOL bFailFlag = FALSE; while(1) { AsnInteger nSNMPErrorCode = 0; AsnInteger nSNMPErrorIndex = 0; if(!::SnmpMgrRequest(m_SnmpSession, SNMP_PDU_GETNEXT, &CurrentVarBindList, &nSNMPErrorCode, &nSNMPErrorIndex)) { DWORD dwLastWinError = ::GetLastError(); assert(nSNMPErrorIndex == 0); const WCHAR * SNMP_ERROR_MESSAGE[] = { L"The agent reports that no errors occurred during transmission. ", L"The agent could not place the results of the requested operation into a single SNMP message. ", L"The requested operation identified an unknown variable. ", L"The requested operation tried to change a variable but it specified either a syntax or value error. ", L"The requested operation tried to change a variable that was not allowed to change according to the community profile of the variable. " }; const WCHAR * WIN_ERROR_MESSAGE[] = {L"The request timed-out.", L"Unexpected error file descriptors indicated by the Windows Sockets select function." }; const WCHAR *pSNMPError = NULL; if (nSNMPErrorIndex < ARRAYSIZE(SNMP_ERROR_MESSAGE)) pSNMPError = SNMP_ERROR_MESSAGE[nSNMPErrorIndex]; else pSNMPError = L"Unknown error. "; const WCHAR *pWinError = NULL; if (dwLastWinError - 40 < ARRAYSIZE(WIN_ERROR_MESSAGE)) pWinError = WIN_ERROR_MESSAGE[dwLastWinError - 40]; else pWinError = L"Unknown error. "; m_strLastError.Format(L"SNMP requesting failed. SNMP ERROR : %s (%ld). WIN ERROR : %s (%lu). ", pSNMPError, nSNMPErrorIndex, pWinError, dwLastWinError); // LPCWSTR pSysError = NULL; // m_strLastError.Format(L"SNMP requesting failed. SNMP ERROR : %s (%ld). ", pError, nErrorIndex); // if (::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, // NULL, dwLastError, 0, (LPTSTR)&pSysError, 0, NULL) && pSysError) // { // m_strLastError.AppendFormat(L"Windows ERROR: %s (%lu). ", pSysError, dwLastError); // // ::LocalFree((HLOCAL)pSysError); // pSysError = NULL; // } bFailFlag = TRUE; break; } assert(SNMP_ERRORSTATUS_NOERROR == nSNMPErrorCode); if (!CurrentVarBindList.list || (!CurrentVarBindList.list->name.ids && CurrentVarBindList.list->name.idLength)) { #ifdef _UNICODE CStringW strOIDW = apColumnOidList[i]; #else CStringW strOIDW = XLibS::StringCode::ConvertAnsiStrToWideStr(apColumnOidList[i]); #endif m_strLastError.Format(L"[SnmpQueryTable] : GetNext returned a bad OID during the request for %s. ", (LPCWSTR)strOIDW); bFailFlag = TRUE; break; } if (CurrentVarBindList.list->name.idLength < TargetObjectIdentifier.idLength) break; if (SnmpUtilOidNCmp(&CurrentVarBindList.list->name, &TargetObjectIdentifier, TargetObjectIdentifier.idLength)) break; CStringA strOIDTarget = ThreadSafeSnmpUtilOidToA(&TargetObjectIdentifier); CStringA strOIDCurrent = ThreadSafeSnmpUtilOidToA(&CurrentVarBindList.list->name); assert(strOIDCurrent.Find(strOIDTarget) == 0); AsnAny value; SnmpUtilAsnAnyCpy(&value, &CurrentVarBindList.list->value); #ifdef _UNICODE CString strRelativeOID = XLibS::StringCode::ConvertAnsiStrToWideStr(strOIDCurrent.Mid(strOIDTarget.GetLength())); #else CString strRelativeOID = strOIDCurrent.Mid(strOIDTarget.GetLength()); #endif vColumnRelativeOidToValue[i].insert(std::make_pair(strRelativeOID, value)); } if (bFailFlag) break; } if (i < nListLen) break; const RELATIVE_OID_TO_VALUE_MAP & FirstCol = vColumnRelativeOidToValue[0]; for (RELATIVE_OID_TO_VALUE_MAP::const_iterator itFirstCol = FirstCol.begin(); itFirstCol != FirstCol.end(); itFirstCol++) { std::vector<RELATIVE_OID_TO_VALUE_MAP::const_iterator> vItFind; UINT i = 1; for (; i < nListLen; i++) { const RELATIVE_OID_TO_VALUE_MAP & CurrentCol = vColumnRelativeOidToValue[i]; RELATIVE_OID_TO_VALUE_MAP::const_iterator itFind = CurrentCol.find(itFirstCol->first); if (itFind == CurrentCol.end()) break; vItFind.push_back(itFind); } if (i < nListLen) continue; pTable->push_back(make_pair(itFirstCol->first, std::vector<AsnAny>(1, itFirstCol->second))); for (std::vector<RELATIVE_OID_TO_VALUE_MAP::const_iterator>::size_type i = 0; i < vItFind.size(); i++) { pTable->back().second.push_back(vItFind[i]->second); } } bRes = TRUE; } while (FALSE); SnmpUtilOidFree(&TargetObjectIdentifier); SnmpUtilVarBindListFree(&CurrentVarBindList); if (!bRes) { ClearQueryTableResult(*pTable); pTable->clear(); } return bRes; }
BOOL WINAPI SnmpExtensionQuery( IN BYTE requestType, IN OUT RFC1157VarBindList *variableBindings, OUT AsnInteger *errorStatus, OUT AsnInteger *errorIndex) { static unsigned long requestCount = 0; // Supports the trap simulation. UINT I; // Iterate through the variable bindings list to resolve individual // variable bindings. for ( I=0;I < variableBindings->len;I++ ) { *errorStatus = ResolveVarBind( &variableBindings->list[I], requestType ); // Test and handle case where Get Next past end of MIB view supported // by this Extension Agent occurs. Special processing is required to // communicate this situation to the Extendible Agent so it can take // appropriate action, possibly querying other Extension Agents. if ( *errorStatus == SNMP_ERRORSTATUS_NOSUCHNAME && requestType == MIB_ACTION_GETNEXT ) { *errorStatus = SNMP_ERRORSTATUS_NOERROR; // Modify variable binding of such variables so the OID points // just outside the MIB view supported by this Extension Agent. // The Extendible Agent tests for this, and takes appropriate // action. SnmpUtilOidFree( &variableBindings->list[I].name ); SnmpUtilOidCpy( &variableBindings->list[I].name, &MIB_OidPrefix ); variableBindings->list[I].name.ids[MIB_PREFIX_LEN-1] ++; } // If an error was indicated, communicate error status and error // index to the Extendible Agent. The Extendible Agent will ensure // that the origional variable bindings are returned in the response // packet. if ( *errorStatus != SNMP_ERRORSTATUS_NOERROR ) { *errorIndex = I+1; goto Exit; } } Exit: // Supports the trap simulation. if (++requestCount % 3 == 0 && hSimulateTrap != NULL) SetEvent(hSimulateTrap); // Indicate that Extension Agent processing was sucessfull. return SNMPAPI_NOERROR; } // end SnmpExtensionQuery()
// // MIB_user_lmget // Retrieve print queue table information from Lan Manager. // If not cached, sort it and then // cache it. // // Notes: // // Return Codes: // SNMPAPI_NOERROR // SNMPAPI_ERROR // // Error Codes: // None. // SNMPAPI MIB_users_lmget( ) { DWORD entriesread; DWORD totalentries; LPBYTE bufptr; unsigned lmCode; unsigned i; USER_INFO_0 *DataTable; USER_ENTRY *MIB_UserTableElement ; int First_of_this_block; LPSTR ansi_string; time_t curr_time ; SNMPAPI nResult = SNMPAPI_NOERROR; DWORD resumehandle=0; time(&curr_time); // get the time // // // If cached, return piece of info. // // if((NULL != cache_table[C_USER_TABLE].bufptr) && (curr_time < (cache_table[C_USER_TABLE].acquisition_time + cache_expire[C_USER_TABLE] ) ) ) { // it has NOT expired! goto Exit ; // the global table is valid } // // // Do network call to gather information and put it in a nice array // // // // remember to free the existing data // MIB_UserTableElement = MIB_UserTable.Table ; // iterate over the whole table for(i=0; i<MIB_UserTable.Len ;i++) { // free any alloc'ed elements of the structure SnmpUtilOidFree(&(MIB_UserTableElement->Oid)); SafeFree(MIB_UserTableElement->svUserName.stream); MIB_UserTableElement ++ ; // increment table entry } SafeFree(MIB_UserTable.Table) ; // free the base Table MIB_UserTable.Table = NULL ; // just for safety MIB_UserTable.Len = 0 ; // just for safety #if 0 // done above // init the length MIB_UserTable.Len = 0; #endif First_of_this_block = 0; do { // as long as there is more data to process lmCode = NetUserEnum( NULL, // local server 0, // level 0, no admin priv. FILTER_NORMAL_ACCOUNT, &bufptr, // data structure to return MAX_PREFERRED_LENGTH, &entriesread, &totalentries, &resumehandle // resume handle ); DataTable = (USER_INFO_0 *) bufptr ; if((NERR_Success == lmCode) || (ERROR_MORE_DATA == lmCode)) { // valid so process it, otherwise error if(0 == MIB_UserTable.Len) { // 1st time, alloc the whole table // alloc the table space MIB_UserTable.Table = SnmpUtilMemAlloc(totalentries * sizeof(USER_ENTRY) ); } MIB_UserTableElement = MIB_UserTable.Table + First_of_this_block ; for(i=0; i<entriesread; i++) { // once for each entry in the buffer // increment the entry number MIB_UserTable.Len ++; // Stuff the data into each item in the table // convert the undocumented unicode to something readable SnmpUtilUnicodeToAnsi( &ansi_string, DataTable->usri0_name, TRUE ); // auto alloc the space for ansi // client name MIB_UserTableElement->svUserName.stream = ansi_string; MIB_UserTableElement->svUserName.length = strlen( ansi_string ) ; MIB_UserTableElement->svUserName.dynamic = TRUE; ansi_string = NULL; MIB_UserTableElement ++ ; // and table entry DataTable ++ ; // advance pointer to next sess entry in buffer } // for each entry in the data table // free all of the lan man data SafeBufferFree( bufptr ) ; // indicate where to start adding on next pass, if any First_of_this_block = i ; } // if data is valid to process else { // Signal error nResult = SNMPAPI_ERROR; goto Exit; } } while (ERROR_MORE_DATA == lmCode) ; // iterate over the table populating the Oid field build_user_entry_oids(); // Sort the table information using MSC QuickSort routine qsort( &MIB_UserTable.Table[0], MIB_UserTable.Len, sizeof(USER_ENTRY), user_entry_cmp ); // // // Cache table // // if(0 != MIB_UserTable.Len) { cache_table[C_USER_TABLE].acquisition_time = curr_time ; cache_table[C_USER_TABLE].bufptr = bufptr ; } // // // Return piece of information requested // // Exit: return nResult; } // MIB_user_get
/***************************************************************************** * SnmpExtensionQuery [INETMIB1.@] */ BOOL WINAPI SnmpExtensionQuery(BYTE bPduType, SnmpVarBindList *pVarBindList, AsnInteger32 *pErrorStatus, AsnInteger32 *pErrorIndex) { AsnObjectIdentifier mib2oid = DEFINE_OID(mib2); AsnInteger32 error = SNMP_ERRORSTATUS_NOERROR, errorIndex = 0; UINT i; BOOL ret = TRUE; TRACE("(0x%02x, %p, %p, %p)\n", bPduType, pVarBindList, pErrorStatus, pErrorIndex); for (i = 0; !error && i < pVarBindList->len; i++) { /* Ignore any OIDs not in MIB2 */ if (!SnmpUtilOidNCmp(&pVarBindList->list[i].name, &mib2oid, mib2oid.idLength)) { struct mibImplementation *impl = NULL; UINT len, matchingIndex = 0; TRACE("%s\n", SnmpUtilOidToA(&pVarBindList->list[i].name)); /* Search for an implementation matching as many octets as possible */ for (len = pVarBindList->list[i].name.idLength; len >= minSupportedIDLength && !impl; len--) impl = findSupportedQuery(pVarBindList->list[i].name.ids, len, &matchingIndex); if (impl && impl->query) ret = impl->query(bPduType, &pVarBindList->list[i], &error); else error = SNMP_ERRORSTATUS_NOSUCHNAME; if (error == SNMP_ERRORSTATUS_NOSUCHNAME && bPduType == SNMP_PDU_GETNEXT) { /* GetNext is special: it finds the successor to the given OID, * so we have to continue until an implementation handles the * query or we exhaust the table of supported OIDs. */ for (matchingIndex++; error == SNMP_ERRORSTATUS_NOSUCHNAME && matchingIndex < DEFINE_SIZEOF(supportedIDs); matchingIndex++) { error = SNMP_ERRORSTATUS_NOERROR; impl = &supportedIDs[matchingIndex]; if (impl->query) ret = impl->query(bPduType, &pVarBindList->list[i], &error); else error = SNMP_ERRORSTATUS_NOSUCHNAME; } /* If the query still isn't resolved, set the OID to the * successor to the last entry in the table. */ if (error == SNMP_ERRORSTATUS_NOSUCHNAME) { SnmpUtilOidFree(&pVarBindList->list[i].name); ret = SnmpUtilOidCpy(&pVarBindList->list[i].name, &supportedIDs[matchingIndex - 1].name); pVarBindList->list[i].name.ids[ pVarBindList->list[i].name.idLength - 1] += 1; } } if (error) errorIndex = i + 1; } } *pErrorStatus = error; *pErrorIndex = errorIndex; return ret; }
// // MIB_sess_func // High level routine for handling operations on the session table // // Notes: // // Return Codes: // None. // // Error Codes: // None. // UINT MIB_sess_func( IN UINT Action, IN MIB_ENTRY *MibPtr, IN OUT RFC1157VarBind *VarBind ) { int Found; UINT Entry; UINT Field; UINT ErrStat; switch ( Action ) { case MIB_ACTION_GETFIRST: // Fill the Session table with the info from server if ( SNMPAPI_ERROR == MIB_sess_lmget() ) { ErrStat = SNMP_ERRORSTATUS_GENERR; goto Exit; } // If no elements in table, then return next MIB var, if one if ( MIB_SessionTable.Len == 0 ) { if ( MibPtr->MibNext == NULL ) { ErrStat = SNMP_ERRORSTATUS_NOSUCHNAME; goto Exit; } // Do get first on the next MIB var ErrStat = (*MibPtr->MibNext->MibFunc)( Action, MibPtr->MibNext, VarBind ); break; } // // Place correct OID in VarBind // Assuming the first field in the first record is the "start" { UINT temp_subs[] = { SESS_FIRST_FIELD }; AsnObjectIdentifier FieldOid = { 1, temp_subs }; SnmpUtilOidFree( &VarBind->name ); SnmpUtilOidCpy( &VarBind->name, &MIB_OidPrefix ); SnmpUtilOidAppend( &VarBind->name, &MIB_SessPrefix ); SnmpUtilOidAppend( &VarBind->name, &FieldOid ); SnmpUtilOidAppend( &VarBind->name, &MIB_SessionTable.Table[0].Oid ); } // // Let fall through on purpose // case MIB_ACTION_GET: ErrStat = MIB_sess_get( VarBind ); break; case MIB_ACTION_GETNEXT: // Fill the Session table with the info from server if ( SNMPAPI_ERROR == MIB_sess_lmget() ) { ErrStat = SNMP_ERRORSTATUS_GENERR; goto Exit; } // Lookup OID in table Found = MIB_sess_match( &VarBind->name, &Entry, TRUE ); // Determine which field Field = VarBind->name.ids[SESS_FIELD_SUBID]; // Index not found, but could be more fields to base GET on if ( Found == MIB_TBL_POS_END ) { // Index not found in table, get next from field // Field ++; // Make sure not past last field // if ( Field > SESS_LAST_FIELD ) // { // Get next VAR in MIB ErrStat = (*MibPtr->MibNext->MibFunc)( MIB_ACTION_GETFIRST, MibPtr->MibNext, VarBind ); break; // } } // Get next TABLE entry if ( Found == MIB_TBL_POS_FOUND ) { Entry ++; if ( Entry > MIB_SessionTable.Len-1 ) { Entry = 0; Field ++; /* item not implemented. Skip */ if (Field == SESS_NUMCONS_FIELD) { Field++; } if ( Field > SESS_LAST_FIELD ) { // Get next VAR in MIB ErrStat = (*MibPtr->MibNext->MibFunc)( MIB_ACTION_GETFIRST, MibPtr->MibNext, VarBind ); break; } } } // // Place correct OID in VarBind // Assuming the first field in the first record is the "start" { UINT temp_subs[1]; AsnObjectIdentifier FieldOid; temp_subs[0] = Field; FieldOid.idLength = 1; FieldOid.ids = temp_subs; SnmpUtilOidFree( &VarBind->name ); SnmpUtilOidCpy( &VarBind->name, &MIB_OidPrefix ); SnmpUtilOidAppend( &VarBind->name, &MIB_SessPrefix ); SnmpUtilOidAppend( &VarBind->name, &FieldOid ); SnmpUtilOidAppend( &VarBind->name, &MIB_SessionTable.Table[Entry].Oid ); } ErrStat = MIB_sess_copyfromtable( Entry, Field, VarBind ); break; case MIB_ACTION_SET: // Make sure OID is long enough if ( SESS_FIELD_SUBID + 1 > VarBind->name.idLength ) { ErrStat = SNMP_ERRORSTATUS_NOSUCHNAME; goto Exit; } // Get field number Field = VarBind->name.ids[SESS_FIELD_SUBID]; // If the field being set is not the STATE field, error if ( Field != SESS_STATE_FIELD ) { ErrStat = SNMP_ERRORSTATUS_NOSUCHNAME; goto Exit; } // Check for proper type before setting if ( ASN_INTEGER != VarBind->value.asnType ) { ErrStat = SNMP_ERRORSTATUS_BADVALUE; goto Exit; } // Make sure that the value is valid if ( VarBind->value.asnValue.number < SESS_STATE_ACTIVE && VarBind->value.asnValue.number > SESS_STATE_DELETED ) { ErrStat = SNMP_ERRORSTATUS_BADVALUE; goto Exit; } ErrStat = MIB_sess_lmset( &VarBind->name, Field, &VarBind->value ); break; default: ErrStat = SNMP_ERRORSTATUS_GENERR; } Exit: return ErrStat; } // MIB_sess_func
// Main program. INT _CRTAPI1 main( IN int argumentCount, IN char *argumentVector[]) { INT operation; LPSTR agent = NULL; LPSTR community = NULL; RFC1157VarBindList variableBindings; LPSNMP_MGR_SESSION session = NULL; INT timeout = TIMEOUT; INT retries = RETRIES; BYTE requestType; AsnInteger errorStatus; AsnInteger errorIndex; // Parse command line arguments to determine requested operation. // Verify number of arguments... if (argumentCount < 5 && argumentCount != 2) { printf("Error: Incorrect number of arguments specified.\n"); printf( "\nusage: snmputil [get|getnext|walk] agent community oid [oid ...]\n"); printf( " snmputil trap\n"); return 1; } // Get/verify operation... argumentVector++; argumentCount--; if (!strcmp(*argumentVector, "get")) operation = GET; else if (!strcmp(*argumentVector, "getnext")) operation = GETNEXT; else if (!strcmp(*argumentVector, "walk")) operation = WALK; else if (!strcmp(*argumentVector, "trap")) operation = TRAP; else { printf("Error: Invalid operation, '%s', specified.\n", *argumentVector); return 1; } if (operation != TRAP) { if (argumentCount < 4) { printf("Error: Incorrect number of arguments specified.\n"); printf( "\nusage: snmputil [get|getnext|walk] agent community oid [oid ...]\n"); printf( " snmputil trap\n"); return 1; } // Get agent address... argumentVector++; argumentCount--; agent = (LPSTR)SnmpUtilMemAlloc((UINT)(strlen(*argumentVector) + 1)); if (agent != NULL) StringCchCopyA(agent, strlen(*argumentVector) + 1, *argumentVector); else { printf("Error: SnmpUtilMemAlloc failed to allocate memory.\n"); return 1; } // Get agent community... argumentVector++; argumentCount--; community = (LPSTR)SnmpUtilMemAlloc((UINT)(strlen(*argumentVector) + 1)); if (community != NULL) StringCchCopyA(community, strlen(*argumentVector) + 1, *argumentVector); else { printf("Error: SnmpUtilMemAlloc failed to allocate memory.\n"); SnmpUtilMemFree(agent); return 1; } // Get oid's... variableBindings.list = NULL; variableBindings.len = 0; while(--argumentCount) { AsnObjectIdentifier reqObject; RFC1157VarBind * tmpVb; argumentVector++; // Convert the string representation to an internal representation. if (!SnmpMgrStrToOid(*argumentVector, &reqObject)) { printf("Error: Invalid oid, %s, specified.\n", *argumentVector); SnmpUtilMemFree(agent); SnmpUtilMemFree(community); SnmpUtilVarBindListFree(&variableBindings); return 1; } else { // Since sucessfull, add to the variable bindings list. variableBindings.len++; if ((tmpVb = (RFC1157VarBind *)SnmpUtilMemReAlloc( variableBindings.list, sizeof(RFC1157VarBind) * variableBindings.len)) == NULL) { printf("Error: Error allocating oid, %s.\n", *argumentVector); SnmpUtilMemFree(agent); SnmpUtilMemFree(community); SnmpUtilOidFree(&reqObject); variableBindings.len--; SnmpUtilVarBindListFree(&variableBindings); return 1; } variableBindings.list = tmpVb; variableBindings.list[variableBindings.len - 1].name = reqObject; // NOTE! structure copy variableBindings.list[variableBindings.len - 1].value.asnType = ASN_NULL; } } // end while() // Make sure only one variable binding was specified if operation // is WALK. if (operation == WALK && variableBindings.len != 1) { printf("Error: Multiple oids specified for WALK.\n"); SnmpUtilMemFree(agent); SnmpUtilMemFree(community); SnmpUtilVarBindListFree(&variableBindings); return 1; } // Establish a SNMP session to communicate with the remote agent. The // community, communications timeout, and communications retry count // for the session are also required. if ((session = SnmpMgrOpen(agent, community, timeout, retries)) == NULL) { printf("error on SnmpMgrOpen %d\n", GetLastError()); SnmpUtilMemFree(agent); SnmpUtilMemFree(community); SnmpUtilVarBindListFree(&variableBindings); return 1; } } // end if(TRAP) // Determine and perform the requested operation. if (operation == GET || operation == GETNEXT) { // Get and GetNext are relatively simple operations to perform. // Simply initiate the request and process the result and/or // possible error conditions. if (operation == GET) requestType = ASN_RFC1157_GETREQUEST; else requestType = ASN_RFC1157_GETNEXTREQUEST; // Request that the API carry out the desired operation. if (!SnmpMgrRequest(session, requestType, &variableBindings, &errorStatus, &errorIndex)) { // The API is indicating an error. printf("error on SnmpMgrRequest %d\n", GetLastError()); } else { // The API succeeded, errors may be indicated from the remote // agent. if (errorStatus > 0) { printf("Error: errorStatus=%d, errorIndex=%d\n", errorStatus, errorIndex); } else { // Display the resulting variable bindings. UINT i; for(i=0; i < variableBindings.len; i++) { char *string = NULL; if (SnmpMgrOidToStr(&variableBindings.list[i].name, &string)) { printf("Variable = %s\n", string); if (string) SnmpUtilMemFree(string); } printf("Value = "); SnmpUtilPrintAsnAny(&variableBindings.list[i].value); printf("\n"); } // end for() } } // Free the variable bindings that have been allocated. SnmpUtilVarBindListFree(&variableBindings); // Free other allocated resources SnmpUtilMemFree(agent); SnmpUtilMemFree(community); } else if (operation == WALK) { // Walk is a common term used to indicate that all MIB variables // under a given OID are to be traversed and displayed. This is // a more complex operation requiring tests and looping in addition // to the steps for get/getnext above. AsnObjectIdentifier root; AsnObjectIdentifier tempOid; if (!SnmpUtilOidCpy(&root, &variableBindings.list[0].name)) { printf("error on SnmpUtilOidCpy\n"); SnmpUtilMemFree(agent); SnmpUtilMemFree(community); SnmpUtilVarBindListFree(&variableBindings); return 1; } requestType = ASN_RFC1157_GETNEXTREQUEST; while(1) { if (!SnmpMgrRequest(session, requestType, &variableBindings, &errorStatus, &errorIndex)) { // The API is indicating an error. printf("error on SnmpMgrRequest %d\n", GetLastError()); break; } else { // The API succeeded, errors may be indicated from the remote // agent. // Test for end of subtree or end of MIB. if (errorStatus == SNMP_ERRORSTATUS_NOSUCHNAME || SnmpUtilOidNCmp(&variableBindings.list[0].name, &root, root.idLength)) { printf("End of MIB subtree.\n\n"); break; } // Test for general error conditions or sucesss. if (errorStatus > 0) { printf("Error: errorStatus=%d, errorIndex=%d \n", errorStatus, errorIndex); break; } else { // Display resulting variable binding for this iteration. char *string = NULL; if (SnmpMgrOidToStr(&variableBindings.list[0].name, &string)) { printf("Variable = %s\n", string); if (string) SnmpUtilMemFree(string); } printf("Value = "); SnmpUtilPrintAsnAny(&variableBindings.list[0].value); printf("\n"); } } // end if() // Prepare for the next iteration. Make sure returned oid is // preserved and the returned value is freed. if (!SnmpUtilOidCpy(&tempOid, &variableBindings.list[0].name)) { printf("error on SnmpUtilOidCpy\n"); SnmpUtilOidFree(&root); SnmpUtilMemFree(agent); SnmpUtilMemFree(community); SnmpUtilVarBindListFree(&variableBindings); return 1; } SnmpUtilVarBindFree(&variableBindings.list[0]); if (!SnmpUtilOidCpy(&variableBindings.list[0].name, &tempOid)) { printf("error on SnmpUtilOidCpy\n"); SnmpUtilOidFree(&tempOid); SnmpUtilOidFree(&root); SnmpUtilMemFree(agent); SnmpUtilMemFree(community); SnmpUtilVarBindListFree(&variableBindings); return 1; } variableBindings.list[0].value.asnType = ASN_NULL; SnmpUtilOidFree(&tempOid); } // end while() // Free the variable bindings that have been allocated. SnmpUtilVarBindListFree(&variableBindings); // Free other allocated resources SnmpUtilOidFree(&root); SnmpUtilMemFree(agent); SnmpUtilMemFree(community); } else if (operation == TRAP) { // Trap handling can be done two different ways: event driven or // polled. The following code illustrates the steps to use event // driven trap reception in a management application. HANDLE hNewTraps = NULL; if (!SnmpMgrTrapListen(&hNewTraps)) { printf("error on SnmpMgrTrapListen %d\n", GetLastError()); return 1; } else { printf("snmputil: listening for traps...\n"); } while(1) { DWORD dwResult; if ((dwResult = WaitForSingleObject(hNewTraps, INFINITE)) == WAIT_FAILED) { printf("error on WaitForSingleObject %d\n", GetLastError()); } else if (dwResult != WAIT_OBJECT_0) { printf("hNewTraps is not signaled\n"); } else if (!ResetEvent(hNewTraps)) { printf("error on ResetEvent %d\n", GetLastError()); } else { AsnObjectIdentifier enterprise; AsnNetworkAddress agentAddress; AsnNetworkAddress sourceAddress; AsnInteger genericTrap; AsnInteger specificTrap; AsnOctetString communityTrap; AsnTimeticks timeStamp; RFC1157VarBindList variableBindingsTrap; UINT i; while(SnmpMgrGetTrapEx( &enterprise, &agentAddress, &sourceAddress, &genericTrap, &specificTrap, &communityTrap, &timeStamp, &variableBindingsTrap)) { LPSTR string = NULL; printf("Incoming Trap:\n" " generic = %d\n" " specific = %d\n" " timeStamp = %u\n", genericTrap, specificTrap, timeStamp); if (SnmpMgrOidToStr(&enterprise, &string)) { printf (" enterprise = %s\n", string); if (string) SnmpUtilMemFree(string); } SnmpUtilOidFree(&enterprise); if (agentAddress.length == 4) { printf (" agent = %d.%d.%d.%d\n", (int)agentAddress.stream[0], (int)agentAddress.stream[1], (int)agentAddress.stream[2], (int)agentAddress.stream[3]); } if (agentAddress.dynamic) { SnmpUtilMemFree(agentAddress.stream); } if (sourceAddress.length == 4) { printf (" source IP = %d.%d.%d.%d\n", (int)sourceAddress.stream[0], (int)sourceAddress.stream[1], (int)sourceAddress.stream[2], (int)sourceAddress.stream[3]); } else if (sourceAddress.length == 10) { printf (" source IPX = %.2x%.2x%.2x%.2x." "%.2x%.2x%.2x%.2x%.2x%.2x\n", (int)sourceAddress.stream[0], (int)sourceAddress.stream[1], (int)sourceAddress.stream[2], (int)sourceAddress.stream[3], (int)sourceAddress.stream[4], (int)sourceAddress.stream[5], (int)sourceAddress.stream[6], (int)sourceAddress.stream[7], (int)sourceAddress.stream[8], (int)sourceAddress.stream[9]); } if (sourceAddress.dynamic) { SnmpUtilMemFree(sourceAddress.stream); } if (communityTrap.length) { string = (LPSTR)SnmpUtilMemAlloc (communityTrap.length + 1); if (string) { memcpy (string, communityTrap.stream, communityTrap.length); string[communityTrap.length] = '\0'; printf (" community = %s\n", string); SnmpUtilMemFree(string); } } if (communityTrap.dynamic) { SnmpUtilMemFree(communityTrap.stream); } for(i=0; i < variableBindingsTrap.len; i++) { string = NULL; if (SnmpMgrOidToStr(&variableBindingsTrap.list[i].name, &string)) { printf(" variable = %s\n", string); if (string) SnmpUtilMemFree(string); } printf(" value = "); SnmpUtilPrintAsnAny(&variableBindingsTrap.list[i].value); } // end for() printf("\n"); SnmpUtilVarBindListFree(&variableBindingsTrap); } dwResult = GetLastError(); // check for errors... if ((dwResult != NOERROR) && (dwResult != SNMP_MGMTAPI_NOTRAPS)) { printf("error on SnmpMgrGetTrap %d\n", dwResult); } } } // end while() } // end if(operation) if (operation != TRAP) { // Close SNMP session with the remote agent. if (!SnmpMgrClose(session)) { printf("error on SnmpMgrClose %d\n", GetLastError()); return 1; } } // Let the command interpreter know things went ok. return 0; } // end main()
void _php3_snmp(INTERNAL_FUNCTION_PARAMETERS, int st) { pval *a1, *a2, *a3; INT operation; LPSTR agent; LPSTR community; RFC1157VarBindList variableBindings; LPSNMP_MGR_SESSION session; INT timeout = TIMEOUT; INT retries = RETRIES; BYTE requestType; AsnInteger errorStatus; AsnInteger errorIndex; AsnObjectIdentifier oid; char *chkPtr = NULL; if (getParameters(ht, 3, &a1, &a2, &a3) == FAILURE) { WRONG_PARAM_COUNT; } convert_to_string(a1); convert_to_string(a2); convert_to_string(a3); agent=a1->value.str.val; community=a2->value.str.val; operation=st; SnmpMgrStrToOid(a3->value.str.val, &oid); /* I've limited this to only one oid, but we can create a list of oid's here, and expand the function to take multiple oid's */ variableBindings.list->name = oid; variableBindings.list->value.asnType = ASN_NULL; variableBindings.len = 1; /* Establish a SNMP session to communicate with the remote agent. The community, communications timeout, and communications retry count for the session are also required. */ if ((session = SnmpMgrOpen(agent, community, timeout, retries)) == NULL){ php_error(E_WARNING,"error on SnmpMgrOpen %d\n", GetLastError()); } /* Determine and perform the requested operation.*/ if (operation == GET || operation == GETNEXT){ /* Get and GetNext are relatively simple operations to perform. Simply initiate the request and process the result and/or possible error conditions. */ if (operation == GET){ requestType = ASN_RFC1157_GETREQUEST; } else { requestType = ASN_RFC1157_GETNEXTREQUEST; } /* Request that the API carry out the desired operation.*/ if (!SnmpMgrRequest(session, requestType, &variableBindings, &errorStatus, &errorIndex)){ /* The API is indicating an error. */ php_error(E_WARNING,"error on SnmpMgrRequest %d\n", GetLastError()); } else { /* The API succeeded, errors may be indicated from the remote agent. */ if (errorStatus > 0){ php_error(E_WARNING,"Error: errorStatus=%d, errorIndex=%d\n", errorStatus, errorIndex); } else { /* Display the resulting variable bindings.*/ UINT i; char *str = NULL; for(i=0; i < variableBindings.len; i++) { SnmpMgrOidToStr(&variableBindings.list[i].name, &str); php_printf("Variable = %s\n", str); if (str) SNMP_free(str); php_printf("Value = "); SnmpUtilPrintAsnAny(&variableBindings.list[i].value); php_printf("\n"); } /* end for() */ } } /* Free the variable bindings that have been allocated.*/ SnmpUtilVarBindListFree(&variableBindings); } else if (operation == WALK) { /* Walk is a common term used to indicate that all MIB variables under a given OID are to be traversed and displayed. This is a more complex operation requiring tests and looping in addition to the steps for get/getnext above. */ AsnObjectIdentifier root; AsnObjectIdentifier tempOid; SnmpUtilOidCpy(&root, &variableBindings.list[0].name); requestType = ASN_RFC1157_GETNEXTREQUEST; while(1) { if (!SnmpMgrRequest(session, requestType, &variableBindings, &errorStatus, &errorIndex)){ /* The API is indicating an error.*/ php_error(E_WARNING,"error on SnmpMgrRequest %d\n", GetLastError()); break; } else { /* The API succeeded, errors may be indicated from the remote agent. Test for end of subtree or end of MIB. */ if (errorStatus == SNMP_ERRORSTATUS_NOSUCHNAME || SnmpUtilOidNCmp(&variableBindings.list[0].name, &root, root.idLength)) { PUTS("End of MIB subtree.\n\n"); break; } /* Test for general error conditions or sucesss. */ if (errorStatus > 0){ php_error(E_ERROR,"Error: errorStatus=%d, errorIndex=%d \n", errorStatus, errorIndex); break; } else { /* Display resulting variable binding for this iteration. */ char *str = NULL; SnmpMgrOidToStr(&variableBindings.list[0].name, &str); php_printf("Variable = %s\n", str); if (str) SNMP_free(str); php_printf("Value = "); SnmpUtilPrintAsnAny(&variableBindings.list[0].value); php_printf("\n"); } } /* end if () */ /* Prepare for the next iteration. Make sure returned oid is preserved and the returned value is freed. */ SnmpUtilOidCpy(&tempOid, &variableBindings.list[0].name); SnmpUtilVarBindFree(&variableBindings.list[0]); SnmpUtilOidCpy(&variableBindings.list[0].name, &tempOid); variableBindings.list[0].value.asnType = ASN_NULL; SnmpUtilOidFree(&tempOid); } /* end while() */ /* Free the variable bindings that have been allocated.*/ SnmpUtilVarBindListFree(&variableBindings); SnmpUtilOidFree(&root); } /* end if (operation) */ /* Close SNMP session with the remote agent.*/ if (!SnmpMgrClose(session)){ php_error(E_WARNING,"error on SnmpMgrClose %d\n", GetLastError()); } }