object save optimization - object properties divided into groups and anly modified...
[public/netxms.git] / src / server / core / vpnconn.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: vpnconn.cpp
20 **
21 **/
22
23 #include "nxcore.h"
24
25 /**
26 * Default constructor for VPNConnector object
27 */
28 VPNConnector::VPNConnector() : NetObj()
29 {
30 m_dwPeerGateway = 0;
31 m_localNetworks = new ObjectArray<InetAddress>(8, 8, true);
32 m_remoteNetworks = new ObjectArray<InetAddress>(8, 8, true);
33 }
34
35 /**
36 * Constructor for new VPNConnector object
37 */
38 VPNConnector::VPNConnector(bool hidden) : NetObj()
39 {
40 m_dwPeerGateway = 0;
41 m_localNetworks = new ObjectArray<InetAddress>(8, 8, true);
42 m_remoteNetworks = new ObjectArray<InetAddress>(8, 8, true);
43 m_isHidden = hidden;
44 }
45
46 /**
47 * VPNConnector class destructor
48 */
49 VPNConnector::~VPNConnector()
50 {
51 delete m_localNetworks;
52 delete m_remoteNetworks;
53 }
54
55 /**
56 * Create object from database data
57 */
58 bool VPNConnector::loadFromDatabase(DB_HANDLE hdb, UINT32 dwId)
59 {
60 m_id = dwId;
61
62 if (!loadCommonProperties(hdb))
63 return false;
64
65 // Load network lists
66 TCHAR szQuery[256];
67 _sntprintf(szQuery, 256, _T("SELECT ip_addr,ip_netmask,network_type FROM vpn_connector_networks WHERE vpn_id=%d"), m_id);
68 DB_RESULT hResult = DBSelect(hdb, szQuery);
69 if (hResult == NULL)
70 return false; // Query failed
71 int count = DBGetNumRows(hResult);
72 for(int i = 0; i < count; i++)
73 {
74 InetAddress addr = DBGetFieldInetAddr(hResult, i, 0);
75 addr.setMaskBits(DBGetFieldLong(hResult, i, 1));
76 if (DBGetFieldLong(hResult, i, 2) == 0)
77 m_localNetworks->add(new InetAddress(addr));
78 else
79 m_remoteNetworks->add(new InetAddress(addr));
80 }
81 DBFreeResult(hResult);
82
83 // Load custom properties
84 _sntprintf(szQuery, 256, _T("SELECT node_id,peer_gateway FROM vpn_connectors WHERE id=%d"), dwId);
85 hResult = DBSelect(hdb, szQuery);
86 if (hResult == NULL)
87 return false; // Query failed
88
89 bool success = false;
90 if (DBGetNumRows(hResult) != 0)
91 {
92 UINT32 dwNodeId = DBGetFieldULong(hResult, 0, 0);
93 m_dwPeerGateway = DBGetFieldULong(hResult, 0, 1);
94
95 // Link VPN connector to node
96 if (!m_isDeleted)
97 {
98 NetObj *pObject = FindObjectById(dwNodeId);
99 if (pObject == NULL)
100 {
101 nxlog_write(MSG_INVALID_NODE_ID_EX, NXLOG_ERROR, "dds", dwId, dwNodeId, _T("VPN connector"));
102 }
103 else if (pObject->getObjectClass() != OBJECT_NODE)
104 {
105 nxlog_write(MSG_NODE_NOT_NODE, EVENTLOG_ERROR_TYPE, "dd", dwId, dwNodeId);
106 }
107 else
108 {
109 pObject->addChild(this);
110 addParent(pObject);
111 success = true;
112 }
113 }
114 else
115 {
116 success = true;
117 }
118 }
119
120 DBFreeResult(hResult);
121
122 // Load access list
123 loadACLFromDB(hdb);
124
125 return success;
126 }
127
128 /**
129 * Save VPN connector object to database
130 */
131 bool VPNConnector::saveToDatabase(DB_HANDLE hdb)
132 {
133 // Lock object's access
134 lockProperties();
135
136 bool success = saveCommonProperties(hdb);
137
138 if (success && (m_modified & MODIFY_OTHER))
139 {
140 // Determine owning node's ID
141 Node *pNode = getParentNode();
142 UINT32 dwNodeId = (pNode != NULL) ? pNode->getId() : 0;
143
144 // Form and execute INSERT or UPDATE query
145 TCHAR szQuery[1024];
146 if (IsDatabaseRecordExist(hdb, _T("vpn_connectors"), _T("id"), m_id))
147 _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), _T("UPDATE vpn_connectors SET node_id=%d,peer_gateway=%d WHERE id=%d"),
148 dwNodeId, m_dwPeerGateway, m_id);
149 else
150 _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), _T("INSERT INTO vpn_connectors (id,node_id,peer_gateway) VALUES (%d,%d,%d)"),
151 m_id, dwNodeId, m_dwPeerGateway);
152 success = DBQuery(hdb, szQuery);
153
154 // Save network list
155 if (success)
156 success = executeQueryOnObject(hdb, _T("DELETE FROM vpn_connector_networks WHERE vpn_id=?"));
157
158 int i;
159 TCHAR buffer[64];
160 for(i = 0; success && (i < m_localNetworks->size()); i++)
161 {
162 InetAddress *addr = m_localNetworks->get(i);
163 _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR),
164 _T("INSERT INTO vpn_connector_networks (vpn_id,network_type,ip_addr,ip_netmask) VALUES (%d,0,'%s',%d)"),
165 (int)m_id, addr->toString(buffer), addr->getMaskBits());
166 success = DBQuery(hdb, szQuery);
167 }
168 for(i = 0; success && (i < m_remoteNetworks->size()); i++)
169 {
170 InetAddress *addr = m_remoteNetworks->get(i);
171 _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR),
172 _T("INSERT INTO vpn_connector_networks (vpn_id,network_type,ip_addr,ip_netmask) VALUES (%d,1,'%s',%d)"),
173 (int)m_id, addr->toString(buffer), addr->getMaskBits());
174 success = DBQuery(hdb, szQuery);
175 }
176 }
177
178 // Save access list
179 if (success)
180 success = saveACLToDB(hdb);
181
182 // Clear modifications flag and unlock object
183 m_modified = 0;
184 unlockProperties();
185
186 return success;
187 }
188
189 /**
190 * Delete VPN connector object from database
191 */
192 bool VPNConnector::deleteFromDatabase(DB_HANDLE hdb)
193 {
194 bool success = NetObj::deleteFromDatabase(hdb);
195 if (success)
196 success = executeQueryOnObject(hdb, _T("DELETE FROM vpn_connectors WHERE id=?"));
197 if (success)
198 success = executeQueryOnObject(hdb, _T("DELETE FROM vpn_connector_networks WHERE vpn_id=?"));
199 return success;
200 }
201
202 /**
203 * Get connector's parent node
204 */
205 Node *VPNConnector::getParentNode()
206 {
207 Node *pNode = NULL;
208
209 lockParentList(false);
210 for(int i = 0; i < m_parentList->size(); i++)
211 {
212 NetObj *object = m_parentList->get(i);
213 if (object->getObjectClass() == OBJECT_NODE)
214 {
215 pNode = (Node *)object;
216 break;
217 }
218 }
219 unlockParentList();
220 return pNode;
221 }
222
223 /**
224 * Create NXCP message with object's data
225 */
226 void VPNConnector::fillMessageInternal(NXCPMessage *pMsg)
227 {
228 NetObj::fillMessageInternal(pMsg);
229 pMsg->setField(VID_PEER_GATEWAY, m_dwPeerGateway);
230 pMsg->setField(VID_NUM_LOCAL_NETS, (UINT32)m_localNetworks->size());
231 pMsg->setField(VID_NUM_REMOTE_NETS, (UINT32)m_remoteNetworks->size());
232
233 UINT32 fieldId;
234 int i;
235
236 for(i = 0, fieldId = VID_VPN_NETWORK_BASE; i < m_localNetworks->size(); i++)
237 pMsg->setField(fieldId++, *m_localNetworks->get(i));
238
239 for(i = 0; i < m_remoteNetworks->size(); i++)
240 pMsg->setField(fieldId++, *m_remoteNetworks->get(i));
241 }
242
243 /**
244 * Modify object from message
245 */
246 UINT32 VPNConnector::modifyFromMessageInternal(NXCPMessage *pRequest)
247 {
248 // Peer gateway
249 if (pRequest->isFieldExist(VID_PEER_GATEWAY))
250 m_dwPeerGateway = pRequest->getFieldAsUInt32(VID_PEER_GATEWAY);
251
252 // Network list
253 if ((pRequest->isFieldExist(VID_NUM_LOCAL_NETS)) &&
254 (pRequest->isFieldExist(VID_NUM_REMOTE_NETS)))
255 {
256 int i;
257 UINT32 fieldId = VID_VPN_NETWORK_BASE;
258
259 m_localNetworks->clear();
260 int count = pRequest->getFieldAsInt32(VID_NUM_LOCAL_NETS);
261 for(i = 0; i < count; i++)
262 m_localNetworks->add(new InetAddress(pRequest->getFieldAsInetAddress(fieldId++)));
263
264 m_remoteNetworks->clear();
265 count = pRequest->getFieldAsInt32(VID_NUM_REMOTE_NETS);
266 for(i = 0; i < count; i++)
267 m_remoteNetworks->add(new InetAddress(pRequest->getFieldAsInetAddress(fieldId++)));
268 }
269
270 return NetObj::modifyFromMessageInternal(pRequest);
271 }
272
273 /**
274 * Check if given address falls into one of the local nets
275 */
276 bool VPNConnector::isLocalAddr(const InetAddress& addr)
277 {
278 bool result = false;
279
280 lockProperties();
281
282 for(int i = 0; i < m_localNetworks->size(); i++)
283 if (m_localNetworks->get(i)->contain(addr))
284 {
285 result = true;
286 break;
287 }
288
289 unlockProperties();
290 return result;
291 }
292
293 /**
294 * Check if given address falls into one of the remote nets
295 */
296 bool VPNConnector::isRemoteAddr(const InetAddress& addr)
297 {
298 bool result = false;
299
300 lockProperties();
301
302 for(int i = 0; i < m_remoteNetworks->size(); i++)
303 if (m_remoteNetworks->get(i)->contain(addr))
304 {
305 result = true;
306 break;
307 }
308
309 unlockProperties();
310 return result;
311 }
312
313 /**
314 * Get address of peer gateway
315 */
316 InetAddress VPNConnector::getPeerGatewayAddr()
317 {
318 NetObj *pObject;
319
320 pObject = FindObjectById(m_dwPeerGateway);
321 if (pObject != NULL)
322 {
323 if (pObject->getObjectClass() == OBJECT_NODE)
324 return ((Node *)pObject)->getIpAddress();
325 }
326 return InetAddress();
327 }
328
329 /**
330 * Serialize object to JSON
331 */
332 json_t *VPNConnector::toJson()
333 {
334 json_t *root = NetObj::toJson();
335 json_object_set_new(root, "peerGateway", json_integer(m_dwPeerGateway));
336 json_object_set_new(root, "localNetworks", json_object_array(m_localNetworks));
337 json_object_set_new(root, "remoteNetworks", json_object_array(m_remoteNetworks));
338 return root;
339 }