SNMP V3 support added (without authentication and encryption)
authorVictor Kirhenshtein <victor@netxms.org>
Sun, 28 Jun 2009 22:58:10 +0000 (22:58 +0000)
committerVictor Kirhenshtein <victor@netxms.org>
Sun, 28 Jun 2009 22:58:10 +0000 (22:58 +0000)
20 files changed:
include/nxsnmp.h
src/server/core/layer2.cpp
src/server/core/node.cpp
src/server/core/np.cpp
src/server/core/objtools.cpp
src/server/core/snmp.cpp
src/server/core/snmptrap.cpp
src/server/include/nxsrvapi.h
src/server/libnxsrv/snmpproxy.cpp
src/snmp/libnxsnmp/Makefile.am
src/snmp/libnxsnmp/engine.cpp [new file with mode: 0644]
src/snmp/libnxsnmp/libnxsnmp.vcproj
src/snmp/libnxsnmp/libnxsnmpw.vcproj
src/snmp/libnxsnmp/main.cpp
src/snmp/libnxsnmp/pdu.cpp
src/snmp/libnxsnmp/security.cpp [new file with mode: 0644]
src/snmp/libnxsnmp/transport.cpp
src/snmp/nxsnmpget/nxsnmpget.cpp
src/snmp/nxsnmpset/nxsnmpset.cpp
src/snmp/nxsnmpwalk/nxsnmpwalk.cpp

index 88e2919..909b053 100644 (file)
 // Various constants
 //
 
-#define MAX_OID_LEN           128
-#define MAX_MIB_OBJECT_NAME   64
-#define SNMP_DEFAULT_PORT     161
-#define SNMP_MAX_CONTEXT_ID   256
-#define SNMP_MAX_CONTEXT_NAME 256
+#define MAX_OID_LEN                 128
+#define MAX_MIB_OBJECT_NAME         64
+#define SNMP_DEFAULT_PORT           161
+#define SNMP_MAX_CONTEXT_NAME       256
+#define SNMP_MAX_ENGINEID_LEN       256
+#define SNMP_DEFAULT_MSG_MAX_SIZE   65536
 
 
 //
 #define SNMP_ERR_FILE_IO            11    /* file I/O error */
 #define SNMP_ERR_BAD_FILE_HEADER    12    /* file header is invalid */
 #define SNMP_ERR_BAD_FILE_DATA      13    /* file data is invalid or corrupted */
+#define SNMP_ERR_UNSUPP_SEC_LEVEL   14    /* unsupported security level */
+#define SNMP_ERR_TIME_WINDOW        15    /* not in time window */
+#define SNMP_ERR_SEC_NAME           16    /* unknown security name */
+#define SNMP_ERR_ENGINE_ID          17    /* unknown engine ID */
+#define SNMP_ERR_AUTH_FAILURE       18    /* authentication failure */
+#define SNMP_ERR_DECRYPTION         19    /* decryption error */
+#define SNMP_ERR_BAD_RESPONSE       20    /* malformed or unexpected response from agent */
 
 
 //
 #define SNMP_INVALID_PDU         255
 #define SNMP_GET_REQUEST         0
 #define SNMP_GET_NEXT_REQUEST    1
-#define SNMP_GET_RESPONSE        2
+#define SNMP_RESPONSE            2
 #define SNMP_SET_REQUEST         3
 #define SNMP_TRAP                4
 #define SNMP_GET_BULK_REQUEST    5
 #define SNMP_INFORM_REQUEST      6
+#define SNMP_REPORT              8
 
 
 //
 #define ASN_NO_SUCH_INSTANCE        0x81
 #define ASN_GET_REQUEST_PDU         0xA0
 #define ASN_GET_NEXT_REQUEST_PDU    0xA1
-#define ASN_GET_RESPONSE_PDU        0xA2
+#define ASN_RESPONSE_PDU            0xA2
 #define ASN_SET_REQUEST_PDU         0xA3
 #define ASN_TRAP_V1_PDU             0xA4
 #define ASN_GET_BULK_REQUEST_PDU    0xA5
 #define ASN_INFORM_REQUEST_PDU      0xA6
 #define ASN_TRAP_V2_PDU             0xA7
+#define ASN_REPORT_PDU              0xA8
+
+
+//
+// Security models
+//
+
+#define SNMP_SECURITY_MODEL_V1      1
+#define SNMP_SECURITY_MODEL_V2C     2
+#define SNMP_SECURITY_MODEL_USM     3
 
 
 //
@@ -379,6 +398,64 @@ public:
 
 
 //
+// Security context
+//
+
+class LIBNXSNMP_EXPORTABLE SNMP_SecurityContext
+{
+private:
+       int m_securityModel;
+       char *m_community;
+       char *m_user;
+       char *m_authPassword;
+       char *m_encryptionPassword;
+
+public:
+       SNMP_SecurityContext();
+       SNMP_SecurityContext(int securityModel);
+       SNMP_SecurityContext(const char *community);
+       SNMP_SecurityContext(const char *user, const char *authPassword, const char *encryptionPassword);
+       ~SNMP_SecurityContext();
+
+       int getSecurityModel() { return m_securityModel; }
+       const char *getCommunity() { return CHECK_NULL_A(m_community); }
+       const char *getUser() { return CHECK_NULL_A(m_user); }
+       const char *getAuthPassword() { return CHECK_NULL_A(m_authPassword); }
+       const char *getEncryptionPassword() { return CHECK_NULL_A(m_encryptionPassword); }
+
+       void setCommunity(const char *community);
+       void setUser(const char *user);
+       void setAuthPassword(const char *authPassword);
+       void setEncryptionPassword(const char *encryptionPassword);
+};
+
+
+//
+// SNMP engine
+//
+
+class LIBNXSNMP_EXPORTABLE SNMP_Engine
+{
+private:
+       BYTE m_id[SNMP_MAX_ENGINEID_LEN];
+       int m_idLen;
+       int m_engineBoots;
+       int m_engineTime;
+
+public:
+       SNMP_Engine();
+       SNMP_Engine(BYTE *id, int idLen, int engineBoots, int engineTime);
+       SNMP_Engine(SNMP_Engine *src);
+       ~SNMP_Engine();
+
+       BYTE *getId() { return m_id; }
+       int getIdLen() { return m_idLen; }
+       int getBoots() { return m_engineBoots; }
+       int getTime() { return m_engineTime; }
+};
+
+
+//
 // SNMP PDU
 //
 
@@ -387,7 +464,6 @@ class LIBNXSNMP_EXPORTABLE SNMP_PDU
 private:
    DWORD m_dwVersion;
    DWORD m_dwCommand;
-   char *m_pszCommunity;
    DWORD m_dwNumVariables;
    SNMP_Variable **m_ppVarList;
    SNMP_ObjectId *m_pEnterprise;
@@ -398,48 +474,62 @@ private:
    DWORD m_dwRqId;
    DWORD m_dwErrorCode;
    DWORD m_dwErrorIndex;
-       DWORD m_dwMsgMaxSize;
+       SNMP_SecurityContext *m_security;
+       SNMP_Engine *m_authoritativeEngine;
+       DWORD m_msgId;
+       DWORD m_msgMaxSize;
        BYTE m_flags;
-       DWORD m_dwSecurityModel;
-       BYTE m_contextId[SNMP_MAX_CONTEXT_ID];
-       int m_contextIdLen;
+       BYTE m_contextEngineId[SNMP_MAX_ENGINEID_LEN];
+       int m_contextEngineIdLen;
        char m_contextName[SNMP_MAX_CONTEXT_NAME];
 
-   BOOL ParseVariable(BYTE *pData, DWORD dwVarLength);
-   BOOL ParseVarBinds(BYTE *pData, DWORD dwPDULength);
-   BOOL ParsePDU(BYTE *pData, DWORD dwPDULength);
-   BOOL ParseTrapPDU(BYTE *pData, DWORD dwPDULength);
-   BOOL ParseTrap2PDU(BYTE *pData, DWORD dwPDULength);
-       DWORD EncodeV3Header(BYTE *buffer, DWORD bufferSize);
-       DWORD EncodeV3SecurityParameters(BYTE *buffer, DWORD bufferSize);
-       DWORD EncodeV3ScopedPDU(DWORD pduType, BYTE *pdu, DWORD pduSize, BYTE *buffer, DWORD bufferSize);
+   BOOL parseVariable(BYTE *pData, DWORD dwVarLength);
+   BOOL parseVarBinds(BYTE *pData, DWORD dwPDULength);
+   BOOL parsePdu(BYTE *pdu, DWORD pduLength);
+   BOOL parseTrapPDU(BYTE *pData, DWORD dwPDULength);
+   BOOL parseTrap2PDU(BYTE *pData, DWORD dwPDULength);
+   BOOL parsePduContent(BYTE *pData, DWORD dwPDULength);
+   BOOL parseV3Header(BYTE *pData, DWORD dwPDULength);
+   BOOL parseV3SecurityUsm(BYTE *pData, DWORD dwPDULength);
+   BOOL parseV3ScopedPdu(BYTE *pData, DWORD dwPDULength);
+       DWORD encodeV3Header(BYTE *buffer, DWORD bufferSize);
+       DWORD encodeV3SecurityParameters(BYTE *buffer, DWORD bufferSize);
+       DWORD encodeV3ScopedPDU(DWORD pduType, BYTE *pdu, DWORD pduSize, BYTE *buffer, DWORD bufferSize);
 
 public:
    SNMP_PDU();
    SNMP_PDU(DWORD dwCommand, char *pszCommunity, DWORD dwRqId, DWORD dwVersion = SNMP_VERSION_2C);
+   SNMP_PDU(DWORD dwCommand, SNMP_SecurityContext *security, DWORD dwRqId, DWORD dwVersion = SNMP_VERSION_3);
    ~SNMP_PDU();
 
-   BOOL Parse(BYTE *pRawData, DWORD dwRawLength);
-   DWORD Encode(BYTE **ppBuffer);
-
-   DWORD GetCommand(void) { return m_dwCommand; }
-   SNMP_ObjectId *GetTrapId(void) { return m_pEnterprise; }
-   int GetTrapType(void) { return m_iTrapType; }
-   int GetSpecificTrapType(void) { return m_iSpecificTrap; }
-   DWORD GetNumVariables(void) { return m_dwNumVariables; }
-   SNMP_Variable *GetVariable(DWORD dwIndex) { return (dwIndex < m_dwNumVariables) ? m_ppVarList[dwIndex] : NULL; }
-   const char *GetCommunity(void) { return m_pszCommunity; }
-   DWORD GetVersion(void) { return m_dwVersion; }
-   DWORD GetErrorCode(void) { return m_dwErrorCode; }
-
-   DWORD GetRequestId(void) { return m_dwRqId; }
-   void SetRequestId(DWORD dwId) { m_dwRqId = dwId; }
-
-       void SetContextId(BYTE *id, int len);
-       void SetContextId(const char *id);
-       void SetContextName(const char *name);
-
-   void BindVariable(SNMP_Variable *pVar);
+   BOOL parse(BYTE *pRawData, DWORD dwRawLength);
+   DWORD encode(BYTE **ppBuffer);
+
+   DWORD getCommand(void) { return m_dwCommand; }
+   SNMP_ObjectId *getTrapId(void) { return m_pEnterprise; }
+   int getTrapType(void) { return m_iTrapType; }
+   int getSpecificTrapType(void) { return m_iSpecificTrap; }
+   DWORD getNumVariables(void) { return m_dwNumVariables; }
+   SNMP_Variable *getVariable(DWORD dwIndex) { return (dwIndex < m_dwNumVariables) ? m_ppVarList[dwIndex] : NULL; }
+   DWORD getVersion(void) { return m_dwVersion; }
+   DWORD getErrorCode(void) { return m_dwErrorCode; }
+       DWORD getMessageId() { return m_msgId; }
+       SNMP_SecurityContext *getSecurityContext() { return m_security; }
+
+   DWORD getRequestId(void) { return m_dwRqId; }
+   void setRequestId(DWORD dwId) { m_dwRqId = dwId; }
+
+       void setAuthoritativeEngine(SNMP_Engine *engine) { delete m_authoritativeEngine; m_authoritativeEngine = engine; }
+       SNMP_Engine *getAuthoritativeEngine() { return m_authoritativeEngine; }
+
+       void setContextEngineId(BYTE *id, int len);
+       void setContextEngineId(const char *id);
+       void setContextName(const char *name);
+       const char *getContextName() { return m_contextName; }
+       int getContextEngineIdLength() { return m_contextEngineIdLen; }
+       BYTE *getContextEngineId() { return m_contextEngineId; }
+
+   void bindVariable(SNMP_Variable *pVar);
 };
 
 
@@ -449,22 +539,25 @@ public:
 
 class LIBNXSNMP_EXPORTABLE SNMP_Transport
 {
+protected:
+       SNMP_Engine *m_authoritativeEngine;
+
 public:
-   SNMP_Transport() { }
-   virtual ~SNMP_Transport() { }
+   SNMP_Transport();
+   virtual ~SNMP_Transport();
 
-   virtual int Read(SNMP_PDU **ppData, DWORD dwTimeout = INFINITE,
-                    struct sockaddr *pSender = NULL, socklen_t *piAddrSize = NULL)
+   virtual int readMessage(SNMP_PDU **data, DWORD timeout = INFINITE,
+                           struct sockaddr *sender = NULL, socklen_t *addrSize = NULL)
        {
                return -1;
        }
-   virtual int Send(SNMP_PDU *pPDU)
+   virtual int sendMessage(SNMP_PDU *pdu)
        {
                return -1;
        }
 
-   DWORD DoRequest(SNMP_PDU *pRequest, SNMP_PDU **pResponse, 
-                   DWORD dwTimeout = INFINITE, DWORD dwNumRetries = 1);
+   DWORD doRequest(SNMP_PDU *request, SNMP_PDU **response, 
+                   DWORD timeout = INFINITE, int numRetries = 1);
 };
 
 
@@ -481,20 +574,20 @@ private:
    DWORD m_dwBufferPos;
    BYTE *m_pBuffer;
 
-   DWORD PreParsePDU(void);
-   int RecvData(DWORD dwTimeout, struct sockaddr *pSender, socklen_t *piAddrSize);
-   void ClearBuffer(void);
+   DWORD preParsePDU(void);
+   int recvData(DWORD dwTimeout, struct sockaddr *pSender, socklen_t *piAddrSize);
+   void clearBuffer(void);
 
 public:
    SNMP_UDPTransport();
    SNMP_UDPTransport(SOCKET hSocket);
    virtual ~SNMP_UDPTransport();
 
-   virtual int Read(SNMP_PDU **ppData, DWORD dwTimeout = INFINITE,
-                    struct sockaddr *pSender = NULL, socklen_t *piAddrSize = NULL);
-   virtual int Send(SNMP_PDU *pPDU);
+   virtual int readMessage(SNMP_PDU **ppData, DWORD dwTimeout = INFINITE,
+                           struct sockaddr *pSender = NULL, socklen_t *piAddrSize = NULL);
+   virtual int sendMessage(SNMP_PDU *pPDU);
 
-   DWORD CreateUDPTransport(TCHAR *pszHostName, DWORD dwHostAddr = 0, WORD wPort = SNMP_DEFAULT_PORT);
+   DWORD createUDPTransport(TCHAR *pszHostName, DWORD dwHostAddr = 0, WORD wPort = SNMP_DEFAULT_PORT);
 };
 
 
index f7fd5b6..e3336e6 100644 (file)
@@ -72,17 +72,17 @@ static DWORD SONMPTopoHandler(DWORD dwVersion, const char *pszCommunity,
    pRqPDU = new SNMP_PDU(SNMP_GET_REQUEST, (char *)pszCommunity, SnmpNewRequestId(), dwVersion);
    _tcscpy(szOid, ".1.3.6.1.4.1.45.1.6.13.2.1.1.1");   // Slot
    _tcscat(szOid, szSuffix);
-       pRqPDU->BindVariable(new SNMP_Variable(szOid));
+       pRqPDU->bindVariable(new SNMP_Variable(szOid));
    _tcscpy(szOid, ".1.3.6.1.4.1.45.1.6.13.2.1.1.2");   // Port
    _tcscat(szOid, szSuffix);
-       pRqPDU->BindVariable(new SNMP_Variable(szOid));
-   dwResult = pTransport->DoRequest(pRqPDU, &pRespPDU, g_dwSNMPTimeout, 3);
+       pRqPDU->bindVariable(new SNMP_Variable(szOid));
+   dwResult = pTransport->doRequest(pRqPDU, &pRespPDU, g_dwSNMPTimeout, 3);
    delete pRqPDU;
 
    if (dwResult == SNMP_ERR_SUCCESS)
    {
-               _stprintf(szIfName, _T("%d/%d"), pRespPDU->GetVariable(0)->GetValueAsUInt(),
-                         pRespPDU->GetVariable(1)->GetValueAsUInt());
+               _stprintf(szIfName, _T("%d/%d"), pRespPDU->getVariable(0)->GetValueAsUInt(),
+                         pRespPDU->getVariable(1)->GetValueAsUInt());
                ((PeerList *)pArg)->Add(ntohl(pVar->GetValueAsUInt()), szIfName);
       delete pRespPDU;
        }
@@ -112,14 +112,14 @@ static DWORD CDPTopoHandler(DWORD dwVersion, const char *pszCommunity,
    pRqPDU = new SNMP_PDU(SNMP_GET_REQUEST, (char *)pszCommunity, SnmpNewRequestId(), dwVersion);
    _tcscpy(szOid, ".1.3.6.1.4.1.9.9.23.1.2.1.1.7");    // Remote port name
    _tcscat(szOid, szSuffix);
-       pRqPDU->BindVariable(new SNMP_Variable(szOid));
-   dwResult = pTransport->DoRequest(pRqPDU, &pRespPDU, g_dwSNMPTimeout, 3);
+       pRqPDU->bindVariable(new SNMP_Variable(szOid));
+   dwResult = pTransport->doRequest(pRqPDU, &pRespPDU, g_dwSNMPTimeout, 3);
    delete pRqPDU;
 
    if (dwResult == SNMP_ERR_SUCCESS)
    {
                ((PeerList *)pArg)->Add(ntohl(inet_addr(pVar->GetValueAsIPAddr(szIpAddr))),
-                                       pRespPDU->GetVariable(0)->GetValueAsString(szIfName, MAX_CONNECTOR_NAME));
+                                       pRespPDU->getVariable(0)->GetValueAsString(szIfName, MAX_CONNECTOR_NAME));
       delete pRespPDU;
        }
 
index 2f8f38d..4959ca2 100644 (file)
@@ -1282,7 +1282,7 @@ void Node::ConfigurationPoll(ClientSession *pSession, DWORD dwRqId,
       if (!((m_dwFlags & NF_IS_CPSNMP) && (m_dwDynamicFlags & NDF_CPSNMP_UNREACHABLE)) && (m_dwIpAddr != 0))
       {
                        pTransport = new SNMP_UDPTransport;
-                       ((SNMP_UDPTransport *)pTransport)->CreateUDPTransport(NULL, htonl(m_dwIpAddr), CHECKPOINT_SNMP_PORT);
+                       ((SNMP_UDPTransport *)pTransport)->createUDPTransport(NULL, htonl(m_dwIpAddr), CHECKPOINT_SNMP_PORT);
          if (SnmpGet(SNMP_VERSION_1, pTransport, m_szCommunityString,
                      ".1.3.6.1.4.1.2620.1.1.10.0", NULL, 0,
                      szBuffer, 4096, FALSE, FALSE) == SNMP_ERR_SUCCESS)
@@ -1842,7 +1842,7 @@ DWORD Node::GetItemFromCheckPointSNMP(const char *szParam, DWORD dwBufSize, char
                SNMP_Transport *pTransport;
 
                pTransport = new SNMP_UDPTransport;
-               ((SNMP_UDPTransport *)pTransport)->CreateUDPTransport(NULL, htonl(m_dwIpAddr), CHECKPOINT_SNMP_PORT);
+               ((SNMP_UDPTransport *)pTransport)->createUDPTransport(NULL, htonl(m_dwIpAddr), CHECKPOINT_SNMP_PORT);
       dwResult = SnmpGet(SNMP_VERSION_1, pTransport,
                          m_szCommunityString, szParam, NULL, 0, szBuffer,
                          dwBufSize, FALSE, TRUE);
@@ -3003,7 +3003,7 @@ SNMP_Transport *Node::CreateSNMPTransport(void)
        if (m_dwSNMPProxy == 0)
        {
                pTransport = new SNMP_UDPTransport;
-               ((SNMP_UDPTransport *)pTransport)->CreateUDPTransport(NULL, htonl(m_dwIpAddr), m_wSNMPPort);
+               ((SNMP_UDPTransport *)pTransport)->createUDPTransport(NULL, htonl(m_dwIpAddr), m_wSNMPPort);
        }
        else
        {
index 4434520..b2188cf 100644 (file)
@@ -232,7 +232,7 @@ static BOOL AcceptNewNode(DWORD dwIpAddr, DWORD dwNetMask)
    // Check SNMP support
        DbgPrintf(4, "AcceptNewNode(%s): checking SNMP support", szIpAddr);
        pTransport = new SNMP_UDPTransport;
-       pTransport->CreateUDPTransport(NULL, htonl(dwIpAddr), 161);
+       pTransport->createUDPTransport(NULL, htonl(dwIpAddr), 161);
        if (SnmpCheckCommSettings(pTransport, NULL, &data.nSNMPVersion, szCommunityString))
        {
       data.dwFlags |= NNF_IS_SNMP;
index 9c1feb8..3e48684 100644 (file)
@@ -345,16 +345,16 @@ static DWORD TableHandler(DWORD dwVersion, const char *szCommunity, SNMP_Variabl
       dwNameLen = SNMPParseOID(szOid, pdwVarName, MAX_OID_LEN);
       if (dwNameLen != 0)
       {
-         pRqPDU->BindVariable(new SNMP_Variable(pdwVarName, dwNameLen));
+         pRqPDU->bindVariable(new SNMP_Variable(pdwVarName, dwNameLen));
       }
    }
 
-   dwResult = pTransport->DoRequest(pRqPDU, &pRespPDU, g_dwSNMPTimeout, 3);
+   dwResult = pTransport->doRequest(pRqPDU, &pRespPDU, g_dwSNMPTimeout, 3);
    delete pRqPDU;
    if (dwResult == SNMP_ERR_SUCCESS)
    {
-      if ((pRespPDU->GetNumVariables() > 0) &&
-          (pRespPDU->GetErrorCode() == SNMP_PDU_ERR_SUCCESS))
+      if ((pRespPDU->getNumVariables() > 0) &&
+          (pRespPDU->getErrorCode() == SNMP_PDU_ERR_SUCCESS))
       {
          ((SNMP_ENUM_ARGS *)pArg)->dwNumRows++;
 
@@ -365,7 +365,7 @@ static DWORD TableHandler(DWORD dwVersion, const char *szCommunity, SNMP_Variabl
 
          for(i = 1; i < ((SNMP_ENUM_ARGS *)pArg)->dwNumCols; i++)
             AddSNMPResult(&((SNMP_ENUM_ARGS *)pArg)->values, 
-                          pRespPDU->GetVariable(i - 1), 
+                          pRespPDU->getVariable(i - 1), 
                           ((SNMP_ENUM_ARGS *)pArg)->pnFormatList[i],
                           ((SNMP_ENUM_ARGS *)pArg)->pNode);
       }
index 673277c..8850ae4 100644 (file)
@@ -136,16 +136,16 @@ DWORD SnmpGet(DWORD dwVersion, SNMP_Transport *pTransport, const char *szCommuni
 
    if (dwResult == SNMP_ERR_SUCCESS)   // Still no errors
    {
-      pRqPDU->BindVariable(new SNMP_Variable(pdwVarName, dwNameLen));
-      dwResult = pTransport->DoRequest(pRqPDU, &pRespPDU, g_dwSNMPTimeout, 3);
+      pRqPDU->bindVariable(new SNMP_Variable(pdwVarName, dwNameLen));
+      dwResult = pTransport->doRequest(pRqPDU, &pRespPDU, g_dwSNMPTimeout, 3);
 
       // Analyze response
       if (dwResult == SNMP_ERR_SUCCESS)
       {
-         if ((pRespPDU->GetNumVariables() > 0) &&
-             (pRespPDU->GetErrorCode() == SNMP_PDU_ERR_SUCCESS))
+         if ((pRespPDU->getNumVariables() > 0) &&
+             (pRespPDU->getErrorCode() == SNMP_PDU_ERR_SUCCESS))
          {
-            SNMP_Variable *pVar = pRespPDU->GetVariable(0);
+            SNMP_Variable *pVar = pRespPDU->getVariable(0);
 
             if ((pVar->GetType() != ASN_NO_SUCH_OBJECT) &&
                 (pVar->GetType() != ASN_NO_SUCH_INSTANCE))
@@ -188,7 +188,7 @@ DWORD SnmpGet(DWORD dwVersion, SNMP_Transport *pTransport, const char *szCommuni
          }
          else
          {
-            if (pRespPDU->GetErrorCode() == SNMP_PDU_ERR_NO_SUCH_NAME)
+            if (pRespPDU->getErrorCode() == SNMP_PDU_ERR_NO_SUCH_NAME)
                dwResult = SNMP_ERR_NO_OBJECT;
             else
                dwResult = SNMP_ERR_AGENT;
@@ -239,16 +239,16 @@ DWORD SnmpEnumerate(DWORD dwVersion, SNMP_Transport *pTransport, const char *szC
       while(bRunning)
       {
          pRqPDU = new SNMP_PDU(SNMP_GET_NEXT_REQUEST, (char *)szCommunity, m_dwRequestId++, dwVersion);
-         pRqPDU->BindVariable(new SNMP_Variable(pdwName, dwNameLen));
-         dwResult = pTransport->DoRequest(pRqPDU, &pRespPDU, g_dwSNMPTimeout, 3);
+         pRqPDU->bindVariable(new SNMP_Variable(pdwName, dwNameLen));
+         dwResult = pTransport->doRequest(pRqPDU, &pRespPDU, g_dwSNMPTimeout, 3);
 
          // Analyze response
          if (dwResult == SNMP_ERR_SUCCESS)
          {
-            if ((pRespPDU->GetNumVariables() > 0) &&
-                (pRespPDU->GetErrorCode() == SNMP_PDU_ERR_SUCCESS))
+            if ((pRespPDU->getNumVariables() > 0) &&
+                (pRespPDU->getErrorCode() == SNMP_PDU_ERR_SUCCESS))
             {
-               SNMP_Variable *pVar = pRespPDU->GetVariable(0);
+               SNMP_Variable *pVar = pRespPDU->getVariable(0);
 
                if ((pVar->GetType() != ASN_NO_SUCH_OBJECT) &&
                    (pVar->GetType() != ASN_NO_SUCH_INSTANCE))
@@ -283,7 +283,7 @@ DWORD SnmpEnumerate(DWORD dwVersion, SNMP_Transport *pTransport, const char *szC
             }
             else
             {
-               if (pRespPDU->GetErrorCode() == SNMP_PDU_ERR_NO_SUCH_NAME)
+               if (pRespPDU->getErrorCode() == SNMP_PDU_ERR_NO_SUCH_NAME)
                   dwResult = SNMP_ERR_NO_OBJECT;
                else
                   dwResult = SNMP_ERR_AGENT;
index 58c0fd7..9a811d1 100644 (file)
@@ -175,7 +175,7 @@ static void GenerateTrapEvent(DWORD dwObjectId, DWORD dwIndex, SNMP_PDU *pdu)
       if (m_pTrapCfg[dwIndex].pMaps[i].dwOidLen & 0x80000000)
       {
                        // Extract by varbind position
-         pVar = pdu->GetVariable((m_pTrapCfg[dwIndex].pMaps[i].dwOidLen & 0x7FFFFFFF) - 1);
+         pVar = pdu->getVariable((m_pTrapCfg[dwIndex].pMaps[i].dwOidLen & 0x7FFFFFFF) - 1);
          if (pVar != NULL)
          {
             pszArgList[i] = _tcsdup(pVar->GetValueAsString(szBuffer, 256));
@@ -188,18 +188,18 @@ static void GenerateTrapEvent(DWORD dwObjectId, DWORD dwIndex, SNMP_PDU *pdu)
       else
       {
                        // Extract by varbind OID
-         for(j = 0; j < pdu->GetNumVariables(); j++)
+         for(j = 0; j < pdu->getNumVariables(); j++)
          {
-            iResult = pdu->GetVariable(j)->GetName()->Compare(
+            iResult = pdu->getVariable(j)->GetName()->Compare(
                   m_pTrapCfg[dwIndex].pMaps[i].pdwObjectId,
                   m_pTrapCfg[dwIndex].pMaps[i].dwOidLen);
             if ((iResult == OID_EQUAL) || (iResult == OID_SHORTER))
             {
-               pszArgList[i] = _tcsdup(pdu->GetVariable(j)->GetValueAsString(szBuffer, 256));
+               pszArgList[i] = _tcsdup(pdu->getVariable(j)->GetValueAsString(szBuffer, 256));
                break;
             }
          }
-         if (j == pdu->GetNumVariables())
+         if (j == pdu->getNumVariables())
             pszArgList[i] = _tcsdup(_T(""));
       }
    }
@@ -207,7 +207,7 @@ static void GenerateTrapEvent(DWORD dwObjectId, DWORD dwIndex, SNMP_PDU *pdu)
    szFormat[m_pTrapCfg[dwIndex].dwNumMaps + 1] = 0;
    PostEventWithTag(m_pTrapCfg[dwIndex].dwEventCode, dwObjectId,
                         m_pTrapCfg[dwIndex].szUserTag,
-                        szFormat, pdu->GetTrapId()->GetValueAsText(),
+                        szFormat, pdu->getTrapId()->GetValueAsText(),
                     pszArgList[0], pszArgList[1], pszArgList[2], pszArgList[3],
                     pszArgList[4], pszArgList[5], pszArgList[6], pszArgList[7],
                     pszArgList[8], pszArgList[9], pszArgList[10], pszArgList[11],
@@ -247,7 +247,7 @@ static void ProcessTrap(SNMP_PDU *pdu, struct sockaddr_in *pOrigin)
 
    dwOriginAddr = ntohl(pOrigin->sin_addr.s_addr);
    DbgPrintf(4, "Received SNMP trap %s from %s", 
-             pdu->GetTrapId()->GetValueAsText(), IpToStr(dwOriginAddr, szBuffer));
+             pdu->getTrapId()->GetValueAsText(), IpToStr(dwOriginAddr, szBuffer));
 
    // Match IP address to object
    pNode = FindNodeByIP(dwOriginAddr);
@@ -259,12 +259,12 @@ static void ProcessTrap(SNMP_PDU *pdu, struct sockaddr_in *pOrigin)
       TCHAR *pszEscTrapArgs, szQuery[8192];
       DWORD dwTimeStamp = (DWORD)time(NULL);
 
-      dwBufSize = pdu->GetNumVariables() * 4096 + 16;
+      dwBufSize = pdu->getNumVariables() * 4096 + 16;
       pszTrapArgs = (TCHAR *)malloc(sizeof(TCHAR) * dwBufSize);
       pszTrapArgs[0] = 0;
-      for(i = 0, dwBufPos = 0; i < pdu->GetNumVariables(); i++)
+      for(i = 0, dwBufPos = 0; i < pdu->getNumVariables(); i++)
       {
-         pVar = pdu->GetVariable(i);
+         pVar = pdu->getVariable(i);
          dwBufPos += _sntprintf(&pszTrapArgs[dwBufPos], dwBufSize - dwBufPos, _T("%s%s == '%s'"),
                                 (i == 0) ? _T("") : _T("; "),
                                 pVar->GetName()->GetValueAsText(), 
@@ -277,7 +277,7 @@ static void ProcessTrap(SNMP_PDU *pdu, struct sockaddr_in *pOrigin)
                                 _T("ip_addr,object_id,trap_oid,trap_varlist) VALUES ")
                                 _T("(") INT64_FMT _T(",%d,'%s',%d,'%s','%s')"),
                  m_qnTrapId, dwTimeStamp, IpToStr(dwOriginAddr, szBuffer),
-                 (pNode != NULL) ? pNode->Id() : (DWORD)0, pdu->GetTrapId()->GetValueAsText(),
+                 (pNode != NULL) ? pNode->Id() : (DWORD)0, pdu->getTrapId()->GetValueAsText(),
                  pszEscTrapArgs);
       free(pszEscTrapArgs);
       QueueSQLRequest(szQuery);
@@ -290,7 +290,7 @@ static void ProcessTrap(SNMP_PDU *pdu, struct sockaddr_in *pOrigin)
       msg.SetVariable(VID_TRAP_LOG_MSG_BASE + 1, dwTimeStamp);
       msg.SetVariable(VID_TRAP_LOG_MSG_BASE + 2, dwOriginAddr);
       msg.SetVariable(VID_TRAP_LOG_MSG_BASE + 3, (pNode != NULL) ? pNode->Id() : (DWORD)0);
-      msg.SetVariable(VID_TRAP_LOG_MSG_BASE + 4, (TCHAR *)pdu->GetTrapId()->GetValueAsText());
+      msg.SetVariable(VID_TRAP_LOG_MSG_BASE + 4, (TCHAR *)pdu->getTrapId()->GetValueAsText());
       msg.SetVariable(VID_TRAP_LOG_MSG_BASE + 5, pszTrapArgs);
       EnumerateClientSessions(BroadcastNewTrap, &msg);
       free(pszTrapArgs);
@@ -318,7 +318,7 @@ static void ProcessTrap(SNMP_PDU *pdu, struct sockaddr_in *pOrigin)
       {
          if (m_pTrapCfg[i].dwOidLen > 0)
          {
-            iResult = pdu->GetTrapId()->Compare(m_pTrapCfg[i].pdwObjectId, m_pTrapCfg[i].dwOidLen);
+            iResult = pdu->getTrapId()->Compare(m_pTrapCfg[i].pdwObjectId, m_pTrapCfg[i].dwOidLen);
             if (iResult == OID_EQUAL)
             {
                dwMatchLen = m_pTrapCfg[i].dwOidLen;
@@ -346,12 +346,12 @@ static void ProcessTrap(SNMP_PDU *pdu, struct sockaddr_in *pOrigin)
          if (!processed)
          {
             // Build trap's parameters string
-            dwBufSize = pdu->GetNumVariables() * 4096 + 16;
+            dwBufSize = pdu->getNumVariables() * 4096 + 16;
             pszTrapArgs = (TCHAR *)malloc(sizeof(TCHAR) * dwBufSize);
             pszTrapArgs[0] = 0;
-            for(i = 0, dwBufPos = 0; i < pdu->GetNumVariables(); i++)
+            for(i = 0, dwBufPos = 0; i < pdu->getNumVariables(); i++)
             {
-               pVar = pdu->GetVariable(i);
+               pVar = pdu->getVariable(i);
                dwBufPos += _sntprintf(&pszTrapArgs[dwBufPos], dwBufSize - dwBufPos, _T("%s%s == '%s'"),
                                       (i == 0) ? _T("") : _T("; "),
                                       pVar->GetName()->GetValueAsText(), 
@@ -360,7 +360,7 @@ static void ProcessTrap(SNMP_PDU *pdu, struct sockaddr_in *pOrigin)
 
             // Generate default event for unmatched traps
             PostEvent(EVENT_SNMP_UNMATCHED_TRAP, pNode->Id(), "ss", 
-                      pdu->GetTrapId()->GetValueAsText(), pszTrapArgs);
+                      pdu->getTrapId()->GetValueAsText(), pszTrapArgs);
             free(pszTrapArgs);
          }
       }
@@ -413,10 +413,10 @@ THREAD_RESULT THREAD_CALL SNMPTrapReceiver(void *pArg)
    while(!ShutdownInProgress())
    {
       nAddrLen = sizeof(struct sockaddr_in);
-      iBytes = pTransport->Read(&pdu, 2000, (struct sockaddr *)&addr, &nAddrLen);
+      iBytes = pTransport->readMessage(&pdu, 2000, (struct sockaddr *)&addr, &nAddrLen);
       if ((iBytes > 0) && (pdu != NULL))
       {
-         if (pdu->GetCommand() == SNMP_TRAP)
+         if (pdu->getCommand() == SNMP_TRAP)
             ProcessTrap(pdu, &addr);
          delete pdu;
       }
index 697a088..6b0467c 100644 (file)
@@ -396,9 +396,9 @@ public:
        SNMP_ProxyTransport(AgentConnection *pConn, DWORD dwIpAddr, WORD wPort);
        virtual ~SNMP_ProxyTransport();
 
-   virtual int Read(SNMP_PDU **ppData, DWORD dwTimeout = INFINITE,
-                    struct sockaddr *pSender = NULL, socklen_t *piAddrSize = NULL);
-   virtual int Send(SNMP_PDU *pPDU);
+   virtual int readMessage(SNMP_PDU **ppData, DWORD dwTimeout = INFINITE,
+                           struct sockaddr *pSender = NULL, socklen_t *piAddrSize = NULL);
+   virtual int sendMessage(SNMP_PDU *pdu);
 };
 
 
index 38edccb..6a1b1da 100644 (file)
@@ -53,14 +53,14 @@ SNMP_ProxyTransport::~SNMP_ProxyTransport()
 // Send PDU
 //
 
-int SNMP_ProxyTransport::Send(SNMP_PDU *pPDU)
+int SNMP_ProxyTransport::sendMessage(SNMP_PDU *pdu)
 {
    BYTE *pBuffer;
    DWORD dwSize;
    int nRet = -1;
        CSCPMessage msg(m_pAgentConnection->getProtocolVersion());
 
-   dwSize = pPDU->Encode(&pBuffer);
+   dwSize = pdu->encode(&pBuffer);
    if (dwSize != 0)
    {
                msg.SetCode(CMD_SNMP_REQUEST);
@@ -85,8 +85,8 @@ int SNMP_ProxyTransport::Send(SNMP_PDU *pPDU)
 // Receive PDU
 //
 
-int SNMP_ProxyTransport::Read(SNMP_PDU **ppData, DWORD dwTimeout, 
-                              struct sockaddr *pSender, socklen_t *piAddrSize)
+int SNMP_ProxyTransport::readMessage(SNMP_PDU **ppData, DWORD dwTimeout, 
+                                     struct sockaddr *pSender, socklen_t *piAddrSize)
 {
        int nRet;
        BYTE *pBuffer;
@@ -101,7 +101,7 @@ int SNMP_ProxyTransport::Read(SNMP_PDU **ppData, DWORD dwTimeout,
                pBuffer = (BYTE *)malloc(dwSize);
                m_pResponse->GetVariableBinary(VID_PDU, pBuffer, dwSize);
                *ppData = new SNMP_PDU;
-               if (!(*ppData)->Parse(pBuffer, dwSize))
+               if (!(*ppData)->parse(pBuffer, dwSize))
                {
                        delete *ppData;
                        *ppData = NULL;
index 9e8ce8a..40485ac 100644 (file)
@@ -1,6 +1,7 @@
 INCLUDES=-I@top_srcdir@/include
 
-SOURCES = ber.cpp main.cpp mib.cpp oid.cpp pdu.cpp transport.cpp variable.cpp zfile.cpp
+SOURCES = ber.cpp engine.cpp main.cpp mib.cpp oid.cpp pdu.cpp \
+          security.cpp transport.cpp variable.cpp zfile.cpp
 
 if BUILD_UNICODE_LIBS
 lib_LTLIBRARIES = libnxsnmp.la libnxsnmpw.la
diff --git a/src/snmp/libnxsnmp/engine.cpp b/src/snmp/libnxsnmp/engine.cpp
new file mode 100644 (file)
index 0000000..d30aa98
--- /dev/null
@@ -0,0 +1,61 @@
+/* 
+** NetXMS - Network Management System
+** SNMP support library
+** Copyright (C) 2003-2009 Victor Kirhenshtein
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+** File: engine.cpp
+**
+**/
+
+#include "libnxsnmp.h"
+
+
+//
+// Constructors
+//
+
+SNMP_Engine::SNMP_Engine()
+{
+       m_idLen = 0;
+       m_engineBoots = 0;
+       m_engineTime = 0;
+}
+
+SNMP_Engine::SNMP_Engine(BYTE *id, int idLen, int engineBoots, int engineTime)
+{
+       m_idLen = min(idLen, SNMP_MAX_ENGINEID_LEN);
+       memcpy(m_id, id, m_idLen);
+       m_engineBoots = 0;
+       m_engineTime = 0;
+}
+
+SNMP_Engine::SNMP_Engine(SNMP_Engine *src)
+{
+       m_idLen = src->m_idLen;
+       memcpy(m_id, src->m_id, m_idLen);
+       m_engineBoots = src->m_engineBoots;
+       m_engineTime = src->m_engineTime;
+}
+
+
+//
+// Destructor
+//
+
+SNMP_Engine::~SNMP_Engine()
+{
+}
index 950e888..084e1d5 100644 (file)
                        />\r
                </Configuration>\r
                <Configuration\r
-                       Name="Release|Win32"\r
-                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"\r
-                       IntermediateDirectory="$(ConfigurationName)"\r
+                       Name="Debug|x64"\r
+                       OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
                        ConfigurationType="2"\r
                        CharacterSet="2"\r
-                       WholeProgramOptimization="1"\r
                        >\r
                        <Tool\r
                                Name="VCPreBuildEventTool"\r
                        />\r
                        <Tool\r
                                Name="VCMIDLTool"\r
+                               TargetEnvironment="3"\r
                        />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
                                AdditionalIncludeDirectories="..\..\..\include;..\..\zlib"\r
-                               PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBNXSNMP_EXPORTS"\r
-                               RuntimeLibrary="2"\r
+                               PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBNXSNMP_EXPORTS"\r
+                               MinimalRebuild="true"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="3"\r
                                UsePrecompiledHeader="0"\r
                                WarningLevel="3"\r
-                               Detect64BitPortabilityProblems="false"\r
+                               Detect64BitPortabilityProblems="true"\r
                                DebugInformationFormat="3"\r
                        />\r
                        <Tool\r
                        <Tool\r
                                Name="VCLinkerTool"\r
                                AdditionalDependencies="ws2_32.lib"\r
-                               LinkIncremental="1"\r
+                               LinkIncremental="2"\r
                                GenerateDebugInformation="true"\r
                                SubSystem="2"\r
-                               OptimizeReferences="2"\r
-                               EnableCOMDATFolding="2"\r
-                               TargetMachine="1"\r
+                               TargetMachine="17"\r
                        />\r
                        <Tool\r
                                Name="VCALinkTool"\r
                        />\r
                </Configuration>\r
                <Configuration\r
-                       Name="Debug|x64"\r
-                       OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"\r
-                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       Name="Release|Win32"\r
+                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"\r
+                       IntermediateDirectory="$(ConfigurationName)"\r
                        ConfigurationType="2"\r
                        CharacterSet="2"\r
+                       WholeProgramOptimization="1"\r
                        >\r
                        <Tool\r
                                Name="VCPreBuildEventTool"\r
                        />\r
                        <Tool\r
                                Name="VCMIDLTool"\r
-                               TargetEnvironment="3"\r
                        />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
-                               Optimization="0"\r
                                AdditionalIncludeDirectories="..\..\..\include;..\..\zlib"\r
-                               PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBNXSNMP_EXPORTS"\r
-                               MinimalRebuild="true"\r
-                               BasicRuntimeChecks="3"\r
-                               RuntimeLibrary="3"\r
+                               PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBNXSNMP_EXPORTS"\r
+                               RuntimeLibrary="2"\r
                                UsePrecompiledHeader="0"\r
                                WarningLevel="3"\r
-                               Detect64BitPortabilityProblems="true"\r
+                               Detect64BitPortabilityProblems="false"\r
                                DebugInformationFormat="3"\r
                        />\r
                        <Tool\r
                        <Tool\r
                                Name="VCLinkerTool"\r
                                AdditionalDependencies="ws2_32.lib"\r
-                               LinkIncremental="2"\r
+                               LinkIncremental="1"\r
                                GenerateDebugInformation="true"\r
                                SubSystem="2"\r
-                               TargetMachine="17"\r
+                               OptimizeReferences="2"\r
+                               EnableCOMDATFolding="2"\r
+                               TargetMachine="1"\r
                        />\r
                        <Tool\r
                                Name="VCALinkTool"\r
                                >\r
                        </File>\r
                        <File\r
+                               RelativePath=".\engine.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
                                RelativePath=".\main.cpp"\r
                                >\r
                        </File>\r
                                >\r
                        </File>\r
                        <File\r
+                               RelativePath=".\security.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
                                RelativePath=".\transport.cpp"\r
                                >\r
                        </File>\r
index 73773a4..dc512a4 100644 (file)
                        />\r
                </Configuration>\r
                <Configuration\r
-                       Name="Release|Win32"\r
-                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"\r
-                       IntermediateDirectory="$(ConfigurationName)_UNICODE"\r
+                       Name="Debug|x64"\r
+                       OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)_UNICODE"\r
                        ConfigurationType="2"\r
                        CharacterSet="1"\r
-                       WholeProgramOptimization="1"\r
                        >\r
                        <Tool\r
                                Name="VCPreBuildEventTool"\r
                        />\r
                        <Tool\r
                                Name="VCMIDLTool"\r
+                               TargetEnvironment="3"\r
                        />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
                                AdditionalIncludeDirectories="..\..\..\include;..\..\zlib"\r
-                               PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBNXSNMP_EXPORTS"\r
-                               RuntimeLibrary="2"\r
+                               PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBNXSNMP_EXPORTS"\r
+                               MinimalRebuild="true"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="3"\r
                                UsePrecompiledHeader="0"\r
                                WarningLevel="3"\r
-                               Detect64BitPortabilityProblems="false"\r
+                               Detect64BitPortabilityProblems="true"\r
                                DebugInformationFormat="3"\r
                        />\r
                        <Tool\r
                        <Tool\r
                                Name="VCLinkerTool"\r
                                AdditionalDependencies="ws2_32.lib"\r
-                               LinkIncremental="1"\r
+                               LinkIncremental="2"\r
                                GenerateDebugInformation="true"\r
                                SubSystem="2"\r
-                               OptimizeReferences="2"\r
-                               EnableCOMDATFolding="2"\r
-                               TargetMachine="1"\r
+                               TargetMachine="17"\r
                        />\r
                        <Tool\r
                                Name="VCALinkTool"\r
                        />\r
                </Configuration>\r
                <Configuration\r
-                       Name="Debug|x64"\r
-                       OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"\r
-                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)_UNICODE"\r
+                       Name="Release|Win32"\r
+                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"\r
+                       IntermediateDirectory="$(ConfigurationName)_UNICODE"\r
                        ConfigurationType="2"\r
                        CharacterSet="1"\r
+                       WholeProgramOptimization="1"\r
                        >\r
                        <Tool\r
                                Name="VCPreBuildEventTool"\r
                        />\r
                        <Tool\r
                                Name="VCMIDLTool"\r
-                               TargetEnvironment="3"\r
                        />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
-                               Optimization="0"\r
                                AdditionalIncludeDirectories="..\..\..\include;..\..\zlib"\r
-                               PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBNXSNMP_EXPORTS"\r
-                               MinimalRebuild="true"\r
-                               BasicRuntimeChecks="3"\r
-                               RuntimeLibrary="3"\r
+                               PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBNXSNMP_EXPORTS"\r
+                               RuntimeLibrary="2"\r
                                UsePrecompiledHeader="0"\r
                                WarningLevel="3"\r
-                               Detect64BitPortabilityProblems="true"\r
+                               Detect64BitPortabilityProblems="false"\r
                                DebugInformationFormat="3"\r
                        />\r
                        <Tool\r
                        <Tool\r
                                Name="VCLinkerTool"\r
                                AdditionalDependencies="ws2_32.lib"\r
-                               LinkIncremental="2"\r
+                               LinkIncremental="1"\r
                                GenerateDebugInformation="true"\r
                                SubSystem="2"\r
-                               TargetMachine="17"\r
+                               OptimizeReferences="2"\r
+                               EnableCOMDATFolding="2"\r
+                               TargetMachine="1"\r
                        />\r
                        <Tool\r
                                Name="VCALinkTool"\r
                                >\r
                        </File>\r
                        <File\r
+                               RelativePath=".\engine.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
                                RelativePath=".\main.cpp"\r
                                >\r
                        </File>\r
                                >\r
                        </File>\r
                        <File\r
+                               RelativePath=".\security.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
                                RelativePath=".\transport.cpp"\r
                                >\r
                        </File>\r
index 359ed53..75fc2ae 100644 (file)
@@ -103,7 +103,7 @@ const TCHAR LIBNXSNMP_EXPORTABLE *SNMPGetErrorText(DWORD dwError)
       _T("Invalid parameters passed to function"),
       _T("Unable to create socket"),
       _T("Communication error"),
-      _T("Rrror parsing PDU"),
+      _T("Error parsing PDU"),
       _T("No such object"),
       _T("Invalid hostname or IP address"),
       _T("OID is incorrect"),
@@ -111,10 +111,17 @@ const TCHAR LIBNXSNMP_EXPORTABLE *SNMPGetErrorText(DWORD dwError)
       _T("Unknown variable data type"),
       _T("File I/O error"),
       _T("Invalid file header"),
-      _T("Invalid or corrupted file data")
+      _T("Invalid or corrupted file data"),
+      _T("Unsupported security level"),
+      _T("Not in time window"),
+      _T("Unknown security name"),
+      _T("Unknown engine ID"),
+      _T("Authentication failure"),
+      _T("Decryption error"),
+      _T("Malformed or unexpected response from agent")
    };
 
-   return ((dwError >= SNMP_ERR_SUCCESS) && (dwError <= SNMP_ERR_BAD_FILE_DATA)) ?
+   return ((dwError >= SNMP_ERR_SUCCESS) && (dwError <= SNMP_ERR_BAD_RESPONSE)) ?
       pszErrorText[dwError] : _T("Unknown error");
 }
 
index ef3d162..43d69e1 100644 (file)
@@ -1,7 +1,7 @@
 /* 
 ** NetXMS - Network Management System
 ** SNMP support library
-** Copyright (C) 2003, 2004, 2005 Victor Kirhenshtein
+** Copyright (C) 2003-2009 Victor Kirhenshtein
 **
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU General Public License as published by
@@ -17,7 +17,7 @@
 ** along with this program; if not, write to the Free Software
 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 **
-** $module: pdu.cpp
+** File: pdu.cpp
 **
 **/
 
@@ -41,7 +41,9 @@ static struct
    { ASN_GET_REQUEST_PDU, -1, SNMP_GET_REQUEST },
    { ASN_GET_NEXT_REQUEST_PDU, -1, SNMP_GET_NEXT_REQUEST },
    { ASN_SET_REQUEST_PDU, -1, SNMP_SET_REQUEST },
-   { ASN_GET_RESPONSE_PDU, -1, SNMP_GET_RESPONSE },
+   { ASN_RESPONSE_PDU, -1, SNMP_RESPONSE },
+   { ASN_REPORT_PDU, -1, SNMP_REPORT },
+   { ASN_INFORM_REQUEST_PDU, -1, SNMP_INFORM_REQUEST },
    { 0, -1, 0 }
 };
 
@@ -54,15 +56,21 @@ SNMP_PDU::SNMP_PDU()
 {
    m_dwVersion = SNMP_VERSION_1;
    m_dwCommand = SNMP_INVALID_PDU;
-   m_pszCommunity = NULL;
+   m_security = new SNMP_SecurityContext;
    m_dwNumVariables = 0;
    m_ppVarList = NULL;
    m_pEnterprise = NULL;
    m_dwErrorCode = 0;
    m_dwErrorIndex = 0;
    m_dwRqId = 0;
+       m_msgId = 0;
+       m_flags = 0;
    m_iTrapType = 0;
    m_iSpecificTrap = 0;
+       m_authoritativeEngine = NULL;
+       m_contextEngineIdLen = 0;
+       m_contextName[0] = 0;
+       m_msgMaxSize = SNMP_DEFAULT_MSG_MAX_SIZE;
 }
 
 
@@ -74,15 +82,47 @@ SNMP_PDU::SNMP_PDU(DWORD dwCommand, char *pszCommunity, DWORD dwRqId, DWORD dwVe
 {
    m_dwVersion = dwVersion;
    m_dwCommand = dwCommand;
-   m_pszCommunity = strdup(CHECK_NULL_A(pszCommunity));
+   m_security = new SNMP_SecurityContext(pszCommunity);
    m_dwNumVariables = 0;
    m_ppVarList = NULL;
    m_pEnterprise = NULL;
    m_dwErrorCode = 0;
    m_dwErrorIndex = 0;
    m_dwRqId = dwRqId;
+       m_msgId = dwRqId;
+       m_flags = 0;
    m_iTrapType = 0;
    m_iSpecificTrap = 0;
+       m_authoritativeEngine = NULL;
+       m_contextEngineIdLen = 0;
+       m_contextName[0] = 0;
+       m_msgMaxSize = SNMP_DEFAULT_MSG_MAX_SIZE;
+}
+
+
+//
+// Create request PDU
+//
+
+SNMP_PDU::SNMP_PDU(DWORD dwCommand, SNMP_SecurityContext *security, DWORD dwRqId, DWORD dwVersion)
+{
+   m_dwVersion = SNMP_VERSION_3;
+   m_dwCommand = dwCommand;
+   m_security = security;
+   m_dwNumVariables = 0;
+   m_ppVarList = NULL;
+   m_pEnterprise = NULL;
+   m_dwErrorCode = 0;
+   m_dwErrorIndex = 0;
+   m_dwRqId = dwRqId;
+       m_msgId = dwRqId;
+       m_flags = 0;
+   m_iTrapType = 0;
+   m_iSpecificTrap = 0;
+       m_authoritativeEngine = NULL;
+       m_contextEngineIdLen = 0;
+       m_contextName[0] = 0;
+       m_msgMaxSize = SNMP_DEFAULT_MSG_MAX_SIZE;
 }
 
 
@@ -94,7 +134,8 @@ SNMP_PDU::~SNMP_PDU()
 {
    DWORD i;
 
-   safe_free(m_pszCommunity);
+   delete m_security;
+       delete m_authoritativeEngine;
    delete m_pEnterprise;
    for(i = 0; i < m_dwNumVariables; i++)
       delete m_ppVarList[i];
@@ -106,22 +147,22 @@ SNMP_PDU::~SNMP_PDU()
 // Parse single variable binding
 //
 
-BOOL SNMP_PDU::ParseVariable(BYTE *pData, DWORD dwVarLength)
+BOOL SNMP_PDU::parseVariable(BYTE *pData, DWORD dwVarLength)
 {
-   SNMP_Variable *pVar;
-   BOOL bResult = TRUE;
+   SNMP_Variable *var;
+   BOOL success = TRUE;
 
-   pVar = new SNMP_Variable;
-   if (pVar->Parse(pData, dwVarLength))
+   var = new SNMP_Variable;
+   if (var->Parse(pData, dwVarLength))
    {
-      BindVariable(pVar);
+      bindVariable(var);
    }
    else
    {
-      delete pVar;
-      bResult = FALSE;
+      delete var;
+      success = FALSE;
    }
-   return bResult;
+   return success;
 }
 
 
@@ -129,7 +170,7 @@ BOOL SNMP_PDU::ParseVariable(BYTE *pData, DWORD dwVarLength)
 // Parse variable bindings
 //
 
-BOOL SNMP_PDU::ParseVarBinds(BYTE *pData, DWORD dwPDULength)
+BOOL SNMP_PDU::parseVarBinds(BYTE *pData, DWORD dwPDULength)
 {
    BYTE *pbCurrPos;
    DWORD dwType, dwLength, dwBindingLength, dwIdLength;
@@ -149,7 +190,7 @@ BOOL SNMP_PDU::ParseVarBinds(BYTE *pData, DWORD dwPDULength)
       if (dwLength > dwBindingLength)
          return FALSE;     // Invalid length
 
-      if (!ParseVariable(pbCurrPos, dwLength))
+      if (!parseVariable(pbCurrPos, dwLength))
          return FALSE;
       dwBindingLength -= dwLength + dwIdLength;
       pbCurrPos += dwLength;
@@ -160,10 +201,10 @@ BOOL SNMP_PDU::ParseVarBinds(BYTE *pData, DWORD dwPDULength)
 
 
 //
-// Parse generic PDU
+// Parse generic PDU content
 //
 
-BOOL SNMP_PDU::ParsePDU(BYTE *pData, DWORD dwPDULength)
+BOOL SNMP_PDU::parsePduContent(BYTE *pData, DWORD dwPDULength)
 {
    DWORD dwType, dwLength ,dwIdLength;
    BYTE *pbCurrPos = pData;
@@ -214,7 +255,7 @@ BOOL SNMP_PDU::ParsePDU(BYTE *pData, DWORD dwPDULength)
    }
 
    if (bResult)
-      bResult = ParseVarBinds(pbCurrPos, dwPDULength);
+      bResult = parseVarBinds(pbCurrPos, dwPDULength);
 
    return bResult;
 }
@@ -224,7 +265,7 @@ BOOL SNMP_PDU::ParsePDU(BYTE *pData, DWORD dwPDULength)
 // Parse version 1 TRAP PDU
 //
 
-BOOL SNMP_PDU::ParseTrapPDU(BYTE *pData, DWORD dwPDULength)
+BOOL SNMP_PDU::parseTrapPDU(BYTE *pData, DWORD dwPDULength)
 {
    DWORD dwType, dwLength, dwIdLength;
    BYTE *pbCurrPos = pData;
@@ -319,7 +360,7 @@ BOOL SNMP_PDU::ParseTrapPDU(BYTE *pData, DWORD dwPDULength)
    }
 
    if (bResult)
-      bResult = ParseVarBinds(pbCurrPos, dwPDULength);
+      bResult = parseVarBinds(pbCurrPos, dwPDULength);
 
    if (bResult)
    {
@@ -353,12 +394,12 @@ BOOL SNMP_PDU::ParseTrapPDU(BYTE *pData, DWORD dwPDULength)
 // Parse version 2 TRAP PDU
 //
 
-BOOL SNMP_PDU::ParseTrap2PDU(BYTE *pData, DWORD dwPDULength)
+BOOL SNMP_PDU::parseTrap2PDU(BYTE *pData, DWORD dwPDULength)
 {
    BOOL bResult;
    static DWORD pdwStdTrapPrefix[9] = { 1, 3, 6, 1, 6, 3, 1, 1, 5 };
 
-   bResult = ParsePDU(pData, dwPDULength);
+   bResult = parsePduContent(pData, dwPDULength);
    if (bResult)
    {
       bResult = FALSE;
@@ -394,77 +435,296 @@ BOOL SNMP_PDU::ParseTrap2PDU(BYTE *pData, DWORD dwPDULength)
 
 
 //
-// Create PDU from packet
+// Parse version 3 header
 //
 
-BOOL SNMP_PDU::Parse(BYTE *pRawData, DWORD dwRawLength)
+BOOL SNMP_PDU::parseV3Header(BYTE *header, DWORD headerLength)
 {
-   BYTE *pbCurrPos;
-   DWORD dwType, dwLength, dwPacketLength, dwIdLength;
-   BOOL bResult = FALSE;
+       DWORD type, length, idLength, remLength = headerLength;
+       BYTE *currPos = header;
 
-   // Packet start
-   if (!BER_DecodeIdentifier(pRawData, dwRawLength, &dwType, &dwPacketLength, &pbCurrPos, &dwIdLength))
+   // Message id
+   if (!BER_DecodeIdentifier(currPos, remLength, &type, &length, &currPos, &idLength))
       return FALSE;
-   if (dwType != ASN_SEQUENCE)
-      return FALSE;   // Packet should start with SEQUENCE
+   if (type != ASN_INTEGER)
+      return FALSE;   // Should be of integer type
+   if (!BER_DecodeContent(type, currPos, length, (BYTE *)&m_msgId))
+      return FALSE;   // Error parsing content
+   currPos += length;
+   remLength -= length + idLength;
+
+   // Message max size
+   if (!BER_DecodeIdentifier(currPos, remLength, &type, &length, &currPos, &idLength))
+      return FALSE;
+   if (type != ASN_INTEGER)
+      return FALSE;   // Should be of integer type
+   if (!BER_DecodeContent(type, currPos, length, (BYTE *)&m_msgMaxSize))
+      return FALSE;   // Error parsing content
+   currPos += length;
+   remLength -= length + idLength;
+
+   // Message flags
+   if (!BER_DecodeIdentifier(currPos, remLength, &type, &length, &currPos, &idLength))
+      return FALSE;
+   if ((type != ASN_OCTET_STRING) || (length != 1))
+      return FALSE;
+       BYTE flags;
+   if (!BER_DecodeContent(type, currPos, length, &flags))
+      return FALSE;   // Error parsing content
+       m_flags = flags;
+   currPos += length;
+   remLength -= length + idLength;
+
+   // Security model
+   if (!BER_DecodeIdentifier(currPos, remLength, &type, &length, &currPos, &idLength))
+      return FALSE;
+   if (type != ASN_INTEGER)
+      return FALSE;   // Should be of integer type
+       DWORD securityModel;
+   if (!BER_DecodeContent(type, currPos, length, (BYTE *)&securityModel))
+      return FALSE;   // Error parsing content
+   currPos += length;
+   remLength -= length + idLength;
+
+       delete m_security;
+       m_security = new SNMP_SecurityContext(securityModel);
+
+       return TRUE;
+}
 
-   // Version
-   if (!BER_DecodeIdentifier(pbCurrPos, dwPacketLength, &dwType, &dwLength, &pbCurrPos, &dwIdLength))
+
+//
+// Parse V3 USM security parameters
+//
+
+BOOL SNMP_PDU::parseV3SecurityUsm(BYTE *data, DWORD dataLength)
+{
+       DWORD type, length, idLength, remLength = dataLength;
+       DWORD engineBoots, engineTime;
+       BYTE *currPos = data;
+       BYTE engineId[SNMP_MAX_ENGINEID_LEN];
+       int engineIdLen;
+
+       // Should be sequence
+   if (!BER_DecodeIdentifier(currPos, remLength, &type, &length, &currPos, &idLength))
       return FALSE;
-   if (dwType != ASN_INTEGER)
-      return FALSE;   // Version field should be of integer type
-   if (!BER_DecodeContent(dwType, pbCurrPos, dwLength, (BYTE *)&m_dwVersion))
-      return FALSE;   // Error parsing content of version field
-   pbCurrPos += dwLength;
-   dwPacketLength -= dwLength + dwIdLength;
-   if ((m_dwVersion != SNMP_VERSION_1) && (m_dwVersion != SNMP_VERSION_2C))
-      return FALSE;   // Unsupported SNMP version
+   if (type != ASN_SEQUENCE)
+      return FALSE;
+   remLength = length;
 
-   // Community string
-   if (!BER_DecodeIdentifier(pbCurrPos, dwPacketLength, &dwType, &dwLength, &pbCurrPos, &dwIdLength))
+       // Engine ID
+   if (!BER_DecodeIdentifier(currPos, remLength, &type, &length, &currPos, &idLength))
       return FALSE;
-   if (dwType != ASN_OCTET_STRING)
-      return FALSE;   // Community field should be of string type
-   m_pszCommunity = (char *)malloc(dwLength + 1);
-   if (!BER_DecodeContent(dwType, pbCurrPos, dwLength, (BYTE *)m_pszCommunity))
-      return FALSE;   // Error parsing content of version field
-   m_pszCommunity[dwLength] = 0;
-   pbCurrPos += dwLength;
-   dwPacketLength -= dwLength + dwIdLength;
+   if (type != ASN_OCTET_STRING)
+      return FALSE;
+       engineIdLen = length;
+   if (!BER_DecodeContent(type, currPos, length, engineId))
+      return FALSE;   // Error parsing content
+   currPos += length;
+   remLength -= length + idLength;
+
+       // engine boots
+   if (!BER_DecodeIdentifier(currPos, remLength, &type, &length, &currPos, &idLength))
+      return FALSE;
+   if (type != ASN_INTEGER)
+      return FALSE;
+   if (!BER_DecodeContent(type, currPos, length, (BYTE *)&engineBoots))
+      return FALSE;   // Error parsing content
+   currPos += length;
+   remLength -= length + idLength;
+
+       // engine time
+   if (!BER_DecodeIdentifier(currPos, remLength, &type, &length, &currPos, &idLength))
+      return FALSE;
+   if (type != ASN_INTEGER)
+      return FALSE;
+   if (!BER_DecodeContent(type, currPos, length, (BYTE *)&engineTime))
+      return FALSE;   // Error parsing content
+   currPos += length;
+   remLength -= length + idLength;
+
+       setAuthoritativeEngine(new SNMP_Engine(engineId, engineIdLen, engineBoots, engineTime));
+
+       return TRUE;
+}
+
+
+//
+// Parse V3 scoped PDU
+//
+
+BOOL SNMP_PDU::parseV3ScopedPdu(BYTE *data, DWORD dataLength)
+{
+       DWORD type, length, idLength, remLength = dataLength;
+       BYTE *currPos = data;
 
-   if (BER_DecodeIdentifier(pbCurrPos, dwPacketLength, &dwType, &dwLength, &pbCurrPos, &dwIdLength))
+   // Context engine ID
+   if (!BER_DecodeIdentifier(currPos, remLength, &type, &length, &currPos, &idLength))
+      return FALSE;
+   if ((type != ASN_OCTET_STRING) || (length > SNMP_MAX_ENGINEID_LEN))
+      return FALSE;
+       m_contextEngineIdLen = length;
+   if (!BER_DecodeContent(type, currPos, length, m_contextEngineId))
+      return FALSE;   // Error parsing content
+   currPos += length;
+   remLength -= length + idLength;
+       
+   // Context name
+   if (!BER_DecodeIdentifier(currPos, remLength, &type, &length, &currPos, &idLength))
+      return FALSE;
+   if ((type != ASN_OCTET_STRING) || (length >= SNMP_MAX_CONTEXT_NAME))
+      return FALSE;
+   if (!BER_DecodeContent(type, currPos, length, (BYTE *)m_contextName))
+      return FALSE;   // Error parsing content
+       m_contextName[length] = 0;
+   currPos += length;
+   remLength -= length + idLength;
+       
+       return parsePdu(currPos, remLength);
+}
+
+
+//
+// Parse PDU
+//
+
+BOOL SNMP_PDU::parsePdu(BYTE *pdu, DWORD pduLength)
+{
+       BYTE *content;
+       DWORD length, idLength, type;
+       BOOL success;
+
+   if (success = BER_DecodeIdentifier(pdu, pduLength, &type, &length, &content, &idLength))
    {
-      switch(dwType)
+      switch(type)
       {
          case ASN_TRAP_V1_PDU:
             m_dwCommand = SNMP_TRAP;
-            bResult = ParseTrapPDU(pbCurrPos, dwLength);
+            success = parseTrapPDU(content, length);
             break;
          case ASN_TRAP_V2_PDU:
             m_dwCommand = SNMP_TRAP;
-            bResult = ParseTrap2PDU(pbCurrPos, dwLength);
+            success = parseTrap2PDU(content, length);
             break;
          case ASN_GET_REQUEST_PDU:
             m_dwCommand = SNMP_GET_REQUEST;
-            bResult = ParsePDU(pbCurrPos, dwLength);
+            success = parsePduContent(content, length);
             break;
          case ASN_GET_NEXT_REQUEST_PDU:
             m_dwCommand = SNMP_GET_NEXT_REQUEST;
-            bResult = ParsePDU(pbCurrPos, dwLength);
+            success = parsePduContent(content, length);
             break;
-         case ASN_GET_RESPONSE_PDU:
-            m_dwCommand = SNMP_GET_RESPONSE;
-            bResult = ParsePDU(pbCurrPos, dwLength);
+         case ASN_RESPONSE_PDU:
+            m_dwCommand = SNMP_RESPONSE;
+            success = parsePduContent(content, length);
             break;
          case ASN_SET_REQUEST_PDU:
             m_dwCommand = SNMP_SET_REQUEST;
-            bResult = ParsePDU(pbCurrPos, dwLength);
+            success = parsePduContent(content, length);
+            break;
+         case ASN_INFORM_REQUEST_PDU:
+            m_dwCommand = SNMP_INFORM_REQUEST;
+            success = parsePduContent(content, length);
+            break;
+         case ASN_REPORT_PDU:
+            m_dwCommand = SNMP_REPORT;
+            success = parsePduContent(content, length);
             break;
          default:
+                               success = FALSE;
             break;
       }
    }
+       return success;
+}
+
+
+//
+// Create PDU from packet
+//
+
+BOOL SNMP_PDU::parse(BYTE *pRawData, DWORD dwRawLength)
+{
+   BYTE *pbCurrPos;
+   DWORD dwType, dwLength, dwPacketLength, dwIdLength;
+   BOOL bResult = FALSE;
+
+   // Packet start
+   if (!BER_DecodeIdentifier(pRawData, dwRawLength, &dwType, &dwPacketLength, &pbCurrPos, &dwIdLength))
+      return FALSE;
+   if (dwType != ASN_SEQUENCE)
+      return FALSE;   // Packet should start with SEQUENCE
+
+   // Version
+   if (!BER_DecodeIdentifier(pbCurrPos, dwPacketLength, &dwType, &dwLength, &pbCurrPos, &dwIdLength))
+      return FALSE;
+   if (dwType != ASN_INTEGER)
+      return FALSE;   // Version field should be of integer type
+   if (!BER_DecodeContent(dwType, pbCurrPos, dwLength, (BYTE *)&m_dwVersion))
+      return FALSE;   // Error parsing content of version field
+   pbCurrPos += dwLength;
+   dwPacketLength -= dwLength + dwIdLength;
+   if ((m_dwVersion != SNMP_VERSION_1) && (m_dwVersion != SNMP_VERSION_2C) && ((m_dwVersion != SNMP_VERSION_3)))
+      return FALSE;   // Unsupported SNMP version
+
+       if (m_dwVersion == SNMP_VERSION_3)
+       {
+               // V3 header
+               if (!BER_DecodeIdentifier(pbCurrPos, dwPacketLength, &dwType, &dwLength, &pbCurrPos, &dwIdLength))
+                       return FALSE;
+               if (dwType != ASN_SEQUENCE)
+                       return FALSE;   // Should be sequence
+               
+               // We don't need BER_DecodeContent because sequence does not need any special decoding
+               if (!parseV3Header(pbCurrPos, dwLength))
+                       return FALSE;
+               pbCurrPos += dwLength;
+               dwPacketLength -= dwLength + dwIdLength;
+
+               // Security parameters
+               if (!BER_DecodeIdentifier(pbCurrPos, dwPacketLength, &dwType, &dwLength, &pbCurrPos, &dwIdLength))
+                       return FALSE;
+               if (dwType != ASN_OCTET_STRING)
+                       return FALSE;   // Should be octet string
+
+               if (m_security->getSecurityModel() == SNMP_SECURITY_MODEL_USM)
+               {
+                       if (!parseV3SecurityUsm(pbCurrPos, dwLength))
+                               return FALSE;
+               }
+
+               pbCurrPos += dwLength;
+               dwPacketLength -= dwLength + dwIdLength;
+
+               // Scoped PDU
+               if (!BER_DecodeIdentifier(pbCurrPos, dwPacketLength, &dwType, &dwLength, &pbCurrPos, &dwIdLength))
+                       return FALSE;
+               if (dwType != ASN_SEQUENCE)
+                       return FALSE;   // Should be sequence
+               bResult = parseV3ScopedPdu(pbCurrPos, dwLength);
+       }
+       else
+       {
+               // Community string
+               if (!BER_DecodeIdentifier(pbCurrPos, dwPacketLength, &dwType, &dwLength, &pbCurrPos, &dwIdLength))
+                       return FALSE;
+               if (dwType != ASN_OCTET_STRING)
+                       return FALSE;   // Community field should be of string type
+               char *community = (char *)malloc(dwLength + 1);
+               if (!BER_DecodeContent(dwType, pbCurrPos, dwLength, (BYTE *)community))
+               {
+                       free(community);
+                       return FALSE;   // Error parsing content of version field
+               }
+               community[dwLength] = 0;
+               delete m_security;
+               m_security = new SNMP_SecurityContext(community);
+               free(community);
+               pbCurrPos += dwLength;
+               dwPacketLength -= dwLength + dwIdLength;
+
+               bResult = parsePdu(pbCurrPos, dwLength);
+       }
 
    return bResult;
 }
@@ -474,7 +734,7 @@ BOOL SNMP_PDU::Parse(BYTE *pRawData, DWORD dwRawLength)
 // Create packet from PDU
 //
 
-DWORD SNMP_PDU::Encode(BYTE **ppBuffer)
+DWORD SNMP_PDU::encode(BYTE **ppBuffer)
 {
    DWORD i, dwBufferSize, dwBytes, dwVarBindsSize, dwPDUType, dwPDUSize, dwPacketSize, dwValue;
    BYTE *pbCurrPos, *pBlock, *pVarBinds, *pPacket;
@@ -574,21 +834,24 @@ DWORD SNMP_PDU::Encode(BYTE **ppBuffer)
 
                if (m_dwVersion == SNMP_VERSION_3)
                {
-                       dwBytes = EncodeV3Header(pbCurrPos, dwBufferSize - dwPacketSize);
+                       if (m_authoritativeEngine == NULL)
+                               m_authoritativeEngine = new SNMP_Engine;
+
+                       dwBytes = encodeV3Header(pbCurrPos, dwBufferSize - dwPacketSize);
                        dwPacketSize += dwBytes;
                        pbCurrPos += dwBytes;
 
-                       dwBytes = EncodeV3SecurityParameters(pbCurrPos, dwBufferSize - dwPacketSize);
+                       dwBytes = encodeV3SecurityParameters(pbCurrPos, dwBufferSize - dwPacketSize);
                        dwPacketSize += dwBytes;
                        pbCurrPos += dwBytes;
 
-                       dwBytes = EncodeV3ScopedPDU(dwPDUType, pBlock, dwPDUSize, pbCurrPos, dwBufferSize - dwPacketSize);
+                       dwBytes = encodeV3ScopedPDU(dwPDUType, pBlock, dwPDUSize, pbCurrPos, dwBufferSize - dwPacketSize);
                        dwPacketSize += dwBytes;
                }
                else
                {
-                       dwBytes = BER_Encode(ASN_OCTET_STRING, (BYTE *)m_pszCommunity,
-                                                                               (DWORD)strlen(m_pszCommunity), pbCurrPos,
+                       dwBytes = BER_Encode(ASN_OCTET_STRING, (BYTE *)m_security->getCommunity(),
+                                                                               (DWORD)strlen(m_security->getCommunity()), pbCurrPos,
                                                                                dwBufferSize - dwPacketSize);
                        dwPacketSize += dwBytes;
                        pbCurrPos += dwBytes;
@@ -619,15 +882,15 @@ DWORD SNMP_PDU::Encode(BYTE **ppBuffer)
 // Encode version 3 header
 //
 
-DWORD SNMP_PDU::EncodeV3Header(BYTE *buffer, DWORD bufferSize)
+DWORD SNMP_PDU::encodeV3Header(BYTE *buffer, DWORD bufferSize)
 {
        BYTE header[256];
-       DWORD bytes;
+       DWORD bytes, securityModel = m_security->getSecurityModel();
 
        bytes = BER_Encode(ASN_INTEGER, (BYTE *)&m_dwRqId, sizeof(DWORD), header, 256);
-       bytes += BER_Encode(ASN_INTEGER, (BYTE *)&m_dwMsgMaxSize, sizeof(DWORD), &header[bytes], 256 - bytes);
+       bytes += BER_Encode(ASN_INTEGER, (BYTE *)&m_msgMaxSize, sizeof(DWORD), &header[bytes], 256 - bytes);
        bytes += BER_Encode(ASN_OCTET_STRING, &m_flags, 1, &header[bytes], 256 - bytes);
-       bytes += BER_Encode(ASN_INTEGER, (BYTE *)&m_dwSecurityModel, sizeof(DWORD), &header[bytes], 256 - bytes);
+       bytes += BER_Encode(ASN_INTEGER, (BYTE *)&securityModel, sizeof(DWORD), &header[bytes], 256 - bytes);
        return BER_Encode(ASN_SEQUENCE, header, bytes, buffer, bufferSize);
 }
 
@@ -636,9 +899,49 @@ DWORD SNMP_PDU::EncodeV3Header(BYTE *buffer, DWORD bufferSize)
 // Encode version 3 security parameters
 //
 
-DWORD SNMP_PDU::EncodeV3SecurityParameters(BYTE *buffer, DWORD bufferSize)
+DWORD SNMP_PDU::encodeV3SecurityParameters(BYTE *buffer, DWORD bufferSize)
 {
-       return 0;
+       BYTE securityParameters[1024], sequence[1040];
+       DWORD bytes, engineBoots = m_authoritativeEngine->getBoots(), engineTime = m_authoritativeEngine->getTime();
+
+       if ((m_security != NULL) && (m_security->getSecurityModel() == SNMP_SECURITY_MODEL_USM))
+       {
+               bytes = BER_Encode(ASN_OCTET_STRING, m_authoritativeEngine->getId(), m_authoritativeEngine->getIdLen(), securityParameters, 1024);
+               bytes += BER_Encode(ASN_INTEGER, (BYTE *)&engineBoots, sizeof(DWORD), &securityParameters[bytes], 1024 - bytes);
+               bytes += BER_Encode(ASN_INTEGER, (BYTE *)&engineTime, sizeof(DWORD), &securityParameters[bytes], 1024 - bytes);
+               bytes += BER_Encode(ASN_OCTET_STRING, (BYTE *)m_security->getUser(), strlen(m_security->getUser()), &securityParameters[bytes], 1024 - bytes);
+
+               // Authentication parameters
+               if (m_flags & SNMP_AUTH_FLAG)
+               {
+                       /* TODO: implement authentication */
+               }
+               else
+               {
+                       bytes += BER_Encode(ASN_OCTET_STRING, NULL, 0, &securityParameters[bytes], 1024 - bytes);
+               }
+
+               // Privacy parameters
+               if (m_flags & SNMP_PRIV_FLAG)
+               {
+                       /* TODO: implement encryption */
+               }
+               else
+               {
+                       bytes += BER_Encode(ASN_OCTET_STRING, NULL, 0, &securityParameters[bytes], 1024 - bytes);
+               }
+
+               // Wrap into sequence
+               bytes = BER_Encode(ASN_SEQUENCE, securityParameters, bytes, sequence, 1040);
+
+               // Wrap sequence into octet string
+               bytes = BER_Encode(ASN_OCTET_STRING, sequence, bytes, buffer, bufferSize);
+       }
+       else
+       {
+               bytes = BER_Encode(ASN_OCTET_STRING, NULL, 0, buffer, bufferSize);
+       }
+       return bytes;
 }
 
 
@@ -646,13 +949,13 @@ DWORD SNMP_PDU::EncodeV3SecurityParameters(BYTE *buffer, DWORD bufferSize)
 // Encode versionj 3 scoped PDU
 //
 
-DWORD SNMP_PDU::EncodeV3ScopedPDU(DWORD pduType, BYTE *pdu, DWORD pduSize, BYTE *buffer, DWORD bufferSize)
+DWORD SNMP_PDU::encodeV3ScopedPDU(DWORD pduType, BYTE *pdu, DWORD pduSize, BYTE *buffer, DWORD bufferSize)
 {
-       DWORD spduLen = pduSize + SNMP_MAX_CONTEXT_NAME + SNMP_MAX_CONTEXT_ID + 32;
+       DWORD spduLen = pduSize + SNMP_MAX_CONTEXT_NAME + SNMP_MAX_ENGINEID_LEN + 32;
        BYTE *spdu = (BYTE *)malloc(spduLen);
        DWORD bytes;
 
-       bytes = BER_Encode(ASN_OCTET_STRING, m_contextId, (DWORD)m_contextIdLen, spdu, spduLen);
+       bytes = BER_Encode(ASN_OCTET_STRING, m_contextEngineId, (DWORD)m_contextEngineIdLen, spdu, spduLen);
        bytes += BER_Encode(ASN_OCTET_STRING, (BYTE *)m_contextName, strlen(m_contextName), &spdu[bytes], spduLen - bytes);
        bytes += BER_Encode(pduType, pdu, pduSize, &spdu[bytes], spduLen - bytes);
        
@@ -667,7 +970,7 @@ DWORD SNMP_PDU::EncodeV3ScopedPDU(DWORD pduType, BYTE *pdu, DWORD pduSize, BYTE
 // Bind variable to PDU
 //
 
-void SNMP_PDU::BindVariable(SNMP_Variable *pVar)
+void SNMP_PDU::bindVariable(SNMP_Variable *pVar)
 {
    m_ppVarList = (SNMP_Variable **)realloc(m_ppVarList, sizeof(SNMP_Variable *) * (m_dwNumVariables + 1));
    m_ppVarList[m_dwNumVariables] = pVar;
@@ -679,16 +982,16 @@ void SNMP_PDU::BindVariable(SNMP_Variable *pVar)
 // Set context ID
 //
 
-void SNMP_PDU::SetContextId(BYTE *id, int len)
+void SNMP_PDU::setContextEngineId(BYTE *id, int len)
 {
-       m_contextIdLen = min(len, SNMP_MAX_CONTEXT_ID);
-       memcpy(m_contextId, id, m_contextIdLen);
+       m_contextEngineIdLen = min(len, SNMP_MAX_ENGINEID_LEN);
+       memcpy(m_contextEngineId, id, m_contextEngineIdLen);
 }
 
-void SNMP_PDU::SetContextId(const char *id)
+void SNMP_PDU::setContextEngineId(const char *id)
 {
-       m_contextIdLen = min(strlen(id), SNMP_MAX_CONTEXT_ID);
-       memcpy(m_contextId, id, m_contextIdLen);
+       m_contextEngineIdLen = min(strlen(id), SNMP_MAX_ENGINEID_LEN);
+       memcpy(m_contextEngineId, id, m_contextEngineIdLen);
 }
 
 
@@ -696,7 +999,7 @@ void SNMP_PDU::SetContextId(const char *id)
 // Set context name
 //
 
-void SNMP_PDU::SetContextName(const char *name)
+void SNMP_PDU::setContextName(const char *name)
 {
        strncpy(m_contextName, name, SNMP_MAX_CONTEXT_NAME);
        m_contextName[SNMP_MAX_CONTEXT_NAME - 1] = 0;
diff --git a/src/snmp/libnxsnmp/security.cpp b/src/snmp/libnxsnmp/security.cpp
new file mode 100644 (file)
index 0000000..a3a8e35
--- /dev/null
@@ -0,0 +1,122 @@
+/* 
+** NetXMS - Network Management System
+** SNMP support library
+** Copyright (C) 2003-2009 Victor Kirhenshtein
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+** File: security.cpp
+**
+**/
+
+#include "libnxsnmp.h"
+
+
+//
+// Constructors for SNMP_SecurityContext
+//
+
+SNMP_SecurityContext::SNMP_SecurityContext()
+{
+       m_securityModel = 0;
+       m_community = NULL;
+       m_user = NULL;
+       m_authPassword = NULL;
+       m_encryptionPassword = NULL;
+}
+
+SNMP_SecurityContext::SNMP_SecurityContext(int securityModel)
+{
+       m_securityModel = securityModel;
+       m_community = NULL;
+       m_user = NULL;
+       m_authPassword = NULL;
+       m_encryptionPassword = NULL;
+}
+
+SNMP_SecurityContext::SNMP_SecurityContext(const char *community)
+{
+       m_securityModel = SNMP_SECURITY_MODEL_V2C;
+       m_community = strdup(CHECK_NULL_A(community));
+       m_user = NULL;
+       m_authPassword = NULL;
+       m_encryptionPassword = NULL;
+}
+
+SNMP_SecurityContext::SNMP_SecurityContext(const char *user, const char *authPassword, const char *encryptionPassword)
+{
+       m_securityModel = SNMP_SECURITY_MODEL_USM;
+       m_community = NULL;
+       m_user = strdup(CHECK_NULL_A(user));
+       m_authPassword = strdup(CHECK_NULL_A(authPassword));
+       m_encryptionPassword = strdup(CHECK_NULL_A(encryptionPassword));
+}
+
+
+//
+// Destructor for security context
+//
+
+SNMP_SecurityContext::~SNMP_SecurityContext()
+{
+       safe_free(m_community);
+       safe_free(m_user);
+       safe_free(m_authPassword);
+       safe_free(m_encryptionPassword);
+}
+
+
+//
+// Set community
+//
+
+void SNMP_SecurityContext::setCommunity(const char *community)
+{
+       safe_free(m_community);
+       m_community = strdup(CHECK_NULL_A(community));
+}
+
+
+//
+// Set user
+//
+
+void SNMP_SecurityContext::setUser(const char *user)
+{
+       safe_free(m_user);
+       m_user = strdup(CHECK_NULL_A(user));
+}
+
+
+//
+// Set authentication password
+//
+
+void SNMP_SecurityContext::setAuthPassword(const char *authPassword)
+{
+       safe_free(m_authPassword);
+       m_authPassword = strdup(CHECK_NULL_A(authPassword));
+}
+
+
+//
+// Set encryption password
+//
+
+void SNMP_SecurityContext::setEncryptionPassword(const char *encryptionPassword)
+{
+       safe_free(m_encryptionPassword);
+       m_encryptionPassword = strdup(CHECK_NULL_A(encryptionPassword));
+}
index 611d10c..e4e8f9a 100644 (file)
 
 
 //
-// Constants
+// Report to SNMP error mapping
 //
 
-#define DEFAULT_BUFFER_SIZE      32768
+static struct
+{
+       const TCHAR *oid;
+       DWORD errorCode;
+} m_oidToErrorMap[] =
+{
+       { _T(".1.3.6.1.6.3.15.1.1.1.0"), SNMP_ERR_UNSUPP_SEC_LEVEL },
+       { _T(".1.3.6.1.6.3.15.1.1.2.0"), SNMP_ERR_TIME_WINDOW },
+       { _T(".1.3.6.1.6.3.15.1.1.3.0"), SNMP_ERR_SEC_NAME },
+       { _T(".1.3.6.1.6.3.15.1.1.4.0"), SNMP_ERR_ENGINE_ID },
+       { _T(".1.3.6.1.6.3.15.1.1.5.0"), SNMP_ERR_AUTH_FAILURE },
+       { _T(".1.3.6.1.6.3.15.1.1.6.0"), SNMP_ERR_DECRYPTION },
+       { NULL, 0 }
+};
+
+
+//
+// Constructor
+//
+
+SNMP_Transport::SNMP_Transport()
+{
+       m_authoritativeEngine = NULL;
+}
+
+
+//
+// Destructor
+//
+
+SNMP_Transport::~SNMP_Transport()
+{
+       delete m_authoritativeEngine;
+}
 
 
 //
 // with respect for timeouts and retransmissions
 //
 
-DWORD SNMP_Transport::DoRequest(SNMP_PDU *pRequest, SNMP_PDU **ppResponse, 
-                                DWORD dwTimeout, DWORD dwNumRetries)
+DWORD SNMP_Transport::doRequest(SNMP_PDU *request, SNMP_PDU **response, 
+                                DWORD timeout, int numRetries)
 {
-   DWORD dwResult;
-   int iBytes;
+   DWORD rc;
+   int bytes;
 
-   if ((pRequest == NULL) || (ppResponse == NULL) || (dwNumRetries == 0))
+   if ((request == NULL) || (response == NULL) || (numRetries == 0))
       return SNMP_ERR_PARAM;
 
-   *ppResponse = NULL;
+   *response = NULL;
+       // Set authoritative engine for PDU if we have cached one
+       if ((request->getVersion() == SNMP_VERSION_3) &&
+                (request->getAuthoritativeEngine() == NULL) &&
+                (m_authoritativeEngine != NULL))
+       {
+               request->setAuthoritativeEngine(new SNMP_Engine(m_authoritativeEngine));
+       }
 
-   while(dwNumRetries-- > 0)
+   while(numRetries-- >= 0)
    {
-               dwResult = SNMP_ERR_SUCCESS;
-      if (Send(pRequest) <= 0)
+retry:
+               rc = SNMP_ERR_SUCCESS;
+      if (sendMessage(request) <= 0)
       {
-         dwResult = SNMP_ERR_COMM;
+         rc = SNMP_ERR_COMM;
          break;
       }
 
-      iBytes = Read(ppResponse, dwTimeout);
-      if (iBytes > 0)
+      bytes = readMessage(response, timeout);
+      if (bytes > 0)
       {
-         if (*ppResponse != NULL)
+         if (*response != NULL)
          {
-            if ((*ppResponse)->GetRequestId() == pRequest->GetRequestId())
-               break;
-            dwResult = SNMP_ERR_TIMEOUT;
+                               if (request->getVersion() == SNMP_VERSION_3)
+                               {
+                                       if ((*response)->getMessageId() == request->getMessageId())
+                                       {
+                                               // Cache authoritative engine ID
+                                               if ((m_authoritativeEngine == NULL) && ((*response)->getAuthoritativeEngine() != NULL))
+                                                       m_authoritativeEngine = new SNMP_Engine((*response)->getAuthoritativeEngine());
+
+                                               if ((*response)->getCommand() == SNMP_REPORT)
+                                               {
+                              SNMP_Variable *var = (*response)->getVariable(0);
+                                                       const TCHAR *oid = var->GetName()->GetValueAsText();
+                                                       rc = SNMP_ERR_AGENT;
+                                                       for(int i = 0; m_oidToErrorMap[i].oid != NULL; i++)
+                                                       {
+                                                               if (!_tcscmp(oid, m_oidToErrorMap[i].oid))
+                                                               {
+                                                                       rc = m_oidToErrorMap[i].errorCode;
+                                                                       break;
+                                                               }
+                                                       }
+
+                                                       // Engine ID discovery - if request contains empty engine ID,
+                                                       // replace it with correct one and retry
+                                                       if (rc == SNMP_ERR_ENGINE_ID)
+                                                       {
+                                                               bool canRetry = false;
+
+                                                               if (request->getContextEngineIdLength() == 0)
+                                                               {
+                                                                       request->setContextEngineId((*response)->getContextEngineId(), (*response)->getContextEngineIdLength());
+                                                                       canRetry = true;
+                                                               }
+                                                               if (request->getAuthoritativeEngine()->getIdLen() == 0)
+                                                               {
+                                                                       request->setAuthoritativeEngine(new SNMP_Engine((*response)->getAuthoritativeEngine()));
+                                                                       canRetry = true;
+                                                               }
+                                                               if (canRetry)
+                                                                       goto retry;
+                                                       }
+                                               }
+                                               else if ((*response)->getCommand() != SNMP_RESPONSE)
+                                               {
+                                                       rc = SNMP_ERR_BAD_RESPONSE;
+                                               }
+                                               break;
+                                       }
+                               }
+                               else
+                               {
+                                       if ((*response)->getRequestId() == request->getRequestId())
+                                               break;
+                               }
+            rc = SNMP_ERR_TIMEOUT;
          }
          else
          {
-            dwResult = SNMP_ERR_PARSE;
+            rc = SNMP_ERR_PARSE;
             break;
          }
       }
       else
       {
-         dwResult = (iBytes == 0) ? SNMP_ERR_TIMEOUT : SNMP_ERR_COMM;
+         rc = (bytes == 0) ? SNMP_ERR_TIMEOUT : SNMP_ERR_COMM;
       }
    }
 
-   return dwResult;
+   return rc;
 }
 
 
@@ -90,7 +183,7 @@ SNMP_UDPTransport::SNMP_UDPTransport()
                   :SNMP_Transport()
 {
    m_hSocket = -1;
-   m_dwBufferSize = DEFAULT_BUFFER_SIZE;
+   m_dwBufferSize = SNMP_DEFAULT_MSG_MAX_SIZE;
    m_dwBufferPos = 0;
    m_dwBytesInBuffer = 0;
    m_pBuffer = (BYTE *)malloc(m_dwBufferSize);
@@ -105,7 +198,7 @@ SNMP_UDPTransport::SNMP_UDPTransport(SOCKET hSocket)
                   :SNMP_Transport()
 {
    m_hSocket = hSocket;
-   m_dwBufferSize = DEFAULT_BUFFER_SIZE;
+   m_dwBufferSize = SNMP_DEFAULT_MSG_MAX_SIZE;
    m_dwBufferPos = 0;
    m_dwBytesInBuffer = 0;
    m_pBuffer = (BYTE *)malloc(m_dwBufferSize);
@@ -118,7 +211,7 @@ SNMP_UDPTransport::SNMP_UDPTransport(SOCKET hSocket)
 // IP address will be used
 //
 
-DWORD SNMP_UDPTransport::CreateUDPTransport(TCHAR *pszHostName, DWORD dwHostAddr, WORD wPort)
+DWORD SNMP_UDPTransport::createUDPTransport(TCHAR *pszHostName, DWORD dwHostAddr, WORD wPort)
 {
    struct sockaddr_in addr;
    DWORD dwResult;
@@ -217,7 +310,7 @@ SNMP_UDPTransport::~SNMP_UDPTransport()
 // Clear buffer
 //
 
-void SNMP_UDPTransport::ClearBuffer(void)
+void SNMP_UDPTransport::clearBuffer(void)
 {
    m_dwBytesInBuffer = 0;
    m_dwBufferPos = 0;
@@ -228,7 +321,7 @@ void SNMP_UDPTransport::ClearBuffer(void)
 // Receive data from socket
 //
 
-int SNMP_UDPTransport::RecvData(DWORD dwTimeout, struct sockaddr *pSender, socklen_t *piAddrSize)
+int SNMP_UDPTransport::recvData(DWORD dwTimeout, struct sockaddr *pSender, socklen_t *piAddrSize)
 {
    fd_set rdfs;
    struct timeval tv;
@@ -274,7 +367,7 @@ int SNMP_UDPTransport::RecvData(DWORD dwTimeout, struct sockaddr *pSender, sockl
 // Pre-parse PDU
 //
 
-DWORD SNMP_UDPTransport::PreParsePDU(void)
+DWORD SNMP_UDPTransport::preParsePDU(void)
 {
    DWORD dwType, dwLength, dwIdLength;
    BYTE *pbCurrPos;
@@ -293,28 +386,28 @@ DWORD SNMP_UDPTransport::PreParsePDU(void)
 // Read PDU from socket
 //
 
-int SNMP_UDPTransport::Read(SNMP_PDU **ppData, DWORD dwTimeout, 
-                            struct sockaddr *pSender, socklen_t *piAddrSize)
+int SNMP_UDPTransport::readMessage(SNMP_PDU **ppData, DWORD dwTimeout, 
+                                   struct sockaddr *pSender, socklen_t *piAddrSize)
 {
    int iBytes;
    DWORD dwPDULength;
 
    if (m_dwBytesInBuffer < 2)
    {
-      iBytes = RecvData(dwTimeout, pSender, piAddrSize);
+      iBytes = recvData(dwTimeout, pSender, piAddrSize);
       if (iBytes <= 0)
       {
-         ClearBuffer();
+         clearBuffer();
          return iBytes;
       }
       m_dwBytesInBuffer += iBytes;
    }
 
-   dwPDULength = PreParsePDU();
+   dwPDULength = preParsePDU();
    if (dwPDULength == 0)
    {
       // Clear buffer
-      ClearBuffer();
+      clearBuffer();
       return 0;
    }
 
@@ -328,10 +421,10 @@ int SNMP_UDPTransport::Read(SNMP_PDU **ppData, DWORD dwTimeout,
    // Read entire PDU into buffer
    while(m_dwBytesInBuffer < dwPDULength)
    {
-      iBytes = RecvData(dwTimeout, pSender, piAddrSize);
+      iBytes = recvData(dwTimeout, pSender, piAddrSize);
       if (iBytes <= 0)
       {
-         ClearBuffer();
+         clearBuffer();
          return iBytes;
       }
       m_dwBytesInBuffer += iBytes;
@@ -339,7 +432,7 @@ int SNMP_UDPTransport::Read(SNMP_PDU **ppData, DWORD dwTimeout,
 
    // Create new PDU object and remove parsed data from buffer
    *ppData = new SNMP_PDU;
-   if (!(*ppData)->Parse(&m_pBuffer[m_dwBufferPos], dwPDULength))
+   if (!(*ppData)->parse(&m_pBuffer[m_dwBufferPos], dwPDULength))
    {
       delete *ppData;
       *ppData = NULL;
@@ -356,13 +449,13 @@ int SNMP_UDPTransport::Read(SNMP_PDU **ppData, DWORD dwTimeout,
 // Send PDU to socket
 //
 
-int SNMP_UDPTransport::Send(SNMP_PDU *pPDU)
+int SNMP_UDPTransport::sendMessage(SNMP_PDU *pPDU)
 {
    BYTE *pBuffer;
    DWORD dwSize;
    int nBytes = 0;
 
-   dwSize = pPDU->Encode(&pBuffer);
+   dwSize = pPDU->encode(&pBuffer);
    if (dwSize != 0)
    {
       nBytes = send(m_hSocket, (char *)pBuffer, dwSize, 0);
index fb0d78a..d15f51b 100644 (file)
 // Static data
 //
 
-static char m_szCommunity[256] = "public";
-static WORD m_wPort = 161;
-static DWORD m_dwVersion = SNMP_VERSION_2C;
-static DWORD m_dwTimeout = 3000;
+static char m_community[256] = "public";
+static char m_user[256] = "";
+static char m_authPassword[256] = "";
+static char m_encryptionPassword[256] = "";
+static WORD m_port = 161;
+static DWORD m_snmpVersion = SNMP_VERSION_2C;
+static DWORD m_timeout = 3000;
 
 
 //
@@ -55,7 +58,7 @@ int GetData(int argc, char *argv[])
 
    // Create SNMP transport
    pTransport = new SNMP_UDPTransport;
-   dwResult = pTransport->CreateUDPTransport(argv[0], 0, m_wPort);
+   dwResult = pTransport->createUDPTransport(argv[0], 0, m_port);
    if (dwResult != SNMP_ERR_SUCCESS)
    {
       printf("Unable to create UDP transport: %s\n", SNMPGetErrorText(dwResult));
@@ -64,12 +67,15 @@ int GetData(int argc, char *argv[])
    else
    {
       // Create request
-      request = new SNMP_PDU(SNMP_GET_REQUEST, m_szCommunity, getpid(), m_dwVersion);
+               if (m_snmpVersion == SNMP_VERSION_3)
+                       request = new SNMP_PDU(SNMP_GET_REQUEST, new SNMP_SecurityContext(m_user, m_authPassword, m_encryptionPassword), getpid(), SNMP_VERSION_3);
+               else
+                       request = new SNMP_PDU(SNMP_GET_REQUEST, m_community, getpid(), m_snmpVersion);
       for(i = 1; i < argc; i++)
       {
          if (SNMPIsCorrectOID(argv[i]))
          {
-            request->BindVariable(new SNMP_Variable(argv[i]));
+            request->bindVariable(new SNMP_Variable(argv[i]));
          }
          else
          {
@@ -81,14 +87,14 @@ int GetData(int argc, char *argv[])
       // Send request and process response
       if (iExit == 0)
       {
-         if ((dwResult = pTransport->DoRequest(request, &response, m_dwTimeout, 3)) == SNMP_ERR_SUCCESS)
+         if ((dwResult = pTransport->doRequest(request, &response, m_timeout, 3)) == SNMP_ERR_SUCCESS)
          {
             SNMP_Variable *var;
             char szBuffer[1024];
 
-            for(i = 0; i < (int)response->GetNumVariables(); i++)
+            for(i = 0; i < (int)response->getNumVariables(); i++)
             {
-               var = response->GetVariable(i);
+               var = response->getVariable(i);
                if (var->GetType() == ASN_NO_SUCH_OBJECT)
                {
                   printf("No such object: %s\n", var->GetName()->GetValueAsText());
@@ -133,24 +139,36 @@ int main(int argc, char *argv[])
 
    // Parse command line
    opterr = 1;
-   while((ch = getopt(argc, argv, "c:hp:v:")) != -1)
+       while((ch = getopt(argc, argv, "A:c:E:hp:u:v:w:")) != -1)
    {
       switch(ch)
       {
          case 'h':   // Display help and exit
             printf("Usage: nxsnmpget [<options>] <host> <variables>\n"
                    "Valid options are:\n"
-                   "   -c <string>  : Specify community string. Default is \"public\".\n"
-                   "   -h           : Display help and exit.\n"
-                   "   -p <port>    : Specify agent's port number. Default is 161.\n"
-                   "   -v <version> : Specify SNMP version (valid values is 1 and 2c).\n"
-                   "   -w <seconds> : Specify request timeout (default is 3 seconds)\n"
+                   "   -A <passwd>  : User's authentication password for SNMP v3 USM\n"
+                   "   -c <string>  : Community string. Default is \"public\"\n"
+                   "   -E <passwd>  : User's encryption password for SNMP v3 USM\n"
+                   "   -h           : Display help and exit\n"
+                   "   -p <port>    : Agent's port number. Default is 161\n"
+                   "   -u <user>    : User name for SNMP v3 USM\n"
+                   "   -v <version> : SNMP version to use (valid values is 1, 2c, and 3)\n"
+                   "   -w <seconds> : Request timeout (default is 3 seconds)\n"
                    "\n");
             iExit = 0;
             bStart = FALSE;
             break;
          case 'c':   // Community
-            nx_strncpy(m_szCommunity, optarg, 256);
+            nx_strncpy(m_community, optarg, 256);
+            break;
+         case 'u':   // User
+            nx_strncpy(m_user, optarg, 256);
+            break;
+         case 'A':   // authentication password
+            nx_strncpy(m_authPassword, optarg, 256);
+            break;
+         case 'E':   // encription password
+            nx_strncpy(m_encryptionPassword, optarg, 256);
             break;
          case 'p':   // Port number
             dwValue = strtoul(optarg, &eptr, 0);
@@ -161,17 +179,21 @@ int main(int argc, char *argv[])
             }
             else
             {
-               m_wPort = (WORD)dwValue;
+               m_port = (WORD)dwValue;
             }
             break;
          case 'v':   // Version
             if (!strcmp(optarg, "1"))
             {
-               m_dwVersion = SNMP_VERSION_1;
+               m_snmpVersion = SNMP_VERSION_1;
             }
             else if (!stricmp(optarg, "2c"))
             {
-               m_dwVersion = SNMP_VERSION_2C;
+               m_snmpVersion = SNMP_VERSION_2C;
+            }
+            else if (!stricmp(optarg, "3"))
+            {
+               m_snmpVersion = SNMP_VERSION_3;
             }
             else
             {
@@ -188,7 +210,7 @@ int main(int argc, char *argv[])
             }
             else
             {
-               m_dwTimeout = dwValue;
+               m_timeout = dwValue;
             }
             break;
          case '?':
index 702fa6c..4bf8595 100644 (file)
@@ -1,6 +1,6 @@
 /* 
-** nxsnmpget - command line tool used to retrieve parameters from SNMP agent
-** Copyright (C) 2004 Victor Kirhenshtein
+** nxsnmpset - command line tool used to set parameters on SNMP agent
+** Copyright (C) 2004-2009 Victor Kirhenshtein
 **
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU General Public License as published by
@@ -16,7 +16,7 @@
 ** along with this program; if not, write to the Free Software
 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 **
-** $module: nxsnmpget.cpp
+** File: nxsnmpset.cpp
 **
 **/
 
 // Static data
 //
 
-static char m_szCommunity[256] = "public";
-static WORD m_wPort = 161;
-static DWORD m_dwVersion = SNMP_VERSION_2C;
-static DWORD m_dwTimeout = 3000;
-static DWORD m_dwType = ASN_OCTET_STRING;
+static char m_community[256] = "public";
+static char m_user[256] = "";
+static char m_authPassword[256] = "";
+static char m_encryptionPassword[256] = "";
+static WORD m_port = 161;
+static DWORD m_snmpVersion = SNMP_VERSION_2C;
+static DWORD m_timeout = 3000;
+static DWORD m_type = ASN_OCTET_STRING;
 
 
 //
@@ -57,7 +60,7 @@ static int SetVariables(int argc, char *argv[])
 
    // Create SNMP transport
    pTransport = new SNMP_UDPTransport;
-   dwResult = pTransport->CreateUDPTransport(argv[0], 0, m_wPort);
+   dwResult = pTransport->createUDPTransport(argv[0], 0, m_port);
    if (dwResult != SNMP_ERR_SUCCESS)
    {
       printf("Unable to create UDP transport: %s\n", SNMPGetErrorText(dwResult));
@@ -66,14 +69,17 @@ static int SetVariables(int argc, char *argv[])
    else
    {
       // Create request
-      request = new SNMP_PDU(SNMP_SET_REQUEST, m_szCommunity, getpid(), m_dwVersion);
+               if (m_snmpVersion == SNMP_VERSION_3)
+                       request = new SNMP_PDU(SNMP_SET_REQUEST, new SNMP_SecurityContext(m_user, m_authPassword, m_encryptionPassword), getpid(), SNMP_VERSION_3);
+               else
+                       request = new SNMP_PDU(SNMP_SET_REQUEST, m_community, getpid(), m_snmpVersion);
       for(i = 1; i < argc; i += 2)
       {
          if (SNMPIsCorrectOID(argv[i]))
          {
             pVar = new SNMP_Variable(argv[i]);
-            pVar->SetValueFromString(m_dwType, argv[i + 1]);
-            request->BindVariable(pVar);
+            pVar->SetValueFromString(m_type, argv[i + 1]);
+            request->bindVariable(pVar);
          }
          else
          {
@@ -85,11 +91,11 @@ static int SetVariables(int argc, char *argv[])
       // Send request and process response
       if (iExit == 0)
       {
-         if ((dwResult = pTransport->DoRequest(request, &response, m_dwTimeout, 3)) == SNMP_ERR_SUCCESS)
+         if ((dwResult = pTransport->doRequest(request, &response, m_timeout, 3)) == SNMP_ERR_SUCCESS)
          {
-            if (response->GetErrorCode() != 0)
+            if (response->getErrorCode() != 0)
             {
-               printf("SET operation failed (error code %d)\n", response->GetErrorCode());
+               printf("SET operation failed (error code %d)\n", response->getErrorCode());
             }
             delete response;
          }
@@ -121,19 +127,22 @@ int main(int argc, char *argv[])
 
    // Parse command line
    opterr = 1;
-   while((ch = getopt(argc, argv, "c:hp:t:v:")) != -1)
+       while((ch = getopt(argc, argv, "A:c:E:hp:t:u:v:w:")) != -1)
    {
       switch(ch)
       {
          case 'h':   // Display help and exit
             printf("Usage: nxsnmpset [<options>] <host> <variable> <value>\n"
                    "Valid options are:\n"
-                   "   -c <string>  : Specify community string. Default is \"public\".\n"
-                   "   -h           : Display help and exit.\n"
-                   "   -p <port>    : Specify agent's port number. Default is 161.\n"
+                   "   -A <passwd>  : User's authentication password for SNMP v3 USM\n"
+                   "   -c <string>  : Community string. Default is \"public\"\n"
+                   "   -E <passwd>  : User's encryption password for SNMP v3 USM\n"
+                   "   -h           : Display help and exit\n"
+                   "   -p <port>    : Agent's port number. Default is 161\n"
                    "   -t <type>    : Specify variable's data type. Default is octet string.\n"
-                   "   -v <version> : Specify SNMP version (valid values is 1 and 2c).\n"
-                   "   -w <seconds> : Specify request timeout (default is 3 seconds)\n\n"
+                   "   -u <user>    : User name for SNMP v3 USM\n"
+                   "   -v <version> : SNMP version to use (valid values is 1, 2c, and 3)\n"
+                   "   -w <seconds> : Request timeout (default is 3 seconds)\n"
                    "Note: You can specify data type either as number or in symbolic form.\n"
                    "      Valid symbolic representations are following:\n"
                    "         INTEGER, STRING, OID, IPADDR, COUNTER32, GAUGE32,\n"
@@ -142,21 +151,6 @@ int main(int argc, char *argv[])
             iExit = 0;
             bStart = FALSE;
             break;
-         case 'c':   // Community
-            nx_strncpy(m_szCommunity, optarg, 256);
-            break;
-         case 'p':   // Port number
-            dwValue = strtoul(optarg, &eptr, 0);
-            if ((*eptr != 0) || (dwValue > 65535) || (dwValue == 0))
-            {
-               printf("Invalid port number %s\n", optarg);
-               bStart = FALSE;
-            }
-            else
-            {
-               m_wPort = (WORD)dwValue;
-            }
-            break;
          case 't':
             // First, check for numeric representation
             dwValue = strtoul(optarg, &eptr, 0);
@@ -171,22 +165,50 @@ int main(int argc, char *argv[])
                }
                else
                {
-                  m_dwType = dwValue;
+                  m_type = dwValue;
                }
             }
             else
             {
-               m_dwType = dwValue;
+               m_type = dwValue;
+            }
+            break;
+         case 'c':   // Community
+            nx_strncpy(m_community, optarg, 256);
+            break;
+         case 'u':   // User
+            nx_strncpy(m_user, optarg, 256);
+            break;
+         case 'A':   // authentication password
+            nx_strncpy(m_authPassword, optarg, 256);
+            break;
+         case 'E':   // encription password
+            nx_strncpy(m_encryptionPassword, optarg, 256);
+            break;
+         case 'p':   // Port number
+            dwValue = strtoul(optarg, &eptr, 0);
+            if ((*eptr != 0) || (dwValue > 65535) || (dwValue == 0))
+            {
+               printf("Invalid port number %s\n", optarg);
+               bStart = FALSE;
+            }
+            else
+            {
+               m_port = (WORD)dwValue;
             }
             break;
          case 'v':   // Version
             if (!strcmp(optarg, "1"))
             {
-               m_dwVersion = SNMP_VERSION_1;
+               m_snmpVersion = SNMP_VERSION_1;
             }
             else if (!stricmp(optarg, "2c"))
             {
-               m_dwVersion = SNMP_VERSION_2C;
+               m_snmpVersion = SNMP_VERSION_2C;
+            }
+            else if (!stricmp(optarg, "3"))
+            {
+               m_snmpVersion = SNMP_VERSION_3;
             }
             else
             {
@@ -203,7 +225,7 @@ int main(int argc, char *argv[])
             }
             else
             {
-               m_dwTimeout = dwValue;
+               m_timeout = dwValue;
             }
             break;
          case '?':
index 42759e9..b660689 100644 (file)
@@ -1,6 +1,6 @@
 /* 
-** nxsnmpget - command line tool used to retrieve parameters from SNMP agent
-** Copyright (C) 2004 Victor Kirhenshtein
+** nxsnmpwalk - command line tool used to retrieve parameters from SNMP agent
+** Copyright (C) 2004-2009 Victor Kirhenshtein
 **
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU General Public License as published by
@@ -16,7 +16,7 @@
 ** along with this program; if not, write to the Free Software
 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 **
-** $module: nxsnmpwalk.cpp
+** File: nxsnmpwalk.cpp
 **
 **/
 
 // Static data
 //
 
-static char m_szCommunity[256] = "public";
-static WORD m_wPort = 161;
-static DWORD m_dwVersion = SNMP_VERSION_2C;
-static DWORD m_dwTimeout = 3000;
+static char m_community[256] = "public";
+static char m_user[256] = "";
+static char m_authPassword[256] = "";
+static char m_encryptionPassword[256] = "";
+static WORD m_port = 161;
+static DWORD m_snmpVersion = SNMP_VERSION_2C;
+static DWORD m_timeout = 3000;
 
 
 //
@@ -58,7 +61,7 @@ int GetData(char *pszHost, char *pszRootOid)
 
    // Create SNMP transport
    pTransport = new SNMP_UDPTransport;
-   dwResult = pTransport->CreateUDPTransport(pszHost, 0, m_wPort);
+   dwResult = pTransport->createUDPTransport(pszHost, 0, m_port);
    if (dwResult != SNMP_ERR_SUCCESS)
    {
       printf("Unable to create UDP transport: %s\n", SNMPGetErrorText(dwResult));
@@ -80,17 +83,20 @@ int GetData(char *pszHost, char *pszRootOid)
          // Walk the MIB
          while(bRunning)
          {
-            pRqPDU = new SNMP_PDU(SNMP_GET_NEXT_REQUEST, m_szCommunity, getpid(), m_dwVersion);
-            pRqPDU->BindVariable(new SNMP_Variable(pdwName, dwNameLen));
-            dwResult = pTransport->DoRequest(pRqPDU, &pRespPDU, m_dwTimeout, 3);
+                               if (m_snmpVersion == SNMP_VERSION_3)
+                                       pRqPDU = new SNMP_PDU(SNMP_GET_NEXT_REQUEST, new SNMP_SecurityContext(m_user, m_authPassword, m_encryptionPassword), getpid(), SNMP_VERSION_3);
+                               else
+                                       pRqPDU = new SNMP_PDU(SNMP_GET_NEXT_REQUEST, m_community, getpid(), m_snmpVersion);
+            pRqPDU->bindVariable(new SNMP_Variable(pdwName, dwNameLen));
+            dwResult = pTransport->doRequest(pRqPDU, &pRespPDU, m_timeout, 3);
 
             // Analyze response
             if (dwResult == SNMP_ERR_SUCCESS)
             {
-               if ((pRespPDU->GetNumVariables() > 0) &&
-                   (pRespPDU->GetErrorCode() == 0))
+               if ((pRespPDU->getNumVariables() > 0) &&
+                   (pRespPDU->getErrorCode() == 0))
                {
-                  SNMP_Variable *pVar = pRespPDU->GetVariable(0);
+                  SNMP_Variable *pVar = pRespPDU->getVariable(0);
 
                   if ((pVar->GetType() != ASN_NO_SUCH_OBJECT) &&
                       (pVar->GetType() != ASN_NO_SUCH_INSTANCE))
@@ -164,24 +170,36 @@ int main(int argc, char *argv[])
 
    // Parse command line
    opterr = 1;
-   while((ch = getopt(argc, argv, "c:hp:v:")) != -1)
+   while((ch = getopt(argc, argv, "A:c:E:hp:u:v:w:")) != -1)
    {
       switch(ch)
       {
          case 'h':   // Display help and exit
             printf("Usage: nxsnmpwalk [<options>] <host> <start_oid>\n"
                    "Valid options are:\n"
-                   "   -c <string>  : Specify community string. Default is \"public\".\n"
-                   "   -h           : Display help and exit.\n"
-                   "   -p <port>    : Specify agent's port number. Default is 161.\n"
-                   "   -v <version> : Specify SNMP version (valid values is 1 and 2c).\n"
-                   "   -w <seconds> : Specify request timeout (default is 3 seconds)\n"
+                   "   -A <passwd>  : User's authentication password for SNMP v3 USM\n"
+                   "   -c <string>  : Community string. Default is \"public\"\n"
+                   "   -E <passwd>  : User's encryption password for SNMP v3 USM\n"
+                   "   -h           : Display help and exit\n"
+                   "   -p <port>    : Agent's port number. Default is 161\n"
+                   "   -u <user>    : User name for SNMP v3 USM\n"
+                   "   -v <version> : SNMP version to use (valid values is 1, 2c, and 3)\n"
+                   "   -w <seconds> : Request timeout (default is 3 seconds)\n"
                    "\n");
             iExit = 0;
             bStart = FALSE;
             break;
          case 'c':   // Community
-            nx_strncpy(m_szCommunity, optarg, 256);
+            nx_strncpy(m_community, optarg, 256);
+            break;
+         case 'u':   // User
+            nx_strncpy(m_user, optarg, 256);
+            break;
+         case 'A':   // authentication password
+            nx_strncpy(m_authPassword, optarg, 256);
+            break;
+         case 'E':   // encription password
+            nx_strncpy(m_encryptionPassword, optarg, 256);
             break;
          case 'p':   // Port number
             dwValue = strtoul(optarg, &eptr, 0);
@@ -192,17 +210,21 @@ int main(int argc, char *argv[])
             }
             else
             {
-               m_wPort = (WORD)dwValue;
+               m_port = (WORD)dwValue;
             }
             break;
          case 'v':   // Version
             if (!strcmp(optarg, "1"))
             {
-               m_dwVersion = SNMP_VERSION_1;
+               m_snmpVersion = SNMP_VERSION_1;
             }
             else if (!stricmp(optarg, "2c"))
             {
-               m_dwVersion = SNMP_VERSION_2C;
+               m_snmpVersion = SNMP_VERSION_2C;
+            }
+            else if (!stricmp(optarg, "3"))
+            {
+               m_snmpVersion = SNMP_VERSION_3;
             }
             else
             {
@@ -219,7 +241,7 @@ int main(int argc, char *argv[])
             }
             else
             {
-               m_dwTimeout = dwValue;
+               m_timeout = dwValue;
             }
             break;
          case '?':