Implemented functionality for zone specific SNMP credentials. Fixes #NX-1199
[public/netxms.git] / src / server / core / zone.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** Copyright (C) 2003-2017 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: zone.cpp
20 **
21 **/
22
23 #include "nxcore.h"
24
25 /**
26 * Dump index to console
27 */
28 void DumpIndex(CONSOLE_CTX pCtx, InetAddressIndex *index);
29
30 /**
31 * Zone class default constructor
32 */
33 Zone::Zone() : NetObj()
34 {
35 m_id = 0;
36 m_uin = 0;
37 _tcscpy(m_name, _T("Default"));
38 m_proxyNodeId = 0;
39 m_idxNodeByAddr = new InetAddressIndex;
40 m_idxInterfaceByAddr = new InetAddressIndex;
41 m_idxSubnetByAddr = new InetAddressIndex;
42 }
43
44 /**
45 * Constructor for new zone object
46 */
47 Zone::Zone(UINT32 uin, const TCHAR *name) : NetObj()
48 {
49 m_id = 0;
50 m_uin = uin;
51 nx_strncpy(m_name, name, MAX_OBJECT_NAME);
52 m_proxyNodeId = 0;
53 m_idxNodeByAddr = new InetAddressIndex;
54 m_idxInterfaceByAddr = new InetAddressIndex;
55 m_idxSubnetByAddr = new InetAddressIndex;
56 }
57
58 /**
59 * Zone class destructor
60 */
61 Zone::~Zone()
62 {
63 delete m_idxNodeByAddr;
64 delete m_idxInterfaceByAddr;
65 delete m_idxSubnetByAddr;
66 }
67
68 /**
69 * Create object from database data
70 */
71 bool Zone::loadFromDatabase(DB_HANDLE hdb, UINT32 dwId)
72 {
73 m_id = dwId;
74
75 if (!loadCommonProperties(hdb))
76 return false;
77
78 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT zone_guid,proxy_node,snmp_ports FROM zones WHERE id=?"));
79 if (hStmt != NULL)
80 {
81 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, dwId);
82 DB_RESULT hResult = DBSelectPrepared(hStmt);
83 if (hResult != NULL)
84 {
85 if (DBGetNumRows(hResult) == 0)
86 {
87 DBFreeResult(hResult);
88 if (dwId == BUILTIN_OID_ZONE0)
89 {
90 m_uin = 0;
91 return true;
92 }
93 else
94 {
95 DbgPrintf(4, _T("Cannot load zone object %ld - missing record in \"zones\" table"), (long)m_id);
96 return false;
97 }
98 }
99
100 m_uin = DBGetFieldULong(hResult, 0, 0);
101 m_proxyNodeId = DBGetFieldULong(hResult, 0, 1);
102 TCHAR buffer[MAX_DB_STRING];
103 DBGetField(hResult, 0, 2, buffer, MAX_DB_STRING);
104 if (buffer[0] != 0)
105 m_snmpPorts.splitAndAdd(buffer, _T(","));
106
107 DBFreeResult(hResult);
108
109 // Load access list
110 loadACLFromDB(hdb);
111
112 return true;
113 }
114 DBFreeStatement(hStmt);
115 }
116
117 return false;
118 }
119
120 /**
121 * Save object to database
122 */
123 bool Zone::saveToDatabase(DB_HANDLE hdb)
124 {
125 lockProperties();
126
127 bool success = saveCommonProperties(hdb);
128 if (success && (m_modified & MODIFY_OTHER))
129 {
130 DB_STATEMENT hStmt;
131 if (IsDatabaseRecordExist(hdb, _T("zones"), _T("id"), m_id))
132 {
133 hStmt = DBPrepare(hdb, _T("UPDATE zones SET zone_guid=?,proxy_node=?,snmp_ports=? WHERE id=?"));
134 }
135 else
136 {
137 hStmt = DBPrepare(hdb, _T("INSERT INTO zones (zone_guid,proxy_node,snmp_ports,id) VALUES (?,?,?,?)"));
138 }
139 if (hStmt != NULL)
140 {
141 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_uin);
142 DBBind(hStmt, 2, DB_SQLTYPE_INTEGER, m_proxyNodeId);
143 DBBind(hStmt, 3, DB_SQLTYPE_VARCHAR, m_snmpPorts.join(_T(",")), DB_BIND_DYNAMIC);
144 DBBind(hStmt, 4, DB_SQLTYPE_INTEGER, m_id);
145 success = DBExecute(hStmt);
146 DBFreeStatement(hStmt);
147 }
148 else
149 {
150 success = false;
151 }
152 }
153
154 if (success)
155 success = saveACLToDB(hdb);
156
157 // Unlock object and clear modification flag
158 m_modified = 0;
159 unlockProperties();
160 return success;
161 }
162
163 /**
164 * Delete zone object from database
165 */
166 bool Zone::deleteFromDatabase(DB_HANDLE hdb)
167 {
168 bool success = NetObj::deleteFromDatabase(hdb);
169 if (success)
170 success = executeQueryOnObject(hdb, _T("DELETE FROM zones WHERE id=?"));
171 return success;
172 }
173
174 /**
175 * Create NXCP message with object's data
176 */
177 void Zone::fillMessageInternal(NXCPMessage *msg)
178 {
179 NetObj::fillMessageInternal(msg);
180 msg->setField(VID_ZONE_UIN, m_uin);
181 msg->setField(VID_ZONE_PROXY, m_proxyNodeId);
182 m_snmpPorts.fillMessage(msg, VID_ZONE_SNMP_PORT_LIST_BASE, VID_ZONE_SNMP_PORT_COUNT);
183 }
184
185 /**
186 * Modify object from message
187 */
188 UINT32 Zone::modifyFromMessageInternal(NXCPMessage *request)
189 {
190 if (request->isFieldExist(VID_ZONE_PROXY))
191 m_proxyNodeId = request->getFieldAsUInt32(VID_ZONE_PROXY);
192 if (request->isFieldExist(VID_ZONE_SNMP_PORT_LIST_BASE) && request->isFieldExist(VID_ZONE_SNMP_PORT_COUNT))
193 {
194 m_snmpPorts.clear();
195 for(int i = 0; i < request->getFieldAsUInt32(VID_ZONE_SNMP_PORT_COUNT); i++)
196 {
197 m_snmpPorts.addPreallocated(request->getFieldAsString(VID_ZONE_SNMP_PORT_LIST_BASE + i));
198 }
199 }
200
201 return NetObj::modifyFromMessageInternal(request);
202 }
203
204 /**
205 * Update interface index
206 */
207 void Zone::updateInterfaceIndex(const InetAddress& oldIp, const InetAddress& newIp, Interface *iface)
208 {
209 m_idxInterfaceByAddr->remove(oldIp);
210 m_idxInterfaceByAddr->put(newIp, iface);
211 }
212
213 /**
214 * Called by client session handler to check if threshold summary should be shown for this object.
215 */
216 bool Zone::showThresholdSummary()
217 {
218 return true;
219 }
220
221 /**
222 * Remove interface from index
223 */
224 void Zone::removeFromIndex(Interface *iface)
225 {
226 const ObjectArray<InetAddress> *list = iface->getIpAddressList()->getList();
227 for(int i = 0; i < list->size(); i++)
228 {
229 InetAddress *addr = list->get(i);
230 if (addr->isValidUnicast())
231 {
232 NetObj *o = m_idxInterfaceByAddr->get(*addr);
233 if ((o != NULL) && (o->getId() == iface->getId()))
234 {
235 m_idxInterfaceByAddr->remove(*addr);
236 }
237 }
238 }
239 }
240
241 /**
242 * Create NXSL object for this object
243 */
244 NXSL_Value *Zone::createNXSLObject()
245 {
246 return new NXSL_Value(new NXSL_Object(&g_nxslZoneClass, this));
247 }
248
249 /**
250 * Dump interface index to console
251 */
252 void Zone::dumpInterfaceIndex(CONSOLE_CTX console)
253 {
254 DumpIndex(console, m_idxInterfaceByAddr);
255 }
256
257 /**
258 * Dump node index to console
259 */
260 void Zone::dumpNodeIndex(CONSOLE_CTX console)
261 {
262 DumpIndex(console, m_idxNodeByAddr);
263 }
264
265 /**
266 * Dump subnet index to console
267 */
268 void Zone::dumpSubnetIndex(CONSOLE_CTX console)
269 {
270 DumpIndex(console, m_idxSubnetByAddr);
271 }
272
273 /**
274 * Serialize object to JSON
275 */
276 json_t *Zone::toJson()
277 {
278 json_t *root = NetObj::toJson();
279 json_object_set_new(root, "uin", json_integer(m_uin));
280 json_object_set_new(root, "proxyNodeId", json_integer(m_proxyNodeId));
281 return root;
282 }