Rollback from r3608 to r3606
[public/netxms.git] / src / server / core / netinfo.cpp
CommitLineData
5039dede
AK
1/*
2** NetXMS - Network Management System
3** Copyright (C) 2003, 2004 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** $module: netinfo.cpp
20**
21**/
22
23#include "nxcore.h"
24
25
26#ifdef _WIN32
27
28#include <iphlpapi.h>
29#include <iprtrmib.h>
30#include <rtinfo.h>
31
32#else
33
34#if HAVE_SYS_UTSNAME_H
35#include <sys/utsname.h>
36#endif
37
38#endif /* _WIN32 */
39
40
41//
42// Static data
43//
44
45#ifdef _WIN32
46static DWORD (__stdcall *imp_HrLanConnectionNameFromGuidOrPath)(LPWSTR, LPWSTR, LPWSTR, LPDWORD) = NULL;
47#else
48static HMODULE m_hSubAgent = NULL;
49static BOOL (* imp_NxSubAgentGetIfList)(NETXMS_VALUES_LIST *) = NULL;
50static BOOL (* imp_NxSubAgentGetArpCache)(NETXMS_VALUES_LIST *) = NULL;
51#endif
52
53
54//
55// Initialize
56//
57
58void InitLocalNetInfo(void)
59{
60#ifdef _WIN32
61 HMODULE hModule;
62
63 hModule = LoadLibrary("NETMAN.DLL");
64 if (hModule != NULL)
65 {
66 imp_HrLanConnectionNameFromGuidOrPath =
67 (DWORD (__stdcall *)(LPWSTR, LPWSTR, LPWSTR, LPDWORD))GetProcAddress(hModule, "HrLanConnectionNameFromGuidOrPath");
68 }
69#elif HAVE_SYS_UTSNAME_H
70 struct utsname un;
71 char szName[MAX_PATH], szErrorText[256];
72 int i;
73
74 if (uname(&un) != -1)
75 {
76 // Convert system name to lowercase
77 for(i = 0; un.sysname[i] != 0; i++)
78 un.sysname[i] = tolower(un.sysname[i]);
79 if (!strcmp(un.sysname, "hp-ux"))
80 strcpy(un.sysname, "hpux");
81 snprintf(szName, MAX_PATH, LIBDIR "/libnsm_%s" SHL_SUFFIX, un.sysname);
82
83 m_hSubAgent = DLOpen(szName, szErrorText);
84 if (m_hSubAgent != NULL)
85 {
86 imp_NxSubAgentGetIfList = (BOOL (*)(NETXMS_VALUES_LIST *))DLGetSymbolAddr(m_hSubAgent, "__NxSubAgentGetIfList", NULL);
87 imp_NxSubAgentGetArpCache = (BOOL (*)(NETXMS_VALUES_LIST *))DLGetSymbolAddr(m_hSubAgent, "__NxSubAgentGetArpCache", NULL);
88 if ((imp_NxSubAgentGetIfList == NULL) &&
89 (imp_NxSubAgentGetArpCache == NULL))
90 {
91 DLClose(m_hSubAgent);
92 m_hSubAgent = NULL;
93 nxlog_write(MSG_PLATFORM_SUBAGENT_NOT_LOADED, EVENTLOG_ERROR_TYPE,
94 "ss", szName, _T("Subagent doesn't provide any usable parameters"));
95 }
96 else
97 {
98 nxlog_write(MSG_PLATFORM_SUBAGENT_LOADED,
99 EVENTLOG_INFORMATION_TYPE, "s", szName);
100 }
101 }
102 else
103 {
104 nxlog_write(MSG_PLATFORM_SUBAGENT_NOT_LOADED, EVENTLOG_ERROR_TYPE,
105 "ss", szName, szErrorText);
106 }
107 }
108#endif
109}
110
111
112//
113// Convert string representation of MAC address to binary form
114//
115
116void StrToMac(char *pszStr, BYTE *pBuffer)
117{
118 DWORD byte1, byte2, byte3, byte4, byte5, byte6;
119
120 memset(pBuffer, 6, 0);
121 if (sscanf(pszStr, "%x:%x:%x:%x:%x:%x", &byte1, &byte2, &byte3,
122 &byte4, &byte5, &byte6) == 6)
123 {
124 pBuffer[0] = (BYTE)byte1;
125 pBuffer[1] = (BYTE)byte2;
126 pBuffer[2] = (BYTE)byte3;
127 pBuffer[3] = (BYTE)byte4;
128 pBuffer[4] = (BYTE)byte5;
129 pBuffer[5] = (BYTE)byte6;
130 }
131}
132
133
134//
135// Get local ARP cache
136//
137
138static ARP_CACHE *SysGetLocalArpCache(void)
139{
140 ARP_CACHE *pArpCache = NULL;
141
142#ifdef _WIN32
143 MIB_IPNETTABLE *sysArpCache;
144 DWORD i, dwError, dwSize;
145
146 sysArpCache = (MIB_IPNETTABLE *)malloc(SIZEOF_IPNETTABLE(4096));
147 if (sysArpCache == NULL)
148 return NULL;
149
150 dwSize = SIZEOF_IPNETTABLE(4096);
151 dwError = GetIpNetTable(sysArpCache, &dwSize, FALSE);
152 if (dwError != NO_ERROR)
153 {
154 nxlog_write(MSG_GETIPNETTABLE_FAILED, EVENTLOG_ERROR_TYPE, "e", NULL);
155 free(sysArpCache);
156 return NULL;
157 }
158
159 pArpCache = (ARP_CACHE *)malloc(sizeof(ARP_CACHE));
160 pArpCache->dwNumEntries = 0;
161 pArpCache->pEntries = (ARP_ENTRY *)malloc(sizeof(ARP_ENTRY) * sysArpCache->dwNumEntries);
162
163 for(i = 0; i < sysArpCache->dwNumEntries; i++)
164 if ((sysArpCache->table[i].dwType == 3) ||
165 (sysArpCache->table[i].dwType == 4)) // Only static and dynamic entries
166 {
167 pArpCache->pEntries[pArpCache->dwNumEntries].dwIndex = sysArpCache->table[i].dwIndex;
168 pArpCache->pEntries[pArpCache->dwNumEntries].dwIpAddr = ntohl(sysArpCache->table[i].dwAddr);
169 memcpy(pArpCache->pEntries[pArpCache->dwNumEntries].bMacAddr, sysArpCache->table[i].bPhysAddr, 6);
170 pArpCache->dwNumEntries++;
171 }
172
173 free(sysArpCache);
174#else
175 NETXMS_VALUES_LIST list;
176 TCHAR szByte[4], *pBuf, *pChar;
177 DWORD i, j;
178
179 if (imp_NxSubAgentGetArpCache != NULL)
180 {
181 memset(&list, 0, sizeof(NETXMS_VALUES_LIST));
182 if (imp_NxSubAgentGetArpCache(&list))
183 {
184 // Create empty structure
185 pArpCache = (ARP_CACHE *)malloc(sizeof(ARP_CACHE));
186 pArpCache->dwNumEntries = list.dwNumStrings;
187 pArpCache->pEntries = (ARP_ENTRY *)malloc(sizeof(ARP_ENTRY) * list.dwNumStrings);
188 memset(pArpCache->pEntries, 0, sizeof(ARP_ENTRY) * list.dwNumStrings);
189
190 szByte[2] = 0;
191
192 // Parse data lines
193 // Each line has form of XXXXXXXXXXXX a.b.c.d n
194 // where XXXXXXXXXXXX is a MAC address (12 hexadecimal digits)
195 // a.b.c.d is an IP address in decimal dotted notation
196 // n is an interface index
197 for(i = 0; i < list.dwNumStrings; i++)
198 {
199 pBuf = list.ppStringList[i];
200 if (_tcslen(pBuf) < 20) // Invalid line
201 continue;
202
203 // MAC address
204 for(j = 0; j < 6; j++)
205 {
206 memcpy(szByte, pBuf, sizeof(TCHAR) * 2);
207 pArpCache->pEntries[i].bMacAddr[j] = (BYTE)_tcstol(szByte, NULL, 16);
208 pBuf+=2;
209 }
210
211 // IP address
212 while(*pBuf == ' ')
213 pBuf++;
214 pChar = _tcschr(pBuf, _T(' '));
215 if (pChar != NULL)
216 *pChar = 0;
217 pArpCache->pEntries[i].dwIpAddr = ntohl(_t_inet_addr(pBuf));
218
219 // Interface index
220 if (pChar != NULL)
221 pArpCache->pEntries[i].dwIndex = _tcstoul(pChar + 1, NULL, 10);
222 }
223
224 for(i = 0; i < list.dwNumStrings; i++)
225 safe_free(list.ppStringList[i]);
226 safe_free(list.ppStringList);
227 }
228 }
229#endif
230
231 return pArpCache;
232}
233
234
235//
236// Get local interface list (built-in system dependent code)
237//
238
239static INTERFACE_LIST *SysGetLocalIfList(void)
240{
241 INTERFACE_LIST *pIfList = NULL;
242
243#ifdef _WIN32
244 DWORD dwSize;
245 IP_ADAPTER_INFO *pBuffer, *pInfo;
246 char szAdapterName[MAX_OBJECT_NAME];
247 char szMacAddr[MAX_ADAPTER_ADDRESS_LENGTH * 2 + 1];
248 IP_ADDR_STRING *pAddr;
249
250 if (GetAdaptersInfo(NULL, &dwSize) != ERROR_BUFFER_OVERFLOW)
251 {
252 return NULL;
253 }
254
255 pBuffer = (IP_ADAPTER_INFO *)malloc(dwSize);
256 if (GetAdaptersInfo(pBuffer, &dwSize) == ERROR_SUCCESS)
257 {
258 // Allocate and initialize interface list structure
259 pIfList = (INTERFACE_LIST *)malloc(sizeof(INTERFACE_LIST));
260 pIfList->iNumEntries = 0;
261 pIfList->pInterfaces = NULL;
262
263 for(pInfo = pBuffer; pInfo != NULL; pInfo = pInfo->Next)
264 {
265 // Get network connection name from adapter name, if possible
266 if (imp_HrLanConnectionNameFromGuidOrPath != NULL)
267 {
268 WORD wGUID[256], wName[256];
269
270 // Resolve GUID to network connection name
271 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pInfo->AdapterName, -1, wGUID, 256);
272 wGUID[255] = 0;
273 dwSize = 256;
274 if (imp_HrLanConnectionNameFromGuidOrPath(NULL, wGUID, wName, &dwSize) == 0)
275 {
276 WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK | WC_DEFAULTCHAR,
277 wName, dwSize, szAdapterName, MAX_OBJECT_NAME, NULL, NULL);
278 szAdapterName[MAX_OBJECT_NAME - 1] = 0;
279 }
280 else
281 {
282 nx_strncpy(szAdapterName, pInfo->AdapterName, MAX_OBJECT_NAME);
283 }
284 }
285 else
286 {
287 // We don't have a GUID resolving function, use GUID as name
288 nx_strncpy(szAdapterName, pInfo->AdapterName, MAX_OBJECT_NAME);
289 }
290
291 BinToStr(pInfo->Address, pInfo->AddressLength, szMacAddr);
292
293 // Compose result for each ip address
294 for(pAddr = &pInfo->IpAddressList; pAddr != NULL; pAddr = pAddr->Next)
295 {
296 pIfList->pInterfaces = (INTERFACE_INFO *)realloc(pIfList->pInterfaces,
297 sizeof(INTERFACE_INFO) * (pIfList->iNumEntries + 1));
298 nx_strncpy(pIfList->pInterfaces[pIfList->iNumEntries].szName, szAdapterName, MAX_OBJECT_NAME);
299 memcpy(pIfList->pInterfaces[pIfList->iNumEntries].bMacAddr, pInfo->Address, MAC_ADDR_LENGTH);
300 pIfList->pInterfaces[pIfList->iNumEntries].dwIndex = pInfo->Index;
301 pIfList->pInterfaces[pIfList->iNumEntries].dwIpAddr = ntohl(_t_inet_addr(pAddr->IpAddress.String));
302 pIfList->pInterfaces[pIfList->iNumEntries].dwIpNetMask = ntohl(_t_inet_addr(pAddr->IpMask.String));
303 pIfList->pInterfaces[pIfList->iNumEntries].dwType = pInfo->Type;
304 pIfList->pInterfaces[pIfList->iNumEntries].iNumSecondary = 0;
305 pIfList->iNumEntries++;
306 }
307 }
308 }
309
310 free(pBuffer);
311
312#else
313 NETXMS_VALUES_LIST list;
314 DWORD i, dwBits;
315 TCHAR *pChar, *pBuf;
316
317 if (imp_NxSubAgentGetIfList != NULL)
318 {
319 memset(&list, 0, sizeof(NETXMS_VALUES_LIST));
320 if (imp_NxSubAgentGetIfList(&list))
321 {
322 pIfList = (INTERFACE_LIST *)malloc(sizeof(INTERFACE_LIST));
323 pIfList->iNumEntries = list.dwNumStrings;
324 pIfList->pInterfaces = (INTERFACE_INFO *)malloc(sizeof(INTERFACE_INFO) * list.dwNumStrings);
325 memset(pIfList->pInterfaces, 0, sizeof(INTERFACE_INFO) * list.dwNumStrings);
326 for(i = 0; i < list.dwNumStrings; i++)
327 {
328 pBuf = list.ppStringList[i];
329
330 // Index
331 pChar = _tcschr(pBuf, ' ');
332 if (pChar != NULL)
333 {
334 *pChar = 0;
335 pIfList->pInterfaces[i].dwIndex = _tcstoul(pBuf, NULL, 10);
336 pBuf = pChar + 1;
337 }
338
339 // Address and mask
340 pChar = _tcschr(pBuf, _T(' '));
341 if (pChar != NULL)
342 {
343 TCHAR *pSlash;
344 static TCHAR defaultMask[] = _T("24");
345
346 *pChar = 0;
347 pSlash = _tcschr(pBuf, _T('/'));
348 if (pSlash != NULL)
349 {
350 *pSlash = 0;
351 pSlash++;
352 }
353 else // Just a paranoia protection, should'n happen if subagent working correctly
354 {
355 pSlash = defaultMask;
356 }
357 pIfList->pInterfaces[i].dwIpAddr = ntohl(_t_inet_addr(pBuf));
358 dwBits = _tcstoul(pSlash, NULL, 10);
359 pIfList->pInterfaces[i].dwIpNetMask = (dwBits == 32) ? 0xFFFFFFFF : (~(0xFFFFFFFF >> dwBits));
360 pBuf = pChar + 1;
361 }
362
363 // Interface type
364 pChar = _tcschr(pBuf, ' ');
365 if (pChar != NULL)
366 {
367 *pChar = 0;
368 pIfList->pInterfaces[i].dwType = _tcstoul(pBuf, NULL, 10);
369 pBuf = pChar + 1;
370 }
371
372 // MAC address
373 pChar = _tcschr(pBuf, ' ');
374 if (pChar != NULL)
375 {
376 *pChar = 0;
377 StrToBin(pBuf, pIfList->pInterfaces[i].bMacAddr, MAC_ADDR_LENGTH);
378 pBuf = pChar + 1;
379 }
380
381 // Name
382 nx_strncpy(pIfList->pInterfaces[i].szName, pBuf, MAX_OBJECT_NAME - 1);
383 }
384
385 for(i = 0; i < list.dwNumStrings; i++)
386 safe_free(list.ppStringList[i]);
387 safe_free(list.ppStringList);
388 }
389 }
390#endif
391
392 return pIfList;
393}
394
395
396//
397// Get local ARP cache
398//
399
400ARP_CACHE *GetLocalArpCache(void)
401{
402 ARP_CACHE *pArpCache = NULL;
403
404 // Get ARP cache from built-in code or platform subagent
405 pArpCache = SysGetLocalArpCache();
406
407 // Try to get ARP cache from agent via loopback address
408 if (pArpCache == NULL)
409 {
410 AgentConnection conn(inet_addr("127.0.0.1"));
411
412 if (conn.Connect(g_pServerKey))
413 {
414 pArpCache = conn.GetArpCache();
415 conn.Disconnect();
416 }
417 }
418
419 return pArpCache;
420}
421
422
423//
424// Get local interface list
425//
426
427INTERFACE_LIST *GetLocalInterfaceList(void)
428{
429 INTERFACE_LIST *pIfList = NULL;
430
431 // Get interface list from built-in code or platform subagent
432 pIfList = SysGetLocalIfList();
433
434 // Try to get local interface list from agent via loopback address
435 if (pIfList == NULL)
436 {
437 AgentConnection conn(inet_addr("127.0.0.1"));
438
439 if (conn.Connect(g_pServerKey))
440 {
441 pIfList = conn.GetInterfaceList();
442 conn.Disconnect();
443 }
444 }
445
446 CleanInterfaceList(pIfList);
447 return pIfList;
448}