3db0ecfda3027087d452afe9e8751db8935c610d
[public/netxms.git] / src / agent / core / dcsnmp.cpp
1 /*
2 ** NetXMS multiplatform core agent
3 ** Copyright (C) 2003-2015 Victor Kirhenshtein
4 **
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.
9 **
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.
14 **
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.
18 **
19 ** File: dcsnmp.cpp
20 **
21 **/
22
23 #include "nxagentd.h"
24
25 /**
26 * SNMP targets
27 */
28 static HashMap<uuid_t, SNMPTarget> s_snmpTargets(true);
29 static MUTEX s_snmpTargetsLock = MutexCreate();
30
31 /**
32 * Create SNMP target from NXCP message
33 */
34 SNMPTarget::SNMPTarget(UINT64 serverId, NXCPMessage *msg, UINT32 baseId)
35 {
36 msg->getFieldAsBinary(baseId, m_guid, UUID_LENGTH);
37 m_serverId = serverId;
38 m_ipAddress = msg->getFieldAsInetAddress(baseId + 1);
39 m_snmpVersion = (BYTE)msg->getFieldAsInt16(baseId + 2);
40 m_port = msg->getFieldAsUInt16(baseId + 3);
41 m_authType = (BYTE)msg->getFieldAsInt16(baseId + 4);
42 m_encType = (BYTE)msg->getFieldAsInt16(baseId + 5);
43 m_authName = msg->getFieldAsUtf8String(baseId + 6);
44 m_authPassword = msg->getFieldAsUtf8String(baseId + 7);
45 m_encPassword = msg->getFieldAsUtf8String(baseId + 8);
46 m_transport = NULL;
47 }
48
49 /**
50 * Create SNMP target from database record
51 * Expected field order:
52 * guid,server_id,ip_address,snmp_version,port,auth_type,enc_type,auth_name,auth_pass,enc_pass
53 */
54 SNMPTarget::SNMPTarget(DB_RESULT hResult, int row)
55 {
56 DBGetFieldGUID(hResult, row, 0, m_guid);
57 m_serverId = DBGetFieldUInt64(hResult, row, 1);
58 m_ipAddress = DBGetFieldInetAddr(hResult, row, 2);
59 m_snmpVersion = (BYTE)DBGetFieldLong(hResult, row, 3);
60 m_port = (UINT16)DBGetFieldLong(hResult, row, 4);
61 m_authType = (BYTE)DBGetFieldLong(hResult, row, 5);
62 m_encType = (BYTE)DBGetFieldLong(hResult, row, 6);
63 m_authName = DBGetFieldUTF8(hResult, row, 7, NULL, 0);
64 m_authPassword = DBGetFieldUTF8(hResult, row, 8, NULL, 0);
65 m_encPassword = DBGetFieldUTF8(hResult, row, 9, NULL, 0);
66 m_transport = NULL;
67 }
68
69 /**
70 * SNMP target destructor
71 */
72 SNMPTarget::~SNMPTarget()
73 {
74 safe_free(m_authName);
75 safe_free(m_authPassword);
76 safe_free(m_encPassword);
77 delete m_transport;
78 }
79
80 /**
81 * Save SNMP target object to database
82 */
83 bool SNMPTarget::saveToDatabase()
84 {
85 DB_HANDLE hdb = GetLocalDatabaseHandle();
86
87 DB_STATEMENT hStmt;
88 if (IsDatabaseRecordExist(hdb, _T("dc_snmp_targets"), _T("guid"), m_guid))
89 hStmt = DBPrepare(hdb, _T("UPDATE dc_snmp_targets SET server_id=?,ip_address=?,snmp_version=?,port=?,auth_type=?,enc_type=?,auth_name=?,auth_pass=?,enc_pass=? WHERE guid=?"));
90 else
91 hStmt = DBPrepare(hdb, _T("INSERT INTO dc_snmp_targets (server_id,ip_address,snmp_version,port,auth_type,enc_type,auth_name,auth_pass,enc_pass,guid) VALUES (?,?,?,?,?,?,?,?,?,?)"));
92 if (hStmt == NULL)
93 return false;
94
95 DBBind(hStmt, 1, DB_SQLTYPE_BIGINT, m_serverId);
96 DBBind(hStmt, 2, DB_SQLTYPE_VARCHAR, (const TCHAR *)m_ipAddress.toString(), DB_BIND_TRANSIENT);
97 DBBind(hStmt, 3, DB_SQLTYPE_INTEGER, (INT32)m_snmpVersion);
98 DBBind(hStmt, 4, DB_SQLTYPE_INTEGER, (INT32)m_port);
99 DBBind(hStmt, 5, DB_SQLTYPE_INTEGER, (INT32)m_authType);
100 DBBind(hStmt, 6, DB_SQLTYPE_INTEGER, (INT32)m_encType);
101 #ifdef UNICODE
102 DBBind(hStmt, 7, DB_SQLTYPE_VARCHAR, WideStringFromUTF8String(m_authName), DB_BIND_DYNAMIC);
103 DBBind(hStmt, 8, DB_SQLTYPE_VARCHAR, WideStringFromUTF8String(m_authPassword), DB_BIND_DYNAMIC);
104 DBBind(hStmt, 9, DB_SQLTYPE_VARCHAR, WideStringFromUTF8String(m_encPassword), DB_BIND_DYNAMIC);
105 #else
106 DBBind(hStmt, 7, DB_SQLTYPE_VARCHAR, m_authName, DB_BIND_STATIC);
107 DBBind(hStmt, 8, DB_SQLTYPE_VARCHAR, m_authPassword, DB_BIND_STATIC);
108 DBBind(hStmt, 9, DB_SQLTYPE_VARCHAR, m_encPassword, DB_BIND_STATIC);
109 #endif
110 TCHAR guidText[64];
111 DBBind(hStmt, 10, DB_SQLTYPE_VARCHAR, uuid_to_string(m_guid, guidText), DB_BIND_STATIC);
112
113 bool success = DBExecute(hStmt);
114 DBFreeStatement(hStmt);
115 return success;
116 }
117
118 /**
119 * Get SNMP transport (create if needed)
120 */
121 SNMP_Transport *SNMPTarget::getTransport(UINT16 port)
122 {
123 if (m_transport != NULL)
124 return m_transport;
125
126 m_transport = new SNMP_UDPTransport;
127 ((SNMP_UDPTransport *)m_transport)->createUDPTransport(m_ipAddress, (port != 0) ? port : m_port);
128 m_transport->setSnmpVersion(m_snmpVersion);
129 SNMP_SecurityContext *ctx = new SNMP_SecurityContext(m_authName, m_authPassword, m_encPassword, m_authType, m_encType);
130 ctx->setSecurityModel((m_snmpVersion == SNMP_VERSION_3) ? SNMP_SECURITY_MODEL_USM : SNMP_SECURITY_MODEL_V2C);
131 m_transport->setSecurityContext(ctx);
132 return m_transport;
133 }
134
135 /**
136 * Update SNMP target information
137 */
138 void UpdateSnmpTarget(SNMPTarget *target)
139 {
140 MutexLock(s_snmpTargetsLock);
141 s_snmpTargets.set(target->getGuid(), target);
142 target->saveToDatabase();
143 MutexUnlock(s_snmpTargetsLock);
144 }
145
146 /**
147 * Get value from SNMP node
148 */
149 bool GetSnmpValue(const uuid_t& target, UINT16 port, const TCHAR *oid, TCHAR *value, int interpretRawValue)
150 {
151 bool success = false;
152
153 MutexLock(s_snmpTargetsLock);
154 SNMPTarget *t = s_snmpTargets.get(target);
155 if (t != NULL)
156 {
157 SNMP_Transport *snmp = t->getTransport(port);
158 UINT32 rcc;
159
160 if (interpretRawValue == SNMP_RAWTYPE_NONE)
161 {
162 rcc = SnmpGetEx(snmp, oid, NULL, 0, value, MAX_RESULT_LENGTH * sizeof(TCHAR), SG_PSTRING_RESULT, NULL);
163 }
164 else
165 {
166 BYTE rawValue[1024];
167 memset(rawValue, 0, 1024);
168 rcc = SnmpGetEx(snmp, oid, NULL, 0, rawValue, 1024, SG_RAW_RESULT, NULL);
169 if (rcc == SNMP_ERR_SUCCESS)
170 {
171 switch(interpretRawValue)
172 {
173 case SNMP_RAWTYPE_INT32:
174 _sntprintf(value, MAX_RESULT_LENGTH, _T("%d"), ntohl(*((LONG *)rawValue)));
175 break;
176 case SNMP_RAWTYPE_UINT32:
177 _sntprintf(value, MAX_RESULT_LENGTH, _T("%u"), ntohl(*((UINT32 *)rawValue)));
178 break;
179 case SNMP_RAWTYPE_INT64:
180 _sntprintf(value, MAX_RESULT_LENGTH, INT64_FMT, (INT64)ntohq(*((INT64 *)rawValue)));
181 break;
182 case SNMP_RAWTYPE_UINT64:
183 _sntprintf(value, MAX_RESULT_LENGTH, UINT64_FMT, ntohq(*((QWORD *)rawValue)));
184 break;
185 case SNMP_RAWTYPE_DOUBLE:
186 _sntprintf(value, MAX_RESULT_LENGTH, _T("%f"), ntohd(*((double *)rawValue)));
187 break;
188 case SNMP_RAWTYPE_IP_ADDR:
189 IpToStr(ntohl(*((UINT32 *)rawValue)), value);
190 break;
191 case SNMP_RAWTYPE_MAC_ADDR:
192 MACToStr(rawValue, value);
193 break;
194 default:
195 value[0] = 0;
196 break;
197 }
198 }
199 }
200 success = (rcc == SNMP_ERR_SUCCESS);
201 }
202 else
203 {
204 TCHAR buffer[64];
205 DebugPrintf(INVALID_INDEX, 6, _T("SNMP target with guid %s not found"), uuid_to_string(target, buffer));
206 }
207 MutexUnlock(s_snmpTargetsLock);
208
209 return success;
210 }