retry SNMP status poll after proxy communication error
[public/netxms.git] / src / server / libnxsrv / snmpproxy.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** Server Library
4 ** Copyright (C) 2003-2015 Victor Kirhenshtein
5 **
6 ** This program is free software; you can redistribute it and/or modify
7 ** it under the terms of the GNU Lesser General Public License as published by
8 ** the Free Software Foundation; either version 3 of the License, or
9 ** (at your option) any later version.
10 **
11 ** This program is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ** GNU General Public License for more details.
15 **
16 ** You should have received a copy of the GNU Lesser General Public License
17 ** along with this program; if not, write to the Free Software
18 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 **
20 ** File: snmpproxy.cpp
21 **
22 **/
23
24 #include "libnxsrv.h"
25
26 /**
27 * Constructor
28 */
29 SNMP_ProxyTransport::SNMP_ProxyTransport(AgentConnection *conn, const InetAddress& ipAddr, UINT16 port)
30 {
31 m_reliable = true; // no need for retries on server side, agent will do retry if needed
32 m_agentConnection = conn;
33 m_ipAddr = ipAddr;
34 m_port = port;
35 m_response = NULL;
36 m_waitForResponse = true;
37 }
38
39 /**
40 * Destructor
41 */
42 SNMP_ProxyTransport::~SNMP_ProxyTransport()
43 {
44 m_agentConnection->decRefCount();
45 delete m_response;
46 }
47
48 /**
49 * Send PDU
50 */
51 int SNMP_ProxyTransport::sendMessage(SNMP_PDU *pdu)
52 {
53 int nRet = -1;
54 NXCPMessage msg(m_agentConnection->getProtocolVersion());
55
56 BYTE *pBuffer;
57 size_t size = pdu->encode(&pBuffer, m_securityContext);
58 if (size != 0)
59 {
60 msg.setCode(CMD_SNMP_REQUEST);
61 msg.setField(VID_IP_ADDRESS, m_ipAddr);
62 msg.setField(VID_PORT, m_port);
63 msg.setField(VID_PDU_SIZE, (UINT32)size);
64 msg.setField(VID_PDU, pBuffer, size);
65 free(pBuffer);
66
67 if (m_waitForResponse)
68 {
69 m_response = m_agentConnection->customRequest(&msg);
70 if (m_response != NULL)
71 {
72 nRet = 1;
73 }
74 }
75 else
76 {
77 m_agentConnection->sendMessage(&msg);
78 }
79 }
80
81 return nRet;
82 }
83
84 /**
85 * Receive PDU
86 */
87 int SNMP_ProxyTransport::readMessage(SNMP_PDU **ppData, UINT32 dwTimeout,
88 struct sockaddr *pSender, socklen_t *piAddrSize,
89 SNMP_SecurityContext* (*contextFinder)(struct sockaddr *, socklen_t))
90 {
91 int nRet;
92 BYTE *pBuffer;
93 UINT32 dwSize;
94
95 if (m_response == NULL)
96 return -1;
97
98 UINT32 rcc = m_response->getFieldAsUInt32(VID_RCC);
99 if (rcc == ERR_SUCCESS)
100 {
101 dwSize = m_response->getFieldAsUInt32(VID_PDU_SIZE);
102 pBuffer = (BYTE *)malloc(dwSize);
103 m_response->getFieldAsBinary(VID_PDU, pBuffer, dwSize);
104
105 if (contextFinder != NULL)
106 setSecurityContext(contextFinder(pSender, *piAddrSize));
107
108 *ppData = new SNMP_PDU;
109 if (!(*ppData)->parse(pBuffer, dwSize, m_securityContext, m_enableEngineIdAutoupdate))
110 {
111 delete *ppData;
112 *ppData = NULL;
113 }
114 free(pBuffer);
115 nRet = (int)dwSize;
116 }
117 else if (rcc == ERR_REQUEST_TIMEOUT)
118 {
119 nRet = 0;
120 }
121 else
122 {
123 nRet = -1;
124 }
125
126 delete_and_null(m_response);
127 return nRet;
128 }
129
130 /**
131 * Get peer IP address
132 */
133 InetAddress SNMP_ProxyTransport::getPeerIpAddress()
134 {
135 return m_ipAddr;
136 }
137
138 /**
139 * Get port number
140 */
141 UINT16 SNMP_ProxyTransport::getPort()
142 {
143 return m_port;
144 }
145
146 /**
147 * Check if this transport is a proxy transport
148 */
149 bool SNMP_ProxyTransport::isProxyTransport()
150 {
151 return true;
152 }