43c5e3bbcb20f78215258e57bff09fbb7a8edf3b
[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 if (m_response->getFieldAsUInt32(VID_RCC) == ERR_SUCCESS)
99 {
100 dwSize = m_response->getFieldAsUInt32(VID_PDU_SIZE);
101 pBuffer = (BYTE *)malloc(dwSize);
102 m_response->getFieldAsBinary(VID_PDU, pBuffer, dwSize);
103
104 if (contextFinder != NULL)
105 setSecurityContext(contextFinder(pSender, *piAddrSize));
106
107 *ppData = new SNMP_PDU;
108 if (!(*ppData)->parse(pBuffer, dwSize, m_securityContext, m_enableEngineIdAutoupdate))
109 {
110 delete *ppData;
111 *ppData = NULL;
112 }
113 free(pBuffer);
114 nRet = (int)dwSize;
115 }
116 else
117 {
118 nRet = -1;
119 }
120
121 delete_and_null(m_response);
122 return nRet;
123 }
124
125 /**
126 * Get peer IP address
127 */
128 InetAddress SNMP_ProxyTransport::getPeerIpAddress()
129 {
130 return m_ipAddr;
131 }
132
133 /**
134 * Get port number
135 */
136 UINT16 SNMP_ProxyTransport::getPort()
137 {
138 return m_port;
139 }
140
141 /**
142 * Check if this transport is a proxy transport
143 */
144 bool SNMP_ProxyTransport::isProxyTransport()
145 {
146 return true;
147 }