2 ** NetXMS multiplatform core agent
3 ** Copyright (C) 2003-2015 Victor Kirhenshtein
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 ** File: snmpproxy.cpp
28 #define SNMP_BUFFER_SIZE 65536
33 static UINT64 s_serverRequests
= 0;
34 static UINT64 s_snmpRequests
= 0;
35 static UINT64 s_snmpResponses
= 0;
38 * Handler for SNMP proxy information parameters
40 LONG
H_SNMPProxyStats(const TCHAR
*cmd
, const TCHAR
*arg
, TCHAR
*value
, AbstractCommSession
*session
)
44 case 'R': // SNMP requests
45 ret_uint64(value
, s_snmpRequests
);
47 case 'r': // SNMP responses
48 ret_uint64(value
, s_snmpResponses
);
50 case 'S': // server requests
51 ret_uint64(value
, s_serverRequests
);
54 return SYSINFO_RC_UNSUPPORTED
;
56 return SYSINFO_RC_SUCCESS
;
60 * Read PDU from network
62 static BOOL
ReadPDU(SOCKET hSocket
, BYTE
*pdu
, UINT32
*pdwSize
)
69 UINT32 dwTimeout
= g_dwSNMPTimeout
;
76 FD_SET(hSocket
, &rdfs
);
78 tv
.tv_sec
= g_dwSNMPTimeout
/ 1000;
79 tv
.tv_usec
= (g_dwSNMPTimeout
% 1000) * 1000;
81 tv
.tv_sec
= dwTimeout
/ 1000;
82 tv
.tv_usec
= (dwTimeout
% 1000) * 1000;
85 if (select(SELECT_NFDS(hSocket
+ 1), &rdfs
, NULL
, NULL
, &tv
) <= 0)
88 qwTime
= GetCurrentTimeMs();
89 if ((iErr
= select(SELECT_NFDS(hSocket
+ 1), &rdfs
, NULL
, NULL
, &tv
)) <= 0)
91 if (((iErr
== -1) && (errno
!= EINTR
)) ||
97 qwTime
= GetCurrentTimeMs() - qwTime
; // Elapsed time
98 dwTimeout
-= min(((UINT32
)qwTime
), dwTimeout
);
102 nBytes
= recv(hSocket
, (char *)pdu
, SNMP_BUFFER_SIZE
, 0);
112 * Send SNMP request to target, receive response, and send it to server
114 void CommSession::proxySnmpRequest(NXCPMessage
*request
)
116 NXCPMessage response
;
117 response
.setCode(CMD_REQUEST_COMPLETED
);
118 response
.setId(request
->getId());
121 UINT32 dwSizeIn
= request
->getFieldAsUInt32(VID_PDU_SIZE
);
124 BYTE
*pduIn
= (BYTE
*)malloc(dwSizeIn
);
127 request
->getFieldAsBinary(VID_PDU
, pduIn
, dwSizeIn
);
129 SOCKET hSocket
= socket(AF_INET
, SOCK_DGRAM
, 0);
130 if (hSocket
!= INVALID_SOCKET
)
132 InetAddress addr
= request
->getFieldAsInetAddress(VID_IP_ADDRESS
);
134 addr
.fillSockAddr(&sa
, request
->getFieldAsUInt16(VID_PORT
));
135 if (connect(hSocket
, (struct sockaddr
*)&sa
, SA_LEN((struct sockaddr
*)&sa
)) != -1)
137 BYTE
*pduOut
= (BYTE
*)malloc(SNMP_BUFFER_SIZE
);
141 for(nRetries
= 0; nRetries
< 3; nRetries
++)
143 if (send(hSocket
, (char *)pduIn
, dwSizeIn
, 0) == (int)dwSizeIn
)
147 if (ReadPDU(hSocket
, pduOut
, &dwSizeOut
))
150 response
.setField(VID_PDU_SIZE
, dwSizeOut
);
151 response
.setField(VID_PDU
, pduOut
, dwSizeOut
);
157 response
.setField(VID_RCC
, (nRetries
== 3) ? ERR_REQUEST_TIMEOUT
: ERR_SUCCESS
);
161 response
.setField(VID_RCC
, ERR_OUT_OF_RESOURCES
);
166 response
.setField(VID_RCC
, ERR_SOCKET_ERROR
);
168 closesocket(hSocket
);
172 response
.setField(VID_RCC
, ERR_SOCKET_ERROR
);
178 response
.setField(VID_RCC
, ERR_OUT_OF_RESOURCES
);
183 response
.setField(VID_RCC
, ERR_MALFORMED_COMMAND
);
185 sendMessage(&response
);