static void setOidWithItem(AsnObjectIdentifier *dst, AsnObjectIdentifier *base, UINT item) { UINT id; AsnObjectIdentifier oid; SnmpUtilOidCpy(dst, base); oid.idLength = 1; oid.ids = &id; id = item; SnmpUtilOidAppend(dst, &oid); }
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; }
/***************************************************************************** * SnmpExtensionInit [INETMIB1.@] */ BOOL WINAPI SnmpExtensionInit(DWORD dwUptimeReference, HANDLE *phSubagentTrapEvent, AsnObjectIdentifier *pFirstSupportedRegion) { AsnObjectIdentifier myOid = DEFINE_OID(mib2System); UINT i; TRACE("(%d, %p, %p)\n", dwUptimeReference, phSubagentTrapEvent, pFirstSupportedRegion); minSupportedIDLength = UINT_MAX; for (i = 0; i < sizeof(supportedIDs) / sizeof(supportedIDs[0]); i++) { if (supportedIDs[i].init) supportedIDs[i].init(); if (supportedIDs[i].name.idLength < minSupportedIDLength) minSupportedIDLength = supportedIDs[i].name.idLength; } *phSubagentTrapEvent = NULL; SnmpUtilOidCpy(pFirstSupportedRegion, &myOid); return TRUE; }
//通过SNMP(简单网络访问协议) bool GetMacAddressBySNMP(std::string &mac_address) { bool ret = false; WSADATA winsock_data; if (WSAStartup(MAKEWORD(2, 0), &winsock_data) != 0) return false; // Load the SNMP dll and get the addresses of the functions necessary const HINSTANCE m_dll = LoadLibrary(L"inetmib1.dll"); if (m_dll < (HINSTANCE) HINSTANCE_ERROR) return false; const PFNSNMPEXTENSIONINIT f_SnmpExtensionInit = (PFNSNMPEXTENSIONINIT) GetProcAddress(m_dll, "SnmpExtensionInit"); // const PFNSNMPEXTENSIONINITEX f_SnmpExtensionInitEx = (PFNSNMPEXTENSIONINITEX) GetProcAddress(m_dll, "SnmpExtensionInitEx"); const PFNSNMPEXTENSIONQUERY f_SnmpExtensionQuery = (PFNSNMPEXTENSIONQUERY) GetProcAddress(m_dll, "SnmpExtensionQuery"); // const PFNSNMPEXTENSIONTRAP f_SnmpExtensionTrap = (PFNSNMPEXTENSIONTRAP) GetProcAddress(m_dll, "SnmpExtensionTrap"); HANDLE poll_for_trap_event; AsnObjectIdentifier supported_view; f_SnmpExtensionInit(GetTickCount(), &poll_for_trap_event, &supported_view); // Initialize the variable list to be retrieved by f_SnmpExtensionQuery const AsnObjectIdentifier MIB_NULL = { 0, 0 }; RFC1157VarBind var_bind[2]; var_bind[0].name = MIB_NULL; var_bind[1].name = MIB_NULL; RFC1157VarBindList var_bind_list; var_bind_list.list = var_bind; UINT OID_ifEntryType[] = { 1, 3, 6, 1, 2, 1, 2, 2, 1, 3 }; UINT OID_ifEntryNum[] = { 1, 3, 6, 1, 2, 1, 2, 1 }; UINT OID_ipMACEntAddr[] = { 1, 3, 6, 1, 2, 1, 2, 2, 1, 6 }; AsnObjectIdentifier MIB_ifMACEntAddr = { sizeof(OID_ipMACEntAddr) / sizeof(UINT), OID_ipMACEntAddr }; AsnObjectIdentifier MIB_ifEntryType = { sizeof(OID_ifEntryType) / sizeof(UINT), OID_ifEntryType }; AsnObjectIdentifier MIB_ifEntryNum = { sizeof(OID_ifEntryNum) / sizeof(UINT), OID_ifEntryNum }; // Copy in the OID to find the number of entries in the Inteface table var_bind_list.len = 1; // Only retrieving one item SnmpUtilOidCpy(&var_bind[0].name, &MIB_ifEntryNum); AsnInteger errorStatus; AsnInteger errorIndex; f_SnmpExtensionQuery(ASN_RFC1157_GETNEXTREQUEST, &var_bind_list, &errorStatus, &errorIndex); var_bind_list.len = 2; // Copy in the OID of ifType, the type of interface SnmpUtilOidCpy(&var_bind[0].name, &MIB_ifEntryType); // Copy in the OID of ifPhysAddress, the address SnmpUtilOidCpy(&var_bind[1].name, &MIB_ifMACEntAddr); for(int j = 0; j < var_bind[0].value.asnValue.number; j++) { // Submit the query. Responses will be loaded into var_bind_list. // We can expect this call to succeed a # of times corresponding to the # of adapters reported to be in the system if(f_SnmpExtensionQuery(ASN_RFC1157_GETNEXTREQUEST, &var_bind_list, &errorStatus, &errorIndex) == FALSE) continue; // Confirm that the proper type has been returned if(SnmpUtilOidNCmp(&var_bind[0].name, &MIB_ifEntryType, MIB_ifEntryType.idLength) != 0) continue; // Type 6 describes ethernet interfaces if(var_bind[0].value.asnValue.number != 6) continue; // Confirm that we have an address here if(SnmpUtilOidNCmp(&var_bind[1].name, &MIB_ifMACEntAddr, MIB_ifMACEntAddr.idLength) != 0) continue; if(var_bind[1].value.asnValue.address.stream == NULL) continue; // Ignore all dial-up networking adapters if ((var_bind[1].value.asnValue.address.stream[0] == 0x44) && (var_bind[1].value.asnValue.address.stream[1] == 0x45) && (var_bind[1].value.asnValue.address.stream[2] == 0x53) && (var_bind[1].value.asnValue.address.stream[3] == 0x54) && (var_bind[1].value.asnValue.address.stream[4] == 0x00)) continue; // Ignore NULL addresses returned by other network interfaces if ((var_bind[1].value.asnValue.address.stream[0] == 0x00) && (var_bind[1].value.asnValue.address.stream[1] == 0x00) && (var_bind[1].value.asnValue.address.stream[2] == 0x00) && (var_bind[1].value.asnValue.address.stream[3] == 0x00) && (var_bind[1].value.asnValue.address.stream[4] == 0x00) && (var_bind[1].value.asnValue.address.stream[5] == 0x00)) continue; StringPrintf(mac_address, "%02x-%02x-%02x-%02x-%02x-%02x", var_bind[1].value.asnValue.address.stream[0], var_bind[1].value.asnValue.address.stream[1], var_bind[1].value.asnValue.address.stream[2], var_bind[1].value.asnValue.address.stream[3], var_bind[1].value.asnValue.address.stream[4], var_bind[1].value.asnValue.address.stream[5]); ret = true; break; } // Free the bindings SnmpUtilVarBindFree(&var_bind[0]); SnmpUtilVarBindFree(&var_bind[1]); return ret; }
int _cdecl main( IN int argumentCount, IN char *argumentVector[]) { HANDLE hExtension; FARPROC initAddr; FARPROC queryAddr; FARPROC trapAddr; DWORD timeZeroReference; HANDLE hPollForTrapEvent; View supportedView; INT numQueries = 10; // avoid compiler warning... UNREFERENCED_PARAMETER(argumentCount); UNREFERENCED_PARAMETER(argumentVector); timeZeroReference = GetCurrentTime(); // load the extension agent dll and resolve the entry points... if (GetModuleHandle("testdll.dll") == NULL) { if ((hExtension = LoadLibrary("testdll.dll")) == NULL) { dbgprintf(1, "error on LoadLibrary %d\n", GetLastError()); } else if ((initAddr = GetProcAddress(hExtension, "SnmpExtensionInit")) == NULL) { dbgprintf(1, "error on GetProcAddress %d\n", GetLastError()); } else if ((queryAddr = GetProcAddress(hExtension, "SnmpExtensionQuery")) == NULL) { dbgprintf(1, "error on GetProcAddress %d\n", GetLastError()); } else if ((trapAddr = GetProcAddress(hExtension, "SnmpExtensionTrap")) == NULL) { dbgprintf(1, "error on GetProcAddress %d\n", GetLastError()); } else { // initialize the extension agent via its init entry point... (*initAddr)( timeZeroReference, &hPollForTrapEvent, &supportedView); } } // end if (Already loaded) // create a trap thread to respond to traps from the extension agent... //rather than oomplicate this test routine, will poll for these events //below. normally this would be done by another thread in the extendible //agent. // loop here doing repetitive extension agent get queries... // poll for potential traps each iteration (see note above)... //block... printf( "SET on toasterManufacturer - shouldn't work\n" ); { UINT itemn[] = { 1, 3, 6, 1, 4, 1, 12, 2, 1, 0 }; RFC1157VarBindList varBinds; AsnInteger errorStatus = 0; AsnInteger errorIndex = 0; varBinds.list = (RFC1157VarBind *)SnmpUtilMemAlloc( sizeof(RFC1157VarBind) ); varBinds.len = 1; varBinds.list[0].name.idLength = sizeof itemn / sizeof(UINT); varBinds.list[0].name.ids = (UINT *)SnmpUtilMemAlloc( sizeof(UINT)* varBinds.list[0].name.idLength ); memcpy( varBinds.list[0].name.ids, &itemn, sizeof(UINT)*varBinds.list[0].name.idLength ); varBinds.list[0].value.asnType = ASN_OCTETSTRING; varBinds.list[0].value.asnValue.string.length = 0; varBinds.list[0].value.asnValue.string.stream = NULL; printf( "SET: " ); SnmpUtilPrintOid( &varBinds.list[0].name ); printf( " to " ); SnmpUtilPrintAsnAny( &varBinds.list[0].value ); (*queryAddr)( ASN_RFC1157_SETREQUEST, &varBinds, &errorStatus, &errorIndex ); printf( "\nSET Errorstatus: %lu\n\n", errorStatus ); (*queryAddr)( ASN_RFC1157_GETREQUEST, &varBinds, &errorStatus, &errorIndex ); if ( errorStatus == SNMP_ERRORSTATUS_NOERROR ) { printf( "New Value: " ); SnmpUtilPrintAsnAny( &varBinds.list[0].value ); putchar( '\n' ); } printf( "\nGET Errorstatus: %lu\n\n", errorStatus ); // Free the memory SnmpUtilVarBindListFree( &varBinds ); printf( "\n\n" ); } printf( "SET on toasterControl with invalid value\n" ); { UINT itemn[] = { 1, 3, 6, 1, 4, 1, 12, 2, 3, 0 }; RFC1157VarBindList varBinds; AsnInteger errorStatus = 0; AsnInteger errorIndex = 0; varBinds.list = (RFC1157VarBind *)SnmpUtilMemAlloc( sizeof(RFC1157VarBind) ); varBinds.len = 1; varBinds.list[0].name.idLength = sizeof itemn / sizeof(UINT); varBinds.list[0].name.ids = (UINT *)SnmpUtilMemAlloc( sizeof(UINT)* varBinds.list[0].name.idLength ); memcpy( varBinds.list[0].name.ids, &itemn, sizeof(UINT)*varBinds.list[0].name.idLength ); varBinds.list[0].value.asnType = ASN_INTEGER; varBinds.list[0].value.asnValue.number = 500; printf( "SET: " ); SnmpUtilPrintOid( &varBinds.list[0].name ); printf( " to " ); SnmpUtilPrintAsnAny( &varBinds.list[0].value ); (*queryAddr)( ASN_RFC1157_SETREQUEST, &varBinds, &errorStatus, &errorIndex ); printf( "\nSET Errorstatus: %lu\n\n", errorStatus ); (*queryAddr)( ASN_RFC1157_GETREQUEST, &varBinds, &errorStatus, &errorIndex ); if ( errorStatus == SNMP_ERRORSTATUS_NOERROR ) { printf( "New Value: " ); SnmpUtilPrintAsnAny( &varBinds.list[0].value ); putchar( '\n' ); } printf( "\nGET Errorstatus: %lu\n\n", errorStatus ); // Free the memory SnmpUtilVarBindListFree( &varBinds ); printf( "\n\n" ); } printf( "SET on toasterControl with invalid type\n" ); { UINT itemn[] = { 1, 3, 6, 1, 4, 1, 12, 2, 3, 0 }; RFC1157VarBindList varBinds; AsnInteger errorStatus = 0; AsnInteger errorIndex = 0; varBinds.list = (RFC1157VarBind *)SnmpUtilMemAlloc( sizeof(RFC1157VarBind) ); varBinds.len = 1; varBinds.list[0].name.idLength = sizeof itemn / sizeof(UINT); varBinds.list[0].name.ids = (UINT *)SnmpUtilMemAlloc( sizeof(UINT)* varBinds.list[0].name.idLength ); memcpy( varBinds.list[0].name.ids, &itemn, sizeof(UINT)*varBinds.list[0].name.idLength ); varBinds.list[0].value.asnType = ASN_NULL; varBinds.list[0].value.asnValue.number = 500; printf( "SET: " ); SnmpUtilPrintOid( &varBinds.list[0].name ); printf( " to " ); SnmpUtilPrintAsnAny( &varBinds.list[0].value ); (*queryAddr)( ASN_RFC1157_SETREQUEST, &varBinds, &errorStatus, &errorIndex ); printf( "\nSET Errorstatus: %lu\n\n", errorStatus ); (*queryAddr)( ASN_RFC1157_GETREQUEST, &varBinds, &errorStatus, &errorIndex ); if ( errorStatus == SNMP_ERRORSTATUS_NOERROR ) { printf( "New Value: " ); SnmpUtilPrintAsnAny( &varBinds.list[0].value ); putchar( '\n' ); } printf( "\nGET Errorstatus: %lu\n\n", errorStatus ); // Free the memory SnmpUtilVarBindListFree( &varBinds ); printf( "\n\n" ); } printf( "SET on toasterControl\n" ); { UINT itemn[] = { 1, 3, 6, 1, 4, 1, 12, 2, 3, 0 }; RFC1157VarBindList varBinds; AsnInteger errorStatus = 0; AsnInteger errorIndex = 0; varBinds.list = (RFC1157VarBind *)SnmpUtilMemAlloc( sizeof(RFC1157VarBind) ); varBinds.len = 1; varBinds.list[0].name.idLength = sizeof itemn / sizeof(UINT); varBinds.list[0].name.ids = (UINT *)SnmpUtilMemAlloc( sizeof(UINT)* varBinds.list[0].name.idLength ); memcpy( varBinds.list[0].name.ids, &itemn, sizeof(UINT)*varBinds.list[0].name.idLength ); varBinds.list[0].value.asnType = ASN_INTEGER; varBinds.list[0].value.asnValue.number = 2; printf( "SET: " ); SnmpUtilPrintOid( &varBinds.list[0].name ); printf( " to " ); SnmpUtilPrintAsnAny( &varBinds.list[0].value ); (*queryAddr)( ASN_RFC1157_SETREQUEST, &varBinds, &errorStatus, &errorIndex ); printf( "\nSET Errorstatus: %lu\n\n", errorStatus ); (*queryAddr)( ASN_RFC1157_GETREQUEST, &varBinds, &errorStatus, &errorIndex ); if ( errorStatus == SNMP_ERRORSTATUS_NOERROR ) { printf( "New Value: " ); SnmpUtilPrintAsnAny( &varBinds.list[0].value ); putchar( '\n' ); } printf( "\nGET Errorstatus: %lu\n\n", errorStatus ); // Free the memory SnmpUtilVarBindListFree( &varBinds ); printf( "\n\n" ); } printf( "SET on toasterDoneness with invalid value\n" ); { UINT itemn[] = { 1, 3, 6, 1, 4, 1, 12, 2, 4, 0 }; RFC1157VarBindList varBinds; AsnInteger errorStatus = 0; AsnInteger errorIndex = 0; varBinds.list = (RFC1157VarBind *)SnmpUtilMemAlloc( sizeof(RFC1157VarBind) ); varBinds.len = 1; varBinds.list[0].name.idLength = sizeof itemn / sizeof(UINT); varBinds.list[0].name.ids = (UINT *)SnmpUtilMemAlloc( sizeof(UINT)* varBinds.list[0].name.idLength ); memcpy( varBinds.list[0].name.ids, &itemn, sizeof(UINT)*varBinds.list[0].name.idLength ); varBinds.list[0].value.asnType = ASN_INTEGER; varBinds.list[0].value.asnValue.number = 1000; printf( "SET: " ); SnmpUtilPrintOid( &varBinds.list[0].name ); printf( " to " ); SnmpUtilPrintAsnAny( &varBinds.list[0].value ); (*queryAddr)( ASN_RFC1157_SETREQUEST, &varBinds, &errorStatus, &errorIndex ); printf( "\nSET Errorstatus: %lu\n\n", errorStatus ); (*queryAddr)( ASN_RFC1157_GETREQUEST, &varBinds, &errorStatus, &errorIndex ); if ( errorStatus == SNMP_ERRORSTATUS_NOERROR ) { printf( "New Value: " ); SnmpUtilPrintAsnAny( &varBinds.list[0].value ); putchar( '\n' ); } printf( "\nGET Errorstatus: %lu\n\n", errorStatus ); // Free the memory SnmpUtilVarBindListFree( &varBinds ); printf( "\n\n" ); } printf( "SET on toasterDoneness with invalid type\n" ); { UINT itemn[] = { 1, 3, 6, 1, 4, 1, 12, 2, 4, 0 }; RFC1157VarBindList varBinds; AsnInteger errorStatus = 0; AsnInteger errorIndex = 0; varBinds.list = (RFC1157VarBind *)SnmpUtilMemAlloc( sizeof(RFC1157VarBind) ); varBinds.len = 1; varBinds.list[0].name.idLength = sizeof itemn / sizeof(UINT); varBinds.list[0].name.ids = (UINT *)SnmpUtilMemAlloc( sizeof(UINT)* varBinds.list[0].name.idLength ); memcpy( varBinds.list[0].name.ids, &itemn, sizeof(UINT)*varBinds.list[0].name.idLength ); varBinds.list[0].value.asnType = ASN_NULL; varBinds.list[0].value.asnValue.number = 1000; printf( "SET: " ); SnmpUtilPrintOid( &varBinds.list[0].name ); printf( " to " ); SnmpUtilPrintAsnAny( &varBinds.list[0].value ); (*queryAddr)( ASN_RFC1157_SETREQUEST, &varBinds, &errorStatus, &errorIndex ); printf( "\nSET Errorstatus: %lu\n\n", errorStatus ); (*queryAddr)( ASN_RFC1157_GETREQUEST, &varBinds, &errorStatus, &errorIndex ); if ( errorStatus == SNMP_ERRORSTATUS_NOERROR ) { printf( "New Value: " ); SnmpUtilPrintAsnAny( &varBinds.list[0].value ); putchar( '\n' ); } printf( "\nGET Errorstatus: %lu\n\n", errorStatus ); // Free the memory SnmpUtilVarBindListFree( &varBinds ); printf( "\n\n" ); } printf( "SET on toasterDoneness\n" ); { UINT itemn[] = { 1, 3, 6, 1, 4, 1, 12, 2, 4, 0 }; RFC1157VarBindList varBinds; AsnInteger errorStatus = 0; AsnInteger errorIndex = 0; varBinds.list = (RFC1157VarBind *)SnmpUtilMemAlloc( sizeof(RFC1157VarBind) ); varBinds.len = 1; varBinds.list[0].name.idLength = sizeof itemn / sizeof(UINT); varBinds.list[0].name.ids = (UINT *)SnmpUtilMemAlloc( sizeof(UINT)* varBinds.list[0].name.idLength ); memcpy( varBinds.list[0].name.ids, &itemn, sizeof(UINT)*varBinds.list[0].name.idLength ); varBinds.list[0].value.asnType = ASN_INTEGER; varBinds.list[0].value.asnValue.number = 10; printf( "SET: " ); SnmpUtilPrintOid( &varBinds.list[0].name ); printf( " to " ); SnmpUtilPrintAsnAny( &varBinds.list[0].value ); (*queryAddr)( ASN_RFC1157_SETREQUEST, &varBinds, &errorStatus, &errorIndex ); printf( "\nSET Errorstatus: %lu\n\n", errorStatus ); (*queryAddr)( ASN_RFC1157_GETREQUEST, &varBinds, &errorStatus, &errorIndex ); if ( errorStatus == SNMP_ERRORSTATUS_NOERROR ) { printf( "New Value: " ); SnmpUtilPrintAsnAny( &varBinds.list[0].value ); putchar( '\n' ); } printf( "\nGET Errorstatus: %lu\n\n", errorStatus ); // Free the memory SnmpUtilVarBindListFree( &varBinds ); printf( "\n\n" ); } printf( "SET on toasterToastType with invalid value\n" ); { UINT itemn[] = { 1, 3, 6, 1, 4, 1, 12, 2, 5, 0 }; RFC1157VarBindList varBinds; AsnInteger errorStatus = 0; AsnInteger errorIndex = 0; varBinds.list = (RFC1157VarBind *)SnmpUtilMemAlloc( sizeof(RFC1157VarBind) ); varBinds.len = 1; varBinds.list[0].name.idLength = sizeof itemn / sizeof(UINT); varBinds.list[0].name.ids = (UINT *)SnmpUtilMemAlloc( sizeof(UINT)* varBinds.list[0].name.idLength ); memcpy( varBinds.list[0].name.ids, &itemn, sizeof(UINT)*varBinds.list[0].name.idLength ); varBinds.list[0].value.asnType = ASN_INTEGER; varBinds.list[0].value.asnValue.number = 10; printf( "SET: " ); SnmpUtilPrintOid( &varBinds.list[0].name ); printf( " to " ); SnmpUtilPrintAsnAny( &varBinds.list[0].value ); (*queryAddr)( ASN_RFC1157_SETREQUEST, &varBinds, &errorStatus, &errorIndex ); printf( "\nSET Errorstatus: %lu\n\n", errorStatus ); (*queryAddr)( ASN_RFC1157_GETREQUEST, &varBinds, &errorStatus, &errorIndex ); if ( errorStatus == SNMP_ERRORSTATUS_NOERROR ) { printf( "New Value: " ); SnmpUtilPrintAsnAny( &varBinds.list[0].value ); putchar( '\n' ); } printf( "\nGET Errorstatus: %lu\n\n", errorStatus ); // Free the memory SnmpUtilVarBindListFree( &varBinds ); printf( "\n\n" ); } printf( "SET on toasterToastType with invalid type\n" ); { UINT itemn[] = { 1, 3, 6, 1, 4, 1, 12, 2, 5, 0 }; RFC1157VarBindList varBinds; AsnInteger errorStatus = 0; AsnInteger errorIndex = 0; varBinds.list = (RFC1157VarBind *)SnmpUtilMemAlloc( sizeof(RFC1157VarBind) ); varBinds.len = 1; varBinds.list[0].name.idLength = sizeof itemn / sizeof(UINT); varBinds.list[0].name.ids = (UINT *)SnmpUtilMemAlloc( sizeof(UINT)* varBinds.list[0].name.idLength ); memcpy( varBinds.list[0].name.ids, &itemn, sizeof(UINT)*varBinds.list[0].name.idLength ); varBinds.list[0].value.asnType = ASN_NULL; varBinds.list[0].value.asnValue.number = 10; printf( "SET: " ); SnmpUtilPrintOid( &varBinds.list[0].name ); printf( " to " ); SnmpUtilPrintAsnAny( &varBinds.list[0].value ); (*queryAddr)( ASN_RFC1157_SETREQUEST, &varBinds, &errorStatus, &errorIndex ); printf( "\nSET Errorstatus: %lu\n\n", errorStatus ); (*queryAddr)( ASN_RFC1157_GETREQUEST, &varBinds, &errorStatus, &errorIndex ); if ( errorStatus == SNMP_ERRORSTATUS_NOERROR ) { printf( "New Value: " ); SnmpUtilPrintAsnAny( &varBinds.list[0].value ); putchar( '\n' ); } printf( "\nGET Errorstatus: %lu\n\n", errorStatus ); // Free the memory SnmpUtilVarBindListFree( &varBinds ); printf( "\n\n" ); } printf( "SET on toasterToastType\n" ); { UINT itemn[] = { 1, 3, 6, 1, 4, 1, 12, 2, 5, 0 }; RFC1157VarBindList varBinds; AsnInteger errorStatus = 0; AsnInteger errorIndex = 0; varBinds.list = (RFC1157VarBind *)SnmpUtilMemAlloc( sizeof(RFC1157VarBind) ); varBinds.len = 1; varBinds.list[0].name.idLength = sizeof itemn / sizeof(UINT); varBinds.list[0].name.ids = (UINT *)SnmpUtilMemAlloc( sizeof(UINT)* varBinds.list[0].name.idLength ); memcpy( varBinds.list[0].name.ids, &itemn, sizeof(UINT)*varBinds.list[0].name.idLength ); varBinds.list[0].value.asnType = ASN_INTEGER; varBinds.list[0].value.asnValue.number = 7; printf( "SET: " ); SnmpUtilPrintOid( &varBinds.list[0].name ); printf( " to " ); SnmpUtilPrintAsnAny( &varBinds.list[0].value ); (*queryAddr)( ASN_RFC1157_SETREQUEST, &varBinds, &errorStatus, &errorIndex ); printf( "\nSET Errorstatus: %lu\n\n", errorStatus ); (*queryAddr)( ASN_RFC1157_GETREQUEST, &varBinds, &errorStatus, &errorIndex ); if ( errorStatus == SNMP_ERRORSTATUS_NOERROR ) { printf( "New Value: " ); SnmpUtilPrintAsnAny( &varBinds.list[0].value ); putchar( '\n' ); } printf( "\nGET Errorstatus: %lu\n\n", errorStatus ); // Free the memory SnmpUtilVarBindListFree( &varBinds ); printf( "\n\n" ); } { RFC1157VarBindList varBinds; AsnInteger errorStatus; AsnInteger errorIndex; UINT OID_Prefix[] = { 1, 3, 6, 1, 4, 1, 12 }; AsnObjectIdentifier MIB_OidPrefix = { OID_SIZEOF(OID_Prefix), OID_Prefix }; errorStatus = 0; errorIndex = 0; varBinds.list = (RFC1157VarBind *)SnmpUtilMemAlloc( sizeof(RFC1157VarBind) ); varBinds.len = 1; SnmpUtilOidCpy( &varBinds.list[0].name, &MIB_OidPrefix ); varBinds.list[0].value.asnType = ASN_NULL; do { printf( "GET-NEXT of: " ); SnmpUtilPrintOid( &varBinds.list[0].name ); printf( " " ); (*queryAddr)( (AsnInteger)ASN_RFC1157_GETNEXTREQUEST, &varBinds, &errorStatus, &errorIndex ); printf( "\n is " ); SnmpUtilPrintOid( &varBinds.list[0].name ); if ( errorStatus ) { printf( "\nErrorstatus: %lu\n\n", errorStatus ); } else { printf( "\n = " ); SnmpUtilPrintAsnAny( &varBinds.list[0].value ); } putchar( '\n' ); // query potential traps (see notes above) if ( NULL != hPollForTrapEvent ) { DWORD dwResult; if ( 0xffffffff == (dwResult = WaitForSingleObject(hPollForTrapEvent, 1000)) ) { dbgprintf(1, "error on WaitForSingleObject %d\n", GetLastError()); } else { if ( dwResult == 0 /*signaled*/ ) { AsnObjectIdentifier enterprise; AsnInteger genericTrap; AsnInteger specificTrap; AsnTimeticks timeStamp; RFC1157VarBindList variableBindings; while( (*trapAddr)(&enterprise, &genericTrap, &specificTrap, &timeStamp, &variableBindings) ) { printf("trap: gen=%d spec=%d time=%d\n", genericTrap, specificTrap, timeStamp); //also print data } // end while () } // end if (trap ready) } } // end if (handling traps) } while ( varBinds.list[0].name.ids[MIB_PREFIX_LEN-1] == 12 ); // Free the memory SnmpUtilVarBindListFree( &varBinds ); } // block return 0; } // end main()
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; }
static void testQuery(void) { BOOL (WINAPI *pQuery)(BYTE, SnmpVarBindList *, AsnInteger32 *, AsnInteger32 *); BOOL ret, moreData, noChange; SnmpVarBindList list; AsnInteger32 error, index; UINT bogus[] = { 1,2,3,4 }; UINT mib2System[] = { 1,3,6,1,2,1,1 }; UINT mib2If[] = { 1,3,6,1,2,1,2 }; UINT mib2IfTable[] = { 1,3,6,1,2,1,2,2 }; UINT mib2IfDescr[] = { 1,3,6,1,2,1,2,2,1,2 }; UINT mib2IfAdminStatus[] = { 1,3,6,1,2,1,2,2,1,7 }; UINT mib2IfOperStatus[] = { 1,3,6,1,2,1,2,2,1,8 }; UINT mib2IpAddr[] = { 1,3,6,1,2,1,4,20,1,1 }; UINT mib2IpRouteTable[] = { 1,3,6,1,2,1,4,21,1,1 }; UINT mib2UdpTable[] = { 1,3,6,1,2,1,7,5,1,1 }; SnmpVarBind vars[3], vars2[3], vars3[3]; UINT entry; pQuery = (void *)GetProcAddress(inetmib1, "SnmpExtensionQuery"); if (!pQuery) { win_skip("couldn't find SnmpExtensionQuery\n"); return; } /* Crash ret = pQuery(0, NULL, NULL, NULL); ret = pQuery(0, NULL, &error, NULL); ret = pQuery(0, NULL, NULL, &index); ret = pQuery(0, &list, NULL, NULL); ret = pQuery(0, &list, &error, NULL); */ /* An empty list succeeds */ list.len = 0; error = 0xdeadbeef; index = 0xdeadbeef; ret = pQuery(SNMP_PDU_GET, &list, &error, &index); ok(ret, "SnmpExtensionQuery failed: %d, %d\n", error, index); ok(error == SNMP_ERRORSTATUS_NOERROR, "expected SNMP_ERRORSTATUS_NOERROR, got %d\n", error); ok(index == 0, "expected index 0, got %d\n", index); /* Oddly enough, this "succeeds," even though the OID is clearly * unsupported. */ vars[0].name.idLength = sizeof(bogus) / sizeof(bogus[0]); vars[0].name.ids = bogus; vars[0].value.asnType = 0; list.len = 1; list.list = vars; SetLastError(0xdeadbeef); error = 0xdeadbeef; index = 0xdeadbeef; ret = pQuery(SNMP_PDU_GET, &list, &error, &index); ok(ret, "SnmpExtensionQuery failed: %d, %d\n", error, index); ok(error == SNMP_ERRORSTATUS_NOERROR || error == ERROR_FILE_NOT_FOUND /* Win9x */, "expected SNMP_ERRORSTATUS_NOERROR or ERROR_FILE_NOT_FOUND, got %d\n", error); if (error == SNMP_ERRORSTATUS_NOERROR) ok(index == 0, "expected index 0, got %d\n", index); else if (error == ERROR_FILE_NOT_FOUND) ok(index == 1, "expected index 1, got %d\n", index); /* The OID isn't changed either: */ ok(!strcmp("1.2.3.4", SnmpUtilOidToA(&vars[0].name)), "expected 1.2.3.4, got %s\n", SnmpUtilOidToA(&vars[0].name)); /* The table is not an accessible variable, so it fails */ vars[0].name.idLength = sizeof(mib2IfTable) / sizeof(mib2IfTable[0]); vars[0].name.ids = mib2IfTable; SetLastError(0xdeadbeef); error = 0xdeadbeef; index = 0xdeadbeef; ret = pQuery(SNMP_PDU_GET, &list, &error, &index); ok(ret, "SnmpExtensionQuery failed: %d, %d\n", error, index); ok(error == SNMP_ERRORSTATUS_NOSUCHNAME, "expected SNMP_ERRORSTATUS_NOSUCHNAME, got %d\n", error); /* The index is 1-based rather than 0-based */ ok(index == 1, "expected index 1, got %d\n", index); /* A Get fails on something that specifies a table (but not a particular * entry in it)... */ vars[0].name.idLength = sizeof(mib2IfDescr) / sizeof(mib2IfDescr[0]); vars[0].name.ids = mib2IfDescr; vars[1].name.idLength = sizeof(mib2IfAdminStatus) / sizeof(mib2IfAdminStatus[0]); vars[1].name.ids = mib2IfAdminStatus; vars[2].name.idLength = sizeof(mib2IfOperStatus) / sizeof(mib2IfOperStatus[0]); vars[2].name.ids = mib2IfOperStatus; list.len = 3; SetLastError(0xdeadbeef); error = 0xdeadbeef; index = 0xdeadbeef; ret = pQuery(SNMP_PDU_GET, &list, &error, &index); ok(ret, "SnmpExtensionQuery failed: %d, %d\n", error, index); ok(error == SNMP_ERRORSTATUS_NOSUCHNAME, "expected SNMP_ERRORSTATUS_NOSUCHNAME, got %d\n", error); ok(index == 1, "expected index 1, got %d\n", index); /* but a GetNext succeeds with the same values, because GetNext gets the * entry after the specified OID, not the entry specified by it. The * successor to the table is the first entry in the table. * The OIDs need to be allocated, because GetNext modifies them to indicate * the end of data. */ SnmpUtilOidCpy(&vars2[0].name, &vars[0].name); SnmpUtilOidCpy(&vars2[1].name, &vars[1].name); SnmpUtilOidCpy(&vars2[2].name, &vars[2].name); list.list = vars2; moreData = TRUE; noChange = FALSE; entry = 0; do { SetLastError(0xdeadbeef); error = 0xdeadbeef; index = 0xdeadbeef; ret = pQuery(SNMP_PDU_GETNEXT, &list, &error, &index); ok(ret, "SnmpExtensionQuery failed: %d, %d\n", error, index); ok(error == SNMP_ERRORSTATUS_NOERROR, "expected SNMP_ERRORSTATUS_NOERROR, got %d\n", error); ok(index == 0, "expected index 0, got %d\n", index); if (!ret) moreData = FALSE; else if (error) moreData = FALSE; else if (SnmpUtilOidNCmp(&vars2[0].name, &vars[0].name, vars[0].name.idLength)) moreData = FALSE; else if (SnmpUtilOidNCmp(&vars2[1].name, &vars[1].name, vars[1].name.idLength)) moreData = FALSE; else if (SnmpUtilOidNCmp(&vars2[2].name, &vars[2].name, vars[2].name.idLength)) moreData = FALSE; else if (!SnmpUtilOidCmp(&vars[0].name, &vars2[0].name) || !SnmpUtilOidCmp(&vars[1].name, &vars2[1].name) || !SnmpUtilOidCmp(&vars[2].name, &vars2[2].name)) { /* If the OID isn't modified, the function isn't implemented on this * platform, skip the remaining tests. */ noChange = TRUE; } if (moreData) { UINT lastID; /* Check the OIDs. For these types of values (display strings and * integers) they should increase by 1 for each element of the table * according to RFC 1158. Windows sometimes has a weird value in the * table, so allow any value as long as it's greater than the previous * value on Windows. */ ok(vars2[0].name.idLength == vars[0].name.idLength + 1, "expected length %d, got %d\n", vars[0].name.idLength + 1, vars2[0].name.idLength); lastID = vars2[0].name.ids[vars2[0].name.idLength - 1]; ok(lastID == entry + 1 || broken(lastID > entry), "expected %d, got %d\n", entry + 1, lastID); ok(vars2[1].name.idLength == vars[1].name.idLength + 1, "expected length %d, got %d\n", vars[1].name.idLength + 1, vars2[1].name.idLength); lastID = vars2[1].name.ids[vars2[1].name.idLength - 1]; ok(lastID == entry + 1 || broken(lastID > entry), "expected %d, got %d\n", entry + 1, lastID); ok(vars2[2].name.idLength == vars[2].name.idLength + 1, "expected length %d, got %d\n", vars[2].name.idLength + 1, vars2[2].name.idLength); lastID = vars2[2].name.ids[vars2[2].name.idLength - 1]; ok(lastID == entry + 1 || broken(lastID > entry), "expected %d, got %d\n", entry + 1, lastID); entry = lastID; /* Check the types while we're at it */ ok(vars2[0].value.asnType == ASN_OCTETSTRING, "expected ASN_OCTETSTRING, got %02x\n", vars2[0].value.asnType); ok(vars2[1].value.asnType == ASN_INTEGER, "expected ASN_INTEGER, got %02x\n", vars2[1].value.asnType); ok(vars2[2].value.asnType == ASN_INTEGER, "expected ASN_INTEGER, got %02x\n", vars2[2].value.asnType); } else if (noChange) skip("no change in OID, no MIB2 IF table implementation\n"); } while (moreData && !noChange); SnmpUtilVarBindFree(&vars2[0]); SnmpUtilVarBindFree(&vars2[1]); SnmpUtilVarBindFree(&vars2[2]); /* Even though SnmpExtensionInit says this DLL supports the MIB2 system * variables, on recent systems (at least Win2k) the first variable it * returns a value for is the first interface. */ vars[0].name.idLength = sizeof(mib2System) / sizeof(mib2System[0]); vars[0].name.ids = mib2System; SnmpUtilOidCpy(&vars2[0].name, &vars[0].name); vars2[0].value.asnType = 0; list.len = 1; list.list = vars2; moreData = TRUE; noChange = FALSE; ret = pQuery(SNMP_PDU_GETNEXT, &list, &error, &index); ok(ret, "SnmpExtensionQuery failed: %d, %d\n", error, index); ok(error == SNMP_ERRORSTATUS_NOERROR, "expected SNMP_ERRORSTATUS_NOERROR, got %d\n", error); ok(index == 0, "expected index 0, got %d\n", index); vars3[0].name.idLength = sizeof(mib2If) / sizeof(mib2If[0]); vars3[0].name.ids = mib2If; ok(!SnmpUtilOidNCmp(&vars2[0].name, &vars[0].name, vars[0].name.idLength) || !SnmpUtilOidNCmp(&vars2[0].name, &vars3[0].name, vars3[0].name.idLength), "expected 1.3.6.1.2.1.1 or 1.3.6.1.2.1.2, got %s\n", SnmpUtilOidToA(&vars2[0].name)); SnmpUtilVarBindFree(&vars2[0]); /* Check the type and OIDs of the IP address table */ vars[0].name.idLength = sizeof(mib2IpAddr) / sizeof(mib2IpAddr[0]); vars[0].name.ids = mib2IpAddr; SnmpUtilOidCpy(&vars2[0].name, &vars[0].name); vars2[0].value.asnType = 0; list.len = 1; list.list = vars2; moreData = TRUE; do { ret = pQuery(SNMP_PDU_GETNEXT, &list, &error, &index); ok(ret, "SnmpExtensionQuery failed: %d, %d\n", error, index); ok(error == SNMP_ERRORSTATUS_NOERROR, "expected SNMP_ERRORSTATUS_NOERROR, got %d\n", error); ok(index == 0, "expected index 0, got %d\n", index); if (!ret) moreData = FALSE; else if (error) moreData = FALSE; else if (SnmpUtilOidNCmp(&vars2[0].name, &vars[0].name, vars[0].name.idLength)) moreData = FALSE; else if (!SnmpUtilOidCmp(&vars2[0].name, &vars[0].name)) { /* If the OID isn't modified, the function isn't implemented on this * platform, skip the remaining tests. */ noChange = TRUE; } if (moreData) { /* Make sure the size of the OID is right. * FIXME: don't know if IPv6 addrs are shared with this table. * Don't think so, but I'm not certain. */ ok(vars2[0].name.idLength == vars[0].name.idLength + 4, "expected length %d, got %d\n", vars[0].name.idLength + 4, vars2[0].name.idLength); /* Make sure the type is right */ ok(vars2[0].value.asnType == ASN_IPADDRESS, "expected type ASN_IPADDRESS, got %02x\n", vars2[0].value.asnType); if (vars2[0].value.asnType == ASN_IPADDRESS) { UINT i; /* This looks uglier than it is: the base OID for the IP * address, 1.3.6.1.2.1.4.20.1.1, is appended with the IP * address of the entry. So e.g. the loopback address is * identified in MIB2 as 1.3.6.1.2.1.4.20.1.1.127.0.0.1 */ for (i = 0; i < vars2[0].value.asnValue.address.length; i++) { ok(vars2[0].value.asnValue.address.stream[i] == vars2[0].name.ids[vars2[0].name.idLength - 4 + i], "expected ident byte %d to be %d, got %d\n", i, vars2[0].value.asnValue.address.stream[i], vars2[0].name.ids[vars2[0].name.idLength - 4 + i]); } } } else if (noChange) skip("no change in OID, no MIB2 IP address table implementation\n"); } while (moreData && !noChange); SnmpUtilVarBindFree(&vars2[0]); /* Check the type and OIDs of the IP route table */ vars[0].name.idLength = DEFINE_SIZEOF(mib2IpRouteTable); vars[0].name.ids = mib2IpRouteTable; SnmpUtilOidCpy(&vars2[0].name, &vars[0].name); vars2[0].value.asnType = 0; list.len = 1; list.list = vars2; moreData = TRUE; noChange = FALSE; do { ret = pQuery(SNMP_PDU_GETNEXT, &list, &error, &index); ok(ret, "SnmpExtensionQuery failed: %d, %d\n", error, index); ok(error == SNMP_ERRORSTATUS_NOERROR, "expected SNMP_ERRORSTATUS_NOERROR, got %d\n", error); ok(index == 0, "expected index 0, got %d\n", index); if (!ret) moreData = FALSE; else if (error) moreData = FALSE; else if (SnmpUtilOidNCmp(&vars2[0].name, &vars[0].name, vars[0].name.idLength)) moreData = FALSE; else if (!SnmpUtilOidCmp(&vars2[0].name, &vars[0].name)) { /* If the OID isn't modified, the function isn't implemented on this * platform, skip the remaining tests. */ noChange = TRUE; } if (moreData) { /* Make sure the size of the OID is right. * FIXME: don't know if IPv6 addrs are shared with this table. * Don't think so, but I'm not certain. */ ok(vars2[0].name.idLength == vars[0].name.idLength + 4, "expected length %d, got %d\n", vars[0].name.idLength + 4, vars2[0].name.idLength); /* Make sure the type is right */ ok(vars2[0].value.asnType == ASN_IPADDRESS, "expected type ASN_IPADDRESS, got %02x\n", vars2[0].value.asnType); if (vars2[0].value.asnType == ASN_IPADDRESS) { UINT i; /* The base OID for the route table, 1.3.6.1.2.1.4.21.1.1, is * appended with the dest IP address of the entry. So e.g. a * route entry for 224.0.0.0 is identified in MIB2 as * 1.3.6.1.2.1.4.21.1.1.224.0.0.0 */ for (i = 0; i < vars2[0].value.asnValue.address.length; i++) { ok(vars2[0].value.asnValue.address.stream[i] == vars2[0].name.ids[vars2[0].name.idLength - 4 + i], "expected ident byte %d to be %d, got %d\n", i, vars2[0].value.asnValue.address.stream[i], vars2[0].name.ids[vars2[0].name.idLength - 4 + i]); } } } else if (noChange) skip("no change in OID, no MIB2 IP route table implementation\n"); } while (moreData && !noChange); SnmpUtilVarBindFree(&vars2[0]); /* Check the type and OIDs of the UDP table */ vars[0].name.idLength = DEFINE_SIZEOF(mib2UdpTable); vars[0].name.ids = mib2UdpTable; SnmpUtilOidCpy(&vars2[0].name, &vars[0].name); vars2[0].value.asnType = 0; list.len = 1; list.list = vars2; moreData = TRUE; noChange = FALSE; do { ret = pQuery(SNMP_PDU_GETNEXT, &list, &error, &index); ok(ret, "SnmpExtensionQuery failed: %d, %d\n", error, index); /* FIXME: error and index aren't checked here because the UDP table is * the last OID currently supported by Wine, so the last GetNext fails. * todo_wine is also not effective because it will succeed for all but * the last GetNext. Remove the if (0) if any later OID is supported * by Wine. */ if (0) { ok(error == SNMP_ERRORSTATUS_NOERROR, "expected SNMP_ERRORSTATUS_NOERROR, got %d\n", error); ok(index == 0, "expected index 0, got %d\n", index); } if (!ret) moreData = FALSE; else if (error) moreData = FALSE; else if (SnmpUtilOidNCmp(&vars2[0].name, &vars[0].name, vars[0].name.idLength)) moreData = FALSE; else if (!SnmpUtilOidCmp(&vars2[0].name, &vars[0].name)) { /* If the OID isn't modified, the function isn't implemented on this * platform, skip the remaining tests. */ noChange = TRUE; } if (moreData) { /* Make sure the size of the OID is right. */ ok(vars2[0].name.idLength == vars[0].name.idLength + 5, "expected length %d, got %d\n", vars[0].name.idLength + 5, vars2[0].name.idLength); /* Make sure the type is right */ ok(vars2[0].value.asnType == ASN_IPADDRESS, "expected type ASN_IPADDRESS, got %02x\n", vars2[0].value.asnType); if (vars2[0].value.asnType == ASN_IPADDRESS) { UINT i; /* Again with the ugly: the base OID for the UDP table, * 1.3.6.1.2.1.7.5.1, is appended with the local IP address and * port number of the entry. So e.g. an entry for * 192.168.1.1:4000 is identified in MIB2 as * 1.3.6.1.2.1.7.5.1.192.168.1.1.4000 */ for (i = 0; i < vars2[0].value.asnValue.address.length; i++) { ok(vars2[0].value.asnValue.address.stream[i] == vars2[0].name.ids[vars2[0].name.idLength - 5 + i], "expected ident byte %d to be %d, got %d\n", i, vars2[0].value.asnValue.address.stream[i], vars2[0].name.ids[vars2[0].name.idLength - 5 + i]); } } } else if (noChange) skip("no change in OID, no MIB2 UDP table implementation\n"); } while (moreData && !noChange); SnmpUtilVarBindFree(&vars2[0]); }
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()
/***************************************************************************** * 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()); } }