4 ** NetXMS subagent for FreeBSD
5 ** Copyright (C) 2004 Alex Kirhenshtein
7 ** This program is free software; you can redistribute it and/or modify
8 ** it under the terms of the GNU General Public License as published by
9 ** the Free Software Foundation; either version 2 of the License, or
10 ** (at your option) any later version.
12 ** This program is distributed in the hope that it will be useful,
13 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ** GNU General Public License for more details.
17 ** You should have received a copy of the GNU General Public License
18 ** along with this program; if not, write to the Free Software
19 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #include <sys/sysctl.h>
26 #include <sys/sockio.h>
28 #include <net/if_media.h>
29 #include <net/if_dl.h>
30 #include <net/if_types.h>
31 #include <net/route.h>
32 #include <netinet/if_ether.h>
33 #include <netinet/in.h>
34 #include <arpa/inet.h>
35 #include <net/ethernet.h>
39 // Internal data structures
42 #define MAX_IF_NAME 128
44 typedef struct t_IfData
46 char szName
[MAX_IF_NAME
];
51 char szPhysIfName
[MAX_IF_NAME
];
57 typedef struct t_IfList
73 // Index to name resolution callback parameters
86 // Callback for index to name resolution
89 static void IndexCallback(char *pszPath
, IRPARAM
*pArg
)
91 char *ptr
, szCtl
[256];
94 snprintf(szCtl
, 256, "%s:index", pszPath
);
95 if (IPSCTLGetInt(pArg
->nHandle
, szCtl
, &nIndex
) == SYSINFO_RC_SUCCESS
)
97 if (nIndex
== pArg
->nIndex
)
99 ptr
= strrchr(pszPath
, ':');
104 nx_strncpy(pArg
->pszName
, ptr
, MAX_IF_NAME
);
105 pArg
->pszResult
= pArg
->pszName
;
112 // Convert logical interface index to name
115 static char *IndexToName(int nIndex
, char *pszName
, BOOL
*pbIsLogical
)
119 if (nIndex
>= 0x01000000)
122 return if_indextoname(nIndex
- 0x01000000, pszName
);
125 *pbIsLogical
= FALSE
;
127 data
.pszResult
= NULL
;
128 data
.nHandle
= ipsctl_open();
129 if (data
.nHandle
> 0)
131 data
.nIndex
= nIndex
;
132 data
.pszName
= pszName
;
133 ipsctl_iterate(data
.nHandle
, "ifphys", IndexCallback
, &data
);
134 ipsctl_close(data
.nHandle
);
136 return data
.pszResult
;
141 // Handler for Net.IP.Forwarding parameter
144 LONG
H_NetIpForwarding(char *pszParam
, char *pArg
, char *pValue
)
146 int nVer
= (int)pArg
;
147 int nRet
= SYSINFO_RC_ERROR
;
152 return ERR_NOT_IMPLEMENTED
;
155 nRet
= IPSCTLGetInt(0, "net:ip:forward:noforwarding", &nVal
);
156 if (nRet
== SYSINFO_RC_SUCCESS
)
157 ret_int(pValue
, !nVal
);
164 // Handler for Net.Interface.XXX parameters
167 LONG
H_NetIfStats(char *pszParam
, char *pArg
, char *pValue
)
169 LONG nTemp
, nRet
= SYSINFO_RC_SUCCESS
;
170 char szName
[MAX_IF_NAME
], szRequest
[256];
172 static char *pszRqListLog
[] =
175 "interface:%s:flags:link_avail",
176 "interface:%s:flags:up",
177 "interface:%s:stats:ibytes",
178 "interface:%s:stats:obytes",
179 "interface:%s:stats:ipackets",
180 "interface:%s:stats:opackets"
182 static char *pszRqListPhy
[] =
184 "ifphys:%s:dev_type",
185 "ifphys:%s:flags:link",
186 "ifphys:%s:flags:up",
187 "ifphys:%s:stats:ibytes",
188 "ifphys:%s:stats:obytes",
189 "ifphys:%s:stats:ipackets",
190 "ifphys:%s:stats:opackets"
193 if (!AgentGetParameterArg(pszParam
, 1, szName
, sizeof(szName
)))
194 return SYSINFO_RC_UNSUPPORTED
;
198 // Convert interface index to name if needed
199 if (szName
[0] >= '0' && szName
[0] <= '9')
202 if (IndexToName(atoi(szName
), szName
, &isLogical
) != szName
)
205 nRet
= SYSINFO_RC_ERROR
;
210 // Check if interface is physical or logical
211 snprintf(szRequest
, sizeof(szRequest
), "ifphys:%s:index", szName
);
212 isLogical
= (IPSCTLGetInt(0, szRequest
, &nTemp
) == SYSINFO_RC_SUCCESS
) ? FALSE
: TRUE
;
215 if (nRet
== SYSINFO_RC_SUCCESS
)
217 snprintf(szRequest
, sizeof(szRequest
),
218 isLogical
? pszRqListLog
[(int)pArg
] : pszRqListPhy
[(int)pArg
],
220 nRet
= IPSCTLGetString(0, szRequest
, pValue
, MAX_RESULT_LENGTH
);
225 nRet
= SYSINFO_RC_UNSUPPORTED
;
233 // Callback for ARP cache enumeration
236 static void ArpCallback(char *pszPath
, CBP
*pArg
)
238 char *ptr
, szBuffer
[1024], szMacAddr
[32], szIfName
[MAX_IF_NAME
];
240 snprintf(szBuffer
, 1024, "%s:macaddr", pszPath
);
241 if (IPSCTLGetString(pArg
->nHandle
, szBuffer
, szMacAddr
, 32) != SYSINFO_RC_SUCCESS
)
244 snprintf(szBuffer
, 1024, "%s:ifname", pszPath
);
245 if (IPSCTLGetString(pArg
->nHandle
, szBuffer
, szIfName
, MAX_IF_NAME
) != SYSINFO_RC_SUCCESS
)
248 ptr
= strrchr(pszPath
, ':');
253 TranslateStr(szMacAddr
, ":", "");
254 snprintf(szBuffer
, 1024, "%s %s %d", szMacAddr
, ptr
,
255 if_nametoindex(szIfName
) + 0x01000000);
256 pArg
->pList
->add(szBuffer
);
261 // Handler for Net.ArpCache enum
264 LONG
H_NetArpCache(char *pszParam
, char *pArg
, StringList
*pValue
)
266 LONG nRet
= SYSINFO_RC_ERROR
;
269 data
.nHandle
= ipsctl_open();
270 if (data
.nHandle
> 0)
273 if (ipsctl_iterate(data
.nHandle
, "net:ip:arp:entry", ArpCallback
, &data
) == 0)
274 nRet
= SYSINFO_RC_SUCCESS
;
275 ipsctl_close(data
.nHandle
);
281 LONG
H_NetRoutingTable(char *pszParam
, char *pArg
, StringList
*pValue
)
283 #define sa2sin(x) ((struct sockaddr_in *)x)
285 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
286 int nRet
= SYSINFO_RC_ERROR
;
287 int mib
[6] = { CTL_NET
, PF_ROUTE
, 0, AF_INET
, NET_RT_DUMP
, 0 };
288 char *pRT
= NULL
, *pNext
= NULL
;
290 struct rt_msghdr
*rtm
;
292 struct sockaddr
*rti_info
[RTAX_MAX
];
294 if (sysctl(mib
, 6, NULL
, &nReqSize
, NULL
, 0) == 0)
298 pRT
= (char *)malloc(nReqSize
);
301 if (sysctl(mib
, 6, pRT
, &nReqSize
, NULL
, 0) < 0)
312 nRet
= SYSINFO_RC_SUCCESS
;
314 for (pNext
= pRT
; pNext
< pRT
+ nReqSize
; pNext
+= rtm
->rtm_msglen
)
316 rtm
= (struct rt_msghdr
*)pNext
;
317 sa
= (struct sockaddr
*)(rtm
+ 1);
319 if (sa
->sa_family
!= AF_INET
)
324 for (int i
= 0; i
< RTAX_MAX
; i
++)
326 if (rtm
->rtm_addrs
& (1 << i
))
329 sa
= (struct sockaddr
*)((char *)(sa
) + ROUNDUP(sa
->sa_len
));
337 if (rti_info
[RTAX_DST
] != NULL
&& !(rtm
->rtm_flags
& RTF_WASCLONED
))
342 if (sa2sin(rti_info
[RTAX_DST
])->sin_addr
.s_addr
== INADDR_ANY
)
344 strcpy(szOut
, "0.0.0.0/0 ");
348 if ((rtm
->rtm_flags
& RTF_HOST
) || rti_info
[RTAX_NETMASK
]==NULL
)
352 inet_ntoa(sa2sin(rti_info
[RTAX_DST
])->sin_addr
));
353 strcat(szOut
, "/32 ");
359 rti_info
[RTAX_NETMASK
] ?
360 ntohl(sa2sin(rti_info
[RTAX_NETMASK
])->sin_addr
.s_addr
)
363 sprintf(szOut
, "%s/%d ",
364 inet_ntoa(sa2sin(rti_info
[RTAX_DST
])->sin_addr
),
365 nMask
? 33 - ffs(nMask
) : 0);
369 if (rti_info
[RTAX_GATEWAY
]->sa_family
!= AF_INET
)
371 strcat(szOut
, "0.0.0.0 ");
376 inet_ntoa(sa2sin(rti_info
[RTAX_GATEWAY
])->sin_addr
));
379 snprintf(szTmp
, sizeof(szTmp
), "%d %d",
381 (rtm
->rtm_flags
& RTF_GATEWAY
) == 0 ? 3 : 4);
382 strcat(szOut
, szTmp
);
399 // Callback for physical interface enumeration
402 static void PhysicalIfCallback(char *pszPath
, IFLIST
*pList
)
404 char *ptr
, szCtl
[256], szBuffer
[256];
407 // Extract interface name from path
408 ptr
= strrchr(pszPath
, ':');
409 if (ptr
== NULL
) // Should never happen
414 // Allocate new interface data structure
415 pList
->pData
= (IFDATA
*)realloc(pList
->pData
, sizeof(IFDATA
) * (pList
->nSize
+ 1));
416 pCurr
= &pList
->pData
[pList
->nSize
];
417 memset(pCurr
, 0, sizeof(IFDATA
));
420 // Fill interface data
421 nx_strncpy(pCurr
->szName
, ptr
, MAX_IF_NAME
);
422 strcpy(pCurr
->szIpAddr
, "0.0.0.0");
425 snprintf(szCtl
, 256, "%s:index", pszPath
);
426 IPSCTLGetInt(pList
->nHandle
, szCtl
, &pCurr
->nIndex
);
429 snprintf(szCtl
, 256, "%s:type", pszPath
);
430 if (IPSCTLGetString(pList
->nHandle
, szCtl
, szBuffer
, 256) == SYSINFO_RC_SUCCESS
)
432 if (!strcmp(szBuffer
, "ethernet"))
433 pCurr
->nType
= IFTYPE_ETHERNET_CSMACD
;
434 else if (!strcmp(szBuffer
, "loopback"))
435 pCurr
->nType
= IFTYPE_SOFTWARE_LOOPBACK
;
436 else if (!strcmp(szBuffer
, "pppoe"))
437 pCurr
->nType
= IFTYPE_EON
;
439 pCurr
->nType
= IFTYPE_OTHER
;
443 pCurr
->nType
= IFTYPE_OTHER
;
447 snprintf(szCtl
, 256, "%s:macaddr", pszPath
);
448 IPSCTLGetString(pList
->nHandle
, szCtl
, pCurr
->szMacAddr
, 24);
449 TranslateStr(pCurr
->szMacAddr
, ":", "");
454 // Callback for logical interface enumeration
457 static void LogicalIfCallback(char *pszPath
, IFLIST
*pList
)
459 char *ptr
, szCtl
[256], szBuffer
[256];
462 // Extract interface name from path
463 ptr
= strrchr(pszPath
, ':');
464 if (ptr
== NULL
) // Should never happen
469 // Allocate new interface data structure
470 pList
->pData
= (IFDATA
*)realloc(pList
->pData
, sizeof(IFDATA
) * (pList
->nSize
+ 1));
471 pCurr
= &pList
->pData
[pList
->nSize
];
472 memset(pCurr
, 0, sizeof(IFDATA
));
475 // Fill interface data
476 nx_strncpy(pCurr
->szName
, ptr
, MAX_IF_NAME
);
477 pCurr
->isLogical
= TRUE
;
480 snprintf(szCtl
, 256, "%s:index", pszPath
);
481 IPSCTLGetInt(pList
->nHandle
, szCtl
, &pCurr
->nIndex
);
482 pCurr
->nIndex
+= 0x01000000;
484 // Get underlaying physical interface
485 snprintf(szCtl
, 256, "%s:phys", pszPath
);
486 IPSCTLGetString(pList
->nHandle
, szCtl
, pCurr
->szPhysIfName
, MAX_IF_NAME
);
489 snprintf(szCtl
, 256, "ifphys:%s:type", pCurr
->szPhysIfName
);
490 if (IPSCTLGetString(pList
->nHandle
, szCtl
, szBuffer
, 256) == SYSINFO_RC_SUCCESS
)
492 if (!strcmp(szBuffer
, "ethernet"))
493 pCurr
->nType
= IFTYPE_ETHERNET_CSMACD
;
494 else if (!strcmp(szBuffer
, "loopback"))
495 pCurr
->nType
= IFTYPE_SOFTWARE_LOOPBACK
;
496 else if (!strcmp(szBuffer
, "pppoe"))
497 pCurr
->nType
= IFTYPE_EON
;
499 pCurr
->nType
= IFTYPE_OTHER
;
503 pCurr
->nType
= IFTYPE_OTHER
;
507 snprintf(szCtl
, 256, "ifphys:%s:macaddr", pCurr
->szPhysIfName
);
508 IPSCTLGetString(pList
->nHandle
, szCtl
, pCurr
->szMacAddr
, 24);
509 TranslateStr(pCurr
->szMacAddr
, ":", "");
514 // Callback for IP address enumeration
517 static void IpAddrCallback(char *pszPath
, IFLIST
*pList
)
520 struct ipsctl_value
*pValue
;
521 char *ptr
, szCtl
[256];
523 if (pList
->pData
[pList
->nCurr
].szIpAddr
[0] != 0)
525 // Interface already has IP address, create additional entry
526 pList
->pData
= (IFDATA
*)realloc(pList
->pData
, sizeof(IFDATA
) * (pList
->nSize
+ 1));
527 pCurr
= &pList
->pData
[pList
->nSize
];
528 memcpy(pCurr
, &pList
->pData
[pList
->nCurr
], sizeof(IFDATA
));
533 pCurr
= &pList
->pData
[pList
->nCurr
];
536 ptr
= strrchr(pszPath
, ':');
541 nx_strncpy(pCurr
->szIpAddr
, ptr
, 16);
543 snprintf(szCtl
, 256, "%s:dest", pszPath
);
544 if (ipsctl_get(pList
->nHandle
, szCtl
, &pValue
) == 0)
546 pCurr
->nMask
= pValue
->data
.ipAddr
.nMaskBits
;
552 // Handler for Net.InterfaceList enum
555 LONG
H_NetIfList(char *pszParam
, char *pArg
, StringList
*pValue
)
557 int i
, nSize
, nHandle
;
560 LONG nRet
= SYSINFO_RC_ERROR
;
562 nHandle
= ipsctl_open();
567 ifList
.nHandle
= nHandle
;
568 if ((ipsctl_iterate(nHandle
, "ifphys",
569 PhysicalIfCallback
, &ifList
) == 0) &&
570 (ipsctl_iterate(nHandle
, "interface",
571 LogicalIfCallback
, &ifList
) == 0))
573 nRet
= SYSINFO_RC_SUCCESS
;
575 // Gather IP addresses
576 nSize
= ifList
.nSize
;
577 for(i
= 0; i
< nSize
; i
++)
579 if (ifList
.pData
[i
].isLogical
)
581 sprintf(szBuffer
, "interface:%s:family:inet:addr",
582 ifList
.pData
[i
].szName
);
584 ipsctl_iterate(nHandle
, szBuffer
, IpAddrCallback
, &ifList
);
585 if (ifList
.pData
[i
].szIpAddr
[0] == 0)
586 strcpy(ifList
.pData
[i
].szIpAddr
, "0.0.0.0");
590 for(i
= 0; i
< ifList
.nSize
; i
++)
592 sprintf(szBuffer
, "%d %s/%d %d %s %s", ifList
.pData
[i
].nIndex
,
593 ifList
.pData
[i
].szIpAddr
, ifList
.pData
[i
].nMask
,
594 ifList
.pData
[i
].nType
, ifList
.pData
[i
].szMacAddr
,
595 ifList
.pData
[i
].szName
);
596 pValue
->add(szBuffer
);
599 ipsctl_close(nHandle
);
605 ///////////////////////////////////////////////////////////////////////////////
608 $Log: not supported by cvs2svn $
609 Revision 1.3 2006/08/16 22:26:09 victor
610 - Most of Net.Interface.XXX functions implemented on IPSO
611 - Added function MACToStr
613 Revision 1.2 2006/07/21 16:22:44 victor
614 Some parameters are working
616 Revision 1.1 2006/07/21 11:48:35 victor