3dfbdc529c58b05629537413386d2539b41d0e7f
[public/netxms.git] / src / agent / subagents / hpux / net.cpp
1 /*
2 ** NetXMS subagent for HP-UX
3 ** Copyright (C) 2010 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 */
20
21 #include <nms_common.h>
22 #include <nms_agent.h>
23 #include <net/if.h>
24 #if HAVE_NET_IF_TYPES_H
25 #include <net/if_types.h>
26 #endif
27
28 #define __STDC__
29 extern "C" {
30 #include <sys/mib.h>
31 }
32
33 #include "net.h"
34
35 #ifndef IFT_LOOP
36 #define IFT_LOOP 24
37 #endif
38
39
40 //
41 // Internal interface representation
42 //
43
44 #define MAX_IPADDR_COUNT 256
45
46 struct IPADDR
47 {
48 DWORD addr;
49 DWORD mask;
50 };
51
52 struct NETIF
53 {
54 char device[MAX_PHYSADDR_LEN];
55 int ppa;
56 int ifIndex;
57 char ifName[MAX_NAME_LENGTH];
58 int ifType;
59 BYTE macAddr[MAX_PHYSADDR_LEN];
60 int ipAddrCount;
61 IPADDR ipAddrList[MAX_IPADDR_COUNT];
62 };
63
64
65 //
66 // Find interface name by interface index
67 //
68
69 #if HAVE_DECL_SIOCGIFNAME
70
71 static char *IfIndexToName(int index, char *buffer)
72 {
73 int fd;
74 struct ifreq ifr;
75 char *ret = NULL;
76
77 fd = socket(AF_INET, SOCK_DGRAM, 0);
78 if (fd != -1)
79 {
80 ifr.ifr_index = index;
81 if (ioctl(fd, SIOCGIFNAME, &ifr) == 0)
82 {
83 strcpy(buffer, ifr.ifr_name);
84 ret = buffer;
85 }
86 close(fd);
87 }
88
89 return ret;
90 }
91
92 #endif
93
94
95 //
96 // Find interface index by name
97 //
98
99 #if HAVE_DECL_SIOCGIFINDEX
100
101 static int IfNameToIndex(const char *name)
102 {
103 int fd, index = -1;
104 struct ifreq ifr;
105
106 fd = socket(AF_INET, SOCK_DGRAM, 0);
107 if (fd != -1)
108 {
109 nx_strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
110 if (ioctl(fd, SIOCGIFINDEX, &ifr) == 0)
111 {
112 index = ifr.ifr_index;
113 }
114 close(fd);
115 }
116
117 return index;
118 }
119
120 #endif
121
122
123 //
124 // Get interface list
125 //
126
127 static int GetInterfaceList(NETIF **iflist)
128 {
129 nmapi_iftable ift[1024];
130 unsigned int size;
131 int i, mib, ifcount;
132 NETIF *curr;
133
134 size = sizeof(ift);
135 if (get_if_table(ift, &size) != 0)
136 return -1;
137
138 ifcount = size / sizeof(nmapi_iftable);
139 *iflist = (NETIF *)malloc(ifcount * sizeof(NETIF));
140 memset(*iflist, 0, ifcount * sizeof(NETIF));
141
142 for(i = 0; i < ifcount; i++)
143 {
144 mib = open_mib(ift[i].nm_device, O_RDWR, ift[i].nm_ppanum, 0);
145 if (mib >= 0)
146 {
147 struct nmparms np;
148 mib_ifEntry iface;
149 unsigned int ifeSize = sizeof(mib_ifEntry);
150
151 np.objid = ID_ifEntry;
152 np.buffer = &iface;
153 np.len = &ifeSize;
154 iface.ifIndex = ift[i].nm_ifindex;
155 if (get_mib_info(mib, &np) == 0)
156 {
157 curr = *iflist + i;
158 strcpy(curr->device, ift[i].nm_device);
159 curr->ppa = ift[i].nm_ppanum;
160 curr->ifIndex = iface.ifIndex;
161 curr->ifType = iface.ifType;
162 memcpy(curr->macAddr, iface.ifPhysAddress.o_bytes, iface.ifPhysAddress.o_length);
163 #if HAVE_DECL_SIOCGIFNAME
164 IfIndexToName(iface.ifIndex, curr->ifName);
165 #else
166 nx_strncpy(curr->ifName, iface.ifDescr, MAX_NAME_LENGTH);
167 #endif
168 }
169 close_mib(mib);
170 }
171 }
172
173 // Remove loopback and unplumbed interfaces
174 for(i = 0; i < ifcount; i++)
175 {
176 if (((*iflist)[i].ifType == IFT_LOOP) || // loopback
177 ((*iflist)[i].ifName[0] == 0)) // unplumbed
178 {
179 ifcount--;
180 memmove(*iflist + i, *iflist + i + 1, (ifcount - i) * sizeof(NETIF));
181 i--;
182 }
183 }
184
185 // Get IP addresses
186 mib = open_mib("/dev/ip", O_RDWR, 0, 0);
187 if (mib >= 0)
188 {
189 struct nmparms np;
190 unsigned int addrCount;
191 unsigned int bufSize = sizeof(unsigned int);
192
193 np.objid = ID_ipAddrNumEnt;
194 np.buffer = &addrCount;
195 np.len = &bufSize;
196 if (get_mib_info(mib, &np) == 0)
197 {
198 bufSize = addrCount * sizeof(mib_ipAdEnt);
199 mib_ipAdEnt *ipList = (mib_ipAdEnt *)malloc(bufSize);
200 memset(ipList, 0, bufSize);
201 np.objid = ID_ipAddrTable;
202 np.buffer = ipList;
203 np.len = &bufSize;
204 if (get_mib_info(mib, &np) == 0)
205 {
206 for(i = 0; i < (int)addrCount; i++)
207 {
208 if (ipList[i].Addr != 0)
209 {
210 for(int j = 0; j < ifcount; j++)
211 {
212 if (((*iflist)[j].ifIndex == ipList[i].IfIndex) && ((*iflist)[j].ipAddrCount < MAX_IPADDR_COUNT))
213 {
214 int pos = (*iflist)[j].ipAddrCount++;
215 (*iflist)[j].ipAddrList[pos].addr = ipList[i].Addr;
216 (*iflist)[j].ipAddrList[pos].mask = ipList[i].NetMask;
217 break;
218 }
219 }
220 }
221 }
222 }
223 free(ipList);
224 }
225 close_mib(mib);
226 }
227
228 return ifcount;
229 }
230
231
232 //
233 // Handler for Net.InterfaceList enum
234 //
235
236 LONG H_NetIfList(const char *pszParam, const char *pArg, StringList *pValue)
237 {
238 int i, j, ifCount;
239 NETIF *ifList;
240 char macAddr[16], ipAddr[32], buffer[256];
241
242 ifCount = GetInterfaceList(&ifList);
243 if (ifCount == -1)
244 return SYSINFO_RC_ERROR;
245
246 for(i = 0; i < ifCount; i++)
247 {
248 BinToStr(ifList[i].macAddr, 6, macAddr);
249 if (ifList[i].ipAddrCount == 0)
250 {
251 snprintf(buffer, 256, "%d 0.0.0.0/0 %d %s %s", ifList[i].ifIndex, ifList[i].ifType, macAddr, ifList[i].ifName);
252 pValue->add(buffer);
253 }
254 else
255 {
256 snprintf(buffer, 256, "%d %s/%d %d %s %s", ifList[i].ifIndex, IpToStr(ifList[i].ipAddrList[0].addr, ipAddr),
257 BitsInMask(ifList[i].ipAddrList[0].mask), ifList[i].ifType, macAddr, ifList[i].ifName);
258 pValue->add(buffer);
259
260 for(j = 1; j < ifList[i].ipAddrCount; j++)
261 {
262 snprintf(buffer, 256, "%d %s/%d %d %s %s:%d", ifList[i].ifIndex, IpToStr(ifList[i].ipAddrList[j].addr, ipAddr),
263 BitsInMask(ifList[i].ipAddrList[j].mask), ifList[i].ifType, macAddr, ifList[i].ifName, j);
264 pValue->add(buffer);
265 }
266 }
267 }
268 free(ifList);
269 return SYSINFO_RC_SUCCESS;
270 }
271
272
273 //
274 // Handler for Net.ArpCache enum
275 //
276
277 LONG H_NetArpCache(const char *pszParam, const char *pArg, StringList *pValue)
278 {
279 int i, mib;
280 struct nmparms np;
281 mib_ipNetToMediaEnt arpCache[8192];
282 unsigned int size, count;
283 char buffer[256], mac[MAX_PHYSADDR_LEN * 2 + 1], ip[32];
284 LONG nRet = SYSINFO_RC_ERROR;
285
286 mib = open_mib("/dev/ip", O_RDWR, 0, 0);
287 if (mib >= 0)
288 {
289 size = sizeof(arpCache);
290 np.objid = ID_ipNetToMediaTable;
291 np.buffer = arpCache;
292 np.len = &size;
293 if (get_mib_info(mib, &np) == 0)
294 {
295 count = size / sizeof(mib_AtEntry);
296 for(i = 0; i < count; i++)
297 {
298 if (((arpCache[i].Type == INTM_DYNAMIC) || (arpCache[i].Type == INTM_STATIC)) &&
299 (arpCache[i].PhysAddr.o_length > 0))
300 {
301 snprintf(buffer, 256, "%s %s %d", BinToStr(arpCache[i].PhysAddr.o_bytes, arpCache[i].PhysAddr.o_length, mac),
302 IpToStr(arpCache[i].NetAddr, ip), arpCache[i].IfIndex);
303 pValue->add(buffer);
304 }
305 }
306 nRet = SYSINFO_RC_SUCCESS;
307 }
308 close_mib(mib);
309 }
310 return nRet;
311 }
312
313
314 //
315 // Handler for Net.IP.Forwarding parameter
316 //
317
318 LONG H_NetIpForwarding(const char *pszParam, const char *pArg, char *pValue)
319 {
320 int ipVer = CAST_FROM_POINTER(pArg, int);
321 int nRet = SYSINFO_RC_ERROR;
322 int mib;
323 unsigned int size, fwFlag;
324 struct nmparms np;
325
326 mib = open_mib((ipVer == 4) ? "/dev/ip" : "/dev/ip6", O_RDWR, 0, 0);
327 if (mib >= 0)
328 {
329 size = sizeof(unsigned int);
330 np.objid = (ipVer == 4) ? ID_ipForwarding : ID_ipv6Forwarding;
331 np.buffer = &fwFlag;
332 np.len = &size;
333 if (get_mib_info(mib, &np) == 0)
334 {
335 ret_int(pValue, (fwFlag == 1) ? 1 : 0);
336 nRet = SYSINFO_RC_SUCCESS;
337 }
338 close_mib(mib);
339 }
340
341 return nRet;
342 }
343
344
345 LONG H_NetRoutingTable(const char *pszParam, const char *pArg, StringList *pValue)
346 {
347 int nRet = SYSINFO_RC_ERROR;
348
349 // TODO
350
351 return nRet;
352 }
353
354
355 //
356 // Handler for Net.Interface.* parameters
357 //
358
359 LONG H_NetIfInfo(const char *pszParam, const char *pArg, char *pValue)
360 {
361 char *eptr, buffer[256];
362 nmapi_iftable ift[1024];
363 int i, mib, ifCount, ifIndex;
364 unsigned int size;
365 LONG nRet = SYSINFO_RC_SUCCESS;
366
367 if (!AgentGetParameterArg(pszParam, 1, buffer, 256))
368 {
369 return SYSINFO_RC_ERROR;
370 }
371
372 // Check if we have interface name or index
373 ifIndex = strtol(buffer, &eptr, 10);
374 if (*eptr != 0)
375 {
376 // Name passed as argument, convert to index
377 #if HAVE_DECL_SIOCGIFINDEX
378 ifIndex = IfNameToIndex(buffer);
379 #else
380 return SYSINFO_RC_UNSUPPORTED; // Unable to convert interface name to index
381 #endif
382 }
383 if (ifIndex <= 0)
384 return SYSINFO_RC_UNSUPPORTED;
385
386 // Find driver for interface
387 size = sizeof(ift);
388 if (get_if_table(ift, &size) != 0)
389 return SYSINFO_RC_ERROR;
390 ifCount = size / sizeof(nmapi_iftable);
391 for(i = 0; i < ifCount; i++)
392 if (ift[i].nm_ifindex == ifIndex)
393 break;
394 if (i == ifCount)
395 return SYSINFO_RC_UNSUPPORTED; // Interface not found
396
397 mib = open_mib(ift[i].nm_device, O_RDWR, ift[i].nm_ppanum, 0);
398 if (mib >= 0)
399 {
400 struct nmparms np;
401 mib_ifEntry iface;
402 unsigned int ifeSize = sizeof(mib_ifEntry);
403
404 np.objid = ID_ifEntry;
405 np.buffer = &iface;
406 np.len = &ifeSize;
407 iface.ifIndex = ift[i].nm_ifindex;
408 if (get_mib_info(mib, &np) == 0)
409 {
410 nRet = SYSINFO_RC_SUCCESS;
411
412 // Get interface information
413 switch((long)pArg)
414 {
415 case IF_INFO_ADMIN_STATUS:
416 ret_int(pValue, iface.ifAdmin);
417 break;
418 case IF_INFO_OPER_STATUS:
419 ret_int(pValue, (iface.ifOper == 1) ? 1 : 0);
420 break;
421 case IF_INFO_DESCRIPTION:
422 ret_string(pValue, iface.ifDescr);
423 break;
424 case IF_INFO_MTU:
425 ret_int(pValue, iface.ifMtu);
426 break;
427 case IF_INFO_SPEED:
428 ret_uint(pValue, iface.ifSpeed);
429 break;
430 case IF_INFO_BYTES_IN:
431 ret_uint(pValue, iface.ifInOctets);
432 break;
433 case IF_INFO_BYTES_OUT:
434 ret_uint(pValue, iface.ifOutOctets);
435 break;
436 case IF_INFO_PACKETS_IN:
437 ret_uint(pValue, iface.ifInUcastPkts + iface.ifInNUcastPkts);
438 break;
439 case IF_INFO_PACKETS_OUT:
440 ret_uint(pValue, iface.ifOutUcastPkts + iface.ifOutNUcastPkts);
441 break;
442 case IF_INFO_IN_ERRORS:
443 ret_uint(pValue, iface.ifInErrors);
444 break;
445 case IF_INFO_OUT_ERRORS:
446 ret_uint(pValue, iface.ifOutErrors);
447 break;
448 default:
449 nRet = SYSINFO_RC_UNSUPPORTED;
450 break;
451 }
452 }
453 close_mib(mib);
454 }
455
456 return nRet;
457 }